From owner-p4-projects@FreeBSD.ORG Tue Jun 19 10:22:03 2012 Return-Path: Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id 3C64F1065670; Tue, 19 Jun 2012 10:22:02 +0000 (UTC) Delivered-To: perforce@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [69.147.83.52]) by hub.freebsd.org (Postfix) with ESMTP id DEB62106564A for ; Tue, 19 Jun 2012 10:22:01 +0000 (UTC) (envelope-from bb+lists.freebsd.perforce@cyrus.watson.org) Received: from skunkworks.freebsd.org (skunkworks.freebsd.org [IPv6:2001:4f8:fff6::2d]) by mx1.freebsd.org (Postfix) with ESMTP id C06398FC15 for ; Tue, 19 Jun 2012 10:22:01 +0000 (UTC) Received: from skunkworks.freebsd.org (localhost [127.0.0.1]) by skunkworks.freebsd.org (8.14.4/8.14.4) with ESMTP id q5JAM14J060948 for ; Tue, 19 Jun 2012 10:22:01 GMT (envelope-from bb+lists.freebsd.perforce@cyrus.watson.org) Received: (from perforce@localhost) by skunkworks.freebsd.org (8.14.4/8.14.4/Submit) id q5JAM1bi060942 for perforce@freebsd.org; Tue, 19 Jun 2012 10:22:01 GMT (envelope-from bb+lists.freebsd.perforce@cyrus.watson.org) Date: Tue, 19 Jun 2012 10:22:01 GMT Message-Id: <201206191022.q5JAM1bi060942@skunkworks.freebsd.org> X-Authentication-Warning: skunkworks.freebsd.org: perforce set sender to bb+lists.freebsd.perforce@cyrus.watson.org using -f From: Robert Watson To: Perforce Change Reviews Precedence: bulk Cc: Subject: PERFORCE change 213130 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.5 List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 19 Jun 2012 10:22:03 -0000 http://p4web.freebsd.org/@@213130?ac=10 Change 213130 by rwatson@rwatson_svr_ctsrd_mipsbuild on 2012/06/19 10:20:58 Checkpoint CHERI CP2 userspace context management for FreeBSD/CHERI: 1. Introduce two new header files, cp2asm.h and cp2reg.h, appropriate for inclusion from both assembly and C files. 2. Centralise previously distributed definitions of CHERI_EXCEPTION_ENTER() and CHERI_EXCEPTION_RETURN() in cp2asm.h. 3. For now, maintain only a userspace cp2frame, not a kernel one, so remove nascent kernel frame from struct pcb. 4. Add new SAVE_CP2_CONTEXT() and RESTORE_CP2_CONTEXT() routines to save and restore userspace CP2 registers in the pcb. 5. Save and restore CP2 state for userspace-sourced system calls and interrupts that fire during usersapce execution. Also restore userspace CP2 state when returning from fork_trampoline(). With this change, the skeleton is in place to support capability-aware userspace programs. Refinement will undoubtably be required, and the object capability invocation exception handler is currently unimplemented in this cut. Affected files ... .. //depot/projects/ctsrd/cheribsd/src/sys/mips/cheri/cp2.c#6 edit .. //depot/projects/ctsrd/cheribsd/src/sys/mips/cheri/cp2.h#8 edit .. //depot/projects/ctsrd/cheribsd/src/sys/mips/cheri/cp2asm.h#1 add .. //depot/projects/ctsrd/cheribsd/src/sys/mips/cheri/cp2reg.h#1 add .. //depot/projects/ctsrd/cheribsd/src/sys/mips/include/pcb.h#3 edit .. //depot/projects/ctsrd/cheribsd/src/sys/mips/mips/exception.S#4 edit .. //depot/projects/ctsrd/cheribsd/src/sys/mips/mips/genassym.c#2 edit .. //depot/projects/ctsrd/cheribsd/src/sys/mips/mips/swtch.S#5 edit Differences ... ==== //depot/projects/ctsrd/cheribsd/src/sys/mips/cheri/cp2.c#6 (text+ko) ==== @@ -465,7 +465,7 @@ { struct cp2_frame *cfp; - cfp = &td->td_pcb->pcb_ucp2frame; + cfp = &td->td_pcb->pcb_cp2frame; cp2_capability_load(CHERI_CR_CT0, &cp2_user_template); cp2_capability_store(CHERI_CR_CT0, &cfp->cf_c0); cp2_capability_store(CHERI_CR_CT0, &cfp->cf_c1); ==== //depot/projects/ctsrd/cheribsd/src/sys/mips/cheri/cp2.h#8 (text+ko) ==== @@ -33,55 +33,9 @@ #include /* CTASSERT */ -/* - * CHERI ISA-defined constants for capabilities. - * - * XXXRW: CHERI_UNSEALED is not currently considered part of the perms word, - * but perhaps it should be. - */ -#define CHERI_PERM_EXECUTE 0x0001 -#define CHERI_PERM_STORE_CAPABILITY 0x0002 -#define CHERI_PERM_LOAD_CAPABILITY 0x0004 -#define CHERI_PERM_STORE 0x0008 -#define CHERI_PERM_LOAD 0x0010 -#define CHERI_PERM_STORE_EPHEMERAL_CAPABILITY 0x0020 -#define CHERI_PERM_SEAL 0x0040 -#define CHERI_PERM_SET_TYPE 0x0080 -#define CHERI_PERM_RESERVED0 0x0100 -#define CHERI_PERM_RESERVED1 0x0200 -#define CHERI_PERM_ACCESS_TSC 0x0400 -#define CHERI_PERM_ACCESS_KCC 0x0800 -#define CHERI_PERM_ACCESS_KDC 0x1000 -#define CHERI_PERM_ACCESS_EPCC 0x2000 -#define CHERI_PERM_NON_EPHEMERAL 0x4000 -#define CHERI_UNSEALED 0x8000 - -/* - * XXXRW: Should this include CHERI_UNSEALED? - */ -#define CHERI_PERM_ALL \ - (CHERI_PERM_EXECUTE | CHERI_PERM_STORE_CAPABILITY | \ - CHERI_PERM_LOAD_CAPABILITY | CHERI_PERM_STORE | \ - CHERI_PERM_STORE_EPHEMERAL_CAPABILITY | CHERI_PERM_SEAL | \ - CHERI_PERM_SET_TYPE | CHERI_PERM_RESERVED0 | \ - CHERI_PERM_RESERVED1 | CHERI_PERM_ACCESS_TSC | \ - CHERI_PERM_ACCESS_KCC | CHERI_PERM_ACCESS_KDC | \ - CHERI_PERM_ACCESS_EPCC | CHERI_PERM_NON_EPHEMERAL) +#include /* - * A blend of hardware and software allocation of capability registers. - */ -#define CHERI_CR_C0 0 /* MIPS fetch/load/store capability. */ -#define CHERI_CR_CT0 10 /* CT0: temporary capability. */ -#define CHERI_CR_UDC 25 /* SC0: user data capability. */ -#define CHERI_CR_KT0 26 /* KT0: temporary kernel capability. */ -#define CHERI_CR_KT1 27 /* KT1: temporary kernel capability. */ -#define CHERI_CR_TSC 28 /* TSC: trusted stack capability. */ -#define CHERI_CR_KCC 29 /* KCC: kernel code capability. */ -#define CHERI_CR_KDC 30 /* KDC: kernel data capability. */ -#define CHERI_CR_EPCC 31 /* EPCC: exception program counter cap. */ - -/* * Canonical C-language representation of a capability. */ #define CAPABILITY_SIZE 32 @@ -101,6 +55,8 @@ * Register frame to be preserved on context switching -- very similar to * struct mips_frame. As with mips_frame, the order of save/restore is very * important for both reasons of correctness and security. + * + * Must match the register offset definitions (CHERI_*_OFF) in cp2reg.h. */ struct cp2_frame { /* c0 has special properties for MIPS load/store instructions. */ ==== //depot/projects/ctsrd/cheribsd/src/sys/mips/include/pcb.h#3 (text+ko) ==== @@ -55,12 +55,9 @@ { struct trapframe pcb_regs; /* saved CPU and registers */ #ifdef CPU_CHERI - struct cp2_frame pcb_ucp2frame; + struct cp2_frame pcb_cp2frame; /* Userspace capabilities. */ #endif __register_t pcb_context[14]; /* kernel context for resume */ -#ifdef CPU_CHERI - struct cp2_frame pcb_cp2frame; -#endif void *pcb_onfault; /* for copyin/copyout faults */ register_t pcb_tpc; }; ==== //depot/projects/ctsrd/cheribsd/src/sys/mips/mips/exception.S#4 (text+ko) ==== @@ -62,6 +62,11 @@ #include #include +#ifdef CPU_CHERI +#include +#include +#endif + #include "opt_cputype.h" #include "assym.s" @@ -73,42 +78,8 @@ */ #define INTRCNT_COUNT 128 -#ifdef CPU_CHERI -/* - * When entering an exception handler, conditionally save the default user - * data capability. Then install the kernel's default data capability. The - * caller provides a temporary register to use for the purposes of querying - * CP0 SR to determine whether the target is userspace or the kernel. - */ -#define CHERI_EXCEPTION_ENTER(reg) \ - mfc0 reg, MIPS_COP_0_STATUS; \ - andi reg, reg, SR_KSU_USER; \ - beq reg, $0, 64f; \ - nop; \ - cmove $c25, $c0; \ -64: \ - cmove $c0, $c30; /* - * When returning from an exception, conditionally restore the default user - * data capability. The caller provides a temporary register to use for the - * purposes of querying CP0 SR to determine whether the target is userspace - * or the kernel. - */ -#define CHERI_EXCEPTION_RETURN(reg) \ - mfc0 reg, MIPS_COP_0_STATUS; \ - andi reg, reg, SR_KSU_USER; \ - beq reg, $0, 65f; \ - nop; \ - cmove $c0, $c25; \ -65: -#else -#define CHERI_EXCEPTION_ENTER(reg) -#define CHERI_EXCEPTION_RETURN(reg) -#endif - - -/* *---------------------------------------------------------------------------- * * MipsTLBMiss -- @@ -124,7 +95,9 @@ VECTOR(MipsTLBMiss, unknown) .set push .set noat +#ifdef CPU_CHERI CHERI_EXCEPTION_ENTER(k0) +#endif j MipsDoTLBMiss MFC0 k0, MIPS_COP_0_BAD_VADDR # get the fault address .set pop @@ -178,7 +151,9 @@ COP0_SYNC tlbwr #1a: write to tlb HAZARD_DELAY +#ifdef CPU_CHERI CHERI_EXCEPTION_RETURN(k0) +#endif eret #1f: retUrn from exception 1: j MipsTLBMissException #20: kernel exception @@ -197,7 +172,9 @@ * Find out what mode we came from and jump to the proper handler. */ .set noat +#ifdef CPU_CHERI CHERI_EXCEPTION_ENTER(k0) +#endif mfc0 k0, MIPS_COP_0_STATUS # Get the status register mfc0 k1, MIPS_COP_0_CAUSE # Get the cause register value. and k0, k0, SR_KSU_USER # test for user mode @@ -427,7 +404,9 @@ RESTORE_CPU # v0 contains the return address. sync +#ifdef CPU_CHERI CHERI_EXCEPTION_RETURN(k0) +#endif eret .set at END(MipsKernGenException) @@ -504,6 +483,9 @@ SAVE_U_PCB_REG(a1, CAUSE, k1) SAVE_U_PCB_REG(a2, BADVADDR, k1) SAVE_U_PCB_REG(a3, PC, k1) +#ifdef CPU_CHERI + SAVE_CP2_CONTEXT(t0, k1) +#endif REG_S a3, CALLFRAME_RA(sp) # for debugging PTR_LA gp, _C_LABEL(_gp) # switch to kernel GP # Turn off fpu and enter kernel mode @@ -553,6 +535,9 @@ or a1, a1, a0 SAVE_U_PCB_REG(a1, SR, k1) +#ifdef CPU_CHERI + RESTORE_CP2_CONTEXT(t0, k1) +#endif RESTORE_U_PCB_REG(t0, MULLO, k1) RESTORE_U_PCB_REG(t1, MULHI, k1) mtlo t0 @@ -594,7 +579,9 @@ mtc0 k0, MIPS_COP_0_STATUS # still exception level ITLBNOPFIX sync +#ifdef CPU_CHERI CHERI_EXCEPTION_RETURN(k0) +#endif eret .set at END(MipsUserGenException) @@ -687,7 +674,9 @@ REG_L v0, CALLFRAME_RA + KERN_REG_SIZE(sp) RESTORE_CPU # v0 contains the return address. sync +#ifdef CPU_CHERI CHERI_EXCEPTION_RETURN(k0) +#endif eret .set at END(MipsKernIntr) @@ -764,6 +753,9 @@ SAVE_U_PCB_REG(a0, SR, k1) SAVE_U_PCB_REG(a1, CAUSE, k1) SAVE_U_PCB_REG(a3, PC, k1) # PC in a3, note used later! +#ifdef CPU_CHERI + SAVE_CP2_CONTEXT(t0, k1) +#endif PTR_SUBU sp, k1, CALLFRAME_SIZ # switch to kernel SP PTR_LA gp, _C_LABEL(_gp) # switch to kernel GP @@ -822,6 +814,9 @@ or a1, a1, a0 SAVE_U_PCB_REG(a1, SR, k1) +#ifdef CPU_CHERI + RESTORE_CP2_CONTEXT(t0, k1) +#endif RESTORE_U_PCB_REG(s0, S0, k1) RESTORE_U_PCB_REG(s1, S1, k1) RESTORE_U_PCB_REG(s2, S2, k1) @@ -863,7 +858,9 @@ mtc0 k0, MIPS_COP_0_STATUS # SR with EXL set. ITLBNOPFIX sync +#ifdef CPU_CHERI CHERI_EXCEPTION_RETURN(k0) +#endif eret .set at END(MipsUserIntr) @@ -959,13 +956,17 @@ bltz k0, tlb_insert_random nop tlbwi +#ifdef CPU_CHERI CHERI_EXCEPTION_RETURN(k0) +#endif eret ssnop tlb_insert_random: tlbwr +#ifdef CPU_CHERI CHERI_EXCEPTION_RETURN(k0) +#endif eret ssnop @@ -1097,7 +1098,9 @@ COP0_SYNC tlbwr # write to tlb HAZARD_DELAY +#ifdef CPU_CHERI CHERI_EXCEPTION_RETURN(k0) +#endif eret # return from exception .set at END(MipsTLBMissException) @@ -1250,7 +1253,9 @@ */ .text VECTOR(MipsCache, unknown) +#ifdef CPU_CHERI CHERI_EXCEPTION_ENTER(k0) +#endif PTR_LA k0, _C_LABEL(MipsCacheException) li k1, MIPS_KSEG0_PHYS_MASK and k0, k1 @@ -1283,7 +1288,9 @@ mtc0 k0, MIPS_COP_0_STATUS # restore status COP0_SYNC +#ifdef CPU_CHERI CHERI_EXCEPTION_RETURN(k0) +#endif eret MSG("cache error @ EPC 0x%x CachErr 0x%x"); ==== //depot/projects/ctsrd/cheribsd/src/sys/mips/mips/genassym.c#2 (text+ko) ==== @@ -78,6 +78,9 @@ ASSYM(TF_REG_SR, offsetof(struct trapframe, sr)); ASSYM(U_PCB_REGS, offsetof(struct pcb, pcb_regs.zero)); +#ifdef CPU_CHERI +ASSYM(U_PCB_CP2FRAME, offsetof(struct pcb, pcb_cp2frame.cf_c0)); +#endif ASSYM(U_PCB_CONTEXT, offsetof(struct pcb, pcb_context)); ASSYM(U_PCB_ONFAULT, offsetof(struct pcb, pcb_onfault)); ASSYM(U_PCB_FPREGS, offsetof(struct pcb, pcb_regs.f0)); ==== //depot/projects/ctsrd/cheribsd/src/sys/mips/mips/swtch.S#5 (text+ko) ==== @@ -64,6 +64,11 @@ #include #include +#ifdef CPU_CHERI +#include +#include +#endif + #include "assym.s" .set noreorder # Noreorder is default style! @@ -92,40 +97,6 @@ #define RESTORE_U_PCB_CONTEXT(reg, offs, base) \ REG_L reg, U_PCB_CONTEXT + (SZREG * offs) (base) -#ifdef CPU_CHERI -/* - * When entering an exception handler, conditionally save the default user - * data capability. Then install the kernel's default data capability. The - * caller provides a temporary register to use for the purposes of querying - * CP0 SR to determine whether the target is userspace or the kernel. - */ -#define CHERI_EXCEPTION_ENTER(reg) \ - mfc0 reg, MIPS_COP_0_STATUS; \ - andi reg, reg, SR_KSU_USER; \ - beq reg, $0, 64f; \ - nop; \ - cmove $c25, $c0; \ -64: \ - cmove $c0, $c30; - -/* - * When returning from an exception, conditionally restore the default user - * data capability. The caller provides a temporary register to use for the - * purposes of querying CP0 SR to determine whether the target is userspace - * or the kernel. - */ -#define CHERI_EXCEPTION_RETURN(reg) \ - mfc0 reg, MIPS_COP_0_STATUS; \ - andi reg, reg, SR_KSU_USER; \ - beq reg, $0, 65f; \ - nop; \ - cmove $c0, $c25; \ -65: -#else -#define CHERI_EXCEPTION_ENTER(reg) -#define CHERI_EXCEPTION_RETURN(reg) -#endif - /* * Setup for and return to user. */ @@ -150,6 +121,9 @@ GET_CPU_PCPU(k1) PTR_L k1, PC_CURPCB(k1) +#ifdef CPU_CHERI + RESTORE_CP2_CONTEXT(t0, k1) +#endif RESTORE_U_PCB_REG(t0, MULLO, k1) RESTORE_U_PCB_REG(t1, MULHI, k1) mtlo t0 @@ -195,7 +169,9 @@ mtc0 k0, MIPS_COP_0_STATUS # switch to user mode (when eret...) HAZARD_DELAY sync +#ifdef CPU_CHERI CHERI_EXCEPTION_RETURN(k0) +#endif eret .set at END(fork_trampoline)