Skip to content

Commit 0510870

Browse files
James Hoganbonzini
authored andcommitted
MIPS: KVM: Add KScratch registers
Allow up to 6 KVM guest KScratch registers to be enabled and accessed via the KVM guest register API and from the guest itself (the fallback reading and writing of commpage registers is sufficient for KScratch registers to work as expected). User mode can expose the registers by setting the appropriate bits of the guest Config4.KScrExist field. KScratch registers that aren't usable won't be writeable via the KVM Ioctl API. 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: linux-mips@linux-mips.org Cc: kvm@vger.kernel.org Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
1 parent cf1fb0f commit 0510870

File tree

6 files changed

+110
-1
lines changed

6 files changed

+110
-1
lines changed

Documentation/virtual/kvm/api.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2032,6 +2032,12 @@ registers, find a list below:
20322032
MIPS | KVM_REG_MIPS_CP0_CONFIG5 | 32
20332033
MIPS | KVM_REG_MIPS_CP0_CONFIG7 | 32
20342034
MIPS | KVM_REG_MIPS_CP0_ERROREPC | 64
2035+
MIPS | KVM_REG_MIPS_CP0_KSCRATCH1 | 64
2036+
MIPS | KVM_REG_MIPS_CP0_KSCRATCH2 | 64
2037+
MIPS | KVM_REG_MIPS_CP0_KSCRATCH3 | 64
2038+
MIPS | KVM_REG_MIPS_CP0_KSCRATCH4 | 64
2039+
MIPS | KVM_REG_MIPS_CP0_KSCRATCH5 | 64
2040+
MIPS | KVM_REG_MIPS_CP0_KSCRATCH6 | 64
20352041
MIPS | KVM_REG_MIPS_COUNT_CTL | 64
20362042
MIPS | KVM_REG_MIPS_COUNT_RESUME | 64
20372043
MIPS | KVM_REG_MIPS_COUNT_HZ | 64

arch/mips/include/asm/kvm_host.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,12 @@
5656
#define KVM_REG_MIPS_CP0_CONFIG7 MIPS_CP0_32(16, 7)
5757
#define KVM_REG_MIPS_CP0_XCONTEXT MIPS_CP0_64(20, 0)
5858
#define KVM_REG_MIPS_CP0_ERROREPC MIPS_CP0_64(30, 0)
59+
#define KVM_REG_MIPS_CP0_KSCRATCH1 MIPS_CP0_64(31, 2)
60+
#define KVM_REG_MIPS_CP0_KSCRATCH2 MIPS_CP0_64(31, 3)
61+
#define KVM_REG_MIPS_CP0_KSCRATCH3 MIPS_CP0_64(31, 4)
62+
#define KVM_REG_MIPS_CP0_KSCRATCH4 MIPS_CP0_64(31, 5)
63+
#define KVM_REG_MIPS_CP0_KSCRATCH5 MIPS_CP0_64(31, 6)
64+
#define KVM_REG_MIPS_CP0_KSCRATCH6 MIPS_CP0_64(31, 7)
5965

6066

6167
#define KVM_MAX_VCPUS 1
@@ -376,6 +382,7 @@ struct kvm_vcpu_arch {
376382

377383
u8 fpu_enabled;
378384
u8 msa_enabled;
385+
u8 kscratch_enabled;
379386
};
380387

381388

