]> www.infradead.org Git - users/dwmw2/linux.git/commitdiff
WIP: Attempt to support interruptible exception handling on x86 clocks intr-exceptions
authorDavid Woodhouse <dwmw@amazon.co.uk>
Fri, 2 Aug 2024 17:17:02 +0000 (18:17 +0100)
committerDavid Woodhouse <dwmw@amazon.co.uk>
Fri, 2 Aug 2024 17:17:02 +0000 (18:17 +0100)
Signed-off-by: David Woodhouse <dwmw@amazon.co.uk>
arch/x86/include/asm/asm.h
arch/x86/include/asm/extable_fixup_types.h
arch/x86/include/asm/trapnr.h
arch/x86/kvm/x86.c
arch/x86/mm/extable.c
arch/x86/mm/fault.c

index 2bec0c89a95c2794cfe15133a9b098e62fe6ef76..854ccd5f234224f7356c77522f49956690206db4 100644 (file)
@@ -229,6 +229,9 @@ register unsigned long current_stack_pointer asm(_ASM_SP);
 #define _ASM_EXTABLE_UA(from, to)                              \
        _ASM_EXTABLE_TYPE(from, to, EX_TYPE_UACCESS)
 
+#define _ASM_EXTABLE_UA_INTR(from, to)                         \
+       _ASM_EXTABLE_TYPE(from, to, EX_TYPE_UACCESS_INTERRUPTIBLE)
+
 #define _ASM_EXTABLE_FAULT(from, to)                           \
        _ASM_EXTABLE_TYPE(from, to, EX_TYPE_FAULT)
 
index 906b0d5541e896fc4f24bd2306607e3a8838483d..651d42f39e9bab8e6d53f4849d9e3d81d658d46d 100644 (file)
@@ -36,7 +36,7 @@
 #define        EX_TYPE_DEFAULT                  1
 #define        EX_TYPE_FAULT                    2
 #define        EX_TYPE_UACCESS                  3
-/* unused, was: #define EX_TYPE_COPY    4 */
+#define        EX_TYPE_UACCESS_INTERRUPTIBLE    4
 #define        EX_TYPE_CLEAR_FS                 5
 #define        EX_TYPE_FPU_RESTORE              6
 #define        EX_TYPE_BPF                      7
index 8d1154cdf7875c923645e3b5f5bf111ce9ffd1f0..9f6397bad3988389ec26231fa155c1da6ab5bd37 100644 (file)
@@ -41,4 +41,5 @@
 #define X86_TRAP_VC            29      /* VMM Communication Exception */
 #define X86_TRAP_IRET          32      /* IRET Exception */
 
+#define X86_TRAP_INTERRUPTIBLE 0x40000000      /* Internal, for interruptible exceptions */
 #endif
index cef729a25655985576126d143e69e61ef8adb4b2..ab00150d360b57e0db3395a2fa7461d072fbd8f1 100644 (file)
@@ -3819,12 +3819,15 @@ static void record_steal_time(struct kvm_vcpu *vcpu)
                asm volatile("1: xchgb %0, %2\n"
                             "xor %1, %1\n"
                             "2:\n"
-                            _ASM_EXTABLE_UA(1b, 2b)
+                            _ASM_EXTABLE_UA_INTR(1b, 2b)
                             : "+q" (st_preempted),
                               "+&r" (err),
                               "+m" (st->preempted));
-               if (err)
+               if (err) {
+                       if (signal_pending(current))
+                               err = -EINTR;
                        goto out;
+               }
 
                user_access_end();
 
index 51986e8a9d353528cbee8186019a3ed8bc7823f2..d2cef84042a5a17607cc03708a5ebf83e3ca46be 100644 (file)
@@ -325,6 +325,12 @@ int fixup_exception(struct pt_regs *regs, int trapnr, unsigned long error_code,
        reg  = FIELD_GET(EX_DATA_REG_MASK,  e->data);
        imm  = FIELD_GET(EX_DATA_IMM_MASK,  e->data);
 
+       if (trapnr & X86_TRAP_INTERRUPTIBLE) {
+               trapnr &= ~X86_TRAP_INTERRUPTIBLE;
+               if (type != EX_TYPE_UACCESS_INTERRUPTIBLE)
+                       return 0;
+       }
+
        switch (type) {
        case EX_TYPE_DEFAULT:
        case EX_TYPE_DEFAULT_MCE_SAFE:
@@ -333,6 +339,7 @@ int fixup_exception(struct pt_regs *regs, int trapnr, unsigned long error_code,
        case EX_TYPE_FAULT_MCE_SAFE:
                return ex_handler_fault(e, regs, trapnr);
        case EX_TYPE_UACCESS:
+       case EX_TYPE_UACCESS_INTERRUPTIBLE:
                return ex_handler_uaccess(e, regs, trapnr, fault_addr);
        case EX_TYPE_CLEAR_FS:
                return ex_handler_clear_fs(e, regs);
index e6c469b323ccb748de22adc7d9f0a16dd195edad..aa9dec82e612ec5c8e1cd49c5cbb660298aa4a76 100644 (file)
@@ -1388,18 +1388,6 @@ retry:
         */
        fault = handle_mm_fault(vma, address, flags, regs);
 
-       if (fault_signal_pending(fault, regs)) {
-               /*
-                * Quick path to respond to signals.  The core mm code
-                * has unlocked the mm for us if we get here.
-                */
-               if (!user_mode(regs))
-                       kernelmode_fixup_or_oops(regs, error_code, address,
-                                                SIGBUS, BUS_ADRERR,
-                                                ARCH_DEFAULT_PKEY);
-               return;
-       }
-
        /* The fault is fully completed (including releasing mmap lock) */
        if (fault & VM_FAULT_COMPLETED)
                return;
@@ -1410,6 +1398,29 @@ retry:
         * that we made any progress. Handle this case first.
         */
        if (unlikely(fault & VM_FAULT_RETRY)) {
+               if (signal_pending(current)) {
+                       if (user_mode(regs))
+                               return;
+
+                       if (fatal_signal_pending(current)) {
+                               kernelmode_fixup_or_oops(regs, error_code, address,
+                                                        SIGBUS, BUS_ADRERR,
+                                                        ARCH_DEFAULT_PKEY);
+                               return;
+                       }
+
+                       /*
+                        * First time round, if woken by a signal, see if there
+                        * is an interruptible exception handler. If so, do it.
+                        * Else, switch off FAULT_FLAG_INTERRUPTIBLE.
+                        */
+                       if (fixup_exception(regs, X86_TRAP_INTERRUPTIBLE | X86_TRAP_PF,
+                                           error_code, address))
+                               return;
+
+                       flags &= ~FAULT_FLAG_INTERRUPTIBLE;
+               }
+
                flags |= FAULT_FLAG_TRIED;
                goto retry;
        }