Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /* sstate.c: System soft state support.
0003  *
0004  * Copyright (C) 2007, 2008 David S. Miller <davem@davemloft.net>
0005  */
0006 
0007 #include <linux/kernel.h>
0008 #include <linux/notifier.h>
0009 #include <linux/panic_notifier.h>
0010 #include <linux/reboot.h>
0011 #include <linux/init.h>
0012 
0013 #include <asm/hypervisor.h>
0014 #include <asm/spitfire.h>
0015 #include <asm/oplib.h>
0016 #include <asm/head.h>
0017 #include <asm/io.h>
0018 
0019 #include "kernel.h"
0020 
0021 static int hv_supports_soft_state;
0022 
0023 static void do_set_sstate(unsigned long state, const char *msg)
0024 {
0025     unsigned long err;
0026 
0027     if (!hv_supports_soft_state)
0028         return;
0029 
0030     err = sun4v_mach_set_soft_state(state, kimage_addr_to_ra(msg));
0031     if (err) {
0032         printk(KERN_WARNING "SSTATE: Failed to set soft-state to "
0033                "state[%lx] msg[%s], err=%lu\n",
0034                state, msg, err);
0035     }
0036 }
0037 
0038 static const char booting_msg[32] __attribute__((aligned(32))) =
0039     "Linux booting";
0040 static const char running_msg[32] __attribute__((aligned(32))) =
0041     "Linux running";
0042 static const char halting_msg[32] __attribute__((aligned(32))) =
0043     "Linux halting";
0044 static const char poweroff_msg[32] __attribute__((aligned(32))) =
0045     "Linux powering off";
0046 static const char rebooting_msg[32] __attribute__((aligned(32))) =
0047     "Linux rebooting";
0048 static const char panicking_msg[32] __attribute__((aligned(32))) =
0049     "Linux panicking";
0050 
0051 static int sstate_reboot_call(struct notifier_block *np, unsigned long type, void *_unused)
0052 {
0053     const char *msg;
0054 
0055     switch (type) {
0056     case SYS_DOWN:
0057     default:
0058         msg = rebooting_msg;
0059         break;
0060 
0061     case SYS_HALT:
0062         msg = halting_msg;
0063         break;
0064 
0065     case SYS_POWER_OFF:
0066         msg = poweroff_msg;
0067         break;
0068     }
0069 
0070     do_set_sstate(HV_SOFT_STATE_TRANSITION, msg);
0071 
0072     return NOTIFY_OK;
0073 }
0074 
0075 static struct notifier_block sstate_reboot_notifier = {
0076     .notifier_call = sstate_reboot_call,
0077 };
0078 
0079 static int sstate_panic_event(struct notifier_block *n, unsigned long event, void *ptr)
0080 {
0081     do_set_sstate(HV_SOFT_STATE_TRANSITION, panicking_msg);
0082 
0083     return NOTIFY_DONE;
0084 }
0085 
0086 static struct notifier_block sstate_panic_block = {
0087     .notifier_call  =   sstate_panic_event,
0088     .priority   =   INT_MAX,
0089 };
0090 
0091 static int __init sstate_init(void)
0092 {
0093     unsigned long major, minor;
0094 
0095     if (tlb_type != hypervisor)
0096         return 0;
0097 
0098     major = 1;
0099     minor = 0;
0100     if (sun4v_hvapi_register(HV_GRP_SOFT_STATE, major, &minor))
0101         return 0;
0102 
0103     hv_supports_soft_state = 1;
0104 
0105     prom_sun4v_guest_soft_state();
0106 
0107     do_set_sstate(HV_SOFT_STATE_TRANSITION, booting_msg);
0108 
0109     atomic_notifier_chain_register(&panic_notifier_list,
0110                        &sstate_panic_block);
0111     register_reboot_notifier(&sstate_reboot_notifier);
0112 
0113     return 0;
0114 }
0115 
0116 core_initcall(sstate_init);
0117 
0118 static int __init sstate_running(void)
0119 {
0120     do_set_sstate(HV_SOFT_STATE_NORMAL, running_msg);
0121     return 0;
0122 }
0123 
0124 late_initcall(sstate_running);