From nobody Tue Feb 10 07:44:27 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) client-ip=192.237.175.120; envelope-from=xen-devel-bounces@lists.xenproject.org; helo=lists.xenproject.org; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; dmarc=pass(p=quarantine dis=none) header.from=suse.com ARC-Seal: i=1; a=rsa-sha256; t=1750063866; cv=none; d=zohomail.com; s=zohoarc; b=a/gO5k6OebmYIHtIdtnZ+uzyyrZMVY+UEKjs5lMKyLTqPgejEFKA+5rVyLJ4gC+M0Hk6cOroYqLyxoCyacq30shbvXuumwjzZI24Myv7yzFdCtrAWOmPvL9ecXHgPkG1IHycAeHKwC/AqYI4Kc/7VG0rVitTfE+N6BMPIFaZ1fs= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1750063866; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=t6vErAErnWD/FpLTzRhfE8JqNkLUXRMZRtPqHFEP1P8=; b=ZzdkOedZoEra/PE5eq244ydlFHUlrE5Z/i+Yv5X9Kf7b3iRr1221Onubw4AFceHhlVIEA6lNRQbF7aRgKJeOwu5fQUoUDNdT5btb3vTfJWUajNYTGTETe09LUzdc5DR0t/fCDpQCp8hh3I65g5VAbub666t29T0L06s9GO8Bg6U= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; dmarc=pass header.from= (p=quarantine dis=none) Return-Path: Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) by mx.zohomail.com with SMTPS id 1750063866975661.9227656020098; Mon, 16 Jun 2025 01:51:06 -0700 (PDT) Received: from list by lists.xenproject.org with outflank-mailman.1016954.1393965 (Exim 4.92) (envelope-from ) id 1uR5YF-0004jt-67; Mon, 16 Jun 2025 08:50:47 +0000 Received: by outflank-mailman (output) from mailman id 1016954.1393965; Mon, 16 Jun 2025 08:50:47 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1uR5YF-0004jU-0w; Mon, 16 Jun 2025 08:50:47 +0000 Received: by outflank-mailman (input) for mailman id 1016954; Mon, 16 Jun 2025 08:50:45 +0000 Received: from se1-gles-sth1-in.inumbo.com ([159.253.27.254] helo=se1-gles-sth1.inumbo.com) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1uR5UX-0007jR-8c for xen-devel@lists.xenproject.org; Mon, 16 Jun 2025 08:46:57 +0000 Received: from smtp-out2.suse.de (smtp-out2.suse.de [2a07:de40:b251:101:10:150:64:2]) by se1-gles-sth1.inumbo.com (Halon) with ESMTPS id 74d926bb-4a8e-11f0-a309-13f23c93f187; Mon, 16 Jun 2025 10:46:55 +0200 (CEST) Received: from imap1.dmz-prg2.suse.org (unknown [10.150.64.97]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by smtp-out2.suse.de (Postfix) with ESMTPS id 44EB41F387; Mon, 16 Jun 2025 08:46:55 +0000 (UTC) Received: from imap1.dmz-prg2.suse.org (localhost [127.0.0.1]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by imap1.dmz-prg2.suse.org (Postfix) with ESMTPS id 16AD3139E2; Mon, 16 Jun 2025 08:46:55 +0000 (UTC) Received: from dovecot-director2.suse.de ([2a07:de40:b281:106:10:150:64:167]) by imap1.dmz-prg2.suse.org with ESMTPSA id yj0oBP/ZT2gXQAAAD6G6ig (envelope-from ); Mon, 16 Jun 2025 08:46:55 +0000 X-Outflank-Mailman: Message body and most headers restored to incoming version X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" X-Inumbo-ID: 74d926bb-4a8e-11f0-a309-13f23c93f187 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.com; s=susede1; t=1750063615; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=t6vErAErnWD/FpLTzRhfE8JqNkLUXRMZRtPqHFEP1P8=; b=PHX2IwrcZ/YS5hTfN4yhU5/SXV3c3swS8eEhIhSMQZqnhRtqk9mZy8zfw2KirRigVGNjG+ 8wFtDb/QDlCghYPtOOd9KgwCx1CoXsPR214SgBevfEnowA9fHu+tVL2of+br5uMXGjlWTa H3aP2zAp1uGsrnSpfq0FFBfNApMf4Fo= Authentication-Results: smtp-out2.suse.de; none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.com; s=susede1; t=1750063615; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=t6vErAErnWD/FpLTzRhfE8JqNkLUXRMZRtPqHFEP1P8=; b=PHX2IwrcZ/YS5hTfN4yhU5/SXV3c3swS8eEhIhSMQZqnhRtqk9mZy8zfw2KirRigVGNjG+ 8wFtDb/QDlCghYPtOOd9KgwCx1CoXsPR214SgBevfEnowA9fHu+tVL2of+br5uMXGjlWTa H3aP2zAp1uGsrnSpfq0FFBfNApMf4Fo= From: Juergen Gross To: minios-devel@lists.xenproject.org, xen-devel@lists.xenproject.org Cc: samuel.thibault@ens-lyon.org, Juergen Gross , Jason Andryuk Subject: [MINI-OS PATCH v2 06/12] mini-os: reserve memory below boundary Date: Mon, 16 Jun 2025 10:46:13 +0200 Message-ID: <20250616084619.11112-7-jgross@suse.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20250616084619.11112-1-jgross@suse.com> References: <20250616084619.11112-1-jgross@suse.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Spamd-Result: default: False [-2.80 / 50.00]; BAYES_HAM(-3.00)[100.00%]; MID_CONTAINS_FROM(1.00)[]; NEURAL_HAM_LONG(-1.00)[-1.000]; R_MISSING_CHARSET(0.50)[]; NEURAL_HAM_SHORT(-0.20)[-0.999]; MIME_GOOD(-0.10)[text/plain]; ARC_NA(0.00)[]; MIME_TRACE(0.00)[0:+]; RCVD_COUNT_TWO(0.00)[2]; TO_DN_SOME(0.00)[]; DKIM_SIGNED(0.00)[suse.com:s=susede1]; FUZZY_BLOCKED(0.00)[rspamd.com]; TO_MATCH_ENVRCPT_ALL(0.00)[]; FROM_HAS_DN(0.00)[]; RCVD_VIA_SMTP_AUTH(0.00)[]; FROM_EQ_ENVFROM(0.00)[]; RCVD_TLS_ALL(0.00)[]; RCPT_COUNT_FIVE(0.00)[5]; DBL_BLOCKED_OPENRESOLVER(0.00)[suse.com:email,suse.com:mid,amd.com:email,imap1.dmz-prg2.suse.org:helo] X-Spam-Level: X-Spam-Flag: NO X-Spam-Score: -2.80 X-ZohoMail-DKIM: pass (identity @suse.com) X-ZM-MESSAGEID: 1750063867873116600 Content-Type: text/plain; charset="utf-8" In order to support kexec any memory used during copying the new kernel to its final destination must not overlap with the destination area. In order to achieve that add a new interface allowing to mark all allocatable memory below a specific physical address as not available. This is done by walking through all chunks of the buddy allocator and removing the chunks (or chunk parts) below the boundary. The removed chunks are put into a list in order to be able to undo the operation in case kexec is failing before doing any unrecoverable system modifications. Any pages freed located below the boundary need to go directly into the list of reserved pages instead of the free pool. Call the new function from kexec code. Signed-off-by: Juergen Gross Reviewed-by: Jason Andryuk --- include/mm.h | 5 +++ kexec.c | 5 +++ mm.c | 89 +++++++++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 98 insertions(+), 1 deletion(-) diff --git a/include/mm.h b/include/mm.h index 4fc364ff..5775c3e1 100644 --- a/include/mm.h +++ b/include/mm.h @@ -57,6 +57,11 @@ unsigned long alloc_pages(int order); void free_pages(void *pointer, int order); #define free_page(p) free_pages(p, 0) =20 +#ifdef CONFIG_KEXEC +void reserve_memory_below(unsigned long boundary); +void unreserve_memory_below(void); +#endif + static __inline__ int get_order(unsigned long size) { int order; diff --git a/kexec.c b/kexec.c index 31839382..1a90d8ab 100644 --- a/kexec.c +++ b/kexec.c @@ -174,6 +174,11 @@ int kexec(void *kernel, unsigned long kernel_size, con= st char *cmdline) =20 kexec_set_param_loc(cmdline); =20 + reserve_memory_below(kexec_last_addr); + + /* Error exit. */ + unreserve_memory_below(); + return ENOSYS; } EXPORT_SYMBOL(kexec); diff --git a/mm.c b/mm.c index a5d3f5e5..9236db58 100644 --- a/mm.c +++ b/mm.c @@ -230,6 +230,84 @@ static void init_page_allocator(unsigned long min, uns= igned long max) mm_alloc_bitmap_remap(); } =20 +#ifdef CONFIG_KEXEC +static chunk_head_t *reserved_chunks; +static unsigned long boundary_pfn; + +static void free_pages_below(void *pointer, unsigned int order) +{ + unsigned long pfn_s, pfn; + chunk_head_t *ch =3D pointer; + + pfn_s =3D virt_to_pfn(ch); + + if ( pfn_s + (1UL << order) <=3D boundary_pfn ) + { + /* Put complete chunk into reserved list. */ + ch->level =3D order; + ch->next =3D reserved_chunks; + reserved_chunks =3D ch; + } + else + { + /* Put pages below boundary into reserved list. */ + for ( pfn =3D pfn_s; pfn < boundary_pfn; pfn++ ) + { + chunk_head_t *ch_res =3D pfn_to_virt(pfn); + + ch_res->level =3D 0; + ch_res->next =3D reserved_chunks; + reserved_chunks =3D ch_res; + } + + /* Return pages above boundary to free pool again. */ + for ( ; pfn < pfn_s + (1UL << order); pfn++ ) + free_pages(pfn_to_virt(pfn), 0); + } +} + +void reserve_memory_below(unsigned long boundary) +{ + unsigned long pfn; + unsigned int order; + chunk_head_t *ch; + + ASSERT(!boundary_pfn); + boundary_pfn =3D PHYS_PFN(boundary); + + for ( order =3D 0; order < FREELIST_SIZE; order++ ) + { + for ( ch =3D free_list[order].next; !FREELIST_EMPTY(ch); ch =3D ch= ->next ) + { + pfn =3D virt_to_pfn(ch); + if ( pfn >=3D boundary_pfn ) + continue; + + /* Dequeue from this level, at least parts will be reserved. */ + dequeue_elem(ch); + /* Mark all as allocated, pieces above boundary will be return= ed. */ + map_alloc(pfn, 1UL << ch->level); + + free_pages_below(ch, ch->level); + } + } +} + +void unreserve_memory_below(void) +{ + chunk_head_t *ch; + + boundary_pfn =3D 0; + + while ( reserved_chunks ) + { + ch =3D reserved_chunks; + reserved_chunks =3D ch->next; + free_pages(ch, ch->level); + } +} +#endif /* CONFIG_KEXEC */ + /* Allocate 2^@order contiguous pages. Returns a VIRTUAL address. */ unsigned long alloc_pages(int order) { @@ -279,10 +357,19 @@ EXPORT_SYMBOL(alloc_pages); void free_pages(void *pointer, int order) { chunk_head_t *freed_ch, *to_merge_ch; + unsigned long pfn =3D virt_to_pfn(pointer); unsigned long mask; =20 +#ifdef CONFIG_KEXEC + if ( pfn < boundary_pfn ) + { + free_pages_below(pointer, order); + return; + } +#endif + /* First free the chunk */ - map_free(virt_to_pfn(pointer), 1UL << order); + map_free(pfn, 1UL << order); =20 /* Create free chunk */ freed_ch =3D (chunk_head_t *)pointer; --=20 2.43.0