Commit ea88812f4f4fa19e08a665fb75a38ffa6d87715f

Authored by bellard
1 parent 58fe2f10

added OS dependent functions (temporary as most functions are generic in fact)


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@624 c046a42c-6fe2-441c-8c8c-71466251a162
Showing 2 changed files with 485 additions and 0 deletions
osdep.c 0 → 100644
  1 +/*
  2 + * QEMU low level functions
  3 + *
  4 + * Copyright (c) 2003 Fabrice Bellard
  5 + *
  6 + * Permission is hereby granted, free of charge, to any person obtaining a copy
  7 + * of this software and associated documentation files (the "Software"), to deal
  8 + * in the Software without restriction, including without limitation the rights
  9 + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  10 + * copies of the Software, and to permit persons to whom the Software is
  11 + * furnished to do so, subject to the following conditions:
  12 + *
  13 + * The above copyright notice and this permission notice shall be included in
  14 + * all copies or substantial portions of the Software.
  15 + *
  16 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  19 + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  21 + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  22 + * THE SOFTWARE.
  23 + */
  24 +#include <stdlib.h>
  25 +#include <stdio.h>
  26 +#include <stdarg.h>
  27 +#include <string.h>
  28 +#include <sys/mman.h>
  29 +#include <sys/ipc.h>
  30 +#include <errno.h>
  31 +#include <unistd.h>
  32 +
  33 +#include "cpu.h"
  34 +
  35 +#if defined(__i386__) && !defined(CONFIG_SOFTMMU) && !defined(CONFIG_USER_ONLY)
  36 +
  37 +/* When not using soft mmu, libc independant functions are needed for
  38 + the CPU core because it needs to use alternates stacks and
  39 + libc/thread incompatibles settings */
  40 +
  41 +#include <linux/unistd.h>
  42 +
  43 +#define QEMU_SYSCALL0(name) \
  44 +{ \
  45 +long __res; \
  46 +__asm__ volatile ("int $0x80" \
  47 + : "=a" (__res) \
  48 + : "0" (__NR_##name)); \
  49 +return __res; \
  50 +}
  51 +
  52 +#define QEMU_SYSCALL1(name,arg1) \
  53 +{ \
  54 +long __res; \
  55 +__asm__ volatile ("int $0x80" \
  56 + : "=a" (__res) \
  57 + : "0" (__NR_##name),"b" ((long)(arg1))); \
  58 +return __res; \
  59 +}
  60 +
  61 +#define QEMU_SYSCALL2(name,arg1,arg2) \
  62 +{ \
  63 +long __res; \
  64 +__asm__ volatile ("int $0x80" \
  65 + : "=a" (__res) \
  66 + : "0" (__NR_##name),"b" ((long)(arg1)),"c" ((long)(arg2))); \
  67 +return __res; \
  68 +}
  69 +
  70 +#define QEMU_SYSCALL3(name,arg1,arg2,arg3) \
  71 +{ \
  72 +long __res; \
  73 +__asm__ volatile ("int $0x80" \
  74 + : "=a" (__res) \
  75 + : "0" (__NR_##name),"b" ((long)(arg1)),"c" ((long)(arg2)), \
  76 + "d" ((long)(arg3))); \
  77 +return __res; \
  78 +}
  79 +
  80 +#define QEMU_SYSCALL4(name,arg1,arg2,arg3,arg4) \
  81 +{ \
  82 +long __res; \
  83 +__asm__ volatile ("int $0x80" \
  84 + : "=a" (__res) \
  85 + : "0" (__NR_##name),"b" ((long)(arg1)),"c" ((long)(arg2)), \
  86 + "d" ((long)(arg3)),"S" ((long)(arg4))); \
  87 +return __res; \
  88 +}
  89 +
  90 +#define QEMU_SYSCALL5(name,arg1,arg2,arg3,arg4,arg5) \
  91 +{ \
  92 +long __res; \
  93 +__asm__ volatile ("int $0x80" \
  94 + : "=a" (__res) \
  95 + : "0" (__NR_##name),"b" ((long)(arg1)),"c" ((long)(arg2)), \
  96 + "d" ((long)(arg3)),"S" ((long)(arg4)),"D" ((long)(arg5))); \
  97 +return __res; \
  98 +}
  99 +
  100 +#define QEMU_SYSCALL6(name,arg1,arg2,arg3,arg4,arg5,arg6) \
  101 +{ \
  102 +long __res; \
  103 +__asm__ volatile ("push %%ebp ; movl %%eax,%%ebp ; movl %1,%%eax ; int $0x80 ; pop %%ebp" \
  104 + : "=a" (__res) \
  105 + : "i" (__NR_##name),"b" ((long)(arg1)),"c" ((long)(arg2)), \
  106 + "d" ((long)(arg3)),"S" ((long)(arg4)),"D" ((long)(arg5)), \
  107 + "0" ((long)(arg6))); \
  108 +return __res; \
  109 +}
  110 +
  111 +int qemu_write(int fd, const void *buf, size_t n)
  112 +{
  113 + QEMU_SYSCALL3(write, fd, buf, n);
  114 +}
  115 +
  116 +
  117 +
  118 +/****************************************************************/
  119 +/* shmat replacement */
  120 +
  121 +int qemu_ipc(int call, unsigned long first,
  122 + unsigned long second, unsigned long third,
  123 + void *ptr, unsigned long fifth)
  124 +{
  125 + QEMU_SYSCALL6(ipc, call, first, second, third, ptr, fifth);
  126 +}
  127 +
  128 +#define SHMAT 21
  129 +
  130 +/* we must define shmat so that a specific address will be used when
  131 + mapping the X11 ximage */
  132 +void *shmat(int shmid, const void *shmaddr, int shmflg)
  133 +{
  134 + void *ptr;
  135 + int ret;
  136 + /* we give an address in the right memory area */
  137 + if (!shmaddr)
  138 + shmaddr = get_mmap_addr(8192 * 1024);
  139 + ret = qemu_ipc(SHMAT, shmid, shmflg, (unsigned long)&ptr, (void *)shmaddr, 0);
  140 + if (ret < 0)
  141 + return NULL;
  142 + return ptr;
  143 +}
  144 +
  145 +/****************************************************************/
  146 +/* memory allocation */
  147 +
  148 +//#define DEBUG_MALLOC
  149 +
  150 +#define MALLOC_BASE 0xab000000
  151 +#define PHYS_RAM_BASE 0xac000000
  152 +
  153 +#define MALLOC_ALIGN 16
  154 +#define BLOCK_HEADER_SIZE 16
  155 +
  156 +typedef struct MemoryBlock {
  157 + struct MemoryBlock *next;
  158 + unsigned long size; /* size of block, including header */
  159 +} MemoryBlock;
  160 +
  161 +static MemoryBlock *first_free_block;
  162 +static unsigned long malloc_addr = MALLOC_BASE;
  163 +
  164 +static void *malloc_get_space(size_t size)
  165 +{
  166 + void *ptr;
  167 + size = TARGET_PAGE_ALIGN(size);
  168 + ptr = mmap((void *)malloc_addr, size,
  169 + PROT_WRITE | PROT_READ,
  170 + MAP_PRIVATE | MAP_FIXED | MAP_ANON, -1, 0);
  171 + if (ptr == MAP_FAILED)
  172 + return NULL;
  173 + malloc_addr += size;
  174 + return ptr;
  175 +}
  176 +
  177 +void *qemu_malloc(size_t size)
  178 +{
  179 + MemoryBlock *mb, *mb1, **pmb;
  180 + void *ptr;
  181 + size_t size1, area_size;
  182 +
  183 + if (size == 0)
  184 + return NULL;
  185 +
  186 + size = (size + BLOCK_HEADER_SIZE + MALLOC_ALIGN - 1) & ~(MALLOC_ALIGN - 1);
  187 + pmb = &first_free_block;
  188 + for(;;) {
  189 + mb = *pmb;
  190 + if (mb == NULL)
  191 + break;
  192 + if (size <= mb->size)
  193 + goto found;
  194 + pmb = &mb->next;
  195 + }
  196 + /* no big enough blocks found: get new space */
  197 + area_size = TARGET_PAGE_ALIGN(size);
  198 + mb = malloc_get_space(area_size);
  199 + if (!mb)
  200 + return NULL;
  201 + size1 = area_size - size;
  202 + if (size1 > 0) {
  203 + /* create a new free block */
  204 + mb1 = (MemoryBlock *)((uint8_t *)mb + size);
  205 + mb1->next = NULL;
  206 + mb1->size = size1;
  207 + *pmb = mb1;
  208 + }
  209 + goto the_end;
  210 + found:
  211 + /* a free block was found: use it */
  212 + size1 = mb->size - size;
  213 + if (size1 > 0) {
  214 + /* create a new free block */
  215 + mb1 = (MemoryBlock *)((uint8_t *)mb + size);
  216 + mb1->next = mb->next;
  217 + mb1->size = size1;
  218 + *pmb = mb1;
  219 + } else {
  220 + /* suppress the first block */
  221 + *pmb = mb->next;
  222 + }
  223 + the_end:
  224 + mb->size = size;
  225 + mb->next = NULL;
  226 + ptr = ((uint8_t *)mb + BLOCK_HEADER_SIZE);
  227 +#ifdef DEBUG_MALLOC
  228 + qemu_printf("malloc: size=0x%x ptr=0x%lx\n", size, (unsigned long)ptr);
  229 +#endif
  230 + return ptr;
  231 +}
  232 +
  233 +void qemu_free(void *ptr)
  234 +{
  235 + MemoryBlock *mb;
  236 +
  237 + mb = (MemoryBlock *)((uint8_t *)ptr - BLOCK_HEADER_SIZE);
  238 + mb->next = first_free_block;
  239 + first_free_block = mb;
  240 +}
  241 +
  242 +/****************************************************************/
  243 +/* virtual memory allocation */
  244 +
  245 +unsigned long mmap_addr = PHYS_RAM_BASE;
  246 +
  247 +void *get_mmap_addr(unsigned long size)
  248 +{
  249 + unsigned long addr;
  250 + addr = mmap_addr;
  251 + mmap_addr += ((size + 4095) & ~4095) + 4096;
  252 + return (void *)addr;
  253 +}
  254 +
  255 +#else
  256 +
  257 +int qemu_write(int fd, const void *buf, size_t n)
  258 +{
  259 + int ret;
  260 + ret = write(fd, buf, n);
  261 + if (ret < 0)
  262 + return -errno;
  263 + else
  264 + return ret;
  265 +}
  266 +
  267 +void *get_mmap_addr(unsigned long size)
  268 +{
  269 + return NULL;
  270 +}
  271 +
  272 +void qemu_free(void *ptr)
  273 +{
  274 + free(ptr);
  275 +}
  276 +
  277 +void *qemu_malloc(size_t size)
  278 +{
  279 + return malloc(size);
  280 +}
  281 +
  282 +#endif
  283 +
  284 +/****************************************************************/
  285 +/* printf support */
  286 +
  287 +static inline int qemu_isdigit(int c)
  288 +{
  289 + return c >= '0' && c <= '9';
  290 +}
  291 +
  292 +#define OUTCHAR(c) (buflen > 0? (--buflen, *buf++ = (c)): 0)
  293 +
  294 +/* from BSD ppp sources */
  295 +int qemu_vsnprintf(char *buf, int buflen, const char *fmt, va_list args)
  296 +{
  297 + int c, i, n;
  298 + int width, prec, fillch;
  299 + int base, len, neg;
  300 + unsigned long val = 0;
  301 + const char *f;
  302 + char *str, *buf0;
  303 + char num[32];
  304 + static const char hexchars[] = "0123456789abcdef";
  305 +
  306 + buf0 = buf;
  307 + --buflen;
  308 + while (buflen > 0) {
  309 + for (f = fmt; *f != '%' && *f != 0; ++f)
  310 + ;
  311 + if (f > fmt) {
  312 + len = f - fmt;
  313 + if (len > buflen)
  314 + len = buflen;
  315 + memcpy(buf, fmt, len);
  316 + buf += len;
  317 + buflen -= len;
  318 + fmt = f;
  319 + }
  320 + if (*fmt == 0)
  321 + break;
  322 + c = *++fmt;
  323 + width = prec = 0;
  324 + fillch = ' ';
  325 + if (c == '0') {
  326 + fillch = '0';
  327 + c = *++fmt;
  328 + }
  329 + if (c == '*') {
  330 + width = va_arg(args, int);
  331 + c = *++fmt;
  332 + } else {
  333 + while (qemu_isdigit(c)) {
  334 + width = width * 10 + c - '0';
  335 + c = *++fmt;
  336 + }
  337 + }
  338 + if (c == '.') {
  339 + c = *++fmt;
  340 + if (c == '*') {
  341 + prec = va_arg(args, int);
  342 + c = *++fmt;
  343 + } else {
  344 + while (qemu_isdigit(c)) {
  345 + prec = prec * 10 + c - '0';
  346 + c = *++fmt;
  347 + }
  348 + }
  349 + }
  350 + /* modifiers */
  351 + switch(c) {
  352 + case 'l':
  353 + c = *++fmt;
  354 + break;
  355 + default:
  356 + break;
  357 + }
  358 + str = 0;
  359 + base = 0;
  360 + neg = 0;
  361 + ++fmt;
  362 + switch (c) {
  363 + case 'd':
  364 + i = va_arg(args, int);
  365 + if (i < 0) {
  366 + neg = 1;
  367 + val = -i;
  368 + } else
  369 + val = i;
  370 + base = 10;
  371 + break;
  372 + case 'o':
  373 + val = va_arg(args, unsigned int);
  374 + base = 8;
  375 + break;
  376 + case 'x':
  377 + case 'X':
  378 + val = va_arg(args, unsigned int);
  379 + base = 16;
  380 + break;
  381 + case 'p':
  382 + val = (unsigned long) va_arg(args, void *);
  383 + base = 16;
  384 + neg = 2;
  385 + break;
  386 + case 's':
  387 + str = va_arg(args, char *);
  388 + break;
  389 + case 'c':
  390 + num[0] = va_arg(args, int);
  391 + num[1] = 0;
  392 + str = num;
  393 + break;
  394 + default:
  395 + *buf++ = '%';
  396 + if (c != '%')
  397 + --fmt; /* so %z outputs %z etc. */
  398 + --buflen;
  399 + continue;
  400 + }
  401 + if (base != 0) {
  402 + str = num + sizeof(num);
  403 + *--str = 0;
  404 + while (str > num + neg) {
  405 + *--str = hexchars[val % base];
  406 + val = val / base;
  407 + if (--prec <= 0 && val == 0)
  408 + break;
  409 + }
  410 + switch (neg) {
  411 + case 1:
  412 + *--str = '-';
  413 + break;
  414 + case 2:
  415 + *--str = 'x';
  416 + *--str = '0';
  417 + break;
  418 + }
  419 + len = num + sizeof(num) - 1 - str;
  420 + } else {
  421 + len = strlen(str);
  422 + if (prec > 0 && len > prec)
  423 + len = prec;
  424 + }
  425 + if (width > 0) {
  426 + if (width > buflen)
  427 + width = buflen;
  428 + if ((n = width - len) > 0) {
  429 + buflen -= n;
  430 + for (; n > 0; --n)
  431 + *buf++ = fillch;
  432 + }
  433 + }
  434 + if (len > buflen)
  435 + len = buflen;
  436 + memcpy(buf, str, len);
  437 + buf += len;
  438 + buflen -= len;
  439 + }
  440 + *buf = 0;
  441 + return buf - buf0;
  442 +}
  443 +
  444 +void qemu_vprintf(const char *fmt, va_list ap)
  445 +{
  446 + char buf[1024];
  447 + int len;
  448 +
  449 + len = qemu_vsnprintf(buf, sizeof(buf), fmt, ap);
  450 + qemu_write(1, buf, len);
  451 +}
  452 +
  453 +void qemu_printf(const char *fmt, ...)
  454 +{
  455 + va_list ap;
  456 + va_start(ap, fmt);
  457 + qemu_vprintf(fmt, ap);
  458 + va_end(ap);
  459 +}
  460 +
... ...
osdep.h 0 → 100644
  1 +#ifndef QEMU_OSDEP_H
  2 +#define QEMU_OSDEP_H
  3 +
  4 +#include <stdarg.h>
  5 +
  6 +int qemu_vsnprintf(char *buf, int buflen, const char *fmt, va_list args);
  7 +void qemu_vprintf(const char *fmt, va_list ap);
  8 +void qemu_printf(const char *fmt, ...);
  9 +
  10 +void *qemu_malloc(size_t size);
  11 +void qemu_free(void *ptr);
  12 +
  13 +void *get_mmap_addr(unsigned long size);
  14 +
  15 +/* specific kludges for OS compatibility (should be moved elsewhere) */
  16 +#if defined(__i386__) && !defined(CONFIG_SOFTMMU) && !defined(CONFIG_USER_ONLY)
  17 +
  18 +/* disabled pthread version of longjmp which prevent us from using an
  19 + alternative signal stack */
  20 +extern void __longjmp(jmp_buf env, int val);
  21 +#define longjmp __longjmp
  22 +
  23 +#endif
  24 +
  25 +#endif
... ...