Statistics
| Branch: | Revision:

root / osdep.c @ c5d6edc3

History | View | Annotate | Download (15 kB)

1 ea88812f bellard
/*
2 ea88812f bellard
 * QEMU low level functions
3 ea88812f bellard
 * 
4 ea88812f bellard
 * Copyright (c) 2003 Fabrice Bellard
5 ea88812f bellard
 * 
6 ea88812f bellard
 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 ea88812f bellard
 * of this software and associated documentation files (the "Software"), to deal
8 ea88812f bellard
 * in the Software without restriction, including without limitation the rights
9 ea88812f bellard
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 ea88812f bellard
 * copies of the Software, and to permit persons to whom the Software is
11 ea88812f bellard
 * furnished to do so, subject to the following conditions:
12 ea88812f bellard
 *
13 ea88812f bellard
 * The above copyright notice and this permission notice shall be included in
14 ea88812f bellard
 * all copies or substantial portions of the Software.
15 ea88812f bellard
 *
16 ea88812f bellard
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 ea88812f bellard
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 ea88812f bellard
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 ea88812f bellard
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 ea88812f bellard
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 ea88812f bellard
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 ea88812f bellard
 * THE SOFTWARE.
23 ea88812f bellard
 */
24 ea88812f bellard
#include <stdlib.h>
25 ea88812f bellard
#include <stdio.h>
26 ea88812f bellard
#include <stdarg.h>
27 ea88812f bellard
#include <string.h>
28 ea88812f bellard
#include <errno.h>
29 ea88812f bellard
#include <unistd.h>
30 ea88812f bellard
31 ea88812f bellard
#include "cpu.h"
32 6cb7ee85 pbrook
#if defined(USE_KQEMU)
33 6cb7ee85 pbrook
#include "vl.h"
34 6cb7ee85 pbrook
#endif
35 ea88812f bellard
36 ea88812f bellard
#if defined(__i386__) && !defined(CONFIG_SOFTMMU) && !defined(CONFIG_USER_ONLY)
37 ea88812f bellard
38 67b915a5 bellard
#include <sys/mman.h>
39 67b915a5 bellard
#include <sys/ipc.h>
40 67b915a5 bellard
41 ea88812f bellard
/* When not using soft mmu, libc independant functions are needed for
42 ea88812f bellard
   the CPU core because it needs to use alternates stacks and
43 ea88812f bellard
   libc/thread incompatibles settings */
