diff options
author | Scott Wood <scottwood@freescale.com> | 2015-10-06 17:55:50 -0500 |
---|---|---|
committer | Simon Horman <horms@verge.net.au> | 2015-12-08 15:01:17 +0900 |
commit | 35cb8a0761a0d6bde49e9ce099bddd8ccf07d74a (patch) | |
tree | 7118781a94f28c169f86107196614285e2ef96c6 /kexec/arch/ppc64/fdt.c | |
parent | eff306e8914cfed05f4c29ea502cb46b1408f0ce (diff) |
ppc64: Add a flag to tell the kernel it's booting from kexec
It needs to know this because the SMP release mechanism for Freescale
book3e is different from when booting with normal hardware. In theory
we could simulate the normal spin table mechanism, but not (easily) at
the addresses U-Boot put in the device tree -- so there'd need to be
even more communication between the kernel and kexec to set that up.
Signed-off-by: Scott Wood <scottwood@freescale.com>
Acked-by: Michael Ellerman <mpe@ellerman.id.au>
Signed-off-by: Simon Horman <horms@verge.net.au>
Diffstat (limited to 'kexec/arch/ppc64/fdt.c')
-rw-r--r-- | kexec/arch/ppc64/fdt.c | 78 |
1 files changed, 78 insertions, 0 deletions
diff --git a/kexec/arch/ppc64/fdt.c b/kexec/arch/ppc64/fdt.c new file mode 100644 index 0000000..8bc6d2d --- /dev/null +++ b/kexec/arch/ppc64/fdt.c @@ -0,0 +1,78 @@ +/* + * ppc64 fdt fixups + * + * Copyright 2015 Freescale Semiconductor, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation (version 2 of the License). + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <arch/fdt.h> +#include <libfdt.h> +#include <stdio.h> +#include <stdlib.h> + +/* + * Let the kernel know it booted from kexec, as some things (e.g. + * secondary CPU release) may work differently. + */ +static int fixup_kexec_prop(void *fdt) +{ + int err, nodeoffset; + + nodeoffset = fdt_subnode_offset(fdt, 0, "chosen"); + if (nodeoffset < 0) + nodeoffset = fdt_add_subnode(fdt, 0, "chosen"); + if (nodeoffset < 0) { + printf("%s: add /chosen %s\n", __func__, + fdt_strerror(nodeoffset)); + return -1; + } + + err = fdt_setprop(fdt, nodeoffset, "linux,booted-from-kexec", + NULL, 0); + if (err < 0) { + printf("%s: couldn't write linux,booted-from-kexec: %s\n", + __func__, fdt_strerror(err)); + return -1; + } + + return 0; +} + + +/* + * For now, assume that the added content fits in the file. + * This should be the case when flattening from /proc/device-tree, + * and when passing in a dtb, dtc can be told to add padding. + */ +int fixup_dt(char **fdt, off_t *size) +{ + int ret; + + *size += 4096; + *fdt = realloc(*fdt, *size); + if (!*fdt) { + fprintf(stderr, "%s: out of memory\n", __func__); + return -1; + } + + ret = fdt_open_into(*fdt, *fdt, *size); + if (ret < 0) { + fprintf(stderr, "%s: fdt_open_into: %s\n", __func__, + fdt_strerror(ret)); + return -1; + } + + ret = fixup_kexec_prop(*fdt); + if (ret < 0) + return ret; + + return 0; +} |