qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Qemu-devel] [PATCH v2] target-arm: Extract some external ARM CPU AP


From: Peter Crosthwaite
Subject: Re: [Qemu-devel] [PATCH v2] target-arm: Extract some external ARM CPU API
Date: Mon, 26 Oct 2015 09:39:05 -0700

On Mon, Oct 26, 2015 at 12:46 AM, Pavel Fedin <address@hidden> wrote:
> Includes, which reside in target-arm, are very problematic to use from code
> which is considered target-independent by the build system (for example,
> hw/intc/something.c). It happens because they depend on config-target.h,
> which is unreachable in this case. This creates problems for example for
> GICv3 implementation, which needs to call define_arm_cp_regs_with_opaque()
> in order to add system registers to the processor model, as well as play
> with affinity IDs.
>
> This patch solves the problem by extracting some self-sufficient
> definitions into public area (include/hw/cpu).
>

So this conflicts with multi-arch, which takes the approach of leaving
the includes in target-* and instead modifying them there in a way
that lets you include cpu.h from device land to get a minimal with
this kind of stuff.

We have plenty of precedent in tree for interrupt controllers being
compiled as arch-specific for reasons such as this. Can we just
promote GIC to an obj-y (much the same way the KVM GIC or V7MNVIC are
promoted)? You should them have access to cpu.h and the CP interface.

> Signed-off-by: Pavel Fedin <address@hidden>
> ---
> v1 => v2:
> - mp-affinity property addition left out, now a pure code move
> - Move some more useful definitions (REGINFO_SENTINEL) and NOP accessors.
> ---
>  include/hw/cpu/arm.h | 308 
> +++++++++++++++++++++++++++++++++++++++++++++++++++

I think this would be hw/arm/cpu.h

Regards,
Peter

