# Node ID e591eadc0c63c9866da76491ba9fe4a16187a0bf # Parent 2f09d85ef98b7f3a1a28c021ad2ec5307f235ad1 diff --git a/src/dev/Cirrus.py b/src/dev/Cirrus.py new file mode 100644 --- /dev/null +++ b/src/dev/Cirrus.py @@ -0,0 +1,69 @@ +# Copyright 2014 Google, Inc. +# +# The license below extends only to copyright in the software and shall +# not be construed as granting a license to any other intellectual +# property including but not limited to intellectual property relating +# to a hardware implementation of the functionality of the software +# licensed hereunder. You may use the software subject to the license +# terms below provided that you ensure that this notice is replicated +# unmodified and in its entirety in all distributions of the software, +# modified or unmodified, in source code or in binary form. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Authors: Slava Malyugin +# Gabe Black + +from m5.defines import buildEnv +from m5.SimObject import SimObject +from m5.params import * +from m5.proxy import * +from Pci import PciDevice + +class Cirrus(PciDevice): + type = 'Cirrus' + cxx_header = "dev/cirrus.hh" + + vnc = Param.VncInput(Parent.any, \ + "Vnc server for remote frame buffer display") + if buildEnv['USE_KVM']: + kvmVM = Param.KvmVM(Parent.any, 'KVM VM (i.e., shared memory domain)') + VendorID = 0x1013 + DeviceID = 0x00b8 + SubsystemVendorID = 0x1AF4 + SubsystemID = 0x1100 + Command = 0x0 + Status = 0x0000 + Revision = 0x0 + ClassCode = 0x03 + SubClassCode = 0x00 + ProgIF = 0x00 + #InterruptLine = 0x1d + #InterruptPin = 0x01 + BAR0 = 0x00000000 + BAR1 = 0x00000000 + + BAR0Size = '4MB' + BAR1Size = '4kB' + diff --git a/src/dev/SConscript b/src/dev/SConscript --- a/src/dev/SConscript +++ b/src/dev/SConscript @@ -49,6 +49,7 @@ SimObject('SimpleDisk.py') SimObject('Terminal.py') SimObject('Uart.py') +SimObject('Cirrus.py') Source('baddev.cc') Source('copy_engine.cc') @@ -77,6 +78,7 @@ Source('terminal.cc') Source('uart.cc') Source('uart8250.cc') +Source('cirrus.cc') DebugFlag('DiskImageRead') DebugFlag('DiskImageWrite') @@ -102,6 +104,7 @@ DebugFlag('Terminal') DebugFlag('TerminalVerbose') DebugFlag('Uart') +DebugFlag('Cirrus') CompoundFlag('DiskImageAll', [ 'DiskImageRead', 'DiskImageWrite' ]) CompoundFlag('EthernetAll', [ 'Ethernet', 'EthernetPIO', 'EthernetDMA', diff --git a/src/dev/cirrus.hh b/src/dev/cirrus.hh new file mode 100644 --- /dev/null +++ b/src/dev/cirrus.hh @@ -0,0 +1,77 @@ +/* + * Copyright 2014 Google, Inc. + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Slava Malyugin + * Gabe Black + */ + +#include "cpu/kvm/vm.hh" +#include "dev/pcidev.hh" +#include "params/Cirrus.hh" + +class VncInput; + +class Cirrus : public PciDevice +{ + VncInput *vnc; + KvmVM *kvmVM; + + const KvmVM::MemSlot memSlot; + uint8_t *dmaBuffer; + + static const int width = 1024; + static const int height = 768; + static const int bytes_per_pixel = 4; + static const int bufsize = width * height * bytes_per_pixel; + + public: + typedef CirrusParams Params; + const Params * + params() const + { + return dynamic_cast(_params); + } + Cirrus(const Params *params); + ~Cirrus(); + + Tick read(PacketPtr pkt); + Tick write(PacketPtr pkt); + void serialize(std::ostream &os); + void unserialize(Checkpoint *cp, const std::string §ion); + Tick writeConfig(PacketPtr pkt); + + void updateFramebuffer(); + EventWrapper updateEvent; +}; diff --git a/src/dev/cirrus.cc b/src/dev/cirrus.cc new file mode 100644 --- /dev/null +++ b/src/dev/cirrus.cc @@ -0,0 +1,196 @@ +/* + * Copyright 2014 Google, Inc. + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Slava Malyugin + * Gabe Black + */ + +#include "base/vnc/vncinput.hh" +#include "config/use_kvm.hh" +#include "debug/Cirrus.hh" +#include "dev/cirrus.hh" + +Tick +Cirrus::read(PacketPtr pkt) +{ + int bar; + Addr daddr; + unsigned size = pkt->getSize(); + + if (!getBAR(pkt->getAddr(), bar, daddr)) + panic("Invalid PCI memory access to unmapped memory.\n"); + + DPRINTF(Cirrus, "Read device register %#X size %u\n", daddr, + pkt->getSize()); + + if (bar == 0) { + assert(dmaBuffer && daddr + size <= bufsize); + memcpy(pkt->getPtr(), dmaBuffer + daddr, size); + } else if (bar == 1) { + // TODO: handle reads from BAR1 + switch (size) { + case 1: pkt->set(0); break; + case 2: pkt->set(0); break; + case 4: pkt->set(0); break; + case 8: pkt->set(0); break; + default: panic("Wrong size in Cirrus::read"); + } + } else { + panic("Unrecognized bar %d\n", bar); + } + + pkt->makeAtomicResponse(); + return pioDelay; +} + +Tick +Cirrus::write(PacketPtr pkt) +{ + int bar; + Addr daddr; + uint32_t val; + unsigned size = pkt->getSize(); + + if (!getBAR(pkt->getAddr(), bar, daddr)) + panic("Invalid PCI memory access to unmapped memory.\n"); + + switch (size) { + case 1: val = pkt->get(); break; + case 2: val = pkt->get(); break; + case 4: val = pkt->get(); break; + case 8: val = pkt->get(); break; + default: panic("Wrong size in Cirrus::write"); + } + DPRINTF(Cirrus, "Wrote device register %#X value %#X size %u\n", + daddr, val, pkt->getSize()); + + if (bar == 0) { + assert(dmaBuffer && daddr + size <= bufsize); + memcpy(dmaBuffer + daddr, pkt->getPtr(), size); +#if 0 // Too much traffic + if (vnc) + vnc->setDirty(); +#endif + } else if (bar == 1) { + // TODO: handle writes to BAR1 + } else { + panic("Unrecognized bar %d\n", bar); + } + + pkt->makeAtomicResponse(); + return pioDelay; +} + +// make BAR0 pass-thru memory +Tick +Cirrus::writeConfig(PacketPtr pkt) +{ + Addr oldAddr = BARAddrs[0]; + Tick delay = PciDevice::writeConfig(pkt); + Addr newAddr = BARAddrs[0]; + + if (USE_KVM && oldAddr != newAddr && kvmVM) { + if (newAddr) + kvmVM->setupMemSlot(memSlot, dmaBuffer, newAddr, 0); + else + kvmVM->disableMemSlot(memSlot); + } + return delay; +} + +void +Cirrus::updateFramebuffer() +{ + vnc->setDirty(); + // Shoot for a 10Hz (100ms) refresh rate. + schedule(updateEvent, curTick() + 100 * SimClock::Int::ms); +} + +Cirrus::Cirrus(const Params *p) : PciDevice(p), vnc(p->vnc), +#if USE_KVM + kvmVM(p->kvmVM), +#else + kvmVM(NULL), +#endif + updateEvent(this) +{ + DPRINTF(Cirrus, "Cirrus is alive %p\n", this); + + dmaBuffer = new uint8_t[bufsize]; + memset(dmaBuffer, 0, bufsize); + + if (USE_KVM && kvmVM) + *const_cast(&memSlot) = kvmVM->allocMemSlot(bufsize); + if (vnc) { + vnc->setFramebufferAddr(dmaBuffer); + vnc->setFrameBufferParams(VideoConvert::bgr888, width, height); + updateFramebuffer(); + } +} + +Cirrus::~Cirrus() +{ + delete[] dmaBuffer; + dmaBuffer = NULL; + if (USE_KVM && kvmVM) + kvmVM->freeMemSlot(memSlot); +} + +void +Cirrus::serialize(std::ostream &os) +{ + PciDevice::serialize(os); + + SERIALIZE_ARRAY(dmaBuffer, bufsize); +} + +void +Cirrus::unserialize(Checkpoint *cp, const std::string §ion) +{ + PciDevice::unserialize(cp, section); + + UNSERIALIZE_ARRAY(dmaBuffer, bufsize); + + if (BARAddrs[0] != 0) { + platform->system->getPhysMem(). + addMemoryRange(BARAddrs[0], dmaBuffer, bufsize); + } +} + +Cirrus * +CirrusParams::create() +{ + return new Cirrus(this); +}