diff options
| author | Alejandro Soto <alejandro@34project.org> | 2022-12-14 19:16:54 -0600 |
|---|---|---|
| committer | Alejandro Soto <alejandro@34project.org> | 2022-12-16 16:29:10 -0600 |
| commit | d2be560fa668cefcc5eff6b88180f12fec0c326e (patch) | |
| tree | 8f833227461f8f97c32c2635f4eab39f1c077d37 /rtl/core/mmu | |
| parent | 8c06c97c81339f68e06ff465aac2d8b1f2da4e27 (diff) | |
Fix implementation of MMU access faults
Diffstat (limited to 'rtl/core/mmu')
| -rw-r--r-- | rtl/core/mmu/fault.sv | 30 | ||||
| -rw-r--r-- | rtl/core/mmu/pagewalk.sv | 2 |
2 files changed, 29 insertions, 3 deletions
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), .* ); |
