[PATCH v2 02/12] powerpc/kexec_file: mark PPC64 specific code
Laurent Dufour
ldufour at linux.ibm.com
Fri Jul 10 17:52:58 AEST 2020
Le 02/07/2020 à 21:54, Hari Bathini a écrit :
> Some of the kexec_file_load code isn't PPC64 specific. Move PPC64
> specific code from kexec/file_load.c to kexec/file_load_64.c. Also,
> rename purgatory/trampoline.S to purgatory/trampoline_64.S in the
> same spirit.
FWIW and despite a minor comment below,
Reviewed-by: Laurent Dufour <ldufour at linux.ibm.com>
> Signed-off-by: Hari Bathini <hbathini at linux.ibm.com>
> ---
>
> Changes in v2:
> * No changes.
>
>
> arch/powerpc/include/asm/kexec.h | 11 +++
> arch/powerpc/kexec/Makefile | 2 -
> arch/powerpc/kexec/elf_64.c | 7 +-
> arch/powerpc/kexec/file_load.c | 37 ++--------
> arch/powerpc/kexec/file_load_64.c | 108 ++++++++++++++++++++++++++++++
> arch/powerpc/purgatory/Makefile | 4 +
> arch/powerpc/purgatory/trampoline.S | 117 --------------------------------
> arch/powerpc/purgatory/trampoline_64.S | 117 ++++++++++++++++++++++++++++++++
> 8 files changed, 248 insertions(+), 155 deletions(-)
> create mode 100644 arch/powerpc/kexec/file_load_64.c
> delete mode 100644 arch/powerpc/purgatory/trampoline.S
> create mode 100644 arch/powerpc/purgatory/trampoline_64.S
>
> diff --git a/arch/powerpc/include/asm/kexec.h b/arch/powerpc/include/asm/kexec.h
> index c684768..7008ea1 100644
> --- a/arch/powerpc/include/asm/kexec.h
> +++ b/arch/powerpc/include/asm/kexec.h
> @@ -114,8 +114,17 @@ int setup_purgatory(struct kimage *image, const void *slave_code,
> unsigned long fdt_load_addr);
> int setup_new_fdt(const struct kimage *image, void *fdt,
> unsigned long initrd_load_addr, unsigned long initrd_len,
> - const char *cmdline);
> + const char *cmdline, int *node);
> int delete_fdt_mem_rsv(void *fdt, unsigned long start, unsigned long size);
> +
> +#ifdef CONFIG_PPC64
> +int setup_purgatory_ppc64(struct kimage *image, const void *slave_code,
> + const void *fdt, unsigned long kernel_load_addr,
> + unsigned long fdt_load_addr);
> +int setup_new_fdt_ppc64(const struct kimage *image, void *fdt,
> + unsigned long initrd_load_addr,
> + unsigned long initrd_len, const char *cmdline);
> +#endif /* CONFIG_PPC64 */
> #endif /* CONFIG_KEXEC_FILE */
>
> #else /* !CONFIG_KEXEC_CORE */
> diff --git a/arch/powerpc/kexec/Makefile b/arch/powerpc/kexec/Makefile
> index 86380c6..67c3553 100644
> --- a/arch/powerpc/kexec/Makefile
> +++ b/arch/powerpc/kexec/Makefile
> @@ -7,7 +7,7 @@ obj-y += core.o crash.o core_$(BITS).o
>
> obj-$(CONFIG_PPC32) += relocate_32.o
>
> -obj-$(CONFIG_KEXEC_FILE) += file_load.o elf_$(BITS).o
> +obj-$(CONFIG_KEXEC_FILE) += file_load.o file_load_$(BITS).o elf_$(BITS).o
>
> ifdef CONFIG_HAVE_IMA_KEXEC
> ifdef CONFIG_IMA
> diff --git a/arch/powerpc/kexec/elf_64.c b/arch/powerpc/kexec/elf_64.c
> index 3072fd6..23ad04c 100644
> --- a/arch/powerpc/kexec/elf_64.c
> +++ b/arch/powerpc/kexec/elf_64.c
> @@ -88,7 +88,8 @@ static void *elf64_load(struct kimage *image, char *kernel_buf,
> goto out;
> }
>
> - ret = setup_new_fdt(image, fdt, initrd_load_addr, initrd_len, cmdline);
> + ret = setup_new_fdt_ppc64(image, fdt, initrd_load_addr,
> + initrd_len, cmdline);
> if (ret)
> goto out;
>
> @@ -107,8 +108,8 @@ static void *elf64_load(struct kimage *image, char *kernel_buf,
> pr_debug("Loaded device tree at 0x%lx\n", fdt_load_addr);
>
> slave_code = elf_info.buffer + elf_info.proghdrs[0].p_offset;
> - ret = setup_purgatory(image, slave_code, fdt, kernel_load_addr,
> - fdt_load_addr);
> + ret = setup_purgatory_ppc64(image, slave_code, fdt, kernel_load_addr,
> + fdt_load_addr);
> if (ret)
> pr_err("Error setting up the purgatory.\n");
>
> diff --git a/arch/powerpc/kexec/file_load.c b/arch/powerpc/kexec/file_load.c
> index 143c917..99a2c4d 100644
> --- a/arch/powerpc/kexec/file_load.c
> +++ b/arch/powerpc/kexec/file_load.c
> @@ -1,6 +1,6 @@
> // SPDX-License-Identifier: GPL-2.0-only
> /*
> - * ppc64 code to implement the kexec_file_load syscall
> + * powerpc code to implement the kexec_file_load syscall
> *
> * Copyright (C) 2004 Adam Litke (agl at us.ibm.com)
> * Copyright (C) 2004 IBM Corp.
> @@ -16,26 +16,10 @@
>
> #include <linux/slab.h>
> #include <linux/kexec.h>
> -#include <linux/of_fdt.h>
> #include <linux/libfdt.h>
> #include <asm/ima.h>
>
> -#define SLAVE_CODE_SIZE 256
> -
> -const struct kexec_file_ops * const kexec_file_loaders[] = {
> - &kexec_elf64_ops,
> - NULL
> -};
> -
> -int arch_kexec_kernel_image_probe(struct kimage *image, void *buf,
> - unsigned long buf_len)
> -{
> - /* We don't support crash kernels yet. */
> - if (image->type == KEXEC_TYPE_CRASH)
> - return -EOPNOTSUPP;
> -
> - return kexec_image_probe_default(image, buf, buf_len);
> -}
> +#define SLAVE_CODE_SIZE 256 /* First 0x100 bytes */
>
> /**
> * setup_purgatory - initialize the purgatory's global variables
> @@ -127,24 +111,17 @@ int delete_fdt_mem_rsv(void *fdt, unsigned long start, unsigned long size)
> * @initrd_len: Size of the next initrd, or 0 if there will be none.
> * @cmdline: Command line for the next kernel, or NULL if there will
> * be none.
> + * @chosen_node: Set this output parameter to chosen_node.
minor: ^ seems to be "node"
> *
> * Return: 0 on success, or negative errno on error.
> */
> int setup_new_fdt(const struct kimage *image, void *fdt,
> unsigned long initrd_load_addr, unsigned long initrd_len,
> - const char *cmdline)
> + const char *cmdline, int *node)
> {
> int ret, chosen_node;
> const void *prop;
>
> - /* Remove memory reservation for the current device tree. */
> - ret = delete_fdt_mem_rsv(fdt, __pa(initial_boot_params),
> - fdt_totalsize(initial_boot_params));
> - if (ret == 0)
> - pr_debug("Removed old device tree reservation.\n");
> - else if (ret != -ENOENT)
> - return ret;
> -
> chosen_node = fdt_path_offset(fdt, "/chosen");
> if (chosen_node == -FDT_ERR_NOTFOUND) {
> chosen_node = fdt_add_subnode(fdt, fdt_path_offset(fdt, "/"),
> @@ -157,6 +134,8 @@ int setup_new_fdt(const struct kimage *image, void *fdt,
> pr_err("Malformed device tree: error reading /chosen.\n");
> return -EINVAL;
> }
> + if (node)
> + *node = chosen_node;
>
> /* Did we boot using an initrd? */
> prop = fdt_getprop(fdt, chosen_node, "linux,initrd-start", NULL);
> @@ -242,10 +221,6 @@ int setup_new_fdt(const struct kimage *image, void *fdt,
> return ret;
> }
>
> - ret = fdt_setprop(fdt, chosen_node, "linux,booted-from-kexec", NULL, 0);
> - if (ret)
> - goto err;
> -
> return 0;
>
> err:
> diff --git a/arch/powerpc/kexec/file_load_64.c b/arch/powerpc/kexec/file_load_64.c
> new file mode 100644
> index 0000000..e6bff960
> --- /dev/null
> +++ b/arch/powerpc/kexec/file_load_64.c
> @@ -0,0 +1,108 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * ppc64 code to implement the kexec_file_load syscall
> + *
> + * Copyright (C) 2004 Adam Litke (agl at us.ibm.com)
> + * Copyright (C) 2004 IBM Corp.
> + * Copyright (C) 2004,2005 Milton D Miller II, IBM Corporation
> + * Copyright (C) 2005 R Sharada (sharada at in.ibm.com)
> + * Copyright (C) 2006 Mohan Kumar M (mohan at in.ibm.com)
> + * Copyright (C) 2020 IBM Corporation
> + *
> + * Based on kexec-tools' kexec-ppc64.c, kexec-elf-rel-ppc64.c, fs2dt.c.
> + * Heavily modified for the kernel by
> + * Hari Bathini <hbathini at linux.ibm.com>.
> + */
> +
> +#include <linux/kexec.h>
> +#include <linux/of_fdt.h>
> +#include <linux/libfdt.h>
> +
> +const struct kexec_file_ops * const kexec_file_loaders[] = {
> + &kexec_elf64_ops,
> + NULL
> +};
> +
> +/**
> + * setup_purgatory_ppc64 - initialize PPC64 specific purgatory's global
> + * variables and call setup_purgatory() to initialize
> + * common global variable.
> + * @image: kexec image.
> + * @slave_code: Slave code for the purgatory.
> + * @fdt: Flattened device tree for the next kernel.
> + * @kernel_load_addr: Address where the kernel is loaded.
> + * @fdt_load_addr: Address where the flattened device tree is loaded.
> + *
> + * Returns 0 on success, negative errno on error.
> + */
> +int setup_purgatory_ppc64(struct kimage *image, const void *slave_code,
> + const void *fdt, unsigned long kernel_load_addr,
> + unsigned long fdt_load_addr)
> +{
> + int ret;
> +
> + ret = setup_purgatory(image, slave_code, fdt, kernel_load_addr,
> + fdt_load_addr);
> + if (ret)
> + pr_err("Failed to setup purgatory symbols");
> + return ret;
> +}
> +
> +/**
> + * setup_new_fdt_ppc64 - Update the flattend device-tree of the kernel
> + * being loaded.
> + * @image: kexec image being loaded.
> + * @fdt: Flattened device tree for the next kernel.
> + * @initrd_load_addr: Address where the next initrd will be loaded.
> + * @initrd_len: Size of the next initrd, or 0 if there will be none.
> + * @cmdline: Command line for the next kernel, or NULL if there will
> + * be none.
> + *
> + * Returns 0 on success, negative errno on error.
> + */
> +int setup_new_fdt_ppc64(const struct kimage *image, void *fdt,
> + unsigned long initrd_load_addr,
> + unsigned long initrd_len, const char *cmdline)
> +{
> + int chosen_node, ret;
> +
> + /* Remove memory reservation for the current device tree. */
> + ret = delete_fdt_mem_rsv(fdt, __pa(initial_boot_params),
> + fdt_totalsize(initial_boot_params));
> + if (ret == 0)
> + pr_debug("Removed old device tree reservation.\n");
> + else if (ret != -ENOENT) {
> + pr_err("Failed to remove old device-tree reservation.\n");
> + return ret;
> + }
> +
> + ret = setup_new_fdt(image, fdt, initrd_load_addr, initrd_len,
> + cmdline, &chosen_node);
> + if (ret)
> + return ret;
> +
> + ret = fdt_setprop(fdt, chosen_node, "linux,booted-from-kexec", NULL, 0);
> + if (ret)
> + pr_err("Failed to update device-tree with linux,booted-from-kexec\n");
> +
> + return ret;
> +}
> +
> +/**
> + * arch_kexec_kernel_image_probe - Does additional handling needed to setup
> + * kexec segments.
> + * @image: kexec image being loaded.
> + * @buf: Buffer pointing to elf data.
> + * @buf_len: Length of the buffer.
> + *
> + * Returns 0 on success, negative errno on error.
> + */
> +int arch_kexec_kernel_image_probe(struct kimage *image, void *buf,
> + unsigned long buf_len)
> +{
> + /* We don't support crash kernels yet. */
> + if (image->type == KEXEC_TYPE_CRASH)
> + return -EOPNOTSUPP;
> +
> + return kexec_image_probe_default(image, buf, buf_len);
> +}
> diff --git a/arch/powerpc/purgatory/Makefile b/arch/powerpc/purgatory/Makefile
> index 7c6d8b1..348f5958 100644
> --- a/arch/powerpc/purgatory/Makefile
> +++ b/arch/powerpc/purgatory/Makefile
> @@ -2,11 +2,11 @@
>
> KASAN_SANITIZE := n
>
> -targets += trampoline.o purgatory.ro kexec-purgatory.c
> +targets += trampoline_$(BITS).o purgatory.ro kexec-purgatory.c
>
> LDFLAGS_purgatory.ro := -e purgatory_start -r --no-undefined
>
> -$(obj)/purgatory.ro: $(obj)/trampoline.o FORCE
> +$(obj)/purgatory.ro: $(obj)/trampoline_$(BITS).o FORCE
> $(call if_changed,ld)
>
> quiet_cmd_bin2c = BIN2C $@
> diff --git a/arch/powerpc/purgatory/trampoline.S b/arch/powerpc/purgatory/trampoline.S
> deleted file mode 100644
> index a5a83c3..0000000
> --- a/arch/powerpc/purgatory/trampoline.S
> +++ /dev/null
> @@ -1,117 +0,0 @@
> -/* SPDX-License-Identifier: GPL-2.0-only */
> -/*
> - * kexec trampoline
> - *
> - * Based on code taken from kexec-tools and kexec-lite.
> - *
> - * Copyright (C) 2004 - 2005, Milton D Miller II, IBM Corporation
> - * Copyright (C) 2006, Mohan Kumar M, IBM Corporation
> - * Copyright (C) 2013, Anton Blanchard, IBM Corporation
> - */
> -
> -#include <asm/asm-compat.h>
> -
> - .machine ppc64
> - .balign 256
> - .globl purgatory_start
> -purgatory_start:
> - b master
> -
> - /* ABI: possible run_at_load flag at 0x5c */
> - .org purgatory_start + 0x5c
> - .globl run_at_load
> -run_at_load:
> - .long 0
> - .size run_at_load, . - run_at_load
> -
> - /* ABI: slaves start at 60 with r3=phys */
> - .org purgatory_start + 0x60
> -slave:
> - b .
> - /* ABI: end of copied region */
> - .org purgatory_start + 0x100
> - .size purgatory_start, . - purgatory_start
> -
> -/*
> - * The above 0x100 bytes at purgatory_start are replaced with the
> - * code from the kernel (or next stage) by setup_purgatory().
> - */
> -
> -master:
> - or %r1,%r1,%r1 /* low priority to let other threads catchup */
> - isync
> - mr %r17,%r3 /* save cpu id to r17 */
> - mr %r15,%r4 /* save physical address in reg15 */
> -
> - or %r3,%r3,%r3 /* ok now to high priority, lets boot */
> - lis %r6,0x1
> - mtctr %r6 /* delay a bit for slaves to catch up */
> - bdnz . /* before we overwrite 0-100 again */
> -
> - bl 0f /* Work out where we're running */
> -0: mflr %r18
> -
> - /* load device-tree address */
> - ld %r3, (dt_offset - 0b)(%r18)
> - mr %r16,%r3 /* save dt address in reg16 */
> - li %r4,20
> - LWZX_BE %r6,%r3,%r4 /* fetch __be32 version number at byte 20 */
> - cmpwi %cr0,%r6,2 /* v2 or later? */
> - blt 1f
> - li %r4,28
> - STWX_BE %r17,%r3,%r4 /* Store my cpu as __be32 at byte 28 */
> -1:
> - /* load the kernel address */
> - ld %r4,(kernel - 0b)(%r18)
> -
> - /* load the run_at_load flag */
> - /* possibly patched by kexec */
> - ld %r6,(run_at_load - 0b)(%r18)
> - /* and patch it into the kernel */
> - stw %r6,(0x5c)(%r4)
> -
> - mr %r3,%r16 /* restore dt address */
> -
> - li %r5,0 /* r5 will be 0 for kernel */
> -
> - mfmsr %r11
> - andi. %r10,%r11,1 /* test MSR_LE */
> - bne .Little_endian
> -
> - mtctr %r4 /* prepare branch to */
> - bctr /* start kernel */
> -
> -.Little_endian:
> - mtsrr0 %r4 /* prepare branch to */
> -
> - clrrdi %r11,%r11,1 /* clear MSR_LE */
> - mtsrr1 %r11
> -
> - rfid /* update MSR and start kernel */
> -
> -
> - .balign 8
> - .globl kernel
> -kernel:
> - .8byte 0x0
> - .size kernel, . - kernel
> -
> - .balign 8
> - .globl dt_offset
> -dt_offset:
> - .8byte 0x0
> - .size dt_offset, . - dt_offset
> -
> -
> - .data
> - .balign 8
> -.globl purgatory_sha256_digest
> -purgatory_sha256_digest:
> - .skip 32
> - .size purgatory_sha256_digest, . - purgatory_sha256_digest
> -
> - .balign 8
> -.globl purgatory_sha_regions
> -purgatory_sha_regions:
> - .skip 8 * 2 * 16
> - .size purgatory_sha_regions, . - purgatory_sha_regions
> diff --git a/arch/powerpc/purgatory/trampoline_64.S b/arch/powerpc/purgatory/trampoline_64.S
> new file mode 100644
> index 0000000..a5a83c3
> --- /dev/null
> +++ b/arch/powerpc/purgatory/trampoline_64.S
> @@ -0,0 +1,117 @@
> +/* SPDX-License-Identifier: GPL-2.0-only */
> +/*
> + * kexec trampoline
> + *
> + * Based on code taken from kexec-tools and kexec-lite.
> + *
> + * Copyright (C) 2004 - 2005, Milton D Miller II, IBM Corporation
> + * Copyright (C) 2006, Mohan Kumar M, IBM Corporation
> + * Copyright (C) 2013, Anton Blanchard, IBM Corporation
> + */
> +
> +#include <asm/asm-compat.h>
> +
> + .machine ppc64
> + .balign 256
> + .globl purgatory_start
> +purgatory_start:
> + b master
> +
> + /* ABI: possible run_at_load flag at 0x5c */
> + .org purgatory_start + 0x5c
> + .globl run_at_load
> +run_at_load:
> + .long 0
> + .size run_at_load, . - run_at_load
> +
> + /* ABI: slaves start at 60 with r3=phys */
> + .org purgatory_start + 0x60
> +slave:
> + b .
> + /* ABI: end of copied region */
> + .org purgatory_start + 0x100
> + .size purgatory_start, . - purgatory_start
> +
> +/*
> + * The above 0x100 bytes at purgatory_start are replaced with the
> + * code from the kernel (or next stage) by setup_purgatory().
> + */
> +
> +master:
> + or %r1,%r1,%r1 /* low priority to let other threads catchup */
> + isync
> + mr %r17,%r3 /* save cpu id to r17 */
> + mr %r15,%r4 /* save physical address in reg15 */
> +
> + or %r3,%r3,%r3 /* ok now to high priority, lets boot */
> + lis %r6,0x1
> + mtctr %r6 /* delay a bit for slaves to catch up */
> + bdnz . /* before we overwrite 0-100 again */
> +
> + bl 0f /* Work out where we're running */
> +0: mflr %r18
> +
> + /* load device-tree address */
> + ld %r3, (dt_offset - 0b)(%r18)
> + mr %r16,%r3 /* save dt address in reg16 */
> + li %r4,20
> + LWZX_BE %r6,%r3,%r4 /* fetch __be32 version number at byte 20 */
> + cmpwi %cr0,%r6,2 /* v2 or later? */
> + blt 1f
> + li %r4,28
> + STWX_BE %r17,%r3,%r4 /* Store my cpu as __be32 at byte 28 */
> +1:
> + /* load the kernel address */
> + ld %r4,(kernel - 0b)(%r18)
> +
> + /* load the run_at_load flag */
> + /* possibly patched by kexec */
> + ld %r6,(run_at_load - 0b)(%r18)
> + /* and patch it into the kernel */
> + stw %r6,(0x5c)(%r4)
> +
> + mr %r3,%r16 /* restore dt address */
> +
> + li %r5,0 /* r5 will be 0 for kernel */
> +
> + mfmsr %r11
> + andi. %r10,%r11,1 /* test MSR_LE */
> + bne .Little_endian
> +
> + mtctr %r4 /* prepare branch to */
> + bctr /* start kernel */
> +
> +.Little_endian:
> + mtsrr0 %r4 /* prepare branch to */
> +
> + clrrdi %r11,%r11,1 /* clear MSR_LE */
> + mtsrr1 %r11
> +
> + rfid /* update MSR and start kernel */
> +
> +
> + .balign 8
> + .globl kernel
> +kernel:
> + .8byte 0x0
> + .size kernel, . - kernel
> +
> + .balign 8
> + .globl dt_offset
> +dt_offset:
> + .8byte 0x0
> + .size dt_offset, . - dt_offset
> +
> +
> + .data
> + .balign 8
> +.globl purgatory_sha256_digest
> +purgatory_sha256_digest:
> + .skip 32
> + .size purgatory_sha256_digest, . - purgatory_sha256_digest
> +
> + .balign 8
> +.globl purgatory_sha_regions
> +purgatory_sha_regions:
> + .skip 8 * 2 * 16
> + .size purgatory_sha_regions, . - purgatory_sha_regions
>
More information about the Linuxppc-dev
mailing list