@@ -429,6 +436,18 @@ struct kvm_vcpu_arch {
429436
#define kvm_write_c0_guest_config7(cop0, val) (cop0->reg[MIPS_CP0_CONFIG][7] = (val))
430437
#define kvm_read_c0_guest_errorepc(cop0) (cop0->reg[MIPS_CP0_ERROR_PC][0])
431438
#define kvm_write_c0_guest_errorepc(cop0, val) (cop0->reg[MIPS_CP0_ERROR_PC][0] = (val))
439+
#define kvm_read_c0_guest_kscratch1(cop0) (cop0->reg[MIPS_CP0_DESAVE][2])
440+
#define kvm_read_c0_guest_kscratch2(cop0) (cop0->reg[MIPS_CP0_DESAVE][3])
441+
#define kvm_read_c0_guest_kscratch3(cop0) (cop0->reg[MIPS_CP0_DESAVE][4])
442+
#define kvm_read_c0_guest_kscratch4(cop0) (cop0->reg[MIPS_CP0_DESAVE][5])
443+
#define kvm_read_c0_guest_kscratch5(cop0) (cop0->reg[MIPS_CP0_DESAVE][6])
444+
#define kvm_read_c0_guest_kscratch6(cop0) (cop0->reg[MIPS_CP0_DESAVE][7])
445+
#define kvm_write_c0_guest_kscratch1(cop0, val) (cop0->reg[MIPS_CP0_DESAVE][2] = (val))
446+
#define kvm_write_c0_guest_kscratch2(cop0, val) (cop0->reg[MIPS_CP0_DESAVE][3] = (val))
447+
#define kvm_write_c0_guest_kscratch3(cop0, val) (cop0->reg[MIPS_CP0_DESAVE][4] = (val))
448+
#define kvm_write_c0_guest_kscratch4(cop0, val) (cop0->reg[MIPS_CP0_DESAVE][5] = (val))
449+
#define kvm_write_c0_guest_kscratch5(cop0, val) (cop0->reg[MIPS_CP0_DESAVE][6] = (val))
450+
#define kvm_write_c0_guest_kscratch6(cop0, val) (cop0->reg[MIPS_CP0_DESAVE][7] = (val))
432451

433452
/*
434453
* Some of the guest registers may be modified asynchronously (e.g. from a

arch/mips/kvm/emulate.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -941,7 +941,12 @@ unsigned int kvm_mips_config3_wrmask(struct kvm_vcpu *vcpu)
941941
unsigned int kvm_mips_config4_wrmask(struct kvm_vcpu *vcpu)
942942
{
943943
/* Config5 is optional */
944-
return MIPS_CONF_M;
944+
unsigned int mask = MIPS_CONF_M;
945+
946+
/* KScrExist */
947+
mask |= (unsigned int)vcpu->arch.kscratch_enabled << 16;
948+
949+
return mask;
945950
}
946951

947952
/**

arch/mips/kvm/mips.c

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
* Authors: Sanjay Lal <sanjayl@kymasys.com>
1010
*/
1111

12+
#include <linux/bitops.h>
1213
#include <linux/errno.h>
1314
#include <linux/err.h>
1415
#include <linux/kdebug.h>
@@ -548,6 +549,15 @@ static u64 kvm_mips_get_one_regs_msa[] = {
548549
KVM_REG_MIPS_MSA_CSR,
549550
};
550551

552+
static u64 kvm_mips_get_one_regs_kscratch[] = {
553+
KVM_REG_MIPS_CP0_KSCRATCH1,
554+
KVM_REG_MIPS_CP0_KSCRATCH2,
555+
KVM_REG_MIPS_CP0_KSCRATCH3,
556+
KVM_REG_MIPS_CP0_KSCRATCH4,
557+
KVM_REG_MIPS_CP0_KSCRATCH5,
558+
KVM_REG_MIPS_CP0_KSCRATCH6,
559+
};
560+
551561
static unsigned long kvm_mips_num_regs(struct kvm_vcpu *vcpu)
552562
{
553563
unsigned long ret;
@@ -561,6 +571,7 @@ static unsigned long kvm_mips_num_regs(struct kvm_vcpu *vcpu)
561571
}
562572
if (kvm_mips_guest_can_have_msa(&vcpu->arch))
563573
ret += ARRAY_SIZE(kvm_mips_get_one_regs_msa) + 32;
574+
ret += __arch_hweight8(vcpu->arch.kscratch_enabled);
564575
ret += kvm_mips_callbacks->num_regs(vcpu);
565576

566577
return ret;
@@ -613,6 +624,16 @@ static int kvm_mips_copy_reg_indices(struct kvm_vcpu *vcpu, u64 __user *indices)
613624
}
614625
}
615626

627+
for (i = 0; i < 6; ++i) {
628+
if (!(vcpu->arch.kscratch_enabled & BIT(i + 2)))
629+
continue;
630+
631+
if (copy_to_user(indices, &kvm_mips_get_one_regs_kscratch[i],
632+
sizeof(kvm_mips_get_one_regs_kscratch[i])))
633+
return -EFAULT;
634+
++indices;
635+
}
636+
616637
return kvm_mips_callbacks->copy_reg_indices(vcpu, indices);
617638
}
618639

