## 2022-08-03: tests with SimH V3.11-0 and 2.11BSD 447

### Background
The `MMR1` response after an MMU abort in an FPP instruction depends on the CPU.
On an 11/70, the registers reflect the state at abort and `MMR1` returns the
change. On a J11, the registers are unchanged, and `MMR1` returns zero.

SimH V3.11-0 used the J11 FPP MMU abort handling for _all_ CPU models.
So even when an 11/70 is modeled, the behavior is like a J11.

The 2.11BSD stack extension logic checks whether the `sp` is below the
current stack allocation, and only in that case, the stack is extended.
On a J11-based system that fails, that's why 2.11BSD up to #473 has a
workaround and shifts the `sp` down by 4 _if and only if_ a J11 was
probed at boot time. The pertinent code in `/usr/src/sys/pdp/trap.c` is
```
    osp = sp;
    if (kdj11)
        osp -= 4;
    if (backup(u.u_ar0) == 0)
        if (!(u.u_sigstk.ss_flags & SA_ONSTACK) && grow((u_int)osp))
            goto out;
    i = SIGSEGV;
```

That leads to two vulnerabilities:
- a `double` push of 8 bytes might fail on J11 systems, real or simulated,
- in a SimH 11/70, which probes as an 11/70 but behaves like a J11, any
  push from an FPP instruction might fail.

The first is a _2.11BSD issue_, the second is a _SimH issue_.

The tests were run under `tcsh`, it gives "Segmentation fault" in case of
a problem. Under `sh` one gets "Memory fault".

### SimH in 11/94 mode
SimH pdp11 started with
```
set cpu 11/94
```
and 2.11BSD starts with
```
94Boot from xp(0,0,0) at 0176700
```
Extending the stack with `float` pushes is no problem until the stack segment
has grown to 020000 and memory is really exhausted:
```
./stktst f ' 1024'
  # stktst-I: before sp 177334 (0,  4,36); 177334 (0,  4,36);
  # stktst-I: after  sp 177334 (0,  4,36); 177334 (0,  4,36); 167334 (0, 68,36);
./stktst f '14263'
  # stktst-I: before sp 177334 (0,  4,36); 177334 (0,  4,36);
  # stktst-I: after  sp 177334 (0,  4,36); 177334 (0,  4,36); 020000 (6,127,64);
./stktst f '14264'
  # stktst-I: before sp 177334 (0,  4,36); 177334 (0,  4,36);
  # Segmentation fault (core dumped)
```

