[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH v3 26/35] arm: enable multi-arch
From: |
Peter Crosthwaite |
Subject: |
[Qemu-devel] [PATCH v3 26/35] arm: enable multi-arch |
Date: |
Sat, 18 Jul 2015 02:40:36 -0700 |
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.
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 */
+}
+
+
--
1.9.1
- [Qemu-devel] [PATCH v3 20/35] Makefile.target: Introduce arch-obj, (continued)
- [Qemu-devel] [PATCH v3 20/35] Makefile.target: Introduce arch-obj, Peter Crosthwaite, 2015/07/18
- [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 <=
- [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