Statistics
| Branch: | Revision:

root / osdep.c @ 4aa42531

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