arch/s390/kernel/alternative.c

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

File Facts

System
Linux kernel
Corpus path
arch/s390/kernel/alternative.c
Extension
.c
Size
2344 bytes
Lines
92
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 alt_debug {
	unsigned long facilities[MAX_FACILITY_BIT / BITS_PER_LONG];
	unsigned long mfeatures[MAX_MFEATURE_BIT / BITS_PER_LONG];
	int spec;
};

static struct alt_debug __bootdata_preserved(alt_debug);

static void alternative_dump(u8 *old, u8 *new, unsigned int len, unsigned int type, unsigned int data)
{
	char oinsn[33], ninsn[33];
	unsigned long kptr;
	unsigned int pos;

	for (pos = 0; pos < len && 2 * pos < sizeof(oinsn) - 3; pos++)
		hex_byte_pack(&oinsn[2 * pos], old[pos]);
	oinsn[2 * pos] = 0;
	for (pos = 0; pos < len && 2 * pos < sizeof(ninsn) - 3; pos++)
		hex_byte_pack(&ninsn[2 * pos], new[pos]);
	ninsn[2 * pos] = 0;
	kptr = (unsigned long)__kernel_va(old);
	a_debug("[%d/%3d] %016lx: %s -> %s\n", type, data, kptr, oinsn, ninsn);
}

void __apply_alternatives(struct alt_instr *start, struct alt_instr *end, unsigned int ctx)
{
	struct alt_debug *d;
	struct alt_instr *a;
	bool debug, replace;
	u8 *old, *new;

	/*
	 * The scan order should be from start to end. A later scanned
	 * alternative code can overwrite previously scanned alternative code.
	 */
	d = &alt_debug;
	for (a = start; a < end; a++) {
		if (!(a->ctx & ctx))
			continue;
		switch (a->type) {
		case ALT_TYPE_FACILITY:
			replace = test_facility(a->data);
			debug = __test_facility(a->data, d->facilities);
			break;
		case ALT_TYPE_FEATURE:
			replace = test_machine_feature(a->data);
			debug = __test_machine_feature(a->data, d->mfeatures);
			break;
		case ALT_TYPE_SPEC:
			replace = nobp_enabled();
			debug = d->spec;
			break;
		default:
			replace = false;
			debug = false;
		}
		if (!replace)
			continue;
		old = (u8 *)&a->instr_offset + a->instr_offset;
		new = (u8 *)&a->repl_offset + a->repl_offset;
		if (debug)
			alternative_dump(old, new, a->instrlen, a->type, a->data);
		s390_kernel_write(old, new, a->instrlen);
	}
}

Annotation

Implementation Notes