[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
>
>
>
- [Qemu-devel] [PATCH v2] target-arm: Extract some external ARM CPU API, Pavel Fedin, 2015/10/26
- Re: [Qemu-devel] [PATCH v2] target-arm: Extract some external ARM CPU API,
Peter Crosthwaite <=
- Re: [Qemu-devel] [PATCH v2] target-arm: Extract some external ARM CPU API, Pavel Fedin, 2015/10/27
- Re: [Qemu-devel] [PATCH v2] target-arm: Extract some external ARM CPU API, Peter Maydell, 2015/10/27
- Re: [Qemu-devel] [PATCH v2] target-arm: Extract some external ARM CPU API, Pavel Fedin, 2015/10/27
- Re: [Qemu-devel] [PATCH v2] target-arm: Extract some external ARM CPU API, Peter Crosthwaite, 2015/10/27
- Re: [Qemu-devel] [PATCH v2] target-arm: Extract some external ARM CPU API, Pavel Fedin, 2015/10/28
- Re: [Qemu-devel] [PATCH v2] target-arm: Extract some external ARM CPU API, Pavel Fedin, 2015/10/28
- Re: [Qemu-devel] [PATCH v2] target-arm: Extract some external ARM CPU API, Shlomo Pongratz, 2015/10/28
Re: [Qemu-devel] [PATCH v2] target-arm: Extract some external ARM CPU API, Pavel Fedin, 2015/10/27