summaryrefslogtreecommitdiff
path: root/rtl/core/mmu
diff options
context:
space:
mode:
authorAlejandro Soto <alejandro@34project.org>2022-12-14 19:16:54 -0600
committerAlejandro Soto <alejandro@34project.org>2022-12-16 16:29:10 -0600
commitd2be560fa668cefcc5eff6b88180f12fec0c326e (patch)
tree8f833227461f8f97c32c2635f4eab39f1c077d37 /rtl/core/mmu
parent8c06c97c81339f68e06ff465aac2d8b1f2da4e27 (diff)
Fix implementation of MMU access faults
Diffstat (limited to 'rtl/core/mmu')
-rw-r--r--rtl/core/mmu/fault.sv30
-rw-r--r--rtl/core/mmu/pagewalk.sv2
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),
.*
);