From 30666c20baa42444fea5481f68d7f3463a69ca82 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Thu, 7 May 2020 04:17:31 -0700 Subject: [PATCH] sim: Retrofit the VPtr type. Rename it to be ProxyPtr and ConstProxyPtr, merge it with the functionality of BufferArg and TypedBufferArg, etc., as described in this design doc. https://docs.google.com/document/d/1BYHBJcf7dB2Z25zAZ9snbeRKfstK9uERYH_3h66w_tc/ Change-Id: I2fddde20cc0ece257685bc50bd3419a4e9a00145 Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/29400 Reviewed-by: Ciro Santilli Reviewed-by: Matthew Poremba Maintainer: Gabe Black Tested-by: kokoro --- src/arch/generic/freebsd/threadinfo.hh | 1 - src/arch/generic/linux/threadinfo.hh | 1 - src/sim/proxy_ptr.hh | 374 +++++++++++++++++++++++++ src/sim/pseudo_inst.cc | 1 - src/sim/syscall_emul.hh | 1 + src/sim/vptr.hh | 133 --------- 6 files changed, 375 insertions(+), 136 deletions(-) create mode 100644 src/sim/proxy_ptr.hh delete mode 100644 src/sim/vptr.hh diff --git a/src/arch/generic/freebsd/threadinfo.hh b/src/arch/generic/freebsd/threadinfo.hh index af9dd85bf..28184e790 100644 --- a/src/arch/generic/freebsd/threadinfo.hh +++ b/src/arch/generic/freebsd/threadinfo.hh @@ -35,7 +35,6 @@ #include "cpu/thread_context.hh" #include "sim/system.hh" -#include "sim/vptr.hh" namespace FreeBSD { diff --git a/src/arch/generic/linux/threadinfo.hh b/src/arch/generic/linux/threadinfo.hh index 3024c8605..a15670d81 100644 --- a/src/arch/generic/linux/threadinfo.hh +++ b/src/arch/generic/linux/threadinfo.hh @@ -31,7 +31,6 @@ #include "cpu/thread_context.hh" #include "sim/system.hh" -#include "sim/vptr.hh" namespace Linux { diff --git a/src/sim/proxy_ptr.hh b/src/sim/proxy_ptr.hh new file mode 100644 index 000000000..a59bbff66 --- /dev/null +++ b/src/sim/proxy_ptr.hh @@ -0,0 +1,374 @@ +/* + * Copyright (c) 2004-2005 The Regents of The University of Michigan + * All rights reserved. + * + * 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. + */ + +#ifndef __SIM_PROXY_PTR_HH__ +#define __SIM_PROXY_PTR_HH__ + +#include +#include +#include + +#include "base/logging.hh" +#include "base/types.hh" +#include "sim/guest_abi.hh" + +template +class ProxyPtrBuffer +{ + private: + std::shared_ptr proxy; + + Addr ptr; + size_t size; + std::unique_ptr data; + + bool dirty = false; + + void markClean() { dirty = false; } + + public: + + std::shared_ptr getProxy() const { return proxy; } + + void markDirty() { dirty = true; } + bool isDirty() { return dirty; } + + template + T & + as() + { + assert(sizeof(T) <= size); + markDirty(); + return *reinterpret_cast(data.get()); + } + + template + const T & + asConst() const + { + assert(sizeof(T) <= size); + return *reinterpret_cast(data.get()); + } + + void + flush(bool force=false) + { + if (force || isDirty()) { + proxy->writeBlob(ptr, data.get(), size); + markClean(); + } + } + + void + load() + { + panic_if(isDirty(), "Overwriting dirty ProxyPtr."); + proxy->readBlob(ptr, data.get(), size); + } + + Addr addr() const { return ptr; } + + ProxyPtrBuffer(std::shared_ptr _proxy, Addr _ptr, size_t _size) : + proxy(_proxy), ptr(_ptr), size(_size), data(new uint8_t[_size]) + { + load(); + } + + ~ProxyPtrBuffer() { flush(); } +}; + +template +class ConstProxyPtr +{ + protected: + std::shared_ptr proxy; + std::shared_ptr> buffer; + + template + friend class ProxyPtr; + + void nullCheck() const { panic_if(!buffer, "Accessing null ProxyPtr."); } + + void + setAddr(Addr ptr) + { + if (ptr) + buffer.reset(new ProxyPtrBuffer(proxy, ptr, sizeof(T))); + else + buffer.reset((ProxyPtrBuffer *)nullptr); + } + + ConstProxyPtr(Addr _ptr, std::shared_ptr _proxy) : proxy(_proxy) + { + setAddr(_ptr); + } + + using CPP = ConstProxyPtr; + + public: + using Type = T; + + template ::value, int>::type = 0> + explicit ConstProxyPtr(Addr _ptr, Args&&... args) : + proxy(std::make_shared(args...)) + { + setAddr(_ptr); + } + template ::value, int>::type = 0> + explicit ConstProxyPtr(Args&&... args) : + proxy(std::make_shared(args...)) + { + setAddr(0); + } + + template ::value>::type> + ConstProxyPtr(const ConstProxyPtr &other) : + proxy(other.proxy), buffer(other.buffer) + {} + + ConstProxyPtr(const CPP &other) : + proxy(other.proxy), buffer(other.buffer) + {} + + void + load() + { + nullCheck(); + buffer->load(); + } + + Addr addr() const { return buffer ? buffer->addr() : 0; } + operator bool() const { return (bool)buffer; } + + template + typename std::enable_if::value, CPP>::type + operator + (A a) const + { + return CPP(addr() + a * sizeof(T), proxy); + } + + template + typename std::enable_if::value, CPP>::type + operator - (A a) const + { + return CPP(addr() - a * sizeof(T), proxy); + } + + ptrdiff_t + operator - (const CPP &other) const + { + return (addr() - other.addr()) / sizeof(T); + } + + CPP & + operator = (const CPP &other) + { + proxy = other.proxy; + buffer = other.buffer; + return *this; + } + + CPP & + operator = (const Addr &a) + { + setAddr(a); + return *this; + } + + operator const T *() const + { + return buffer ? &buffer->template asConst() : nullptr; + } + + const T & + operator *() const + { + nullCheck(); + return buffer->template asConst(); + } + const T * + operator ->() const + { + nullCheck(); + return &buffer->template asConst(); + } +}; + +template +typename std::enable_if::value, + ConstProxyPtr>::type +operator + (A a, const ConstProxyPtr &other) +{ + return other + a; +} + +template +class ProxyPtr : public ConstProxyPtr +{ + protected: + using CPP = ConstProxyPtr; + using PP = ProxyPtr; + + ProxyPtr(Addr _ptr, std::shared_ptr _proxy) : CPP(_ptr, _proxy) {} + + public: + template ::value, int>::type = 0> + explicit ProxyPtr(Addr _ptr, Args&&... args) : CPP(_ptr, args...) {} + template ::value, int>::type = 0> + explicit ProxyPtr(Args&&... args) : CPP(0, args...) {} + + template ::value>::type> + ProxyPtr(const ProxyPtr &other) : CPP(other) {} + + ProxyPtr(const PP &other) : CPP(other) {} + operator bool() const { return (bool)this->buffer; } + + void + flush(bool force=false) + { + this->nullCheck(); + this->buffer->flush(force); + } + + template + typename std::enable_if::value, PP>::type + operator + (A a) const + { + return PP(this->addr() + a * sizeof(T), this->proxy); + } + + template + typename std::enable_if::value, PP>::type + operator - (A a) const + { + return PP(this->addr() - a * sizeof(T), this->proxy); + } + + ptrdiff_t + operator - (const PP &other) const + { + return (this->addr() - other.addr()) / sizeof(T); + } + + PP & + operator = (const PP &other) + { + this->proxy = other.proxy; + this->buffer = other.buffer; + return *this; + } + + PP & + operator = (const Addr &a) + { + this->setAddr(a); + return *this; + } + + using CPP::operator const T *; + operator T *() const + { + return this->buffer ? &this->buffer->template as() : nullptr; + } + + using CPP::operator *; + T & + operator *() const + { + this->nullCheck(); + return this->buffer->template as(); + } + + using CPP::operator ->; + T * + operator ->() const + { + this->nullCheck(); + return &this->buffer->template as(); + } +}; + +template +typename std::enable_if::value, ProxyPtr>::type +operator + (A a, const ProxyPtr &other) +{ + return other + a; +} + +namespace GuestABI +{ + +template +struct Argument> +{ + static ProxyPtr + get(ThreadContext *tc, typename ABI::State &state) + { + return ProxyPtr(Argument::get(tc, state), tc); + } +}; + +template +struct Argument> +{ + static ConstProxyPtr + get(ThreadContext *tc, typename ABI::State &state) + { + return ConstProxyPtr( + Argument::get(tc, state), tc); + } +}; + +} // namespace GuestABI + +template +std::ostream & +operator << (std::ostream &os, const ConstProxyPtr &vptr) +{ + ccprintf(os, "%#x", vptr.addr()); + return os; +} + +class SETranslatingPortProxy; + +template +using ConstVPtr = ConstProxyPtr; +template +using VPtr = ProxyPtr; + +#endif // __SIM_PROXY_PTR_HH__ diff --git a/src/sim/pseudo_inst.cc b/src/sim/pseudo_inst.cc index 8c662c657..acc9dcf62 100644 --- a/src/sim/pseudo_inst.cc +++ b/src/sim/pseudo_inst.cc @@ -69,7 +69,6 @@ #include "sim/stat_control.hh" #include "sim/stats.hh" #include "sim/system.hh" -#include "sim/vptr.hh" using namespace std; using namespace Stats; diff --git a/src/sim/syscall_emul.hh b/src/sim/syscall_emul.hh index aa81e14b3..55695781b 100644 --- a/src/sim/syscall_emul.hh +++ b/src/sim/syscall_emul.hh @@ -101,6 +101,7 @@ #include "sim/futex_map.hh" #include "sim/guest_abi.hh" #include "sim/process.hh" +#include "sim/proxy_ptr.hh" #include "sim/syscall_debug_macros.hh" #include "sim/syscall_desc.hh" #include "sim/syscall_emul_buf.hh" diff --git a/src/sim/vptr.hh b/src/sim/vptr.hh deleted file mode 100644 index 92aea797c..000000000 --- a/src/sim/vptr.hh +++ /dev/null @@ -1,133 +0,0 @@ -/* - * Copyright (c) 2004-2005 The Regents of The University of Michigan - * All rights reserved. - * - * 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. - */ - -#ifndef __SIM_VPTR_HH__ -#define __SIM_VPTR_HH__ - -#include "mem/port_proxy.hh" - -class ThreadContext; - -template -class VPtr -{ - public: - typedef T Type; - - protected: - ThreadContext *tc; - Addr ptr; - Addr buffer[(sizeof(T)-1)/sizeof(Addr) + 1]; - - public: - explicit VPtr(ThreadContext *_tc, Addr p = 0) - : tc(_tc), ptr(p) - { - refresh(); - } - - template - VPtr(const VPtr &vp) - : tc(vp.tc), ptr(vp.ptr) - { - refresh(); - } - - ~VPtr() - {} - - void - refresh() - { - if (!ptr) - return; - - PortProxy &proxy = tc->getVirtProxy(); - proxy.readBlob(ptr, buffer, sizeof(T)); - } - - bool - operator!() const - { - return ptr == 0; - } - - VPtr - operator+(int offset) - { - return VPtr(tc, ptr + offset); - } - - const VPtr & - operator+=(int offset) - { - ptr += offset; - refresh(); - - return *this; - } - - const VPtr & - operator=(Addr p) - { - ptr = p; - refresh(); - - return *this; - } - - template - const VPtr & - operator=(const VPtr &vp) - { - tc = vp.tc; - ptr = vp.ptr; - refresh(); - - return *this; - } - - operator T *() - { - return (T *)buffer; - } - - T * - operator->() - { - return (T *)buffer; - } - - T & - operator*() - { - return *(T *)buffer; - } -}; - -#endif // __SIM_VPTR_HH__ -- 2.30.2