aboutsummaryrefslogtreecommitdiff
path: root/exec.c
diff options
context:
space:
mode:
authorbellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162>2003-10-27 21:22:23 +0000
committerbellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162>2003-10-27 21:22:23 +0000
commit61382a500a9e54ef96ca28e0f221151f569cbb6e (patch)
tree453252700fc701b0e1be1d4832a8c2969a2b3ec2 /exec.c
parent3a51dee658b9cc781acd57dd11bffbd1e402f93d (diff)
full softmmu support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@410 c046a42c-6fe2-441c-8c8c-71466251a162
Diffstat (limited to 'exec.c')
-rw-r--r--exec.c103
1 files changed, 81 insertions, 22 deletions
diff --git a/exec.c b/exec.c
index f4f6a9bc41..ca767e2af0 100644
--- a/exec.c
+++ b/exec.c
@@ -444,16 +444,20 @@ static inline void tb_alloc_page(TranslationBlock *tb, unsigned int page_index)
prot = 0;
for(addr = host_start; addr < host_end; addr += TARGET_PAGE_SIZE)
prot |= page_get_flags(addr);
+#if !defined(CONFIG_SOFTMMU)
mprotect((void *)host_start, host_page_size,
(prot & PAGE_BITS) & ~PAGE_WRITE);
+#endif
+#if !defined(CONFIG_USER_ONLY)
+ /* suppress soft TLB */
+ /* XXX: must flush on all processor with same address space */
+ tlb_flush_page_write(cpu_single_env, host_start);
+#endif
#ifdef DEBUG_TB_INVALIDATE
printf("protecting code page: 0x%08lx\n",
host_start);
#endif
p->flags &= ~PAGE_WRITE;
-#ifdef DEBUG_TB_CHECK
- tb_page_check();
-#endif
}
}
@@ -483,6 +487,9 @@ void tb_link(TranslationBlock *tb)
if (page_index2 != page_index1) {
tb_alloc_page(tb, page_index2);
}
+#ifdef DEBUG_TB_CHECK
+ tb_page_check();
+#endif
tb->jmp_first = (TranslationBlock *)((long)tb | 2);
tb->jmp_next[0] = NULL;
tb->jmp_next[1] = NULL;
@@ -517,20 +524,23 @@ int page_unprotect(unsigned long address)
/* if the page was really writable, then we change its
protection back to writable */
if (prot & PAGE_WRITE_ORG) {
- mprotect((void *)host_start, host_page_size,
- (prot & PAGE_BITS) | PAGE_WRITE);
pindex = (address - host_start) >> TARGET_PAGE_BITS;
- p1[pindex].flags |= PAGE_WRITE;
- /* and since the content will be modified, we must invalidate
- the corresponding translated code. */
- tb_invalidate_page(address);
+ if (!(p1[pindex].flags & PAGE_WRITE)) {
+#if !defined(CONFIG_SOFTMMU)
+ mprotect((void *)host_start, host_page_size,
+ (prot & PAGE_BITS) | PAGE_WRITE);
+#endif
+ p1[pindex].flags |= PAGE_WRITE;
+ /* and since the content will be modified, we must invalidate
+ the corresponding translated code. */
+ tb_invalidate_page(address);
#ifdef DEBUG_TB_CHECK
- tb_invalidate_check(address);
+ tb_invalidate_check(address);
#endif
- return 1;
- } else {
- return 0;
+ return 1;
+ }
}
+ return 0;
}
/* call this function when system calls directly modify a memory area */
@@ -734,13 +744,17 @@ void cpu_abort(CPUState *env, const char *fmt, ...)
/* unmap all maped pages and flush all associated code */
void page_unmap(void)
{
- PageDesc *p, *pmap;
- unsigned long addr;
- int i, j, ret, j1;
+ PageDesc *pmap;
+ int i;
for(i = 0; i < L1_SIZE; i++) {
pmap = l1_map[i];
if (pmap) {
+#if !defined(CONFIG_SOFTMMU)
+ PageDesc *p;
+ unsigned long addr;
+ int j, ret, j1;
+
p = pmap;
for(j = 0;j < L2_SIZE;) {
if (p->flags & PAGE_VALID) {
@@ -763,6 +777,7 @@ void page_unmap(void)
j++;
}
}
+#endif
free(pmap);
l1_map[i] = NULL;
}
@@ -773,7 +788,7 @@ void page_unmap(void)
void tlb_flush(CPUState *env)
{
-#if defined(TARGET_I386)
+#if !defined(CONFIG_USER_ONLY)
int i;
for(i = 0; i < CPU_TLB_SIZE; i++) {
env->tlb_read[0][i].address = -1;
@@ -784,16 +799,38 @@ void tlb_flush(CPUState *env)
#endif
}
+static inline void tlb_flush_entry(CPUTLBEntry *tlb_entry, uint32_t addr)
+{
+ if (addr == (tlb_entry->address &
+ (TARGET_PAGE_MASK | TLB_INVALID_MASK)))
+ tlb_entry->address = -1;
+}
+
void tlb_flush_page(CPUState *env, uint32_t addr)
{
-#if defined(TARGET_I386)
+#if !defined(CONFIG_USER_ONLY)
+ int i;
+
+ addr &= TARGET_PAGE_MASK;
+ i = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
+ tlb_flush_entry(&env->tlb_read[0][i], addr);
+ tlb_flush_entry(&env->tlb_write[0][i], addr);
+ tlb_flush_entry(&env->tlb_read[1][i], addr);
+ tlb_flush_entry(&env->tlb_write[1][i], addr);
+#endif
+}
+
+/* make all write to page 'addr' trigger a TLB exception to detect
+ self modifying code */
+void tlb_flush_page_write(CPUState *env, uint32_t addr)
+{
+#if !defined(CONFIG_USER_ONLY)
int i;
+ addr &= TARGET_PAGE_MASK;
i = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
- env->tlb_read[0][i].address = -1;
- env->tlb_write[0][i].address = -1;
- env->tlb_read[1][i].address = -1;
- env->tlb_write[1][i].address = -1;
+ tlb_flush_entry(&env->tlb_write[0][i], addr);
+ tlb_flush_entry(&env->tlb_write[1][i], addr);
#endif
}
@@ -900,3 +937,25 @@ int cpu_register_io_memory(int io_index,
}
return io_index << IO_MEM_SHIFT;
}
+
+#if !defined(CONFIG_USER_ONLY)
+
+#define MMUSUFFIX _cmmu
+#define GETPC() NULL
+#define env cpu_single_env
+
+#define SHIFT 0
+#include "softmmu_template.h"
+
+#define SHIFT 1
+#include "softmmu_template.h"
+
+#define SHIFT 2
+#include "softmmu_template.h"
+
+#define SHIFT 3
+#include "softmmu_template.h"
+
+#undef env
+
+#endif