linux/arch/arm64/kvm/sys_regs.h
<<
>>
Prefs
   1/* SPDX-License-Identifier: GPL-2.0-only */
   2/*
   3 * Copyright (C) 2012,2013 - ARM Ltd
   4 * Author: Marc Zyngier <marc.zyngier@arm.com>
   5 *
   6 * Derived from arch/arm/kvm/coproc.h
   7 * Copyright (C) 2012 - Virtual Open Systems and Columbia University
   8 * Authors: Christoffer Dall <c.dall@virtualopensystems.com>
   9 */
  10
  11#ifndef __ARM64_KVM_SYS_REGS_LOCAL_H__
  12#define __ARM64_KVM_SYS_REGS_LOCAL_H__
  13
  14struct sys_reg_params {
  15        u8      Op0;
  16        u8      Op1;
  17        u8      CRn;
  18        u8      CRm;
  19        u8      Op2;
  20        u64     regval;
  21        bool    is_write;
  22        bool    is_aarch32;
  23        bool    is_32bit;       /* Only valid if is_aarch32 is true */
  24};
  25
  26struct sys_reg_desc {
  27        /* Sysreg string for debug */
  28        const char *name;
  29
  30        /* MRS/MSR instruction which accesses it. */
  31        u8      Op0;
  32        u8      Op1;
  33        u8      CRn;
  34        u8      CRm;
  35        u8      Op2;
  36
  37        /* Trapped access from guest, if non-NULL. */
  38        bool (*access)(struct kvm_vcpu *,
  39                       struct sys_reg_params *,
  40                       const struct sys_reg_desc *);
  41
  42        /* Initialization for vcpu. */
  43        void (*reset)(struct kvm_vcpu *, const struct sys_reg_desc *);
  44
  45        /* Index into sys_reg[], or 0 if we don't need to save it. */
  46        int reg;
  47
  48        /* Value (usually reset value) */
  49        u64 val;
  50
  51        /* Custom get/set_user functions, fallback to generic if NULL */
  52        int (*get_user)(struct kvm_vcpu *vcpu, const struct sys_reg_desc *rd,
  53                        const struct kvm_one_reg *reg, void __user *uaddr);
  54        int (*set_user)(struct kvm_vcpu *vcpu, const struct sys_reg_desc *rd,
  55                        const struct kvm_one_reg *reg, void __user *uaddr);
  56
  57        /* Return mask of REG_* runtime visibility overrides */
  58        unsigned int (*visibility)(const struct kvm_vcpu *vcpu,
  59                                   const struct sys_reg_desc *rd);
  60};
  61
  62#define REG_HIDDEN_USER         (1 << 0) /* hidden from userspace ioctls */
  63#define REG_HIDDEN_GUEST        (1 << 1) /* hidden from guest */
  64
  65static inline void print_sys_reg_instr(const struct sys_reg_params *p)
  66{
  67        /* Look, we even formatted it for you to paste into the table! */
  68        kvm_pr_unimpl(" { Op0(%2u), Op1(%2u), CRn(%2u), CRm(%2u), Op2(%2u), func_%s },\n",
  69                      p->Op0, p->Op1, p->CRn, p->CRm, p->Op2, p->is_write ? "write" : "read");
  70}
  71
  72static inline bool ignore_write(struct kvm_vcpu *vcpu,
  73                                const struct sys_reg_params *p)
  74{
  75        return true;
  76}
  77
  78static inline bool read_zero(struct kvm_vcpu *vcpu,
  79                             struct sys_reg_params *p)
  80{
  81        p->regval = 0;
  82        return true;
  83}
  84
  85/* Reset functions */
  86static inline void reset_unknown(struct kvm_vcpu *vcpu,
  87                                 const struct sys_reg_desc *r)
  88{
  89        BUG_ON(!r->reg);
  90        BUG_ON(r->reg >= NR_SYS_REGS);
  91        __vcpu_sys_reg(vcpu, r->reg) = 0x1de7ec7edbadc0deULL;
  92}
  93
  94static inline void reset_val(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r)
  95{
  96        BUG_ON(!r->reg);
  97        BUG_ON(r->reg >= NR_SYS_REGS);
  98        __vcpu_sys_reg(vcpu, r->reg) = r->val;
  99}
 100
 101static inline bool sysreg_hidden_from_guest(const struct kvm_vcpu *vcpu,
 102                                            const struct sys_reg_desc *r)
 103{
 104        if (likely(!r->visibility))
 105                return false;
 106
 107        return r->visibility(vcpu, r) & REG_HIDDEN_GUEST;
 108}
 109
 110static inline bool sysreg_hidden_from_user(const struct kvm_vcpu *vcpu,
 111                                           const struct sys_reg_desc *r)
 112{
 113        if (likely(!r->visibility))
 114                return false;
 115
 116        return r->visibility(vcpu, r) & REG_HIDDEN_USER;
 117}
 118
 119static inline int cmp_sys_reg(const struct sys_reg_desc *i1,
 120                              const struct sys_reg_desc *i2)
 121{
 122        BUG_ON(i1 == i2);
 123        if (!i1)
 124                return 1;
 125        else if (!i2)
 126                return -1;
 127        if (i1->Op0 != i2->Op0)
 128                return i1->Op0 - i2->Op0;
 129        if (i1->Op1 != i2->Op1)
 130                return i1->Op1 - i2->Op1;
 131        if (i1->CRn != i2->CRn)
 132                return i1->CRn - i2->CRn;
 133        if (i1->CRm != i2->CRm)
 134                return i1->CRm - i2->CRm;
 135        return i1->Op2 - i2->Op2;
 136}
 137
 138const struct sys_reg_desc *find_reg_by_id(u64 id,
 139                                          struct sys_reg_params *params,
 140                                          const struct sys_reg_desc table[],
 141                                          unsigned int num);
 142
 143#define Op0(_x)         .Op0 = _x
 144#define Op1(_x)         .Op1 = _x
 145#define CRn(_x)         .CRn = _x
 146#define CRm(_x)         .CRm = _x
 147#define Op2(_x)         .Op2 = _x
 148
 149#define SYS_DESC(reg)                                   \
 150        .name = #reg,                                   \
 151        Op0(sys_reg_Op0(reg)), Op1(sys_reg_Op1(reg)),   \
 152        CRn(sys_reg_CRn(reg)), CRm(sys_reg_CRm(reg)),   \
 153        Op2(sys_reg_Op2(reg))
 154
 155#endif /* __ARM64_KVM_SYS_REGS_LOCAL_H__ */
 156