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        u8      Rt;
  32        bool    is_write;
  33};
  34
  35struct sys_reg_desc {
  36        /* MRS/MSR instruction which accesses it. */
  37        u8      Op0;
  38        u8      Op1;
  39        u8      CRn;
  40        u8      CRm;
  41        u8      Op2;
  42
  43        /* Trapped access from guest, if non-NULL. */
  44        bool (*access)(struct kvm_vcpu *,
  45                       const struct sys_reg_params *,
  46                       const struct sys_reg_desc *);
  47
  48        /* Initialization for vcpu. */
  49        void (*reset)(struct kvm_vcpu *, const struct sys_reg_desc *);
  50
  51        /* Index into sys_reg[], or 0 if we don't need to save it. */
  52        int reg;
  53
  54        /* Value (usually reset value) */
  55        u64 val;
  56};
  57
  58static inline void print_sys_reg_instr(const struct sys_reg_params *p)
  59{
  60        /* Look, we even formatted it for you to paste into the table! */
  61        kvm_pr_unimpl(" { Op0(%2u), Op1(%2u), CRn(%2u), CRm(%2u), Op2(%2u), func_%s },\n",
  62                      p->Op0, p->Op1, p->CRn, p->CRm, p->Op2, p->is_write ? "write" : "read");
  63}
  64
  65static inline bool ignore_write(struct kvm_vcpu *vcpu,
  66                                const struct sys_reg_params *p)
  67{
  68        return true;
  69}
  70
  71static inline bool read_zero(struct kvm_vcpu *vcpu,
  72                             const struct sys_reg_params *p)
  73{
  74        *vcpu_reg(vcpu, p->Rt) = 0;
  75        return true;
  76}
  77
  78static inline bool write_to_read_only(struct kvm_vcpu *vcpu,
  79                                      const struct sys_reg_params *params)
  80{
  81        kvm_debug("sys_reg write to read-only register at: %lx\n",
  82                  *vcpu_pc(vcpu));
  83        print_sys_reg_instr(params);
  84        return false;
  85}
  86
  87static inline bool read_from_write_only(struct kvm_vcpu *vcpu,
  88                                        const struct sys_reg_params *params)
  89{
  90        kvm_debug("sys_reg read to write-only register at: %lx\n",
  91                  *vcpu_pc(vcpu));
  92        print_sys_reg_instr(params);
  93        return false;
  94}
  95
  96/* Reset functions */
  97static inline void reset_unknown(struct kvm_vcpu *vcpu,
  98                                 const struct sys_reg_desc *r)
  99{
 100        BUG_ON(!r->reg);
 101        BUG_ON(r->reg >= NR_SYS_REGS);
 102        vcpu_sys_reg(vcpu, r->reg) = 0x1de7ec7edbadc0deULL;
 103}
 104
 105static inline void reset_val(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r)
 106{
 107        BUG_ON(!r->reg);
 108        BUG_ON(r->reg >= NR_SYS_REGS);
 109        vcpu_sys_reg(vcpu, r->reg) = r->val;
 110}
 111
 112static inline int cmp_sys_reg(const struct sys_reg_desc *i1,
 113                              const struct sys_reg_desc *i2)
 114{
 115        BUG_ON(i1 == i2);
 116        if (!i1)
 117                return 1;
 118        else if (!i2)
 119                return -1;
 120        if (i1->Op0 != i2->Op0)
 121                return i1->Op0 - i2->Op0;
 122        if (i1->Op1 != i2->Op1)
 123                return i1->Op1 - i2->Op1;
 124        if (i1->CRn != i2->CRn)
 125                return i1->CRn - i2->CRn;
 126        if (i1->CRm != i2->CRm)
 127                return i1->CRm - i2->CRm;
 128        return i1->Op2 - i2->Op2;
 129}
 130
 131
 132#define Op0(_x)         .Op0 = _x
 133#define Op1(_x)         .Op1 = _x
 134#define CRn(_x)         .CRn = _x
 135#define CRm(_x)         .CRm = _x
 136#define Op2(_x)         .Op2 = _x
 137
 138#endif /* __ARM64_KVM_SYS_REGS_LOCAL_H__ */
 139