This patch adds support for compiling/running on Solaris SPARC (9 and 10) This patch allows qemu to compile on Solaris X86 and SPARC, under Solaris 9, 10 and Solaris express..
This should apply against the current CVS tree. Comments? Ben
diff -ruN qemu/Makefile qemu-solaris/Makefile --- qemu/Makefile 2006-04-23 13:57:59.000000000 -0400 +++ qemu-solaris/Makefile 2006-04-27 20:49:08.299867000 -0400 @@ -4,6 +4,9 @@ ifdef CONFIG_DARWIN CFLAGS+= -mdynamic-no-pic endif +ifeq ($(ARCH),sparc) +CFLAGS+=-mcpu=ultrasparc +endif LDFLAGS=-g LIBS= DEFINES+=-D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE diff -ruN qemu/Makefile.target qemu-solaris/Makefile.target --- qemu/Makefile.target 2006-04-27 19:15:07.000000000 -0400 +++ qemu-solaris/Makefile.target 2006-04-27 20:51:14.468478000 -0400 @@ -107,6 +107,11 @@ endif ifeq ($(ARCH),sparc) +ifeq ($(CONFIG_SOLARIS),yes) +CFLAGS+=-mcpu=ultrasparc -m32 -ffixed-g2 -ffixed-g3 +LDFLAGS+=-m32 +OP_CFLAGS=$(CFLAGS) -fno-delayed-branch -fno-omit-frame-pointer -ffixed-i0 +else CFLAGS+=-m32 -ffixed-g1 -ffixed-g2 -ffixed-g3 -ffixed-g6 LDFLAGS+=-m32 OP_CFLAGS=$(CFLAGS) -fno-delayed-branch -ffixed-i0 @@ -114,6 +119,7 @@ # -static is used to avoid g1/g3 usage by the dynamic linker LDFLAGS+=-Wl,-T,$(SRC_PATH)/sparc.ld -static endif +endif ifeq ($(ARCH),sparc64) CFLAGS+=-m64 -ffixed-g1 -ffixed-g2 -ffixed-g3 -ffixed-g6 diff -ruN qemu/cpu-exec.c qemu-solaris/cpu-exec.c --- qemu/cpu-exec.c 2006-04-27 17:05:14.000000000 -0400 +++ qemu-solaris/cpu-exec.c 2006-04-28 02:22:03.576500000 -0400 @@ -253,7 +253,7 @@ uint32_t *saved_regwptr; #endif #endif -#ifdef __sparc__ +#if defined(__sparc__) && !defined(SOLARISREV) int saved_i7, tmp_T0; #endif int ret, interrupt_request; @@ -323,7 +323,7 @@ #if defined(reg_T2) saved_T2 = T2; #endif -#ifdef __sparc__ +#if defined(__sparc__) && !defined(SOLARISREV) /* we also save i7 because longjmp may not restore it */ asm volatile ("mov %%i7, %0" : "=r" (saved_i7)); #endif @@ -447,7 +447,7 @@ T0 = 0; /* force lookup of first TB */ for(;;) { -#ifdef __sparc__ +#if defined(__sparc__) && !defined(SOLARISREV) /* g1 can be modified by some libc? functions */ tmp_T0 = T0; #endif @@ -467,7 +467,7 @@ do_interrupt(intno, 0, 0, 0, 1); /* ensure that no TB jump will be modified as the program flow was changed */ -#ifdef __sparc__ +#if defined(__sparc__) && !defined(SOLARISREV) tmp_T0 = 0; #else T0 = 0; @@ -486,7 +486,7 @@ env->error_code = 0; do_interrupt(env); env->interrupt_request &= ~CPU_INTERRUPT_HARD; -#ifdef __sparc__ +#if defined(__sparc__) && !defined(SOLARISREV) tmp_T0 = 0; #else T0 = 0; @@ -497,7 +497,7 @@ env->error_code = 0; do_interrupt(env); env->interrupt_request &= ~CPU_INTERRUPT_TIMER; -#ifdef __sparc__ +#if defined(__sparc__) && !defined(SOLARISREV) tmp_T0 = 0; #else T0 = 0; @@ -516,7 +516,7 @@ env->error_code = 0; do_interrupt(env); env->interrupt_request &= ~CPU_INTERRUPT_HARD; -#ifdef __sparc__ +#if defined(__sparc__) && !defined(SOLARISREV) tmp_T0 = 0; #else T0 = 0; @@ -534,7 +534,7 @@ env->interrupt_request &= ~CPU_INTERRUPT_HARD; do_interrupt(env->interrupt_index); env->interrupt_index = 0; -#ifdef __sparc__ +#if defined(__sparc__) && !defined(SOLARISREV) tmp_T0 = 0; #else T0 = 0; @@ -565,7 +565,7 @@ env->interrupt_request &= ~CPU_INTERRUPT_EXITTB; /* ensure that no TB jump will be modified as the program flow was changed */ -#ifdef __sparc__ +#if defined(__sparc__) && !defined(SOLARISREV) tmp_T0 = 0; #else T0 = 0; @@ -633,7 +633,7 @@ lookup_symbol(tb->pc)); } #endif -#ifdef __sparc__ +#if defined(__sparc__) && !defined(SOLARISREV) T0 = tmp_T0; #endif /* see if we can patch the calling TB. When the TB @@ -669,7 +669,9 @@ "mov %%o7,%%i0" : /* no outputs */ : "r" (gen_func) - : "i0", "i1", "i2", "i3", "i4", "i5"); + : "i0", "i1", "i2", "i3", "i4", "i5", + "l0", "l1", "l2", "l3", "l4", "l5", + "l6", "l7"); #elif defined(__arm__) asm volatile ("mov pc, %0\n\t" ".global exec_loop\n\t" @@ -834,7 +836,7 @@ #else #error unsupported target CPU #endif -#ifdef __sparc__ +#if defined(__sparc__) && !defined(SOLARISREV) asm volatile ("mov %0, %%i7" : : "r" (saved_i7)); #endif T0 = saved_T0; diff -ruN qemu/dyngen-exec.h qemu-solaris/dyngen-exec.h --- qemu/dyngen-exec.h 2006-04-25 18:36:06.000000000 -0400 +++ qemu-solaris/dyngen-exec.h 2006-04-27 21:04:58.187059000 -0400 @@ -121,6 +121,13 @@ #define AREG3 "s2" #endif #ifdef __sparc__ +#ifdef SOLARISREV +#define AREG0 "g2" +#define AREG1 "g3" +#define AREG2 "g4" +#define AREG3 "g5" +#define AREG4 "g6" +#else #define AREG0 "g6" #define AREG1 "g1" #define AREG2 "g2" @@ -133,6 +140,7 @@ #define AREG9 "l5" #define AREG10 "l6" #define AREG11 "l7" +#endif #define USE_FP_CONVERT #endif #ifdef __s390__ @@ -241,10 +249,8 @@ ASM_NAME(__op_gen_label) #n) #endif #ifdef __sparc__ -#define EXIT_TB() asm volatile ("jmpl %i0 + 8, %g0\n" \ - "nop") -#define GOTO_LABEL_PARAM(n) asm volatile ( \ - "set " ASM_NAME(__op_gen_label) #n ", %g1; jmp %g1; nop") +#define EXIT_TB() asm volatile ("jmpl %i0 + 8, %g0; nop") +#define GOTO_LABEL_PARAM(n) asm volatile ("ba " ASM_NAME(__op_gen_label) #n ";nop") #endif #ifdef __arm__ #define EXIT_TB() asm volatile ("b exec_loop") diff -ruN qemu/dyngen.c qemu-solaris/dyngen.c --- qemu/dyngen.c 2006-04-24 16:32:17.000000000 -0400 +++ qemu-solaris/dyngen.c 2006-04-28 04:17:44.774951000 -0400 @@ -1196,7 +1196,7 @@ } else { #ifdef HOST_SPARC if (sym_name[0] == '.') - snprintf(name, sizeof(name), + snprintf(name, name_size, "(long)(&__dot_%s)", sym_name + 1); else @@ -1440,6 +1440,12 @@ } #elif defined(HOST_SPARC) { +#define INSN_SAVE 0x9de3a000 +#define INSN_RET 0x81c7e008 +#define INSN_RESTORE 0x81e80000 +#define INSN_RETURN 0x81cfe008 +#define INSN_NOP 0x01000000 + uint32_t start_insn, end_insn1, end_insn2; uint8_t *p; p = (void *)(p_end - 8); @@ -1448,12 +1454,17 @@ start_insn = get32((uint32_t *)(p_start + 0x0)); end_insn1 = get32((uint32_t *)(p + 0x0)); end_insn2 = get32((uint32_t *)(p + 0x4)); - if ((start_insn & ~0x1fff) == 0x9de3a000) { + if ((start_insn & ~0x1fff) == INSN_SAVE) { p_start += 0x4; start_offset += 0x4; if ((int)(start_insn | ~0x1fff) < -128) error("Found bogus save at the start of %s", name); - if (end_insn1 != 0x81c7e008 || end_insn2 != 0x81e80000) + if (end_insn1 == INSN_RET && end_insn2 == INSN_RESTORE) + /* SPARC v7: ret; restore; */ ; + else if (end_insn1 == INSN_RETURN && end_insn2 == INSN_NOP) + /* SPARC v9: return; nop; */ ; + else + error("ret; restore; not found at end of %s", name); } else { error("No save at the beginning of %s", name); @@ -1462,7 +1473,7 @@ /* Skip a preceeding nop, if present. */ if (p > p_start) { skip_insn = get32((uint32_t *)(p - 0x4)); - if (skip_insn == 0x01000000) + if (skip_insn == INSN_NOP) p -= 4; } #endif @@ -2151,6 +2162,18 @@ reloc_offset, reloc_offset, name, addend, reloc_offset); break; + case R_SPARC_WDISP22: + fprintf(outfile, + " *(uint32_t *)(gen_code_ptr + %d) = " + "((*(uint32_t *)(gen_code_ptr + %d)) " + " & ~0x3fffff) " + " | ((((%s + %d) - (long)(gen_code_ptr + %d))>>2) " + " & 0x3fffff);\n", + rel->r_offset - start_offset, + rel->r_offset - start_offset, + name, addend, + rel->r_offset - start_offset); + break; default: error("unsupported sparc relocation (%d)", type); } diff -ruN qemu/dyngen.h qemu-solaris/dyngen.h --- qemu/dyngen.h 2006-04-24 16:32:17.000000000 -0400 +++ qemu-solaris/dyngen.h 2006-04-27 21:11:26.701363000 -0400 @@ -19,7 +19,13 @@ */ int __op_param1, __op_param2, __op_param3; -int __op_gen_label1, __op_gen_label2, __op_gen_label3; +#ifdef __sparc__ + void __op_gen_label1(){} + void __op_gen_label2(){} + void __op_gen_label3(){} +#else + int __op_gen_label1, __op_gen_label2, __op_gen_label3; +#endif int __op_jmp0, __op_jmp1, __op_jmp2, __op_jmp3; #ifdef __i386__ diff -ruN qemu/hw/apic.c qemu-solaris/hw/apic.c --- qemu/hw/apic.c 2005-12-16 20:27:28.000000000 -0500 +++ qemu-solaris/hw/apic.c 2006-04-28 00:59:32.507902000 -0400 @@ -108,7 +108,7 @@ unsigned int ret = 0; #if defined(HOST_I386) - __asm__ __volatile__ ("bsr %1, %0\n" : "+r" (ret) : "rm" (value)); + __asm__ __volatile__ ("bsrl %1, %0\n" : "+r" (ret) : "rm" (value)); return ret; #else if (value > 0xffff) @@ -129,7 +129,7 @@ unsigned int ret = 0; #if defined(HOST_I386) - __asm__ __volatile__ ("bsf %1, %0\n" : "+r" (ret) : "rm" (value)); + __asm__ __volatile__ ("bsfl %1, %0\n" : "+r" (ret) : "rm" (value)); return ret; #else if (!value) diff -ruN qemu/hw/es1370.c qemu-solaris/hw/es1370.c --- qemu/hw/es1370.c 2005-11-20 11:20:39.000000000 -0500 +++ qemu-solaris/hw/es1370.c 2006-04-28 01:02:25.180345000 -0400 @@ -479,9 +479,10 @@ IO_WRITE_PROTO (es1370_writeb) { ES1370State *s = opaque; - addr = es1370_fixup (s, addr); uint32_t shift, mask; + addr = es1370_fixup (s, addr); + switch (addr) { case ES1370_REG_CONTROL: case ES1370_REG_CONTROL + 1: @@ -516,9 +517,11 @@ IO_WRITE_PROTO (es1370_writew) { ES1370State *s = opaque; - addr = es1370_fixup (s, addr); uint32_t shift, mask; - struct chan *d = &s->chan[0]; + struct chan *d; + + addr = es1370_fixup (s, addr); + d = &s->chan[0]; switch (addr) { case ES1370_REG_CODEC: diff -ruN qemu/hw/ide.c qemu-solaris/hw/ide.c --- qemu/hw/ide.c 2006-04-25 17:24:22.000000000 -0400 +++ qemu-solaris/hw/ide.c 2006-04-28 01:30:59.548829000 -0400 @@ -391,6 +391,10 @@ } PCIIDEState; static void ide_dma_start(IDEState *s, IDEDMAFunc *dma_cb); +static int ide_atapi_cmd_read_dma_cb(IDEState *s, + target_phys_addr_t phys_addr, + int transfer_size1); + static void padstr(char *str, const char *src, int len) { @@ -513,10 +517,17 @@ padstr((uint8_t *)(p + 23), QEMU_VERSION, 8); /* firmware version */ padstr((uint8_t *)(p + 27), "QEMU CD-ROM", 40); /* model */ put_le16(p + 48, 1); /* dword I/O (XXX: should not be set on CDROM) */ +#ifdef __sun__ + put_le16(p + 49, 1 << 8 | 1 << 9); /* DMA and LBA supported */ + put_le16(p + 53, 7); /* words 64-70, 54-58, 88 valid */ + put_le16(p + 63, 0x07 | 0x4 << 8); /* Multiword DMA supported/selected */ + put_le16(p + 64, 0x03); /* PIO modes 3,4 supported */ +#else put_le16(p + 49, 1 << 9); /* LBA supported, no DMA */ put_le16(p + 53, 3); /* words 64-70, 54-58 valid */ put_le16(p + 63, 0x103); /* DMA modes XXX: may be incorrect */ put_le16(p + 64, 1); /* PIO modes */ +#endif put_le16(p + 65, 0xb4); /* minimum DMA multiword tx cycle time */ put_le16(p + 66, 0xb4); /* recommended DMA multiword tx cycle time */ put_le16(p + 67, 0x12c); /* minimum PIO cycle time without flow control */ @@ -994,8 +1005,14 @@ s->elementary_transfer_size = 0; s->io_buffer_index = 0; - s->status = READY_STAT; - ide_atapi_cmd_reply_end(s); + if (s->atapi_dma) { + s->status = READY_STAT | DRQ_STAT; + ide_dma_start(s, ide_atapi_cmd_read_dma_cb); + } else { + s->status = READY_STAT; + ide_atapi_cmd_reply_end(s); + } + } /* start a CD-CDROM read command */ @@ -1026,14 +1043,19 @@ #endif if (s->packet_transfer_size <= 0) break; - len = s->cd_sector_size - s->io_buffer_index; - if (len <= 0) { - /* transfert next data */ - cd_read_sector(s->bs, s->lba, s->io_buffer, s->cd_sector_size); - s->lba++; - s->io_buffer_index = 0; - len = s->cd_sector_size; + if (s->lba == -1) + len = s->packet_transfer_size; + else { + len = s->cd_sector_size - s->io_buffer_index; + if (len <= 0) { + /* transfert next data */ + cd_read_sector(s->bs, s->lba, s->io_buffer, s->cd_sector_size); + s->lba++; + s->io_buffer_index = 0; + len = s->cd_sector_size; + } } + if (len > transfer_size) len = transfer_size; cpu_physical_memory_write(phys_addr, @@ -2488,6 +2510,11 @@ cmd646_set_irq, d, 1); } +// PCI 0x04: command(word), 0x06(word): status +#define PCI_COMMAND_IOACCESS 0x0001 +#define PCI_COMMAND_MEMACCESS 0x0002 +#define PCI_COMMAND_BUSMASTER 0x0004 + /* hd_table must contain 4 block drivers */ /* NOTE: for the PIIX3, the IRQs and IOports are hardcoded */ void pci_piix3_ide_init(PCIBus *bus, BlockDriverState **hd_table) @@ -2507,7 +2534,9 @@ pci_conf[0x01] = 0x80; pci_conf[0x02] = 0x10; pci_conf[0x03] = 0x70; - pci_conf[0x09] = 0x80; // legacy ATA mode + pci_conf[0x04] = PCI_COMMAND_IOACCESS | PCI_COMMAND_MEMACCESS \ + | PCI_COMMAND_BUSMASTER; + pci_conf[0x09] = 0x8a; // programming interface = PCI_IDE bus master is supported pci_conf[0x0a] = 0x01; // class_sub = PCI_IDE pci_conf[0x0b] = 0x01; // class_base = PCI_mass_storage pci_conf[0x0e] = 0x00; // header_type diff -ruN qemu/slirp/mbuf.c qemu-solaris/slirp/mbuf.c --- qemu/slirp/mbuf.c 2004-04-21 20:10:47.000000000 -0400 +++ qemu-solaris/slirp/mbuf.c 2006-04-28 01:27:54.732625000 -0400 @@ -146,16 +146,18 @@ struct mbuf *m; int size; { + int datasize; + /* some compiles throw up on gotos. This one we can fake. */ if(m->m_size>size) return; if (m->m_flags & M_EXT) { - /* datasize = m->m_data - m->m_ext; */ + datasize = m->m_data - m->m_ext; m->m_ext = (char *)realloc(m->m_ext,size); /* if (m->m_ext == NULL) * return (struct mbuf *)NULL; */ - /* m->m_data = m->m_ext + datasize; */ + m->m_data = m->m_ext + datasize; } else { int datasize; char *dat; diff -ruN qemu/slirp/slirp.c qemu-solaris/slirp/slirp.c --- qemu/slirp/slirp.c 2006-04-23 15:41:17.000000000 -0400 +++ qemu-solaris/slirp/slirp.c 2006-04-28 04:12:46.302799000 -0400 @@ -137,6 +137,16 @@ } #endif +#if defined(SOLARISREV) && defined(__sparc__) + /* + * Tell the kernel to fix unaligned accesses for us. + * + * The slirp code accesses at least |struct ip| structures + * from unaligned addresses. + */ + asm("ta 6"); +#endif + link_up = 1; if_init(); diff -ruN qemu/target-mips/cpu.h qemu-solaris/target-mips/cpu.h --- qemu/target-mips/cpu.h 2006-03-11 11:23:39.000000000 -0500 +++ qemu-solaris/target-mips/cpu.h 2006-04-28 04:00:24.365813000 -0400 @@ -8,6 +8,12 @@ #include "config.h" #include "softfloat.h" +// uint_fast8_t and uint_fast16_t not in <sys/int_types.h> +#if defined(SOLARISREV) && SOLARISREV < 10 +typedef unsigned char uint_fast8_t; +typedef unsigned int uint_fast16_t; +#endif + typedef union fpr_t fpr_t; union fpr_t { double d; diff -ruN qemu/vl.c qemu-solaris/vl.c --- qemu/vl.c 2006-04-27 19:15:07.000000000 -0400 +++ qemu-solaris/vl.c 2006-04-27 21:14:03.238223000 -0400 @@ -535,6 +535,28 @@ return val; } +#elif defined(SOLARISREV) + +uint64_t cpu_get_real_ticks (void) +{ +#if defined(_LP64) + uint64_t rval; + asm volatile("rd %%tick,%0" : "=r"(rval)); + return rval; +#else + union { + uint64_t i64; + struct { + uint32_t high; + uint32_t low; + } i32; + } rval; + asm volatile("rd %%tick,%1; srlx %1,32,%0" + : "=r"(rval.i32.high), "=r"(rval.i32.low)); + return rval.i64; +#endif +} + #elif defined(__ia64) int64_t cpu_get_real_ticks(void)
_______________________________________________ Qemu-devel mailing list Qemu-devel@nongnu.org http://lists.nongnu.org/mailman/listinfo/qemu-devel