um: make stub data pages size tweakable
There's a lot of code here that hard-codes that the data is a single page, and right now that seems to be sufficient, but to make it easier to change this in the future, add a new STUB_DATA_PAGES constant and use it throughout the code. Signed-off-by: Johannes Berg <johannes.berg@intel.com> Signed-off-by: Richard Weinberger <richard@nod.at>
This commit is contained in:
parent
fc54a4f159
commit
6032aca0de
arch
um
x86/um
@ -23,7 +23,8 @@
|
||||
#define STUB_START stub_start
|
||||
#define STUB_CODE STUB_START
|
||||
#define STUB_DATA (STUB_CODE + UM_KERN_PAGE_SIZE)
|
||||
#define STUB_END (STUB_DATA + UM_KERN_PAGE_SIZE)
|
||||
#define STUB_DATA_PAGES 1 /* must be a power of two */
|
||||
#define STUB_END (STUB_DATA + STUB_DATA_PAGES * UM_KERN_PAGE_SIZE)
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
|
@ -24,11 +24,12 @@
|
||||
void __attribute__ ((__section__ (".__syscall_stub")))
|
||||
stub_clone_handler(void)
|
||||
{
|
||||
struct stub_data *data = get_stub_page();
|
||||
struct stub_data *data = get_stub_data();
|
||||
long err;
|
||||
|
||||
err = stub_syscall2(__NR_clone, CLONE_PARENT | CLONE_FILES | SIGCHLD,
|
||||
(unsigned long)data + UM_KERN_PAGE_SIZE / 2);
|
||||
(unsigned long)data +
|
||||
STUB_DATA_PAGES * UM_KERN_PAGE_SIZE / 2);
|
||||
if (err) {
|
||||
data->parent_err = err;
|
||||
goto done;
|
||||
|
@ -21,7 +21,7 @@ int init_new_context(struct task_struct *task, struct mm_struct *mm)
|
||||
unsigned long stack = 0;
|
||||
int ret = -ENOMEM;
|
||||
|
||||
stack = get_zeroed_page(GFP_KERNEL);
|
||||
stack = __get_free_pages(GFP_KERNEL | __GFP_ZERO, ilog2(STUB_DATA_PAGES));
|
||||
if (stack == 0)
|
||||
goto out;
|
||||
|
||||
@ -52,7 +52,7 @@ int init_new_context(struct task_struct *task, struct mm_struct *mm)
|
||||
|
||||
out_free:
|
||||
if (to_mm->id.stack != 0)
|
||||
free_page(to_mm->id.stack);
|
||||
free_pages(to_mm->id.stack, ilog2(STUB_DATA_PAGES));
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
@ -74,6 +74,6 @@ void destroy_context(struct mm_struct *mm)
|
||||
}
|
||||
os_kill_ptraced_process(mmu->id.u.pid, 1);
|
||||
|
||||
free_page(mmu->id.stack);
|
||||
free_pages(mmu->id.stack, ilog2(STUB_DATA_PAGES));
|
||||
free_ldt(mmu);
|
||||
}
|
||||
|
@ -326,9 +326,13 @@ int __init linux_main(int argc, char **argv)
|
||||
add_arg(DEFAULT_COMMAND_LINE_CONSOLE);
|
||||
|
||||
host_task_size = os_get_top_address();
|
||||
/* reserve two pages for the stubs */
|
||||
host_task_size -= 2 * PAGE_SIZE;
|
||||
stub_start = host_task_size;
|
||||
/* reserve a few pages for the stubs (taking care of data alignment) */
|
||||
/* align the data portion */
|
||||
BUILD_BUG_ON(!is_power_of_2(STUB_DATA_PAGES));
|
||||
stub_start = (host_task_size - 1) & ~(STUB_DATA_PAGES * PAGE_SIZE - 1);
|
||||
/* another page for the code portion */
|
||||
stub_start -= PAGE_SIZE;
|
||||
host_task_size = stub_start;
|
||||
|
||||
/*
|
||||
* TASK_SIZE needs to be PGDIR_SIZE aligned or else exit_mmap craps
|
||||
|
@ -262,7 +262,7 @@ static int userspace_tramp(void *stack)
|
||||
if (stack != NULL) {
|
||||
fd = phys_mapping(uml_to_phys(stack), &offset);
|
||||
addr = mmap((void *) STUB_DATA,
|
||||
UM_KERN_PAGE_SIZE, PROT_READ | PROT_WRITE,
|
||||
STUB_DATA_PAGES * UM_KERN_PAGE_SIZE, PROT_READ | PROT_WRITE,
|
||||
MAP_FIXED | MAP_SHARED, fd, offset);
|
||||
if (addr == MAP_FAILED) {
|
||||
printk(UM_KERN_ERR "mapping segfault stack at 0x%lx failed, errno = %d\n",
|
||||
@ -277,7 +277,7 @@ static int userspace_tramp(void *stack)
|
||||
(unsigned long) stub_segv_handler -
|
||||
(unsigned long) __syscall_stub_start;
|
||||
|
||||
set_sigstack((void *) STUB_DATA, UM_KERN_PAGE_SIZE);
|
||||
set_sigstack((void *) STUB_DATA, STUB_DATA_PAGES * UM_KERN_PAGE_SIZE);
|
||||
sigemptyset(&sa.sa_mask);
|
||||
sa.sa_flags = SA_ONSTACK | SA_NODEFER | SA_SIGINFO;
|
||||
sa.sa_sigaction = (void *) v;
|
||||
@ -515,7 +515,7 @@ static int __init init_thread_regs(void)
|
||||
thread_regs[REGS_IP_INDEX] = STUB_CODE +
|
||||
(unsigned long) stub_clone_handler -
|
||||
(unsigned long) __syscall_stub_start;
|
||||
thread_regs[REGS_SP_INDEX] = STUB_DATA + UM_KERN_PAGE_SIZE -
|
||||
thread_regs[REGS_SP_INDEX] = STUB_DATA + STUB_DATA_PAGES * UM_KERN_PAGE_SIZE -
|
||||
sizeof(void *);
|
||||
#ifdef __SIGNAL_FRAMESIZE
|
||||
thread_regs[REGS_SP_INDEX] -= __SIGNAL_FRAMESIZE;
|
||||
|
@ -89,19 +89,19 @@ static inline void remap_stack_and_trap(void)
|
||||
"addl %4,%%ebx ; movl %%eax, (%%ebx) ;"
|
||||
"int $3"
|
||||
: :
|
||||
"g" (~(UM_KERN_PAGE_SIZE - 1)),
|
||||
"g" (~(STUB_DATA_PAGES * UM_KERN_PAGE_SIZE - 1)),
|
||||
"g" (STUB_MMAP_NR),
|
||||
"g" (UML_STUB_FIELD_FD),
|
||||
"g" (UML_STUB_FIELD_OFFSET),
|
||||
"g" (UML_STUB_FIELD_CHILD_ERR),
|
||||
"c" (UM_KERN_PAGE_SIZE),
|
||||
"c" (STUB_DATA_PAGES * UM_KERN_PAGE_SIZE),
|
||||
"d" (PROT_READ | PROT_WRITE),
|
||||
"S" (MAP_FIXED | MAP_SHARED)
|
||||
:
|
||||
"memory");
|
||||
}
|
||||
|
||||
static __always_inline void *get_stub_page(void)
|
||||
static __always_inline void *get_stub_data(void)
|
||||
{
|
||||
unsigned long ret;
|
||||
|
||||
@ -109,7 +109,7 @@ static __always_inline void *get_stub_page(void)
|
||||
"movl %%esp,%0 ;"
|
||||
"andl %1,%0"
|
||||
: "=a" (ret)
|
||||
: "g" (~(UM_KERN_PAGE_SIZE - 1)));
|
||||
: "g" (~(STUB_DATA_PAGES * UM_KERN_PAGE_SIZE - 1)));
|
||||
|
||||
return (void *)ret;
|
||||
}
|
||||
|
@ -98,18 +98,18 @@ static inline void remap_stack_and_trap(void)
|
||||
"int3"
|
||||
: :
|
||||
"g" (STUB_MMAP_NR),
|
||||
"g" (~(UM_KERN_PAGE_SIZE - 1)),
|
||||
"g" (~(STUB_DATA_PAGES * UM_KERN_PAGE_SIZE - 1)),
|
||||
"g" (MAP_FIXED | MAP_SHARED),
|
||||
"g" (UML_STUB_FIELD_FD),
|
||||
"g" (UML_STUB_FIELD_OFFSET),
|
||||
"g" (UML_STUB_FIELD_CHILD_ERR),
|
||||
"S" (UM_KERN_PAGE_SIZE),
|
||||
"S" (STUB_DATA_PAGES * UM_KERN_PAGE_SIZE),
|
||||
"d" (PROT_READ | PROT_WRITE)
|
||||
:
|
||||
__syscall_clobber, "r10", "r8", "r9");
|
||||
}
|
||||
|
||||
static __always_inline void *get_stub_page(void)
|
||||
static __always_inline void *get_stub_data(void)
|
||||
{
|
||||
unsigned long ret;
|
||||
|
||||
@ -117,7 +117,7 @@ static __always_inline void *get_stub_page(void)
|
||||
"movq %%rsp,%0 ;"
|
||||
"andq %1,%0"
|
||||
: "=a" (ret)
|
||||
: "g" (~(UM_KERN_PAGE_SIZE - 1)));
|
||||
: "g" (~(STUB_DATA_PAGES * UM_KERN_PAGE_SIZE - 1)));
|
||||
|
||||
return (void *)ret;
|
||||
}
|
||||
|
@ -11,7 +11,7 @@
|
||||
void __attribute__ ((__section__ (".__syscall_stub")))
|
||||
stub_segv_handler(int sig, siginfo_t *info, void *p)
|
||||
{
|
||||
struct faultinfo *f = get_stub_page();
|
||||
struct faultinfo *f = get_stub_data();
|
||||
ucontext_t *uc = p;
|
||||
|
||||
GET_FAULTINFO_FROM_MC(*f, &uc->uc_mcontext);
|
||||
|
Loading…
Reference in New Issue
Block a user