[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Qemu-devel] [PATCH v3 26/35] arm: enable multi-arch
From: |
Paolo Bonzini |
Subject: |
Re: [Qemu-devel] [PATCH v3 26/35] arm: enable multi-arch |
Date: |
Sat, 18 Jul 2015 14:32:53 +0200 |
User-agent: |
Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Thunderbird/38.0.1 |
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 <address@hidden>
> ---
> 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 */
> +}
> +
> +
>
- Re: [Qemu-devel] [PATCH v3 20/35] Makefile.target: Introduce arch-obj, (continued)
- [Qemu-devel] [PATCH v3 22/35] core: Introduce multi-arch build, Peter Crosthwaite, 2015/07/18
- [Qemu-devel] [PATCH v3 21/35] core: virtualise CPU interfaces completely, Peter Crosthwaite, 2015/07/18
- [Qemu-devel] [PATCH v3 23/35] arm: cpu: static inline cpu_arm_init(), Peter Crosthwaite, 2015/07/18
- [Qemu-devel] [PATCH v3 25/35] arm: register cpu_list() function, Peter Crosthwaite, 2015/07/18
- [Qemu-devel] [PATCH v3 24/35] target-arm: Split cp helper API to new C file, Peter Crosthwaite, 2015/07/18
- [Qemu-devel] [PATCH v3 27/35] hw: arm: Explicitly include cpu.h for consumers, Peter Crosthwaite, 2015/07/18
- [Qemu-devel] [PATCH v3 26/35] arm: enable multi-arch, Peter Crosthwaite, 2015/07/18
- Re: [Qemu-devel] [PATCH v3 26/35] arm: enable multi-arch,
Paolo Bonzini <=
- [Qemu-devel] [PATCH v3 28/35] arm: Remove ELF_MACHINE from cpu.h, Peter Crosthwaite, 2015/07/18
- [Qemu-devel] [PATCH v3 29/35] hw: mb: Explicitly include cpu.h for consumers, Peter Crosthwaite, 2015/07/18
- [Qemu-devel] [PATCH v3 30/35] mb: Remove ELF_MACHINE from cpu.h, Peter Crosthwaite, 2015/07/18
- [Qemu-devel] [PATCH v3 31/35] microblaze: enable multi-arch, Peter Crosthwaite, 2015/07/18
- [Qemu-devel] [PATCH v3 32/35] arm: boot: Don't assume all CPUs are ARM, Peter Crosthwaite, 2015/07/18
- [Qemu-devel] [PATCH v3 34/35] HACK: mb: boot: Assume using -firmware for mb software, Peter Crosthwaite, 2015/07/18
- [Qemu-devel] [PATCH v3 35/35] HACK: mb: boot: Disable dtb load in multi-arch, Peter Crosthwaite, 2015/07/18