44 ea88812f bellard
45 ea88812f bellard
#include <linux/unistd.h>
46 ea88812f bellard
47 ea88812f bellard
#define QEMU_SYSCALL0(name) \
48 ea88812f bellard
{ \
49 ea88812f bellard
long __res; \
50 ea88812f bellard
__asm__ volatile ("int $0x80" \
51 ea88812f bellard
        : "=a" (__res) \
52 ea88812f bellard
        : "0" (__NR_##name)); \
53 ea88812f bellard
return __res; \
54 ea88812f bellard
}
55 ea88812f bellard
56 ea88812f bellard
#define QEMU_SYSCALL1(name,arg1) \
57 ea88812f bellard
{ \
58 ea88812f bellard
long __res; \
59 ea88812f bellard
__asm__ volatile ("int $0x80" \
60 ea88812f bellard
        : "=a" (__res) \
61 ea88812f bellard
        : "0" (__NR_##name),"b" ((long)(arg1))); \
62 ea88812f bellard
return __res; \
63 ea88812f bellard
}
64 ea88812f bellard
65 ea88812f bellard
#define QEMU_SYSCALL2(name,arg1,arg2) \
66 ea88812f bellard
{ \
67 ea88812f bellard
long __res; \
68 ea88812f bellard
__asm__ volatile ("int $0x80" \
69 ea88812f bellard
        : "=a" (__res) \
70 ea88812f bellard
        : "0" (__NR_##name),"b" ((long)(arg1)),"c" ((long)(arg2))); \
71 ea88812f bellard
return __res; \
72 ea88812f bellard
}
73 ea88812f bellard
74 ea88812f bellard
#define QEMU_SYSCALL3(name,arg1,arg2,arg3) \
75 ea88812f bellard
{ \
76 ea88812f bellard
long __res; \
77 ea88812f bellard
__asm__ volatile ("int $0x80" \
78 ea88812f bellard
        : "=a" (__res) \
79 ea88812f bellard
        : "0" (__NR_##name),"b" ((long)(arg1)),"c" ((long)(arg2)), \
80 ea88812f bellard
                  "d" ((long)(arg3))); \
81 ea88812f bellard
return __res; \
82 ea88812f bellard
}
83 ea88812f bellard
84 ea88812f bellard
#define QEMU_SYSCALL4(name,arg1,arg2,arg3,arg4) \
85 ea88812f bellard
{ \
86 ea88812f bellard
long __res; \
87 ea88812f bellard
__asm__ volatile ("int $0x80" \
88 ea88812f bellard
        : "=a" (__res) \
89 ea88812f bellard
        : "0" (__NR_##name),"b" ((long)(arg1)),"c" ((long)(arg2)), \
90 ea88812f bellard
          "d" ((long)(arg3)),"S" ((long)(arg4))); \
91 ea88812f bellard
return __res; \
92 ea88812f bellard
} 
93 ea88812f bellard
94 ea88812f bellard
#define QEMU_SYSCALL5(name,arg1,arg2,arg3,arg4,arg5) \
95 ea88812f bellard
{ \
96 ea88812f bellard
long __res; \
97 ea88812f bellard
__asm__ volatile ("int $0x80" \
98 ea88812f bellard
        : "=a" (__res) \
99 ea88812f bellard
        : "0" (__NR_##name),"b" ((long)(arg1)),"c" ((long)(arg2)), \
100 ea88812f bellard
          "d" ((long)(arg3)),"S" ((long)(arg4)),"D" ((long)(arg5))); \
101 ea88812f bellard
return __res; \
102 ea88812f bellard
}
103 ea88812f bellard
104 ea88812f bellard
#define QEMU_SYSCALL6(name,arg1,arg2,arg3,arg4,arg5,arg6) \
105 ea88812f bellard
{ \
106 ea88812f bellard
long __res; \
107 ea88812f bellard
__asm__ volatile ("push %%ebp ; movl %%eax,%%ebp ; movl %1,%%eax ; int $0x80 ; pop %%ebp" \
108 ea88812f bellard
        : "=a" (__res) \
109 ea88812f bellard
        : "i" (__NR_##name),"b" ((long)(arg1)),"c" ((long)(arg2)), \
110 ea88812f bellard
          "d" ((long)(arg3)),"S" ((long)(arg4)),"D" ((long)(arg5)), \
111 ea88812f bellard
          "0" ((long)(arg6))); \
112 ea88812f bellard
return __res; \
113 ea88812f bellard
}
114 ea88812f bellard
115 ea88812f bellard
int qemu_write(int fd, const void *buf, size_t n)
116 ea88812f bellard
{
117 ea88812f bellard
    QEMU_SYSCALL3(write, fd, buf, n);
118 ea88812f bellard
}
119 ea88812f bellard
120 ea88812f bellard
121 ea88812f bellard
122 ea88812f bellard
/****************************************************************/
123 ea88812f bellard
/* shmat replacement */
124 ea88812f bellard
125 ea88812f bellard
int qemu_ipc(int call, unsigned long first, 
126 ea88812f bellard
            unsigned long second, unsigned long third, 
127 ea88812f bellard
            void *ptr, unsigned long fifth)
128 ea88812f bellard
{
129 ea88812f bellard
    QEMU_SYSCALL6(ipc, call, first, second, third, ptr, fifth);
130 ea88812f bellard
}
131 ea88812f bellard
132 ea88812f bellard
#define SHMAT 21
133 ea88812f bellard
134 ea88812f bellard
/* we must define shmat so that a specific address will be used when
135 ea88812f bellard
   mapping the X11 ximage */
136 ea88812f bellard
void *shmat(int shmid, const void *shmaddr, int shmflg)
137 ea88812f bellard
{
138 ea88812f bellard
    void *ptr;
139 ea88812f bellard
    int ret;
140 ea88812f bellard
    /* we give an address in the right memory area */
141 ea88812f bellard
    if (!shmaddr)
142 ea88812f bellard
        shmaddr = get_mmap_addr(8192 * 1024);
143 ea88812f bellard
    ret = qemu_ipc(SHMAT, shmid, shmflg, (unsigned long)&ptr, (void *)shmaddr, 0);
144 ea88812f bellard
    if (ret < 0)
145 ea88812f bellard
        return NULL;
146 ea88812f bellard
    return ptr;
147 ea88812f bellard
}
148 ea88812f bellard
149 ea88812f bellard
/****************************************************************/
150 d2bfb39a bellard
/* sigaction bypassing the threads */
151 d2bfb39a bellard
152 d2bfb39a bellard
static int kernel_sigaction(int signum, const struct qemu_sigaction *act, 
153 d2bfb39a bellard
                            struct qemu_sigaction *oldact, 
154 d2bfb39a bellard
                            int sigsetsize)
155 d2bfb39a bellard
{
156 d2bfb39a bellard
    QEMU_SYSCALL4(rt_sigaction, signum, act, oldact, sigsetsize);
157 d2bfb39a bellard
}
158 d2bfb39a bellard
159 d2bfb39a bellard
int qemu_sigaction(int signum, const struct qemu_sigaction *act, 
160 d2bfb39a bellard
                   struct qemu_sigaction *oldact)
161 d2bfb39a bellard
{
162 d2bfb39a bellard
    return kernel_sigaction(signum, act, oldact, 8);
163 d2bfb39a bellard
}
164 d2bfb39a bellard
165 d2bfb39a bellard
/****************************************************************/
166 ea88812f bellard
/* memory allocation */
167 ea88812f bellard
168 ea88812f bellard
//#define DEBUG_MALLOC
169 ea88812f bellard
170 ea88812f bellard
#define MALLOC_BASE       0xab000000
171 ea88812f bellard
#define PHYS_RAM_BASE     0xac000000
172 ea88812f bellard
173 ea88812f bellard
#define MALLOC_ALIGN      16
174 ea88812f bellard
#define BLOCK_HEADER_SIZE 16
175 ea88812f bellard
176 ea88812f bellard
typedef struct MemoryBlock {
177 ea88812f bellard
    struct MemoryBlock *next;
178 ea88812f bellard
    unsigned long size; /* size of block, including header */
179 ea88812f bellard
} MemoryBlock;
180 ea88812f bellard
181 ea88812f bellard
static MemoryBlock *first_free_block;
182 ea88812f bellard
static unsigned long malloc_addr = MALLOC_BASE;
183 ea88812f bellard
184 ea88812f bellard
static void *malloc_get_space(size_t size)
185 ea88812f bellard
{
186 ea88812f bellard
    void *ptr;
187 ea88812f bellard
    size = TARGET_PAGE_ALIGN(size);
188 ea88812f bellard
    ptr = mmap((void *)malloc_addr, size, 
189 ea88812f bellard
               PROT_WRITE | PROT_READ, 
190 ea88812f bellard
               MAP_PRIVATE | MAP_FIXED | MAP_ANON, -1, 0);
191 ea88812f bellard
    if (ptr == MAP_FAILED)
192 ea88812f bellard
        return NULL;
193 ea88812f bellard
    malloc_addr += size;
194 ea88812f bellard
    return ptr;
195 ea88812f bellard
}
196 ea88812f bellard
197 ea88812f bellard
void *qemu_malloc(size_t size)
198 ea88812f bellard
{
199 ea88812f bellard
    MemoryBlock *mb, *mb1, **pmb;
200 ea88812f bellard
    void *ptr;
201 ea88812f bellard
    size_t size1, area_size;
202 ea88812f bellard
    
203 ea88812f bellard
    if (size == 0)
204 ea88812f bellard
        return NULL;
205 ea88812f bellard
206 ea88812f bellard
    size = (size + BLOCK_HEADER_SIZE + MALLOC_ALIGN - 1) & ~(MALLOC_ALIGN - 1);
207 ea88812f bellard
    pmb = &first_free_block;
208 ea88812f bellard
    for(;;) {
209 ea88812f bellard
        mb = *pmb;
210 ea88812f bellard
        if (mb == NULL)
211 ea88812f bellard
            break;
212 ea88812f bellard
        if (size <= mb->size)
213 ea88812f bellard
            goto found;
214 ea88812f bellard
        pmb = &mb->next;
215 ea88812f bellard
    }
216 ea88812f bellard
    /* no big enough blocks found: get new space */
217 ea88812f bellard
    area_size = TARGET_PAGE_ALIGN(size);
218 ea88812f bellard
    mb = malloc_get_space(area_size);
219 ea88812f bellard
    if (!mb)
220 ea88812f bellard
        return NULL;
221 ea88812f bellard
    size1 = area_size - size;
222 ea88812f bellard
    if (size1 > 0) {
223 ea88812f bellard
        /* create a new free block */
224 ea88812f bellard
        mb1 = (MemoryBlock *)((uint8_t *)mb + size);
225 ea88812f bellard
        mb1->next = NULL;
226 ea88812f bellard
        mb1->size = size1;
227 ea88812f bellard
        *pmb = mb1;
228 ea88812f bellard
    }
229 ea88812f bellard
    goto the_end;
230 ea88812f bellard
 found:
231 ea88812f bellard
    /* a free block was found: use it */
232 ea88812f bellard
    size1 = mb->size - size;
233 ea88812f bellard
    if (size1 > 0) {
234 ea88812f bellard
        /* create a new free block */
235 ea88812f bellard
        mb1 = (MemoryBlock *)((uint8_t *)mb + size);
236 ea88812f bellard
        mb1->next = mb->next;
237 ea88812f bellard
        mb1->size = size1;
238 ea88812f bellard
        *pmb = mb1;
239 ea88812f bellard
    } else {
240 ea88812f bellard
        /* suppress the first block */
241 ea88812f bellard
        *pmb = mb->next;
242 ea88812f bellard
    }
243 ea88812f bellard
 the_end:
244 ea88812f bellard
    mb->size = size;
245 ea88812f bellard
    mb->next = NULL;
246 ea88812f bellard
    ptr = ((uint8_t *)mb + BLOCK_HEADER_SIZE);
247 ea88812f bellard
#ifdef DEBUG_MALLOC
248 ea88812f bellard
    qemu_printf("malloc: size=0x%x ptr=0x%lx\n", size, (unsigned long)ptr);
249 ea88812f bellard
#endif
250 ea88812f bellard
    return ptr;
251 ea88812f bellard
}
252 ea88812f bellard
253 ea88812f bellard
void qemu_free(void *ptr)
254 ea88812f bellard
{
255 ea88812f bellard
    MemoryBlock *mb;
256 ea88812f bellard
257 57c30724 bellard
    if (!ptr)
258 57c30724 bellard
        return;
259 ea88812f bellard
    mb = (MemoryBlock *)((uint8_t *)ptr - BLOCK_HEADER_SIZE);
260 ea88812f bellard
    mb->next = first_free_block;
261 ea88812f bellard
    first_free_block = mb;
262 ea88812f bellard
}
263 ea88812f bellard
264 ea88812f bellard
/****************************************************************/
265 ea88812f bellard
/* virtual memory allocation */
266 ea88812f bellard
267 ea88812f bellard
unsigned long mmap_addr = PHYS_RAM_BASE;
268 ea88812f bellard
269 ea88812f bellard
void *get_mmap_addr(unsigned long size)
270 ea88812f bellard
{
271 ea88812f bellard
    unsigned long addr;
272 ea88812f bellard
    addr = mmap_addr;
273 ea88812f bellard
    mmap_addr += ((size + 4095) & ~4095) + 4096;
274 ea88812f bellard
    return (void *)addr;
275 ea88812f bellard
}
276 ea88812f bellard
277 ea88812f bellard
#else
278 ea88812f bellard
279 6e4255f6 bellard
#ifdef _WIN32
280 6e4255f6 bellard
#include <windows.h>
281 6e4255f6 bellard
#elif defined(_BSD)
282 194884dd bellard
#include <stdlib.h>
283 194884dd bellard
#else
284 49b470eb bellard
#include <malloc.h>
285 194884dd bellard
#endif
286 49b470eb bellard
287 ea88812f bellard
int qemu_write(int fd, const void *buf, size_t n)
288 ea88812f bellard
{
289 ea88812f bellard
    int ret;
290 ea88812f bellard
    ret = write(fd, buf, n);
291 ea88812f bellard
    if (ret < 0)
292 ea88812f bellard
        return -errno;
293 ea88812f bellard
    else
294 ea88812f bellard
        return ret;
295 ea88812f bellard
}
296 ea88812f bellard
297 ea88812f bellard
void *get_mmap_addr(unsigned long size)
298 ea88812f bellard
{
299 ea88812f bellard
    return NULL;
300 ea88812f bellard
}
301 ea88812f bellard
302 ea88812f bellard
void qemu_free(void *ptr)
303 ea88812f bellard
{
304 ea88812f bellard
    free(ptr);
305 ea88812f bellard
}
306 ea88812f bellard
307 ea88812f bellard
void *qemu_malloc(size_t size)
308 ea88812f bellard
{
309 ea88812f bellard
    return malloc(size);
310 ea88812f bellard
}
311 ea88812f bellard
312 6e4255f6 bellard
#if defined(_WIN32)
313 6e4255f6 bellard
314 6e4255f6 bellard
void *qemu_vmalloc(size_t size)
315 6e4255f6 bellard
{
316 6e4255f6 bellard
    /* FIXME: this is not exactly optimal solution since VirtualAlloc
317 6e4255f6 bellard
       has 64Kb granularity, but at least it guarantees us that the
318 6e4255f6 bellard
       memory is page aligned. */
319 6e4255f6 bellard
    return VirtualAlloc(NULL, size, MEM_COMMIT, PAGE_READWRITE);
320 6e4255f6 bellard
}
321 6e4255f6 bellard
322 6e4255f6 bellard
void qemu_vfree(void *ptr)
323 6e4255f6 bellard
{
324 6e4255f6 bellard
    VirtualFree(ptr, 0, MEM_RELEASE);
325 6e4255f6 bellard
}
326 6e4255f6 bellard
327 6cb7ee85 pbrook
#else
328 6cb7ee85 pbrook
329 6cb7ee85 pbrook
#if defined(USE_KQEMU)
330 49b470eb bellard
331 6bae7ed8 bellard
#include <sys/vfs.h>
332 49b470eb bellard
#include <sys/mman.h>
333 49b470eb bellard
#include <fcntl.h>
334 49b470eb bellard
335 6cb7ee85 pbrook
void *kqemu_vmalloc(size_t size)
336 49b470eb bellard
{
337 49b470eb bellard
    static int phys_ram_fd = -1;
338 49b470eb bellard
    static int phys_ram_size = 0;
339 49b470eb bellard
    const char *tmpdir;
340 49b470eb bellard
    char phys_ram_file[1024];
341 49b470eb bellard
    void *ptr;
342 6bae7ed8 bellard
    struct statfs stfs;
343 49b470eb bellard
344 49b470eb bellard
    if (phys_ram_fd < 0) {
345 49b470eb bellard
        tmpdir = getenv("QEMU_TMPDIR");
346 49b470eb bellard
        if (!tmpdir)
347 49b470eb bellard
            tmpdir = "/dev/shm";
348 6bae7ed8 bellard
        if (statfs(tmpdir, &stfs) == 0) {
349 6bae7ed8 bellard
            int64_t free_space;
350 6bae7ed8 bellard
            int ram_mb;
351 6bae7ed8 bellard
352 6bae7ed8 bellard
            extern int ram_size;
353 6bae7ed8 bellard
            free_space = (int64_t)stfs.f_bavail * stfs.f_bsize;
354 6bae7ed8 bellard
            if ((ram_size + 8192 * 1024) >= free_space) {
355 6bae7ed8 bellard
                ram_mb = (ram_size / (1024 * 1024));
356 6bae7ed8 bellard
                fprintf(stderr, 
357 6bae7ed8 bellard
                        "You do not have enough space in '%s' for the %d MB of QEMU virtual RAM.\n",
358 6bae7ed8 bellard
                        tmpdir, ram_mb);
359 6bae7ed8 bellard
                if (strcmp(tmpdir, "/dev/shm") == 0) {
360 6bae7ed8 bellard
                    fprintf(stderr, "To have more space available provided you have enough RAM and swap, do as root:\n"
361 6bae7ed8 bellard
                            "umount /dev/shm\n"
362 6bae7ed8 bellard
                            "mount -t tmpfs -o size=%dm none /dev/shm\n",
363 6bae7ed8 bellard
                            ram_mb + 16);
364 6bae7ed8 bellard
                } else {
365 6bae7ed8 bellard
                    fprintf(stderr, 
366 6bae7ed8 bellard
                            "Use the '-m' option of QEMU to diminish the amount of virtual RAM or use the\n"
367 6bae7ed8 bellard
                            "QEMU_TMPDIR environment variable to set another directory where the QEMU\n"
368 6bae7ed8 bellard
                            "temporary RAM file will be opened.\n");
369 6bae7ed8 bellard
                }
370 6cb7ee85 pbrook
                fprintf(stderr, "Or disable the accelerator module with -no-kqemu\n");
371 6bae7ed8 bellard
                exit(1);
372 6bae7ed8 bellard
            }
373 6bae7ed8 bellard
        }
374 49b470eb bellard
        snprintf(phys_ram_file, sizeof(phys_ram_file), "%s/qemuXXXXXX", 
375 49b470eb bellard
                 tmpdir);
376 49b470eb bellard
        if (mkstemp(phys_ram_file) < 0) {
377 49b470eb bellard
            fprintf(stderr, 
378 49b470eb bellard
                    "warning: could not create temporary file in '%s'.\n"
379 49b470eb bellard
                    "Use QEMU_TMPDIR to select a directory in a tmpfs filesystem.\n"
380 49b470eb bellard
                    "Using '/tmp' as fallback.\n",
381 49b470eb bellard
                    tmpdir);
382 49b470eb bellard
            snprintf(phys_ram_file, sizeof(phys_ram_file), "%s/qemuXXXXXX", 
383 49b470eb bellard
                     "/tmp");
384 49b470eb bellard
            if (mkstemp(phys_ram_file) < 0) {
385 49b470eb bellard
                fprintf(stderr, "Could not create temporary memory file '%s'\n", 
386 49b470eb bellard
                        phys_ram_file);
387 49b470eb bellard
                exit(1);
388 49b470eb bellard
            }
389 49b470eb bellard
        }
390 49b470eb bellard
        phys_ram_fd = open(phys_ram_file, O_CREAT | O_TRUNC | O_RDWR, 0600);
391 49b470eb bellard
        if (phys_ram_fd < 0) {
392 49b470eb bellard
            fprintf(stderr, "Could not open temporary memory file '%s'\n", 
393 49b470eb bellard
                    phys_ram_file);
394 49b470eb bellard
            exit(1);
395 49b470eb bellard
        }
396 49b470eb bellard
        unlink(phys_ram_file);
397 49b470eb bellard
    }
398 49b470eb bellard
    size = (size + 4095) & ~4095;
399 49b470eb bellard
    ftruncate(phys_ram_fd, phys_ram_size + size);
400 49b470eb bellard
    ptr = mmap(NULL, 
401 49b470eb bellard
               size, 
402 49b470eb bellard
               PROT_WRITE | PROT_READ, MAP_SHARED, 
403 49b470eb bellard
               phys_ram_fd, phys_ram_size);
404 49b470eb bellard
    if (ptr == MAP_FAILED) {
405 49b470eb bellard
        fprintf(stderr, "Could not map physical memory\n");
406 49b470eb bellard
        exit(1);
407 49b470eb bellard
    }
408 49b470eb bellard
    phys_ram_size += size;
409 49b470eb bellard
    return ptr;
410 49b470eb bellard
}
411 49b470eb bellard
412 6cb7ee85 pbrook
void kqemu_vfree(void *ptr)
413 49b470eb bellard
{
414 49b470eb bellard
    /* may be useful some day, but currently we do not need to free */
415 49b470eb bellard
}
416 49b470eb bellard
417 6cb7ee85 pbrook
#endif
418 49b470eb bellard
419 49b470eb bellard
/* alloc shared memory pages */
420 49b470eb bellard
void *qemu_vmalloc(size_t size)
421 49b470eb bellard
{
422 6cb7ee85 pbrook
#if defined(USE_KQEMU)
423 6cb7ee85 pbrook
    if (kqemu_allowed)
424 6cb7ee85 pbrook
        return kqemu_vmalloc(size);
425 6cb7ee85 pbrook
#endif
426 49b470eb bellard
#ifdef _BSD
427 49b470eb bellard
    return valloc(size);
428 49b470eb bellard
#else
429 49b470eb bellard
    return memalign(4096, size);
430 49b470eb bellard
#endif
431 49b470eb bellard
}
432 49b470eb bellard
433 49b470eb bellard
void qemu_vfree(void *ptr)
434 49b470eb bellard
{
435 6cb7ee85 pbrook
#if defined(USE_KQEMU)
436 6cb7ee85 pbrook
    if (kqemu_allowed)
437 6cb7ee85 pbrook
        kqemu_vfree(ptr);
438 6cb7ee85 pbrook
#endif
439 49b470eb bellard
    free(ptr);
440 49b470eb bellard
}
441 49b470eb bellard
442 49b470eb bellard
#endif
443 49b470eb bellard
444 ea88812f bellard
#endif
445 ea88812f bellard
446 07d89866 bellard
void *qemu_mallocz(size_t size)
447 07d89866 bellard
{
448 07d89866 bellard
    void *ptr;
449 07d89866 bellard
    ptr = qemu_malloc(size);
450 07d89866 bellard
    if (!ptr)
451 07d89866 bellard
        return NULL;
452 07d89866 bellard
    memset(ptr, 0, size);
453 07d89866 bellard
    return ptr;
454 07d89866 bellard
}
455 07d89866 bellard
456 2571929a bellard
char *qemu_strdup(const char *str)
457 2571929a bellard
{
458 2571929a bellard
    char *ptr;
459 2571929a bellard
    ptr = qemu_malloc(strlen(str) + 1);
460 2571929a bellard
    if (!ptr)
461 2571929a bellard
        return NULL;
462 2571929a bellard
    strcpy(ptr, str);
463 2571929a bellard
    return ptr;
464 2571929a bellard
}
465 2571929a bellard
466 ea88812f bellard
/****************************************************************/
467 ea88812f bellard
/* printf support */
468 ea88812f bellard
469 ea88812f bellard
static inline int qemu_isdigit(int c)
470 ea88812f bellard
{
471 ea88812f bellard
    return c >= '0' && c <= '9';
472 ea88812f bellard
}
473 ea88812f bellard
474 ea88812f bellard
#define OUTCHAR(c)        (buflen > 0? (--buflen, *buf++ = (c)): 0)
475 ea88812f bellard
476 ea88812f bellard
/* from BSD ppp sources */
477 ea88812f bellard
int qemu_vsnprintf(char *buf, int buflen, const char *fmt, va_list args)
478 ea88812f bellard
{
479 ea88812f bellard
    int c, i, n;
480 ea88812f bellard
    int width, prec, fillch;
481 ea88812f bellard
    int base, len, neg;
482 ea88812f bellard
    unsigned long val = 0;
483 ea88812f bellard
    const char *f;
484 ea88812f bellard
    char *str, *buf0;
485 ea88812f bellard
    char num[32];
486 ea88812f bellard
    static const char hexchars[] = "0123456789abcdef";
487 ea88812f bellard
488 ea88812f bellard
    buf0 = buf;
489 ea88812f bellard
    --buflen;
490 ea88812f bellard
    while (buflen > 0) {
491 ea88812f bellard
        for (f = fmt; *f != '%' && *f != 0; ++f)
492 ea88812f bellard
            ;
493 ea88812f bellard
        if (f > fmt) {
494 ea88812f bellard
            len = f - fmt;
495 ea88812f bellard
            if (len > buflen)
496 ea88812f bellard
                len = buflen;
497 ea88812f bellard
            memcpy(buf, fmt, len);
498 ea88812f bellard
            buf += len;
499 ea88812f bellard
            buflen -= len;
500 ea88812f bellard
            fmt = f;
501 ea88812f bellard
        }
502 ea88812f bellard
        if (*fmt == 0)
503 ea88812f bellard
            break;
504 ea88812f bellard
        c = *++fmt;
505 ea88812f bellard
        width = prec = 0;
506 ea88812f bellard
        fillch = ' ';
507 ea88812f bellard
        if (c == '0') {
508 ea88812f bellard
            fillch = '0';
509 ea88812f bellard
            c = *++fmt;
510 ea88812f bellard
        }
511 ea88812f bellard
        if (c == '*') {
512 ea88812f bellard
            width = va_arg(args, int);
513 ea88812f bellard
            c = *++fmt;
514 ea88812f bellard
        } else {
515 ea88812f bellard
            while (qemu_isdigit(c)) {
516 ea88812f bellard
                width = width * 10 + c - '0';
517 ea88812f bellard
                c = *++fmt;
518 ea88812f bellard
            }
519 ea88812f bellard
        }
520 ea88812f bellard
        if (c == '.') {
521 ea88812f bellard
            c = *++fmt;
522 ea88812f bellard
            if (c == '*') {
523 ea88812f bellard
                prec = va_arg(args, int);
524 ea88812f bellard
                c = *++fmt;
525 ea88812f bellard
            } else {
526 ea88812f bellard
                while (qemu_isdigit(c)) {
527 ea88812f bellard
                    prec = prec * 10 + c - '0';
528 ea88812f bellard
                    c = *++fmt;
529 ea88812f bellard
                }
530 ea88812f bellard
            }
531 ea88812f bellard
        }
532 ea88812f bellard
        /* modifiers */
533 ea88812f bellard
        switch(c) {
534 ea88812f bellard
        case 'l':
535 ea88812f bellard
            c = *++fmt;
536 ea88812f bellard
            break;
537 ea88812f bellard
        default:
538 ea88812f bellard
            break;
539 ea88812f bellard
        }
540 ea88812f bellard
        str = 0;
541 ea88812f bellard
        base = 0;
542 ea88812f bellard
        neg = 0;
543 ea88812f bellard
        ++fmt;
544 ea88812f bellard
        switch (c) {
545 ea88812f bellard
        case 'd':
546 ea88812f bellard
            i = va_arg(args, int);
547 ea88812f bellard
            if (i < 0) {
548 ea88812f bellard
                neg = 1;
549 ea88812f bellard
                val = -i;
550 ea88812f bellard
            } else
551 ea88812f bellard
                val = i;
552 ea88812f bellard
            base = 10;
553 ea88812f bellard
            break;
554 ea88812f bellard
        case 'o':
555 ea88812f bellard
            val = va_arg(args, unsigned int);
556 ea88812f bellard
            base = 8;
557 ea88812f bellard
            break;
558 ea88812f bellard
        case 'x':
559 ea88812f bellard
        case 'X':
560 ea88812f bellard
            val = va_arg(args, unsigned int);
561 ea88812f bellard
            base = 16;
562 ea88812f bellard
            break;
563 ea88812f bellard
        case 'p':
564 ea88812f bellard
            val = (unsigned long) va_arg(args, void *);
565 ea88812f bellard
            base = 16;
566 ea88812f bellard
            neg = 2;
567 ea88812f bellard
            break;
568 ea88812f bellard
        case 's':
569 ea88812f bellard
            str = va_arg(args, char *);
570 ea88812f bellard
            break;
571 ea88812f bellard
        case 'c':
572 ea88812f bellard
            num[0] = va_arg(args, int);
573 ea88812f bellard
            num[1] = 0;
574 ea88812f bellard
            str = num;
575 ea88812f bellard
            break;
576 ea88812f bellard
        default:
577 ea88812f bellard
            *buf++ = '%';
578 ea88812f bellard
            if (c != '%')
579 ea88812f bellard
                --fmt;                /* so %z outputs %z etc. */
580 ea88812f bellard
            --buflen;
581 ea88812f bellard
            continue;
582 ea88812f bellard
        }
583 ea88812f bellard
        if (base != 0) {
584 ea88812f bellard
            str = num + sizeof(num);
585 ea88812f bellard
            *--str = 0;
586 ea88812f bellard
            while (str > num + neg) {
587 ea88812f bellard
                *--str = hexchars[val % base];
588 ea88812f bellard
                val = val / base;
589 ea88812f bellard
                if (--prec <= 0 && val == 0)
590 ea88812f bellard
                    break;
591 ea88812f bellard
            }
592 ea88812f bellard
            switch (neg) {
593 ea88812f bellard
            case 1:
594 ea88812f bellard
                *--str = '-';
595 ea88812f bellard
                break;
596 ea88812f bellard
            case 2:
597 ea88812f bellard
                *--str = 'x';
598 ea88812f bellard
                *--str = '0';
599 ea88812f bellard
                break;
600 ea88812f bellard
            }
601 ea88812f bellard
            len = num + sizeof(num) - 1 - str;
602 ea88812f bellard
        } else {
603 ea88812f bellard
            len = strlen(str);
604 ea88812f bellard
            if (prec > 0 && len > prec)
605 ea88812f bellard
                len = prec;
606 ea88812f bellard
        }
607 ea88812f bellard
        if (width > 0) {
608 ea88812f bellard
            if (width > buflen)
609 ea88812f bellard
                width = buflen;
610 ea88812f bellard
            if ((n = width - len) > 0) {
611 ea88812f bellard
                buflen -= n;
612 ea88812f bellard
                for (; n > 0; --n)
613 ea88812f bellard
                    *buf++ = fillch;
614 ea88812f bellard
            }
615 ea88812f bellard
        }
616 ea88812f bellard
        if (len > buflen)
617 ea88812f bellard
            len = buflen;
618 ea88812f bellard
        memcpy(buf, str, len);
619 ea88812f bellard
        buf += len;
620 ea88812f bellard
        buflen -= len;
621 ea88812f bellard
    }
622 ea88812f bellard
    *buf = 0;
623 ea88812f bellard
    return buf - buf0;
624 ea88812f bellard
}
625 ea88812f bellard
626 ea88812f bellard
void qemu_vprintf(const char *fmt, va_list ap)
627 ea88812f bellard
{
628 ea88812f bellard
    char buf[1024];
629 ea88812f bellard
    int len;
630 ea88812f bellard
    
631 ea88812f bellard
    len = qemu_vsnprintf(buf, sizeof(buf), fmt, ap);
632 ea88812f bellard
    qemu_write(1, buf, len);
633 ea88812f bellard
}
634 ea88812f bellard
635 ea88812f bellard
void qemu_printf(const char *fmt, ...)
636 ea88812f bellard
{
637 ea88812f bellard
    va_list ap;
638 ea88812f bellard
    va_start(ap, fmt);
639 ea88812f bellard
    qemu_vprintf(fmt, ap);
640 ea88812f bellard
    va_end(ap);
641 ea88812f bellard
}