From d2be560fa668cefcc5eff6b88180f12fec0c326e Mon Sep 17 00:00:00 2001 From: Alejandro Soto Date: Wed, 14 Dec 2022 19:16:54 -0600 Subject: Fix implementation of MMU access faults --- rtl/core/cp15/domain.sv | 2 +- rtl/core/mmu/fault.sv | 30 +++++++++++++++++++++++++++--- rtl/core/mmu/pagewalk.sv | 2 ++ 3 files changed, 30 insertions(+), 4 deletions(-) (limited to 'rtl') diff --git a/rtl/core/cp15/domain.sv b/rtl/core/cp15/domain.sv index 92112be..de37de4 100644 --- a/rtl/core/cp15/domain.sv +++ b/rtl/core/cp15/domain.sv @@ -10,7 +10,7 @@ module core_cp15_domain input word write, output word read, - mmu_dac + mmu_dac /*verilator public*/ ); assign read = mmu_dac; diff --git a/rtl/core/mmu/fault.sv b/rtl/core/mmu/fault.sv index e922284..b33cec2 100644 --- a/rtl/core/mmu/fault.sv +++ b/rtl/core/mmu/fault.sv @@ -8,6 +8,8 @@ module core_mmu_fault 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 @@ -46,12 +48,34 @@ module core_mmu_fault 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 = 1; + fault = !privileged || write; - //TODO: los demás solo se tienen efecto para unprivileged - default: ; + 2'b01: + fault = !privileged; + + 2'b10: + fault = !privileged && write; + + 2'b11: ; endcase end end diff --git a/rtl/core/mmu/pagewalk.sv b/rtl/core/mmu/pagewalk.sv index c6d51c0..ce25b19 100644 --- a/rtl/core/mmu/pagewalk.sv +++ b/rtl/core/mmu/pagewalk.sv @@ -53,8 +53,10 @@ module core_mmu_pagewalk core_mmu_fault access_check ( + .write(hold_write), .fault(access_fault), .domain(entry_domain), + .privileged(1), //TODO .fault_type(access_fault_type), .* ); -- cgit v1.2.3