aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kvm/mmu.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86/kvm/mmu.c')
-rw-r--r--arch/x86/kvm/mmu.c38
1 files changed, 33 insertions, 5 deletions
diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c
index f5704d9e5ddc..813d31038b93 100644
--- a/arch/x86/kvm/mmu.c
+++ b/arch/x86/kvm/mmu.c
@@ -3601,20 +3601,27 @@ static void reset_rsvds_bits_mask_ept(struct kvm_vcpu *vcpu,
3601 } 3601 }
3602} 3602}
3603 3603
3604static void update_permission_bitmask(struct kvm_vcpu *vcpu, 3604void update_permission_bitmask(struct kvm_vcpu *vcpu,
3605 struct kvm_mmu *mmu, bool ept) 3605 struct kvm_mmu *mmu, bool ept)
3606{ 3606{
3607 unsigned bit, byte, pfec; 3607 unsigned bit, byte, pfec;
3608 u8 map; 3608 u8 map;
3609 bool fault, x, w, u, wf, uf, ff, smep; 3609 bool fault, x, w, u, wf, uf, ff, smapf, cr4_smap, cr4_smep, smap = 0;
3610 3610
3611 smep = kvm_read_cr4_bits(vcpu, X86_CR4_SMEP); 3611 cr4_smep = kvm_read_cr4_bits(vcpu, X86_CR4_SMEP);
3612 cr4_smap = kvm_read_cr4_bits(vcpu, X86_CR4_SMAP);
3612 for (byte = 0; byte < ARRAY_SIZE(mmu->permissions); ++byte) { 3613 for (byte = 0; byte < ARRAY_SIZE(mmu->permissions); ++byte) {
3613 pfec = byte << 1; 3614 pfec = byte << 1;
3614 map = 0; 3615 map = 0;
3615 wf = pfec & PFERR_WRITE_MASK; 3616 wf = pfec & PFERR_WRITE_MASK;
3616 uf = pfec & PFERR_USER_MASK; 3617 uf = pfec & PFERR_USER_MASK;
3617 ff = pfec & PFERR_FETCH_MASK; 3618 ff = pfec & PFERR_FETCH_MASK;
3619 /*
3620 * PFERR_RSVD_MASK bit is set in PFEC if the access is not
3621 * subject to SMAP restrictions, and cleared otherwise. The
3622 * bit is only meaningful if the SMAP bit is set in CR4.
3623 */
3624 smapf = !(pfec & PFERR_RSVD_MASK);
3618 for (bit = 0; bit < 8; ++bit) { 3625 for (bit = 0; bit < 8; ++bit) {
3619 x = bit & ACC_EXEC_MASK; 3626 x = bit & ACC_EXEC_MASK;
3620 w = bit & ACC_WRITE_MASK; 3627 w = bit & ACC_WRITE_MASK;
@@ -3626,12 +3633,33 @@ static void update_permission_bitmask(struct kvm_vcpu *vcpu,
3626 /* Allow supervisor writes if !cr0.wp */ 3633 /* Allow supervisor writes if !cr0.wp */
3627 w |= !is_write_protection(vcpu) && !uf; 3634 w |= !is_write_protection(vcpu) && !uf;
3628 /* Disallow supervisor fetches of user code if cr4.smep */ 3635 /* Disallow supervisor fetches of user code if cr4.smep */
3629 x &= !(smep && u && !uf); 3636 x &= !(cr4_smep && u && !uf);
3637
3638 /*
3639 * SMAP:kernel-mode data accesses from user-mode
3640 * mappings should fault. A fault is considered
3641 * as a SMAP violation if all of the following
3642 * conditions are ture:
3643 * - X86_CR4_SMAP is set in CR4
3644 * - An user page is accessed
3645 * - Page fault in kernel mode
3646 * - if CPL = 3 or X86_EFLAGS_AC is clear
3647 *
3648 * Here, we cover the first three conditions.
3649 * The fourth is computed dynamically in
3650 * permission_fault() and is in smapf.
3651 *
3652 * Also, SMAP does not affect instruction
3653 * fetches, add the !ff check here to make it
3654 * clearer.
3655 */
3656 smap = cr4_smap && u && !uf && !ff;
3630 } else 3657 } else
3631 /* Not really needed: no U/S accesses on ept */ 3658 /* Not really needed: no U/S accesses on ept */
3632 u = 1; 3659 u = 1;
3633 3660
3634 fault = (ff && !x) || (uf && !u) || (wf && !w); 3661 fault = (ff && !x) || (uf && !u) || (wf && !w) ||
3662 (smapf && smap);
3635 map |= fault << bit; 3663 map |= fault << bit;
3636 } 3664 }
3637 mmu->permissions[byte] = map; 3665 mmu->permissions[byte] = map;