sstate.c (2715B)
1// SPDX-License-Identifier: GPL-2.0 2/* sstate.c: System soft state support. 3 * 4 * Copyright (C) 2007, 2008 David S. Miller <davem@davemloft.net> 5 */ 6 7#include <linux/kernel.h> 8#include <linux/notifier.h> 9#include <linux/panic_notifier.h> 10#include <linux/reboot.h> 11#include <linux/init.h> 12 13#include <asm/hypervisor.h> 14#include <asm/spitfire.h> 15#include <asm/oplib.h> 16#include <asm/head.h> 17#include <asm/io.h> 18 19#include "kernel.h" 20 21static int hv_supports_soft_state; 22 23static void do_set_sstate(unsigned long state, const char *msg) 24{ 25 unsigned long err; 26 27 if (!hv_supports_soft_state) 28 return; 29 30 err = sun4v_mach_set_soft_state(state, kimage_addr_to_ra(msg)); 31 if (err) { 32 printk(KERN_WARNING "SSTATE: Failed to set soft-state to " 33 "state[%lx] msg[%s], err=%lu\n", 34 state, msg, err); 35 } 36} 37 38static const char booting_msg[32] __attribute__((aligned(32))) = 39 "Linux booting"; 40static const char running_msg[32] __attribute__((aligned(32))) = 41 "Linux running"; 42static const char halting_msg[32] __attribute__((aligned(32))) = 43 "Linux halting"; 44static const char poweroff_msg[32] __attribute__((aligned(32))) = 45 "Linux powering off"; 46static const char rebooting_msg[32] __attribute__((aligned(32))) = 47 "Linux rebooting"; 48static const char panicking_msg[32] __attribute__((aligned(32))) = 49 "Linux panicking"; 50 51static int sstate_reboot_call(struct notifier_block *np, unsigned long type, void *_unused) 52{ 53 const char *msg; 54 55 switch (type) { 56 case SYS_DOWN: 57 default: 58 msg = rebooting_msg; 59 break; 60 61 case SYS_HALT: 62 msg = halting_msg; 63 break; 64 65 case SYS_POWER_OFF: 66 msg = poweroff_msg; 67 break; 68 } 69 70 do_set_sstate(HV_SOFT_STATE_TRANSITION, msg); 71 72 return NOTIFY_OK; 73} 74 75static struct notifier_block sstate_reboot_notifier = { 76 .notifier_call = sstate_reboot_call, 77}; 78 79static int sstate_panic_event(struct notifier_block *n, unsigned long event, void *ptr) 80{ 81 do_set_sstate(HV_SOFT_STATE_TRANSITION, panicking_msg); 82 83 return NOTIFY_DONE; 84} 85 86static struct notifier_block sstate_panic_block = { 87 .notifier_call = sstate_panic_event, 88 .priority = INT_MAX, 89}; 90 91static int __init sstate_init(void) 92{ 93 unsigned long major, minor; 94 95 if (tlb_type != hypervisor) 96 return 0; 97 98 major = 1; 99 minor = 0; 100 if (sun4v_hvapi_register(HV_GRP_SOFT_STATE, major, &minor)) 101 return 0; 102 103 hv_supports_soft_state = 1; 104 105 prom_sun4v_guest_soft_state(); 106 107 do_set_sstate(HV_SOFT_STATE_TRANSITION, booting_msg); 108 109 atomic_notifier_chain_register(&panic_notifier_list, 110 &sstate_panic_block); 111 register_reboot_notifier(&sstate_reboot_notifier); 112 113 return 0; 114} 115 116core_initcall(sstate_init); 117 118static int __init sstate_running(void) 119{ 120 do_set_sstate(HV_SOFT_STATE_NORMAL, running_msg); 121 return 0; 122} 123 124late_initcall(sstate_running);