On 18/07/2015 11:40, Peter Crosthwaite wrote: > Multi-arch conversion consisting of: > * Compiling out all target-arm private contents of cpu.h when doing > multi-arch build > * Defining the QOM cpu hooks > * move cp.c to hw subdir for system-level visibility > * Add aarch64 to multi-support list > > Signed-off-by: Peter Crosthwaite <crosthwaite.pe...@gmail.com> > --- > I guess I could split to multi patches but it will bloat this series! > > Changed since RFC v2: > Remove macro undefs (obsoleted) > Remove arch prefixing redefinitions of cpu-defs symbols (obsoleted) > Added cp.c movement.
Please add [core] renames = true to your ~/.gitconfig or ~/.config/git/config file so that you'll get a nicer (and easier to review) patch. The multi-support directory is a bit weird. Is it so ugly to do it directly in "configure"? Perhaps we could add CONFIG_MULTI to default-configs/aarch64-softmmu.mak and grep in configure. It would not support include files, but otherwise wouldn't be a big deal, I think. Paolo > Remove configury changes > Remove arch-obj changes > --- > multi-support/aarch64 | 0 > target-arm/Makefile.objs | 25 ++-- > target-arm/cp.c | 328 > -------------------------------------------- > target-arm/cpu-qom.h | 2 + > target-arm/cpu.c | 2 + > target-arm/cpu.h | 45 ++++++ > target-arm/hw/Makefile.objs | 1 + > target-arm/hw/cp.c | 328 > ++++++++++++++++++++++++++++++++++++++++++++ > 8 files changed, 390 insertions(+), 341 deletions(-) > create mode 100644 multi-support/aarch64 > delete mode 100644 target-arm/cp.c > create mode 100644 target-arm/hw/Makefile.objs > create mode 100644 target-arm/hw/cp.c > > diff --git a/multi-support/aarch64 b/multi-support/aarch64 > new file mode 100644 > index 0000000..e69de29 > diff --git a/target-arm/Makefile.objs b/target-arm/Makefile.objs > index 6d9f62e..5725c57 100644 > --- a/target-arm/Makefile.objs > +++ b/target-arm/Makefile.objs > @@ -1,13 +1,12 @@ > -obj-y += arm-semi.o > -obj-$(CONFIG_SOFTMMU) += machine.o > -obj-$(CONFIG_KVM) += kvm.o > -obj-$(call land,$(CONFIG_KVM),$(call lnot,$(TARGET_AARCH64))) += kvm32.o > -obj-$(call land,$(CONFIG_KVM),$(TARGET_AARCH64)) += kvm64.o > -obj-$(call lnot,$(CONFIG_KVM)) += kvm-stub.o > -obj-y += translate.o op_helper.o helper.o cpu.o > -obj-y += cp.o > -obj-y += neon_helper.o iwmmxt_helper.o > -obj-y += gdbstub.o > -obj-$(CONFIG_SOFTMMU) += psci.o > -obj-$(TARGET_AARCH64) += cpu64.o translate-a64.o helper-a64.o gdbstub64.o > -obj-y += crypto_helper.o > +arch-obj-y += arm-semi.o > +arch-obj-$(CONFIG_SOFTMMU) += machine.o > +arch-obj-$(CONFIG_KVM) += kvm.o > +arch-obj-$(call land,$(CONFIG_KVM),$(call lnot,$(TARGET_AARCH64))) += kvm32.o > +arch-obj-$(call land,$(CONFIG_KVM),$(TARGET_AARCH64)) += kvm64.o > +arch-obj-$(call lnot,$(CONFIG_KVM)) += kvm-stub.o > +arch-obj-y += translate.o op_helper.o helper.o cpu.o > +arch-obj-y += neon_helper.o iwmmxt_helper.o > +arch-obj-y += gdbstub.o > +arch-obj-$(CONFIG_SOFTMMU) += psci.o > +arch-obj-$(TARGET_AARCH64) += cpu64.o translate-a64.o helper-a64.o > gdbstub64.o > +arch-obj-y += crypto_helper.o > diff --git a/target-arm/cp.c b/target-arm/cp.c > deleted file mode 100644 > index 39a15ee..0000000 > --- a/target-arm/cp.c > +++ /dev/null > @@ -1,328 +0,0 @@ > -#include "qemu-common.h" > -#include "../cpu.h" > - > -static bool raw_accessors_invalid(const ARMCPRegInfo *ri) > -{ > - /* Return true if the regdef would cause an assertion if you called > - * read_raw_cp_reg() or write_raw_cp_reg() on it (ie if it is a > - * program bug for it not to have the NO_RAW flag). > - * NB that returning false here doesn't necessarily mean that calling > - * read/write_raw_cp_reg() is safe, because we can't distinguish "has > - * read/write access functions which are safe for raw use" from "has > - * read/write access functions which have side effects but has forgotten > - * to provide raw access functions". > - * The tests here line up with the conditions in read/write_raw_cp_reg() > - * and assertions in raw_read()/raw_write(). > - */ > - if ((ri->type & ARM_CP_CONST) || > - ri->fieldoffset || > - ((ri->raw_writefn || ri->writefn) && (ri->raw_readfn || > ri->readfn))) { > - return false; > - } > - return true; > -} > - > -static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r, > - void *opaque, int state, int secstate, > - int crm, int opc1, int opc2) > -{ > - /* Private utility function for define_one_arm_cp_reg_with_opaque(): > - * add a single reginfo struct to the hash table. > - */ > - uint32_t *key = g_new(uint32_t, 1); > - ARMCPRegInfo *r2 = g_memdup(r, sizeof(ARMCPRegInfo)); > - int is64 = (r->type & ARM_CP_64BIT) ? 1 : 0; > - int ns = (secstate & ARM_CP_SECSTATE_NS) ? 1 : 0; > - > - /* Reset the secure state to the specific incoming state. This is > - * necessary as the register may have been defined with both states. > - */ > - r2->secure = secstate; > - > - if (r->bank_fieldoffsets[0] && r->bank_fieldoffsets[1]) { > - /* Register is banked (using both entries in array). > - * Overwriting fieldoffset as the array is only used to define > - * banked registers but later only fieldoffset is used. > - */ > - r2->fieldoffset = r->bank_fieldoffsets[ns]; > - } > - > - if (state == ARM_CP_STATE_AA32) { > - if (r->bank_fieldoffsets[0] && r->bank_fieldoffsets[1]) { > - /* If the register is banked then we don't need to migrate or > - * reset the 32-bit instance in certain cases: > - * > - * 1) If the register has both 32-bit and 64-bit instances then > we > - * can count on the 64-bit instance taking care of the > - * non-secure bank. > - * 2) If ARMv8 is enabled then we can count on a 64-bit version > - * taking care of the secure bank. This requires that > separate > - * 32 and 64-bit definitions are provided. > - */ > - if ((r->state == ARM_CP_STATE_BOTH && ns) || > - (arm_feature(&cpu->env, ARM_FEATURE_V8) && !ns)) { > - r2->type |= ARM_CP_ALIAS; > - } > - } else if ((secstate != r->secure) && !ns) { > - /* The register is not banked so we only want to allow migration > of > - * the non-secure instance. > - */ > - r2->type |= ARM_CP_ALIAS; > - } > - > - if (r->state == ARM_CP_STATE_BOTH) { > - /* We assume it is a cp15 register if the .cp field is left > unset. > - */ > - if (r2->cp == 0) { > - r2->cp = 15; > - } > - > -#ifdef HOST_WORDS_BIGENDIAN > - if (r2->fieldoffset) { > - r2->fieldoffset += sizeof(uint32_t); > - } > -#endif > - } > - } > - if (state == ARM_CP_STATE_AA64) { > - /* To allow abbreviation of ARMCPRegInfo > - * definitions, we treat cp == 0 as equivalent to > - * the value for "standard guest-visible sysreg". > - * STATE_BOTH definitions are also always "standard > - * sysreg" in their AArch64 view (the .cp value may > - * be non-zero for the benefit of the AArch32 view). > - */ > - if (r->cp == 0 || r->state == ARM_CP_STATE_BOTH) { > - r2->cp = CP_REG_ARM64_SYSREG_CP; > - } > - *key = ENCODE_AA64_CP_REG(r2->cp, r2->crn, crm, > - r2->opc0, opc1, opc2); > - } else { > - *key = ENCODE_CP_REG(r2->cp, is64, ns, r2->crn, crm, opc1, opc2); > - } > - if (opaque) { > - r2->opaque = opaque; > - } > - /* reginfo passed to helpers is correct for the actual access, > - * and is never ARM_CP_STATE_BOTH: > - */ > - r2->state = state; > - /* Make sure reginfo passed to helpers for wildcarded regs > - * has the correct crm/opc1/opc2 for this reg, not CP_ANY: > - */ > - r2->crm = crm; > - r2->opc1 = opc1; > - r2->opc2 = opc2; > - /* By convention, for wildcarded registers only the first > - * entry is used for migration; the others are marked as > - * ALIAS so we don't try to transfer the register > - * multiple times. Special registers (ie NOP/WFI) are > - * never migratable and not even raw-accessible. > - */ > - if ((r->type & ARM_CP_SPECIAL)) { > - r2->type |= ARM_CP_NO_RAW; > - } > - if (((r->crm == CP_ANY) && crm != 0) || > - ((r->opc1 == CP_ANY) && opc1 != 0) || > - ((r->opc2 == CP_ANY) && opc2 != 0)) { > - r2->type |= ARM_CP_ALIAS; > - } > - > - /* Check that raw accesses are either forbidden or handled. Note that > - * we can't assert this earlier because the setup of fieldoffset for > - * banked registers has to be done first. > - */ > - if (!(r2->type & ARM_CP_NO_RAW)) { > - assert(!raw_accessors_invalid(r2)); > - } > - > - /* Overriding of an existing definition must be explicitly > - * requested. > - */ > - if (!(r->type & ARM_CP_OVERRIDE)) { > - ARMCPRegInfo *oldreg; > - oldreg = g_hash_table_lookup(cpu->cp_regs, key); > - if (oldreg && !(oldreg->type & ARM_CP_OVERRIDE)) { > - fprintf(stderr, "Register redefined: cp=%d %d bit " > - "crn=%d crm=%d opc1=%d opc2=%d, " > - "was %s, now %s\n", r2->cp, 32 + 32 * is64, > - r2->crn, r2->crm, r2->opc1, r2->opc2, > - oldreg->name, r2->name); > - g_assert_not_reached(); > - } > - } > - g_hash_table_insert(cpu->cp_regs, key, r2); > -} > - > - > -void define_one_arm_cp_reg_with_opaque(ARMCPU *cpu, > - const ARMCPRegInfo *r, void *opaque) > -{ > - /* Define implementations of coprocessor registers. > - * We store these in a hashtable because typically > - * there are less than 150 registers in a space which > - * is 16*16*16*8*8 = 262144 in size. > - * Wildcarding is supported for the crm, opc1 and opc2 fields. > - * If a register is defined twice then the second definition is > - * used, so this can be used to define some generic registers and > - * then override them with implementation specific variations. > - * At least one of the original and the second definition should > - * include ARM_CP_OVERRIDE in its type bits -- this is just a guard > - * against accidental use. > - * > - * The state field defines whether the register is to be > - * visible in the AArch32 or AArch64 execution state. If the > - * state is set to ARM_CP_STATE_BOTH then we synthesise a > - * reginfo structure for the AArch32 view, which sees the lower > - * 32 bits of the 64 bit register. > - * > - * Only registers visible in AArch64 may set r->opc0; opc0 cannot > - * be wildcarded. AArch64 registers are always considered to be 64 > - * bits; the ARM_CP_64BIT* flag applies only to the AArch32 view of > - * the register, if any. > - */ > - int crm, opc1, opc2, state; > - int crmmin = (r->crm == CP_ANY) ? 0 : r->crm; > - int crmmax = (r->crm == CP_ANY) ? 15 : r->crm; > - int opc1min = (r->opc1 == CP_ANY) ? 0 : r->opc1; > - int opc1max = (r->opc1 == CP_ANY) ? 7 : r->opc1; > - int opc2min = (r->opc2 == CP_ANY) ? 0 : r->opc2; > - int opc2max = (r->opc2 == CP_ANY) ? 7 : r->opc2; > - /* 64 bit registers have only CRm and Opc1 fields */ > - assert(!((r->type & ARM_CP_64BIT) && (r->opc2 || r->crn))); > - /* op0 only exists in the AArch64 encodings */ > - assert((r->state != ARM_CP_STATE_AA32) || (r->opc0 == 0)); > - /* AArch64 regs are all 64 bit so ARM_CP_64BIT is meaningless */ > - assert((r->state != ARM_CP_STATE_AA64) || !(r->type & ARM_CP_64BIT)); > - /* The AArch64 pseudocode CheckSystemAccess() specifies that op1 > - * encodes a minimum access level for the register. We roll this > - * runtime check into our general permission check code, so check > - * here that the reginfo's specified permissions are strict enough > - * to encompass the generic architectural permission check. > - */ > - if (r->state != ARM_CP_STATE_AA32) { > - int mask = 0; > - switch (r->opc1) { > - case 0: case 1: case 2: > - /* min_EL EL1 */ > - mask = PL1_RW; > - break; > - case 3: > - /* min_EL EL0 */ > - mask = PL0_RW; > - break; > - case 4: > - /* min_EL EL2 */ > - mask = PL2_RW; > - break; > - case 5: > - /* unallocated encoding, so not possible */ > - assert(false); > - break; > - case 6: > - /* min_EL EL3 */ > - mask = PL3_RW; > - break; > - case 7: > - /* min_EL EL1, secure mode only (we don't check the latter) */ > - mask = PL1_RW; > - break; > - default: > - /* broken reginfo with out-of-range opc1 */ > - assert(false); > - break; > - } > - /* assert our permissions are not too lax (stricter is fine) */ > - assert((r->access & ~mask) == 0); > - } > - > - /* Check that the register definition has enough info to handle > - * reads and writes if they are permitted. > - */ > - if (!(r->type & (ARM_CP_SPECIAL|ARM_CP_CONST))) { > - if (r->access & PL3_R) { > - assert((r->fieldoffset || > - (r->bank_fieldoffsets[0] && r->bank_fieldoffsets[1])) || > - r->readfn); > - } > - if (r->access & PL3_W) { > - assert((r->fieldoffset || > - (r->bank_fieldoffsets[0] && r->bank_fieldoffsets[1])) || > - r->writefn); > - } > - } > - /* Bad type field probably means missing sentinel at end of reg list */ > - assert(cptype_valid(r->type)); > - for (crm = crmmin; crm <= crmmax; crm++) { > - for (opc1 = opc1min; opc1 <= opc1max; opc1++) { > - for (opc2 = opc2min; opc2 <= opc2max; opc2++) { > - for (state = ARM_CP_STATE_AA32; > - state <= ARM_CP_STATE_AA64; state++) { > - if (r->state != state && r->state != ARM_CP_STATE_BOTH) { > - continue; > - } > - if (state == ARM_CP_STATE_AA32) { > - /* Under AArch32 CP registers can be common > - * (same for secure and non-secure world) or banked. > - */ > - switch (r->secure) { > - case ARM_CP_SECSTATE_S: > - case ARM_CP_SECSTATE_NS: > - add_cpreg_to_hashtable(cpu, r, opaque, state, > - r->secure, crm, opc1, > opc2); > - break; > - default: > - add_cpreg_to_hashtable(cpu, r, opaque, state, > - ARM_CP_SECSTATE_S, > - crm, opc1, opc2); > - add_cpreg_to_hashtable(cpu, r, opaque, state, > - ARM_CP_SECSTATE_NS, > - crm, opc1, opc2); > - break; > - } > - } else { > - /* AArch64 registers get mapped to non-secure > instance > - * of AArch32 */ > - add_cpreg_to_hashtable(cpu, r, opaque, state, > - ARM_CP_SECSTATE_NS, > - crm, opc1, opc2); > - } > - } > - } > - } > - } > -} > - > -void define_arm_cp_regs_with_opaque(ARMCPU *cpu, > - const ARMCPRegInfo *regs, void *opaque) > -{ > - /* Define a whole list of registers */ > - const ARMCPRegInfo *r; > - for (r = regs; r->type != ARM_CP_SENTINEL; r++) { > - define_one_arm_cp_reg_with_opaque(cpu, r, opaque); > - } > -} > - > -const ARMCPRegInfo *get_arm_cp_reginfo(GHashTable *cpregs, uint32_t > encoded_cp) > -{ > - return g_hash_table_lookup(cpregs, &encoded_cp); > -} > - > -void arm_cp_write_ignore(CPUARMState *env, const ARMCPRegInfo *ri, > - uint64_t value) > -{ > - /* Helper coprocessor write function for write-ignore registers */ > -} > - > -uint64_t arm_cp_read_zero(CPUARMState *env, const ARMCPRegInfo *ri) > -{ > - /* Helper coprocessor write function for read-as-zero registers */ > - return 0; > -} > - > -void arm_cp_reset_ignore(CPUARMState *env, const ARMCPRegInfo *opaque) > -{ > - /* Helper coprocessor reset function for do-nothing-on-reset registers */ > -} > - > - > diff --git a/target-arm/cpu-qom.h b/target-arm/cpu-qom.h > index 3cbc4a0..77cfaf1 100644 > --- a/target-arm/cpu-qom.h > +++ b/target-arm/cpu-qom.h > @@ -198,9 +198,11 @@ static inline ARMCPU *arm_env_get_cpu(CPUARMState *env) > return container_of(env, ARMCPU, env); > } > > +#ifndef TARGET_MULTI > #define ENV_GET_CPU(e) CPU(arm_env_get_cpu(e)) > > #define ENV_OFFSET offsetof(ARMCPU, env) > +#endif /* !TARGET_MULTI */ > > #ifndef CONFIG_USER_ONLY > extern const struct VMStateDescription vmstate_arm_cpu; > diff --git a/target-arm/cpu.c b/target-arm/cpu.c > index 6edee95..8b5471a 100644 > --- a/target-arm/cpu.c > +++ b/target-arm/cpu.c > @@ -29,6 +29,7 @@ > #include "sysemu/sysemu.h" > #include "sysemu/kvm.h" > #include "kvm_arm.h" > +#include "tcg/tcg.h" > > static void arm_cpu_set_pc(CPUState *cs, vaddr value) > { > @@ -426,6 +427,7 @@ static void arm_cpu_initfn(Object *obj) > static bool inited; > uint32_t Aff1, Aff0; > > + CPU_SET_QOM_HOOKS(cs); > cs->env_ptr = &cpu->env; > cpu_exec_init(cs, &error_abort); > cpu->cp_regs = g_hash_table_new_full(g_int_hash, g_int_equal, > diff --git a/target-arm/cpu.h b/target-arm/cpu.h > index 40f8551..9c53cc6 100644 > --- a/target-arm/cpu.h > +++ b/target-arm/cpu.h > @@ -38,10 +38,13 @@ > #define CPUArchState struct CPUARMState > > #include "qemu-common.h" > + > #include "exec/cpu-defs.h" > > #include "fpu/softfloat.h" > > +#ifndef TARGET_MULTI > + > #define EXCP_UDEF 1 /* undefined instruction */ > #define EXCP_SWI 2 /* software interrupt */ > #define EXCP_PREFETCH_ABORT 3 > @@ -58,6 +61,10 @@ > #define EXCP_VIRQ 14 > #define EXCP_VFIQ 15 > > +#endif /* TARGET_MULTI */ > + > +/* These defs are public as needed by ARMv7M NVIC */ > + > #define ARMV7M_EXCP_RESET 1 > #define ARMV7M_EXCP_NMI 2 > #define ARMV7M_EXCP_HARD 3 > @@ -74,6 +81,8 @@ > #define CPU_INTERRUPT_VIRQ CPU_INTERRUPT_TGT_EXT_2 > #define CPU_INTERRUPT_VFIQ CPU_INTERRUPT_TGT_EXT_3 > > +#ifndef TARGET_MULTI > + > /* The usual mapping for an AArch64 system register to its AArch32 > * counterpart is for the 32 bit world to have access to the lower > * half only (with writes leaving the upper half untouched). It's > @@ -88,6 +97,8 @@ > #define offsetofhigh32(S, M) (offsetof(S, M) + sizeof(uint32_t)) > #endif > > +#endif /* !TARGET_MULTI */ > + > /* Meanings of the ARMCPU object's four inbound GPIO lines */ > #define ARM_CPU_IRQ 0 > #define ARM_CPU_FIQ 1 > @@ -504,6 +515,8 @@ static inline ARMCPU *cpu_arm_init(const char *cpu_model) > return ARM_CPU(cpu_generic_init(TYPE_ARM_CPU, cpu_model)); > } > > +#ifndef TARGET_MULTI > + > uint32_t do_arm_semihosting(CPUARMState *env); > void aarch64_sync_32_to_64(CPUARMState *env); > void aarch64_sync_64_to_32(CPUARMState *env); > @@ -638,6 +651,12 @@ void pmccntr_sync(CPUARMState *env); > #define TTBCR_SH1 (1U << 28) > #define TTBCR_EAE (1U << 31) > > +#endif /* !TARGET_MULTI */ > + > +/* Some bits of system level code do direct deposit to the PSTATE. Allow > + * these symbols as global even in multi-arch. > + */ > + > /* Bit definitions for ARMv8 SPSR (PSTATE) format. > * Only these are valid when in AArch64 mode; in > * AArch32 mode SPSRs are basically CPSR-format. > @@ -667,6 +686,8 @@ void pmccntr_sync(CPUARMState *env); > #define PSTATE_MODE_EL1t 4 > #define PSTATE_MODE_EL0t 0 > > +#ifndef TARGET_MULTI > + > /* Map EL and handler into a PSTATE_MODE. */ > static inline unsigned int aarch64_pstate_mode(unsigned int el, bool handler) > { > @@ -775,7 +796,13 @@ static inline void xpsr_write(CPUARMState *env, uint32_t > val, uint32_t mask) > #define HCR_ID (1ULL << 33) > #define HCR_MASK ((1ULL << 34) - 1) > > +#endif /* !TARGET_MULTI */ > + > +/* bootloader needs this to init security state of processor */ > #define SCR_NS (1U << 0) > + > +#ifndef TARGET_MULTI > + > #define SCR_IRQ (1U << 1) > #define SCR_FIQ (1U << 2) > #define SCR_EA (1U << 3) > @@ -824,6 +851,8 @@ static inline void vfp_set_fpcr(CPUARMState *env, > uint32_t val) > vfp_set_fpscr(env, new_fpscr); > } > > +#endif /* !TARGET_MULTI */ > + > enum arm_cpu_mode { > ARM_CPU_MODE_USR = 0x10, > ARM_CPU_MODE_FIQ = 0x11, > @@ -836,6 +865,8 @@ enum arm_cpu_mode { > ARM_CPU_MODE_SYS = 0x1f > }; > > +#ifndef TARGET_MULTI > + > /* VFP system registers. */ > #define ARM_VFP_FPSID 0 > #define ARM_VFP_FPSCR 1 > @@ -856,6 +887,8 @@ enum arm_cpu_mode { > #define ARM_IWMMXT_wCGR2 10 > #define ARM_IWMMXT_wCGR3 11 > > +#endif /* TARGET_MULTI */ > + > /* If adding a feature bit which corresponds to a Linux ELF > * HWCAP bit, remember to update the feature-bit-to-hwcap > * mapping in linux-user/elfload.c:get_elf_hwcap(). > @@ -912,6 +945,8 @@ static inline int arm_feature(CPUARMState *env, int > feature) > return (env->features & (1ULL << feature)) != 0; > } > > +#ifndef TARGET_MULTI > + > #if !defined(CONFIG_USER_ONLY) > /* Return true if exception levels below EL3 are in secure state, > * or would be following an exception return to that level. > @@ -1022,6 +1057,8 @@ static inline bool access_secure_reg(CPUARMState *env) > uint32_t arm_phys_excp_target_el(CPUState *cs, uint32_t excp_idx, > uint32_t cur_el, bool secure); > > +#endif /* TARGET_MULTI */ > + > /* Interface between CPU and Interrupt controller. */ > void armv7m_nvic_set_pending(void *opaque, int irq); > int armv7m_nvic_acknowledge_irq(void *opaque); > @@ -1231,6 +1268,8 @@ static inline bool cptype_valid(int cptype) > #define PL1_RW (PL1_R | PL1_W) > #define PL0_RW (PL0_R | PL0_W) > > +#ifndef TARGET_MULTI > + > /* Return the current Exception Level (as per ARMv8; note that this differs > * from the ARMv7 Privilege Level). > */ > @@ -1263,6 +1302,8 @@ static inline int arm_current_el(CPUARMState *env) > } > } > > +#endif > + > typedef struct ARMCPRegInfo ARMCPRegInfo; > > typedef enum CPAccessResult { > @@ -1448,6 +1489,8 @@ static inline bool cp_access_ok(int current_el, > return (ri->access >> ((current_el * 2) + isread)) & 1; > } > > +#ifndef TARGET_MULTI > + > /** > * write_list_to_cpustate > * @cpu: ARMCPU > @@ -1928,6 +1971,8 @@ static inline void cpu_get_tb_cpu_state(CPUARMState > *env, target_ulong *pc, > > #include "exec/exec-all.h" > > +#endif /* !TARGET_MULTI */ > + > enum { > QEMU_PSCI_CONDUIT_DISABLED = 0, > QEMU_PSCI_CONDUIT_SMC = 1, > diff --git a/target-arm/hw/Makefile.objs b/target-arm/hw/Makefile.objs > new file mode 100644 > index 0000000..d34bbd4 > --- /dev/null > +++ b/target-arm/hw/Makefile.objs > @@ -0,0 +1 @@ > +obj-y += cp.o > diff --git a/target-arm/hw/cp.c b/target-arm/hw/cp.c > new file mode 100644 > index 0000000..39a15ee > --- /dev/null > +++ b/target-arm/hw/cp.c > @@ -0,0 +1,328 @@ > +#include "qemu-common.h" > +#include "../cpu.h" > + > +static bool raw_accessors_invalid(const ARMCPRegInfo *ri) > +{ > + /* Return true if the regdef would cause an assertion if you called > + * read_raw_cp_reg() or write_raw_cp_reg() on it (ie if it is a > + * program bug for it not to have the NO_RAW flag). > + * NB that returning false here doesn't necessarily mean that calling > + * read/write_raw_cp_reg() is safe, because we can't distinguish "has > + * read/write access functions which are safe for raw use" from "has > + * read/write access functions which have side effects but has forgotten > + * to provide raw access functions". > + * The tests here line up with the conditions in read/write_raw_cp_reg() > + * and assertions in raw_read()/raw_write(). > + */ > + if ((ri->type & ARM_CP_CONST) || > + ri->fieldoffset || > + ((ri->raw_writefn || ri->writefn) && (ri->raw_readfn || > ri->readfn))) { > + return false; > + } > + return true; > +} > + > +static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r, > + void *opaque, int state, int secstate, > + int crm, int opc1, int opc2) > +{ > + /* Private utility function for define_one_arm_cp_reg_with_opaque(): > + * add a single reginfo struct to the hash table. > + */ > + uint32_t *key = g_new(uint32_t, 1); > + ARMCPRegInfo *r2 = g_memdup(r, sizeof(ARMCPRegInfo)); > + int is64 = (r->type & ARM_CP_64BIT) ? 1 : 0; > + int ns = (secstate & ARM_CP_SECSTATE_NS) ? 1 : 0; > + > + /* Reset the secure state to the specific incoming state. This is > + * necessary as the register may have been defined with both states. > + */ > + r2->secure = secstate; > + > + if (r->bank_fieldoffsets[0] && r->bank_fieldoffsets[1]) { > + /* Register is banked (using both entries in array). > + * Overwriting fieldoffset as the array is only used to define > + * banked registers but later only fieldoffset is used. > + */ > + r2->fieldoffset = r->bank_fieldoffsets[ns]; > + } > + > + if (state == ARM_CP_STATE_AA32) { > + if (r->bank_fieldoffsets[0] && r->bank_fieldoffsets[1]) { > + /* If the register is banked then we don't need to migrate or > + * reset the 32-bit instance in certain cases: > + * > + * 1) If the register has both 32-bit and 64-bit instances then > we > + * can count on the 64-bit instance taking care of the > + * non-secure bank. > + * 2) If ARMv8 is enabled then we can count on a 64-bit version > + * taking care of the secure bank. This requires that > separate > + * 32 and 64-bit definitions are provided. > + */ > + if ((r->state == ARM_CP_STATE_BOTH && ns) || > + (arm_feature(&cpu->env, ARM_FEATURE_V8) && !ns)) { > + r2->type |= ARM_CP_ALIAS; > + } > + } else if ((secstate != r->secure) && !ns) { > + /* The register is not banked so we only want to allow migration > of > + * the non-secure instance. > + */ > + r2->type |= ARM_CP_ALIAS; > + } > + > + if (r->state == ARM_CP_STATE_BOTH) { > + /* We assume it is a cp15 register if the .cp field is left > unset. > + */ > + if (r2->cp == 0) { > + r2->cp = 15; > + } > + > +#ifdef HOST_WORDS_BIGENDIAN > + if (r2->fieldoffset) { > + r2->fieldoffset += sizeof(uint32_t); > + } > +#endif > + } > + } > + if (state == ARM_CP_STATE_AA64) { > + /* To allow abbreviation of ARMCPRegInfo > + * definitions, we treat cp == 0 as equivalent to > + * the value for "standard guest-visible sysreg". > + * STATE_BOTH definitions are also always "standard > + * sysreg" in their AArch64 view (the .cp value may > + * be non-zero for the benefit of the AArch32 view). > + */ > + if (r->cp == 0 || r->state == ARM_CP_STATE_BOTH) { > + r2->cp = CP_REG_ARM64_SYSREG_CP; > + } > + *key = ENCODE_AA64_CP_REG(r2->cp, r2->crn, crm, > + r2->opc0, opc1, opc2); > + } else { > + *key = ENCODE_CP_REG(r2->cp, is64, ns, r2->crn, crm, opc1, opc2); > + } > + if (opaque) { > + r2->opaque = opaque; > + } > + /* reginfo passed to helpers is correct for the actual access, > + * and is never ARM_CP_STATE_BOTH: > + */ > + r2->state = state; > + /* Make sure reginfo passed to helpers for wildcarded regs > + * has the correct crm/opc1/opc2 for this reg, not CP_ANY: > + */ > + r2->crm = crm; > + r2->opc1 = opc1; > + r2->opc2 = opc2; > + /* By convention, for wildcarded registers only the first > + * entry is used for migration; the others are marked as > + * ALIAS so we don't try to transfer the register > + * multiple times. Special registers (ie NOP/WFI) are > + * never migratable and not even raw-accessible. > + */ > + if ((r->type & ARM_CP_SPECIAL)) { > + r2->type |= ARM_CP_NO_RAW; > + } > + if (((r->crm == CP_ANY) && crm != 0) || > + ((r->opc1 == CP_ANY) && opc1 != 0) || > + ((r->opc2 == CP_ANY) && opc2 != 0)) { > + r2->type |= ARM_CP_ALIAS; > + } > + > + /* Check that raw accesses are either forbidden or handled. Note that > + * we can't assert this earlier because the setup of fieldoffset for > + * banked registers has to be done first. > + */ > + if (!(r2->type & ARM_CP_NO_RAW)) { > + assert(!raw_accessors_invalid(r2)); > + } > + > + /* Overriding of an existing definition must be explicitly > + * requested. > + */ > + if (!(r->type & ARM_CP_OVERRIDE)) { > + ARMCPRegInfo *oldreg; > + oldreg = g_hash_table_lookup(cpu->cp_regs, key); > + if (oldreg && !(oldreg->type & ARM_CP_OVERRIDE)) { > + fprintf(stderr, "Register redefined: cp=%d %d bit " > + "crn=%d crm=%d opc1=%d opc2=%d, " > + "was %s, now %s\n", r2->cp, 32 + 32 * is64, > + r2->crn, r2->crm, r2->opc1, r2->opc2, > + oldreg->name, r2->name); > + g_assert_not_reached(); > + } > + } > + g_hash_table_insert(cpu->cp_regs, key, r2); > +} > + > + > +void define_one_arm_cp_reg_with_opaque(ARMCPU *cpu, > + const ARMCPRegInfo *r, void *opaque) > +{ > + /* Define implementations of coprocessor registers. > + * We store these in a hashtable because typically > + * there are less than 150 registers in a space which > + * is 16*16*16*8*8 = 262144 in size. > + * Wildcarding is supported for the crm, opc1 and opc2 fields. > + * If a register is defined twice then the second definition is > + * used, so this can be used to define some generic registers and > + * then override them with implementation specific variations. > + * At least one of the original and the second definition should > + * include ARM_CP_OVERRIDE in its type bits -- this is just a guard > + * against accidental use. > + * > + * The state field defines whether the register is to be > + * visible in the AArch32 or AArch64 execution state. If the > + * state is set to ARM_CP_STATE_BOTH then we synthesise a > + * reginfo structure for the AArch32 view, which sees the lower > + * 32 bits of the 64 bit register. > + * > + * Only registers visible in AArch64 may set r->opc0; opc0 cannot > + * be wildcarded. AArch64 registers are always considered to be 64 > + * bits; the ARM_CP_64BIT* flag applies only to the AArch32 view of > + * the register, if any. > + */ > + int crm, opc1, opc2, state; > + int crmmin = (r->crm == CP_ANY) ? 0 : r->crm; > + int crmmax = (r->crm == CP_ANY) ? 15 : r->crm; > + int opc1min = (r->opc1 == CP_ANY) ? 0 : r->opc1; > + int opc1max = (r->opc1 == CP_ANY) ? 7 : r->opc1; > + int opc2min = (r->opc2 == CP_ANY) ? 0 : r->opc2; > + int opc2max = (r->opc2 == CP_ANY) ? 7 : r->opc2; > + /* 64 bit registers have only CRm and Opc1 fields */ > + assert(!((r->type & ARM_CP_64BIT) && (r->opc2 || r->crn))); > + /* op0 only exists in the AArch64 encodings */ > + assert((r->state != ARM_CP_STATE_AA32) || (r->opc0 == 0)); > + /* AArch64 regs are all 64 bit so ARM_CP_64BIT is meaningless */ > + assert((r->state != ARM_CP_STATE_AA64) || !(r->type & ARM_CP_64BIT)); > + /* The AArch64 pseudocode CheckSystemAccess() specifies that op1 > + * encodes a minimum access level for the register. We roll this > + * runtime check into our general permission check code, so check > + * here that the reginfo's specified permissions are strict enough > + * to encompass the generic architectural permission check. > + */ > + if (r->state != ARM_CP_STATE_AA32) { > + int mask = 0; > + switch (r->opc1) { > + case 0: case 1: case 2: > + /* min_EL EL1 */ > + mask = PL1_RW; > + break; > + case 3: > + /* min_EL EL0 */ > + mask = PL0_RW; > + break; > + case 4: > + /* min_EL EL2 */ > + mask = PL2_RW; > + break; > + case 5: > + /* unallocated encoding, so not possible */ > + assert(false); > + break; > + case 6: > + /* min_EL EL3 */ > + mask = PL3_RW; > + break; > + case 7: > + /* min_EL EL1, secure mode only (we don't check the latter) */ > + mask = PL1_RW; > + break; > + default: > + /* broken reginfo with out-of-range opc1 */ > + assert(false); > + break; > + } > + /* assert our permissions are not too lax (stricter is fine) */ > + assert((r->access & ~mask) == 0); > + } > + > + /* Check that the register definition has enough info to handle > + * reads and writes if they are permitted. > + */ > + if (!(r->type & (ARM_CP_SPECIAL|ARM_CP_CONST))) { > + if (r->access & PL3_R) { > + assert((r->fieldoffset || > + (r->bank_fieldoffsets[0] && r->bank_fieldoffsets[1])) || > + r->readfn); > + } > + if (r->access & PL3_W) { > + assert((r->fieldoffset || > + (r->bank_fieldoffsets[0] && r->bank_fieldoffsets[1])) || > + r->writefn); > + } > + } > + /* Bad type field probably means missing sentinel at end of reg list */ > + assert(cptype_valid(r->type)); > + for (crm = crmmin; crm <= crmmax; crm++) { > + for (opc1 = opc1min; opc1 <= opc1max; opc1++) { > + for (opc2 = opc2min; opc2 <= opc2max; opc2++) { > + for (state = ARM_CP_STATE_AA32; > + state <= ARM_CP_STATE_AA64; state++) { > + if (r->state != state && r->state != ARM_CP_STATE_BOTH) { > + continue; > + } > + if (state == ARM_CP_STATE_AA32) { > + /* Under AArch32 CP registers can be common > + * (same for secure and non-secure world) or banked. > + */ > + switch (r->secure) { > + case ARM_CP_SECSTATE_S: > + case ARM_CP_SECSTATE_NS: > + add_cpreg_to_hashtable(cpu, r, opaque, state, > + r->secure, crm, opc1, > opc2); > + break; > + default: > + add_cpreg_to_hashtable(cpu, r, opaque, state, > + ARM_CP_SECSTATE_S, > + crm, opc1, opc2); > + add_cpreg_to_hashtable(cpu, r, opaque, state, > + ARM_CP_SECSTATE_NS, > + crm, opc1, opc2); > + break; > + } > + } else { > + /* AArch64 registers get mapped to non-secure > instance > + * of AArch32 */ > + add_cpreg_to_hashtable(cpu, r, opaque, state, > + ARM_CP_SECSTATE_NS, > + crm, opc1, opc2); > + } > + } > + } > + } > + } > +} > + > +void define_arm_cp_regs_with_opaque(ARMCPU *cpu, > + const ARMCPRegInfo *regs, void *opaque) > +{ > + /* Define a whole list of registers */ > + const ARMCPRegInfo *r; > + for (r = regs; r->type != ARM_CP_SENTINEL; r++) { > + define_one_arm_cp_reg_with_opaque(cpu, r, opaque); > + } > +} > + > +const ARMCPRegInfo *get_arm_cp_reginfo(GHashTable *cpregs, uint32_t > encoded_cp) > +{ > + return g_hash_table_lookup(cpregs, &encoded_cp); > +} > + > +void arm_cp_write_ignore(CPUARMState *env, const ARMCPRegInfo *ri, > + uint64_t value) > +{ > + /* Helper coprocessor write function for write-ignore registers */ > +} > + > +uint64_t arm_cp_read_zero(CPUARMState *env, const ARMCPRegInfo *ri) > +{ > + /* Helper coprocessor write function for read-as-zero registers */ > + return 0; > +} > + > +void arm_cp_reset_ignore(CPUARMState *env, const ARMCPRegInfo *opaque) > +{ > + /* Helper coprocessor reset function for do-nothing-on-reset registers */ > +} > + > + >