| 68 |
#define L2_SIZE (1 << L2_BITS) |
#define L2_SIZE (1 << L2_BITS) |
| 69 |
|
|
| 70 |
static void tb_invalidate_page(unsigned long address); |
static void tb_invalidate_page(unsigned long address); |
| 71 |
|
static void io_mem_init(void); |
| 72 |
|
|
| 73 |
unsigned long real_host_page_size; |
unsigned long real_host_page_size; |
| 74 |
unsigned long host_page_bits; |
unsigned long host_page_bits; |
| 77 |
|
|
| 78 |
static PageDesc *l1_map[L1_SIZE]; |
static PageDesc *l1_map[L1_SIZE]; |
| 79 |
|
|
| 80 |
|
/* io memory support */ |
| 81 |
|
static unsigned long *l1_physmap[L1_SIZE]; |
| 82 |
|
CPUWriteMemoryFunc *io_mem_write[IO_MEM_NB_ENTRIES][4]; |
| 83 |
|
CPUReadMemoryFunc *io_mem_read[IO_MEM_NB_ENTRIES][4]; |
| 84 |
|
static int io_mem_nb; |
| 85 |
|
|
| 86 |
static void page_init(void) |
static void page_init(void) |
| 87 |
{ |
{ |
| 88 |
/* NOTE: we can always suppose that host_page_size >= |
/* NOTE: we can always suppose that host_page_size >= |
| 208 |
if (!code_gen_ptr) { |
if (!code_gen_ptr) { |
| 209 |
code_gen_ptr = code_gen_buffer; |
code_gen_ptr = code_gen_buffer; |
| 210 |
page_init(); |
page_init(); |
| 211 |
|
io_mem_init(); |
| 212 |
} |
} |
| 213 |
} |
} |
| 214 |
|
|
| 752 |
tb_flush(); |
tb_flush(); |
| 753 |
} |
} |
| 754 |
#endif |
#endif |
| 755 |
|
|
| 756 |
|
void tlb_flush(CPUState *env) |
| 757 |
|
{ |
| 758 |
|
#if defined(TARGET_I386) |
| 759 |
|
int i; |
| 760 |
|
for(i = 0; i < CPU_TLB_SIZE; i++) { |
| 761 |
|
env->tlb_read[0][i].address = -1; |
| 762 |
|
env->tlb_write[0][i].address = -1; |
| 763 |
|
env->tlb_read[1][i].address = -1; |
| 764 |
|
env->tlb_write[1][i].address = -1; |
| 765 |
|
} |
| 766 |
|
#endif |
| 767 |
|
} |
| 768 |
|
|
| 769 |
|
void tlb_flush_page(CPUState *env, uint32_t addr) |
| 770 |
|
{ |
| 771 |
|
#if defined(TARGET_I386) |
| 772 |
|
int i; |
| 773 |
|
|
| 774 |
|
i = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1); |
| 775 |
|
env->tlb_read[0][i].address = -1; |
| 776 |
|
env->tlb_write[0][i].address = -1; |
| 777 |
|
env->tlb_read[1][i].address = -1; |
| 778 |
|
env->tlb_write[1][i].address = -1; |
| 779 |
|
#endif |
| 780 |
|
} |
| 781 |
|
|
| 782 |
|
static inline unsigned long *physpage_find_alloc(unsigned int page) |
| 783 |
|
{ |
| 784 |
|
unsigned long **lp, *p; |
| 785 |
|
unsigned int index, i; |
| 786 |
|
|
| 787 |
|
index = page >> TARGET_PAGE_BITS; |
| 788 |
|
lp = &l1_physmap[index >> L2_BITS]; |
| 789 |
|
p = *lp; |
| 790 |
|
if (!p) { |
| 791 |
|
/* allocate if not found */ |
| 792 |
|
p = malloc(sizeof(unsigned long) * L2_SIZE); |
| 793 |
|
for(i = 0; i < L2_SIZE; i++) |
| 794 |
|
p[i] = IO_MEM_UNASSIGNED; |
| 795 |
|
*lp = p; |
| 796 |
|
} |
| 797 |
|
return p + (index & (L2_SIZE - 1)); |
| 798 |
|
} |
| 799 |
|
|
| 800 |
|
/* return NULL if no page defined (unused memory) */ |
| 801 |
|
unsigned long physpage_find(unsigned long page) |
| 802 |
|
{ |
| 803 |
|
unsigned long *p; |
| 804 |
|
unsigned int index; |
| 805 |
|
index = page >> TARGET_PAGE_BITS; |
| 806 |
|
p = l1_physmap[index >> L2_BITS]; |
| 807 |
|
if (!p) |
| 808 |
|
return IO_MEM_UNASSIGNED; |
| 809 |
|
return p[index & (L2_SIZE - 1)]; |
| 810 |
|
} |
| 811 |
|
|
| 812 |
|
/* register physical memory. 'size' must be a multiple of the target |
| 813 |
|
page size. If (phys_offset & ~TARGET_PAGE_MASK) != 0, then it is an |
| 814 |
|
io memory page */ |
| 815 |
|
void cpu_register_physical_memory(unsigned long start_addr, unsigned long size, |
| 816 |
|
long phys_offset) |
| 817 |
|
{ |
| 818 |
|
unsigned long addr, end_addr; |
| 819 |
|
unsigned long *p; |
| 820 |
|
|
| 821 |
|
end_addr = start_addr + size; |
| 822 |
|
for(addr = start_addr; addr < end_addr; addr += TARGET_PAGE_SIZE) { |
| 823 |
|
p = physpage_find_alloc(addr); |
| 824 |
|
*p = phys_offset; |
| 825 |
|
if ((phys_offset & ~TARGET_PAGE_MASK) == 0) |
| 826 |
|
phys_offset += TARGET_PAGE_SIZE; |
| 827 |
|
} |
| 828 |
|
} |
| 829 |
|
|
| 830 |
|
static uint32_t unassigned_mem_readb(uint32_t addr) |
| 831 |
|
{ |
| 832 |
|
return 0; |
| 833 |
|
} |
| 834 |
|
|
| 835 |
|
static void unassigned_mem_writeb(uint32_t addr, uint32_t val) |
| 836 |
|
{ |
| 837 |
|
} |
| 838 |
|
|
| 839 |
|
static CPUReadMemoryFunc *unassigned_mem_read[3] = { |
| 840 |
|
unassigned_mem_readb, |
| 841 |
|
unassigned_mem_readb, |
| 842 |
|
unassigned_mem_readb, |
| 843 |
|
}; |
| 844 |
|
|
| 845 |
|
static CPUWriteMemoryFunc *unassigned_mem_write[3] = { |
| 846 |
|
unassigned_mem_writeb, |
| 847 |
|
unassigned_mem_writeb, |
| 848 |
|
unassigned_mem_writeb, |
| 849 |
|
}; |
| 850 |
|
|
| 851 |
|
|
| 852 |
|
static void io_mem_init(void) |
| 853 |
|
{ |
| 854 |
|
io_mem_nb = 1; |
| 855 |
|
cpu_register_io_memory(0, unassigned_mem_read, unassigned_mem_write); |
| 856 |
|
} |
| 857 |
|
|
| 858 |
|
/* mem_read and mem_write are arrays of functions containing the |
| 859 |
|
function to access byte (index 0), word (index 1) and dword (index |
| 860 |
|
2). All functions must be supplied. If io_index is non zero, the |
| 861 |
|
corresponding io zone is modified. If it is zero, a new io zone is |
| 862 |
|
allocated. The return value can be used with |
| 863 |
|
cpu_register_physical_memory(). (-1) is returned if error. */ |
| 864 |
|
int cpu_register_io_memory(int io_index, |
| 865 |
|
CPUReadMemoryFunc **mem_read, |
| 866 |
|
CPUWriteMemoryFunc **mem_write) |
| 867 |
|
{ |
| 868 |
|
int i; |
| 869 |
|
|
| 870 |
|
if (io_index <= 0) { |
| 871 |
|
if (io_index >= IO_MEM_NB_ENTRIES) |
| 872 |
|
return -1; |
| 873 |
|
io_index = io_mem_nb++; |
| 874 |
|
} else { |
| 875 |
|
if (io_index >= IO_MEM_NB_ENTRIES) |
| 876 |
|
return -1; |
| 877 |
|
} |
| 878 |
|
|
| 879 |
|
for(i = 0;i < 3; i++) { |
| 880 |
|
io_mem_read[io_index][i] = mem_read[i]; |
| 881 |
|
io_mem_write[io_index][i] = mem_write[i]; |
| 882 |
|
} |
| 883 |
|
return io_index << IO_MEM_SHIFT; |
| 884 |
|
} |