0001
0002
0003
0004
0005
0006
0007
0008
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
0047 const char *name;
0048
0049 enum {
0050 AA32_DIRECT,
0051 AA32_LO,
0052 AA32_HI,
0053 } aarch32_map;
0054
0055
0056 u8 Op0;
0057 u8 Op1;
0058 u8 CRn;
0059 u8 CRm;
0060 u8 Op2;
0061
0062
0063 bool (*access)(struct kvm_vcpu *,
0064 struct sys_reg_params *,
0065 const struct sys_reg_desc *);
0066
0067
0068 void (*reset)(struct kvm_vcpu *, const struct sys_reg_desc *);
0069
0070
0071 int reg;
0072
0073
0074 u64 val;
0075
0076
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
0083 unsigned int (*visibility)(const struct kvm_vcpu *vcpu,
0084 const struct sys_reg_desc *rd);
0085 };
0086
0087 #define REG_HIDDEN (1 << 0)
0088 #define REG_RAZ (1 << 1)
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
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
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
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