From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1DvUtq-0004gq-Km for qemu-devel@nongnu.org; Thu, 21 Jul 2005 02:51:19 -0400 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1DvUtR-0004Zc-4K for qemu-devel@nongnu.org; Thu, 21 Jul 2005 02:51:13 -0400 Received: from [199.232.76.173] (helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1DvUtP-0004Dp-6p for qemu-devel@nongnu.org; Thu, 21 Jul 2005 02:50:51 -0400 Received: from [195.250.128.83] (helo=smtp3.vol.cz) by monty-python.gnu.org with esmtp (Exim 4.34) id 1DvUtQ-0007bI-FU for qemu-devel@nongnu.org; Thu, 21 Jul 2005 02:50:53 -0400 Received: from [10.0.0.2] (prg-v-6-220.static.adsl.vol.cz [62.177.70.220]) by smtp3.vol.cz (Postfix) with ESMTP id 1E59559283 for ; Thu, 21 Jul 2005 08:40:50 +0200 (CEST) Message-ID: <42DF4374.10703@reactos.com> Date: Thu, 21 Jul 2005 08:40:52 +0200 From: Filip Navara MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="------------000906000006040809010905" Subject: [Qemu-devel] [patch] Various (mostly) x86-64 related patches Reply-To: qemu-devel@nongnu.org List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org This is a multi-part message in MIME format. --------------000906000006040809010905 Content-Type: text/plain; charset=ISO-8859-2; format=flowed Content-Transfer-Encoding: 7bit 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). --------------000906000006040809010905 Content-Type: text/plain; name="qemu-20050718-05-sdl.patch" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="qemu-20050718-05-sdl.patch" 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); --------------000906000006040809010905 Content-Type: text/plain; name="qemu-20050718-01-vaddr.patch" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="qemu-20050718-01-vaddr.patch" 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; --------------000906000006040809010905 Content-Type: text/plain; name="qemu-20050718-02-insns.patch" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="qemu-20050718-02-insns.patch" 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, ®_addr, &offset_addr); + /* ignore for now */ break; case 0x110 ... 0x117: case 0x128 ... 0x12f: --------------000906000006040809010905 Content-Type: text/plain; name="qemu-20050718-03-apic.patch" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="qemu-20050718-03-apic.patch" 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); --------------000906000006040809010905 Content-Type: text/plain; name="qemu-20050718-04-doc.patch" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="qemu-20050718-04-doc.patch" 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. --------------000906000006040809010905--