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:
parent
5f0370749e
commit
7677dad67d
16 changed files with 56 additions and 22 deletions
|
@ -528,6 +528,8 @@ struct pdp_dib {
|
||||||
/* DEVICE structure (e.g., DZ, VH, DL, DC). */
|
/* DEVICE structure (e.g., DZ, VH, DL, DC). */
|
||||||
/* Populated by auto-configure */
|
/* Populated by auto-configure */
|
||||||
struct pdp_dib *next; /* devices with more than one DIB can chain them */
|
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;
|
typedef struct pdp_dib DIB;
|
||||||
|
|
|
@ -66,6 +66,7 @@ extern void fixup_mbus_tab (void);
|
||||||
|
|
||||||
t_stat (*iodispR[IOPAGESIZE >> 1])(int32 *dat, int32 ad, int32 md);
|
t_stat (*iodispR[IOPAGESIZE >> 1])(int32 *dat, int32 ad, int32 md);
|
||||||
t_stat (*iodispW[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_vec[IPL_HLVL][32]; /* int req to vector */
|
||||||
int32 (*int_ack[IPL_HLVL][32])(void); /* int ack routines */
|
int32 (*int_ack[IPL_HLVL][32])(void); /* int ack routines */
|
||||||
|
@ -119,6 +120,23 @@ if (iodispW[idx]) {
|
||||||
return SCPE_NXM;
|
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
|
/* Calculate interrupt outstanding
|
||||||
In a Qbus system, all device interrupts are treated as BR4 */
|
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;
|
uint32 alim, lim, ma;
|
||||||
|
|
||||||
if (ba >= IOPAGEBASE) {
|
if (ba >= (IOPAGEBASE & BUSMASK)) {
|
||||||
int32 value;
|
int32 value;
|
||||||
|
|
||||||
while (bc) {
|
while (bc) {
|
||||||
if (iopageR( &value, (ba & ~1), READ) != SCPE_OK)
|
if (iopageCPUReg (ba) ||
|
||||||
|
(iopageR( &value, (ba & ~1), READ) != SCPE_OK))
|
||||||
break;
|
break;
|
||||||
*buf++ = (uint8) (((ba & 1)? (value >> 8): value) & 0xff);
|
*buf++ = (uint8) (((ba & 1)? (value >> 8): value) & 0xff);
|
||||||
ba++;
|
ba++;
|
||||||
|
@ -277,12 +296,13 @@ int32 Map_ReadW (uint32 ba, int32 bc, uint16 *buf)
|
||||||
{
|
{
|
||||||
uint32 alim, lim, ma;
|
uint32 alim, lim, ma;
|
||||||
|
|
||||||
if (ba >= IOPAGEBASE) {
|
if (ba >= (IOPAGEBASE & BUSMASK)) {
|
||||||
int32 value;
|
int32 value;
|
||||||
if ((ba & 1) || (bc & 1))
|
if ((ba & 1) || (bc & 1))
|
||||||
return bc;
|
return bc;
|
||||||
while (bc) {
|
while (bc) {
|
||||||
if (iopageR( &value, ba, READ) != SCPE_OK)
|
if (iopageCPUReg (ba) ||
|
||||||
|
(iopageR( &value, ba, READ) != SCPE_OK))
|
||||||
break;
|
break;
|
||||||
*buf++ = (uint16) (value & 0xffff);
|
*buf++ = (uint16) (value & 0xffff);
|
||||||
ba += 2;
|
ba += 2;
|
||||||
|
@ -318,9 +338,10 @@ int32 Map_WriteB (uint32 ba, int32 bc, const uint8 *buf)
|
||||||
{
|
{
|
||||||
uint32 alim, lim, ma;
|
uint32 alim, lim, ma;
|
||||||
|
|
||||||
if (ba >= IOPAGEBASE) {
|
if (ba >= (IOPAGEBASE & BUSMASK)) {
|
||||||
while (bc) {
|
while (bc) {
|
||||||
if (iopageW( ((int32) *buf++) & 0xff, ba, WRITEB) != SCPE_OK)
|
if (iopageCPUReg (ba) ||
|
||||||
|
(iopageW( ((int32) *buf++) & 0xff, ba, WRITEB) != SCPE_OK))
|
||||||
break;
|
break;
|
||||||
ba++;
|
ba++;
|
||||||
bc--;
|
bc--;
|
||||||
|
@ -355,11 +376,12 @@ int32 Map_WriteW (uint32 ba, int32 bc, const uint16 *buf)
|
||||||
{
|
{
|
||||||
uint32 alim, lim, ma;
|
uint32 alim, lim, ma;
|
||||||
|
|
||||||
if (ba >= IOPAGEBASE) {
|
if (ba >= (IOPAGEBASE & BUSMASK)) {
|
||||||
if ((ba & 1) || (bc & 1))
|
if ((ba & 1) || (bc & 1))
|
||||||
return bc;
|
return bc;
|
||||||
while (bc) {
|
while (bc) {
|
||||||
if (iopageW( ((int32) *buf++) & 0xffff, ba, WRITE) != SCPE_OK)
|
if (iopageCPUReg (ba) ||
|
||||||
|
(iopageW( ((int32) *buf++) & 0xffff, ba, WRITE) != SCPE_OK))
|
||||||
break;
|
break;
|
||||||
ba += 2;
|
ba += 2;
|
||||||
bc -= 2;
|
bc -= 2;
|
||||||
|
|
|
@ -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 int32 (*int_ack[IPL_HLVL][32])(void);
|
||||||
extern t_stat (*iodispR[IOPAGESIZE >> 1])(int32 *dat, int32 ad, int32 md);
|
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 t_stat (*iodispW[IOPAGESIZE >> 1])(int32 dat, int32 ad, int32 md);
|
||||||
|
extern DIB *iodibp[IOPAGESIZE >> 1];
|
||||||
|
|
||||||
extern t_stat build_dib_tab (void);
|
extern t_stat build_dib_tab (void);
|
||||||
|
|
||||||
static DIB *iodibp[IOPAGESIZE >> 1];
|
|
||||||
|
|
||||||
static void build_vector_tab (void);
|
static void build_vector_tab (void);
|
||||||
|
|
||||||
#if !defined(UNIMEMSIZE)
|
#if !defined(UNIMEMSIZE)
|
||||||
|
@ -307,6 +306,7 @@ const char *cdname;
|
||||||
|
|
||||||
if ((dptr == NULL) || (dibp == NULL)) /* validate args */
|
if ((dptr == NULL) || (dibp == NULL)) /* validate args */
|
||||||
return SCPE_IERR;
|
return SCPE_IERR;
|
||||||
|
dibp->dptr = dptr; /* save back pointer */
|
||||||
if (dibp->vnum > VEC_DEVMAX)
|
if (dibp->vnum > VEC_DEVMAX)
|
||||||
return SCPE_IERR;
|
return SCPE_IERR;
|
||||||
vec = dibp->vec;
|
vec = dibp->vec;
|
||||||
|
@ -453,12 +453,7 @@ for (i = 0, dibp = NULL; i < (IOPAGESIZE >> 1); i++) { /* loop thru entries */
|
||||||
size_t l;
|
size_t l;
|
||||||
if (iodibp[i] && (iodibp[i] != dibp)) { /* new block? */
|
if (iodibp[i] && (iodibp[i] != dibp)) { /* new block? */
|
||||||
dibp = iodibp[i]; /* DIB for block */
|
dibp = iodibp[i]; /* DIB for block */
|
||||||
for (j = 0, dptr = NULL; sim_devices[j] != NULL; j++) {
|
dptr = dibp->dptr;
|
||||||
if (((DIB*) sim_devices[j]->ctxt) == dibp) {
|
|
||||||
dptr = sim_devices[j]; /* locate device */
|
|
||||||
break;
|
|
||||||
} /* end if */
|
|
||||||
} /* end for j */
|
|
||||||
if ((dibp->ba+ dibp->lnt - 1) > maxaddr)
|
if ((dibp->ba+ dibp->lnt - 1) > maxaddr)
|
||||||
maxaddr = dibp->ba+ dibp->lnt - 1;
|
maxaddr = dibp->ba+ dibp->lnt - 1;
|
||||||
if (dibp->vec > maxvec)
|
if (dibp->vec > maxvec)
|
||||||
|
@ -522,12 +517,7 @@ fputc ('\n', st);
|
||||||
for (i = 0, dibp = NULL; i < (IOPAGESIZE >> 1); i++) { /* loop thru entries */
|
for (i = 0, dibp = NULL; i < (IOPAGESIZE >> 1); i++) { /* loop thru entries */
|
||||||
if (iodibp[i] && (iodibp[i] != dibp)) { /* new block? */
|
if (iodibp[i] && (iodibp[i] != dibp)) { /* new block? */
|
||||||
dibp = iodibp[i]; /* DIB for block */
|
dibp = iodibp[i]; /* DIB for block */
|
||||||
for (j = 0, dptr = NULL; sim_devices[j] != NULL; j++) {
|
dptr = dibp->dptr; /* locate device */
|
||||||
if (((DIB*) sim_devices[j]->ctxt) == dibp) {
|
|
||||||
dptr = sim_devices[j]; /* locate device */
|
|
||||||
break;
|
|
||||||
} /* end if */
|
|
||||||
} /* end for j */
|
|
||||||
fprint_val (st, (t_value) dibp->ba, DEV_RDX, 32, PV_LEFT);
|
fprint_val (st, (t_value) dibp->ba, DEV_RDX, 32, PV_LEFT);
|
||||||
fprintf (st, " - ");
|
fprintf (st, " - ");
|
||||||
fprint_val (st, (t_value) dibp->ba + dibp->lnt - 1, DEV_RDX, 32, PV_LEFT);
|
fprint_val (st, (t_value) dibp->ba + dibp->lnt - 1, DEV_RDX, 32, PV_LEFT);
|
||||||
|
|
|
@ -206,6 +206,8 @@ typedef struct {
|
||||||
/* simulated through a single */
|
/* simulated through a single */
|
||||||
/* DEVICE structure (e.g., DZ, VH, DL, DC). */
|
/* DEVICE structure (e.g., DZ, VH, DL, DC). */
|
||||||
/* Populated by auto-configure */
|
/* Populated by auto-configure */
|
||||||
|
DEVICE *dptr; /* back pointer to related device */
|
||||||
|
/* Populated by auto-configure */
|
||||||
} DIB;
|
} DIB;
|
||||||
|
|
||||||
/* Qbus I/O page layout - see pdp11_io_lib.c for address layout details */
|
/* Qbus I/O page layout - see pdp11_io_lib.c for address layout details */
|
||||||
|
|
|
@ -80,6 +80,7 @@ DEVICE qba_dev = {
|
||||||
|
|
||||||
t_stat (*iodispR[IOPAGESIZE >> 1])(int32 *dat, int32 ad, int32 md);
|
t_stat (*iodispR[IOPAGESIZE >> 1])(int32 *dat, int32 ad, int32 md);
|
||||||
t_stat (*iodispW[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 */
|
/* Interrupt request to interrupt action map */
|
||||||
|
|
||||||
|
|
|
@ -256,6 +256,8 @@ typedef struct {
|
||||||
/* simulated through a single */
|
/* simulated through a single */
|
||||||
/* DEVICE structure (e.g., DZ, VH, DL, DC). */
|
/* DEVICE structure (e.g., DZ, VH, DL, DC). */
|
||||||
/* Populated by auto-configure */
|
/* Populated by auto-configure */
|
||||||
|
DEVICE *dptr; /* back pointer to related device */
|
||||||
|
/* Populated by auto-configure */
|
||||||
} DIB;
|
} DIB;
|
||||||
|
|
||||||
/* Qbus I/O page layout - see pdp11_io_lib.c for address layout details */
|
/* Qbus I/O page layout - see pdp11_io_lib.c for address layout details */
|
||||||
|
|
|
@ -151,6 +151,7 @@ DEVICE qba_dev = {
|
||||||
|
|
||||||
t_stat (*iodispR[IOPAGESIZE >> 1])(int32 *dat, int32 ad, int32 md);
|
t_stat (*iodispR[IOPAGESIZE >> 1])(int32 *dat, int32 ad, int32 md);
|
||||||
t_stat (*iodispW[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 */
|
/* Interrupt request to interrupt action map */
|
||||||
|
|
||||||
|
|
|
@ -249,6 +249,8 @@ typedef struct {
|
||||||
/* simulated through a single */
|
/* simulated through a single */
|
||||||
/* DEVICE structure (e.g., DZ, VH, DL, DC). */
|
/* DEVICE structure (e.g., DZ, VH, DL, DC). */
|
||||||
/* Populated by auto-configure */
|
/* Populated by auto-configure */
|
||||||
|
DEVICE *dptr; /* back pointer to related device */
|
||||||
|
/* Populated by auto-configure */
|
||||||
} DIB;
|
} DIB;
|
||||||
|
|
||||||
/* Unibus I/O page layout - see pdp11_io_lib.c for address layout details */
|
/* Unibus I/O page layout - see pdp11_io_lib.c for address layout details */
|
||||||
|
|
|
@ -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 (*iodispR[IOPAGESIZE >> 1])(int32 *dat, int32 ad, int32 md);
|
||||||
t_stat (*iodispW[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 */
|
/* Unibus interrupt request to interrupt action map */
|
||||||
|
|
||||||
|
|
|
@ -289,6 +289,8 @@ typedef struct {
|
||||||
/* simulated through a single */
|
/* simulated through a single */
|
||||||
/* DEVICE structure (e.g., DZ, VH, DL, DC). */
|
/* DEVICE structure (e.g., DZ, VH, DL, DC). */
|
||||||
/* Populated by auto-configure */
|
/* Populated by auto-configure */
|
||||||
|
DEVICE *dptr; /* back pointer to related device */
|
||||||
|
/* Populated by auto-configure */
|
||||||
} DIB;
|
} DIB;
|
||||||
|
|
||||||
/* Unibus I/O page layout - see pdp11_io_lib.c for address layout details
|
/* Unibus I/O page layout - see pdp11_io_lib.c for address layout details
|
||||||
|
|
|
@ -105,6 +105,7 @@ extern void cmi_set_tmo (void);
|
||||||
|
|
||||||
t_stat (*iodispR[IOPAGESIZE >> 1])(int32 *dat, int32 ad, int32 md);
|
t_stat (*iodispR[IOPAGESIZE >> 1])(int32 *dat, int32 ad, int32 md);
|
||||||
t_stat (*iodispW[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 */
|
/* Unibus interrupt request to interrupt action map */
|
||||||
|
|
||||||
|
|
|
@ -305,6 +305,8 @@ typedef struct {
|
||||||
/* simulated through a single */
|
/* simulated through a single */
|
||||||
/* DEVICE structure (e.g., DZ, VH, DL, DC). */
|
/* DEVICE structure (e.g., DZ, VH, DL, DC). */
|
||||||
/* Populated by auto-configure */
|
/* Populated by auto-configure */
|
||||||
|
DEVICE *dptr; /* back pointer to related device */
|
||||||
|
/* Populated by auto-configure */
|
||||||
} DIB;
|
} DIB;
|
||||||
|
|
||||||
/* Unibus I/O page layout - see pdp11_io_lib.c for address layout details
|
/* Unibus I/O page layout - see pdp11_io_lib.c for address layout details
|
||||||
|
|
|
@ -209,6 +209,7 @@ extern t_stat build_dib_tab (void);
|
||||||
|
|
||||||
t_stat (*iodispR[IOPAGESIZE >> 1])(int32 *dat, int32 ad, int32 md);
|
t_stat (*iodispR[IOPAGESIZE >> 1])(int32 *dat, int32 ad, int32 md);
|
||||||
t_stat (*iodispW[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 */
|
/* Unibus interrupt request to interrupt action map */
|
||||||
|
|
||||||
|
|
|
@ -333,6 +333,8 @@ typedef struct {
|
||||||
/* simulated through a single */
|
/* simulated through a single */
|
||||||
/* DEVICE structure (e.g., DZ, VH, DL, DC). */
|
/* DEVICE structure (e.g., DZ, VH, DL, DC). */
|
||||||
/* Populated by auto-configure */
|
/* Populated by auto-configure */
|
||||||
|
DEVICE *dptr; /* back pointer to related device */
|
||||||
|
/* Populated by auto-configure */
|
||||||
} DIB;
|
} DIB;
|
||||||
|
|
||||||
/* Unibus I/O page layout - XUB,RQB,RQC,RQD float based on number of DZ's
|
/* Unibus I/O page layout - XUB,RQB,RQC,RQD float based on number of DZ's
|
||||||
|
|
|
@ -190,6 +190,7 @@ DEVICE qba_dev = {
|
||||||
|
|
||||||
t_stat (*iodispR[IOPAGESIZE >> 1])(int32 *dat, int32 ad, int32 md);
|
t_stat (*iodispR[IOPAGESIZE >> 1])(int32 *dat, int32 ad, int32 md);
|
||||||
t_stat (*iodispW[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 */
|
/* Interrupt request to interrupt action map */
|
||||||
|
|
||||||
|
|
|
@ -308,6 +308,8 @@ typedef struct {
|
||||||
/* simulated through a single */
|
/* simulated through a single */
|
||||||
/* DEVICE structure (e.g., DZ, VH, DL, DC). */
|
/* DEVICE structure (e.g., DZ, VH, DL, DC). */
|
||||||
/* Populated by auto-configure */
|
/* Populated by auto-configure */
|
||||||
|
DEVICE *dptr; /* back pointer to related device */
|
||||||
|
/* Populated by auto-configure */
|
||||||
} DIB;
|
} DIB;
|
||||||
|
|
||||||
/* Qbus I/O page layout - see pdp11_io_lib.c for address layout details */
|
/* Qbus I/O page layout - see pdp11_io_lib.c for address layout details */
|
||||||
|
|
Loading…
Add table
Reference in a new issue