From: Paolo Bonzini <pbonzini@redhat.com>
To: Peter Crosthwaite <crosthwaitepeter@gmail.com>, qemu-devel@nongnu.org
Cc: peter.maydell@linaro.org, rth@twiddle.net,
edgar.iglesias@gmail.com, afaerber@suse.de,
Peter Crosthwaite <crosthwaite.peter@gmail.com>
Subject: Re: [Qemu-devel] [PATCH v3 26/35] arm: enable multi-arch
Date: Sat, 18 Jul 2015 14:32:53 +0200 [thread overview]
Message-ID: <55AA4775.8010801@redhat.com> (raw)
In-Reply-To: <3bb02808559f2a7281003517770329232800f564.1437212383.git.crosthwaite.peter@gmail.com>
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.peter@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 */
> +}
> +
> +
>
next prev parent reply other threads:[~2015-07-18 12:33 UTC|newest]
Thread overview: 53+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-07-18 9:40 [Qemu-devel] [PATCH v3 00/35] Multi Architecture System Emulation Peter Crosthwaite
2015-07-18 9:40 ` [Qemu-devel] [PATCH v3 01/35] cpu-exec: Migrate some generic fns to cpu-exec-common Peter Crosthwaite
2015-07-18 12:44 ` Paolo Bonzini
2015-09-07 5:22 ` Peter Crosthwaite
2015-07-18 9:40 ` [Qemu-devel] [PATCH v3 02/35] translate: Listify tcg_exec_init() Peter Crosthwaite
2015-09-07 5:24 ` Peter Crosthwaite
2015-07-18 9:40 ` [Qemu-devel] [PATCH v3 03/35] translate-all: Move tcg_handle_interrupt() to -common Peter Crosthwaite
2015-07-18 9:40 ` [Qemu-devel] [PATCH v3 04/35] tcg: split tcg_op_defs " Peter Crosthwaite
2015-07-18 9:40 ` [Qemu-devel] [PATCH v3 05/35] tcg: Move tcg_tb_ptr " Peter Crosthwaite
2015-07-18 9:40 ` [Qemu-devel] [PATCH v3 06/35] translate: move real_host_page setting " Peter Crosthwaite
2015-07-18 9:40 ` [Qemu-devel] [PATCH v3 07/35] cpus: Listify cpu_list() function Peter Crosthwaite
2015-07-18 9:40 ` [Qemu-devel] [PATCH v3 08/35] translate-common: Listify tcg_enabled() Peter Crosthwaite
2015-07-18 9:40 ` [Qemu-devel] [PATCH v3 09/35] core: Convert tcg_enabled() users to tcg_(any|all)_enabled() Peter Crosthwaite
2015-07-18 9:40 ` [Qemu-devel] [PATCH v3 10/35] exec-all: Move cpu_can_do_io() to qom/cpu.h Peter Crosthwaite
2015-07-18 9:40 ` [Qemu-devel] [PATCH v3 11/35] cputlb: move CPU_LOOP() for tlb_reset() to exec.c Peter Crosthwaite
2015-07-18 9:40 ` [Qemu-devel] [PATCH v3 12/35] cputlb: Change tlb_set_dirty() arg to cpu Peter Crosthwaite
2015-07-18 9:40 ` [Qemu-devel] [PATCH v3 13/35] include/exec: Move cputlb exec.c defs out Peter Crosthwaite
2015-07-18 9:40 ` [Qemu-devel] [PATCH v3 14/35] cpu-common: Define tb_page_addr_t for everyone Peter Crosthwaite
2015-07-18 9:40 ` [Qemu-devel] [PATCH v3 15/35] include/exec: Split target_long def to new header Peter Crosthwaite
2015-07-18 12:16 ` Paolo Bonzini
2015-07-18 12:37 ` Paolo Bonzini
2015-07-18 15:37 ` Peter Crosthwaite
2015-07-18 16:01 ` Paolo Bonzini
2015-07-18 9:40 ` [Qemu-devel] [PATCH v3 16/35] cpu-defs: Allow multiple inclusions Peter Crosthwaite
2015-07-18 9:40 ` [Qemu-devel] [PATCH v3 17/35] monitor: uninclude cpu_ldst Peter Crosthwaite
2015-07-18 9:40 ` [Qemu-devel] [PATCH v3 18/35] target-*: Don't redefine cpu_exec() Peter Crosthwaite
2016-06-21 11:19 ` Paolo Bonzini
2015-07-18 9:40 ` [Qemu-devel] [PATCH v3 19/35] target-*: cpu.h: Undefine core code symbols Peter Crosthwaite
2015-07-18 9:40 ` [Qemu-devel] [PATCH v3 20/35] Makefile.target: Introduce arch-obj Peter Crosthwaite
2015-07-18 12:23 ` Paolo Bonzini
2015-07-18 12:29 ` Paolo Bonzini
2015-07-18 9:40 ` [Qemu-devel] [PATCH v3 21/35] core: virtualise CPU interfaces completely Peter Crosthwaite
2015-07-18 9:40 ` [Qemu-devel] [PATCH v3 22/35] core: Introduce multi-arch build Peter Crosthwaite
2015-07-18 9:40 ` [Qemu-devel] [PATCH v3 23/35] arm: cpu: static inline cpu_arm_init() Peter Crosthwaite
2015-07-18 9:40 ` [Qemu-devel] [PATCH v3 24/35] target-arm: Split cp helper API to new C file Peter Crosthwaite
2015-07-18 12:30 ` Paolo Bonzini
2015-07-18 9:40 ` [Qemu-devel] [PATCH v3 25/35] arm: register cpu_list() function Peter Crosthwaite
2015-07-18 9:40 ` [Qemu-devel] [PATCH v3 26/35] arm: enable multi-arch Peter Crosthwaite
2015-07-18 12:32 ` Paolo Bonzini [this message]
2015-07-18 9:40 ` [Qemu-devel] [PATCH v3 27/35] hw: arm: Explicitly include cpu.h for consumers Peter Crosthwaite
2015-07-18 9:40 ` [Qemu-devel] [PATCH v3 28/35] arm: Remove ELF_MACHINE from cpu.h Peter Crosthwaite
2015-07-18 12:33 ` Paolo Bonzini
2015-08-15 23:29 ` Peter Crosthwaite
2015-07-18 9:40 ` [Qemu-devel] [PATCH v3 29/35] hw: mb: Explicitly include cpu.h for consumers Peter Crosthwaite
2015-07-18 9:40 ` [Qemu-devel] [PATCH v3 30/35] mb: Remove ELF_MACHINE from cpu.h Peter Crosthwaite
2015-07-18 9:40 ` [Qemu-devel] [PATCH v3 31/35] microblaze: enable multi-arch Peter Crosthwaite
2015-07-18 12:35 ` Paolo Bonzini
2015-07-18 20:04 ` Peter Crosthwaite
2015-07-18 9:40 ` [Qemu-devel] [PATCH v3 32/35] arm: boot: Don't assume all CPUs are ARM Peter Crosthwaite
2015-07-18 9:40 ` [Qemu-devel] [PATCH v3 34/35] HACK: mb: boot: Assume using -firmware for mb software Peter Crosthwaite
2015-07-18 9:40 ` [Qemu-devel] [PATCH v3 35/35] HACK: mb: boot: Disable dtb load in multi-arch Peter Crosthwaite
2015-07-18 12:44 ` [Qemu-devel] [PATCH v3 00/35] Multi Architecture System Emulation Paolo Bonzini
2015-07-18 15:45 ` Peter Crosthwaite
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=55AA4775.8010801@redhat.com \
--to=pbonzini@redhat.com \
--cc=afaerber@suse.de \
--cc=crosthwaite.peter@gmail.com \
--cc=crosthwaitepeter@gmail.com \
--cc=edgar.iglesias@gmail.com \
--cc=peter.maydell@linaro.org \
--cc=qemu-devel@nongnu.org \
--cc=rth@twiddle.net \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.