summaryrefslogtreecommitdiff
path: root/rtl/core/mmu/fault.sv
diff options
context:
space:
mode:
Diffstat (limited to 'rtl/core/mmu/fault.sv')
-rw-r--r--rtl/core/mmu/fault.sv30
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