diff options
author | Andreas Sandberg <andreas.sandberg@arm.com> | 2018-02-13 18:03:32 +0000 |
---|---|---|
committer | Andreas Sandberg <andreas.sandberg@arm.com> | 2018-02-19 14:24:46 +0000 |
commit | 3b25b7cc64035b181d139b90abb692f5eda935a5 (patch) | |
tree | 3d7ab1c3bea654735e0be6569062700ad7265887 | |
parent | 7b96fc2456d71d0df2700384ab44c1ed01be2f03 (diff) | |
download | gem5-3b25b7cc64035b181d139b90abb692f5eda935a5.tar.xz |
arch-arm: Add support for secure state in semihosting
The semihosting component currently issues non-secure memory accesses
using the standard port proxy. This doesn't work when the guest is
running in secure state.
Change-Id: Id34b142cfcd9d77b455c040ae7f7397c29aebbc6
Signed-off-by: Andreas Sandberg <andreas.sandberg@arm.com>
Reviewed-by: Jack Travaglini <giacomo.travaglini@arm.com>
Reviewed-on: https://gem5-review.googlesource.com/8365
Reviewed-by: Giacomo Travaglini <giacomo.travaglini@arm.com>
-rw-r--r-- | src/arch/arm/semihosting.cc | 39 | ||||
-rw-r--r-- | src/arch/arm/semihosting.hh | 4 |
2 files changed, 32 insertions, 11 deletions
diff --git a/src/arch/arm/semihosting.cc b/src/arch/arm/semihosting.cc index 98b50f468..89e1b2e7d 100644 --- a/src/arch/arm/semihosting.cc +++ b/src/arch/arm/semihosting.cc @@ -157,7 +157,7 @@ ArmSemihosting::call64(ThreadContext *tc, uint32_t op, uint64_t param) } std::vector<uint64_t> argv(call->argc64 + 1); - PortProxy &proxy = tc->getPhysProxy(); + PortProxy &proxy = physProxy(tc); ByteOrder endian = ArmISA::byteOrder(tc); DPRINTF(Semihosting, "Semihosting call64: %s(0x%x)\n", call->name, param); @@ -192,7 +192,7 @@ ArmSemihosting::call32(ThreadContext *tc, uint32_t op, uint32_t param) } std::vector<uint64_t> argv(call->argc32 + 1); - PortProxy &proxy = tc->getPhysProxy(); + PortProxy &proxy = physProxy(tc); ByteOrder endian = ArmISA::byteOrder(tc); DPRINTF(Semihosting, "Semihosting call32: %s(0x%x)\n", call->name, param); @@ -236,13 +236,30 @@ ArmSemihosting::unserialize(CheckpointIn &cp) files[i] = FileBase::create(*this, cp, csprintf("file%i", i)); } +PortProxy & +ArmSemihosting::physProxy(ThreadContext *tc) +{ + if (ArmISA::inSecureState(tc)) { + if (!physProxyS) { + System *sys = tc->getSystemPtr(); + physProxyS.reset(new SecurePortProxy( + sys->getSystemPort(), + sys->cacheLineSize())); + } + return *physProxyS; + } else { + return tc->getPhysProxy(); + } +} + + std::string ArmSemihosting::readString(ThreadContext *tc, Addr ptr, size_t len) { std::vector<char> buf(len + 1); buf[len] = '\0'; - tc->getPhysProxy().readBlob(ptr, (uint8_t *)buf.data(), len); + physProxy(tc).readBlob(ptr, (uint8_t *)buf.data(), len); return std::string(buf.data()); } @@ -302,7 +319,7 @@ ArmSemihosting::RetErrno ArmSemihosting::callWriteC(ThreadContext *tc, bool aarch64, std::vector<uint64_t> &argv) { - const char c = tc->getPhysProxy().read<char>(argv[0]); + const char c = physProxy(tc).read<char>(argv[0]); DPRINTF(Semihosting, "Semihosting SYS_WRITEC('%c')\n", c); std::cout.put(c); @@ -315,7 +332,7 @@ ArmSemihosting::callWrite0(ThreadContext *tc, bool aarch64, std::vector<uint64_t> &argv) { DPRINTF(Semihosting, "Semihosting SYS_WRITE0(...)\n"); - PortProxy &proxy = tc->getPhysProxy(); + PortProxy &proxy = physProxy(tc); for (Addr addr = (Addr)argv[0]; ; ++addr) { char data = proxy.read<char>(addr); if (data == 0) @@ -335,7 +352,7 @@ ArmSemihosting::callWrite(ThreadContext *tc, bool aarch64, return RetErrno(argv[3], EBADF); std::vector<uint8_t> buffer(argv[3]); - tc->getPhysProxy().readBlob(argv[2], buffer.data(), buffer.size()); + physProxy(tc).readBlob(argv[2], buffer.data(), buffer.size()); int64_t ret = files[argv[1]]->write(buffer.data(), buffer.size()); if (ret < 0) { @@ -362,7 +379,7 @@ ArmSemihosting::callRead(ThreadContext *tc, bool aarch64, } else { panic_if(ret > buffer.size(), "Read longer than buffer size."); - tc->getPhysProxy().writeBlob(argv[2], buffer.data(), ret); + physProxy(tc).writeBlob(argv[2], buffer.data(), ret); // Return the number of bytes not written return retOK(argv[3] - ret); @@ -449,7 +466,7 @@ ArmSemihosting::callTmpNam(ThreadContext *tc, bool aarch64, if (path_len >= max_len) return retError(ENOSPC); - tc->getPhysProxy().writeBlob( + physProxy(tc).writeBlob( guest_buf, (const uint8_t *)path, path_len + 1); return retOK(0); } @@ -519,7 +536,7 @@ ArmSemihosting::callGetCmdLine(ThreadContext *tc, bool aarch64, std::vector<uint64_t> &argv) { if (cmdLine.size() + 1 < argv[2]) { - PortProxy &proxy = tc->getPhysProxy(); + PortProxy &proxy = physProxy(tc); ByteOrder endian = ArmISA::byteOrder(tc); proxy.writeBlob( (Addr)argv[1], @@ -576,7 +593,7 @@ ArmSemihosting::callHeapInfo(ThreadContext *tc, bool aarch64, heap_base, heap_limit, stack_base, stack_limit); Addr base = argv[1]; - PortProxy &proxy = tc->getPhysProxy(); + PortProxy &proxy = physProxy(tc); ByteOrder endian = ArmISA::byteOrder(tc); if (aarch64) { proxy.writeHtoG<uint64_t>(base + 0 * 8, heap_base, endian); @@ -631,7 +648,7 @@ ArmSemihosting::RetErrno ArmSemihosting::callElapsed(ThreadContext *tc, bool aarch64, std::vector<uint64_t> &argv) { - PortProxy &proxy = tc->getPhysProxy(); + PortProxy &proxy = physProxy(tc); ByteOrder endian = ArmISA::byteOrder(tc); const uint64_t tick = semiTick(curTick()); diff --git a/src/arch/arm/semihosting.hh b/src/arch/arm/semihosting.hh index a4aa845a3..14c5f9d2d 100644 --- a/src/arch/arm/semihosting.hh +++ b/src/arch/arm/semihosting.hh @@ -48,6 +48,7 @@ #include "sim/sim_object.hh" struct ArmSemihostingParams; +class PortProxy; class SerialDevice; class ThreadContext; @@ -253,8 +254,11 @@ class ArmSemihosting : public SimObject return tick >> tickShift; } void semiExit(uint64_t code, uint64_t subcode); + PortProxy &physProxy(ThreadContext *tc); std::string readString(ThreadContext *tc, Addr ptr, size_t len); + std::unique_ptr<PortProxy> physProxyS; + private: typedef std::pair<uint64_t, SemiErrno> RetErrno; static constexpr RetErrno retError(SemiErrno e) { |