From: Gabe Black Date: Wed, 26 Feb 2020 23:49:39 +0000 (-0800) Subject: arm: Add a gem5 specific pseudo op semihosting call. X-Git-Tag: v20.0.0.0~240 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=19bba883547c139d5ccd2d1abeaf65ceea18e2a7;p=gem5.git arm: Add a gem5 specific pseudo op semihosting call. This is in the range of call numbers set aside for extensions. When called, it will extract the function to use from the first argument slot. Then it calls the pseudoInst dispatching function using an ABI which drops the return value (which is handled by semihosting itself) and which extracts arguments from the remaining slots in the param structure. This makes gem5 pseudo ops available on CPU models which support semihosting but not instruction based or address based "magic" operations, aka hypercalls. This includes the fast model CPUs. Change-Id: Ic4817f2b1e6aad7784af77a1a494cf614d4d4c6c Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/25950 Reviewed-by: Giacomo Travaglini Maintainer: Giacomo Travaglini Tested-by: kokoro --- diff --git a/src/arch/arm/semihosting.cc b/src/arch/arm/semihosting.cc index 230ded1b2..7b7592f92 100644 --- a/src/arch/arm/semihosting.cc +++ b/src/arch/arm/semihosting.cc @@ -48,6 +48,7 @@ #include "mem/secure_port_proxy.hh" #include "params/ArmSemihosting.hh" #include "sim/byteswap.hh" +#include "sim/pseudo_inst.hh" #include "sim/sim_exit.hh" #include "sim/system.hh" @@ -83,6 +84,9 @@ const std::map ArmSemihosting::calls{ { SYS_ELAPSED, { "SYS_ELAPSED", &ArmSemihosting::callElapsed32, &ArmSemihosting::callElapsed64 } }, { SYS_TICKFREQ, { "SYS_TICKFREQ", &ArmSemihosting::callTickFreq } }, + { SYS_GEM5_PSEUDO_OP, + { "SYS_GEM5_PSEUDO_OP", &ArmSemihosting::callGem5PseudoOp32, + &ArmSemihosting::callGem5PseudoOp64 } }, }; const std::vector ArmSemihosting::fmodes{ @@ -653,6 +657,87 @@ ArmSemihosting::callTickFreq(ThreadContext *tc) return retOK(semiTick(SimClock::Frequency)); } + +struct SemiPseudoAbi32 : public ArmSemihosting::Abi32 +{ + class State : public ArmSemihosting::Abi32::State + { + public: + State(const ThreadContext *tc) : ArmSemihosting::Abi32::State(tc) + { + // Use getAddr() to skip the func number in the first slot. + getAddr(); + } + }; +}; + +struct SemiPseudoAbi64 : public ArmSemihosting::Abi64 +{ + class State : public ArmSemihosting::Abi64::State + { + public: + State(const ThreadContext *tc) : ArmSemihosting::Abi64::State(tc) + { + // Use getAddr() to skip the func number in the first slot. + getAddr(); + } + }; +}; + +namespace GuestABI +{ + +// Ignore return values since those will be handled by semihosting. +template +struct Result +{ + static void store(ThreadContext *tc, const T &ret) {} +}; +template +struct Result +{ + static void store(ThreadContext *tc, const T &ret) {} +}; + +// Handle arguments the same as for semihosting operations. Skipping the first +// slot is handled internally by the State type. +template +struct Argument : + public Argument +{}; +template +struct Argument : + public Argument +{}; + +} // namespace GuestABI + +ArmSemihosting::RetErrno +ArmSemihosting::callGem5PseudoOp32(ThreadContext *tc, uint32_t encoded_func) +{ + uint8_t func; + PseudoInst::decodeAddrOffset(encoded_func, func); + + uint64_t ret; + if (PseudoInst::pseudoInst(tc, func, ret)) + return retOK(ret); + else + return retError(EINVAL); +} + +ArmSemihosting::RetErrno +ArmSemihosting::callGem5PseudoOp64(ThreadContext *tc, uint64_t encoded_func) +{ + uint8_t func; + PseudoInst::decodeAddrOffset(encoded_func, func); + + uint64_t ret; + if (PseudoInst::pseudoInst(tc, func, ret)) + return retOK(ret); + else + return retError(EINVAL); +} + FILE * ArmSemihosting::getSTDIO(const char *stream_name, const std::string &name, const char *mode) diff --git a/src/arch/arm/semihosting.hh b/src/arch/arm/semihosting.hh index 58843496c..e255d201b 100644 --- a/src/arch/arm/semihosting.hh +++ b/src/arch/arm/semihosting.hh @@ -208,7 +208,9 @@ class ArmSemihosting : public SimObject SYS_ELAPSED = 0x30, SYS_TICKFREQ = 0x31, - MaxStandardOp = 0xFF + MaxStandardOp = 0xFF, + + SYS_GEM5_PSEUDO_OP = 0x100 }; ArmSemihosting(const ArmSemihostingParams *p); @@ -547,6 +549,9 @@ class ArmSemihosting : public SimObject RetErrno callElapsed64(ThreadContext *tc, InPlaceArg ticks); RetErrno callTickFreq(ThreadContext *tc); + RetErrno callGem5PseudoOp32(ThreadContext *tc, uint32_t encoded_func); + RetErrno callGem5PseudoOp64(ThreadContext *tc, uint64_t encoded_func); + template void unrecognizedCall(ThreadContext *tc, const char *format, uint64_t op)