summaryrefslogtreecommitdiff
path: root/arch/um
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2023-04-14 15:46:39 +0200
committerRichard Weinberger <richard@nod.at>2023-04-20 23:08:43 +0200
commit6032aca0deb9c138df122192f8ef02de1fdccf25 (patch)
treef9acfe2a2c09cfa1b3a86351b8bdf2ccd8fa48ef /arch/um
parentfc54a4f15988e228cf88f888483e985c5f35031e (diff)
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>
Diffstat (limited to 'arch/um')
-rw-r--r--arch/um/include/shared/as-layout.h3
-rw-r--r--arch/um/kernel/skas/clone.c5
-rw-r--r--arch/um/kernel/skas/mmu.c6
-rw-r--r--arch/um/kernel/um_arch.c10
-rw-r--r--arch/um/os-Linux/skas/process.c6
5 files changed, 18 insertions, 12 deletions
diff --git a/arch/um/include/shared/as-layout.h b/arch/um/include/shared/as-layout.h
index 9a0bd648d872..9ec3015bc5e2 100644
--- a/arch/um/include/shared/as-layout.h
+++ b/arch/um/include/shared/as-layout.h
@@ -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__
diff --git a/arch/um/kernel/skas/clone.c b/arch/um/kernel/skas/clone.c
index ff5061f29167..62435187dda4 100644
--- a/arch/um/kernel/skas/clone.c
+++ b/arch/um/kernel/skas/clone.c
@@ -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;
diff --git a/arch/um/kernel/skas/mmu.c b/arch/um/kernel/skas/mmu.c
index 125df465e8ea..656fe16c9b63 100644
--- a/arch/um/kernel/skas/mmu.c
+++ b/arch/um/kernel/skas/mmu.c
@@ -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);
}
diff --git a/arch/um/kernel/um_arch.c b/arch/um/kernel/um_arch.c
index 8dcda617b8bf..0a23a98d4ca0 100644
--- a/arch/um/kernel/um_arch.c
+++ b/arch/um/kernel/um_arch.c
@@ -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
diff --git a/arch/um/os-Linux/skas/process.c b/arch/um/os-Linux/skas/process.c
index b1ea53285af1..9464833e741a 100644
--- a/arch/um/os-Linux/skas/process.c
+++ b/arch/um/os-Linux/skas/process.c
@@ -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;