Message ID | e4ad304a57afeff9e3bd6f1fc57a927c943506b0.1517497017.git.khalid.aziz@oracle.com |
---|---|
State | Superseded |
Delegated to: | David Miller |
Headers | show |
Series | Application Data Integrity feature introduced by SPARC M7 | expand |
On Thu, 2018-02-01 at 11:01 -0700, Khalid Aziz wrote: > diff --git a/arch/sparc/include/asm/pgtable_64.h b/arch/sparc/include/asm/pgtable_64.h [] > @@ -164,6 +164,8 @@ bool kern_addr_valid(unsigned long addr); > #define _PAGE_E_4V _AC(0x0000000000000800,UL) /* side-Effect */ > #define _PAGE_CP_4V _AC(0x0000000000000400,UL) /* Cacheable in P-Cache */ > #define _PAGE_CV_4V _AC(0x0000000000000200,UL) /* Cacheable in V-Cache */ > +/* Bit 9 is used to enable MCD corruption detection instead on M7 */ > +#define _PAGE_MCD_4V _AC(0x0000000000000200,UL) /* Memory Corruption */ trivia: There are some whitespace alignment issues here > diff --git a/arch/sparc/include/asm/ttable.h b/arch/sparc/include/asm/ttable.h [] > @@ -219,6 +219,16 @@ > nop; \ > nop; > > +#define SUN4V_MCD_PRECISE \ > + ldxa [%g0] ASI_SCRATCHPAD, %g2; \ > + ldx [%g2 + HV_FAULT_D_ADDR_OFFSET], %g4; \ > + ldx [%g2 + HV_FAULT_D_CTX_OFFSET], %g5; \ > + ba,pt %xcc, etrap; \ > + rd %pc, %g7; \ > + ba,pt %xcc, sun4v_mcd_detect_precise; \ > + nop; \ > + nop; and here and elsewhere. It would be nicer to make all these use similar indentation. > diff --git a/arch/sparc/kernel/sun4v_mcd.S b/arch/sparc/kernel/sun4v_mcd.S [] > +sun4v_mcd_detect_precise: > + mov %l4, %o1 > + mov %l5, %o2 > + call sun4v_mem_corrupt_detect_precise > + add %sp, PTREGS_OFF, %o0 > + ba,a,pt %xcc, rtrap > + nop etc... -- To unsubscribe from this list: send the line "unsubscribe sparclinux" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
From: Joe Perches <joe@perches.com> Date: Thu, 01 Feb 2018 12:32:02 -0800 >> diff --git a/arch/sparc/include/asm/ttable.h b/arch/sparc/include/asm/ttable.h > [] >> @@ -219,6 +219,16 @@ >> nop; \ >> nop; >> >> +#define SUN4V_MCD_PRECISE \ >> + ldxa [%g0] ASI_SCRATCHPAD, %g2; \ >> + ldx [%g2 + HV_FAULT_D_ADDR_OFFSET], %g4; \ >> + ldx [%g2 + HV_FAULT_D_CTX_OFFSET], %g5; \ >> + ba,pt %xcc, etrap; \ >> + rd %pc, %g7; \ >> + ba,pt %xcc, sun4v_mcd_detect_precise; \ >> + nop; \ >> + nop; > > and here and elsewhere. Joe, this is intentional in Sparc assembler. Branches on sparc have delay slots, and this is annotated by indenting the delay slot instruction one space more than the branch preceeding it. Please make more constructive review comments than whitespace as these patches have been under review for more than half a year. Thank you very much. -- To unsubscribe from this list: send the line "unsubscribe sparclinux" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
> > #define _PAGE_E_4V _AC(0x0000000000000800,UL) /* side-Effect */ > > #define _PAGE_CP_4V _AC(0x0000000000000400,UL) /* Cacheable in P-Cache */ > > #define _PAGE_CV_4V _AC(0x0000000000000200,UL) /* Cacheable in V-Cache */ > > +/* Bit 9 is used to enable MCD corruption detection instead on M7 */ > > +#define _PAGE_MCD_4V _AC(0x0000000000000200,UL) /* Memory Corruption */ > > trivia: > > There are some whitespace alignment issues here Looks like you are fouled by the use of tabs. When you apply the patch it is fine. > > > diff --git a/arch/sparc/include/asm/ttable.h b/arch/sparc/include/asm/ttable.h > [] > > @@ -219,6 +219,16 @@ > > nop; \ > > nop; > > > > +#define SUN4V_MCD_PRECISE \ > > + ldxa [%g0] ASI_SCRATCHPAD, %g2; \ > > + ldx [%g2 + HV_FAULT_D_ADDR_OFFSET], %g4; \ > > + ldx [%g2 + HV_FAULT_D_CTX_OFFSET], %g5; \ > > + ba,pt %xcc, etrap; \ > > + rd %pc, %g7; \ > > + ba,pt %xcc, sun4v_mcd_detect_precise; \ > > + nop; \ > > + nop; > > and here and elsewhere. > > It would be nicer to make all these use > similar indentation. The patch uses the sparc idiom to indent instructions in the delay slot after a branch with one space. So the space before the nop is mandatory and not a bug. Sam -- To unsubscribe from this list: send the line "unsubscribe sparclinux" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On Thu, 2018-02-01 at 15:39 -0500, David Miller wrote: > From: Joe Perches <joe@perches.com> > Date: Thu, 01 Feb 2018 12:32:02 -0800 > > >> diff --git a/arch/sparc/include/asm/ttable.h b/arch/sparc/include/asm/ttable.h > > [] > >> @@ -219,6 +219,16 @@ > >> nop; \ > >> nop; > >> > >> +#define SUN4V_MCD_PRECISE \ > >> + ldxa [%g0] ASI_SCRATCHPAD, %g2; \ > >> + ldx [%g2 + HV_FAULT_D_ADDR_OFFSET], %g4; \ > >> + ldx [%g2 + HV_FAULT_D_CTX_OFFSET], %g5; \ > >> + ba,pt %xcc, etrap; \ > >> + rd %pc, %g7; \ > >> + ba,pt %xcc, sun4v_mcd_detect_precise; \ > >> + nop; \ > >> + nop; > > > > and here and elsewhere. > > Joe, this is intentional in Sparc assembler. > > Branches on sparc have delay slots, and this is annotated by indenting > the delay slot instruction one space more than the branch preceeding > it. OK, that is new to me and seems a sensible convention. btw: There seem to be only a few instances where that convention is not followed in arch/sparc/... (maybe some missing or false positives below) $ git ls-files arch/sparc/ | \ xargs grep-2.5.4 -P -n '^([ \t]+)b\w+,p.*\n\1[^ ]\S' | \ perl -p -e 's/(:\d+:)/\1\n/' arch/sparc/include/asm/tsb.h:168: brz,pn REG1, FAIL_LABEL; \ sethi %uhi(_PAGE_PUD_HUGE), REG2; \ arch/sparc/include/asm/ttable.h:281: ba,pt %xcc, etrap_save; \ wrpr %g1, %cwp; \ arch/sparc/kernel/head_64.S:472: bne,pn %icc, 49f add %g7, 1, %g7 arch/sparc/kernel/head_64.S:474: bne,pt %xcc, 41b add %g1, 1, %g1 arch/sparc/kernel/rtrap_64.S:72: ba,pt %xcc, rtrap_no_irq_enable nop arch/sparc/kernel/rtrap_64.S:161: brz,pt %l3, 1f mov %g6, %l2 arch/sparc/lib/GENmemcpy.S:100: bne,pt %XCC, 1b add %o0, 1, %o0 arch/sparc/lib/M7memcpy.S:896: bgu,pt %xcc, .Lsmallnotalign4 ! loop til 3 or fewer bytes remain EX_ST(STORE(stb, %o3, %o0-1), memcpy_retl_o2_plus_4) arch/sparc/lib/M7memcpy.S:902: bz,pt %xcc, .Lsmallx EX_ST(STORE(stb, %o3, %o0), memcpy_retl_o2_plus_1) ! store one byte arch/sparc/lib/M7memcpy.S:905: bz,pt %xcc, .Lsmallx EX_ST(STORE(stb, %o3, %o0+1), memcpy_retl_o2_plus_1)! store second byte arch/sparc/lib/NG2memcpy.S:299: bne,pt %XCC, 1b add %o0, 1, %o0 arch/sparc/lib/NG4fls.S:23: brz,pn %o0, 1f LZCNT_O0_G2 !lzcnt %o0, %g2 arch/sparc/lib/NGmemcpy.S:216: bne,pt %XCC, 1b add %o0, 1, %o0 arch/sparc/lib/csum_copy.S:103: ba,pt %xcc, 1f LOAD(prefetch, %o0 + 0x140, #n_reads) -- To unsubscribe from this list: send the line "unsubscribe sparclinux" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
diff --git a/arch/sparc/include/asm/hypervisor.h b/arch/sparc/include/asm/hypervisor.h index 89a0c57aed59..83fdcc5e91db 100644 --- a/arch/sparc/include/asm/hypervisor.h +++ b/arch/sparc/include/asm/hypervisor.h @@ -566,6 +566,8 @@ struct hv_fault_status { #define HV_FAULT_TYPE_RESV1 13 #define HV_FAULT_TYPE_UNALIGNED 14 #define HV_FAULT_TYPE_INV_PGSZ 15 +#define HV_FAULT_TYPE_MCD 17 +#define HV_FAULT_TYPE_MCD_DIS 18 /* Values 16 --> -2 are reserved. */ #define HV_FAULT_TYPE_MULTIPLE -1 diff --git a/arch/sparc/include/asm/pgtable_64.h b/arch/sparc/include/asm/pgtable_64.h index 9937c5ff94a9..db5c83532cfd 100644 --- a/arch/sparc/include/asm/pgtable_64.h +++ b/arch/sparc/include/asm/pgtable_64.h @@ -164,6 +164,8 @@ bool kern_addr_valid(unsigned long addr); #define _PAGE_E_4V _AC(0x0000000000000800,UL) /* side-Effect */ #define _PAGE_CP_4V _AC(0x0000000000000400,UL) /* Cacheable in P-Cache */ #define _PAGE_CV_4V _AC(0x0000000000000200,UL) /* Cacheable in V-Cache */ +/* Bit 9 is used to enable MCD corruption detection instead on M7 */ +#define _PAGE_MCD_4V _AC(0x0000000000000200,UL) /* Memory Corruption */ #define _PAGE_P_4V _AC(0x0000000000000100,UL) /* Privileged Page */ #define _PAGE_EXEC_4V _AC(0x0000000000000080,UL) /* Executable Page */ #define _PAGE_W_4V _AC(0x0000000000000040,UL) /* Writable */ diff --git a/arch/sparc/include/asm/ttable.h b/arch/sparc/include/asm/ttable.h index ede2b66cf4a0..8f6469408019 100644 --- a/arch/sparc/include/asm/ttable.h +++ b/arch/sparc/include/asm/ttable.h @@ -219,6 +219,16 @@ nop; \ nop; +#define SUN4V_MCD_PRECISE \ + ldxa [%g0] ASI_SCRATCHPAD, %g2; \ + ldx [%g2 + HV_FAULT_D_ADDR_OFFSET], %g4; \ + ldx [%g2 + HV_FAULT_D_CTX_OFFSET], %g5; \ + ba,pt %xcc, etrap; \ + rd %pc, %g7; \ + ba,pt %xcc, sun4v_mcd_detect_precise; \ + nop; \ + nop; + /* Before touching these macros, you owe it to yourself to go and * see how arch/sparc64/kernel/winfixup.S works... -DaveM * diff --git a/arch/sparc/include/uapi/asm/asi.h b/arch/sparc/include/uapi/asm/asi.h index d371b269571a..fbb30a5b082f 100644 --- a/arch/sparc/include/uapi/asm/asi.h +++ b/arch/sparc/include/uapi/asm/asi.h @@ -145,6 +145,8 @@ * ASIs, "(4V)" designates SUN4V specific ASIs. "(NG4)" designates SPARC-T4 * and later ASIs. */ +#define ASI_MCD_PRIV_PRIMARY 0x02 /* (NG7) Privileged MCD version VA */ +#define ASI_MCD_REAL 0x05 /* (NG7) Privileged MCD version PA */ #define ASI_PHYS_USE_EC 0x14 /* PADDR, E-cachable */ #define ASI_PHYS_BYPASS_EC_E 0x15 /* PADDR, E-bit */ #define ASI_BLK_AIUP_4V 0x16 /* (4V) Prim, user, block ld/st */ @@ -245,6 +247,9 @@ #define ASI_UDBL_CONTROL_R 0x7f /* External UDB control regs rd low*/ #define ASI_INTR_R 0x7f /* IRQ vector dispatch read */ #define ASI_INTR_DATAN_R 0x7f /* (III) In irq vector data reg N */ +#define ASI_MCD_PRIMARY 0x90 /* (NG7) MCD version load/store */ +#define ASI_MCD_ST_BLKINIT_PRIMARY \ + 0x92 /* (NG7) MCD store BLKINIT primary */ #define ASI_PIC 0xb0 /* (NG4) PIC registers */ #define ASI_PST8_P 0xc0 /* Primary, 8 8-bit, partial */ #define ASI_PST8_S 0xc1 /* Secondary, 8 8-bit, partial */ diff --git a/arch/sparc/include/uapi/asm/pstate.h b/arch/sparc/include/uapi/asm/pstate.h index b6999c9e7e86..ceca96e685c2 100644 --- a/arch/sparc/include/uapi/asm/pstate.h +++ b/arch/sparc/include/uapi/asm/pstate.h @@ -11,7 +11,12 @@ * ----------------------------------------------------------------------- * 63 12 11 10 9 8 7 6 5 4 3 2 1 0 */ +/* IG on V9 conflicts with MCDE on M7. PSTATE_MCDE will only be used on + * processors that support ADI which do not use IG, hence there is no + * functional conflict + */ #define PSTATE_IG _AC(0x0000000000000800,UL) /* Interrupt Globals. */ +#define PSTATE_MCDE _AC(0x0000000000000800,UL) /* MCD Enable */ #define PSTATE_MG _AC(0x0000000000000400,UL) /* MMU Globals. */ #define PSTATE_CLE _AC(0x0000000000000200,UL) /* Current Little Endian.*/ #define PSTATE_TLE _AC(0x0000000000000100,UL) /* Trap Little Endian. */ @@ -48,7 +53,12 @@ #define TSTATE_ASI _AC(0x00000000ff000000,UL) /* AddrSpace ID. */ #define TSTATE_PIL _AC(0x0000000000f00000,UL) /* %pil (Linux traps)*/ #define TSTATE_PSTATE _AC(0x00000000000fff00,UL) /* PSTATE. */ +/* IG on V9 conflicts with MCDE on M7. TSTATE_MCDE will only be used on + * processors that support ADI which do not support IG, hence there is + * no functional conflict + */ #define TSTATE_IG _AC(0x0000000000080000,UL) /* Interrupt Globals.*/ +#define TSTATE_MCDE _AC(0x0000000000080000,UL) /* MCD enable. */ #define TSTATE_MG _AC(0x0000000000040000,UL) /* MMU Globals. */ #define TSTATE_CLE _AC(0x0000000000020000,UL) /* CurrLittleEndian. */ #define TSTATE_TLE _AC(0x0000000000010000,UL) /* TrapLittleEndian. */ diff --git a/arch/sparc/kernel/entry.h b/arch/sparc/kernel/entry.h index 7378567b601f..c746c0fd5d6b 100644 --- a/arch/sparc/kernel/entry.h +++ b/arch/sparc/kernel/entry.h @@ -160,6 +160,9 @@ void sun4v_resum_overflow(struct pt_regs *regs); void sun4v_nonresum_error(struct pt_regs *regs, unsigned long offset); void sun4v_nonresum_overflow(struct pt_regs *regs); +void sun4v_mem_corrupt_detect_precise(struct pt_regs *regs, + unsigned long addr, + unsigned long context); extern unsigned long sun4v_err_itlb_vaddr; extern unsigned long sun4v_err_itlb_ctx; diff --git a/arch/sparc/kernel/head_64.S b/arch/sparc/kernel/head_64.S index a41e6e16eb36..540bfc98472c 100644 --- a/arch/sparc/kernel/head_64.S +++ b/arch/sparc/kernel/head_64.S @@ -897,6 +897,7 @@ sparc64_boot_end: #include "syscalls.S" #include "helpers.S" #include "sun4v_tlb_miss.S" +#include "sun4v_mcd.S" #include "sun4v_ivec.S" #include "ktlb.S" #include "tsb.S" diff --git a/arch/sparc/kernel/sun4v_mcd.S b/arch/sparc/kernel/sun4v_mcd.S new file mode 100644 index 000000000000..d6c69ebca110 --- /dev/null +++ b/arch/sparc/kernel/sun4v_mcd.S @@ -0,0 +1,18 @@ +/* sun4v_mcd.S: Sun4v memory corruption detected precise exception handler + * + * Copyright (c) 2015 Oracle and/or its affiliates. All rights reserved. + * Authors: Bob Picco <bob.picco@oracle.com>, + * Khalid Aziz <khalid.aziz@oracle.com> + * + * This work is licensed under the terms of the GNU GPL, version 2. + */ + .text + .align 32 + +sun4v_mcd_detect_precise: + mov %l4, %o1 + mov %l5, %o2 + call sun4v_mem_corrupt_detect_precise + add %sp, PTREGS_OFF, %o0 + ba,a,pt %xcc, rtrap + nop diff --git a/arch/sparc/kernel/traps_64.c b/arch/sparc/kernel/traps_64.c index 0a56dc257cb9..fc73baa588f6 100644 --- a/arch/sparc/kernel/traps_64.c +++ b/arch/sparc/kernel/traps_64.c @@ -2656,6 +2656,60 @@ void sun4v_do_mna(struct pt_regs *regs, unsigned long addr, unsigned long type_c force_sig_info(SIGBUS, &info, current); } +/* sun4v_mem_corrupt_detect_precise() - Handle precise exception on an ADI + * tag mismatch. + * + * ADI version tag mismatch on a load from memory always results in a + * precise exception. Tag mismatch on a store to memory will result in + * precise exception if MCDPER or PMCDPER is set to 1. + */ +void sun4v_mem_corrupt_detect_precise(struct pt_regs *regs, unsigned long addr, + unsigned long context) +{ + siginfo_t info; + + if (notify_die(DIE_TRAP, "memory corruption precise exception", regs, + 0, 0x8, SIGSEGV) == NOTIFY_STOP) + return; + + if (regs->tstate & TSTATE_PRIV) { + /* MCD exception could happen because the task was running + * a system call with MCD enabled and passed a non-versioned + * pointer or pointer with bad version tag to the system + * call. + */ + const struct exception_table_entry *entry; + + entry = search_exception_tables(regs->tpc); + if (entry) { + /* Looks like a bad syscall parameter */ +#ifdef DEBUG_EXCEPTIONS + pr_emerg("Exception: PC<%016lx> faddr<UNKNOWN>\n", + regs->tpc); + pr_emerg("EX_TABLE: insn<%016lx> fixup<%016lx>\n", + regs->tpc, entry->fixup); +#endif + regs->tpc = entry->fixup; + regs->tnpc = regs->tpc + 4; + return; + } + pr_emerg("%s: ADDR[%016lx] CTX[%lx], going.\n", + __func__, addr, context); + die_if_kernel("MCD precise", regs); + } + + if (test_thread_flag(TIF_32BIT)) { + regs->tpc &= 0xffffffff; + regs->tnpc &= 0xffffffff; + } + info.si_signo = SIGSEGV; + info.si_code = SEGV_ADIPERR; + info.si_errno = 0; + info.si_addr = (void __user *) addr; + info.si_trapno = 0; + force_sig_info(SIGSEGV, &info, current); +} + void do_privop(struct pt_regs *regs) { enum ctx_state prev_state = exception_enter(); diff --git a/arch/sparc/kernel/ttable_64.S b/arch/sparc/kernel/ttable_64.S index 18685fe69b91..86e737e59c7e 100644 --- a/arch/sparc/kernel/ttable_64.S +++ b/arch/sparc/kernel/ttable_64.S @@ -26,8 +26,10 @@ tl0_ill: membar #Sync TRAP_7INSNS(do_illegal_instruction) tl0_privop: TRAP(do_privop) tl0_resv012: BTRAP(0x12) BTRAP(0x13) BTRAP(0x14) BTRAP(0x15) BTRAP(0x16) BTRAP(0x17) -tl0_resv018: BTRAP(0x18) BTRAP(0x19) BTRAP(0x1a) BTRAP(0x1b) BTRAP(0x1c) BTRAP(0x1d) -tl0_resv01e: BTRAP(0x1e) BTRAP(0x1f) +tl0_resv018: BTRAP(0x18) BTRAP(0x19) +tl0_mcd: SUN4V_MCD_PRECISE +tl0_resv01b: BTRAP(0x1b) +tl0_resv01c: BTRAP(0x1c) BTRAP(0x1d) BTRAP(0x1e) BTRAP(0x1f) tl0_fpdis: TRAP_NOSAVE(do_fpdis) tl0_fpieee: TRAP_SAVEFPU(do_fpieee) tl0_fpother: TRAP_NOSAVE(do_fpother_check_fitos)