linux/arch/arm64/kvm/sys_regs.h
<<
>>
Prefs
   1/*
   2 * Copyright (C) 2012,2013 - ARM Ltd
   3 * Author: Marc Zyngier <marc.zyngier@arm.com>
   4 *
   5 * Derived from arch/arm/kvm/coproc.h
   6 * Copyright (C) 2012 - Virtual Open Systems and Columbia University
   7 * Authors: Christoffer Dall <c.dall@virtualopensystems.com>
   8 *
   9 * This program is free software; you can redistribute it and/or modify
  10 * it under the terms of the GNU General Public License, version 2, as
  11 * published by the Free Software Foundation.
  12 *
  13 * This program is distributed in the hope that it will be useful,
  14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16 * GNU General Public License for more details.
  17 *
  18 * You should have received a copy of the GNU General Public License
  19 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  20 */
  21
  22#ifndef __ARM64_KVM_SYS_REGS_LOCAL_H__
  23#define __ARM64_KVM_SYS_REGS_LOCAL_H__
  24
  25struct sys_reg_params {
  26        u8      Op0;
  27        u8      Op1;
  28        u8      CRn;
  29        u8      CRm;
  30        u8      Op2;
  31        u64     regval;
  32        bool    is_write;
  33        bool    is_aarch32;
  34        bool    is_32bit;       /* Only valid if is_aarch32 is true */
  35};
  36
  37struct sys_reg_desc {
  38        /* MRS/MSR instruction which accesses it. */
  39        u8      Op0;
  40        u8      Op1;
  41        u8      CRn;
  42        u8      CRm;
  43        u8      Op2;
  44
  45        /* Trapped access from guest, if non-NULL. */
  46        bool (*access)(struct kvm_vcpu *,
  47                       struct sys_reg_params *,
  48                       const struct sys_reg_desc *);
  49
  50        /* Initialization for vcpu. */
  51        void (*reset)(struct kvm_vcpu *, const struct sys_reg_desc *);
  52
  53        /* Index into sys_reg[], or 0 if we don't need to save it. */
  54        int reg;
  55
  56        /* Value (usually reset value) */
  57        u64 val;
  58
  59        /* Custom get/set_user functions, fallback to generic if NULL */
  60        int (*get_user)(struct kvm_vcpu *vcpu, const struct sys_reg_desc *rd,
  61                        const struct kvm_one_reg *reg, void __user *uaddr);
  62        int (*set_user)(struct kvm_vcpu *vcpu, const struct sys_reg_desc *rd,
  63                        const struct kvm_one_reg *reg, void __user *uaddr);
  64};
  65
  66static inline void print_sys_reg_instr(const struct sys_reg_params *p)
  67{
  68        /* Look, we even formatted it for you to paste into the table! */
  69        kvm_pr_unimpl(" { Op0(%2u), Op1(%2u), CRn(%2u), CRm(%2u), Op2(%2u), func_%s },\n",
  70                      p->Op0, p->Op1, p->CRn, p->CRm, p->Op2, p->is_write ? "write" : "read");
  71}
  72
  73static inline bool ignore_write(struct kvm_vcpu *vcpu,
  74                                const struct sys_reg_params *p)
  75{
  76        return true;
  77}
  78
  79static inline bool read_zero(struct kvm_vcpu *vcpu,
  80                             struct sys_reg_params *p)
  81{
  82        p->regval = 0;
  83        return true;
  84}
  85
  86/* Reset functions */
  87static inline void reset_unknown(struct kvm_vcpu *vcpu,
  88                                 const struct sys_reg_desc *r)
  89{
  90        BUG_ON(!r->reg);
  91        BUG_ON(r->reg >= NR_SYS_REGS);
  92        __vcpu_sys_reg(vcpu, r->reg) = 0x1de7ec7edbadc0deULL;
  93}
  94
  95static inline void reset_val(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r)
  96{
  97        BUG_ON(!r->reg);
  98        BUG_ON(r->reg >= NR_SYS_REGS);
  99        __vcpu_sys_reg(vcpu, r->reg) = r->val;
 100}
 101
 102static inline int cmp_sys_reg(const struct sys_reg_desc *i1,
 103                              const struct sys_reg_desc *i2)
 104{
 105        BUG_ON(i1 == i2);
 106        if (!i1)
 107                return 1;
 108        else if (!i2)
 109                return -1;
 110        if (i1->Op0 != i2->Op0)
 111                return i1->Op0 - i2->Op0;
 112        if (i1->Op1 != i2->Op1)
 113                return i1->Op1 - i2->Op1;
 114        if (i1->CRn != i2->CRn)
 115                return i1->CRn - i2->CRn;
 116        if (i1->CRm != i2->CRm)
 117                return i1->CRm - i2->CRm;
 118        return i1->Op2 - i2->Op2;
 119}
 120
 121const struct sys_reg_desc *find_reg_by_id(u64 id,
 122                                          struct sys_reg_params *params,
 123                                          const struct sys_reg_desc table[],
 124                                          unsigned int num);
 125
 126#define Op0(_x)         .Op0 = _x
 127#define Op1(_x)         .Op1 = _x
 128#define CRn(_x)         .CRn = _x
 129#define CRm(_x)         .CRm = _x
 130#define Op2(_x)         .Op2 = _x
 131
 132#define SYS_DESC(reg)                                   \
 133        Op0(sys_reg_Op0(reg)), Op1(sys_reg_Op1(reg)),   \
 134        CRn(sys_reg_CRn(reg)), CRm(sys_reg_CRm(reg)),   \
 135        Op2(sys_reg_Op2(reg))
 136
 137#endif /* __ARM64_KVM_SYS_REGS_LOCAL_H__ */
 138