* [PATCH v2 1/5] KVM: Let vcpu structure alignment be determined at runtime
2010-05-02 9:48 [PATCH v2 0/5] Fix EFER.NX=0 with EPT Avi Kivity
@ 2010-05-02 9:48 ` Avi Kivity
2010-05-02 9:48 ` [PATCH v2 2/5] KVM: VMX: Add definition for msr autoload entry Avi Kivity
` (4 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Avi Kivity @ 2010-05-02 9:48 UTC (permalink / raw)
To: kvm; +Cc: Marcelo Tosatti
vmx and svm vcpus have different contents and therefore may have different
alignmment requirements. Let each specify its required alignment.
Signed-off-by: Avi Kivity <avi@redhat.com>
---
arch/ia64/kvm/vmm.c | 2 +-
arch/powerpc/kvm/44x.c | 2 +-
arch/powerpc/kvm/book3s.c | 3 ++-
arch/powerpc/kvm/e500.c | 2 +-
arch/s390/kvm/kvm-s390.c | 2 +-
arch/x86/kvm/svm.c | 2 +-
arch/x86/kvm/vmx.c | 3 ++-
include/linux/kvm_host.h | 2 +-
virt/kvm/kvm_main.c | 7 ++++---
9 files changed, 14 insertions(+), 11 deletions(-)
diff --git a/arch/ia64/kvm/vmm.c b/arch/ia64/kvm/vmm.c
index 7a62f75..f0b9cac 100644
--- a/arch/ia64/kvm/vmm.c
+++ b/arch/ia64/kvm/vmm.c
@@ -51,7 +51,7 @@ static int __init kvm_vmm_init(void)
vmm_fpswa_interface = fpswa_interface;
/*Register vmm data to kvm side*/
- return kvm_init(&vmm_info, 1024, THIS_MODULE);
+ return kvm_init(&vmm_info, 1024, 0, THIS_MODULE);
}
static void __exit kvm_vmm_exit(void)
diff --git a/arch/powerpc/kvm/44x.c b/arch/powerpc/kvm/44x.c
index 689a57c..73c0a3f 100644
--- a/arch/powerpc/kvm/44x.c
+++ b/arch/powerpc/kvm/44x.c
@@ -147,7 +147,7 @@ static int __init kvmppc_44x_init(void)
if (r)
return r;
- return kvm_init(NULL, sizeof(struct kvmppc_vcpu_44x), THIS_MODULE);
+ return kvm_init(NULL, sizeof(struct kvmppc_vcpu_44x), 0, THIS_MODULE);
}
static void __exit kvmppc_44x_exit(void)
diff --git a/arch/powerpc/kvm/book3s.c b/arch/powerpc/kvm/book3s.c
index 28e785f..11f226f 100644
--- a/arch/powerpc/kvm/book3s.c
+++ b/arch/powerpc/kvm/book3s.c
@@ -1385,7 +1385,8 @@ int __kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
static int kvmppc_book3s_init(void)
{
- return kvm_init(NULL, sizeof(struct kvmppc_vcpu_book3s), THIS_MODULE);
+ return kvm_init(NULL, sizeof(struct kvmppc_vcpu_book3s), 0,
+ THIS_MODULE);
}
static void kvmppc_book3s_exit(void)
diff --git a/arch/powerpc/kvm/e500.c b/arch/powerpc/kvm/e500.c
index 669a5c5..bc2b400 100644
--- a/arch/powerpc/kvm/e500.c
+++ b/arch/powerpc/kvm/e500.c
@@ -161,7 +161,7 @@ static int __init kvmppc_e500_init(void)
flush_icache_range(kvmppc_booke_handlers,
kvmppc_booke_handlers + max_ivor + kvmppc_handler_len);
- return kvm_init(NULL, sizeof(struct kvmppc_vcpu_e500), THIS_MODULE);
+ return kvm_init(NULL, sizeof(struct kvmppc_vcpu_e500), 0, THIS_MODULE);
}
static void __init kvmppc_e500_exit(void)
diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c
index ee7c713..8093e6f 100644
--- a/arch/s390/kvm/kvm-s390.c
+++ b/arch/s390/kvm/kvm-s390.c
@@ -752,7 +752,7 @@ gfn_t unalias_gfn(struct kvm *kvm, gfn_t gfn)
static int __init kvm_s390_init(void)
{
int ret;
- ret = kvm_init(NULL, sizeof(struct kvm_vcpu), THIS_MODULE);
+ ret = kvm_init(NULL, sizeof(struct kvm_vcpu), 0, THIS_MODULE);
if (ret)
return ret;
diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
index 889f660..2511664 100644
--- a/arch/x86/kvm/svm.c
+++ b/arch/x86/kvm/svm.c
@@ -3319,7 +3319,7 @@ static struct kvm_x86_ops svm_x86_ops = {
static int __init svm_init(void)
{
return kvm_init(&svm_x86_ops, sizeof(struct vcpu_svm),
- THIS_MODULE);
+ __alignof__(struct vcpu_svm), THIS_MODULE);
}
static void __exit svm_exit(void)
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index 875b785..2e87296 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -4245,7 +4245,8 @@ static int __init vmx_init(void)
set_bit(0, vmx_vpid_bitmap); /* 0 is reserved for host */
- r = kvm_init(&vmx_x86_ops, sizeof(struct vcpu_vmx), THIS_MODULE);
+ r = kvm_init(&vmx_x86_ops, sizeof(struct vcpu_vmx),
+ __alignof__(struct vcpu_vmx), THIS_MODULE);
if (r)
goto out3;
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
index ce027d5..7cb116a 100644
--- a/include/linux/kvm_host.h
+++ b/include/linux/kvm_host.h
@@ -243,7 +243,7 @@ void kvm_vcpu_uninit(struct kvm_vcpu *vcpu);
void vcpu_load(struct kvm_vcpu *vcpu);
void vcpu_put(struct kvm_vcpu *vcpu);
-int kvm_init(void *opaque, unsigned int vcpu_size,
+int kvm_init(void *opaque, unsigned vcpu_size, unsigned vcpu_align,
struct module *module);
void kvm_exit(void);
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index 9ab1a77..f032806 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -2178,7 +2178,7 @@ static void kvm_sched_out(struct preempt_notifier *pn,
kvm_arch_vcpu_put(vcpu);
}
-int kvm_init(void *opaque, unsigned int vcpu_size,
+int kvm_init(void *opaque, unsigned vcpu_size, unsigned vcpu_align,
struct module *module)
{
int r;
@@ -2228,8 +2228,9 @@ int kvm_init(void *opaque, unsigned int vcpu_size,
goto out_free_4;
/* A kmem cache lets us meet the alignment requirements of fx_save. */
- kvm_vcpu_cache = kmem_cache_create("kvm_vcpu", vcpu_size,
- __alignof__(struct kvm_vcpu),
+ if (!vcpu_align)
+ vcpu_align = __alignof__(struct kvm_vcpu);
+ kvm_vcpu_cache = kmem_cache_create("kvm_vcpu", vcpu_size, vcpu_align,
0, NULL);
if (!kvm_vcpu_cache) {
r = -ENOMEM;
--
1.7.0.4
^ permalink raw reply related [flat|nested] 7+ messages in thread* [PATCH v2 2/5] KVM: VMX: Add definition for msr autoload entry
2010-05-02 9:48 [PATCH v2 0/5] Fix EFER.NX=0 with EPT Avi Kivity
2010-05-02 9:48 ` [PATCH v2 1/5] KVM: Let vcpu structure alignment be determined at runtime Avi Kivity
@ 2010-05-02 9:48 ` Avi Kivity
2010-05-02 9:48 ` [PATCH v2 3/5] KVM: VMX: Add definitions for guest and host EFER autoswitch vmcs entries Avi Kivity
` (3 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Avi Kivity @ 2010-05-02 9:48 UTC (permalink / raw)
To: kvm; +Cc: Marcelo Tosatti
Signed-off-by: Avi Kivity <avi@redhat.com>
---
arch/x86/include/asm/vmx.h | 8 +++++++-
1 files changed, 7 insertions(+), 1 deletions(-)
diff --git a/arch/x86/include/asm/vmx.h b/arch/x86/include/asm/vmx.h
index fb9a080..4497318 100644
--- a/arch/x86/include/asm/vmx.h
+++ b/arch/x86/include/asm/vmx.h
@@ -25,6 +25,8 @@
*
*/
+#include <linux/types.h>
+
/*
* Definitions of Primary Processor-Based VM-Execution Controls.
*/
@@ -394,6 +396,10 @@ enum vmcs_field {
#define ASM_VMX_INVEPT ".byte 0x66, 0x0f, 0x38, 0x80, 0x08"
#define ASM_VMX_INVVPID ".byte 0x66, 0x0f, 0x38, 0x81, 0x08"
-
+struct vmx_msr_entry {
+ u32 index;
+ u32 reserved;
+ u64 value;
+} __aligned(16);
#endif
--
1.7.0.4
^ permalink raw reply related [flat|nested] 7+ messages in thread* [PATCH v2 3/5] KVM: VMX: Add definitions for guest and host EFER autoswitch vmcs entries
2010-05-02 9:48 [PATCH v2 0/5] Fix EFER.NX=0 with EPT Avi Kivity
2010-05-02 9:48 ` [PATCH v2 1/5] KVM: Let vcpu structure alignment be determined at runtime Avi Kivity
2010-05-02 9:48 ` [PATCH v2 2/5] KVM: VMX: Add definition for msr autoload entry Avi Kivity
@ 2010-05-02 9:48 ` Avi Kivity
2010-05-02 9:48 ` [PATCH v2 4/5] KVM: VMX: Add facility to atomically switch MSRs on guest entry/exit Avi Kivity
` (2 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Avi Kivity @ 2010-05-02 9:48 UTC (permalink / raw)
To: kvm; +Cc: Marcelo Tosatti
Signed-off-by: Avi Kivity <avi@redhat.com>
---
arch/x86/include/asm/vmx.h | 4 ++++
1 files changed, 4 insertions(+), 0 deletions(-)
diff --git a/arch/x86/include/asm/vmx.h b/arch/x86/include/asm/vmx.h
index 4497318..9e6779f 100644
--- a/arch/x86/include/asm/vmx.h
+++ b/arch/x86/include/asm/vmx.h
@@ -122,6 +122,8 @@ enum vmcs_field {
GUEST_IA32_DEBUGCTL_HIGH = 0x00002803,
GUEST_IA32_PAT = 0x00002804,
GUEST_IA32_PAT_HIGH = 0x00002805,
+ GUEST_IA32_EFER = 0x00002806,
+ GUEST_IA32_EFER_HIGH = 0x00002807,
GUEST_PDPTR0 = 0x0000280a,
GUEST_PDPTR0_HIGH = 0x0000280b,
GUEST_PDPTR1 = 0x0000280c,
@@ -132,6 +134,8 @@ enum vmcs_field {
GUEST_PDPTR3_HIGH = 0x00002811,
HOST_IA32_PAT = 0x00002c00,
HOST_IA32_PAT_HIGH = 0x00002c01,
+ HOST_IA32_EFER = 0x00002c02,
+ HOST_IA32_EFER_HIGH = 0x00002c03,
PIN_BASED_VM_EXEC_CONTROL = 0x00004000,
CPU_BASED_VM_EXEC_CONTROL = 0x00004002,
EXCEPTION_BITMAP = 0x00004004,
--
1.7.0.4
^ permalink raw reply related [flat|nested] 7+ messages in thread* [PATCH v2 4/5] KVM: VMX: Add facility to atomically switch MSRs on guest entry/exit
2010-05-02 9:48 [PATCH v2 0/5] Fix EFER.NX=0 with EPT Avi Kivity
` (2 preceding siblings ...)
2010-05-02 9:48 ` [PATCH v2 3/5] KVM: VMX: Add definitions for guest and host EFER autoswitch vmcs entries Avi Kivity
@ 2010-05-02 9:48 ` Avi Kivity
2010-05-02 9:48 ` [PATCH v2 5/5] KVM: VMX: Atomically switch efer if EPT && !EFER.NX Avi Kivity
2010-05-06 19:43 ` [PATCH v2 0/5] Fix EFER.NX=0 with EPT Marcelo Tosatti
5 siblings, 0 replies; 7+ messages in thread
From: Avi Kivity @ 2010-05-02 9:48 UTC (permalink / raw)
To: kvm; +Cc: Marcelo Tosatti
Some guest msr values cannot be used on the host (for example. EFER.NX=0),
so we need to switch them atomically during guest entry or exit.
Add a facility to program the vmx msr autoload registers accordingly.
Signed-off-by: Avi Kivity <avi@redhat.com>
---
arch/x86/kvm/vmx.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 49 insertions(+), 0 deletions(-)
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index 2e87296..ae22dcf 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -98,6 +98,8 @@ module_param(ple_gap, int, S_IRUGO);
static int ple_window = KVM_VMX_DEFAULT_PLE_WINDOW;
module_param(ple_window, int, S_IRUGO);
+#define NR_AUTOLOAD_MSRS 1
+
struct vmcs {
u32 revision_id;
u32 abort;
@@ -125,6 +127,11 @@ struct vcpu_vmx {
u64 msr_guest_kernel_gs_base;
#endif
struct vmcs *vmcs;
+ struct msr_autoload {
+ unsigned nr;
+ struct vmx_msr_entry guest[NR_AUTOLOAD_MSRS];
+ struct vmx_msr_entry host[NR_AUTOLOAD_MSRS];
+ } msr_autoload;
struct {
int loaded;
u16 fs_sel, gs_sel, ldt_sel;
@@ -595,6 +602,46 @@ static void update_exception_bitmap(struct kvm_vcpu *vcpu)
vmcs_write32(EXCEPTION_BITMAP, eb);
}
+static void clear_atomic_switch_msr(struct vcpu_vmx *vmx, unsigned msr)
+{
+ unsigned i;
+ struct msr_autoload *m = &vmx->msr_autoload;
+
+ for (i = 0; i < m->nr; ++i)
+ if (m->guest[i].index == msr)
+ break;
+
+ if (i == m->nr)
+ return;
+ --m->nr;
+ m->guest[i] = m->guest[m->nr];
+ m->host[i] = m->host[m->nr];
+ vmcs_write32(VM_ENTRY_MSR_LOAD_COUNT, m->nr);
+ vmcs_write32(VM_EXIT_MSR_LOAD_COUNT, m->nr);
+}
+
+static void add_atomic_switch_msr(struct vcpu_vmx *vmx, unsigned msr,
+ u64 guest_val, u64 host_val)
+{
+ unsigned i;
+ struct msr_autoload *m = &vmx->msr_autoload;
+
+ for (i = 0; i < m->nr; ++i)
+ if (m->guest[i].index == msr)
+ break;
+
+ if (i == m->nr) {
+ ++m->nr;
+ vmcs_write32(VM_ENTRY_MSR_LOAD_COUNT, m->nr);
+ vmcs_write32(VM_EXIT_MSR_LOAD_COUNT, m->nr);
+ }
+
+ m->guest[i].index = msr;
+ m->guest[i].value = guest_val;
+ m->host[i].index = msr;
+ m->host[i].value = host_val;
+}
+
static void reload_tss(void)
{
/*
@@ -2470,7 +2517,9 @@ static int vmx_vcpu_setup(struct vcpu_vmx *vmx)
vmcs_writel(HOST_RIP, kvm_vmx_return); /* 22.2.5 */
vmcs_write32(VM_EXIT_MSR_STORE_COUNT, 0);
vmcs_write32(VM_EXIT_MSR_LOAD_COUNT, 0);
+ vmcs_write64(VM_EXIT_MSR_LOAD_ADDR, __pa(vmx->msr_autoload.host));
vmcs_write32(VM_ENTRY_MSR_LOAD_COUNT, 0);
+ vmcs_write64(VM_ENTRY_MSR_LOAD_ADDR, __pa(vmx->msr_autoload.guest));
rdmsr(MSR_IA32_SYSENTER_CS, host_sysenter_cs, junk);
vmcs_write32(HOST_IA32_SYSENTER_CS, host_sysenter_cs);
--
1.7.0.4
^ permalink raw reply related [flat|nested] 7+ messages in thread* [PATCH v2 5/5] KVM: VMX: Atomically switch efer if EPT && !EFER.NX
2010-05-02 9:48 [PATCH v2 0/5] Fix EFER.NX=0 with EPT Avi Kivity
` (3 preceding siblings ...)
2010-05-02 9:48 ` [PATCH v2 4/5] KVM: VMX: Add facility to atomically switch MSRs on guest entry/exit Avi Kivity
@ 2010-05-02 9:48 ` Avi Kivity
2010-05-06 19:43 ` [PATCH v2 0/5] Fix EFER.NX=0 with EPT Marcelo Tosatti
5 siblings, 0 replies; 7+ messages in thread
From: Avi Kivity @ 2010-05-02 9:48 UTC (permalink / raw)
To: kvm; +Cc: Marcelo Tosatti
When EPT is enabled, we cannot emulate EFER.NX=0 through the shadow page
tables. This causes accesses through ptes with bit 63 set to succeed instead
of failing a reserved bit check.
Signed-off-by: Avi Kivity <avi@redhat.com>
---
v2:
call vmx_set_efer() in exit_lmode() to update the guest msr
arch/x86/kvm/vmx.c | 12 ++++++++++++
1 files changed, 12 insertions(+), 0 deletions(-)
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index ae22dcf..c4f3955 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -678,6 +678,17 @@ static bool update_transition_efer(struct vcpu_vmx *vmx, int efer_offset)
guest_efer |= host_efer & ignore_bits;
vmx->guest_msrs[efer_offset].data = guest_efer;
vmx->guest_msrs[efer_offset].mask = ~ignore_bits;
+
+ clear_atomic_switch_msr(vmx, MSR_EFER);
+ /* On ept, can't emulate nx, and must switch nx atomically */
+ if (enable_ept && ((vmx->vcpu.arch.efer ^ host_efer) & EFER_NX)) {
+ guest_efer = vmx->vcpu.arch.efer;
+ if (!(guest_efer & EFER_LMA))
+ guest_efer &= ~EFER_LME;
+ add_atomic_switch_msr(vmx, MSR_EFER, guest_efer, host_efer);
+ return false;
+ }
+
return true;
}
@@ -1734,6 +1745,7 @@ static void exit_lmode(struct kvm_vcpu *vcpu)
vmcs_write32(VM_ENTRY_CONTROLS,
vmcs_read32(VM_ENTRY_CONTROLS)
& ~VM_ENTRY_IA32E_MODE);
+ vmx_set_efer(vcpu, vcpu->arch.efer);
}
#endif
--
1.7.0.4
^ permalink raw reply related [flat|nested] 7+ messages in thread* Re: [PATCH v2 0/5] Fix EFER.NX=0 with EPT
2010-05-02 9:48 [PATCH v2 0/5] Fix EFER.NX=0 with EPT Avi Kivity
` (4 preceding siblings ...)
2010-05-02 9:48 ` [PATCH v2 5/5] KVM: VMX: Atomically switch efer if EPT && !EFER.NX Avi Kivity
@ 2010-05-06 19:43 ` Marcelo Tosatti
5 siblings, 0 replies; 7+ messages in thread
From: Marcelo Tosatti @ 2010-05-06 19:43 UTC (permalink / raw)
To: Avi Kivity; +Cc: kvm
On Sun, May 02, 2010 at 12:48:49PM +0300, Avi Kivity wrote:
> Currently we run with EFER.NX=1 on the guest even if the guest value is 0.
> This is fine with shadow, since we check bit 63 when instantiating a page
> table, and fault if bit 63 is set while EFER.NX is clear.
>
> This doesn't work with EPT, since we no longer get the change to check guest
> ptes. So we need to run with EFER.NX=0.
>
> This is complicated by the fact that if we switch EFER.NX on the host, we'll
> trap immediately, since some host pages are mapped with the NX bit set. As
> a result, we need to switch the MSR atomically during guest entry and exit.
>
> This patchset implements the complications described above.
>
> v2:
> Fix transition from long mode to legacy mode
Reviewed-by: Marcelo Tosatti <mtosatti@redhat.com>
^ permalink raw reply [flat|nested] 7+ messages in thread