1 // SPDX-License-Identifier: GPL-2.0 1 2 /* 3 * Copyright (C) 2021 Western Digital Corporat 4 * 5 * Authors: 6 * Atish Patra <atish.patra@wdc.com> 7 * Anup Patel <anup.patel@wdc.com> 8 */ 9 10 #include <linux/errno.h> 11 #include <linux/err.h> 12 #include <linux/kvm_host.h> 13 #include <linux/uaccess.h> 14 #include <asm/cpufeature.h> 15 16 #ifdef CONFIG_FPU 17 void kvm_riscv_vcpu_fp_reset(struct kvm_vcpu * 18 { 19 struct kvm_cpu_context *cntx = &vcpu-> 20 21 cntx->sstatus &= ~SR_FS; 22 if (riscv_isa_extension_available(vcpu 23 riscv_isa_extension_available(vcpu 24 cntx->sstatus |= SR_FS_INITIAL 25 else 26 cntx->sstatus |= SR_FS_OFF; 27 } 28 29 static void kvm_riscv_vcpu_fp_clean(struct kvm 30 { 31 cntx->sstatus &= ~SR_FS; 32 cntx->sstatus |= SR_FS_CLEAN; 33 } 34 35 void kvm_riscv_vcpu_guest_fp_save(struct kvm_c 36 const unsign 37 { 38 if ((cntx->sstatus & SR_FS) == SR_FS_D 39 if (riscv_isa_extension_availa 40 __kvm_riscv_fp_d_save( 41 else if (riscv_isa_extension_a 42 __kvm_riscv_fp_f_save( 43 kvm_riscv_vcpu_fp_clean(cntx); 44 } 45 } 46 47 void kvm_riscv_vcpu_guest_fp_restore(struct kv 48 const uns 49 { 50 if ((cntx->sstatus & SR_FS) != SR_FS_O 51 if (riscv_isa_extension_availa 52 __kvm_riscv_fp_d_resto 53 else if (riscv_isa_extension_a 54 __kvm_riscv_fp_f_resto 55 kvm_riscv_vcpu_fp_clean(cntx); 56 } 57 } 58 59 void kvm_riscv_vcpu_host_fp_save(struct kvm_cp 60 { 61 /* No need to check host sstatus as it 62 if (riscv_isa_extension_available(NULL 63 __kvm_riscv_fp_d_save(cntx); 64 else if (riscv_isa_extension_available 65 __kvm_riscv_fp_f_save(cntx); 66 } 67 68 void kvm_riscv_vcpu_host_fp_restore(struct kvm 69 { 70 if (riscv_isa_extension_available(NULL 71 __kvm_riscv_fp_d_restore(cntx) 72 else if (riscv_isa_extension_available 73 __kvm_riscv_fp_f_restore(cntx) 74 } 75 #endif 76 77 int kvm_riscv_vcpu_get_reg_fp(struct kvm_vcpu 78 const struct kvm 79 unsigned long rt 80 { 81 struct kvm_cpu_context *cntx = &vcpu-> 82 unsigned long __user *uaddr = 83 (unsigned long __user 84 unsigned long reg_num = reg->id & ~(KV 85 KV 86 rt 87 void *reg_val; 88 89 if ((rtype == KVM_REG_RISCV_FP_F) && 90 riscv_isa_extension_available(vcpu 91 if (KVM_REG_SIZE(reg->id) != s 92 return -EINVAL; 93 if (reg_num == KVM_REG_RISCV_F 94 reg_val = &cntx->fp.f. 95 else if ((KVM_REG_RISCV_FP_F_R 96 reg_num <= KVM_REG_R 97 reg_val = &cntx->fp.f. 98 else 99 return -ENOENT; 100 } else if ((rtype == KVM_REG_RISCV_FP_ 101 riscv_isa_extension_availab 102 if (reg_num == KVM_REG_RISCV_F 103 if (KVM_REG_SIZE(reg-> 104 return -EINVAL 105 reg_val = &cntx->fp.d. 106 } else if ((KVM_REG_RISCV_FP_D 107 reg_num <= KVM_REG_ 108 if (KVM_REG_SIZE(reg-> 109 return -EINVAL 110 reg_val = &cntx->fp.d. 111 } else 112 return -ENOENT; 113 } else 114 return -ENOENT; 115 116 if (copy_to_user(uaddr, reg_val, KVM_R 117 return -EFAULT; 118 119 return 0; 120 } 121 122 int kvm_riscv_vcpu_set_reg_fp(struct kvm_vcpu 123 const struct kvm 124 unsigned long rt 125 { 126 struct kvm_cpu_context *cntx = &vcpu-> 127 unsigned long __user *uaddr = 128 (unsigned long __user 129 unsigned long reg_num = reg->id & ~(KV 130 KV 131 rt 132 void *reg_val; 133 134 if ((rtype == KVM_REG_RISCV_FP_F) && 135 riscv_isa_extension_available(vcpu 136 if (KVM_REG_SIZE(reg->id) != s 137 return -EINVAL; 138 if (reg_num == KVM_REG_RISCV_F 139 reg_val = &cntx->fp.f. 140 else if ((KVM_REG_RISCV_FP_F_R 141 reg_num <= KVM_REG_R 142 reg_val = &cntx->fp.f. 143 else 144 return -ENOENT; 145 } else if ((rtype == KVM_REG_RISCV_FP_ 146 riscv_isa_extension_availab 147 if (reg_num == KVM_REG_RISCV_F 148 if (KVM_REG_SIZE(reg-> 149 return -EINVAL 150 reg_val = &cntx->fp.d. 151 } else if ((KVM_REG_RISCV_FP_D 152 reg_num <= KVM_REG_ 153 if (KVM_REG_SIZE(reg-> 154 return -EINVAL 155 reg_val = &cntx->fp.d. 156 } else 157 return -ENOENT; 158 } else 159 return -ENOENT; 160 161 if (copy_from_user(reg_val, uaddr, KVM 162 return -EFAULT; 163 164 return 0; 165 } 166
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.