linux-user: Align mmap memory to the target page size.
PATCH 1/1 linux-user: Align mmap memory to the target page size.
Previously, mmap_find_vma could return addresses not properly aligned to the target page size. This of course led to all sorts of odd problems down the road.
The trivial fix, to simply reject the unaligned address and continue searching the address space by increments of one page, is not a good idea when there's a 64-bit address space involved. The kernel may well continue to return the last available address which we've already rejected while we search upward from e.g. 2**42 from 2**64.
This patch uses a more complex search algorithm that takes the result of the previous allocation into account. We normally search upward, but notice 2 consecutive results and start searching downward instead.
--- linux-user/main.c | 7 +--- linux-user/mmap.c | 71 ++++++++++++++++++++++++++++++++++++++++++++++------ 2 files changed, 64 insertions(+), 14 deletions(-)
linux-user/main.c +2 -5
@@ -2725,12 +2725,9 @@ int main(int argc, char **argv, char **envp)/* * Read in mmap_min_addr kernel parameter. This value is used * When loading the ELF image to determine whether guest_base -* is needed. -* -* When user has explicitly set the quest base, we skip this -* test. +* is needed. It is also used in mmap_find_vma. */ -if (!have_guest_base) { + {FILE *fp;if ((fp =fopen ("/proc/sys/vm/mmap_min_addr" ,"r" )) !=NULL ) {
linux-user/mmap.c +62 -9
98 lines not on this page · raw message
Signature · 1 line
1.6.5.2
Quoted 10 lines · Richard Henderson
Previously,
mmap_find_vmacould return addresses not properly aligned to the target page size. This of course led to all sorts of odd problems down the road.The trivial fix, to simply reject the unaligned address and continue searching the address space by increments of one page, is not a good idea when there's a 64-bit address space involved. The kernel may well continue to return the last available address which we've already rejected while we search upward from e.g. 2**42 from 2**64.
Quoted 3 lines
This patch uses a more complex search algorithm that takes the result of the previous allocation into account. We normally search upward, but notice 2 consecutive results and start searching downward instead.
I've failed to take guest_base into account properly; my testing happened to have guest_base = 0. New patch to follow.
r~
Quoted 6 lines · Richard Henderson
Quoted 3 lines
This patch uses a more complex search algorithm that takes the result of the previous allocation into account. We normally search upward, but notice 2 consecutive results and start searching downward instead.
I've failed to take
guest_baseinto account properly; my testing happened to haveguest_base= 0. New patch to follow.
Did you have time to look at this again?
Quoted 9 lines · Riku Voipio
Quoted 6 lines · Richard Henderson
Quoted 3 lines
This patch uses a more complex search algorithm that takes the result of the previous allocation into account. We normally search upward, but notice 2 consecutive results and start searching downward instead.
I've failed to take
guest_baseinto account properly; my testing happened to haveguest_base= 0. New patch to follow.Did you have time to look at this again?
Some. There is an additional problem.
The target's pages are recorded in the physical page mapping via page_set_flags, whose input address is bounded by TARGET_PHYS_ADDR_SPACE_BITS, which is local to exec.c. Doubly unfortunately, page_set_flags silently discards pages that it considers must be outside the target's address space.
It's fairly easy to get the x86-64 kernel to return a vma outside the range of any of the existing TARGET_PHYS_ADDR_SPACE_BITS. Which works fine inside the TB's, but causes any other syscall to return -EFAULT.
We have a check
/* If address fits target address space we've found what we need */ if ((unsigned long)ptr + size - 1 <= (abi_ulong)-1)
break;
which kind-of works for 32-bit targets. (You'll note, of course, that the comparison is against PTR, which is a host address; the correct test would have been h2g_valid, as seen with -B 0x100000000.) However, it does nothing for 64-bit targets and the artificial 2**42 virtual address space limit we impose on most of them.
I talked with pbrook a bit about this on irc, and there seems to be no simple solution (like exporting TARGET_PHYS_ADDR_SPACE_BITS, possibly renamed as TARGET_ADDR_SPACE_BITS, in cpu.h) that would be acceptable to him.
Given the number of patches I've already submitted that aren't being reviewed, I'm unlikely to develop the momentum to totally rewrite qemu's page table support. Particularly without a clue as to what sort of solution might be acceptable. (Something like Sparc64's hashed page tables perhaps, which support a full 64-bit virtual address space?)
r~