arch/s390/kernel/nmi.c

Source file repositories/reference/linux-study-clean/arch/s390/kernel/nmi.c

File Facts

System
Linux kernel
Corpus path
arch/s390/kernel/nmi.c
Extension
.c
Size
14373 bytes
Lines
515
Domain
Architecture Layer
Bucket
arch/s390
Inferred role
Architecture Layer: implementation source
Status
source implementation candidate

Why This File Exists

CPU and platform-specific kernel glue: boot entry, traps, syscall entry, interrupts, page tables, context switch, and low-level barriers.

Dependency Surface

Detected Declarations

Annotated Snippet

struct mcck_struct {
	unsigned int kill_task : 1;
	unsigned int channel_report : 1;
	unsigned int warning : 1;
	unsigned int stp_queue : 1;
	unsigned long mcck_code;
};

static DEFINE_PER_CPU(struct mcck_struct, cpu_mcck);

static inline int nmi_needs_mcesa(void)
{
	return cpu_has_vx() || cpu_has_gs();
}

/*
 * The initial machine check extended save area for the boot CPU.
 * It will be replaced on the boot CPU reinit with an allocated
 * structure. The structure is required for machine check happening
 * early in the boot process.
 */
static struct mcesa boot_mcesa __aligned(MCESA_MAX_SIZE);

void __init nmi_alloc_mcesa_early(u64 *mcesad)
{
	if (!nmi_needs_mcesa())
		return;
	*mcesad = __pa(&boot_mcesa);
	if (cpu_has_gs())
		*mcesad |= ilog2(MCESA_MAX_SIZE);
}

int nmi_alloc_mcesa(u64 *mcesad)
{
	unsigned long size;
	void *origin;

	*mcesad = 0;
	if (!nmi_needs_mcesa())
		return 0;
	size = cpu_has_gs() ? MCESA_MAX_SIZE : MCESA_MIN_SIZE;
	origin = kmalloc(size, GFP_KERNEL);
	if (!origin)
		return -ENOMEM;
	/* The pointer is stored with mcesa_bits ORed in */
	kmemleak_not_leak(origin);
	*mcesad = __pa(origin);
	if (cpu_has_gs())
		*mcesad |= ilog2(MCESA_MAX_SIZE);
	return 0;
}

void nmi_free_mcesa(u64 *mcesad)
{
	if (!nmi_needs_mcesa())
		return;
	kfree(__va(*mcesad & MCESA_ORIGIN_MASK));
}

static __always_inline char *nmi_puts(char *dest, const char *src)
{
	while (*src)
		*dest++ = *src++;
	*dest = 0;
	return dest;
}

static __always_inline char *u64_to_hex(char *dest, u64 val)
{
	int i, num;

	for (i = 1; i <= 16; i++) {
		num = (val >> (64 - 4 * i)) & 0xf;
		if (num >= 10)
			*dest++ = 'A' + num - 10;
		else
			*dest++ = '0' + num;
	}
	*dest = 0;
	return dest;
}

static notrace void nmi_print_info(void)
{
	struct lowcore *lc = get_lowcore();
	char message[100];
	char *ptr;
	int i;

	ptr = nmi_puts(message, "Unrecoverable machine check, code: ");

Annotation

Implementation Notes