aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kvm/mmu.c
diff options
context:
space:
mode:
authorYang Zhang <yang.z.zhang@Intel.com>2013-08-06 05:00:32 -0400
committerPaolo Bonzini <pbonzini@redhat.com>2013-08-07 09:57:40 -0400
commit25d92081ae2ff9858fa733621ef8e91d30fec9d0 (patch)
tree3896c76a90796a54f0cac910bfd9abbc01cb428b /arch/x86/kvm/mmu.c
parent53166229e96941f27e7f0ba405c7a44d648751c9 (diff)
nEPT: Add nEPT violation/misconfigration support
Inject nEPT fault to L1 guest. This patch is original from Xinhao. Reviewed-by: Xiao Guangrong <xiaoguangrong@linux.vnet.ibm.com> Signed-off-by: Jun Nakajima <jun.nakajima@intel.com> Signed-off-by: Xinhao Xu <xinhao.xu@intel.com> Signed-off-by: Yang Zhang <yang.z.zhang@Intel.com> Signed-off-by: Gleb Natapov <gleb@redhat.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Diffstat (limited to 'arch/x86/kvm/mmu.c')
-rw-r--r--arch/x86/kvm/mmu.c61
1 files changed, 50 insertions, 11 deletions
diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c
index 75d843bb4ca3..a215c41b5176 100644
--- a/arch/x86/kvm/mmu.c
+++ b/arch/x86/kvm/mmu.c
@@ -3519,6 +3519,8 @@ static void reset_rsvds_bits_mask(struct kvm_vcpu *vcpu,
3519 int maxphyaddr = cpuid_maxphyaddr(vcpu); 3519 int maxphyaddr = cpuid_maxphyaddr(vcpu);
3520 u64 exb_bit_rsvd = 0; 3520 u64 exb_bit_rsvd = 0;
3521 3521
3522 context->bad_mt_xwr = 0;
3523
3522 if (!context->nx) 3524 if (!context->nx)
3523 exb_bit_rsvd = rsvd_bits(63, 63); 3525 exb_bit_rsvd = rsvd_bits(63, 63);
3524 switch (context->root_level) { 3526 switch (context->root_level) {
@@ -3574,7 +3576,40 @@ static void reset_rsvds_bits_mask(struct kvm_vcpu *vcpu,
3574 } 3576 }
3575} 3577}
3576 3578
3577static void update_permission_bitmask(struct kvm_vcpu *vcpu, struct kvm_mmu *mmu) 3579static void reset_rsvds_bits_mask_ept(struct kvm_vcpu *vcpu,
3580 struct kvm_mmu *context, bool execonly)
3581{
3582 int maxphyaddr = cpuid_maxphyaddr(vcpu);
3583 int pte;
3584
3585 context->rsvd_bits_mask[0][3] =
3586 rsvd_bits(maxphyaddr, 51) | rsvd_bits(3, 7);
3587 context->rsvd_bits_mask[0][2] =
3588 rsvd_bits(maxphyaddr, 51) | rsvd_bits(3, 6);
3589 context->rsvd_bits_mask[0][1] =
3590 rsvd_bits(maxphyaddr, 51) | rsvd_bits(3, 6);
3591 context->rsvd_bits_mask[0][0] = rsvd_bits(maxphyaddr, 51);
3592
3593 /* large page */
3594 context->rsvd_bits_mask[1][3] = context->rsvd_bits_mask[0][3];
3595 context->rsvd_bits_mask[1][2] =
3596 rsvd_bits(maxphyaddr, 51) | rsvd_bits(12, 29);
3597 context->rsvd_bits_mask[1][1] =
3598 rsvd_bits(maxphyaddr, 51) | rsvd_bits(12, 20);
3599 context->rsvd_bits_mask[1][0] = context->rsvd_bits_mask[0][0];
3600
3601 for (pte = 0; pte < 64; pte++) {
3602 int rwx_bits = pte & 7;
3603 int mt = pte >> 3;
3604 if (mt == 0x2 || mt == 0x3 || mt == 0x7 ||
3605 rwx_bits == 0x2 || rwx_bits == 0x6 ||
3606 (rwx_bits == 0x4 && !execonly))
3607 context->bad_mt_xwr |= (1ull << pte);
3608 }
3609}
3610
3611static void update_permission_bitmask(struct kvm_vcpu *vcpu,
3612 struct kvm_mmu *mmu, bool ept)
3578{ 3613{
3579 unsigned bit, byte, pfec; 3614 unsigned bit, byte, pfec;
3580 u8 map; 3615 u8 map;
@@ -3592,12 +3627,16 @@ static void update_permission_bitmask(struct kvm_vcpu *vcpu, struct kvm_mmu *mmu
3592 w = bit & ACC_WRITE_MASK; 3627 w = bit & ACC_WRITE_MASK;
3593 u = bit & ACC_USER_MASK; 3628 u = bit & ACC_USER_MASK;
3594 3629
3595 /* Not really needed: !nx will cause pte.nx to fault */ 3630 if (!ept) {
3596 x |= !mmu->nx; 3631 /* Not really needed: !nx will cause pte.nx to fault */
3597 /* Allow supervisor writes if !cr0.wp */ 3632 x |= !mmu->nx;
3598 w |= !is_write_protection(vcpu) && !uf; 3633 /* Allow supervisor writes if !cr0.wp */
3599 /* Disallow supervisor fetches of user code if cr4.smep */ 3634 w |= !is_write_protection(vcpu) && !uf;
3600 x &= !(smep && u && !uf); 3635 /* Disallow supervisor fetches of user code if cr4.smep */
3636 x &= !(smep && u && !uf);
3637 } else
3638 /* Not really needed: no U/S accesses on ept */
3639 u = 1;
3601 3640
3602 fault = (ff && !x) || (uf && !u) || (wf && !w); 3641 fault = (ff && !x) || (uf && !u) || (wf && !w);
3603 map |= fault << bit; 3642 map |= fault << bit;
@@ -3632,7 +3671,7 @@ static int paging64_init_context_common(struct kvm_vcpu *vcpu,
3632 context->root_level = level; 3671 context->root_level = level;
3633 3672
3634 reset_rsvds_bits_mask(vcpu, context); 3673 reset_rsvds_bits_mask(vcpu, context);
3635 update_permission_bitmask(vcpu, context); 3674 update_permission_bitmask(vcpu, context, false);
3636 update_last_pte_bitmap(vcpu, context); 3675 update_last_pte_bitmap(vcpu, context);
3637 3676
3638 ASSERT(is_pae(vcpu)); 3677 ASSERT(is_pae(vcpu));
@@ -3662,7 +3701,7 @@ static int paging32_init_context(struct kvm_vcpu *vcpu,
3662 context->root_level = PT32_ROOT_LEVEL; 3701 context->root_level = PT32_ROOT_LEVEL;
3663 3702
3664 reset_rsvds_bits_mask(vcpu, context); 3703 reset_rsvds_bits_mask(vcpu, context);
3665 update_permission_bitmask(vcpu, context); 3704 update_permission_bitmask(vcpu, context, false);
3666 update_last_pte_bitmap(vcpu, context); 3705 update_last_pte_bitmap(vcpu, context);
3667 3706
3668 context->new_cr3 = paging_new_cr3; 3707 context->new_cr3 = paging_new_cr3;
@@ -3724,7 +3763,7 @@ static int init_kvm_tdp_mmu(struct kvm_vcpu *vcpu)
3724 context->gva_to_gpa = paging32_gva_to_gpa; 3763 context->gva_to_gpa = paging32_gva_to_gpa;
3725 } 3764 }
3726 3765
3727 update_permission_bitmask(vcpu, context); 3766 update_permission_bitmask(vcpu, context, false);
3728 update_last_pte_bitmap(vcpu, context); 3767 update_last_pte_bitmap(vcpu, context);
3729 3768
3730 return 0; 3769 return 0;
@@ -3803,7 +3842,7 @@ static int init_kvm_nested_mmu(struct kvm_vcpu *vcpu)
3803 g_context->gva_to_gpa = paging32_gva_to_gpa_nested; 3842 g_context->gva_to_gpa = paging32_gva_to_gpa_nested;
3804 } 3843 }
3805 3844
3806 update_permission_bitmask(vcpu, g_context); 3845 update_permission_bitmask(vcpu, g_context, false);
3807 update_last_pte_bitmap(vcpu, g_context); 3846 update_last_pte_bitmap(vcpu, g_context);
3808 3847
3809 return 0; 3848 return 0;