>  target-arm/cpu-qom.h |  40 +------
>  target-arm/cpu.h     | 239 +--------------------------------------
>  3 files changed, 311 insertions(+), 276 deletions(-)
>  create mode 100644 include/hw/cpu/arm.h
>
> diff --git a/include/hw/cpu/arm.h b/include/hw/cpu/arm.h
> new file mode 100644
> index 0000000..de7bec7
> --- /dev/null
> +++ b/include/hw/cpu/arm.h
> @@ -0,0 +1,308 @@
> +/*
> + * QEMU ARM CPU
> + *
> + * Copyright (c) 2003 Fabrice Bellard
> + * Copyright (c) 2012 SUSE LINUX Products GmbH
> + * Copyright (c) 2015 Samsung Electronics Co. Ltd.
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License
> + * as published by the Free Software Foundation; either version 2
> + * of the License, or (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, see
> + * <http://www.gnu.org/licenses/gpl-2.0.html>
> + */
> +
> +#ifndef HW_CPU_ARM_H
> +#define HW_CPU_ARM_H
> +
> +#include "qom/cpu.h"
> +
> +#define TYPE_ARM_CPU "arm-cpu"
> +
> +#define ARM_CPU_CLASS(klass) \
> +    OBJECT_CLASS_CHECK(ARMCPUClass, (klass), TYPE_ARM_CPU)
> +#define ARM_CPU(obj) \
> +    OBJECT_CHECK(ARMCPU, (obj), TYPE_ARM_CPU)
> +#define ARM_CPU_GET_CLASS(obj) \
> +    OBJECT_GET_CLASS(ARMCPUClass, (obj), TYPE_ARM_CPU)
> +
> +/**
> + * ARMCPUClass:
> + * @parent_realize: The parent class' realize handler.
> + * @parent_reset: The parent class' reset handler.
> + *
> + * An ARM CPU model.
> + */
> +typedef struct ARMCPUClass {
> +    /*< private >*/
> +    CPUClass parent_class;
> +    /*< public >*/
> +
> +    DeviceRealize parent_realize;
> +    void (*parent_reset)(CPUState *cpu);
> +} ARMCPUClass;
> +
> +/* These two are black boxes for us */
> +typedef struct ARMCPU ARMCPU;
> +typedef struct CPUARMState CPUARMState;
> +
> +/* 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
> + * TCG can assume the value to be constant (ie load at translate time)
> + * and 64BIT indicates a 64 bit wide coprocessor register. SUPPRESS_TB_END
> + * indicates that the TB should not be ended after a write to this register
> + * (the default is that the TB ends after cp writes). OVERRIDE permits
> + * 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.
> + * ALIAS indicates that this register is an alias view of some underlying
> + * state which is also visible via another register, and that the other
> + * register is handling migration and reset; registers marked ALIAS will not 
> be
> + * migrated but may have their state set by syncing of register state from 
> KVM.
> + * NO_RAW indicates that this register has no underlying state and does not
> + * support raw access for state saving/loading; it will not be used for 
> either
> + * migration or KVM state synchronization. (Typically this is for "registers"
> + * which are actually used as instructions for cache maintenance and so on.)
> + * IO indicates that this register does I/O and therefore its accesses
> + * need to be surrounded by gen_io_start()/gen_io_end(). In particular,
> + * registers which implement clocks or timers require this.
> + */
> +#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_ALIAS 32
> +#define ARM_CP_IO 64
> +#define ARM_CP_NO_RAW 128
> +#define ARM_CP_NOP (ARM_CP_SPECIAL | (1 << 8))
> +#define ARM_CP_WFI (ARM_CP_SPECIAL | (2 << 8))
> +#define ARM_CP_NZCV (ARM_CP_SPECIAL | (3 << 8))
> +#define ARM_CP_CURRENTEL (ARM_CP_SPECIAL | (4 << 8))
> +#define ARM_CP_DC_ZVA (ARM_CP_SPECIAL | (5 << 8))
> +#define ARM_LAST_SPECIAL ARM_CP_DC_ZVA
> +/* 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 0xff
> +
> +/* Valid values for ARMCPRegInfo state field, indicating which of
> + * the AArch32 and AArch64 execution states this register is visible in.
> + * If the reginfo doesn't explicitly specify then it is AArch32 only.
> + * If the reginfo is declared to be visible in both states then a second
> + * reginfo is synthesised for the AArch32 view of the AArch64 register,
> + * such that the AArch32 view is the lower 32 bits of the AArch64 one.
> + * Note that we rely on the values of these enums as we iterate through
> + * the various states in some places.
> + */
> +enum {
> +    ARM_CP_STATE_AA32 = 0,
> +    ARM_CP_STATE_AA64 = 1,
> +    ARM_CP_STATE_BOTH = 2,
> +};
> +
> +/* ARM CP register secure state flags.  These flags identify security state
> + * attributes for a given CP register entry.
> + * The existence of both or neither secure and non-secure flags indicates 
> that
> + * the register has both a secure and non-secure hash entry.  A single one of
> + * these flags causes the register to only be hashed for the specified
> + * security state.
> + * Although definitions may have any combination of the S/NS bits, each
> + * registered entry will only have one to identify whether the entry is 
> secure
> + * or non-secure.
> + */
> +enum {
> +    ARM_CP_SECSTATE_S =   (1 << 0), /* bit[0]: Secure state register */
> +    ARM_CP_SECSTATE_NS =  (1 << 1), /* bit[1]: Non-secure state register */
> +};
> +
> +typedef struct ARMCPRegInfo ARMCPRegInfo;
> +
> +typedef enum CPAccessResult {
> +    /* Access is permitted */
> +    CP_ACCESS_OK = 0,
> +    /* Access fails due to a configurable trap or enable which would
> +     * result in a categorized exception syndrome giving information about
> +     * the failing instruction (ie syndrome category 0x3, 0x4, 0x5, 0x6,
> +     * 0xc or 0x18). The exception is taken to the usual target EL (EL1 or
> +     * PL1 if in EL0, otherwise to the current EL).
> +     */
> +    CP_ACCESS_TRAP = 1,
> +    /* Access fails and results in an exception syndrome 0x0 
> ("uncategorized").
> +     * Note that this is not a catch-all case -- the set of cases which may
> +     * result in this failure is specifically defined by the architecture.
> +     */
> +    CP_ACCESS_TRAP_UNCATEGORIZED = 2,
> +    /* As CP_ACCESS_TRAP, but for traps directly to EL2 or EL3 */
> +    CP_ACCESS_TRAP_EL2 = 3,
> +    CP_ACCESS_TRAP_EL3 = 4,
> +    /* As CP_ACCESS_UNCATEGORIZED, but for traps directly to EL2 or EL3 */
> +    CP_ACCESS_TRAP_UNCATEGORIZED_EL2 = 5,
> +    CP_ACCESS_TRAP_UNCATEGORIZED_EL3 = 6,
> +} CPAccessResult;
> +
> +/* Access functions for coprocessor registers. These cannot fail and
> + * may not raise exceptions.
> + */
> +typedef uint64_t CPReadFn(CPUARMState *env, const ARMCPRegInfo *opaque);
> +typedef void CPWriteFn(CPUARMState *env, const ARMCPRegInfo *opaque,
> +                       uint64_t value);
> +/* Access permission check functions for coprocessor registers. */
> +typedef CPAccessResult CPAccessFn(CPUARMState *env, const ARMCPRegInfo 
> *opaque);
> +/* Hook function for register reset */
> +typedef void CPResetFn(CPUARMState *env, const ARMCPRegInfo *opaque);
> +
> +#define CP_ANY 0xff
> +
> +/* Definition of an ARM coprocessor register */
> +struct ARMCPRegInfo {
> +    /* Name of register (useful mainly for debugging, need not be unique) */
> +    const char *name;
> +    /* Location of register: coprocessor number and (crn,crm,opc1,opc2)
> +     * tuple. Any of crm, opc1 and opc2 may be CP_ANY to indicate a
> +     * 'wildcard' field -- any value of that field in the MRC/MCR insn
> +     * will be decoded to this register. The register read and write
> +     * callbacks will be passed an ARMCPRegInfo with the crn/crm/opc1/opc2
> +     * used by the program, so it is possible to register a wildcard and
> +     * then behave differently on read/write if necessary.
> +     * For 64 bit registers, only crm and opc1 are relevant; crn and opc2
> +     * must both be zero.
> +     * For AArch64-visible registers, opc0 is also used.
> +     * Since there are no "coprocessors" in AArch64, cp is purely used as a
> +     * way to distinguish (for KVM's benefit) guest-visible system registers
> +     * from demuxed ones provided to preserve the "no side effects on
> +     * KVM register read/write from QEMU" semantics. cp==0x13 is guest
> +     * visible (to match KVM's encoding); cp==0 will be converted to
> +     * cp==0x13 when the ARMCPRegInfo is registered, for convenience.
> +     */
> +    uint8_t cp;
> +    uint8_t crn;
> +    uint8_t crm;
> +    uint8_t opc0;
> +    uint8_t opc1;
> +    uint8_t opc2;
> +    /* Execution state in which this register is visible: ARM_CP_STATE_* */
> +    int state;
> +    /* Register type: ARM_CP_* bits/values */
> +    int type;
> +    /* Access rights: PL*_[RW] */
> +    int access;
> +    /* Security state: ARM_CP_SECSTATE_* bits/values */
> +    int secure;
> +    /* The opaque pointer passed to define_arm_cp_regs_with_opaque() when
> +     * this register was defined: can be used to hand data through to the
> +     * register read/write functions, since they are passed the 
> ARMCPRegInfo*.
> +     */
> +    void *opaque;
> +    /* Value of this register, if it is ARM_CP_CONST. Otherwise, if
> +     * fieldoffset is non-zero, the reset value of the register.
> +     */
> +    uint64_t resetvalue;
> +    /* Offset of the field in CPUARMState for this register.
> +     *
> +     * This is not needed if either:
> +     *  1. type is ARM_CP_CONST or one of the ARM_CP_SPECIALs
> +     *  2. both readfn and writefn are specified
> +     */
> +    ptrdiff_t fieldoffset; /* offsetof(CPUARMState, field) */
> +
> +    /* Offsets of the secure and non-secure fields in CPUARMState for the
> +     * register if it is banked.  These fields are only used during the 
> static
> +     * registration of a register.  During hashing the bank associated
> +     * with a given security state is copied to fieldoffset which is used 
> from
> +     * there on out.
> +     *
> +     * It is expected that register definitions use either fieldoffset or
> +     * bank_fieldoffsets in the definition but not both.  It is also expected
> +     * that both bank offsets are set when defining a banked register.  This
> +     * use indicates that a register is banked.
> +     */
> +    ptrdiff_t bank_fieldoffsets[2];
> +
> +    /* Function for making any access checks for this register in addition to
> +     * those specified by the 'access' permissions bits. If NULL, no extra
> +     * checks required. The access check is performed at runtime, not at
> +     * translate time.
> +     */
> +    CPAccessFn *accessfn;
> +    /* Function for handling reads of this register. If NULL, then reads
> +     * will be done by loading from the offset into CPUARMState specified
> +     * by fieldoffset.
> +     */
> +    CPReadFn *readfn;
> +    /* Function for handling writes of this register. If NULL, then writes
> +     * will be done by writing to the offset into CPUARMState specified
> +     * 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 has side effects (for instance clear-on-read bits).
> +     */
> +    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 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.
> +     */
> +    CPResetFn *resetfn;
> +};
> +
> +#define REGINFO_SENTINEL { .type = ARM_CP_SENTINEL }
> +
> +void define_arm_cp_regs_with_opaque(ARMCPU *cpu,
> +                                    const ARMCPRegInfo *regs, void *opaque);
> +void define_one_arm_cp_reg_with_opaque(ARMCPU *cpu,
> +                                       const ARMCPRegInfo *regs, void 
> *opaque);
> +static inline void define_arm_cp_regs(ARMCPU *cpu, const ARMCPRegInfo *regs)
> +{
> +    define_arm_cp_regs_with_opaque(cpu, regs, NULL);
> +}
> +static inline void define_one_arm_cp_reg(ARMCPU *cpu, const ARMCPRegInfo 
> *regs)
> +{
> +    define_one_arm_cp_reg_with_opaque(cpu, regs, NULL);
> +}
> +
> +/* CPWriteFn that can be used to implement writes-ignored behaviour */
> +void arm_cp_write_ignore(CPUARMState *env, const ARMCPRegInfo *ri,
> +                         uint64_t value);
> +/* CPReadFn that can be used for read-as-zero behaviour */
> +uint64_t arm_cp_read_zero(CPUARMState *env, const ARMCPRegInfo *ri);
> +
> +/* CPResetFn that does nothing, for use if no reset is required even
> + * if fieldoffset is non zero.
> + */
> +void arm_cp_reset_ignore(CPUARMState *env, const ARMCPRegInfo *opaque);
> +
> +/* Affinity ID composition */
> +
> +#define ARM_AFF0_SHIFT 0
> +#define ARM_AFF0_MASK  (0xFFULL << ARM_AFF0_SHIFT)
> +#define ARM_AFF1_SHIFT 8
> +#define ARM_AFF1_MASK  (0xFFULL << ARM_AFF1_SHIFT)
> +#define ARM_AFF2_SHIFT 16
> +#define ARM_AFF2_MASK  (0xFFULL << ARM_AFF2_SHIFT)
> +#define ARM_AFF3_SHIFT 32
> +#define ARM_AFF3_MASK  (0xFFULL << ARM_AFF3_SHIFT)
> +
> +#define ARM32_AFFINITY_MASK (ARM_AFF0_MASK|ARM_AFF1_MASK|ARM_AFF2_MASK)
> +#define ARM64_AFFINITY_MASK \
> +    (ARM_AFF0_MASK|ARM_AFF1_MASK|ARM_AFF2_MASK|ARM_AFF3_MASK)
> +
> +#endif
> diff --git a/target-arm/cpu-qom.h b/target-arm/cpu-qom.h
> index 25fb1ce..38e0b94 100644
> --- a/target-arm/cpu-qom.h
> +++ b/target-arm/cpu-qom.h
> @@ -20,32 +20,7 @@
>  #ifndef QEMU_ARM_CPU_QOM_H
>  #define QEMU_ARM_CPU_QOM_H
>
> -#include "qom/cpu.h"
> -
> -#define TYPE_ARM_CPU "arm-cpu"
> -
> -#define ARM_CPU_CLASS(klass) \
> -    OBJECT_CLASS_CHECK(ARMCPUClass, (klass), TYPE_ARM_CPU)
> -#define ARM_CPU(obj) \
> -    OBJECT_CHECK(ARMCPU, (obj), TYPE_ARM_CPU)
> -#define ARM_CPU_GET_CLASS(obj) \
> -    OBJECT_GET_CLASS(ARMCPUClass, (obj), TYPE_ARM_CPU)
> -
> -/**
> - * ARMCPUClass:
> - * @parent_realize: The parent class' realize handler.
> - * @parent_reset: The parent class' reset handler.
> - *
> - * An ARM CPU model.
> - */
> -typedef struct ARMCPUClass {
> -    /*< private >*/
> -    CPUClass parent_class;
> -    /*< public >*/
> -
> -    DeviceRealize parent_realize;
> -    void (*parent_reset)(CPUState *cpu);
> -} ARMCPUClass;
> +#include "hw/cpu/arm.h"
>
>  /**
>   * ARMCPU:
> @@ -227,19 +202,6 @@ void arm_gt_vtimer_cb(void *opaque);
>  void arm_gt_htimer_cb(void *opaque);
>  void arm_gt_stimer_cb(void *opaque);
>
> -#define ARM_AFF0_SHIFT 0
> -#define ARM_AFF0_MASK  (0xFFULL << ARM_AFF0_SHIFT)
> -#define ARM_AFF1_SHIFT 8
> -#define ARM_AFF1_MASK  (0xFFULL << ARM_AFF1_SHIFT)
> -#define ARM_AFF2_SHIFT 16
> -#define ARM_AFF2_MASK  (0xFFULL << ARM_AFF2_SHIFT)
> -#define ARM_AFF3_SHIFT 32
> -#define ARM_AFF3_MASK  (0xFFULL << ARM_AFF3_SHIFT)
> -
> -#define ARM32_AFFINITY_MASK (ARM_AFF0_MASK|ARM_AFF1_MASK|ARM_AFF2_MASK)
> -#define ARM64_AFFINITY_MASK \
> -    (ARM_AFF0_MASK|ARM_AFF1_MASK|ARM_AFF2_MASK|ARM_AFF3_MASK)
> -
>  #ifdef TARGET_AARCH64
>  int aarch64_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg);
>  int aarch64_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
> diff --git a/target-arm/cpu.h b/target-arm/cpu.h
> index 35339aa..bef2322 100644
> --- a/target-arm/cpu.h
> +++ b/target-arm/cpu.h
> @@ -123,7 +123,7 @@ typedef struct {
>      uint32_t base_mask;
>  } TCR;
>
> -typedef struct CPUARMState {
> +struct CPUARMState {
>      /* Regs for current mode.  */
>      uint32_t regs[16];
>
> @@ -507,7 +507,7 @@ typedef struct CPUARMState {
>       */
>      DeviceState *irqchip;
>      const struct arm_boot_info *boot_info;
> -} CPUARMState;
> +};
>
>  #include "cpu-qom.h"
>
> @@ -1138,77 +1138,6 @@ static inline uint64_t cpreg_to_kvm_id(uint32_t 
> cpregid)
>      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
> - * TCG can assume the value to be constant (ie load at translate time)
> - * and 64BIT indicates a 64 bit wide coprocessor register. SUPPRESS_TB_END
> - * indicates that the TB should not be ended after a write to this register
> - * (the default is that the TB ends after cp writes). OVERRIDE permits
> - * 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.
> - * ALIAS indicates that this register is an alias view of some underlying
> - * state which is also visible via another register, and that the other
> - * register is handling migration and reset; registers marked ALIAS will not 
> be
> - * migrated but may have their state set by syncing of register state from 
> KVM.
> - * NO_RAW indicates that this register has no underlying state and does not
> - * support raw access for state saving/loading; it will not be used for 
> either
> - * migration or KVM state synchronization. (Typically this is for "registers"
> - * which are actually used as instructions for cache maintenance and so on.)
> - * IO indicates that this register does I/O and therefore its accesses
> - * need to be surrounded by gen_io_start()/gen_io_end(). In particular,
> - * registers which implement clocks or timers require this.
> - */
> -#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_ALIAS 32
> -#define ARM_CP_IO 64
> -#define ARM_CP_NO_RAW 128
> -#define ARM_CP_NOP (ARM_CP_SPECIAL | (1 << 8))
> -#define ARM_CP_WFI (ARM_CP_SPECIAL | (2 << 8))
> -#define ARM_CP_NZCV (ARM_CP_SPECIAL | (3 << 8))
> -#define ARM_CP_CURRENTEL (ARM_CP_SPECIAL | (4 << 8))
> -#define ARM_CP_DC_ZVA (ARM_CP_SPECIAL | (5 << 8))
> -#define ARM_LAST_SPECIAL ARM_CP_DC_ZVA
> -/* 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 0xff
> -
> -/* Valid values for ARMCPRegInfo state field, indicating which of
> - * the AArch32 and AArch64 execution states this register is visible in.
> - * If the reginfo doesn't explicitly specify then it is AArch32 only.
> - * If the reginfo is declared to be visible in both states then a second
> - * reginfo is synthesised for the AArch32 view of the AArch64 register,
> - * such that the AArch32 view is the lower 32 bits of the AArch64 one.
> - * Note that we rely on the values of these enums as we iterate through
> - * the various states in some places.
> - */
> -enum {
> -    ARM_CP_STATE_AA32 = 0,
> -    ARM_CP_STATE_AA64 = 1,
> -    ARM_CP_STATE_BOTH = 2,
> -};
> -
> -/* ARM CP register secure state flags.  These flags identify security state
> - * attributes for a given CP register entry.
> - * The existence of both or neither secure and non-secure flags indicates 
> that
> - * the register has both a secure and non-secure hash entry.  A single one of
> - * these flags causes the register to only be hashed for the specified
> - * security state.
> - * Although definitions may have any combination of the S/NS bits, each
> - * registered entry will only have one to identify whether the entry is 
> secure
> - * or non-secure.
> - */
> -enum {
> -    ARM_CP_SECSTATE_S =   (1 << 0), /* bit[0]: Secure state register */
> -    ARM_CP_SECSTATE_NS =  (1 << 1), /* bit[1]: Non-secure state register */
> -};
> -
>  /* 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
>   * of a list of registers.
> @@ -1283,145 +1212,6 @@ static inline int arm_current_el(CPUARMState *env)
>      }
>  }
>
> -typedef struct ARMCPRegInfo ARMCPRegInfo;
> -
> -typedef enum CPAccessResult {
> -    /* Access is permitted */
> -    CP_ACCESS_OK = 0,
> -    /* Access fails due to a configurable trap or enable which would
> -     * result in a categorized exception syndrome giving information about
> -     * the failing instruction (ie syndrome category 0x3, 0x4, 0x5, 0x6,
> -     * 0xc or 0x18). The exception is taken to the usual target EL (EL1 or
> -     * PL1 if in EL0, otherwise to the current EL).
> -     */
> -    CP_ACCESS_TRAP = 1,
> -    /* Access fails and results in an exception syndrome 0x0 
> ("uncategorized").
> -     * Note that this is not a catch-all case -- the set of cases which may
> -     * result in this failure is specifically defined by the architecture.
> -     */
> -    CP_ACCESS_TRAP_UNCATEGORIZED = 2,
> -    /* As CP_ACCESS_TRAP, but for traps directly to EL2 or EL3 */
> -    CP_ACCESS_TRAP_EL2 = 3,
> -    CP_ACCESS_TRAP_EL3 = 4,
> -    /* As CP_ACCESS_UNCATEGORIZED, but for traps directly to EL2 or EL3 */
> -    CP_ACCESS_TRAP_UNCATEGORIZED_EL2 = 5,
> -    CP_ACCESS_TRAP_UNCATEGORIZED_EL3 = 6,
> -} CPAccessResult;
> -
> -/* Access functions for coprocessor registers. These cannot fail and
> - * may not raise exceptions.
> - */
> -typedef uint64_t CPReadFn(CPUARMState *env, const ARMCPRegInfo *opaque);
> -typedef void CPWriteFn(CPUARMState *env, const ARMCPRegInfo *opaque,
> -                       uint64_t value);
> -/* Access permission check functions for coprocessor registers. */
> -typedef CPAccessResult CPAccessFn(CPUARMState *env, const ARMCPRegInfo 
> *opaque);
> -/* Hook function for register reset */
> -typedef void CPResetFn(CPUARMState *env, const ARMCPRegInfo *opaque);
> -
> -#define CP_ANY 0xff
> -
> -/* Definition of an ARM coprocessor register */
> -struct ARMCPRegInfo {
> -    /* Name of register (useful mainly for debugging, need not be unique) */
> -    const char *name;
> -    /* Location of register: coprocessor number and (crn,crm,opc1,opc2)
> -     * tuple. Any of crm, opc1 and opc2 may be CP_ANY to indicate a
> -     * 'wildcard' field -- any value of that field in the MRC/MCR insn
> -     * will be decoded to this register. The register read and write
> -     * callbacks will be passed an ARMCPRegInfo with the crn/crm/opc1/opc2
> -     * used by the program, so it is possible to register a wildcard and
> -     * then behave differently on read/write if necessary.
> -     * For 64 bit registers, only crm and opc1 are relevant; crn and opc2
> -     * must both be zero.
> -     * For AArch64-visible registers, opc0 is also used.
> -     * Since there are no "coprocessors" in AArch64, cp is purely used as a
> -     * way to distinguish (for KVM's benefit) guest-visible system registers
> -     * from demuxed ones provided to preserve the "no side effects on
> -     * KVM register read/write from QEMU" semantics. cp==0x13 is guest
> -     * visible (to match KVM's encoding); cp==0 will be converted to
> -     * cp==0x13 when the ARMCPRegInfo is registered, for convenience.
> -     */
> -    uint8_t cp;
> -    uint8_t crn;
> -    uint8_t crm;
> -    uint8_t opc0;
> -    uint8_t opc1;
> -    uint8_t opc2;
> -    /* Execution state in which this register is visible: ARM_CP_STATE_* */
> -    int state;
> -    /* Register type: ARM_CP_* bits/values */
> -    int type;
> -    /* Access rights: PL*_[RW] */
> -    int access;
> -    /* Security state: ARM_CP_SECSTATE_* bits/values */
> -    int secure;
> -    /* The opaque pointer passed to define_arm_cp_regs_with_opaque() when
> -     * this register was defined: can be used to hand data through to the
> -     * register read/write functions, since they are passed the 
> ARMCPRegInfo*.
> -     */
> -    void *opaque;
> -    /* Value of this register, if it is ARM_CP_CONST. Otherwise, if
> -     * fieldoffset is non-zero, the reset value of the register.
> -     */
> -    uint64_t resetvalue;
> -    /* Offset of the field in CPUARMState for this register.
> -     *
> -     * This is not needed if either:
> -     *  1. type is ARM_CP_CONST or one of the ARM_CP_SPECIALs
> -     *  2. both readfn and writefn are specified
> -     */
> -    ptrdiff_t fieldoffset; /* offsetof(CPUARMState, field) */
> -
> -    /* Offsets of the secure and non-secure fields in CPUARMState for the
> -     * register if it is banked.  These fields are only used during the 
> static
> -     * registration of a register.  During hashing the bank associated
> -     * with a given security state is copied to fieldoffset which is used 
> from
> -     * there on out.
> -     *
> -     * It is expected that register definitions use either fieldoffset or
> -     * bank_fieldoffsets in the definition but not both.  It is also expected
> -     * that both bank offsets are set when defining a banked register.  This
> -     * use indicates that a register is banked.
> -     */
> -    ptrdiff_t bank_fieldoffsets[2];
> -
> -    /* Function for making any access checks for this register in addition to
> -     * those specified by the 'access' permissions bits. If NULL, no extra
> -     * checks required. The access check is performed at runtime, not at
> -     * translate time.
> -     */
> -    CPAccessFn *accessfn;
> -    /* Function for handling reads of this register. If NULL, then reads
> -     * will be done by loading from the offset into CPUARMState specified
> -     * by fieldoffset.
> -     */
> -    CPReadFn *readfn;
> -    /* Function for handling writes of this register. If NULL, then writes
> -     * will be done by writing to the offset into CPUARMState specified
> -     * 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 has side effects (for instance clear-on-read bits).
> -     */
> -    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 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.
> -     */
> -    CPResetFn *resetfn;
> -};
> -
>  /* Macros which are lvalues for the field in CPUARMState for the
>   * ARMCPRegInfo *ri.
>   */
> @@ -1430,33 +1220,8 @@ struct ARMCPRegInfo {
>  #define CPREG_FIELD64(env, ri) \
>      (*(uint64_t *)((char *)(env) + (ri)->fieldoffset))
>
> -#define REGINFO_SENTINEL { .type = ARM_CP_SENTINEL }
> -
> -void define_arm_cp_regs_with_opaque(ARMCPU *cpu,
> -                                    const ARMCPRegInfo *regs, void *opaque);
> -void define_one_arm_cp_reg_with_opaque(ARMCPU *cpu,
> -                                       const ARMCPRegInfo *regs, void 
> *opaque);
> -static inline void define_arm_cp_regs(ARMCPU *cpu, const ARMCPRegInfo *regs)
> -{
> -    define_arm_cp_regs_with_opaque(cpu, regs, 0);
> -}
> -static inline void define_one_arm_cp_reg(ARMCPU *cpu, const ARMCPRegInfo 
> *regs)
> -{
> -    define_one_arm_cp_reg_with_opaque(cpu, regs, 0);
> -}
>  const ARMCPRegInfo *get_arm_cp_reginfo(GHashTable *cpregs, uint32_t 
> encoded_cp);
>
> -/* CPWriteFn that can be used to implement writes-ignored behaviour */
> -void arm_cp_write_ignore(CPUARMState *env, const ARMCPRegInfo *ri,
> -                         uint64_t value);
> -/* CPReadFn that can be used for read-as-zero behaviour */
> -uint64_t arm_cp_read_zero(CPUARMState *env, const ARMCPRegInfo *ri);
> -
> -/* CPResetFn that does nothing, for use if no reset is required even
> - * if fieldoffset is non zero.
> - */
> -void arm_cp_reset_ignore(CPUARMState *env, const ARMCPRegInfo *opaque);
> -
>  /* Return true if this reginfo struct's field in the cpu state struct
>   * is 64 bits wide.
>   */
> --
> 1.9.5.msysgit.0
>
>
>



reply via email to

[Prev in Thread] Current Thread [Next in Thread]