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 | |
| parent | 8c06c97c81339f68e06ff465aac2d8b1f2da4e27 (diff) | |
Fix implementation of MMU access faults
| -rw-r--r-- | rtl/core/cp15/domain.sv | 2 | ||||
| -rw-r--r-- | rtl/core/mmu/fault.sv | 30 | ||||
| -rw-r--r-- | rtl/core/mmu/pagewalk.sv | 2 | ||||
| -rwxr-xr-x | sim/sim.py | 1 | ||||
| -rw-r--r-- | tb/interval_timer.cpp | 2 | ||||
| -rw-r--r-- | tb/top/conspiracion.cpp | 2 |
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), .* ); @@ -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); }; |
