Merge tag 'mm-stable-2024-03-13-20-04' of git://git.kernel.org/pub/scm/linux/kernel...
[sfrench/cifs-2.6.git] / arch / x86 / mm / fault.c
index 2cc6fa5dc561203822f44e716ab595be448b7564..622d12ec7f08518ba6701c33efd74d5f77545806 100644 (file)
@@ -34,6 +34,8 @@
 #include <asm/kvm_para.h>              /* kvm_handle_async_pf          */
 #include <asm/vdso.h>                  /* fixup_vdso_exception()       */
 #include <asm/irq_stack.h>
+#include <asm/fred.h>
+#include <asm/sev.h>                   /* snp_dump_hva_rmpentry()      */
 
 #define CREATE_TRACE_POINTS
 #include <asm/trace/exceptions.h>
@@ -547,6 +549,7 @@ show_fault_oops(struct pt_regs *regs, unsigned long error_code, unsigned long ad
                 !(error_code & X86_PF_PROT) ? "not-present page" :
                 (error_code & X86_PF_RSVD)  ? "reserved bit violation" :
                 (error_code & X86_PF_PK)    ? "protection keys violation" :
+                (error_code & X86_PF_RMP)   ? "RMP violation" :
                                               "permissions violation");
 
        if (!(error_code & X86_PF_USER) && user_mode(regs)) {
@@ -579,6 +582,9 @@ show_fault_oops(struct pt_regs *regs, unsigned long error_code, unsigned long ad
        }
 
        dump_pagetable(address);
+
+       if (error_code & X86_PF_RMP)
+               snp_dump_hva_rmpentry(address);
 }
 
 static noinline void
@@ -798,15 +804,6 @@ show_signal_msg(struct pt_regs *regs, unsigned long error_code,
        show_opcodes(regs, loglvl);
 }
 
-/*
- * The (legacy) vsyscall page is the long page in the kernel portion
- * of the address space that has user-accessible permissions.
- */
-static bool is_vsyscall_vaddr(unsigned long vaddr)
-{
-       return unlikely((vaddr & PAGE_MASK) == VSYSCALL_ADDR);
-}
-
 static void
 __bad_area_nosemaphore(struct pt_regs *regs, unsigned long error_code,
                       unsigned long address, u32 pkey, int si_code)
@@ -1302,21 +1299,14 @@ void do_user_addr_fault(struct pt_regs *regs,
                return;
        }
 
-       /*
-        * It's safe to allow irq's after cr2 has been saved and the
-        * vmalloc fault has been handled.
-        *
-        * User-mode registers count as a user access even for any
-        * potential system fault or CPU buglet:
-        */
-       if (user_mode(regs)) {
-               local_irq_enable();
-               flags |= FAULT_FLAG_USER;
-       } else {
-               if (regs->flags & X86_EFLAGS_IF)
-                       local_irq_enable();
+       /* Legacy check - remove this after verifying that it doesn't trigger */
+       if (WARN_ON_ONCE(!(regs->flags & X86_EFLAGS_IF))) {
+               bad_area_nosemaphore(regs, error_code, address);
+               return;
        }
 
+       local_irq_enable();
+
        perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, regs, address);
 
        /*
@@ -1332,6 +1322,14 @@ void do_user_addr_fault(struct pt_regs *regs,
        if (error_code & X86_PF_INSTR)
                flags |= FAULT_FLAG_INSTRUCTION;
 
+       /*
+        * We set FAULT_FLAG_USER based on the register state, not
+        * based on X86_PF_USER. User space accesses that cause
+        * system page faults are still user accesses.
+        */
+       if (user_mode(regs))
+               flags |= FAULT_FLAG_USER;
+
 #ifdef CONFIG_X86_64
        /*
         * Faults in the vsyscall page might need emulation.  The
@@ -1518,8 +1516,10 @@ handle_page_fault(struct pt_regs *regs, unsigned long error_code,
 
 DEFINE_IDTENTRY_RAW_ERRORCODE(exc_page_fault)
 {
-       unsigned long address = read_cr2();
        irqentry_state_t state;
+       unsigned long address;
+
+       address = cpu_feature_enabled(X86_FEATURE_FRED) ? fred_event_data(regs) : read_cr2();
 
        prefetchw(&current->mm->mmap_lock);