x86: Add checkpointing capability to devices
authorJoel Hestness <hestness@cs.utexas.edu>
Mon, 7 Feb 2011 06:14:18 +0000 (22:14 -0800)
committerJoel Hestness <hestness@cs.utexas.edu>
Mon, 7 Feb 2011 06:14:18 +0000 (22:14 -0800)
Add checkpointing capability to the Intel 8254 timer, CMOS, I8042,
PS2 Keyboard and Mouse, I82094AA, I8237, I8254, I8259, and speaker
devices

15 files changed:
src/dev/intel_8254_timer.cc
src/dev/x86/cmos.cc
src/dev/x86/cmos.hh
src/dev/x86/i8042.cc
src/dev/x86/i8042.hh
src/dev/x86/i82094aa.cc
src/dev/x86/i82094aa.hh
src/dev/x86/i8237.cc
src/dev/x86/i8237.hh
src/dev/x86/i8254.cc
src/dev/x86/i8254.hh
src/dev/x86/i8259.cc
src/dev/x86/i8259.hh
src/dev/x86/speaker.cc
src/dev/x86/speaker.hh

index aee716c010d05d41bd017c6759911fcd017368e9..cad59bbdb30db089d77c8c81b5e03586d4b4d226 100644 (file)
@@ -247,7 +247,9 @@ Intel8254Timer::Counter::unserialize(const string &base, Checkpoint *cp,
     paramIn(cp, section, base + ".read_byte", read_byte);
     paramIn(cp, section, base + ".write_byte", write_byte);
 
-    Tick event_tick;
+    Tick event_tick = 0;
+    if (event.scheduled())
+        parent->deschedule(event);
     paramIn(cp, section, base + ".event_tick", event_tick);
     if (event_tick)
         parent->schedule(event, event_tick);
index 122b531caf1c98095bee6ae35de8990b67a21bd5..aa92521dca2dc4335a582211513ad705e22df80c 100644 (file)
@@ -111,6 +111,26 @@ X86ISA::Cmos::writeRegister(uint8_t reg, uint8_t val)
     }
 }
 
+void
+X86ISA::Cmos::serialize(std::ostream &os)
+{
+    SERIALIZE_SCALAR(address);
+    SERIALIZE_ARRAY(regs, numRegs);
+
+    // Serialize the timer
+    rtc.serialize("rtc", os);
+}
+
+void
+X86ISA::Cmos::unserialize(Checkpoint *cp, const std::string &section)
+{
+    UNSERIALIZE_SCALAR(address);
+    UNSERIALIZE_ARRAY(regs, numRegs);
+
+    // Serialize the timer
+    rtc.unserialize("rtc", cp, section);
+}
+
 X86ISA::Cmos *
 CmosParams::create()
 {
index 22cd9e3afdcb68992396d92c20b0962d1b30c214..83d92e7219c87c05c046abddb7673f5114b9eebd 100644 (file)
@@ -82,6 +82,10 @@ class Cmos : public BasicPioDevice
     Tick read(PacketPtr pkt);
 
     Tick write(PacketPtr pkt);
+
+    virtual void serialize(std::ostream &os);
+    virtual void unserialize(Checkpoint *cp, const std::string &section);
+
 };
 
 } // namespace X86ISA
index afcbfdfb4b316f1f5be76475a6079460a4793eca..fb1412615b9306121c28592f74ccbda8790f9183 100644 (file)
@@ -439,6 +439,115 @@ X86ISA::I8042::write(PacketPtr pkt)
     return latency;
 }
 
