lkml.org 
[lkml]   [2021]   [Dec]   [7]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[RFC v2 4/6] crash hp: generic crash hotplug support infrastructure
    Date
    This patch introduces a generic crash hot plug/unplug infrastructure
    for CPU and memory changes. Upon CPU and memory changes, a generic
    crash_hotplug_handler() obtains the appropriate lock, does some
    important house keeping and then dispatches the hot plug/unplug event
    to the architecture specific arch_crash_hotplug_handler(), and when
    that handler returns, the lock is released.

    This patch modifies crash_core.c to implement a subsys_initcall()
    function that installs handlers for hot plug/unplug events. If CPU
    hotplug is enabled, then cpuhp_setup_state() is invoked to register a
    handler for CPU changes. Similarly, if memory hotplug is enabled, then
    register_memory_notifier() is invoked to install a handler for memory
    changes. These handlers in turn invoke the common generic handler
    crash_hotplug_handler().

    On the CPU side, cpuhp_setup_state_nocalls() is invoked with parameter
    CPUHP_AP_ONLINE_DYN. While this works, when a CPU is being unplugged,
    the CPU still shows up in foreach_present_cpu() during the regeneration
    of the new CPU list, thus the need to explicitly check and exclude the
    soon-to-be offlined CPU in crash_prepare_elf64_headers().

    On the memory side, each un/plugged memory block passes through the
    handler. For example, if a 1GiB DIMM is hotplugged, that generate 8
    memory events, one for each 128MiB memblock.

    Signed-off-by: Eric DeVolder <eric.devolder@oracle.com>
    ---
    kernel/crash_core.c | 118 ++++++++++++++++++++++++++++++++++++++++++++
    1 file changed, 118 insertions(+)

    diff --git a/kernel/crash_core.c b/kernel/crash_core.c
    index eb53f5ec62c9..9a30a305b04d 100644
    --- a/kernel/crash_core.c
    +++ b/kernel/crash_core.c
    @@ -8,12 +8,16 @@
    #include <linux/crash_core.h>
    #include <linux/utsname.h>
    #include <linux/vmalloc.h>
    +#include <linux/memory.h>
    +#include <linux/cpuhotplug.h>

    #include <asm/page.h>
    #include <asm/sections.h>

    #include <crypto/sha1.h>

    +#include "kexec_internal.h"
    +
    /* vmcoreinfo stuff */
    unsigned char *vmcoreinfo_data;
    size_t vmcoreinfo_size;
    @@ -480,3 +484,117 @@ static int __init crash_save_vmcoreinfo_init(void)
    }

    subsys_initcall(crash_save_vmcoreinfo_init);
    +
    +#ifdef CONFIG_CRASH_HOTPLUG
    +void __weak arch_crash_hotplug_handler(struct kimage *image,
    + unsigned int hp_action, unsigned long a, unsigned long b)
    +{
    + pr_warn("crash hp: %s not implemented", __func__);
    +}
    +
    +static void crash_hotplug_handler(unsigned int hp_action,
    + unsigned long a, unsigned long b)
    +{
    + /* Obtain lock while changing crash information */
    + if (!mutex_trylock(&kexec_mutex))
    + return;
    +
    + /* Check kdump is loaded */
    + if (kexec_crash_image) {
    + pr_debug("crash hp: hp_action %u, a %lu, b %lu", hp_action,
    + a, b);
    +
    + /* Needed in order for the segments to be updated */
    + arch_kexec_unprotect_crashkres();
    +
    + /* Flag to differentiate between normal load and hotplug */
    + kexec_crash_image->hotplug_event = true;
    +
    + /*
    + * Due to use of CPUHP_AP_ONLINE_DYN, upon unplug and during
    + * this callback, the CPU is still in the for_each_present_cpu()
    + * list. Must explicitly look to exclude this CPU when building
    + * new list.
    + */
    + kexec_crash_image->offlinecpu =
    + (hp_action == KEXEC_CRASH_HP_REMOVE_CPU) ?
    + (unsigned int)a : ~0U;
    +
    + /* Now invoke arch-specific update handler */
    + arch_crash_hotplug_handler(kexec_crash_image, hp_action, a, b);
    +
    + /* No longer handling a hotplug event */
    + kexec_crash_image->hotplug_event = false;
    +
    + /* Change back to read-only */
    + arch_kexec_protect_crashkres();
    + }
    +
    + /* Release lock now that update complete */
    + mutex_unlock(&kexec_mutex);
    +}
    +
    +#if defined(CONFIG_MEMORY_HOTPLUG)
    +static int crash_memhp_notifier(struct notifier_block *nb,
    + unsigned long val, void *v)
    +{
    + struct memory_notify *mhp = v;
    + unsigned long start, end;
    +
    + start = mhp->start_pfn << PAGE_SHIFT;
    + end = ((mhp->start_pfn + mhp->nr_pages) << PAGE_SHIFT) - 1;
    +
    + switch (val) {
    + case MEM_GOING_ONLINE:
    + crash_hotplug_handler(KEXEC_CRASH_HP_ADD_MEMORY,
    + start, end-start);
    + break;
    +
    + case MEM_OFFLINE:
    + case MEM_CANCEL_ONLINE:
    + crash_hotplug_handler(KEXEC_CRASH_HP_REMOVE_MEMORY,
    + start, end-start);
    + break;
    + }
    + return NOTIFY_OK;
    +}
    +
    +static struct notifier_block crash_memhp_nb = {
    + .notifier_call = crash_memhp_notifier,
    + .priority = 0
    +};
    +#endif
    +
    +#if defined(CONFIG_HOTPLUG_CPU)
    +static int crash_cpuhp_online(unsigned int cpu)
    +{
    + crash_hotplug_handler(KEXEC_CRASH_HP_ADD_CPU, cpu, 0);
    + return 0;
    +}
    +
    +static int crash_cpuhp_offline(unsigned int cpu)
    +{
    + crash_hotplug_handler(KEXEC_CRASH_HP_REMOVE_CPU, cpu, 0);
    + return 0;
    +}
    +#endif
    +
    +static int __init crash_hotplug_init(void)
    +{
    + int result = 0;
    +
    +#if defined(CONFIG_MEMORY_HOTPLUG)
    + register_memory_notifier(&crash_memhp_nb);
    +#endif
    +
    +#if defined(CONFIG_HOTPLUG_CPU)
    + result = cpuhp_setup_state_nocalls(CPUHP_AP_ONLINE_DYN,
    + "crash/cpuhp",
    + crash_cpuhp_online, crash_cpuhp_offline);
    +#endif
    +
    + return result;
    +}
    +
    +subsys_initcall(crash_hotplug_init);
    +#endif /* CONFIG_CRASH_HOTPLUG */
    --
    2.27.0
    \
     
     \ /
      Last update: 2021-12-07 20:55    [W:4.760 / U:0.004 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site