fixed page_unprotect() if host_page_size > TARGET_PAGE_SIZE
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@179 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
		
							parent
							
								
									b409186b8d
								
							
						
					
					
						commit
						1565b7bcd7
					
				
							
								
								
									
										29
									
								
								exec.c
									
									
									
									
									
								
							
							
						
						
									
										29
									
								
								exec.c
									
									
									
									
									
								
							@ -394,26 +394,29 @@ TranslationBlock *tb_alloc(unsigned long pc,
 | 
				
			|||||||
   page. Return TRUE if the fault was succesfully handled. */
 | 
					   page. Return TRUE if the fault was succesfully handled. */
 | 
				
			||||||
int page_unprotect(unsigned long address)
 | 
					int page_unprotect(unsigned long address)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    unsigned int page_index, prot;
 | 
					    unsigned int page_index, prot, pindex;
 | 
				
			||||||
    PageDesc *p;
 | 
					    PageDesc *p, *p1;
 | 
				
			||||||
    unsigned long host_start, host_end, addr;
 | 
					    unsigned long host_start, host_end, addr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    page_index = address >> TARGET_PAGE_BITS;
 | 
					    host_start = address & host_page_mask;
 | 
				
			||||||
    p = page_find(page_index);
 | 
					    page_index = host_start >> TARGET_PAGE_BITS;
 | 
				
			||||||
    if (!p)
 | 
					    p1 = page_find(page_index);
 | 
				
			||||||
 | 
					    if (!p1)
 | 
				
			||||||
        return 0;
 | 
					        return 0;
 | 
				
			||||||
    if ((p->flags & (PAGE_WRITE_ORG | PAGE_WRITE)) == PAGE_WRITE_ORG) {
 | 
					    host_end = host_start + host_page_size;
 | 
				
			||||||
 | 
					    p = p1;
 | 
				
			||||||
 | 
					    prot = 0;
 | 
				
			||||||
 | 
					    for(addr = host_start;addr < host_end; addr += TARGET_PAGE_SIZE) {
 | 
				
			||||||
 | 
					        prot |= p->flags;
 | 
				
			||||||
 | 
					        p++;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
    /* if the page was really writable, then we change its
 | 
					    /* if the page was really writable, then we change its
 | 
				
			||||||
       protection back to writable */
 | 
					       protection back to writable */
 | 
				
			||||||
        host_start = address & host_page_mask;
 | 
					    if (prot & PAGE_WRITE_ORG) {
 | 
				
			||||||
        host_end = host_start + host_page_size;
 | 
					 | 
				
			||||||
        prot = 0;
 | 
					 | 
				
			||||||
        for(addr = host_start; addr < host_end; addr += TARGET_PAGE_SIZE)
 | 
					 | 
				
			||||||
            prot |= page_get_flags(addr);
 | 
					 | 
				
			||||||
        mprotect((void *)host_start, host_page_size, 
 | 
					        mprotect((void *)host_start, host_page_size, 
 | 
				
			||||||
                 (prot & PAGE_BITS) | PAGE_WRITE);
 | 
					                 (prot & PAGE_BITS) | PAGE_WRITE);
 | 
				
			||||||
        p->flags |= PAGE_WRITE;
 | 
					        pindex = (address - host_start) >> TARGET_PAGE_BITS;
 | 
				
			||||||
 | 
					        p1[pindex].flags |= PAGE_WRITE;
 | 
				
			||||||
        /* and since the content will be modified, we must invalidate
 | 
					        /* and since the content will be modified, we must invalidate
 | 
				
			||||||
           the corresponding translated code. */
 | 
					           the corresponding translated code. */
 | 
				
			||||||
        tb_invalidate_page(address);
 | 
					        tb_invalidate_page(address);
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user