+void
+X86ISA::I8042::serialize(std::ostream &os)
+{
+    uint8_t statusRegData = statusReg.__data;
+    uint8_t commandByteData = commandByte.__data;
+    
+    SERIALIZE_SCALAR(dataPort);
+    SERIALIZE_SCALAR(commandPort);
+    SERIALIZE_SCALAR(statusRegData);
+    SERIALIZE_SCALAR(commandByteData);
+    SERIALIZE_SCALAR(dataReg);
+    SERIALIZE_SCALAR(lastCommand);
+    mouse.serialize("mouse", os);
+    keyboard.serialize("keyboard", os);
+}
+
+void
+X86ISA::I8042::unserialize(Checkpoint *cp, const std::string &section)
+{
+    uint8_t statusRegData;
+    uint8_t commandByteData;
+
+    UNSERIALIZE_SCALAR(dataPort);
+    UNSERIALIZE_SCALAR(commandPort);
+    UNSERIALIZE_SCALAR(statusRegData);
+    UNSERIALIZE_SCALAR(commandByteData);
+    UNSERIALIZE_SCALAR(dataReg);
+    UNSERIALIZE_SCALAR(lastCommand);
+    mouse.unserialize("mouse", cp, section);
+    keyboard.unserialize("keyboard", cp, section);
+
+    statusReg.__data = statusRegData;
+    commandByte.__data = commandByteData;
+}
+
+void
+X86ISA::PS2Keyboard::serialize(const std::string &base, std::ostream &os)
+{
+    paramOut(os, base + ".lastCommand", lastCommand);
+    int bufferSize = outBuffer.size();
+    paramOut(os, base + ".outBuffer.size", bufferSize);
+    uint8_t *buffer = new uint8_t[bufferSize];
+    for (int i = 0; i < bufferSize; ++i) {
+        buffer[i] = outBuffer.front();
+        outBuffer.pop();
+    }
+    arrayParamOut(os, base + ".outBuffer.elts", buffer,
+            bufferSize*sizeof(uint8_t));
+    delete buffer;
+}
+
+void
+X86ISA::PS2Keyboard::unserialize(const std::string &base, Checkpoint *cp,
+        const std::string &section)
+{
+    paramIn(cp, section, base + ".lastCommand", lastCommand);
+    int bufferSize;
+    paramIn(cp, section, base + ".outBuffer.size", bufferSize);
+    uint8_t *buffer = new uint8_t[bufferSize];
+    arrayParamIn(cp, section, base + ".outBuffer.elts", buffer,
+            bufferSize*sizeof(uint8_t));
+    for (int i = 0; i < bufferSize; ++i) {
+        outBuffer.push(buffer[i]);
+    }
+    delete buffer;
+}
+
+void
+X86ISA::PS2Mouse::serialize(const std::string &base, std::ostream &os)
+{
+    uint8_t statusData = status.__data;
+    paramOut(os, base + ".lastCommand", lastCommand);
+    int bufferSize = outBuffer.size();
+    paramOut(os, base + ".outBuffer.size", bufferSize);
+    uint8_t *buffer = new uint8_t[bufferSize];
+    for (int i = 0; i < bufferSize; ++i) {
+        buffer[i] = outBuffer.front();
+        outBuffer.pop();
+    }
+    arrayParamOut(os, base + ".outBuffer.elts", buffer,
+            bufferSize*sizeof(uint8_t));
+    delete buffer;
+    paramOut(os, base + ".status", statusData);
+    paramOut(os, base + ".resolution", resolution);
+    paramOut(os, base + ".sampleRate", sampleRate);
+}
+
+void
+X86ISA::PS2Mouse::unserialize(const std::string &base, Checkpoint *cp,
+        const std::string &section)
+{
+    uint8_t statusData;
+    paramIn(cp, section, base + ".lastCommand", lastCommand);
+    int bufferSize;
+    paramIn(cp, section, base + ".outBuffer.size", bufferSize);
+    uint8_t *buffer = new uint8_t[bufferSize];
+    arrayParamIn(cp, section, base + ".outBuffer.elts", buffer,
+            bufferSize*sizeof(uint8_t));
+    for (int i = 0; i < bufferSize; ++i) {
+        outBuffer.push(buffer[i]);
+    }
+    delete buffer;
+    paramIn(cp, section, base + ".status", statusData);
+    paramIn(cp, section, base + ".resolution", resolution);
+    paramIn(cp, section, base + ".sampleRate", sampleRate);
+
+    status.__data = statusData;
+}
+
 X86ISA::I8042 *
 I8042Params::create()
 {
index 7aa59e9a78b0011677ec90c017d8b2c56e7652d0..b14d254ca8e571b5f4796c520a128004074a24e7 100644 (file)
@@ -116,6 +116,10 @@ class PS2Mouse : public PS2Device
     {}
 
     bool processData(uint8_t data);
+
+    void serialize(const std::string &base, std::ostream &os);
+    void unserialize(const std::string &base, Checkpoint *cp,
+            const std::string &section);
 };
 
 class PS2Keyboard : public PS2Device
@@ -146,6 +150,10 @@ class PS2Keyboard : public PS2Device
 
   public:
     bool processData(uint8_t data);
+
+    void serialize(const std::string &base, std::ostream &os);
+    void unserialize(const std::string &base, Checkpoint *cp,
+            const std::string &section);
 };
 
 class I8042 : public BasicPioDevice
@@ -252,6 +260,9 @@ class I8042 : public BasicPioDevice
     Tick read(PacketPtr pkt);
 
     Tick write(PacketPtr pkt);
