cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

cpu_hotplug.c (2344B)


      1// SPDX-License-Identifier: GPL-2.0
      2#define pr_fmt(fmt) "xen:" KBUILD_MODNAME ": " fmt
      3
      4#include <linux/notifier.h>
      5
      6#include <xen/xen.h>
      7#include <xen/xenbus.h>
      8
      9#include <asm/xen/hypervisor.h>
     10#include <asm/cpu.h>
     11
     12static void enable_hotplug_cpu(int cpu)
     13{
     14	if (!cpu_present(cpu))
     15		xen_arch_register_cpu(cpu);
     16
     17	set_cpu_present(cpu, true);
     18}
     19
     20static void disable_hotplug_cpu(int cpu)
     21{
     22	if (!cpu_is_hotpluggable(cpu))
     23		return;
     24	lock_device_hotplug();
     25	if (cpu_online(cpu))
     26		device_offline(get_cpu_device(cpu));
     27	if (!cpu_online(cpu) && cpu_present(cpu)) {
     28		xen_arch_unregister_cpu(cpu);
     29		set_cpu_present(cpu, false);
     30	}
     31	unlock_device_hotplug();
     32}
     33
     34static int vcpu_online(unsigned int cpu)
     35{
     36	int err;
     37	char dir[16], state[16];
     38
     39	sprintf(dir, "cpu/%u", cpu);
     40	err = xenbus_scanf(XBT_NIL, dir, "availability", "%15s", state);
     41	if (err != 1) {
     42		if (!xen_initial_domain())
     43			pr_err("Unable to read cpu state\n");
     44		return err;
     45	}
     46
     47	if (strcmp(state, "online") == 0)
     48		return 1;
     49	else if (strcmp(state, "offline") == 0)
     50		return 0;
     51
     52	pr_err("unknown state(%s) on CPU%d\n", state, cpu);
     53	return -EINVAL;
     54}
     55static void vcpu_hotplug(unsigned int cpu)
     56{
     57	if (cpu >= nr_cpu_ids || !cpu_possible(cpu))
     58		return;
     59
     60	switch (vcpu_online(cpu)) {
     61	case 1:
     62		enable_hotplug_cpu(cpu);
     63		break;
     64	case 0:
     65		disable_hotplug_cpu(cpu);
     66		break;
     67	default:
     68		break;
     69	}
     70}
     71
     72static void handle_vcpu_hotplug_event(struct xenbus_watch *watch,
     73				      const char *path, const char *token)
     74{
     75	unsigned int cpu;
     76	char *cpustr;
     77
     78	cpustr = strstr(path, "cpu/");
     79	if (cpustr != NULL) {
     80		sscanf(cpustr, "cpu/%u", &cpu);
     81		vcpu_hotplug(cpu);
     82	}
     83}
     84
     85static int setup_cpu_watcher(struct notifier_block *notifier,
     86			      unsigned long event, void *data)
     87{
     88	int cpu;
     89	static struct xenbus_watch cpu_watch = {
     90		.node = "cpu",
     91		.callback = handle_vcpu_hotplug_event};
     92
     93	(void)register_xenbus_watch(&cpu_watch);
     94
     95	for_each_possible_cpu(cpu) {
     96		if (vcpu_online(cpu) == 0)
     97			disable_hotplug_cpu(cpu);
     98	}
     99
    100	return NOTIFY_DONE;
    101}
    102
    103static int __init setup_vcpu_hotplug_event(void)
    104{
    105	static struct notifier_block xsn_cpu = {
    106		.notifier_call = setup_cpu_watcher };
    107
    108#ifdef CONFIG_X86
    109	if (!xen_pv_domain() && !xen_pvh_domain())
    110#else
    111	if (!xen_domain())
    112#endif
    113		return -ENODEV;
    114
    115	register_xenstore_notifier(&xsn_cpu);
    116
    117	return 0;
    118}
    119
    120late_initcall(setup_vcpu_hotplug_event);
    121