Add page table cap store checking
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
};
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user