mirror of
https://github.com/wfjm/w11.git
synced 2026-01-12 00:43:01 +00:00
pdp11_sequencer BUGFIX: restore PSW after vector push abort
- rtl/w11a/pdp11_sequencer.vhd: BUGFIX: restore PSW after vector push abort - tools - tcode/cpu_details.mac: add A3.6, verify PSW after vector push abort - tcode/cpu_mmu.mac: D2.1: verify PSW - gwstart/lib/dpath.tcl: added, show dpath basics
This commit is contained in:
parent
5d8c065ee4
commit
12ada8fbf7
@ -50,6 +50,10 @@ The full set of tests is only run for tagged releases.
|
||||
- tcl/rw11/shell_egd.tcl: add ODX format options for .e command
|
||||
|
||||
### Bug Fixes
|
||||
- rtl/w11a
|
||||
- pdp11_sequencer:
|
||||
- BUGFIX: restore PSW after vector push abort, see
|
||||
[ECO-041](ECO-041-vpush_abort_psw.md)
|
||||
- tools/bin/asm-11
|
||||
- BUGFIX: fix directly nested .if behavior
|
||||
- tools/tcode
|
||||
|
||||
@ -47,3 +47,7 @@ first entry.
|
||||
This deficit had no impact on OS operation and had therefore low priority.
|
||||
However, the goal of the w11 is to be an as precise as feasible replica of
|
||||
the 11/70, and it was overdue to fix this.
|
||||
|
||||
### Note 2023-03-22
|
||||
This fixed only part of the problem, see [ECO-041](ECO-041-vpush_abort_psw.md)
|
||||
for the full solution.
|
||||
39
doc/ECO-041-vpush_abort_psw.md
Normal file
39
doc/ECO-041-vpush_abort_psw.md
Normal file
@ -0,0 +1,39 @@
|
||||
# ECO-041: Get correct `PSW` after vector push abort (2023-03-22)
|
||||
|
||||
### Scope
|
||||
- [ECO-036](ECO-036-vpush_abort_ps.md) fixed only part of the problem
|
||||
- affects: all w11a systems
|
||||
|
||||
### Symptom summary
|
||||
The tcode [cpu_mmu.mac](../tools/tcode/cpu_mmu.mac) failed in test D2.1 when
|
||||
running on the E11 simulator while it happily executed on w11.
|
||||
|
||||
### Analysis
|
||||
The changes done in [ECO-036](ECO-036-vpush_abort_ps.md) ensured that the
|
||||
correct `PS` was saved on the stack. But they did not restore the `PSW` of
|
||||
the CPU. The vector flow has therefore
|
||||
- loaded the `PSW` with current mode = supervisor in the initial PIRQ
|
||||
vector fetch
|
||||
- was aborted during a vector push
|
||||
- loaded again the `PSW` in the following MMU vector fetch. Because the `PSW`
|
||||
wasn't rolled back, the current mode was still supervisor, which now became
|
||||
the previous mode, the only field not taken from the new `PS`.
|
||||
|
||||
The previous mode in the `PSW` should, of course, reflect the current mode
|
||||
active before the first entry in the vector flow. In the test D2.1 this is
|
||||
kernel mode.
|
||||
|
||||
### Fixes
|
||||
The states `s_vec_pushps_w` and `s_vec_pushpc_w` now restore the `PSW`
|
||||
when an abort is detected. This also ensures that the correct `PS` is
|
||||
saved when the vector flow is re-entered. The special handling in
|
||||
`do_start_vec` that was introduced in [ECO-036](ECO-036-vpush_abort_ps.md)
|
||||
was removed.
|
||||
|
||||
### Hindsight
|
||||
This bug was first discovered by cross-checking with the E11 simulator.
|
||||
cpu_mmu.mac test D2.1 failed under E11 and worked on w11. The reason was that
|
||||
the test was faulty too and expected that the `PSW` previous mode is already
|
||||
the mode of the failed stack push. So a bug in the test hid a bug in the CPU.
|
||||
Great to have a second PDP-11 simulator which provides a very close 11/70
|
||||
replica. That helps to avoid such double errors in the future.
|
||||
@ -1,4 +1,4 @@
|
||||
-- $Id: pdp11_sequencer.vhd 1349 2023-01-11 14:52:42Z mueller $
|
||||
-- $Id: pdp11_sequencer.vhd 1384 2023-03-22 07:35:32Z mueller $
|
||||
-- SPDX-License-Identifier: GPL-3.0-or-later
|
||||
-- Copyright 2006-2023 by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
|
||||
--
|
||||
@ -13,11 +13,12 @@
|
||||
--
|
||||
-- Revision History:
|
||||
-- Date Rev Version Comment
|
||||
-- 2023-03-21 1384 1.6.29 BUGFIX: restore PSW after vector push abort
|
||||
-- 2023-01-11 1349 1.6.28 BUGFIX: handle CPUERR.rsv correctly
|
||||
-- 2023-01-02 1342 1.6.27 BUGFIX: cc state unchanged after abort
|
||||
-- 2022-12-26 1337 1.6.26 tbit logic overhaul 2, now fully 11/70 compatible
|
||||
-- 2022-12-12 1330 1.6.25 implement MMR0,MMR2 instruction complete
|
||||
-- 2022-12-10 1329 1.6.24 BUGFIX: get correct PS after vector push abort
|
||||
-- 2022-12-10 1329 1.6.24 BUGFIX: store correct PS after vector push abort
|
||||
-- 2022-12-05 1324 1.6.23 tbit logic overhaul; use treq_tbit; cleanups
|
||||
-- use resetcnt for 8 cycle RESET wait
|
||||
-- 2022-11-29 1323 1.6.22 rename adderr -> oddadr, don't set after err_mmu
|
||||
@ -593,7 +594,7 @@ begin
|
||||
pvector : in slv9_2) is
|
||||
begin
|
||||
pndpcntl.dtmp_sel := c_dpath_dtmp_psw; -- DTMP = PSW
|
||||
pndpcntl.dtmp_we := not R_STATUS.in_vecflow; -- save PS on first entry
|
||||
pndpcntl.dtmp_we := '1'; -- save PS
|
||||
pndpcntl.ounit_azero := '1'; -- OUNIT A = 0
|
||||
pndpcntl.ounit_const := pvector & "00"; -- vector
|
||||
pndpcntl.ounit_bsel := c_ounit_bsel_const;-- OUNIT B=const(vector)
|
||||
@ -2303,6 +2304,12 @@ begin
|
||||
|
||||
nstate := s_vec_pushps_w;
|
||||
do_memcheck(nstate, nstatus, imemok);
|
||||
if VM_STAT.err = '1' then -- if err restore PS from DTMP
|
||||
ndpcntl.ounit_asel := c_ounit_asel_dtmp; -- OUNIT A=DTMP
|
||||
ndpcntl.ounit_const := "000000000"; -- OUNIT const=0
|
||||
ndpcntl.psr_func := c_psr_func_wall; -- write all fields
|
||||
ndpcntl.psr_we := '1'; -- re-store PS from DTMP
|
||||
end if;
|
||||
if imemok then
|
||||
ndpcntl.dsrc_we := '1'; -- update DSRC
|
||||
ndpcntl.gr_we := '1'; -- update SP too
|
||||
@ -2330,6 +2337,12 @@ begin
|
||||
|
||||
nstate := s_vec_pushpc_w;
|
||||
do_memcheck(nstate, nstatus, imemok);
|
||||
if VM_STAT.err = '1' then -- if err restore PS from DTMP
|
||||
ndpcntl.ounit_asel := c_ounit_asel_dtmp; -- OUNIT A=DTMP
|
||||
ndpcntl.ounit_const := "000000000"; -- OUNIT const=0
|
||||
ndpcntl.psr_func := c_psr_func_wall; -- write all fields
|
||||
ndpcntl.psr_we := '1'; -- re-store PS from DTMP
|
||||
end if;
|
||||
if imemok then
|
||||
nstatus.treq_tbit := PSW.tflag; -- copy PSW.tflag to treq_bit
|
||||
nstatus.in_vecflow := '0'; -- signal end vector flow
|
||||
@ -2448,7 +2461,7 @@ begin
|
||||
do_start_vec(nstate, ndpcntl, lvector);
|
||||
end if;
|
||||
end if;
|
||||
|
||||
|
||||
when s_cpufail => -- -----------------------------------
|
||||
nstatus.cpugo := '0';
|
||||
nstatus.cpurust := c_cpurust_sfail;
|
||||
|
||||
17
tools/gwstart/lib/dpath.tcl
Normal file
17
tools/gwstart/lib/dpath.tcl
Normal file
@ -0,0 +1,17 @@
|
||||
# $Id: dpath.tcl 1384 2023-03-22 07:35:32Z mueller $
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
# Copyright 2023- by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
|
||||
#
|
||||
# pdp11_dpath basics
|
||||
#
|
||||
gwaddcom "dpath"
|
||||
gwaddsig {**.dpath.clk}
|
||||
gwaddsig {**.dpath.cntl.dsrc_we}
|
||||
gwaddsig {**.dpath.cntl.dsrc_sel}
|
||||
gwaddsig -oct {**.dpath.r_dsrc}
|
||||
gwaddsig {**.dpath.cntl.ddst_we}
|
||||
gwaddsig {**.dpath.cntl.ddst_sel}
|
||||
gwaddsig -oct {**.dpath.r_ddst}
|
||||
gwaddsig {**.dpath.cntl.dtmp_we}
|
||||
gwaddsig {**.dpath.cntl.dtmp_sel}
|
||||
gwaddsig -oct {**.dpath.r_dtmp}
|
||||
@ -1,9 +1,10 @@
|
||||
; $Id: cpu_details.mac 1384 2023-03-22 07:35:32Z mueller $
|
||||
; $Id: cpu_details.mac 1385 2023-03-23 08:27:44Z mueller $
|
||||
; SPDX-License-Identifier: GPL-3.0-or-later
|
||||
; Copyright 2022-2023 by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
|
||||
;
|
||||
; Revision History:
|
||||
; Date Rev Version Comment
|
||||
; 2023-03-22 1385 1.1.3 add A3.6, verify PSW after vector push abort
|
||||
; 2023-03-21 1384 1.1.2 remove e11 exemptions for A2.3, A2.5-9,
|
||||
; A3.2 part 2+3; A3.3, A4.4 part 3+4;
|
||||
; A4.4 part 5: skip on e11 (SPL in u mode handling)
|
||||
@ -80,7 +81,8 @@
|
||||
; part 2: test instructions that should not trap
|
||||
; part 3: test that interrupt (from PIRQ) vector push traps
|
||||
; A3.4 red stack abort conditions
|
||||
; A3.5 vector push abort recovery
|
||||
; A3.5 vector push abort recovery - saved PS
|
||||
; A3.6 vector push abort recovery - restored PSW
|
||||
; A4 PSW + tbit traps
|
||||
; A4.1 PSW direct write/read test
|
||||
; part 1: all bits except register set (cp.ars)
|
||||
@ -806,7 +808,7 @@ ta0304: vecset v..iit,1000$,cp.pr7 ; set up iit handler, lockout interrupts
|
||||
;
|
||||
9999$: iot ; end of test A3.4
|
||||
;
|
||||
; Test A3.5 -- vector push abort recovery ++++++++++++++++++++++++++++
|
||||
; Test A3.5 -- vector push abort recovery - saved PS +++++++++++++++++
|
||||
; Verify that the frame pushed to the emergency stack after a vector push
|
||||
; abort has the PS and PC values at entry into the initial vector flow and
|
||||
; not the values read in the vector fetch of the failed vector flow.
|
||||
@ -846,14 +848,14 @@ ta0305: cmpb systyp,#sy.sih ; skip on SimH (different stklim logic)
|
||||
hcmpeq (sp),#300$ ; PC: return after trap
|
||||
hcmpeq 2(sp),#cp.pr4!cp000c ; PS: should be code signature
|
||||
;
|
||||
; trap without error, checks in_vecflow reset ----
|
||||
; trap without error -----------------------------
|
||||
clr cp.slr ; STKLIM to default
|
||||
mov #600$,v..trp ; set up TRAP handler (continuation)
|
||||
mov #stack,sp ; 1st push will fail
|
||||
mov #stack,sp ; SP to default
|
||||
spl 2 ; use PR2 as signature code
|
||||
ccc ; clear all ccs
|
||||
sez ; and set z
|
||||
trap 300 ; will fail
|
||||
trap 300 ; will work
|
||||
500$: halt
|
||||
;
|
||||
600$: hcmpeq #stack-4,sp ; check stack, 1 frame
|
||||
@ -868,6 +870,43 @@ ta0305: cmpb systyp,#sy.sih ; skip on SimH (different stklim logic)
|
||||
;
|
||||
9999$: iot ; end of test A3.5
|
||||
;
|
||||
; Test A3.6 -- vector push abort recovery - restored PSW +++++++++++++
|
||||
; Verify that the PSW is restored when a vector flow is aborted during a push.
|
||||
; The previous test A3.5 checks that the correct PS is saved on stack. This
|
||||
; test verifies that the PSW is restored before the new vector is fetched.
|
||||
; This affects the previous mode bits because they are taken from the PSW
|
||||
; at the time the new PS is fetched. To test this, PIRQ is set up with a
|
||||
; handler in supervisor space and an odd SP value. That will cause a vector 4
|
||||
; abort during first push. A PIRQ is requested from kernel mode. The PSW
|
||||
; seen by the vector 4 handler should see a previous mode of kernel, and not
|
||||
; supervisor.
|
||||
; See also cpu_mmu tests C2.5,C2.6, they check vector push abort by mmu.
|
||||
;
|
||||
ta0306: vecset v..pir,200$,cp.cms!cp.pr6 ; set up PIRQ handler
|
||||
vecset v..iit,300$,cp.pr5 ; set up iit handler
|
||||
;
|
||||
mov #cp.pms,cp.psw ; supervisor now previous mode
|
||||
push #1777 ; use odd address
|
||||
mtpi sp ; for supervisor stack
|
||||
mov #cp.pr1,cp.psw ; code signature PR1, back to kernel
|
||||
movb #bit04,cp.pir+1 ; request PIRQ 4
|
||||
100$: halt
|
||||
200$: halt ; PIRQ handler, should not be called
|
||||
;
|
||||
300$: hcmpeq #cp.pr5,cp.psw ; CM=PM=kernel
|
||||
hcmpeq #stack-4,sp ; 1 frame pushed
|
||||
hcmpeq #100$,(sp) ; saved PC
|
||||
hcmpeq #cp.pr1,2(sp) ; saved PC
|
||||
;
|
||||
; restore
|
||||
vecclr v..pir ; v..pir to catcher
|
||||
vecclr v..iit ; v..iit to catcher
|
||||
mov #stack,sp ; SP to default
|
||||
clr cp.pir ; cancel PIRQ
|
||||
clr cp.psw ; back to kernel PR0
|
||||
;
|
||||
9999$: iot ; end of test A3.6
|
||||
|
||||
; Test A4: PSW + tbit traps +++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
; This sub-section verifies operation of PSW register and tbit traps.
|
||||
;
|
||||
@ -2038,7 +2077,7 @@ tc0103: vecset v..iit,vhugen ; set iit handler, pr0 kernel
|
||||
; END OF ALL TESTS - loop closure ============================================
|
||||
;
|
||||
mov tstno,r0 ; hack, for easy monitoring ...
|
||||
hcmpeq tstno,#39. ; all tests done ?
|
||||
hcmpeq tstno,#40. ; all tests done ?
|
||||
;
|
||||
jmp loop
|
||||
;
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
; $Id: cpu_mmu.mac 1383 2023-03-20 08:19:14Z mueller $
|
||||
; $Id: cpu_mmu.mac 1385 2023-03-23 08:27:44Z mueller $
|
||||
; SPDX-License-Identifier: GPL-3.0-or-later
|
||||
; Copyright 2022-2023 by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
|
||||
;
|
||||
@ -1932,6 +1932,8 @@ td0201: cmpb systyp,#sy.sih ; skip on on SimH
|
||||
; Note: MMR2 holds the vector address. So push PS and PC of that vector
|
||||
; to kernel stack and start handler with an RTT.
|
||||
;
|
||||
ccc ; clear ccs before PSW check
|
||||
hcmpeq #cp.pr7,cp.psw ; PSW has CM=PM=kernel
|
||||
hcmpeq #m0.ale!m0.ent!m0.ico!m0.pms!<3*m0.pno>!m0.ena,r0 ; check mmr0
|
||||
hcmpeq #240,mmr2 ; check mmr2: PIRQ vector
|
||||
;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user