* [Qemu-devel] TARGET_PAGE_SIZE > host page size
@ 2007-09-21 13:29 Edgar E. Iglesias
2007-09-21 15:43 ` Paul Brook
0 siblings, 1 reply; 4+ messages in thread
From: Edgar E. Iglesias @ 2007-09-21 13:29 UTC (permalink / raw)
To: qemu-devel
Hello,
I'm working on a new target port and the linux-user emulation is fairly functional and passing quite extensive test-suites.
I've got a problem though, my target has 8K page sizes, so for example when running on a x86 host TARGET_PAGE_SIZE > host page size.
I'm not very familiar with linux-user/mmap.c, but I though I'd let you know that with this patch things seem to be working fine for me. I am not sure if the patch is correct so if anyone with more experience sees an obvious flaw I'd appreciate to know.
Thanks!
Edgar E. Iglesias
Axis Communications AB
Index: linux-user/mmap.c
===================================================================
RCS file: /sources/qemu/qemu/linux-user/mmap.c,v
retrieving revision 1.14
diff -u -p -b -u -p -r1.14 mmap.c
--- linux-user/mmap.c 17 Sep 2007 08:09:49 -0000 1.14
+++ linux-user/mmap.c 21 Sep 2007 13:24:42 -0000
@@ -209,26 +209,34 @@ long target_mmap(target_ulong start, tar
last_start += HOST_PAGE_ALIGN(len);
}
#endif
- if (0 && qemu_host_page_size != qemu_real_host_page_size) {
+ if (qemu_host_page_size != qemu_real_host_page_size) {
/* NOTE: this code is only for debugging with '-p' option */
/* ??? Can also occur when TARGET_PAGE_SIZE > host page size. */
/* reserve a memory area */
/* ??? This needs fixing for remapping. */
-abort();
- host_len = HOST_PAGE_ALIGN(len) + qemu_host_page_size - TARGET_PAGE_SIZE;
+
+ /* Make sure we have enough room for fixing up the buffer. */
+ host_len = HOST_PAGE_ALIGN(len + TARGET_PAGE_SIZE);
real_start = (long)mmap(g2h(real_start), host_len, PROT_NONE,
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
if (real_start == -1)
return real_start;
real_end = real_start + host_len;
- start = HOST_PAGE_ALIGN(real_start);
- end = start + HOST_PAGE_ALIGN(len);
+
+ /* Find start and end, aligned to the targets pagesize with-in the
+ mmaped area. */
+ start = TARGET_PAGE_ALIGN(real_start);
+ end = start + TARGET_PAGE_ALIGN(len);
+ /* Chop off the leftovers, if any. */
if (start > real_start)
munmap((void *)real_start, start - real_start);
if (end < real_end)
munmap((void *)end, real_end - end);
/* use it as a fixed mapping */
flags |= MAP_FIXED;
+ /* These are now real. */
+ real_start = start;
+ real_end = end;
} else {
/* if not fixed, no need to do anything */
host_offset = offset & qemu_host_page_mask;
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [Qemu-devel] TARGET_PAGE_SIZE > host page size
2007-09-21 13:29 [Qemu-devel] TARGET_PAGE_SIZE > host page size Edgar E. Iglesias
@ 2007-09-21 15:43 ` Paul Brook
2007-09-22 1:08 ` Edgar E. Iglesias
2007-09-22 7:34 ` Edgar E. Iglesias
0 siblings, 2 replies; 4+ messages in thread
From: Paul Brook @ 2007-09-21 15:43 UTC (permalink / raw)
To: qemu-devel; +Cc: Edgar E. Iglesias
On Friday 21 September 2007, Edgar E. Iglesias wrote:
> Hello,
>
> I'm working on a new target port and the linux-user emulation is fairly
> functional and passing quite extensive test-suites.
>
> I've got a problem though, my target has 8K page sizes, so for example when
> running on a x86 host TARGET_PAGE_SIZE > host page size.
>
> I'm not very familiar with linux-user/mmap.c, but I though I'd let you know
> that with this patch things seem to be working fine for me. I am not sure
> if the patch is correct so if anyone with more experience sees an obvious
> flaw I'd appreciate to know.
qemu_host_page_size is always >= TARGET_PAGE_SIZE. See exec.c.
There are several existing target that have >4k page sizes.
Paul
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [Qemu-devel] TARGET_PAGE_SIZE > host page size
2007-09-21 15:43 ` Paul Brook
@ 2007-09-22 1:08 ` Edgar E. Iglesias
2007-09-22 7:34 ` Edgar E. Iglesias
1 sibling, 0 replies; 4+ messages in thread
From: Edgar E. Iglesias @ 2007-09-22 1:08 UTC (permalink / raw)
To: qemu-devel
On Fri, Sep 21, 2007 at 04:43:37PM +0100, Paul Brook wrote:
> On Friday 21 September 2007, Edgar E. Iglesias wrote:
> > Hello,
> >
> > I'm working on a new target port and the linux-user emulation is fairly
> > functional and passing quite extensive test-suites.
> >
> > I've got a problem though, my target has 8K page sizes, so for example when
> > running on a x86 host TARGET_PAGE_SIZE > host page size.
> >
> > I'm not very familiar with linux-user/mmap.c, but I though I'd let you know
> > that with this patch things seem to be working fine for me. I am not sure
> > if the patch is correct so if anyone with more experience sees an obvious
> > flaw I'd appreciate to know.
>
> qemu_host_page_size is always >= TARGET_PAGE_SIZE. See exec.c.
> There are several existing target that have >4k page sizes.
Thanks alot for the info I'll investigate this more.
A quick look shows that qemu_real_host_page_size is not = TARGET_PAGE_SIZE. As far as I can see, target_mmap is not doing the right thing when the guest page size is larger than the host page size. mmap might return an unaligned area to the guest code which results in target_mmap returning -1. Maybe I forgot to define something in the target specific files?
Best regards
--
Edgar E. Iglesias
Axis Communications AB
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [Qemu-devel] TARGET_PAGE_SIZE > host page size
2007-09-21 15:43 ` Paul Brook
2007-09-22 1:08 ` Edgar E. Iglesias
@ 2007-09-22 7:34 ` Edgar E. Iglesias
1 sibling, 0 replies; 4+ messages in thread
From: Edgar E. Iglesias @ 2007-09-22 7:34 UTC (permalink / raw)
To: Paul Brook; +Cc: qemu-devel
On Fri, Sep 21, 2007 at 04:43:37PM +0100, Paul Brook wrote:
> On Friday 21 September 2007, Edgar E. Iglesias wrote:
> > Hello,
> >
> > I'm working on a new target port and the linux-user emulation is fairly
> > functional and passing quite extensive test-suites.
> >
> > I've got a problem though, my target has 8K page sizes, so for example when
> > running on a x86 host TARGET_PAGE_SIZE > host page size.
> >
> > I'm not very familiar with linux-user/mmap.c, but I though I'd let you know
> > that with this patch things seem to be working fine for me. I am not sure
> > if the patch is correct so if anyone with more experience sees an obvious
> > flaw I'd appreciate to know.
>
> qemu_host_page_size is always >= TARGET_PAGE_SIZE. See exec.c.
> There are several existing target that have >4k page sizes.
Hi again,
I had a look at this last night and it seems to be a combination of the elf loader for linux-user and target_mmap that are causing the problems I am seeing.
target_mmap is (as it is coded now) allowed to return addresses that are not aligned to the target page size but it (correctly) does not allow the request of fixed mappings for unaligned addresses. IMO things would be simpler if we made sure target_mmap always returns target pagesize aligned addresses.
If target_mmap returns a target pagesize unaligned address when the elf loader is loading the ELF interpreter, more specifically when mapping the load address of the interpreter, subsequent calls for mapping each segment will be made for MAP_FIXED areas of the unaligned load_addr + segment offsets. This offsets may not be target pagesize aligned and target_mmap will correctly fail to mmap the segments. See load_elf_interp in elfload.c.
The patch I sent in previous emails makes target_mmap return target page aligned addresses and avoids this issue.
I attach output from a debug run further down.
Thanks.
[snip]
mmap: start=0x0 len=0x2000000 prot=--- flags=MAP_ANON MAP_PRIVATE fd=-1 offset=0
target_mmap target_mmap returns an ualigned address b5cb9000.
ret=0xb5cb9000
start end size prot
00080000-00082000 00002000 r-x
00082000-00084000 00002000 rw-
b5cb8000-b7cba000 02002000 ---
b7cba000-b7d3c000 00082000 rw-
load_elf_interp ELF interp at unaligned target addr b5cb9000.
ELF loader map b5cb9000 fixed=16
mmap: start=0xb5cb9000 len=0xedeb prot=r-x flags=MAP_FIXED MAP_PRIVATE fd=5 offset=0
target_mmap fixed mapping of target-unaligned addr=b5cb9000 denied.
Unable to load interpreter
------
These are the elf program headers for my dynamic loader:
laped:test % readelf-cris --segments /usr/local/cris/r63v32/crisv32-axis-linux-gnu/lib/ld.so.1
Elf file type is DYN (Shared object file)
Entry point 0x1378
There are 3 program headers, starting at offset 52
Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
LOAD 0x000000 0x00000000 0x00000000 0x0edeb 0x0edeb R E 0x2000
LOAD 0x00ee00 0x00010e00 0x00010e00 0x002a4 0x00640 RW 0x2000
DYNAMIC 0x00eea4 0x00010ea4 0x00010ea4 0x000b0 0x000b0 RW 0x4
Section to Segment mapping:
Segment Sections...
00 .hash .dynsym .dynstr .gnu.version .gnu.version_d .rela.data .rela.got .rela.plt .plt .text .rodata
01 .data .dynamic .got .bss
02 .dynamic
------
This is what I used to debug:
Index: mmap.c
===================================================================
RCS file: /sources/qemu/qemu/linux-user/mmap.c,v
retrieving revision 1.14
diff -u -p -b -u -p -r1.14 mmap.c
--- mmap.c 17 Sep 2007 08:09:49 -0000 1.14
+++ mmap.c 22 Sep 2007 07:03:57 -0000
@@ -27,7 +27,7 @@
#include "qemu.h"
-//#define DEBUG_MMAP
+#define DEBUG_MMAP
/* NOTE: all the constants are the HOST ones, but addresses are target. */
int target_mprotect(target_ulong start, target_ulong len, int prot)
@@ -246,6 +246,8 @@ abort();
}
if (start & ~TARGET_PAGE_MASK) {
+ printf ("%s fixed mapping of target-unaligned addr=%x denied.\n",
+ __func__, start);
errno = EINVAL;
return -1;
}
@@ -320,6 +322,10 @@ abort();
page_set_flags(start, start + len, prot | PAGE_VALID);
the_end:
#ifdef DEBUG_MMAP
+ if (start & ~TARGET_PAGE_MASK) {
+ printf ("%s target_mmap returns an ualigned address %x.\n",
+ __func__, start);
+ }
printf("ret=0x%lx\n", (long)start);
page_dump(stdout);
printf("\n");
Index: elfload.c
===================================================================
RCS file: /sources/qemu/qemu/linux-user/elfload.c,v
retrieving revision 1.46
diff -u -p -b -u -p -r1.46 elfload.c
--- elfload.c 17 Sep 2007 08:09:49 -0000 1.46
+++ elfload.c 22 Sep 2007 07:03:57 -0000
@@ -333,6 +333,27 @@ static inline void init_thread(struct ta
#endif
+#ifdef TARGET_CRIS
+
+#define ELF_START_MMAP 0x80000000
+
+#define elf_check_arch(x) ( (x) == EM_CRIS )
+
+#define ELF_CLASS ELFCLASS32
+#define ELF_DATA ELFDATA2LSB
+#define ELF_ARCH EM_CRIS
+
+static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop)
+{
+ /* Check other registers XXXXX */
+ regs->erp = infop->entry;
+}
+
+#define USE_ELF_CORE_DUMP
+#define ELF_EXEC_PAGESIZE 8192
+
+#endif
+
#ifdef TARGET_M68K
#define ELF_START_MMAP 0x80000000
@@ -810,6 +831,10 @@ static unsigned long load_elf_interp(str
}
load_addr = error;
load_addr_set = 1;
+ if (load_addr & ~TARGET_PAGE_MASK) {
+ printf ("%s ELF interp at unaligned target addr %x.\n",
+ __func__, load_addr);
+ }
}
eppnt = elf_phdata;
@@ -827,6 +852,9 @@ static unsigned long load_elf_interp(str
elf_type |= MAP_FIXED;
vaddr = eppnt->p_vaddr;
}
+ printf ("ELF loader map %x fixed=%d\n",
+ load_addr+TARGET_ELF_PAGESTART(vaddr),
+ elf_type & MAP_FIXED);
error = target_mmap(load_addr+TARGET_ELF_PAGESTART(vaddr),
eppnt->p_filesz + TARGET_ELF_PAGEOFFSET(eppnt->p_vaddr),
elf_prot,
--
Edgar E. Iglesias
Axis Communications AB
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2007-09-22 7:34 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-09-21 13:29 [Qemu-devel] TARGET_PAGE_SIZE > host page size Edgar E. Iglesias
2007-09-21 15:43 ` Paul Brook
2007-09-22 1:08 ` Edgar E. Iglesias
2007-09-22 7:34 ` Edgar E. Iglesias
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.