Commit 8f793433afd8f892db15fc153bb0aa94145582d6
1 parent
0387d928
Enable PowerPC 64 MMU model and exceptions.
Cleanups in MMU exceptions generation. git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3319 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
1 changed file
with
71 additions
and
68 deletions
target-ppc/helper.c
@@ -45,10 +45,10 @@ int cpu_ppc_handle_mmu_fault (CPUState *env, target_ulong address, int rw, | @@ -45,10 +45,10 @@ int cpu_ppc_handle_mmu_fault (CPUState *env, target_ulong address, int rw, | ||
45 | 45 | ||
46 | if (rw == 2) { | 46 | if (rw == 2) { |
47 | exception = POWERPC_EXCP_ISI; | 47 | exception = POWERPC_EXCP_ISI; |
48 | - error_code = 0; | 48 | + error_code = 0x40000000; |
49 | } else { | 49 | } else { |
50 | exception = POWERPC_EXCP_DSI; | 50 | exception = POWERPC_EXCP_DSI; |
51 | - error_code = 0; | 51 | + error_code = 0x40000000; |
52 | if (rw) | 52 | if (rw) |
53 | error_code |= 0x02000000; | 53 | error_code |= 0x02000000; |
54 | env->spr[SPR_DAR] = address; | 54 | env->spr[SPR_DAR] = address; |
@@ -1227,7 +1227,6 @@ int cpu_ppc_handle_mmu_fault (CPUState *env, target_ulong address, int rw, | @@ -1227,7 +1227,6 @@ int cpu_ppc_handle_mmu_fault (CPUState *env, target_ulong address, int rw, | ||
1227 | int is_user, int is_softmmu) | 1227 | int is_user, int is_softmmu) |
1228 | { | 1228 | { |
1229 | mmu_ctx_t ctx; | 1229 | mmu_ctx_t ctx; |
1230 | - int exception = 0, error_code = 0; | ||
1231 | int access_type; | 1230 | int access_type; |
1232 | int ret = 0; | 1231 | int ret = 0; |
1233 | 1232 | ||
@@ -1253,40 +1252,34 @@ int cpu_ppc_handle_mmu_fault (CPUState *env, target_ulong address, int rw, | @@ -1253,40 +1252,34 @@ int cpu_ppc_handle_mmu_fault (CPUState *env, target_ulong address, int rw, | ||
1253 | cpu_dump_state(env, logfile, fprintf, 0); | 1252 | cpu_dump_state(env, logfile, fprintf, 0); |
1254 | #endif | 1253 | #endif |
1255 | if (access_type == ACCESS_CODE) { | 1254 | if (access_type == ACCESS_CODE) { |
1256 | - exception = POWERPC_EXCP_ISI; | ||
1257 | switch (ret) { | 1255 | switch (ret) { |
1258 | case -1: | 1256 | case -1: |
1259 | /* No matches in page tables or TLB */ | 1257 | /* No matches in page tables or TLB */ |
1260 | switch (env->mmu_model) { | 1258 | switch (env->mmu_model) { |
1261 | case POWERPC_MMU_SOFT_6xx: | 1259 | case POWERPC_MMU_SOFT_6xx: |
1262 | - exception = POWERPC_EXCP_IFTLB; | 1260 | + env->exception_index = POWERPC_EXCP_IFTLB; |
1261 | + env->error_code = 1 << 18; | ||
1263 | env->spr[SPR_IMISS] = address; | 1262 | env->spr[SPR_IMISS] = address; |
1264 | env->spr[SPR_ICMP] = 0x80000000 | ctx.ptem; | 1263 | env->spr[SPR_ICMP] = 0x80000000 | ctx.ptem; |
1265 | - error_code = 1 << 18; | ||
1266 | goto tlb_miss; | 1264 | goto tlb_miss; |
1267 | case POWERPC_MMU_SOFT_74xx: | 1265 | case POWERPC_MMU_SOFT_74xx: |
1268 | - exception = POWERPC_EXCP_IFTLB; | 1266 | + env->exception_index = POWERPC_EXCP_IFTLB; |
1269 | goto tlb_miss_74xx; | 1267 | goto tlb_miss_74xx; |
1270 | case POWERPC_MMU_SOFT_4xx: | 1268 | case POWERPC_MMU_SOFT_4xx: |
1271 | case POWERPC_MMU_SOFT_4xx_Z: | 1269 | case POWERPC_MMU_SOFT_4xx_Z: |
1272 | - exception = POWERPC_EXCP_ITLB; | ||
1273 | - error_code = 0; | 1270 | + env->exception_index = POWERPC_EXCP_ITLB; |
1271 | + env->error_code = 0; | ||
1274 | env->spr[SPR_40x_DEAR] = address; | 1272 | env->spr[SPR_40x_DEAR] = address; |
1275 | env->spr[SPR_40x_ESR] = 0x00000000; | 1273 | env->spr[SPR_40x_ESR] = 0x00000000; |
1276 | break; | 1274 | break; |
1277 | case POWERPC_MMU_32B: | 1275 | case POWERPC_MMU_32B: |
1278 | - error_code = 0x40000000; | ||
1279 | - break; | ||
1280 | #if defined(TARGET_PPC64) | 1276 | #if defined(TARGET_PPC64) |
1281 | case POWERPC_MMU_64B: | 1277 | case POWERPC_MMU_64B: |
1282 | - /* XXX: TODO */ | ||
1283 | - cpu_abort(env, "MMU model not implemented\n"); | ||
1284 | - return -1; | ||
1285 | case POWERPC_MMU_64BRIDGE: | 1278 | case POWERPC_MMU_64BRIDGE: |
1286 | - /* XXX: TODO */ | ||
1287 | - cpu_abort(env, "MMU model not implemented\n"); | ||
1288 | - return -1; | ||
1289 | #endif | 1279 | #endif |
1280 | + env->exception_index = POWERPC_EXCP_ISI; | ||
1281 | + env->error_code = 0x40000000; | ||
1282 | + break; | ||
1290 | case POWERPC_MMU_601: | 1283 | case POWERPC_MMU_601: |
1291 | /* XXX: TODO */ | 1284 | /* XXX: TODO */ |
1292 | cpu_abort(env, "MMU model not implemented\n"); | 1285 | cpu_abort(env, "MMU model not implemented\n"); |
@@ -1310,64 +1303,65 @@ int cpu_ppc_handle_mmu_fault (CPUState *env, target_ulong address, int rw, | @@ -1310,64 +1303,65 @@ int cpu_ppc_handle_mmu_fault (CPUState *env, target_ulong address, int rw, | ||
1310 | break; | 1303 | break; |
1311 | case -2: | 1304 | case -2: |
1312 | /* Access rights violation */ | 1305 | /* Access rights violation */ |
1313 | - error_code = 0x08000000; | 1306 | + env->exception_index = POWERPC_EXCP_ISI; |
1307 | + env->error_code = 0x08000000; | ||
1314 | break; | 1308 | break; |
1315 | case -3: | 1309 | case -3: |
1316 | /* No execute protection violation */ | 1310 | /* No execute protection violation */ |
1317 | - error_code = 0x10000000; | 1311 | + env->exception_index = POWERPC_EXCP_ISI; |
1312 | + env->error_code = 0x10000000; | ||
1318 | break; | 1313 | break; |
1319 | case -4: | 1314 | case -4: |
1320 | /* Direct store exception */ | 1315 | /* Direct store exception */ |
1321 | /* No code fetch is allowed in direct-store areas */ | 1316 | /* No code fetch is allowed in direct-store areas */ |
1322 | - error_code = 0x10000000; | 1317 | + env->exception_index = POWERPC_EXCP_ISI; |
1318 | + env->error_code = 0x10000000; | ||
1323 | break; | 1319 | break; |
1324 | #if defined(TARGET_PPC64) | 1320 | #if defined(TARGET_PPC64) |
1325 | case -5: | 1321 | case -5: |
1326 | /* No match in segment table */ | 1322 | /* No match in segment table */ |
1327 | - exception = POWERPC_EXCP_ISEG; | ||
1328 | - error_code = 0; | 1323 | + env->exception_index = POWERPC_EXCP_ISEG; |
1324 | + env->error_code = 0; | ||
1329 | break; | 1325 | break; |
1330 | #endif | 1326 | #endif |
1331 | } | 1327 | } |
1332 | } else { | 1328 | } else { |
1333 | - exception = POWERPC_EXCP_DSI; | ||
1334 | switch (ret) { | 1329 | switch (ret) { |
1335 | case -1: | 1330 | case -1: |
1336 | /* No matches in page tables or TLB */ | 1331 | /* No matches in page tables or TLB */ |
1337 | switch (env->mmu_model) { | 1332 | switch (env->mmu_model) { |
1338 | case POWERPC_MMU_SOFT_6xx: | 1333 | case POWERPC_MMU_SOFT_6xx: |
1339 | if (rw == 1) { | 1334 | if (rw == 1) { |
1340 | - exception = POWERPC_EXCP_DSTLB; | ||
1341 | - error_code = 1 << 16; | 1335 | + env->exception_index = POWERPC_EXCP_DSTLB; |
1336 | + env->error_code = 1 << 16; | ||
1342 | } else { | 1337 | } else { |
1343 | - exception = POWERPC_EXCP_DLTLB; | ||
1344 | - error_code = 0; | 1338 | + env->exception_index = POWERPC_EXCP_DLTLB; |
1339 | + env->error_code = 0; | ||
1345 | } | 1340 | } |
1346 | env->spr[SPR_DMISS] = address; | 1341 | env->spr[SPR_DMISS] = address; |
1347 | env->spr[SPR_DCMP] = 0x80000000 | ctx.ptem; | 1342 | env->spr[SPR_DCMP] = 0x80000000 | ctx.ptem; |
1348 | tlb_miss: | 1343 | tlb_miss: |
1349 | - error_code |= ctx.key << 19; | 1344 | + env->error_code |= ctx.key << 19; |
1350 | env->spr[SPR_HASH1] = ctx.pg_addr[0]; | 1345 | env->spr[SPR_HASH1] = ctx.pg_addr[0]; |
1351 | env->spr[SPR_HASH2] = ctx.pg_addr[1]; | 1346 | env->spr[SPR_HASH2] = ctx.pg_addr[1]; |
1352 | - /* Do not alter DAR nor DSISR */ | ||
1353 | - goto out; | 1347 | + break; |
1354 | case POWERPC_MMU_SOFT_74xx: | 1348 | case POWERPC_MMU_SOFT_74xx: |
1355 | if (rw == 1) { | 1349 | if (rw == 1) { |
1356 | - exception = POWERPC_EXCP_DSTLB; | 1350 | + env->exception_index = POWERPC_EXCP_DSTLB; |
1357 | } else { | 1351 | } else { |
1358 | - exception = POWERPC_EXCP_DLTLB; | 1352 | + env->exception_index = POWERPC_EXCP_DLTLB; |
1359 | } | 1353 | } |
1360 | tlb_miss_74xx: | 1354 | tlb_miss_74xx: |
1361 | /* Implement LRU algorithm */ | 1355 | /* Implement LRU algorithm */ |
1356 | + env->error_code = ctx.key << 19; | ||
1362 | env->spr[SPR_TLBMISS] = (address & ~((target_ulong)0x3)) | | 1357 | env->spr[SPR_TLBMISS] = (address & ~((target_ulong)0x3)) | |
1363 | ((env->last_way + 1) & (env->nb_ways - 1)); | 1358 | ((env->last_way + 1) & (env->nb_ways - 1)); |
1364 | env->spr[SPR_PTEHI] = 0x80000000 | ctx.ptem; | 1359 | env->spr[SPR_PTEHI] = 0x80000000 | ctx.ptem; |
1365 | - error_code = ctx.key << 19; | ||
1366 | break; | 1360 | break; |
1367 | case POWERPC_MMU_SOFT_4xx: | 1361 | case POWERPC_MMU_SOFT_4xx: |
1368 | case POWERPC_MMU_SOFT_4xx_Z: | 1362 | case POWERPC_MMU_SOFT_4xx_Z: |
1369 | - exception = POWERPC_EXCP_DTLB; | ||
1370 | - error_code = 0; | 1363 | + env->exception_index = POWERPC_EXCP_DTLB; |
1364 | + env->error_code = 0; | ||
1371 | env->spr[SPR_40x_DEAR] = address; | 1365 | env->spr[SPR_40x_DEAR] = address; |
1372 | if (rw) | 1366 | if (rw) |
1373 | env->spr[SPR_40x_ESR] = 0x00800000; | 1367 | env->spr[SPR_40x_ESR] = 0x00800000; |
@@ -1375,18 +1369,18 @@ int cpu_ppc_handle_mmu_fault (CPUState *env, target_ulong address, int rw, | @@ -1375,18 +1369,18 @@ int cpu_ppc_handle_mmu_fault (CPUState *env, target_ulong address, int rw, | ||
1375 | env->spr[SPR_40x_ESR] = 0x00000000; | 1369 | env->spr[SPR_40x_ESR] = 0x00000000; |
1376 | break; | 1370 | break; |
1377 | case POWERPC_MMU_32B: | 1371 | case POWERPC_MMU_32B: |
1378 | - error_code = 0x40000000; | ||
1379 | - break; | ||
1380 | #if defined(TARGET_PPC64) | 1372 | #if defined(TARGET_PPC64) |
1381 | case POWERPC_MMU_64B: | 1373 | case POWERPC_MMU_64B: |
1382 | - /* XXX: TODO */ | ||
1383 | - cpu_abort(env, "MMU model not implemented\n"); | ||
1384 | - return -1; | ||
1385 | case POWERPC_MMU_64BRIDGE: | 1374 | case POWERPC_MMU_64BRIDGE: |
1386 | - /* XXX: TODO */ | ||
1387 | - cpu_abort(env, "MMU model not implemented\n"); | ||
1388 | - return -1; | ||
1389 | #endif | 1375 | #endif |
1376 | + env->exception_index = POWERPC_EXCP_DSI; | ||
1377 | + env->error_code = 0; | ||
1378 | + env->spr[SPR_DAR] = address; | ||
1379 | + if (rw == 1) | ||
1380 | + env->spr[SPR_DSISR] = 0x42000000; | ||
1381 | + else | ||
1382 | + env->spr[SPR_DSISR] = 0x40000000; | ||
1383 | + break; | ||
1390 | case POWERPC_MMU_601: | 1384 | case POWERPC_MMU_601: |
1391 | /* XXX: TODO */ | 1385 | /* XXX: TODO */ |
1392 | cpu_abort(env, "MMU model not implemented\n"); | 1386 | cpu_abort(env, "MMU model not implemented\n"); |
@@ -1410,52 +1404,66 @@ int cpu_ppc_handle_mmu_fault (CPUState *env, target_ulong address, int rw, | @@ -1410,52 +1404,66 @@ int cpu_ppc_handle_mmu_fault (CPUState *env, target_ulong address, int rw, | ||
1410 | break; | 1404 | break; |
1411 | case -2: | 1405 | case -2: |
1412 | /* Access rights violation */ | 1406 | /* Access rights violation */ |
1413 | - error_code = 0x08000000; | 1407 | + env->exception_index = POWERPC_EXCP_DSI; |
1408 | + env->error_code = 0; | ||
1409 | + env->spr[SPR_DAR] = address; | ||
1410 | + if (rw == 1) | ||
1411 | + env->spr[SPR_DSISR] = 0x0A000000; | ||
1412 | + else | ||
1413 | + env->spr[SPR_DSISR] = 0x08000000; | ||
1414 | break; | 1414 | break; |
1415 | case -4: | 1415 | case -4: |
1416 | /* Direct store exception */ | 1416 | /* Direct store exception */ |
1417 | switch (access_type) { | 1417 | switch (access_type) { |
1418 | case ACCESS_FLOAT: | 1418 | case ACCESS_FLOAT: |
1419 | /* Floating point load/store */ | 1419 | /* Floating point load/store */ |
1420 | - exception = POWERPC_EXCP_ALIGN; | ||
1421 | - error_code = POWERPC_EXCP_ALIGN_FP; | 1420 | + env->exception_index = POWERPC_EXCP_ALIGN; |
1421 | + env->error_code = POWERPC_EXCP_ALIGN_FP; | ||
1422 | + env->spr[SPR_DAR] = address; | ||
1422 | break; | 1423 | break; |
1423 | case ACCESS_RES: | 1424 | case ACCESS_RES: |
1424 | - /* lwarx, ldarx or srwcx. */ | ||
1425 | - error_code = 0x04000000; | 1425 | + /* lwarx, ldarx or stwcx. */ |
1426 | + env->exception_index = POWERPC_EXCP_DSI; | ||
1427 | + env->error_code = 0; | ||
1428 | + env->spr[SPR_DAR] = address; | ||
1429 | + if (rw == 1) | ||
1430 | + env->spr[SPR_DSISR] = 0x06000000; | ||
1431 | + else | ||
1432 | + env->spr[SPR_DSISR] = 0x04000000; | ||
1426 | break; | 1433 | break; |
1427 | case ACCESS_EXT: | 1434 | case ACCESS_EXT: |
1428 | /* eciwx or ecowx */ | 1435 | /* eciwx or ecowx */ |
1429 | - error_code = 0x04100000; | 1436 | + env->exception_index = POWERPC_EXCP_DSI; |
1437 | + env->error_code = 0; | ||
1438 | + env->spr[SPR_DAR] = address; | ||
1439 | + if (rw == 1) | ||
1440 | + env->spr[SPR_DSISR] = 0x06100000; | ||
1441 | + else | ||
1442 | + env->spr[SPR_DSISR] = 0x04100000; | ||
1430 | break; | 1443 | break; |
1431 | default: | 1444 | default: |
1432 | printf("DSI: invalid exception (%d)\n", ret); | 1445 | printf("DSI: invalid exception (%d)\n", ret); |
1433 | - exception = POWERPC_EXCP_PROGRAM; | ||
1434 | - error_code = POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_INVAL; | 1446 | + env->exception_index = POWERPC_EXCP_PROGRAM; |
1447 | + env->error_code = | ||
1448 | + POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_INVAL; | ||
1449 | + env->spr[SPR_DAR] = address; | ||
1435 | break; | 1450 | break; |
1436 | } | 1451 | } |
1437 | break; | 1452 | break; |
1438 | #if defined(TARGET_PPC64) | 1453 | #if defined(TARGET_PPC64) |
1439 | case -5: | 1454 | case -5: |
1440 | /* No match in segment table */ | 1455 | /* No match in segment table */ |
1441 | - exception = POWERPC_EXCP_DSEG; | ||
1442 | - error_code = 0; | 1456 | + env->exception_index = POWERPC_EXCP_DSEG; |
1457 | + env->error_code = 0; | ||
1458 | + env->spr[SPR_DAR] = address; | ||
1443 | break; | 1459 | break; |
1444 | #endif | 1460 | #endif |
1445 | } | 1461 | } |
1446 | - if (exception == POWERPC_EXCP_DSI && rw == 1) | ||
1447 | - error_code |= 0x02000000; | ||
1448 | - /* Store fault address */ | ||
1449 | - env->spr[SPR_DAR] = address; | ||
1450 | - env->spr[SPR_DSISR] = error_code; | ||
1451 | } | 1462 | } |
1452 | - out: | ||
1453 | #if 0 | 1463 | #if 0 |
1454 | - printf("%s: set exception to %d %02x\n", | ||
1455 | - __func__, exception, error_code); | 1464 | + printf("%s: set exception to %d %02x\n", __func__, |
1465 | + env->exception, env->error_code); | ||
1456 | #endif | 1466 | #endif |
1457 | - env->exception_index = exception; | ||
1458 | - env->error_code = error_code; | ||
1459 | ret = 1; | 1467 | ret = 1; |
1460 | } | 1468 | } |
1461 | 1469 | ||
@@ -2291,8 +2299,6 @@ static always_inline void powerpc_excp (CPUState *env, | @@ -2291,8 +2299,6 @@ static always_inline void powerpc_excp (CPUState *env, | ||
2291 | if (lpes1 == 0) | 2299 | if (lpes1 == 0) |
2292 | msr_hv = 1; | 2300 | msr_hv = 1; |
2293 | #endif | 2301 | #endif |
2294 | - /* XXX: TODO */ | ||
2295 | - cpu_abort(env, "Data segment exception is not implemented yet !\n"); | ||
2296 | goto store_next; | 2302 | goto store_next; |
2297 | case POWERPC_EXCP_ISEG: /* Instruction segment exception */ | 2303 | case POWERPC_EXCP_ISEG: /* Instruction segment exception */ |
2298 | msr_ri = 0; | 2304 | msr_ri = 0; |
@@ -2300,9 +2306,6 @@ static always_inline void powerpc_excp (CPUState *env, | @@ -2300,9 +2306,6 @@ static always_inline void powerpc_excp (CPUState *env, | ||
2300 | if (lpes1 == 0) | 2306 | if (lpes1 == 0) |
2301 | msr_hv = 1; | 2307 | msr_hv = 1; |
2302 | #endif | 2308 | #endif |
2303 | - /* XXX: TODO */ | ||
2304 | - cpu_abort(env, | ||
2305 | - "Instruction segment exception is not implemented yet !\n"); | ||
2306 | goto store_next; | 2309 | goto store_next; |
2307 | #endif /* defined(TARGET_PPC64) */ | 2310 | #endif /* defined(TARGET_PPC64) */ |
2308 | #if defined(TARGET_PPC64H) | 2311 | #if defined(TARGET_PPC64H) |