arch/x86/entry/vdso/vma.c

Source file repositories/reference/linux-study-clean/arch/x86/entry/vdso/vma.c

File Facts

System
Linux kernel
Corpus path
arch/x86/entry/vdso/vma.c
Extension
.c
Size
7800 bytes
Lines
307
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

static inline void vdso_futex_robust_unlock_update_ips(void) { }
#endif

static int vdso_mremap(const struct vm_special_mapping *sm,
		struct vm_area_struct *new_vma)
{
	const struct vdso_image *image = current->mm->context.vdso_image;

	vdso_fix_landing(image, new_vma);
	current->mm->context.vdso = (void __user *)new_vma->vm_start;
	vdso_futex_robust_unlock_update_ips();

	return 0;
}

static vm_fault_t vvar_vclock_fault(const struct vm_special_mapping *sm,
				    struct vm_area_struct *vma, struct vm_fault *vmf)
{
	switch (vmf->pgoff) {
	case VDSO_PAGE_PVCLOCK_OFFSET:
	{
		struct pvclock_vsyscall_time_info *pvti =
			pvclock_get_pvti_cpu0_va();

		if (pvti && vclock_was_used(VDSO_CLOCKMODE_PVCLOCK))
			return vmf_insert_pfn_prot(vma, vmf->address,
					__pa(pvti) >> PAGE_SHIFT,
					pgprot_decrypted(vma->vm_page_prot));
		break;
	}
	case VDSO_PAGE_HVCLOCK_OFFSET:
	{
		unsigned long pfn = hv_get_tsc_pfn();
		if (pfn && vclock_was_used(VDSO_CLOCKMODE_HVCLOCK))
			return vmf_insert_pfn(vma, vmf->address, pfn);
		break;
	}
	}

	return VM_FAULT_SIGBUS;
}

static const struct vm_special_mapping vdso_mapping = {
	.name = "[vdso]",
	.fault = vdso_fault,
	.mremap = vdso_mremap,
};
static const struct vm_special_mapping vvar_vclock_mapping = {
	.name = "[vvar_vclock]",
	.fault = vvar_vclock_fault,
};

/*
 * Add vdso and vvar mappings to current process.
 * @image          - blob to map
 * @addr           - request a specific address (zero to map at free addr)
 */
static int map_vdso(const struct vdso_image *image, unsigned long addr)
{
	struct mm_struct *mm = current->mm;
	struct vm_area_struct *vma;
	unsigned long text_start;
	int ret = 0;

	if (mmap_write_lock_killable(mm))
		return -EINTR;

	addr = get_unmapped_area(NULL, addr,
				 image->size + __VDSO_PAGES * PAGE_SIZE, 0, 0);
	if (IS_ERR_VALUE(addr)) {
		ret = addr;
		goto up_fail;
	}

	text_start = addr + __VDSO_PAGES * PAGE_SIZE;

	/*
	 * MAYWRITE to allow gdb to COW and set breakpoints
	 */
	vma = _install_special_mapping(mm,
				       text_start,
				       image->size,
				       VM_READ|VM_EXEC|
				       VM_MAYREAD|VM_MAYWRITE|VM_MAYEXEC|
				       VM_SEALED_SYSMAP,
				       &vdso_mapping);

	if (IS_ERR(vma)) {
		ret = PTR_ERR(vma);
		goto up_fail;

Annotation

Implementation Notes