aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/kernel/cpu-probe.c
diff options
context:
space:
mode:
authorJames Hogan <james.hogan@imgtec.com>2016-05-11 10:50:30 -0400
committerRalf Baechle <ralf@linux-mips.org>2016-05-13 09:30:25 -0400
commit6ad816e77ed77538fe729050cf6631328c6113f7 (patch)
treef04c89b18b8a90d9abc9be6e181cb247c1335d63 /arch/mips/kernel/cpu-probe.c
parent7eb91118227d71132ca2da06a9b376ba656171d9 (diff)
MIPS: Add probing & defs for VZ & guest features
Add a few new cpu-features.h definitions for VZ sub-features, namely the existence of the CP0_GuestCtl0Ext, CP0_GuestCtl1, and CP0_GuestCtl2 registers, and support for GuestID to dialias TLB entries belonging to different guests. Also add certain features present in the guest, with the naming scheme cpu_guest_has_*. These are added separately to the main options bitfield since they generally parallel similar features in the root context. A few of these (FPU, MSA, watchpoints, perf counters, CP0_[X]ContextConfig registers, MAAR registers, and probably others in future) can be dynamically configured in the guest context, for which the cpu_guest_has_dyn_* macros are added. [ralf@linux-mips.org: Resolve merge conflict.] Signed-off-by: James Hogan <james.hogan@imgtec.com> Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/13231/ Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'arch/mips/kernel/cpu-probe.c')
-rw-r--r--arch/mips/kernel/cpu-probe.c232
1 files changed, 232 insertions, 0 deletions
diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c
index 31c27576a931..5ac5c3e23460 100644
--- a/arch/mips/kernel/cpu-probe.c
+++ b/arch/mips/kernel/cpu-probe.c
@@ -915,6 +915,235 @@ static void decode_configs(struct cpuinfo_mips *c)
915#endif 915#endif
916} 916}
917 917
918/*
919 * Probe for certain guest capabilities by writing config bits and reading back.
920 * Finally write back the original value.
921 */
922#define probe_gc0_config(name, maxconf, bits) \
923do { \
924 unsigned int tmp; \
925 tmp = read_gc0_##name(); \
926 write_gc0_##name(tmp | (bits)); \
927 back_to_back_c0_hazard(); \
928 maxconf = read_gc0_##name(); \
929 write_gc0_##name(tmp); \
930} while (0)
931
932/*
933 * Probe for dynamic guest capabilities by changing certain config bits and
934 * reading back to see if they change. Finally write back the original value.
935 */
936#define probe_gc0_config_dyn(name, maxconf, dynconf, bits) \
937do { \
938 maxconf = read_gc0_##name(); \
939 write_gc0_##name(maxconf ^ (bits)); \
940 back_to_back_c0_hazard(); \
941 dynconf = maxconf ^ read_gc0_##name(); \
942 write_gc0_##name(maxconf); \
943 maxconf |= dynconf; \
944} while (0)
945
946static inline unsigned int decode_guest_config0(struct cpuinfo_mips *c)
947{
948 unsigned int config0;
949
950 probe_gc0_config(config, config0, MIPS_CONF_M);
951
952 if (config0 & MIPS_CONF_M)
953 c->guest.conf |= BIT(1);
954 return config0 & MIPS_CONF_M;
955}
956
957static inline unsigned int decode_guest_config1(struct cpuinfo_mips *c)
958{
959 unsigned int config1, config1_dyn;
960
961 probe_gc0_config_dyn(config1, config1, config1_dyn,
962 MIPS_CONF_M | MIPS_CONF1_PC | MIPS_CONF1_WR |
963 MIPS_CONF1_FP);
964
965 if (config1 & MIPS_CONF1_FP)
966 c->guest.options |= MIPS_CPU_FPU;
967 if (config1_dyn & MIPS_CONF1_FP)
968 c->guest.options_dyn |= MIPS_CPU_FPU;
969
970 if (config1 & MIPS_CONF1_WR)
971 c->guest.options |= MIPS_CPU_WATCH;
972 if (config1_dyn & MIPS_CONF1_WR)
973 c->guest.options_dyn |= MIPS_CPU_WATCH;
974
975 if (config1 & MIPS_CONF1_PC)
976 c->guest.options |= MIPS_CPU_PERF;
977 if (config1_dyn & MIPS_CONF1_PC)
978 c->guest.options_dyn |= MIPS_CPU_PERF;
979
980 if (config1 & MIPS_CONF_M)
981 c->guest.conf |= BIT(2);
982 return config1 & MIPS_CONF_M;
983}
984
985static inline unsigned int decode_guest_config2(struct cpuinfo_mips *c)
986{
987 unsigned int config2;
988
989 probe_gc0_config(config2, config2, MIPS_CONF_M);
990
991 if (config2 & MIPS_CONF_M)
992 c->guest.conf |= BIT(3);
993 return config2 & MIPS_CONF_M;
994}
995
996static inline unsigned int decode_guest_config3(struct cpuinfo_mips *c)
997{
998 unsigned int config3, config3_dyn;
999
1000 probe_gc0_config_dyn(config3, config3, config3_dyn,
1001 MIPS_CONF_M | MIPS_CONF3_MSA | MIPS_CONF3_CTXTC);
1002
1003 if (config3 & MIPS_CONF3_CTXTC)
1004 c->guest.options |= MIPS_CPU_CTXTC;
1005 if (config3_dyn & MIPS_CONF3_CTXTC)
1006 c->guest.options_dyn |= MIPS_CPU_CTXTC;
1007
1008 if (config3 & MIPS_CONF3_PW)
1009 c->guest.options |= MIPS_CPU_HTW;
1010
1011 if (config3 & MIPS_CONF3_SC)
1012 c->guest.options |= MIPS_CPU_SEGMENTS;
1013
1014 if (config3 & MIPS_CONF3_BI)
1015 c->guest.options |= MIPS_CPU_BADINSTR;
1016 if (config3 & MIPS_CONF3_BP)
1017 c->guest.options |= MIPS_CPU_BADINSTRP;
1018
1019 if (config3 & MIPS_CONF3_MSA)
1020 c->guest.ases |= MIPS_ASE_MSA;
1021 if (config3_dyn & MIPS_CONF3_MSA)
1022 c->guest.ases_dyn |= MIPS_ASE_MSA;
1023
1024 if (config3 & MIPS_CONF_M)
1025 c->guest.conf |= BIT(4);
1026 return config3 & MIPS_CONF_M;
1027}
1028
1029static inline unsigned int decode_guest_config4(struct cpuinfo_mips *c)
1030{
1031 unsigned int config4;
1032
1033 probe_gc0_config(config4, config4,
1034 MIPS_CONF_M | MIPS_CONF4_KSCREXIST);
1035
1036 c->guest.kscratch_mask = (config4 & MIPS_CONF4_KSCREXIST)
1037 >> MIPS_CONF4_KSCREXIST_SHIFT;
1038
1039 if (config4 & MIPS_CONF_M)
1040 c->guest.conf |= BIT(5);
1041 return config4 & MIPS_CONF_M;
1042}
1043
1044static inline unsigned int decode_guest_config5(struct cpuinfo_mips *c)
1045{
1046 unsigned int config5, config5_dyn;
1047
1048 probe_gc0_config_dyn(config5, config5, config5_dyn,
1049 MIPS_CONF_M | MIPS_CONF5_MRP);
1050
1051 if (config5 & MIPS_CONF5_MRP)
1052 c->guest.options |= MIPS_CPU_MAAR;
1053 if (config5_dyn & MIPS_CONF5_MRP)
1054 c->guest.options_dyn |= MIPS_CPU_MAAR;
1055
1056 if (config5 & MIPS_CONF5_LLB)
1057 c->guest.options |= MIPS_CPU_RW_LLB;
1058
1059 if (config5 & MIPS_CONF_M)
1060 c->guest.conf |= BIT(6);
1061 return config5 & MIPS_CONF_M;
1062}
1063
1064static inline void decode_guest_configs(struct cpuinfo_mips *c)
1065{
1066 unsigned int ok;
1067
1068 ok = decode_guest_config0(c);
1069 if (ok)
1070 ok = decode_guest_config1(c);
1071 if (ok)
1072 ok = decode_guest_config2(c);
1073 if (ok)
1074 ok = decode_guest_config3(c);
1075 if (ok)
1076 ok = decode_guest_config4(c);
1077 if (ok)
1078 decode_guest_config5(c);
1079}
1080
1081static inline void cpu_probe_guestctl0(struct cpuinfo_mips *c)
1082{
1083 unsigned int guestctl0, temp;
1084
1085 guestctl0 = read_c0_guestctl0();
1086
1087 if (guestctl0 & MIPS_GCTL0_G0E)
1088 c->options |= MIPS_CPU_GUESTCTL0EXT;
1089 if (guestctl0 & MIPS_GCTL0_G1)
1090 c->options |= MIPS_CPU_GUESTCTL1;
1091 if (guestctl0 & MIPS_GCTL0_G2)
1092 c->options |= MIPS_CPU_GUESTCTL2;
1093 if (!(guestctl0 & MIPS_GCTL0_RAD)) {
1094 c->options |= MIPS_CPU_GUESTID;
1095
1096 /*
1097 * Probe for Direct Root to Guest (DRG). Set GuestCtl1.RID = 0
1098 * first, otherwise all data accesses will be fully virtualised
1099 * as if they were performed by guest mode.
1100 */
1101 write_c0_guestctl1(0);
1102 tlbw_use_hazard();
1103
1104 write_c0_guestctl0(guestctl0 | MIPS_GCTL0_DRG);
1105 back_to_back_c0_hazard();
1106 temp = read_c0_guestctl0();
1107
1108 if (temp & MIPS_GCTL0_DRG) {
1109 write_c0_guestctl0(guestctl0);
1110 c->options |= MIPS_CPU_DRG;
1111 }
1112 }
1113}
1114
1115static inline void cpu_probe_guestctl1(struct cpuinfo_mips *c)
1116{
1117 if (cpu_has_guestid) {
1118 /* determine the number of bits of GuestID available */
1119 write_c0_guestctl1(MIPS_GCTL1_ID);
1120 back_to_back_c0_hazard();
1121 c->guestid_mask = (read_c0_guestctl1() & MIPS_GCTL1_ID)
1122 >> MIPS_GCTL1_ID_SHIFT;
1123 write_c0_guestctl1(0);
1124 }
1125}
1126
1127static inline void cpu_probe_gtoffset(struct cpuinfo_mips *c)
1128{
1129 /* determine the number of bits of GTOffset available */
1130 write_c0_gtoffset(0xffffffff);
1131 back_to_back_c0_hazard();
1132 c->gtoffset_mask = read_c0_gtoffset();
1133 write_c0_gtoffset(0);
1134}
1135
1136static inline void cpu_probe_vz(struct cpuinfo_mips *c)
1137{
1138 cpu_probe_guestctl0(c);
1139 if (cpu_has_guestctl1)
1140 cpu_probe_guestctl1(c);
1141
1142 cpu_probe_gtoffset(c);
1143
1144 decode_guest_configs(c);
1145}
1146
918#define R4K_OPTS (MIPS_CPU_TLB | MIPS_CPU_4KEX | MIPS_CPU_4K_CACHE \ 1147#define R4K_OPTS (MIPS_CPU_TLB | MIPS_CPU_4KEX | MIPS_CPU_4K_CACHE \
919 | MIPS_CPU_COUNTER) 1148 | MIPS_CPU_COUNTER)
920 1149
@@ -1817,6 +2046,9 @@ void cpu_probe(void)
1817 elf_hwcap |= HWCAP_MIPS_MSA; 2046 elf_hwcap |= HWCAP_MIPS_MSA;
1818 } 2047 }
1819 2048
2049 if (cpu_has_vz)
2050 cpu_probe_vz(c);
2051
1820 cpu_probe_vmbits(c); 2052 cpu_probe_vmbits(c);
1821 2053
1822#ifdef CONFIG_64BIT 2054#ifdef CONFIG_64BIT