From nobody Fri Oct 31 11:32:52 2025 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=1750063870; cv=none; d=zohomail.com; s=zohoarc; b=TBRypr8etUavzALUaHlD9qM4v/dORkuYxm1x9lzaiMM7NcfJqW+sWmEToHGa1taLN20zYN+SCOCKV25O2Od9AFssgUd2oBAcvE7DzbZQ/rvyoPAjYIdIFeYE9krnDndlTcEqqmAwALZ9UscM/n38dRXNhZ3JPtfhiVXmIr9sZos= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1750063870; 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=gNbWUmZdTVJqcXlU2fjp4XsMXe38emePLWQ2ppavBkA=; b=NcVQ1cLxRk0CTevDIDUCmbZ1d2tGbzWA2sf7ZnmV5wX0gC8914zUju/4fOEAJZQ0fc1j157mvTVM78MroKxgTHjPRw8wYC0jT74aSgMxMMFju4nsCCaamRAq8AX6zs/if/D/PCjLRwKPBelAYwgS3sfldSse/OfG6uivqTSWL1c= 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 1750063870852836.1324667821747; Mon, 16 Jun 2025 01:51:10 -0700 (PDT) Received: from list by lists.xenproject.org with outflank-mailman.1016988.1394015 (Exim 4.92) (envelope-from ) id 1uR5YP-0006Fu-01; Mon, 16 Jun 2025 08:50:57 +0000 Received: by outflank-mailman (output) from mailman id 1016988.1394015; Mon, 16 Jun 2025 08:50:56 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1uR5YO-0006Fb-QX; Mon, 16 Jun 2025 08:50:56 +0000 Received: by outflank-mailman (input) for mailman id 1016988; Mon, 16 Jun 2025 08:50:55 +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 1uR5Uh-0007jR-Ep for xen-devel@lists.xenproject.org; Mon, 16 Jun 2025 08:47:07 +0000 Received: from smtp-out1.suse.de (smtp-out1.suse.de [195.135.223.130]) by se1-gles-sth1.inumbo.com (Halon) with ESMTPS id 7b999b87-4a8e-11f0-a309-13f23c93f187; Mon, 16 Jun 2025 10:47:06 +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-out1.suse.de (Postfix) with ESMTPS id 861F32118C; Mon, 16 Jun 2025 08:47:06 +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 4B8F4139E2; Mon, 16 Jun 2025 08:47:06 +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 khXvEAraT2gsQAAAD6G6ig (envelope-from ); Mon, 16 Jun 2025 08:47:06 +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: 7b999b87-4a8e-11f0-a309-13f23c93f187 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.com; s=susede1; t=1750063626; 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=gNbWUmZdTVJqcXlU2fjp4XsMXe38emePLWQ2ppavBkA=; b=tls3nwVCrtCHQR59uMJcXlRMhSzYdIzt6nLDRUrn5+RcFk84twmAK068pfugW7FkGASKel omvkvRx7Ez7ZPUfB9awNnuzVEX00E9WvgLBp1SaJgt9kdeBwIr8QLdStc5veO8tRuo3SzN HJza56kLAE3SyO3bGwPWHlve/xxoPXc= Authentication-Results: smtp-out1.suse.de; none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.com; s=susede1; t=1750063626; 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=gNbWUmZdTVJqcXlU2fjp4XsMXe38emePLWQ2ppavBkA=; b=tls3nwVCrtCHQR59uMJcXlRMhSzYdIzt6nLDRUrn5+RcFk84twmAK068pfugW7FkGASKel omvkvRx7Ez7ZPUfB9awNnuzVEX00E9WvgLBp1SaJgt9kdeBwIr8QLdStc5veO8tRuo3SzN HJza56kLAE3SyO3bGwPWHlve/xxoPXc= 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 08/12] mini-os: kexec: move used pages away for new kernel Date: Mon, 16 Jun 2025 10:46:15 +0200 Message-ID: <20250616084619.11112-9-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,imap1.dmz-prg2.suse.org:helo,amd.com:email] X-Spam-Level: X-Spam-Flag: NO X-Spam-Score: -2.80 X-ZohoMail-DKIM: pass (identity @suse.com) X-ZM-MESSAGEID: 1750063871804116600 Content-Type: text/plain; charset="utf-8" Copying the new kexec kernel must not overwrite any pages still needed during this process. Those are especially the GDT, IDT and page tables. Move those to new allocated pages and update any related pointers. In case the kexec process is cancelled later, don't undo any page table moves, as the system can just be used with the new layout. By freeing the original pages there is no memory leaking. GDT and IDT should be reverted to their original locations, as their original memory can't be freed due to not being whole pages. Signed-off-by: Juergen Gross Reviewed-by: Jason Andryuk --- arch/x86/mm.c | 126 ++++++++++++++++++++++++++++++++++++++++++++++++ include/kexec.h | 5 ++ kexec.c | 6 +++ 3 files changed, 137 insertions(+) diff --git a/arch/x86/mm.c b/arch/x86/mm.c index 3ba6d917..a71eb192 100644 --- a/arch/x86/mm.c +++ b/arch/x86/mm.c @@ -42,6 +42,7 @@ #include #include #include +#include #include #include #include @@ -923,3 +924,128 @@ unsigned long map_frame_virt(unsigned long mfn) return addr; } EXPORT_SYMBOL(map_frame_virt); + +#ifdef CONFIG_KEXEC +static unsigned long kexec_gdt; +static unsigned long kexec_idt; + +static int move_pt(unsigned long va, unsigned int lvl, bool is_leaf, + pgentry_t *pte, void *par) +{ + unsigned long boundary_pfn =3D *(unsigned long *)par; + unsigned long pfn; + void *old_pg, *new_pg; + + if ( is_leaf ) + return 0; + + pfn =3D (lvl =3D=3D PAGETABLE_LEVELS + 1) ? PHYS_PFN(*(unsigned long *= )pte) + : pte_to_mfn(*pte); + if ( pfn >=3D boundary_pfn ) + return 0; + + new_pg =3D (void *)alloc_page(); + if ( !new_pg ) + return ENOMEM; + old_pg =3D pfn_to_virt(pfn); + memcpy(new_pg, old_pg, PAGE_SIZE); + if ( lvl =3D=3D PAGETABLE_LEVELS + 1 ) + *(pgentry_t **)pte =3D new_pg; + else + *pte =3D ((unsigned long)new_pg & PAGE_MASK) | ptdata[lvl].prot; + + tlb_flush(); + + free_page(old_pg); + + return 0; +} + +static int move_leaf(unsigned long va, unsigned int lvl, bool is_leaf, + pgentry_t *pte, void *par) +{ + unsigned long boundary_pfn =3D *(unsigned long *)par; + unsigned long pfn; + void *old_pg, *new_pg; + + if ( !is_leaf ) + return 0; + + /* No large page support, all pages must be valid. */ + if ( (*pte & _PAGE_PSE) || !(*pte & _PAGE_PRESENT) ) + return EINVAL; + + pfn =3D pte_to_mfn(*pte); + if ( pfn >=3D boundary_pfn ) + return 0; + + new_pg =3D (void *)alloc_page(); + if ( !new_pg ) + return ENOMEM; + old_pg =3D pfn_to_virt(pfn); + memcpy(new_pg, old_pg, PAGE_SIZE); + *pte =3D ((unsigned long)new_pg & PAGE_MASK) | ptdata[lvl].prot; + + invlpg(va); + + free_page(old_pg); + + return 0; +} + +int kexec_move_used_pages(unsigned long boundary, unsigned long kernel, + unsigned long kernel_size) +{ + int ret; + unsigned long boundary_pfn =3D PHYS_PFN(boundary); + + kexec_gdt =3D alloc_page(); + if ( !kexec_gdt ) + return ENOMEM; + memcpy((char *)kexec_gdt, &gdt, sizeof(gdt)); + gdt_ptr.base =3D kexec_gdt; + asm volatile("lgdt %0" : : "m" (gdt_ptr)); + + kexec_idt =3D alloc_page(); + if ( !kexec_idt ) + return ENOMEM; + memcpy((char *)kexec_idt, &idt, sizeof(idt)); + idt_ptr.base =3D kexec_idt; + asm volatile("lidt %0" : : "m" (idt_ptr)); + + /* Top level page table needs special handling. */ + ret =3D move_pt(0, PAGETABLE_LEVELS + 1, false, (pgentry_t *)(&pt_base= ), + &boundary_pfn); + if ( ret ) + return ret; + ret =3D walk_pt(0, ~0UL, move_pt, &boundary_pfn); + if ( ret ) + return ret; + + /* Move new kernel image pages. */ + ret =3D walk_pt(kernel, kernel + kernel_size - 1, move_leaf, &boundary= _pfn); + if ( ret ) + return ret; + + return 0; +} + +void kexec_move_used_pages_undo(void) +{ + if ( kexec_gdt ) + { + gdt_ptr.base =3D (unsigned long)&gdt; + asm volatile("lgdt %0" : : "m" (gdt_ptr)); + free_page((void *)kexec_gdt); + kexec_gdt =3D 0; + } + + if ( kexec_idt ) + { + idt_ptr.base =3D (unsigned long)&idt; + asm volatile("lidt %0" : : "m" (idt_ptr)); + free_page((void *)kexec_idt); + kexec_idt =3D 0; + } +} +#endif diff --git a/include/kexec.h b/include/kexec.h index 7b103dea..411fa013 100644 --- a/include/kexec.h +++ b/include/kexec.h @@ -49,4 +49,9 @@ void kexec_set_param_loc(const char *cmdline); int kexec_get_entry(const char *cmdline); void kexec_get_entry_undo(void); =20 +/* Move used pages away from new kernel area. */ +int kexec_move_used_pages(unsigned long boundary, unsigned long kernel, + unsigned long kernel_size); +void kexec_move_used_pages_undo(void); + #endif /* _KEXEC_H */ diff --git a/kexec.c b/kexec.c index e762fbeb..3b11a69c 100644 --- a/kexec.c +++ b/kexec.c @@ -183,11 +183,17 @@ int kexec(void *kernel, unsigned long kernel_size, co= nst char *cmdline) goto err; } =20 + ret =3D kexec_move_used_pages(kexec_last_addr, (unsigned long)kernel, + kernel_size); + if ( ret ) + goto err; + /* Error exit. */ ret =3D ENOSYS; =20 err: unreserve_memory_below(); + kexec_move_used_pages_undo(); kexec_get_entry_undo(); =20 return ret; --=20 2.43.0