*/
if (!hc->fast && is_guest_mode(vcpu)) {
hc->ingpa = translate_nested_gpa(vcpu, hc->ingpa,
- PFERR_GUEST_FINAL_MASK, NULL);
+ PFERR_GUEST_FINAL_MASK, NULL, 0);
if (unlikely(hc->ingpa == INVALID_GPA))
return HV_STATUS_INVALID_HYPERCALL_INPUT;
}
#define PT32_ROOT_LEVEL 2
#define PT32E_ROOT_LEVEL 3
+#define ACC_READ_MASK PT_PRESENT_MASK
+#define ACC_WRITE_MASK PT_WRITABLE_MASK
+#define ACC_USER_MASK PT_USER_MASK
+#define ACC_EXEC_MASK 8
+#define ACC_ALL (ACC_EXEC_MASK | ACC_WRITE_MASK | ACC_USER_MASK | ACC_READ_MASK)
+
#define KVM_MMU_CR4_ROLE_BITS (X86_CR4_PSE | X86_CR4_PAE | X86_CR4_LA57 | \
X86_CR4_SMEP | X86_CR4_SMAP | X86_CR4_PKE)
}
gpa_t translate_nested_gpa(struct kvm_vcpu *vcpu, gpa_t gpa, u64 access,
- struct x86_exception *exception);
+ struct x86_exception *exception,
+ u64 pte_access);
static inline gpa_t kvm_translate_gpa(struct kvm_vcpu *vcpu,
struct kvm_mmu *mmu,
gpa_t gpa, u64 access,
- struct x86_exception *exception)
+ struct x86_exception *exception,
+ u64 pte_access)
{
if (mmu != &vcpu->arch.nested_mmu)
return gpa;
- return translate_nested_gpa(vcpu, gpa, access, exception);
+ return translate_nested_gpa(vcpu, gpa, access, exception,
+ pte_access);
}
static inline bool kvm_has_mirrored_tdp(const struct kvm *kvm)
{
if (exception)
exception->error_code = 0;
+ /*
+ * EPT MBEC uses the effective access bits from the PTE to distinguish
+ * user and supervisor accesses, and treats every linear address as a
+ * user-mode address if CR0.PG=0. Therefore *include* ACC_USER_MASK in
+ * the last argument to kvm_translate_gpa (which NPT does not use).
+ */
return kvm_translate_gpa(vcpu, mmu, vaddr, access | PFERR_GUEST_FINAL_MASK,
- exception);
+ exception, ACC_ALL);
}
static bool mmio_info_in_cache(struct kvm_vcpu *vcpu, u64 addr, bool direct)
real_gpa = kvm_translate_gpa(vcpu, mmu, gfn_to_gpa(table_gfn),
nested_access | PFERR_GUEST_PAGE_MASK,
- &walker->fault);
+ &walker->fault, 0);
/*
* FIXME: This can happen if emulation (for of an INS/OUTS
real_gpa = kvm_translate_gpa(vcpu, mmu, gfn_to_gpa(gfn),
access | PFERR_GUEST_FINAL_MASK,
- &walker->fault);
+ &walker->fault, walker->pte_access);
if (real_gpa == INVALID_GPA)
return 0;
#define SPTE_BASE_ADDR_MASK (((1ULL << 52) - 1) & ~(u64)(PAGE_SIZE-1))
#endif
-#define ACC_READ_MASK PT_PRESENT_MASK
-#define ACC_WRITE_MASK PT_WRITABLE_MASK
-#define ACC_USER_MASK PT_USER_MASK
-#define ACC_EXEC_MASK 8
-#define ACC_ALL (ACC_EXEC_MASK | ACC_WRITE_MASK | ACC_USER_MASK | ACC_READ_MASK)
-
#define SPTE_LEVEL_BITS 9
#define SPTE_LEVEL_SHIFT(level) __PT_LEVEL_SHIFT(level, SPTE_LEVEL_BITS)
#define SPTE_INDEX(address, level) __PT_INDEX(address, level, SPTE_LEVEL_BITS)
*/
real_gpa = kvm_translate_gpa(vcpu, mmu, gfn_to_gpa(pdpt_gfn),
PFERR_USER_MASK | PFERR_WRITE_MASK |
- PFERR_GUEST_PAGE_MASK, NULL);
+ PFERR_GUEST_PAGE_MASK, NULL, 0);
if (real_gpa == INVALID_GPA)
return 0;
}
gpa_t translate_nested_gpa(struct kvm_vcpu *vcpu, gpa_t gpa, u64 access,
- struct x86_exception *exception)
+ struct x86_exception *exception,
+ u64 pte_access)
{
struct kvm_mmu *mmu = vcpu->arch.mmu;
gpa_t t_gpa;