gem5 v24.0.0.0
Loading...
Searching...
No Matches
semihosting.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2018, 2019 ARM Limited
3 * All rights reserved
4 *
5 * The license below extends only to copyright in the software and shall
6 * not be construed as granting a license to any other intellectual
7 * property including but not limited to intellectual property relating
8 * to a hardware implementation of the functionality of the software
9 * licensed hereunder. You may use the software subject to the license
10 * terms below provided that you ensure that this notice is replicated
11 * unmodified and in its entirety in all distributions of the software,
12 * modified or unmodified, in source code or in binary form.
13 *
14 * Redistribution and use in source and binary forms, with or without
15 * modification, are permitted provided that the following conditions are
16 * met: redistributions of source code must retain the above copyright
17 * notice, this list of conditions and the following disclaimer;
18 * redistributions in binary form must reproduce the above copyright
19 * notice, this list of conditions and the following disclaimer in the
20 * documentation and/or other materials provided with the distribution;
21 * neither the name of the copyright holders nor the names of its
22 * contributors may be used to endorse or promote products derived from
23 * this software without specific prior written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
28 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
29 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
30 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
31 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
35 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 */
37
39
40#include <unistd.h>
41
42#include <cerrno>
43#include <cstdio>
44
45#include "arch/riscv/isa.hh"
47#include "base/logging.hh"
48#include "base/output.hh"
49#include "base/time.hh"
50#include "cpu/exec_context.hh"
51#include "debug/Semihosting.hh"
52#include "dev/serial/serial.hh"
53#include "mem/physical.hh"
56#include "params/RiscvSemihosting.hh"
57#include "pcstate.hh"
58#include "sim/byteswap.hh"
59#include "sim/full_system.hh"
60#include "sim/pseudo_inst.hh"
61#include "sim/system.hh"
62
63namespace gem5
64{
65
66const std::map<uint32_t, RiscvSemihosting::SemiCall> RiscvSemihosting::calls{
67 {SYS_OPEN, {"SYS_OPEN", &RiscvSemihosting::callOpen}},
68 {SYS_CLOSE, {"SYS_CLOSE", &RiscvSemihosting::callClose}},
69 {SYS_WRITEC, {"SYS_WRITEC", &RiscvSemihosting::callWriteC}},
70 {SYS_WRITE0, {"SYS_WRITE0", &RiscvSemihosting::callWrite0}},
71 {SYS_WRITE, {"SYS_WRITE", &RiscvSemihosting::callWrite}},
72 {SYS_READ, {"SYS_READ", &RiscvSemihosting::callRead}},
73 {SYS_READC, {"SYS_READC", &RiscvSemihosting::callReadC}},
74 {SYS_ISERROR, {"SYS_ISERROR", &RiscvSemihosting::callIsError}},
75 {SYS_ISTTY, {"SYS_ISTTY", &RiscvSemihosting::callIsTTY}},
76 {SYS_SEEK, {"SYS_SEEK", &RiscvSemihosting::callSeek}},
77 {SYS_FLEN, {"SYS_FLEN", &RiscvSemihosting::callFLen}},
78 {SYS_TMPNAM, {"SYS_TMPNAM", &RiscvSemihosting::callTmpNam}},
79 {SYS_REMOVE, {"SYS_REMOVE", &RiscvSemihosting::callRemove}},
80 {SYS_RENAME, {"SYS_RENAME", &RiscvSemihosting::callRename}},
81 {SYS_CLOCK, {"SYS_CLOCK", &RiscvSemihosting::callClock}},
82 {SYS_TIME, {"SYS_TIME", &RiscvSemihosting::callTime}},
83 {SYS_SYSTEM, {"SYS_SYSTEM", &RiscvSemihosting::callSystem}},
84 {SYS_ERRNO, {"SYS_ERRNO", &RiscvSemihosting::callErrno}},
85 {SYS_GET_CMDLINE,
86 {"SYS_GET_CMDLINE", &RiscvSemihosting::callGetCmdLine}},
87 {SYS_HEAPINFO, {"SYS_HEAPINFO", &RiscvSemihosting::callHeapInfo32,
89
90 {SYS_EXIT, {"SYS_EXIT", &RiscvSemihosting::callExit32,
92 {SYS_EXIT_EXTENDED,
93 {"SYS_EXIT_EXTENDED", &RiscvSemihosting::callExitExtended}},
94
95 {SYS_ELAPSED, {"SYS_ELAPSED", &RiscvSemihosting::callElapsed32,
97 {SYS_TICKFREQ, {"SYS_TICKFREQ", &RiscvSemihosting::callTickFreq}},
98};
99
101RiscvSemihosting(const RiscvSemihostingParams &p) : BaseSemihosting(p)
102{}
103
104bool
106{
108 auto it = calls.find(op);
109 if (it == calls.end()) {
110 unrecognizedCall<Abi64>(tc, "Unknown semihosting call: op = 0x%x", op);
111 return false;
112 }
113 const SemiCall &call = it->second;
114
115 DPRINTF(Semihosting, "Semihosting call64: %s\n", call.dump64(tc));
116 auto err = call.call64(this, tc);
117 semiErrno = err.second;
118 DPRINTF(Semihosting, "\t ->: 0x%x, %i\n", err.first, err.second);
119
120 return true;
121}
122
123bool
125{
127 auto it = calls.find(op);
128 if (it == calls.end()) {
130 tc, "Unknown aarch32 semihosting call: op = 0x%x", op);
131 return false;
132 }
133 const SemiCall &call = it->second;
134
135 DPRINTF(Semihosting, "Semihosting call32: %s\n", call.dump32(tc));
136 auto err = call.call32(this, tc);
137 semiErrno = err.second;
138 DPRINTF(Semihosting, "\t ->: 0x%x, %i\n", err.first, err.second);
139
140 return true;
141}
142
143bool
145{
146 auto isa = dynamic_cast<RiscvISA::ISA *>(tc->getIsaPtr());
147 panic_if(!isa, "Cannot derive rv_type from non-riscv isa");
148 return isa->rvType() == enums::RV32 ? call32(tc) : call64(tc);
149}
150
151PortProxy &
153{
154 static std::unique_ptr<PortProxy> port_proxy([=]() {
155 return FullSystem ? new TranslatingPortProxy(tc) :
157 }());
158 return *port_proxy;
159}
160
161bool
163{
164 // Check if the surrounding bytes match the semihosting magic sequence.
165 PortProxy& proxy = portProxyImpl(xc->tcBase());
166 Addr PrevInstAddr = xc->pcState().instAddr() - 4;
167 Addr NextInstAddr = xc->pcState().instAddr() + 4;
168 if (roundDown(PrevInstAddr, RiscvISA::PageBytes) !=
169 roundDown(NextInstAddr, RiscvISA::PageBytes)) {
170 DPRINTF(Semihosting,
171 "Ebreak cannot be a semihosting ebreak since previous "
172 "and next instruction are on different pages\n");
173 return false;
174 }
175 uint32_t instSequence[3];
176 if (!proxy.tryReadBlob(PrevInstAddr, instSequence, sizeof(instSequence))) {
177 DPRINTF(Semihosting,
178 "Ebreak cannot be a semihosting ebreak since surrounding "
179 "instructions at %#x cannot be accessed\n");
180 return false;
181 }
182 uint32_t PrevInst = gtoh(instSequence[0], ByteOrder::little);
183 uint32_t EBreakInst = gtoh(instSequence[1], ByteOrder::little);
184 uint32_t NextInst = gtoh(instSequence[2], ByteOrder::little);
185 DPRINTF(Semihosting,
186 "Checking ebreak for semihosting: Prev=%#x EBreak=%#x Next=%#x\n",
187 PrevInst, EBreakInst, NextInst);
188 return PrevInst == (uint32_t)Opcode::Prefix &&
189 EBreakInst == (uint32_t)Opcode::EBreak &&
190 NextInst == (uint32_t)Opcode::Suffix;
191}
192
193} // namespace gem5
#define DPRINTF(x,...)
Definition trace.hh:210
Semihosting for AArch32, AArch64, RISCV-32 and RISCV-64: https://github.com/ARM-software/abi-aa/blob/...
RetErrno callReadC(ThreadContext *tc)
RetErrno callElapsed32(ThreadContext *tc, InPlaceArg low, InPlaceArg high)
RetErrno callExit64(ThreadContext *tc, uint64_t code, uint64_t subcode)
RetErrno callFLen(ThreadContext *tc, Handle handle)
void unrecognizedCall(ThreadContext *tc, const char *format, uint64_t op)
RetErrno callTickFreq(ThreadContext *tc)
RetErrno callRename(ThreadContext *tc, Addr from_addr, size_t from_size, Addr to_addr, size_t to_size)
RetErrno callExitExtended(ThreadContext *tc, uint64_t code, uint64_t subcode)
RetErrno callTmpNam(ThreadContext *tc, Addr buffer, uint64_t id, size_t size)
RetErrno callSeek(ThreadContext *tc, Handle handle, uint64_t pos)
RetErrno callSystem(ThreadContext *tc, Addr cmd_addr, size_t cmd_size)
RetErrno callWrite(ThreadContext *tc, Handle handle, Addr buffer, size_t size)
RetErrno callOpen(ThreadContext *tc, const Addr name_base, int fmode, size_t name_size)
RetErrno callIsError(ThreadContext *tc, int64_t status)
RetErrno callElapsed64(ThreadContext *tc, InPlaceArg ticks)
RetErrno callRead(ThreadContext *tc, Handle handle, Addr buffer, size_t size)
RetErrno callExit32(ThreadContext *tc, InPlaceArg code)
RetErrno callGetCmdLine(ThreadContext *tc, Addr addr, InPlaceArg size_arg)
RetErrno callHeapInfo32(ThreadContext *tc, Addr block_addr)
RetErrno callClock(ThreadContext *tc)
RetErrno callRemove(ThreadContext *tc, Addr name_base, size_t name_size)
RetErrno callHeapInfo64(ThreadContext *tc, Addr block_addr)
RetErrno callIsTTY(ThreadContext *tc, Handle handle)
RetErrno callWriteC(ThreadContext *tc, InPlaceArg c)
RetErrno callErrno(ThreadContext *tc)
RetErrno callTime(ThreadContext *tc)
RetErrno callWrite0(ThreadContext *tc, InPlaceArg str)
RetErrno callClose(ThreadContext *tc, Handle handle)
The ExecContext is an abstract base class the provides the interface used by the ISA to manipulate th...
virtual ThreadContext * tcBase() const =0
Returns a pointer to the ThreadContext.
virtual const PCStateBase & pcState() const =0
Addr instAddr() const
Returns the memory address of the instruction this PC points to.
Definition pcstate.hh:108
This object is a proxy for a port or other object which implements the functional response protocol,...
Definition port_proxy.hh:87
virtual bool tryReadBlob(Addr addr, void *p, uint64_t size) const
Methods to override in base classes.
bool call64(ThreadContext *tc)
static PortProxy & portProxyImpl(ThreadContext *tc)
RiscvSemihosting(const RiscvSemihostingParams &p)
static const std::map< uint32_t, SemiCall > calls
SemiCallBase< RiscvSemihosting, Abi32, Abi64 > SemiCall
bool call(ThreadContext *tc)
bool isSemihostingEBreak(ExecContext *xc)
Perform a RISC-V Semihosting call.
bool call32(ThreadContext *tc)
ThreadContext is the external interface to all thread state for anything outside of the CPU.
virtual RegVal getReg(const RegId &reg) const
virtual BaseISA * getIsaPtr() const =0
This proxy attempts to translate virtual addresses using the TLBs.
static constexpr T roundDown(const T &val, const U &align)
This function is used to align addresses in memory.
Definition intmath.hh:279
#define panic_if(cond,...)
Conditional panic macro that checks the supplied condition and only panics if the condition is true a...
Definition logging.hh:214
Bitfield< 3, 0 > mask
Definition pcstate.hh:63
Bitfield< 6 > err
Bitfield< 0 > p
constexpr RegId A0
Definition int.hh:101
const Addr PageBytes
Definition page_size.hh:54
Bitfield< 4 > op
Definition types.hh:83
Copyright (c) 2024 - Pranith Kumar Copyright (c) 2020 Inria All rights reserved.
Definition binary32.hh:36
uint64_t RegVal
Definition types.hh:173
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition types.hh:147
T gtoh(T value, ByteOrder guest_byte_order)
Definition byteswap.hh:194
bool FullSystem
The FullSystem variable can be used to determine the current mode of simulation.
Definition root.cc:220

Generated on Tue Jun 18 2024 16:23:57 for gem5 by doxygen 1.11.0