1 /* SPDX-License-Identifier: GPL-2.0-only */
3 * Copyright (C) 2012,2013 - ARM Ltd
4 * Author: Marc Zyngier <marc.zyngier@arm.com>
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>
11 #ifndef __ARM64_KVM_SYS_REGS_LOCAL_H__
12 #define __ARM64_KVM_SYS_REGS_LOCAL_H__
14 #include <linux/bsearch.h>
16 #define reg_to_encoding(x) \
17 sys_reg((u32)(x)->Op0, (u32)(x)->Op1, \
18 (u32)(x)->CRn, (u32)(x)->CRm, (u32)(x)->Op2)
20 struct sys_reg_params
{
30 #define encoding_to_params(reg) \
31 ((struct sys_reg_params){ .Op0 = sys_reg_Op0(reg), \
32 .Op1 = sys_reg_Op1(reg), \
33 .CRn = sys_reg_CRn(reg), \
34 .CRm = sys_reg_CRm(reg), \
35 .Op2 = sys_reg_Op2(reg) })
37 #define esr_sys64_to_params(esr) \
38 ((struct sys_reg_params){ .Op0 = ((esr) >> 20) & 3, \
39 .Op1 = ((esr) >> 14) & 0x7, \
40 .CRn = ((esr) >> 10) & 0xf, \
41 .CRm = ((esr) >> 1) & 0xf, \
42 .Op2 = ((esr) >> 17) & 0x7, \
43 .is_write = !((esr) & 1) })
45 #define esr_cp1x_32_to_params(esr) \
46 ((struct sys_reg_params){ .Op1 = ((esr) >> 14) & 0x7, \
47 .CRn = ((esr) >> 10) & 0xf, \
48 .CRm = ((esr) >> 1) & 0xf, \
49 .Op2 = ((esr) >> 17) & 0x7, \
50 .is_write = !((esr) & 1) })
53 /* Sysreg string for debug */
62 /* MRS/MSR instruction which accesses it. */
69 /* Trapped access from guest, if non-NULL. */
70 bool (*access
)(struct kvm_vcpu
*,
71 struct sys_reg_params
*,
72 const struct sys_reg_desc
*);
75 * Initialization for vcpu. Return initialized value, or KVM
76 * sanitized value for ID registers.
78 u64 (*reset
)(struct kvm_vcpu
*, const struct sys_reg_desc
*);
80 /* Index into sys_reg[], or 0 if we don't need to save it. */
83 /* Value (usually reset value), or write mask for idregs */
86 /* Custom get/set_user functions, fallback to generic if NULL */
87 int (*get_user
)(struct kvm_vcpu
*vcpu
, const struct sys_reg_desc
*rd
,
89 int (*set_user
)(struct kvm_vcpu
*vcpu
, const struct sys_reg_desc
*rd
,
92 /* Return mask of REG_* runtime visibility overrides */
93 unsigned int (*visibility
)(const struct kvm_vcpu
*vcpu
,
94 const struct sys_reg_desc
*rd
);
97 #define REG_HIDDEN (1 << 0) /* hidden from userspace and guest */
98 #define REG_RAZ (1 << 1) /* RAZ from userspace and guest */
99 #define REG_USER_WI (1 << 2) /* WI from userspace only */
101 static __printf(2, 3)
102 inline void print_sys_reg_msg(const struct sys_reg_params
*p
,
108 /* Look, we even formatted it for you to paste into the table! */
109 kvm_pr_unimpl("%pV { Op0(%2u), Op1(%2u), CRn(%2u), CRm(%2u), Op2(%2u), func_%s },\n",
110 &(struct va_format
){ fmt
, &va
},
111 p
->Op0
, p
->Op1
, p
->CRn
, p
->CRm
, p
->Op2
, p
->is_write
? "write" : "read");
115 static inline void print_sys_reg_instr(const struct sys_reg_params
*p
)
117 /* GCC warns on an empty format string */
118 print_sys_reg_msg(p
, "%s", "");
121 static inline bool ignore_write(struct kvm_vcpu
*vcpu
,
122 const struct sys_reg_params
*p
)
127 static inline bool read_zero(struct kvm_vcpu
*vcpu
,
128 struct sys_reg_params
*p
)
134 /* Reset functions */
135 static inline u64
reset_unknown(struct kvm_vcpu
*vcpu
,
136 const struct sys_reg_desc
*r
)
139 BUG_ON(r
->reg
>= NR_SYS_REGS
);
140 __vcpu_sys_reg(vcpu
, r
->reg
) = 0x1de7ec7edbadc0deULL
;
141 return __vcpu_sys_reg(vcpu
, r
->reg
);
144 static inline u64
reset_val(struct kvm_vcpu
*vcpu
, const struct sys_reg_desc
*r
)
147 BUG_ON(r
->reg
>= NR_SYS_REGS
);
148 __vcpu_sys_reg(vcpu
, r
->reg
) = r
->val
;
149 return __vcpu_sys_reg(vcpu
, r
->reg
);
152 static inline unsigned int sysreg_visibility(const struct kvm_vcpu
*vcpu
,
153 const struct sys_reg_desc
*r
)
155 if (likely(!r
->visibility
))
158 return r
->visibility(vcpu
, r
);
161 static inline bool sysreg_hidden(const struct kvm_vcpu
*vcpu
,
162 const struct sys_reg_desc
*r
)
164 return sysreg_visibility(vcpu
, r
) & REG_HIDDEN
;
167 static inline bool sysreg_visible_as_raz(const struct kvm_vcpu
*vcpu
,
168 const struct sys_reg_desc
*r
)
170 return sysreg_visibility(vcpu
, r
) & REG_RAZ
;
173 static inline bool sysreg_user_write_ignore(const struct kvm_vcpu
*vcpu
,
174 const struct sys_reg_desc
*r
)
176 return sysreg_visibility(vcpu
, r
) & REG_USER_WI
;
179 static inline int cmp_sys_reg(const struct sys_reg_desc
*i1
,
180 const struct sys_reg_desc
*i2
)
187 if (i1
->Op0
!= i2
->Op0
)
188 return i1
->Op0
- i2
->Op0
;
189 if (i1
->Op1
!= i2
->Op1
)
190 return i1
->Op1
- i2
->Op1
;
191 if (i1
->CRn
!= i2
->CRn
)
192 return i1
->CRn
- i2
->CRn
;
193 if (i1
->CRm
!= i2
->CRm
)
194 return i1
->CRm
- i2
->CRm
;
195 return i1
->Op2
- i2
->Op2
;
198 static inline int match_sys_reg(const void *key
, const void *elt
)
200 const unsigned long pval
= (unsigned long)key
;
201 const struct sys_reg_desc
*r
= elt
;
203 return pval
- reg_to_encoding(r
);
206 static inline const struct sys_reg_desc
*
207 find_reg(const struct sys_reg_params
*params
, const struct sys_reg_desc table
[],
210 unsigned long pval
= reg_to_encoding(params
);
212 return __inline_bsearch((void *)pval
, table
, num
, sizeof(table
[0]), match_sys_reg
);
215 const struct sys_reg_desc
*get_reg_by_id(u64 id
,
216 const struct sys_reg_desc table
[],
219 int kvm_arm_sys_reg_get_reg(struct kvm_vcpu
*vcpu
, const struct kvm_one_reg
*);
220 int kvm_arm_sys_reg_set_reg(struct kvm_vcpu
*vcpu
, const struct kvm_one_reg
*);
221 int kvm_sys_reg_get_user(struct kvm_vcpu
*vcpu
, const struct kvm_one_reg
*reg
,
222 const struct sys_reg_desc table
[], unsigned int num
);
223 int kvm_sys_reg_set_user(struct kvm_vcpu
*vcpu
, const struct kvm_one_reg
*reg
,
224 const struct sys_reg_desc table
[], unsigned int num
);
226 bool triage_sysreg_trap(struct kvm_vcpu
*vcpu
, int *sr_index
);
228 int kvm_finalize_sys_regs(struct kvm_vcpu
*vcpu
);
230 #define AA32(_x) .aarch32_map = AA32_##_x
231 #define Op0(_x) .Op0 = _x
232 #define Op1(_x) .Op1 = _x
233 #define CRn(_x) .CRn = _x
234 #define CRm(_x) .CRm = _x
235 #define Op2(_x) .Op2 = _x
237 #define SYS_DESC(reg) \
239 Op0(sys_reg_Op0(reg)), Op1(sys_reg_Op1(reg)), \
240 CRn(sys_reg_CRn(reg)), CRm(sys_reg_CRm(reg)), \
241 Op2(sys_reg_Op2(reg))
243 #define CP15_SYS_DESC(reg) \
245 .aarch32_map = AA32_DIRECT, \
246 Op0(0), Op1(sys_reg_Op1(reg)), \
247 CRn(sys_reg_CRn(reg)), CRm(sys_reg_CRm(reg)), \
248 Op2(sys_reg_Op2(reg))
250 #endif /* __ARM64_KVM_SYS_REGS_LOCAL_H__ */