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>,
	Arnd Bergmann <arnd@arndb.de>
Cc: The AWS Nitro Enclaves Team <aws-nitro-enclaves-devel@amazon.com>,
	"Shuah Khan" <skhan@linuxfoundation.org>,
	Randy Dunlap <rdunlap@infradead.org>,
	Marek Szyprowski <m.szyprowski@samsung.com>,
	Robin Murphy <robin.murphy@arm.com>, <linux-doc@vger.kernel.org>,
	<iommu@lists.linux.dev>,
	Andrew Morton <akpm@linux-foundation.org>,
	David Hildenbrand <david@kernel.org>,
	Mike Rapoport <rppt@kernel.org>, <nh-open-source@amazon.com>,
	<linux-mm@kvack.org>, Jonathan Corbet <corbet@lwn.net>
Subject: [PATCH 37/40] nitro_enclaves: Add NE_ENCLAVE_CPU_OVERCOMMIT_MODE
Date: Wed, 11 Nov 2026 22:59:41 +0000	[thread overview]
Message-ID: <58469275b84367e8a49ae9975df231abc26234ea.1794393491.git.graf@amazon.com> (raw)
In-Reply-To: <cover.1794300002.git.graf@amazon.com>

Nitro Sandboxes relax the dedicated-vCPU requirement and allow a sandbox
to opt-in to CPU overcommitment. When active, the hypervisor performs
vCPU scheduling of sandbox vCPUs (vCores really) on top of the parent's
vCPUs.

Add the NE_ENCLAVE_CPU_OVERCOMMIT_MODE flag and relax the dedicated CPU
validation and pooling logic when the mode is active.

Signed-off-by: Alexander Graf <graf@amazon.com>
---
 Documentation/virt/ne_overview.rst        |  15 +-
 drivers/virt/nitro_enclaves/ne_misc_dev.c | 249 ++++++++++++++++++++--
 drivers/virt/nitro_enclaves/ne_misc_dev.h |   1 +
 include/uapi/linux/nitro_enclaves.h       |  45 +++-
 4 files changed, 283 insertions(+), 27 deletions(-)

diff --git a/Documentation/virt/ne_overview.rst b/Documentation/virt/ne_overview.rst
index 5984fd32ec07a..3aa33d3f06cf2 100644
--- a/Documentation/virt/ne_overview.rst
+++ b/Documentation/virt/ne_overview.rst
@@ -113,10 +113,23 @@ each node in turn, and sets numa_node to NE_NUMA_ANY when it does not
 care. Both start from a free thread of a core the enclave already holds,
 and only take a new core once there is none.
 
+A slot allocated with NE_ENCLAVE_CPU_OVERCOMMIT_MODE has its vCPUs
+scheduled by the host alongside the parent's own and takes no core out of
+the pool, so the pool is not consulted for it. Both NE_ADD_VCPU and
+NE_ADD_ANY_VCPU choose an id the enclave does not hold yet, and the host
+schedules the vCPU alongside the parent CPU that id names, so the node
+NE_ADD_ANY_VCPU takes still places it, and a node with no free id left
+fails the request. Both prefer a free id whose SMT sibling the enclave
+already holds, so its vCPUs share cores as they do with a pool, and
+otherwise take the lowest free id. A parent that never set a pool up runs
+such an enclave.
+
 The node says where cores come from. NE_ALLOC_MEMORY takes its own node;
 see `Memory pool`_. An enclave built out of a pool that spans
 nodes has no node of its own, so the rule that its memory be on that node
-does not apply to it and its memory can come from any node.
+does not apply to it and its memory can come from any node. A slot
+allocated with NE_ENCLAVE_CPU_OVERCOMMIT_MODE holds no core at all, so it
+has no node of its own either.
 
 The pool occupancy is readable under
 /sys/devices/virtual/misc/nitro_enclaves/cpu_pool/, and per node under
