Skip to content

Commit 8a5097e

Browse files
chenhuacaibonzini
authored andcommitted
KVM: MIPS: Add CONFIG6 and DIAG registers emulation
Loongson-3 has CONFIG6 and DIAG registers which need to be emulated. CONFIG6 is mostly used to enable/disable FTLB and SFB, while DIAG is mostly used to flush BTB, ITLB, DTLB, VTLB and FTLB. Acked-by: Thomas Bogendoerfer <[email protected]> Reviewed-by: Aleksandar Markovic <[email protected]> Signed-off-by: Huacai Chen <[email protected]> Co-developed-by: Jiaxun Yang <[email protected]> Message-Id: <[email protected]> Signed-off-by: Paolo Bonzini <[email protected]>
1 parent 7f2a83f commit 8a5097e

File tree

4 files changed

+113
-1
lines changed

4 files changed

+113
-1
lines changed

arch/mips/include/asm/kvm_host.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,9 +68,11 @@
6868
#define KVM_REG_MIPS_CP0_CONFIG3 MIPS_CP0_32(16, 3)
6969
#define KVM_REG_MIPS_CP0_CONFIG4 MIPS_CP0_32(16, 4)
7070
#define KVM_REG_MIPS_CP0_CONFIG5 MIPS_CP0_32(16, 5)
71+
#define KVM_REG_MIPS_CP0_CONFIG6 MIPS_CP0_32(16, 6)
7172
#define KVM_REG_MIPS_CP0_CONFIG7 MIPS_CP0_32(16, 7)
7273
#define KVM_REG_MIPS_CP0_MAARI MIPS_CP0_64(17, 2)
7374
#define KVM_REG_MIPS_CP0_XCONTEXT MIPS_CP0_64(20, 0)
75+
#define KVM_REG_MIPS_CP0_DIAG MIPS_CP0_32(22, 0)
7476
#define KVM_REG_MIPS_CP0_ERROREPC MIPS_CP0_64(30, 0)
7577
#define KVM_REG_MIPS_CP0_KSCRATCH1 MIPS_CP0_64(31, 2)
7678
#define KVM_REG_MIPS_CP0_KSCRATCH2 MIPS_CP0_64(31, 3)
@@ -258,6 +260,7 @@ struct mips_coproc {
258260
#define MIPS_CP0_WATCH_LO 18
259261
#define MIPS_CP0_WATCH_HI 19
260262
#define MIPS_CP0_TLB_XCONTEXT 20
263+
#define MIPS_CP0_DIAG 22
261264
#define MIPS_CP0_ECC 26
262265
#define MIPS_CP0_CACHE_ERR 27
263266
#define MIPS_CP0_TAG_LO 28
@@ -929,6 +932,10 @@ void kvm_vz_save_guesttlb(struct kvm_mips_tlb *buf, unsigned int index,
929932
unsigned int count);
930933
void kvm_vz_load_guesttlb(const struct kvm_mips_tlb *buf, unsigned int index,
931934
unsigned int count);
935+
#ifdef CONFIG_CPU_LOONGSON64
936+
void kvm_loongson_clear_guest_vtlb(void);
937+
void kvm_loongson_clear_guest_ftlb(void);
938+
#endif
932939
#endif
933940

934941
void kvm_mips_suspend_mm(int cpu);

arch/mips/include/asm/mipsregs.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1038,6 +1038,8 @@
10381038
/* Disable Branch Return Cache */
10391039
#define R10K_DIAG_D_BRC (_ULCAST_(1) << 22)
10401040

1041+
/* Flush BTB */
1042+
#define LOONGSON_DIAG_BTB (_ULCAST_(1) << 1)
10411043
/* Flush ITLB */
10421044
#define LOONGSON_DIAG_ITLB (_ULCAST_(1) << 2)
10431045
/* Flush DTLB */
@@ -2874,7 +2876,9 @@ __BUILD_SET_C0(status)
28742876
__BUILD_SET_C0(cause)
28752877
__BUILD_SET_C0(config)
28762878
__BUILD_SET_C0(config5)
2879+
__BUILD_SET_C0(config6)
28772880
__BUILD_SET_C0(config7)
2881+
__BUILD_SET_C0(diag)
28782882
__BUILD_SET_C0(intcontrol)
28792883
__BUILD_SET_C0(intctl)
28802884
__BUILD_SET_C0(srsmap)

arch/mips/kvm/tlb.c

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020

2121
#include <asm/cpu.h>
2222
#include <asm/bootinfo.h>
23+
#include <asm/mipsregs.h>
2324
#include <asm/mmu_context.h>
2425
#include <asm/pgtable.h>
2526
#include <asm/cacheflush.h>
@@ -622,6 +623,46 @@ void kvm_vz_load_guesttlb(const struct kvm_mips_tlb *buf, unsigned int index,
622623
}
623624
EXPORT_SYMBOL_GPL(kvm_vz_load_guesttlb);
624625

626+
#ifdef CONFIG_CPU_LOONGSON64
627+
void kvm_loongson_clear_guest_vtlb(void)
628+
{
629+
int idx = read_gc0_index();
630+
631+
/* Set root GuestID for root probe and write of guest TLB entry */
632+
set_root_gid_to_guest_gid();
633+
634+
write_gc0_index(0);
635+
guest_tlbinvf();
636+
write_gc0_index(idx);
637+
638+
clear_root_gid();
639+
set_c0_diag(LOONGSON_DIAG_ITLB | LOONGSON_DIAG_DTLB);
640+
}
641+
EXPORT_SYMBOL_GPL(kvm_loongson_clear_guest_vtlb);
642+
643+
void kvm_loongson_clear_guest_ftlb(void)
644+
{
645+
int i;
646+
int idx = read_gc0_index();
647+
648+
/* Set root GuestID for root probe and write of guest TLB entry */
649+
set_root_gid_to_guest_gid();
650+
651+
for (i = current_cpu_data.tlbsizevtlb;
652+
i < (current_cpu_data.tlbsizevtlb +
653+
current_cpu_data.tlbsizeftlbsets);
654+
i++) {
655+
write_gc0_index(i);
656+
guest_tlbinvf();
657+
}
658+
write_gc0_index(idx);
659+
660+
clear_root_gid();
661+
set_c0_diag(LOONGSON_DIAG_ITLB | LOONGSON_DIAG_DTLB);
662+
}
663+
EXPORT_SYMBOL_GPL(kvm_loongson_clear_guest_ftlb);
664+
#endif
665+
625666
#endif
626667

627668
/**

arch/mips/kvm/vz.c

Lines changed: 61 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,11 @@ static inline unsigned int kvm_vz_config5_guest_wrmask(struct kvm_vcpu *vcpu)
127127
return mask;
128128
}
129129

130+
static inline unsigned int kvm_vz_config6_guest_wrmask(struct kvm_vcpu *vcpu)
131+
{
132+
return MIPS_CONF6_LOONGSON_INTIMER | MIPS_CONF6_LOONGSON_EXTIMER;
133+
}
134+
130135
/*
131136
* VZ optionally allows these additional Config bits to be written by root:
132137
* Config: M, [MT]
@@ -181,6 +186,12 @@ static inline unsigned int kvm_vz_config5_user_wrmask(struct kvm_vcpu *vcpu)
181186
return kvm_vz_config5_guest_wrmask(vcpu) | MIPS_CONF5_MRP;
182187
}
183188

189+
static inline unsigned int kvm_vz_config6_user_wrmask(struct kvm_vcpu *vcpu)
190+
{
191+
return kvm_vz_config6_guest_wrmask(vcpu) |
192+
MIPS_CONF6_LOONGSON_SFBEN | MIPS_CONF6_LOONGSON_FTLBDIS;
193+
}
194+
184195
static gpa_t kvm_vz_gva_to_gpa_cb(gva_t gva)
185196
{
186197
/* VZ guest has already converted gva to gpa */
@@ -930,14 +941,20 @@ static enum emulation_result kvm_vz_gpsi_cop0(union mips_instruction inst,
930941
(sel == 2 || /* SRSCtl */
931942
sel == 3)) || /* SRSMap */
932943
(rd == MIPS_CP0_CONFIG &&
933-
(sel == 7)) || /* Config7 */
944+
(sel == 6 || /* Config6 */
945+
sel == 7)) || /* Config7 */
934946
(rd == MIPS_CP0_LLADDR &&
935947
(sel == 2) && /* MAARI */
936948
cpu_guest_has_maar &&
937949
!cpu_guest_has_dyn_maar) ||
938950
(rd == MIPS_CP0_ERRCTL &&
939951
(sel == 0))) { /* ErrCtl */
940952
val = cop0->reg[rd][sel];
953+
#ifdef CONFIG_CPU_LOONGSON64
954+
} else if (rd == MIPS_CP0_DIAG &&
955+
(sel == 0)) { /* Diag */
956+
val = cop0->reg[rd][sel];
957+
#endif
941958
} else {
942959
val = 0;
943960
er = EMULATE_FAIL;
@@ -1000,9 +1017,40 @@ static enum emulation_result kvm_vz_gpsi_cop0(union mips_instruction inst,
10001017
cpu_guest_has_maar &&
10011018
!cpu_guest_has_dyn_maar) {
10021019
kvm_write_maari(vcpu, val);
1020+
} else if (rd == MIPS_CP0_CONFIG &&
1021+
(sel == 6)) {
1022+
cop0->reg[rd][sel] = (int)val;
10031023
} else if (rd == MIPS_CP0_ERRCTL &&
10041024
(sel == 0)) { /* ErrCtl */
10051025
/* ignore the written value */
1026+
#ifdef CONFIG_CPU_LOONGSON64
1027+
} else if (rd == MIPS_CP0_DIAG &&
1028+
(sel == 0)) { /* Diag */
1029+
unsigned long flags;
1030+
1031+
local_irq_save(flags);
1032+
if (val & LOONGSON_DIAG_BTB) {
1033+
/* Flush BTB */
1034+
set_c0_diag(LOONGSON_DIAG_BTB);
1035+
}
1036+
if (val & LOONGSON_DIAG_ITLB) {
1037+
/* Flush ITLB */
1038+
set_c0_diag(LOONGSON_DIAG_ITLB);
1039+
}
1040+
if (val & LOONGSON_DIAG_DTLB) {
1041+
/* Flush DTLB */
1042+
set_c0_diag(LOONGSON_DIAG_DTLB);
1043+
}
1044+
if (val & LOONGSON_DIAG_VTLB) {
1045+
/* Flush VTLB */
1046+
kvm_loongson_clear_guest_vtlb();
1047+
}
1048+
if (val & LOONGSON_DIAG_FTLB) {
1049+
/* Flush FTLB */
1050+
kvm_loongson_clear_guest_ftlb();
1051+
}
1052+
local_irq_restore(flags);
1053+
#endif
10061054
} else {
10071055
er = EMULATE_FAIL;
10081056
}
@@ -1692,6 +1740,7 @@ static u64 kvm_vz_get_one_regs[] = {
16921740
KVM_REG_MIPS_CP0_CONFIG3,
16931741
KVM_REG_MIPS_CP0_CONFIG4,
16941742
KVM_REG_MIPS_CP0_CONFIG5,
1743+
KVM_REG_MIPS_CP0_CONFIG6,
16951744
#ifdef CONFIG_64BIT
16961745
KVM_REG_MIPS_CP0_XCONTEXT,
16971746
#endif
@@ -2019,6 +2068,9 @@ static int kvm_vz_get_one_reg(struct kvm_vcpu *vcpu,
20192068
return -EINVAL;
20202069
*v = read_gc0_config5();
20212070
break;
2071+
case KVM_REG_MIPS_CP0_CONFIG6:
2072+
*v = kvm_read_sw_gc0_config6(cop0);
2073+
break;
20222074
case KVM_REG_MIPS_CP0_MAAR(0) ... KVM_REG_MIPS_CP0_MAAR(0x3f):
20232075
if (!cpu_guest_has_maar || cpu_guest_has_dyn_maar)
20242076
return -EINVAL;
@@ -2288,6 +2340,14 @@ static int kvm_vz_set_one_reg(struct kvm_vcpu *vcpu,
22882340
write_gc0_config5(v);
22892341
}
22902342
break;
2343+
case KVM_REG_MIPS_CP0_CONFIG6:
2344+
cur = kvm_read_sw_gc0_config6(cop0);
2345+
change = (cur ^ v) & kvm_vz_config6_user_wrmask(vcpu);
2346+
if (change) {
2347+
v = cur ^ change;
2348+
kvm_write_sw_gc0_config6(cop0, (int)v);
2349+
}
2350+
break;
22912351
case KVM_REG_MIPS_CP0_MAAR(0) ... KVM_REG_MIPS_CP0_MAAR(0x3f):
22922352
if (!cpu_guest_has_maar || cpu_guest_has_dyn_maar)
22932353
return -EINVAL;

0 commit comments

Comments
 (0)