x86: add MSR API via reg API (#755)
Writing / reading to model specific registers should be as easy as calling a function, it's a bit stupid to write shell code and run them just to write/read to a MSR, and even worse, you need more than just a shellcode to read... So, add a special register ID called UC_X86_REG_MSR, which should be passed to uc_reg_write()/uc_reg_read() as the register ID, and then a data structure which is uc_x86_msr (12 bytes), as the value (always), where: Byte Value Size 0 MSR ID 4 4 MSR val 8
This commit is contained in:

committed by
Nguyen Anh Quynh

parent
8acd6d47c9
commit
02e6c14e12
@ -17,6 +17,10 @@ static void load_seg_16_helper(CPUX86State *env, int seg, uint32_t selector)
|
||||
cpu_x86_load_seg_cache(env, seg, selector, (selector << 4), 0xffff, X86_NON_CS_FLAGS);
|
||||
}
|
||||
|
||||
|
||||
extern void helper_wrmsr(CPUX86State *env);
|
||||
extern void helper_rdmsr(CPUX86State *env);
|
||||
|
||||
const int X86_REGS_STORAGE_SIZE = offsetof(CPUX86State, tlb_table);
|
||||
|
||||
static void x86_set_pc(struct uc_struct *uc, uint64_t address)
|
||||
@ -156,6 +160,49 @@ void x86_reg_reset(struct uc_struct *uc)
|
||||
}
|
||||
}
|
||||
|
||||
static int x86_msr_read(struct uc_struct *uc, uc_x86_msr *msr)
|
||||
{
|
||||
CPUX86State *env = (CPUX86State *)uc->cpu->env_ptr;
|
||||
uint64_t ecx = env->regs[R_ECX];
|
||||
uint64_t eax = env->regs[R_EAX];
|
||||
uint64_t edx = env->regs[R_EDX];
|
||||
|
||||
env->regs[R_ECX] = msr->rid;
|
||||
helper_rdmsr(env);
|
||||
|
||||
msr->value = ((uint32_t)env->regs[R_EAX]) |
|
||||
((uint64_t)((uint32_t)env->regs[R_EDX]) << 32);
|
||||
|
||||
env->regs[R_EAX] = eax;
|
||||
env->regs[R_ECX] = ecx;
|
||||
env->regs[R_EDX] = edx;
|
||||
|
||||
/* The implementation doesn't throw exception or return an error if there is one, so
|
||||
* we will return 0. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int x86_msr_write(struct uc_struct *uc, uc_x86_msr *msr)
|
||||
{
|
||||
CPUX86State *env = (CPUX86State *)uc->cpu->env_ptr;
|
||||
uint64_t ecx = env->regs[R_ECX];
|
||||
uint64_t eax = env->regs[R_EAX];
|
||||
uint64_t edx = env->regs[R_EDX];
|
||||
|
||||
env->regs[R_ECX] = msr->rid;
|
||||
env->regs[R_EAX] = (unsigned int)msr->value;
|
||||
env->regs[R_EDX] = (unsigned int)(msr->value >> 32);
|
||||
helper_wrmsr(env);
|
||||
|
||||
env->regs[R_ECX] = ecx;
|
||||
env->regs[R_EAX] = eax;
|
||||
env->regs[R_EDX] = edx;
|
||||
|
||||
/* The implementation doesn't throw exception or return an error if there is one, so
|
||||
* we will return 0. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
int x86_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, int count)
|
||||
{
|
||||
CPUState *mycpu = uc->cpu;
|
||||
@ -376,6 +423,9 @@ int x86_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, int coun
|
||||
((uc_x86_mmr *)value)->selector = (uint16_t)X86_CPU(uc, mycpu)->env.tr.selector;
|
||||
((uc_x86_mmr *)value)->flags = X86_CPU(uc, mycpu)->env.tr.flags;
|
||||
break;
|
||||
case UC_X86_REG_MSR:
|
||||
x86_msr_read(uc, (uc_x86_msr *)value);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
@ -644,6 +694,9 @@ int x86_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, int coun
|
||||
((uc_x86_mmr *)value)->selector = (uint16_t)X86_CPU(uc, mycpu)->env.tr.selector;
|
||||
((uc_x86_mmr *)value)->flags = X86_CPU(uc, mycpu)->env.tr.flags;
|
||||
break;
|
||||
case UC_X86_REG_MSR:
|
||||
x86_msr_read(uc, (uc_x86_msr *)value);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
@ -863,6 +916,9 @@ int x86_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals, i
|
||||
X86_CPU(uc, mycpu)->env.tr.selector = (uint16_t)((uc_x86_mmr *)value)->selector;
|
||||
X86_CPU(uc, mycpu)->env.tr.flags = ((uc_x86_mmr *)value)->flags;
|
||||
break;
|
||||
case UC_X86_REG_MSR:
|
||||
x86_msr_write(uc, (uc_x86_msr *)value);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
@ -1141,6 +1197,9 @@ int x86_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals, i
|
||||
X86_CPU(uc, mycpu)->env.tr.selector = (uint16_t)((uc_x86_mmr *)value)->selector;
|
||||
X86_CPU(uc, mycpu)->env.tr.flags = ((uc_x86_mmr *)value)->flags;
|
||||
break;
|
||||
case UC_X86_REG_MSR:
|
||||
x86_msr_write(uc, (uc_x86_msr *)value);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
@ -1185,3 +1244,5 @@ void x86_uc_init(struct uc_struct* uc)
|
||||
uc->stop_interrupt = x86_stop_interrupt;
|
||||
uc_common_init(uc);
|
||||
}
|
||||
|
||||
/* vim: set ts=4 sts=4 sw=4 et: */
|
||||
|
Reference in New Issue
Block a user