From 422ff9e00657729cdabe3bbf19d6438e0a6af480 Mon Sep 17 00:00:00 2001 From: xinyangli Date: Tue, 23 Jul 2024 17:15:35 +0800 Subject: [PATCH] refactor: drop internal difftest support --- nemu/.result.tmp | 0 nemu/default.nix | 4 +- nemu/include/config.h | 9 ++ nemu/include/cpu/difftest.h | 53 ---------- nemu/include/device/map.h | 20 ++-- nemu/include/difftest-def.h | 40 -------- nemu/include/difftest.h | 8 ++ nemu/include/macro.h | 62 +++++++----- nemu/include/nemu.h | 28 ++++++ nemu/src/cpu/cpu-exec.c | 1 - nemu/src/cpu/difftest/dut.c | 132 ------------------------- nemu/src/cpu/difftest/ref.c | 51 ---------- nemu/src/device/io/port-io.c | 14 ++- nemu/src/device/serial.c | 23 +++-- nemu/src/device/timer.c | 5 +- nemu/src/engine/interpreter/hostcall.c | 33 ++++--- nemu/src/engine/interpreter/init.c | 15 ++- nemu/src/isa/riscv32/difftest/dut.c | 28 ------ nemu/src/isa/riscv32/reg.c | 1 - nemu/src/monitor/gdbstub.cc | 34 ++++--- nemu/src/monitor/monitor.c | 64 ++++-------- 21 files changed, 192 insertions(+), 433 deletions(-) create mode 100644 nemu/.result.tmp create mode 100644 nemu/include/config.h delete mode 100644 nemu/include/cpu/difftest.h delete mode 100644 nemu/include/difftest-def.h create mode 100644 nemu/include/difftest.h create mode 100644 nemu/include/nemu.h delete mode 100644 nemu/src/cpu/difftest/dut.c delete mode 100644 nemu/src/cpu/difftest/ref.c delete mode 100644 nemu/src/isa/riscv32/difftest/dut.c diff --git a/nemu/.result.tmp b/nemu/.result.tmp new file mode 100644 index 0000000..e69de29 diff --git a/nemu/default.nix b/nemu/default.nix index 785d77e..1977e53 100644 --- a/nemu/default.nix +++ b/nemu/default.nix @@ -1,9 +1,9 @@ { pkgs, lib, stdenv, - am-kernels, dtc, mini-gdbstub, + am-kernels ? null, defconfig ? "alldefconfig", }: @@ -41,7 +41,7 @@ stdenv.mkDerivation rec { make ''; - doCheck = (defconfig == "alldefconfig"); + doCheck = (am-kernels != null); checkPhase = if doCheck then '' export NEMU_IMAGES_PATH=${am-kernels}/share/am-kernels make test diff --git a/nemu/include/config.h b/nemu/include/config.h new file mode 100644 index 0000000..6df4bf9 --- /dev/null +++ b/nemu/include/config.h @@ -0,0 +1,9 @@ +#ifndef __NEMU_CONFIG_H__ +#define __NEMU_CONFIG_H__ + +extern char *log_file = NULL; +extern char *elf_file = NULL; +extern char *img_file = NULL; +extern bool enable_gdbstub = false; + +#endif // __NEMU_CONFIG_H__ diff --git a/nemu/include/cpu/difftest.h b/nemu/include/cpu/difftest.h deleted file mode 100644 index 0c60d3b..0000000 --- a/nemu/include/cpu/difftest.h +++ /dev/null @@ -1,53 +0,0 @@ -/*************************************************************************************** -* Copyright (c) 2014-2022 Zihao Yu, Nanjing University -* -* NEMU is licensed under Mulan PSL v2. -* You can use this software according to the terms and conditions of the Mulan PSL v2. -* You may obtain a copy of Mulan PSL v2 at: -* http://license.coscl.org.cn/MulanPSL2 -* -* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, -* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, -* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. -* -* See the Mulan PSL v2 for more details. -***************************************************************************************/ - -#ifndef __CPU_DIFFTEST_H__ -#define __CPU_DIFFTEST_H__ - -#include -#include - -#ifdef CONFIG_DIFFTEST -void difftest_skip_ref(); -void difftest_skip_dut(int nr_ref, int nr_dut); -void difftest_set_patch(void (*fn)(void *arg), void *arg); -void difftest_step(vaddr_t pc, vaddr_t npc); -void difftest_detach(); -void difftest_attach(); -#else -static inline void difftest_skip_ref() {} -static inline void difftest_skip_dut(int nr_ref, int nr_dut) {} -static inline void difftest_set_patch(void (*fn)(void *arg), void *arg) {} -static inline void difftest_step(vaddr_t pc, vaddr_t npc) {} -static inline void difftest_detach() {} -static inline void difftest_attach() {} -#endif - -extern void (*ref_difftest_memcpy)(paddr_t addr, void *buf, size_t n, bool direction); -extern void (*ref_difftest_regcpy)(void *dut, bool direction); -extern void (*ref_difftest_exec)(uint64_t n); -extern void (*ref_difftest_raise_intr)(uint64_t NO); - -static inline bool difftest_check_reg(const char *name, vaddr_t pc, word_t ref, word_t dut) { - if (ref != dut) { - Log("%s is different after executing instruction at pc = " FMT_WORD - ", right = " FMT_WORD ", wrong = " FMT_WORD ", diff = " FMT_WORD, - name, pc, ref, dut, ref ^ dut); - return false; - } - return true; -} - -#endif diff --git a/nemu/include/device/map.h b/nemu/include/device/map.h index 841d36c..ecea817 100644 --- a/nemu/include/device/map.h +++ b/nemu/include/device/map.h @@ -16,10 +16,12 @@ #ifndef __DEVICE_MAP_H__ #define __DEVICE_MAP_H__ -#include +#include +#include +#include -typedef void(*io_callback_t)(uint32_t, int, bool); -uint8_t* new_space(int size); +typedef void (*io_callback_t)(uint32_t, int, bool); +uint8_t *new_space(int size); typedef struct { const char *name; @@ -36,19 +38,19 @@ static inline bool map_inside(IOMap *map, paddr_t addr) { static inline int find_mapid_by_addr(IOMap *maps, int size, paddr_t addr) { int i; - for (i = 0; i < size; i ++) { + for (i = 0; i < size; i++) { if (map_inside(maps + i, addr)) { - difftest_skip_ref(); + nemu_do_difftest = false; return i; } } return -1; } -void add_pio_map(const char *name, ioaddr_t addr, - void *space, uint32_t len, io_callback_t callback); -void add_mmio_map(const char *name, paddr_t addr, - void *space, uint32_t len, io_callback_t callback); +void add_pio_map(const char *name, ioaddr_t addr, void *space, uint32_t len, + io_callback_t callback); +void add_mmio_map(const char *name, paddr_t addr, void *space, uint32_t len, + io_callback_t callback); word_t map_read(paddr_t addr, int len, IOMap *map); void map_write(paddr_t addr, int len, word_t data, IOMap *map); diff --git a/nemu/include/difftest-def.h b/nemu/include/difftest-def.h deleted file mode 100644 index 77948fb..0000000 --- a/nemu/include/difftest-def.h +++ /dev/null @@ -1,40 +0,0 @@ -/*************************************************************************************** -* Copyright (c) 2014-2022 Zihao Yu, Nanjing University -* -* NEMU is licensed under Mulan PSL v2. -* You can use this software according to the terms and conditions of the Mulan PSL v2. -* You may obtain a copy of Mulan PSL v2 at: -* http://license.coscl.org.cn/MulanPSL2 -* -* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, -* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, -* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. -* -* See the Mulan PSL v2 for more details. -***************************************************************************************/ - -#ifndef __DIFFTEST_DEF_H__ -#define __DIFFTEST_DEF_H__ - -#include -#include -#include - -#define __EXPORT __attribute__((visibility("default"))) -enum { DIFFTEST_TO_DUT, DIFFTEST_TO_REF }; - -#if defined(CONFIG_ISA_x86) -# define DIFFTEST_REG_SIZE (sizeof(uint32_t) * 9) // GPRs + pc -#elif defined(CONFIG_ISA_mips32) -# define DIFFTEST_REG_SIZE (sizeof(uint32_t) * 38) // GPRs + status + lo + hi + badvaddr + cause + pc -#elif defined(CONFIG_ISA_riscv) -#define RISCV_GPR_TYPE MUXDEF(CONFIG_RV64, uint64_t, uint32_t) -#define RISCV_GPR_NUM MUXDEF(CONFIG_RVE , 16, 32) -#define DIFFTEST_REG_SIZE (sizeof(RISCV_GPR_TYPE) * (RISCV_GPR_NUM + 1)) // GPRs + pc -#elif defined(CONFIG_ISA_loongarch32r) -# define DIFFTEST_REG_SIZE (sizeof(uint32_t) * 33) // GPRs + pc -#else -# error Unsupport ISA -#endif - -#endif diff --git a/nemu/include/difftest.h b/nemu/include/difftest.h new file mode 100644 index 0000000..f9933bc --- /dev/null +++ b/nemu/include/difftest.h @@ -0,0 +1,8 @@ +#ifndef __NEMU_DIFFTEST_H__ +#define __NEMU_DIFFTEST_H__ + +#include + +extern bool nemu_do_difftest; + +#endif // __NEMU_DIFFTEST_H__ diff --git a/nemu/include/macro.h b/nemu/include/macro.h index 47f11b0..041a65a 100644 --- a/nemu/include/macro.h +++ b/nemu/include/macro.h @@ -29,7 +29,7 @@ #define ARRLEN(arr) (int)(sizeof(arr) / sizeof(arr[0])) // macro concatenation -#define concat_temp(x, y) x ## y +#define concat_temp(x, y) x##y #define concat(x, y) concat_temp(x, y) #define concat3(x, y, z) concat(concat(x, y), z) #define concat4(x, y, z, w) concat3(concat(x, y), z, w) @@ -39,17 +39,18 @@ // See https://stackoverflow.com/questions/26099745/test-if-preprocessor-symbol-is-defined-inside-macro #define CHOOSE2nd(a, b, ...) b #define MUX_WITH_COMMA(contain_comma, a, b) CHOOSE2nd(contain_comma a, b) -#define MUX_MACRO_PROPERTY(p, macro, a, b) MUX_WITH_COMMA(concat(p, macro), a, b) +#define MUX_MACRO_PROPERTY(p, macro, a, b) \ + MUX_WITH_COMMA(concat(p, macro), a, b) // define placeholders for some property -#define __P_DEF_0 X, -#define __P_DEF_1 X, -#define __P_ONE_1 X, +#define __P_DEF_0 X, +#define __P_DEF_1 X, +#define __P_ONE_1 X, #define __P_ZERO_0 X, // define some selection functions based on the properties of BOOLEAN macro -#define MUXDEF(macro, X, Y) MUX_MACRO_PROPERTY(__P_DEF_, macro, X, Y) +#define MUXDEF(macro, X, Y) MUX_MACRO_PROPERTY(__P_DEF_, macro, X, Y) #define MUXNDEF(macro, X, Y) MUX_MACRO_PROPERTY(__P_DEF_, macro, Y, X) -#define MUXONE(macro, X, Y) MUX_MACRO_PROPERTY(__P_ONE_, macro, X, Y) -#define MUXZERO(macro, X, Y) MUX_MACRO_PROPERTY(__P_ZERO_,macro, X, Y) +#define MUXONE(macro, X, Y) MUX_MACRO_PROPERTY(__P_ONE_, macro, X, Y) +#define MUXZERO(macro, X, Y) MUX_MACRO_PROPERTY(__P_ZERO_, macro, X, Y) // test if a boolean macro is defined #define ISDEF(macro) MUXDEF(macro, 1, 0) @@ -84,29 +85,46 @@ #define MAP(c, f) c(f) #define BITMASK(bits) ((1ull << (bits)) - 1) -#define BITS(x, hi, lo) (((x) >> (lo)) & BITMASK((hi) - (lo) + 1)) // similar to x[hi:lo] in verilog -#define SEXT(x, len) ({ struct { int64_t n : len; } __x = { .n = x }; (uint64_t)__x.n; }) +#define BITS(x, hi, lo) \ + (((x) >> (lo)) & BITMASK((hi) - (lo) + 1)) // similar to x[hi:lo] in verilog +#define SEXT(x, len) \ + ({ \ + struct { \ + int64_t n : len; \ + } __x = {.n = x}; \ + (uint64_t) __x.n; \ + }) -#define ROUNDUP(a, sz) ((((uintptr_t)a) + (sz) - 1) & ~((sz) - 1)) -#define ROUNDDOWN(a, sz) ((((uintptr_t)a)) & ~((sz) - 1)) +#define ROUNDUP(a, sz) ((((uintptr_t)a) + (sz)-1) & ~((sz)-1)) +#define ROUNDDOWN(a, sz) ((((uintptr_t)a)) & ~((sz)-1)) #define PG_ALIGN __attribute((aligned(4096))) -#define FAILED_GOTO(tag, exp) do {if((exp)) goto tag;} while(0) +#define FAILED_GOTO(tag, exp) \ + do { \ + if ((exp)) \ + goto tag; \ + } while (0) #if !defined(likely) -#define likely(cond) __builtin_expect(cond, 1) +#define likely(cond) __builtin_expect(cond, 1) #define unlikely(cond) __builtin_expect(cond, 0) #endif -// for AM IOE -#define io_read(reg) \ - ({ reg##_T __io_param; \ - ioe_read(reg, &__io_param); \ - __io_param; }) +#define __EXPORT __attribute__((visibility("default"))) -#define io_write(reg, ...) \ - ({ reg##_T __io_param = (reg##_T) { __VA_ARGS__ }; \ - ioe_write(reg, &__io_param); }) +// for AM IOE +#define io_read(reg) \ + ({ \ + reg##_T __io_param; \ + ioe_read(reg, &__io_param); \ + __io_param; \ + }) + +#define io_write(reg, ...) \ + ({ \ + reg##_T __io_param = (reg##_T){__VA_ARGS__}; \ + ioe_write(reg, &__io_param); \ + }) #endif diff --git a/nemu/include/nemu.h b/nemu/include/nemu.h new file mode 100644 index 0000000..505fc52 --- /dev/null +++ b/nemu/include/nemu.h @@ -0,0 +1,28 @@ +#ifndef __NEMU_HEADER__ +#define __NEMU_HEADER__ + +#include +#ifdef __cplusplus +extern "C" { +#endif +#include +#ifdef __cplusplus +} +#endif + +int nemu_read_mem(void *args, size_t addr, size_t len, void *val); +int nemu_write_mem(void *args, size_t addr, size_t len, void *val); +void nemu_cont(void *args, gdb_action_t *res); +void nemu_stepi(void *args, gdb_action_t *res); +bool nemu_set_bp(void *args, size_t addr, bp_type_t type); +bool nemu_del_bp(void *args, size_t addr, bp_type_t type); +void nemu_on_interrupt(void *args); +int nemu_read_reg(void *args, int regno, size_t *data); +int nemu_write_reg(void *args, int regno, size_t data); +void nemu_init(void *args); + +extern arch_info_t nemu_isa_arch_info; +extern bool nemu_do_difftest; +extern bool nemu_dbg_state_size; + +#endif // __NEMU_HEADER__ diff --git a/nemu/src/cpu/cpu-exec.c b/nemu/src/cpu/cpu-exec.c index f4be925..583013e 100644 --- a/nemu/src/cpu/cpu-exec.c +++ b/nemu/src/cpu/cpu-exec.c @@ -16,7 +16,6 @@ #include "gdbstub.h" #include #include -#include #include #include diff --git a/nemu/src/cpu/difftest/dut.c b/nemu/src/cpu/difftest/dut.c deleted file mode 100644 index b003202..0000000 --- a/nemu/src/cpu/difftest/dut.c +++ /dev/null @@ -1,132 +0,0 @@ -/*************************************************************************************** -* Copyright (c) 2014-2022 Zihao Yu, Nanjing University -* -* NEMU is licensed under Mulan PSL v2. -* You can use this software according to the terms and conditions of the Mulan PSL v2. -* You may obtain a copy of Mulan PSL v2 at: -* http://license.coscl.org.cn/MulanPSL2 -* -* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, -* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, -* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. -* -* See the Mulan PSL v2 for more details. -***************************************************************************************/ - -#include - -#include -#include -#include -#include -#include - -void (*ref_difftest_memcpy)(paddr_t addr, void *buf, size_t n, bool direction) = NULL; -void (*ref_difftest_regcpy)(void *dut, bool direction) = NULL; -void (*ref_difftest_exec)(uint64_t n) = NULL; -void (*ref_difftest_raise_intr)(uint64_t NO) = NULL; - -#ifdef CONFIG_DIFFTEST - -static bool is_skip_ref = false; -static int skip_dut_nr_inst = 0; - -// this is used to let ref skip instructions which -// can not produce consistent behavior with NEMU -void difftest_skip_ref() { - is_skip_ref = true; - // If such an instruction is one of the instruction packing in QEMU - // (see below), we end the process of catching up with QEMU's pc to - // keep the consistent behavior in our best. - // Note that this is still not perfect: if the packed instructions - // already write some memory, and the incoming instruction in NEMU - // will load that memory, we will encounter false negative. But such - // situation is infrequent. - skip_dut_nr_inst = 0; -} - -// this is used to deal with instruction packing in QEMU. -// Sometimes letting QEMU step once will execute multiple instructions. -// We should skip checking until NEMU's pc catches up with QEMU's pc. -// The semantic is -// Let REF run `nr_ref` instructions first. -// We expect that DUT will catch up with REF within `nr_dut` instructions. -void difftest_skip_dut(int nr_ref, int nr_dut) { - skip_dut_nr_inst += nr_dut; - - while (nr_ref -- > 0) { - ref_difftest_exec(1); - } -} - -void init_difftest(char *ref_so_file, long img_size, int port) { - assert(ref_so_file != NULL); - - void *handle; - handle = dlopen(ref_so_file, RTLD_LAZY); - assert(handle); - - ref_difftest_memcpy = dlsym(handle, "difftest_memcpy"); - assert(ref_difftest_memcpy); - - ref_difftest_regcpy = dlsym(handle, "difftest_regcpy"); - assert(ref_difftest_regcpy); - - ref_difftest_exec = dlsym(handle, "difftest_exec"); - assert(ref_difftest_exec); - - ref_difftest_raise_intr = dlsym(handle, "difftest_raise_intr"); - assert(ref_difftest_raise_intr); - - void (*ref_difftest_init)(int) = dlsym(handle, "difftest_init"); - assert(ref_difftest_init); - - Log("Differential testing: %s", ANSI_FMT("ON", ANSI_FG_GREEN)); - Log("The result of every instruction will be compared with %s. " - "This will help you a lot for debugging, but also significantly reduce the performance. " - "If it is not necessary, you can turn it off in menuconfig.", ref_so_file); - - ref_difftest_init(port); - ref_difftest_memcpy(RESET_VECTOR, guest_to_host(RESET_VECTOR), img_size, DIFFTEST_TO_REF); - ref_difftest_regcpy(&cpu, DIFFTEST_TO_REF); -} - -static void checkregs(CPU_state *ref, vaddr_t pc) { - if (!isa_difftest_checkregs(ref, pc)) { - nemu_state.state = NEMU_ABORT; - nemu_state.halt_pc = pc; - isa_reg_display(); - } -} - -void difftest_step(vaddr_t pc, vaddr_t npc) { - CPU_state ref_r; - - if (skip_dut_nr_inst > 0) { - ref_difftest_regcpy(&ref_r, DIFFTEST_TO_DUT); - if (ref_r.pc == npc) { - skip_dut_nr_inst = 0; - checkregs(&ref_r, npc); - return; - } - skip_dut_nr_inst --; - if (skip_dut_nr_inst == 0) - panic("can not catch up with ref.pc = " FMT_WORD " at pc = " FMT_WORD, ref_r.pc, pc); - return; - } - - if (is_skip_ref) { - // to skip the checking of an instruction, just copy the reg state to reference design - ref_difftest_regcpy(&cpu, DIFFTEST_TO_REF); - is_skip_ref = false; - return; - } - - ref_difftest_exec(1); - ref_difftest_regcpy(&ref_r, DIFFTEST_TO_DUT); - - checkregs(&ref_r, pc); -} -#else -void init_difftest(char *ref_so_file, long img_size, int port) { } -#endif diff --git a/nemu/src/cpu/difftest/ref.c b/nemu/src/cpu/difftest/ref.c deleted file mode 100644 index 3f44732..0000000 --- a/nemu/src/cpu/difftest/ref.c +++ /dev/null @@ -1,51 +0,0 @@ -/*************************************************************************************** -* Copyright (c) 2014-2022 Zihao Yu, Nanjing University -* -* NEMU is licensed under Mulan PSL v2. -* You can use this software according to the terms and conditions of the Mulan PSL v2. -* You may obtain a copy of Mulan PSL v2 at: -* http://license.coscl.org.cn/MulanPSL2 -* -* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, -* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, -* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. -* -* See the Mulan PSL v2 for more details. -***************************************************************************************/ - -#include "types.h" -#include -#include -#include -#include -#include - -__EXPORT void difftest_memcpy(paddr_t addr, void *buf, size_t n, - bool direction) { - if (direction == DIFFTEST_TO_REF) { - memcpy(guest_to_host(addr), buf, n); - } else { - memcpy(buf, guest_to_host(addr), n); - } -} - -__EXPORT void difftest_regcpy(void *dut, bool direction) { - // assert(0); - if (direction == DIFFTEST_TO_DUT) - memcpy(dut, &cpu, sizeof(CPU_state)); - else - memcpy(&cpu, dut, sizeof(CPU_state)); -} - -__EXPORT void difftest_exec(uint64_t n) { cpu_exec(n); } - -__EXPORT void difftest_raise_intr(word_t NO) { - // assert(0); -} - -__EXPORT void difftest_init(int port) { - void init_mem(); - init_mem(); - /* Perform ISA dependent initialization. */ - init_isa(); -} diff --git a/nemu/src/device/io/port-io.c b/nemu/src/device/io/port-io.c index ba6977b..a2d502d 100644 --- a/nemu/src/device/io/port-io.c +++ b/nemu/src/device/io/port-io.c @@ -13,6 +13,8 @@ * See the Mulan PSL v2 for more details. ***************************************************************************************/ +#include +#include #include #define PORT_IO_SPACE_MAX 65535 @@ -22,15 +24,19 @@ static IOMap maps[NR_MAP] = {}; static int nr_map = 0; /* device interface */ -void add_pio_map(const char *name, ioaddr_t addr, void *space, uint32_t len, io_callback_t callback) { +void add_pio_map(const char *name, ioaddr_t addr, void *space, uint32_t len, + io_callback_t callback) { assert(nr_map < NR_MAP); assert(addr + len <= PORT_IO_SPACE_MAX); - maps[nr_map] = (IOMap){ .name = name, .low = addr, .high = addr + len - 1, - .space = space, .callback = callback }; + maps[nr_map] = (IOMap){.name = name, + .low = addr, + .high = addr + len - 1, + .space = space, + .callback = callback}; Log("Add port-io map '%s' at [" FMT_PADDR ", " FMT_PADDR "]", maps[nr_map].name, maps[nr_map].low, maps[nr_map].high); - nr_map ++; + nr_map++; } /* CPU interface */ diff --git a/nemu/src/device/serial.c b/nemu/src/device/serial.c index b181c5f..ad437e8 100644 --- a/nemu/src/device/serial.c +++ b/nemu/src/device/serial.c @@ -13,8 +13,10 @@ * See the Mulan PSL v2 for more details. ***************************************************************************************/ -#include +#include +#include #include +#include /* http://en.wikibooks.org/wiki/Serial_Programming/8250_UART_Programming */ // NOTE: this is compatible to 16550 @@ -23,7 +25,6 @@ static uint8_t *serial_base = NULL; - static void serial_putc(char ch) { MUXDEF(CONFIG_TARGET_AM, putch(ch), putc(ch, stderr)); } @@ -31,21 +32,23 @@ static void serial_putc(char ch) { static void serial_io_handler(uint32_t offset, int len, bool is_write) { assert(len == 1); switch (offset) { - /* We bind the serial port with the host stderr in NEMU. */ - case CH_OFFSET: - if (is_write) serial_putc(serial_base[0]); - else panic("do not support read"); - break; - default: panic("do not support offset = %d", offset); + /* We bind the serial port with the host stderr in NEMU. */ + case CH_OFFSET: + if (is_write) + serial_putc(serial_base[0]); + else + panic("do not support read"); + break; + default: + panic("do not support offset = %d", offset); } } void init_serial() { serial_base = new_space(8); #ifdef CONFIG_HAS_PORT_IO - add_pio_map ("serial", CONFIG_SERIAL_PORT, serial_base, 8, serial_io_handler); + add_pio_map("serial", CONFIG_SERIAL_PORT, serial_base, 8, serial_io_handler); #else add_mmio_map("serial", CONFIG_SERIAL_MMIO, serial_base, 8, serial_io_handler); #endif - } diff --git a/nemu/src/device/timer.c b/nemu/src/device/timer.c index 2aff819..23c2d49 100644 --- a/nemu/src/device/timer.c +++ b/nemu/src/device/timer.c @@ -13,8 +13,9 @@ * See the Mulan PSL v2 for more details. ***************************************************************************************/ -#include +#include #include +#include #include static uint32_t *rtc_port_base = NULL; @@ -40,7 +41,7 @@ static void timer_intr() { void init_timer() { rtc_port_base = (uint32_t *)new_space(8); #ifdef CONFIG_HAS_PORT_IO - add_pio_map ("rtc", CONFIG_RTC_PORT, rtc_port_base, 8, rtc_io_handler); + add_pio_map("rtc", CONFIG_RTC_PORT, rtc_port_base, 8, rtc_io_handler); #else add_mmio_map("rtc", CONFIG_RTC_MMIO, rtc_port_base, 8, rtc_io_handler); #endif diff --git a/nemu/src/engine/interpreter/hostcall.c b/nemu/src/engine/interpreter/hostcall.c index d37d5b5..a0ab112 100644 --- a/nemu/src/engine/interpreter/hostcall.c +++ b/nemu/src/engine/interpreter/hostcall.c @@ -13,20 +13,19 @@ * See the Mulan PSL v2 for more details. ***************************************************************************************/ -#include #include +#include #include -#include +#include void set_nemu_state(int state, vaddr_t pc, int halt_ret) { - difftest_skip_ref(); + nemu_do_difftest = false; nemu_state.state = state; nemu_state.halt_pc = pc; nemu_state.halt_ret = halt_ret; } -__attribute__((noinline)) -void invalid_inst(vaddr_t thispc) { +__attribute__((noinline)) void invalid_inst(vaddr_t thispc) { uint32_t temp[2]; vaddr_t pc = thispc; temp[0] = inst_fetch(&pc, 4); @@ -34,18 +33,24 @@ void invalid_inst(vaddr_t thispc) { uint8_t *p = (uint8_t *)temp; printf("invalid opcode(PC = " FMT_WORD "):\n" - "\t%02x %02x %02x %02x %02x %02x %02x %02x ...\n" - "\t%08x %08x...\n", - thispc, p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7], temp[0], temp[1]); + "\t%02x %02x %02x %02x %02x %02x %02x %02x ...\n" + "\t%08x %08x...\n", + thispc, p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7], temp[0], + temp[1]); printf("There are two cases which will trigger this unexpected exception:\n" - "1. The instruction at PC = " FMT_WORD " is not implemented.\n" - "2. Something is implemented incorrectly.\n", thispc); - printf("Find this PC(" FMT_WORD ") in the disassembling result to distinguish which case it is.\n\n", thispc); + "1. The instruction at PC = " FMT_WORD " is not implemented.\n" + "2. Something is implemented incorrectly.\n", + thispc); + printf("Find this PC(" FMT_WORD + ") in the disassembling result to distinguish which case it is.\n\n", + thispc); printf(ANSI_FMT("If it is the first case, see\n%s\nfor more details.\n\n" - "If it is the second case, remember:\n" - "* The machine is always right!\n" - "* Every line of untested code is always wrong!\n\n", ANSI_FG_RED), isa_logo); + "If it is the second case, remember:\n" + "* The machine is always right!\n" + "* Every line of untested code is always wrong!\n\n", + ANSI_FG_RED), + isa_logo); set_nemu_state(NEMU_ABORT, thispc, -1); } diff --git a/nemu/src/engine/interpreter/init.c b/nemu/src/engine/interpreter/init.c index fed4923..ab07185 100644 --- a/nemu/src/engine/interpreter/init.c +++ b/nemu/src/engine/interpreter/init.c @@ -17,17 +17,22 @@ #include #include -void sdb_mainloop(); +int gdbstub_loop(); +extern bool enable_gdbstub; void engine_start() { #ifdef CONFIG_TARGET_AM cpu_exec(-1); #else /* Receive commands from user. */ - int nemu_gdbstub_run(); - if (nemu_gdbstub_run()) { - Error("gdbstub exited abnormally"); - exit(1); + int ret = 0; + if (enable_gdbstub) { + if ((ret = gdbstub_loop())) { + Error("gdbstub exited abnormally"); + exit(ret); + } + } else { + cpu_exec(-1); } #endif } diff --git a/nemu/src/isa/riscv32/difftest/dut.c b/nemu/src/isa/riscv32/difftest/dut.c deleted file mode 100644 index 06748ce..0000000 --- a/nemu/src/isa/riscv32/difftest/dut.c +++ /dev/null @@ -1,28 +0,0 @@ -/*************************************************************************************** -* Copyright (c) 2014-2022 Zihao Yu, Nanjing University -* -* NEMU is licensed under Mulan PSL v2. -* You can use this software according to the terms and conditions of the Mulan PSL v2. -* You may obtain a copy of Mulan PSL v2 at: -* http://license.coscl.org.cn/MulanPSL2 -* -* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, -* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, -* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. -* -* See the Mulan PSL v2 for more details. -***************************************************************************************/ - -#include -#include -#include "../local-include/reg.h" - -bool isa_difftest_checkregs(CPU_state *ref_r, vaddr_t pc) { - for(int i = 0; i < MUXDEF(CONFIG_RVE, 16, 32); i++) { - if(!difftest_check_reg(reg_name(i), pc, ref_r->gpr[i], gpr(i))) return false; - } - return true; -} - -void isa_difftest_attach() { -} diff --git a/nemu/src/isa/riscv32/reg.c b/nemu/src/isa/riscv32/reg.c index c15d349..fe96b86 100644 --- a/nemu/src/isa/riscv32/reg.c +++ b/nemu/src/isa/riscv32/reg.c @@ -15,7 +15,6 @@ #include "local-include/reg.h" #include "macro.h" -#include #include #include #include diff --git a/nemu/src/monitor/gdbstub.cc b/nemu/src/monitor/gdbstub.cc index 81ca433..5905ef4 100644 --- a/nemu/src/monitor/gdbstub.cc +++ b/nemu/src/monitor/gdbstub.cc @@ -4,7 +4,6 @@ extern "C" { #include #include -#include #include #include #include @@ -17,6 +16,10 @@ typedef struct { bool halt; } DbgState; +__EXPORT size_t nemu_dbg_state_size = sizeof(DbgState); +__EXPORT bool nemu_do_difftest = true; +__EXPORT arch_info_t nemu_isa_arch_info; + __EXPORT int nemu_read_mem(void *args, size_t addr, size_t len, void *val) { if (!in_pmem(addr)) return EINVAL; @@ -109,7 +112,6 @@ __EXPORT int nemu_read_reg(void *args, int regno, size_t *data) { __EXPORT int nemu_write_reg(void *args, int regno, size_t data) { return isa_write_reg(args, regno, data); } -__EXPORT size_t argsize = sizeof(DbgState); static struct target_ops nemu_gdbstub_ops = {.cont = nemu_cont, .stepi = nemu_stepi, @@ -120,35 +122,41 @@ static struct target_ops nemu_gdbstub_ops = {.cont = nemu_cont, .set_bp = nemu_set_bp, .del_bp = nemu_del_bp, .on_interrupt = NULL}; -static DbgState dbg; +static DbgState *pdbg; static gdbstub_t gdbstub_priv; const char SOCKET_ADDR[] = "/tmp/gdbstub-nemu.sock"; -__EXPORT void nemu_init(void *args) { +static void init_remote_gdbstub(void *args) { DbgState *dbg_state = (DbgState *)args; + pdbg = (DbgState *)args; dbg_state->bp = new std::vector(); dbg_state->halt = 0; Assert(dbg_state->bp != NULL, "Failed to allocate breakpoint"); +} +__EXPORT void nemu_init(void *args) { + init_remote_gdbstub(args); + + void init_rand(); void init_mem(); + + IFDEF(CONFIG_DEVICE, void init_device()); + + init_rand(); init_mem(); + IFDEF(CONFIG_DEVICE, init_device()); + /* Perform ISA dependent initialization. */ init_isa(); } -__EXPORT int nemu_gdbstub_init() { - dbg.bp = new std::vector(); - assert(dbg.bp); +int gdbstub_loop() { if (!gdbstub_init(&gdbstub_priv, &nemu_gdbstub_ops, - (arch_info_t)isa_arch_info, strdup(SOCKET_ADDR))) { + (arch_info_t)isa_arch_info, SOCKET_ADDR)) { return EINVAL; } - return 0; -} - -__EXPORT int nemu_gdbstub_run() { printf("Waiting for gdb connection at %s", SOCKET_ADDR); - bool success = gdbstub_run(&gdbstub_priv, &dbg); + bool success = gdbstub_run(&gdbstub_priv, pdbg); // gdbstub_close(&gdbstub_priv); return !success; } diff --git a/nemu/src/monitor/monitor.c b/nemu/src/monitor/monitor.c index 264d463..b4b0dc1 100644 --- a/nemu/src/monitor/monitor.c +++ b/nemu/src/monitor/monitor.c @@ -13,9 +13,11 @@ * See the Mulan PSL v2 for more details. ***************************************************************************************/ +#include #include #include #include +#include #include #include @@ -25,7 +27,11 @@ void init_mem(); void init_difftest(char *ref_so_file, long img_size, int port); void init_device(); void init_disasm(const char *triple); -void nemu_init(); + +char *log_file = NULL; +char *elf_file = NULL; +char *img_file = NULL; +bool enable_gdbstub = false; static void welcome() { Log("Trace: %s", MUXDEF(CONFIG_TRACE, ANSI_FMT("ON", ANSI_FG_GREEN), @@ -43,12 +49,6 @@ static void welcome() { #ifndef CONFIG_TARGET_AM #include -static char *log_file = NULL; -static char *elf_file = NULL; -static char *diff_so_file = NULL; -static char *img_file = NULL; -static int difftest_port = 1234; - static long load_img() { FILE *fp = NULL; size_t img_filename_len = strlen(img_file); @@ -113,38 +113,30 @@ static long load_img() { static int parse_args(int argc, char *argv[]) { const struct option table[] = { - {"batch", no_argument, NULL, 'b'}, - {"log", required_argument, NULL, 'l'}, - {"diff", required_argument, NULL, 'd'}, - {"port", required_argument, NULL, 'p'}, - {"elf", required_argument, NULL, 'f'}, - {"help", no_argument, NULL, 'h'}, - {0, 0, NULL, 0}, + {"batch", no_argument, NULL, 'b'}, {"log", required_argument, NULL, 'l'}, + {"debug", no_argument, NULL, 'g'}, {"elf", required_argument, NULL, 'f'}, + {"help", no_argument, NULL, 'h'}, {0, 0, NULL, 0}, }; int o; while ((o = getopt_long(argc, argv, "-bhl:d:p:", table, NULL)) != -1) { switch (o) { - case 'p': - sscanf(optarg, "%d", &difftest_port); - break; case 'l': log_file = optarg; break; - case 'd': - diff_so_file = optarg; - break; case 'f': elf_file = optarg; break; + case 'g': + enable_gdbstub = true; + break; case 1: img_file = optarg; return 0; default: printf("Usage: %s [OPTION...] IMAGE [args]\n\n", argv[0]); printf("\t-b,--batch run with batch mode\n"); + printf("\t-g,--debug enable gdb remote server\n"); printf("\t-l,--log=FILE output log to FILE\n"); - printf("\t-d,--diff=REF_SO run DiffTest with reference REF_SO\n"); - printf("\t-p,--port=PORT run DiffTest with port PORT\n"); printf("\t-f,--elf=FILE elf file with debug info\n"); printf("\n"); exit(0); @@ -154,38 +146,18 @@ static int parse_args(int argc, char *argv[]) { } void init_monitor(int argc, char *argv[]) { - /* Perform some global initialization. */ - /* Parse arguments. */ parse_args(argc, argv); - /* Set random seed. */ - init_rand(); - + void init_log(const char *log_file); /* Open the log file. */ init_log(log_file); - /* Initialize memory. */ - init_mem(); - - /* Initialize devices. */ - IFDEF(CONFIG_DEVICE, init_device()); - - /* Perform ISA dependent initialization. */ - init_isa(); + /* Perform some global initialization. */ + nemu_init(malloc(nemu_dbg_state_size)); /* Load the image to memory. This will overwrite the built-in image. */ - long img_size = load_img(); - - /* Initialize differential testing. */ - init_difftest(diff_so_file, img_size, difftest_port); - - /* Initialize debugger */ - // if (nemu_init()) { - // Error("Failed to init"); - // exit(1); - // } - nemu_init(); + load_img(); // printf("elf_file: %s\n", elf_file); if (elf_file != NULL) {