mirror of
https://github.com/openhwgroup/cva6.git
synced 2025-04-23 13:47:13 -04:00
🐛 Fix delivery of faulting address exception
The page table walker was unconditionally delivering exceptions even when the instruction fetch stage wasn't any longer interested in it.
This commit is contained in:
parent
38ea32047b
commit
2b97d2b4b9
2 changed files with 32 additions and 22 deletions
17
src/mmu.sv
17
src/mmu.sv
|
@ -93,6 +93,7 @@ module mmu #(
|
|||
logic ptw_active; // PTW is currently walking a page table
|
||||
logic walking_instr; // PTW is walking because of an ITLB miss
|
||||
logic ptw_error; // PTW threw an exception
|
||||
logic [63:0] faulting_address;
|
||||
|
||||
logic update_is_2M;
|
||||
logic update_is_1G;
|
||||
|
@ -175,6 +176,7 @@ module mmu #(
|
|||
.ptw_active_o ( ptw_active ),
|
||||
.walking_instr_o ( walking_instr ),
|
||||
.ptw_error_o ( ptw_error ),
|
||||
.faulting_address_o ( faulting_address ),
|
||||
.enable_translation_i ( enable_translation_i ),
|
||||
|
||||
.itlb_update_o ( itlb_update ),
|
||||
|
@ -261,9 +263,14 @@ module mmu #(
|
|||
// ---------
|
||||
// watch out for exceptions happening during walking the page table
|
||||
if (ptw_active && walking_instr) begin
|
||||
// on an error pass through fetch with an error signaled
|
||||
fetch_gnt_o = ptw_error;
|
||||
ierr_valid_n = ptw_error; // signal valid/error on next cycle
|
||||
// check that the fetch address is equal with the faulting address as it could be that the page table walker
|
||||
// has walked an instruction the instruction fetch stage is no longer interested in as we didn't give a grant
|
||||
// we should not propagate back the exception when the request is no longer high
|
||||
if (faulting_address == fetch_vaddr_i && fetch_req_i) begin
|
||||
// on an error pass through fetch with an error signaled
|
||||
fetch_gnt_o = ptw_error;
|
||||
ierr_valid_n = ptw_error; // signal valid/error on next cycle
|
||||
end
|
||||
fetch_exception = {INSTR_PAGE_FAULT, {25'b0, update_vaddr}, 1'b1};
|
||||
end
|
||||
end
|
||||
|
@ -273,14 +280,14 @@ module mmu #(
|
|||
// ---------------------------
|
||||
// Fetch exception register
|
||||
// ---------------------------
|
||||
// We can have two oustanding transactions
|
||||
// We can have two outstanding transactions
|
||||
fifo #(
|
||||
.dtype ( exception ),
|
||||
.DEPTH ( 2 )
|
||||
) i_exception_fifo (
|
||||
.clk_i ( clk_i ),
|
||||
.rst_ni ( rst_ni ),
|
||||
.flush_i ( ),
|
||||
.flush_i ( 1'b0 ),
|
||||
.full_o ( ),
|
||||
.empty_o ( ),
|
||||
.single_element_o ( ),
|
||||
|
|
37
src/ptw.sv
37
src/ptw.sv
|
@ -32,6 +32,7 @@ module ptw #(
|
|||
output logic ptw_active_o,
|
||||
output logic walking_instr_o, // set when walking for TLB
|
||||
output logic ptw_error_o, // set when an error occurred
|
||||
output logic [63:0] faulting_address_o, // the address which threw the page-fault exception
|
||||
input logic enable_translation_i, // CSRs indicate to enable SV39
|
||||
input logic en_ld_st_translation_i, // enable virtual memory translation for load/stores
|
||||
|
||||
|
@ -97,7 +98,7 @@ module ptw #(
|
|||
// register the ASID
|
||||
logic [ASID_WIDTH-1:0] tlb_update_asid_q, tlb_update_asid_n;
|
||||
// register the VPN we need to walk, SV39 defines a 39 bit virtual address
|
||||
logic [38:0] vaddr_q, vaddr_n;
|
||||
logic [63:0] vaddr_q, vaddr_n;
|
||||
// 4 byte aligned physical pointer
|
||||
logic[55:0] ptw_pptr_q, ptw_pptr_n;
|
||||
|
||||
|
@ -147,22 +148,22 @@ module ptw #(
|
|||
always_comb begin : ptw
|
||||
// default assignments
|
||||
// PTW memory interface
|
||||
tag_valid_n = 1'b0;
|
||||
data_req_o = 1'b0;
|
||||
data_be_o = 8'hFF;
|
||||
data_we_o = 1'b0;
|
||||
ptw_error_o = 1'b0;
|
||||
itlb_update_o = 1'b0;
|
||||
dtlb_update_o = 1'b0;
|
||||
is_instr_ptw_n = is_instr_ptw_q;
|
||||
ptw_lvl_n = ptw_lvl_q;
|
||||
ptw_pptr_n = ptw_pptr_q;
|
||||
NS = CS;
|
||||
global_mapping_n = global_mapping_q;
|
||||
tag_valid_n = 1'b0;
|
||||
data_req_o = 1'b0;
|
||||
data_be_o = 8'hFF;
|
||||
data_we_o = 1'b0;
|
||||
ptw_error_o = 1'b0;
|
||||
itlb_update_o = 1'b0;
|
||||
dtlb_update_o = 1'b0;
|
||||
is_instr_ptw_n = is_instr_ptw_q;
|
||||
ptw_lvl_n = ptw_lvl_q;
|
||||
ptw_pptr_n = ptw_pptr_q;
|
||||
NS = CS;
|
||||
global_mapping_n = global_mapping_q;
|
||||
// input registers
|
||||
tlb_update_asid_n = tlb_update_asid_q;
|
||||
vaddr_n = vaddr_q;
|
||||
|
||||
tlb_update_asid_n = tlb_update_asid_q;
|
||||
vaddr_n = vaddr_q;
|
||||
faulting_address_o = '0;
|
||||
|
||||
case (CS)
|
||||
|
||||
|
@ -297,7 +298,8 @@ module ptw #(
|
|||
// Propagate error to MMU/LSU
|
||||
PROPAGATE_ERROR: begin
|
||||
NS = IDLE;
|
||||
ptw_error_o = 1'b1;
|
||||
ptw_error_o = 1'b1;
|
||||
faulting_address_o = vaddr_q;
|
||||
end
|
||||
// wait for the rvalid before going back to IDLE
|
||||
WAIT_RVALID: begin
|
||||
|
@ -305,6 +307,7 @@ module ptw #(
|
|||
NS = IDLE;
|
||||
end
|
||||
endcase
|
||||
|
||||
// -------
|
||||
// Flush
|
||||
// -------
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue