#define ARM_CPU_H
#include "kvm-consts.h"
+#include "hw/registerfields.h"
#if defined(TARGET_AARCH64)
/* AArch64 definitions */
# define TARGET_LONG_BITS 32
#endif
+/* ARM processors have a weak memory model */
+#define TCG_GUEST_DEFAULT_MO (0)
+
#define CPUArchState struct CPUARMState
#include "qemu-common.h"
#define EXCP_VIRQ 14
#define EXCP_VFIQ 15
#define EXCP_SEMIHOST 16 /* semihosting call */
+#define EXCP_NOCP 17 /* v7M NOCP UsageFault */
+#define EXCP_INVSTATE 18 /* v7M INVSTATE UsageFault */
+/* NB: add new EXCP_ defines to the array in arm_log_exception() too */
#define ARMV7M_EXCP_RESET 1
#define ARMV7M_EXCP_NMI 2
uint64_t c9_pmcr; /* performance monitor control register */
uint64_t c9_pmcnten; /* perf monitor counter enables */
uint32_t c9_pmovsr; /* perf monitor overflow status */
- uint32_t c9_pmxevtyper; /* perf monitor event type */
uint32_t c9_pmuserenr; /* perf monitor user enable */
- uint32_t c9_pminten; /* perf monitor interrupt enables */
+ uint64_t c9_pmselr; /* perf monitor counter selection register */
+ uint64_t c9_pminten; /* perf monitor interrupt enables */
union { /* Memory attribute redirection */
struct {
#ifdef HOST_WORDS_BIGENDIAN
uint32_t vecbase;
uint32_t basepri;
uint32_t control;
- int current_sp;
+ uint32_t ccr; /* Configuration and Control */
+ uint32_t cfsr; /* Configurable Fault Status */
+ uint32_t hfsr; /* HardFault Status */
+ uint32_t dfsr; /* Debug Fault Status Register */
+ uint32_t mmfar; /* MemManage Fault Address */
+ uint32_t bfar; /* BusFault Address */
int exception;
} v7m;
void *nvic;
const struct arm_boot_info *boot_info;
+ /* Store GICv3CPUState to access from this struct */
+ void *gicv3state;
} CPUARMState;
/**
*/
typedef void ARMELChangeHook(ARMCPU *cpu, void *opaque);
+
+/* These values map onto the return values for
+ * QEMU_PSCI_0_2_FN_AFFINITY_INFO */
+typedef enum ARMPSCIState {
+ PSCI_ON = 0,
+ PSCI_OFF = 1,
+ PSCI_ON_PENDING = 2
+} ARMPSCIState;
+
/**
* ARMCPU:
* @env: #CPUARMState
QEMUTimer *gt_timer[NUM_GTIMERS];
/* GPIO outputs for generic timer */
qemu_irq gt_timer_outputs[NUM_GTIMERS];
+ /* GPIO output for GICv3 maintenance interrupt signal */
+ qemu_irq gicv3_maintenance_interrupt;
/* MemoryRegion to use for secure physical accesses */
MemoryRegion *secure_memory;
/* Should CPU start in PSCI powered-off state? */
bool start_powered_off;
- /* CPU currently in PSCI powered-off state */
- bool powered_off;
+
+ /* Current power state, access guarded by BQL */
+ ARMPSCIState power_state;
+
+ /* CPU has virtualization extension */
+ bool has_el2;
/* CPU has security extension */
bool has_el3;
/* CPU has PMU (Performance Monitor Unit) */
uint32_t dcz_blocksize;
uint64_t rvbar;
+ /* Configurable aspects of GIC cpu interface (which is part of the CPU) */
+ int gic_num_lrs; /* number of list registers */
+ int gic_vpribits; /* number of virtual priority bits */
+ int gic_vprebits; /* number of virtual preemption bits */
+
+ /* Whether the cfgend input is high (i.e. this CPU should reset into
+ * big-endian mode). This setting isn't used directly: instead it modifies
+ * the reset_sctlr value to have SCTLR_B or SCTLR_EE set, depending on the
+ * architecture version.
+ */
+ bool cfgend;
+
ARMELChangeHook *el_change_hook;
void *el_change_hook_opaque;
};
return container_of(env, ARMCPU, env);
}
+uint64_t arm_cpu_mp_affinity(int idx, uint8_t clustersz);
+
#define ENV_GET_CPU(e) CPU(arm_env_get_cpu(e))
#define ENV_OFFSET offsetof(ARMCPU, env)
#define ARM_IWMMXT_wCGR2 10
#define ARM_IWMMXT_wCGR3 11
+/* V7M CCR bits */
+FIELD(V7M_CCR, NONBASETHRDENA, 0, 1)
+FIELD(V7M_CCR, USERSETMPEND, 1, 1)
+FIELD(V7M_CCR, UNALIGN_TRP, 3, 1)
+FIELD(V7M_CCR, DIV_0_TRP, 4, 1)
+FIELD(V7M_CCR, BFHFNMIGN, 8, 1)
+FIELD(V7M_CCR, STKALIGN, 9, 1)
+FIELD(V7M_CCR, DC, 16, 1)
+FIELD(V7M_CCR, IC, 17, 1)
+
+/* V7M CFSR bits for MMFSR */
+FIELD(V7M_CFSR, IACCVIOL, 0, 1)
+FIELD(V7M_CFSR, DACCVIOL, 1, 1)
+FIELD(V7M_CFSR, MUNSTKERR, 3, 1)
+FIELD(V7M_CFSR, MSTKERR, 4, 1)
+FIELD(V7M_CFSR, MLSPERR, 5, 1)
+FIELD(V7M_CFSR, MMARVALID, 7, 1)
+
+/* V7M CFSR bits for BFSR */
+FIELD(V7M_CFSR, IBUSERR, 8 + 0, 1)
+FIELD(V7M_CFSR, PRECISERR, 8 + 1, 1)
+FIELD(V7M_CFSR, IMPRECISERR, 8 + 2, 1)
+FIELD(V7M_CFSR, UNSTKERR, 8 + 3, 1)
+FIELD(V7M_CFSR, STKERR, 8 + 4, 1)
+FIELD(V7M_CFSR, LSPERR, 8 + 5, 1)
+FIELD(V7M_CFSR, BFARVALID, 8 + 7, 1)
+
+/* V7M CFSR bits for UFSR */
+FIELD(V7M_CFSR, UNDEFINSTR, 16 + 0, 1)
+FIELD(V7M_CFSR, INVSTATE, 16 + 1, 1)
+FIELD(V7M_CFSR, INVPC, 16 + 2, 1)
+FIELD(V7M_CFSR, NOCP, 16 + 3, 1)
+FIELD(V7M_CFSR, UNALIGNED, 16 + 8, 1)
+FIELD(V7M_CFSR, DIVBYZERO, 16 + 9, 1)
+
+/* V7M HFSR bits */
+FIELD(V7M_HFSR, VECTTBL, 1, 1)
+FIELD(V7M_HFSR, FORCED, 30, 1)
+FIELD(V7M_HFSR, DEBUGEVT, 31, 1)
+
+/* V7M DFSR bits */
+FIELD(V7M_DFSR, HALTED, 0, 1)
+FIELD(V7M_DFSR, BKPT, 1, 1)
+FIELD(V7M_DFSR, DWTTRAP, 2, 1)
+FIELD(V7M_DFSR, VCATCH, 3, 1)
+FIELD(V7M_DFSR, EXTERNAL, 4, 1)
+
/* 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().
uint32_t cur_el, bool secure);
/* Interface between CPU and Interrupt controller. */
+#ifndef CONFIG_USER_ONLY
+bool armv7m_nvic_can_take_pending_exception(void *opaque);
+#else
+static inline bool armv7m_nvic_can_take_pending_exception(void *opaque)
+{
+ return true;
+}
+#endif
void armv7m_nvic_set_pending(void *opaque, int irq);
-int armv7m_nvic_acknowledge_irq(void *opaque);
-void armv7m_nvic_complete_irq(void *opaque, int irq);
+void armv7m_nvic_acknowledge_irq(void *opaque);
+/**
+ * armv7m_nvic_complete_irq: complete specified interrupt or exception
+ * @opaque: the NVIC
+ * @irq: the exception number to complete
+ *
+ * Returns: -1 if the irq was not active
+ * 1 if completing this irq brought us back to base (no active irqs)
+ * 0 if there is still an irq active after this one was completed
+ * (Ignoring -1, this is the same as the RETTOBASE value before completion.)
+ */
+int armv7m_nvic_complete_irq(void *opaque, int irq);
/* Interface for defining coprocessor registers.
* Registers are defined in tables of arm_cp_reginfo structs
*/
bool write_cpustate_to_list(ARMCPU *cpu);
-/* Does the core conform to the "MicroController" profile. e.g. Cortex-M3.
- Note the M in older cores (eg. ARM7TDMI) stands for Multiply. These are
- conventional cores (ie. Application or Realtime profile). */
-
-#define IS_M(env) arm_feature(env, ARM_FEATURE_M)
-
#define ARM_CPUID_TI915T 0x54029152
#define ARM_CPUID_TI925T 0x54029252
#define ARM_TBFLAG_NS_MASK (1 << ARM_TBFLAG_NS_SHIFT)
#define ARM_TBFLAG_BE_DATA_SHIFT 20
#define ARM_TBFLAG_BE_DATA_MASK (1 << ARM_TBFLAG_BE_DATA_SHIFT)
+/* For M profile only, Handler (ie not Thread) mode */
+#define ARM_TBFLAG_HANDLER_SHIFT 21
+#define ARM_TBFLAG_HANDLER_MASK (1 << ARM_TBFLAG_HANDLER_SHIFT)
/* Bit usage when in AArch64 state */
#define ARM_TBFLAG_TBI0_SHIFT 0 /* TBI0 for EL0/1 or TBI for EL2/3 */
(((F) & ARM_TBFLAG_NS_MASK) >> ARM_TBFLAG_NS_SHIFT)
#define ARM_TBFLAG_BE_DATA(F) \
(((F) & ARM_TBFLAG_BE_DATA_MASK) >> ARM_TBFLAG_BE_DATA_SHIFT)
+#define ARM_TBFLAG_HANDLER(F) \
+ (((F) & ARM_TBFLAG_HANDLER_MASK) >> ARM_TBFLAG_HANDLER_SHIFT)
#define ARM_TBFLAG_TBI0(F) \
(((F) & ARM_TBFLAG_TBI0_MASK) >> ARM_TBFLAG_TBI0_SHIFT)
#define ARM_TBFLAG_TBI1(F) \
}
*flags |= fp_exception_el(env) << ARM_TBFLAG_FPEXC_EL_SHIFT;
+ if (env->v7m.exception != 0) {
+ *flags |= ARM_TBFLAG_HANDLER_MASK;
+ }
+
*cs_base = 0;
}