From patchwork Fri May 31 22:26:17 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Haitao Huang X-Patchwork-Id: 13682240 Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.15]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 890D580032; Fri, 31 May 2024 22:26:33 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.15 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1717194395; cv=none; b=JM5y45TaYa77OgpGJYNXQ981uo6TLqdyoMq59Ar/IwSgYr1AdBD/ooJ2Pdv/z/p/Hwc+P3fkWlVVRpFaCi0eWTcA+uXRO5zrMtu8S6nfrTopEMRB3xeJEbSMSPriEwCh3RSnb8672zVnvUhD/j3hjwzje286vjl1nZDLo7Ox0zk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1717194395; c=relaxed/simple; bh=4X530XTWe91d+vfeFhus02owSTog22R9aM2mY+OXuoQ=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=iAURiH9bRBTklghHdtjtPjYNegKzCR+q082ToDOk3FtzVdPFmVPory8QyQGEi7WsMpI97EahsKYnHOhfLDAwlN7sds/EUgJuvqB3RD1mEB5WolsNSvT/SCTd43w9888Tocv5EXC2VTDQIVD+GP22OhAOy2NnAhBfGJeaKZbEqFg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com; spf=none smtp.mailfrom=linux.intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=XiVVsMhE; arc=none smtp.client-ip=192.198.163.15 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; spf=none smtp.mailfrom=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="XiVVsMhE" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1717194394; x=1748730394; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=4X530XTWe91d+vfeFhus02owSTog22R9aM2mY+OXuoQ=; b=XiVVsMhEpFTFslwc5LQq9ncgwHMQIUTy8RaFQCedHItNYix9ZxUE+//T bn1rpm/HD7zoa/it9hi1GmmhCBUbFC949/zgApGAO/gU3BxyZ3i+MFRfV 8PvbxE7QG6U4P2SXcLJKUJrtZCf/7+prU5Ujt+PnuPqZz2JqoWHY8OGTG 58St/sof26cHizzngyj/Ff0pG+Gjh7I1xGxZNmRAB6NR3Ce9oUIT7v5bJ LKMgJbc2/zBLe24LOOBPF/yL94yl/7Zr/J4mFvi2AW3CTbHrcUJ3E/dOK sbPXW1Kd748UJ7bpyP3Cpdgc/zKFdxNeMztwYpoSjGPQD3S4ORVBAd3Ph A==; X-CSE-ConnectionGUID: oynmnmcCTiuGvSxANAyDLw== X-CSE-MsgGUID: CxivFo2gQfiVMsSJ0pXKlQ== X-IronPort-AV: E=McAfee;i="6600,9927,11089"; a="13949728" X-IronPort-AV: E=Sophos;i="6.08,205,1712646000"; d="scan'208";a="13949728" Received: from fmviesa005.fm.intel.com ([10.60.135.145]) by fmvoesa109.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 31 May 2024 15:26:32 -0700 X-CSE-ConnectionGUID: 7dQbuErPS6KshSwqoe/unQ== X-CSE-MsgGUID: rhSTct/eRQyEJEhJsnfhQw== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.08,205,1712646000"; d="scan'208";a="40736915" Received: from b4969161e530.jf.intel.com ([10.165.56.46]) by fmviesa005.fm.intel.com with ESMTP; 31 May 2024 15:26:31 -0700 From: Haitao Huang To: jarkko@kernel.org, dave.hansen@linux.intel.com, kai.huang@intel.com, tj@kernel.org, mkoutny@suse.com, linux-kernel@vger.kernel.org, linux-sgx@vger.kernel.org, x86@kernel.org, cgroups@vger.kernel.org, tglx@linutronix.de, mingo@redhat.com, bp@alien8.de, hpa@zytor.com, sohil.mehta@intel.com, tim.c.chen@linux.intel.com Cc: zhiquan1.li@intel.com, kristen@linux.intel.com, seanjc@google.com, zhanb@microsoft.com, anakrish@microsoft.com, mikko.ylinen@linux.intel.com, yangjie@microsoft.com, chrisyan@microsoft.com Subject: [PATCH v14 01/14] x86/sgx: Replace boolean parameters with enums Date: Fri, 31 May 2024 15:26:17 -0700 Message-Id: <20240531222630.4634-2-haitao.huang@linux.intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20240531222630.4634-1-haitao.huang@linux.intel.com> References: <20240531222630.4634-1-haitao.huang@linux.intel.com> Precedence: bulk X-Mailing-List: linux-sgx@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Replace boolean parameters for 'reclaim' in the function sgx_alloc_epc_page() and its callers with an enum. Also opportunistically remove non-static declaration of __sgx_alloc_epc_page() and a typo Signed-off-by: Haitao Huang Suggested-by: Jarkko Sakkinen Suggested-by: Dave Hansen Reviewed-by: Jarkko Sakkinen Reviewed-by: Kai Huang Tested-by: Jarkko Sakkinen --- arch/x86/kernel/cpu/sgx/encl.c | 12 ++++++------ arch/x86/kernel/cpu/sgx/encl.h | 4 ++-- arch/x86/kernel/cpu/sgx/ioctl.c | 10 +++++----- arch/x86/kernel/cpu/sgx/main.c | 14 +++++++------- arch/x86/kernel/cpu/sgx/sgx.h | 13 +++++++++++-- arch/x86/kernel/cpu/sgx/virt.c | 2 +- 6 files changed, 32 insertions(+), 23 deletions(-) diff --git a/arch/x86/kernel/cpu/sgx/encl.c b/arch/x86/kernel/cpu/sgx/encl.c index 279148e72459..f474179b6f77 100644 --- a/arch/x86/kernel/cpu/sgx/encl.c +++ b/arch/x86/kernel/cpu/sgx/encl.c @@ -217,7 +217,7 @@ static struct sgx_epc_page *sgx_encl_eldu(struct sgx_encl_page *encl_page, struct sgx_epc_page *epc_page; int ret; - epc_page = sgx_alloc_epc_page(encl_page, false); + epc_page = sgx_alloc_epc_page(encl_page, SGX_NO_RECLAIM); if (IS_ERR(epc_page)) return epc_page; @@ -359,14 +359,14 @@ static vm_fault_t sgx_encl_eaug_page(struct vm_area_struct *vma, goto err_out_unlock; } - epc_page = sgx_alloc_epc_page(encl_page, false); + epc_page = sgx_alloc_epc_page(encl_page, SGX_NO_RECLAIM); if (IS_ERR(epc_page)) { if (PTR_ERR(epc_page) == -EBUSY) vmret = VM_FAULT_NOPAGE; goto err_out_unlock; } - va_page = sgx_encl_grow(encl, false); + va_page = sgx_encl_grow(encl, SGX_NO_RECLAIM); if (IS_ERR(va_page)) { if (PTR_ERR(va_page) == -EBUSY) vmret = VM_FAULT_NOPAGE; @@ -1232,8 +1232,8 @@ void sgx_zap_enclave_ptes(struct sgx_encl *encl, unsigned long addr) /** * sgx_alloc_va_page() - Allocate a Version Array (VA) page - * @reclaim: Reclaim EPC pages directly if none available. Enclave - * mutex should not be held if this is set. + * @reclaim: Whether reclaim EPC pages directly if none available. Enclave + * mutex should not be held for SGX_DO_RECLAIM. * * Allocate a free EPC page and convert it to a Version Array (VA) page. * @@ -1241,7 +1241,7 @@ void sgx_zap_enclave_ptes(struct sgx_encl *encl, unsigned long addr) * a VA page, * -errno otherwise */ -struct sgx_epc_page *sgx_alloc_va_page(bool reclaim) +struct sgx_epc_page *sgx_alloc_va_page(enum sgx_reclaim reclaim) { struct sgx_epc_page *epc_page; int ret; diff --git a/arch/x86/kernel/cpu/sgx/encl.h b/arch/x86/kernel/cpu/sgx/encl.h index f94ff14c9486..fe15ade02ca1 100644 --- a/arch/x86/kernel/cpu/sgx/encl.h +++ b/arch/x86/kernel/cpu/sgx/encl.h @@ -116,14 +116,14 @@ struct sgx_encl_page *sgx_encl_page_alloc(struct sgx_encl *encl, unsigned long offset, u64 secinfo_flags); void sgx_zap_enclave_ptes(struct sgx_encl *encl, unsigned long addr); -struct sgx_epc_page *sgx_alloc_va_page(bool reclaim); +struct sgx_epc_page *sgx_alloc_va_page(enum sgx_reclaim reclaim); unsigned int sgx_alloc_va_slot(struct sgx_va_page *va_page); void sgx_free_va_slot(struct sgx_va_page *va_page, unsigned int offset); bool sgx_va_page_full(struct sgx_va_page *va_page); void sgx_encl_free_epc_page(struct sgx_epc_page *page); struct sgx_encl_page *sgx_encl_load_page(struct sgx_encl *encl, unsigned long addr); -struct sgx_va_page *sgx_encl_grow(struct sgx_encl *encl, bool reclaim); +struct sgx_va_page *sgx_encl_grow(struct sgx_encl *encl, enum sgx_reclaim reclaim); void sgx_encl_shrink(struct sgx_encl *encl, struct sgx_va_page *va_page); #endif /* _X86_ENCL_H */ diff --git a/arch/x86/kernel/cpu/sgx/ioctl.c b/arch/x86/kernel/cpu/sgx/ioctl.c index b65ab214bdf5..793a0ba2cb16 100644 --- a/arch/x86/kernel/cpu/sgx/ioctl.c +++ b/arch/x86/kernel/cpu/sgx/ioctl.c @@ -17,7 +17,7 @@ #include "encl.h" #include "encls.h" -struct sgx_va_page *sgx_encl_grow(struct sgx_encl *encl, bool reclaim) +struct sgx_va_page *sgx_encl_grow(struct sgx_encl *encl, enum sgx_reclaim reclaim) { struct sgx_va_page *va_page = NULL; void *err; @@ -64,7 +64,7 @@ static int sgx_encl_create(struct sgx_encl *encl, struct sgx_secs *secs) struct file *backing; long ret; - va_page = sgx_encl_grow(encl, true); + va_page = sgx_encl_grow(encl, SGX_DO_RECLAIM); if (IS_ERR(va_page)) return PTR_ERR(va_page); else if (va_page) @@ -83,7 +83,7 @@ static int sgx_encl_create(struct sgx_encl *encl, struct sgx_secs *secs) encl->backing = backing; - secs_epc = sgx_alloc_epc_page(&encl->secs, true); + secs_epc = sgx_alloc_epc_page(&encl->secs, SGX_DO_RECLAIM); if (IS_ERR(secs_epc)) { ret = PTR_ERR(secs_epc); goto err_out_backing; @@ -269,13 +269,13 @@ static int sgx_encl_add_page(struct sgx_encl *encl, unsigned long src, if (IS_ERR(encl_page)) return PTR_ERR(encl_page); - epc_page = sgx_alloc_epc_page(encl_page, true); + epc_page = sgx_alloc_epc_page(encl_page, SGX_DO_RECLAIM); if (IS_ERR(epc_page)) { kfree(encl_page); return PTR_ERR(epc_page); } - va_page = sgx_encl_grow(encl, true); + va_page = sgx_encl_grow(encl, SGX_DO_RECLAIM); if (IS_ERR(va_page)) { ret = PTR_ERR(va_page); goto err_out_free; diff --git a/arch/x86/kernel/cpu/sgx/main.c b/arch/x86/kernel/cpu/sgx/main.c index 27892e57c4ef..e64073fb4256 100644 --- a/arch/x86/kernel/cpu/sgx/main.c +++ b/arch/x86/kernel/cpu/sgx/main.c @@ -464,14 +464,14 @@ static struct sgx_epc_page *__sgx_alloc_epc_page_from_node(int nid) /** * __sgx_alloc_epc_page() - Allocate an EPC page * - * Iterate through NUMA nodes and reserve ia free EPC page to the caller. Start + * Iterate through NUMA nodes and reserve a free EPC page to the caller. Start * from the NUMA node, where the caller is executing. * * Return: * - an EPC page: A borrowed EPC pages were available. * - NULL: Out of EPC pages. */ -struct sgx_epc_page *__sgx_alloc_epc_page(void) +static struct sgx_epc_page *__sgx_alloc_epc_page(void) { struct sgx_epc_page *page; int nid_of_current = numa_node_id(); @@ -543,12 +543,12 @@ int sgx_unmark_page_reclaimable(struct sgx_epc_page *page) /** * sgx_alloc_epc_page() - Allocate an EPC page * @owner: the owner of the EPC page - * @reclaim: reclaim pages if necessary + * @reclaim: whether reclaim pages if necessary * * Iterate through EPC sections and borrow a free EPC page to the caller. When a * page is no longer needed it must be released with sgx_free_epc_page(). If - * @reclaim is set to true, directly reclaim pages when we are out of pages. No - * mm's can be locked when @reclaim is set to true. + * @reclaim is set to SGX_DO_RECLAIM, directly reclaim pages when we are out of + * pages. No mm's can be locked for SGX_DO_RECLAIM. * * Finally, wake up ksgxd when the number of pages goes below the watermark * before returning back to the caller. @@ -557,7 +557,7 @@ int sgx_unmark_page_reclaimable(struct sgx_epc_page *page) * an EPC page, * -errno on error */ -struct sgx_epc_page *sgx_alloc_epc_page(void *owner, bool reclaim) +struct sgx_epc_page *sgx_alloc_epc_page(void *owner, enum sgx_reclaim reclaim) { struct sgx_epc_page *page; @@ -571,7 +571,7 @@ struct sgx_epc_page *sgx_alloc_epc_page(void *owner, bool reclaim) if (list_empty(&sgx_active_page_list)) return ERR_PTR(-ENOMEM); - if (!reclaim) { + if (reclaim == SGX_NO_RECLAIM) { page = ERR_PTR(-EBUSY); break; } diff --git a/arch/x86/kernel/cpu/sgx/sgx.h b/arch/x86/kernel/cpu/sgx/sgx.h index d2dad21259a8..ca34cd4f58ac 100644 --- a/arch/x86/kernel/cpu/sgx/sgx.h +++ b/arch/x86/kernel/cpu/sgx/sgx.h @@ -29,6 +29,16 @@ /* Pages on free list */ #define SGX_EPC_PAGE_IS_FREE BIT(1) +/** + * enum sgx_reclaim - Whether EPC reclamation is allowed within a function. + * %SGX_NO_RECLAIM: Do not reclaim EPC pages. + * %SGX_DO_RECLAIM: Reclaim EPC pages as needed. + */ +enum sgx_reclaim { + SGX_NO_RECLAIM, + SGX_DO_RECLAIM +}; + struct sgx_epc_page { unsigned int section; u16 flags; @@ -83,13 +93,12 @@ static inline void *sgx_get_epc_virt_addr(struct sgx_epc_page *page) return section->virt_addr + index * PAGE_SIZE; } -struct sgx_epc_page *__sgx_alloc_epc_page(void); void sgx_free_epc_page(struct sgx_epc_page *page); void sgx_reclaim_direct(void); void sgx_mark_page_reclaimable(struct sgx_epc_page *page); int sgx_unmark_page_reclaimable(struct sgx_epc_page *page); -struct sgx_epc_page *sgx_alloc_epc_page(void *owner, bool reclaim); +struct sgx_epc_page *sgx_alloc_epc_page(void *owner, enum sgx_reclaim reclaim); void sgx_ipi_cb(void *info); diff --git a/arch/x86/kernel/cpu/sgx/virt.c b/arch/x86/kernel/cpu/sgx/virt.c index 7aaa3652e31d..e7fdc3a9abae 100644 --- a/arch/x86/kernel/cpu/sgx/virt.c +++ b/arch/x86/kernel/cpu/sgx/virt.c @@ -46,7 +46,7 @@ static int __sgx_vepc_fault(struct sgx_vepc *vepc, if (epc_page) return 0; - epc_page = sgx_alloc_epc_page(vepc, false); + epc_page = sgx_alloc_epc_page(vepc, SGX_NO_RECLAIM); if (IS_ERR(epc_page)) return PTR_ERR(epc_page); From patchwork Fri May 31 22:26:18 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Haitao Huang X-Patchwork-Id: 13682242 Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.15]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 934408121F; Fri, 31 May 2024 22:26:34 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.15 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1717194396; cv=none; b=dvwUdNQXB9zRPfzlGRcioc7ek5j4RfoGWwSfgEDBbkkD9/f/AEeXsEybZXKCsY9IG2YqruMq94x45NSDo+73FMYlQB5LcW6zyM0+5W8S8S5QpOyTQlgE+LXJEODD0xcJ7R8XMpAFwhwnBTJZO7IF2q2maYzgvHGkE45T/Eb1E3c= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1717194396; c=relaxed/simple; bh=FiuxKeDzaIT6o2ExoNnP4zdRxGfrm0SktFxj+ktBG5g=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=FNKo+nP3oUL5MKwL2Cp1Iw1PRkGnATc7IgqZZwDH9ONlmGC2rCEOaZD+J2I7lUgNbwtmnzRrgFyDj3SrnDvCbTGP/kK5fDxZtJb6HilYCjZz53wfkTU5xbrUpArFY3IWc0MZkrvIvt6LMXyJPcubJH9XduvrvV4BO/OuEeDypiM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com; spf=none smtp.mailfrom=linux.intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=FuY7RHwH; arc=none smtp.client-ip=192.198.163.15 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; spf=none smtp.mailfrom=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="FuY7RHwH" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1717194395; x=1748730395; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=FiuxKeDzaIT6o2ExoNnP4zdRxGfrm0SktFxj+ktBG5g=; b=FuY7RHwHCtw51shWhjHxtbsa5QXgS+A2alBb7yLquW4wpcWvR8KpNpNd eYctKxF5zom7QddFnrSgxhr4XjkJwp2PSa+Y9E4eKuQDpSZD9xjIXnX3v MSI+TA7F103moc9qwgloVlDWXMom6wxdVopueBAORn0Bz7z1a0jrejWgU 8ob1D5oUjFqwdww4yFhopl5UL4DthwrV3fawLdKHR/svFy/+4nm/jX5D3 0X723r1pzF8f0GmnqOywuitRDqQVOFWnPIKLyewlsi6yttpnB0C2O3NI6 bnatZ1GR/LOn7voLlxgvWmXA3pahykh/UoAyY9sFOI1dTkmhs8HR7Mk8b w==; X-CSE-ConnectionGUID: KYrQe3fNSQa/4Kay8rHCDw== X-CSE-MsgGUID: CgqyRFgcTMKw0Kbo4oGPJw== X-IronPort-AV: E=McAfee;i="6600,9927,11089"; a="13949738" X-IronPort-AV: E=Sophos;i="6.08,205,1712646000"; d="scan'208";a="13949738" Received: from fmviesa005.fm.intel.com ([10.60.135.145]) by fmvoesa109.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 31 May 2024 15:26:32 -0700 X-CSE-ConnectionGUID: MFUrt1Z1TQGUlFKpwyuS7Q== X-CSE-MsgGUID: 7x6vsv26TbKYHw6LxxBjcg== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.08,205,1712646000"; d="scan'208";a="40736918" Received: from b4969161e530.jf.intel.com ([10.165.56.46]) by fmviesa005.fm.intel.com with ESMTP; 31 May 2024 15:26:32 -0700 From: Haitao Huang To: jarkko@kernel.org, dave.hansen@linux.intel.com, kai.huang@intel.com, tj@kernel.org, mkoutny@suse.com, linux-kernel@vger.kernel.org, linux-sgx@vger.kernel.org, x86@kernel.org, cgroups@vger.kernel.org, tglx@linutronix.de, mingo@redhat.com, bp@alien8.de, hpa@zytor.com, sohil.mehta@intel.com, tim.c.chen@linux.intel.com Cc: zhiquan1.li@intel.com, kristen@linux.intel.com, seanjc@google.com, zhanb@microsoft.com, anakrish@microsoft.com, mikko.ylinen@linux.intel.com, yangjie@microsoft.com, chrisyan@microsoft.com Subject: [PATCH v14 02/14] cgroup/misc: Add per resource callbacks for CSS events Date: Fri, 31 May 2024 15:26:18 -0700 Message-Id: <20240531222630.4634-3-haitao.huang@linux.intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20240531222630.4634-1-haitao.huang@linux.intel.com> References: <20240531222630.4634-1-haitao.huang@linux.intel.com> Precedence: bulk X-Mailing-List: linux-sgx@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Kristen Carlson Accardi The misc cgroup controller (subsystem) currently does not perform resource type specific action for Cgroups Subsystem State (CSS) events: the 'css_alloc' event when a cgroup is created and the 'css_free' event when a cgroup is destroyed. Define callbacks for those events and allow resource providers to register the callbacks per resource type as needed. This will be utilized later by the EPC misc cgroup support implemented in the SGX driver. This design passes a struct misc_cg into the callbacks. An alternative to pass only a struct misc_res was considered for encapsulating how misc_cg stores its misc_res array. However, the SGX driver would still need to access the misc_res array in the statically defined misc root_cg during initialization to set resource specific fields. Therefore, some extra getter/setter APIs to abstract such access to the misc_res array within the misc_cg struct would be needed. That seems an overkill at the moment and is deferred to later improvement when there are more users of these callbacks. Link: https://lore.kernel.org/lkml/op.2kdw36otwjvjmi@hhuan26-mobl.amr.corp.intel.com/ Signed-off-by: Kristen Carlson Accardi Co-developed-by: Haitao Huang Signed-off-by: Haitao Huang Reviewed-by: Jarkko Sakkinen Reviewed-by: Tejun Heo Reviewed-by: Kai Huang Tested-by: Jarkko Sakkinen --- V12: - Add comments in commit to clarify reason to pass in misc_cg, not misc_res. (Kai) - Remove unlikely (Kai) V8: - Abstract out _misc_cg_res_free() and _misc_cg_res_alloc() (Jarkko) V7: - Make ops one per resource type and store them in array (Michal) - Rename the ops struct to misc_res_ops, and enforce the constraints of required callback functions (Jarkko) - Moved addition of priv field to patch 4 where it was used first. (Jarkko) V6: - Create ops struct for per resource callbacks (Jarkko) - Drop max_write callback (Dave, Michal) - Style fixes (Kai) --- include/linux/misc_cgroup.h | 11 +++++ kernel/cgroup/misc.c | 82 +++++++++++++++++++++++++++++++++---- 2 files changed, 86 insertions(+), 7 deletions(-) diff --git a/include/linux/misc_cgroup.h b/include/linux/misc_cgroup.h index e799b1f8d05b..0806d4436208 100644 --- a/include/linux/misc_cgroup.h +++ b/include/linux/misc_cgroup.h @@ -27,6 +27,16 @@ struct misc_cg; #include +/** + * struct misc_res_ops: per resource type callback ops. + * @alloc: invoked for resource specific initialization when cgroup is allocated. + * @free: invoked for resource specific cleanup when cgroup is deallocated. + */ +struct misc_res_ops { + int (*alloc)(struct misc_cg *cg); + void (*free)(struct misc_cg *cg); +}; + /** * struct misc_res: Per cgroup per misc type resource * @max: Maximum limit on the resource. @@ -56,6 +66,7 @@ struct misc_cg { u64 misc_cg_res_total_usage(enum misc_res_type type); int misc_cg_set_capacity(enum misc_res_type type, u64 capacity); +int misc_cg_set_ops(enum misc_res_type type, const struct misc_res_ops *ops); int misc_cg_try_charge(enum misc_res_type type, struct misc_cg *cg, u64 amount); void misc_cg_uncharge(enum misc_res_type type, struct misc_cg *cg, u64 amount); diff --git a/kernel/cgroup/misc.c b/kernel/cgroup/misc.c index 79a3717a5803..4a602d68cf7d 100644 --- a/kernel/cgroup/misc.c +++ b/kernel/cgroup/misc.c @@ -39,6 +39,9 @@ static struct misc_cg root_cg; */ static u64 misc_res_capacity[MISC_CG_RES_TYPES]; +/* Resource type specific operations */ +static const struct misc_res_ops *misc_res_ops[MISC_CG_RES_TYPES]; + /** * parent_misc() - Get the parent of the passed misc cgroup. * @cgroup: cgroup whose parent needs to be fetched. @@ -105,6 +108,36 @@ int misc_cg_set_capacity(enum misc_res_type type, u64 capacity) } EXPORT_SYMBOL_GPL(misc_cg_set_capacity); +/** + * misc_cg_set_ops() - set resource specific operations. + * @type: Type of the misc res. + * @ops: Operations for the given type. + * + * Context: Any context. + * Return: + * * %0 - Successfully registered the operations. + * * %-EINVAL - If @type is invalid, or the operations missing any required callbacks. + */ +int misc_cg_set_ops(enum misc_res_type type, const struct misc_res_ops *ops) +{ + if (!valid_type(type)) + return -EINVAL; + + if (!ops->alloc) { + pr_err("%s: alloc missing\n", __func__); + return -EINVAL; + } + + if (!ops->free) { + pr_err("%s: free missing\n", __func__); + return -EINVAL; + } + + misc_res_ops[type] = ops; + return 0; +} +EXPORT_SYMBOL_GPL(misc_cg_set_ops); + /** * misc_cg_cancel_charge() - Cancel the charge from the misc cgroup. * @type: Misc res type in misc cg to cancel the charge from. @@ -371,6 +404,33 @@ static struct cftype misc_cg_files[] = { {} }; +static inline int _misc_cg_res_alloc(struct misc_cg *cg) +{ + enum misc_res_type i; + int ret; + + for (i = 0; i < MISC_CG_RES_TYPES; i++) { + WRITE_ONCE(cg->res[i].max, MAX_NUM); + atomic64_set(&cg->res[i].usage, 0); + if (misc_res_ops[i]) { + ret = misc_res_ops[i]->alloc(cg); + if (ret) + return ret; + } + } + + return 0; +} + +static inline void _misc_cg_res_free(struct misc_cg *cg) +{ + enum misc_res_type i; + + for (i = 0; i < MISC_CG_RES_TYPES; i++) + if (misc_res_ops[i]) + misc_res_ops[i]->free(cg); +} + /** * misc_cg_alloc() - Allocate misc cgroup. * @parent_css: Parent cgroup. @@ -383,20 +443,25 @@ static struct cftype misc_cg_files[] = { static struct cgroup_subsys_state * misc_cg_alloc(struct cgroup_subsys_state *parent_css) { - enum misc_res_type i; - struct misc_cg *cg; + struct misc_cg *parent_cg, *cg; + int ret; if (!parent_css) { - cg = &root_cg; + parent_cg = cg = &root_cg; } else { cg = kzalloc(sizeof(*cg), GFP_KERNEL); if (!cg) return ERR_PTR(-ENOMEM); + parent_cg = css_misc(parent_css); } - for (i = 0; i < MISC_CG_RES_TYPES; i++) { - WRITE_ONCE(cg->res[i].max, MAX_NUM); - atomic64_set(&cg->res[i].usage, 0); + ret = _misc_cg_res_alloc(cg); + if (ret) { + _misc_cg_res_free(cg); + if (likely(parent_css)) + kfree(cg); + + return ERR_PTR(ret); } return &cg->css; @@ -410,7 +475,10 @@ misc_cg_alloc(struct cgroup_subsys_state *parent_css) */ static void misc_cg_free(struct cgroup_subsys_state *css) { - kfree(css_misc(css)); + struct misc_cg *cg = css_misc(css); + + _misc_cg_res_free(cg); + kfree(cg); } /* Cgroup controller callbacks */ From patchwork Fri May 31 22:26:19 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Haitao Huang X-Patchwork-Id: 13682241 Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.15]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 6255381204; Fri, 31 May 2024 22:26:34 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.15 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1717194396; cv=none; b=oWFTo4wYGvGJLltar2jkyIVTqUk9E2isUCMqWSoe/Yflm0O7vJmYkF2kUIcP4B0sEk6AGWnTN8t9WGUbq3P1PzsfbsIsW46N08W7WSefgAk/duZGNLsYCf9qRT4Xv0a8Cp8xHBp7Q9rt0WiwNEKYoYqTVMvPmXzJWLIzq86PoNY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1717194396; c=relaxed/simple; bh=eqN2yKPP04cTarojAaLprGk14sHMHhoIfgiMAqyE0Ac=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=eKbI2S6Jbj+R8oqUL6osd3R28wuPP3xCGrcf1J4lAtdilUCfx3pQjF4ghptSZsMhGVJoEMbe1xSlWbmBgw8giuXPcO6gjiv6hevf4/3ns4bxb3JAPN+rqYd4bef1vd56azVecaAZAyzzRhZAZLINacVH1biGmpn/I7JcWOyUz7g= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com; spf=none smtp.mailfrom=linux.intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=P+Au7tMx; arc=none smtp.client-ip=192.198.163.15 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; spf=none smtp.mailfrom=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="P+Au7tMx" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1717194394; x=1748730394; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=eqN2yKPP04cTarojAaLprGk14sHMHhoIfgiMAqyE0Ac=; b=P+Au7tMxlkX/rMczxPEGEClwFkdU9mPUdrP/F57Uc6VlB+HEHxBp6lnq RKqTQfLjCiH8cs+Bf1e0BP95N3aDA7lvSJmIT2gQNCKNZ2DEfxbBX80pJ KxpJiuoNdW77ahgF3+P47QLgwIbOSnGbBuxQNnscJvVNwuecgePCK06Qu byNZh01ZgZEREWaHoHVL4zGQM4SM4D/vbT4Hj/wGghF/rAvgDBlQFgQvc GqNPin/0TA0xVMpMP/9dp5X9aNvDAYCg8koDGfyknVchC6/ZCRhsYgHKn vS+M7HYA0BKCyqrbFIec3emd1U/rqeWNND5C/GCiTwfD1wCcAGoPGjOV/ w==; X-CSE-ConnectionGUID: ntQbN9hvQ5OBNZgXiiO+HA== X-CSE-MsgGUID: 6wcc7LN+RueDUTrBT4xU7w== X-IronPort-AV: E=McAfee;i="6600,9927,11089"; a="13949752" X-IronPort-AV: E=Sophos;i="6.08,205,1712646000"; d="scan'208";a="13949752" Received: from fmviesa005.fm.intel.com ([10.60.135.145]) by fmvoesa109.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 31 May 2024 15:26:33 -0700 X-CSE-ConnectionGUID: 44jArniuRd+A6i6mX8tIew== X-CSE-MsgGUID: jg7XUO40RaOhL9ENjCry3A== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.08,205,1712646000"; d="scan'208";a="40736921" Received: from b4969161e530.jf.intel.com ([10.165.56.46]) by fmviesa005.fm.intel.com with ESMTP; 31 May 2024 15:26:32 -0700 From: Haitao Huang To: jarkko@kernel.org, dave.hansen@linux.intel.com, kai.huang@intel.com, tj@kernel.org, mkoutny@suse.com, linux-kernel@vger.kernel.org, linux-sgx@vger.kernel.org, x86@kernel.org, cgroups@vger.kernel.org, tglx@linutronix.de, mingo@redhat.com, bp@alien8.de, hpa@zytor.com, sohil.mehta@intel.com, tim.c.chen@linux.intel.com Cc: zhiquan1.li@intel.com, kristen@linux.intel.com, seanjc@google.com, zhanb@microsoft.com, anakrish@microsoft.com, mikko.ylinen@linux.intel.com, yangjie@microsoft.com, chrisyan@microsoft.com Subject: [PATCH v14 03/14] cgroup/misc: Export APIs for SGX driver Date: Fri, 31 May 2024 15:26:19 -0700 Message-Id: <20240531222630.4634-4-haitao.huang@linux.intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20240531222630.4634-1-haitao.huang@linux.intel.com> References: <20240531222630.4634-1-haitao.huang@linux.intel.com> Precedence: bulk X-Mailing-List: linux-sgx@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Kristen Carlson Accardi The SGX EPC cgroup will reclaim EPC pages when usage in a cgroup reaches its or ancestor's limit. This requires a walk from the current cgroup up to the root similar to misc_cg_try_charge(). Export misc_cg_parent() to enable this walk. The SGX driver also needs start a global level reclamation from the root. Export misc_cg_root() for the SGX driver to access. Signed-off-by: Kristen Carlson Accardi Co-developed-by: Haitao Huang Signed-off-by: Haitao Huang Reviewed-by: Jarkko Sakkinen Reviewed-by: Tejun Heo Reviewed-by: Kai Huang Tested-by: Jarkko Sakkinen --- V6: - Make commit messages more concise and split the original patch into two(Kai) --- include/linux/misc_cgroup.h | 24 ++++++++++++++++++++++++ kernel/cgroup/misc.c | 21 ++++++++------------- 2 files changed, 32 insertions(+), 13 deletions(-) diff --git a/include/linux/misc_cgroup.h b/include/linux/misc_cgroup.h index 0806d4436208..541a5611c597 100644 --- a/include/linux/misc_cgroup.h +++ b/include/linux/misc_cgroup.h @@ -64,6 +64,7 @@ struct misc_cg { struct misc_res res[MISC_CG_RES_TYPES]; }; +struct misc_cg *misc_cg_root(void); u64 misc_cg_res_total_usage(enum misc_res_type type); int misc_cg_set_capacity(enum misc_res_type type, u64 capacity); int misc_cg_set_ops(enum misc_res_type type, const struct misc_res_ops *ops); @@ -84,6 +85,20 @@ static inline struct misc_cg *css_misc(struct cgroup_subsys_state *css) return css ? container_of(css, struct misc_cg, css) : NULL; } +/** + * misc_cg_parent() - Get the parent of the passed misc cgroup. + * @cgroup: cgroup whose parent needs to be fetched. + * + * Context: Any context. + * Return: + * * struct misc_cg* - Parent of the @cgroup. + * * %NULL - If @cgroup is null or the passed cgroup does not have a parent. + */ +static inline struct misc_cg *misc_cg_parent(struct misc_cg *cgroup) +{ + return cgroup ? css_misc(cgroup->css.parent) : NULL; +} + /* * get_current_misc_cg() - Find and get the misc cgroup of the current task. * @@ -108,6 +123,15 @@ static inline void put_misc_cg(struct misc_cg *cg) } #else /* !CONFIG_CGROUP_MISC */ +static inline struct misc_cg *misc_cg_root(void) +{ + return NULL; +} + +static inline struct misc_cg *misc_cg_parent(struct misc_cg *cg) +{ + return NULL; +} static inline u64 misc_cg_res_total_usage(enum misc_res_type type) { diff --git a/kernel/cgroup/misc.c b/kernel/cgroup/misc.c index 4a602d68cf7d..7d852139121a 100644 --- a/kernel/cgroup/misc.c +++ b/kernel/cgroup/misc.c @@ -43,18 +43,13 @@ static u64 misc_res_capacity[MISC_CG_RES_TYPES]; static const struct misc_res_ops *misc_res_ops[MISC_CG_RES_TYPES]; /** - * parent_misc() - Get the parent of the passed misc cgroup. - * @cgroup: cgroup whose parent needs to be fetched. - * - * Context: Any context. - * Return: - * * struct misc_cg* - Parent of the @cgroup. - * * %NULL - If @cgroup is null or the passed cgroup does not have a parent. + * misc_cg_root() - Return the root misc cgroup. */ -static struct misc_cg *parent_misc(struct misc_cg *cgroup) +struct misc_cg *misc_cg_root(void) { - return cgroup ? css_misc(cgroup->css.parent) : NULL; + return &root_cg; } +EXPORT_SYMBOL_GPL(misc_cg_root); /** * valid_type() - Check if @type is valid or not. @@ -183,7 +178,7 @@ int misc_cg_try_charge(enum misc_res_type type, struct misc_cg *cg, u64 amount) if (!amount) return 0; - for (i = cg; i; i = parent_misc(i)) { + for (i = cg; i; i = misc_cg_parent(i)) { res = &i->res[type]; new_usage = atomic64_add_return(amount, &res->usage); @@ -196,12 +191,12 @@ int misc_cg_try_charge(enum misc_res_type type, struct misc_cg *cg, u64 amount) return 0; err_charge: - for (j = i; j; j = parent_misc(j)) { + for (j = i; j; j = misc_cg_parent(j)) { atomic64_inc(&j->res[type].events); cgroup_file_notify(&j->events_file); } - for (j = cg; j != i; j = parent_misc(j)) + for (j = cg; j != i; j = misc_cg_parent(j)) misc_cg_cancel_charge(type, j, amount); misc_cg_cancel_charge(type, i, amount); return ret; @@ -223,7 +218,7 @@ void misc_cg_uncharge(enum misc_res_type type, struct misc_cg *cg, u64 amount) if (!(amount && valid_type(type) && cg)) return; - for (i = cg; i; i = parent_misc(i)) + for (i = cg; i; i = misc_cg_parent(i)) misc_cg_cancel_charge(type, i, amount); } EXPORT_SYMBOL_GPL(misc_cg_uncharge); From patchwork Fri May 31 22:26:20 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Haitao Huang X-Patchwork-Id: 13682243 Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.15]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 6278E81AB4; Fri, 31 May 2024 22:26:35 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.15 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1717194397; cv=none; b=SqTGkBuG3mpj6fRk+8mPuADGGrX6Nh+AZWK3XUXIYjqAokJWaoWPECs+ih5WHKxnF8bBnPRA+7/HE0TQylDQhvIX1FJyUY/2fJqLQrxq+tYa3WgyloX3VJEGyzMZHz1OosmJXouhVHQs1FwYxngFSpaGqzQkrXUHI04V0vorkNQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1717194397; c=relaxed/simple; bh=sJFW0ltM0O1BHkI+u582PzoUZyLLTIZYbeD8rl/i1fI=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=lQMlGTSLSV22qPpJRKPcxXSqntmVzOH20f3vxq+5RrNh8SH+Z/JEGCeplujKprfquewET5tjF5W3vTlX4aWawf6Kdlwf7iRFOEhwHFLZ+Zla5zgEtW/OWDsKSzqN7RFgSzzekuSsWqF+2KsRQ4cA7m3eEkFZMBDwVHjnxNTJN10= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com; spf=none smtp.mailfrom=linux.intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=m1/l2woj; arc=none smtp.client-ip=192.198.163.15 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; spf=none smtp.mailfrom=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="m1/l2woj" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1717194395; x=1748730395; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=sJFW0ltM0O1BHkI+u582PzoUZyLLTIZYbeD8rl/i1fI=; b=m1/l2wojdLJKpyGLuo9rJUGquiopwAMasCA2nBWa6cpoNOB9IQLqokEG Q2oJZt7Pk/SfdZFEyrH88aXcubaL94h6XRkdT2eQZWfpjBBJNOmQx2Edw B1bTNZA06/YW2ywErRlI5fkzacm8CRY+I95zxGoJ6ZKJWfSxvUCXPJq0u /YT12qlmJsmOQLT8W26tks9TxEcVmJe0qTwHJDSCnCA+vcwfuu4/+uvjI xtzd6KKtVsV1fgTB61DZmnOTGFoptVBrmV+tk392pUAC5ibgb0JdpbT+5 IJH9TaSYeE2l5+zcu8RnNNt1OzpA66uQAN0RmM1pUJRsEgtnbubWwGpM0 A==; X-CSE-ConnectionGUID: 3Z7QUYBbQNWe3OM858Nb9Q== X-CSE-MsgGUID: mZdim+z9T/i9Rm4RxLLGIQ== X-IronPort-AV: E=McAfee;i="6600,9927,11089"; a="13949758" X-IronPort-AV: E=Sophos;i="6.08,205,1712646000"; d="scan'208";a="13949758" Received: from fmviesa005.fm.intel.com ([10.60.135.145]) by fmvoesa109.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 31 May 2024 15:26:34 -0700 X-CSE-ConnectionGUID: ZvUew+Q/Q0uea+QDMLKGEQ== X-CSE-MsgGUID: DnZsrCtyQ4eN4+vEgCWBhg== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.08,205,1712646000"; d="scan'208";a="40736924" Received: from b4969161e530.jf.intel.com ([10.165.56.46]) by fmviesa005.fm.intel.com with ESMTP; 31 May 2024 15:26:33 -0700 From: Haitao Huang To: jarkko@kernel.org, dave.hansen@linux.intel.com, kai.huang@intel.com, tj@kernel.org, mkoutny@suse.com, linux-kernel@vger.kernel.org, linux-sgx@vger.kernel.org, x86@kernel.org, cgroups@vger.kernel.org, tglx@linutronix.de, mingo@redhat.com, bp@alien8.de, hpa@zytor.com, sohil.mehta@intel.com, tim.c.chen@linux.intel.com Cc: zhiquan1.li@intel.com, kristen@linux.intel.com, seanjc@google.com, zhanb@microsoft.com, anakrish@microsoft.com, mikko.ylinen@linux.intel.com, yangjie@microsoft.com, chrisyan@microsoft.com Subject: [PATCH v14 04/14] cgroup/misc: Add SGX EPC resource type Date: Fri, 31 May 2024 15:26:20 -0700 Message-Id: <20240531222630.4634-5-haitao.huang@linux.intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20240531222630.4634-1-haitao.huang@linux.intel.com> References: <20240531222630.4634-1-haitao.huang@linux.intel.com> Precedence: bulk X-Mailing-List: linux-sgx@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Kristen Carlson Accardi Add SGX EPC memory, MISC_CG_RES_SGX_EPC, to be a valid resource type for the misc controller. Signed-off-by: Kristen Carlson Accardi Co-developed-by: Haitao Huang Signed-off-by: Haitao Huang Reviewed-by: Jarkko Sakkinen Reviewed-by: Kai Huang Tested-by: Jarkko Sakkinen --- V12: - Remove CONFIG_CGROUP_SGX_EPC (Jarkko) V6: - Split the original patch into this and the preceding one (Kai) --- include/linux/misc_cgroup.h | 4 ++++ kernel/cgroup/misc.c | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/include/linux/misc_cgroup.h b/include/linux/misc_cgroup.h index 541a5611c597..440ed2bb8053 100644 --- a/include/linux/misc_cgroup.h +++ b/include/linux/misc_cgroup.h @@ -17,6 +17,10 @@ enum misc_res_type { MISC_CG_RES_SEV, /* AMD SEV-ES ASIDs resource */ MISC_CG_RES_SEV_ES, +#endif +#ifdef CONFIG_X86_SGX + /* SGX EPC memory resource */ + MISC_CG_RES_SGX_EPC, #endif MISC_CG_RES_TYPES }; diff --git a/kernel/cgroup/misc.c b/kernel/cgroup/misc.c index 7d852139121a..863f9147602b 100644 --- a/kernel/cgroup/misc.c +++ b/kernel/cgroup/misc.c @@ -24,6 +24,10 @@ static const char *const misc_res_name[] = { /* AMD SEV-ES ASIDs resource */ "sev_es", #endif +#ifdef CONFIG_X86_SGX + /* Intel SGX EPC memory bytes */ + "sgx_epc", +#endif }; /* Root misc cgroup */ From patchwork Fri May 31 22:26:21 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Haitao Huang X-Patchwork-Id: 13682244 Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.15]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 2DA40823DD; Fri, 31 May 2024 22:26:36 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.15 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1717194398; cv=none; b=EoMaZ9kNZI6Cg9gqn1pE5mJ3vpBfZk/oep1MdvG/8Rk8UsLhpiYix1n/XG1Tp6DMEetBHMHP46ehv/v++uz8PyKSnz98A6c3fcWsnFOPja9i7JHMEoTzlXSRxjrh79fPlro/PCpQ5xc7VA1F8utq/7lV6r+qjR1xJhwcLGpj4CY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1717194398; c=relaxed/simple; bh=LaiFdQ777VSgjrEUhmWJY9mpRLQNtynEI+l+dvlgo00=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=r4eyJBpP2zggS9z3iuANKCLkEvvoLb7JM/GI4X+bZGCC0X5VPiBhI/j6WdJqcO/92BOGQrOulq1L4/uHVvbca49N/gym/vNXPJHEpdGG+KBqOeHQ+Mq+q8t8oYePfiGEyfIAVcHgLpPn84+Xld8jIoOU1RQCvvzO2GTNEKh1YKI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com; spf=none smtp.mailfrom=linux.intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=FSD4UuyV; arc=none smtp.client-ip=192.198.163.15 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; spf=none smtp.mailfrom=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="FSD4UuyV" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1717194396; x=1748730396; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=LaiFdQ777VSgjrEUhmWJY9mpRLQNtynEI+l+dvlgo00=; b=FSD4UuyVg9//QQiUmdgD/uk3kaOOr+ALzSw/iQvX1uYdaMb+1o01WYmr X0giBUz4o56qNWJA7uEwpiAvaTS8tqm/PWbafjctTQ7k/5wjOiV4Gm94+ qmiS2TcA+eBHZiiURA9bxmynJf2PiD/sGxnJ9boUoQzjRk7tbHXGYJKnq C5s8Pr/gbAOMO8XqJ6JMsLYFM1YK+RYpXppL46FNOl1iXw6eexkgRclon HA6Jj1pDfBj7Rn8yGRQG8rC2cAvvPiGHevBf+3Dluvs+d2iL+ALPdic2b YZNheIM14xf4FG2rESdA4hXXK9+CMPvkqAL5UAEQuljgeJiYkPrKuVnK9 g==; X-CSE-ConnectionGUID: 5jUZrTZ5Ra2EEXTg5fet1g== X-CSE-MsgGUID: Mjl24ybZRQaglWcEPVZ6YA== X-IronPort-AV: E=McAfee;i="6600,9927,11089"; a="13949766" X-IronPort-AV: E=Sophos;i="6.08,205,1712646000"; d="scan'208";a="13949766" Received: from fmviesa005.fm.intel.com ([10.60.135.145]) by fmvoesa109.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 31 May 2024 15:26:34 -0700 X-CSE-ConnectionGUID: Wfz5nMuTTdyeEgHbPYgoYg== X-CSE-MsgGUID: OcMMD7DIQn+7NjfK+A6wbA== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.08,205,1712646000"; d="scan'208";a="40736927" Received: from b4969161e530.jf.intel.com ([10.165.56.46]) by fmviesa005.fm.intel.com with ESMTP; 31 May 2024 15:26:33 -0700 From: Haitao Huang To: jarkko@kernel.org, dave.hansen@linux.intel.com, kai.huang@intel.com, tj@kernel.org, mkoutny@suse.com, linux-kernel@vger.kernel.org, linux-sgx@vger.kernel.org, x86@kernel.org, cgroups@vger.kernel.org, tglx@linutronix.de, mingo@redhat.com, bp@alien8.de, hpa@zytor.com, sohil.mehta@intel.com, tim.c.chen@linux.intel.com Cc: zhiquan1.li@intel.com, kristen@linux.intel.com, seanjc@google.com, zhanb@microsoft.com, anakrish@microsoft.com, mikko.ylinen@linux.intel.com, yangjie@microsoft.com, chrisyan@microsoft.com Subject: [PATCH v14 05/14] x86/sgx: Implement basic EPC misc cgroup functionality Date: Fri, 31 May 2024 15:26:21 -0700 Message-Id: <20240531222630.4634-6-haitao.huang@linux.intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20240531222630.4634-1-haitao.huang@linux.intel.com> References: <20240531222630.4634-1-haitao.huang@linux.intel.com> Precedence: bulk X-Mailing-List: linux-sgx@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Kristen Carlson Accardi SGX Enclave Page Cache (EPC) memory allocations are separate from normal RAM allocations, and are managed solely by the SGX subsystem. The existing cgroup memory controller cannot be used to limit or account for SGX EPC memory, which is a desirable feature in some environments. For instance, within a Kubernetes environment, while a user may specify a particular EPC quota for a pod, the orchestrator requires a mechanism to enforce that the pod's actual runtime EPC usage does not exceed the allocated quota. Utilize the misc controller [admin-guide/cgroup-v2.rst, 5-9. Misc] to limit and track EPC allocations per cgroup. Earlier patches have added the "sgx_epc" resource type in the misc cgroup subsystem. Add basic support in SGX driver as the "sgx_epc" resource provider: - Set "capacity" of EPC by calling misc_cg_set_capacity() - Update EPC usage counter, "current", by calling charge and uncharge APIs for EPC allocation and deallocation, respectively. - Setup sgx_epc resource type specific callbacks, which perform initialization and cleanup during cgroup allocation and deallocation, respectively. With these changes, the misc cgroup controller enables users to set a hard limit for EPC usage in the "misc.max" interface file. It reports current usage in "misc.current", the total EPC memory available in "misc.capacity", and the number of times EPC usage reached the max limit in "misc.events". For now, the EPC cgroup simply blocks additional EPC allocation in sgx_alloc_epc_page() when the limit is reached. Reclaimable pages are still tracked in the global active list, only reclaimed by the global reclaimer when the total free page count is lower than a threshold. Later patches will reorganize the tracking and reclamation code in the global reclaimer and implement per-cgroup tracking and reclaiming. Co-developed-by: Sean Christopherson Signed-off-by: Sean Christopherson Signed-off-by: Kristen Carlson Accardi Co-developed-by: Haitao Huang Signed-off-by: Haitao Huang Reviewed-by: Jarkko Sakkinen Reviewed-by: Tejun Heo Reviewed-by: Kai Huang Tested-by: Jarkko Sakkinen --- V13: - Remove unneeded includes. (Kai) V12: - Remove CONFIG_CGROUP_SGX_EPC and make sgx cgroup implementation conditionally compiled with CONFIG_CGROUP_MISC. (Jarkko) V11: - Update copyright and format better (Kai) - Create wrappers to remove #ifdefs in c file. (Kai) - Remove unneeded comments (Kai) V10: - Shorten function, variable, struct names, s/sgx_epc_cgroup/sgx_cgroup. (Jarkko) - Use enums instead of booleans for the parameters. (Dave, Jarkko) V8: - Remove null checks for epc_cg in try_charge()/uncharge(). (Jarkko) - Remove extra space, '_INTEL'. (Jarkko) V7: - Use a static for root cgroup (Kai) - Wrap epc_cg field in sgx_epc_page struct with #ifdef (Kai) - Correct check for charge API return (Kai) - Start initialization in SGX device driver init (Kai) - Remove unneeded BUG_ON (Kai) - Split sgx_get_current_epc_cg() out of sgx_epc_cg_try_charge() (Kai) V6: - Split the original large patch"Limit process EPC usage with misc cgroup controller" and restructure it (Kai) --- arch/x86/kernel/cpu/sgx/Makefile | 1 + arch/x86/kernel/cpu/sgx/epc_cgroup.c | 71 +++++++++++++++++++++++++++ arch/x86/kernel/cpu/sgx/epc_cgroup.h | 72 ++++++++++++++++++++++++++++ arch/x86/kernel/cpu/sgx/main.c | 42 +++++++++++++++- arch/x86/kernel/cpu/sgx/sgx.h | 21 ++++++++ include/linux/misc_cgroup.h | 2 + 6 files changed, 207 insertions(+), 2 deletions(-) create mode 100644 arch/x86/kernel/cpu/sgx/epc_cgroup.c create mode 100644 arch/x86/kernel/cpu/sgx/epc_cgroup.h diff --git a/arch/x86/kernel/cpu/sgx/Makefile b/arch/x86/kernel/cpu/sgx/Makefile index 9c1656779b2a..081cb424575e 100644 --- a/arch/x86/kernel/cpu/sgx/Makefile +++ b/arch/x86/kernel/cpu/sgx/Makefile @@ -4,3 +4,4 @@ obj-y += \ ioctl.o \ main.o obj-$(CONFIG_X86_SGX_KVM) += virt.o +obj-$(CONFIG_CGROUP_MISC) += epc_cgroup.o diff --git a/arch/x86/kernel/cpu/sgx/epc_cgroup.c b/arch/x86/kernel/cpu/sgx/epc_cgroup.c new file mode 100644 index 000000000000..5c484fd10160 --- /dev/null +++ b/arch/x86/kernel/cpu/sgx/epc_cgroup.c @@ -0,0 +1,71 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2022-2024 Intel Corporation. */ + +#include +#include "epc_cgroup.h" + +/* The root SGX EPC cgroup */ +static struct sgx_cgroup sgx_cg_root; + +/** + * sgx_cgroup_try_charge() - try to charge cgroup for a single EPC page + * + * @sgx_cg: The EPC cgroup to be charged for the page. + * Return: + * * %0 - If successfully charged. + * * -errno - for failures. + */ +int sgx_cgroup_try_charge(struct sgx_cgroup *sgx_cg) +{ + return misc_cg_try_charge(MISC_CG_RES_SGX_EPC, sgx_cg->cg, PAGE_SIZE); +} + +/** + * sgx_cgroup_uncharge() - uncharge a cgroup for an EPC page + * @sgx_cg: The charged sgx cgroup. + */ +void sgx_cgroup_uncharge(struct sgx_cgroup *sgx_cg) +{ + misc_cg_uncharge(MISC_CG_RES_SGX_EPC, sgx_cg->cg, PAGE_SIZE); +} + +static void sgx_cgroup_free(struct misc_cg *cg) +{ + struct sgx_cgroup *sgx_cg; + + sgx_cg = sgx_cgroup_from_misc_cg(cg); + if (!sgx_cg) + return; + + kfree(sgx_cg); +} + +static void sgx_cgroup_misc_init(struct misc_cg *cg, struct sgx_cgroup *sgx_cg) +{ + cg->res[MISC_CG_RES_SGX_EPC].priv = sgx_cg; + sgx_cg->cg = cg; +} + +static int sgx_cgroup_alloc(struct misc_cg *cg) +{ + struct sgx_cgroup *sgx_cg; + + sgx_cg = kzalloc(sizeof(*sgx_cg), GFP_KERNEL); + if (!sgx_cg) + return -ENOMEM; + + sgx_cgroup_misc_init(cg, sgx_cg); + + return 0; +} + +const struct misc_res_ops sgx_cgroup_ops = { + .alloc = sgx_cgroup_alloc, + .free = sgx_cgroup_free, +}; + +void sgx_cgroup_init(void) +{ + misc_cg_set_ops(MISC_CG_RES_SGX_EPC, &sgx_cgroup_ops); + sgx_cgroup_misc_init(misc_cg_root(), &sgx_cg_root); +} diff --git a/arch/x86/kernel/cpu/sgx/epc_cgroup.h b/arch/x86/kernel/cpu/sgx/epc_cgroup.h new file mode 100644 index 000000000000..bd9606479e67 --- /dev/null +++ b/arch/x86/kernel/cpu/sgx/epc_cgroup.h @@ -0,0 +1,72 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _SGX_EPC_CGROUP_H_ +#define _SGX_EPC_CGROUP_H_ + +#include +#include +#include + +#include "sgx.h" + +#ifndef CONFIG_CGROUP_MISC + +#define MISC_CG_RES_SGX_EPC MISC_CG_RES_TYPES +struct sgx_cgroup; + +static inline struct sgx_cgroup *sgx_get_current_cg(void) +{ + return NULL; +} + +static inline void sgx_put_cg(struct sgx_cgroup *sgx_cg) { } + +static inline int sgx_cgroup_try_charge(struct sgx_cgroup *sgx_cg) +{ + return 0; +} + +static inline void sgx_cgroup_uncharge(struct sgx_cgroup *sgx_cg) { } + +static inline void sgx_cgroup_init(void) { } + +#else /* CONFIG_CGROUP_MISC */ + +struct sgx_cgroup { + struct misc_cg *cg; +}; + +static inline struct sgx_cgroup *sgx_cgroup_from_misc_cg(struct misc_cg *cg) +{ + return (struct sgx_cgroup *)(cg->res[MISC_CG_RES_SGX_EPC].priv); +} + +/** + * sgx_get_current_cg() - get the EPC cgroup of current process. + * + * Returned cgroup has its ref count increased by 1. Caller must call + * sgx_put_cg() to return the reference. + * + * Return: EPC cgroup to which the current task belongs to. + */ +static inline struct sgx_cgroup *sgx_get_current_cg(void) +{ + /* get_current_misc_cg() never returns NULL when Kconfig enabled */ + return sgx_cgroup_from_misc_cg(get_current_misc_cg()); +} + +/** + * sgx_put_cg() - Put the EPC cgroup and reduce its ref count. + * @sgx_cg - EPC cgroup to put. + */ +static inline void sgx_put_cg(struct sgx_cgroup *sgx_cg) +{ + put_misc_cg(sgx_cg->cg); +} + +int sgx_cgroup_try_charge(struct sgx_cgroup *sgx_cg); +void sgx_cgroup_uncharge(struct sgx_cgroup *sgx_cg); +void sgx_cgroup_init(void); + +#endif /* CONFIG_CGROUP_MISC */ + +#endif /* _SGX_EPC_CGROUP_H_ */ diff --git a/arch/x86/kernel/cpu/sgx/main.c b/arch/x86/kernel/cpu/sgx/main.c index e64073fb4256..d7a945d44268 100644 --- a/arch/x86/kernel/cpu/sgx/main.c +++ b/arch/x86/kernel/cpu/sgx/main.c @@ -18,6 +18,7 @@ #include "driver.h" #include "encl.h" #include "encls.h" +#include "epc_cgroup.h" struct sgx_epc_section sgx_epc_sections[SGX_MAX_EPC_SECTIONS]; static int sgx_nr_epc_sections; @@ -559,7 +560,16 @@ int sgx_unmark_page_reclaimable(struct sgx_epc_page *page) */ struct sgx_epc_page *sgx_alloc_epc_page(void *owner, enum sgx_reclaim reclaim) { + struct sgx_cgroup *sgx_cg; struct sgx_epc_page *page; + int ret; + + sgx_cg = sgx_get_current_cg(); + ret = sgx_cgroup_try_charge(sgx_cg); + if (ret) { + sgx_put_cg(sgx_cg); + return ERR_PTR(ret); + } for ( ; ; ) { page = __sgx_alloc_epc_page(); @@ -568,8 +578,10 @@ struct sgx_epc_page *sgx_alloc_epc_page(void *owner, enum sgx_reclaim reclaim) break; } - if (list_empty(&sgx_active_page_list)) - return ERR_PTR(-ENOMEM); + if (list_empty(&sgx_active_page_list)) { + page = ERR_PTR(-ENOMEM); + break; + } if (reclaim == SGX_NO_RECLAIM) { page = ERR_PTR(-EBUSY); @@ -585,6 +597,15 @@ struct sgx_epc_page *sgx_alloc_epc_page(void *owner, enum sgx_reclaim reclaim) cond_resched(); } + if (!IS_ERR(page)) { + WARN_ON_ONCE(sgx_epc_page_get_cgroup(page)); + /* sgx_put_cg() in sgx_free_epc_page() */ + sgx_epc_page_set_cgroup(page, sgx_cg); + } else { + sgx_cgroup_uncharge(sgx_cg); + sgx_put_cg(sgx_cg); + } + if (sgx_should_reclaim(SGX_NR_LOW_PAGES)) wake_up(&ksgxd_waitq); @@ -603,8 +624,16 @@ struct sgx_epc_page *sgx_alloc_epc_page(void *owner, enum sgx_reclaim reclaim) void sgx_free_epc_page(struct sgx_epc_page *page) { struct sgx_epc_section *section = &sgx_epc_sections[page->section]; + struct sgx_cgroup *sgx_cg = sgx_epc_page_get_cgroup(page); struct sgx_numa_node *node = section->node; + /* sgx_cg could be NULL if called from __sgx_sanitize_pages() */ + if (sgx_cg) { + sgx_cgroup_uncharge(sgx_cg); + sgx_put_cg(sgx_cg); + sgx_epc_page_set_cgroup(page, NULL); + } + spin_lock(&node->lock); page->owner = NULL; @@ -644,6 +673,8 @@ static bool __init sgx_setup_epc_section(u64 phys_addr, u64 size, section->pages[i].flags = 0; section->pages[i].owner = NULL; section->pages[i].poison = 0; + sgx_epc_page_set_cgroup(§ion->pages[i], NULL); + list_add_tail(§ion->pages[i].list, &sgx_dirty_page_list); } @@ -788,6 +819,7 @@ static void __init arch_update_sysfs_visibility(int nid) {} static bool __init sgx_page_cache_init(void) { u32 eax, ebx, ecx, edx, type; + u64 capacity = 0; u64 pa, size; int nid; int i; @@ -838,6 +870,7 @@ static bool __init sgx_page_cache_init(void) sgx_epc_sections[i].node = &sgx_numa_nodes[nid]; sgx_numa_nodes[nid].size += size; + capacity += size; sgx_nr_epc_sections++; } @@ -847,6 +880,8 @@ static bool __init sgx_page_cache_init(void) return false; } + misc_cg_set_capacity(MISC_CG_RES_SGX_EPC, capacity); + return true; } @@ -943,6 +978,9 @@ static int __init sgx_init(void) if (sgx_vepc_init() && ret) goto err_provision; + /* Setup cgroup if either the native or vepc driver is active */ + sgx_cgroup_init(); + return 0; err_provision: diff --git a/arch/x86/kernel/cpu/sgx/sgx.h b/arch/x86/kernel/cpu/sgx/sgx.h index ca34cd4f58ac..fae8eef10232 100644 --- a/arch/x86/kernel/cpu/sgx/sgx.h +++ b/arch/x86/kernel/cpu/sgx/sgx.h @@ -39,14 +39,35 @@ enum sgx_reclaim { SGX_DO_RECLAIM }; +struct sgx_cgroup; + struct sgx_epc_page { unsigned int section; u16 flags; u16 poison; struct sgx_encl_page *owner; struct list_head list; +#ifdef CONFIG_CGROUP_MISC + struct sgx_cgroup *sgx_cg; +#endif }; +static inline void sgx_epc_page_set_cgroup(struct sgx_epc_page *page, struct sgx_cgroup *cg) +{ +#ifdef CONFIG_CGROUP_MISC + page->sgx_cg = cg; +#endif +} + +static inline struct sgx_cgroup *sgx_epc_page_get_cgroup(struct sgx_epc_page *page) +{ +#ifdef CONFIG_CGROUP_MISC + return page->sgx_cg; +#else + return NULL; +#endif +} + /* * Contains the tracking data for NUMA nodes having EPC pages. Most importantly, * the free page list local to the node is stored here. diff --git a/include/linux/misc_cgroup.h b/include/linux/misc_cgroup.h index 440ed2bb8053..c9b47a5e966a 100644 --- a/include/linux/misc_cgroup.h +++ b/include/linux/misc_cgroup.h @@ -46,11 +46,13 @@ struct misc_res_ops { * @max: Maximum limit on the resource. * @usage: Current usage of the resource. * @events: Number of times, the resource limit exceeded. + * @priv: resource specific data. */ struct misc_res { u64 max; atomic64_t usage; atomic64_t events; + void *priv; }; /** From patchwork Fri May 31 22:26:22 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Haitao Huang X-Patchwork-Id: 13682245 Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.15]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 70F15824A0; Fri, 31 May 2024 22:26:36 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.15 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1717194398; cv=none; b=Lv1sFU7loMx8ESSj3RxnzpbFfoTFeRiwsPDtzBk4U06g/EU/A37HQYm4InSeCfANGHFoLPZJUP0TOfyFDJ/+wBgxqOj+kwQHiNOUksBBFufYOQnNJyjNz85p7UTYDKYTs9ZiMZIKD8YfQN7yzFCDD9GYlYRnCxScIZPk92hWoR8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1717194398; c=relaxed/simple; bh=ULMIKofVoIh99bNeyoHngXl40WOSk5hCz1677L8ajL8=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=GxpZAM2m1VsrArJXNQG0Z9DiG1yTTu7uouFkQMnFsd3kSzlXkzmCJ1sMOfLUM0+Je2XReb9lCOSJqN2Rd5DOx9P1ZoTsfSfUYWhKATEhw80kdSC57uSzC/epqaZ8C3n31/oW41cK2qfNfSkNhmWwOKqI0/bMhs8eex82Vg80WMQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com; spf=none smtp.mailfrom=linux.intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=ExDDjVMe; arc=none smtp.client-ip=192.198.163.15 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; spf=none smtp.mailfrom=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="ExDDjVMe" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1717194396; x=1748730396; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=ULMIKofVoIh99bNeyoHngXl40WOSk5hCz1677L8ajL8=; b=ExDDjVMeqKI98a/v/r4h3Zm52DmC+rmbhJBbly4nGI53TZ08ZSk/x7zn zzKTzvU0ayjJ5WypxTE0bNiiyQjqnSXKB/sXN0zZquu+2DYraSPFZak2g Nh4HmVLliXvuN5TUXuqUKM1xDdy8Dtgl7gsYd/QgBU/wv7vu27ZMtEUZw Z8zsCaiw8qaFPyShQfYKBtk6d3Epd9KjM7Ab5uhB3fbGxBX6UTbYKgJP/ O1frh9DH02aScTjuFf7B/AZYMuyi8cIGysy2LKHrblu90SF0Zdr5bpJM9 yujQFY77FRuqaKodcQOvrd/M8CdWFynG2lZzZc/qx8AuE4k7yLEqC7PtT g==; X-CSE-ConnectionGUID: LdjMkQ34SeKqwJYlmoHmbg== X-CSE-MsgGUID: o6UzMr67TNuirDzkl2ipNA== X-IronPort-AV: E=McAfee;i="6600,9927,11089"; a="13949775" X-IronPort-AV: E=Sophos;i="6.08,205,1712646000"; d="scan'208";a="13949775" Received: from fmviesa005.fm.intel.com ([10.60.135.145]) by fmvoesa109.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 31 May 2024 15:26:35 -0700 X-CSE-ConnectionGUID: gHdOx2DrSE6dNu0O2lundA== X-CSE-MsgGUID: VzwN5xI/TFmt7ePeOW75zg== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.08,205,1712646000"; d="scan'208";a="40736930" Received: from b4969161e530.jf.intel.com ([10.165.56.46]) by fmviesa005.fm.intel.com with ESMTP; 31 May 2024 15:26:34 -0700 From: Haitao Huang To: jarkko@kernel.org, dave.hansen@linux.intel.com, kai.huang@intel.com, tj@kernel.org, mkoutny@suse.com, linux-kernel@vger.kernel.org, linux-sgx@vger.kernel.org, x86@kernel.org, cgroups@vger.kernel.org, tglx@linutronix.de, mingo@redhat.com, bp@alien8.de, hpa@zytor.com, sohil.mehta@intel.com, tim.c.chen@linux.intel.com Cc: zhiquan1.li@intel.com, kristen@linux.intel.com, seanjc@google.com, zhanb@microsoft.com, anakrish@microsoft.com, mikko.ylinen@linux.intel.com, yangjie@microsoft.com, chrisyan@microsoft.com Subject: [PATCH v14 06/14] x86/sgx: Add sgx_epc_lru_list to encapsulate LRU list Date: Fri, 31 May 2024 15:26:22 -0700 Message-Id: <20240531222630.4634-7-haitao.huang@linux.intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20240531222630.4634-1-haitao.huang@linux.intel.com> References: <20240531222630.4634-1-haitao.huang@linux.intel.com> Precedence: bulk X-Mailing-List: linux-sgx@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Sean Christopherson Introduce a data structure to wrap the existing reclaimable list and its spinlock. Each cgroup later will have one instance of this structure to track EPC pages allocated for processes associated with the same cgroup. Just like the global SGX reclaimer (ksgxd), an EPC cgroup reclaims pages from the reclaimable list in this structure when its usage reaches near its limit. Use this structure to encapsulate the LRU list and its lock used by the global reclaimer. Signed-off-by: Sean Christopherson Co-developed-by: Kristen Carlson Accardi Signed-off-by: Kristen Carlson Accardi Co-developed-by: Haitao Huang Signed-off-by: Haitao Huang Cc: Sean Christopherson Reviewed-by: Jarkko Sakkinen Reviewed-by: Kai Huang Tested-by: Jarkko Sakkinen --- V6: - removed introduction to unreclaimables in commit message. V4: - Removed unneeded comments for the spinlock and the non-reclaimables. (Kai, Jarkko) - Revised the commit to add introduction comments for unreclaimables and multiple LRU lists.(Kai) - Reordered the patches: delay all changes for unreclaimables to later, and this one becomes the first change in the SGX subsystem. V3: - Removed the helper functions and revised commit messages. --- arch/x86/kernel/cpu/sgx/main.c | 39 +++++++++++++++++----------------- arch/x86/kernel/cpu/sgx/sgx.h | 15 +++++++++++++ 2 files changed, 35 insertions(+), 19 deletions(-) diff --git a/arch/x86/kernel/cpu/sgx/main.c b/arch/x86/kernel/cpu/sgx/main.c index d7a945d44268..75d6ce72b9b8 100644 --- a/arch/x86/kernel/cpu/sgx/main.c +++ b/arch/x86/kernel/cpu/sgx/main.c @@ -28,10 +28,9 @@ static DEFINE_XARRAY(sgx_epc_address_space); /* * These variables are part of the state of the reclaimer, and must be accessed - * with sgx_reclaimer_lock acquired. + * with sgx_global_lru.lock acquired. */ -static LIST_HEAD(sgx_active_page_list); -static DEFINE_SPINLOCK(sgx_reclaimer_lock); +static struct sgx_epc_lru_list sgx_global_lru; static atomic_long_t sgx_nr_free_pages = ATOMIC_LONG_INIT(0); @@ -306,13 +305,13 @@ static void sgx_reclaim_pages(void) int ret; int i; - spin_lock(&sgx_reclaimer_lock); + spin_lock(&sgx_global_lru.lock); for (i = 0; i < SGX_NR_TO_SCAN; i++) { - if (list_empty(&sgx_active_page_list)) + epc_page = list_first_entry_or_null(&sgx_global_lru.reclaimable, + struct sgx_epc_page, list); + if (!epc_page) break; - epc_page = list_first_entry(&sgx_active_page_list, - struct sgx_epc_page, list); list_del_init(&epc_page->list); encl_page = epc_page->owner; @@ -324,7 +323,7 @@ static void sgx_reclaim_pages(void) */ epc_page->flags &= ~SGX_EPC_PAGE_RECLAIMER_TRACKED; } - spin_unlock(&sgx_reclaimer_lock); + spin_unlock(&sgx_global_lru.lock); for (i = 0; i < cnt; i++) { epc_page = chunk[i]; @@ -347,9 +346,9 @@ static void sgx_reclaim_pages(void) continue; skip: - spin_lock(&sgx_reclaimer_lock); - list_add_tail(&epc_page->list, &sgx_active_page_list); - spin_unlock(&sgx_reclaimer_lock); + spin_lock(&sgx_global_lru.lock); + list_add_tail(&epc_page->list, &sgx_global_lru.reclaimable); + spin_unlock(&sgx_global_lru.lock); kref_put(&encl_page->encl->refcount, sgx_encl_release); @@ -380,7 +379,7 @@ static void sgx_reclaim_pages(void) static bool sgx_should_reclaim(unsigned long watermark) { return atomic_long_read(&sgx_nr_free_pages) < watermark && - !list_empty(&sgx_active_page_list); + !list_empty(&sgx_global_lru.reclaimable); } /* @@ -432,6 +431,8 @@ static bool __init sgx_page_reclaimer_init(void) ksgxd_tsk = tsk; + sgx_lru_init(&sgx_global_lru); + return true; } @@ -507,10 +508,10 @@ static struct sgx_epc_page *__sgx_alloc_epc_page(void) */ void sgx_mark_page_reclaimable(struct sgx_epc_page *page) { - spin_lock(&sgx_reclaimer_lock); + spin_lock(&sgx_global_lru.lock); page->flags |= SGX_EPC_PAGE_RECLAIMER_TRACKED; - list_add_tail(&page->list, &sgx_active_page_list); - spin_unlock(&sgx_reclaimer_lock); + list_add_tail(&page->list, &sgx_global_lru.reclaimable); + spin_unlock(&sgx_global_lru.lock); } /** @@ -525,18 +526,18 @@ void sgx_mark_page_reclaimable(struct sgx_epc_page *page) */ int sgx_unmark_page_reclaimable(struct sgx_epc_page *page) { - spin_lock(&sgx_reclaimer_lock); + spin_lock(&sgx_global_lru.lock); if (page->flags & SGX_EPC_PAGE_RECLAIMER_TRACKED) { /* The page is being reclaimed. */ if (list_empty(&page->list)) { - spin_unlock(&sgx_reclaimer_lock); + spin_unlock(&sgx_global_lru.lock); return -EBUSY; } list_del(&page->list); page->flags &= ~SGX_EPC_PAGE_RECLAIMER_TRACKED; } - spin_unlock(&sgx_reclaimer_lock); + spin_unlock(&sgx_global_lru.lock); return 0; } @@ -578,7 +579,7 @@ struct sgx_epc_page *sgx_alloc_epc_page(void *owner, enum sgx_reclaim reclaim) break; } - if (list_empty(&sgx_active_page_list)) { + if (list_empty(&sgx_global_lru.reclaimable)) { page = ERR_PTR(-ENOMEM); break; } diff --git a/arch/x86/kernel/cpu/sgx/sgx.h b/arch/x86/kernel/cpu/sgx/sgx.h index fae8eef10232..3cf5a59a4eac 100644 --- a/arch/x86/kernel/cpu/sgx/sgx.h +++ b/arch/x86/kernel/cpu/sgx/sgx.h @@ -114,6 +114,21 @@ static inline void *sgx_get_epc_virt_addr(struct sgx_epc_page *page) return section->virt_addr + index * PAGE_SIZE; } +/* + * Contains EPC pages tracked by the global reclaimer (ksgxd) or an EPC + * cgroup. + */ +struct sgx_epc_lru_list { + spinlock_t lock; + struct list_head reclaimable; +}; + +static inline void sgx_lru_init(struct sgx_epc_lru_list *lru) +{ + spin_lock_init(&lru->lock); + INIT_LIST_HEAD(&lru->reclaimable); +} + void sgx_free_epc_page(struct sgx_epc_page *page); void sgx_reclaim_direct(void); From patchwork Fri May 31 22:26:23 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Haitao Huang X-Patchwork-Id: 13682246 Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.15]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 254D9839E2; Fri, 31 May 2024 22:26:37 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.15 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1717194399; cv=none; b=g7+44Me5/tFAebnS2RqBV2AnuxzoW6jEf/VbLRyOMJxSC4uE8LixFgCxGlvzG1GeUAA+XD3pYmaQCMrHioi/4ATxC6bt03VBcMR2Zzffqcz5iP71qge0Erloisv7qME0l5UOAKDWubw9/8IVobhyfOwOzLdqY+qfEPzGAP+aYlU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1717194399; c=relaxed/simple; bh=E42w3c+6Y5YrvHQsNc8yLjQB5Qr3qeGM4uvZtGJ21I4=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=NDWv2riKwsU96cmzJz9YV6LFC6fnRznv4sGPpnxbrgAo0nVFG3pyhr44P9D68yhqBeI1ZEM+4QxmlsQQl1CtSulLHs1BfuQv7eaTrfX+ivOddyHbo722Oaiv2CdDeqFYFpxqoChgIFIE+tlvSBwjVMAyDddysjqzPwHy4H7QuRY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com; spf=none smtp.mailfrom=linux.intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=SFAtrEdY; arc=none smtp.client-ip=192.198.163.15 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; spf=none smtp.mailfrom=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="SFAtrEdY" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1717194397; x=1748730397; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=E42w3c+6Y5YrvHQsNc8yLjQB5Qr3qeGM4uvZtGJ21I4=; b=SFAtrEdYWwK7YQ8k9hinOJK8hiPAxQH2tl9CAOk+zd3Niyxo8JeFl/VB KFBNk+cLkobG/+VLLNf/OyXr4VdTVbrf/udM0JMcuzOB61uQ3AIU+JSPj RyWC7DbGorWKC/ZcuH9wJ61kDtG68Ox7WLBHCo55h8LZuNy678+OmSyap V4Hq9zLsiy3TB2MThze27kzsHq7LgusjxxCMEo0EcqiWu2jpFURaHhCrO tvNqnYfXJPCzMX7iNJWE4QXMYTjCXccDG/9QY0DM96NhWxlKkcwts8zqf PN17Y0IhbSOQH6kQ6Zmm8EGn8hz0N3G3I1k8Eq+zf6VwKgj69fGdOGahv Q==; X-CSE-ConnectionGUID: v5cem1KfQIifacZpYhOUpQ== X-CSE-MsgGUID: vtYNQoQ7SbeCJPUCbams9Q== X-IronPort-AV: E=McAfee;i="6600,9927,11089"; a="13949785" X-IronPort-AV: E=Sophos;i="6.08,205,1712646000"; d="scan'208";a="13949785" Received: from fmviesa005.fm.intel.com ([10.60.135.145]) by fmvoesa109.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 31 May 2024 15:26:35 -0700 X-CSE-ConnectionGUID: GWG2+tU0SEW0gFQN+ELnMw== X-CSE-MsgGUID: fwvSUvxSTnCmc81uEgMRuA== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.08,205,1712646000"; d="scan'208";a="40736933" Received: from b4969161e530.jf.intel.com ([10.165.56.46]) by fmviesa005.fm.intel.com with ESMTP; 31 May 2024 15:26:35 -0700 From: Haitao Huang To: jarkko@kernel.org, dave.hansen@linux.intel.com, kai.huang@intel.com, tj@kernel.org, mkoutny@suse.com, linux-kernel@vger.kernel.org, linux-sgx@vger.kernel.org, x86@kernel.org, cgroups@vger.kernel.org, tglx@linutronix.de, mingo@redhat.com, bp@alien8.de, hpa@zytor.com, sohil.mehta@intel.com, tim.c.chen@linux.intel.com Cc: zhiquan1.li@intel.com, kristen@linux.intel.com, seanjc@google.com, zhanb@microsoft.com, anakrish@microsoft.com, mikko.ylinen@linux.intel.com, yangjie@microsoft.com, chrisyan@microsoft.com Subject: [PATCH v14 07/14] x86/sgx: Abstract tracking reclaimable pages in LRU Date: Fri, 31 May 2024 15:26:23 -0700 Message-Id: <20240531222630.4634-8-haitao.huang@linux.intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20240531222630.4634-1-haitao.huang@linux.intel.com> References: <20240531222630.4634-1-haitao.huang@linux.intel.com> Precedence: bulk X-Mailing-List: linux-sgx@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Kristen Carlson Accardi The SGX driver tracks reclaimable EPC pages by adding a newly allocated page into the global LRU list in sgx_mark_page_reclaimable(), and doing the opposite in sgx_unmark_page_reclaimable(). To support SGX EPC cgroup, the SGX driver will need to maintain an LRU list for each cgroup, and each newly allocated EPC page will need to be added to the LRU of associated cgroup, not always the global LRU list. When sgx_mark_page_reclaimable() is called, the cgroup that the newly allocated EPC page belongs to is already known, i.e., it has been set to the 'struct sgx_epc_page'. Add a helper, sgx_epc_page_lru(), to return the LRU that the EPC page should be added to for the given EPC page. Currently it just returns the global LRU. Change sgx_{mark|unmark}_page_reclaimable() to use the helper function to get the LRU from the EPC page instead of referring to the global LRU directly. This allows EPC page being able to be tracked in "per-cgroup" LRU when that becomes ready. Co-developed-by: Sean Christopherson Signed-off-by: Sean Christopherson Signed-off-by: Kristen Carlson Accardi Co-developed-by: Haitao Huang Signed-off-by: Haitao Huang Reviewed-by: Jarkko Sakkinen Reviewed-by: Kai Huang Tested-by: Jarkko Sakkinen --- V13: - Revise commit log (Kai) - Rename sgx_lru_list() to sgx_epc_page_lru() V7: - Split this out from the big patch, #10 in V6. (Dave, Kai) --- arch/x86/kernel/cpu/sgx/main.c | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/arch/x86/kernel/cpu/sgx/main.c b/arch/x86/kernel/cpu/sgx/main.c index 75d6ce72b9b8..1fa73250e2b9 100644 --- a/arch/x86/kernel/cpu/sgx/main.c +++ b/arch/x86/kernel/cpu/sgx/main.c @@ -32,6 +32,11 @@ static DEFINE_XARRAY(sgx_epc_address_space); */ static struct sgx_epc_lru_list sgx_global_lru; +static inline struct sgx_epc_lru_list *sgx_epc_page_lru(struct sgx_epc_page *epc_page) +{ + return &sgx_global_lru; +} + static atomic_long_t sgx_nr_free_pages = ATOMIC_LONG_INIT(0); /* Nodes with one or more EPC sections. */ @@ -500,25 +505,24 @@ static struct sgx_epc_page *__sgx_alloc_epc_page(void) } /** - * sgx_mark_page_reclaimable() - Mark a page as reclaimable + * sgx_mark_page_reclaimable() - Mark a page as reclaimable and track it in a LRU. * @page: EPC page - * - * Mark a page as reclaimable and add it to the active page list. Pages - * are automatically removed from the active list when freed. */ void sgx_mark_page_reclaimable(struct sgx_epc_page *page) { - spin_lock(&sgx_global_lru.lock); + struct sgx_epc_lru_list *lru = sgx_epc_page_lru(page); + + spin_lock(&lru->lock); page->flags |= SGX_EPC_PAGE_RECLAIMER_TRACKED; - list_add_tail(&page->list, &sgx_global_lru.reclaimable); - spin_unlock(&sgx_global_lru.lock); + list_add_tail(&page->list, &lru->reclaimable); + spin_unlock(&lru->lock); } /** - * sgx_unmark_page_reclaimable() - Remove a page from the reclaim list + * sgx_unmark_page_reclaimable() - Remove a page from its tracking LRU * @page: EPC page * - * Clear the reclaimable flag and remove the page from the active page list. + * Clear the reclaimable flag if set and remove the page from its LRU. * * Return: * 0 on success, @@ -526,18 +530,20 @@ void sgx_mark_page_reclaimable(struct sgx_epc_page *page) */ int sgx_unmark_page_reclaimable(struct sgx_epc_page *page) { - spin_lock(&sgx_global_lru.lock); + struct sgx_epc_lru_list *lru = sgx_epc_page_lru(page); + + spin_lock(&lru->lock); if (page->flags & SGX_EPC_PAGE_RECLAIMER_TRACKED) { /* The page is being reclaimed. */ if (list_empty(&page->list)) { - spin_unlock(&sgx_global_lru.lock); + spin_unlock(&lru->lock); return -EBUSY; } list_del(&page->list); page->flags &= ~SGX_EPC_PAGE_RECLAIMER_TRACKED; } - spin_unlock(&sgx_global_lru.lock); + spin_unlock(&lru->lock); return 0; } From patchwork Fri May 31 22:26:24 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Haitao Huang X-Patchwork-Id: 13682248 Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.15]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 596F112FB2F; Fri, 31 May 2024 22:26:38 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.15 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1717194400; cv=none; b=ptFZML++jooJt4RWc8hpYaWM5DBrku8XbVKZ1SA5pazVD33LI511/zzl6v+k2bUtMqP7dLNqWEidJ/4GOzQWNM09IWq4zsTiZ2+ALSaPJkpxx95en8AP2gSbNFXyEG/g1GGd3mbrYZ9B1aYvk6TYy/cWnjS8RMwn0hQOKJw0lhw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1717194400; c=relaxed/simple; bh=UJuS7mu2GOF4JEYJpGcdD5mywD6itpqClAursfA189Y=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=g8udTiGYpJWPxukMKZcnh/qVwKto5Bb3CRFxU1ws5EfUtIvZTYxA+sFZ2t/pCwnuJsqKVwkaEENkGZVMdfMx8WKAjuUlGup2vBQ1knDvx69sr7JsjsDOSxfFFwrmrUJpDbuSen8PkqvvZnIe/ryWOr1HEePuZtl3O61QvsXUcJM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com; spf=none smtp.mailfrom=linux.intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=LrenDag6; arc=none smtp.client-ip=192.198.163.15 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; spf=none smtp.mailfrom=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="LrenDag6" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1717194398; x=1748730398; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=UJuS7mu2GOF4JEYJpGcdD5mywD6itpqClAursfA189Y=; b=LrenDag60kJzAGhpuAWCBD4psjFgShUFlhCVJzBypIozmwVZrvE9aXq5 uSBrUX655QLrdtSofNJc3KVvgwfeIriU9QnbJOXpCUm2I0POBUBHiRKFW qamTXdvlXnvhRAoFiztwn3EOc3Rw7QN/X7zgscJEbEhpb8b7Ob/h1k1+1 t7UU7ZJJ3sCx7Fsx76i7KIOytnVwSjtEd4zkzyhqQTl8VQ1C/cCn7LZwL JeoqaSOlk4zHyeWIKw9mpReY9sbX2AztIydS2vX3tn5N/vKOkRA8sz+hP XmsAoNctz1RPvK3M+lC/9bQhj9VKTMSim9rW2ihV8czq8Bq4Z3Zor9lNW Q==; X-CSE-ConnectionGUID: qrYFusJnR7udI0/fdvwPyA== X-CSE-MsgGUID: 2GQoykUMQMus5/FEkhgUpQ== X-IronPort-AV: E=McAfee;i="6600,9927,11089"; a="13949794" X-IronPort-AV: E=Sophos;i="6.08,205,1712646000"; d="scan'208";a="13949794" Received: from fmviesa005.fm.intel.com ([10.60.135.145]) by fmvoesa109.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 31 May 2024 15:26:36 -0700 X-CSE-ConnectionGUID: pS6wsOZoSrqiKwDEH6IGQg== X-CSE-MsgGUID: iE8fLZ7/S+ieRL/rnc9pow== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.08,205,1712646000"; d="scan'208";a="40736936" Received: from b4969161e530.jf.intel.com ([10.165.56.46]) by fmviesa005.fm.intel.com with ESMTP; 31 May 2024 15:26:35 -0700 From: Haitao Huang To: jarkko@kernel.org, dave.hansen@linux.intel.com, kai.huang@intel.com, tj@kernel.org, mkoutny@suse.com, linux-kernel@vger.kernel.org, linux-sgx@vger.kernel.org, x86@kernel.org, cgroups@vger.kernel.org, tglx@linutronix.de, mingo@redhat.com, bp@alien8.de, hpa@zytor.com, sohil.mehta@intel.com, tim.c.chen@linux.intel.com Cc: zhiquan1.li@intel.com, kristen@linux.intel.com, seanjc@google.com, zhanb@microsoft.com, anakrish@microsoft.com, mikko.ylinen@linux.intel.com, yangjie@microsoft.com, chrisyan@microsoft.com Subject: [PATCH v14 08/14] x86/sgx: Add basic EPC reclamation flow for cgroup Date: Fri, 31 May 2024 15:26:24 -0700 Message-Id: <20240531222630.4634-9-haitao.huang@linux.intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20240531222630.4634-1-haitao.huang@linux.intel.com> References: <20240531222630.4634-1-haitao.huang@linux.intel.com> Precedence: bulk X-Mailing-List: linux-sgx@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Kristen Carlson Accardi Currently in the EPC page allocation, the kernel simply fails the allocation when the current EPC cgroup fails to charge due to its usage reaching limit. This is not ideal. When that happens, a better way is to reclaim EPC page(s) from the current EPC cgroup (and/or its descendants) to reduce its usage so the new allocation can succeed. Add the basic building blocks to support per-cgroup reclamation. Currently the kernel only has one place to reclaim EPC pages: the global EPC LRU list. To support the "per-cgroup" EPC reclaim, maintain an LRU list for each EPC cgroup, and introduce a "cgroup" variant function to reclaim EPC pages from a given EPC cgroup and its descendants. Currently the kernel does the global EPC reclaim in sgx_reclaim_page(). It always tries to reclaim EPC pages in batch of SGX_NR_TO_SCAN (16) pages. Specifically, it always "scans", or "isolates" SGX_NR_TO_SCAN pages from the global LRU, and then tries to reclaim these pages at once for better performance. Implement the "cgroup" variant EPC reclaim in a similar way, but keep the implementation simple: 1) change sgx_reclaim_pages() to take an LRU as input, and return the pages that are "scanned" and attempted for reclamation (but not necessarily reclaimed successfully); 2) loop the given EPC cgroup and its descendants and do the new sgx_reclaim_pages() until SGX_NR_TO_SCAN pages are "scanned". This implementation, encapsulated in sgx_cgroup_reclaim_pages(), always tries to reclaim SGX_NR_TO_SCAN pages from the LRU of the given EPC cgroup, and only moves to its descendants when there's no enough reclaimable EPC pages to "scan" in its LRU. It should be enough for most cases. In other cases, the caller may invoke this function in a loop to ensure enough pages reclaimed for its usage. To ensure all descendant groups scanned in a round-robin fashion in those cases, sgx_cgroup_reclaim_pages() takes in a starting cgroup and returns the next cgroup that the caller can pass in as the new starting cgroup for a subsequent call. Note, this simple implementation doesn't _exactly_ mimic the current global EPC reclaim (which always tries to do the actual reclaim in batch of SGX_NR_TO_SCAN pages): when LRUs have less than SGX_NR_TO_SCAN reclaimable pages, the actual reclaim of EPC pages will be split into smaller batches _across_ multiple LRUs with each being smaller than SGX_NR_TO_SCAN pages. A more precise way to mimic the current global EPC reclaim would be to have a new function to only "scan" (or "isolate") SGX_NR_TO_SCAN pages _across_ the given EPC cgroup _AND_ its descendants, and then do the actual reclaim in one batch. But this is unnecessarily complicated at this stage. Alternatively, the current sgx_reclaim_pages() could be changed to return the actual "reclaimed" pages, but not "scanned" pages. However, the reclamation is a lengthy process, forcing a successful reclamation of predetermined number of pages may block the caller for too long. And that may not be acceptable in some synchronous contexts, e.g., in serving an ioctl(). With this building block in place, add synchronous reclamation support in sgx_cgroup_try_charge(): trigger a call to sgx_cgroup_reclaim_pages() if the cgroup reaches its limit and the caller allows synchronous reclaim as indicated by s newly added parameter. A later patch will add support for asynchronous reclamation reusing sgx_cgroup_reclaim_pages(). Note all reclaimable EPC pages are still tracked in the global LRU thus no per-cgroup reclamation is actually active at the moment. Per-cgroup tracking and reclamation will be turned on in the end after all necessary infrastructure is in place. Co-developed-by: Sean Christopherson Signed-off-by: Sean Christopherson Signed-off-by: Kristen Carlson Accardi Co-developed-by: Haitao Huang Signed-off-by: Haitao Huang Reviewed-by: Jarkko Sakkinen Reviewed-by: Kai Huang Tested-by: Jarkko Sakkinen --- V14: - Allow sgx_cgroup_reclaim_pages() to continue from previous tree-walk. It takes in a 'start' node and returns the 'next' node for the caller to use as the new 'start'. This is to ensure pages in lower level cgroups can be reclaimed if all pages in upper level nodes are "too young". (Kai) - Move renaming sgx_should_reclaim() to sgx_should_reclaim_global() from a later patch to this one. (Kai) V11: - Use commit message suggested by Kai - Remove "usage" comments for functions. (Kai) V10: - Simplify the signature by removing a pointer to nr_to_scan (Kai) - Return pages attempted instead of reclaimed as it is really what the cgroup caller needs to track progress. This further simplifies the design. - Merge patch for exposing sgx_reclaim_pages() with basic synchronous reclamation. (Kai) - Shorten names for EPC cgroup functions. (Jarkko) - Fix/add comments to justify the design (Kai) - Separate out a helper for for addressing single iteration of the loop in sgx_cgroup_try_charge(). (Jarkko) V9: - Add comments for static variables. (Jarkko) V8: - Use width of 80 characters in text paragraphs. (Jarkko) - Remove alignment for substructure variables. (Jarkko) V7: - Reworked from patch 9 of V6, "x86/sgx: Restructure top-level EPC reclaim function". Do not split the top level function (Kai) - Dropped patches 7 and 8 of V6. - Split this out from the big patch, #10 in V6. (Dave, Kai) --- arch/x86/kernel/cpu/sgx/epc_cgroup.c | 149 ++++++++++++++++++++++++++- arch/x86/kernel/cpu/sgx/epc_cgroup.h | 5 +- arch/x86/kernel/cpu/sgx/main.c | 55 ++++++---- arch/x86/kernel/cpu/sgx/sgx.h | 1 + 4 files changed, 183 insertions(+), 27 deletions(-) diff --git a/arch/x86/kernel/cpu/sgx/epc_cgroup.c b/arch/x86/kernel/cpu/sgx/epc_cgroup.c index 5c484fd10160..4406077acd1c 100644 --- a/arch/x86/kernel/cpu/sgx/epc_cgroup.c +++ b/arch/x86/kernel/cpu/sgx/epc_cgroup.c @@ -8,16 +8,158 @@ static struct sgx_cgroup sgx_cg_root; /** - * sgx_cgroup_try_charge() - try to charge cgroup for a single EPC page + * sgx_cgroup_lru_empty() - check if a cgroup tree has no pages on its LRUs + * @root: Root of the tree to check * + * Return: %true if all cgroups under the specified root have empty LRU lists. + */ +static bool sgx_cgroup_lru_empty(struct misc_cg *root) +{ + struct cgroup_subsys_state *css_root; + struct cgroup_subsys_state *pos; + struct sgx_cgroup *sgx_cg; + bool ret = true; + + /* + * Caller must ensure css_root ref acquired + */ + css_root = &root->css; + + rcu_read_lock(); + css_for_each_descendant_pre(pos, css_root) { + if (!css_tryget(pos)) + break; + + rcu_read_unlock(); + + sgx_cg = sgx_cgroup_from_misc_cg(css_misc(pos)); + + spin_lock(&sgx_cg->lru.lock); + ret = list_empty(&sgx_cg->lru.reclaimable); + spin_unlock(&sgx_cg->lru.lock); + + rcu_read_lock(); + css_put(pos); + if (!ret) + break; + } + + rcu_read_unlock(); + + return ret; +} + +/** + * sgx_cgroup_reclaim_pages() - reclaim EPC from a cgroup tree + * @root: The root of cgroup tree to reclaim from. + * @start: The descendant cgroup from which to start the tree walking. + * + * This function performs a pre-order walk in the cgroup tree under the given + * root, starting from the node %start, or from the root if %start is NULL. The + * function will attempt to reclaim pages at each node until a fixed number of + * pages (%SGX_NR_TO_SCAN) are attempted for reclamation. No guarantee of + * success on the actual reclamation process. In extreme cases, if all pages in + * front of the LRUs are recently accessed, i.e., considered "too young" to + * reclaim, no page will actually be reclaimed after walking the whole tree. + * + * In some cases, a caller may want to ensure enough reclamation until its + * specific need is met. In those cases, the caller should invoke this function + * in a loop, and at each iteration passes in the same root and the next node + * returned from the previous call as the new %start. + * + * Return: The next misc cgroup in the subtree to continue the scanning and + * attempt for more reclamation from this subtree if needed. Caller must + * release the reference if the returned is not used as %start for a subsequent + * call. + */ +static struct misc_cg *sgx_cgroup_reclaim_pages(struct misc_cg *root, struct misc_cg *start) +{ + struct cgroup_subsys_state *css_root, *pos; + struct cgroup_subsys_state *next = NULL; + struct sgx_cgroup *sgx_cg; + unsigned int cnt = 0; + + /* Caller must ensure css_root and start ref's acquired */ + css_root = &root->css; + if (start) + pos = &start->css; + else + pos = css_root; + + while (cnt < SGX_NR_TO_SCAN) { + sgx_cg = sgx_cgroup_from_misc_cg(css_misc(pos)); + cnt += sgx_reclaim_pages(&sgx_cg->lru); + + rcu_read_lock(); + + next = css_next_descendant_pre(pos, css_root); + + if (pos != css_root) + css_put(pos); + + if (!next || !css_tryget(next)) { + /* We are done if next is NULL or not safe to continue + * the walk if next is dead. Return NULL and the caller + * determines whether to restart from root. + */ + rcu_read_unlock(); + return NULL; + } + + rcu_read_unlock(); + pos = next; + } + + return css_misc(next); +} + +static int __sgx_cgroup_try_charge(struct sgx_cgroup *epc_cg) +{ + if (!misc_cg_try_charge(MISC_CG_RES_SGX_EPC, epc_cg->cg, PAGE_SIZE)) + return 0; + + /* No reclaimable pages left in the cgroup */ + if (sgx_cgroup_lru_empty(epc_cg->cg)) + return -ENOMEM; + + if (signal_pending(current)) + return -ERESTARTSYS; + + return -EBUSY; +} + +/** + * sgx_cgroup_try_charge() - try to charge cgroup for a single EPC page * @sgx_cg: The EPC cgroup to be charged for the page. + * @reclaim: Whether or not synchronous EPC reclaim is allowed. * Return: * * %0 - If successfully charged. * * -errno - for failures. */ -int sgx_cgroup_try_charge(struct sgx_cgroup *sgx_cg) +int sgx_cgroup_try_charge(struct sgx_cgroup *sgx_cg, enum sgx_reclaim reclaim) { - return misc_cg_try_charge(MISC_CG_RES_SGX_EPC, sgx_cg->cg, PAGE_SIZE); + int ret; + struct misc_cg *cg_next = NULL; + + for (;;) { + ret = __sgx_cgroup_try_charge(sgx_cg); + + if (ret != -EBUSY) + goto out; + + if (reclaim == SGX_NO_RECLAIM) { + ret = -ENOMEM; + goto out; + } + + cg_next = sgx_cgroup_reclaim_pages(sgx_cg->cg, cg_next); + cond_resched(); + } + +out: + if (cg_next != sgx_cg->cg) + put_misc_cg(cg_next); + return ret; } /** @@ -42,6 +184,7 @@ static void sgx_cgroup_free(struct misc_cg *cg) static void sgx_cgroup_misc_init(struct misc_cg *cg, struct sgx_cgroup *sgx_cg) { + sgx_lru_init(&sgx_cg->lru); cg->res[MISC_CG_RES_SGX_EPC].priv = sgx_cg; sgx_cg->cg = cg; } diff --git a/arch/x86/kernel/cpu/sgx/epc_cgroup.h b/arch/x86/kernel/cpu/sgx/epc_cgroup.h index bd9606479e67..538524f5669d 100644 --- a/arch/x86/kernel/cpu/sgx/epc_cgroup.h +++ b/arch/x86/kernel/cpu/sgx/epc_cgroup.h @@ -20,7 +20,7 @@ static inline struct sgx_cgroup *sgx_get_current_cg(void) static inline void sgx_put_cg(struct sgx_cgroup *sgx_cg) { } -static inline int sgx_cgroup_try_charge(struct sgx_cgroup *sgx_cg) +static inline int sgx_cgroup_try_charge(struct sgx_cgroup *sgx_cg, enum sgx_reclaim reclaim) { return 0; } @@ -33,6 +33,7 @@ static inline void sgx_cgroup_init(void) { } struct sgx_cgroup { struct misc_cg *cg; + struct sgx_epc_lru_list lru; }; static inline struct sgx_cgroup *sgx_cgroup_from_misc_cg(struct misc_cg *cg) @@ -63,7 +64,7 @@ static inline void sgx_put_cg(struct sgx_cgroup *sgx_cg) put_misc_cg(sgx_cg->cg); } -int sgx_cgroup_try_charge(struct sgx_cgroup *sgx_cg); +int sgx_cgroup_try_charge(struct sgx_cgroup *sgx_cg, enum sgx_reclaim reclaim); void sgx_cgroup_uncharge(struct sgx_cgroup *sgx_cg); void sgx_cgroup_init(void); diff --git a/arch/x86/kernel/cpu/sgx/main.c b/arch/x86/kernel/cpu/sgx/main.c index 1fa73250e2b9..71e84937bc17 100644 --- a/arch/x86/kernel/cpu/sgx/main.c +++ b/arch/x86/kernel/cpu/sgx/main.c @@ -286,11 +286,14 @@ static void sgx_reclaimer_write(struct sgx_epc_page *epc_page, mutex_unlock(&encl->lock); } -/* - * Take a fixed number of pages from the head of the active page pool and - * reclaim them to the enclave's private shmem files. Skip the pages, which have - * been accessed since the last scan. Move those pages to the tail of active - * page pool so that the pages get scanned in LRU like fashion. +/** + * sgx_reclaim_pages() - Attempt to reclaim a fixed number of pages from an LRU + * @lru: The LRU from which pages are reclaimed. + * + * Take a fixed number of pages from the head of a given LRU and reclaim them to + * the enclave's private shmem files. Skip the pages, which have been accessed + * since the last scan. Move those pages to the tail of the list so that the + * pages get scanned in LRU like fashion. * * Batch process a chunk of pages (at the moment 16) in order to degrade amount * of IPI's and ETRACK's potentially required. sgx_encl_ewb() does degrade a bit @@ -298,8 +301,10 @@ static void sgx_reclaimer_write(struct sgx_epc_page *epc_page, * + EWB) but not sufficiently. Reclaiming one page at a time would also be * problematic as it would increase the lock contention too much, which would * halt forward progress. + * + * Return: Number of pages attempted for reclamation. */ -static void sgx_reclaim_pages(void) +unsigned int sgx_reclaim_pages(struct sgx_epc_lru_list *lru) { struct sgx_epc_page *chunk[SGX_NR_TO_SCAN]; struct sgx_backing backing[SGX_NR_TO_SCAN]; @@ -310,10 +315,9 @@ static void sgx_reclaim_pages(void) int ret; int i; - spin_lock(&sgx_global_lru.lock); + spin_lock(&lru->lock); for (i = 0; i < SGX_NR_TO_SCAN; i++) { - epc_page = list_first_entry_or_null(&sgx_global_lru.reclaimable, - struct sgx_epc_page, list); + epc_page = list_first_entry_or_null(&lru->reclaimable, struct sgx_epc_page, list); if (!epc_page) break; @@ -328,7 +332,7 @@ static void sgx_reclaim_pages(void) */ epc_page->flags &= ~SGX_EPC_PAGE_RECLAIMER_TRACKED; } - spin_unlock(&sgx_global_lru.lock); + spin_unlock(&lru->lock); for (i = 0; i < cnt; i++) { epc_page = chunk[i]; @@ -351,9 +355,9 @@ static void sgx_reclaim_pages(void) continue; skip: - spin_lock(&sgx_global_lru.lock); - list_add_tail(&epc_page->list, &sgx_global_lru.reclaimable); - spin_unlock(&sgx_global_lru.lock); + spin_lock(&lru->lock); + list_add_tail(&epc_page->list, &lru->reclaimable); + spin_unlock(&lru->lock); kref_put(&encl_page->encl->refcount, sgx_encl_release); @@ -379,14 +383,21 @@ static void sgx_reclaim_pages(void) sgx_free_epc_page(epc_page); } + + return cnt; } -static bool sgx_should_reclaim(unsigned long watermark) +static bool sgx_should_reclaim_global(unsigned long watermark) { return atomic_long_read(&sgx_nr_free_pages) < watermark && !list_empty(&sgx_global_lru.reclaimable); } +static void sgx_reclaim_pages_global(void) +{ + sgx_reclaim_pages(&sgx_global_lru); +} + /* * sgx_reclaim_direct() should be called (without enclave's mutex held) * in locations where SGX memory resources might be low and might be @@ -394,8 +405,8 @@ static bool sgx_should_reclaim(unsigned long watermark) */ void sgx_reclaim_direct(void) { - if (sgx_should_reclaim(SGX_NR_LOW_PAGES)) - sgx_reclaim_pages(); + if (sgx_should_reclaim_global(SGX_NR_LOW_PAGES)) + sgx_reclaim_pages_global(); } static int ksgxd(void *p) @@ -415,10 +426,10 @@ static int ksgxd(void *p) wait_event_freezable(ksgxd_waitq, kthread_should_stop() || - sgx_should_reclaim(SGX_NR_HIGH_PAGES)); + sgx_should_reclaim_global(SGX_NR_HIGH_PAGES)); - if (sgx_should_reclaim(SGX_NR_HIGH_PAGES)) - sgx_reclaim_pages(); + if (sgx_should_reclaim_global(SGX_NR_HIGH_PAGES)) + sgx_reclaim_pages_global(); cond_resched(); } @@ -572,7 +583,7 @@ struct sgx_epc_page *sgx_alloc_epc_page(void *owner, enum sgx_reclaim reclaim) int ret; sgx_cg = sgx_get_current_cg(); - ret = sgx_cgroup_try_charge(sgx_cg); + ret = sgx_cgroup_try_charge(sgx_cg, reclaim); if (ret) { sgx_put_cg(sgx_cg); return ERR_PTR(ret); @@ -600,7 +611,7 @@ struct sgx_epc_page *sgx_alloc_epc_page(void *owner, enum sgx_reclaim reclaim) break; } - sgx_reclaim_pages(); + sgx_reclaim_pages_global(); cond_resched(); } @@ -613,7 +624,7 @@ struct sgx_epc_page *sgx_alloc_epc_page(void *owner, enum sgx_reclaim reclaim) sgx_put_cg(sgx_cg); } - if (sgx_should_reclaim(SGX_NR_LOW_PAGES)) + if (sgx_should_reclaim_global(SGX_NR_LOW_PAGES)) wake_up(&ksgxd_waitq); return page; diff --git a/arch/x86/kernel/cpu/sgx/sgx.h b/arch/x86/kernel/cpu/sgx/sgx.h index 3cf5a59a4eac..89adac646381 100644 --- a/arch/x86/kernel/cpu/sgx/sgx.h +++ b/arch/x86/kernel/cpu/sgx/sgx.h @@ -135,6 +135,7 @@ void sgx_reclaim_direct(void); void sgx_mark_page_reclaimable(struct sgx_epc_page *page); int sgx_unmark_page_reclaimable(struct sgx_epc_page *page); struct sgx_epc_page *sgx_alloc_epc_page(void *owner, enum sgx_reclaim reclaim); +unsigned int sgx_reclaim_pages(struct sgx_epc_lru_list *lru); void sgx_ipi_cb(void *info); From patchwork Fri May 31 22:26:25 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Haitao Huang X-Patchwork-Id: 13682247 Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.15]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 8980212FF7B; Fri, 31 May 2024 22:26:38 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.15 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1717194400; cv=none; b=CoZizrLXb2dCC5Zv9nmrRsBsUG1WhSutR/UorLq3LJQKwB8YiEVn0cxEGrVnuEjYAuZYGQ/lr3uI9SGKYNBpE9AOpX49k1erSKSfQ24s70d7I9TewFTukk/tlPeAxlxS1vkTCrwtTikQnhX5Y0ctxeg1fHCfbeVb1zLpURDPfjQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1717194400; c=relaxed/simple; bh=JhBkkvxcxApIUu75BdrXooosSs++QdD4f2HYG2mD4Rk=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=lJoLjzxUjoYPgtY91Qk6NXLJ3mqzm983sDyKTRBKCR3TTtVlX9TvQMh8G3e0ohygD9ds159hrsrPnzic4kZphgaqjKWGoiOW2nGKa99XE2iwcl9b3zURMykIAyImkzyGVTNMylV1wccLvfxjjMLM6tWBfp0iQlSUrj0BDRqTAZE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com; spf=none smtp.mailfrom=linux.intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=J/sjouoK; arc=none smtp.client-ip=192.198.163.15 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; spf=none smtp.mailfrom=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="J/sjouoK" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1717194399; x=1748730399; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=JhBkkvxcxApIUu75BdrXooosSs++QdD4f2HYG2mD4Rk=; b=J/sjouoKe6VxxKQagS1qPhT7g0h+Vw4xnr4QeNCVqLS0wtKQFu/qUmDl 1E9liXj7tEQcxfenWSHlxtlgQLw63eZCSg8EUQwuMK5qcS0eZc4Bogx8x RTudQ0JY4AakXFASyrJfbC2Fy8GNalRkwV66yVy0VzD3kIzWpYLyEb4Dp DCeu4Pw7vyROqaHS8NrlzFxJ8F7gat2sTXEwwSjYLi3sR07JASrD5SO7m /U2v5BGafrIa/SfHFMuGCqjVfFgRXlsuXIoBrklGbdZ9TsXzy+Of9t7Rg 44Ro8pcrWRFH/R8VoEYqLCuL92xQ6YoN4N3Dl69O9wjrfBUB4p7xrOhOb g==; X-CSE-ConnectionGUID: fWlYl3NdT1yfgIgRsZLqrw== X-CSE-MsgGUID: v+OUF6E6TcShaoFuZVtaug== X-IronPort-AV: E=McAfee;i="6600,9927,11089"; a="13949803" X-IronPort-AV: E=Sophos;i="6.08,205,1712646000"; d="scan'208";a="13949803" Received: from fmviesa005.fm.intel.com ([10.60.135.145]) by fmvoesa109.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 31 May 2024 15:26:37 -0700 X-CSE-ConnectionGUID: DIJa8Jw2T1m+PZZ+riOgFw== X-CSE-MsgGUID: 3fkaA2fOSMuBQUs809zKeg== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.08,205,1712646000"; d="scan'208";a="40736939" Received: from b4969161e530.jf.intel.com ([10.165.56.46]) by fmviesa005.fm.intel.com with ESMTP; 31 May 2024 15:26:36 -0700 From: Haitao Huang To: jarkko@kernel.org, dave.hansen@linux.intel.com, kai.huang@intel.com, tj@kernel.org, mkoutny@suse.com, linux-kernel@vger.kernel.org, linux-sgx@vger.kernel.org, x86@kernel.org, cgroups@vger.kernel.org, tglx@linutronix.de, mingo@redhat.com, bp@alien8.de, hpa@zytor.com, sohil.mehta@intel.com, tim.c.chen@linux.intel.com Cc: zhiquan1.li@intel.com, kristen@linux.intel.com, seanjc@google.com, zhanb@microsoft.com, anakrish@microsoft.com, mikko.ylinen@linux.intel.com, yangjie@microsoft.com, chrisyan@microsoft.com Subject: [PATCH v14 09/14] x86/sgx: Abstract check for global reclaimable pages Date: Fri, 31 May 2024 15:26:25 -0700 Message-Id: <20240531222630.4634-10-haitao.huang@linux.intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20240531222630.4634-1-haitao.huang@linux.intel.com> References: <20240531222630.4634-1-haitao.huang@linux.intel.com> Precedence: bulk X-Mailing-List: linux-sgx@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Kristen Carlson Accardi For the global reclaimer to determine if any page available for reclamation at the global level, it currently only checks for emptiness of the global LRU. That will be inadequate when pages are tracked in multiple LRUs, one per cgroup. For this purpose, create a new helper, sgx_can_reclaim_global(), to abstract this check. Currently it only checks the global LRU, later will check emptiness of LRUs of all cgroups when per-cgroup tracking is turned on. Replace all the checks for emptiness of the global LRU, list_empty(&sgx_global_lru.reclaimable), with calls to sgx_can_reclaim_global(). Co-developed-by: Sean Christopherson Signed-off-by: Sean Christopherson Signed-off-by: Kristen Carlson Accardi Co-developed-by: Haitao Huang Signed-off-by: Haitao Huang Reviewed-by: Jarkko Sakkinen Reviewed-by: Kai Huang Tested-by: Jarkko Sakkinen --- V13: - Rename sgx_can_reclaim() to sgx_can_reclaim_global() and sgx_should_reclaim() to sgx_should_reclaim_global(). (Kai) V10: - Add comments for the new function. (Jarkko) V7: - Split this out from the big patch, #10 in V6. (Dave, Kai) --- arch/x86/kernel/cpu/sgx/main.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/arch/x86/kernel/cpu/sgx/main.c b/arch/x86/kernel/cpu/sgx/main.c index 71e84937bc17..0a06b80e26b8 100644 --- a/arch/x86/kernel/cpu/sgx/main.c +++ b/arch/x86/kernel/cpu/sgx/main.c @@ -37,6 +37,14 @@ static inline struct sgx_epc_lru_list *sgx_epc_page_lru(struct sgx_epc_page *epc return &sgx_global_lru; } +/* + * Check if there is any reclaimable page at global level. + */ +static inline bool sgx_can_reclaim_global(void) +{ + return !list_empty(&sgx_global_lru.reclaimable); +} + static atomic_long_t sgx_nr_free_pages = ATOMIC_LONG_INIT(0); /* Nodes with one or more EPC sections. */ @@ -390,7 +398,7 @@ unsigned int sgx_reclaim_pages(struct sgx_epc_lru_list *lru) static bool sgx_should_reclaim_global(unsigned long watermark) { return atomic_long_read(&sgx_nr_free_pages) < watermark && - !list_empty(&sgx_global_lru.reclaimable); + sgx_can_reclaim_global(); } static void sgx_reclaim_pages_global(void) @@ -596,7 +604,7 @@ struct sgx_epc_page *sgx_alloc_epc_page(void *owner, enum sgx_reclaim reclaim) break; } - if (list_empty(&sgx_global_lru.reclaimable)) { + if (!sgx_can_reclaim_global()) { page = ERR_PTR(-ENOMEM); break; } From patchwork Fri May 31 22:26:26 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Haitao Huang X-Patchwork-Id: 13682249 Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.15]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 3667F132106; Fri, 31 May 2024 22:26:39 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.15 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1717194401; cv=none; b=kpB/hSIPrpgD3yB/wYboygTNhyC29TFdqB+UNpqIbxGZ5P0urA3OlxrCBiauI2DsG44O13z+8C4cKfuWSNSR+9Ef4ZQH5D8Mwsgpe13qlSfFpVohBMTl0TbiKEpCEBFRw5ylTYkQ2uuXAbAR3SAFUZRnxeelZ2wrVoV23yeDZ3o= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1717194401; c=relaxed/simple; bh=3xt1weILLGfju81ZRhocvOHuO3M+95xn3/6Ta724eHE=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=qVSndqDH9hm9DyRkqE65GCModPsdV5BJDNS3lEwyfPafijkmaCvpXgJoRu1D1ewmTbrHjReD1ZGnH7sjd+rBiSQCIRyM+SYSM+8mHj2C2u6y/9VnjXr0sAFFODJr9Bq5daLSRKCKva2pY6EMc+Xf1ViYzbDGHo78Dkq0idcd2YE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com; spf=none smtp.mailfrom=linux.intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=EhOlmpVY; arc=none smtp.client-ip=192.198.163.15 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; spf=none smtp.mailfrom=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="EhOlmpVY" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1717194399; x=1748730399; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=3xt1weILLGfju81ZRhocvOHuO3M+95xn3/6Ta724eHE=; b=EhOlmpVYShMEDl9PoNdHxwWN5Te2l8I9aZ9r/vdNdRxsF08toaeJ65rL lGxuUwINqxmtImedFbPcwHXCkehR1ao0r15hBCXpXfoZyG1SPStjSH/bu R9LPAFv/B8SUKPp3XwEfPniU+ktrgTKf3kQuVYJCjTIh41OS2pPdWjCdl 3RRftq+Fn7+9o1XAVEFs7OHHqaoulkSff/oO97mQSqAjsyURcVAW2V5zR Q50wN8dxuORjG84G0HcrNii9b0TQdMkpr63TTY3U8tYNdayqy/D4hOoSm GroTvGSL+5AGU7+JzWEwOnmFsJF4cOlj5LUTPMkWjdJWmRSiMo2vpmELs g==; X-CSE-ConnectionGUID: Rtzl08shTl+wybCTY2+XlA== X-CSE-MsgGUID: nMfn3UvOTAaVeLiGLiCGIA== X-IronPort-AV: E=McAfee;i="6600,9927,11089"; a="13949816" X-IronPort-AV: E=Sophos;i="6.08,205,1712646000"; d="scan'208";a="13949816" Received: from fmviesa005.fm.intel.com ([10.60.135.145]) by fmvoesa109.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 31 May 2024 15:26:37 -0700 X-CSE-ConnectionGUID: y4iZr6WVQoGgd2LD1TM00w== X-CSE-MsgGUID: ck+pfSqdREy0dLWF/hO4iw== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.08,205,1712646000"; d="scan'208";a="40736942" Received: from b4969161e530.jf.intel.com ([10.165.56.46]) by fmviesa005.fm.intel.com with ESMTP; 31 May 2024 15:26:36 -0700 From: Haitao Huang To: jarkko@kernel.org, dave.hansen@linux.intel.com, kai.huang@intel.com, tj@kernel.org, mkoutny@suse.com, linux-kernel@vger.kernel.org, linux-sgx@vger.kernel.org, x86@kernel.org, cgroups@vger.kernel.org, tglx@linutronix.de, mingo@redhat.com, bp@alien8.de, hpa@zytor.com, sohil.mehta@intel.com, tim.c.chen@linux.intel.com Cc: zhiquan1.li@intel.com, kristen@linux.intel.com, seanjc@google.com, zhanb@microsoft.com, anakrish@microsoft.com, mikko.ylinen@linux.intel.com, yangjie@microsoft.com, chrisyan@microsoft.com Subject: [PATCH v14 10/14] x86/sgx: Implement async reclamation for cgroup Date: Fri, 31 May 2024 15:26:26 -0700 Message-Id: <20240531222630.4634-11-haitao.huang@linux.intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20240531222630.4634-1-haitao.huang@linux.intel.com> References: <20240531222630.4634-1-haitao.huang@linux.intel.com> Precedence: bulk X-Mailing-List: linux-sgx@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Kristen Carlson Accardi In cases EPC pages need be allocated during a page fault and the cgroup usage is near its limit, an asynchronous reclamation needs be triggered to avoid blocking the page fault handling. Create a workqueue, corresponding work item and function definitions for EPC cgroup to support the asynchronous reclamation. In sgx_cgroup_try_charge(), if caller does not allow synchronous reclamation, queue an asynchronous work into the workqueue. Reclaiming only when the usage is at or very close to the limit would cause thrashing. To avoid that, before returning from sgx_cgroup_try_charge(), check the need for reclamation (usage too close to the limit), queue an async work if needed, similar to how the global reclaimer wakes up its reclaiming thread after each allocation in sgx_alloc_epc_pages(). Co-developed-by: Sean Christopherson Signed-off-by: Sean Christopherson Signed-off-by: Kristen Carlson Accardi Co-developed-by: Haitao Huang Signed-off-by: Haitao Huang Reviewed-by: Jarkko Sakkinen Tested-by: Jarkko Sakkinen --- V13: - Revert to BUG_ON() in case of workq allocation failure in init and only alloc if misc is enabled. V11: - Print error instead of WARN (Kai) - Add check for need to queue an async reclamation before returning from try_charge(), do so if needed. This is to be consistent with global reclaimer to minimize thrashing during allocation time. V10: - Split asynchronous flow in separate patch. (Kai) - Consider cgroup disabled when the workqueue allocation fail during init. (Kai) - Abstract out sgx_cgroup_should_reclaim(). V9: - Add comments for static variables. (Jarkko) V8: - Remove alignment for substructure variables. (Jarkko) V7: - Split this out from the big patch, #10 in V6. (Dave, Kai) --- arch/x86/kernel/cpu/sgx/epc_cgroup.c | 136 ++++++++++++++++++++++++++- arch/x86/kernel/cpu/sgx/epc_cgroup.h | 1 + 2 files changed, 136 insertions(+), 1 deletion(-) diff --git a/arch/x86/kernel/cpu/sgx/epc_cgroup.c b/arch/x86/kernel/cpu/sgx/epc_cgroup.c index 4406077acd1c..9e366068e0cd 100644 --- a/arch/x86/kernel/cpu/sgx/epc_cgroup.c +++ b/arch/x86/kernel/cpu/sgx/epc_cgroup.c @@ -4,9 +4,63 @@ #include #include "epc_cgroup.h" +/* + * The minimal free pages maintained by per-cgroup reclaimer + * Set this to the low threshold used by the global reclaimer, ksgxd. + */ +#define SGX_CG_MIN_FREE_PAGE (SGX_NR_LOW_PAGES) + +/* + * If the cgroup limit is close to SGX_CG_MIN_FREE_PAGE, maintaining the minimal + * free pages would barely leave any page for use, causing excessive reclamation + * and thrashing. + * + * Define the following limit, below which cgroup does not maintain the minimal + * free page threshold. Set this to quadruple of the minimal so at least 75% + * pages used without being reclaimed. + */ +#define SGX_CG_LOW_LIMIT (SGX_CG_MIN_FREE_PAGE * 4) + /* The root SGX EPC cgroup */ static struct sgx_cgroup sgx_cg_root; +/* + * The work queue that reclaims EPC pages in the background for cgroups. + * + * A cgroup schedules a work item into this queue to reclaim pages within the + * same cgroup when its usage limit is reached and synchronous reclamation is not + * an option, i.e., in a page fault handler. + */ +static struct workqueue_struct *sgx_cg_wq; + +static inline u64 sgx_cgroup_page_counter_read(struct sgx_cgroup *sgx_cg) +{ + return atomic64_read(&sgx_cg->cg->res[MISC_CG_RES_SGX_EPC].usage) / PAGE_SIZE; +} + +static inline u64 sgx_cgroup_max_pages(struct sgx_cgroup *sgx_cg) +{ + return READ_ONCE(sgx_cg->cg->res[MISC_CG_RES_SGX_EPC].max) / PAGE_SIZE; +} + +/* + * Get the lower bound of limits of a cgroup and its ancestors. Used in + * sgx_cgroup_should_reclaim() to determine if EPC usage of a cgroup is + * close to its limit or its ancestors' hence reclamation is needed. + */ +static inline u64 sgx_cgroup_max_pages_to_root(struct sgx_cgroup *sgx_cg) +{ + struct misc_cg *i = sgx_cg->cg; + u64 m = U64_MAX; + + while (i) { + m = min(m, READ_ONCE(i->res[MISC_CG_RES_SGX_EPC].max)); + i = misc_cg_parent(i); + } + + return m / PAGE_SIZE; +} + /** * sgx_cgroup_lru_empty() - check if a cgroup tree has no pages on its LRUs * @root: Root of the tree to check @@ -113,6 +167,65 @@ static struct misc_cg *sgx_cgroup_reclaim_pages(struct misc_cg *root, struct mis return css_misc(next); } +/** + * sgx_cgroup_should_reclaim() - check if EPC reclamation is needed for a cgroup + * @sgx_cg: The cgroup to be checked. + * + * This function can be used to guard a call to sgx_cgroup_reclaim_pages() where + * the minimal number of free page needs be maintained for the cgroup to make + * good forward progress. + * + * Return: %true if number of free pages available for the cgroup below a + * threshold (%SGX_CG_MIN_FREE_PAGE) and there are reclaimable pages within the + * cgroup. + */ +static bool sgx_cgroup_should_reclaim(struct sgx_cgroup *sgx_cg) +{ + u64 cur, max; + + if (sgx_cgroup_lru_empty(sgx_cg->cg)) + return false; + + max = sgx_cgroup_max_pages_to_root(sgx_cg); + + /* + * Unless the limit is very low, maintain a minimal number of free pages + * so there is always a few pages available to serve new allocation + * requests quickly. + */ + if (max > SGX_CG_LOW_LIMIT) + max -= SGX_CG_MIN_FREE_PAGE; + + cur = sgx_cgroup_page_counter_read(sgx_cg); + + return (cur >= max); +} + +/* + * Asynchronous work flow to reclaim pages from the cgroup when the cgroup is + * at/near its maximum capacity. + */ +static void sgx_cgroup_reclaim_work_func(struct work_struct *work) +{ + struct sgx_cgroup *sgx_cg = container_of(work, struct sgx_cgroup, reclaim_work); + struct misc_cg *cg_next = NULL; + + /* + * This work func is scheduled by sgx_cgroup_try_charge() when it cannot + * directly reclaim, i.e., EPC allocation in a fault handler. Waiting to + * reclaim until the cgroup is actually at its limit is less performant, + * as it means the task scheduling this asynchronous work is effectively + * blocked until a worker makes its way through the global work queue. + */ + while (sgx_cgroup_should_reclaim(sgx_cg)) { + cg_next = sgx_cgroup_reclaim_pages(sgx_cg->cg, cg_next); + cond_resched(); + } + + if (cg_next != sgx_cg->cg) + put_misc_cg(cg_next); +} + static int __sgx_cgroup_try_charge(struct sgx_cgroup *epc_cg) { if (!misc_cg_try_charge(MISC_CG_RES_SGX_EPC, epc_cg->cg, PAGE_SIZE)) @@ -148,7 +261,8 @@ int sgx_cgroup_try_charge(struct sgx_cgroup *sgx_cg, enum sgx_reclaim reclaim) goto out; if (reclaim == SGX_NO_RECLAIM) { - ret = -ENOMEM; + queue_work(sgx_cg_wq, &sgx_cg->reclaim_work); + ret = -EBUSY; goto out; } @@ -156,6 +270,9 @@ int sgx_cgroup_try_charge(struct sgx_cgroup *sgx_cg, enum sgx_reclaim reclaim) cond_resched(); } + if (sgx_cgroup_should_reclaim(sgx_cg)) + queue_work(sgx_cg_wq, &sgx_cg->reclaim_work); + out: if (cg_next != sgx_cg->cg) put_misc_cg(cg_next); @@ -179,12 +296,14 @@ static void sgx_cgroup_free(struct misc_cg *cg) if (!sgx_cg) return; + cancel_work_sync(&sgx_cg->reclaim_work); kfree(sgx_cg); } static void sgx_cgroup_misc_init(struct misc_cg *cg, struct sgx_cgroup *sgx_cg) { sgx_lru_init(&sgx_cg->lru); + INIT_WORK(&sgx_cg->reclaim_work, sgx_cgroup_reclaim_work_func); cg->res[MISC_CG_RES_SGX_EPC].priv = sgx_cg; sgx_cg->cg = cg; } @@ -209,6 +328,21 @@ const struct misc_res_ops sgx_cgroup_ops = { void sgx_cgroup_init(void) { + /* + * misc root always exists even if misc is disabled from command line. + * Initialize properly. + */ misc_cg_set_ops(MISC_CG_RES_SGX_EPC, &sgx_cgroup_ops); sgx_cgroup_misc_init(misc_cg_root(), &sgx_cg_root); + + /* + * Only alloc additional resource for workqueue when misc is enabled. + * User can disable sgx or disable misc to avoid the failure + */ + if (cgroup_subsys_enabled(misc_cgrp_subsys)) { + sgx_cg_wq = alloc_workqueue("sgx_cg_wq", WQ_UNBOUND | WQ_FREEZABLE, + WQ_UNBOUND_MAX_ACTIVE); + BUG_ON(!sgx_cg_wq); + } + } diff --git a/arch/x86/kernel/cpu/sgx/epc_cgroup.h b/arch/x86/kernel/cpu/sgx/epc_cgroup.h index 538524f5669d..2044e0d64076 100644 --- a/arch/x86/kernel/cpu/sgx/epc_cgroup.h +++ b/arch/x86/kernel/cpu/sgx/epc_cgroup.h @@ -34,6 +34,7 @@ static inline void sgx_cgroup_init(void) { } struct sgx_cgroup { struct misc_cg *cg; struct sgx_epc_lru_list lru; + struct work_struct reclaim_work; }; static inline struct sgx_cgroup *sgx_cgroup_from_misc_cg(struct misc_cg *cg) From patchwork Fri May 31 22:26:27 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Haitao Huang X-Patchwork-Id: 13682250 Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.15]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 9526F135A46; Fri, 31 May 2024 22:26:40 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.15 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1717194402; cv=none; b=EHKN8cskKtXrkuLgaZyheJx0nN+2eF/riNhyHzNxpeAkOCxvxCLhcz/+LxxIvJjC+Pwy9VbmWo5LiwPHNwUyUv2C80tsB0FlqOl/L+TQvn0Fsfc6lwpdDZAXCnmPWYZB9BVtBR24E7nwZEULroaI4u93OIm6i88EWlH706noT9c= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1717194402; c=relaxed/simple; bh=tF955xMuW1EHkFoi7eshEs2wQd/fgKYYCmBcjOvyEP8=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=o3RM+eOuhDOTg3KRj6/UxszfaDLNTrZtPvNPCv0b8QORwNtZXDS8rFUxtwtBkYZwDaWXfwwl20Ptb0hKDvoUc598pnFYKWflt4aNrH4FkzDzrURzCaE0Nj8IJiNqx5vnQZUR/maAL/PogrkNXaKEkxietr94lephgxl1MtuAD0o= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com; spf=none smtp.mailfrom=linux.intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=mY5OyYzY; arc=none smtp.client-ip=192.198.163.15 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; spf=none smtp.mailfrom=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="mY5OyYzY" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1717194401; x=1748730401; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=tF955xMuW1EHkFoi7eshEs2wQd/fgKYYCmBcjOvyEP8=; b=mY5OyYzYoPl1khLHMTmC6smVy3OfPqKw8zn5ItU2bPyyS/pXKZNmPTy6 V9ceZrJ4+lQRv/Lk3MU9vH/Sjzvwgzu5Qk0PbuNx+KXqtmHAjlhuu5gJp FDwRFrOPbzu1YWXNIw6fczH2s+625KKmgqe6V5FD5olDoDQG+XIL4gEmE /dp5MZUp7mT6QxrhpwDM8FX7jC6hVKGLXwSVS25QVH1Q48jyHp48uNWGH O0AEtXco8or6ok9C3YUNvrK4+xXrUHYTjbdkICOkHkdmsIkGNXF9vxmtM odo4vYkSaX39PB0fOMrq2ovf3g9m068SPNKT9rEueEHkTx/nB3gY1RJ9i g==; X-CSE-ConnectionGUID: myeoXfnBReGuwtiaJzbLkQ== X-CSE-MsgGUID: 2R0XUDgrRWiYEEgd7Rty5A== X-IronPort-AV: E=McAfee;i="6600,9927,11089"; a="13949826" X-IronPort-AV: E=Sophos;i="6.08,205,1712646000"; d="scan'208";a="13949826" Received: from fmviesa005.fm.intel.com ([10.60.135.145]) by fmvoesa109.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 31 May 2024 15:26:38 -0700 X-CSE-ConnectionGUID: F9RyWtJ4S/aTM5nmIcb5DQ== X-CSE-MsgGUID: WHiXQh4LTN+20eqmKYk13A== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.08,205,1712646000"; d="scan'208";a="40736945" Received: from b4969161e530.jf.intel.com ([10.165.56.46]) by fmviesa005.fm.intel.com with ESMTP; 31 May 2024 15:26:37 -0700 From: Haitao Huang To: jarkko@kernel.org, dave.hansen@linux.intel.com, kai.huang@intel.com, tj@kernel.org, mkoutny@suse.com, linux-kernel@vger.kernel.org, linux-sgx@vger.kernel.org, x86@kernel.org, cgroups@vger.kernel.org, tglx@linutronix.de, mingo@redhat.com, bp@alien8.de, hpa@zytor.com, sohil.mehta@intel.com, tim.c.chen@linux.intel.com Cc: zhiquan1.li@intel.com, kristen@linux.intel.com, seanjc@google.com, zhanb@microsoft.com, anakrish@microsoft.com, mikko.ylinen@linux.intel.com, yangjie@microsoft.com, chrisyan@microsoft.com Subject: [PATCH v14 11/14] x86/sgx: Charge mem_cgroup for per-cgroup reclamation Date: Fri, 31 May 2024 15:26:27 -0700 Message-Id: <20240531222630.4634-12-haitao.huang@linux.intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20240531222630.4634-1-haitao.huang@linux.intel.com> References: <20240531222630.4634-1-haitao.huang@linux.intel.com> Precedence: bulk X-Mailing-List: linux-sgx@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Enclave Page Cache(EPC) memory can be swapped out to regular system memory, and the consumed memory should be charged to a proper mem_cgroup. Currently the selection of mem_cgroup to charge is done in sgx_encl_get_mem_cgroup(). But it considers all contexts other than the ksgxd thread are user processes. With the new EPC cgroup implementation, the swapping can also happen in EPC cgroup work-queue threads. In those cases, it improperly selects the root mem_cgroup to charge for the RAM usage. Remove current_is_ksgxd() and change sgx_encl_get_mem_cgroup() to take an additional argument to explicitly specify the mm struct to charge for allocations. Callers from background kthreads not associated with a charging mm struct would set it to NULL, while callers in user process contexts set it to current->mm. Internally, it handles the case when the charging mm given is NULL, by searching for an mm struct from enclave's mm_list. Signed-off-by: Haitao Huang Reported-by: Mikko Ylinen Reviewed-by: Kai Huang Reviewed-by: Jarkko Sakkinen Tested-by: Mikko Ylinen Tested-by: Jarkko Sakkinen --- V10: - Pass mm struct instead of a boolean 'indirect'. (Dave, Jarkko) V9: - Reduce number of if statements. (Tim) V8: - Limit text paragraphs to 80 characters wide. (Jarkko) --- arch/x86/kernel/cpu/sgx/encl.c | 29 ++++++++++++++-------------- arch/x86/kernel/cpu/sgx/encl.h | 3 +-- arch/x86/kernel/cpu/sgx/epc_cgroup.c | 11 +++++++---- arch/x86/kernel/cpu/sgx/main.c | 29 +++++++++++++--------------- arch/x86/kernel/cpu/sgx/sgx.h | 2 +- 5 files changed, 37 insertions(+), 37 deletions(-) diff --git a/arch/x86/kernel/cpu/sgx/encl.c b/arch/x86/kernel/cpu/sgx/encl.c index f474179b6f77..7b77dad41daf 100644 --- a/arch/x86/kernel/cpu/sgx/encl.c +++ b/arch/x86/kernel/cpu/sgx/encl.c @@ -993,23 +993,23 @@ static int __sgx_encl_get_backing(struct sgx_encl *encl, unsigned long page_inde } /* - * When called from ksgxd, returns the mem_cgroup of a struct mm stored - * in the enclave's mm_list. When not called from ksgxd, just returns - * the mem_cgroup of the current task. + * Find the mem_cgroup to charge for memory allocated on behalf of an enclave. + * + * Used in sgx_encl_alloc_backing() for backing store allocation. + * + * Return the mem_cgroup of the given charge_mm. Otherwise return the mem_cgroup + * of a struct mm stored in the enclave's mm_list. */ -static struct mem_cgroup *sgx_encl_get_mem_cgroup(struct sgx_encl *encl) +static struct mem_cgroup *sgx_encl_get_mem_cgroup(struct sgx_encl *encl, + struct mm_struct *charge_mm) { struct mem_cgroup *memcg = NULL; struct sgx_encl_mm *encl_mm; int idx; - /* - * If called from normal task context, return the mem_cgroup - * of the current task's mm. The remainder of the handling is for - * ksgxd. - */ - if (!current_is_ksgxd()) - return get_mem_cgroup_from_mm(current->mm); + /* Use the charge_mm if given. */ + if (charge_mm) + return get_mem_cgroup_from_mm(charge_mm); /* * Search the enclave's mm_list to find an mm associated with @@ -1047,8 +1047,9 @@ static struct mem_cgroup *sgx_encl_get_mem_cgroup(struct sgx_encl *encl) * @encl: an enclave pointer * @page_index: enclave page index * @backing: data for accessing backing storage for the page + * @charge_mm: the mm to charge for the allocation * - * When called from ksgxd, sets the active memcg from one of the + * When charge_mm is NULL, sets the active memcg from one of the * mms in the enclave's mm_list prior to any backing page allocation, * in order to ensure that shmem page allocations are charged to the * enclave. Create a backing page for loading data back into an EPC page with @@ -1060,9 +1061,9 @@ static struct mem_cgroup *sgx_encl_get_mem_cgroup(struct sgx_encl *encl) * -errno otherwise. */ int sgx_encl_alloc_backing(struct sgx_encl *encl, unsigned long page_index, - struct sgx_backing *backing) + struct sgx_backing *backing, struct mm_struct *charge_mm) { - struct mem_cgroup *encl_memcg = sgx_encl_get_mem_cgroup(encl); + struct mem_cgroup *encl_memcg = sgx_encl_get_mem_cgroup(encl, charge_mm); struct mem_cgroup *memcg = set_active_memcg(encl_memcg); int ret; diff --git a/arch/x86/kernel/cpu/sgx/encl.h b/arch/x86/kernel/cpu/sgx/encl.h index fe15ade02ca1..5ce9d108290f 100644 --- a/arch/x86/kernel/cpu/sgx/encl.h +++ b/arch/x86/kernel/cpu/sgx/encl.h @@ -103,12 +103,11 @@ static inline int sgx_encl_find(struct mm_struct *mm, unsigned long addr, int sgx_encl_may_map(struct sgx_encl *encl, unsigned long start, unsigned long end, unsigned long vm_flags); -bool current_is_ksgxd(void); void sgx_encl_release(struct kref *ref); int sgx_encl_mm_add(struct sgx_encl *encl, struct mm_struct *mm); const cpumask_t *sgx_encl_cpumask(struct sgx_encl *encl); int sgx_encl_alloc_backing(struct sgx_encl *encl, unsigned long page_index, - struct sgx_backing *backing); + struct sgx_backing *backing, struct mm_struct *charge_mm); void sgx_encl_put_backing(struct sgx_backing *backing); int sgx_encl_test_and_clear_young(struct mm_struct *mm, struct sgx_encl_page *page); diff --git a/arch/x86/kernel/cpu/sgx/epc_cgroup.c b/arch/x86/kernel/cpu/sgx/epc_cgroup.c index 9e366068e0cd..7e0e9a4fedf0 100644 --- a/arch/x86/kernel/cpu/sgx/epc_cgroup.c +++ b/arch/x86/kernel/cpu/sgx/epc_cgroup.c @@ -107,6 +107,7 @@ static bool sgx_cgroup_lru_empty(struct misc_cg *root) * sgx_cgroup_reclaim_pages() - reclaim EPC from a cgroup tree * @root: The root of cgroup tree to reclaim from. * @start: The descendant cgroup from which to start the tree walking. + * @charge_mm: The mm to charge for backing store allocation. * * This function performs a pre-order walk in the cgroup tree under the given * root, starting from the node %start, or from the root if %start is NULL. The @@ -126,7 +127,8 @@ static bool sgx_cgroup_lru_empty(struct misc_cg *root) * release the reference if the returned is not used as %start for a subsequent * call. */ -static struct misc_cg *sgx_cgroup_reclaim_pages(struct misc_cg *root, struct misc_cg *start) +static struct misc_cg *sgx_cgroup_reclaim_pages(struct misc_cg *root, struct misc_cg *start, + struct mm_struct *charge_mm) { struct cgroup_subsys_state *css_root, *pos; struct cgroup_subsys_state *next = NULL; @@ -142,7 +144,7 @@ static struct misc_cg *sgx_cgroup_reclaim_pages(struct misc_cg *root, struct mis while (cnt < SGX_NR_TO_SCAN) { sgx_cg = sgx_cgroup_from_misc_cg(css_misc(pos)); - cnt += sgx_reclaim_pages(&sgx_cg->lru); + cnt += sgx_reclaim_pages(&sgx_cg->lru, charge_mm); rcu_read_lock(); @@ -218,7 +220,8 @@ static void sgx_cgroup_reclaim_work_func(struct work_struct *work) * blocked until a worker makes its way through the global work queue. */ while (sgx_cgroup_should_reclaim(sgx_cg)) { - cg_next = sgx_cgroup_reclaim_pages(sgx_cg->cg, cg_next); + /* Indirect reclaim, no mm to charge, so NULL: */ + cg_next = sgx_cgroup_reclaim_pages(sgx_cg->cg, cg_next, NULL); cond_resched(); } @@ -266,7 +269,7 @@ int sgx_cgroup_try_charge(struct sgx_cgroup *sgx_cg, enum sgx_reclaim reclaim) goto out; } - cg_next = sgx_cgroup_reclaim_pages(sgx_cg->cg, cg_next); + cg_next = sgx_cgroup_reclaim_pages(sgx_cg->cg, cg_next, current->mm); cond_resched(); } diff --git a/arch/x86/kernel/cpu/sgx/main.c b/arch/x86/kernel/cpu/sgx/main.c index 0a06b80e26b8..c8ac4eb996aa 100644 --- a/arch/x86/kernel/cpu/sgx/main.c +++ b/arch/x86/kernel/cpu/sgx/main.c @@ -261,8 +261,8 @@ static void sgx_encl_ewb(struct sgx_epc_page *epc_page, } } -static void sgx_reclaimer_write(struct sgx_epc_page *epc_page, - struct sgx_backing *backing) +static void sgx_reclaimer_write(struct sgx_epc_page *epc_page, struct sgx_backing *backing, + struct mm_struct *charge_mm) { struct sgx_encl_page *encl_page = epc_page->owner; struct sgx_encl *encl = encl_page->encl; @@ -278,7 +278,7 @@ static void sgx_reclaimer_write(struct sgx_epc_page *epc_page, if (!encl->secs_child_cnt && test_bit(SGX_ENCL_INITIALIZED, &encl->flags)) { ret = sgx_encl_alloc_backing(encl, PFN_DOWN(encl->size), - &secs_backing); + &secs_backing, charge_mm); if (ret) goto out; @@ -297,6 +297,7 @@ static void sgx_reclaimer_write(struct sgx_epc_page *epc_page, /** * sgx_reclaim_pages() - Attempt to reclaim a fixed number of pages from an LRU * @lru: The LRU from which pages are reclaimed. + * @charge_mm: The mm to charge for backing store allocation. * * Take a fixed number of pages from the head of a given LRU and reclaim them to * the enclave's private shmem files. Skip the pages, which have been accessed @@ -312,7 +313,7 @@ static void sgx_reclaimer_write(struct sgx_epc_page *epc_page, * * Return: Number of pages attempted for reclamation. */ -unsigned int sgx_reclaim_pages(struct sgx_epc_lru_list *lru) +unsigned int sgx_reclaim_pages(struct sgx_epc_lru_list *lru, struct mm_struct *charge_mm) { struct sgx_epc_page *chunk[SGX_NR_TO_SCAN]; struct sgx_backing backing[SGX_NR_TO_SCAN]; @@ -352,7 +353,7 @@ unsigned int sgx_reclaim_pages(struct sgx_epc_lru_list *lru) page_index = PFN_DOWN(encl_page->desc - encl_page->encl->base); mutex_lock(&encl_page->encl->lock); - ret = sgx_encl_alloc_backing(encl_page->encl, page_index, &backing[i]); + ret = sgx_encl_alloc_backing(encl_page->encl, page_index, &backing[i], charge_mm); if (ret) { mutex_unlock(&encl_page->encl->lock); goto skip; @@ -384,7 +385,7 @@ unsigned int sgx_reclaim_pages(struct sgx_epc_lru_list *lru) continue; encl_page = epc_page->owner; - sgx_reclaimer_write(epc_page, &backing[i]); + sgx_reclaimer_write(epc_page, &backing[i], charge_mm); kref_put(&encl_page->encl->refcount, sgx_encl_release); epc_page->flags &= ~SGX_EPC_PAGE_RECLAIMER_TRACKED; @@ -401,9 +402,9 @@ static bool sgx_should_reclaim_global(unsigned long watermark) sgx_can_reclaim_global(); } -static void sgx_reclaim_pages_global(void) +static void sgx_reclaim_pages_global(struct mm_struct *charge_mm) { - sgx_reclaim_pages(&sgx_global_lru); + sgx_reclaim_pages(&sgx_global_lru, charge_mm); } /* @@ -414,7 +415,7 @@ static void sgx_reclaim_pages_global(void) void sgx_reclaim_direct(void) { if (sgx_should_reclaim_global(SGX_NR_LOW_PAGES)) - sgx_reclaim_pages_global(); + sgx_reclaim_pages_global(current->mm); } static int ksgxd(void *p) @@ -437,7 +438,8 @@ static int ksgxd(void *p) sgx_should_reclaim_global(SGX_NR_HIGH_PAGES)); if (sgx_should_reclaim_global(SGX_NR_HIGH_PAGES)) - sgx_reclaim_pages_global(); + /* Indirect reclaim, no mm to charge, so NULL: */ + sgx_reclaim_pages_global(NULL); cond_resched(); } @@ -460,11 +462,6 @@ static bool __init sgx_page_reclaimer_init(void) return true; } -bool current_is_ksgxd(void) -{ - return current == ksgxd_tsk; -} - static struct sgx_epc_page *__sgx_alloc_epc_page_from_node(int nid) { struct sgx_numa_node *node = &sgx_numa_nodes[nid]; @@ -619,7 +616,7 @@ struct sgx_epc_page *sgx_alloc_epc_page(void *owner, enum sgx_reclaim reclaim) break; } - sgx_reclaim_pages_global(); + sgx_reclaim_pages_global(current->mm); cond_resched(); } diff --git a/arch/x86/kernel/cpu/sgx/sgx.h b/arch/x86/kernel/cpu/sgx/sgx.h index 89adac646381..72b022755ff1 100644 --- a/arch/x86/kernel/cpu/sgx/sgx.h +++ b/arch/x86/kernel/cpu/sgx/sgx.h @@ -135,7 +135,7 @@ void sgx_reclaim_direct(void); void sgx_mark_page_reclaimable(struct sgx_epc_page *page); int sgx_unmark_page_reclaimable(struct sgx_epc_page *page); struct sgx_epc_page *sgx_alloc_epc_page(void *owner, enum sgx_reclaim reclaim); -unsigned int sgx_reclaim_pages(struct sgx_epc_lru_list *lru); +unsigned int sgx_reclaim_pages(struct sgx_epc_lru_list *lru, struct mm_struct *charge_mm); void sgx_ipi_cb(void *info); From patchwork Fri May 31 22:26:28 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Haitao Huang X-Patchwork-Id: 13682251 Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.15]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id F346F135A7F; Fri, 31 May 2024 22:26:40 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.15 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1717194403; cv=none; b=VIKfSL45ElLa0COW35vX5vVJv1r/ejUHJXYEQrBcnjCcRH82uY2nzUIRXqNe8DnlhA3XIg/0SwjZ9N/AlE5ShxpqebhFzjXA+h56DybFMq/hHxPPK/Q0qE7kClC3NRvdIVHqaNFYLXprH6QJ7gnGBcNwXEqJJNC1n8p8pXlN3Z8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1717194403; c=relaxed/simple; bh=5BTLXi1/KI8XQZw0+Z796GXFKI2caQPmAuHrPbBuWdY=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=cd4I8Wn69tvh/p/qvTMLGrOvcrFmrb4UsGQdMWp/55KOrndqZJUfsbux0DvgsCljLAOfy2ugYotWpIKiQhSR2GZuSieKoep+0fy2sl2xoH4cN6rAoi0t7idHDCNWt84QgENxFmYCRx5EpRvO0wVCdcsp9X3vjyAyNOBvmYloKB0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com; spf=none smtp.mailfrom=linux.intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=fxBUuz3Q; arc=none smtp.client-ip=192.198.163.15 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; spf=none smtp.mailfrom=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="fxBUuz3Q" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1717194401; x=1748730401; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=5BTLXi1/KI8XQZw0+Z796GXFKI2caQPmAuHrPbBuWdY=; b=fxBUuz3Q5Z1RgzYMi//uybxUCTDAkYa/5MKI50ZS5FSIPuo/qRnirsyD RBAtZNYjQn6VQY4l+ZgHWV9C0khJNvN2YLkKQM8CRpKqxCNox6MegpPsw dGoEikDflPqxj1M80h/dp1o1OopImZxgLJdKcZo/URxTLjjpuC0V0pVr6 s96VXB7btGl+Va+REDsj8gLBKmcJGmOhToALxngK8FT/jEfGUnmYN/nLY JnbxvbP9MaznA4rwoBwN5mokCV9ZhZNDoN64HbhUNY2LVoI2kbPzV5yA9 Q65uDv2EwtRE+S7ynp2WEkG6ZaU936iNQZiyaXLx3Xh8sLumhF8gRQVkM A==; X-CSE-ConnectionGUID: qziP3hhHRf2+xi3fT7oJCg== X-CSE-MsgGUID: /eAeDGFLSd215VVQ9nvV1g== X-IronPort-AV: E=McAfee;i="6600,9927,11089"; a="13949832" X-IronPort-AV: E=Sophos;i="6.08,205,1712646000"; d="scan'208";a="13949832" Received: from fmviesa005.fm.intel.com ([10.60.135.145]) by fmvoesa109.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 31 May 2024 15:26:39 -0700 X-CSE-ConnectionGUID: KaOHzvXGSMWd6Fhs71Va2Q== X-CSE-MsgGUID: cpVR2DYwQjW0C07FRpB5TA== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.08,205,1712646000"; d="scan'208";a="40736948" Received: from b4969161e530.jf.intel.com ([10.165.56.46]) by fmviesa005.fm.intel.com with ESMTP; 31 May 2024 15:26:38 -0700 From: Haitao Huang To: jarkko@kernel.org, dave.hansen@linux.intel.com, kai.huang@intel.com, tj@kernel.org, mkoutny@suse.com, linux-kernel@vger.kernel.org, linux-sgx@vger.kernel.org, x86@kernel.org, cgroups@vger.kernel.org, tglx@linutronix.de, mingo@redhat.com, bp@alien8.de, hpa@zytor.com, sohil.mehta@intel.com, tim.c.chen@linux.intel.com Cc: zhiquan1.li@intel.com, kristen@linux.intel.com, seanjc@google.com, zhanb@microsoft.com, anakrish@microsoft.com, mikko.ylinen@linux.intel.com, yangjie@microsoft.com, chrisyan@microsoft.com Subject: [PATCH v14 12/14] x86/sgx: Turn on per-cgroup EPC reclamation Date: Fri, 31 May 2024 15:26:28 -0700 Message-Id: <20240531222630.4634-13-haitao.huang@linux.intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20240531222630.4634-1-haitao.huang@linux.intel.com> References: <20240531222630.4634-1-haitao.huang@linux.intel.com> Precedence: bulk X-Mailing-List: linux-sgx@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Kristen Carlson Accardi Previous patches have implemented all infrastructure needed for per-cgroup EPC page tracking and reclaiming. But all reclaimable EPC pages are still tracked in the global LRU as sgx_epc_page_lru() always returns reference to the global LRU. Change sgx_epc_page_lru() to return the LRU of the cgroup in which the given EPC page is allocated. This makes all EPC pages tracked in per-cgroup LRUs and the global reclaimer (ksgxd) will not be able to reclaim any pages from the global LRU. However, in cases of over-committing, i.e., the sum of cgroup limits greater than the total capacity, cgroups may never reclaim but the total usage can still be near the capacity. Therefore a global reclamation is still needed in those cases and it should be performed from the root cgroup. Modify sgx_reclaim_pages_global(), to reclaim from the root EPC cgroup when cgroup is enabled. Similar to sgx_cgroup_reclaim_pages(), return the next cgroup so callers can use it as the new starting node for next round of reclamation if needed. Also update sgx_can_reclaim_global(), to check emptiness of LRUs of all cgroups when EPC cgroup is enabled, otherwise only check the global LRU. Finally, change sgx_reclaim_direct(), to check and ensure there are free pages at cgroup level so forward progress can be made by the caller. With these changes, the global reclamation and per-cgroup reclamation both work properly with all pages tracked in per-cgroup LRUs. Co-developed-by: Sean Christopherson Signed-off-by: Sean Christopherson Signed-off-by: Kristen Carlson Accardi Co-developed-by: Haitao Huang Signed-off-by: Haitao Huang Reviewed-by: Jarkko Sakkinen Tested-by: Mikko Ylinen Tested-by: Jarkko Sakkinen --- V14: - Update global reclamation to use the new sgx_cgroup_reclaim_pages() to iterate cgroups at lower level if the top cgroups are too busy. V13: - Use IS_ENABLED(CONFIG_CGROUP_MISC) in sgx_can_reclaim_global(). (Kai) V12: - Remove CONFIG_CGROUP_SGX_EPC, conditional compile SGX Cgroup for CONFIGCONFIG_CGROUPMISC. (Jarkko) V11: - Reword the comments for global reclamation for allocation failure after passing cgroup charging. (Kai) - Add stub functions to remove ifdefs in c file (Kai) - Add more detailed comments to clarify each page belongs to one cgroup, or the root. (Kai) V10: - Add comment to clarify each page belongs to one cgroup, or the root by default. (Kai) - Merge the changes that expose sgx_cgroup_* functions to this patch. - Add changes for sgx_reclaim_direct() that was missed previously. V7: - Split this out from the big patch, #10 in V6. (Dave, Kai) --- arch/x86/kernel/cpu/sgx/epc_cgroup.c | 8 +-- arch/x86/kernel/cpu/sgx/epc_cgroup.h | 32 +++++++++++ arch/x86/kernel/cpu/sgx/main.c | 80 +++++++++++++++++++++++++--- 3 files changed, 109 insertions(+), 11 deletions(-) diff --git a/arch/x86/kernel/cpu/sgx/epc_cgroup.c b/arch/x86/kernel/cpu/sgx/epc_cgroup.c index 7e0e9a4fedf0..2702bbd49c60 100644 --- a/arch/x86/kernel/cpu/sgx/epc_cgroup.c +++ b/arch/x86/kernel/cpu/sgx/epc_cgroup.c @@ -67,7 +67,7 @@ static inline u64 sgx_cgroup_max_pages_to_root(struct sgx_cgroup *sgx_cg) * * Return: %true if all cgroups under the specified root have empty LRU lists. */ -static bool sgx_cgroup_lru_empty(struct misc_cg *root) +bool sgx_cgroup_lru_empty(struct misc_cg *root) { struct cgroup_subsys_state *css_root; struct cgroup_subsys_state *pos; @@ -127,8 +127,8 @@ static bool sgx_cgroup_lru_empty(struct misc_cg *root) * release the reference if the returned is not used as %start for a subsequent * call. */ -static struct misc_cg *sgx_cgroup_reclaim_pages(struct misc_cg *root, struct misc_cg *start, - struct mm_struct *charge_mm) +struct misc_cg *sgx_cgroup_reclaim_pages(struct misc_cg *root, struct misc_cg *start, + struct mm_struct *charge_mm) { struct cgroup_subsys_state *css_root, *pos; struct cgroup_subsys_state *next = NULL; @@ -181,7 +181,7 @@ static struct misc_cg *sgx_cgroup_reclaim_pages(struct misc_cg *root, struct mis * threshold (%SGX_CG_MIN_FREE_PAGE) and there are reclaimable pages within the * cgroup. */ -static bool sgx_cgroup_should_reclaim(struct sgx_cgroup *sgx_cg) +bool sgx_cgroup_should_reclaim(struct sgx_cgroup *sgx_cg) { u64 cur, max; diff --git a/arch/x86/kernel/cpu/sgx/epc_cgroup.h b/arch/x86/kernel/cpu/sgx/epc_cgroup.h index 2044e0d64076..c6940bb8ec3b 100644 --- a/arch/x86/kernel/cpu/sgx/epc_cgroup.h +++ b/arch/x86/kernel/cpu/sgx/epc_cgroup.h @@ -13,6 +13,11 @@ #define MISC_CG_RES_SGX_EPC MISC_CG_RES_TYPES struct sgx_cgroup; +static inline struct misc_cg *misc_from_sgx(struct sgx_cgroup *sgx_cg) +{ + return NULL; +} + static inline struct sgx_cgroup *sgx_get_current_cg(void) { return NULL; @@ -27,8 +32,25 @@ static inline int sgx_cgroup_try_charge(struct sgx_cgroup *sgx_cg, enum sgx_recl static inline void sgx_cgroup_uncharge(struct sgx_cgroup *sgx_cg) { } +static inline bool sgx_cgroup_lru_empty(struct misc_cg *root) +{ + return true; +} + +static inline bool sgx_cgroup_should_reclaim(struct sgx_cgroup *sgx_cg) +{ + return false; +} + static inline void sgx_cgroup_init(void) { } +static inline struct misc_cg *sgx_cgroup_reclaim_pages(struct misc_cg *root, + struct misc_cg *next_cg, + struct mm_struct *charge_mm) +{ + return NULL; +} + #else /* CONFIG_CGROUP_MISC */ struct sgx_cgroup { @@ -37,6 +59,11 @@ struct sgx_cgroup { struct work_struct reclaim_work; }; +static inline struct misc_cg *misc_from_sgx(struct sgx_cgroup *sgx_cg) +{ + return sgx_cg->cg; +} + static inline struct sgx_cgroup *sgx_cgroup_from_misc_cg(struct misc_cg *cg) { return (struct sgx_cgroup *)(cg->res[MISC_CG_RES_SGX_EPC].priv); @@ -67,6 +94,11 @@ static inline void sgx_put_cg(struct sgx_cgroup *sgx_cg) int sgx_cgroup_try_charge(struct sgx_cgroup *sgx_cg, enum sgx_reclaim reclaim); void sgx_cgroup_uncharge(struct sgx_cgroup *sgx_cg); +bool sgx_cgroup_lru_empty(struct misc_cg *root); +bool sgx_cgroup_should_reclaim(struct sgx_cgroup *sgx_cg); +struct misc_cg *sgx_cgroup_reclaim_pages(struct misc_cg *root, + struct misc_cg *next_cg, + struct mm_struct *charge_mm); void sgx_cgroup_init(void); #endif /* CONFIG_CGROUP_MISC */ diff --git a/arch/x86/kernel/cpu/sgx/main.c b/arch/x86/kernel/cpu/sgx/main.c index c8ac4eb996aa..30ca489007ec 100644 --- a/arch/x86/kernel/cpu/sgx/main.c +++ b/arch/x86/kernel/cpu/sgx/main.c @@ -32,9 +32,30 @@ static DEFINE_XARRAY(sgx_epc_address_space); */ static struct sgx_epc_lru_list sgx_global_lru; +/* + * Get the per-cgroup or global LRU list that tracks the given reclaimable page. + */ static inline struct sgx_epc_lru_list *sgx_epc_page_lru(struct sgx_epc_page *epc_page) { +#ifdef CONFIG_CGROUP_MISC + /* + * epc_page->sgx_cg here is never NULL during a reclaimable epc_page's + * life between sgx_alloc_epc_page() and sgx_free_epc_page(): + * + * In sgx_alloc_epc_page(), epc_page->sgx_cg is set to the return from + * sgx_get_current_cg() which is the misc cgroup of the current task, or + * the root by default even if the misc cgroup is disabled by kernel + * command line. + * + * epc_page->sgx_cg is only unset by sgx_free_epc_page(). + * + * This function is never used before sgx_alloc_epc_page() or after + * sgx_free_epc_page(). + */ + return &epc_page->sgx_cg->lru; +#else return &sgx_global_lru; +#endif } /* @@ -42,7 +63,10 @@ static inline struct sgx_epc_lru_list *sgx_epc_page_lru(struct sgx_epc_page *epc */ static inline bool sgx_can_reclaim_global(void) { - return !list_empty(&sgx_global_lru.reclaimable); + if (IS_ENABLED(CONFIG_CGROUP_MISC)) + return !sgx_cgroup_lru_empty(misc_cg_root()); + else + return !list_empty(&sgx_global_lru.reclaimable); } static atomic_long_t sgx_nr_free_pages = ATOMIC_LONG_INIT(0); @@ -402,9 +426,14 @@ static bool sgx_should_reclaim_global(unsigned long watermark) sgx_can_reclaim_global(); } -static void sgx_reclaim_pages_global(struct mm_struct *charge_mm) +static struct misc_cg *sgx_reclaim_pages_global(struct misc_cg *next_cg, + struct mm_struct *charge_mm) { + if (IS_ENABLED(CONFIG_CGROUP_MISC)) + return sgx_cgroup_reclaim_pages(misc_cg_root(), next_cg, charge_mm); + sgx_reclaim_pages(&sgx_global_lru, charge_mm); + return NULL; } /* @@ -414,12 +443,35 @@ static void sgx_reclaim_pages_global(struct mm_struct *charge_mm) */ void sgx_reclaim_direct(void) { + struct sgx_cgroup *sgx_cg = sgx_get_current_cg(); + struct misc_cg *cg = misc_from_sgx(sgx_cg); + struct misc_cg *next_cg = NULL; + + /* + * Make sure there are some free pages at both cgroup and global levels. + * In both cases, only make one attempt of reclamation to avoid lengthy + * block on the caller. + */ + if (sgx_cg && sgx_cgroup_should_reclaim(sgx_cg)) + next_cg = sgx_cgroup_reclaim_pages(cg, next_cg, current->mm); + + if (next_cg != cg) + put_misc_cg(next_cg); + + next_cg = NULL; if (sgx_should_reclaim_global(SGX_NR_LOW_PAGES)) - sgx_reclaim_pages_global(current->mm); + next_cg = sgx_reclaim_pages_global(next_cg, current->mm); + + if (next_cg != misc_cg_root()) + put_misc_cg(next_cg); + + sgx_put_cg(sgx_cg); } static int ksgxd(void *p) { + struct misc_cg *next_cg = NULL; + set_freezable(); /* @@ -437,11 +489,15 @@ static int ksgxd(void *p) kthread_should_stop() || sgx_should_reclaim_global(SGX_NR_HIGH_PAGES)); - if (sgx_should_reclaim_global(SGX_NR_HIGH_PAGES)) + while (!kthread_should_stop() && sgx_should_reclaim_global(SGX_NR_HIGH_PAGES)) { /* Indirect reclaim, no mm to charge, so NULL: */ - sgx_reclaim_pages_global(NULL); + next_cg = sgx_reclaim_pages_global(next_cg, NULL); + cond_resched(); + } - cond_resched(); + if (next_cg != misc_cg_root()) + put_misc_cg(next_cg); + next_cg = NULL; } return 0; @@ -583,6 +639,7 @@ int sgx_unmark_page_reclaimable(struct sgx_epc_page *page) */ struct sgx_epc_page *sgx_alloc_epc_page(void *owner, enum sgx_reclaim reclaim) { + struct misc_cg *next_cg = NULL; struct sgx_cgroup *sgx_cg; struct sgx_epc_page *page; int ret; @@ -616,10 +673,19 @@ struct sgx_epc_page *sgx_alloc_epc_page(void *owner, enum sgx_reclaim reclaim) break; } - sgx_reclaim_pages_global(current->mm); + /* + * At this point, the usage within this cgroup is under its + * limit but there is no physical page left for allocation. + * Perform a global reclaim to get some pages released from any + * cgroup with reclaimable pages. + */ + next_cg = sgx_reclaim_pages_global(next_cg, current->mm); cond_resched(); } + if (next_cg != misc_cg_root()) + put_misc_cg(next_cg); + if (!IS_ERR(page)) { WARN_ON_ONCE(sgx_epc_page_get_cgroup(page)); /* sgx_put_cg() in sgx_free_epc_page() */ From patchwork Fri May 31 22:26:29 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Haitao Huang X-Patchwork-Id: 13682252 Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.15]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 62E8B136672; Fri, 31 May 2024 22:26:41 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.15 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1717194403; cv=none; b=c6i3eDzgTqdm2eoAuy91X5Rv0ylH1k3qcmhXbVV8oiRLa4oSxQcZhaOZLrbXDXWD1PL8Vl70ARmm3L37YBmmmZgvCITBre1JSv02d5FhuAXxSR6DP5YT0yx54FC3hTMqwQYmgOxFWkn6eiB06MvxraOIyifEUa7D19+UygVs7lA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1717194403; c=relaxed/simple; bh=Zw7+XtU28xAKPPo/jwXOi19mKbM25ziwIytdc6JGrDU=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=rff1BVwMq3bfrH6l6iu4z1Mx6s5roLFNvc/Wdn5FITF9jUHiO56oiyO8aVahmliL0ibQUtUh9H8kOAz8wOy8Kr1sAKJdTzRcg92EBGoOjEr/ufFpT7xOpEW6nwmRjvhIfJ2cCsdlsj+pEN2AJCOFAWH3tGjC5Fu7oVaMjyG7ZTM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com; spf=none smtp.mailfrom=linux.intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=MCJh2Ps1; arc=none smtp.client-ip=192.198.163.15 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; spf=none smtp.mailfrom=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="MCJh2Ps1" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1717194401; x=1748730401; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=Zw7+XtU28xAKPPo/jwXOi19mKbM25ziwIytdc6JGrDU=; b=MCJh2Ps1FWabRqyCqDUgV1Co4AjcsNSA2yjPS5IdHHF34dKEQ24SGxuD wjnQXABik3h8KQWnd7PWmpFijqavu1I85qxWYwa2ZVkGN3FInikrfx2n4 xKLxmWua2gHnDaBgw1F/BL9HiFS2PCYDBT2dBUPqB6PTyXfM3/uX3jbHY 5CLqaHiZj+ZjdJsQzLdy02RUBosyhuN76aMovxbVfztGg88PZYjwCefC/ ks/2zH+W4GyUqfvv3uj589xAo9oNfzi81d0ibuDDIODxAEaCeBrfnggre M1GnKxNoQGKyfJkN1TeivG+Qv/vr2NG5IeRv7qs4Mb79ekuVj7efo3u9C A==; X-CSE-ConnectionGUID: mWcXNvPGQ0K2EWuEoSqevg== X-CSE-MsgGUID: ADQgk9P0QKyMSAzrkrFLRg== X-IronPort-AV: E=McAfee;i="6600,9927,11089"; a="13949842" X-IronPort-AV: E=Sophos;i="6.08,205,1712646000"; d="scan'208";a="13949842" Received: from fmviesa005.fm.intel.com ([10.60.135.145]) by fmvoesa109.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 31 May 2024 15:26:39 -0700 X-CSE-ConnectionGUID: 9BanqYf7QuaC5vGzRa4PdQ== X-CSE-MsgGUID: TA/25mt/SEG+TH73u5q84Q== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.08,205,1712646000"; d="scan'208";a="40736951" Received: from b4969161e530.jf.intel.com ([10.165.56.46]) by fmviesa005.fm.intel.com with ESMTP; 31 May 2024 15:26:38 -0700 From: Haitao Huang To: jarkko@kernel.org, dave.hansen@linux.intel.com, kai.huang@intel.com, tj@kernel.org, mkoutny@suse.com, linux-kernel@vger.kernel.org, linux-sgx@vger.kernel.org, x86@kernel.org, cgroups@vger.kernel.org, tglx@linutronix.de, mingo@redhat.com, bp@alien8.de, hpa@zytor.com, sohil.mehta@intel.com, tim.c.chen@linux.intel.com Cc: zhiquan1.li@intel.com, kristen@linux.intel.com, seanjc@google.com, zhanb@microsoft.com, anakrish@microsoft.com, mikko.ylinen@linux.intel.com, yangjie@microsoft.com, chrisyan@microsoft.com Subject: [PATCH v14 13/14] Docs/x86/sgx: Add description for cgroup support Date: Fri, 31 May 2024 15:26:29 -0700 Message-Id: <20240531222630.4634-14-haitao.huang@linux.intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20240531222630.4634-1-haitao.huang@linux.intel.com> References: <20240531222630.4634-1-haitao.huang@linux.intel.com> Precedence: bulk X-Mailing-List: linux-sgx@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Sean Christopherson Add initial documentation of how to regulate the distribution of SGX Enclave Page Cache (EPC) memory via the Miscellaneous cgroup controller. Signed-off-by: Sean Christopherson Co-developed-by: Kristen Carlson Accardi Signed-off-by: Kristen Carlson Accardi Co-developed-by: Haitao Huang Signed-off-by: Haitao Huang Cc: Sean Christopherson Reviewed-by: Bagas Sanjaya Reviewed-by: Jarkko Sakkinen Acked-by: Kai Huang Tested-by: Mikko Ylinen Tested-by: Jarkko Sakkinen --- V8: - Limit text width to 80 characters to be consistent. V6: - Remove mentioning of VMM specific behavior on handling SIGBUS - Remove statement of forced reclamation, add statement to specify ENOMEM returned when no reclamation possible. - Added statements on the non-preemptive nature for the max limit - Dropped Reviewed-by tag because of changes V4: - Fix indentation (Randy) - Change misc.events file to be read-only - Fix a typo for 'subsystem' - Add behavior when VMM overcommit EPC with a cgroup (Mikko) --- Documentation/arch/x86/sgx.rst | 83 ++++++++++++++++++++++++++++++++++ 1 file changed, 83 insertions(+) diff --git a/Documentation/arch/x86/sgx.rst b/Documentation/arch/x86/sgx.rst index d90796adc2ec..c537e6a9aa65 100644 --- a/Documentation/arch/x86/sgx.rst +++ b/Documentation/arch/x86/sgx.rst @@ -300,3 +300,86 @@ to expected failures and handle them as follows: first call. It indicates a bug in the kernel or the userspace client if any of the second round of ``SGX_IOC_VEPC_REMOVE_ALL`` calls has a return code other than 0. + + +Cgroup Support +============== + +The "sgx_epc" resource within the Miscellaneous cgroup controller regulates +distribution of SGX EPC memory, which is a subset of system RAM that is used to +provide SGX-enabled applications with protected memory, and is otherwise +inaccessible, i.e. shows up as reserved in /proc/iomem and cannot be +read/written outside of an SGX enclave. + +Although current systems implement EPC by stealing memory from RAM, for all +intents and purposes the EPC is independent from normal system memory, e.g. must +be reserved at boot from RAM and cannot be converted between EPC and normal +memory while the system is running. The EPC is managed by the SGX subsystem and +is not accounted by the memory controller. Note that this is true only for EPC +memory itself, i.e. normal memory allocations related to SGX and EPC memory, +e.g. the backing memory for evicted EPC pages, are accounted, limited and +protected by the memory controller. + +Much like normal system memory, EPC memory can be overcommitted via virtual +memory techniques and pages can be swapped out of the EPC to their backing store +(normal system memory allocated via shmem). The SGX EPC subsystem is analogous +to the memory subsystem, and it implements limit and protection models for EPC +memory. + +SGX EPC Interface Files +----------------------- + +For a generic description of the Miscellaneous controller interface files, +please see Documentation/admin-guide/cgroup-v2.rst + +All SGX EPC memory amounts are in bytes unless explicitly stated otherwise. If +a value which is not PAGE_SIZE aligned is written, the actual value used by the +controller will be rounded down to the closest PAGE_SIZE multiple. + + misc.capacity + A read-only flat-keyed file shown only in the root cgroup. The sgx_epc + resource will show the total amount of EPC memory available on the + platform. + + misc.current + A read-only flat-keyed file shown in the non-root cgroups. The sgx_epc + resource will show the current active EPC memory usage of the cgroup and + its descendants. EPC pages that are swapped out to backing RAM are not + included in the current count. + + misc.max + A read-write single value file which exists on non-root cgroups. The + sgx_epc resource will show the EPC usage hard limit. The default is + "max". + + If a cgroup's EPC usage reaches this limit, EPC allocations, e.g., for + page fault handling, will be blocked until EPC can be reclaimed from the + cgroup. If there are no pages left that are reclaimable within the same + group, the kernel returns ENOMEM. + + The EPC pages allocated for a guest VM by the virtual EPC driver are not + reclaimable by the host kernel. In case the guest cgroup's limit is + reached and no reclaimable pages left in the same cgroup, the virtual + EPC driver returns SIGBUS to the user space process to indicate failure + on new EPC allocation requests. + + The misc.max limit is non-preemptive. If a user writes a limit lower + than the current usage to this file, the cgroup will not preemptively + deallocate pages currently in use, and will only start blocking the next + allocation and reclaiming EPC at that time. + + misc.events + A read-only flat-keyed file which exists on non-root cgroups. + A value change in this file generates a file modified event. + + max + The number of times the cgroup has triggered a reclaim due to + its EPC usage approaching (or exceeding) its max EPC boundary. + +Migration +--------- + +Once an EPC page is charged to a cgroup (during allocation), it remains charged +to the original cgroup until the page is released or reclaimed. Migrating a +process to a different cgroup doesn't move the EPC charges that it incurred +while in the previous cgroup to its new cgroup. From patchwork Fri May 31 22:26:30 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Haitao Huang X-Patchwork-Id: 13682253 Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.15]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C9030136E1B; Fri, 31 May 2024 22:26:42 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.15 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1717194405; cv=none; b=E2meuSWa8YTijtvx19wIcmfaNcqKXQjQ9pzCeSxB94kIiDZD/+Ui0rZLP/tn2qh3Psq+rX6wg41HT9ZCVbTTLZ6j6digu0nAMROZpGSEqz7JLzk8P0OnukJsqBJXr4jsIWud2fcy6ylx++k5OX7Vwk4c+hovb1pmlDabnOQFPa4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1717194405; c=relaxed/simple; bh=ZvSqE1J8uvdrp7+ebQz6eLSVWVss0NuPMkYi0D2Zzj8=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=XAJlTNqVkU6ACDVajtngXT0Ko90ndUfVCmQqYNvYJs4Cfhz4uMfldVPMRTiw0d+KPPMR/PawmrSLOmDQws0s3C3wYFKnnNSbUCSjZgH7zFhnjKoBJ+0prBCISKNkzcdSkl6BLT3rqPdurty7DgGQXW/RDY83HFm/3fNYAtrQlO4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com; spf=none smtp.mailfrom=linux.intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=KO4DWAVz; arc=none smtp.client-ip=192.198.163.15 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; spf=none smtp.mailfrom=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="KO4DWAVz" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1717194403; x=1748730403; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=ZvSqE1J8uvdrp7+ebQz6eLSVWVss0NuPMkYi0D2Zzj8=; b=KO4DWAVz8yJIdkvqZjfVf5EEFgbBg59IDTn3NwQXjQ4m/udMxq0fGnLs VHllTYgygbPenNBIDRR6k91nASLEE5Zrbzgf1KRKe9koRbnBzuPtgMSPs Thte7+pMLJxpiN8JsaP8LFwitqdp7DN4dqsGKRO0FHM41SrwB4SgoqAeM X5MMmAhvJ43cfm2UwuCTGS33ki9iqIS3eV0/cVzEzsGdFg8owlFG0ns+z lxZHVEMlSxJX2fJzkGq9LMGsGcsDpkdAO997q9JzAL2yJeXQHPpyZCvkP IidBeFWw8PYG3ntEF0qvV75dVDeERnxqK4ylE6nUNSFdZjd7OvtesyRm7 g==; X-CSE-ConnectionGUID: Kbbd+5XOSD6W8L6y0vq7yQ== X-CSE-MsgGUID: LRxJCRjLTMC1ms3OiLj+5Q== X-IronPort-AV: E=McAfee;i="6600,9927,11089"; a="13949851" X-IronPort-AV: E=Sophos;i="6.08,205,1712646000"; d="scan'208";a="13949851" Received: from fmviesa005.fm.intel.com ([10.60.135.145]) by fmvoesa109.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 31 May 2024 15:26:40 -0700 X-CSE-ConnectionGUID: 5+EXY/WsT6ukoF6ylmiqWA== X-CSE-MsgGUID: rubWArYYQ8yFFtCwQZZ7eA== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.08,205,1712646000"; d="scan'208";a="40736954" Received: from b4969161e530.jf.intel.com ([10.165.56.46]) by fmviesa005.fm.intel.com with ESMTP; 31 May 2024 15:26:39 -0700 From: Haitao Huang To: jarkko@kernel.org, dave.hansen@linux.intel.com, kai.huang@intel.com, tj@kernel.org, mkoutny@suse.com, linux-kernel@vger.kernel.org, linux-sgx@vger.kernel.org, x86@kernel.org, cgroups@vger.kernel.org, tglx@linutronix.de, mingo@redhat.com, bp@alien8.de, hpa@zytor.com, sohil.mehta@intel.com, tim.c.chen@linux.intel.com Cc: zhiquan1.li@intel.com, kristen@linux.intel.com, seanjc@google.com, zhanb@microsoft.com, anakrish@microsoft.com, mikko.ylinen@linux.intel.com, yangjie@microsoft.com, chrisyan@microsoft.com Subject: [PATCH v14 14/14] selftests/sgx: Add scripts for EPC cgroup testing Date: Fri, 31 May 2024 15:26:30 -0700 Message-Id: <20240531222630.4634-15-haitao.huang@linux.intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20240531222630.4634-1-haitao.huang@linux.intel.com> References: <20240531222630.4634-1-haitao.huang@linux.intel.com> Precedence: bulk X-Mailing-List: linux-sgx@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 With different cgroups, the script starts one or multiple concurrent SGX selftests (test_sgx), each to run the unclobbered_vdso_oversubscribed test case, which loads an enclave of EPC size equal to the EPC capacity available on the platform. The script checks results against the expectation set for each cgroup and reports success or failure. The script creates 3 different cgroups at the beginning with following expectations: 1) small - intentionally small enough to fail the test loading an enclave of size equal to the capacity. 2) large - large enough to run up to 4 concurrent tests but fail some if more than 4 concurrent tests are run. The script starts 4 expecting at least one test to pass, and then starts 5 expecting at least one test to fail. 3) larger - limit is the same as the capacity, large enough to run lots of concurrent tests. The script starts 8 of them and expects all pass. Then it reruns the same test with one process randomly killed and usage checked to be zero after all processes exit. The script also includes a test with low mem_cg limit and large sgx_epc limit to verify that the RAM used for per-cgroup reclamation is charged to a proper mem_cg. For this test, it turns off swapping before start, and turns swapping back on afterwards. Add README to document how to run the tests. Signed-off-by: Haitao Huang Reviewed-by: Jarkko Sakkinen Tested-by: Jarkko Sakkinen --- V13: - More improvement on handling error cases and style fixes. - Add settings file for custom timeout V12: - Integrate the scripts to the "run_tests" target. (Jarkko) V11: - Remove cgroups-tools dependency and make scripts ash compatible. (Jarkko) - Drop support for cgroup v1 and simplify. (Michal, Jarkko) - Add documentation for functions. (Jarkko) - Turn off swapping before memcontrol tests and back on after - Format and style fixes, name for hard coded values V7: - Added memcontrol test. V5: - Added script with automatic results checking, remove the interactive script. - The script can run independent from the series below. --- tools/testing/selftests/sgx/Makefile | 3 +- tools/testing/selftests/sgx/README | 109 +++++++ tools/testing/selftests/sgx/ash_cgexec.sh | 16 + tools/testing/selftests/sgx/config | 4 + .../selftests/sgx/run_epc_cg_selftests.sh | 295 ++++++++++++++++++ tools/testing/selftests/sgx/settings | 2 + .../selftests/sgx/watch_misc_for_tests.sh | 11 + 7 files changed, 439 insertions(+), 1 deletion(-) create mode 100644 tools/testing/selftests/sgx/README create mode 100755 tools/testing/selftests/sgx/ash_cgexec.sh create mode 100644 tools/testing/selftests/sgx/config create mode 100755 tools/testing/selftests/sgx/run_epc_cg_selftests.sh create mode 100644 tools/testing/selftests/sgx/settings create mode 100755 tools/testing/selftests/sgx/watch_misc_for_tests.sh diff --git a/tools/testing/selftests/sgx/Makefile b/tools/testing/selftests/sgx/Makefile index 867f88ce2570..739376af9e33 100644 --- a/tools/testing/selftests/sgx/Makefile +++ b/tools/testing/selftests/sgx/Makefile @@ -20,7 +20,8 @@ ENCL_LDFLAGS := -Wl,-T,test_encl.lds,--build-id=none ifeq ($(CAN_BUILD_X86_64), 1) TEST_CUSTOM_PROGS := $(OUTPUT)/test_sgx -TEST_FILES := $(OUTPUT)/test_encl.elf +TEST_FILES := $(OUTPUT)/test_encl.elf ash_cgexec.sh +TEST_PROGS := run_epc_cg_selftests.sh all: $(TEST_CUSTOM_PROGS) $(OUTPUT)/test_encl.elf endif diff --git a/tools/testing/selftests/sgx/README b/tools/testing/selftests/sgx/README new file mode 100644 index 000000000000..f84406bf29a4 --- /dev/null +++ b/tools/testing/selftests/sgx/README @@ -0,0 +1,109 @@ +SGX selftests + +The SGX selftests includes a c program (test_sgx) that covers basic user space +facing APIs and a shell scripts (run_sgx_cg_selftests.sh) testing SGX misc +cgroup. The SGX cgroup test script requires root privileges and runs a +specific test case of the test_sgx in different cgroups configured by the +script. More details about the cgroup test can be found below. + +All SGX selftests can run with or without kselftest framework. + +WITH KSELFTEST FRAMEWORK +======================= + +BUILD +----- + +Build executable file "test_sgx" from top level directory of the kernel source: + $ make -C tools/testing/selftests TARGETS=sgx + +RUN +--- + +Run all sgx tests as sudo or root since the cgroup tests need to configure cgroup +limits in files under /sys/fs/cgroup. + + $ sudo make -C tools/testing/selftests/sgx run_tests + +Without sudo, SGX cgroup tests will be skipped. + +On platforms with large Enclave Page Cache (EPC) and/or less cpu cores, you may +need adjust the timeout in 'settings' to avoid timeouts. + +More details about kselftest framework can be found in +Documentation/dev-tools/kselftest.rst. + +WITHOUT KSELFTEST FRAMEWORK +=========================== + +BUILD +----- + +Build executable file "test_sgx" from this +directory(tools/testing/selftests/sgx/): + + $ make + +RUN +--- + +Run all non-cgroup tests: + + $ ./test_sgx + +To test SGX cgroup: + + $ sudo ./run_sgx_cg_selftests.sh + +THE SGX CGROUP TEST SCRIPTS +=========================== + +Overview of the main cgroup test script +--------------------------------------- + +With different cgroups, the script (run_sgx_cg_selftests.sh) starts one or +multiple concurrent SGX selftests (test_sgx), each to run the +unclobbered_vdso_oversubscribed test case, which loads an enclave of EPC size +equal to the EPC capacity available on the platform. The script checks results +against the expectation set for each cgroup and reports success or failure. + +The script creates 3 different cgroups at the beginning with following +expectations: + + 1) small - intentionally small enough to fail the test loading an enclave of + size equal to the capacity. + + 2) large - large enough to run up to 4 concurrent tests but fail some if more + than 4 concurrent tests are run. The script starts 4 expecting at + least one test to pass, and then starts 5 expecting at least one + test to fail. + + 3) larger - limit is the same as the capacity, large enough to run lots of + concurrent tests. The script starts 8 of them and expects all + pass. Then it reruns the same test with one process randomly + killed and usage checked to be zero after all processes exit. + +The script also includes a test with low mem_cg limit (memory.max) and the +'large' sgx_epc limit to verify that the RAM used for per-cgroup reclamation is +charged to a proper mem_cg. To validate mem_cg OOM-kills processes when its +memory.max limit is reached due to SGX EPC reclamation, the script turns off +swapping before start, and turns swapping back on afterwards for this particular +test. + +The helper script +------------------------------------------------------ + +To monitor the SGX cgroup settings and behaviors or trouble-shoot during +testing, the helper script, watch_misc_for_tests.sh, can be used to watch +relevant entries in cgroupfs files. For example, to watch the SGX cgroup +'current' counter changes during testing, run this in a separate terminal from +this directory: + + $ ./watch_misc_for_tests.sh current + +For more details about SGX cgroups, see "Cgroup Support" in +Documentation/arch/x86/sgx.rst. + +The scripts require cgroup v2 support. More details about cgroup v2 can be found +in Documentation/admin-guide/cgroup-v2.rst. + diff --git a/tools/testing/selftests/sgx/ash_cgexec.sh b/tools/testing/selftests/sgx/ash_cgexec.sh new file mode 100755 index 000000000000..cfa5d2b0e795 --- /dev/null +++ b/tools/testing/selftests/sgx/ash_cgexec.sh @@ -0,0 +1,16 @@ +#!/usr/bin/env sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright(c) 2024 Intel Corporation. + +# Start a program in a given cgroup. +# Supports V2 cgroup paths, relative to /sys/fs/cgroup +if [ "$#" -lt 2 ]; then + echo "Usage: $0 [args...]" + exit 1 +fi +# Move this shell to the cgroup. +echo 0 >/sys/fs/cgroup/$1/cgroup.procs +shift +# Execute the command within the cgroup +exec "$@" + diff --git a/tools/testing/selftests/sgx/config b/tools/testing/selftests/sgx/config new file mode 100644 index 000000000000..e7f1db1d3eff --- /dev/null +++ b/tools/testing/selftests/sgx/config @@ -0,0 +1,4 @@ +CONFIG_CGROUPS=y +CONFIG_CGROUP_MISC=y +CONFIG_MEMCG=y +CONFIG_X86_SGX=y diff --git a/tools/testing/selftests/sgx/run_epc_cg_selftests.sh b/tools/testing/selftests/sgx/run_epc_cg_selftests.sh new file mode 100755 index 000000000000..f3d463c09cc2 --- /dev/null +++ b/tools/testing/selftests/sgx/run_epc_cg_selftests.sh @@ -0,0 +1,295 @@ +#!/usr/bin/env sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright(c) 2023, 2024 Intel Corporation. + +PROCESS_SUCCESS=1 +PROCESS_FAILURE=0 +# Wait for a process and check for expected exit status. +# +# Arguments: +# $1 - the pid of the process to wait and check. +# $2 - 1 if expecting success, 0 for failure. +# +# Return: +# 0 if the exit status of the process matches the expectation. +# 1 otherwise. +wait_check_process_status() { + pid=$1 + check_for_success=$2 + + wait "$pid" + status=$? + + if [ $check_for_success -eq $PROCESS_SUCCESS ] && [ $status -eq 0 ]; then + echo "# Process $pid succeeded." + return 0 + elif [ $check_for_success -eq $PROCESS_FAILURE ] && [ $status -ne 0 ]; then + echo "# Process $pid returned failure." + return 0 + fi + return 1 +} + +# Wait for a set of processes and check for expected exit status +# +# Arguments: +# $1 - 1 if expecting success, 0 for failure. +# remaining args - The pids of the processes +# +# Return: +# 0 if exit status of any process matches the expectation. +# 1 otherwise. +wait_and_detect_for_any() { + check_for_success=$1 + + shift + detected=1 # 0 for success detection + + for pid in $@; do + if wait_check_process_status "$pid" "$check_for_success"; then + detected=0 + # Wait for other processes to exit + fi + done + + return $detected +} + +# Kselftest framework requirement - SKIP code is 4. +ksft_skip=4 +if [ "$(id -u)" -ne 0 ]; then + echo "SKIP: SGX cgroup tests need root privileges." + exit $ksft_skip +fi + +cg_root=/sys/fs/cgroup +if [ ! -d "$cg_root/$test_root_cg" ]; then + echo "SKIP: SGX cgroup tests require v2 cgroups." + exit $ksft_skip +fi +test_root_cg=sgx_kselftest +#make sure we start clean +if [ -d "$cg_root/$test_root_cg" ]; then + echo "SKIP: Please clean up $cg_root/$test_root_cg." + exit $ksft_skip +fi + +test_cg_small_parent=$test_root_cg/sgx_test_small_parent +test_cg_large=$test_root_cg/sgx_test_large +# We will only set limit in test1 and run tests in test3 +test_cg_small=$test_cg_small_parent/sgx_test_small +test_cg_larger=$test_root_cg/sgx_test_larger + +clean_up() +{ + # Wait a little for cgroups to reset counters for dead processes. + sleep 2 + rmdir $cg_root/$test_cg_large + rmdir $cg_root/$test_cg_small + rmdir $cg_root/$test_cg_larger + rmdir $cg_root/$test_cg_small_parent + rmdir $cg_root/$test_root_cg +} + +mkdir $cg_root/$test_root_cg && \ +mkdir $cg_root/$test_cg_small_parent && \ +mkdir $cg_root/$test_cg_large && \ +mkdir $cg_root/$test_cg_small && \ +mkdir $cg_root/$test_cg_larger +if [ $? -ne 0 ]; then + echo "FAIL: Failed creating cgroups." + exit 1 +fi + +# Turn on misc and memory controller in non-leaf nodes +echo "+misc" > $cg_root/cgroup.subtree_control && \ +echo "+memory" > $cg_root/cgroup.subtree_control && \ +echo "+misc" > $cg_root/$test_root_cg/cgroup.subtree_control && \ +echo "+memory" > $cg_root/$test_root_cg/cgroup.subtree_control && \ +echo "+misc" > $cg_root/$test_cg_small_parent/cgroup.subtree_control +if [ $? -ne 0 ]; then + echo "FAIL: can't set up cgroups, make sure misc and memory cgroups are enabled." + clean_up + exit 1 +fi + +epc_capacity=$(grep "sgx_epc" "$cg_root/misc.capacity" | awk '{print $2}') + +# This is below number of VA pages needed for enclave of capacity size. So +# should fail oversubscribed cases +epc_small_limit=$(( epc_capacity / 512 )) + +# At least load one enclave of capacity size successfully, maybe up to 4. +# But some may fail if we run more than 4 concurrent enclaves of capacity size. +epc_large_limit=$(( epc_small_limit * 4 )) + +# Load lots of enclaves +epc_larger_limit=$epc_capacity +echo "# Setting up SGX cgroup limits." +echo "sgx_epc $epc_small_limit" > $cg_root/$test_cg_small_parent/misc.max && \ +echo "sgx_epc $epc_large_limit" > $cg_root/$test_cg_large/misc.max && \ +echo "sgx_epc $epc_larger_limit" > $cg_root/$test_cg_larger/misc.max +if [ $? -ne 0 ]; then + echo "# Failed setting up misc limits for sgx_epc." + echo "SKIP: Kernel does not support SGX cgroup." + clean_up + exit $ksft_skip +fi + +test_cmd="./test_sgx -t unclobbered_vdso_oversubscribed" + +echo "# Start unclobbered_vdso_oversubscribed with small EPC limit, expecting failure..." +./ash_cgexec.sh $test_cg_small $test_cmd >/dev/null 2>&1 +if [ $? -eq 0 ]; then + echo "FAIL: Fail on small EPC limit, not expecting any test passes." + clean_up + exit 1 +else + echo "# Test failed as expected." +fi + +echo "PASS: small EPC limit test." + +echo "# Start 4 concurrent unclobbered_vdso_oversubscribed tests with large EPC limit, \ +expecting at least one success...." + +pids="" +for i in 1 2 3 4; do + ( + ./ash_cgexec.sh $test_cg_large $test_cmd >/dev/null 2>&1 + ) & + pids="$pids $!" +done + +if wait_and_detect_for_any $PROCESS_SUCCESS "$pids"; then + echo "PASS: large EPC limit positive testing." +else + echo "FAIL: Failed on large EPC limit positive testing, no test passes." + clean_up + exit 1 +fi + +echo "# Start 5 concurrent unclobbered_vdso_oversubscribed tests with large EPC limit, \ +expecting at least one failure...." +pids="" +for i in 1 2 3 4 5; do + ( + ./ash_cgexec.sh $test_cg_large $test_cmd >/dev/null 2>&1 + ) & + pids="$pids $!" +done + +if wait_and_detect_for_any $PROCESS_FAILURE "$pids"; then + echo "PASS: large EPC limit negative testing." +else + echo "FAIL: Failed on large EPC limit negative testing, no test fails." + clean_up + exit 1 +fi + +echo "# Start 8 concurrent unclobbered_vdso_oversubscribed tests with larger EPC limit, \ +expecting no failure...." +pids="" +for i in 1 2 3 4 5 6 7 8; do + ( + ./ash_cgexec.sh $test_cg_larger $test_cmd >/dev/null 2>&1 + ) & + pids="$pids $!" +done + +if wait_and_detect_for_any $PROCESS_FAILURE "$pids"; then + echo "FAIL: Failed on larger EPC limit, at least one test fails." + clean_up + exit 1 +else + echo "PASS: larger EPC limit tests." +fi + +echo "# Start 8 concurrent unclobbered_vdso_oversubscribed tests with larger EPC limit,\ + randomly kill one, expecting no failure...." +pids="" +for i in 1 2 3 4 5 6 7 8; do + ( + ./ash_cgexec.sh $test_cg_larger $test_cmd >/dev/null 2>&1 + ) & + pids="$pids $!" +done +random_number=$(awk 'BEGIN{srand();print int(rand()*5)}') +sleep $((random_number + 1)) + +# Randomly select a process to kill +# Make sure usage counter not leaked at the end. +random_index=$(awk 'BEGIN{srand();print int(rand()*8)}') +counter=0 +for pid in $pids; do + if [ "$counter" -eq "$random_index" ]; then + pid_to_kill=$pid + break + fi + counter=$((counter + 1)) +done + +kill $pid_to_kill +echo "# Killed process with PID: $pid_to_kill" + +any_failure=0 +for pid in $pids; do + wait "$pid" + status=$? + if [ "$pid" != "$pid_to_kill" ]; then + if [ $status -ne 0 ]; then + echo "# Process $pid returned failure." + any_failure=1 + fi + fi +done + +if [ $any_failure -ne 0 ]; then + echo "FAIL: Failed on random killing, at least one test fails." + clean_up + exit 1 +fi +echo "PASS: larger EPC limit test with a process randomly killed." + +mem_limit_too_small=$((epc_capacity - 2 * epc_large_limit)) + +echo "$mem_limit_too_small" > $cg_root/$test_cg_large/memory.max +if [ $? -ne 0 ]; then + echo "FAIL: Failed setting up memory controller." + clean_up + exit 1 +fi + +echo "# Start 4 concurrent unclobbered_vdso_oversubscribed tests with large EPC limit, \ +and too small RAM limit, expecting all failures...." +# Ensure swapping off so the OOM killer is activated when mem_cgroup limit is hit. +swapoff -a +pids="" +for i in 1 2 3 4; do + ( + ./ash_cgexec.sh $test_cg_large $test_cmd >/dev/null 2>&1 + ) & + pids="$pids $!" +done + +if wait_and_detect_for_any $PROCESS_SUCCESS "$pids"; then + echo "FAIL: Failed on tests with memcontrol, some tests did not fail." + clean_up + swapon -a + exit 1 +else + swapon -a + echo "PASS: large EPC limit tests with memcontrol." +fi + +sleep 2 + +epc_usage=$(grep '^sgx_epc' "$cg_root/$test_root_cg/misc.current" | awk '{print $2}') +if [ "$epc_usage" -ne 0 ]; then + echo "FAIL: Final usage is $epc_usage, not 0." +else + echo "PASS: leakage check." + echo "PASS: ALL cgroup limit tests, cleanup cgroups..." +fi +clean_up +echo "# Done SGX cgroup tests." diff --git a/tools/testing/selftests/sgx/settings b/tools/testing/selftests/sgx/settings new file mode 100644 index 000000000000..4bf7dcbf9fa8 --- /dev/null +++ b/tools/testing/selftests/sgx/settings @@ -0,0 +1,2 @@ +# This timeout may need be increased for platforms with EPC larger than 4G +timeout=140 diff --git a/tools/testing/selftests/sgx/watch_misc_for_tests.sh b/tools/testing/selftests/sgx/watch_misc_for_tests.sh new file mode 100755 index 000000000000..9280a5e0962b --- /dev/null +++ b/tools/testing/selftests/sgx/watch_misc_for_tests.sh @@ -0,0 +1,11 @@ +#!/usr/bin/env sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright(c) 2023, 2024 Intel Corporation. + +if [ -z "$1" ]; then + echo "No argument supplied, please provide 'max', 'current', or 'events'" + exit 1 +fi + +watch -n 1 'find /sys/fs/cgroup -wholename "*/sgx_test*/misc.'$1'" -exec \ + sh -c '\''echo "$1:"; cat "$1"'\'' _ {} \;'