Revision dae3270c

b/cpu-all.h
690 690
void page_dump(FILE *f);
691 691
int page_get_flags(target_ulong address);
692 692
void page_set_flags(target_ulong start, target_ulong end, int flags);
693
void page_unprotect_range(target_ulong data, target_ulong data_size);
694 693
int page_check_range(target_ulong start, target_ulong len, int flags);
695 694

  
696 695
CPUState *cpu_copy(CPUState *env);
b/exec.c
1894 1894
        if( !(p->flags & PAGE_VALID) )
1895 1895
            return -1;
1896 1896

  
1897
        if (!(p->flags & PAGE_READ) && (flags & PAGE_READ) )
1898
            return -1;
1899
        if (!(p->flags & PAGE_WRITE) && (flags & PAGE_WRITE) )
1897
        if ((flags & PAGE_READ) && !(p->flags & PAGE_READ))
1900 1898
            return -1;
1899
        if (flags & PAGE_WRITE) {
1900
            if (!(p->flags & PAGE_WRITE_ORG))
1901
                return -1;
1902
            /* unprotect the page if it was put read-only because it
1903
               contains translated code */
1904
            if (!(p->flags & PAGE_WRITE)) {
1905
                if (!page_unprotect(addr, 0, NULL))
1906
                    return -1;
1907
            }
1908
            return 0;
1909
        }
1901 1910
    }
1902 1911
    return 0;
1903 1912
}
......
1942 1951
    return 0;
1943 1952
}
1944 1953

  
1945
/* call this function when system calls directly modify a memory area */
1946
/* ??? This should be redundant now we have lock_user.  */
1947
void page_unprotect_range(target_ulong data, target_ulong data_size)
1948
{
1949
    target_ulong start, end, addr;
1950

  
1951
    start = data;
1952
    end = start + data_size;
1953
    start &= TARGET_PAGE_MASK;
1954
    end = TARGET_PAGE_ALIGN(end);
1955
    for(addr = start; addr < end; addr += TARGET_PAGE_SIZE) {
1956
        page_unprotect(addr, 0, NULL);
1957
    }
1958
}
1959

  
1960 1954
static inline void tlb_set_dirty(CPUState *env,
1961 1955
                                 unsigned long addr, target_ulong vaddr)
1962 1956
{
b/linux-user/qemu.h
207 207
#define VERIFY_READ 0
208 208
#define VERIFY_WRITE 1 /* implies read access */
209 209

  
210
#define access_ok(type,addr,size) \
211
    (page_check_range((target_ulong)addr,size,(type==VERIFY_READ)?PAGE_READ:PAGE_WRITE)==0)
210
static inline int access_ok(int type, abi_ulong addr, abi_ulong size)
211
{
212
    return page_check_range((target_ulong)addr, size,
213
                            (type == VERIFY_READ) ? PAGE_READ : (PAGE_READ | PAGE_WRITE)) == 0;
214
}
212 215

  
213 216
/* NOTE __get_user and __put_user use host pointers and don't check access. */
214 217
/* These are usually used to access struct data members once the
b/linux-user/syscall.c
2773 2773
        ret = 0; /* avoid warning */
2774 2774
        break;
2775 2775
    case TARGET_NR_read:
2776
        page_unprotect_range(arg2, arg3);
2777 2776
        if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0)))
2778 2777
            goto efault;
2779 2778
        ret = get_errno(read(arg1, p, arg3));
......
4537 4536
        break;
4538 4537
#ifdef TARGET_NR_pread
4539 4538
    case TARGET_NR_pread:
4540
        page_unprotect_range(arg2, arg3);
4541 4539
        if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0)))
4542 4540
            goto efault;
4543 4541
        ret = get_errno(pread(arg1, p, arg3, arg4));

Also available in: Unified diff