All of lore.kernel.org
 help / color / mirror / Atom feed
From: Filip Navara <navaraf@reactos.com>
To: qemu-devel@nongnu.org
Subject: [Qemu-devel] [patch] Various (mostly) x86-64 related patches
Date: Thu, 21 Jul 2005 08:40:52 +0200	[thread overview]
Message-ID: <42DF4374.10703@reactos.com> (raw)

[-- Attachment #1: Type: text/plain, Size: 2012 bytes --]

qemu-20050718-01-vaddr.patch
        Fix TB virtual page map for x86-64 (at least 48bits of VA must 
be honoured).

qemu-20050718-02-insns.patch
        - Add support for AMD cache info MCR.
        - Fix INVLPG instruction in 64bit mode.
        - Implement the ENTER instruction for 64bit mode.
        - Add dummy support for MCA, PAT, MTRR and CLFLUSH.
        - Correct size of 16bit stack pushes in 64bit mode.
        - Correct segment arithmetics for various instructions in 64bit 
mode.
        - Correctly honour the ADDR prefix for these instrutions:
          maskmov; mov EAX, Ov; mov Ov, EAX
        - Fix the implicit 64bit semantics for these instrutions:
          ret im; lcall; lret
        - Support the PREFETCHW instruction.

qemu-20050718-03-apic.patch
        * vl.h (ioapic_init, ioapic_set_irq): Declare.
        * hw/apic.c (apic_get_current_count, apic_timer_update):
        Fix division by zero if s->initial_count == ~0.
        (apic_get_delivery_bitmask, apic_bus_deliver,
        apic_deliver, apic_mem_readl, apic_mem_writel):
        Implent basic interrupt control and delivery (no arbitration).
        (ioapic_service, ioapic_set_irq, ioapic_mem_readl,
        ioapic_mem_writel, ioapic_mem_read, ioapic_mem_write,
        ioapic_init): Implement I/O APIC.
        (apic_init): Automatically assign ID to the APIC and
        link it to local APIC list.
        (apic_reset, ioapic_reset): Add reset handlers.
        (apic_save, apic_load, ioapic_save, ioapic_load):
        Add save and load handlers.
        * hw/i8259.c (pic_set_irq): Forward interrupts to I/O APIC.
        * hw/pc.c (pc_init1): Initialize the I/O APIC.
        (cpu_get_pic_interrupt): Compile the APIC stuff even in
        non-x86-64 case.
   
qemu-20050718-04-doc.patch
       Minor qemu-img documentation update.

qemu-20050718-05-sdl.patch
       Don't make the SDL window resizable. It doesn't make sense to 
mark it that way since we really don't handle it (either by scrolling or 
scaling).

[-- Attachment #2: qemu-20050718-05-sdl.patch --]
[-- Type: text/plain, Size: 501 bytes --]

Index: sdl.c
===================================================================
RCS file: /cvsroot/qemu/qemu/sdl.c,v
retrieving revision 1.21
diff -u -r1.21 sdl.c
--- sdl.c	17 Jan 2005 22:32:23 -0000	1.21
+++ sdl.c	20 Jul 2005 09:37:07 -0000
@@ -53,7 +53,6 @@
     //    printf("resizing to %d %d\n", w, h);
 
     flags = SDL_HWSURFACE|SDL_ASYNCBLIT|SDL_HWACCEL;
-    flags |= SDL_RESIZABLE;
     if (gui_fullscreen)
         flags |= SDL_FULLSCREEN;
     screen = SDL_SetVideoMode(w, h, 0, flags);

[-- Attachment #3: qemu-20050718-01-vaddr.patch --]
[-- Type: text/plain, Size: 3621 bytes --]

Index: exec.c
===================================================================
RCS file: /cvsroot/qemu/qemu/exec.c,v
retrieving revision 1.60
diff -u -r1.60 exec.c
--- exec.c	24 Apr 2005 18:02:38 -0000	1.60
+++ exec.c	20 Jul 2005 11:36:49 -0000
@@ -95,9 +95,22 @@
 #endif
 } VirtPageDesc;
 
+#ifdef TARGET_X86_64
+/* XXX: this isn't exactly efficient, but we really need to maintain at least
+   48bit virtual address space */
+#define L2_VIRT_BITS 18
+#define L1_VIRT_BITS (48 - L2_VIRT_BITS - TARGET_PAGE_BITS)
 #define L2_BITS 10
 #define L1_BITS (32 - L2_BITS - TARGET_PAGE_BITS)
+#else
+#define L2_VIRT_BITS 10
+#define L1_VIRT_BITS (32 - L2_VIRT_BITS - TARGET_PAGE_BITS)
+#define L2_BITS 10
+#define L1_BITS (32 - L2_BITS - TARGET_PAGE_BITS)
+#endif
 
+#define L1_VIRT_SIZE (1 << L1_VIRT_BITS)
+#define L2_VIRT_SIZE (1 << L2_VIRT_BITS)
 #define L1_SIZE (1 << L1_BITS)
 #define L2_SIZE (1 << L2_BITS)
 
@@ -113,7 +126,7 @@
 PhysPageDesc **l1_phys_map;
 
 #if !defined(CONFIG_USER_ONLY)
-static VirtPageDesc *l1_virt_map[L1_SIZE];
+static VirtPageDesc *l1_virt_map[L1_VIRT_SIZE];
 static unsigned int virt_valid_tag;
 #endif
 
@@ -234,33 +247,29 @@
 static void tlb_protect_code(CPUState *env, target_ulong addr);
 static void tlb_unprotect_code_phys(CPUState *env, unsigned long phys_addr, target_ulong vaddr);
 
-static inline VirtPageDesc *virt_page_find_alloc(unsigned int index)
+static inline VirtPageDesc *virt_page_find_alloc(target_ulong index)
 {
     VirtPageDesc **lp, *p;
 
-    /* XXX: should not truncate for 64 bit addresses */
-#if TARGET_LONG_BITS > 32
-    index &= (L1_SIZE - 1);
-#endif
-    lp = &l1_virt_map[index >> L2_BITS];
+    lp = &l1_virt_map[(index >> L2_VIRT_BITS) & (L1_VIRT_SIZE - 1)];
     p = *lp;
     if (!p) {
         /* allocate if not found */
-        p = qemu_malloc(sizeof(VirtPageDesc) * L2_SIZE);
-        memset(p, 0, sizeof(VirtPageDesc) * L2_SIZE);
+        p = qemu_malloc(sizeof(VirtPageDesc) * L2_VIRT_SIZE);
+        memset(p, 0, sizeof(VirtPageDesc) * L2_VIRT_SIZE);
         *lp = p;
     }
-    return p + (index & (L2_SIZE - 1));
+    return p + (index & (L2_VIRT_SIZE - 1));
 }
 
-static inline VirtPageDesc *virt_page_find(unsigned int index)
+static inline VirtPageDesc *virt_page_find(target_ulong index)
 {
     VirtPageDesc *p;
 
-    p = l1_virt_map[index >> L2_BITS];
+    p = l1_virt_map[(index >> L2_VIRT_BITS) & (L1_VIRT_SIZE - 1)];
     if (!p)
         return 0;
-    return p + (index & (L2_SIZE - 1));
+    return p + (index & (L2_VIRT_SIZE - 1));
 }
 
 static void virt_page_flush(void)
@@ -272,10 +281,10 @@
 
     if (virt_valid_tag == 0) {
         virt_valid_tag = 1;
-        for(i = 0; i < L1_SIZE; i++) {
+        for(i = 0; i < L1_VIRT_SIZE; i++) {
             p = l1_virt_map[i];
             if (p) {
-                for(j = 0; j < L2_SIZE; j++)
+                for(j = 0; j < L2_VIRT_SIZE; j++)
                     p[j].valid_tag = 0;
             }
         }
@@ -367,6 +376,7 @@
 /* verify that all the pages have correct rights for code */
 static void tb_page_check(void)
 {
+#ifndef _WIN32
     TranslationBlock *tb;
     int i, flags1, flags2;
     
@@ -380,6 +390,7 @@
             }
         }
     }
+#endif
 }
 
 void tb_jmp_check(TranslationBlock *tb)
