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, ®_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.
next 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.