Patchwork [1/2] Support for MIPS64 user mode emulation

login
register
mail settings
Submitter Khansa Butt
Date June 16, 2011, 6:14 a.m.
Message ID <BANLkTimsmwZU-kNLVA5T1MBW7FaS6jKJFQ@mail.gmail.com>
Download mbox | patch
Permalink /patch/100590/
State New
Headers show

Comments

Khansa Butt - June 16, 2011, 6:14 a.m.
This is the case for 64 bit guest user mode static binary on 32 bit host.
Dynamically linked binary has not this problem
see in elfload.c:load_elf_image()
for (i = 0; i < ehdr->e_phnum; ++i) {
        if(phdr[i].p_type == PT_INTERP)
           dyn_link = 1;
        if (phdr[i].p_type == PT_LOAD) {
            abi_ulong a = phdr[i].p_vaddr;
            if (a < loaddr) {
                loaddr = a;
            }
            a += phdr[i].p_memsz;
            if (a > hiaddr) {
                hiaddr = a;
            }
#ifdef CONFIG_USE_FDPIC
            ++info->nsegs;
#endif
        }
    }

    load_addr = loaddr;
at this point load_addr has 64 bit value.
if (!have_guest_base && !reserved_va) {
            unsigned long host_start, real_start, host_size;

            /* Round addresses to page boundaries.  */
            loaddr &= qemu_host_page_mask;
            hiaddr = HOST_PAGE_ALIGN(hiaddr);
because of above loaddr is rounded to 32 bit value and
load_bias = load_addr - loaddr;
now load_addr has a big value which is added to entry point address which
causes problem.

for my MIPS64 bit statically linked ELF the variables loaddr and hiaddr have
36 bit values.
for probing guest_base these values are rounded to 32 bit as my underlying
OS is 32 bit Fedore13
because of this load_bais has value = 0x100000000
this load_bias is then added to entry point address and mem and file size of
the segment.
and the addresses which are starting from 0x120000000 are now changed to
0x220000000.
because of this when lladdr comes to SCD instruction in do_store_exclusive()
it does not get valid l1_map entry.
and because of which we made a fake page which was not correct way to do
although it was working.
so we did another workaround as follows
  linux-user/elfload.c |    6 +++++-
 1 files changed, 5 insertions(+), 1 deletions(-)

     /* First of all, some simple consistency checks */
@@ -1341,6 +1341,8 @@ static void load_elf_image(const char *image_name, int
image_fd,
        amount of memory to handle that.  */
     loaddr = -1, hiaddr = 0;
     for (i = 0; i < ehdr->e_phnum; ++i) {
+        if(phdr[i].p_type == PT_INTERP) /* Is the ELF dynamically linked?
+            dyn_link = 1;
         if (phdr[i].p_type == PT_LOAD) {
             abi_ulong a = phdr[i].p_vaddr;
             if (a < loaddr) {
@@ -1395,6 +1397,8 @@ static void load_elf_image(const char *image_name, int
image_fd,
                 }
             }
             host_size = hiaddr - loaddr;
+            if (!dyn_link)
+                /* ELF is statically linked */
+                load_addr = loaddr;
             while (1) {
                 /* Do not use mmap_find_vma here because that is limited to
the
                    guest address space.  We are going to make the
Richard Henderson - June 16, 2011, 2:49 p.m.
On 06/15/2011 11:14 PM, Khansa Butt wrote:
> for my MIPS64 bit statically linked ELF the variables loaddr and hiaddr have 36 bit values.
> for probing guest_base these values are rounded to 32 bit as my underlying OS is 32 bit Fedore13

Those last 8 words are the Real Problem.  We don't support 64-bit
address spaces in user mode from a 32-bit host.  Some 64-bit guest
tests accidentally work, but that's about all.

Try again with a proper 64-bit host.


r~

Patch

diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index dcfeb7a..9ab3296 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -1307,7 +1307,7 @@  static void load_elf_image(const char *image_name, int
image_fd,
     struct elfhdr *ehdr = (struct elfhdr *)bprm_buf;
     struct elf_phdr *phdr;
     abi_ulong load_addr, load_bias, loaddr, hiaddr, error;
-    int i, retval;
+    int i, retval, dyn_link;
     const char *errmsg;