vcpu->arch.mmu->shadow_root_level);
 }
 
+struct kvm_page_fault {
+       /* arguments to kvm_mmu_do_page_fault.  */
+       const gpa_t addr;
+       const u32 error_code;
+       const bool prefault;
+
+       /* Derived from error_code.  */
+       const bool exec;
+       const bool write;
+       const bool present;
+       const bool rsvd;
+       const bool user;
+
+       /* Derived from mmu.  */
+       const bool is_tdp;
+};
+
 int kvm_tdp_page_fault(struct kvm_vcpu *vcpu, gpa_t gpa, u32 error_code,
                       bool prefault);
 
 static inline int kvm_mmu_do_page_fault(struct kvm_vcpu *vcpu, gpa_t cr2_or_gpa,
                                        u32 err, bool prefault)
 {
+       struct kvm_page_fault fault = {
+               .addr = cr2_or_gpa,
+               .error_code = err,
+               .exec = err & PFERR_FETCH_MASK,
+               .write = err & PFERR_WRITE_MASK,
+               .present = err & PFERR_PRESENT_MASK,
+               .rsvd = err & PFERR_RSVD_MASK,
+               .user = err & PFERR_USER_MASK,
+               .prefault = prefault,
+               .is_tdp = likely(vcpu->arch.mmu->page_fault == kvm_tdp_page_fault),
+       };
 #ifdef CONFIG_RETPOLINE
-       if (likely(vcpu->arch.mmu->page_fault == kvm_tdp_page_fault))
-               return kvm_tdp_page_fault(vcpu, cr2_or_gpa, err, prefault);
+       if (fault.is_tdp)
+               return kvm_tdp_page_fault(vcpu, fault.addr, fault.error_code, fault.prefault);
 #endif
-       return vcpu->arch.mmu->page_fault(vcpu, cr2_or_gpa, err, prefault);
+       return vcpu->arch.mmu->page_fault(vcpu, fault.addr, fault.error_code, fault.prefault);
 }
 
 /*