diff options
| -rw-r--r-- | cheri/Makefile | 2 | ||||
| -rw-r--r-- | cheri/cheri_insts.sail | 81 | ||||
| -rw-r--r-- | cheri/cheri_prelude_common.sail | 11 | ||||
| -rw-r--r-- | mips/mips_prelude.sail | 12 | ||||
| -rw-r--r-- | mips/mips_tlb.sail | 10 |
5 files changed, 106 insertions, 10 deletions
diff --git a/cheri/Makefile b/cheri/Makefile index 663c8763..fd8a22a9 100644 --- a/cheri/Makefile +++ b/cheri/Makefile @@ -107,4 +107,6 @@ extract: cheri_insts.sail $(call EXTRACT_INST,CStore) $(call EXTRACT_INST,CSC) $(call EXTRACT_INST,CLC) + $(call EXTRACT_INST,CReadHwr) + $(call EXTRACT_INST,CWriteHwr) diff --git a/cheri/cheri_insts.sail b/cheri/cheri_insts.sail index a1ddc8aa..fb3b370d 100644 --- a/cheri/cheri_insts.sail +++ b/cheri/cheri_insts.sail @@ -100,6 +100,9 @@ function clause decode (0b010010 @ 0b00000 @ rd : regno @ cb : regno @ 0b0010 function clause decode (0b010010 @ 0b00000 @ rd : regno @ cb : regno @ 0b00110 @ 0b111111) = Some(CGetOffset(rd, cb)) function clause decode (0b010010 @ 0b00000 @ cd : regno @ rs : regno @ 0b00111 @ 0b111111) = Some(CGetPCCSetOffset(cd, rs)) +function clause decode (0b010010 @ 0b00000 @ cd : regno @ sel : regno @ 0b01101 @ 0b111111) = Some(CReadHwr(cd, sel)) +function clause decode (0b010010 @ 0b00000 @ cb : regno @ sel : regno @ 0b01110 @ 0b111111) = Some(CWriteHwr(cb, sel)) + /* Three operand */ /* Capability Modification */ @@ -345,6 +348,84 @@ function clause execute (CSetCause(rt)) = /* END_CSetCause */ } +union clause ast = CReadHwr : (regno, regno) +function clause execute (CReadHwr(cd, sel)) = +{ + /* START_CReadHwr */ + checkCP2usable(); + let (needSup, needAccessSys) : (bool, bool) = match unsigned(sel) { + 0 => (false, false), /* DDC -- no access control */ + 1 => (false, false), /* CTLSU -- no access control */ + 8 => (false, true), /* CTLSP -- privileged TLS */ + 22 => (true, false), /* KR1C */ + 23 => (true, false), /* KR2C */ + 29 => (true, true), /* KCC */ + 30 => (true, true), /* KDC */ + 31 => (true, true), /* EPCC */ + _ => SignalException(ResI) + }; + if register_inaccessible(cd) then + raise_c2_exception(CapEx_AccessSystemRegsViolation, cd) + else if needAccessSys & not(pcc_access_system_regs()) then + raise_c2_exception(CapEx_AccessSystemRegsViolation, sel) + else if needSup & not(grantsAccess(getAccessLevel(), Supervisor)) then + raise_c2_exception(CapEx_AccessSystemRegsViolation, sel) + else { + capVal : CapStruct = match unsigned(sel) { + 0 => readCapReg(DDC), + 1 => capRegToCapStruct(CTLSU), + 8 => capRegToCapStruct(CTLSP), + 22 => readCapReg(KR1C), + 23 => readCapReg(KR2C), + 29 => readCapReg(KCC), + 30 => readCapReg(KDC), + 31 => readCapReg(EPCC), + _ => {assert(false, "should be unreachable code"); undefined} + }; + writeCapReg(cd, capVal); + }; + /* END_CReadHwr */ +} + +union clause ast = CWriteHwr : (regno, regno) +function clause execute (CWriteHwr(cb, sel)) = +{ + /* START_CWriteHwr */ + checkCP2usable(); + let (needSup, needAccessSys) : (bool, bool) = match unsigned(sel) { + 0 => (false, false), /* DDC -- no access control */ + 1 => (false, false), /* CTLSU -- no access control */ + 8 => (false, true), /* CTLSP -- privileged TLS */ + 22 => (true, false), /* KR1C */ + 23 => (true, false), /* KR2C */ + 29 => (true, true), /* KCC */ + 30 => (true, true), /* KDC */ + 31 => (true, true), /* EPCC */ + _ => SignalException(ResI) + }; + if register_inaccessible(cb) then + raise_c2_exception(CapEx_AccessSystemRegsViolation, cb) + else if needAccessSys & not(pcc_access_system_regs()) then + raise_c2_exception(CapEx_AccessSystemRegsViolation, sel) + else if needSup & not(grantsAccess(getAccessLevel(), Supervisor)) then + raise_c2_exception(CapEx_AccessSystemRegsViolation, sel) + else { + capVal = readCapReg(cb); + match unsigned(sel) { + 0 => writeCapReg(DDC, capVal), + 1 => CTLSU = capStructToCapReg(capVal), + 8 => CTLSP = capStructToCapReg(capVal), + 22 => writeCapReg(KR1C, capVal), + 23 => writeCapReg(KR2C, capVal), + 29 => writeCapReg(KCC, capVal), + 30 => writeCapReg(KDC, capVal), + 31 => writeCapReg(EPCC, capVal), + _ => assert(false, "should be unreachable code") + }; + }; + /* END_CWriteHwr */ +} + union clause ast = CAndPerm : (regno, regno, regno) function clause execute(CAndPerm(cd, cb, rt)) = { diff --git a/cheri/cheri_prelude_common.sail b/cheri/cheri_prelude_common.sail index 9c51966b..c2fb9c24 100644 --- a/cheri/cheri_prelude_common.sail +++ b/cheri/cheri_prelude_common.sail @@ -78,7 +78,16 @@ register C29 : CapReg /* aka kernel code capability, KCC */ register C30 : CapReg /* aka kernel data capability, KDC */ register C31 : CapReg /* aka exception program counter capability, EPCC */ -let IDC : regno = 0b11010 /* 26 */ +register CTLSU : CapReg /* User thread local storage capabiltiy */ +register CTLSP : CapReg /* Privileged thread local storage capabiltiy */ + +let DDC : regno = 0b00000 /* C0 */ +let IDC : regno = 0b11010 /* C26 */ +let KR1C : regno = 0b11011 /* C27 */ +let KR2C : regno = 0b11100 /* C28 */ +let KCC : regno = 0b11101 /* C29 */ +let KDC : regno = 0b11110 /* C30 */ +let EPCC : regno = 0b11111 /* C31 */ let CapRegs : vector(32, dec, register(CapReg)) = [ diff --git a/mips/mips_prelude.sail b/mips/mips_prelude.sail index 3c3c45f4..9e81a5d0 100644 --- a/mips/mips_prelude.sail +++ b/mips/mips_prelude.sail @@ -461,6 +461,18 @@ function SignalExceptionTLB(ex, badAddr) = { enum MemAccessType = {Instruction, LoadData, StoreData} enum AccessLevel = {User, Supervisor, Kernel} +val int_of_AccessLevel : AccessLevel -> int effect pure +function int_of_AccessLevel level = + match level { + User => 0, + Supervisor => 1, + Kernel => 2 + } + +val grantsAccess : (AccessLevel, AccessLevel) -> bool +function grantsAccess (currentLevel, requiredLevel) = + int_of_AccessLevel(currentLevel) >= int_of_AccessLevel(requiredLevel) + function getAccessLevel() : unit -> AccessLevel= if ((CP0Status.EXL()) | (CP0Status.ERL())) then Kernel diff --git a/mips/mips_tlb.sail b/mips/mips_tlb.sail index 6313c001..a8bb819e 100644 --- a/mips/mips_tlb.sail +++ b/mips/mips_tlb.sail @@ -100,14 +100,6 @@ function TLBTranslate2 (vAddr, accessType) = { } } -val cast_AccessLevel : AccessLevel -> int effect pure -function cast_AccessLevel level = - match level { - User => 0, - Supervisor => 1, - Kernel => 2 - } - /* perform TLB translation. bool is CHERI specific TLB bits noStoreCap/suppressTag */ val TLBTranslateC : (bits(64), MemAccessType) -> (bits(64), bool) effect {escape, rreg, undef, wreg} function TLBTranslateC (vAddr, accessType) = @@ -126,7 +118,7 @@ function TLBTranslateC (vAddr, accessType) = 0b01 => (Supervisor, None() : option(bits(64))), /* xsseg - supervisor mapped */ 0b00 => (User, None() : option(bits(64))) /* xuseg - user mapped */ } in - if (cast_AccessLevel(currentAccessLevel) < cast_AccessLevel(requiredLevel)) then + if not(grantsAccess(currentAccessLevel, requiredLevel)) then SignalExceptionBadAddr(if (accessType == StoreData) then AdES else AdEL, vAddr) else let (pa, c) : (bits(64), bool) = match addr { |
