~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/arch/s390/kernel/lgr.c

Version: ~ [ linux-5.2-rc1 ] ~ [ linux-5.1.2 ] ~ [ linux-5.0.16 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.43 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.119 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.176 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.179 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.19.8 ] ~ [ linux-3.18.139 ] ~ [ linux-3.17.8 ] ~ [ linux-3.16.67 ] ~ [ linux-3.15.10 ] ~ [ linux-3.14.79 ] ~ [ linux-3.13.11 ] ~ [ linux-3.12.74 ] ~ [ linux-3.11.10 ] ~ [ linux-3.10.108 ] ~ [ linux-3.9.11 ] ~ [ linux-3.8.13 ] ~ [ linux-3.7.10 ] ~ [ linux-3.6.11 ] ~ [ linux-3.5.7 ] ~ [ linux-3.4.113 ] ~ [ linux-3.3.8 ] ~ [ linux-3.2.102 ] ~ [ linux-3.1.10 ] ~ [ linux-3.0.101 ] ~ [ linux-2.6.39.4 ] ~ [ linux-2.6.38.8 ] ~ [ linux-2.6.37.6 ] ~ [ linux-2.6.36.4 ] ~ [ linux-2.6.35.14 ] ~ [ linux-2.6.34.15 ] ~ [ linux-2.6.33.20 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

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

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp