[v11,03/10] sparc64: Add support for ADI register fields, ASIs and traps

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
Related show

Commit Message

Khalid Aziz Feb. 1, 2018, 6:01 p.m.
SPARC M7 processor adds new control register fields, ASIs and a new
trap to support the ADI (Application Data Integrity) feature. This
patch adds definitions for these register fields, ASIs and a handler
for the new precise memory corruption detected trap.

Signed-off-by: Khalid Aziz <khalid.aziz@oracle.com>
Cc: Khalid Aziz <khalid@gonehiking.org>
Reviewed-by: Anthony Yznaga <anthony.yznaga@oracle.com>
---
v10:
	- Updated copyright
v8:
	- Minor print formatting change as suggested by checkpatch
v6:
	- Added a missing nop in the delay slot in sun4v_mcd_detect_precise

v5:
	- Fixed indentation issues in assembly code

v4:
	- Broke patch up into smaller patches

v3:
	- Removed CONFIG_SPARC_ADI
	- Replaced prctl commands with mprotect
	- Added auxiliary vectors for ADI parameters
	- Enabled ADI for swappable pages

v2:
	- Fixed a build error

 arch/sparc/include/asm/hypervisor.h  |  2 ++
 arch/sparc/include/asm/pgtable_64.h  |  2 ++
 arch/sparc/include/asm/ttable.h      | 10 +++++++
 arch/sparc/include/uapi/asm/asi.h    |  5 ++++
 arch/sparc/include/uapi/asm/pstate.h | 10 +++++++
 arch/sparc/kernel/entry.h            |  3 ++
 arch/sparc/kernel/head_64.S          |  1 +
 arch/sparc/kernel/sun4v_mcd.S        | 18 ++++++++++++
 arch/sparc/kernel/traps_64.c         | 54 ++++++++++++++++++++++++++++++++++++
 arch/sparc/kernel/ttable_64.S        |  6 ++--
 10 files changed, 109 insertions(+), 2 deletions(-)
 create mode 100644 arch/sparc/kernel/sun4v_mcd.S

Comments

Joe Perches Feb. 1, 2018, 8:32 p.m. | #1
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
David Miller Feb. 1, 2018, 8:39 p.m. | #2
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
Sam Ravnborg Feb. 1, 2018, 9:49 p.m. | #3
> >  #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
Joe Perches Feb. 1, 2018, 10:09 p.m. | #4
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

Patch

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)