Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

RISC-V: KVM: Implement KVM_GET_ONE_REG/KVM_SET_ONE_REG ioctls

For KVM RISC-V, we use KVM_GET_ONE_REG/KVM_SET_ONE_REG ioctls to access
VCPU config and registers from user-space.

We have three types of VCPU registers:
1. CONFIG - these are VCPU config and capabilities
2. CORE - these are VCPU general purpose registers
3. CSR - these are VCPU control and status registers

The CONFIG register available to user-space is ISA. The ISA register is
a read and write register where user-space can only write the desired
VCPU ISA capabilities before running the VCPU.

The CORE registers available to user-space are PC, RA, SP, GP, TP, A0-A7,
T0-T6, S0-S11 and MODE. Most of these are RISC-V general registers except
PC and MODE. The PC register represents program counter whereas the MODE
register represent VCPU privilege mode (i.e. S/U-mode).

The CSRs available to user-space are SSTATUS, SIE, STVEC, SSCRATCH, SEPC,
SCAUSE, STVAL, SIP, and SATP. All of these are read/write registers.

In future, more VCPU register types will be added (such as FP) for the
KVM_GET_ONE_REG/KVM_SET_ONE_REG ioctls.

Signed-off-by: Anup Patel <anup.patel@wdc.com>
Acked-by: Paolo Bonzini <pbonzini@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Acked-by: Palmer Dabbelt <palmerdabbelt@google.com>

authored by

Anup Patel and committed by
Anup Patel
92ad8200 cce69aff

