Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 5 Oct 2013 18:40:25 GMT
From:      Robert Watson <rwatson@FreeBSD.org>
To:        Perforce Change Reviews <perforce@FreeBSD.org>
Subject:   PERFORCE change 971766 for review
Message-ID:  <201310051840.r95IePYU046295@skunkworks.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://p4web.freebsd.org/@@971766?ac=10

Change 971766 by rwatson@rwatson_zenith_cl_cam_ac_uk on 2013/10/05 18:40:20

	Continue implementation of software CCall/CReturn:
	
	- Implement support for per-thread trusted stacks in the
	  CCall/CReturn exception handlers, with tests for
	  overflow/underflow.
	
	- Use correct branch instructions when testing code and
	  data-capability seals, target PC.
	
	We now get successfully into and out of sandboxes using
	CCall/CReturn under CheriBSD, but there remains only limited
	error handling.

Affected files ...

.. //depot/projects/ctsrd/cheribsd/src/sys/mips/cheri/ccall.S#9 edit
.. //depot/projects/ctsrd/cheribsd/src/sys/mips/cheri/cheri_stack.c#2 edit
.. //depot/projects/ctsrd/cheribsd/src/sys/mips/include/cheri.h#26 edit
.. //depot/projects/ctsrd/cheribsd/src/sys/mips/mips/genassym.c#7 edit

Differences ...

==== //depot/projects/ctsrd/cheribsd/src/sys/mips/cheri/ccall.S#9 (text+ko) ====

@@ -107,10 +107,6 @@
  * XXXRW: Lots of non-done checking -- e.g., types, protection bits, etc.  We
  * need a C error-handling path.
  *
- * XXXRW: Temporarily, store a one-entry trusted stack in a global.  k1 should
- * eventually point to the next entry in td->td_pcb.pcb_cheristack, with an
- * overflow check.
- *
  * XXXRW: We'd like a CSetCause so that we can jump to the general CP2
  * exception handler from here after setting its state appropriately.
  *
@@ -129,11 +125,11 @@
 
 	/* Second, check for the sealed bit on both arguments. */
 	cgetunsealed	k0, CHERI_REG_CCALLCODE
-	beqz		k0, CCall_c1_unsealed
+	bnez		k0, CCall_c1_unsealed
 	nop
 
 	cgetunsealed	k0, CHERI_REG_CCALLDATA
-	beqz		k0, CCall_c2_unsealed
+	bnez		k0, CCall_c2_unsealed
 	nop
 
 	/* Third, check for type equality. */
@@ -146,14 +142,14 @@
 	cgetperm	k0, CHERI_REG_CCALLCODE
 	REG_LI		k1, CHERI_PERM_SEAL | CHERI_PERM_EXECUTE
 	and		k0, k0, k1
-	beq		k0, k1, CCall_c1_perms
+	bne		k0, k1, CCall_c1_perms
 	nop
 
 	/* Fifth, check proposed PC is not lower than base. */
 	cgetbase	k0, CHERI_REG_CCALLCODE
 	cgettype	k1, CHERI_REG_CCALLCODE
 	sltu		k1, k1, k0
-	bne		k1, zero, CCall_c1_range
+	bnez		k1, CCall_c1_range
 	nop
 
 	/*
@@ -170,22 +166,43 @@
 	PTR_SUBIU	k0, 4
 	cgettype	k1, CHERI_REG_CCALLCODE
 	sltu		k1, k1, k0
-	bne		k1, zero, CCall_c1_range
+	bnez		k1, CCall_c1_range
+	nop
+
+	/*
+	 * Now prepare to push IDC, PCC, PC+4 onto the trusted stack.  Begin
+	 * by retrieving the current PCB pointer to reach the trusted stack.
+	 */
+	GET_CPU_PCPU(k1)   
+	PTR_L		k1, PC_CURPCB(k1)
+
+	/* Retrieve current trusted stack pointer. */
+	PTR_L		k0, U_PCB_CHERISTACK_SP(k1)
+
+	/* If at bottom (byte offset 0), then overflow. */
+	beqz		k0, CCall_stack_overflow
 	nop
 
