You can subscribe to this list here.
2006 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
(33) |
Nov
(325) |
Dec
(320) |
---|---|---|---|---|---|---|---|---|---|---|---|---|
2007 |
Jan
(484) |
Feb
(438) |
Mar
(407) |
Apr
(713) |
May
(831) |
Jun
(806) |
Jul
(1023) |
Aug
(1184) |
Sep
(1118) |
Oct
(1461) |
Nov
(1224) |
Dec
(1042) |
2008 |
Jan
(1449) |
Feb
(1110) |
Mar
(1428) |
Apr
(1643) |
May
(682) |
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
From: Guillaume T. <gui...@ex...> - 2008-04-25 07:27:28
|
On Fri, 25 Apr 2008 09:51:04 +0300 Avi Kivity <av...@qu...> wrote: > > [60108.040894] emulation at (46e53) rip 6e13: ea 18 6e 18 > > > > Here cs.rpl == cpl == 0 > > > [60108.072108] emulation at (46e58) rip 6e18: 66 b8 20 00 > > [60108.103997] emulation at (46e5c) rip 6e1c: 8e d8 8c d0 > > [60108.148114] emulation at (46e5e) rip 6e1e: 8c d0 81 e4 > > [60108.180117] emulation at (46e60) rip 6e20: 81 e4 ff ff > > [60108.212008] emulation at (46e66) rip 6e26: c1 e0 04 01 > > [60108.244926] emulation at (46e69) rip 6e29: 01 c4 66 b8 > > [60108.272948] emulation at (46e6b) rip 6e2b: 66 b8 08 00 > > > > mov $8, %eax > > > [60108.304953] emulation at (46e6f) rip 6e2f: 8e d0 8e c0 > > > mov %eax, %ss > > Here, ss.rpl == 0 Yes, thus ss.rpl should be equal to cs.rpl (both equal to 0) and we should be in VMX friendly state. Mmmh, that means I made a mistake in the implementation of 0xb8 or 0x8e instruction. I'm investigating, thanks for your help. Best regards, Guillaume |
From: Avi K. <av...@qu...> - 2008-04-25 06:52:51
|
Guillaume Thouvenin wrote: > On Thu, 24 Apr 2008 11:05:39 -0500 > Anthony Liguori <an...@co...> wrote: > > >> The first stage is to detect vmentry failures and run x86_emulate() for >> a single instruction. If you look at the mailing list, you'll see >> patches from myself and Guillaume. This should be enough to allow most >> Ubuntu installer CDs to work under KVM. >> > > Howdy, > > Here is the last patch I have. It can detects a vmentry failure and it > emulates one instruction. I added the emulation of several instructions > like "ljmp", "mov Sreg, reg", "mov reg, Sreg"... The problem I'm > working on is that once I entered in emulation of real mode I do not > manage to recover a VMX friendly state (in my case cs.rpl == > ss.rpl). So I emulate more and more instructions. > > I added a trace to see instructions that are emulated (emulation of > 0xa8 is in progress so it currently fails): > > [60108.040894] emulation at (46e53) rip 6e13: ea 18 6e 18 > Here cs.rpl == cpl == 0 > [60108.072108] emulation at (46e58) rip 6e18: 66 b8 20 00 > [60108.103997] emulation at (46e5c) rip 6e1c: 8e d8 8c d0 > [60108.148114] emulation at (46e5e) rip 6e1e: 8c d0 81 e4 > [60108.180117] emulation at (46e60) rip 6e20: 81 e4 ff ff > [60108.212008] emulation at (46e66) rip 6e26: c1 e0 04 01 > [60108.244926] emulation at (46e69) rip 6e29: 01 c4 66 b8 > [60108.272948] emulation at (46e6b) rip 6e2b: 66 b8 08 00 > mov $8, %eax > [60108.304953] emulation at (46e6f) rip 6e2f: 8e d0 8e c0 > mov %eax, %ss Here, ss.rpl == 0 -- Do not meddle in the internals of kernels, for they are subtle and quick to panic. |
From: Guillaume T. <gui...@ex...> - 2008-04-25 06:08:56
|
On Thu, 24 Apr 2008 11:05:39 -0500 Anthony Liguori <an...@co...> wrote: > The first stage is to detect vmentry failures and run x86_emulate() for > a single instruction. If you look at the mailing list, you'll see > patches from myself and Guillaume. This should be enough to allow most > Ubuntu installer CDs to work under KVM. Howdy, Here is the last patch I have. It can detects a vmentry failure and it emulates one instruction. I added the emulation of several instructions like "ljmp", "mov Sreg, reg", "mov reg, Sreg"... The problem I'm working on is that once I entered in emulation of real mode I do not manage to recover a VMX friendly state (in my case cs.rpl == ss.rpl). So I emulate more and more instructions. I added a trace to see instructions that are emulated (emulation of 0xa8 is in progress so it currently fails): [60108.040894] emulation at (46e53) rip 6e13: ea 18 6e 18 [60108.072108] emulation at (46e58) rip 6e18: 66 b8 20 00 [60108.103997] emulation at (46e5c) rip 6e1c: 8e d8 8c d0 [60108.148114] emulation at (46e5e) rip 6e1e: 8c d0 81 e4 [60108.180117] emulation at (46e60) rip 6e20: 81 e4 ff ff [60108.212008] emulation at (46e66) rip 6e26: c1 e0 04 01 [60108.244926] emulation at (46e69) rip 6e29: 01 c4 66 b8 [60108.272948] emulation at (46e6b) rip 6e2b: 66 b8 08 00 [60108.304953] emulation at (46e6f) rip 6e2f: 8e d0 8e c0 [60108.348973] emulation at (46e71) rip 6e31: 8e c0 8e e0 [60108.396965] emulation at (46e73) rip 6e33: 8e e0 8e e8 [60108.445002] emulation at (46e75) rip 6e35: 8e e8 58 66 [60108.489021] emulation at (46e77) rip 6e37: 58 66 9d 66 [60108.521028] emulation at (46e78) rip 6e38: 66 9d 66 c3 [60108.552979] emulation at (46e7a) rip 6e3a: 66 c3 66 9c [60108.581048] emulation at (40e2a) rip dea: be 29 0a 00 [60108.613033] emulation at (40e2f) rip def: e8 41 12 00 [60108.644970] emulation at (42075) rip 2035: c6 05 84 07 [60108.673038] emulation at (4207c) rip 203c: e8 18 01 00 [60108.705039] emulation at (42199) rip 2159: 31 c0 80 3d [60108.736998] emulation at (4219b) rip 215b: 80 3d 86 07 [60108.765041] emulation at (421a2) rip 2162: 74 01 26 ac [60108.797044] emulation at (421a5) rip 2165: ac c3 80 3d [60108.829033] emulation at (421a6) rip 2166: c3 80 3d 86 [60108.857068] emulation at (42081) rip 2041: 09 c0 0f 84 [60108.889053] emulation at (42083) rip 2043: 0f 84 0f 01 [60108.921054] emulation at (42198) rip 2158: c3 31 c0 80 [60108.949076] emulation at (40e34) rip df4: 26 66 ff 35 [60108.981077] emulation at (40e3c) rip dfc: 66 8f 05 d0 [60109.013011] emulation at (40e43) rip e03: a1 b4 00 00 [60109.041079] emulation at (40e48) rip e08: 26 8a 40 03 [60109.073039] emulation at (40e4c) rip e0c: a8 01 74 4c [60109.101078] emulation failed (vmentry failure) rip e0c a8 01 74 4c So as we can see the first emulated instruction is the ljump and after we emulate gfxboot loader instruction. I suspect a problem with an update of SS segment or something like that in instructions that I emulate. I paste the patch. Don't worry about the last modification of the two header files it's not related to real mode emulation. Regards, Guillaume --- diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index 8e5d664..2c4c14d 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c @@ -1183,7 +1183,9 @@ static void enter_pmode(struct kvm_vcpu *vcpu) fix_pmode_dataseg(VCPU_SREG_GS, &vcpu->arch.rmode.gs); fix_pmode_dataseg(VCPU_SREG_FS, &vcpu->arch.rmode.fs); +#if 0 vmcs_write16(GUEST_SS_SELECTOR, 0); +#endif vmcs_write32(GUEST_SS_AR_BYTES, 0x93); vmcs_write16(GUEST_CS_SELECTOR, @@ -2323,6 +2325,53 @@ static int handle_task_switch(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) return kvm_task_switch(vcpu, tss_selector, reason); } +static int handle_vmentry_failure(struct kvm_vcpu *vcpu, + struct kvm_run *kvm_run, u32 failure_reason) +{ + u16 ss, cs; + u8 opcodes[4]; + unsigned long rip = vcpu->arch.rip; + unsigned long rip_linear; + + ss = vmcs_read16(GUEST_SS_SELECTOR); + cs = vmcs_read16(GUEST_CS_SELECTOR); + + if ((ss & 0x03) != (cs & 0x03)) { + int err; + +#if 0 + printk(KERN_INFO "vmentry failure because ss.cpl != cs.cpl\n"); +#endif + rip_linear = rip + vmx_get_segment_base(vcpu, VCPU_SREG_CS); + emulator_read_std(rip_linear, (void *)opcodes, 4, vcpu); + printk(KERN_INFO "emulation at (%lx) rip %lx: %02x %02x %02x %02x\n", + rip_linear, + rip, opcodes[0], opcodes[1], opcodes[2], opcodes[3]); + err = emulate_instruction(vcpu, kvm_run, 0, 0, 0); + switch (err) { + case EMULATE_DONE: +#if 0 + printk(KERN_INFO "successfully emulated instruction\n"); +#endif + return 1; + case EMULATE_DO_MMIO: + printk(KERN_INFO "mmio?\n"); + return 0; +#if 0 + case EMULATE_FAIL: +#endif + default: + kvm_report_emulation_failure(vcpu, "vmentry failure"); + break; + } + } + + kvm_run->exit_reason = KVM_EXIT_UNKNOWN; + kvm_run->hw.hardware_exit_reason = failure_reason; + + return 0; +} + /* * The exit handlers return 1 if the exit was handled fully and guest execution * may resume. Otherwise they set the kvm_run parameter to indicate what needs @@ -2375,6 +2424,12 @@ static int kvm_handle_exit(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu) exit_reason != EXIT_REASON_EXCEPTION_NMI) printk(KERN_WARNING "%s: unexpected, valid vectoring info and " "exit reason is 0x%x\n", __func__, exit_reason); + + if ((exit_reason & VMX_EXIT_REASONS_FAILED_VMENTRY)) { + exit_reason &= ~VMX_EXIT_REASONS_FAILED_VMENTRY; + return handle_vmentry_failure(vcpu, kvm_run, exit_reason); + } + if (exit_reason < kvm_vmx_max_exit_handlers && kvm_vmx_exit_handlers[exit_reason]) return kvm_vmx_exit_handlers[exit_reason](vcpu, kvm_run); diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 0ce5563..f394efd 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -3267,8 +3267,8 @@ static int load_segment_descriptor_to_kvm_desct(struct kvm_vcpu *vcpu, return 0; } -static int load_segment_descriptor(struct kvm_vcpu *vcpu, u16 selector, - int type_bits, int seg) +int load_segment_descriptor(struct kvm_vcpu *vcpu, u16 selector, + int type_bits, int seg) { struct kvm_segment kvm_seg; diff --git a/arch/x86/kvm/x86_emulate.c b/arch/x86/kvm/x86_emulate.c index 2ca0838..287811c 100644 --- a/arch/x86/kvm/x86_emulate.c +++ b/arch/x86/kvm/x86_emulate.c @@ -138,7 +138,8 @@ static u16 opcode_table[256] = { /* 0x88 - 0x8F */ ByteOp | DstMem | SrcReg | ModRM | Mov, DstMem | SrcReg | ModRM | Mov, ByteOp | DstReg | SrcMem | ModRM | Mov, DstReg | SrcMem | ModRM | Mov, - 0, ModRM | DstReg, 0, Group | Group1A, + DstMem | SrcReg | ModRM | Mov, ModRM | DstReg, DstReg |SrcMem |ModRM | Mov, + Group | Group1A, /* 0x90 - 0x9F */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ImplicitOps | Stack, ImplicitOps | Stack, 0, 0, @@ -148,11 +149,16 @@ static u16 opcode_table[256] = { ByteOp | ImplicitOps | Mov | String, ImplicitOps | Mov | String, ByteOp | ImplicitOps | String, ImplicitOps | String, /* 0xA8 - 0xAF */ - 0, 0, ByteOp | ImplicitOps | Mov | String, ImplicitOps | Mov | String, + 0, 0, ByteOp | ImplicitOps | Mov | String, + ImplicitOps | Mov | String, ByteOp | ImplicitOps | Mov | String, ImplicitOps | Mov | String, ByteOp | ImplicitOps | String, ImplicitOps | String, - /* 0xB0 - 0xBF */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + /* 0xB0 - 0xB7 */ + Mov | SrcImmByte, Mov | SrcImmByte, Mov | SrcImmByte, Mov | SrcImmByte, + Mov | SrcImmByte, Mov | SrcImmByte, Mov | SrcImmByte, Mov | SrcImmByte, + /* 0xB8 - 0xBF */ + Mov | SrcImm, Mov | SrcImm, Mov | SrcImm, Mov | SrcImm, + Mov | SrcImm, Mov | SrcImm, Mov | SrcImm, Mov | SrcImm, /* 0xC0 - 0xC7 */ ByteOp | DstMem | SrcImm | ModRM, DstMem | SrcImmByte | ModRM, 0, ImplicitOps | Stack, 0, 0, @@ -168,7 +174,7 @@ static u16 opcode_table[256] = { /* 0xE0 - 0xE7 */ 0, 0, 0, 0, 0, 0, 0, 0, /* 0xE8 - 0xEF */ - ImplicitOps | Stack, SrcImm|ImplicitOps, 0, SrcImmByte|ImplicitOps, + ImplicitOps | Stack, SrcImm|ImplicitOps, ImplicitOps, SrcImmByte|ImplicitOps, 0, 0, 0, 0, /* 0xF0 - 0xF7 */ 0, 0, 0, 0, @@ -215,7 +221,7 @@ static u16 twobyte_table[256] = { /* 0xA0 - 0xA7 */ 0, 0, 0, DstMem | SrcReg | ModRM | BitOp, 0, 0, 0, 0, /* 0xA8 - 0xAF */ - 0, 0, 0, DstMem | SrcReg | ModRM | BitOp, 0, 0, 0, 0, + ImplicitOps, 0, 0, DstMem | SrcReg | ModRM | BitOp, 0, 0, 0, 0, /* 0xB0 - 0xB7 */ ByteOp | DstMem | SrcReg | ModRM, DstMem | SrcReg | ModRM, 0, DstMem | SrcReg | ModRM | BitOp, @@ -680,7 +686,7 @@ static int decode_modrm(struct x86_emulate_ctxt *ctxt, c->modrm_val = *(unsigned long *) decode_register(c->modrm_rm, c->regs, c->d & ByteOp); return rc; - } + } if (c->ad_bytes == 2) { unsigned bx = c->regs[VCPU_REGS_RBX]; @@ -1483,6 +1489,9 @@ special_insn: goto cmp; } break; + case 0xa8: /* test imm,%%eax */ + c->dst.ptr = &c->regs[VCPU_REGS_RAX]; + c->dst.val = c->regs[VCPU_REGS_RAX]; case 0x84 ... 0x85: emulate_2op_SrcV("test", c->src, c->dst, ctxt->eflags); break; @@ -1511,9 +1520,95 @@ special_insn: break; case 0x88 ... 0x8b: /* mov */ goto mov; + case 0x8c: { /* mov Sreg, r/m */ + struct kvm_save_segment *segreg; + + if (c->modrm_mod == 0x3) + c->src.val = c->modrm_val; + + switch ( c->modrm_reg ) { + case 0: + segreg = &ctxt->vcpu->arch.rmode.es; + break; + case 1: + segreg = &ctxt->vcpu->arch.rmode.cs; + break; + case 2: + segreg = &ctxt->vcpu->arch.rmode.ss; + break; + case 3: + segreg = &ctxt->vcpu->arch.rmode.ds; + break; + case 4: + segreg = &ctxt->vcpu->arch.rmode.fs; + break; + case 5: + segreg = &ctxt->vcpu->arch.rmode.gs; + break; + default: + printk(KERN_INFO "Invalid segreg in modrm byte 0x%02x\n", + c->modrm); + goto cannot_emulate; + } + c->dst.val = segreg->selector; + if (c->dst.type == OP_MEM) + c->dst.bytes = 2; + + break; + } case 0x8d: /* lea r16/r32, m */ c->dst.val = c->modrm_ea; break; + case 0x8e: { /* mov seg, r/m16 */ + struct kvm_save_segment *segreg; + int ar_type; + + if (c->modrm_mod == 0x3) + c->src.val = c->modrm_val; + + switch ( c->modrm_reg ) { + case 0: + segreg = &ctxt->vcpu->arch.rmode.es; + ar_type = 0x3; + printk(KERN_INFO "es_base = %lx\n", c->src.val * 0x10); + break; + case 1: + segreg = &ctxt->vcpu->arch.rmode.cs; + ar_type = 0xb; + printk(KERN_INFO "cs_base = %lx\n", c->src.val * 0x10); + break; + case 2: + segreg = &ctxt->vcpu->arch.rmode.ss; + ar_type = 0x3; + printk(KERN_INFO "ss_base = %lx\n", c->src.val * 0x10); + break; + case 3: + segreg = &ctxt->vcpu->arch.rmode.ds; + ar_type = 0x3; + printk(KERN_INFO "ds_base = %lx\n", c->src.val * 0x10); + break; + case 4: + segreg = &ctxt->vcpu->arch.rmode.fs; + ar_type = 0x3; + printk(KERN_INFO "fs_base = %lx\n", c->src.val * 0x10); + break; + case 5: + segreg = &ctxt->vcpu->arch.rmode.gs; + ar_type = 0x3; + printk(KERN_INFO "gs_base = %lx\n", c->src.val * 0x10); + break; + default: + printk(KERN_INFO "Invalid segreg in modrm byte 0x%02x\n", c->modrm); + goto cannot_emulate; + } + segreg->selector = c->src.val; + segreg->base = (u64) c->src.val << 4; + segreg->limit = 0xffff; + segreg->ar = ar_type; + + c->dst.type = OP_NONE; /* Disable writeback. */ + break; + } case 0x8f: /* pop (sole member of Grp1a) */ rc = emulate_grp1a(ctxt, ops); if (rc != 0) @@ -1619,6 +1714,23 @@ special_insn: case 0xae ... 0xaf: /* scas */ DPRINTF("Urk! I don't handle SCAS.\n"); goto cannot_emulate; + case 0xb0 ... 0xb3: /* mov rl, imm8 */ + c->dst.ptr = (unsigned long *)&c->regs[VCPU_REGS_RAX + (c->b & 0x3)]; + c->dst.val = c->src.val; + c->dst.type = OP_REG; + c->dst.bytes = 1; + break; + case 0xb4 ... 0xb7: /* mov rh, imm8 */ + c->dst.ptr = ((void *)&c->regs[VCPU_REGS_RAX + (c->b & 0x3)] + 1); + c->dst.val = c->src.val; + c->dst.type = OP_REG; + c->dst.bytes = 1; + break; + case 0xb8 ... 0xbf: /* mov r, imm */ + c->dst.ptr = (unsigned long *)&c->regs[VCPU_REGS_RAX + (c->b & 0x7)]; + c->dst.val = c->src.val; + c->dst.type = OP_REG; + break; case 0xc0 ... 0xc1: emulate_grp2(ctxt); break; @@ -1661,6 +1773,31 @@ special_insn: jmp_rel(c, c->src.val); c->dst.type = OP_NONE; /* Disable writeback. */ break; + case 0xea: /* jmp (far, absolute) */ { + uint32_t eip; + uint16_t sel; + + switch (c->op_bytes) { + case 2: + eip = insn_fetch(u16, 2, c->eip); + eip = eip & 0x0000FFFF; /* clear upper 16 bits */ + break; + case 4: + eip = insn_fetch(u32, 4, c->eip); + break; + default: + DPRINTF("Jmp far: Invalid op_bytes\n"); + goto cannot_emulate; + } + sel = insn_fetch(u16, 2, c->eip); + if (load_segment_descriptor(ctxt->vcpu, sel, 9, VCPU_SREG_CS) < 0) { + DPRINTF("Jmp far: Cannot load CS segment descriptor\n"); + goto cannot_emulate; + } + + c->eip = eip; + break; + } case 0xf4: /* hlt */ ctxt->vcpu->arch.halt_request = 1; goto done; diff --git a/include/asm-x86/kvm_host.h b/include/asm-x86/kvm_host.h index 9d963cd..24c8bf9 100644 --- a/include/asm-x86/kvm_host.h +++ b/include/asm-x86/kvm_host.h @@ -271,7 +271,7 @@ struct kvm_vcpu_arch { unsigned long base; u32 limit; u32 ar; - } tr, es, ds, fs, gs; + } tr, cs, es, ds, fs, gs, ss; } rmode; int halt_request; /* real mode on Intel only */ @@ -488,6 +488,8 @@ int emulator_get_dr(struct x86_emulate_ctxt *ctxt, int dr, int emulator_set_dr(struct x86_emulate_ctxt *ctxt, int dr, unsigned long value); +int load_segment_descriptor(struct kvm_vcpu *vcpu, u16 selector, + int type_bits, int seg); int kvm_task_switch(struct kvm_vcpu *vcpu, u16 tss_selector, int reason); void kvm_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0); diff --git a/include/asm-x86/posix_types.h b/include/asm-x86/posix_types.h index fe312a5..0c8329e 100644 --- a/include/asm-x86/posix_types.h +++ b/include/asm-x86/posix_types.h @@ -1,7 +1,13 @@ #ifdef __KERNEL__ -# if defined(CONFIG_X86_32) || defined(__i386__) +# ifdef CONFIG_X86_32 # include "posix_types_32.h" # else # include "posix_types_64.h" -# endif +# endif +#else +# ifdef __i386__ +# include "posix_types_32.h" +# else +# include "posix_types_64.h" +# endif #endif diff --git a/include/asm-x86/unistd.h b/include/asm-x86/unistd.h index effc7ad..1dea24a 100644 --- a/include/asm-x86/unistd.h +++ b/include/asm-x86/unistd.h @@ -1,7 +1,13 @@ #ifdef __KERNEL__ -# if defined(CONFIG_X86_32) || defined(__i386__) +# ifdef CONFIG_X86_32 # include "unistd_32.h" # else # include "unistd_64.h" -# endif +# endif +#else +# ifdef __i386__ +# include "unistd_32.h" +# else +# include "unistd_64.h" +# endif #endif |
From: Jerone Y. <jy...@us...> - 2008-04-25 05:58:27
|
2 files changed, 7 insertions(+), 3 deletions(-) arch/powerpc/kvm/emulate.c | 5 +++++ arch/powerpc/kvm/powerpc.c | 5 ++--- This patch handles a guest that is in a wait state. This ensures that the guest is not allways eating up 100% cpu when it is idle. Signed-off-by: Jerone Young <jy...@us...> diff --git a/arch/powerpc/kvm/emulate.c b/arch/powerpc/kvm/emulate.c --- a/arch/powerpc/kvm/emulate.c +++ b/arch/powerpc/kvm/emulate.c @@ -265,6 +265,11 @@ int kvmppc_emulate_instruction(struct kv case 146: /* mtmsr */ rs = get_rs(inst); kvmppc_set_msr(vcpu, vcpu->arch.gpr[rs]); + + /* handle guest vcpu that is in wait state */ + if (vcpu->arch.msr & MSR_WE) { + kvm_vcpu_block(vcpu); + } break; case 163: /* wrteei */ diff --git a/arch/powerpc/kvm/powerpc.c b/arch/powerpc/kvm/powerpc.c --- a/arch/powerpc/kvm/powerpc.c +++ b/arch/powerpc/kvm/powerpc.c @@ -36,13 +36,12 @@ gfn_t unalias_gfn(struct kvm *kvm, gfn_t int kvm_cpu_has_interrupt(struct kvm_vcpu *v) { - /* XXX implement me */ - return 0; + return !!(v->arch.pending_exceptions); } int kvm_arch_vcpu_runnable(struct kvm_vcpu *v) { - return 1; + return !(v->arch.msr & MSR_WE); } |
From: Jerone Y. <jy...@us...> - 2008-04-25 05:58:27
|
2 files changed, 68 insertions(+), 1 deletion(-) arch/powerpc/platforms/44x/Makefile | 2 - arch/powerpc/platforms/44x/idle.c | 67 +++++++++++++++++++++++++++++++++++ This patch has been accepted upstream and will be in 2.6.26. So it will eventually need to be removed when we move to 2.6.26rc. This patch adds the ability for the CPU to go into wait state while in cpu_idle loop. This helps virtulization solutions know when the guest Linux kernel is in an idle state. There are two ways to do it. Command line options: idle=spin <-- CPU will spin By default will go into wait mode. Signed-off-by: Jerone Young <jy...@us...> diff --git a/arch/powerpc/platforms/44x/Makefile b/arch/powerpc/platforms/44x/Makefile --- a/arch/powerpc/platforms/44x/Makefile +++ b/arch/powerpc/platforms/44x/Makefile @@ -1,4 +1,4 @@ obj-$(CONFIG_44x) := misc_44x.o -obj-$(CONFIG_44x) := misc_44x.o +obj-$(CONFIG_44x) := misc_44x.o idle.o obj-$(CONFIG_EBONY) += ebony.o obj-$(CONFIG_TAISHAN) += taishan.o obj-$(CONFIG_BAMBOO) += bamboo.o diff --git a/arch/powerpc/platforms/44x/idle.c b/arch/powerpc/platforms/44x/idle.c new file mode 100644 --- /dev/null +++ b/arch/powerpc/platforms/44x/idle.c @@ -0,0 +1,67 @@ +/* + * Copyright 2008 IBM Corp. + * + * Based on arch/powerpc/platforms/pasemi/idle.c: + * Copyright (C) 2006-2007 PA Semi, Inc + * + * Added by: Jerone Young <jy...@us...> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include <linux/of.h> +#include <linux/kernel.h> +#include <asm/machdep.h> + +static int mode_spin; + +static void ppc44x_idle(void) +{ + unsigned long msr_save; + + msr_save = mfmsr(); + /* set wait state MSR */ + mtmsr(msr_save|MSR_WE|MSR_EE|MSR_CE|MSR_DE); + isync(); + /* return to initial state */ + mtmsr(msr_save); + isync(); +} + +int __init ppc44x_idle_init(void) +{ + if (!mode_spin) { + /* If we are not setting spin mode + then we set to wait mode */ + ppc_md.power_save = &ppc44x_idle; + } + + return 0; +} + +arch_initcall(ppc44x_idle_init); + +static int __init idle_param(char *p) +{ + + if (!strcmp("spin", p)) { + mode_spin = 1; + ppc_md.power_save = NULL; + } + + return 0; +} + +early_param("idle", idle_param); |
From: Jerone Y. <jy...@us...> - 2008-04-25 05:57:36
|
This set of patches fixes 100% CPU usage when a guest is idle on PowerPC. This ti me it uses common kvm functions to sleep the guest. Signed-off-by: Jerone Young <jy...@us...> 5 files changed, 91 insertions(+), 4 deletions(-) arch/powerpc/kvm/booke_guest.c | 6 +++ arch/powerpc/kvm/emulate.c | 5 ++ arch/powerpc/kvm/powerpc.c | 15 ++++++- arch/powerpc/platforms/44x/Makefile | 2 - arch/powerpc/platforms/44x/idle.c | 67 +++++++++++++++++++++++++++++++++++ |
From: Jerone Y. <jy...@us...> - 2008-04-25 05:57:35
|
2 files changed, 16 insertions(+) arch/powerpc/kvm/booke_guest.c | 6 ++++++ arch/powerpc/kvm/powerpc.c | 10 ++++++++++ This patch adds vcpu_put & vpu_load in strategic places (as x86 does it), for use of premption. This patch also adds a very critial bit need to wake up guest that end up going to being rescheduled and go to sleep. Signed-off-by: Jerone Young <jy...@us...> diff --git a/arch/powerpc/kvm/booke_guest.c b/arch/powerpc/kvm/booke_guest.c --- a/arch/powerpc/kvm/booke_guest.c +++ b/arch/powerpc/kvm/booke_guest.c @@ -514,6 +514,8 @@ int kvm_arch_vcpu_ioctl_get_regs(struct { int i; + vcpu_load(vcpu); + regs->pc = vcpu->arch.pc; regs->cr = vcpu->arch.cr; regs->ctr = vcpu->arch.ctr; @@ -533,6 +535,8 @@ int kvm_arch_vcpu_ioctl_get_regs(struct for (i = 0; i < ARRAY_SIZE(regs->gpr); i++) regs->gpr[i] = vcpu->arch.gpr[i]; + + vcpu_put(vcpu); return 0; } @@ -595,6 +599,7 @@ int kvm_arch_vcpu_ioctl_translate(struct u8 pid; u8 as; + vcpu_load(vcpu); eaddr = tr->linear_address; pid = (tr->linear_address >> 32) & 0xff; as = (tr->linear_address >> 40) & 0x1; @@ -610,6 +615,7 @@ int kvm_arch_vcpu_ioctl_translate(struct tr->physical_address = tlb_xlate(gtlbe, eaddr); /* XXX what does "writeable" and "usermode" even mean? */ tr->valid = 1; + vcpu_put(vcpu); return 0; } diff --git a/arch/powerpc/kvm/powerpc.c b/arch/powerpc/kvm/powerpc.c --- a/arch/powerpc/kvm/powerpc.c +++ b/arch/powerpc/kvm/powerpc.c @@ -212,6 +212,9 @@ static void kvmppc_decrementer_func(unsi { struct kvm_vcpu *vcpu = (struct kvm_vcpu *)data; + if (waitqueue_active(&vcpu->wq)) + wake_up_interruptible(&vcpu->wq); + kvmppc_queue_exception(vcpu, BOOKE_INTERRUPT_DECREMENTER); } @@ -338,6 +341,8 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_v int r; sigset_t sigsaved; + vcpu_load(vcpu); + if (vcpu->sigset_active) sigprocmask(SIG_SETMASK, &vcpu->sigset, &sigsaved); @@ -362,12 +367,17 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_v if (vcpu->sigset_active) sigprocmask(SIG_SETMASK, &sigsaved, NULL); + vcpu_put(vcpu); + return r; } int kvm_vcpu_ioctl_interrupt(struct kvm_vcpu *vcpu, struct kvm_interrupt *irq) { + vcpu_load(vcpu); kvmppc_queue_exception(vcpu, BOOKE_INTERRUPT_EXTERNAL); + vcpu_put(vcpu); + return 0; } |
From: Glauber C. <gc...@re...> - 2008-04-25 03:28:58
|
As the current state of matters, all architectures call a function with the same name and signature for updating the pc. Remove the ifdefs, leading to a cleaner code --- translate-all.c | 19 +------------------ 1 files changed, 1 insertions(+), 18 deletions(-) diff --git a/translate-all.c b/translate-all.c index 3afb656..83056d5 100644 --- a/translate-all.c +++ b/translate-all.c @@ -193,25 +193,8 @@ int cpu_restore_state(TranslationBlock *tb, /* now find start of instruction before */ while (gen_opc_instr_start[j] == 0) j--; -#if defined(TARGET_I386) + gen_pc_load(env, tb, searched_pc, j, puc); -#elif defined(TARGET_ARM) - gen_pc_load(env, tb, searched_pc, j, puc); -#elif defined(TARGET_SPARC) - gen_pc_load(env, tb, searched_pc, j, puc); -#elif defined(TARGET_PPC) - gen_pc_load(env, tb, searched_pc, j, puc); -#elif defined(TARGET_M68K) - gen_pc_load(env, tb, searched_pc, j, puc); -#elif defined(TARGET_MIPS) - gen_pc_load(env, tb, searched_pc, j, puc); -#elif defined(TARGET_ALPHA) - gen_pc_load(env, tb, searched_pc, j, puc); -#elif defined(TARGET_SH4) - gen_pc_load(env, tb, searched_pc, j, puc); -#elif defined(TARGET_CRIS) - gen_pc_load(env, tb, searched_pc, j, puc); -#endif #ifdef CONFIG_PROFILER dyngen_restore_time += profile_getclock() - ti; -- 1.5.0.6 |
From: Glauber C. <gc...@re...> - 2008-04-25 03:28:53
|
this patch replaced code inside specific ifdef in translate-all.c with a generic architecture-implemented function. This leads to a cleaner and more modular code in the generic part. --- target-cris/translate.c | 6 ++++++ translate-all.c | 2 +- 2 files changed, 7 insertions(+), 1 deletions(-) diff --git a/target-cris/translate.c b/target-cris/translate.c index 5769175..e522678 100644 --- a/target-cris/translate.c +++ b/target-cris/translate.c @@ -2701,3 +2701,9 @@ void cpu_reset (CPUCRISState *env) memset(env, 0, offsetof(CPUCRISState, breakpoints)); tlb_flush(env, 1); } + +void gen_pc_load(CPUState *env, struct TranslationBlock *tb, + unsigned long searched_pc, int pc_pos, void *puc) +{ + env->pregs[PR_ERP] = gen_opc_pc[pc_pos]; +} diff --git a/translate-all.c b/translate-all.c index 401969c..3afb656 100644 --- a/translate-all.c +++ b/translate-all.c @@ -210,7 +210,7 @@ int cpu_restore_state(TranslationBlock *tb, #elif defined(TARGET_SH4) gen_pc_load(env, tb, searched_pc, j, puc); #elif defined(TARGET_CRIS) - env->pregs[PR_ERP] = gen_opc_pc[j]; + gen_pc_load(env, tb, searched_pc, j, puc); #endif #ifdef CONFIG_PROFILER -- 1.5.0.6 |
From: Glauber C. <gc...@re...> - 2008-04-25 03:28:51
|
this patch replaced code inside specific ifdef in translate-all.c with a generic architecture-implemented function. This leads to a cleaner and more modular code in the generic part. --- target-sh4/translate.c | 7 +++++++ translate-all.c | 3 +-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/target-sh4/translate.c b/target-sh4/translate.c index b7c5f8d..1468e7a 100644 --- a/target-sh4/translate.c +++ b/target-sh4/translate.c @@ -1302,3 +1302,10 @@ int gen_intermediate_code_pc(CPUState * env, struct TranslationBlock *tb) { return gen_intermediate_code_internal(env, tb, 1); } + +void gen_pc_load(CPUState *env, TranslationBlock *tb, + unsigned long searched_pc, int pc_pos, void *puc) +{ + env->pc = gen_opc_pc[pc_pos]; + env->flags = gen_opc_hflags[pc_pos]; +} diff --git a/translate-all.c b/translate-all.c index bcad1f4..401969c 100644 --- a/translate-all.c +++ b/translate-all.c @@ -208,8 +208,7 @@ int cpu_restore_state(TranslationBlock *tb, #elif defined(TARGET_ALPHA) gen_pc_load(env, tb, searched_pc, j, puc); #elif defined(TARGET_SH4) - env->pc = gen_opc_pc[j]; - env->flags = gen_opc_hflags[j]; + gen_pc_load(env, tb, searched_pc, j, puc); #elif defined(TARGET_CRIS) env->pregs[PR_ERP] = gen_opc_pc[j]; #endif -- 1.5.0.6 |
From: Glauber C. <gc...@re...> - 2008-04-25 03:28:47
|
this patch replaced code inside specific ifdef in translate-all.c with a generic architecture-implemented function. This leads to a cleaner and more modular code in the generic part. --- target-alpha/translate.c | 5 +++++ translate-all.c | 2 +- 2 files changed, 6 insertions(+), 1 deletions(-) diff --git a/target-alpha/translate.c b/target-alpha/translate.c index 1c8587d..c7bb207 100644 --- a/target-alpha/translate.c +++ b/target-alpha/translate.c @@ -2108,3 +2108,8 @@ CPUAlphaState * cpu_alpha_init (const char *cpu_model) return env; } +void gen_pc_load(CPUState *env, TranslationBlock *tb, + unsigned long searched_pc, int pc_pos, void *puc) +{ + env->pc = gen_opc_pc[pc_pos]; +} diff --git a/translate-all.c b/translate-all.c index d2408f6..bcad1f4 100644 --- a/translate-all.c +++ b/translate-all.c @@ -206,7 +206,7 @@ int cpu_restore_state(TranslationBlock *tb, #elif defined(TARGET_MIPS) gen_pc_load(env, tb, searched_pc, j, puc); #elif defined(TARGET_ALPHA) - env->pc = gen_opc_pc[j]; + gen_pc_load(env, tb, searched_pc, j, puc); #elif defined(TARGET_SH4) env->pc = gen_opc_pc[j]; env->flags = gen_opc_hflags[j]; -- 1.5.0.6 |
From: Glauber C. <gc...@re...> - 2008-04-25 03:28:43
|
this patch replaced code inside specific ifdef in translate-all.c with a generic architecture-implemented function. This leads to a cleaner and more modular code in the generic part. --- target-mips/translate.c | 8 ++++++++ translate-all.c | 4 +--- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/target-mips/translate.c b/target-mips/translate.c index 65f0ba9..46b917e 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -6942,3 +6942,11 @@ void cpu_reset (CPUMIPSState *env) #endif cpu_mips_register(env, env->cpu_model); } + +void gen_pc_load(CPUState *env, TranslationBlock *tb, + unsigned long searched_pc, int pc_pos, void *puc) +{ + env->PC[env->current_tc] = gen_opc_pc[pc_pos]; + env->hflags &= ~MIPS_HFLAG_BMASK; + env->hflags |= gen_opc_hflags[pc_pos]; +} diff --git a/translate-all.c b/translate-all.c index 5e63978..d2408f6 100644 --- a/translate-all.c +++ b/translate-all.c @@ -204,9 +204,7 @@ int cpu_restore_state(TranslationBlock *tb, #elif defined(TARGET_M68K) gen_pc_load(env, tb, searched_pc, j, puc); #elif defined(TARGET_MIPS) - env->PC[env->current_tc] = gen_opc_pc[j]; - env->hflags &= ~MIPS_HFLAG_BMASK; - env->hflags |= gen_opc_hflags[j]; + gen_pc_load(env, tb, searched_pc, j, puc); #elif defined(TARGET_ALPHA) env->pc = gen_opc_pc[j]; #elif defined(TARGET_SH4) -- 1.5.0.6 |
From: Glauber C. <gc...@re...> - 2008-04-25 03:28:43
|
this patch replaced code inside specific ifdef in translate-all.c with a generic architecture-implemented function. This leads to a cleaner and more modular code in the generic part. --- target-m68k/translate.c | 5 +++++ translate-all.c | 2 +- 2 files changed, 6 insertions(+), 1 deletions(-) diff --git a/target-m68k/translate.c b/target-m68k/translate.c index 39816f4..36e27a1 100644 --- a/target-m68k/translate.c +++ b/target-m68k/translate.c @@ -3280,3 +3280,8 @@ void cpu_dump_state(CPUState *env, FILE *f, cpu_fprintf (f, "FPRESULT = %12g\n", *(double *)&env->fp_result); } +void gen_pc_load(CPUState *env, TranslationBlock *tb, + unsigned long searched_pc, int pc_pos, void *puc) +{ + env->pc = gen_opc_pc[pc_pos]; +} diff --git a/translate-all.c b/translate-all.c index 66f03e1..5e63978 100644 --- a/translate-all.c +++ b/translate-all.c @@ -202,7 +202,7 @@ int cpu_restore_state(TranslationBlock *tb, #elif defined(TARGET_PPC) gen_pc_load(env, tb, searched_pc, j, puc); #elif defined(TARGET_M68K) - env->pc = gen_opc_pc[j]; + gen_pc_load(env, tb, searched_pc, j, puc); #elif defined(TARGET_MIPS) env->PC[env->current_tc] = gen_opc_pc[j]; env->hflags &= ~MIPS_HFLAG_BMASK; -- 1.5.0.6 |
From: Glauber C. <gc...@re...> - 2008-04-25 03:28:40
|
this patch replaced code inside specific ifdef in translate-all.c with a generic architecture-implemented function. This leads to a cleaner and more modular code in the generic part. --- target-ppc/translate.c | 42 ++++++++++++++++++++++++++++++++++++++++++ translate-all.c | 40 +--------------------------------------- 2 files changed, 43 insertions(+), 39 deletions(-) diff --git a/target-ppc/translate.c b/target-ppc/translate.c index c9530eb..6f7d16c 100644 --- a/target-ppc/translate.c +++ b/target-ppc/translate.c @@ -6344,3 +6344,45 @@ int gen_intermediate_code_pc (CPUState *env, struct TranslationBlock *tb) { return gen_intermediate_code_internal(env, tb, 1); } + +void gen_pc_load(CPUState *env, TranslationBlock *tb, + unsigned long searched_pc, int pc_pos, void *puc) +{ + int type, c; + /* for PPC, we need to look at the micro operation to get the + * access type */ + env->nip = gen_opc_pc[pc_pos]; + c = gen_opc_buf[pc_pos]; + switch(c) { +#if defined(CONFIG_USER_ONLY) +#define CASE3(op)\ + case INDEX_op_ ## op ## _raw +#else +#define CASE3(op)\ + case INDEX_op_ ## op ## _user:\ + case INDEX_op_ ## op ## _kernel:\ + case INDEX_op_ ## op ## _hypv +#endif + + CASE3(stfd): + CASE3(stfs): + CASE3(lfd): + CASE3(lfs): + type = ACCESS_FLOAT; + break; + CASE3(lwarx): + type = ACCESS_RES; + break; + CASE3(stwcx): + type = ACCESS_RES; + break; + CASE3(eciwx): + CASE3(ecowx): + type = ACCESS_EXT; + break; + default: + type = ACCESS_INT; + break; + } + env->access_type = type; +} diff --git a/translate-all.c b/translate-all.c index 92c8f1c..66f03e1 100644 --- a/translate-all.c +++ b/translate-all.c @@ -200,45 +200,7 @@ int cpu_restore_state(TranslationBlock *tb, #elif defined(TARGET_SPARC) gen_pc_load(env, tb, searched_pc, j, puc); #elif defined(TARGET_PPC) - { - int type, c; - /* for PPC, we need to look at the micro operation to get the - access type */ - env->nip = gen_opc_pc[j]; - c = gen_opc_buf[j]; - switch(c) { -#if defined(CONFIG_USER_ONLY) -#define CASE3(op)\ - case INDEX_op_ ## op ## _raw -#else -#define CASE3(op)\ - case INDEX_op_ ## op ## _user:\ - case INDEX_op_ ## op ## _kernel:\ - case INDEX_op_ ## op ## _hypv -#endif - - CASE3(stfd): - CASE3(stfs): - CASE3(lfd): - CASE3(lfs): - type = ACCESS_FLOAT; - break; - CASE3(lwarx): - type = ACCESS_RES; - break; - CASE3(stwcx): - type = ACCESS_RES; - break; - CASE3(eciwx): - CASE3(ecowx): - type = ACCESS_EXT; - break; - default: - type = ACCESS_INT; - break; - } - env->access_type = type; - } + gen_pc_load(env, tb, searched_pc, j, puc); #elif defined(TARGET_M68K) env->pc = gen_opc_pc[j]; #elif defined(TARGET_MIPS) -- 1.5.0.6 |
From: Glauber C. <gc...@re...> - 2008-04-25 03:28:37
|
this patch replaced code inside specific ifdef in translate-all.c with a generic architecture-implemented function. This leads to a cleaner and more modular code in the generic part. --- target-sparc/translate.c | 20 ++++++++++++++++++++ translate-all.c | 18 +----------------- 2 files changed, 21 insertions(+), 17 deletions(-) diff --git a/target-sparc/translate.c b/target-sparc/translate.c index 90d9278..6edf64d 100644 --- a/target-sparc/translate.c +++ b/target-sparc/translate.c @@ -4659,3 +4659,23 @@ void gen_intermediate_code_init(CPUSPARCState *env) gregnames[i]); } } + +void gen_pc_load(CPUState *env, TranslationBlock *tb, + unsigned long searched_pc, int pc_pos, void *puc) +{ + target_ulong npc; + env->pc = gen_opc_pc[pc_pos]; + npc = gen_opc_npc[pc_pos]; + if (npc == 1) { + /* dynamic NPC: already stored */ + } else if (npc == 2) { + target_ulong t2 = (target_ulong)(unsigned long)puc; + /* jump PC: use T2 and the jump targets of the translation */ + if (t2) + env->npc = gen_opc_jump_pc[0]; + else + env->npc = gen_opc_jump_pc[1]; + } else { + env->npc = npc; + } +} diff --git a/translate-all.c b/translate-all.c index e688318..92c8f1c 100644 --- a/translate-all.c +++ b/translate-all.c @@ -198,23 +198,7 @@ int cpu_restore_state(TranslationBlock *tb, #elif defined(TARGET_ARM) gen_pc_load(env, tb, searched_pc, j, puc); #elif defined(TARGET_SPARC) - { - target_ulong npc; - env->pc = gen_opc_pc[j]; - npc = gen_opc_npc[j]; - if (npc == 1) { - /* dynamic NPC: already stored */ - } else if (npc == 2) { - target_ulong t2 = (target_ulong)(unsigned long)puc; - /* jump PC: use T2 and the jump targets of the translation */ - if (t2) - env->npc = gen_opc_jump_pc[0]; - else - env->npc = gen_opc_jump_pc[1]; - } else { - env->npc = npc; - } - } + gen_pc_load(env, tb, searched_pc, j, puc); #elif defined(TARGET_PPC) { int type, c; -- 1.5.0.6 |
From: Glauber C. <gc...@re...> - 2008-04-25 03:28:33
|
this patch replaced code inside specific ifdef in translate-all.c with a generic architecture-implemented function. This leads to a cleaner and more modular code in the generic part. --- exec-all.h | 3 +++ target-i386/translate.c | 23 +++++++++++++++++++++++ translate-all.c | 22 +--------------------- 3 files changed, 27 insertions(+), 21 deletions(-) diff --git a/exec-all.h b/exec-all.h index 62b8191..3ce8242 100644 --- a/exec-all.h +++ b/exec-all.h @@ -61,6 +61,9 @@ extern int loglevel; int gen_intermediate_code(CPUState *env, struct TranslationBlock *tb); int gen_intermediate_code_pc(CPUState *env, struct TranslationBlock *tb); +void gen_pc_load(CPUState *env, struct TranslationBlock *tb, + unsigned long searched_pc, int pc_pos, void *puc); + unsigned long code_gen_max_block_size(void); void cpu_gen_init(void); int cpu_gen_code(CPUState *env, struct TranslationBlock *tb, diff --git a/target-i386/translate.c b/target-i386/translate.c index 356ceff..895d14b 100644 --- a/target-i386/translate.c +++ b/target-i386/translate.c @@ -6832,3 +6832,26 @@ int gen_intermediate_code_pc(CPUState *env, TranslationBlock *tb) return gen_intermediate_code_internal(env, tb, 1); } +void gen_pc_load(CPUState *env, TranslationBlock *tb, + unsigned long searched_pc, int pc_pos, void *puc) +{ + int cc_op; +#ifdef DEBUG_DISAS + if (loglevel & CPU_LOG_TB_OP) { + int i; + fprintf(logfile, "RESTORE:\n"); + for(i = 0;i <= pc_pos; i++) { + if (gen_opc_instr_start[i]) { + fprintf(logfile, "0x%04x: " TARGET_FMT_lx "\n", i, gen_opc_pc[i]); + } + } + fprintf(logfile, "spc=0x%08lx pc_pos=0x%x eip=" TARGET_FMT_lx " cs_base=%x\n", + searched_pc, pc_pos, gen_opc_pc[pc_pos] - tb->cs_base, + (uint32_t)tb->cs_base); + } +#endif + env->eip = gen_opc_pc[pc_pos] - tb->cs_base; + cc_op = gen_opc_cc_op[pc_pos]; + if (cc_op != CC_OP_DYNAMIC) + env->cc_op = cc_op; +} diff --git a/translate-all.c b/translate-all.c index 6a273a8..73e1d67 100644 --- a/translate-all.c +++ b/translate-all.c @@ -194,27 +194,7 @@ int cpu_restore_state(TranslationBlock *tb, while (gen_opc_instr_start[j] == 0) j--; #if defined(TARGET_I386) - { - int cc_op; -#ifdef DEBUG_DISAS - if (loglevel & CPU_LOG_TB_OP) { - int i; - fprintf(logfile, "RESTORE:\n"); - for(i=0;i<=j; i++) { - if (gen_opc_instr_start[i]) { - fprintf(logfile, "0x%04x: " TARGET_FMT_lx "\n", i, gen_opc_pc[i]); - } - } - fprintf(logfile, "spc=0x%08lx j=0x%x eip=" TARGET_FMT_lx " cs_base=%x\n", - searched_pc, j, gen_opc_pc[j] - tb->cs_base, - (uint32_t)tb->cs_base); - } -#endif - env->eip = gen_opc_pc[j] - tb->cs_base; - cc_op = gen_opc_cc_op[j]; - if (cc_op != CC_OP_DYNAMIC) - env->cc_op = cc_op; - } + gen_pc_load(env, tb, searched_pc, j, puc); #elif defined(TARGET_ARM) env->regs[15] = gen_opc_pc[j]; #elif defined(TARGET_SPARC) -- 1.5.0.6 |
From: Glauber C. <gc...@re...> - 2008-04-25 03:28:32
|
this patch replaced code inside specific ifdef in translate-all.c with a generic architecture-implemented function. This leads to a cleaner and more modular code in the generic part. --- target-arm/translate.c | 5 +++++ translate-all.c | 2 +- 2 files changed, 6 insertions(+), 1 deletions(-) diff --git a/target-arm/translate.c b/target-arm/translate.c index 6de78f8..8966996 100644 --- a/target-arm/translate.c +++ b/target-arm/translate.c @@ -7706,3 +7706,8 @@ void cpu_dump_state(CPUState *env, FILE *f, cpu_fprintf(f, "FPSCR: %08x\n", (int)env->vfp.xregs[ARM_VFP_FPSCR]); } +void gen_pc_load(CPUState *env, TranslationBlock *tb, + unsigned long searched_pc, int pc_pos, void *puc) +{ + env->regs[15] = gen_opc_pc[pc_pos]; +} diff --git a/translate-all.c b/translate-all.c index 73e1d67..e688318 100644 --- a/translate-all.c +++ b/translate-all.c @@ -196,7 +196,7 @@ int cpu_restore_state(TranslationBlock *tb, #if defined(TARGET_I386) gen_pc_load(env, tb, searched_pc, j, puc); #elif defined(TARGET_ARM) - env->regs[15] = gen_opc_pc[j]; + gen_pc_load(env, tb, searched_pc, j, puc); #elif defined(TARGET_SPARC) { target_ulong npc; -- 1.5.0.6 |
From: Glauber C. <gc...@re...> - 2008-04-25 03:28:28
|
Hi, This series is an (initial) attempt to make qemu code a little bit more modular. In this patch series specifically, I'm removing some #ifdef TARGET_* from the general-purpose translate.c, and rather, replacing them with a common function implemented in architecture specific files. Any rants and complaints, let me know Hope you like it |
From: David A. <da...@bo...> - 2008-04-25 03:06:53
|
If I suspend my host while running a Windows XP guest, the whole machine crashes, so I was hoping to automate hibernation of the guest OS and integrate that into my host's suspend process. Does anyone know how to do that? TIA, -- Dave Abrahams Boost Consulting http://boost-consulting.com |
From: Yang, S. <she...@in...> - 2008-04-25 01:15:45
|
On Friday 25 April 2008 08:33:04 Jan Kiszka wrote: > Hi, > > I saw kvm-userspace recently merged qemu's new CPU_INTERRUPT_NMI > support. But the required infrastructure to use this in kvm mode is not > yet visible. Is anyone working on this? Sheng? IIRC, you once said to > work on it. > > Currently I just need the basic mechanism for injecting NMIs into the > guest (from special hardware emulation), no full support for in-kernel > [A]PICs. But before starting some quick&dirty hack, I would like to know > if someone already has a patch pending and is able to share even just > preliminary results. > > Thanks, > Jan Yeah, the patchset is mostly completed. But I have to switch to do EPT enabling these days so don't have time to do more test and push them out... I tested patchset by NMI watchdog(also introduce the logic of the NMI watchlog), about one thousand NMI per second at most. The patchset also did some clean up on VMX interrupt handling. I would like to push the patch next week (if the EPT things can be done this week or early next week). Sorry for keep you waiting so long... -- Thanks Yang, Sheng |
From: Marcelo T. <mto...@re...> - 2008-04-25 00:58:21
|
Add three PCI bridges to support 128 slots. Vendor and device_id have been stolen from my test box. I/O port addresses behind each bridge are statically allocated starting from 0x2000 with 0x1000 length. Once the bridge runs out of I/O space the guest (Linux at least) happily allocates outside of the region. That needs verification. I/O memory addresses are divided between 0xf0000000 -> APIC base. The PCI irq mapping function is also changed, there was the assumption that devices behind the bridge use the IRQ allocated to the bridge device itself, which is weird. Apparently this is how the SPARC ABP PCI host works (only user of the bridge code at the moment). There was a copy&paste buglet in acpi-dsdt.dsl, slots 8 and 9 were sharing the same address, and that error was later copy&pasted to slots 24 and 25. Please review and give it a try (attached is the patch to increase the QEMU static tables). Index: kvm-userspace.pci2/hw/pci.c =================================================================== --- a/qemu/hw/pci.c +++ b/qemu/hw/pci.c @@ -532,6 +532,7 @@ uint32_t pci_data_read(void *opaque, uint32_t addr, int len) static void pci_set_irq(void *opaque, int irq_num, int level) { PCIDevice *pci_dev = (PCIDevice *)opaque; + PCIDevice *host_dev; PCIBus *bus; int change; @@ -539,13 +540,16 @@ static void pci_set_irq(void *opaque, int irq_num, int level) if (!change) return; + pci_dev->irq_state[irq_num] = level; + host_dev = pci_dev; for (;;) { - bus = pci_dev->bus; - irq_num = bus->map_irq(pci_dev, irq_num); - if (bus->set_irq) + bus = host_dev->bus; + if (bus->set_irq) { + irq_num = bus->map_irq(pci_dev, irq_num); break; - pci_dev = bus->parent_dev; + } + host_dev = bus->parent_dev; } bus->irq_count[irq_num] += change; bus->set_irq(bus->irq_opaque, irq_num, bus->irq_count[irq_num] != 0); Index: kvm-userspace.pci2/bios/acpi-dsdt.dsl =================================================================== --- kvm-userspace.pci2.orig/bios/acpi-dsdt.dsl +++ kvm-userspace.pci2/bios/acpi-dsdt.dsl @@ -208,218 +208,29 @@ DefinitionBlock ( Name (_HID, EisaId ("PNP0A03")) Name (_ADR, 0x00) Name (_UID, 1) - Name(_PRT, Package() { - /* PCI IRQ routing table, example from ACPI 2.0a specification, - section 6.2.8.1 */ - /* Note: we provide the same info as the PCI routing - table of the Bochs BIOS */ - - // PCI Slot 0 - Package() {0x0000ffff, 0, LNKD, 0}, - Package() {0x0000ffff, 1, LNKA, 0}, - Package() {0x0000ffff, 2, LNKB, 0}, - Package() {0x0000ffff, 3, LNKC, 0}, - - // PCI Slot 1 - Package() {0x0001ffff, 0, LNKA, 0}, - Package() {0x0001ffff, 1, LNKB, 0}, - Package() {0x0001ffff, 2, LNKC, 0}, - Package() {0x0001ffff, 3, LNKD, 0}, - - // PCI Slot 2 - Package() {0x0002ffff, 0, LNKB, 0}, - Package() {0x0002ffff, 1, LNKC, 0}, - Package() {0x0002ffff, 2, LNKD, 0}, - Package() {0x0002ffff, 3, LNKA, 0}, - - // PCI Slot 3 - Package() {0x0003ffff, 0, LNKC, 0}, - Package() {0x0003ffff, 1, LNKD, 0}, - Package() {0x0003ffff, 2, LNKA, 0}, - Package() {0x0003ffff, 3, LNKB, 0}, - - // PCI Slot 4 - Package() {0x0004ffff, 0, LNKD, 0}, - Package() {0x0004ffff, 1, LNKA, 0}, - Package() {0x0004ffff, 2, LNKB, 0}, - Package() {0x0004ffff, 3, LNKC, 0}, - - // PCI Slot 5 - Package() {0x0005ffff, 0, LNKA, 0}, - Package() {0x0005ffff, 1, LNKB, 0}, - Package() {0x0005ffff, 2, LNKC, 0}, - Package() {0x0005ffff, 3, LNKD, 0}, - - // PCI Slot 6 - Package() {0x0006ffff, 0, LNKB, 0}, - Package() {0x0006ffff, 1, LNKC, 0}, - Package() {0x0006ffff, 2, LNKD, 0}, - Package() {0x0006ffff, 3, LNKA, 0}, - - // PCI Slot 7 - Package() {0x0007ffff, 0, LNKC, 0}, - Package() {0x0007ffff, 1, LNKD, 0}, - Package() {0x0007ffff, 2, LNKA, 0}, - Package() {0x0007ffff, 3, LNKB, 0}, - - // PCI Slot 8 - Package() {0x0008ffff, 0, LNKD, 0}, - Package() {0x0008ffff, 1, LNKA, 0}, - Package() {0x0008ffff, 2, LNKB, 0}, - Package() {0x0008ffff, 3, LNKC, 0}, - - // PCI Slot 9 - Package() {0x0008ffff, 0, LNKA, 0}, - Package() {0x0008ffff, 1, LNKB, 0}, - Package() {0x0008ffff, 2, LNKC, 0}, - Package() {0x0008ffff, 3, LNKD, 0}, - - // PCI Slot 10 - Package() {0x000affff, 0, LNKB, 0}, - Package() {0x000affff, 1, LNKC, 0}, - Package() {0x000affff, 2, LNKD, 0}, - Package() {0x000affff, 3, LNKA, 0}, - - // PCI Slot 11 - Package() {0x000bffff, 0, LNKC, 0}, - Package() {0x000bffff, 1, LNKD, 0}, - Package() {0x000bffff, 2, LNKA, 0}, - Package() {0x000bffff, 3, LNKB, 0}, - - // PCI Slot 12 - Package() {0x000cffff, 0, LNKD, 0}, - Package() {0x000cffff, 1, LNKA, 0}, - Package() {0x000cffff, 2, LNKB, 0}, - Package() {0x000cffff, 3, LNKC, 0}, - - // PCI Slot 13 - Package() {0x000dffff, 0, LNKA, 0}, - Package() {0x000dffff, 1, LNKB, 0}, - Package() {0x000dffff, 2, LNKC, 0}, - Package() {0x000dffff, 3, LNKD, 0}, - - // PCI Slot 14 - Package() {0x000effff, 0, LNKB, 0}, - Package() {0x000effff, 1, LNKC, 0}, - Package() {0x000effff, 2, LNKD, 0}, - Package() {0x000effff, 3, LNKA, 0}, - - // PCI Slot 15 - Package() {0x000fffff, 0, LNKC, 0}, - Package() {0x000fffff, 1, LNKD, 0}, - Package() {0x000fffff, 2, LNKA, 0}, - Package() {0x000fffff, 3, LNKB, 0}, - - // PCI Slot 16 - Package() {0x0010ffff, 0, LNKD, 0}, - Package() {0x0010ffff, 1, LNKA, 0}, - Package() {0x0010ffff, 2, LNKB, 0}, - Package() {0x0010ffff, 3, LNKC, 0}, - - // PCI Slot 17 - Package() {0x0011ffff, 0, LNKA, 0}, - Package() {0x0011ffff, 1, LNKB, 0}, - Package() {0x0011ffff, 2, LNKC, 0}, - Package() {0x0011ffff, 3, LNKD, 0}, - - // PCI Slot 18 - Package() {0x0012ffff, 0, LNKB, 0}, - Package() {0x0012ffff, 1, LNKC, 0}, - Package() {0x0012ffff, 2, LNKD, 0}, - Package() {0x0012ffff, 3, LNKA, 0}, - - // PCI Slot 19 - Package() {0x0013ffff, 0, LNKC, 0}, - Package() {0x0013ffff, 1, LNKD, 0}, - Package() {0x0013ffff, 2, LNKA, 0}, - Package() {0x0013ffff, 3, LNKB, 0}, - - // PCI Slot 20 - Package() {0x0014ffff, 0, LNKD, 0}, - Package() {0x0014ffff, 1, LNKA, 0}, - Package() {0x0014ffff, 2, LNKB, 0}, - Package() {0x0014ffff, 3, LNKC, 0}, - - // PCI Slot 21 - Package() {0x0015ffff, 0, LNKA, 0}, - Package() {0x0015ffff, 1, LNKB, 0}, - Package() {0x0015ffff, 2, LNKC, 0}, - Package() {0x0015ffff, 3, LNKD, 0}, - - // PCI Slot 22 - Package() {0x0016ffff, 0, LNKB, 0}, - Package() {0x0016ffff, 1, LNKC, 0}, - Package() {0x0016ffff, 2, LNKD, 0}, - Package() {0x0016ffff, 3, LNKA, 0}, - - // PCI Slot 23 - Package() {0x0017ffff, 0, LNKC, 0}, - Package() {0x0017ffff, 1, LNKD, 0}, - Package() {0x0017ffff, 2, LNKA, 0}, - Package() {0x0017ffff, 3, LNKB, 0}, - - // PCI Slot 24 - Package() {0x0018ffff, 0, LNKD, 0}, - Package() {0x0018ffff, 1, LNKA, 0}, - Package() {0x0018ffff, 2, LNKB, 0}, - Package() {0x0018ffff, 3, LNKC, 0}, - - // PCI Slot 25 - Package() {0x0018ffff, 0, LNKA, 0}, - Package() {0x0018ffff, 1, LNKB, 0}, - Package() {0x0018ffff, 2, LNKC, 0}, - Package() {0x0018ffff, 3, LNKD, 0}, - - // PCI Slot 26 - Package() {0x001affff, 0, LNKB, 0}, - Package() {0x001affff, 1, LNKC, 0}, - Package() {0x001affff, 2, LNKD, 0}, - Package() {0x001affff, 3, LNKA, 0}, - - // PCI Slot 27 - Package() {0x001bffff, 0, LNKC, 0}, - Package() {0x001bffff, 1, LNKD, 0}, - Package() {0x001bffff, 2, LNKA, 0}, - Package() {0x001bffff, 3, LNKB, 0}, - - // PCI Slot 28 - Package() {0x001cffff, 0, LNKD, 0}, - Package() {0x001cffff, 1, LNKA, 0}, - Package() {0x001cffff, 2, LNKB, 0}, - Package() {0x001cffff, 3, LNKC, 0}, - - // PCI Slot 29 - Package() {0x001dffff, 0, LNKA, 0}, - Package() {0x001dffff, 1, LNKB, 0}, - Package() {0x001dffff, 2, LNKC, 0}, - Package() {0x001dffff, 3, LNKD, 0}, - - // PCI Slot 30 - Package() {0x001effff, 0, LNKB, 0}, - Package() {0x001effff, 1, LNKC, 0}, - Package() {0x001effff, 2, LNKD, 0}, - Package() {0x001effff, 3, LNKA, 0}, - - // PCI Slot 31 - Package() {0x001fffff, 0, LNKC, 0}, - Package() {0x001fffff, 1, LNKD, 0}, - Package() {0x001fffff, 2, LNKA, 0}, - Package() {0x001fffff, 3, LNKB, 0}, - }) + + Include ("acpi-irq-routing.dsl") OperationRegion(PCST, SystemIO, 0xae00, 0x08) Field (PCST, DWordAcc, NoLock, WriteAsZeros) - { + { PCIU, 32, PCID, 32, - } - + } OperationRegion(SEJ, SystemIO, 0xae08, 0x04) Field (SEJ, DWordAcc, NoLock, WriteAsZeros) { B0EJ, 32, } + Device (S0) { // Slot 0 + Name (_ADR, 0x00000000) + Method (_EJ0,1) { + Store(0x1, B0EJ) + Return (0x0) + } + } + Device (S1) { // Slot 1 Name (_ADR, 0x00010000) Method (_EJ0,1) { @@ -436,28 +247,70 @@ DefinitionBlock ( } } - Device (S3) { // Slot 3 + Device (S3) { // Slot 3, PCI-to-PCI bridge Name (_ADR, 0x00030000) - Method (_EJ0,1) { - Store (0x8, B0EJ) - Return (0x0) + Include ("acpi-irq-routing.dsl") + + OperationRegion(PCST, SystemIO, 0xae0c, 0x08) + Field (PCST, DWordAcc, NoLock, WriteAsZeros) + { + PCIU, 32, + PCID, 32, } + + OperationRegion(SEJ, SystemIO, 0xae14, 0x04) + Field (SEJ, DWordAcc, NoLock, WriteAsZeros) + { + B1EJ, 32, + } + + Name (SUN1, 30) + Alias (\_SB.PCI0.S3.B1EJ, BEJ) + Include ("acpi-pci-slots.dsl") } - Device (S4) { // Slot 4 + Device (S4) { // Slot 4, PCI-to-PCI bridge Name (_ADR, 0x00040000) - Method (_EJ0,1) { - Store(0x10, B0EJ) - Return (0x0) + Include ("acpi-irq-routing.dsl") + + OperationRegion(PCST, SystemIO, 0xae18, 0x08) + Field (PCST, DWordAcc, NoLock, WriteAsZeros) + { + PCIU, 32, + PCID, 32, + } + + OperationRegion(SEJ, SystemIO, 0xae20, 0x04) + Field (SEJ, DWordAcc, NoLock, WriteAsZeros) + { + B2EJ, 32, } + + Name (SUN1, 62) + Alias (\_SB.PCI0.S4.B2EJ, BEJ) + Include ("acpi-pci-slots.dsl") } - Device (S5) { // Slot 5 + Device (S5) { // Slot 5, PCI-to-PCI bridge Name (_ADR, 0x00050000) - Method (_EJ0,1) { - Store(0x20, B0EJ) - Return (0x0) + Include ("acpi-irq-routing.dsl") + + OperationRegion(PCST, SystemIO, 0xae24, 0x08) + Field (PCST, DWordAcc, NoLock, WriteAsZeros) + { + PCIU, 32, + PCID, 32, } + + OperationRegion(SEJ, SystemIO, 0xae2c, 0x04) + Field (SEJ, DWordAcc, NoLock, WriteAsZeros) + { + B3EJ, 32, + } + + Name (SUN1, 94) + Alias (\_SB.PCI0.S5.B3EJ, BEJ) + Include ("acpi-pci-slots.dsl") } Device (S6) { // Slot 6 @@ -1248,266 +1101,156 @@ DefinitionBlock ( Return(0x01) } Method(_L01) { - /* Up status */ - If (And(\_SB.PCI0.PCIU, 0x2)) { - Notify(\_SB.PCI0.S1, 0x1) - } - - If (And(\_SB.PCI0.PCIU, 0x4)) { - Notify(\_SB.PCI0.S2, 0x1) - } - - If (And(\_SB.PCI0.PCIU, 0x8)) { - Notify(\_SB.PCI0.S3, 0x1) - } - - If (And(\_SB.PCI0.PCIU, 0x10)) { - Notify(\_SB.PCI0.S4, 0x1) - } - - If (And(\_SB.PCI0.PCIU, 0x20)) { - Notify(\_SB.PCI0.S5, 0x1) - } - - If (And(\_SB.PCI0.PCIU, 0x40)) { - Notify(\_SB.PCI0.S6, 0x1) - } - - If (And(\_SB.PCI0.PCIU, 0x80)) { - Notify(\_SB.PCI0.S7, 0x1) - } - - If (And(\_SB.PCI0.PCIU, 0x0100)) { - Notify(\_SB.PCI0.S8, 0x1) - } - - If (And(\_SB.PCI0.PCIU, 0x0200)) { - Notify(\_SB.PCI0.S9, 0x1) - } - - If (And(\_SB.PCI0.PCIU, 0x0400)) { - Notify(\_SB.PCI0.S10, 0x1) - } - - If (And(\_SB.PCI0.PCIU, 0x0800)) { - Notify(\_SB.PCI0.S11, 0x1) - } - - If (And(\_SB.PCI0.PCIU, 0x1000)) { - Notify(\_SB.PCI0.S12, 0x1) - } - - If (And(\_SB.PCI0.PCIU, 0x2000)) { - Notify(\_SB.PCI0.S13, 0x1) - } - - If (And(\_SB.PCI0.PCIU, 0x4000)) { - Notify(\_SB.PCI0.S14, 0x1) - } - - If (And(\_SB.PCI0.PCIU, 0x8000)) { - Notify(\_SB.PCI0.S15, 0x1) - } - - If (And(\_SB.PCI0.PCIU, 0x10000)) { - Notify(\_SB.PCI0.S16, 0x1) - } - - If (And(\_SB.PCI0.PCIU, 0x20000)) { - Notify(\_SB.PCI0.S17, 0x1) - } - - If (And(\_SB.PCI0.PCIU, 0x40000)) { - Notify(\_SB.PCI0.S18, 0x1) - } - - If (And(\_SB.PCI0.PCIU, 0x80000)) { - Notify(\_SB.PCI0.S19, 0x1) - } - - If (And(\_SB.PCI0.PCIU, 0x100000)) { - Notify(\_SB.PCI0.S20, 0x1) - } - - If (And(\_SB.PCI0.PCIU, 0x200000)) { - Notify(\_SB.PCI0.S21, 0x1) - } - - If (And(\_SB.PCI0.PCIU, 0x400000)) { - Notify(\_SB.PCI0.S22, 0x1) - } - - If (And(\_SB.PCI0.PCIU, 0x800000)) { - Notify(\_SB.PCI0.S23, 0x1) - } - - If (And(\_SB.PCI0.PCIU, 0x1000000)) { - Notify(\_SB.PCI0.S24, 0x1) - } - - If (And(\_SB.PCI0.PCIU, 0x2000000)) { - Notify(\_SB.PCI0.S25, 0x1) - } - - If (And(\_SB.PCI0.PCIU, 0x4000000)) { - Notify(\_SB.PCI0.S26, 0x1) - } - - If (And(\_SB.PCI0.PCIU, 0x8000000)) { - Notify(\_SB.PCI0.S27, 0x1) - } - - If (And(\_SB.PCI0.PCIU, 0x10000000)) { - Notify(\_SB.PCI0.S28, 0x1) - } - - If (And(\_SB.PCI0.PCIU, 0x20000000)) { - Notify(\_SB.PCI0.S29, 0x1) - } - - If (And(\_SB.PCI0.PCIU, 0x40000000)) { - Notify(\_SB.PCI0.S30, 0x1) - } - - If (And(\_SB.PCI0.PCIU, 0x80000000)) { - Notify(\_SB.PCI0.S31, 0x1) - } - - /* Down status */ - If (And(\_SB.PCI0.PCID, 0x2)) { - Notify(\_SB.PCI0.S1, 0x3) - } - - If (And(\_SB.PCI0.PCID, 0x4)) { - Notify(\_SB.PCI0.S2, 0x3) - } - - If (And(\_SB.PCI0.PCID, 0x8)) { - Notify(\_SB.PCI0.S3, 0x3) - } - - If (And(\_SB.PCI0.PCID, 0x10)) { - Notify(\_SB.PCI0.S4, 0x3) - } - - If (And(\_SB.PCI0.PCID, 0x20)) { - Notify(\_SB.PCI0.S5, 0x3) - } - - If (And(\_SB.PCI0.PCID, 0x40)) { - Notify(\_SB.PCI0.S6, 0x3) - } - - If (And(\_SB.PCI0.PCID, 0x80)) { - Notify(\_SB.PCI0.S7, 0x3) - } - - If (And(\_SB.PCI0.PCID, 0x0100)) { - Notify(\_SB.PCI0.S8, 0x3) - } - - If (And(\_SB.PCI0.PCID, 0x0200)) { - Notify(\_SB.PCI0.S9, 0x3) - } - - If (And(\_SB.PCI0.PCID, 0x0400)) { - Notify(\_SB.PCI0.S10, 0x3) - } - - If (And(\_SB.PCI0.PCID, 0x0800)) { - Notify(\_SB.PCI0.S11, 0x3) - } - - If (And(\_SB.PCI0.PCID, 0x1000)) { - Notify(\_SB.PCI0.S12, 0x3) - } - - If (And(\_SB.PCI0.PCID, 0x2000)) { - Notify(\_SB.PCI0.S13, 0x3) - } - - If (And(\_SB.PCI0.PCID, 0x4000)) { - Notify(\_SB.PCI0.S14, 0x3) - } - - If (And(\_SB.PCI0.PCID, 0x8000)) { - Notify(\_SB.PCI0.S15, 0x3) - } - - If (And(\_SB.PCI0.PCID, 0x10000)) { - Notify(\_SB.PCI0.S16, 0x3) - } - - If (And(\_SB.PCI0.PCID, 0x20000)) { - Notify(\_SB.PCI0.S17, 0x3) - } - - If (And(\_SB.PCI0.PCID, 0x40000)) { - Notify(\_SB.PCI0.S18, 0x3) - } - - If (And(\_SB.PCI0.PCID, 0x80000)) { - Notify(\_SB.PCI0.S19, 0x3) - } - - If (And(\_SB.PCI0.PCID, 0x100000)) { - Notify(\_SB.PCI0.S20, 0x3) - } - - If (And(\_SB.PCI0.PCID, 0x200000)) { - Notify(\_SB.PCI0.S21, 0x3) - } - - If (And(\_SB.PCI0.PCID, 0x400000)) { - Notify(\_SB.PCI0.S22, 0x3) - } - - If (And(\_SB.PCI0.PCID, 0x800000)) { - Notify(\_SB.PCI0.S23, 0x3) - } - - If (And(\_SB.PCI0.PCID, 0x1000000)) { - Notify(\_SB.PCI0.S24, 0x3) - } - - If (And(\_SB.PCI0.PCID, 0x2000000)) { - Notify(\_SB.PCI0.S25, 0x3) - } - - If (And(\_SB.PCI0.PCID, 0x4000000)) { - Notify(\_SB.PCI0.S26, 0x3) - } - - If (And(\_SB.PCI0.PCID, 0x8000000)) { - Notify(\_SB.PCI0.S27, 0x3) - } - - If (And(\_SB.PCI0.PCID, 0x10000000)) { - Notify(\_SB.PCI0.S28, 0x3) - } - - If (And(\_SB.PCI0.PCID, 0x20000000)) { - Notify(\_SB.PCI0.S29, 0x3) - } - - If (And(\_SB.PCI0.PCID, 0x40000000)) { - Notify(\_SB.PCI0.S30, 0x3) - } - - If (And(\_SB.PCI0.PCID, 0x80000000)) { - Notify(\_SB.PCI0.S31, 0x3) - } - - Return(0x01) + Alias (\_SB.PCI0.PCIU, UP) + Alias (\_SB.PCI0.PCID, DOWN) + Alias (\_SB.PCI0.S0, S0) + Alias (\_SB.PCI0.S1, S1) + Alias (\_SB.PCI0.S2, S2) + Alias (\_SB.PCI0.S3, S3) + Alias (\_SB.PCI0.S4, S4) + Alias (\_SB.PCI0.S5, S5) + Alias (\_SB.PCI0.S6, S6) + Alias (\_SB.PCI0.S7, S7) + Alias (\_SB.PCI0.S8, S8) + Alias (\_SB.PCI0.S9, S9) + Alias (\_SB.PCI0.S10, S10) + Alias (\_SB.PCI0.S11, S11) + Alias (\_SB.PCI0.S12, S12) + Alias (\_SB.PCI0.S13, S13) + Alias (\_SB.PCI0.S14, S14) + Alias (\_SB.PCI0.S15, S15) + Alias (\_SB.PCI0.S16, S16) + Alias (\_SB.PCI0.S17, S17) + Alias (\_SB.PCI0.S18, S18) + Alias (\_SB.PCI0.S19, S19) + Alias (\_SB.PCI0.S20, S20) + Alias (\_SB.PCI0.S21, S21) + Alias (\_SB.PCI0.S22, S22) + Alias (\_SB.PCI0.S23, S23) + Alias (\_SB.PCI0.S24, S24) + Alias (\_SB.PCI0.S25, S25) + Alias (\_SB.PCI0.S26, S26) + Alias (\_SB.PCI0.S27, S27) + Alias (\_SB.PCI0.S28, S28) + Alias (\_SB.PCI0.S29, S29) + Alias (\_SB.PCI0.S30, S30) + Alias (\_SB.PCI0.S31, S31) + Include ("acpi-hotplug-gpe.dsl") + Return (0x01) } Method(_L02) { - Return(0x01) + Alias (\_SB.PCI0.S3.PCIU, UP) + Alias (\_SB.PCI0.S3.PCID, DOWN) + Alias (\_SB.PCI0.S3.S0, S0) + Alias (\_SB.PCI0.S3.S1, S1) + Alias (\_SB.PCI0.S3.S2, S2) + Alias (\_SB.PCI0.S3.S3, S3) + Alias (\_SB.PCI0.S3.S4, S4) + Alias (\_SB.PCI0.S3.S5, S5) + Alias (\_SB.PCI0.S3.S6, S6) + Alias (\_SB.PCI0.S3.S7, S7) + Alias (\_SB.PCI0.S3.S8, S8) + Alias (\_SB.PCI0.S3.S9, S9) + Alias (\_SB.PCI0.S3.S10, S10) + Alias (\_SB.PCI0.S3.S11, S11) + Alias (\_SB.PCI0.S3.S12, S12) + Alias (\_SB.PCI0.S3.S13, S13) + Alias (\_SB.PCI0.S3.S14, S14) + Alias (\_SB.PCI0.S3.S15, S15) + Alias (\_SB.PCI0.S3.S16, S16) + Alias (\_SB.PCI0.S3.S17, S17) + Alias (\_SB.PCI0.S3.S18, S18) + Alias (\_SB.PCI0.S3.S19, S19) + Alias (\_SB.PCI0.S3.S20, S20) + Alias (\_SB.PCI0.S3.S21, S21) + Alias (\_SB.PCI0.S3.S22, S22) + Alias (\_SB.PCI0.S3.S23, S23) + Alias (\_SB.PCI0.S3.S24, S24) + Alias (\_SB.PCI0.S3.S25, S25) + Alias (\_SB.PCI0.S3.S26, S26) + Alias (\_SB.PCI0.S3.S27, S27) + Alias (\_SB.PCI0.S3.S28, S28) + Alias (\_SB.PCI0.S3.S29, S29) + Alias (\_SB.PCI0.S3.S30, S30) + Alias (\_SB.PCI0.S3.S31, S31) + Include ("acpi-hotplug-gpe.dsl") + Return (0x01) } Method(_L03) { - Return(0x01) + Alias (\_SB.PCI0.S4.PCIU, UP) + Alias (\_SB.PCI0.S4.PCID, DOWN) + Alias (\_SB.PCI0.S4.S0, S0) + Alias (\_SB.PCI0.S4.S1, S1) + Alias (\_SB.PCI0.S4.S2, S2) + Alias (\_SB.PCI0.S4.S3, S3) + Alias (\_SB.PCI0.S4.S4, S4) + Alias (\_SB.PCI0.S4.S5, S5) + Alias (\_SB.PCI0.S4.S6, S6) + Alias (\_SB.PCI0.S4.S7, S7) + Alias (\_SB.PCI0.S4.S8, S8) + Alias (\_SB.PCI0.S4.S9, S9) + Alias (\_SB.PCI0.S4.S10, S10) + Alias (\_SB.PCI0.S4.S11, S11) + Alias (\_SB.PCI0.S4.S12, S12) + Alias (\_SB.PCI0.S4.S13, S13) + Alias (\_SB.PCI0.S4.S14, S14) + Alias (\_SB.PCI0.S4.S15, S15) + Alias (\_SB.PCI0.S4.S16, S16) + Alias (\_SB.PCI0.S4.S17, S17) + Alias (\_SB.PCI0.S4.S18, S18) + Alias (\_SB.PCI0.S4.S19, S19) + Alias (\_SB.PCI0.S4.S20, S20) + Alias (\_SB.PCI0.S4.S21, S21) + Alias (\_SB.PCI0.S4.S22, S22) + Alias (\_SB.PCI0.S4.S23, S23) + Alias (\_SB.PCI0.S4.S24, S24) + Alias (\_SB.PCI0.S4.S25, S25) + Alias (\_SB.PCI0.S4.S26, S26) + Alias (\_SB.PCI0.S4.S27, S27) + Alias (\_SB.PCI0.S4.S28, S28) + Alias (\_SB.PCI0.S4.S29, S29) + Alias (\_SB.PCI0.S4.S30, S30) + Alias (\_SB.PCI0.S4.S31, S31) + Include ("acpi-hotplug-gpe.dsl") + Return (0x01) } Method(_L04) { - Return(0x01) + Alias (\_SB.PCI0.S5.PCIU, UP) + Alias (\_SB.PCI0.S5.PCID, DOWN) + Alias (\_SB.PCI0.S5.S0, S0) + Alias (\_SB.PCI0.S5.S1, S1) + Alias (\_SB.PCI0.S5.S2, S2) + Alias (\_SB.PCI0.S5.S3, S3) + Alias (\_SB.PCI0.S5.S4, S4) + Alias (\_SB.PCI0.S5.S5, S5) + Alias (\_SB.PCI0.S5.S6, S6) + Alias (\_SB.PCI0.S5.S7, S7) + Alias (\_SB.PCI0.S5.S8, S8) + Alias (\_SB.PCI0.S5.S9, S9) + Alias (\_SB.PCI0.S5.S10, S10) + Alias (\_SB.PCI0.S5.S11, S11) + Alias (\_SB.PCI0.S5.S12, S12) + Alias (\_SB.PCI0.S5.S13, S13) + Alias (\_SB.PCI0.S5.S14, S14) + Alias (\_SB.PCI0.S5.S15, S15) + Alias (\_SB.PCI0.S5.S16, S16) + Alias (\_SB.PCI0.S5.S17, S17) + Alias (\_SB.PCI0.S5.S18, S18) + Alias (\_SB.PCI0.S5.S19, S19) + Alias (\_SB.PCI0.S5.S20, S20) + Alias (\_SB.PCI0.S5.S21, S21) + Alias (\_SB.PCI0.S5.S22, S22) + Alias (\_SB.PCI0.S5.S23, S23) + Alias (\_SB.PCI0.S5.S24, S24) + Alias (\_SB.PCI0.S5.S25, S25) + Alias (\_SB.PCI0.S5.S26, S26) + Alias (\_SB.PCI0.S5.S27, S27) + Alias (\_SB.PCI0.S5.S28, S28) + Alias (\_SB.PCI0.S5.S29, S29) + Alias (\_SB.PCI0.S5.S30, S30) + Alias (\_SB.PCI0.S5.S31, S31) + Include ("acpi-hotplug-gpe.dsl") + Return (0x01) } Method(_L05) { Return(0x01) Index: kvm-userspace.pci2/bios/acpi-hotplug-gpe.dsl =================================================================== --- /dev/null +++ kvm-userspace.pci2/bios/acpi-hotplug-gpe.dsl @@ -0,0 +1,257 @@ + /* Up status */ + If (And(UP, 0x1)) { + Notify(S0, 0x1) + } + + If (And(UP, 0x2)) { + Notify(S1, 0x1) + } + + If (And(UP, 0x4)) { + Notify(S2, 0x1) + } + + If (And(UP, 0x8)) { + Notify(S3, 0x1) + } + + If (And(UP, 0x10)) { + Notify(S4, 0x1) + } + + If (And(UP, 0x20)) { + Notify(S5, 0x1) + } + + If (And(UP, 0x40)) { + Notify(S6, 0x1) + } + + If (And(UP, 0x80)) { + Notify(S7, 0x1) + } + + If (And(UP, 0x0100)) { + Notify(S8, 0x1) + } + + If (And(UP, 0x0200)) { + Notify(S9, 0x1) + } + + If (And(UP, 0x0400)) { + Notify(S10, 0x1) + } + + If (And(UP, 0x0800)) { + Notify(S11, 0x1) + } + + If (And(UP, 0x1000)) { + Notify(S12, 0x1) + } + + If (And(UP, 0x2000)) { + Notify(S13, 0x1) + } + + If (And(UP, 0x4000)) { + Notify(S14, 0x1) + } + + If (And(UP, 0x8000)) { + Notify(S15, 0x1) + } + + If (And(UP, 0x10000)) { + Notify(S16, 0x1) + } + + If (And(UP, 0x20000)) { + Notify(S17, 0x1) + } + + If (And(UP, 0x40000)) { + Notify(S18, 0x1) + } + + If (And(UP, 0x80000)) { + Notify(S19, 0x1) + } + + If (And(UP, 0x100000)) { + Notify(S20, 0x1) + } + + If (And(UP, 0x200000)) { + Notify(S21, 0x1) + } + + If (And(UP, 0x400000)) { + Notify(S22, 0x1) + } + + If (And(UP, 0x800000)) { + Notify(S23, 0x1) + } + + If (And(UP, 0x1000000)) { + Notify(S24, 0x1) + } + + If (And(UP, 0x2000000)) { + Notify(S25, 0x1) + } + + If (And(UP, 0x4000000)) { + Notify(S26, 0x1) + } + + If (And(UP, 0x8000000)) { + Notify(S27, 0x1) + } + + If (And(UP, 0x10000000)) { + Notify(S28, 0x1) + } + + If (And(UP, 0x20000000)) { + Notify(S29, 0x1) + } + + If (And(UP, 0x40000000)) { + Notify(S30, 0x1) + } + + If (And(UP, 0x80000000)) { + Notify(S31, 0x1) + } + + /* Down status */ + If (And(DOWN, 0x1)) { + Notify(S0, 0x3) + } + + If (And(DOWN, 0x2)) { + Notify(S1, 0x3) + } + + If (And(DOWN, 0x4)) { + Notify(S2, 0x3) + } + + If (And(DOWN, 0x8)) { + Notify(S3, 0x3) + } + + If (And(DOWN, 0x10)) { + Notify(S4, 0x3) + } + + If (And(DOWN, 0x20)) { + Notify(S5, 0x3) + } + + If (And(DOWN, 0x40)) { + Notify(S6, 0x3) + } + + If (And(DOWN, 0x80)) { + Notify(S7, 0x3) + } + + If (And(DOWN, 0x0100)) { + Notify(S8, 0x3) + } + + If (And(DOWN, 0x0200)) { + Notify(S9, 0x3) + } + + If (And(DOWN, 0x0400)) { + Notify(S10, 0x3) + } + + If (And(DOWN, 0x0800)) { + Notify(S11, 0x3) + } + + If (And(DOWN, 0x1000)) { + Notify(S12, 0x3) + } + + If (And(DOWN, 0x2000)) { + Notify(S13, 0x3) + } + + If (And(DOWN, 0x4000)) { + Notify(S14, 0x3) + } + + If (And(DOWN, 0x8000)) { + Notify(S15, 0x3) + } + + If (And(DOWN, 0x10000)) { + Notify(S16, 0x3) + } + + If (And(DOWN, 0x20000)) { + Notify(S17, 0x3) + } + + If (And(DOWN, 0x40000)) { + Notify(S18, 0x3) + } + + If (And(DOWN, 0x80000)) { + Notify(S19, 0x3) + } + + If (And(DOWN, 0x100000)) { + Notify(S20, 0x3) + } + + If (And(DOWN, 0x200000)) { + Notify(S21, 0x3) + } + + If (And(DOWN, 0x400000)) { + Notify(S22, 0x3) + } + + If (And(DOWN, 0x800000)) { + Notify(S23, 0x3) + } + + If (And(DOWN, 0x1000000)) { + Notify(S24, 0x3) + } + + If (And(DOWN, 0x2000000)) { + Notify(S25, 0x3) + } + + If (And(DOWN, 0x4000000)) { + Notify(S26, 0x3) + } + + If (And(DOWN, 0x8000000)) { + Notify(S27, 0x3) + } + + If (And(DOWN, 0x10000000)) { + Notify(S28, 0x3) + } + + If (And(DOWN, 0x20000000)) { + Notify(S29, 0x3) + } + + If (And(DOWN, 0x40000000)) { + Notify(S30, 0x3) + } + + If (And(DOWN, 0x80000000)) { + Notify(S31, 0x3) + } Index: kvm-userspace.pci2/bios/acpi-irq-routing.dsl =================================================================== --- /dev/null +++ kvm-userspace.pci2/bios/acpi-irq-routing.dsl @@ -0,0 +1,203 @@ + External(LNKA, DeviceObj) + External(LNKB, DeviceObj) + External(LNKC, DeviceObj) + External(LNKD, DeviceObj) + + Name(_PRT, Package() { + /* PCI IRQ routing table, example from ACPI 2.0a specification, + section 6.2.8.1 */ + /* Note: we provide the same info as the PCI routing + table of the Bochs BIOS */ + + // PCI Slot 0 + Package() {0x0000ffff, 0, LNKD, 0}, + Package() {0x0000ffff, 1, LNKA, 0}, + Package() {0x0000ffff, 2, LNKB, 0}, + Package() {0x0000ffff, 3, LNKC, 0}, + + // PCI Slot 1 + Package() {0x0001ffff, 0, LNKA, 0}, + Package() {0x0001ffff, 1, LNKB, 0}, + Package() {0x0001ffff, 2, LNKC, 0}, + Package() {0x0001ffff, 3, LNKD, 0}, + + // PCI Slot 2 + Package() {0x0002ffff, 0, LNKB, 0}, + Package() {0x0002ffff, 1, LNKC, 0}, + Package() {0x0002ffff, 2, LNKD, 0}, + Package() {0x0002ffff, 3, LNKA, 0}, + + // PCI Slot 3 + Package() {0x0003ffff, 0, LNKC, 0}, + Package() {0x0003ffff, 1, LNKD, 0}, + Package() {0x0003ffff, 2, LNKA, 0}, + Package() {0x0003ffff, 3, LNKB, 0}, + + // PCI Slot 4 + Package() {0x0004ffff, 0, LNKD, 0}, + Package() {0x0004ffff, 1, LNKA, 0}, + Package() {0x0004ffff, 2, LNKB, 0}, + Package() {0x0004ffff, 3, LNKC, 0}, + + // PCI Slot 5 + Package() {0x0005ffff, 0, LNKA, 0}, + Package() {0x0005ffff, 1, LNKB, 0}, + Package() {0x0005ffff, 2, LNKC, 0}, + Package() {0x0005ffff, 3, LNKD, 0}, + + // PCI Slot 6 + Package() {0x0006ffff, 0, LNKB, 0}, + Package() {0x0006ffff, 1, LNKC, 0}, + Package() {0x0006ffff, 2, LNKD, 0}, + Package() {0x0006ffff, 3, LNKA, 0}, + + // PCI Slot 7 + Package() {0x0007ffff, 0, LNKC, 0}, + Package() {0x0007ffff, 1, LNKD, 0}, + Package() {0x0007ffff, 2, LNKA, 0}, + Package() {0x0007ffff, 3, LNKB, 0}, + + // PCI Slot 8 + Package() {0x0008ffff, 0, LNKD, 0}, + Package() {0x0008ffff, 1, LNKA, 0}, + Package() {0x0008ffff, 2, LNKB, 0}, + Package() {0x0008ffff, 3, LNKC, 0}, + + // PCI Slot 9 + Package() {0x0009ffff, 0, LNKA, 0}, + Package() {0x0009ffff, 1, LNKB, 0}, + Package() {0x0009ffff, 2, LNKC, 0}, + Package() {0x0009ffff, 3, LNKD, 0}, + + // PCI Slot 10 + Package() {0x000affff, 0, LNKB, 0}, + Package() {0x000affff, 1, LNKC, 0}, + Package() {0x000affff, 2, LNKD, 0}, + Package() {0x000affff, 3, LNKA, 0}, + + // PCI Slot 11 + Package() {0x000bffff, 0, LNKC, 0}, + Package() {0x000bffff, 1, LNKD, 0}, + Package() {0x000bffff, 2, LNKA, 0}, + Package() {0x000bffff, 3, LNKB, 0}, + + // PCI Slot 12 + Package() {0x000cffff, 0, LNKD, 0}, + Package() {0x000cffff, 1, LNKA, 0}, + Package() {0x000cffff, 2, LNKB, 0}, + Package() {0x000cffff, 3, LNKC, 0}, + + // PCI Slot 13 + Package() {0x000dffff, 0, LNKA, 0}, + Package() {0x000dffff, 1, LNKB, 0}, + Package() {0x000dffff, 2, LNKC, 0}, + Package() {0x000dffff, 3, LNKD, 0}, + + // PCI Slot 14 + Package() {0x000effff, 0, LNKB, 0}, + Package() {0x000effff, 1, LNKC, 0}, + Package() {0x000effff, 2, LNKD, 0}, + Package() {0x000effff, 3, LNKA, 0}, + + // PCI Slot 15 + Package() {0x000fffff, 0, LNKC, 0}, + Package() {0x000fffff, 1, LNKD, 0}, + Package() {0x000fffff, 2, LNKA, 0}, + Package() {0x000fffff, 3, LNKB, 0}, + + // PCI Slot 16 + Package() {0x0010ffff, 0, LNKD, 0}, + Package() {0x0010ffff, 1, LNKA, 0}, + Package() {0x0010ffff, 2, LNKB, 0}, + Package() {0x0010ffff, 3, LNKC, 0}, + + // PCI Slot 17 + Package() {0x0011ffff, 0, LNKA, 0}, + Package() {0x0011ffff, 1, LNKB, 0}, + Package() {0x0011ffff, 2, LNKC, 0}, + Package() {0x0011ffff, 3, LNKD, 0}, + + // PCI Slot 18 + Package() {0x0012ffff, 0, LNKB, 0}, + Package() {0x0012ffff, 1, LNKC, 0}, + Package() {0x0012ffff, 2, LNKD, 0}, + Package() {0x0012ffff, 3, LNKA, 0}, + + // PCI Slot 19 + Package() {0x0013ffff, 0, LNKC, 0}, + Package() {0x0013ffff, 1, LNKD, 0}, + Package() {0x0013ffff, 2, LNKA, 0}, + Package() {0x0013ffff, 3, LNKB, 0}, + + // PCI Slot 20 + Package() {0x0014ffff, 0, LNKD, 0}, + Package() {0x0014ffff, 1, LNKA, 0}, + Package() {0x0014ffff, 2, LNKB, 0}, + Package() {0x0014ffff, 3, LNKC, 0}, + + // PCI Slot 21 + Package() {0x0015ffff, 0, LNKA, 0}, + Package() {0x0015ffff, 1, LNKB, 0}, + Package() {0x0015ffff, 2, LNKC, 0}, + Package() {0x0015ffff, 3, LNKD, 0}, + + // PCI Slot 22 + Package() {0x0016ffff, 0, LNKB, 0}, + Package() {0x0016ffff, 1, LNKC, 0}, + Package() {0x0016ffff, 2, LNKD, 0}, + Package() {0x0016ffff, 3, LNKA, 0}, + + // PCI Slot 23 + Package() {0x0017ffff, 0, LNKC, 0}, + Package() {0x0017ffff, 1, LNKD, 0}, + Package() {0x0017ffff, 2, LNKA, 0}, + Package() {0x0017ffff, 3, LNKB, 0}, + + // PCI Slot 24 + Package() {0x0018ffff, 0, LNKD, 0}, + Package() {0x0018ffff, 1, LNKA, 0}, + Package() {0x0018ffff, 2, LNKB, 0}, + Package() {0x0018ffff, 3, LNKC, 0}, + + // PCI Slot 25 + Package() {0x0019ffff, 0, LNKA, 0}, + Package() {0x0019ffff, 1, LNKB, 0}, + Package() {0x0019ffff, 2, LNKC, 0}, + Package() {0x0019ffff, 3, LNKD, 0}, + + // PCI Slot 26 + Package() {0x001affff, 0, LNKB, 0}, + Package() {0x001affff, 1, LNKC, 0}, + Package() {0x001affff, 2, LNKD, 0}, + Package() {0x001affff, 3, LNKA, 0}, + + // PCI Slot 27 + Package() {0x001bffff, 0, LNKC, 0}, + Package() {0x001bffff, 1, LNKD, 0}, + Package() {0x001bffff, 2, LNKA, 0}, + Package() {0x001bffff, 3, LNKB, 0}, + + // PCI Slot 28 + Package() {0x001cffff, 0, LNKD, 0}, + Package() {0x001cffff, 1, LNKA, 0}, + Package() {0x001cffff, 2, LNKB, 0}, + Package() {0x001cffff, 3, LNKC, 0}, + + // PCI Slot 29 + Package() {0x001dffff, 0, LNKA, 0}, + Package() {0x001dffff, 1, LNKB, 0}, + Package() {0x001dffff, 2, LNKC, 0}, + Package() {0x001dffff, 3, LNKD, 0}, + + // PCI Slot 30 + Package() {0x001effff, 0, LNKB, 0}, + Package() {0x001effff, 1, LNKC, 0}, + Package() {0x001effff, 2, LNKD, 0}, + Package() {0x001effff, 3, LNKA, 0}, + + // PCI Slot 31 + Package() {0x001fffff, 0, LNKC, 0}, + Package() {0x001fffff, 1, LNKD, 0}, + Package() {0x001fffff, 2, LNKA, 0}, + Package() {0x001fffff, 3, LNKB, 0}, + }) Index: kvm-userspace.pci2/bios/acpi-pci-slots.dsl =================================================================== --- /dev/null +++ kvm-userspace.pci2/bios/acpi-pci-slots.dsl @@ -0,0 +1,385 @@ + Device (S0) { // Slot 0 + Name (_ADR, 0x00000000) + Method (_EJ0,1) { + Store(0x1, BEJ) + Return (0x0) + } + Method(_SUN) { + Add (SUN1, 0, Local0) + Return (Local0) + } + } + + Device (S1) { // Slot 1 + Name (_ADR, 0x00010000) + Method (_EJ0,1) { + Store(0x2, BEJ) + Return (0x0) + } + Method(_SUN) { + Add (SUN1, 1, Local0) + Return (Local0) + } + } + + Device (S2) { // Slot 2 + Name (_ADR, 0x00020000) + Method (_EJ0,1) { + Store(0x4, BEJ) + Return (0x0) + } + Method(_SUN) { + Add (SUN1, 2, Local0) + Return (Local0) + } + } + + Device (S3) { // Slot 3 + Name (_ADR, 0x00030000) + Method (_EJ0,1) { + Store(0x4, BEJ) + Return (0x0) + } + Method(_SUN) { + Add (SUN1, 3, Local0) + Return (Local0) + } + } + + Device (S4) { // Slot 4 + Name (_ADR, 0x00040000) + Method (_EJ0,1) { + Store(0x4, BEJ) + Return (0x0) + } + Method(_SUN) { + Add (SUN1, 4, Local0) + Return (Local0) + } + } + + Device (S5) { // Slot 5 + Name (_ADR, 0x00050000) + Method (_EJ0,1) { + Store(0x4, BEJ) + Return (0x0) + } + Method(_SUN) { + Add (SUN1, 5, Local0) + Return (Local0) + } + } + + Device (S6) { // Slot 6 + Name (_ADR, 0x00060000) + Method (_EJ0,1) { + Store(0x40, BEJ) + Return (0x0) + } + + Method(_SUN) { + Add (SUN1, 6, Local0) + Return (Local0) + } + } + + Device (S7) { // Slot 7 + Name (_ADR, 0x00070000) + Method (_EJ0,1) { + Store(0x80, BEJ) + Return (0x0) + } + + Method(_SUN) { + Add (SUN1, 7, Local0) + Return (Local0) + } + } + + Device (S8) { // Slot 8 + Name (_ADR, 0x00080000) + Method (_EJ0,1) { + Store(0x100, BEJ) + Return (0x0) + } + Method(_SUN) { + Add (SUN1, 8, Local0) + Return (Local0) + } + } + + Device (S9) { // Slot 9 + Name (_ADR, 0x00090000) + Method (_EJ0,1) { + Store(0x200, BEJ) + Return (0x0) + } + Method(_SUN) { + Add (SUN1, 9, Local0) + Return (Local0) + } + } + + Device (S10) { // Slot 10 + Name (_ADR, 0x000A0000) + Method (_EJ0,1) { + Store(0x400, BEJ) + Return (0x0) + } + Method(_SUN) { + Add (SUN1, 10, Local0) + Return (Local0) + } + } + + Device (S11) { // Slot 11 + Name (_ADR, 0x000B0000) + Method (_EJ0,1) { + Store(0x800, BEJ) + Return (0x0) + } + Method(_SUN) { + Add (SUN1, 11, Local0) + Return (Local0) + } + } + + Device (S12) { // Slot 12 + Name (_ADR, 0x000C0000) + Method (_EJ0,1) { + Store(0x1000, BEJ) + Return (0x0) + } + Method(_SUN) { + Add (SUN1, 12, Local0) + Return (Local0) + } + } + + Device (S13) { // Slot 13 + Name (_ADR, 0x000D0000) + Method (_EJ0,1) { + Store(0x2000, BEJ) + Return (0x0) + } + Method(_SUN) { + Add (SUN1, 13, Local0) + Return (Local0) + } + } + + Device (S14) { // Slot 14 + Name (_ADR, 0x000E0000) + Method (_EJ0,1) { + Store(0x4000, BEJ) + Return (0x0) + } + Method(_SUN) { + Add (SUN1, 14, Local0) + Return (Local0) + } + } + + Device (S15) { // Slot 15 + Name (_ADR, 0x000F0000) + Method (_EJ0,1) { + Store(0x8000, BEJ) + Return (0x0) + } + Method(_SUN) { + Add (SUN1, 15, Local0) + Return (Local0) + } + } + + Device (S16) { // Slot 16 + Name (_ADR, 0x00100000) + Method (_EJ0,1) { + Store(0x10000, BEJ) + Return (0x0) + } + Method(_SUN) { + Add (SUN1, 16, Local0) + Return (Local0) + } + } + + Device (S17) { // Slot 17 + Name (_ADR, 0x00110000) + Method (_EJ0,1) { + Store(0x20000, BEJ) + Return (0x0) + } + Method(_SUN) { + Add (SUN1, 17, Local0) + Return (Local0) + } + } + + Device (S18) { // Slot 18 + Name (_ADR, 0x00120000) + Method (_EJ0,1) { + Store(0x40000, BEJ) + Return (0x0) + } + Method(_SUN) { + Add (SUN1, 18, Local0) + Return (Local0) + } + } + + Device (S19) { // Slot 19 + Name (_ADR, 0x00130000) + Method (_EJ0,1) { + Store(0x80000, BEJ) + Return (0x0) + } + Method(_SUN) { + Add (SUN1, 19, Local0) + Return (Local0) + } + } + + Device (S20) { // Slot 20 + Name (_ADR, 0x00140000) + Method (_EJ0,1) { + Store(0x100000, BEJ) + Return (0x0) + } + Method(_SUN) { + Add (SUN1, 20, Local0) + Return (Local0) + } + } + + Device (S21) { // Slot 21 + Name (_ADR, 0x00150000) + Method (_EJ0,1) { + Store(0x200000, BEJ) + Return (0x0) + } + Method(_SUN) { + Add (SUN1, 21, Local0) + Return (Local0) + } + } + + Device (S22) { // Slot 22 + Name (_ADR, 0x00160000) + Method (_EJ0,1) { + Store(0x400000, BEJ) + Return (0x0) + } + Method(_SUN) { + Add (SUN1, 22, Local0) + Return (Local0) + } + } + + Device (S23) { // Slot 23 + Name (_ADR, 0x00170000) + Method (_EJ0,1) { + Store(0x800000, BEJ) + Return (0x0) + } + Method(_SUN) { + Add (SUN1, 23, Local0) + Return (Local0) + } + } + + Device (S24) { // Slot 24 + Name (_ADR, 0x00180000) + Method (_EJ0,1) { + Store(0x1000000, BEJ) + Return (0x0) + } + Method(_SUN) { + Add (SUN1, 24, Local0) + Return (Local0) + } + } + + Device (S25) { // Slot 25 + Name (_ADR, 0x00190000) + Method (_EJ0,1) { + Store(0x2000000, BEJ) + Return (0x0) + } + Method(_SUN) { + Add (SUN1, 25, Local0) + Return (Local0) + } + } + + Device (S26) { // Slot 26 + Name (_ADR, 0x001A0000) + Method (_EJ0,1) { + Store(0x4000000, BEJ) + Return (0x0) + } + Method(_SUN) { + Add (SUN1, 26, Local0) + Return (Local0) + } + } + + Device (S27) { // Slot 27 + Name (_ADR, 0x001B0000) + Method (_EJ0,1) { + Store(0x8000000, BEJ) + Return (0x0) + } + Method(_SUN) { + Add (SUN1, 27, Local0) + Return (Local0) + } + } + + Device (S28) { // Slot 28 + Name (_ADR, 0x001C0000) + Method (_EJ0,1) { + Store(0x10000000, BEJ) + Return (0x0) + } + Method(_SUN) { + Add (SUN1, 28, Local0) + Return (Local0) + } + } + + Device (S29) { // Slot 29 + Name (_ADR, 0x001D0000) + Method (_EJ0,1) { + Store(0x20000000, BEJ) + Return (0x0) + } + Method(_SUN) { + Add (SUN1, 29, Local0) + Return (Local0) + } + } + + Device (S30) { // Slot 30 + Name (_ADR, 0x001E0000) + Method (_EJ0,1) { + Store(0x40000000, BEJ) + Return (0x0) + } + Method(_SUN) { + Add (SUN1, 30, Local0) + Return (Local0) + } + } + + Device (S31) { // Slot 31 + Name (_ADR, 0x001F0000) + Method (_EJ0,1) { + Store(0x80000000, BEJ) + Return (0x0) + } + Method(_SUN) { + Add (SUN1, 31, Local0) + Return (Local0) + } + } Index: kvm-userspace.pci2/bios/rombios32.c =================================================================== --- kvm-userspace.pci2.orig/bios/rombios32.c +++ kvm-userspace.pci2/bios/rombios32.c @@ -652,6 +652,30 @@ static void bios_lock_shadow_ram(void) pci_config_writeb(d, 0x59, v); } +static int nr_bridges = 1; +static int current_bridge = 0; + +static void pci_bios_count_p2p(PCIDevice *d) +{ + uint16_t vendor_id, device_id; + + vendor_id = pci_config_readw(d, PCI_VENDOR_ID); + device_id = pci_config_readw(d, PCI_DEVICE_ID); + if (vendor_id == 0x8086 && device_id == 0x244e) + nr_bridges++; +} + +int fls(int i) +{ + int bit; + + for (bit=31; bit >= 0; bit--) + if (i & (1 << bit)) + return bit+1; + + return 0; +} + static void pci_bios_init_bridges(PCIDevice *d) { uint16_t vendor_id, device_id; @@ -681,6 +705,27 @@ static void pci_bios_init_bridges(PCIDev } else if (vendor_id == 0x8086 && device_id == 0x1237) { /* i440 PCI bridge */ bios_shadow_init(d); + } else if (vendor_id == 0x8086 && device_id == 0x244e) { + int len, base; + + len = (0xfebfffff - 0xf0000000) / nr_bridges; + if (len & (len-1)) + len = 1 << fls(len); + + /* memory IO */ + base = (0xf0000000+len) + (current_bridge*len); + base >>= 16; + pci_config_writew(d, 0x20, base); + pci_config_writew(d, 0x22, base); + + /* port IO */ + len = 0x1000; + base = 0x2000 + (current_bridge*len); + base >>= 8; + pci_config_writeb(d, 0x1c, base); + pci_config_writeb(d, 0x1d, base); + + current_bridge++; } } @@ -775,6 +820,8 @@ static void pci_bios_init_device(PCIDevi pci_set_io_region_addr(d, 0, 0x80800000); } break; + case 0x0604: + break; default: default_map: /* default memory mappings */ @@ -859,6 +906,8 @@ void pci_bios_init(void) if (pci_bios_bigmem_addr < 0x90000000) pci_bios_bigmem_addr = 0x90000000; + pci_for_each_device(pci_bios_count_p2p); + pci_for_each_device(pci_bios_init_bridges); pci_for_each_device(pci_bios_init_device); Index: kvm-userspace.pci2/qemu/hw/acpi.c =================================================================== --- kvm-userspace.pci2.orig/qemu/hw/acpi.c +++ kvm-userspace.pci2/qemu/hw/acpi.c @@ -557,10 +557,11 @@ struct gpe_regs { struct pci_status { uint32_t up; uint32_t down; + unsigned long base; }; static struct gpe_regs gpe; -static struct pci_status pci0_status; +static struct pci_status pci_bus_status[4]; static uint32_t gpe_readb(void *opaque, uint32_t addr) { @@ -630,16 +631,19 @@ static void gpe_writeb(void *opaque, uin static uint32_t pcihotplug_read(void *opaque, uint32_t addr) { - uint32_t val = 0; struct pci_status *g = opaque; - switch (addr) { - case PCI_BASE: + uint32_t val, offset; + + offset = addr - g->base; + switch (offset) { + case 0: val = g->up; break; - case PCI_BASE + 4: + case 4: val = g->down; break; default: + val = 0; break; } @@ -652,11 +656,13 @@ static uint32_t pcihotplug_read(void *op static void pcihotplug_write(void *opaque, uint32_t addr, uint32_t val) { struct pci_status *g = opaque; - switch (addr) { - case PCI_BASE: + uint32_t offset = addr - g->base; + + switch (offset) { + case 0: g->up = val; break; - case PCI_BASE + 4: + case 4: g->down = val; break; } @@ -676,9 +682,13 @@ static uint32_t pciej_read(void *opaque, static void pciej_write(void *opaque, uint32_t addr, uint32_t val) { - int slot = ffs(val) - 1; + struct pci_status *g = opaque; + int slot, bus; - device_hot_remove_success(0, slot); + bus = (g->base - PCI_BASE) / 12; + slot = ffs(val) - 1; + + device_hot_remove_success(bus, slot); #if defined(DEBUG) printf("pciej write %lx <== %d\n", addr, val); @@ -689,17 +699,25 @@ static const char *model; void qemu_system_hot_add_init(const char *cpu_model) { + int i; + register_ioport_write(GPE_BASE, 4, 1, gpe_writeb, &gpe); register_ioport_read(GPE_BASE, 4, 1, gpe_readb, &gpe); register_ioport_write(PROC_BASE, 4, 1, gpe_writeb, &gpe); register_ioport_read(PROC_BASE, 4, 1, gpe_readb, &gpe); - register_ioport_write(PCI_BASE, 8, 4, pcihotplug_write, &pci0_status); - register_ioport_read(PCI_BASE, 8, 4, pcihotplug_read, &pci0_status); + for (i = 0; i < 4; i++) { + struct pci_status *pci_status = &pci_bus_status[i]; + unsigned long base = PCI_BASE + (i*12); + + pci_status->base = base; + register_ioport_write(base, 8, 4, pcihotplug_write, pci_status); + register_ioport_read(base, 8, 4, pcihotplug_read, pci_status); + register_ioport_write(base+8, 4, 4, pciej_write, pci_status); + register_ioport_read(base+8, 4, 4, pciej_read, pci_status); + } - register_ioport_write(PCI_EJ_BASE, 4, 4, pciej_write, NULL); - register_ioport_read(PCI_EJ_BASE, 4, 4, pciej_read, NULL); model = cpu_model; } @@ -745,28 +763,34 @@ void qemu_system_cpu_hot_add(int cpu, in } #endif -static void enable_device(struct pci_status *p, struct gpe_regs *g, int slot) +static void enable_device(struct pci_status *p, struct gpe_regs *g, int bus, int slot) { - g->sts |= 2; - g->en |= 2; + int gpe_bit = (1 << (bus+1)); + + g->sts |= gpe_bit; + g->en |= gpe_bit; p->up |= (1 << slot); } -static void disable_device(struct pci_status *p, struct gpe_regs *g, int slot) +static void disable_device(struct pci_status *p, struct gpe_regs *g, int bus, int slot) { - g->sts |= 2; - g->en |= 2; + int gpe_bit = (1 << (bus+1)); + + g->sts |= gpe_bit; + g->en |= gpe_bit; p->down |= (1 << slot); } void qemu_system_device_hot_add(int pcibus, int slot, int state) { + struct pci_status *pci_status = &pci_bus_status[pcibus]; + qemu_set_irq(pm_state->irq, 1); - pci0_status.up = 0; - pci0_status.down = 0; + pci_status->up = 0; + pci_status->down = 0; if (state) - enable_device(&pci0_status, &gpe, slot); + enable_device(pci_status, &gpe, pcibus, slot); else - disable_device(&pci0_status, &gpe, slot); + disable_device(pci_status, &gpe, pcibus, slot); qemu_set_irq(pm_state->irq, 0); } Index: kvm-userspace.pci2/qemu/hw/piix_pci.c =================================================================== --- kvm-userspace.pci2.orig/qemu/hw/piix_pci.c +++ kvm-userspace.pci2/qemu/hw/piix_pci.c @@ -171,7 +171,7 @@ static int i440fx_load(QEMUFile* f, void PCIBus *i440fx_init(PCIDevice **pi440fx_state, qemu_irq *pic) { - PCIBus *b; + PCIBus *b, *b1, *b2, *b3; PCIDevice *d; I440FXState *s; @@ -203,6 +203,13 @@ PCIBus *i440fx_init(PCIDevice **pi440fx_ d->config[0x72] = 0x02; /* SMRAM */ + b1 = pci_bridge_init(s->bus, 24, 0x8086244e, pci_slot_get_pirq, + "first PCI-to-PCI bridge "); + b2 = pci_bridge_in... [truncated message content] |
From: Jan K. <jan...@we...> - 2008-04-25 00:33:52
|
Hi, I saw kvm-userspace recently merged qemu's new CPU_INTERRUPT_NMI support. But the required infrastructure to use this in kvm mode is not yet visible. Is anyone working on this? Sheng? IIRC, you once said to work on it. Currently I just need the basic mechanism for injecting NMIs into the guest (from special hardware emulation), no full support for in-kernel [A]PICs. But before starting some quick&dirty hack, I would like to know if someone already has a patch pending and is able to share even just preliminary results. Thanks, Jan |
From: Chris L. <cla...@re...> - 2008-04-24 22:13:13
|
Avi Kivity wrote: > Now it uses %rsi instead of %esi, and any junk in the upper bits will > cause the ja to be taken. > > We need to get a reduced testcase to the gcc folks, this is a serious > bug. Any changes in the code to work around this would be fragile. > Avi, I've now filed a bug in the upstream gcc database: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=36040 And I came up with a reduced test case, available here: http://people.redhat.com/clalance/rsi-test-case.tar.bz2 If I compile the code in the above and look at the disassembly, it shows the problem; however, I can't reproduce the bug by actually running the code. I suspect the %rsi register is always 0 when we start in this userland code, so I never run into the bogus ja, but I just thought I'd mention it. Chris Lalancette |
From: Andi K. <an...@fi...> - 2008-04-24 19:43:14
|
David Miller <da...@da...> writes: > I'm fine with adding the list, but we don't do mass subscribes like > that, and this rule applies to every list which moves to vger from > somewhere else. > > People will need to subscribe themselves to the new list. Can someone please resubscribe gmane too for us gmane users when the move occurs? Thanks, -Andi |
From: Andrea A. <an...@qu...> - 2008-04-24 17:41:52
|
On Thu, Apr 24, 2008 at 05:39:43PM +0200, Andrea Arcangeli wrote: > There's at least one small issue I noticed so far, that while _release > don't need to care about _register, but _unregister definitely need to > care about _register. I've to take the mmap_sem in addition or in In the end the best is to use the spinlock around those list_add/list_del they all run in O(1) with the hlist and they take a few asm insn. This also avoids to take the mmap_sem in exit_mmap, at exit_mmap time nobody should need to use mmap_sem anymore, it might work but this looks cleaner. The lock is dynamically allocated only when the notifiers are registered, so the few bytes taken by it aren't relevant. A full new update will some become visible here: http://www.kernel.org/pub/linux/kernel/people/andrea/patches/v2.6/2.6.25/mmu-notifier-v14-pre3/ Please have a close look again. Your help is extremely appreciated and very helpful as usual! Thanks a lot. diff -urN xxx/include/linux/mmu_notifier.h xx/include/linux/mmu_notifier.h --- xxx/include/linux/mmu_notifier.h 2008-04-24 19:41:15.000000000 +0200 +++ xx/include/linux/mmu_notifier.h 2008-04-24 19:38:37.000000000 +0200 @@ -15,7 +15,7 @@ struct hlist_head list; struct srcu_struct srcu; /* to serialize mmu_notifier_unregister against mmu_notifier_release */ - spinlock_t unregister_lock; + spinlock_t lock; }; struct mmu_notifier_ops { diff -urN xxx/mm/memory.c xx/mm/memory.c --- xxx/mm/memory.c 2008-04-24 19:41:15.000000000 +0200 +++ xx/mm/memory.c 2008-04-24 19:38:37.000000000 +0200 @@ -605,16 +605,13 @@ * readonly mappings. The tradeoff is that copy_page_range is more * efficient than faulting. */ - ret = 0; if (!(vma->vm_flags & (VM_HUGETLB|VM_NONLINEAR|VM_PFNMAP|VM_INSERTPAGE))) { if (!vma->anon_vma) - goto out; + return 0; } - if (unlikely(is_vm_hugetlb_page(vma))) { - ret = copy_hugetlb_page_range(dst_mm, src_mm, vma); - goto out; - } + if (is_vm_hugetlb_page(vma)) + return copy_hugetlb_page_range(dst_mm, src_mm, vma); if (is_cow_mapping(vma->vm_flags)) mmu_notifier_invalidate_range_start(src_mm, addr, end); @@ -636,7 +633,6 @@ if (is_cow_mapping(vma->vm_flags)) mmu_notifier_invalidate_range_end(src_mm, vma->vm_start, end); -out: return ret; } diff -urN xxx/mm/mmap.c xx/mm/mmap.c --- xxx/mm/mmap.c 2008-04-24 19:41:15.000000000 +0200 +++ xx/mm/mmap.c 2008-04-24 19:38:37.000000000 +0200 @@ -2381,7 +2381,7 @@ if (data->nr_anon_vma_locks) mm_unlock_vfree(data->anon_vma_locks, data->nr_anon_vma_locks); - if (data->i_mmap_locks) + if (data->nr_i_mmap_locks) mm_unlock_vfree(data->i_mmap_locks, data->nr_i_mmap_locks); } diff -urN xxx/mm/mmu_notifier.c xx/mm/mmu_notifier.c --- xxx/mm/mmu_notifier.c 2008-04-24 19:41:15.000000000 +0200 +++ xx/mm/mmu_notifier.c 2008-04-24 19:31:23.000000000 +0200 @@ -24,22 +24,16 @@ * zero). All other tasks of this mm already quit so they can't invoke * mmu notifiers anymore. This can run concurrently only against * mmu_notifier_unregister and it serializes against it with the - * unregister_lock in addition to RCU. struct mmu_notifier_mm can't go - * away from under us as the exit_mmap holds a mm_count pin itself. - * - * The ->release method can't allow the module to be unloaded, the - * module can only be unloaded after mmu_notifier_unregister run. This - * is because the release method has to run the ret instruction to - * return back here, and so it can't allow the ret instruction to be - * freed. + * mmu_notifier_mm->lock in addition to RCU. struct mmu_notifier_mm + * can't go away from under us as exit_mmap holds a mm_count pin + * itself. */ void __mmu_notifier_release(struct mm_struct *mm) { struct mmu_notifier *mn; int srcu; - srcu = srcu_read_lock(&mm->mmu_notifier_mm->srcu); - spin_lock(&mm->mmu_notifier_mm->unregister_lock); + spin_lock(&mm->mmu_notifier_mm->lock); while (unlikely(!hlist_empty(&mm->mmu_notifier_mm->list))) { mn = hlist_entry(mm->mmu_notifier_mm->list.first, struct mmu_notifier, @@ -52,23 +46,28 @@ */ hlist_del_init(&mn->hlist); /* + * SRCU here will block mmu_notifier_unregister until + * ->release returns. + */ + srcu = srcu_read_lock(&mm->mmu_notifier_mm->srcu); + spin_unlock(&mm->mmu_notifier_mm->lock); + /* * if ->release runs before mmu_notifier_unregister it * must be handled as it's the only way for the driver - * to flush all existing sptes before the pages in the - * mm are freed. + * to flush all existing sptes and stop the driver + * from establishing any more sptes before all the + * pages in the mm are freed. */ - spin_unlock(&mm->mmu_notifier_mm->unregister_lock); - /* SRCU will block mmu_notifier_unregister */ mn->ops->release(mn, mm); - spin_lock(&mm->mmu_notifier_mm->unregister_lock); + srcu_read_unlock(&mm->mmu_notifier_mm->srcu, srcu); + spin_lock(&mm->mmu_notifier_mm->lock); } - spin_unlock(&mm->mmu_notifier_mm->unregister_lock); - srcu_read_unlock(&mm->mmu_notifier_mm->srcu, srcu); + spin_unlock(&mm->mmu_notifier_mm->lock); /* - * Wait ->release if mmu_notifier_unregister run list_del_rcu. - * srcu can't go away from under us because one mm_count is - * hold by exit_mmap. + * Wait ->release if mmu_notifier_unregister is running it. + * The mmu_notifier_mm can't go away from under us because one + * mm_count is hold by exit_mmap. */ synchronize_srcu(&mm->mmu_notifier_mm->srcu); } @@ -177,11 +176,19 @@ goto out_unlock; } INIT_HLIST_HEAD(&mm->mmu_notifier_mm->list); - spin_lock_init(&mm->mmu_notifier_mm->unregister_lock); + spin_lock_init(&mm->mmu_notifier_mm->lock); } atomic_inc(&mm->mm_count); + /* + * Serialize the update against mmu_notifier_unregister. A + * side note: mmu_notifier_release can't run concurrently with + * us because we hold the mm_users pin (either implicitly as + * current->mm or explicitly with get_task_mm() or similar). + */ + spin_lock(&mm->mmu_notifier_mm->lock); hlist_add_head_rcu(&mn->hlist, &mm->mmu_notifier_mm->list); + spin_unlock(&mm->mmu_notifier_mm->lock); out_unlock: mm_unlock(mm, &data); out: @@ -215,23 +222,32 @@ BUG_ON(atomic_read(&mm->mm_count) <= 0); - srcu = srcu_read_lock(&mm->mmu_notifier_mm->srcu); - spin_lock(&mm->mmu_notifier_mm->unregister_lock); + spin_lock(&mm->mmu_notifier_mm->lock); if (!hlist_unhashed(&mn->hlist)) { hlist_del_rcu(&mn->hlist); before_release = 1; } - spin_unlock(&mm->mmu_notifier_mm->unregister_lock); if (before_release) /* + * SRCU here will force exit_mmap to wait ->release to finish + * before freeing the pages. + */ + srcu = srcu_read_lock(&mm->mmu_notifier_mm->srcu); + spin_unlock(&mm->mmu_notifier_mm->lock); + if (before_release) { + /* * exit_mmap will block in mmu_notifier_release to * guarantee ->release is called before freeing the * pages. */ mn->ops->release(mn, mm); - srcu_read_unlock(&mm->mmu_notifier_mm->srcu, srcu); + srcu_read_unlock(&mm->mmu_notifier_mm->srcu, srcu); + } - /* wait any running method to finish, including ->release */ + /* + * Wait any running method to finish, of course including + * ->release if it was run by mmu_notifier_relase instead of us. + */ synchronize_srcu(&mm->mmu_notifier_mm->srcu); BUG_ON(atomic_read(&mm->mm_count) <= 0); |