arch/s390/kernel/uprobes.c

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

File Facts

System
Linux kernel
Corpus path
arch/s390/kernel/uprobes.c
Extension
.c
Size
9865 bytes
Lines
381
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 insn_ril {
	u8 opc0;
	u8 reg	: 4;
	u8 opc1 : 4;
	s32 disp;
} __packed;

union split_register {
	u64 u64;
	u32 u32[2];
	u16 u16[4];
	s64 s64;
	s32 s32[2];
	s16 s16[4];
};

/*
 * If user per registers are setup to trace storage alterations and an
 * emulated store took place on a fitting address a user trap is generated.
 */
static void sim_stor_event(struct pt_regs *regs, void *addr, int len)
{
	if (!(regs->psw.mask & PSW_MASK_PER))
		return;
	if (!(current->thread.per_user.control & PER_EVENT_STORE))
		return;
	if ((void *)current->thread.per_user.start > (addr + len))
		return;
	if ((void *)current->thread.per_user.end < addr)
		return;
	current->thread.per_event.address = regs->psw.addr;
	current->thread.per_event.cause = PER_EVENT_STORE >> 16;
	set_thread_flag(TIF_PER_TRAP);
}

/*
 * pc relative instructions are emulated, since parameters may not be
 * accessible from the xol area due to range limitations.
 */
static void handle_insn_ril(struct arch_uprobe *auprobe, struct pt_regs *regs)
{
	union split_register *rx;
	struct insn_ril *insn;
	unsigned int ilen;
	void *uptr;
	int rc = 0;

	insn = (struct insn_ril *) &auprobe->insn;
	rx = (union split_register *) &regs->gprs[insn->reg];
	uptr = (void *)(regs->psw.addr + (insn->disp * 2));
	ilen = insn_length(insn->opc0);

	switch (insn->opc0) {
	case 0xc0:
		switch (insn->opc1) {
		case 0x00: /* larl */
			rx->u64 = (unsigned long)uptr;
			break;
		}
		break;
	case 0xc4:
		switch (insn->opc1) {
		case 0x02: /* llhrl */
			rc = emu_load_ril((u16 __user *)uptr, &rx->u32[1]);
			break;
		case 0x04: /* lghrl */
			rc = emu_load_ril((s16 __user *)uptr, &rx->u64);
			break;
		case 0x05: /* lhrl */
			rc = emu_load_ril((s16 __user *)uptr, &rx->u32[1]);
			break;
		case 0x06: /* llghrl */
			rc = emu_load_ril((u16 __user *)uptr, &rx->u64);
			break;
		case 0x08: /* lgrl */
			rc = emu_load_ril((u64 __user *)uptr, &rx->u64);
			break;
		case 0x0c: /* lgfrl */
			rc = emu_load_ril((s32 __user *)uptr, &rx->u64);
			break;
		case 0x0d: /* lrl */
			rc = emu_load_ril((u32 __user *)uptr, &rx->u32[1]);
			break;
		case 0x0e: /* llgfrl */
			rc = emu_load_ril((u32 __user *)uptr, &rx->u64);
			break;
		case 0x07: /* sthrl */
			rc = emu_store_ril(regs, (u16 __user *)uptr, &rx->u16[3]);
			break;
		case 0x0b: /* stgrl */

Annotation

Implementation Notes