//#define DEBUG_TB_CHECK
//#define DEBUG_TLB_CHECK
+#if !defined(CONFIG_USER_ONLY)
+/* TB consistency checks only implemented for usermode emulation. */
+#undef DEBUG_TB_CHECK
+#endif
+
/* threshold to flush the translated code buffer */
#define CODE_GEN_BUFFER_MAX_SIZE (CODE_GEN_BUFFER_SIZE - CODE_GEN_MAX_SIZE)
static PhysPageDesc *phys_page_find_alloc(target_phys_addr_t index, int alloc)
{
void **lp, **p;
+ PhysPageDesc *pd;
p = (void **)l1_phys_map;
#if TARGET_PHYS_ADDR_SPACE_BITS > 32
}
#endif
lp = p + ((index >> L2_BITS) & (L1_SIZE - 1));
- p = *lp;
- if (!p) {
+ pd = *lp;
+ if (!pd) {
+ int i;
/* allocate if not found */
if (!alloc)
return NULL;
- p = qemu_vmalloc(sizeof(PhysPageDesc) * L2_SIZE);
- memset(p, 0, sizeof(PhysPageDesc) * L2_SIZE);
- *lp = p;
+ pd = qemu_vmalloc(sizeof(PhysPageDesc) * L2_SIZE);
+ *lp = pd;
+ for (i = 0; i < L2_SIZE; i++)
+ pd[i].phys_offset = IO_MEM_UNASSIGNED;
}
- return ((PhysPageDesc *)p) + (index & (L2_SIZE - 1));
+ return ((PhysPageDesc *)pd) + (index & (L2_SIZE - 1));
}
static inline PhysPageDesc *phys_page_find(target_phys_addr_t index)
TranslationBlock *tb;
int i;
address &= TARGET_PAGE_MASK;
- for(i = 0;i < CODE_GEN_HASH_SIZE; i++) {
- for(tb = tb_hash[i]; tb != NULL; tb = tb->hash_next) {
+ for(i = 0;i < CODE_GEN_PHYS_HASH_SIZE; i++) {
+ for(tb = tb_phys_hash[i]; tb != NULL; tb = tb->phys_hash_next) {
if (!(address + TARGET_PAGE_SIZE <= tb->pc ||
address >= tb->pc + tb->size)) {
printf("ERROR invalidate: address=%08lx PC=%08lx size=%04x\n",
- address, tb->pc, tb->size);
+ address, (long)tb->pc, tb->size);
}
}
}
TranslationBlock *tb;
int i, flags1, flags2;
- for(i = 0;i < CODE_GEN_HASH_SIZE; i++) {
- for(tb = tb_hash[i]; tb != NULL; tb = tb->hash_next) {
+ for(i = 0;i < CODE_GEN_PHYS_HASH_SIZE; i++) {
+ for(tb = tb_phys_hash[i]; tb != NULL; tb = tb->phys_hash_next) {
flags1 = page_get_flags(tb->pc);
flags2 = page_get_flags(tb->pc + tb->size - 1);
if ((flags1 & PAGE_WRITE) || (flags2 & PAGE_WRITE)) {
printf("ERROR page flags: PC=%08lx size=%04x f1=%x f2=%x\n",
- tb->pc, tb->size, flags1, flags2);
+ (long)tb->pc, tb->size, flags1, flags2);
}
}
}
pd = p->phys_offset;
}
ram_addr = (pd & TARGET_PAGE_MASK) | (pc & ~TARGET_PAGE_MASK);
- tb_invalidate_ram_page_range(ram_addr, ram_addr + 1, 0);
+ tb_invalidate_phys_page_range(ram_addr, ram_addr + 1, 0);
}
#endif
tlb_flush_entry(&env->tlb_table[0][i], addr);
tlb_flush_entry(&env->tlb_table[1][i], addr);
- for(i = 0; i < TB_JMP_CACHE_SIZE; i++) {
- tb = env->tb_jmp_cache[i];
- if (tb &&
- ((tb->pc & TARGET_PAGE_MASK) == addr ||
- ((tb->pc + tb->size - 1) & TARGET_PAGE_MASK) == addr)) {
- env->tb_jmp_cache[i] = NULL;
- }
- }
+ /* Discard jump cache entries for any tb which might potentially
+ overlap the flushed page. */
+ i = tb_jmp_cache_hash_page(addr - TARGET_PAGE_SIZE);
+ memset (&env->tb_jmp_cache[i], 0, TB_JMP_PAGE_SIZE * sizeof(tb));
+
+ i = tb_jmp_cache_hash_page(addr);
+ memset (&env->tb_jmp_cache[i], 0, TB_JMP_PAGE_SIZE * sizeof(tb));
#if !defined(CONFIG_SOFTMMU)
if (addr < MMAP_AREA_END)
if (is_softmmu)
#endif
{
- if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM) {
+ if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM && !(pd & IO_MEM_ROMD)) {
/* IO memory case */
address = vaddr | pd;
addend = paddr;
te->addr_code = -1;
}
if (prot & PAGE_WRITE) {
- if ((pd & ~TARGET_PAGE_MASK) == IO_MEM_ROM) {
- /* ROM: access is ignored (same as unassigned) */
- te->addr_write = vaddr | IO_MEM_ROM;
+ if ((pd & ~TARGET_PAGE_MASK) == IO_MEM_ROM ||
+ (pd & IO_MEM_ROMD)) {
+ /* write access calls the I/O callback */
+ te->addr_write = vaddr |
+ (pd & ~(TARGET_PAGE_MASK | IO_MEM_ROMD));
} else if ((pd & ~TARGET_PAGE_MASK) == IO_MEM_RAM &&
!cpu_physical_memory_is_dirty(pd)) {
te->addr_write = vaddr | IO_MEM_NOTDIRTY;
{
target_phys_addr_t addr, end_addr;
PhysPageDesc *p;
+ CPUState *env;
size = (size + TARGET_PAGE_SIZE - 1) & TARGET_PAGE_MASK;
end_addr = start_addr + size;
for(addr = start_addr; addr != end_addr; addr += TARGET_PAGE_SIZE) {
p = phys_page_find_alloc(addr >> TARGET_PAGE_BITS, 1);
p->phys_offset = phys_offset;
- if ((phys_offset & ~TARGET_PAGE_MASK) <= IO_MEM_ROM)
+ if ((phys_offset & ~TARGET_PAGE_MASK) <= IO_MEM_ROM ||
+ (phys_offset & IO_MEM_ROMD))
phys_offset += TARGET_PAGE_SIZE;
}
+
+ /* since each CPU stores ram addresses in its TLB cache, we must
+ reset the modified entries */
+ /* XXX: slow ! */
+ for(env = first_cpu; env != NULL; env = env->next_cpu) {
+ tlb_flush(env, 1);
+ }
+}
+
+/* XXX: temporary until new memory mapping API */
+uint32_t cpu_get_physical_page_desc(target_phys_addr_t addr)
+{
+ PhysPageDesc *p;
+
+ p = phys_page_find(addr >> TARGET_PAGE_BITS);
+ if (!p)
+ return IO_MEM_UNASSIGNED;
+ return p->phys_offset;
}
static uint32_t unassigned_mem_readb(void *opaque, target_phys_addr_t addr)
}
}
} else {
- if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM) {
+ if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM &&
+ !(pd & IO_MEM_ROMD)) {
/* I/O case */
io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
if (l >= 4 && ((addr & 3) == 0)) {
}
}
+/* used for ROM loading : can write in RAM and ROM */
+void cpu_physical_memory_write_rom(target_phys_addr_t addr,
+ const uint8_t *buf, int len)
+{
+ int l;
+ uint8_t *ptr;
+ target_phys_addr_t page;
+ unsigned long pd;
+ PhysPageDesc *p;
+
+ while (len > 0) {
+ page = addr & TARGET_PAGE_MASK;
+ l = (page + TARGET_PAGE_SIZE) - addr;
+ if (l > len)
+ l = len;
+ p = phys_page_find(page >> TARGET_PAGE_BITS);
+ if (!p) {
+ pd = IO_MEM_UNASSIGNED;
+ } else {
+ pd = p->phys_offset;
+ }
+
+ if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM &&
+ (pd & ~TARGET_PAGE_MASK) != IO_MEM_ROM &&
+ !(pd & IO_MEM_ROMD)) {
+ /* do nothing */
+ } else {
+ unsigned long addr1;
+ addr1 = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK);
+ /* ROM/RAM case */
+ ptr = phys_ram_base + addr1;
+ memcpy(ptr, buf, l);
+ }
+ len -= l;
+ buf += l;
+ addr += l;
+ }
+}
+
+
/* warning: addr must be aligned */
uint32_t ldl_phys(target_phys_addr_t addr)
{
pd = p->phys_offset;
}
- if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM) {
+ if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM &&
+ !(pd & IO_MEM_ROMD)) {
/* I/O case */
io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
val = io_mem_read[io_index][2](io_mem_opaque[io_index], addr);
pd = p->phys_offset;
}
- if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM) {
+ if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM &&
+ !(pd & IO_MEM_ROMD)) {
/* I/O case */
io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
#ifdef TARGET_WORDS_BIGENDIAN