@@ -116,11 +116,13 @@ static inline u64 sc_retry(sc_func_t func, u64 fn,
int tdx_cpu_enable(void);
int tdx_enable(void);
const char *tdx_dump_mce_info(struct mce *m);
+int tdx_check_hotplug_memory_range(u64 start, u64 size);
#else
static inline void tdx_init(void) { }
static inline int tdx_cpu_enable(void) { return -ENODEV; }
static inline int tdx_enable(void) { return -ENODEV; }
static inline const char *tdx_dump_mce_info(struct mce *m) { return NULL; }
+static inline int tdx_check_hotplug_memory_range(u64 start, u64 size) { return 0; }
#endif /* CONFIG_INTEL_TDX_HOST */
#endif /* !__ASSEMBLY__ */
@@ -55,6 +55,7 @@
#include <asm/uv/uv.h>
#include <asm/setup.h>
#include <asm/ftrace.h>
+#include <asm/tdx.h>
#include "mm_internal.h"
@@ -974,6 +975,11 @@ int add_pages(int nid, unsigned long start_pfn, unsigned long nr_pages,
return ret;
}
+int arch_check_hotplug_memory_range(u64 start, u64 size)
+{
+ return tdx_check_hotplug_memory_range(start, size);
+}
+
int arch_add_memory(int nid, u64 start, u64 size,
struct mhp_params *params)
{
@@ -1388,36 +1388,37 @@ static bool is_tdx_memory(unsigned long start_pfn, unsigned long end_pfn)
return false;
}
-static int tdx_memory_notifier(struct notifier_block *nb, unsigned long action,
- void *v)
+/*
+ * We don't allow mixture of TDX and !TDX memory in the buddy so we
+ * won't run into trouble when launching encrypted VMs that really
+ * need TDX-capable memory.
+ */
+int tdx_check_hotplug_memory_range(u64 start, u64 size)
{
- struct memory_notify *mn = v;
-
- if (action != MEM_GOING_ONLINE)
- return NOTIFY_OK;
+ u64 start_pfn = PHYS_PFN(start);
+ u64 end_pfn = PHYS_PFN(start + size);
/*
* Empty list means TDX isn't enabled. Allow any memory
- * to go online.
+ * to be hot-added.
*/
if (list_empty(&tdx_memlist))
- return NOTIFY_OK;
+ return 0;
/*
* The TDX memory configuration is static and can not be
- * changed. Reject onlining any memory which is outside of
+ * changed. Reject hot-adding any memory which is outside of
* the static configuration whether it supports TDX or not.
*/
- if (is_tdx_memory(mn->start_pfn, mn->start_pfn + mn->nr_pages))
- return NOTIFY_OK;
+ if (is_tdx_memory(start_pfn, end_pfn))
+ return 0;
- return NOTIFY_BAD;
+ pr_info("Reject hot-adding memory range: %#llx-%#llx for TDX compatibility.\n",
+ start, start + size);
+
+ return -EINVAL;
}
-static struct notifier_block tdx_memory_nb = {
- .notifier_call = tdx_memory_notifier,
-};
-
static void __init check_tdx_erratum(void)
{
/*
@@ -1465,13 +1466,6 @@ void __init tdx_init(void)
return;
}
- err = register_memory_notifier(&tdx_memory_nb);
- if (err) {
- pr_err("initialization failed: register_memory_notifier() failed (%d)\n",
- err);
- return;
- }
-
#if defined(CONFIG_ACPI) && defined(CONFIG_SUSPEND)
pr_info("Disable ACPI S3. Turn off TDX in the BIOS to use ACPI S3.\n");
acpi_suspend_lowlevel = NULL;
@@ -140,6 +140,9 @@ extern int try_online_node(int nid);
extern int arch_add_memory(int nid, u64 start, u64 size,
struct mhp_params *params);
+
+extern int arch_check_hotplug_memory_range(u64 start, u64 size);
+
extern u64 max_mem_size;
extern int mhp_online_type_from_str(const char *str);
@@ -1305,6 +1305,11 @@ int try_online_node(int nid)
return ret;
}
+int __weak arch_check_hotplug_memory_range(u64 start, u64 size)
+{
+ return 0;
+}
+
static int check_hotplug_memory_range(u64 start, u64 size)
{
/* memory range must be block size aligned */
@@ -1315,7 +1320,7 @@ static int check_hotplug_memory_range(u64 start, u64 size)
return -EINVAL;
}
- return 0;
+ return arch_check_hotplug_memory_range(start, size);
}
static int online_memory_block(struct memory_block *mem, void *arg)