mirror of
https://github.com/yuzu-emu/unicorn.git
synced 2025-02-02 07:51:08 +00:00
target/arm: expose CPUID registers to userspace
A number of CPUID registers are exposed to userspace by modern Linux kernels thanks to the "ARM64 CPU Feature Registers" ABI. For QEMU's user-mode emulation we don't need to emulate the kernels trap but just return the value the trap would have done. To avoid too much #ifdef hackery we process ARMCPRegInfo with a new helper (modify_arm_cp_regs) before defining the registers. The modify routine is driven by a simple data structure which describes which bits are exported and which are fixed. Backports commit 6c5c0fec29bbfe36c64eca1edfd8455be46b77c6 from qemu
This commit is contained in:
parent
0a51e5055f
commit
babf31dfa0
|
@ -2040,6 +2040,7 @@
|
||||||
#define memory_register_types memory_register_types_aarch64
|
#define memory_register_types memory_register_types_aarch64
|
||||||
#define memory_try_enable_merging memory_try_enable_merging_aarch64
|
#define memory_try_enable_merging memory_try_enable_merging_aarch64
|
||||||
#define memory_unmap memory_unmap_aarch64
|
#define memory_unmap memory_unmap_aarch64
|
||||||
|
#define modify_arm_cp_regs modify_arm_cp_regs_aarch64
|
||||||
#define module_call_init module_call_init_aarch64
|
#define module_call_init module_call_init_aarch64
|
||||||
#define module_load module_load_aarch64
|
#define module_load module_load_aarch64
|
||||||
#define mpidr_cp_reginfo mpidr_cp_reginfo_aarch64
|
#define mpidr_cp_reginfo mpidr_cp_reginfo_aarch64
|
||||||
|
|
|
@ -2040,6 +2040,7 @@
|
||||||
#define memory_register_types memory_register_types_aarch64eb
|
#define memory_register_types memory_register_types_aarch64eb
|
||||||
#define memory_try_enable_merging memory_try_enable_merging_aarch64eb
|
#define memory_try_enable_merging memory_try_enable_merging_aarch64eb
|
||||||
#define memory_unmap memory_unmap_aarch64eb
|
#define memory_unmap memory_unmap_aarch64eb
|
||||||
|
#define modify_arm_cp_regs modify_arm_cp_regs_aarch64eb
|
||||||
#define module_call_init module_call_init_aarch64eb
|
#define module_call_init module_call_init_aarch64eb
|
||||||
#define module_load module_load_aarch64eb
|
#define module_load module_load_aarch64eb
|
||||||
#define mpidr_cp_reginfo mpidr_cp_reginfo_aarch64eb
|
#define mpidr_cp_reginfo mpidr_cp_reginfo_aarch64eb
|
||||||
|
|
|
@ -2040,6 +2040,7 @@
|
||||||
#define memory_register_types memory_register_types_arm
|
#define memory_register_types memory_register_types_arm
|
||||||
#define memory_try_enable_merging memory_try_enable_merging_arm
|
#define memory_try_enable_merging memory_try_enable_merging_arm
|
||||||
#define memory_unmap memory_unmap_arm
|
#define memory_unmap memory_unmap_arm
|
||||||
|
#define modify_arm_cp_regs modify_arm_cp_regs_arm
|
||||||
#define module_call_init module_call_init_arm
|
#define module_call_init module_call_init_arm
|
||||||
#define module_load module_load_arm
|
#define module_load module_load_arm
|
||||||
#define mpidr_cp_reginfo mpidr_cp_reginfo_arm
|
#define mpidr_cp_reginfo mpidr_cp_reginfo_arm
|
||||||
|
|
|
@ -2040,6 +2040,7 @@
|
||||||
#define memory_register_types memory_register_types_armeb
|
#define memory_register_types memory_register_types_armeb
|
||||||
#define memory_try_enable_merging memory_try_enable_merging_armeb
|
#define memory_try_enable_merging memory_try_enable_merging_armeb
|
||||||
#define memory_unmap memory_unmap_armeb
|
#define memory_unmap memory_unmap_armeb
|
||||||
|
#define modify_arm_cp_regs modify_arm_cp_regs_armeb
|
||||||
#define module_call_init module_call_init_armeb
|
#define module_call_init module_call_init_armeb
|
||||||
#define module_load module_load_armeb
|
#define module_load module_load_armeb
|
||||||
#define mpidr_cp_reginfo mpidr_cp_reginfo_armeb
|
#define mpidr_cp_reginfo mpidr_cp_reginfo_armeb
|
||||||
|
|
|
@ -2046,6 +2046,7 @@ symbols = (
|
||||||
'memory_register_types',
|
'memory_register_types',
|
||||||
'memory_try_enable_merging',
|
'memory_try_enable_merging',
|
||||||
'memory_unmap',
|
'memory_unmap',
|
||||||
|
'modify_arm_cp_regs',
|
||||||
'module_call_init',
|
'module_call_init',
|
||||||
'module_load',
|
'module_load',
|
||||||
'mpidr_cp_reginfo',
|
'mpidr_cp_reginfo',
|
||||||
|
|
|
@ -2040,6 +2040,7 @@
|
||||||
#define memory_register_types memory_register_types_m68k
|
#define memory_register_types memory_register_types_m68k
|
||||||
#define memory_try_enable_merging memory_try_enable_merging_m68k
|
#define memory_try_enable_merging memory_try_enable_merging_m68k
|
||||||
#define memory_unmap memory_unmap_m68k
|
#define memory_unmap memory_unmap_m68k
|
||||||
|
#define modify_arm_cp_regs modify_arm_cp_regs_m68k
|
||||||
#define module_call_init module_call_init_m68k
|
#define module_call_init module_call_init_m68k
|
||||||
#define module_load module_load_m68k
|
#define module_load module_load_m68k
|
||||||
#define mpidr_cp_reginfo mpidr_cp_reginfo_m68k
|
#define mpidr_cp_reginfo mpidr_cp_reginfo_m68k
|
||||||
|
|
|
@ -2040,6 +2040,7 @@
|
||||||
#define memory_register_types memory_register_types_mips
|
#define memory_register_types memory_register_types_mips
|
||||||
#define memory_try_enable_merging memory_try_enable_merging_mips
|
#define memory_try_enable_merging memory_try_enable_merging_mips
|
||||||
#define memory_unmap memory_unmap_mips
|
#define memory_unmap memory_unmap_mips
|
||||||
|
#define modify_arm_cp_regs modify_arm_cp_regs_mips
|
||||||
#define module_call_init module_call_init_mips
|
#define module_call_init module_call_init_mips
|
||||||
#define module_load module_load_mips
|
#define module_load module_load_mips
|
||||||
#define mpidr_cp_reginfo mpidr_cp_reginfo_mips
|
#define mpidr_cp_reginfo mpidr_cp_reginfo_mips
|
||||||
|
|
|
@ -2040,6 +2040,7 @@
|
||||||
#define memory_register_types memory_register_types_mips64
|
#define memory_register_types memory_register_types_mips64
|
||||||
#define memory_try_enable_merging memory_try_enable_merging_mips64
|
#define memory_try_enable_merging memory_try_enable_merging_mips64
|
||||||
#define memory_unmap memory_unmap_mips64
|
#define memory_unmap memory_unmap_mips64
|
||||||
|
#define modify_arm_cp_regs modify_arm_cp_regs_mips64
|
||||||
#define module_call_init module_call_init_mips64
|
#define module_call_init module_call_init_mips64
|
||||||
#define module_load module_load_mips64
|
#define module_load module_load_mips64
|
||||||
#define mpidr_cp_reginfo mpidr_cp_reginfo_mips64
|
#define mpidr_cp_reginfo mpidr_cp_reginfo_mips64
|
||||||
|
|
|
@ -2040,6 +2040,7 @@
|
||||||
#define memory_register_types memory_register_types_mips64el
|
#define memory_register_types memory_register_types_mips64el
|
||||||
#define memory_try_enable_merging memory_try_enable_merging_mips64el
|
#define memory_try_enable_merging memory_try_enable_merging_mips64el
|
||||||
#define memory_unmap memory_unmap_mips64el
|
#define memory_unmap memory_unmap_mips64el
|
||||||
|
#define modify_arm_cp_regs modify_arm_cp_regs_mips64el
|
||||||
#define module_call_init module_call_init_mips64el
|
#define module_call_init module_call_init_mips64el
|
||||||
#define module_load module_load_mips64el
|
#define module_load module_load_mips64el
|
||||||
#define mpidr_cp_reginfo mpidr_cp_reginfo_mips64el
|
#define mpidr_cp_reginfo mpidr_cp_reginfo_mips64el
|
||||||
|
|
|
@ -2040,6 +2040,7 @@
|
||||||
#define memory_register_types memory_register_types_mipsel
|
#define memory_register_types memory_register_types_mipsel
|
||||||
#define memory_try_enable_merging memory_try_enable_merging_mipsel
|
#define memory_try_enable_merging memory_try_enable_merging_mipsel
|
||||||
#define memory_unmap memory_unmap_mipsel
|
#define memory_unmap memory_unmap_mipsel
|
||||||
|
#define modify_arm_cp_regs modify_arm_cp_regs_mipsel
|
||||||
#define module_call_init module_call_init_mipsel
|
#define module_call_init module_call_init_mipsel
|
||||||
#define module_load module_load_mipsel
|
#define module_load module_load_mipsel
|
||||||
#define mpidr_cp_reginfo mpidr_cp_reginfo_mipsel
|
#define mpidr_cp_reginfo mpidr_cp_reginfo_mipsel
|
||||||
|
|
|
@ -2040,6 +2040,7 @@
|
||||||
#define memory_register_types memory_register_types_powerpc
|
#define memory_register_types memory_register_types_powerpc
|
||||||
#define memory_try_enable_merging memory_try_enable_merging_powerpc
|
#define memory_try_enable_merging memory_try_enable_merging_powerpc
|
||||||
#define memory_unmap memory_unmap_powerpc
|
#define memory_unmap memory_unmap_powerpc
|
||||||
|
#define modify_arm_cp_regs modify_arm_cp_regs_powerpc
|
||||||
#define module_call_init module_call_init_powerpc
|
#define module_call_init module_call_init_powerpc
|
||||||
#define module_load module_load_powerpc
|
#define module_load module_load_powerpc
|
||||||
#define mpidr_cp_reginfo mpidr_cp_reginfo_powerpc
|
#define mpidr_cp_reginfo mpidr_cp_reginfo_powerpc
|
||||||
|
|
|
@ -2040,6 +2040,7 @@
|
||||||
#define memory_register_types memory_register_types_sparc
|
#define memory_register_types memory_register_types_sparc
|
||||||
#define memory_try_enable_merging memory_try_enable_merging_sparc
|
#define memory_try_enable_merging memory_try_enable_merging_sparc
|
||||||
#define memory_unmap memory_unmap_sparc
|
#define memory_unmap memory_unmap_sparc
|
||||||
|
#define modify_arm_cp_regs modify_arm_cp_regs_sparc
|
||||||
#define module_call_init module_call_init_sparc
|
#define module_call_init module_call_init_sparc
|
||||||
#define module_load module_load_sparc
|
#define module_load module_load_sparc
|
||||||
#define mpidr_cp_reginfo mpidr_cp_reginfo_sparc
|
#define mpidr_cp_reginfo mpidr_cp_reginfo_sparc
|
||||||
|
|
|
@ -2040,6 +2040,7 @@
|
||||||
#define memory_register_types memory_register_types_sparc64
|
#define memory_register_types memory_register_types_sparc64
|
||||||
#define memory_try_enable_merging memory_try_enable_merging_sparc64
|
#define memory_try_enable_merging memory_try_enable_merging_sparc64
|
||||||
#define memory_unmap memory_unmap_sparc64
|
#define memory_unmap memory_unmap_sparc64
|
||||||
|
#define modify_arm_cp_regs modify_arm_cp_regs_sparc64
|
||||||
#define module_call_init module_call_init_sparc64
|
#define module_call_init module_call_init_sparc64
|
||||||
#define module_load module_load_sparc64
|
#define module_load module_load_sparc64
|
||||||
#define mpidr_cp_reginfo mpidr_cp_reginfo_sparc64
|
#define mpidr_cp_reginfo mpidr_cp_reginfo_sparc64
|
||||||
|
|
|
@ -2406,6 +2406,27 @@ static inline void define_one_arm_cp_reg(ARMCPU *cpu, const ARMCPRegInfo *regs)
|
||||||
}
|
}
|
||||||
const ARMCPRegInfo *get_arm_cp_reginfo(GHashTable *cpregs, uint32_t encoded_cp);
|
const ARMCPRegInfo *get_arm_cp_reginfo(GHashTable *cpregs, uint32_t encoded_cp);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Definition of an ARM co-processor register as viewed from
|
||||||
|
* userspace. This is used for presenting sanitised versions of
|
||||||
|
* registers to userspace when emulating the Linux AArch64 CPU
|
||||||
|
* ID/feature ABI (advertised as HWCAP_CPUID).
|
||||||
|
*/
|
||||||
|
typedef struct ARMCPRegUserSpaceInfo {
|
||||||
|
/* Name of register */
|
||||||
|
const char *name;
|
||||||
|
|
||||||
|
/* Only some bits are exported to user space */
|
||||||
|
uint64_t exported_bits;
|
||||||
|
|
||||||
|
/* Fixed bits are applied after the mask */
|
||||||
|
uint64_t fixed_bits;
|
||||||
|
} ARMCPRegUserSpaceInfo;
|
||||||
|
|
||||||
|
#define REGUSERINFO_SENTINEL { .name = NULL }
|
||||||
|
|
||||||
|
void modify_arm_cp_regs(ARMCPRegInfo *regs, const ARMCPRegUserSpaceInfo *mods);
|
||||||
|
|
||||||
/* CPWriteFn that can be used to implement writes-ignored behaviour */
|
/* CPWriteFn that can be used to implement writes-ignored behaviour */
|
||||||
void arm_cp_write_ignore(CPUARMState *env, const ARMCPRegInfo *ri,
|
void arm_cp_write_ignore(CPUARMState *env, const ARMCPRegInfo *ri,
|
||||||
uint64_t value);
|
uint64_t value);
|
||||||
|
|
|
@ -5290,6 +5290,30 @@ void register_cp_regs_for_features(ARMCPU *cpu)
|
||||||
pmreg_access },
|
pmreg_access },
|
||||||
REGINFO_SENTINEL
|
REGINFO_SENTINEL
|
||||||
};
|
};
|
||||||
|
#ifdef CONFIG_USER_ONLY
|
||||||
|
ARMCPRegUserSpaceInfo v8_user_idregs[] = {
|
||||||
|
{ .name = "ID_AA64PFR0_EL1",
|
||||||
|
.exported_bits = 0x000f000f00ff0000,
|
||||||
|
.fixed_bits = 0x0000000000000011 },
|
||||||
|
{ .name = "ID_AA64PFR1_EL1",
|
||||||
|
.exported_bits = 0x00000000000000f0 },
|
||||||
|
{ .name = "ID_AA64ZFR0_EL1" },
|
||||||
|
{ .name = "ID_AA64MMFR0_EL1",
|
||||||
|
.fixed_bits = 0x00000000ff000000 },
|
||||||
|
{ .name = "ID_AA64MMFR1_EL1" },
|
||||||
|
{ .name = "ID_AA64DFR0_EL1",
|
||||||
|
.fixed_bits = 0x0000000000000006 },
|
||||||
|
{ .name = "ID_AA64DFR1_EL1" },
|
||||||
|
{ .name = "ID_AA64AFR0_EL1" },
|
||||||
|
{ .name = "ID_AA64AFR1_EL1" },
|
||||||
|
{ .name = "ID_AA64ISAR0_EL1",
|
||||||
|
.exported_bits = 0x00fffffff0fffff0 },
|
||||||
|
{ .name = "ID_AA64ISAR1_EL1",
|
||||||
|
.exported_bits = 0x000000f0ffffffff },
|
||||||
|
REGUSERINFO_SENTINEL
|
||||||
|
};
|
||||||
|
modify_arm_cp_regs(v8_idregs, v8_user_idregs);
|
||||||
|
#endif
|
||||||
/* RVBAR_EL1 is only implemented if EL1 is the highest EL */
|
/* RVBAR_EL1 is only implemented if EL1 is the highest EL */
|
||||||
if (!arm_feature(env, ARM_FEATURE_EL3) &&
|
if (!arm_feature(env, ARM_FEATURE_EL3) &&
|
||||||
!arm_feature(env, ARM_FEATURE_EL2)) {
|
!arm_feature(env, ARM_FEATURE_EL2)) {
|
||||||
|
@ -5524,6 +5548,15 @@ void register_cp_regs_for_features(ARMCPU *cpu)
|
||||||
"CRN0_WI", 15,0,CP_ANY, 0,CP_ANY,CP_ANY, 0,
|
"CRN0_WI", 15,0,CP_ANY, 0,CP_ANY,CP_ANY, 0,
|
||||||
ARM_CP_NOP | ARM_CP_OVERRIDE, PL1_W,
|
ARM_CP_NOP | ARM_CP_OVERRIDE, PL1_W,
|
||||||
};
|
};
|
||||||
|
#ifdef CONFIG_USER_ONLY
|
||||||
|
ARMCPRegUserSpaceInfo id_v8_user_midr_cp_reginfo[] = {
|
||||||
|
{ .name = "MIDR_EL1",
|
||||||
|
.exported_bits = 0x00000000ffffffff },
|
||||||
|
{ .name = "REVIDR_EL1" },
|
||||||
|
REGUSERINFO_SENTINEL
|
||||||
|
};
|
||||||
|
modify_arm_cp_regs(id_v8_midr_cp_reginfo, id_v8_user_midr_cp_reginfo);
|
||||||
|
#endif
|
||||||
if (arm_feature(env, ARM_FEATURE_OMAPCP) ||
|
if (arm_feature(env, ARM_FEATURE_OMAPCP) ||
|
||||||
arm_feature(env, ARM_FEATURE_STRONGARM)) {
|
arm_feature(env, ARM_FEATURE_STRONGARM)) {
|
||||||
ARMCPRegInfo *r;
|
ARMCPRegInfo *r;
|
||||||
|
@ -6046,6 +6079,32 @@ void define_arm_cp_regs_with_opaque(ARMCPU *cpu,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Modify ARMCPRegInfo for access from userspace.
|
||||||
|
*
|
||||||
|
* This is a data driven modification directed by
|
||||||
|
* ARMCPRegUserSpaceInfo. All registers become ARM_CP_CONST as
|
||||||
|
* user-space cannot alter any values and dynamic values pertaining to
|
||||||
|
* execution state are hidden from user space view anyway.
|
||||||
|
*/
|
||||||
|
void modify_arm_cp_regs(ARMCPRegInfo *regs, const ARMCPRegUserSpaceInfo *mods)
|
||||||
|
{
|
||||||
|
const ARMCPRegUserSpaceInfo *m;
|
||||||
|
ARMCPRegInfo *r;
|
||||||
|
|
||||||
|
for (m = mods; m->name; m++) {
|
||||||
|
for (r = regs; r->type != ARM_CP_SENTINEL; r++) {
|
||||||
|
if (strcmp(r->name, m->name) == 0) {
|
||||||
|
r->type = ARM_CP_CONST;
|
||||||
|
r->access = PL0U_R;
|
||||||
|
r->resetvalue &= m->exported_bits;
|
||||||
|
r->resetvalue |= m->fixed_bits;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const ARMCPRegInfo *get_arm_cp_reginfo(GHashTable *cpregs, uint32_t encoded_cp)
|
const ARMCPRegInfo *get_arm_cp_reginfo(GHashTable *cpregs, uint32_t encoded_cp)
|
||||||
{
|
{
|
||||||
return g_hash_table_lookup(cpregs, &encoded_cp);
|
return g_hash_table_lookup(cpregs, &encoded_cp);
|
||||||
|
|
|
@ -2040,6 +2040,7 @@
|
||||||
#define memory_register_types memory_register_types_x86_64
|
#define memory_register_types memory_register_types_x86_64
|
||||||
#define memory_try_enable_merging memory_try_enable_merging_x86_64
|
#define memory_try_enable_merging memory_try_enable_merging_x86_64
|
||||||
#define memory_unmap memory_unmap_x86_64
|
#define memory_unmap memory_unmap_x86_64
|
||||||
|
#define modify_arm_cp_regs modify_arm_cp_regs_x86_64
|
||||||
#define module_call_init module_call_init_x86_64
|
#define module_call_init module_call_init_x86_64
|
||||||
#define module_load module_load_x86_64
|
#define module_load module_load_x86_64
|
||||||
#define mpidr_cp_reginfo mpidr_cp_reginfo_x86_64
|
#define mpidr_cp_reginfo mpidr_cp_reginfo_x86_64
|
||||||
|
|
Loading…
Reference in a new issue