diff options
Diffstat (limited to 'include/asm-mips/mipsregs.h')
| -rw-r--r-- | include/asm-mips/mipsregs.h | 133 |
1 files changed, 133 insertions, 0 deletions
diff --git a/include/asm-mips/mipsregs.h b/include/asm-mips/mipsregs.h index e85a42e2ea0c..a2ef579f6b1a 100644 --- a/include/asm-mips/mipsregs.h +++ b/include/asm-mips/mipsregs.h | |||
| @@ -861,7 +861,19 @@ do { \ | |||
| 861 | #define write_c0_compare3(val) __write_32bit_c0_register($11, 7, val) | 861 | #define write_c0_compare3(val) __write_32bit_c0_register($11, 7, val) |
| 862 | 862 | ||
| 863 | #define read_c0_status() __read_32bit_c0_register($12, 0) | 863 | #define read_c0_status() __read_32bit_c0_register($12, 0) |
| 864 | #ifdef CONFIG_MIPS_MT_SMTC | ||
| 865 | #define write_c0_status(val) \ | ||
| 866 | do { \ | ||
| 867 | __write_32bit_c0_register($12, 0, val); \ | ||
| 868 | __ehb(); \ | ||
| 869 | } while (0) | ||
| 870 | #else | ||
| 871 | /* | ||
| 872 | * Legacy non-SMTC code, which may be hazardous | ||
| 873 | * but which might not support EHB | ||
| 874 | */ | ||
| 864 | #define write_c0_status(val) __write_32bit_c0_register($12, 0, val) | 875 | #define write_c0_status(val) __write_32bit_c0_register($12, 0, val) |
| 876 | #endif /* CONFIG_MIPS_MT_SMTC */ | ||
| 865 | 877 | ||
| 866 | #define read_c0_cause() __read_32bit_c0_register($13, 0) | 878 | #define read_c0_cause() __read_32bit_c0_register($13, 0) |
| 867 | #define write_c0_cause(val) __write_32bit_c0_register($13, 0, val) | 879 | #define write_c0_cause(val) __write_32bit_c0_register($13, 0, val) |
| @@ -1004,6 +1016,9 @@ do { \ | |||
| 1004 | #define read_c0_taglo() __read_32bit_c0_register($28, 0) | 1016 | #define read_c0_taglo() __read_32bit_c0_register($28, 0) |
| 1005 | #define write_c0_taglo(val) __write_32bit_c0_register($28, 0, val) | 1017 | #define write_c0_taglo(val) __write_32bit_c0_register($28, 0, val) |
| 1006 | 1018 | ||
| 1019 | #define read_c0_dtaglo() __read_32bit_c0_register($28, 2) | ||
| 1020 | #define write_c0_dtaglo(val) __write_32bit_c0_register($28, 2, val) | ||
| 1021 | |||
| 1007 | #define read_c0_taghi() __read_32bit_c0_register($29, 0) | 1022 | #define read_c0_taghi() __read_32bit_c0_register($29, 0) |
| 1008 | #define write_c0_taghi(val) __write_32bit_c0_register($29, 0, val) | 1023 | #define write_c0_taghi(val) __write_32bit_c0_register($29, 0, val) |
| 1009 | 1024 | ||
| @@ -1357,6 +1372,11 @@ static inline void tlb_write_random(void) | |||
| 1357 | /* | 1372 | /* |
| 1358 | * Manipulate bits in a c0 register. | 1373 | * Manipulate bits in a c0 register. |
| 1359 | */ | 1374 | */ |
| 1375 | #ifndef CONFIG_MIPS_MT_SMTC | ||
| 1376 | /* | ||
| 1377 | * SMTC Linux requires shutting-down microthread scheduling | ||
| 1378 | * during CP0 register read-modify-write sequences. | ||
| 1379 | */ | ||
| 1360 | #define __BUILD_SET_C0(name) \ | 1380 | #define __BUILD_SET_C0(name) \ |
| 1361 | static inline unsigned int \ | 1381 | static inline unsigned int \ |
| 1362 | set_c0_##name(unsigned int set) \ | 1382 | set_c0_##name(unsigned int set) \ |
| @@ -1395,6 +1415,119 @@ change_c0_##name(unsigned int change, unsigned int new) \ | |||
| 1395 | return res; \ | 1415 | return res; \ |
| 1396 | } | 1416 | } |
| 1397 | 1417 | ||
| 1418 | #else /* SMTC versions that manage MT scheduling */ | ||
| 1419 | |||
| 1420 | #include <asm/interrupt.h> | ||
| 1421 | |||
| 1422 | /* | ||
| 1423 | * This is a duplicate of dmt() in mipsmtregs.h to avoid problems with | ||
| 1424 | * header file recursion. | ||
| 1425 | */ | ||
| 1426 | static inline unsigned int __dmt(void) | ||
| 1427 | { | ||
| 1428 | int res; | ||
| 1429 | |||
| 1430 | __asm__ __volatile__( | ||
| 1431 | " .set push \n" | ||
| 1432 | " .set mips32r2 \n" | ||
| 1433 | " .set noat \n" | ||
| 1434 | " .word 0x41610BC1 # dmt $1 \n" | ||
| 1435 | " ehb \n" | ||
| 1436 | " move %0, $1 \n" | ||
| 1437 | " .set pop \n" | ||
| 1438 | : "=r" (res)); | ||
| 1439 | |||
| 1440 | instruction_hazard(); | ||
| 1441 | |||
| 1442 | return res; | ||
| 1443 | } | ||
| 1444 | |||
| 1445 | #define __VPECONTROL_TE_SHIFT 15 | ||
| 1446 | #define __VPECONTROL_TE (1UL << __VPECONTROL_TE_SHIFT) | ||
| 1447 | |||
| 1448 | #define __EMT_ENABLE __VPECONTROL_TE | ||
| 1449 | |||
| 1450 | static inline void __emt(unsigned int previous) | ||
| 1451 | { | ||
| 1452 | if ((previous & __EMT_ENABLE)) | ||
| 1453 | __asm__ __volatile__( | ||
| 1454 | " .set noreorder \n" | ||
| 1455 | " .set mips32r2 \n" | ||
| 1456 | " .word 0x41600be1 # emt \n" | ||
| 1457 | " ehb \n" | ||
| 1458 | " .set mips0 \n" | ||
| 1459 | " .set reorder \n"); | ||
| 1460 | } | ||
| 1461 | |||
| 1462 | static inline void __ehb(void) | ||
| 1463 | { | ||
| 1464 | __asm__ __volatile__( | ||
| 1465 | " ehb \n"); | ||
| 1466 | } | ||
| 1467 | |||
| 1468 | /* | ||
| 1469 | * Note that local_irq_save/restore affect TC-specific IXMT state, | ||
| 1470 | * not Status.IE as in non-SMTC kernel. | ||
| 1471 | */ | ||
| 1472 | |||
| 1473 | #define __BUILD_SET_C0(name) \ | ||
| 1474 | static inline unsigned int \ | ||
| 1475 | set_c0_##name(unsigned int set) \ | ||
| 1476 | { \ | ||
| 1477 | unsigned int res; \ | ||
| 1478 | unsigned int omt; \ | ||
| 1479 | unsigned int flags; \ | ||
| 1480 | \ | ||
| 1481 | local_irq_save(flags); \ | ||
| 1482 | omt = __dmt(); \ | ||
| 1483 | res = read_c0_##name(); \ | ||
| 1484 | res |= set; \ | ||
| 1485 | write_c0_##name(res); \ | ||
| 1486 | __emt(omt); \ | ||
| 1487 | local_irq_restore(flags); \ | ||
| 1488 | \ | ||
| 1489 | return res; \ | ||
| 1490 | } \ | ||
| 1491 | \ | ||
| 1492 | static inline unsigned int \ | ||
| 1493 | clear_c0_##name(unsigned int clear) \ | ||
| 1494 | { \ | ||
| 1495 | unsigned int res; \ | ||
| 1496 | unsigned int omt; \ | ||
| 1497 | unsigned int flags; \ | ||
| 1498 | \ | ||
| 1499 | local_irq_save(flags); \ | ||
| 1500 | omt = __dmt(); \ | ||
| 1501 | res = read_c0_##name(); \ | ||
| 1502 | res &= ~clear; \ | ||
| 1503 | write_c0_##name(res); \ | ||
| 1504 | __emt(omt); \ | ||
| 1505 | local_irq_restore(flags); \ | ||
| 1506 | \ | ||
| 1507 | return res; \ | ||
| 1508 | } \ | ||
| 1509 | \ | ||
| 1510 | static inline unsigned int \ | ||
| 1511 | change_c0_##name(unsigned int change, unsigned int new) \ | ||
| 1512 | { \ | ||
| 1513 | unsigned int res; \ | ||
| 1514 | unsigned int omt; \ | ||
| 1515 | unsigned int flags; \ | ||
| 1516 | \ | ||
| 1517 | local_irq_save(flags); \ | ||
| 1518 | \ | ||
| 1519 | omt = __dmt(); \ | ||
| 1520 | res = read_c0_##name(); \ | ||
| 1521 | res &= ~change; \ | ||
| 1522 | res |= (new & change); \ | ||
| 1523 | write_c0_##name(res); \ | ||
| 1524 | __emt(omt); \ | ||
| 1525 | local_irq_restore(flags); \ | ||
| 1526 | \ | ||
| 1527 | return res; \ | ||
| 1528 | } | ||
| 1529 | #endif | ||
| 1530 | |||
| 1398 | __BUILD_SET_C0(status) | 1531 | __BUILD_SET_C0(status) |
| 1399 | __BUILD_SET_C0(cause) | 1532 | __BUILD_SET_C0(cause) |
| 1400 | __BUILD_SET_C0(config) | 1533 | __BUILD_SET_C0(config) |
