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) |