-	/* XXXRW: Change to PCB reference in the future. */
-	PTR_LA		k1, cheri_tsc_hack
+	/* Decrement stack pointer. */
+	PTR_SUBIU	k0, k0, CHERI_FRAME_SIZE
+
+	/* Write back stack pointer. */
+	PTR_S		k0, U_PCB_CHERISTACK_SP(k1)
+
+	/* Convert stack-relative offset to global pointer. */
+	PTR_ADDU	k0, k1, k0			/* Add PCB pointer. */
+	PTR_ADDIU	k0, k0, U_PCB_CHERISTACK_FRAMES	/* Add PCB offset. */
 
 	/* Push IDC. */
-	csc		CHERI_REG_IDC, k1, U_CHERI_STACK_IDC(CHERI_REG_KDC)
+	csc		CHERI_REG_IDC, k0, CHERI_STACKFRAME_IDC(CHERI_REG_KDC)
 
 	/* Push PCC. */
-	csc		CHERI_REG_EPCC, k1, U_CHERI_STACK_PCC(CHERI_REG_KDC)
+	csc		CHERI_REG_EPCC, k0, CHERI_STACKFRAME_PCC(CHERI_REG_KDC)
 
-	/* Push PC + 4 */
-	MFC0		k0, MIPS_COP_0_EXC_PC
-	PTR_ADDU	k0, k0, 4
-	csd		k0, k1, U_CHERI_STACK_PC(CHERI_REG_KDC)
+	/* Push PC + 4; k1 is overwritten, so no longer PCB pointer. */
+	MFC0		k1, MIPS_COP_0_EXC_PC
+	PTR_ADDU	k1, k1, 4
+	csd		k1, k0, CHERI_STACKFRAME_PC(CHERI_REG_KDC)
 
 	/*
 	 * Temporarily set KDC type to allow unsealing.
@@ -201,7 +218,7 @@
 	/* Unseal cb; install in IDC. */
 	cunseal		CHERI_REG_IDC, CHERI_REG_CCALLDATA, CHERI_REG_KDC
 
-	/* Installe cs.otype - cs.base into PC; note clobbers k1. */
+	/* Installe cs.otype. */
 	cgettype	k0, CHERI_REG_CCALLCODE
 	cgetbase	k1, CHERI_REG_CCALLCODE
 	dsub		k0, k0, k1
@@ -226,6 +243,7 @@
 CCall_c1_c2_type_mismatch:
 CCall_c1_perms:
 CCall_c1_range:
+CCall_stack_overflow:
 	/* XXXRW: For now, treat as a NOP. */
 	MFC0		k0, MIPS_COP_0_EXC_PC
 	PTR_ADDIU	k0, 4
@@ -243,10 +261,6 @@
  * XXXRW: Lots of non-done checking -- e.g., types, protection bits, etc.  We
  * need a C error handling path.
  *
- * XXXRW: Temporarily, store a one-entry trusted stack in a global.  k1 should
- * eventually point to the next entry in td->td_pcb.pcb_cheristack, with an
- * underflow check.
- *
  * XXXRW: We'd like a CSetCause so that we can jump to the general CP2
  * exception handler from here after setting its state appropriately.
  *
@@ -258,24 +272,46 @@
         .set push
         .set noat
 
-	/* XXXRW: Change to PCB reference in the future. */
-	PTR_LA		k1, cheri_tsc_hack
+	/* Retrieve current PCB pointer. */
+	GET_CPU_PCPU(k1)   
+	PTR_L		k1, PC_CURPCB(k1)
+
+	/*
+	 * The only currently defined check in CReturn is stack underflow;
+	 * perform that check.
+	 */
+	PTR_L		k0, U_PCB_CHERISTACK_SP(k1)
+	sltiu		k0, CHERI_STACK_SIZE
+	beqz		k0, CReturn_stack_underflow
+	nop
+
+	/* Reload stack pointer. */
+	PTR_L		k0, U_PCB_CHERISTACK_SP(k1)
+	
+	/* Convert stack-relative offset to global pointer. */
+	PTR_ADDU	k0, k1, k0			/* Add PCB pointer. */
+	PTR_ADDIU	k0, k0, U_PCB_CHERISTACK_FRAMES	/* Add PCB offset. */
 
 	/* Pop IDC. */
-	clc		CHERI_REG_IDC, k1, U_CHERI_STACK_IDC(CHERI_REG_KDC)
+	clc		CHERI_REG_IDC, k0, CHERI_STACKFRAME_IDC(CHERI_REG_KDC)
 
 	/* Pop PCC. */
-	clc		CHERI_REG_EPCC, k1, U_CHERI_STACK_PCC(CHERI_REG_KDC)
+	clc		CHERI_REG_EPCC, k0, CHERI_STACKFRAME_PCC(CHERI_REG_KDC)
 
