summaryrefslogtreecommitdiff
path: root/rtl/core/mmu
diff options
context:
space:
mode:
authorAlejandro Soto <alejandro@34project.org>2024-01-21 06:23:46 -0600
committerAlejandro Soto <alejandro@34project.org>2024-02-20 11:11:17 -0600
commitf3b18ead59ae02f95dabbf0a1dea40873a816975 (patch)
tree8979e50f2a37f66a4cd27e937b480efe60d72cf7 /rtl/core/mmu
parenta8bc5a353ea997f73209b39377ee15a73e471237 (diff)
rtl: refactor filenames and directory hierarchy
Diffstat (limited to 'rtl/core/mmu')
-rw-r--r--rtl/core/mmu/arbiter.sv132
-rw-r--r--rtl/core/mmu/fault.sv83
-rw-r--r--rtl/core/mmu/format.sv105
-rw-r--r--rtl/core/mmu/mmu.sv140
-rw-r--r--rtl/core/mmu/pagewalk.sv266
5 files changed, 0 insertions, 726 deletions
diff --git a/rtl/core/mmu/arbiter.sv b/rtl/core/mmu/arbiter.sv
deleted file mode 100644
index b0da7c8..0000000
--- a/rtl/core/mmu/arbiter.sv
+++ /dev/null
@@ -1,132 +0,0 @@
-module core_mmu_arbiter
-(
- input logic clk,
- rst_n,
-
- input logic bus_ready,
- bus_ex_fail,
- input word bus_data_rd,
- data_data_wr,
- input ptr insn_addr,
- data_addr,
- input logic insn_start,
- data_start,
- data_write,
- data_ex_lock,
- input logic[3:0] data_data_be,
-
- output word bus_data_wr,
- output logic[3:0] bus_data_be,
- output ptr bus_addr,
- output logic bus_start,
- bus_write,
- bus_ex_lock,
- insn_ready,
- data_ready,
- data_ex_fail,
- output word insn_data_rd,
- data_data_rd
-);
-
- enum int unsigned
- {
- INSN,
- DATA
- } master, next_master;
-
- ptr hold_addr;
- word hold_data_wr;
- logic active, hold_ex_lock, hold_start, hold_write, hold_issue, hold_free, transition;
- logic[3:0] hold_data_be;
-
- assign data_ex_fail = bus_ex_fail;
- assign insn_data_rd = bus_data_rd;
- assign data_data_rd = bus_data_rd;
-
- always_comb begin
- next_master = master;
- if(bus_ready || !active)
- unique case(master)
- DATA: next_master = data_start ? DATA : INSN;
- INSN: next_master = !data_start && !hold_start ? INSN : DATA;
- endcase
-
- // Causa UNOPTFLAT en Verilator con assign
- transition = master != next_master;
- hold_issue = transition && hold_start;
- hold_free = transition || !hold_start;
-
- insn_ready = 0;
- data_ready = 0;
-
- unique case(master)
- INSN: insn_ready = bus_ready;
- DATA: data_ready = bus_ready;
- endcase
-
- bus_data_wr = data_data_wr;
- unique case(next_master)
- INSN: begin
- bus_addr = insn_addr;
- bus_write = 0;
- bus_start = insn_start;
- bus_data_be = 4'b1111;
- bus_ex_lock = 0;
- end
-
- DATA: begin
- bus_addr = data_addr;
- bus_write = data_write;
- bus_start = data_start;
- bus_data_be = data_data_be;
- bus_ex_lock = data_ex_lock;
- end
- endcase
-
- if(hold_issue) begin
- bus_addr = hold_addr;
- bus_write = hold_write;
- bus_start = 1;
- bus_data_wr = hold_data_wr;
- bus_data_be = hold_data_be;
- bus_ex_lock = hold_ex_lock;
- end
- end
-
- always_ff @(posedge clk or negedge rst_n)
- if(!rst_n) begin
- master <= INSN;
- active <= 0;
-
- hold_addr <= 30'b0;
- hold_start <= 0;
- hold_write <= 0;
- hold_data_wr <= 0;
- hold_data_be <= 0;
- hold_ex_lock <= 0;
- end else begin
- master <= next_master;
- active <= bus_start || (active && !bus_ready);
-
- if(hold_free)
- unique case(next_master)
- INSN: begin
- hold_addr <= data_addr;
- hold_start <= data_start;
- hold_write <= data_write;
- hold_data_wr <= data_data_wr;
- hold_data_be <= data_data_be;
- hold_ex_lock <= data_ex_lock;
- end
-
- DATA: begin
- hold_addr <= insn_addr;
- hold_start <= insn_start;
- hold_write <= 0;
- hold_data_be <= 4'b1111;
- hold_ex_lock <= 0;
- end
- endcase
- end
-
-endmodule
diff --git a/rtl/core/mmu/fault.sv b/rtl/core/mmu/fault.sv
deleted file mode 100644
index b33cec2..0000000
--- a/rtl/core/mmu/fault.sv
+++ /dev/null
@@ -1,83 +0,0 @@
-`include "core/mmu/format.sv"
-`include "core/uarch.sv"
-
-module core_mmu_fault
-(
- input logic valid_entry,
- skip_perms,
- input word mmu_dac,
- input mmu_domain domain,
- input logic[1:0] ap,
- input logic privileged,
- write,
-
- output logic fault,
- output mmu_fault_type fault_type
-);
-
- mmu_domain_ctrl domain_ctrl;
-
- always_comb begin
- unique case(domain)
- 4'h0: domain_ctrl = mmu_dac[1:0];
- 4'h1: domain_ctrl = mmu_dac[3:2];
- 4'h2: domain_ctrl = mmu_dac[5:4];
- 4'h3: domain_ctrl = mmu_dac[7:6];
- 4'h4: domain_ctrl = mmu_dac[9:8];
- 4'h5: domain_ctrl = mmu_dac[11:10];
- 4'h6: domain_ctrl = mmu_dac[13:12];
- 4'h7: domain_ctrl = mmu_dac[15:14];
- 4'h8: domain_ctrl = mmu_dac[17:16];
- 4'h9: domain_ctrl = mmu_dac[19:18];
- 4'ha: domain_ctrl = mmu_dac[21:20];
- 4'hb: domain_ctrl = mmu_dac[23:22];
- 4'hc: domain_ctrl = mmu_dac[25:24];
- 4'hd: domain_ctrl = mmu_dac[27:26];
- 4'he: domain_ctrl = mmu_dac[29:28];
- 4'hf: domain_ctrl = mmu_dac[31:30];
- endcase
-
- fault = 0;
- fault_type = `MMU_FAULT_ACCESS;
-
- if(!valid_entry) begin
- fault = 1;
- fault_type = `MMU_FAULT_WALK;
- end else if(!skip_perms) begin
- if(!domain_ctrl.allowed) begin
- fault = 1;
- fault_type = `MMU_FAULT_DOMAIN;
- end else if(!domain_ctrl.manager)
- /* Hay una diferencia importante entre lo que dicen los
- * manuales y lo que al parecer pasa realmente. Según
- * el source del kernel, 0b00 debe permitir lecturas
- * desde modos privilegiados (PTE_SMALL_AP_UNO_SRO),
- * lo cual corresponde al caso con S = 1 en la tabla B4-1
- * del ARM ARM. Por otro lado, el kernel nunca usa su propia
- * definición de CR_S. Mi única explicación para que esto
- * funcione es que los cores legacy tienen S = 1 en reset
- * y a nadie nunca se le ocurrió revisar eso, o tal vez
- * el manual está mal.
- *
- * Todo esto resulta en que, si se interpretan los bits AP
- * como dice el manual de ARMv6, la página inmediatamente
- * posterior a tabla de vectores altos del kernel provoque
- * un prefetch abort (!!!) cuando los vectores saltan a esta,
- * lo cual causa un bucle infinito de aborts a la primera IRQ.
- */
- unique case(ap)
- 2'b00:
- fault = !privileged || write;
-
- 2'b01:
- fault = !privileged;
-
- 2'b10:
- fault = !privileged && write;
-
- 2'b11: ;
- endcase
- end
- end
-
-endmodule
diff --git a/rtl/core/mmu/format.sv b/rtl/core/mmu/format.sv
deleted file mode 100644
index 3029b83..0000000
--- a/rtl/core/mmu/format.sv
+++ /dev/null
@@ -1,105 +0,0 @@
-`ifndef CORE_MMU_FORMAT_SV
-`define CORE_MMU_FORMAT_SV
-
-typedef logic[17:0] mmu_base;
-typedef logic[3:0] mmu_domain;
-
-`define MMU_L1_INDEX [29:18]
-`define MMU_L1_FAULT 2'b00
-`define MMU_L1_PAGETABLE 2'b01
-`define MMU_L1_SECTION 2'b10
-
-typedef struct packed
-{
- logic[31:10] field10;
- logic[9:9] imp;
- logic[8:5] domain;
- logic[4:4] sbz;
- logic[3:2] field2;
- logic[1:0] typ;
-} mmu_l1_entry;
-
-typedef struct packed
-{
- logic[31:10] base;
- logic[9:9] imp;
- logic[8:5] domain;
- logic[4:2] sbz;
- logic[1:0] typ;
-} mmu_l1_pagetable;
-
-typedef struct packed
-{
- logic[31:20] base;
- logic[19:15] sbz0;
- logic[14:12] tex;
- logic[11:10] ap;
- logic[9:9] imp;
- logic[8:5] domain;
- logic[4:4] sbz1;
- logic[3:3] c;
- logic[2:2] b;
- logic[1:0] typ;
-} mmu_l1_section;
-
-`define MMU_SECTION_INDEX [17:0]
-
-`define MMU_L2_INDEX [17:10]
-`define MMU_L2_FAULT 2'b00
-`define MMU_L2_LARGE 2'b01
-`define MMU_L2_SMALL 2'b10
-`define MMU_L2_SMALLEXT 2'b11
-
-typedef struct packed
-{
- logic[31:16] base;
- logic[15:15] sbz;
- logic[14:12] tex;
- logic[11:10] ap3;
- logic[9:8] ap2;
- logic[7:6] ap1;
- logic[5:4] ap0;
- logic[3:3] c;
- logic[2:2] b;
- logic[1:0] typ;
-} mmu_l2_large;
-
-typedef struct packed
-{
- logic[31:12] base;
- logic[11:10] ap3;
- logic[9:8] ap2;
- logic[7:6] ap1;
- logic[5:4] ap0;
- logic[3:3] c;
- logic[2:2] b;
- logic[1:0] typ;
-} mmu_l2_small;
-
-typedef struct packed
-{
- logic[31:12] base;
- logic[11:9] sbz;
- logic[8:6] tex;
- logic[5:4] ap;
- logic[3:3] c;
- logic[2:2] b;
- logic[1:0] typ;
-} mmu_l2_smallext;
-
-`define MMU_LARGE_INDEX [13:0]
-`define MMU_SMALL_INDEX [9:0]
-
-typedef logic[1:0] mmu_fault_type;
-
-`define MMU_FAULT_WALK 2'b01
-`define MMU_FAULT_DOMAIN 2'b10
-`define MMU_FAULT_ACCESS 2'b11
-
-typedef struct packed
-{
- logic manager,
- allowed;
-} mmu_domain_ctrl;
-
-`endif
diff --git a/rtl/core/mmu/mmu.sv b/rtl/core/mmu/mmu.sv
deleted file mode 100644
index 22dfc3b..0000000
--- a/rtl/core/mmu/mmu.sv
+++ /dev/null
@@ -1,140 +0,0 @@
-`include "core/mmu/format.sv"
-`include "core/uarch.sv"
-
-module core_mmu
-(
- input logic clk,
- rst_n,
-
- input logic privileged,
- mmu_enable /*verilator public*/,
- input mmu_base mmu_ttbr /*verilator public*/,
- input word mmu_dac,
-
- input logic bus_ready,
- bus_ex_fail,
- input word bus_data_rd,
- data_data_wr,
- input ptr insn_addr,
- data_addr,
- input logic insn_start,
- data_start,
- data_write,
- data_ex_lock,
- data_user,
- input logic[3:0] data_data_be,
-
- output word bus_data_wr,
- output logic[3:0] bus_data_be,
- output ptr bus_addr,
- output logic bus_start,
- bus_write,
- bus_ex_lock,
- insn_ready,
- insn_fault,
- data_ready,
- data_fault,
- data_ex_fail,
- output word insn_data_rd,
- data_data_rd,
-
- output logic fault_register,
- fault_page,
- output ptr fault_addr,
- output mmu_fault_type fault_type,
- output mmu_domain fault_domain
-);
-
- ptr iphys_addr, dphys_addr;
- word iphys_data_rd, dphys_data_rd, dphys_data_wr;
- logic[3:0] dphys_data_be;
-
- logic iphys_start, dphys_start, iphys_ready, dphys_ready, dphys_write,
- dphys_ex_fail, dphys_ex_lock;
-
- assign fault_register = data_fault;
-
- core_mmu_pagewalk iwalk
- (
- .core_addr(insn_addr),
- .core_start(insn_start),
- .core_write(0),
- .core_ready(insn_ready),
- .core_data_wr(0),
- .core_data_be(0),
- .core_data_rd(insn_data_rd),
- .core_ex_fail(),
- .core_ex_lock(0),
-
- .core_fault(insn_fault),
- .core_fault_addr(),
- .core_fault_page(),
- .core_fault_type(),
- .core_fault_domain(),
-
- .bus_addr(iphys_addr),
- .bus_start(iphys_start),
- .bus_write(),
- .bus_ready(iphys_ready),
- .bus_data_wr(),
- .bus_data_be(),
- .bus_data_rd(iphys_data_rd),
- .bus_ex_fail(0),
- .bus_ex_lock(),
-
- .*
- );
-
- core_mmu_pagewalk dwalk
- (
- .core_addr(data_addr),
- .core_start(data_start),
- .core_write(data_write),
- .core_ready(data_ready),
- .core_data_wr(data_data_wr),
- .core_data_be(data_data_be),
- .core_data_rd(data_data_rd),
- .core_ex_fail(data_ex_fail),
- .core_ex_lock(data_ex_lock),
-
- .core_fault(data_fault),
- .core_fault_addr(fault_addr),
- .core_fault_page(fault_page),
- .core_fault_type(fault_type),
- .core_fault_domain(fault_domain),
-
- .bus_addr(dphys_addr),
- .bus_start(dphys_start),
- .bus_write(dphys_write),
- .bus_ready(dphys_ready),
- .bus_data_wr(dphys_data_wr),
- .bus_data_be(dphys_data_be),
- .bus_data_rd(dphys_data_rd),
- .bus_ex_fail(dphys_ex_fail),
- .bus_ex_lock(dphys_ex_lock),
-
- .privileged(privileged && !data_user),
- .*
- );
-
- core_mmu_arbiter arbiter
- (
- .insn_addr(iphys_addr),
- .insn_start(iphys_start),
- .insn_ready(iphys_ready),
- .insn_data_rd(iphys_data_rd),
-
- .data_addr(dphys_addr),
- .data_start(dphys_start),
- .data_write(dphys_write),
- .data_ready(dphys_ready),
- .data_data_wr(dphys_data_wr),
- .data_data_be(dphys_data_be),
- .data_data_rd(dphys_data_rd),
- .data_ex_fail(dphys_ex_fail),
- .data_ex_lock(dphys_ex_lock),
-
- .*
- );
-
-endmodule
diff --git a/rtl/core/mmu/pagewalk.sv b/rtl/core/mmu/pagewalk.sv
deleted file mode 100644
index 70c932c..0000000
--- a/rtl/core/mmu/pagewalk.sv
+++ /dev/null
@@ -1,266 +0,0 @@
-`include "core/mmu/format.sv"
-`include "core/uarch.sv"
-
-module core_mmu_pagewalk
-(
- input logic clk,
- rst_n,
-
- input logic privileged,
- mmu_enable,
- input mmu_base mmu_ttbr,
- input word mmu_dac,
-
- input logic bus_ready,
- bus_ex_fail,
- input word bus_data_rd,
-
- input ptr core_addr,
- input word core_data_wr,
- input logic[3:0] core_data_be,
- input logic core_start,
- core_write,
- core_ex_lock,
-
- output ptr bus_addr,
- output word bus_data_wr,
- output logic[3:0] bus_data_be,
- output logic bus_start,
- bus_write,
- bus_ex_lock,
-
- output word core_data_rd,
- output logic core_ready,
- core_ex_fail,
- core_fault,
- core_fault_page,
- output ptr core_fault_addr,
- output mmu_fault_type core_fault_type,
- output mmu_domain core_fault_domain
-);
-
- enum int unsigned
- {
- IDLE,
- L1,
- L2,
- DATA,
- FAULT
- } state;
-
- logic access_fault, valid_entry, skip_perms;
- logic[1:0] ap, entry_type;
- mmu_domain domain, entry_domain;
- mmu_fault_type access_fault_type;
-
- assign entry_type = bus_data_rd[1:0];
- assign core_fault_domain = domain;
-
- core_mmu_fault access_check
- (
- .write(hold_write),
- .fault(access_fault),
- .domain(entry_domain),
- .fault_type(access_fault_type),
- .*
- );
-
- mmu_l1_entry l1;
- assign l1 = bus_data_rd;
-
- mmu_l1_pagetable pagetable;
- assign pagetable = bus_data_rd;
-
- mmu_l1_section section;
- assign section = bus_data_rd;
-
- mmu_l2_large ptentry_large;
- assign ptentry_large = bus_data_rd;
-
- mmu_l2_small ptentry_small;
- assign ptentry_small = bus_data_rd;
-
- mmu_l2_smallext ptentry_smallext;
- assign ptentry_smallext = bus_data_rd;
-
- ptr target;
- word hold_data;
- logic hold_write, hold_ex_lock;
- logic[3:0] hold_be;
-
- always_comb begin
- ap = 2'bxx;
- skip_perms = 0;
- valid_entry = 1;
- entry_domain = domain;
-
- unique case(state)
- L1:
- unique case(entry_type)
- `MMU_L1_PAGETABLE: begin
- ap = 2'bxx;
- skip_perms = 1;
- end
-
- `MMU_L1_SECTION: begin
- ap = section.ap;
- entry_domain = l1.domain;
- end
-
- // Tiny (1KiB wtf?) pages and supersections not supported
- default:
- valid_entry = 0;
- endcase
-
- L2:
- unique case(entry_type)
- `MMU_L2_FAULT:
- valid_entry = 0;
-
- `MMU_L2_LARGE:
- //TODO: ap3-ap2 (también en L2_SMALL)
- ap = ptentry_large.ap0;
-
- `MMU_L2_SMALL:
- ap = ptentry_small.ap0;
-
- `MMU_L2_SMALLEXT:
- ap = ptentry_smallext.ap;
- endcase
-
- default:
- valid_entry = 1'bx;
- endcase
- end
-
- always @(posedge clk or negedge rst_n)
- if(!rst_n) begin
- state <= IDLE;
- target <= 0;
- domain <= 0;
-
- hold_be <= 0;
- hold_data <= 0;
- hold_write <= 0;
- hold_ex_lock <= 0;
-
- bus_addr <= 0;
- bus_start <= 0;
- bus_write <= 0;
- bus_ex_lock <= 0;
- bus_data_be <= 0;
- bus_data_wr <= 0;
-
- core_ready <= 0;
- core_fault <= 0;
- core_ex_fail <= 0;
- core_data_rd <= 0;
- core_fault_page <= 0;
- core_fault_addr <= 0;
- core_fault_type <= 0;
- end else begin
- if(bus_start)
- bus_start <= 0;
-
- if(core_ready)
- core_ready <= 0;
-
- if(core_fault)
- core_fault <= 0;
-
- unique case(state)
- IDLE:
- if(core_start) begin
- bus_start <= 1;
-
- if(mmu_enable) begin
- target <= core_addr;
- hold_be <= core_data_be;
- hold_data <= core_data_wr;
- hold_write <= core_write;
- hold_ex_lock <= core_ex_lock;
-
- state <= L1;
- bus_addr <= {mmu_ttbr, core_addr `MMU_L1_INDEX};
- bus_write <= 0;
- bus_ex_lock <= 0;
- end else begin
- state <= DATA;
- bus_addr <= core_addr;
- bus_write <= core_write;
- bus_ex_lock <= core_ex_lock;
- bus_data_wr <= core_data_wr;
- bus_data_be <= core_data_be;
- end
- end
-
- L1:
- if(bus_ready) begin
- domain <= l1.domain;
-
- unique case(entry_type)
- `MMU_L1_PAGETABLE: begin
- state <= L2;
- bus_addr <= {pagetable.base, target `MMU_L2_INDEX};
- end
-
- `MMU_L1_SECTION: begin
- state <= DATA;
- bus_addr <= {section.base, target `MMU_SECTION_INDEX};
- bus_write <= hold_write;
- bus_ex_lock <= hold_ex_lock;
- bus_data_wr <= hold_data;
- bus_data_be <= hold_be;
- end
-
- default: ;
- endcase
- end
-
- L2:
- if(bus_ready) begin
- state <= DATA;
-
- bus_write <= hold_write;
- bus_ex_lock <= hold_ex_lock;
- bus_data_wr <= hold_data;
- bus_data_be <= hold_be;
-
- unique case(entry_type)
- `MMU_L2_FAULT: ;
-
- `MMU_L2_LARGE:
- bus_addr <= {ptentry_large.base, target `MMU_LARGE_INDEX};
-
- `MMU_L2_SMALL, `MMU_L2_SMALLEXT:
- bus_addr <= {ptentry_small.base, target `MMU_SMALL_INDEX};
- endcase
- end
-
- DATA:
- if(bus_ready) begin
- state <= IDLE;
- core_ready <= 1;
- core_ex_fail <= bus_ex_fail;
- core_data_rd <= bus_data_rd;
- end
-
- FAULT: begin
- state <= IDLE;
- core_fault <= 1;
- core_ready <= 1;
- core_fault_addr <= target;
- end
- endcase
-
- if((state == L1 || state == L2) && bus_ready) begin
- if(access_fault) begin
- state <= FAULT;
- core_fault_type <= access_fault_type;
- core_fault_page <= state == L2;
- end else
- bus_start <= 1;
- end
- end
-
-endmodule