Support changing cpu model for ARM
This commit is contained in:
parent
28013c13be
commit
dfbffa44ec
@ -267,7 +267,8 @@ struct uc_struct {
|
||||
unsigned int alloc_hint;
|
||||
/* qemu/exec-vary.c */
|
||||
TargetPageBits *init_target_page;
|
||||
int target_bits; // User defined page bits by uc_ctl
|
||||
int target_bits; // User defined page bits by uc_ctl
|
||||
int cpu_model;
|
||||
BounceBuffer bounce; // qemu/cpu-exec.c
|
||||
volatile sig_atomic_t exit_request; // qemu/cpu-exec.c
|
||||
/* qemu/accel/tcg/cpu-exec-common.c */
|
||||
|
@ -30,9 +30,9 @@ typedef enum uc_cpu_arm {
|
||||
UC_CPU_ARM_CORTEX_M33,
|
||||
UC_CPU_ARM_CORTEX_R5,
|
||||
UC_CPU_ARM_CORTEX_R5F,
|
||||
UC_CPU_ARM_CORTEX_A7,
|
||||
UC_CPU_ARM_CORTEX_A8,
|
||||
UC_CPU_ARM_CORTEX_A9,
|
||||
UC_CPU_ARM_CORTEX_A7,
|
||||
UC_CPU_ARM_CORTEX_A15,
|
||||
UC_CPU_ARM_TI925T,
|
||||
UC_CPU_ARM_SA1100,
|
||||
|
@ -513,7 +513,7 @@ typedef enum uc_control_type {
|
||||
// Note this option can only be set before any Unicorn
|
||||
// API is called except for uc_open.
|
||||
// Write: @args = (int)
|
||||
// Read: @args = (int)
|
||||
// Read: @args = (int*)
|
||||
UC_CTL_CPU_MODEL,
|
||||
// Request a tb cache at a specific address
|
||||
// Read: @args = (uint64_t, uc_tb*)
|
||||
|
@ -2017,33 +2017,32 @@ static void arm_cpu_instance_init(CPUState *obj)
|
||||
|
||||
ARMCPU *cpu_arm_init(struct uc_struct *uc)
|
||||
{
|
||||
#if !defined(TARGET_AARCH64)
|
||||
int i;
|
||||
char *cpu_model;
|
||||
#endif
|
||||
ARMCPU *cpu;
|
||||
CPUState *cs;
|
||||
CPUClass *cc;
|
||||
|
||||
#if !defined(TARGET_AARCH64)
|
||||
if (uc->mode & UC_MODE_MCLASS) {
|
||||
cpu_model = "cortex-m33";
|
||||
} else if (uc->mode & UC_MODE_ARM926) {
|
||||
cpu_model = "arm926";
|
||||
} else if (uc->mode & UC_MODE_ARM946) {
|
||||
cpu_model = "arm946";
|
||||
} else if (uc->mode & UC_MODE_ARM1176) {
|
||||
cpu_model = "arm1176";
|
||||
} else {
|
||||
cpu_model = "cortex-a15";
|
||||
}
|
||||
#endif
|
||||
|
||||
cpu = calloc(1, sizeof(*cpu));
|
||||
if (cpu == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#if !defined(TARGET_AARCH64)
|
||||
if (uc->mode & UC_MODE_MCLASS) {
|
||||
uc->cpu_model = 11;
|
||||
} else if (uc->mode & UC_MODE_ARM926) {
|
||||
uc->cpu_model = 0;
|
||||
} else if (uc->mode & UC_MODE_ARM946) {
|
||||
uc->cpu_model = 1;
|
||||
} else if (uc->mode & UC_MODE_ARM1176) {
|
||||
uc->cpu_model = 5;
|
||||
} else if (uc->cpu_model == INT_MAX) {
|
||||
uc->cpu_model = 17; // cortex-a15
|
||||
} else if (uc->cpu_model >= ARR_SIZE(arm_cpus)) {
|
||||
free(cpu);
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
cs = (CPUState *)cpu;
|
||||
cc = (CPUClass *)&cpu->cc;
|
||||
cs->cc = cc;
|
||||
@ -2064,20 +2063,11 @@ ARMCPU *cpu_arm_init(struct uc_struct *uc)
|
||||
|
||||
#if !defined(TARGET_AARCH64)
|
||||
/* init ARM types */
|
||||
for (i = 0; i < ARRAY_SIZE(arm_cpus); i++) {
|
||||
if (strcmp(cpu_model, arm_cpus[i].name) == 0) {
|
||||
if (arm_cpus[i].class_init) {
|
||||
arm_cpus[i].class_init(uc, cc, uc);
|
||||
}
|
||||
if (arm_cpus[i].initfn) {
|
||||
arm_cpus[i].initfn(uc, cs);
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (arm_cpus[uc->cpu_model].class_init) {
|
||||
arm_cpus[uc->cpu_model].class_init(uc, cc, uc);
|
||||
}
|
||||
if (i == ARRAY_SIZE(arm_cpus)) {
|
||||
free(cpu);
|
||||
return NULL;
|
||||
if (arm_cpus[uc->cpu_model].initfn) {
|
||||
arm_cpus[uc->cpu_model].initfn(uc, cs);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -160,7 +160,6 @@ static void test_uc_ctl_change_page_size()
|
||||
{
|
||||
uc_engine *uc;
|
||||
uc_engine *uc2;
|
||||
int r_pc;
|
||||
|
||||
OK(uc_open(UC_ARCH_ARM, UC_MODE_ARM, &uc));
|
||||
OK(uc_open(UC_ARCH_ARM, UC_MODE_ARM, &uc2));
|
||||
@ -174,6 +173,40 @@ static void test_uc_ctl_change_page_size()
|
||||
OK(uc_close(uc2));
|
||||
}
|
||||
|
||||
// Copy from test_arm.c but with new API.
|
||||
static void test_uc_ctl_arm_cpu() {
|
||||
uc_engine *uc;
|
||||
int r_control, r_msp, r_psp;
|
||||
|
||||
OK(uc_open(UC_ARCH_ARM, UC_MODE_THUMB, &uc));
|
||||
|
||||
OK(uc_ctl_set_cpu_model(uc, UC_CPU_ARM_CORTEX_M7));
|
||||
|
||||
r_control = 0; // Make sure we are using MSP.
|
||||
OK(uc_reg_write(uc, UC_ARM_REG_CONTROL, &r_control));
|
||||
|
||||
r_msp = 0x1000;
|
||||
OK(uc_reg_write(uc, UC_ARM_REG_R13, &r_msp));
|
||||
|
||||
r_control = 0b10; // Make the switch.
|
||||
OK(uc_reg_write(uc, UC_ARM_REG_CONTROL, &r_control));
|
||||
|
||||
OK(uc_reg_read(uc, UC_ARM_REG_R13, &r_psp));
|
||||
TEST_CHECK(r_psp != r_msp);
|
||||
|
||||
r_psp = 0x2000;
|
||||
OK(uc_reg_write(uc, UC_ARM_REG_R13, &r_psp));
|
||||
|
||||
r_control = 0; // Switch again
|
||||
OK(uc_reg_write(uc, UC_ARM_REG_CONTROL, &r_control));
|
||||
|
||||
OK(uc_reg_read(uc, UC_ARM_REG_R13, &r_msp));
|
||||
TEST_CHECK(r_psp != r_msp);
|
||||
TEST_CHECK(r_msp == 0x1000);
|
||||
|
||||
OK(uc_close(uc));
|
||||
}
|
||||
|
||||
TEST_LIST = {{"test_uc_ctl_mode", test_uc_ctl_mode},
|
||||
{"test_uc_ctl_page_size", test_uc_ctl_page_size},
|
||||
{"test_uc_ctl_arch", test_uc_ctl_arch},
|
||||
@ -181,4 +214,5 @@ TEST_LIST = {{"test_uc_ctl_mode", test_uc_ctl_mode},
|
||||
{"test_uc_ctl_exits", test_uc_ctl_exits},
|
||||
{"test_uc_ctl_tb_cache", test_uc_ctl_tb_cache},
|
||||
{"test_uc_ctl_change_page_size", test_uc_ctl_change_page_size},
|
||||
{"test_uc_ctl_arm_cpu", test_uc_ctl_arm_cpu},
|
||||
{NULL, NULL}};
|
27
uc.c
27
uc.c
@ -348,6 +348,7 @@ uc_err uc_open(uc_arch arch, uc_mode mode, uc_engine **result)
|
||||
}
|
||||
|
||||
uc->init_done = false;
|
||||
uc->cpu_model = INT_MAX; // INT_MAX means the default cpu model.
|
||||
|
||||
*result = uc;
|
||||
|
||||
@ -1975,6 +1976,11 @@ uc_err uc_ctl(uc_engine *uc, uc_control_type control, ...)
|
||||
uint32_t page_size = va_arg(args, uint32_t);
|
||||
int bits = 0;
|
||||
|
||||
if (uc->init_done) {
|
||||
err = UC_ERR_ARG;
|
||||
break;
|
||||
}
|
||||
|
||||
if (uc->arch != UC_ARCH_ARM) {
|
||||
err = UC_ERR_ARG;
|
||||
break;
|
||||
@ -1996,6 +2002,7 @@ uc_err uc_ctl(uc_engine *uc, uc_control_type control, ...)
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case UC_CTL_UC_USE_EXITS: {
|
||||
if (rw == UC_CTL_IO_WRITE) {
|
||||
int use_exits = va_arg(args, int);
|
||||
@ -2054,10 +2061,24 @@ uc_err uc_ctl(uc_engine *uc, uc_control_type control, ...)
|
||||
break;
|
||||
}
|
||||
|
||||
case UC_CTL_CPU_MODEL:
|
||||
// Not implemented.
|
||||
err = UC_ERR_ARG;
|
||||
case UC_CTL_CPU_MODEL: {
|
||||
if (rw == UC_CTL_IO_READ) {
|
||||
int *model = va_arg(args, int *);
|
||||
*model = uc->cpu_model;
|
||||
} else {
|
||||
int model = va_arg(args, int);
|
||||
|
||||
if (uc->init_done) {
|
||||
err = UC_ERR_ARG;
|
||||
break;
|
||||
}
|
||||
|
||||
uc->cpu_model = model;
|
||||
|
||||
err = UC_ERR_OK;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case UC_CTL_TB_REQUEST_CACHE: {
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user