From 7677dad67d5a9312c1ab023d8ffdedd1663a79b0 Mon Sep 17 00:00:00 2001 From: Mark Pizzolato Date: Thu, 6 Sep 2018 11:03:45 -0700 Subject: [PATCH] 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 --- PDP11/pdp11_defs.h | 2 ++ PDP11/pdp11_io.c | 38 ++++++++++++++++++++++++++++++-------- PDP11/pdp11_io_lib.c | 18 ++++-------------- VAX/vax610_defs.h | 2 ++ VAX/vax610_io.c | 1 + VAX/vax630_defs.h | 2 ++ VAX/vax630_io.c | 1 + VAX/vax730_defs.h | 2 ++ VAX/vax730_uba.c | 1 + VAX/vax750_defs.h | 2 ++ VAX/vax750_uba.c | 1 + VAX/vax780_defs.h | 2 ++ VAX/vax780_uba.c | 1 + VAX/vax860_defs.h | 2 ++ VAX/vax_io.c | 1 + VAX/vaxmod_defs.h | 2 ++ 16 files changed, 56 insertions(+), 22 deletions(-) diff --git a/PDP11/pdp11_defs.h b/PDP11/pdp11_defs.h index 6fbbf9b7..868d47ac 100644 --- a/PDP11/pdp11_defs.h +++ b/PDP11/pdp11_defs.h @@ -528,6 +528,8 @@ struct pdp_dib { /* DEVICE structure (e.g., DZ, VH, DL, DC). */ /* Populated by auto-configure */ struct pdp_dib *next; /* devices with more than one DIB can chain them */ + DEVICE *dptr; /* back pointer to related device */ + /* Populated by auto-configure */ }; typedef struct pdp_dib DIB; diff --git a/PDP11/pdp11_io.c b/PDP11/pdp11_io.c index 7c171899..54659c08 100644 --- a/PDP11/pdp11_io.c +++ b/PDP11/pdp11_io.c @@ -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; diff --git a/PDP11/pdp11_io_lib.c b/PDP11/pdp11_io_lib.c index 83a9be7f..c6756e81 100644 --- a/PDP11/pdp11_io_lib.c +++ b/PDP11/pdp11_io_lib.c @@ -47,11 +47,10 @@ extern int32 int_vec_set[IPL_HLVL][32]; /* bits to set in vector extern int32 (*int_ack[IPL_HLVL][32])(void); extern t_stat (*iodispR[IOPAGESIZE >> 1])(int32 *dat, int32 ad, int32 md); extern t_stat (*iodispW[IOPAGESIZE >> 1])(int32 dat, int32 ad, int32 md); +extern DIB *iodibp[IOPAGESIZE >> 1]; extern t_stat build_dib_tab (void); -static DIB *iodibp[IOPAGESIZE >> 1]; - static void build_vector_tab (void); #if !defined(UNIMEMSIZE) @@ -307,6 +306,7 @@ const char *cdname; if ((dptr == NULL) || (dibp == NULL)) /* validate args */ return SCPE_IERR; +dibp->dptr = dptr; /* save back pointer */ if (dibp->vnum > VEC_DEVMAX) return SCPE_IERR; vec = dibp->vec; @@ -453,12 +453,7 @@ for (i = 0, dibp = NULL; i < (IOPAGESIZE >> 1); i++) { /* loop thru entries */ size_t l; if (iodibp[i] && (iodibp[i] != dibp)) { /* new block? */ dibp = iodibp[i]; /* DIB for block */ - for (j = 0, dptr = NULL; sim_devices[j] != NULL; j++) { - if (((DIB*) sim_devices[j]->ctxt) == dibp) { - dptr = sim_devices[j]; /* locate device */ - break; - } /* end if */ - } /* end for j */ + dptr = dibp->dptr; if ((dibp->ba+ dibp->lnt - 1) > maxaddr) maxaddr = dibp->ba+ dibp->lnt - 1; if (dibp->vec > maxvec) @@ -522,12 +517,7 @@ fputc ('\n', st); for (i = 0, dibp = NULL; i < (IOPAGESIZE >> 1); i++) { /* loop thru entries */ if (iodibp[i] && (iodibp[i] != dibp)) { /* new block? */ dibp = iodibp[i]; /* DIB for block */ - for (j = 0, dptr = NULL; sim_devices[j] != NULL; j++) { - if (((DIB*) sim_devices[j]->ctxt) == dibp) { - dptr = sim_devices[j]; /* locate device */ - break; - } /* end if */ - } /* end for j */ + dptr = dibp->dptr; /* locate device */ fprint_val (st, (t_value) dibp->ba, DEV_RDX, 32, PV_LEFT); fprintf (st, " - "); fprint_val (st, (t_value) dibp->ba + dibp->lnt - 1, DEV_RDX, 32, PV_LEFT); diff --git a/VAX/vax610_defs.h b/VAX/vax610_defs.h index 57bc805b..ba71188d 100644 --- a/VAX/vax610_defs.h +++ b/VAX/vax610_defs.h @@ -206,6 +206,8 @@ typedef struct { /* simulated through a single */ /* DEVICE structure (e.g., DZ, VH, DL, DC). */ /* Populated by auto-configure */ + DEVICE *dptr; /* back pointer to related device */ + /* Populated by auto-configure */ } DIB; /* Qbus I/O page layout - see pdp11_io_lib.c for address layout details */ diff --git a/VAX/vax610_io.c b/VAX/vax610_io.c index a45fc176..24b71a72 100644 --- a/VAX/vax610_io.c +++ b/VAX/vax610_io.c @@ -80,6 +80,7 @@ DEVICE qba_dev = { 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]; /* Interrupt request to interrupt action map */ diff --git a/VAX/vax630_defs.h b/VAX/vax630_defs.h index fd5f1a89..5f4ff40a 100644 --- a/VAX/vax630_defs.h +++ b/VAX/vax630_defs.h @@ -256,6 +256,8 @@ typedef struct { /* simulated through a single */ /* DEVICE structure (e.g., DZ, VH, DL, DC). */ /* Populated by auto-configure */ + DEVICE *dptr; /* back pointer to related device */ + /* Populated by auto-configure */ } DIB; /* Qbus I/O page layout - see pdp11_io_lib.c for address layout details */ diff --git a/VAX/vax630_io.c b/VAX/vax630_io.c index 1d2535e5..879b9b76 100644 --- a/VAX/vax630_io.c +++ b/VAX/vax630_io.c @@ -151,6 +151,7 @@ DEVICE qba_dev = { 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]; /* Interrupt request to interrupt action map */ diff --git a/VAX/vax730_defs.h b/VAX/vax730_defs.h index 1ed11411..f941ad46 100644 --- a/VAX/vax730_defs.h +++ b/VAX/vax730_defs.h @@ -249,6 +249,8 @@ typedef struct { /* simulated through a single */ /* DEVICE structure (e.g., DZ, VH, DL, DC). */ /* Populated by auto-configure */ + DEVICE *dptr; /* back pointer to related device */ + /* Populated by auto-configure */ } DIB; /* Unibus I/O page layout - see pdp11_io_lib.c for address layout details */ diff --git a/VAX/vax730_uba.c b/VAX/vax730_uba.c index b47f8e75..794e1d59 100644 --- a/VAX/vax730_uba.c +++ b/VAX/vax730_uba.c @@ -117,6 +117,7 @@ extern t_stat rb_wr32 (int32 data, int32 PA, int32 access); 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]; /* Unibus interrupt request to interrupt action map */ diff --git a/VAX/vax750_defs.h b/VAX/vax750_defs.h index 4e5007b8..e9bbac7e 100644 --- a/VAX/vax750_defs.h +++ b/VAX/vax750_defs.h @@ -289,6 +289,8 @@ typedef struct { /* simulated through a single */ /* DEVICE structure (e.g., DZ, VH, DL, DC). */ /* Populated by auto-configure */ + DEVICE *dptr; /* back pointer to related device */ + /* Populated by auto-configure */ } DIB; /* Unibus I/O page layout - see pdp11_io_lib.c for address layout details diff --git a/VAX/vax750_uba.c b/VAX/vax750_uba.c index 47b9334d..6f20a279 100644 --- a/VAX/vax750_uba.c +++ b/VAX/vax750_uba.c @@ -105,6 +105,7 @@ extern void cmi_set_tmo (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]; /* Unibus interrupt request to interrupt action map */ diff --git a/VAX/vax780_defs.h b/VAX/vax780_defs.h index 94ac0f79..6e4f986c 100644 --- a/VAX/vax780_defs.h +++ b/VAX/vax780_defs.h @@ -305,6 +305,8 @@ typedef struct { /* simulated through a single */ /* DEVICE structure (e.g., DZ, VH, DL, DC). */ /* Populated by auto-configure */ + DEVICE *dptr; /* back pointer to related device */ + /* Populated by auto-configure */ } DIB; /* Unibus I/O page layout - see pdp11_io_lib.c for address layout details diff --git a/VAX/vax780_uba.c b/VAX/vax780_uba.c index 83f61dbc..03544e7e 100644 --- a/VAX/vax780_uba.c +++ b/VAX/vax780_uba.c @@ -209,6 +209,7 @@ extern t_stat build_dib_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]; /* Unibus interrupt request to interrupt action map */ diff --git a/VAX/vax860_defs.h b/VAX/vax860_defs.h index be403fda..80eb9273 100644 --- a/VAX/vax860_defs.h +++ b/VAX/vax860_defs.h @@ -333,6 +333,8 @@ typedef struct { /* simulated through a single */ /* DEVICE structure (e.g., DZ, VH, DL, DC). */ /* Populated by auto-configure */ + DEVICE *dptr; /* back pointer to related device */ + /* Populated by auto-configure */ } DIB; /* Unibus I/O page layout - XUB,RQB,RQC,RQD float based on number of DZ's diff --git a/VAX/vax_io.c b/VAX/vax_io.c index 0b46f595..9c01b242 100644 --- a/VAX/vax_io.c +++ b/VAX/vax_io.c @@ -190,6 +190,7 @@ DEVICE qba_dev = { 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]; /* Interrupt request to interrupt action map */ diff --git a/VAX/vaxmod_defs.h b/VAX/vaxmod_defs.h index 284787c1..e75a0c3d 100644 --- a/VAX/vaxmod_defs.h +++ b/VAX/vaxmod_defs.h @@ -308,6 +308,8 @@ typedef struct { /* simulated through a single */ /* DEVICE structure (e.g., DZ, VH, DL, DC). */ /* Populated by auto-configure */ + DEVICE *dptr; /* back pointer to related device */ + /* Populated by auto-configure */ } DIB; /* Qbus I/O page layout - see pdp11_io_lib.c for address layout details */