[PATCH RFC V2 2/2] arm64: Pass RAM boundary and enable-dcache flag to purgatory
Pratyush Anand
panand at redhat.com
Mon Jan 11 21:12:51 PST 2016
When "enable-dcache" is passed to the kexec() command line, kexec-tools
passes this information to purgatory, which in turn enables cache during
sha-256 verification.
RAM boundary which includes all the sections is needed for creating
identity page mapping and to enable d-cache for those areas. Therefore
these informations are passed to purgatory as well.
Signed-off-by: Pratyush Anand <panand at redhat.com>
---
kexec/arch/arm64/include/arch/options.h | 6 +++++-
kexec/arch/arm64/include/types.h | 16 ++++++++++++++++
kexec/arch/arm64/kexec-arm64.c | 24 +++++++++++++++++++++++-
purgatory/arch/arm64/entry.S | 15 +++++++++++++++
purgatory/arch/arm64/purgatory-arm64.c | 10 +++++++++-
5 files changed, 68 insertions(+), 3 deletions(-)
create mode 100644 kexec/arch/arm64/include/types.h
diff --git a/kexec/arch/arm64/include/arch/options.h b/kexec/arch/arm64/include/arch/options.h
index fbe17de595a9..3d84bb12ee37 100644
--- a/kexec/arch/arm64/include/arch/options.h
+++ b/kexec/arch/arm64/include/arch/options.h
@@ -8,7 +8,8 @@
#define OPT_PORT ((OPT_MAX)+4)
#define OPT_REUSE_CMDLINE ((OPT_MAX)+5)
#define OPT_PORT_LSR ((OPT_MAX)+6)
-#define OPT_ARCH_MAX ((OPT_MAX)+7)
+#define OPT_ENABLE_DCACHE ((OPT_MAX)+7)
+#define OPT_ARCH_MAX ((OPT_MAX)+8)
#define KEXEC_ARCH_OPTIONS \
KEXEC_OPTIONS \
@@ -20,6 +21,7 @@
{ "port", 1, NULL, OPT_PORT }, \
{ "port-lsr", 1, NULL, OPT_PORT_LSR }, \
{ "ramdisk", 1, NULL, OPT_INITRD }, \
+ { "enable-dcache", 0, NULL, OPT_ENABLE_DCACHE }, \
{ "reuse-cmdline", 0, NULL, OPT_REUSE_CMDLINE }, \
#define KEXEC_ARCH_OPT_STR KEXEC_OPT_STR /* Only accept long arch options. */
@@ -33,6 +35,7 @@ static const char arm64_opts_usage[] __attribute__ ((unused)) =
" --initrd=FILE Use FILE as the kernel initial ramdisk.\n"
" --port=ADDRESS Purgatory output to port ADDRESS.\n"
" --port-lsr=ADDR,VAL Purgatory output port line status address and TX Empty Bit Field.\n"
+" --enable-dcache Enable D-Cache in Purgatory for faster SHA verification.\n"
" --ramdisk=FILE Use FILE as the kernel initial ramdisk.\n"
" --reuse-cmdline Use command line arg of primary kernel.\n";
@@ -44,6 +47,7 @@ struct arm64_opts {
uint64_t port;
uint64_t port_lsr;
uint32_t port_lsr_val;
+ uint32_t enable_dcache;
};
extern struct arm64_opts arm64_opts;
diff --git a/kexec/arch/arm64/include/types.h b/kexec/arch/arm64/include/types.h
new file mode 100644
index 000000000000..08f833a6d585
--- /dev/null
+++ b/kexec/arch/arm64/include/types.h
@@ -0,0 +1,16 @@
+#ifndef _TYPES_H_
+#define _TYPES_H_
+
+#define min(x,y) ({ \
+ typeof(x) _x = (x); \
+ typeof(y) _y = (y); \
+ (void) (&_x == &_y); \
+ _x < _y ? _x : _y; })
+
+#define max(x,y) ({ \
+ typeof(x) _x = (x); \
+ typeof(y) _y = (y); \
+ (void) (&_x == &_y); \
+ _x > _y ? _x : _y; })
+
+#endif /* _TYPES_H_ */
diff --git a/kexec/arch/arm64/kexec-arm64.c b/kexec/arch/arm64/kexec-arm64.c
index be9170af06e8..9b78b481f4a0 100644
--- a/kexec/arch/arm64/kexec-arm64.c
+++ b/kexec/arch/arm64/kexec-arm64.c
@@ -29,6 +29,7 @@
#include "fs2dt.h"
#include "kexec-syscall.h"
#include "arch/options.h"
+#include "types.h"
/* Global varables the core kexec routines expect. */
@@ -103,6 +104,9 @@ int arch_process_options(int argc, char **argv)
arm64_opts.port_lsr_val = strtoul(strtok(NULL, ","),
NULL, 0);
break;
+ case OPT_ENABLE_DCACHE:
+ arm64_opts.enable_dcache = 1;
+ break;
case OPT_PAGE_OFFSET:
arm64_opts.page_offset = strtoull(optarg, NULL, 0);
break;
@@ -591,12 +595,15 @@ static uint64_t read_sink(const char *command_line)
int arm64_load_other_segments(struct kexec_info *info,
uint64_t kernel_entry, char *option)
{
- int result;
+ int result, i;
uint64_t dtb_base;
+ unsigned long arm64_ram_start = -1;
+ unsigned long arm64_ram_end = 0;
unsigned long hole_min, hole_max;
uint64_t purgatory_sink;
uint64_t purgatory_sink_lsr;
uint32_t purgatory_sink_lsr_val;
+ uint32_t purgatory_enable_dcache;
struct mem_ehdr ehdr;
char *initrd_buf = NULL;
struct dtb dtb_1 = {.name = "dtb_1"};
@@ -621,6 +628,7 @@ int arm64_load_other_segments(struct kexec_info *info,
purgatory_sink_lsr = arm64_opts.port_lsr;
purgatory_sink_lsr_val = arm64_opts.port_lsr_val;
+ purgatory_enable_dcache = arm64_opts.enable_dcache;
if (arm64_opts.dtb) {
dtb_2.buf = slurp_file(arm64_opts.dtb, &dtb_2.size);
@@ -724,11 +732,25 @@ int arm64_load_other_segments(struct kexec_info *info,
elf_rel_set_symbol(&info->rhdr, "arm64_sink_lsr_val",
&purgatory_sink_lsr_val, sizeof(purgatory_sink_lsr_val));
+ elf_rel_set_symbol(&info->rhdr, "arm64_enable_dcache",
+ &purgatory_enable_dcache, sizeof(purgatory_enable_dcache));
+
elf_rel_set_symbol(&info->rhdr, "arm64_kernel_entry", &kernel_entry,
sizeof(kernel_entry));
elf_rel_set_symbol(&info->rhdr, "arm64_dtb_addr", &dtb_base,
sizeof(dtb_base));
+ for (i = 0; i < info->nr_segments; i++) {
+ arm64_ram_start = min(arm64_ram_start,
+ (unsigned long)info->segment[i].mem);
+ arm64_ram_end = max(arm64_ram_end,
+ ((unsigned long)info->segment[i].mem +
+ info->segment[i].memsz));
+ }
+ elf_rel_set_symbol(&info->rhdr, "arm64_ram_start",
+ &arm64_ram_start, sizeof(arm64_ram_start));
+ elf_rel_set_symbol(&info->rhdr, "arm64_ram_end",
+ &arm64_ram_end, sizeof(arm64_ram_end));
return 0;
}
diff --git a/purgatory/arch/arm64/entry.S b/purgatory/arch/arm64/entry.S
index be184e9a7469..d5563459d078 100644
--- a/purgatory/arch/arm64/entry.S
+++ b/purgatory/arch/arm64/entry.S
@@ -63,7 +63,22 @@ arm64_kexec_lite:
.quad 0
size arm64_kexec_lite
+.globl arm64_ram_start
+arm64_ram_start:
+ .quad 0
+size arm64_ram_start
+
+.globl arm64_ram_end
+arm64_ram_end:
+ .quad 0
+size arm64_ram_end
+
.globl arm64_sink_lsr_val
arm64_sink_lsr_val:
.long 0
size arm64_sink_lsr_val
+
+.globl arm64_enable_dcache
+arm64_enable_dcache:
+ .long 0
+size arm64_enable_dcache
diff --git a/purgatory/arch/arm64/purgatory-arm64.c b/purgatory/arch/arm64/purgatory-arm64.c
index bca802e0504d..70c01aee46e0 100644
--- a/purgatory/arch/arm64/purgatory-arm64.c
+++ b/purgatory/arch/arm64/purgatory-arm64.c
@@ -4,14 +4,18 @@
#include <stdint.h>
#include <purgatory.h>
+#include "cache.h"
/* Symbols set by kexec. */
extern uint32_t *arm64_sink;
extern uint32_t *arm64_sink_lsr;
extern uint32_t arm64_sink_lsr_val;
+extern uint32_t arm64_enable_dcache;
extern void (*arm64_kernel_entry)(uint64_t, uint64_t, uint64_t, uint64_t);
extern uint64_t arm64_dtb_addr;
+extern uint64_t arm64_ram_start;
+extern uint64_t arm64_ram_end;
static void wait_for_xmit_complete(void)
{
@@ -44,6 +48,8 @@ void putchar(int ch)
void post_verification_setup_arch(void)
{
+ if (arm64_enable_dcache)
+ disable_dcache(arm64_ram_start, arm64_ram_end);
arm64_kernel_entry(arm64_dtb_addr, 0, 0, 0);
}
@@ -51,5 +57,7 @@ void setup_arch(void)
{
printf("purgatory: entry=%lx\n", (unsigned long)arm64_kernel_entry);
printf("purgatory: dtb=%lx\n", arm64_dtb_addr);
-}
+ if (arm64_enable_dcache)
+ enable_dcache(arm64_ram_start, arm64_ram_end, (uint64_t)arm64_sink);
+}
--
2.5.0
More information about the kexec
mailing list