mem: Add a MemBackdoor type to track memory backdoors.
authorGabe Black <gabeblack@google.com>
Fri, 22 Mar 2019 00:12:08 +0000 (17:12 -0700)
committerGabe Black <gabeblack@google.com>
Sat, 6 Apr 2019 00:52:15 +0000 (00:52 +0000)
These are similar to the structures TLM's DMI mechanism uses. Instead
of having an invalidation broadcast which propogates backwards up the
port hierarchy, this mechanism tracks a set of callbacks which are
triggered when a back door is invalidated to let other holders clean
up their bookkeeping.

Change-Id: If24489258dcaee14d7b6e5b996dfb1c2636f26ab
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/17589
Reviewed-by: Andreas Sandberg <andreas.sandberg@arm.com>
Reviewed-by: Jason Lowe-Power <jason@lowepower.com>
Maintainer: Gabe Black <gabeblack@google.com>

src/mem/backdoor.hh [new file with mode: 0644]

diff --git a/src/mem/backdoor.hh b/src/mem/backdoor.hh
new file mode 100644 (file)
index 0000000..24db2c9
--- /dev/null
@@ -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__