arch/s390/include/asm/alternative.h

Source file repositories/reference/linux-study-clean/arch/s390/include/asm/alternative.h

File Facts

System
Linux kernel
Corpus path
arch/s390/include/asm/alternative.h
Extension
.h
Size
7424 bytes
Lines
239
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_instr {
	s32 instr_offset;	/* original instruction */
	s32 repl_offset;	/* offset to replacement instruction */
	union {
		u32 feature;	/* feature required for replacement */
		struct {
			u32 ctx	 : 4;  /* context */
			u32 type : 8;  /* type of alternative */
			u32 data : 20; /* patching information */
		};
	};
	u8  instrlen;		/* length of original instruction */
} __packed;

extern struct alt_instr __alt_instructions[], __alt_instructions_end[];

void __apply_alternatives(struct alt_instr *start, struct alt_instr *end, unsigned int ctx);

static inline void apply_alternative_instructions(void)
{
	__apply_alternatives(__alt_instructions, __alt_instructions_end, ALT_CTX_LATE);
}

static inline void apply_alternatives(struct alt_instr *start, struct alt_instr *end)
{
	__apply_alternatives(start, end, ALT_CTX_ALL);
}

/*
 * +---------------------------------+
 * |661:			     |662:
 * | oldinstr			     |
 * +---------------------------------+
 *
 * .altinstr_replacement section
 * +---------------------------------+
 * |6641:			     |6651:
 * | alternative instr 1	     |
 * +---------------------------------+
 * |6642:			     |6652:
 * | alternative instr 2	     |
 * +---------------------------------+
 *
 * .altinstructions section
 * +---------------------------------+
 * | alt_instr entries for each      |
 * | alternative instr		     |
 * +---------------------------------+
 */

#define b_altinstr(num)		"664"#num
#define e_altinstr(num)		"665"#num
#define oldinstr_len		"662b-661b"
#define altinstr_len(num)	e_altinstr(num)"b-"b_altinstr(num)"b"

#define OLDINSTR(oldinstr) \
	"661:\n\t" oldinstr "\n662:\n"

#define ALTINSTR_ENTRY(feature, num)					\
	"\t.long 661b - .\n"			/* old instruction */	\
	"\t.long " b_altinstr(num)"b - .\n"	/* alt instruction */	\
	"\t.long " __stringify(feature) "\n"	/* feature	   */	\
	"\t.byte " oldinstr_len "\n"		/* instruction len */	\
	"\t.org . - (" oldinstr_len ") & 1\n"				\
	"\t.org . - (" oldinstr_len ") + (" altinstr_len(num) ")\n"	\
	"\t.org . - (" altinstr_len(num) ") + (" oldinstr_len ")\n"

#define ALTINSTR_REPLACEMENT(altinstr, num)	/* replacement */	\
	b_altinstr(num)":\n\t" altinstr "\n" e_altinstr(num) ":\n"

/* alternative assembly primitive: */
#define ALTERNATIVE(oldinstr, altinstr, feature) \
	".pushsection .altinstr_replacement, \"ax\"\n"			\
	ALTINSTR_REPLACEMENT(altinstr, 1)				\
	".popsection\n"							\
	OLDINSTR(oldinstr)						\
	".pushsection .altinstructions,\"a\"\n"				\
	ALTINSTR_ENTRY(feature, 1)					\
	".popsection\n"

#define ALTERNATIVE_2(oldinstr, altinstr1, feature1, altinstr2, feature2)\
	".pushsection .altinstr_replacement, \"ax\"\n"			\
	ALTINSTR_REPLACEMENT(altinstr1, 1)				\
	ALTINSTR_REPLACEMENT(altinstr2, 2)				\
	".popsection\n"							\
	OLDINSTR(oldinstr)						\
	".pushsection .altinstructions,\"a\"\n"				\
	ALTINSTR_ENTRY(feature1, 1)					\
	ALTINSTR_ENTRY(feature2, 2)					\
	".popsection\n"

Annotation

Implementation Notes