mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Alexander Graf <graf@amazon.com>
To: <linux-kernel@vger.kernel.org>,
	Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Arnd Bergmann <arnd@arndb.de>, <nh-open-source@amazon.com>,
	"The AWS Nitro Enclaves Team"
	<aws-nitro-enclaves-devel@amazon.com>
Subject: [PATCH 11/19] nitro_enclaves: Keep the CPU pool when the new CPU list does not parse
Date: Thu, 12 Nov 2026 03:07:07 +0000	[thread overview]
Message-ID: <6906689236135feecc54366f7795f5c812dc0ce5.1794393487.git.graf@amazon.com> (raw)
In-Reply-To: <cover.1794300000.git.graf@amazon.com>

An admin who mistypes a CPU list into ne_cpus loses the pool that was
there, because ne_set_kernel_param() tears the pool down before
ne_setup_cpu_pool() parses the new value. The write fails, but the
pool's CPUs come back online and ne_cpus reads empty.

Parse the list before the teardown and pass the mask down. The other
checks stay after the teardown, because they want every CPU of the list
online, and a list that extends the current pool names offline CPUs.

Fixes: ff8a4d3e3a99 ("nitro_enclaves: Add logic for setting an enclave vCPU")
Signed-off-by: Alexander Graf <graf@amazon.com>
---
 drivers/virt/nitro_enclaves/ne_misc_dev.c | 58 ++++++++++++-----------
 1 file changed, 31 insertions(+), 27 deletions(-)

