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:
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user