mirror of https://github.com/xemu-project/xemu.git
64 bit virtual addressing fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1525 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
parent
9529397248
commit
90f18422d9
114
exec.c
114
exec.c
|
@ -83,6 +83,8 @@ typedef struct PhysPageDesc {
|
||||||
uint32_t phys_offset;
|
uint32_t phys_offset;
|
||||||
} PhysPageDesc;
|
} PhysPageDesc;
|
||||||
|
|
||||||
|
/* Note: the VirtPage handling is absolete and will be suppressed
|
||||||
|
ASAP */
|
||||||
typedef struct VirtPageDesc {
|
typedef struct VirtPageDesc {
|
||||||
/* physical address of code page. It is valid only if 'valid_tag'
|
/* physical address of code page. It is valid only if 'valid_tag'
|
||||||
matches 'virt_valid_tag' */
|
matches 'virt_valid_tag' */
|
||||||
|
@ -113,7 +115,13 @@ static PageDesc *l1_map[L1_SIZE];
|
||||||
PhysPageDesc **l1_phys_map;
|
PhysPageDesc **l1_phys_map;
|
||||||
|
|
||||||
#if !defined(CONFIG_USER_ONLY)
|
#if !defined(CONFIG_USER_ONLY)
|
||||||
|
#if TARGET_LONG_BITS > 32
|
||||||
|
#define VIRT_L_BITS 9
|
||||||
|
#define VIRT_L_SIZE (1 << VIRT_L_BITS)
|
||||||
|
static void *l1_virt_map[VIRT_L_SIZE];
|
||||||
|
#else
|
||||||
static VirtPageDesc *l1_virt_map[L1_SIZE];
|
static VirtPageDesc *l1_virt_map[L1_SIZE];
|
||||||
|
#endif
|
||||||
static unsigned int virt_valid_tag;
|
static unsigned int virt_valid_tag;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -234,44 +242,104 @@ static inline PhysPageDesc *phys_page_find(unsigned int index)
|
||||||
static void tlb_protect_code(CPUState *env, target_ulong addr);
|
static void tlb_protect_code(CPUState *env, target_ulong addr);
|
||||||
static void tlb_unprotect_code_phys(CPUState *env, unsigned long phys_addr, target_ulong vaddr);
|
static void tlb_unprotect_code_phys(CPUState *env, unsigned long phys_addr, target_ulong vaddr);
|
||||||
|
|
||||||
static inline VirtPageDesc *virt_page_find_alloc(unsigned int index)
|
static VirtPageDesc *virt_page_find_alloc(target_ulong index, int alloc)
|
||||||
{
|
{
|
||||||
VirtPageDesc **lp, *p;
|
|
||||||
|
|
||||||
/* XXX: should not truncate for 64 bit addresses */
|
|
||||||
#if TARGET_LONG_BITS > 32
|
#if TARGET_LONG_BITS > 32
|
||||||
index &= (L1_SIZE - 1);
|
void **p, **lp;
|
||||||
#endif
|
|
||||||
|
p = l1_virt_map;
|
||||||
|
lp = p + ((index >> (5 * VIRT_L_BITS)) & (VIRT_L_SIZE - 1));
|
||||||
|
p = *lp;
|
||||||
|
if (!p) {
|
||||||
|
if (!alloc)
|
||||||
|
return NULL;
|
||||||
|
p = qemu_mallocz(sizeof(void *) * VIRT_L_SIZE);
|
||||||
|
*lp = p;
|
||||||
|
}
|
||||||
|
lp = p + ((index >> (4 * VIRT_L_BITS)) & (VIRT_L_SIZE - 1));
|
||||||
|
p = *lp;
|
||||||
|
if (!p) {
|
||||||
|
if (!alloc)
|
||||||
|
return NULL;
|
||||||
|
p = qemu_mallocz(sizeof(void *) * VIRT_L_SIZE);
|
||||||
|
*lp = p;
|
||||||
|
}
|
||||||
|
lp = p + ((index >> (3 * VIRT_L_BITS)) & (VIRT_L_SIZE - 1));
|
||||||
|
p = *lp;
|
||||||
|
if (!p) {
|
||||||
|
if (!alloc)
|
||||||
|
return NULL;
|
||||||
|
p = qemu_mallocz(sizeof(void *) * VIRT_L_SIZE);
|
||||||
|
*lp = p;
|
||||||
|
}
|
||||||
|
lp = p + ((index >> (2 * VIRT_L_BITS)) & (VIRT_L_SIZE - 1));
|
||||||
|
p = *lp;
|
||||||
|
if (!p) {
|
||||||
|
if (!alloc)
|
||||||
|
return NULL;
|
||||||
|
p = qemu_mallocz(sizeof(void *) * VIRT_L_SIZE);
|
||||||
|
*lp = p;
|
||||||
|
}
|
||||||
|
lp = p + ((index >> (1 * VIRT_L_BITS)) & (VIRT_L_SIZE - 1));
|
||||||
|
p = *lp;
|
||||||
|
if (!p) {
|
||||||
|
if (!alloc)
|
||||||
|
return NULL;
|
||||||
|
p = qemu_mallocz(sizeof(VirtPageDesc) * VIRT_L_SIZE);
|
||||||
|
*lp = p;
|
||||||
|
}
|
||||||
|
return ((VirtPageDesc *)p) + (index & (VIRT_L_SIZE - 1));
|
||||||
|
#else
|
||||||
|
VirtPageDesc *p, **lp;
|
||||||
|
|
||||||
lp = &l1_virt_map[index >> L2_BITS];
|
lp = &l1_virt_map[index >> L2_BITS];
|
||||||
p = *lp;
|
p = *lp;
|
||||||
if (!p) {
|
if (!p) {
|
||||||
/* allocate if not found */
|
/* allocate if not found */
|
||||||
p = qemu_malloc(sizeof(VirtPageDesc) * L2_SIZE);
|
if (!alloc)
|
||||||
memset(p, 0, sizeof(VirtPageDesc) * L2_SIZE);
|
return NULL;
|
||||||
|
p = qemu_mallocz(sizeof(VirtPageDesc) * L2_SIZE);
|
||||||
*lp = p;
|
*lp = p;
|
||||||
}
|
}
|
||||||
return p + (index & (L2_SIZE - 1));
|
return p + (index & (L2_SIZE - 1));
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline VirtPageDesc *virt_page_find(unsigned int index)
|
static inline VirtPageDesc *virt_page_find(target_ulong index)
|
||||||
{
|
{
|
||||||
VirtPageDesc *p;
|
return virt_page_find_alloc(index, 0);
|
||||||
|
|
||||||
p = l1_virt_map[index >> L2_BITS];
|
|
||||||
if (!p)
|
|
||||||
return 0;
|
|
||||||
return p + (index & (L2_SIZE - 1));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if TARGET_LONG_BITS > 32
|
||||||
|
static void virt_page_flush_internal(void **p, int level)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
if (level == 0) {
|
||||||
|
VirtPageDesc *q = (VirtPageDesc *)p;
|
||||||
|
for(i = 0; i < VIRT_L_SIZE; i++)
|
||||||
|
q[i].valid_tag = 0;
|
||||||
|
} else {
|
||||||
|
level--;
|
||||||
|
for(i = 0; i < VIRT_L_SIZE; i++) {
|
||||||
|
if (p[i])
|
||||||
|
virt_page_flush_internal(p[i], level);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static void virt_page_flush(void)
|
static void virt_page_flush(void)
|
||||||
{
|
{
|
||||||
int i, j;
|
|
||||||
VirtPageDesc *p;
|
|
||||||
|
|
||||||
virt_valid_tag++;
|
virt_valid_tag++;
|
||||||
|
|
||||||
if (virt_valid_tag == 0) {
|
if (virt_valid_tag == 0) {
|
||||||
virt_valid_tag = 1;
|
virt_valid_tag = 1;
|
||||||
|
#if TARGET_LONG_BITS > 32
|
||||||
|
virt_page_flush_internal(l1_virt_map, 5);
|
||||||
|
#else
|
||||||
|
{
|
||||||
|
int i, j;
|
||||||
|
VirtPageDesc *p;
|
||||||
for(i = 0; i < L1_SIZE; i++) {
|
for(i = 0; i < L1_SIZE; i++) {
|
||||||
p = l1_virt_map[i];
|
p = l1_virt_map[i];
|
||||||
if (p) {
|
if (p) {
|
||||||
|
@ -280,6 +348,8 @@ static void virt_page_flush(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
static void virt_page_flush(void)
|
static void virt_page_flush(void)
|
||||||
|
@ -945,7 +1015,7 @@ void tb_link(TranslationBlock *tb)
|
||||||
|
|
||||||
/* save the code memory mappings (needed to invalidate the code) */
|
/* save the code memory mappings (needed to invalidate the code) */
|
||||||
addr = tb->pc & TARGET_PAGE_MASK;
|
addr = tb->pc & TARGET_PAGE_MASK;
|
||||||
vp = virt_page_find_alloc(addr >> TARGET_PAGE_BITS);
|
vp = virt_page_find_alloc(addr >> TARGET_PAGE_BITS, 1);
|
||||||
#ifdef DEBUG_TLB_CHECK
|
#ifdef DEBUG_TLB_CHECK
|
||||||
if (vp->valid_tag == virt_valid_tag &&
|
if (vp->valid_tag == virt_valid_tag &&
|
||||||
vp->phys_addr != tb->page_addr[0]) {
|
vp->phys_addr != tb->page_addr[0]) {
|
||||||
|
@ -963,7 +1033,7 @@ void tb_link(TranslationBlock *tb)
|
||||||
|
|
||||||
if (tb->page_addr[1] != -1) {
|
if (tb->page_addr[1] != -1) {
|
||||||
addr += TARGET_PAGE_SIZE;
|
addr += TARGET_PAGE_SIZE;
|
||||||
vp = virt_page_find_alloc(addr >> TARGET_PAGE_BITS);
|
vp = virt_page_find_alloc(addr >> TARGET_PAGE_BITS, 1);
|
||||||
#ifdef DEBUG_TLB_CHECK
|
#ifdef DEBUG_TLB_CHECK
|
||||||
if (vp->valid_tag == virt_valid_tag &&
|
if (vp->valid_tag == virt_valid_tag &&
|
||||||
vp->phys_addr != tb->page_addr[1]) {
|
vp->phys_addr != tb->page_addr[1]) {
|
||||||
|
@ -1572,7 +1642,7 @@ int tlb_set_page(CPUState *env, target_ulong vaddr,
|
||||||
addend = (unsigned long)phys_ram_base + (pd & TARGET_PAGE_MASK);
|
addend = (unsigned long)phys_ram_base + (pd & TARGET_PAGE_MASK);
|
||||||
}
|
}
|
||||||
|
|
||||||
index = (vaddr >> 12) & (CPU_TLB_SIZE - 1);
|
index = (vaddr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
|
||||||
addend -= vaddr;
|
addend -= vaddr;
|
||||||
if (prot & PAGE_READ) {
|
if (prot & PAGE_READ) {
|
||||||
env->tlb_read[is_user][index].address = address;
|
env->tlb_read[is_user][index].address = address;
|
||||||
|
@ -1635,7 +1705,7 @@ int tlb_set_page(CPUState *env, target_ulong vaddr,
|
||||||
original mapping */
|
original mapping */
|
||||||
VirtPageDesc *vp;
|
VirtPageDesc *vp;
|
||||||
|
|
||||||
vp = virt_page_find_alloc(vaddr >> TARGET_PAGE_BITS);
|
vp = virt_page_find_alloc(vaddr >> TARGET_PAGE_BITS, 1);
|
||||||
vp->phys_addr = pd;
|
vp->phys_addr = pd;
|
||||||
vp->prot = prot;
|
vp->prot = prot;
|
||||||
vp->valid_tag = virt_valid_tag;
|
vp->valid_tag = virt_valid_tag;
|
||||||
|
|
Loading…
Reference in New Issue