Partialy fix mmap at EOF for large pagesize targets in user-mode.
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@gmail.com> git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@6510 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
		
							parent
							
								
									d6755878db
								
							
						
					
					
						commit
						54c5a2ae54
					
				@ -24,6 +24,8 @@
 | 
				
			|||||||
#include <string.h>
 | 
					#include <string.h>
 | 
				
			||||||
#include <unistd.h>
 | 
					#include <unistd.h>
 | 
				
			||||||
#include <errno.h>
 | 
					#include <errno.h>
 | 
				
			||||||
 | 
					#include <sys/types.h>
 | 
				
			||||||
 | 
					#include <sys/stat.h>
 | 
				
			||||||
#include <sys/mman.h>
 | 
					#include <sys/mman.h>
 | 
				
			||||||
#include <linux/mman.h>
 | 
					#include <linux/mman.h>
 | 
				
			||||||
#include <linux/unistd.h>
 | 
					#include <linux/unistd.h>
 | 
				
			||||||
@ -366,6 +368,36 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int prot,
 | 
				
			|||||||
        goto the_end;
 | 
					        goto the_end;
 | 
				
			||||||
    real_start = start & qemu_host_page_mask;
 | 
					    real_start = start & qemu_host_page_mask;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* When mapping files into a memory area larger than the file, accesses
 | 
				
			||||||
 | 
					       to pages beyond the file size will cause a SIGBUS. 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					       For example, if mmaping a file of 100 bytes on a host with 4K pages
 | 
				
			||||||
 | 
					       emulating a target with 8K pages, the target expects to be able to
 | 
				
			||||||
 | 
					       access the first 8K. But the host will trap us on any access beyond
 | 
				
			||||||
 | 
					       4K.  
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					       When emulating a target with a larger page-size than the hosts, we
 | 
				
			||||||
 | 
					       may need to truncate file maps at EOF and add extra anonymous pages
 | 
				
			||||||
 | 
					       up to the targets page boundary.  */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if ((qemu_real_host_page_size < TARGET_PAGE_SIZE)
 | 
				
			||||||
 | 
					        && !(flags & MAP_ANONYMOUS)) {
 | 
				
			||||||
 | 
					       struct stat sb;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					       if (fstat (fd, &sb) == -1)
 | 
				
			||||||
 | 
					           goto fail;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					       /* Are we trying to create a map beyond EOF?.  */
 | 
				
			||||||
 | 
					       if (offset + len > sb.st_size) {
 | 
				
			||||||
 | 
					           /* If so, truncate the file map at eof aligned with 
 | 
				
			||||||
 | 
					              the hosts real pagesize. Additional anonymous maps
 | 
				
			||||||
 | 
					              will be created beyond EOF.  */
 | 
				
			||||||
 | 
					           len = (sb.st_size - offset);
 | 
				
			||||||
 | 
					           len += qemu_real_host_page_size - 1;
 | 
				
			||||||
 | 
					           len &= ~(qemu_real_host_page_size - 1);
 | 
				
			||||||
 | 
					       }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (!(flags & MAP_FIXED)) {
 | 
					    if (!(flags & MAP_FIXED)) {
 | 
				
			||||||
        abi_ulong mmap_start;
 | 
					        abi_ulong mmap_start;
 | 
				
			||||||
        void *p;
 | 
					        void *p;
 | 
				
			||||||
@ -381,13 +413,16 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int prot,
 | 
				
			|||||||
           especially important if qemu_host_page_size >
 | 
					           especially important if qemu_host_page_size >
 | 
				
			||||||
           qemu_real_host_page_size */
 | 
					           qemu_real_host_page_size */
 | 
				
			||||||
        p = mmap(g2h(mmap_start),
 | 
					        p = mmap(g2h(mmap_start),
 | 
				
			||||||
                 host_len, prot, flags | MAP_FIXED, fd, host_offset);
 | 
					                 host_len, prot, flags | MAP_FIXED | MAP_ANONYMOUS, -1, 0);
 | 
				
			||||||
        if (p == MAP_FAILED)
 | 
					        if (p == MAP_FAILED)
 | 
				
			||||||
            goto fail;
 | 
					            goto fail;
 | 
				
			||||||
        /* update start so that it points to the file position at 'offset' */
 | 
					        /* update start so that it points to the file position at 'offset' */
 | 
				
			||||||
        host_start = (unsigned long)p;
 | 
					        host_start = (unsigned long)p;
 | 
				
			||||||
        if (!(flags & MAP_ANONYMOUS))
 | 
					        if (!(flags & MAP_ANONYMOUS)) {
 | 
				
			||||||
 | 
					            p = mmap(g2h(mmap_start), len, prot, 
 | 
				
			||||||
 | 
					                     flags | MAP_FIXED, fd, host_offset);
 | 
				
			||||||
            host_start += offset - host_offset;
 | 
					            host_start += offset - host_offset;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
        start = h2g(host_start);
 | 
					        start = h2g(host_start);
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
        int flg;
 | 
					        int flg;
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user