// SPDX-License-Identifier: GPL-2.0 /* linux/arch/sparc64/kernel/sys_sparc.c * * This file contains various random system calls that * have a non-standard calling sequence on the Linux/sparc * platform.
*/
/* Does addr --> addr+len fall within 4GB of the VA-space hole or * overflow past the end of the 64-bit address space?
*/ staticinlineint invalid_64bit_range(unsignedlong addr, unsignedlong len)
{ unsignedlong va_exclude_start, va_exclude_end;
/* These functions differ from the default implementations in * mm/mmap.c in two ways: * * 1) For file backed MAP_SHARED mmap()'s we D-cache color align, * for fixed such mappings we just validate what the user gave us. * 2) For 64-bit tasks we avoid mapping anything within 4GB of * the spitfire/niagara VA-hole.
*/
staticinlineunsignedlong COLOR_ALIGN(unsignedlong addr, unsignedlong pgoff)
{ unsignedlong base = (addr+SHMLBA-1)&~(SHMLBA-1); unsignedlong off = (pgoff<<PAGE_SHIFT) & (SHMLBA-1);
if (filp && is_file_hugepages(filp))
file_hugepage = true;
if (flags & MAP_FIXED) { /* We do not accept a shared mapping if it would violate * cache aliasing constraints.
*/ if (!file_hugepage && (flags & MAP_SHARED) &&
((addr - (pgoff << PAGE_SHIFT)) & (SHMLBA - 1))) return -EINVAL; return addr;
}
if (test_thread_flag(TIF_32BIT))
task_size = STACK_TOP32; if (unlikely(len > task_size || len >= VA_EXCLUDE_START)) return -ENOMEM;
/* This should only ever run for 32-bit processes. */
BUG_ON(!test_thread_flag(TIF_32BIT));
if (filp && is_file_hugepages(filp))
file_hugepage = true;
if (flags & MAP_FIXED) { /* We do not accept a shared mapping if it would violate * cache aliasing constraints.
*/ if (!file_hugepage && (flags & MAP_SHARED) &&
((addr - (pgoff << PAGE_SHIFT)) & (SHMLBA - 1))) return -EINVAL; return addr;
}
/* * A failed mmap() very likely causes application failure, * so fall back to the bottom-up function here. This scenario * can happen with large stack limits and large mmap() * allocations.
*/ if (addr & ~PAGE_MASK) {
VM_BUG_ON(addr != -ENOMEM);
info.flags = 0;
info.low_limit = TASK_UNMAPPED_BASE;
info.high_limit = STACK_TOP32;
addr = vm_unmapped_area(&info);
}
return addr;
}
/* Try to align mapping such that we align it as much as possible. */ unsignedlong get_fb_unmapped_area(struct file *filp, unsignedlong orig_addr, unsignedlong len, unsignedlong pgoff, unsignedlong flags)
{ unsignedlong align_goal, addr = -ENOMEM;
if (flags & MAP_FIXED) { /* Ok, don't mess with it. */ return mm_get_unmapped_area(current->mm, NULL, orig_addr, len, pgoff, flags);
}
flags &= ~MAP_SHARED;
/* Mapping is smaller than 64K or larger areas could not * be obtained.
*/ if (addr & ~PAGE_MASK)
addr = mm_get_unmapped_area(current->mm, NULL, orig_addr, len, pgoff, flags);
/* * Fall back to the standard layout if the personality * bit is set, or if the expected stack growth is unlimited:
*/
gap = rlim_stack->rlim_cur; if (!test_thread_flag(TIF_32BIT) ||
(current->personality & ADDR_COMPAT_LAYOUT) ||
gap == RLIM_INFINITY ||
sysctl_legacy_va_layout) {
mm->mmap_base = TASK_UNMAPPED_BASE + random_factor;
clear_bit(MMF_TOPDOWN, &mm->flags);
} else { /* We know it's 32-bit */ unsignedlong task_size = STACK_TOP32;
if (gap < 128 * 1024 * 1024)
gap = 128 * 1024 * 1024; if (gap > (task_size / 6 * 5))
gap = (task_size / 6 * 5);
/* * sys_pipe() is the normal C calling standard for creating * a pipe. It's not the way unix traditionally does this, though.
*/
SYSCALL_DEFINE0(sparc_pipe)
{ int fd[2]; int error;
/* Copy the user data space into the kernel copy * structure. But bear in mind that the structures * may change
*/ if (copy_from_user(&txc, txc_p, sizeof(txc))) return -EFAULT;
/* * override for sparc64 specific timeval type: tv_usec * is 32 bit wide instead of 64-bit in __kernel_timex
*/
txc.time.tv_usec = tv->tv_usec;
ret = do_adjtimex(&txc);
tv->tv_usec = txc.time.tv_usec;
if (!IS_ENABLED(CONFIG_POSIX_TIMERS)) {
pr_err_once("process %d (%s) attempted a POSIX timer syscall " "while CONFIG_POSIX_TIMERS is not set\n",
current->pid, current->comm);
return -ENOSYS;
}
/* Copy the user data space into the kernel copy * structure. But bear in mind that the structures * may change
*/ if (copy_from_user(&txc, txc_p, sizeof(txc))) return -EFAULT;
/* * override for sparc64 specific timeval type: tv_usec * is 32 bit wide instead of 64-bit in __kernel_timex
*/
txc.time.tv_usec = tv->tv_usec;
ret = do_clock_adjtime(which_clock, &txc);
tv->tv_usec = txc.time.tv_usec;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.