Go to the documentation of this file.
45 #include "debug/Semihosting.hh"
50 #include "params/ArmSemihosting.hh"
95 "r",
"rb",
"r+",
"r+b",
96 "w",
"wb",
"w+",
"w+b",
97 "a",
"ab",
"a+",
"a+b",
101 { 0x20000,
"semi:ADP_Stopped_BranchThroughZero" },
102 { 0x20001,
"semi:ADP_Stopped_UndefinedInstr" },
103 { 0x20002,
"semi:ADP_Stopped_SoftwareInterrupt" },
104 { 0x20003,
"semi:ADP_Stopped_PrefetchAbort" },
105 { 0x20004,
"semi:ADP_Stopped_DataAbort" },
106 { 0x20005,
"semi:ADP_Stopped_AddressException" },
107 { 0x20006,
"semi:ADP_Stopped_IRQ" },
108 { 0x20007,
"semi:ADP_Stopped_FIQ" },
110 { 0x20020,
"semi:ADP_Stopped_BreakPoint" },
111 { 0x20021,
"semi:ADP_Stopped_WatchPoint" },
112 { 0x20022,
"semi:ADP_Stopped_StepComplete" },
113 { 0x20023,
"semi:ADP_Stopped_RunTimeErrorUnknown" },
114 { 0x20024,
"semi:ADP_Stopped_InternalError" },
115 { 0x20025,
"semi:ADP_Stopped_UserInterruption" },
116 { 0x20026,
"semi:ADP_Stopped_ApplicationExit" },
117 { 0x20027,
"semi:ADP_Stopped_StackOverflow" },
118 { 0x20028,
"semi:ADP_Stopped_DivisionByZero" },
119 { 0x20029,
"semi:ADP_Stopped_DivisionByZero" },
124 0x53, 0x48, 0x46, 0x42,
132 {
"stdout", ::stdout},
134 {
"stderr", ::stderr},
139 cmdLine(
p->cmd_line),
140 memReserve(
p->mem_reserve),
141 stackSize(
p->stack_size),
142 timeBase([
p]{
struct tm
t =
p->time;
return mkutctime(&
t); }()),
143 tickShift(calcTickShift()),
145 filesRootDir(!
p->files_root_dir.empty() &&
146 p->files_root_dir.back() !=
'/' ?
147 p->files_root_dir +
'/' :
p->files_root_dir),
148 stdin(getSTDIO(
"stdin",
p->stdin,
"r")),
149 stdout(getSTDIO(
"stdout",
p->stdout,
"w")),
150 stderr(
p->stderr ==
p->stdout ?
151 stdout : getSTDIO(
"stderr",
p->stderr,
"w"))
155 files.push_back(
nullptr);
158 inform(
"Semihosting: Shifting elapsed ticks by %i bits.",
167 unrecognizedCall<Abi64>(
168 tc,
"Gem5 semihosting op (0x%x) disabled from here.",
op);
173 if (it ==
calls.end()) {
174 unrecognizedCall<Abi64>(
175 tc,
"Unknown aarch64 semihosting call: op = 0x%x",
op);
180 DPRINTF(Semihosting,
"Semihosting call64: %s\n", call.
dump64(tc));
183 DPRINTF(Semihosting,
"\t ->: 0x%x, %i\n",
err.first,
err.second);
193 unrecognizedCall<Abi32>(
194 tc,
"Gem5 semihosting op (0x%x) disabled from here.",
op);
199 if (it ==
calls.end()) {
200 unrecognizedCall<Abi32>(
201 tc,
"Unknown aarch32 semihosting call: op = 0x%x",
op);
206 DPRINTF(Semihosting,
"Semihosting call32: %s\n", call.
dump32(tc));
209 DPRINTF(Semihosting,
"\t ->: 0x%x, %i\n",
err.first,
err.second);
220 for (
int i = 0;
i <
files.size();
i++) {
236 files.resize(num_files);
237 for (
int i = 0;
i < num_files;
i++)
244 static std::unique_ptr<PortProxy> port_proxy_s;
245 static System *secure_sys =
nullptr;
249 if (sys != secure_sys) {
261 return *port_proxy_s;
276 return std::string(buf.data());
281 int fmode,
size_t name_size)
285 DPRINTF(Semihosting,
"Semihosting SYS_OPEN(0x%x, %i[%s], %i)\n",
286 name_base, fmode,
mode ?
mode :
"-", name_size);
287 if (!
mode || !name_base)
290 std::string fname =
readString(tc, name_base, name_size);
291 if (!fname.empty() && fname.front() !=
'/')
294 std::unique_ptr<ArmSemihosting::FileBase> file =
296 int64_t ret = file->open();
297 DPRINTF(Semihosting,
"Semihosting SYS_OPEN(\"%s\", %i[%s]): %i\n",
298 fname, fmode,
mode, ret);
302 files.push_back(std::move(file));
310 if (handle >
files.size()) {
311 DPRINTF(Semihosting,
"Semihosting SYS_CLOSE(%i): Illegal file\n");
315 std::unique_ptr<FileBase> &file =
files[handle];
316 int64_t error = file->close();
317 DPRINTF(Semihosting,
"Semihosting SYS_CLOSE(%i[%s]): %i\n",
318 handle, file->fileName(), error);
324 files[handle].reset();
334 DPRINTF(Semihosting,
"Semihosting SYS_WRITEC('%c')\n",
c);
343 DPRINTF(Semihosting,
"Semihosting SYS_WRITE0(...)\n");
347 std::cout.write(str.c_str(), str.size());
362 int64_t ret =
files[handle]->write(buffer.data(), buffer.size());
381 int64_t ret =
files[handle]->read(buffer.data(), buffer.size());
385 panic_if(ret > buffer.size(),
"Read longer than buffer size.");
390 return retOK(size - ret);
397 return retOK((
char)std::cin.get());
412 int64_t ret =
files[handle]->isTTY();
416 return retOK(ret ? 1 : 0);
426 int64_t ret =
files[handle]->seek(pos);
440 int64_t ret =
files[handle]->flen();
453 char *
path = tmpnam(buf.data());
457 const size_t path_len = strlen(
path);
458 if (path_len >= size)
468 std::string fname =
readString(tc, name_base, name_size);
470 if (remove(fname.c_str()) != 0) {
479 Addr to_addr,
size_t to_size)
481 std::string from =
readString(tc, from_addr, from_size);
482 std::string to =
readString(tc, to_addr, to_size);
484 if (rename(from.c_str(), to.c_str()) != 0) {
506 const std::string cmd =
readString(tc, cmd_addr, cmd_size);
507 warn(
"Semihosting: SYS_SYSTEM not implemented. Guest tried to run: %s\n",
526 size_t size = size_arg.
read(tc, endian);
528 if (
cmdLine.size() + 1 < size) {
540 Addr &stack_base,
Addr &stack_limit)
544 fatal_if(memories.size() < 1,
"No memories reported from System");
545 warn_if(memories.size() > 1,
"Multiple physical memory ranges available. "
546 "Using first range heap/stack.");
553 const Addr phys_max = (1
ULL << 32) - 1;
555 "Physical memory out of range for a 32-bit guest.");
556 if (mem_end > phys_max) {
557 warn(
"Some physical memory out of range for a 32-bit guest.");
563 "Physical memory too small to fit desired stack and a heap.");
565 heap_base = mem_start;
567 stack_base = (mem_end + 1) & ~0x7ULL;
568 stack_limit = heap_limit;
570 inform(
"Reporting heap/stack info to guest:\n"
571 "\tHeap base: 0x%x\n"
572 "\tHeap limit: 0x%x\n"
573 "\tStack base: 0x%x\n"
574 "\tStack limit: 0x%x\n",
575 heap_base, heap_limit, stack_base, stack_limit);
581 uint64_t heap_base, heap_limit, stack_base, stack_limit;
582 gatherHeapInfo(tc,
false, heap_base, heap_limit, stack_base, stack_limit);
584 std::array<uint32_t, 4> block = {{
585 (uint32_t)heap_base, (uint32_t)heap_limit,
586 (uint32_t)stack_base, (uint32_t)stack_limit
596 uint64_t heap_base, heap_limit, stack_base, stack_limit;
597 gatherHeapInfo(tc,
true, heap_base, heap_limit, stack_base, stack_limit);
599 std::array<uint64_t, 4> block = {{
600 heap_base, heap_limit, stack_base, stack_limit
623 uint64_t code, uint64_t subcode)
648 low.
write(tc, tick, endian);
649 high.
write(tc, tick >> 32, endian);
701 template <
typename T>
703 public Argument<ArmSemihosting::Abi32, T>
705 template <
typename T>
707 public Argument<ArmSemihosting::Abi64, T>
719 if (PseudoInst::pseudoInst<SemiPseudoAbi32>(tc, func, ret))
732 if (PseudoInst::pseudoInst<SemiPseudoAbi64>(tc, func, ret))
740 const std::string &
name,
const char *
mode)
746 fatal(
"Failed to open %s (%s): %s\n",
747 stream_name,
name, strerror(errno));
755 std::unique_ptr<ArmSemihosting::FileBase>
759 std::unique_ptr<FileBase> file;
760 if (fname ==
":semihosting-features") {
769 std::unique_ptr<ArmSemihosting::FileBase>
773 std::unique_ptr<FileBase> file;
780 std::string fname,
mode;
783 file = create(parent, fname,
mode.c_str());
785 file->unserialize(
cp);
874 const char *_name,
const char *_perms)
889 panic_if(file,
"Trying to open an already open file.\n");
891 if (_name ==
":tt") {
892 if (
mode[0] ==
'r') {
894 }
else if (
mode[0] ==
'w') {
895 file = parent.stdout;
896 }
else if (
mode[0] ==
'a') {
897 file = parent.stderr;
899 warn(
"Unknown file mode for the ':tt' special file");
903 std::string real_mode(this->
mode);
906 if (in_cpt && real_mode[0] ==
'w')
909 file = fopen(_name.c_str(), real_mode.c_str());
912 return file ? 0 : -errno;
918 panic_if(!file,
"Trying to close an already closed file.\n");
931 return file == parent.stdout ||
932 file == parent.stderr ||
933 file == parent.stdin;
939 panic_if(!file,
"Trying to read from a closed file");
941 size_t ret = fread(buffer, 1, size, file);
945 return ferror(file) ? -EINVAL : 0;
954 panic_if(!file,
"Trying to write to a closed file");
957 size_t ret = fwrite(buffer, 1, size, file);
970 panic_if(!file,
"Trying to seek in a closed file");
973 if (fseek(file, _pos, SEEK_SET) == 0)
983 long pos = ftell(file);
987 if (fseek(file, 0, SEEK_END) != 0)
990 long len = ftell(file);
994 if (fseek(file, pos, SEEK_SET) != 0)
1007 long pos = file ? ftell(file) : 0;
1008 panic_if(pos < 0,
"Failed to get file position.");
1018 if (openImpl(
true) < 0) {
1019 fatal(
"Failed to open file: %s", _name);
1025 if (fseek(file, pos, SEEK_SET) != 0) {
1026 fatal(
"Failed seek to current position (%i) in '%s'", pos, _name);
1040 ArmSemihostingParams::create()
void gatherHeapInfo(ThreadContext *tc, bool aarch64, Addr &heap_base, Addr &heap_limit, Addr &stack_base, Addr &stack_limit)
#define fatal(...)
This implements a cprintf based fatal() function.
Implementation of the ':semihosting-features' magic file.
static std::unique_ptr< FileBase > create(ArmSemihosting &parent, const std::string &fname, const char *mode)
static RetErrno retError(SemiErrno e)
RetErrno callWrite0(ThreadContext *tc, InPlaceArg str)
RetErrno callWrite(ThreadContext *tc, Handle handle, Addr buffer, size_t size)
RetErrno callExit64(ThreadContext *tc, uint64_t code, uint64_t subcode)
double s
These variables equal the number of ticks in the unit of time they're named after in a double.
virtual int64_t flen()
Get the length of a file in bytes.
RetErrno callElapsed32(ThreadContext *tc, InPlaceArg low, InPlaceArg high)
static const std::map< const std::string, FILE * > stdioMap
RetErrno callTickFreq(ThreadContext *tc)
RetErrno callRename(ThreadContext *tc, Addr from_addr, size_t from_size, Addr to_addr, size_t to_size)
static RetErrno retOK(uint64_t r)
RetErrno callElapsed64(ThreadContext *tc, InPlaceArg ticks)
#define UNSERIALIZE_SCALAR(scalar)
RetErrno callWriteC(ThreadContext *tc, InPlaceArg c)
ByteOrder byteOrder(const ThreadContext *tc)
RetErrno callOpen(ThreadContext *tc, const Addr name_base, int fmode, size_t name_size)
time_t mkutctime(struct tm *time)
int64_t openImpl(bool unserialize)
uint64_t semiTick(Tick tick) const
const std::string cmdLine
static const std::vector< uint8_t > features
State(const ThreadContext *tc)
static const std::vector< const char * > fmodes
RetErrno callErrno(ThreadContext *tc)
RetErrno callRemove(ThreadContext *tc, Addr name_base, size_t name_size)
virtual int64_t seek(uint64_t pos)
Seek to an absolute position in the file.
State(const ThreadContext *tc)
RetErrno callExit32(ThreadContext *tc, InPlaceArg code)
RetErrno callClock(ThreadContext *tc)
static void decodeAddrOffset(Addr offset, uint8_t &func)
bool call32(ThreadContext *tc, bool gem5_ops)
Perform an Arm Semihosting call from aarch32 code.
bool FullSystem
The FullSystem variable can be used to determine the current mode of simulation.
RetErrno callGetCmdLine(ThreadContext *tc, Addr addr, InPlaceArg size_arg)
void write(ThreadContext *tc, uint64_t val, ByteOrder endian)
RetErrno callSeek(ThreadContext *tc, Handle handle, uint64_t pos)
void paramOut(CheckpointOut &cp, const string &name, ExtMachInst const &machInst)
RetErrno callTime(ThreadContext *tc)
PhysicalMemory & getPhysMem()
Get a pointer to access the physical memory of the system.
int64_t flen() override
Get the length of a file in bytes.
RetErrno callHeapInfo32(ThreadContext *tc, Addr block_addr)
Tick Frequency
The simulated frequency of curTick(). (In ticks per second)
void writeBlob(Addr addr, const void *p, int size) const
Same as tryWriteBlob, but insists on success.
int64_t read(uint8_t *buffer, uint64_t size) override
Read data from file.
File(ArmSemihosting &_parent, const char *name, const char *mode)
virtual int64_t read(uint8_t *buffer, uint64_t size)
Read data from file.
@ SECURE
The request targets the secure memory space.
ThreadContext is the external interface to all thread state for anything outside of the CPU.
void readString(std::string &str, Addr addr) const
Same as tryReadString, but insists on success.
The AddrRange class encapsulates an address range, and supports a number of tests to check if two ran...
bool call64(ThreadContext *tc, bool gem5_ops)
Perform an Arm Semihosting call from aarch64 code.
bool isTTY() const override
Check if a file corresponds to a TTY device.
static const std::map< uint32_t, SemiCall > calls
RetErrno callSystem(ThreadContext *tc, Addr cmd_addr, size_t cmd_size)
std::string readString(ThreadContext *tc, Addr ptr, size_t len)
RetErrno callIsTTY(ThreadContext *tc, Handle handle)
RetErrno callHeapInfo64(ThreadContext *tc, Addr block_addr)
static const std::map< uint64_t, const char * > exitCodes
int64_t close() override
Close the file.
void semiExit(uint64_t code, uint64_t subcode)
std::ostream & operator<<(std::ostream &os, const ArmSemihosting::InPlaceArg &ipa)
void exitSimLoop(const std::string &message, int exit_code, Tick when, Tick repeat, bool serialize)
Schedule an event to exit the simulation loop (returning to Python) at the end of the current cycle (...
int64_t seek(uint64_t pos) override
Seek to an absolute position in the file.
void serialize(CheckpointOut &cp) const override
Serialize an object.
static FILE * getSTDIO(const char *stream_name, const std::string &name, const char *mode)
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
int64_t seek(uint64_t pos) override
Seek to an absolute position in the file.
const std::string & name()
#define SERIALIZE_SCALAR(scalar)
uint64_t read(ThreadContext *tc, ByteOrder endian)
virtual const std::string name() const
virtual PortProxy & getVirtProxy()=0
RetErrno callGem5PseudoOp32(ThreadContext *tc, uint32_t encoded_func)
RetErrno callExitExtended(ThreadContext *tc, uint64_t code, uint64_t subcode)
#define warn_if(cond,...)
Conditional warning macro that checks the supplied condition and only prints a warning if the conditi...
This proxy attempts to translate virtual addresses using the TLBs.
#define panic_if(cond,...)
Conditional panic macro that checks the supplied condition and only panics if the condition is true a...
The physical memory encapsulates all memories in the system and provides basic functionality for acce...
static PortProxy & portProxy(ThreadContext *tc)
This object is a proxy for a port or other object which implements the functional response protocol,...
Semihosting call information structure.
void serialize(CheckpointOut &cp) const override
Serialize an object.
T read(Addr address) const
Read sizeof(T) bytes from address and return as object T.
int64_t read(uint8_t *buffer, uint64_t size) override
Read data from file.
RetErrno callFLen(ThreadContext *tc, Handle handle)
ArmSemihosting(const ArmSemihostingParams *p)
RetErrno callReadC(ThreadContext *tc)
FileFeatures(ArmSemihosting &_parent, const char *name, const char *mode)
void paramIn(CheckpointIn &cp, const string &name, ExtMachInst &machInst)
void ccprintf(cp::Print &print)
void unserialize(CheckpointIn &cp) override
Unserialize an object.
void unserialize(CheckpointIn &cp) override
Unserialize an object.
int64_t write(const uint8_t *buffer, uint64_t size) override
Write data to file.
virtual int64_t write(const uint8_t *buffer, uint64_t size)
Write data to file.
std::ostream CheckpointOut
static const std::string & currentSection()
Gets the fully-qualified name of the active section.
AddrRangeList getConfAddrRanges() const
Get the memory ranges for all memories that are to be reported to the configuration table.
RetErrno callClose(ThreadContext *tc, Handle handle)
virtual RegVal readIntReg(RegIndex reg_idx) const =0
#define fatal_if(cond,...)
Conditional fatal macro that checks the supplied condition and only causes a fatal error if the condi...
std::vector< std::unique_ptr< FileBase > > files
void readBlob(Addr addr, void *p, int size) const
Higher level interfaces based on the above.
const time_t timeBase
Base time when the simulation started.
Semihosting for AArch32 and AArch64.
RetErrno callTmpNam(ThreadContext *tc, Addr buffer, uint64_t id, size_t size)
RetErrno callRead(ThreadContext *tc, Handle handle, Addr buffer, size_t size)
void serialize(CheckpointOut &cp) const override
Serialize an object.
RetErrno callIsError(ThreadContext *tc, int64_t status)
std::string csprintf(const char *format, const Args &...args)
std::pair< uint64_t, SemiErrno > RetErrno
void serialize(CheckpointOut &cp) const override
Serialize an object.
static std::stack< std::string > path
#define ULL(N)
uint64_t constant
void write(Addr address, const T &data) const
Write object T to address.
bool isSecure(ThreadContext *tc)
void unserialize(CheckpointIn &cp) override
Unserialize an object.
Internal state for open files.
virtual System * getSystemPtr()=0
RetErrno callGem5PseudoOp64(ThreadContext *tc, uint64_t encoded_func)
Tick curTick()
The current simulated tick.
void unserialize(CheckpointIn &cp) override
Unserialize an object.
Abstract superclass for simulation objects.
Generated on Wed Sep 30 2020 14:02:01 for gem5 by doxygen 1.8.17