Support changing cpu model for ARM

This commit is contained in:
lazymio 2021-11-04 18:37:10 +01:00
parent 28013c13be
commit dfbffa44ec
No known key found for this signature in database
GPG Key ID: DFF27E34A47CB873
6 changed files with 84 additions and 38 deletions

View File

@ -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 */

View File

@ -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,

View File

@ -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*)

View File

@ -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

View File

@ -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
View File

@ -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: {