From 1644863a5832f676cfb823e92cc9c41717586876 Mon Sep 17 00:00:00 2001 From: wfjm Date: Fri, 9 Sep 2022 09:01:06 +0200 Subject: [PATCH] pdp11_mmu.vhd: BUGFIX: correct trap and PDR A logic - tools/asm-11/lib/defs_mmu.mac: rename md.a??, saner names for ACF - tcode/cpu_mmu.mac: add E1.1, test m0.trp, pdr aia/aiw transitions (verify fix) Closes #34 Closes #33 Closes #26 Closes #25 --- doc/CHANGELOG.md | 9 +- doc/ECO-033-MMU_AFC-1_PDR-A.md | 58 +++++ rtl/w11a/pdp11_mmu.vhd | 45 +++- tools/asm-11/lib/defs_mmu.mac | 10 +- tools/tcode/cpu_mmu.mac | 386 ++++++++++++++++++++++++++++++--- 5 files changed, 458 insertions(+), 50 deletions(-) create mode 100644 doc/ECO-033-MMU_AFC-1_PDR-A.md diff --git a/doc/CHANGELOG.md b/doc/CHANGELOG.md index 8ff949e4..6070364b 100644 --- a/doc/CHANGELOG.md +++ b/doc/CHANGELOG.md @@ -36,7 +36,7 @@ The full set of tests is only run for tagged releases. - remove Atlys support (only test designs, a w11 design was never done) - cleanup SimH setup files (\*.scmd), use autoconfig, set disk types - cleanup code base, use page,mmr\*,pdr,par instead of segment,ssr\*,sdr,sar -- sysid encodes now system type, allows to distingish w11,SimH,e11 +- sysid encodes now system type, allows to distinguish w11,SimH,e11 - added dasm-11, a PDP-11 disassembler ### New features - new verification codes @@ -90,12 +90,15 @@ The full set of tests is only run for tagged releases. - *.scmd: set sysid to 110234 --> emu Simh - *.ecmd: set sysid to 120345 --> emu e11 ### Bug Fixes + - rtl/w11a + - pdp11_mmu: BUGFIX: correct trap and PDR A logic, see + [ECO-033](ECO-033-MMU_AFC-1_PDR-A.md) + - src/librwxxtpp + - RtclRw11Cpu.cpp: quit before mem write if asm-11 error seen - tools/asm-11/lib - tcode_std_start.mac: fix sdreg probe code - tools/mcode - m9312/bootw11.mac: proper init of unit number in getnam - - src/librwxxtpp - - RtclRw11Cpu.cpp: quit before mem write if asm-11 error seen --- diff --git a/doc/ECO-033-MMU_AFC-1_PDR-A.md b/doc/ECO-033-MMU_AFC-1_PDR-A.md new file mode 100644 index 00000000..0ed6e57b --- /dev/null +++ b/doc/ECO-033-MMU_AFC-1_PDR-A.md @@ -0,0 +1,58 @@ +# ECO-033: MMU: ACF=1 trap and PDR A fix (2022-09-07) + +### Scope +- was in w11a since 2009 +- affects: all w11a systems + +### Symptom summary +- part 1: ACF=1 traps on any access + Test 055 of `ekbee1` fails with + ``` + MEMORY MANAGEMENT TRAP OR ABORT HAD INCORRECT CONDITION + EXPECTD ERROR AUTOI/D VIRTUAL + CONDITN REGISTR REGISTR ADDRESS TESTNO PC AT ABORT + 020011 030011 013427 054032 000055 054040 + ``` + +- part 2: `PDR` A bit is set for every access + This was discovered in a code review. The `PDR` A bit was set for + all accesses. The `PDR` A bit should be set only when + _"trap condition met by the Access Control Field (ACF)"_ is fulfilled. + Thus for + ``` + ACF=001 read-only trap and A bit on read + ACF=100 read/write trap and A bit on read or write + ACF=101 read/write trap and A bit on write + ``` + + `ekbee1` only checks whether this bit is set when expected, but does + _not_ verify that is stays '0' when it should. + +### Analysis +- part 1: ACF=1 traps on any access + Caused by a simple mistake in the `ACF` handling in pdp11_mmu.vhd + ```vhdl + case PARPDR.acf is -- evaluate accecc control field + when "001" => -- read-only; trap on read + if CNTL.wacc='1' or CNTL.macc='1' then + abo_rdonly := '1'; + end if; + dotrap := '1'; -- <== BUG, should be 'not write' + ``` +- part 2: PDR A bit is set for every access + Caused simplistic AIB handling in pdp11_mmu.vhd + ```vhdl + if doabort = '0' then + AIB_SETA <= '1'; -- <== BUG, should be 'dotrap' + AIB_SETW <= CNTL.wacc or CNTL.macc; + end if; + ``` + +### Fixes +- part 1: `AIB_SETA <= dotrap;` +- part 2: `dotrap := not iswrite;` + +### Hindsight +Took 13 years to fix. The MMU traps and `PDR` A and W bits are 11/45 and 11/70 +specific and not used by any operating system. Only tests like `ekbee1` use +this functionality. diff --git a/rtl/w11a/pdp11_mmu.vhd b/rtl/w11a/pdp11_mmu.vhd index 7530953d..e0eeace2 100644 --- a/rtl/w11a/pdp11_mmu.vhd +++ b/rtl/w11a/pdp11_mmu.vhd @@ -1,4 +1,4 @@ --- $Id: pdp11_mmu.vhd 1279 2022-08-14 08:02:21Z mueller $ +-- $Id: pdp11_mmu.vhd 1294 2022-09-07 14:21:20Z mueller $ -- SPDX-License-Identifier: GPL-3.0-or-later -- Copyright 2006-2022 by Walter F.J. Mueller -- @@ -17,6 +17,7 @@ -- -- Revision History: -- Date Rev Version Comment +-- 2022-09-05 1294 1,4.4 BUGFIX: correct trap and PDR A logic -- 2022-08-13 1279 1.4.3 ssr->mmr rename -- 2011-11-18 427 1.4.2 now numeric_std clean -- 2010-10-23 335 1.4.1 use ib_sel @@ -264,9 +265,10 @@ begin variable abo_rdonly : slbit := '0'; variable mmr_freeze : slbit := '0'; variable doabort : slbit := '0'; - variable dotrap : slbit := '0'; + variable dotrap : slbit := '0'; variable dotrace : slbit := '0'; - + variable iswrite : slbit := '0'; + begin nmmr0 := R_MMR0; @@ -277,7 +279,8 @@ begin mmr_freeze := R_MMR0.abo_nonres or R_MMR0.abo_length or R_MMR0.abo_rdonly; dotrace := not(CNTL.cacc or mmr_freeze); - + iswrite := CNTL.wacc or CNTL.macc; + apf := VADDR(15 downto 13); bn := VADDR(12 downto 6); @@ -285,7 +288,7 @@ begin abo_length := '0'; abo_rdonly := '0'; doabort := '0'; - dotrap := '0'; + dotrap := '0'; if PARPDR.ed = '0' then -- ed=0: upward expansion if unsigned(bn) > unsigned(PARPDR.plf) then @@ -297,19 +300,39 @@ begin end if; end if; + -- ACF decision logic + -- w11 has 4 memory cycle types, the ACF is based only on read or write + -- wacc='0' macc'0' : read cycle --> read + -- wacc='1' macc'0' : write cycle --> write + -- wacc='0' macc'1' : read part of rmw --> write + -- wacc='1' macc'1' : write part of rmw --> write + -- Depending of ACF the MMU aborts, queues a trap, sets A and W bit in PDR + -- ACF abort trap Comment + -- 000 nonres - non-resident: abort all accesses + -- 001 rdonly R read-only: abort on write, trap on read + -- 010 rdonly read-only: abort on write + -- 011 nonres - unused: abort all accesses + -- 100 - R+W read/write: no abort, trap on read or write + -- 101 - W read/write: no abort, trap on write + -- 110 - - read/write: no abort, no trap + -- 111 nonres - unused: abort all accesses + -- + -- The PDR W bit is set for non-aborted write accesses + -- The PDR A bit is set if the trap condition is fulfilled and not aborted + case PARPDR.acf is -- evaluate accecc control field when "000" => -- page non-resident abo_nonres := '1'; when "001" => -- read-only; trap on read - if CNTL.wacc='1' or CNTL.macc='1' then + if iswrite='1' then abo_rdonly := '1'; end if; - dotrap := '1'; + dotrap := not iswrite; when "010" => -- read-only - if CNTL.wacc='1' or CNTL.macc='1' then + if iswrite='1' then abo_rdonly := '1'; end if; @@ -317,7 +340,7 @@ begin dotrap := '1'; when "101" => -- read/write; trap on write - dotrap := CNTL.wacc or CNTL.macc; + dotrap := iswrite; when "110" => null; -- read/write; @@ -358,8 +381,8 @@ begin doabort := abo_nonres or abo_length or abo_rdonly; if doabort = '0' then - AIB_SETA <= '1'; - AIB_SETW <= CNTL.wacc or CNTL.macc; + AIB_SETA <= dotrap; + AIB_SETW <= iswrite; end if; if mmr_freeze = '0' then diff --git a/tools/asm-11/lib/defs_mmu.mac b/tools/asm-11/lib/defs_mmu.mac index 569bec93..847530ce 100644 --- a/tools/asm-11/lib/defs_mmu.mac +++ b/tools/asm-11/lib/defs_mmu.mac @@ -1,4 +1,4 @@ -; $Id: defs_mmu.mac 1291 2022-09-03 07:00:27Z mueller $ +; $Id: defs_mmu.mac 1295 2022-09-07 16:28:55Z mueller $ ; SPDX-License-Identifier: GPL-3.0-or-later ; Copyright 2015-2022 by Walter F.J. Mueller ; @@ -53,8 +53,8 @@ md.dwn = 000010 ; ed field 1, down expansion md.an7 = 000007 ; abort all; reserved md.arw = 000006 ; allow r+w; no traps - md.atw = 000005 ; allow r+w; trap w - md.atr = 000004 ; allow r+w; trap r+w + md.art = 000005 ; allow r+w; trap w + md.att = 000004 ; allow r+w; trap r+w md.an3 = 000003 ; abort all; reserved - md.aro = 000002 ; allow r; abort w; no traps - md.art = 000001 ; allow r; abort w; trap r + md.ara = 000002 ; allow r; abort w; no traps + md.ata = 000001 ; allow r; abort w; trap r diff --git a/tools/tcode/cpu_mmu.mac b/tools/tcode/cpu_mmu.mac index a2a73106..643249e7 100644 --- a/tools/tcode/cpu_mmu.mac +++ b/tools/tcode/cpu_mmu.mac @@ -1,17 +1,18 @@ -; $Id: cpu_mmu.mac 1291 2022-09-03 07:00:27Z mueller $ +; $Id: cpu_mmu.mac 1295 2022-09-07 16:28:55Z mueller $ ; SPDX-License-Identifier: GPL-3.0-or-later ; Copyright 2022- by Walter F.J. Mueller ; ; Revision History: ; Date Rev Version Comment -; 2022-08-31 1291 1.0 Initial version +; 2022-09-06 1294 1.0 Initial version ; 2022-07-24 1262 0.1 First draft ; ; Test CPU MMU: all aspects of the MMU ; Section A: pdr,par registers ; Section B: mmr0,mmr3 registers, mapping, instructions -; Section C: mmr1+mmr0 register, aborts and traps +; Section C: mmr1+mmr0 register, aborts ; Section D: mmr2+mmr1+mmr0 register, abort recovery +; Section E: traps and pdr aia and aiw bits ; .include |lib/tcode_std_base.mac| .include |lib/defs_mmu.mac| @@ -35,6 +36,21 @@ kipar6 = kipar+14 kipdr7 = kipdr+16 kipar7 = kipar+16 + + p0p1p2 = <1*100>+2 ; page 0, +1 click, +2 + p0p1p4 = <1*100>+4 ; page 0, +1 click, +4 + p1base = <1*20000> ; page 1 + p1p0p2 = p1base+2 ; page 1, +2 + p1m1p0 = p1base+<127.*100> ; page 1, 128-1 click + p2base = <2*20000> ; page 2 + p2m1p0 = p2base+<127.*100> ; page 1, 128-1 click + p2m1m4 = p2base+<127.*100>-4 ; page 1, 128-1 click, -4 + p3base = <3*20000> ; page 3 + p4base = <4*20000> ; page 4 + p5base = <5*20000> ; page 5 + p6base = <6*20000> ; page 6 + p6p1p2 = p6base+<1*100>+2 ; page 6, +1 click, +2 + p7base = <7*20000> ; page 7 ; ; Section A: pdr,par registers =============================================== ; @@ -564,7 +580,7 @@ tb0302: ; 9999$: iot ; end of test B3.2 ; -; Section C: mmr1+mmr0 register, aborts and traps ============================ +; Section C: mmr1+mmr0 register, aborts ====================================== ; ; Test C1: ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ; @@ -646,7 +662,7 @@ tc0101: mov #1000$,r1 ; ptr to abort bit table ; Test C2.1 -- test unary/binary instructions ++++++++++++++++++++++++ ; Excercise access to kernel page 6 and inspect mmr0 and mmr1 ; -tc0201: mov #vhemmu,v..mmu +tc0201: mov #vhmmua,v..mmu clr v..mmu+2 ; pr0 kernel reset mov #m0.ena,mmr0 ; enable mmu ;! MMU 18 @@ -692,7 +708,7 @@ tc0201: mov #vhemmu,v..mmu .word ^b0000000011110100 ; mmr1 -2,4 ; ; write abort in mapped area (write access) -1300$: mov #<0.*md.plf>!md.aro,kipdr6 ; plf= 0.;ed=0;acf=r +1300$: mov #<0.*md.plf>!md.ara,kipdr6 ; plf= 0.;ed=0;acf=r mov #140002,r2 tstb (r2)+ ; read ok mov #1310$,vhvmmu @@ -738,7 +754,7 @@ tc0201: mov #vhemmu,v..mmu mov #2001$,r2 tst @(r2)+ ; will fail halt -2001$: .word 140102 ; probed address +2001$: .word p6p1p2 ; probed address, page 6, +1 click, +2 2010$: .word m0.ale!<6*m0.pno>!m0.ena ; mmr0 ; dddddrrrdddddrrr .word ^b0000000000010010 ; mmr1 +2,2 @@ -778,7 +794,7 @@ tc0201: mov #vhemmu,v..mmu mov #3201$,r4 mov @(r4)+,(r3)+ ; will fail halt -3201$: .word 140102 ; probed address +3201$: .word p6p1p2 ; probed address, page 6, +1 click, +2 3210$: .word m0.ale!<6*m0.pno>!m0.ena ; mmr0 ; dddddrrrdddddrrr .word ^b0000000000010100 ; mmr1 +2,4 @@ -820,12 +836,12 @@ tc0201: mov #vhemmu,v..mmu mov 4201$,r5 cmp (r2)+,@(r5)+ ; will fail halt -4201$: .word 140102 ; probed address +4201$: .word p6p1p2 ; probed address, page 6, +1 click, +2 4210$: .word m0.ale!<6*m0.pno>!m0.ena ; mmr0 ; dddddrrrdddddrrr .word ^b0001010100010010 ; mmr1 +2,5; +2,2 ; -4300$: mov #<0.*md.plf>!md.aro,kipdr6 ; plf= 0.;ed=0;acf=r +4300$: mov #<0.*md.plf>!md.ara,kipdr6 ; plf= 0.;ed=0;acf=r mov #4310$,vhvmmu mov #140010,r4 bis -(r2),(r4)+ ; will fail @@ -870,7 +886,7 @@ tc0201: mov #vhemmu,v..mmu .word ^b0000000000010011 ; mmr1 +2,3 ; ; length + read-only abort -5200$: mov #<0.*md.plf>!md.aro,kipdr6 ; plf= 0.;ed=0;acf=r +5200$: mov #<0.*md.plf>!md.ara,kipdr6 ; plf= 0.;ed=0;acf=r mov #5210$,vhvmmu mov #140102,r4 com (r4)+ ; will fail @@ -893,14 +909,14 @@ tc0201: mov #vhemmu,v..mmu ; udpdr1 1 click up acr=2 read ; udpdr2 1 click dn acr=6 w/r ; -tc0202: mov #vhemmu,v..mmu +tc0202: mov #vhmmua,v..mmu clr v..mmu+2 ; pr0 kernel reset mov #cp.pmu,cp.psw ; pm to user mov #m3.dum,mmr3 ; enable user D space mov #<0.*md.plf>!md.arw,kipdr6 ; plf= 0.;ed=0;acf=w/r - mov #<0.*md.plf>!md.aro,uipdr0 ; plf= 0.;ed=0;acf=r - mov #<0.*md.plf>!md.aro,udpdr1 ; plf= 0.;ed=0;acf=r + mov #<0.*md.plf>!md.ara,uipdr0 ; plf= 0.;ed=0;acf=r + mov #<0.*md.plf>!md.ara,udpdr1 ; plf= 0.;ed=0;acf=r mov #<127.*md.plf>!md.dwn!md.arw,udpdr2 ; plf=127.;ed=1;acf=w/r mov #m0.ena,mmr0 ; enable mmu ;! MMU 18 ; @@ -914,7 +930,7 @@ tc0202: mov #vhemmu,v..mmu ; ; MPPI: I space page 1 non-resident 1000$: mov #1010$,vhvmmu - mov #020000,r2 + mov #p1base,r2 mfpi (r2)+ ; will fail, page 1 unmapped halt 1010$: .word m0.anr!m0.pmu!<1*m0.pno>!m0.ena ; mmr0 @@ -923,7 +939,7 @@ tc0202: mov #vhemmu,v..mmu ; ; MFPI: I space page 0 length abort 1100$: mov #1110$,vhvmmu - mov #000102,r3 + mov #p0p1p2,r3 ; page 0, +1 click, +2 mfpi (r3)+ ; will fail halt 1110$: .word m0.ale!m0.pmu!<0*m0.pno>!m0.ena ; mmr0 @@ -933,7 +949,7 @@ tc0202: mov #vhemmu,v..mmu ; MFPI @(R)+: 1st access fails (in kernel space) 1200$: mov #cp.pmu,cp.psw ; pm to user mov #1210$,vhvmmu - mov #140102,r4 + mov #p6p1p2,r4 ; page 6, +1 click, +2 mfpi @(r4)+ ; will fail halt 1210$: .word m0.ale!<6*m0.pno>!m0.ena ; mmr0 -> p6 k @@ -946,7 +962,7 @@ tc0202: mov #vhemmu,v..mmu mov #1301$,r5 mfpi @(r5)+ ; will fail halt -1301$: .word 000104 ; probed address +1301$: .word p0p1p4 ; probed address 1310$: .word m0.ale!m0.pmu!<0*m0.pno>!m0.ena ; mmr0 -> p0 u ; dddddrrrdddddrrr .word ^b0000000000010101 ; mmr1 +2,5 @@ -954,7 +970,7 @@ tc0202: mov #vhemmu,v..mmu ; MFPD: D space page 1 length abort (has ed=1) 1400$: mov #cp.pmu,cp.psw ; pm to user mov #1410$,vhvmmu - mov #037700,r3 + mov #p1m1p0,r3 ; page 1, 128-1 click mfpd -(r3) ; will fail halt 1410$: .word m0.ale!m0.pmu!m0.dsp!<1*m0.pno>!m0.ena ; mmr0 @@ -974,7 +990,7 @@ tc0202: mov #vhemmu,v..mmu ; MTPD: D space page 3 non-resident 2000$: mov #cp.pmu,cp.psw ; pm to user mov #2010$,vhvmmu - mov #060000,r2 + mov #p3base,r2 push #1234 mtpd (r2)+ ; will fail, page 3 unmapped halt @@ -985,7 +1001,7 @@ tc0202: mov #vhemmu,v..mmu ; MTPD: D space page 1 read-only 2100$: mov #cp.pmu,cp.psw ; pm to user mov #2110$,vhvmmu - mov #020002,r3 + mov #p1p0p2,r3 ; page 1, +2 push #1234 mtpd (r3)+ ; will fail halt @@ -995,7 +1011,7 @@ tc0202: mov #vhemmu,v..mmu ; ; MTPD: D space page 2 length 2200$: mov #2210$,vhvmmu - mov #057700,r4 + mov #p2m1p0,r4 push #1234 mtpd -(r4) ; will fail halt @@ -1005,7 +1021,7 @@ tc0202: mov #vhemmu,v..mmu ; ; MTPD @(R)+: 1st access fails (in kernel space) 2300$: mov #2310$,vhvmmu - mov #140102,r5 + mov #p6p1p2,r5 ; page 6, +1 click, +2 push #1234 mtpd @(r5)+ ; will fail halt @@ -1019,7 +1035,7 @@ tc0202: mov #vhemmu,v..mmu push #1234 mtpd @(r3)+ ; will fail halt -2401$: .word 057600 ; probed address +2401$: .word p2m1m4 ; probed address, page 1, 128-1 click, -4 2410$: .word m0.ale!m0.pmu!m0.dsp!<2*m0.pno>!m0.ena ; mmr0 ; dddddrrrdddddrrr .word ^b0001001100010110 ; mmr1 +2,3; +2,6 @@ -1054,7 +1070,7 @@ tc0202: mov #vhemmu,v..mmu ; si.7 as 1-to-1 (psw access) ; ui.0 as 1-to-1 (for read access) ; -tc0203: mov #vhemmu,v..mmu +tc0203: mov #vhmmua,v..mmu clr v..mmu+2 ; pr0 kernel reset mov kipdr0,sipdr0 ; super 0: 1-to-1 @@ -1281,26 +1297,316 @@ td0101: 3002$: .word 0 ; save mmr2 ; 9999$: iot ; end of test D1.1 - +; +; Section E: traps and pdr aia and aiw bits ================================== +; +; Test E1: ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +; +; Test E1.1 -- test m0.trp, pdr aia/aiw transitions ++++++++++++++++++ +; Summary +; PDR MMR0 action aia aiw trp Trap Comment +; acf=6 ent=0 tst (r3) 0 0 0 no no ai, no trap +; clr (r3) 0 1 0 no clr sets aiw +; tst (r3) 0 1 0 no aiw stays +; pdr->pdr 0 0 0 - any pdr write clears aia,aiw +; clr (r3) 0 1 0 no clr sets aiw +; pdr+1 write 0 0 0 - any pdr write clears aia,aiw +; clr (r3) 0 1 0 no clr sets aiw +; par->par 0 0 0 - any par write clears aia,aiw +; +; acf=6 ent=1 tst (r3) 0 0 0 no no trap +; clr (r3) 0 1 0 no no trap +; +; acf=4 ent=0 tst (r3) 1 0 1 no trp set, aia set +; clr (r3) 1 1 1 no trp stays, aiw set +; trp=0;pdr 0 0 0 - any par write clears aia,aiw +; +; acf=4 ent=1 tst (r3) 1 0 1 yes trap taken, trp set, aia set +; clr (r3) 1 1 1 no no trap, aia set +; trp=0;pdr 0 0 0 - any pdr write clears aia,aiw +; clr (r3) 1 1 1 yes trap taken, trp,aia,aiw set +; tst (r3) 1 1 1 no no trap, no additional bits +; trp=0;pdr 0 0 0 - any par write clears aia,aiw +; +; Uses page 6 with plf=1 and varying acf +; +te0101: mov #vhmmut,v..mmu ; setup MMU trap handler + clr v..mmu+2 ; pr0 kernel + reset + mov #m0.ena,mmr0 ; enable mmu ;! MMU 18 + mov #kipdr6,r4 ; keep in register + mov #p6base,r3 ; probed address + clr vhvmmu ; dont expect traps initially +; +; acf=6 ent=0 tst (r3) 0 0 0 no no ai, no trap + mov #md.plf!md.arw,(r4) ; set pdr + tst (r3) ; probe read + hbiteq mmr0,#m0.trp ; check trp=0 + hcmpeq (r4),#md.plf!md.arw ; check aia,aiw=0 +; +; clr (r3) 0 1 0 no clr sets aiw + clr (r3) ; probe write + hbiteq mmr0,#m0.trp ; check trp=0 + hcmpeq (r4),#md.plf!md.aiw!md.arw ; check aiw=1 +; +; tst (r3) 0 1 0 no aiw stays + tst (r3) ; probe read + hcmpeq (r4),#md.plf!md.aiw!md.arw ; check aiw=1 +; +; pdr->pdr 0 0 0 - any pdr write clears aia,aiw + mov (r4),(r4) ; write pdr->pdr, should clear aiw + hcmpeq (r4),#md.plf!md.arw ; check aiw=0 +; +; clr (r3) 0 1 0 no clr sets aiw + clr (r3) ; probe write + hcmpeq (r4),#md.plf!md.aiw!md.arw ; check aiw=1 +; +; pdr+1 write 0 0 0 - any pdr write clears aia,aiw + movb #1,1(r4) ; write pdr+1, should clear aiw + hcmpeq (r4),#md.plf!md.arw ; check aiw=0 +; +; clr (r3) 0 1 0 no clr sets aiw + clr (r3) ; probe write + hcmpeq (r4),#md.plf!md.aiw!md.arw ; check aiw=1 +; +; par->par 0 0 0 - any par write clears aia,aiw + mov kipar6,kipar6 ; write par->par, should clear aiw + hcmpeq (r4),#md.plf!md.arw ; check aiw=0 +; +; acf=6 ent=1 tst (r3) 0 0 0 no no trap + mov #m0.ent!m0.ena,mmr0 ; enable mmu with traps enabled + tst (r3) ; probe read +; +; clr (r3) 0 1 0 no no trap + clr (r3) ; probe write +; +; acf=4 ent=0 tst (r3) 1 0 1 no trp set, aia set + mov #md.plf!md.att,(r4) ; set pdr + mov #m0.ena,mmr0 ; enable mmu with traps disabled + tst (r3) ; probe read + hbitne mmr0,#m0.trp ; check trp=1 + hcmpeq (r4),#md.plf!md.aia!md.att ; check aia=1 +; +; clr (r3) 1 1 1 no trp stays, aiw set + clr (r3) ; probe write + hbitne mmr0,#m0.trp ; check trp=1 + hcmpeq (r4),#md.plf!md.aia!md.aiw!md.att ; check aia=1,aiw=1 +; +; trp=0;pdr 0 0 0 - any par write clears aia,aiw + bic #m0.trp,mmr0 ; clear trp + hbiteq mmr0,#m0.trp ; check trp=0 + mov (r4),(r4) ; write pdr->pdr, should clear aia and aiw + hcmpeq (r4),#md.plf!md.att ; check aia=0,aiw=0 +; +; acf=4 ent=1 tst (r3) 1 0 1 yes trap taken, trp set, aia set + mov #m0.ent!m0.ena,mmr0 ; enable mmu with traps enabled + mov #1010$,vhvmmu + tst (r3) ; probe read + halt ; expect trap +1010$: hbitne mmr0,#m0.trp ; check trp=1 + hcmpeq (r4),#md.plf!md.aia!md.att ; check aia=1 +; +; clr (r3) 1 1 1 no no trap, aia set + clr (r3) ; probe write + hbitne mmr0,#m0.trp ; check trp=1 + hcmpeq (r4),#md.plf!md.aia!md.aiw!md.att ; check aia=1,aiw=1 +; +; trp=0;pdr 0 0 0 - any pdr write clears aia,aiw + bic #m0.trp,mmr0 ; clear trp + mov (r4),(r4) ; write pdr->pdr, should clear aia and aiw + hcmpeq (r4),#md.plf!md.att ; check aia=0,aiw=0 +; +; clr (r3) 1 1 1 yes trap taken, trp,aia,aiw set + mov #1020$,vhvmmu + clr (r3) ; probe write + halt ; expect trap +1020$: hbitne mmr0,#m0.trp ; check trp=1 + hcmpeq (r4),#md.plf!md.aia!md.aiw!md.att ; check aia=1,aiw=1 +; +; tst (r3) 1 1 1 no no trap, no additional bits + tst (r3) ; probe read + hbitne mmr0,#m0.trp ; check trp=1 + hcmpeq (r4),#md.plf!md.aia!md.aiw!md.att ; check aia=1,aiw=1 +; +; trp=0;pdr 0 0 0 - any par write clears aia,aiw + bic #m0.trp,mmr0 ; clear trp + mov (r4),(r4) ; write pdr->pdr, should clear aia and aiw + hcmpeq (r4),#md.plf!md.att ; check aia=0,aiw=0 +; +9000$: reset ; mmu off ;! MMU off + clr cp.psw + mov #<127.*md.plf>!md.arw,kipdr6 ; restore kernel mapping + mov #v..mmu+2,v..mmu ; restore mmu catcher + clr v..mmu+2 +9999$: iot ; end of test E1.1 +; +; Test E1.2 -- systematic abort/trap testing for all valid afc +++++++ +; Summary +; afc action handler abort aia aiw trap Comment +; 0 tst (r3) r-abo anr 0 0 no +; 0 add r0,(r3) w-abo anr 0 0 no +; 1 tst (r3) r-trap - 1 0 yes +; 1 add r0,(r3) w-abo ard 0 0 no +; 2 tst (r3) r-ok - 0 0 no +; 2 add r0,(r3) w-abo ard 0 0 no +; 4 tst (r3) r-trap - 1 0 yes +; 4 clr (r3) w-trap - 1 1 yes +; 5 tst (r3) r-ok - 0 0 no +; 5 clr (r3) w-trap - 1 1 yes +; 6 tst (r3) r-ok - 0 0 no +; 6 mov r0,(r3) w-ok - 0 1 no +; +te0102: mov #vhmmut,v..mmu ; setup MMU trap handler + clr v..mmu+2 ; pr0 kernel + reset + mov #m0.ent!m0.ena,mmr0 ; enable mmu with traps ;! MMU 18 + clr vhvmmu ; dont expect traps initially +; + mov #3000$,r5 ; ptr to data table + mov #kipdr6,r4 ; keep in register + mov #p6base,r3 ; probed address + mov #vhvmmu,r2 ; ptr to vhvmmu +; +1000$: mov (r5)+,(r4) ; load pdr + jmp @(r5)+ ; execute case handler +; +; case r-ok: read, no abort, no trap +1100$: clr (r2) ; no abort/trap expected + tst (r3) ; probe read + br 1900$ ; to ok-check +; +; case r-abo: read, abort +1200$: mov #vhmmua,v..mmu ; setup MMU abort handler + mov (r5)+,1210$ + mov #1210$,(r2) + tst (r3) ; probe read + halt ; expect abort +1210$: .word 0,0 + br 1910$ ; to abo-check +; +; case r-trap: read, trap +1300$: mov #vhmmut,v..mmu ; setup MMU trap handler + mov #1900$,(r2) ; to ok-check + tst (r3) ; probe read + halt ; expect trap +; +; case w-ok: write, no abort, no trap +1400$: clr (r2) ; no abort/trap expected + mov r0,(r3) ; probe write + br 1900$ ; to ok-check +; +; case w-abo: write, abort +1500$: mov #vhmmua,v..mmu ; setup MMU abort handler + mov (r5)+,1510$ + mov #1510$,(r2) + add r0,(r3) ; probe write + halt ; expect abort +1510$: .word 0,0 + br 1910$ ; to tr-check +; +; case w-trap: write, trap +1600$: mov #vhmmut,v..mmu ; setup MMU trap handler + mov #1900$,(r2) + clr (r3) ; probe write + halt ; expect trap +; +1900$: tst (r5)+ ; drop unused mmr0 info +1910$: mov (r5)+,r0 ; get pdrexp + hcmpeq (r4),r0 ; check pdr + mov (r4),(r4) ; clear pdr aia,aiw + bic #m0.trp,mmr0 ; clear mmr0 trp flag + tst (r5) ; look at next case + beq 9000$ ; if eq end sentinel found ? + br 1000$ ; if ne go for next case +; +3000$: .word md.plf ; afc=0 + read: - anr ------- + .word 1200$ ; r-abo + .word m0.anr!m0.ent!<6*m0.pno>!m0.ena ; mmr0 + .word md.plf ; pdf: no aib +; + .word md.plf ; afc=0 + write: - anr ------- + .word 1500$ ; w-abo + .word m0.anr!m0.ent!<6*m0.pno>!m0.ena ; mmr0 + .word md.plf ; pdf: no aib +; + .word md.plf!md.ata ; afc=1 + read: - trp aia --- + .word 1300$ ; r-trap + .word 0 ; mmr0 + .word md.plf!md.aia!md.ata ; pdf: aia +; + .word md.plf!md.ata ; afc=1 + write: - ard ------- + .word 1500$ ; w-abo + .word m0.ard!m0.ent!<6*m0.pno>!m0.ena ; mmr0 + .word md.plf!md.ata ; pdf: no aib +; + .word md.plf!md.ara ; afc=2 + read: ------------- + .word 1100$ ; r-ok + .word 0 ; mmr0 + .word md.plf!md.ara ; pdf: no aib +; + .word md.plf!md.ara ; afc=2 + write: - ard ------- + .word 1500$ ; w-abo + .word m0.ard!m0.ent!<6*m0.pno>!m0.ena ; mmr0 + .word md.plf!md.ara ; pdf: no aib +; + .word md.plf!md.att ; afc=4 + read: - trp aia --- + .word 1300$ ; r-trap + .word 0 ; mmr0 + .word md.plf!md.aia!md.att ; pdf: aia +; + .word md.plf!md.att ; afc=4 + write - trp aia,aiw + .word 1600$ ; w-trap + .word 0 ; mmr0 + .word md.plf!md.aia!md.aiw!md.att ; pdf: aia aiw +; + .word md.plf!md.art ; afc=5 + read: ------------- + .word 1100$ ; r-ok + .word 0 ; mmr0 + .word md.plf!md.art ; pdf: no aib +; + .word md.plf!md.art ; afc=5 + write: - trp aia,aiw + .word 1600$ ; w-trap + .word 0 ; mmr0 + .word md.plf!md.aia!md.aiw!md.art ; pdf: aia aiw +; + .word md.plf!md.arw ; afc=6 + read: ------------- + .word 1100$ ; r-ok + .word 0 ; mmr0 + .word md.plf!md.arw ; pdf: no aib +; + .word md.plf!md.arw ; afc=6 + write: - aiw ------- + .word 1400$ ; w-ok + .word 0 ; mmr0 + .word md.plf!md.aiw!md.arw ; pdf: aiw +; + .word 0 ; end sentinel ------------------------------ +; +9000$: reset ; mmu off ;! MMU off + clr cp.psw + mov #<127.*md.plf>!md.arw,kipdr6 ; restore kernel mapping + mov #v..mmu+2,v..mmu ; restore mmu catcher + clr v..mmu+2 +9999$: iot ; end of test E1.2 +; ; END OF ALL TESTS - loop closure ============================================ ; mov tstno,r0 ; hack, for easy monitoring ... - hcmpeq tstno,#13. ; all tests done ? + hcmpeq tstno,#15. ; all tests done ? ; jmp loop ; ; kernel handlers ============================================================ ; -; vhemmu - expected mmu abort/trap handler +++++++++++++++++++++++++++++++++++ -; used to catch expected MMU aborts or traps +; vhmmua - expected mmu abort handler ++++++++++++++++++++++++++++++++++++++++ +; used to catch expected MMU aborts ; the pointer to expected mmr0/mmr1 values must be in vhvmmu -; code will continue after context +; code will continue after the test value context ; execution will clear vhvmmu ; --> vhvmmu must be set for each execution ; the handler uses and modifies r0,r1 ; --> tests should only use r2,...,r5 ; -vhemmu: mov vhvmmu,r1 ; get context +vhmmua: mov vhvmmu,r1 ; get context beq 1000$ ; if 0 halt mov mmr0,r0 bic #m0.ico,r0 ; mask ico (for Simh compatibility) @@ -1313,6 +1619,24 @@ vhemmu: mov vhvmmu,r1 ; get context 1000$: halt vhvmmu: .word 0 ; context pointer ; +; vhmmut - expected mmu trap handler +++++++++++++++++++++++++++++++++++++++++ +; used to catch expected MMU traps +; the pointer to continuation address must be in vhvmmu +; execution will clear vhvmmu +; --> vhvmmu must be set for each execution +; the handler uses and modifies r0,r1 +; --> tests should only use r2,...,r5 +; +vhmmut: mov vhvmmu,r1 ; get context + beq 1000$ ; if 0 halt + mov mmr0,r0 + hbiteq r0,#m0.anr!m0.ale!m0.ard ; check abort flags 0 + hbitne r0,#m0.trp ; check trap flag 1 + mov r1,(sp) ; set up kernel return address + clr vhvmmu ; reset context + rti ; end return to continuation address +1000$: halt +; ; vhuemt - emt handler, drop frame, continue in kernel mode ++++++++++++++++++ ; use to end user/supervisor mode code with an emt xxx ; the kernel continution address must be written to vhustp