1
0
mirror of https://github.com/kata-containers/kata-containers.git synced 2025-05-12 10:25:18 +00:00
kata-containers/tools/packaging/kernel/patches/6.1.x/dragonball-experimental/0003-upcall-add-cpu-hotplug-hot-unplug-into-device-manage.patch
Zvonko Kaiser ad574b7e10 dragonball: Add patches for 6.1.x
Ported the 5.10 patchs to 6.1.x

Signed-off-by: Zvonko Kaiser <zkaiser@nvidia.com>
2024-07-04 17:06:39 +00:00

302 lines
8.0 KiB
Diff

From 901fb71c77144b170465611617f0f25099d8a780 Mon Sep 17 00:00:00 2001
From: Chao Wu <chaowu@linux.alibaba.com>
Date: Mon, 21 Nov 2022 19:44:50 +0800
Subject: [PATCH 3/4] upcall: add cpu hotplug/hot-unplug into device manager
service
Add cpu hotplug and hot-unplug support into device manager. In the
`devmgr_req` message, `msg_type` ADD_CPU in `msg_header` will trigger
`add_cpu_dev` action and DEL_CPU will trigger `del_cpu_dev` action, and
we use `apic_ids` and `count` delivered in `cpu_dev_info` to notify
which and how many cpus will be hotplugged / hot-unplugged.
`add_cpu_dev` and `del_cpu_dev` will eventually trigger `add_cpu_upcall`
and `del_cpu_upcall` to trigger the cpu hotplug / hot-unplug process in
the kernel. After the cpu hotplug / hot-unplug process,
`cpu_event_notification` will generate device manager reply to the
client side.
Signed-off-by: Liu Jiang <gerry@linux.alibaba.com>
Signed-off-by: Zizheng Bian <zizheng.bian@linux.alibaba.com>
Signed-off-by: Chao Wu <chaowu@linux.alibaba.com>
Signed-off-by: WangYu <WangYu@linux.alibaba.com>
Signed-off-by: Xingjun Liu <xingjun.liu@linux.alibaba.com>
---
drivers/misc/dragonball/upcall_srv/Kconfig | 11 +
.../upcall_srv/dragonball_device_manager.c | 219 ++++++++++++++++++
2 files changed, 230 insertions(+)
diff --git a/drivers/misc/dragonball/upcall_srv/Kconfig b/drivers/misc/dragonball/upcall_srv/Kconfig
index 6554a9741c00..b237882a2928 100644
--- a/drivers/misc/dragonball/upcall_srv/Kconfig
+++ b/drivers/misc/dragonball/upcall_srv/Kconfig
@@ -24,3 +24,14 @@ config DRAGONBALL_DEVICE_MANAGER
devices etc.
If unsure, say N.
+
+config DRAGONBALL_HOTPLUG_CPU
+ bool "CPU hotplug/hotunplug support"
+ depends on DRAGONBALL_DEVICE_MANAGER
+ default y
+ help
+ This configure implements a vCPU hotplug/hotunplug support, vmm
+ should send hotplug request by vsock which follow special data
+ structure with command and parameter to hot-pluging an vCPU.
+
+ If unsure, say N.
diff --git a/drivers/misc/dragonball/upcall_srv/dragonball_device_manager.c b/drivers/misc/dragonball/upcall_srv/dragonball_device_manager.c
index ebcb6ef74285..210ef5d6c9d5 100644
--- a/drivers/misc/dragonball/upcall_srv/dragonball_device_manager.c
+++ b/drivers/misc/dragonball/upcall_srv/dragonball_device_manager.c
@@ -75,9 +75,20 @@ struct devmgr_req {
struct devmgr_msg_header msg_header;
union {
char pad[DEV_MGR_MSG_SIZE - sizeof(struct devmgr_msg_header)];
+#if defined(CONFIG_DRAGONBALL_HOTPLUG_CPU)
+ struct {
+ uint8_t count;
+ uint8_t apic_ver;
+ uint8_t apic_ids[256];
+ } cpu_dev_info;
+#endif
} msg_load;
};
+struct cpu_dev_reply_info {
+ uint32_t apic_index;
+};
+
struct devmgr_reply {
struct devmgr_msg_header msg_header;
/*
@@ -87,6 +98,9 @@ struct devmgr_reply {
int32_t ret;
union {
char pad[DEV_MGR_MSG_SIZE - sizeof(struct devmgr_msg_header) - sizeof(int32_t)];
+#if defined(CONFIG_DRAGONBALL_HOTPLUG_CPU)
+ struct cpu_dev_reply_info cpu_dev_info;
+#endif
} msg_load;
};
@@ -109,10 +123,215 @@ static void _fill_msg_header(struct devmgr_msg_header *msg, uint32_t msg_size,
msg->msg_flags = msg_flags;
}
+#if defined(CONFIG_DRAGONBALL_HOTPLUG_CPU) && defined(CONFIG_X86_64)
+static int get_cpu_id(int apic_id)
+{
+ int i;
+
+ for (i = 0; i < num_processors; i++) {
+ if (cpu_physical_id(i) == apic_id)
+ return i;
+ }
+ return -1;
+}
+
+/**
+ * Return the first failed hotplug index of the apic_ids to dragonball.
+ * If it is not equal to the count of all hotplug needed vcpus,
+ * we will rollback the vcpus from apics_ids[0] to apic_ids[i-1] in dragonball.
+ */
+static void cpu_event_notification(
+ uint8_t apic_ids_index,
+ int ret,
+ uint32_t action_type,
+ struct devmgr_reply *rep)
+{
+ pr_info("cpu event notification: apic ids index %d", apic_ids_index);
+ rep->msg_load.cpu_dev_info.apic_index = apic_ids_index;
+ rep->ret = ret;
+ _fill_msg_header(&rep->msg_header,
+ sizeof(struct cpu_dev_reply_info), action_type, 0);
+}
+#endif
+
+#if defined(CONFIG_DRAGONBALL_HOTPLUG_CPU) && defined(CONFIG_X86_64)
+static int add_cpu_upcall(int apic_id, uint8_t apic_ver)
+{
+ int cpu_id, node_id;
+ int ret;
+
+ pr_info("adding vcpu apic_id %d", apic_id);
+
+ /**
+ * Get the mutex lock for hotplug and cpu update and cpu write lock.
+ * So that other threads won't influence the hotplug process.
+ */
+ lock_device_hotplug();
+ cpu_maps_update_begin();
+ cpu_hotplug_begin();
+
+ cpu_id = generic_processor_info(apic_id, apic_ver);
+ if (cpu_id < 0) {
+ pr_err("cpu (apic id %d) cannot be added, generic processor info failed", apic_id);
+ ret = -EINVAL;
+ goto rollback_generic_cpu;
+ }
+
+ /* update numa mapping for hot-plugged cpus. */
+ node_id = numa_cpu_node(cpu_id);
+ if (node_id != NUMA_NO_NODE)
+ numa_set_node(cpu_id, node_id);
+
+ ret = arch_register_cpu(cpu_id);
+ if (ret) {
+ pr_err("cpu %d cannot be added, register cpu failed %d", cpu_id, ret);
+ goto rollback_register_cpu;
+ }
+
+ cpu_hotplug_done();
+ cpu_maps_update_done();
+ unlock_device_hotplug();
+
+ ret = add_cpu(cpu_id);
+ if (ret) {
+ pr_err("cpu %d cannot be added, cpu up failed: %d", cpu_id, ret);
+ goto rollback_cpu_up;
+ }
+ return ret;
+
+rollback_cpu_up:
+ arch_unregister_cpu(cpu_id);
+ set_cpu_present(cpu_id, false);
+ per_cpu(x86_cpu_to_apicid, cpu_id) = -1;
+ num_processors--;
+ return ret;
+
+rollback_register_cpu:
+ set_cpu_present(cpu_id, false);
+ per_cpu(x86_cpu_to_apicid, cpu_id) = -1;
+ num_processors--;
+rollback_generic_cpu:
+ cpu_hotplug_done();
+ cpu_maps_update_done();
+ unlock_device_hotplug();
+ return ret;
+}
+
+static int del_cpu_upcall(int apic_id)
+{
+ int cpu_id = get_cpu_id(apic_id);
+ int ret;
+
+ if (cpu_id == 0) {
+ pr_err("cannot del bootstrap processor.");
+ return -EINVAL;
+ }
+ pr_info("deleting vcpu %d", cpu_id);
+ ret = remove_cpu(cpu_id);
+ if (ret) {
+ pr_err("del vcpu failed, err: %d", ret);
+ return ret;
+ }
+
+ lock_device_hotplug();
+ cpu_maps_update_begin();
+ cpu_hotplug_begin();
+
+ arch_unregister_cpu(cpu_id);
+ set_cpu_present(cpu_id, false);
+ per_cpu(x86_cpu_to_apicid, cpu_id) = -1;
+ num_processors--;
+
+ cpu_hotplug_done();
+ cpu_maps_update_done();
+ unlock_device_hotplug();
+
+ return ret;
+}
+
+static int add_cpu_dev(struct devmgr_req *req,
+ struct devmgr_reply *rep)
+{
+ int ret;
+ uint8_t i;
+ int apic_id;
+
+ uint8_t count = req->msg_load.cpu_dev_info.count;
+ uint8_t apic_ver = req->msg_load.cpu_dev_info.apic_ver;
+ uint8_t *apic_ids = req->msg_load.cpu_dev_info.apic_ids;
+
+ pr_info("add vcpu number: %d", count);
+
+ for (i = 0; i < count; ++i) {
+ apic_id = apic_ids[i];
+ if (get_cpu_id(apic_id) != -1) {
+ pr_err("cpu cannot be added: apci_id %d is already been used.", apic_id);
+ ret = -EINVAL;
+ return ret;
+ }
+ }
+
+ for (i = 0; i < count; ++i) {
+ apic_id = apic_ids[i];
+ ret = add_cpu_upcall(apic_id, apic_ver);
+ if (ret != 0)
+ break;
+ }
+
+ if (!ret)
+ cpu_event_notification(i, ret, ADD_CPU, rep);
+ return ret;
+}
+
+static int del_cpu_dev(struct devmgr_req *req,
+ struct devmgr_reply *rep)
+{
+ int ret;
+ uint8_t i;
+ int cpu_id;
+
+ uint8_t count = req->msg_load.cpu_dev_info.count;
+ uint8_t *apic_ids = req->msg_load.cpu_dev_info.apic_ids;
+
+ pr_info("del vcpu number : %d", count);
+
+ if (count >= num_processors) {
+ pr_err("cpu del parameter check error: cannot remove all vcpus");
+ ret = -EINVAL;
+ cpu_event_notification(0, ret, DEL_CPU, rep);
+ return ret;
+ }
+
+ for (i = 0; i < count; ++i) {
+ cpu_id = get_cpu_id(apic_ids[i]);
+ if (!cpu_possible(cpu_id)) {
+ pr_err("cpu %d cannot be deleted: cpu not possible", cpu_id);
+ ret = -EINVAL;
+ cpu_event_notification(0, ret, DEL_CPU, rep);
+ return ret;
+ }
+ }
+
+ for (i = 0; i < count; ++i) {
+ ret = del_cpu_upcall(apic_ids[i]);
+ if (ret != 0)
+ break;
+ }
+
+ if (!ret)
+ cpu_event_notification(i, ret, DEL_CPU, rep);
+ return ret;
+}
+#endif
+
static struct {
enum devmgr_msg_type cmd;
action_route_t fn;
} opt_map[] = {
+#if defined(CONFIG_DRAGONBALL_HOTPLUG_CPU) && defined(CONFIG_X86_64)
+ {ADD_CPU, add_cpu_dev},
+ {DEL_CPU, del_cpu_dev},
+#endif
};
static action_route_t get_action(struct devmgr_req *req)
--
2.19.1.6.gb485710b