$(EXTRA_C_OPTS) \
$(VMM_FLAGS) \
-I$(PROJECT_ROOT)/include \
- -fPIC \
-Werror \
-Wp,-MD,$(@D)/.$(@F).d \
-Wp,-MT,$@ \
+#-fPIC \
#-fvisibility=hidden
struct v3_dbg_regs dbg_regs;
struct v3_segments segments;
- struct emulation_state emulator;
-
v3_vm_operating_mode_t run_state;
void * vmm_data;
+ void * decoder_state;
+
struct v3_msr guest_efer;
/* TEMP */
/* utility definitions */
-#ifdef VMM_DEBUG
+
#define PrintDebug(fmt, args...) \
do { \
extern struct v3_os_hooks * os_hooks; \
(os_hooks)->print_debug((fmt), ##args); \
} \
} while (0)
+
+#if 1
#else
#define PrintDebug(fmt,args ...)
#endif
#include <palacios/vmm.h>
+typedef enum { V3_INVALID_OP,
+ V3_OP_MOVCR2, V3_OP_MOV2CR, V3_OP_SMSW, V3_OP_LMSW, V3_OP_CLTS,
+ V3_OP_ADC, V3_OP_ADD, V3_OP_AND, V3_OP_OR, V3_OP_XOR, V3_OP_SUB,
+ V3_OP_INC, V3_OP_DEC, V3_OP_NEG, V3_OP_MOV, V3_OP_NOT, V3_OP_XCHG,
+ V3_OP_SETB, V3_OP_SETBE, V3_OP_SETL, V3_OP_SETLE, V3_OP_SETNB,
+ V3_OP_SETNBE, V3_OP_SETNL, V3_OP_SETNLE, V3_OP_SETNO, V3_OP_SETNP,
+ V3_OP_SETNS, V3_OP_SETNZ, V3_OP_SETO, V3_OP_SETP, V3_OP_SETS,
+ V3_OP_SETZ, V3_OP_MOVS} v3_op_type_t;
+
+
typedef enum {INVALID_OPERAND, REG_OPERAND, MEM_OPERAND, IMM_OPERAND} v3_operand_type_t;
struct x86_operand {
uint_t fs_override : 1; // 0x64
uint_t gs_override : 1; // 0x65
uint_t br_not_taken : 1; // 0x2E
- uint_t br_takend : 1; // 0x3E
+ uint_t br_taken : 1; // 0x3E
uint_t op_size : 1; // 0x66
uint_t addr_size : 1; // 0x67
};
struct x86_instr {
struct x86_prefixes prefixes;
uint_t instr_length;
- addr_t opcode; // a pointer to the V3_OPCODE_[*] arrays defined below
+ v3_op_type_t op_type;
uint_t num_operands;
struct x86_operand dst_operand;
struct x86_operand src_operand;
struct x86_operand third_operand;
+ addr_t str_op_length;
+ addr_t is_str_op;
void * decoder_data;
};
/* Removes a rep prefix in place */
void v3_strip_rep_prefix(uchar_t * instr, int length);
-
+void v3_get_prefixes(uchar_t * instr, struct x86_prefixes * prefixes);
/*
base_addr = gprs->rax;
break;
case 1:
- base_addr = gprs->rcx;
+ base_addr = gprs->rcx;
break;
case 2:
base_addr = gprs->rdx;
#ifdef __V3VEE__
-#include <palacios/vmm_list.h>
#include <palacios/vmm_shadow_paging.h>
#include <palacios/vmm_paging.h>
-
-struct emulated_page {
- addr_t page_addr;
- addr_t va;
- pte32_t pte;
- struct list_head page_list;
-};
-
-struct saved_page {
- addr_t va;
- pte32_t pte;
- struct list_head page_list;
-};
-
-
-struct write_region {
- void * write_data;
-
- uint_t length;
- int (*write)(addr_t write_addr, void * src, uint_t length, void * priv_data);
- addr_t write_addr;
- void * private_data;
-
- struct list_head write_list;
-};
-
-
-struct emulation_state {
- uint_t num_emulated_pages;
- struct list_head emulated_pages;
-
- uint_t num_saved_pages;
- struct list_head saved_pages;
-
- uint_t num_write_regions;
- struct list_head write_regions;
-
- uint_t running : 1;
- uint_t instr_length;
-
- uint_t tf_enabled : 1;
-};
-
-
-int v3_init_emulator(struct guest_info * info);
-
-
-int v3_emulation_exit_handler(struct guest_info * info);
-
-int v3_emulate_memory_write(struct guest_info * info, addr_t fault_gva,
- int (*write)(addr_t write_addr, void * src, uint_t length, void * priv_data),
- addr_t write_addr, void * private_data);
-int v3_emulate_memory_read(struct guest_info * info, addr_t fault_gva,
- int (*read)(addr_t read_addr, void * dst, uint_t length, void * priv_data),
- addr_t read_addr, void * private_data);
+int v3_emulate_write_op(struct guest_info * info, addr_t fault_gva, addr_t write_gpa, addr_t * dst_addr);
#endif // !__V3VEE__
--- /dev/null
+#include <palacios/vmm_types.h>
+
+
+
+#define MAKE_1OP_8FLAGS_INST(iname) static inline void iname##8(addr_t * dst, addr_t * flags) { \
+ uchar_t tmp_dst = *dst; \
+ \
+ /* Some of the flags values are not copied out in a pushf, we save them here */ \
+ addr_t flags_rsvd = *flags & ~0xfffe7fff; \
+ \
+ asm volatile ( \
+ "pushf; " \
+ "push %2; " \
+ "popf; " \
+ #iname"b %0; " \
+ "pushf; " \
+ "pop %1; " \
+ "popf; " \
+ : "=q"(tmp_dst),"=q"(*flags) \
+ : "q"(*flags), "0"(tmp_dst) \
+ ); \
+ *dst = tmp_dst; \
+ *flags |= flags_rsvd; \
+ \
+ }
+
+#define MAKE_1OP_16FLAGS_INST(iname) static inline void iname##16(addr_t * dst, addr_t * flags) { \
+ ushort_t tmp_dst = *dst; \
+ \
+ /* Some of the flags values are not copied out in a pushf, we save them here */ \
+ addr_t flags_rsvd = *flags & ~0xfffe7fff; \
+ \
+ asm volatile ( \
+ "pushf; " \
+ "push %2; " \
+ "popf; " \
+ #iname"w %0; " \
+ "pushf; " \
+ "pop %1; " \
+ "popf; " \
+ : "=q"(tmp_dst),"=q"(*flags) \
+ : "q"(*flags), "0"(tmp_dst) \
+ ); \
+ *dst = tmp_dst; \
+ *flags |= flags_rsvd; \
+ \
+ }
+
+#define MAKE_1OP_32FLAGS_INST(iname) static inline void iname##32(addr_t * dst, addr_t * flags) { \
+ uint_t tmp_dst = *dst; \
+ \
+ /* Some of the flags values are not copied out in a pushf, we save them here */ \
+ addr_t flags_rsvd = *flags & ~0xfffe7fff; \
+ \
+ asm volatile ( \
+ "pushf; " \
+ "push %2; " \
+ "popf; " \
+ #iname"l %0; " \
+ "pushf; " \
+ "pop %1; " \
+ "popf; " \
+ : "=q"(tmp_dst),"=q"(*flags) \
+ : "q"(*flags), "0"(tmp_dst) \
+ ); \
+ *dst = tmp_dst; \
+ *flags |= flags_rsvd; \
+ \
+ }
+
+#define MAKE_1OP_64FLAGS_INST(iname) static inline void iname##64(addr_t * dst, addr_t * flags) { \
+ ullong_t tmp_dst = *dst; \
+ \
+ /* Some of the flags values are not copied out in a pushf, we save them here */ \
+ addr_t flags_rsvd = *flags & ~0xfffe7fff; \
+ \
+ asm volatile ( \
+ "pushfq; " \
+ "push %2; " \
+ "popfq; " \
+ #iname"q %0; " \
+ "pushfq; " \
+ "pop %1; " \
+ "popfq; " \
+ : "=q"(tmp_dst),"=q"(*flags) \
+ : "q"(*flags), "0"(tmp_dst) \
+ ); \
+ *dst = tmp_dst; \
+ *flags |= flags_rsvd; \
+ \
+ }
+
+
+
+#define MAKE_1OP_8_INST(iname) static inline void iname##8(addr_t * dst) { \
+ uchar_t tmp_dst = *dst; \
+ \
+ asm volatile ( \
+ #iname"b %0; " \
+ : "=q"(tmp_dst) \
+ : "0"(tmp_dst) \
+ ); \
+ *dst = tmp_dst; \
+ }
+
+#define MAKE_1OP_16_INST(iname) static inline void iname##16(addr_t * dst) { \
+ ushort_t tmp_dst = *dst; \
+ \
+ asm volatile ( \
+ #iname"w %0; " \
+ : "=q"(tmp_dst) \
+ : "0"(tmp_dst) \
+ ); \
+ *dst = tmp_dst; \
+ }
+
+#define MAKE_1OP_32_INST(iname) static inline void iname##32(addr_t * dst) { \
+ uint_t tmp_dst = *dst; \
+ \
+ asm volatile ( \
+ #iname"l %0; " \
+ : "=q"(tmp_dst) \
+ : "0"(tmp_dst) \
+ ); \
+ *dst = tmp_dst; \
+ }
+
+#define MAKE_1OP_64_INST(iname) static inline void iname##64(addr_t * dst) { \
+ ullong_t tmp_dst = *dst; \
+ \
+ asm volatile ( \
+ #iname"q %0; " \
+ : "=q"(tmp_dst) \
+ : "0"(tmp_dst) \
+ ); \
+ *dst = tmp_dst; \
+ }
+
+
+#define MAKE_2OP_64FLAGS_INST(iname) static inline void iname##64(addr_t * dst, addr_t * src, addr_t * flags) { \
+ uint64_t tmp_dst = *dst, tmp_src = *src; \
+ addr_t tmp_flags = *flags; \
+ \
+ /* Some of the flags values are not copied out in a pushf, we save them here */ \
+ addr_t flags_rsvd = *flags & ~0xfffe7fff; \
+ \
+ asm volatile ( \
+ "pushfq\r\n" \
+ "push %3\r\n" \
+ "popfq\r\n" \
+ #iname"q %2, %0\r\n" \
+ "pushfq\r\n" \
+ "pop %1\r\n" \
+ "popfq\r\n" \
+ : "=q"(tmp_dst),"=q"(tmp_flags) \
+ : "q"(tmp_src),"q"(tmp_flags), "0"(tmp_dst) \
+ ); \
+ \
+ *dst = tmp_dst; \
+ *flags = tmp_flags; \
+ *flags |= flags_rsvd; \
+ \
+ }
+
+
+
+
+#define MAKE_2OP_32FLAGS_INST(iname) static inline void iname##32(addr_t * dst, addr_t * src, addr_t * flags) { \
+ uint32_t tmp_dst = *dst, tmp_src = *src; \
+ \
+ /* Some of the flags values are not copied out in a pushf, we save them here */ \
+ addr_t flags_rsvd = *flags & ~0xfffe7fff; \
+ \
+ asm volatile ( \
+ "pushf; " \
+ "push %3; " \
+ "popf; " \
+ #iname"l %2, %0; " \
+ "pushf; " \
+ "pop %1; " \
+ "popf; " \
+ : "=q"(tmp_dst),"=q"(*flags) \
+ : "q"(tmp_src),"q"(*flags), "0"(tmp_dst) \
+ ); \
+ *dst = tmp_dst; \
+ *flags |= flags_rsvd; \
+ \
+ }
+
+
+#define MAKE_2OP_16FLAGS_INST(iname) static inline void iname##16(addr_t * dst, addr_t * src, addr_t * flags) { \
+ ushort_t tmp_dst = *dst, tmp_src = *src; \
+ \
+ /* Some of the flags values are not copied out in a pushf, we save them here */ \
+ addr_t flags_rsvd = *flags & ~0xfffe7fff; \
+ \
+ asm volatile ( \
+ "pushf; " \
+ "push %3; " \
+ "popf; " \
+ #iname"w %2, %0; " \
+ "pushf; " \
+ "pop %1; " \
+ "popf; " \
+ : "=q"(tmp_dst),"=q"(*flags) \
+ : "q"(tmp_src),"q"(*flags), "0"(tmp_dst) \
+ ); \
+ *dst = tmp_dst; \
+ *flags |= flags_rsvd; \
+ \
+ }
+
+#define MAKE_2OP_8FLAGS_INST(iname) static inline void iname##8(addr_t * dst, addr_t * src, addr_t * flags) { \
+ uchar_t tmp_dst = *dst, tmp_src = *src; \
+ \
+ /* Some of the flags values are not copied out in a pushf, we save them here */ \
+ addr_t flags_rsvd = *flags & ~0xfffe7fff; \
+ \
+ asm volatile ( \
+ "pushf; " \
+ "push %3; " \
+ "popf; " \
+ #iname"b %2, %0; " \
+ "pushf; " \
+ "pop %1; " \
+ "popf; " \
+ : "=q"(tmp_dst),"=q"(*flags) \
+ : "q"(tmp_src),"q"(*flags), "0"(tmp_dst) \
+ ); \
+ *dst = tmp_dst; \
+ *flags |= flags_rsvd; \
+ \
+ }
+
+
+
+
+#define MAKE_2OP_32STR_INST(iname) static inline void iname##32(addr_t * dst, \
+ addr_t * src, \
+ addr_t * ecx, addr_t * flags) { \
+ /* Some of the flags values are not copied out in a pushf, we save them here */ \
+ addr_t flags_rsvd = *flags & ~0xfffe7fff; \
+ \
+ asm volatile ( \
+ "pushf; " \
+ "push %4; " \
+ "popf; " \
+ "rep; " \
+ #iname"l; " \
+ "pushf; " \
+ "pop %0; " \
+ "popf; " \
+ : "=b"(*flags) \
+ : "D"(*dst),"S"(*src),"c"(*ecx),"b"(*flags) \
+ ); \
+ \
+ /* : "=D"(*dst),"=S"(*src),"=c"(*ecx),"=q"(*flags)*/ \
+ *flags |= flags_rsvd; \
+ }
+
+#define MAKE_2OP_16STR_INST(iname) static inline void iname##16(addr_t * dst, \
+ addr_t * src, \
+ addr_t * ecx, addr_t * flags) { \
+ /* Some of the flags values are not copied out in a pushf, we save them here */ \
+ addr_t flags_rsvd = *flags & ~0xfffe7fff; \
+ \
+ asm volatile ( \
+ "pushf; " \
+ "push %4; " \
+ "popf; " \
+ "rep; " \
+ #iname"w; " \
+ "pushf; " \
+ "pop %0; " \
+ "popf; " \
+ : "=b"(*flags) \
+ : "D"(*dst),"S"(*src),"c"(*ecx),"b"(*flags) \
+ ); \
+ *flags |= flags_rsvd; \
+ }
+
+
+
+#define MAKE_2OP_8STR_INST(iname) static inline void iname##8(addr_t * dst, \
+ addr_t * src, \
+ addr_t * ecx, addr_t * flags) { \
+ /* Some of the flags values are not copied out in a pushf, we save them here */ \
+ addr_t flags_rsvd = *flags & ~0xfffe7fff; \
+ \
+ asm volatile ( \
+ "pushf; " \
+ "push %4; " \
+ "popf; " \
+ "rep; " \
+ #iname"b; " \
+ "pushf; " \
+ "pop %0; " \
+ "popf; " \
+ : "=b"(*flags) \
+ : "D"(*dst),"S"(*src),"c"(*ecx),"b"(*flags) \
+ ); \
+ *flags |= flags_rsvd; \
+ }
+
+
+
+
+#define MAKE_2OP_32_INST(iname) static inline void iname##32(addr_t * dst, addr_t * src) { \
+ uint32_t tmp_dst = *dst, tmp_src = *src; \
+ \
+ asm volatile ( \
+ #iname"l %1, %0; " \
+ : "=q"(tmp_dst) \
+ : "q"(tmp_src), "0"(tmp_dst) \
+ ); \
+ *dst = tmp_dst; \
+ }
+
+#define MAKE_2OP_16_INST(iname) static inline void iname##16(addr_t * dst, addr_t * src) { \
+ ushort_t tmp_dst = *dst, tmp_src = *src; \
+ \
+ asm volatile ( \
+ #iname"w %1, %0; " \
+ : "=q"(tmp_dst) \
+ : "q"(tmp_src), "0"(tmp_dst) \
+ ); \
+ *dst = tmp_dst; \
+ }
+
+#define MAKE_2OP_8_INST(iname) static inline void iname##8(addr_t * dst, addr_t * src) { \
+ uchar_t tmp_dst = *dst, tmp_src = *src; \
+ \
+ asm volatile ( \
+ #iname"b %1, %0; " \
+ : "=q"(tmp_dst) \
+ : "q"(tmp_src), "0"(tmp_dst) \
+ ); \
+ *dst = tmp_dst; \
+ }
+
+
+
+
+
+
+
+MAKE_2OP_8FLAGS_INST(adc);
+MAKE_2OP_8FLAGS_INST(add);
+MAKE_2OP_8FLAGS_INST(and);
+MAKE_2OP_8FLAGS_INST(or);
+MAKE_2OP_8FLAGS_INST(xor);
+MAKE_2OP_8FLAGS_INST(sub);
+
+
+MAKE_1OP_8FLAGS_INST(inc);
+MAKE_1OP_8FLAGS_INST(dec);
+MAKE_1OP_8FLAGS_INST(neg);
+MAKE_1OP_8FLAGS_INST(setb);
+MAKE_1OP_8FLAGS_INST(setbe);
+MAKE_1OP_8FLAGS_INST(setl);
+MAKE_1OP_8FLAGS_INST(setle);
+MAKE_1OP_8FLAGS_INST(setnb);
+MAKE_1OP_8FLAGS_INST(setnbe);
+MAKE_1OP_8FLAGS_INST(setnl);
+MAKE_1OP_8FLAGS_INST(setnle);
+MAKE_1OP_8FLAGS_INST(setno);
+MAKE_1OP_8FLAGS_INST(setnp);
+MAKE_1OP_8FLAGS_INST(setns);
+MAKE_1OP_8FLAGS_INST(setnz);
+MAKE_1OP_8FLAGS_INST(seto);
+MAKE_1OP_8FLAGS_INST(setp);
+MAKE_1OP_8FLAGS_INST(sets);
+MAKE_1OP_8FLAGS_INST(setz);
+
+
+MAKE_1OP_8_INST(not);
+
+MAKE_2OP_8_INST(mov);
+MAKE_2OP_8_INST(xchg);
+
+
+
+MAKE_2OP_16FLAGS_INST(adc);
+MAKE_2OP_16FLAGS_INST(add);
+MAKE_2OP_16FLAGS_INST(and);
+MAKE_2OP_16FLAGS_INST(or);
+MAKE_2OP_16FLAGS_INST(xor);
+MAKE_2OP_16FLAGS_INST(sub);
+
+
+MAKE_1OP_16FLAGS_INST(inc);
+MAKE_1OP_16FLAGS_INST(dec);
+MAKE_1OP_16FLAGS_INST(neg);
+
+MAKE_1OP_16_INST(not);
+
+MAKE_2OP_16_INST(mov);
+MAKE_2OP_16_INST(xchg);
+
+
+
+
+
+MAKE_2OP_32FLAGS_INST(adc);
+MAKE_2OP_32FLAGS_INST(add);
+MAKE_2OP_32FLAGS_INST(and);
+MAKE_2OP_32FLAGS_INST(or);
+MAKE_2OP_32FLAGS_INST(xor);
+MAKE_2OP_32FLAGS_INST(sub);
+
+
+MAKE_1OP_32FLAGS_INST(inc);
+MAKE_1OP_32FLAGS_INST(dec);
+MAKE_1OP_32FLAGS_INST(neg);
+
+MAKE_1OP_32_INST(not);
+
+MAKE_2OP_32_INST(mov);
+MAKE_2OP_32_INST(xchg);
+
+MAKE_2OP_8STR_INST(movs);
+MAKE_2OP_16STR_INST(movs);
+MAKE_2OP_32STR_INST(movs);
struct guest_info;
-/*
-
- Guest Shadow Host
- Virtual Physical Virtual Physical Virtual Physical
- OK OK
- OK NOK
- NOK OK
- NOK NOK
-
-*/
-
-// These are the types of physical memory address regions
-// from the perspective of the guest
-typedef enum guest_region_type {
- GUEST_REGION_NOTHING,
- GUEST_REGION_PHYSICAL_MEMORY,
- GUEST_REGION_MEMORY_MAPPED_DEVICE} guest_region_type_t;
// These are the types of physical memory address regions
// from the perspective of the HOST
-typedef enum host_region_type {
- HOST_REGION_INVALID, // This region is INVALID (this is a return type, to denote errors)
- HOST_REGION_HOOK, // This region is mapped as not present (always generate page faults)
- HOST_REGION_PHYSICAL_MEMORY, // Region is a section of host memory
- HOST_REGION_MEMORY_MAPPED_DEVICE, // Region is allocated for DMA
- HOST_REGION_UNALLOCATED, // Region is mapped on demand
- HOST_REGION_REMOTE, // Region is located on a remote machine
- HOST_REGION_SWAPPED, // Region is swapped
-} host_region_type_t;
+typedef enum shdw_region_type {
+ SHDW_REGION_INVALID, // This region is INVALID (this is a return type to denote errors)
+ SHDW_REGION_WRITE_HOOK, // This region is mapped as read-only (page faults on write)
+ SHDW_REGION_FULL_HOOK, // This region is mapped as not present (always generate page faults)
+ SHDW_REGION_ALLOCATED, // Region is a section of host memory
+ SHDW_REGION_UNALLOCATED, // Region is mapped on demand
+} shdw_region_type_t;
-#define shadow_mem_type_t host_region_type_t
+struct vmm_mem_hook;
struct shadow_region {
- guest_region_type_t guest_type;
addr_t guest_start;
addr_t guest_end;
- host_region_type_t host_type;
- addr_t host_addr; // This either points to a host address mapping,
- // or a structure holding the map info
+ shdw_region_type_t host_type;
+
+ addr_t host_addr; // This either points to a host address mapping
+
+
+ // Called when data is read from a memory page
+ int (*read_hook)(addr_t guest_addr, void * dst, uint_t length, void * priv_data);
+ // Called when data is written to a memory page
+ int (*write_hook)(addr_t guest_addr, void * src, uint_t length, void * priv_data);
+
+ void * priv_data;
struct shadow_region *next, *prev;
};
};
+
void init_shadow_region(struct shadow_region * entry,
- addr_t guest_addr_start,
- addr_t guest_addr_end,
- guest_region_type_t guest_region_type,
- host_region_type_t host_region_type);
+ addr_t guest_addr_start,
+ addr_t guest_addr_end,
+ shdw_region_type_t shdw_region_type);
-/*
-void init_shadow_region_physical(struct shadow_region * entry,
- addr_t guest_addr_start,
- addr_t guest_addr_end,
- guest_region_type_t guest_region_type,
- addr_t host_addr_start,
- host_region_type_t host_region_type);
-*/
int add_shadow_region_passthrough(struct guest_info * guest_info,
addr_t guest_addr_start,
struct shadow_region * get_shadow_region_by_index(struct shadow_map * map, uint_t index);
-host_region_type_t lookup_shadow_map_addr(struct shadow_map * map, addr_t guest_addr, addr_t * host_addr);
+shdw_region_type_t lookup_shadow_map_addr(struct shadow_map * map, addr_t guest_addr, addr_t * host_addr);
-host_region_type_t get_shadow_addr_type(struct guest_info * info, addr_t guest_addr);
+shdw_region_type_t get_shadow_addr_type(struct guest_info * info, addr_t guest_addr);
addr_t get_shadow_addr(struct guest_info * info, addr_t guest_addr);
// Semantics:
// Semantics:
// Deletions result in splitting
int delete_shadow_region(struct shadow_map * map,
- addr_t guest_start,
- addr_t guest_end);
+ addr_t guest_start,
+ addr_t guest_end);
void print_shadow_map(struct shadow_map * map);
-struct vmm_mem_hook {
- // Called when data is read from a memory page
- int (*read)(addr_t guest_addr, void * dst, uint_t length, void * priv_data);
-
- // Called when data is written to a memory page
- int (*write)(addr_t guest_addr, void * src, uint_t length, void * priv_data);
-
- void * priv_data;
- struct shadow_region * region;
-};
+struct shadow_region * v3_get_shadow_region(struct guest_info * info, addr_t addr);
+int v3_hook_full_mem(struct guest_info * info, addr_t guest_addr_start, addr_t guest_addr_end,
+ int (*read)(addr_t guest_addr, void * dst, uint_t length, void * priv_data),
+ int (*write)(addr_t guest_addr, void * src, uint_t length, void * priv_data),
+ void * priv_data);
+int v3_hook_write_mem(struct guest_info * info, addr_t guest_addr_start, addr_t guest_addr_end,
+ addr_t host_addr,
+ int (*write)(addr_t guest_addr, void * src, uint_t length, void * priv_data),
+ void * priv_data);
-struct vmm_mem_hook * get_mem_hook(struct guest_info * info, addr_t guest_addr);
-
-int hook_guest_mem(struct guest_info * info, addr_t guest_addr_start, addr_t guest_addr_end,
- int (*read)(addr_t guest_addr, void * dst, uint_t length, void * priv_data),
- int (*write)(addr_t guest_addr, void * src, uint_t length, void * priv_data),
- void * priv_data);
int unhook_guest_mem(struct guest_info * info, addr_t guest_addr);
+const uchar_t * shdw_region_type_to_str(shdw_region_type_t type);
+
int handle_special_page_fault(struct guest_info * info, addr_t fault_addr, addr_t gp_addr, pf_error_t access_info);
+int v3_handle_mem_wr_hook(struct guest_info * info, addr_t guest_va, addr_t guest_pa,
+ struct shadow_region * reg, pf_error_t access_info);
+int v3_handle_mem_full_hook(struct guest_info * info, addr_t guest_va, addr_t guest_pa,
+ struct shadow_region * reg, pf_error_t access_info);
#endif // ! __V3VEE__
-----------------------------------------------------------------------
*/
-#ifndef _LINUX_RBTREE_H
-#define _LINUX_RBTREE_H
+#ifndef _VMM_RBTREE_H
+#define _VMM_RBTREE_H
+
+#ifdef __V3VEE__
+
+
+#define container_of(ptr, type, member) ({ \
+ const typeof( ((type *)0)->member ) *__mptr = (ptr); \
+ (type *)( (char *)__mptr - offsetof(type,member) );})
+
-#include <linux/kernel.h>
-#include <linux/stddef.h>
struct rb_node
{
#define RB_EMPTY_NODE(node) (rb_parent(node) != node)
#define RB_CLEAR_NODE(node) (rb_set_parent(node, node))
-extern void rb_insert_color(struct rb_node *, struct rb_root *);
-extern void rb_erase(struct rb_node *, struct rb_root *);
+extern void v3_rb_insert_color(struct rb_node *, struct rb_root *);
+extern void v3_rb_erase(struct rb_node *, struct rb_root *);
/* Find logical next and previous nodes in a tree */
-extern struct rb_node *rb_next(struct rb_node *);
-extern struct rb_node *rb_prev(struct rb_node *);
-extern struct rb_node *rb_first(struct rb_root *);
-extern struct rb_node *rb_last(struct rb_root *);
+extern struct rb_node *v3_rb_next(struct rb_node *);
+extern struct rb_node *v3_rb_prev(struct rb_node *);
+extern struct rb_node *v3_rb_first(struct rb_root *);
+extern struct rb_node *v3_rb_last(struct rb_root *);
/* Fast replacement of a single node without remove/rebalance/add/rebalance */
-extern void rb_replace_node(struct rb_node *victim, struct rb_node *new,
+extern void v3_rb_replace_node(struct rb_node *victim, struct rb_node *new,
struct rb_root *root);
static inline void rb_link_node(struct rb_node * node, struct rb_node * parent,
*rb_link = node;
}
+
+#endif
+
#endif /* _LINUX_RBTREE_H */
#ifdef __V3VEE__
-
#endif // ! __V3VEE__
#endif
}
break;
+
+#if 0
+ // Emulation handlers currently not used
case VMEXIT_EXCP1:
{
#ifdef DEBUG_EMULATOR
}
break;
}
-
+
case VMEXIT_VMMCALL:
{
}
break;
}
-
+#endif
case VMEXIT_WBINVD:
int guest_pa_to_host_pa(struct guest_info * guest_info, addr_t guest_pa, addr_t * host_pa) {
// we use the shadow map here...
- host_region_type_t reg_type = lookup_shadow_map_addr(&(guest_info->mem_map), guest_pa, host_pa);
+ shdw_region_type_t reg_type = lookup_shadow_map_addr(&(guest_info->mem_map), guest_pa, host_pa);
- if (reg_type != HOST_REGION_PHYSICAL_MEMORY) {
+ if ((reg_type == SHDW_REGION_INVALID) ||
+ (reg_type == SHDW_REGION_UNALLOCATED) ||
+ (reg_type == SHDW_REGION_FULL_HOOK)){
PrintError("In GPA->HPA: Could not find address in shadow map (addr=%p) (reg_type=%d)\n",
(void *)guest_pa, reg_type);
return -1;
#include <palacios/vmm_intr.h>
#include <palacios/vmm_config.h>
#include <palacios/vm_guest.h>
-#include <palacios/vmm_decoder.h>
+
v3_cpu_arch_t v3_cpu_type;
struct v3_os_hooks * os_hooks = NULL;
v3_cpu_type = V3_INVALID_CPU;
- v3_init_decoder();
+
if (v3_is_svm_capable()) {
#include <palacios/vmm.h>
#include <palacios/vmm_debug.h>
#include <palacios/vmm_msr.h>
-
+#include <palacios/vmm_decoder.h>
#include <devices/serial.h>
#include <devices/keyboard.h>
-static int mem_test_read(addr_t guest_addr, void * dst, uint_t length, void * priv_data) {
- int foo = 20;
-
- memcpy(dst, &foo, length);
+static int passthrough_mem_write(addr_t guest_addr, void * src, uint_t length, void * priv_data) {
- PrintDebug("Passthrough mem read returning: %p (length=%d)\n", (void *)(foo + (guest_addr & 0xfff)), length);
return length;
-}
+ // memcpy((void*)guest_addr, src, length);
+ PrintDebug("Write of %d bytes to %p\n", length, (void *)guest_addr);
+ PrintDebug("Write Value = %p\n", (void *)*(addr_t *)src);
-static int passthrough_mem_read(addr_t guest_addr, void * dst, uint_t length, void * priv_data) {
- memcpy(dst, (void*)guest_addr, length);
- return length;
-}
-
-static int passthrough_mem_write(addr_t guest_addr, void * src, uint_t length, void * priv_data) {
- memcpy((void*)guest_addr, src, length);
return length;
}
v3_init_msr_map(info);
v3_init_interrupt_state(info);
v3_init_dev_mgr(info);
- v3_init_emulator(info);
v3_init_host_events(info);
+ v3_init_decoder(info);
+
init_shadow_map(info);
if (v3_cpu_type == V3_SVM_REV3_CPU) {
//
add_shadow_region_passthrough(info, 0x0, 0xa0000, (addr_t)V3_AllocPages(160));
- if (1) {
+ if (0) {
add_shadow_region_passthrough(info, 0xa0000, 0xc0000, 0xa0000);
} else {
- hook_guest_mem(info, 0xa0000, 0xc0000, passthrough_mem_read, passthrough_mem_write, NULL);
+ v3_hook_write_mem(info, 0xa0000, 0xc0000, 0xa0000, passthrough_mem_write, NULL);
}
// TEMP
} else {
/* MEMORY HOOK TEST */
add_shadow_region_passthrough(info, 0x100000, 0xa00000, (addr_t)V3_AllocPages(2304));
- hook_guest_mem(info, 0xa00000, 0xa01000, mem_test_read, passthrough_mem_write, NULL);
+ v3_hook_write_mem(info, 0xa00000, 0xa01000, (addr_t)V3_AllocPages(1), passthrough_mem_write, NULL);
add_shadow_region_passthrough(info, 0xa01000, 0x1000000, (addr_t)V3_AllocPages(1791));
}
return -1;
}
- if (v3_opcode_cmp(V3_OPCODE_LMSW, (const uchar_t *)(dec_instr.opcode)) == 0) {
+ if (dec_instr.op_type == V3_OP_LMSW) {
+ // if (v3_opcode_cmp(V3_OPCODE_LMSW, (const uchar_t *)(dec_instr.opcode)) == 0) {
if (handle_lmsw(info, &dec_instr) == -1) {
return -1;
}
- } else if (v3_opcode_cmp(V3_OPCODE_MOV2CR, (const uchar_t *)(dec_instr.opcode)) == 0) {
-
+ // } else if (v3_opcode_cmp(V3_OPCODE_MOV2CR, (const uchar_t *)(dec_instr.opcode)) == 0) {
+ } else if (dec_instr.op_type == V3_OP_MOV2CR) {
if (handle_mov_to_cr0(info, &dec_instr) == -1) {
return -1;
}
- } else if (v3_opcode_cmp(V3_OPCODE_CLTS, (const uchar_t *)(dec_instr.opcode)) == 0) {
+ // } else if (v3_opcode_cmp(V3_OPCODE_CLTS, (const uchar_t *)(dec_instr.opcode)) == 0) {
+ } else if (dec_instr.op_type == V3_OP_CLTS) {
if (handle_clts(info, &dec_instr) == -1) {
return -1;
return -1;
}
- if (v3_opcode_cmp(V3_OPCODE_MOVCR2, (const uchar_t *)(dec_instr.opcode)) == 0) {
+ // if (v3_opcode_cmp(V3_OPCODE_MOVCR2, (const uchar_t *)(dec_instr.opcode)) == 0) {
+ if (dec_instr.op_type == V3_OP_MOVCR2) {
struct cr0_32 * dst_reg = (struct cr0_32 *)(dec_instr.dst_operand.operand);
struct cr0_32 * shadow_cr0 = (struct cr0_32 *)&(info->ctrl_regs.cr0);
PrintDebug("Shadow CR0: %x\n", *(uint_t*)shadow_cr0);
PrintDebug("returned CR0: %x\n", *(uint_t*)dst_reg);
- } else if (v3_opcode_cmp(V3_OPCODE_SMSW, (const uchar_t *)(dec_instr.opcode)) == 0) {
+ // } else if (v3_opcode_cmp(V3_OPCODE_SMSW, (const uchar_t *)(dec_instr.opcode)) == 0) {
+ } else if (dec_instr.op_type == V3_OP_SMSW) {
struct cr0_real * shadow_cr0 = (struct cr0_real *)&(info->ctrl_regs.cr0);
struct cr0_real * dst_reg = (struct cr0_real *)(dec_instr.dst_operand.operand);
char cr0_val = *(char*)shadow_cr0 & 0x0f;
return -1;
}
- if (v3_opcode_cmp(V3_OPCODE_MOV2CR, (const uchar_t *)(dec_instr.opcode)) == 0) {
+ // if (v3_opcode_cmp(V3_OPCODE_MOV2CR, (const uchar_t *)(dec_instr.opcode)) == 0) {
+ if (dec_instr.op_type == V3_OP_MOV2CR) {
PrintDebug("MOV2CR3 (cpu_mode=%s)\n", v3_cpu_mode_to_str(info->cpu_mode));
if (info->shdw_pg_mode == SHADOW_PAGING) {
return -1;
}
- if (v3_opcode_cmp(V3_OPCODE_MOVCR2, (const uchar_t *)(dec_instr.opcode)) == 0) {
+ // if (v3_opcode_cmp(V3_OPCODE_MOVCR2, (const uchar_t *)(dec_instr.opcode)) == 0) {
+ if (dec_instr.op_type == V3_OP_MOVCR2) {
PrintDebug("MOVCR32 (mode=%s)\n", v3_cpu_mode_to_str(info->cpu_mode));
if (info->shdw_pg_mode == SHADOW_PAGING) {
return -1;
}
- if (v3_opcode_cmp(V3_OPCODE_MOV2CR, (const uchar_t *)(dec_instr.opcode)) != 0) {
+ // if (v3_opcode_cmp(V3_OPCODE_MOV2CR, (const uchar_t *)(dec_instr.opcode)) != 0) {
+ if (dec_instr.op_type != V3_OP_MOV2CR) {
PrintError("Invalid opcode in write to CR4\n");
return -1;
}
}
+void v3_get_prefixes(uchar_t * instr, struct x86_prefixes * prefixes) {
+ while (1) {
+ switch (*instr) {
+ case 0xF0: // lock
+ prefixes->lock = 1;
+ break;
+
+ case 0xF2: // REPNE/REPNZ
+ prefixes->repnz = 1;
+ prefixes->repne = 1;
+ break;
+
+ case 0xF3: // REP or REPE/REPZ
+ prefixes->rep = 1;
+ prefixes->repe = 1;
+ prefixes->repz = 1;
+ break;
+
+ case 0x2E: // CS override or Branch hint not taken (with Jcc instrs)
+ prefixes->cs_override = 1;
+ prefixes->br_not_taken = 1;
+ break;
+
+ case 0x36: // SS override
+ prefixes->ss_override = 1;
+ break;
+
+ case 0x3E: // DS override or Branch hint taken (with Jcc instrs)
+ prefixes->ds_override = 1;
+ prefixes->br_taken = 1;
+ break;
+
+ case 0x26: // ES override
+ prefixes->es_override = 1;
+ break;
+
+ case 0x64: // FS override
+ prefixes->fs_override = 1;
+ break;
+
+ case 0x65: // GS override
+ prefixes->gs_override = 1;
+ break;
+
+ case 0x66: // operand size override
+ prefixes->op_size = 1;
+ break;
+
+ case 0x67: // address size override
+ prefixes->addr_size = 1;
+ break;
+
+ default:
+ return;
+ }
+
+ instr++;
+ }
+
+}
+
void v3_strip_rep_prefix(uchar_t * instr, int length) {
int read_ctr = 0;
int write_ctr = 0;
#include <palacios/vmm_emulator.h>
#include <palacios/vm_guest_mem.h>
#include <palacios/vmm_decoder.h>
-#include <palacios/vmm_debug.h>
-#include <palacios/vmcb.h>
-#include <palacios/vmm_ctrl_regs.h>
-
-static const char VMMCALL[3] = {0x0f, 0x01, 0xd9};
+#include <palacios/vmm_paging.h>
+#include <palacios/vmm_instr_emulator.h>
#ifndef DEBUG_EMULATOR
#undef PrintDebug
#endif
-int v3_init_emulator(struct guest_info * info) {
- struct emulation_state * emulator = &(info->emulator);
-
- emulator->num_emulated_pages = 0;
- INIT_LIST_HEAD(&(emulator->emulated_pages));
-
- emulator->num_saved_pages = 0;
- INIT_LIST_HEAD(&(emulator->saved_pages));
-
- emulator->num_write_regions = 0;
- INIT_LIST_HEAD(&(emulator->write_regions));
- emulator->running = 0;
- emulator->instr_length = 0;
- emulator->tf_enabled = 0;
- return 0;
-}
+// We emulate up to the next 4KB page boundry
+static int emulate_string_write_op(struct guest_info * info, struct x86_instr * dec_instr,
+ addr_t write_gva, addr_t write_gpa, addr_t * dst_addr) {
+ uint_t emulation_length = 0;
+ addr_t tmp_rcx = 0;
+ addr_t src_addr = 0;
-static addr_t get_new_page() {
- void * page = V3_VAddr(V3_AllocPages(1));
- memset(page, 0, PAGE_SIZE);
+ if (dec_instr->op_type == V3_OP_MOVS) {
+ PrintDebug("MOVS emulation\n");
- return (addr_t)page;
-}
+ if (dec_instr->dst_operand.operand != write_gva) {
+ PrintError("Inconsistency between Pagefault and Instruction Decode XED_ADDR=%p, PF_ADDR=%p\n",
+ (void *)dec_instr->dst_operand.operand, (void *)write_gva);
+ return -1;
+ }
-/*
-static int setup_code_page(struct guest_info * info, char * instr, struct basic_instr_info * instr_info ) {
- addr_t code_page_offset = PT32_PAGE_OFFSET(info->rip);
- addr_t code_page = get_new_page();
- struct emulated_page * new_code_page = V3_Malloc(sizeof(struct emulated_page));
- struct saved_page * saved_code_page = V3_Malloc(sizeof(struct saved_page));
+ emulation_length = ( (dec_instr->str_op_length < (0x1000 - PAGE_OFFSET_4KB(write_gva))) ?
+ dec_instr->str_op_length :
+ (0x1000 - PAGE_OFFSET_4KB(write_gva)));
+ /* ** Fix emulation length so that it doesn't overrun over the src page either ** */
- saved_code_page->va = PT32_PAGE_ADDR(info->rip);
-
- new_code_page->page_addr = code_page;
- new_code_page->va = PT32_PAGE_ADDR(info->rip);
-
- new_code_page->pte.present = 1;
- new_code_page->pte.writable = 0;
- new_code_page->pte.user_page = 1;
- new_code_page->pte.page_base_addr = PT32_BASE_ADDR(code_page);
-
- memcpy((void *)(code_page + code_page_offset), instr, instr_info->instr_length);
- memcpy((void *)(code_page + code_page_offset + instr_info->instr_length), VMMCALL, 3);
-
-#ifdef DEBUG_EMULATOR
- PrintDebug("New Instr Stream:\n");
- PrintTraceMemDump((void *)(code_page + code_page_offset), 32);
- PrintDebug("rip =%x\n", info->rip);
-#endif
+ PrintDebug("STR_OP_LEN: %d, Page Len: %d\n",
+ (uint_t)dec_instr->str_op_length,
+ (uint_t)(0x1000 - PAGE_OFFSET_4KB(write_gva)));
+ PrintDebug("Emulation length: %d\n", emulation_length);
+ tmp_rcx = emulation_length;
+
+ if (guest_pa_to_host_va(info, write_gpa, dst_addr) == -1) {
+ PrintError("Could not translate write destination to host VA\n");
+ return -1;
+ }
+ // figure out addresses here....
+ if (info->mem_mode == PHYSICAL_MEM) {
+ if (guest_pa_to_host_va(info, dec_instr->src_operand.operand, &src_addr) == -1) {
+ PrintError("Could not translate write Source (Physical) to host VA\n");
+ return -1;
+ }
+ } else {
+ if (guest_va_to_host_va(info, dec_instr->src_operand.operand, &src_addr) == -1) {
+ PrintError("Could not translate write Source (Virtual) to host VA\n");
+ return -1;
+ }
+ }
- v3_replace_shdw_page32(info, new_code_page->va, &(new_code_page->pte), &(saved_code_page->pte));
+ PrintDebug("Dst Operand: %p (size=%d), Src Operand: %p\n",
+ (void *)dec_instr->dst_operand.operand,
+ dec_instr->dst_operand.size,
+ (void *)dec_instr->src_operand.operand);
+ PrintDebug("Dst Addr: %p, Src Addr: %p\n", (void *)(addr_t *)*dst_addr, (void *)src_addr);
+ //return -1;
- list_add(&(new_code_page->page_list), &(info->emulator.emulated_pages));
- info->emulator.num_emulated_pages++;
- list_add(&(saved_code_page->page_list), &(info->emulator.saved_pages));
- info->emulator.num_saved_pages++;
+
- return 0;
-}
-*/
+ if (dec_instr->dst_operand.size == 1) {
+ movs8(dst_addr, &src_addr, &tmp_rcx, (addr_t *)&(info->ctrl_regs.rflags));
+ } else if (dec_instr->dst_operand.size == 2) {
+ movs16(dst_addr, &src_addr, &tmp_rcx, (addr_t *)&(info->ctrl_regs.rflags));
+ } else if (dec_instr->dst_operand.size == 4) {
+ movs32(dst_addr, &src_addr, &tmp_rcx, (addr_t *)&(info->ctrl_regs.rflags));
+ } else {
+ PrintError("Invalid operand length\n");
+ return -1;
+ }
-static int set_stepping(struct guest_info * info) {
- vmcb_ctrl_t * ctrl_area = GET_VMCB_CTRL_AREA((vmcb_t*)(info->vmm_data));
- ctrl_area->exceptions.db = 1;
- info->emulator.tf_enabled = ((struct rflags *)&(info->ctrl_regs.rflags))->tf;
- ((struct rflags *)&(info->ctrl_regs.rflags))->tf = 1;
- return 0;
-}
+ PrintDebug("RDI=%p, RSI=%p, RCX=%p\n",
+ (void *)*(addr_t *)&(info->vm_regs.rdi),
+ (void *)*(addr_t *)&(info->vm_regs.rsi),
+ (void *)*(addr_t *)&(info->vm_regs.rcx));
-static int unset_stepping(struct guest_info * info) {
- vmcb_ctrl_t * ctrl_area = GET_VMCB_CTRL_AREA((vmcb_t*)(info->vmm_data));
- ctrl_area->exceptions.db = 0;
+ info->vm_regs.rdi += emulation_length;
+ info->vm_regs.rsi += emulation_length;
+ info->vm_regs.rcx -= emulation_length;
+
+ PrintDebug("RDI=%p, RSI=%p, RCX=%p\n",
+ (void *)*(addr_t *)&(info->vm_regs.rdi),
+ (void *)*(addr_t *)&(info->vm_regs.rsi),
+ (void *)*(addr_t *)&(info->vm_regs.rcx));
- ((struct rflags *)&(info->ctrl_regs.rflags))->tf = info->emulator.tf_enabled;
+ if (emulation_length == dec_instr->str_op_length) {
+ info->rip += dec_instr->instr_length;
+ }
- if (info->emulator.tf_enabled) {
- // Inject breakpoint exception into guest
+ return emulation_length;
}
- return 0;
+
+
+ return -1;
}
-// get the current instr
-// check if rep + remove
-// put into new page, vmexit after
-// replace new page with current eip page
-//
-int v3_emulate_memory_read(struct guest_info * info, addr_t read_gva,
- int (*read)(addr_t read_addr, void * dst, uint_t length, void * priv_data),
- addr_t read_gpa, void * private_data) {
- struct basic_instr_info instr_info;
+int v3_emulate_write_op(struct guest_info * info, addr_t write_gva, addr_t write_gpa, addr_t * dst_addr) {
+ struct x86_instr dec_instr;
uchar_t instr[15];
- int ret;
- struct emulated_page * data_page = V3_Malloc(sizeof(struct emulated_page));
- addr_t data_addr_offset = PAGE_OFFSET(read_gva);
- pte32_t saved_pte;
+ int ret = 0;
+ addr_t src_addr = 0;
+
- PrintDebug("Emulating Read\n");
+ PrintDebug("Emulating Write for instruction at %p\n", (void *)(addr_t)(info->rip));
+ PrintDebug("GPA=%p, GVA=%p\n", (void *)write_gpa, (void *)write_gva);
if (info->mem_mode == PHYSICAL_MEM) {
ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
}
if (ret == -1) {
- PrintError("Could not read guest memory\n");
return -1;
}
-#ifdef DEBUG_EMULATOR
- PrintDebug("Instr (15 bytes) at %p:\n", (void *)(addr_t)instr);
- PrintTraceMemDump(instr, 15);
-#endif
-
- if (v3_basic_mem_decode(info, (addr_t)instr, &instr_info) == -1) {
- PrintError("Could not do a basic memory instruction decode\n");
- V3_Free(data_page);
+ if (guest_pa_to_host_va(info, write_gpa, dst_addr) == -1) {
+ PrintError("Could not translate write destination to host VA\n");
return -1;
}
- /*
- if (instr_info.has_rep == 1) {
- PrintError("We currently don't handle rep* instructions\n");
- V3_Free(data_page);
+ if (v3_decode(info, (addr_t)instr, &dec_instr) == -1) {
+ PrintError("Decoding Error\n");
+ // Kick off single step emulator
return -1;
}
- */
-
- data_page->page_addr = get_new_page();
- data_page->va = PAGE_ADDR(read_gva);
- data_page->pte.present = 1;
- data_page->pte.writable = 0;
- data_page->pte.user_page = 1;
- data_page->pte.page_base_addr = PAGE_BASE_ADDR((addr_t)V3_PAddr((void *)(addr_t)(data_page->page_addr)));
-
-
- // Read the data directly onto the emulated page
- ret = read(read_gpa, (void *)(data_page->page_addr + data_addr_offset), instr_info.op_size, private_data);
- if ((ret == -1) || ((uint_t)ret != instr_info.op_size)) {
- PrintError("Read error in emulator\n");
- V3_FreePage((void *)V3_PAddr((void *)(data_page->page_addr)));
- V3_Free(data_page);
- return -1;
+
+ if (dec_instr.is_str_op) {
+ return emulate_string_write_op(info, &dec_instr, write_gva, write_gpa, dst_addr);
}
- v3_replace_shdw_page32(info, data_page->va, &(data_page->pte), &saved_pte);
-
-
- list_add(&(data_page->page_list), &(info->emulator.emulated_pages));
- info->emulator.num_emulated_pages++;
- if (saved_pte.present == 1) {
- struct saved_page * saved_data_page = V3_Malloc(sizeof(struct saved_page));
- saved_data_page->pte = saved_pte;
- saved_data_page->va = PAGE_ADDR(read_gva);
-
- list_add(&(saved_data_page->page_list), &(info->emulator.saved_pages));
- info->emulator.num_saved_pages++;
+ if ((dec_instr.dst_operand.type != MEM_OPERAND) ||
+ (dec_instr.dst_operand.operand != write_gva)) {
+ PrintError("Inconsistency between Pagefault and Instruction Decode XED_ADDR=%p, PF_ADDR=%p\n",
+ (void *)dec_instr.dst_operand.operand, (void *)write_gva);
+ return -1;
}
- // setup_code_page(info, instr, &instr_info);
- set_stepping(info);
-
- info->emulator.running = 1;
- info->run_state = VM_EMULATING;
- info->emulator.instr_length = instr_info.instr_length;
-
- return 0;
-}
-
-
-
-int v3_emulate_memory_write(struct guest_info * info, addr_t write_gva,
- int (*write)(addr_t write_addr, void * src, uint_t length, void * priv_data),
- addr_t write_gpa, void * private_data) {
-
- struct basic_instr_info instr_info;
- uchar_t instr[15];
- int ret;
- struct write_region * write_op = V3_Malloc(sizeof(struct write_region ));
- struct emulated_page * data_page = V3_Malloc(sizeof(struct emulated_page));
- addr_t data_addr_offset = PAGE_OFFSET(write_gva);
- pte32_t saved_pte;
- int i;
-
- PrintDebug("Emulating Write for instruction at 0x%p\n", (void *)(addr_t)(info->rip));
-
- if (info->mem_mode == PHYSICAL_MEM) {
- ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
- } else {
- ret = read_guest_va_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
+ if (dec_instr.src_operand.type == MEM_OPERAND) {
+ if (info->mem_mode == PHYSICAL_MEM) {
+ if (guest_pa_to_host_va(info, dec_instr.src_operand.operand, &src_addr) == -1) {
+ PrintError("Could not translate write Source (Physical) to host VA\n");
+ return -1;
+ }
+ } else {
+ if (guest_va_to_host_va(info, dec_instr.src_operand.operand, &src_addr) == -1) {
+ PrintError("Could not translate write Source (Virtual) to host VA\n");
+ return -1;
+ }
+ }
+ } else if (dec_instr.src_operand.type == REG_OPERAND) {
+ src_addr = dec_instr.src_operand.operand;
+ } else {
+ src_addr = (addr_t)&(dec_instr.src_operand.operand);
}
- PrintDebug("Instruction is");
- for (i=0;i<15;i++) { PrintDebug(" 0x%x",instr[i]); }
- PrintDebug("\n");
-
- if (v3_basic_mem_decode(info, (addr_t)instr, &instr_info) == -1) {
- PrintError("Could not do a basic memory instruction decode\n");
- V3_Free(write_op);
- V3_Free(data_page);
+ PrintDebug("Dst_Addr Ptr = %p (val=%p), SRC operand = %p\n",
+ (void *)dst_addr, (void *)*dst_addr, (void *)src_addr);
+
+
+ if (dec_instr.dst_operand.size == 1) {
+
+ switch (dec_instr.op_type) {
+ case V3_OP_ADC:
+ adc8((addr_t *)*dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
+ break;
+ case V3_OP_ADD:
+ add8((addr_t *)*dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
+ break;
+ case V3_OP_AND:
+ and8((addr_t *)*dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
+ break;
+ case V3_OP_OR:
+ or8((addr_t *)*dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
+ break;
+ case V3_OP_XOR:
+ xor8((addr_t *)*dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
+ break;
+ case V3_OP_SUB:
+ sub8((addr_t *)*dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
+ break;
+
+ case V3_OP_MOV:
+ mov8((addr_t *)*dst_addr, (addr_t *)src_addr);
+ break;
+ case V3_OP_NOT:
+ not8((addr_t *)*dst_addr);
+ break;
+ case V3_OP_XCHG:
+ xchg8((addr_t *)*dst_addr, (addr_t *)src_addr);
+ break;
+
+
+ case V3_OP_INC:
+ inc8((addr_t *)*dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
+ break;
+ case V3_OP_DEC:
+ dec8((addr_t *)*dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
+ break;
+ case V3_OP_NEG:
+ neg8((addr_t *)*dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
+ break;
+ case V3_OP_SETB:
+ setb8((addr_t *)*dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
+ break;
+ case V3_OP_SETBE:
+ setbe8((addr_t *)*dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
+ break;
+ case V3_OP_SETL:
+ setl8((addr_t *)*dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
+ break;
+ case V3_OP_SETLE:
+ setle8((addr_t *)*dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
+ break;
+ case V3_OP_SETNB:
+ setnb8((addr_t *)*dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
+ break;
+ case V3_OP_SETNBE:
+ setnbe8((addr_t *)*dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
+ break;
+ case V3_OP_SETNL:
+ setnl8((addr_t *)*dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
+ break;
+ case V3_OP_SETNLE:
+ setnle8((addr_t *)*dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
+ break;
+ case V3_OP_SETNO:
+ setno8((addr_t *)*dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
+ break;
+ case V3_OP_SETNP:
+ setnp8((addr_t *)*dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
+ break;
+ case V3_OP_SETNS:
+ setns8((addr_t *)*dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
+ break;
+ case V3_OP_SETNZ:
+ setnz8((addr_t *)*dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
+ break;
+ case V3_OP_SETO:
+ seto8((addr_t *)*dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
+ break;
+ case V3_OP_SETP:
+ setp8((addr_t *)*dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
+ break;
+ case V3_OP_SETS:
+ sets8((addr_t *)*dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
+ break;
+ case V3_OP_SETZ:
+ setz8((addr_t *)*dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
+ break;
+
+ default:
+ PrintError("Unknown 8 bit instruction\n");
+ return -1;
+ }
+
+ } else if (dec_instr.dst_operand.size == 2) {
+
+ switch (dec_instr.op_type) {
+ case V3_OP_ADC:
+ adc16((addr_t *)*dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
+ break;
+ case V3_OP_ADD:
+ add16((addr_t *)*dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
+ break;
+ case V3_OP_AND:
+ and16((addr_t *)*dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
+ break;
+ case V3_OP_OR:
+ or16((addr_t *)*dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
+ break;
+ case V3_OP_XOR:
+ xor16((addr_t *)*dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
+ break;
+ case V3_OP_SUB:
+ sub16((addr_t *)*dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
+ break;
+
+
+ case V3_OP_INC:
+ inc16((addr_t *)*dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
+ break;
+ case V3_OP_DEC:
+ dec16((addr_t *)*dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
+ break;
+ case V3_OP_NEG:
+ neg16((addr_t *)*dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
+ break;
+
+ case V3_OP_MOV:
+ mov16((addr_t *)*dst_addr, (addr_t *)src_addr);
+ break;
+ case V3_OP_NOT:
+ not16((addr_t *)*dst_addr);
+ break;
+ case V3_OP_XCHG:
+ xchg16((addr_t *)*dst_addr, (addr_t *)src_addr);
+ break;
+
+ default:
+ PrintError("Unknown 16 bit instruction\n");
+ return -1;
+ }
+
+ } else if (dec_instr.dst_operand.size == 4) {
+
+ switch (dec_instr.op_type) {
+ case V3_OP_ADC:
+ adc32((addr_t *)*dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
+ break;
+ case V3_OP_ADD:
+ add32((addr_t *)*dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
+ break;
+ case V3_OP_AND:
+ and32((addr_t *)*dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
+ break;
+ case V3_OP_OR:
+ or32((addr_t *)*dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
+ break;
+ case V3_OP_XOR:
+ xor32((addr_t *)*dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
+ break;
+ case V3_OP_SUB:
+ sub32((addr_t *)*dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
+ break;
+
+ case V3_OP_INC:
+ inc32((addr_t *)*dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
+ break;
+ case V3_OP_DEC:
+ dec32((addr_t *)*dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
+ break;
+ case V3_OP_NEG:
+ neg32((addr_t *)*dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
+ break;
+
+ case V3_OP_MOV:
+ mov32((addr_t *)*dst_addr, (addr_t *)src_addr);
+ break;
+ case V3_OP_NOT:
+ not32((addr_t *)*dst_addr);
+ break;
+ case V3_OP_XCHG:
+ xchg32((addr_t *)*dst_addr, (addr_t *)src_addr);
+ break;
+
+ default:
+ PrintError("Unknown 32 bit instruction\n");
+ return -1;
+ }
+
+ } else if (dec_instr.dst_operand.size == 8) {
+ PrintError("64 bit instructions not handled\n");
return -1;
- }
-
- if (instr_info.has_rep==1) {
- PrintDebug("Emulated instruction has rep\n");
- }
-
- /*
- if (instr_info.has_rep == 1) {
- PrintError("We currently don't handle rep* instructions\n");
- V3_Free(write_op);
- V3_Free(data_page);
+ } else {
+ PrintError("Invalid Operation Size\n");
return -1;
}
- */
- data_page->page_addr = get_new_page();
- data_page->va = PAGE_ADDR(write_gva);
- data_page->pte.present = 1;
- data_page->pte.writable = 1;
- data_page->pte.user_page = 1;
- data_page->pte.page_base_addr = PAGE_BASE_ADDR((addr_t)V3_PAddr((void *)(addr_t)(data_page->page_addr)));
+ info->rip += dec_instr.instr_length;
-
-
- write_op->write = write;
- write_op->write_addr = write_gpa;
- write_op->length = instr_info.op_size;
- write_op->private_data = private_data;
-
- write_op->write_data = (void *)(data_page->page_addr + data_addr_offset);
-
- list_add(&(write_op->write_list), &(info->emulator.write_regions));
- info->emulator.num_write_regions--;
-
- v3_replace_shdw_page32(info, data_page->va, &(data_page->pte), &saved_pte);
-
-
- list_add(&(data_page->page_list), &(info->emulator.emulated_pages));
- info->emulator.num_emulated_pages++;
-
- if (saved_pte.present == 1) {
- struct saved_page * saved_data_page = V3_Malloc(sizeof(struct saved_page));
- saved_data_page->pte = saved_pte;
- saved_data_page->va = PAGE_ADDR(write_gva);
-
- list_add(&(saved_data_page->page_list), &(info->emulator.saved_pages));
- info->emulator.num_saved_pages++;
- }
-
-
- if (info->emulator.running == 0) {
- // setup_code_page(info, instr, &instr_info);
- set_stepping(info);
- info->emulator.running = 1;
- info->run_state = VM_EMULATING;
- info->emulator.instr_length = instr_info.instr_length;
- }
-
- return 0;
+ return dec_instr.dst_operand.size;
}
-
-// end emulation
-int v3_emulation_exit_handler(struct guest_info * info) {
- struct saved_page * svpg, * p_svpg;
- struct emulated_page * empg, * p_empg;
- struct write_region * wr_reg, * p_wr_reg;
- pte32_t dummy_pte;
-
- // Complete the writes
- // delete writes
- // swap out emulated pages with blank dummies
- // swap in saved pages
- // increment rip
-
- PrintDebug("V3 Emulation Exit Handler\n");
-
- list_for_each_entry_safe(wr_reg, p_wr_reg, &(info->emulator.write_regions), write_list) {
- wr_reg->write(wr_reg->write_addr, wr_reg->write_data, wr_reg->length, wr_reg->private_data);
- PrintDebug("Writing \n");
-
- list_del(&(wr_reg->write_list));
- V3_Free(wr_reg);
-
- }
- info->emulator.num_write_regions = 0;
-
-
- *(uint_t *)&dummy_pte = 0;
-
- list_for_each_entry_safe(empg, p_empg, &(info->emulator.emulated_pages), page_list) {
- pte32_t empte32_t;
-
- PrintDebug("wiping page %p\n", (void *)(addr_t)(empg->va));
-
- v3_replace_shdw_page32(info, empg->va, &dummy_pte, &empte32_t);
- V3_FreePage((void *)(V3_PAddr((void *)(empg->page_addr))));
-
- list_del(&(empg->page_list));
- V3_Free(empg);
- }
- info->emulator.num_emulated_pages = 0;
-
- list_for_each_entry_safe(svpg, p_svpg, &(info->emulator.saved_pages), page_list) {
-
- PrintDebug("Setting Saved page %p back\n", (void *)(addr_t)(svpg->va));
- v3_replace_shdw_page32(info, empg->va, &(svpg->pte), &dummy_pte);
-
- list_del(&(svpg->page_list));
- V3_Free(svpg);
- }
- info->emulator.num_saved_pages = 0;
-
- info->run_state = VM_RUNNING;
- info->emulator.running = 0;
- //info->rip += info->emulator.instr_length;
-
-
- PrintDebug("Returning to rip: 0x%p\n", (void *)(addr_t)(info->rip));
-
- info->emulator.instr_length = 0;
-
-
- unset_stepping(info);
-
-
- PrintDebug("returning from emulation\n");
-
- return 0;
-}
+++ /dev/null
-#include <stdio.h>
-#include <stdlib.h>
-
-#define addr_t unsigned long
-
-
-
-
-void test() {
- int a = 10;
- int b;
-
- asm ("movl %1, %%eax\n\t"
- "movl %%eax, %0\n\t"
- :"=r"(b) /* output */
- :"r"(a) /* input */
- :"%eax" /* clobbered register */
- );
-
-}
-
-void get_flags(addr_t * flags) {
- addr_t tmp;
- asm ("pushfq\n\t"
- "pop %0\n\t"
- :"=r"(tmp)
- :
- );
-
- *flags = tmp;
-}
-
-void adc64(int * dst, int * src, addr_t * flags) {
- int tmp_dst = *dst, tmp_src = *src;
- addr_t tmp_flags = *flags;
-
- char * inst = "adcl";
-
- // Some of the flags values are not copied out in a pushf, we save them here
- addr_t flags_rsvd = *flags & ~0xfffe7fff;
-
- asm volatile (
- "pushfq\r\n"
- "push %3\r\n"
- "popfq\r\n"
- "adcl %2, %0\r\n"
- "pushfq\r\n"
- "pop %1\r\n"
- "popfq\r\n"
- : "=a"(tmp_dst),"=c"(tmp_flags)
- : "b"(tmp_src),"c"(tmp_flags), "0"(tmp_dst)
- );
-
- *dst = tmp_dst;
- *flags = tmp_flags;
- *flags |= flags_rsvd;
-
-}
-
-
-void adc32(int * dst, int * src, addr_t * flags) {
- int tmp_dst = *dst, tmp_src = *src;
- addr_t tmp_flags = *flags;
-
-
- asm volatile (
- "pushfd\r\n"
- "push %3\r\n"
- "popfd\r\n"
- "adcl %2, %0\r\n"
- "pushfd\r\n"
- "pop %1\r\n"
- "popfd\r\n"
- : "=a"(tmp_dst),"=c"(tmp_flags)
- : "b"(tmp_src),"c"(tmp_flags), "0"(tmp_dst)
- );
-
- *dst = tmp_dst;
- *flags = tmp_flags;
-
-}
-
-
-int main(int argc, char ** argv) {
- addr_t flags;
- int dest = 4;
- int src = 5;
-
- printf("sizeof ulong: %d\n", sizeof(unsigned long));
-
- printf("Getting flags\n");
- get_flags(&flags);
- flags = flags | 0x1;
-
- printf("Flags=0x%x\n", flags);
- test();
- printf("Adding\n");
- adc64(&dest, &src, &flags);
- printf("Result=%d\n", dest);
-
-}
void init_shadow_region(struct shadow_region * entry,
addr_t guest_addr_start,
addr_t guest_addr_end,
- guest_region_type_t guest_region_type,
- host_region_type_t host_region_type)
+ shdw_region_type_t shdw_region_type)
{
- entry->guest_type = guest_region_type;
entry->guest_start = guest_addr_start;
entry->guest_end = guest_addr_end;
- entry->host_type = host_region_type;
+ entry->host_type = shdw_region_type;
entry->host_addr = 0;
- entry->next=entry->prev = NULL;
+ entry->next = entry->prev = NULL;
}
int add_shadow_region_passthrough( struct guest_info * guest_info,
struct shadow_region * entry = (struct shadow_region *)V3_Malloc(sizeof(struct shadow_region));
init_shadow_region(entry, guest_addr_start, guest_addr_end,
- GUEST_REGION_PHYSICAL_MEMORY, HOST_REGION_PHYSICAL_MEMORY);
+ SHDW_REGION_ALLOCATED);
entry->host_addr = host_addr;
return add_shadow_region(&(guest_info->mem_map), entry);
}
-int hook_guest_mem(struct guest_info * info, addr_t guest_addr_start, addr_t guest_addr_end,
- int (*read)(addr_t guest_addr, void * dst, uint_t length, void * priv_data),
- int (*write)(addr_t guest_addr, void * src, uint_t length, void * priv_data),
- void * priv_data) {
-
- struct shadow_region * entry = (struct shadow_region *)V3_Malloc(sizeof(struct shadow_region));
- struct vmm_mem_hook * hook = (struct vmm_mem_hook *)V3_Malloc(sizeof(struct vmm_mem_hook));
-
- memset(hook, 0, sizeof(struct vmm_mem_hook));
-
- hook->read = read;
- hook->write = write;
- hook->region = entry;
- hook->priv_data = priv_data;
+int v3_hook_write_mem(struct guest_info * info, addr_t guest_addr_start, addr_t guest_addr_end,
+ addr_t host_addr,
+ int (*write)(addr_t guest_addr, void * src, uint_t length, void * priv_data),
+ void * priv_data) {
+ struct shadow_region * entry = (struct shadow_region *)V3_Malloc(sizeof(struct shadow_region));
init_shadow_region(entry, guest_addr_start, guest_addr_end,
- GUEST_REGION_PHYSICAL_MEMORY, HOST_REGION_HOOK);
+ SHDW_REGION_WRITE_HOOK);
- entry->host_addr = (addr_t)hook;
+ entry->write_hook = write;
+ entry->read_hook = NULL;
+ entry->host_addr = host_addr;
+ entry->priv_data = priv_data;
- return add_shadow_region(&(info->mem_map), entry);
+ return add_shadow_region(&(info->mem_map), entry);
}
+int v3_hook_full_mem(struct guest_info * info, addr_t guest_addr_start, addr_t guest_addr_end,
+ int (*read)(addr_t guest_addr, void * dst, uint_t length, void * priv_data),
+ int (*write)(addr_t guest_addr, void * src, uint_t length, void * priv_data),
+ void * priv_data) {
+
+ struct shadow_region * entry = (struct shadow_region *)V3_Malloc(sizeof(struct shadow_region));
-struct vmm_mem_hook * get_mem_hook(struct guest_info * info, addr_t guest_addr) {
- struct shadow_region * region = get_shadow_region_by_addr(&(info->mem_map), guest_addr);
-
- if (region == NULL) {
- PrintDebug("Could not find shadow region for addr: %p\n", (void *)guest_addr);
- return NULL;
- }
-
- return (struct vmm_mem_hook *)(region->host_addr);
-}
-
+ init_shadow_region(entry, guest_addr_start, guest_addr_end,
+ SHDW_REGION_FULL_HOOK);
-/* mem_addr is the guest physical memory address */
-static int mem_hook_dispatch(struct guest_info * info,
- addr_t fault_gva, addr_t fault_gpa,
- pf_error_t access_info, struct vmm_mem_hook * hook)
-{
+ entry->write_hook = write;
+ entry->read_hook = read;
+ entry->priv_data = priv_data;
- // emulate and then dispatch
- // or dispatch and emulate
+ entry->host_addr = 0;
+ return add_shadow_region(&(info->mem_map), entry);
+}
- if (access_info.write == 1) {
- if (v3_emulate_memory_write(info, fault_gva, hook->write, fault_gpa, hook->priv_data) == -1) {
- PrintError("Memory write emulation failed\n");
- return -1;
- }
-
- } else {
- if (v3_emulate_memory_read(info, fault_gva, hook->read, fault_gpa, hook->priv_data) == -1) {
- PrintError("Memory read emulation failed\n");
- return -1;
- }
- }
- return 0;
-}
int handle_special_page_fault(struct guest_info * info,
addr_t fault_gva, addr_t fault_gpa,
pf_error_t access_info)
{
- struct shadow_region * reg = get_shadow_region_by_addr(&(info->mem_map), fault_gpa);
+ struct shadow_region * reg = get_shadow_region_by_addr(&(info->mem_map), fault_gpa);
PrintDebug("Handling Special Page Fault\n");
switch (reg->host_type) {
- case HOST_REGION_HOOK:
- return mem_hook_dispatch(info, fault_gva, fault_gpa, access_info, (struct vmm_mem_hook *)(reg->host_addr));
+ case SHDW_REGION_WRITE_HOOK:
+ return v3_handle_mem_wr_hook(info, fault_gva, fault_gpa, reg, access_info);
+ case SHDW_REGION_FULL_HOOK:
+ return v3_handle_mem_full_hook(info, fault_gva, fault_gpa, reg, access_info);
default:
return -1;
}
}
+int v3_handle_mem_wr_hook(struct guest_info * info, addr_t guest_va, addr_t guest_pa,
+ struct shadow_region * reg, pf_error_t access_info) {
+
+ addr_t write_src_addr = 0;
+
+ int write_len = v3_emulate_write_op(info, guest_va, guest_pa, &write_src_addr);
+
+ if (write_len == -1) {
+ PrintError("Emulation failure in write hook\n");
+ return -1;
+ }
+
+
+ if (reg->write_hook(guest_pa, (void *)write_src_addr, write_len, reg->priv_data) != write_len) {
+ PrintError("Memory write hook did not return correct value\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+int v3_handle_mem_full_hook(struct guest_info * info, addr_t guest_va, addr_t guest_pa,
+ struct shadow_region * reg, pf_error_t access_info) {
+ return -1;
+}
+
+
+
+struct shadow_region * v3_get_shadow_region(struct guest_info * info, addr_t addr) {
+ struct shadow_region * reg = info->mem_map.head;
+
+ while (reg) {
+ if ((reg->guest_start <= addr) && (reg->guest_end > addr)) {
+ return reg;
+ } else if (reg->guest_start > addr) {
+ return NULL;
+ } else {
+ reg = reg->next;
+ }
+ }
+ return NULL;
+}
void init_shadow_map(struct guest_info * info) {
}
-host_region_type_t get_shadow_addr_type(struct guest_info * info, addr_t guest_addr) {
+shdw_region_type_t get_shadow_addr_type(struct guest_info * info, addr_t guest_addr) {
struct shadow_region * reg = get_shadow_region_by_addr(&(info->mem_map), guest_addr);
if (!reg) {
- return HOST_REGION_INVALID;
+ return SHDW_REGION_INVALID;
} else {
return reg->host_type;
}
}
-host_region_type_t lookup_shadow_map_addr(struct shadow_map * map, addr_t guest_addr, addr_t * host_addr) {
+shdw_region_type_t lookup_shadow_map_addr(struct shadow_map * map, addr_t guest_addr, addr_t * host_addr) {
struct shadow_region * reg = get_shadow_region_by_addr(map, guest_addr);
if (!reg) {
// No mapping exists
- return HOST_REGION_INVALID;
+ return SHDW_REGION_INVALID;
} else {
switch (reg->host_type) {
- case HOST_REGION_PHYSICAL_MEMORY:
+ case SHDW_REGION_ALLOCATED:
+ case SHDW_REGION_WRITE_HOOK:
*host_addr = (guest_addr - reg->guest_start) + reg->host_addr;
return reg->host_type;
- case HOST_REGION_MEMORY_MAPPED_DEVICE:
- case HOST_REGION_UNALLOCATED:
+ case SHDW_REGION_UNALLOCATED:
+ case SHDW_REGION_FULL_HOOK:
// ...
default:
*host_addr = 0;
PrintDebug("Memory Layout (regions: %d) \n", map->num_regions);
while (cur) {
- PrintDebug("%d: 0x%p - 0x%p (%s) -> ", i,
- (void *)cur->guest_start, (void *)(cur->guest_end - 1),
- cur->guest_type == GUEST_REGION_PHYSICAL_MEMORY ? "GUEST_REGION_PHYSICAL_MEMORY" :
- cur->guest_type == GUEST_REGION_NOTHING ? "GUEST_REGION_NOTHING" :
- cur->guest_type == GUEST_REGION_MEMORY_MAPPED_DEVICE ? "GUEST_REGION_MEMORY_MAPPED_DEVICE" :
- "UNKNOWN");
- if (cur->host_type == HOST_REGION_PHYSICAL_MEMORY ||
- cur->host_type == HOST_REGION_UNALLOCATED ||
- cur->host_type == HOST_REGION_MEMORY_MAPPED_DEVICE) {
+ PrintDebug("%d: 0x%p - 0x%p -> ", i,
+ (void *)cur->guest_start, (void *)(cur->guest_end - 1));
+ if (cur->host_type == SHDW_REGION_ALLOCATED ||
+ cur->host_type == SHDW_REGION_UNALLOCATED) {
PrintDebug("0x%p", (void *)(cur->host_addr));
}
- PrintDebug("(%s)\n",
- cur->host_type == HOST_REGION_PHYSICAL_MEMORY ? "HOST_REGION_PHYSICAL_MEMORY" :
- cur->host_type == HOST_REGION_UNALLOCATED ? "HOST_REGION_UNALLOACTED" :
- cur->host_type == HOST_REGION_HOOK ? "HOST_REGION_HOOK" :
- cur->host_type == HOST_REGION_MEMORY_MAPPED_DEVICE ? "HOST_REGION_MEMORY_MAPPED_DEVICE" :
- cur->host_type == HOST_REGION_REMOTE ? "HOST_REGION_REMOTE" :
- cur->host_type == HOST_REGION_SWAPPED ? "HOST_REGION_SWAPPED" :
- "UNKNOWN");
+ PrintDebug("(%s)\n", shdw_region_type_to_str(cur->host_type));
cur = cur->next;
i++;
}
}
+static const uchar_t SHDW_REGION_INVALID_STR[] = "SHDW_REGION_INVALID";
+static const uchar_t SHDW_REGION_WRITE_HOOK_STR[] = "SHDW_REGION_WRITE_HOOK";
+static const uchar_t SHDW_REGION_FULL_HOOK_STR[] = "SHDW_REGION_FULL_HOOK";
+static const uchar_t SHDW_REGION_ALLOCATED_STR[] = "SHDW_REGION_ALLOCATED";
+static const uchar_t SHDW_REGION_UNALLOCATED_STR[] = "SHDW_REGION_UNALLOCATED";
+
+
+const uchar_t * shdw_region_type_to_str(shdw_region_type_t type) {
+ switch (type) {
+ case SHDW_REGION_INVALID:
+ return SHDW_REGION_INVALID_STR;
+ case SHDW_REGION_WRITE_HOOK:
+ return SHDW_REGION_WRITE_HOOK_STR;
+ case SHDW_REGION_FULL_HOOK:
+ return SHDW_REGION_FULL_HOOK_STR;
+ case SHDW_REGION_ALLOCATED:
+ return SHDW_REGION_ALLOCATED_STR;
+ case SHDW_REGION_UNALLOCATED:
+ return SHDW_REGION_UNALLOCATED_STR;
+ default:
+ return SHDW_REGION_INVALID_STR;
+ }
+}
struct shadow_region * region = get_shadow_region_by_addr(map, current_page_addr);
if (!region ||
- (region->host_type == HOST_REGION_HOOK) ||
- (region->host_type == HOST_REGION_UNALLOCATED) ||
- (region->host_type == HOST_REGION_MEMORY_MAPPED_DEVICE) ||
- (region->host_type == HOST_REGION_REMOTE) ||
- (region->host_type == HOST_REGION_SWAPPED)) {
+ (region->host_type == SHDW_REGION_FULL_HOOK) ||
+ (region->host_type == SHDW_REGION_UNALLOCATED)) {
pte[j].present = 0;
pte[j].writable = 0;
pte[j].user_page = 0;
} else {
addr_t host_addr;
pte[j].present = 1;
- pte[j].writable = 1;
+
+ if (region->host_type == SHDW_REGION_WRITE_HOOK) {
+ pte[j].writable = 0;
+ PrintDebug("Marking Write hook host_addr %p as RO\n", (void *)current_page_addr);
+ } else {
+ pte[j].writable = 1;
+ }
+
pte[j].user_page = 1;
pte[j].write_through = 0;
pte[j].cache_disable = 0;
struct shadow_region * region = get_shadow_region_by_addr(map, current_page_addr);
if (!region ||
- (region->host_type == HOST_REGION_HOOK) ||
- (region->host_type == HOST_REGION_UNALLOCATED) ||
- (region->host_type == HOST_REGION_MEMORY_MAPPED_DEVICE) ||
- (region->host_type == HOST_REGION_REMOTE) ||
- (region->host_type == HOST_REGION_SWAPPED)) {
+ (region->host_type == SHDW_REGION_FULL_HOOK) ||
+ (region->host_type == SHDW_REGION_UNALLOCATED)) {
pte[k].present = 0;
pte[k].writable = 0;
pte[k].user_page = 0;
} else {
addr_t host_addr;
pte[k].present = 1;
- pte[k].writable = 1;
+
+ if (region->host_type == SHDW_REGION_WRITE_HOOK) {
+ pte[k].writable = 0;
+ } else {
+ pte[k].writable = 1;
+ }
+
pte[k].user_page = 1;
pte[k].write_through = 0;
pte[k].cache_disable = 0;
if (!region ||
- (region->host_type == HOST_REGION_HOOK) ||
- (region->host_type == HOST_REGION_UNALLOCATED) ||
- (region->host_type == HOST_REGION_MEMORY_MAPPED_DEVICE) ||
- (region->host_type == HOST_REGION_REMOTE) ||
- (region->host_type == HOST_REGION_SWAPPED)) {
+ (region->host_type == SHDW_REGION_FULL_HOOK) ||
+ (region->host_type == SHDW_REGION_UNALLOCATED)) {
pte[m].present = 0;
pte[m].writable = 0;
pte[m].user_page = 0;
} else {
addr_t host_addr;
pte[m].present = 1;
- pte[m].writable = 1;
+
+ if (region->host_type == SHDW_REGION_WRITE_HOOK) {
+ pte[m].writable = 0;
+ } else {
+ pte[m].writable = 1;
+ }
+
pte[m].user_page = 1;
pte[m].write_through = 0;
pte[m].cache_disable = 0;
linux/lib/rbtree.c
*/
-#include <linux/rbtree.h>
-#include <linux/module.h>
+#include <palacios/vmm_rbtree.h>
+
static void __rb_rotate_left(struct rb_node *node, struct rb_root *root)
{
rb_set_parent(node, left);
}
-void rb_insert_color(struct rb_node *node, struct rb_root *root)
+void v3_rb_insert_color(struct rb_node *node, struct rb_root *root)
{
struct rb_node *parent, *gparent;
rb_set_black(root->rb_node);
}
-EXPORT_SYMBOL(rb_insert_color);
+
static void __rb_erase_color(struct rb_node *node, struct rb_node *parent,
struct rb_root *root)
rb_set_black(node);
}
-void rb_erase(struct rb_node *node, struct rb_root *root)
+void v3_rb_erase(struct rb_node *node, struct rb_root *root)
{
struct rb_node *child, *parent;
int color;
if (color == RB_BLACK)
__rb_erase_color(child, parent, root);
}
-EXPORT_SYMBOL(rb_erase);
+
/*
* This function returns the first node (in sort order) of the tree.
*/
-struct rb_node *rb_first(struct rb_root *root)
+struct rb_node *v3_rb_first(struct rb_root *root)
{
struct rb_node *n;
n = n->rb_left;
return n;
}
-EXPORT_SYMBOL(rb_first);
-struct rb_node *rb_last(struct rb_root *root)
+
+struct rb_node *v3_rb_last(struct rb_root *root)
{
struct rb_node *n;
n = n->rb_right;
return n;
}
-EXPORT_SYMBOL(rb_last);
-struct rb_node *rb_next(struct rb_node *node)
+
+struct rb_node *v3_rb_next(struct rb_node *node)
{
struct rb_node *parent;
return parent;
}
-EXPORT_SYMBOL(rb_next);
-struct rb_node *rb_prev(struct rb_node *node)
+
+struct rb_node *v3_rb_prev(struct rb_node *node)
{
struct rb_node *parent;
return parent;
}
-EXPORT_SYMBOL(rb_prev);
-void rb_replace_node(struct rb_node *victim, struct rb_node *new,
+
+void v3_rb_replace_node(struct rb_node *victim, struct rb_node *new,
struct rb_root *root)
{
struct rb_node *parent = rb_parent(victim);
/* Copy the pointers/colour from the victim to the replacement */
*new = *victim;
}
-EXPORT_SYMBOL(rb_replace_node);
+
{
pt_access_status_t shadow_pte_access = v3_can_access_pte32(shadow_pt, fault_addr, error_code);
pte32_t * shadow_pte = (pte32_t *)&(shadow_pt[PTE32_INDEX(fault_addr)]);
-
+ addr_t guest_fault_pa = BASE_TO_PAGE_ADDR_4MB(large_guest_pde->page_base_addr) + PAGE_OFFSET_4MB(fault_addr);
+
if (shadow_pte_access == PT_ACCESS_OK) {
// Inconsistent state...
// Guest Re-Entry will flush tables and everything should now workd
if (shadow_pte_access == PT_ACCESS_NOT_PRESENT) {
// Get the guest physical address of the fault
- addr_t guest_fault_pa = BASE_TO_PAGE_ADDR_4MB(large_guest_pde->page_base_addr) + PAGE_OFFSET_4MB(fault_addr);
- host_region_type_t host_page_type = get_shadow_addr_type(info, guest_fault_pa);
+ shdw_region_type_t host_page_type = get_shadow_addr_type(info, guest_fault_pa);
- if (host_page_type == HOST_REGION_INVALID) {
+ if (host_page_type == SHDW_REGION_INVALID) {
// Inject a machine check in the guest
PrintDebug("Invalid Guest Address in page table (0x%p)\n", (void *)guest_fault_pa);
v3_raise_exception(info, MC_EXCEPTION);
return 0;
}
- if (host_page_type == HOST_REGION_PHYSICAL_MEMORY) {
+ if ((host_page_type == SHDW_REGION_ALLOCATED) ||
+ (host_page_type == SHDW_REGION_WRITE_HOOK)) {
struct shadow_page_state * state = &(info->shdw_pg_state);
addr_t shadow_pa = get_shadow_addr(info, guest_fault_pa);
PrintDebug("Marking page as Guest Page Table (large page)\n");
shadow_pte->vmm_info = PT32_GUEST_PT;
shadow_pte->writable = 0;
+ } else if (host_page_type == SHDW_REGION_WRITE_HOOK) {
+ shadow_pte->writable = 0;
} else {
shadow_pte->writable = 1;
}
-
//set according to VMM policy
shadow_pte->write_through = 0;
shadow_pte->cache_disable = 0;
} else {
// Handle hooked pages as well as other special pages
- if (handle_special_page_fault(info, fault_addr, guest_fault_pa, error_code) == -1) {
+ // if (handle_special_page_fault(info, fault_addr, guest_fault_pa, error_code) == -1) {
+ struct shadow_region * reg = v3_get_shadow_region(info, guest_fault_pa);
+
+ if (v3_handle_mem_full_hook(info, fault_addr, guest_fault_pa, reg, error_code) == -1) {
PrintError("Special Page Fault handler returned error for address: %p\n", (void *)fault_addr);
return -1;
}
}
- } else if ((shadow_pte_access == PT_ACCESS_WRITE_ERROR) &&
- (shadow_pte->vmm_info == PT32_GUEST_PT)) {
+ } else if (shadow_pte_access == PT_ACCESS_WRITE_ERROR) {
+ shdw_region_type_t host_page_type = get_shadow_addr_type(info, guest_fault_pa);
+
+ if (host_page_type == SHDW_REGION_WRITE_HOOK) {
+ struct shadow_region * reg = v3_get_shadow_region(info, guest_fault_pa);
- struct shadow_page_state * state = &(info->shdw_pg_state);
- PrintDebug("Write operation on Guest PAge Table Page (large page)\n");
- state->cached_cr3 = 0;
- shadow_pte->writable = 1;
+ if (v3_handle_mem_wr_hook(info, fault_addr, guest_fault_pa, reg, error_code) == -1) {
+ PrintError("Special Page Fault handler returned error for address: %p\n", (void *)fault_addr);
+ return -1;
+ }
+ } else if (shadow_pte->vmm_info == PT32_GUEST_PT) {
+ struct shadow_page_state * state = &(info->shdw_pg_state);
+ PrintDebug("Write operation on Guest PAge Table Page (large page)\n");
+ state->cached_cr3 = 0;
+ shadow_pte->writable = 1;
+ }
} else {
PrintError("Error in large page fault handler...\n");
pt_access_status_t shadow_pte_access;
pte32_t * guest_pte = (pte32_t *)&(guest_pt[PTE32_INDEX(fault_addr)]);;
pte32_t * shadow_pte = (pte32_t *)&(shadow_pt[PTE32_INDEX(fault_addr)]);
+ addr_t guest_pa = BASE_TO_PAGE_ADDR((addr_t)(guest_pte->page_base_addr)) + PAGE_OFFSET(fault_addr);
// Check the guest page permissions
if (shadow_pte_access == PT_ACCESS_NOT_PRESENT) {
- addr_t guest_pa = BASE_TO_PAGE_ADDR((addr_t)(guest_pte->page_base_addr)) + PAGE_OFFSET(fault_addr);
// Page Table Entry Not Present
PrintDebug("guest_pa =%p\n", (void *)guest_pa);
- host_region_type_t host_page_type = get_shadow_addr_type(info, guest_pa);
+ shdw_region_type_t host_page_type = get_shadow_addr_type(info, guest_pa);
- if (host_page_type == HOST_REGION_INVALID) {
+ if (host_page_type == SHDW_REGION_INVALID) {
// Inject a machine check in the guest
PrintDebug("Invalid Guest Address in page table (0x%p)\n", (void *)guest_pa);
v3_raise_exception(info, MC_EXCEPTION);
// else...
- if (host_page_type == HOST_REGION_PHYSICAL_MEMORY) {
+ if ((host_page_type == SHDW_REGION_ALLOCATED) ||
+ (host_page_type == SHDW_REGION_WRITE_HOOK)) {
struct shadow_page_state * state = &(info->shdw_pg_state);
addr_t shadow_pa = get_shadow_addr(info, guest_pa);
shadow_pte->vmm_info = PT32_GUEST_PT;
}
- if (guest_pte->dirty == 1) {
+ if (host_page_type == SHDW_REGION_WRITE_HOOK) {
+ shadow_pte->writable = 0;
+ } else if (guest_pte->dirty == 1) {
shadow_pte->writable = guest_pte->writable;
} else if ((guest_pte->dirty == 0) && (error_code.write == 1)) {
shadow_pte->writable = guest_pte->writable;
shadow_pte->writable = 0;
}
-
-
} else {
// Page fault handled by hook functions
- if (handle_special_page_fault(info, fault_addr, guest_pa, error_code) == -1) {
+ struct shadow_region * reg = v3_get_shadow_region(info, guest_pa);
+
+ if (v3_handle_mem_full_hook(info, fault_addr, guest_pa, reg, error_code) == -1) {
PrintError("Special Page fault handler returned error for address: %p\n", (void *)fault_addr);
return -1;
}
}
-
+ /*
} else if ((shadow_pte_access == PT_ACCESS_WRITE_ERROR) &&
(guest_pte->dirty == 0)) {
-
- PrintDebug("Shadow PTE Write Error\n");
+ */
+ } else if (shadow_pte_access == PT_ACCESS_WRITE_ERROR) {
guest_pte->dirty = 1;
- shadow_pte->writable = guest_pte->writable;
+
+ shdw_region_type_t host_page_type = get_shadow_addr_type(info, guest_pa);
+
+ if (host_page_type == SHDW_REGION_WRITE_HOOK) {
+ struct shadow_region * reg = v3_get_shadow_region(info, guest_pa);
+
+ if (v3_handle_mem_wr_hook(info, fault_addr, guest_pa, reg, error_code) == -1) {
+ PrintError("Special Page fault handler returned error for address: %p\n", (void *)fault_addr);
+ return -1;
+ }
+ } else {
+ PrintDebug("Shadow PTE Write Error\n");
+ shadow_pte->writable = guest_pte->writable;
+ }
if (shadow_pte->vmm_info == PT32_GUEST_PT) {
struct shadow_page_state * state = &(info->shdw_pg_state);
PrintDebug("Write operation on Guest PAge Table Page\n");
state->cached_cr3 = 0;
}
-
+
return 0;
} else {
#include <xed/xed-interface.h>
#include "vm_guest.h"
#include "test.h"
+
#else
+
#include <palacios/vmm_decoder.h>
#include <palacios/vmm_xed.h>
#include <xed/xed-interface.h>
#include <palacios/vm_guest.h>
#include <palacios/vmm.h>
-
-
#endif
-static xed_state_t decoder_state;
+
+static uint_t tables_inited = 0;
+
#define GPR_REGISTER 0
#define SEGMENT_REGISTER 1
-// This returns a pointer to a V3_OPCODE_[*] array defined in vmm_decoder.h
-static int get_opcode(xed_iform_enum_t iform, addr_t * opcode);
+
+static v3_op_type_t get_opcode(xed_iform_enum_t iform);
static int xed_reg_to_v3_reg(struct guest_info * info, xed_reg_enum_t xed_reg, addr_t * v3_reg, uint_t * reg_len);
static int get_memory_operand(struct guest_info * info, xed_decoded_inst_t * xed_instr, uint_t index, struct x86_operand * operand);
-int v3_init_decoder() {
- xed_tables_init();
- xed_state_zero(&decoder_state);
+int v3_init_decoder(struct guest_info * info) {
+ // Global library initialization, only do it once
+ if (tables_inited == 0) {
+ xed_tables_init();
+ tables_inited = 1;
+ }
+
+ xed_state_t * decoder_state = (xed_state_t *)V3_Malloc(sizeof(xed_state_t));
+ xed_state_zero(decoder_state);
+
+ info->decoder_state = decoder_state;
+
return 0;
}
xed_error_enum_t xed_error;
- if (set_decoder_mode(info, &decoder_state) == -1) {
+ if (set_decoder_mode(info, info->decoder_state) == -1) {
PrintError("Could not set decoder mode\n");
return -1;
}
- xed_decoded_inst_zero_set_mode(&xed_instr, &decoder_state);
+ xed_decoded_inst_zero_set_mode(&xed_instr, info->decoder_state);
xed_error = xed_decode(&xed_instr,
REINTERPRET_CAST(const xed_uint8_t *, instr_ptr),
}
+static int decode_string_op(struct guest_info * info,
+ xed_decoded_inst_t * xed_instr, const xed_inst_t * xi,
+ struct x86_instr * instr) {
+
+ PrintDebug("String operation\n");
+
+ if (instr->op_type == V3_OP_MOVS) {
+ instr->num_operands = 2;
+
+ if (get_memory_operand(info, xed_instr, 0, &(instr->dst_operand)) == -1) {
+ PrintError("Could not get Destination memory operand\n");
+ return -1;
+ }
+
+ if (get_memory_operand(info, xed_instr, 1, &(instr->src_operand)) == -1) {
+ PrintError("Could not get Source memory operand\n");
+ return -1;
+ }
+
+ if (instr->prefixes.rep == 1) {
+ addr_t reg_addr = 0;
+ uint_t reg_length = 0;
+
+ xed_reg_to_v3_reg(info, xed_decoded_inst_get_reg(xed_instr, XED_OPERAND_REG0), ®_addr, ®_length);
+ instr->str_op_length = MASK(*(addr_t *)reg_addr, reg_length);
+ } else {
+ instr->str_op_length = 1;
+ }
+
+ }
+
+ return 0;
+}
+
+
int v3_decode(struct guest_info * info, addr_t instr_ptr, struct x86_instr * instr) {
xed_decoded_inst_t xed_instr;
xed_error_enum_t xed_error;
+ v3_get_prefixes((uchar_t *)instr_ptr, &(instr->prefixes));
- if (set_decoder_mode(info, &decoder_state) == -1) {
+ if (set_decoder_mode(info, info->decoder_state) == -1) {
PrintError("Could not set decoder mode\n");
return -1;
}
-
-
- xed_decoded_inst_zero_set_mode(&xed_instr, &decoder_state);
+ xed_decoded_inst_zero_set_mode(&xed_instr, info->decoder_state);
xed_error = xed_decode(&xed_instr,
REINTERPRET_CAST(const xed_uint8_t *, instr_ptr),
const xed_inst_t * xi = xed_decoded_inst_inst(&xed_instr);
instr->instr_length = xed_decoded_inst_get_length(&xed_instr);
- instr->num_operands = xed_decoded_inst_noperands(&xed_instr);
+
xed_iform_enum_t iform = xed_decoded_inst_get_iform_enum(&xed_instr);
+#ifdef DEBUG_XED
+ xed_iclass_enum_t iclass = xed_decoded_inst_get_iclass(&xed_instr);
- PrintDebug("iform=%s\n", xed_iform_enum_t2str(iform));
+ PrintDebug("iform=%s, iclass=%s\n", xed_iform_enum_t2str(iform), xed_iclass_enum_t2str(iclass));
+#endif
+ if ((instr->op_type = get_opcode(iform)) == V3_INVALID_OP) {
+ PrintError("Could not get opcode. (iform=%s)\n", xed_iform_enum_t2str(iform));
+ return -1;
+ }
+
+
+ // We special case the string operations...
+ if (xed_decoded_inst_get_category(&xed_instr) == XED_CATEGORY_STRINGOP) {
+ instr->is_str_op = 1;
+ return decode_string_op(info, &xed_instr, xi, instr);
+ } else {
+ instr->is_str_op = 0;
+ instr->str_op_length = 0;
+ }
+
+
+ instr->num_operands = xed_decoded_inst_noperands(&xed_instr);
+
if (instr->num_operands > 3) {
PrintDebug("Special Case Not Handled\n");
return -1;
-
-
- if (get_opcode(iform, &(instr->opcode)) == -1) {
- PrintError("Could not get opcode. (iform=%s)\n", xed_iform_enum_t2str(iform));
- return -1;
- }
-
-
-
-
//PrintDebug("Number of operands: %d\n", instr->num_operands);
//PrintDebug("INSTR length: %d\n", instr->instr_length);
xed_reg,
&(v3_op->operand),
&(v3_op->size));
-
+
if (v3_reg_type == -1) {
PrintError("First operand is an Unhandled Operand: %s\n", xed_reg_enum_t2str(xed_reg));
v3_op->type = INVALID_OPERAND;
case XED_OPERAND_MEM0:
{
- /*
- struct x86_operand * operand = &(instr->dst_operand);
-
- if (xed_decoded_inst_mem_read(&xed_instr, 0)) {
- operand = &(instr->src_operand);
- } else if (xed_decoded_inst_mem_written(&xed_instr, 0)) {
- operand = &(instr->dst_operand);
- }
- */
-
if (get_memory_operand(info, &xed_instr, 0, v3_op) == -1) {
PrintError("Could not get first memory operand\n");
return -1;
case XED_OPERAND_MEM0:
{
-
- /*
- if (xed_decoded_inst_mem_read(&xed_instr, 0)) {
- v3_op = &(instr->src_operand);
- } else if (xed_decoded_inst_mem_written(&xed_instr, 0)) {
- v3_op = &(instr->dst_operand);
- }
- */
-
if (get_memory_operand(info, &xed_instr, 0, v3_op) == -1) {
PrintError("Could not get first memory operand\n");
return -1;
if (disp_bits) {
xed_int64_t xed_disp = xed_decoded_inst_get_memory_displacement(xed_instr, op_index);
- mem_op.displacement_size = disp_bits / 8;
+ mem_op.displacement_size = disp_bits;
mem_op.displacement = xed_disp;
-
}
operand->type = MEM_OPERAND;
- PrintDebug("Struct: Seg=%x, base=%x, index=%x, scale=%x, displacement=%x\n",
- mem_op.segment, mem_op.base, mem_op.index, mem_op.scale, mem_op.displacement);
+ PrintDebug("Struct: Seg=%p, base=%p, index=%p, scale=%p, displacement=%p\n",
+ (void *)mem_op.segment, (void*)mem_op.base, (void *)mem_op.index,
+ (void *)mem_op.scale, (void *)(addr_t)mem_op.displacement);
+
+ PrintDebug("operand size: %d\n", operand->size);
seg = mem_op.segment;
base = MASK(mem_op.base, mem_op.base_size);
scale = mem_op.scale;
displacement = MASK(mem_op.displacement, mem_op.displacement_size);
- PrintDebug("Seg=%x, base=%x, index=%x, scale=%x, displacement=%x\n", seg, base, index, scale, displacement);
+ PrintDebug("Seg=%p, base=%p, index=%p, scale=%p, displacement=%p\n",
+ (void *)seg, (void *)base, (void *)index, (void *)scale, (void *)(addr_t)displacement);
operand->operand = seg + base + (scale * index) + displacement;
return 0;
return CTRL_REGISTER;
case XED_REG_CR4:
*v3_reg = (addr_t)&(info->ctrl_regs.cr4);
- *reg_len = 4;
+ *reg_len = 4;
return CTRL_REGISTER;
case XED_REG_CR8:
*v3_reg = (addr_t)&(info->ctrl_regs.cr8);
-static int get_opcode(xed_iform_enum_t iform, addr_t * opcode) {
+static v3_op_type_t get_opcode(xed_iform_enum_t iform) {
switch (iform) {
case XED_IFORM_MOV_CR_GPR64_CR:
case XED_IFORM_MOV_CR_GPR32_CR:
- *opcode = (addr_t)&V3_OPCODE_MOVCR2;
- break;
+ return V3_OP_MOVCR2;
case XED_IFORM_MOV_CR_CR_GPR64:
case XED_IFORM_MOV_CR_CR_GPR32:
- *opcode = (addr_t)&V3_OPCODE_MOV2CR;
- break;
+ return V3_OP_MOV2CR;
case XED_IFORM_SMSW_GPRv:
- *opcode = (addr_t)&V3_OPCODE_SMSW;
- break;
+ return V3_OP_SMSW;
case XED_IFORM_LMSW_GPR16:
- *opcode = (addr_t)&V3_OPCODE_LMSW;
- break;
+ return V3_OP_LMSW;
case XED_IFORM_CLTS:
- *opcode = (addr_t)&V3_OPCODE_CLTS;
- break;
+ return V3_OP_CLTS;
+
+ case XED_IFORM_ADC_MEMv_GPRv:
+ case XED_IFORM_ADC_MEMv_IMM:
+ case XED_IFORM_ADC_MEMb_GPR8:
+ case XED_IFORM_ADC_MEMb_IMM:
+ return V3_OP_ADC;
+
+ case XED_IFORM_ADD_MEMv_GPRv:
+ case XED_IFORM_ADD_MEMb_IMM:
+ case XED_IFORM_ADD_MEMb_GPR8:
+ case XED_IFORM_ADD_MEMv_IMM:
+ return V3_OP_ADD;
+
+ case XED_IFORM_AND_MEMv_IMM:
+ case XED_IFORM_AND_MEMb_GPR8:
+ case XED_IFORM_AND_MEMv_GPRv:
+ case XED_IFORM_AND_MEMb_IMM:
+ return V3_OP_AND;
+
+ case XED_IFORM_SUB_MEMv_IMM:
+ case XED_IFORM_SUB_MEMb_GPR8:
+ case XED_IFORM_SUB_MEMb_IMM:
+ case XED_IFORM_SUB_MEMv_GPRv:
+ return V3_OP_SUB;
+
+ case XED_IFORM_MOV_MEMv_GPRv:
+ case XED_IFORM_MOV_MEMb_GPR8:
+ case XED_IFORM_MOV_MEMb_AL:
+ case XED_IFORM_MOV_MEMv_IMM:
+ case XED_IFORM_MOV_MEMb_IMM:
+ return V3_OP_MOV;
+
+ case XED_IFORM_DEC_MEMv:
+ case XED_IFORM_DEC_MEMb:
+ return V3_OP_DEC;
+
+ case XED_IFORM_INC_MEMb:
+ case XED_IFORM_INC_MEMv:
+ return V3_OP_INC;
+
+ case XED_IFORM_OR_MEMv_IMM:
+ case XED_IFORM_OR_MEMb_IMM:
+ case XED_IFORM_OR_MEMv_GPRv:
+ case XED_IFORM_OR_MEMb_GPR8:
+ return V3_OP_OR;
+
+ case XED_IFORM_XOR_MEMv_GPRv:
+ case XED_IFORM_XOR_MEMb_IMM:
+ case XED_IFORM_XOR_MEMb_GPR8:
+ case XED_IFORM_XOR_MEMv_IMM:
+ return V3_OP_XOR;
+
+ case XED_IFORM_NEG_MEMb:
+ case XED_IFORM_NEG_MEMv:
+ return V3_OP_NEG;
+
+ case XED_IFORM_NOT_MEMv:
+ case XED_IFORM_NOT_MEMb:
+ return V3_OP_NOT;
+
+ case XED_IFORM_XCHG_MEMv_GPRv:
+ case XED_IFORM_XCHG_MEMb_GPR8:
+ return V3_OP_XCHG;
+
+ case XED_IFORM_SETB_MEMb:
+ return V3_OP_SETB;
+
+ case XED_IFORM_SETBE_MEMb:
+ return V3_OP_SETBE;
+
+ case XED_IFORM_SETL_MEMb:
+ return V3_OP_SETL;
+
+ case XED_IFORM_SETLE_MEMb:
+ return V3_OP_SETLE;
+
+ case XED_IFORM_SETNB_MEMb:
+ return V3_OP_SETNB;
+
+ case XED_IFORM_SETNBE_MEMb:
+ return V3_OP_SETNBE;
+
+ case XED_IFORM_SETNL_MEMb:
+ return V3_OP_SETNL;
+
+ case XED_IFORM_SETNLE_MEMb:
+ return V3_OP_SETNLE;
+
+ case XED_IFORM_SETNO_MEMb:
+ return V3_OP_SETNO;
+
+ case XED_IFORM_SETNP_MEMb:
+ return V3_OP_SETNP;
+
+ case XED_IFORM_SETNS_MEMb:
+ return V3_OP_SETNS;
+
+ case XED_IFORM_SETNZ_MEMb:
+ return V3_OP_SETNZ;
+
+ case XED_IFORM_SETO_MEMb:
+ return V3_OP_SETO;
+
+ case XED_IFORM_SETP_MEMb:
+ return V3_OP_SETP;
+ case XED_IFORM_SETS_MEMb:
+ return V3_OP_SETS;
+ case XED_IFORM_SETZ_MEMb:
+ return V3_OP_SETZ;
+
+ case XED_IFORM_MOVSB:
+ case XED_IFORM_MOVSW:
+ case XED_IFORM_MOVSD:
+ case XED_IFORM_MOVSQ:
+ return V3_OP_MOVS;
default:
- *opcode = 0;
- return -1;
+ return V3_INVALID_OP;
}
-
- return 0;
}