1
0
mirror of https://github.com/simh/simh.git synced 2026-04-17 08:41:28 +00:00

PDP11: Properly range check DMA access to the I/O page

Make sure that DMA access to the I/O page can only see addresses on the
Qbus/Unibus and not internal CPU registers
This commit is contained in:
Mark Pizzolato
2018-09-06 11:03:45 -07:00
parent 5f0370749e
commit 7677dad67d
16 changed files with 56 additions and 22 deletions

View File

@@ -66,6 +66,7 @@ extern void fixup_mbus_tab (void);
t_stat (*iodispR[IOPAGESIZE >> 1])(int32 *dat, int32 ad, int32 md);
t_stat (*iodispW[IOPAGESIZE >> 1])(int32 dat, int32 ad, int32 md);
DIB *iodibp[IOPAGESIZE >> 1];
int32 int_vec[IPL_HLVL][32]; /* int req to vector */
int32 (*int_ack[IPL_HLVL][32])(void); /* int ack routines */
@@ -119,6 +120,23 @@ if (iodispW[idx]) {
return SCPE_NXM;
}
/* I/O page CPU register verifier
Inputs:
pa = address
Outputs:
status = TRUE or FALSE
*/
t_bool iopageCPUReg (uint32 pa)
{
int32 idx;
DIB *dibp;
idx = (pa & IOPAGEMASK) >> 1;
dibp = iodibp[idx];
return (dibp && (dibp->dptr == &cpu_dev));
}
/* Calculate interrupt outstanding
In a Qbus system, all device interrupts are treated as BR4 */
@@ -237,11 +255,12 @@ int32 Map_ReadB (uint32 ba, int32 bc, uint8 *buf)
{
uint32 alim, lim, ma;
if (ba >= IOPAGEBASE) {
if (ba >= (IOPAGEBASE & BUSMASK)) {
int32 value;
while (bc) {
if (iopageR( &value, (ba & ~1), READ) != SCPE_OK)
if (iopageCPUReg (ba) ||
(iopageR( &value, (ba & ~1), READ) != SCPE_OK))
break;
*buf++ = (uint8) (((ba & 1)? (value >> 8): value) & 0xff);
ba++;
@@ -277,12 +296,13 @@ int32 Map_ReadW (uint32 ba, int32 bc, uint16 *buf)
{
uint32 alim, lim, ma;
if (ba >= IOPAGEBASE) {
if (ba >= (IOPAGEBASE & BUSMASK)) {
int32 value;
if ((ba & 1) || (bc & 1))
return bc;
while (bc) {
if (iopageR( &value, ba, READ) != SCPE_OK)
if (iopageCPUReg (ba) ||
(iopageR( &value, ba, READ) != SCPE_OK))
break;
*buf++ = (uint16) (value & 0xffff);
ba += 2;
@@ -318,9 +338,10 @@ int32 Map_WriteB (uint32 ba, int32 bc, const uint8 *buf)
{
uint32 alim, lim, ma;
if (ba >= IOPAGEBASE) {
if (ba >= (IOPAGEBASE & BUSMASK)) {
while (bc) {
if (iopageW( ((int32) *buf++) & 0xff, ba, WRITEB) != SCPE_OK)
if (iopageCPUReg (ba) ||
(iopageW( ((int32) *buf++) & 0xff, ba, WRITEB) != SCPE_OK))
break;
ba++;
bc--;
@@ -355,11 +376,12 @@ int32 Map_WriteW (uint32 ba, int32 bc, const uint16 *buf)
{
uint32 alim, lim, ma;
if (ba >= IOPAGEBASE) {
if (ba >= (IOPAGEBASE & BUSMASK)) {
if ((ba & 1) || (bc & 1))
return bc;
while (bc) {
if (iopageW( ((int32) *buf++) & 0xffff, ba, WRITE) != SCPE_OK)
if (iopageCPUReg (ba) ||
(iopageW( ((int32) *buf++) & 0xffff, ba, WRITE) != SCPE_OK))
break;
ba += 2;
bc -= 2;