Kexec on arm64

Arun Chandran achandran at mvista.com
Wed Aug 13 04:09:28 PDT 2014


Hi Geoff,

On Tue, Aug 12, 2014 at 11:12 AM, Arun Chandran <achandran at mvista.com> wrote:
> Hi Geoff, Mark,
>
>
> Sorry for top posting. I hope we have solved almost all the problems
> with kexec in uni-processor scenario except converting soft_restart()
> to assembly (I will give try to do this).
>

I have one more concern regarding flushing of D-cache area corresponding
to the kexec_list entrees.

Currently kexec_list_walk() is doing

1) flush_dcache_area of the kexec_list[0] till PAGE_SIZE

2) continue accessing entries in kexec_list[0] to PAGE_SIZE

3) switch to next kexec_list depending upon kexec_list[entry] & flag
==  IND_INDIRECTION

4) goto 1

Shouldn't that be doing flush_dcache_area() after completely using the list??

Like given below?
######################
diff --git a/arch/arm64/kernel/machine_kexec.c
b/arch/arm64/kernel/machine_kexec.c
index 5b15a00..ffb3b54 100644
--- a/arch/arm64/kernel/machine_kexec.c
+++ b/arch/arm64/kernel/machine_kexec.c
@@ -155,6 +155,7 @@ static void kexec_list_walk(void *ctx, unsigned
long kimage_head,
 {
        void *dest;
        unsigned long *entry;
+       void *last_accessed_dir = NULL;

        for (entry = &kimage_head, dest = NULL; ; entry++) {
                unsigned int flag = *entry & IND_FLAGS;
@@ -163,7 +164,10 @@ static void kexec_list_walk(void *ctx, unsigned
long kimage_head,
                switch (flag) {
                case IND_INDIRECTION:
                        entry = (unsigned long *)addr - 1;
-                       cb(ctx, flag, addr, NULL);
+                       if (last_accessed_dir != addr) {
+                               cb(ctx, flag, last_accessed_dir, NULL);
+                               last_accessed_dir = addr;
+                       }
                        break;
                case IND_DESTINATION:
                        dest = addr;
@@ -174,7 +178,7 @@ static void kexec_list_walk(void *ctx, unsigned
long kimage_head,
                        dest += PAGE_SIZE;
                        break;
                case IND_DONE:
-                       cb(ctx, flag , NULL, NULL);
+                       cb(ctx, flag , last_accessed_dir, NULL);
                        return;
                default:
                        pr_devel("%s:%d unknown flag %xh\n", __func__, __LINE__,
@@ -617,6 +621,9 @@ on_exit:
 static void kexec_list_flush_cb(void *ctx , unsigned int flag,
        void *addr, void *dest)
 {
+       if (addr == NULL)
+               return;
+
        switch (flag) {
        case IND_INDIRECTION:
                __flush_dcache_area(addr, PAGE_SIZE);
@@ -624,6 +631,9 @@ static void kexec_list_flush_cb(void *ctx ,
unsigned int flag,
        case IND_SOURCE:
                __flush_dcache_area(addr, PAGE_SIZE);
                break;
+       case IND_DONE:
+               __flush_dcache_area(addr, PAGE_SIZE);
+               break;
        default:
                break;
        }

########################

--Arun



More information about the linux-arm-kernel mailing list