aboutsummaryrefslogtreecommitdiffstats
path: root/include/asm-mips/mipsregs.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/asm-mips/mipsregs.h')
-rw-r--r--include/asm-mips/mipsregs.h133
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) \
866do { \
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) \
1361static inline unsigned int \ 1381static inline unsigned int \
1362set_c0_##name(unsigned int set) \ 1382set_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 */
1426static 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
1450static 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
1462static 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) \
1474static inline unsigned int \
1475set_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 \
1492static inline unsigned int \
1493clear_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 \
1510static inline unsigned int \
1511change_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)