113837Sgabeblack@google.com/* 213837Sgabeblack@google.com * Copyright 2019 Google, Inc. 313837Sgabeblack@google.com * 413837Sgabeblack@google.com * Redistribution and use in source and binary forms, with or without 513837Sgabeblack@google.com * modification, are permitted provided that the following conditions are 613837Sgabeblack@google.com * met: redistributions of source code must retain the above copyright 713837Sgabeblack@google.com * notice, this list of conditions and the following disclaimer; 813837Sgabeblack@google.com * redistributions in binary form must reproduce the above copyright 913837Sgabeblack@google.com * notice, this list of conditions and the following disclaimer in the 1013837Sgabeblack@google.com * documentation and/or other materials provided with the distribution; 1113837Sgabeblack@google.com * neither the name of the copyright holders nor the names of its 1213837Sgabeblack@google.com * contributors may be used to endorse or promote products derived from 1313837Sgabeblack@google.com * this software without specific prior written permission. 1413837Sgabeblack@google.com * 1513837Sgabeblack@google.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1613837Sgabeblack@google.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 1713837Sgabeblack@google.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 1813837Sgabeblack@google.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 1913837Sgabeblack@google.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 2013837Sgabeblack@google.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 2113837Sgabeblack@google.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2213837Sgabeblack@google.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2313837Sgabeblack@google.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2413837Sgabeblack@google.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 2513837Sgabeblack@google.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2613837Sgabeblack@google.com * 2713837Sgabeblack@google.com * Authors: Gabe Black 2813837Sgabeblack@google.com */ 2913837Sgabeblack@google.com 3013837Sgabeblack@google.com#ifndef __MEM_BACKDOOR_HH__ 3113837Sgabeblack@google.com#define __MEM_BACKDOOR_HH__ 3213837Sgabeblack@google.com 3313837Sgabeblack@google.com#include <cstdint> 3413837Sgabeblack@google.com#include <functional> 3513837Sgabeblack@google.com#include <memory> 3613837Sgabeblack@google.com 3713837Sgabeblack@google.com#include "base/addr_range.hh" 3813837Sgabeblack@google.com#include "base/callback.hh" 3913837Sgabeblack@google.com 4013837Sgabeblack@google.comclass MemBackdoor 4113837Sgabeblack@google.com{ 4213837Sgabeblack@google.com public: 4313837Sgabeblack@google.com // Callbacks from this back door are set up using a callable which accepts 4413837Sgabeblack@google.com // a const reference to this back door as their only parameter. 4513837Sgabeblack@google.com typedef std::function<void(const MemBackdoor &backdoor)> CbFunction; 4613837Sgabeblack@google.com 4713837Sgabeblack@google.com private: 4813837Sgabeblack@google.com // This wrapper class holds the callables described above so that they 4913837Sgabeblack@google.com // can be stored in a generic CallbackQueue. 5013837Sgabeblack@google.com class Callback : public ::Callback 5113837Sgabeblack@google.com { 5213837Sgabeblack@google.com public: 5313837Sgabeblack@google.com Callback(MemBackdoor &bd, CbFunction cb) : 5413837Sgabeblack@google.com _backdoor(bd), cbFunction(cb) 5513837Sgabeblack@google.com {} 5613837Sgabeblack@google.com 5713837Sgabeblack@google.com void process() override { cbFunction(_backdoor); } 5813837Sgabeblack@google.com // It looks like this is only called when the CallbackQueue is 5913837Sgabeblack@google.com // destroyed and this Callback is currently in the queue. 6013837Sgabeblack@google.com void autoDestruct() override { delete this; } 6113837Sgabeblack@google.com 6213837Sgabeblack@google.com MemBackdoor &backdoor() { return _backdoor; } 6313837Sgabeblack@google.com 6413837Sgabeblack@google.com private: 6513837Sgabeblack@google.com MemBackdoor &_backdoor; 6613837Sgabeblack@google.com CbFunction cbFunction; 6713837Sgabeblack@google.com }; 6813837Sgabeblack@google.com 6913837Sgabeblack@google.com public: 7013837Sgabeblack@google.com enum Flags{ 7113837Sgabeblack@google.com // How data is allowed to be accessed through this backdoor. 7213837Sgabeblack@google.com NoAccess = 0x0, 7313837Sgabeblack@google.com Readable = 0x1, 7413837Sgabeblack@google.com Writeable = 0x2 7513837Sgabeblack@google.com }; 7613837Sgabeblack@google.com 7713837Sgabeblack@google.com // The range in the guest address space covered by this back door. 7813837Sgabeblack@google.com const AddrRange &range() const { return _range; } 7913837Sgabeblack@google.com void range(const AddrRange &r) { _range = r; } 8013837Sgabeblack@google.com 8113837Sgabeblack@google.com // A pointer to the data accessible through this back door. 8213837Sgabeblack@google.com uint8_t *ptr() const { return _ptr; } 8313837Sgabeblack@google.com void ptr(uint8_t *p) { _ptr = p; } 8413837Sgabeblack@google.com 8513837Sgabeblack@google.com /* 8613837Sgabeblack@google.com * Helper functions to make it easier to set/check particular flags. 8713837Sgabeblack@google.com */ 8813837Sgabeblack@google.com 8913837Sgabeblack@google.com bool readable() const { return _flags & Readable; } 9013837Sgabeblack@google.com void 9113837Sgabeblack@google.com readable(bool r) 9213837Sgabeblack@google.com { 9313837Sgabeblack@google.com if (r) 9413837Sgabeblack@google.com _flags = (Flags)(_flags | Readable); 9513837Sgabeblack@google.com else 9613837Sgabeblack@google.com _flags = (Flags)(_flags & ~Readable); 9713837Sgabeblack@google.com } 9813837Sgabeblack@google.com 9913837Sgabeblack@google.com bool writeable() const { return _flags & Writeable; } 10013837Sgabeblack@google.com void 10113837Sgabeblack@google.com writeable(bool w) 10213837Sgabeblack@google.com { 10313837Sgabeblack@google.com if (w) 10413837Sgabeblack@google.com _flags = (Flags)(_flags | Writeable); 10513837Sgabeblack@google.com else 10613837Sgabeblack@google.com _flags = (Flags)(_flags & ~Writeable); 10713837Sgabeblack@google.com } 10813837Sgabeblack@google.com 10913837Sgabeblack@google.com Flags flags() const { return _flags; } 11013837Sgabeblack@google.com void flags(Flags f) { _flags = f; } 11113837Sgabeblack@google.com 11213837Sgabeblack@google.com MemBackdoor(AddrRange r, uint8_t *p, Flags flags) : 11313837Sgabeblack@google.com invalidationCallbacks(new CallbackQueue), 11413837Sgabeblack@google.com _range(r), _ptr(p), _flags(flags) 11513837Sgabeblack@google.com {} 11613837Sgabeblack@google.com 11713837Sgabeblack@google.com MemBackdoor() : MemBackdoor(AddrRange(), nullptr, NoAccess) 11813837Sgabeblack@google.com {} 11913837Sgabeblack@google.com 12013837Sgabeblack@google.com // Set up a callable to be called when this back door is invalidated. This 12113837Sgabeblack@google.com // lets holders update their bookkeeping to remove any references to it, 12213837Sgabeblack@google.com // and/or to propogate that invalidation to other interested parties. 12313837Sgabeblack@google.com void 12413837Sgabeblack@google.com addInvalidationCallback(CbFunction func) 12513837Sgabeblack@google.com { 12613837Sgabeblack@google.com auto *cb = new MemBackdoor::Callback(*this, func); 12713837Sgabeblack@google.com assert(cb); 12813837Sgabeblack@google.com invalidationCallbacks->add(cb); 12913837Sgabeblack@google.com } 13013837Sgabeblack@google.com 13113837Sgabeblack@google.com // Notify and clear invalidation callbacks when the data in the backdoor 13213837Sgabeblack@google.com // structure is no longer valid/current. The backdoor might then be 13313837Sgabeblack@google.com // updated or even deleted without having to worry about stale data being 13413837Sgabeblack@google.com // used. 13513837Sgabeblack@google.com void 13613837Sgabeblack@google.com invalidate() 13713837Sgabeblack@google.com { 13813837Sgabeblack@google.com invalidationCallbacks->process(); 13913837Sgabeblack@google.com // Delete and recreate the callback queue to ensure the callback 14013837Sgabeblack@google.com // objects are deleted. 14113837Sgabeblack@google.com invalidationCallbacks.reset(new CallbackQueue()); 14213837Sgabeblack@google.com } 14313837Sgabeblack@google.com 14413837Sgabeblack@google.com private: 14513837Sgabeblack@google.com std::unique_ptr<CallbackQueue> invalidationCallbacks; 14613837Sgabeblack@google.com 14713837Sgabeblack@google.com AddrRange _range; 14813837Sgabeblack@google.com uint8_t *_ptr; 14913837Sgabeblack@google.com Flags _flags; 15013837Sgabeblack@google.com}; 15113837Sgabeblack@google.com 15213837Sgabeblack@google.comtypedef MemBackdoor *MemBackdoorPtr; 15313837Sgabeblack@google.com 15413837Sgabeblack@google.com#endif //__MEM_BACKDOOR_HH__ 155