aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/kvm
diff options
context:
space:
mode:
authorJames Hogan <james.hogan@imgtec.com>2017-03-14 06:15:34 -0400
committerJames Hogan <james.hogan@imgtec.com>2017-03-28 09:53:56 -0400
commitdffe042fd8b2cc174966b929b379503af2c97933 (patch)
tree42b0f80e8b9d341cf34b72c0ddcf91101964bfd1 /arch/mips/kvm
parentedc89260d474fd044e77b7039bd2a697dddcac6c (diff)
KVM: MIPS/VZ: Support guest CP0_[X]ContextConfig
Add support for VZ guest CP0_ContextConfig and CP0_XContextConfig (MIPS64 only) registers, as found on P5600 and P6600 cores. These guest registers need initialising, context switching, and exposing via the KVM ioctl API when they are present. Signed-off-by: James Hogan <james.hogan@imgtec.com> Cc: Paolo Bonzini <pbonzini@redhat.com> Cc: "Radim Krčmář" <rkrcmar@redhat.com> Cc: Ralf Baechle <ralf@linux-mips.org> Cc: Jonathan Corbet <corbet@lwn.net> Cc: linux-mips@linux-mips.org Cc: kvm@vger.kernel.org Cc: linux-doc@vger.kernel.org
Diffstat (limited to 'arch/mips/kvm')
-rw-r--r--arch/mips/kvm/vz.c62
1 files changed, 60 insertions, 2 deletions
diff --git a/arch/mips/kvm/vz.c b/arch/mips/kvm/vz.c
index ec909fcd08ce..97e7a788bf4a 100644
--- a/arch/mips/kvm/vz.c
+++ b/arch/mips/kvm/vz.c
@@ -131,7 +131,7 @@ static inline unsigned int kvm_vz_config5_guest_wrmask(struct kvm_vcpu *vcpu)
131 * Config: M, [MT] 131 * Config: M, [MT]
132 * Config1: M, [MMUSize-1, C2, MD, PC, WR, CA], FP 132 * Config1: M, [MMUSize-1, C2, MD, PC, WR, CA], FP
133 * Config2: M 133 * Config2: M
134 * Config3: M, MSAP, [BPG], ULRI, [DSP2P, DSPP, CTXTC, ITL, LPA, VEIC, 134 * Config3: M, MSAP, [BPG], ULRI, [DSP2P, DSPP], CTXTC, [ITL, LPA, VEIC,
135 * VInt, SP, CDMM, MT, SM, TL] 135 * VInt, SP, CDMM, MT, SM, TL]
136 * Config4: M, [VTLBSizeExt, MMUSizeExt] 136 * Config4: M, [VTLBSizeExt, MMUSizeExt]
137 * Config5: [MRP] 137 * Config5: [MRP]
@@ -161,7 +161,7 @@ static inline unsigned int kvm_vz_config2_user_wrmask(struct kvm_vcpu *vcpu)
161static inline unsigned int kvm_vz_config3_user_wrmask(struct kvm_vcpu *vcpu) 161static inline unsigned int kvm_vz_config3_user_wrmask(struct kvm_vcpu *vcpu)
162{ 162{
163 unsigned int mask = kvm_vz_config3_guest_wrmask(vcpu) | MIPS_CONF_M | 163 unsigned int mask = kvm_vz_config3_guest_wrmask(vcpu) | MIPS_CONF_M |
164 MIPS_CONF3_ULRI; 164 MIPS_CONF3_ULRI | MIPS_CONF3_CTXTC;
165 165
166 /* Permit MSA to be present if MSA is supported */ 166 /* Permit MSA to be present if MSA is supported */
167 if (kvm_mips_guest_can_have_msa(&vcpu->arch)) 167 if (kvm_mips_guest_can_have_msa(&vcpu->arch))
@@ -1205,6 +1205,13 @@ static u64 kvm_vz_get_one_regs[] = {
1205 KVM_REG_MIPS_COUNT_HZ, 1205 KVM_REG_MIPS_COUNT_HZ,
1206}; 1206};
1207 1207
1208static u64 kvm_vz_get_one_regs_contextconfig[] = {
1209 KVM_REG_MIPS_CP0_CONTEXTCONFIG,
1210#ifdef CONFIG_64BIT
1211 KVM_REG_MIPS_CP0_XCONTEXTCONFIG,
1212#endif
1213};
1214
1208static u64 kvm_vz_get_one_regs_kscratch[] = { 1215static u64 kvm_vz_get_one_regs_kscratch[] = {
1209 KVM_REG_MIPS_CP0_KSCRATCH1, 1216 KVM_REG_MIPS_CP0_KSCRATCH1,
1210 KVM_REG_MIPS_CP0_KSCRATCH2, 1217 KVM_REG_MIPS_CP0_KSCRATCH2,
@@ -1225,6 +1232,8 @@ static unsigned long kvm_vz_num_regs(struct kvm_vcpu *vcpu)
1225 ++ret; 1232 ++ret;
1226 if (cpu_guest_has_badinstrp) 1233 if (cpu_guest_has_badinstrp)
1227 ++ret; 1234 ++ret;
1235 if (cpu_guest_has_contextconfig)
1236 ret += ARRAY_SIZE(kvm_vz_get_one_regs_contextconfig);
1228 ret += __arch_hweight8(cpu_data[0].guest.kscratch_mask); 1237 ret += __arch_hweight8(cpu_data[0].guest.kscratch_mask);
1229 1238
1230 return ret; 1239 return ret;
@@ -1258,6 +1267,12 @@ static int kvm_vz_copy_reg_indices(struct kvm_vcpu *vcpu, u64 __user *indices)
1258 return -EFAULT; 1267 return -EFAULT;
1259 ++indices; 1268 ++indices;
1260 } 1269 }
1270 if (cpu_guest_has_contextconfig) {
1271 if (copy_to_user(indices, kvm_vz_get_one_regs_contextconfig,
1272 sizeof(kvm_vz_get_one_regs_contextconfig)))
1273 return -EFAULT;
1274 indices += ARRAY_SIZE(kvm_vz_get_one_regs_contextconfig);
1275 }
1261 for (i = 0; i < 6; ++i) { 1276 for (i = 0; i < 6; ++i) {
1262 if (!cpu_guest_has_kscr(i + 2)) 1277 if (!cpu_guest_has_kscr(i + 2))
1263 continue; 1278 continue;
@@ -1323,11 +1338,23 @@ static int kvm_vz_get_one_reg(struct kvm_vcpu *vcpu,
1323 case KVM_REG_MIPS_CP0_CONTEXT: 1338 case KVM_REG_MIPS_CP0_CONTEXT:
1324 *v = (long)read_gc0_context(); 1339 *v = (long)read_gc0_context();
1325 break; 1340 break;
1341 case KVM_REG_MIPS_CP0_CONTEXTCONFIG:
1342 if (!cpu_guest_has_contextconfig)
1343 return -EINVAL;
1344 *v = read_gc0_contextconfig();
1345 break;
1326 case KVM_REG_MIPS_CP0_USERLOCAL: 1346 case KVM_REG_MIPS_CP0_USERLOCAL:
1327 if (!cpu_guest_has_userlocal) 1347 if (!cpu_guest_has_userlocal)
1328 return -EINVAL; 1348 return -EINVAL;
1329 *v = read_gc0_userlocal(); 1349 *v = read_gc0_userlocal();
1330 break; 1350 break;
1351#ifdef CONFIG_64BIT
1352 case KVM_REG_MIPS_CP0_XCONTEXTCONFIG:
1353 if (!cpu_guest_has_contextconfig)
1354 return -EINVAL;
1355 *v = read_gc0_xcontextconfig();
1356 break;
1357#endif
1331 case KVM_REG_MIPS_CP0_PAGEMASK: 1358 case KVM_REG_MIPS_CP0_PAGEMASK:
1332 *v = (long)read_gc0_pagemask(); 1359 *v = (long)read_gc0_pagemask();
1333 break; 1360 break;
@@ -1478,11 +1505,23 @@ static int kvm_vz_set_one_reg(struct kvm_vcpu *vcpu,
1478 case KVM_REG_MIPS_CP0_CONTEXT: 1505 case KVM_REG_MIPS_CP0_CONTEXT:
1479 write_gc0_context(v); 1506 write_gc0_context(v);
1480 break; 1507 break;
1508 case KVM_REG_MIPS_CP0_CONTEXTCONFIG:
1509 if (!cpu_guest_has_contextconfig)
1510 return -EINVAL;
1511 write_gc0_contextconfig(v);
1512 break;
1481 case KVM_REG_MIPS_CP0_USERLOCAL: 1513 case KVM_REG_MIPS_CP0_USERLOCAL:
1482 if (!cpu_guest_has_userlocal) 1514 if (!cpu_guest_has_userlocal)
1483 return -EINVAL; 1515 return -EINVAL;
1484 write_gc0_userlocal(v); 1516 write_gc0_userlocal(v);
1485 break; 1517 break;
1518#ifdef CONFIG_64BIT
1519 case KVM_REG_MIPS_CP0_XCONTEXTCONFIG:
1520 if (!cpu_guest_has_contextconfig)
1521 return -EINVAL;
1522 write_gc0_xcontextconfig(v);
1523 break;
1524#endif
1486 case KVM_REG_MIPS_CP0_PAGEMASK: 1525 case KVM_REG_MIPS_CP0_PAGEMASK:
1487 write_gc0_pagemask(v); 1526 write_gc0_pagemask(v);
1488 break; 1527 break;
@@ -1874,8 +1913,12 @@ static int kvm_vz_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
1874 kvm_restore_gc0_entrylo0(cop0); 1913 kvm_restore_gc0_entrylo0(cop0);
1875 kvm_restore_gc0_entrylo1(cop0); 1914 kvm_restore_gc0_entrylo1(cop0);
1876 kvm_restore_gc0_context(cop0); 1915 kvm_restore_gc0_context(cop0);
1916 if (cpu_guest_has_contextconfig)
1917 kvm_restore_gc0_contextconfig(cop0);
1877#ifdef CONFIG_64BIT 1918#ifdef CONFIG_64BIT
1878 kvm_restore_gc0_xcontext(cop0); 1919 kvm_restore_gc0_xcontext(cop0);
1920 if (cpu_guest_has_contextconfig)
1921 kvm_restore_gc0_xcontextconfig(cop0);
1879#endif 1922#endif
1880 kvm_restore_gc0_pagemask(cop0); 1923 kvm_restore_gc0_pagemask(cop0);
1881 kvm_restore_gc0_pagegrain(cop0); 1924 kvm_restore_gc0_pagegrain(cop0);
@@ -1933,8 +1976,12 @@ static int kvm_vz_vcpu_put(struct kvm_vcpu *vcpu, int cpu)
1933 kvm_save_gc0_entrylo0(cop0); 1976 kvm_save_gc0_entrylo0(cop0);
1934 kvm_save_gc0_entrylo1(cop0); 1977 kvm_save_gc0_entrylo1(cop0);
1935 kvm_save_gc0_context(cop0); 1978 kvm_save_gc0_context(cop0);
1979 if (cpu_guest_has_contextconfig)
1980 kvm_save_gc0_contextconfig(cop0);
1936#ifdef CONFIG_64BIT 1981#ifdef CONFIG_64BIT
1937 kvm_save_gc0_xcontext(cop0); 1982 kvm_save_gc0_xcontext(cop0);
1983 if (cpu_guest_has_contextconfig)
1984 kvm_save_gc0_xcontextconfig(cop0);
1938#endif 1985#endif
1939 kvm_save_gc0_pagemask(cop0); 1986 kvm_save_gc0_pagemask(cop0);
1940 kvm_save_gc0_pagegrain(cop0); 1987 kvm_save_gc0_pagegrain(cop0);
@@ -2298,6 +2345,17 @@ static int kvm_vz_vcpu_setup(struct kvm_vcpu *vcpu)
2298 kvm_clear_sw_gc0_config5(cop0, MIPS_CONF5_MRP); 2345 kvm_clear_sw_gc0_config5(cop0, MIPS_CONF5_MRP);
2299 } 2346 }
2300 2347
2348 if (cpu_guest_has_contextconfig) {
2349 /* ContextConfig */
2350 kvm_write_sw_gc0_contextconfig(cop0, 0x007ffff0);
2351#ifdef CONFIG_64BIT
2352 /* XContextConfig */
2353 /* bits SEGBITS-13+3:4 set */
2354 kvm_write_sw_gc0_xcontextconfig(cop0,
2355 ((1ull << (cpu_vmbits - 13)) - 1) << 4);
2356#endif
2357 }
2358
2301 /* start with no pending virtual guest interrupts */ 2359 /* start with no pending virtual guest interrupts */
2302 if (cpu_has_guestctl2) 2360 if (cpu_has_guestctl2)
2303 cop0->reg[MIPS_CP0_GUESTCTL2][MIPS_CP0_GUESTCTL2_SEL] = 0; 2361 cop0->reg[MIPS_CP0_GUESTCTL2][MIPS_CP0_GUESTCTL2_SEL] = 0;