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.h136
1 files changed, 136 insertions, 0 deletions
diff --git a/include/asm-mips/mipsregs.h b/include/asm-mips/mipsregs.h
index 035ba0a9b0df..a2ef579f6b1a 100644
--- a/include/asm-mips/mipsregs.h
+++ b/include/asm-mips/mipsregs.h
@@ -836,6 +836,9 @@ do { \
836#define read_c0_cache() __read_32bit_c0_register($7, 0) /* TX39xx */ 836#define read_c0_cache() __read_32bit_c0_register($7, 0) /* TX39xx */
837#define write_c0_cache(val) __write_32bit_c0_register($7, 0, val) 837#define write_c0_cache(val) __write_32bit_c0_register($7, 0, val)
838 838
839#define read_c0_badvaddr() __read_ulong_c0_register($8, 0)
840#define write_c0_badvaddr(val) __write_ulong_c0_register($8, 0, val)
841
839#define read_c0_count() __read_32bit_c0_register($9, 0) 842#define read_c0_count() __read_32bit_c0_register($9, 0)
840#define write_c0_count(val) __write_32bit_c0_register($9, 0, val) 843#define write_c0_count(val) __write_32bit_c0_register($9, 0, val)
841 844
@@ -858,7 +861,19 @@ do { \
858#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)
859 862
860#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 */
861#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 */
862 877
863#define read_c0_cause() __read_32bit_c0_register($13, 0) 878#define read_c0_cause() __read_32bit_c0_register($13, 0)
864#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)
@@ -1001,6 +1016,9 @@ do { \
1001#define read_c0_taglo() __read_32bit_c0_register($28, 0) 1016#define read_c0_taglo() __read_32bit_c0_register($28, 0)
1002#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)
1003 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
1004#define read_c0_taghi() __read_32bit_c0_register($29, 0) 1022#define read_c0_taghi() __read_32bit_c0_register($29, 0)
1005#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)
1006 1024
@@ -1354,15 +1372,119 @@ static inline void tlb_write_random(void)
1354/* 1372/*
1355 * Manipulate bits in a c0 register. 1373 * Manipulate bits in a c0 register.
1356 */ 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 */
1380#define __BUILD_SET_C0(name) \
1381static inline unsigned int \
1382set_c0_##name(unsigned int set) \
1383{ \
1384 unsigned int res; \
1385 \
1386 res = read_c0_##name(); \
1387 res |= set; \
1388 write_c0_##name(res); \
1389 \
1390 return res; \
1391} \
1392 \
1393static inline unsigned int \
1394clear_c0_##name(unsigned int clear) \
1395{ \
1396 unsigned int res; \
1397 \
1398 res = read_c0_##name(); \
1399 res &= ~clear; \
1400 write_c0_##name(res); \
1401 \
1402 return res; \
1403} \
1404 \
1405static inline unsigned int \
1406change_c0_##name(unsigned int change, unsigned int new) \
1407{ \
1408 unsigned int res; \
1409 \
1410 res = read_c0_##name(); \
1411 res &= ~change; \
1412 res |= (new & change); \
1413 write_c0_##name(res); \
1414 \
1415 return res; \
1416}
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
1357#define __BUILD_SET_C0(name) \ 1473#define __BUILD_SET_C0(name) \
1358static inline unsigned int \ 1474static inline unsigned int \
1359set_c0_##name(unsigned int set) \ 1475set_c0_##name(unsigned int set) \
1360{ \ 1476{ \
1361 unsigned int res; \ 1477 unsigned int res; \
1478 unsigned int omt; \
1479 unsigned int flags; \
1362 \ 1480 \
1481 local_irq_save(flags); \
1482 omt = __dmt(); \
1363 res = read_c0_##name(); \ 1483 res = read_c0_##name(); \
1364 res |= set; \ 1484 res |= set; \
1365 write_c0_##name(res); \ 1485 write_c0_##name(res); \
1486 __emt(omt); \
1487 local_irq_restore(flags); \
1366 \ 1488 \
1367 return res; \ 1489 return res; \
1368} \ 1490} \
@@ -1371,10 +1493,16 @@ static inline unsigned int \
1371clear_c0_##name(unsigned int clear) \ 1493clear_c0_##name(unsigned int clear) \
1372{ \ 1494{ \
1373 unsigned int res; \ 1495 unsigned int res; \
1496 unsigned int omt; \
1497 unsigned int flags; \
1374 \ 1498 \
1499 local_irq_save(flags); \
1500 omt = __dmt(); \
1375 res = read_c0_##name(); \ 1501 res = read_c0_##name(); \
1376 res &= ~clear; \ 1502 res &= ~clear; \
1377 write_c0_##name(res); \ 1503 write_c0_##name(res); \
1504 __emt(omt); \
1505 local_irq_restore(flags); \
1378 \ 1506 \
1379 return res; \ 1507 return res; \
1380} \ 1508} \
@@ -1383,14 +1511,22 @@ static inline unsigned int \
1383change_c0_##name(unsigned int change, unsigned int new) \ 1511change_c0_##name(unsigned int change, unsigned int new) \
1384{ \ 1512{ \
1385 unsigned int res; \ 1513 unsigned int res; \
1514 unsigned int omt; \
1515 unsigned int flags; \
1386 \ 1516 \
1517 local_irq_save(flags); \
1518 \
1519 omt = __dmt(); \
1387 res = read_c0_##name(); \ 1520 res = read_c0_##name(); \
1388 res &= ~change; \ 1521 res &= ~change; \
1389 res |= (new & change); \ 1522 res |= (new & change); \
1390 write_c0_##name(res); \ 1523 write_c0_##name(res); \
1524 __emt(omt); \
1525 local_irq_restore(flags); \
1391 \ 1526 \
1392 return res; \ 1527 return res; \
1393} 1528}
1529#endif
1394 1530
1395__BUILD_SET_C0(status) 1531__BUILD_SET_C0(status)
1396__BUILD_SET_C0(cause) 1532__BUILD_SET_C0(cause)