summaryrefslogtreecommitdiff
path: root/libre/qemu-user-static
diff options
context:
space:
mode:
authorLuke Shumaker <lukeshu@lukeshu.com>2017-12-25 04:40:41 -0500
committerLuke Shumaker <lukeshu@lukeshu.com>2017-12-28 15:08:38 -0500
commit28afb45ff5151bd0e1c6d2796a12fac36b960b1b (patch)
treec175cd03862d5c98cb229f76fdfa9f5a59630fed /libre/qemu-user-static
parent55ce24617af467542ae1b07814617fbe2b360e33 (diff)
libre/{qemu-static => qemu-user-static}: upgpkg 2.11.0-3.parabola1
Diffstat (limited to 'libre/qemu-user-static')
-rw-r--r--libre/qemu-user-static/0001-linux-user-Use-if-to-only-call-validate_guest_space-.patch81
-rw-r--r--libre/qemu-user-static/0002-linux-user-Rename-validate_guest_space-init_guest_co.patch54
-rw-r--r--libre/qemu-user-static/0003-linux-user-init_guest_space-Clean-up-if-we-can-t-ini.patch29
-rw-r--r--libre/qemu-user-static/0004-linux-user-init_guest_space-Correctly-handle-guest_s.patch47
-rw-r--r--libre/qemu-user-static/0005-linux-user-init_guest_space-Clarify-page-alignment-l.patch120
-rw-r--r--libre/qemu-user-static/0006-linux-user-init_guest_commpage-Add-a-comment-about-s.patch30
-rw-r--r--libre/qemu-user-static/0007-linux-user-init_guest_space-Clean-up-control-flow-a-.patch94
-rw-r--r--libre/qemu-user-static/0008-linux-user-init_guest_space-Don-t-try-to-align-if-we.patch50
-rw-r--r--libre/qemu-user-static/0009-linux-user-init_guest_space-Add-a-comment-about-sear.patch29
-rw-r--r--libre/qemu-user-static/0010-linux-user-init_guest_space-Try-to-make-ARM-space-co.patch99
-rw-r--r--libre/qemu-user-static/PKGBUILD170
-rw-r--r--libre/qemu-user-static/allow_elf64.patch27
12 files changed, 830 insertions, 0 deletions
diff --git a/libre/qemu-user-static/0001-linux-user-Use-if-to-only-call-validate_guest_space-.patch b/libre/qemu-user-static/0001-linux-user-Use-if-to-only-call-validate_guest_space-.patch
new file mode 100644
index 000000000..bbc3840fe
--- /dev/null
+++ b/libre/qemu-user-static/0001-linux-user-Use-if-to-only-call-validate_guest_space-.patch
@@ -0,0 +1,81 @@
+From 0c5afb7a15b6bb0e3fe276e377ad3702427e85d1 Mon Sep 17 00:00:00 2001
+From: Luke Shumaker <lukeshu@parabola.nu>
+Date: Wed, 27 Dec 2017 03:33:21 -0500
+Subject: [PATCH 01/10] linux-user: Use #if to only call validate_guest_space
+ for 32-bit ARM target
+
+Instead of defining a bogus validate_guest_space that always returns 1 on
+targets other than 32-bit ARM, use #if blocks to only call it on 32-bit ARM
+targets. This makes the "normal" flow control clearer.
+
+Signed-off-by: Luke Shumaker <lukeshu@parabola.nu>
+---
+ linux-user/elfload.c | 21 +++++++++------------
+ 1 file changed, 9 insertions(+), 12 deletions(-)
+
+diff --git a/linux-user/elfload.c b/linux-user/elfload.c
+index 20f3d8c2c3..cac991159c 100644
+--- a/linux-user/elfload.c
++++ b/linux-user/elfload.c
+@@ -354,7 +354,6 @@ enum {
+
+ /* The commpage only exists for 32 bit kernels */
+
+-#define TARGET_HAS_VALIDATE_GUEST_SPACE
+ /* Return 1 if the proposed guest space is suitable for the guest.
+ * Return 0 if the proposed guest space isn't suitable, but another
+ * address space should be tried.
+@@ -1823,15 +1822,6 @@ static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc,
+ return sp;
+ }
+
+-#ifndef TARGET_HAS_VALIDATE_GUEST_SPACE
+-/* If the guest doesn't have a validation function just agree */
+-static int validate_guest_space(unsigned long guest_base,
+- unsigned long guest_size)
+-{
+- return 1;
+-}
+-#endif
+-
+ unsigned long init_guest_space(unsigned long host_start,
+ unsigned long host_size,
+ unsigned long guest_start,
+@@ -1845,11 +1835,12 @@ unsigned long init_guest_space(unsigned long host_start,
+ /* If just a starting address is given, then just verify that
+ * address. */
+ if (host_start && !host_size) {
++#if defined(TARGET_ARM) && !defined(TARGET_AARCH64)
+ if (validate_guest_space(host_start, host_size) == 1) {
+- return host_start;
+- } else {
+ return (unsigned long)-1;
+ }
++#endif
++ return host_start;
+ }
+
+ /* Setup the initial flags and start address. */
+@@ -1888,6 +1879,8 @@ unsigned long init_guest_space(unsigned long host_start,
+
+ /* Check to see if the address is valid. */
+ if (!host_start || real_start == current_start) {
++#if defined(TARGET_ARM) && !defined(TARGET_AARCH64)
++ /* On 32-bit ARM, we need to also be able to map the commpage. */
+ int valid = validate_guest_space(real_start - guest_start,
+ real_size);
+ if (valid == 1) {
+@@ -1896,6 +1889,10 @@ unsigned long init_guest_space(unsigned long host_start,
+ return (unsigned long)-1;
+ }
+ /* valid == 0, so try again. */
++#else
++ /* On other architectures, whatever we have here is fine. */
++ break;
++#endif
+ }
+
+ /* That address didn't work. Unmap and try a different one.
+--
+2.15.1
+
diff --git a/libre/qemu-user-static/0002-linux-user-Rename-validate_guest_space-init_guest_co.patch b/libre/qemu-user-static/0002-linux-user-Rename-validate_guest_space-init_guest_co.patch
new file mode 100644
index 000000000..06e508219
--- /dev/null
+++ b/libre/qemu-user-static/0002-linux-user-Rename-validate_guest_space-init_guest_co.patch
@@ -0,0 +1,54 @@
+From b5b929b0423e5db333c9d5dfc104bb3598ff4182 Mon Sep 17 00:00:00 2001
+From: Luke Shumaker <lukeshu@parabola.nu>
+Date: Thu, 28 Dec 2017 08:03:26 -0500
+Subject: [PATCH 02/10] linux-user: Rename validate_guest_space =>
+ init_guest_commpage
+
+init_guest_commpage is a much more honest description of what the function
+does. validate_guest_space not only suggests that the function has no
+side-effects, but also introduces confusion as to why it is only needed on
+32-bit ARM targets.
+
+Signed-off-by: Luke Shumaker <lukeshu@parabola.nu>
+---
+ linux-user/elfload.c | 10 +++++-----
+ 1 file changed, 5 insertions(+), 5 deletions(-)
+
+diff --git a/linux-user/elfload.c b/linux-user/elfload.c
+index cac991159c..453394239c 100644
+--- a/linux-user/elfload.c
++++ b/linux-user/elfload.c
+@@ -362,8 +362,8 @@ enum {
+ * The guest code may leave a page mapped and populate it if the
+ * address is suitable.
+ */
+-static int validate_guest_space(unsigned long guest_base,
+- unsigned long guest_size)
++static int init_guest_commpage(unsigned long guest_base,
++ unsigned long guest_size)
+ {
+ unsigned long real_start, test_page_addr;
+
+@@ -1836,7 +1836,7 @@ unsigned long init_guest_space(unsigned long host_start,
+ * address. */
+ if (host_start && !host_size) {
+ #if defined(TARGET_ARM) && !defined(TARGET_AARCH64)
+- if (validate_guest_space(host_start, host_size) == 1) {
++ if (init_guest_commpage(host_start, host_size) != 1) {
+ return (unsigned long)-1;
+ }
+ #endif
+@@ -1881,8 +1881,8 @@ unsigned long init_guest_space(unsigned long host_start,
+ if (!host_start || real_start == current_start) {
+ #if defined(TARGET_ARM) && !defined(TARGET_AARCH64)
+ /* On 32-bit ARM, we need to also be able to map the commpage. */
+- int valid = validate_guest_space(real_start - guest_start,
+- real_size);
++ int valid = init_guest_commpage(real_start - guest_start,
++ real_size);
+ if (valid == 1) {
+ break;
+ } else if (valid == -1) {
+--
+2.15.1
+
diff --git a/libre/qemu-user-static/0003-linux-user-init_guest_space-Clean-up-if-we-can-t-ini.patch b/libre/qemu-user-static/0003-linux-user-init_guest_space-Clean-up-if-we-can-t-ini.patch
new file mode 100644
index 000000000..ea9eff138
--- /dev/null
+++ b/libre/qemu-user-static/0003-linux-user-init_guest_space-Clean-up-if-we-can-t-ini.patch
@@ -0,0 +1,29 @@
+From c03d2cc51c5fa496f894b641c035b12e49fd637b Mon Sep 17 00:00:00 2001
+From: Luke Shumaker <lukeshu@parabola.nu>
+Date: Wed, 27 Dec 2017 14:40:39 -0500
+Subject: [PATCH 03/10] linux-user: init_guest_space: Clean up if we can't
+ initialize the commpage
+
+We'll just exit with an error anyway, so it doesn't really matter, but it
+is cleaned up in all of the other places were we error out.
+
+Signed-off-by: Luke Shumaker <lukeshu@parabola.nu>
+---
+ linux-user/elfload.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/linux-user/elfload.c b/linux-user/elfload.c
+index 453394239c..1a6b660b25 100644
+--- a/linux-user/elfload.c
++++ b/linux-user/elfload.c
+@@ -1886,6 +1886,7 @@ unsigned long init_guest_space(unsigned long host_start,
+ if (valid == 1) {
+ break;
+ } else if (valid == -1) {
++ munmap((void *)real_start, host_size);
+ return (unsigned long)-1;
+ }
+ /* valid == 0, so try again. */
+--
+2.15.1
+
diff --git a/libre/qemu-user-static/0004-linux-user-init_guest_space-Correctly-handle-guest_s.patch b/libre/qemu-user-static/0004-linux-user-init_guest_space-Correctly-handle-guest_s.patch
new file mode 100644
index 000000000..7f9cfc7a8
--- /dev/null
+++ b/libre/qemu-user-static/0004-linux-user-init_guest_space-Correctly-handle-guest_s.patch
@@ -0,0 +1,47 @@
+From bc26025ccc64a2a63fc58776c93e2e4392445abe Mon Sep 17 00:00:00 2001
+From: Luke Shumaker <lukeshu@parabola.nu>
+Date: Wed, 27 Dec 2017 19:44:00 -0500
+Subject: [PATCH 04/10] linux-user: init_guest_space: Correctly handle
+ guest_start in commpage initialization
+
+init_guest_commpage needs to check if the mapped space, which ends at
+real_start+real_size overlaps with where it needs to put the commpage,
+which is (assuming sane qemu_host_page_size) guest_base + 0xffff000, where
+guest_base is real_start - guest_start.
+
+ [guest_base][ 0xffff0000 ][commpage]
+ [guest_base][guest_start][real_size] [commpage]
+ [ real_start ][real_size] [commpage]
+ ^
+ fail if this gap < 0
+
+Since init_guest_commpage wants to do everything relative to guest_base
+(rather than real_start), it obviously needs to be comparing 0xffff0000
+against guest_start+real_size, not just real_size.
+
+This bug has been present since 806d102141b99d4f1e55a97d68b7ea8c8ba3129f in
+2012, but guest_start is usually 0, and prior to v2.11 real_size was
+usually much smaller than 0xffff0000, so it was uncommon for it to have
+made a difference.
+
+Signed-off-by: Luke Shumaker <lukeshu@parabola.nu>
+---
+ linux-user/elfload.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/linux-user/elfload.c b/linux-user/elfload.c
+index 1a6b660b25..f41cecc3cb 100644
+--- a/linux-user/elfload.c
++++ b/linux-user/elfload.c
+@@ -1882,7 +1882,7 @@ unsigned long init_guest_space(unsigned long host_start,
+ #if defined(TARGET_ARM) && !defined(TARGET_AARCH64)
+ /* On 32-bit ARM, we need to also be able to map the commpage. */
+ int valid = init_guest_commpage(real_start - guest_start,
+- real_size);
++ real_size + guest_start);
+ if (valid == 1) {
+ break;
+ } else if (valid == -1) {
+--
+2.15.1
+
diff --git a/libre/qemu-user-static/0005-linux-user-init_guest_space-Clarify-page-alignment-l.patch b/libre/qemu-user-static/0005-linux-user-init_guest_space-Clarify-page-alignment-l.patch
new file mode 100644
index 000000000..1570774ee
--- /dev/null
+++ b/libre/qemu-user-static/0005-linux-user-init_guest_space-Clarify-page-alignment-l.patch
@@ -0,0 +1,120 @@
+From b2432d1b415143a55083782712f11241f194c0ba Mon Sep 17 00:00:00 2001
+From: Luke Shumaker <lukeshu@parabola.nu>
+Date: Wed, 27 Dec 2017 20:05:52 -0500
+Subject: [PATCH 05/10] linux-user: init_guest_space: Clarify page alignment
+ logic
+
+There are 3 parts to this change:
+ - Add a comment showing the relative sizes and positions of the blocks of
+ memory
+ - introduce and use new aligned_{start,size} instead of adjusting
+ real_{start_size}
+ - When we clean up (on failure), munmap(real_start, real_size) instead of
+ munmap(aligned_start, aligned_size). It *shouldn't* make any
+ difference, but I will admit that this does mean we are making the
+ syscall with different values, so this isn't quite a no-op patch.
+
+Signed-off-by: Luke Shumaker <lukeshu@parabola.nu>
+---
+ linux-user/elfload.c | 43 +++++++++++++++++++++++++++++++++----------
+ 1 file changed, 33 insertions(+), 10 deletions(-)
+
+diff --git a/linux-user/elfload.c b/linux-user/elfload.c
+index f41cecc3cb..22f2632dfa 100644
+--- a/linux-user/elfload.c
++++ b/linux-user/elfload.c
+@@ -1827,7 +1827,7 @@ unsigned long init_guest_space(unsigned long host_start,
+ unsigned long guest_start,
+ bool fixed)
+ {
+- unsigned long current_start, real_start;
++ unsigned long current_start, aligned_start;
+ int flags;
+
+ assert(host_start || host_size);
+@@ -1853,7 +1853,8 @@ unsigned long init_guest_space(unsigned long host_start,
+ /* Otherwise, a non-zero size region of memory needs to be mapped
+ * and validated. */
+ while (1) {
+- unsigned long real_size = host_size;
++ unsigned long real_start, real_size, aligned_size;
++ aligned_size = real_size = host_size;
+
+ /* Do not use mmap_find_vma here because that is limited to the
+ * guest address space. We are going to make the
+@@ -1867,26 +1868,48 @@ unsigned long init_guest_space(unsigned long host_start,
+
+ /* Ensure the address is properly aligned. */
+ if (real_start & ~qemu_host_page_mask) {
++ /* Ideally, we adjust like
++ *
++ * pages: [ ][ ][ ][ ][ ]
++ * old: [ real ]
++ * [ aligned ]
++ * new: [ real ]
++ * [ aligned ]
++ *
++ * But if there is something else mapped right after it,
++ * then obviously it won't have room to grow, and the
++ * kernel will put the new larger real someplace else with
++ * unknown alignment (if we made it to here, then
++ * fixed=false). Which is why we grow real by a full page
++ * size, instead of by part of one; so that even if we get
++ * moved, we can still guarantee alignment. But this does
++ * mean that there is a padding of < 1 page both before
++ * and after the aligned range; the "after" could could
++ * cause problems for ARM emulation where it could butt in
++ * to where we need to put the commpage.
++ */
+ munmap((void *)real_start, host_size);
+- real_size = host_size + qemu_host_page_size;
++ real_size = aligned_size + qemu_host_page_size;
+ real_start = (unsigned long)
+ mmap((void *)real_start, real_size, PROT_NONE, flags, -1, 0);
+ if (real_start == (unsigned long)-1) {
+ return (unsigned long)-1;
+ }
+- real_start = HOST_PAGE_ALIGN(real_start);
++ aligned_start = HOST_PAGE_ALIGN(real_start);
++ } else {
++ aligned_start = real_start;
+ }
+
+ /* Check to see if the address is valid. */
+- if (!host_start || real_start == current_start) {
++ if (!host_start || aligned_start == current_start) {
+ #if defined(TARGET_ARM) && !defined(TARGET_AARCH64)
+ /* On 32-bit ARM, we need to also be able to map the commpage. */
+- int valid = init_guest_commpage(real_start - guest_start,
+- real_size + guest_start);
++ int valid = init_guest_commpage(aligned_start - guest_start,
++ aligned_size + guest_start);
+ if (valid == 1) {
+ break;
+ } else if (valid == -1) {
+- munmap((void *)real_start, host_size);
++ munmap((void *)real_start, real_size);
+ return (unsigned long)-1;
+ }
+ /* valid == 0, so try again. */
+@@ -1905,7 +1928,7 @@ unsigned long init_guest_space(unsigned long host_start,
+ * address space randomization put a shared library somewhere
+ * inconvenient.
+ */
+- munmap((void *)real_start, host_size);
++ munmap((void *)real_start, real_size);
+ current_start += qemu_host_page_size;
+ if (host_start == current_start) {
+ /* Theoretically possible if host doesn't have any suitably
+@@ -1917,7 +1940,7 @@ unsigned long init_guest_space(unsigned long host_start,
+
+ qemu_log_mask(CPU_LOG_PAGE, "Reserved 0x%lx bytes of guest address space\n", host_size);
+
+- return real_start;
++ return aligned_start;
+ }
+
+ static void probe_guest_base(const char *image_name,
+--
+2.15.1
+
diff --git a/libre/qemu-user-static/0006-linux-user-init_guest_commpage-Add-a-comment-about-s.patch b/libre/qemu-user-static/0006-linux-user-init_guest_commpage-Add-a-comment-about-s.patch
new file mode 100644
index 000000000..4436b7817
--- /dev/null
+++ b/libre/qemu-user-static/0006-linux-user-init_guest_commpage-Add-a-comment-about-s.patch
@@ -0,0 +1,30 @@
+From ca873a81cc020df0ee0ec072a60678bb83dce9e2 Mon Sep 17 00:00:00 2001
+From: Luke Shumaker <lukeshu@parabola.nu>
+Date: Wed, 27 Dec 2017 21:05:29 -0500
+Subject: [PATCH 06/10] linux-user: init_guest_commpage: Add a comment about
+ size check
+
+Signed-off-by: Luke Shumaker <lukeshu@parabola.nu>
+---
+ linux-user/elfload.c | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+diff --git a/linux-user/elfload.c b/linux-user/elfload.c
+index 22f2632dfa..b560f5d6fe 100644
+--- a/linux-user/elfload.c
++++ b/linux-user/elfload.c
+@@ -374,6 +374,11 @@ static int init_guest_commpage(unsigned long guest_base,
+
+ /* If the commpage lies within the already allocated guest space,
+ * then there is no way we can allocate it.
++ *
++ * You may be thinking that that this check is redundant because
++ * we already validated the guest size against MAX_RESERVED_VA;
++ * but if qemu_host_page_mask is unusually large, then
++ * test_page_addr may be lower.
+ */
+ if (test_page_addr >= guest_base
+ && test_page_addr < (guest_base + guest_size)) {
+--
+2.15.1
+
diff --git a/libre/qemu-user-static/0007-linux-user-init_guest_space-Clean-up-control-flow-a-.patch b/libre/qemu-user-static/0007-linux-user-init_guest_space-Clean-up-control-flow-a-.patch
new file mode 100644
index 000000000..59be04cf9
--- /dev/null
+++ b/libre/qemu-user-static/0007-linux-user-init_guest_space-Clean-up-control-flow-a-.patch
@@ -0,0 +1,94 @@
+From dbbba45fa37da85ac213fbbe1f7eab3e1de74b41 Mon Sep 17 00:00:00 2001
+From: Luke Shumaker <lukeshu@parabola.nu>
+Date: Wed, 27 Dec 2017 21:17:52 -0500
+Subject: [PATCH 07/10] linux-user: init_guest_space: Clean up control flow a
+ bit
+
+Instead of doing
+
+ if (check1) {
+ if (check2) {
+ success;
+ }
+ }
+
+ retry;
+
+Do a clearer
+
+ if (!check1) {
+ goto try_again;
+ }
+
+ if (!check2) {
+ goto try_again;
+ }
+
+ success;
+
+ try_again:
+ retry;
+
+Besides being clearer, this makes it easier to insert more checks that
+need to trigger a retry on check failure, or rearrange them, or anything
+like that.
+
+Because some indentation is changing, "ignore space change" may be useful
+for viewing this patch.
+
+Signed-off-by: Luke Shumaker <lukeshu@parabola.nu>
+---
+ linux-user/elfload.c | 34 +++++++++++++++++++---------------
+ 1 file changed, 19 insertions(+), 15 deletions(-)
+
+diff --git a/linux-user/elfload.c b/linux-user/elfload.c
+index b560f5d6fe..5c0ad65611 100644
+--- a/linux-user/elfload.c
++++ b/linux-user/elfload.c
+@@ -1906,24 +1906,28 @@ unsigned long init_guest_space(unsigned long host_start,
+ }
+
+ /* Check to see if the address is valid. */
+- if (!host_start || aligned_start == current_start) {
++ if (host_start && aligned_start != current_start) {
++ goto try_again;
++ }
++
+ #if defined(TARGET_ARM) && !defined(TARGET_AARCH64)
+- /* On 32-bit ARM, we need to also be able to map the commpage. */
+- int valid = init_guest_commpage(aligned_start - guest_start,
+- aligned_size + guest_start);
+- if (valid == 1) {
+- break;
+- } else if (valid == -1) {
+- munmap((void *)real_start, real_size);
+- return (unsigned long)-1;
+- }
+- /* valid == 0, so try again. */
+-#else
+- /* On other architectures, whatever we have here is fine. */
+- break;
+-#endif
++ /* On 32-bit ARM, we need to also be able to map the commpage. */
++ int valid = init_guest_commpage(aligned_start - guest_start,
++ aligned_size + guest_start);
++ if (valid == -1) {
++ munmap((void *)real_start, real_size);
++ return (unsigned long)-1;
++ } else if (valid == -1) {
++ goto try_again;
+ }
++#endif
++
++ /* If nothing has said `return -1` or `goto try_again` yet,
++ * then the address we have is good.
++ */
++ break;
+
++ try_again:
+ /* That address didn't work. Unmap and try a different one.
+ * The address the host picked because is typically right at
+ * the top of the host address space and leaves the guest with
+--
+2.15.1
+
diff --git a/libre/qemu-user-static/0008-linux-user-init_guest_space-Don-t-try-to-align-if-we.patch b/libre/qemu-user-static/0008-linux-user-init_guest_space-Don-t-try-to-align-if-we.patch
new file mode 100644
index 000000000..9f434e116
--- /dev/null
+++ b/libre/qemu-user-static/0008-linux-user-init_guest_space-Don-t-try-to-align-if-we.patch
@@ -0,0 +1,50 @@
+From 8f38106de8d023be8b3b28955df3615637c65dd9 Mon Sep 17 00:00:00 2001
+From: Luke Shumaker <lukeshu@parabola.nu>
+Date: Thu, 28 Dec 2017 06:42:12 -0500
+Subject: [PATCH 08/10] linux-user: init_guest_space: Don't try to align if
+ we'll reject it
+
+If the ensure-alignment code gets triggered, then the
+"if (host_start && real_start != current_start)" check will always trigger,
+so save 2 syscalls and put that check first.
+
+Note that we can't just switch to using MAP_FIXED for that check, because
+then we couldn't differentiate between a failure because "there isn't
+enough space" and "there isn't enough space *here*".
+
+Signed-off-by: Luke Shumaker <lukeshu@parabola.nu>
+---
+ linux-user/elfload.c | 10 +++++-----
+ 1 file changed, 5 insertions(+), 5 deletions(-)
+
+diff --git a/linux-user/elfload.c b/linux-user/elfload.c
+index 5c0ad65611..1b7583d659 100644
+--- a/linux-user/elfload.c
++++ b/linux-user/elfload.c
+@@ -1871,6 +1871,11 @@ unsigned long init_guest_space(unsigned long host_start,
+ return (unsigned long)-1;
+ }
+
++ /* Check to see if the address is valid. */
++ if (host_start && real_start != current_start) {
++ goto try_again;
++ }
++
+ /* Ensure the address is properly aligned. */
+ if (real_start & ~qemu_host_page_mask) {
+ /* Ideally, we adjust like
+@@ -1905,11 +1910,6 @@ unsigned long init_guest_space(unsigned long host_start,
+ aligned_start = real_start;
+ }
+
+- /* Check to see if the address is valid. */
+- if (host_start && aligned_start != current_start) {
+- goto try_again;
+- }
+-
+ #if defined(TARGET_ARM) && !defined(TARGET_AARCH64)
+ /* On 32-bit ARM, we need to also be able to map the commpage. */
+ int valid = init_guest_commpage(aligned_start - guest_start,
+--
+2.15.1
+
diff --git a/libre/qemu-user-static/0009-linux-user-init_guest_space-Add-a-comment-about-sear.patch b/libre/qemu-user-static/0009-linux-user-init_guest_space-Add-a-comment-about-sear.patch
new file mode 100644
index 000000000..e91fdefd8
--- /dev/null
+++ b/libre/qemu-user-static/0009-linux-user-init_guest_space-Add-a-comment-about-sear.patch
@@ -0,0 +1,29 @@
+From 81033c66738a2e3b713c414e8e07e6ef8e59d8d7 Mon Sep 17 00:00:00 2001
+From: Luke Shumaker <lukeshu@parabola.nu>
+Date: Thu, 28 Dec 2017 07:22:29 -0500
+Subject: [PATCH 09/10] linux-user: init_guest_space: Add a comment about
+ search strategy
+
+Signed-off-by: Luke Shumaker <lukeshu@parabola.nu>
+---
+ linux-user/elfload.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/linux-user/elfload.c b/linux-user/elfload.c
+index 1b7583d659..7736ea2c3a 100644
+--- a/linux-user/elfload.c
++++ b/linux-user/elfload.c
+@@ -1936,6 +1936,10 @@ unsigned long init_guest_space(unsigned long host_start,
+ * happen often. Probably means we got unlucky and host
+ * address space randomization put a shared library somewhere
+ * inconvenient.
++ *
++ * This is probably a good strategy if host_start, but is
++ * probably a bad strategy if not, which means we got here
++ * because of trouble with ARM commpage setup.
+ */
+ munmap((void *)real_start, real_size);
+ current_start += qemu_host_page_size;
+--
+2.15.1
+
diff --git a/libre/qemu-user-static/0010-linux-user-init_guest_space-Try-to-make-ARM-space-co.patch b/libre/qemu-user-static/0010-linux-user-init_guest_space-Try-to-make-ARM-space-co.patch
new file mode 100644
index 000000000..587293564
--- /dev/null
+++ b/libre/qemu-user-static/0010-linux-user-init_guest_space-Try-to-make-ARM-space-co.patch
@@ -0,0 +1,99 @@
+From f8ccd5e7353937e0a48ccd8bfbc07202dc85afac Mon Sep 17 00:00:00 2001
+From: Luke Shumaker <lukeshu@parabola.nu>
+Date: Thu, 28 Dec 2017 07:27:20 -0500
+Cc: paul@codesourcery.com
+Subject: [PATCH 10/10] linux-user: init_guest_space: Try to make ARM
+ space+commpage continuous
+
+At a fixed distance after the usable memory that init_guest_space maps, for
+32-bit ARM targets we also need to map a commpage. The normal
+init_guest_space logic doesn't keep this in mind when searching for an
+address range.
+
+If !host_start, then try to find a big continuous segment where we can put
+both the usable memory and the commpage; we then munmap that segment and
+set current_start to that address; and let the normal code mmap the usable
+memory and the commpage separately. That is: if we don't have hint of
+where to start looking for memory, come up with one that is better than
+NULL. Depending on host_size and guest_start, there may or may not be a
+gap between the usable memory and the commpage, so this is slightly more
+restrictive than it needs to be; but it's only a hint, so that's OK.
+
+We only do that for !host start, because if host_start, then either:
+ - we got an address passed in with -B, in which case we don't want to
+ interfere with what the user said;
+ - or host_start is based off of the ELF image's loaddr. The check "if
+ (host_start && real_start != current_start)" suggests that we really
+ want lowest available address that is >= loaddr. I don't know why that
+ is, but I'm trusting that Paul Brook knew what he was doing when he
+ wrote the original version of that check in
+ c581deda322080e8beb88b2e468d4af54454e4b3 way back in 2010.
+
+Signed-off-by: Luke Shumaker <lukeshu@parabola.nu>
+---
+ linux-user/elfload.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 49 insertions(+)
+
+diff --git a/linux-user/elfload.c b/linux-user/elfload.c
+index 7736ea2c3a..cd3a7d877d 100644
+--- a/linux-user/elfload.c
++++ b/linux-user/elfload.c
+@@ -1857,6 +1857,55 @@ unsigned long init_guest_space(unsigned long host_start,
+
+ /* Otherwise, a non-zero size region of memory needs to be mapped
+ * and validated. */
++
++#if defined(TARGET_ARM) && !defined(TARGET_AARCH64)
++ /* On 32-bit ARM, we need to map not just the usable memory, but
++ * also the commpage. Try to find a suitable place by allocating
++ * a big chunk for all of it. If host_start, then the naive
++ * strategy probably does good enough.
++ */
++ if (!host_start) {
++ unsigned long guest_full_size, host_full_size, real_start;
++
++ guest_full_size =
++ (0xffff0f00 & qemu_host_page_mask) + qemu_host_page_size;
++ host_full_size = guest_full_size - guest_start;
++ real_start = (unsigned long)
++ mmap(NULL, host_full_size, PROT_NONE, flags, -1, 0);
++ if (real_start == (unsigned long)-1) {
++ if (host_size < host_full_size - qemu_host_page_size) {
++ /* We failed to map a continous segment, but we're
++ * allowed to have a gap between the usable memory and
++ * the commpage where other things can be mapped.
++ * This sparseness gives us more flexibility to find
++ * an address range.
++ */
++ goto naive;
++ }
++ return (unsigned long)-1;
++ }
++ munmap((void *)real_start, host_full_size);
++ if (real_start & ~qemu_host_page_mask) {
++ /* The same thing again, but with an extra qemu_host_page_size
++ * so that we can shift around alignment.
++ */
++ unsigned long real_size = host_full_size + qemu_host_page_size;
++ real_start = (unsigned long)
++ mmap(NULL, real_size, PROT_NONE, flags, -1, 0);
++ if (real_start == (unsigned long)-1) {
++ if (host_size < host_full_size - qemu_host_page_size) {
++ goto naive;
++ }
++ return (unsigned long)-1;
++ }
++ munmap((void *)real_start, real_size);
++ real_start = HOST_PAGE_ALIGN(real_start);
++ }
++ current_start = real_start;
++ }
++ naive:
++#endif
++
+ while (1) {
+ unsigned long real_start, real_size, aligned_size;
+ aligned_size = real_size = host_size;
+--
+2.15.1
+
diff --git a/libre/qemu-user-static/PKGBUILD b/libre/qemu-user-static/PKGBUILD
new file mode 100644
index 000000000..a3030470b
--- /dev/null
+++ b/libre/qemu-user-static/PKGBUILD
@@ -0,0 +1,170 @@
+# Maintainer (Arch:qemu): Tobias Powalowski <tpowa@archlinux.org>
+# Contributor (Arch:qemu): Sébastien "Seblu" Luttringer <seblu@seblu.net>
+# Maintainer: Luke Shumaker <lukeshu@parabola.nu>
+# Contributor: Márcio Silva <coadde@hyperbola.info>
+
+_pkgbase=qemu
+pkgname=(qemu-user-static qemu-user-static-binfmt)
+pkgdesc="A generic and open source machine emulator and virtualizer"
+pkgver=2.11.0
+pkgrel=3.parabola1
+arch=(x86_64)
+arch+=(i686 armv7h)
+license=(GPL2 LGPL2.1)
+url="http://wiki.qemu.org/"
+makedepends=(pixman-static glib2-static pcre-static python2)
+source=("$url/download/${_pkgbase}-${pkgver}.tar.bz2"{,.sig}
+ 0001-linux-user-Use-if-to-only-call-validate_guest_space-.patch
+ 0002-linux-user-Rename-validate_guest_space-init_guest_co.patch
+ 0003-linux-user-init_guest_space-Clean-up-if-we-can-t-ini.patch
+ 0004-linux-user-init_guest_space-Correctly-handle-guest_s.patch
+ 0005-linux-user-init_guest_space-Clarify-page-alignment-l.patch
+ 0006-linux-user-init_guest_commpage-Add-a-comment-about-s.patch
+ 0007-linux-user-init_guest_space-Clean-up-control-flow-a-.patch
+ 0008-linux-user-init_guest_space-Don-t-try-to-align-if-we.patch
+ 0009-linux-user-init_guest_space-Add-a-comment-about-sear.patch
+ 0010-linux-user-init_guest_space-Try-to-make-ARM-space-co.patch
+ allow_elf64.patch)
+sha256sums=('c4f034c7665a84a1c3be72c8da37f3c31ec063475699df062ab646d8b2e17fcb'
+ 'SKIP'
+ '9953a8debd9456adb4f5968817fa89da4d4542e44980a5533ccf86371d819845'
+ 'a977e9295daa14a9c73258cf16399eb5af66382217f8a4e69951ec044131a7ce'
+ 'dba2cfeb24841d45936091319957ee6f65e481da3c761791d410d3b8e6799998'
+ '75b3bda6752c4bf17488489f898767b6772b10ecc5d1f0a5bc1bd831e99a31e3'
+ '731895a8ed6f6d322bb60764b01cf09e0ea762d7d53fc01e91c2d2aecfdc8844'
+ '69b37040f52ef86b86c7c2952eb3f85f3c67d7adf289c43fdac8c71827c6e5b9'
+ '76f88850b0f52450eecb80029ffe16db6f418cec3b58231aca354cc20bbfb16a'
+ '76944d84990cc76e47c381849c683a346c5234bcebbe4c24334d0fd8368482db'
+ '7845867348fd380def28c7fe023e54cee8ff88cd6754aae3ab3472149cfbde51'
+ '1953e7cac58c23526d007d8559410e0042d4a7c1b8cbd5f4c0543f7f876436dd'
+ '13a6d9e678bdc9e1f051006cfd0555f5a80582368f54c8a1bb5a78ece3832ac4')
+validpgpkeys=('CEACC9E15534EBABB82D3FA03353C9CEF108B584')
+
+case $CARCH in
+ i?86) _corearch=i386 ;;
+ x86_64) _corearch=x86_64 ;;
+esac
+
+prepare() {
+ mkdir build-static
+ mkdir -p extra-arch-static/usr/{bin,share/qemu}
+
+ cd ${_pkgbase}-${pkgver}
+ sed -i 's/vte-2\.90/vte-2.91/g' configure
+
+ # https://bugs.launchpad.net/qemu/+bug/1740219
+ # https://lists.nongnu.org/archive/html/qemu-devel/2017-12/msg05237.html
+ local patchfile
+ for patchfile in ../????-linux-user-*.patch; do
+ patch -p1 < "$patchfile"
+ done
+
+ patch -p1 < ../allow_elf64.patch
+}
+
+build() {
+ local flags=(
+ --static
+ --disable-system # disable building qemu-system-$CPU, we only want qemu-$CPU
+ --disable-guest-agent # disable building qemu-ga
+ --disable-tools # disable building the qemu-{io,nbd,img} tools
+ --disable-blobs # disable installing firmware files used by system
+ --disable-docs
+ --disable-modules # modules imply dynamic linking
+
+ # jemalloc-static isn't packaged
+ --disable-jemalloc
+
+ # These libraries are only used for system or tools, but even
+ # though that's disabled, libqemuutil.a still tries to link
+ # against them unless we specifically tell it not to (the linkage
+ # would be removed at the final linker's tree-shaking).
+ --disable-gcrypt
+ --disable-nettle
+ )
+ _build static "${flags[@]}" \
+ --audio-drv-list= \
+ --disable-bluez \
+ --disable-sdl \
+ --disable-gtk \
+ --disable-vte \
+ --disable-opengl \
+ --disable-virglrenderer
+}
+
+_build() (
+ cd build-$1
+
+ # qemu vs. make 4 == bad
+ export ARFLAGS=rv
+
+ # http://permalink.gmane.org/gmane.comp.emulators.qemu/238740
+ export CFLAGS+=" -fPIC"
+
+ ../${_pkgbase}-${pkgver}/configure \
+ --prefix=/usr \
+ --sysconfdir=/etc \
+ --localstatedir=/var \
+ --libexecdir=/usr/lib/qemu \
+ --python=/usr/bin/python2 \
+ --smbd=/usr/bin/smbd \
+ --with-gtkabi=3.0 \
+ --with-sdlabi=2.0 \
+ --enable-modules \
+ --enable-jemalloc \
+ "${@:2}"
+
+ make
+)
+
+package_qemu-user-static() {
+ pkgdesc="QEMU user-mode emulation (static binaries)"
+
+ provides=("qemu-static=$pkgver")
+ replaces=(qemu-static)
+ conflicts=(qemu-static)
+
+ _package static
+
+ rm -vr -- \
+ "$pkgdir"/usr/lib/ \
+ "$pkgdir"/usr/share/
+
+ local prog
+ for prog in "$pkgdir"/usr/bin/*; do
+ mv -nT -- "$prog" "${prog%-static}-static"
+ done
+}
+
+_package() {
+ options=(!strip)
+
+ make -C build-$1 DESTDIR="$pkgdir" install "${@:2}"
+
+ cd "$pkgdir"/usr/bin
+ tidy_strip
+}
+
+package_qemu-user-static-binfmt() {
+ pkgdesc="binfmt registration for QEMU user-mode emulation"
+ depends=("qemu-user-static=$pkgver")
+
+ provides=("binfmt-qemu-static=$pkgver")
+ replaces=('binfmt-qemu-static')
+ conflicts=('binfmt-qemu-static')
+
+ cd ${_pkgbase}-${pkgver}
+
+ install -d "$pkgdir"/usr/lib/binfmt.d
+
+ < scripts/qemu-binfmt-conf.sh \
+ sed -e 's/^CHECK=.*/CHECK=qemu_check_systemd/' \
+ -e 's/^BINFMT_SET=.*/BINFMT_SET=qemu_generate_systemd/' \
+ | sh /dev/stdin \
+ --qemu-path /usr/bin \
+ --exportdir "$pkgdir"/usr/lib/binfmt.d \
+ --credential yes
+
+ # add the "-static" suffix
+ sed -i 's/:[^:]*$/-static&/' -- "$pkgdir"/usr/lib/binfmt.d/*.conf
+}
diff --git a/libre/qemu-user-static/allow_elf64.patch b/libre/qemu-user-static/allow_elf64.patch
new file mode 100644
index 000000000..07f27a038
--- /dev/null
+++ b/libre/qemu-user-static/allow_elf64.patch
@@ -0,0 +1,27 @@
+commit 3c72765ec760a51f0e879dc792be82c93141e318
+Author: Anatol Pomozov <anatol.pomozov@gmail.com>
+Date: Tue Jun 6 20:07:03 2017 -0700
+
+ Remove restriction that prevents bootimg elf64 images
+
+ It is possible to create a 64 bit elf image that has valid multiboot header.
+ qemu should be able to boot such images.
+
+ Signed-off-by: Anatol Pomozov <anatol.pomozov@gmail.com>
+
+diff --git a/hw/i386/multiboot.c b/hw/i386/multiboot.c
+index 663f35a658..cf1b4f5fb3 100644
+--- a/hw/i386/multiboot.c
++++ b/hw/i386/multiboot.c
+@@ -192,11 +192,6 @@ int load_multiboot(FWCfgState *fw_cfg,
+ int kernel_size;
+ fclose(f);
+
+- if (((struct elf64_hdr*)header)->e_machine == EM_X86_64) {
+- fprintf(stderr, "Cannot load x86-64 image, give a 32bit one.\n");
+- exit(1);
+- }
+-
+ kernel_size = load_elf(kernel_filename, NULL, NULL, &elf_entry,
+ &elf_low, &elf_high, 0, I386_ELF_MACHINE,
+ 0, 0);