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