+
+    virtual void serialize(std::ostream &os);
+    virtual void unserialize(Checkpoint *cp, const std::string &section);
 };
 
 } // namespace X86ISA
index 65b3ee732913d98b38f7b0c736cd51a5ae05193d..cb9b51d58f15dd88085b7ce3ca79fe4f356b34db 100644 (file)
@@ -236,6 +236,35 @@ X86ISA::I82094AA::registerLocalApic(int initialId, Interrupts *localApic)
     localApics[initialId] = localApic;
 }
 
+void
+X86ISA::I82094AA::serialize(std::ostream &os)
+{
+    uint64_t* redirTableArray = (uint64_t*)redirTable;
+    SERIALIZE_SCALAR(regSel);
+    SERIALIZE_SCALAR(initialApicId);
+    SERIALIZE_SCALAR(id);
+    SERIALIZE_SCALAR(arbId);
+    SERIALIZE_SCALAR(lowestPriorityOffset);
+    SERIALIZE_ARRAY(redirTableArray, TableSize);
+    SERIALIZE_ARRAY(pinStates, TableSize);
+}
+
+void
+X86ISA::I82094AA::unserialize(Checkpoint *cp, const std::string &section)
+{
+    uint64_t redirTableArray[TableSize];
+    UNSERIALIZE_SCALAR(regSel);
+    UNSERIALIZE_SCALAR(initialApicId);
+    UNSERIALIZE_SCALAR(id);
+    UNSERIALIZE_SCALAR(arbId);
+    UNSERIALIZE_SCALAR(lowestPriorityOffset);
+    UNSERIALIZE_ARRAY(redirTableArray, TableSize);
+    UNSERIALIZE_ARRAY(pinStates, TableSize);
+    for (int i = 0; i < TableSize; i++) {
+        redirTable[i] = (RedirTableEntry)redirTableArray[i];
+    }
+}
+
 X86ISA::I82094AA *
 I82094AAParams::create()
 {
index 70717f6ba0f3fe020213700b6a23ca4443fc95f6..442163bbf3c2af26a71db0ababdc33ee163d95ef 100644 (file)
@@ -130,6 +130,9 @@ class I82094AA : public PioDevice, public IntDev
     void raiseInterruptPin(int number);
     void lowerInterruptPin(int number);
     void registerLocalApic(int id, Interrupts *localApic);
+
+    virtual void serialize(std::ostream &os);
+    virtual void unserialize(Checkpoint *cp, const std::string &section);
 };
 
 } // namespace X86ISA
index f6ea9d75f677a3b6db2a55ac4f1eeb043ca56186..a43c1ec91ab856ecd053ab4b1a3d5e0aa2ac021a 100644 (file)
@@ -119,12 +119,24 @@ X86ISA::I8237::write(PacketPtr pkt)
       case 0xf:
         panic("Write to i8237 write all mask register bits unimplemented.\n");
       default:
-        panic("Write to undefined i8254 register.\n");
+        panic("Write to undefined i8237 register.\n");
     }
     pkt->makeAtomicResponse();
     return latency;
 }
 
+void
+X86ISA::I8237::serialize(std::ostream &os)
+{
+    SERIALIZE_SCALAR(maskReg);
+}
+
+void
+X86ISA::I8237::unserialize(Checkpoint *cp, const std::string &section)
+{
+    UNSERIALIZE_SCALAR(maskReg);
+}
+
 X86ISA::I8237 *
 I8237Params::create()
 {
index 1db91236a80b20d5c82afb03de42530b2c120038..28d9e85a3eaab37cbb314e9fa46cdf2b5f49761f 100644 (file)
@@ -59,6 +59,9 @@ class I8237 : public BasicPioDevice
     Tick read(PacketPtr pkt);
 
     Tick write(PacketPtr pkt);
+
+    virtual void serialize(std::ostream &os);
+    virtual void unserialize(Checkpoint *cp, const std::string &section);
 };
 
 } // namespace X86ISA
index 5eb28844a7a7ac53ff45851f709ce02e379c45dd..dd1ff7c5e309b7e3b0b2e70921f72fad44d926b4 100644 (file)
@@ -76,6 +76,18 @@ X86ISA::I8254::write(PacketPtr pkt)
     return latency;
 }
 