Extending with `double` pushes can fail depending on the alignment of the
`double`. If they are click aligned all is fine, the 4 byte offset in
2.11BSB ensures that the `sp` is below the allocation. In case of a
misalignment of 2 or 4 bytes, this is not the case, one gets a `SIGSEGV`.
In case of a misalignment of 6 bytes, it works again.
```
./stktst d '1024' -c '   2' -o '   0'
  # stktst-I: before sp 177304 (0,  4,60); 177200 (0,  5,64);
  # stktst-I: after  sp 177304 (0,  4,60); 177200 (0,  5,64); 157200 (1,  5,64);
./stktst d '1024' -c '   2' -o '  -2'
  # stktst-I: before sp 177304 (0,  4,60); 177176 (0,  6, 2);
  # Segmentation fault (core dumped)
./stktst d '1024' -c '   2' -o '  -4'
  # stktst-I: before sp 177304 (0,  4,60); 177174 (0,  6, 4);
  # Segmentation fault (core dumped)
./stktst d '1024' -c '   2' -o '  -6'
  # stktst-I: before sp 177304 (0,  4,60); 177172 (0,  6, 6);
  # stktst-I: after  sp 177304 (0,  4,60); 177172 (0,  6, 6); 157172 (1,  6, 6);
```
With some trial and error one can determine the situation where it fails:
```
./stktst d ' 151' -c '   2' -o '  -2'
  # stktst-I: before sp 177304 (0,  4,60); 177176 (0,  6, 2);
  # stktst-I: after  sp 177304 (0,  4,60); 177176 (0,  6, 2); 174706 (0, 24,58);
./stktst d ' 152' -c '   2' -o '  -2'
  # stktst-I: before sp 177304 (0,  4,60); 177176 (0,  6, 2);
  # Segmentation fault (core dumped)
```
That's after 25 clicks. The initial stack size is 20 clicks
(see [SSIZE](https://www.retro11.de/ouxr/211bsd/usr/src/sys/pdp/machparam.h.html#m:SSIZE)) and the stack segment is a bit larger to accommodate argument and
environment structures.
So the `double` pushes fail when the initial allocation is exhausted.

### SimH in 11/70 mode, FPP enabled
SimH pdp11 started with
```
set cpu 11/70
```
and 2.11BSD starts with
```
70Boot from xp(0,0,0) at 0176700
```
The CPU probes now as 11/70, indicated by the `70Boot` startup message,
but behaves like a J11 for `MMR1`. The 2.11BSD J11 hack isn't done and
_all_ FPP pushes are vulnerable. That's what tests show:
```
# word push from FPP
./stktst i '4096' -c '   2' -o '  -2'
  # stktst-I: before sp 177304 (0,  4,60); 177176 (0,  6, 2);
  # Segmentation fault (core dumped)
 ./stktst i ' 607' -c '   2' -o '  -2'
  # stktst-I: before sp 177304 (0,  4,60); 177176 (0,  6, 2);
  # stktst-I: after  sp 177304 (0,  4,60); 177176 (0,  6, 2); 174700 (0, 24,64);
./stktst i ' 608' -c '   2' -o '  -2'
  # stktst-I: before sp 177304 (0,  4,60); 177176 (0,  6, 2);
#
# long push from FPP
./stktst l '2048' -c '   2' -o '  -2'
  # stktst-I: before sp 177304 (0,  4,60); 177176 (0,  6, 2);
  # Segmentation fault (core dumped)
./stktst l ' 303' -c '   2' -o '  -2'
  # stktst-I: before sp 177304 (0,  4,60); 177176 (0,  6, 2);
  # stktst-I: after  sp 177304 (0,  4,60); 177176 (0,  6, 2); 174702 (0, 24,62);
./stktst l ' 304' -c '   2' -o '  -2'
  # stktst-I: before sp 177304 (0,  4,60); 177176 (0,  6, 2);
  # Segmentation fault (core dumped)
#
# float push from FPP
./stktst f '2048' -c '   2' -o '  -2'
  # stktst-I: before sp 177304 (0,  4,60); 177176 (0,  6, 2);
  # Segmentation fault (core dumped)
./stktst f ' 303' -c '   2' -o '  -2'
  # stktst-I: before sp 177304 (0,  4,60); 177176 (0,  6, 2);
  # stktst-I: after  sp 177304 (0,  4,60); 177176 (0,  6, 2); 174702 (0, 24,62);
./stktst f ' 304' -c '   2' -o '  -2'
  # stktst-I: before sp 177304 (0,  4,60); 177176 (0,  6, 2);
  # Segmentation fault (core dumped)
#
# double push from FPP
./stktst d '1024' -c '   2' -o '  -2'
  # stktst-I: before sp 177304 (0,  4,60); 177176 (0,  6, 2);
  # Segmentation fault (core dumped)
./stktst d ' 151' -c '   2' -o '  -2'
  # stktst-I: before sp 177304 (0,  4,60); 177176 (0,  6, 2);
  # stktst-I: after  sp 177304 (0,  4,60); 177176 (0,  6, 2); 174706 (0, 24,58);
./stktst d ' 152' -c '   2' -o '  -2'
  # stktst-I: before sp 177304 (0,  4,60); 177176 (0,  6, 2);
  # Segmentation fault (core dumped)
```
All FPP pushes fail when the first stack extend is reached.
This is, as stated before, not a 2.11BSD issue but a SimH issue.

### SimH in 11/70 mode, FPP disabled
SimH pdp11 started with
```
set cpu 11/70
set cpu nofpp
```
and 2.11BSD starts with
```
70Boot from xp(0,0,0) at 0176700
```
All FPP instructions trap and are emulated by a kernel mode handler with
plain integer arithmetic. Stack extends work as expected:
```
./stktst d '1024' -c '   2' -o '  -2'
  # stktst-I: before sp 177304 (0,  4,60); 177176 (0,  6, 2);
  # stktst-I: after  sp 177304 (0,  4,60); 177176 (0,  6, 2); 157176 (1,  6, 2);
# fill 2 pages
./stktst d '1999' -c '   2' -o '  -2'
  # stktst-I: before sp 177304 (0,  4,60); 177176 (0,  6, 2);
  # stktst-I: after  sp 177304 (0,  4,60); 177176 (0,  6, 2); 140006 (1,127,58);
# fill 3 pages
./stktst d '3023' -c '   2' -o '  -2'
  # stktst-I: before sp 177304 (0,  4,60); 177176 (0,  6, 2);
  # stktst-I: after  sp 177304 (0,  4,60); 177176 (0,  6, 2); 120006 (2,127,58);
# fill 5 pages
./stktst d '5071' -c '   2' -o '  -2'
  # stktst-I: before sp 177304 (0,  4,60); 177176 (0,  6, 2);
  # stktst-I: after  sp 177304 (0,  4,60); 177176 (0,  6, 2); 060006 (4,127,58);
# fill 6 pages
./stktst d '6095' -c '   2' -o '  -2'
  # stktst-I: before sp 177304 (0,  4,60); 177176 (0,  6, 2);
  # stktst-I: after  sp 177304 (0,  4,60); 177176 (0,  6, 2); 040006 (5,127,58);
# fill 7 pages
./stktst d '7119' -c '   2' -o '  -2'
  # stktst-I: before sp 177304 (0,  4,60); 177176 (0,  6, 2);
  # stktst-I: after  sp 177304 (0,  4,60); 177176 (0,  6, 2); 020006 (6,127,58);
```
`stktst` doesn't use separate I/D space, so page 0 is used by code and data.
The stack segment can't grow larger than 7 pages, and an extension beyond must
fail. And it does fail, a bit more spectacular than it should:
```
# and try one more
./stktst d '7120' -c '   2' -o '  -2'
  # ka6 36722 aps 147472
  # pc 161324 ps 30004
  # ov 4
  # cpuerr 20
  # trap type 0
  # panic: trap
  # syncing disks... done
```
**Note added 2022-08-06**:
This kernel _panic_ is a Deja-vu of the problem discovered in 2017, see
[blog post](https://wfjm.github.io/blogs/211bsd/2017-06-06-kernel-panic-here-doc-tcsh.html), and fixed with 2.11BSD patch [453](https://www.retro11.de/data/211bsd/patches/453). Due to a mistake, the `stktst` tests were done on a system
at patch level 447 and not on an up-to-date system. That doesn't change any
of the prior findings on the stack extend logic.
