diff options
author | James Hogan <james.hogan@imgtec.com> | 2017-03-14 06:15:34 -0400 |
---|---|---|
committer | James Hogan <james.hogan@imgtec.com> | 2017-03-28 09:53:56 -0400 |
commit | dffe042fd8b2cc174966b929b379503af2c97933 (patch) | |
tree | 42b0f80e8b9d341cf34b72c0ddcf91101964bfd1 /arch/mips/kvm | |
parent | edc89260d474fd044e77b7039bd2a697dddcac6c (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.c | 62 |
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) | |||
161 | static inline unsigned int kvm_vz_config3_user_wrmask(struct kvm_vcpu *vcpu) | 161 | static 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 | ||
1208 | static 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 | |||
1208 | static u64 kvm_vz_get_one_regs_kscratch[] = { | 1215 | static 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; |