Re: [Qemu-devel] [PATCH 1/2] Support for MIPS64 user mode emulation

2011-06-16 Thread Khansa Butt
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 = 0x1
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 0x12000 are now changed to
0x22000.
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(-)

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;

 /* 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
-- 
1.7.0.1
please give some comments regarding this workaround


Re: [Qemu-devel] [PATCH 1/2] Support for MIPS64 user mode emulation

2011-06-16 Thread Richard Henderson
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~



Re: [Qemu-devel] [PATCH 1/2] Support for MIPS64 user mode emulation

2011-06-08 Thread Khansa Butt
please see inline comments at the end.

On Fri, Apr 29, 2011 at 2:01 PM, Aurelien Jarno aurel...@aurel32.netwrote:

 On Mon, Apr 25, 2011 at 04:54:19PM +0500, Khansa Butt wrote:
  please see inline comments highlighted in red color.
 
  On Wed, Apr 13, 2011 at 2:32 AM, Aurelien Jarno aurel...@aurel32.net
 wrote:
 
   [I don't know very well linux-user, it would be nice to Cc: Riku
 Voipio,
the linux-user maintainer for the next version.]
  
   On Sat, Apr 09, 2011 at 04:02:31PM +0500, Khansa Butt wrote:
From e96e20e50cada1c9e1b65de5925281cdd5659746 Mon Sep 17 00:00:00
 2001
From: Ehsan-ul-Haq  Khansa Butt kha...@kics.edu.pk
Date: Sat, 9 Apr 2011 10:51:22 +0500
Subject: [PATCH 1/2] Support for MIPS64 user mode emulation
   
   
Signed-off-by: Ehsan-ul-Haq, Abdul Qadeer, Abdul Waheed, Khansa Butt
 
kha...@kics.edu.pk
---
 configure |1 +
 default-configs/mips64-linux-user.mak |1 +
 linux-user/elfload.c  |2 +-
 linux-user/main.c |   29
   +++--
 linux-user/mips64/syscall.h   |3 +++
 linux-user/signal.c   |3 ++-
 target-mips/translate.c   |1 +
 7 files changed, 36 insertions(+), 4 deletions(-)
 create mode 100644 default-configs/mips64-linux-user.mak
   
diff --git a/configure b/configure
index ae97e11..d1f7867 100755
--- a/configure
+++ b/configure
@@ -1039,6 +1039,7 @@ m68k-linux-user \
 microblaze-linux-user \
 microblazeel-linux-user \
 mips-linux-user \
+mips64-linux-user \
 mipsel-linux-user \
 ppc-linux-user \
 ppc64-linux-user \
diff --git a/default-configs/mips64-linux-user.mak
b/default-configs/mips64-linux-user.mak
new file mode 100644
index 000..1598bfc
--- /dev/null
+++ b/default-configs/mips64-linux-user.mak
@@ -0,0 +1 @@
+# Default configuration for mips64-linux-user
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index fe5410e..2832a33 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -1384,7 +1384,7 @@ static void load_elf_image(const char
 *image_name,
   int
image_fd,
 vaddr_po = TARGET_ELF_PAGEOFFSET(vaddr);
 vaddr_ps = TARGET_ELF_PAGESTART(vaddr);
   
-error = target_mmap(vaddr_ps, eppnt-p_filesz +
 vaddr_po,
+error = target_mmap(vaddr_ps, eppnt-p_memsz + vaddr_po,
  
   What is the goal of this change? If the mmapped aread is bigger than
 the
   file size rounded up to te page size, it will cause a SIGBUS.
  
 elf_prot, MAP_PRIVATE | MAP_FIXED,
 image_fd, eppnt-p_offset -
 vaddr_po);
 if (error == -1) {
diff --git a/linux-user/main.c b/linux-user/main.c
index e651bfd..a7f4955 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -1937,6 +1937,14 @@ static int do_store_exclusive(CPUMIPSState
 *env)
 int d;
   
 addr = env-lladdr;
+#if defined(TARGET_MIPS64)
+/* For MIPS64 on 32 bit host there is a need to make
+* the page accessible to which the above 'addr' is belonged */
+#if HOST_LONG_BITS == 32
+int flag = PAGE_VALID | PAGE_READ | PAGE_WRITE | PAGE_WRITE_ORG;
+page_set_flags(addr, addr + 4096, flag);
+#endif
+#endif
  
   I don't really see the reason why this should be done that way. Are you
   trying to run MIPS32 binaries compiled for 8kB page size?
  
 
 
 
  this change is needed when we run MIPS64 ELF on 32 bit x86 host. MIPS64
 ELF
  contains 36 bit address.

 Actually it can contains up to 62-bit address there (all the user mapped
 space).

   load_elf_image() at /home/khansa/testpatch/qemu/linux-user/elfload.c:
 QEMU
   contains these lines
 /* Round addresses to page boundaries.  */
  loaddr = qemu_host_page_mask;
  hiaddr = HOST_PAGE_ALIGN(hiaddr);
  when QEMU run on 32 bit x86 the above two variables are rounded to 32 bit
  value while these should be 36 bits as these come from MIPS64 ELF.and
 then

 It is correct to truncate them, as the address space of the host is
 smaller. It's just based on the fact that programs only need a subset of
 the 62 bit address space.

  for these rounded address l1_map is initialized in page_find_alloc().
  in case of SCD(store condition double ) instruction of MIPS64r2 when we
 have
  to check load linked address its again 36 bit so it will make an
 index(addr
   TARGET_PAGE_BITS) for which l1_map is no valid entry, returning 0
 value
  and we got segmentation fault. this is the reason we did following
 changes
  in main.c do_store_exclusive()

 No, the load linked address register size, as well as the shift is
 actually implementation dependent. On old 64-bit MIPS implementation
 and MIPS32 core it is a 32-bit register and a 4-bit 