+290 -4
+52 -1
arch/riscv/include/uapi/asm/kvm.h
··· 41 41 struct kvm_sync_regs { 42 42 }; 43 43 44 - /* dummy definition */ 44 + /* for KVM_GET_SREGS and KVM_SET_SREGS */ 45 45 struct kvm_sregs { 46 46 }; 47 + 48 + /* CONFIG registers for KVM_GET_ONE_REG and KVM_SET_ONE_REG */ 49 + struct kvm_riscv_config { 50 + unsigned long isa; 51 + }; 52 + 53 + /* CORE registers for KVM_GET_ONE_REG and KVM_SET_ONE_REG */ 54 + struct kvm_riscv_core { 55 + struct user_regs_struct regs; 56 + unsigned long mode; 57 + }; 58 + 59 + /* Possible privilege modes for kvm_riscv_core */ 60 + #define KVM_RISCV_MODE_S 1 61 + #define KVM_RISCV_MODE_U 0 62 + 63 + /* CSR registers for KVM_GET_ONE_REG and KVM_SET_ONE_REG */ 64 + struct kvm_riscv_csr { 65 + unsigned long sstatus; 66 + unsigned long sie; 67 + unsigned long stvec; 68 + unsigned long sscratch; 69 + unsigned long sepc; 70 + unsigned long scause; 71 + unsigned long stval; 72 + unsigned long sip; 73 + unsigned long satp; 74 + unsigned long scounteren; 75 + }; 76 + 77 + #define KVM_REG_SIZE(id) \ 78 + (1U << (((id) & KVM_REG_SIZE_MASK) >> KVM_REG_SIZE_SHIFT)) 79 + 80 + /* If you need to interpret the index values, here is the key: */ 81 + #define KVM_REG_RISCV_TYPE_MASK 0x00000000FF000000 82 + #define KVM_REG_RISCV_TYPE_SHIFT 24 83 + 84 + /* Config registers are mapped as type 1 */ 85 + #define KVM_REG_RISCV_CONFIG (0x01 << KVM_REG_RISCV_TYPE_SHIFT) 86 + #define KVM_REG_RISCV_CONFIG_REG(name) \ 87 + (offsetof(struct kvm_riscv_config, name) / sizeof(unsigned long)) 88 + 89 + /* Core registers are mapped as type 2 */ 90 + #define KVM_REG_RISCV_CORE (0x02 << KVM_REG_RISCV_TYPE_SHIFT) 91 + #define KVM_REG_RISCV_CORE_REG(name) \ 92 + (offsetof(struct kvm_riscv_core, name) / sizeof(unsigned long)) 93 + 94 + /* Control and status registers are mapped as type 3 */ 95 + #define KVM_REG_RISCV_CSR (0x03 << KVM_REG_RISCV_TYPE_SHIFT) 96 + #define KVM_REG_RISCV_CSR_REG(name) \ 97 + (offsetof(struct kvm_riscv_csr, name) / sizeof(unsigned long)) 47 98 48 99 #endif 49 100
+238 -3
arch/riscv/kvm/vcpu.c
··· 18 18 #include <linux/fs.h> 19 19 #include <linux/kvm_host.h> 20 20 #include <asm/csr.h> 21 - #include <asm/delay.h> 22 21 #include <asm/hwcap.h> 23 22 24 23 const struct _kvm_stats_desc kvm_vcpu_stats_desc[] = { ··· 135 136 return VM_FAULT_SIGBUS; 136 137 } 137 138 139 + static int kvm_riscv_vcpu_get_reg_config(struct kvm_vcpu *vcpu, 140 + const struct kvm_one_reg *reg) 141 + { 142 + unsigned long __user *uaddr = 143 + (unsigned long __user *)(unsigned long)reg->addr; 144 + unsigned long reg_num = reg->id & ~(KVM_REG_ARCH_MASK | 145 + KVM_REG_SIZE_MASK | 146 + KVM_REG_RISCV_CONFIG); 147 + unsigned long reg_val; 148 + 149 + if (KVM_REG_SIZE(reg->id) != sizeof(unsigned long)) 150 + return -EINVAL; 151 + 152 + switch (reg_num) { 153 + case KVM_REG_RISCV_CONFIG_REG(isa): 154 + reg_val = vcpu->arch.isa; 155 + break; 156 + default: 157 + return -EINVAL; 158 + }; 159 + 160 + if (copy_to_user(uaddr, &reg_val, KVM_REG_SIZE(reg->id))) 161 + return -EFAULT; 162 + 163 + return 0; 164 + } 165 + 166 + static int kvm_riscv_vcpu_set_reg_config(struct kvm_vcpu *vcpu, 167 + const struct kvm_one_reg *reg) 168 + { 169 + unsigned long __user *uaddr = 170 + (unsigned long __user *)(unsigned long)reg->addr; 171 + unsigned long reg_num = reg->id & ~(KVM_REG_ARCH_MASK | 172 + KVM_REG_SIZE_MASK | 173 + KVM_REG_RISCV_CONFIG); 174 + unsigned long reg_val; 175 + 176 + if (KVM_REG_SIZE(reg->id) != sizeof(unsigned long)) 177 + return -EINVAL; 178 + 179 + if (copy_from_user(&reg_val, uaddr, KVM_REG_SIZE(reg->id))) 180 + return -EFAULT; 181 + 182 + switch (reg_num) { 183 + case KVM_REG_RISCV_CONFIG_REG(isa): 184 + if (!vcpu->arch.ran_atleast_once) { 185 + vcpu->arch.isa = reg_val; 186 + vcpu->arch.isa &= riscv_isa_extension_base(NULL); 187 + vcpu->arch.isa &= KVM_RISCV_ISA_ALLOWED; 188 + } else { 189 + return -EOPNOTSUPP; 190 + } 191 + break; 192 + default: 193 + return -EINVAL; 194 + }; 195 + 196 + return 0; 197 + } 198 + 199 + static int kvm_riscv_vcpu_get_reg_core(struct kvm_vcpu *vcpu, 200 + const struct kvm_one_reg *reg) 201 + { 202 + struct kvm_cpu_context *cntx = &vcpu->arch.guest_context; 203 + unsigned long __user *uaddr = 204 + (unsigned long __user *)(unsigned long)reg->addr; 205 + unsigned long reg_num = reg->id & ~(KVM_REG_ARCH_MASK | 206 + KVM_REG_SIZE_MASK | 207 + KVM_REG_RISCV_CORE); 208 + unsigned long reg_val; 209 + 210 + if (KVM_REG_SIZE(reg->id) != sizeof(unsigned long)) 211 + return -EINVAL; 212 + if (reg_num >= sizeof(struct kvm_riscv_core) / sizeof(unsigned long)) 213 + return -EINVAL; 214 + 215 + if (reg_num == KVM_REG_RISCV_CORE_REG(regs.pc)) 216 + reg_val = cntx->sepc; 217 + else if (KVM_REG_RISCV_CORE_REG(regs.pc) < reg_num && 218 + reg_num <= KVM_REG_RISCV_CORE_REG(regs.t6)) 219 + reg_val = ((unsigned long *)cntx)[reg_num]; 220 + else if (reg_num == KVM_REG_RISCV_CORE_REG(mode)) 221 + reg_val = (cntx->sstatus & SR_SPP) ? 222 + KVM_RISCV_MODE_S : KVM_RISCV_MODE_U; 223 + else 224 + return -EINVAL; 225 + 226 + if (copy_to_user(uaddr, &reg_val, KVM_REG_SIZE(reg->id))) 227 + return -EFAULT; 228 + 229 + return 0; 230 + } 231 + 232 + static int kvm_riscv_vcpu_set_reg_core(struct kvm_vcpu *vcpu, 233 + const struct kvm_one_reg *reg) 234 + { 235 + struct kvm_cpu_context *cntx = &vcpu->arch.guest_context; 236 + unsigned long __user *uaddr = 237 + (unsigned long __user *)(unsigned long)reg->addr; 238 + unsigned long reg_num = reg->id & ~(KVM_REG_ARCH_MASK | 239 + KVM_REG_SIZE_MASK | 240 + KVM_REG_RISCV_CORE); 241 + unsigned long reg_val; 242 + 243 + if (KVM_REG_SIZE(reg->id) != sizeof(unsigned long)) 244 + return -EINVAL; 245 + if (reg_num >= sizeof(struct kvm_riscv_core) / sizeof(unsigned long)) 246 + return -EINVAL; 247 + 248 + if (copy_from_user(&reg_val, uaddr, KVM_REG_SIZE(reg->id))) 249 + return -EFAULT; 250 + 251 + if (reg_num == KVM_REG_RISCV_CORE_REG(regs.pc)) 252 + cntx->sepc = reg_val; 253 + else if (KVM_REG_RISCV_CORE_REG(regs.pc) < reg_num && 254 + reg_num <= KVM_REG_RISCV_CORE_REG(regs.t6)) 255 + ((unsigned long *)cntx)[reg_num] = reg_val; 256 + else if (reg_num == KVM_REG_RISCV_CORE_REG(mode)) { 257 + if (reg_val == KVM_RISCV_MODE_S) 258 + cntx->sstatus |= SR_SPP; 259 + else 260 + cntx->sstatus &= ~SR_SPP; 261 + } else 262 + return -EINVAL; 263 + 264 + return 0; 265 + } 266 + 267 + static int kvm_riscv_vcpu_get_reg_csr(struct kvm_vcpu *vcpu, 268 + const struct kvm_one_reg *reg) 269 + { 270 + struct kvm_vcpu_csr *csr = &vcpu->arch.guest_csr; 271 + unsigned long __user *uaddr = 272 + (unsigned long __user *)(unsigned long)reg->addr; 273 + unsigned long reg_num = reg->id & ~(KVM_REG_ARCH_MASK | 274 + KVM_REG_SIZE_MASK | 275 + KVM_REG_RISCV_CSR); 276 + unsigned long reg_val; 277 + 278 + if (KVM_REG_SIZE(reg->id) != sizeof(unsigned long)) 279 + return -EINVAL; 280 + if (reg_num >= sizeof(struct kvm_riscv_csr) / sizeof(unsigned long)) 281 + return -EINVAL; 282 + 283 + if (reg_num == KVM_REG_RISCV_CSR_REG(sip)) { 284 + kvm_riscv_vcpu_flush_interrupts(vcpu); 285 + reg_val = (csr->hvip >> VSIP_TO_HVIP_SHIFT) & VSIP_VALID_MASK; 286 + } else 287 + reg_val = ((unsigned long *)csr)[reg_num]; 288 + 289 + if (copy_to_user(uaddr, &reg_val, KVM_REG_SIZE(reg->id))) 290 + return -EFAULT; 291 + 292 + return 0; 293 + } 294 + 295 + static int kvm_riscv_vcpu_set_reg_csr(struct kvm_vcpu *vcpu, 296 + const struct kvm_one_reg *reg) 297 + { 298 + struct kvm_vcpu_csr *csr = &vcpu->arch.guest_csr; 299 + unsigned long __user *uaddr = 300 + (unsigned long __user *)(unsigned long)reg->addr; 301 + unsigned long reg_num = reg->id & ~(KVM_REG_ARCH_MASK | 302 + KVM_REG_SIZE_MASK | 303 + KVM_REG_RISCV_CSR); 304 + unsigned long reg_val; 305 + 306 + if (KVM_REG_SIZE(reg->id) != sizeof(unsigned long)) 307 + return -EINVAL; 308 + if (reg_num >= sizeof(struct kvm_riscv_csr) / sizeof(unsigned long)) 309 + return -EINVAL; 310 + 311 + if (copy_from_user(&reg_val, uaddr, KVM_REG_SIZE(reg->id))) 312 + return -EFAULT; 313 + 314 + if (reg_num == KVM_REG_RISCV_CSR_REG(sip)) { 315 + reg_val &= VSIP_VALID_MASK; 316 + reg_val <<= VSIP_TO_HVIP_SHIFT; 317 + } 318 + 319 + ((unsigned long *)csr)[reg_num] = reg_val; 320 + 321 + if (reg_num == KVM_REG_RISCV_CSR_REG(sip)) 322 + WRITE_ONCE(vcpu->arch.irqs_pending_mask, 0); 323 + 324 + return 0; 325 + } 326 + 327 + static int kvm_riscv_vcpu_set_reg(struct kvm_vcpu *vcpu, 328 + const struct kvm_one_reg *reg) 329 + { 330 + if ((reg->id & KVM_REG_RISCV_TYPE_MASK) == KVM_REG_RISCV_CONFIG) 331 + return kvm_riscv_vcpu_set_reg_config(vcpu, reg); 332 + else if ((reg->id & KVM_REG_RISCV_TYPE_MASK) == KVM_REG_RISCV_CORE) 333 + return kvm_riscv_vcpu_set_reg_core(vcpu, reg); 334 + else if ((reg->id & KVM_REG_RISCV_TYPE_MASK) == KVM_REG_RISCV_CSR) 335 + return kvm_riscv_vcpu_set_reg_csr(vcpu, reg); 336 + 337 + return -EINVAL; 338 + } 339 + 340 + static int kvm_riscv_vcpu_get_reg(struct kvm_vcpu *vcpu, 341 + const struct kvm_one_reg *reg) 342 + { 343 + if ((reg->id & KVM_REG_RISCV_TYPE_MASK) == KVM_REG_RISCV_CONFIG) 344 + return kvm_riscv_vcpu_get_reg_config(vcpu, reg); 345 + else if ((reg->id & KVM_REG_RISCV_TYPE_MASK) == KVM_REG_RISCV_CORE) 346 + return kvm_riscv_vcpu_get_reg_core(vcpu, reg); 347 + else if ((reg->id & KVM_REG_RISCV_TYPE_MASK) == KVM_REG_RISCV_CSR) 348 + return kvm_riscv_vcpu_get_reg_csr(vcpu, reg); 349 + 350 + return -EINVAL; 351 + } 352 + 138 353 long kvm_arch_vcpu_async_ioctl(struct file *filp, 139 354 unsigned int ioctl, unsigned long arg) 140 355 { ··· 373 160 long kvm_arch_vcpu_ioctl(struct file *filp, 374 161 unsigned int ioctl, unsigned long arg) 375 162 { 376 - /* TODO: */ 377 - return -EINVAL; 163 + struct kvm_vcpu *vcpu = filp->private_data; 164 + void __user *argp = (void __user *)arg; 165 + long r = -EINVAL; 166 + 167 + switch (ioctl) { 168 + case KVM_SET_ONE_REG: 169 + case KVM_GET_ONE_REG: { 170 + struct kvm_one_reg reg; 171 + 172 + r = -EFAULT; 173 + if (copy_from_user(&reg, argp, sizeof(reg))) 174 + break; 175 + 176 + if (ioctl == KVM_SET_ONE_REG) 177 + r = kvm_riscv_vcpu_set_reg(vcpu, &reg); 178 + else 179 + r = kvm_riscv_vcpu_get_reg(vcpu, &reg); 180 + break; 181 + } 182 + default: 183 + break; 184 + } 185 + 186 + return r; 378 187 } 379 188 380 189 int kvm_arch_vcpu_ioctl_get_sregs(struct kvm_vcpu *vcpu,