On Mon, Oct 26, 2015 at 12:46 AM, Pavel Fedin <p.fe...@samsung.com> 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 <p.fe...@samsung.com> > --- > 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 > > >