Revision d4c430a8
b/cpu-defs.h | ||
---|---|---|
111 | 111 |
/* The meaning of the MMU modes is defined in the target code. */ \ |
112 | 112 |
CPUTLBEntry tlb_table[NB_MMU_MODES][CPU_TLB_SIZE]; \ |
113 | 113 |
target_phys_addr_t iotlb[NB_MMU_MODES][CPU_TLB_SIZE]; \ |
114 |
target_ulong tlb_flush_addr; \ |
|
115 |
target_ulong tlb_flush_mask; |
|
114 | 116 |
|
115 | 117 |
#else |
116 | 118 |
|
b/exec-all.h | ||
---|---|---|
96 | 96 |
void tlb_flush_page(CPUState *env, target_ulong addr); |
97 | 97 |
void tlb_flush(CPUState *env, int flush_global); |
98 | 98 |
#if !defined(CONFIG_USER_ONLY) |
99 |
int tlb_set_page_exec(CPUState *env, target_ulong vaddr, |
|
100 |
target_phys_addr_t paddr, int prot, |
|
101 |
int mmu_idx, int is_softmmu); |
|
102 |
static inline int tlb_set_page(CPUState *env1, target_ulong vaddr, |
|
103 |
target_phys_addr_t paddr, int prot, |
|
104 |
int mmu_idx, int is_softmmu) |
|
105 |
{ |
|
106 |
if (prot & PAGE_READ) |
|
107 |
prot |= PAGE_EXEC; |
|
108 |
return tlb_set_page_exec(env1, vaddr, paddr, prot, mmu_idx, is_softmmu); |
|
109 |
} |
|
99 |
void tlb_set_page(CPUState *env, target_ulong vaddr, |
|
100 |
target_phys_addr_t paddr, int prot, |
|
101 |
int mmu_idx, target_ulong size); |
|
110 | 102 |
#endif |
111 | 103 |
|
112 | 104 |
#define CODE_GEN_ALIGN 16 /* must be >= of the size of a icache line */ |
b/exec.c | ||
---|---|---|
1918 | 1918 |
|
1919 | 1919 |
memset (env->tb_jmp_cache, 0, TB_JMP_CACHE_SIZE * sizeof (void *)); |
1920 | 1920 |
|
1921 |
env->tlb_flush_addr = -1; |
|
1922 |
env->tlb_flush_mask = 0; |
|
1921 | 1923 |
tlb_flush_count++; |
1922 | 1924 |
} |
1923 | 1925 |
|
... | ... | |
1941 | 1943 |
#if defined(DEBUG_TLB) |
1942 | 1944 |
printf("tlb_flush_page: " TARGET_FMT_lx "\n", addr); |
1943 | 1945 |
#endif |
1946 |
/* Check if we need to flush due to large pages. */ |
|
1947 |
if ((addr & env->tlb_flush_mask) == env->tlb_flush_addr) { |
|
1948 |
#if defined(DEBUG_TLB) |
|
1949 |
printf("tlb_flush_page: forced full flush (" |
|
1950 |
TARGET_FMT_lx "/" TARGET_FMT_lx ")\n", |
|
1951 |
env->tlb_flush_addr, env->tlb_flush_mask); |
|
1952 |
#endif |
|
1953 |
tlb_flush(env, 1); |
|
1954 |
return; |
|
1955 |
} |
|
1944 | 1956 |
/* must reset current TB so that interrupts cannot modify the |
1945 | 1957 |
links while we are modifying them */ |
1946 | 1958 |
env->current_tb = NULL; |
... | ... | |
2090 | 2102 |
tlb_set_dirty1(&env->tlb_table[mmu_idx][i], vaddr); |
2091 | 2103 |
} |
2092 | 2104 |
|
2093 |
/* add a new TLB entry. At most one entry for a given virtual address |
|
2094 |
is permitted. Return 0 if OK or 2 if the page could not be mapped |
|
2095 |
(can only happen in non SOFTMMU mode for I/O pages or pages |
|
2096 |
conflicting with the host address space). */ |
|
2097 |
int tlb_set_page_exec(CPUState *env, target_ulong vaddr, |
|
2098 |
target_phys_addr_t paddr, int prot, |
|
2099 |
int mmu_idx, int is_softmmu) |
|
2105 |
/* Our TLB does not support large pages, so remember the area covered by |
|
2106 |
large pages and trigger a full TLB flush if these are invalidated. */ |
|
2107 |
static void tlb_add_large_page(CPUState *env, target_ulong vaddr, |
|
2108 |
target_ulong size) |
|
2109 |
{ |
|
2110 |
target_ulong mask = ~(size - 1); |
|
2111 |
|
|
2112 |
if (env->tlb_flush_addr == (target_ulong)-1) { |
|
2113 |
env->tlb_flush_addr = vaddr & mask; |
|
2114 |
env->tlb_flush_mask = mask; |
|
2115 |
return; |
|
2116 |
} |
|
2117 |
/* Extend the existing region to include the new page. |
|
2118 |
This is a compromise between unnecessary flushes and the cost |
|
2119 |
of maintaining a full variable size TLB. */ |
|
2120 |
mask &= env->tlb_flush_mask; |
|
2121 |
while (((env->tlb_flush_addr ^ vaddr) & mask) != 0) { |
|
2122 |
mask <<= 1; |
|
2123 |
} |
|
2124 |
env->tlb_flush_addr &= mask; |
|
2125 |
env->tlb_flush_mask = mask; |
|
2126 |
} |
|
2127 |
|
|
2128 |
/* Add a new TLB entry. At most one entry for a given virtual address |
|
2129 |
is permitted. Only a single TARGET_PAGE_SIZE region is mapped, the |
|
2130 |
supplied size is only used by tlb_flush_page. */ |
|
2131 |
void tlb_set_page(CPUState *env, target_ulong vaddr, |
|
2132 |
target_phys_addr_t paddr, int prot, |
|
2133 |
int mmu_idx, target_ulong size) |
|
2100 | 2134 |
{ |
2101 | 2135 |
PhysPageDesc *p; |
2102 | 2136 |
unsigned long pd; |
... | ... | |
2104 | 2138 |
target_ulong address; |
2105 | 2139 |
target_ulong code_address; |
2106 | 2140 |
target_phys_addr_t addend; |
2107 |
int ret; |
|
2108 | 2141 |
CPUTLBEntry *te; |
2109 | 2142 |
CPUWatchpoint *wp; |
2110 | 2143 |
target_phys_addr_t iotlb; |
2111 | 2144 |
|
2145 |
assert(size >= TARGET_PAGE_SIZE); |
|
2146 |
if (size != TARGET_PAGE_SIZE) { |
|
2147 |
tlb_add_large_page(env, vaddr, size); |
|
2148 |
} |
|
2112 | 2149 |
p = phys_page_find(paddr >> TARGET_PAGE_BITS); |
2113 | 2150 |
if (!p) { |
2114 | 2151 |
pd = IO_MEM_UNASSIGNED; |
... | ... | |
2120 | 2157 |
vaddr, (int)paddr, prot, mmu_idx, is_softmmu, pd); |
2121 | 2158 |
#endif |
2122 | 2159 |
|
2123 |
ret = 0; |
|
2124 | 2160 |
address = vaddr; |
2125 | 2161 |
if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM && !(pd & IO_MEM_ROMD)) { |
2126 | 2162 |
/* IO memory case (romd handled later) */ |
... | ... | |
2190 | 2226 |
} else { |
2191 | 2227 |
te->addr_write = -1; |
2192 | 2228 |
} |
2193 |
return ret; |
|
2194 | 2229 |
} |
2195 | 2230 |
|
2196 | 2231 |
#else |
b/hw/alpha_palcode.c | ||
---|---|---|
1003 | 1003 |
/* No fault */ |
1004 | 1004 |
page_size = 1ULL << zbits; |
1005 | 1005 |
address &= ~(page_size - 1); |
1006 |
/* FIXME: page_size should probably be passed to tlb_set_page, |
|
1007 |
and this loop removed. */ |
|
1006 | 1008 |
for (end = physical + page_size; physical < end; physical += 0x1000) { |
1007 |
ret = tlb_set_page(env, address, physical, prot,
|
|
1008 |
mmu_idx, is_softmmu);
|
|
1009 |
tlb_set_page(env, address, physical, prot, mmu_idx,
|
|
1010 |
TARGET_PAGE_SIZE);
|
|
1009 | 1011 |
address += 0x1000; |
1010 | 1012 |
} |
1013 |
ret = 0; |
|
1011 | 1014 |
break; |
1012 | 1015 |
#if 0 |
1013 | 1016 |
case 1: |
b/target-arm/helper.c | ||
---|---|---|
894 | 894 |
} |
895 | 895 |
|
896 | 896 |
static int get_phys_addr_v5(CPUState *env, uint32_t address, int access_type, |
897 |
int is_user, uint32_t *phys_ptr, int *prot) |
|
897 |
int is_user, uint32_t *phys_ptr, int *prot, |
|
898 |
target_ulong *page_size) |
|
898 | 899 |
{ |
899 | 900 |
int code; |
900 | 901 |
uint32_t table; |
... | ... | |
927 | 928 |
phys_addr = (desc & 0xfff00000) | (address & 0x000fffff); |
928 | 929 |
ap = (desc >> 10) & 3; |
929 | 930 |
code = 13; |
931 |
*page_size = 1024 * 1024; |
|
930 | 932 |
} else { |
931 | 933 |
/* Lookup l2 entry. */ |
932 | 934 |
if (type == 1) { |
... | ... | |
944 | 946 |
case 1: /* 64k page. */ |
945 | 947 |
phys_addr = (desc & 0xffff0000) | (address & 0xffff); |
946 | 948 |
ap = (desc >> (4 + ((address >> 13) & 6))) & 3; |
949 |
*page_size = 0x10000; |
|
947 | 950 |
break; |
948 | 951 |
case 2: /* 4k page. */ |
949 | 952 |
phys_addr = (desc & 0xfffff000) | (address & 0xfff); |
950 | 953 |
ap = (desc >> (4 + ((address >> 13) & 6))) & 3; |
954 |
*page_size = 0x1000; |
|
951 | 955 |
break; |
952 | 956 |
case 3: /* 1k page. */ |
953 | 957 |
if (type == 1) { |
... | ... | |
962 | 966 |
phys_addr = (desc & 0xfffffc00) | (address & 0x3ff); |
963 | 967 |
} |
964 | 968 |
ap = (desc >> 4) & 3; |
969 |
*page_size = 0x400; |
|
965 | 970 |
break; |
966 | 971 |
default: |
967 | 972 |
/* Never happens, but compiler isn't smart enough to tell. */ |
... | ... | |
981 | 986 |
} |
982 | 987 |
|
983 | 988 |
static int get_phys_addr_v6(CPUState *env, uint32_t address, int access_type, |
984 |
int is_user, uint32_t *phys_ptr, int *prot) |
|
989 |
int is_user, uint32_t *phys_ptr, int *prot, |
|
990 |
target_ulong *page_size) |
|
985 | 991 |
{ |
986 | 992 |
int code; |
987 | 993 |
uint32_t table; |
... | ... | |
1021 | 1027 |
if (desc & (1 << 18)) { |
1022 | 1028 |
/* Supersection. */ |
1023 | 1029 |
phys_addr = (desc & 0xff000000) | (address & 0x00ffffff); |
1030 |
*page_size = 0x1000000; |
|
1024 | 1031 |
} else { |
1025 | 1032 |
/* Section. */ |
1026 | 1033 |
phys_addr = (desc & 0xfff00000) | (address & 0x000fffff); |
1034 |
*page_size = 0x100000; |
|
1027 | 1035 |
} |
1028 | 1036 |
ap = ((desc >> 10) & 3) | ((desc >> 13) & 4); |
1029 | 1037 |
xn = desc & (1 << 4); |
... | ... | |
1040 | 1048 |
case 1: /* 64k page. */ |
1041 | 1049 |
phys_addr = (desc & 0xffff0000) | (address & 0xffff); |
1042 | 1050 |
xn = desc & (1 << 15); |
1051 |
*page_size = 0x10000; |
|
1043 | 1052 |
break; |
1044 | 1053 |
case 2: case 3: /* 4k page. */ |
1045 | 1054 |
phys_addr = (desc & 0xfffff000) | (address & 0xfff); |
1046 | 1055 |
xn = desc & 1; |
1056 |
*page_size = 0x1000; |
|
1047 | 1057 |
break; |
1048 | 1058 |
default: |
1049 | 1059 |
/* Never happens, but compiler isn't smart enough to tell. */ |
... | ... | |
1132 | 1142 |
|
1133 | 1143 |
static inline int get_phys_addr(CPUState *env, uint32_t address, |
1134 | 1144 |
int access_type, int is_user, |
1135 |
uint32_t *phys_ptr, int *prot) |
|
1145 |
uint32_t *phys_ptr, int *prot, |
|
1146 |
target_ulong *page_size) |
|
1136 | 1147 |
{ |
1137 | 1148 |
/* Fast Context Switch Extension. */ |
1138 | 1149 |
if (address < 0x02000000) |
... | ... | |
1142 | 1153 |
/* MMU/MPU disabled. */ |
1143 | 1154 |
*phys_ptr = address; |
1144 | 1155 |
*prot = PAGE_READ | PAGE_WRITE; |
1156 |
*page_size = TARGET_PAGE_SIZE; |
|
1145 | 1157 |
return 0; |
1146 | 1158 |
} else if (arm_feature(env, ARM_FEATURE_MPU)) { |
1159 |
*page_size = TARGET_PAGE_SIZE; |
|
1147 | 1160 |
return get_phys_addr_mpu(env, address, access_type, is_user, phys_ptr, |
1148 | 1161 |
prot); |
1149 | 1162 |
} else if (env->cp15.c1_sys & (1 << 23)) { |
1150 | 1163 |
return get_phys_addr_v6(env, address, access_type, is_user, phys_ptr, |
1151 |
prot); |
|
1164 |
prot, page_size);
|
|
1152 | 1165 |
} else { |
1153 | 1166 |
return get_phys_addr_v5(env, address, access_type, is_user, phys_ptr, |
1154 |
prot); |
|
1167 |
prot, page_size);
|
|
1155 | 1168 |
} |
1156 | 1169 |
} |
1157 | 1170 |
|
... | ... | |
1159 | 1172 |
int access_type, int mmu_idx, int is_softmmu) |
1160 | 1173 |
{ |
1161 | 1174 |
uint32_t phys_addr; |
1175 |
target_ulong page_size; |
|
1162 | 1176 |
int prot; |
1163 | 1177 |
int ret, is_user; |
1164 | 1178 |
|
1165 | 1179 |
is_user = mmu_idx == MMU_USER_IDX; |
1166 |
ret = get_phys_addr(env, address, access_type, is_user, &phys_addr, &prot); |
|
1180 |
ret = get_phys_addr(env, address, access_type, is_user, &phys_addr, &prot, |
|
1181 |
&page_size); |
|
1167 | 1182 |
if (ret == 0) { |
1168 | 1183 |
/* Map a single [sub]page. */ |
1169 | 1184 |
phys_addr &= ~(uint32_t)0x3ff; |
1170 | 1185 |
address &= ~(uint32_t)0x3ff; |
1171 |
return tlb_set_page (env, address, phys_addr, prot, mmu_idx, |
|
1172 |
is_softmmu); |
|
1186 |
tlb_set_page (env, address, phys_addr, prot | PAGE_EXEC, mmu_idx, |
|
1187 |
page_size); |
|
1188 |
return 0; |
|
1173 | 1189 |
} |
1174 | 1190 |
|
1175 | 1191 |
if (access_type == 2) { |
... | ... | |
1189 | 1205 |
target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr) |
1190 | 1206 |
{ |
1191 | 1207 |
uint32_t phys_addr; |
1208 |
target_ulong page_size; |
|
1192 | 1209 |
int prot; |
1193 | 1210 |
int ret; |
1194 | 1211 |
|
1195 |
ret = get_phys_addr(env, addr, 0, 0, &phys_addr, &prot); |
|
1212 |
ret = get_phys_addr(env, addr, 0, 0, &phys_addr, &prot, &page_size);
|
|
1196 | 1213 |
|
1197 | 1214 |
if (ret != 0) |
1198 | 1215 |
return -1; |
... | ... | |
1406 | 1423 |
tlb_flush(env, 0); |
1407 | 1424 |
break; |
1408 | 1425 |
case 1: /* Invalidate single TLB entry. */ |
1409 |
#if 0 |
|
1410 |
/* ??? This is wrong for large pages and sections. */ |
|
1411 |
/* As an ugly hack to make linux work we always flush a 4K |
|
1412 |
pages. */ |
|
1413 |
val &= 0xfffff000; |
|
1414 |
tlb_flush_page(env, val); |
|
1415 |
tlb_flush_page(env, val + 0x400); |
|
1416 |
tlb_flush_page(env, val + 0x800); |
|
1417 |
tlb_flush_page(env, val + 0xc00); |
|
1418 |
#else |
|
1419 |
tlb_flush(env, 1); |
|
1420 |
#endif |
|
1426 |
tlb_flush_page(env, val & TARGET_PAGE_MASK); |
|
1421 | 1427 |
break; |
1422 | 1428 |
case 2: /* Invalidate on ASID. */ |
1423 | 1429 |
tlb_flush(env, val == 0); |
b/target-cris/helper.c | ||
---|---|---|
100 | 100 |
*/ |
101 | 101 |
phy = res.phy & ~0x80000000; |
102 | 102 |
prot = res.prot; |
103 |
r = tlb_set_page(env, address & TARGET_PAGE_MASK, |
|
104 |
phy, prot, mmu_idx, is_softmmu); |
|
103 |
tlb_set_page(env, address & TARGET_PAGE_MASK, phy, |
|
104 |
prot | PAGE_EXEC, mmu_idx, TARGET_PAGE_SIZE); |
|
105 |
r = 0; |
|
105 | 106 |
} |
106 | 107 |
if (r > 0) |
107 | 108 |
D_LOG("%s returns %d irqreq=%x addr=%x" |
b/target-i386/helper.c | ||
---|---|---|
531 | 531 |
-1 = cannot handle fault |
532 | 532 |
0 = nothing more to do |
533 | 533 |
1 = generate PF fault |
534 |
2 = soft MMU activation required for this block |
|
535 | 534 |
*/ |
536 | 535 |
int cpu_x86_handle_mmu_fault(CPUX86State *env, target_ulong addr, |
537 | 536 |
int is_write1, int mmu_idx, int is_softmmu) |
538 | 537 |
{ |
539 | 538 |
uint64_t ptep, pte; |
540 | 539 |
target_ulong pde_addr, pte_addr; |
541 |
int error_code, is_dirty, prot, page_size, ret, is_write, is_user;
|
|
540 |
int error_code, is_dirty, prot, page_size, is_write, is_user; |
|
542 | 541 |
target_phys_addr_t paddr; |
543 | 542 |
uint32_t page_offset; |
544 | 543 |
target_ulong vaddr, virt_addr; |
... | ... | |
799 | 798 |
paddr = (pte & TARGET_PAGE_MASK) + page_offset; |
800 | 799 |
vaddr = virt_addr + page_offset; |
801 | 800 |
|
802 |
ret = tlb_set_page_exec(env, vaddr, paddr, prot, mmu_idx, is_softmmu);
|
|
803 |
return ret;
|
|
801 |
tlb_set_page(env, vaddr, paddr, prot, mmu_idx, page_size);
|
|
802 |
return 0;
|
|
804 | 803 |
do_fault_protect: |
805 | 804 |
error_code = PG_ERROR_P_MASK; |
806 | 805 |
do_fault: |
b/target-m68k/helper.c | ||
---|---|---|
368 | 368 |
int prot; |
369 | 369 |
|
370 | 370 |
address &= TARGET_PAGE_MASK; |
371 |
prot = PAGE_READ | PAGE_WRITE; |
|
372 |
return tlb_set_page(env, address, address, prot, mmu_idx, is_softmmu); |
|
371 |
prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC; |
|
372 |
tlb_set_page(env, address, address, prot, mmu_idx, TARGET_PAGE_SIZE); |
|
373 |
return 0; |
|
373 | 374 |
} |
374 | 375 |
|
375 | 376 |
/* Notify CPU of a pending interrupt. Prioritization and vectoring should |
b/target-microblaze/helper.c | ||
---|---|---|
76 | 76 |
|
77 | 77 |
DMMU(qemu_log("MMU map mmu=%d v=%x p=%x prot=%x\n", |
78 | 78 |
mmu_idx, vaddr, paddr, lu.prot)); |
79 |
r = tlb_set_page(env, vaddr,
|
|
80 |
paddr, lu.prot, mmu_idx, is_softmmu);
|
|
79 |
tlb_set_page(env, vaddr, paddr, lu.prot, mmu_idx, TARGET_PAGE_SIZE);
|
|
80 |
r = 0;
|
|
81 | 81 |
} else { |
82 | 82 |
env->sregs[SR_EAR] = address; |
83 | 83 |
DMMU(qemu_log("mmu=%d miss v=%x\n", mmu_idx, address)); |
... | ... | |
107 | 107 |
/* MMU disabled or not available. */ |
108 | 108 |
address &= TARGET_PAGE_MASK; |
109 | 109 |
prot = PAGE_BITS; |
110 |
r = tlb_set_page(env, address, address, prot, mmu_idx, is_softmmu); |
|
110 |
tlb_set_page(env, address, address, prot, mmu_idx, TARGET_PAGE_SIZE); |
|
111 |
r = 0; |
|
111 | 112 |
} |
112 | 113 |
return r; |
113 | 114 |
} |
b/target-mips/helper.c | ||
---|---|---|
296 | 296 |
qemu_log("%s address=" TARGET_FMT_lx " ret %d physical " TARGET_FMT_plx " prot %d\n", |
297 | 297 |
__func__, address, ret, physical, prot); |
298 | 298 |
if (ret == TLBRET_MATCH) { |
299 |
ret = tlb_set_page(env, address & TARGET_PAGE_MASK, |
|
300 |
physical & TARGET_PAGE_MASK, prot, |
|
301 |
mmu_idx, is_softmmu); |
|
299 |
tlb_set_page(env, address & TARGET_PAGE_MASK, |
|
300 |
physical & TARGET_PAGE_MASK, prot | PAGE_EXEC, |
|
301 |
mmu_idx, TARGET_PAGE_SIZE); |
|
302 |
ret = 0; |
|
302 | 303 |
} else if (ret < 0) |
303 | 304 |
#endif |
304 | 305 |
{ |
b/target-ppc/helper.c | ||
---|---|---|
1410 | 1410 |
} |
1411 | 1411 |
ret = get_physical_address(env, &ctx, address, rw, access_type); |
1412 | 1412 |
if (ret == 0) { |
1413 |
ret = tlb_set_page_exec(env, address & TARGET_PAGE_MASK, |
|
1414 |
ctx.raddr & TARGET_PAGE_MASK, ctx.prot, |
|
1415 |
mmu_idx, is_softmmu); |
|
1413 |
tlb_set_page(env, address & TARGET_PAGE_MASK, |
|
1414 |
ctx.raddr & TARGET_PAGE_MASK, ctx.prot, |
|
1415 |
mmu_idx, TARGET_PAGE_SIZE); |
|
1416 |
ret = 0; |
|
1416 | 1417 |
} else if (ret < 0) { |
1417 | 1418 |
LOG_MMU_STATE(env); |
1418 | 1419 |
if (access_type == ACCESS_CODE) { |
b/target-s390x/helper.c | ||
---|---|---|
69 | 69 |
/* XXX: implement mmu */ |
70 | 70 |
|
71 | 71 |
phys = address; |
72 |
prot = PAGE_READ | PAGE_WRITE; |
|
72 |
prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
|
|
73 | 73 |
|
74 |
return tlb_set_page(env, address & TARGET_PAGE_MASK, |
|
75 |
phys & TARGET_PAGE_MASK, prot, |
|
76 |
mmu_idx, is_softmmu); |
|
74 |
tlb_set_page(env, address & TARGET_PAGE_MASK, |
|
75 |
phys & TARGET_PAGE_MASK, prot, |
|
76 |
mmu_idx, TARGET_PAGE_SIZE); |
|
77 |
return 0; |
|
77 | 78 |
} |
78 | 79 |
#endif /* CONFIG_USER_ONLY */ |
b/target-sh4/helper.c | ||
---|---|---|
470 | 470 |
address &= TARGET_PAGE_MASK; |
471 | 471 |
physical &= TARGET_PAGE_MASK; |
472 | 472 |
|
473 |
return tlb_set_page(env, address, physical, prot, mmu_idx, is_softmmu); |
|
473 |
tlb_set_page(env, address, physical, prot, mmu_idx, TARGET_PAGE_SIZE); |
|
474 |
return 0; |
|
474 | 475 |
} |
475 | 476 |
|
476 | 477 |
target_phys_addr_t cpu_get_phys_page_debug(CPUState * env, target_ulong addr) |
b/target-sparc/helper.c | ||
---|---|---|
102 | 102 |
|
103 | 103 |
static int get_physical_address(CPUState *env, target_phys_addr_t *physical, |
104 | 104 |
int *prot, int *access_index, |
105 |
target_ulong address, int rw, int mmu_idx) |
|
105 |
target_ulong address, int rw, int mmu_idx, |
|
106 |
target_ulong *page_size) |
|
106 | 107 |
{ |
107 | 108 |
int access_perms = 0; |
108 | 109 |
target_phys_addr_t pde_ptr; |
... | ... | |
113 | 114 |
is_user = mmu_idx == MMU_USER_IDX; |
114 | 115 |
|
115 | 116 |
if ((env->mmuregs[0] & MMU_E) == 0) { /* MMU disabled */ |
117 |
*page_size = TARGET_PAGE_SIZE; |
|
116 | 118 |
// Boot mode: instruction fetches are taken from PROM |
117 | 119 |
if (rw == 2 && (env->mmuregs[0] & env->def->mmu_bm)) { |
118 | 120 |
*physical = env->prom_addr | (address & 0x7ffffULL); |
... | ... | |
175 | 177 |
page_offset = (address & TARGET_PAGE_MASK) & |
176 | 178 |
(TARGET_PAGE_SIZE - 1); |
177 | 179 |
} |
180 |
*page_size = TARGET_PAGE_SIZE; |
|
178 | 181 |
break; |
179 | 182 |
case 2: /* L2 PTE */ |
180 | 183 |
page_offset = address & 0x3ffff; |
184 |
*page_size = 0x40000; |
|
181 | 185 |
} |
182 | 186 |
break; |
183 | 187 |
case 2: /* L1 PTE */ |
184 | 188 |
page_offset = address & 0xffffff; |
189 |
*page_size = 0x1000000; |
|
185 | 190 |
} |
186 | 191 |
} |
187 | 192 |
|
... | ... | |
220 | 225 |
{ |
221 | 226 |
target_phys_addr_t paddr; |
222 | 227 |
target_ulong vaddr; |
223 |
int error_code = 0, prot, ret = 0, access_index; |
|
228 |
target_ulong page_size; |
|
229 |
int error_code = 0, prot, access_index; |
|
224 | 230 |
|
225 | 231 |
error_code = get_physical_address(env, &paddr, &prot, &access_index, |
226 |
address, rw, mmu_idx); |
|
232 |
address, rw, mmu_idx, &page_size);
|
|
227 | 233 |
if (error_code == 0) { |
228 | 234 |
vaddr = address & TARGET_PAGE_MASK; |
229 | 235 |
paddr &= TARGET_PAGE_MASK; |
... | ... | |
231 | 237 |
printf("Translate at " TARGET_FMT_lx " -> " TARGET_FMT_plx ", vaddr " |
232 | 238 |
TARGET_FMT_lx "\n", address, paddr, vaddr); |
233 | 239 |
#endif |
234 |
ret = tlb_set_page_exec(env, vaddr, paddr, prot, mmu_idx, is_softmmu);
|
|
235 |
return ret;
|
|
240 |
tlb_set_page(env, vaddr, paddr, prot, mmu_idx, page_size);
|
|
241 |
return 0;
|
|
236 | 242 |
} |
237 | 243 |
|
238 | 244 |
if (env->mmuregs[3]) /* Fault status register */ |
... | ... | |
247 | 253 |
// switching to normal mode. |
248 | 254 |
vaddr = address & TARGET_PAGE_MASK; |
249 | 255 |
prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC; |
250 |
ret = tlb_set_page_exec(env, vaddr, paddr, prot, mmu_idx, is_softmmu);
|
|
251 |
return ret;
|
|
256 |
tlb_set_page(env, vaddr, paddr, prot, mmu_idx, TARGET_PAGE_SIZE);
|
|
257 |
return 0;
|
|
252 | 258 |
} else { |
253 | 259 |
if (rw & 2) |
254 | 260 |
env->exception_index = TT_TFAULT; |
... | ... | |
531 | 537 |
|
532 | 538 |
static int get_physical_address(CPUState *env, target_phys_addr_t *physical, |
533 | 539 |
int *prot, int *access_index, |
534 |
target_ulong address, int rw, int mmu_idx) |
|
540 |
target_ulong address, int rw, int mmu_idx, |
|
541 |
target_ulong *page_size) |
|
535 | 542 |
{ |
536 | 543 |
int is_user = mmu_idx == MMU_USER_IDX; |
537 | 544 |
|
545 |
/* ??? We treat everything as a small page, then explicitly flush |
|
546 |
everything when an entry is evicted. */ |
|
547 |
*page_size = TARGET_PAGE_SIZE; |
|
538 | 548 |
if (rw == 2) |
539 | 549 |
return get_physical_address_code(env, physical, prot, address, |
540 | 550 |
is_user); |
... | ... | |
549 | 559 |
{ |
550 | 560 |
target_ulong virt_addr, vaddr; |
551 | 561 |
target_phys_addr_t paddr; |
552 |
int error_code = 0, prot, ret = 0, access_index; |
|
562 |
target_ulong page_size; |
|
563 |
int error_code = 0, prot, access_index; |
|
553 | 564 |
|
554 | 565 |
error_code = get_physical_address(env, &paddr, &prot, &access_index, |
555 |
address, rw, mmu_idx); |
|
566 |
address, rw, mmu_idx, &page_size);
|
|
556 | 567 |
if (error_code == 0) { |
557 | 568 |
virt_addr = address & TARGET_PAGE_MASK; |
558 | 569 |
vaddr = virt_addr + ((address & TARGET_PAGE_MASK) & |
... | ... | |
561 | 572 |
printf("Translate at 0x%" PRIx64 " -> 0x%" PRIx64 ", vaddr 0x%" PRIx64 |
562 | 573 |
"\n", address, paddr, vaddr); |
563 | 574 |
#endif |
564 |
ret = tlb_set_page_exec(env, vaddr, paddr, prot, mmu_idx, is_softmmu);
|
|
565 |
return ret;
|
|
575 |
tlb_set_page(env, vaddr, paddr, prot, mmu_idx, page_size);
|
|
576 |
return 0;
|
|
566 | 577 |
} |
567 | 578 |
// XXX |
568 | 579 |
return 1; |
... | ... | |
656 | 667 |
target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr) |
657 | 668 |
{ |
658 | 669 |
target_phys_addr_t phys_addr; |
670 |
target_ulong page_size; |
|
659 | 671 |
int prot, access_index; |
660 | 672 |
|
661 | 673 |
if (get_physical_address(env, &phys_addr, &prot, &access_index, addr, 2, |
662 |
MMU_KERNEL_IDX) != 0) |
|
674 |
MMU_KERNEL_IDX, &page_size) != 0)
|
|
663 | 675 |
if (get_physical_address(env, &phys_addr, &prot, &access_index, addr, |
664 |
0, MMU_KERNEL_IDX) != 0) |
|
676 |
0, MMU_KERNEL_IDX, &page_size) != 0)
|
|
665 | 677 |
return -1; |
666 | 678 |
if (cpu_get_physical_page_desc(phys_addr) == IO_MEM_UNASSIGNED) |
667 | 679 |
return -1; |
Also available in: Unified diff