From owner-p4-projects@FreeBSD.ORG Tue Jun 26 14:18:18 2012 Return-Path: Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id 6775F1065749; Tue, 26 Jun 2012 14:18:16 +0000 (UTC) Delivered-To: perforce@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id B2AE81065740 for ; Tue, 26 Jun 2012 14:18:15 +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 993418FC15 for ; Tue, 26 Jun 2012 14:18:15 +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 q5QEIFLw023036 for ; Tue, 26 Jun 2012 14:18:15 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 q5QEIF9J023033 for perforce@freebsd.org; Tue, 26 Jun 2012 14:18:15 GMT (envelope-from bb+lists.freebsd.perforce@cyrus.watson.org) Date: Tue, 26 Jun 2012 14:18:15 GMT Message-Id: <201206261418.q5QEIF9J023033@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 213491 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, 26 Jun 2012 14:18:18 -0000 http://p4web.freebsd.org/@@213491?ac=10 Change 213491 by rwatson@rwatson_svr_ctsrd_mipsbuild on 2012/06/26 14:17:55 Refine and generally improve kernel CP2 management: Don't maintain a PCB CP2 frame entry for udc (user data capability), as that's actually just the kernel's register for temporarily holding userspace's c0, which we already have a field for. Fix a bug in which PCC isn't properly saved and restored for capability-aware processes -- no symptoms yet, but they would have turned up in due course. Add DDB functions to print the current CP0 register file, and also preserved CP2 state for a thread (by default, the current thread). Fix a mistranscription of various capability permissions, and define a more refined set of rights for user processes. With these changes, capability registers appear to be properly initialised by execve(), maintained across a variety of context switches, conventional programs work properly, and programs that manipulate capabilities are able to do so successfully. Affected files ... .. //depot/projects/ctsrd/cheribsd/src/sys/mips/cheri/cp2.c#9 edit .. //depot/projects/ctsrd/cheribsd/src/sys/mips/include/cheri.h#4 edit .. //depot/projects/ctsrd/cheribsd/src/sys/mips/include/cheriasm.h#3 edit .. //depot/projects/ctsrd/cheribsd/src/sys/mips/include/cherireg.h#4 edit Differences ... ==== //depot/projects/ctsrd/cheribsd/src/sys/mips/cheri/cp2.c#9 (text+ko) ==== @@ -28,10 +28,14 @@ * SUCH DAMAGE. */ +#include "opt_ddb.h" + #include #include #include +#include + #include #include @@ -153,7 +157,6 @@ cp2_capability_copy(&cf_destp->cf_c22, &cf_srcp->cf_c22); cp2_capability_copy(&cf_destp->cf_c23, &cf_srcp->cf_c23); cp2_capability_copy(&cf_destp->cf_c24, &cf_srcp->cf_c24); - cp2_capability_copy(&cf_destp->cf_udc, &cf_srcp->cf_udc); cp2_capability_copy(&cf_destp->cf_tsc, &cf_srcp->cf_tsc); cp2_capability_copy(&cf_destp->cf_pcc, &cf_srcp->cf_pcc); } @@ -479,7 +482,94 @@ cp2_capability_set_null(&cfp->cf_c22); cp2_capability_set_null(&cfp->cf_c23); cp2_capability_set_null(&cfp->cf_c24); - cp2_capability_set_null(&cfp->cf_udc); cp2_capability_set_null(&cfp->cf_tsc); cp2_capability_set_null(&cfp->cf_pcc); } + +#ifdef DDB +#define DB_CP2_REG_PRINT_NUM(crn, num) do { \ + struct capability c; \ + \ + CP2_CR_GET((crn), c); \ + db_printf("C%u perms %08jx otype %016jx\n", num, \ + (uintmax_t)c.c_uperms, (uintmax_t)c.u.c_otype); \ + db_printf("\tbase %016jx length %016jx\n", (uintmax_t)c.c_base, \ + (uintmax_t)c.c_length); \ +} while (0) + +#define DB_CP2_REG_PRINT(crn) DB_CP2_REG_PRINT_NUM(crn, crn) + +/* + * Variation that prints live register state from CP2. + */ +DB_SHOW_COMMAND(cp0, ddb_dump_cp0) +{ + + db_printf("CP0 registers\n"); + DB_CP2_REG_PRINT(0); + DB_CP2_REG_PRINT(1); + DB_CP2_REG_PRINT(2); + DB_CP2_REG_PRINT(3); + DB_CP2_REG_PRINT(4); + DB_CP2_REG_PRINT(5); + DB_CP2_REG_PRINT(6); + DB_CP2_REG_PRINT(7); + DB_CP2_REG_PRINT(8); + DB_CP2_REG_PRINT(9); + DB_CP2_REG_PRINT(10); + DB_CP2_REG_PRINT(11); + DB_CP2_REG_PRINT(12); + DB_CP2_REG_PRINT(13); + DB_CP2_REG_PRINT(14); + DB_CP2_REG_PRINT(15); + DB_CP2_REG_PRINT(16); + DB_CP2_REG_PRINT(17); + DB_CP2_REG_PRINT(18); + DB_CP2_REG_PRINT(19); + DB_CP2_REG_PRINT(20); + DB_CP2_REG_PRINT(21); + DB_CP2_REG_PRINT(22); + DB_CP2_REG_PRINT(23); + DB_CP2_REG_PRINT(24); + DB_CP2_REG_PRINT(25); + DB_CP2_REG_PRINT(26); + DB_CP2_REG_PRINT(27); + DB_CP2_REG_PRINT(28); + DB_CP2_REG_PRINT(29); + DB_CP2_REG_PRINT(30); + DB_CP2_REG_PRINT(31); +} + +/* + * Variation that prints the saved userspace CP2 register frame for a thread. + */ +DB_SHOW_COMMAND(cp0frame, ddb_dump_cp0frame) +{ + struct thread *td; + struct cp2_frame *cfp; + u_int i; + + if (have_addr) + td = db_lookup_thread(addr, TRUE); + else + td = curthread; + + cfp = &td->td_pcb->pcb_cp2frame; + db_printf("Thread %d at %p\n", td->td_tid, td); + db_printf("CP2 frame at %p\n", cfp); + + /* Laboriously load and print each capability. */ + for (i = 0; i < 25; i++) { + cp2_capability_load(CHERI_CR_CT0, + (struct capability *)&cfp->cf_c0 + i); + DB_CP2_REG_PRINT_NUM(CHERI_CR_CT0, i); + } + db_printf("\nTSC and PCC:\n"); + cp2_capability_load(CHERI_CR_CT0, (struct capability *)&cfp->cf_c0 + + CHERI_CR_TSC_OFF); + DB_CP2_REG_PRINT_NUM(CHERI_CR_CT0, CHERI_CR_TSC); + cp2_capability_load(CHERI_CR_CT0, (struct capability *)&cfp->cf_c0 + + CHERI_CR_PCC_OFF); + DB_CP2_REG_PRINT_NUM(CHERI_CR_CT0, CHERI_CR_EPCC); +} +#endif ==== //depot/projects/ctsrd/cheribsd/src/sys/mips/include/cheri.h#4 (text+ko) ==== @@ -84,13 +84,12 @@ * Special-purpose capability registers that must be preserved on a * user context switch. Note that KT0, KT1, KCC, and KDC are omitted. */ - struct capability cf_udc; struct capability cf_tsc; /* Program counter capability. */ struct capability cf_pcc; }; -CTASSERT(sizeof(struct cp2_frame) == (28 * CAPABILITY_SIZE)); +CTASSERT(sizeof(struct cp2_frame) == (27 * CAPABILITY_SIZE)); #endif /* ==== //depot/projects/ctsrd/cheribsd/src/sys/mips/include/cheriasm.h#3 (text+ko) ==== @@ -119,8 +119,8 @@ SAVE_U_PCB_CP2REG(treg, $c22, CHERI_CR_C22_OFF, base); \ SAVE_U_PCB_CP2REG(treg, $c23, CHERI_CR_C23_OFF, base); \ SAVE_U_PCB_CP2REG(treg, $c24, CHERI_CR_C24_OFF, base); \ - SAVE_U_PCB_CP2REG(treg, $c25, CHERI_CR_UDC_OFF, base); \ - SAVE_U_PCB_CP2REG(treg, $c28, CHERI_CR_TSC_OFF, base) + SAVE_U_PCB_CP2REG(treg, $c28, CHERI_CR_TSC_OFF, base); \ + SAVE_U_PCB_CP2REG(treg, $c31, CHERI_CR_PCC_OFF, base) #define RESTORE_CP2_CONTEXT(treg, base) \ RESTORE_U_PCB_CP2REG(treg, $c25, CHERI_CR_C0_OFF, base); \ @@ -148,7 +148,7 @@ RESTORE_U_PCB_CP2REG(treg, $c22, CHERI_CR_C22_OFF, base); \ RESTORE_U_PCB_CP2REG(treg, $c23, CHERI_CR_C23_OFF, base); \ RESTORE_U_PCB_CP2REG(treg, $c24, CHERI_CR_C24_OFF, base); \ - RESTORE_U_PCB_CP2REG(treg, $c25, CHERI_CR_UDC_OFF, base); \ - RESTORE_U_PCB_CP2REG(treg, $c28, CHERI_CR_TSC_OFF, base) + RESTORE_U_PCB_CP2REG(treg, $c28, CHERI_CR_TSC_OFF, base); \ + RESTORE_U_PCB_CP2REG(treg, $c31, CHERI_CR_PCC_OFF, base) #endif /* _MIPS_INCLUDE_CHERIASM_H_ */ ==== //depot/projects/ctsrd/cheribsd/src/sys/mips/include/cherireg.h#4 (text+ko) ==== @@ -38,34 +38,38 @@ * 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 +#define CHERI_PERM_NON_EPHEMERAL 0x0001 +#define CHERI_PERM_ACCESS_CR31 0x0002 +#define CHERI_PERM_ACCESS_CR30 0x0004 +#define CHERI_PERM_ACCESS_CR29 0x0008 +#define CHERI_PERM_ACCESS_CR28 0x0010 +#define CHERI_PERM_RESERVED1 0x0020 +#define CHERI_PERM_RESERVED2 0x0040 +#define CHERI_PERM_RESERVED3 0x0080 +#define CHERI_PERM_SEAL 0x0100 +#define CHERI_PERM_STORE_EPHEMERAL_CAPABILITY 0x0200 +#define CHERI_PERM_LOAD 0x0400 +#define CHERI_PERM_STORE 0x0800 +#define CHERI_PERM_LOAD_CAP 0x1000 +#define CHERI_PERM_STORE_CAP 0x2000 +#define CHEIR_PERM_EXECUTE 0x4000 /* * 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) +#define CHERI_PERM_PRIV \ + (CHERI_PERM_NON_EPHEMERAL | CHERI_PERM_ACCESS_CR31 | \ + CHERI_PERM_ACCESS_CR30 | CHERI_PERM_ACCESS_CR29 | \ + CHERI_PERM_ACCESS_CR28 | CHERI_PERM_SEAL | \ + CHERI_PERM_STORE_EPHEMERAL_CAPABILITY | CHERI_PERM_LOAD | \ + CHERI_PERM_STORE | CHERI_PERM_LOAD_CAP | CHERI_PERM_STORE_CAP | \ + CHEIR_PERM_EXECUTE) + +#define CHERI_PERM_USER \ + (CHERI_PERM_NON_EPHEMERAL | CHERI_PERM_SEAL | \ + CHERI_PERM_STORE_EPHEMERAL_CAPABILITY | CHERI_PERM_LOAD | \ + CHERI_PERM_STORE | CHERI_PERM_LOAD_CAP | CHERI_PERM_STORE_CAP | \ + CHEIR_PERM_EXECUTE) /* * Definition for kernel "privileged" capability able to name the entire @@ -73,7 +77,7 @@ * * XXXRW: Perhaps CHERI_UCAP_UNPRIV_LENGTH should actually just cover useg. */ -#define CHERI_CAP_PRIV_UPERMS CHERI_PERM_ALL +#define CHERI_CAP_PRIV_UPERMS CHERI_PERM_PRIV #define CHERI_CAP_PRIV_OTYPE 0x0 #define CHERI_CAP_PRIV_BASE 0x0 #define CHERI_CAP_PRIV_LENGTH 0xffffffffffffffff @@ -82,7 +86,7 @@ * Definition for userspace "unprivileged" capability able to name the user * portion of the address space. */ -#define CHERI_CAP_USER_UPERMS CHERI_PERM_ALL +#define CHERI_CAP_USER_UPERMS CHERI_PERM_USER #define CHERI_CAP_USER_OTYPE 0x0 #define CHERI_CAP_USER_BASE MIPS_XUSEG_START #define CHERI_CAP_USER_LENGTH (MIPS_XUSEG_END - MIPS_XUSEG_START) @@ -125,7 +129,7 @@ #define CHERI_CR_C22 22 #define CHERI_CR_C23 23 #define CHERI_CR_C24 24 -#define CHERI_CR_UDC 25 /* SC0: user data capability. */ +#define CHERI_CR_UDC 25 /* UDC: user data capability (saved C0). */ #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. */ @@ -164,8 +168,7 @@ #define CHERI_CR_C22_OFF 22 #define CHERI_CR_C23_OFF 23 #define CHERI_CR_C24_OFF 24 -#define CHERI_CR_UDC_OFF 25 -#define CHERI_CR_TSC_OFF 26 -#define CHERI_CR_PC_OFF 27 +#define CHERI_CR_TSC_OFF 25 +#define CHERI_CR_PCC_OFF 26 #endif /* _MIPS_INCLUDE_CHERIREG_H_ */