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.
This commit is contained in:
parent
af6b51925c
commit
39d8034475
2 changed files with 42 additions and 69 deletions
|
@ -91,6 +91,29 @@ X86ISA::I8042::writeData(uint8_t newData, bool mouse)
|
|||
}
|
||||
}
|
||||
|
||||
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()
|
||||
{
|
||||
|
@ -108,7 +131,7 @@ X86ISA::PS2Device::bufferData(const uint8_t *data, int size)
|
|||
{
|
||||
assert(data || size == 0);
|
||||
while (size) {
|
||||
outBuffer.push(*(data++));
|
||||
outBuffer.push_back(*(data++));
|
||||
size--;
|
||||
}
|
||||
}
|
||||
|
@ -463,7 +486,7 @@ X86ISA::I8042::write(PacketPtr pkt)
|
|||
}
|
||||
|
||||
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 @@ X86ISA::I8042::unserialize(CheckpointIn &cp)
|
|||
}
|
||||
|
||||
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 @@ X86ISA::PS2Mouse::serialize(const std::string &base, CheckpointOut &cp)
|
|||
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 *
|
||||
|
|
|
@ -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 IntPin;
|
|||
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 @@ class PS2Device
|
|||
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 @@ class PS2Device
|
|||
uint8_t getData()
|
||||
{
|
||||
uint8_t data = outBuffer.front();
|
||||
outBuffer.pop();
|
||||
outBuffer.pop_front();
|
||||
return data;
|
||||
}
|
||||
|
||||
|
@ -117,8 +120,10 @@ class PS2Mouse : public PS2Device
|
|||
|
||||
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 @@ class PS2Keyboard : public PS2Device
|
|||
|
||||
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 @@ class I8042 : public BasicPioDevice
|
|||
|
||||
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;
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in a new issue