Commit 293f2060 authored by Luke Shumaker's avatar Luke Shumaker Committed by Laurent Vivier
Browse files

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: default avatarLuke Shumaker <lukeshu@parabola.nu>
Message-Id: <20171228180814.9749-6-lukeshu@lukeshu.com>
Reviewed-by: default avatarPeter Maydell <peter.maydell@linaro.org>
Signed-off-by: default avatarLaurent Vivier <laurent@vivier.eu>
parent e7ea02e6
Loading
Loading
Loading
Loading
+33 −10
Original line number Diff line number Diff line
@@ -1801,7 +1801,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);
@@ -1827,7 +1827,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
@@ -1841,26 +1842,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. */
@@ -1879,7 +1902,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
@@ -1891,7 +1914,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,