Add page table cap store checking

This commit is contained in:
Peter Rugg
2020-07-21 16:02:37 +01:00
parent a74596c956
commit 0040b05ada
6 changed files with 69 additions and 26 deletions

View File

@@ -108,6 +108,7 @@ typedef struct {
ByteEn store_data_BE;
`endif
Bool misaligned;
Bool capStore;
Maybe#(CSR_XCapCause) capException;
Maybe#(BoundsCheck) check;
} MemExeToFinish deriving(Bits, FShow);
@@ -158,7 +159,8 @@ module mkDTlbSynth(DTlbSynth);
write: (case(x.mem_func)
St, Sc, Amo: True;
default: False;
endcase)
endcase),
cap: x.capStore
};
endfunction
let m <- mkDTlb(getTlbReq);
@@ -522,6 +524,7 @@ module mkMemExePipeline#(MemExeInput inIfc)(MemExePipeline);
store_data_BE: origBE,
`endif
misaligned: memAddrMisaligned(getAddr(vaddr), origBE),
capStore: isValidCap(data) && pack(origBE) == ~0,
capException: capChecksMem(x.rVal1, x.rVal2, x.cap_checks, x.mem_func, origBE),
check: prepareBoundsCheck(x.rVal1, x.rVal2, almightyCap/*ToDo: pcc*/,
ddc, getAddr(vaddr), pack(countOnes(pack(origBE))), x.cap_checks)

View File

@@ -271,11 +271,14 @@ module mkDTlb#(
end
else if(pRs.entry matches tagged Valid .en) begin
// check permission
if(hasVMPermission(vm_info,
en.pteType,
en.ppn,
en.level,
r.write ? DataStore : DataLoad)) begin
let permCheck = hasVMPermission(vm_info,
en.pteType,
en.pteUpperType,
en.ppn,
en.level,
r.write ? DataStore : DataLoad,
r.cap);
if (permCheck.allowed) begin
// fill TLB, and record resp
tlb.addEntry(en);
let trans_addr = translate(r.addr, en.ppn, en.level);
@@ -287,7 +290,7 @@ module mkDTlb#(
end
else begin
// page fault
Exception fault = r.write ? StorePageFault : LoadPageFault;
Exception fault = permCheck.excCode;
pendResp[idx] <= tuple2(?, Valid (fault));
if(verbose) begin
$display("[DTLB] refill no permission: idx %d; ", idx, fshow(r));
@@ -448,11 +451,14 @@ module mkDTlb#(
// TLB hit
let entry = trans_result.entry;
// check permission
if (hasVMPermission(vm_info,
entry.pteType,
entry.ppn,
entry.level,
r.write ? DataStore : DataLoad)) begin
let permCheck = hasVMPermission(vm_info,
entry.pteType,
entry.pteUpperType,
entry.ppn,
entry.level,
r.write ? DataStore : DataLoad,
r.cap);
if (permCheck.allowed) begin
// update TLB replacement info
tlb.updateRepByHit(trans_result.index);
// translate addr
@@ -472,7 +478,7 @@ module mkDTlb#(
end
else begin
// page fault
Exception fault = r.write ? StorePageFault : LoadPageFault;
Exception fault = permCheck.excCode;
pendWait[idx] <= None;
pendResp[idx] <= tuple2(?, Valid (fault));
if(verbose) $display("[DTLB] req no permission: idx %d; ", idx, fshow(r));

View File

@@ -176,9 +176,11 @@ module mkITlb(ITlb::ITlb);
// check permission
if(hasVMPermission(vm_info,
en.pteType,
en.pteUpperType,
en.ppn,
en.level,
InstFetch)) begin
InstFetch,
False).allowed) begin
// fill TLB and resp to proc
tlb.addEntry(en);
let trans_addr = translate(vaddr, en.ppn, en.level);
@@ -285,9 +287,11 @@ module mkITlb(ITlb::ITlb);
// check permission
if(hasVMPermission(vm_info,
entry.pteType,
entry.pteUpperType,
entry.ppn,
entry.level,
InstFetch)) begin
InstFetch,
False).allowed) begin
// update replacement info
tlb.updateRepByHit(trans_result.index);
// translate addr

View File

@@ -653,6 +653,7 @@ module mkL2Tlb(L2Tlb::L2Tlb);
vpn: masked_vpn,
ppn: masked_ppn,
pteType: pte.pteType,
pteUpperType: pte.pteUpperType,
level: walkLevel,
asid: vm_info.asid
};

View File

@@ -393,6 +393,8 @@ typedef enum {
InstPageFault = 5'd12,
LoadPageFault = 5'd13,
StorePageFault = 5'd15,
LoadCapPageFault = 5'd26,
StoreCapPageFault = 5'd27,
CHERIFault = 5'd28
} Exception deriving(Bits, Eq, FShow);

View File

@@ -31,6 +31,7 @@ import ProcTypes::*;
typedef struct{
Addr addr;
Bool write;
Bool cap;
} TlbReq deriving(Eq, Bits, FShow);
typedef Tuple2#(Addr, Maybe#(Exception)) TlbResp;
@@ -66,7 +67,13 @@ typedef struct {
} PTEType deriving (Bits, Eq, FShow);
typedef struct {
Bit#(10) reserved;
Bool cap_writable;
Bool cap_readable;
} PTEUpperType deriving (Bits, Eq, FShow);
typedef struct {
PTEUpperType pteUpperType;
Bit#(8) reserved;
Ppn ppn;
Bit#(2) reserved_sw; // reserved for supervisor software
PTEType pteType;
@@ -78,6 +85,7 @@ typedef struct {
Vpn vpn;
Ppn ppn;
PTEType pteType;
PTEUpperType pteUpperType;
PageWalkLevel level;
Asid asid;
} TlbEntry deriving (Bits, Eq, FShow);
@@ -169,10 +177,16 @@ typedef enum {
DataStore // also contain DataLoad
} TlbAccessType deriving(Bits, Eq, FShow);
function Bool hasVMPermission(
typedef struct {
Bool allowed;
Exception excCode; // Only defined if !allowed
} TlbPermissionCheck deriving(Bits, Eq, FShow);
function TlbPermissionCheck hasVMPermission(
VMInfo vm_info,
PTEType pte_type, Ppn ppn, PageWalkLevel level,
TlbAccessType access
PTEType pte_type, PTEUpperType pte_upper_type,
Ppn ppn, PageWalkLevel level,
TlbAccessType access, Bool cap
);
// try to find any page fault
Bool fault = False;
@@ -229,13 +243,26 @@ function Bool hasVMPermission(
end
endcase
// check if accessed or dirty bit needs to be set
if(!pte_type.accessed) begin
fault = True;
end
if(access == DataStore && !pte_type.dirty) begin
fault = True;
TlbPermissionCheck ret = TlbPermissionCheck {
allowed: !fault,
excCode: access == DataStore ? StorePageFault : LoadPageFault};
if (!fault) begin
if (cap && access == DataStore && !pte_upper_type.cap_writable) begin
ret.allowed = False;
ret.excCode = StoreCapPageFault;
end else begin
// check if accessed or dirty bit needs to be set
if(!pte_type.accessed) begin
ret.allowed = False;
ret.excCode = access == DataStore ? StorePageFault : LoadPageFault;
end
if(access == DataStore && !pte_type.dirty) begin
ret.allowed = False;
ret.excCode = access == DataStore ? StorePageFault : LoadPageFault;
end
end
end
return !fault;
return ret;
endfunction