diff mbox series

[MINI-OS,11/12] kexec: add kexec callback functionality

Message ID 20250321092451.17309-12-jgross@suse.com (mailing list archive)
State New
Headers show
Series kexec: add kexec support to Mini-OS | expand

Commit Message

Jürgen Groß March 21, 2025, 9:24 a.m. UTC
Add a kexec_call() macro which will provide the capability to register
a function for being called when doing a kexec() call. The called
functions will be called with a boolean parameter "undo" indicating
whether a previous call needs to be undone due to a failure during
kexec().

The related loop to call all callbacks is added to kexec().

Signed-off-by: Juergen Gross <jgross@suse.com>
---
 arch/x86/minios-x86.lds.S |  8 ++++++++
 arch/x86/mm.c             |  3 ++-
 include/kexec.h           |  6 ++++++
 kexec.c                   | 13 +++++++++++++
 4 files changed, 29 insertions(+), 1 deletion(-)
diff mbox series

Patch

diff --git a/arch/x86/minios-x86.lds.S b/arch/x86/minios-x86.lds.S
index 83ec41ce..35356b34 100644
--- a/arch/x86/minios-x86.lds.S
+++ b/arch/x86/minios-x86.lds.S
@@ -58,6 +58,14 @@  SECTIONS
         }
         PROVIDE (__fini_array_end = .);
 
+#if defined(CONFIG_KEXEC)
+        PROVIDE (__kexec_array_start = .);
+        .kexec_array : {
+                *(.kexec_array)
+        }
+        PROVIDE (__kexec_array_end = .);
+#endif
+
         .ctors : {
                 __CTOR_LIST__ = .;
                 *(.ctors)
diff --git a/arch/x86/mm.c b/arch/x86/mm.c
index f4419d95..26ede6f4 100644
--- a/arch/x86/mm.c
+++ b/arch/x86/mm.c
@@ -529,7 +529,8 @@  void change_readonly(bool readonly)
 #endif
     }
 
-    printk("setting %p-%p readonly\n", &_text, &_erodata);
+    printk("setting %p-%p %s\n", &_text, &_erodata,
+           readonly ? "readonly" : "writable");
     walk_pt(start_address, ro.etext, change_readonly_func, &ro);
 
 #ifdef CONFIG_PARAVIRT
diff --git a/include/kexec.h b/include/kexec.h
index 411fa013..b89c3000 100644
--- a/include/kexec.h
+++ b/include/kexec.h
@@ -18,6 +18,12 @@  struct kexec_action {
 
 extern char _kexec_start[], _kexec_end[];
 extern struct kexec_action kexec_actions[KEXEC_MAX_ACTIONS];
+extern unsigned long __kexec_array_start[], __kexec_array_end[];
+
+typedef int(*kexeccall_t)(bool undo);
+#define kexec_call(func)                                                   \
+    static kexeccall_t __kexeccall_##func __attribute__((__used__))        \
+                       __attribute__((__section__(".kexec_array"))) = func
 
 extern unsigned long kexec_last_addr;
 
diff --git a/kexec.c b/kexec.c
index 2992f58f..2db876e8 100644
--- a/kexec.c
+++ b/kexec.c
@@ -168,6 +168,7 @@  static int analyze_kernel(void *kernel, unsigned long size)
 int kexec(void *kernel, unsigned long kernel_size, const char *cmdline)
 {
     int ret;
+    unsigned long *func;
 
     ret = analyze_kernel(kernel, kernel_size);
     if ( ret )
@@ -191,6 +192,18 @@  int kexec(void *kernel, unsigned long kernel_size, const char *cmdline)
     if ( ret )
         goto err;
 
+    for ( func = __kexec_array_start; func < __kexec_array_end; func++ )
+    {
+        ret = ((kexeccall_t)(*func))(false);
+        if ( ret )
+        {
+            for ( func--; func >= __kexec_array_start; func-- )
+                ((kexeccall_t)(*func))(true);
+
+            goto err;
+        }
+    }
+
     /* Error exit. */
     ret = ENOSYS;