* [PATCH 11/18] powerpc/64s/exception: KVM_HANDLER reorder arguments to match other macros
From: Nicholas Piggin @ 2019-07-29 14:12 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Nicholas Piggin
In-Reply-To: <20190729141247.26762-1-npiggin@gmail.com>
Also change argument name (n -> vec) to match others.
No generated code change.
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
---
arch/powerpc/kernel/exceptions-64s.S | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/arch/powerpc/kernel/exceptions-64s.S b/arch/powerpc/kernel/exceptions-64s.S
index 4b2d4c8f8831..e46d27be06fe 100644
--- a/arch/powerpc/kernel/exceptions-64s.S
+++ b/arch/powerpc/kernel/exceptions-64s.S
@@ -316,7 +316,7 @@ END_FTR_SECTION_NESTED(ftr,ftr,943)
.endif
.endm
-.macro KVM_HANDLER area, hsrr, n, skip
+.macro KVM_HANDLER vec, hsrr, area, skip
.if \skip
cmpwi r10,KVM_GUEST_MODE_SKIP
beq 89f
@@ -337,14 +337,14 @@ END_FTR_SECTION_NESTED(CPU_FTR_HAS_PPR,CPU_FTR_HAS_PPR,948)
/* HSRR variants have the 0x2 bit added to their trap number */
.if \hsrr == EXC_HV_OR_STD
BEGIN_FTR_SECTION
- ori r12,r12,(\n + 0x2)
+ ori r12,r12,(\vec + 0x2)
FTR_SECTION_ELSE
- ori r12,r12,(\n)
+ ori r12,r12,(\vec)
ALT_FTR_SECTION_END_IFSET(CPU_FTR_HVMODE | CPU_FTR_ARCH_206)
.elseif \hsrr
- ori r12,r12,(\n + 0x2)
+ ori r12,r12,(\vec + 0x2)
.else
- ori r12,r12,(\n)
+ ori r12,r12,(\vec)
.endif
#ifdef CONFIG_RELOCATABLE
@@ -386,7 +386,7 @@ END_FTR_SECTION_NESTED(CPU_FTR_HAS_PPR,CPU_FTR_HAS_PPR,948)
#else
.macro KVMTEST hsrr, n
.endm
-.macro KVM_HANDLER area, hsrr, n, skip
+.macro KVM_HANDLER vec, hsrr, area, skip
.endm
#endif
@@ -657,7 +657,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_CAN_NAP)
.else
TRAMP_KVM_BEGIN(do_kvm_\vec\())
.endif
- KVM_HANDLER \area, \hsrr, \vec, \skip
+ KVM_HANDLER \vec, \hsrr, \area, \skip
.endm
#define EXC_COMMON(name, realvec, hdlr) \
@@ -1539,7 +1539,7 @@ TRAMP_KVM_BEGIN(do_kvm_0xc00)
SET_SCRATCH0(r10)
std r9,PACA_EXGEN+EX_R9(r13)
mfcr r9
- KVM_HANDLER PACA_EXGEN, EXC_STD, 0xc00, 0
+ KVM_HANDLER 0xc00, EXC_STD, PACA_EXGEN, 0
#endif
--
2.22.0
^ permalink raw reply related
* [PATCH 10/18] powerpc/64s/exception: Add INT_KVM_HANDLER gas macro
From: Nicholas Piggin @ 2019-07-29 14:12 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Nicholas Piggin
In-Reply-To: <20190729141247.26762-1-npiggin@gmail.com>
Replace the 4 variants of cpp macros with one gas macro.
No generated code change except BUG line number constants.
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
---
arch/powerpc/kernel/exceptions-64s.S | 99 +++++++++++-----------------
1 file changed, 40 insertions(+), 59 deletions(-)
diff --git a/arch/powerpc/kernel/exceptions-64s.S b/arch/powerpc/kernel/exceptions-64s.S
index e5122ace5f05..4b2d4c8f8831 100644
--- a/arch/powerpc/kernel/exceptions-64s.S
+++ b/arch/powerpc/kernel/exceptions-64s.S
@@ -651,22 +651,14 @@ END_FTR_SECTION_IFSET(CPU_FTR_CAN_NAP)
.endif
.endm
-
-#define TRAMP_KVM(area, n) \
- TRAMP_KVM_BEGIN(do_kvm_##n); \
- KVM_HANDLER area, EXC_STD, n, 0
-
-#define TRAMP_KVM_SKIP(area, n) \
- TRAMP_KVM_BEGIN(do_kvm_##n); \
- KVM_HANDLER area, EXC_STD, n, 1
-
-#define TRAMP_KVM_HV(area, n) \
- TRAMP_KVM_BEGIN(do_kvm_H##n); \
- KVM_HANDLER area, EXC_HV, n, 0
-
-#define TRAMP_KVM_HV_SKIP(area, n) \
- TRAMP_KVM_BEGIN(do_kvm_H##n); \
- KVM_HANDLER area, EXC_HV, n, 1
+.macro INT_KVM_HANDLER vec, hsrr, area, skip
+ .if \hsrr
+ TRAMP_KVM_BEGIN(do_kvm_H\vec\())
+ .else
+ TRAMP_KVM_BEGIN(do_kvm_\vec\())
+ .endif
+ KVM_HANDLER \area, \hsrr, \vec, \skip
+.endm
#define EXC_COMMON(name, realvec, hdlr) \
EXC_COMMON_BEGIN(name); \
@@ -827,9 +819,8 @@ END_FTR_SECTION_IFSET(CPU_FTR_HVMODE | CPU_FTR_ARCH_206)
* be dangerous anyway.
*/
EXC_REAL_END(system_reset, 0x100, 0x100)
-
EXC_VIRT_NONE(0x4100, 0x100)
-TRAMP_KVM(PACA_EXNMI, 0x100)
+INT_KVM_HANDLER 0x100, EXC_STD, PACA_EXNMI, 0
#ifdef CONFIG_PPC_P7_NAP
TRAMP_REAL_BEGIN(system_reset_idle_wake)
@@ -923,7 +914,7 @@ TRAMP_REAL_BEGIN(machine_check_fwnmi)
INT_HANDLER machine_check, 0x200, 0, 1, 0, EXC_STD, PACA_EXMC, 0, 1, 1, 0, 0
#endif
-TRAMP_KVM_SKIP(PACA_EXMC, 0x200)
+INT_KVM_HANDLER 0x200, EXC_STD, PACA_EXMC, 1
#define MACHINE_CHECK_HANDLER_WINDUP \
/* Clear MSR_RI before setting SRR0 and SRR1. */\
@@ -1162,9 +1153,7 @@ EXC_REAL_END(data_access, 0x300, 0x80)
EXC_VIRT_BEGIN(data_access, 0x4300, 0x80)
INT_HANDLER data_access, 0x300, 0, 0, 1, EXC_STD, PACA_EXGEN, 1, 1, 1, 0, 0
EXC_VIRT_END(data_access, 0x4300, 0x80)
-
-TRAMP_KVM_SKIP(PACA_EXGEN, 0x300)
-
+INT_KVM_HANDLER 0x300, EXC_STD, PACA_EXGEN, 1
EXC_COMMON_BEGIN(data_access_common)
/*
* Here r13 points to the paca, r9 contains the saved CR,
@@ -1193,9 +1182,7 @@ EXC_REAL_END(data_access_slb, 0x380, 0x80)
EXC_VIRT_BEGIN(data_access_slb, 0x4380, 0x80)
INT_HANDLER data_access_slb, 0x380, 0, 0, 1, 0, PACA_EXSLB, 1, 1, 0, 0, 0
EXC_VIRT_END(data_access_slb, 0x4380, 0x80)
-
-TRAMP_KVM_SKIP(PACA_EXSLB, 0x380)
-
+INT_KVM_HANDLER 0x380, EXC_STD, PACA_EXSLB, 1
EXC_COMMON_BEGIN(data_access_slb_common)
EXCEPTION_COMMON(PACA_EXSLB, 0x380)
ld r4,PACA_EXSLB+EX_DAR(r13)
@@ -1228,9 +1215,7 @@ EXC_REAL_END(instruction_access, 0x400, 0x80)
EXC_VIRT_BEGIN(instruction_access, 0x4400, 0x80)
INT_HANDLER instruction_access, 0x400, 0, 0, 1, EXC_STD, PACA_EXGEN, 1, 0, 0, 0, 0
EXC_VIRT_END(instruction_access, 0x4400, 0x80)
-
-TRAMP_KVM(PACA_EXGEN, 0x400)
-
+INT_KVM_HANDLER 0x400, EXC_STD, PACA_EXGEN, 0
EXC_COMMON_BEGIN(instruction_access_common)
EXCEPTION_COMMON(PACA_EXGEN, 0x400)
RECONCILE_IRQ_STATE(r10, r11)
@@ -1253,8 +1238,7 @@ EXC_REAL_END(instruction_access_slb, 0x480, 0x80)
EXC_VIRT_BEGIN(instruction_access_slb, 0x4480, 0x80)
INT_HANDLER instruction_access_slb, 0x480, 0, 0, 1, EXC_STD, PACA_EXSLB, 1, 0, 0, 0, 0
EXC_VIRT_END(instruction_access_slb, 0x4480, 0x80)
-TRAMP_KVM(PACA_EXSLB, 0x480)
-
+INT_KVM_HANDLER 0x480, EXC_STD, PACA_EXSLB, 0
EXC_COMMON_BEGIN(instruction_access_slb_common)
EXCEPTION_COMMON(PACA_EXSLB, 0x480)
ld r4,_NIP(r1)
@@ -1285,9 +1269,8 @@ EXC_REAL_END(hardware_interrupt, 0x500, 0x100)
EXC_VIRT_BEGIN(hardware_interrupt, 0x4500, 0x100)
INT_HANDLER hardware_interrupt, 0x500, 0, 0, 1, EXC_HV_OR_STD, PACA_EXGEN, 1, 0, 0, IRQS_DISABLED, 1
EXC_VIRT_END(hardware_interrupt, 0x4500, 0x100)
-
-TRAMP_KVM(PACA_EXGEN, 0x500)
-TRAMP_KVM_HV(PACA_EXGEN, 0x500)
+INT_KVM_HANDLER 0x500, EXC_STD, PACA_EXGEN, 0
+INT_KVM_HANDLER 0x500, EXC_HV, PACA_EXGEN, 0
EXC_COMMON_ASYNC(hardware_interrupt_common, 0x500, do_IRQ)
@@ -1297,8 +1280,7 @@ EXC_REAL_END(alignment, 0x600, 0x100)
EXC_VIRT_BEGIN(alignment, 0x4600, 0x100)
INT_HANDLER alignment, 0x600, 0, 0, 1, EXC_STD, PACA_EXGEN, 1, 1, 1, 0, 0
EXC_VIRT_END(alignment, 0x4600, 0x100)
-
-TRAMP_KVM(PACA_EXGEN, 0x600)
+INT_KVM_HANDLER 0x600, EXC_STD, PACA_EXGEN, 0
EXC_COMMON_BEGIN(alignment_common)
EXCEPTION_COMMON(PACA_EXGEN, 0x600)
ld r3,PACA_EXGEN+EX_DAR(r13)
@@ -1318,7 +1300,7 @@ EXC_REAL_END(program_check, 0x700, 0x100)
EXC_VIRT_BEGIN(program_check, 0x4700, 0x100)
INT_HANDLER program_check, 0x700, 0, 0, 1, EXC_STD, PACA_EXGEN, 1, 0, 0, 0, 0
EXC_VIRT_END(program_check, 0x4700, 0x100)
-TRAMP_KVM(PACA_EXGEN, 0x700)
+INT_KVM_HANDLER 0x700, EXC_STD, PACA_EXGEN, 0
EXC_COMMON_BEGIN(program_check_common)
/*
* It's possible to receive a TM Bad Thing type program check with
@@ -1360,7 +1342,7 @@ EXC_REAL_END(fp_unavailable, 0x800, 0x100)
EXC_VIRT_BEGIN(fp_unavailable, 0x4800, 0x100)
INT_HANDLER fp_unavailable, 0x800, 0, 0, 1, EXC_STD, PACA_EXGEN, 1, 0, 0, 0, 0
EXC_VIRT_END(fp_unavailable, 0x4800, 0x100)
-TRAMP_KVM(PACA_EXGEN, 0x800)
+INT_KVM_HANDLER 0x800, EXC_STD, PACA_EXGEN, 0
EXC_COMMON_BEGIN(fp_unavailable_common)
EXCEPTION_COMMON(PACA_EXGEN, 0x800)
bne 1f /* if from user, just load it up */
@@ -1397,7 +1379,7 @@ EXC_REAL_END(decrementer, 0x900, 0x80)
EXC_VIRT_BEGIN(decrementer, 0x4900, 0x80)
INT_HANDLER decrementer, 0x900, 0, 0, 1, EXC_STD, PACA_EXGEN, 1, 0, 0, IRQS_DISABLED, 0
EXC_VIRT_END(decrementer, 0x4900, 0x80)
-TRAMP_KVM(PACA_EXGEN, 0x900)
+INT_KVM_HANDLER 0x900, EXC_STD, PACA_EXGEN, 0
EXC_COMMON_ASYNC(decrementer_common, 0x900, timer_interrupt)
@@ -1407,7 +1389,7 @@ EXC_REAL_END(hdecrementer, 0x980, 0x80)
EXC_VIRT_BEGIN(hdecrementer, 0x4980, 0x80)
INT_HANDLER hdecrementer, 0x980, 0, 0, 1, EXC_HV, PACA_EXGEN, 1, 0, 0, 0, 1
EXC_VIRT_END(hdecrementer, 0x4980, 0x80)
-TRAMP_KVM_HV(PACA_EXGEN, 0x980)
+INT_KVM_HANDLER 0x980, EXC_HV, PACA_EXGEN, 0
EXC_COMMON(hdecrementer_common, 0x980, hdec_interrupt)
@@ -1417,7 +1399,7 @@ EXC_REAL_END(doorbell_super, 0xa00, 0x100)
EXC_VIRT_BEGIN(doorbell_super, 0x4a00, 0x100)
INT_HANDLER doorbell_super, 0xa00, 0, 0, 1, EXC_STD, PACA_EXGEN, 1, 0, 0, IRQS_DISABLED, 0
EXC_VIRT_END(doorbell_super, 0x4a00, 0x100)
-TRAMP_KVM(PACA_EXGEN, 0xa00)
+INT_KVM_HANDLER 0xa00, EXC_STD, PACA_EXGEN, 0
#ifdef CONFIG_PPC_DOORBELL
EXC_COMMON_ASYNC(doorbell_super_common, 0xa00, doorbell_exception)
#else
@@ -1567,7 +1549,7 @@ EXC_REAL_END(single_step, 0xd00, 0x100)
EXC_VIRT_BEGIN(single_step, 0x4d00, 0x100)
INT_HANDLER single_step, 0xd00, 0, 0, 1, EXC_STD, PACA_EXGEN, 1, 0, 0, 0, 0
EXC_VIRT_END(single_step, 0x4d00, 0x100)
-TRAMP_KVM(PACA_EXGEN, 0xd00)
+INT_KVM_HANDLER 0xd00, EXC_STD, PACA_EXGEN, 0
EXC_COMMON(single_step_common, 0xd00, single_step_exception)
@@ -1577,7 +1559,7 @@ EXC_REAL_END(h_data_storage, 0xe00, 0x20)
EXC_VIRT_BEGIN(h_data_storage, 0x4e00, 0x20)
INT_HANDLER h_data_storage, 0xe00, 1, 0, 1, EXC_HV, PACA_EXGEN, 1, 1, 1, 0, 1
EXC_VIRT_END(h_data_storage, 0x4e00, 0x20)
-TRAMP_KVM_HV_SKIP(PACA_EXGEN, 0xe00)
+INT_KVM_HANDLER 0xe00, EXC_HV, PACA_EXGEN, 1
EXC_COMMON_BEGIN(h_data_storage_common)
EXCEPTION_COMMON(PACA_EXGEN, 0xe00)
bl save_nvgprs
@@ -1602,7 +1584,7 @@ EXC_REAL_END(h_instr_storage, 0xe20, 0x20)
EXC_VIRT_BEGIN(h_instr_storage, 0x4e20, 0x20)
INT_HANDLER h_instr_storage, 0xe20, 1, 0, 1, EXC_HV, PACA_EXGEN, 1, 0, 0, 0, 1
EXC_VIRT_END(h_instr_storage, 0x4e20, 0x20)
-TRAMP_KVM_HV(PACA_EXGEN, 0xe20)
+INT_KVM_HANDLER 0xe20, EXC_HV, PACA_EXGEN, 0
EXC_COMMON(h_instr_storage_common, 0xe20, unknown_exception)
@@ -1612,7 +1594,7 @@ EXC_REAL_END(emulation_assist, 0xe40, 0x20)
EXC_VIRT_BEGIN(emulation_assist, 0x4e40, 0x20)
INT_HANDLER emulation_assist, 0xe40, 1, 0, 1, EXC_HV, PACA_EXGEN, 1, 0, 0, 0, 1
EXC_VIRT_END(emulation_assist, 0x4e40, 0x20)
-TRAMP_KVM_HV(PACA_EXGEN, 0xe40)
+INT_KVM_HANDLER 0xe40, EXC_HV, PACA_EXGEN, 0
EXC_COMMON(emulation_assist_common, 0xe40, emulation_assist_interrupt)
@@ -1625,8 +1607,7 @@ EXC_REAL_BEGIN(hmi_exception, 0xe60, 0x20)
INT_HANDLER hmi_exception, 0xe60, 1, 1, 0, EXC_HV, PACA_EXGEN, 0, 0, 0, 0, 1
EXC_REAL_END(hmi_exception, 0xe60, 0x20)
EXC_VIRT_NONE(0x4e60, 0x20)
-TRAMP_KVM_HV(PACA_EXGEN, 0xe60)
-
+INT_KVM_HANDLER 0xe60, EXC_HV, PACA_EXGEN, 0
EXC_COMMON_BEGIN(hmi_exception_early_common)
mtctr r10 /* Restore ctr */
mfspr r11,SPRN_HSRR0 /* Save HSRR0 */
@@ -1671,7 +1652,7 @@ EXC_REAL_END(h_doorbell, 0xe80, 0x20)
EXC_VIRT_BEGIN(h_doorbell, 0x4e80, 0x20)
INT_HANDLER h_doorbell, 0xe80, 1, 0, 1, EXC_HV, PACA_EXGEN, 1, 0, 0, IRQS_DISABLED, 1
EXC_VIRT_END(h_doorbell, 0x4e80, 0x20)
-TRAMP_KVM_HV(PACA_EXGEN, 0xe80)
+INT_KVM_HANDLER 0xe80, EXC_HV, PACA_EXGEN, 0
#ifdef CONFIG_PPC_DOORBELL
EXC_COMMON_ASYNC(h_doorbell_common, 0xe80, doorbell_exception)
#else
@@ -1685,7 +1666,7 @@ EXC_REAL_END(h_virt_irq, 0xea0, 0x20)
EXC_VIRT_BEGIN(h_virt_irq, 0x4ea0, 0x20)
INT_HANDLER h_virt_irq, 0xea0, 1, 0, 1, EXC_HV, PACA_EXGEN, 1, 0, 0, IRQS_DISABLED, 1
EXC_VIRT_END(h_virt_irq, 0x4ea0, 0x20)
-TRAMP_KVM_HV(PACA_EXGEN, 0xea0)
+INT_KVM_HANDLER 0xea0, EXC_HV, PACA_EXGEN, 0
EXC_COMMON_ASYNC(h_virt_irq_common, 0xea0, do_IRQ)
@@ -1701,7 +1682,7 @@ EXC_REAL_END(performance_monitor, 0xf00, 0x20)
EXC_VIRT_BEGIN(performance_monitor, 0x4f00, 0x20)
INT_HANDLER performance_monitor, 0xf00, 1, 0, 1, EXC_STD, PACA_EXGEN, 1, 0, 0, IRQS_PMI_DISABLED, 0
EXC_VIRT_END(performance_monitor, 0x4f00, 0x20)
-TRAMP_KVM(PACA_EXGEN, 0xf00)
+INT_KVM_HANDLER 0xf00, EXC_STD, PACA_EXGEN, 0
EXC_COMMON_ASYNC(performance_monitor_common, 0xf00, performance_monitor_exception)
@@ -1711,7 +1692,7 @@ EXC_REAL_END(altivec_unavailable, 0xf20, 0x20)
EXC_VIRT_BEGIN(altivec_unavailable, 0x4f20, 0x20)
INT_HANDLER altivec_unavailable, 0xf20, 1, 0, 1, EXC_STD, PACA_EXGEN, 1, 0, 0, 0, 0
EXC_VIRT_END(altivec_unavailable, 0x4f20, 0x20)
-TRAMP_KVM(PACA_EXGEN, 0xf20)
+INT_KVM_HANDLER 0xf20, EXC_STD, PACA_EXGEN, 0
EXC_COMMON_BEGIN(altivec_unavailable_common)
EXCEPTION_COMMON(PACA_EXGEN, 0xf20)
#ifdef CONFIG_ALTIVEC
@@ -1752,7 +1733,7 @@ EXC_REAL_END(vsx_unavailable, 0xf40, 0x20)
EXC_VIRT_BEGIN(vsx_unavailable, 0x4f40, 0x20)
INT_HANDLER vsx_unavailable, 0xf40, 1, 0, 1, EXC_STD, PACA_EXGEN, 1, 0, 0, 0, 0
EXC_VIRT_END(vsx_unavailable, 0x4f40, 0x20)
-TRAMP_KVM(PACA_EXGEN, 0xf40)
+INT_KVM_HANDLER 0xf40, EXC_STD, PACA_EXGEN, 0
EXC_COMMON_BEGIN(vsx_unavailable_common)
EXCEPTION_COMMON(PACA_EXGEN, 0xf40)
#ifdef CONFIG_VSX
@@ -1792,7 +1773,7 @@ EXC_REAL_END(facility_unavailable, 0xf60, 0x20)
EXC_VIRT_BEGIN(facility_unavailable, 0x4f60, 0x20)
INT_HANDLER facility_unavailable, 0xf60, 1, 0, 1, EXC_STD, PACA_EXGEN, 1, 0, 0, 0, 0
EXC_VIRT_END(facility_unavailable, 0x4f60, 0x20)
-TRAMP_KVM(PACA_EXGEN, 0xf60)
+INT_KVM_HANDLER 0xf60, EXC_STD, PACA_EXGEN, 0
EXC_COMMON(facility_unavailable_common, 0xf60, facility_unavailable_exception)
@@ -1802,7 +1783,7 @@ EXC_REAL_END(h_facility_unavailable, 0xf80, 0x20)
EXC_VIRT_BEGIN(h_facility_unavailable, 0x4f80, 0x20)
INT_HANDLER h_facility_unavailable, 0xf80, 1, 0, 1, EXC_HV, PACA_EXGEN, 1, 0, 0, 0, 1
EXC_VIRT_END(h_facility_unavailable, 0x4f80, 0x20)
-TRAMP_KVM_HV(PACA_EXGEN, 0xf80)
+INT_KVM_HANDLER 0xf80, EXC_HV, PACA_EXGEN, 0
EXC_COMMON(h_facility_unavailable_common, 0xf80, facility_unavailable_exception)
@@ -1823,7 +1804,7 @@ EXC_REAL_BEGIN(cbe_system_error, 0x1200, 0x20)
INT_HANDLER cbe_system_error, 0x1200, 1, 0, 0, EXC_HV, PACA_EXGEN, 1, 0, 0, 0, 1
EXC_REAL_END(cbe_system_error, 0x1200, 0x20)
EXC_VIRT_NONE(0x5200, 0x100)
-TRAMP_KVM_HV_SKIP(PACA_EXGEN, 0x1200)
+INT_KVM_HANDLER 0x1200, EXC_HV, PACA_EXGEN, 1
EXC_COMMON(cbe_system_error_common, 0x1200, cbe_system_error_exception)
#else /* CONFIG_CBE_RAS */
EXC_REAL_NONE(0x1200, 0x100)
@@ -1837,7 +1818,7 @@ EXC_REAL_END(instruction_breakpoint, 0x1300, 0x100)
EXC_VIRT_BEGIN(instruction_breakpoint, 0x5300, 0x100)
INT_HANDLER instruction_breakpoint, 0x1300, 0, 0, 1, EXC_STD, PACA_EXGEN, 1, 0, 0, 0, 0
EXC_VIRT_END(instruction_breakpoint, 0x5300, 0x100)
-TRAMP_KVM_SKIP(PACA_EXGEN, 0x1300)
+INT_KVM_HANDLER 0x1300, EXC_STD, PACA_EXGEN, 1
EXC_COMMON(instruction_breakpoint_common, 0x1300, instruction_breakpoint_exception)
@@ -1867,7 +1848,7 @@ EXC_VIRT_END(denorm_exception, 0x5500, 0x100)
EXC_VIRT_NONE(0x5500, 0x100)
#endif
-TRAMP_KVM_HV(PACA_EXGEN, 0x1500)
+INT_KVM_HANDLER 0x1500, EXC_HV, PACA_EXGEN, 0
#ifdef CONFIG_PPC_DENORMALISATION
TRAMP_REAL_BEGIN(denorm_assist)
@@ -1946,7 +1927,7 @@ EXC_REAL_BEGIN(cbe_maintenance, 0x1600, 0x20)
INT_HANDLER cbe_maintenance, 0x1600, 1, 0, 0, EXC_HV, PACA_EXGEN, 1, 0, 0, 0, 1
EXC_REAL_END(cbe_maintenance, 0x1600, 0x20)
EXC_VIRT_NONE(0x5600, 0x100)
-TRAMP_KVM_HV_SKIP(PACA_EXGEN, 0x1600)
+INT_KVM_HANDLER 0x1600, EXC_HV, PACA_EXGEN, 1
EXC_COMMON(cbe_maintenance_common, 0x1600, cbe_maintenance_exception)
#else /* CONFIG_CBE_RAS */
EXC_REAL_NONE(0x1600, 0x100)
@@ -1960,7 +1941,7 @@ EXC_REAL_END(altivec_assist, 0x1700, 0x100)
EXC_VIRT_BEGIN(altivec_assist, 0x5700, 0x100)
INT_HANDLER altivec_assist, 0x1700, 0, 0, 1, EXC_STD, PACA_EXGEN, 1, 0, 0, 0, 0
EXC_VIRT_END(altivec_assist, 0x5700, 0x100)
-TRAMP_KVM(PACA_EXGEN, 0x1700)
+INT_KVM_HANDLER 0x1700, EXC_STD, PACA_EXGEN, 0
#ifdef CONFIG_ALTIVEC
EXC_COMMON(altivec_assist_common, 0x1700, altivec_assist_exception)
#else
@@ -1973,7 +1954,7 @@ EXC_REAL_BEGIN(cbe_thermal, 0x1800, 0x20)
INT_HANDLER cbe_thermal, 0x1800, 1, 0, 0, EXC_HV, PACA_EXGEN, 1, 0, 0, 0, 1
EXC_REAL_END(cbe_thermal, 0x1800, 0x20)
EXC_VIRT_NONE(0x5800, 0x100)
-TRAMP_KVM_HV_SKIP(PACA_EXGEN, 0x1800)
+INT_KVM_HANDLER 0x1800, EXC_HV, PACA_EXGEN, 1
EXC_COMMON(cbe_thermal_common, 0x1800, cbe_thermal_exception)
#else /* CONFIG_CBE_RAS */
EXC_REAL_NONE(0x1800, 0x100)
--
2.22.0
^ permalink raw reply related
* [PATCH 09/18] powerpc/64s/exception: INT_HANDLER support HDAR/HDSISR and use it in HDSI
From: Nicholas Piggin @ 2019-07-29 14:12 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Nicholas Piggin
In-Reply-To: <20190729141247.26762-1-npiggin@gmail.com>
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
---
arch/powerpc/kernel/exceptions-64s.S | 16 ++++++++++------
1 file changed, 10 insertions(+), 6 deletions(-)
diff --git a/arch/powerpc/kernel/exceptions-64s.S b/arch/powerpc/kernel/exceptions-64s.S
index 1c07b5fc6692..e5122ace5f05 100644
--- a/arch/powerpc/kernel/exceptions-64s.S
+++ b/arch/powerpc/kernel/exceptions-64s.S
@@ -620,11 +620,19 @@ END_FTR_SECTION_IFSET(CPU_FTR_CAN_NAP)
GET_SCRATCH0(r10)
std r10,\area\()+EX_R13(r13)
.if \dar
+ .if \hsrr
+ mfspr r10,SPRN_HDAR
+ .else
mfspr r10,SPRN_DAR
+ .endif
std r10,\area\()+EX_DAR(r13)
.endif
.if \dsisr
+ .if \hsrr
+ mfspr r10,SPRN_HDSISR
+ .else
mfspr r10,SPRN_DSISR
+ .endif
stw r10,\area\()+EX_DSISR(r13)
.endif
@@ -1564,17 +1572,13 @@ EXC_COMMON(single_step_common, 0xd00, single_step_exception)
EXC_REAL_BEGIN(h_data_storage, 0xe00, 0x20)
- INT_HANDLER h_data_storage, 0xe00, 1, 0, 0, EXC_HV, PACA_EXGEN, 1, 0, 0, 0, 1
+ INT_HANDLER h_data_storage, 0xe00, 1, 0, 0, EXC_HV, PACA_EXGEN, 1, 1, 1, 0, 1
EXC_REAL_END(h_data_storage, 0xe00, 0x20)
EXC_VIRT_BEGIN(h_data_storage, 0x4e00, 0x20)
- INT_HANDLER h_data_storage, 0xe00, 1, 0, 1, EXC_HV, PACA_EXGEN, 1, 0, 0, 0, 1
+ INT_HANDLER h_data_storage, 0xe00, 1, 0, 1, EXC_HV, PACA_EXGEN, 1, 1, 1, 0, 1
EXC_VIRT_END(h_data_storage, 0x4e00, 0x20)
TRAMP_KVM_HV_SKIP(PACA_EXGEN, 0xe00)
EXC_COMMON_BEGIN(h_data_storage_common)
- mfspr r10,SPRN_HDAR
- std r10,PACA_EXGEN+EX_DAR(r13)
- mfspr r10,SPRN_HDSISR
- stw r10,PACA_EXGEN+EX_DSISR(r13)
EXCEPTION_COMMON(PACA_EXGEN, 0xe00)
bl save_nvgprs
RECONCILE_IRQ_STATE(r10, r11)
--
2.22.0
^ permalink raw reply related
* [PATCH 08/18] powerpc/64s/exception: Add the virt variant of the denorm interrupt handler
From: Nicholas Piggin @ 2019-07-29 14:12 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Nicholas Piggin
In-Reply-To: <20190729141247.26762-1-npiggin@gmail.com>
All other virt handlers have the prolog code in the virt vector rather
than branch to the real vector. Follow this pattern in the denorm virt
handler.
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
---
arch/powerpc/kernel/exceptions-64s.S | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/arch/powerpc/kernel/exceptions-64s.S b/arch/powerpc/kernel/exceptions-64s.S
index 94f885c58022..1c07b5fc6692 100644
--- a/arch/powerpc/kernel/exceptions-64s.S
+++ b/arch/powerpc/kernel/exceptions-64s.S
@@ -1853,7 +1853,11 @@ EXC_REAL_END(denorm_exception_hv, 0x1500, 0x100)
#ifdef CONFIG_PPC_DENORMALISATION
EXC_VIRT_BEGIN(denorm_exception, 0x5500, 0x100)
- b exc_real_0x1500_denorm_exception_hv
+ INT_HANDLER denorm_exception, 0x1500, 0, 2, 1, EXC_HV, PACA_EXGEN, 1, 0, 0, 0, 0
+ mfspr r10,SPRN_HSRR1
+ andis. r10,r10,(HSRR1_DENORM)@h /* denorm? */
+ bne+ denorm_assist
+ INT_VIRT_SAVE_SRR_AND_JUMP denorm_common, EXC_HV
EXC_VIRT_END(denorm_exception, 0x5500, 0x100)
#else
EXC_VIRT_NONE(0x5500, 0x100)
--
2.22.0
^ permalink raw reply related
* [PATCH 07/18] powerpc/64s/exception: remove EXCEPTION_PROLOG_0/1, rename _2
From: Nicholas Piggin @ 2019-07-29 14:12 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Nicholas Piggin
In-Reply-To: <20190729141247.26762-1-npiggin@gmail.com>
EXCEPTION_PROLOG_0 and _1 have only a single caller, so expand them
into it.
Rename EXCEPTION_PROLOG_2_REAL to INT_SAVE_SRR_AND_JUMP and
EXCEPTION_PROLOG_2_VIRT to INT_VIRT_SAVE_SRR_AND_JUMP, which are
more descriptive.
No generated code change except BUG line number constants.
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
---
arch/powerpc/kernel/exceptions-64s.S | 151 +++++++++++++--------------
1 file changed, 73 insertions(+), 78 deletions(-)
diff --git a/arch/powerpc/kernel/exceptions-64s.S b/arch/powerpc/kernel/exceptions-64s.S
index b07de1106d9e..94f885c58022 100644
--- a/arch/powerpc/kernel/exceptions-64s.S
+++ b/arch/powerpc/kernel/exceptions-64s.S
@@ -180,77 +180,7 @@ BEGIN_FTR_SECTION_NESTED(943) \
std ra,offset(r13); \
END_FTR_SECTION_NESTED(ftr,ftr,943)
-.macro EXCEPTION_PROLOG_0 area
- SET_SCRATCH0(r13) /* save r13 */
- GET_PACA(r13)
- std r9,\area\()+EX_R9(r13) /* save r9 */
- OPT_GET_SPR(r9, SPRN_PPR, CPU_FTR_HAS_PPR)
- HMT_MEDIUM
- std r10,\area\()+EX_R10(r13) /* save r10 - r12 */
- OPT_GET_SPR(r10, SPRN_CFAR, CPU_FTR_CFAR)
-.endm
-
-.macro EXCEPTION_PROLOG_1 hsrr, area, kvm, vec, dar, dsisr, bitmask
- OPT_SAVE_REG_TO_PACA(\area\()+EX_PPR, r9, CPU_FTR_HAS_PPR)
- OPT_SAVE_REG_TO_PACA(\area\()+EX_CFAR, r10, CPU_FTR_CFAR)
- INTERRUPT_TO_KERNEL
- SAVE_CTR(r10, \area\())
- mfcr r9
- .if \kvm
- KVMTEST \hsrr \vec
- .endif
- .if \bitmask
- lbz r10,PACAIRQSOFTMASK(r13)
- andi. r10,r10,\bitmask
- /* Associate vector numbers with bits in paca->irq_happened */
- .if \vec == 0x500 || \vec == 0xea0
- li r10,PACA_IRQ_EE
- .elseif \vec == 0x900
- li r10,PACA_IRQ_DEC
- .elseif \vec == 0xa00 || \vec == 0xe80
- li r10,PACA_IRQ_DBELL
- .elseif \vec == 0xe60
- li r10,PACA_IRQ_HMI
- .elseif \vec == 0xf00
- li r10,PACA_IRQ_PMI
- .else
- .abort "Bad maskable vector"
- .endif
-
- .if \hsrr == EXC_HV_OR_STD
- BEGIN_FTR_SECTION
- bne masked_Hinterrupt
- FTR_SECTION_ELSE
- bne masked_interrupt
- ALT_FTR_SECTION_END_IFSET(CPU_FTR_HVMODE | CPU_FTR_ARCH_206)
- .elseif \hsrr
- bne masked_Hinterrupt
- .else
- bne masked_interrupt
- .endif
- .endif
-
- std r11,\area\()+EX_R11(r13)
- std r12,\area\()+EX_R12(r13)
-
- /*
- * DAR/DSISR, SCRATCH0 must be read before setting MSR[RI],
- * because a d-side MCE will clobber those registers so is
- * not recoverable if they are live.
- */
- GET_SCRATCH0(r10)
- std r10,\area\()+EX_R13(r13)
- .if \dar
- mfspr r10,SPRN_DAR
- std r10,\area\()+EX_DAR(r13)
- .endif
- .if \dsisr
- mfspr r10,SPRN_DSISR
- stw r10,\area\()+EX_DSISR(r13)
- .endif
-.endm
-
-.macro EXCEPTION_PROLOG_2_REAL label, hsrr, set_ri
+.macro INT_SAVE_SRR_AND_JUMP label, hsrr, set_ri
ld r10,PACAKMSR(r13) /* get MSR value for kernel */
.if ! \set_ri
xori r10,r10,MSR_RI /* Clear MSR_RI */
@@ -293,7 +223,8 @@ END_FTR_SECTION_NESTED(ftr,ftr,943)
b . /* prevent speculative execution */
.endm
-.macro EXCEPTION_PROLOG_2_VIRT label, hsrr
+/* INT_SAVE_SRR_AND_JUMP works for real or virt, this is faster but virt only */
+.macro INT_VIRT_SAVE_SRR_AND_JUMP label, hsrr
#ifdef CONFIG_RELOCATABLE
.if \hsrr == EXC_HV_OR_STD
BEGIN_FTR_SECTION
@@ -620,7 +551,13 @@ END_FTR_SECTION_IFSET(CPU_FTR_CAN_NAP)
* This is done if early=2.
*/
.macro INT_HANDLER name, vec, ool, early, virt, hsrr, area, ri, dar, dsisr, bitmask, kvm
- EXCEPTION_PROLOG_0 \area
+ SET_SCRATCH0(r13) /* save r13 */
+ GET_PACA(r13)
+ std r9,\area\()+EX_R9(r13) /* save r9 */
+ OPT_GET_SPR(r9, SPRN_PPR, CPU_FTR_HAS_PPR)
+ HMT_MEDIUM
+ std r10,\area\()+EX_R10(r13) /* save r10 - r12 */
+ OPT_GET_SPR(r10, SPRN_CFAR, CPU_FTR_CFAR)
.if \ool
.if !\virt
b tramp_real_\name
@@ -632,16 +569,74 @@ END_FTR_SECTION_IFSET(CPU_FTR_CAN_NAP)
TRAMP_VIRT_BEGIN(tramp_virt_\name)
.endif
.endif
- EXCEPTION_PROLOG_1 \hsrr, \area, \kvm, \vec, \dar, \dsisr, \bitmask
+
+ OPT_SAVE_REG_TO_PACA(\area\()+EX_PPR, r9, CPU_FTR_HAS_PPR)
+ OPT_SAVE_REG_TO_PACA(\area\()+EX_CFAR, r10, CPU_FTR_CFAR)
+ INTERRUPT_TO_KERNEL
+ SAVE_CTR(r10, \area\())
+ mfcr r9
+ .if \kvm
+ KVMTEST \hsrr \vec
+ .endif
+ .if \bitmask
+ lbz r10,PACAIRQSOFTMASK(r13)
+ andi. r10,r10,\bitmask
+ /* Associate vector numbers with bits in paca->irq_happened */
+ .if \vec == 0x500 || \vec == 0xea0
+ li r10,PACA_IRQ_EE
+ .elseif \vec == 0x900
+ li r10,PACA_IRQ_DEC
+ .elseif \vec == 0xa00 || \vec == 0xe80
+ li r10,PACA_IRQ_DBELL
+ .elseif \vec == 0xe60
+ li r10,PACA_IRQ_HMI
+ .elseif \vec == 0xf00
+ li r10,PACA_IRQ_PMI
+ .else
+ .abort "Bad maskable vector"
+ .endif
+
+ .if \hsrr == EXC_HV_OR_STD
+ BEGIN_FTR_SECTION
+ bne masked_Hinterrupt
+ FTR_SECTION_ELSE
+ bne masked_interrupt
+ ALT_FTR_SECTION_END_IFSET(CPU_FTR_HVMODE | CPU_FTR_ARCH_206)
+ .elseif \hsrr
+ bne masked_Hinterrupt
+ .else
+ bne masked_interrupt
+ .endif
+ .endif
+
+ std r11,\area\()+EX_R11(r13)
+ std r12,\area\()+EX_R12(r13)
+
+ /*
+ * DAR/DSISR, SCRATCH0 must be read before setting MSR[RI],
+ * because a d-side MCE will clobber those registers so is
+ * not recoverable if they are live.
+ */
+ GET_SCRATCH0(r10)
+ std r10,\area\()+EX_R13(r13)
+ .if \dar
+ mfspr r10,SPRN_DAR
+ std r10,\area\()+EX_DAR(r13)
+ .endif
+ .if \dsisr
+ mfspr r10,SPRN_DSISR
+ stw r10,\area\()+EX_DSISR(r13)
+ .endif
+
.if \early == 2
/* nothing more */
.elseif \early
mfctr r10 /* save ctr, even for !RELOCATABLE */
BRANCH_TO_C000(r11, \name\()_early_common)
.elseif !\virt
- EXCEPTION_PROLOG_2_REAL \name\()_common, \hsrr, \ri
+ INT_SAVE_SRR_AND_JUMP \name\()_common, \hsrr, \ri
.else
- EXCEPTION_PROLOG_2_VIRT \name\()_common, \hsrr
+ INT_VIRT_SAVE_SRR_AND_JUMP \name\()_common, \hsrr
.endif
.if \ool
.popsection
@@ -1853,7 +1848,7 @@ EXC_REAL_BEGIN(denorm_exception_hv, 0x1500, 0x100)
bne+ denorm_assist
#endif
KVMTEST EXC_HV 0x1500
- EXCEPTION_PROLOG_2_REAL denorm_common, EXC_HV, 1
+ INT_SAVE_SRR_AND_JUMP denorm_common, EXC_HV, 1
EXC_REAL_END(denorm_exception_hv, 0x1500, 0x100)
#ifdef CONFIG_PPC_DENORMALISATION
@@ -1987,7 +1982,7 @@ EXC_VIRT_NONE(0x5800, 0x100)
std r12,PACA_EXGEN+EX_R12(r13); \
GET_SCRATCH0(r10); \
std r10,PACA_EXGEN+EX_R13(r13); \
- EXCEPTION_PROLOG_2_REAL soft_nmi_common, _H, 1
+ INT_SAVE_SRR_AND_JUMP soft_nmi_common, _H, 1
/*
* Branch to soft_nmi_interrupt using the emergency stack. The emergency
--
2.22.0
^ permalink raw reply related
* [PATCH 06/18] powerpc/64s/exception: Replace PROLOG macros and EXC helpers with a gas macro
From: Nicholas Piggin @ 2019-07-29 14:12 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Nicholas Piggin
In-Reply-To: <20190729141247.26762-1-npiggin@gmail.com>
This creates a single macro that generates the exception prolog code,
with variants specified by arguments, rather than assorted nested
macros for different variants.
The increasing length of macro argument list is not nice to read or
modify, but this is a temporary condition that will be improved in
later changes.
No generated code change except BUG line number constants and label
names.
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
---
arch/powerpc/kernel/exceptions-64s.S | 502 +++++++++++----------------
1 file changed, 206 insertions(+), 296 deletions(-)
diff --git a/arch/powerpc/kernel/exceptions-64s.S b/arch/powerpc/kernel/exceptions-64s.S
index 9c407392774c..b07de1106d9e 100644
--- a/arch/powerpc/kernel/exceptions-64s.S
+++ b/arch/powerpc/kernel/exceptions-64s.S
@@ -43,6 +43,17 @@
.endif
#endif
+/*
+ * Following are fixed section helper macros.
+ *
+ * EXC_REAL_BEGIN/END - real, unrelocated exception vectors
+ * EXC_VIRT_BEGIN/END - virt (AIL), unrelocated exception vectors
+ * TRAMP_REAL_BEGIN - real, unrelocated helpers (virt may call these)
+ * TRAMP_VIRT_BEGIN - virt, unreloc helpers (in practice, real can use)
+ * TRAMP_KVM_BEGIN - KVM handlers, these are put into real, unrelocated
+ * EXC_COMMON - After switching to virtual, relocated mode.
+ */
+
#define EXC_REAL_BEGIN(name, start, size) \
FIXED_SECTION_ENTRY_BEGIN_LOCATION(real_vectors, exc_real_##start##_##name, start, size)
@@ -589,196 +600,54 @@ END_FTR_SECTION_IFSET(CPU_FTR_CAN_NAP)
#endif
/*
- * Following are the BOOK3S exception handler helper macros.
- * Handlers come in a number of types, and each type has a number of varieties.
- *
- * EXC_REAL_* - real, unrelocated exception vectors
- * EXC_VIRT_* - virt (AIL), unrelocated exception vectors
- * TRAMP_REAL_* - real, unrelocated helpers (virt can call these)
- * TRAMP_VIRT_* - virt, unreloc helpers (in practice, real can use)
- * TRAMP_KVM - KVM handlers that get put into real, unrelocated
- * EXC_COMMON - virt, relocated common handlers
- *
- * The EXC handlers are given a name, and branch to name_common, or the
- * appropriate KVM or masking function. Vector handler verieties are as
- * follows:
- *
- * EXC_{REAL|VIRT}_BEGIN/END - used to open-code the exception
- *
- * EXC_{REAL|VIRT} - standard exception
- *
- * EXC_{REAL|VIRT}_suffix
- * where _suffix is:
- * - _MASKABLE - maskable exception
- * - _OOL - out of line with trampoline to common handler
- * - _HV - HV exception
- *
- * There can be combinations, e.g., EXC_VIRT_OOL_MASKABLE_HV
+ * This is the BOOK3S interrupt entry code macro.
*
- * KVM handlers come in the following verieties:
- * TRAMP_KVM
- * TRAMP_KVM_SKIP
- * TRAMP_KVM_HV
- * TRAMP_KVM_HV_SKIP
- *
- * COMMON handlers come in the following verieties:
- * EXC_COMMON_BEGIN/END - used to open-code the handler
- * EXC_COMMON
- * EXC_COMMON_ASYNC
- *
- * TRAMP_REAL and TRAMP_VIRT can be used with BEGIN/END. KVM
- * and OOL handlers are implemented as types of TRAMP and TRAMP_VIRT handlers.
+ * This can result in one of several things happening:
+ * - Branch to the _common handler, relocated, in virtual mode.
+ * These are normal interrupts (synchronous and asynchronous) handled by
+ * the kernel.
+ * - Branch to KVM, relocated but real mode interrupts remain in real mode.
+ * These occur when HSTATE_IN_GUEST is set. The interrupt may be caused by
+ * / intended for host or guest kernel, but KVM must always be involved
+ * because the machine state is set for guest execution.
+ * - Branch to the masked handler, unrelocated.
+ * These occur when maskable asynchronous interrupts are taken with the
+ * irq_soft_mask set.
+ * - Branch to an "early" handler in real mode but relocated.
+ * This is done if early=1. MCE and HMI use these to handle errors in real
+ * mode.
+ * - Fall through and continue executing in real, unrelocated mode.
+ * This is done if early=2.
*/
+.macro INT_HANDLER name, vec, ool, early, virt, hsrr, area, ri, dar, dsisr, bitmask, kvm
+ EXCEPTION_PROLOG_0 \area
+ .if \ool
+ .if !\virt
+ b tramp_real_\name
+ .pushsection .text
+ TRAMP_REAL_BEGIN(tramp_real_\name)
+ .else
+ b tramp_virt_\name
+ .pushsection .text
+ TRAMP_VIRT_BEGIN(tramp_virt_\name)
+ .endif
+ .endif
+ EXCEPTION_PROLOG_1 \hsrr, \area, \kvm, \vec, \dar, \dsisr, \bitmask
+ .if \early == 2
+ /* nothing more */
+ .elseif \early
+ mfctr r10 /* save ctr, even for !RELOCATABLE */
+ BRANCH_TO_C000(r11, \name\()_early_common)
+ .elseif !\virt
+ EXCEPTION_PROLOG_2_REAL \name\()_common, \hsrr, \ri
+ .else
+ EXCEPTION_PROLOG_2_VIRT \name\()_common, \hsrr
+ .endif
+ .if \ool
+ .popsection
+ .endif
+.endm
-#define __EXC_REAL(name, start, size, area) \
- EXC_REAL_BEGIN(name, start, size); \
- EXCEPTION_PROLOG_0 area ; \
- EXCEPTION_PROLOG_1 EXC_STD, area, 1, start, 0, 0, 0 ; \
- EXCEPTION_PROLOG_2_REAL name##_common, EXC_STD, 1 ; \
- EXC_REAL_END(name, start, size)
-
-#define EXC_REAL(name, start, size) \
- __EXC_REAL(name, start, size, PACA_EXGEN)
-
-#define __EXC_VIRT(name, start, size, realvec, area) \
- EXC_VIRT_BEGIN(name, start, size); \
- EXCEPTION_PROLOG_0 area ; \
- EXCEPTION_PROLOG_1 EXC_STD, area, 0, realvec, 0, 0, 0; \
- EXCEPTION_PROLOG_2_VIRT name##_common, EXC_STD ; \
- EXC_VIRT_END(name, start, size)
-
-#define EXC_VIRT(name, start, size, realvec) \
- __EXC_VIRT(name, start, size, realvec, PACA_EXGEN)
-
-#define EXC_REAL_MASKABLE(name, start, size, bitmask) \
- EXC_REAL_BEGIN(name, start, size); \
- EXCEPTION_PROLOG_0 PACA_EXGEN ; \
- EXCEPTION_PROLOG_1 EXC_STD, PACA_EXGEN, 1, start, 0, 0, bitmask ; \
- EXCEPTION_PROLOG_2_REAL name##_common, EXC_STD, 1 ; \
- EXC_REAL_END(name, start, size)
-
-#define EXC_VIRT_MASKABLE(name, start, size, realvec, bitmask) \
- EXC_VIRT_BEGIN(name, start, size); \
- EXCEPTION_PROLOG_0 PACA_EXGEN ; \
- EXCEPTION_PROLOG_1 EXC_STD, PACA_EXGEN, 0, realvec, 0, 0, bitmask ; \
- EXCEPTION_PROLOG_2_VIRT name##_common, EXC_STD ; \
- EXC_VIRT_END(name, start, size)
-
-#define EXC_REAL_HV(name, start, size) \
- EXC_REAL_BEGIN(name, start, size); \
- EXCEPTION_PROLOG_0 PACA_EXGEN; \
- EXCEPTION_PROLOG_1 EXC_HV, PACA_EXGEN, 1, start, 0, 0, 0 ; \
- EXCEPTION_PROLOG_2_REAL name##_common, EXC_HV, 1 ; \
- EXC_REAL_END(name, start, size)
-
-#define EXC_VIRT_HV(name, start, size, realvec) \
- EXC_VIRT_BEGIN(name, start, size); \
- EXCEPTION_PROLOG_0 PACA_EXGEN; \
- EXCEPTION_PROLOG_1 EXC_HV, PACA_EXGEN, 1, realvec, 0, 0, 0 ; \
- EXCEPTION_PROLOG_2_VIRT name##_common, EXC_HV ; \
- EXC_VIRT_END(name, start, size)
-
-#define __EXC_REAL_OOL(name, start, size) \
- EXC_REAL_BEGIN(name, start, size); \
- EXCEPTION_PROLOG_0 PACA_EXGEN ; \
- b tramp_real_##name ; \
- EXC_REAL_END(name, start, size)
-
-#define __TRAMP_REAL_OOL(name, vec) \
- TRAMP_REAL_BEGIN(tramp_real_##name); \
- EXCEPTION_PROLOG_1 EXC_STD, PACA_EXGEN, 1, vec, 0, 0, 0 ; \
- EXCEPTION_PROLOG_2_REAL name##_common, EXC_STD, 1
-
-#define EXC_REAL_OOL(name, start, size) \
- __EXC_REAL_OOL(name, start, size); \
- __TRAMP_REAL_OOL(name, start)
-
-#define __EXC_REAL_OOL_MASKABLE(name, start, size) \
- __EXC_REAL_OOL(name, start, size)
-
-#define __TRAMP_REAL_OOL_MASKABLE(name, vec, bitmask) \
- TRAMP_REAL_BEGIN(tramp_real_##name); \
- EXCEPTION_PROLOG_1 EXC_STD, PACA_EXGEN, 1, vec, 0, 0, bitmask ; \
- EXCEPTION_PROLOG_2_REAL name##_common, EXC_STD, 1
-
-#define EXC_REAL_OOL_MASKABLE(name, start, size, bitmask) \
- __EXC_REAL_OOL_MASKABLE(name, start, size); \
- __TRAMP_REAL_OOL_MASKABLE(name, start, bitmask)
-
-#define __EXC_REAL_OOL_HV(name, start, size) \
- __EXC_REAL_OOL(name, start, size)
-
-#define __TRAMP_REAL_OOL_HV(name, vec) \
- TRAMP_REAL_BEGIN(tramp_real_##name); \
- EXCEPTION_PROLOG_1 EXC_HV, PACA_EXGEN, 1, vec, 0, 0, 0 ; \
- EXCEPTION_PROLOG_2_REAL name##_common, EXC_HV, 1
-
-#define EXC_REAL_OOL_HV(name, start, size) \
- __EXC_REAL_OOL_HV(name, start, size); \
- __TRAMP_REAL_OOL_HV(name, start)
-
-#define __EXC_REAL_OOL_MASKABLE_HV(name, start, size) \
- __EXC_REAL_OOL(name, start, size)
-
-#define __TRAMP_REAL_OOL_MASKABLE_HV(name, vec, bitmask) \
- TRAMP_REAL_BEGIN(tramp_real_##name); \
- EXCEPTION_PROLOG_1 EXC_HV, PACA_EXGEN, 1, vec, 0, 0, bitmask ; \
- EXCEPTION_PROLOG_2_REAL name##_common, EXC_HV, 1
-
-#define EXC_REAL_OOL_MASKABLE_HV(name, start, size, bitmask) \
- __EXC_REAL_OOL_MASKABLE_HV(name, start, size); \
- __TRAMP_REAL_OOL_MASKABLE_HV(name, start, bitmask)
-
-#define __EXC_VIRT_OOL(name, start, size) \
- EXC_VIRT_BEGIN(name, start, size); \
- EXCEPTION_PROLOG_0 PACA_EXGEN ; \
- b tramp_virt_##name; \
- EXC_VIRT_END(name, start, size)
-
-#define __TRAMP_VIRT_OOL(name, realvec) \
- TRAMP_VIRT_BEGIN(tramp_virt_##name); \
- EXCEPTION_PROLOG_1 EXC_STD, PACA_EXGEN, 0, vec, 0, 0, 0 ; \
- EXCEPTION_PROLOG_2_VIRT name##_common, EXC_STD
-
-#define EXC_VIRT_OOL(name, start, size, realvec) \
- __EXC_VIRT_OOL(name, start, size); \
- __TRAMP_VIRT_OOL(name, realvec)
-
-#define __EXC_VIRT_OOL_MASKABLE(name, start, size) \
- __EXC_VIRT_OOL(name, start, size)
-
-#define __TRAMP_VIRT_OOL_MASKABLE(name, realvec, bitmask) \
- TRAMP_VIRT_BEGIN(tramp_virt_##name); \
- EXCEPTION_PROLOG_1 EXC_STD, PACA_EXGEN, 0, realvec, 0, 0, bitmask ; \
- EXCEPTION_PROLOG_2_VIRT name##_common, EXC_STD
-
-#define EXC_VIRT_OOL_MASKABLE(name, start, size, realvec, bitmask) \
- __EXC_VIRT_OOL_MASKABLE(name, start, size); \
- __TRAMP_VIRT_OOL_MASKABLE(name, realvec, bitmask)
-
-#define __EXC_VIRT_OOL_HV(name, start, size) \
- __EXC_VIRT_OOL(name, start, size)
-
-#define __TRAMP_VIRT_OOL_HV(name, realvec) \
- TRAMP_VIRT_BEGIN(tramp_virt_##name); \
- EXCEPTION_PROLOG_1 EXC_HV, PACA_EXGEN, 1, realvec, 0, 0, 0 ; \
- EXCEPTION_PROLOG_2_VIRT name##_common, EXC_HV
-
-#define EXC_VIRT_OOL_HV(name, start, size, realvec) \
- __EXC_VIRT_OOL_HV(name, start, size); \
- __TRAMP_VIRT_OOL_HV(name, realvec)
-
-#define __EXC_VIRT_OOL_MASKABLE_HV(name, start, size) \
- __EXC_VIRT_OOL(name, start, size)
-
-#define __TRAMP_VIRT_OOL_MASKABLE_HV(name, realvec, bitmask) \
- TRAMP_VIRT_BEGIN(tramp_virt_##name); \
- EXCEPTION_PROLOG_1 EXC_HV, PACA_EXGEN, 1, realvec, 0, 0, bitmask ; \
- EXCEPTION_PROLOG_2_VIRT name##_common, EXC_HV
-
-#define EXC_VIRT_OOL_MASKABLE_HV(name, start, size, realvec, bitmask) \
- __EXC_VIRT_OOL_MASKABLE_HV(name, start, size); \
- __TRAMP_VIRT_OOL_MASKABLE_HV(name, realvec, bitmask)
#define TRAMP_KVM(area, n) \
TRAMP_KVM_BEGIN(do_kvm_##n); \
@@ -943,9 +812,7 @@ BEGIN_FTR_SECTION
END_FTR_SECTION_IFSET(CPU_FTR_HVMODE | CPU_FTR_ARCH_206)
#endif
- EXCEPTION_PROLOG_0 PACA_EXNMI
- EXCEPTION_PROLOG_1 EXC_STD, PACA_EXNMI, 1, 0x100, 0, 0, 0
- EXCEPTION_PROLOG_2_REAL system_reset_common, EXC_STD, 0
+ INT_HANDLER system_reset, 0x100, 0, 0, 0, EXC_STD, PACA_EXNMI, 0, 0, 0, 0, 1
/*
* MSR_RI is not enabled, because PACA_EXNMI and nmi stack is
* being used, so a nested NMI exception would corrupt it.
@@ -975,9 +842,7 @@ TRAMP_REAL_BEGIN(system_reset_idle_wake)
*/
TRAMP_REAL_BEGIN(system_reset_fwnmi)
/* See comment at system_reset exception, don't turn on RI */
- EXCEPTION_PROLOG_0 PACA_EXNMI
- EXCEPTION_PROLOG_1 EXC_STD, PACA_EXNMI, 0, 0x100, 0, 0, 0
- EXCEPTION_PROLOG_2_REAL system_reset_common, EXC_STD, 0
+ INT_HANDLER system_reset, 0x100, 0, 0, 0, EXC_STD, PACA_EXNMI, 0, 0, 0, 0, 0
#endif /* CONFIG_PPC_PSERIES */
@@ -1040,10 +905,7 @@ EXC_COMMON_BEGIN(system_reset_common)
EXC_REAL_BEGIN(machine_check, 0x200, 0x100)
- EXCEPTION_PROLOG_0 PACA_EXMC
- EXCEPTION_PROLOG_1 EXC_STD, PACA_EXMC, 0, 0x200, 1, 1, 0
- mfctr r10 /* save ctr, even for !RELOCATABLE */
- BRANCH_TO_C000(r11, machine_check_early_common)
+ INT_HANDLER machine_check, 0x200, 0, 1, 0, EXC_STD, PACA_EXMC, 0, 1, 1, 0, 0
/*
* MSR_RI is not enabled, because PACA_EXMC is being used, so a
* nested machine check corrupts it. machine_check_common enables
@@ -1055,10 +917,7 @@ EXC_VIRT_NONE(0x4200, 0x100)
#ifdef CONFIG_PPC_PSERIES
TRAMP_REAL_BEGIN(machine_check_fwnmi)
/* See comment at machine_check exception, don't turn on RI */
- EXCEPTION_PROLOG_0 PACA_EXMC
- EXCEPTION_PROLOG_1 EXC_STD, PACA_EXMC, 0, 0x200, 1, 1, 0
- mfctr r10 /* save ctr */
- BRANCH_TO_C000(r11, machine_check_early_common)
+ INT_HANDLER machine_check, 0x200, 0, 1, 0, EXC_STD, PACA_EXMC, 0, 1, 1, 0, 0
#endif
TRAMP_KVM_SKIP(PACA_EXMC, 0x200)
@@ -1209,9 +1068,7 @@ BEGIN_FTR_SECTION
END_FTR_SECTION_IFSET(CPU_FTR_CFAR)
MACHINE_CHECK_HANDLER_WINDUP
/* See comment at machine_check exception, don't turn on RI */
- EXCEPTION_PROLOG_0 PACA_EXMC
- EXCEPTION_PROLOG_1 EXC_STD, PACA_EXMC, 1, 0x200, 1, 1, 0
- EXCEPTION_PROLOG_2_REAL machine_check_common, EXC_STD, 0
+ INT_HANDLER machine_check, 0x200, 0, 0, 0, EXC_STD, PACA_EXMC, 0, 1, 1, 0, 1
EXC_COMMON_BEGIN(machine_check_common)
/*
@@ -1297,18 +1154,10 @@ END_FTR_SECTION_IFSET(CPU_FTR_HVMODE)
EXC_REAL_BEGIN(data_access, 0x300, 0x80)
- EXCEPTION_PROLOG_0 PACA_EXGEN
- b tramp_real_data_access
+ INT_HANDLER data_access, 0x300, 1, 0, 0, EXC_STD, PACA_EXGEN, 1, 1, 1, 0, 1
EXC_REAL_END(data_access, 0x300, 0x80)
-
-TRAMP_REAL_BEGIN(tramp_real_data_access)
- EXCEPTION_PROLOG_1 EXC_STD, PACA_EXGEN, 1, 0x300, 1, 1, 0
- EXCEPTION_PROLOG_2_REAL data_access_common, EXC_STD, 1
-
EXC_VIRT_BEGIN(data_access, 0x4300, 0x80)
- EXCEPTION_PROLOG_0 PACA_EXGEN
- EXCEPTION_PROLOG_1 EXC_STD, PACA_EXGEN, 0, 0x300, 1, 1, 0
-EXCEPTION_PROLOG_2_VIRT data_access_common, EXC_STD
+ INT_HANDLER data_access, 0x300, 0, 0, 1, EXC_STD, PACA_EXGEN, 1, 1, 1, 0, 0
EXC_VIRT_END(data_access, 0x4300, 0x80)
TRAMP_KVM_SKIP(PACA_EXGEN, 0x300)
@@ -1336,18 +1185,10 @@ ALT_MMU_FTR_SECTION_END_IFCLR(MMU_FTR_TYPE_RADIX)
EXC_REAL_BEGIN(data_access_slb, 0x380, 0x80)
- EXCEPTION_PROLOG_0 PACA_EXSLB
- b tramp_real_data_access_slb
+ INT_HANDLER data_access_slb, 0x380, 1, 0, 0, 0, PACA_EXSLB, 1, 1, 0, 0, 1
EXC_REAL_END(data_access_slb, 0x380, 0x80)
-
-TRAMP_REAL_BEGIN(tramp_real_data_access_slb)
- EXCEPTION_PROLOG_1 EXC_STD, PACA_EXSLB, 1, 0x380, 1, 0, 0
- EXCEPTION_PROLOG_2_REAL data_access_slb_common, EXC_STD, 1
-
EXC_VIRT_BEGIN(data_access_slb, 0x4380, 0x80)
- EXCEPTION_PROLOG_0 PACA_EXSLB
- EXCEPTION_PROLOG_1 EXC_STD, PACA_EXSLB, 0, 0x380, 1, 0, 0
- EXCEPTION_PROLOG_2_VIRT data_access_slb_common, EXC_STD
+ INT_HANDLER data_access_slb, 0x380, 0, 0, 1, 0, PACA_EXSLB, 1, 1, 0, 0, 0
EXC_VIRT_END(data_access_slb, 0x4380, 0x80)
TRAMP_KVM_SKIP(PACA_EXSLB, 0x380)
@@ -1378,8 +1219,13 @@ ALT_MMU_FTR_SECTION_END_IFCLR(MMU_FTR_TYPE_RADIX)
b ret_from_except
-EXC_REAL(instruction_access, 0x400, 0x80)
-EXC_VIRT(instruction_access, 0x4400, 0x80, 0x400)
+EXC_REAL_BEGIN(instruction_access, 0x400, 0x80)
+ INT_HANDLER instruction_access, 0x400, 0, 0, 0, EXC_STD, PACA_EXGEN, 1, 0, 0, 0, 1
+EXC_REAL_END(instruction_access, 0x400, 0x80)
+EXC_VIRT_BEGIN(instruction_access, 0x4400, 0x80)
+ INT_HANDLER instruction_access, 0x400, 0, 0, 1, EXC_STD, PACA_EXGEN, 1, 0, 0, 0, 0
+EXC_VIRT_END(instruction_access, 0x4400, 0x80)
+
TRAMP_KVM(PACA_EXGEN, 0x400)
EXC_COMMON_BEGIN(instruction_access_common)
@@ -1398,8 +1244,12 @@ MMU_FTR_SECTION_ELSE
ALT_MMU_FTR_SECTION_END_IFCLR(MMU_FTR_TYPE_RADIX)
-__EXC_REAL(instruction_access_slb, 0x480, 0x80, PACA_EXSLB)
-__EXC_VIRT(instruction_access_slb, 0x4480, 0x80, 0x480, PACA_EXSLB)
+EXC_REAL_BEGIN(instruction_access_slb, 0x480, 0x80)
+ INT_HANDLER instruction_access_slb, 0x480, 0, 0, 0, EXC_STD, PACA_EXSLB, 1, 0, 0, 0, 1
+EXC_REAL_END(instruction_access_slb, 0x480, 0x80)
+EXC_VIRT_BEGIN(instruction_access_slb, 0x4480, 0x80)
+ INT_HANDLER instruction_access_slb, 0x480, 0, 0, 1, EXC_STD, PACA_EXSLB, 1, 0, 0, 0, 0
+EXC_VIRT_END(instruction_access_slb, 0x4480, 0x80)
TRAMP_KVM(PACA_EXSLB, 0x480)
EXC_COMMON_BEGIN(instruction_access_slb_common)
@@ -1426,17 +1276,11 @@ ALT_MMU_FTR_SECTION_END_IFCLR(MMU_FTR_TYPE_RADIX)
bl do_bad_slb_fault
b ret_from_except
-
EXC_REAL_BEGIN(hardware_interrupt, 0x500, 0x100)
- EXCEPTION_PROLOG_0 PACA_EXGEN
- EXCEPTION_PROLOG_1 EXC_HV_OR_STD, PACA_EXGEN, 1, 0x500, 0, 0, IRQS_DISABLED
- EXCEPTION_PROLOG_2_REAL hardware_interrupt_common, EXC_HV_OR_STD, 1
+ INT_HANDLER hardware_interrupt, 0x500, 0, 0, 0, EXC_HV_OR_STD, PACA_EXGEN, 1, 0, 0, IRQS_DISABLED, 1
EXC_REAL_END(hardware_interrupt, 0x500, 0x100)
-
EXC_VIRT_BEGIN(hardware_interrupt, 0x4500, 0x100)
- EXCEPTION_PROLOG_0 PACA_EXGEN
- EXCEPTION_PROLOG_1 EXC_HV_OR_STD, PACA_EXGEN, 1, 0x500, 0, 0, IRQS_DISABLED
- EXCEPTION_PROLOG_2_VIRT hardware_interrupt_common, EXC_HV_OR_STD
+ INT_HANDLER hardware_interrupt, 0x500, 0, 0, 1, EXC_HV_OR_STD, PACA_EXGEN, 1, 0, 0, IRQS_DISABLED, 1
EXC_VIRT_END(hardware_interrupt, 0x4500, 0x100)
TRAMP_KVM(PACA_EXGEN, 0x500)
@@ -1445,15 +1289,10 @@ EXC_COMMON_ASYNC(hardware_interrupt_common, 0x500, do_IRQ)
EXC_REAL_BEGIN(alignment, 0x600, 0x100)
- EXCEPTION_PROLOG_0 PACA_EXGEN
- EXCEPTION_PROLOG_1 EXC_STD, PACA_EXGEN, 1, 0x600, 1, 1, 0
- EXCEPTION_PROLOG_2_REAL alignment_common, EXC_STD, 1
+ INT_HANDLER alignment, 0x600, 0, 0, 0, EXC_STD, PACA_EXGEN, 1, 1, 1, 0, 1
EXC_REAL_END(alignment, 0x600, 0x100)
-
EXC_VIRT_BEGIN(alignment, 0x4600, 0x100)
- EXCEPTION_PROLOG_0 PACA_EXGEN
- EXCEPTION_PROLOG_1 EXC_STD, PACA_EXGEN, 0, 0x600, 1, 1, 0
- EXCEPTION_PROLOG_2_VIRT alignment_common, EXC_STD
+ INT_HANDLER alignment, 0x600, 0, 0, 1, EXC_STD, PACA_EXGEN, 1, 1, 1, 0, 0
EXC_VIRT_END(alignment, 0x4600, 0x100)
TRAMP_KVM(PACA_EXGEN, 0x600)
@@ -1470,8 +1309,12 @@ EXC_COMMON_BEGIN(alignment_common)
b ret_from_except
-EXC_REAL(program_check, 0x700, 0x100)
-EXC_VIRT(program_check, 0x4700, 0x100, 0x700)
+EXC_REAL_BEGIN(program_check, 0x700, 0x100)
+ INT_HANDLER program_check, 0x700, 0, 0, 0, EXC_STD, PACA_EXGEN, 1, 0, 0, 0, 1
+EXC_REAL_END(program_check, 0x700, 0x100)
+EXC_VIRT_BEGIN(program_check, 0x4700, 0x100)
+ INT_HANDLER program_check, 0x700, 0, 0, 1, EXC_STD, PACA_EXGEN, 1, 0, 0, 0, 0
+EXC_VIRT_END(program_check, 0x4700, 0x100)
TRAMP_KVM(PACA_EXGEN, 0x700)
EXC_COMMON_BEGIN(program_check_common)
/*
@@ -1508,8 +1351,12 @@ EXC_COMMON_BEGIN(program_check_common)
b ret_from_except
-EXC_REAL(fp_unavailable, 0x800, 0x100)
-EXC_VIRT(fp_unavailable, 0x4800, 0x100, 0x800)
+EXC_REAL_BEGIN(fp_unavailable, 0x800, 0x100)
+ INT_HANDLER fp_unavailable, 0x800, 0, 0, 0, EXC_STD, PACA_EXGEN, 1, 0, 0, 0, 1
+EXC_REAL_END(fp_unavailable, 0x800, 0x100)
+EXC_VIRT_BEGIN(fp_unavailable, 0x4800, 0x100)
+ INT_HANDLER fp_unavailable, 0x800, 0, 0, 1, EXC_STD, PACA_EXGEN, 1, 0, 0, 0, 0
+EXC_VIRT_END(fp_unavailable, 0x4800, 0x100)
TRAMP_KVM(PACA_EXGEN, 0x800)
EXC_COMMON_BEGIN(fp_unavailable_common)
EXCEPTION_COMMON(PACA_EXGEN, 0x800)
@@ -1541,20 +1388,32 @@ END_FTR_SECTION_IFSET(CPU_FTR_TM)
#endif
-EXC_REAL_OOL_MASKABLE(decrementer, 0x900, 0x80, IRQS_DISABLED)
-EXC_VIRT_MASKABLE(decrementer, 0x4900, 0x80, 0x900, IRQS_DISABLED)
+EXC_REAL_BEGIN(decrementer, 0x900, 0x80)
+ INT_HANDLER decrementer, 0x900, 1, 0, 0, EXC_STD, PACA_EXGEN, 1, 0, 0, IRQS_DISABLED, 1
+EXC_REAL_END(decrementer, 0x900, 0x80)
+EXC_VIRT_BEGIN(decrementer, 0x4900, 0x80)
+ INT_HANDLER decrementer, 0x900, 0, 0, 1, EXC_STD, PACA_EXGEN, 1, 0, 0, IRQS_DISABLED, 0
+EXC_VIRT_END(decrementer, 0x4900, 0x80)
TRAMP_KVM(PACA_EXGEN, 0x900)
EXC_COMMON_ASYNC(decrementer_common, 0x900, timer_interrupt)
-EXC_REAL_HV(hdecrementer, 0x980, 0x80)
-EXC_VIRT_HV(hdecrementer, 0x4980, 0x80, 0x980)
+EXC_REAL_BEGIN(hdecrementer, 0x980, 0x80)
+ INT_HANDLER hdecrementer, 0x980, 0, 0, 0, EXC_HV, PACA_EXGEN, 1, 0, 0, 0, 1
+EXC_REAL_END(hdecrementer, 0x980, 0x80)
+EXC_VIRT_BEGIN(hdecrementer, 0x4980, 0x80)
+ INT_HANDLER hdecrementer, 0x980, 0, 0, 1, EXC_HV, PACA_EXGEN, 1, 0, 0, 0, 1
+EXC_VIRT_END(hdecrementer, 0x4980, 0x80)
TRAMP_KVM_HV(PACA_EXGEN, 0x980)
EXC_COMMON(hdecrementer_common, 0x980, hdec_interrupt)
-EXC_REAL_MASKABLE(doorbell_super, 0xa00, 0x100, IRQS_DISABLED)
-EXC_VIRT_MASKABLE(doorbell_super, 0x4a00, 0x100, 0xa00, IRQS_DISABLED)
+EXC_REAL_BEGIN(doorbell_super, 0xa00, 0x100)
+ INT_HANDLER doorbell_super, 0xa00, 0, 0, 0, EXC_STD, PACA_EXGEN, 1, 0, 0, IRQS_DISABLED, 1
+EXC_REAL_END(doorbell_super, 0xa00, 0x100)
+EXC_VIRT_BEGIN(doorbell_super, 0x4a00, 0x100)
+ INT_HANDLER doorbell_super, 0xa00, 0, 0, 1, EXC_STD, PACA_EXGEN, 1, 0, 0, IRQS_DISABLED, 0
+EXC_VIRT_END(doorbell_super, 0x4a00, 0x100)
TRAMP_KVM(PACA_EXGEN, 0xa00)
#ifdef CONFIG_PPC_DOORBELL
EXC_COMMON_ASYNC(doorbell_super_common, 0xa00, doorbell_exception)
@@ -1670,7 +1529,6 @@ END_FTR_SECTION_IFSET(CPU_FTR_REAL_LE)
EXC_REAL_BEGIN(system_call, 0xc00, 0x100)
SYSTEM_CALL 0
EXC_REAL_END(system_call, 0xc00, 0x100)
-
EXC_VIRT_BEGIN(system_call, 0x4c00, 0x100)
SYSTEM_CALL 1
EXC_VIRT_END(system_call, 0x4c00, 0x100)
@@ -1700,13 +1558,22 @@ TRAMP_KVM_BEGIN(do_kvm_0xc00)
#endif
-EXC_REAL(single_step, 0xd00, 0x100)
-EXC_VIRT(single_step, 0x4d00, 0x100, 0xd00)
+EXC_REAL_BEGIN(single_step, 0xd00, 0x100)
+ INT_HANDLER single_step, 0xd00, 0, 0, 0, EXC_STD, PACA_EXGEN, 1, 0, 0, 0, 1
+EXC_REAL_END(single_step, 0xd00, 0x100)
+EXC_VIRT_BEGIN(single_step, 0x4d00, 0x100)
+ INT_HANDLER single_step, 0xd00, 0, 0, 1, EXC_STD, PACA_EXGEN, 1, 0, 0, 0, 0
+EXC_VIRT_END(single_step, 0x4d00, 0x100)
TRAMP_KVM(PACA_EXGEN, 0xd00)
EXC_COMMON(single_step_common, 0xd00, single_step_exception)
-EXC_REAL_OOL_HV(h_data_storage, 0xe00, 0x20)
-EXC_VIRT_OOL_HV(h_data_storage, 0x4e00, 0x20, 0xe00)
+
+EXC_REAL_BEGIN(h_data_storage, 0xe00, 0x20)
+ INT_HANDLER h_data_storage, 0xe00, 1, 0, 0, EXC_HV, PACA_EXGEN, 1, 0, 0, 0, 1
+EXC_REAL_END(h_data_storage, 0xe00, 0x20)
+EXC_VIRT_BEGIN(h_data_storage, 0x4e00, 0x20)
+ INT_HANDLER h_data_storage, 0xe00, 1, 0, 1, EXC_HV, PACA_EXGEN, 1, 0, 0, 0, 1
+EXC_VIRT_END(h_data_storage, 0x4e00, 0x20)
TRAMP_KVM_HV_SKIP(PACA_EXGEN, 0xe00)
EXC_COMMON_BEGIN(h_data_storage_common)
mfspr r10,SPRN_HDAR
@@ -1730,14 +1597,22 @@ ALT_MMU_FTR_SECTION_END_IFSET(MMU_FTR_TYPE_RADIX)
b ret_from_except
-EXC_REAL_OOL_HV(h_instr_storage, 0xe20, 0x20)
-EXC_VIRT_OOL_HV(h_instr_storage, 0x4e20, 0x20, 0xe20)
+EXC_REAL_BEGIN(h_instr_storage, 0xe20, 0x20)
+ INT_HANDLER h_instr_storage, 0xe20, 1, 0, 0, EXC_HV, PACA_EXGEN, 1, 0, 0, 0, 1
+EXC_REAL_END(h_instr_storage, 0xe20, 0x20)
+EXC_VIRT_BEGIN(h_instr_storage, 0x4e20, 0x20)
+ INT_HANDLER h_instr_storage, 0xe20, 1, 0, 1, EXC_HV, PACA_EXGEN, 1, 0, 0, 0, 1
+EXC_VIRT_END(h_instr_storage, 0x4e20, 0x20)
TRAMP_KVM_HV(PACA_EXGEN, 0xe20)
EXC_COMMON(h_instr_storage_common, 0xe20, unknown_exception)
-EXC_REAL_OOL_HV(emulation_assist, 0xe40, 0x20)
-EXC_VIRT_OOL_HV(emulation_assist, 0x4e40, 0x20, 0xe40)
+EXC_REAL_BEGIN(emulation_assist, 0xe40, 0x20)
+ INT_HANDLER emulation_assist, 0xe40, 1, 0, 0, EXC_HV, PACA_EXGEN, 1, 0, 0, 0, 1
+EXC_REAL_END(emulation_assist, 0xe40, 0x20)
+EXC_VIRT_BEGIN(emulation_assist, 0x4e40, 0x20)
+ INT_HANDLER emulation_assist, 0xe40, 1, 0, 1, EXC_HV, PACA_EXGEN, 1, 0, 0, 0, 1
+EXC_VIRT_END(emulation_assist, 0x4e40, 0x20)
TRAMP_KVM_HV(PACA_EXGEN, 0xe40)
EXC_COMMON(emulation_assist_common, 0xe40, emulation_assist_interrupt)
@@ -1748,15 +1623,10 @@ EXC_COMMON(emulation_assist_common, 0xe40, emulation_assist_interrupt)
* mode.
*/
EXC_REAL_BEGIN(hmi_exception, 0xe60, 0x20)
- EXCEPTION_PROLOG_0 PACA_EXGEN
- b hmi_exception_early
+ INT_HANDLER hmi_exception, 0xe60, 1, 1, 0, EXC_HV, PACA_EXGEN, 0, 0, 0, 0, 1
EXC_REAL_END(hmi_exception, 0xe60, 0x20)
EXC_VIRT_NONE(0x4e60, 0x20)
TRAMP_KVM_HV(PACA_EXGEN, 0xe60)
-TRAMP_REAL_BEGIN(hmi_exception_early)
- EXCEPTION_PROLOG_1 EXC_HV, PACA_EXGEN, 1, 0xe60, 0, 0, 0
- mfctr r10 /* save ctr, even for !RELOCATABLE */
- BRANCH_TO_C000(r11, hmi_exception_early_common)
EXC_COMMON_BEGIN(hmi_exception_early_common)
mtctr r10 /* Restore ctr */
@@ -1783,9 +1653,7 @@ EXC_COMMON_BEGIN(hmi_exception_early_common)
* firmware.
*/
EXCEPTION_RESTORE_REGS EXC_HV
- EXCEPTION_PROLOG_0 PACA_EXGEN
- EXCEPTION_PROLOG_1 EXC_HV, PACA_EXGEN, 1, 0xe60, 0, 0, IRQS_DISABLED
- EXCEPTION_PROLOG_2_REAL hmi_exception_common, EXC_HV, 1
+ INT_HANDLER hmi_exception, 0xe60, 0, 0, 0, EXC_HV, PACA_EXGEN, 1, 0, 0, IRQS_DISABLED, 1
EXC_COMMON_BEGIN(hmi_exception_common)
EXCEPTION_COMMON(PACA_EXGEN, 0xe60)
@@ -1797,8 +1665,13 @@ EXC_COMMON_BEGIN(hmi_exception_common)
bl handle_hmi_exception
b ret_from_except
-EXC_REAL_OOL_MASKABLE_HV(h_doorbell, 0xe80, 0x20, IRQS_DISABLED)
-EXC_VIRT_OOL_MASKABLE_HV(h_doorbell, 0x4e80, 0x20, 0xe80, IRQS_DISABLED)
+
+EXC_REAL_BEGIN(h_doorbell, 0xe80, 0x20)
+ INT_HANDLER h_doorbell, 0xe80, 1, 0, 0, EXC_HV, PACA_EXGEN, 1, 0, 0, IRQS_DISABLED, 1
+EXC_REAL_END(h_doorbell, 0xe80, 0x20)
+EXC_VIRT_BEGIN(h_doorbell, 0x4e80, 0x20)
+ INT_HANDLER h_doorbell, 0xe80, 1, 0, 1, EXC_HV, PACA_EXGEN, 1, 0, 0, IRQS_DISABLED, 1
+EXC_VIRT_END(h_doorbell, 0x4e80, 0x20)
TRAMP_KVM_HV(PACA_EXGEN, 0xe80)
#ifdef CONFIG_PPC_DOORBELL
EXC_COMMON_ASYNC(h_doorbell_common, 0xe80, doorbell_exception)
@@ -1807,8 +1680,12 @@ EXC_COMMON_ASYNC(h_doorbell_common, 0xe80, unknown_exception)
#endif
-EXC_REAL_OOL_MASKABLE_HV(h_virt_irq, 0xea0, 0x20, IRQS_DISABLED)
-EXC_VIRT_OOL_MASKABLE_HV(h_virt_irq, 0x4ea0, 0x20, 0xea0, IRQS_DISABLED)
+EXC_REAL_BEGIN(h_virt_irq, 0xea0, 0x20)
+ INT_HANDLER h_virt_irq, 0xea0, 1, 0, 0, EXC_HV, PACA_EXGEN, 1, 0, 0, IRQS_DISABLED, 1
+EXC_REAL_END(h_virt_irq, 0xea0, 0x20)
+EXC_VIRT_BEGIN(h_virt_irq, 0x4ea0, 0x20)
+ INT_HANDLER h_virt_irq, 0xea0, 1, 0, 1, EXC_HV, PACA_EXGEN, 1, 0, 0, IRQS_DISABLED, 1
+EXC_VIRT_END(h_virt_irq, 0x4ea0, 0x20)
TRAMP_KVM_HV(PACA_EXGEN, 0xea0)
EXC_COMMON_ASYNC(h_virt_irq_common, 0xea0, do_IRQ)
@@ -1819,14 +1696,22 @@ EXC_REAL_NONE(0xee0, 0x20)
EXC_VIRT_NONE(0x4ee0, 0x20)
-EXC_REAL_OOL_MASKABLE(performance_monitor, 0xf00, 0x20, IRQS_PMI_DISABLED)
-EXC_VIRT_OOL_MASKABLE(performance_monitor, 0x4f00, 0x20, 0xf00, IRQS_PMI_DISABLED)
+EXC_REAL_BEGIN(performance_monitor, 0xf00, 0x20)
+ INT_HANDLER performance_monitor, 0xf00, 1, 0, 0, EXC_STD, PACA_EXGEN, 1, 0, 0, IRQS_PMI_DISABLED, 1
+EXC_REAL_END(performance_monitor, 0xf00, 0x20)
+EXC_VIRT_BEGIN(performance_monitor, 0x4f00, 0x20)
+ INT_HANDLER performance_monitor, 0xf00, 1, 0, 1, EXC_STD, PACA_EXGEN, 1, 0, 0, IRQS_PMI_DISABLED, 0
+EXC_VIRT_END(performance_monitor, 0x4f00, 0x20)
TRAMP_KVM(PACA_EXGEN, 0xf00)
EXC_COMMON_ASYNC(performance_monitor_common, 0xf00, performance_monitor_exception)
-EXC_REAL_OOL(altivec_unavailable, 0xf20, 0x20)
-EXC_VIRT_OOL(altivec_unavailable, 0x4f20, 0x20, 0xf20)
+EXC_REAL_BEGIN(altivec_unavailable, 0xf20, 0x20)
+ INT_HANDLER altivec_unavailable, 0xf20, 1, 0, 0, EXC_STD, PACA_EXGEN, 1, 0, 0, 0, 1
+EXC_REAL_END(altivec_unavailable, 0xf20, 0x20)
+EXC_VIRT_BEGIN(altivec_unavailable, 0x4f20, 0x20)
+ INT_HANDLER altivec_unavailable, 0xf20, 1, 0, 1, EXC_STD, PACA_EXGEN, 1, 0, 0, 0, 0
+EXC_VIRT_END(altivec_unavailable, 0x4f20, 0x20)
TRAMP_KVM(PACA_EXGEN, 0xf20)
EXC_COMMON_BEGIN(altivec_unavailable_common)
EXCEPTION_COMMON(PACA_EXGEN, 0xf20)
@@ -1862,8 +1747,12 @@ END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
b ret_from_except
-EXC_REAL_OOL(vsx_unavailable, 0xf40, 0x20)
-EXC_VIRT_OOL(vsx_unavailable, 0x4f40, 0x20, 0xf40)
+EXC_REAL_BEGIN(vsx_unavailable, 0xf40, 0x20)
+ INT_HANDLER vsx_unavailable, 0xf40, 1, 0, 0, EXC_STD, PACA_EXGEN, 1, 0, 0, 0, 1
+EXC_REAL_END(vsx_unavailable, 0xf40, 0x20)
+EXC_VIRT_BEGIN(vsx_unavailable, 0x4f40, 0x20)
+ INT_HANDLER vsx_unavailable, 0xf40, 1, 0, 1, EXC_STD, PACA_EXGEN, 1, 0, 0, 0, 0
+EXC_VIRT_END(vsx_unavailable, 0x4f40, 0x20)
TRAMP_KVM(PACA_EXGEN, 0xf40)
EXC_COMMON_BEGIN(vsx_unavailable_common)
EXCEPTION_COMMON(PACA_EXGEN, 0xf40)
@@ -1898,14 +1787,22 @@ END_FTR_SECTION_IFSET(CPU_FTR_VSX)
b ret_from_except
-EXC_REAL_OOL(facility_unavailable, 0xf60, 0x20)
-EXC_VIRT_OOL(facility_unavailable, 0x4f60, 0x20, 0xf60)
+EXC_REAL_BEGIN(facility_unavailable, 0xf60, 0x20)
+ INT_HANDLER facility_unavailable, 0xf60, 1, 0, 0, EXC_STD, PACA_EXGEN, 1, 0, 0, 0, 1
+EXC_REAL_END(facility_unavailable, 0xf60, 0x20)
+EXC_VIRT_BEGIN(facility_unavailable, 0x4f60, 0x20)
+ INT_HANDLER facility_unavailable, 0xf60, 1, 0, 1, EXC_STD, PACA_EXGEN, 1, 0, 0, 0, 0
+EXC_VIRT_END(facility_unavailable, 0x4f60, 0x20)
TRAMP_KVM(PACA_EXGEN, 0xf60)
EXC_COMMON(facility_unavailable_common, 0xf60, facility_unavailable_exception)
-EXC_REAL_OOL_HV(h_facility_unavailable, 0xf80, 0x20)
-EXC_VIRT_OOL_HV(h_facility_unavailable, 0x4f80, 0x20, 0xf80)
+EXC_REAL_BEGIN(h_facility_unavailable, 0xf80, 0x20)
+ INT_HANDLER h_facility_unavailable, 0xf80, 1, 0, 0, EXC_HV, PACA_EXGEN, 1, 0, 0, 0, 1
+EXC_REAL_END(h_facility_unavailable, 0xf80, 0x20)
+EXC_VIRT_BEGIN(h_facility_unavailable, 0x4f80, 0x20)
+ INT_HANDLER h_facility_unavailable, 0xf80, 1, 0, 1, EXC_HV, PACA_EXGEN, 1, 0, 0, 0, 1
+EXC_VIRT_END(h_facility_unavailable, 0x4f80, 0x20)
TRAMP_KVM_HV(PACA_EXGEN, 0xf80)
EXC_COMMON(h_facility_unavailable_common, 0xf80, facility_unavailable_exception)
@@ -1923,7 +1820,9 @@ EXC_REAL_NONE(0x1100, 0x100)
EXC_VIRT_NONE(0x5100, 0x100)
#ifdef CONFIG_CBE_RAS
-EXC_REAL_HV(cbe_system_error, 0x1200, 0x100)
+EXC_REAL_BEGIN(cbe_system_error, 0x1200, 0x20)
+ INT_HANDLER cbe_system_error, 0x1200, 1, 0, 0, EXC_HV, PACA_EXGEN, 1, 0, 0, 0, 1
+EXC_REAL_END(cbe_system_error, 0x1200, 0x20)
EXC_VIRT_NONE(0x5200, 0x100)
TRAMP_KVM_HV_SKIP(PACA_EXGEN, 0x1200)
EXC_COMMON(cbe_system_error_common, 0x1200, cbe_system_error_exception)
@@ -1933,24 +1832,26 @@ EXC_VIRT_NONE(0x5200, 0x100)
#endif
-EXC_REAL(instruction_breakpoint, 0x1300, 0x100)
-EXC_VIRT(instruction_breakpoint, 0x5300, 0x100, 0x1300)
+EXC_REAL_BEGIN(instruction_breakpoint, 0x1300, 0x100)
+ INT_HANDLER instruction_breakpoint, 0x1300, 0, 0, 0, EXC_STD, PACA_EXGEN, 1, 0, 0, 0, 1
+EXC_REAL_END(instruction_breakpoint, 0x1300, 0x100)
+EXC_VIRT_BEGIN(instruction_breakpoint, 0x5300, 0x100)
+ INT_HANDLER instruction_breakpoint, 0x1300, 0, 0, 1, EXC_STD, PACA_EXGEN, 1, 0, 0, 0, 0
+EXC_VIRT_END(instruction_breakpoint, 0x5300, 0x100)
TRAMP_KVM_SKIP(PACA_EXGEN, 0x1300)
EXC_COMMON(instruction_breakpoint_common, 0x1300, instruction_breakpoint_exception)
+
EXC_REAL_NONE(0x1400, 0x100)
EXC_VIRT_NONE(0x5400, 0x100)
EXC_REAL_BEGIN(denorm_exception_hv, 0x1500, 0x100)
- EXCEPTION_PROLOG_0 PACA_EXGEN
- EXCEPTION_PROLOG_1 EXC_HV, PACA_EXGEN, 0, 0x1500, 0, 0, 0
-
+ INT_HANDLER denorm_exception_hv, 0x1500, 0, 2, 0, EXC_HV, PACA_EXGEN, 1, 0, 0, 0, 0
#ifdef CONFIG_PPC_DENORMALISATION
mfspr r10,SPRN_HSRR1
andis. r10,r10,(HSRR1_DENORM)@h /* denorm? */
bne+ denorm_assist
#endif
-
KVMTEST EXC_HV 0x1500
EXCEPTION_PROLOG_2_REAL denorm_common, EXC_HV, 1
EXC_REAL_END(denorm_exception_hv, 0x1500, 0x100)
@@ -2038,7 +1939,9 @@ EXC_COMMON(denorm_common, 0x1500, unknown_exception)
#ifdef CONFIG_CBE_RAS
-EXC_REAL_HV(cbe_maintenance, 0x1600, 0x100)
+EXC_REAL_BEGIN(cbe_maintenance, 0x1600, 0x20)
+ INT_HANDLER cbe_maintenance, 0x1600, 1, 0, 0, EXC_HV, PACA_EXGEN, 1, 0, 0, 0, 1
+EXC_REAL_END(cbe_maintenance, 0x1600, 0x20)
EXC_VIRT_NONE(0x5600, 0x100)
TRAMP_KVM_HV_SKIP(PACA_EXGEN, 0x1600)
EXC_COMMON(cbe_maintenance_common, 0x1600, cbe_maintenance_exception)
@@ -2048,8 +1951,12 @@ EXC_VIRT_NONE(0x5600, 0x100)
#endif
-EXC_REAL(altivec_assist, 0x1700, 0x100)
-EXC_VIRT(altivec_assist, 0x5700, 0x100, 0x1700)
+EXC_REAL_BEGIN(altivec_assist, 0x1700, 0x100)
+ INT_HANDLER altivec_assist, 0x1700, 0, 0, 0, EXC_STD, PACA_EXGEN, 1, 0, 0, 0, 1
+EXC_REAL_END(altivec_assist, 0x1700, 0x100)
+EXC_VIRT_BEGIN(altivec_assist, 0x5700, 0x100)
+ INT_HANDLER altivec_assist, 0x1700, 0, 0, 1, EXC_STD, PACA_EXGEN, 1, 0, 0, 0, 0
+EXC_VIRT_END(altivec_assist, 0x5700, 0x100)
TRAMP_KVM(PACA_EXGEN, 0x1700)
#ifdef CONFIG_ALTIVEC
EXC_COMMON(altivec_assist_common, 0x1700, altivec_assist_exception)
@@ -2059,7 +1966,9 @@ EXC_COMMON(altivec_assist_common, 0x1700, unknown_exception)
#ifdef CONFIG_CBE_RAS
-EXC_REAL_HV(cbe_thermal, 0x1800, 0x100)
+EXC_REAL_BEGIN(cbe_thermal, 0x1800, 0x20)
+ INT_HANDLER cbe_thermal, 0x1800, 1, 0, 0, EXC_HV, PACA_EXGEN, 1, 0, 0, 0, 1
+EXC_REAL_END(cbe_thermal, 0x1800, 0x20)
EXC_VIRT_NONE(0x5800, 0x100)
TRAMP_KVM_HV_SKIP(PACA_EXGEN, 0x1800)
EXC_COMMON(cbe_thermal_common, 0x1800, cbe_thermal_exception)
@@ -2068,6 +1977,7 @@ EXC_REAL_NONE(0x1800, 0x100)
EXC_VIRT_NONE(0x5800, 0x100)
#endif
+
#ifdef CONFIG_PPC_WATCHDOG
#define MASKED_DEC_HANDLER_LABEL 3f
--
2.22.0
^ permalink raw reply related
* [PATCH 05/18] powerpc/64s/exception: remove 0xb00 handler
From: Nicholas Piggin @ 2019-07-29 14:12 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Nicholas Piggin
In-Reply-To: <20190729141247.26762-1-npiggin@gmail.com>
This vector is not used by any supported processor, and has been
implemented as an unknown exception going back to 2.6. There is
nothing special about 0xb00, so remove it like other unused
vectors.
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
---
arch/powerpc/kernel/exceptions-64s.S | 6 ++----
1 file changed, 2 insertions(+), 4 deletions(-)
diff --git a/arch/powerpc/kernel/exceptions-64s.S b/arch/powerpc/kernel/exceptions-64s.S
index 723c37f3da17..9c407392774c 100644
--- a/arch/powerpc/kernel/exceptions-64s.S
+++ b/arch/powerpc/kernel/exceptions-64s.S
@@ -1563,10 +1563,8 @@ EXC_COMMON_ASYNC(doorbell_super_common, 0xa00, unknown_exception)
#endif
-EXC_REAL(trap_0b, 0xb00, 0x100)
-EXC_VIRT(trap_0b, 0x4b00, 0x100, 0xb00)
-TRAMP_KVM(PACA_EXGEN, 0xb00)
-EXC_COMMON(trap_0b_common, 0xb00, unknown_exception)
+EXC_REAL_NONE(0xb00, 0x100)
+EXC_VIRT_NONE(0x4b00, 0x100)
/*
* system call / hypercall (0xc00, 0x4c00)
--
2.22.0
^ permalink raw reply related
* [PATCH 04/18] powerpc/64s/exception: Fix performance monitor virt handler
From: Nicholas Piggin @ 2019-07-29 14:12 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Nicholas Piggin
In-Reply-To: <20190729141247.26762-1-npiggin@gmail.com>
The perf virt handler uses EXCEPTION_PROLOG_2_REAL rather than _VIRT.
In practice this is okay because the _REAL variant is usable by virt
mode interrupts, but should be fixed (and is a performance win).
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
---
arch/powerpc/kernel/exceptions-64s.S | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/powerpc/kernel/exceptions-64s.S b/arch/powerpc/kernel/exceptions-64s.S
index 60969992e9e0..723c37f3da17 100644
--- a/arch/powerpc/kernel/exceptions-64s.S
+++ b/arch/powerpc/kernel/exceptions-64s.S
@@ -750,7 +750,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_CAN_NAP)
#define __TRAMP_VIRT_OOL_MASKABLE(name, realvec, bitmask) \
TRAMP_VIRT_BEGIN(tramp_virt_##name); \
EXCEPTION_PROLOG_1 EXC_STD, PACA_EXGEN, 0, realvec, 0, 0, bitmask ; \
- EXCEPTION_PROLOG_2_REAL name##_common, EXC_STD, 1
+ EXCEPTION_PROLOG_2_VIRT name##_common, EXC_STD
#define EXC_VIRT_OOL_MASKABLE(name, start, size, realvec, bitmask) \
__EXC_VIRT_OOL_MASKABLE(name, start, size); \
--
2.22.0
^ permalink raw reply related
* [PATCH 03/18] powerpc/64s/exception: Add EXC_HV_OR_STD, for HSRR if HV=1 else SRR
From: Nicholas Piggin @ 2019-07-29 14:12 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Nicholas Piggin
In-Reply-To: <20190729141247.26762-1-npiggin@gmail.com>
Use EXC_HV_OR_STD to de-duplicate the 0x500 external interrupt.
This helps with consolidation in future.
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
---
arch/powerpc/kernel/exceptions-64s.S | 102 +++++++++++++++++++++------
1 file changed, 79 insertions(+), 23 deletions(-)
diff --git a/arch/powerpc/kernel/exceptions-64s.S b/arch/powerpc/kernel/exceptions-64s.S
index 1fb46fb24696..60969992e9e0 100644
--- a/arch/powerpc/kernel/exceptions-64s.S
+++ b/arch/powerpc/kernel/exceptions-64s.S
@@ -109,6 +109,7 @@ name:
addis reg,reg,(ABS_ADDR(label))@h
/* Exception register prefixes */
+#define EXC_HV_OR_STD 2 /* depends on HVMODE */
#define EXC_HV 1
#define EXC_STD 0
@@ -205,7 +206,13 @@ END_FTR_SECTION_NESTED(ftr,ftr,943)
.abort "Bad maskable vector"
.endif
- .if \hsrr
+ .if \hsrr == EXC_HV_OR_STD
+ BEGIN_FTR_SECTION
+ bne masked_Hinterrupt
+ FTR_SECTION_ELSE
+ bne masked_interrupt
+ ALT_FTR_SECTION_END_IFSET(CPU_FTR_HVMODE | CPU_FTR_ARCH_206)
+ .elseif \hsrr
bne masked_Hinterrupt
.else
bne masked_interrupt
@@ -237,7 +244,17 @@ END_FTR_SECTION_NESTED(ftr,ftr,943)
.if ! \set_ri
xori r10,r10,MSR_RI /* Clear MSR_RI */
.endif
- .if \hsrr
+ .if \hsrr == EXC_HV_OR_STD
+ BEGIN_FTR_SECTION
+ mfspr r11,SPRN_HSRR0 /* save HSRR0 */
+ mfspr r12,SPRN_HSRR1 /* and HSRR1 */
+ mtspr SPRN_HSRR1,r10
+ FTR_SECTION_ELSE
+ mfspr r11,SPRN_SRR0 /* save SRR0 */
+ mfspr r12,SPRN_SRR1 /* and SRR1 */
+ mtspr SPRN_SRR1,r10
+ ALT_FTR_SECTION_END_IFSET(CPU_FTR_HVMODE | CPU_FTR_ARCH_206)
+ .elseif \hsrr
mfspr r11,SPRN_HSRR0 /* save HSRR0 */
mfspr r12,SPRN_HSRR1 /* and HSRR1 */
mtspr SPRN_HSRR1,r10
@@ -247,7 +264,15 @@ END_FTR_SECTION_NESTED(ftr,ftr,943)
mtspr SPRN_SRR1,r10
.endif
LOAD_HANDLER(r10, \label\())
- .if \hsrr
+ .if \hsrr == EXC_HV_OR_STD
+ BEGIN_FTR_SECTION
+ mtspr SPRN_HSRR0,r10
+ HRFI_TO_KERNEL
+ FTR_SECTION_ELSE
+ mtspr SPRN_SRR0,r10
+ RFI_TO_KERNEL
+ ALT_FTR_SECTION_END_IFSET(CPU_FTR_HVMODE | CPU_FTR_ARCH_206)
+ .elseif \hsrr
mtspr SPRN_HSRR0,r10
HRFI_TO_KERNEL
.else
@@ -259,14 +284,26 @@ END_FTR_SECTION_NESTED(ftr,ftr,943)
.macro EXCEPTION_PROLOG_2_VIRT label, hsrr
#ifdef CONFIG_RELOCATABLE
- .if \hsrr
+ .if \hsrr == EXC_HV_OR_STD
+ BEGIN_FTR_SECTION
+ mfspr r11,SPRN_HSRR0 /* save HSRR0 */
+ FTR_SECTION_ELSE
+ mfspr r11,SPRN_SRR0 /* save SRR0 */
+ ALT_FTR_SECTION_END_IFSET(CPU_FTR_HVMODE | CPU_FTR_ARCH_206)
+ .elseif \hsrr
mfspr r11,SPRN_HSRR0 /* save HSRR0 */
.else
mfspr r11,SPRN_SRR0 /* save SRR0 */
.endif
LOAD_HANDLER(r12, \label\())
mtctr r12
- .if \hsrr
+ .if \hsrr == EXC_HV_OR_STD
+ BEGIN_FTR_SECTION
+ mfspr r12,SPRN_HSRR1 /* and HSRR1 */
+ FTR_SECTION_ELSE
+ mfspr r12,SPRN_SRR1 /* and HSRR1 */
+ ALT_FTR_SECTION_END_IFSET(CPU_FTR_HVMODE | CPU_FTR_ARCH_206)
+ .elseif \hsrr
mfspr r12,SPRN_HSRR1 /* and HSRR1 */
.else
mfspr r12,SPRN_SRR1 /* and HSRR1 */
@@ -275,7 +312,15 @@ END_FTR_SECTION_NESTED(ftr,ftr,943)
mtmsrd r10,1 /* Set RI (EE=0) */
bctr
#else
- .if \hsrr
+ .if \hsrr == EXC_HV_OR_STD
+ BEGIN_FTR_SECTION
+ mfspr r11,SPRN_HSRR0 /* save HSRR0 */
+ mfspr r12,SPRN_HSRR1 /* and HSRR1 */
+ FTR_SECTION_ELSE
+ mfspr r11,SPRN_SRR0 /* save SRR0 */
+ mfspr r12,SPRN_SRR1 /* and SRR1 */
+ ALT_FTR_SECTION_END_IFSET(CPU_FTR_HVMODE | CPU_FTR_ARCH_206)
+ .elseif \hsrr
mfspr r11,SPRN_HSRR0 /* save HSRR0 */
mfspr r12,SPRN_HSRR1 /* and HSRR1 */
.else
@@ -316,7 +361,13 @@ END_FTR_SECTION_NESTED(ftr,ftr,943)
.macro KVMTEST hsrr, n
lbz r10,HSTATE_IN_GUEST(r13)
cmpwi r10,0
- .if \hsrr
+ .if \hsrr == EXC_HV_OR_STD
+ BEGIN_FTR_SECTION
+ bne do_kvm_H\n
+ FTR_SECTION_ELSE
+ bne do_kvm_\n
+ ALT_FTR_SECTION_END_IFSET(CPU_FTR_HVMODE | CPU_FTR_ARCH_206)
+ .elseif \hsrr
bne do_kvm_H\n
.else
bne do_kvm_\n
@@ -342,7 +393,13 @@ END_FTR_SECTION_NESTED(CPU_FTR_HAS_PPR,CPU_FTR_HAS_PPR,948)
std r12,HSTATE_SCRATCH0(r13)
sldi r12,r9,32
/* HSRR variants have the 0x2 bit added to their trap number */
- .if \hsrr
+ .if \hsrr == EXC_HV_OR_STD
+ BEGIN_FTR_SECTION
+ ori r12,r12,(\n + 0x2)
+ FTR_SECTION_ELSE
+ ori r12,r12,(\n)
+ ALT_FTR_SECTION_END_IFSET(CPU_FTR_HVMODE | CPU_FTR_ARCH_206)
+ .elseif \hsrr
ori r12,r12,(\n + 0x2)
.else
ori r12,r12,(\n)
@@ -370,7 +427,13 @@ END_FTR_SECTION_NESTED(CPU_FTR_HAS_PPR,CPU_FTR_HAS_PPR,948)
89: mtocrf 0x80,r9
ld r9,\area+EX_R9(r13)
ld r10,\area+EX_R10(r13)
- .if \hsrr
+ .if \hsrr == EXC_HV_OR_STD
+ BEGIN_FTR_SECTION
+ b kvmppc_skip_Hinterrupt
+ FTR_SECTION_ELSE
+ b kvmppc_skip_interrupt
+ ALT_FTR_SECTION_END_IFSET(CPU_FTR_HVMODE | CPU_FTR_ARCH_206)
+ .elseif \hsrr
b kvmppc_skip_Hinterrupt
.else
b kvmppc_skip_interrupt
@@ -469,6 +532,9 @@ END_FTR_SECTION_NESTED(CPU_FTR_CFAR, CPU_FTR_CFAR, 66); \
.macro EXCEPTION_RESTORE_REGS hsrr
/* Move original SRR0 and SRR1 into the respective regs */
ld r9,_MSR(r1)
+ .if \hsrr == EXC_HV_OR_STD
+ .error "EXC_HV_OR_STD Not implemented for EXCEPTION_RESTORE_REGS"
+ .endif
.if \hsrr
mtspr SPRN_HSRR1,r9
.else
@@ -1363,24 +1429,14 @@ ALT_MMU_FTR_SECTION_END_IFCLR(MMU_FTR_TYPE_RADIX)
EXC_REAL_BEGIN(hardware_interrupt, 0x500, 0x100)
EXCEPTION_PROLOG_0 PACA_EXGEN
-BEGIN_FTR_SECTION
- EXCEPTION_PROLOG_1 EXC_HV, PACA_EXGEN, 1, 0x500, 0, 0, IRQS_DISABLED
- EXCEPTION_PROLOG_2_REAL hardware_interrupt_common, EXC_HV, 1
-FTR_SECTION_ELSE
- EXCEPTION_PROLOG_1 EXC_STD, PACA_EXGEN, 1, 0x500, 0, 0, IRQS_DISABLED
- EXCEPTION_PROLOG_2_REAL hardware_interrupt_common, EXC_STD, 1
-ALT_FTR_SECTION_END_IFSET(CPU_FTR_HVMODE | CPU_FTR_ARCH_206)
+ EXCEPTION_PROLOG_1 EXC_HV_OR_STD, PACA_EXGEN, 1, 0x500, 0, 0, IRQS_DISABLED
+ EXCEPTION_PROLOG_2_REAL hardware_interrupt_common, EXC_HV_OR_STD, 1
EXC_REAL_END(hardware_interrupt, 0x500, 0x100)
EXC_VIRT_BEGIN(hardware_interrupt, 0x4500, 0x100)
EXCEPTION_PROLOG_0 PACA_EXGEN
-BEGIN_FTR_SECTION
- EXCEPTION_PROLOG_1 EXC_HV, PACA_EXGEN, 1, 0x500, 0, 0, IRQS_DISABLED
- EXCEPTION_PROLOG_2_VIRT hardware_interrupt_common, EXC_HV
-FTR_SECTION_ELSE
- EXCEPTION_PROLOG_1 EXC_STD, PACA_EXGEN, 1, 0x500, 0, 0, IRQS_DISABLED
- EXCEPTION_PROLOG_2_VIRT hardware_interrupt_common, EXC_STD
-ALT_FTR_SECTION_END_IFSET(CPU_FTR_HVMODE)
+ EXCEPTION_PROLOG_1 EXC_HV_OR_STD, PACA_EXGEN, 1, 0x500, 0, 0, IRQS_DISABLED
+ EXCEPTION_PROLOG_2_VIRT hardware_interrupt_common, EXC_HV_OR_STD
EXC_VIRT_END(hardware_interrupt, 0x4500, 0x100)
TRAMP_KVM(PACA_EXGEN, 0x500)
--
2.22.0
^ permalink raw reply related
* [PATCH 02/18] powerpc/64s/exception: move head-64.h exception code to exception-64s.S
From: Nicholas Piggin @ 2019-07-29 14:12 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Nicholas Piggin
In-Reply-To: <20190729141247.26762-1-npiggin@gmail.com>
The head-64.h code should deal only with the head code sections
and offset calculations.
No generated code change except BUG line number constants.
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
---
arch/powerpc/include/asm/head-64.h | 41 ----------------------------
arch/powerpc/kernel/exceptions-64s.S | 41 ++++++++++++++++++++++++++++
2 files changed, 41 insertions(+), 41 deletions(-)
diff --git a/arch/powerpc/include/asm/head-64.h b/arch/powerpc/include/asm/head-64.h
index a466765709a9..2dabcf668292 100644
--- a/arch/powerpc/include/asm/head-64.h
+++ b/arch/powerpc/include/asm/head-64.h
@@ -169,47 +169,6 @@ end_##sname:
#define ABS_ADDR(label) (label - fs_label + fs_start)
-#define EXC_REAL_BEGIN(name, start, size) \
- FIXED_SECTION_ENTRY_BEGIN_LOCATION(real_vectors, exc_real_##start##_##name, start, size)
-
-#define EXC_REAL_END(name, start, size) \
- FIXED_SECTION_ENTRY_END_LOCATION(real_vectors, exc_real_##start##_##name, start, size)
-
-#define EXC_VIRT_BEGIN(name, start, size) \
- FIXED_SECTION_ENTRY_BEGIN_LOCATION(virt_vectors, exc_virt_##start##_##name, start, size)
-
-#define EXC_VIRT_END(name, start, size) \
- FIXED_SECTION_ENTRY_END_LOCATION(virt_vectors, exc_virt_##start##_##name, start, size)
-
-#define EXC_COMMON_BEGIN(name) \
- USE_TEXT_SECTION(); \
- .balign IFETCH_ALIGN_BYTES; \
- .global name; \
- _ASM_NOKPROBE_SYMBOL(name); \
- DEFINE_FIXED_SYMBOL(name); \
-name:
-
-#define TRAMP_REAL_BEGIN(name) \
- FIXED_SECTION_ENTRY_BEGIN(real_trampolines, name)
-
-#define TRAMP_VIRT_BEGIN(name) \
- FIXED_SECTION_ENTRY_BEGIN(virt_trampolines, name)
-
-#ifdef CONFIG_KVM_BOOK3S_64_HANDLER
-#define TRAMP_KVM_BEGIN(name) \
- TRAMP_VIRT_BEGIN(name)
-#else
-#define TRAMP_KVM_BEGIN(name)
-#endif
-
-#define EXC_REAL_NONE(start, size) \
- FIXED_SECTION_ENTRY_BEGIN_LOCATION(real_vectors, exc_real_##start##_##unused, start, size); \
- FIXED_SECTION_ENTRY_END_LOCATION(real_vectors, exc_real_##start##_##unused, start, size)
-
-#define EXC_VIRT_NONE(start, size) \
- FIXED_SECTION_ENTRY_BEGIN_LOCATION(virt_vectors, exc_virt_##start##_##unused, start, size); \
- FIXED_SECTION_ENTRY_END_LOCATION(virt_vectors, exc_virt_##start##_##unused, start, size)
-
#endif /* __ASSEMBLY__ */
#endif /* _ASM_POWERPC_HEAD_64_H */
diff --git a/arch/powerpc/kernel/exceptions-64s.S b/arch/powerpc/kernel/exceptions-64s.S
index f79f811ee131..1fb46fb24696 100644
--- a/arch/powerpc/kernel/exceptions-64s.S
+++ b/arch/powerpc/kernel/exceptions-64s.S
@@ -43,6 +43,47 @@
.endif
#endif
+#define EXC_REAL_BEGIN(name, start, size) \
+ FIXED_SECTION_ENTRY_BEGIN_LOCATION(real_vectors, exc_real_##start##_##name, start, size)
+
+#define EXC_REAL_END(name, start, size) \
+ FIXED_SECTION_ENTRY_END_LOCATION(real_vectors, exc_real_##start##_##name, start, size)
+
+#define EXC_VIRT_BEGIN(name, start, size) \
+ FIXED_SECTION_ENTRY_BEGIN_LOCATION(virt_vectors, exc_virt_##start##_##name, start, size)
+
+#define EXC_VIRT_END(name, start, size) \
+ FIXED_SECTION_ENTRY_END_LOCATION(virt_vectors, exc_virt_##start##_##name, start, size)
+
+#define EXC_COMMON_BEGIN(name) \
+ USE_TEXT_SECTION(); \
+ .balign IFETCH_ALIGN_BYTES; \
+ .global name; \
+ _ASM_NOKPROBE_SYMBOL(name); \
+ DEFINE_FIXED_SYMBOL(name); \
+name:
+
+#define TRAMP_REAL_BEGIN(name) \
+ FIXED_SECTION_ENTRY_BEGIN(real_trampolines, name)
+
+#define TRAMP_VIRT_BEGIN(name) \
+ FIXED_SECTION_ENTRY_BEGIN(virt_trampolines, name)
+
+#ifdef CONFIG_KVM_BOOK3S_64_HANDLER
+#define TRAMP_KVM_BEGIN(name) \
+ TRAMP_VIRT_BEGIN(name)
+#else
+#define TRAMP_KVM_BEGIN(name)
+#endif
+
+#define EXC_REAL_NONE(start, size) \
+ FIXED_SECTION_ENTRY_BEGIN_LOCATION(real_vectors, exc_real_##start##_##unused, start, size); \
+ FIXED_SECTION_ENTRY_END_LOCATION(real_vectors, exc_real_##start##_##unused, start, size)
+
+#define EXC_VIRT_NONE(start, size) \
+ FIXED_SECTION_ENTRY_BEGIN_LOCATION(virt_vectors, exc_virt_##start##_##unused, start, size); \
+ FIXED_SECTION_ENTRY_END_LOCATION(virt_vectors, exc_virt_##start##_##unused, start, size)
+
/*
* We're short on space and time in the exception prolog, so we can't
* use the normal LOAD_REG_IMMEDIATE macro to load the address of label.
--
2.22.0
^ permalink raw reply related
* [PATCH 01/18] powerpc/64s/exception: Fix DAR load for handle_page_fault error case
From: Nicholas Piggin @ 2019-07-29 14:12 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Nicholas Piggin
In-Reply-To: <20190729141247.26762-1-npiggin@gmail.com>
This buglet goes back to before the 64/32 arch merge, but it does not
seem to have had practical consequences because bad_page_fault does
not use the 2nd argument, but rather regs->dar/nip.
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
---
arch/powerpc/kernel/exceptions-64s.S | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/powerpc/kernel/exceptions-64s.S b/arch/powerpc/kernel/exceptions-64s.S
index 6b409d62d36c..f79f811ee131 100644
--- a/arch/powerpc/kernel/exceptions-64s.S
+++ b/arch/powerpc/kernel/exceptions-64s.S
@@ -2336,7 +2336,7 @@ handle_page_fault:
bl save_nvgprs
mr r5,r3
addi r3,r1,STACK_FRAME_OVERHEAD
- lwz r4,_DAR(r1)
+ ld r4,_DAR(r1)
bl bad_page_fault
b ret_from_except
--
2.22.0
^ permalink raw reply related
* [PATCH 00/18] powerpc/64s/exception: cleanup and gas macroify, round 2
From: Nicholas Piggin @ 2019-07-29 14:12 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Nicholas Piggin
This series goes on top of the unmerged machine check handler
changes
https://patchwork.ozlabs.org/project/linuxppc-dev/list/?series=118814
This carries on with the goal of unwinding macros and consolidating
code. This gets most of the way there, but we have traded that
improvement for another problem, which is the argument list for code
generation macros is unwieldy.
INT_HANDLER system_reset, 0x100, 0, 0, 0, EXC_STD, PACA_EXNMI, 0, 0, 0, 0, 1
There are two possible ways I see to solve this. One is to come up
with new sets of constants for each argument.
INT_HANDLER system_reset, 0x100, INLINE, FULL, REAL, EXC_STD, PACA_EXNMI, CLEAR_RI, NO_DAR, NO_DSISR, NO_MASK, KVM
I don't really like that, my preferred way is we can set symbols to
configure the behaviour of the code generation macro.
INT_DEFINE_BEGIN(system_reset)
IVEC=0x100
IHSRR=0
IAREA=PACA_EXNMI
ISET_RI=0
IKVM_REAL=1
INT_DEFINE_END(data_access)
INT_HANDLER system_reset
Any other suggestions?
Thanks,
Nick
Nicholas Piggin (18):
powerpc/64s/exception: Fix DAR load for handle_page_fault error case
powerpc/64s/exception: move head-64.h exception code to
exception-64s.S
powerpc/64s/exception: Add EXC_HV_OR_STD, for HSRR if HV=1 else SRR
powerpc/64s/exception: Fix performance monitor virt handler
powerpc/64s/exception: remove 0xb00 handler
powerpc/64s/exception: Replace PROLOG macros and EXC helpers with a
gas macro
powerpc/64s/exception: remove EXCEPTION_PROLOG_0/1, rename _2
powerpc/64s/exception: Add the virt variant of the denorm interrupt
handler
powerpc/64s/exception: INT_HANDLER support HDAR/HDSISR and use it in
HDSI
powerpc/64s/exception: Add INT_KVM_HANDLER gas macro
powerpc/64s/exception: KVM_HANDLER reorder arguments to match other
macros
powerpc/64s/exception: Merge EXCEPTION_PROLOG_COMMON_2/3
powerpc/64s/exception: Add INT_COMMON gas macro to generate common
exception code
powerpc/64s/exception: Expand EXCEPTION_COMMON macro into caller
powerpc/64s/exception: Expand EXCEPTION_PROLOG_COMMON_1 and 2 into
caller
powerpc/64s/exception: INT_COMMON add DIR, DSISR, reconcile options
powerpc/64s/exception: move interrupt entry code above the common
handler
powerpc/64s/exception: program check handler do not branch into a
macro
arch/powerpc/include/asm/head-64.h | 41 -
arch/powerpc/kernel/exceptions-64s.S | 1264 +++++++++++++-------------
2 files changed, 623 insertions(+), 682 deletions(-)
--
2.22.0
^ permalink raw reply
* Re: [RFC PATCH 10/10] powerpc/fsl_booke/kaslr: dump out kernel offset information on panic
From: Jason Yan @ 2019-07-29 14:08 UTC (permalink / raw)
To: Christophe Leroy, mpe, linuxppc-dev, diana.craciun, benh, paulus,
npiggin, keescook, kernel-hardening
Cc: wangkefeng.wang, linux-kernel, jingxiangfeng, thunder.leizhen,
fanchengyang, yebin10
In-Reply-To: <d10db1e3-6bc4-eaa4-d68e-b7343e35b55f@c-s.fr>
On 2019/7/29 19:43, Christophe Leroy wrote:
>
>
> Le 17/07/2019 à 10:06, Jason Yan a écrit :
>> When kaslr is enabled, the kernel offset is different for every boot.
>> This brings some difficult to debug the kernel. Dump out the kernel
>> offset when panic so that we can easily debug the kernel.
>>
>> Signed-off-by: Jason Yan <yanaijie@huawei.com>
>> Cc: Diana Craciun <diana.craciun@nxp.com>
>> Cc: Michael Ellerman <mpe@ellerman.id.au>
>> Cc: Christophe Leroy <christophe.leroy@c-s.fr>
>> Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
>> Cc: Paul Mackerras <paulus@samba.org>
>> Cc: Nicholas Piggin <npiggin@gmail.com>
>> Cc: Kees Cook <keescook@chromium.org>
>> ---
>> arch/powerpc/include/asm/page.h | 5 +++++
>> arch/powerpc/kernel/machine_kexec.c | 1 +
>> arch/powerpc/kernel/setup-common.c | 23 +++++++++++++++++++++++
>> 3 files changed, 29 insertions(+)
>>
>> diff --git a/arch/powerpc/include/asm/page.h
>> b/arch/powerpc/include/asm/page.h
>> index 60a68d3a54b1..cd3ac530e58d 100644
>> --- a/arch/powerpc/include/asm/page.h
>> +++ b/arch/powerpc/include/asm/page.h
>> @@ -317,6 +317,11 @@ struct vm_area_struct;
>> extern unsigned long kimage_vaddr;
>> +static inline unsigned long kaslr_offset(void)
>> +{
>> + return kimage_vaddr - KERNELBASE;
>> +}
>> +
>> #include <asm-generic/memory_model.h>
>> #endif /* __ASSEMBLY__ */
>> #include <asm/slice.h>
>> diff --git a/arch/powerpc/kernel/machine_kexec.c
>> b/arch/powerpc/kernel/machine_kexec.c
>> index c4ed328a7b96..078fe3d76feb 100644
>> --- a/arch/powerpc/kernel/machine_kexec.c
>> +++ b/arch/powerpc/kernel/machine_kexec.c
>> @@ -86,6 +86,7 @@ void arch_crash_save_vmcoreinfo(void)
>> VMCOREINFO_STRUCT_SIZE(mmu_psize_def);
>> VMCOREINFO_OFFSET(mmu_psize_def, shift);
>> #endif
>> + vmcoreinfo_append_str("KERNELOFFSET=%lx\n", kaslr_offset());
>> }
>> /*
>> diff --git a/arch/powerpc/kernel/setup-common.c
>> b/arch/powerpc/kernel/setup-common.c
>> index 1f8db666468d..49e540c0adeb 100644
>> --- a/arch/powerpc/kernel/setup-common.c
>> +++ b/arch/powerpc/kernel/setup-common.c
>> @@ -715,12 +715,35 @@ static struct notifier_block ppc_panic_block = {
>> .priority = INT_MIN /* may not return; must be done last */
>> };
>> +/*
>> + * Dump out kernel offset information on panic.
>> + */
>> +static int dump_kernel_offset(struct notifier_block *self, unsigned
>> long v,
>> + void *p)
>> +{
>> + const unsigned long offset = kaslr_offset();
>> +
>> + if (IS_ENABLED(CONFIG_RANDOMIZE_BASE) && offset > 0)
>> + pr_emerg("Kernel Offset: 0x%lx from 0x%lx\n",
>> + offset, KERNELBASE);
>> + else
>> + pr_emerg("Kernel Offset: disabled\n");
>
> Do we really need that else branch ?
>
> Why not just make the below atomic_notifier_chain_register()
> conditionnal to IS_ENABLED(CONFIG_RANDOMIZE_BASE) && offset > 0
> and not print anything otherwise ?
>
I'm trying to keep the same fashion as x86/arm64 do. But I agree
with you that it's simpler to not print anything else if not randomized.
> Christophe
>
>> +
>> + return 0;
>> +}
>> +
>> +static struct notifier_block kernel_offset_notifier = {
>> + .notifier_call = dump_kernel_offset
>> +};
>> +
>> void __init setup_panic(void)
>> {
>> /* PPC64 always does a hard irq disable in its panic handler */
>> if (!IS_ENABLED(CONFIG_PPC64) && !ppc_md.panic)
>> return;
>> atomic_notifier_chain_register(&panic_notifier_list,
>> &ppc_panic_block);
>> + atomic_notifier_chain_register(&panic_notifier_list,
>> + &kernel_offset_notifier);
>> }
>> #ifdef CONFIG_CHECK_CACHE_COHERENCY
>>
>
> .
>
^ permalink raw reply
* Re: [RFC PATCH 09/10] powerpc/fsl_booke/kaslr: support nokaslr cmdline parameter
From: Jason Yan @ 2019-07-29 14:04 UTC (permalink / raw)
To: Christophe Leroy, mpe, linuxppc-dev, diana.craciun, benh, paulus,
npiggin, keescook, kernel-hardening
Cc: wangkefeng.wang, linux-kernel, jingxiangfeng, thunder.leizhen,
fanchengyang, yebin10
In-Reply-To: <e31851fd-5032-2787-ea36-c48a7a6ebbe9@c-s.fr>
On 2019/7/29 19:38, Christophe Leroy wrote:
>
>
> Le 17/07/2019 à 10:06, Jason Yan a écrit :
>> One may want to disable kaslr when boot, so provide a cmdline parameter
>> 'nokaslr' to support this.
>>
>> Signed-off-by: Jason Yan <yanaijie@huawei.com>
>> Cc: Diana Craciun <diana.craciun@nxp.com>
>> Cc: Michael Ellerman <mpe@ellerman.id.au>
>> Cc: Christophe Leroy <christophe.leroy@c-s.fr>
>> Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
>> Cc: Paul Mackerras <paulus@samba.org>
>> Cc: Nicholas Piggin <npiggin@gmail.com>
>> Cc: Kees Cook <keescook@chromium.org>
>> ---
>> arch/powerpc/kernel/kaslr_booke.c | 14 ++++++++++++++
>> 1 file changed, 14 insertions(+)
>>
>> diff --git a/arch/powerpc/kernel/kaslr_booke.c
>> b/arch/powerpc/kernel/kaslr_booke.c
>> index 00339c05879f..e65a5d9d2ff1 100644
>> --- a/arch/powerpc/kernel/kaslr_booke.c
>> +++ b/arch/powerpc/kernel/kaslr_booke.c
>> @@ -373,6 +373,18 @@ static unsigned long __init
>> kaslr_choose_location(void *dt_ptr, phys_addr_t size
>> return kaslr_offset;
>> }
>> +static inline __init bool kaslr_disabled(void)
>> +{
>> + char *str;
>> +
>> + str = strstr(early_command_line, "nokaslr");
>
> Why using early_command_line instead of boot_command_line ?
>
Will switch to boot_command_line.
>
>> + if ((str == early_command_line) ||
>> + (str > early_command_line && *(str - 1) == ' '))
>
> Is that stuff really needed ?
>
> Why not just:
>
> return strstr(early_command_line, "nokaslr") != NULL;
>
This code is derived from other arch such as arm64/mips. It's trying to
make sure that 'nokaslr' is a separate word but not part of other words
such as 'abcnokaslr'.
>> + return true;
>> +
>> + return false;
>> +}
>
>
>> +
>> /*
>> * To see if we need to relocate the kernel to a random offset
>> * void *dt_ptr - address of the device tree
>> @@ -388,6 +400,8 @@ notrace void __init kaslr_early_init(void *dt_ptr,
>> phys_addr_t size)
>> kernel_sz = (unsigned long)_end - KERNELBASE;
>> kaslr_get_cmdline(dt_ptr);
>> + if (kaslr_disabled())
>> + return;
>> offset = kaslr_choose_location(dt_ptr, size, kernel_sz);
>>
>
> Christophe
>
> .
>
^ permalink raw reply
* Re: [RFC PATCH 07/10] powerpc/fsl_booke/32: randomize the kernel image offset
From: Jason Yan @ 2019-07-29 13:53 UTC (permalink / raw)
To: Christophe Leroy, mpe, linuxppc-dev, diana.craciun, benh, paulus,
npiggin, keescook, kernel-hardening
Cc: wangkefeng.wang, linux-kernel, jingxiangfeng, thunder.leizhen,
fanchengyang, yebin10
In-Reply-To: <d2ed1821-96a2-d7eb-4c1e-4787c7dd467a@c-s.fr>
On 2019/7/29 19:33, Christophe Leroy wrote:
>
>
> Le 17/07/2019 à 10:06, Jason Yan a écrit :
>> After we have the basic support of relocate the kernel in some
>> appropriate place, we can start to randomize the offset now.
>>
>> Entropy is derived from the banner and timer, which will change every
>> build and boot. This not so much safe so additionally the bootloader may
>> pass entropy via the /chosen/kaslr-seed node in device tree.
>>
>> We will use the first 512M of the low memory to randomize the kernel
>> image. The memory will be split in 64M zones. We will use the lower 8
>> bit of the entropy to decide the index of the 64M zone. Then we chose a
>> 16K aligned offset inside the 64M zone to put the kernel in.
>>
>> KERNELBASE
>>
>> |--> 64M <--|
>> | |
>> +---------------+ +----------------+---------------+
>> | |....| |kernel| | |
>> +---------------+ +----------------+---------------+
>> | |
>> |-----> offset <-----|
>>
>> kimage_vaddr
>>
>> We also check if we will overlap with some areas like the dtb area, the
>> initrd area or the crashkernel area. If we cannot find a proper area,
>> kaslr will be disabled and boot from the original kernel.
>>
>> Signed-off-by: Jason Yan <yanaijie@huawei.com>
>> Cc: Diana Craciun <diana.craciun@nxp.com>
>> Cc: Michael Ellerman <mpe@ellerman.id.au>
>> Cc: Christophe Leroy <christophe.leroy@c-s.fr>
>> Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
>> Cc: Paul Mackerras <paulus@samba.org>
>> Cc: Nicholas Piggin <npiggin@gmail.com>
>> Cc: Kees Cook <keescook@chromium.org>
>> ---
>> arch/powerpc/kernel/kaslr_booke.c | 335 +++++++++++++++++++++++++++++-
>> 1 file changed, 333 insertions(+), 2 deletions(-)
>>
>> diff --git a/arch/powerpc/kernel/kaslr_booke.c
>> b/arch/powerpc/kernel/kaslr_booke.c
>> index 72d8e9432048..90357f4bd313 100644
>> --- a/arch/powerpc/kernel/kaslr_booke.c
>> +++ b/arch/powerpc/kernel/kaslr_booke.c
>> @@ -22,6 +22,8 @@
>> #include <linux/delay.h>
>> #include <linux/highmem.h>
>> #include <linux/memblock.h>
>> +#include <linux/libfdt.h>
>> +#include <linux/crash_core.h>
>> #include <asm/pgalloc.h>
>> #include <asm/prom.h>
>> #include <asm/io.h>
>> @@ -33,15 +35,342 @@
>> #include <asm/machdep.h>
>> #include <asm/setup.h>
>> #include <asm/paca.h>
>> +#include <asm/kdump.h>
>> #include <mm/mmu_decl.h>
>> +#include <generated/compile.h>
>> +#include <generated/utsrelease.h>
>> +
>> +#ifdef DEBUG
>> +#define DBG(fmt...) printk(KERN_ERR fmt)
>> +#else
>> +#define DBG(fmt...)
>> +#endif
>> +
>> +struct regions {
>> + unsigned long pa_start;
>> + unsigned long pa_end;
>> + unsigned long kernel_size;
>> + unsigned long dtb_start;
>> + unsigned long dtb_end;
>> + unsigned long initrd_start;
>> + unsigned long initrd_end;
>> + unsigned long crash_start;
>> + unsigned long crash_end;
>> + int reserved_mem;
>> + int reserved_mem_addr_cells;
>> + int reserved_mem_size_cells;
>> +};
>> extern int is_second_reloc;
>> +/* Simplified build-specific string for starting entropy. */
>> +static const char build_str[] = UTS_RELEASE " (" LINUX_COMPILE_BY "@"
>> + LINUX_COMPILE_HOST ") (" LINUX_COMPILER ") " UTS_VERSION;
>> +static char __initdata early_command_line[COMMAND_LINE_SIZE];
>> +
>> +static __init void kaslr_get_cmdline(void *fdt)
>> +{
>> + const char *cmdline = CONFIG_CMDLINE;
>> + if (!IS_ENABLED(CONFIG_CMDLINE_FORCE)) {
>> + int node;
>> + const u8 *prop;
>> + node = fdt_path_offset(fdt, "/chosen");
>> + if (node < 0)
>> + goto out;
>> +
>> + prop = fdt_getprop(fdt, node, "bootargs", NULL);
>> + if (!prop)
>> + goto out;
>> + cmdline = prop;
>> + }
>> +out:
>> + strscpy(early_command_line, cmdline, COMMAND_LINE_SIZE);
>> +}
>> +
>
> Can you explain why we need that and can't use the already existing
> cmdline stuff ?
>
I'm afraid of breaking the other initializing code of the cmdline
buffer at first. I will have a try to use it to see if there is any
problems.
> Christophe
>
>> +static unsigned long __init rotate_xor(unsigned long hash, const void
>> *area,
>> + size_t size)
>> +{
>> + size_t i;
>> + unsigned long *ptr = (unsigned long *)area;
>> +
>> + for (i = 0; i < size / sizeof(hash); i++) {
>> + /* Rotate by odd number of bits and XOR. */
>> + hash = (hash << ((sizeof(hash) * 8) - 7)) | (hash >> 7);
>> + hash ^= ptr[i];
>> + }
>> +
>> + return hash;
>> +}
>> +
>> +/* Attempt to create a simple but unpredictable starting entropy. */
>> +static unsigned long __init get_boot_seed(void *fdt)
>> +{
>> + unsigned long hash = 0;
>> +
>> + hash = rotate_xor(hash, build_str, sizeof(build_str));
>> + hash = rotate_xor(hash, fdt, fdt_totalsize(fdt));
>> +
>> + return hash;
>> +}
>> +
>> +static __init u64 get_kaslr_seed(void *fdt)
>> +{
>> + int node, len;
>> + fdt64_t *prop;
>> + u64 ret;
>> +
>> + node = fdt_path_offset(fdt, "/chosen");
>> + if (node < 0)
>> + return 0;
>> +
>> + prop = fdt_getprop_w(fdt, node, "kaslr-seed", &len);
>> + if (!prop || len != sizeof(u64))
>> + return 0;
>> +
>> + ret = fdt64_to_cpu(*prop);
>> + *prop = 0;
>> + return ret;
>> +}
>> +
>> +static __init bool regions_overlap(u32 s1, u32 e1, u32 s2, u32 e2)
>> +{
>> + return e1 >= s2 && e2 >= s1;
>> +}
>> +
>> +static __init bool overlaps_reserved_region(const void *fdt, u32 start,
>> + u32 end, struct regions *regions)
>> +{
>> + int subnode, len, i;
>> + u64 base, size;
>> +
>> + /* check for overlap with /memreserve/ entries */
>> + for (i = 0; i < fdt_num_mem_rsv(fdt); i++) {
>> + if (fdt_get_mem_rsv(fdt, i, &base, &size) < 0)
>> + continue;
>> + if (regions_overlap(start, end, base, base + size))
>> + return true;
>> + }
>> +
>> + if (regions->reserved_mem < 0)
>> + return false;
>> +
>> + /* check for overlap with static reservations in /reserved-memory */
>> + for (subnode = fdt_first_subnode(fdt, regions->reserved_mem);
>> + subnode >= 0;
>> + subnode = fdt_next_subnode(fdt, subnode)) {
>> + const fdt32_t *reg;
>> + u64 rsv_end;
>> +
>> + len = 0;
>> + reg = fdt_getprop(fdt, subnode, "reg", &len);
>> + while (len >= (regions->reserved_mem_addr_cells +
>> + regions->reserved_mem_size_cells)) {
>> + base = fdt32_to_cpu(reg[0]);
>> + if (regions->reserved_mem_addr_cells == 2)
>> + base = (base << 32) | fdt32_to_cpu(reg[1]);
>> +
>> + reg += regions->reserved_mem_addr_cells;
>> + len -= 4 * regions->reserved_mem_addr_cells;
>> +
>> + size = fdt32_to_cpu(reg[0]);
>> + if (regions->reserved_mem_size_cells == 2)
>> + size = (size << 32) | fdt32_to_cpu(reg[1]);
>> +
>> + reg += regions->reserved_mem_size_cells;
>> + len -= 4 * regions->reserved_mem_size_cells;
>> +
>> + if (base >= regions->pa_end)
>> + continue;
>> +
>> + rsv_end = min(base + size, (u64)U32_MAX);
>> +
>> + if (regions_overlap(start, end, base, rsv_end))
>> + return true;
>> + }
>> + }
>> + return false;
>> +}
>> +
>> +static __init bool overlaps_region(const void *fdt, u32 start,
>> + u32 end, struct regions *regions)
>> +{
>> + if (regions_overlap(start, end, regions->dtb_start,
>> + regions->dtb_end))
>> + return true;
>> +
>> + if (regions_overlap(start, end, regions->initrd_start,
>> + regions->initrd_end))
>> + return true;
>> +
>> + if (regions_overlap(start, end, regions->crash_start,
>> + regions->crash_end))
>> + return true;
>> +
>> + return overlaps_reserved_region(fdt, start, end, regions);
>> +}
>> +
>> +static void __init get_crash_kernel(void *fdt, unsigned long size,
>> + struct regions *regions)
>> +{
>> +#ifdef CONFIG_KEXEC_CORE
>> + unsigned long long crash_size, crash_base;
>> + int ret;
>> +
>> + ret = parse_crashkernel(early_command_line, size, &crash_size,
>> + &crash_base);
>> + if (ret != 0 || crash_size == 0)
>> + return;
>> + if (crash_base == 0)
>> + crash_base = KDUMP_KERNELBASE;
>> +
>> + regions->crash_start = (unsigned long)crash_base;
>> + regions->crash_end = (unsigned long)(crash_base + crash_size);
>> +
>> + DBG("crash_base=0x%llx crash_size=0x%llx\n", crash_base,
>> crash_size);
>> +#endif
>> +}
>> +
>> +static void __init get_initrd_range(void *fdt, struct regions *regions)
>> +{
>> + u64 start, end;
>> + int node, len;
>> + const __be32 *prop;
>> +
>> + node = fdt_path_offset(fdt, "/chosen");
>> + if (node < 0)
>> + return;
>> +
>> + prop = fdt_getprop(fdt, node, "linux,initrd-start", &len);
>> + if (!prop)
>> + return;
>> + start = of_read_number(prop, len / 4);
>> +
>> + prop = fdt_getprop(fdt, node, "linux,initrd-end", &len);
>> + if (!prop)
>> + return;
>> + end = of_read_number(prop, len / 4);
>> +
>> + regions->initrd_start = (unsigned long)start;
>> + regions->initrd_end = (unsigned long)end;
>> +
>> + DBG("initrd_start=0x%llx initrd_end=0x%llx\n", start, end);
>> +}
>> +
>> +static __init unsigned long get_usable_offset(const void *fdt, struct
>> regions *regions,
>> + unsigned long start)
>> +{
>> + unsigned long pa;
>> + unsigned long pa_end;
>> +
>> + for (pa = start; pa > regions->pa_start; pa -= SZ_16K) {
>> + pa_end = pa + regions->kernel_size;
>> + if (overlaps_region(fdt, pa, pa_end, regions))
>> + continue;
>> +
>> + return pa;
>> + }
>> + return 0;
>> +}
>> +
>> +static __init void get_cell_sizes(const void *fdt, int node, int
>> *addr_cells,
>> + int *size_cells)
>> +{
>> + const int *prop;
>> + int len;
>> +
>> + /*
>> + * Retrieve the #address-cells and #size-cells properties
>> + * from the 'node', or use the default if not provided.
>> + */
>> + *addr_cells = *size_cells = 1;
>> +
>> + prop = fdt_getprop(fdt, node, "#address-cells", &len);
>> + if (len == 4)
>> + *addr_cells = fdt32_to_cpu(*prop);
>> + prop = fdt_getprop(fdt, node, "#size-cells", &len);
>> + if (len == 4)
>> + *size_cells = fdt32_to_cpu(*prop);
>> +}
>> +
>> static unsigned long __init kaslr_choose_location(void *dt_ptr,
>> phys_addr_t size,
>> unsigned long kernel_sz)
>> {
>> - /* return a fixed offset of 64M for now */
>> - return 0x4000000;
>> + unsigned long offset, random;
>> + unsigned long ram, linear_sz;
>> + unsigned long kaslr_offset;
>> + u64 seed;
>> + struct regions regions;
>> + unsigned long index;
>> +
>> + random = get_boot_seed(dt_ptr);
>> +
>> + seed = get_tb() << 32;
>> + seed ^= get_tb();
>> + random = rotate_xor(random, &seed, sizeof(seed));
>> +
>> + /*
>> + * Retrieve (and wipe) the seed from the FDT
>> + */
>> + seed = get_kaslr_seed(dt_ptr);
>> + if (seed)
>> + random = rotate_xor(random, &seed, sizeof(seed));
>> +
>> + ram = min((phys_addr_t)__max_low_memory, size);
>> + ram = map_mem_in_cams(ram, CONFIG_LOWMEM_CAM_NUM, true);
>> + linear_sz = min(ram, (unsigned long)SZ_512M);
>> +
>> + /* If the linear size is smaller than 64M, do not randmize */
>> + if (linear_sz < SZ_64M)
>> + return 0;
>> +
>> + memset(®ions, 0, sizeof(regions));
>> +
>> + /* check for a reserved-memory node and record its cell sizes */
>> + regions.reserved_mem = fdt_path_offset(dt_ptr, "/reserved-memory");
>> + if (regions.reserved_mem >= 0)
>> + get_cell_sizes(dt_ptr, regions.reserved_mem,
>> + ®ions.reserved_mem_addr_cells,
>> + ®ions.reserved_mem_size_cells);
>> +
>> + regions.pa_start = 0;
>> + regions.pa_end = linear_sz;
>> + regions.dtb_start = __pa(dt_ptr);
>> + regions.dtb_end = __pa(dt_ptr) + fdt_totalsize(dt_ptr);
>> + regions.kernel_size = kernel_sz;
>> +
>> + get_initrd_range(dt_ptr, ®ions);
>> + get_crash_kernel(dt_ptr, ram, ®ions);
>> +
>> + /*
>> + * Decide which 64M we want to start
>> + * Only use the low 8 bits of the random seed
>> + */
>> + index = random & 0xFF;
>> + index %= linear_sz / SZ_64M;
>> +
>> + /* Decide offset inside 64M */
>> + if (index == 0) {
>> + offset = random % (SZ_64M - round_up(kernel_sz, SZ_16K) * 2);
>> + offset += round_up(kernel_sz, SZ_16K);
>> + offset = round_up(offset, SZ_16K);
>> + } else {
>> + offset = random % (SZ_64M - kernel_sz);
>> + offset = round_down(offset, SZ_16K);
>> + }
>> +
>> + while (index >= 0) {
>> + offset = offset + index * SZ_64M;
>> + kaslr_offset = get_usable_offset(dt_ptr, ®ions, offset);
>> + if (kaslr_offset)
>> + break;
>> + index--;
>> + }
>> +
>> + /* Did not find any usable region? Give up randomize */
>> + if (index < 0)
>> + kaslr_offset = 0;
>> +
>> + return kaslr_offset;
>> }
>> /*
>> @@ -58,6 +387,8 @@ notrace void __init kaslr_early_init(void *dt_ptr,
>> phys_addr_t size)
>> kernel_sz = (unsigned long)_end - KERNELBASE;
>> + kaslr_get_cmdline(dt_ptr);
>> +
>> offset = kaslr_choose_location(dt_ptr, size, kernel_sz);
>> if (offset == 0)
>>
>
> .
>
^ permalink raw reply
* Re: [RFC PATCH 08/10] powerpc/fsl_booke/kaslr: clear the original kernel if randomized
From: Jason Yan @ 2019-07-29 13:43 UTC (permalink / raw)
To: Christophe Leroy, mpe, linuxppc-dev, diana.craciun, benh, paulus,
npiggin, keescook, kernel-hardening
Cc: wangkefeng.wang, linux-kernel, jingxiangfeng, thunder.leizhen,
fanchengyang, yebin10
In-Reply-To: <a09b4f53-2ccd-e675-4385-b53fd91fbafc@c-s.fr>
On 2019/7/29 19:19, Christophe Leroy wrote:
>
>
> Le 17/07/2019 à 10:06, Jason Yan a écrit :
>> The original kernel still exists in the memory, clear it now.
>>
>> Signed-off-by: Jason Yan <yanaijie@huawei.com>
>> Cc: Diana Craciun <diana.craciun@nxp.com>
>> Cc: Michael Ellerman <mpe@ellerman.id.au>
>> Cc: Christophe Leroy <christophe.leroy@c-s.fr>
>> Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
>> Cc: Paul Mackerras <paulus@samba.org>
>> Cc: Nicholas Piggin <npiggin@gmail.com>
>> Cc: Kees Cook <keescook@chromium.org>
>> ---
>> arch/powerpc/kernel/kaslr_booke.c | 11 +++++++++++
>> arch/powerpc/mm/mmu_decl.h | 2 ++
>> arch/powerpc/mm/nohash/fsl_booke.c | 1 +
>> 3 files changed, 14 insertions(+)
>>
>> diff --git a/arch/powerpc/kernel/kaslr_booke.c
>> b/arch/powerpc/kernel/kaslr_booke.c
>> index 90357f4bd313..00339c05879f 100644
>> --- a/arch/powerpc/kernel/kaslr_booke.c
>> +++ b/arch/powerpc/kernel/kaslr_booke.c
>> @@ -412,3 +412,14 @@ notrace void __init kaslr_early_init(void
>> *dt_ptr, phys_addr_t size)
>> reloc_kernel_entry(dt_ptr, kimage_vaddr);
>> }
>> +
>> +void __init kaslr_second_init(void)
>> +{
>> + /* If randomized, clear the original kernel */
>> + if (kimage_vaddr != KERNELBASE) {
>> + unsigned long kernel_sz;
>> +
>> + kernel_sz = (unsigned long)_end - kimage_vaddr;
>> + memset((void *)KERNELBASE, 0, kernel_sz);
>
> Why are we clearing ? Is that just to tidy up or is it of security
> importance ?
>
If we leave it there, attackers can still find the kernel object very
easy, it's still dangerous especially if without
CONFIG_STRICT_KERNEL_RWX enabled.
> If so, maybe memzero_explicit() should be used instead ?
>
OK
>> + }
>> +}
>> diff --git a/arch/powerpc/mm/mmu_decl.h b/arch/powerpc/mm/mmu_decl.h
>> index 754ae1e69f92..9912ee598f9b 100644
>> --- a/arch/powerpc/mm/mmu_decl.h
>> +++ b/arch/powerpc/mm/mmu_decl.h
>> @@ -150,8 +150,10 @@ extern void loadcam_multi(int first_idx, int num,
>> int tmp_idx);
>> #ifdef CONFIG_RANDOMIZE_BASE
>> extern void kaslr_early_init(void *dt_ptr, phys_addr_t size);
>> +extern void kaslr_second_init(void);
>
> No new 'extern' please.
>
>> #else
>> static inline void kaslr_early_init(void *dt_ptr, phys_addr_t size) {}
>> +static inline void kaslr_second_init(void) {}
>> #endif
>> struct tlbcam {
>> diff --git a/arch/powerpc/mm/nohash/fsl_booke.c
>> b/arch/powerpc/mm/nohash/fsl_booke.c
>> index 8d25a8dc965f..fa5a87f5c08e 100644
>> --- a/arch/powerpc/mm/nohash/fsl_booke.c
>> +++ b/arch/powerpc/mm/nohash/fsl_booke.c
>> @@ -269,6 +269,7 @@ notrace void __init relocate_init(u64 dt_ptr,
>> phys_addr_t start)
>> kernstart_addr = start;
>> if (is_second_reloc) {
>> virt_phys_offset = PAGE_OFFSET - memstart_addr;
>> + kaslr_second_init();
>> return;
>> }
>>
>
> Christophe
>
> .
>
^ permalink raw reply
* Re: [RFC PATCH 05/10] powerpc/fsl_booke/32: introduce reloc_kernel_entry() helper
From: Jason Yan @ 2019-07-29 13:35 UTC (permalink / raw)
To: Christophe Leroy, mpe, linuxppc-dev, diana.craciun, benh, paulus,
npiggin, keescook, kernel-hardening
Cc: wangkefeng.wang, linux-kernel, jingxiangfeng, thunder.leizhen,
fanchengyang, yebin10
In-Reply-To: <e4ccd015-a9c4-b0a6-e3ca-d37a04e29ec6@c-s.fr>
On 2019/7/29 19:08, Christophe Leroy wrote:
>
>
> Le 17/07/2019 à 10:06, Jason Yan a écrit :
>> Add a new helper reloc_kernel_entry() to jump back to the start of the
>> new kernel. After we put the new kernel in a randomized place we can use
>> this new helper to enter the kernel and begin to relocate again.
>>
>> Signed-off-by: Jason Yan <yanaijie@huawei.com>
>> Cc: Diana Craciun <diana.craciun@nxp.com>
>> Cc: Michael Ellerman <mpe@ellerman.id.au>
>> Cc: Christophe Leroy <christophe.leroy@c-s.fr>
>> Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
>> Cc: Paul Mackerras <paulus@samba.org>
>> Cc: Nicholas Piggin <npiggin@gmail.com>
>> Cc: Kees Cook <keescook@chromium.org>
>> ---
>> arch/powerpc/kernel/head_fsl_booke.S | 16 ++++++++++++++++
>> arch/powerpc/mm/mmu_decl.h | 1 +
>> 2 files changed, 17 insertions(+)
>>
>> diff --git a/arch/powerpc/kernel/head_fsl_booke.S
>> b/arch/powerpc/kernel/head_fsl_booke.S
>> index a57d44638031..ce40f96dae20 100644
>> --- a/arch/powerpc/kernel/head_fsl_booke.S
>> +++ b/arch/powerpc/kernel/head_fsl_booke.S
>> @@ -1144,6 +1144,22 @@ _GLOBAL(create_tlb_entry)
>> sync
>> blr
>> +/*
>> + * Return to the start of the relocated kernel and run again
>> + * r3 - virtual address of fdt
>> + * r4 - entry of the kernel
>> + */
>> +_GLOBAL(reloc_kernel_entry)
>> + mfmsr r7
>> + li r8,(MSR_IS | MSR_DS)
>> + andc r7,r7,r8
>
> Instead of the li/andc, what about the following:
>
> rlwinm r7, r7, 0, ~(MSR_IS | MSR_DS)
>
Good idea.
>> +
>> + mtspr SPRN_SRR0,r4
>> + mtspr SPRN_SRR1,r7
>> + isync
>> + sync
>> + rfi
>
> Are the isync/sync really necessary ? AFAIK, rfi is context synchronising.
>
I see some code with sync before rfi so I'm not sure. I will check this
and drop the isync/sync if it's true.
Thanks.
>> +
>> /*
>> * Create a tlb entry with the same effective and physical address as
>> * the tlb entry used by the current running code. But set the TS to 1.
>> diff --git a/arch/powerpc/mm/mmu_decl.h b/arch/powerpc/mm/mmu_decl.h
>> index d7737cf97cee..dae8e9177574 100644
>> --- a/arch/powerpc/mm/mmu_decl.h
>> +++ b/arch/powerpc/mm/mmu_decl.h
>> @@ -143,6 +143,7 @@ extern void adjust_total_lowmem(void);
>> extern int switch_to_as1(void);
>> extern void restore_to_as0(int esel, int offset, void *dt_ptr, int
>> bootcpu);
>> extern void create_tlb_entry(phys_addr_t phys, unsigned long virt,
>> int entry);
>> +extern void reloc_kernel_entry(void *fdt, int addr);
>
> No new 'extern' please, see
> https://openpower.xyz/job/snowpatch/job/snowpatch-linux-checkpatch/8125//artifact/linux/checkpatch.log
>
>
>
>> #endif
>> extern void loadcam_entry(unsigned int index);
>> extern void loadcam_multi(int first_idx, int num, int tmp_idx);
>>
>
> Christophe
>
> .
>
^ permalink raw reply
* Re: [RFC PATCH 04/10] powerpc/fsl_booke/32: introduce create_tlb_entry() helper
From: Jason Yan @ 2019-07-29 13:26 UTC (permalink / raw)
To: Christophe Leroy, mpe, linuxppc-dev, diana.craciun, benh, paulus,
npiggin, keescook, kernel-hardening
Cc: wangkefeng.wang, linux-kernel, jingxiangfeng, thunder.leizhen,
fanchengyang, yebin10
In-Reply-To: <4e6c468d-287b-4bba-675c-8b3f73456500@c-s.fr>
On 2019/7/29 19:05, Christophe Leroy wrote:
>
>
> Le 17/07/2019 à 10:06, Jason Yan a écrit :
>> Add a new helper create_tlb_entry() to create a tlb entry by the virtual
>> and physical address. This is a preparation to support boot kernel at a
>> randomized address.
>>
>> Signed-off-by: Jason Yan <yanaijie@huawei.com>
>> Cc: Diana Craciun <diana.craciun@nxp.com>
>> Cc: Michael Ellerman <mpe@ellerman.id.au>
>> Cc: Christophe Leroy <christophe.leroy@c-s.fr>
>> Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
>> Cc: Paul Mackerras <paulus@samba.org>
>> Cc: Nicholas Piggin <npiggin@gmail.com>
>> Cc: Kees Cook <keescook@chromium.org>
>> ---
>> arch/powerpc/kernel/head_fsl_booke.S | 30 ++++++++++++++++++++++++++++
>> arch/powerpc/mm/mmu_decl.h | 1 +
>> 2 files changed, 31 insertions(+)
>>
>> diff --git a/arch/powerpc/kernel/head_fsl_booke.S
>> b/arch/powerpc/kernel/head_fsl_booke.S
>> index adf0505dbe02..a57d44638031 100644
>> --- a/arch/powerpc/kernel/head_fsl_booke.S
>> +++ b/arch/powerpc/kernel/head_fsl_booke.S
>> @@ -1114,6 +1114,36 @@ __secondary_hold_acknowledge:
>> .long -1
>> #endif
>> +/*
>> + * Create a 64M tlb by address and entry
>> + * r3/r4 - physical address
>> + * r5 - virtual address
>> + * r6 - entry
>> + */
>> +_GLOBAL(create_tlb_entry)
>> + lis r7,0x1000 /* Set MAS0(TLBSEL) = 1 */
>> + rlwimi r7,r6,16,4,15 /* Setup MAS0 = TLBSEL | ESEL(r6) */
>> + mtspr SPRN_MAS0,r7 /* Write MAS0 */
>> +
>> + lis r6,(MAS1_VALID|MAS1_IPROT)@h
>> + ori r6,r6,(MAS1_TSIZE(BOOK3E_PAGESZ_64M))@l
>> + mtspr SPRN_MAS1,r6 /* Write MAS1 */
>> +
>> + lis r6,MAS2_EPN_MASK(BOOK3E_PAGESZ_64M)@h
>> + ori r6,r6,MAS2_EPN_MASK(BOOK3E_PAGESZ_64M)@l
>> + and r6,r6,r5
>> + ori r6,r6,MAS2_M@l
>> + mtspr SPRN_MAS2,r6 /* Write MAS2(EPN) */
>> +
>> + mr r8,r4
>> + ori r8,r8,(MAS3_SW|MAS3_SR|MAS3_SX)
>
> Could drop the mr r8, r4 and do:
>
> ori r8,r4,(MAS3_SW|MAS3_SR|MAS3_SX)
>
OK, thanks for the suggestion.
>> + mtspr SPRN_MAS3,r8 /* Write MAS3(RPN) */
>> +
>> + tlbwe /* Write TLB */
>> + isync
>> + sync
>> + blr
>> +
>> /*
>> * Create a tlb entry with the same effective and physical address as
>> * the tlb entry used by the current running code. But set the TS to 1.
>> diff --git a/arch/powerpc/mm/mmu_decl.h b/arch/powerpc/mm/mmu_decl.h
>> index 32c1a191c28a..d7737cf97cee 100644
>> --- a/arch/powerpc/mm/mmu_decl.h
>> +++ b/arch/powerpc/mm/mmu_decl.h
>> @@ -142,6 +142,7 @@ extern unsigned long calc_cam_sz(unsigned long
>> ram, unsigned long virt,
>> extern void adjust_total_lowmem(void);
>> extern int switch_to_as1(void);
>> extern void restore_to_as0(int esel, int offset, void *dt_ptr, int
>> bootcpu);
>> +extern void create_tlb_entry(phys_addr_t phys, unsigned long virt,
>> int entry);
>
> Please please do not add new declarations with the useless 'extern'
> keyword. See checkpatch report:
> https://openpower.xyz/job/snowpatch/job/snowpatch-linux-checkpatch/8124//artifact/linux/checkpatch.log
>
Will drop all useless 'extern' in this and other patches, thanks.
>
>> #endif
>> extern void loadcam_entry(unsigned int index);
>> extern void loadcam_multi(int first_idx, int num, int tmp_idx);
>>
>
> .
>
^ permalink raw reply
* Re: [PATCH] powerpc: Use nid as fallback for chip_id
From: Michael Ellerman @ 2019-07-29 12:41 UTC (permalink / raw)
To: Srikar Dronamraju, linuxppc-dev, Vasant Hegde
Cc: Vaidyanathan Srinivasan, Srikar Dronamraju
In-Reply-To: <1562062765-31104-1-git-send-email-srikar@linux.vnet.ibm.com>
Srikar Dronamraju <srikar@linux.vnet.ibm.com> writes:
> One of the uses of chip_id is to find out all cores that are part of the same
> chip. However ibm,chip_id property is not present in device-tree of PowerVM
> Lpars. Hence lscpu output shows one core per socket and multiple cores.
>
> Before the patch.
> # lscpu
> Architecture: ppc64le
> Byte Order: Little Endian
> CPU(s): 128
> On-line CPU(s) list: 0-127
> Thread(s) per core: 8
> Core(s) per socket: 1
> Socket(s): 16
> NUMA node(s): 2
> Model: 2.2 (pvr 004e 0202)
> Model name: POWER9 (architected), altivec supported
> Hypervisor vendor: pHyp
> Virtualization type: para
> L1d cache: 32K
> L1i cache: 32K
> L2 cache: 512K
> L3 cache: 10240K
> NUMA node0 CPU(s): 0-63
> NUMA node1 CPU(s): 64-127
>
> # cat /sys/devices/system/cpu/cpu0/topology/physical_package_id
> -1
>
> Signed-off-by: Srikar Dronamraju <srikar@linux.vnet.ibm.com>
> ---
> arch/powerpc/kernel/prom.c | 10 ++++++++--
> 1 file changed, 8 insertions(+), 2 deletions(-)
>
> diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c
> index 7159e791a70d..0b8918b43580 100644
> --- a/arch/powerpc/kernel/prom.c
> +++ b/arch/powerpc/kernel/prom.c
> @@ -867,18 +867,24 @@ EXPORT_SYMBOL(of_get_ibm_chip_id);
> * @cpu: The logical cpu number.
> *
> * Return the value of the ibm,chip-id property corresponding to the given
> - * logical cpu number. If the chip-id can not be found, returns -1.
> + * logical cpu number. If the chip-id can not be found, return nid.
> + *
> */
> int cpu_to_chip_id(int cpu)
> {
> struct device_node *np;
> + int chip_id = -1;
>
> np = of_get_cpu_node(cpu, NULL);
> if (!np)
> return -1;
>
> + chip_id = of_get_ibm_chip_id(np);
> + if (chip_id == -1)
> + chip_id = of_node_to_nid(np);
> +
> of_node_put(np);
> - return of_get_ibm_chip_id(np);
> + return chip_id;
> }
A nid is not a chip-id.
This obviously happens to work for the case you've identified above but
it's not something I'm happy to merge in general.
We could do a similar change in the topology code, but I'd probably like
it to be restricted to when we're running under PowerVM and there are no
chip-ids found at all.
I'm also not clear how it will interact with migration.
cheers
^ permalink raw reply
* Re: [PATCH v2] powerpc/imc: Dont create debugfs files for cpu-less nodes
From: Michael Ellerman @ 2019-07-29 12:36 UTC (permalink / raw)
To: Anju T Sudhakar, Qian Cai, Madhavan Srinivasan; +Cc: linuxppc-dev
In-Reply-To: <b1d6a06f-5f3b-d887-27cf-ba8c0255c4b0@linux.vnet.ibm.com>
Anju T Sudhakar <anju@linux.vnet.ibm.com> writes:
> Hi Qian,
>
> On 7/16/19 12:11 AM, Qian Cai wrote:
>> On Thu, 2019-07-11 at 14:53 +1000, Michael Ellerman wrote:
>>> Hi Maddy,
>>>
>>> Madhavan Srinivasan <maddy@linux.vnet.ibm.com> writes:
>>>> diff --git a/arch/powerpc/platforms/powernv/opal-imc.c
>>>> b/arch/powerpc/platforms/powernv/opal-imc.c
>>>> index 186109bdd41b..e04b20625cb9 100644
>>>> --- a/arch/powerpc/platforms/powernv/opal-imc.c
>>>> +++ b/arch/powerpc/platforms/powernv/opal-imc.c
>>>> @@ -69,20 +69,20 @@ static void export_imc_mode_and_cmd(struct device_node
>>>> *node,
>>>> if (of_property_read_u32(node, "cb_offset", &cb_offset))
>>>> cb_offset = IMC_CNTL_BLK_OFFSET;
>>>>
>>>> - for_each_node(nid) {
>>>> - loc = (u64)(pmu_ptr->mem_info[chip].vbase) + cb_offset;
>>>> + while (ptr->vbase != NULL) {
>>> This means you'll bail out as soon as you find a node with no vbase, but
>>> it's possible we could have a CPU-less node intermingled with other
>>> nodes.
>>>
>>> So I think you want to keep the for loop, but continue if you see a NULL
>>> vbase?
>> Not sure if this will also takes care of some of those messages during the boot
>> on today's linux-next even without this patch.
>>
>>
>> [ 18.077780][ T1] debugfs: Directory 'imc' with parent 'powerpc' already
>> present!
>>
>>
>
> This is introduced by a recent commit: c33d442328f55 (debugfs: make
> error message a bit more verbose).
>
> So basically, the debugfs imc_* file is created per node, and is created
> by the first nest unit which is
>
> being registered. For the subsequent nest units, debugfs_create_dir()
> will just return since the imc_* file already
>
> exist.
>
> The commit "c33d442328f55 (debugfs: make error message a bit more
> verbose)", prints
>
> a message if the debugfs file already exists in debugfs_create_dir().
> That is why we are encountering these
>
> messages now.
>
>
> This patch (i.e, powerpc/imc: Dont create debugfs files for cpu-less
> nodes) will address the initial issue, i.e
>
> "numa crash while reading imc_* debugfs files for cpu less nodes", and
> will not address these debugfs messages.
>
>
> But yeah this is a good catch. We can have some checks to avoid these
> debugfs messages.
>
>
> Hi Michael,
>
> Do we need to have a separate patch to address these debugfs messages,
> or can we address the same
>
> in the next version of this patch itself?
No, please do one logical change per patch.
cheers
^ permalink raw reply
* Re: [PATCH 4/5] powerpc/64: Add VIRTUAL_BUG_ON checks for __va and __pa addresses
From: Christophe Leroy @ 2019-07-29 11:57 UTC (permalink / raw)
To: Nicholas Piggin, linuxppc-dev
Cc: Aneesh Kumar K . V, Madhavan Srinivasan, Anju T Sudhakar,
Reza Arbab
In-Reply-To: <20190724084638.24982-4-npiggin@gmail.com>
Le 24/07/2019 à 10:46, Nicholas Piggin a écrit :
> Ensure __va is given a physical address below PAGE_OFFSET, and __pa is
> given a virtual address above PAGE_OFFSET.
>
> Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
> ---
> arch/powerpc/include/asm/page.h | 14 ++++++++++++--
> 1 file changed, 12 insertions(+), 2 deletions(-)
>
> diff --git a/arch/powerpc/include/asm/page.h b/arch/powerpc/include/asm/page.h
> index 0d52f57fca04..c8bb14ff4713 100644
> --- a/arch/powerpc/include/asm/page.h
> +++ b/arch/powerpc/include/asm/page.h
> @@ -215,9 +215,19 @@ static inline bool pfn_valid(unsigned long pfn)
> /*
> * gcc miscompiles (unsigned long)(&static_var) - PAGE_OFFSET
> * with -mcmodel=medium, so we use & and | instead of - and + on 64-bit.
> + * This also results in better code generation.
> */
> -#define __va(x) ((void *)(unsigned long)((phys_addr_t)(x) | PAGE_OFFSET))
> -#define __pa(x) ((unsigned long)(x) & 0x0fffffffffffffffUL)
> +#define __va(x) \
> +({ \
> + VIRTUAL_BUG_ON((unsigned long)(x) >= PAGE_OFFSET); \
Do we really want to add a BUG_ON here ?
Can't we just add a WARN_ON, like in
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/arch/powerpc/include/asm/io.h?id=6bf752daca07c85c181159f75dcf65b12056883b
?
> + (void *)(unsigned long)((phys_addr_t)(x) | PAGE_OFFSET); \
> +})
> +
> +#define __pa(x) \
> +({ \
> + VIRTUAL_BUG_ON((unsigned long)(x) < PAGE_OFFSET); \
Same
> + (unsigned long)(x) & 0x0fffffffffffffffUL; \
> +})
>
> #else /* 32-bit, non book E */
> #define __va(x) ((void *)(unsigned long)((phys_addr_t)(x) + PAGE_OFFSET - MEMORY_START))
>
Would it be possible to change those macros into static inlines ?
Christophe
^ permalink raw reply
* Re: [RFC PATCH 10/10] powerpc/fsl_booke/kaslr: dump out kernel offset information on panic
From: Christophe Leroy @ 2019-07-29 11:43 UTC (permalink / raw)
To: Jason Yan, mpe, linuxppc-dev, diana.craciun, benh, paulus,
npiggin, keescook, kernel-hardening
Cc: wangkefeng.wang, linux-kernel, jingxiangfeng, thunder.leizhen,
fanchengyang, yebin10
In-Reply-To: <20190717080621.40424-11-yanaijie@huawei.com>
Le 17/07/2019 à 10:06, Jason Yan a écrit :
> When kaslr is enabled, the kernel offset is different for every boot.
> This brings some difficult to debug the kernel. Dump out the kernel
> offset when panic so that we can easily debug the kernel.
>
> Signed-off-by: Jason Yan <yanaijie@huawei.com>
> Cc: Diana Craciun <diana.craciun@nxp.com>
> Cc: Michael Ellerman <mpe@ellerman.id.au>
> Cc: Christophe Leroy <christophe.leroy@c-s.fr>
> Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
> Cc: Paul Mackerras <paulus@samba.org>
> Cc: Nicholas Piggin <npiggin@gmail.com>
> Cc: Kees Cook <keescook@chromium.org>
> ---
> arch/powerpc/include/asm/page.h | 5 +++++
> arch/powerpc/kernel/machine_kexec.c | 1 +
> arch/powerpc/kernel/setup-common.c | 23 +++++++++++++++++++++++
> 3 files changed, 29 insertions(+)
>
> diff --git a/arch/powerpc/include/asm/page.h b/arch/powerpc/include/asm/page.h
> index 60a68d3a54b1..cd3ac530e58d 100644
> --- a/arch/powerpc/include/asm/page.h
> +++ b/arch/powerpc/include/asm/page.h
> @@ -317,6 +317,11 @@ struct vm_area_struct;
>
> extern unsigned long kimage_vaddr;
>
> +static inline unsigned long kaslr_offset(void)
> +{
> + return kimage_vaddr - KERNELBASE;
> +}
> +
> #include <asm-generic/memory_model.h>
> #endif /* __ASSEMBLY__ */
> #include <asm/slice.h>
> diff --git a/arch/powerpc/kernel/machine_kexec.c b/arch/powerpc/kernel/machine_kexec.c
> index c4ed328a7b96..078fe3d76feb 100644
> --- a/arch/powerpc/kernel/machine_kexec.c
> +++ b/arch/powerpc/kernel/machine_kexec.c
> @@ -86,6 +86,7 @@ void arch_crash_save_vmcoreinfo(void)
> VMCOREINFO_STRUCT_SIZE(mmu_psize_def);
> VMCOREINFO_OFFSET(mmu_psize_def, shift);
> #endif
> + vmcoreinfo_append_str("KERNELOFFSET=%lx\n", kaslr_offset());
> }
>
> /*
> diff --git a/arch/powerpc/kernel/setup-common.c b/arch/powerpc/kernel/setup-common.c
> index 1f8db666468d..49e540c0adeb 100644
> --- a/arch/powerpc/kernel/setup-common.c
> +++ b/arch/powerpc/kernel/setup-common.c
> @@ -715,12 +715,35 @@ static struct notifier_block ppc_panic_block = {
> .priority = INT_MIN /* may not return; must be done last */
> };
>
> +/*
> + * Dump out kernel offset information on panic.
> + */
> +static int dump_kernel_offset(struct notifier_block *self, unsigned long v,
> + void *p)
> +{
> + const unsigned long offset = kaslr_offset();
> +
> + if (IS_ENABLED(CONFIG_RANDOMIZE_BASE) && offset > 0)
> + pr_emerg("Kernel Offset: 0x%lx from 0x%lx\n",
> + offset, KERNELBASE);
> + else
> + pr_emerg("Kernel Offset: disabled\n");
Do we really need that else branch ?
Why not just make the below atomic_notifier_chain_register()
conditionnal to IS_ENABLED(CONFIG_RANDOMIZE_BASE) && offset > 0
and not print anything otherwise ?
Christophe
> +
> + return 0;
> +}
> +
> +static struct notifier_block kernel_offset_notifier = {
> + .notifier_call = dump_kernel_offset
> +};
> +
> void __init setup_panic(void)
> {
> /* PPC64 always does a hard irq disable in its panic handler */
> if (!IS_ENABLED(CONFIG_PPC64) && !ppc_md.panic)
> return;
> atomic_notifier_chain_register(&panic_notifier_list, &ppc_panic_block);
> + atomic_notifier_chain_register(&panic_notifier_list,
> + &kernel_offset_notifier);
> }
>
> #ifdef CONFIG_CHECK_CACHE_COHERENCY
>
^ permalink raw reply
* Re: [RFC PATCH 09/10] powerpc/fsl_booke/kaslr: support nokaslr cmdline parameter
From: Christophe Leroy @ 2019-07-29 11:38 UTC (permalink / raw)
To: Jason Yan, mpe, linuxppc-dev, diana.craciun, benh, paulus,
npiggin, keescook, kernel-hardening
Cc: wangkefeng.wang, linux-kernel, jingxiangfeng, thunder.leizhen,
fanchengyang, yebin10
In-Reply-To: <20190717080621.40424-10-yanaijie@huawei.com>
Le 17/07/2019 à 10:06, Jason Yan a écrit :
> One may want to disable kaslr when boot, so provide a cmdline parameter
> 'nokaslr' to support this.
>
> Signed-off-by: Jason Yan <yanaijie@huawei.com>
> Cc: Diana Craciun <diana.craciun@nxp.com>
> Cc: Michael Ellerman <mpe@ellerman.id.au>
> Cc: Christophe Leroy <christophe.leroy@c-s.fr>
> Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
> Cc: Paul Mackerras <paulus@samba.org>
> Cc: Nicholas Piggin <npiggin@gmail.com>
> Cc: Kees Cook <keescook@chromium.org>
> ---
> arch/powerpc/kernel/kaslr_booke.c | 14 ++++++++++++++
> 1 file changed, 14 insertions(+)
>
> diff --git a/arch/powerpc/kernel/kaslr_booke.c b/arch/powerpc/kernel/kaslr_booke.c
> index 00339c05879f..e65a5d9d2ff1 100644
> --- a/arch/powerpc/kernel/kaslr_booke.c
> +++ b/arch/powerpc/kernel/kaslr_booke.c
> @@ -373,6 +373,18 @@ static unsigned long __init kaslr_choose_location(void *dt_ptr, phys_addr_t size
> return kaslr_offset;
> }
>
> +static inline __init bool kaslr_disabled(void)
> +{
> + char *str;
> +
> + str = strstr(early_command_line, "nokaslr");
Why using early_command_line instead of boot_command_line ?
> + if ((str == early_command_line) ||
> + (str > early_command_line && *(str - 1) == ' '))
Is that stuff really needed ?
Why not just:
return strstr(early_command_line, "nokaslr") != NULL;
> + return true;
> +
> + return false;
> +}
> +
> /*
> * To see if we need to relocate the kernel to a random offset
> * void *dt_ptr - address of the device tree
> @@ -388,6 +400,8 @@ notrace void __init kaslr_early_init(void *dt_ptr, phys_addr_t size)
> kernel_sz = (unsigned long)_end - KERNELBASE;
>
> kaslr_get_cmdline(dt_ptr);
> + if (kaslr_disabled())
> + return;
>
> offset = kaslr_choose_location(dt_ptr, size, kernel_sz);
>
>
Christophe
^ permalink raw reply
* Re: [RFC PATCH 07/10] powerpc/fsl_booke/32: randomize the kernel image offset
From: Christophe Leroy @ 2019-07-29 11:33 UTC (permalink / raw)
To: Jason Yan, mpe, linuxppc-dev, diana.craciun, benh, paulus,
npiggin, keescook, kernel-hardening
Cc: wangkefeng.wang, linux-kernel, jingxiangfeng, thunder.leizhen,
fanchengyang, yebin10
In-Reply-To: <20190717080621.40424-8-yanaijie@huawei.com>
Le 17/07/2019 à 10:06, Jason Yan a écrit :
> After we have the basic support of relocate the kernel in some
> appropriate place, we can start to randomize the offset now.
>
> Entropy is derived from the banner and timer, which will change every
> build and boot. This not so much safe so additionally the bootloader may
> pass entropy via the /chosen/kaslr-seed node in device tree.
>
> We will use the first 512M of the low memory to randomize the kernel
> image. The memory will be split in 64M zones. We will use the lower 8
> bit of the entropy to decide the index of the 64M zone. Then we chose a
> 16K aligned offset inside the 64M zone to put the kernel in.
>
> KERNELBASE
>
> |--> 64M <--|
> | |
> +---------------+ +----------------+---------------+
> | |....| |kernel| | |
> +---------------+ +----------------+---------------+
> | |
> |-----> offset <-----|
>
> kimage_vaddr
>
> We also check if we will overlap with some areas like the dtb area, the
> initrd area or the crashkernel area. If we cannot find a proper area,
> kaslr will be disabled and boot from the original kernel.
>
> Signed-off-by: Jason Yan <yanaijie@huawei.com>
> Cc: Diana Craciun <diana.craciun@nxp.com>
> Cc: Michael Ellerman <mpe@ellerman.id.au>
> Cc: Christophe Leroy <christophe.leroy@c-s.fr>
> Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
> Cc: Paul Mackerras <paulus@samba.org>
> Cc: Nicholas Piggin <npiggin@gmail.com>
> Cc: Kees Cook <keescook@chromium.org>
> ---
> arch/powerpc/kernel/kaslr_booke.c | 335 +++++++++++++++++++++++++++++-
> 1 file changed, 333 insertions(+), 2 deletions(-)
>
> diff --git a/arch/powerpc/kernel/kaslr_booke.c b/arch/powerpc/kernel/kaslr_booke.c
> index 72d8e9432048..90357f4bd313 100644
> --- a/arch/powerpc/kernel/kaslr_booke.c
> +++ b/arch/powerpc/kernel/kaslr_booke.c
> @@ -22,6 +22,8 @@
> #include <linux/delay.h>
> #include <linux/highmem.h>
> #include <linux/memblock.h>
> +#include <linux/libfdt.h>
> +#include <linux/crash_core.h>
> #include <asm/pgalloc.h>
> #include <asm/prom.h>
> #include <asm/io.h>
> @@ -33,15 +35,342 @@
> #include <asm/machdep.h>
> #include <asm/setup.h>
> #include <asm/paca.h>
> +#include <asm/kdump.h>
> #include <mm/mmu_decl.h>
> +#include <generated/compile.h>
> +#include <generated/utsrelease.h>
> +
> +#ifdef DEBUG
> +#define DBG(fmt...) printk(KERN_ERR fmt)
> +#else
> +#define DBG(fmt...)
> +#endif
> +
> +struct regions {
> + unsigned long pa_start;
> + unsigned long pa_end;
> + unsigned long kernel_size;
> + unsigned long dtb_start;
> + unsigned long dtb_end;
> + unsigned long initrd_start;
> + unsigned long initrd_end;
> + unsigned long crash_start;
> + unsigned long crash_end;
> + int reserved_mem;
> + int reserved_mem_addr_cells;
> + int reserved_mem_size_cells;
> +};
>
> extern int is_second_reloc;
>
> +/* Simplified build-specific string for starting entropy. */
> +static const char build_str[] = UTS_RELEASE " (" LINUX_COMPILE_BY "@"
> + LINUX_COMPILE_HOST ") (" LINUX_COMPILER ") " UTS_VERSION;
> +static char __initdata early_command_line[COMMAND_LINE_SIZE];
> +
> +static __init void kaslr_get_cmdline(void *fdt)
> +{
> + const char *cmdline = CONFIG_CMDLINE;
> + if (!IS_ENABLED(CONFIG_CMDLINE_FORCE)) {
> + int node;
> + const u8 *prop;
> + node = fdt_path_offset(fdt, "/chosen");
> + if (node < 0)
> + goto out;
> +
> + prop = fdt_getprop(fdt, node, "bootargs", NULL);
> + if (!prop)
> + goto out;
> + cmdline = prop;
> + }
> +out:
> + strscpy(early_command_line, cmdline, COMMAND_LINE_SIZE);
> +}
> +
Can you explain why we need that and can't use the already existing
cmdline stuff ?
Christophe
> +static unsigned long __init rotate_xor(unsigned long hash, const void *area,
> + size_t size)
> +{
> + size_t i;
> + unsigned long *ptr = (unsigned long *)area;
> +
> + for (i = 0; i < size / sizeof(hash); i++) {
> + /* Rotate by odd number of bits and XOR. */
> + hash = (hash << ((sizeof(hash) * 8) - 7)) | (hash >> 7);
> + hash ^= ptr[i];
> + }
> +
> + return hash;
> +}
> +
> +/* Attempt to create a simple but unpredictable starting entropy. */
> +static unsigned long __init get_boot_seed(void *fdt)
> +{
> + unsigned long hash = 0;
> +
> + hash = rotate_xor(hash, build_str, sizeof(build_str));
> + hash = rotate_xor(hash, fdt, fdt_totalsize(fdt));
> +
> + return hash;
> +}
> +
> +static __init u64 get_kaslr_seed(void *fdt)
> +{
> + int node, len;
> + fdt64_t *prop;
> + u64 ret;
> +
> + node = fdt_path_offset(fdt, "/chosen");
> + if (node < 0)
> + return 0;
> +
> + prop = fdt_getprop_w(fdt, node, "kaslr-seed", &len);
> + if (!prop || len != sizeof(u64))
> + return 0;
> +
> + ret = fdt64_to_cpu(*prop);
> + *prop = 0;
> + return ret;
> +}
> +
> +static __init bool regions_overlap(u32 s1, u32 e1, u32 s2, u32 e2)
> +{
> + return e1 >= s2 && e2 >= s1;
> +}
> +
> +static __init bool overlaps_reserved_region(const void *fdt, u32 start,
> + u32 end, struct regions *regions)
> +{
> + int subnode, len, i;
> + u64 base, size;
> +
> + /* check for overlap with /memreserve/ entries */
> + for (i = 0; i < fdt_num_mem_rsv(fdt); i++) {
> + if (fdt_get_mem_rsv(fdt, i, &base, &size) < 0)
> + continue;
> + if (regions_overlap(start, end, base, base + size))
> + return true;
> + }
> +
> + if (regions->reserved_mem < 0)
> + return false;
> +
> + /* check for overlap with static reservations in /reserved-memory */
> + for (subnode = fdt_first_subnode(fdt, regions->reserved_mem);
> + subnode >= 0;
> + subnode = fdt_next_subnode(fdt, subnode)) {
> + const fdt32_t *reg;
> + u64 rsv_end;
> +
> + len = 0;
> + reg = fdt_getprop(fdt, subnode, "reg", &len);
> + while (len >= (regions->reserved_mem_addr_cells +
> + regions->reserved_mem_size_cells)) {
> + base = fdt32_to_cpu(reg[0]);
> + if (regions->reserved_mem_addr_cells == 2)
> + base = (base << 32) | fdt32_to_cpu(reg[1]);
> +
> + reg += regions->reserved_mem_addr_cells;
> + len -= 4 * regions->reserved_mem_addr_cells;
> +
> + size = fdt32_to_cpu(reg[0]);
> + if (regions->reserved_mem_size_cells == 2)
> + size = (size << 32) | fdt32_to_cpu(reg[1]);
> +
> + reg += regions->reserved_mem_size_cells;
> + len -= 4 * regions->reserved_mem_size_cells;
> +
> + if (base >= regions->pa_end)
> + continue;
> +
> + rsv_end = min(base + size, (u64)U32_MAX);
> +
> + if (regions_overlap(start, end, base, rsv_end))
> + return true;
> + }
> + }
> + return false;
> +}
> +
> +static __init bool overlaps_region(const void *fdt, u32 start,
> + u32 end, struct regions *regions)
> +{
> + if (regions_overlap(start, end, regions->dtb_start,
> + regions->dtb_end))
> + return true;
> +
> + if (regions_overlap(start, end, regions->initrd_start,
> + regions->initrd_end))
> + return true;
> +
> + if (regions_overlap(start, end, regions->crash_start,
> + regions->crash_end))
> + return true;
> +
> + return overlaps_reserved_region(fdt, start, end, regions);
> +}
> +
> +static void __init get_crash_kernel(void *fdt, unsigned long size,
> + struct regions *regions)
> +{
> +#ifdef CONFIG_KEXEC_CORE
> + unsigned long long crash_size, crash_base;
> + int ret;
> +
> + ret = parse_crashkernel(early_command_line, size, &crash_size,
> + &crash_base);
> + if (ret != 0 || crash_size == 0)
> + return;
> + if (crash_base == 0)
> + crash_base = KDUMP_KERNELBASE;
> +
> + regions->crash_start = (unsigned long)crash_base;
> + regions->crash_end = (unsigned long)(crash_base + crash_size);
> +
> + DBG("crash_base=0x%llx crash_size=0x%llx\n", crash_base, crash_size);
> +#endif
> +}
> +
> +static void __init get_initrd_range(void *fdt, struct regions *regions)
> +{
> + u64 start, end;
> + int node, len;
> + const __be32 *prop;
> +
> + node = fdt_path_offset(fdt, "/chosen");
> + if (node < 0)
> + return;
> +
> + prop = fdt_getprop(fdt, node, "linux,initrd-start", &len);
> + if (!prop)
> + return;
> + start = of_read_number(prop, len / 4);
> +
> + prop = fdt_getprop(fdt, node, "linux,initrd-end", &len);
> + if (!prop)
> + return;
> + end = of_read_number(prop, len / 4);
> +
> + regions->initrd_start = (unsigned long)start;
> + regions->initrd_end = (unsigned long)end;
> +
> + DBG("initrd_start=0x%llx initrd_end=0x%llx\n", start, end);
> +}
> +
> +static __init unsigned long get_usable_offset(const void *fdt, struct regions *regions,
> + unsigned long start)
> +{
> + unsigned long pa;
> + unsigned long pa_end;
> +
> + for (pa = start; pa > regions->pa_start; pa -= SZ_16K) {
> + pa_end = pa + regions->kernel_size;
> + if (overlaps_region(fdt, pa, pa_end, regions))
> + continue;
> +
> + return pa;
> + }
> + return 0;
> +}
> +
> +static __init void get_cell_sizes(const void *fdt, int node, int *addr_cells,
> + int *size_cells)
> +{
> + const int *prop;
> + int len;
> +
> + /*
> + * Retrieve the #address-cells and #size-cells properties
> + * from the 'node', or use the default if not provided.
> + */
> + *addr_cells = *size_cells = 1;
> +
> + prop = fdt_getprop(fdt, node, "#address-cells", &len);
> + if (len == 4)
> + *addr_cells = fdt32_to_cpu(*prop);
> + prop = fdt_getprop(fdt, node, "#size-cells", &len);
> + if (len == 4)
> + *size_cells = fdt32_to_cpu(*prop);
> +}
> +
> static unsigned long __init kaslr_choose_location(void *dt_ptr, phys_addr_t size,
> unsigned long kernel_sz)
> {
> - /* return a fixed offset of 64M for now */
> - return 0x4000000;
> + unsigned long offset, random;
> + unsigned long ram, linear_sz;
> + unsigned long kaslr_offset;
> + u64 seed;
> + struct regions regions;
> + unsigned long index;
> +
> + random = get_boot_seed(dt_ptr);
> +
> + seed = get_tb() << 32;
> + seed ^= get_tb();
> + random = rotate_xor(random, &seed, sizeof(seed));
> +
> + /*
> + * Retrieve (and wipe) the seed from the FDT
> + */
> + seed = get_kaslr_seed(dt_ptr);
> + if (seed)
> + random = rotate_xor(random, &seed, sizeof(seed));
> +
> + ram = min((phys_addr_t)__max_low_memory, size);
> + ram = map_mem_in_cams(ram, CONFIG_LOWMEM_CAM_NUM, true);
> + linear_sz = min(ram, (unsigned long)SZ_512M);
> +
> + /* If the linear size is smaller than 64M, do not randmize */
> + if (linear_sz < SZ_64M)
> + return 0;
> +
> + memset(®ions, 0, sizeof(regions));
> +
> + /* check for a reserved-memory node and record its cell sizes */
> + regions.reserved_mem = fdt_path_offset(dt_ptr, "/reserved-memory");
> + if (regions.reserved_mem >= 0)
> + get_cell_sizes(dt_ptr, regions.reserved_mem,
> + ®ions.reserved_mem_addr_cells,
> + ®ions.reserved_mem_size_cells);
> +
> + regions.pa_start = 0;
> + regions.pa_end = linear_sz;
> + regions.dtb_start = __pa(dt_ptr);
> + regions.dtb_end = __pa(dt_ptr) + fdt_totalsize(dt_ptr);
> + regions.kernel_size = kernel_sz;
> +
> + get_initrd_range(dt_ptr, ®ions);
> + get_crash_kernel(dt_ptr, ram, ®ions);
> +
> + /*
> + * Decide which 64M we want to start
> + * Only use the low 8 bits of the random seed
> + */
> + index = random & 0xFF;
> + index %= linear_sz / SZ_64M;
> +
> + /* Decide offset inside 64M */
> + if (index == 0) {
> + offset = random % (SZ_64M - round_up(kernel_sz, SZ_16K) * 2);
> + offset += round_up(kernel_sz, SZ_16K);
> + offset = round_up(offset, SZ_16K);
> + } else {
> + offset = random % (SZ_64M - kernel_sz);
> + offset = round_down(offset, SZ_16K);
> + }
> +
> + while (index >= 0) {
> + offset = offset + index * SZ_64M;
> + kaslr_offset = get_usable_offset(dt_ptr, ®ions, offset);
> + if (kaslr_offset)
> + break;
> + index--;
> + }
> +
> + /* Did not find any usable region? Give up randomize */
> + if (index < 0)
> + kaslr_offset = 0;
> +
> + return kaslr_offset;
> }
>
> /*
> @@ -58,6 +387,8 @@ notrace void __init kaslr_early_init(void *dt_ptr, phys_addr_t size)
>
> kernel_sz = (unsigned long)_end - KERNELBASE;
>
> + kaslr_get_cmdline(dt_ptr);
> +
> offset = kaslr_choose_location(dt_ptr, size, kernel_sz);
>
> if (offset == 0)
>
^ permalink raw reply
* Re: [RFC PATCH 08/10] powerpc/fsl_booke/kaslr: clear the original kernel if randomized
From: Christophe Leroy @ 2019-07-29 11:19 UTC (permalink / raw)
To: Jason Yan, mpe, linuxppc-dev, diana.craciun, benh, paulus,
npiggin, keescook, kernel-hardening
Cc: wangkefeng.wang, linux-kernel, jingxiangfeng, thunder.leizhen,
fanchengyang, yebin10
In-Reply-To: <20190717080621.40424-9-yanaijie@huawei.com>
Le 17/07/2019 à 10:06, Jason Yan a écrit :
> The original kernel still exists in the memory, clear it now.
>
> Signed-off-by: Jason Yan <yanaijie@huawei.com>
> Cc: Diana Craciun <diana.craciun@nxp.com>
> Cc: Michael Ellerman <mpe@ellerman.id.au>
> Cc: Christophe Leroy <christophe.leroy@c-s.fr>
> Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
> Cc: Paul Mackerras <paulus@samba.org>
> Cc: Nicholas Piggin <npiggin@gmail.com>
> Cc: Kees Cook <keescook@chromium.org>
> ---
> arch/powerpc/kernel/kaslr_booke.c | 11 +++++++++++
> arch/powerpc/mm/mmu_decl.h | 2 ++
> arch/powerpc/mm/nohash/fsl_booke.c | 1 +
> 3 files changed, 14 insertions(+)
>
> diff --git a/arch/powerpc/kernel/kaslr_booke.c b/arch/powerpc/kernel/kaslr_booke.c
> index 90357f4bd313..00339c05879f 100644
> --- a/arch/powerpc/kernel/kaslr_booke.c
> +++ b/arch/powerpc/kernel/kaslr_booke.c
> @@ -412,3 +412,14 @@ notrace void __init kaslr_early_init(void *dt_ptr, phys_addr_t size)
>
> reloc_kernel_entry(dt_ptr, kimage_vaddr);
> }
> +
> +void __init kaslr_second_init(void)
> +{
> + /* If randomized, clear the original kernel */
> + if (kimage_vaddr != KERNELBASE) {
> + unsigned long kernel_sz;
> +
> + kernel_sz = (unsigned long)_end - kimage_vaddr;
> + memset((void *)KERNELBASE, 0, kernel_sz);
Why are we clearing ? Is that just to tidy up or is it of security
importance ?
If so, maybe memzero_explicit() should be used instead ?
> + }
> +}
> diff --git a/arch/powerpc/mm/mmu_decl.h b/arch/powerpc/mm/mmu_decl.h
> index 754ae1e69f92..9912ee598f9b 100644
> --- a/arch/powerpc/mm/mmu_decl.h
> +++ b/arch/powerpc/mm/mmu_decl.h
> @@ -150,8 +150,10 @@ extern void loadcam_multi(int first_idx, int num, int tmp_idx);
>
> #ifdef CONFIG_RANDOMIZE_BASE
> extern void kaslr_early_init(void *dt_ptr, phys_addr_t size);
> +extern void kaslr_second_init(void);
No new 'extern' please.
> #else
> static inline void kaslr_early_init(void *dt_ptr, phys_addr_t size) {}
> +static inline void kaslr_second_init(void) {}
> #endif
>
> struct tlbcam {
> diff --git a/arch/powerpc/mm/nohash/fsl_booke.c b/arch/powerpc/mm/nohash/fsl_booke.c
> index 8d25a8dc965f..fa5a87f5c08e 100644
> --- a/arch/powerpc/mm/nohash/fsl_booke.c
> +++ b/arch/powerpc/mm/nohash/fsl_booke.c
> @@ -269,6 +269,7 @@ notrace void __init relocate_init(u64 dt_ptr, phys_addr_t start)
> kernstart_addr = start;
> if (is_second_reloc) {
> virt_phys_offset = PAGE_OFFSET - memstart_addr;
> + kaslr_second_init();
> return;
> }
>
>
Christophe
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox