Skip to content

Commit 3b4eecf

Browse files
committed
Initial implementation of cap PTE bits
1 parent 9e451f2 commit 3b4eecf

File tree

3 files changed

+45
-17
lines changed

3 files changed

+45
-17
lines changed

src_Core/ISA/ISA_Decls_Priv_S.bsv

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -270,7 +270,8 @@ Integer pte_U_offset = 4; // Accessible-to-user-mode
270270
Integer pte_G_offset = 5; // Global mapping
271271
Integer pte_A_offset = 6; // Accessed
272272
Integer pte_D_offset = 7; // Dirty
273-
Integer pte_RSW_offset = 8; // Reserved for supervisor SW
273+
Integer pte_cap_W_offset = 8;
274+
Integer pte_cap_R_offset = 9;
274275

275276
`ifdef RV32
276277
Integer pte_PPN_0_offset = 10;
@@ -313,6 +314,14 @@ function Bit #(1) fn_PTE_to_D (PTE pte);
313314
return pte [pte_D_offset];
314315
endfunction
315316

317+
function Bit #(1) fn_PTE_to_cap_W (PTE pte);
318+
return pte [pte_cap_W_offset];
319+
endfunction
320+
321+
function Bit #(1) fn_PTE_to_cap_R (PTE pte);
322+
return pte [pte_cap_R_offset];
323+
endfunction
324+
316325
function PPN fn_PTE_to_PPN (PTE pte);
317326
return pte [ppn_sz + pte_PPN_0_offset - 1 : pte_PPN_0_offset];
318327
endfunction
@@ -355,6 +364,7 @@ endfunction
355364

356365
function Bool is_pte_denial (Bool dmem_not_imem, // load-store or fetch?
357366
Bool read_not_write,
367+
Bool capability,
358368
Priv_Mode priv,
359369
Bit #(1) sstatus_SUM,
360370
Bit #(1) mstatus_MXR,
@@ -365,21 +375,28 @@ function Bool is_pte_denial (Bool dmem_not_imem, // load-store or f
365375
let pte_w = fn_PTE_to_W (pte);
366376
let pte_r = fn_PTE_to_R (pte);
367377

378+
let pte_cap_w = fn_PTE_to_cap_W(pte);
379+
// pte_cap_r would not cause a denial
380+
368381
Bool priv_deny = ( ((priv == u_Priv_Mode) && (pte_u == 1'b0))
369382
|| ((priv == s_Priv_Mode) && (pte_u == 1'b1) && (sstatus_SUM == 1'b0)));
370383

371384
Bool access_fetch = ((! dmem_not_imem) && read_not_write);
372385
Bool access_load = (dmem_not_imem && read_not_write);
373386
Bool access_store = (dmem_not_imem && (! read_not_write));
387+
Bool access_cap = (dmem_not_imem && capability);
374388

375389
let pte_r_mxr = (pte_r | (mstatus_MXR & pte_x));
376390

377391
Bool access_ok = ( (access_fetch && (pte_x == 1'b1))
378392
|| (access_load && (pte_r_mxr == 1'b1))
379393
|| (access_store && (pte_w == 1'b1)));
380394

381-
382-
return (priv_deny || (! access_ok));
395+
Bool access_cap_ok = (! capability)
396+
|| (access_load)
397+
|| (access_store && (pte_cap_w == 1'b1));
398+
399+
return (priv_deny || (! access_ok) || (! access_cap_ok));
383400
endfunction
384401

385402
// ----------------

src_Core/Near_Mem_VM/MMU_Cache.bsv

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -526,6 +526,7 @@ module mkMMU_Cache #(parameter Bool dmem_not_imem,
526526
`endif
527527
Reg #(WordXL) rg_addr <- mkRegU; // VA or PA
528528
Reg #(Tuple2#(Bool, Bit #(128))) rg_st_amo_val <- mkRegU; // Store-value for ST, SC, AMO
529+
Reg #(Bool) rg_allow_cap <- mkRegU; // Whether load result is allowed to be tagged by VM page bits
529530