diff --git a/drivers/virt/nitro_enclaves/ne_misc_dev.c b/drivers/virt/nitro_enclaves/ne_misc_dev.c
index 870b3a6368cf9..e79740eac6f29 100644
--- a/drivers/virt/nitro_enclaves/ne_misc_dev.c
+++ b/drivers/virt/nitro_enclaves/ne_misc_dev.c
@@ -267,6 +267,12 @@ static const struct kernel_param *ne_cpus_kp;
  *				ne_setup_cpu_pool() offlines them, because
  *				cpu_to_node() is not documented to answer for an
  *				offline CPU.
+ * @core_cpus:			The threads of each core slot, indexed the same
+ *				way as @avail_threads_per_core. Unlike that
+ *				array it does not change while the pool is set
+ *				up, so it names the SMT siblings of a pool CPU
+ *				while the CPU is offline and
+ *				topology_sibling_cpumask() no longer names them.
  * @node_cpus:			The threads of the pool on each NUMA node, indexed
  *				by node id and sized by nr_node_ids. It partitions
  *				@total_cpus: a thread sits in the entry of the node
@@ -292,6 +298,7 @@ struct ne_cpu_pool {
 	unsigned int	nr_parent_vm_cores;
 	int		numa_node;
 	int		*core_nid;
+	cpumask_var_t	*core_cpus;
 	cpumask_var_t	*node_cpus;
 	struct cpumask	total_cpus;
 	struct cpumask	used_cpus;
@@ -656,6 +663,14 @@ static void ne_free_core_slots(void)
 	kfree(ne_cpu_pool.core_nid);
 	ne_cpu_pool.core_nid = NULL;
 
+	if (ne_cpu_pool.core_cpus) {
+		for (i = 0; i < ne_cpu_pool.nr_parent_vm_cores; i++)
+			free_cpumask_var(ne_cpu_pool.core_cpus[i]);
+
+		kfree(ne_cpu_pool.core_cpus);
+		ne_cpu_pool.core_cpus = NULL;
+	}
+
 	if (ne_cpu_pool.node_cpus) {
 		for (nid = 0; nid < nr_node_ids; nid++)
 			free_cpumask_var(ne_cpu_pool.node_cpus[nid]);
@@ -719,6 +734,10 @@ static int ne_build_core_slots(const struct cpumask *cpu_pool)
 	if (!ne_cpu_pool.core_nid)
 		goto free_slots;
 
+	ne_cpu_pool.core_cpus = kzalloc_objs(*ne_cpu_pool.core_cpus, nr_cores);
+	if (!ne_cpu_pool.core_cpus)
+		goto free_slots;
+
 	ne_cpu_pool.node_cpus = kzalloc_objs(*ne_cpu_pool.node_cpus, nr_node_ids);
 	if (!ne_cpu_pool.node_cpus)
 		goto free_slots;
@@ -728,7 +747,8 @@ static int ne_build_core_slots(const struct cpumask *cpu_pool)
 			goto free_slots;
 
 	for (i = 0; i < nr_cores; i++)
-		if (!zalloc_cpumask_var(&ne_cpu_pool.avail_threads_per_core[i], GFP_KERNEL))
+		if (!zalloc_cpumask_var(&ne_cpu_pool.avail_threads_per_core[i], GFP_KERNEL) ||
+		    !zalloc_cpumask_var(&ne_cpu_pool.core_cpus[i], GFP_KERNEL))
 			goto free_slots;
 
 	cpumask_clear(processed);
@@ -746,6 +766,9 @@ static int ne_build_core_slots(const struct cpumask *cpu_pool)
 			cpumask_set_cpu(cpu_sibling, processed);
 		}
 
+		cpumask_copy(ne_cpu_pool.core_cpus[next_core_idx],
+			     ne_cpu_pool.avail_threads_per_core[next_core_idx]);
+
 		core_nid = cpu_to_node(cpu);
 
 		ne_cpu_pool.core_nid[next_core_idx] = core_nid;
@@ -1166,6 +1189,118 @@ static bool ne_donated_cpu(struct ne_enclave *ne_enclave, unsigned int cpu)
 	return false;
 }
 
