18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */ 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright (C) 2020-2022 Loongson Technology Corporation Limited 48c2ecf20Sopenharmony_ci */ 58c2ecf20Sopenharmony_ci 68c2ecf20Sopenharmony_ci#ifndef __LOONGARCH_KVM_CSR_H__ 78c2ecf20Sopenharmony_ci#define __LOONGARCH_KVM_CSR_H__ 88c2ecf20Sopenharmony_ci#include <asm/kvm_host.h> 98c2ecf20Sopenharmony_ci#include <asm/watch.h> 108c2ecf20Sopenharmony_ci#include <linux/uaccess.h> 118c2ecf20Sopenharmony_ci#include <linux/kvm_host.h> 128c2ecf20Sopenharmony_ci#include "kvmcpu.h" 138c2ecf20Sopenharmony_ci 148c2ecf20Sopenharmony_ci#define kvm_read_hw_gcsr(id) gcsr_read(id) 158c2ecf20Sopenharmony_ci#define kvm_write_hw_gcsr(csr, id, val) gcsr_write(val, id) 168c2ecf20Sopenharmony_ci 178c2ecf20Sopenharmony_ciint _kvm_getcsr(struct kvm_vcpu *vcpu, unsigned int id, u64 *v, int force); 188c2ecf20Sopenharmony_ciint _kvm_setcsr(struct kvm_vcpu *vcpu, unsigned int id, u64 *v, int force); 198c2ecf20Sopenharmony_ciunsigned long _kvm_emu_read_csr(struct kvm_vcpu *vcpu, int csrid); 208c2ecf20Sopenharmony_civoid _kvm_emu_write_csr(struct kvm_vcpu *vcpu, int csrid, unsigned long val); 218c2ecf20Sopenharmony_civoid _kvm_emu_xchg_csr(struct kvm_vcpu *vcpu, int csrid, 228c2ecf20Sopenharmony_ci unsigned long csr_mask, unsigned long val); 238c2ecf20Sopenharmony_ciint _kvm_emu_iocsr(larch_inst inst, struct kvm_run *run, struct kvm_vcpu *vcpu); 248c2ecf20Sopenharmony_ci 258c2ecf20Sopenharmony_cistatic inline void kvm_save_hw_gcsr(struct loongarch_csrs *csr, int gid) 268c2ecf20Sopenharmony_ci{ 278c2ecf20Sopenharmony_ci csr->csrs[gid] = gcsr_read(gid); 288c2ecf20Sopenharmony_ci} 298c2ecf20Sopenharmony_ci 308c2ecf20Sopenharmony_cistatic inline void kvm_restore_hw_gcsr(struct loongarch_csrs *csr, int gid) 318c2ecf20Sopenharmony_ci{ 328c2ecf20Sopenharmony_ci gcsr_write(csr->csrs[gid], gid); 338c2ecf20Sopenharmony_ci} 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_cistatic inline unsigned long kvm_read_sw_gcsr(struct loongarch_csrs *csr, int gid) 368c2ecf20Sopenharmony_ci{ 378c2ecf20Sopenharmony_ci return csr->csrs[gid]; 388c2ecf20Sopenharmony_ci} 398c2ecf20Sopenharmony_ci 408c2ecf20Sopenharmony_cistatic inline void kvm_write_sw_gcsr(struct loongarch_csrs *csr, int gid, unsigned long val) 418c2ecf20Sopenharmony_ci{ 428c2ecf20Sopenharmony_ci csr->csrs[gid] = val; 438c2ecf20Sopenharmony_ci} 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_cistatic inline void kvm_set_sw_gcsr(struct loongarch_csrs *csr, int gid, unsigned long val) 468c2ecf20Sopenharmony_ci{ 478c2ecf20Sopenharmony_ci csr->csrs[gid] |= val; 488c2ecf20Sopenharmony_ci} 498c2ecf20Sopenharmony_ci 508c2ecf20Sopenharmony_cistatic inline void kvm_change_sw_gcsr(struct loongarch_csrs *csr, int gid, unsigned mask, 518c2ecf20Sopenharmony_ci unsigned long val) 528c2ecf20Sopenharmony_ci{ 538c2ecf20Sopenharmony_ci unsigned long _mask = mask; 548c2ecf20Sopenharmony_ci csr->csrs[gid] &= ~_mask; 558c2ecf20Sopenharmony_ci csr->csrs[gid] |= val & _mask; 568c2ecf20Sopenharmony_ci} 578c2ecf20Sopenharmony_ci 588c2ecf20Sopenharmony_ci 598c2ecf20Sopenharmony_ci#define GET_HW_GCSR(id, csrid, v) \ 608c2ecf20Sopenharmony_ci do { \ 618c2ecf20Sopenharmony_ci if (csrid == id) { \ 628c2ecf20Sopenharmony_ci *v = (long)kvm_read_hw_gcsr(csrid); \ 638c2ecf20Sopenharmony_ci return 0; \ 648c2ecf20Sopenharmony_ci } \ 658c2ecf20Sopenharmony_ci } while (0) 668c2ecf20Sopenharmony_ci 678c2ecf20Sopenharmony_ci#define GET_SW_GCSR(csr, id, csrid, v) \ 688c2ecf20Sopenharmony_ci do { \ 698c2ecf20Sopenharmony_ci if (csrid == id) { \ 708c2ecf20Sopenharmony_ci *v = kvm_read_sw_gcsr(csr, id); \ 718c2ecf20Sopenharmony_ci return 0; \ 728c2ecf20Sopenharmony_ci } \ 738c2ecf20Sopenharmony_ci } while (0) 748c2ecf20Sopenharmony_ci 758c2ecf20Sopenharmony_ci#define SET_HW_GCSR(csr, id, csrid, v) \ 768c2ecf20Sopenharmony_ci do { \ 778c2ecf20Sopenharmony_ci if (csrid == id) { \ 788c2ecf20Sopenharmony_ci kvm_write_hw_gcsr(csr, csrid, *v); \ 798c2ecf20Sopenharmony_ci return 0; \ 808c2ecf20Sopenharmony_ci } \ 818c2ecf20Sopenharmony_ci } while (0) 828c2ecf20Sopenharmony_ci 838c2ecf20Sopenharmony_ci#define SET_SW_GCSR(csr, id, csrid, v) \ 848c2ecf20Sopenharmony_ci do { \ 858c2ecf20Sopenharmony_ci if (csrid == id) { \ 868c2ecf20Sopenharmony_ci kvm_write_sw_gcsr(csr, csrid, *v); \ 878c2ecf20Sopenharmony_ci return 0; \ 888c2ecf20Sopenharmony_ci } \ 898c2ecf20Sopenharmony_ci } while (0) 908c2ecf20Sopenharmony_ci 918c2ecf20Sopenharmony_ciint _kvm_init_iocsr(struct kvm *kvm); 928c2ecf20Sopenharmony_ciint _kvm_set_iocsr(struct kvm *kvm, struct kvm_iocsr_entry *__user argp); 938c2ecf20Sopenharmony_ciint _kvm_get_iocsr(struct kvm *kvm, struct kvm_iocsr_entry *__user argp); 948c2ecf20Sopenharmony_ci 958c2ecf20Sopenharmony_ci#define KVM_PMU_PLV_ENABLE (CSR_PERFCTRL_PLV0 | \ 968c2ecf20Sopenharmony_ci CSR_PERFCTRL_PLV1 | \ 978c2ecf20Sopenharmony_ci CSR_PERFCTRL_PLV2 | \ 988c2ecf20Sopenharmony_ci CSR_PERFCTRL_PLV3) 998c2ecf20Sopenharmony_ci 1008c2ecf20Sopenharmony_ci#define CASE_WRITE_HW_PMU(vcpu, csr, id, csrid, v) \ 1018c2ecf20Sopenharmony_ci do { \ 1028c2ecf20Sopenharmony_ci if (csrid == id) { \ 1038c2ecf20Sopenharmony_ci if (v & KVM_PMU_PLV_ENABLE) { \ 1048c2ecf20Sopenharmony_ci write_csr_gcfg(read_csr_gcfg() | CSR_GCFG_GPERF); \ 1058c2ecf20Sopenharmony_ci kvm_write_hw_gcsr(csr, csrid, v | CSR_PERFCTRL_GMOD); \ 1068c2ecf20Sopenharmony_ci vcpu->arch.aux_inuse |= KVM_LARCH_PERF; \ 1078c2ecf20Sopenharmony_ci return ; \ 1088c2ecf20Sopenharmony_ci } else { \ 1098c2ecf20Sopenharmony_ci kvm_write_sw_gcsr(csr, csrid, v); \ 1108c2ecf20Sopenharmony_ci return; \ 1118c2ecf20Sopenharmony_ci } \ 1128c2ecf20Sopenharmony_ci } \ 1138c2ecf20Sopenharmony_ci } while (0) 1148c2ecf20Sopenharmony_ci 1158c2ecf20Sopenharmony_ci#endif /* __LOONGARCH_KVM_CSR_H__ */ 116