Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  lgr.c   Sprache: C

 
// SPDX-License-Identifier: GPL-2.0
/*
 * Linux Guest Relocation (LGR) detection
 *
 * Copyright IBM Corp. 2012
 * Author(s): Michael Holzheu <holzheu@linux.vnet.ibm.com>
 */


#include <linux/init.h>
#include <linux/export.h>
#include <linux/timer.h>
#include <linux/slab.h>
#include <asm/facility.h>
#include <asm/sysinfo.h>
#include <asm/ebcdic.h>
#include <asm/debug.h>
#include <asm/ipl.h>

#define LGR_TIMER_INTERVAL_SECS (30 * 60)
#define VM_LEVEL_MAX 2 /* Maximum is 8, but we only record two levels */

/*
 * LGR info: Contains stfle and stsi data
 */

struct lgr_info {
 /* Bit field with facility information: 4 DWORDs are stored */
 u64 stfle_fac_list[4];
 /* Level of system (1 = CEC, 2 = LPAR, 3 = z/VM */
 u32 level;
 /* Level 1: CEC info (stsi 1.1.1) */
 char manufacturer[16];
 char type[4];
 char sequence[16];
 char plant[4];
 char model[16];
 /* Level 2: LPAR info (stsi 2.2.2) */
 u16 lpar_number;
 char name[8];
 /* Level 3: VM info (stsi 3.2.2) */
 u8 vm_count;
 struct {
  char name[8];
  char cpi[16];
 } vm[VM_LEVEL_MAX];
} __packed __aligned(8);

/*
 * LGR globals
 */

static char lgr_page[PAGE_SIZE] __aligned(PAGE_SIZE);
static struct lgr_info lgr_info_last;
static struct lgr_info lgr_info_cur;
static struct debug_info *lgr_dbf;

/*
 * Copy buffer and then convert it to ASCII
 */

static void cpascii(char *dst, char *src, int size)
{
 memcpy(dst, src, size);
 EBCASC(dst, size);
}

/*
 * Fill LGR info with 1.1.1 stsi data
 */

static void lgr_stsi_1_1_1(struct lgr_info *lgr_info)
{
 struct sysinfo_1_1_1 *si = (void *) lgr_page;

 if (stsi(si, 1, 1, 1))
  return;
 cpascii(lgr_info->manufacturer, si->manufacturer,
  sizeof(si->manufacturer));
 cpascii(lgr_info->type, si->type, sizeof(si->type));
 cpascii(lgr_info->model, si->model, sizeof(si->model));
 cpascii(lgr_info->sequence, si->sequence, sizeof(si->sequence));
 cpascii(lgr_info->plant, si->plant, sizeof(si->plant));
}

/*
 * Fill LGR info with 2.2.2 stsi data
 */

static void lgr_stsi_2_2_2(struct lgr_info *lgr_info)
{
 struct sysinfo_2_2_2 *si = (void *) lgr_page;

 if (stsi(si, 2, 2, 2))
  return;
 cpascii(lgr_info->name, si->name, sizeof(si->name));
 lgr_info->lpar_number = si->lpar_number;
}

/*
 * Fill LGR info with 3.2.2 stsi data
 */

static void lgr_stsi_3_2_2(struct lgr_info *lgr_info)
{
 struct sysinfo_3_2_2 *si = (void *) lgr_page;
 int i;

 if (stsi(si, 3, 2, 2))
  return;
 for (i = 0; i < min_t(u8, si->count, VM_LEVEL_MAX); i++) {
  cpascii(lgr_info->vm[i].name, si->vm[i].name,
   sizeof(si->vm[i].name));
  cpascii(lgr_info->vm[i].cpi, si->vm[i].cpi,
   sizeof(si->vm[i].cpi));
 }
 lgr_info->vm_count = si->count;
}

/*
 * Fill LGR info with current data
 */

static void lgr_info_get(struct lgr_info *lgr_info)
{
 int level;

 memset(lgr_info, 0, sizeof(*lgr_info));
 stfle(lgr_info->stfle_fac_list, ARRAY_SIZE(lgr_info->stfle_fac_list));
 level = stsi(NULL, 0, 0, 0);
 lgr_info->level = level;
 if (level >= 1)
  lgr_stsi_1_1_1(lgr_info);
 if (level >= 2)
  lgr_stsi_2_2_2(lgr_info);
 if (level >= 3)
  lgr_stsi_3_2_2(lgr_info);
}

/*
 * Check if LGR info has changed and if yes log new LGR info to s390dbf
 */

void lgr_info_log(void)
{
 static DEFINE_SPINLOCK(lgr_info_lock);
 unsigned long flags;

 if (!spin_trylock_irqsave(&lgr_info_lock, flags))
  return;
 lgr_info_get(&lgr_info_cur);
 if (memcmp(&lgr_info_last, &lgr_info_cur, sizeof(lgr_info_cur)) != 0) {
  debug_event(lgr_dbf, 1, &lgr_info_cur, sizeof(lgr_info_cur));
  lgr_info_last = lgr_info_cur;
 }
 spin_unlock_irqrestore(&lgr_info_lock, flags);
}
EXPORT_SYMBOL_GPL(lgr_info_log);

static void lgr_timer_set(void);

/*
 * LGR timer callback
 */

static void lgr_timer_fn(struct timer_list *unused)
{
 lgr_info_log();
 lgr_timer_set();
}

static struct timer_list lgr_timer;

/*
 * Setup next LGR timer
 */

static void lgr_timer_set(void)
{
 mod_timer(&lgr_timer, jiffies + secs_to_jiffies(LGR_TIMER_INTERVAL_SECS));
}

/*
 * Initialize LGR: Add s390dbf, write initial lgr_info and setup timer
 */

static int __init lgr_init(void)
{
 lgr_dbf = debug_register("lgr", 1, 1, sizeof(struct lgr_info));
 if (!lgr_dbf)
  return -ENOMEM;
 debug_register_view(lgr_dbf, &debug_hex_ascii_view);
 lgr_info_get(&lgr_info_last);
 debug_event(lgr_dbf, 1, &lgr_info_last, sizeof(lgr_info_last));
 timer_setup(&lgr_timer, lgr_timer_fn, TIMER_DEFERRABLE);
 lgr_timer_set();
 return 0;
}
device_initcall(lgr_init);

Messung V0.5
C=94 H=91 G=92

¤ Dauer der Verarbeitung: 0.3 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge