arch/s390/kernel/diag/diag.c

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

File Facts

System
Linux kernel
Corpus path
arch/s390/kernel/diag/diag.c
Extension
.c
Size
9216 bytes
Lines
325
Domain
Architecture Layer
Bucket
arch/s390
Inferred role
Architecture Layer: exported/initcall integration point
Status
integration 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

device_initcall(show_diag_stat_init);

void diag_stat_inc(enum diag_stat_enum nr)
{
	this_cpu_inc(diag_stat.counter[nr]);
	trace_s390_diagnose(diag_map[nr].code);
}
EXPORT_SYMBOL(diag_stat_inc);

void notrace diag_stat_inc_norecursion(enum diag_stat_enum nr)
{
	this_cpu_inc(diag_stat.counter[nr]);
	trace_s390_diagnose_norecursion(diag_map[nr].code);
}
EXPORT_SYMBOL(diag_stat_inc_norecursion);

/*
 * Diagnose 0c: Pseudo Timer
 */
void diag0c(struct hypfs_diag0c_entry *data)
{
	diag_stat_inc(DIAG_STAT_X00C);
	diag_amode31_ops.diag0c(virt_to_phys(data));
}

/*
 * Diagnose 14: Input spool file manipulation
 *
 * The subcode parameter determines the type of the first parameter rx.
 * Currently used are the following 3 subcommands:
 * 0x0:   Read the Next Spool File Buffer (Data Record)
 * 0x28:  Position a Spool File to the Designated Record
 * 0xfff: Retrieve Next File Descriptor
 *
 * For subcommands 0x0 and 0xfff, the value of the first parameter is
 * a virtual address of a memory buffer and needs virtual to physical
 * address translation. For other subcommands the rx parameter is not
 * a virtual address.
 */
int diag14(unsigned long rx, unsigned long ry1, unsigned long subcode)
{
	diag_stat_inc(DIAG_STAT_X014);
	switch (subcode) {
	case 0x0:
	case 0xfff:
		rx = virt_to_phys((void *)rx);
		break;
	default:
		/* Do nothing */
		break;
	}
	return diag_amode31_ops.diag14(rx, ry1, subcode);
}
EXPORT_SYMBOL(diag14);

#define DIAG204_BUSY_RC 8

static inline int __diag204(unsigned long *subcode, unsigned long size, void *addr)
{
	union register_pair rp = { .even = *subcode, .odd = size };

	asm_inline volatile(
		"	diag	%[addr],%[rp],0x204\n"
		"0:	nopr	%%r7\n"
		EX_TABLE(0b,0b)
		: [rp] "+&d" (rp.pair) : [addr] "d" (addr) : "memory");
	*subcode = rp.even;
	return rp.odd;
}

/**
 * diag204() - Issue diagnose 204 call.
 * @subcode: Subcode of diagnose 204 to be executed.
 * @size: Size of area in pages which @area points to, if given.
 * @addr: Vmalloc'ed memory area where the result is written to.
 *
 * Execute diagnose 204 with the given subcode and write the result to the
 * memory area specified with @addr. For subcodes which do not write a
 * result to memory both @size and @addr must be zero. If @addr is
 * specified it must be page aligned and must have been allocated with
 * vmalloc(). Conversion to real / physical addresses will be handled by
 * this function if required.
 */
int diag204(unsigned long subcode, unsigned long size, void *addr)
{
	if (addr) {
		if (WARN_ON_ONCE(!is_vmalloc_addr(addr)))
			return -EINVAL;
		if (WARN_ON_ONCE(!IS_ALIGNED((unsigned long)addr, PAGE_SIZE)))
			return -EINVAL;

Annotation

Implementation Notes