mirror of
https://github.com/torvalds/linux.git
synced 2026-07-27 17:47:41 +02:00
KVM: x86/mmu: move cr4_smep to base role
Guest page tables can be reused independent of the value of CR4.SMEP (at least if WP=1). However, this is not true of EPT MBEC pages, because presence of EPT entries is signaled by bits 0-2 when MBEC is off, and bits 0-2 + bit 10 when MBEC is on. In preparation for enabling MBEC, move cr4_smep to the base role. This makes the smep_andnot_wp bit redundant, so remove it. Tested-by: David Riley <d.riley@proxmox.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
parent
2e111d932d
commit
f603854a1b
|
|
@ -184,10 +184,8 @@ Shadow pages contain the following information:
|
|||
Contains the value of efer.nx for which the page is valid.
|
||||
role.cr0_wp:
|
||||
Contains the value of cr0.wp for which the page is valid.
|
||||
role.smep_andnot_wp:
|
||||
Contains the value of cr4.smep && !cr0.wp for which the page is valid
|
||||
(pages for which this is true are different from other pages; see the
|
||||
treatment of cr0.wp=0 below).
|
||||
role.cr4_smep:
|
||||
Contains the value of cr4.smep for which the page is valid.
|
||||
role.smap_andnot_wp:
|
||||
Contains the value of cr4.smap && !cr0.wp for which the page is valid
|
||||
(pages for which this is true are different from other pages; see the
|
||||
|
|
@ -435,8 +433,8 @@ from being written by the kernel after cr0.wp has changed to 1, we make
|
|||
the value of cr0.wp part of the page role. This means that an spte created
|
||||
with one value of cr0.wp cannot be used when cr0.wp has a different value -
|
||||
it will simply be missed by the shadow page lookup code. A similar issue
|
||||
exists when an spte created with cr0.wp=0 and cr4.smep=0 is used after
|
||||
changing cr4.smep to 1. To avoid this, the value of !cr0.wp && cr4.smep
|
||||
exists when an spte created with cr0.wp=0 and cr4.smap=0 is used after
|
||||
changing cr4.smap to 1. To avoid this, the value of !cr0.wp && cr4.smap
|
||||
is also made a part of the page role.
|
||||
|
||||
Large pages
|
||||
|
|
|
|||
|
|
@ -94,6 +94,7 @@ KVM_X86_OP_OPTIONAL(sync_pir_to_irr)
|
|||
KVM_X86_OP_OPTIONAL_RET0(set_tss_addr)
|
||||
KVM_X86_OP_OPTIONAL_RET0(set_identity_map_addr)
|
||||
KVM_X86_OP_OPTIONAL_RET0(get_mt_mask)
|
||||
KVM_X86_OP_OPTIONAL_RET0(tdp_has_smep)
|
||||
KVM_X86_OP(load_mmu_pgd)
|
||||
KVM_X86_OP_OPTIONAL(link_external_spt)
|
||||
KVM_X86_OP_OPTIONAL(set_external_spte)
|
||||
|
|
|
|||
|
|
@ -343,8 +343,8 @@ struct kvm_kernel_irq_routing_entry;
|
|||
* paging has exactly one upper level, making level completely redundant
|
||||
* when has_4_byte_gpte=1.
|
||||
*
|
||||
* - on top of this, smep_andnot_wp and smap_andnot_wp are only set if
|
||||
* cr0_wp=0, therefore these three bits only give rise to 5 possibilities.
|
||||
* - on top of this, smap_andnot_wp is only set if cr0_wp=0,
|
||||
* therefore these two bits only give rise to 3 possibilities.
|
||||
*
|
||||
* Therefore, the maximum number of possible upper-level shadow pages for a
|
||||
* single gfn is a bit less than 2^14.
|
||||
|
|
@ -360,12 +360,19 @@ union kvm_mmu_page_role {
|
|||
unsigned invalid:1;
|
||||
unsigned efer_nx:1;
|
||||
unsigned cr0_wp:1;
|
||||
unsigned smep_andnot_wp:1;
|
||||
unsigned smap_andnot_wp:1;
|
||||
unsigned ad_disabled:1;
|
||||
unsigned guest_mode:1;
|
||||
unsigned passthrough:1;
|
||||
unsigned is_mirror:1;
|
||||
|
||||
/*
|
||||
* cr4_smep is also set for EPT MBEC. Because it affects
|
||||
* which pages are considered non-present (bit 10 additionally
|
||||
* must be zero if MBEC is on) it has to be in the base role.
|
||||
*/
|
||||
unsigned cr4_smep:1;
|
||||
|
||||
unsigned:3;
|
||||
|
||||
/*
|
||||
|
|
@ -392,10 +399,10 @@ union kvm_mmu_page_role {
|
|||
* tables (because KVM doesn't support Protection Keys with shadow paging), and
|
||||
* CR0.PG, CR4.PAE, and CR4.PSE are indirectly reflected in role.level.
|
||||
*
|
||||
* Note, SMEP and SMAP are not redundant with sm*p_andnot_wp in the page role.
|
||||
* If CR0.WP=1, KVM can reuse shadow pages for the guest regardless of SMEP and
|
||||
* SMAP, but the MMU's permission checks for software walks need to be SMEP and
|
||||
* SMAP aware regardless of CR0.WP.
|
||||
* Note, SMAP is not redundant with smap_andnot_wp in the page role. If
|
||||
* CR0.WP=1, KVM can reuse shadow pages for the guest regardless of SMAP,
|
||||
* but the MMU's permission checks for software walks need to be SMAP
|
||||
* aware regardless of CR0.WP.
|
||||
*/
|
||||
union kvm_mmu_extended_role {
|
||||
u32 word;
|
||||
|
|
@ -405,7 +412,6 @@ union kvm_mmu_extended_role {
|
|||
unsigned int cr4_pse:1;
|
||||
unsigned int cr4_pke:1;
|
||||
unsigned int cr4_smap:1;
|
||||
unsigned int cr4_smep:1;
|
||||
unsigned int cr4_la57:1;
|
||||
unsigned int efer_lma:1;
|
||||
};
|
||||
|
|
@ -1887,6 +1893,7 @@ struct kvm_x86_ops {
|
|||
int (*set_tss_addr)(struct kvm *kvm, unsigned int addr);
|
||||
int (*set_identity_map_addr)(struct kvm *kvm, u64 ident_addr);
|
||||
u8 (*get_mt_mask)(struct kvm_vcpu *vcpu, gfn_t gfn, bool is_mmio);
|
||||
bool (*tdp_has_smep)(struct kvm *kvm);
|
||||
|
||||
void (*load_mmu_pgd)(struct kvm_vcpu *vcpu, hpa_t root_hpa,
|
||||
int root_level);
|
||||
|
|
|
|||
|
|
@ -227,7 +227,7 @@ static inline bool __maybe_unused is_##reg##_##name(struct kvm_mmu *mmu) \
|
|||
}
|
||||
BUILD_MMU_ROLE_ACCESSOR(base, cr0, wp);
|
||||
BUILD_MMU_ROLE_ACCESSOR(ext, cr4, pse);
|
||||
BUILD_MMU_ROLE_ACCESSOR(ext, cr4, smep);
|
||||
BUILD_MMU_ROLE_ACCESSOR(base, cr4, smep);
|
||||
BUILD_MMU_ROLE_ACCESSOR(ext, cr4, smap);
|
||||
BUILD_MMU_ROLE_ACCESSOR(ext, cr4, pke);
|
||||
BUILD_MMU_ROLE_ACCESSOR(ext, cr4, la57);
|
||||
|
|
@ -5764,7 +5764,7 @@ static union kvm_cpu_role kvm_calc_cpu_role(struct kvm_vcpu *vcpu,
|
|||
|
||||
role.base.efer_nx = ____is_efer_nx(regs);
|
||||
role.base.cr0_wp = ____is_cr0_wp(regs);
|
||||
role.base.smep_andnot_wp = ____is_cr4_smep(regs) && !____is_cr0_wp(regs);
|
||||
role.base.cr4_smep = ____is_cr4_smep(regs);
|
||||
role.base.smap_andnot_wp = ____is_cr4_smap(regs) && !____is_cr0_wp(regs);
|
||||
role.base.has_4_byte_gpte = !____is_cr4_pae(regs);
|
||||
|
||||
|
|
@ -5776,7 +5776,6 @@ static union kvm_cpu_role kvm_calc_cpu_role(struct kvm_vcpu *vcpu,
|
|||
else
|
||||
role.base.level = PT32_ROOT_LEVEL;
|
||||
|
||||
role.ext.cr4_smep = ____is_cr4_smep(regs);
|
||||
role.ext.cr4_smap = ____is_cr4_smap(regs);
|
||||
role.ext.cr4_pse = ____is_cr4_pse(regs);
|
||||
|
||||
|
|
@ -5835,6 +5834,7 @@ kvm_calc_tdp_mmu_root_page_role(struct kvm_vcpu *vcpu,
|
|||
|
||||
role.access = ACC_ALL;
|
||||
role.cr0_wp = true;
|
||||
role.cr4_smep = kvm_x86_call(tdp_has_smep)(vcpu->kvm);
|
||||
role.efer_nx = true;
|
||||
role.smm = cpu_role.base.smm;
|
||||
role.guest_mode = cpu_role.base.guest_mode;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user