1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * ACRN Hypervisor Service Module (HSM) 4 * 5 * Copyright (C) 2020 Intel Corporation. All rights reserved. 6 * 7 * Authors: 8 * Fengwei Yin <fengwei.yin@intel.com> 9 * Yakui Zhao <yakui.zhao@intel.com> 10 */ 11 12 #include <linux/cpu.h> 13 #include <linux/io.h> 14 #include <linux/mm.h> 15 #include <linux/module.h> 16 #include <linux/slab.h> 17 18 #include <asm/acrn.h> 19 #include <asm/cpuid/api.h> 20 #include <asm/hypervisor.h> 21 22 #include "acrn_drv.h" 23 24 /* 25 * When /dev/acrn_hsm is opened, a 'struct acrn_vm' object is created to 26 * represent a VM instance and continues to be associated with the opened file 27 * descriptor. All ioctl operations on this file descriptor will be targeted to 28 * the VM instance. Release of this file descriptor will destroy the object. 29 */ 30 static int acrn_dev_open(struct inode *inode, struct file *filp) 31 { 32 struct acrn_vm *vm; 33 34 vm = kzalloc_obj(*vm); 35 if (!vm) 36 return -ENOMEM; 37 38 vm->vmid = ACRN_INVALID_VMID; 39 filp->private_data = vm; 40 return 0; 41 } 42 43 static int pmcmd_ioctl(u64 cmd, void __user *uptr) 44 { 45 struct acrn_pstate_data *px_data; 46 struct acrn_cstate_data *cx_data; 47 u64 *pm_info; 48 int ret = 0; 49 50 switch (cmd & PMCMD_TYPE_MASK) { 51 case ACRN_PMCMD_GET_PX_CNT: 52 case ACRN_PMCMD_GET_CX_CNT: 53 pm_info = kzalloc(sizeof(u64), GFP_KERNEL); 54 if (!pm_info) 55 return -ENOMEM; 56 57 ret = hcall_get_cpu_state(cmd, virt_to_phys(pm_info)); 58 if (ret < 0) { 59 kfree(pm_info); 60 break; 61 } 62 63 if (copy_to_user(uptr, pm_info, sizeof(u64))) 64 ret = -EFAULT; 65 kfree(pm_info); 66 break; 67 case ACRN_PMCMD_GET_PX_DATA: 68 px_data = kzalloc_obj(*px_data); 69 if (!px_data) 70 return -ENOMEM; 71 72 ret = hcall_get_cpu_state(cmd, virt_to_phys(px_data)); 73 if (ret < 0) { 74 kfree(px_data); 75 break; 76 } 77 78 if (copy_to_user(uptr, px_data, sizeof(*px_data))) 79 ret = -EFAULT; 80 kfree(px_data); 81 break; 82 case ACRN_PMCMD_GET_CX_DATA: 83 cx_data = kzalloc_obj(*cx_data); 84 if (!cx_data) 85 return -ENOMEM; 86 87 ret = hcall_get_cpu_state(cmd, virt_to_phys(cx_data)); 88 if (ret < 0) { 89 kfree(cx_data); 90 break; 91 } 92 93 if (copy_to_user(uptr, cx_data, sizeof(*cx_data))) 94 ret = -EFAULT; 95 kfree(cx_data); 96 break; 97 default: 98 break; 99 } 100 101 return ret; 102 } 103 104 /* 105 * HSM relies on hypercall layer of the ACRN hypervisor to do the 106 * sanity check against the input parameters. 107 */ 108 static long acrn_dev_ioctl(struct file *filp, unsigned int cmd, 109 unsigned long ioctl_param) 110 { 111 struct acrn_vm *vm = filp->private_data; 112 struct acrn_vm_creation *vm_param; 113 struct acrn_vcpu_regs *cpu_regs; 114 struct acrn_ioreq_notify notify; 115 struct acrn_ptdev_irq *irq_info; 116 struct acrn_ioeventfd ioeventfd; 117 struct acrn_vm_memmap memmap; 118 struct acrn_mmiodev *mmiodev; 119 struct acrn_msi_entry *msi; 120 struct acrn_pcidev *pcidev; 121 struct acrn_irqfd irqfd; 122 struct acrn_vdev *vdev; 123 struct page *page; 124 u64 cstate_cmd; 125 int i, ret = 0; 126 127 if (vm->vmid == ACRN_INVALID_VMID && cmd != ACRN_IOCTL_CREATE_VM) { 128 dev_dbg(acrn_dev.this_device, 129 "ioctl 0x%x: Invalid VM state!\n", cmd); 130 return -EINVAL; 131 } 132 133 switch (cmd) { 134 case ACRN_IOCTL_CREATE_VM: 135 vm_param = memdup_user((void __user *)ioctl_param, 136 sizeof(struct acrn_vm_creation)); 137 if (IS_ERR(vm_param)) 138 return PTR_ERR(vm_param); 139 140 if ((vm_param->reserved0 | vm_param->reserved1) != 0) { 141 kfree(vm_param); 142 return -EINVAL; 143 } 144 145 vm = acrn_vm_create(vm, vm_param); 146 if (!vm) { 147 ret = -EINVAL; 148 kfree(vm_param); 149 break; 150 } 151 152 if (copy_to_user((void __user *)ioctl_param, vm_param, 153 sizeof(struct acrn_vm_creation))) { 154 acrn_vm_destroy(vm); 155 ret = -EFAULT; 156 } 157 158 kfree(vm_param); 159 break; 160 case ACRN_IOCTL_START_VM: 161 ret = hcall_start_vm(vm->vmid); 162 if (ret < 0) 163 dev_dbg(acrn_dev.this_device, 164 "Failed to start VM %u!\n", vm->vmid); 165 break; 166 case ACRN_IOCTL_PAUSE_VM: 167 ret = hcall_pause_vm(vm->vmid); 168 if (ret < 0) 169 dev_dbg(acrn_dev.this_device, 170 "Failed to pause VM %u!\n", vm->vmid); 171 break; 172 case ACRN_IOCTL_RESET_VM: 173 ret = hcall_reset_vm(vm->vmid); 174 if (ret < 0) 175 dev_dbg(acrn_dev.this_device, 176 "Failed to restart VM %u!\n", vm->vmid); 177 break; 178 case ACRN_IOCTL_DESTROY_VM: 179 ret = acrn_vm_destroy(vm); 180 break; 181 case ACRN_IOCTL_SET_VCPU_REGS: 182 cpu_regs = memdup_user((void __user *)ioctl_param, 183 sizeof(struct acrn_vcpu_regs)); 184 if (IS_ERR(cpu_regs)) 185 return PTR_ERR(cpu_regs); 186 187 for (i = 0; i < ARRAY_SIZE(cpu_regs->reserved); i++) 188 if (cpu_regs->reserved[i]) { 189 kfree(cpu_regs); 190 return -EINVAL; 191 } 192 193 for (i = 0; i < ARRAY_SIZE(cpu_regs->vcpu_regs.reserved_32); i++) 194 if (cpu_regs->vcpu_regs.reserved_32[i]) { 195 kfree(cpu_regs); 196 return -EINVAL; 197 } 198 199 for (i = 0; i < ARRAY_SIZE(cpu_regs->vcpu_regs.reserved_64); i++) 200 if (cpu_regs->vcpu_regs.reserved_64[i]) { 201 kfree(cpu_regs); 202 return -EINVAL; 203 } 204 205 for (i = 0; i < ARRAY_SIZE(cpu_regs->vcpu_regs.gdt.reserved); i++) 206 if (cpu_regs->vcpu_regs.gdt.reserved[i] | 207 cpu_regs->vcpu_regs.idt.reserved[i]) { 208 kfree(cpu_regs); 209 return -EINVAL; 210 } 211 212 ret = hcall_set_vcpu_regs(vm->vmid, virt_to_phys(cpu_regs)); 213 if (ret < 0) 214 dev_dbg(acrn_dev.this_device, 215 "Failed to set regs state of VM%u!\n", 216 vm->vmid); 217 kfree(cpu_regs); 218 break; 219 case ACRN_IOCTL_SET_MEMSEG: 220 if (copy_from_user(&memmap, (void __user *)ioctl_param, 221 sizeof(memmap))) 222 return -EFAULT; 223 224 ret = acrn_vm_memseg_map(vm, &memmap); 225 break; 226 case ACRN_IOCTL_UNSET_MEMSEG: 227 if (copy_from_user(&memmap, (void __user *)ioctl_param, 228 sizeof(memmap))) 229 return -EFAULT; 230 231 ret = acrn_vm_memseg_unmap(vm, &memmap); 232 break; 233 case ACRN_IOCTL_ASSIGN_MMIODEV: 234 mmiodev = memdup_user((void __user *)ioctl_param, 235 sizeof(struct acrn_mmiodev)); 236 if (IS_ERR(mmiodev)) 237 return PTR_ERR(mmiodev); 238 239 ret = hcall_assign_mmiodev(vm->vmid, virt_to_phys(mmiodev)); 240 if (ret < 0) 241 dev_dbg(acrn_dev.this_device, 242 "Failed to assign MMIO device!\n"); 243 kfree(mmiodev); 244 break; 245 case ACRN_IOCTL_DEASSIGN_MMIODEV: 246 mmiodev = memdup_user((void __user *)ioctl_param, 247 sizeof(struct acrn_mmiodev)); 248 if (IS_ERR(mmiodev)) 249 return PTR_ERR(mmiodev); 250 251 ret = hcall_deassign_mmiodev(vm->vmid, virt_to_phys(mmiodev)); 252 if (ret < 0) 253 dev_dbg(acrn_dev.this_device, 254 "Failed to deassign MMIO device!\n"); 255 kfree(mmiodev); 256 break; 257 case ACRN_IOCTL_ASSIGN_PCIDEV: 258 pcidev = memdup_user((void __user *)ioctl_param, 259 sizeof(struct acrn_pcidev)); 260 if (IS_ERR(pcidev)) 261 return PTR_ERR(pcidev); 262 263 ret = hcall_assign_pcidev(vm->vmid, virt_to_phys(pcidev)); 264 if (ret < 0) 265 dev_dbg(acrn_dev.this_device, 266 "Failed to assign pci device!\n"); 267 kfree(pcidev); 268 break; 269 case ACRN_IOCTL_DEASSIGN_PCIDEV: 270 pcidev = memdup_user((void __user *)ioctl_param, 271 sizeof(struct acrn_pcidev)); 272 if (IS_ERR(pcidev)) 273 return PTR_ERR(pcidev); 274 275 ret = hcall_deassign_pcidev(vm->vmid, virt_to_phys(pcidev)); 276 if (ret < 0) 277 dev_dbg(acrn_dev.this_device, 278 "Failed to deassign pci device!\n"); 279 kfree(pcidev); 280 break; 281 case ACRN_IOCTL_CREATE_VDEV: 282 vdev = memdup_user((void __user *)ioctl_param, 283 sizeof(struct acrn_vdev)); 284 if (IS_ERR(vdev)) 285 return PTR_ERR(vdev); 286 287 ret = hcall_create_vdev(vm->vmid, virt_to_phys(vdev)); 288 if (ret < 0) 289 dev_dbg(acrn_dev.this_device, 290 "Failed to create virtual device!\n"); 291 kfree(vdev); 292 break; 293 case ACRN_IOCTL_DESTROY_VDEV: 294 vdev = memdup_user((void __user *)ioctl_param, 295 sizeof(struct acrn_vdev)); 296 if (IS_ERR(vdev)) 297 return PTR_ERR(vdev); 298 ret = hcall_destroy_vdev(vm->vmid, virt_to_phys(vdev)); 299 if (ret < 0) 300 dev_dbg(acrn_dev.this_device, 301 "Failed to destroy virtual device!\n"); 302 kfree(vdev); 303 break; 304 case ACRN_IOCTL_SET_PTDEV_INTR: 305 irq_info = memdup_user((void __user *)ioctl_param, 306 sizeof(struct acrn_ptdev_irq)); 307 if (IS_ERR(irq_info)) 308 return PTR_ERR(irq_info); 309 310 ret = hcall_set_ptdev_intr(vm->vmid, virt_to_phys(irq_info)); 311 if (ret < 0) 312 dev_dbg(acrn_dev.this_device, 313 "Failed to configure intr for ptdev!\n"); 314 kfree(irq_info); 315 break; 316 case ACRN_IOCTL_RESET_PTDEV_INTR: 317 irq_info = memdup_user((void __user *)ioctl_param, 318 sizeof(struct acrn_ptdev_irq)); 319 if (IS_ERR(irq_info)) 320 return PTR_ERR(irq_info); 321 322 ret = hcall_reset_ptdev_intr(vm->vmid, virt_to_phys(irq_info)); 323 if (ret < 0) 324 dev_dbg(acrn_dev.this_device, 325 "Failed to reset intr for ptdev!\n"); 326 kfree(irq_info); 327 break; 328 case ACRN_IOCTL_SET_IRQLINE: 329 ret = hcall_set_irqline(vm->vmid, ioctl_param); 330 if (ret < 0) 331 dev_dbg(acrn_dev.this_device, 332 "Failed to set interrupt line!\n"); 333 break; 334 case ACRN_IOCTL_INJECT_MSI: 335 msi = memdup_user((void __user *)ioctl_param, 336 sizeof(struct acrn_msi_entry)); 337 if (IS_ERR(msi)) 338 return PTR_ERR(msi); 339 340 ret = hcall_inject_msi(vm->vmid, virt_to_phys(msi)); 341 if (ret < 0) 342 dev_dbg(acrn_dev.this_device, 343 "Failed to inject MSI!\n"); 344 kfree(msi); 345 break; 346 case ACRN_IOCTL_VM_INTR_MONITOR: 347 ret = pin_user_pages_fast(ioctl_param, 1, 348 FOLL_WRITE | FOLL_LONGTERM, &page); 349 if (unlikely(ret != 1)) { 350 dev_dbg(acrn_dev.this_device, 351 "Failed to pin intr hdr buffer!\n"); 352 return -EFAULT; 353 } 354 355 ret = hcall_vm_intr_monitor(vm->vmid, page_to_phys(page)); 356 if (ret < 0) { 357 unpin_user_page(page); 358 dev_dbg(acrn_dev.this_device, 359 "Failed to monitor intr data!\n"); 360 return ret; 361 } 362 if (vm->monitor_page) 363 unpin_user_page(vm->monitor_page); 364 vm->monitor_page = page; 365 break; 366 case ACRN_IOCTL_CREATE_IOREQ_CLIENT: 367 if (vm->default_client) 368 return -EEXIST; 369 if (!acrn_ioreq_client_create(vm, NULL, NULL, true, "acrndm")) 370 ret = -EINVAL; 371 break; 372 case ACRN_IOCTL_DESTROY_IOREQ_CLIENT: 373 if (vm->default_client) 374 acrn_ioreq_client_destroy(vm->default_client); 375 break; 376 case ACRN_IOCTL_ATTACH_IOREQ_CLIENT: 377 if (vm->default_client) 378 ret = acrn_ioreq_client_wait(vm->default_client); 379 else 380 ret = -ENODEV; 381 break; 382 case ACRN_IOCTL_NOTIFY_REQUEST_FINISH: 383 if (copy_from_user(¬ify, (void __user *)ioctl_param, 384 sizeof(struct acrn_ioreq_notify))) 385 return -EFAULT; 386 387 if (notify.reserved != 0) 388 return -EINVAL; 389 390 ret = acrn_ioreq_request_default_complete(vm, notify.vcpu); 391 break; 392 case ACRN_IOCTL_CLEAR_VM_IOREQ: 393 acrn_ioreq_request_clear(vm); 394 break; 395 case ACRN_IOCTL_PM_GET_CPU_STATE: 396 if (copy_from_user(&cstate_cmd, (void __user *)ioctl_param, 397 sizeof(cstate_cmd))) 398 return -EFAULT; 399 400 ret = pmcmd_ioctl(cstate_cmd, (void __user *)ioctl_param); 401 break; 402 case ACRN_IOCTL_IOEVENTFD: 403 if (copy_from_user(&ioeventfd, (void __user *)ioctl_param, 404 sizeof(ioeventfd))) 405 return -EFAULT; 406 407 if (ioeventfd.reserved != 0) 408 return -EINVAL; 409 410 ret = acrn_ioeventfd_config(vm, &ioeventfd); 411 break; 412 case ACRN_IOCTL_IRQFD: 413 if (copy_from_user(&irqfd, (void __user *)ioctl_param, 414 sizeof(irqfd))) 415 return -EFAULT; 416 ret = acrn_irqfd_config(vm, &irqfd); 417 break; 418 default: 419 dev_dbg(acrn_dev.this_device, "Unknown IOCTL 0x%x!\n", cmd); 420 ret = -ENOTTY; 421 } 422 423 return ret; 424 } 425 426 static int acrn_dev_release(struct inode *inode, struct file *filp) 427 { 428 struct acrn_vm *vm = filp->private_data; 429 430 acrn_vm_destroy(vm); 431 kfree(vm); 432 return 0; 433 } 434 435 static ssize_t remove_cpu_store(struct device *dev, 436 struct device_attribute *attr, 437 const char *buf, size_t count) 438 { 439 u64 cpu, lapicid; 440 int ret; 441 442 if (kstrtoull(buf, 0, &cpu) < 0) 443 return -EINVAL; 444 445 if (cpu >= num_possible_cpus() || cpu == 0 || !cpu_is_hotpluggable(cpu)) 446 return -EINVAL; 447 448 if (cpu_online(cpu)) 449 remove_cpu(cpu); 450 451 lapicid = cpu_data(cpu).topo.apicid; 452 dev_dbg(dev, "Try to remove cpu %lld with lapicid %lld\n", cpu, lapicid); 453 ret = hcall_sos_remove_cpu(lapicid); 454 if (ret < 0) { 455 dev_err(dev, "Failed to remove cpu %lld!\n", cpu); 456 goto fail_remove; 457 } 458 459 return count; 460 461 fail_remove: 462 add_cpu(cpu); 463 return ret; 464 } 465 static DEVICE_ATTR_WO(remove_cpu); 466 467 static umode_t acrn_attr_visible(struct kobject *kobj, struct attribute *a, int n) 468 { 469 if (a == &dev_attr_remove_cpu.attr) 470 return IS_ENABLED(CONFIG_HOTPLUG_CPU) ? a->mode : 0; 471 472 return a->mode; 473 } 474 475 static struct attribute *acrn_attrs[] = { 476 &dev_attr_remove_cpu.attr, 477 NULL 478 }; 479 480 static struct attribute_group acrn_attr_group = { 481 .attrs = acrn_attrs, 482 .is_visible = acrn_attr_visible, 483 }; 484 485 static const struct attribute_group *acrn_attr_groups[] = { 486 &acrn_attr_group, 487 NULL 488 }; 489 490 static const struct file_operations acrn_fops = { 491 .owner = THIS_MODULE, 492 .open = acrn_dev_open, 493 .release = acrn_dev_release, 494 .unlocked_ioctl = acrn_dev_ioctl, 495 }; 496 497 struct miscdevice acrn_dev = { 498 .minor = MISC_DYNAMIC_MINOR, 499 .name = "acrn_hsm", 500 .fops = &acrn_fops, 501 .groups = acrn_attr_groups, 502 }; 503 504 static int __init hsm_init(void) 505 { 506 int ret; 507 508 if (x86_hyper_type != X86_HYPER_ACRN) 509 return -ENODEV; 510 511 if (!(cpuid_eax(ACRN_CPUID_FEATURES) & ACRN_FEATURE_PRIVILEGED_VM)) 512 return -EPERM; 513 514 ret = misc_register(&acrn_dev); 515 if (ret) { 516 pr_err("Create misc dev failed!\n"); 517 return ret; 518 } 519 520 ret = acrn_ioreq_intr_setup(); 521 if (ret) { 522 pr_err("Setup I/O request handler failed!\n"); 523 misc_deregister(&acrn_dev); 524 return ret; 525 } 526 return 0; 527 } 528 529 static void __exit hsm_exit(void) 530 { 531 acrn_ioreq_intr_remove(); 532 misc_deregister(&acrn_dev); 533 } 534 module_init(hsm_init); 535 module_exit(hsm_exit); 536 537 MODULE_AUTHOR("Intel Corporation"); 538 MODULE_LICENSE("GPL"); 539 MODULE_DESCRIPTION("ACRN Hypervisor Service Module (HSM)"); 540