@@ -1572,7 +1583,7 @@
             addend = (unsigned long)phys_ram_base + (pd & TARGET_PAGE_MASK);
         }
         
-        index = (vaddr >> 12) & (CPU_TLB_SIZE - 1);
+        index = (vaddr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
         addend -= vaddr;
         if (prot & PAGE_READ) {
             env->tlb_read[is_user][index].address = address;

[-- Attachment #4: qemu-20050718-02-insns.patch --]
[-- Type: text/plain, Size: 16905 bytes --]

Index: target-i386/cpu.h
===================================================================
RCS file: /cvsroot/qemu/qemu/target-i386/cpu.h,v
retrieving revision 1.30
diff -u -r1.30 cpu.h
--- target-i386/cpu.h	23 Apr 2005 17:46:55 -0000	1.30
+++ target-i386/cpu.h	20 Jul 2005 09:37:07 -0000
@@ -214,6 +214,12 @@
 #define MSR_IA32_SYSENTER_ESP           0x175
 #define MSR_IA32_SYSENTER_EIP           0x176
 
+#define MSR_MCG_CAP                     0x179
+#define MSR_MCG_STATUS                  0x17a
+#define MSR_MCG_CTL                     0x17b
+
+#define MSR_PAT                         0x277
+
 #define MSR_EFER                        0xc0000080
 
 #define MSR_EFER_SCE   (1 << 0)
@@ -231,26 +237,29 @@
 #define MSR_KERNELGSBASE                0xc0000102
 
 /* cpuid_features bits */
-#define CPUID_FP87 (1 << 0)
-#define CPUID_VME  (1 << 1)
-#define CPUID_DE   (1 << 2)
-#define CPUID_PSE  (1 << 3)
-#define CPUID_TSC  (1 << 4)
-#define CPUID_MSR  (1 << 5)
-#define CPUID_PAE  (1 << 6)
-#define CPUID_MCE  (1 << 7)
-#define CPUID_CX8  (1 << 8)
-#define CPUID_APIC (1 << 9)
-#define CPUID_SEP  (1 << 11) /* sysenter/sysexit */
-#define CPUID_MTRR (1 << 12)
-#define CPUID_PGE  (1 << 13)
-#define CPUID_MCA  (1 << 14)
-#define CPUID_CMOV (1 << 15)
+#define CPUID_FP87    (1 << 0)
+#define CPUID_VME     (1 << 1)
+#define CPUID_DE      (1 << 2)
+#define CPUID_PSE     (1 << 3)
+#define CPUID_TSC     (1 << 4)
+#define CPUID_MSR     (1 << 5)
+#define CPUID_PAE     (1 << 6)
+#define CPUID_MCE     (1 << 7)
+#define CPUID_CX8     (1 << 8)
+#define CPUID_APIC    (1 << 9)
+#define CPUID_SEP     (1 << 11) /* sysenter/sysexit */
+#define CPUID_MTRR    (1 << 12)
+#define CPUID_PGE     (1 << 13)
+#define CPUID_MCA     (1 << 14)
+#define CPUID_CMOV    (1 << 15)
+#define CPUID_PAT     (1 << 16)
 /* ... */
-#define CPUID_MMX  (1 << 23)
-#define CPUID_FXSR (1 << 24)
-#define CPUID_SSE  (1 << 25)
-#define CPUID_SSE2 (1 << 26)
+#define CPUID_CLFLUSH (1 << 19)
+/* ... */
+#define CPUID_MMX     (1 << 23)
+#define CPUID_FXSR    (1 << 24)
+#define CPUID_SSE     (1 << 25)
+#define CPUID_SSE2    (1 << 26)
 
 #define CPUID_EXT_SS3      (1 << 0)
 #define CPUID_EXT_MONITOR  (1 << 3)
@@ -473,6 +482,8 @@
     target_ulong fmask;
     target_ulong kernelgsbase;
 #endif
+
+    uint64_t pat;
 
     /* temporary data for USE_CODE_COPY mode */
 #ifdef USE_CODE_COPY
Index: target-i386/exec.h
===================================================================
RCS file: /cvsroot/qemu/qemu/target-i386/exec.h,v
retrieving revision 1.24
diff -u -r1.24 exec.h
--- target-i386/exec.h	20 Mar 2005 10:39:24 -0000	1.24
+++ target-i386/exec.h	20 Jul 2005 09:37:07 -0000
@@ -157,11 +157,11 @@
 void helper_ltr_T0(void);
 void helper_movl_crN_T0(int reg);
 void helper_movl_drN_T0(int reg);
-void helper_invlpg(unsigned int addr);
+void helper_invlpg(target_ulong addr);
 void cpu_x86_update_cr0(CPUX86State *env, uint32_t new_cr0);
 void cpu_x86_update_cr3(CPUX86State *env, target_ulong new_cr3);
 void cpu_x86_update_cr4(CPUX86State *env, uint32_t new_cr4);
-void cpu_x86_flush_tlb(CPUX86State *env, uint32_t addr);
+void cpu_x86_flush_tlb(CPUX86State *env, target_ulong addr);
 int cpu_x86_handle_mmu_fault(CPUX86State *env, target_ulong addr, 
                              int is_write, int is_user, int is_softmmu);
 void tlb_fill(target_ulong addr, int is_write, int is_user, 
Index: target-i386/helper.c
===================================================================
RCS file: /cvsroot/qemu/qemu/target-i386/helper.c,v
retrieving revision 1.49
diff -u -r1.49 helper.c
--- target-i386/helper.c	24 Apr 2005 18:04:33 -0000	1.49
+++ target-i386/helper.c	20 Jul 2005 09:37:07 -0000
@@ -1334,6 +1334,20 @@
         ECX = env->cpuid_model[(index - 0x80000002) * 4 + 2];
         EDX = env->cpuid_model[(index - 0x80000002) * 4 + 3];
         break;
+    case 0x80000005:
+        /* cache info (L1 cache) */
+        EAX = 0x01ff01ff;
+        EBX = 0x01ff01ff;
+        ECX = 0x40020140;
+        EDX = 0x40020140;
+        break;
+    case 0x80000006:
+        /* cache info (L2 cache) */
+        EAX = 0;
+        EBX = 0x42004200;
+        ECX = 0x02008140;
+        EDX = 0;
+        break;
     case 0x80000008:
         /* virtual & phys address size in low 2 bytes. */
         EAX = 0x00003028;
@@ -1354,12 +1368,26 @@
 void helper_enter_level(int level, int data32)
 {
     target_ulong ssp;
-    uint32_t esp_mask, esp, ebp;
+    uint32_t esp_mask;
+    target_ulong esp, ebp;
 
     esp_mask = get_sp_mask(env->segs[R_SS].flags);
     ssp = env->segs[R_SS].base;
     ebp = EBP;
     esp = ESP;
+#ifdef TARGET_X86_64
+    if (env->hflags & HF_CS64_MASK) {
+        /* 64 bit */
+        esp -= 8;
+        while (--level) {
+            esp -= 8;
+            ebp -= 8;
+            stq(ssp + esp, ldq(ssp + ebp));
+        }
+        esp -= 8;
+        stq(ssp + esp, T1);
+    } else 
+#endif
     if (data32) {
         /* 32 bit */
         esp -= 4;
@@ -2271,7 +2299,7 @@
     env->dr[reg] = T0;
 }
 
-void helper_invlpg(unsigned int addr)
+void helper_invlpg(target_ulong addr)
 {
     cpu_x86_flush_tlb(env, addr);
 }
@@ -2332,6 +2360,9 @@
     case MSR_STAR:
         env->star = val;
         break;
+    case MSR_PAT:
+        env->pat = val;
+        break;
 #ifdef TARGET_X86_64
     case MSR_LSTAR:
         env->lstar = val;
@@ -2379,6 +2410,9 @@
         break;
     case MSR_STAR:
         val = env->star;
+        break;
+    case MSR_PAT:
+        val = env->pat;
         break;
 #ifdef TARGET_X86_64
     case MSR_LSTAR:
Index: target-i386/helper2.c
===================================================================
RCS file: /cvsroot/qemu/qemu/target-i386/helper2.c,v
retrieving revision 1.34
diff -u -r1.34 helper2.c
--- target-i386/helper2.c	3 Jul 2005 21:29:17 -0000	1.34
+++ target-i386/helper2.c	20 Jul 2005 20:32:36 -0000
@@ -106,7 +106,9 @@
         env->cpuid_version = (family << 8) | (model << 4) | stepping;
         env->cpuid_features = (CPUID_FP87 | CPUID_DE | CPUID_PSE |
                                CPUID_TSC | CPUID_MSR | CPUID_MCE |
-                               CPUID_CX8 | CPUID_PGE | CPUID_CMOV);
+                               CPUID_CX8 | CPUID_PGE | CPUID_CMOV |
+                               CPUID_PAT);
+        env->pat = 0x0007040600070406ULL;
         env->cpuid_ext_features = 0;
         env->cpuid_features |= CPUID_FXSR | CPUID_MMX | CPUID_SSE | CPUID_SSE2 | CPUID_PAE | CPUID_SEP;
         env->cpuid_xlevel = 0;
@@ -128,6 +130,9 @@
         env->cpuid_ext2_features = (env->cpuid_features & 0x0183F3FF);
         env->cpuid_ext2_features |= CPUID_EXT2_LM | CPUID_EXT2_SYSCALL;
         env->cpuid_xlevel = 0x80000008;
+
+        /* these features are needed for Win64 and aren't fully implemented */
+        env->cpuid_features |= CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA;
 #endif
     }
     cpu_single_env = env;
@@ -546,7 +551,7 @@
 }
 
 /* XXX: also flush 4MB pages */
-void cpu_x86_flush_tlb(CPUX86State *env, uint32_t addr)
+void cpu_x86_flush_tlb(CPUX86State *env, target_ulong addr)
 {
     tlb_flush_page(env, addr);
 }
Index: target-i386/op.c
===================================================================
RCS file: /cvsroot/qemu/qemu/target-i386/op.c,v
retrieving revision 1.37
diff -u -r1.37 op.c
--- target-i386/op.c	26 Apr 2005 20:38:17 -0000	1.37
+++ target-i386/op.c	20 Jul 2005 09:37:07 -0000
@@ -898,6 +898,11 @@
 }
 
 #ifdef TARGET_X86_64
+void op_subq_A0_2(void)
+{
+    A0 -= 2;
+}
+
 void op_subq_A0_8(void)
 {
     A0 -= 8;
Index: target-i386/translate.c
===================================================================
RCS file: /cvsroot/qemu/qemu/target-i386/translate.c,v
retrieving revision 1.49
diff -u -r1.49 translate.c
--- target-i386/translate.c	23 Apr 2005 17:53:12 -0000	1.49
+++ target-i386/translate.c	20 Jul 2005 09:37:07 -0000
@@ -1604,7 +1604,14 @@
                 else
                     override = R_DS;
             }
-            gen_op_addl_A0_seg(offsetof(CPUX86State,segs[override].base));
+#ifdef TARGET_X86_64
+            if (CODE64(s)) {
+                gen_op_addq_A0_seg(offsetof(CPUX86State,segs[override].base));
+            } else 
+#endif
+            {
+                gen_op_addl_A0_seg(offsetof(CPUX86State,segs[override].base));
+            }
         }
     }
 
