diff --git a/Kconfig b/Kconfig index 2425ecda8..4f6603187 100644 --- a/Kconfig +++ b/Kconfig @@ -519,3 +519,18 @@ config ENABLE_INSTR_CNT default n endmenu + + +menu "memtrace" +config MEMTRACE + depends on !USE_SPARSEMM + bool "start memtrace" + default n + +config MEMTRACE_PATH + depends on MEMTRACE + string "memtrace log output path" + default "tmp/memtrace.gz" + help + Set the output path for memtrace log file. +endmenu diff --git a/configs/riscv64-xs-cpt_defconfig b/configs/riscv64-xs-cpt_defconfig index 77f82f842..fc1968970 100644 --- a/configs/riscv64-xs-cpt_defconfig +++ b/configs/riscv64-xs-cpt_defconfig @@ -70,10 +70,11 @@ CONFIG_PMA_GRANULARITY=12 # PMA Check Disabled when enabling PERF_OPT # CONFIG_RV_SVINVAL=y -# CONFIG_RV_SV39 is not set -CONFIG_RV_SV48=y +# CONFIG_RV_SV48 is not set +CONFIG_RV_SV39=y CONFIG_RV_ASID_LEN=16 CONFIG_RV_VMID_LEN=14 + CONFIG_RV_SSNPM=y CONFIG_RV_SMNPM=y CONFIG_RV_SMMPM=y @@ -230,3 +231,5 @@ CONFIG_INSTR_CNT_BY_BB=y # CONFIG_INSTR_CNT_BY_INSTR_PERF_OPT is not set CONFIG_ENABLE_INSTR_CNT=y # end of Miscellaneous + +CONFIG_MEMTRACE=n \ No newline at end of file diff --git a/configs/riscv64-xs_defconfig b/configs/riscv64-xs_defconfig index e29929eb8..0cab3ea34 100644 --- a/configs/riscv64-xs_defconfig +++ b/configs/riscv64-xs_defconfig @@ -78,10 +78,11 @@ CONFIG_PMA_GRANULARITY=12 # PMA Check Disabled when enabling PERF_OPT # CONFIG_RV_SVINVAL=y -# CONFIG_RV_SV39 is not set -CONFIG_RV_SV48=y +# CONFIG_RV_SV48 is not set +CONFIG_RV_SV39=y CONFIG_RV_ASID_LEN=16 CONFIG_RV_VMID_LEN=14 + CONFIG_RV_SSNPM=y CONFIG_RV_SMNPM=y CONFIG_RV_SMMPM=y @@ -240,3 +241,6 @@ CONFIG_INSTR_CNT_BY_BB=y # CONFIG_INSTR_CNT_BY_INSTR_PERF_OPT is not set CONFIG_ENABLE_INSTR_CNT=y # end of Miscellaneous + + +CONFIG_MEMTRACE=n \ No newline at end of file diff --git a/include/checkpoint/serializer.h b/include/checkpoint/serializer.h index 82956846c..76e78cab5 100644 --- a/include/checkpoint/serializer.h +++ b/include/checkpoint/serializer.h @@ -23,6 +23,7 @@ #include #include #include "generated/autoconf.h" +#include #ifdef CONFIG_LIBCHECKPOINT_RESTORER extern "C" { diff --git a/include/utils.h b/include/utils.h index 04e99c27b..118a8937b 100644 --- a/include/utils.h +++ b/include/utils.h @@ -136,4 +136,29 @@ bool is_zstd_file(const char *filename); } #endif + +typedef struct pkt_data_used_small{ + uint64_t addr; + bool cmdstr; +} pkt_data_used_small; + + +#ifdef __cplusplus +extern "C" { +#endif + +extern const char* get_memtrace_file_path(); +void memtrace_flush(); +void memtrace_trapflush(); +void memtrace_dump(pkt_data_used_small temp); + +#ifdef __cplusplus +} +#endif + + + + + + #endif diff --git a/src/checkpoint/serializer.cpp b/src/checkpoint/serializer.cpp index a8b992385..8ba0ebd6d 100644 --- a/src/checkpoint/serializer.cpp +++ b/src/checkpoint/serializer.cpp @@ -145,6 +145,13 @@ extern void log_file_flush(); extern unsigned long MEMORY_SIZE; } +#ifdef CONFIG_MEMTRACE +string memtrace_file_path; +extern "C" const char* get_memtrace_file_path() { + return memtrace_file_path.c_str(); +} +#endif + #ifdef CONFIG_MEM_COMPRESS void Serializer::serializePMem(uint64_t inst_count, uint8_t *pmem_addr, uint8_t *flash_addr) { // We must dump registers before memory to store them in the Generic Arch CPT @@ -317,6 +324,15 @@ void Serializer::serializePMem(uint64_t inst_count, uint8_t *pmem_addr, uint8_t xpanic("You need to specify the compress file format using: --checkpoint-format\n"); } + + + #ifdef CONFIG_MEMTRACE + memtrace_file_path = pathManager.getOutputPath() + "memtrace.gz"; + memtrace_flush(); + Log("Memtrace dumped to %s\n", memtrace_file_path.c_str()); + #endif + + Log("Checkpoint done!\n"); regDumped = false; } @@ -479,6 +495,14 @@ void Serializer::init(bool store_cpt_in_flash) { #endif this->store_cpt_in_flash = store_cpt_in_flash; + + #ifdef CONFIG_MEMTRACE + if (std::remove(CONFIG_MEMTRACE_PATH) == 0) { + fprintf(stderr, "memtrace file error: %s\n", CONFIG_MEMTRACE_PATH); + } else { + fprintf(stderr, "memtrace file error: %s\n", CONFIG_MEMTRACE_PATH); + } + #endif #ifdef CONFIG_LIBCHECKPOINT_RESTORER this->enable_libcheckpoint = enable_libcheckpoint; @@ -526,7 +550,7 @@ void Serializer::init(bool store_cpt_in_flash) { assert(checkpoint_interval); intervalSize = checkpoint_interval; Log("Taking uniform checkpionts with interval %lu", checkpoint_interval); - nextUniformPoint = intervalSize; + nextUniformPoint = 0; } pathManager.setCheckpointingOutputDir(); } diff --git a/src/isa/riscv64/instr/special.h b/src/isa/riscv64/instr/special.h index 9a00b16c4..b0a0931e9 100644 --- a/src/isa/riscv64/instr/special.h +++ b/src/isa/riscv64/instr/special.h @@ -48,6 +48,9 @@ def_EHelper(nemu_trap) { } } else { rtl_hostcall(s, HOSTCALL_EXIT,NULL, &cpu.gpr[10]._64, NULL, 0); // gpr[10] is $a0 + #ifdef CONFIG_MEMTRACE + memtrace_trapflush(); + #endif longjmp_context(NEMU_EXEC_END); } } diff --git a/src/memory/host-tlb.c b/src/memory/host-tlb.c index 559e2d328..ca0f0bdd4 100644 --- a/src/memory/host-tlb.c +++ b/src/memory/host-tlb.c @@ -130,7 +130,12 @@ word_t hosttlb_read(struct Decode *s, vaddr_t vaddr, int len, int type) { #ifdef CONFIG_USE_SPARSEMM return sparse_mem_wread(get_sparsemm(), (vaddr_t)e->offset + vaddr, len); #else - return host_read(e->offset + vaddr, len); + uint8_t* host_addr = (e->offset + vaddr); + #ifdef CONFIG_MEMTRACE + pkt_data_used_small pkt ={host_to_guest(host_addr), 0}; + memtrace_dump(pkt); + #endif + return host_read(host_addr, len); #endif } } @@ -181,6 +186,10 @@ void hosttlb_write(struct Decode *s, vaddr_t vaddr, int len, word_t data) { // Also do store commit check with performance optimization enlabled store_commit_queue_push(host_to_guest(host_addr), data, len, 0); #endif // CONFIG_DIFFTEST_STORE_COMMIT + #ifdef CONFIG_MEMTRACE + pkt_data_used_small pkt ={host_to_guest(host_addr), 1}; + memtrace_dump(pkt); + #endif host_write(host_addr, len, data); #endif // NOT CONFIG_USE_SPARSEMM } diff --git a/src/memory/paddr.c b/src/memory/paddr.c index eb0948613..9ae7cbd72 100644 --- a/src/memory/paddr.c +++ b/src/memory/paddr.c @@ -98,6 +98,15 @@ static inline word_t pmem_read(paddr_t addr, int len) { #ifdef CONFIG_MEMORY_REGION_ANALYSIS analysis_memory_commit(addr); #endif + + #ifdef CONFIG_MEMTRACE + pkt_data_used_small pkt ={addr, 0}; + memtrace_dump(pkt); + static uint64_t read_count = 0; + read_count++; + + #endif + #ifdef CONFIG_USE_SPARSEMM return sparse_mem_wread(sparse_mm, addr, len); #else @@ -106,6 +115,11 @@ static inline word_t pmem_read(paddr_t addr, int len) { } static inline void pmem_write(paddr_t addr, int len, word_t data, int cross_page_store) { +#ifdef CONFIG_MEMTRACE +pkt_data_used_small pkt ={addr, 1}; +memtrace_dump(pkt); +#endif + #ifdef CONFIG_DIFFTEST_STORE_COMMIT store_commit_queue_push(addr, data, len, cross_page_store); #endif diff --git a/src/memory/vaddr.c b/src/memory/vaddr.c index ca2e05bc3..abfceabcf 100644 --- a/src/memory/vaddr.c +++ b/src/memory/vaddr.c @@ -170,7 +170,6 @@ static void vaddr_mmu_write(struct Decode *s, vaddr_t addr, int len, word_t data #endif // ENABLE_HOSTTLB static inline word_t vaddr_read_internal(void *s, vaddr_t addr, int len, int type, int mmu_mode) { - #ifdef CONFIG_RVH // check whether here is a hlvx instruction // when inst fetch or vaddr_read_safe (for examine memory), s is NULL diff --git a/src/utils/memtrace.c b/src/utils/memtrace.c new file mode 100644 index 000000000..db9444bb2 --- /dev/null +++ b/src/utils/memtrace.c @@ -0,0 +1,51 @@ +#include +#ifdef CONFIG_MEMTRACE +#include +#include +#define MEMTRACE_BUF_SIZE 65536 + +static pkt_data_used_small memtrace_buf[MEMTRACE_BUF_SIZE]; +static int memtrace_buf_count = 0; + +extern const char* get_memtrace_file_path(); + +void memtrace_dump(pkt_data_used_small temp) +{ +#ifdef CONFIG_MEMTRACE + memtrace_buf[memtrace_buf_count++] = temp; + if (memtrace_buf_count >= MEMTRACE_BUF_SIZE) { + gzFile appendFile = gzopen(CONFIG_MEMTRACE_PATH, "ab"); + gzwrite(appendFile, memtrace_buf, sizeof(memtrace_buf)); + gzclose(appendFile); + memtrace_buf_count = 0; + } +#endif +} + +void memtrace_flush() +{ +#ifdef CONFIG_MEMTRACE + if (memtrace_buf_count > 0) { + rename(CONFIG_MEMTRACE_PATH, get_memtrace_file_path()); + gzFile appendFile = gzopen(get_memtrace_file_path(), "ab"); + Log("memtrace_flush: %d", memtrace_buf_count); + gzwrite(appendFile, memtrace_buf, memtrace_buf_count * sizeof(pkt_data_used_small)); + gzclose(appendFile); + memtrace_buf_count = 0; + } +#endif +} + +void memtrace_trapflush() +{ +#ifdef CONFIG_MEMTRACE + if (memtrace_buf_count > 0) { + gzFile appendFile = gzopen(CONFIG_MEMTRACE_PATH, "ab"); + Log("memtrace_flush: %d", memtrace_buf_count); + gzwrite(appendFile, memtrace_buf, memtrace_buf_count * sizeof(pkt_data_used_small)); + gzclose(appendFile); + memtrace_buf_count = 0; + } +#endif +} +#endif \ No newline at end of file