fa28237cfc
Using 64k pages on 64-bit PowerPC systems makes life difficult for emulators that are trying to emulate an ISA, such as x86, which use a smaller page size, since the emulator can no longer use the MMU and the normal system calls for controlling page protections. Of course, the emulator can emulate the MMU by checking and possibly remapping the address for each memory access in software, but that is pretty slow. This provides a facility for such programs to control the access permissions on individual 4k sub-pages of 64k pages. The idea is that the emulator supplies an array of protection masks to apply to a specified range of virtual addresses. These masks are applied at the level where hardware PTEs are inserted into the hardware page table based on the Linux PTEs, so the Linux PTEs are not affected. Note that this new mechanism does not allow any access that would otherwise be prohibited; it can only prohibit accesses that would otherwise be allowed. This new facility is only available on 64-bit PowerPC and only when the kernel is configured for 64k pages. The masks are supplied using a new subpage_prot system call, which takes a starting virtual address and length, and a pointer to an array of protection masks in memory. The array has a 32-bit word per 64k page to be protected; each 32-bit word consists of 16 2-bit fields, for which 0 allows any access (that is otherwise allowed), 1 prevents write accesses, and 2 or 3 prevent any access. Implicit in this is that the regions of the address space that are protected are switched to use 4k hardware pages rather than 64k hardware pages (on machines with hardware 64k page support). In fact the whole process is switched to use 4k hardware pages when the subpage_prot system call is used, but this could be improved in future to switch only the affected segments. The subpage protection bits are stored in a 3 level tree akin to the page table tree. The top level of this tree is stored in a structure that is appended to the top level of the page table tree, i.e., the pgd array. Since it will often only be 32-bit addresses (below 4GB) that are protected, the pointers to the first four bottom level pages are also stored in this structure (each bottom level page contains the protection bits for 1GB of address space), so the protection bits for addresses below 4GB can be accessed with one fewer loads than those for higher addresses. Signed-off-by: Paul Mackerras <paulus@samba.org>
160 lines
4.4 KiB
C
160 lines
4.4 KiB
C
|
|
#include <linux/linkage.h>
|
|
#include <linux/errno.h>
|
|
|
|
#include <asm/unistd.h>
|
|
|
|
/* we can't #include <linux/syscalls.h> here,
|
|
but tell gcc to not warn with -Wmissing-prototypes */
|
|
asmlinkage long sys_ni_syscall(void);
|
|
|
|
/*
|
|
* Non-implemented system calls get redirected here.
|
|
*/
|
|
asmlinkage long sys_ni_syscall(void)
|
|
{
|
|
return -ENOSYS;
|
|
}
|
|
|
|
cond_syscall(sys_nfsservctl);
|
|
cond_syscall(sys_quotactl);
|
|
cond_syscall(sys32_quotactl);
|
|
cond_syscall(sys_acct);
|
|
cond_syscall(sys_lookup_dcookie);
|
|
cond_syscall(sys_swapon);
|
|
cond_syscall(sys_swapoff);
|
|
cond_syscall(sys_kexec_load);
|
|
cond_syscall(compat_sys_kexec_load);
|
|
cond_syscall(sys_init_module);
|
|
cond_syscall(sys_delete_module);
|
|
cond_syscall(sys_socketpair);
|
|
cond_syscall(sys_bind);
|
|
cond_syscall(sys_listen);
|
|
cond_syscall(sys_accept);
|
|
cond_syscall(sys_connect);
|
|
cond_syscall(sys_getsockname);
|
|
cond_syscall(sys_getpeername);
|
|
cond_syscall(sys_sendto);
|
|
cond_syscall(sys_send);
|
|
cond_syscall(sys_recvfrom);
|
|
cond_syscall(sys_recv);
|
|
cond_syscall(sys_socket);
|
|
cond_syscall(sys_setsockopt);
|
|
cond_syscall(compat_sys_setsockopt);
|
|
cond_syscall(sys_getsockopt);
|
|
cond_syscall(compat_sys_getsockopt);
|
|
cond_syscall(sys_shutdown);
|
|
cond_syscall(sys_sendmsg);
|
|
cond_syscall(compat_sys_sendmsg);
|
|
cond_syscall(sys_recvmsg);
|
|
cond_syscall(compat_sys_recvmsg);
|
|
cond_syscall(sys_socketcall);
|
|
cond_syscall(sys_futex);
|
|
cond_syscall(compat_sys_futex);
|
|
cond_syscall(sys_set_robust_list);
|
|
cond_syscall(compat_sys_set_robust_list);
|
|
cond_syscall(sys_get_robust_list);
|
|
cond_syscall(compat_sys_get_robust_list);
|
|
cond_syscall(sys_epoll_create);
|
|
cond_syscall(sys_epoll_ctl);
|
|
cond_syscall(sys_epoll_wait);
|
|
cond_syscall(sys_epoll_pwait);
|
|
cond_syscall(sys_semget);
|
|
cond_syscall(sys_semop);
|
|
cond_syscall(sys_semtimedop);
|
|
cond_syscall(sys_semctl);
|
|
cond_syscall(sys_msgget);
|
|
cond_syscall(sys_msgsnd);
|
|
cond_syscall(sys_msgrcv);
|
|
cond_syscall(sys_msgctl);
|
|
cond_syscall(sys_shmget);
|
|
cond_syscall(sys_shmat);
|
|
cond_syscall(sys_shmdt);
|
|
cond_syscall(sys_shmctl);
|
|
cond_syscall(sys_mq_open);
|
|
cond_syscall(sys_mq_unlink);
|
|
cond_syscall(sys_mq_timedsend);
|
|
cond_syscall(sys_mq_timedreceive);
|
|
cond_syscall(sys_mq_notify);
|
|
cond_syscall(sys_mq_getsetattr);
|
|
cond_syscall(compat_sys_mq_open);
|
|
cond_syscall(compat_sys_mq_timedsend);
|
|
cond_syscall(compat_sys_mq_timedreceive);
|
|
cond_syscall(compat_sys_mq_notify);
|
|
cond_syscall(compat_sys_mq_getsetattr);
|
|
cond_syscall(sys_mbind);
|
|
cond_syscall(sys_get_mempolicy);
|
|
cond_syscall(sys_set_mempolicy);
|
|
cond_syscall(compat_sys_mbind);
|
|
cond_syscall(compat_sys_get_mempolicy);
|
|
cond_syscall(compat_sys_set_mempolicy);
|
|
cond_syscall(sys_add_key);
|
|
cond_syscall(sys_request_key);
|
|
cond_syscall(sys_keyctl);
|
|
cond_syscall(compat_sys_keyctl);
|
|
cond_syscall(compat_sys_socketcall);
|
|
cond_syscall(sys_inotify_init);
|
|
cond_syscall(sys_inotify_add_watch);
|
|
cond_syscall(sys_inotify_rm_watch);
|
|
cond_syscall(sys_migrate_pages);
|
|
cond_syscall(sys_move_pages);
|
|
cond_syscall(sys_chown16);
|
|
cond_syscall(sys_fchown16);
|
|
cond_syscall(sys_getegid16);
|
|
cond_syscall(sys_geteuid16);
|
|
cond_syscall(sys_getgid16);
|
|
cond_syscall(sys_getgroups16);
|
|
cond_syscall(sys_getresgid16);
|
|
cond_syscall(sys_getresuid16);
|
|
cond_syscall(sys_getuid16);
|
|
cond_syscall(sys_lchown16);
|
|
cond_syscall(sys_setfsgid16);
|
|
cond_syscall(sys_setfsuid16);
|
|
cond_syscall(sys_setgid16);
|
|
cond_syscall(sys_setgroups16);
|
|
cond_syscall(sys_setregid16);
|
|
cond_syscall(sys_setresgid16);
|
|
cond_syscall(sys_setresuid16);
|
|
cond_syscall(sys_setreuid16);
|
|
cond_syscall(sys_setuid16);
|
|
cond_syscall(sys_vm86old);
|
|
cond_syscall(sys_vm86);
|
|
cond_syscall(compat_sys_ipc);
|
|
cond_syscall(compat_sys_sysctl);
|
|
|
|
/* arch-specific weak syscall entries */
|
|
cond_syscall(sys_pciconfig_read);
|
|
cond_syscall(sys_pciconfig_write);
|
|
cond_syscall(sys_pciconfig_iobase);
|
|
cond_syscall(sys32_ipc);
|
|
cond_syscall(sys32_sysctl);
|
|
cond_syscall(ppc_rtas);
|
|
cond_syscall(sys_spu_run);
|
|
cond_syscall(sys_spu_create);
|
|
cond_syscall(sys_subpage_prot);
|
|
|
|
/* mmu depending weak syscall entries */
|
|
cond_syscall(sys_mprotect);
|
|
cond_syscall(sys_msync);
|
|
cond_syscall(sys_mlock);
|
|
cond_syscall(sys_munlock);
|
|
cond_syscall(sys_mlockall);
|
|
cond_syscall(sys_munlockall);
|
|
cond_syscall(sys_mincore);
|
|
cond_syscall(sys_madvise);
|
|
cond_syscall(sys_mremap);
|
|
cond_syscall(sys_remap_file_pages);
|
|
cond_syscall(compat_sys_move_pages);
|
|
cond_syscall(compat_sys_migrate_pages);
|
|
|
|
/* block-layer dependent */
|
|
cond_syscall(sys_bdflush);
|
|
cond_syscall(sys_ioprio_set);
|
|
cond_syscall(sys_ioprio_get);
|
|
|
|
/* New file descriptors */
|
|
cond_syscall(sys_signalfd);
|
|
cond_syscall(sys_timerfd);
|
|
cond_syscall(compat_sys_signalfd);
|
|
cond_syscall(compat_sys_timerfd);
|
|
cond_syscall(sys_eventfd);
|