/* SPDX-License-Identifier: GPL-2.0 */ /* * Copyright (C) 2020-2022 Loongson Technology Corporation Limited */ #ifndef __LOONGARCH_KVM_CSR_H__ #define __LOONGARCH_KVM_CSR_H__ #include #include #include #include #include "kvmcpu.h" #define kvm_read_hw_gcsr(id) gcsr_read(id) #define kvm_write_hw_gcsr(csr, id, val) gcsr_write(val, id) int _kvm_getcsr(struct kvm_vcpu *vcpu, unsigned int id, u64 *v, int force); int _kvm_setcsr(struct kvm_vcpu *vcpu, unsigned int id, u64 *v, int force); unsigned long _kvm_emu_read_csr(struct kvm_vcpu *vcpu, int csrid); void _kvm_emu_write_csr(struct kvm_vcpu *vcpu, int csrid, unsigned long val); void _kvm_emu_xchg_csr(struct kvm_vcpu *vcpu, int csrid, unsigned long csr_mask, unsigned long val); int _kvm_emu_iocsr(larch_inst inst, struct kvm_run *run, struct kvm_vcpu *vcpu); static inline void kvm_save_hw_gcsr(struct loongarch_csrs *csr, int gid) { csr->csrs[gid] = gcsr_read(gid); } static inline void kvm_restore_hw_gcsr(struct loongarch_csrs *csr, int gid) { gcsr_write(csr->csrs[gid], gid); } static inline unsigned long kvm_read_sw_gcsr(struct loongarch_csrs *csr, int gid) { return csr->csrs[gid]; } static inline void kvm_write_sw_gcsr(struct loongarch_csrs *csr, int gid, unsigned long val) { csr->csrs[gid] = val; } static inline void kvm_set_sw_gcsr(struct loongarch_csrs *csr, int gid, unsigned long val) { csr->csrs[gid] |= val; } static inline void kvm_change_sw_gcsr(struct loongarch_csrs *csr, int gid, unsigned mask, unsigned long val) { unsigned long _mask = mask; csr->csrs[gid] &= ~_mask; csr->csrs[gid] |= val & _mask; } #define GET_HW_GCSR(id, csrid, v) \ do { \ if (csrid == id) { \ *v = (long)kvm_read_hw_gcsr(csrid); \ return 0; \ } \ } while (0) #define GET_SW_GCSR(csr, id, csrid, v) \ do { \ if (csrid == id) { \ *v = kvm_read_sw_gcsr(csr, id); \ return 0; \ } \ } while (0) #define SET_HW_GCSR(csr, id, csrid, v) \ do { \ if (csrid == id) { \ kvm_write_hw_gcsr(csr, csrid, *v); \ return 0; \ } \ } while (0) #define SET_SW_GCSR(csr, id, csrid, v) \ do { \ if (csrid == id) { \ kvm_write_sw_gcsr(csr, csrid, *v); \ return 0; \ } \ } while (0) int _kvm_init_iocsr(struct kvm *kvm); int _kvm_set_iocsr(struct kvm *kvm, struct kvm_iocsr_entry *__user argp); int _kvm_get_iocsr(struct kvm *kvm, struct kvm_iocsr_entry *__user argp); #define KVM_PMU_PLV_ENABLE (CSR_PERFCTRL_PLV0 | \ CSR_PERFCTRL_PLV1 | \ CSR_PERFCTRL_PLV2 | \ CSR_PERFCTRL_PLV3) #define CASE_WRITE_HW_PMU(vcpu, csr, id, csrid, v) \ do { \ if (csrid == id) { \ if (v & KVM_PMU_PLV_ENABLE) { \ write_csr_gcfg(read_csr_gcfg() | CSR_GCFG_GPERF); \ kvm_write_hw_gcsr(csr, csrid, v | CSR_PERFCTRL_GMOD); \ vcpu->arch.aux_inuse |= KVM_LARCH_PERF; \ return ; \ } else { \ kvm_write_sw_gcsr(csr, csrid, v); \ return; \ } \ } \ } while (0) #endif /* __LOONGARCH_KVM_CSR_H__ */