changeset 179bc8ca2d8c in /z/repo/gem5 details: http://repo.gem5.org/gem5?cmd=changeset;node=179bc8ca2d8c description: dev, x86: Fix serialization bug in the i8042 device
The i8042 device drops the contents of a PS2 device's buffer when serializing, which results in corrupted PS2 state when continuing simulation after a checkpoint. This changeset fixes this bug and transitions the i8042 model to use the new serialization API that requires the serialize() method to be const. diffstat: src/dev/x86/i8042.cc | 91 +++++++++++++++++---------------------------------- src/dev/x86/i8042.hh | 20 ++++++----- 2 files changed, 42 insertions(+), 69 deletions(-) diffs (205 lines): diff -r 703f42dbca21 -r 179bc8ca2d8c src/dev/x86/i8042.cc --- a/src/dev/x86/i8042.cc Fri Aug 07 09:59:14 2015 +0100 +++ b/src/dev/x86/i8042.cc Fri Aug 07 09:59:15 2015 +0100 @@ -92,6 +92,29 @@ } void +X86ISA::PS2Device::serialize(const std::string &base, CheckpointOut &cp) const +{ + paramOut(cp, base + ".lastCommand", lastCommand); + + std::vector<uint8_t> buffer(outBuffer.size()); + std::copy(outBuffer.begin(), outBuffer.end(), buffer.begin()); + arrayParamOut(cp, base + ".outBuffer.elts", buffer); +} + +void +X86ISA::PS2Device::unserialize(const std::string &base, CheckpointIn &cp) +{ + paramIn(cp, base + ".lastCommand", lastCommand); + + std::vector<uint8_t> buffer; + arrayParamIn(cp, base + ".outBuffer.elts", buffer); + assert(outBuffer.empty()); + for (auto c : buffer) + outBuffer.push_back(c); +} + + +void X86ISA::PS2Device::ack() { bufferData(&CommandAck, sizeof(CommandAck)); @@ -108,7 +131,7 @@ { assert(data || size == 0); while (size) { - outBuffer.push(*(data++)); + outBuffer.push_back(*(data++)); size--; } } @@ -463,7 +486,7 @@ } void -X86ISA::I8042::serializeOld(CheckpointOut &cp) +X86ISA::I8042::serialize(CheckpointOut &cp) const { uint8_t statusRegData = statusReg.__data; uint8_t commandByteData = commandByte.__data; @@ -498,52 +521,11 @@ } void -X86ISA::PS2Keyboard::serialize(const std::string &base, CheckpointOut &cp) +X86ISA::PS2Mouse::serialize(const std::string &base, CheckpointOut &cp) const { - paramOut(cp, base + ".lastCommand", lastCommand); - int bufferSize = outBuffer.size(); - paramOut(cp, 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(cp, base + ".outBuffer.elts", buffer, - bufferSize*sizeof(uint8_t)); - delete[] buffer; -} + PS2Device::serialize(base, cp); -void -X86ISA::PS2Keyboard::unserialize(const std::string &base, CheckpointIn &cp) -{ - paramIn(cp, base + ".lastCommand", lastCommand); - int bufferSize; - paramIn(cp, base + ".outBuffer.size", bufferSize); - uint8_t *buffer = new uint8_t[bufferSize]; - arrayParamIn(cp, 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, CheckpointOut &cp) -{ - uint8_t statusData = status.__data; - paramOut(cp, base + ".lastCommand", lastCommand); - int bufferSize = outBuffer.size(); - paramOut(cp, 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(cp, base + ".outBuffer.elts", buffer, - bufferSize*sizeof(uint8_t)); - delete[] buffer; - paramOut(cp, base + ".status", statusData); + paramOut(cp, base + ".status", status); paramOut(cp, base + ".resolution", resolution); paramOut(cp, base + ".sampleRate", sampleRate); } @@ -551,22 +533,11 @@ void X86ISA::PS2Mouse::unserialize(const std::string &base, CheckpointIn &cp) { - uint8_t statusData; - paramIn(cp, base + ".lastCommand", lastCommand); - int bufferSize; - paramIn(cp, base + ".outBuffer.size", bufferSize); - uint8_t *buffer = new uint8_t[bufferSize]; - arrayParamIn(cp, base + ".outBuffer.elts", buffer, - bufferSize*sizeof(uint8_t)); - for (int i = 0; i < bufferSize; ++i) { - outBuffer.push(buffer[i]); - } - delete[] buffer; - paramIn(cp, base + ".status", statusData); + PS2Device::unserialize(base, cp); + + paramIn(cp, base + ".status", status); paramIn(cp, base + ".resolution", resolution); paramIn(cp, base + ".sampleRate", sampleRate); - - status.__data = statusData; } X86ISA::I8042 * diff -r 703f42dbca21 -r 179bc8ca2d8c src/dev/x86/i8042.hh --- a/src/dev/x86/i8042.hh Fri Aug 07 09:59:14 2015 +0100 +++ b/src/dev/x86/i8042.hh Fri Aug 07 09:59:15 2015 +0100 @@ -31,7 +31,7 @@ #ifndef __DEV_X86_I8042_HH__ #define __DEV_X86_I8042_HH__ -#include <queue> +#include <deque> #include "dev/x86/intdev.hh" #include "dev/io_device.hh" @@ -45,7 +45,7 @@ class PS2Device { protected: - std::queue<uint8_t> outBuffer; + std::deque<uint8_t> outBuffer; static const uint16_t NoCommand = (uint16_t)(-1); @@ -61,6 +61,9 @@ PS2Device() : lastCommand(NoCommand) {} + virtual void serialize(const std::string &base, CheckpointOut &cp) const; + virtual void unserialize(const std::string &base, CheckpointIn &cp); + bool hasData() { return !outBuffer.empty(); @@ -69,7 +72,7 @@ uint8_t getData() { uint8_t data = outBuffer.front(); - outBuffer.pop(); + outBuffer.pop_front(); return data; } @@ -117,8 +120,10 @@ bool processData(uint8_t data); - void serialize(const std::string &base, CheckpointOut &cp); - void unserialize(const std::string &base, CheckpointIn &cp); + void serialize(const std::string &base, + CheckpointOut &cp) const M5_ATTR_OVERRIDE; + void unserialize(const std::string &base, + CheckpointIn &cp) M5_ATTR_OVERRIDE; }; class PS2Keyboard : public PS2Device @@ -149,9 +154,6 @@ public: bool processData(uint8_t data); - - void serialize(const std::string &base, CheckpointOut &cp); - void unserialize(const std::string &base, CheckpointIn &cp); }; class I8042 : public BasicPioDevice @@ -247,7 +249,7 @@ Tick write(PacketPtr pkt); - void serializeOld(CheckpointOut &cp) M5_ATTR_OVERRIDE; + void serialize(CheckpointOut &cp) const M5_ATTR_OVERRIDE; void unserialize(CheckpointIn &cp) M5_ATTR_OVERRIDE; }; _______________________________________________ gem5-dev mailing list gem5-dev@gem5.org http://m5sim.org/mailman/listinfo/gem5-dev