diff options
author | Yang Zhang <yang.z.zhang@Intel.com> | 2013-08-06 05:00:32 -0400 |
---|---|---|
committer | Paolo Bonzini <pbonzini@redhat.com> | 2013-08-07 09:57:40 -0400 |
commit | 25d92081ae2ff9858fa733621ef8e91d30fec9d0 (patch) | |
tree | 3896c76a90796a54f0cac910bfd9abbc01cb428b /arch/x86/kvm/mmu.c | |
parent | 53166229e96941f27e7f0ba405c7a44d648751c9 (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.c | 61 |
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 | ||
3577 | static void update_permission_bitmask(struct kvm_vcpu *vcpu, struct kvm_mmu *mmu) | 3579 | static 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 | |||
3611 | static 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; |