diff --git a/include/device/map.h b/include/device/map.h index 8420259b..bf6a0c41 100644 --- a/include/device/map.h +++ b/include/device/map.h @@ -19,7 +19,7 @@ #include typedef void(*io_callback_t)(uint32_t, int, bool); -uint8_t* new_space(int size); +void* new_space(int size); typedef struct { const char *name; diff --git a/include/macro.h b/include/macro.h index 6b102c21..aaac3525 100644 --- a/include/macro.h +++ b/include/macro.h @@ -108,3 +108,28 @@ ioe_write(reg, &__io_param); }) #endif + +/** + * @brief 对一个变量的位模式进行类型重解释,类似于 C++20 的 std::bit_cast。 + * @note 此宏使用了GCC/Clang的语句表达式扩展,以便在表达式中使用。 + * @param dest_type 目标类型。 + * @param src 源变量(不是指针)。 + * @return 一个类型为 dest_type 的新值,其位模式与 src 相同。 + */ +#if __STDC_VERSION__ >= 201112L +#define BITCAST(dest_type, src) \ + ({ \ + _Static_assert(sizeof(dest_type) == sizeof(src), "Bitcast types must have the same size"); \ + dest_type dest; \ + memcpy(&dest, &src, sizeof(dest)); \ + dest; \ + }) +#else +#define BITCAST(dest_type, src) \ + ({ \ + assert(sizeof(dest_type) == sizeof(src) && "Bitcast types must have the same size"); \ + dest_type dest; \ + memcpy(&dest, &src, sizeof(dest)); \ + dest; \ + }) +#endif diff --git a/include/memory/host.h b/include/memory/host.h index 433ef141..b9e6ea99 100644 --- a/include/memory/host.h +++ b/include/memory/host.h @@ -19,22 +19,20 @@ #include static inline word_t host_read(void *addr, int len) { + word_t ret = 0; switch (len) { - case 1: return *(uint8_t *)addr; - case 2: return *(uint16_t *)addr; - case 4: return *(uint32_t *)addr; - IFDEF(CONFIG_ISA64, case 8: return *(uint64_t *)addr); + case 1: case 2: case 4: IFDEF(CONFIG_ISA64, case 8: ) + memcpy(&ret, addr, len); break; default: MUXDEF(CONFIG_RT_CHECK, assert(0), return 0); } + return ret; } static inline void host_write(void *addr, int len, word_t data) { switch (len) { - case 1: *(uint8_t *)addr = data; return; - case 2: *(uint16_t *)addr = data; return; - case 4: *(uint32_t *)addr = data; return; - IFDEF(CONFIG_ISA64, case 8: *(uint64_t *)addr = data; return); - IFDEF(CONFIG_RT_CHECK, default: assert(0)); + case 1: case 2: case 4: IFDEF(CONFIG_ISA64, case 8: ) + memcpy(addr, &data, len); return; + default: IFDEF(CONFIG_RT_CHECK, assert(0)); } } diff --git a/src/device/io/map.c b/src/device/io/map.c index 6239b5a1..064fc670 100644 --- a/src/device/io/map.c +++ b/src/device/io/map.c @@ -20,15 +20,17 @@ #define IO_SPACE_MAX (32 * 1024 * 1024) -static uint8_t *io_space = NULL; -static uint8_t *p_space = NULL; +static void *io_space = NULL; +static void *p_space = NULL; -uint8_t* new_space(int size) { - uint8_t *p = p_space; +// 与malloc保持一致,由调用者决定以什么方式使用这块内存 +// 只要调用者不强转则不违反严格别名规则 +void *new_space(int size) { + void *p = p_space; // page aligned; size = (size + (PAGE_SIZE - 1)) & ~PAGE_MASK; - p_space += size; - assert(p_space - io_space < IO_SPACE_MAX); + p_space = (uint8_t *)p_space + size ; + assert((uint8_t *)p_space - (uint8_t *)io_space < IO_SPACE_MAX); return p; } @@ -57,7 +59,7 @@ word_t map_read(paddr_t addr, int len, IOMap *map) { check_bound(map, addr); paddr_t offset = addr - map->low; invoke_callback(map->callback, offset, len, false); // prepare data to read - word_t ret = host_read(map->space + offset, len); + word_t ret = host_read((uint8_t *)map->space + offset, len); return ret; } @@ -65,6 +67,6 @@ void map_write(paddr_t addr, int len, word_t data, IOMap *map) { assert(len >= 1 && len <= 8); check_bound(map, addr); paddr_t offset = addr - map->low; - host_write(map->space + offset, len, data); + host_write((uint8_t *)map->space + offset, len, data); invoke_callback(map->callback, offset, len, true); } diff --git a/tools/kvm-diff/src/kvm.c b/tools/kvm-diff/src/kvm.c index 1e86d35d..f3f4ad45 100644 --- a/tools/kvm-diff/src/kvm.c +++ b/tools/kvm-diff/src/kvm.c @@ -20,6 +20,7 @@ #include #include +#include #include #include #include @@ -238,7 +239,8 @@ static int patching() { if (vcpu.int_wp_state == STATE_INT_INST) return 0; vcpu.kvm_run->s.regs.regs.rsp -= 4; uint32_t esp = va2pa(vcpu.kvm_run->s.regs.regs.rsp); - *(uint32_t *)(vm.mem + esp) = vcpu.kvm_run->s.regs.regs.rflags & ~RFLAGS_FIX_MASK; + uint32_t rflags_val = vcpu.kvm_run->s.regs.regs.rflags & ~RFLAGS_FIX_MASK; + memcpy(vm.mem + esp, &rflags_val, sizeof(rflags_val)); vcpu.kvm_run->s.regs.regs.rflags |= RFLAGS_TF; vcpu.kvm_run->s.regs.regs.rip ++; vcpu.kvm_run->kvm_dirty_regs = KVM_SYNC_X86_REGS; @@ -247,7 +249,9 @@ static int patching() { else if (vm.mem[pc] == 0x9d) { // popf if (vcpu.int_wp_state == STATE_INT_INST) return 0; uint32_t esp = va2pa(vcpu.kvm_run->s.regs.regs.rsp); - vcpu.kvm_run->s.regs.regs.rflags = *(uint32_t *)(vm.mem + esp) | RFLAGS_TF | 2; + uint32_t value_from_mem; + memcpy(&value_from_mem, vm.mem + esp, sizeof(value_from_mem)); + vcpu.kvm_run->s.regs.regs.rflags = value_from_mem | RFLAGS_TF | 2; vcpu.kvm_run->s.regs.regs.rsp += 4; vcpu.kvm_run->s.regs.regs.rip ++; vcpu.kvm_run->kvm_dirty_regs = KVM_SYNC_X86_REGS; @@ -255,7 +259,8 @@ static int patching() { } else if (vm.mem[pc] == 0xcf) { // iret uint32_t ret_addr = va2pa(vcpu.kvm_run->s.regs.regs.rsp); - uint32_t eip = *(uint32_t *)(vm.mem + ret_addr); + uint32_t eip = 0; + memcpy(&eip, vm.mem + ret_addr, sizeof(eip)); vcpu.entry = eip; kvm_set_step_mode(true, eip); vcpu.int_wp_state = STATE_IRET_INST; @@ -266,7 +271,10 @@ static int patching() { static void fix_push_sreg() { uint32_t esp = va2pa(vcpu.kvm_run->s.regs.regs.rsp); - *(uint32_t *)(vm.mem + esp) &= 0x0000ffff; + uint32_t value_from_mem = 0; + memcpy(&value_from_mem, vm.mem + esp, sizeof(value_from_mem)); + value_from_mem &= 0x0000ffff; + memcpy(vm.mem + esp, &value_from_mem, sizeof(value_from_mem)); } static void patching_after(uint64_t last_pc) { @@ -310,8 +318,10 @@ static void kvm_exec(uint64_t n) { if (vcpu.int_wp_state == STATE_INT_INST) { uint32_t eflag_offset = 8 + (vcpu.has_error_code ? 4 : 0); uint32_t eflag_addr = va2pa(vcpu.kvm_run->s.regs.regs.rsp + eflag_offset); - *(uint32_t *)(vm.mem + eflag_addr) &= ~RFLAGS_FIX_MASK; - + uint32_t value_from_mem = 0; + memcpy(&value_from_mem, vm.mem + eflag_addr, sizeof(value_from_mem)); + value_from_mem &= ~RFLAGS_FIX_MASK; + memcpy(vm.mem + eflag_addr, &value_from_mem, sizeof(value_from_mem)); Assert(vcpu.entry == vcpu.kvm_run->debug.arch.pc, "entry not match, right = 0x%llx, wrong = 0x%x", vcpu.kvm_run->debug.arch.pc, vcpu.entry); kvm_set_step_mode(false, 0);