This commit is contained in:
parent
b3f04a4118
commit
01d85e1b5e
@ -1,380 +0,0 @@
|
||||
diff -rpu qemu-0.9.0.orig/block.c qemu-0.9.0/block.c
|
||||
--- qemu-0.9.0.orig/block.c 2007-02-05 23:01:54.000000000 +0000
|
||||
+++ qemu-0.9.0/block.c 2007-02-20 22:41:03.000000000 +0000
|
||||
@@ -539,13 +539,22 @@ int bdrv_write(BlockDriverState *bs, int
|
||||
return -ENOMEDIUM;
|
||||
if (bs->read_only)
|
||||
return -EACCES;
|
||||
+ if (sector_num < 0)
|
||||
+ return -EINVAL;
|
||||
if (sector_num == 0 && bs->boot_sector_enabled && nb_sectors > 0) {
|
||||
memcpy(bs->boot_sector_data, buf, 512);
|
||||
}
|
||||
if (drv->bdrv_pwrite) {
|
||||
int ret, len;
|
||||
+ unsigned ns;
|
||||
+
|
||||
+ ns = sector_num * 512;
|
||||
len = nb_sectors * 512;
|
||||
- ret = drv->bdrv_pwrite(bs, sector_num * 512, buf, len);
|
||||
+
|
||||
+ if (ns < 0)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ ret = drv->bdrv_pwrite(bs, ns, buf, len);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
else if (ret != len)
|
||||
diff -rpu qemu-0.9.0.orig/hw/cirrus_vga.c qemu-0.9.0/hw/cirrus_vga.c
|
||||
--- qemu-0.9.0.orig/hw/cirrus_vga.c 2007-02-05 23:01:54.000000000 +0000
|
||||
+++ qemu-0.9.0/hw/cirrus_vga.c 2007-02-21 17:00:09.585042632 +0000
|
||||
@@ -217,6 +217,20 @@
|
||||
#define CIRRUS_HOOK_NOT_HANDLED 0
|
||||
#define CIRRUS_HOOK_HANDLED 1
|
||||
|
||||
+#define BLTUNSAFE(s) \
|
||||
+ ( \
|
||||
+ ( /* check dst is within bounds */ \
|
||||
+ (s)->cirrus_blt_height * (s)->cirrus_blt_dstpitch \
|
||||
+ + ((s)->cirrus_blt_dstaddr & (s)->cirrus_addr_mask) > \
|
||||
+ (s)->vram_size \
|
||||
+ ) || \
|
||||
+ ( /* check src is within bounds */ \
|
||||
+ (s)->cirrus_blt_height * (s)->cirrus_blt_srcpitch \
|
||||
+ + ((s)->cirrus_blt_srcaddr & (s)->cirrus_addr_mask) > \
|
||||
+ (s)->vram_size \
|
||||
+ ) \
|
||||
+ )
|
||||
+
|
||||
struct CirrusVGAState;
|
||||
typedef void (*cirrus_bitblt_rop_t) (struct CirrusVGAState *s,
|
||||
uint8_t * dst, const uint8_t * src,
|
||||
@@ -589,7 +603,7 @@ static void cirrus_invalidate_region(Cir
|
||||
|
||||
for (y = 0; y < lines; y++) {
|
||||
off_cur = off_begin;
|
||||
- off_cur_end = off_cur + bytesperline;
|
||||
+ off_cur_end = (off_cur + bytesperline) & s->cirrus_addr_mask;
|
||||
off_cur &= TARGET_PAGE_MASK;
|
||||
while (off_cur < off_cur_end) {
|
||||
cpu_physical_memory_set_dirty(s->vram_offset + off_cur);
|
||||
@@ -604,7 +618,11 @@ static int cirrus_bitblt_common_patternc
|
||||
{
|
||||
uint8_t *dst;
|
||||
|
||||
- dst = s->vram_ptr + s->cirrus_blt_dstaddr;
|
||||
+ dst = s->vram_ptr + (s->cirrus_blt_dstaddr & s->cirrus_addr_mask);
|
||||
+
|
||||
+ if (BLTUNSAFE(s))
|
||||
+ return 0;
|
||||
+
|
||||
(*s->cirrus_rop) (s, dst, src,
|
||||
s->cirrus_blt_dstpitch, 0,
|
||||
s->cirrus_blt_width, s->cirrus_blt_height);
|
||||
@@ -620,8 +638,11 @@ static int cirrus_bitblt_solidfill(Cirru
|
||||
{
|
||||
cirrus_fill_t rop_func;
|
||||
|
||||
+ if (BLTUNSAFE(s))
|
||||
+ return 0;
|
||||
+
|
||||
rop_func = cirrus_fill[rop_to_index[blt_rop]][s->cirrus_blt_pixelwidth - 1];
|
||||
- rop_func(s, s->vram_ptr + s->cirrus_blt_dstaddr,
|
||||
+ rop_func(s, s->vram_ptr + (s->cirrus_blt_dstaddr & s->cirrus_addr_mask),
|
||||
s->cirrus_blt_dstpitch,
|
||||
s->cirrus_blt_width, s->cirrus_blt_height);
|
||||
cirrus_invalidate_region(s, s->cirrus_blt_dstaddr,
|
||||
@@ -640,8 +661,8 @@ static int cirrus_bitblt_solidfill(Cirru
|
||||
static int cirrus_bitblt_videotovideo_patterncopy(CirrusVGAState * s)
|
||||
{
|
||||
return cirrus_bitblt_common_patterncopy(s,
|
||||
- s->vram_ptr +
|
||||
- (s->cirrus_blt_srcaddr & ~7));
|
||||
+ s->vram_ptr + ((s->cirrus_blt_srcaddr & ~7) &
|
||||
+ s->cirrus_addr_mask));
|
||||
}
|
||||
|
||||
static void cirrus_do_copy(CirrusVGAState *s, int dst, int src, int w, int h)
|
||||
@@ -691,8 +712,10 @@ static void cirrus_do_copy(CirrusVGAStat
|
||||
if (notify)
|
||||
vga_hw_update();
|
||||
|
||||
- (*s->cirrus_rop) (s, s->vram_ptr + s->cirrus_blt_dstaddr,
|
||||
- s->vram_ptr + s->cirrus_blt_srcaddr,
|
||||
+ (*s->cirrus_rop) (s, s->vram_ptr +
|
||||
+ (s->cirrus_blt_dstaddr & s->cirrus_addr_mask),
|
||||
+ s->vram_ptr +
|
||||
+ (s->cirrus_blt_srcaddr & s->cirrus_addr_mask),
|
||||
s->cirrus_blt_dstpitch, s->cirrus_blt_srcpitch,
|
||||
s->cirrus_blt_width, s->cirrus_blt_height);
|
||||
|
||||
@@ -718,8 +741,14 @@ static int cirrus_bitblt_videotovideo_co
|
||||
s->cirrus_blt_srcaddr - s->start_addr,
|
||||
s->cirrus_blt_width, s->cirrus_blt_height);
|
||||
} else {
|
||||
- (*s->cirrus_rop) (s, s->vram_ptr + s->cirrus_blt_dstaddr,
|
||||
- s->vram_ptr + s->cirrus_blt_srcaddr,
|
||||
+
|
||||
+ if (BLTUNSAFE(s))
|
||||
+ return 0;
|
||||
+
|
||||
+ (*s->cirrus_rop) (s, s->vram_ptr +
|
||||
+ (s->cirrus_blt_dstaddr & s->cirrus_addr_mask),
|
||||
+ s->vram_ptr +
|
||||
+ (s->cirrus_blt_srcaddr & s->cirrus_addr_mask),
|
||||
s->cirrus_blt_dstpitch, s->cirrus_blt_srcpitch,
|
||||
s->cirrus_blt_width, s->cirrus_blt_height);
|
||||
|
||||
@@ -751,8 +780,9 @@ static void cirrus_bitblt_cputovideo_nex
|
||||
} else {
|
||||
/* at least one scan line */
|
||||
do {
|
||||
- (*s->cirrus_rop)(s, s->vram_ptr + s->cirrus_blt_dstaddr,
|
||||
- s->cirrus_bltbuf, 0, 0, s->cirrus_blt_width, 1);
|
||||
+ (*s->cirrus_rop)(s, s->vram_ptr +
|
||||
+ (s->cirrus_blt_dstaddr & s->cirrus_addr_mask),
|
||||
+ s->cirrus_bltbuf, 0, 0, s->cirrus_blt_width, 1);
|
||||
cirrus_invalidate_region(s, s->cirrus_blt_dstaddr, 0,
|
||||
s->cirrus_blt_width, 1);
|
||||
s->cirrus_blt_dstaddr += s->cirrus_blt_dstpitch;
|
||||
@@ -1857,7 +1887,7 @@ static void cirrus_mem_writeb_mode4and5_
|
||||
unsigned val = mem_value;
|
||||
uint8_t *dst;
|
||||
|
||||
- dst = s->vram_ptr + offset;
|
||||
+ dst = s->vram_ptr + (offset &= s->cirrus_addr_mask);
|
||||
for (x = 0; x < 8; x++) {
|
||||
if (val & 0x80) {
|
||||
*dst = s->cirrus_shadow_gr1;
|
||||
@@ -1880,7 +1910,7 @@ static void cirrus_mem_writeb_mode4and5_
|
||||
unsigned val = mem_value;
|
||||
uint8_t *dst;
|
||||
|
||||
- dst = s->vram_ptr + offset;
|
||||
+ dst = s->vram_ptr + (offset &= s->cirrus_addr_mask);
|
||||
for (x = 0; x < 8; x++) {
|
||||
if (val & 0x80) {
|
||||
*dst = s->cirrus_shadow_gr1;
|
||||
diff -rpu qemu-0.9.0.orig/hw/cirrus_vga_rop.h qemu-0.9.0/hw/cirrus_vga_rop.h
|
||||
--- qemu-0.9.0.orig/hw/cirrus_vga_rop.h 2007-02-05 23:01:54.000000000 +0000
|
||||
+++ qemu-0.9.0/hw/cirrus_vga_rop.h 2007-02-21 01:45:32.000000000 +0000
|
||||
@@ -31,6 +31,12 @@ glue(cirrus_bitblt_rop_fwd_, ROP_NAME)(C
|
||||
int x,y;
|
||||
dstpitch -= bltwidth;
|
||||
srcpitch -= bltwidth;
|
||||
+
|
||||
+ if (dstpitch < 0 || srcpitch < 0) {
|
||||
+ /* is 0 valid? srcpitch == 0 could be useful */
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
for (y = 0; y < bltheight; y++) {
|
||||
for (x = 0; x < bltwidth; x++) {
|
||||
ROP_OP(*dst, *src);
|
||||
diff -rpu qemu-0.9.0.orig/hw/dma.c qemu-0.9.0/hw/dma.c
|
||||
--- qemu-0.9.0.orig/hw/dma.c 2007-02-05 23:01:54.000000000 +0000
|
||||
+++ qemu-0.9.0/hw/dma.c 2007-02-20 21:53:41.000000000 +0000
|
||||
@@ -340,9 +340,11 @@ static void channel_run (int ncont, int
|
||||
#endif
|
||||
|
||||
r = dma_controllers[ncont].regs + ichan;
|
||||
- n = r->transfer_handler (r->opaque, ichan + (ncont << 2),
|
||||
- r->now[COUNT], (r->base[COUNT] + 1) << ncont);
|
||||
- r->now[COUNT] = n;
|
||||
+ if (r->transfer_handler) {
|
||||
+ n = r->transfer_handler (r->opaque, ichan + (ncont << 2),
|
||||
+ r->now[COUNT], (r->base[COUNT] + 1) << ncont);
|
||||
+ r->now[COUNT] = n;
|
||||
+ }
|
||||
ldebug ("dma_pos %d size %d\n", n, (r->base[COUNT] + 1) << ncont);
|
||||
}
|
||||
|
||||
diff -rpu qemu-0.9.0.orig/hw/fdc.c qemu-0.9.0/hw/fdc.c
|
||||
--- qemu-0.9.0.orig/hw/fdc.c 2007-02-05 23:01:54.000000000 +0000
|
||||
+++ qemu-0.9.0/hw/fdc.c 2007-02-20 23:41:01.000000000 +0000
|
||||
@@ -1100,8 +1100,13 @@ static uint32_t fdctrl_read_data (fdctrl
|
||||
len = fdctrl->data_len - fdctrl->data_pos;
|
||||
if (len > FD_SECTOR_LEN)
|
||||
len = FD_SECTOR_LEN;
|
||||
- bdrv_read(cur_drv->bs, fd_sector(cur_drv),
|
||||
- fdctrl->fifo, len);
|
||||
+ if (cur_drv->bs) {
|
||||
+ bdrv_read(cur_drv->bs, fd_sector(cur_drv),
|
||||
+ fdctrl->fifo, len);
|
||||
+ } else {
|
||||
+ FLOPPY_ERROR("can't read data from drive\n");
|
||||
+ return 0;
|
||||
+ }
|
||||
}
|
||||
}
|
||||
retval = fdctrl->fifo[pos];
|
||||
diff -rpu qemu-0.9.0.orig/hw/i8259.c qemu-0.9.0/hw/i8259.c
|
||||
--- qemu-0.9.0.orig/hw/i8259.c 2007-02-05 23:01:54.000000000 +0000
|
||||
+++ qemu-0.9.0/hw/i8259.c 2007-02-20 21:53:41.000000000 +0000
|
||||
@@ -299,9 +299,11 @@ static void pic_ioport_write(void *opaqu
|
||||
s->init_state = 1;
|
||||
s->init4 = val & 1;
|
||||
if (val & 0x02)
|
||||
- hw_error("single mode not supported");
|
||||
+ /* hw_error("single mode not supported"); */
|
||||
+ return;
|
||||
if (val & 0x08)
|
||||
- hw_error("level sensitive irq not supported");
|
||||
+ /* hw_error("level sensitive irq not supported"); */
|
||||
+ return;
|
||||
} else if (val & 0x08) {
|
||||
if (val & 0x04)
|
||||
s->poll = 1;
|
||||
diff -rpu qemu-0.9.0.orig/hw/ne2000.c qemu-0.9.0/hw/ne2000.c
|
||||
--- qemu-0.9.0.orig/hw/ne2000.c 2007-02-05 23:01:54.000000000 +0000
|
||||
+++ qemu-0.9.0/hw/ne2000.c 2007-02-20 21:53:41.000000000 +0000
|
||||
@@ -230,7 +230,7 @@ static void ne2000_receive(void *opaque,
|
||||
{
|
||||
NE2000State *s = opaque;
|
||||
uint8_t *p;
|
||||
- int total_len, next, avail, len, index, mcast_idx;
|
||||
+ unsigned int total_len, next, avail, len, index, mcast_idx;
|
||||
uint8_t buf1[60];
|
||||
static const uint8_t broadcast_macaddr[6] =
|
||||
{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
|
||||
@@ -299,7 +299,11 @@ static void ne2000_receive(void *opaque,
|
||||
|
||||
/* write packet data */
|
||||
while (size > 0) {
|
||||
- avail = s->stop - index;
|
||||
+ /* taviso: this can wrap, so check its okay. */
|
||||
+ if (index <= s->stop)
|
||||
+ avail = s->stop - index;
|
||||
+ else
|
||||
+ avail = 0;
|
||||
len = size;
|
||||
if (len > avail)
|
||||
len = avail;
|
||||
diff -rpu qemu-0.9.0.orig/hw/pc.c qemu-0.9.0/hw/pc.c
|
||||
--- qemu-0.9.0.orig/hw/pc.c 2007-02-05 23:01:54.000000000 +0000
|
||||
+++ qemu-0.9.0/hw/pc.c 2007-02-20 21:53:41.000000000 +0000
|
||||
@@ -299,7 +299,8 @@ void bochs_bios_write(void *opaque, uint
|
||||
case 0x400:
|
||||
case 0x401:
|
||||
fprintf(stderr, "BIOS panic at rombios.c, line %d\n", val);
|
||||
- exit(1);
|
||||
+ /* according to documentation, these can be safely ignored */
|
||||
+ break;
|
||||
case 0x402:
|
||||
case 0x403:
|
||||
#ifdef DEBUG_BIOS
|
||||
@@ -322,8 +323,9 @@ void bochs_bios_write(void *opaque, uint
|
||||
/* LGPL'ed VGA BIOS messages */
|
||||
case 0x501:
|
||||
case 0x502:
|
||||
+ /* according to documentation, these can be safely ignored */
|
||||
fprintf(stderr, "VGA BIOS panic, line %d\n", val);
|
||||
- exit(1);
|
||||
+ break;
|
||||
case 0x500:
|
||||
case 0x503:
|
||||
#ifdef DEBUG_BIOS
|
||||
diff -rpu qemu-0.9.0.orig/hw/sb16.c qemu-0.9.0/hw/sb16.c
|
||||
--- qemu-0.9.0.orig/hw/sb16.c 2007-02-05 23:01:54.000000000 +0000
|
||||
+++ qemu-0.9.0/hw/sb16.c 2007-02-20 21:53:41.000000000 +0000
|
||||
@@ -1235,8 +1235,10 @@ static int SB_read_DMA (void *opaque, in
|
||||
s->block_size);
|
||||
#endif
|
||||
|
||||
- while (s->left_till_irq <= 0) {
|
||||
- s->left_till_irq = s->block_size + s->left_till_irq;
|
||||
+ if (s->block_size) {
|
||||
+ while (s->left_till_irq <= 0) {
|
||||
+ s->left_till_irq = s->block_size + s->left_till_irq;
|
||||
+ }
|
||||
}
|
||||
|
||||
return dma_pos;
|
||||
diff -rpu qemu-0.9.0.orig/slirp/slirp.c qemu-0.9.0/slirp/slirp.c
|
||||
--- qemu-0.9.0.orig/slirp/slirp.c 2007-02-05 23:01:54.000000000 +0000
|
||||
+++ qemu-0.9.0/slirp/slirp.c 2007-02-20 21:53:41.000000000 +0000
|
||||
@@ -611,6 +611,10 @@ void slirp_input(const uint8_t *pkt, int
|
||||
if (!m)
|
||||
return;
|
||||
/* Note: we add to align the IP header */
|
||||
+ /* taviso: large values in ne2k TCNT register may exceed msize on transmit */
|
||||
+ if (M_FREEROOM(m) < pkt_len + 2) {
|
||||
+ m_inc(m, pkt_len + 2);
|
||||
+ }
|
||||
m->m_len = pkt_len + 2;
|
||||
memcpy(m->m_data + 2, pkt, pkt_len);
|
||||
|
||||
diff -rpu qemu-0.9.0.orig/target-i386/translate.c qemu-0.9.0/target-i386/translate.c
|
||||
--- qemu-0.9.0.orig/target-i386/translate.c 2007-02-05 23:01:54.000000000 +0000
|
||||
+++ qemu-0.9.0/target-i386/translate.c 2007-02-20 21:53:41.000000000 +0000
|
||||
@@ -5326,7 +5326,12 @@ static target_ulong disas_insn(DisasCont
|
||||
if (CODE64(s))
|
||||
goto illegal_op;
|
||||
val = ldub_code(s->pc++);
|
||||
- gen_op_aam(val);
|
||||
+ /* taviso: operand can be zero */
|
||||
+ if (val) {
|
||||
+ gen_op_aam(val);
|
||||
+ } else {
|
||||
+ gen_exception(s, EXCP00_DIVZ, s->pc - s->cs_base);
|
||||
+ }
|
||||
s->cc_op = CC_OP_LOGICB;
|
||||
break;
|
||||
case 0xd5: /* aad */
|
||||
@@ -5374,6 +5379,7 @@ static target_ulong disas_insn(DisasCont
|
||||
gen_jmp_im(pc_start - s->cs_base);
|
||||
gen_op_into(s->pc - pc_start);
|
||||
break;
|
||||
+#ifdef WANT_ICEBP
|
||||
case 0xf1: /* icebp (undocumented, exits to external debugger) */
|
||||
#if 1
|
||||
gen_debug(s, pc_start - s->cs_base);
|
||||
@@ -5383,6 +5389,7 @@ static target_ulong disas_insn(DisasCont
|
||||
cpu_set_log(CPU_LOG_INT | CPU_LOG_TB_IN_ASM);
|
||||
#endif
|
||||
break;
|
||||
+#endif /* icebp */
|
||||
case 0xfa: /* cli */
|
||||
if (!s->vm86) {
|
||||
if (s->cpl <= s->iopl) {
|
||||
diff -rpu qemu-0.9.0.orig/vl.c qemu-0.9.0/vl.c
|
||||
--- qemu-0.9.0.orig/vl.c 2007-02-05 23:01:54.000000000 +0000
|
||||
+++ qemu-0.9.0/vl.c 2007-02-20 21:53:41.000000000 +0000
|
||||
@@ -3329,8 +3329,8 @@ typedef struct NetSocketState {
|
||||
VLANClientState *vc;
|
||||
int fd;
|
||||
int state; /* 0 = getting length, 1 = getting data */
|
||||
- int index;
|
||||
- int packet_len;
|
||||
+ unsigned int index;
|
||||
+ unsigned int packet_len;
|
||||
uint8_t buf[4096];
|
||||
struct sockaddr_in dgram_dst; /* contains inet host and port destination iff connectionless (SOCK_DGRAM) */
|
||||
} NetSocketState;
|
||||
@@ -3361,7 +3361,8 @@ static void net_socket_receive_dgram(voi
|
||||
static void net_socket_send(void *opaque)
|
||||
{
|
||||
NetSocketState *s = opaque;
|
||||
- int l, size, err;
|
||||
+ int size, err;
|
||||
+ unsigned l;
|
||||
uint8_t buf1[4096];
|
||||
const uint8_t *buf;
|
||||
|
||||
@@ -3400,7 +3401,15 @@ static void net_socket_send(void *opaque
|
||||
l = s->packet_len - s->index;
|
||||
if (l > size)
|
||||
l = size;
|
||||
- memcpy(s->buf + s->index, buf, l);
|
||||
+ if (s->index + l <= sizeof(s->buf)) {
|
||||
+ memcpy(s->buf + s->index, buf, l);
|
||||
+ } else {
|
||||
+ fprintf(stderr, "serious error: oversized packet received,"
|
||||
+ "connection terminated.\n");
|
||||
+ s->state = 0;
|
||||
+ goto eoc;
|
||||
+ }
|
||||
+
|
||||
s->index += l;
|
||||
buf += l;
|
||||
size -= l;
|
@ -274,309 +274,3 @@
|
||||
- /* These must appear regardless of . */
|
||||
+ /DISCARD/ : { *(.note.GNU-stack) }
|
||||
}
|
||||
--- ppc.ld
|
||||
+++ ppc.ld
|
||||
@@ -1,116 +1,200 @@
|
||||
-/* ld script to make i386 Linux kernel
|
||||
- * Written by Martin Mares <mj@atrey.karlin.mff.cuni.cz>;
|
||||
- */
|
||||
-OUTPUT_FORMAT("elf32-powerpc", "elf32-powerpc", "elf32-powerpc")
|
||||
-OUTPUT_ARCH(powerpc)
|
||||
-SEARCH_DIR(/lib); SEARCH_DIR(/usr/lib); SEARCH_DIR(/usr/local/lib); SEARCH_DIR(/usr/alpha-unknown-linux-gnu/lib);
|
||||
+/* Default linker script, for normal executables */
|
||||
+OUTPUT_FORMAT("elf32-powerpc", "elf32-powerpc",
|
||||
+ "elf32-powerpc")
|
||||
+OUTPUT_ARCH(powerpc:common)
|
||||
ENTRY(_start)
|
||||
+SEARCH_DIR("/usr/powerpc-suse-linux/lib"); SEARCH_DIR("/usr/local/lib"); SEARCH_DIR("/lib"); SEARCH_DIR("/usr/lib");
|
||||
SECTIONS
|
||||
{
|
||||
/* Read-only sections, merged into text segment: */
|
||||
- . = 0x60000000 + SIZEOF_HEADERS;
|
||||
- .interp : { *(.interp) }
|
||||
- .hash : { *(.hash) }
|
||||
- .dynsym : { *(.dynsym) }
|
||||
- .dynstr : { *(.dynstr) }
|
||||
- .gnu.version : { *(.gnu.version) }
|
||||
- .gnu.version_d : { *(.gnu.version_d) }
|
||||
- .gnu.version_r : { *(.gnu.version_r) }
|
||||
- .rel.text :
|
||||
- { *(.rel.text) *(.rel.gnu.linkonce.t*) }
|
||||
- .rela.text :
|
||||
- { *(.rela.text) *(.rela.gnu.linkonce.t*) }
|
||||
- .rel.data :
|
||||
- { *(.rel.data) *(.rel.gnu.linkonce.d*) }
|
||||
- .rela.data :
|
||||
- { *(.rela.data) *(.rela.gnu.linkonce.d*) }
|
||||
- .rel.rodata :
|
||||
- { *(.rel.rodata) *(.rel.gnu.linkonce.r*) }
|
||||
- .rela.rodata :
|
||||
- { *(.rela.rodata) *(.rela.gnu.linkonce.r*) }
|
||||
- .rel.got : { *(.rel.got) }
|
||||
- .rela.got : { *(.rela.got) }
|
||||
- .rel.ctors : { *(.rel.ctors) }
|
||||
- .rela.ctors : { *(.rela.ctors) }
|
||||
- .rel.dtors : { *(.rel.dtors) }
|
||||
- .rela.dtors : { *(.rela.dtors) }
|
||||
- .rel.init : { *(.rel.init) }
|
||||
- .rela.init : { *(.rela.init) }
|
||||
- .rel.fini : { *(.rel.fini) }
|
||||
- .rela.fini : { *(.rela.fini) }
|
||||
- .rel.bss : { *(.rel.bss) }
|
||||
- .rela.bss : { *(.rela.bss) }
|
||||
- .rel.plt : { *(.rel.plt) }
|
||||
- .rela.plt : { *(.rela.plt) }
|
||||
- .init : { *(.init) } =0x47ff041f
|
||||
- .text :
|
||||
+ PROVIDE (__executable_start = 0x60000000); . = 0x60000000 + SIZEOF_HEADERS;
|
||||
+ .interp : { *(.interp) }
|
||||
+ .hash : { *(.hash) }
|
||||
+ .dynsym : { *(.dynsym) }
|
||||
+ .dynstr : { *(.dynstr) }
|
||||
+ .gnu.version : { *(.gnu.version) }
|
||||
+ .gnu.version_d : { *(.gnu.version_d) }
|
||||
+ .gnu.version_r : { *(.gnu.version_r) }
|
||||
+ .rel.init : { *(.rel.init) }
|
||||
+ .rela.init : { *(.rela.init) }
|
||||
+ .rel.text : { *(.rel.text .rel.text.* .rel.gnu.linkonce.t.*) }
|
||||
+ .rela.text : { *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*) }
|
||||
+ .rel.fini : { *(.rel.fini) }
|
||||
+ .rela.fini : { *(.rela.fini) }
|
||||
+ .rel.rodata : { *(.rel.rodata .rel.rodata.* .rel.gnu.linkonce.r.*) }
|
||||
+ .rela.rodata : { *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*) }
|
||||
+ .rel.data.rel.ro : { *(.rel.data.rel.ro*) }
|
||||
+ .rela.data.rel.ro : { *(.rel.data.rel.ro*) }
|
||||
+ .rel.data : { *(.rel.data .rel.data.* .rel.gnu.linkonce.d.*) }
|
||||
+ .rela.data : { *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*) }
|
||||
+ .rel.tdata : { *(.rel.tdata .rel.tdata.* .rel.gnu.linkonce.td.*) }
|
||||
+ .rela.tdata : { *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*) }
|
||||
+ .rel.tbss : { *(.rel.tbss .rel.tbss.* .rel.gnu.linkonce.tb.*) }
|
||||
+ .rela.tbss : { *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*) }
|
||||
+ .rel.ctors : { *(.rel.ctors) }
|
||||
+ .rela.ctors : { *(.rela.ctors) }
|
||||
+ .rel.dtors : { *(.rel.dtors) }
|
||||
+ .rela.dtors : { *(.rela.dtors) }
|
||||
+ .rel.got : { *(.rel.got) }
|
||||
+ .rela.got : { *(.rela.got) }
|
||||
+ .rela.got1 : { *(.rela.got1) }
|
||||
+ .rela.got2 : { *(.rela.got2) }
|
||||
+ .rel.sdata : { *(.rel.sdata .rel.sdata.* .rel.gnu.linkonce.s.*) }
|
||||
+ .rela.sdata : { *(.rela.sdata .rela.sdata.* .rela.gnu.linkonce.s.*) }
|
||||
+ .rel.sbss : { *(.rel.sbss .rel.sbss.* .rel.gnu.linkonce.sb.*) }
|
||||
+ .rela.sbss : { *(.rela.sbss .rela.sbss.* .rela.gnu.linkonce.sb.*) }
|
||||
+ .rel.sdata2 : { *(.rel.sdata2 .rel.sdata2.* .rel.gnu.linkonce.s2.*) }
|
||||
+ .rela.sdata2 : { *(.rela.sdata2 .rela.sdata2.* .rela.gnu.linkonce.s2.*) }
|
||||
+ .rel.sbss2 : { *(.rel.sbss2 .rel.sbss2.* .rel.gnu.linkonce.sb2.*) }
|
||||
+ .rela.sbss2 : { *(.rela.sbss2 .rela.sbss2.* .rela.gnu.linkonce.sb2.*) }
|
||||
+ .rel.bss : { *(.rel.bss .rel.bss.* .rel.gnu.linkonce.b.*) }
|
||||
+ .rela.bss : { *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*) }
|
||||
+ .rel.plt : { *(.rel.plt) }
|
||||
+ .rela.plt : { *(.rela.plt) }
|
||||
+ .init :
|
||||
{
|
||||
- *(.text)
|
||||
+ KEEP (*(.init))
|
||||
+ } =0
|
||||
+ .text :
|
||||
+ {
|
||||
+ *(.text .stub .text.* .gnu.linkonce.t.*)
|
||||
+ KEEP (*(.text.*personality*))
|
||||
/* .gnu.warning sections are handled specially by elf32.em. */
|
||||
*(.gnu.warning)
|
||||
- *(.gnu.linkonce.t*)
|
||||
- } =0x47ff041f
|
||||
- _etext = .;
|
||||
+ *(.glink)
|
||||
+ } =0
|
||||
+ .fini :
|
||||
+ {
|
||||
+ KEEP (*(.fini))
|
||||
+ } =0
|
||||
+ PROVIDE (__etext = .);
|
||||
+ PROVIDE (_etext = .);
|
||||
PROVIDE (etext = .);
|
||||
- .fini : { *(.fini) } =0x47ff041f
|
||||
- . = ALIGN(32 / 8);
|
||||
- PROVIDE (__preinit_array_start = .);
|
||||
- .preinit_array : { *(.preinit_array) }
|
||||
- PROVIDE (__preinit_array_end = .);
|
||||
- PROVIDE (__init_array_start = .);
|
||||
- .init_array : { *(.init_array) }
|
||||
- PROVIDE (__init_array_end = .);
|
||||
- PROVIDE (__fini_array_start = .);
|
||||
- .fini_array : { *(.fini_array) }
|
||||
- PROVIDE (__fini_array_end = .);
|
||||
- .rodata : { *(.rodata) *(.gnu.linkonce.r*) }
|
||||
- .rodata1 : { *(.rodata1) }
|
||||
- .reginfo : { *(.reginfo) }
|
||||
+ .rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) }
|
||||
+ .rodata1 : { *(.rodata1) }
|
||||
+ .sdata2 :
|
||||
+ {
|
||||
+ PROVIDE (_SDA2_BASE_ = 32768);
|
||||
+ *(.sdata2 .sdata2.* .gnu.linkonce.s2.*)
|
||||
+ }
|
||||
+ .sbss2 : { *(.sbss2 .sbss2.* .gnu.linkonce.sb2.*) }
|
||||
+ .eh_frame_hdr : { *(.eh_frame_hdr) }
|
||||
+ .eh_frame : ONLY_IF_RO { KEEP (*(.eh_frame)) }
|
||||
+ .gcc_except_table : ONLY_IF_RO { *(.gcc_except_table .gcc_except_table.*) }
|
||||
/* Adjust the address for the data segment. We want to adjust up to
|
||||
the same address within the page on the next page up. */
|
||||
- . = ALIGN(0x100000) + (. & (0x100000 - 1));
|
||||
- .data :
|
||||
+ . = ALIGN (0x10000) - ((0x10000 - .) & (0x10000 - 1)); . = DATA_SEGMENT_ALIGN (0x10000, 0x1000);
|
||||
+ /* Exception handling */
|
||||
+ .eh_frame : ONLY_IF_RW { KEEP (*(.eh_frame)) }
|
||||
+ .gcc_except_table : ONLY_IF_RW { *(.gcc_except_table .gcc_except_table.*) }
|
||||
+ /* Thread Local Storage sections */
|
||||
+ .tdata : { *(.tdata .tdata.* .gnu.linkonce.td.*) }
|
||||
+ .tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) }
|
||||
+ .preinit_array :
|
||||
+ {
|
||||
+ PROVIDE_HIDDEN (__preinit_array_start = .);
|
||||
+ KEEP (*(.preinit_array))
|
||||
+ PROVIDE_HIDDEN (__preinit_array_end = .);
|
||||
+ }
|
||||
+ .init_array :
|
||||
+ {
|
||||
+ PROVIDE_HIDDEN (__init_array_start = .);
|
||||
+ KEEP (*(.init_array))
|
||||
+ PROVIDE_HIDDEN (__init_array_end = .);
|
||||
+ }
|
||||
+ .fini_array :
|
||||
{
|
||||
- *(.data)
|
||||
- *(.gnu.linkonce.d*)
|
||||
- CONSTRUCTORS
|
||||
+ PROVIDE_HIDDEN (__fini_array_start = .);
|
||||
+ KEEP (*(.fini_array))
|
||||
+ PROVIDE_HIDDEN (__fini_array_end = .);
|
||||
}
|
||||
- .data1 : { *(.data1) }
|
||||
- .ctors :
|
||||
+ .ctors :
|
||||
{
|
||||
- *(.ctors)
|
||||
+ /* gcc uses crtbegin.o to find the start of
|
||||
+ the constructors, so we make sure it is
|
||||
+ first. Because this is a wildcard, it
|
||||
+ doesn't matter if the user does not
|
||||
+ actually link against crtbegin.o; the
|
||||
+ linker won't look for a file to match a
|
||||
+ wildcard. The wildcard also means that it
|
||||
+ doesn't matter which directory crtbegin.o
|
||||
+ is in. */
|
||||
+ KEEP (*crtbegin*.o(.ctors))
|
||||
+ /* We don't want to include the .ctor section from
|
||||
+ from the crtend.o file until after the sorted ctors.
|
||||
+ The .ctor section from the crtend file contains the
|
||||
+ end of ctors marker and it must be last */
|
||||
+ KEEP (*(EXCLUDE_FILE (*crtend*.o ) .ctors))
|
||||
+ KEEP (*(SORT(.ctors.*)))
|
||||
+ KEEP (*(.ctors))
|
||||
}
|
||||
- .dtors :
|
||||
+ .dtors :
|
||||
{
|
||||
- *(.dtors)
|
||||
+ KEEP (*crtbegin*.o(.dtors))
|
||||
+ KEEP (*(EXCLUDE_FILE (*crtend*.o ) .dtors))
|
||||
+ KEEP (*(SORT(.dtors.*)))
|
||||
+ KEEP (*(.dtors))
|
||||
}
|
||||
- .plt : { *(.plt) }
|
||||
- .got : { *(.got.plt) *(.got) }
|
||||
- .dynamic : { *(.dynamic) }
|
||||
+ .jcr : { KEEP (*(.jcr)) }
|
||||
+ .data.rel.ro : { *(.data.rel.ro.local) *(.data.rel.ro*) }
|
||||
+ .got1 : { *(.got1) }
|
||||
+ .got2 : { *(.got2) }
|
||||
+ .dynamic : { *(.dynamic) }
|
||||
+ .got : SPECIAL { *(.got) }
|
||||
+ . = DATA_SEGMENT_RELRO_END (0, .);
|
||||
+ .plt : SPECIAL { *(.plt) }
|
||||
+ .data :
|
||||
+ {
|
||||
+ *(.data .data.* .gnu.linkonce.d.*)
|
||||
+ KEEP (*(.gnu.linkonce.d.*personality*))
|
||||
+ SORT(CONSTRUCTORS)
|
||||
+ }
|
||||
+ .data1 : { *(.data1) }
|
||||
+ .got : SPECIAL { *(.got) }
|
||||
/* We want the small data sections together, so single-instruction offsets
|
||||
can access them all, and initialized data all before uninitialized, so
|
||||
we can shorten the on-disk segment size. */
|
||||
- .sdata : { *(.sdata) }
|
||||
- _edata = .;
|
||||
- PROVIDE (edata = .);
|
||||
+ .sdata :
|
||||
+ {
|
||||
+ PROVIDE (_SDA_BASE_ = 32768);
|
||||
+ *(.sdata .sdata.* .gnu.linkonce.s.*)
|
||||
+ }
|
||||
+ _edata = .; PROVIDE (edata = .);
|
||||
__bss_start = .;
|
||||
- .sbss : { *(.sbss) *(.scommon) }
|
||||
- .bss :
|
||||
+ .sbss :
|
||||
+ {
|
||||
+ PROVIDE (__sbss_start = .); PROVIDE (___sbss_start = .);
|
||||
+ *(.dynsbss)
|
||||
+ *(.sbss .sbss.* .gnu.linkonce.sb.*)
|
||||
+ *(.scommon)
|
||||
+ PROVIDE (__sbss_end = .); PROVIDE (___sbss_end = .);
|
||||
+ }
|
||||
+ .plt : SPECIAL { *(.plt) }
|
||||
+ .bss :
|
||||
{
|
||||
*(.dynbss)
|
||||
- *(.bss)
|
||||
+ *(.bss .bss.* .gnu.linkonce.b.*)
|
||||
*(COMMON)
|
||||
+ /* Align here to ensure that the .bss section occupies space up to
|
||||
+ _end. Align after .bss to ensure correct alignment even if the
|
||||
+ .bss section disappears because there are no input sections.
|
||||
+ FIXME: Why do we need it? When there is no .bss section, we don't
|
||||
+ pad the .data section. */
|
||||
+ . = ALIGN(. != 0 ? 32 / 8 : 1);
|
||||
}
|
||||
- _end = . ;
|
||||
+ . = ALIGN(32 / 8);
|
||||
+ . = ALIGN(32 / 8);
|
||||
+ _end = .;
|
||||
PROVIDE (end = .);
|
||||
+ . = DATA_SEGMENT_END (.);
|
||||
/* Stabs debugging sections. */
|
||||
- .stab 0 : { *(.stab) }
|
||||
- .stabstr 0 : { *(.stabstr) }
|
||||
- .stab.excl 0 : { *(.stab.excl) }
|
||||
- .stab.exclstr 0 : { *(.stab.exclstr) }
|
||||
- .stab.index 0 : { *(.stab.index) }
|
||||
+ .stab 0 : { *(.stab) }
|
||||
+ .stabstr 0 : { *(.stabstr) }
|
||||
+ .stab.excl 0 : { *(.stab.excl) }
|
||||
+ .stab.exclstr 0 : { *(.stab.exclstr) }
|
||||
+ .stab.index 0 : { *(.stab.index) }
|
||||
.stab.indexstr 0 : { *(.stab.indexstr) }
|
||||
- .comment 0 : { *(.comment) }
|
||||
+ .comment 0 : { *(.comment) }
|
||||
/* DWARF debug sections.
|
||||
Symbols in the DWARF debugging sections are relative to the beginning
|
||||
of the section so we begin them at 0. */
|
||||
@@ -124,7 +208,7 @@
|
||||
.debug_aranges 0 : { *(.debug_aranges) }
|
||||
.debug_pubnames 0 : { *(.debug_pubnames) }
|
||||
/* DWARF 2 */
|
||||
- .debug_info 0 : { *(.debug_info) }
|
||||
+ .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) }
|
||||
.debug_abbrev 0 : { *(.debug_abbrev) }
|
||||
.debug_line 0 : { *(.debug_line) }
|
||||
.debug_frame 0 : { *(.debug_frame) }
|
||||
@@ -136,5 +220,6 @@
|
||||
.debug_funcnames 0 : { *(.debug_funcnames) }
|
||||
.debug_typenames 0 : { *(.debug_typenames) }
|
||||
.debug_varnames 0 : { *(.debug_varnames) }
|
||||
- /* These must appear regardless of . */
|
||||
+ /DISCARD/ : { *(.fixup) }
|
||||
+ /DISCARD/ : { *(.note.GNU-stack) }
|
||||
}
|
||||
|
@ -1,17 +1,8 @@
|
||||
--- qemu-binfmt-conf.sh
|
||||
+++ qemu-binfmt-conf.sh
|
||||
@@ -2,38 +2,46 @@
|
||||
# enable automatic i386/ARM/SPARC/PPC program execution by the kernel
|
||||
|
||||
# load the binfmt_misc module
|
||||
-/sbin/modprobe binfmt_misc
|
||||
+
|
||||
+if test ! -e /proc/sys/fs/binfmt_misc/register
|
||||
+then
|
||||
+ /sbin/modprobe binfmt_misc
|
||||
+ mount -t binfmt_misc none /proc/sys/fs/binfmt_misc
|
||||
+fi
|
||||
|
||||
Index: qemu-0.9.0/qemu-binfmt-conf.sh
|
||||
===================================================================
|
||||
--- qemu-0.9.0.orig/qemu-binfmt-conf.sh
|
||||
+++ qemu-0.9.0/qemu-binfmt-conf.sh
|
||||
@@ -12,7 +12,7 @@ fi
|
||||
# probe cpu type
|
||||
cpu=`uname -m`
|
||||
case "$cpu" in
|
||||
@ -19,6 +10,8 @@
|
||||
+ i386|i486|i586|i686|i86pc|BePC|x86_64)
|
||||
cpu="i386"
|
||||
;;
|
||||
m68k)
|
||||
@@ -24,32 +24,34 @@ case "$cpu" in
|
||||
"Power Macintosh"|ppc|ppc64)
|
||||
cpu="ppc"
|
||||
;;
|
||||
@ -28,7 +21,6 @@
|
||||
;;
|
||||
+ sparc*)
|
||||
+ cpu="sparc"
|
||||
+ ;;
|
||||
esac
|
||||
|
||||
# register the interpreter for each cpu except for the native one
|
||||
@ -51,8 +43,14 @@
|
||||
if [ $cpu != "ppc" ] ; then
|
||||
- echo ':ppc:M::\x7fELF\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x14:\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff:/usr/local/bin/qemu-ppc:' > /proc/sys/fs/binfmt_misc/register
|
||||
+ echo ':ppc:M::\x7fELF\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x14:\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff:/usr/bin/qemu-ppc:' > /proc/sys/fs/binfmt_misc/register
|
||||
fi
|
||||
if [ $cpu != "m68k" ] ; then
|
||||
echo 'Please check cpu value and header information for m68k!'
|
||||
- echo ':m68k:M::\x7fELF\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00\x08:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff:/usr/local/bin/qemu-m68k:' > /proc/sys/fs/binfmt_misc/register
|
||||
+ echo ':m68k:M::\x7fELF\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00\x08:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff:/usr/bin/qemu-m68k:' > /proc/sys/fs/binfmt_misc/register
|
||||
fi
|
||||
if [ $cpu != "mips" ] ; then
|
||||
# FIXME: We could use the other endianness on a MIPS host.
|
||||
- echo ':mips:M::\x7fELF\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x08:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff:/usr/local/bin/qemu-mips:' > /proc/sys/fs/binfmt_misc/register
|
||||
- echo ':mipsel:M::\x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x08\x00:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff:/usr/local/bin/qemu-mipsel:' > /proc/sys/fs/binfmt_misc/register
|
||||
+ echo ':mips:M::\x7fELF\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x08:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff:/usr/bin/qemu-mips:' > /proc/sys/fs/binfmt_misc/register
|
||||
|
@ -1,117 +0,0 @@
|
||||
--- kqemu/kqemu.h
|
||||
+++ kqemu/kqemu.h
|
||||
@@ -0,0 +1,114 @@
|
||||
+/*
|
||||
+ * KQEMU header
|
||||
+ *
|
||||
+ * Copyright (c) 2004-2005 Fabrice Bellard
|
||||
+ *
|
||||
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
+ * of this software and associated documentation files (the "Software"), to deal
|
||||
+ * in the Software without restriction, including without limitation the rights
|
||||
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
+ * copies of the Software, and to permit persons to whom the Software is
|
||||
+ * furnished to do so, subject to the following conditions:
|
||||
+ *
|
||||
+ * The above copyright notice and this permission notice shall be included in
|
||||
+ * all copies or substantial portions of the Software.
|
||||
+ *
|
||||
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
+ * THE SOFTWARE.
|
||||
+ */
|
||||
+#ifndef KQEMU_H
|
||||
+#define KQEMU_H
|
||||
+
|
||||
+#define KQEMU_VERSION 0x010200
|
||||
+
|
||||
+struct kqemu_segment_cache {
|
||||
+ uint32_t selector;
|
||||
+ unsigned long base;
|
||||
+ uint32_t limit;
|
||||
+ uint32_t flags;
|
||||
+};
|
||||
+
|
||||
+struct kqemu_cpu_state {
|
||||
+#ifdef __x86_64__
|
||||
+ unsigned long regs[16];
|
||||
+#else
|
||||
+ unsigned long regs[8];
|
||||
+#endif
|
||||
+ unsigned long eip;
|
||||
+ unsigned long eflags;
|
||||
+
|
||||
+ uint32_t dummy0, dummy1, dumm2, dummy3, dummy4;
|
||||
+
|
||||
+ struct kqemu_segment_cache segs[6]; /* selector values */
|
||||
+ struct kqemu_segment_cache ldt;
|
||||
+ struct kqemu_segment_cache tr;
|
||||
+ struct kqemu_segment_cache gdt; /* only base and limit are used */
|
||||
+ struct kqemu_segment_cache idt; /* only base and limit are used */
|
||||
+
|
||||
+ unsigned long cr0;
|
||||
+ unsigned long dummy5;
|
||||
+ unsigned long cr2;
|
||||
+ unsigned long cr3;
|
||||
+ unsigned long cr4;
|
||||
+ uint32_t a20_mask;
|
||||
+
|
||||
+ uint64_t efer __attribute__((aligned(8)));
|
||||
+
|
||||
+ unsigned long dr0;
|
||||
+ unsigned long dr1;
|
||||
+ unsigned long dr2;
|
||||
+ unsigned long dr3;
|
||||
+ unsigned long dr6;
|
||||
+ unsigned long dr7;
|
||||
+
|
||||
+ uint8_t cpl;
|
||||
+ uint8_t user_only;
|
||||
+
|
||||
+ uint32_t error_code; /* error_code when exiting with an exception */
|
||||
+ unsigned long next_eip; /* next eip value when exiting with an interrupt */
|
||||
+ unsigned int nb_pages_to_flush; /* number of pages to flush,
|
||||
+ KQEMU_FLUSH_ALL means full flush */
|
||||
+#define KQEMU_MAX_PAGES_TO_FLUSH 512
|
||||
+#define KQEMU_FLUSH_ALL (KQEMU_MAX_PAGES_TO_FLUSH + 1)
|
||||
+
|
||||
+ long retval;
|
||||
+
|
||||
+ /* number of ram_dirty entries to update */
|
||||
+ unsigned int nb_ram_pages_to_update;
|
||||
+#define KQEMU_MAX_RAM_PAGES_TO_UPDATE 512
|
||||
+#define KQEMU_RAM_PAGES_UPDATE_ALL (KQEMU_MAX_RAM_PAGES_TO_UPDATE + 1)
|
||||
+};
|
||||
+
|
||||
+struct kqemu_init {
|
||||
+ uint8_t *ram_base; /* must be page aligned */
|
||||
+ unsigned long ram_size; /* must be multiple of 4 KB */
|
||||
+ uint8_t *ram_dirty; /* must be page aligned */
|
||||
+ uint32_t **phys_to_ram_map; /* must be page aligned */
|
||||
+ unsigned long *pages_to_flush; /* must be page aligned */
|
||||
+ unsigned long *ram_pages_to_update; /* must be page aligned */
|
||||
+};
|
||||
+
|
||||
+#define KQEMU_RET_ABORT (-1)
|
||||
+#define KQEMU_RET_EXCEPTION 0x0000 /* 8 low order bit are the exception */
|
||||
+#define KQEMU_RET_INT 0x0100 /* 8 low order bit are the interrupt */
|
||||
+#define KQEMU_RET_SOFTMMU 0x0200 /* emulation needed (I/O or
|
||||
+ unsupported INSN) */
|
||||
+#define KQEMU_RET_INTR 0x0201 /* interrupted by a signal */
|
||||
+#define KQEMU_RET_SYSCALL 0x0300 /* syscall insn */
|
||||
+
|
||||
+#ifdef _WIN32
|
||||
+#define KQEMU_EXEC CTL_CODE(FILE_DEVICE_UNKNOWN, 1, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
|
||||
+#define KQEMU_INIT CTL_CODE(FILE_DEVICE_UNKNOWN, 2, METHOD_BUFFERED, FILE_WRITE_ACCESS)
|
||||
+#define KQEMU_GET_VERSION CTL_CODE(FILE_DEVICE_UNKNOWN, 3, METHOD_BUFFERED, FILE_READ_ACCESS)
|
||||
+#else
|
||||
+#define KQEMU_EXEC _IOWR('q', 1, struct kqemu_cpu_state)
|
||||
+#define KQEMU_INIT _IOW('q', 2, struct kqemu_init)
|
||||
+#define KQEMU_GET_VERSION _IOR('q', 3, int)
|
||||
+#endif
|
||||
+
|
||||
+#endif /* KQEMU_H */
|
901
qemu-0.8.3-gcc4.patch
Normal file
901
qemu-0.8.3-gcc4.patch
Normal file
@ -0,0 +1,901 @@
|
||||
2007-02-17 Gwenole Beauchesne <gbeauchesne@mandriva.com>
|
||||
|
||||
* target-i386/op.c (op_imull_EAX_T0, op_imulw_T0_T1,
|
||||
op_imull_T0_T1): Add FORCE_RET() since CC_SRC involves a
|
||||
compare-branch that may be optimized into a beqlr on ppc.
|
||||
|
||||
2005-06-02 Gwenole Beauchesne <gbeauchesne@mandriva.com>
|
||||
|
||||
* dyngen.c (trace_i386_insn): Fix push/imul case with 8-bit
|
||||
immediate.
|
||||
|
||||
2005-05-11 Paul Brook <paul@codesourcery.com>
|
||||
|
||||
* gcc4 host support.
|
||||
|
||||
--- qemu-0.8.3/dyngen-exec.h.gcc4 2006-12-23 01:49:32.000000000 +0100
|
||||
+++ qemu-0.8.3/dyngen-exec.h 2007-01-30 18:14:25.000000000 +0100
|
||||
@@ -188,7 +188,12 @@ extern int printf(const char *, ...);
|
||||
#endif
|
||||
|
||||
/* force GCC to generate only one epilog at the end of the function */
|
||||
+#if defined(__i386__) || defined(__x86_64__)
|
||||
+/* Also add 4 bytes of padding so that we can replace the ret with a jmp. */
|
||||
+#define FORCE_RET() __asm__ __volatile__("nop;nop;nop;nop" : : : "memory");
|
||||
+#else
|
||||
#define FORCE_RET() __asm__ __volatile__("" : : : "memory");
|
||||
+#endif
|
||||
|
||||
#ifndef OPPROTO
|
||||
#define OPPROTO
|
||||
@@ -238,9 +243,16 @@ extern int __op_jmp0, __op_jmp1, __op_jm
|
||||
#endif
|
||||
|
||||
#if defined(__i386__)
|
||||
-#define EXIT_TB() asm volatile ("ret")
|
||||
-#define GOTO_LABEL_PARAM(n) asm volatile ("jmp " ASM_NAME(__op_gen_label) #n)
|
||||
+/* Dyngen will replace hlt instructions with a ret instruction. Inserting a
|
||||
+ ret directly would confuse dyngen. */
|
||||
+#define EXIT_TB() asm volatile ("hlt")
|
||||
+/* Dyngen will replace cli with 0x9e (jmp).
|
||||
+ We generate the offset manually. */
|
||||
+#define GOTO_LABEL_PARAM(n) \
|
||||
+ asm volatile ("cli;.long " ASM_NAME(__op_gen_label) #n " - 1f;1:")
|
||||
#elif defined(__x86_64__)
|
||||
-#define EXIT_TB() asm volatile ("ret")
|
||||
-#define GOTO_LABEL_PARAM(n) asm volatile ("jmp " ASM_NAME(__op_gen_label) #n)
|
||||
+/* The same as i386. */
|
||||
+#define EXIT_TB() asm volatile ("hlt")
|
||||
+#define GOTO_LABEL_PARAM(n) \
|
||||
+ asm volatile ("cli;.long " ASM_NAME(__op_gen_label) #n " - 1f;1:")
|
||||
#elif defined(__powerpc__)
|
||||
--- qemu-0.8.3/dyngen.c.gcc4 2006-12-21 17:49:27.000000000 +0100
|
||||
+++ qemu-0.8.3/dyngen.c 2007-01-30 18:11:21.000000000 +0100
|
||||
@@ -32,6 +32,8 @@
|
||||
|
||||
#include "config-host.h"
|
||||
|
||||
+//#define DEBUG_OP
|
||||
+
|
||||
/* NOTE: we test CONFIG_WIN32 instead of _WIN32 to enabled cross
|
||||
compilation */
|
||||
#if defined(CONFIG_WIN32)
|
||||
@@ -1414,6 +1416,644 @@ int arm_emit_ldr_info(const char *name,
|
||||
#endif
|
||||
|
||||
|
||||
+#if defined(HOST_I386) || defined(HOST_X86_64)
|
||||
+
|
||||
+/* This byte is the first byte of an instruction. */
|
||||
+#define FLAG_INSN (1 << 0)
|
||||
+/* This byte has been processed as part of an instruction. */
|
||||
+#define FLAG_SCANNED (1 << 1)
|
||||
+/* This instruction is a return instruction. Gcc cometimes generates prefix
|
||||
+ bytes, so may be more than one byte long. */
|
||||
+#define FLAG_RET (1 << 2)
|
||||
+/* This is either the target of a jump, or the preceeding instruction uses
|
||||
+ a pc-relative offset. */
|
||||
+#define FLAG_TARGET (1 << 3)
|
||||
+/* This is a magic instruction that needs fixing up. */
|
||||
+#define FLAG_EXIT (1 << 4)
|
||||
+#define MAX_EXITS 5
|
||||
+
|
||||
+static void
|
||||
+bad_opcode(const char *name, uint32_t op)
|
||||
+{
|
||||
+ error("Unsupported opcode %0*x in %s", (op > 0xff) ? 4 : 2, op, name);
|
||||
+}
|
||||
+
|
||||
+/* Mark len bytes as scanned, Returns insn_size + len. Reports an error
|
||||
+ if these bytes have already been scanned. */
|
||||
+static int
|
||||
+eat_bytes(const char *name, char *flags, int insn, int insn_size, int len)
|
||||
+{
|
||||
+ while (len > 0) {
|
||||
+ /* This should never occur in sane code. */
|
||||
+ if (flags[insn + insn_size] & FLAG_SCANNED)
|
||||
+ error ("Overlapping instructions in %s", name);
|
||||
+ flags[insn + insn_size] |= FLAG_SCANNED;
|
||||
+ insn_size++;
|
||||
+ len--;
|
||||
+ }
|
||||
+ return insn_size;
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+trace_i386_insn (const char *name, uint8_t *start_p, char *flags, int insn,
|
||||
+ int len)
|
||||
+{
|
||||
+ uint8_t *ptr;
|
||||
+ uint8_t op;
|
||||
+ int modrm;
|
||||
+ int is_prefix;
|
||||
+ int op_size;
|
||||
+ int addr_size;
|
||||
+ int insn_size;
|
||||
+ int is_ret;
|
||||
+ int is_condjmp;
|
||||
+ int is_jmp;
|
||||
+ int is_exit;
|
||||
+ int is_pcrel;
|
||||
+ int immed;
|
||||
+ int seen_rexw;
|
||||
+ int32_t disp;
|
||||
+
|
||||
+ ptr = start_p + insn;
|
||||
+ /* nonzero if this insn has a ModR/M byte. */
|
||||
+ modrm = 1;
|
||||
+ /* The size of the immediate value in this instruction. */
|
||||
+ immed = 0;
|
||||
+ /* The operand size. */
|
||||
+ op_size = 4;
|
||||
+ /* The address size */
|
||||
+ addr_size = 4;
|
||||
+ /* The total length of this instruction. */
|
||||
+ insn_size = 0;
|
||||
+ is_prefix = 1;
|
||||
+ is_ret = 0;
|
||||
+ is_condjmp = 0;
|
||||
+ is_jmp = 0;
|
||||
+ is_exit = 0;
|
||||
+ seen_rexw = 0;
|
||||
+ is_pcrel = 0;
|
||||
+
|
||||
+ while (is_prefix) {
|
||||
+ op = ptr[insn_size];
|
||||
+ insn_size = eat_bytes(name, flags, insn, insn_size, 1);
|
||||
+ is_prefix = 0;
|
||||
+ switch (op >> 4) {
|
||||
+ case 0:
|
||||
+ case 1:
|
||||
+ case 2:
|
||||
+ case 3:
|
||||
+ if (op == 0x0f) {
|
||||
+ /* two-byte opcode. */
|
||||
+ op = ptr[insn_size];
|
||||
+ insn_size = eat_bytes(name, flags, insn, insn_size, 1);
|
||||
+ switch (op >> 4) {
|
||||
+ case 0:
|
||||
+ if ((op & 0xf) > 3)
|
||||
+ modrm = 0;
|
||||
+ break;
|
||||
+ case 1: /* vector move or prefetch */
|
||||
+ case 2: /* various moves and vector compares. */
|
||||
+ case 4: /* cmov */
|
||||
+ case 5: /* vector instructions */
|
||||
+ case 6:
|
||||
+ case 13:
|
||||
+ case 14:
|
||||
+ case 15:
|
||||
+ break;
|
||||
+ case 7: /* mmx */
|
||||
+ if (op & 0x77) /* emms */
|
||||
+ modrm = 0;
|
||||
+ break;
|
||||
+ case 3: /* wrmsr, rdtsc, rdmsr, rdpmc, sysenter, sysexit */
|
||||
+ modrm = 0;
|
||||
+ break;
|
||||
+ case 8: /* long conditional jump */
|
||||
+ is_condjmp = 1;
|
||||
+ immed = op_size;
|
||||
+ modrm = 0;
|
||||
+ break;
|
||||
+ case 9: /* setcc */
|
||||
+ break;
|
||||
+ case 10:
|
||||
+ switch (op & 0x7) {
|
||||
+ case 0: /* push fs/gs */
|
||||
+ case 1: /* pop fs/gs */
|
||||
+ case 2: /* cpuid/rsm */
|
||||
+ modrm = 0;
|
||||
+ break;
|
||||
+ case 4: /* shld/shrd immediate */
|
||||
+ immed = 1;
|
||||
+ break;
|
||||
+ default: /* Normal instructions with a ModR/M byte. */
|
||||
+ break;
|
||||
+ }
|
||||
+ break;
|
||||
+ case 11:
|
||||
+ switch (op & 0xf) {
|
||||
+ case 10: /* bt, bts, btr, btc */
|
||||
+ immed = 1;
|
||||
+ break;
|
||||
+ default:
|
||||
+ /* cmpxchg, lss, btr, lfs, lgs, movzx, btc, bsf, bsr
|
||||
+ undefined, and movsx */
|
||||
+ break;
|
||||
+ }
|
||||
+ break;
|
||||
+ case 12:
|
||||
+ if (op & 8) {
|
||||
+ /* bswap */
|
||||
+ modrm = 0;
|
||||
+ } else {
|
||||
+ switch (op & 0x7) {
|
||||
+ case 2:
|
||||
+ case 4:
|
||||
+ case 5:
|
||||
+ case 6:
|
||||
+ immed = 1;
|
||||
+ break;
|
||||
+ default:
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+ break;
|
||||
+ }
|
||||
+ } else if ((op & 0x07) <= 0x3) {
|
||||
+ /* General arithmentic ax. */
|
||||
+ } else if ((op & 0x07) <= 0x5) {
|
||||
+ /* General arithmetic ax, immediate. */
|
||||
+ if (op & 0x01)
|
||||
+ immed = op_size;
|
||||
+ else
|
||||
+ immed = 1;
|
||||
+ modrm = 0;
|
||||
+ } else if ((op & 0x23) == 0x22) {
|
||||
+ /* Segment prefix. */
|
||||
+ is_prefix = 1;
|
||||
+ } else {
|
||||
+ /* Segment register push/pop or DAA/AAA/DAS/AAS. */
|
||||
+ modrm = 0;
|
||||
+ }
|
||||
+ break;
|
||||
+
|
||||
+#if defined(HOST_X86_64)
|
||||
+ case 4: /* rex prefix. */
|
||||
+ is_prefix = 1;
|
||||
+ /* The address/operand size is actually 64-bit, but the immediate
|
||||
+ values in the instruction are still 32-bit. */
|
||||
+ op_size = 4;
|
||||
+ addr_size = 4;
|
||||
+ if (op & 8)
|
||||
+ seen_rexw = 1;
|
||||
+ break;
|
||||
+#else
|
||||
+ case 4: /* inc/dec register. */
|
||||
+#endif
|
||||
+ case 5: /* push/pop general register. */
|
||||
+ modrm = 0;
|
||||
+ break;
|
||||
+
|
||||
+ case 6:
|
||||
+ switch (op & 0x0f) {
|
||||
+ case 0: /* pusha */
|
||||
+ case 1: /* popa */
|
||||
+ modrm = 0;
|
||||
+ break;
|
||||
+ case 2: /* bound */
|
||||
+ case 3: /* arpl */
|
||||
+ break;
|
||||
+ case 4: /* FS */
|
||||
+ case 5: /* GS */
|
||||
+ is_prefix = 1;
|
||||
+ break;
|
||||
+ case 6: /* opcode size prefix. */
|
||||
+ op_size = 2;
|
||||
+ is_prefix = 1;
|
||||
+ break;
|
||||
+ case 7: /* Address size prefix. */
|
||||
+ addr_size = 2;
|
||||
+ is_prefix = 1;
|
||||
+ break;
|
||||
+ case 8: /* push immediate */
|
||||
+ immed = op_size;
|
||||
+ modrm = 0;
|
||||
+ break;
|
||||
+ case 10: /* push 8-bit immediate */
|
||||
+ immed = 1;
|
||||
+ modrm = 0;
|
||||
+ break;
|
||||
+ case 9: /* imul immediate */
|
||||
+ immed = op_size;
|
||||
+ break;
|
||||
+ case 11: /* imul 8-bit immediate */
|
||||
+ immed = 1;
|
||||
+ break;
|
||||
+ case 12: /* insb */
|
||||
+ case 13: /* insw */
|
||||
+ case 14: /* outsb */
|
||||
+ case 15: /* outsw */
|
||||
+ modrm = 0;
|
||||
+ break;
|
||||
+ }
|
||||
+ break;
|
||||
+
|
||||
+ case 7: /* Short conditional jump. */
|
||||
+ is_condjmp = 1;
|
||||
+ immed = 1;
|
||||
+ modrm = 0;
|
||||
+ break;
|
||||
+
|
||||
+ case 8:
|
||||
+ if ((op & 0xf) <= 3) {
|
||||
+ /* arithmetic immediate. */
|
||||
+ if ((op & 3) == 1)
|
||||
+ immed = op_size;
|
||||
+ else
|
||||
+ immed = 1;
|
||||
+ }
|
||||
+ /* else test, xchg, mov, lea or pop general. */
|
||||
+ break;
|
||||
+
|
||||
+ case 9:
|
||||
+ /* Various single-byte opcodes with no modrm byte. */
|
||||
+ modrm = 0;
|
||||
+ if (op == 10) {
|
||||
+ /* Call */
|
||||
+ immed = 4;
|
||||
+ }
|
||||
+ break;
|
||||
+
|
||||
+ case 10:
|
||||
+ switch ((op & 0xe) >> 1) {
|
||||
+ case 0: /* mov absoliute immediate. */
|
||||
+ case 1:
|
||||
+ if (seen_rexw)
|
||||
+ immed = 8;
|
||||
+ else
|
||||
+ immed = addr_size;
|
||||
+ break;
|
||||
+ case 4: /* test immediate. */
|
||||
+ if (op & 1)
|
||||
+ immed = op_size;
|
||||
+ else
|
||||
+ immed = 1;
|
||||
+ break;
|
||||
+ default: /* Various string ops. */
|
||||
+ break;
|
||||
+ }
|
||||
+ modrm = 0;
|
||||
+ break;
|
||||
+
|
||||
+ case 11: /* move immediate to register */
|
||||
+ if (op & 8) {
|
||||
+ if (seen_rexw)
|
||||
+ immed = 8;
|
||||
+ else
|
||||
+ immed = op_size;
|
||||
+ } else {
|
||||
+ immed = 1;
|
||||
+ }
|
||||
+ modrm = 0;
|
||||
+ break;
|
||||
+
|
||||
+ case 12:
|
||||
+ switch (op & 0xf) {
|
||||
+ case 0: /* shift immediate */
|
||||
+ case 1:
|
||||
+ immed = 1;
|
||||
+ break;
|
||||
+ case 2: /* ret immediate */
|
||||
+ immed = 2;
|
||||
+ modrm = 0;
|
||||
+ bad_opcode(name, op);
|
||||
+ break;
|
||||
+ case 3: /* ret */
|
||||
+ modrm = 0;
|
||||
+ is_ret = 1;
|
||||
+ case 4: /* les */
|
||||
+ case 5: /* lds */
|
||||
+ break;
|
||||
+ case 6: /* mov immediate byte */
|
||||
+ immed = 1;
|
||||
+ break;
|
||||
+ case 7: /* mov immediate */
|
||||
+ immed = op_size;
|
||||
+ break;
|
||||
+ case 8: /* enter */
|
||||
+ /* TODO: Is this right? */
|
||||
+ immed = 3;
|
||||
+ modrm = 0;
|
||||
+ break;
|
||||
+ case 10: /* retf immediate */
|
||||
+ immed = 2;
|
||||
+ modrm = 0;
|
||||
+ bad_opcode(name, op);
|
||||
+ break;
|
||||
+ case 13: /* int */
|
||||
+ immed = 1;
|
||||
+ modrm = 0;
|
||||
+ break;
|
||||
+ case 11: /* retf */
|
||||
+ case 15: /* iret */
|
||||
+ modrm = 0;
|
||||
+ bad_opcode(name, op);
|
||||
+ break;
|
||||
+ default: /* leave, int3 or into */
|
||||
+ modrm = 0;
|
||||
+ break;
|
||||
+ }
|
||||
+ break;
|
||||
+
|
||||
+ case 13:
|
||||
+ if ((op & 0xf) >= 8) {
|
||||
+ /* Coprocessor escape. For our purposes this is just a normal
|
||||
+ instruction with a ModR/M byte. */
|
||||
+ } else if ((op & 0xf) >= 4) {
|
||||
+ /* AAM, AAD or XLAT */
|
||||
+ modrm = 0;
|
||||
+ }
|
||||
+ /* else shift instruction */
|
||||
+ break;
|
||||
+
|
||||
+ case 14:
|
||||
+ switch ((op & 0xc) >> 2) {
|
||||
+ case 0: /* loop or jcxz */
|
||||
+ is_condjmp = 1;
|
||||
+ immed = 1;
|
||||
+ break;
|
||||
+ case 1: /* in/out immed */
|
||||
+ immed = 1;
|
||||
+ break;
|
||||
+ case 2: /* call or jmp */
|
||||
+ switch (op & 3) {
|
||||
+ case 0: /* call */
|
||||
+ immed = op_size;
|
||||
+ break;
|
||||
+ case 1: /* long jump */
|
||||
+ immed = 4;
|
||||
+ is_jmp = 1;
|
||||
+ break;
|
||||
+ case 2: /* far jmp */
|
||||
+ bad_opcode(name, op);
|
||||
+ break;
|
||||
+ case 3: /* short jmp */
|
||||
+ immed = 1;
|
||||
+ is_jmp = 1;
|
||||
+ break;
|
||||
+ }
|
||||
+ break;
|
||||
+ case 3: /* in/out register */
|
||||
+ break;
|
||||
+ }
|
||||
+ modrm = 0;
|
||||
+ break;
|
||||
+
|
||||
+ case 15:
|
||||
+ switch ((op & 0xe) >> 1) {
|
||||
+ case 0:
|
||||
+ case 1:
|
||||
+ is_prefix = 1;
|
||||
+ break;
|
||||
+ case 2:
|
||||
+ case 4:
|
||||
+ case 5:
|
||||
+ case 6:
|
||||
+ modrm = 0;
|
||||
+ /* Some privileged insns are used as markers. */
|
||||
+ switch (op) {
|
||||
+ case 0xf4: /* hlt: Exit translation block. */
|
||||
+ is_exit = 1;
|
||||
+ break;
|
||||
+ case 0xfa: /* cli: Jump to label. */
|
||||
+ is_exit = 1;
|
||||
+ immed = 4;
|
||||
+ break;
|
||||
+ case 0xfb: /* sti: TB patch jump. */
|
||||
+ /* Mark the insn for patching, but continue sscanning. */
|
||||
+ flags[insn] |= FLAG_EXIT;
|
||||
+ immed = 4;
|
||||
+ break;
|
||||
+ }
|
||||
+ break;
|
||||
+ case 3: /* unary grp3 */
|
||||
+ if ((ptr[insn_size] & 0x38) == 0) {
|
||||
+ if (op == 0xf7)
|
||||
+ immed = op_size;
|
||||
+ else
|
||||
+ immed = 1; /* test immediate */
|
||||
+ }
|
||||
+ break;
|
||||
+ case 7: /* inc/dec grp4/5 */
|
||||
+ /* TODO: This includes indirect jumps. We should fail if we
|
||||
+ encounter one of these. */
|
||||
+ break;
|
||||
+ }
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (modrm) {
|
||||
+ if (addr_size != 4)
|
||||
+ error("16-bit addressing mode used in %s", name);
|
||||
+
|
||||
+ disp = 0;
|
||||
+ modrm = ptr[insn_size];
|
||||
+ insn_size = eat_bytes(name, flags, insn, insn_size, 1);
|
||||
+ modrm &= 0xc7;
|
||||
+ switch ((modrm & 0xc0) >> 6) {
|
||||
+ case 0:
|
||||
+ if (modrm == 5)
|
||||
+ disp = 4;
|
||||
+ break;
|
||||
+ case 1:
|
||||
+ disp = 1;
|
||||
+ break;
|
||||
+ case 2:
|
||||
+ disp = 4;
|
||||
+ break;
|
||||
+ }
|
||||
+ if ((modrm & 0xc0) != 0xc0 && (modrm & 0x7) == 4) {
|
||||
+ /* SIB byte */
|
||||
+ if (modrm == 4 && (ptr[insn_size] & 0x7) == 5) {
|
||||
+ disp = 4;
|
||||
+ is_pcrel = 1;
|
||||
+ }
|
||||
+ insn_size = eat_bytes(name, flags, insn, insn_size, 1);
|
||||
+ }
|
||||
+ insn_size = eat_bytes(name, flags, insn, insn_size, disp);
|
||||
+ }
|
||||
+ insn_size = eat_bytes(name, flags, insn, insn_size, immed);
|
||||
+ if (is_condjmp || is_jmp) {
|
||||
+ if (immed == 1) {
|
||||
+ disp = (int8_t)*(ptr + insn_size - 1);
|
||||
+ } else {
|
||||
+ disp = (((int32_t)*(ptr + insn_size - 1)) << 24)
|
||||
+ | (((int32_t)*(ptr + insn_size - 2)) << 16)
|
||||
+ | (((int32_t)*(ptr + insn_size - 3)) << 8)
|
||||
+ | *(ptr + insn_size - 4);
|
||||
+ }
|
||||
+ disp += insn_size;
|
||||
+ /* Jumps to external symbols point to the address of the offset
|
||||
+ before relocation. */
|
||||
+ /* ??? These are probably a tailcall. We could fix them up by
|
||||
+ replacing them with jmp to EOB + call, but it's easier to just
|
||||
+ prevent the compiler generating them. */
|
||||
+ if (disp == 1)
|
||||
+ error("Unconditional jump (sibcall?) in %s", name);
|
||||
+ disp += insn;
|
||||
+ if (disp < 0 || disp > len)
|
||||
+ error("Jump outside instruction in %s", name);
|
||||
+
|
||||
+ if ((flags[disp] & (FLAG_INSN | FLAG_SCANNED)) == FLAG_SCANNED)
|
||||
+ error("Overlapping instructions in %s", name);
|
||||
+
|
||||
+ flags[disp] |= (FLAG_INSN | FLAG_TARGET);
|
||||
+ is_pcrel = 1;
|
||||
+ }
|
||||
+ if (is_pcrel) {
|
||||
+ /* Mark the following insn as a jump target. This will stop
|
||||
+ this instruction being moved. */
|
||||
+ flags[insn + insn_size] |= FLAG_TARGET;
|
||||
+ }
|
||||
+ if (is_ret)
|
||||
+ flags[insn] |= FLAG_RET;
|
||||
+
|
||||
+ if (is_exit)
|
||||
+ flags[insn] |= FLAG_EXIT;
|
||||
+
|
||||
+ if (!(is_jmp || is_ret || is_exit))
|
||||
+ flags[insn + insn_size] |= FLAG_INSN;
|
||||
+}
|
||||
+
|
||||
+/* Scan a function body. Returns the position of the return sequence.
|
||||
+ Sets *patch_bytes to the number of bytes that need to be copied from that
|
||||
+ location. If no patching is required (ie. the return is the last insn)
|
||||
+ *patch_bytes will be set to -1. *plen is the number of code bytes to copy.
|
||||
+ */
|
||||
+static int trace_i386_op(const char * name, uint8_t *start_p, int *plen,
|
||||
+ int *patch_bytes, int *exit_addrs)
|
||||
+{
|
||||
+ char *flags;
|
||||
+ int more;
|
||||
+ int insn;
|
||||
+ int retpos;
|
||||
+ int bytes;
|
||||
+ int num_exits;
|
||||
+ int len;
|
||||
+ int last_insn;
|
||||
+
|
||||
+ len = *plen;
|
||||
+ flags = malloc(len + 1);
|
||||
+ memset(flags, 0, len + 1);
|
||||
+ flags[0] |= FLAG_INSN;
|
||||
+ more = 1;
|
||||
+ while (more) {
|
||||
+ more = 0;
|
||||
+ for (insn = 0; insn < len; insn++) {
|
||||
+ if ((flags[insn] & (FLAG_INSN | FLAG_SCANNED)) == FLAG_INSN) {
|
||||
+ trace_i386_insn(name, start_p, flags, insn, len);
|
||||
+ more = 1;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ /* Strip any unused code at the end of the function. */
|
||||
+ while (len > 0 && flags[len - 1] == 0)
|
||||
+ len--;
|
||||
+
|
||||
+ retpos = -1;
|
||||
+ num_exits = 0;
|
||||
+ last_insn = 0;
|
||||
+ for (insn = 0; insn < len; insn++) {
|
||||
+ if (flags[insn] & FLAG_RET) {
|
||||
+ /* ??? In theory it should be possible to handle multiple return
|
||||
+ points. In practice it's not worth the effort. */
|
||||
+ if (retpos != -1)
|
||||
+ error("Multiple return instructions in %s", name);
|
||||
+ retpos = insn;
|
||||
+ }
|
||||
+ if (flags[insn] & FLAG_EXIT) {
|
||||
+ if (num_exits == MAX_EXITS)
|
||||
+ error("Too many block exits in %s", name);
|
||||
+ exit_addrs[num_exits] = insn;
|
||||
+ num_exits++;
|
||||
+ }
|
||||
+ if (flags[insn] & FLAG_INSN)
|
||||
+ last_insn = insn;
|
||||
+ }
|
||||
+
|
||||
+ exit_addrs[num_exits] = -1;
|
||||
+ if (retpos == -1) {
|
||||
+ if (num_exits == 0) {
|
||||
+ error ("No return instruction found in %s", name);
|
||||
+ } else {
|
||||
+ retpos = len;
|
||||
+ last_insn = len;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ /* If the return instruction is the last instruction we can just
|
||||
+ remove it. */
|
||||
+ if (retpos == last_insn)
|
||||
+ *patch_bytes = -1;
|
||||
+ else
|
||||
+ *patch_bytes = 0;
|
||||
+
|
||||
+ /* Back up over any nop instructions. */
|
||||
+ while (retpos > 0
|
||||
+ && (flags[retpos] & FLAG_TARGET) == 0
|
||||
+ && (flags[retpos - 1] & FLAG_INSN) != 0
|
||||
+ && start_p[retpos - 1] == 0x90) {
|
||||
+ retpos--;
|
||||
+ }
|
||||
+
|
||||
+ if (*patch_bytes == -1) {
|
||||
+ *plen = retpos;
|
||||
+ free (flags);
|
||||
+ return retpos;
|
||||
+ }
|
||||
+ *plen = len;
|
||||
+
|
||||
+ /* The ret is in the middle of the function. Find four more bytes that
|
||||
+ so the ret can be replaced by a jmp. */
|
||||
+ /* ??? Use a short jump where possible. */
|
||||
+ bytes = 4;
|
||||
+ insn = retpos + 1;
|
||||
+ /* We can clobber everything up to the next jump target. */
|
||||
+ while (insn < len && bytes > 0 && (flags[insn] & FLAG_TARGET) == 0) {
|
||||
+ insn++;
|
||||
+ bytes--;
|
||||
+ }
|
||||
+ if (bytes > 0) {
|
||||
+ /* ???: Strip out nop blocks. */
|
||||
+ /* We can't do the replacement without clobbering anything important.
|
||||
+ Copy preceeding instructions(s) to give us some space. */
|
||||
+ while (retpos > 0) {
|
||||
+ /* If this byte is the target of a jmp we can't move it. */
|
||||
+ if (flags[retpos] & FLAG_TARGET)
|
||||
+ break;
|
||||
+
|
||||
+ (*patch_bytes)++;
|
||||
+ bytes--;
|
||||
+ retpos--;
|
||||
+
|
||||
+ /* Break out of the loop if we have enough space and this is either
|
||||
+ the first byte of an instruction or a pad byte. */
|
||||
+ if ((flags[retpos] & (FLAG_INSN | FLAG_SCANNED)) != FLAG_SCANNED
|
||||
+ && bytes <= 0) {
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (bytes > 0)
|
||||
+ error("Unable to replace ret with jmp in %s\n", name);
|
||||
+
|
||||
+ free(flags);
|
||||
+ return retpos;
|
||||
+}
|
||||
+
|
||||
+#endif
|
||||
+
|
||||
#define MAX_ARGS 3
|
||||
|
||||
/* generate op code */
|
||||
@@ -1427,6 +2067,11 @@ void gen_code(const char *name, host_ulo
|
||||
uint8_t args_present[MAX_ARGS];
|
||||
const char *sym_name, *p;
|
||||
EXE_RELOC *rel;
|
||||
+#if defined(HOST_I386) || defined(HOST_X86_64)
|
||||
+ int patch_bytes;
|
||||
+ int retpos;
|
||||
+ int exit_addrs[MAX_EXITS];
|
||||
+#endif
|
||||
|
||||
/* Compute exact size excluding prologue and epilogue instructions.
|
||||
* Increment start_offset to skip epilogue instructions, then compute
|
||||
@@ -1437,33 +2082,12 @@ void gen_code(const char *name, host_ulo
|
||||
p_end = p_start + size;
|
||||
start_offset = offset;
|
||||
#if defined(HOST_I386) || defined(HOST_X86_64)
|
||||
-#ifdef CONFIG_FORMAT_COFF
|
||||
- {
|
||||
- uint8_t *p;
|
||||
- p = p_end - 1;
|
||||
- if (p == p_start)
|
||||
- error("empty code for %s", name);
|
||||
- while (*p != 0xc3) {
|
||||
- p--;
|
||||
- if (p <= p_start)
|
||||
- error("ret or jmp expected at the end of %s", name);
|
||||
- }
|
||||
- copy_size = p - p_start;
|
||||
- }
|
||||
-#else
|
||||
{
|
||||
int len;
|
||||
len = p_end - p_start;
|
||||
- if (len == 0)
|
||||
- error("empty code for %s", name);
|
||||
- if (p_end[-1] == 0xc3) {
|
||||
- len--;
|
||||
- } else {
|
||||
- error("ret or jmp expected at the end of %s", name);
|
||||
- }
|
||||
+ retpos = trace_i386_op(name, p_start, &len, &patch_bytes, exit_addrs);
|
||||
copy_size = len;
|
||||
}
|
||||
-#endif
|
||||
#elif defined(HOST_PPC)
|
||||
{
|
||||
uint8_t *p;
|
||||
@@ -1675,6 +2299,13 @@ void gen_code(const char *name, host_ulo
|
||||
}
|
||||
|
||||
if (gen_switch == 2) {
|
||||
+#if defined(HOST_I386) || defined(HOST_X86_64)
|
||||
+ if (patch_bytes != -1)
|
||||
+ copy_size += patch_bytes;
|
||||
+#ifdef DEBUG_OP
|
||||
+ copy_size += 2;
|
||||
+#endif
|
||||
+#endif
|
||||
fprintf(outfile, "DEF(%s, %d, %d)\n", name + 3, nb_args, copy_size);
|
||||
} else if (gen_switch == 1) {
|
||||
|
||||
@@ -1879,7 +2510,43 @@ void gen_code(const char *name, host_ulo
|
||||
#error unsupport object format
|
||||
#endif
|
||||
}
|
||||
+ }
|
||||
+ /* Replace the marker instructions with the actual opcodes. */
|
||||
+ for (i = 0; exit_addrs[i] != -1; i++) {
|
||||
+ int op;
|
||||
+ switch (p_start[exit_addrs[i]])
|
||||
+ {
|
||||
+ case 0xf4: op = 0xc3; break; /* hlt -> ret */
|
||||
+ case 0xfa: op = 0xe9; break; /* cli -> jmp */
|
||||
+ case 0xfb: op = 0xe9; break; /* sti -> jmp */
|
||||
+ default: error("Internal error");
|
||||
+ }
|
||||
+ fprintf(outfile,
|
||||
+ " *(uint8_t *)(gen_code_ptr + %d) = 0x%x;\n",
|
||||
+ exit_addrs[i], op);
|
||||
}
|
||||
+ /* Fix up the return instruction. */
|
||||
+ if (patch_bytes != -1) {
|
||||
+ if (patch_bytes) {
|
||||
+ fprintf(outfile, " memcpy(gen_code_ptr + %d,"
|
||||
+ "gen_code_ptr + %d, %d);\n",
|
||||
+ copy_size, retpos, patch_bytes);
|
||||
+ }
|
||||
+ fprintf(outfile,
|
||||
+ " *(uint8_t *)(gen_code_ptr + %d) = 0xe9;\n",
|
||||
+ retpos);
|
||||
+ fprintf(outfile,
|
||||
+ " *(uint32_t *)(gen_code_ptr + %d) = 0x%x;\n",
|
||||
+ retpos + 1, copy_size - (retpos + 5));
|
||||
+
|
||||
+ copy_size += patch_bytes;
|
||||
+ }
|
||||
+#ifdef DEBUG_OP
|
||||
+ fprintf(outfile,
|
||||
+ " *(uint16_t *)(gen_code_ptr + %d) = 0x9090;\n",
|
||||
+ copy_size);
|
||||
+ copy_size += 2;
|
||||
+#endif
|
||||
}
|
||||
#elif defined(HOST_X86_64)
|
||||
{
|
||||
@@ -1913,6 +2580,42 @@ void gen_code(const char *name, host_ulo
|
||||
}
|
||||
}
|
||||
}
|
||||
+ /* Replace the marker instructions with the actual opcodes. */
|
||||
+ for (i = 0; exit_addrs[i] != -1; i++) {
|
||||
+ int op;
|
||||
+ switch (p_start[exit_addrs[i]])
|
||||
+ {
|
||||
+ case 0xf4: op = 0xc3; break; /* hlt -> ret */
|
||||
+ case 0xfa: op = 0xe9; break; /* cli -> jmp */
|
||||
+ case 0xfb: op = 0xe9; break; /* sti -> jmp */
|
||||
+ default: error("Internal error");
|
||||
+ }
|
||||
+ fprintf(outfile,
|
||||
+ " *(uint8_t *)(gen_code_ptr + %d) = 0x%x;\n",
|
||||
+ exit_addrs[i], op);
|
||||
+ }
|
||||
+ /* Fix up the return instruction. */
|
||||
+ if (patch_bytes != -1) {
|
||||
+ if (patch_bytes) {
|
||||
+ fprintf(outfile, " memcpy(gen_code_ptr + %d,"
|
||||
+ "gen_code_ptr + %d, %d);\n",
|
||||
+ copy_size, retpos, patch_bytes);
|
||||
+ }
|
||||
+ fprintf(outfile,
|
||||
+ " *(uint8_t *)(gen_code_ptr + %d) = 0xe9;\n",
|
||||
+ retpos);
|
||||
+ fprintf(outfile,
|
||||
+ " *(uint32_t *)(gen_code_ptr + %d) = 0x%x;\n",
|
||||
+ retpos + 1, copy_size - (retpos + 5));
|
||||
+
|
||||
+ copy_size += patch_bytes;
|
||||
+ }
|
||||
+#ifdef DEBUG_OP
|
||||
+ fprintf(outfile,
|
||||
+ " *(uint16_t *)(gen_code_ptr + %d) = 0x9090;\n",
|
||||
+ copy_size);
|
||||
+ copy_size += 2;
|
||||
+#endif
|
||||
}
|
||||
#elif defined(HOST_PPC)
|
||||
{
|
||||
--- qemu-0.8.3/exec-all.h.gcc4 2006-11-12 21:40:55.000000000 +0100
|
||||
+++ qemu-0.8.3/exec-all.h 2007-01-30 18:11:21.000000000 +0100
|
||||
@@ -326,14 +326,15 @@ do {\
|
||||
|
||||
#elif defined(__i386__) && defined(USE_DIRECT_JUMP)
|
||||
|
||||
-/* we patch the jump instruction directly */
|
||||
+/* we patch the jump instruction directly. Use sti in place of the actual
|
||||
+ jmp instruction so that dyngen can patch in the correct result. */
|
||||
#define GOTO_TB(opname, tbparam, n)\
|
||||
do {\
|
||||
asm volatile (".section .data\n"\
|
||||
ASM_OP_LABEL_NAME(n, opname) ":\n"\
|
||||
".long 1f\n"\
|
||||
ASM_PREVIOUS_SECTION \
|
||||
- "jmp " ASM_NAME(__op_jmp) #n "\n"\
|
||||
+ "sti;.long " ASM_NAME(__op_jmp) #n " - 1f\n"\
|
||||
"1:\n");\
|
||||
} while (0)
|
||||
|
||||
--- qemu-0.8.3/target-i386/op.c~ 2007-02-17 17:12:48.000000000 +0100
|
||||
+++ qemu-0.8.3/target-i386/op.c 2007-02-17 17:48:46.000000000 +0100
|
||||
@@ -303,6 +303,7 @@
|
||||
EDX = (uint32_t)(res >> 32);
|
||||
CC_DST = res;
|
||||
CC_SRC = (res != (int32_t)res);
|
||||
+ FORCE_RET();
|
||||
}
|
||||
|
||||
void OPPROTO op_imulw_T0_T1(void)
|
||||
@@ -312,6 +313,7 @@
|
||||
T0 = res;
|
||||
CC_DST = res;
|
||||
CC_SRC = (res != (int16_t)res);
|
||||
+ FORCE_RET();
|
||||
}
|
||||
|
||||
void OPPROTO op_imull_T0_T1(void)
|
||||
@@ -321,6 +323,7 @@
|
||||
T0 = res;
|
||||
CC_DST = res;
|
||||
CC_SRC = (res != (int32_t)res);
|
||||
+ FORCE_RET();
|
||||
}
|
||||
|
||||
#ifdef TARGET_X86_64
|
@ -1,47 +0,0 @@
|
||||
Index: qemu-0.9.0/linux-user/syscall.c
|
||||
===================================================================
|
||||
--- qemu-0.9.0.orig/linux-user/syscall.c
|
||||
+++ qemu-0.9.0/linux-user/syscall.c
|
||||
@@ -144,6 +144,7 @@ type name (type1 arg1,type2 arg2,type3 a
|
||||
#define __NR_sys_getdents64 __NR_getdents64
|
||||
#define __NR_sys_rt_sigqueueinfo __NR_rt_sigqueueinfo
|
||||
#define __NR_sys_syslog __NR_syslog
|
||||
+#define __NR_sys_fadvise64 __NR_fadvise64
|
||||
|
||||
#if defined(__alpha__) || defined (__ia64__) || defined(__x86_64__)
|
||||
#define __NR__llseek __NR_lseek
|
||||
@@ -164,6 +165,7 @@ _syscall5(int, _llseek, uint, fd, ulon
|
||||
loff_t *, res, uint, wh);
|
||||
_syscall3(int,sys_rt_sigqueueinfo,int,pid,int,sig,siginfo_t *,uinfo)
|
||||
_syscall3(int,sys_syslog,int,type,char*,bufp,int,len)
|
||||
+_syscall4(int,sys_fadvise64,int,fd,loff_t,offset,loff_t,len,int,advice)
|
||||
#ifdef __NR_exit_group
|
||||
_syscall1(int,exit_group,int,error_code)
|
||||
#endif
|
||||
@@ -4151,6 +4153,17 @@ long do_syscall(void *cpu_env, int num,
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
+#ifdef TARGET_NR_fadvise64
|
||||
+ case TARGET_NR_fadvise64:
|
||||
+ ret = get_errno(sys_fadvise64((int)arg1, arg2, arg3, (int)arg4));
|
||||
+ break;
|
||||
+#endif
|
||||
+#ifdef TARGET_NR_fadvise64_64
|
||||
+ case TARGET_NR_fadvise64_64:
|
||||
+ // fadvise64_64 should be just a wrapper for fadvise_64
|
||||
+ ret = get_errno(sys_fadvise64((int)arg1, arg2, arg3, (int)arg4));
|
||||
+ break;
|
||||
+#endif
|
||||
default:
|
||||
unimplemented:
|
||||
gemu_log("qemu: Unsupported syscall: %d\n", num);
|
||||
Index: qemu-0.9.0/linux-user/i386/syscall_nr.h
|
||||
===================================================================
|
||||
--- qemu-0.9.0.orig/linux-user/i386/syscall_nr.h
|
||||
+++ qemu-0.9.0/linux-user/i386/syscall_nr.h
|
||||
@@ -272,3 +272,4 @@
|
||||
#define TARGET_NR_clock_nanosleep (TARGET_NR_timer_create+8)
|
||||
|
||||
#define TARGET_NR_utimes 271
|
||||
+#define TARGET_NR_fadvise64_64 272
|
@ -1,46 +0,0 @@
|
||||
From gbeauchesne@mandriva.com Tue Mar 13 17:01:17 2007
|
||||
Date: Tue, 20 Feb 2007 01:44:37 +0100 (CET)
|
||||
From: Gwenole Beauchesne <gbeauchesne@mandriva.com>
|
||||
Reply-To: qemu-devel@nongnu.org
|
||||
To: qemu-devel@nongnu.org
|
||||
Subject: [Qemu-devel] [PATCH] Fix CPU chaining in linux-user emulation
|
||||
|
||||
Hi,
|
||||
|
||||
This patch fixes chaining of CPU instances. It was simply trashed with the
|
||||
memcpy() thus causing problems in threaded programs (N > 2): an infinite
|
||||
loop in next cpu_init().
|
||||
|
||||
================================================================================
|
||||
--- qemu-0.9.0/cpu-all.h
|
||||
+++ qemu-0.9.0/cpu-all.h
|
||||
@@ -760,6 +760,8 @@
|
||||
|
||||
#endif /* SINGLE_CPU_DEFINES */
|
||||
|
||||
+CPUState *cpu_copy(CPUState *env);
|
||||
+
|
||||
void cpu_dump_state(CPUState *env, FILE *f,
|
||||
int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
|
||||
int flags);
|
||||
--- qemu-0.9.0/exec.c
|
||||
+++ qemu-0.9.0/exec.c
|
||||
@@ -1221,6 +1221,18 @@
|
||||
abort();
|
||||
}
|
||||
|
||||
+CPUState *cpu_copy(CPUState *env)
|
||||
+{
|
||||
+ CPUState *new_env = cpu_init();
|
||||
+ /* preserve chaining and index */
|
||||
+ CPUState *next_cpu = new_env->next_cpu;
|
||||
+ int cpu_index = new_env->cpu_index;
|
||||
+ memcpy(new_env, env, sizeof(CPUState));
|
||||
+ new_env->next_cpu = next_cpu;
|
||||
+ new_env->cpu_index = cpu_index;
|
||||
+ return new_env;
|
||||
+}
|
||||
+
|
||||
#if !defined(CONFIG_USER_ONLY)
|
||||
|
||||
/* NOTE: if flush_global is true, also flush global entries (not
|
@ -1,151 +0,0 @@
|
||||
From jseward@acm.org Tue Mar 27 18:05:53 2007
|
||||
Date: Sat, 17 Mar 2007 17:35:38 +0000
|
||||
From: Julian Seward <jseward@acm.org>
|
||||
Reply-To: qemu-devel@nongnu.org
|
||||
To: qemu-devel@nongnu.org
|
||||
Subject: [Qemu-devel] [PATCH] Fix guest x86/amd64 helper_fprem/helper_fprem1
|
||||
|
||||
|
||||
The helpers for x86/amd64 fprem and fprem1 in target-i386/helper.c are
|
||||
significantly borked and, for example, cause konqueror in RedHat8 (x86
|
||||
guest) to go into an infinite loop when displaying http://news.bbc.co.uk.
|
||||
|
||||
helper_fprem has the following borkage:
|
||||
- various Inf/Nan/zero inputs not handled correctly
|
||||
- incorrect rounding when converting negative 'dblq' to 'q'
|
||||
- incorrect order of assignment to C bits (0,3,1 not 0,1,3)
|
||||
|
||||
helper_fprem1 has those problems and is also incorrect about the points
|
||||
at which its rounding needs to differ from that of helper_fprem.
|
||||
|
||||
Patch below fixes all these. It brings the fprem and fprem1 behaviour
|
||||
very much closer to the hardware -- not identical, but close. Some
|
||||
+0.0 results should really be -0.0 and there may still be other differences.
|
||||
|
||||
Anyway konquerer no longer loops with the patch applied.
|
||||
|
||||
--- qemu-0.9.0/target-i386/helper.c.fix-x86-fprem 2007-03-27 13:48:10.000000000 -0400
|
||||
+++ qemu-0.9.0/target-i386/helper.c 2007-03-27 14:03:06.000000000 -0400
|
||||
@@ -3124,30 +3124,51 @@ void helper_fprem1(void)
|
||||
CPU86_LDouble dblq, fpsrcop, fptemp;
|
||||
CPU86_LDoubleU fpsrcop1, fptemp1;
|
||||
int expdif;
|
||||
- int q;
|
||||
+ signed long long int q;
|
||||
+
|
||||
+ if (isinf(ST0) || isnan(ST0) || isnan(ST1) || (ST1 == 0.0)) {
|
||||
+ ST0 = 0.0 / 0.0; /* NaN */
|
||||
+ env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
|
||||
+ return;
|
||||
+ }
|
||||
|
||||
fpsrcop = ST0;
|
||||
fptemp = ST1;
|
||||
fpsrcop1.d = fpsrcop;
|
||||
fptemp1.d = fptemp;
|
||||
expdif = EXPD(fpsrcop1) - EXPD(fptemp1);
|
||||
+
|
||||
+ if (expdif < 0) {
|
||||
+ /* optimisation? taken from the AMD docs */
|
||||
+ env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
|
||||
+ /* ST0 is unchanged */
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
if (expdif < 53) {
|
||||
dblq = fpsrcop / fptemp;
|
||||
- dblq = (dblq < 0.0)? ceil(dblq): floor(dblq);
|
||||
+ /* round dblq towards nearest integer */
|
||||
+ dblq = rint(dblq);
|
||||
ST0 = fpsrcop - fptemp*dblq;
|
||||
- q = (int)dblq; /* cutting off top bits is assumed here */
|
||||
+
|
||||
+ /* convert dblq to q by truncating towards zero */
|
||||
+ if (dblq < 0.0)
|
||||
+ q = (signed long long int)(-dblq);
|
||||
+ else
|
||||
+ q = (signed long long int)dblq;
|
||||
+
|
||||
env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
|
||||
- /* (C0,C1,C3) <-- (q2,q1,q0) */
|
||||
- env->fpus |= (q&0x4) << 6; /* (C0) <-- q2 */
|
||||
- env->fpus |= (q&0x2) << 8; /* (C1) <-- q1 */
|
||||
- env->fpus |= (q&0x1) << 14; /* (C3) <-- q0 */
|
||||
+ /* (C0,C3,C1) <-- (q2,q1,q0) */
|
||||
+ env->fpus |= (q&0x4) << (8-2); /* (C0) <-- q2 */
|
||||
+ env->fpus |= (q&0x2) << (14-1); /* (C3) <-- q1 */
|
||||
+ env->fpus |= (q&0x1) << (9-0); /* (C1) <-- q0 */
|
||||
} else {
|
||||
env->fpus |= 0x400; /* C2 <-- 1 */
|
||||
fptemp = pow(2.0, expdif-50);
|
||||
fpsrcop = (ST0 / ST1) / fptemp;
|
||||
- /* fpsrcop = integer obtained by rounding to the nearest */
|
||||
- fpsrcop = (fpsrcop-floor(fpsrcop) < ceil(fpsrcop)-fpsrcop)?
|
||||
- floor(fpsrcop): ceil(fpsrcop);
|
||||
+ /* fpsrcop = integer obtained by chopping */
|
||||
+ fpsrcop = (fpsrcop < 0.0)?
|
||||
+ -(floor(fabs(fpsrcop))): floor(fpsrcop);
|
||||
ST0 -= (ST1 * fpsrcop * fptemp);
|
||||
}
|
||||
}
|
||||
@@ -3157,26 +3178,48 @@ void helper_fprem(void)
|
||||
CPU86_LDouble dblq, fpsrcop, fptemp;
|
||||
CPU86_LDoubleU fpsrcop1, fptemp1;
|
||||
int expdif;
|
||||
- int q;
|
||||
-
|
||||
- fpsrcop = ST0;
|
||||
- fptemp = ST1;
|
||||
+ signed long long int q;
|
||||
+
|
||||
+ if (isinf(ST0) || isnan(ST0) || isnan(ST1) || (ST1 == 0.0)) {
|
||||
+ ST0 = 0.0 / 0.0; /* NaN */
|
||||
+ env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ fpsrcop = (CPU86_LDouble)ST0;
|
||||
+ fptemp = (CPU86_LDouble)ST1;
|
||||
fpsrcop1.d = fpsrcop;
|
||||
fptemp1.d = fptemp;
|
||||
expdif = EXPD(fpsrcop1) - EXPD(fptemp1);
|
||||
+
|
||||
+ if (expdif < 0) {
|
||||
+ /* optimisation? taken from the AMD docs */
|
||||
+ env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
|
||||
+ /* ST0 is unchanged */
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
if ( expdif < 53 ) {
|
||||
- dblq = fpsrcop / fptemp;
|
||||
+ dblq = fpsrcop/*ST0*/ / fptemp/*ST1*/;
|
||||
+ /* round dblq towards zero */
|
||||
dblq = (dblq < 0.0)? ceil(dblq): floor(dblq);
|
||||
- ST0 = fpsrcop - fptemp*dblq;
|
||||
- q = (int)dblq; /* cutting off top bits is assumed here */
|
||||
+ ST0 = fpsrcop/*ST0*/ - fptemp*dblq;
|
||||
+
|
||||
+ /* convert dblq to q by truncating towards zero */
|
||||
+ if (dblq < 0.0)
|
||||
+ q = (signed long long int)(-dblq);
|
||||
+ else
|
||||
+ q = (signed long long int)dblq;
|
||||
+
|
||||
env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
|
||||
- /* (C0,C1,C3) <-- (q2,q1,q0) */
|
||||
- env->fpus |= (q&0x4) << 6; /* (C0) <-- q2 */
|
||||
- env->fpus |= (q&0x2) << 8; /* (C1) <-- q1 */
|
||||
- env->fpus |= (q&0x1) << 14; /* (C3) <-- q0 */
|
||||
+ /* (C0,C3,C1) <-- (q2,q1,q0) */
|
||||
+ env->fpus |= (q&0x4) << (8-2); /* (C0) <-- q2 */
|
||||
+ env->fpus |= (q&0x2) << (14-1); /* (C3) <-- q1 */
|
||||
+ env->fpus |= (q&0x1) << (9-0); /* (C1) <-- q0 */
|
||||
} else {
|
||||
+ int N = 32 + (expdif % 32); /* as per AMD docs */
|
||||
env->fpus |= 0x400; /* C2 <-- 1 */
|
||||
- fptemp = pow(2.0, expdif-50);
|
||||
+ fptemp = pow(2.0, (double)(expdif-N));
|
||||
fpsrcop = (ST0 / ST1) / fptemp;
|
||||
/* fpsrcop = integer obtained by chopping */
|
||||
fpsrcop = (fpsrcop < 0.0)?
|
@ -1,114 +0,0 @@
|
||||
Index: qemu-0.9.0/linux-user/syscall.c
|
||||
===================================================================
|
||||
--- qemu-0.9.0.orig/linux-user/syscall.c
|
||||
+++ qemu-0.9.0/linux-user/syscall.c
|
||||
@@ -2127,11 +2127,40 @@ static inline void host_to_target_timesp
|
||||
unlock_user_struct(target_ts, target_addr, 1);
|
||||
}
|
||||
|
||||
+#ifdef BSWAP_NEEDED
|
||||
+static int futex_op(int oldval, int op, int oparg)
|
||||
+{
|
||||
+ int retval = oparg;
|
||||
+ switch(op) {
|
||||
+ case FUTEX_OP_SET: break;
|
||||
+ case FUTEX_OP_ADD: retval += oparg; break;
|
||||
+ case FUTEX_OP_OR: retval |= oparg; break;
|
||||
+ case FUTEX_OP_ANDN: retval &= oparg; break;
|
||||
+ case FUTEX_OP_XOR: retval ^= oparg; break;
|
||||
+ }
|
||||
+ return retval;
|
||||
+}
|
||||
+
|
||||
+static int futex_cmp(int oldval, int cmp, int cmparg)
|
||||
+{
|
||||
+ switch(cmp) {
|
||||
+ case FUTEX_OP_CMP_EQ: return oldval == cmparg;
|
||||
+ case FUTEX_OP_CMP_NE: return oldval != cmparg;
|
||||
+ case FUTEX_OP_CMP_LT: return oldval < cmparg;
|
||||
+ case FUTEX_OP_CMP_LE: return oldval <= cmparg;
|
||||
+ case FUTEX_OP_CMP_GT: return oldval > cmparg;
|
||||
+ case FUTEX_OP_CMP_GE: return oldval >= cmparg;
|
||||
+ }
|
||||
+ return -1;
|
||||
+}
|
||||
+#endif
|
||||
+
|
||||
static long do_futex(target_ulong uaddr, int op, uint32_t val,
|
||||
target_ulong utime, target_ulong uaddr2,
|
||||
uint32_t val3)
|
||||
{
|
||||
struct timespec host_utime;
|
||||
unsigned long val2 = utime;
|
||||
+ long retval;
|
||||
|
||||
if (utime && (op == FUTEX_WAIT || op == FUTEX_LOCK_PI)) {
|
||||
@@ -2141,6 +2170,7 @@ static long do_futex(target_ulong uaddr,
|
||||
}
|
||||
|
||||
#ifdef BSWAP_NEEDED
|
||||
+// if( op == FUTEX_WAKE_OP ) { gemu_log("FUTEX_WAKE_OP -> FUTEX_WAKE\n"); op = FUTEX_WAKE; sleep(1); }
|
||||
switch(op) {
|
||||
case FUTEX_CMP_REQUEUE:
|
||||
val3 = tswap32(val3);
|
||||
@@ -2148,41 +2178,40 @@ static long do_futex(target_ulong uaddr,
|
||||
val2 = tswap32(val2);
|
||||
case FUTEX_WAIT:
|
||||
case FUTEX_WAKE:
|
||||
+ case FUTEX_WAKE_OP:
|
||||
val = tswap32(val);
|
||||
case FUTEX_LOCK_PI: /* This one's icky, but comes out OK */
|
||||
case FUTEX_UNLOCK_PI:
|
||||
break;
|
||||
default:
|
||||
gemu_log("qemu: Unsupported futex op %d\n", op);
|
||||
+ spin_unlock(&mmap_lock);
|
||||
return -ENOSYS;
|
||||
}
|
||||
-#if 0 /* No, it's worse than this */
|
||||
if (op == FUTEX_WAKE_OP) {
|
||||
/* Need to munge the secondary operation (val3) */
|
||||
val3 = tswap32(val3);
|
||||
- int op2 = (val3 >> 28) & 7;
|
||||
- int cmp = (val3 >> 24) & 15;
|
||||
- int oparg = (val3 << 8) >> 20;
|
||||
- int cmparg = (val3 << 20) >> 20;
|
||||
+ int op2 = (val3 >> 28) & 0xf;
|
||||
+ int cmp = (val3 >> 24) & 0xf;
|
||||
+ int oparg = (val3 >> 12) & 0xfff;
|
||||
+ int cmparg = val3 & 0xfff;
|
||||
int shift = val3 & (FUTEX_OP_OPARG_SHIFT << 28);
|
||||
-
|
||||
+ int oldval = tget32(uaddr2);
|
||||
if (shift)
|
||||
- oparg = (oparg & 7) + 24 - (oparg & 24);
|
||||
- else oparg =
|
||||
- if (op2 == FUTEX_OP_ADD) {
|
||||
- gemu_log("qemu: Unsupported wrong-endian FUTEX_OP_ADD\n");
|
||||
- return -ENOSYS;
|
||||
- }
|
||||
- if (cmparg == FUTEX_OP_CMP_LT || cmparg == FUTEX_OP_CMP_GE ||
|
||||
- cmparg == FUTEX_OP_CMP_LE || cmparg == FUTEX_OP_CMP_GT) {
|
||||
- gemu_log("qemu: Unsupported wrong-endian futex cmparg %d\n", cmparg);
|
||||
- return -ENOSYS;
|
||||
- }
|
||||
- val3 = shift | (op2<<28) | (cmp<<24) | (oparg<<12) | cmparg;
|
||||
+ oparg = 1 << oparg;
|
||||
+
|
||||
+ tput32(uaddr2,futex_op(oldval, op2, oparg));
|
||||
+ retval = syscall(__NR_futex, g2h(uaddr), FUTEX_WAKE, val, 0, 0, 0);
|
||||
+ if(futex_cmp(oldval, cmp, cmparg)) {
|
||||
+ retval = syscall(__NR_futex, g2h(uaddr2), FUTEX_WAKE, val2, 0, 0, 0);
|
||||
+ }
|
||||
+ } else {
|
||||
+ retval = syscall(__NR_futex, g2h(uaddr), op, val, val2, g2h(uaddr2), val3);
|
||||
}
|
||||
-#endif
|
||||
+#else
|
||||
+ retval = syscall(__NR_futex, g2h(uaddr), op, val, val2, g2h(uaddr2), val3);
|
||||
#endif
|
||||
- return syscall(__NR_futex, g2h(uaddr), op, val, val2, g2h(uaddr2), val3);
|
||||
+ return retval;
|
||||
}
|
||||
|
||||
int do_set_tid_address(target_ulong tidptr)
|
@ -1,64 +0,0 @@
|
||||
Index: qemu-0.9.0/hw/pc.c
|
||||
===================================================================
|
||||
--- qemu-0.9.0.orig/hw/pc.c
|
||||
+++ qemu-0.9.0/hw/pc.c
|
||||
@@ -32,9 +32,11 @@
|
||||
#define LINUX_BOOT_FILENAME "linux_boot.bin"
|
||||
|
||||
#define KERNEL_LOAD_ADDR 0x00100000
|
||||
-#define INITRD_LOAD_ADDR 0x00600000
|
||||
+#define MAX_INITRD_LOAD_ADDR 0x38000000
|
||||
#define KERNEL_PARAMS_ADDR 0x00090000
|
||||
#define KERNEL_CMDLINE_ADDR 0x00099000
|
||||
+/* Leave a chunk of memory at the top of RAM for the BIOS ACPI tables. */
|
||||
+#define ACPI_DATA_SIZE 0x10000
|
||||
|
||||
static fdctrl_t *floppy_controller;
|
||||
static RTCState *rtc_state;
|
||||
@@ -452,6 +454,7 @@ static void pc_init1(int ram_size, int v
|
||||
char buf[1024];
|
||||
int ret, linux_boot, initrd_size, i;
|
||||
unsigned long bios_offset, vga_bios_offset, option_rom_offset;
|
||||
+ unsigned long initrd_offset;
|
||||
int bios_size, isa_bios_size;
|
||||
PCIBus *pci_bus;
|
||||
int piix3_devfn = -1;
|
||||
@@ -576,8 +579,28 @@ static void pc_init1(int ram_size, int v
|
||||
|
||||
/* load initrd */
|
||||
initrd_size = 0;
|
||||
+ initrd_offset = 0;
|
||||
if (initrd_filename) {
|
||||
- initrd_size = load_image(initrd_filename, phys_ram_base + INITRD_LOAD_ADDR);
|
||||
+ initrd_size = get_image_size (initrd_filename);
|
||||
+ if (initrd_size > 0) {
|
||||
+ initrd_offset = (ram_size - initrd_size) & TARGET_PAGE_MASK;
|
||||
+ /* Leave space for BIOS ACPI tables. */
|
||||
+ initrd_offset -= ACPI_DATA_SIZE;
|
||||
+ /* Avoid the last 64k to avoid 2.2.x kernel bugs. */
|
||||
+ initrd_offset -= 0x10000;
|
||||
+ if (initrd_offset > MAX_INITRD_LOAD_ADDR)
|
||||
+ initrd_offset = MAX_INITRD_LOAD_ADDR;
|
||||
+
|
||||
+ if (initrd_size > ram_size
|
||||
+ || initrd_offset < KERNEL_LOAD_ADDR + ret) {
|
||||
+ fprintf(stderr,
|
||||
+ "qemu: memory too small for initial ram disk '%s'\n",
|
||||
+ initrd_filename);
|
||||
+ exit(1);
|
||||
+ }
|
||||
+ initrd_size = load_image(initrd_filename,
|
||||
+ phys_ram_base + initrd_offset);
|
||||
+ }
|
||||
if (initrd_size < 0) {
|
||||
fprintf(stderr, "qemu: could not load initial ram disk '%s'\n",
|
||||
initrd_filename);
|
||||
@@ -585,7 +608,7 @@ static void pc_init1(int ram_size, int v
|
||||
}
|
||||
}
|
||||
if (initrd_size > 0) {
|
||||
- stl_raw(phys_ram_base + KERNEL_PARAMS_ADDR + 0x218, INITRD_LOAD_ADDR);
|
||||
+ stl_raw(phys_ram_base + KERNEL_PARAMS_ADDR + 0x218, initrd_offset);
|
||||
stl_raw(phys_ram_base + KERNEL_PARAMS_ADDR + 0x21c, initrd_size);
|
||||
}
|
||||
pstrcpy(phys_ram_base + KERNEL_CMDLINE_ADDR, 4096,
|
@ -1,36 +0,0 @@
|
||||
--- qemu-0.9.0/hw/pc.c.kernel-option-vga 2007-02-13 14:41:12.000000000 +0100
|
||||
+++ qemu-0.9.0/hw/pc.c 2007-02-14 17:01:57.000000000 +0100
|
||||
@@ -567,6 +567,7 @@ static void pc_init1(int ram_size, int v
|
||||
if (linux_boot) {
|
||||
uint8_t bootsect[512];
|
||||
uint8_t old_bootsect[512];
|
||||
+ char *vmode;
|
||||
|
||||
if (bs_table[0] == NULL) {
|
||||
fprintf(stderr, "A disk image must be given for 'hda' when booting a Linux kernel\n");
|
||||
@@ -618,6 +619,25 @@ static void pc_init1(int ram_size, int v
|
||||
KERNEL_CMDLINE_ADDR - KERNEL_PARAMS_ADDR);
|
||||
/* loader type */
|
||||
stw_raw(phys_ram_base + KERNEL_PARAMS_ADDR + 0x210, 0x01);
|
||||
+
|
||||
+ /* handle vga= parameter */
|
||||
+ vmode = strstr(kernel_cmdline, "vga=");
|
||||
+ if (vmode) {
|
||||
+ char *space;
|
||||
+ unsigned int video_mode;
|
||||
+ /* skip "vga=" */
|
||||
+ vmode += 4;
|
||||
+ if (!strncmp(vmode, "normal", 6)) {
|
||||
+ video_mode = 0xffff;
|
||||
+ } else if (!strncmp(vmode, "ext", 3)) {
|
||||
+ video_mode = 0xfffe;
|
||||
+ } else if (!strncmp(vmode, "ask", 3)) {
|
||||
+ video_mode = 0xfffd;
|
||||
+ } else {
|
||||
+ video_mode = strtol(vmode, NULL, 0);
|
||||
+ }
|
||||
+ stw_raw(phys_ram_base + KERNEL_PARAMS_ADDR + 0x1fa, video_mode);
|
||||
+ }
|
||||
}
|
||||
|
||||
if (pci_enabled) {
|
@ -1,203 +0,0 @@
|
||||
Index: qemu-0.9.0/linux-user/syscall.c
|
||||
===================================================================
|
||||
--- qemu-0.9.0.orig/linux-user/syscall.c
|
||||
+++ qemu-0.9.0/linux-user/syscall.c
|
||||
@@ -185,6 +185,9 @@ extern int getresgid(gid_t *, gid_t *, g
|
||||
extern int setgroups(int, gid_t *);
|
||||
extern int uselib(const char*);
|
||||
|
||||
+#include "exec-all.h"
|
||||
+long mmap_lock;
|
||||
+
|
||||
static inline long get_errno(long ret)
|
||||
{
|
||||
if (ret == -1)
|
||||
@@ -227,9 +235,11 @@ long do_brk(target_ulong new_brk)
|
||||
|
||||
/* We need to allocate more memory after the brk... */
|
||||
new_alloc_size = HOST_PAGE_ALIGN(new_brk - brk_page + 1);
|
||||
+ spin_lock(&mmap_lock);
|
||||
mapped_addr = get_errno(target_mmap(brk_page, new_alloc_size,
|
||||
PROT_READ|PROT_WRITE,
|
||||
MAP_ANON|MAP_FIXED|MAP_PRIVATE, 0, 0));
|
||||
+ spin_unlock(&mmap_lock);
|
||||
if (is_error(mapped_addr)) {
|
||||
return mapped_addr;
|
||||
} else {
|
||||
@@ -2985,15 +3021,19 @@ long do_syscall(void *cpu_env, int num,
|
||||
v5 = tswapl(v[4]);
|
||||
v6 = tswapl(v[5]);
|
||||
unlock_user(v, arg1, 0);
|
||||
+ spin_lock(&mmap_lock);
|
||||
ret = get_errno(target_mmap(v1, v2, v3,
|
||||
target_to_host_bitmask(v4, mmap_flags_tbl),
|
||||
v5, v6));
|
||||
+ spin_unlock(&mmap_lock);
|
||||
}
|
||||
#else
|
||||
+ spin_lock(&mmap_lock);
|
||||
ret = get_errno(target_mmap(arg1, arg2, arg3,
|
||||
target_to_host_bitmask(arg4, mmap_flags_tbl),
|
||||
arg5,
|
||||
arg6));
|
||||
+ spin_unlock(&mmap_lock);
|
||||
#endif
|
||||
break;
|
||||
#ifdef TARGET_NR_mmap2
|
||||
@@ -3003,36 +3043,54 @@ long do_syscall(void *cpu_env, int num,
|
||||
#else
|
||||
#define MMAP_SHIFT TARGET_PAGE_BITS
|
||||
#endif
|
||||
+ spin_lock(&mmap_lock);
|
||||
ret = get_errno(target_mmap(arg1, arg2, arg3,
|
||||
target_to_host_bitmask(arg4, mmap_flags_tbl),
|
||||
arg5,
|
||||
arg6 << MMAP_SHIFT));
|
||||
+ spin_unlock(&mmap_lock);
|
||||
break;
|
||||
#endif
|
||||
case TARGET_NR_munmap:
|
||||
+ spin_lock(&mmap_lock);
|
||||
ret = get_errno(target_munmap(arg1, arg2));
|
||||
+ spin_unlock(&mmap_lock);
|
||||
break;
|
||||
case TARGET_NR_mprotect:
|
||||
+ spin_lock(&mmap_lock);
|
||||
ret = get_errno(target_mprotect(arg1, arg2, arg3));
|
||||
+ spin_unlock(&mmap_lock);
|
||||
break;
|
||||
case TARGET_NR_mremap:
|
||||
+ spin_lock(&mmap_lock);
|
||||
ret = get_errno(target_mremap(arg1, arg2, arg3, arg4, arg5));
|
||||
+ spin_unlock(&mmap_lock);
|
||||
break;
|
||||
/* ??? msync/mlock/munlock are broken for softmmu. */
|
||||
case TARGET_NR_msync:
|
||||
+ spin_lock(&mmap_lock);
|
||||
ret = get_errno(msync(g2h(arg1), arg2, arg3));
|
||||
+ spin_unlock(&mmap_lock);
|
||||
break;
|
||||
case TARGET_NR_mlock:
|
||||
+ spin_lock(&mmap_lock);
|
||||
ret = get_errno(mlock(g2h(arg1), arg2));
|
||||
+ spin_unlock(&mmap_lock);
|
||||
break;
|
||||
case TARGET_NR_munlock:
|
||||
+ spin_lock(&mmap_lock);
|
||||
ret = get_errno(munlock(g2h(arg1), arg2));
|
||||
+ spin_unlock(&mmap_lock);
|
||||
break;
|
||||
case TARGET_NR_mlockall:
|
||||
+ spin_lock(&mmap_lock);
|
||||
ret = get_errno(mlockall(arg1));
|
||||
+ spin_unlock(&mmap_lock);
|
||||
break;
|
||||
case TARGET_NR_munlockall:
|
||||
+ spin_lock(&mmap_lock);
|
||||
ret = get_errno(munlockall());
|
||||
+ spin_unlock(&mmap_lock);
|
||||
break;
|
||||
case TARGET_NR_truncate:
|
||||
p = lock_user_string(arg1);
|
||||
Index: qemu-0.9.0/exec.c
|
||||
===================================================================
|
||||
--- qemu-0.9.0.orig/exec.c
|
||||
+++ qemu-0.9.0/exec.c
|
||||
@@ -1676,6 +1684,50 @@ void page_dump(FILE *f)
|
||||
}
|
||||
}
|
||||
|
||||
+/* dump memory mappings */
|
||||
+target_ulong page_find_end()
|
||||
+{
|
||||
+ unsigned long start, end;
|
||||
+ int i, j, prot, prot1;
|
||||
+ void *firsttb;
|
||||
+ PageDesc *p;
|
||||
+ target_ulong last = 0;
|
||||
+
|
||||
+ start = -1;
|
||||
+ end = -1;
|
||||
+ prot = 0;
|
||||
+ for(i = 0; i <= L1_SIZE; i++) {
|
||||
+ if (i < L1_SIZE)
|
||||
+ p = l1_map[i];
|
||||
+ else
|
||||
+ p = NULL;
|
||||
+ for(j = 0;j < L2_SIZE; j++) {
|
||||
+ if (!p) {
|
||||
+ firsttb = NULL;
|
||||
+ prot1 = 0;
|
||||
+ }
|
||||
+ else {
|
||||
+ prot1 = p[j].flags;
|
||||
+ firsttb = p[j].first_tb;
|
||||
+ }
|
||||
+ if (prot1 != prot) {
|
||||
+ end = (i << (32 - L1_BITS)) | (j << TARGET_PAGE_BITS);
|
||||
+ if (start != -1) {
|
||||
+ last = end;
|
||||
+ }
|
||||
+ if (prot1 != 0)
|
||||
+ start = end;
|
||||
+ else
|
||||
+ start = -1;
|
||||
+ prot = prot1;
|
||||
+ }
|
||||
+ if (!p)
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+ return last;
|
||||
+}
|
||||
+
|
||||
int page_get_flags(target_ulong address)
|
||||
{
|
||||
PageDesc *p;
|
||||
Index: qemu-0.9.0/linux-user/mmap.c
|
||||
===================================================================
|
||||
--- qemu-0.9.0.orig/linux-user/mmap.c
|
||||
+++ qemu-0.9.0/linux-user/mmap.c
|
||||
@@ -48,8 +48,14 @@ int target_mprotect(target_ulong start,
|
||||
end = start + len;
|
||||
if (end < start)
|
||||
return -EINVAL;
|
||||
- if (prot & ~(PROT_READ | PROT_WRITE | PROT_EXEC))
|
||||
- return -EINVAL;
|
||||
+ if (prot & ~(PROT_READ | PROT_WRITE | PROT_EXEC)) {
|
||||
+#ifdef DEBUG_MMAP
|
||||
+ gemu_log("mprotect: ERROR (prot & ~(PROT_READ | PROT_WRITE | PROT_EXEC)\n");
|
||||
+#endif
|
||||
+ // dirty hack to get mplayer running (sets PROT_GROWSDOWN) we just ignore advanced flags
|
||||
+ prot &= (PROT_READ | PROT_WRITE | PROT_EXEC);
|
||||
+// return -EINVAL;
|
||||
+ }
|
||||
if (len == 0)
|
||||
return 0;
|
||||
|
||||
@@ -205,9 +233,23 @@ long target_mmap(target_ulong start, tar
|
||||
defined(__ia64) || defined(__CYGWIN__)
|
||||
/* tell the kenel to search at the same place as i386 */
|
||||
if (real_start == 0) {
|
||||
- real_start = last_start;
|
||||
- last_start += HOST_PAGE_ALIGN(len);
|
||||
+ target_ulong curend = page_find_end();
|
||||
+
|
||||
+ if(curend > last_start) {
|
||||
+#ifdef DEBUG_MMAP
|
||||
+ gemu_log("qemu: set last_start from %p to %p\n", last_start, curend + HOST_PAGE_ALIGN(len)); fflush(stdout); fflush(stderr);
|
||||
+#endif
|
||||
+ last_start = curend;
|
||||
+#ifdef DEBUG_MMAP
|
||||
+ } else {
|
||||
+ gemu_log("qemu: curend(%p) <= last_start(%p)\n", curend, last_start); fflush(stdout); fflush(stderr);
|
||||
+#endif
|
||||
+ }
|
||||
+
|
||||
+ real_start = last_start;
|
||||
+ last_start += HOST_PAGE_ALIGN(len);
|
||||
}
|
||||
+
|
||||
#endif
|
||||
if (0 && qemu_host_page_size != qemu_real_host_page_size) {
|
||||
/* NOTE: this code is only for debugging with '-p' option */
|
@ -1,12 +0,0 @@
|
||||
Index: qemu-0.9.0/linux-user/syscall.c
|
||||
===================================================================
|
||||
--- qemu-0.9.0.orig/linux-user/syscall.c
|
||||
+++ qemu-0.9.0/linux-user/syscall.c
|
||||
@@ -791,6 +791,7 @@ static long do_socket(int domain, int ty
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
+ if(domain == PF_NETLINK) return -EAFNOSUPPORT;
|
||||
return get_errno(socket(domain, type, protocol));
|
||||
}
|
||||
|
@ -1,300 +0,0 @@
|
||||
Index: qemu-0.9.0/linux-user/main.c
|
||||
===================================================================
|
||||
--- qemu-0.9.0.orig/linux-user/main.c
|
||||
+++ qemu-0.9.0/linux-user/main.c
|
||||
@@ -156,7 +156,7 @@ static void set_gate(void *ptr, unsigned
|
||||
p[1] = tswapl(e2);
|
||||
}
|
||||
|
||||
-uint64_t gdt_table[6];
|
||||
+uint64_t gdt_table[9];
|
||||
uint64_t idt_table[256];
|
||||
|
||||
/* only dpl matters as we do only user space emulation */
|
||||
@@ -1604,7 +1604,11 @@ int main(int argc, char **argv)
|
||||
int optind;
|
||||
const char *r;
|
||||
int gdbstub_port = 0;
|
||||
-
|
||||
+ char *assume_kernel = getenv("QEMU_ASSUME_KERNEL");
|
||||
+
|
||||
+ if (assume_kernel)
|
||||
+ setenv("LD_ASSUME_KERNEL", assume_kernel, 1);
|
||||
+
|
||||
if (argc <= 1)
|
||||
usage();
|
||||
|
||||
Index: qemu-0.9.0/linux-user/syscall.c
|
||||
===================================================================
|
||||
--- qemu-0.9.0.orig/linux-user/syscall.c
|
||||
+++ qemu-0.9.0/linux-user/syscall.c
|
||||
@@ -17,6 +17,8 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
+
|
||||
+#define __user
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
@@ -57,6 +59,7 @@
|
||||
#define tchars host_tchars /* same as target */
|
||||
#define ltchars host_ltchars /* same as target */
|
||||
|
||||
+#include <linux/futex.h>
|
||||
#include <linux/termios.h>
|
||||
#include <linux/unistd.h>
|
||||
#include <linux/utsname.h>
|
||||
@@ -1690,6 +1693,80 @@ int do_modify_ldt(CPUX86State *env, int
|
||||
return ret;
|
||||
}
|
||||
|
||||
+int do_set_thread_area(CPUX86State *env, target_ulong ptr)
|
||||
+{
|
||||
+ uint64_t *gdt_table = g2h(env->gdt.base);
|
||||
+ struct target_modify_ldt_ldt_s ldt_info;
|
||||
+ struct target_modify_ldt_ldt_s *target_ldt_info;
|
||||
+ int seg_32bit, contents, read_exec_only, limit_in_pages;
|
||||
+ int seg_not_present, useable;
|
||||
+ uint32_t *lp, entry_1, entry_2;
|
||||
+ int i;
|
||||
+
|
||||
+ lock_user_struct(target_ldt_info, ptr, 1);
|
||||
+ ldt_info.entry_number = tswap32(target_ldt_info->entry_number);
|
||||
+ ldt_info.base_addr = tswapl(target_ldt_info->base_addr);
|
||||
+ ldt_info.limit = tswap32(target_ldt_info->limit);
|
||||
+ ldt_info.flags = tswap32(target_ldt_info->flags);
|
||||
+ if (ldt_info.entry_number == -1) {
|
||||
+ for (i=6; i<8; i++)
|
||||
+ if (gdt_table[i] == 0) {
|
||||
+ ldt_info.entry_number = i;
|
||||
+ target_ldt_info->entry_number = tswap32(i);
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+ unlock_user_struct(target_ldt_info, ptr, 0);
|
||||
+
|
||||
+ if (ldt_info.entry_number < 6 || ldt_info.entry_number > 8)
|
||||
+ return -EINVAL;
|
||||
+ seg_32bit = ldt_info.flags & 1;
|
||||
+ contents = (ldt_info.flags >> 1) & 3;
|
||||
+ read_exec_only = (ldt_info.flags >> 3) & 1;
|
||||
+ limit_in_pages = (ldt_info.flags >> 4) & 1;
|
||||
+ seg_not_present = (ldt_info.flags >> 5) & 1;
|
||||
+ useable = (ldt_info.flags >> 6) & 1;
|
||||
+
|
||||
+ if (contents == 3) {
|
||||
+ if (seg_not_present == 0)
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ /* NOTE: same code as Linux kernel */
|
||||
+ /* Allow LDTs to be cleared by the user. */
|
||||
+ if (ldt_info.base_addr == 0 && ldt_info.limit == 0) {
|
||||
+ if ((contents == 0 &&
|
||||
+ read_exec_only == 1 &&
|
||||
+ seg_32bit == 0 &&
|
||||
+ limit_in_pages == 0 &&
|
||||
+ seg_not_present == 1 &&
|
||||
+ useable == 0 )) {
|
||||
+ entry_1 = 0;
|
||||
+ entry_2 = 0;
|
||||
+ goto install;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ entry_1 = ((ldt_info.base_addr & 0x0000ffff) << 16) |
|
||||
+ (ldt_info.limit & 0x0ffff);
|
||||
+ entry_2 = (ldt_info.base_addr & 0xff000000) |
|
||||
+ ((ldt_info.base_addr & 0x00ff0000) >> 16) |
|
||||
+ (ldt_info.limit & 0xf0000) |
|
||||
+ ((read_exec_only ^ 1) << 9) |
|
||||
+ (contents << 10) |
|
||||
+ ((seg_not_present ^ 1) << 15) |
|
||||
+ (seg_32bit << 22) |
|
||||
+ (limit_in_pages << 23) |
|
||||
+ (useable << 20) |
|
||||
+ 0x7000;
|
||||
+
|
||||
+ /* Install the new entry ... */
|
||||
+install:
|
||||
+ lp = (uint32_t *)(gdt_table + ldt_info.entry_number);
|
||||
+ lp[0] = tswap32(entry_1);
|
||||
+ lp[1] = tswap32(entry_2);
|
||||
+ return 0;
|
||||
+}
|
||||
#endif /* defined(TARGET_I386) */
|
||||
|
||||
/* this stack is the equivalent of the kernel stack associated with a
|
||||
@@ -1710,9 +1787,13 @@ int do_fork(CPUState *env, unsigned int
|
||||
TaskState *ts;
|
||||
uint8_t *new_stack;
|
||||
CPUState *new_env;
|
||||
-
|
||||
+#if defined(TARGET_I386)
|
||||
+ uint64_t *new_gdt_table;
|
||||
+#endif
|
||||
if (flags & CLONE_VM) {
|
||||
ts = malloc(sizeof(TaskState) + NEW_STACK_SIZE);
|
||||
+ if (!ts)
|
||||
+ return -ENOMEM;
|
||||
memset(ts, 0, sizeof(TaskState));
|
||||
new_stack = ts->stack;
|
||||
ts->used = 1;
|
||||
@@ -1725,6 +1807,29 @@ int do_fork(CPUState *env, unsigned int
|
||||
#if defined(TARGET_I386)
|
||||
if (!newsp)
|
||||
newsp = env->regs[R_ESP];
|
||||
+ new_gdt_table = malloc(9 * 8);
|
||||
+ if (!new_gdt_table) {
|
||||
+ free(new_env);
|
||||
+ return -ENOMEM;
|
||||
+ }
|
||||
+ /* Copy main GDT table from parent, but clear TLS entries */
|
||||
+ memcpy(new_gdt_table, g2h(env->gdt.base), 6 * 8);
|
||||
+ memset(&new_gdt_table[6], 0, 3 * 8);
|
||||
+ new_env->gdt.base = h2g(new_gdt_table);
|
||||
+ if (flags & 0x00080000 /* CLONE_SETTLS */) {
|
||||
+ ret = do_set_thread_area(new_env, new_env->regs[R_ESI]);
|
||||
+ if (ret) {
|
||||
+ free(new_gdt_table);
|
||||
+ free(new_env);
|
||||
+ return ret;
|
||||
+ }
|
||||
+ }
|
||||
+ cpu_x86_load_seg(env, R_CS, new_env->regs[R_CS]);
|
||||
+ cpu_x86_load_seg(env, R_DS, new_env->regs[R_DS]);
|
||||
+ cpu_x86_load_seg(env, R_ES, new_env->regs[R_ES]);
|
||||
+ cpu_x86_load_seg(env, R_SS, new_env->regs[R_SS]);
|
||||
+ cpu_x86_load_seg(env, R_FS, new_env->regs[R_FS]);
|
||||
+ cpu_x86_load_seg(env, R_GS, new_env->regs[R_GS]);
|
||||
new_env->regs[R_ESP] = newsp;
|
||||
new_env->regs[R_EAX] = 0;
|
||||
#elif defined(TARGET_ARM)
|
||||
@@ -1991,6 +2096,68 @@ static inline void host_to_target_timesp
|
||||
unlock_user_struct(target_ts, target_addr, 1);
|
||||
}
|
||||
|
||||
+static long do_futex(target_ulong uaddr, int op, uint32_t val,
|
||||
+ target_ulong utime, target_ulong uaddr2,
|
||||
+ uint32_t val3)
|
||||
+{
|
||||
+ struct timespec host_utime;
|
||||
+ unsigned long val2 = utime;
|
||||
+
|
||||
+ if (utime && (op == FUTEX_WAIT || op == FUTEX_LOCK_PI)) {
|
||||
+ target_to_host_timespec(&host_utime, utime);
|
||||
+ val2 = (unsigned long)&host_utime;
|
||||
+ }
|
||||
+
|
||||
+#ifdef BSWAP_NEEDED
|
||||
+ switch(op) {
|
||||
+ case FUTEX_CMP_REQUEUE:
|
||||
+ val3 = tswap32(val3);
|
||||
+ case FUTEX_REQUEUE:
|
||||
+ val2 = tswap32(val2);
|
||||
+ case FUTEX_WAIT:
|
||||
+ case FUTEX_WAKE:
|
||||
+ val = tswap32(val);
|
||||
+ case FUTEX_LOCK_PI: /* This one's icky, but comes out OK */
|
||||
+ case FUTEX_UNLOCK_PI:
|
||||
+ break;
|
||||
+ default:
|
||||
+ gemu_log("qemu: Unsupported futex op %d\n", op);
|
||||
+ return -ENOSYS;
|
||||
+ }
|
||||
+#if 0 /* No, it's worse than this */
|
||||
+ if (op == FUTEX_WAKE_OP) {
|
||||
+ /* Need to munge the secondary operation (val3) */
|
||||
+ val3 = tswap32(val3);
|
||||
+ int op2 = (val3 >> 28) & 7;
|
||||
+ int cmp = (val3 >> 24) & 15;
|
||||
+ int oparg = (val3 << 8) >> 20;
|
||||
+ int cmparg = (val3 << 20) >> 20;
|
||||
+ int shift = val3 & (FUTEX_OP_OPARG_SHIFT << 28);
|
||||
+
|
||||
+ if (shift)
|
||||
+ oparg = (oparg & 7) + 24 - (oparg & 24);
|
||||
+ else oparg =
|
||||
+ if (op2 == FUTEX_OP_ADD) {
|
||||
+ gemu_log("qemu: Unsupported wrong-endian FUTEX_OP_ADD\n");
|
||||
+ return -ENOSYS;
|
||||
+ }
|
||||
+ if (cmparg == FUTEX_OP_CMP_LT || cmparg == FUTEX_OP_CMP_GE ||
|
||||
+ cmparg == FUTEX_OP_CMP_LE || cmparg == FUTEX_OP_CMP_GT) {
|
||||
+ gemu_log("qemu: Unsupported wrong-endian futex cmparg %d\n", cmparg);
|
||||
+ return -ENOSYS;
|
||||
+ }
|
||||
+ val3 = shift | (op2<<28) | (cmp<<24) | (oparg<<12) | cmparg;
|
||||
+ }
|
||||
+#endif
|
||||
+#endif
|
||||
+ return syscall(__NR_futex, g2h(uaddr), op, val, val2, g2h(uaddr2), val3);
|
||||
+}
|
||||
+
|
||||
+int do_set_tid_address(target_ulong tidptr)
|
||||
+{
|
||||
+ return syscall(__NR_set_tid_address, g2h(tidptr));
|
||||
+}
|
||||
+
|
||||
long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3,
|
||||
long arg4, long arg5, long arg6)
|
||||
{
|
||||
@@ -2008,7 +2175,7 @@ long do_syscall(void *cpu_env, int num,
|
||||
_mcleanup();
|
||||
#endif
|
||||
gdb_exit(cpu_env, arg1);
|
||||
- /* XXX: should free thread stack and CPU env */
|
||||
+ /* XXX: should free thread stack, GDT and CPU env */
|
||||
_exit(arg1);
|
||||
ret = 0; /* avoid warning */
|
||||
break;
|
||||
@@ -3153,6 +3320,9 @@ long do_syscall(void *cpu_env, int num,
|
||||
case TARGET_NR_vm86:
|
||||
ret = do_vm86(cpu_env, arg1, arg2);
|
||||
break;
|
||||
+ case TARGET_NR_set_thread_area:
|
||||
+ ret = get_errno(do_set_thread_area(cpu_env, arg1));
|
||||
+ break;
|
||||
#endif
|
||||
case TARGET_NR_adjtimex:
|
||||
goto unimplemented;
|
||||
@@ -3947,15 +4117,24 @@ long do_syscall(void *cpu_env, int num,
|
||||
case TARGET_NR_fremovexattr:
|
||||
goto unimplemented_nowarn;
|
||||
#endif
|
||||
-#ifdef TARGET_NR_set_thread_area
|
||||
- case TARGET_NR_set_thread_area:
|
||||
- case TARGET_NR_get_thread_area:
|
||||
- goto unimplemented_nowarn;
|
||||
-#endif
|
||||
#ifdef TARGET_NR_getdomainname
|
||||
case TARGET_NR_getdomainname:
|
||||
goto unimplemented_nowarn;
|
||||
#endif
|
||||
+#ifdef TARGET_NR_futex
|
||||
+ case TARGET_NR_futex:
|
||||
+ ret = get_errno(do_futex(arg1, arg2, arg3, arg4, arg5, arg6));
|
||||
+ break;
|
||||
+#endif
|
||||
+#ifdef TARGET_NR_set_tid_address
|
||||
+ case TARGET_NR_set_tid_address:
|
||||
+ ret = get_errno(do_set_tid_address(arg1));
|
||||
+ break;
|
||||
+#endif
|
||||
+#ifdef TARGET_NR_set_robust_list
|
||||
+ case TARGET_NR_set_robust_list:
|
||||
+ goto unimplemented_nowarn;
|
||||
+#endif
|
||||
#ifdef TARGET_NR_clock_gettime
|
||||
case TARGET_NR_clock_gettime:
|
||||
{
|
||||
@@ -3975,7 +4154,7 @@ long do_syscall(void *cpu_env, int num,
|
||||
default:
|
||||
unimplemented:
|
||||
gemu_log("qemu: Unsupported syscall: %d\n", num);
|
||||
-#if defined(TARGET_NR_setxattr) || defined(TARGET_NR_set_thread_area) || defined(TARGET_NR_getdomainname)
|
||||
+#if defined(TARGET_NR_setxattr) || defined(TARGET_NR_set_thread_area) || defined(TARGET_NR_set_robust_list) || defined(TARGET_NR_getdomainname)
|
||||
unimplemented_nowarn:
|
||||
#endif
|
||||
ret = -ENOSYS;
|
@ -1,219 +0,0 @@
|
||||
Index: qemu-0.9.0/linux-user/i386/syscall_nr.h
|
||||
===================================================================
|
||||
--- qemu-0.9.0.orig/linux-user/i386/syscall_nr.h
|
||||
+++ qemu-0.9.0/linux-user/i386/syscall_nr.h
|
||||
@@ -271,5 +271,6 @@
|
||||
#define TARGET_NR_clock_getres (TARGET_NR_timer_create+7)
|
||||
#define TARGET_NR_clock_nanosleep (TARGET_NR_timer_create+8)
|
||||
|
||||
+#define TARGET_NR_tgkill 270
|
||||
#define TARGET_NR_utimes 271
|
||||
#define TARGET_NR_fadvise64_64 272
|
||||
Index: qemu-0.9.0/linux-user/syscall.c
|
||||
===================================================================
|
||||
--- qemu-0.9.0.orig/linux-user/syscall.c
|
||||
+++ qemu-0.9.0/linux-user/syscall.c
|
||||
@@ -145,6 +145,8 @@ type name (type1 arg1,type2 arg2,type3 a
|
||||
#define __NR_sys_rt_sigqueueinfo __NR_rt_sigqueueinfo
|
||||
#define __NR_sys_syslog __NR_syslog
|
||||
#define __NR_sys_fadvise64 __NR_fadvise64
|
||||
+#define __NR_sys_tgkill __NR_tgkill
|
||||
+#define __NR_sys_clone __NR_clone
|
||||
|
||||
#if defined(__alpha__) || defined (__ia64__) || defined(__x86_64__)
|
||||
#define __NR__llseek __NR_lseek
|
||||
@@ -166,6 +168,8 @@ _syscall5(int, _llseek, uint, fd, ulon
|
||||
_syscall3(int,sys_rt_sigqueueinfo,int,pid,int,sig,siginfo_t *,uinfo)
|
||||
_syscall3(int,sys_syslog,int,type,char*,bufp,int,len)
|
||||
_syscall4(int,sys_fadvise64,int,fd,loff_t,offset,loff_t,len,int,advice)
|
||||
+_syscall3(int,sys_tgkill,int,tgid,int,pid,int,sig)
|
||||
+_syscall5(int,sys_clone, int, flags, void *, child_stack, int *, parent_tidptr, struct user_desc *, newtls, int *, child_tidptr)
|
||||
#ifdef __NR_exit_group
|
||||
_syscall1(int,exit_group,int,error_code)
|
||||
#endif
|
||||
@@ -1699,7 +1704,7 @@ int do_modify_ldt(CPUX86State *env, int
|
||||
return ret;
|
||||
}
|
||||
|
||||
-int do_set_thread_area(CPUX86State *env, target_ulong ptr)
|
||||
+int do_set_thread_area(CPUX86State *env, target_ulong ptr, int set_shadow_registers)
|
||||
{
|
||||
uint64_t *gdt_table = g2h(env->gdt.base);
|
||||
struct target_modify_ldt_ldt_s ldt_info;
|
||||
@@ -1708,6 +1713,7 @@ int do_set_thread_area(CPUX86State *env,
|
||||
int seg_not_present, useable;
|
||||
uint32_t *lp, entry_1, entry_2;
|
||||
int i;
|
||||
+ SegmentCache *sc = &env->segs[R_GS];
|
||||
|
||||
lock_user_struct(target_ldt_info, ptr, 1);
|
||||
ldt_info.entry_number = tswap32(target_ldt_info->entry_number);
|
||||
@@ -1767,6 +1767,12 @@ int do_set_thread_area(CPUX86State *env,
|
||||
(useable << 20) |
|
||||
0x7000;
|
||||
|
||||
+ if(set_shadow_registers) {
|
||||
+ sc->selector = env->regs[R_GS];
|
||||
+ sc->base = ldt_info.base_addr;
|
||||
+ sc->limit = ldt_info.limit;
|
||||
+ sc->flags = entry_2;
|
||||
+ }
|
||||
/* Install the new entry ... */
|
||||
install:
|
||||
lp = (uint32_t *)(gdt_table + ldt_info.entry_number);
|
||||
@@ -1779,20 +1802,21 @@ install:
|
||||
thread/process */
|
||||
#define NEW_STACK_SIZE 8192
|
||||
|
||||
-static int clone_func(void *arg)
|
||||
+static int clone_func(CPUState *cloneenv)
|
||||
{
|
||||
- CPUState *env = arg;
|
||||
- cpu_loop(env);
|
||||
+ cpu_loop(cloneenv);
|
||||
/* never exits */
|
||||
return 0;
|
||||
}
|
||||
|
||||
-int do_fork(CPUState *env, unsigned int flags, unsigned long newsp)
|
||||
+int do_fork(CPUState *env, unsigned int flags, target_ulong newsp, target_ulong parent_tidptr, target_ulong newtls, target_ulong child_tidptr)
|
||||
{
|
||||
int ret;
|
||||
+ int cpu_index;
|
||||
+ unsigned long parent_tid=gettid();
|
||||
TaskState *ts;
|
||||
uint8_t *new_stack;
|
||||
- CPUState *new_env;
|
||||
+ CPUState *new_env, *next_cpu;
|
||||
#if defined(TARGET_I386)
|
||||
uint64_t *new_gdt_table;
|
||||
#endif
|
||||
@@ -1807,9 +1835,14 @@ int do_fork(CPUState *env, unsigned int
|
||||
/* add in task state list */
|
||||
ts->next = first_task_state;
|
||||
first_task_state = ts;
|
||||
- /* we create a new CPU instance. */
|
||||
- new_env = cpu_init();
|
||||
- memcpy(new_env, env, sizeof(CPUState));
|
||||
+ /* we create a new CPU instance. (cpu_copy() in cvs) */
|
||||
+ new_env = cpu_init();
|
||||
+ /* preserve chaining and index */
|
||||
+ next_cpu = new_env->next_cpu;
|
||||
+ cpu_index = new_env->cpu_index;
|
||||
+ memcpy(new_env, env, sizeof(CPUState));
|
||||
+ new_env->next_cpu = next_cpu;
|
||||
+ new_env->cpu_index = cpu_index;
|
||||
#if defined(TARGET_I386)
|
||||
if (!newsp)
|
||||
newsp = env->regs[R_ESP];
|
||||
@@ -1818,26 +1851,20 @@ int do_fork(CPUState *env, unsigned int
|
||||
free(new_env);
|
||||
return -ENOMEM;
|
||||
}
|
||||
/* Copy main GDT table from parent, but clear TLS entries */
|
||||
memcpy(new_gdt_table, g2h(env->gdt.base), 6 * 8);
|
||||
memset(&new_gdt_table[6], 0, 3 * 8);
|
||||
new_env->gdt.base = h2g(new_gdt_table);
|
||||
- if (flags & 0x00080000 /* CLONE_SETTLS */) {
|
||||
- ret = do_set_thread_area(new_env, new_env->regs[R_ESI]);
|
||||
+ if (flags & CLONE_SETTLS) {
|
||||
+ ret = do_set_thread_area(new_env, newtls, 1);
|
||||
if (ret) {
|
||||
free(new_gdt_table);
|
||||
free(new_env);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
- cpu_x86_load_seg(env, R_CS, new_env->regs[R_CS]);
|
||||
- cpu_x86_load_seg(env, R_DS, new_env->regs[R_DS]);
|
||||
- cpu_x86_load_seg(env, R_ES, new_env->regs[R_ES]);
|
||||
- cpu_x86_load_seg(env, R_SS, new_env->regs[R_SS]);
|
||||
- cpu_x86_load_seg(env, R_FS, new_env->regs[R_FS]);
|
||||
- cpu_x86_load_seg(env, R_GS, new_env->regs[R_GS]);
|
||||
new_env->regs[R_ESP] = newsp;
|
||||
new_env->regs[R_EAX] = 0;
|
||||
#elif defined(TARGET_ARM)
|
||||
if (!newsp)
|
||||
newsp = env->regs[13];
|
||||
@@ -1877,16 +1933,28 @@ int do_fork(CPUState *env, unsigned int
|
||||
#endif
|
||||
new_env->opaque = ts;
|
||||
#ifdef __ia64__
|
||||
- ret = __clone2(clone_func, new_stack + NEW_STACK_SIZE, flags, new_env);
|
||||
+ ret = __clone2(clone_func, new_stack + NEW_STACK_SIZE, flags & ~(CLONE_SETTLS|CLONE_PARENT_SETTID|CLONE_CHILD_CLEARTID), new_env);
|
||||
#else
|
||||
- ret = clone(clone_func, new_stack + NEW_STACK_SIZE, flags, new_env);
|
||||
+ ret = clone(clone_func, new_stack + NEW_STACK_SIZE, flags & ~(CLONE_SETTLS|CLONE_PARENT_SETTID|CLONE_CHILD_CLEARTID), new_env);
|
||||
#endif
|
||||
} else {
|
||||
/* if no CLONE_VM, we consider it is a fork */
|
||||
- if ((flags & ~CSIGNAL) != 0)
|
||||
- return -EINVAL;
|
||||
- ret = fork();
|
||||
+ ret = sys_clone(flags & ~(CLONE_SETTLS|CLONE_PARENT_SETTID|CLONE_CHILD_CLEARTID), 0, g2h(parent_tidptr), NULL, g2h(child_tidptr));
|
||||
+ }
|
||||
+ /* Store child thread ID at location parent_tidptr in parent and child memory.
|
||||
+ Currently this is only done in client memory*/
|
||||
+ if(flags & CLONE_PARENT_SETTID) {
|
||||
+ tput32(parent_tidptr, parent_tid);
|
||||
+ }
|
||||
+
|
||||
+ /* Store child thread ID at location child_tidptr in child memory. */
|
||||
+ if(flags & CLONE_CHILD_SETTID) {
|
||||
+ if(ret==0) { // only in client memory for fork()
|
||||
+ tput32(child_tidptr, gettid());
|
||||
+ } else if(flags & CLONE_VM) { // real threads need it too
|
||||
+ tput32(child_tidptr, ret);
|
||||
+ }
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -2206,7 +2221,7 @@ long do_syscall(void *cpu_env, int num,
|
||||
ret = do_brk(arg1);
|
||||
break;
|
||||
case TARGET_NR_fork:
|
||||
- ret = get_errno(do_fork(cpu_env, SIGCHLD, 0));
|
||||
+ ret = get_errno(do_fork(cpu_env, SIGCHLD, 0, 0,0,0));
|
||||
break;
|
||||
case TARGET_NR_waitpid:
|
||||
{
|
||||
@@ -3281,7 +3297,7 @@ long do_syscall(void *cpu_env, int num,
|
||||
ret = get_errno(fsync(arg1));
|
||||
break;
|
||||
case TARGET_NR_clone:
|
||||
- ret = get_errno(do_fork(cpu_env, arg1, arg2));
|
||||
+ ret = get_errno(do_fork(cpu_env, arg1, arg2,arg3,arg4,arg5));
|
||||
break;
|
||||
#ifdef __NR_exit_group
|
||||
/* new thread calls */
|
||||
@@ -3339,7 +3397,7 @@ long do_syscall(void *cpu_env, int num,
|
||||
ret = do_vm86(cpu_env, arg1, arg2);
|
||||
break;
|
||||
case TARGET_NR_set_thread_area:
|
||||
- ret = get_errno(do_set_thread_area(cpu_env, arg1));
|
||||
+ ret = get_errno(do_set_thread_area(cpu_env, arg1, 0));
|
||||
break;
|
||||
#endif
|
||||
case TARGET_NR_adjtimex:
|
||||
@@ -3635,7 +3651,7 @@ long do_syscall(void *cpu_env, int num,
|
||||
#endif
|
||||
#ifdef TARGET_NR_vfork
|
||||
case TARGET_NR_vfork:
|
||||
- ret = get_errno(do_fork(cpu_env, CLONE_VFORK | CLONE_VM | SIGCHLD, 0));
|
||||
+ ret = get_errno(do_fork(cpu_env, CLONE_VFORK | CLONE_VM | SIGCHLD, 0, 0,0,0));
|
||||
break;
|
||||
#endif
|
||||
#ifdef TARGET_NR_ugetrlimit
|
||||
@@ -4164,6 +4180,11 @@ long do_syscall(void *cpu_env, int num,
|
||||
ret = get_errno(sys_fadvise64((int)arg1, arg2, arg3, (int)arg4));
|
||||
break;
|
||||
#endif
|
||||
+#ifdef TARGET_NR_tgkill
|
||||
+ case TARGET_NR_tgkill:
|
||||
+ ret = get_errno(sys_tgkill((int)arg1, (int)arg2, (int)arg3));
|
||||
+ break;
|
||||
+#endif
|
||||
default:
|
||||
unimplemented:
|
||||
gemu_log("qemu: Unsupported syscall: %d\n", num);
|
@ -1,10 +0,0 @@
|
||||
Index: qemu-0.9.0/linux-user/i386/syscall_nr.h
|
||||
===================================================================
|
||||
--- qemu-0.9.0.orig/linux-user/i386/syscall_nr.h
|
||||
+++ qemu-0.9.0/linux-user/i386/syscall_nr.h
|
||||
@@ -274,3 +274,5 @@
|
||||
#define TARGET_NR_tgkill 270
|
||||
#define TARGET_NR_utimes 271
|
||||
#define TARGET_NR_fadvise64_64 272
|
||||
+
|
||||
+#define TARGET_NR_set_robust_list 311
|
@ -1,32 +0,0 @@
|
||||
Index: qemu-0.9.0/linux-user/syscall.c
|
||||
===================================================================
|
||||
--- qemu-0.9.0.orig/linux-user/syscall.c
|
||||
+++ qemu-0.9.0/linux-user/syscall.c
|
||||
@@ -147,6 +147,7 @@ type name (type1 arg1,type2 arg2,type3 a
|
||||
#define __NR_sys_fadvise64 __NR_fadvise64
|
||||
#define __NR_sys_tgkill __NR_tgkill
|
||||
#define __NR_sys_clone __NR_clone
|
||||
+#define __NR_sys_sched_getaffinity __NR_sched_getaffinity
|
||||
|
||||
#if defined(__alpha__) || defined (__ia64__) || defined(__x86_64__)
|
||||
#define __NR__llseek __NR_lseek
|
||||
@@ -170,6 +171,7 @@ _syscall3(int,sys_syslog,int,type,char*,
|
||||
_syscall4(int,sys_fadvise64,int,fd,loff_t,offset,loff_t,len,int,advice)
|
||||
_syscall3(int,sys_tgkill,int,tgid,int,pid,int,sig)
|
||||
_syscall5(int,sys_clone, int, flags, void *, child_stack, int *, parent_tidptr, struct user_desc *, newtls, int *, child_tidptr)
|
||||
+_syscall3(int,sys_sched_getaffinity,pid_t,pid,unsigned int,cpusetsize,void*,mask)
|
||||
#ifdef __NR_exit_group
|
||||
_syscall1(int,exit_group,int,error_code)
|
||||
#endif
|
||||
@@ -4248,6 +4250,11 @@ long do_syscall(void *cpu_env, int num,
|
||||
ret = get_errno(sys_tgkill((int)arg1, (int)arg2, (int)arg3));
|
||||
break;
|
||||
#endif
|
||||
+#ifdef TARGET_NR_sched_getaffinity
|
||||
+ case TARGET_NR_sched_getaffinity:
|
||||
+ ret = get_errno(sys_sched_getaffinity((pid_t)arg1, (unsigned int)arg2, (void*)arg3));
|
||||
+ break;
|
||||
+#endif
|
||||
default:
|
||||
unimplemented:
|
||||
gemu_log("qemu: Unsupported syscall: %d\n", num);
|
@ -1,22 +0,0 @@
|
||||
Index: qemu-0.9.0/linux-user/syscall.c
|
||||
===================================================================
|
||||
--- qemu-0.9.0.orig/linux-user/syscall.c
|
||||
+++ qemu-0.9.0/linux-user/syscall.c
|
||||
@@ -869,7 +869,7 @@ static long do_getpeername(int fd, targe
|
||||
target_ulong target_addrlen)
|
||||
{
|
||||
socklen_t addrlen = tget32(target_addrlen);
|
||||
- void *addr = alloca(target_addrlen);
|
||||
+ void *addr = alloca(addrlen);
|
||||
long ret;
|
||||
|
||||
gemu_log("getpeername(%d,0x%lx,0x%lx)\n", fd, addr, addrlen);
|
||||
@@ -887,7 +887,7 @@ static long do_getsockname(int fd, targe
|
||||
target_ulong target_addrlen)
|
||||
{
|
||||
socklen_t addrlen = tget32(target_addrlen);
|
||||
- void *addr = alloca(target_addrlen);
|
||||
+ void *addr = alloca(addrlen);
|
||||
long ret;
|
||||
|
||||
ret = get_errno(getsockname(fd, addr, &addrlen));
|
File diff suppressed because it is too large
Load Diff
@ -1,92 +0,0 @@
|
||||
--- linux-user/syscall.c
|
||||
+++ linux-user/syscall.c
|
||||
@@ -140,6 +140,7 @@
|
||||
#define __NR_sys_getdents __NR_getdents
|
||||
#define __NR_sys_getdents64 __NR_getdents64
|
||||
#define __NR_sys_rt_sigqueueinfo __NR_rt_sigqueueinfo
|
||||
+#define __NR_sys_syslog __NR_syslog
|
||||
|
||||
#if defined(__alpha__) || defined (__ia64__) || defined(__x86_64__)
|
||||
#define __NR__llseek __NR_lseek
|
||||
@@ -159,6 +160,7 @@
|
||||
_syscall5(int, _llseek, uint, fd, ulong, hi, ulong, lo,
|
||||
loff_t *, res, uint, wh);
|
||||
_syscall3(int,sys_rt_sigqueueinfo,int,pid,int,sig,siginfo_t *,uinfo)
|
||||
+_syscall3(int,sys_syslog,int,type,char*,bufp,int,len)
|
||||
#ifdef __NR_exit_group
|
||||
_syscall1(int,exit_group,int,error_code)
|
||||
#endif
|
||||
@@ -172,6 +174,7 @@
|
||||
extern int setresgid(gid_t, gid_t, gid_t);
|
||||
extern int getresgid(gid_t *, gid_t *, gid_t *);
|
||||
extern int setgroups(int, gid_t *);
|
||||
+extern int uselib(const char*);
|
||||
|
||||
static inline long get_errno(long ret)
|
||||
{
|
||||
@@ -2709,7 +2712,9 @@
|
||||
}
|
||||
break;
|
||||
case TARGET_NR_uselib:
|
||||
- goto unimplemented;
|
||||
+ ret = get_errno(uselib(path((const char*)arg1)));
|
||||
+ break;
|
||||
+
|
||||
case TARGET_NR_swapon:
|
||||
p = lock_user_string(arg1);
|
||||
ret = get_errno(swapon(p, arg2));
|
||||
@@ -2949,7 +2954,9 @@
|
||||
#endif
|
||||
|
||||
case TARGET_NR_syslog:
|
||||
- goto unimplemented;
|
||||
+ ret = get_errno(sys_syslog((int)arg1, (char*)arg2, (int)arg3));
|
||||
+ break;
|
||||
+
|
||||
case TARGET_NR_setitimer:
|
||||
{
|
||||
struct itimerval value, ovalue, *pvalue;
|
||||
@@ -3824,7 +3831,9 @@
|
||||
goto unimplemented;
|
||||
#ifdef TARGET_NR_mincore
|
||||
case TARGET_NR_mincore:
|
||||
- goto unimplemented;
|
||||
+ page_unprotect_range((void*)arg3, ((size_t)arg2 + TARGET_PAGE_SIZE - 1) / TARGET_PAGE_SIZE);
|
||||
+ ret = get_errno(mincore((void*)arg1, (size_t)arg2, (unsigned char*)arg3));
|
||||
+ break;
|
||||
#endif
|
||||
#ifdef TARGET_NR_madvise
|
||||
case TARGET_NR_madvise:
|
||||
@@ -3921,7 +3930,8 @@
|
||||
ret = get_errno(gettid());
|
||||
break;
|
||||
case TARGET_NR_readahead:
|
||||
- goto unimplemented;
|
||||
+ ret = get_errno(readahead((int)arg1, (off64_t)arg2, (size_t)arg3));
|
||||
+ break;
|
||||
#ifdef TARGET_NR_setxattr
|
||||
case TARGET_NR_setxattr:
|
||||
case TARGET_NR_lsetxattr:
|
||||
@@ -3946,6 +3956,22 @@
|
||||
case TARGET_NR_getdomainname:
|
||||
goto unimplemented_nowarn;
|
||||
#endif
|
||||
+#ifdef TARGET_NR_clock_gettime
|
||||
+ case TARGET_NR_clock_gettime:
|
||||
+ {
|
||||
+ struct target_timespec* ttp = (struct target_timespec*)arg2;
|
||||
+ struct timespec htp;
|
||||
+ if(ttp) {
|
||||
+ htp.tv_sec = tswapl(ttp->tv_sec);
|
||||
+ htp.tv_nsec = tswapl(ttp->tv_nsec);
|
||||
+ ret = get_errno(clock_gettime((clockid_t)arg1, &htp));
|
||||
+ ttp->tv_sec = tswapl(htp.tv_sec);
|
||||
+ ttp->tv_nsec = tswapl(htp.tv_nsec);
|
||||
+ } else
|
||||
+ ret = get_errno(clock_gettime((clockid_t)arg1, NULL));
|
||||
+ break;
|
||||
+ }
|
||||
+#endif
|
||||
default:
|
||||
unimplemented:
|
||||
gemu_log("qemu: Unsupported syscall: %d\n", num);
|
@ -1,12 +0,0 @@
|
||||
Index: qemu-0.9.0/linux-user/main.c
|
||||
===================================================================
|
||||
--- qemu-0.9.0.orig/linux-user/main.c
|
||||
+++ qemu-0.9.0/linux-user/main.c
|
||||
@@ -1787,6 +1787,7 @@ int main(int argc, char **argv)
|
||||
cpu_x86_load_seg(env, R_FS, __USER_DS);
|
||||
cpu_x86_load_seg(env, R_GS, __USER_DS);
|
||||
|
||||
+ env->segs[R_FS].selector = 0;
|
||||
#elif defined(TARGET_ARM)
|
||||
{
|
||||
int i;
|
@ -1,79 +0,0 @@
|
||||
2007-03-13 Gwenole Beauchesne <gbeauchesne@mandriva.com>
|
||||
|
||||
* dyngen-exec.h (AREG4, AREG5): Temporarily disable for KVM support.
|
||||
|
||||
2007-02-03 Gwenole Beauchesne <gbeauchesne@mandriva.com>
|
||||
|
||||
* dyngen-exec.h (AREG4, AREG5): Enable when building with GCC4.
|
||||
|
||||
2005-06-04 Gwenole Beauchesne <gbeauchesne@mandriva.com>
|
||||
|
||||
* Add direct jump support to x86-64.
|
||||
|
||||
================================================================================
|
||||
--- qemu-0.9.0/dyngen-exec.h
|
||||
+++ qemu-0.9.0/dyngen-exec.h
|
||||
@@ -95,8 +95,11 @@
|
||||
#define AREG1 "rbx"
|
||||
#define AREG2 "r12"
|
||||
#define AREG3 "r13"
|
||||
-//#define AREG4 "r14"
|
||||
-//#define AREG5 "r15"
|
||||
+#if __GNUC__ >= 4 && ! USE_KVM
|
||||
+/* XXX: earlier GCC crashes */
|
||||
+#define AREG4 "r14"
|
||||
+#define AREG5 "r15"
|
||||
+#endif
|
||||
#endif
|
||||
#ifdef __powerpc__
|
||||
#define AREG0 "r27"
|
||||
--- qemu-0.9.0/dyngen.c
|
||||
+++ qemu-0.9.0/dyngen.c
|
||||
@@ -2614,6 +2614,17 @@
|
||||
if (rel->r_offset >= start_offset &&
|
||||
rel->r_offset < start_offset + copy_size) {
|
||||
sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name;
|
||||
+ if (strstart(sym_name, "__op_jmp", &p)) {
|
||||
+ int n;
|
||||
+ n = strtol(p, NULL, 10);
|
||||
+ /* __op_jmp relocations are done at
|
||||
+ runtime to do translated block
|
||||
+ chaining: the offset of the instruction
|
||||
+ needs to be stored */
|
||||
+ fprintf(outfile, " jmp_offsets[%d] = %d + (gen_code_ptr - gen_code_buf);\n",
|
||||
+ n, rel->r_offset - start_offset);
|
||||
+ continue;
|
||||
+ }
|
||||
get_reloc_expr(name, sizeof(name), sym_name);
|
||||
type = ELF32_R_TYPE(rel->r_info);
|
||||
addend = rel->r_addend;
|
||||
--- qemu-0.9.0/exec-all.h
|
||||
+++ qemu-0.9.0/exec-all.h
|
||||
@@ -159,6 +159,9 @@
|
||||
#if defined(__i386__) && !defined(_WIN32)
|
||||
#define USE_DIRECT_JUMP
|
||||
#endif
|
||||
+#if defined(__x86_64__)
|
||||
+#define USE_DIRECT_JUMP
|
||||
+#endif
|
||||
|
||||
typedef struct TranslationBlock {
|
||||
target_ulong pc; /* simulated PC corresponding to this block (EIP + CS base) */
|
||||
@@ -245,7 +248,7 @@
|
||||
asm volatile ("sync" : : : "memory");
|
||||
asm volatile ("isync" : : : "memory");
|
||||
}
|
||||
-#elif defined(__i386__)
|
||||
+#elif defined(__i386__) || defined(__x86_64__)
|
||||
static inline void tb_set_jmp_target1(unsigned long jmp_addr, unsigned long addr)
|
||||
{
|
||||
/* patch the branch destination */
|
||||
@@ -324,7 +327,7 @@
|
||||
"1:\n");\
|
||||
} while (0)
|
||||
|
||||
-#elif defined(__i386__) && defined(USE_DIRECT_JUMP)
|
||||
+#elif (defined(__i386__) || defined(__x86_64__)) && defined(USE_DIRECT_JUMP)
|
||||
|
||||
/* we patch the jump instruction directly. Use sti in place of the actual
|
||||
jmp instruction so that dyngen can patch in the correct result. */
|
3
qemu-0.9.0.cvs.tar.bz2
Normal file
3
qemu-0.9.0.cvs.tar.bz2
Normal file
@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:b21915f6e941724eba05dce9b0f96295e4f7ff69b7ea0f743f5798c678b8839e
|
||||
size 2043438
|
@ -1,35 +0,0 @@
|
||||
--- linux-user/signal.c
|
||||
+++ linux-user/signal.c 2007/02/12 12:47:45
|
||||
@@ -389,6 +389,8 @@
|
||||
{
|
||||
int sig;
|
||||
target_siginfo_t tinfo;
|
||||
+
|
||||
+ //printf("host_signal_handler, signum %d\n",host_signum);
|
||||
|
||||
/* the CPU emulator uses some host signals to detect exceptions,
|
||||
we we forward to it some signals */
|
||||
--- Makefile
|
||||
+++ Makefile 2007/02/12 12:48:38
|
||||
@@ -27,7 +27,7 @@
|
||||
ifndef CONFIG_DARWIN
|
||||
ifndef CONFIG_WIN32
|
||||
ifndef CONFIG_SOLARIS
|
||||
-LIBS+=-lrt
|
||||
+LIBS+=-lrt -lpthread
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
--- Makefile.target
|
||||
+++ Makefile.target 2007/02/12 12:47:45
|
||||
@@ -181,8 +181,8 @@
|
||||
|
||||
#########################################################
|
||||
|
||||
-CPPFLAGS+=-D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE
|
||||
-LIBS+=-lm
|
||||
+CPPFLAGS+=-D_GNU_SOURCE -D_BSD_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE
|
||||
+LIBS+=-lm -lrt -lpthread
|
||||
ifndef CONFIG_USER_ONLY
|
||||
LIBS+=-lz
|
||||
endif
|
@ -1,3 +0,0 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:1ce3d34e3fafde6a3802f3c6317dac14f6b482fa918df0d3af54edd8b0314242
|
||||
size 1625107
|
67
qemu-cvs-alsa_bitfield.patch
Normal file
67
qemu-cvs-alsa_bitfield.patch
Normal file
@ -0,0 +1,67 @@
|
||||
Index: qemu/thunk.h
|
||||
===================================================================
|
||||
--- qemu.orig/thunk.h
|
||||
+++ qemu/thunk.h
|
||||
@@ -38,6 +38,7 @@ typedef enum argtype {
|
||||
TYPE_PTR,
|
||||
TYPE_ARRAY,
|
||||
TYPE_STRUCT,
|
||||
+ TYPE_INTBITFIELD,
|
||||
} argtype;
|
||||
|
||||
#define MK_PTR(type) TYPE_PTR, type
|
||||
@@ -87,6 +88,7 @@ static inline int thunk_type_size(const
|
||||
case TYPE_SHORT:
|
||||
return 2;
|
||||
case TYPE_INT:
|
||||
+ case TYPE_INTBITFIELD:
|
||||
return 4;
|
||||
case TYPE_LONGLONG:
|
||||
case TYPE_ULONGLONG:
|
||||
@@ -124,6 +126,7 @@ static inline int thunk_type_align(const
|
||||
case TYPE_SHORT:
|
||||
return 2;
|
||||
case TYPE_INT:
|
||||
+ case TYPE_INTBITFIELD:
|
||||
return 4;
|
||||
case TYPE_LONGLONG:
|
||||
case TYPE_ULONGLONG:
|
||||
Index: qemu/thunk.c
|
||||
===================================================================
|
||||
--- qemu.orig/thunk.c
|
||||
+++ qemu/thunk.c
|
||||
@@ -40,6 +40,7 @@ static inline const argtype *thunk_type_
|
||||
case TYPE_CHAR:
|
||||
case TYPE_SHORT:
|
||||
case TYPE_INT:
|
||||
+ case TYPE_INTBITFIELD:
|
||||
case TYPE_LONGLONG:
|
||||
case TYPE_ULONGLONG:
|
||||
case TYPE_LONG:
|
||||
@@ -132,6 +133,26 @@ const argtype *thunk_convert(void *dst,
|
||||
case TYPE_INT:
|
||||
*(uint32_t *)dst = tswap32(*(uint32_t *)src);
|
||||
break;
|
||||
+ case TYPE_INTBITFIELD:
|
||||
+#if defined(TARGET_I386) && defined(__powerpc__)
|
||||
+ /* powerpc uses the MSB, whereas i386 uses the LSB
|
||||
+ * to store the first bit in a field */
|
||||
+ {
|
||||
+ unsigned char byte = *(uint8_t *)src;
|
||||
+ *(uint8_t *)dst = ((byte >> 7) & 1)
|
||||
+ | ((byte >> 5) & 2)
|
||||
+ | ((byte >> 3) & 4)
|
||||
+ | ((byte >> 1) & 8)
|
||||
+ | ((byte << 1) & 16)
|
||||
+ | ((byte << 3) & 32)
|
||||
+ | ((byte << 5) & 64)
|
||||
+ | ((byte << 7) & 128);
|
||||
+ /* FIXME: implement for bitfields > 1 byte and other archs */
|
||||
+ }
|
||||
+#else
|
||||
+ *(uint32_t *)dst = tswap32(*(uint32_t *)src);
|
||||
+#endif
|
||||
+ break;
|
||||
case TYPE_LONGLONG:
|
||||
case TYPE_ULONGLONG:
|
||||
*(uint64_t *)dst = tswap64(*(uint64_t *)src);
|
3592
qemu-cvs-alsa_ioctl.patch
Normal file
3592
qemu-cvs-alsa_ioctl.patch
Normal file
File diff suppressed because it is too large
Load Diff
32
qemu-cvs-alsa_mmap.patch
Normal file
32
qemu-cvs-alsa_mmap.patch
Normal file
@ -0,0 +1,32 @@
|
||||
Index: qemu/linux-user/mmap.c
|
||||
===================================================================
|
||||
--- qemu.orig/linux-user/mmap.c
|
||||
+++ qemu/linux-user/mmap.c
|
||||
@@ -152,6 +152,9 @@ static int mmap_frag(target_ulong real_s
|
||||
return 0;
|
||||
}
|
||||
|
||||
+#define SNDRV_PCM_MMAP_OFFSET_STATUS 0x80000000
|
||||
+#define SNDRV_PCM_MMAP_OFFSET_CONTROL 0x81000000
|
||||
+
|
||||
/* NOTE: all the constants are the HOST ones */
|
||||
long target_mmap(target_ulong start, target_ulong len, int prot,
|
||||
int flags, int fd, target_ulong offset)
|
||||
@@ -192,6 +195,17 @@ long target_mmap(target_ulong start, tar
|
||||
}
|
||||
#endif
|
||||
|
||||
+ /* Alsa tries to communcate with the kernel via mmap. This usually
|
||||
+ * is a good idea when user- and kernelspace are running on the
|
||||
+ * same architecture but does not work out when not. To make alsa
|
||||
+ * not to use mmap, we can just have it fail on the mmap calls that
|
||||
+ * would initiate this.
|
||||
+ */
|
||||
+ if(offset == SNDRV_PCM_MMAP_OFFSET_STATUS || offset == SNDRV_PCM_MMAP_OFFSET_CONTROL) {
|
||||
+ errno = EINVAL;
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
if (offset & ~TARGET_PAGE_MASK) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
13
qemu-cvs-flash.patch
Normal file
13
qemu-cvs-flash.patch
Normal file
@ -0,0 +1,13 @@
|
||||
Index: qemu/linux-user/syscall.c
|
||||
===================================================================
|
||||
--- qemu.orig/linux-user/syscall.c
|
||||
+++ qemu/linux-user/syscall.c
|
||||
@@ -1736,6 +1736,8 @@ static long do_ipc(long call, long first
|
||||
|
||||
switch (call) {
|
||||
case IPCOP_semop:
|
||||
+ ret = -EINVAL;
|
||||
+ break;
|
||||
{
|
||||
struct sembuf *target_sops;
|
||||
int i;
|
125
qemu-cvs-futex.patch
Normal file
125
qemu-cvs-futex.patch
Normal file
@ -0,0 +1,125 @@
|
||||
Index: qemu.bkp/linux-user/syscall.c
|
||||
===================================================================
|
||||
--- qemu.bkp.orig/linux-user/syscall.c
|
||||
+++ qemu.bkp/linux-user/syscall.c
|
||||
@@ -17,6 +17,8 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
+
|
||||
+#define __user
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
@@ -60,6 +62,7 @@
|
||||
#define tchars host_tchars /* same as target */
|
||||
#define ltchars host_ltchars /* same as target */
|
||||
|
||||
+#include <linux/futex.h>
|
||||
#include <linux/termios.h>
|
||||
#include <linux/unistd.h>
|
||||
#include <linux/utsname.h>
|
||||
@@ -2554,6 +2557,91 @@ static inline void host_to_target_timesp
|
||||
unlock_user_struct(target_ts, target_addr, 1);
|
||||
}
|
||||
|
||||
+#ifdef BSWAP_NEEDED
|
||||
+static int futex_op(int oldval, int op, int oparg)
|
||||
+{
|
||||
+ int retval = oparg;
|
||||
+ switch(op) {
|
||||
+ case FUTEX_OP_SET: break;
|
||||
+ case FUTEX_OP_ADD: retval += oparg; break;
|
||||
+ case FUTEX_OP_OR: retval |= oparg; break;
|
||||
+ case FUTEX_OP_ANDN: retval &= oparg; break;
|
||||
+ case FUTEX_OP_XOR: retval ^= oparg; break;
|
||||
+ }
|
||||
+ return retval;
|
||||
+}
|
||||
+
|
||||
+static int futex_cmp(int oldval, int cmp, int cmparg)
|
||||
+{
|
||||
+ switch(cmp) {
|
||||
+ case FUTEX_OP_CMP_EQ: return oldval == cmparg;
|
||||
+ case FUTEX_OP_CMP_NE: return oldval != cmparg;
|
||||
+ case FUTEX_OP_CMP_LT: return oldval < cmparg;
|
||||
+ case FUTEX_OP_CMP_LE: return oldval <= cmparg;
|
||||
+ case FUTEX_OP_CMP_GT: return oldval > cmparg;
|
||||
+ case FUTEX_OP_CMP_GE: return oldval >= cmparg;
|
||||
+ }
|
||||
+ return -1;
|
||||
+}
|
||||
+#endif
|
||||
+
|
||||
+static long do_futex(target_ulong uaddr, int op, uint32_t val,
|
||||
+ target_ulong utime, target_ulong uaddr2,
|
||||
+ uint32_t val3)
|
||||
+{
|
||||
+ struct timespec host_utime;
|
||||
+ unsigned long val2 = utime;
|
||||
+ long retval;
|
||||
+
|
||||
+ if (utime && (op == FUTEX_WAIT || op == FUTEX_LOCK_PI)) {
|
||||
+ target_to_host_timespec(&host_utime, utime);
|
||||
+ val2 = (unsigned long)&host_utime;
|
||||
+ }
|
||||
+
|
||||
+#ifdef BSWAP_NEEDED
|
||||
+ switch(op) {
|
||||
+ case FUTEX_CMP_REQUEUE:
|
||||
+ val3 = tswap32(val3);
|
||||
+ case FUTEX_REQUEUE:
|
||||
+ val2 = tswap32(val2);
|
||||
+ case FUTEX_WAIT:
|
||||
+ case FUTEX_WAKE:
|
||||
+ case FUTEX_WAKE_OP:
|
||||
+ val = tswap32(val);
|
||||
+ case FUTEX_LOCK_PI: /* This one's icky, but comes out OK */
|
||||
+ case FUTEX_UNLOCK_PI:
|
||||
+ break;
|
||||
+ default:
|
||||
+ gemu_log("qemu: Unsupported futex op %d\n", op);
|
||||
+ return -ENOSYS;
|
||||
+ }
|
||||
+ if (op == FUTEX_WAKE_OP) {
|
||||
+ /* Need to munge the secondary operation (val3) */
|
||||
+ gemu_log("qemu: Tricky FUTEX_WAKE_OP - trying to emulate it\n");
|
||||
+ val3 = tswap32(val3);
|
||||
+ int op2 = (val3 >> 28) & 0xf;
|
||||
+ int cmp = (val3 >> 24) & 0xf;
|
||||
+ int oparg = (val3 >> 12) & 0xfff;
|
||||
+ int cmparg = val3 & 0xfff;
|
||||
+ int shift = val3 & (FUTEX_OP_OPARG_SHIFT << 28);
|
||||
+ int oldval = tget32(uaddr2);
|
||||
+ if (shift)
|
||||
+ oparg = 1 << oparg;
|
||||
+
|
||||
+ tput32(uaddr2,futex_op(oldval, op2, oparg));
|
||||
+ retval = syscall(__NR_futex, g2h(uaddr), FUTEX_WAKE, val, 0, 0, 0);
|
||||
+ if(futex_cmp(oldval, cmp, cmparg)) {
|
||||
+ retval = syscall(__NR_futex, g2h(uaddr2), FUTEX_WAKE, val2, 0, 0, 0);
|
||||
+ }
|
||||
+ } else {
|
||||
+ retval = syscall(__NR_futex, g2h(uaddr), op, val, val2, g2h(uaddr2), val3);
|
||||
+ }
|
||||
+#else
|
||||
+ retval = syscall(__NR_futex, g2h(uaddr), op, val, val2, g2h(uaddr2), val3);
|
||||
+#endif
|
||||
+ return retval;
|
||||
+}
|
||||
+
|
||||
long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3,
|
||||
long arg4, long arg5, long arg6)
|
||||
{
|
||||
@@ -4713,6 +4801,11 @@ long do_syscall(void *cpu_env, int num,
|
||||
}
|
||||
#endif
|
||||
|
||||
+#ifdef TARGET_NR_futex
|
||||
+ case TARGET_NR_futex:
|
||||
+ ret = get_errno(do_futex(arg1, arg2, arg3, arg4, arg5, arg6));
|
||||
+ break;
|
||||
+#endif
|
||||
#if defined(TARGET_NR_set_tid_address) && defined(__NR_set_tid_address)
|
||||
case TARGET_NR_set_tid_address:
|
||||
ret = get_errno(set_tid_address((int *) arg1));
|
34
qemu-cvs-gettimeofday.patch
Normal file
34
qemu-cvs-gettimeofday.patch
Normal file
@ -0,0 +1,34 @@
|
||||
Index: qemu/linux-user/syscall.c
|
||||
===================================================================
|
||||
--- qemu.orig/linux-user/syscall.c
|
||||
+++ qemu/linux-user/syscall.c
|
||||
@@ -3596,6 +3596,7 @@ long do_syscall(void *cpu_env, int num,
|
||||
case TARGET_NR_gettimeofday:
|
||||
{
|
||||
struct timeval tv;
|
||||
+ target_to_host_timeval(&tv, arg1);
|
||||
ret = get_errno(gettimeofday(&tv, NULL));
|
||||
if (!is_error(ret)) {
|
||||
host_to_target_timeval(arg1, &tv);
|
||||
Index: qemu/linux-user/signal.c
|
||||
===================================================================
|
||||
--- qemu.orig/linux-user/signal.c
|
||||
+++ qemu/linux-user/signal.c
|
||||
@@ -207,6 +207,8 @@ static inline void host_to_target_siginf
|
||||
/* should never come here, but who knows. The information for
|
||||
the target is irrelevant */
|
||||
tinfo->_sifields._sigfault._addr = 0;
|
||||
+ } else if (sig == SIGIO) {
|
||||
+ tinfo->_sifields._sigpoll._fd = info->si_fd;
|
||||
} else if (sig >= TARGET_SIGRTMIN) {
|
||||
tinfo->_sifields._rt._pid = info->si_pid;
|
||||
tinfo->_sifields._rt._uid = info->si_uid;
|
||||
@@ -228,6 +230,8 @@ static void tswap_siginfo(target_siginfo
|
||||
sig == SIGBUS || sig == SIGTRAP) {
|
||||
tinfo->_sifields._sigfault._addr =
|
||||
tswapl(info->_sifields._sigfault._addr);
|
||||
+ } else if (sig == SIGIO) {
|
||||
+ tinfo->_sifields._sigpoll._fd = tswap32(info->_sifields._sigpoll._fd);
|
||||
} else if (sig >= TARGET_SIGRTMIN) {
|
||||
tinfo->_sifields._rt._pid = tswap32(info->_sifields._rt._pid);
|
||||
tinfo->_sifields._rt._uid = tswap32(info->_sifields._rt._uid);
|
47
qemu-cvs-ia64.patch
Normal file
47
qemu-cvs-ia64.patch
Normal file
@ -0,0 +1,47 @@
|
||||
--- Makefile.target.~1.186.~ 2007-07-02 17:08:34.000000000 +0200
|
||||
+++ Makefile.target 2007-07-09 19:13:35.000000000 +0200
|
||||
@@ -92,6 +92,8 @@ cc-option = $(shell if $(CC) $(OP_CFLAGS
|
||||
OP_CFLAGS+=$(call cc-option, -fno-reorder-blocks, "")
|
||||
OP_CFLAGS+=$(call cc-option, -fno-gcse, "")
|
||||
OP_CFLAGS+=$(call cc-option, -fno-tree-ch, "")
|
||||
+OP_CFLAGS+=$(call cc-option, -fno-tree-dominator-opts, "")
|
||||
+OP_CFLAGS+=$(call cc-option, -fno-tree-vrp, "")
|
||||
OP_CFLAGS+=$(call cc-option, -fno-optimize-sibling-calls, "")
|
||||
OP_CFLAGS+=$(call cc-option, -fno-crossjumping, "")
|
||||
OP_CFLAGS+=$(call cc-option, -fno-align-labels, "")
|
||||
@@ -165,8 +167,9 @@ BASE_LDFLAGS+=-Wl,-T,$(SRC_PATH)/$(ARCH)
|
||||
endif
|
||||
|
||||
ifeq ($(ARCH),ia64)
|
||||
-BASE_CFLAGS+=-mno-sdata
|
||||
-OP_CFLAGS+=-mno-sdata
|
||||
+OP_CFLAGS+=$(call cc-option, -mno-sched-ar-data-spec, "")
|
||||
+BASE_CFLAGS+=-G0 -mno-sdata
|
||||
+OP_CFLAGS+=-G0 -mno-sdata
|
||||
BASE_LDFLAGS+=-Wl,-G0 -Wl,-T,$(SRC_PATH)/$(ARCH).ld
|
||||
endif
|
||||
|
||||
--- target-alpha/op.c.~1.1.~ 2007-04-05 08:58:33.000000000 +0200
|
||||
+++ target-alpha/op.c 2007-07-09 20:11:42.000000000 +0200
|
||||
@@ -18,8 +18,6 @@
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
-#define DEBUG_OP
|
||||
-
|
||||
#include "config.h"
|
||||
#include "exec.h"
|
||||
|
||||
@@ -125,8 +123,12 @@
|
||||
void OPPROTO op_no_op (void)
|
||||
{
|
||||
#if !defined (DEBUG_OP)
|
||||
+#ifdef __ia64__
|
||||
+ __asm__ __volatile__("nop 0" : : : "memory");
|
||||
+#else
|
||||
__asm__ __volatile__("nop" : : : "memory");
|
||||
#endif
|
||||
+#endif
|
||||
RETURN();
|
||||
}
|
||||
|
11
qemu-cvs-img.patch
Normal file
11
qemu-cvs-img.patch
Normal file
@ -0,0 +1,11 @@
|
||||
--- Makefile.orig 2007-07-05 14:43:40.000000000 +0000
|
||||
+++ Makefile 2007-07-05 14:46:50.000000000 +0000
|
||||
@@ -33,7 +33,7 @@
|
||||
recurse-all: $(patsubst %,subdir-%, $(TARGET_DIRS))
|
||||
|
||||
qemu-img$(EXESUF): qemu-img.c cutils.c block.c block-raw.c block-cow.c block-qcow.c aes.c block-vmdk.c block-cloop.c block-dmg.c block-bochs.c block-vpc.c block-vvfat.c block-qcow2.c
|
||||
- $(CC) -DQEMU_TOOL $(CFLAGS) $(CPPFLAGS) $(BASE_CFLAGS) $(LDFLAGS) $(BASE_LDFLAGS) -o $@ $^ -lz $(LIBS)
|
||||
+ $(CC) -DQEMU_TOOL $(CFLAGS) $(CPPFLAGS) $(BASE_CFLAGS) $(LDFLAGS) -o $@ $^ -lz $(LIBS)
|
||||
|
||||
dyngen$(EXESUF): dyngen.c
|
||||
$(HOST_CC) $(CFLAGS) $(CPPFLAGS) $(BASE_CFLAGS) -o $@ $^
|
18
qemu-cvs-ioctl_debug.patch
Normal file
18
qemu-cvs-ioctl_debug.patch
Normal file
@ -0,0 +1,18 @@
|
||||
Index: qemu/linux-user/syscall.c
|
||||
===================================================================
|
||||
--- qemu.orig/linux-user/syscall.c
|
||||
+++ qemu/linux-user/syscall.c
|
||||
@@ -1950,7 +1950,12 @@ static long do_ioctl(long fd, long cmd,
|
||||
ie = ioctl_entries;
|
||||
for(;;) {
|
||||
if (ie->target_cmd == 0) {
|
||||
- gemu_log("Unsupported ioctl: cmd=0x%04lx\n", cmd);
|
||||
+ int i;
|
||||
+ gemu_log("Unsupported ioctl: cmd=0x%04lx (%x)\n", cmd, (cmd & (TARGET_IOC_SIZEMASK << TARGET_IOC_SIZESHIFT)) >> TARGET_IOC_SIZESHIFT);
|
||||
+ for(i=0;ioctl_entries[i].target_cmd;i++) {
|
||||
+ if((ioctl_entries[i].target_cmd & ~(TARGET_IOC_SIZEMASK << TARGET_IOC_SIZESHIFT)) == (cmd & ~(TARGET_IOC_SIZEMASK << TARGET_IOC_SIZESHIFT)))
|
||||
+ gemu_log("%p\t->\t%s (%x)\n", ioctl_entries[i].host_cmd, ioctl_entries[i].name, (ioctl_entries[i].target_cmd & (TARGET_IOC_SIZEMASK << TARGET_IOC_SIZESHIFT)) >> TARGET_IOC_SIZESHIFT);
|
||||
+ }
|
||||
return -ENOSYS;
|
||||
}
|
||||
if (ie->target_cmd == cmd)
|
24
qemu-cvs-ioctl_nodirection.patch
Normal file
24
qemu-cvs-ioctl_nodirection.patch
Normal file
@ -0,0 +1,24 @@
|
||||
Index: qemu/linux-user/syscall.c
|
||||
===================================================================
|
||||
--- qemu.orig/linux-user/syscall.c
|
||||
+++ qemu/linux-user/syscall.c
|
||||
@@ -1980,6 +1980,11 @@ static long do_ioctl(long fd, long cmd,
|
||||
arg_type++;
|
||||
target_size = thunk_type_size(arg_type, 0);
|
||||
switch(ie->access) {
|
||||
+ /* FIXME: actually the direction given in the ioctl should be
|
||||
+ * correct so we can assume the communication is uni-directional.
|
||||
+ * The alsa developers did not like this concept though and
|
||||
+ * declared ioctls IOC_R and IOC_W even though they were IOC_RW.*/
|
||||
+/*
|
||||
case IOC_R:
|
||||
ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp));
|
||||
if (!is_error(ret)) {
|
||||
@@ -1994,6 +1999,7 @@ static long do_ioctl(long fd, long cmd,
|
||||
unlock_user(argptr, arg, 0);
|
||||
ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp));
|
||||
break;
|
||||
+*/
|
||||
default:
|
||||
case IOC_RW:
|
||||
argptr = lock_user(arg, target_size, 1);
|
341
qemu-cvs-ipc.patch
Normal file
341
qemu-cvs-ipc.patch
Normal file
@ -0,0 +1,341 @@
|
||||
Index: qemu/linux-user/syscall.c
|
||||
===================================================================
|
||||
--- qemu.orig/linux-user/syscall.c
|
||||
+++ qemu/linux-user/syscall.c
|
||||
@@ -29,7 +29,7 @@
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <time.h>
|
||||
-#include <sys/types.h>
|
||||
+#include <linux/types.h>
|
||||
#include <sys/ipc.h>
|
||||
#include <sys/msg.h>
|
||||
#include <sys/wait.h>
|
||||
@@ -46,6 +46,9 @@
|
||||
#include <sys/uio.h>
|
||||
#include <sys/poll.h>
|
||||
#include <sys/times.h>
|
||||
+#include <asm/ipcbuf.h>
|
||||
+#include <asm/shmbuf.h>
|
||||
+#include <asm/sembuf.h>
|
||||
#include <sys/shm.h>
|
||||
#include <sys/sem.h>
|
||||
#include <sys/statfs.h>
|
||||
@@ -150,6 +153,7 @@ type name (type1 arg1,type2 arg2,type3 a
|
||||
#define __NR_sys_tgkill __NR_tgkill
|
||||
#define __NR_sys_clone __NR_clone
|
||||
#define __NR_sys_sched_getaffinity __NR_sched_getaffinity
|
||||
+#define __NR_sys_ipc __NR_ipc
|
||||
|
||||
#if defined(__alpha__) || defined (__ia64__) || defined(__x86_64__)
|
||||
#define __NR__llseek __NR_lseek
|
||||
@@ -172,6 +176,10 @@ _syscall3(int,sys_rt_sigqueueinfo,int,pi
|
||||
_syscall3(int,sys_syslog,int,type,char*,bufp,int,len)
|
||||
_syscall3(int,sys_tgkill,int,tgid,int,pid,int,sig)
|
||||
_syscall5(int,sys_clone, int, flags, void *, child_stack, int *, parent_tidptr, void *, newtls, int *, child_tidptr)
|
||||
+#ifdef __NR_ipc
|
||||
+_syscall6(int,sys_ipc, long, call, long, first, long, second, long, third, void *, ptr, long, fifth)
|
||||
+#define semctl(a,b,c,d) sys_ipc(IPCOP_semctl,a,b,c,&d,0l)
|
||||
+#endif
|
||||
_syscall3(int,sys_sched_getaffinity,pid_t,pid,unsigned int,cpusetsize,void*,mask)
|
||||
#ifdef __NR_exit_group
|
||||
_syscall1(int,exit_group,int,error_code)
|
||||
@@ -1255,6 +1263,21 @@ struct target_ipc_perm
|
||||
target_ulong __unused2;
|
||||
};
|
||||
|
||||
+struct target_ipc64_perm
|
||||
+{
|
||||
+ int key;
|
||||
+ unsigned int uid;
|
||||
+ unsigned int gid;
|
||||
+ unsigned int cuid;
|
||||
+ unsigned int cgid;
|
||||
+ unsigned short mode;
|
||||
+ unsigned short __pad1;
|
||||
+ unsigned short seq;
|
||||
+ unsigned short __pad2;
|
||||
+ target_ulong __unused1;
|
||||
+ target_ulong __unused2;
|
||||
+};
|
||||
+
|
||||
struct target_semid_ds
|
||||
{
|
||||
struct target_ipc_perm sem_perm;
|
||||
@@ -1267,6 +1290,18 @@ struct target_semid_ds
|
||||
target_ulong __unused4;
|
||||
};
|
||||
|
||||
+struct target_semid64_ds
|
||||
+{
|
||||
+ struct target_ipc64_perm sem_perm;
|
||||
+ target_ulong sem_otime;
|
||||
+ target_ulong __unused1;
|
||||
+ target_ulong sem_ctime;
|
||||
+ target_ulong __unused2;
|
||||
+ target_ulong sem_nsems;
|
||||
+ target_ulong __unused3;
|
||||
+ target_ulong __unused4;
|
||||
+};
|
||||
+
|
||||
static inline void target_to_host_ipc_perm(struct ipc_perm *host_ip,
|
||||
target_ulong target_addr)
|
||||
{
|
||||
@@ -1301,6 +1336,41 @@ static inline void host_to_target_ipc_pe
|
||||
unlock_user_struct(target_sd, target_addr, 1);
|
||||
}
|
||||
|
||||
+static inline void target_to_host_ipc64_perm( struct ipc64_perm *host_ip, target_ulong target_addr )
|
||||
+{
|
||||
+ struct target_ipc64_perm *target_ip;
|
||||
+ struct target_semid64_ds *target_sd;
|
||||
+
|
||||
+ lock_user_struct(target_sd, target_addr, 1);
|
||||
+ target_ip=&(target_sd->sem_perm);
|
||||
+ host_ip->key = tswapl(target_ip->key);
|
||||
+ host_ip->uid = tswapl(target_ip->uid);
|
||||
+ host_ip->gid = tswapl(target_ip->gid);
|
||||
+ host_ip->cuid = tswapl(target_ip->cuid);
|
||||
+ host_ip->cgid = tswapl(target_ip->cgid);
|
||||
+ host_ip->mode = tswap16(target_ip->mode);
|
||||
+ host_ip->seq = tswap16(target_ip->seq);
|
||||
+ unlock_user_struct(target_sd, target_addr, 1);
|
||||
+}
|
||||
+
|
||||
+static inline void host_to_target_ipc64_perm(target_ulong target_addr,
|
||||
+ struct ipc64_perm *host_ip)
|
||||
+{
|
||||
+ struct target_ipc64_perm *target_ip;
|
||||
+ struct target_semid64_ds *target_sd;
|
||||
+
|
||||
+ lock_user_struct(target_sd, target_addr, 0);
|
||||
+ target_ip = &(target_sd->sem_perm);
|
||||
+ target_ip->key = tswapl(host_ip->key);
|
||||
+ target_ip->uid = tswapl(host_ip->uid);
|
||||
+ target_ip->gid = tswapl(host_ip->gid);
|
||||
+ target_ip->cuid = tswapl(host_ip->cuid);
|
||||
+ target_ip->cgid = tswapl(host_ip->cgid);
|
||||
+ target_ip->mode = tswap16(host_ip->mode);
|
||||
+ target_ip->seq = tswap16(host_ip->seq);
|
||||
+ unlock_user_struct(target_sd, target_addr, 1);
|
||||
+}
|
||||
+
|
||||
static inline void target_to_host_semid_ds(struct semid_ds *host_sd,
|
||||
target_ulong target_addr)
|
||||
{
|
||||
@@ -1327,6 +1397,32 @@ static inline void host_to_target_semid_
|
||||
unlock_user_struct(target_sd, target_addr, 1);
|
||||
}
|
||||
|
||||
+static inline void target_to_host_semid64_ds(struct semid64_ds *host_sd,
|
||||
+ target_ulong target_addr)
|
||||
+{
|
||||
+ struct target_semid64_ds *target_sd;
|
||||
+
|
||||
+ lock_user_struct(target_sd, target_addr, 1);
|
||||
+ target_to_host_ipc64_perm(&(host_sd->sem_perm),target_addr);
|
||||
+ host_sd->sem_nsems = tswapl(target_sd->sem_nsems);
|
||||
+ host_sd->sem_otime = tswapl(target_sd->sem_otime);
|
||||
+ host_sd->sem_ctime = tswapl(target_sd->sem_ctime);
|
||||
+ unlock_user_struct(target_sd, target_addr, 0);
|
||||
+}
|
||||
+
|
||||
+static inline void host_to_target_semid64_ds(target_ulong target_addr,
|
||||
+ struct semid64_ds *host_sd)
|
||||
+{
|
||||
+ struct target_semid64_ds *target_sd;
|
||||
+
|
||||
+ lock_user_struct(target_sd, target_addr, 0);
|
||||
+ host_to_target_ipc64_perm(target_addr,&(host_sd->sem_perm));
|
||||
+ target_sd->sem_nsems = tswapl(host_sd->sem_nsems);
|
||||
+ target_sd->sem_otime = tswapl(host_sd->sem_otime);
|
||||
+ target_sd->sem_ctime = tswapl(host_sd->sem_ctime);
|
||||
+ unlock_user_struct(target_sd, target_addr, 1);
|
||||
+}
|
||||
+
|
||||
union semun {
|
||||
int val;
|
||||
struct semid_ds *buf;
|
||||
@@ -1339,6 +1435,10 @@ union target_semun {
|
||||
unsigned short int *array;
|
||||
};
|
||||
|
||||
+#ifndef IPC_64
|
||||
+#define IPC_64 0x100
|
||||
+#endif
|
||||
+
|
||||
static inline void target_to_host_semun(unsigned long cmd,
|
||||
union semun *host_su,
|
||||
target_ulong target_addr,
|
||||
@@ -1350,7 +1450,16 @@ static inline void target_to_host_semun(
|
||||
case IPC_STAT:
|
||||
case IPC_SET:
|
||||
lock_user_struct(target_su, target_addr, 1);
|
||||
- target_to_host_semid_ds(ds,target_su->buf);
|
||||
+ target_to_host_semid_ds(ds,tswapl(target_su->buf));
|
||||
+ host_su->buf = ds;
|
||||
+ unlock_user_struct(target_su, target_addr, 0);
|
||||
+ break;
|
||||
+ case IPC_STAT + IPC_64:
|
||||
+ case IPC_SET + IPC_64:
|
||||
+ lock_user_struct(target_su, target_addr, 1);
|
||||
+
|
||||
+ //target_to_host_semid_ds(ds,tswapl(target_su->buf));
|
||||
+ target_to_host_semid64_ds((struct semid64_ds *)ds,tswapl(target_su->buf));
|
||||
host_su->buf = ds;
|
||||
unlock_user_struct(target_su, target_addr, 0);
|
||||
break;
|
||||
@@ -1382,7 +1491,14 @@ static inline void host_to_target_semun(
|
||||
case IPC_STAT:
|
||||
case IPC_SET:
|
||||
lock_user_struct(target_su, target_addr, 0);
|
||||
- host_to_target_semid_ds(target_su->buf,ds);
|
||||
+ host_to_target_semid_ds(tswapl(target_su->buf),ds);
|
||||
+ unlock_user_struct(target_su, target_addr, 1);
|
||||
+ break;
|
||||
+ case IPC_STAT + IPC_64:
|
||||
+ case IPC_SET + IPC_64:
|
||||
+ lock_user_struct(target_su, target_addr, 0);
|
||||
+ //host_to_target_semid_ds(tswapl(target_su->buf),ds);
|
||||
+ host_to_target_semid64_ds(tswapl(target_su->buf),(struct semid64_ds *)ds);
|
||||
unlock_user_struct(target_su, target_addr, 1);
|
||||
break;
|
||||
case GETVAL:
|
||||
@@ -1406,7 +1522,8 @@ static inline long do_semctl(long first,
|
||||
{
|
||||
union semun arg;
|
||||
struct semid_ds dsarg;
|
||||
- int cmd = third&0xff;
|
||||
+ struct semid64_ds dsarg64;
|
||||
+ int cmd = third; // & 0xff;
|
||||
long ret = 0;
|
||||
|
||||
switch( cmd ) {
|
||||
@@ -1435,13 +1552,23 @@ static inline long do_semctl(long first,
|
||||
ret = get_errno(semctl(first, second, cmd, arg));
|
||||
host_to_target_semun(cmd,ptr,&arg,&dsarg);
|
||||
break;
|
||||
+ case IPC_STAT + IPC_64:
|
||||
+ target_to_host_semun(cmd,&arg,ptr,(struct semid_ds *)&dsarg64);
|
||||
+ ret = get_errno(semctl(first, second, cmd, arg));
|
||||
+ host_to_target_semun(cmd,ptr,&arg,(struct semid_ds *)&dsarg64);
|
||||
+ break;
|
||||
case IPC_SET:
|
||||
target_to_host_semun(cmd,&arg,ptr,&dsarg);
|
||||
ret = get_errno(semctl(first, second, cmd, arg));
|
||||
host_to_target_semun(cmd,ptr,&arg,&dsarg);
|
||||
break;
|
||||
- default:
|
||||
+ case IPC_SET + IPC_64:
|
||||
+ target_to_host_semun(cmd,&arg,ptr,(struct semid_ds *)&dsarg64);
|
||||
ret = get_errno(semctl(first, second, cmd, arg));
|
||||
+ host_to_target_semun(cmd,ptr,&arg,(struct semid_ds *)&dsarg64);
|
||||
+ break;
|
||||
+ default:
|
||||
+ ret = get_errno(semctl(first, second, cmd & 0xff, arg));
|
||||
}
|
||||
|
||||
return ret;
|
||||
@@ -1465,6 +1592,42 @@ struct target_msqid_ds
|
||||
target_ulong __unused5;
|
||||
};
|
||||
|
||||
+
|
||||
+struct target_shmid64_ds {
|
||||
+ struct target_ipc64_perm shm_perm; /* operation perms */
|
||||
+ target_ulong shm_segsz; /* size of segment (bytes) */
|
||||
+ target_ulong shm_atime; /* last attach time */
|
||||
+ target_ulong __unused1;
|
||||
+ target_ulong shm_dtime; /* last detach time */
|
||||
+ target_ulong __unused2;
|
||||
+ target_ulong shm_ctime; /* last change time */
|
||||
+ target_ulong __unused3;
|
||||
+ int32_t shm_cpid; /* pid of creator */
|
||||
+ int32_t shm_lpid; /* pid of last operator */
|
||||
+ target_ulong shm_nattch; /* no. of current attaches */
|
||||
+ target_ulong __unused4;
|
||||
+ target_ulong __unused5;
|
||||
+};
|
||||
+
|
||||
+/* Data structure describing a set of semaphores. */
|
||||
+struct target_shmid_ds
|
||||
+ {
|
||||
+ struct target_ipc_perm shm_perm; /* operation permission struct */
|
||||
+ unsigned int __unused1;
|
||||
+ target_ulong shm_atime; /* time of last shmat() */
|
||||
+ unsigned int __unused2;
|
||||
+ target_ulong shm_dtime; /* time of last shmdt() */
|
||||
+ unsigned int __unused3;
|
||||
+ target_ulong shm_ctime; /* time of last change by shmctl() */
|
||||
+ unsigned int __unused4;
|
||||
+ target_ulong shm_segsz; /* size of segment in bytes */
|
||||
+ unsigned int shm_cpid; /* pid of creator */
|
||||
+ unsigned int shm_lpid; /* pid of last shmop */
|
||||
+ target_ulong shm_nattch; /* number of current attaches */
|
||||
+ unsigned long __unused5;
|
||||
+ unsigned long __unused6;
|
||||
+ };
|
||||
+
|
||||
static inline void target_to_host_msqid_ds(struct msqid_ds *host_md,
|
||||
target_ulong target_addr)
|
||||
{
|
||||
@@ -1665,11 +1828,59 @@ static long do_ipc(long call, long first
|
||||
case IPCOP_shmctl:
|
||||
switch(second) {
|
||||
case IPC_RMID:
|
||||
+ case IPC_RMID + IPC_64:
|
||||
case SHM_LOCK:
|
||||
+ case SHM_LOCK + IPC_64:
|
||||
case SHM_UNLOCK:
|
||||
+ case SHM_UNLOCK + IPC_64:
|
||||
ret = get_errno(shmctl(first, second, NULL));
|
||||
break;
|
||||
+ case IPC_STAT + IPC_64:
|
||||
+ {
|
||||
+ struct shmid64_ds buf;
|
||||
+ struct target_shmid64_ds *target_buf;
|
||||
+#ifdef DEBUG
|
||||
+ gemu_log("qemu: doing IPC_STAT\n");
|
||||
+#endif
|
||||
+ lock_user_struct(target_buf, ptr, 1);
|
||||
+ ret = get_errno(shmctl(first, second, (struct shmid_ds*)&buf));
|
||||
+
|
||||
+ host_to_target_ipc64_perm(ptr, &buf.shm_perm);
|
||||
+ target_buf->shm_atime = tswapl(buf.shm_atime);
|
||||
+ target_buf->shm_dtime = tswapl(buf.shm_dtime);
|
||||
+ target_buf->shm_ctime = tswapl(buf.shm_ctime);
|
||||
+ target_buf->shm_segsz = tswapl(buf.shm_segsz);
|
||||
+ target_buf->shm_cpid = tswap32(buf.shm_cpid);
|
||||
+ target_buf->shm_lpid = tswap32(buf.shm_lpid);
|
||||
+ target_buf->shm_nattch = tswapl(buf.shm_nattch);
|
||||
+ unlock_user_struct(target_buf, ptr, 0);
|
||||
+ break;
|
||||
+ }
|
||||
+ case IPC_SET + IPC_64:
|
||||
+ {
|
||||
+ struct shmid64_ds buf;
|
||||
+ struct target_shmid64_ds *target_buf;
|
||||
+#ifdef DEBUG
|
||||
+ gemu_log("qemu: doing IPC_SET\n");
|
||||
+#endif
|
||||
+ lock_user_struct(target_buf, ptr, 1);
|
||||
+
|
||||
+ target_to_host_ipc64_perm(&buf.shm_perm, ptr);
|
||||
+ buf.shm_atime = tswapl(target_buf->shm_atime);
|
||||
+ buf.shm_dtime = tswapl(target_buf->shm_dtime);
|
||||
+ buf.shm_ctime = tswapl(target_buf->shm_ctime);
|
||||
+ buf.shm_segsz = tswapl(target_buf->shm_segsz);
|
||||
+ buf.shm_cpid = tswap32(target_buf->shm_cpid);
|
||||
+ buf.shm_lpid = tswap32(target_buf->shm_lpid);
|
||||
+ buf.shm_nattch = tswapl(target_buf->shm_nattch);
|
||||
+
|
||||
+ ret = get_errno(shmctl(first, second, (struct shmid_ds*)&buf));
|
||||
+
|
||||
+ unlock_user_struct(target_buf, ptr, 0);
|
||||
+ break;
|
||||
+ }
|
||||
default:
|
||||
+ gemu_log("Unsopported shmctl(%ld,%#lx)\n", second, second);
|
||||
goto unimplemented;
|
||||
}
|
||||
break;
|
26
qemu-cvs-ipc_semop.patch
Normal file
26
qemu-cvs-ipc_semop.patch
Normal file
@ -0,0 +1,26 @@
|
||||
Index: qemu/linux-user/syscall.c
|
||||
===================================================================
|
||||
--- qemu.orig/linux-user/syscall.c
|
||||
+++ qemu/linux-user/syscall.c
|
||||
@@ -1573,9 +1732,19 @@ static long do_ipc(long call, long first
|
||||
|
||||
switch (call) {
|
||||
case IPCOP_semop:
|
||||
- ret = get_errno(semop(first,(struct sembuf *) ptr, second));
|
||||
+ {
|
||||
+ struct sembuf *target_sops;
|
||||
+ int i;
|
||||
+ lock_user_struct(target_sops, ptr, 0);
|
||||
+ for(i=0; i<second; i++) {
|
||||
+ target_sops[i].sem_num = tswap16(target_sops[i].sem_num);
|
||||
+ target_sops[i].sem_op = tswap16(target_sops[i].sem_op);
|
||||
+ target_sops[i].sem_flg = tswap16(target_sops[i].sem_flg);
|
||||
+ }
|
||||
+ ret = get_errno(semop(first, target_sops, second));
|
||||
+ unlock_user_struct(target_sops, ptr, 0);
|
||||
break;
|
||||
-
|
||||
+ }
|
||||
case IPCOP_semget:
|
||||
ret = get_errno(semget(first, second, third));
|
||||
break;
|
@ -1,6 +1,7 @@
|
||||
diff -uNr qemu-0.8.2.orig/linux-user/mmap.c qemu-0.8.2/linux-user/mmap.c
|
||||
--- qemu-0.8.2.orig/linux-user/mmap.c 2007-01-16 16:05:33 +0200
|
||||
+++ qemu-0.8.2/linux-user/mmap.c 2007-01-16 16:27:28 +0200
|
||||
Index: qemu/linux-user/mmap.c
|
||||
===================================================================
|
||||
--- qemu.orig/linux-user/mmap.c
|
||||
+++ qemu/linux-user/mmap.c
|
||||
@@ -27,6 +27,10 @@
|
||||
|
||||
#include "qemu.h"
|
||||
@ -12,7 +13,7 @@ diff -uNr qemu-0.8.2.orig/linux-user/mmap.c qemu-0.8.2/linux-user/mmap.c
|
||||
//#define DEBUG_MMAP
|
||||
|
||||
/* NOTE: all the constants are the HOST ones, but addresses are target. */
|
||||
@@ -116,7 +120,7 @@
|
||||
@@ -118,7 +122,7 @@ static int mmap_frag(target_ulong real_s
|
||||
if (prot1 == 0) {
|
||||
/* no page was there, so we allocate one */
|
||||
ret = (long)mmap(host_start, qemu_host_page_size, prot,
|
||||
@ -21,7 +22,7 @@ diff -uNr qemu-0.8.2.orig/linux-user/mmap.c qemu-0.8.2/linux-user/mmap.c
|
||||
if (ret == -1)
|
||||
return ret;
|
||||
prot1 = prot;
|
||||
@@ -217,7 +221,8 @@
|
||||
@@ -219,7 +223,8 @@ long target_mmap(target_ulong start, tar
|
||||
abort();
|
||||
host_len = HOST_PAGE_ALIGN(len) + qemu_host_page_size - TARGET_PAGE_SIZE;
|
||||
real_start = (long)mmap(g2h(real_start), host_len, PROT_NONE,
|
||||
@ -31,7 +32,7 @@ diff -uNr qemu-0.8.2.orig/linux-user/mmap.c qemu-0.8.2/linux-user/mmap.c
|
||||
if (real_start == -1)
|
||||
return real_start;
|
||||
real_end = real_start + host_len;
|
||||
@@ -234,7 +239,7 @@
|
||||
@@ -236,7 +241,7 @@ abort();
|
||||
host_offset = offset & qemu_host_page_mask;
|
||||
host_len = len + offset - host_offset;
|
||||
host_start = (long)mmap(real_start ? g2h(real_start) : NULL,
|
||||
@ -40,7 +41,7 @@ diff -uNr qemu-0.8.2.orig/linux-user/mmap.c qemu-0.8.2/linux-user/mmap.c
|
||||
if (host_start == -1)
|
||||
return host_start;
|
||||
/* update start so that it points to the file position at 'offset' */
|
||||
@@ -312,7 +317,7 @@
|
||||
@@ -314,7 +319,7 @@ abort();
|
||||
else
|
||||
offset1 = offset + real_start - start;
|
||||
ret = (long)mmap(g2h(real_start), real_end - real_start,
|
||||
@ -49,7 +50,7 @@ diff -uNr qemu-0.8.2.orig/linux-user/mmap.c qemu-0.8.2/linux-user/mmap.c
|
||||
if (ret == -1)
|
||||
return ret;
|
||||
}
|
||||
@@ -388,7 +393,7 @@
|
||||
@@ -390,7 +395,7 @@ long target_mremap(target_ulong old_addr
|
||||
int prot;
|
||||
|
||||
/* XXX: use 5 args syscall */
|
17
qemu-cvs-mplayer.patch
Normal file
17
qemu-cvs-mplayer.patch
Normal file
@ -0,0 +1,17 @@
|
||||
Index: qemu/linux-user/mmap.c
|
||||
===================================================================
|
||||
--- qemu.orig/linux-user/mmap.c
|
||||
+++ qemu/linux-user/mmap.c
|
||||
@@ -48,8 +48,10 @@ int target_mprotect(target_ulong start,
|
||||
end = start + len;
|
||||
if (end < start)
|
||||
return -EINVAL;
|
||||
- if (prot & ~(PROT_READ | PROT_WRITE | PROT_EXEC))
|
||||
- return -EINVAL;
|
||||
+ if (prot & ~(PROT_READ | PROT_WRITE | PROT_EXEC)) {
|
||||
+ gemu_log("WARNING: dirty hack in mprotect: setting prot (%#x -> %#x)\n", prot, prot & (PROT_READ | PROT_WRITE | PROT_EXEC));
|
||||
+ prot &= (PROT_READ | PROT_WRITE | PROT_EXEC);
|
||||
+ }
|
||||
if (len == 0)
|
||||
return 0;
|
||||
|
12
qemu-cvs-netlink.patch
Normal file
12
qemu-cvs-netlink.patch
Normal file
@ -0,0 +1,12 @@
|
||||
Index: qemu/linux-user/syscall.c
|
||||
===================================================================
|
||||
--- qemu.orig/linux-user/syscall.c
|
||||
+++ qemu/linux-user/syscall.c
|
||||
@@ -898,6 +906,7 @@ static long do_socket(int domain, int ty
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
+ if(domain == PF_NETLINK) return -EAFNOSUPPORT; /* do not make NETLINK socket connections possible */
|
||||
return get_errno(socket(domain, type, protocol));
|
||||
}
|
||||
|
@ -1,6 +1,8 @@
|
||||
--- qemu/linux-user/path.c
|
||||
+++ qemu/linux-user/path.c
|
||||
@@ -1,147 +1,81 @@
|
||||
Index: qemu.bkp/linux-user/path.c
|
||||
===================================================================
|
||||
--- qemu.bkp.orig/linux-user/path.c
|
||||
+++ qemu.bkp/linux-user/path.c
|
||||
@@ -1,159 +1,81 @@
|
||||
/* Code to mangle pathnames into those matching a given prefix.
|
||||
eg. open("/lib/foo.so") => open("/usr/gnemul/i386-linux/lib/foo.so");
|
||||
-
|
||||
@ -98,28 +100,7 @@
|
||||
- for (i = 0; i < child->num_entries; i++)
|
||||
- set_parents(child->entries[i], child);
|
||||
-}
|
||||
+static struct path_list_head* list_head;
|
||||
|
||||
void init_paths(const char *prefix)
|
||||
{
|
||||
if (prefix[0] != '/' ||
|
||||
- prefix[0] == '\0' ||
|
||||
- !strcmp(prefix, "/"))
|
||||
+ prefix[0] == '\0' ||
|
||||
+ !strcmp(prefix, "/"))
|
||||
return;
|
||||
|
||||
- base = new_entry("", NULL, prefix+1);
|
||||
- base = add_dir_maybe(base);
|
||||
- if (base->num_entries == 0) {
|
||||
- free (base);
|
||||
- base = NULL;
|
||||
- } else {
|
||||
- set_parents(base, base);
|
||||
- }
|
||||
-}
|
||||
+ list_head = malloc(sizeof(struct path_list_head));
|
||||
|
||||
-
|
||||
-/* FIXME: Doesn't handle DIR/.. where DIR is not in emulated dir. */
|
||||
-static const char *
|
||||
-follow_path(const struct pathelem *cursor, const char *name)
|
||||
@ -144,6 +125,41 @@
|
||||
-
|
||||
- /* Not found */
|
||||
- return NULL;
|
||||
-}
|
||||
+static struct path_list_head* list_head;
|
||||
|
||||
void init_paths(const char *prefix)
|
||||
{
|
||||
- char pref_buf[PATH_MAX];
|
||||
-
|
||||
- if (prefix[0] == '\0' ||
|
||||
- !strcmp(prefix, "/"))
|
||||
+ if (prefix[0] != '/' ||
|
||||
+ prefix[0] == '\0' ||
|
||||
+ !strcmp(prefix, "/"))
|
||||
return;
|
||||
|
||||
- if (prefix[0] != '/') {
|
||||
- char *cwd = get_current_dir_name();
|
||||
- if (!cwd)
|
||||
- abort();
|
||||
- strcpy(pref_buf, cwd);
|
||||
- strcat(pref_buf, "/");
|
||||
- strcat(pref_buf, prefix);
|
||||
- free(cwd);
|
||||
- } else
|
||||
- strcpy(pref_buf,prefix + 1);
|
||||
-
|
||||
- base = new_entry("", NULL, pref_buf);
|
||||
- base = add_dir_maybe(base);
|
||||
- if (base->num_entries == 0) {
|
||||
- free (base);
|
||||
- base = NULL;
|
||||
- } else {
|
||||
- set_parents(base, base);
|
||||
- }
|
||||
+ list_head = malloc(sizeof(struct path_list_head));
|
||||
+
|
||||
+ /* first element of list is prefix */
|
||||
+ list_head->path = strdup(prefix);
|
||||
+ list_head->next = NULL;
|
||||
@ -162,14 +178,13 @@
|
||||
Could do relative by tracking cwd. */
|
||||
- if (!base || name[0] != '/')
|
||||
- return name;
|
||||
-
|
||||
- return follow_path(base, name) ?: name;
|
||||
+ if (!list_head || result[0] != '/')
|
||||
+ goto exit;
|
||||
+
|
||||
+ strncpy(newname, list_head->path, path_length);
|
||||
+ strncat(newname, name, path_length);
|
||||
+
|
||||
|
||||
- return follow_path(base, name) ?: name;
|
||||
+ /* look for place where path should be present */
|
||||
+ while ( list->next && (strcmp(list->next->path, newname) < 0) )
|
||||
+ list = list->next;
|
16
qemu-cvs-nofadvise64.patch
Normal file
16
qemu-cvs-nofadvise64.patch
Normal file
@ -0,0 +1,16 @@
|
||||
Index: qemu/linux-user/syscall.c
|
||||
===================================================================
|
||||
--- qemu.orig/linux-user/syscall.c
|
||||
+++ qemu/linux-user/syscall.c
|
||||
@@ -5059,6 +5059,11 @@ long do_syscall(void *cpu_env, int num,
|
||||
goto unimplemented_nowarn;
|
||||
#endif
|
||||
|
||||
+#ifdef TARGET_NR_fadvise64
|
||||
+ case TARGET_NR_fadvise64:
|
||||
+ goto unimplemented_nowarn;
|
||||
+#endif
|
||||
+
|
||||
#ifdef TARGET_NR_sched_getaffinity
|
||||
case TARGET_NR_sched_getaffinity:
|
||||
{
|
13
qemu-cvs-noppcemb.patch
Normal file
13
qemu-cvs-noppcemb.patch
Normal file
@ -0,0 +1,13 @@
|
||||
Index: qemu-0.9.0/configure
|
||||
===================================================================
|
||||
--- qemu-0.9.0.orig/configure
|
||||
+++ qemu-0.9.0/configure
|
||||
@@ -473,7 +473,7 @@ fi
|
||||
if test -z "$target_list" ; then
|
||||
# these targets are portable
|
||||
if [ "$softmmu" = "yes" ] ; then
|
||||
- target_list="i386-softmmu ppc-softmmu sparc-softmmu x86_64-softmmu mips-softmmu mipsel-softmmu mips64-softmmu mips64el-softmmu arm-softmmu ppc64-softmmu ppcemb-softmmu m68k-softmmu z80-softmmu"
|
||||
+ target_list="i386-softmmu ppc-softmmu sparc-softmmu x86_64-softmmu mips-softmmu mipsel-softmmu mips64-softmmu mips64el-softmmu arm-softmmu ppc64-softmmu m68k-softmmu z80-softmmu"
|
||||
fi
|
||||
# the following are Linux specific
|
||||
if [ "$linux_user" = "yes" ] ; then
|
13
qemu-cvs-pthread.patch
Normal file
13
qemu-cvs-pthread.patch
Normal file
@ -0,0 +1,13 @@
|
||||
Index: qemu-0.9.0/Makefile
|
||||
===================================================================
|
||||
--- qemu-0.9.0.orig/Makefile
|
||||
+++ qemu-0.9.0/Makefile
|
||||
@@ -12,7 +12,7 @@ BASE_CFLAGS += $(OS_CFLAGS) $(ARCH_CFLAG
|
||||
BASE_LDFLAGS += $(OS_LDFLAGS) $(ARCH_LDFLAGS)
|
||||
|
||||
CPPFLAGS += -I. -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE
|
||||
-LIBS=
|
||||
+LIBS=-lpthread
|
||||
TOOLS=qemu-img$(EXESUF)
|
||||
ifdef CONFIG_STATIC
|
||||
BASE_LDFLAGS += -static
|
38
qemu-cvs-sched_getaffinity.patch
Normal file
38
qemu-cvs-sched_getaffinity.patch
Normal file
@ -0,0 +1,38 @@
|
||||
Index: qemu.bkp/linux-user/syscall.c
|
||||
===================================================================
|
||||
--- qemu.bkp.orig/linux-user/syscall.c
|
||||
+++ qemu.bkp/linux-user/syscall.c
|
||||
@@ -149,6 +149,7 @@ type name (type1 arg1,type2 arg2,type3 a
|
||||
#define __NR_sys_syslog __NR_syslog
|
||||
#define __NR_sys_tgkill __NR_tgkill
|
||||
#define __NR_sys_clone __NR_clone
|
||||
+#define __NR_sys_sched_getaffinity __NR_sched_getaffinity
|
||||
|
||||
#if defined(__alpha__) || defined (__ia64__) || defined(__x86_64__)
|
||||
#define __NR__llseek __NR_lseek
|
||||
@@ -171,6 +172,7 @@ _syscall3(int,sys_rt_sigqueueinfo,int,pi
|
||||
_syscall3(int,sys_syslog,int,type,char*,bufp,int,len)
|
||||
_syscall3(int,sys_tgkill,int,tgid,int,pid,int,sig)
|
||||
_syscall5(int,sys_clone, int, flags, void *, child_stack, int *, parent_tidptr, void *, newtls, int *, child_tidptr)
|
||||
+_syscall3(int,sys_sched_getaffinity,pid_t,pid,unsigned int,cpusetsize,void*,mask)
|
||||
#ifdef __NR_exit_group
|
||||
_syscall1(int,exit_group,int,error_code)
|
||||
#endif
|
||||
@@ -4823,6 +4825,17 @@ long do_syscall(void *cpu_env, int num,
|
||||
goto unimplemented_nowarn;
|
||||
#endif
|
||||
|
||||
+#ifdef TARGET_NR_sched_getaffinity
|
||||
+ case TARGET_NR_sched_getaffinity:
|
||||
+ {
|
||||
+ cpu_set_t *mask;
|
||||
+ lock_user_struct(mask, arg3, 1);
|
||||
+ ret = get_errno(sys_sched_getaffinity((pid_t)arg1, (unsigned int)arg2, mask));
|
||||
+ unlock_user_struct(mask, arg3, 0);
|
||||
+ break;
|
||||
+ }
|
||||
+#endif
|
||||
+
|
||||
default:
|
||||
unimplemented:
|
||||
gemu_log("qemu: Unsupported syscall: %d\n", num);
|
260
qemu-cvs-tls.patch
Normal file
260
qemu-cvs-tls.patch
Normal file
@ -0,0 +1,260 @@
|
||||
Index: qemu.bkp/linux-user/main.c
|
||||
===================================================================
|
||||
--- qemu.bkp.orig/linux-user/main.c
|
||||
+++ qemu.bkp/linux-user/main.c
|
||||
@@ -156,7 +156,7 @@ static void set_gate(void *ptr, unsigned
|
||||
p[1] = tswapl(e2);
|
||||
}
|
||||
|
||||
-uint64_t gdt_table[6];
|
||||
+uint64_t gdt_table[9];
|
||||
uint64_t idt_table[256];
|
||||
|
||||
/* only dpl matters as we do only user space emulation */
|
||||
Index: qemu.bkp/linux-user/syscall.c
|
||||
===================================================================
|
||||
--- qemu.bkp.orig/linux-user/syscall.c
|
||||
+++ qemu.bkp/linux-user/syscall.c
|
||||
@@ -145,6 +145,7 @@ type name (type1 arg1,type2 arg2,type3 a
|
||||
#define __NR_sys_rt_sigqueueinfo __NR_rt_sigqueueinfo
|
||||
#define __NR_sys_syslog __NR_syslog
|
||||
#define __NR_sys_tgkill __NR_tgkill
|
||||
+#define __NR_sys_clone __NR_clone
|
||||
|
||||
#if defined(__alpha__) || defined (__ia64__) || defined(__x86_64__)
|
||||
#define __NR__llseek __NR_lseek
|
||||
@@ -166,6 +167,7 @@ _syscall5(int, _llseek, uint, fd, ulon
|
||||
_syscall3(int,sys_rt_sigqueueinfo,int,pid,int,sig,siginfo_t *,uinfo)
|
||||
_syscall3(int,sys_syslog,int,type,char*,bufp,int,len)
|
||||
_syscall3(int,sys_tgkill,int,tgid,int,pid,int,sig)
|
||||
+_syscall5(int,sys_clone, int, flags, void *, child_stack, int *, parent_tidptr, void *, newtls, int *, child_tidptr)
|
||||
#ifdef __NR_exit_group
|
||||
_syscall1(int,exit_group,int,error_code)
|
||||
#endif
|
||||
@@ -2115,29 +2117,107 @@ int do_modify_ldt(CPUX86State *env, int
|
||||
return ret;
|
||||
}
|
||||
|
||||
+int do_set_thread_area(CPUX86State *env, target_ulong ptr)
|
||||
+{
|
||||
+ uint64_t *gdt_table = g2h(env->gdt.base);
|
||||
+ struct target_modify_ldt_ldt_s ldt_info;
|
||||
+ struct target_modify_ldt_ldt_s *target_ldt_info;
|
||||
+ int seg_32bit, contents, read_exec_only, limit_in_pages;
|
||||
+ int seg_not_present, useable;
|
||||
+ uint32_t *lp, entry_1, entry_2;
|
||||
+ int i;
|
||||
+
|
||||
+ lock_user_struct(target_ldt_info, ptr, 1);
|
||||
+ ldt_info.entry_number = tswap32(target_ldt_info->entry_number);
|
||||
+ ldt_info.base_addr = tswapl(target_ldt_info->base_addr);
|
||||
+ ldt_info.limit = tswap32(target_ldt_info->limit);
|
||||
+ ldt_info.flags = tswap32(target_ldt_info->flags);
|
||||
+ if (ldt_info.entry_number == -1) {
|
||||
+ for (i=6; i<8; i++)
|
||||
+ if (gdt_table[i] == 0) {
|
||||
+ ldt_info.entry_number = i;
|
||||
+ target_ldt_info->entry_number = tswap32(i);
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+ unlock_user_struct(target_ldt_info, ptr, 0);
|
||||
+
|
||||
+ if (ldt_info.entry_number < 6 || ldt_info.entry_number > 8)
|
||||
+ return -EINVAL;
|
||||
+ seg_32bit = ldt_info.flags & 1;
|
||||
+ contents = (ldt_info.flags >> 1) & 3;
|
||||
+ read_exec_only = (ldt_info.flags >> 3) & 1;
|
||||
+ limit_in_pages = (ldt_info.flags >> 4) & 1;
|
||||
+ seg_not_present = (ldt_info.flags >> 5) & 1;
|
||||
+ useable = (ldt_info.flags >> 6) & 1;
|
||||
+
|
||||
+ if (contents == 3) {
|
||||
+ if (seg_not_present == 0)
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ /* NOTE: same code as Linux kernel */
|
||||
+ /* Allow LDTs to be cleared by the user. */
|
||||
+ if (ldt_info.base_addr == 0 && ldt_info.limit == 0) {
|
||||
+ if ((contents == 0 &&
|
||||
+ read_exec_only == 1 &&
|
||||
+ seg_32bit == 0 &&
|
||||
+ limit_in_pages == 0 &&
|
||||
+ seg_not_present == 1 &&
|
||||
+ useable == 0 )) {
|
||||
+ entry_1 = 0;
|
||||
+ entry_2 = 0;
|
||||
+ goto install;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ entry_1 = ((ldt_info.base_addr & 0x0000ffff) << 16) |
|
||||
+ (ldt_info.limit & 0x0ffff);
|
||||
+ entry_2 = (ldt_info.base_addr & 0xff000000) |
|
||||
+ ((ldt_info.base_addr & 0x00ff0000) >> 16) |
|
||||
+ (ldt_info.limit & 0xf0000) |
|
||||
+ ((read_exec_only ^ 1) << 9) |
|
||||
+ (contents << 10) |
|
||||
+ ((seg_not_present ^ 1) << 15) |
|
||||
+ (seg_32bit << 22) |
|
||||
+ (limit_in_pages << 23) |
|
||||
+ (useable << 20) |
|
||||
+ 0x7000;
|
||||
+
|
||||
+ /* Install the new entry ... */
|
||||
+install:
|
||||
+ lp = (uint32_t *)(gdt_table + ldt_info.entry_number);
|
||||
+ lp[0] = tswap32(entry_1);
|
||||
+ lp[1] = tswap32(entry_2);
|
||||
+ return 0;
|
||||
+}
|
||||
#endif /* defined(TARGET_I386) */
|
||||
|
||||
/* this stack is the equivalent of the kernel stack associated with a
|
||||
thread/process */
|
||||
#define NEW_STACK_SIZE 8192
|
||||
|
||||
-static int clone_func(void *arg)
|
||||
+static int clone_func(void *cloneenv)
|
||||
{
|
||||
- CPUState *env = arg;
|
||||
- cpu_loop(env);
|
||||
+ cpu_loop((CPUState *)cloneenv);
|
||||
/* never exits */
|
||||
return 0;
|
||||
}
|
||||
|
||||
-int do_fork(CPUState *env, unsigned int flags, unsigned long newsp)
|
||||
+int do_fork(CPUState *env, unsigned int flags, target_ulong newsp, target_ulong parent_tidptr, target_ulong newtls, target_ulong child_tidptr)
|
||||
{
|
||||
int ret;
|
||||
+ unsigned long parent_tid=gettid();
|
||||
TaskState *ts;
|
||||
uint8_t *new_stack;
|
||||
CPUState *new_env;
|
||||
-
|
||||
+#if defined(TARGET_I386)
|
||||
+ uint64_t *new_gdt_table;
|
||||
+#endif
|
||||
if (flags & CLONE_VM) {
|
||||
ts = malloc(sizeof(TaskState) + NEW_STACK_SIZE);
|
||||
+ if (!ts)
|
||||
+ return -ENOMEM;
|
||||
memset(ts, 0, sizeof(TaskState));
|
||||
new_stack = ts->stack;
|
||||
ts->used = 1;
|
||||
@@ -2149,6 +2229,27 @@ int do_fork(CPUState *env, unsigned int
|
||||
#if defined(TARGET_I386)
|
||||
if (!newsp)
|
||||
newsp = env->regs[R_ESP];
|
||||
+ new_gdt_table = malloc(9 * 8);
|
||||
+ if (!new_gdt_table) {
|
||||
+ free(new_env);
|
||||
+ return -ENOMEM;
|
||||
+ }
|
||||
+ /* Copy main GDT table from parent, but clear TLS entries */
|
||||
+ memcpy(new_gdt_table, g2h(env->gdt.base), 6 * 8);
|
||||
+ memset(&new_gdt_table[6], 0, 3 * 8);
|
||||
+ new_env->gdt.base = h2g(new_gdt_table);
|
||||
+ if (flags & CLONE_SETTLS) {
|
||||
+ ret = do_set_thread_area(new_env, newtls);
|
||||
+ if (ret) {
|
||||
+ free(new_gdt_table);
|
||||
+ free(new_env);
|
||||
+ return ret;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ cpu_x86_load_seg(new_env, R_FS, new_env->segs[R_FS].selector);
|
||||
+ cpu_x86_load_seg(new_env, R_GS, new_env->segs[R_GS].selector);
|
||||
+
|
||||
new_env->regs[R_ESP] = newsp;
|
||||
new_env->regs[R_EAX] = 0;
|
||||
#elif defined(TARGET_ARM)
|
||||
@@ -2202,15 +2303,27 @@ int do_fork(CPUState *env, unsigned int
|
||||
#endif
|
||||
new_env->opaque = ts;
|
||||
#ifdef __ia64__
|
||||
- ret = __clone2(clone_func, new_stack + NEW_STACK_SIZE, flags, new_env);
|
||||
+ ret = __clone2(clone_func, new_stack + NEW_STACK_SIZE, flags & ~(CLONE_SETTLS|CLONE_PARENT_SETTID|CLONE_CHILD_CLEARTID), new_env);
|
||||
#else
|
||||
- ret = clone(clone_func, new_stack + NEW_STACK_SIZE, flags, new_env);
|
||||
+ ret = clone(clone_func, new_stack + NEW_STACK_SIZE, flags & ~(CLONE_SETTLS|CLONE_PARENT_SETTID|CLONE_CHILD_CLEARTID), new_env);
|
||||
#endif
|
||||
} else {
|
||||
/* if no CLONE_VM, we consider it is a fork */
|
||||
- if ((flags & ~CSIGNAL) != 0)
|
||||
- return -EINVAL;
|
||||
- ret = fork();
|
||||
+ ret = sys_clone(flags & ~(CLONE_SETTLS|CLONE_PARENT_SETTID|CLONE_CHILD_CLEARTID), 0, g2h(parent_tidptr), NULL, g2h(child_tidptr));
|
||||
+ }
|
||||
+ /* Store child thread ID at location parent_tidptr in parent and child memory.
|
||||
+ Currently this is only done in client memory */
|
||||
+ if(flags & CLONE_PARENT_SETTID) {
|
||||
+ tput32(parent_tidptr, parent_tid);
|
||||
+ }
|
||||
+
|
||||
+ /* Store child thread ID at location child_tidptr in child memory. */
|
||||
+ if(flags & CLONE_CHILD_SETTID) {
|
||||
+ if(ret==0) { /* only in client memory for fork() */
|
||||
+ tput32(child_tidptr, gettid());
|
||||
+ } else if(flags & CLONE_VM) { /* real threads need it too */
|
||||
+ tput32(child_tidptr, ret);
|
||||
+ }
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
@@ -2458,7 +2571,7 @@ long do_syscall(void *cpu_env, int num,
|
||||
_mcleanup();
|
||||
#endif
|
||||
gdb_exit(cpu_env, arg1);
|
||||
- /* XXX: should free thread stack and CPU env */
|
||||
+ /* XXX: should free thread stack, GDT and CPU env */
|
||||
_exit(arg1);
|
||||
ret = 0; /* avoid warning */
|
||||
break;
|
||||
@@ -2487,7 +2600,7 @@ long do_syscall(void *cpu_env, int num,
|
||||
ret = do_brk(arg1);
|
||||
break;
|
||||
case TARGET_NR_fork:
|
||||
- ret = get_errno(do_fork(cpu_env, SIGCHLD, 0));
|
||||
+ ret = get_errno(do_fork(cpu_env, SIGCHLD, 0, 0,0,0));
|
||||
break;
|
||||
#ifdef TARGET_NR_waitpid
|
||||
case TARGET_NR_waitpid:
|
||||
@@ -3651,7 +3764,7 @@ long do_syscall(void *cpu_env, int num,
|
||||
ret = get_errno(fsync(arg1));
|
||||
break;
|
||||
case TARGET_NR_clone:
|
||||
- ret = get_errno(do_fork(cpu_env, arg1, arg2));
|
||||
+ ret = get_errno(do_fork(cpu_env, arg1, arg2,arg3,arg4,arg5));
|
||||
break;
|
||||
#ifdef __NR_exit_group
|
||||
/* new thread calls */
|
||||
@@ -4039,7 +4152,7 @@ long do_syscall(void *cpu_env, int num,
|
||||
#endif
|
||||
#ifdef TARGET_NR_vfork
|
||||
case TARGET_NR_vfork:
|
||||
- ret = get_errno(do_fork(cpu_env, CLONE_VFORK | CLONE_VM | SIGCHLD, 0));
|
||||
+ ret = get_errno(do_fork(cpu_env, CLONE_VFORK | CLONE_VM | SIGCHLD, 0, 0,0,0));
|
||||
break;
|
||||
#endif
|
||||
#ifdef TARGET_NR_ugetrlimit
|
||||
@@ -4561,12 +4674,12 @@ long do_syscall(void *cpu_env, int num,
|
||||
#ifdef TARGET_NR_set_thread_area
|
||||
case TARGET_NR_set_thread_area:
|
||||
#ifdef TARGET_MIPS
|
||||
- ((CPUMIPSState *) cpu_env)->tls_value = arg1;
|
||||
- ret = 0;
|
||||
- break;
|
||||
+ ((CPUMIPSState *) cpu_env)->tls_value = arg1;
|
||||
+ ret = 0;
|
||||
#else
|
||||
- goto unimplemented_nowarn;
|
||||
+ ret = get_errno(do_set_thread_area(cpu_env, arg1));
|
||||
#endif
|
||||
+ break;
|
||||
#endif
|
||||
#ifdef TARGET_NR_get_thread_area
|
||||
case TARGET_NR_get_thread_area:
|
2766
qemu-m68k.diff
Normal file
2766
qemu-m68k.diff
Normal file
File diff suppressed because it is too large
Load Diff
458
qemu-z80.diff
458
qemu-z80.diff
@ -1,19 +1,63 @@
|
||||
diff -urN qemu-0.9.0/configure qemu-z80/configure
|
||||
--- qemu-0.9.0/configure 2007-02-05 23:01:54.000000000 +0000
|
||||
+++ qemu-z80/configure 2007-03-27 21:07:11.000000000 +0100
|
||||
@@ -415,7 +415,7 @@
|
||||
diff --exclude='*.orig' --exclude=CVS -ruN qemu/configure qemu-z80/configure
|
||||
--- qemu/configure 2007-06-23 18:03:35.000000000 +0200
|
||||
+++ qemu-z80/configure 2007-07-06 13:07:47.000000000 +0200
|
||||
@@ -86,6 +86,7 @@
|
||||
dsound="no"
|
||||
coreaudio="no"
|
||||
alsa="no"
|
||||
+libspectrum="no"
|
||||
fmod="no"
|
||||
fmod_lib=""
|
||||
fmod_inc=""
|
||||
@@ -245,6 +246,8 @@
|
||||
;;
|
||||
--fmod-inc=*) fmod_inc="$optarg"
|
||||
;;
|
||||
+ --enable-libspectrum) libspectrum="yes"
|
||||
+ ;;
|
||||
--enable-mingw32) mingw32="yes" ; cross_prefix="i386-mingw32-" ; linux_user="no"
|
||||
;;
|
||||
--disable-slirp) slirp="no"
|
||||
@@ -355,6 +358,7 @@
|
||||
echo " --enable-alsa enable ALSA audio driver"
|
||||
echo " --enable-fmod enable FMOD audio driver"
|
||||
echo " --enable-dsound enable DirectSound audio driver"
|
||||
+echo " --enable-libspectrum enable ZX Spectrum snapshot loading"
|
||||
echo " --enable-system enable all system emulation targets"
|
||||
echo " --disable-system disable all system emulation targets"
|
||||
echo " --enable-linux-user enable all linux usermode emulation targets"
|
||||
@@ -473,7 +477,7 @@
|
||||
if test -z "$target_list" ; then
|
||||
# these targets are portable
|
||||
if [ "$softmmu" = "yes" ] ; then
|
||||
- target_list="i386-softmmu ppc-softmmu sparc-softmmu x86_64-softmmu mips-softmmu mipsel-softmmu arm-softmmu"
|
||||
+ target_list="i386-softmmu ppc-softmmu sparc-softmmu x86_64-softmmu mips-softmmu mipsel-softmmu arm-softmmu z80-softmmu"
|
||||
- target_list="i386-softmmu ppc-softmmu sparc-softmmu x86_64-softmmu mips-softmmu mipsel-softmmu mips64-softmmu mips64el-softmmu arm-softmmu ppc64-softmmu ppcemb-softmmu m68k-softmmu"
|
||||
+ target_list="i386-softmmu ppc-softmmu sparc-softmmu x86_64-softmmu mips-softmmu mipsel-softmmu mips64-softmmu mips64el-softmmu arm-softmmu ppc64-softmmu ppcemb-softmmu m68k-softmmu z80-softmmu"
|
||||
fi
|
||||
# the following are Linux specific
|
||||
if [ "$linux_user" = "yes" ] ; then
|
||||
@@ -911,6 +911,11 @@
|
||||
echo "#define TARGET_ARCH \"m68k\"" >> $config_h
|
||||
echo "#define TARGET_M68K 1" >> $config_h
|
||||
bflt="yes"
|
||||
@@ -680,6 +684,7 @@
|
||||
if test -n "$sparc_cpu"; then
|
||||
echo "Target Sparc Arch $sparc_cpu"
|
||||
fi
|
||||
+echo "libspec. support $libspectrum"
|
||||
echo "kqemu support $kqemu"
|
||||
echo "Documentation $build_docs"
|
||||
[ ! -z "$uname_release" ] && \
|
||||
@@ -841,6 +846,10 @@
|
||||
echo "CONFIG_FMOD_INC=$fmod_inc" >> $config_mak
|
||||
echo "#define CONFIG_FMOD 1" >> $config_h
|
||||
fi
|
||||
+if test "$libspectrum" = "yes" ; then
|
||||
+ echo "CONFIG_LIBSPECTRUM=yes" >> $config_mak
|
||||
+ echo "#define CONFIG_LIBSPECTRUM 1" >> $config_h
|
||||
+fi
|
||||
qemu_version=`head $source_path/VERSION`
|
||||
echo "VERSION=$qemu_version" >>$config_mak
|
||||
echo "#define QEMU_VERSION \"$qemu_version\"" >> $config_h
|
||||
@@ -1008,6 +1017,11 @@
|
||||
echo "TARGET_ARCH=alpha" >> $config_mak
|
||||
echo "#define TARGET_ARCH \"alpha\"" >> $config_h
|
||||
echo "#define TARGET_ALPHA 1" >> $config_h
|
||||
+elif test "$target_cpu" = "z80" ; then
|
||||
+ echo "TARGET_ARCH=z80" >> $config_mak
|
||||
+ echo "#define TARGET_ARCH \"z80\"" >> $config_h
|
||||
@ -22,29 +66,12 @@ diff -urN qemu-0.9.0/configure qemu-z80/configure
|
||||
else
|
||||
echo "Unsupported target CPU"
|
||||
exit 1
|
||||
diff -urN qemu-0.9.0/cpu-all.h qemu-z80/cpu-all.h
|
||||
--- qemu-0.9.0/cpu-all.h 2007-02-05 23:01:54.000000000 +0000
|
||||
+++ qemu-z80/cpu-all.h 2007-03-27 21:07:11.000000000 +0100
|
||||
@@ -746,6 +746,13 @@
|
||||
#define cpu_gen_code cpu_sh4_gen_code
|
||||
#define cpu_signal_handler cpu_sh4_signal_handler
|
||||
|
||||
+#elif defined(TARGET_Z80)
|
||||
+#define CPUState CPUZ80State
|
||||
+#define cpu_init cpu_z80_init
|
||||
+#define cpu_exec cpu_z80_exec
|
||||
+#define cpu_gen_code cpu_z80_gen_code
|
||||
+#define cpu_signal_handler cpu_z80_signal_handler
|
||||
+
|
||||
#else
|
||||
|
||||
#error unsupported target CPU
|
||||
diff -urN qemu-0.9.0/cpu-exec.c qemu-z80/cpu-exec.c
|
||||
--- qemu-0.9.0/cpu-exec.c 2007-02-05 23:01:54.000000000 +0000
|
||||
+++ qemu-z80/cpu-exec.c 2007-04-17 21:14:13.000000000 +0100
|
||||
@@ -202,6 +202,10 @@
|
||||
flags = env->sr & (SR_MD | SR_RB);
|
||||
cs_base = 0; /* XXXXX */
|
||||
diff --exclude='*.orig' --exclude=CVS -ruN qemu/cpu-exec.c qemu-z80/cpu-exec.c
|
||||
--- qemu/cpu-exec.c 2007-06-03 20:52:15.000000000 +0200
|
||||
+++ qemu-z80/cpu-exec.c 2007-07-05 18:36:50.000000000 +0200
|
||||
@@ -209,6 +209,10 @@
|
||||
flags = env->ps;
|
||||
cs_base = 0;
|
||||
pc = env->pc;
|
||||
+#elif defined(TARGET_Z80)
|
||||
+ flags = env->hflags;
|
||||
@ -53,7 +80,7 @@ diff -urN qemu-0.9.0/cpu-exec.c qemu-z80/cpu-exec.c
|
||||
#else
|
||||
#error unsupported CPU
|
||||
#endif
|
||||
@@ -325,6 +329,12 @@
|
||||
@@ -284,6 +288,15 @@
|
||||
#elif defined(TARGET_MIPS)
|
||||
#elif defined(TARGET_SH4)
|
||||
/* XXXXX */
|
||||
@ -63,13 +90,16 @@ diff -urN qemu-0.9.0/cpu-exec.c qemu-z80/cpu-exec.c
|
||||
+ CC_SRC = env->eflags & (CC_S | CC_Z | CC_P | CC_C);
|
||||
+ CC_OP = CC_OP_EFLAGS;
|
||||
+ env->eflags &= ~(CC_S | CC_Z | CC_P | CC_C);
|
||||
+#elif defined(TARGET_Z80)
|
||||
+ /* restore flags in standard format */
|
||||
+// env->eflags = env->eflags | cc_table[CC_OP].compute_all();
|
||||
#else
|
||||
#error unsupported target CPU
|
||||
#endif
|
||||
@@ -525,6 +535,13 @@
|
||||
@@ -500,6 +513,13 @@
|
||||
env->exception_index = env->pending_vector;
|
||||
do_interrupt(1);
|
||||
}
|
||||
#elif defined(TARGET_SH4)
|
||||
/* XXXXX */
|
||||
+#elif defined(TARGET_Z80)
|
||||
+ if (interrupt_request & CPU_INTERRUPT_HARD) {
|
||||
+ env->interrupt_request &= ~CPU_INTERRUPT_HARD;
|
||||
@ -80,18 +110,18 @@ diff -urN qemu-0.9.0/cpu-exec.c qemu-z80/cpu-exec.c
|
||||
#endif
|
||||
/* Don't use the cached interupt_request value,
|
||||
do_interrupt may have updated the EXITTB flag. */
|
||||
@@ -593,6 +610,8 @@
|
||||
cpu_dump_state(env, logfile, fprintf, 0);
|
||||
#elif defined(TARGET_SH4)
|
||||
@@ -547,6 +567,8 @@
|
||||
cpu_dump_state(env, logfile, fprintf, 0);
|
||||
#elif defined(TARGET_ALPHA)
|
||||
cpu_dump_state(env, logfile, fprintf, 0);
|
||||
+#elif defined(TARGET_Z80)
|
||||
+ cpu_dump_state(env, logfile, fprintf, 0);
|
||||
+ cpu_dump_state(env, logfile, fprintf, 0);
|
||||
#else
|
||||
#error unsupported target CPU
|
||||
#endif
|
||||
@@ -785,6 +804,9 @@
|
||||
#elif defined(TARGET_MIPS)
|
||||
@@ -741,6 +763,9 @@
|
||||
#elif defined(TARGET_SH4)
|
||||
#elif defined(TARGET_ALPHA)
|
||||
/* XXXXX */
|
||||
+#elif defined(TARGET_Z80)
|
||||
+ /* restore flags in standard format */
|
||||
@ -99,32 +129,32 @@ diff -urN qemu-0.9.0/cpu-exec.c qemu-z80/cpu-exec.c
|
||||
#else
|
||||
#error unsupported target CPU
|
||||
#endif
|
||||
diff -urN qemu-0.9.0/disas.c qemu-z80/disas.c
|
||||
--- qemu-0.9.0/disas.c 2007-02-05 23:01:54.000000000 +0000
|
||||
+++ qemu-z80/disas.c 2007-03-27 21:07:11.000000000 +0100
|
||||
@@ -197,6 +197,8 @@
|
||||
#elif defined(TARGET_SH4)
|
||||
disasm_info.mach = bfd_mach_sh4;
|
||||
print_insn = print_insn_sh;
|
||||
diff --exclude='*.orig' --exclude=CVS -ruN qemu/disas.c qemu-z80/disas.c
|
||||
--- qemu/disas.c 2007-06-03 21:16:42.000000000 +0200
|
||||
+++ qemu-z80/disas.c 2007-07-05 18:03:59.000000000 +0200
|
||||
@@ -200,6 +200,8 @@
|
||||
#elif defined(TARGET_ALPHA)
|
||||
disasm_info.mach = bfd_mach_alpha;
|
||||
print_insn = print_insn_alpha;
|
||||
+#elif defined(TARGET_Z80)
|
||||
+ print_insn = print_insn_z80;
|
||||
#else
|
||||
fprintf(out, "0x" TARGET_FMT_lx
|
||||
": Asm output not supported on this arch\n", code);
|
||||
diff -urN qemu-0.9.0/dis-asm.h qemu-z80/dis-asm.h
|
||||
--- qemu-0.9.0/dis-asm.h 2007-02-05 23:01:54.000000000 +0000
|
||||
+++ qemu-z80/dis-asm.h 2007-03-27 21:07:11.000000000 +0100
|
||||
@@ -377,6 +377,7 @@
|
||||
extern int print_insn_v850 PARAMS ((bfd_vma, disassemble_info*));
|
||||
diff --exclude='*.orig' --exclude=CVS -ruN qemu/dis-asm.h qemu-z80/dis-asm.h
|
||||
--- qemu/dis-asm.h 2007-04-05 09:22:49.000000000 +0200
|
||||
+++ qemu-z80/dis-asm.h 2007-07-05 18:05:17.000000000 +0200
|
||||
@@ -379,6 +379,7 @@
|
||||
extern int print_insn_tic30 PARAMS ((bfd_vma, disassemble_info*));
|
||||
extern int print_insn_ppc PARAMS ((bfd_vma, disassemble_info*));
|
||||
extern int print_insn_alpha PARAMS ((bfd_vma, disassemble_info*));
|
||||
+extern int print_insn_z80 PARAMS ((bfd_vma, disassemble_info*));
|
||||
|
||||
#if 0
|
||||
/* Fetch the disassembler for a given BFD, if that support is available. */
|
||||
diff -urN qemu-0.9.0/exec-all.h qemu-z80/exec-all.h
|
||||
--- qemu-0.9.0/exec-all.h 2007-02-05 23:01:54.000000000 +0000
|
||||
+++ qemu-z80/exec-all.h 2007-04-17 21:26:41.000000000 +0100
|
||||
diff --exclude='*.orig' --exclude=CVS -ruN qemu/exec-all.h qemu-z80/exec-all.h
|
||||
--- qemu/exec-all.h 2007-07-02 16:06:26.000000000 +0200
|
||||
+++ qemu-z80/exec-all.h 2007-07-05 18:04:44.000000000 +0200
|
||||
@@ -69,7 +69,7 @@
|
||||
typedef void (GenOpFunc2)(long, long);
|
||||
typedef void (GenOpFunc3)(long, long, long);
|
||||
@ -134,19 +164,19 @@ diff -urN qemu-0.9.0/exec-all.h qemu-z80/exec-all.h
|
||||
|
||||
void optimize_flags_init(void);
|
||||
|
||||
@@ -572,6 +572,8 @@
|
||||
is_user = ((env->uncached_cpsr & CPSR_M) == ARM_CPU_MODE_USR);
|
||||
#elif defined (TARGET_SH4)
|
||||
is_user = ((env->sr & SR_MD) == 0);
|
||||
@@ -586,6 +586,8 @@
|
||||
is_user = ((env->ps >> 3) & 3);
|
||||
#elif defined (TARGET_M68K)
|
||||
is_user = ((env->sr & SR_S) == 0);
|
||||
+#elif defined (TARGET_Z80)
|
||||
+ is_user = 0; /* no user-mode */
|
||||
#else
|
||||
#error unimplemented CPU
|
||||
#endif
|
||||
diff -urN qemu-0.9.0/exec.c qemu-z80/exec.c
|
||||
--- qemu-0.9.0/exec.c 2007-02-05 23:01:54.000000000 +0000
|
||||
+++ qemu-z80/exec.c 2007-04-15 22:54:52.000000000 +0100
|
||||
@@ -679,6 +679,9 @@
|
||||
diff --exclude='*.orig' --exclude=CVS -ruN qemu/exec.c qemu-z80/exec.c
|
||||
--- qemu/exec.c 2007-07-01 20:21:11.000000000 +0200
|
||||
+++ qemu-z80/exec.c 2007-07-06 12:04:38.000000000 +0200
|
||||
@@ -709,6 +709,9 @@
|
||||
current_flags |= (env->eflags & (IOPL_MASK | TF_MASK | VM_MASK));
|
||||
current_cs_base = (target_ulong)env->segs[R_CS].base;
|
||||
current_pc = current_cs_base + env->eip;
|
||||
@ -156,12 +186,12 @@ diff -urN qemu-0.9.0/exec.c qemu-z80/exec.c
|
||||
#else
|
||||
#error unsupported CPU
|
||||
#endif
|
||||
diff -urN qemu-0.9.0/gdbstub.c qemu-z80/gdbstub.c
|
||||
--- qemu-0.9.0/gdbstub.c 2007-02-05 23:01:54.000000000 +0000
|
||||
+++ qemu-z80/gdbstub.c 2007-04-04 21:35:14.000000000 +0100
|
||||
@@ -700,6 +700,34 @@
|
||||
LOAD (env->macl);
|
||||
LOAD (env->sr);
|
||||
diff --exclude='*.orig' --exclude=CVS -ruN qemu/gdbstub.c qemu-z80/gdbstub.c
|
||||
--- qemu/gdbstub.c 2007-06-03 19:08:32.000000000 +0200
|
||||
+++ qemu-z80/gdbstub.c 2007-07-05 18:03:12.000000000 +0200
|
||||
@@ -718,6 +718,34 @@
|
||||
for (i = 0; i < 8; i++) LOAD(env->gregs[i]);
|
||||
for (i = 0; i < 8; i++) LOAD(env->gregs[i + 16]);
|
||||
}
|
||||
+#elif defined(TARGET_Z80)
|
||||
+/* Z80 FIXME Z80 TODO Z80 */
|
||||
@ -194,10 +224,10 @@ diff -urN qemu-0.9.0/gdbstub.c qemu-z80/gdbstub.c
|
||||
#else
|
||||
static int cpu_gdb_read_registers(CPUState *env, uint8_t *mem_buf)
|
||||
{
|
||||
diff -urN qemu-0.9.0/hw/zx_spectrum.c qemu-z80/hw/zx_spectrum.c
|
||||
--- qemu-0.9.0/hw/zx_spectrum.c 1970-01-01 01:00:00.000000000 +0100
|
||||
+++ qemu-z80/hw/zx_spectrum.c 2007-04-17 20:27:16.000000000 +0100
|
||||
@@ -0,0 +1,236 @@
|
||||
diff --exclude='*.orig' --exclude=CVS -ruN qemu/hw/zx_spectrum.c qemu-z80/hw/zx_spectrum.c
|
||||
--- qemu/hw/zx_spectrum.c 1970-01-01 01:00:00.000000000 +0100
|
||||
+++ qemu-z80/hw/zx_spectrum.c 2007-07-06 13:17:46.000000000 +0200
|
||||
@@ -0,0 +1,303 @@
|
||||
+/*
|
||||
+ * QEMU ZX Spectrum Emulator
|
||||
+ *
|
||||
@ -223,6 +253,9 @@ diff -urN qemu-0.9.0/hw/zx_spectrum.c qemu-z80/hw/zx_spectrum.c
|
||||
+ * THE SOFTWARE.
|
||||
+ */
|
||||
+#include "vl.h"
|
||||
+#ifdef CONFIG_LIBSPECTRUM
|
||||
+#include <libspectrum.h>
|
||||
+#endif
|
||||
+
|
||||
+/* output Bochs bios info messages */
|
||||
+//#define DEBUG_BIOS
|
||||
@ -259,12 +292,14 @@ diff -urN qemu-0.9.0/hw/zx_spectrum.c qemu-z80/hw/zx_spectrum.c
|
||||
+ return io_keyboard_read(opaque, addr);
|
||||
+}
|
||||
+
|
||||
+#if 0
|
||||
+/* MSDOS compatibility mode FPU exception support */
|
||||
+/* XXX: add IGNNE support */
|
||||
+void cpu_set_ferr(CPUZ80State *s)
|
||||
+{
|
||||
+ pic_set_irq(13, 1);
|
||||
+}
|
||||
+#endif
|
||||
+
|
||||
+/* TSC handling */
|
||||
+uint64_t cpu_get_tsc(CPUZ80State *env)
|
||||
@ -380,7 +415,7 @@ diff -urN qemu-0.9.0/hw/zx_spectrum.c qemu-z80/hw/zx_spectrum.c
|
||||
+ register_savevm("cpu", 0, 4, cpu_save, cpu_load, env);
|
||||
+ qemu_register_reset(main_cpu_reset, env);
|
||||
+
|
||||
+ cpu_register_physical_memory(0, 0x10000, 0);
|
||||
+ cpu_register_physical_memory(0x4000, 0x10000 - 0x4000, 0 | IO_MEM_RAM);
|
||||
+
|
||||
+ /* allocate RAM */
|
||||
+// ram_addr = qemu_ram_alloc(0x10000 - 0x5b00);
|
||||
@ -412,8 +447,70 @@ diff -urN qemu-0.9.0/hw/zx_spectrum.c qemu-z80/hw/zx_spectrum.c
|
||||
+ register_ioport_read(0, 0x10000, 1, io_spectrum_read, NULL);
|
||||
+
|
||||
+ zx_ula_init(ds, phys_ram_base + ram_size, ram_size);
|
||||
+
|
||||
+ zx_keyboard_init();
|
||||
+ zx_timer_init(ds);
|
||||
+
|
||||
+#ifdef CONFIG_LIBSPECTRUM
|
||||
+ if(kernel_filename) {
|
||||
+ libspectrum_id_t type;
|
||||
+ libspectrum_class_t cls;
|
||||
+ libspectrum_snap* snap;
|
||||
+ uint8_t* snapmem;
|
||||
+ libspectrum_byte* page;
|
||||
+ int length;
|
||||
+ int i;
|
||||
+ if(libspectrum_init() != LIBSPECTRUM_ERROR_NONE ||
|
||||
+ libspectrum_identify_file(&type, kernel_filename, NULL, 0) != LIBSPECTRUM_ERROR_NONE ||
|
||||
+ libspectrum_identify_class(&cls, type) != LIBSPECTRUM_ERROR_NONE ||
|
||||
+ libspectrum_snap_alloc(&snap) != LIBSPECTRUM_ERROR_NONE) {
|
||||
+ fprintf(stderr, "%s: libspectrum error\n", __FUNCTION__);
|
||||
+ exit(1);
|
||||
+ }
|
||||
+ if(cls != LIBSPECTRUM_CLASS_SNAPSHOT) {
|
||||
+ fprintf(stderr, "%s: %s is not a snapshot\n", __FUNCTION__, kernel_filename);
|
||||
+ exit(1);
|
||||
+ }
|
||||
+ snapmem = malloc(65536);
|
||||
+ length = load_image(kernel_filename, snapmem);
|
||||
+ //printf("loaded %d bytes from %s\n",length, kernel_filename);
|
||||
+ if(libspectrum_snap_read(snap, snapmem, length, type, NULL) != LIBSPECTRUM_ERROR_NONE) {
|
||||
+ fprintf(stderr, "%s: failed to load snapshot %s\n", __FUNCTION__, kernel_filename);
|
||||
+ exit(1);
|
||||
+ }
|
||||
+ //printf("snap pc = %d\n",libspectrum_snap_pc(snap));
|
||||
+ page = libspectrum_snap_pages(snap, 5);
|
||||
+ for(i = 0x4000; i < 0x8000; i++) {
|
||||
+ //printf("storing 0x%x in 0x%x\n",page[i-0x4000],i);
|
||||
+ stb_phys(i, page[i - 0x4000]);
|
||||
+ }
|
||||
+ page = libspectrum_snap_pages(snap, 2);
|
||||
+ for(i = 0x8000; i < 0xc000; i++)
|
||||
+ stb_phys(i, page[i - 0x8000]);
|
||||
+ page = libspectrum_snap_pages(snap, 0);
|
||||
+ for(i = 0xc000; i < 0x10000; i++)
|
||||
+ stb_phys(i, page[i - 0xc000]);
|
||||
+ env->regs[R_A] = libspectrum_snap_a(snap);
|
||||
+ env->regs[R_F] = libspectrum_snap_f(snap);
|
||||
+ env->regs[R_BC] = libspectrum_snap_bc(snap);
|
||||
+ env->regs[R_DE] = libspectrum_snap_de(snap);
|
||||
+ env->regs[R_HL] = libspectrum_snap_hl(snap);
|
||||
+ env->regs[R_AFX] = libspectrum_snap_a_(snap) << 8 | libspectrum_snap_f_(snap);
|
||||
+ env->regs[R_BCX] = libspectrum_snap_bc_(snap);
|
||||
+ env->regs[R_DEX] = libspectrum_snap_de_(snap);
|
||||
+ env->regs[R_HLX] = libspectrum_snap_hl_(snap);
|
||||
+ env->regs[R_IX] = libspectrum_snap_ix(snap);
|
||||
+ env->regs[R_IY] = libspectrum_snap_iy(snap);
|
||||
+ env->regs[R_I] = libspectrum_snap_i(snap);
|
||||
+ env->regs[R_R] = libspectrum_snap_r(snap);
|
||||
+ env->regs[R_SP] = libspectrum_snap_sp(snap);
|
||||
+ env->pc = libspectrum_snap_pc(snap);
|
||||
+ env->iff1 = libspectrum_snap_iff1(snap);
|
||||
+ env->iff2 = libspectrum_snap_iff2(snap);
|
||||
+ env->imode = libspectrum_snap_im(snap);
|
||||
+
|
||||
+ }
|
||||
+#endif
|
||||
+}
|
||||
+
|
||||
+static void zx_spectrum_init(int ram_size, int vga_ram_size, int boot_device,
|
||||
@ -434,9 +531,9 @@ diff -urN qemu-0.9.0/hw/zx_spectrum.c qemu-z80/hw/zx_spectrum.c
|
||||
+ "Z80 Machine",
|
||||
+ zx_spectrum_init,
|
||||
+};
|
||||
diff -urN qemu-0.9.0/hw/zx_ula.c qemu-z80/hw/zx_ula.c
|
||||
--- qemu-0.9.0/hw/zx_ula.c 1970-01-01 01:00:00.000000000 +0100
|
||||
+++ qemu-z80/hw/zx_ula.c 2007-04-17 20:55:28.000000000 +0100
|
||||
diff --exclude='*.orig' --exclude=CVS -ruN qemu/hw/zx_ula.c qemu-z80/hw/zx_ula.c
|
||||
--- qemu/hw/zx_ula.c 1970-01-01 01:00:00.000000000 +0100
|
||||
+++ qemu-z80/hw/zx_ula.c 2007-07-06 13:01:14.000000000 +0200
|
||||
@@ -0,0 +1,355 @@
|
||||
+/*
|
||||
+ * QEMU ZX Spectrum Video Emulation.
|
||||
@ -652,8 +749,8 @@ diff -urN qemu-0.9.0/hw/zx_ula.c qemu-z80/hw/zx_ula.c
|
||||
+ ZXVState *s = (ZXVState *)opaque;
|
||||
+ uint32_t addr, attrib;
|
||||
+
|
||||
+ if (!s->dirty)
|
||||
+ return;
|
||||
+ //if (!s->dirty)
|
||||
+ // return;
|
||||
+
|
||||
+ d = s->ds->data;
|
||||
+ d += s->bheight * s->ds->linesize;
|
||||
@ -783,43 +880,46 @@ diff -urN qemu-0.9.0/hw/zx_ula.c qemu-z80/hw/zx_ula.c
|
||||
+ s->border = 0;
|
||||
+ dpy_resize(s->ds, s->twidth, s->theight);
|
||||
+
|
||||
+ zx_io_memory = cpu_register_io_memory(0, zx_mem_read, zx_mem_write, s);
|
||||
+ cpu_register_physical_memory(0x4000, 0x1b00, zx_io_memory);
|
||||
+ //zx_io_memory = cpu_register_io_memory(0, zx_mem_read, zx_mem_write, s);
|
||||
+ //cpu_register_physical_memory(0x4000, 0x2000, zx_io_memory);
|
||||
+// cpu_register_physical_memory(0x4000, 0x2000, zx_io_memory);
|
||||
+// cpu_register_physical_memory(0x4000, 0xc000, zx_io_memory);
|
||||
+ s->vram_ptr = phys_ram_base + zx_io_memory;
|
||||
+ s->vram_offset = zx_io_memory;
|
||||
+ s->vram_ptr = phys_ram_base + 0;//x4000;//zx_io_memory;
|
||||
+ s->vram_offset = 0;//x4000;//zx_io_memory;
|
||||
+
|
||||
+ /* ZX Spectrum ULA */
|
||||
+ register_ioport_write(0, 0x10000, 1, io_spectrum_write, s);
|
||||
+}
|
||||
diff -urN qemu-0.9.0/Makefile qemu-z80/Makefile
|
||||
--- qemu-0.9.0/Makefile 2007-02-05 23:01:54.000000000 +0000
|
||||
+++ qemu-z80/Makefile 2007-03-27 21:07:11.000000000 +0100
|
||||
@@ -79,7 +79,7 @@
|
||||
diff --exclude='*.orig' --exclude=CVS -ruN qemu/Makefile qemu-z80/Makefile
|
||||
--- qemu/Makefile 2007-06-17 18:41:04.000000000 +0200
|
||||
+++ qemu-z80/Makefile 2007-07-05 18:07:36.000000000 +0200
|
||||
@@ -72,7 +72,7 @@
|
||||
mkdir -p "$(DESTDIR)$(datadir)"
|
||||
for x in bios.bin vgabios.bin vgabios-cirrus.bin ppc_rom.bin \
|
||||
video.x openbios-sparc32 linux_boot.bin pxe-ne2k_pci.bin \
|
||||
video.x openbios-sparc32 pxe-ne2k_pci.bin \
|
||||
- pxe-rtl8139.bin pxe-pcnet.bin; do \
|
||||
+ pxe-rtl8139.bin pxe-pcnet.bin zx-rom.bin ; do \
|
||||
$(INSTALL) -m 644 $(SRC_PATH)/pc-bios/$$x "$(DESTDIR)$(datadir)"; \
|
||||
done
|
||||
ifndef CONFIG_WIN32
|
||||
diff -urN qemu-0.9.0/Makefile.target qemu-z80/Makefile.target
|
||||
--- qemu-0.9.0/Makefile.target 2007-02-05 23:01:54.000000000 +0000
|
||||
+++ qemu-z80/Makefile.target 2007-04-15 19:35:13.000000000 +0100
|
||||
@@ -271,6 +271,10 @@
|
||||
LIBOBJS+= helper.o
|
||||
diff --exclude='*.orig' --exclude=CVS -ruN qemu/Makefile.target qemu-z80/Makefile.target
|
||||
--- qemu/Makefile.target 2007-06-30 19:32:17.000000000 +0200
|
||||
+++ qemu-z80/Makefile.target 2007-07-06 14:59:02.000000000 +0200
|
||||
@@ -315,6 +315,13 @@
|
||||
LIBOBJS+= op_helper.o helper.o alpha_palcode.o
|
||||
endif
|
||||
|
||||
+ifeq ($(TARGET_BASE_ARCH), z80)
|
||||
+LIBOBJS+=helper.o helper2.o
|
||||
+ifdef CONFIG_LIBSPECTRUM
|
||||
+LIBS+=-lspectrum
|
||||
+endif
|
||||
+endif
|
||||
+
|
||||
# NOTE: the disassembler code is only needed for debugging
|
||||
LIBOBJS+=disas.o
|
||||
ifeq ($(findstring i386, $(TARGET_ARCH) $(ARCH)),i386)
|
||||
@@ -303,6 +307,9 @@
|
||||
@@ -347,6 +354,9 @@
|
||||
ifeq ($(findstring sh4, $(TARGET_ARCH) $(ARCH)),sh4)
|
||||
LIBOBJS+=sh4-dis.o
|
||||
endif
|
||||
@ -829,9 +929,9 @@ diff -urN qemu-0.9.0/Makefile.target qemu-z80/Makefile.target
|
||||
|
||||
ifdef CONFIG_GDBSTUB
|
||||
OBJS+=gdbstub.o
|
||||
@@ -407,6 +414,10 @@
|
||||
ifeq ($(TARGET_BASE_ARCH), sh4)
|
||||
VL_OBJS+= shix.o sh7750.o sh7750_regnames.o tc58128.o
|
||||
@@ -472,6 +482,10 @@
|
||||
VL_OBJS+= an5206.o mcf5206.o ptimer.o mcf_uart.o mcf_intc.o mcf5208.o mcf_fec.o
|
||||
VL_OBJS+= m68k-semi.o
|
||||
endif
|
||||
+ifeq ($(TARGET_BASE_ARCH), z80)
|
||||
+VL_OBJS+= zx_spectrum.o zx_ula.o dma.o $(AUDIODRV)
|
||||
@ -840,7 +940,7 @@ diff -urN qemu-0.9.0/Makefile.target qemu-z80/Makefile.target
|
||||
ifdef CONFIG_GDBSTUB
|
||||
VL_OBJS+=gdbstub.o
|
||||
endif
|
||||
@@ -514,9 +525,15 @@
|
||||
@@ -582,9 +596,15 @@
|
||||
helper.o: helper.c
|
||||
$(CC) $(HELPER_CFLAGS) $(CPPFLAGS) $(BASE_CFLAGS) -c -o $@ $<
|
||||
else
|
||||
@ -856,7 +956,7 @@ diff -urN qemu-0.9.0/Makefile.target qemu-z80/Makefile.target
|
||||
|
||||
cpu-exec.o: cpu-exec.c
|
||||
$(CC) $(HELPER_CFLAGS) $(CPPFLAGS) $(BASE_CFLAGS) -c -o $@ $<
|
||||
@@ -529,6 +546,9 @@
|
||||
@@ -601,6 +621,9 @@
|
||||
ifeq ($(TARGET_BASE_ARCH), i386)
|
||||
op.o: op.c opreg_template.h ops_template.h ops_template_mem.h ops_mem.h ops_sse.h
|
||||
endif
|
||||
@ -866,32 +966,32 @@ diff -urN qemu-0.9.0/Makefile.target qemu-z80/Makefile.target
|
||||
|
||||
ifeq ($(TARGET_ARCH), arm)
|
||||
op.o: op.c op_template.h
|
||||
Binary files qemu-0.9.0/pc-bios/zx-rom.bin and qemu-z80/pc-bios/zx-rom.bin differ
|
||||
diff -urN qemu-0.9.0/softmmu_header.h qemu-z80/softmmu_header.h
|
||||
--- qemu-0.9.0/softmmu_header.h 2007-02-05 23:01:54.000000000 +0000
|
||||
+++ qemu-z80/softmmu_header.h 2007-03-27 21:07:11.000000000 +0100
|
||||
@@ -63,6 +63,8 @@
|
||||
#define CPU_MEM_INDEX ((env->uncached_cpsr & CPSR_M) == ARM_CPU_MODE_USR)
|
||||
#elif defined (TARGET_SH4)
|
||||
#define CPU_MEM_INDEX ((env->sr & SR_MD) == 0)
|
||||
Files qemu/school.z80 and qemu-z80/school.z80 differ
|
||||
diff --exclude='*.orig' --exclude=CVS -ruN qemu/softmmu_header.h qemu-z80/softmmu_header.h
|
||||
--- qemu/softmmu_header.h 2007-05-23 21:58:10.000000000 +0200
|
||||
+++ qemu-z80/softmmu_header.h 2007-07-05 18:11:08.000000000 +0200
|
||||
@@ -67,6 +67,8 @@
|
||||
#define CPU_MEM_INDEX ((env->ps >> 3) & 3)
|
||||
#elif defined (TARGET_M68K)
|
||||
#define CPU_MEM_INDEX ((env->sr & SR_S) == 0)
|
||||
+#elif defined (TARGET_Z80)
|
||||
+#define CPU_MEM_INDEX ((env->hflags & HF_CPL_MASK) == 3)
|
||||
#else
|
||||
#error unsupported CPU
|
||||
#endif
|
||||
@@ -82,6 +84,8 @@
|
||||
#define CPU_MEM_INDEX ((env->uncached_cpsr & CPSR_M) == ARM_CPU_MODE_USR)
|
||||
#elif defined (TARGET_SH4)
|
||||
#define CPU_MEM_INDEX ((env->sr & SR_MD) == 0)
|
||||
@@ -90,6 +92,8 @@
|
||||
#define CPU_MEM_INDEX ((env->ps >> 3) & 3)
|
||||
#elif defined (TARGET_M68K)
|
||||
#define CPU_MEM_INDEX ((env->sr & SR_S) == 0)
|
||||
+#elif defined (TARGET_Z80)
|
||||
+#define CPU_MEM_INDEX ((env->hflags & HF_CPL_MASK) == 3)
|
||||
#else
|
||||
#error unsupported CPU
|
||||
#endif
|
||||
diff -urN qemu-0.9.0/target-z80/cpu.h qemu-z80/target-z80/cpu.h
|
||||
--- qemu-0.9.0/target-z80/cpu.h 1970-01-01 01:00:00.000000000 +0100
|
||||
+++ qemu-z80/target-z80/cpu.h 2007-04-17 21:05:57.000000000 +0100
|
||||
@@ -0,0 +1,235 @@
|
||||
diff --exclude='*.orig' --exclude=CVS -ruN qemu/target-z80/cpu.h qemu-z80/target-z80/cpu.h
|
||||
--- qemu/target-z80/cpu.h 1970-01-01 01:00:00.000000000 +0100
|
||||
+++ qemu-z80/target-z80/cpu.h 2007-07-06 11:59:06.000000000 +0200
|
||||
@@ -0,0 +1,243 @@
|
||||
+/*
|
||||
+ * Z80 virtual CPU header
|
||||
+ *
|
||||
@ -1083,6 +1183,7 @@ diff -urN qemu-0.9.0/target-z80/cpu.h qemu-z80/target-z80/cpu.h
|
||||
+ uint32_t smbase;
|
||||
+ int interrupt_request;
|
||||
+ int user_mode_only; /* user mode only simulation */
|
||||
+ int halted;
|
||||
+
|
||||
+ CPU_COMMON
|
||||
+
|
||||
@ -1124,13 +1225,20 @@ diff -urN qemu-0.9.0/target-z80/cpu.h qemu-z80/target-z80/cpu.h
|
||||
+void cpu_smm_update(CPUZ80State *env);
|
||||
+
|
||||
+#define TARGET_PAGE_BITS 12
|
||||
+
|
||||
+#define CPUState CPUZ80State
|
||||
+#define cpu_init cpu_z80_init
|
||||
+#define cpu_exec cpu_z80_exec
|
||||
+#define cpu_gen_code cpu_z80_gen_code
|
||||
+#define cpu_signal_handler cpu_z80_signal_handler
|
||||
+
|
||||
+#include "cpu-all.h"
|
||||
+
|
||||
+#endif /* CPU_Z80_H */
|
||||
diff -urN qemu-0.9.0/target-z80/exec.h qemu-z80/target-z80/exec.h
|
||||
--- qemu-0.9.0/target-z80/exec.h 1970-01-01 01:00:00.000000000 +0100
|
||||
+++ qemu-z80/target-z80/exec.h 2007-04-17 21:02:26.000000000 +0100
|
||||
@@ -0,0 +1,361 @@
|
||||
diff --exclude='*.orig' --exclude=CVS -ruN qemu/target-z80/exec.h qemu-z80/target-z80/exec.h
|
||||
--- qemu/target-z80/exec.h 1970-01-01 01:00:00.000000000 +0100
|
||||
+++ qemu-z80/target-z80/exec.h 2007-07-05 18:30:59.000000000 +0200
|
||||
@@ -0,0 +1,372 @@
|
||||
+/*
|
||||
+ * Z80 execution defines
|
||||
+ *
|
||||
@ -1492,9 +1600,20 @@ diff -urN qemu-0.9.0/target-z80/exec.h qemu-z80/target-z80/exec.h
|
||||
+ env->regs[R_HLX] = HLX;
|
||||
+#endif
|
||||
+}
|
||||
diff -urN qemu-0.9.0/target-z80/helper2.c qemu-z80/target-z80/helper2.c
|
||||
--- qemu-0.9.0/target-z80/helper2.c 1970-01-01 01:00:00.000000000 +0100
|
||||
+++ qemu-z80/target-z80/helper2.c 2007-04-17 21:29:49.000000000 +0100
|
||||
+
|
||||
+static inline int cpu_halted(CPUState* env) {
|
||||
+ if (!env->halted)
|
||||
+ return 0;
|
||||
+ if (env->interrupt_request & CPU_INTERRUPT_HARD) {
|
||||
+ env->halted = 0;
|
||||
+ env->hflags &= ~HF_HALTED_MASK;
|
||||
+ return 0;
|
||||
+ }
|
||||
+ return EXCP_HALTED;
|
||||
+}
|
||||
diff --exclude='*.orig' --exclude=CVS -ruN qemu/target-z80/helper2.c qemu-z80/target-z80/helper2.c
|
||||
--- qemu/target-z80/helper2.c 1970-01-01 01:00:00.000000000 +0100
|
||||
+++ qemu-z80/target-z80/helper2.c 2007-07-05 18:37:36.000000000 +0200
|
||||
@@ -0,0 +1,170 @@
|
||||
+/*
|
||||
+ * Z80 helpers (without register variable usage)
|
||||
@ -1655,7 +1774,7 @@ diff -urN qemu-0.9.0/target-z80/helper2.c qemu-z80/target-z80/helper2.c
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+target_ulong cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
|
||||
+target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
|
||||
+{
|
||||
+ uint32_t pte, paddr, page_offset, page_size;
|
||||
+
|
||||
@ -1666,10 +1785,10 @@ diff -urN qemu-0.9.0/target-z80/helper2.c qemu-z80/target-z80/helper2.c
|
||||
+ paddr = (pte & TARGET_PAGE_MASK) + page_offset;
|
||||
+ return paddr;
|
||||
+}
|
||||
diff -urN qemu-0.9.0/target-z80/helper.c qemu-z80/target-z80/helper.c
|
||||
--- qemu-0.9.0/target-z80/helper.c 1970-01-01 01:00:00.000000000 +0100
|
||||
+++ qemu-z80/target-z80/helper.c 2007-04-25 17:54:06.000000000 +0100
|
||||
@@ -0,0 +1,283 @@
|
||||
diff --exclude='*.orig' --exclude=CVS -ruN qemu/target-z80/helper.c qemu-z80/target-z80/helper.c
|
||||
--- qemu/target-z80/helper.c 1970-01-01 01:00:00.000000000 +0100
|
||||
+++ qemu-z80/target-z80/helper.c 2007-07-05 18:38:49.000000000 +0200
|
||||
@@ -0,0 +1,276 @@
|
||||
+/*
|
||||
+ * Z80 helpers
|
||||
+ *
|
||||
@ -1760,14 +1879,6 @@ diff -urN qemu-0.9.0/target-z80/helper.c qemu-z80/target-z80/helper.c
|
||||
+ spin_unlock(&global_cpu_lock);
|
||||
+}
|
||||
+
|
||||
+void cpu_loop_exit(void)
|
||||
+{
|
||||
+ /* NOTE: the register at this point must be saved by hand because
|
||||
+ longjmp restore them */
|
||||
+ regs_to_env();
|
||||
+ longjmp(env->jmp_env, 1);
|
||||
+}
|
||||
+
|
||||
+void do_interrupt(CPUZ80State *env)
|
||||
+{
|
||||
+// printf("z80: do_interrupt()\n");
|
||||
@ -1849,6 +1960,7 @@ diff -urN qemu-0.9.0/target-z80/helper.c qemu-z80/target-z80/helper.c
|
||||
+
|
||||
+void helper_hlt(void)
|
||||
+{
|
||||
+ env->halted = 1;
|
||||
+ env->hflags &= ~HF_INHIBIT_IRQ_MASK; /* needed if sti is just before */
|
||||
+ env->hflags |= HF_HALTED_MASK;
|
||||
+ env->exception_index = EXCP_HLT;
|
||||
@ -1953,9 +2065,9 @@ diff -urN qemu-0.9.0/target-z80/helper.c qemu-z80/target-z80/helper.c
|
||||
+ fl & 0x01 ? 'C' : '-',
|
||||
+ env->imode, env->iff1, env->iff2, env->regs[R_I], env->regs[R_R]);
|
||||
+}
|
||||
diff -urN qemu-0.9.0/target-z80/op.c qemu-z80/target-z80/op.c
|
||||
--- qemu-0.9.0/target-z80/op.c 1970-01-01 01:00:00.000000000 +0100
|
||||
+++ qemu-z80/target-z80/op.c 2007-04-25 17:41:33.000000000 +0100
|
||||
diff --exclude='*.orig' --exclude=CVS -ruN qemu/target-z80/op.c qemu-z80/target-z80/op.c
|
||||
--- qemu/target-z80/op.c 1970-01-01 01:00:00.000000000 +0100
|
||||
+++ qemu-z80/target-z80/op.c 2007-07-05 18:03:12.000000000 +0200
|
||||
@@ -0,0 +1,1175 @@
|
||||
+/*
|
||||
+ * Z80 micro operations
|
||||
@ -3132,9 +3244,9 @@ diff -urN qemu-0.9.0/target-z80/op.c qemu-z80/target-z80/op.c
|
||||
+{
|
||||
+ cpu_unlock();
|
||||
+}
|
||||
diff -urN qemu-0.9.0/target-z80/opreg_template2.h qemu-z80/target-z80/opreg_template2.h
|
||||
--- qemu-0.9.0/target-z80/opreg_template2.h 1970-01-01 01:00:00.000000000 +0100
|
||||
+++ qemu-z80/target-z80/opreg_template2.h 2007-03-27 21:42:55.000000000 +0100
|
||||
diff --exclude='*.orig' --exclude=CVS -ruN qemu/target-z80/opreg_template2.h qemu-z80/target-z80/opreg_template2.h
|
||||
--- qemu/target-z80/opreg_template2.h 1970-01-01 01:00:00.000000000 +0100
|
||||
+++ qemu-z80/target-z80/opreg_template2.h 2007-07-05 18:03:12.000000000 +0200
|
||||
@@ -0,0 +1,63 @@
|
||||
+/*
|
||||
+ * Z80 micro operations (templates for various register related
|
||||
@ -3199,9 +3311,9 @@ diff -urN qemu-0.9.0/target-z80/opreg_template2.h qemu-z80/target-z80/opreg_temp
|
||||
+ REGHIGH = (uint16_t)(T1 >> 8);
|
||||
+ REGLOW = (uint16_t)T1;
|
||||
+}
|
||||
diff -urN qemu-0.9.0/target-z80/opreg_template.h qemu-z80/target-z80/opreg_template.h
|
||||
--- qemu-0.9.0/target-z80/opreg_template.h 1970-01-01 01:00:00.000000000 +0100
|
||||
+++ qemu-z80/target-z80/opreg_template.h 2007-03-27 21:43:07.000000000 +0100
|
||||
diff --exclude='*.orig' --exclude=CVS -ruN qemu/target-z80/opreg_template.h qemu-z80/target-z80/opreg_template.h
|
||||
--- qemu/target-z80/opreg_template.h 1970-01-01 01:00:00.000000000 +0100
|
||||
+++ qemu-z80/target-z80/opreg_template.h 2007-07-05 18:03:12.000000000 +0200
|
||||
@@ -0,0 +1,74 @@
|
||||
+/*
|
||||
+ * Z80 micro operations (templates for various register related
|
||||
@ -3277,9 +3389,9 @@ diff -urN qemu-0.9.0/target-z80/opreg_template.h qemu-z80/target-z80/opreg_templ
|
||||
+{
|
||||
+ REG = (uint16_t)T1;
|
||||
+}
|
||||
diff -urN qemu-0.9.0/target-z80/ops_mem.h qemu-z80/target-z80/ops_mem.h
|
||||
--- qemu-0.9.0/target-z80/ops_mem.h 1970-01-01 01:00:00.000000000 +0100
|
||||
+++ qemu-z80/target-z80/ops_mem.h 2007-04-15 19:39:49.000000000 +0100
|
||||
diff --exclude='*.orig' --exclude=CVS -ruN qemu/target-z80/ops_mem.h qemu-z80/target-z80/ops_mem.h
|
||||
--- qemu/target-z80/ops_mem.h 1970-01-01 01:00:00.000000000 +0100
|
||||
+++ qemu-z80/target-z80/ops_mem.h 2007-07-05 18:03:12.000000000 +0200
|
||||
@@ -0,0 +1,59 @@
|
||||
+void OPPROTO glue(glue(op_ldub, MEMSUFFIX), _T0_A0)(void)
|
||||
+{
|
||||
@ -3340,9 +3452,9 @@ diff -urN qemu-0.9.0/target-z80/ops_mem.h qemu-z80/target-z80/ops_mem.h
|
||||
+}
|
||||
+
|
||||
+#undef MEMSUFFIX
|
||||
diff -urN qemu-0.9.0/target-z80/translate.c qemu-z80/target-z80/translate.c
|
||||
--- qemu-0.9.0/target-z80/translate.c 1970-01-01 01:00:00.000000000 +0100
|
||||
+++ qemu-z80/target-z80/translate.c 2007-04-25 17:54:16.000000000 +0100
|
||||
diff --exclude='*.orig' --exclude=CVS -ruN qemu/target-z80/translate.c qemu-z80/target-z80/translate.c
|
||||
--- qemu/target-z80/translate.c 1970-01-01 01:00:00.000000000 +0100
|
||||
+++ qemu-z80/target-z80/translate.c 2007-07-05 18:03:12.000000000 +0200
|
||||
@@ -0,0 +1,1600 @@
|
||||
+/*
|
||||
+ * Z80 translation
|
||||
@ -4944,10 +5056,10 @@ diff -urN qemu-0.9.0/target-z80/translate.c qemu-z80/target-z80/translate.c
|
||||
+ return gen_intermediate_code_internal(env, tb, 1);
|
||||
+}
|
||||
+
|
||||
diff -urN qemu-0.9.0/vl.c qemu-z80/vl.c
|
||||
--- qemu-0.9.0/vl.c 2007-02-05 23:01:54.000000000 +0000
|
||||
+++ qemu-z80/vl.c 2007-04-25 17:58:06.000000000 +0100
|
||||
@@ -5201,6 +5201,7 @@
|
||||
diff --exclude='*.orig' --exclude=CVS -ruN qemu/vl.c qemu-z80/vl.c
|
||||
--- qemu/vl.c 2007-07-02 17:03:13.000000000 +0200
|
||||
+++ qemu-z80/vl.c 2007-07-05 18:09:48.000000000 +0200
|
||||
@@ -5595,6 +5595,7 @@
|
||||
qemu_get_be64s(f, &env->fmask);
|
||||
qemu_get_be64s(f, &env->kernelgsbase);
|
||||
#endif
|
||||
@ -4955,7 +5067,7 @@ diff -urN qemu-0.9.0/vl.c qemu-z80/vl.c
|
||||
if (version_id >= 4)
|
||||
qemu_get_be32s(f, &env->smbase);
|
||||
|
||||
@@ -5319,6 +5320,19 @@
|
||||
@@ -5846,6 +5847,19 @@
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -4975,21 +5087,21 @@ diff -urN qemu-0.9.0/vl.c qemu-z80/vl.c
|
||||
#else
|
||||
|
||||
#warning No CPU save/restore functions
|
||||
@@ -6368,6 +6382,8 @@
|
||||
qemu_register_machine(&realview_machine);
|
||||
#elif defined(TARGET_SH4)
|
||||
qemu_register_machine(&shix_machine);
|
||||
@@ -6997,6 +7011,8 @@
|
||||
#elif defined(TARGET_M68K)
|
||||
qemu_register_machine(&mcf5208evb_machine);
|
||||
qemu_register_machine(&an5206_machine);
|
||||
+#elif defined(TARGET_Z80)
|
||||
+ qemu_register_machine(&z80pc_machine);
|
||||
#else
|
||||
#error unsupported CPU
|
||||
#endif
|
||||
diff -urN qemu-0.9.0/vl.h qemu-z80/vl.h
|
||||
--- qemu-0.9.0/vl.h 2007-02-05 23:01:54.000000000 +0000
|
||||
+++ qemu-z80/vl.h 2007-04-17 20:16:51.000000000 +0100
|
||||
@@ -901,6 +901,11 @@
|
||||
void isa_cirrus_vga_init(DisplayState *ds, uint8_t *vga_ram_base,
|
||||
unsigned long vga_ram_offset, int vga_ram_size);
|
||||
diff --exclude='*.orig' --exclude=CVS -ruN qemu/vl.h qemu-z80/vl.h
|
||||
--- qemu/vl.h 2007-06-30 19:32:17.000000000 +0200
|
||||
+++ qemu-z80/vl.h 2007-07-05 18:03:12.000000000 +0200
|
||||
@@ -959,6 +959,11 @@
|
||||
void pci_vmsvga_init(PCIBus *bus, DisplayState *ds, uint8_t *vga_ram_base,
|
||||
unsigned long vga_ram_offset, int vga_ram_size);
|
||||
|
||||
+/* zx_ula.c */
|
||||
+void zx_ula_init(DisplayState *ds, uint8_t *zx_screen_base,
|
||||
@ -4997,9 +5109,9 @@ diff -urN qemu-0.9.0/vl.h qemu-z80/vl.h
|
||||
+void zx_set_flash_dirty(void);
|
||||
+
|
||||
/* sdl.c */
|
||||
void sdl_display_init(DisplayState *ds, int full_screen);
|
||||
void sdl_display_init(DisplayState *ds, int full_screen, int no_frame);
|
||||
|
||||
@@ -1065,6 +1070,9 @@
|
||||
@@ -1150,6 +1155,9 @@
|
||||
extern QEMUMachine isapc_machine;
|
||||
extern int fd_bootchk;
|
||||
|
||||
@ -5009,9 +5121,9 @@ diff -urN qemu-0.9.0/vl.h qemu-z80/vl.h
|
||||
void ioport_set_a20(int enable);
|
||||
int ioport_get_a20(void);
|
||||
|
||||
diff -urN qemu-0.9.0/z80-dis.c qemu-z80/z80-dis.c
|
||||
--- qemu-0.9.0/z80-dis.c 1970-01-01 01:00:00.000000000 +0100
|
||||
+++ qemu-z80/z80-dis.c 2007-02-01 15:20:38.000000000 +0000
|
||||
diff --exclude='*.orig' --exclude=CVS -ruN qemu/z80-dis.c qemu-z80/z80-dis.c
|
||||
--- qemu/z80-dis.c 1970-01-01 01:00:00.000000000 +0100
|
||||
+++ qemu-z80/z80-dis.c 2007-07-05 18:03:12.000000000 +0200
|
||||
@@ -0,0 +1,621 @@
|
||||
+/* Print Z80 and R800 instructions
|
||||
+ Copyright 2005 Free Software Foundation, Inc.
|
||||
|
24
qemu.changes
24
qemu.changes
@ -1,3 +1,27 @@
|
||||
-------------------------------------------------------------------
|
||||
Tue Jul 10 15:44:03 CEST 2007 - schwab@suse.de
|
||||
|
||||
- Add (incomplete) m68k emulation.
|
||||
|
||||
-------------------------------------------------------------------
|
||||
Mon Jul 9 17:02:48 CEST 2007 - agraf@suse.de
|
||||
|
||||
- included alsa support in qemu-user
|
||||
- update to current cvs
|
||||
- TFTP booting from host directory (Anthony Liguori, Erwan Velu)
|
||||
- Tap device emulation for Solaris (Sittichai Palanisong)
|
||||
- Monitor multiplexing to several I/O channels (Jason Wessel)
|
||||
- ds1225y nvram support (Herve Poussineau)
|
||||
- CPU model selection support (J. Mayer, Paul Brook, Herve Poussineau)
|
||||
- Several Sparc fixes (Aurelien Jarno, Blue Swirl)
|
||||
- MIPS 64-bit FPU support (Thiemo Seufer)
|
||||
- Xscale PDA emulation (Andrzei Zaborowski)
|
||||
- ColdFire system emulation (Paul Brook)
|
||||
- Improved SH4 support (Magnus Damm)
|
||||
- MIPS64 support (Aurelien Jarno, Thiemo Seufer)
|
||||
- Preliminary Alpha guest support (J. Mayer)
|
||||
- IPC fixes
|
||||
|
||||
-------------------------------------------------------------------
|
||||
Wed Jun 20 14:38:47 CEST 2007 - agraf@suse.de
|
||||
|
||||
|
216
qemu.spec
216
qemu.spec
@ -1,5 +1,5 @@
|
||||
#
|
||||
# spec file for package qemu (Version 0.9.0)
|
||||
# spec file for package qemu (Version 0.9.0.cvs)
|
||||
#
|
||||
# Copyright (c) 2007 SUSE LINUX Products GmbH, Nuernberg, Germany.
|
||||
# This file and all modifications and additions to the pristine
|
||||
@ -13,11 +13,11 @@
|
||||
Name: qemu
|
||||
BuildRequires: SDL-devel bison e2fsprogs-devel
|
||||
URL: http://fabrice.bellard.free.fr/qemu/
|
||||
License: BSD License and BSD-like, GNU General Public License (GPL)
|
||||
Group: System/Emulators/Other
|
||||
License: BSD 3-Clause, GPL v2 or later
|
||||
Group: System/Emulators/PC
|
||||
Summary: Universal CPU emulator
|
||||
Version: 0.9.0
|
||||
Release: 38
|
||||
Version: 0.9.0.cvs
|
||||
Release: 1
|
||||
Source: %name-%version.tar.bz2
|
||||
#Patch400: qemu-0.7.0-gcc4-dot-syms.patch
|
||||
#Patch401: qemu-0.8.0-gcc4-hacks.patch
|
||||
@ -25,38 +25,39 @@ Source: %name-%version.tar.bz2
|
||||
Patch1: qemu-0.7.0-binfmt.patch
|
||||
Patch5: qemu-0.7.0-sigaltstackhack.patch
|
||||
Patch6: qemu-0.7.0-amd64.patch
|
||||
Patch8: qemu-0.9.0.patch
|
||||
Patch8: qemu-cvs-pthread.patch
|
||||
Patch10: linkerscripts.patch
|
||||
Patch11: qemu-0.7.2-kqemu.patch
|
||||
Patch14: qemu-0.7.1-jobsignals.patch
|
||||
Patch15: qemu-0.9.0-syscalls.patch
|
||||
Patch16: qemu-0.7.1-armfpaex.patch
|
||||
Patch19: qemu-0.9.0-nousbdevfs.patch
|
||||
Patch20: qemu-0.9.0-usbheaders.patch
|
||||
Patch21: qemu-0.9.0-initrd.patch
|
||||
Patch22: qemu-0.9.0-nptl.patch
|
||||
Patch23: qemu-0.9.0-fadvise64.patch
|
||||
Patch25: qemu-0.9.0-nptl2.patch
|
||||
Patch26: qemu-0.9.0-socket.patch
|
||||
Patch27: qemu-0.9.0-strace.patch
|
||||
Patch28: qemu-0.9.0-mmap.patch
|
||||
Patch29: qemu-0.9.0-alt-path.patch
|
||||
Patch30: qemu-0.9.0-nonetlink.patch
|
||||
Patch31: qemu-0.9.0-kernel-option-vga.patch
|
||||
Patch32: qemu-0.9.0-x86_64-opts.patch
|
||||
Patch33: qemu-0.9.0-fix-cpus-chaining.patch
|
||||
Patch34: qemu-0.9.0-migration.patch
|
||||
Patch36: qemu-0.9.0-fix-x86-fprem.patch
|
||||
Patch37: qemu-0.9.0-kvm.patch
|
||||
Patch38: qemu-0.9.0-kvm-bios.patch
|
||||
Patch39: qemu-0.9.0-kvm-kqemu-window-caption.patch
|
||||
Patch40: qemu-z80.diff
|
||||
Patch41: qemu-0.9.0-sched.patch
|
||||
Patch42: qemu-0.8.2-alt-mmap.patch
|
||||
Patch43: qemu-0.9.0-futex.patch
|
||||
Patch44: qemu-0.9.0-robust_list.patch
|
||||
Patch45: qemu-0.9.0-wine.patch
|
||||
Patch46: bug-252519_goo-qemu-sec-0.9.0.diff
|
||||
Patch48: qemu-z80.diff
|
||||
Patch49: qemu-cvs-img.patch
|
||||
Patch50: qemu-cvs-newpath.patch
|
||||
Patch51: qemu-cvs-tls.patch
|
||||
Patch52: qemu-cvs-futex.patch
|
||||
Patch53: qemu-cvs-sched_getaffinity.patch
|
||||
Patch54: qemu-cvs-mplayer.patch
|
||||
Patch55: qemu-cvs-netlink.patch
|
||||
Patch56: qemu-cvs-ipc.patch
|
||||
Patch57: qemu-cvs-ipc_semop.patch
|
||||
Patch58: qemu-cvs-ioctl_debug.patch
|
||||
Patch59: qemu-cvs-alsa_bitfield.patch
|
||||
Patch60: qemu-cvs-alsa_ioctl.patch
|
||||
Patch61: qemu-cvs-ioctl_nodirection.patch
|
||||
Patch62: qemu-cvs-alsa_mmap.patch
|
||||
Patch63: qemu-cvs-gettimeofday.patch
|
||||
Patch64: qemu-cvs-nofadvise64.patch
|
||||
Patch65: qemu-cvs-flash.patch
|
||||
Patch66: qemu-cvs-mmap-amd64.patch
|
||||
Patch67: qemu-cvs-noppcemb.patch
|
||||
Patch68: qemu-0.8.3-gcc4.patch
|
||||
Patch69: qemu-cvs-ia64.patch
|
||||
Patch70: qemu-m68k.diff
|
||||
Source200: kvm_bios.bin
|
||||
Source201: zx-rom.bin
|
||||
Source202: COPYING.zx-rom
|
||||
@ -98,6 +99,8 @@ Patch663: gcc-ppc-nostartfileprefix.patch
|
||||
Patch664: gcc-ppc-nof.patch
|
||||
Patch700: gcc-abuildappease.patch
|
||||
Patch701: gcc-3.3.5.dif
|
||||
# this is to make lint happy
|
||||
Source300: rpmlintrc
|
||||
BuildRoot: %{_tmppath}/%{name}-%{version}-build
|
||||
ExclusiveArch: %ix86 ppc sparc x86_64 ia64
|
||||
|
||||
@ -119,41 +122,45 @@ Authors:
|
||||
#%patch400 -p1
|
||||
#%patch401 -p1
|
||||
#%patch402 -p1
|
||||
%patch1
|
||||
%patch1 -p1
|
||||
%patch5
|
||||
%patch6
|
||||
%patch8
|
||||
%patch8 -p1
|
||||
%patch10
|
||||
%patch11
|
||||
%patch14
|
||||
%patch15
|
||||
%patch16
|
||||
%patch19
|
||||
%patch20
|
||||
%patch21 -p1
|
||||
%patch22 -p1
|
||||
%patch23 -p1
|
||||
%patch25 -p1
|
||||
%patch26 -p1
|
||||
%patch27 -p1
|
||||
%patch28 -p1
|
||||
%patch29 -p1
|
||||
%patch30 -p1
|
||||
%patch31 -p1
|
||||
%patch32 -p1
|
||||
%patch33 -p1
|
||||
%patch34 -p1
|
||||
%patch36 -p1
|
||||
%patch37 -p1
|
||||
%patch38 -p1
|
||||
%patch39 -p1
|
||||
%patch40 -p1
|
||||
%patch41 -p1
|
||||
%patch42 -p1
|
||||
%patch43 -p1
|
||||
%patch44 -p1
|
||||
%patch45 -p1
|
||||
%patch46 -p1
|
||||
#%patch34 -p1
|
||||
#%patch37 -p1
|
||||
#%patch38 -p1
|
||||
#%patch39 -p1
|
||||
%patch48 -p1
|
||||
%patch49
|
||||
%patch50 -p1
|
||||
%patch51 -p1
|
||||
%patch52 -p1
|
||||
%patch53 -p1
|
||||
%patch54 -p1
|
||||
%patch55 -p1
|
||||
%patch56 -p1
|
||||
%patch57 -p1
|
||||
%patch58 -p1
|
||||
%patch59 -p1
|
||||
%patch60 -p1
|
||||
%patch61 -p1
|
||||
%patch62 -p1
|
||||
%patch63 -p1
|
||||
%patch64 -p1
|
||||
%patch65 -p1
|
||||
%patch66 -p1
|
||||
%patch67 -p1
|
||||
%patch69
|
||||
%patch70
|
||||
%ifarch ia64 ppc64
|
||||
#this is the dyngen for gcc4 patch (does not work on x86)
|
||||
%patch68 -p1
|
||||
%endif
|
||||
cp -p %SOURCE200 pc-bios/
|
||||
cp -p %SOURCE202 .
|
||||
cd gcc-3.3.5
|
||||
@ -192,9 +199,12 @@ cd gcc-3.3.5
|
||||
cd ..
|
||||
|
||||
%build
|
||||
QEMU_OPT_FLAGS="$RPM_OPT_FLAGS"
|
||||
%ifarch ia64 ppc64
|
||||
%define qemucc gcc
|
||||
%else
|
||||
%define gcc33tmp /tmp/gcc33
|
||||
%define qemucc %{gcc33tmp}/bin/gcc
|
||||
QEMU_OPT_FLAGS="$RPM_OPT_FLAGS"
|
||||
# fix opt flags for gcc3
|
||||
%ifarch %ix86
|
||||
QEMU_OPT_FLAGS="${RPM_OPT_FLAGS/-mtune=/-mcpu=}"
|
||||
@ -214,79 +224,41 @@ cd gcc-3.3.5
|
||||
make bootstrap-lean BOOT_CFLAGS="$QEMU_OPT_FLAGS" STAGE1_CFLAGS="$QEMU_OPT_FLAGS" CFLAGS="$QEMU_OPT_FLAGS" %{?jobs:-j%{jobs}}
|
||||
make install
|
||||
cd ..
|
||||
QEMU_OPT_FLAGS="$QEMU_OPT_FLAGS -fno-strict-aliasing"
|
||||
%endif
|
||||
# build QEMU
|
||||
mkdir -p dynamic
|
||||
# build qemu-system without kqemu support
|
||||
./configure --prefix=/usr \
|
||||
--interp-prefix=/usr/share/qemu/qemu-i386 \
|
||||
--cc=%qemucc --enable-adlib --disable-gcc-check \
|
||||
--extra-cflags="$QEMU_OPT_FLAGS" --enable-system --disable-linux-user
|
||||
make %{?jobs:-j%{jobs}}
|
||||
mv */qemu */qemu-* dynamic || true
|
||||
make clean
|
||||
# build qemu-system with kqemu support
|
||||
# kqemu target
|
||||
%ifarch %ix86 x86_64
|
||||
%ifarch x86_64
|
||||
target_list_kqemu="x86_64-softmmu"
|
||||
%else
|
||||
target_list_kqemu="i386-softmmu"
|
||||
%endif
|
||||
# targets for all platforms
|
||||
target_list="ppc-softmmu sparc-softmmu mips-softmmu mipsel-softmmu arm-softmmu z80-softmmu"
|
||||
# AMD64 -> i386 without kqemu
|
||||
# x86 -> AMD64 without kqemu
|
||||
# others -> both without kqemu
|
||||
%ifarch x86_64
|
||||
target_list="$target_list i386-softmmu"
|
||||
%else
|
||||
%ifarch %ix86
|
||||
target_list="$target_list x86_64-softmmu"
|
||||
%else
|
||||
target_list="$target_list i386-softmmu x86_64-softmmu"
|
||||
%endif
|
||||
%endif
|
||||
# linux-user targets
|
||||
target_list_user=""
|
||||
%ifnarch %ix86 x86_64
|
||||
target_list_user="$target_list_user i386-linux-user"
|
||||
%endif
|
||||
%ifnarch armv4l
|
||||
target_list_user="$target_list_user arm-linux-user"
|
||||
%endif
|
||||
%ifnarch armv4b
|
||||
target_list_user="$target_list_user armeb-linux-user"
|
||||
%endif
|
||||
%ifnarch sparc sparc64
|
||||
target_list_user="$target_list_user sparc-linux-user"
|
||||
%endif
|
||||
%ifnarch ppc ppc64
|
||||
target_list_user="$target_list_user ppc-linux-user"
|
||||
%endif
|
||||
%ifnarch mips
|
||||
target_list_user="$target_list_user mips-linux-user"
|
||||
%endif
|
||||
%ifnarch mipsel
|
||||
target_list_user="$target_list_user mipsel-linux-user"
|
||||
%endif
|
||||
%ifnarch m68k
|
||||
target_list_user="$target_list_user m68k-linux-user"
|
||||
%endif
|
||||
QEMU_OPT_FLAGS="$QEMU_OPT_FLAGS -fno-strict-aliasing"
|
||||
mkdir -p dynamic
|
||||
%ifarch %ix86 x86_64
|
||||
# build i386/x86_64 system with kqemu support
|
||||
./configure --prefix=/usr \
|
||||
--interp-prefix=/usr/share/qemu/qemu-i386 \
|
||||
--target-list="$target_list_kqemu" --cc=%qemucc \
|
||||
--enable-adlib --extra-cflags="$QEMU_OPT_FLAGS"
|
||||
--enable-adlib --extra-cflags="$QEMU_OPT_FLAGS"
|
||||
echo '#define USE_KQEMU 1' >>config-host.h
|
||||
make %{?jobs:-j%{jobs}}
|
||||
mv */qemu */qemu-* dynamic || true
|
||||
make clean
|
||||
%endif
|
||||
# build system emus without kqemu support
|
||||
./configure --prefix=/usr \
|
||||
--interp-prefix=/usr/share/qemu/qemu-i386 \
|
||||
--target-list="$target_list" --cc=%qemucc \
|
||||
--enable-adlib --extra-cflags="$QEMU_OPT_FLAGS"
|
||||
make %{?jobs:-j%{jobs}}
|
||||
mv */qemu *-*/qemu-* dynamic || true
|
||||
make clean
|
||||
# build userland emus
|
||||
./configure --prefix=/usr \
|
||||
--interp-prefix=/usr/share/qemu/qemu-i386 \
|
||||
--target-list="$target_list_user" --cc=%qemucc \
|
||||
--static --extra-cflags="$QEMU_OPT_FLAGS"
|
||||
--enable-linux-user --disable-system --cc=%qemucc \
|
||||
--static --disable-gcc-check \
|
||||
--extra-cflags="$QEMU_OPT_FLAGS"
|
||||
make %{?jobs:-j%{jobs}}
|
||||
|
||||
%install
|
||||
@ -299,7 +271,7 @@ install -m 755 */qemu-*[^.]? $RPM_BUILD_ROOT/usr/bin
|
||||
install -d -m 755 $RPM_BUILD_ROOT/%{_mandir}/man1
|
||||
install -m 644 qemu.1 $RPM_BUILD_ROOT/%{_mandir}/man1
|
||||
install -d -m 755 $RPM_BUILD_ROOT/usr/share/qemu
|
||||
install -m 644 pc-bios/*.bin pc-bios/video.x pc-bios/openbios-sparc32 $RPM_BUILD_ROOT/usr/share/qemu
|
||||
install -m 644 pc-bios/*.bin pc-bios/video.x pc-bios/openbios-sparc* $RPM_BUILD_ROOT/usr/share/qemu
|
||||
install -d -m 755 $RPM_BUILD_ROOT/usr/sbin
|
||||
install -m 755 qemu-binfmt-conf.sh $RPM_BUILD_ROOT/usr/sbin
|
||||
install -m 755 qemu-img $RPM_BUILD_ROOT/usr/bin
|
||||
@ -332,6 +304,24 @@ rm -rf %{gcc33tmp}
|
||||
%endif
|
||||
|
||||
%changelog
|
||||
* Tue Jul 10 2007 - schwab@suse.de
|
||||
- Add (incomplete) m68k emulation.
|
||||
* Mon Jul 09 2007 - agraf@suse.de
|
||||
- included alsa support in qemu-user
|
||||
- update to current cvs
|
||||
- TFTP booting from host directory (Anthony Liguori, Erwan Velu)
|
||||
- Tap device emulation for Solaris (Sittichai Palanisong)
|
||||
- Monitor multiplexing to several I/O channels (Jason Wessel)
|
||||
- ds1225y nvram support (Herve Poussineau)
|
||||
- CPU model selection support (J. Mayer, Paul Brook, Herve Poussineau)
|
||||
- Several Sparc fixes (Aurelien Jarno, Blue Swirl)
|
||||
- MIPS 64-bit FPU support (Thiemo Seufer)
|
||||
- Xscale PDA emulation (Andrzei Zaborowski)
|
||||
- ColdFire system emulation (Paul Brook)
|
||||
- Improved SH4 support (Magnus Damm)
|
||||
- MIPS64 support (Aurelien Jarno, Thiemo Seufer)
|
||||
- Preliminary Alpha guest support (J. Mayer)
|
||||
- IPC fixes
|
||||
* Wed Jun 20 2007 - agraf@suse.de
|
||||
- applied proper fix for x86_64 and the MAP_32BIT flag
|
||||
* Wed Jun 20 2007 - uli@suse.de
|
||||
|
Loading…
Reference in New Issue
Block a user