forked from torvalds/linux
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Calculate TASK_SIZE at run-time by figuring out the host's VMSPLIT - this is needed on i386 if UML is to run on hosts with varying VMSPLITs without recompilation. TASK_SIZE is now defined in terms of a variable, task_size. This gets rid of an include of pgtable.h from processor.h, which can cause include loops. On i386, task_size is calculated early in boot by probing the address space in a binary search to figure out where the boundary between usable and non-usable memory is. This tries to make sure that a page that is considered to be in userspace is, or can be made, read-write. I'm concerned about a system-global VDSO page in kernel memory being hit and considered to be a userspace page. On x86_64, task_size is just the old value of CONFIG_TOP_ADDR. A bunch of config variable are gone now. CONFIG_TOP_ADDR is directly replaced by TASK_SIZE. NEST_LEVEL is gone since the relocation of the stubs makes it irrelevant. All the HOST_VMSPLIT stuff is gone. All references to these in arch/um/Makefile are also gone. I noticed and fixed a missing extern in os.h when adding os_get_task_size. Note: This has been revised to fix the 32-bit UML on 64-bit host bug that Miklos ran into. Signed-off-by: Jeff Dike <[email protected]> Cc: Miklos Szeredi <[email protected]> Signed-off-by: Andrew Morton <[email protected]> Signed-off-by: Linus Torvalds <[email protected]>
- Loading branch information
Showing
15 changed files
with
153 additions
and
75 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,120 @@ | ||
#include <stdio.h> | ||
#include <stdlib.h> | ||
#include <signal.h> | ||
#include <sys/mman.h> | ||
#include "longjmp.h" | ||
#include "kern_constants.h" | ||
|
||
static jmp_buf buf; | ||
|
||
static void segfault(int sig) | ||
{ | ||
longjmp(buf, 1); | ||
} | ||
|
||
static int page_ok(unsigned long page) | ||
{ | ||
unsigned long *address = (unsigned long *) (page << UM_KERN_PAGE_SHIFT); | ||
unsigned long n = ~0UL; | ||
void *mapped = NULL; | ||
int ok = 0; | ||
|
||
/* | ||
* First see if the page is readable. If it is, it may still | ||
* be a VDSO, so we go on to see if it's writable. If not | ||
* then try mapping memory there. If that fails, then we're | ||
* still in the kernel area. As a sanity check, we'll fail if | ||
* the mmap succeeds, but gives us an address different from | ||
* what we wanted. | ||
*/ | ||
if (setjmp(buf) == 0) | ||
n = *address; | ||
else { | ||
mapped = mmap(address, UM_KERN_PAGE_SIZE, | ||
PROT_READ | PROT_WRITE, | ||
MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); | ||
if (mapped == MAP_FAILED) | ||
return 0; | ||
if (mapped != address) | ||
goto out; | ||
} | ||
|
||
/* | ||
* Now, is it writeable? If so, then we're in user address | ||
* space. If not, then try mprotecting it and try the write | ||
* again. | ||
*/ | ||
if (setjmp(buf) == 0) { | ||
*address = n; | ||
ok = 1; | ||
goto out; | ||
} else if (mprotect(address, UM_KERN_PAGE_SIZE, | ||
PROT_READ | PROT_WRITE) != 0) | ||
goto out; | ||
|
||
if (setjmp(buf) == 0) { | ||
*address = n; | ||
ok = 1; | ||
} | ||
|
||
out: | ||
if (mapped != NULL) | ||
munmap(mapped, UM_KERN_PAGE_SIZE); | ||
return ok; | ||
} | ||
|
||
unsigned long os_get_task_size(void) | ||
{ | ||
struct sigaction sa, old; | ||
unsigned long bottom = 0; | ||
/* | ||
* A 32-bit UML on a 64-bit host gets confused about the VDSO at | ||
* 0xffffe000. It is mapped, is readable, can be reprotected writeable | ||
* and written. However, exec discovers later that it can't be | ||
* unmapped. So, just set the highest address to be checked to just | ||
* below it. This might waste some address space on 4G/4G 32-bit | ||
* hosts, but shouldn't hurt otherwise. | ||
*/ | ||
unsigned long top = 0xffffd000 >> UM_KERN_PAGE_SHIFT; | ||
unsigned long test; | ||
|
||
printf("Locating the top of the address space ... "); | ||
fflush(stdout); | ||
|
||
/* | ||
* We're going to be longjmping out of the signal handler, so | ||
* SA_DEFER needs to be set. | ||
*/ | ||
sa.sa_handler = segfault; | ||
sigemptyset(&sa.sa_mask); | ||
sa.sa_flags = SA_NODEFER; | ||
sigaction(SIGSEGV, &sa, &old); | ||
|
||
if (!page_ok(bottom)) { | ||
fprintf(stderr, "Address 0x%x no good?\n", | ||
bottom << UM_KERN_PAGE_SHIFT); | ||
exit(1); | ||
} | ||
|
||
/* This could happen with a 4G/4G split */ | ||
if (page_ok(top)) | ||
goto out; | ||
|
||
do { | ||
test = bottom + (top - bottom) / 2; | ||
if (page_ok(test)) | ||
bottom = test; | ||
else | ||
top = test; | ||
} while (top - bottom > 1); | ||
|
||
out: | ||
/* Restore the old SIGSEGV handling */ | ||
sigaction(SIGSEGV, &old, NULL); | ||
|
||
top <<= UM_KERN_PAGE_SHIFT; | ||
printf("0x%x\n", top); | ||
fflush(stdout); | ||
|
||
return top; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
unsigned long os_get_task_size(unsigned long shift) | ||
{ | ||
/* The old value of CONFIG_TOP_ADDR */ | ||
return 0x7fc0000000; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters