diff options
Diffstat (limited to 'arch/parisc/kernel/entry.S')
| -rw-r--r-- | arch/parisc/kernel/entry.S | 230 |
1 files changed, 134 insertions, 96 deletions
diff --git a/arch/parisc/kernel/entry.S b/arch/parisc/kernel/entry.S index 6337adef30f6..6f0594439143 100644 --- a/arch/parisc/kernel/entry.S +++ b/arch/parisc/kernel/entry.S | |||
| @@ -187,8 +187,8 @@ | |||
| 187 | 187 | ||
| 188 | /* Register definitions for tlb miss handler macros */ | 188 | /* Register definitions for tlb miss handler macros */ |
| 189 | 189 | ||
| 190 | va = r8 /* virtual address for which the trap occured */ | 190 | va = r8 /* virtual address for which the trap occurred */ |
| 191 | spc = r24 /* space for which the trap occured */ | 191 | spc = r24 /* space for which the trap occurred */ |
| 192 | 192 | ||
| 193 | #ifndef CONFIG_64BIT | 193 | #ifndef CONFIG_64BIT |
| 194 | 194 | ||
| @@ -225,22 +225,13 @@ | |||
| 225 | #ifndef CONFIG_64BIT | 225 | #ifndef CONFIG_64BIT |
| 226 | /* | 226 | /* |
| 227 | * naitlb miss interruption handler (parisc 1.1 - 32 bit) | 227 | * naitlb miss interruption handler (parisc 1.1 - 32 bit) |
| 228 | * | ||
| 229 | * Note: naitlb misses will be treated | ||
| 230 | * as an ordinary itlb miss for now. | ||
| 231 | * However, note that naitlb misses | ||
| 232 | * have the faulting address in the | ||
| 233 | * IOR/ISR. | ||
| 234 | */ | 228 | */ |
| 235 | 229 | ||
| 236 | .macro naitlb_11 code | 230 | .macro naitlb_11 code |
| 237 | 231 | ||
| 238 | mfctl %isr,spc | 232 | mfctl %isr,spc |
| 239 | b itlb_miss_11 | 233 | b naitlb_miss_11 |
| 240 | mfctl %ior,va | 234 | mfctl %ior,va |
| 241 | /* FIXME: If user causes a naitlb miss, the priv level may not be in | ||
| 242 | * lower bits of va, where the itlb miss handler is expecting them | ||
| 243 | */ | ||
| 244 | 235 | ||
| 245 | .align 32 | 236 | .align 32 |
| 246 | .endm | 237 | .endm |
| @@ -248,26 +239,17 @@ | |||
| 248 | 239 | ||
| 249 | /* | 240 | /* |
| 250 | * naitlb miss interruption handler (parisc 2.0) | 241 | * naitlb miss interruption handler (parisc 2.0) |
| 251 | * | ||
| 252 | * Note: naitlb misses will be treated | ||
| 253 | * as an ordinary itlb miss for now. | ||
| 254 | * However, note that naitlb misses | ||
| 255 | * have the faulting address in the | ||
| 256 | * IOR/ISR. | ||
| 257 | */ | 242 | */ |
| 258 | 243 | ||
| 259 | .macro naitlb_20 code | 244 | .macro naitlb_20 code |
| 260 | 245 | ||
| 261 | mfctl %isr,spc | 246 | mfctl %isr,spc |
| 262 | #ifdef CONFIG_64BIT | 247 | #ifdef CONFIG_64BIT |
| 263 | b itlb_miss_20w | 248 | b naitlb_miss_20w |
| 264 | #else | 249 | #else |
| 265 | b itlb_miss_20 | 250 | b naitlb_miss_20 |
| 266 | #endif | 251 | #endif |
| 267 | mfctl %ior,va | 252 | mfctl %ior,va |
| 268 | /* FIXME: If user causes a naitlb miss, the priv level may not be in | ||
| 269 | * lower bits of va, where the itlb miss handler is expecting them | ||
| 270 | */ | ||
| 271 | 253 | ||
| 272 | .align 32 | 254 | .align 32 |
| 273 | .endm | 255 | .endm |
| @@ -581,7 +563,24 @@ | |||
| 581 | copy \va,\tmp1 | 563 | copy \va,\tmp1 |
| 582 | depi 0,31,23,\tmp1 | 564 | depi 0,31,23,\tmp1 |
| 583 | cmpb,COND(<>),n \tmp,\tmp1,\fault | 565 | cmpb,COND(<>),n \tmp,\tmp1,\fault |
| 584 | ldi (_PAGE_DIRTY|_PAGE_WRITE|_PAGE_READ),\prot | 566 | mfctl %cr19,\tmp /* iir */ |
| 567 | /* get the opcode (first six bits) into \tmp */ | ||
| 568 | extrw,u \tmp,5,6,\tmp | ||
| 569 | /* | ||
| 570 | * Only setting the T bit prevents data cache movein | ||
| 571 | * Setting access rights to zero prevents instruction cache movein | ||
| 572 | * | ||
| 573 | * Note subtlety here: _PAGE_GATEWAY, _PAGE_EXEC and _PAGE_WRITE go | ||
| 574 | * to type field and _PAGE_READ goes to top bit of PL1 | ||
| 575 | */ | ||
| 576 | ldi (_PAGE_REFTRAP|_PAGE_READ|_PAGE_WRITE),\prot | ||
| 577 | /* | ||
| 578 | * so if the opcode is one (i.e. this is a memory management | ||
| 579 | * instruction) nullify the next load so \prot is only T. | ||
| 580 | * Otherwise this is a normal data operation | ||
| 581 | */ | ||
| 582 | cmpiclr,= 0x01,\tmp,%r0 | ||
| 583 | ldi (_PAGE_DIRTY|_PAGE_READ|_PAGE_WRITE),\prot | ||
| 585 | depd,z \prot,8,7,\prot | 584 | depd,z \prot,8,7,\prot |
| 586 | /* | 585 | /* |
| 587 | * OK, it is in the temp alias region, check whether "from" or "to". | 586 | * OK, it is in the temp alias region, check whether "from" or "to". |
| @@ -631,11 +630,7 @@ ENTRY(fault_vector_20) | |||
| 631 | def 13 | 630 | def 13 |
| 632 | def 14 | 631 | def 14 |
| 633 | dtlb_20 15 | 632 | dtlb_20 15 |
| 634 | #if 0 | ||
| 635 | naitlb_20 16 | 633 | naitlb_20 16 |
| 636 | #else | ||
| 637 | def 16 | ||
| 638 | #endif | ||
| 639 | nadtlb_20 17 | 634 | nadtlb_20 17 |
| 640 | def 18 | 635 | def 18 |
| 641 | def 19 | 636 | def 19 |
| @@ -678,11 +673,7 @@ ENTRY(fault_vector_11) | |||
| 678 | def 13 | 673 | def 13 |
| 679 | def 14 | 674 | def 14 |
| 680 | dtlb_11 15 | 675 | dtlb_11 15 |
| 681 | #if 0 | ||
| 682 | naitlb_11 16 | 676 | naitlb_11 16 |
| 683 | #else | ||
| 684 | def 16 | ||
| 685 | #endif | ||
| 686 | nadtlb_11 17 | 677 | nadtlb_11 17 |
| 687 | def 18 | 678 | def 18 |
| 688 | def 19 | 679 | def 19 |
| @@ -701,6 +692,9 @@ ENTRY(fault_vector_11) | |||
| 701 | END(fault_vector_11) | 692 | END(fault_vector_11) |
| 702 | 693 | ||
| 703 | #endif | 694 | #endif |
| 695 | /* Fault vector is separately protected and *must* be on its own page */ | ||
| 696 | .align PAGE_SIZE | ||
| 697 | ENTRY(end_fault_vector) | ||
| 704 | 698 | ||
| 705 | .import handle_interruption,code | 699 | .import handle_interruption,code |
| 706 | .import do_cpu_irq_mask,code | 700 | .import do_cpu_irq_mask,code |
| @@ -891,7 +885,7 @@ ENTRY(syscall_exit_rfi) | |||
| 891 | * (we don't store them in the sigcontext), so set them | 885 | * (we don't store them in the sigcontext), so set them |
| 892 | * to "proper" values now (otherwise we'll wind up restoring | 886 | * to "proper" values now (otherwise we'll wind up restoring |
| 893 | * whatever was last stored in the task structure, which might | 887 | * whatever was last stored in the task structure, which might |
| 894 | * be inconsistent if an interrupt occured while on the gateway | 888 | * be inconsistent if an interrupt occurred while on the gateway |
| 895 | * page). Note that we may be "trashing" values the user put in | 889 | * page). Note that we may be "trashing" values the user put in |
| 896 | * them, but we don't support the user changing them. | 890 | * them, but we don't support the user changing them. |
| 897 | */ | 891 | */ |
| @@ -1165,11 +1159,11 @@ ENDPROC(intr_save) | |||
| 1165 | */ | 1159 | */ |
| 1166 | 1160 | ||
| 1167 | t0 = r1 /* temporary register 0 */ | 1161 | t0 = r1 /* temporary register 0 */ |
| 1168 | va = r8 /* virtual address for which the trap occured */ | 1162 | va = r8 /* virtual address for which the trap occurred */ |
| 1169 | t1 = r9 /* temporary register 1 */ | 1163 | t1 = r9 /* temporary register 1 */ |
| 1170 | pte = r16 /* pte/phys page # */ | 1164 | pte = r16 /* pte/phys page # */ |
| 1171 | prot = r17 /* prot bits */ | 1165 | prot = r17 /* prot bits */ |
| 1172 | spc = r24 /* space for which the trap occured */ | 1166 | spc = r24 /* space for which the trap occurred */ |
| 1173 | ptp = r25 /* page directory/page table pointer */ | 1167 | ptp = r25 /* page directory/page table pointer */ |
| 1174 | 1168 | ||
| 1175 | #ifdef CONFIG_64BIT | 1169 | #ifdef CONFIG_64BIT |
| @@ -1203,7 +1197,7 @@ nadtlb_miss_20w: | |||
| 1203 | get_pgd spc,ptp | 1197 | get_pgd spc,ptp |
| 1204 | space_check spc,t0,nadtlb_fault | 1198 | space_check spc,t0,nadtlb_fault |
| 1205 | 1199 | ||
| 1206 | L3_ptep ptp,pte,t0,va,nadtlb_check_flush_20w | 1200 | L3_ptep ptp,pte,t0,va,nadtlb_check_alias_20w |
| 1207 | 1201 | ||
| 1208 | update_ptep ptp,pte,t0,t1 | 1202 | update_ptep ptp,pte,t0,t1 |
| 1209 | 1203 | ||
| @@ -1214,16 +1208,8 @@ nadtlb_miss_20w: | |||
| 1214 | rfir | 1208 | rfir |
| 1215 | nop | 1209 | nop |
| 1216 | 1210 | ||
| 1217 | nadtlb_check_flush_20w: | 1211 | nadtlb_check_alias_20w: |
| 1218 | bb,>=,n pte,_PAGE_FLUSH_BIT,nadtlb_emulate | 1212 | do_alias spc,t0,t1,va,pte,prot,nadtlb_emulate |
| 1219 | |||
| 1220 | /* Insert a "flush only" translation */ | ||
| 1221 | |||
| 1222 | depdi,z 7,7,3,prot | ||
| 1223 | depdi 1,10,1,prot | ||
| 1224 | |||
| 1225 | /* Drop prot bits from pte and convert to page addr for idtlbt */ | ||
| 1226 | convert_for_tlb_insert20 pte | ||
| 1227 | 1213 | ||
| 1228 | idtlbt pte,prot | 1214 | idtlbt pte,prot |
| 1229 | 1215 | ||
| @@ -1255,25 +1241,7 @@ dtlb_miss_11: | |||
| 1255 | nop | 1241 | nop |
| 1256 | 1242 | ||
| 1257 | dtlb_check_alias_11: | 1243 | dtlb_check_alias_11: |
| 1258 | 1244 | do_alias spc,t0,t1,va,pte,prot,dtlb_fault | |
| 1259 | /* Check to see if fault is in the temporary alias region */ | ||
| 1260 | |||
| 1261 | cmpib,<>,n 0,spc,dtlb_fault /* forward */ | ||
| 1262 | ldil L%(TMPALIAS_MAP_START),t0 | ||
| 1263 | copy va,t1 | ||
| 1264 | depwi 0,31,23,t1 | ||
| 1265 | cmpb,<>,n t0,t1,dtlb_fault /* forward */ | ||
| 1266 | ldi (_PAGE_DIRTY|_PAGE_WRITE|_PAGE_READ),prot | ||
| 1267 | depw,z prot,8,7,prot | ||
| 1268 | |||
| 1269 | /* | ||
| 1270 | * OK, it is in the temp alias region, check whether "from" or "to". | ||
| 1271 | * Check "subtle" note in pacache.S re: r23/r26. | ||
| 1272 | */ | ||
| 1273 | |||
| 1274 | extrw,u,= va,9,1,r0 | ||
| 1275 | or,tr %r23,%r0,pte /* If "from" use "from" page */ | ||
| 1276 | or %r26,%r0,pte /* else "to", use "to" page */ | ||
| 1277 | 1245 | ||
| 1278 | idtlba pte,(va) | 1246 | idtlba pte,(va) |
| 1279 | idtlbp prot,(va) | 1247 | idtlbp prot,(va) |
| @@ -1286,7 +1254,7 @@ nadtlb_miss_11: | |||
| 1286 | 1254 | ||
| 1287 | space_check spc,t0,nadtlb_fault | 1255 | space_check spc,t0,nadtlb_fault |
| 1288 | 1256 | ||
| 1289 | L2_ptep ptp,pte,t0,va,nadtlb_check_flush_11 | 1257 | L2_ptep ptp,pte,t0,va,nadtlb_check_alias_11 |
| 1290 | 1258 | ||
| 1291 | update_ptep ptp,pte,t0,t1 | 1259 | update_ptep ptp,pte,t0,t1 |
| 1292 | 1260 | ||
| @@ -1304,26 +1272,11 @@ nadtlb_miss_11: | |||
| 1304 | rfir | 1272 | rfir |
| 1305 | nop | 1273 | nop |
| 1306 | 1274 | ||
| 1307 | nadtlb_check_flush_11: | 1275 | nadtlb_check_alias_11: |
| 1308 | bb,>=,n pte,_PAGE_FLUSH_BIT,nadtlb_emulate | 1276 | do_alias spc,t0,t1,va,pte,prot,nadtlb_emulate |
| 1309 | |||
| 1310 | /* Insert a "flush only" translation */ | ||
| 1311 | |||
| 1312 | zdepi 7,7,3,prot | ||
| 1313 | depi 1,10,1,prot | ||
| 1314 | 1277 | ||
| 1315 | /* Get rid of prot bits and convert to page addr for idtlba */ | 1278 | idtlba pte,(va) |
| 1316 | 1279 | idtlbp prot,(va) | |
| 1317 | depi 0,31,ASM_PFN_PTE_SHIFT,pte | ||
| 1318 | SHRREG pte,(ASM_PFN_PTE_SHIFT-(31-26)),pte | ||
| 1319 | |||
| 1320 | mfsp %sr1,t0 /* Save sr1 so we can use it in tlb inserts */ | ||
| 1321 | mtsp spc,%sr1 | ||
| 1322 | |||
| 1323 | idtlba pte,(%sr1,va) | ||
| 1324 | idtlbp prot,(%sr1,va) | ||
| 1325 | |||
| 1326 | mtsp t0, %sr1 /* Restore sr1 */ | ||
| 1327 | 1280 | ||
| 1328 | rfir | 1281 | rfir |
| 1329 | nop | 1282 | nop |
| @@ -1359,7 +1312,7 @@ nadtlb_miss_20: | |||
| 1359 | 1312 | ||
| 1360 | space_check spc,t0,nadtlb_fault | 1313 | space_check spc,t0,nadtlb_fault |
| 1361 | 1314 | ||
| 1362 | L2_ptep ptp,pte,t0,va,nadtlb_check_flush_20 | 1315 | L2_ptep ptp,pte,t0,va,nadtlb_check_alias_20 |
| 1363 | 1316 | ||
| 1364 | update_ptep ptp,pte,t0,t1 | 1317 | update_ptep ptp,pte,t0,t1 |
| 1365 | 1318 | ||
| @@ -1372,21 +1325,14 @@ nadtlb_miss_20: | |||
| 1372 | rfir | 1325 | rfir |
| 1373 | nop | 1326 | nop |
| 1374 | 1327 | ||
| 1375 | nadtlb_check_flush_20: | 1328 | nadtlb_check_alias_20: |
| 1376 | bb,>=,n pte,_PAGE_FLUSH_BIT,nadtlb_emulate | 1329 | do_alias spc,t0,t1,va,pte,prot,nadtlb_emulate |
| 1377 | |||
| 1378 | /* Insert a "flush only" translation */ | ||
| 1379 | |||
| 1380 | depdi,z 7,7,3,prot | ||
| 1381 | depdi 1,10,1,prot | ||
| 1382 | |||
| 1383 | /* Drop prot bits from pte and convert to page addr for idtlbt */ | ||
| 1384 | convert_for_tlb_insert20 pte | ||
| 1385 | 1330 | ||
| 1386 | idtlbt pte,prot | 1331 | idtlbt pte,prot |
| 1387 | 1332 | ||
| 1388 | rfir | 1333 | rfir |
| 1389 | nop | 1334 | nop |
| 1335 | |||
| 1390 | #endif | 1336 | #endif |
| 1391 | 1337 | ||
| 1392 | nadtlb_emulate: | 1338 | nadtlb_emulate: |
| @@ -1484,6 +1430,36 @@ itlb_miss_20w: | |||
| 1484 | rfir | 1430 | rfir |
| 1485 | nop | 1431 | nop |
| 1486 | 1432 | ||
| 1433 | naitlb_miss_20w: | ||
| 1434 | |||
| 1435 | /* | ||
| 1436 | * I miss is a little different, since we allow users to fault | ||
| 1437 | * on the gateway page which is in the kernel address space. | ||
| 1438 | */ | ||
| 1439 | |||
| 1440 | space_adjust spc,va,t0 | ||
| 1441 | get_pgd spc,ptp | ||
| 1442 | space_check spc,t0,naitlb_fault | ||
| 1443 | |||
| 1444 | L3_ptep ptp,pte,t0,va,naitlb_check_alias_20w | ||
| 1445 | |||
| 1446 | update_ptep ptp,pte,t0,t1 | ||
| 1447 | |||
| 1448 | make_insert_tlb spc,pte,prot | ||
| 1449 | |||
| 1450 | iitlbt pte,prot | ||
| 1451 | |||
| 1452 | rfir | ||
| 1453 | nop | ||
| 1454 | |||
| 1455 | naitlb_check_alias_20w: | ||
| 1456 | do_alias spc,t0,t1,va,pte,prot,naitlb_fault | ||
| 1457 | |||
| 1458 | iitlbt pte,prot | ||
| 1459 | |||
| 1460 | rfir | ||
| 1461 | nop | ||
| 1462 | |||
| 1487 | #else | 1463 | #else |
| 1488 | 1464 | ||
| 1489 | itlb_miss_11: | 1465 | itlb_miss_11: |
| @@ -1508,6 +1484,38 @@ itlb_miss_11: | |||
| 1508 | rfir | 1484 | rfir |
| 1509 | nop | 1485 | nop |
| 1510 | 1486 | ||
| 1487 | naitlb_miss_11: | ||
| 1488 | get_pgd spc,ptp | ||
| 1489 | |||
| 1490 | space_check spc,t0,naitlb_fault | ||
| 1491 | |||
| 1492 | L2_ptep ptp,pte,t0,va,naitlb_check_alias_11 | ||
| 1493 | |||
| 1494 | update_ptep ptp,pte,t0,t1 | ||
| 1495 | |||
| 1496 | make_insert_tlb_11 spc,pte,prot | ||
| 1497 | |||
| 1498 | mfsp %sr1,t0 /* Save sr1 so we can use it in tlb inserts */ | ||
| 1499 | mtsp spc,%sr1 | ||
| 1500 | |||
| 1501 | iitlba pte,(%sr1,va) | ||
| 1502 | iitlbp prot,(%sr1,va) | ||
| 1503 | |||
| 1504 | mtsp t0, %sr1 /* Restore sr1 */ | ||
| 1505 | |||
| 1506 | rfir | ||
| 1507 | nop | ||
| 1508 | |||
| 1509 | naitlb_check_alias_11: | ||
| 1510 | do_alias spc,t0,t1,va,pte,prot,itlb_fault | ||
| 1511 | |||
| 1512 | iitlba pte,(%sr0, va) | ||
| 1513 | iitlbp prot,(%sr0, va) | ||
| 1514 | |||
| 1515 | rfir | ||
| 1516 | nop | ||
| 1517 | |||
| 1518 | |||
| 1511 | itlb_miss_20: | 1519 | itlb_miss_20: |
| 1512 | get_pgd spc,ptp | 1520 | get_pgd spc,ptp |
| 1513 | 1521 | ||
| @@ -1526,6 +1534,32 @@ itlb_miss_20: | |||
| 1526 | rfir | 1534 | rfir |
| 1527 | nop | 1535 | nop |
| 1528 | 1536 | ||
| 1537 | naitlb_miss_20: | ||
| 1538 | get_pgd spc,ptp | ||
| 1539 | |||
| 1540 | space_check spc,t0,naitlb_fault | ||
| 1541 | |||
| 1542 | L2_ptep ptp,pte,t0,va,naitlb_check_alias_20 | ||
| 1543 | |||
| 1544 | update_ptep ptp,pte,t0,t1 | ||
| 1545 | |||
| 1546 | make_insert_tlb spc,pte,prot | ||
| 1547 | |||
| 1548 | f_extend pte,t0 | ||
| 1549 | |||
| 1550 | iitlbt pte,prot | ||
| 1551 | |||
| 1552 | rfir | ||
| 1553 | nop | ||
| 1554 | |||
| 1555 | naitlb_check_alias_20: | ||
| 1556 | do_alias spc,t0,t1,va,pte,prot,naitlb_fault | ||
| 1557 | |||
| 1558 | iitlbt pte,prot | ||
| 1559 | |||
| 1560 | rfir | ||
| 1561 | nop | ||
| 1562 | |||
| 1529 | #endif | 1563 | #endif |
| 1530 | 1564 | ||
| 1531 | #ifdef CONFIG_64BIT | 1565 | #ifdef CONFIG_64BIT |
| @@ -1662,6 +1696,10 @@ nadtlb_fault: | |||
| 1662 | b intr_save | 1696 | b intr_save |
| 1663 | ldi 17,%r8 | 1697 | ldi 17,%r8 |
| 1664 | 1698 | ||
| 1699 | naitlb_fault: | ||
| 1700 | b intr_save | ||
| 1701 | ldi 16,%r8 | ||
| 1702 | |||
| 1665 | dtlb_fault: | 1703 | dtlb_fault: |
| 1666 | b intr_save | 1704 | b intr_save |
| 1667 | ldi 15,%r8 | 1705 | ldi 15,%r8 |
