Revision 53a5960a exec.c
b/exec.c | ||
---|---|---|
34 | 34 |
|
35 | 35 |
#include "cpu.h" |
36 | 36 |
#include "exec-all.h" |
37 |
#if defined(CONFIG_USER_ONLY) |
|
38 |
#include <qemu.h> |
|
39 |
#endif |
|
37 | 40 |
|
38 | 41 |
//#define DEBUG_TB_INVALIDATE |
39 | 42 |
//#define DEBUG_FLUSH |
... | ... | |
810 | 813 |
|
811 | 814 |
/* add the tb in the target page and protect it if necessary */ |
812 | 815 |
static inline void tb_alloc_page(TranslationBlock *tb, |
813 |
unsigned int n, unsigned int page_addr)
|
|
816 |
unsigned int n, target_ulong page_addr)
|
|
814 | 817 |
{ |
815 | 818 |
PageDesc *p; |
816 | 819 |
TranslationBlock *last_first_tb; |
... | ... | |
826 | 829 |
|
827 | 830 |
#if defined(CONFIG_USER_ONLY) |
828 | 831 |
if (p->flags & PAGE_WRITE) { |
829 |
unsigned long host_start, host_end, addr; |
|
832 |
target_ulong addr; |
|
833 |
PageDesc *p2; |
|
830 | 834 |
int prot; |
831 | 835 |
|
832 | 836 |
/* force the host page as non writable (writes will have a |
833 | 837 |
page fault + mprotect overhead) */ |
834 |
host_start = page_addr & qemu_host_page_mask; |
|
835 |
host_end = host_start + qemu_host_page_size; |
|
838 |
page_addr &= qemu_host_page_mask; |
|
836 | 839 |
prot = 0; |
837 |
for(addr = host_start; addr < host_end; addr += TARGET_PAGE_SIZE) |
|
838 |
prot |= page_get_flags(addr); |
|
839 |
mprotect((void *)host_start, qemu_host_page_size, |
|
840 |
for(addr = page_addr; addr < page_addr + qemu_host_page_size; |
|
841 |
addr += TARGET_PAGE_SIZE) { |
|
842 |
|
|
843 |
p2 = page_find (addr >> TARGET_PAGE_BITS); |
|
844 |
if (!p2) |
|
845 |
continue; |
|
846 |
prot |= p2->flags; |
|
847 |
p2->flags &= ~PAGE_WRITE; |
|
848 |
page_get_flags(addr); |
|
849 |
} |
|
850 |
mprotect(g2h(page_addr), qemu_host_page_size, |
|
840 | 851 |
(prot & PAGE_BITS) & ~PAGE_WRITE); |
841 | 852 |
#ifdef DEBUG_TB_INVALIDATE |
842 | 853 |
printf("protecting code page: 0x%08lx\n", |
843 |
host_start);
|
|
854 |
page_addr);
|
|
844 | 855 |
#endif |
845 |
p->flags &= ~PAGE_WRITE; |
|
846 | 856 |
} |
847 | 857 |
#else |
848 | 858 |
/* if some code is already present, then the pages are already |
... | ... | |
1546 | 1556 |
|
1547 | 1557 |
/* called from signal handler: invalidate the code and unprotect the |
1548 | 1558 |
page. Return TRUE if the fault was succesfully handled. */ |
1549 |
int page_unprotect(unsigned long addr, unsigned long pc, void *puc)
|
|
1559 |
int page_unprotect(target_ulong addr, unsigned long pc, void *puc)
|
|
1550 | 1560 |
{ |
1551 | 1561 |
#if !defined(CONFIG_SOFTMMU) |
1552 | 1562 |
VirtPageDesc *vp; |
... | ... | |
1645 | 1655 |
} |
1646 | 1656 |
} |
1647 | 1657 |
|
1648 |
int page_get_flags(unsigned long address)
|
|
1658 |
int page_get_flags(target_ulong address)
|
|
1649 | 1659 |
{ |
1650 | 1660 |
PageDesc *p; |
1651 | 1661 |
|
... | ... | |
1658 | 1668 |
/* modify the flags of a page and invalidate the code if |
1659 | 1669 |
necessary. The flag PAGE_WRITE_ORG is positionned automatically |
1660 | 1670 |
depending on PAGE_WRITE */ |
1661 |
void page_set_flags(unsigned long start, unsigned long end, int flags)
|
|
1671 |
void page_set_flags(target_ulong start, target_ulong end, int flags)
|
|
1662 | 1672 |
{ |
1663 | 1673 |
PageDesc *p; |
1664 |
unsigned long addr;
|
|
1674 |
target_ulong addr;
|
|
1665 | 1675 |
|
1666 | 1676 |
start = start & TARGET_PAGE_MASK; |
1667 | 1677 |
end = TARGET_PAGE_ALIGN(end); |
... | ... | |
1684 | 1694 |
|
1685 | 1695 |
/* called from signal handler: invalidate the code and unprotect the |
1686 | 1696 |
page. Return TRUE if the fault was succesfully handled. */ |
1687 |
int page_unprotect(unsigned long address, unsigned long pc, void *puc)
|
|
1697 |
int page_unprotect(target_ulong address, unsigned long pc, void *puc)
|
|
1688 | 1698 |
{ |
1689 | 1699 |
unsigned int page_index, prot, pindex; |
1690 | 1700 |
PageDesc *p, *p1; |
1691 |
unsigned long host_start, host_end, addr;
|
|
1701 |
target_ulong host_start, host_end, addr;
|
|
1692 | 1702 |
|
1693 | 1703 |
host_start = address & qemu_host_page_mask; |
1694 | 1704 |
page_index = host_start >> TARGET_PAGE_BITS; |
... | ... | |
1707 | 1717 |
if (prot & PAGE_WRITE_ORG) { |
1708 | 1718 |
pindex = (address - host_start) >> TARGET_PAGE_BITS; |
1709 | 1719 |
if (!(p1[pindex].flags & PAGE_WRITE)) { |
1710 |
mprotect((void *)host_start, qemu_host_page_size,
|
|
1720 |
mprotect((void *)g2h(host_start), qemu_host_page_size,
|
|
1711 | 1721 |
(prot & PAGE_BITS) | PAGE_WRITE); |
1712 | 1722 |
p1[pindex].flags |= PAGE_WRITE; |
1713 | 1723 |
/* and since the content will be modified, we must invalidate |
... | ... | |
1723 | 1733 |
} |
1724 | 1734 |
|
1725 | 1735 |
/* call this function when system calls directly modify a memory area */ |
1726 |
void page_unprotect_range(uint8_t *data, unsigned long data_size) |
|
1736 |
/* ??? This should be redundant now we have lock_user. */ |
|
1737 |
void page_unprotect_range(target_ulong data, target_ulong data_size) |
|
1727 | 1738 |
{ |
1728 |
unsigned long start, end, addr;
|
|
1739 |
target_ulong start, end, addr;
|
|
1729 | 1740 |
|
1730 |
start = (unsigned long)data;
|
|
1741 |
start = data; |
|
1731 | 1742 |
end = start + data_size; |
1732 | 1743 |
start &= TARGET_PAGE_MASK; |
1733 | 1744 |
end = TARGET_PAGE_ALIGN(end); |
... | ... | |
1932 | 1943 |
{ |
1933 | 1944 |
int l, flags; |
1934 | 1945 |
target_ulong page; |
1946 |
void * p; |
|
1935 | 1947 |
|
1936 | 1948 |
while (len > 0) { |
1937 | 1949 |
page = addr & TARGET_PAGE_MASK; |
... | ... | |
1944 | 1956 |
if (is_write) { |
1945 | 1957 |
if (!(flags & PAGE_WRITE)) |
1946 | 1958 |
return; |
1947 |
memcpy((uint8_t *)addr, buf, len); |
|
1959 |
p = lock_user(addr, len, 0); |
|
1960 |
memcpy(p, buf, len); |
|
1961 |
unlock_user(p, addr, len); |
|
1948 | 1962 |
} else { |
1949 | 1963 |
if (!(flags & PAGE_READ)) |
1950 | 1964 |
return; |
1951 |
memcpy(buf, (uint8_t *)addr, len); |
|
1965 |
p = lock_user(addr, len, 1); |
|
1966 |
memcpy(buf, p, len); |
|
1967 |
unlock_user(p, addr, 0); |
|
1952 | 1968 |
} |
1953 | 1969 |
len -= l; |
1954 | 1970 |
buf += l; |
Also available in: Unified diff