530531
// The following are needed for VM
531532
`ifdef ISA_PRIV_S
@@ -583,9 +584,9 @@ module mkMMU_Cache #(parameter Bool dmem_not_imem,
583584
Reg #(Bool) dw_exc <- mkDWire (False);
584585
Reg #(Exc_Code) rg_exc_code <- mkRegU;
585586
Reg #(Exc_Code) dw_exc_code <- mkDWire (?);
586-
Reg #(Tuple2#(Bool, Bit#(128))) rg_ld_val <- mkRegU; // Load-value for LOAD/LR/AMO, success/fail for SC
587-
Reg #(Tuple2#(Bool, Bit#(128))) dw_output_ld_val <- mkDWire (?);
588-
Reg #(Tuple2#(Bool, Bit#(128))) dw_output_st_amo_val <- mkDWire (?); // stored value for ST, SC, AMO (for verification only)
587+
Reg #(Tuple2#(Bool, Bit#(128))) rg_ld_val <- mkReg(tuple2(False, ?)); // Load-value for LOAD/LR/AMO, success/fail for SC
588+
Reg #(Tuple2#(Bool, Bit#(128))) dw_output_ld_val <- mkDWire (tuple2(False, ?));
589+
Reg #(Tuple2#(Bool, Bit#(128))) dw_output_st_amo_val <- mkDWire (tuple2(False, ?)); // stored value for ST, SC, AMO (for verification only)
589590

590591
// This reg is used during PTWs
591592
Reg #(PA) rg_pte_pa <- mkRegU;
@@ -685,11 +686,13 @@ module mkMMU_Cache #(parameter Bool dmem_not_imem,
685686
// Functions to drive read-responses (outputs)
686687

687688
// Memory-read responses
688-
function Action fa_drive_mem_rsp (Bit #(3) width_code, Bool is_unsigned, Addr addr, Cache_Entry ld_val, Cache_Entry st_amo_val, Bool commit);
689+
function Action fa_drive_mem_rsp (Bit #(3) width_code, Bool is_unsigned, Addr addr, Cache_Entry ld_val, Cache_Entry st_amo_val, Bool allow_cap, Bool commit);
689690
action
690691
dw_valid <= commit;
691692
// Value loaded into rd (LOAD, LR, AMO, SC success/fail result)
692-
dw_output_ld_val <= fn_extract_and_extend_bytes (width_code, is_unsigned, addr, ld_val);
693+
let extracted = fn_extract_and_extend_bytes (width_code, is_unsigned, addr, ld_val);
694+
if (!allow_cap) extracted = tuple2(False, tpl_2(extracted));
695+
dw_output_ld_val <= extracted;
693696
// Value stored into mem (STORE, SC, AMO final value stored)
694697
dw_output_st_amo_val <= tuple2(tpl_1(st_amo_val)[(valueOf(CLEN) == 64 && addr[4:0] == 0) ? 1 : 0] == 1'b1, tpl_2(st_amo_val));
695698
if (cfg_verbosity > 1)
@@ -699,10 +702,11 @@ module mkMMU_Cache #(parameter Bool dmem_not_imem,
699702
endfunction
700703

701704
// IO-read responses
702-
function Action fa_drive_IO_read_rsp (Bit #(3) width_code, Bool is_unsigned, Addr addr, Tuple2#(Bool, Bit #(128)) ld_val);
705+
function Action fa_drive_IO_read_rsp (Bit #(3) width_code, Bool is_unsigned, Addr addr, Tuple2#(Bool, Bit #(128)) ld_val, Bool allow_cap);
703706
action
704707
dw_valid <= True;
705708
// Value loaded into rd (LOAD, LR, AMO, SC success/fail result)
709+
if (!allow_cap) ld_val = tuple2(False, tpl_2(ld_val));
706710
dw_output_ld_val <= ld_val;
707711
if (cfg_verbosity > 1)
708712
$display ("%0d: %s.drive_IO_read_rsp: addr 0x%0h ld_val 0x%0h", cur_cycle, d_or_i, addr, ld_val);
@@ -936,6 +940,7 @@ module mkMMU_Cache #(parameter Bool dmem_not_imem,
936940
tlb_result,
937941
dmem_not_imem,
938942
((rg_op == CACHE_LD) || is_AMO_LR),
943+
tpl_1(rg_st_amo_val),
939944
rg_priv,
940945
rg_sstatus_SUM,
941946
rg_mstatus_MXR);
@@ -967,6 +972,7 @@ module mkMMU_Cache #(parameter Bool dmem_not_imem,
967972
`endif
968973