+void
+X86ISA::I8254::serialize(std::ostream &os)
+{
+    pit.serialize("pit", os);
+}
+
+void
+X86ISA::I8254::unserialize(Checkpoint *cp, const std::string &section)
+{
+    pit.unserialize("pit", cp, section);
+}
+
 X86ISA::I8254 *
 I8254Params::create()
 {
index e295f5105cd0f33a646ebafe3812ed73de7945c7..e6d500f42c0d78d863e779604897dd2e5aa5b5bd 100644 (file)
@@ -109,6 +109,10 @@ class I8254 : public BasicPioDevice
     {
         pit.writeControl(val);
     }
+
+    virtual void serialize(std::ostream &os);
+    virtual void unserialize(Checkpoint *cp, const std::string &section);
+
 };
 
 } // namespace X86ISA
index b868295ebc7a792c409473f7d1c8c31ff64f3a41..651196b4725647bde963e576f970707a1085d574 100644 (file)
@@ -303,6 +303,42 @@ X86ISA::I8259::getVector()
     return line | vectorOffset;
 }
 
+void
+X86ISA::I8259::serialize(std::ostream &os)
+{
+    SERIALIZE_ARRAY(pinStates, NumLines);
+    SERIALIZE_ENUM(mode);
+    SERIALIZE_SCALAR(IRR);
+    SERIALIZE_SCALAR(ISR);
+    SERIALIZE_SCALAR(IMR);
+    SERIALIZE_SCALAR(vectorOffset);
+    SERIALIZE_SCALAR(cascadeMode);
+    SERIALIZE_SCALAR(cascadeBits);
+    SERIALIZE_SCALAR(edgeTriggered);
+    SERIALIZE_SCALAR(readIRR);
+    SERIALIZE_SCALAR(expectICW4);
+    SERIALIZE_SCALAR(initControlWord);
+    SERIALIZE_SCALAR(autoEOI);
+}
+
+void
+X86ISA::I8259::unserialize(Checkpoint *cp, const std::string &section)
+{
+    UNSERIALIZE_ARRAY(pinStates, NumLines);
+    UNSERIALIZE_ENUM(mode);
+    UNSERIALIZE_SCALAR(IRR);
+    UNSERIALIZE_SCALAR(ISR);
+    UNSERIALIZE_SCALAR(IMR);
+    UNSERIALIZE_SCALAR(vectorOffset);
+    UNSERIALIZE_SCALAR(cascadeMode);
+    UNSERIALIZE_SCALAR(cascadeBits);
+    UNSERIALIZE_SCALAR(edgeTriggered);
+    UNSERIALIZE_SCALAR(readIRR);
+    UNSERIALIZE_SCALAR(expectICW4);
+    UNSERIALIZE_SCALAR(initControlWord);
+    UNSERIALIZE_SCALAR(autoEOI);
+}
+
 X86ISA::I8259 *
 I8259Params::create()
 {
index a9362d403d29c1e4d8a0368c7a45f5e26134df2e..2a5d5f6aa2b481d0de90fdfd9cd6f05905e5050c 100644 (file)
@@ -108,6 +108,9 @@ class I8259 : public BasicPioDevice, public IntDev
     void raiseInterruptPin(int number);
     void lowerInterruptPin(int number);
     int getVector();
+
+    virtual void serialize(std::ostream &os);
+    virtual void unserialize(Checkpoint *cp, const std::string &section);
 };
 
 } // namespace X86ISA
index c6eb9db9ec64cb30af9116dad0248554b130684f..b0f4dcd8bbe13b4d395494214aec71b31fda30a0 100644 (file)
@@ -72,6 +72,21 @@ X86ISA::Speaker::write(PacketPtr pkt)
     return latency;
 }
 
+void
+X86ISA::Speaker::serialize(std::ostream &os)
+{
+    uint8_t controlValData = controlVal.__data;
+    SERIALIZE_SCALAR(controlValData);
+}
+
+void
+X86ISA::Speaker::unserialize(Checkpoint *cp, const std::string &section)
+{
+    uint8_t controlValData;
+    UNSERIALIZE_SCALAR(controlValData);
+    controlVal.__data = controlValData;
+}
+
 X86ISA::Speaker *
 PcSpeakerParams::create()
 {
index fb7476ca0a3181e4b43e2236af8bdddd0cb78944..5aa1ccf0a0bc48cffdd6ce7a366934561d7d3352 100644 (file)
@@ -72,6 +72,10 @@ class Speaker : public BasicPioDevice
     Tick read(PacketPtr pkt);
 
     Tick write(PacketPtr pkt);
+
+    virtual void serialize(std::ostream &os);
+    virtual void unserialize(Checkpoint *cp, const std::string &section);
+
 };
 
 } // namespace X86ISA