Re: [Qemu-devel] [PATCH 1/2] Support for MIPS64 user mode emulation

2011-05-03 Thread Khansa Butt
I have made following changes
 addr = env-lladdr;
addr = qemu_host_page_mask;
 page_addr = addr  TARGET_PAGE_MASK;
 start_exclusive();
 mmap_lock();
 flags = page_get_flags(page_addr);
now return to elfload.c
I have a simple hello world mips64 binary for which I have two loadable
segments
so following rounded off address ranges passed to page_set_flags() in
target_mmap()
1) 0x2000 - 0x2008d000
2) 0x2009c000 - 0x200a6000
the last addresses of these ranges are not included in l1_map
because of the for loop condition in page_set_flags()

 for (addr = start, len = end - start;

len != 0;
len -= TARGET_PAGE_SIZE, addr += TARGET_PAGE_SIZE) {
while env-lladdr after rounding off belong to 0x200a6000 so in order to
include last address of above range i made following change
error = target_mmap(vaddr_ps, eppnt-p_memsz + v addr_po,
elf_prot, MAP_PRIVATE | MAP_FIXED,
image_fd, eppnt-p_offset - vaddr_po);
as mem size of a segment is greater than its file size but you told me that
it will cause SIGBUS
please suggest some solution for me in order to avoid target_mmap()
change(i.e. filesz to memsz)
or can I change condition of for loop some how so that one more iteration
will run for the last address.


On Fri, Apr 29, 2011 at 2:01 PM, Aurelien Jarno aurel...@aurel32.netwrote:

 On Mon, Apr 25, 2011 at 04:54:19PM +0500, Khansa Butt wrote:
  please see inline comments highlighted in red color.
 
  On Wed, Apr 13, 2011 at 2:32 AM, Aurelien Jarno aurel...@aurel32.net
 wrote:
 
   [I don't know very well linux-user, it would be nice to Cc: Riku
 Voipio,
the linux-user maintainer for the next version.]
  
   On Sat, Apr 09, 2011 at 04:02:31PM +0500, Khansa Butt wrote:
From e96e20e50cada1c9e1b65de5925281cdd5659746 Mon Sep 17 00:00:00
 2001
From: Ehsan-ul-Haq  Khansa Butt kha...@kics.edu.pk
Date: Sat, 9 Apr 2011 10:51:22 +0500
Subject: [PATCH 1/2] Support for MIPS64 user mode emulation
   
   
Signed-off-by: Ehsan-ul-Haq, Abdul Qadeer, Abdul Waheed, Khansa Butt
 
kha...@kics.edu.pk
---
 configure |1 +
 default-configs/mips64-linux-user.mak |1 +
 linux-user/elfload.c  |2 +-
 linux-user/main.c |   29
   +++--
 linux-user/mips64/syscall.h   |3 +++
 linux-user/signal.c   |3 ++-
 target-mips/translate.c   |1 +
 7 files changed, 36 insertions(+), 4 deletions(-)
 create mode 100644 default-configs/mips64-linux-user.mak
   
diff --git a/configure b/configure
index ae97e11..d1f7867 100755
--- a/configure
+++ b/configure
@@ -1039,6 +1039,7 @@ m68k-linux-user \
 microblaze-linux-user \
 microblazeel-linux-user \
 mips-linux-user \
+mips64-linux-user \
 mipsel-linux-user \
 ppc-linux-user \
 ppc64-linux-user \
diff --git a/default-configs/mips64-linux-user.mak
b/default-configs/mips64-linux-user.mak
new file mode 100644
index 000..1598bfc
--- /dev/null
+++ b/default-configs/mips64-linux-user.mak
@@ -0,0 +1 @@
+# Default configuration for mips64-linux-user
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index fe5410e..2832a33 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -1384,7 +1384,7 @@ static void load_elf_image(const char
 *image_name,
   int
image_fd,
 vaddr_po = TARGET_ELF_PAGEOFFSET(vaddr);
 vaddr_ps = TARGET_ELF_PAGESTART(vaddr);
   
-error = target_mmap(vaddr_ps, eppnt-p_filesz +
 vaddr_po,
+error = target_mmap(vaddr_ps, eppnt-p_memsz + vaddr_po,
  
   What is the goal of this change? If the mmapped aread is bigger than
 the
   file size rounded up to te page size, it will cause a SIGBUS.
  
 elf_prot, MAP_PRIVATE | MAP_FIXED,
 image_fd, eppnt-p_offset -
 vaddr_po);
 if (error == -1) {
diff --git a/linux-user/main.c b/linux-user/main.c
index e651bfd..a7f4955 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -1937,6 +1937,14 @@ static int do_store_exclusive(CPUMIPSState
 *env)
 int d;
   
 addr = env-lladdr;
+#if defined(TARGET_MIPS64)
+/* For MIPS64 on 32 bit host there is a need to make
+* the page accessible to which the above 'addr' is belonged */
+#if HOST_LONG_BITS == 32
+int flag = PAGE_VALID | PAGE_READ | PAGE_WRITE | PAGE_WRITE_ORG;
+page_set_flags(addr, addr + 4096, flag);
+#endif
+#endif
  
   I don't really see the reason why this should be done that way. Are you
   trying to run MIPS32 binaries compiled for 8kB page size?
  
 
 
 
  this change is needed when we run MIPS64 ELF on 32 bit x86 host. MIPS64
 ELF
  contains 36 bit address.

 Actually it can contains up to 

Re: [Qemu-devel] [PATCH 1/2] Support for MIPS64 user mode emulation

2011-04-29 Thread Aurelien Jarno
On Mon, Apr 25, 2011 at 04:54:19PM +0500, Khansa Butt wrote:
 please see inline comments highlighted in red color.
 
 On Wed, Apr 13, 2011 at 2:32 AM, Aurelien Jarno aurel...@aurel32.netwrote:
 
  [I don't know very well linux-user, it would be nice to Cc: Riku Voipio,
   the linux-user maintainer for the next version.]
 
  On Sat, Apr 09, 2011 at 04:02:31PM +0500, Khansa Butt wrote:
   From e96e20e50cada1c9e1b65de5925281cdd5659746 Mon Sep 17 00:00:00 2001
   From: Ehsan-ul-Haq  Khansa Butt kha...@kics.edu.pk
   Date: Sat, 9 Apr 2011 10:51:22 +0500
   Subject: [PATCH 1/2] Support for MIPS64 user mode emulation
  
  
   Signed-off-by: Ehsan-ul-Haq, Abdul Qadeer, Abdul Waheed, Khansa Butt 
   kha...@kics.edu.pk
   ---
configure |1 +
default-configs/mips64-linux-user.mak |1 +
linux-user/elfload.c  |2 +-
linux-user/main.c |   29
  +++--
linux-user/mips64/syscall.h   |3 +++
linux-user/signal.c   |3 ++-
target-mips/translate.c   |1 +
7 files changed, 36 insertions(+), 4 deletions(-)
create mode 100644 default-configs/mips64-linux-user.mak
  
   diff --git a/configure b/configure
   index ae97e11..d1f7867 100755
   --- a/configure
   +++ b/configure
   @@ -1039,6 +1039,7 @@ m68k-linux-user \
microblaze-linux-user \
microblazeel-linux-user \
mips-linux-user \
   +mips64-linux-user \
mipsel-linux-user \
ppc-linux-user \
ppc64-linux-user \
   diff --git a/default-configs/mips64-linux-user.mak
   b/default-configs/mips64-linux-user.mak
   new file mode 100644
   index 000..1598bfc
   --- /dev/null
   +++ b/default-configs/mips64-linux-user.mak
   @@ -0,0 +1 @@
   +# Default configuration for mips64-linux-user
   diff --git a/linux-user/elfload.c b/linux-user/elfload.c
   index fe5410e..2832a33 100644
   --- a/linux-user/elfload.c
   +++ b/linux-user/elfload.c
   @@ -1384,7 +1384,7 @@ static void load_elf_image(const char *image_name,
  int
   image_fd,
vaddr_po = TARGET_ELF_PAGEOFFSET(vaddr);
vaddr_ps = TARGET_ELF_PAGESTART(vaddr);
  
   -error = target_mmap(vaddr_ps, eppnt-p_filesz + vaddr_po,
   +error = target_mmap(vaddr_ps, eppnt-p_memsz + vaddr_po,
 
  What is the goal of this change? If the mmapped aread is bigger than the
  file size rounded up to te page size, it will cause a SIGBUS.
 
elf_prot, MAP_PRIVATE | MAP_FIXED,
image_fd, eppnt-p_offset - vaddr_po);
if (error == -1) {
   diff --git a/linux-user/main.c b/linux-user/main.c
   index e651bfd..a7f4955 100644
   --- a/linux-user/main.c
   +++ b/linux-user/main.c
   @@ -1937,6 +1937,14 @@ static int do_store_exclusive(CPUMIPSState *env)
int d;
  
addr = env-lladdr;
   +#if defined(TARGET_MIPS64)
   +/* For MIPS64 on 32 bit host there is a need to make
   +* the page accessible to which the above 'addr' is belonged */
   +#if HOST_LONG_BITS == 32
   +int flag = PAGE_VALID | PAGE_READ | PAGE_WRITE | PAGE_WRITE_ORG;
   +page_set_flags(addr, addr + 4096, flag);
   +#endif
   +#endif
 
  I don't really see the reason why this should be done that way. Are you
  trying to run MIPS32 binaries compiled for 8kB page size?
 
 
 
 
 this change is needed when we run MIPS64 ELF on 32 bit x86 host. MIPS64 ELF
 contains 36 bit address.

Actually it can contains up to 62-bit address there (all the user mapped
space).

  load_elf_image() at /home/khansa/testpatch/qemu/linux-user/elfload.c: QEMU
  contains these lines
/* Round addresses to page boundaries.  */
 loaddr = qemu_host_page_mask;
 hiaddr = HOST_PAGE_ALIGN(hiaddr);
 when QEMU run on 32 bit x86 the above two variables are rounded to 32 bit
 value while these should be 36 bits as these come from MIPS64 ELF.and then

It is correct to truncate them, as the address space of the host is
smaller. It's just based on the fact that programs only need a subset of
the 62 bit address space.

 for these rounded address l1_map is initialized in page_find_alloc().
 in case of SCD(store condition double ) instruction of MIPS64r2 when we have
 to check load linked address its again 36 bit so it will make an index(addr
  TARGET_PAGE_BITS) for which l1_map is no valid entry, returning 0 value
 and we got segmentation fault. this is the reason we did following changes
 in main.c do_store_exclusive()

No, the load linked address register size, as well as the shift is
actually implementation dependent. On old 64-bit MIPS implementation 
and MIPS32 core it is a 32-bit register and a 4-bit shift, where as 
on MIPS64 cores it is a 64-bit register and a 0-bit shift.

In any case this value is the *physical address*, not the *virtual
address*, hence we have to workaround that by saving the virtual 
address in the linux-user code. For 

Re: [Qemu-devel] [PATCH 1/2] Support for MIPS64 user mode emulation

2011-04-29 Thread Khansa Butt
Please see comments highlighted in green.

On Fri, Apr 29, 2011 at 2:01 PM, Aurelien Jarno aurel...@aurel32.netwrote:

 On Mon, Apr 25, 2011 at 04:54:19PM +0500, Khansa Butt wrote:
  please see inline comments highlighted in red color.
 
  On Wed, Apr 13, 2011 at 2:32 AM, Aurelien Jarno aurel...@aurel32.net
 wrote:
 
   [I don't know very well linux-user, it would be nice to Cc: Riku
 Voipio,
the linux-user maintainer for the next version.]
  
   On Sat, Apr 09, 2011 at 04:02:31PM +0500, Khansa Butt wrote:
From e96e20e50cada1c9e1b65de5925281cdd5659746 Mon Sep 17 00:00:00
 2001
From: Ehsan-ul-Haq  Khansa Butt kha...@kics.edu.pk
Date: Sat, 9 Apr 2011 10:51:22 +0500
Subject: [PATCH 1/2] Support for MIPS64 user mode emulation
   
   
Signed-off-by: Ehsan-ul-Haq, Abdul Qadeer, Abdul Waheed, Khansa Butt
 
kha...@kics.edu.pk
---
 configure |1 +
 default-configs/mips64-linux-user.mak |1 +
 linux-user/elfload.c  |2 +-
 linux-user/main.c |   29
   +++--
 linux-user/mips64/syscall.h   |3 +++
 linux-user/signal.c   |3 ++-
 target-mips/translate.c   |1 +
 7 files changed, 36 insertions(+), 4 deletions(-)
 create mode 100644 default-configs/mips64-linux-user.mak
   
diff --git a/configure b/configure
index ae97e11..d1f7867 100755
--- a/configure
+++ b/configure
@@ -1039,6 +1039,7 @@ m68k-linux-user \
 microblaze-linux-user \
 microblazeel-linux-user \
 mips-linux-user \
+mips64-linux-user \
 mipsel-linux-user \
 ppc-linux-user \
 ppc64-linux-user \
diff --git a/default-configs/mips64-linux-user.mak
b/default-configs/mips64-linux-user.mak
new file mode 100644
index 000..1598bfc
--- /dev/null
+++ b/default-configs/mips64-linux-user.mak
@@ -0,0 +1 @@
+# Default configuration for mips64-linux-user
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index fe5410e..2832a33 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -1384,7 +1384,7 @@ static void load_elf_image(const char
 *image_name,
   int
image_fd,
 vaddr_po = TARGET_ELF_PAGEOFFSET(vaddr);
 vaddr_ps = TARGET_ELF_PAGESTART(vaddr);
   
-error = target_mmap(vaddr_ps, eppnt-p_filesz +
 vaddr_po,
+error = target_mmap(vaddr_ps, eppnt-p_memsz + vaddr_po,
  
   What is the goal of this change? If the mmapped aread is bigger than
 the
   file size rounded up to te page size, it will cause a SIGBUS.
  
 elf_prot, MAP_PRIVATE | MAP_FIXED,
 image_fd, eppnt-p_offset -
 vaddr_po);
 if (error == -1) {
diff --git a/linux-user/main.c b/linux-user/main.c
index e651bfd..a7f4955 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -1937,6 +1937,14 @@ static int do_store_exclusive(CPUMIPSState
 *env)
 int d;
   
 addr = env-lladdr;
+#if defined(TARGET_MIPS64)
+/* For MIPS64 on 32 bit host there is a need to make
+* the page accessible to which the above 'addr' is belonged */
+#if HOST_LONG_BITS == 32
+int flag = PAGE_VALID | PAGE_READ | PAGE_WRITE | PAGE_WRITE_ORG;
+page_set_flags(addr, addr + 4096, flag);
+#endif
+#endif
  
   I don't really see the reason why this should be done that way. Are you
   trying to run MIPS32 binaries compiled for 8kB page size?
  
 
 
 
  this change is needed when we run MIPS64 ELF on 32 bit x86 host. MIPS64
 ELF
  contains 36 bit address.

 Actually it can contains up to 62-bit address there (all the user mapped
 space).

   load_elf_image() at /home/khansa/testpatch/qemu/linux-user/elfload.c:
 QEMU
   contains these lines
 /* Round addresses to page boundaries.  */
  loaddr = qemu_host_page_mask;
  hiaddr = HOST_PAGE_ALIGN(hiaddr);
  when QEMU run on 32 bit x86 the above two variables are rounded to 32 bit
  value while these should be 36 bits as these come from MIPS64 ELF.and
 then

 It is correct to truncate them, as the address space of the host is
 smaller. It's just based on the fact that programs only need a subset of
 the 62 bit address space.

  for these rounded address l1_map is initialized in page_find_alloc().
  in case of SCD(store condition double ) instruction of MIPS64r2 when we
 have
  to check load linked address its again 36 bit so it will make an
 index(addr
   TARGET_PAGE_BITS) for which l1_map is no valid entry, returning 0
 value
  and we got segmentation fault. this is the reason we did following
 changes
  in main.c do_store_exclusive()

 No, the load linked address register size, as well as the shift is
 actually implementation dependent. On old 64-bit MIPS implementation
 and MIPS32 core it is a 32-bit register and a 4-bit 

Re: [Qemu-devel] [PATCH 1/2] Support for MIPS64 user mode emulation

2011-04-25 Thread Khansa Butt
please see inline comments highlighted in red color.

On Wed, Apr 13, 2011 at 2:32 AM, Aurelien Jarno aurel...@aurel32.netwrote:

 [I don't know very well linux-user, it would be nice to Cc: Riku Voipio,
  the linux-user maintainer for the next version.]

 On Sat, Apr 09, 2011 at 04:02:31PM +0500, Khansa Butt wrote:
  From e96e20e50cada1c9e1b65de5925281cdd5659746 Mon Sep 17 00:00:00 2001
  From: Ehsan-ul-Haq  Khansa Butt kha...@kics.edu.pk
  Date: Sat, 9 Apr 2011 10:51:22 +0500
  Subject: [PATCH 1/2] Support for MIPS64 user mode emulation
 
 
  Signed-off-by: Ehsan-ul-Haq, Abdul Qadeer, Abdul Waheed, Khansa Butt 
  kha...@kics.edu.pk
  ---
   configure |1 +
   default-configs/mips64-linux-user.mak |1 +
   linux-user/elfload.c  |2 +-
   linux-user/main.c |   29
 +++--
   linux-user/mips64/syscall.h   |3 +++
   linux-user/signal.c   |3 ++-
   target-mips/translate.c   |1 +
   7 files changed, 36 insertions(+), 4 deletions(-)
   create mode 100644 default-configs/mips64-linux-user.mak
 
  diff --git a/configure b/configure
  index ae97e11..d1f7867 100755
  --- a/configure
  +++ b/configure
  @@ -1039,6 +1039,7 @@ m68k-linux-user \
   microblaze-linux-user \
   microblazeel-linux-user \
   mips-linux-user \
  +mips64-linux-user \
   mipsel-linux-user \
   ppc-linux-user \
   ppc64-linux-user \
  diff --git a/default-configs/mips64-linux-user.mak
  b/default-configs/mips64-linux-user.mak
  new file mode 100644
  index 000..1598bfc
  --- /dev/null
  +++ b/default-configs/mips64-linux-user.mak
  @@ -0,0 +1 @@
  +# Default configuration for mips64-linux-user
  diff --git a/linux-user/elfload.c b/linux-user/elfload.c
  index fe5410e..2832a33 100644
  --- a/linux-user/elfload.c
  +++ b/linux-user/elfload.c
  @@ -1384,7 +1384,7 @@ static void load_elf_image(const char *image_name,
 int
  image_fd,
   vaddr_po = TARGET_ELF_PAGEOFFSET(vaddr);
   vaddr_ps = TARGET_ELF_PAGESTART(vaddr);
 
  -error = target_mmap(vaddr_ps, eppnt-p_filesz + vaddr_po,
  +error = target_mmap(vaddr_ps, eppnt-p_memsz + vaddr_po,

 What is the goal of this change? If the mmapped aread is bigger than the
 file size rounded up to te page size, it will cause a SIGBUS.

   elf_prot, MAP_PRIVATE | MAP_FIXED,
   image_fd, eppnt-p_offset - vaddr_po);
   if (error == -1) {
  diff --git a/linux-user/main.c b/linux-user/main.c
  index e651bfd..a7f4955 100644
  --- a/linux-user/main.c
  +++ b/linux-user/main.c
  @@ -1937,6 +1937,14 @@ static int do_store_exclusive(CPUMIPSState *env)
   int d;
 
   addr = env-lladdr;
  +#if defined(TARGET_MIPS64)
  +/* For MIPS64 on 32 bit host there is a need to make
  +* the page accessible to which the above 'addr' is belonged */
  +#if HOST_LONG_BITS == 32
  +int flag = PAGE_VALID | PAGE_READ | PAGE_WRITE | PAGE_WRITE_ORG;
  +page_set_flags(addr, addr + 4096, flag);
  +#endif
  +#endif

 I don't really see the reason why this should be done that way. Are you
 trying to run MIPS32 binaries compiled for 8kB page size?




this change is needed when we run MIPS64 ELF on 32 bit x86 host. MIPS64 ELF
contains 36 bit address.
 load_elf_image() at /home/khansa/testpatch/qemu/linux-user/elfload.c: QEMU
 contains these lines
   /* Round addresses to page boundaries.  */
loaddr = qemu_host_page_mask;
hiaddr = HOST_PAGE_ALIGN(hiaddr);
when QEMU run on 32 bit x86 the above two variables are rounded to 32 bit
value while these should be 36 bits as these come from MIPS64 ELF.and then
for these rounded address l1_map is initialized in page_find_alloc().
in case of SCD(store condition double ) instruction of MIPS64r2 when we have
to check load linked address its again 36 bit so it will make an index(addr
 TARGET_PAGE_BITS) for which l1_map is no valid entry, returning 0 value
and we got segmentation fault. this is the reason we did following changes
in main.c do_store_exclusive()

 +#if HOST_LONG_BITS == 32
 +int flag = PAGE_VALID | PAGE_READ | PAGE_WRITE | PAGE_WRITE_ORG;
 +page_set_flags(addr, addr + 4096, flag);
 +#endif
Please give comments on this



   page_addr = addr  TARGET_PAGE_MASK;
   start_exclusive();
   mmap_lock();
  @@ -1978,7 +1986,8 @@ static int do_store_exclusive(CPUMIPSState *env)
   void cpu_loop(CPUMIPSState *env)
   {
   target_siginfo_t info;
  -int trapnr, ret;
  +int trapnr;
  +abi_long ret;
   unsigned int syscall_num;
 
   for(;;) {
  @@ -1987,7 +1996,11 @@ void cpu_loop(CPUMIPSState *env)
   cpu_exec_end(env);
   switch(trapnr) {
   case EXCP_SYSCALL:
  +#if defined(TARGET_MIPS64)
  +syscall_num = env-active_tc.gpr[2] - 5000;
  +#else
   syscall_num = env-active_tc.gpr[2] - 4000;
  +#endif

Re: [Qemu-devel] [PATCH 1/2] Support for MIPS64 user mode emulation

2011-04-12 Thread Aurelien Jarno
[I don't know very well linux-user, it would be nice to Cc: Riku Voipio,
 the linux-user maintainer for the next version.]

On Sat, Apr 09, 2011 at 04:02:31PM +0500, Khansa Butt wrote:
 From e96e20e50cada1c9e1b65de5925281cdd5659746 Mon Sep 17 00:00:00 2001
 From: Ehsan-ul-Haq  Khansa Butt kha...@kics.edu.pk
 Date: Sat, 9 Apr 2011 10:51:22 +0500
 Subject: [PATCH 1/2] Support for MIPS64 user mode emulation
 
 
 Signed-off-by: Ehsan-ul-Haq, Abdul Qadeer, Abdul Waheed, Khansa Butt 
 kha...@kics.edu.pk
 ---
  configure |1 +
  default-configs/mips64-linux-user.mak |1 +
  linux-user/elfload.c  |2 +-
  linux-user/main.c |   29 +++--
  linux-user/mips64/syscall.h   |3 +++
  linux-user/signal.c   |3 ++-
  target-mips/translate.c   |1 +
  7 files changed, 36 insertions(+), 4 deletions(-)
  create mode 100644 default-configs/mips64-linux-user.mak
 
 diff --git a/configure b/configure
 index ae97e11..d1f7867 100755
 --- a/configure
 +++ b/configure
 @@ -1039,6 +1039,7 @@ m68k-linux-user \
  microblaze-linux-user \
  microblazeel-linux-user \
  mips-linux-user \
 +mips64-linux-user \
  mipsel-linux-user \
  ppc-linux-user \
  ppc64-linux-user \
 diff --git a/default-configs/mips64-linux-user.mak
 b/default-configs/mips64-linux-user.mak
 new file mode 100644
 index 000..1598bfc
 --- /dev/null
 +++ b/default-configs/mips64-linux-user.mak
 @@ -0,0 +1 @@
 +# Default configuration for mips64-linux-user
 diff --git a/linux-user/elfload.c b/linux-user/elfload.c
 index fe5410e..2832a33 100644
 --- a/linux-user/elfload.c
 +++ b/linux-user/elfload.c
 @@ -1384,7 +1384,7 @@ static void load_elf_image(const char *image_name, int
 image_fd,
  vaddr_po = TARGET_ELF_PAGEOFFSET(vaddr);
  vaddr_ps = TARGET_ELF_PAGESTART(vaddr);
 
 -error = target_mmap(vaddr_ps, eppnt-p_filesz + vaddr_po,
 +error = target_mmap(vaddr_ps, eppnt-p_memsz + vaddr_po,

What is the goal of this change? If the mmapped aread is bigger than the
file size rounded up to te page size, it will cause a SIGBUS.

  elf_prot, MAP_PRIVATE | MAP_FIXED,
  image_fd, eppnt-p_offset - vaddr_po);
  if (error == -1) {
 diff --git a/linux-user/main.c b/linux-user/main.c
 index e651bfd..a7f4955 100644
 --- a/linux-user/main.c
 +++ b/linux-user/main.c
 @@ -1937,6 +1937,14 @@ static int do_store_exclusive(CPUMIPSState *env)
  int d;
 
  addr = env-lladdr;
 +#if defined(TARGET_MIPS64)
 +/* For MIPS64 on 32 bit host there is a need to make
 +* the page accessible to which the above 'addr' is belonged */
 +#if HOST_LONG_BITS == 32
 +int flag = PAGE_VALID | PAGE_READ | PAGE_WRITE | PAGE_WRITE_ORG;
 +page_set_flags(addr, addr + 4096, flag);
 +#endif
 +#endif

I don't really see the reason why this should be done that way. Are you
trying to run MIPS32 binaries compiled for 8kB page size?

  page_addr = addr  TARGET_PAGE_MASK;
  start_exclusive();
  mmap_lock();
 @@ -1978,7 +1986,8 @@ static int do_store_exclusive(CPUMIPSState *env)
  void cpu_loop(CPUMIPSState *env)
  {
  target_siginfo_t info;
 -int trapnr, ret;
 +int trapnr;
 +abi_long ret;
  unsigned int syscall_num;
 
  for(;;) {
 @@ -1987,7 +1996,11 @@ void cpu_loop(CPUMIPSState *env)
  cpu_exec_end(env);
  switch(trapnr) {
  case EXCP_SYSCALL:
 +#if defined(TARGET_MIPS64)
 +syscall_num = env-active_tc.gpr[2] - 5000;
 +#else
  syscall_num = env-active_tc.gpr[2] - 4000;
 +#endif
  env-active_tc.PC += 4;
  if (syscall_num = sizeof(mips_syscall_args)) {

I don't think you can do it like that. mips_syscall_args corresponds to
a table of 32-bit syscalls, which have totally different numbers than
64-bit syscalls. It's not a simple shift by 1000. See for example
pread64 is 4200 is 32-bit, 5016 in 64-bit.

  ret = -ENOSYS;
 @@ -2008,12 +2021,22 @@ void cpu_loop(CPUMIPSState *env)
  default:
  break;
  }
 +#if defined(TARGET_MIPS64)
 +ret = do_syscall(env, env-active_tc.gpr[2],
 + env-active_tc.gpr[4],
 + env-active_tc.gpr[5],
 + env-active_tc.gpr[6],
 + env-active_tc.gpr[7],
 + env-active_tc.gpr[8],
 + env-active_tc.gpr[9]);
 +#else
  ret = do_syscall(env, env-active_tc.gpr[2],
   env-active_tc.gpr[4],
   env-active_tc.gpr[5],
   env-active_tc.gpr[6],
   env-active_tc.gpr[7],
   arg5, arg6/*, arg7, arg8*/);