cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

pdc_chassis.c (7276B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/* 
      3 *    interfaces to Chassis Codes via PDC (firmware)
      4 *
      5 *    Copyright (C) 2002 Laurent Canet <canetl@esiee.fr>
      6 *    Copyright (C) 2002-2006 Thibaut VARENE <varenet@parisc-linux.org>
      7 *
      8 *    TODO: poll chassis warns, trigger (configurable) machine shutdown when
      9 *    		needed.
     10 *    	    Find out how to get Chassis warnings out of PAT boxes?
     11 */
     12
     13#undef PDC_CHASSIS_DEBUG
     14#ifdef PDC_CHASSIS_DEBUG
     15#define DPRINTK(fmt, args...)	printk(fmt, ## args)
     16#else
     17#define DPRINTK(fmt, args...)
     18#endif
     19
     20#include <linux/init.h>
     21#include <linux/module.h>
     22#include <linux/kernel.h>
     23#include <linux/panic_notifier.h>
     24#include <linux/reboot.h>
     25#include <linux/notifier.h>
     26#include <linux/cache.h>
     27#include <linux/proc_fs.h>
     28#include <linux/seq_file.h>
     29
     30#include <asm/pdc_chassis.h>
     31#include <asm/processor.h>
     32#include <asm/pdc.h>
     33#include <asm/pdcpat.h>
     34
     35#define PDC_CHASSIS_VER	"0.05"
     36
     37#ifdef CONFIG_PDC_CHASSIS
     38static unsigned int pdc_chassis_enabled __read_mostly = 1;
     39
     40
     41/**
     42 * pdc_chassis_setup() - Enable/disable pdc_chassis code at boot time.
     43 * @str configuration param: 0 to disable chassis log
     44 * @return 1
     45 */
     46 
     47static int __init pdc_chassis_setup(char *str)
     48{
     49	/*panic_timeout = simple_strtoul(str, NULL, 0);*/
     50	get_option(&str, &pdc_chassis_enabled);
     51	return 1;
     52}
     53__setup("pdcchassis=", pdc_chassis_setup);
     54
     55
     56/** 
     57 * pdc_chassis_checkold() - Checks for old PDC_CHASSIS compatibility
     58 * @pdc_chassis_old: 1 if old pdc chassis style
     59 * 
     60 * Currently, only E class and A180 are known to work with this.
     61 * Inspired by Christoph Plattner
     62 */
     63#if 0
     64static void __init pdc_chassis_checkold(void)
     65{
     66	switch(CPU_HVERSION) {
     67		case 0x480:		/* E25 */
     68		case 0x481:		/* E35 */
     69		case 0x482:		/* E45 */
     70		case 0x483:		/* E55 */
     71		case 0x516:		/* A180 */
     72			break;
     73
     74		default:
     75			break;
     76	}
     77	DPRINTK(KERN_DEBUG "%s: pdc_chassis_checkold(); pdc_chassis_old = %d\n", __FILE__, pdc_chassis_old);
     78}
     79#endif
     80
     81/**
     82 * pdc_chassis_panic_event() - Called by the panic handler.
     83 *
     84 * As soon as a panic occurs, we should inform the PDC.
     85 */
     86
     87static int pdc_chassis_panic_event(struct notifier_block *this,
     88		        unsigned long event, void *ptr)
     89{
     90	pdc_chassis_send_status(PDC_CHASSIS_DIRECT_PANIC);
     91		return NOTIFY_DONE;
     92}   
     93
     94
     95static struct notifier_block pdc_chassis_panic_block = {
     96	.notifier_call = pdc_chassis_panic_event,
     97	.priority = INT_MAX,
     98};
     99
    100
    101/**
    102 * parisc_reboot_event() - Called by the reboot handler.
    103 *
    104 * As soon as a reboot occurs, we should inform the PDC.
    105 */
    106
    107static int pdc_chassis_reboot_event(struct notifier_block *this,
    108		        unsigned long event, void *ptr)
    109{
    110	pdc_chassis_send_status(PDC_CHASSIS_DIRECT_SHUTDOWN);
    111		return NOTIFY_DONE;
    112}   
    113
    114
    115static struct notifier_block pdc_chassis_reboot_block = {
    116	.notifier_call = pdc_chassis_reboot_event,
    117	.priority = INT_MAX,
    118};
    119#endif /* CONFIG_PDC_CHASSIS */
    120
    121
    122/**
    123 * parisc_pdc_chassis_init() - Called at boot time.
    124 */
    125
    126void __init parisc_pdc_chassis_init(void)
    127{
    128#ifdef CONFIG_PDC_CHASSIS
    129	if (likely(pdc_chassis_enabled)) {
    130		DPRINTK(KERN_DEBUG "%s: parisc_pdc_chassis_init()\n", __FILE__);
    131
    132		/* Let see if we have something to handle... */
    133		printk(KERN_INFO "Enabling %s chassis codes support v%s\n",
    134				is_pdc_pat() ? "PDC_PAT" : "regular",
    135				PDC_CHASSIS_VER);
    136
    137		/* initialize panic notifier chain */
    138		atomic_notifier_chain_register(&panic_notifier_list,
    139				&pdc_chassis_panic_block);
    140
    141		/* initialize reboot notifier chain */
    142		register_reboot_notifier(&pdc_chassis_reboot_block);
    143	}
    144#endif /* CONFIG_PDC_CHASSIS */
    145}
    146
    147
    148/** 
    149 * pdc_chassis_send_status() - Sends a predefined message to the chassis,
    150 * and changes the front panel LEDs according to the new system state
    151 * @retval: PDC call return value.
    152 *
    153 * Only machines with 64 bits PDC PAT and those reported in
    154 * pdc_chassis_checkold() are supported atm.
    155 * 
    156 * returns 0 if no error, -1 if no supported PDC is present or invalid message,
    157 * else returns the appropriate PDC error code.
    158 * 
    159 * For a list of predefined messages, see asm-parisc/pdc_chassis.h
    160 */
    161
    162int pdc_chassis_send_status(int message)
    163{
    164	/* Maybe we should do that in an other way ? */
    165	int retval = 0;
    166#ifdef CONFIG_PDC_CHASSIS
    167	if (likely(pdc_chassis_enabled)) {
    168
    169		DPRINTK(KERN_DEBUG "%s: pdc_chassis_send_status(%d)\n", __FILE__, message);
    170
    171#ifdef CONFIG_64BIT
    172		if (is_pdc_pat()) {
    173			switch(message) {
    174				case PDC_CHASSIS_DIRECT_BSTART:
    175					retval = pdc_pat_chassis_send_log(PDC_CHASSIS_PMSG_BSTART, PDC_CHASSIS_LSTATE_RUN_NORMAL);
    176					break;
    177
    178				case PDC_CHASSIS_DIRECT_BCOMPLETE:
    179					retval = pdc_pat_chassis_send_log(PDC_CHASSIS_PMSG_BCOMPLETE, PDC_CHASSIS_LSTATE_RUN_NORMAL);
    180					break;
    181
    182				case PDC_CHASSIS_DIRECT_SHUTDOWN:
    183					retval = pdc_pat_chassis_send_log(PDC_CHASSIS_PMSG_SHUTDOWN, PDC_CHASSIS_LSTATE_NONOS);
    184					break;
    185
    186				case PDC_CHASSIS_DIRECT_PANIC:
    187					retval = pdc_pat_chassis_send_log(PDC_CHASSIS_PMSG_PANIC, PDC_CHASSIS_LSTATE_RUN_CRASHREC);
    188					break;
    189
    190				case PDC_CHASSIS_DIRECT_LPMC:
    191					retval = pdc_pat_chassis_send_log(PDC_CHASSIS_PMSG_LPMC, PDC_CHASSIS_LSTATE_RUN_SYSINT);
    192					break;
    193
    194				case PDC_CHASSIS_DIRECT_HPMC:
    195					retval = pdc_pat_chassis_send_log(PDC_CHASSIS_PMSG_HPMC, PDC_CHASSIS_LSTATE_RUN_NCRIT);
    196					break;
    197
    198				default:
    199					retval = -1;
    200			}
    201		} else retval = -1;
    202#else
    203		if (1) {
    204			switch (message) {
    205				case PDC_CHASSIS_DIRECT_BSTART:
    206					retval = pdc_chassis_disp(PDC_CHASSIS_DISP_DATA(OSTAT_INIT));
    207					break;
    208
    209				case PDC_CHASSIS_DIRECT_BCOMPLETE:
    210					retval = pdc_chassis_disp(PDC_CHASSIS_DISP_DATA(OSTAT_RUN));
    211					break;
    212
    213				case PDC_CHASSIS_DIRECT_SHUTDOWN:
    214					retval = pdc_chassis_disp(PDC_CHASSIS_DISP_DATA(OSTAT_SHUT));
    215					break;
    216
    217				case PDC_CHASSIS_DIRECT_HPMC:
    218				case PDC_CHASSIS_DIRECT_PANIC:
    219					retval = pdc_chassis_disp(PDC_CHASSIS_DISP_DATA(OSTAT_FLT));
    220					break;
    221
    222				case PDC_CHASSIS_DIRECT_LPMC:
    223					retval = pdc_chassis_disp(PDC_CHASSIS_DISP_DATA(OSTAT_WARN));
    224					break;
    225
    226				default:
    227					retval = -1;
    228			}
    229		} else retval = -1;
    230#endif /* CONFIG_64BIT */
    231	}	/* if (pdc_chassis_enabled) */
    232#endif /* CONFIG_PDC_CHASSIS */
    233	return retval;
    234}
    235
    236#ifdef CONFIG_PDC_CHASSIS_WARN
    237#ifdef CONFIG_PROC_FS
    238static int pdc_chassis_warn_show(struct seq_file *m, void *v)
    239{
    240	unsigned long warn;
    241	u32 warnreg;
    242
    243	if (pdc_chassis_warn(&warn) != PDC_OK)
    244		return -EIO;
    245
    246	warnreg = (warn & 0xFFFFFFFF);
    247
    248	if ((warnreg >> 24) & 0xFF)
    249		seq_printf(m, "Chassis component failure! (eg fan or PSU): 0x%.2x\n",
    250			   (warnreg >> 24) & 0xFF);
    251
    252	seq_printf(m, "Battery: %s\n", (warnreg & 0x04) ? "Low!" : "OK");
    253	seq_printf(m, "Temp low: %s\n", (warnreg & 0x02) ? "Exceeded!" : "OK");
    254	seq_printf(m, "Temp mid: %s\n", (warnreg & 0x01) ? "Exceeded!" : "OK");
    255	return 0;
    256}
    257
    258static int __init pdc_chassis_create_procfs(void)
    259{
    260	unsigned long test;
    261	int ret;
    262
    263	ret = pdc_chassis_warn(&test);
    264	if ((ret == PDC_BAD_PROC) || (ret == PDC_BAD_OPTION)) {
    265		/* seems that some boxes (eg L1000) do not implement this */
    266		printk(KERN_INFO "Chassis warnings not supported.\n");
    267		return 0;
    268	}
    269
    270	printk(KERN_INFO "Enabling PDC chassis warnings support v%s\n",
    271			PDC_CHASSIS_VER);
    272	proc_create_single("chassis", 0400, NULL, pdc_chassis_warn_show);
    273	return 0;
    274}
    275
    276__initcall(pdc_chassis_create_procfs);
    277
    278#endif /* CONFIG_PROC_FS */
    279#endif /* CONFIG_PDC_CHASSIS_WARN */