diff --git a/drivers/virt/nitro_enclaves/ne_misc_dev.c b/drivers/virt/nitro_enclaves/ne_misc_dev.c
index 1c2a4994257d1..de3bf93a4ef0f 100644
--- a/drivers/virt/nitro_enclaves/ne_misc_dev.c
+++ b/drivers/virt/nitro_enclaves/ne_misc_dev.c
@@ -143,7 +143,7 @@ struct ne_phys_contig_mem_regions {
  *			 or not using CPU 0, which should remain available for
  *			 the primary / parent VM. Offline the CPUs from the
  *			 pool after the checks passed.
- * @ne_cpu_list:	The CPU list used for setting NE CPU pool.
+ * @cpu_pool:	The CPU mask used for setting NE CPU pool.
  *
  * Context: Process context. This function is called with the ne_pci_dev enclave
  *	    mutex held, if there is a NE PCI device.
@@ -151,35 +151,24 @@ struct ne_phys_contig_mem_regions {
  * * 0 on success.
  * * Negative return value on failure.
  */
-static int ne_setup_cpu_pool(const char *ne_cpu_list)
+static int ne_setup_cpu_pool(const struct cpumask *cpu_pool)
 {
 	int core_id = -1;
 	unsigned int cpu = 0;
-	cpumask_var_t cpu_pool;
 	unsigned int cpu_sibling = 0;
 	unsigned int i = 0;
 	int numa_node = -1;
 	int rc = -EINVAL;
 
-	if (!zalloc_cpumask_var(&cpu_pool, GFP_KERNEL))
-		return -ENOMEM;
-
 	mutex_lock(&ne_cpu_pool.mutex);
 
-	rc = cpulist_parse(ne_cpu_list, cpu_pool);
-	if (rc < 0) {
-		pr_err("%s: Error in cpulist parse [rc=%d]\n", ne_misc_dev.name, rc);
-
-		goto free_pool_cpumask;
-	}
-
 	cpu = cpumask_any(cpu_pool);
 	if (cpu >= nr_cpu_ids) {
 		pr_err("%s: No CPUs available in CPU pool\n", ne_misc_dev.name);
 
 		rc = -EINVAL;
 
-		goto free_pool_cpumask;
+		goto reset_cpu_pool;
 	}
 
 	/*
@@ -193,7 +182,7 @@ static int ne_setup_cpu_pool(const char *ne_cpu_list)
 
 			rc = -EINVAL;
 
-			goto free_pool_cpumask;
+			goto reset_cpu_pool;
 		}
 
 	/*
@@ -208,7 +197,7 @@ static int ne_setup_cpu_pool(const char *ne_cpu_list)
 
 				rc = -EINVAL;
 
-				goto free_pool_cpumask;
+				goto reset_cpu_pool;
 			}
 		} else {
 			if (numa_node != cpu_to_node(cpu)) {
@@ -217,7 +206,7 @@ static int ne_setup_cpu_pool(const char *ne_cpu_list)
 
 				rc = -EINVAL;
 
-				goto free_pool_cpumask;
+				goto reset_cpu_pool;
 			}
 		}
 
@@ -230,7 +219,7 @@ static int ne_setup_cpu_pool(const char *ne_cpu_list)
 
 		rc = -EINVAL;
 
-		goto free_pool_cpumask;
+		goto reset_cpu_pool;
 	}
 
 	for_each_cpu(cpu_sibling, topology_sibling_cpumask(0)) {
@@ -240,7 +229,7 @@ static int ne_setup_cpu_pool(const char *ne_cpu_list)
 
 			rc = -EINVAL;
 
-			goto free_pool_cpumask;
+			goto reset_cpu_pool;
 		}
 	}
 
@@ -257,7 +246,7 @@ static int ne_setup_cpu_pool(const char *ne_cpu_list)
 
 				rc = -EINVAL;
 
-				goto free_pool_cpumask;
+				goto reset_cpu_pool;
 			}
 		}
 	}
@@ -274,7 +263,7 @@ static int ne_setup_cpu_pool(const char *ne_cpu_list)
 	if (!ne_cpu_pool.avail_threads_per_core) {
 		rc = -ENOMEM;
 
-		goto free_pool_cpumask;
+		goto reset_cpu_pool;
 	}
 
 	for (i = 0; i < ne_cpu_pool.nr_parent_vm_cores; i++)
@@ -325,8 +314,6 @@ static int ne_setup_cpu_pool(const char *ne_cpu_list)
 		}
 	}
 
-	free_cpumask_var(cpu_pool);
-
 	ne_cpu_pool.numa_node = numa_node;
 
 	mutex_unlock(&ne_cpu_pool.mutex);
@@ -343,8 +330,7 @@ static int ne_setup_cpu_pool(const char *ne_cpu_list)
 	for (i = 0; i < ne_cpu_pool.nr_parent_vm_cores; i++)
 		free_cpumask_var(ne_cpu_pool.avail_threads_per_core[i]);
 	kfree(ne_cpu_pool.avail_threads_per_core);
-free_pool_cpumask:
-	free_cpumask_var(cpu_pool);
+reset_cpu_pool:
 	ne_cpu_pool.nr_parent_vm_cores = 0;
 	ne_cpu_pool.nr_threads_per_core = 0;
 	ne_cpu_pool.numa_node = -1;
@@ -409,15 +395,19 @@ static void ne_teardown_cpu_pool(void)
 static int ne_set_kernel_param(const char *val, const struct kernel_param *kp)
 {
 	char error_val[] = "";
+	cpumask_var_t cpu_pool;
 	struct ne_pci_dev *ne_pci_dev = NULL;
 	int rc = -EINVAL;
 
 	if (!capable(CAP_SYS_ADMIN))
 		return -EPERM;
 
+	if (!zalloc_cpumask_var(&cpu_pool, GFP_KERNEL))
+		return -ENOMEM;
+
 	rc = down_read_killable(&ne_devs.lock);
 	if (rc)
-		return rc;
+		goto free_cpumasks;
 
 	ne_pci_dev = ne_devs.ne_pci_dev;
 
@@ -442,9 +432,20 @@ static int ne_set_kernel_param(const char *val, const struct kernel_param *kp)
 		goto unlock;
 	}
 
+	/*
+	 * Parse the list before the teardown below drops the pool the driver
+	 * already has, so that a value that does not parse leaves it in place.
+	 */
+	rc = cpulist_parse(val, cpu_pool);
+	if (rc < 0) {
+		pr_err("%s: Error in cpulist parse [rc=%d]\n", ne_misc_dev.name, rc);
+
+		goto unlock;
+	}
+
 	ne_teardown_cpu_pool();
 
-	rc = ne_setup_cpu_pool(val);
+	rc = ne_setup_cpu_pool(cpu_pool);
 	if (rc < 0) {
 		pr_err("%s: Error in setup CPU pool [rc=%d]\n", ne_misc_dev.name, rc);
 
@@ -469,6 +470,9 @@ static int ne_set_kernel_param(const char *val, const struct kernel_param *kp)
 unlock_devs:
 	up_read(&ne_devs.lock);
 
+free_cpumasks:
+	free_cpumask_var(cpu_pool);
+
 	return rc;
 }
 
-- 
2.47.1


  parent reply	other threads:[~2026-11-12  3:08 UTC|newest]

Thread overview: 20+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-11-11 13:49 [PATCH 00/19] nitro_enclaves: Fix enclave release, command retries and the CPU pool Alexander Graf
2026-11-11 13:49 ` [PATCH 01/19] nitro_enclaves: Release the reference on a rejected region page Alexander Graf
2026-11-11 13:49 ` [PATCH 02/19] nitro_enclaves: Split freeing the slot from freeing the enclave Alexander Graf
2026-11-11 13:49 ` [PATCH 03/19] nitro_enclaves: Ignore the reply of a failed slot info command Alexander Graf
2026-11-11 13:49 ` [PATCH 04/19] nitro_enclaves: Retry a command the device asks us to retry Alexander Graf
2026-11-11 13:49 ` [PATCH 05/19] nitro_enclaves: Stop sending commands to a broken device Alexander Graf
2026-11-11 13:49 ` [PATCH 06/19] nitro_enclaves: Set up the device state before requesting its interrupts Alexander Graf
2026-11-11 13:49 ` [PATCH 07/19] nitro_enclaves: Wait for file operations before unbinding the PCI device Alexander Graf
2026-11-12  3:07 ` [PATCH 08/19] nitro_enclaves: Let the region tracking arrays fall back to vmalloc Alexander Graf
2026-11-12  3:07 ` [PATCH 09/19] nitro_enclaves: Do not return enclave threads to a replaced CPU pool Alexander Graf
2026-11-12  3:07 ` [PATCH 10/19] nitro_enclaves: Do not report a torn down CPU pool as set Alexander Graf
2026-11-12  3:07 ` Alexander Graf [this message]
2026-11-12  3:07 ` [PATCH 12/19] nitro_enclaves: Put the CPU pool back when the new CPU list is refused Alexander Graf
2026-11-12  3:07 ` [PATCH 13/19] nitro_enclaves: Initialise the CPU pool mutex statically Alexander Graf
2026-11-12  3:07 ` [PATCH 14/19] nitro_enclaves: Build the boot-time CPU pool once the CPUs are online Alexander Graf
2026-11-12  3:07 ` [PATCH 15/19] nitro_enclaves: Set up the CPU pool under the CPU hotplug read lock Alexander Graf
2026-11-12  3:07 ` [PATCH 16/19] nitro_enclaves: Let 32-bit processes use the ioctl interface Alexander Graf
2026-11-12  3:07 ` [PATCH 17/19] nitro_enclaves: Index CPU pool cores by sibling mask Alexander Graf
2026-11-12  3:07 ` [PATCH 18/19] nitro_enclaves: Time the wait for the device to turn off by the clock Alexander Graf
2026-11-12  3:07 ` [PATCH 19/19] MAINTAINERS: Take over the Nitro Enclaves driver Alexander Graf

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=6906689236135feecc54366f7795f5c812dc0ce5.1794393487.git.graf@amazon.com \
    --to=graf@amazon.com \
    --cc=arnd@arndb.de \
    --cc=aws-nitro-enclaves-devel@amazon.com \
    --cc=gregkh@linuxfoundation.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=nh-open-source@amazon.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®