mirror of https://gitee.com/openkylin/linux.git
Merge branch 'fixes' into next
Merge our fixes branch from the 4.15 cycle. Unusually the fixes branch saw some significant features merged, notably the RFI flush patches, so we want the code in next to be tested against that, to avoid any surprises when the two are merged. There's also some other work on the panic handling that was reverted in fixes and we now want to do properly in next, which would conflict. And we also fix a few other minor merge conflicts.
This commit is contained in:
commit
ebf0b6a8b1
|
@ -168,6 +168,7 @@ config PPC
|
|||
select GENERIC_CLOCKEVENTS_BROADCAST if SMP
|
||||
select GENERIC_CMOS_UPDATE
|
||||
select GENERIC_CPU_AUTOPROBE
|
||||
select GENERIC_CPU_VULNERABILITIES if PPC_BOOK3S_64
|
||||
select GENERIC_IRQ_SHOW
|
||||
select GENERIC_IRQ_SHOW_LEVEL
|
||||
select GENERIC_SMP_IDLE_THREAD
|
||||
|
|
|
@ -209,5 +209,11 @@ exc_##label##_book3e:
|
|||
ori r3,r3,vector_offset@l; \
|
||||
mtspr SPRN_IVOR##vector_number,r3;
|
||||
|
||||
#define RFI_TO_KERNEL \
|
||||
rfi
|
||||
|
||||
#define RFI_TO_USER \
|
||||
rfi
|
||||
|
||||
#endif /* _ASM_POWERPC_EXCEPTION_64E_H */
|
||||
|
||||
|
|
|
@ -74,6 +74,59 @@
|
|||
*/
|
||||
#define EX_R3 EX_DAR
|
||||
|
||||
/*
|
||||
* Macros for annotating the expected destination of (h)rfid
|
||||
*
|
||||
* The nop instructions allow us to insert one or more instructions to flush the
|
||||
* L1-D cache when returning to userspace or a guest.
|
||||
*/
|
||||
#define RFI_FLUSH_SLOT \
|
||||
RFI_FLUSH_FIXUP_SECTION; \
|
||||
nop; \
|
||||
nop; \
|
||||
nop
|
||||
|
||||
#define RFI_TO_KERNEL \
|
||||
rfid
|
||||
|
||||
#define RFI_TO_USER \
|
||||
RFI_FLUSH_SLOT; \
|
||||
rfid; \
|
||||
b rfi_flush_fallback
|
||||
|
||||
#define RFI_TO_USER_OR_KERNEL \
|
||||
RFI_FLUSH_SLOT; \
|
||||
rfid; \
|
||||
b rfi_flush_fallback
|
||||
|
||||
#define RFI_TO_GUEST \
|
||||
RFI_FLUSH_SLOT; \
|
||||
rfid; \
|
||||
b rfi_flush_fallback
|
||||
|
||||
#define HRFI_TO_KERNEL \
|
||||
hrfid
|
||||
|
||||
#define HRFI_TO_USER \
|
||||
RFI_FLUSH_SLOT; \
|
||||
hrfid; \
|
||||
b hrfi_flush_fallback
|
||||
|
||||
#define HRFI_TO_USER_OR_KERNEL \
|
||||
RFI_FLUSH_SLOT; \
|
||||
hrfid; \
|
||||
b hrfi_flush_fallback
|
||||
|
||||
#define HRFI_TO_GUEST \
|
||||
RFI_FLUSH_SLOT; \
|
||||
hrfid; \
|
||||
b hrfi_flush_fallback
|
||||
|
||||
#define HRFI_TO_UNKNOWN \
|
||||
RFI_FLUSH_SLOT; \
|
||||
hrfid; \
|
||||
b hrfi_flush_fallback
|
||||
|
||||
#ifdef CONFIG_RELOCATABLE
|
||||
#define __EXCEPTION_RELON_PROLOG_PSERIES_1(label, h) \
|
||||
mfspr r11,SPRN_##h##SRR0; /* save SRR0 */ \
|
||||
|
@ -240,7 +293,7 @@ END_FTR_SECTION_NESTED(ftr,ftr,943)
|
|||
mtspr SPRN_##h##SRR0,r12; \
|
||||
mfspr r12,SPRN_##h##SRR1; /* and SRR1 */ \
|
||||
mtspr SPRN_##h##SRR1,r10; \
|
||||
h##rfid; \
|
||||
h##RFI_TO_KERNEL; \
|
||||
b . /* prevent speculative execution */
|
||||
#define EXCEPTION_PROLOG_PSERIES_1(label, h) \
|
||||
__EXCEPTION_PROLOG_PSERIES_1(label, h)
|
||||
|
@ -254,7 +307,7 @@ END_FTR_SECTION_NESTED(ftr,ftr,943)
|
|||
mtspr SPRN_##h##SRR0,r12; \
|
||||
mfspr r12,SPRN_##h##SRR1; /* and SRR1 */ \
|
||||
mtspr SPRN_##h##SRR1,r10; \
|
||||
h##rfid; \
|
||||
h##RFI_TO_KERNEL; \
|
||||
b . /* prevent speculative execution */
|
||||
|
||||
#define EXCEPTION_PROLOG_PSERIES_1_NORI(label, h) \
|
||||
|
|
|
@ -187,7 +187,20 @@ label##3: \
|
|||
FTR_ENTRY_OFFSET label##1b-label##3b; \
|
||||
.popsection;
|
||||
|
||||
#define RFI_FLUSH_FIXUP_SECTION \
|
||||
951: \
|
||||
.pushsection __rfi_flush_fixup,"a"; \
|
||||
.align 2; \
|
||||
952: \
|
||||
FTR_ENTRY_OFFSET 951b-952b; \
|
||||
.popsection;
|
||||
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
#include <linux/types.h>
|
||||
|
||||
extern long __start___rfi_flush_fixup, __stop___rfi_flush_fixup;
|
||||
|
||||
void apply_feature_fixups(void);
|
||||
void setup_feature_keys(void);
|
||||
#endif
|
||||
|
|
|
@ -353,6 +353,7 @@
|
|||
#define PROC_TABLE_GTSE 0x01
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
#include <linux/types.h>
|
||||
|
||||
/**
|
||||
* plpar_hcall_norets: - Make a pseries hypervisor call with no return arguments
|
||||
|
|
|
@ -76,6 +76,7 @@ struct machdep_calls {
|
|||
|
||||
void __noreturn (*restart)(char *cmd);
|
||||
void __noreturn (*halt)(void);
|
||||
void (*panic)(char *str);
|
||||
void (*cpu_die)(void);
|
||||
|
||||
long (*time_init)(void); /* Optional, may be NULL */
|
||||
|
|
|
@ -232,6 +232,16 @@ struct paca_struct {
|
|||
struct sibling_subcore_state *sibling_subcore_state;
|
||||
#endif
|
||||
#endif
|
||||
#ifdef CONFIG_PPC_BOOK3S_64
|
||||
/*
|
||||
* rfi fallback flush must be in its own cacheline to prevent
|
||||
* other paca data leaking into the L1d
|
||||
*/
|
||||
u64 exrfi[EX_SIZE] __aligned(0x80);
|
||||
void *rfi_flush_fallback_area;
|
||||
u64 l1d_flush_congruence;
|
||||
u64 l1d_flush_sets;
|
||||
#endif
|
||||
};
|
||||
|
||||
extern void copy_mm_to_paca(struct mm_struct *mm);
|
||||
|
|
|
@ -24,6 +24,7 @@ extern void reloc_got2(unsigned long);
|
|||
|
||||
void check_for_initrd(void);
|
||||
void initmem_init(void);
|
||||
void setup_panic(void);
|
||||
#define ARCH_PANIC_TIMEOUT 180
|
||||
|
||||
#ifdef CONFIG_PPC_PSERIES
|
||||
|
@ -38,6 +39,19 @@ static inline void pseries_big_endian_exceptions(void) {}
|
|||
static inline void pseries_little_endian_exceptions(void) {}
|
||||
#endif /* CONFIG_PPC_PSERIES */
|
||||
|
||||
void rfi_flush_enable(bool enable);
|
||||
|
||||
/* These are bit flags */
|
||||
enum l1d_flush_type {
|
||||
L1D_FLUSH_NONE = 0x1,
|
||||
L1D_FLUSH_FALLBACK = 0x2,
|
||||
L1D_FLUSH_ORI = 0x4,
|
||||
L1D_FLUSH_MTTRIG = 0x8,
|
||||
};
|
||||
|
||||
void __init setup_rfi_flush(enum l1d_flush_type, bool enable);
|
||||
void do_rfi_flush_fixups(enum l1d_flush_type types);
|
||||
|
||||
#endif /* !__ASSEMBLY__ */
|
||||
|
||||
#endif /* _ASM_POWERPC_SETUP_H */
|
||||
|
|
|
@ -237,6 +237,11 @@ int main(void)
|
|||
OFFSET(PACA_NMI_EMERG_SP, paca_struct, nmi_emergency_sp);
|
||||
OFFSET(PACA_IN_MCE, paca_struct, in_mce);
|
||||
OFFSET(PACA_IN_NMI, paca_struct, in_nmi);
|
||||
OFFSET(PACA_RFI_FLUSH_FALLBACK_AREA, paca_struct, rfi_flush_fallback_area);
|
||||
OFFSET(PACA_EXRFI, paca_struct, exrfi);
|
||||
OFFSET(PACA_L1D_FLUSH_CONGRUENCE, paca_struct, l1d_flush_congruence);
|
||||
OFFSET(PACA_L1D_FLUSH_SETS, paca_struct, l1d_flush_sets);
|
||||
|
||||
#endif
|
||||
OFFSET(PACAHWCPUID, paca_struct, hw_cpu_id);
|
||||
OFFSET(PACAKEXECSTATE, paca_struct, kexec_state);
|
||||
|
|
|
@ -98,6 +98,7 @@ _GLOBAL(__setup_cpu_power9)
|
|||
li r0,0
|
||||
mtspr SPRN_PSSCR,r0
|
||||
mtspr SPRN_LPID,r0
|
||||
mtspr SPRN_PID,r0
|
||||
mfspr r3,SPRN_LPCR
|
||||
LOAD_REG_IMMEDIATE(r4, LPCR_PECEDH | LPCR_PECE_HVEE | LPCR_HVICE | LPCR_HEIC)
|
||||
or r3, r3, r4
|
||||
|
@ -121,6 +122,7 @@ _GLOBAL(__restore_cpu_power9)
|
|||
li r0,0
|
||||
mtspr SPRN_PSSCR,r0
|
||||
mtspr SPRN_LPID,r0
|
||||
mtspr SPRN_PID,r0
|
||||
mfspr r3,SPRN_LPCR
|
||||
LOAD_REG_IMMEDIATE(r4, LPCR_PECEDH | LPCR_PECE_HVEE | LPCR_HVICE | LPCR_HEIC)
|
||||
or r3, r3, r4
|
||||
|
|
|
@ -37,6 +37,11 @@
|
|||
#include <asm/tm.h>
|
||||
#include <asm/ppc-opcode.h>
|
||||
#include <asm/export.h>
|
||||
#ifdef CONFIG_PPC_BOOK3S
|
||||
#include <asm/exception-64s.h>
|
||||
#else
|
||||
#include <asm/exception-64e.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
* System calls.
|
||||
|
@ -261,13 +266,23 @@ BEGIN_FTR_SECTION
|
|||
END_FTR_SECTION_IFSET(CPU_FTR_HAS_PPR)
|
||||
|
||||
ld r13,GPR13(r1) /* only restore r13 if returning to usermode */
|
||||
ld r2,GPR2(r1)
|
||||
ld r1,GPR1(r1)
|
||||
mtlr r4
|
||||
mtcr r5
|
||||
mtspr SPRN_SRR0,r7
|
||||
mtspr SPRN_SRR1,r8
|
||||
RFI_TO_USER
|
||||
b . /* prevent speculative execution */
|
||||
|
||||
/* exit to kernel */
|
||||
1: ld r2,GPR2(r1)
|
||||
ld r1,GPR1(r1)
|
||||
mtlr r4
|
||||
mtcr r5
|
||||
mtspr SPRN_SRR0,r7
|
||||
mtspr SPRN_SRR1,r8
|
||||
RFI
|
||||
RFI_TO_KERNEL
|
||||
b . /* prevent speculative execution */
|
||||
|
||||
.Lsyscall_error:
|
||||
|
@ -396,8 +411,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_HAS_PPR)
|
|||
mtmsrd r10, 1
|
||||
mtspr SPRN_SRR0, r11
|
||||
mtspr SPRN_SRR1, r12
|
||||
|
||||
rfid
|
||||
RFI_TO_USER
|
||||
b . /* prevent speculative execution */
|
||||
#endif
|
||||
_ASM_NOKPROBE_SYMBOL(system_call_common);
|
||||
|
@ -877,7 +891,7 @@ BEGIN_FTR_SECTION
|
|||
END_FTR_SECTION_IFSET(CPU_FTR_HAS_PPR)
|
||||
ACCOUNT_CPU_USER_EXIT(r13, r2, r4)
|
||||
REST_GPR(13, r1)
|
||||
1:
|
||||
|
||||
mtspr SPRN_SRR1,r3
|
||||
|
||||
ld r2,_CCR(r1)
|
||||
|
@ -890,8 +904,22 @@ END_FTR_SECTION_IFSET(CPU_FTR_HAS_PPR)
|
|||
ld r3,GPR3(r1)
|
||||
ld r4,GPR4(r1)
|
||||
ld r1,GPR1(r1)
|
||||
RFI_TO_USER
|
||||
b . /* prevent speculative execution */
|
||||
|
||||
rfid
|
||||
1: mtspr SPRN_SRR1,r3
|
||||
|
||||
ld r2,_CCR(r1)
|
||||
mtcrf 0xFF,r2
|
||||
ld r2,_NIP(r1)
|
||||
mtspr SPRN_SRR0,r2
|
||||
|
||||
ld r0,GPR0(r1)
|
||||
ld r2,GPR2(r1)
|
||||
ld r3,GPR3(r1)
|
||||
ld r4,GPR4(r1)
|
||||
ld r1,GPR1(r1)
|
||||
RFI_TO_KERNEL
|
||||
b . /* prevent speculative execution */
|
||||
|
||||
#endif /* CONFIG_PPC_BOOK3E */
|
||||
|
@ -1081,7 +1109,7 @@ __enter_rtas:
|
|||
|
||||
mtspr SPRN_SRR0,r5
|
||||
mtspr SPRN_SRR1,r6
|
||||
rfid
|
||||
RFI_TO_KERNEL
|
||||
b . /* prevent speculative execution */
|
||||
|
||||
rtas_return_loc:
|
||||
|
@ -1111,7 +1139,7 @@ rtas_return_loc:
|
|||
|
||||
mtspr SPRN_SRR0,r3
|
||||
mtspr SPRN_SRR1,r4
|
||||
rfid
|
||||
RFI_TO_KERNEL
|
||||
b . /* prevent speculative execution */
|
||||
_ASM_NOKPROBE_SYMBOL(__enter_rtas)
|
||||
_ASM_NOKPROBE_SYMBOL(rtas_return_loc)
|
||||
|
@ -1184,7 +1212,7 @@ _GLOBAL(enter_prom)
|
|||
LOAD_REG_IMMEDIATE(r12, MSR_SF | MSR_ISF | MSR_LE)
|
||||
andc r11,r11,r12
|
||||
mtsrr1 r11
|
||||
rfid
|
||||
RFI_TO_KERNEL
|
||||
#endif /* CONFIG_PPC_BOOK3E */
|
||||
|
||||
1: /* Return from OF */
|
||||
|
|
|
@ -256,7 +256,7 @@ BEGIN_FTR_SECTION
|
|||
LOAD_HANDLER(r12, machine_check_handle_early)
|
||||
1: mtspr SPRN_SRR0,r12
|
||||
mtspr SPRN_SRR1,r11
|
||||
rfid
|
||||
RFI_TO_KERNEL
|
||||
b . /* prevent speculative execution */
|
||||
2:
|
||||
/* Stack overflow. Stay on emergency stack and panic.
|
||||
|
@ -445,7 +445,7 @@ EXC_COMMON_BEGIN(machine_check_handle_early)
|
|||
li r3,MSR_ME
|
||||
andc r10,r10,r3 /* Turn off MSR_ME */
|
||||
mtspr SPRN_SRR1,r10
|
||||
rfid
|
||||
RFI_TO_KERNEL
|
||||
b .
|
||||
2:
|
||||
/*
|
||||
|
@ -463,7 +463,7 @@ EXC_COMMON_BEGIN(machine_check_handle_early)
|
|||
*/
|
||||
bl machine_check_queue_event
|
||||
MACHINE_CHECK_HANDLER_WINDUP
|
||||
rfid
|
||||
RFI_TO_USER_OR_KERNEL
|
||||
9:
|
||||
/* Deliver the machine check to host kernel in V mode. */
|
||||
MACHINE_CHECK_HANDLER_WINDUP
|
||||
|
@ -598,6 +598,9 @@ EXC_COMMON_BEGIN(slb_miss_common)
|
|||
stw r9,PACA_EXSLB+EX_CCR(r13) /* save CR in exc. frame */
|
||||
std r10,PACA_EXSLB+EX_LR(r13) /* save LR */
|
||||
|
||||
andi. r9,r11,MSR_PR // Check for exception from userspace
|
||||
cmpdi cr4,r9,MSR_PR // And save the result in CR4 for later
|
||||
|
||||
/*
|
||||
* Test MSR_RI before calling slb_allocate_realmode, because the
|
||||
* MSR in r11 gets clobbered. However we still want to allocate
|
||||
|
@ -624,9 +627,12 @@ END_MMU_FTR_SECTION_IFCLR(MMU_FTR_TYPE_RADIX)
|
|||
|
||||
/* All done -- return from exception. */
|
||||
|
||||
bne cr4,1f /* returning to kernel */
|
||||
|
||||
.machine push
|
||||
.machine "power4"
|
||||
mtcrf 0x80,r9
|
||||
mtcrf 0x08,r9 /* MSR[PR] indication is in cr4 */
|
||||
mtcrf 0x04,r9 /* MSR[RI] indication is in cr5 */
|
||||
mtcrf 0x02,r9 /* I/D indication is in cr6 */
|
||||
mtcrf 0x01,r9 /* slb_allocate uses cr0 and cr7 */
|
||||
|
@ -640,8 +646,29 @@ END_MMU_FTR_SECTION_IFCLR(MMU_FTR_TYPE_RADIX)
|
|||
ld r11,PACA_EXSLB+EX_R11(r13)
|
||||
ld r12,PACA_EXSLB+EX_R12(r13)
|
||||
ld r13,PACA_EXSLB+EX_R13(r13)
|
||||
rfid
|
||||
RFI_TO_USER
|
||||
b . /* prevent speculative execution */
|
||||
1:
|
||||
.machine push
|
||||
.machine "power4"
|
||||
mtcrf 0x80,r9
|
||||
mtcrf 0x08,r9 /* MSR[PR] indication is in cr4 */
|
||||
mtcrf 0x04,r9 /* MSR[RI] indication is in cr5 */
|
||||
mtcrf 0x02,r9 /* I/D indication is in cr6 */
|
||||
mtcrf 0x01,r9 /* slb_allocate uses cr0 and cr7 */
|
||||
.machine pop
|
||||
|
||||
RESTORE_CTR(r9, PACA_EXSLB)
|
||||
RESTORE_PPR_PACA(PACA_EXSLB, r9)
|
||||
mr r3,r12
|
||||
ld r9,PACA_EXSLB+EX_R9(r13)
|
||||
ld r10,PACA_EXSLB+EX_R10(r13)
|
||||
ld r11,PACA_EXSLB+EX_R11(r13)
|
||||
ld r12,PACA_EXSLB+EX_R12(r13)
|
||||
ld r13,PACA_EXSLB+EX_R13(r13)
|
||||
RFI_TO_KERNEL
|
||||
b . /* prevent speculative execution */
|
||||
|
||||
|
||||
2: std r3,PACA_EXSLB+EX_DAR(r13)
|
||||
mr r3,r12
|
||||
|
@ -651,7 +678,7 @@ END_MMU_FTR_SECTION_IFCLR(MMU_FTR_TYPE_RADIX)
|
|||
mtspr SPRN_SRR0,r10
|
||||
ld r10,PACAKMSR(r13)
|
||||
mtspr SPRN_SRR1,r10
|
||||
rfid
|
||||
RFI_TO_KERNEL
|
||||
b .
|
||||
|
||||
8: std r3,PACA_EXSLB+EX_DAR(r13)
|
||||
|
@ -662,7 +689,7 @@ END_MMU_FTR_SECTION_IFCLR(MMU_FTR_TYPE_RADIX)
|
|||
mtspr SPRN_SRR0,r10
|
||||
ld r10,PACAKMSR(r13)
|
||||
mtspr SPRN_SRR1,r10
|
||||
rfid
|
||||
RFI_TO_KERNEL
|
||||
b .
|
||||
|
||||
EXC_COMMON_BEGIN(unrecov_slb)
|
||||
|
@ -907,7 +934,7 @@ EXC_COMMON(trap_0b_common, 0xb00, unknown_exception)
|
|||
mtspr SPRN_SRR0,r10 ; \
|
||||
ld r10,PACAKMSR(r13) ; \
|
||||
mtspr SPRN_SRR1,r10 ; \
|
||||
rfid ; \
|
||||
RFI_TO_KERNEL ; \
|
||||
b . ; /* prevent speculative execution */
|
||||
|
||||
#ifdef CONFIG_PPC_FAST_ENDIAN_SWITCH
|
||||
|
@ -923,7 +950,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_REAL_LE) \
|
|||
xori r12,r12,MSR_LE ; \
|
||||
mtspr SPRN_SRR1,r12 ; \
|
||||
mr r13,r9 ; \
|
||||
rfid ; /* return to userspace */ \
|
||||
RFI_TO_USER ; /* return to userspace */ \
|
||||
b . ; /* prevent speculative execution */
|
||||
#else
|
||||
#define SYSCALL_FASTENDIAN_TEST
|
||||
|
@ -1069,7 +1096,7 @@ TRAMP_REAL_BEGIN(hmi_exception_early)
|
|||
mtcr r11
|
||||
REST_GPR(11, r1)
|
||||
ld r1,GPR1(r1)
|
||||
hrfid
|
||||
HRFI_TO_USER_OR_KERNEL
|
||||
|
||||
1: mtcr r11
|
||||
REST_GPR(11, r1)
|
||||
|
@ -1320,7 +1347,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_CFAR)
|
|||
ld r11,PACA_EXGEN+EX_R11(r13)
|
||||
ld r12,PACA_EXGEN+EX_R12(r13)
|
||||
ld r13,PACA_EXGEN+EX_R13(r13)
|
||||
HRFID
|
||||
HRFI_TO_UNKNOWN
|
||||
b .
|
||||
#endif
|
||||
|
||||
|
@ -1424,10 +1451,94 @@ masked_##_H##interrupt: \
|
|||
ld r10,PACA_EXGEN+EX_R10(r13); \
|
||||
ld r11,PACA_EXGEN+EX_R11(r13); \
|
||||
/* returns to kernel where r13 must be set up, so don't restore it */ \
|
||||
##_H##rfid; \
|
||||
##_H##RFI_TO_KERNEL; \
|
||||
b .; \
|
||||
MASKED_DEC_HANDLER(_H)
|
||||
|
||||
TRAMP_REAL_BEGIN(rfi_flush_fallback)
|
||||
SET_SCRATCH0(r13);
|
||||
GET_PACA(r13);
|
||||
std r9,PACA_EXRFI+EX_R9(r13)
|
||||
std r10,PACA_EXRFI+EX_R10(r13)
|
||||
std r11,PACA_EXRFI+EX_R11(r13)
|
||||
std r12,PACA_EXRFI+EX_R12(r13)
|
||||
std r8,PACA_EXRFI+EX_R13(r13)
|
||||
mfctr r9
|
||||
ld r10,PACA_RFI_FLUSH_FALLBACK_AREA(r13)
|
||||
ld r11,PACA_L1D_FLUSH_SETS(r13)
|
||||
ld r12,PACA_L1D_FLUSH_CONGRUENCE(r13)
|
||||
/*
|
||||
* The load adresses are at staggered offsets within cachelines,
|
||||
* which suits some pipelines better (on others it should not
|
||||
* hurt).
|
||||
*/
|
||||
addi r12,r12,8
|
||||
mtctr r11
|
||||
DCBT_STOP_ALL_STREAM_IDS(r11) /* Stop prefetch streams */
|
||||
|
||||
/* order ld/st prior to dcbt stop all streams with flushing */
|
||||
sync
|
||||
1: li r8,0
|
||||
.rept 8 /* 8-way set associative */
|
||||
ldx r11,r10,r8
|
||||
add r8,r8,r12
|
||||
xor r11,r11,r11 // Ensure r11 is 0 even if fallback area is not
|
||||
add r8,r8,r11 // Add 0, this creates a dependency on the ldx
|
||||
.endr
|
||||
addi r10,r10,128 /* 128 byte cache line */
|
||||
bdnz 1b
|
||||
|
||||
mtctr r9
|
||||
ld r9,PACA_EXRFI+EX_R9(r13)
|
||||
ld r10,PACA_EXRFI+EX_R10(r13)
|
||||
ld r11,PACA_EXRFI+EX_R11(r13)
|
||||
ld r12,PACA_EXRFI+EX_R12(r13)
|
||||
ld r8,PACA_EXRFI+EX_R13(r13)
|
||||
GET_SCRATCH0(r13);
|
||||
rfid
|
||||
|
||||
TRAMP_REAL_BEGIN(hrfi_flush_fallback)
|
||||
SET_SCRATCH0(r13);
|
||||
GET_PACA(r13);
|
||||
std r9,PACA_EXRFI+EX_R9(r13)
|
||||
std r10,PACA_EXRFI+EX_R10(r13)
|
||||
std r11,PACA_EXRFI+EX_R11(r13)
|
||||
std r12,PACA_EXRFI+EX_R12(r13)
|
||||
std r8,PACA_EXRFI+EX_R13(r13)
|
||||
mfctr r9
|
||||
ld r10,PACA_RFI_FLUSH_FALLBACK_AREA(r13)
|
||||
ld r11,PACA_L1D_FLUSH_SETS(r13)
|
||||
ld r12,PACA_L1D_FLUSH_CONGRUENCE(r13)
|
||||
/*
|
||||
* The load adresses are at staggered offsets within cachelines,
|
||||
* which suits some pipelines better (on others it should not
|
||||
* hurt).
|
||||
*/
|
||||
addi r12,r12,8
|
||||
mtctr r11
|
||||
DCBT_STOP_ALL_STREAM_IDS(r11) /* Stop prefetch streams */
|
||||
|
||||
/* order ld/st prior to dcbt stop all streams with flushing */
|
||||
sync
|
||||
1: li r8,0
|
||||
.rept 8 /* 8-way set associative */
|
||||
ldx r11,r10,r8
|
||||
add r8,r8,r12
|
||||
xor r11,r11,r11 // Ensure r11 is 0 even if fallback area is not
|
||||
add r8,r8,r11 // Add 0, this creates a dependency on the ldx
|
||||
.endr
|
||||
addi r10,r10,128 /* 128 byte cache line */
|
||||
bdnz 1b
|
||||
|
||||
mtctr r9
|
||||
ld r9,PACA_EXRFI+EX_R9(r13)
|
||||
ld r10,PACA_EXRFI+EX_R10(r13)
|
||||
ld r11,PACA_EXRFI+EX_R11(r13)
|
||||
ld r12,PACA_EXRFI+EX_R12(r13)
|
||||
ld r8,PACA_EXRFI+EX_R13(r13)
|
||||
GET_SCRATCH0(r13);
|
||||
hrfid
|
||||
|
||||
/*
|
||||
* Real mode exceptions actually use this too, but alternate
|
||||
* instruction code patches (which end up in the common .text area)
|
||||
|
@ -1447,7 +1558,7 @@ TRAMP_REAL_BEGIN(kvmppc_skip_interrupt)
|
|||
addi r13, r13, 4
|
||||
mtspr SPRN_SRR0, r13
|
||||
GET_SCRATCH0(r13)
|
||||
rfid
|
||||
RFI_TO_KERNEL
|
||||
b .
|
||||
|
||||
TRAMP_REAL_BEGIN(kvmppc_skip_Hinterrupt)
|
||||
|
@ -1459,7 +1570,7 @@ TRAMP_REAL_BEGIN(kvmppc_skip_Hinterrupt)
|
|||
addi r13, r13, 4
|
||||
mtspr SPRN_HSRR0, r13
|
||||
GET_SCRATCH0(r13)
|
||||
hrfid
|
||||
HRFI_TO_KERNEL
|
||||
b .
|
||||
#endif
|
||||
|
||||
|
|
|
@ -1462,25 +1462,6 @@ static void fadump_init_files(void)
|
|||
return;
|
||||
}
|
||||
|
||||
static int fadump_panic_event(struct notifier_block *this,
|
||||
unsigned long event, void *ptr)
|
||||
{
|
||||
/*
|
||||
* If firmware-assisted dump has been registered then trigger
|
||||
* firmware-assisted dump and let firmware handle everything
|
||||
* else. If this returns, then fadump was not registered, so
|
||||
* go through the rest of the panic path.
|
||||
*/
|
||||
crash_fadump(NULL, ptr);
|
||||
|
||||
return NOTIFY_DONE;
|
||||
}
|
||||
|
||||
static struct notifier_block fadump_panic_block = {
|
||||
.notifier_call = fadump_panic_event,
|
||||
.priority = INT_MIN /* may not return; must be done last */
|
||||
};
|
||||
|
||||
/*
|
||||
* Prepare for firmware-assisted dump.
|
||||
*/
|
||||
|
@ -1513,9 +1494,6 @@ int __init setup_fadump(void)
|
|||
init_fadump_mem_struct(&fdm, fw_dump.reserve_dump_area_start);
|
||||
fadump_init_files();
|
||||
|
||||
atomic_notifier_chain_register(&panic_notifier_list,
|
||||
&fadump_panic_block);
|
||||
|
||||
return 1;
|
||||
}
|
||||
subsys_initcall(setup_fadump);
|
||||
|
|
|
@ -1409,7 +1409,7 @@ void show_regs(struct pt_regs * regs)
|
|||
|
||||
printk("NIP: "REG" LR: "REG" CTR: "REG"\n",
|
||||
regs->nip, regs->link, regs->ctr);
|
||||
printk("REGS: %p TRAP: %04lx %s (%s)\n",
|
||||
printk("REGS: %px TRAP: %04lx %s (%s)\n",
|
||||
regs, regs->trap, print_tainted(), init_utsname()->release);
|
||||
printk("MSR: "REG" ", regs->msr);
|
||||
print_msr_bits(regs->msr);
|
||||
|
|
|
@ -242,14 +242,6 @@ static int show_cpuinfo(struct seq_file *m, void *v)
|
|||
unsigned short maj;
|
||||
unsigned short min;
|
||||
|
||||
/* We only show online cpus: disable preempt (overzealous, I
|
||||
* knew) to prevent cpu going down. */
|
||||
preempt_disable();
|
||||
if (!cpu_online(cpu_id)) {
|
||||
preempt_enable();
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
pvr = per_cpu(cpu_pvr, cpu_id);
|
||||
#else
|
||||
|
@ -356,8 +348,6 @@ static int show_cpuinfo(struct seq_file *m, void *v)
|
|||
#endif
|
||||
seq_printf(m, "\n");
|
||||
|
||||
preempt_enable();
|
||||
|
||||
/* If this is the last cpu, print the summary */
|
||||
if (cpumask_next(cpu_id, cpu_online_mask) >= nr_cpu_ids)
|
||||
show_cpuinfo_summary(m);
|
||||
|
@ -706,6 +696,30 @@ int check_legacy_ioport(unsigned long base_port)
|
|||
}
|
||||
EXPORT_SYMBOL(check_legacy_ioport);
|
||||
|
||||
static int ppc_panic_event(struct notifier_block *this,
|
||||
unsigned long event, void *ptr)
|
||||
{
|
||||
/*
|
||||
* If firmware-assisted dump has been registered then trigger
|
||||
* firmware-assisted dump and let firmware handle everything else.
|
||||
*/
|
||||
crash_fadump(NULL, ptr);
|
||||
ppc_md.panic(ptr); /* May not return */
|
||||
return NOTIFY_DONE;
|
||||
}
|
||||
|
||||
static struct notifier_block ppc_panic_block = {
|
||||
.notifier_call = ppc_panic_event,
|
||||
.priority = INT_MIN /* may not return; must be done last */
|
||||
};
|
||||
|
||||
void __init setup_panic(void)
|
||||
{
|
||||
if (!ppc_md.panic)
|
||||
return;
|
||||
atomic_notifier_chain_register(&panic_notifier_list, &ppc_panic_block);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_CHECK_CACHE_COHERENCY
|
||||
/*
|
||||
* For platforms that have configurable cache-coherency. This function
|
||||
|
@ -850,6 +864,9 @@ void __init setup_arch(char **cmdline_p)
|
|||
/* Probe the machine type, establish ppc_md. */
|
||||
probe_machine();
|
||||
|
||||
/* Setup panic notifier if requested by the platform. */
|
||||
setup_panic();
|
||||
|
||||
/*
|
||||
* Configure ppc_md.power_save (ppc32 only, 64-bit machines do
|
||||
* it from their respective probe() function.
|
||||
|
|
|
@ -36,6 +36,7 @@
|
|||
#include <linux/memory.h>
|
||||
#include <linux/nmi.h>
|
||||
|
||||
#include <asm/debugfs.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/kdump.h>
|
||||
#include <asm/prom.h>
|
||||
|
@ -808,3 +809,141 @@ static int __init disable_hardlockup_detector(void)
|
|||
return 0;
|
||||
}
|
||||
early_initcall(disable_hardlockup_detector);
|
||||
|
||||
#ifdef CONFIG_PPC_BOOK3S_64
|
||||
static enum l1d_flush_type enabled_flush_types;
|
||||
static void *l1d_flush_fallback_area;
|
||||
static bool no_rfi_flush;
|
||||
bool rfi_flush;
|
||||
|
||||
static int __init handle_no_rfi_flush(char *p)
|
||||
{
|
||||
pr_info("rfi-flush: disabled on command line.");
|
||||
no_rfi_flush = true;
|
||||
return 0;
|
||||
}
|
||||
early_param("no_rfi_flush", handle_no_rfi_flush);
|
||||
|
||||
/*
|
||||
* The RFI flush is not KPTI, but because users will see doco that says to use
|
||||
* nopti we hijack that option here to also disable the RFI flush.
|
||||
*/
|
||||
static int __init handle_no_pti(char *p)
|
||||
{
|
||||
pr_info("rfi-flush: disabling due to 'nopti' on command line.\n");
|
||||
handle_no_rfi_flush(NULL);
|
||||
return 0;
|
||||
}
|
||||
early_param("nopti", handle_no_pti);
|
||||
|
||||
static void do_nothing(void *unused)
|
||||
{
|
||||
/*
|
||||
* We don't need to do the flush explicitly, just enter+exit kernel is
|
||||
* sufficient, the RFI exit handlers will do the right thing.
|
||||
*/
|
||||
}
|
||||
|
||||
void rfi_flush_enable(bool enable)
|
||||
{
|
||||
if (rfi_flush == enable)
|
||||
return;
|
||||
|
||||
if (enable) {
|
||||
do_rfi_flush_fixups(enabled_flush_types);
|
||||
on_each_cpu(do_nothing, NULL, 1);
|
||||
} else
|
||||
do_rfi_flush_fixups(L1D_FLUSH_NONE);
|
||||
|
||||
rfi_flush = enable;
|
||||
}
|
||||
|
||||
static void init_fallback_flush(void)
|
||||
{
|
||||
u64 l1d_size, limit;
|
||||
int cpu;
|
||||
|
||||
l1d_size = ppc64_caches.l1d.size;
|
||||
limit = min(ppc64_bolted_size(), ppc64_rma_size);
|
||||
|
||||
/*
|
||||
* Align to L1d size, and size it at 2x L1d size, to catch possible
|
||||
* hardware prefetch runoff. We don't have a recipe for load patterns to
|
||||
* reliably avoid the prefetcher.
|
||||
*/
|
||||
l1d_flush_fallback_area = __va(memblock_alloc_base(l1d_size * 2, l1d_size, limit));
|
||||
memset(l1d_flush_fallback_area, 0, l1d_size * 2);
|
||||
|
||||
for_each_possible_cpu(cpu) {
|
||||
/*
|
||||
* The fallback flush is currently coded for 8-way
|
||||
* associativity. Different associativity is possible, but it
|
||||
* will be treated as 8-way and may not evict the lines as
|
||||
* effectively.
|
||||
*
|
||||
* 128 byte lines are mandatory.
|
||||
*/
|
||||
u64 c = l1d_size / 8;
|
||||
|
||||
paca[cpu].rfi_flush_fallback_area = l1d_flush_fallback_area;
|
||||
paca[cpu].l1d_flush_congruence = c;
|
||||
paca[cpu].l1d_flush_sets = c / 128;
|
||||
}
|
||||
}
|
||||
|
||||
void __init setup_rfi_flush(enum l1d_flush_type types, bool enable)
|
||||
{
|
||||
if (types & L1D_FLUSH_FALLBACK) {
|
||||
pr_info("rfi-flush: Using fallback displacement flush\n");
|
||||
init_fallback_flush();
|
||||
}
|
||||
|
||||
if (types & L1D_FLUSH_ORI)
|
||||
pr_info("rfi-flush: Using ori type flush\n");
|
||||
|
||||
if (types & L1D_FLUSH_MTTRIG)
|
||||
pr_info("rfi-flush: Using mttrig type flush\n");
|
||||
|
||||
enabled_flush_types = types;
|
||||
|
||||
if (!no_rfi_flush)
|
||||
rfi_flush_enable(enable);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
static int rfi_flush_set(void *data, u64 val)
|
||||
{
|
||||
if (val == 1)
|
||||
rfi_flush_enable(true);
|
||||
else if (val == 0)
|
||||
rfi_flush_enable(false);
|
||||
else
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rfi_flush_get(void *data, u64 *val)
|
||||
{
|
||||
*val = rfi_flush ? 1 : 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_SIMPLE_ATTRIBUTE(fops_rfi_flush, rfi_flush_get, rfi_flush_set, "%llu\n");
|
||||
|
||||
static __init int rfi_flush_debugfs_init(void)
|
||||
{
|
||||
debugfs_create_file("rfi_flush", 0600, powerpc_debugfs_root, NULL, &fops_rfi_flush);
|
||||
return 0;
|
||||
}
|
||||
device_initcall(rfi_flush_debugfs_init);
|
||||
#endif
|
||||
|
||||
ssize_t cpu_show_meltdown(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
{
|
||||
if (rfi_flush)
|
||||
return sprintf(buf, "Mitigation: RFI Flush\n");
|
||||
|
||||
return sprintf(buf, "Vulnerable\n");
|
||||
}
|
||||
#endif /* CONFIG_PPC_BOOK3S_64 */
|
||||
|
|
|
@ -132,6 +132,15 @@ SECTIONS
|
|||
/* Read-only data */
|
||||
RO_DATA(PAGE_SIZE)
|
||||
|
||||
#ifdef CONFIG_PPC64
|
||||
. = ALIGN(8);
|
||||
__rfi_flush_fixup : AT(ADDR(__rfi_flush_fixup) - LOAD_OFFSET) {
|
||||
__start___rfi_flush_fixup = .;
|
||||
*(__rfi_flush_fixup)
|
||||
__stop___rfi_flush_fixup = .;
|
||||
}
|
||||
#endif
|
||||
|
||||
EXCEPTION_TABLE(0)
|
||||
|
||||
NOTES :kernel :notes
|
||||
|
|
|
@ -79,7 +79,7 @@ _GLOBAL_TOC(kvmppc_hv_entry_trampoline)
|
|||
mtmsrd r0,1 /* clear RI in MSR */
|
||||
mtsrr0 r5
|
||||
mtsrr1 r6
|
||||
RFI
|
||||
RFI_TO_KERNEL
|
||||
|
||||
kvmppc_call_hv_entry:
|
||||
BEGIN_FTR_SECTION
|
||||
|
@ -199,7 +199,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S)
|
|||
mtmsrd r6, 1 /* Clear RI in MSR */
|
||||
mtsrr0 r8
|
||||
mtsrr1 r7
|
||||
RFI
|
||||
RFI_TO_KERNEL
|
||||
|
||||
/* Virtual-mode return */
|
||||
.Lvirt_return:
|
||||
|
@ -1167,8 +1167,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_300)
|
|||
|
||||
ld r0, VCPU_GPR(R0)(r4)
|
||||
ld r4, VCPU_GPR(R4)(r4)
|
||||
|
||||
hrfid
|
||||
HRFI_TO_GUEST
|
||||
b .
|
||||
|
||||
secondary_too_late:
|
||||
|
@ -3321,7 +3320,7 @@ END_MMU_FTR_SECTION_IFSET(MMU_FTR_TYPE_RADIX)
|
|||
ld r4, PACAKMSR(r13)
|
||||
mtspr SPRN_SRR0, r3
|
||||
mtspr SPRN_SRR1, r4
|
||||
rfid
|
||||
RFI_TO_KERNEL
|
||||
9: addi r3, r1, STACK_FRAME_OVERHEAD
|
||||
bl kvmppc_bad_interrupt
|
||||
b 9b
|
||||
|
|
|
@ -46,6 +46,9 @@
|
|||
|
||||
#define FUNC(name) name
|
||||
|
||||
#define RFI_TO_KERNEL RFI
|
||||
#define RFI_TO_GUEST RFI
|
||||
|
||||
.macro INTERRUPT_TRAMPOLINE intno
|
||||
|
||||
.global kvmppc_trampoline_\intno
|
||||
|
@ -141,7 +144,7 @@ kvmppc_handler_skip_ins:
|
|||
GET_SCRATCH0(r13)
|
||||
|
||||
/* And get back into the code */
|
||||
RFI
|
||||
RFI_TO_KERNEL
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
@ -164,6 +167,6 @@ _GLOBAL_TOC(kvmppc_entry_trampoline)
|
|||
ori r5, r5, MSR_EE
|
||||
mtsrr0 r7
|
||||
mtsrr1 r6
|
||||
RFI
|
||||
RFI_TO_KERNEL
|
||||
|
||||
#include "book3s_segment.S"
|
||||
|
|
|
@ -156,7 +156,7 @@ no_dcbz32_on:
|
|||
PPC_LL r9, SVCPU_R9(r3)
|
||||
PPC_LL r3, (SVCPU_R3)(r3)
|
||||
|
||||
RFI
|
||||
RFI_TO_GUEST
|
||||
kvmppc_handler_trampoline_enter_end:
|
||||
|
||||
|
||||
|
@ -407,5 +407,5 @@ END_FTR_SECTION_IFSET(CPU_FTR_HVMODE)
|
|||
cmpwi r12, BOOK3S_INTERRUPT_DOORBELL
|
||||
beqa BOOK3S_INTERRUPT_DOORBELL
|
||||
|
||||
RFI
|
||||
RFI_TO_KERNEL
|
||||
kvmppc_handler_trampoline_exit_end:
|
||||
|
|
|
@ -725,7 +725,8 @@ u64 kvmppc_xive_get_icp(struct kvm_vcpu *vcpu)
|
|||
|
||||
/* Return the per-cpu state for state saving/migration */
|
||||
return (u64)xc->cppr << KVM_REG_PPC_ICP_CPPR_SHIFT |
|
||||
(u64)xc->mfrr << KVM_REG_PPC_ICP_MFRR_SHIFT;
|
||||
(u64)xc->mfrr << KVM_REG_PPC_ICP_MFRR_SHIFT |
|
||||
(u64)0xff << KVM_REG_PPC_ICP_PPRI_SHIFT;
|
||||
}
|
||||
|
||||
int kvmppc_xive_set_icp(struct kvm_vcpu *vcpu, u64 icpval)
|
||||
|
@ -1558,7 +1559,7 @@ static int xive_set_source(struct kvmppc_xive *xive, long irq, u64 addr)
|
|||
|
||||
/*
|
||||
* Restore P and Q. If the interrupt was pending, we
|
||||
* force both P and Q, which will trigger a resend.
|
||||
* force Q and !P, which will trigger a resend.
|
||||
*
|
||||
* That means that a guest that had both an interrupt
|
||||
* pending (queued) and Q set will restore with only
|
||||
|
@ -1566,7 +1567,7 @@ static int xive_set_source(struct kvmppc_xive *xive, long irq, u64 addr)
|
|||
* is perfectly fine as coalescing interrupts that haven't
|
||||
* been presented yet is always allowed.
|
||||
*/
|
||||
if (val & KVM_XICS_PRESENTED || val & KVM_XICS_PENDING)
|
||||
if (val & KVM_XICS_PRESENTED && !(val & KVM_XICS_PENDING))
|
||||
state->old_p = true;
|
||||
if (val & KVM_XICS_QUEUED || val & KVM_XICS_PENDING)
|
||||
state->old_q = true;
|
||||
|
|
|
@ -116,6 +116,47 @@ void do_feature_fixups(unsigned long value, void *fixup_start, void *fixup_end)
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PPC_BOOK3S_64
|
||||
void do_rfi_flush_fixups(enum l1d_flush_type types)
|
||||
{
|
||||
unsigned int instrs[3], *dest;
|
||||
long *start, *end;
|
||||
int i;
|
||||
|
||||
start = PTRRELOC(&__start___rfi_flush_fixup),
|
||||
end = PTRRELOC(&__stop___rfi_flush_fixup);
|
||||
|
||||
instrs[0] = 0x60000000; /* nop */
|
||||
instrs[1] = 0x60000000; /* nop */
|
||||
instrs[2] = 0x60000000; /* nop */
|
||||
|
||||
if (types & L1D_FLUSH_FALLBACK)
|
||||
/* b .+16 to fallback flush */
|
||||
instrs[0] = 0x48000010;
|
||||
|
||||
i = 0;
|
||||
if (types & L1D_FLUSH_ORI) {
|
||||
instrs[i++] = 0x63ff0000; /* ori 31,31,0 speculation barrier */
|
||||
instrs[i++] = 0x63de0000; /* ori 30,30,0 L1d flush*/
|
||||
}
|
||||
|
||||
if (types & L1D_FLUSH_MTTRIG)
|
||||
instrs[i++] = 0x7c12dba6; /* mtspr TRIG2,r0 (SPR #882) */
|
||||
|
||||
for (i = 0; start < end; start++, i++) {
|
||||
dest = (void *)start + *start;
|
||||
|
||||
pr_devel("patching dest %lx\n", (unsigned long)dest);
|
||||
|
||||
patch_instruction(dest, instrs[0]);
|
||||
patch_instruction(dest + 1, instrs[1]);
|
||||
patch_instruction(dest + 2, instrs[2]);
|
||||
}
|
||||
|
||||
printk(KERN_DEBUG "rfi-flush: patched %d locations\n", i);
|
||||
}
|
||||
#endif /* CONFIG_PPC_BOOK3S_64 */
|
||||
|
||||
void do_lwsync_fixups(unsigned long value, void *fixup_start, void *fixup_end)
|
||||
{
|
||||
long *start, *end;
|
||||
|
|
|
@ -153,6 +153,11 @@ static int bad_key_fault_exception(struct pt_regs *regs, unsigned long address,
|
|||
return __bad_area_nosemaphore(regs, address, SEGV_PKUERR, pkey);
|
||||
}
|
||||
|
||||
static noinline int bad_access(struct pt_regs *regs, unsigned long address)
|
||||
{
|
||||
return __bad_area(regs, address, SEGV_ACCERR, 0);
|
||||
}
|
||||
|
||||
static int do_sigbus(struct pt_regs *regs, unsigned long address,
|
||||
unsigned int fault)
|
||||
{
|
||||
|
@ -502,7 +507,7 @@ static int __do_page_fault(struct pt_regs *regs, unsigned long address,
|
|||
|
||||
good_area:
|
||||
if (unlikely(access_error(is_write, is_exec, vma)))
|
||||
return bad_area(regs, address);
|
||||
return bad_access(regs, address);
|
||||
|
||||
/*
|
||||
* If for any reason at all we couldn't handle the fault,
|
||||
|
|
|
@ -410,8 +410,12 @@ static __u64 power_pmu_bhrb_to(u64 addr)
|
|||
int ret;
|
||||
__u64 target;
|
||||
|
||||
if (is_kernel_addr(addr))
|
||||
return branch_target((unsigned int *)addr);
|
||||
if (is_kernel_addr(addr)) {
|
||||
if (probe_kernel_read(&instr, (void *)addr, sizeof(instr)))
|
||||
return 0;
|
||||
|
||||
return branch_target(&instr);
|
||||
}
|
||||
|
||||
/* Userspace: need copy instruction here then translate it */
|
||||
pagefault_disable();
|
||||
|
@ -1415,7 +1419,7 @@ static int collect_events(struct perf_event *group, int max_count,
|
|||
int n = 0;
|
||||
struct perf_event *event;
|
||||
|
||||
if (!is_software_event(group)) {
|
||||
if (group->pmu->task_ctx_nr == perf_hw_context) {
|
||||
if (n >= max_count)
|
||||
return -1;
|
||||
ctrs[n] = group;
|
||||
|
@ -1423,7 +1427,7 @@ static int collect_events(struct perf_event *group, int max_count,
|
|||
events[n++] = group->hw.config;
|
||||
}
|
||||
list_for_each_entry(event, &group->sibling_list, group_entry) {
|
||||
if (!is_software_event(event) &&
|
||||
if (event->pmu->task_ctx_nr == perf_hw_context &&
|
||||
event->state != PERF_EVENT_STATE_OFF) {
|
||||
if (n >= max_count)
|
||||
return -1;
|
||||
|
|
|
@ -322,6 +322,19 @@ static int ppc_nest_imc_cpu_offline(unsigned int cpu)
|
|||
if (!cpumask_test_and_clear_cpu(cpu, &nest_imc_cpumask))
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* Check whether nest_imc is registered. We could end up here if the
|
||||
* cpuhotplug callback registration fails. i.e, callback invokes the
|
||||
* offline path for all successfully registered nodes. At this stage,
|
||||
* nest_imc pmu will not be registered and we should return here.
|
||||
*
|
||||
* We return with a zero since this is not an offline failure. And
|
||||
* cpuhp_setup_state() returns the actual failure reason to the caller,
|
||||
* which in turn will call the cleanup routine.
|
||||
*/
|
||||
if (!nest_pmus)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* Now that this cpu is one of the designated,
|
||||
* find a next cpu a) which is online and b) in same chip.
|
||||
|
@ -1179,7 +1192,6 @@ static void imc_common_mem_free(struct imc_pmu *pmu_ptr)
|
|||
kfree(pmu_ptr->attr_groups[IMC_EVENT_ATTR]->attrs);
|
||||
kfree(pmu_ptr->attr_groups[IMC_EVENT_ATTR]);
|
||||
kfree(pmu_ptr);
|
||||
kfree(per_nest_pmu_arr);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1195,6 +1207,7 @@ static void imc_common_cpuhp_mem_free(struct imc_pmu *pmu_ptr)
|
|||
if (nest_pmus == 1) {
|
||||
cpuhp_remove_state(CPUHP_AP_PERF_POWERPC_NEST_IMC_ONLINE);
|
||||
kfree(nest_imc_refc);
|
||||
kfree(per_nest_pmu_arr);
|
||||
}
|
||||
|
||||
if (nest_pmus > 0)
|
||||
|
@ -1330,6 +1343,8 @@ int init_imc_pmu(struct device_node *parent, struct imc_pmu *pmu_ptr, int pmu_id
|
|||
ret = nest_pmu_cpumask_init();
|
||||
if (ret) {
|
||||
mutex_unlock(&nest_init_lock);
|
||||
kfree(nest_imc_refc);
|
||||
kfree(per_nest_pmu_arr);
|
||||
goto err_free;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -37,13 +37,62 @@
|
|||
#include <asm/kexec.h>
|
||||
#include <asm/smp.h>
|
||||
#include <asm/tm.h>
|
||||
#include <asm/setup.h>
|
||||
|
||||
#include "powernv.h"
|
||||
|
||||
static void pnv_setup_rfi_flush(void)
|
||||
{
|
||||
struct device_node *np, *fw_features;
|
||||
enum l1d_flush_type type;
|
||||
int enable;
|
||||
|
||||
/* Default to fallback in case fw-features are not available */
|
||||
type = L1D_FLUSH_FALLBACK;
|
||||
enable = 1;
|
||||
|
||||
np = of_find_node_by_name(NULL, "ibm,opal");
|
||||
fw_features = of_get_child_by_name(np, "fw-features");
|
||||
of_node_put(np);
|
||||
|
||||
if (fw_features) {
|
||||
np = of_get_child_by_name(fw_features, "inst-l1d-flush-trig2");
|
||||
if (np && of_property_read_bool(np, "enabled"))
|
||||
type = L1D_FLUSH_MTTRIG;
|
||||
|
||||
of_node_put(np);
|
||||
|
||||
np = of_get_child_by_name(fw_features, "inst-l1d-flush-ori30,30,0");
|
||||
if (np && of_property_read_bool(np, "enabled"))
|
||||
type = L1D_FLUSH_ORI;
|
||||
|
||||
of_node_put(np);
|
||||
|
||||
/* Enable unless firmware says NOT to */
|
||||
enable = 2;
|
||||
np = of_get_child_by_name(fw_features, "needs-l1d-flush-msr-hv-1-to-0");
|
||||
if (np && of_property_read_bool(np, "disabled"))
|
||||
enable--;
|
||||
|
||||
of_node_put(np);
|
||||
|
||||
np = of_get_child_by_name(fw_features, "needs-l1d-flush-msr-pr-0-to-1");
|
||||
if (np && of_property_read_bool(np, "disabled"))
|
||||
enable--;
|
||||
|
||||
of_node_put(np);
|
||||
of_node_put(fw_features);
|
||||
}
|
||||
|
||||
setup_rfi_flush(type, enable > 0);
|
||||
}
|
||||
|
||||
static void __init pnv_setup_arch(void)
|
||||
{
|
||||
set_arch_panic_timeout(10, ARCH_PANIC_TIMEOUT);
|
||||
|
||||
pnv_setup_rfi_flush();
|
||||
|
||||
/* Initialize SMP */
|
||||
pnv_smp_init();
|
||||
|
||||
|
|
|
@ -104,6 +104,20 @@ static void __noreturn ps3_halt(void)
|
|||
ps3_sys_manager_halt(); /* never returns */
|
||||
}
|
||||
|
||||
static void ps3_panic(char *str)
|
||||
{
|
||||
DBG("%s:%d %s\n", __func__, __LINE__, str);
|
||||
|
||||
smp_send_stop();
|
||||
printk("\n");
|
||||
printk(" System does not reboot automatically.\n");
|
||||
printk(" Please press POWER button.\n");
|
||||
printk("\n");
|
||||
|
||||
while(1)
|
||||
lv1_pause(1);
|
||||
}
|
||||
|
||||
#if defined(CONFIG_FB_PS3) || defined(CONFIG_FB_PS3_MODULE) || \
|
||||
defined(CONFIG_PS3_FLASH) || defined(CONFIG_PS3_FLASH_MODULE)
|
||||
static void __init prealloc(struct ps3_prealloc *p)
|
||||
|
@ -255,6 +269,7 @@ define_machine(ps3) {
|
|||
.probe = ps3_probe,
|
||||
.setup_arch = ps3_setup_arch,
|
||||
.init_IRQ = ps3_init_IRQ,
|
||||
.panic = ps3_panic,
|
||||
.get_boot_time = ps3_get_boot_time,
|
||||
.set_dabr = ps3_set_dabr,
|
||||
.calibrate_decr = ps3_calibrate_decr,
|
||||
|
|
|
@ -574,11 +574,26 @@ static ssize_t dlpar_show(struct class *class, struct class_attribute *attr,
|
|||
|
||||
static CLASS_ATTR_RW(dlpar);
|
||||
|
||||
static int __init pseries_dlpar_init(void)
|
||||
int __init dlpar_workqueue_init(void)
|
||||
{
|
||||
if (pseries_hp_wq)
|
||||
return 0;
|
||||
|
||||
pseries_hp_wq = alloc_workqueue("pseries hotplug workqueue",
|
||||
WQ_UNBOUND, 1);
|
||||
WQ_UNBOUND, 1);
|
||||
|
||||
return pseries_hp_wq ? 0 : -ENOMEM;
|
||||
}
|
||||
|
||||
static int __init dlpar_sysfs_init(void)
|
||||
{
|
||||
int rc;
|
||||
|
||||
rc = dlpar_workqueue_init();
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
return sysfs_create_file(kernel_kobj, &class_attr_dlpar.attr);
|
||||
}
|
||||
machine_device_initcall(pseries, pseries_dlpar_init);
|
||||
machine_device_initcall(pseries, dlpar_sysfs_init);
|
||||
|
||||
|
|
|
@ -98,4 +98,6 @@ static inline unsigned long cmo_get_page_size(void)
|
|||
return CMO_PageSize;
|
||||
}
|
||||
|
||||
int dlpar_workqueue_init(void);
|
||||
|
||||
#endif /* _PSERIES_PSERIES_H */
|
||||
|
|
|
@ -69,7 +69,8 @@ static int __init init_ras_IRQ(void)
|
|||
/* Hotplug Events */
|
||||
np = of_find_node_by_path("/event-sources/hot-plug-events");
|
||||
if (np != NULL) {
|
||||
request_event_sources_irqs(np, ras_hotplug_interrupt,
|
||||
if (dlpar_workqueue_init() == 0)
|
||||
request_event_sources_irqs(np, ras_hotplug_interrupt,
|
||||
"RAS_HOTPLUG");
|
||||
of_node_put(np);
|
||||
}
|
||||
|
|
|
@ -459,6 +459,39 @@ static void __init find_and_init_phbs(void)
|
|||
of_pci_check_probe_only();
|
||||
}
|
||||
|
||||
static void pseries_setup_rfi_flush(void)
|
||||
{
|
||||
struct h_cpu_char_result result;
|
||||
enum l1d_flush_type types;
|
||||
bool enable;
|
||||
long rc;
|
||||
|
||||
/* Enable by default */
|
||||
enable = true;
|
||||
|
||||
rc = plpar_get_cpu_characteristics(&result);
|
||||
if (rc == H_SUCCESS) {
|
||||
types = L1D_FLUSH_NONE;
|
||||
|
||||
if (result.character & H_CPU_CHAR_L1D_FLUSH_TRIG2)
|
||||
types |= L1D_FLUSH_MTTRIG;
|
||||
if (result.character & H_CPU_CHAR_L1D_FLUSH_ORI30)
|
||||
types |= L1D_FLUSH_ORI;
|
||||
|
||||
/* Use fallback if nothing set in hcall */
|
||||
if (types == L1D_FLUSH_NONE)
|
||||
types = L1D_FLUSH_FALLBACK;
|
||||
|
||||
if (!(result.behaviour & H_CPU_BEHAV_L1D_FLUSH_PR))
|
||||
enable = false;
|
||||
} else {
|
||||
/* Default to fallback if case hcall is not available */
|
||||
types = L1D_FLUSH_FALLBACK;
|
||||
}
|
||||
|
||||
setup_rfi_flush(types, enable);
|
||||
}
|
||||
|
||||
static void __init pSeries_setup_arch(void)
|
||||
{
|
||||
set_arch_panic_timeout(10, ARCH_PANIC_TIMEOUT);
|
||||
|
@ -476,6 +509,8 @@ static void __init pSeries_setup_arch(void)
|
|||
|
||||
fwnmi_init();
|
||||
|
||||
pseries_setup_rfi_flush();
|
||||
|
||||
/* By default, only probe PCI (can be overridden by rtas_pci) */
|
||||
pci_add_flags(PCI_PROBE_ONLY);
|
||||
|
||||
|
@ -726,6 +761,7 @@ define_machine(pseries) {
|
|||
.pcibios_fixup = pSeries_final_fixup,
|
||||
.restart = rtas_restart,
|
||||
.halt = rtas_halt,
|
||||
.panic = rtas_os_term,
|
||||
.get_boot_time = rtas_get_boot_time,
|
||||
.get_rtc_time = rtas_get_rtc_time,
|
||||
.set_rtc_time = rtas_set_rtc_time,
|
||||
|
|
|
@ -1590,7 +1590,7 @@ static void print_bug_trap(struct pt_regs *regs)
|
|||
printf("kernel BUG at %s:%u!\n",
|
||||
bug->file, bug->line);
|
||||
#else
|
||||
printf("kernel BUG at %p!\n", (void *)bug->bug_addr);
|
||||
printf("kernel BUG at %px!\n", (void *)bug->bug_addr);
|
||||
#endif
|
||||
#endif /* CONFIG_BUG */
|
||||
}
|
||||
|
@ -2329,7 +2329,7 @@ static void dump_one_paca(int cpu)
|
|||
|
||||
p = &paca[cpu];
|
||||
|
||||
printf("paca for cpu 0x%x @ %p:\n", cpu, p);
|
||||
printf("paca for cpu 0x%x @ %px:\n", cpu, p);
|
||||
|
||||
printf(" %-*s = %s\n", 20, "possible", cpu_possible(cpu) ? "yes" : "no");
|
||||
printf(" %-*s = %s\n", 20, "present", cpu_present(cpu) ? "yes" : "no");
|
||||
|
@ -2344,10 +2344,10 @@ static void dump_one_paca(int cpu)
|
|||
DUMP(p, kernel_toc, "lx");
|
||||
DUMP(p, kernelbase, "lx");
|
||||
DUMP(p, kernel_msr, "lx");
|
||||
DUMP(p, emergency_sp, "p");
|
||||
DUMP(p, emergency_sp, "px");
|
||||
#ifdef CONFIG_PPC_BOOK3S_64
|
||||
DUMP(p, nmi_emergency_sp, "p");
|
||||
DUMP(p, mc_emergency_sp, "p");
|
||||
DUMP(p, nmi_emergency_sp, "px");
|
||||
DUMP(p, mc_emergency_sp, "px");
|
||||
DUMP(p, in_nmi, "x");
|
||||
DUMP(p, in_mce, "x");
|
||||
DUMP(p, hmi_event_available, "x");
|
||||
|
@ -2375,17 +2375,21 @@ static void dump_one_paca(int cpu)
|
|||
DUMP(p, slb_cache_ptr, "x");
|
||||
for (i = 0; i < SLB_CACHE_ENTRIES; i++)
|
||||
printf(" slb_cache[%d]: = 0x%016lx\n", i, p->slb_cache[i]);
|
||||
|
||||
DUMP(p, rfi_flush_fallback_area, "px");
|
||||
DUMP(p, l1d_flush_congruence, "llx");
|
||||
DUMP(p, l1d_flush_sets, "llx");
|
||||
#endif
|
||||
DUMP(p, dscr_default, "llx");
|
||||
#ifdef CONFIG_PPC_BOOK3E
|
||||
DUMP(p, pgd, "p");
|
||||
DUMP(p, kernel_pgd, "p");
|
||||
DUMP(p, tcd_ptr, "p");
|
||||
DUMP(p, mc_kstack, "p");
|
||||
DUMP(p, crit_kstack, "p");
|
||||
DUMP(p, dbg_kstack, "p");
|
||||
DUMP(p, pgd, "px");
|
||||
DUMP(p, kernel_pgd, "px");
|
||||
DUMP(p, tcd_ptr, "px");
|
||||
DUMP(p, mc_kstack, "px");
|
||||
DUMP(p, crit_kstack, "px");
|
||||
DUMP(p, dbg_kstack, "px");
|
||||
#endif
|
||||
DUMP(p, __current, "p");
|
||||
DUMP(p, __current, "px");
|
||||
DUMP(p, kstack, "lx");
|
||||
printf(" kstack_base = 0x%016lx\n", p->kstack & ~(THREAD_SIZE - 1));
|
||||
DUMP(p, stab_rr, "lx");
|
||||
|
@ -2403,7 +2407,7 @@ static void dump_one_paca(int cpu)
|
|||
#endif
|
||||
|
||||
#ifdef CONFIG_PPC_POWERNV
|
||||
DUMP(p, core_idle_state_ptr, "p");
|
||||
DUMP(p, core_idle_state_ptr, "px");
|
||||
DUMP(p, thread_idle_state, "x");
|
||||
DUMP(p, thread_mask, "x");
|
||||
DUMP(p, subcore_sibling_mask, "x");
|
||||
|
@ -2945,7 +2949,7 @@ static void show_task(struct task_struct *tsk)
|
|||
(tsk->exit_state & EXIT_DEAD) ? 'E' :
|
||||
(tsk->state & TASK_INTERRUPTIBLE) ? 'S' : '?';
|
||||
|
||||
printf("%p %016lx %6d %6d %c %2d %s\n", tsk,
|
||||
printf("%px %016lx %6d %6d %c %2d %s\n", tsk,
|
||||
tsk->thread.ksp,
|
||||
tsk->pid, tsk->parent->pid,
|
||||
state, task_thread_info(tsk)->cpu,
|
||||
|
@ -2988,7 +2992,7 @@ static void show_pte(unsigned long addr)
|
|||
|
||||
if (setjmp(bus_error_jmp) != 0) {
|
||||
catch_memory_errors = 0;
|
||||
printf("*** Error dumping pte for task %p\n", tsk);
|
||||
printf("*** Error dumping pte for task %px\n", tsk);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -3074,7 +3078,7 @@ static void show_tasks(void)
|
|||
|
||||
if (setjmp(bus_error_jmp) != 0) {
|
||||
catch_memory_errors = 0;
|
||||
printf("*** Error dumping task %p\n", tsk);
|
||||
printf("*** Error dumping task %px\n", tsk);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue