powerpc/64: Allow for relocation-on interrupts from guest to host
authorPaul Mackerras <paulus@ozlabs.org>
Mon, 30 Jan 2017 10:21:40 +0000 (21:21 +1100)
committerMichael Ellerman <mpe@ellerman.id.au>
Tue, 31 Jan 2017 08:11:46 +0000 (19:11 +1100)
With host and guest both using radix translation, it is feasible
for the host to take interrupts that come from the guest with
relocation on, and that is in fact what the POWER9 hardware will
do when LPCR[AIL] = 3.  All such interrupts use HSRR0/1 not SRR0/1
except for system call with LEV=1 (hcall).

Therefore this adds the KVM tests to the _HV variants of the
relocation-on interrupt handlers, and adds the KVM test to the
relocation-on system call entry point.

We also instantiate the relocation-on versions of the hypervisor
data storage and instruction interrupt handlers, since these can
occur with relocation on in radix guests.

Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
arch/powerpc/include/asm/exception-64s.h
arch/powerpc/kernel/exceptions-64s.S

index 9a5dbfb2d9f24d28a1954a063ca98ee8c2e7270d..8fa09fa500f043e279e5c8e047d3570a76c71dfb 100644 (file)
@@ -428,12 +428,12 @@ END_FTR_SECTION_NESTED(ftr,ftr,943)
        EXCEPTION_RELON_PROLOG_PSERIES_1(label, EXC_STD)
 
 #define STD_RELON_EXCEPTION_HV(loc, vec, label)                \
-       /* No guest interrupts come through here */     \
        SET_SCRATCH0(r13);      /* save r13 */          \
-       EXCEPTION_RELON_PROLOG_PSERIES(PACA_EXGEN, label, EXC_HV, NOTEST, vec);
+       EXCEPTION_RELON_PROLOG_PSERIES(PACA_EXGEN, label,       \
+                                      EXC_HV, KVMTEST_HV, vec);
 
 #define STD_RELON_EXCEPTION_HV_OOL(vec, label)                 \
-       EXCEPTION_PROLOG_1(PACA_EXGEN, NOTEST, vec);            \
+       EXCEPTION_PROLOG_1(PACA_EXGEN, KVMTEST_HV, vec);        \
        EXCEPTION_RELON_PROLOG_PSERIES_1(label, EXC_HV)
 
 /* This associate vector numbers with bits in paca->irq_happened */
@@ -510,10 +510,10 @@ END_FTR_SECTION_NESTED(ftr,ftr,943)
 
 #define MASKABLE_RELON_EXCEPTION_HV(loc, vec, label)                   \
        _MASKABLE_RELON_EXCEPTION_PSERIES(vec, label,                   \
-                                         EXC_HV, SOFTEN_NOTEST_HV)
+                                         EXC_HV, SOFTEN_TEST_HV)
 
 #define MASKABLE_RELON_EXCEPTION_HV_OOL(vec, label)                    \
-       EXCEPTION_PROLOG_1(PACA_EXGEN, SOFTEN_NOTEST_HV, vec);          \
+       EXCEPTION_PROLOG_1(PACA_EXGEN, SOFTEN_TEST_HV, vec);            \
        EXCEPTION_PROLOG_PSERIES_1(label, EXC_HV)
 
 /*
index 65a2559eeb7fc251c0c92ac08f3d9d2d325aef93..34a04a5fa468e3e3516060b6018f19df3cc3a34d 100644 (file)
@@ -830,6 +830,31 @@ EXC_VIRT(trap_0b, 0x4b00, 0x4c00, 0xb00)
 TRAMP_KVM(PACA_EXGEN, 0xb00)
 EXC_COMMON(trap_0b_common, 0xb00, unknown_exception)
 
+#ifdef CONFIG_KVM_BOOK3S_64_HANDLER
+        /*
+         * If CONFIG_KVM_BOOK3S_64_HANDLER is set, save the PPR (on systems
+         * that support it) before changing to HMT_MEDIUM. That allows the KVM
+         * code to save that value into the guest state (it is the guest's PPR
+         * value). Otherwise just change to HMT_MEDIUM as userspace has
+         * already saved the PPR.
+         */
+#define SYSCALL_KVMTEST                                                        \
+       SET_SCRATCH0(r13);                                              \
+       GET_PACA(r13);                                                  \
+       std     r9,PACA_EXGEN+EX_R9(r13);                               \
+       OPT_GET_SPR(r9, SPRN_PPR, CPU_FTR_HAS_PPR);                     \
+       HMT_MEDIUM;                                                     \
+       std     r10,PACA_EXGEN+EX_R10(r13);                             \
+       OPT_SAVE_REG_TO_PACA(PACA_EXGEN+EX_PPR, r9, CPU_FTR_HAS_PPR);   \
+       mfcr    r9;                                                     \
+       KVMTEST_PR(0xc00);                                              \
+       GET_SCRATCH0(r13)
+
+#else
+#define SYSCALL_KVMTEST                                                        \
+       HMT_MEDIUM
+#endif
+       
 #define LOAD_SYSCALL_HANDLER(reg)                                      \
        __LOAD_HANDLER(reg, system_call_common)
 
@@ -883,34 +908,14 @@ END_FTR_SECTION_IFSET(CPU_FTR_REAL_LE)                            \
 #endif
 
 EXC_REAL_BEGIN(system_call, 0xc00, 0xd00)
-        /*
-         * If CONFIG_KVM_BOOK3S_64_HANDLER is set, save the PPR (on systems
-         * that support it) before changing to HMT_MEDIUM. That allows the KVM
-         * code to save that value into the guest state (it is the guest's PPR
-         * value). Otherwise just change to HMT_MEDIUM as userspace has
-         * already saved the PPR.
-         */
-#ifdef CONFIG_KVM_BOOK3S_64_HANDLER
-       SET_SCRATCH0(r13)
-       GET_PACA(r13)
-       std     r9,PACA_EXGEN+EX_R9(r13)
-       OPT_GET_SPR(r9, SPRN_PPR, CPU_FTR_HAS_PPR);
-       HMT_MEDIUM;
-       std     r10,PACA_EXGEN+EX_R10(r13)
-       OPT_SAVE_REG_TO_PACA(PACA_EXGEN+EX_PPR, r9, CPU_FTR_HAS_PPR);
-       mfcr    r9
-       KVMTEST_PR(0xc00)
-       GET_SCRATCH0(r13)
-#else
-       HMT_MEDIUM;
-#endif
+       SYSCALL_KVMTEST
        SYSCALL_PSERIES_1
        SYSCALL_PSERIES_2_RFID
        SYSCALL_PSERIES_3
 EXC_REAL_END(system_call, 0xc00, 0xd00)
 
 EXC_VIRT_BEGIN(system_call, 0x4c00, 0x4d00)
-       HMT_MEDIUM
+       SYSCALL_KVMTEST
        SYSCALL_PSERIES_1
        SYSCALL_PSERIES_2_DIRECT
        SYSCALL_PSERIES_3
@@ -925,7 +930,7 @@ TRAMP_KVM(PACA_EXGEN, 0xd00)
 EXC_COMMON(single_step_common, 0xd00, single_step_exception)
 
 EXC_REAL_OOL_HV(h_data_storage, 0xe00, 0xe20)
-EXC_VIRT_NONE(0x4e00, 0x4e20)
+EXC_VIRT_OOL_HV(h_data_storage, 0x4e00, 0x4e20, 0xe00)
 TRAMP_KVM_HV_SKIP(PACA_EXGEN, 0xe00)
 EXC_COMMON_BEGIN(h_data_storage_common)
        mfspr   r10,SPRN_HDAR
@@ -941,7 +946,7 @@ EXC_COMMON_BEGIN(h_data_storage_common)
 
 
 EXC_REAL_OOL_HV(h_instr_storage, 0xe20, 0xe40)
-EXC_VIRT_NONE(0x4e20, 0x4e40)
+EXC_VIRT_OOL_HV(h_instr_storage, 0x4e20, 0x4e40, 0xe20)
 TRAMP_KVM_HV(PACA_EXGEN, 0xe20)
 EXC_COMMON(h_instr_storage_common, 0xe20, unknown_exception)