969974
rg_pa <= vm_xlate_result.pa;
975+
rg_allow_cap <= vm_xlate_result.allow_cap;
970976
let is_mem_addr = soc_map.m_is_mem_addr (fn_PA_to_Fabric_Addr (vm_xlate_result.pa));
971977

972978
// Access to non-memory
@@ -989,7 +995,7 @@ module mkMMU_Cache #(parameter Bool dmem_not_imem,
989995
if ((rg_op == CACHE_LD) || is_AMO_LR || (! dmem_not_imem)) begin
990996
if (hit) begin
991997
// Cache hit; drive response
992-
fa_drive_mem_rsp (rg_width_code, rg_is_unsigned, rg_addr, word128, unpack(0), dw_commit);
998+
fa_drive_mem_rsp (rg_width_code, rg_is_unsigned, rg_addr, word128, unpack(0), vm_xlate_result.allow_cap, dw_commit);
993999

9941000
`ifdef ISA_A
9951001
if (is_AMO_LR) begin
@@ -1091,7 +1097,7 @@ module mkMMU_Cache #(parameter Bool dmem_not_imem,
10911097
else begin // do_write == False
10921098
// SC fail
10931099
// Hard-code address to 0 to ensure fn_extract_and_extend_bytes takes the LSBs of our 1 value.
1094-
fa_drive_mem_rsp (rg_width_code, rg_is_unsigned, 0, tuple2(0,1), unpack(0), dw_commit);
1100+
fa_drive_mem_rsp (rg_width_code, rg_is_unsigned, 0, tuple2(0,1), unpack(0), False, dw_commit);
10951101
if (cfg_verbosity > 1)
10961102
$display (" AMO SC: Fail response for addr 0x%0h", rg_addr);
10971103
end
@@ -1635,7 +1641,9 @@ module mkMMU_Cache #(parameter Bool dmem_not_imem,
16351641

16361642
rule rl_ST_AMO_response (rg_state == CACHE_ST_AMO_RSP && dmem_not_imem);
16371643
dw_valid <= True;
1638-
dw_output_ld_val <= rg_ld_val; // Irrelevant for ST; relevant for SC, AMO
1644+
let ld_val = rg_ld_val;
1645+
if (!rg_allow_cap) ld_val = tuple2(False, tpl_2(ld_val));
1646+
dw_output_ld_val <= ld_val; // Irrelevant for ST; relevant for SC, AMO
16391647
dw_output_st_amo_val <= rg_st_amo_val;
16401648
endrule
16411649

@@ -1687,7 +1695,7 @@ module mkMMU_Cache #(parameter Bool dmem_not_imem,
16871695

16881696
// Successful read
16891697
if (rd_data.rresp == OKAY) begin
1690-
fa_drive_IO_read_rsp (rg_width_code, rg_is_unsigned, rg_addr, ld_val);
1698+
fa_drive_IO_read_rsp (rg_width_code, rg_is_unsigned, rg_addr, ld_val, rg_allow_cap);
16911699
rg_state <= IO_READ_RSP;
16921700
end
16931701

@@ -1705,7 +1713,7 @@ module mkMMU_Cache #(parameter Bool dmem_not_imem,
17051713
rg_lower_word64 <= rd_data.rdata;
17061714
end else begin // rg_lower_word64_full && rd_data.rlast
17071715
if (rd_data.rresp == OKAY) begin
1708-
fa_drive_IO_read_rsp(rg_width_code, rg_is_unsigned, rg_addr, tuple2(False, {rd_data.rdata, rg_lower_word64})); // No tags from IO mem
1716+
fa_drive_IO_read_rsp(rg_width_code, rg_is_unsigned, rg_addr, tuple2(False, {rd_data.rdata, rg_lower_word64}), rg_allow_cap); // No tags from IO mem
17091717
rg_ld_val <= tuple2(False, {rd_data.rdata, rg_lower_word64});
17101718
rg_lower_word64_full <= False;
17111719
end else begin
@@ -1724,7 +1732,7 @@ module mkMMU_Cache #(parameter Bool dmem_not_imem,
17241732
// Stays in this state until CPU's next request puts it back into RUNNING state
17251733

17261734
rule rl_maintain_io_read_rsp (!resetting && rg_state == IO_READ_RSP && dmem_not_imem);
1727-
fa_drive_IO_read_rsp (rg_width_code, rg_is_unsigned, rg_addr, rg_ld_val);
1735+
fa_drive_IO_read_rsp (rg_width_code, rg_is_unsigned, rg_addr, rg_ld_val, rg_allow_cap);
17281736
endrule
17291737

17301738
// ----------------------------------------------------------------
@@ -1838,7 +1846,7 @@ module mkMMU_Cache #(parameter Bool dmem_not_imem,
18381846
// Write back new st_val to fabric
18391847
fa_fabric_send_write_req (rg_width_code, rg_pa, new_st_val);
18401848

1841-
fa_drive_IO_read_rsp (rg_width_code, rg_is_unsigned, rg_addr, new_ld_val);
1849+
fa_drive_IO_read_rsp (rg_width_code, rg_is_unsigned, rg_addr, new_ld_val, rg_allow_cap);
18421850
rg_ld_val <= new_ld_val;
18431851
rg_state <= IO_READ_RSP;
18441852

src_Core/Near_Mem_VM/TLB.bsv

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -351,6 +351,7 @@ deriving (Bits, Eq, FShow);
351351

352352
typedef struct {
353353
VM_Xlate_Outcome outcome;
354+
Bool allow_cap; // whether we will be allowed to load a cap
354355
PA pa; // phys addr, if VM_XLATE_OK
355356
Exc_Code exc_code; // if VM_XLATE_EXC
356357
Bool pte_modified; // if VM_XLATE_OK and pte's A or D bits were modified
@@ -363,6 +364,7 @@ function ActionValue #(VM_Xlate_Result) fav_vm_xlate (WordXL addr,
363364
TLB_Lookup_Result tlb_result,
364365
Bool dmem_not_imem,
365366
Bool read_not_write,
367+
Bool capability,
366368
Priv_Mode priv,
367369
Bit #(1) sstatus_SUM,
368370
Bit #(1) mstatus_MXR);
@@ -385,7 +387,7 @@ function ActionValue #(VM_Xlate_Result) fav_vm_xlate (WordXL addr,
385387

386388
if (xlate) begin
387389
if (tlb_result.hit) begin
388-
Bool deny = is_pte_denial (dmem_not_imem, read_not_write, priv, sstatus_SUM, mstatus_MXR, pte);
390+
Bool deny = is_pte_denial (dmem_not_imem, read_not_write, capability, priv, sstatus_SUM, mstatus_MXR, pte);
389391
if (deny) begin
390392
outcome = VM_XLATE_EXCEPTION;
391393
exc_code = fn_page_fault_exc_code (dmem_not_imem, read_not_write);
@@ -434,6 +436,7 @@ function ActionValue #(VM_Xlate_Result) fav_vm_xlate (WordXL addr,
434436
outcome = VM_XLATE_TLB_MISS;
435437
end
436438
return VM_Xlate_Result {outcome: outcome,
439+
allow_cap: fn_PTE_to_cap_R(pte) == 1'b1,
437440
pa: pa,
438441
exc_code: exc_code,
439442
pte_modified: pte_modified,

0 commit comments

Comments
 (0)