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