@@ -1627,7 +1634,14 @@
         override = R_DS;
     }
     if (must_add_seg) {
-        gen_op_addl_A0_seg(offsetof(CPUX86State,segs[override].base));
+#ifdef TARGET_X86_64
+        if (CODE64(s)) {
+            gen_op_addq_A0_seg(offsetof(CPUX86State,segs[override].base));
+        } else 
+#endif
+        {
+            gen_op_addl_A0_seg(offsetof(CPUX86State,segs[override].base));
+        }
     }
 }
 
@@ -1948,10 +1962,14 @@
 {
 #ifdef TARGET_X86_64
     if (CODE64(s)) {
-        /* XXX: check 16 bit behaviour */
         gen_op_movq_A0_reg[R_ESP]();
-        gen_op_subq_A0_8();
-        gen_op_st_T0_A0[OT_QUAD + s->mem_index]();
+        if (s->dflag) {
+            gen_op_subq_A0_8();
+            gen_op_st_T0_A0[OT_QUAD + s->mem_index]();
+        } else {
+            gen_op_subq_A0_2();
+            gen_op_st_T0_A0[OT_WORD + s->mem_index]();
+        }
         gen_op_movq_ESP_A0();
     } else 
 #endif
@@ -1985,10 +2003,14 @@
 {
 #ifdef TARGET_X86_64
     if (CODE64(s)) {
-        /* XXX: check 16 bit behaviour */
         gen_op_movq_A0_reg[R_ESP]();
-        gen_op_subq_A0_8();
-        gen_op_st_T1_A0[OT_QUAD + s->mem_index]();
+        if (s->dflag) {
+            gen_op_subq_A0_8();
+            gen_op_st_T1_A0[OT_QUAD + s->mem_index]();
+        } else {
+            gen_op_subq_A0_2();
+            gen_op_st_T0_A0[OT_WORD + s->mem_index]();
+        }
         gen_op_movq_ESP_A0();
     } else 
 #endif
@@ -2020,9 +2042,8 @@
 {
 #ifdef TARGET_X86_64
     if (CODE64(s)) {
-        /* XXX: check 16 bit behaviour */
         gen_op_movq_A0_reg[R_ESP]();
-        gen_op_ld_T0_A0[OT_QUAD + s->mem_index]();
+        gen_op_ld_T0_A0[(s->dflag ? OT_QUAD : OT_WORD) + s->mem_index]();
     } else 
 #endif
     {
@@ -2041,7 +2062,7 @@
 static void gen_pop_update(DisasContext *s)
 {
 #ifdef TARGET_X86_64
-    if (CODE64(s)) {
+    if (CODE64(s) && s->dflag) {
         gen_stack_update(s, 8);
     } else
 #endif
@@ -2056,8 +2077,16 @@
     if (!s->ss32)
         gen_op_andl_A0_ffff();
     gen_op_movl_T1_A0();
-    if (s->addseg)
-        gen_op_addl_A0_seg(offsetof(CPUX86State,segs[R_SS].base));
+    if (s->addseg) {
+#ifdef TARGET_X86_64
+        if (CODE64(s)) {
+            gen_op_addq_A0_seg(offsetof(CPUX86State,segs[R_SS].base));
+        } else 
+#endif
+        {
+            gen_op_addl_A0_seg(offsetof(CPUX86State,segs[R_SS].base));
+        }
+    }
 }
 
 /* NOTE: wrap around in 16 bit not fully handled */
@@ -2069,8 +2098,16 @@
     if (!s->ss32)
         gen_op_andl_A0_ffff();
     gen_op_movl_T1_A0();
-    if (s->addseg)
-        gen_op_addl_A0_seg(offsetof(CPUX86State,segs[R_SS].base));
+    if (s->addseg) {
+#ifdef TARGET_X86_64
+        if (CODE64(s)) {
+            gen_op_addq_A0_seg(offsetof(CPUX86State,segs[R_SS].base));
+        } else 
+#endif
+        {
+            gen_op_addl_A0_seg(offsetof(CPUX86State,segs[R_SS].base));
+        }
+    }
     for(i = 0;i < 8; i++) {
         gen_op_mov_TN_reg[OT_LONG][0][7 - i]();
         gen_op_st_T0_A0[OT_WORD + s->dflag + s->mem_index]();
@@ -2088,8 +2125,16 @@
         gen_op_andl_A0_ffff();
     gen_op_movl_T1_A0();
     gen_op_addl_T1_im(16 <<  s->dflag);
-    if (s->addseg)
-        gen_op_addl_A0_seg(offsetof(CPUX86State,segs[R_SS].base));
+    if (s->addseg) {
+#ifdef TARGET_X86_64
+        if (CODE64(s)) {
+            gen_op_addq_A0_seg(offsetof(CPUX86State,segs[R_SS].base));
+        } else 
+#endif
+        {
+            gen_op_addl_A0_seg(offsetof(CPUX86State,segs[R_SS].base));
+        }
+    }
     for(i = 0;i < 8; i++) {
         /* ESP is not reloaded */
         if (i != 3) {
@@ -2105,26 +2150,39 @@
 {
     int ot, opsize;
 
-    ot = s->dflag + OT_WORD;
+    if (CODE64(s)) {
+        ot = OT_QUAD;
+        opsize = 8;
+    } else {
+        ot = s->ss32 + OT_WORD;
+        opsize = 2 << s->ss32;
+    }
     level &= 0x1f;
-    opsize = 2 << s->dflag;
 
     gen_op_movl_A0_ESP();
     gen_op_addl_A0_im(-opsize);
     if (!s->ss32)
         gen_op_andl_A0_ffff();
     gen_op_movl_T1_A0();
-    if (s->addseg)
-        gen_op_addl_A0_seg(offsetof(CPUX86State,segs[R_SS].base));
+    if (s->addseg) {
+#ifdef TARGET_X86_64
+        if (CODE64(s)) {
+            gen_op_addq_A0_seg(offsetof(CPUX86State,segs[R_SS].base));
+        } else 
+#endif
+        {
+            gen_op_addl_A0_seg(offsetof(CPUX86State,segs[R_SS].base));
+        }
+    }
     /* push bp */
-    gen_op_mov_TN_reg[OT_LONG][0][R_EBP]();
+    gen_op_mov_TN_reg[ot][0][R_EBP]();
     gen_op_st_T0_A0[ot + s->mem_index]();
     if (level) {
         gen_op_enter_level(level, s->dflag);
     }
     gen_op_mov_reg_T1[ot][R_EBP]();
     gen_op_addl_T1_im( -esp_addend + (-opsize * level) );
-    gen_op_mov_reg_T1[OT_WORD + s->ss32][R_ESP]();
+    gen_op_mov_reg_T1[ot][R_ESP]();
 }
 
 static void gen_exception(DisasContext *s, int trapno, target_ulong cur_eip)
@@ -2901,7 +2960,7 @@
             if (mod != 3) 
                 goto illegal_op;
 #ifdef TARGET_X86_64
-            if (CODE64(s)) {
+            if (s->aflag == 2) {
                 gen_op_movq_A0_reg[R_EDI]();
             } else 
 #endif
@@ -3442,6 +3501,8 @@
             gen_add_A0_im(s, 1 << (ot - OT_WORD + 1));
             gen_op_ldu_T0_A0[OT_WORD + s->mem_index]();
         do_lcall:
+            if (CODE64(s) && s->dflag)
+                s->dflag = 2;
             if (s->pe && !s->vm86) {
                 if (s->cc_op != CC_OP_DYNAMIC)
                     gen_op_set_cc_op(s->cc_op);
@@ -3635,7 +3696,12 @@
         /**************************/
         /* push/pop */
     case 0x50 ... 0x57: /* push */
-        gen_op_mov_TN_reg[OT_LONG][0][(b & 7) | REX_B(s)]();
+        if (CODE64(s)) {
+            ot = dflag ? OT_QUAD : OT_WORD;
+        } else {
+            ot = dflag + OT_WORD;
+        }
+        gen_op_mov_TN_reg[ot][0][(b & 7) | REX_B(s)]();
         gen_push_T0(s);
         break;
     case 0x58 ... 0x5f: /* pop */
@@ -3697,7 +3763,6 @@
         break;
     case 0xc8: /* enter */
         {
-            /* XXX: long mode support */
             int level;
             val = lduw_code(s->pc);
             s->pc += 2;
@@ -3707,7 +3772,6 @@
         break;
     case 0xc9: /* leave */
         /* XXX: exception not precise (ESP is updated before potential exception) */
-        /* XXX: may be invalid for 16 bit in long mode */
         if (CODE64(s)) {
             gen_op_mov_TN_reg[OT_QUAD][0][R_EBP]();
             gen_op_mov_reg_T0[OT_QUAD][R_ESP]();
@@ -3926,7 +3990,7 @@
             else
                 ot = dflag + OT_WORD;
 #ifdef TARGET_X86_64
-            if (CODE64(s)) {
+            if (s->aflag == 2) {
                 offset_addr = ldq_code(s->pc);
                 s->pc += 8;
                 if (offset_addr == (int32_t)offset_addr)
@@ -3955,7 +4019,7 @@
         break;
     case 0xd7: /* xlat */
 #ifdef TARGET_X86_64
-        if (CODE64(s)) {
+        if (s->aflag == 2) {
             gen_op_movq_A0_reg[R_EBX]();
             gen_op_addq_A0_AL();
         } else 
@@ -4779,6 +4843,8 @@
         val = ldsw_code(s->pc);
         s->pc += 2;
         gen_pop_T0(s);
+        if (CODE64(s) && s->dflag)
+            s->dflag = 2;
         gen_stack_update(s, val + (2 << s->dflag));
         if (s->dflag == 0)
             gen_op_andl_T0_ffff();
@@ -4801,6 +4867,8 @@
             if (s->cc_op != CC_OP_DYNAMIC)
                 gen_op_set_cc_op(s->cc_op);
             gen_jmp_im(pc_start - s->cs_base);
+            if (CODE64(s) && s->dflag)
+                s->dflag = 2;
             gen_op_lret_protected(s->dflag, val);
         } else {
             gen_stack_A0(s);
@@ -5782,13 +5850,26 @@
             break;
         case 5: /* lfence */
         case 6: /* mfence */
-        case 7: /* sfence */
-            if ((modrm & 0xc7) != 0xc0 || !(s->cpuid_features & CPUID_SSE))
-                goto illegal_op;
-            break;
+        case 7: /* sfence / clflush */
+            if ((modrm & 0xc7) == 0xc0) {
+                if (!(s->cpuid_features & CPUID_SSE))
+                    goto illegal_op;
+                break;
+            } else
+            if (op == 7) {
+                if (!(s->cpuid_features & CPUID_CLFLUSH))
+                    goto illegal_op;
+                break;
+            }
+            /* fallback */
         default:
             goto illegal_op;
         }
+        break;
+    case 0x10d:
+        modrm = ldub_code(s->pc++);
+        gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
+        /* ignore for now */
         break;
     case 0x110 ... 0x117:
     case 0x128 ... 0x12f:

[-- Attachment #5: qemu-20050718-03-apic.patch --]
[-- Type: text/plain, Size: 22429 bytes --]

Index: vl.h
===================================================================
RCS file: /cvsroot/qemu/qemu/vl.h,v
retrieving revision 1.79
diff -u -r1.79 vl.h
--- vl.h	3 Jul 2005 14:00:50 -0000	1.79
+++ vl.h	20 Jul 2005 09:37:07 -0000
@@ -703,6 +703,8 @@
 /* APIC */
 int apic_init(CPUState *env);
 int apic_get_interrupt(CPUState *env);
+int ioapic_init(void);
+void ioapic_set_irq(uint32_t vector, int level);
 
 /* i8254.c */
 
Index: hw/apic.c
===================================================================
RCS file: /cvsroot/qemu/qemu/hw/apic.c,v
retrieving revision 1.2
diff -u -r1.2 apic.c
--- hw/apic.c	23 Jan 2005 20:42:29 -0000	1.2
+++ hw/apic.c	21 Jul 2005 05:57:01 -0000
@@ -20,6 +20,7 @@
 #include "vl.h"
 
 //#define DEBUG_APIC
+//#define DEBUG_IOAPIC
 
 /* APIC Local Vector Table */
 #define APIC_LVT_TIMER   0
@@ -39,6 +40,10 @@
 #define APIC_DM_SIPI	6
 #define APIC_DM_EXTINT	7
 
+/* APIC destination mode */
+#define APIC_DESTMODE_FLAT	0xf
+#define APIC_DESTMODE_CLUSTER	1
+
 #define APIC_TRIGGER_EDGE  0
 #define APIC_TRIGGER_LEVEL 1
 
@@ -49,6 +54,8 @@
 #define	APIC_INPUT_POLARITY		(1<<13)
 #define	APIC_SEND_PENDING		(1<<12)
 
+#define IOAPIC_NUM_PINS			0x18
+
 #define ESR_ILLEGAL_ADDRESS (1 << 7)
 
 #define APIC_SV_ENABLE (1 << 8)
@@ -57,8 +64,11 @@
     CPUState *cpu_env;
     uint32_t apicbase;
     uint8_t id;
+    uint8_t arb_id;
     uint8_t tpr;
     uint32_t spurious_vec;
+    uint8_t log_dest;
+    uint8_t dest_mode;
     uint32_t isr[8];  /* in service register */
     uint32_t tmr[8];  /* trigger mode register */
     uint32_t irr[8]; /* interrupt request register */
@@ -71,9 +81,65 @@
     uint32_t initial_count;
     int64_t initial_count_load_time, next_time;
     QEMUTimer *timer;
+
+    struct APICState *next_apic;
 } APICState;
 
+typedef struct IOAPICState {
+    uint8_t id;
+    uint8_t ioregsel;
+
+    uint32_t irr;
+    uint64_t ioredtbl[IOAPIC_NUM_PINS];
+} IOAPICState;
+
 static int apic_io_memory;
+static APICState *first_local_apic = NULL;
+static int last_apic_id = 0;
+static IOAPICState *ioapic_state;
+
+static void apic_init_ipi(APICState *s);
+static void apic_set_irq(APICState *s, int vector_num, int trigger_mode);
+static void apic_update_irq(APICState *s);
+
+static void apic_bus_deliver(uint32_t deliver_bitmask, uint8_t delivery_mode,
+                             uint8_t vector_num, uint8_t polarity,
+                             uint8_t trigger_mode)
+{
+    APICState *apic_iter;
+
+    switch (delivery_mode) {
+        case APIC_DM_LOWPRI:
+        case APIC_DM_FIXED:
+            /* XXX: arbitration */
+            break;
+
+        case APIC_DM_SMI:
+        case APIC_DM_NMI:
+            break;
+
+        case APIC_DM_INIT:
+            /* normal INIT IPI sent to processors */
+            for (apic_iter = first_local_apic; apic_iter != NULL;
+                 apic_iter = apic_iter->next_apic) {
+                apic_init_ipi(apic_iter);
+            }
+            return;
+    
+        case APIC_DM_EXTINT:
+            /* XXX: implement */
+            break;
+
+        default:
+            return;
+    }
+
+    for (apic_iter = first_local_apic; apic_iter != NULL;
+         apic_iter = apic_iter->next_apic) {
+        if (deliver_bitmask & (1 << apic_iter->id))
+            apic_set_irq(apic_iter, vector_num, trigger_mode);
+    }
+}
 
 void cpu_set_apic_base(CPUState *env, uint64_t val)
 {
@@ -104,6 +170,7 @@
 {
     APICState *s = env->apic_state;
     s->tpr = (val & 0x0f) << 4;
+    apic_update_irq(s);
 }
 
 uint8_t cpu_get_apic_tpr(CPUX86State *env)
@@ -112,16 +179,24 @@
     return s->tpr >> 4;
 }
 
-/* return -1 if no bit is set */
-static int get_highest_priority_int(uint32_t *tab)
+int fls_bit(int value)
 {
-    int i;
-    for(i = 0;i < 8; i++) {
-        if (tab[i] != 0) {
-            return i * 32 + ffs(tab[i]) - 1;
-        }
-    }
-    return -1;
+    unsigned int ret = 0;
+
+#ifdef HOST_I386
+    __asm__ __volatile__ ("bsr %1, %0\n" : "+r" (ret) : "rm" (value));
+    return ret;
+#else
+    if (value > 0xffff)
+        value >>= 16, ret = 16;
+    if (value > 0xff)
+        value >>= 8, ret += 8;
+    if (value > 0xf)
+        value >>= 4, ret += 4;
+    if (value > 0x3)
+        value >>= 2, ret += 2;
+    return ret + (value >> 1);
+#endif
 }
 
 static inline void set_bit(uint32_t *tab, int index)
@@ -140,6 +215,18 @@
     tab[i] &= ~mask;
 }
 
+/* return -1 if no bit is set */
+static int get_highest_priority_int(uint32_t *tab)
+{
+    int i;
+    for(i = 7; i >= 0; i--) {
+        if (tab[i] != 0) {
+            return i * 32 + fls_bit(tab[i]);
+        }
+    }
+    return -1;
+}
+
 static int apic_get_ppr(APICState *s)
 {
     int tpr, isrv, ppr;
@@ -156,16 +243,23 @@
     return ppr;
 }
 
+static int apic_get_arb_pri(APICState *s)
+{
+    /* XXX: arbitration */
+    return 0;
+}
+
 /* signal the CPU if an irq is pending */
 static void apic_update_irq(APICState *s)
 {
-    int irrv, isrv;
+    int irrv, ppr;
+    if (!(s->spurious_vec & APIC_SV_ENABLE))
+        return;
     irrv = get_highest_priority_int(s->irr);
     if (irrv < 0)
         return;
-    isrv = get_highest_priority_int(s->isr);
-    /* if the pending irq has less priority, we do not make a new request */
-    if (isrv >= 0 && irrv >= isrv)
+    ppr = apic_get_ppr(s);
+    if (ppr && (irrv & 0xf0) <= (ppr & 0xf0))
         return;
     cpu_interrupt(s->cpu_env, CPU_INTERRUPT_HARD);
 }
@@ -187,9 +281,116 @@
     if (isrv < 0)
         return;
     reset_bit(s->isr, isrv);
+    /* XXX: send the EOI packet to the APIC bus to allow the I/O APIC to
+            set the remote IRR bit for level triggered interrupts. */
     apic_update_irq(s);
 }
 
+static uint32_t apic_get_delivery_bitmask(uint8_t dest, uint8_t dest_mode)
+{
+    uint32_t mask = 0;
+    APICState *apic_iter;
+
+    if (dest_mode == 0) {
+        if (dest == 0xff)
+            mask = 0xff;
+        else
+            mask = 1 << dest;
+    } else {
+        /* XXX: cluster mode */
+        for (apic_iter = first_local_apic; apic_iter != NULL;
+             apic_iter = apic_iter->next_apic) {
+            if (dest & apic_iter->log_dest)
+                mask |= (1 << apic_iter->id);
+        }
+    }
+
+    return mask;
+}
+
+
+static void apic_init_ipi(APICState *s)
+{
+    int i;
+
+    for(i = 0; i < APIC_LVT_NB; i++)
+        s->lvt[i] = 1 << 16; /* mask LVT */
+    s->tpr = 0;
+    s->spurious_vec = 0xff;
+    s->log_dest = 0;
+    s->dest_mode = 0;
+    memset(s->isr, 0, sizeof(s->isr));
+    memset(s->tmr, 0, sizeof(s->tmr));
+    memset(s->irr, 0, sizeof(s->irr));
+    memset(s->lvt, 0, sizeof(s->lvt));
+    s->esr = 0;
+    memset(s->icr, 0, sizeof(s->icr));
+    s->divide_conf = 0;
+    s->count_shift = 0;
+    s->initial_count = 0;
+    s->initial_count_load_time = 0;
+    s->next_time = 0;
+}
+
+static void apic_deliver(APICState *s, uint8_t dest, uint8_t dest_mode,
+                         uint8_t delivery_mode, uint8_t vector_num,
+                         uint8_t polarity, uint8_t trigger_mode)
+{
+    uint32_t deliver_bitmask = 0;
+    int dest_shorthand = (s->icr[0] >> 18) & 3;
+    APICState *apic_iter;
+
+    switch (delivery_mode) {
+        case APIC_DM_LOWPRI:
+            /* XXX: serch for focus processor, arbitration */
+            dest = s->id;
+
+        case APIC_DM_INIT:
+            {
+                int trig_mode = (s->icr[0] >> 15) & 1;
+                int level = (s->icr[0] >> 14) & 1;
+                if (level == 0 && trig_mode == 1) {
+                    for (apic_iter = first_local_apic; apic_iter != NULL;
+                         apic_iter = apic_iter->next_apic) {
+                        if (deliver_bitmask & (1 << apic_iter->id)) {
+                            apic_iter->arb_id = apic_iter->id;
+                        }
+                    }
+                    return;
+                }
+            }
+            break;
+
+        case APIC_DM_SIPI:
+            for (apic_iter = first_local_apic; apic_iter != NULL;
+                 apic_iter = apic_iter->next_apic) {
+                if (deliver_bitmask & (1 << apic_iter->id)) {
+                    /* XXX: SMP support */
+                    /* apic_startup(apic_iter); */
+                }
+            }
+            return;
+    }
+
+    switch (dest_shorthand) {
+        case 0:
+            deliver_bitmask = apic_get_delivery_bitmask(dest, dest_mode);
+            break;
+        case 1:
+            deliver_bitmask = (1 << s->id);
+            break;
+        case 2:
+            deliver_bitmask = 0xffffffff;
+            break;
+        case 3:
+            deliver_bitmask = 0xffffffff & ~(1 << s->id);
+            break;
+    }
+
+    apic_bus_deliver(deliver_bitmask, delivery_mode, vector_num, polarity,
+                     trigger_mode);
+}
+
 int apic_get_interrupt(CPUState *env)
 {
     APICState *s = env->apic_state;
@@ -207,6 +408,8 @@
     if (intno < 0)
         return -1;
     reset_bit(s->irr, intno);
+    if (s->tpr && intno <= s->tpr)
+        return s->spurious_vec & 0xff;
     set_bit(s->isr, intno);
     apic_update_irq(s);
     return intno;
@@ -220,7 +423,7 @@
         s->count_shift;
     if (s->lvt[APIC_LVT_TIMER] & APIC_LVT_TIMER_PERIODIC) {
         /* periodic */
-        val = s->initial_count - (d % (s->initial_count + 1));
+        val = s->initial_count - (d % ((uint64_t)s->initial_count + 1));
     } else {
         if (d >= s->initial_count)
             val = 0;
@@ -238,11 +441,11 @@
         d = (current_time - s->initial_count_load_time) >> 
             s->count_shift;
         if (s->lvt[APIC_LVT_TIMER] & APIC_LVT_TIMER_PERIODIC) {
-            d = ((d / (s->initial_count + 1)) + 1) * (s->initial_count + 1);
+            d = ((d / ((uint64_t)s->initial_count + 1)) + 1) * ((uint64_t)s->initial_count + 1);
         } else {
             if (d >= s->initial_count)
                 goto no_timer;
-            d = s->initial_count + 1;
+            d = (uint64_t)s->initial_count + 1;
         }
         next_time = s->initial_count_load_time + (d << s->count_shift);
         qemu_mod_timer(s->timer, next_time);
@@ -283,16 +486,10 @@
 
 static uint32_t apic_mem_readl(void *opaque, target_phys_addr_t addr)
 {
-    CPUState *env;
-    APICState *s;
+    APICState *s = opaque;
     uint32_t val;
     int index;
 
-    env = cpu_single_env;
-    if (!env)
-        return 0;
-    s = env->apic_state;
-
     index = (addr >> 4) & 0xff;
     switch(index) {
     case 0x02: /* id */
@@ -304,10 +501,19 @@
     case 0x08:
         val = s->tpr;
         break;
+    case 0x09:
+        val = apic_get_arb_pri(s);
+        break;
     case 0x0a:
         /* ppr */
         val = apic_get_ppr(s);
         break;
+    case 0x0d:
+        val = s->log_dest << 24;
+        break;
+    case 0x0e:
+        val = s->dest_mode << 28;
+        break;
     case 0x0f:
         val = s->spurious_vec;
         break;
@@ -352,15 +558,9 @@
 
 static void apic_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
 {
-    CPUState *env;
-    APICState *s;
+    APICState *s = opaque;
     int index;
 
-    env = cpu_single_env;
-    if (!env)
-        return;
-    s = env->apic_state;
-
 #ifdef DEBUG_APIC
     printf("APIC write: %08x = %08x\n", (uint32_t)addr, val);
 #endif
@@ -372,16 +572,29 @@
         break;
     case 0x08:
         s->tpr = val;
+        apic_update_irq(s);
         break;
     case 0x0b: /* EOI */
         apic_eoi(s);
         break;
+    case 0x0d:
+        s->log_dest = val >> 24;
+        break;
+    case 0x0e:
+        s->dest_mode = val >> 28;
+        break;
     case 0x0f:
         s->spurious_vec = val & 0x1ff;
+        apic_update_irq(s);
         break;
     case 0x30:
+        s->icr[0] = val;
+        apic_deliver(s, (s->icr[1] >> 24) & 0xff, (s->icr[0] >> 11) & 1,
+                     (s->icr[0] >> 8) & 7, (s->icr[0] & 0xff),
+                     (s->icr[0] >> 14) & 1, (s->icr[0] >> 15) & 1);
+        break;
     case 0x31:
-        s->icr[index & 1] = val;
+        s->icr[1] = val;
         break;
     case 0x32 ... 0x37:
         {
@@ -410,7 +623,76 @@
     }
 }
 
+static void apic_save(QEMUFile *f, void *opaque)
+{
+    APICState *s = opaque;
+    int i;
+
+    qemu_put_be32s(f, &s->apicbase);
+    qemu_put_8s(f, &s->id);
+    qemu_put_8s(f, &s->arb_id);
+    qemu_put_8s(f, &s->tpr);
+    qemu_put_be32s(f, &s->spurious_vec);
+    qemu_put_8s(f, &s->log_dest);
+    qemu_put_8s(f, &s->dest_mode);
+    for (i = 0; i < 8; i++) {
+        qemu_put_be32s(f, &s->isr[i]);
+        qemu_put_be32s(f, &s->tmr[i]);
+        qemu_put_be32s(f, &s->irr[i]);
+    }
+    for (i = 0; i < APIC_LVT_NB; i++) {
+        qemu_put_be32s(f, &s->lvt[i]);
+    }
+    qemu_put_be32s(f, &s->esr);
+    qemu_put_be32s(f, &s->icr[0]);
+    qemu_put_be32s(f, &s->icr[1]);
+    qemu_put_be32s(f, &s->divide_conf);
+    qemu_put_be32s(f, &s->count_shift);
+    qemu_put_be32s(f, &s->initial_count);
+    qemu_put_be64s(f, &s->initial_count_load_time);
+    qemu_put_be64s(f, &s->next_time);
+}
+
+static int apic_load(QEMUFile *f, void *opaque, int version_id)
+{
+    APICState *s = opaque;
+    int i;
+
+    if (version_id != 1)
+        return -EINVAL;
 
+    /* XXX: what if the base changes? (registered memory regions) */
+    qemu_get_be32s(f, &s->apicbase);
+    qemu_get_8s(f, &s->id);
+    qemu_get_8s(f, &s->arb_id);
+    qemu_get_8s(f, &s->tpr);
+    qemu_get_be32s(f, &s->spurious_vec);
+    qemu_get_8s(f, &s->log_dest);
+    qemu_get_8s(f, &s->dest_mode);
+    for (i = 0; i < 8; i++) {
+        qemu_get_be32s(f, &s->isr[i]);
+        qemu_get_be32s(f, &s->tmr[i]);
+        qemu_get_be32s(f, &s->irr[i]);
+    }
+    for (i = 0; i < APIC_LVT_NB; i++) {
+        qemu_get_be32s(f, &s->lvt[i]);
+    }
+    qemu_get_be32s(f, &s->esr);
+    qemu_get_be32s(f, &s->icr[0]);
+    qemu_get_be32s(f, &s->icr[1]);
+    qemu_get_be32s(f, &s->divide_conf);
+    qemu_get_be32s(f, &s->count_shift);
+    qemu_get_be32s(f, &s->initial_count);
+    qemu_get_be64s(f, &s->initial_count_load_time);
+    qemu_get_be64s(f, &s->next_time);
+    return 0;
+}
+
+static void apic_reset(void *opaque)
+{
+    APICState *s = opaque;
+    apic_init_ipi(s);
+}
 
 static CPUReadMemoryFunc *apic_mem_read[3] = {
     apic_mem_readb,
@@ -427,27 +709,231 @@
 int apic_init(CPUState *env)
 {
     APICState *s;
-    int i;
 
-    s = malloc(sizeof(APICState));
+    s = qemu_mallocz(sizeof(APICState));
     if (!s)
         return -1;
-    memset(s, 0, sizeof(*s));
     env->apic_state = s;
+    apic_init_ipi(s);
+    s->id = last_apic_id++;
     s->cpu_env = env;
     s->apicbase = 0xfee00000 | 
-        MSR_IA32_APICBASE_BSP | MSR_IA32_APICBASE_ENABLE;
-    for(i = 0; i < APIC_LVT_NB; i++)
-        s->lvt[i] = 1 << 16; /* mask LVT */
-    s->spurious_vec = 0xff;
+        (s->id ? 0 : MSR_IA32_APICBASE_BSP) | MSR_IA32_APICBASE_ENABLE;
 
+    /* XXX: mapping more APICs at the same memory location */
     if (apic_io_memory == 0) {
         /* NOTE: the APIC is directly connected to the CPU - it is not
            on the global memory bus. */
         apic_io_memory = cpu_register_io_memory(0, apic_mem_read, 
-                                                apic_mem_write, NULL);
-        cpu_register_physical_memory(s->apicbase & ~0xfff, 0x1000, apic_io_memory);
+                                                apic_mem_write, s);
+        cpu_register_physical_memory(s->apicbase & ~0xfff, 0x1000,
+                                     apic_io_memory);
     }
     s->timer = qemu_new_timer(vm_clock, apic_timer, s);
+
+    register_savevm("apic", 0, 1, apic_save, apic_load, s);
+    qemu_register_reset(apic_reset, s);
+
+    s->next_apic = first_local_apic;
+    first_local_apic = s;
+    
+    return 0;
+}
+
+static void ioapic_service(IOAPICState *s)
+{
+    uint8_t vector;
+    uint32_t mask;
+    uint64_t entry;
+    uint8_t dest;
+    uint8_t dest_mode;
+
+    for (vector = 0; vector < IOAPIC_NUM_PINS; vector++) {
+        mask = 1 << vector;
+        if (s->irr & mask) {
+            entry = s->ioredtbl[vector];
+            if (!(entry & APIC_LVT_MASKED)) {
+                if (!((entry >> 15) & 1))
+                    s->irr &= ~mask;
+                dest = entry >> 56;
+                dest_mode = (entry >> 11) & 1;
+                apic_bus_deliver(apic_get_delivery_bitmask(dest, dest_mode),
+                                 (entry >> 8) & 7, entry & 0xff,
+                                 (entry >> 13) & 1, (entry >> 15) & 1);
+            }
+        }
+    }
+}
+
+void ioapic_set_irq(uint32_t vector, int level)
+{
+    IOAPICState *s = ioapic_state;
+
+    if (!s)
+        return;
+
+    if (vector >= 0 && vector < IOAPIC_NUM_PINS) {        
+        uint32_t mask = 1 << vector;
+        uint64_t entry = s->ioredtbl[vector];
+
+        if ((entry >> 15) & 1) {
+            /* level triggered */
+            if (level) {
+                s->irr |= mask;
+                ioapic_service(s);
+            } else {
+                s->irr &= ~mask;
+            }
+        } else {
+            /* edge triggered */
+            if (level) {
+                s->irr |= mask;
+                ioapic_service(s);
+            }
+        }
+    }
+}
+
+static uint32_t ioapic_mem_readl(void *opaque, target_phys_addr_t addr)
+{
+    IOAPICState *s = opaque;
+    int index;
+    uint32_t val = 0;
+
+    addr &= 0xff;
+    if (addr == 0x00) {
+        val = s->ioregsel;
+    } else if (addr == 0x10) {
+        switch (s->ioregsel) {
+            case 0x00:
+                val = s->id << 24;
+                break;
+            case 0x01:
+                val = 0x11 | ((IOAPIC_NUM_PINS - 1) << 16); /* version 0x11 */
+                break;
+            case 0x02:
+                val = 0;
+                break;
+            default:
+                index = (s->ioregsel - 0x10) >> 1;
+                if (index >= 0 && index < IOAPIC_NUM_PINS) {
+                    if (s->ioregsel & 1)
+                        val = s->ioredtbl[index] >> 32;
+                    else
+                        val = s->ioredtbl[index] & 0xffffffff;
+                }
+        }
+#ifdef DEBUG_IOAPIC
+        printf("I/O APIC read: %08x = %08x\n", s->ioregsel, val);
+#endif
+    }
+    return val;
+}
+
+static void ioapic_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
+{
+    IOAPICState *s = opaque;
+    int index;
+
+    addr &= 0xff;
+    if (addr == 0x00)  {
+        s->ioregsel = val;
+        return;
+    } else if (addr == 0x10) {
+#ifdef DEBUG_IOAPIC
+        printf("I/O APIC write: %08x = %08x\n", s->ioregsel, val);
+#endif
+        switch (s->ioregsel) {
+            case 0x00:
+                s->id = (val >> 24) & 0xff;
+                return;
+            case 0x01:
+            case 0x02:
+                return;
+            default:
+                index = (s->ioregsel - 0x10) >> 1;
+                if (index >= 0 && index < IOAPIC_NUM_PINS) {
+                    if (s->ioregsel & 1) {
+                        s->ioredtbl[index] &= 0xffffffff;
+                        s->ioredtbl[index] |= (uint64_t)val << 32;
+                    } else {
+                        s->ioredtbl[index] &= ~0xffffffffULL;
+                        s->ioredtbl[index] |= val;
+                    }
+                    ioapic_service(s);
+                }
+        }
+    }
+}
+
+static void ioapic_save(QEMUFile *f, void *opaque)
+{
+    IOAPICState *s = opaque;
+    int i;
+
+    qemu_put_8s(f, &s->id);
+    qemu_put_8s(f, &s->ioregsel);
+    for (i = 0; i < IOAPIC_NUM_PINS; i++) {
+        qemu_put_be64s(f, &s->ioredtbl[i]);
+    }
+}
+
+static int ioapic_load(QEMUFile *f, void *opaque, int version_id)
+{
+    IOAPICState *s = opaque;
+    int i;
+
+    if (version_id != 1)
+        return -EINVAL;
+
+    qemu_get_8s(f, &s->id);
+    qemu_get_8s(f, &s->ioregsel);
+    for (i = 0; i < IOAPIC_NUM_PINS; i++) {
+        qemu_get_be64s(f, &s->ioredtbl[i]);
+    }
+    return 0;
+}
+
+static void ioapic_reset(void *opaque)
+{
+    IOAPICState *s = opaque;
+    int i;
+
+    memset(s, 0, sizeof(*s));
+    for(i = 0; i < IOAPIC_NUM_PINS; i++)
+        s->ioredtbl[i] = 1 << 16; /* mask LVT */
+}
+
+static CPUReadMemoryFunc *ioapic_mem_read[3] = {
+    ioapic_mem_readl,
+    ioapic_mem_readl,
+    ioapic_mem_readl,
+};
+
+static CPUWriteMemoryFunc *ioapic_mem_write[3] = {
+    ioapic_mem_writel,
+    ioapic_mem_writel,
+    ioapic_mem_writel,
+};
+
+int ioapic_init(void)
+{
+    IOAPICState *s;
+    int io_memory;
+
+    s = malloc(sizeof(IOAPICState));
+    if (!s)
+        return -1;
+    ioapic_state = s;
+    ioapic_reset(s);
+    s->id = last_apic_id++;
+
+    io_memory = cpu_register_io_memory(0, ioapic_mem_read, 
+                                       ioapic_mem_write, s);
+    cpu_register_physical_memory(0xfec00000, 0x1000, io_memory);
+
+    register_savevm("ioapic", 0, 1, ioapic_save, ioapic_load, s);
+    qemu_register_reset(ioapic_reset, s);
+    
     return 0;
 }
Index: hw/i8259.c
===================================================================
RCS file: /cvsroot/qemu/qemu/hw/i8259.c,v
retrieving revision 1.16
diff -u -r1.16 i8259.c
--- hw/i8259.c	2 Jul 2005 18:11:44 -0000	1.16
+++ hw/i8259.c	20 Jul 2005 09:37:07 -0000
@@ -186,6 +186,7 @@
     }
 #endif
     pic_set_irq1(&s->pics[irq >> 3], irq & 7, level);
+    ioapic_set_irq(irq, level);
     pic_update_irq(s);
 }
 
Index: hw/pc.c
===================================================================
RCS file: /cvsroot/qemu/qemu/hw/pc.c,v
retrieving revision 1.38
diff -u -r1.38 pc.c
--- hw/pc.c	3 Jul 2005 14:00:51 -0000	1.38
+++ hw/pc.c	20 Jul 2005 09:37:07 -0000
@@ -70,7 +70,6 @@
 {
     int intno;
 
-#ifdef TARGET_X86_64
     intno = apic_get_interrupt(env);
     if (intno >= 0) {
         /* set irq request if a PIC irq is still pending */
@@ -78,7 +77,6 @@
         pic_update_irq(isa_pic); 
         return intno;
     }
-#endif
     /* read the irq from the PIC */
     intno = pic_read_irq(isa_pic);
     return intno;
@@ -557,8 +555,10 @@
     register_ioport_read(0x92, 1, 1, ioport92_read, NULL);
     register_ioport_write(0x92, 1, 1, ioport92_write, NULL);
 
-    if (pci_enabled)
+    if (pci_enabled) {
         apic_init(cpu_single_env);
+        ioapic_init();
+    }
     isa_pic = pic_init(pic_irq_request, cpu_single_env);
     pit = pit_init(0x40, 0);
 

[-- Attachment #6: qemu-20050718-04-doc.patch --]
[-- Type: text/plain, Size: 689 bytes --]

Index: qemu-img.texi
===================================================================
RCS file: /cvsroot/qemu/qemu/qemu-img.texi,v
retrieving revision 1.1
diff -u -r1.1 qemu-img.texi
--- qemu-img.texi	15 Nov 2004 22:57:26 -0000	1.1
+++ qemu-img.texi	20 Jul 2005 09:37:07 -0000
@@ -44,8 +44,7 @@
 image format in QEMU. It is supported only for compatibility with
 previous versions. It does not work on win32.
 @item vmdk
-VMware 3 and 4 compatible image format. Currently only supported as
-read-only.
+VMware 3 and 4 compatible image format.
 @item cloop
 Linux Compressed Loop image, useful only to reuse directly compressed
 CD-ROM images present for example in the Knoppix CD-ROMs.

             reply	other threads:[~2005-07-21  6:51 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2005-07-21  6:40 Filip Navara [this message]
2005-07-21 10:36 ` [Qemu-devel] [patch] Various (mostly) x86-64 related patches Filip Navara
2005-07-23 14:34   ` Filip Navara

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=42DF4374.10703@reactos.com \
    --to=navaraf@reactos.com \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.