diff options
Diffstat (limited to 'rtl/core/mmu/fault.sv')
| -rw-r--r-- | rtl/core/mmu/fault.sv | 30 |
1 files changed, 27 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 |