-	/* Pop PC + padding; +4 increment already done. */
-	cld		k0, k1, U_CHERI_STACK_PC(CHERI_REG_KDC)
+	/* Pop PC + padding; +4 already done; toasts k0; k1 still PCB. */
+	cld		k0, k0, CHERI_STACKFRAME_PC(CHERI_REG_KDC)
 	MTC0		k0, MIPS_COP_0_EXC_PC
 	COP0_SYNC
 
+	/* Update stack pointer. */
+	PTR_L		k0, U_PCB_CHERISTACK_SP(k1)
+	PTR_ADDIU	k0, CHERI_FRAME_SIZE
+	PTR_S		k0, U_PCB_CHERISTACK_SP(k1)
+
 	CHERI_EXCEPTION_RETURN(k0)
 	eret
 
-CReturn_error:
+CReturn_stack_underflow:
 	/* XXXRW: For now, treat as a NOP. */
 	MFC0		k0, MIPS_COP_0_EXC_PC
 	PTR_ADDIU	k0, 4

==== //depot/projects/ctsrd/cheribsd/src/sys/mips/cheri/cheri_stack.c#2 (text+ko) ====

@@ -82,7 +82,7 @@
 {
 
 	bzero(&pcb->pcb_cheristack, sizeof(pcb->pcb_cheristack));
-	pcb->pcb_cheristack.cs_max = CHERI_STACK_DEPTH;
+	pcb->pcb_cheristack.cs_sp = CHERI_STACK_SIZE;
 }
 
 /*

==== //depot/projects/ctsrd/cheribsd/src/sys/mips/include/cheri.h#26 (text+ko) ====

@@ -120,13 +120,16 @@
 
 #define	CHERI_STACK_DEPTH	2	/* XXXRW: 2 is a nice round number. */
 struct cheri_stack {
-	u_int		cs_max;		/* Maximum frame depth. */
-	u_int		cs_pointer;	/* Current frame index. */
+	register_t	cs_sp;		/* Byte offset, not frame index. */
 	register_t	_cs_pad0;
 	register_t	_cs_pad1;
 	register_t	_cs_pad2;
+	register_t	_cs_pad3;
 	struct cheri_stack_frame	cs_frames[CHERI_STACK_DEPTH];
 } __aligned(CHERICAP_SIZE);
+
+#define	CHERI_FRAME_SIZE	sizeof(struct cheri_stack_frame)
+#define	CHERI_STACK_SIZE	(CHERI_STACK_DEPTH * CHERI_FRAME_SIZE)
 #endif
 
 /*

==== //depot/projects/ctsrd/cheribsd/src/sys/mips/mips/genassym.c#7 (text+ko) ====

@@ -106,10 +106,14 @@
 ASSYM(MIPS_XKSEG_START, MIPS_XKSEG_START);
 
 #ifdef	CPU_CHERI
-ASSYM(U_PCB_CHERIFRAME, offsetof(struct pcb, pcb_cheriframe.cf_c0));
-ASSYM(U_CHERI_STACK_PC, offsetof(struct cheri_stack_frame, csf_pc));
-ASSYM(U_CHERI_STACK_PCC, offsetof(struct cheri_stack_frame, csf_pcc));
-ASSYM(U_CHERI_STACK_IDC, offsetof(struct cheri_stack_frame, csf_idc));
+ASSYM(CHERI_FRAME_SIZE, sizeof(struct cheri_stack_frame) * CHERI_STACK_DEPTH);
+ASSYM(CHERI_STACK_SIZE, sizeof(struct cheri_stack_frame));
+ASSYM(U_PCB_CHERIFRAME, offsetof(struct pcb, pcb_cheriframe));
+ASSYM(U_PCB_CHERISTACK_SP, offsetof(struct pcb, pcb_cheristack.cs_sp));
+ASSYM(U_PCB_CHERISTACK_FRAMES, offsetof(struct pcb, pcb_cheristack.cs_frames));
+ASSYM(CHERI_STACKFRAME_PC, offsetof(struct cheri_stack_frame, csf_pc));
+ASSYM(CHERI_STACKFRAME_PCC, offsetof(struct cheri_stack_frame, csf_pcc));
+ASSYM(CHERI_STACKFRAME_IDC, offsetof(struct cheri_stack_frame, csf_idc));
 #endif
 
 #ifdef	CPU_CNMIPS



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201310051840.r95IePYU046295>