diff --git a/simulators/gem5/configs/example/fail_fs.py b/simulators/gem5/configs/example/fail_fs.py index 443c4ef5..9be5c34c 100644 --- a/simulators/gem5/configs/example/fail_fs.py +++ b/simulators/gem5/configs/example/fail_fs.py @@ -154,6 +154,8 @@ else: ranges = [test_sys.physmem.range]) test_sys.iobridge.slave = test_sys.iobus.master test_sys.iobridge.master = test_sys.membus.slave + test_sys.failfake = FailFakeDevice(pio_addr=0xF00); #DanceOS + test_sys.iobus.default = test_sys.failfake.pio #DanceOS # Sanity check if options.fastmem and (options.caches or options.l2cache): diff --git a/simulators/gem5/configs/example/fs.py b/simulators/gem5/configs/example/fs.py index a6d4869f..058bd677 100644 --- a/simulators/gem5/configs/example/fs.py +++ b/simulators/gem5/configs/example/fs.py @@ -130,6 +130,8 @@ else: ranges = [test_sys.physmem.range]) test_sys.iobridge.slave = test_sys.iobus.master test_sys.iobridge.master = test_sys.membus.slave + test_sys.failfake = FailFakeDevice(pio_addr=0xF00); #DanceOS + test_sys.iobus.default = test_sys.failfake.pio #DanceOS # Sanity check if options.fastmem and (options.caches or options.l2cache): diff --git a/simulators/gem5/src/cpu/simple/atomic.cc b/simulators/gem5/src/cpu/simple/atomic.cc index 4e70d77c..b5277b83 100644 --- a/simulators/gem5/src/cpu/simple/atomic.cc +++ b/simulators/gem5/src/cpu/simple/atomic.cc @@ -49,6 +49,7 @@ #include "cpu/exetrace.hh" #include "debug/ExecFaulting.hh" #include "debug/SimpleCPU.hh" +#include "debug/Fail.hh" //DanceOS #include "mem/packet.hh" #include "mem/packet_access.hh" #include "mem/physical.hh" @@ -289,7 +290,11 @@ AtomicSimpleCPU::readMem(Addr addr, uint8_t * data, } dcache_access = true; - assert(!pkt.isError()); + //DanceOS + //assert(!pkt.isError()); + if(pkt.isError()) { + DPRINTF(Fail, "[FAIL] cpu/simple/atomic.cc readMem(): assert(!pkt.isError()) bypassed\n"); + } // DanceOS #ifdef CONFIG_EVENT_MEMREAD @@ -397,7 +402,11 @@ AtomicSimpleCPU::writeMem(uint8_t *data, unsigned size, } dcache_access = true; - assert(!pkt.isError()); + //DanceOS + //assert(!pkt.isError()); + if(pkt.isError()) { + DPRINTF(Fail, "[FAIL] cpu/simple/atomic.cc writeMem(): assert(!pkt.isError()) bypassed\n"); + } // DanceOS #ifdef CONFIG_EVENT_MEMWRITE diff --git a/simulators/gem5/src/dev/Device.py b/simulators/gem5/src/dev/Device.py index 96c95ebc..26938364 100644 --- a/simulators/gem5/src/dev/Device.py +++ b/simulators/gem5/src/dev/Device.py @@ -65,6 +65,19 @@ class IsaFake(BasicPioDevice): warn_access = Param.String("", "String to print when device is accessed") fake_mem = Param.Bool(False, "Is this device acting like a memory and thus may get a cache line sized req") +#DanceOS +class FailFakeDevice(BasicPioDevice): + type = 'FailFakeDevice' + pio_size = Param.Addr(0x8, "Size of address range") + ret_data8 = Param.UInt8(0xFF, "Default data to return") + ret_data16 = Param.UInt16(0xFFFF, "Default data to return") + ret_data32 = Param.UInt32(0xFFFFFFFF, "Default data to return") + ret_data64 = Param.UInt64(0xFFFFFFFFFFFFFFFF, "Default data to return") + ret_bad_addr = Param.Bool(False, "Return pkt status bad address on access") + update_data = Param.Bool(False, "Update the data that is returned on writes") + warn_access = Param.String("", "String to print when device is accessed") + fake_mem = Param.Bool(False, + "Is this device acting like a memory and thus may get a cache line sized req") class BadAddr(IsaFake): pio_addr = 0 diff --git a/simulators/gem5/src/dev/SConscript b/simulators/gem5/src/dev/SConscript index cba821f8..d1c447c7 100644 --- a/simulators/gem5/src/dev/SConscript +++ b/simulators/gem5/src/dev/SConscript @@ -63,6 +63,7 @@ Source('ide_disk.cc') Source('intel_8254_timer.cc') Source('io_device.cc') Source('isa_fake.cc') +Source('fail_fake_device.cc') #DanceOS Source('mc146818.cc') Source('ns_gige.cc') Source('pciconfigall.cc') diff --git a/simulators/gem5/src/dev/arm/pl011.cc b/simulators/gem5/src/dev/arm/pl011.cc index 97e178ea..7ab721bd 100644 --- a/simulators/gem5/src/dev/arm/pl011.cc +++ b/simulators/gem5/src/dev/arm/pl011.cc @@ -43,6 +43,7 @@ #include "base/trace.hh" #include "debug/Checkpoint.hh" #include "debug/Uart.hh" +#include "debug/Fail.hh" //DanceOS #include "dev/arm/amba_device.hh" #include "dev/arm/gic.hh" #include "dev/arm/pl011.hh" @@ -185,7 +186,9 @@ Pl011::write(PacketPtr pkt) switch (daddr) { case UART_DR: if ((data & 0xFF) == 0x04 && endOnEOT) { - exitSimLoop("UART received EOT", 0); + //DanceOS + //exitSimLoop("UART received EOT", 0); + DPRINTF(Fail, "[FAIL] dev/arm/pl011.cc write(): exitSimLoop(\"UART received EOT\", 0) bypassed\n"); } term->out(data & 0xFF); diff --git a/simulators/gem5/src/dev/fail_fake_device.cc b/simulators/gem5/src/dev/fail_fake_device.cc new file mode 100644 index 00000000..3210325a --- /dev/null +++ b/simulators/gem5/src/dev/fail_fake_device.cc @@ -0,0 +1,70 @@ +#include "base/trace.hh" +#include "debug/Fail.hh" +#include "dev/fail_fake_device.hh" +#include "mem/packet.hh" +#include "mem/packet_access.hh" +#include "sim/system.hh" + +#include "config/FailConfig.hpp" +#include "sal/SALInst.hpp" + +using namespace std; + +FailFakeDevice::FailFakeDevice(Params *p) + : BasicPioDevice(p) +{ + if (!p->ret_bad_addr) + pioSize = p->pio_size; + + retData8 = p->ret_data8; + retData16 = p->ret_data16; + retData32 = p->ret_data32; + retData64 = p->ret_data64; +} + +Tick +FailFakeDevice::read(PacketPtr pkt) +{ + pkt->allocate(); + pkt->makeAtomicResponse(); + + DPRINTF(Fail, "[FAIL] dev/fail_fake_device.cc read(): fake response\n"); + + switch (pkt->getSize()) { + case sizeof(uint64_t): + pkt->set(retData64); + break; + case sizeof(uint32_t): + pkt->set(retData32); + break; + case sizeof(uint16_t): + pkt->set(retData16); + break; + case sizeof(uint8_t): + pkt->set(retData8); + break; + default: + if (params()->fake_mem) + std::memset(pkt->getPtr(), 0, pkt->getSize()); + else + panic("invalid access size! Device being accessed by cache?\n"); + } + + return pioDelay; +} + +Tick +FailFakeDevice::write(PacketPtr pkt) +{ + pkt->makeAtomicResponse(); + + DPRINTF(Fail, "[FAIL] dev/fail_fake_device.cc write(): fake response\n"); + + return pioDelay; +} + +FailFakeDevice * +FailFakeDeviceParams::create() +{ + return new FailFakeDevice(this); +} diff --git a/simulators/gem5/src/dev/fail_fake_device.hh b/simulators/gem5/src/dev/fail_fake_device.hh new file mode 100644 index 00000000..803bb60e --- /dev/null +++ b/simulators/gem5/src/dev/fail_fake_device.hh @@ -0,0 +1,59 @@ +/** @file + * Declaration of a fake device. + */ + +#ifndef __FAIL_FAKE__DEVICE_HH__ +#define __FAIL_FAKE__DEVICE_HH__ + +#include + +#include "base/range.hh" +#include "dev/io_device.hh" +#include "mem/packet.hh" +#include "params/FailFakeDevice.hh" + +/** + * This device implements a fake device for an iobus. + * On a read this device returns on every request the maximum value. + * On a write nothing happens. + * This device is needed because the iobus has no default device by default. + * In the case of an fault injection the memory request could run over + * membus -> bridge -> iobus. + * If findport() in mem/bus.cc doesnt find a matching port on the iobus a default device is needed. + * This Device is configuered in fs.py and Device.py. + */ +class FailFakeDevice : public BasicPioDevice +{ + protected: + uint8_t retData8; + uint16_t retData16; + uint32_t retData32; + uint64_t retData64; + + public: + typedef FailFakeDeviceParams Params; + const Params * + params() const + { + return dynamic_cast(_params); + } + /** + * The constructor for FailFakeDevice just registers itself with the MMU. + * @param p params structure + */ + FailFakeDevice(Params *p); + + /** + * This read always returns -1. + * @param pkt The memory request. + */ + virtual Tick read(PacketPtr pkt); + + /** + * All writes are simply ignored. + * @param pkt The memory request. + */ + virtual Tick write(PacketPtr pkt); +}; + +#endif // __FAIL_FAKE__DEVICE_HH__