From patchwork Mon Mar 10 12:03:13 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrey Ryabinin X-Patchwork-Id: 14009705 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by smtp.lore.kernel.org (Postfix) with ESMTP id 5D8CAC28B2E for ; Mon, 10 Mar 2025 12:04:12 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id 4ACA5280005; Mon, 10 Mar 2025 08:04:08 -0400 (EDT) Received: by kanga.kvack.org (Postfix, from userid 40) id 4111E280001; Mon, 10 Mar 2025 08:04:08 -0400 (EDT) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 239F7280005; Mon, 10 Mar 2025 08:04:08 -0400 (EDT) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0012.hostedemail.com [216.40.44.12]) by kanga.kvack.org (Postfix) with ESMTP id 03716280001 for ; Mon, 10 Mar 2025 08:04:07 -0400 (EDT) Received: from smtpin29.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay02.hostedemail.com (Postfix) with ESMTP id B95B3120EBE for ; Mon, 10 Mar 2025 12:04:09 +0000 (UTC) X-FDA: 83205508218.29.58FADFE Received: from forwardcorp1a.mail.yandex.net (forwardcorp1a.mail.yandex.net [178.154.239.72]) by imf23.hostedemail.com (Postfix) with ESMTP id C158814001A for ; Mon, 10 Mar 2025 12:04:07 +0000 (UTC) Authentication-Results: imf23.hostedemail.com; dkim=pass header.d=yandex-team.com header.s=default header.b=N3tQSyH7; spf=pass (imf23.hostedemail.com: domain of arbn@yandex-team.com designates 178.154.239.72 as permitted sender) smtp.mailfrom=arbn@yandex-team.com; dmarc=pass (policy=none) header.from=yandex-team.com ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1741608248; h=from:from:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:dkim-signature; bh=QkhEET4Wo+gouJiK8Lgb4vMFbcgAXJpnZW6CjWUXYUI=; b=vcbW7eKvswIUUBu7E9xBujEXYy9R90Td/p1dLG01gfEyXXYpEp2bxlqoRjBShoUrBQnSu1 MsGjG5lTp+qKlWhPTzPBdFpGsrRY2IDKqOtfjWDUyeT1+fZgHQ5gsCyT34XxCGJ8t2d0og 7aBaGCMVDteokfS8/Re/Zl8GH0/1XJM= ARC-Authentication-Results: i=1; imf23.hostedemail.com; dkim=pass header.d=yandex-team.com header.s=default header.b=N3tQSyH7; spf=pass (imf23.hostedemail.com: domain of arbn@yandex-team.com designates 178.154.239.72 as permitted sender) smtp.mailfrom=arbn@yandex-team.com; dmarc=pass (policy=none) header.from=yandex-team.com ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1741608248; a=rsa-sha256; cv=none; b=r8gSgi5LPaNam4nlUsyQXFyx7ot4iULawOyftNqgTicM52luIJlXPuGPoy+ZLR1oEZECgi vDamdBNVns1qS5v+RwZ7FOF+baoekXJYxPTGjGOFC3qkR3OiZnOeyp3qkLj2254rsUx1oD cKqenwz31EeZ51GBvVJcdzR/yNXIVuo= Received: from mail-nwsmtp-smtp-corp-main-83.vla.yp-c.yandex.net (mail-nwsmtp-smtp-corp-main-83.vla.yp-c.yandex.net [IPv6:2a02:6b8:c1f:600c:0:640:a431:0]) by forwardcorp1a.mail.yandex.net (Yandex) with ESMTPS id 3D4D160DE9; Mon, 10 Mar 2025 15:04:06 +0300 (MSK) Received: from dellarbn.yandex.net (unknown [10.214.35.248]) by mail-nwsmtp-smtp-corp-main-83.vla.yp-c.yandex.net (smtpcorp/Yandex) with ESMTPSA id s3o0lL2FT0U0-U5ZTnMcq; Mon, 10 Mar 2025 15:04:05 +0300 X-Yandex-Fwd: 1 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=yandex-team.com; s=default; t=1741608245; bh=QkhEET4Wo+gouJiK8Lgb4vMFbcgAXJpnZW6CjWUXYUI=; h=Message-ID:Date:In-Reply-To:Cc:Subject:References:To:From; b=N3tQSyH7q5Aw8vLpj6oIzXJUFol2N5amtQM0FyQ56H5V1ZTHW1L15Ttrhb4B+gc9s kwO45GOraHszy2v9J2VM/BFPgJC3K8JF8XkbIkUICHgn30PaHURZx5W6AKTRCMaz9h /YGOyUFNzrS71N7G5BQA84g6wuvpXWXemUAU3A/g= From: Andrey Ryabinin To: linux-kernel@vger.kernel.org Cc: Alexander Graf , James Gowans , Mike Rapoport , Andrew Morton , linux-mm@kvack.org, Thomas Gleixner , Ingo Molnar , Borislav Petkov , Dave Hansen , x86@kernel.org, "H . Peter Anvin" , Eric Biederman , kexec@lists.infradead.org, Pratyush Yadav , Jason Gunthorpe , Pasha Tatashin , David Rientjes , Andrey Ryabinin Subject: [PATCH v2 2/7] kstate, kexec, x86: transfer kstate data across kexec Date: Mon, 10 Mar 2025 13:03:13 +0100 Message-ID: <20250310120318.2124-3-arbn@yandex-team.com> X-Mailer: git-send-email 2.45.3 In-Reply-To: <20250310120318.2124-1-arbn@yandex-team.com> References: <20250310120318.2124-1-arbn@yandex-team.com> MIME-Version: 1.0 X-Rspamd-Server: rspam07 X-Rspamd-Queue-Id: C158814001A X-Stat-Signature: i3pzkpgek6brytgs4ayfmxa9dfaan163 X-Rspam-User: X-HE-Tag: 1741608247-952481 X-HE-Meta: U2FsdGVkX19EaDlqGeupPS70Hrbg/me6SW6lPEfnBOB95fc8YA2pwTUChgNObzVkCgTRlTrcFjDZ4nD97bfHeGBLCkJebQwVI1OBvNzrfBvzvFbAxPCXAqDbYnaQ8uo+EvMs5dKvtZd44VxETdJSAhEpLrhSsBBFNstJ3T1+HQOqsjwlEu1uidMRbGdq+FcjVDLtvCQW3/pys+lVjgWgu4iobzR2kz29pOx7vOPvE9aWEzilMDuyS+2eNVBzU6G3wn+FAb0pK+hoOFOlk2u6Yhsae/PPLeGbf10FgLArcoREC4lQ6nckGZEz41+tKGkIZ+f8a+DEZVwIdOBnOG3UkQVExN8AKXh2gP7ZA+miSSeeZAMcGKSQ9TasPX3kMMcDoIlcEvzf+RRLa5mDcYDWJSLWELDMz37BOffNjd1dGy4W/P0nTuZwwQLrgJSYsU9oheMNTmaWDnQtAfCuLzMcwr5Ty+oeNi3H6Rl8/ydaIvSzYLKgL7zcwHga1autzub6tBkReIXajK14UUEeFp59I4rv5x5ZyX7F1qi52V/nziZ2HB26X4emTcotG1xoNZ60DmibfSoRng7p5Ap6zvK5qxm2eRaDaNcUrMR9XSYYdbCb2djX7wyEyH0xWd+mLhoiJh3hDjjb753TWGzKkWID9njV8uVxT6vdNx60s/E1KE5apDqyW32fQXOoONqExmR6pFn/gsHA/FHdx8INKEYsgz55jEn/KMGf2mF8drGmVyTQdytk4aYA//TyfdMvfspmlUhq8YsycU2e0qEc6kIBo0AOk+rA6OwMlJAXgG+299EDZ/GE2uzNJXWPAM3syxinB0uJ+yDwEXiHEhR54JqhW7AGe9IzPvnmHd3xPLNUysUSnZCWF5+wbHj1C0a46Cn0pDRAnQLfWBMpcjTymiTEfm1lQKPf2GCRzofbghmgotREUxPETO9BxIYP/uYEYM0ASy26JRPKli9RoGBQtq2 g8837DXR 4Z4UDoO+uSsgtktNkg8A/Xs2UMCCRbokefQGF0yTMHpqu8kuGgIaTQgosMKDseW0Fld/u0YV042Q/6NF3Mjf91HZU8Zi7Hl8nOhWNrnFagf8tzdPficaXu56GZSsZ+15FFXkR98XUxrER759iqVgY4fZBTk7VBVcPhyQ7k30lqeezVUfZ4bnPkvVgTf4MuuVvZurmui/fPtYAHs6gIkAddk3jcswdAyMxVwnxw95WiAkd9bq4kFSGjTS+chXfA63AL2vbrctzTpituPnE3kb2TPak3KS3c3qVZFK7ATP9luWisHsgqZ1LNwa5RwtuIPsd+pc1wACEkn/g9DRDokBbUP65kkKx+AZXbM0K X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: List-Subscribe: List-Unsubscribe: Add kstate data to kexec segments so it got copied to the new kernel. Use cmdline to inform next kernel about kstate data location and size. Signed-off-by: Andrey Ryabinin --- I've used cmdline as it's the simplest way to transfer address to the new kernel. Perhaps passing it via dtb would be more elegant solution, but I don't have strong opinion here. --- arch/x86/Kconfig | 1 + arch/x86/kernel/kexec-bzimage64.c | 4 +++ arch/x86/kernel/setup.c | 2 ++ include/linux/kexec.h | 2 ++ include/linux/kstate.h | 5 ++++ kernel/kexec_file.c | 5 ++++ kernel/kstate.c | 49 ++++++++++++++++++++++++++++++- 7 files changed, 67 insertions(+), 1 deletion(-) diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 0e27ebd7e36a..7358d9e15957 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -90,6 +90,7 @@ config X86 select ARCH_HAS_GCOV_PROFILE_ALL select ARCH_HAS_KCOV if X86_64 select ARCH_HAS_KERNEL_FPU_SUPPORT + select ARCH_HAS_KSTATE if X86_64 select ARCH_HAS_MEM_ENCRYPT select ARCH_HAS_MEMBARRIER_SYNC_CORE select ARCH_HAS_NMI_SAFE_THIS_CPU_OPS diff --git a/arch/x86/kernel/kexec-bzimage64.c b/arch/x86/kernel/kexec-bzimage64.c index 68530fad05f7..d3c98c8bda29 100644 --- a/arch/x86/kernel/kexec-bzimage64.c +++ b/arch/x86/kernel/kexec-bzimage64.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -77,6 +78,9 @@ static int setup_cmdline(struct kimage *image, struct boot_params *params, len = sprintf(cmdline_ptr, "elfcorehdr=0x%lx ", image->elf_load_addr); } + if (IS_ENABLED(CONFIG_KSTATE)) + len = sprintf(cmdline_ptr, "kstate_stream=0x0%lx@%ld ", + image->kstate_stream_addr, image->kstate_size); memcpy(cmdline_ptr + len, cmdline, cmdline_len); cmdline_len += len; diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index cebee310e200..b32c141ffcdd 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -992,6 +993,7 @@ void __init setup_arch(char **cmdline_p) memblock_set_current_limit(ISA_END_ADDRESS); e820__memblock_setup(); + kstate_init(); /* * Needs to run after memblock setup because it needs the physical diff --git a/include/linux/kexec.h b/include/linux/kexec.h index f0e9f8eda7a3..bd82f04888a1 100644 --- a/include/linux/kexec.h +++ b/include/linux/kexec.h @@ -299,6 +299,8 @@ struct kimage { unsigned long start; struct page *control_code_page; struct page *swap_page; + unsigned long kstate_stream_addr; + size_t kstate_size; void *vmcoreinfo_data_copy; /* locates in the crash memory */ unsigned long nr_segments; diff --git a/include/linux/kstate.h b/include/linux/kstate.h index 4fc01e535bc0..ae583d090111 100644 --- a/include/linux/kstate.h +++ b/include/linux/kstate.h @@ -126,6 +126,8 @@ static inline unsigned long kstate_get_ulong(struct kstate_stream *stream) #ifdef CONFIG_KSTATE +void kstate_init(void); + int kstate_save_state(void); void free_kstate_stream(void); @@ -137,14 +139,17 @@ int save_kstate(struct kstate_stream *stream, int id, void *obj); void restore_kstate(struct kstate_stream *stream, int id, const struct kstate_description *kstate, void *obj); +int kstate_load_migrate_buf(struct kimage *image); #else +static inline void kstate_init(void) { } #define kstate_register(state, obj) static inline int kstate_save_state(void) { return 0; } static inline void free_kstate_stream(void) { } +static inline int kstate_load_migrate_buf(struct kimage *image) { return 0; } #endif diff --git a/kernel/kexec_file.c b/kernel/kexec_file.c index 3eedb8c226ad..a024ff379133 100644 --- a/kernel/kexec_file.c +++ b/kernel/kexec_file.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -253,6 +254,10 @@ 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); + ret = kstate_load_migrate_buf(image); + if (ret) + goto out; + /* Call image load handler */ ldata = kexec_image_load_default(image); diff --git a/kernel/kstate.c b/kernel/kstate.c index a73a9a42e55b..d35996287b76 100644 --- a/kernel/kstate.c +++ b/kernel/kstate.c @@ -2,6 +2,7 @@ #include #include #include +#include #include #include #include @@ -182,6 +183,31 @@ int kstate_save_state(void) return 0; } +int kstate_load_migrate_buf(struct kimage *image) +{ + int ret; + struct kexec_buf kbuf = { .image = image, .buf_min = 0, + .buf_max = ULONG_MAX, .top_down = true }; + + kbuf.bufsz = kstate_stream.size; + kbuf.buffer = kstate_stream.start; + + kbuf.memsz = kstate_stream.size; + + kbuf.buf_align = PAGE_SIZE; + kbuf.mem = KEXEC_BUF_MEM_UNKNOWN; + ret = kexec_add_buffer(&kbuf); + if (ret) + return ret; + image->kstate_stream_addr = kbuf.mem; + image->kstate_size = kstate_stream.size; + + pr_info("kstate: Loaded mig_stream at 0x%lx bufsz=0x%lx memsz=0x%lx\n", + kbuf.mem, kbuf.bufsz, kbuf.memsz); + + return ret; +} + void restore_kstate(struct kstate_stream *stream, int id, const struct kstate_description *kstate, void *obj) { @@ -258,6 +284,9 @@ static void restore_migrate_state(unsigned long kstate_data, } } +static unsigned long kstate_stream_addr = -1; +static unsigned long kstate_size; + static void __kstate_register(struct kstate_description *state, void *obj, struct state_entry *se) { @@ -265,7 +294,7 @@ static void __kstate_register(struct kstate_description *state, void *obj, se->id = atomic_inc_return(&state->instance_id); se->obj = obj; list_add(&se->list, &states); - restore_migrate_state(0 /*migrate_stream_addr*/, se); + restore_migrate_state(kstate_stream_addr, se); } int kstate_register(struct kstate_description *state, void *obj) @@ -280,3 +309,21 @@ int kstate_register(struct kstate_description *state, void *obj) return 0; } +static int __init setup_kstate(char *arg) +{ + char *end; + + if (!arg) + return -EINVAL; + kstate_stream_addr = memparse(arg, &end); + if (*end == '@') + kstate_size = memparse(end + 1, &end); + + return end > arg ? 0 : -EINVAL; +} +early_param("kstate_stream", setup_kstate); + +void __init kstate_init(void) +{ + memblock_reserve(kstate_stream_addr, kstate_size); +}