+/**
+ * ne_cpu_pool_core() - Find the core slot of a CPU in the NE CPU pool.
+ * @cpu:	CPU to look up.
+ *
+ * Context: Process context. This function is called with the ne_cpu_pool mutex
+ *	    held.
+ * Return:
+ * * Index of the core slot that holds @cpu.
+ * * -1 if @cpu is not in the pool.
+ */
+static int ne_cpu_pool_core(unsigned int cpu)
+{
+	unsigned int i = 0;
+
+	if (!cpumask_test_cpu(cpu, &ne_cpu_pool.total_cpus))
+		return -1;
+
+	for (i = 0; i < ne_cpu_pool.nr_parent_vm_cores; i++)
+		if (cpumask_test_cpu(cpu, ne_cpu_pool.core_cpus[i]))
+			return i;
+
+	return -1;
+}
+
+/**
+ * ne_get_floating_vcpu_id() - Choose a vCPU id for a slot whose vCPUs the host
+ *				schedules.
+ * @ne_enclave :	Private data associated with the current enclave.
+ * @vcpu_id:		The chosen vCPU id, set on success.
+ * @lowest_id:		The lowest id the caller allows to be chosen.
+ * @nid:		The NUMA node the vCPU should land on, or NUMA_NO_NODE
+ *			for no preference.
+ *
+ * The host schedules such a vCPU wherever it schedules the parent's own
+ * threads, so no core is taken and there is no pool to take one out of. It
+ * reads the id as the parent CPU to schedule the vCPU alongside, so
+ * cpu_to_node() on the id says which node the vCPU lands on, and only a free
+ * id on @nid is chosen. A node with no free id fails instead of yielding an
+ * id on another node. Without NE_ENCLAVE_PCIE_NUMA_MODE the hypervisor
+ * refuses a slot whose vCPUs straddle nodes, and the caller would only learn
+ * that when it starts the enclave.
+ *
+ * A free id whose SMT sibling already holds one of the enclave's vCPUs comes
+ * first, so the vCPUs fill whole cores the way they do for a slot that takes
+ * its cores from the pool. Otherwise the lowest free id is chosen. The siblings
+ * and the node of a CPU in the NE CPU pool come from what the pool recorded
+ * while the CPU was online, because the pool may have taken it offline since.
+ * An id that is not a possible CPU names no host CPU and is only chosen when
+ * @nid is NUMA_NO_NODE.
+ *
+ * @lowest_id is 1 where the caller hands the id back in the same word it
+ * read the request from, since zero is the request there.
+ *
+ * Context: Process context. This function is called with the ne_enclave mutex held.
+ * Return:
+ * * 0 on success.
+ * * Negative return value on failure.
+ */
+static int ne_get_floating_vcpu_id(struct ne_enclave *ne_enclave, u32 *vcpu_id,
+				   unsigned int lowest_id, int nid)
+{
+	const struct cpumask *siblings;
+	unsigned int first = nr_cpu_ids;
+	unsigned int cpu;
+	int core;
+
+	mutex_lock(&ne_cpu_pool.mutex);
+
+	for (cpu = lowest_id; cpu < nr_cpu_ids; cpu++) {
+		if (cpumask_test_cpu(cpu, ne_enclave->vcpu_ids))
+			continue;
+
+		if (!cpu_possible(cpu)) {
+			if (nid != NUMA_NO_NODE)
+				continue;
+
+			if (first == nr_cpu_ids)
+				first = cpu;
+
+			continue;
+		}
+
+		core = ne_cpu_pool_core(cpu);
+		if (core >= 0)
+			siblings = ne_cpu_pool.core_cpus[core];
+		else
+			siblings = topology_sibling_cpumask(cpu);
+
+		if (nid != NUMA_NO_NODE &&
+		    (core >= 0 ? ne_cpu_pool.core_nid[core] : cpu_to_node(cpu)) != nid)
+			continue;
+
+		if (first == nr_cpu_ids)
+			first = cpu;
+
+		if (cpumask_intersects(ne_enclave->vcpu_ids, siblings))
+			break;
+	}
+
+	mutex_unlock(&ne_cpu_pool.mutex);
+
+	if (cpu >= nr_cpu_ids)
+		cpu = first;
+
+	if (cpu >= nr_cpu_ids)
+		return -NE_ERR_INVALID_VCPU;
+
+	*vcpu_id = cpu;
+
+	return 0;
+}
+
 /**
  * ne_get_unused_core_from_cpu_pool() - Get the id of a full core from the
  *					NE CPU pool.
@@ -2578,7 +2713,37 @@ static long ne_enclave_do_ioctl(struct file *file, unsigned int cmd, unsigned lo
 			return -NE_ERR_INVALID_VCPU;
 		}
 
-		if (!vcpu_id) {
+		if (ne_enclave->launch_flags & NE_ENCLAVE_CPU_OVERCOMMIT_MODE) {
+			/*
+			 * The pool hands out the parent VM cores a slot runs
+			 * its vCPUs on, and a slot the host schedules the vCPUs
+			 * of takes none, so the pool is not consulted for it.
+			 * An id of zero asks this kernel to choose, as it does
+			 * for any other slot; an enclave still cannot be given
+			 * the same id twice.
+			 */
+			if (!vcpu_id) {
+				rc = ne_get_floating_vcpu_id(ne_enclave, &vcpu_id,
+							     1, NUMA_NO_NODE);
+				if (rc < 0) {
+					dev_err_ratelimited(ne_misc_dev.this_device,
+							    "Error in choosing a vCPU id [rc=%d]\n",
+							    rc);
+
+					mutex_unlock(&ne_enclave->enclave_info_mutex);
+
+					return rc;
+				}
+			} else if (ne_donated_cpu(ne_enclave, vcpu_id)) {
+				dev_err_ratelimited(ne_misc_dev.this_device,
+						    "CPU %d already used\n",
+						    vcpu_id);
+
+				mutex_unlock(&ne_enclave->enclave_info_mutex);
+
+				return -NE_ERR_VCPU_ALREADY_USED;
+			}
+		} else if (!vcpu_id) {
 			/* Use the CPU pool for choosing a CPU for the enclave. */
 			rc = ne_get_cpu_from_cpu_pool(ne_enclave, &vcpu_id,
 						      NUMA_NO_NODE);
@@ -2823,15 +2988,38 @@ static long ne_enclave_do_ioctl(struct file *file, unsigned int cmd, unsigned lo
 			return -NE_ERR_NOT_IN_INIT_STATE;
 		}
 
-		rc = ne_get_cpu_from_cpu_pool(ne_enclave, &vcpu_id, args.numa_node);
-		if (rc < 0) {
-			dev_err_ratelimited(ne_misc_dev.this_device,
-					    "Error in get CPU from pool [rc=%d node=%d]\n",
-					    rc, args.numa_node);
+		if (ne_enclave->launch_flags & NE_ENCLAVE_CPU_OVERCOMMIT_MODE) {
+			/*
+			 * The host schedules the vCPUs of such a slot wherever
+			 * it schedules the parent's own threads, so the slot
+			 * takes no core out of the pool and the pool is not
+			 * consulted for it. It reads the id as the parent CPU
+			 * to schedule the vCPU alongside, so @numa_node still
+			 * says which node the vCPU lands on and the id is
+			 * chosen to match it.
+			 */
+			rc = ne_get_floating_vcpu_id(ne_enclave, &vcpu_id, 0,
+						     args.numa_node);
+			if (rc < 0) {
+				dev_err_ratelimited(ne_misc_dev.this_device,
+						    "Error in choosing a vCPU id [rc=%d]\n",
+						    rc);
 
-			mutex_unlock(&ne_enclave->enclave_info_mutex);
+				mutex_unlock(&ne_enclave->enclave_info_mutex);
 
-			return rc;
+				return rc;
+			}
+		} else {
+			rc = ne_get_cpu_from_cpu_pool(ne_enclave, &vcpu_id, args.numa_node);
+			if (rc < 0) {
+				dev_err_ratelimited(ne_misc_dev.this_device,
+						    "Error in get CPU from pool [rc=%d node=%d]\n",
+						    rc, args.numa_node);
+
+				mutex_unlock(&ne_enclave->enclave_info_mutex);
+
+				return rc;
+			}
 		}
 
 		rc = ne_add_vcpu_ioctl(ne_enclave, vcpu_id);
@@ -3433,22 +3621,31 @@ static int ne_create_vm_ioctl(struct ne_pci_dev *ne_pci_dev, u64 flags,
 		slot_alloc_req.flags = flags;
 	}
 
-	mutex_lock(&ne_cpu_pool.mutex);
+	/*
+	 * The pool hands out the cores a slot runs its vCPUs on, and it has
+	 * none left once every core in it has had its threads taken, which is
+	 * also where a parent that never set one up starts. A slot the host
+	 * schedules the vCPUs of takes no core out of the pool, so what the
+	 * pool has left says nothing about it.
+	 */
+	if (!(flags & NE_ENCLAVE_CPU_OVERCOMMIT_MODE)) {
+		mutex_lock(&ne_cpu_pool.mutex);
 
-	for (i = 0; i < ne_cpu_pool.nr_parent_vm_cores; i++)
-		if (!cpumask_empty(ne_cpu_pool.avail_threads_per_core[i]))
-			break;
+		for (i = 0; i < ne_cpu_pool.nr_parent_vm_cores; i++)
+			if (!cpumask_empty(ne_cpu_pool.avail_threads_per_core[i]))
+				break;
 
-	if (i == ne_cpu_pool.nr_parent_vm_cores) {
-		dev_err_ratelimited(ne_misc_dev.this_device,
-				    "No CPUs available in CPU pool\n");
+		if (i == ne_cpu_pool.nr_parent_vm_cores) {
+			dev_err_ratelimited(ne_misc_dev.this_device,
+					    "No CPUs available in CPU pool\n");
 
-		mutex_unlock(&ne_cpu_pool.mutex);
+			mutex_unlock(&ne_cpu_pool.mutex);
 
-		return -NE_ERR_NO_CPUS_AVAIL_IN_POOL;
-	}
+			return -NE_ERR_NO_CPUS_AVAIL_IN_POOL;
+		}
 
-	mutex_unlock(&ne_cpu_pool.mutex);
+		mutex_unlock(&ne_cpu_pool.mutex);
+	}
 
 	ne_enclave = kzalloc_obj(*ne_enclave);
 	if (!ne_enclave)
@@ -3459,7 +3656,17 @@ static int ne_create_vm_ioctl(struct ne_pci_dev *ne_pci_dev, u64 flags,
 	mutex_lock(&ne_cpu_pool.mutex);
 
 	ne_enclave->nr_parent_vm_cores = ne_cpu_pool.nr_parent_vm_cores;
-	ne_enclave->numa_node = ne_cpu_pool.numa_node;
+
+	/*
+	 * The node an enclave takes its memory from is the node its cores
+	 * are on. A slot the host schedules the vCPUs of holds no core, so
+	 * it has no node of its own and its memory can come from any of
+	 * them.
+	 */
+	if (flags & NE_ENCLAVE_CPU_OVERCOMMIT_MODE)
+		ne_enclave->numa_node = NUMA_NO_NODE;
+	else
+		ne_enclave->numa_node = ne_cpu_pool.numa_node;
 
 	mutex_unlock(&ne_cpu_pool.mutex);
 
diff --git a/drivers/virt/nitro_enclaves/ne_misc_dev.h b/drivers/virt/nitro_enclaves/ne_misc_dev.h
index ed1b29997e1bb..f18b57a225325 100644
--- a/drivers/virt/nitro_enclaves/ne_misc_dev.h
+++ b/drivers/virt/nitro_enclaves/ne_misc_dev.h
@@ -27,6 +27,7 @@
 					 NE_ENCLAVE_PCIE_VSOCK_MODE | \
 					 NE_ENCLAVE_PCIE_VIRTIO_MODE | \
 					 NE_ENCLAVE_PCIE_HOTPLUG_MODE | \
+					 NE_ENCLAVE_CPU_OVERCOMMIT_MODE | \
 					 NE_ENCLAVE_PCIE_NUMA_MODE)
 
 struct cma;
diff --git a/include/uapi/linux/nitro_enclaves.h b/include/uapi/linux/nitro_enclaves.h
index f204d0f6e7efd..bfe1ca5ef7f7f 100644
--- a/include/uapi/linux/nitro_enclaves.h
+++ b/include/uapi/linux/nitro_enclaves.h
@@ -96,6 +96,21 @@
  */
 #define NE_ENCLAVE_PCIE_HOTPLUG_MODE	(1u << 8)
 
+/**
+ * NE_ENCLAVE_CPU_OVERCOMMIT_MODE - Allocate a slot whose vCPUs the host
+ *				    schedules alongside the parent's own,
+ *				    instead of running them on cores taken out
+ *				    of the NE CPU pool. The pool is not consulted
+ *				    for such a slot: %NE_ADD_VCPU and
+ *				    %NE_ADD_ANY_VCPU both choose an id the enclave
+ *				    does not hold yet, and the host schedules the
+ *				    vCPU alongside the parent CPU that id names.
+ *				    Requires
+ *				    NE_ENCLAVE_PCIE_MODE and
+ *				    NE_ENCLAVE_PCIE_VIRTIO_MODE.
+ */
+#define NE_ENCLAVE_CPU_OVERCOMMIT_MODE	(1u << 11)
+
 /**
  * NE_ENCLAVE_PCIE_NUMA_MODE - Allocate a slot whose memory and vCPUs may come
  *			       from more than one host NUMA node. Without it the
@@ -162,7 +177,9 @@ struct ne_create_vm_args {
  * * ENOMEM				- Memory allocation failure for internal
  *					  bookkeeping variables.
  * * NE_ERR_NO_CPUS_AVAIL_IN_POOL	- No NE CPU pool set / no CPUs available
- *					  in the pool.
+ *					  in the pool, for a slot allocated
+ *					  without
+ *					  %NE_ENCLAVE_CPU_OVERCOMMIT_MODE.
  * * Error codes from get_unused_fd_flags() and anon_inode_getfile().
  * * Error codes from the NE PCI device request.
  */
@@ -177,7 +194,12 @@ struct ne_create_vm_args {
  *		 one enclave can be from different nodes.
  *		 The vCPU id is an input / output parameter. If its value is 0,
  *		 then a CPU is chosen from the enclave CPU pool and returned via
- *		 this parameter.
+ *		 this parameter. A slot allocated with
+ *		 %NE_ENCLAVE_CPU_OVERCOMMIT_MODE takes no CPU out of the pool,
+ *		 so the pool is not consulted for it: an id of 0 asks this
+ *		 kernel for one the enclave does not hold yet, preferring an
+ *		 id whose SMT sibling the enclave already holds, and the id
+ *		 it chooses is never 0.
  *		 The ioctl can be invoked on the enclave fd, before an enclave
  *		 is started.
  *
@@ -200,7 +222,9 @@ struct ne_create_vm_args {
  * * NE_ERR_NOT_IN_INIT_STATE		- The enclave is not in init state
  *					  (init = before being started).
  * * NE_ERR_INVALID_VCPU		- The provided vCPU is not in the available
- *					  CPUs range.
+ *					  CPUs range, or the slot was allocated
+ *					  with %NE_ENCLAVE_CPU_OVERCOMMIT_MODE and
+ *					  every id is taken.
  * * Error codes from the NE PCI device request.
  */
 #define NE_ADD_VCPU			_IOWR(0xAE, 0x21, __u32)
@@ -208,7 +232,9 @@ struct ne_create_vm_args {
 /**
  * struct ne_add_any_vcpu_args - Argument for %NE_ADD_ANY_VCPU.
  * @numa_node:	The NUMA node the vCPU has to come from, or %NE_NUMA_ANY for
- *		any node.
+ *		any node. For a slot allocated with
+ *		%NE_ENCLAVE_CPU_OVERCOMMIT_MODE it is the node the host
+ *		should schedule the vCPU on.
  * @vcpu_id:	The vCPU id the kernel chose, set on success. Ignored on
  *		input.
  */
@@ -231,7 +257,13 @@ struct ne_add_any_vcpu_args {
  *		     for each node in turn and stops when a node runs out.
  *		     @vcpu_id carries back the vCPU id the kernel chose, so
  *		     a caller collects the enclave's vCPU set as it builds
- *		     it.
+ *		     it. For a slot allocated with
+ *		     %NE_ENCLAVE_CPU_OVERCOMMIT_MODE the host schedules the
+ *		     vCPU rather than a core out of the pool running it, so
+ *		     the pool is not consulted and the chosen id is the
+ *		     parent CPU the host schedules it alongside. The kernel
+ *		     prefers an id whose SMT sibling the enclave already
+ *		     holds.
  *		     The ioctl can be invoked on the enclave fd, before an
  *		     enclave is started.
  *
@@ -251,6 +283,9 @@ struct ne_add_any_vcpu_args {
  *				  about and the excess is not all zero.
  * * NE_ERR_NOT_IN_INIT_STATE	- The enclave is not in init state (init =
  *				  before being started).
+ * * NE_ERR_INVALID_VCPU	- The slot was allocated with
+ *				  %NE_ENCLAVE_CPU_OVERCOMMIT_MODE and every id
+ *				  on @numa_node is taken.
  * * NE_ERR_NO_CPUS_AVAIL_IN_POOL - No CPUs available in the NE CPU pool on
  *				  @numa_node.
  * * NE_ERR_VCPU_INVALID_CPU_CORE - The core the pool handed back is outside
-- 
2.47.1


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

Thread overview: 41+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-11-11 22:41 [PATCH 00/40] nitro_enclaves: Add support for Nitro Sandboxes Alexander Graf
2026-11-11 22:41 ` [PATCH 01/40] nitro_enclaves: Allow the CPU pool to span NUMA nodes Alexander Graf
2026-11-11 22:41 ` [PATCH 02/40] nitro_enclaves: Add NE_ADD_ANY_VCPU Alexander Graf
2026-11-11 22:41 ` [PATCH 03/40] nitro_enclaves: Expose CPU pool state under sysfs Alexander Graf
2026-11-11 22:41 ` [PATCH 04/40] nitro_enclaves: Document multi-NUMA CPU pools Alexander Graf
2026-11-11 22:41 ` [PATCH 05/40] dma-contiguous: add dma_get_numa_cma_area() accessor Alexander Graf
2026-11-11 22:41 ` [PATCH 06/40] nitro_enclaves: Add NE_ALLOC_MEMORY ioctl Alexander Graf
2026-11-11 22:41 ` [PATCH 07/40] nitro_enclaves: Add NE_MEMORY_SHARED Alexander Graf
2026-11-11 22:41 ` [PATCH 08/40] nitro_enclaves: Add NE_ADD_MEMORY_REGION Alexander Graf
2026-11-11 22:41 ` [PATCH 09/40] nitro_enclaves: Document the memory pool Alexander Graf
2026-11-11 22:41 ` [PATCH 10/40] nitro_enclaves: Add NE_CREATE_VM2 with a launch flag word Alexander Graf
2026-11-11 22:41 ` [PATCH 11/40] nitro_enclaves: Add NE_ENCLAVE_PCIE_MODE launch flag Alexander Graf
2026-11-11 22:41 ` [PATCH 12/40] nitro_enclaves: Name the device's error codes in the UAPI header Alexander Graf
2026-11-11 22:41 ` [PATCH 13/40] nitro_enclaves: Log a reached device limit at info level Alexander Graf
2026-11-11 22:56 ` [PATCH 14/40] nitro_enclaves: Add NE_SET_INFO_PAGE Alexander Graf
2026-11-11 22:59 ` [PATCH 15/40] nitro_enclaves: Document the info page in the memory pool Alexander Graf
2026-11-11 22:59 ` [PATCH 16/40] nitro_enclaves: Turn the command reply into a per-command union Alexander Graf
2026-11-11 22:59 ` [PATCH 17/40] nitro_enclaves: Add the slot pool donation commands Alexander Graf
2026-11-11 22:59 ` [PATCH 18/40] nitro_enclaves: Donate memory for the slot pool Alexander Graf
2026-11-11 22:59 ` [PATCH 19/40] nitro_enclaves: Add the slot pool growth commands Alexander Graf
2026-11-11 22:59 ` [PATCH 20/40] nitro_enclaves: Add a helper to grow the slot pool Alexander Graf
2026-11-11 22:59 ` [PATCH 21/40] nitro_enclaves: Document " Alexander Graf
2026-11-11 22:59 ` [PATCH 22/40] nitro_enclaves: Expose slot pool state under sysfs Alexander Graf
2026-11-11 22:59 ` [PATCH 23/40] nitro_enclaves: Add the device add command Alexander Graf
2026-11-11 22:59 ` [PATCH 24/40] nitro_enclaves: Add NE_ADD_DEVICE Alexander Graf
2026-11-11 22:59 ` [PATCH 25/40] nitro_enclaves: Read the interrupt multiplexer geometry at probe Alexander Graf
2026-11-11 22:59 ` [PATCH 26/40] nitro_enclaves: Donate a bitmap page per multiplexed vector Alexander Graf
2026-11-11 22:59 ` [PATCH 27/40] nitro_enclaves: Dispatch multiplexed interrupts to per-queue bindings Alexander Graf
2026-11-11 22:59 ` [PATCH 28/40] nitro_enclaves: Add NE_SET_NOTIFY_EVENTFD Alexander Graf
2026-11-11 22:59 ` [PATCH 29/40] nitro_enclaves: Report the device's info notification Alexander Graf
2026-11-11 22:59 ` [PATCH 30/40] nitro_enclaves: Count multiplexed interrupts under debugfs Alexander Graf
2026-11-11 22:59 ` [PATCH 31/40] nitro_enclaves: Map the doorbell window at probe Alexander Graf
2026-11-11 22:59 ` [PATCH 32/40] nitro_enclaves: Add NE_SET_VRING_CALL Alexander Graf
2026-11-11 22:59 ` [PATCH 33/40] nitro_enclaves: Assert the layout of the ioctl argument structs Alexander Graf
2026-11-11 22:59 ` [PATCH 34/40] nitro_enclaves: Pass on the Nitro Sandbox launch flags Alexander Graf
2026-11-11 22:59 ` [PATCH 35/40] nitro_enclaves: Add NE_ENCLAVE_DIRECT_MODE Alexander Graf
2026-11-11 22:59 ` [PATCH 36/40] nitro_enclaves: Add NE_ENCLAVE_PCIE_HOTPLUG_MODE Alexander Graf
2026-11-11 22:59 ` Alexander Graf [this message]
2026-11-11 22:59 ` [PATCH 38/40] nitro_enclaves: Add NE_GET_CAPS Alexander Graf
2026-11-11 22:59 ` [PATCH 39/40] nitro_enclaves: Add NE_UPDATE_DEVICE_CONFIG Alexander Graf
2026-11-11 22:59 ` [PATCH 40/40] nitro_enclaves: Document the driver side of Nitro Sandboxes 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=58469275b84367e8a49ae9975df231abc26234ea.1794393491.git.graf@amazon.com \
    --to=graf@amazon.com \
    --cc=akpm@linux-foundation.org \
    --cc=arnd@arndb.de \
    --cc=aws-nitro-enclaves-devel@amazon.com \
    --cc=corbet@lwn.net \
    --cc=david@kernel.org \
    --cc=gregkh@linuxfoundation.org \
    --cc=iommu@lists.linux.dev \
    --cc=linux-doc@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-mm@kvack.org \
    --cc=m.szyprowski@samsung.com \
    --cc=nh-open-source@amazon.com \
    --cc=rdunlap@infradead.org \
    --cc=robin.murphy@arm.com \
    --cc=rppt@kernel.org \
    --cc=skhan@linuxfoundation.org \
    /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®