Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion include/device/map.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
#include <cpu/difftest.h>

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;
Expand Down
25 changes: 25 additions & 0 deletions include/macro.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
16 changes: 7 additions & 9 deletions include/memory/host.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,22 +19,20 @@
#include <common.h>

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));
}
}

Expand Down
18 changes: 10 additions & 8 deletions src/device/io/map.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down Expand Up @@ -57,14 +59,14 @@ 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;
}

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);
}
22 changes: 16 additions & 6 deletions tools/kvm-diff/src/kvm.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <linux/kvm.h>
Expand Down Expand Up @@ -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;
Expand All @@ -247,15 +249,18 @@ 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;
return 1;
}
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;
Expand All @@ -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) {
Expand Down Expand Up @@ -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);
Expand Down