qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: "Cédric VINCENT" <cedric.vincent@st.com>
To: Peter Maydell <peter.maydell@linaro.org>,
	Martin Mohring <martin.mohring@opensuse.org>,
	qemu-devel@nongnu.org
Cc: "Christophe Guillon" <christophe.guillon@st.com>,
	"Mike McCormack" <mj.mccormack@samsung.com>,
	"Riku Voipio" <riku.voipio@iki.fi>,
	"Stephen Clarke" <stephen.clarke@st.com>,
	"Cédric VINCENT" <cedric.vincent@st.com>
Subject: [Qemu-devel] [PATCH] linux-user: Fix the computation of the requested heap size
Date: Wed, 1 Jun 2011 11:37:19 +0200	[thread overview]
Message-ID: <1306921039-27324-1-git-send-email-cedric.vincent@st.com> (raw)
In-Reply-To: <BANLkTi=vqzLPb0gnrMrJhKgixZtKvXS9yw@mail.gmail.com>

Hi Peter & Martin,

On 2011-04-21 14:04:40, Peter Maydell <peter.maydell@linaro.org> wrote:
>
> I've had a report from Martin Mohring that this patch breaks some
> programs which previously worked in linux-user mode (one wonders if
> they were overwriting some chunk of memory that they happened not
> to be using for anything important...)

Peter, actually your patch exposes two old bugs more explicitly (since
the error code is now correctly reported).  To complete your patchset,
just consider this contribution as "PATCH 4/3" ;)

Martin, I suppose you have encountered a problem with the memory
allocator used in Bash and Emacs.  I reduced the problem to the
test-case embedded in the commit message below.

Also, I wonder how this whole new implementation of the target brk
could help ScratchBox2? [1]

Regards,
Cédric

[1] http://lists.gnu.org/archive/html/qemu-devel/2011-04/msg01817.html

PS: feel free to ask me for a separated patch if you don't [like to]
    use "git am --scissors"

8<----8<----8<----8<----8<----8<----8<----8<----8<----8<----8<----8<----

There were two remaining bugs in the previous implementation of
do_brk():

    1. the value of "new_alloc_size" was one page too large when the
       requested brk was aligned on a host page boundary.

    2. no new pages should be (re-)allocated when the requested brk is
       in the range of the pages that were already allocated
       previsouly (for the same purpose).  Technically these pages are
       never unmapped in the current implementation.

The problem/fix can be reproduced/validated with the following test
case:

    #include <unistd.h>       /* syscall(2),      */
    #include <sys/syscall.h>  /* SYS_brk,         */
    #include <stdio.h>        /* puts(3),         */
    #include <stdlib.h>       /* exit(3), EXIT_*, */

    int main()
    {
        int current_brk = 0;
        int new_brk;
        int failure = 0;

        void test(int increment) {
            static int test_number = 0;
            test_number++;

            new_brk = syscall(SYS_brk, current_brk + increment);
            if (new_brk == current_brk) {
                printf("test %d fails\n", test_number);
                failure++;
            }

            current_brk = new_brk;
        }

        /* Initialization.  */
        test(0);

        /* Does QEMU overlap host pages?  */
        test(HOST_PAGE_SIZE);
        test(HOST_PAGE_SIZE);

        /* Does QEMU allocate the same host page twice?  */
        test(-HOST_PAGE_SIZE);
        test(HOST_PAGE_SIZE);

        if (!failure) {
            printf("success\n");
            exit(EXIT_SUCCESS);
        }
        else {
            exit(EXIT_FAILURE);
        }
    }

Signed-off-by: Cédric VINCENT <cedric.vincent@st.com>
Reviewed-by: Christophe Guillon <christophe.guillon@st.com>
Cc: Riku Voipio <riku.voipio@iki.fi>
---
 linux-user/syscall.c |   11 ++++++-----
 1 files changed, 6 insertions(+), 5 deletions(-)

diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index b975730..be27f53 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -709,16 +709,17 @@ char *target_strerror(int err)
 
 static abi_ulong target_brk;
 static abi_ulong target_original_brk;
+static abi_ulong brk_page;
 
 void target_set_brk(abi_ulong new_brk)
 {
     target_original_brk = target_brk = HOST_PAGE_ALIGN(new_brk);
+    brk_page = HOST_PAGE_ALIGN(target_brk);
 }
 
 /* do_brk() must return target values and target errnos. */
 abi_long do_brk(abi_ulong new_brk)
 {
-    abi_ulong brk_page;
     abi_long mapped_addr;
     int	new_alloc_size;
 
@@ -727,9 +728,8 @@ abi_long do_brk(abi_ulong new_brk)
     if (new_brk < target_original_brk)
         return target_brk;
 
-    brk_page = HOST_PAGE_ALIGN(target_brk);
-
-    /* If the new brk is less than this, set it and we're done... */
+    /* If the new brk is less than the highest page reserved to the
+     * target heap allocation, set it and we're done... */
     if (new_brk < brk_page) {
 	target_brk = new_brk;
     	return target_brk;
@@ -741,13 +741,14 @@ abi_long do_brk(abi_ulong new_brk)
      * itself); instead we treat "mapped but at wrong address" as
      * a failure and unmap again.
      */
-    new_alloc_size = HOST_PAGE_ALIGN(new_brk - brk_page + 1);
+    new_alloc_size = HOST_PAGE_ALIGN(new_brk - brk_page);
     mapped_addr = get_errno(target_mmap(brk_page, new_alloc_size,
                                         PROT_READ|PROT_WRITE,
                                         MAP_ANON|MAP_PRIVATE, 0, 0));
 
     if (mapped_addr == brk_page) {
         target_brk = new_brk;
+        brk_page = HOST_PAGE_ALIGN(target_brk);
         return target_brk;
     } else if (mapped_addr != -1) {
         /* Mapped but at wrong address, meaning there wasn't actually
-- 
1.7.5.1

  reply	other threads:[~2011-06-01  9:40 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2011-04-18 15:34 [Qemu-devel] [PATCH 0/3] Fix ARM semihosting SYS_HEAPINFO issues Peter Maydell
2011-04-18 15:34 ` [Qemu-devel] [PATCH 1/3] linux-user: Don't use MAP_FIXED in do_brk() Peter Maydell
2011-04-21 14:04   ` Peter Maydell
2011-06-01  9:37     ` Cédric VINCENT [this message]
2011-06-15  7:56       ` [Qemu-devel] [PATCH v2] linux-user: Fix the computation of the requested heap size Cédric VINCENT
2011-04-18 15:34 ` [Qemu-devel] [PATCH 2/3] arm-semi.c: Use correct check for failure of do_brk() Peter Maydell
2011-04-18 15:34 ` [Qemu-devel] [PATCH 3/3] m68k-semi.c: " Peter Maydell

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1306921039-27324-1-git-send-email-cedric.vincent@st.com \
    --to=cedric.vincent@st.com \
    --cc=christophe.guillon@st.com \
    --cc=martin.mohring@opensuse.org \
    --cc=mj.mccormack@samsung.com \
    --cc=peter.maydell@linaro.org \
    --cc=qemu-devel@nongnu.org \
    --cc=riku.voipio@iki.fi \
    --cc=stephen.clarke@st.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).