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

Reply via email to