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