MIPS: KVM: Abstract guest ASID mask
In preparation for supporting varied widths of ASID mask in the kernel in general, switch KVM's guest ASIDs to a new KVM_ENTRYHI_ASID definition based on the 8-bit MIPS_ENTRYHI_ASID instead of ASID_MASK. It could potentially be used to support extended guest ASIDs in the future. Signed-off-by: Paul Burton <paul.burton@imgtec.com> Signed-off-by: James Hogan <james.hogan@imgtec.com> Cc: Paolo Bonzini <pbonzini@redhat.com> Cc: Radim Krčmář <rkrcmar@redhat.com> Cc: linux-mips@linux-mips.org Cc: kvm@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/13207/ Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
This commit is contained in:
parent
9b5c339958
commit
ca64c2beec
|
@ -311,17 +311,18 @@ enum emulation_result {
|
||||||
#define MIPS3_PG_FRAME 0x3fffffc0
|
#define MIPS3_PG_FRAME 0x3fffffc0
|
||||||
|
|
||||||
#define VPN2_MASK 0xffffe000
|
#define VPN2_MASK 0xffffe000
|
||||||
|
#define KVM_ENTRYHI_ASID MIPS_ENTRYHI_ASID
|
||||||
#define TLB_IS_GLOBAL(x) (((x).tlb_lo0 & MIPS3_PG_G) && \
|
#define TLB_IS_GLOBAL(x) (((x).tlb_lo0 & MIPS3_PG_G) && \
|
||||||
((x).tlb_lo1 & MIPS3_PG_G))
|
((x).tlb_lo1 & MIPS3_PG_G))
|
||||||
#define TLB_VPN2(x) ((x).tlb_hi & VPN2_MASK)
|
#define TLB_VPN2(x) ((x).tlb_hi & VPN2_MASK)
|
||||||
#define TLB_ASID(x) ((x).tlb_hi & ASID_MASK)
|
#define TLB_ASID(x) ((x).tlb_hi & KVM_ENTRYHI_ASID)
|
||||||
#define TLB_IS_VALID(x, va) (((va) & (1 << PAGE_SHIFT)) \
|
#define TLB_IS_VALID(x, va) (((va) & (1 << PAGE_SHIFT)) \
|
||||||
? ((x).tlb_lo1 & MIPS3_PG_V) \
|
? ((x).tlb_lo1 & MIPS3_PG_V) \
|
||||||
: ((x).tlb_lo0 & MIPS3_PG_V))
|
: ((x).tlb_lo0 & MIPS3_PG_V))
|
||||||
#define TLB_HI_VPN2_HIT(x, y) ((TLB_VPN2(x) & ~(x).tlb_mask) == \
|
#define TLB_HI_VPN2_HIT(x, y) ((TLB_VPN2(x) & ~(x).tlb_mask) == \
|
||||||
((y) & VPN2_MASK & ~(x).tlb_mask))
|
((y) & VPN2_MASK & ~(x).tlb_mask))
|
||||||
#define TLB_HI_ASID_HIT(x, y) (TLB_IS_GLOBAL(x) || \
|
#define TLB_HI_ASID_HIT(x, y) (TLB_IS_GLOBAL(x) || \
|
||||||
TLB_ASID(x) == ((y) & ASID_MASK))
|
TLB_ASID(x) == ((y) & KVM_ENTRYHI_ASID))
|
||||||
|
|
||||||
struct kvm_mips_tlb {
|
struct kvm_mips_tlb {
|
||||||
long tlb_mask;
|
long tlb_mask;
|
||||||
|
|
|
@ -1068,15 +1068,15 @@ enum emulation_result kvm_mips_emulate_CP0(uint32_t inst, uint32_t *opc,
|
||||||
kvm_read_c0_guest_ebase(cop0));
|
kvm_read_c0_guest_ebase(cop0));
|
||||||
} else if (rd == MIPS_CP0_TLB_HI && sel == 0) {
|
} else if (rd == MIPS_CP0_TLB_HI && sel == 0) {
|
||||||
uint32_t nasid =
|
uint32_t nasid =
|
||||||
vcpu->arch.gprs[rt] & ASID_MASK;
|
vcpu->arch.gprs[rt] & KVM_ENTRYHI_ASID;
|
||||||
if ((KSEGX(vcpu->arch.gprs[rt]) != CKSEG0) &&
|
if ((KSEGX(vcpu->arch.gprs[rt]) != CKSEG0) &&
|
||||||
((kvm_read_c0_guest_entryhi(cop0) &
|
((kvm_read_c0_guest_entryhi(cop0) &
|
||||||
ASID_MASK) != nasid)) {
|
KVM_ENTRYHI_ASID) != nasid)) {
|
||||||
kvm_debug("MTCz, change ASID from %#lx to %#lx\n",
|
kvm_debug("MTCz, change ASID from %#lx to %#lx\n",
|
||||||
kvm_read_c0_guest_entryhi(cop0)
|
kvm_read_c0_guest_entryhi(cop0)
|
||||||
& ASID_MASK,
|
& KVM_ENTRYHI_ASID,
|
||||||
vcpu->arch.gprs[rt]
|
vcpu->arch.gprs[rt]
|
||||||
& ASID_MASK);
|
& KVM_ENTRYHI_ASID);
|
||||||
|
|
||||||
/* Blow away the shadow host TLBs */
|
/* Blow away the shadow host TLBs */
|
||||||
kvm_mips_flush_host_tlb(1);
|
kvm_mips_flush_host_tlb(1);
|
||||||
|
@ -1620,7 +1620,7 @@ enum emulation_result kvm_mips_emulate_cache(uint32_t inst, uint32_t *opc,
|
||||||
*/
|
*/
|
||||||
index = kvm_mips_guest_tlb_lookup(vcpu, (va & VPN2_MASK) |
|
index = kvm_mips_guest_tlb_lookup(vcpu, (va & VPN2_MASK) |
|
||||||
(kvm_read_c0_guest_entryhi
|
(kvm_read_c0_guest_entryhi
|
||||||
(cop0) & ASID_MASK));
|
(cop0) & KVM_ENTRYHI_ASID));
|
||||||
|
|
||||||
if (index < 0) {
|
if (index < 0) {
|
||||||
vcpu->arch.host_cp0_entryhi = (va & VPN2_MASK);
|
vcpu->arch.host_cp0_entryhi = (va & VPN2_MASK);
|
||||||
|
@ -1786,7 +1786,7 @@ enum emulation_result kvm_mips_emulate_tlbmiss_ld(unsigned long cause,
|
||||||
struct mips_coproc *cop0 = vcpu->arch.cop0;
|
struct mips_coproc *cop0 = vcpu->arch.cop0;
|
||||||
struct kvm_vcpu_arch *arch = &vcpu->arch;
|
struct kvm_vcpu_arch *arch = &vcpu->arch;
|
||||||
unsigned long entryhi = (vcpu->arch. host_cp0_badvaddr & VPN2_MASK) |
|
unsigned long entryhi = (vcpu->arch. host_cp0_badvaddr & VPN2_MASK) |
|
||||||
(kvm_read_c0_guest_entryhi(cop0) & ASID_MASK);
|
(kvm_read_c0_guest_entryhi(cop0) & KVM_ENTRYHI_ASID);
|
||||||
|
|
||||||
if ((kvm_read_c0_guest_status(cop0) & ST0_EXL) == 0) {
|
if ((kvm_read_c0_guest_status(cop0) & ST0_EXL) == 0) {
|
||||||
/* save old pc */
|
/* save old pc */
|
||||||
|
@ -1833,7 +1833,7 @@ enum emulation_result kvm_mips_emulate_tlbinv_ld(unsigned long cause,
|
||||||
struct kvm_vcpu_arch *arch = &vcpu->arch;
|
struct kvm_vcpu_arch *arch = &vcpu->arch;
|
||||||
unsigned long entryhi =
|
unsigned long entryhi =
|
||||||
(vcpu->arch.host_cp0_badvaddr & VPN2_MASK) |
|
(vcpu->arch.host_cp0_badvaddr & VPN2_MASK) |
|
||||||
(kvm_read_c0_guest_entryhi(cop0) & ASID_MASK);
|
(kvm_read_c0_guest_entryhi(cop0) & KVM_ENTRYHI_ASID);
|
||||||
|
|
||||||
if ((kvm_read_c0_guest_status(cop0) & ST0_EXL) == 0) {
|
if ((kvm_read_c0_guest_status(cop0) & ST0_EXL) == 0) {
|
||||||
/* save old pc */
|
/* save old pc */
|
||||||
|
@ -1878,7 +1878,7 @@ enum emulation_result kvm_mips_emulate_tlbmiss_st(unsigned long cause,
|
||||||
struct mips_coproc *cop0 = vcpu->arch.cop0;
|
struct mips_coproc *cop0 = vcpu->arch.cop0;
|
||||||
struct kvm_vcpu_arch *arch = &vcpu->arch;
|
struct kvm_vcpu_arch *arch = &vcpu->arch;
|
||||||
unsigned long entryhi = (vcpu->arch.host_cp0_badvaddr & VPN2_MASK) |
|
unsigned long entryhi = (vcpu->arch.host_cp0_badvaddr & VPN2_MASK) |
|
||||||
(kvm_read_c0_guest_entryhi(cop0) & ASID_MASK);
|
(kvm_read_c0_guest_entryhi(cop0) & KVM_ENTRYHI_ASID);
|
||||||
|
|
||||||
if ((kvm_read_c0_guest_status(cop0) & ST0_EXL) == 0) {
|
if ((kvm_read_c0_guest_status(cop0) & ST0_EXL) == 0) {
|
||||||
/* save old pc */
|
/* save old pc */
|
||||||
|
@ -1922,7 +1922,7 @@ enum emulation_result kvm_mips_emulate_tlbinv_st(unsigned long cause,
|
||||||
struct mips_coproc *cop0 = vcpu->arch.cop0;
|
struct mips_coproc *cop0 = vcpu->arch.cop0;
|
||||||
struct kvm_vcpu_arch *arch = &vcpu->arch;
|
struct kvm_vcpu_arch *arch = &vcpu->arch;
|
||||||
unsigned long entryhi = (vcpu->arch.host_cp0_badvaddr & VPN2_MASK) |
|
unsigned long entryhi = (vcpu->arch.host_cp0_badvaddr & VPN2_MASK) |
|
||||||
(kvm_read_c0_guest_entryhi(cop0) & ASID_MASK);
|
(kvm_read_c0_guest_entryhi(cop0) & KVM_ENTRYHI_ASID);
|
||||||
|
|
||||||
if ((kvm_read_c0_guest_status(cop0) & ST0_EXL) == 0) {
|
if ((kvm_read_c0_guest_status(cop0) & ST0_EXL) == 0) {
|
||||||
/* save old pc */
|
/* save old pc */
|
||||||
|
@ -1967,7 +1967,7 @@ enum emulation_result kvm_mips_handle_tlbmod(unsigned long cause, uint32_t *opc,
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
struct mips_coproc *cop0 = vcpu->arch.cop0;
|
struct mips_coproc *cop0 = vcpu->arch.cop0;
|
||||||
unsigned long entryhi = (vcpu->arch.host_cp0_badvaddr & VPN2_MASK) |
|
unsigned long entryhi = (vcpu->arch.host_cp0_badvaddr & VPN2_MASK) |
|
||||||
(kvm_read_c0_guest_entryhi(cop0) & ASID_MASK);
|
(kvm_read_c0_guest_entryhi(cop0) & KVM_ENTRYHI_ASID);
|
||||||
int index;
|
int index;
|
||||||
|
|
||||||
/* If address not in the guest TLB, then we are in trouble */
|
/* If address not in the guest TLB, then we are in trouble */
|
||||||
|
@ -1994,7 +1994,7 @@ enum emulation_result kvm_mips_emulate_tlbmod(unsigned long cause,
|
||||||
{
|
{
|
||||||
struct mips_coproc *cop0 = vcpu->arch.cop0;
|
struct mips_coproc *cop0 = vcpu->arch.cop0;
|
||||||
unsigned long entryhi = (vcpu->arch.host_cp0_badvaddr & VPN2_MASK) |
|
unsigned long entryhi = (vcpu->arch.host_cp0_badvaddr & VPN2_MASK) |
|
||||||
(kvm_read_c0_guest_entryhi(cop0) & ASID_MASK);
|
(kvm_read_c0_guest_entryhi(cop0) & KVM_ENTRYHI_ASID);
|
||||||
struct kvm_vcpu_arch *arch = &vcpu->arch;
|
struct kvm_vcpu_arch *arch = &vcpu->arch;
|
||||||
|
|
||||||
if ((kvm_read_c0_guest_status(cop0) & ST0_EXL) == 0) {
|
if ((kvm_read_c0_guest_status(cop0) & ST0_EXL) == 0) {
|
||||||
|
@ -2569,7 +2569,8 @@ enum emulation_result kvm_mips_handle_tlbmiss(unsigned long cause,
|
||||||
*/
|
*/
|
||||||
index = kvm_mips_guest_tlb_lookup(vcpu,
|
index = kvm_mips_guest_tlb_lookup(vcpu,
|
||||||
(va & VPN2_MASK) |
|
(va & VPN2_MASK) |
|
||||||
(kvm_read_c0_guest_entryhi(vcpu->arch.cop0) & ASID_MASK));
|
(kvm_read_c0_guest_entryhi(vcpu->arch.cop0) &
|
||||||
|
KVM_ENTRYHI_ASID));
|
||||||
if (index < 0) {
|
if (index < 0) {
|
||||||
if (exccode == EXCCODE_TLBL) {
|
if (exccode == EXCCODE_TLBL) {
|
||||||
er = kvm_mips_emulate_tlbmiss_ld(cause, opc, run, vcpu);
|
er = kvm_mips_emulate_tlbmiss_ld(cause, opc, run, vcpu);
|
||||||
|
|
|
@ -748,7 +748,8 @@ uint32_t kvm_get_inst(uint32_t *opc, struct kvm_vcpu *vcpu)
|
||||||
inst = *(opc);
|
inst = *(opc);
|
||||||
} else {
|
} else {
|
||||||
vpn2 = (unsigned long) opc & VPN2_MASK;
|
vpn2 = (unsigned long) opc & VPN2_MASK;
|
||||||
asid = kvm_read_c0_guest_entryhi(cop0) & ASID_MASK;
|
asid = kvm_read_c0_guest_entryhi(cop0) &
|
||||||
|
KVM_ENTRYHI_ASID;
|
||||||
index = kvm_mips_guest_tlb_lookup(vcpu, vpn2 | asid);
|
index = kvm_mips_guest_tlb_lookup(vcpu, vpn2 | asid);
|
||||||
if (index < 0) {
|
if (index < 0) {
|
||||||
kvm_err("%s: get_user_failed for %p, vcpu: %p, ASID: %#lx\n",
|
kvm_err("%s: get_user_failed for %p, vcpu: %p, ASID: %#lx\n",
|
||||||
|
|
Loading…
Reference in New Issue