arch/powerpc/lib/sstep.c

Source file repositories/reference/linux-study-clean/arch/powerpc/lib/sstep.c

File Facts

System
Linux kernel
Corpus path
arch/powerpc/lib/sstep.c
Extension
.c
Size
83817 bytes
Lines
3661
Domain
Architecture Layer
Bucket
arch/powerpc
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

switch (c) {
		case 1:
			unsafe_get_user(*dest, (u8 __user *)ea, Efault);
			break;
		case 2:
			unsafe_get_user(*(u16 *)dest, (u16 __user *)ea, Efault);
			break;
		case 4:
			unsafe_get_user(*(u32 *)dest, (u32 __user *)ea, Efault);
			break;
#ifdef __powerpc64__
		case 8:
			unsafe_get_user(*(u64 *)dest, (u64 __user *)ea, Efault);
			break;
#endif
		}
		dest += c;
		ea += c;
	}
	return 0;

Efault:
	regs->dar = ea;
	return -EFAULT;
}

static nokprobe_inline int copy_mem_in(u8 *dest, unsigned long ea, int nb, struct pt_regs *regs)
{
	void __user *uea = (void __user *)ea;

	if (is_kernel_addr(ea))
		return __copy_mem_in(dest, ea, nb, regs);

	scoped_user_read_access_size(uea, nb, efault)
		return __copy_mem_in(dest, (unsigned long)uea, nb, regs);

efault:
	regs->dar = ea;
	return -EFAULT;
}

static nokprobe_inline int read_mem_unaligned(unsigned long *dest,
					      unsigned long ea, int nb,
					      struct pt_regs *regs)
{
	union {
		unsigned long ul;
		u8 b[sizeof(unsigned long)];
	} u;
	int i;
	int err;

	u.ul = 0;
	i = IS_BE ? sizeof(unsigned long) - nb : 0;
	err = copy_mem_in(&u.b[i], ea, nb, regs);
	if (!err)
		*dest = u.ul;
	return err;
}

/*
 * Read memory at address ea for nb bytes, return 0 for success
 * or -EFAULT if an error occurred.  N.B. nb must be 1, 2, 4 or 8.
 * If nb < sizeof(long), the result is right-justified on BE systems.
 */
static int read_mem(unsigned long *dest, unsigned long ea, int nb,
			      struct pt_regs *regs)
{
	if (!address_ok(regs, ea, nb))
		return -EFAULT;
	if ((ea & (nb - 1)) == 0)
		return read_mem_aligned(dest, ea, nb, regs);
	return read_mem_unaligned(dest, ea, nb, regs);
}
NOKPROBE_SYMBOL(read_mem);

static __always_inline int
__write_mem_aligned(unsigned long val, unsigned long ea, int nb, struct pt_regs *regs)
{
	switch (nb) {
	case 1:
		unsafe_put_user(val, (unsigned char __user *)ea, Efault);
		break;
	case 2:
		unsafe_put_user(val, (unsigned short __user *)ea, Efault);
		break;
	case 4:
		unsafe_put_user(val, (unsigned int __user *)ea, Efault);
		break;
#ifdef __powerpc64__

Annotation

Implementation Notes