arch-x86: Filter out the NMI masking bit from the CMOS offset.

A (another) weird/terrible quirk of the architecture of the PC is that
the the highest order bit of the value which selects a register to read
from the CMOS NVRAM/RTC is stolen and repurposed to enable/disable NMIs
since the 286, if the internet is to be believed.

Fortunately We don't currently attempt to generate an NMI anywhere, and so
this bit won't do anything in gem5 currently.

Unfortunately if we treat this value as the real offset without masking
off this bit, if software attempts to disable NMIs with it, it will
trigger an out of bounds assert in the CMOS device.

This change makes the CMOS device slightly smarter and has it maintain
but ignore the NMI disabling bit.

Change-Id: I8d7d0f1b0aadcca2060bf6a27931035859d66ca7
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/55244
Reviewed-by: Gabe Black <gabe.black@gmail.com>
Maintainer: Gabe Black <gabe.black@gmail.com>
Tested-by: kokoro <noreply+kokoro@google.com>
This commit is contained in:
Gabe Black
2022-01-08 23:46:54 -08:00
parent 10b8bc95d3
commit c419207b82
2 changed files with 10 additions and 3 deletions

View File

@@ -56,7 +56,7 @@ X86ISA::Cmos::read(PacketPtr pkt)
pkt->setLE(address);
break;
case 0x1:
pkt->setLE(readRegister(address));
pkt->setLE(readRegister(address.regNum));
break;
default:
panic("Read from undefined CMOS port.\n");
@@ -75,7 +75,8 @@ X86ISA::Cmos::write(PacketPtr pkt)
address = pkt->getLE<uint8_t>();
break;
case 0x1:
writeRegister(address, pkt->getLE<uint8_t>());
// Ignore the NMI mask bit since we never try to generate one anyway.
writeRegister(address.regNum, pkt->getLE<uint8_t>());
break;
default:
panic("Write to undefined CMOS port.\n");

View File

@@ -29,6 +29,7 @@
#ifndef __DEV_X86_CMOS_HH__
#define __DEV_X86_CMOS_HH__
#include "base/bitunion.hh"
#include "dev/intpin.hh"
#include "dev/io_device.hh"
#include "dev/mc146818.hh"
@@ -45,7 +46,12 @@ class Cmos : public BasicPioDevice
protected:
Tick latency;
uint8_t address;
BitUnion8(CmosAddress)
Bitfield<6, 0> regNum;
Bitfield<7> nmiMask;
EndBitUnion(CmosAddress)
CmosAddress address;
static const int numRegs = 128;