From de52f3614cb6da91ada190d2e5b6e9f9825511f5 Mon Sep 17 00:00:00 2001 From: Robert Hauser Date: Mon, 11 Mar 2024 15:27:58 +0000 Subject: [PATCH 1/9] sim: enable pseudo instructions with varying pointer size In this patch, Addr is subtituted by a struct wrapper (uint64_t) in the pseudo instruction functions. This enables a correct argument handling in systems where pointer size != 64 bit. Change-Id: Ie84b43b4ab8e6c0d38c7b6b16e19fc043110681b --- src/arch/arm/reg_abi.hh | 8 ++++++-- src/arch/arm/semihosting.hh | 24 +++++++++++++++++------- src/arch/riscv/reg_abi.hh | 28 ++++++++++++++++++++++++++-- src/arch/sparc/pseudo_inst_abi.hh | 15 +++++++++++++++ src/arch/x86/pseudo_inst_abi.hh | 26 ++++++++++++++++++++++++++ src/sim/guest_abi/layout.hh | 3 ++- src/sim/pseudo_inst.cc | 28 ++++++++++++++-------------- src/sim/pseudo_inst.hh | 20 ++++++++++++++++---- src/sim/syscall_abi.hh | 8 ++++++-- 9 files changed, 128 insertions(+), 32 deletions(-) diff --git a/src/arch/arm/reg_abi.hh b/src/arch/arm/reg_abi.hh index e892166c5e..6bdc8b36c1 100644 --- a/src/arch/arm/reg_abi.hh +++ b/src/arch/arm/reg_abi.hh @@ -31,6 +31,7 @@ #include #include "base/logging.hh" +#include "sim/pseudo_inst.hh" #include "sim/syscall_abi.hh" namespace gem5 @@ -54,11 +55,13 @@ struct RegABI64 : public GenericSyscallABI64 namespace guest_abi { +using namespace pseudo_inst; + template struct Argument && - std::is_integral_v && + (std::is_integral_v || std::is_same::value) && ABI::template IsWideV>> { static Arg @@ -71,7 +74,8 @@ struct Argument(&merge); } }; diff --git a/src/arch/arm/semihosting.hh b/src/arch/arm/semihosting.hh index 557eb76636..221c0ce3cb 100644 --- a/src/arch/arm/semihosting.hh +++ b/src/arch/arm/semihosting.hh @@ -51,6 +51,7 @@ #include "mem/port_proxy.hh" #include "sim/core.hh" #include "sim/guest_abi.hh" +#include "sim/pseudo_inst.hh" #include "sim/sim_object.hh" namespace gem5 @@ -602,28 +603,37 @@ std::ostream &operator << ( namespace guest_abi { +using namespace pseudo_inst; + template struct Argument>> + typename std::enable_if_t< + (std::is_integral_v || std::is_same::value)>> { static Arg get(ThreadContext *tc, ArmSemihosting::Abi64::State &state) { - return state.get(tc); + auto arg = state.get(tc); + return *reinterpret_cast(&arg); } }; template struct Argument>> + typename std::enable_if_t< + (std::is_integral_v || std::is_same::value)>> { static Arg get(ThreadContext *tc, ArmSemihosting::Abi32::State &state) { - if (std::is_signed_v) - return sext<32>(state.get(tc)); - else - return state.get(tc); + if (std::is_signed_v) { + auto arg = sext<32>(state.get(tc)); + return *reinterpret_cast(&arg); + } + else { + auto arg = state.get(tc); + return *reinterpret_cast(&arg); + } } }; diff --git a/src/arch/riscv/reg_abi.hh b/src/arch/riscv/reg_abi.hh index 4c965321f7..6f1c8cbc6c 100644 --- a/src/arch/riscv/reg_abi.hh +++ b/src/arch/riscv/reg_abi.hh @@ -54,8 +54,10 @@ struct RegABI32 : public GenericSyscallABI32 namespace guest_abi { +using namespace pseudo_inst; + // This method will be used if the size of argument type of function is -// greater than 4 for Riscv 32. +// greater than 4 byte for Riscv 32. template struct Argument= ABI::ArgumentRegs.size(), "Ran out of syscall argument registers."); - return bits(tc->getReg(ABI::ArgumentRegs[state++]), 31, 0); + + auto low = ABI::ArgumentRegs[state++]; + auto high = ABI::ArgumentRegs[state++]; + return (Arg)ABI::mergeRegs(tc, low, high); + } +}; + +// This method will be used for Riscv 32 pointers. +template +struct Argument && + std::is_same::value && + ABI::template IsWideV>> +{ + static Arg + get(ThreadContext *tc, typename ABI::State &state) + { + panic_if(state >= ABI::ArgumentRegs.size(), + "Ran out of syscall argument registers."); + + auto arg = bits(tc->getReg(ABI::ArgumentRegs[state++]), 31, 0); + return *reinterpret_cast(&arg); } }; diff --git a/src/arch/sparc/pseudo_inst_abi.hh b/src/arch/sparc/pseudo_inst_abi.hh index 989f0e7dfc..58b64d805a 100644 --- a/src/arch/sparc/pseudo_inst_abi.hh +++ b/src/arch/sparc/pseudo_inst_abi.hh @@ -31,6 +31,7 @@ #include "arch/sparc/regs/int.hh" #include "cpu/thread_context.hh" #include "sim/guest_abi.hh" +#include "sim/pseudo_inst.hh" namespace gem5 { @@ -43,6 +44,8 @@ struct SparcPseudoInstABI namespace guest_abi { +using namespace pseudo_inst; + template struct Result { @@ -67,6 +70,18 @@ struct Argument } }; +template <> +struct Argument +{ + static GuestAddr + get(ThreadContext *tc, SparcPseudoInstABI::State &state) + { + panic_if(state >= 6, "Too many psuedo inst arguments."); + auto arg = tc->getReg(SparcISA::int_reg::o(state++)); + return *reinterpret_cast(&arg); + } +}; + } // namespace guest_abi } // namespace gem5 diff --git a/src/arch/x86/pseudo_inst_abi.hh b/src/arch/x86/pseudo_inst_abi.hh index e465c7abd5..0c098f16e2 100644 --- a/src/arch/x86/pseudo_inst_abi.hh +++ b/src/arch/x86/pseudo_inst_abi.hh @@ -37,6 +37,7 @@ #include "arch/x86/regs/int.hh" #include "sim/guest_abi.hh" +#include "sim/pseudo_inst.hh" namespace gem5 { @@ -49,6 +50,8 @@ struct X86PseudoInstABI namespace guest_abi { +using namespace pseudo_inst; + template struct Result { @@ -84,5 +87,28 @@ struct Argument } }; +template <> +struct Argument +{ + static GuestAddr + get(ThreadContext *tc, X86PseudoInstABI::State &state) + { + // The first 6 integer arguments are passed in registers, the rest + // are passed on the stack. + + panic_if(state >= 6, "Too many psuedo inst arguments."); + + using namespace X86ISA; + + constexpr RegId int_reg_map[] = { + int_reg::Rdi, int_reg::Rsi, int_reg::Rdx, + int_reg::Rcx, int_reg::R8, int_reg::R9 + }; + + auto arg = tc->getReg(int_reg_map[state++]); + return *reinterpret_cast(&arg); + } +}; + } // namespace guest_abi } // namespace gem5 diff --git a/src/sim/guest_abi/layout.hh b/src/sim/guest_abi/layout.hh index 4d469b177c..3ea01c168c 100644 --- a/src/sim/guest_abi/layout.hh +++ b/src/sim/guest_abi/layout.hh @@ -169,7 +169,8 @@ template static Arg getArgument(ThreadContext *tc, typename ABI::State &state) { - return Argument::get(tc, state); + auto arg = Argument::get(tc, state); + return *reinterpret_cast(&arg); } } // namespace guest_abi diff --git a/src/sim/pseudo_inst.cc b/src/sim/pseudo_inst.cc index 29caba6661..084be5a419 100644 --- a/src/sim/pseudo_inst.cc +++ b/src/sim/pseudo_inst.cc @@ -256,27 +256,27 @@ loadsymbol(ThreadContext *tc) } void -addsymbol(ThreadContext *tc, Addr addr, Addr symbolAddr) +addsymbol(ThreadContext *tc, GuestAddr addr, GuestAddr symbolAddr) { DPRINTF(PseudoInst, "pseudo_inst::addsymbol(0x%x, 0x%x)\n", - addr, symbolAddr); + addr.addr, symbolAddr.addr); std::string symbol; TranslatingPortProxy fs_proxy(tc); SETranslatingPortProxy se_proxy(tc); PortProxy &virt_proxy = FullSystem ? fs_proxy : se_proxy; - virt_proxy.readString(symbol, symbolAddr); + virt_proxy.readString(symbol, symbolAddr.addr); - DPRINTF(Loader, "Loaded symbol: %s @ %#llx\n", symbol, addr); + DPRINTF(Loader, "Loaded symbol: %s @ %#llx\n", symbol, addr.addr); tc->getSystemPtr()->workload->insertSymbol( { loader::Symbol::Binding::Global, - loader::Symbol::SymbolType::Function, symbol, addr } + loader::Symbol::SymbolType::Function, symbol, addr.addr } ); loader::debugSymbolTable.insert( { loader::Symbol::Binding::Global, - loader::Symbol::SymbolType::Function, symbol, addr } + loader::Symbol::SymbolType::Function, symbol, addr.addr } ); } @@ -368,10 +368,10 @@ m5checkpoint(ThreadContext *tc, Tick delay, Tick period) } uint64_t -readfile(ThreadContext *tc, Addr vaddr, uint64_t len, uint64_t offset) +readfile(ThreadContext *tc, GuestAddr vaddr, uint64_t len, uint64_t offset) { DPRINTF(PseudoInst, "pseudo_inst::readfile(0x%x, 0x%x, 0x%x)\n", - vaddr, len, offset); + vaddr.addr, len, offset); const std::string &file = tc->getSystemPtr()->params().readfile; if (file.empty()) { @@ -404,17 +404,17 @@ readfile(ThreadContext *tc, Addr vaddr, uint64_t len, uint64_t offset) SETranslatingPortProxy se_proxy(tc); PortProxy &virt_proxy = FullSystem ? fs_proxy : se_proxy; - virt_proxy.writeBlob(vaddr, buf, result); + virt_proxy.writeBlob(vaddr.addr, buf, result); delete [] buf; return result; } uint64_t -writefile(ThreadContext *tc, Addr vaddr, uint64_t len, uint64_t offset, - Addr filename_addr) +writefile(ThreadContext *tc, GuestAddr vaddr, uint64_t len, uint64_t offset, + GuestAddr filename_addr) { DPRINTF(PseudoInst, "pseudo_inst::writefile(0x%x, 0x%x, 0x%x, 0x%x)\n", - vaddr, len, offset, filename_addr); + vaddr.addr, len, offset, filename_addr.addr); // copy out target filename std::string filename; @@ -422,7 +422,7 @@ writefile(ThreadContext *tc, Addr vaddr, uint64_t len, uint64_t offset, SETranslatingPortProxy se_proxy(tc); PortProxy &virt_proxy = FullSystem ? fs_proxy : se_proxy; - virt_proxy.readString(filename, filename_addr); + virt_proxy.readString(filename, filename_addr.addr); OutputStream *out; if (offset == 0) { @@ -448,7 +448,7 @@ writefile(ThreadContext *tc, Addr vaddr, uint64_t len, uint64_t offset, // copy out data and write to file char *buf = new char[len]; - virt_proxy.readBlob(vaddr, buf, len); + virt_proxy.readBlob(vaddr.addr, buf, len); os->write(buf, len); if (os->fail() || os->bad()) panic("Error while doing writefile!\n"); diff --git a/src/sim/pseudo_inst.hh b/src/sim/pseudo_inst.hh index ba15370c55..57b5ae23e6 100644 --- a/src/sim/pseudo_inst.hh +++ b/src/sim/pseudo_inst.hh @@ -64,18 +64,29 @@ decodeAddrOffset(Addr offset, uint8_t &func) func = bits(offset, 15, 8); } +struct GuestAddr +{ + uint64_t addr; +}; + +inline std::ostream& +operator<<(std::ostream& os, const GuestAddr addr) +{ + return os << addr.addr; +} + void arm(ThreadContext *tc); void quiesce(ThreadContext *tc); void quiesceSkip(ThreadContext *tc); void quiesceNs(ThreadContext *tc, uint64_t ns); void quiesceCycles(ThreadContext *tc, uint64_t cycles); uint64_t quiesceTime(ThreadContext *tc); -uint64_t readfile(ThreadContext *tc, Addr vaddr, uint64_t len, +uint64_t readfile(ThreadContext *tc, GuestAddr vaddr, uint64_t len, uint64_t offset); -uint64_t writefile(ThreadContext *tc, Addr vaddr, uint64_t len, - uint64_t offset, Addr filenameAddr); +uint64_t writefile(ThreadContext *tc, GuestAddr vaddr, uint64_t len, + uint64_t offset, GuestAddr filenameAddr); void loadsymbol(ThreadContext *xc); -void addsymbol(ThreadContext *tc, Addr addr, Addr symbolAddr); +void addsymbol(ThreadContext *tc, GuestAddr addr, GuestAddr symbolAddr); uint64_t initParam(ThreadContext *xc, uint64_t key_str1, uint64_t key_str2); uint64_t rpns(ThreadContext *tc); void wakeCPU(ThreadContext *tc, uint64_t cpuid); @@ -95,6 +106,7 @@ void m5Syscall(ThreadContext *tc); void togglesync(ThreadContext *tc); void triggerWorkloadEvent(ThreadContext *tc); + /** * Execute a decoded M5 pseudo instruction * diff --git a/src/sim/syscall_abi.hh b/src/sim/syscall_abi.hh index 90dbd9747b..136555ea37 100644 --- a/src/sim/syscall_abi.hh +++ b/src/sim/syscall_abi.hh @@ -32,6 +32,7 @@ #include "base/types.hh" #include "cpu/thread_context.hh" #include "sim/guest_abi.hh" +#include "sim/pseudo_inst.hh" #include "sim/syscall_return.hh" namespace gem5 @@ -78,19 +79,22 @@ struct GenericSyscallABI32 : public GenericSyscallABI namespace guest_abi { +using namespace pseudo_inst; + // For 64 bit systems, return syscall args directly. template struct Argument && - std::is_integral_v>> + (std::is_integral_v || std::is_same::value)>> { static Arg get(ThreadContext *tc, typename ABI::State &state) { panic_if(state >= ABI::ArgumentRegs.size(), "Ran out of syscall argument registers."); - return tc->getReg(ABI::ArgumentRegs[state++]); + auto arg = tc->getReg(ABI::ArgumentRegs[state++]); + return *reinterpret_cast(&arg); } }; From d358813a7a5dd2872b80bc71a752d30f5888ce22 Mon Sep 17 00:00:00 2001 From: Robert Hauser Date: Mon, 11 Mar 2024 15:28:23 +0000 Subject: [PATCH 2/9] arch-riscv: fix argument handling of syscalls in SE mode With the previously introduced struct wrapper GuestAddr, the asm tests fail. This patch substitutes implements SyscallABI32 similar to RegABI32, i.e., as a struct based on GenericSyscallABI32. Furthermore, a get function for arguments is implemented for wide arguments. It returns the lower 32 bits of a register. Change-Id: I233a67a5d5c15ab0d019a63bc57f1225288e33cc --- src/arch/riscv/SConscript | 1 + src/arch/riscv/se_workload.cc | 44 +++++++++++++++++++++++++++++++++++ src/arch/riscv/se_workload.hh | 22 +++++++++++++++++- 3 files changed, 66 insertions(+), 1 deletion(-) create mode 100644 src/arch/riscv/se_workload.cc diff --git a/src/arch/riscv/SConscript b/src/arch/riscv/SConscript index 78864523c7..2231a0ffa1 100644 --- a/src/arch/riscv/SConscript +++ b/src/arch/riscv/SConscript @@ -58,6 +58,7 @@ Source('pma_checker.cc', tags='riscv isa') Source('pmp.cc', tags='riscv isa') Source('reg_abi.cc', tags='riscv isa') Source('remote_gdb.cc', tags='riscv isa') +Source('se_workload.cc', tags='riscv isa') Source('tlb.cc', tags='riscv isa') Source('linux/se_workload.cc', tags='riscv isa') diff --git a/src/arch/riscv/se_workload.cc b/src/arch/riscv/se_workload.cc new file mode 100644 index 0000000000..108bea9d86 --- /dev/null +++ b/src/arch/riscv/se_workload.cc @@ -0,0 +1,44 @@ +/* + * Copyright 2020 Google Inc. + * Copyright (c) 2024 University of Rostock + * + * 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. + */ + + +#include + +namespace gem5 +{ + +namespace RiscvISA +{ + +const std::vector SEWorkload::SyscallABI32::ArgumentRegs = { + int_reg::A0, int_reg::A1, int_reg::A2, int_reg::A3, + int_reg::A4, int_reg::A5, int_reg::A6 +}; + +} // namespace RiscvISA +} // namespace gem5 diff --git a/src/arch/riscv/se_workload.hh b/src/arch/riscv/se_workload.hh index dd18a92905..8357ab5ac6 100644 --- a/src/arch/riscv/se_workload.hh +++ b/src/arch/riscv/se_workload.hh @@ -1,5 +1,6 @@ /* * Copyright 2020 Google Inc. + * Copyright (c) 2024 University of Rostock * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -61,7 +62,12 @@ class SEWorkload : public gem5::SEWorkload loader::Arch getArch() const override { return loader::Riscv64; } using SyscallABI64 = RegABI64; - using SyscallABI32 = RegABI32; + + struct SyscallABI32 : public GenericSyscallABI32 + { + static const std::vector ArgumentRegs; + }; + }; } // namespace RiscvISA @@ -69,6 +75,20 @@ class SEWorkload : public gem5::SEWorkload namespace guest_abi { +template +struct Argument && + std::is_integral_v && + ABI::template IsWideV>> +{ + static Arg + get(ThreadContext *tc, typename ABI::State &state) + { + return (Arg) bits(tc->getReg(ABI::ArgumentRegs[state++]), 31, 0); + } +}; + template <> struct Result { From 3d2d960f10805ff52512676fd76683da7c967c0c Mon Sep 17 00:00:00 2001 From: Robert Hauser Date: Mon, 11 Mar 2024 15:32:15 +0000 Subject: [PATCH 3/9] arch-riscv: fix return value of pseudo instruction Only the lower 32 bit of return values of pseudo instructions are stored (in a0). Therefore, the upper 32 bit are stored in a1 to enable a correct return value. Change-Id: Idf33c325033281fc191a9285eb5d34fd4965cde9 --- src/arch/riscv/isa/formats/m5ops.isa | 7 +++++-- src/arch/riscv/isa/operands.isa | 2 ++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/arch/riscv/isa/formats/m5ops.isa b/src/arch/riscv/isa/formats/m5ops.isa index 034a0dd2b5..ce2092cac3 100644 --- a/src/arch/riscv/isa/formats/m5ops.isa +++ b/src/arch/riscv/isa/formats/m5ops.isa @@ -1,5 +1,6 @@ // // Copyright (c) 2020 Barkhausen Institut +// Copyright (c) 2024 University of Rostock // All rights reserved // // The license below extends only to copyright in the software and shall @@ -40,10 +41,12 @@ def format M5Op() {{ uint64_t result; if (machInst.rv_type == RV32) { pseudo_inst::pseudoInst(xc->tcBase(), M5FUNC, result); + a0 = bits(result, 31, 0); + a1 = bits(result, 63, 32); } else { pseudo_inst::pseudoInst(xc->tcBase(), M5FUNC, result); - } - a0 = rvSext(result)''', + a0 = rvSext(result); + }''', ['IsNonSpeculative', 'IsSerializeAfter']) header_output = BasicDeclare.subst(iop) decoder_output = BasicConstructor.subst(iop) diff --git a/src/arch/riscv/isa/operands.isa b/src/arch/riscv/isa/operands.isa index 3a16e0994c..de36d902b1 100644 --- a/src/arch/riscv/isa/operands.isa +++ b/src/arch/riscv/isa/operands.isa @@ -3,6 +3,7 @@ // Copyright (c) 2015 RISC-V Foundation // Copyright (c) 2016 The University of Virginia // Copyright (c) 2020 Barkhausen Institut +// Copyright (c) 2024 University of Rostock // All rights reserved. // // Redistribution and use in source and binary forms, with or without @@ -71,6 +72,7 @@ def operands {{ 'sp': IntReg('ud', 'StackPointerReg', 'IsInteger', 2), 'a0': IntReg('ud', '10', 'IsInteger', 1), + 'a1': IntReg('ud', '11', 'IsInteger', 2), 'Fd': FloatRegOp('df', 'FD', 'IsFloating', 1), 'Fd_bits': FloatRegOp('ud', 'FD', 'IsFloating', 1), From bf63ec953a4ef29018b186e9154157e6270b0f0f Mon Sep 17 00:00:00 2001 From: Robert Hauser Date: Sat, 16 Mar 2024 09:04:36 +0000 Subject: [PATCH 4/9] arch-riscv: revert SyscallABI32 changes Change-Id: I07c3e4aee06a6f5576d4a3488a29673fdb0a09bf --- src/arch/riscv/SConscript | 1 - src/arch/riscv/se_workload.cc | 44 ----------------------------------- src/arch/riscv/se_workload.hh | 22 +----------------- 3 files changed, 1 insertion(+), 66 deletions(-) delete mode 100644 src/arch/riscv/se_workload.cc diff --git a/src/arch/riscv/SConscript b/src/arch/riscv/SConscript index 2231a0ffa1..78864523c7 100644 --- a/src/arch/riscv/SConscript +++ b/src/arch/riscv/SConscript @@ -58,7 +58,6 @@ Source('pma_checker.cc', tags='riscv isa') Source('pmp.cc', tags='riscv isa') Source('reg_abi.cc', tags='riscv isa') Source('remote_gdb.cc', tags='riscv isa') -Source('se_workload.cc', tags='riscv isa') Source('tlb.cc', tags='riscv isa') Source('linux/se_workload.cc', tags='riscv isa') diff --git a/src/arch/riscv/se_workload.cc b/src/arch/riscv/se_workload.cc deleted file mode 100644 index 108bea9d86..0000000000 --- a/src/arch/riscv/se_workload.cc +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright 2020 Google Inc. - * Copyright (c) 2024 University of Rostock - * - * 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. - */ - - -#include - -namespace gem5 -{ - -namespace RiscvISA -{ - -const std::vector SEWorkload::SyscallABI32::ArgumentRegs = { - int_reg::A0, int_reg::A1, int_reg::A2, int_reg::A3, - int_reg::A4, int_reg::A5, int_reg::A6 -}; - -} // namespace RiscvISA -} // namespace gem5 diff --git a/src/arch/riscv/se_workload.hh b/src/arch/riscv/se_workload.hh index 8357ab5ac6..dd18a92905 100644 --- a/src/arch/riscv/se_workload.hh +++ b/src/arch/riscv/se_workload.hh @@ -1,6 +1,5 @@ /* * Copyright 2020 Google Inc. - * Copyright (c) 2024 University of Rostock * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -62,12 +61,7 @@ class SEWorkload : public gem5::SEWorkload loader::Arch getArch() const override { return loader::Riscv64; } using SyscallABI64 = RegABI64; - - struct SyscallABI32 : public GenericSyscallABI32 - { - static const std::vector ArgumentRegs; - }; - + using SyscallABI32 = RegABI32; }; } // namespace RiscvISA @@ -75,20 +69,6 @@ class SEWorkload : public gem5::SEWorkload namespace guest_abi { -template -struct Argument && - std::is_integral_v && - ABI::template IsWideV>> -{ - static Arg - get(ThreadContext *tc, typename ABI::State &state) - { - return (Arg) bits(tc->getReg(ABI::ArgumentRegs[state++]), 31, 0); - } -}; - template <> struct Result { From e3fd3d777592fa8c7750d3ed76492fe3b0e05355 Mon Sep 17 00:00:00 2001 From: Robert Hauser Date: Sat, 16 Mar 2024 09:04:51 +0000 Subject: [PATCH 5/9] arch-arm,sim: fix argument handling for GuestAddr Change-Id: If7bc759ee752333b717b61a6c577cf2d5846f4db --- src/arch/arm/reg_abi.hh | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/src/arch/arm/reg_abi.hh b/src/arch/arm/reg_abi.hh index 6bdc8b36c1..ca349283e2 100644 --- a/src/arch/arm/reg_abi.hh +++ b/src/arch/arm/reg_abi.hh @@ -61,7 +61,7 @@ template struct Argument && - (std::is_integral_v || std::is_same::value) && + std::is_integral_v && ABI::template IsWideV>> { static Arg @@ -74,8 +74,22 @@ struct Argument(&merge); + return (Arg) ABI::mergeRegs(tc, low, high); + } +}; + +template <> +struct Argument +{ + using ABI = ArmISA::RegABI32; + + static GuestAddr + get(ThreadContext *tc, typename ABI::State &state) + { + panic_if(state + 1 >= ABI::ArgumentRegs.size(), + "Ran out of syscall argument registers."); + auto arg = bits(tc->getReg(ABI::ArgumentRegs[state++]), 31, 0); + return *reinterpret_cast(&arg); } }; From f7da70bd10f76090961051e85c7ed37ad26ac2ce Mon Sep 17 00:00:00 2001 From: Robert Hauser Date: Sat, 16 Mar 2024 09:05:30 +0000 Subject: [PATCH 6/9] arch-riscv,sim: simplify templates for GuestAddr Simplify templates in argument handling for ABI=RicsvISA::RegABI32 and Arg=GuestAddr. Change-Id: I6af2e6fe1b77b1367136a8e8621053069bf3c3f0 --- src/arch/riscv/reg_abi.hh | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/src/arch/riscv/reg_abi.hh b/src/arch/riscv/reg_abi.hh index 6f1c8cbc6c..0869e0f4a6 100644 --- a/src/arch/riscv/reg_abi.hh +++ b/src/arch/riscv/reg_abi.hh @@ -77,22 +77,20 @@ struct Argument -struct Argument && - std::is_same::value && - ABI::template IsWideV>> +// This method will be used for RV32 pointers. +template <> +struct Argument { - static Arg + using ABI = RiscvISA::RegABI32; + + static GuestAddr get(ThreadContext *tc, typename ABI::State &state) { panic_if(state >= ABI::ArgumentRegs.size(), "Ran out of syscall argument registers."); auto arg = bits(tc->getReg(ABI::ArgumentRegs[state++]), 31, 0); - return *reinterpret_cast(&arg); + return *reinterpret_cast(&arg); } }; From 0fc08acf92e0d911bf7e264609ffeccdc77fc044 Mon Sep 17 00:00:00 2001 From: Robert Hauser Date: Sat, 16 Mar 2024 09:07:38 +0000 Subject: [PATCH 7/9] sim: add whitespace for correct coding style This commit adds two additional whitespaces in the definition of GuestAddr as well as in the operator << overload. Change-Id: Ifb371a09b378fcf4862a768f113b5963b45bd167 --- src/sim/pseudo_inst.hh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sim/pseudo_inst.hh b/src/sim/pseudo_inst.hh index 57b5ae23e6..6eac340989 100644 --- a/src/sim/pseudo_inst.hh +++ b/src/sim/pseudo_inst.hh @@ -66,13 +66,13 @@ decodeAddrOffset(Addr offset, uint8_t &func) struct GuestAddr { - uint64_t addr; + uint64_t addr; }; inline std::ostream& operator<<(std::ostream& os, const GuestAddr addr) { - return os << addr.addr; + return os << addr.addr; } void arm(ThreadContext *tc); From 0b45be7720c1a9b9317930469232619fbf835c75 Mon Sep 17 00:00:00 2001 From: Robert Hauser Date: Sat, 16 Mar 2024 09:09:57 +0000 Subject: [PATCH 8/9] arch-riscv: define size_t and off_t for 32 bit size_t is defined as 32 bit unsigned integer and off_t as 64 bit signed integer for 32 bit Linux. Change-Id: Icaa26dfc75600df2450d7df45b6ba4e3c1a1546f --- src/arch/riscv/linux/linux.hh | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/arch/riscv/linux/linux.hh b/src/arch/riscv/linux/linux.hh index de8bccc85e..997eb6af4c 100644 --- a/src/arch/riscv/linux/linux.hh +++ b/src/arch/riscv/linux/linux.hh @@ -289,6 +289,10 @@ class RiscvLinux32 : public RiscvLinux, public OpenFlagTable // Currently time_t in glibc for riscv32 is 32-bits, but will be changed. typedef int64_t time_t; + // Linux types for RV32 + typedef uint32_t size_t; + typedef int64_t off_t; + /// Limit struct for getrlimit/setrlimit. struct rlimit { From f9a9e5000781a441038201dd85ca17e16b97f036 Mon Sep 17 00:00:00 2001 From: Robert Hauser Date: Sat, 30 Mar 2024 20:09:18 +0000 Subject: [PATCH 9/9] sim: adding constructor to GuestAddr A constructor is added to GuestAddr as suggested in the pull request feedback. This allows a cast conversion from uint64_t GuestAddr. Hence, the casting from uint64_t to GuestAddr by reinterpret_cast is removed (was added in a previous commit). using namespace pseudo_inst is also removed as requested. Comments are added to GuestAddr. Change-Id: Ib76de2bff285f4e53ad03361969c27f7bb2dfe9e --- src/arch/arm/reg_abi.hh | 12 +++++------- src/arch/arm/semihosting.hh | 17 +++++++---------- src/arch/riscv/reg_abi.hh | 9 ++++----- src/arch/sparc/pseudo_inst_abi.hh | 11 +++++------ src/arch/x86/pseudo_inst_abi.hh | 11 +++++------ src/sim/guest_abi/layout.hh | 3 +-- src/sim/pseudo_inst.hh | 10 +++++++++- src/sim/syscall_abi.hh | 8 +++----- 8 files changed, 39 insertions(+), 42 deletions(-) diff --git a/src/arch/arm/reg_abi.hh b/src/arch/arm/reg_abi.hh index ca349283e2..34fe44c16d 100644 --- a/src/arch/arm/reg_abi.hh +++ b/src/arch/arm/reg_abi.hh @@ -55,8 +55,6 @@ struct RegABI64 : public GenericSyscallABI64 namespace guest_abi { -using namespace pseudo_inst; - template struct Argument -struct Argument +struct Argument { using ABI = ArmISA::RegABI32; + using Arg = pseudo_inst::GuestAddr; - static GuestAddr + static Arg get(ThreadContext *tc, typename ABI::State &state) { panic_if(state + 1 >= ABI::ArgumentRegs.size(), "Ran out of syscall argument registers."); - auto arg = bits(tc->getReg(ABI::ArgumentRegs[state++]), 31, 0); - return *reinterpret_cast(&arg); + return (Arg)bits(tc->getReg(ABI::ArgumentRegs[state++]), 31, 0); } }; diff --git a/src/arch/arm/semihosting.hh b/src/arch/arm/semihosting.hh index 221c0ce3cb..7242581eb6 100644 --- a/src/arch/arm/semihosting.hh +++ b/src/arch/arm/semihosting.hh @@ -603,36 +603,33 @@ std::ostream &operator << ( namespace guest_abi { -using namespace pseudo_inst; - template struct Argument || std::is_same::value)>> + (std::is_integral_v || + std::is_same::value)>> { static Arg get(ThreadContext *tc, ArmSemihosting::Abi64::State &state) { - auto arg = state.get(tc); - return *reinterpret_cast(&arg); + return (Arg)state.get(tc); } }; template struct Argument || std::is_same::value)>> + (std::is_integral_v || + std::is_same::value)>> { static Arg get(ThreadContext *tc, ArmSemihosting::Abi32::State &state) { if (std::is_signed_v) { - auto arg = sext<32>(state.get(tc)); - return *reinterpret_cast(&arg); + return (Arg)sext<32>(state.get(tc)); } else { - auto arg = state.get(tc); - return *reinterpret_cast(&arg); + return (Arg)state.get(tc); } } }; diff --git a/src/arch/riscv/reg_abi.hh b/src/arch/riscv/reg_abi.hh index 0869e0f4a6..383e9df266 100644 --- a/src/arch/riscv/reg_abi.hh +++ b/src/arch/riscv/reg_abi.hh @@ -54,7 +54,6 @@ struct RegABI32 : public GenericSyscallABI32 namespace guest_abi { -using namespace pseudo_inst; // This method will be used if the size of argument type of function is // greater than 4 byte for Riscv 32. @@ -79,18 +78,18 @@ struct Argument -struct Argument +struct Argument { using ABI = RiscvISA::RegABI32; + using Arg = pseudo_inst::GuestAddr; - static GuestAddr + static Arg get(ThreadContext *tc, typename ABI::State &state) { panic_if(state >= ABI::ArgumentRegs.size(), "Ran out of syscall argument registers."); - auto arg = bits(tc->getReg(ABI::ArgumentRegs[state++]), 31, 0); - return *reinterpret_cast(&arg); + return (Arg)bits(tc->getReg(ABI::ArgumentRegs[state++]), 31, 0); } }; diff --git a/src/arch/sparc/pseudo_inst_abi.hh b/src/arch/sparc/pseudo_inst_abi.hh index 58b64d805a..569cfb8da8 100644 --- a/src/arch/sparc/pseudo_inst_abi.hh +++ b/src/arch/sparc/pseudo_inst_abi.hh @@ -44,8 +44,6 @@ struct SparcPseudoInstABI namespace guest_abi { -using namespace pseudo_inst; - template struct Result { @@ -71,14 +69,15 @@ struct Argument }; template <> -struct Argument +struct Argument { - static GuestAddr + using Arg = pseudo_inst::GuestAddr; + + static Arg get(ThreadContext *tc, SparcPseudoInstABI::State &state) { panic_if(state >= 6, "Too many psuedo inst arguments."); - auto arg = tc->getReg(SparcISA::int_reg::o(state++)); - return *reinterpret_cast(&arg); + return (Arg)tc->getReg(SparcISA::int_reg::o(state++)); } }; diff --git a/src/arch/x86/pseudo_inst_abi.hh b/src/arch/x86/pseudo_inst_abi.hh index 0c098f16e2..bfedb7a8cb 100644 --- a/src/arch/x86/pseudo_inst_abi.hh +++ b/src/arch/x86/pseudo_inst_abi.hh @@ -50,8 +50,6 @@ struct X86PseudoInstABI namespace guest_abi { -using namespace pseudo_inst; - template struct Result { @@ -88,9 +86,11 @@ struct Argument }; template <> -struct Argument +struct Argument { - static GuestAddr + using Arg = pseudo_inst::GuestAddr; + + static Arg get(ThreadContext *tc, X86PseudoInstABI::State &state) { // The first 6 integer arguments are passed in registers, the rest @@ -105,8 +105,7 @@ struct Argument int_reg::Rcx, int_reg::R8, int_reg::R9 }; - auto arg = tc->getReg(int_reg_map[state++]); - return *reinterpret_cast(&arg); + return (Arg)tc->getReg(int_reg_map[state++]); } }; diff --git a/src/sim/guest_abi/layout.hh b/src/sim/guest_abi/layout.hh index 3ea01c168c..9873a61215 100644 --- a/src/sim/guest_abi/layout.hh +++ b/src/sim/guest_abi/layout.hh @@ -169,8 +169,7 @@ template static Arg getArgument(ThreadContext *tc, typename ABI::State &state) { - auto arg = Argument::get(tc, state); - return *reinterpret_cast(&arg); + return (Arg)Argument::get(tc, state); } } // namespace guest_abi diff --git a/src/sim/pseudo_inst.hh b/src/sim/pseudo_inst.hh index 6eac340989..2d7b27715b 100644 --- a/src/sim/pseudo_inst.hh +++ b/src/sim/pseudo_inst.hh @@ -64,9 +64,17 @@ decodeAddrOffset(Addr offset, uint8_t &func) func = bits(offset, 15, 8); } +/** + * This struct wrapper for Addr enables m5ops for systems with 32 bit pointer, + * since it allows to distinguish between address arguments and native C++ + * types. GuestAddr is only a temporary solution and will likely replaced in + * the future. +*/ struct GuestAddr { - uint64_t addr; + Addr addr; + /** Constructor is necessary to cast from uint64_t to GuestAddr. */ + GuestAddr(Addr _addr) : addr(_addr) {} }; inline std::ostream& diff --git a/src/sim/syscall_abi.hh b/src/sim/syscall_abi.hh index 136555ea37..c50b1de16e 100644 --- a/src/sim/syscall_abi.hh +++ b/src/sim/syscall_abi.hh @@ -79,22 +79,20 @@ struct GenericSyscallABI32 : public GenericSyscallABI namespace guest_abi { -using namespace pseudo_inst; - // For 64 bit systems, return syscall args directly. template struct Argument && - (std::is_integral_v || std::is_same::value)>> + (std::is_integral_v || + std::is_same::value)>> { static Arg get(ThreadContext *tc, typename ABI::State &state) { panic_if(state >= ABI::ArgumentRegs.size(), "Ran out of syscall argument registers."); - auto arg = tc->getReg(ABI::ArgumentRegs[state++]); - return *reinterpret_cast(&arg); + return (Arg)tc->getReg(ABI::ArgumentRegs[state++]); } };