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 "base/logging.hh"
46#include "base/output.hh"
47#include "base/time.hh"
48#include "debug/Semihosting.hh"
49#include "dev/serial/serial.hh"
50#include "mem/physical.hh"
51#include "params/BaseSemihosting.hh"
52#include "sim/byteswap.hh"
53#include "sim/pseudo_inst.hh"
54#include "sim/sim_exit.hh"
55#include "sim/system.hh"
56
57namespace gem5
58{
59
61 "r",
62 "rb",
63 "r+",
64 "r+b",
65 "w",
66 "wb",
67 "w+",
68 "w+b",
69 "a",
70 "ab",
71 "a+",
72 "a+b",
73};
74
75const std::map<uint64_t, const char *> BaseSemihosting::exitCodes{
76 {0x20000, "semi:ADP_Stopped_BranchThroughZero"},
77 {0x20001, "semi:ADP_Stopped_UndefinedInstr"},
78 {0x20002, "semi:ADP_Stopped_SoftwareInterrupt"},
79 {0x20003, "semi:ADP_Stopped_PrefetchAbort"},
80 {0x20004, "semi:ADP_Stopped_DataAbort"},
81 {0x20005, "semi:ADP_Stopped_AddressException"},
82 {0x20006, "semi:ADP_Stopped_IRQ"},
83 {0x20007, "semi:ADP_Stopped_FIQ"},
84
85 {0x20020, "semi:ADP_Stopped_BreakPoint"},
86 {0x20021, "semi:ADP_Stopped_WatchPoint"},
87 {0x20022, "semi:ADP_Stopped_StepComplete"},
88 {0x20023, "semi:ADP_Stopped_RunTimeErrorUnknown"},
89 {0x20024, "semi:ADP_Stopped_InternalError"},
90 {0x20025, "semi:ADP_Stopped_UserInterruption"},
91 {0x20026, "semi:ADP_Stopped_ApplicationExit"},
92 {0x20027, "semi:ADP_Stopped_StackOverflow"},
93 {0x20028, "semi:ADP_Stopped_DivisionByZero"},
94 {0x20029, "semi:ADP_Stopped_DivisionByZero"},
95};
96
97const std::array<uint8_t, 5> BaseSemihosting::features{
98 0x53, 0x48, 0x46, 0x42, // Magic
99 0x3, // EXT_EXIT_EXTENDED, EXT_STDOUT_STDERR
100};
101
102const std::map<const std::string, FILE *> BaseSemihosting::stdioMap{
103 {"cin", ::stdin},
104 {"stdin", ::stdin},
105 {"cout", ::stdout},
106 {"stdout", ::stdout},
107 {"cerr", ::stderr},
108 {"stderr", ::stderr},
109};
110
111BaseSemihosting::BaseSemihosting(const BaseSemihostingParams &p)
112 : SimObject(p), cmdLine(p.cmd_line), memReserve(p.mem_reserve),
113 stackSize(p.stack_size), timeBase([p] {
114 struct tm t = p.time;
115 return mkutctime(&t);
116 }()),
117 tickShift(calcTickShift()), semiErrno(0),
118 filesRootDir(!p.files_root_dir.empty() && p.files_root_dir.back() != '/' ?
119 p.files_root_dir + '/' :
120 p.files_root_dir),
121 stdin(getSTDIO("stdin", p.stdin, "r")),
122 stdout(getSTDIO("stdout", p.stdout, "w")),
123 stderr(p.stderr == p.stdout ? stdout : getSTDIO("stderr", p.stderr, "w"))
124{
125 // Create an empty place-holder file for position 0 as semi-hosting
126 // calls typically expect non-zero file handles.
127 files.push_back(nullptr);
128
129 if (tickShift > 0)
130 inform("Semihosting: Shifting elapsed ticks by %i bits.", tickShift);
131}
132
133void
135{
137
138 paramOut(cp, "num_files", files.size());
139 for (int i = 0; i < files.size(); i++) {
140 // File closed?
141 if (!files[i])
142 continue;
143
144 files[i]->serializeSection(cp, csprintf("file%i", i));
145 }
146}
147
148void
150{
152
153 size_t num_files;
154 paramIn(cp, "num_files", num_files);
155 files.resize(num_files);
156 for (int i = 0; i < num_files; i++)
157 files[i] = FileBase::create(*this, cp, csprintf("file%i", i));
158}
159
160std::optional<std::string>
162{
163 if (len > 65536) {
164 // If the semihosting call passes an incorrect argument, reject it rather
165 // than attempting to allocate a buffer of that size. We chose 64K as
166 // an arbitrary limit here since no valid program should be attempting
167 // to open a file with such a large filename.
168 warn("BaseSemihosting::readString(): attempting to read too large "
169 "(%d bytes) string from %#x", len, ptr);
170 return std::nullopt;
171 }
172 std::vector<char> buf(len + 1);
173
174 buf[len] = '\0';
175 portProxy(tc).readBlob(ptr, buf.data(), len);
176
177 return std::string(buf.data());
178}
179
182 ThreadContext *tc, const Addr name_base, int fmode, size_t name_size)
183{
184 const char *mode = fmode < fmodes.size() ? fmodes[fmode] : nullptr;
185
186 DPRINTF(Semihosting, "Semihosting SYS_OPEN(0x%x, %i[%s], %i)\n", name_base,
187 fmode, mode ? mode : "-", name_size);
188 if (!mode || !name_base)
189 return retError(EINVAL);
190
191 std::optional<std::string> fnameOpt = readString(tc, name_base, name_size);
192 if (!fnameOpt.has_value())
193 return retError(ERANGE);
194 std::string fname = *fnameOpt;
195 if (!fname.empty() && fname.front() != '/' && fname != ":tt" &&
196 fname != ":semihosting-features")
197 fname = filesRootDir + fname;
198
199 std::unique_ptr<BaseSemihosting::FileBase> file =
200 FileBase::create(*this, fname, mode);
201 int64_t ret = file->open();
202 DPRINTF(Semihosting, "Semihosting SYS_OPEN(\"%s\", %i[%s]): %i\n", fname,
203 fmode, mode, ret);
204 if (ret < 0) {
205 return retError(-ret);
206 } else {
207 files.push_back(std::move(file));
208 return retOK(files.size() - 1);
209 }
210}
211
214{
215 if (handle > files.size()) {
216 DPRINTF(Semihosting, "Semihosting SYS_CLOSE(%i): Illegal file\n");
217 return retError(EBADF);
218 }
219
220 std::unique_ptr<FileBase> &file = files[handle];
221 int64_t error = file->close();
222 DPRINTF(Semihosting, "Semihosting SYS_CLOSE(%i[%s]): %i\n", handle,
223 file->fileName(), error);
224 if (error < 0) {
225 return retError(-error);
226 } else {
227 // Zap the pointer and free the entry in the file table as
228 // well.
229 files[handle].reset();
230 return retOK(0);
231 }
232}
233
236{
237 const char c = portProxy(tc).read<char>(arg.addr);
238
239 DPRINTF(Semihosting, "Semihosting SYS_WRITEC('%c')\n", c);
240 std::cout.put(c);
241 std::cout.flush();
242
243 return retOK(0);
244}
245
248{
249 DPRINTF(Semihosting, "Semihosting SYS_WRITE0(...)\n");
250 PortProxy &proxy = portProxy(tc);
251 std::string str;
252 proxy.readString(str, arg.addr);
253 std::cout.write(str.c_str(), str.size());
254 std::cout.flush();
255
256 return retOK(0);
257}
258
261 ThreadContext *tc, Handle handle, Addr addr, size_t size)
262{
263 if (handle > files.size() || !files[handle])
264 return RetErrno(size, EBADF);
265
266 std::vector<uint8_t> buffer(size);
267 portProxy(tc).readBlob(addr, buffer.data(), buffer.size());
268
269 int64_t ret = files[handle]->write(buffer.data(), buffer.size());
270 if (ret < 0) {
271 // No bytes written (we're returning the number of bytes not
272 // written)
273 return RetErrno(size, -ret);
274 } else {
275 // Return the number of bytes not written
276 return RetErrno(size - ret, 0);
277 }
278}
279
282 ThreadContext *tc, Handle handle, Addr addr, size_t size)
283{
284 if (handle > files.size() || !files[handle])
285 return RetErrno(size, EBADF);
286
287 std::vector<uint8_t> buffer(size);
288 int64_t ret = files[handle]->read(buffer.data(), buffer.size());
289 if (ret < 0) {
290 return RetErrno(size, -ret);
291 } else {
292 panic_if(ret > buffer.size(), "Read longer than buffer size.");
293
294 portProxy(tc).writeBlob(addr, buffer.data(), ret);
295
296 // Return the number of bytes not written
297 return retOK(size - ret);
298 }
299}
300
303{
304 return retOK((char)std::cin.get());
305}
306
309{
310 return retOK(status < 0 ? 1 : 0);
311}
312
315{
316 if (handle > files.size() || !files[handle])
317 return retError(EBADF);
318
319 int64_t ret = files[handle]->isTTY();
320 if (ret < 0) {
321 return retError(-ret);
322 } else {
323 return retOK(ret ? 1 : 0);
324 }
325}
326
329{
330 if (handle > files.size() || !files[handle])
331 return retError(EBADF);
332
333 int64_t ret = files[handle]->seek(pos);
334 if (ret < 0) {
335 return retError(-ret);
336 } else {
337 return retOK(0);
338 }
339}
340
343{
344 if (handle > files.size() || !files[handle])
345 return retError(EBADF);
346
347 int64_t ret = files[handle]->flen();
348 if (ret < 0) {
349 return retError(-ret);
350 } else {
351 return retOK(ret);
352 }
353}
354
357 ThreadContext *tc, Addr addr, uint64_t id, size_t size)
358{
359 std::string path = "";
360 int64_t unlink_call_ret = 0;
361
362 do {
363 path = simout.resolve(csprintf("%s.tmp%05i", name(), tmpNameIndex++));
364 // remove the (potentially existing) file of the given path
365 unlink_call_ret = unlink(path.c_str());
366 // if the file is busy, find another name
367 } while ((unlink_call_ret < 0) && (errno == EBUSY));
368
369 const size_t path_len = path.length();
370 if (path_len >= size)
371 return retError(ENOSPC);
372
373 portProxy(tc).writeBlob(addr, path.c_str(), path_len + 1);
374 return retOK(0);
375}
376
379 ThreadContext *tc, Addr name_base, size_t name_size)
380{
381 std::optional<std::string> fname = readString(tc, name_base, name_size);
382
383 if (!fname.has_value()) {
384 return retError(ERANGE);
385 } else if (remove(fname->c_str()) != 0) {
386 return retError(errno);
387 } else {
388 return retOK(0);
389 }
390}
391
394 size_t from_size, Addr to_addr, size_t to_size)
395{
396 std::optional<std::string> from = readString(tc, from_addr, from_size);
397 std::optional<std::string> to = readString(tc, to_addr, to_size);
398 if (!from.has_value() || !to.has_value()) {
399 return retError(ERANGE);
400 } else if (rename(from->c_str(), to->c_str()) != 0) {
401 return retError(errno);
402 } else {
403 return retOK(0);
404 }
405}
406
412
418
420BaseSemihosting::callSystem(ThreadContext *tc, Addr cmd_addr, size_t cmd_size)
421{
422 const std::optional<std::string> cmd = readString(tc, cmd_addr, cmd_size);
423 if (!cmd.has_value())
424 return retError(ERANGE);
425 warn("Semihosting: SYS_SYSTEM not implemented. Guest tried to run: %s\n",
426 *cmd);
427 return retError(EINVAL);
428}
429
432{
433 // Preserve errno by returning it in errno as well.
435}
436
439 ThreadContext *tc, Addr addr, InPlaceArg size_arg)
440{
441 PortProxy &proxy = portProxy(tc);
442 ByteOrder endian = byteOrder(tc);
443 size_t size = size_arg.read(tc, proxy, endian);
444
445 if (cmdLine.size() + 1 < size) {
446 proxy.writeBlob(addr, cmdLine.c_str(), cmdLine.size() + 1);
447 size_arg.write(tc, proxy, cmdLine.size(), endian);
448 return retOK(0);
449 } else {
450 return retError(0);
451 }
452}
453
454void
456 Addr &heap_base, Addr &heap_limit, Addr &stack_base, Addr &stack_limit)
457{
458 const memory::PhysicalMemory &phys = tc->getSystemPtr()->getPhysMem();
459 const AddrRangeList memories = phys.getConfAddrRanges();
460 fatal_if(memories.size() < 1, "No memories reported from System");
461 warn_if(memories.size() > 1,
462 "Multiple physical memory ranges available. "
463 "Using first range heap/stack.");
464 const AddrRange mem = *memories.begin();
465 const Addr mem_start = mem.start() + memReserve;
466 Addr mem_end = mem.end();
467
468 // Make sure that 32-bit guests can access their memory.
469 if (!aarch64) {
470 const Addr phys_max = (1ULL << 32) - 1;
471 panic_if(mem_start > phys_max,
472 "Physical memory out of range for a 32-bit guest.");
473 if (mem_end > phys_max) {
474 warn("Some physical memory out of range for a 32-bit guest.");
475 mem_end = phys_max;
476 }
477 }
478
479 fatal_if(mem_start + stackSize >= mem_end,
480 "Physical memory too small to fit desired stack and a heap.");
481
482 heap_base = mem_start;
483 heap_limit = mem_end - stackSize + 1;
484 stack_base = (mem_end + 1) & ~0x7ULL; // 8 byte stack alignment
485 stack_limit = heap_limit;
486
487 inform("Reporting heap/stack info to guest:\n"
488 "\tHeap base: 0x%x\n"
489 "\tHeap limit: 0x%x\n"
490 "\tStack base: 0x%x\n"
491 "\tStack limit: 0x%x\n",
492 heap_base, heap_limit, stack_base, stack_limit);
493}
494
497{
498 uint64_t heap_base, heap_limit, stack_base, stack_limit;
499 gatherHeapInfo(tc, false, heap_base, heap_limit, stack_base, stack_limit);
500
501 std::array<uint32_t, 4> block = {
502 {(uint32_t)heap_base, (uint32_t)heap_limit, (uint32_t)stack_base,
503 (uint32_t)stack_limit}};
504 portProxy(tc).write(block_addr, block, byteOrder(tc));
505
506 return retOK(0);
507}
508
511{
512 uint64_t heap_base, heap_limit, stack_base, stack_limit;
513 gatherHeapInfo(tc, true, heap_base, heap_limit, stack_base, stack_limit);
514
515 std::array<uint64_t, 4> block = {
516 {heap_base, heap_limit, stack_base, stack_limit}};
517 portProxy(tc).write(block_addr, block, byteOrder(tc));
518
519 return retOK(0);
520}
521
524{
525 semiExit(code.addr, 0);
526 return retOK(0);
527}
528
530BaseSemihosting::callExit64(ThreadContext *tc, uint64_t code, uint64_t subcode)
531{
532 semiExit(code, subcode);
533 return retOK(0);
534}
535
538 ThreadContext *tc, uint64_t code, uint64_t subcode)
539{
540 semiExit(code, subcode);
541 return retOK(0);
542}
543
544void
545BaseSemihosting::semiExit(uint64_t code, uint64_t subcode)
546{
547 auto it = exitCodes.find(code);
548 if (it != exitCodes.end()) {
549 exitSimLoop(it->second, subcode);
550 } else {
551 exitSimLoop(csprintf("semi:0x%x", code), subcode);
552 }
553}
554
557 ThreadContext *tc, InPlaceArg low, InPlaceArg high)
558{
559 PortProxy &proxy = portProxy(tc);
560 ByteOrder endian = byteOrder(tc);
561 uint64_t tick = semiTick(curTick());
562
563 low.write(tc, proxy, tick, endian);
564 high.write(tc, proxy, tick >> 32, endian);
565
566 return retOK(0);
567}
568
571{
572 ticks.write(tc, portProxy(tc), semiTick(curTick()), byteOrder(tc));
573 return retOK(0);
574}
575
581
582FILE *
584 const char *stream_name, const std::string &name, const char *mode)
585{
586 auto it = stdioMap.find(name);
587 if (it == stdioMap.end()) {
588 FILE *f = fopen(name.c_str(), mode);
589 if (!f) {
590 fatal("Failed to open %s (%s): %s\n", stream_name, name,
591 strerror(errno));
592 }
593 return f;
594 } else {
595 return it->second;
596 }
597}
598
599std::unique_ptr<BaseSemihosting::FileBase>
601 BaseSemihosting &parent, const std::string &fname, const char *mode)
602{
603 std::unique_ptr<FileBase> file;
604 if (fname == ":semihosting-features") {
605 file.reset(new FileFeatures(parent, fname.c_str(), mode));
606 } else {
607 file.reset(new File(parent, fname.c_str(), mode));
608 }
609
610 return file;
611}
612
613std::unique_ptr<BaseSemihosting::FileBase>
615 BaseSemihosting &parent, CheckpointIn &cp, const std::string &sec)
616{
617 std::unique_ptr<FileBase> file;
618 ScopedCheckpointSection _sec(cp, sec);
619
620 // Was the file open when the checkpoint was created?
622 return file;
623
624 std::string fname, mode;
625 paramIn(cp, "name", fname);
626 paramIn(cp, "mode", mode);
627 file = create(parent, fname, mode.c_str());
628 assert(file);
629 file->unserialize(cp);
630
631 return file;
632}
633
634void
640
641void
643{
644 /* Unserialization of name and mode happens in
645 * BaseSemihosting::FileBase::create() */
646}
647
648int64_t
649BaseSemihosting::FileBase::read(uint8_t *buffer, uint64_t size)
650{
651 return -EINVAL;
652}
653
654int64_t
655BaseSemihosting::FileBase::write(const uint8_t *buffer, uint64_t size)
656{
657 return -EINVAL;
658}
659
660int64_t
662{
663 return -EINVAL;
664}
665
666int64_t
668{
669 return -EINVAL;
670}
671
673FileFeatures(BaseSemihosting &_parent, const char *_name, const char *_mode) :
674 FileBase(_parent, _name, _mode)
675{}
676
677int64_t
679{
680 return features.size();
681}
682
683int64_t
684BaseSemihosting::FileFeatures::read(uint8_t *buffer, uint64_t size)
685{
686 int64_t len = 0;
687
688 for (; len < size && pos < features.size(); pos++)
689 buffer[len++] = features[pos];
690
691 return len;
692}
693
694int64_t
696{
697 if (_pos < BaseSemihosting::features.size()) {
698 pos = _pos;
699 return 0;
700 } else {
701 return -ENXIO;
702 }
703}
704
705void
711
712void
718
720File(BaseSemihosting &_parent, const char *_name, const char *_perms) :
721 FileBase(_parent, _name, _perms), file(nullptr)
722{}
723
724BaseSemihosting::File::~
725File()
726{
727 if (file)
728 close();
729}
730
731int64_t
733{
734 panic_if(file, "Trying to open an already open file.\n");
735
736 if (_name == ":tt") {
737 if (mode[0] == 'r') {
738 file = parent.stdin;
739 } else if (mode[0] == 'w') {
740 file = parent.stdout;
741 } else if (mode[0] == 'a') {
742 file = parent.stderr;
743 } else {
744 warn("Unknown file mode for the ':tt' special file");
745 return -EINVAL;
746 }
747 } else {
748 std::string real_mode(this->mode);
749 // Avoid truncating the file if we are restoring from a
750 // checkpoint.
751 if (in_cpt && real_mode[0] == 'w')
752 real_mode[0] = 'a';
753
754 file = fopen(_name.c_str(), real_mode.c_str());
755 }
756
757 return file ? 0 : -errno;
758}
759
760int64_t
762{
763 panic_if(!file, "Trying to close an already closed file.\n");
764
765 if (needClose()) {
766 fclose(file);
767 }
768 file = nullptr;
769
770 return 0;
771}
772
773bool
775{
776 return file == parent.stdout || file == parent.stderr ||
777 file == parent.stdin;
778}
779
780int64_t
781BaseSemihosting::File::read(uint8_t *buffer, uint64_t size)
782{
783 panic_if(!file, "Trying to read from a closed file");
784
785 size_t ret = fread(buffer, 1, size, file);
786 if (ret == 0) {
787 // Error or EOF. Assume errors are due to invalid file
788 // operations (e.g., reading a write-only stream).
789 return ferror(file) ? -EINVAL : 0;
790 } else {
791 return ret;
792 }
793}
794
795int64_t
796BaseSemihosting::File::write(const uint8_t *buffer, uint64_t size)
797{
798 panic_if(!file, "Trying to write to a closed file");
799
800 size_t ret = fwrite(buffer, 1, size, file);
801 if (ret == 0) {
802 // Assume errors are due to invalid file operations (e.g.,
803 // writing a read-only stream).
804 return -EINVAL;
805 } else {
806 return ret;
807 }
808}
809
810int64_t
812{
813 panic_if(!file, "Trying to seek in a closed file");
814
815 errno = 0;
816 if (fseek(file, _pos, SEEK_SET) == 0)
817 return 0;
818 else
819 return -errno;
820}
821
822int64_t
824{
825 errno = 0;
826 long pos = ftell(file);
827 if (pos < 0)
828 return -errno;
829
830 if (fseek(file, 0, SEEK_END) != 0)
831 return -errno;
832
833 long len = ftell(file);
834 if (len < 0)
835 return -errno;
836
837 if (fseek(file, pos, SEEK_SET) != 0)
838 return -errno;
839
840 return len;
841}
842
843void
845{
847
848 if (!isTTY()) {
849 long pos = file ? ftell(file) : 0;
850 panic_if(pos < 0, "Failed to get file position.");
851 SERIALIZE_SCALAR(pos);
852 }
853}
854
855void
857{
859
860 if (openImpl(true) < 0) {
861 fatal("Failed to open file: %s", _name);
862 }
863
864 if (!isTTY()) {
865 long pos = 0;
867 if (fseek(file, pos, SEEK_SET) != 0) {
868 fatal("Failed seek to current position (%i) in '%s'", pos, _name);
869 }
870 }
871}
872
873std::ostream &
874operator<<(std::ostream &os, const BaseSemihosting::InPlaceArg &ipa)
875{
876 ccprintf(os, "[%#x-%#x)", ipa.addr, ipa.addr + ipa.size - 1);
877 return os;
878}
879
880} // namespace gem5
std::string error
#define DPRINTF(x,...)
Definition trace.hh:210
The AddrRange class encapsulates an address range, and supports a number of tests to check if two ran...
Definition addr_range.hh:82
Internal state for open files.
virtual int64_t write(const uint8_t *buffer, uint64_t size)
Write data to file.
void serialize(CheckpointOut &cp) const override
Serialize an object.
virtual int64_t seek(uint64_t pos)
Seek to an absolute position in the file.
virtual int64_t read(uint8_t *buffer, uint64_t size)
Read data from file.
static std::unique_ptr< FileBase > create(BaseSemihosting &parent, const std::string &fname, const char *mode)
virtual int64_t flen()
Get the length of a file in bytes.
void unserialize(CheckpointIn &cp) override
Unserialize an object.
Implementation of the ':semihosting-features' magic file.
void unserialize(CheckpointIn &cp) override
Unserialize an object.
int64_t seek(uint64_t pos) override
Seek to an absolute position in the file.
FileFeatures(BaseSemihosting &_parent, const char *name, const char *mode)
int64_t flen() override
Get the length of a file in bytes.
int64_t read(uint8_t *buffer, uint64_t size) override
Read data from file.
void serialize(CheckpointOut &cp) const override
Serialize an object.
bool isTTY() const override
Check if a file corresponds to a TTY device.
int64_t close() override
Close the file.
void unserialize(CheckpointIn &cp) override
Unserialize an object.
File(BaseSemihosting &_parent, const char *name, const char *mode)
void serialize(CheckpointOut &cp) const override
Serialize an object.
int64_t read(uint8_t *buffer, uint64_t size) override
Read data from file.
int64_t flen() override
Get the length of a file in bytes.
int64_t seek(uint64_t pos) override
Seek to an absolute position in the file.
int64_t openImpl(bool unserialize)
int64_t write(const uint8_t *buffer, uint64_t size) override
Write data to file.
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)
static const std::map< uint64_t, const char * > exitCodes
RetErrno callFLen(ThreadContext *tc, Handle handle)
const std::string cmdLine
static const std::array< uint8_t, 5 > features
static FILE * getSTDIO(const char *stream_name, const std::string &name, const char *mode)
RetErrno callTickFreq(ThreadContext *tc)
std::pair< uint64_t, SemiErrno > RetErrno
virtual ByteOrder byteOrder(ThreadContext *tc) const =0
static const std::map< const std::string, FILE * > stdioMap
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)
std::vector< std::unique_ptr< FileBase > > files
static const std::vector< const char * > fmodes
RetErrno callSystem(ThreadContext *tc, Addr cmd_addr, size_t cmd_size)
BaseSemihosting(const BaseSemihostingParams &p)
void unserialize(CheckpointIn &cp) override
Unserialize an object.
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)
static RetErrno retError(SemiErrno e)
RetErrno callIsError(ThreadContext *tc, int64_t status)
void semiExit(uint64_t code, uint64_t subcode)
RetErrno callElapsed64(ThreadContext *tc, InPlaceArg ticks)
RetErrno callRead(ThreadContext *tc, Handle handle, Addr buffer, size_t size)
const time_t timeBase
Base time when the simulation started.
RetErrno callExit32(ThreadContext *tc, InPlaceArg code)
void serialize(CheckpointOut &cp) const override
Serialize an object.
virtual PortProxy & portProxy(ThreadContext *tc) const =0
static RetErrno retOK(uint64_t r)
void gatherHeapInfo(ThreadContext *tc, bool aarch64, Addr &heap_base, Addr &heap_limit, Addr &stack_base, Addr &stack_limit)
RetErrno callGetCmdLine(ThreadContext *tc, Addr addr, InPlaceArg size_arg)
RetErrno callHeapInfo32(ThreadContext *tc, Addr block_addr)
RetErrno callClock(ThreadContext *tc)
std::optional< std::string > readString(ThreadContext *tc, Addr ptr, size_t len)
RetErrno callRemove(ThreadContext *tc, Addr name_base, size_t name_size)
RetErrno callHeapInfo64(ThreadContext *tc, Addr block_addr)
uint64_t semiTick(Tick tick) const
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)
const std::string _name
Definition named.hh:41
virtual std::string name() const
Definition named.hh:47
std::string resolve(const std::string &name) const
Returns relative file names prepended with name of this directory.
Definition output.cc:204
This object is a proxy for a port or other object which implements the functional response protocol,...
Definition port_proxy.hh:87
void readBlob(Addr addr, void *p, uint64_t size) const
Higher level interfaces based on the above.
T read(Addr address) const
Read sizeof(T) bytes from address and return as object T.
void writeBlob(Addr addr, const void *p, uint64_t size) const
Same as tryWriteBlob, but insists on success.
void write(Addr address, const T &data) const
Write object T to address.
void readString(std::string &str, Addr addr) const
Same as tryReadString, but insists on success.
static std::stack< std::string > path
Definition serialize.hh:315
Abstract superclass for simulation objects.
memory::PhysicalMemory & getPhysMem()
Get a pointer to access the physical memory of the system.
Definition system.hh:342
ThreadContext is the external interface to all thread state for anything outside of the CPU.
virtual System * getSystemPtr()=0
The physical memory encapsulates all memories in the system and provides basic functionality for acce...
Definition physical.hh:137
AddrRangeList getConfAddrRanges() const
Get the memory ranges for all memories that are to be reported to the configuration table.
Definition physical.cc:279
STL pair class.
Definition stl.hh:58
STL vector class.
Definition stl.hh:37
#define fatal_if(cond,...)
Conditional fatal macro that checks the supplied condition and only causes a fatal error if the condi...
Definition logging.hh:236
#define fatal(...)
This implements a cprintf based fatal() function.
Definition logging.hh:200
#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
static const std::string & currentSection()
Gets the fully-qualified name of the active section.
Definition serialize.cc:130
bool sectionExists(const std::string &section)
Definition serialize.cc:203
#define warn(...)
Definition logging.hh:256
#define warn_if(cond,...)
Conditional warning macro that checks the supplied condition and only prints a warning if the conditi...
Definition logging.hh:283
#define inform(...)
Definition logging.hh:257
Bitfield< 18, 16 > len
Bitfield< 4, 0 > mode
Definition misc_types.hh:74
Bitfield< 5 > t
Definition misc_types.hh:71
Bitfield< 7 > i
Definition misc_types.hh:67
Bitfield< 5, 0 > status
Bitfield< 29 > c
Definition misc_types.hh:53
Bitfield< 6 > f
Definition misc_types.hh:68
Bitfield< 34 > aarch64
Definition types.hh:81
Bitfield< 0 > p
Bitfield< 25, 21 > to
Definition types.hh:96
Bitfield< 32 > tm
Definition misc.hh:112
Bitfield< 17 > os
Definition misc.hh:838
Bitfield< 3 > addr
Definition types.hh:84
double s
These variables equal the number of ticks in the unit of time they're named after in a double.
Definition core.cc:51
Tick Frequency
The simulated frequency of curTick(). (In ticks per second)
Definition core.cc:47
Copyright (c) 2024 - Pranith Kumar Copyright (c) 2020 Inria All rights reserved.
Definition binary32.hh:36
Tick curTick()
The universal simulation clock.
Definition cur_tick.hh:46
std::ostream CheckpointOut
Definition serialize.hh:66
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition types.hh:147
void paramOut(CheckpointOut &cp, const std::string &name, ExtMachInst const &machInst)
Definition types.cc:40
time_t mkutctime(struct tm *time)
Definition time.cc:154
void paramIn(CheckpointIn &cp, const std::string &name, ExtMachInst &machInst)
Definition types.cc:72
OutputDirectory simout
Definition output.cc:62
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 (...
Definition sim_events.cc:88
static std::ostream & operator<<(std::ostream &os, const DummyMatRegContainer &d)
Definition matrix.hh:564
std::string csprintf(const char *format, const Args &...args)
Definition cprintf.hh:161
void ccprintf(cp::Print &print)
Definition cprintf.hh:130
#define UNSERIALIZE_SCALAR(scalar)
Definition serialize.hh:575
#define SERIALIZE_SCALAR(scalar)
Definition serialize.hh:568
void write(ThreadContext *tc, PortProxy &proxy, uint64_t val, ByteOrder endian)
uint64_t read(ThreadContext *tc, PortProxy &proxy, ByteOrder endian)
bool_vector8 mem[]
Definition reset_stim.h:43
const std::string & name()
Definition trace.cc:48

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