From nobody Mon Feb 9 11:47:57 2026 Received: from mail-pf1-f201.google.com (mail-pf1-f201.google.com [209.85.210.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id A846A279795 for ; Thu, 1 May 2025 22:55:25 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1746140127; cv=none; b=WdgUpqmqjB+X72+vCMjTlXfIS6hfLjjG/Gvgxgc4N4NnW1yuFYJuHvmBqd5lLvsZKRVgHwzfK+tLKsq1HlIu5nUtq0cxyu0YYRJbgbfTSE5vhWnLBTUcvtZ+lL4oSFA9Y9wycSRfEBTNgW2HO5FVxbphA/SoJb4eUvMRWoAZ8uE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1746140127; c=relaxed/simple; bh=06t98HDICDCgMl4HzFJp4ELtosyt/1PD7AifsRCrmEs=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=uFLpuKrX+8BDARhWM8chM9VBZZ0GXXr7Ivx6yC5rMwfKqbKdXYU57EDJJmKsrcS3enG/R3uhjS1Qh/8Ka/P5EB+9sWFcdbtvvZNggh7fm6q8e2wklkU5I9nu5rEmWzAk/NFXFKAAWYxTC+sdj3pK979VBLI5Ad+o3imn82erOz4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--changyuanl.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=nLRZqkKr; arc=none smtp.client-ip=209.85.210.201 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--changyuanl.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="nLRZqkKr" Received: by mail-pf1-f201.google.com with SMTP id d2e1a72fcca58-736b431ee0dso1219912b3a.0 for ; Thu, 01 May 2025 15:55:25 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1746140125; x=1746744925; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=KCC7bKa/se6mYg+6T9wGzMiASCuQ0cecrMrt+P8VCow=; b=nLRZqkKrm4j3OdqZNm1q3d/B3vL/x39VsjVpZtvbP74KjTNmT+/PcDsk1yHmo7pSGl Z1vf7cppIEdCrcxVBDPT4WVD6BHeBEjizfSVRKp85j6XMR2W+7AT8/jPO+KfYbtkv4x4 f5065sZ8vaX2WfujA39gGImYXMgnHsM/K7FZZGEQI2nmE+p5MZxlnUWQERii4G5dA1Mh wmTesW19Z2g3Xy+dBNGno0c1YCHuHiF2jknicv287Y7ls08yZds8pvwFm/O01gXl7GTC 173oV+0Tlw9VCE0cRfidj8h2ZwDu7axuHnyU+hKihNQoLCrpIv712kKafkXvSoSbI5eZ pYHQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1746140125; x=1746744925; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=KCC7bKa/se6mYg+6T9wGzMiASCuQ0cecrMrt+P8VCow=; b=DYgv7ga4KwGsWr6Cqv+G52rdMlggW/fkpWPpkSzOOC9lI835J3+2yTHNRnNGpOdbDG S43AXkwMaWRmFm7s/aWsQs2WtVze5Wp8tNjchun2dIOR7F9jaARZW3MgzU1jRNVzk3Yi gNHzf4KtYT3h41PBEsSAThgFH145Dg5Q5mrriPJaPLX9K9rPolmy1aeSZlt5ZngfNYtR ZaDXgiLludG4VOtkN0iajN3JUA95a5BjVoIhXHmfSF7dg1Hxj9Huf8j4/TAW1Rav/5uE oTgQ45H3TqW5nfLFkO2qohzK+qqXakoby1n3UtfWe1akCmvYZVM5vlXdKxlG1OvQTu7+ waWw== X-Gm-Message-State: AOJu0YzHshtVBpAVq2lZFN/s1zkdtJKZI/snYgQz0BMrwqLDVWbZL+/3 +5tiG1q7DxhjZm5aDxIyEjzIFe7BpNPvgN11HXO9l+M5WX4/gpIXFLji1G6dDm6duB0c2Pajbvk KS76O+/nK/nBk3xrRDva0f+XuwU59SFqjwByvgy1z3dfDRUm/G4kqRQxSKrHqFqwa73a6v5hDyh shHQNFH4CY4i5bzCJONJ5yYPmWNPAq4Bd4cYuBMSkUPiQ5l8D+kZbIHxPZpemAFA== X-Google-Smtp-Source: AGHT+IG+w15ETdCoK+fHMVjjNvznubiYgRmkIOBeTduHj1HNG9YRODcurbY+TyPTJCH95DRqbicgO/a5HkcDFdV/ X-Received: from pgbd25.prod.google.com ([2002:a63:4f19:0:b0:b15:84fa:ff1f]) (user=changyuanl job=prod-delivery.src-stubby-dispatcher) by 2002:a05:6a20:d527:b0:1f5:82ae:69d1 with SMTP id adf61e73a8af0-20cded43612mr889605637.20.1746140124601; Thu, 01 May 2025 15:55:24 -0700 (PDT) Date: Thu, 1 May 2025 15:54:15 -0700 In-Reply-To: <20250501225425.635167-1-changyuanl@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20250501225425.635167-1-changyuanl@google.com> X-Mailer: git-send-email 2.49.0.906.g1f30a19c02-goog Message-ID: <20250501225425.635167-9-changyuanl@google.com> Subject: [PATCH v7 08/18] kexec: add KHO support to kexec file loads From: Changyuan Lyu To: linux-kernel@vger.kernel.org Cc: changyuanl@google.com, akpm@linux-foundation.org, anthony.yznaga@oracle.com, arnd@arndb.de, ashish.kalra@amd.com, benh@kernel.crashing.org, bp@alien8.de, catalin.marinas@arm.com, corbet@lwn.net, dave.hansen@linux.intel.com, devicetree@vger.kernel.org, dwmw2@infradead.org, ebiederm@xmission.com, graf@amazon.com, hpa@zytor.com, jgowans@amazon.com, kexec@lists.infradead.org, krzk@kernel.org, linux-arm-kernel@lists.infradead.org, linux-doc@vger.kernel.org, linux-mm@kvack.org, luto@kernel.org, mark.rutland@arm.com, mingo@redhat.com, pasha.tatashin@soleen.com, pbonzini@redhat.com, peterz@infradead.org, ptyadav@amazon.de, robh@kernel.org, rostedt@goodmis.org, rppt@kernel.org, saravanak@google.com, skinsburskii@linux.microsoft.com, tglx@linutronix.de, thomas.lendacky@amd.com, will@kernel.org, x86@kernel.org Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Alexander Graf Kexec has 2 modes: A user space driven mode and a kernel driven mode. For the kernel driven mode, kernel code determines the physical addresses of all target buffers that the payload gets copied into. With KHO, we can only safely copy payloads into the "scratch area". Teach the kexec file loader about it, so it only allocates for that area. In addition, enlighten it with support to ask the KHO subsystem for its respective payloads to copy into target memory. Also teach the KHO subsystem how to fill the images for file loads. Signed-off-by: Alexander Graf Co-developed-by: Mike Rapoport (Microsoft) Signed-off-by: Mike Rapoport (Microsoft) Co-developed-by: Changyuan Lyu Signed-off-by: Changyuan Lyu --- include/linux/kexec.h | 5 +++ kernel/kexec_file.c | 13 ++++++++ kernel/kexec_handover.c | 67 +++++++++++++++++++++++++++++++++++++++++ kernel/kexec_internal.h | 16 ++++++++++ 4 files changed, 101 insertions(+) diff --git a/include/linux/kexec.h b/include/linux/kexec.h index c8971861521a5..075255de81543 100644 --- a/include/linux/kexec.h +++ b/include/linux/kexec.h @@ -371,6 +371,11 @@ struct kimage { size_t ima_buffer_size; #endif =20 + struct { + struct kexec_segment *scratch; + phys_addr_t fdt; + } kho; + /* Core ELF header buffer */ void *elf_headers; unsigned long elf_headers_sz; diff --git a/kernel/kexec_file.c b/kernel/kexec_file.c index fba686487e3b5..77758c5331229 100644 --- a/kernel/kexec_file.c +++ b/kernel/kexec_file.c @@ -253,6 +253,11 @@ kimage_file_prepare_segments(struct kimage *image, int= kernel_fd, int initrd_fd, /* IMA needs to pass the measurement list to the next kernel. */ ima_add_kexec_buffer(image); =20 + /* If KHO is active, add its images to the list */ + ret =3D kho_fill_kimage(image); + if (ret) + goto out; + /* Call image load handler */ ldata =3D kexec_image_load_default(image); =20 @@ -648,6 +653,14 @@ int kexec_locate_mem_hole(struct kexec_buf *kbuf) if (kbuf->mem !=3D KEXEC_BUF_MEM_UNKNOWN) return 0; =20 + /* + * If KHO is active, only use KHO scratch memory. All other memory + * could potentially be handed over. + */ + ret =3D kho_locate_mem_hole(kbuf, locate_mem_hole_callback); + if (ret <=3D 0) + return ret; + if (!IS_ENABLED(CONFIG_ARCH_KEEP_MEMBLOCK)) ret =3D kexec_walk_resources(kbuf, locate_mem_hole_callback); else diff --git a/kernel/kexec_handover.c b/kernel/kexec_handover.c index 3bf74b4960f84..ef21db6c59d51 100644 --- a/kernel/kexec_handover.c +++ b/kernel/kexec_handover.c @@ -26,6 +26,7 @@ * internal APIs. */ #include "../mm/internal.h" +#include "kexec_internal.h" =20 #define KHO_FDT_COMPATIBLE "kho-v1" #define PROP_PRESERVED_MEMORY_MAP "preserved-memory-map" @@ -1192,3 +1193,69 @@ void __init kho_populate(phys_addr_t fdt_phys, u64 f= dt_len, if (err) pr_warn("disabling KHO revival: %d\n", err); } + +/* Helper functions for kexec_file_load */ + +int kho_fill_kimage(struct kimage *image) +{ + ssize_t scratch_size; + int err =3D 0; + struct kexec_buf scratch; + + if (!kho_enable) + return 0; + + image->kho.fdt =3D page_to_phys(kho_out.ser.fdt); + + scratch_size =3D sizeof(*kho_scratch) * kho_scratch_cnt; + scratch =3D (struct kexec_buf){ + .image =3D image, + .buffer =3D kho_scratch, + .bufsz =3D scratch_size, + .mem =3D KEXEC_BUF_MEM_UNKNOWN, + .memsz =3D scratch_size, + .buf_align =3D SZ_64K, /* Makes it easier to map */ + .buf_max =3D ULONG_MAX, + .top_down =3D true, + }; + err =3D kexec_add_buffer(&scratch); + if (err) + return err; + image->kho.scratch =3D &image->segment[image->nr_segments - 1]; + + return 0; +} + +static int kho_walk_scratch(struct kexec_buf *kbuf, + int (*func)(struct resource *, void *)) +{ + int ret =3D 0; + int i; + + for (i =3D 0; i < kho_scratch_cnt; i++) { + struct resource res =3D { + .start =3D kho_scratch[i].addr, + .end =3D kho_scratch[i].addr + kho_scratch[i].size - 1, + }; + + /* Try to fit the kimage into our KHO scratch region */ + ret =3D func(&res, kbuf); + if (ret) + break; + } + + return ret; +} + +int kho_locate_mem_hole(struct kexec_buf *kbuf, + int (*func)(struct resource *, void *)) +{ + int ret; + + if (!kho_enable || kbuf->image->type =3D=3D KEXEC_TYPE_CRASH) + return 1; + + ret =3D kho_walk_scratch(kbuf, func); + + return ret =3D=3D 1 ? 0 : -EADDRNOTAVAIL; +} diff --git a/kernel/kexec_internal.h b/kernel/kexec_internal.h index d35d9792402d1..30a733a55a67b 100644 --- a/kernel/kexec_internal.h +++ b/kernel/kexec_internal.h @@ -39,4 +39,20 @@ extern size_t kexec_purgatory_size; #else /* CONFIG_KEXEC_FILE */ static inline void kimage_file_post_load_cleanup(struct kimage *image) { } #endif /* CONFIG_KEXEC_FILE */ + +struct kexec_buf; + +#ifdef CONFIG_KEXEC_HANDOVER +int kho_locate_mem_hole(struct kexec_buf *kbuf, + int (*func)(struct resource *, void *)); +int kho_fill_kimage(struct kimage *image); +#else +static inline int kho_locate_mem_hole(struct kexec_buf *kbuf, + int (*func)(struct resource *, void *)) +{ + return 1; +} + +static inline int kho_fill_kimage(struct kimage *image) { return 0; } +#endif /* CONFIG_KEXEC_HANDOVER */ #endif /* LINUX_KEXEC_INTERNAL_H */ --=20 2.49.0.906.g1f30a19c02-goog