Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0-only */
0002 /*
0003  * Copyright (C) 2012,2013 - ARM Ltd
0004  * Author: Marc Zyngier <marc.zyngier@arm.com>
0005  *
0006  * Derived from arch/arm/kvm/coproc.h
0007  * Copyright (C) 2012 - Virtual Open Systems and Columbia University
0008  * Authors: Christoffer Dall <c.dall@virtualopensystems.com>
0009  */
0010 
0011 #ifndef __ARM64_KVM_SYS_REGS_LOCAL_H__
0012 #define __ARM64_KVM_SYS_REGS_LOCAL_H__
0013 
0014 #include <linux/bsearch.h>
0015 
0016 #define reg_to_encoding(x)                      \
0017     sys_reg((u32)(x)->Op0, (u32)(x)->Op1,               \
0018         (u32)(x)->CRn, (u32)(x)->CRm, (u32)(x)->Op2)
0019 
0020 struct sys_reg_params {
0021     u8  Op0;
0022     u8  Op1;
0023     u8  CRn;
0024     u8  CRm;
0025     u8  Op2;
0026     u64 regval;
0027     bool    is_write;
0028 };
0029 
0030 #define esr_sys64_to_params(esr)                                               \
0031     ((struct sys_reg_params){ .Op0 = ((esr) >> 20) & 3,                    \
0032                   .Op1 = ((esr) >> 14) & 0x7,                  \
0033                   .CRn = ((esr) >> 10) & 0xf,                  \
0034                   .CRm = ((esr) >> 1) & 0xf,                   \
0035                   .Op2 = ((esr) >> 17) & 0x7,                  \
0036                   .is_write = !((esr) & 1) })
0037 
0038 #define esr_cp1x_32_to_params(esr)                      \
0039     ((struct sys_reg_params){ .Op1 = ((esr) >> 14) & 0x7,           \
0040                   .CRn = ((esr) >> 10) & 0xf,           \
0041                   .CRm = ((esr) >> 1) & 0xf,            \
0042                   .Op2 = ((esr) >> 17) & 0x7,           \
0043                   .is_write = !((esr) & 1) })
0044 
0045 struct sys_reg_desc {
0046     /* Sysreg string for debug */
0047     const char *name;
0048 
0049     enum {
0050         AA32_DIRECT,
0051         AA32_LO,
0052         AA32_HI,
0053     } aarch32_map;
0054 
0055     /* MRS/MSR instruction which accesses it. */
0056     u8  Op0;
0057     u8  Op1;
0058     u8  CRn;
0059     u8  CRm;
0060     u8  Op2;
0061 
0062     /* Trapped access from guest, if non-NULL. */
0063     bool (*access)(struct kvm_vcpu *,
0064                struct sys_reg_params *,
0065                const struct sys_reg_desc *);
0066 
0067     /* Initialization for vcpu. */
0068     void (*reset)(struct kvm_vcpu *, const struct sys_reg_desc *);
0069 
0070     /* Index into sys_reg[], or 0 if we don't need to save it. */
0071     int reg;
0072 
0073     /* Value (usually reset value) */
0074     u64 val;
0075 
0076     /* Custom get/set_user functions, fallback to generic if NULL */
0077     int (*get_user)(struct kvm_vcpu *vcpu, const struct sys_reg_desc *rd,
0078             u64 *val);
0079     int (*set_user)(struct kvm_vcpu *vcpu, const struct sys_reg_desc *rd,
0080             u64 val);
0081 
0082     /* Return mask of REG_* runtime visibility overrides */
0083     unsigned int (*visibility)(const struct kvm_vcpu *vcpu,
0084                    const struct sys_reg_desc *rd);
0085 };
0086 
0087 #define REG_HIDDEN      (1 << 0) /* hidden from userspace and guest */
0088 #define REG_RAZ         (1 << 1) /* RAZ from userspace and guest */
0089 
0090 static __printf(2, 3)
0091 inline void print_sys_reg_msg(const struct sys_reg_params *p,
0092                        char *fmt, ...)
0093 {
0094     va_list va;
0095 
0096     va_start(va, fmt);
0097     /* Look, we even formatted it for you to paste into the table! */
0098     kvm_pr_unimpl("%pV { Op0(%2u), Op1(%2u), CRn(%2u), CRm(%2u), Op2(%2u), func_%s },\n",
0099               &(struct va_format){ fmt, &va },
0100               p->Op0, p->Op1, p->CRn, p->CRm, p->Op2, p->is_write ? "write" : "read");
0101     va_end(va);
0102 }
0103 
0104 static inline void print_sys_reg_instr(const struct sys_reg_params *p)
0105 {
0106     /* GCC warns on an empty format string */
0107     print_sys_reg_msg(p, "%s", "");
0108 }
0109 
0110 static inline bool ignore_write(struct kvm_vcpu *vcpu,
0111                 const struct sys_reg_params *p)
0112 {
0113     return true;
0114 }
0115 
0116 static inline bool read_zero(struct kvm_vcpu *vcpu,
0117                  struct sys_reg_params *p)
0118 {
0119     p->regval = 0;
0120     return true;
0121 }
0122 
0123 /* Reset functions */
0124 static inline void reset_unknown(struct kvm_vcpu *vcpu,
0125                  const struct sys_reg_desc *r)
0126 {
0127     BUG_ON(!r->reg);
0128     BUG_ON(r->reg >= NR_SYS_REGS);
0129     __vcpu_sys_reg(vcpu, r->reg) = 0x1de7ec7edbadc0deULL;
0130 }
0131 
0132 static inline void reset_val(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r)
0133 {
0134     BUG_ON(!r->reg);
0135     BUG_ON(r->reg >= NR_SYS_REGS);
0136     __vcpu_sys_reg(vcpu, r->reg) = r->val;
0137 }
0138 
0139 static inline bool sysreg_hidden(const struct kvm_vcpu *vcpu,
0140                  const struct sys_reg_desc *r)
0141 {
0142     if (likely(!r->visibility))
0143         return false;
0144 
0145     return r->visibility(vcpu, r) & REG_HIDDEN;
0146 }
0147 
0148 static inline bool sysreg_visible_as_raz(const struct kvm_vcpu *vcpu,
0149                      const struct sys_reg_desc *r)
0150 {
0151     if (likely(!r->visibility))
0152         return false;
0153 
0154     return r->visibility(vcpu, r) & REG_RAZ;
0155 }
0156 
0157 static inline int cmp_sys_reg(const struct sys_reg_desc *i1,
0158                   const struct sys_reg_desc *i2)
0159 {
0160     BUG_ON(i1 == i2);
0161     if (!i1)
0162         return 1;
0163     else if (!i2)
0164         return -1;
0165     if (i1->Op0 != i2->Op0)
0166         return i1->Op0 - i2->Op0;
0167     if (i1->Op1 != i2->Op1)
0168         return i1->Op1 - i2->Op1;
0169     if (i1->CRn != i2->CRn)
0170         return i1->CRn - i2->CRn;
0171     if (i1->CRm != i2->CRm)
0172         return i1->CRm - i2->CRm;
0173     return i1->Op2 - i2->Op2;
0174 }
0175 
0176 static inline int match_sys_reg(const void *key, const void *elt)
0177 {
0178     const unsigned long pval = (unsigned long)key;
0179     const struct sys_reg_desc *r = elt;
0180 
0181     return pval - reg_to_encoding(r);
0182 }
0183 
0184 static inline const struct sys_reg_desc *
0185 find_reg(const struct sys_reg_params *params, const struct sys_reg_desc table[],
0186      unsigned int num)
0187 {
0188     unsigned long pval = reg_to_encoding(params);
0189 
0190     return __inline_bsearch((void *)pval, table, num, sizeof(table[0]), match_sys_reg);
0191 }
0192 
0193 const struct sys_reg_desc *get_reg_by_id(u64 id,
0194                      const struct sys_reg_desc table[],
0195                      unsigned int num);
0196 
0197 int kvm_arm_sys_reg_get_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *);
0198 int kvm_arm_sys_reg_set_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *);
0199 int kvm_sys_reg_get_user(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg,
0200              const struct sys_reg_desc table[], unsigned int num);
0201 int kvm_sys_reg_set_user(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg,
0202              const struct sys_reg_desc table[], unsigned int num);
0203 
0204 #define AA32(_x)    .aarch32_map = AA32_##_x
0205 #define Op0(_x)     .Op0 = _x
0206 #define Op1(_x)     .Op1 = _x
0207 #define CRn(_x)     .CRn = _x
0208 #define CRm(_x)     .CRm = _x
0209 #define Op2(_x)     .Op2 = _x
0210 
0211 #define SYS_DESC(reg)                   \
0212     .name = #reg,                   \
0213     Op0(sys_reg_Op0(reg)), Op1(sys_reg_Op1(reg)),   \
0214     CRn(sys_reg_CRn(reg)), CRm(sys_reg_CRm(reg)),   \
0215     Op2(sys_reg_Op2(reg))
0216 
0217 #endif /* __ARM64_KVM_SYS_REGS_LOCAL_H__ */