--- /dev/null
+/*
+ * 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__