Commit 8c260b11 authored by Anthony Liguori's avatar Anthony Liguori
Browse files

Merge remote-tracking branch 'pmaydell/target-arm.for-upstream' into staging



# By Peter Maydell
# Via Peter Maydell
* pmaydell/target-arm.for-upstream:
  target-arm: Make LPAE feature imply V7MP
  target-arm: Use tuple list to sync cp regs with KVM
  target-arm: Reinitialize all KVM VCPU registers on reset
  target-arm: Initialize cpreg list from KVM when using KVM
  target-arm: Convert TCG to using (index,value) list for cp migration
  target-arm: mark up cpregs for no-migrate or raw access
  target-arm: Add raw_readfn and raw_writefn to ARMCPRegInfo
  target-arm: Allow special cpregs to have flags set

Message-id: 1372181592-32170-1-git-send-email-peter.maydell@linaro.org
Signed-off-by: default avatarAnthony Liguori <aliguori@us.ibm.com>
parents 9e49c8c5 bdcc150d
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
obj-y += arm-semi.o
obj-$(CONFIG_SOFTMMU) += machine.o
obj-$(CONFIG_KVM) += kvm.o
obj-$(CONFIG_NO_KVM) += kvm-stub.o
obj-y += translate.o op_helper.o helper.o cpu.o
obj-y += neon_helper.o iwmmxt_helper.o
+24 −0
Original line number Diff line number Diff line
@@ -62,6 +62,29 @@ typedef struct ARMCPU {

    /* Coprocessor information */
    GHashTable *cp_regs;
    /* For marshalling (mostly coprocessor) register state between the
     * kernel and QEMU (for KVM) and between two QEMUs (for migration),
     * we use these arrays.
     */
    /* List of register indexes managed via these arrays; (full KVM style
     * 64 bit indexes, not CPRegInfo 32 bit indexes)
     */
    uint64_t *cpreg_indexes;
    /* Values of the registers (cpreg_indexes[i]'s value is cpreg_values[i]) */
    uint64_t *cpreg_values;
    /* When using KVM, keeps a copy of the initial state of the VCPU,
     * so that on reset we can feed the reset values back into the kernel.
     */
    uint64_t *cpreg_reset_values;
    /* Length of the indexes, values, reset_values arrays */
    int32_t cpreg_array_len;
    /* These are used only for migration: incoming data arrives in
     * these fields and is sanity checked in post_load before copying
     * to the working data structures above.
     */
    uint64_t *cpreg_vmstate_indexes;
    uint64_t *cpreg_vmstate_values;
    int32_t cpreg_vmstate_array_len;

    /* The instance init functions for implementation-specific subclasses
     * set these fields to specify the implementation-dependent values of
@@ -116,6 +139,7 @@ extern const struct VMStateDescription vmstate_arm_cpu;
#endif

void register_cp_regs_for_features(ARMCPU *cpu);
void init_cpreg_list(ARMCPU *cpu);

void arm_cpu_do_interrupt(CPUState *cpu);
void arm_v7m_cpu_do_interrupt(CPUState *cpu);
+3 −1
Original line number Diff line number Diff line
@@ -198,12 +198,15 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
        set_feature(env, ARM_FEATURE_VFP);
    }
    if (arm_feature(env, ARM_FEATURE_LPAE)) {
        set_feature(env, ARM_FEATURE_V7MP);
        set_feature(env, ARM_FEATURE_PXN);
    }

    register_cp_regs_for_features(cpu);
    arm_cpu_register_gdb_regs_for_features(cpu);

    init_cpreg_list(cpu);

    cpu_reset(CPU(cpu));
    qemu_init_vcpu(env);

@@ -571,7 +574,6 @@ static void cortex_a15_initfn(Object *obj)
    set_feature(&cpu->env, ARM_FEATURE_NEON);
    set_feature(&cpu->env, ARM_FEATURE_THUMB2EE);
    set_feature(&cpu->env, ARM_FEATURE_ARM_DIV);
    set_feature(&cpu->env, ARM_FEATURE_V7MP);
    set_feature(&cpu->env, ARM_FEATURE_GENERIC_TIMER);
    set_feature(&cpu->env, ARM_FEATURE_DUMMY_C15_REGS);
    set_feature(&cpu->env, ARM_FEATURE_LPAE);
+87 −2
Original line number Diff line number Diff line
@@ -424,6 +424,43 @@ void armv7m_nvic_complete_irq(void *opaque, int irq);
    (((cp) << 16) | ((is64) << 15) | ((crn) << 11) |    \
     ((crm) << 7) | ((opc1) << 3) | (opc2))

/* Note that these must line up with the KVM/ARM register
 * ID field definitions (kvm.c will check this, but we
 * can't just use the KVM defines here as the kvm headers
 * are unavailable to non-KVM-specific files)
 */
#define CP_REG_SIZE_SHIFT 52
#define CP_REG_SIZE_MASK       0x00f0000000000000ULL
#define CP_REG_SIZE_U32        0x0020000000000000ULL
#define CP_REG_SIZE_U64        0x0030000000000000ULL
#define CP_REG_ARM             0x4000000000000000ULL

/* Convert a full 64 bit KVM register ID to the truncated 32 bit
 * version used as a key for the coprocessor register hashtable
 */
static inline uint32_t kvm_to_cpreg_id(uint64_t kvmid)
{
    uint32_t cpregid = kvmid;
    if ((kvmid & CP_REG_SIZE_MASK) == CP_REG_SIZE_U64) {
        cpregid |= (1 << 15);
    }
    return cpregid;
}

/* Convert a truncated 32 bit hashtable key into the full
 * 64 bit KVM register ID.
 */
static inline uint64_t cpreg_to_kvm_id(uint32_t cpregid)
{
    uint64_t kvmid = cpregid & ~(1 << 15);
    if (cpregid & (1 << 15)) {
        kvmid |= CP_REG_SIZE_U64 | CP_REG_ARM;
    } else {
        kvmid |= CP_REG_SIZE_U32 | CP_REG_ARM;
    }
    return kvmid;
}

/* ARMCPRegInfo type field bits. If the SPECIAL bit is set this is a
 * special-behaviour cp reg and bits [15..8] indicate what behaviour
 * it has. Otherwise it is a simple cp reg, where CONST indicates that
@@ -434,19 +471,22 @@ void armv7m_nvic_complete_irq(void *opaque, int irq);
 * a register definition to override a previous definition for the
 * same (cp, is64, crn, crm, opc1, opc2) tuple: either the new or the
 * old must have the OVERRIDE bit set.
 * NO_MIGRATE indicates that this register should be ignored for migration;
 * (eg because any state is accessed via some other coprocessor register).
 */
#define ARM_CP_SPECIAL 1
#define ARM_CP_CONST 2
#define ARM_CP_64BIT 4
#define ARM_CP_SUPPRESS_TB_END 8
#define ARM_CP_OVERRIDE 16
#define ARM_CP_NO_MIGRATE 32
#define ARM_CP_NOP (ARM_CP_SPECIAL | (1 << 8))
#define ARM_CP_WFI (ARM_CP_SPECIAL | (2 << 8))
#define ARM_LAST_SPECIAL ARM_CP_WFI
/* Used only as a terminator for ARMCPRegInfo lists */
#define ARM_CP_SENTINEL 0xffff
/* Mask of only the flag bits in a type field */
#define ARM_CP_FLAG_MASK 0x1f
#define ARM_CP_FLAG_MASK 0x3f

/* Return true if cptype is a valid type field. This is used to try to
 * catch errors where the sentinel has been accidentally left off the end
@@ -456,7 +496,7 @@ static inline bool cptype_valid(int cptype)
{
    return ((cptype & ~ARM_CP_FLAG_MASK) == 0)
        || ((cptype & ARM_CP_SPECIAL) &&
            (cptype <= ARM_LAST_SPECIAL));
            ((cptype & ~ARM_CP_FLAG_MASK) <= ARM_LAST_SPECIAL));
}

/* Access rights:
@@ -562,6 +602,19 @@ struct ARMCPRegInfo {
     * by fieldoffset.
     */
    CPWriteFn *writefn;
    /* Function for doing a "raw" read; used when we need to copy
     * coprocessor state to the kernel for KVM or out for
     * migration. This only needs to be provided if there is also a
     * readfn and it makes an access permission check.
     */
    CPReadFn *raw_readfn;
    /* Function for doing a "raw" write; used when we need to copy KVM
     * kernel coprocessor state into userspace, or for inbound
     * migration. This only needs to be provided if there is also a
     * writefn and it makes an access permission check or masks out
     * "unwritable" bits or has write-one-to-clear or similar behaviour.
     */
    CPWriteFn *raw_writefn;
    /* Function for resetting the register. If NULL, then reset will be done
     * by writing resetvalue to the field specified in fieldoffset. If
     * fieldoffset is 0 then no reset will be done.
@@ -605,6 +658,38 @@ static inline bool cp_access_ok(CPUARMState *env,
    return (ri->access >> ((arm_current_pl(env) * 2) + isread)) & 1;
}

/**
 * write_list_to_cpustate
 * @cpu: ARMCPU
 *
 * For each register listed in the ARMCPU cpreg_indexes list, write
 * its value from the cpreg_values list into the ARMCPUState structure.
 * This updates TCG's working data structures from KVM data or
 * from incoming migration state.
 *
 * Returns: true if all register values were updated correctly,
 * false if some register was unknown or could not be written.
 * Note that we do not stop early on failure -- we will attempt
 * writing all registers in the list.
 */
bool write_list_to_cpustate(ARMCPU *cpu);

/**
 * write_cpustate_to_list:
 * @cpu: ARMCPU
 *
 * For each register listed in the ARMCPU cpreg_indexes list, write
 * its value from the ARMCPUState structure into the cpreg_values list.
 * This is used to copy info from TCG's working data structures into
 * KVM or for outbound migration.
 *
 * Returns: true if all register values were read correctly,
 * false if some register was unknown or could not be read.
 * Note that we do not stop early on failure -- we will attempt
 * reading all registers in the list.
 */
bool write_cpustate_to_list(ARMCPU *cpu);

/* Does the core conform to the 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).  */
+281 −46

File changed.

Preview size limit exceeded, changes collapsed.

Loading