diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/mem/backdoor.hh | 154 |
1 files changed, 154 insertions, 0 deletions
diff --git a/src/mem/backdoor.hh b/src/mem/backdoor.hh new file mode 100644 index 000000000..24db2c980 --- /dev/null +++ b/src/mem/backdoor.hh @@ -0,0 +1,154 @@ +/* + * Copyright 2019 Google, Inc. + * + * 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: Gabe Black + */ + +#ifndef __MEM_BACKDOOR_HH__ +#define __MEM_BACKDOOR_HH__ + +#include <cstdint> +#include <functional> +#include <memory> + +#include "base/addr_range.hh" +#include "base/callback.hh" + +class MemBackdoor +{ + public: + // Callbacks from this back door are set up using a callable which accepts + // a const reference to this back door as their only parameter. + typedef std::function<void(const MemBackdoor &backdoor)> CbFunction; + + private: + // This wrapper class holds the callables described above so that they + // can be stored in a generic CallbackQueue. + class Callback : public ::Callback + { + public: + Callback(MemBackdoor &bd, CbFunction cb) : + _backdoor(bd), cbFunction(cb) + {} + + void process() override { cbFunction(_backdoor); } + // It looks like this is only called when the CallbackQueue is + // destroyed and this Callback is currently in the queue. + void autoDestruct() override { delete this; } + + MemBackdoor &backdoor() { return _backdoor; } + + private: + MemBackdoor &_backdoor; + CbFunction cbFunction; + }; + + public: + enum Flags{ + // How data is allowed to be accessed through this backdoor. + NoAccess = 0x0, + Readable = 0x1, + Writeable = 0x2 + }; + + // The range in the guest address space covered by this back door. + const AddrRange &range() const { return _range; } + void range(const AddrRange &r) { _range = r; } + + // A pointer to the data accessible through this back door. + uint8_t *ptr() const { return _ptr; } + void ptr(uint8_t *p) { _ptr = p; } + + /* + * Helper functions to make it easier to set/check particular flags. + */ + + bool readable() const { return _flags & Readable; } + void + readable(bool r) + { + if (r) + _flags = (Flags)(_flags | Readable); + else + _flags = (Flags)(_flags & ~Readable); + } + + bool writeable() const { return _flags & Writeable; } + void + writeable(bool w) + { + if (w) + _flags = (Flags)(_flags | Writeable); + else + _flags = (Flags)(_flags & ~Writeable); + } + + Flags flags() const { return _flags; } + void flags(Flags f) { _flags = f; } + + MemBackdoor(AddrRange r, uint8_t *p, Flags flags) : + invalidationCallbacks(new CallbackQueue), + _range(r), _ptr(p), _flags(flags) + {} + + MemBackdoor() : MemBackdoor(AddrRange(), nullptr, NoAccess) + {} + + // Set up a callable to be called when this back door is invalidated. This + // lets holders update their bookkeeping to remove any references to it, + // and/or to propogate that invalidation to other interested parties. + void + addInvalidationCallback(CbFunction func) + { + auto *cb = new MemBackdoor::Callback(*this, func); + assert(cb); + invalidationCallbacks->add(cb); + } + + // Notify and clear invalidation callbacks when the data in the backdoor + // structure is no longer valid/current. The backdoor might then be + // updated or even deleted without having to worry about stale data being + // used. + void + invalidate() + { + invalidationCallbacks->process(); + // Delete and recreate the callback queue to ensure the callback + // objects are deleted. + invalidationCallbacks.reset(new CallbackQueue()); + } + + private: + std::unique_ptr<CallbackQueue> invalidationCallbacks; + + AddrRange _range; + uint8_t *_ptr; + Flags _flags; +}; + +typedef MemBackdoor *MemBackdoorPtr; + +#endif //__MEM_BACKDOOR_HH__ |