From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.6 required=3.0 tests=DKIM_INVALID,DKIM_SIGNED, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH,MAILING_LIST_MULTI,SIGNED_OFF_BY, SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id B9BFBC43603 for ; Wed, 4 Dec 2019 16:00:43 +0000 (UTC) Received: from kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by mail.kernel.org (Postfix) with ESMTP id 64D872077B for ; Wed, 4 Dec 2019 16:00:43 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (2048-bit key) header.d=soleen.com header.i=@soleen.com header.b="IUIwOJtH" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 64D872077B Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=soleen.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=owner-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix) id BBD446B0B74; Wed, 4 Dec 2019 11:00:12 -0500 (EST) Received: by kanga.kvack.org (Postfix, from userid 40) id B477E6B0B75; Wed, 4 Dec 2019 11:00:12 -0500 (EST) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id A0D196B0B76; Wed, 4 Dec 2019 11:00:12 -0500 (EST) X-Delivered-To: linux-mm@kvack.org Received: from forelay.hostedemail.com (smtprelay0139.hostedemail.com [216.40.44.139]) by kanga.kvack.org (Postfix) with ESMTP id 8E4746B0B74 for ; Wed, 4 Dec 2019 11:00:12 -0500 (EST) Received: from smtpin15.hostedemail.com (10.5.19.251.rfc1918.com [10.5.19.251]) by forelay02.hostedemail.com (Postfix) with SMTP id 49BB75DD3 for ; Wed, 4 Dec 2019 16:00:12 +0000 (UTC) X-FDA: 76227920664.15.man58_1ec76299fbf3a X-HE-Tag: man58_1ec76299fbf3a X-Filterd-Recvd-Size: 13058 Received: from mail-qk1-f195.google.com (mail-qk1-f195.google.com [209.85.222.195]) by imf07.hostedemail.com (Postfix) with ESMTP for ; Wed, 4 Dec 2019 16:00:11 +0000 (UTC) Received: by mail-qk1-f195.google.com with SMTP id d202so392277qkb.1 for ; Wed, 04 Dec 2019 08:00:11 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=soleen.com; s=google; h=from:to:subject:date:message-id:in-reply-to:references:mime-version :content-transfer-encoding; bh=KGHNTS1i9Mb+VjEW80oB6ma/qr78DMUZ0Yk4HKHBgxE=; b=IUIwOJtHDnWwAE7bGS3k3U59S4A8UZHQsy+y3SpSkp7rqndC3ccoPP3LUH+R3ybge9 zGpcKlWBs5eknO8rWn7o4jTrRiG2Mkwy3hJ6nMUUkqkPAzLb75OAt7kHpGqrg7JjM2Um dKnz7/7XTo35PS3DRPY4KvGwpU4DgE0KrJ1q83CQo40URT4e/W5BuwCLeH8CfNq+6PSS yGBCbMg12Q/UNUDbiWQ6tEMLYR9eCGehkIjq8PTk3Fct9VCNgyBISEwTJ2eY1E42IOtr Ohtto3AMe973KJdFPUm5OeayD09xrtaYiS9DnAVa1yvamBBIzgsUOkk67AnV55idMlZE lPxA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=KGHNTS1i9Mb+VjEW80oB6ma/qr78DMUZ0Yk4HKHBgxE=; b=Q0vBA0PxMUa68Wk21HFf5RBiRRpY9TO8p2k1NOuleSTOC4mL8NJqVPgYW1atOYnDVk L5lAYtzlxlgll1kmQZvkt3wD26ryhe4SA6XPSMjiMnkXXktPWzMxCHxLKSYx67Z4gxRK YJxH8wRh2D3/9zyiYPnCp3R34MwUbHKtgOZVsVO4k0r6ywB+4iYMyRaaT+EaVoigEuZz d2at4p/VFeMu4jhVnLpqcnbCgV12EJ7rm9is6znwEBLJEHo5c6gnA8KxWxGdFp/ZVvg+ 3uUJk6wTWqER2h8BY/onReAHgGX1WnTN10f+OFqRc0zm8A7rVv66ZhYJS2HviYd42xgW A0SA== X-Gm-Message-State: APjAAAUWlJ6lUUR7qlIQ76HYzgJpvnZBuOHFUbJrju6S2EiCtenVZZSD maAQdS+p2OVJ/6q1TGoYtUK5ug== X-Google-Smtp-Source: APXvYqznNG6Kcze/EASto7milz4hvG1HUi65CXT+uVMcvIF73cewNTeZZEKAMJBRqrpDESE5tUCYAQ== X-Received: by 2002:a37:4d16:: with SMTP id a22mr3667063qkb.237.1575475210569; Wed, 04 Dec 2019 08:00:10 -0800 (PST) Received: from localhost.localdomain (c-73-69-118-222.hsd1.nh.comcast.net. [73.69.118.222]) by smtp.gmail.com with ESMTPSA id w21sm4177585qth.17.2019.12.04.08.00.09 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 04 Dec 2019 08:00:09 -0800 (PST) From: Pavel Tatashin To: pasha.tatashin@soleen.com, jmorris@namei.org, sashal@kernel.org, ebiederm@xmission.com, kexec@lists.infradead.org, linux-kernel@vger.kernel.org, corbet@lwn.net, catalin.marinas@arm.com, will@kernel.org, linux-arm-kernel@lists.infradead.org, marc.zyngier@arm.com, james.morse@arm.com, vladimir.murzin@arm.com, matthias.bgg@gmail.com, bhsharma@redhat.com, linux-mm@kvack.org, mark.rutland@arm.com, steve.capper@arm.com, rfontana@redhat.com, tglx@linutronix.de Subject: [PATCH v8 20/25] arm64: kexec: add expandable argument to relocation function Date: Wed, 4 Dec 2019 10:59:33 -0500 Message-Id: <20191204155938.2279686-21-pasha.tatashin@soleen.com> X-Mailer: git-send-email 2.24.0 In-Reply-To: <20191204155938.2279686-1-pasha.tatashin@soleen.com> References: <20191204155938.2279686-1-pasha.tatashin@soleen.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable 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: Currently, kexec relocation function (arm64_relocate_new_kernel) accepts the following arguments: head: start of array that contains relocation information. entry: entry point for new kernel or purgatory. dtb_mem: first and only argument to entry. The number of arguments cannot be easily expended, because this function is also called from HVC_SOFT_RESTART, which preserves only three arguments. And, also arm64_relocate_new_kernel is written in assembly but called without stack, thus no place to move extra arguments to free registers. Soon, we will need to pass more arguments: once we enable MMU we will need to pass information about page tables. Another benefit of allowing this function to accept more arguments, is th= at kernel can actually accept up to 4 arguments (x0-x3), however currently only one is used, but if in the future we will need for more (for example= , pass information about when previous kernel exited to have a precise measurement in time spent in purgatory), we won't be easilty do that if arm64_relocate_new_kernel can't accept more arguments. So, add a new struct: kern_reloc_arg, and place it in kexec safe page (i.= e memory that is not overwritten during relocation). Thus, make arm64_relocate_new_kernel to only take one argument, that contains all the needed information. Signed-off-by: Pavel Tatashin --- arch/arm64/include/asm/kexec.h | 18 ++++++++++++++++++ arch/arm64/kernel/asm-offsets.c | 9 +++++++++ arch/arm64/kernel/cpu-reset.S | 8 ++------ arch/arm64/kernel/cpu-reset.h | 8 +++----- arch/arm64/kernel/machine_kexec.c | 26 ++++++++++++++++++++++++-- arch/arm64/kernel/relocate_kernel.S | 19 ++++++++----------- 6 files changed, 64 insertions(+), 24 deletions(-) diff --git a/arch/arm64/include/asm/kexec.h b/arch/arm64/include/asm/kexe= c.h index 00dbcc71aeb2..189dce24f4cb 100644 --- a/arch/arm64/include/asm/kexec.h +++ b/arch/arm64/include/asm/kexec.h @@ -90,12 +90,30 @@ static inline void crash_prepare_suspend(void) {} static inline void crash_post_resume(void) {} #endif =20 +/* + * kern_reloc_arg is passed to kernel relocation function as an argument= . + * head kimage->head, allows to traverse through relocation segments. + * entry_addr kimage->start, where to jump from relocation function (new + * kernel, or purgatory entry address). + * kern_arg0 first argument to kernel is its dtb address. The other + * arguments are currently unused, and must be set to 0 + */ +struct kern_reloc_arg { + phys_addr_t head; + phys_addr_t entry_addr; + phys_addr_t kern_arg0; + phys_addr_t kern_arg1; + phys_addr_t kern_arg2; + phys_addr_t kern_arg3; +}; + #define ARCH_HAS_KIMAGE_ARCH =20 struct kimage_arch { void *dtb; phys_addr_t dtb_mem; phys_addr_t kern_reloc; + phys_addr_t kern_reloc_arg; }; =20 #ifdef CONFIG_KEXEC_FILE diff --git a/arch/arm64/kernel/asm-offsets.c b/arch/arm64/kernel/asm-offs= ets.c index a5bdce8af65b..448230684749 100644 --- a/arch/arm64/kernel/asm-offsets.c +++ b/arch/arm64/kernel/asm-offsets.c @@ -23,6 +23,7 @@ #include #include #include +#include =20 int main(void) { @@ -127,6 +128,14 @@ int main(void) #ifdef CONFIG_ARM_SDE_INTERFACE DEFINE(SDEI_EVENT_INTREGS, offsetof(struct sdei_registered_event, inte= rrupted_regs)); DEFINE(SDEI_EVENT_PRIORITY, offsetof(struct sdei_registered_event, pri= ority)); +#endif +#ifdef CONFIG_KEXEC_CORE + DEFINE(KEXEC_KRELOC_HEAD, offsetof(struct kern_reloc_arg, head)); + DEFINE(KEXEC_KRELOC_ENTRY_ADDR, offsetof(struct kern_reloc_arg, entry_= addr)); + DEFINE(KEXEC_KRELOC_KERN_ARG0, offsetof(struct kern_reloc_arg, kern_ar= g0)); + DEFINE(KEXEC_KRELOC_KERN_ARG1, offsetof(struct kern_reloc_arg, kern_ar= g1)); + DEFINE(KEXEC_KRELOC_KERN_ARG2, offsetof(struct kern_reloc_arg, kern_ar= g2)); + DEFINE(KEXEC_KRELOC_KERN_ARG3, offsetof(struct kern_reloc_arg, kern_ar= g3)); #endif return 0; } diff --git a/arch/arm64/kernel/cpu-reset.S b/arch/arm64/kernel/cpu-reset.= S index 6ea337d464c4..99a761bc5ee1 100644 --- a/arch/arm64/kernel/cpu-reset.S +++ b/arch/arm64/kernel/cpu-reset.S @@ -21,9 +21,7 @@ * * @el2_switch: Flag to indicate a switch to EL2 is needed. * @entry: Location to jump to for soft reset. - * arg0: First argument passed to @entry. (relocation list) - * arg1: Second argument passed to @entry.(physical kernel entry) - * arg2: Third argument passed to @entry. (physical dtb address) + * arg: Entry argument * * Put the CPU into the same state as it would be if it had been reset, = and * branch to what would be the reset vector. It must be executed with th= e @@ -43,9 +41,7 @@ ENTRY(__cpu_soft_restart) hvc #0 // no return =20 1: mov x18, x1 // entry - mov x0, x2 // arg0 - mov x1, x3 // arg1 - mov x2, x4 // arg2 + mov x0, x2 // arg br x18 ENDPROC(__cpu_soft_restart) =20 diff --git a/arch/arm64/kernel/cpu-reset.h b/arch/arm64/kernel/cpu-reset.= h index 3a54c4d987f3..7649eec64f82 100644 --- a/arch/arm64/kernel/cpu-reset.h +++ b/arch/arm64/kernel/cpu-reset.h @@ -11,12 +11,10 @@ #include =20 void __cpu_soft_restart(phys_addr_t el2_switch, phys_addr_t entry, - phys_addr_t arg0, phys_addr_t arg1, phys_addr_t arg2); + phys_addr_t arg); =20 static inline void __noreturn cpu_soft_restart(phys_addr_t entry, - phys_addr_t arg0, - phys_addr_t arg1, - phys_addr_t arg2) + phys_addr_t arg) { typeof(__cpu_soft_restart) *restart; =20 @@ -25,7 +23,7 @@ static inline void __noreturn cpu_soft_restart(phys_add= r_t entry, restart =3D (void *)__pa_symbol(__cpu_soft_restart); =20 cpu_install_idmap(); - restart(el2_switch, entry, arg0, arg1, arg2); + restart(el2_switch, entry, arg); unreachable(); } =20 diff --git a/arch/arm64/kernel/machine_kexec.c b/arch/arm64/kernel/machin= e_kexec.c index f94119b5cebc..5f1211f3aeef 100644 --- a/arch/arm64/kernel/machine_kexec.c +++ b/arch/arm64/kernel/machine_kexec.c @@ -43,6 +43,7 @@ static void _kexec_image_info(const char *func, int lin= e, pr_debug(" head: %lx\n", kimage->head); pr_debug(" nr_segments: %lu\n", kimage->nr_segments); pr_debug(" kern_reloc: %pa\n", &kimage->arch.kern_reloc); + pr_debug(" kern_reloc_arg: %pa\n", &kimage->arch.kern_reloc_arg); =20 for (i =3D 0; i < kimage->nr_segments; i++) { pr_debug(" segment[%lu]: %016lx - %016lx, 0x%lx bytes, %lu pages\= n", @@ -59,13 +60,35 @@ void machine_kexec_cleanup(struct kimage *kimage) /* Empty routine needed to avoid build errors. */ } =20 +/* Allocates pages for kexec page table */ +static void *kexec_page_alloc(void *arg) +{ + struct kimage *kimage =3D (struct kimage *)arg; + struct page *page =3D kimage_alloc_control_pages(kimage, 0); + + if (!page) + return NULL; + + memset(page_address(page), 0, PAGE_SIZE); + + return page_address(page); +} + int machine_kexec_post_load(struct kimage *kimage) { void *reloc_code =3D page_to_virt(kimage->control_code_page); + struct kern_reloc_arg *kern_reloc_arg =3D kexec_page_alloc(kimage); + + if (!kern_reloc_arg) + return -ENOMEM; =20 memcpy(reloc_code, arm64_relocate_new_kernel, arm64_relocate_new_kernel_size); kimage->arch.kern_reloc =3D __pa(reloc_code); + kimage->arch.kern_reloc_arg =3D __pa(kern_reloc_arg); + kern_reloc_arg->head =3D kimage->head; + kern_reloc_arg->entry_addr =3D kimage->start; + kern_reloc_arg->kern_arg0 =3D kimage->arch.dtb_mem; kexec_image_info(kimage); =20 return 0; @@ -201,8 +224,7 @@ void machine_kexec(struct kimage *kimage) * userspace (kexec-tools). * In kexec_file case, the kernel starts directly without purgatory. */ - cpu_soft_restart(kimage->arch.kern_reloc, kimage->head, kimage->start, - kimage->arch.dtb_mem); + cpu_soft_restart(kimage->arch.kern_reloc, kimage->arch.kern_reloc_arg); =20 BUG(); /* Should never get here. */ } diff --git a/arch/arm64/kernel/relocate_kernel.S b/arch/arm64/kernel/relo= cate_kernel.S index 41f9c95fabe8..22ccdcb106d3 100644 --- a/arch/arm64/kernel/relocate_kernel.S +++ b/arch/arm64/kernel/relocate_kernel.S @@ -8,6 +8,7 @@ =20 #include #include +#include #include #include #include @@ -25,12 +26,6 @@ * safe memory that has been set up to be preserved during the copy oper= ation. */ ENTRY(arm64_relocate_new_kernel) - /* Setup the list loop variables. */ - mov x18, x2 /* x18 =3D dtb address */ - mov x17, x1 /* x17 =3D kimage_start */ - mov x16, x0 /* x16 =3D kimage_head */ - mov x14, xzr /* x14 =3D entry ptr */ - mov x13, xzr /* x13 =3D copy dest */ /* Clear the sctlr_el2 flags. */ mrs x2, CurrentEL cmp x2, #CurrentEL_EL2 @@ -42,6 +37,7 @@ ENTRY(arm64_relocate_new_kernel) msr sctlr_el2, x2 isb 1: /* Check if the new image needs relocation. */ + ldr x16, [x0, #KEXEC_KRELOC_HEAD] /* x16 =3D kimage_head */ tbnz x16, IND_DONE_BIT, .Ldone raw_dcache_line_size x15, x1 /* x15 =3D dcache line size */ .Lloop: @@ -81,11 +77,12 @@ ENTRY(arm64_relocate_new_kernel) isb =20 /* Start new image. */ - mov x0, x18 - mov x1, xzr - mov x2, xzr - mov x3, xzr - br x17 + ldr x4, [x0, #KEXEC_KRELOC_ENTRY_ADDR] /* x4 =3D kimage_start */ + ldr x3, [x0, #KEXEC_KRELOC_KERN_ARG3] + ldr x2, [x0, #KEXEC_KRELOC_KERN_ARG2] + ldr x1, [x0, #KEXEC_KRELOC_KERN_ARG1] + ldr x0, [x0, #KEXEC_KRELOC_KERN_ARG0] /* x0 =3D dtb address */ + br x4 .ltorg END(arm64_relocate_new_kernel) =20 --=20 2.24.0