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