diff options
Diffstat (limited to 'drivers/virt/acrn/hsm.c')
-rw-r--r-- | drivers/virt/acrn/hsm.c | 48 |
1 files changed, 48 insertions, 0 deletions
diff --git a/drivers/virt/acrn/hsm.c b/drivers/virt/acrn/hsm.c index 93f6abe10fa6..1f6b7c54a1a4 100644 --- a/drivers/virt/acrn/hsm.c +++ b/drivers/virt/acrn/hsm.c @@ -9,6 +9,7 @@ * Yakui Zhao <yakui.zhao@intel.com> */ +#include <linux/cpu.h> #include <linux/io.h> #include <linux/mm.h> #include <linux/module.h> @@ -371,6 +372,52 @@ static int acrn_dev_release(struct inode *inode, struct file *filp) return 0; } +static ssize_t remove_cpu_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + u64 cpu, lapicid; + int ret; + + if (kstrtoull(buf, 0, &cpu) < 0) + return -EINVAL; + + if (cpu >= num_possible_cpus() || cpu == 0 || !cpu_is_hotpluggable(cpu)) + return -EINVAL; + + if (cpu_online(cpu)) + remove_cpu(cpu); + + lapicid = cpu_data(cpu).apicid; + dev_dbg(dev, "Try to remove cpu %lld with lapicid %lld\n", cpu, lapicid); + ret = hcall_sos_remove_cpu(lapicid); + if (ret < 0) { + dev_err(dev, "Failed to remove cpu %lld!\n", cpu); + goto fail_remove; + } + + return count; + +fail_remove: + add_cpu(cpu); + return ret; +} +static DEVICE_ATTR_WO(remove_cpu); + +static struct attribute *acrn_attrs[] = { + &dev_attr_remove_cpu.attr, + NULL +}; + +static struct attribute_group acrn_attr_group = { + .attrs = acrn_attrs, +}; + +static const struct attribute_group *acrn_attr_groups[] = { + &acrn_attr_group, + NULL +}; + static const struct file_operations acrn_fops = { .owner = THIS_MODULE, .open = acrn_dev_open, @@ -382,6 +429,7 @@ struct miscdevice acrn_dev = { .minor = MISC_DYNAMIC_MINOR, .name = "acrn_hsm", .fops = &acrn_fops, + .groups = acrn_attr_groups, }; static int __init hsm_init(void) |