summaryrefslogtreecommitdiff
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
parent8c06c97c81339f68e06ff465aac2d8b1f2da4e27 (diff)
Fix implementation of MMU access faults
Diffstat (limited to '')
-rw-r--r--rtl/core/cp15/domain.sv2
-rw-r--r--rtl/core/mmu/fault.sv30
-rw-r--r--rtl/core/mmu/pagewalk.sv2
-rwxr-xr-xsim/sim.py1
-rw-r--r--tb/interval_timer.cpp2
-rw-r--r--tb/top/conspiracion.cpp2
6 files changed, 34 insertions, 5 deletions
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),
.*
);
diff --git a/sim/sim.py b/sim/sim.py
index 4a1dfa8..03d45c7 100755
--- a/sim/sim.py
+++ b/sim/sim.py
@@ -72,6 +72,7 @@ all_regs = [
('ttbr', 'ttbr'),
('far', 'far'),
('fsr', 'fsr'),
+ ('dacr', 'dacr'),
]
regs = {}
diff --git a/tb/interval_timer.cpp b/tb/interval_timer.cpp
index 88c24f7..7ab15d8 100644
--- a/tb/interval_timer.cpp
+++ b/tb/interval_timer.cpp
@@ -75,7 +75,7 @@ namespace taller::avalon
control_ito = !!(data & (1 << 0));
control_cont = !!(data & (1 << 1));
- status_run = (status_run && !!(data << (1 << 3))) || !!(data << (1 << 2));
+ status_run = (status_run && !!(data & (1 << 3))) || !!(data & (1 << 2));
break;
case 2:
diff --git a/tb/top/conspiracion.cpp b/tb/top/conspiracion.cpp
index 67ad2db..5af439f 100644
--- a/tb/top/conspiracion.cpp
+++ b/tb/top/conspiracion.cpp
@@ -19,6 +19,7 @@
#include "Vconspiracion_platform.h"
#include "Vconspiracion_vga_domain.h"
#include "Vconspiracion_core_control.h"
+#include "Vconspiracion_core_cp15_domain.h"
#include "Vconspiracion_core_cp15_far.h"
#include "Vconspiracion_core_cp15_fsr.h"
#include "Vconspiracion_core_cp15_syscfg.h"
@@ -464,6 +465,7 @@ int main(int argc, char **argv)
std::fprintf(ctrl, "%08x ttbr\n", core.cp15->ttbr->read);
std::fprintf(ctrl, "%08x far\n", core.cp15->far_->read);
std::fprintf(ctrl, "%08x fsr\n", core.cp15->fsr->read);
+ std::fprintf(ctrl, "%08x dacr\n", core.cp15->domain->mmu_dac);
std::fputs("=== end-regs ===\n", ctrl);
};