root/arch/s390/kernel/lgr.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. cpascii
  2. lgr_stsi_1_1_1
  3. lgr_stsi_2_2_2
  4. lgr_stsi_3_2_2
  5. lgr_info_get
  6. lgr_info_log
  7. lgr_timer_fn
  8. lgr_timer_set
  9. lgr_init

   1 // SPDX-License-Identifier: GPL-2.0
   2 /*
   3  * Linux Guest Relocation (LGR) detection
   4  *
   5  * Copyright IBM Corp. 2012
   6  * Author(s): Michael Holzheu <holzheu@linux.vnet.ibm.com>
   7  */
   8 
   9 #include <linux/init.h>
  10 #include <linux/export.h>
  11 #include <linux/timer.h>
  12 #include <linux/slab.h>
  13 #include <asm/facility.h>
  14 #include <asm/sysinfo.h>
  15 #include <asm/ebcdic.h>
  16 #include <asm/debug.h>
  17 #include <asm/ipl.h>
  18 
  19 #define LGR_TIMER_INTERVAL_SECS (30 * 60)
  20 #define VM_LEVEL_MAX 2 /* Maximum is 8, but we only record two levels */
  21 
  22 /*
  23  * LGR info: Contains stfle and stsi data
  24  */
  25 struct lgr_info {
  26         /* Bit field with facility information: 4 DWORDs are stored */
  27         u64 stfle_fac_list[4];
  28         /* Level of system (1 = CEC, 2 = LPAR, 3 = z/VM */
  29         u32 level;
  30         /* Level 1: CEC info (stsi 1.1.1) */
  31         char manufacturer[16];
  32         char type[4];
  33         char sequence[16];
  34         char plant[4];
  35         char model[16];
  36         /* Level 2: LPAR info (stsi 2.2.2) */
  37         u16 lpar_number;
  38         char name[8];
  39         /* Level 3: VM info (stsi 3.2.2) */
  40         u8 vm_count;
  41         struct {
  42                 char name[8];
  43                 char cpi[16];
  44         } vm[VM_LEVEL_MAX];
  45 } __packed __aligned(8);
  46 
  47 /*
  48  * LGR globals
  49  */
  50 static char lgr_page[PAGE_SIZE] __aligned(PAGE_SIZE);
  51 static struct lgr_info lgr_info_last;
  52 static struct lgr_info lgr_info_cur;
  53 static struct debug_info *lgr_dbf;
  54 
  55 /*
  56  * Copy buffer and then convert it to ASCII
  57  */
  58 static void cpascii(char *dst, char *src, int size)
  59 {
  60         memcpy(dst, src, size);
  61         EBCASC(dst, size);
  62 }
  63 
  64 /*
  65  * Fill LGR info with 1.1.1 stsi data
  66  */
  67 static void lgr_stsi_1_1_1(struct lgr_info *lgr_info)
  68 {
  69         struct sysinfo_1_1_1 *si = (void *) lgr_page;
  70 
  71         if (stsi(si, 1, 1, 1))
  72                 return;
  73         cpascii(lgr_info->manufacturer, si->manufacturer,
  74                 sizeof(si->manufacturer));
  75         cpascii(lgr_info->type, si->type, sizeof(si->type));
  76         cpascii(lgr_info->model, si->model, sizeof(si->model));
  77         cpascii(lgr_info->sequence, si->sequence, sizeof(si->sequence));
  78         cpascii(lgr_info->plant, si->plant, sizeof(si->plant));
  79 }
  80 
  81 /*
  82  * Fill LGR info with 2.2.2 stsi data
  83  */
  84 static void lgr_stsi_2_2_2(struct lgr_info *lgr_info)
  85 {
  86         struct sysinfo_2_2_2 *si = (void *) lgr_page;
  87 
  88         if (stsi(si, 2, 2, 2))
  89                 return;
  90         cpascii(lgr_info->name, si->name, sizeof(si->name));
  91         memcpy(&lgr_info->lpar_number, &si->lpar_number,
  92                sizeof(lgr_info->lpar_number));
  93 }
  94 
  95 /*
  96  * Fill LGR info with 3.2.2 stsi data
  97  */
  98 static void lgr_stsi_3_2_2(struct lgr_info *lgr_info)
  99 {
 100         struct sysinfo_3_2_2 *si = (void *) lgr_page;
 101         int i;
 102 
 103         if (stsi(si, 3, 2, 2))
 104                 return;
 105         for (i = 0; i < min_t(u8, si->count, VM_LEVEL_MAX); i++) {
 106                 cpascii(lgr_info->vm[i].name, si->vm[i].name,
 107                         sizeof(si->vm[i].name));
 108                 cpascii(lgr_info->vm[i].cpi, si->vm[i].cpi,
 109                         sizeof(si->vm[i].cpi));
 110         }
 111         lgr_info->vm_count = si->count;
 112 }
 113 
 114 /*
 115  * Fill LGR info with current data
 116  */
 117 static void lgr_info_get(struct lgr_info *lgr_info)
 118 {
 119         int level;
 120 
 121         memset(lgr_info, 0, sizeof(*lgr_info));
 122         stfle(lgr_info->stfle_fac_list, ARRAY_SIZE(lgr_info->stfle_fac_list));
 123         level = stsi(NULL, 0, 0, 0);
 124         lgr_info->level = level;
 125         if (level >= 1)
 126                 lgr_stsi_1_1_1(lgr_info);
 127         if (level >= 2)
 128                 lgr_stsi_2_2_2(lgr_info);
 129         if (level >= 3)
 130                 lgr_stsi_3_2_2(lgr_info);
 131 }
 132 
 133 /*
 134  * Check if LGR info has changed and if yes log new LGR info to s390dbf
 135  */
 136 void lgr_info_log(void)
 137 {
 138         static DEFINE_SPINLOCK(lgr_info_lock);
 139         unsigned long flags;
 140 
 141         if (!spin_trylock_irqsave(&lgr_info_lock, flags))
 142                 return;
 143         lgr_info_get(&lgr_info_cur);
 144         if (memcmp(&lgr_info_last, &lgr_info_cur, sizeof(lgr_info_cur)) != 0) {
 145                 debug_event(lgr_dbf, 1, &lgr_info_cur, sizeof(lgr_info_cur));
 146                 lgr_info_last = lgr_info_cur;
 147         }
 148         spin_unlock_irqrestore(&lgr_info_lock, flags);
 149 }
 150 EXPORT_SYMBOL_GPL(lgr_info_log);
 151 
 152 static void lgr_timer_set(void);
 153 
 154 /*
 155  * LGR timer callback
 156  */
 157 static void lgr_timer_fn(struct timer_list *unused)
 158 {
 159         lgr_info_log();
 160         lgr_timer_set();
 161 }
 162 
 163 static struct timer_list lgr_timer;
 164 
 165 /*
 166  * Setup next LGR timer
 167  */
 168 static void lgr_timer_set(void)
 169 {
 170         mod_timer(&lgr_timer, jiffies + LGR_TIMER_INTERVAL_SECS * HZ);
 171 }
 172 
 173 /*
 174  * Initialize LGR: Add s390dbf, write initial lgr_info and setup timer
 175  */
 176 static int __init lgr_init(void)
 177 {
 178         lgr_dbf = debug_register("lgr", 1, 1, sizeof(struct lgr_info));
 179         if (!lgr_dbf)
 180                 return -ENOMEM;
 181         debug_register_view(lgr_dbf, &debug_hex_ascii_view);
 182         lgr_info_get(&lgr_info_last);
 183         debug_event(lgr_dbf, 1, &lgr_info_last, sizeof(lgr_info_last));
 184         timer_setup(&lgr_timer, lgr_timer_fn, TIMER_DEFERRABLE);
 185         lgr_timer_set();
 186         return 0;
 187 }
 188 device_initcall(lgr_init);

/* [<][>][^][v][top][bottom][index][help] */