aboutsummaryrefslogtreecommitdiff
path: root/arch/um/kernel
diff options
context:
space:
mode:
authorBenjamin Berg <[email protected]>2024-09-19 14:45:09 +0200
committerJohannes Berg <[email protected]>2024-10-10 13:37:22 +0200
commit68b9883cc16ec2ce699d832ef60241b1a4e47d33 (patch)
tree643472cca34b474083cf41dd9859840648c2e8f8 /arch/um/kernel
parent830003c73d190259e45d0a99a0e3d14cb73e0af0 (diff)
um: Discover host_task_size from envp
When loading the UML binary, the host kernel will place the stack at the highest possible address. It will then map the program name and environment variables onto the start of the stack. As such, an easy way to figure out the host_task_size is to use the highest pointer to an environment variable as a reference. Ensure that this works by disabling address layout randomization and re-executing UML in case it was enabled. This increases the available TASK_SIZE for 64 bit UML considerably. Signed-off-by: Benjamin Berg <[email protected]> Link: https://patch.msgid.link/[email protected] Signed-off-by: Johannes Berg <[email protected]>
Diffstat (limited to 'arch/um/kernel')
-rw-r--r--arch/um/kernel/um_arch.c21
1 files changed, 19 insertions, 2 deletions
diff --git a/arch/um/kernel/um_arch.c b/arch/um/kernel/um_arch.c
index 4452df4f2c4b..38cbb41a64bc 100644
--- a/arch/um/kernel/um_arch.c
+++ b/arch/um/kernel/um_arch.c
@@ -302,7 +302,24 @@ static void parse_cache_line(char *line)
}
}
-int __init linux_main(int argc, char **argv)
+static unsigned long get_top_address(char **envp)
+{
+ unsigned long top_addr = (unsigned long) &top_addr;
+ int i;
+
+ /* The earliest variable should be after the program name in ELF */
+ for (i = 0; envp[i]; i++) {
+ if ((unsigned long) envp[i] > top_addr)
+ top_addr = (unsigned long) envp[i];
+ }
+
+ top_addr &= ~(UM_KERN_PAGE_SIZE - 1);
+ top_addr += UM_KERN_PAGE_SIZE;
+
+ return top_addr;
+}
+
+int __init linux_main(int argc, char **argv, char **envp)
{
unsigned long avail, diff;
unsigned long virtmem_size, max_physmem;
@@ -324,7 +341,7 @@ int __init linux_main(int argc, char **argv)
if (have_console == 0)
add_arg(DEFAULT_COMMAND_LINE_CONSOLE);
- host_task_size = os_get_top_address();
+ host_task_size = get_top_address(envp);
/* reserve a few pages for the stubs */
stub_start = host_task_size - STUB_DATA_PAGES * PAGE_SIZE;
/* another page for the code portion */