arch/x86/include/asm/uaccess_64.h

Source file repositories/reference/linux-study-clean/arch/x86/include/asm/uaccess_64.h

File Facts

System
Linux kernel
Corpus path
arch/x86/include/asm/uaccess_64.h
Extension
.h
Size
5526 bytes
Lines
211
Domain
Architecture Layer
Bucket
arch/x86
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

#ifndef _ASM_X86_UACCESS_64_H
#define _ASM_X86_UACCESS_64_H

/*
 * User space memory access functions
 */
#include <linux/compiler.h>
#include <linux/lockdep.h>
#include <linux/kasan-checks.h>
#include <asm/alternative.h>
#include <asm/cpufeatures.h>
#include <asm/page.h>
#include <asm/percpu.h>

#ifdef MODULE
  #define runtime_const_ptr(sym) (sym)
#else
  #include <asm/runtime-const.h>
#endif
extern unsigned long USER_PTR_MAX;

#ifdef CONFIG_ADDRESS_MASKING
/*
 * Mask out tag bits from the address.
 */
static inline unsigned long __untagged_addr(unsigned long addr)
{
	asm_inline (ALTERNATIVE("", "and " __percpu_arg([mask]) ", %[addr]",
				X86_FEATURE_LAM)
	     : [addr] "+r" (addr)
	     : [mask] "m" (__my_cpu_var(tlbstate_untag_mask)));

	return addr;
}

#define untagged_addr(addr)	({					\
	unsigned long __addr = (__force unsigned long)(addr);		\
	(__force __typeof__(addr))__untagged_addr(__addr);		\
})

static inline unsigned long __untagged_addr_remote(struct mm_struct *mm,
						   unsigned long addr)
{
	mmap_assert_locked(mm);
	return addr & (mm)->context.untag_mask;
}

#define untagged_addr_remote(mm, addr)	({				\
	unsigned long __addr = (__force unsigned long)(addr);		\
	(__force __typeof__(addr))__untagged_addr_remote(mm, __addr);	\
})

#endif

#define valid_user_address(x) \
	likely((__force unsigned long)(x) <= runtime_const_ptr(USER_PTR_MAX))

/*
 * Masking the user address is an alternative to a conditional
 * user_access_begin that can avoid the fencing. This only works
 * for dense accesses starting at the address.
 */
static inline void __user *mask_user_address(const void __user *ptr)
{
	void __user *ret;
	asm("cmp %1,%0\n\t"
	    "cmova %1,%0"
		:"=r" (ret)
		:"r" (runtime_const_ptr(USER_PTR_MAX)),
		 "0" (ptr));
	return ret;
}
#define masked_user_access_begin(x) ({				\
	auto __masked_ptr = (x);				\
	__masked_ptr = mask_user_address(__masked_ptr);		\
	__uaccess_begin(); __masked_ptr; })

/*
 * User pointers can have tag bits on x86-64.  This scheme tolerates
 * arbitrary values in those bits rather then masking them off.
 *
 * Enforce two rules:
 * 1. 'ptr' must be in the user part of the address space
 * 2. 'ptr+size' must not overflow into kernel addresses
 *
 * Note that we always have at least one guard page between the
 * max user address and the non-canonical gap, allowing us to
 * ignore small sizes entirely.
 *
 * In fact, we could probably remove the size check entirely, since

Annotation

Implementation Notes