aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJames Hogan <james.hogan@imgtec.com>2014-06-26 10:11:29 -0400
committerJames Hogan <james.hogan@imgtec.com>2015-03-27 17:25:12 -0400
commitc771607af959f282704268a209743560d3264eb3 (patch)
tree3916947b717cd4b4af754bf881063490e204c6e4
parent2211ee810ac6fdcdb42b7a126e20d1b4e5c55124 (diff)
MIPS: KVM: Add Config4/5 and writing of Config registers
Add Config4 and Config5 co-processor 0 registers, and add capability to write the Config1, Config3, Config4, and Config5 registers using the KVM API. Only supported bits can be written, to minimise the chances of the guest being given a configuration from e.g. QEMU that is inconsistent with that being emulated, and as such the handling is in trap_emul.c as it may need to be different for VZ. Currently the only modification permitted is to make Config4 and Config5 exist via the M bits, but other bits will be added for FPU and MSA support in future patches. Care should be taken by userland not to change bits without fully handling the possible extra state that may then exist and which the guest may begin to use and depend on. Signed-off-by: James Hogan <james.hogan@imgtec.com> Cc: Paolo Bonzini <pbonzini@redhat.com> Cc: Ralf Baechle <ralf@linux-mips.org> Cc: Gleb Natapov <gleb@kernel.org> Cc: linux-mips@linux-mips.org Cc: kvm@vger.kernel.org
-rw-r--r--Documentation/virtual/kvm/api.txt2
-rw-r--r--arch/mips/include/asm/kvm_host.h13
-rw-r--r--arch/mips/kvm/emulate.c52
-rw-r--r--arch/mips/kvm/mips.c14
-rw-r--r--arch/mips/kvm/trap_emul.c49
5 files changed, 128 insertions, 2 deletions
diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt
index 9a5f8a482db1..3f295a04b09f 100644
--- a/Documentation/virtual/kvm/api.txt
+++ b/Documentation/virtual/kvm/api.txt
@@ -1972,6 +1972,8 @@ registers, find a list below:
1972 MIPS | KVM_REG_MIPS_CP0_CONFIG1 | 32 1972 MIPS | KVM_REG_MIPS_CP0_CONFIG1 | 32
1973 MIPS | KVM_REG_MIPS_CP0_CONFIG2 | 32 1973 MIPS | KVM_REG_MIPS_CP0_CONFIG2 | 32
1974 MIPS | KVM_REG_MIPS_CP0_CONFIG3 | 32 1974 MIPS | KVM_REG_MIPS_CP0_CONFIG3 | 32
1975 MIPS | KVM_REG_MIPS_CP0_CONFIG4 | 32
1976 MIPS | KVM_REG_MIPS_CP0_CONFIG5 | 32
1975 MIPS | KVM_REG_MIPS_CP0_CONFIG7 | 32 1977 MIPS | KVM_REG_MIPS_CP0_CONFIG7 | 32
1976 MIPS | KVM_REG_MIPS_CP0_ERROREPC | 64 1978 MIPS | KVM_REG_MIPS_CP0_ERROREPC | 64
1977 MIPS | KVM_REG_MIPS_COUNT_CTL | 64 1979 MIPS | KVM_REG_MIPS_COUNT_CTL | 64
diff --git a/arch/mips/include/asm/kvm_host.h b/arch/mips/include/asm/kvm_host.h
index 6996447fd2a7..3f58ee1ebfab 100644
--- a/arch/mips/include/asm/kvm_host.h
+++ b/arch/mips/include/asm/kvm_host.h
@@ -48,6 +48,8 @@
48#define KVM_REG_MIPS_CP0_CONFIG1 MIPS_CP0_32(16, 1) 48#define KVM_REG_MIPS_CP0_CONFIG1 MIPS_CP0_32(16, 1)
49#define KVM_REG_MIPS_CP0_CONFIG2 MIPS_CP0_32(16, 2) 49#define KVM_REG_MIPS_CP0_CONFIG2 MIPS_CP0_32(16, 2)
50#define KVM_REG_MIPS_CP0_CONFIG3 MIPS_CP0_32(16, 3) 50#define KVM_REG_MIPS_CP0_CONFIG3 MIPS_CP0_32(16, 3)
51#define KVM_REG_MIPS_CP0_CONFIG4 MIPS_CP0_32(16, 4)
52#define KVM_REG_MIPS_CP0_CONFIG5 MIPS_CP0_32(16, 5)
51#define KVM_REG_MIPS_CP0_CONFIG7 MIPS_CP0_32(16, 7) 53#define KVM_REG_MIPS_CP0_CONFIG7 MIPS_CP0_32(16, 7)
52#define KVM_REG_MIPS_CP0_XCONTEXT MIPS_CP0_64(20, 0) 54#define KVM_REG_MIPS_CP0_XCONTEXT MIPS_CP0_64(20, 0)
53#define KVM_REG_MIPS_CP0_ERROREPC MIPS_CP0_64(30, 0) 55#define KVM_REG_MIPS_CP0_ERROREPC MIPS_CP0_64(30, 0)
@@ -209,6 +211,8 @@ struct mips_coproc {
209#define MIPS_CP0_CONFIG1_SEL 1 211#define MIPS_CP0_CONFIG1_SEL 1
210#define MIPS_CP0_CONFIG2_SEL 2 212#define MIPS_CP0_CONFIG2_SEL 2
211#define MIPS_CP0_CONFIG3_SEL 3 213#define MIPS_CP0_CONFIG3_SEL 3
214#define MIPS_CP0_CONFIG4_SEL 4
215#define MIPS_CP0_CONFIG5_SEL 5
212 216
213/* Config0 register bits */ 217/* Config0 register bits */
214#define CP0C0_M 31 218#define CP0C0_M 31
@@ -461,11 +465,15 @@ struct kvm_vcpu_arch {
461#define kvm_read_c0_guest_config1(cop0) (cop0->reg[MIPS_CP0_CONFIG][1]) 465#define kvm_read_c0_guest_config1(cop0) (cop0->reg[MIPS_CP0_CONFIG][1])
462#define kvm_read_c0_guest_config2(cop0) (cop0->reg[MIPS_CP0_CONFIG][2]) 466#define kvm_read_c0_guest_config2(cop0) (cop0->reg[MIPS_CP0_CONFIG][2])
463#define kvm_read_c0_guest_config3(cop0) (cop0->reg[MIPS_CP0_CONFIG][3]) 467#define kvm_read_c0_guest_config3(cop0) (cop0->reg[MIPS_CP0_CONFIG][3])
468#define kvm_read_c0_guest_config4(cop0) (cop0->reg[MIPS_CP0_CONFIG][4])
469#define kvm_read_c0_guest_config5(cop0) (cop0->reg[MIPS_CP0_CONFIG][5])
464#define kvm_read_c0_guest_config7(cop0) (cop0->reg[MIPS_CP0_CONFIG][7]) 470#define kvm_read_c0_guest_config7(cop0) (cop0->reg[MIPS_CP0_CONFIG][7])
465#define kvm_write_c0_guest_config(cop0, val) (cop0->reg[MIPS_CP0_CONFIG][0] = (val)) 471#define kvm_write_c0_guest_config(cop0, val) (cop0->reg[MIPS_CP0_CONFIG][0] = (val))
466#define kvm_write_c0_guest_config1(cop0, val) (cop0->reg[MIPS_CP0_CONFIG][1] = (val)) 472#define kvm_write_c0_guest_config1(cop0, val) (cop0->reg[MIPS_CP0_CONFIG][1] = (val))
467#define kvm_write_c0_guest_config2(cop0, val) (cop0->reg[MIPS_CP0_CONFIG][2] = (val)) 473#define kvm_write_c0_guest_config2(cop0, val) (cop0->reg[MIPS_CP0_CONFIG][2] = (val))
468#define kvm_write_c0_guest_config3(cop0, val) (cop0->reg[MIPS_CP0_CONFIG][3] = (val)) 474#define kvm_write_c0_guest_config3(cop0, val) (cop0->reg[MIPS_CP0_CONFIG][3] = (val))
475#define kvm_write_c0_guest_config4(cop0, val) (cop0->reg[MIPS_CP0_CONFIG][4] = (val))
476#define kvm_write_c0_guest_config5(cop0, val) (cop0->reg[MIPS_CP0_CONFIG][5] = (val))
469#define kvm_write_c0_guest_config7(cop0, val) (cop0->reg[MIPS_CP0_CONFIG][7] = (val)) 477#define kvm_write_c0_guest_config7(cop0, val) (cop0->reg[MIPS_CP0_CONFIG][7] = (val))
470#define kvm_read_c0_guest_errorepc(cop0) (cop0->reg[MIPS_CP0_ERROR_PC][0]) 478#define kvm_read_c0_guest_errorepc(cop0) (cop0->reg[MIPS_CP0_ERROR_PC][0])
471#define kvm_write_c0_guest_errorepc(cop0, val) (cop0->reg[MIPS_CP0_ERROR_PC][0] = (val)) 479#define kvm_write_c0_guest_errorepc(cop0, val) (cop0->reg[MIPS_CP0_ERROR_PC][0] = (val))
@@ -735,6 +743,11 @@ enum emulation_result kvm_mips_emulate_load(uint32_t inst,
735 struct kvm_run *run, 743 struct kvm_run *run,
736 struct kvm_vcpu *vcpu); 744 struct kvm_vcpu *vcpu);
737 745
746unsigned int kvm_mips_config1_wrmask(struct kvm_vcpu *vcpu);
747unsigned int kvm_mips_config3_wrmask(struct kvm_vcpu *vcpu);
748unsigned int kvm_mips_config4_wrmask(struct kvm_vcpu *vcpu);
749unsigned int kvm_mips_config5_wrmask(struct kvm_vcpu *vcpu);
750
738/* Dynamic binary translation */ 751/* Dynamic binary translation */
739extern int kvm_mips_trans_cache_index(uint32_t inst, uint32_t *opc, 752extern int kvm_mips_trans_cache_index(uint32_t inst, uint32_t *opc,
740 struct kvm_vcpu *vcpu); 753 struct kvm_vcpu *vcpu);
diff --git a/arch/mips/kvm/emulate.c b/arch/mips/kvm/emulate.c
index 33e132dc7de8..91d5b0e370b4 100644
--- a/arch/mips/kvm/emulate.c
+++ b/arch/mips/kvm/emulate.c
@@ -884,6 +884,58 @@ enum emulation_result kvm_mips_emul_tlbp(struct kvm_vcpu *vcpu)
884 return EMULATE_DONE; 884 return EMULATE_DONE;
885} 885}
886 886
887/**
888 * kvm_mips_config1_wrmask() - Find mask of writable bits in guest Config1
889 * @vcpu: Virtual CPU.
890 *
891 * Finds the mask of bits which are writable in the guest's Config1 CP0
892 * register, by userland (currently read-only to the guest).
893 */
894unsigned int kvm_mips_config1_wrmask(struct kvm_vcpu *vcpu)
895{
896 /* Read-only */
897 return 0;
898}
899
900/**
901 * kvm_mips_config3_wrmask() - Find mask of writable bits in guest Config3
902 * @vcpu: Virtual CPU.
903 *
904 * Finds the mask of bits which are writable in the guest's Config3 CP0
905 * register, by userland (currently read-only to the guest).
906 */
907unsigned int kvm_mips_config3_wrmask(struct kvm_vcpu *vcpu)
908{
909 /* Config4 is optional */
910 return MIPS_CONF_M;
911}
912
913/**
914 * kvm_mips_config4_wrmask() - Find mask of writable bits in guest Config4
915 * @vcpu: Virtual CPU.
916 *
917 * Finds the mask of bits which are writable in the guest's Config4 CP0
918 * register, by userland (currently read-only to the guest).
919 */
920unsigned int kvm_mips_config4_wrmask(struct kvm_vcpu *vcpu)
921{
922 /* Config5 is optional */
923 return MIPS_CONF_M;
924}
925
926/**
927 * kvm_mips_config5_wrmask() - Find mask of writable bits in guest Config5
928 * @vcpu: Virtual CPU.
929 *
930 * Finds the mask of bits which are writable in the guest's Config5 CP0
931 * register, by the guest itself.
932 */
933unsigned int kvm_mips_config5_wrmask(struct kvm_vcpu *vcpu)
934{
935 /* Read-only */
936 return 0;
937}
938
887enum emulation_result kvm_mips_emulate_CP0(uint32_t inst, uint32_t *opc, 939enum emulation_result kvm_mips_emulate_CP0(uint32_t inst, uint32_t *opc,
888 uint32_t cause, struct kvm_run *run, 940 uint32_t cause, struct kvm_run *run,
889 struct kvm_vcpu *vcpu) 941 struct kvm_vcpu *vcpu)
diff --git a/arch/mips/kvm/mips.c b/arch/mips/kvm/mips.c
index 0aab83d894ba..73eecc779454 100644
--- a/arch/mips/kvm/mips.c
+++ b/arch/mips/kvm/mips.c
@@ -510,6 +510,8 @@ static u64 kvm_mips_get_one_regs[] = {
510 KVM_REG_MIPS_CP0_CONFIG1, 510 KVM_REG_MIPS_CP0_CONFIG1,
511 KVM_REG_MIPS_CP0_CONFIG2, 511 KVM_REG_MIPS_CP0_CONFIG2,
512 KVM_REG_MIPS_CP0_CONFIG3, 512 KVM_REG_MIPS_CP0_CONFIG3,
513 KVM_REG_MIPS_CP0_CONFIG4,
514 KVM_REG_MIPS_CP0_CONFIG5,
513 KVM_REG_MIPS_CP0_CONFIG7, 515 KVM_REG_MIPS_CP0_CONFIG7,
514 KVM_REG_MIPS_CP0_ERROREPC, 516 KVM_REG_MIPS_CP0_ERROREPC,
515 517
@@ -590,6 +592,12 @@ static int kvm_mips_get_reg(struct kvm_vcpu *vcpu,
590 case KVM_REG_MIPS_CP0_CONFIG3: 592 case KVM_REG_MIPS_CP0_CONFIG3:
591 v = (long)kvm_read_c0_guest_config3(cop0); 593 v = (long)kvm_read_c0_guest_config3(cop0);
592 break; 594 break;
595 case KVM_REG_MIPS_CP0_CONFIG4:
596 v = (long)kvm_read_c0_guest_config4(cop0);
597 break;
598 case KVM_REG_MIPS_CP0_CONFIG5:
599 v = (long)kvm_read_c0_guest_config5(cop0);
600 break;
593 case KVM_REG_MIPS_CP0_CONFIG7: 601 case KVM_REG_MIPS_CP0_CONFIG7:
594 v = (long)kvm_read_c0_guest_config7(cop0); 602 v = (long)kvm_read_c0_guest_config7(cop0);
595 break; 603 break;
@@ -701,6 +709,12 @@ static int kvm_mips_set_reg(struct kvm_vcpu *vcpu,
701 case KVM_REG_MIPS_CP0_COUNT: 709 case KVM_REG_MIPS_CP0_COUNT:
702 case KVM_REG_MIPS_CP0_COMPARE: 710 case KVM_REG_MIPS_CP0_COMPARE:
703 case KVM_REG_MIPS_CP0_CAUSE: 711 case KVM_REG_MIPS_CP0_CAUSE:
712 case KVM_REG_MIPS_CP0_CONFIG:
713 case KVM_REG_MIPS_CP0_CONFIG1:
714 case KVM_REG_MIPS_CP0_CONFIG2:
715 case KVM_REG_MIPS_CP0_CONFIG3:
716 case KVM_REG_MIPS_CP0_CONFIG4:
717 case KVM_REG_MIPS_CP0_CONFIG5:
704 case KVM_REG_MIPS_COUNT_CTL: 718 case KVM_REG_MIPS_COUNT_CTL:
705 case KVM_REG_MIPS_COUNT_RESUME: 719 case KVM_REG_MIPS_COUNT_RESUME:
706 case KVM_REG_MIPS_COUNT_HZ: 720 case KVM_REG_MIPS_COUNT_HZ:
diff --git a/arch/mips/kvm/trap_emul.c b/arch/mips/kvm/trap_emul.c
index bffba002d1a4..8e0968428a78 100644
--- a/arch/mips/kvm/trap_emul.c
+++ b/arch/mips/kvm/trap_emul.c
@@ -418,8 +418,14 @@ static int kvm_trap_emul_vcpu_setup(struct kvm_vcpu *vcpu)
418 kvm_write_c0_guest_config2(cop0, MIPS_CONF_M); 418 kvm_write_c0_guest_config2(cop0, MIPS_CONF_M);
419 /* MIPS_CONF_M | (read_c0_config2() & 0xfff) */ 419 /* MIPS_CONF_M | (read_c0_config2() & 0xfff) */
420 420
421 /* No config4, UserLocal */ 421 /* Have config4, UserLocal */
422 kvm_write_c0_guest_config3(cop0, MIPS_CONF3_ULRI); 422 kvm_write_c0_guest_config3(cop0, MIPS_CONF_M | MIPS_CONF3_ULRI);
423
424 /* Have config5 */
425 kvm_write_c0_guest_config4(cop0, MIPS_CONF_M);
426
427 /* No config6 */
428 kvm_write_c0_guest_config5(cop0, 0);
423 429
424 /* Set Wait IE/IXMT Ignore in Config7, IAR, AR */ 430 /* Set Wait IE/IXMT Ignore in Config7, IAR, AR */
425 kvm_write_c0_guest_config7(cop0, (MIPS_CONF7_WII) | (1 << 10)); 431 kvm_write_c0_guest_config7(cop0, (MIPS_CONF7_WII) | (1 << 10));
@@ -464,6 +470,7 @@ static int kvm_trap_emul_set_one_reg(struct kvm_vcpu *vcpu,
464{ 470{
465 struct mips_coproc *cop0 = vcpu->arch.cop0; 471 struct mips_coproc *cop0 = vcpu->arch.cop0;
466 int ret = 0; 472 int ret = 0;
473 unsigned int cur, change;
467 474
468 switch (reg->id) { 475 switch (reg->id) {
469 case KVM_REG_MIPS_CP0_COUNT: 476 case KVM_REG_MIPS_CP0_COUNT:
@@ -492,6 +499,44 @@ static int kvm_trap_emul_set_one_reg(struct kvm_vcpu *vcpu,
492 kvm_write_c0_guest_cause(cop0, v); 499 kvm_write_c0_guest_cause(cop0, v);
493 } 500 }
494 break; 501 break;
502 case KVM_REG_MIPS_CP0_CONFIG:
503 /* read-only for now */
504 break;
505 case KVM_REG_MIPS_CP0_CONFIG1:
506 cur = kvm_read_c0_guest_config1(cop0);
507 change = (cur ^ v) & kvm_mips_config1_wrmask(vcpu);
508 if (change) {
509 v = cur ^ change;
510 kvm_write_c0_guest_config1(cop0, v);
511 }
512 break;
513 case KVM_REG_MIPS_CP0_CONFIG2:
514 /* read-only for now */
515 break;
516 case KVM_REG_MIPS_CP0_CONFIG3:
517 cur = kvm_read_c0_guest_config3(cop0);
518 change = (cur ^ v) & kvm_mips_config3_wrmask(vcpu);
519 if (change) {
520 v = cur ^ change;
521 kvm_write_c0_guest_config3(cop0, v);
522 }
523 break;
524 case KVM_REG_MIPS_CP0_CONFIG4:
525 cur = kvm_read_c0_guest_config4(cop0);
526 change = (cur ^ v) & kvm_mips_config4_wrmask(vcpu);
527 if (change) {
528 v = cur ^ change;
529 kvm_write_c0_guest_config4(cop0, v);
530 }
531 break;
532 case KVM_REG_MIPS_CP0_CONFIG5:
533 cur = kvm_read_c0_guest_config5(cop0);
534 change = (cur ^ v) & kvm_mips_config5_wrmask(vcpu);
535 if (change) {
536 v = cur ^ change;
537 kvm_write_c0_guest_config5(cop0, v);
538 }
539 break;
495 case KVM_REG_MIPS_COUNT_CTL: 540 case KVM_REG_MIPS_COUNT_CTL:
496 ret = kvm_mips_set_count_ctl(vcpu, v); 541 ret = kvm_mips_set_count_ctl(vcpu, v);
497 break; 542 break;