summaryrefslogtreecommitdiff
path: root/cheri
diff options
context:
space:
mode:
Diffstat (limited to 'cheri')
-rw-r--r--cheri/cheri_insts.sail91
-rw-r--r--cheri/cheri_prelude.sail170
2 files changed, 261 insertions, 0 deletions
diff --git a/cheri/cheri_insts.sail b/cheri/cheri_insts.sail
new file mode 100644
index 00000000..7b9e555f
--- /dev/null
+++ b/cheri/cheri_insts.sail
@@ -0,0 +1,91 @@
+(* Operations that extract parts of a capability into GPR *)
+
+union ast member (CGetXOp, regno, regno) CGetX
+function clause decode (0b010010 : 0b00000 : (regno) rd : (regno) cb : 0b00000000 : 0b000) = Some(CGetX(CGetPerm, rd, cb))
+function clause decode (0b010010 : 0b00000 : (regno) rd : (regno) cb : 0b00000000 : 0b001) = Some(CGetX(CGetType, rd, cb))
+function clause decode (0b010010 : 0b00000 : (regno) rd : (regno) cb : 0b00000000 : 0b010) = Some(CGetX(CGetBase, rd, cb))
+function clause decode (0b010010 : 0b00000 : (regno) rd : (regno) cb : 0b00000000 : 0b011) = Some(CGetX(CGetLen, rd, cb))
+(* NB CGetCause Handled separately *)
+function clause decode (0b010010 : 0b00000 : (regno) rd : (regno) cb : 0b00000000 : 0b101) = Some(CGetX(CGetTag, rd, cb))
+function clause decode (0b010010 : 0b00000 : (regno) rd : (regno) cb : 0b00000000 : 0b110) = Some(CGetX(CGetUnsealed, rd, cb))
+function clause decode (0b010010 : 0b01101 : (regno) rd : (regno) cb : 0b00000000 : 0b010) = Some(CGetX(CGetOffset, rd, cb)) (* NB encoding does not follow pattern *)
+
+function clause execute (CGetX(op, rd, cb)) =
+ {
+ if (register_inaccessible(cb)) then
+ exit (raise_c2_exception_v(cb))
+ else
+ {
+ cbval := CapRegs[cb];
+ wGPR(rd) := switch(op) {
+ case CGetPerm -> EXTZ(cbval[223..193])
+ case CGetType -> EXTZ(cbval.otype)
+ case CGetBase -> cbval.base
+ case CGetOffset -> cbval.cursor
+ case CGetLen -> cbval.length (* XXX only correct for 256-bit *)
+ case CGetTag -> EXTZ([cbval.tag])
+ case CGetUnsealed -> EXTZ([cbval.sealed])
+ }
+ }
+ }
+
+
+union ast member regno CGetPCC
+function clause decode (0b010010 : 0b00000 : 0b00000 : (regno) cd : 0b00000 : 0b000 : 0b111) = Some(CGetPCC(cd))
+function clause execute (CGetPCC(cd)) =
+ {
+ if (register_inaccessible(cd)) then
+ exit (raise_c2_exception_v(cd))
+ else
+ {
+ (CapRegs[cd]).cursor := 0;
+ (*destReg := PCC;*)
+ (*destReg.cursor):= PC; XXX help *)
+ }
+ }
+(* Get and Set CP2 cause register *)
+
+union ast member regno CGetCause
+function clause decode (0b010010 : 0b00000 : (regno) rd : 0b00000 : 0b00000000 : 0b100) = Some(CGetCause(rd))
+function clause execute (CGetCause(rd)) =
+ {
+ if (~(PCC.access_EPCC)) then
+ exit (raise_c2_exception_noreg(CapEx_AccessEPCCViolation))
+ else
+ wGPR(rd) := EXTZ(CapCause)
+ }
+
+union ast member (regno) CSetCause
+function clause decode (0b010010 : 0b00100 : 0b00000 : 0b00000 : (regno) rt : 0b000 : 0b100) = Some(CSetCause(rt))
+function clause execute (CSetCause((regno) rt)) =
+ {
+ if (~(PCC.access_EPCC)) then
+ exit (raise_c2_exception_noreg(CapEx_AccessEPCCViolation))
+ else
+ {
+ (bit[64]) rt_val := rGPR(rt);
+ CapCause.ExcCode := rt_val[15..8];
+ CapCause.RegNum := rt_val[7..0];
+ }
+ }
+
+union ast member (regno, regno, regno) CAndPerm
+function clause decode (0b010010 : 0b00100 : (regno) cd : (regno) cb : (regno) rt : 0b000 : 0b000) = Some(CAndPerm(cd, cb, rt))
+function clause execute(CAndPerm(cd, cb, rt)) =
+{
+ cb_reg := CapRegs[cb];
+ if (register_inaccessible(cd)) then
+ exit (raise_c2_exception_v(cd))
+ else if (register_inaccessible(cb)) then
+ exit (raise_c2_exception_v(cb))
+ else if (~(cb_reg.tag)) then
+ exit (raise_c2_exception(CapEx_TagViolation, cb))
+ else if (~(cb_reg.sealed)) then
+ exit (raise_c2_exception(CapEx_SealViolation, cb))
+ else
+ {
+ (CapRegs[cd]) := cb_reg;
+ (*cd_reg :=*)
+ }
+}
+
diff --git a/cheri/cheri_prelude.sail b/cheri/cheri_prelude.sail
new file mode 100644
index 00000000..ec64ea45
--- /dev/null
+++ b/cheri/cheri_prelude.sail
@@ -0,0 +1,170 @@
+(* 265-bit capability is really 257 bits including tag *)
+typedef Capability = register bits [256:0] {
+ 256: tag;
+ 255..248: reserved; (* padding *)
+ 247..224: otype;
+ 223..208: sw_perms;
+ 207: access_KR2C;
+ 206: access_KR1C;
+ 205: access_KCC;
+ 204: access_KDC;
+ 203: access_EPCC;
+ 202: reserved;
+ 201: permit_set_type;
+ 200: permit_seal;
+ 199: permit_store_ephemeral_cap;
+ 198: permit_store_cap;
+ 197: permit_load_cap;
+ 196: permit_store;
+ 195: permit_load;
+ 194: permit_execute;
+ 193: non_ephemeral;
+ 192: sealed;
+ 191..128: cursor;
+ 127..64: base;
+ 63 .. 0: length;
+}
+
+register Capability PCC
+register Capability C00 (* aka default data capability, DDC *)
+register Capability C01
+register Capability C02
+register Capability C03
+register Capability C04
+register Capability C05
+register Capability C06
+register Capability C07
+register Capability C08
+register Capability C09
+register Capability C10
+register Capability C11
+register Capability C12
+register Capability C13
+register Capability C14
+register Capability C15
+register Capability C16
+register Capability C17
+register Capability C18
+register Capability C19
+register Capability C20
+register Capability C21
+register Capability C22
+register Capability C23
+register Capability C24 (* aka return code capability, RCC *)
+register Capability C25
+register Capability C26 (* aka invoked data capability, IDC *)
+register Capability C27 (* aka kernel reserved capability 1, KR1C *)
+register Capability C28 (* aka kernel reserved capability 2, KR2C *)
+register Capability C29 (* aka kernel code capability, KCC *)
+register Capability C30 (* aka kernel data capability, KDC *)
+register Capability C31 (* aka exception program counter capability, EPCC *)
+
+let (vector <0, 32, inc, (Capability)>) CapRegs =
+ [ C00, C01, C02, C03, C04, C05, C06, C07, C08, C09, C10,
+ C11, C12, C13, C14, C15, C16, C17, C18, C19, C20,
+ C21, C22, C23, C24, C25, C26, C27, C28, C29, C30, C31
+ ]
+
+typedef CapEx = enumerate {
+ CapEx_None;
+ CapEx_LengthVioloation;
+ CapEx_TagViolation;
+ CapEx_SealViolation;
+ CapEx_TypeViolation;
+ CapEx_CallTrap;
+ CapEx_ReturnTrap;
+ CapEx_TSSUnderFlow;
+ CapEx_UserDefViolation;
+ CapEx_TLBNoStoreCap;
+ CapEx_InexactBounds;
+ CapEx_GlobalViolation;
+ CapEx_PermitExecuteViolation;
+ CapEx_PermitLoadViolation;
+ CapEx_PermitStoreViolation;
+ CapEx_PermitLoadCapViolation;
+ CapEx_PermitStoreCapViolation;
+ CapEx_PermitStoreLocalCapViolation;
+ CapEx_PermitSealViolation;
+ CapEx_AccessEPCCViolation;
+ CapEx_AccessKDCViolation;
+ CapEx_AccessKCCViolation;
+ CapEx_AccessKR1CViolation;
+ CapEx_AccessKR2CViolation;
+}
+
+typedef CGetXOp = enumerate {
+ CGetPerm;
+ CGetType;
+ CGetBase;
+ CGetOffset;
+ CGetLen;
+ CGetTag;
+ CGetUnsealed;
+}
+
+
+
+function (bit[8]) CapExCode((CapEx) ex) =
+ switch(ex) {
+ case CapEx_None -> 0x00
+ case CapEx_LengthVioloation -> 0x01
+ case CapEx_TagViolation -> 0x02
+ case CapEx_SealViolation -> 0x03
+ case CapEx_TypeViolation -> 0x04
+ case CapEx_CallTrap -> 0x05
+ case CapEx_ReturnTrap -> 0x06
+ case CapEx_TSSUnderFlow -> 0x07
+ case CapEx_UserDefViolation -> 0x08
+ case CapEx_TLBNoStoreCap -> 0x09
+ case CapEx_InexactBounds -> 0x0a
+ case CapEx_GlobalViolation -> 0x10
+ case CapEx_PermitExecuteViolation -> 0x11
+ case CapEx_PermitLoadViolation -> 0x12
+ case CapEx_PermitStoreViolation -> 0x13
+ case CapEx_PermitLoadCapViolation -> 0x14
+ case CapEx_PermitStoreCapViolation -> 0x15
+ case CapEx_PermitStoreLocalCapViolation -> 0x16
+ case CapEx_PermitSealViolation -> 0x17
+ case CapEx_AccessEPCCViolation -> 0x1a
+ case CapEx_AccessKDCViolation -> 0x1b
+ case CapEx_AccessKCCViolation -> 0x1c
+ case CapEx_AccessKR1CViolation -> 0x1d
+ case CapEx_AccessKR2CViolation -> 0x1e
+ }
+
+typedef CapCauseReg = register bits [15:0] {
+ 15..8: ExcCode;
+ 7..0: RegNum;
+}
+
+register CapCauseReg CapCause
+
+function unit raise_c2_exception((CapEx) capEx, (bit[8]) regnum) =
+ {
+ (CapCause.ExcCode) := CapExCode(capEx);
+ (CapCause.RegNum) := regnum;
+ SignalException(C2E);
+ }
+
+function unit raise_c2_exception_v((bit[8]) regnum) =
+ switch(regnum[4..0]) {
+ case 0b11011 -> raise_c2_exception(CapEx_AccessKR1CViolation, regnum)
+ case 0b11100 -> raise_c2_exception(CapEx_AccessKR2CViolation, regnum)
+ case 0b11101 -> raise_c2_exception(CapEx_AccessKCCViolation, regnum)
+ case 0b11110 -> raise_c2_exception(CapEx_AccessKDCViolation, regnum)
+ case 0b11111 -> raise_c2_exception(CapEx_AccessEPCCViolation, regnum)
+ case _ -> assert(false, Some("should only call for cap reg violation"))
+ }
+
+function unit raise_c2_exception_noreg((CapEx) capEx) =
+ raise_c2_exception(capEx, 0xff)
+
+function bool register_inaccessible((regno) r) =
+ ~(switch(r) {
+ case 0b11011 -> (PCC.access_KR1C)
+ case 0b11100 -> (PCC.access_KR2C)
+ case 0b11101 -> (PCC.access_KCC)
+ case 0b11110 -> (PCC.access_KDC)
+ case 0b11111 -> (PCC.access_EPCC)
+ case _ -> bitone
+ })