@@ -765,6 +786,31 @@ static int kvm_mips_get_reg(struct kvm_vcpu *vcpu,
765786
case KVM_REG_MIPS_CP0_ERROREPC:
766787
v = (long)kvm_read_c0_guest_errorepc(cop0);
767788
break;
789+
case KVM_REG_MIPS_CP0_KSCRATCH1 ... KVM_REG_MIPS_CP0_KSCRATCH6:
790+
idx = reg->id - KVM_REG_MIPS_CP0_KSCRATCH1 + 2;
791+
if (!(vcpu->arch.kscratch_enabled & BIT(idx)))
792+
return -EINVAL;
793+
switch (idx) {
794+
case 2:
795+
v = (long)kvm_read_c0_guest_kscratch1(cop0);
796+
break;
797+
case 3:
798+
v = (long)kvm_read_c0_guest_kscratch2(cop0);
799+
break;
800+
case 4:
801+
v = (long)kvm_read_c0_guest_kscratch3(cop0);
802+
break;
803+
case 5:
804+
v = (long)kvm_read_c0_guest_kscratch4(cop0);
805+
break;
806+
case 6:
807+
v = (long)kvm_read_c0_guest_kscratch5(cop0);
808+
break;
809+
case 7:
810+
v = (long)kvm_read_c0_guest_kscratch6(cop0);
811+
break;
812+
}
813+
break;
768814
/* registers to be handled specially */
769815
default:
770816
ret = kvm_mips_callbacks->get_one_reg(vcpu, reg, &v);
@@ -931,6 +977,31 @@ static int kvm_mips_set_reg(struct kvm_vcpu *vcpu,
931977
case KVM_REG_MIPS_CP0_ERROREPC:
932978
kvm_write_c0_guest_errorepc(cop0, v);
933979
break;
980+
case KVM_REG_MIPS_CP0_KSCRATCH1 ... KVM_REG_MIPS_CP0_KSCRATCH6:
981+
idx = reg->id - KVM_REG_MIPS_CP0_KSCRATCH1 + 2;
982+
if (!(vcpu->arch.kscratch_enabled & BIT(idx)))
983+
return -EINVAL;
984+
switch (idx) {
985+
case 2:
986+
kvm_write_c0_guest_kscratch1(cop0, v);
987+
break;
988+
case 3:
989+
kvm_write_c0_guest_kscratch2(cop0, v);
990+
break;
991+
case 4:
992+
kvm_write_c0_guest_kscratch3(cop0, v);
993+
break;
994+
case 5:
995+
kvm_write_c0_guest_kscratch4(cop0, v);
996+
break;
997+
case 6:
998+
kvm_write_c0_guest_kscratch5(cop0, v);
999+
break;
1000+
case 7:
1001+
kvm_write_c0_guest_kscratch6(cop0, v);
1002+
break;
1003+
}
1004+
break;
9341005
/* registers to be handled specially */
9351006
default:
9361007
return kvm_mips_callbacks->set_one_reg(vcpu, reg, v);

arch/mips/kvm/trace.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,12 @@ TRACE_EVENT(kvm_exit,
178178
{ KVM_TRACE_COP0(16, 7), "Config7" }, \
179179
{ KVM_TRACE_COP0(26, 0), "ECC" }, \
180180
{ KVM_TRACE_COP0(30, 0), "ErrorEPC" }, \
181+
{ KVM_TRACE_COP0(31, 2), "KScratch1" }, \
182+
{ KVM_TRACE_COP0(31, 3), "KScratch2" }, \
183+
{ KVM_TRACE_COP0(31, 4), "KScratch3" }, \
184+
{ KVM_TRACE_COP0(31, 5), "KScratch4" }, \
185+
{ KVM_TRACE_COP0(31, 6), "KScratch5" }, \
186+
{ KVM_TRACE_COP0(31, 7), "KScratch6" }, \
181187
{ KVM_TRACE_HWR( 0, 0), "CPUNum" }, \
182188
{ KVM_TRACE_HWR( 1, 0), "SYNCI_Step" }, \
183189
{ KVM_TRACE_HWR( 2, 0), "CC" }, \

arch/mips/kvm/trap_emul.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -418,6 +418,8 @@ static int kvm_trap_emul_vm_init(struct kvm *kvm)
418418

419419
static int kvm_trap_emul_vcpu_init(struct kvm_vcpu *vcpu)
420420
{
421+
vcpu->arch.kscratch_enabled = 0xfc;
422+
421423
return 0;
422424
}
423425

0 commit comments

Comments
 (0)