* [PATCH 00/12] MIPS: KVM: 64-bit host support
@ 2016-07-08 10:53 James Hogan
2016-07-08 10:53 ` [PATCH 01/12] MIPS: Fix definition of KSEGX() for 64-bit James Hogan
` (11 more replies)
0 siblings, 12 replies; 17+ messages in thread
From: James Hogan @ 2016-07-08 10:53 UTC (permalink / raw)
To: Paolo Bonzini, Ralf Baechle
Cc: Radim Krčmář, James Hogan, Maciej W. Rozycki,
linux-mips, kvm
Add basic MIPS KVM support for 64-bit host kernels, primarily to prepare
for VZ support on MIPS64 processors. Note, this does not allow 64-bit
guests to be supported. This patchset is based on my recent r6 support
patchset.
Patches 1-11 fix various distinct parts of KVM MIPS that aren't portable
to a 64-bit host kernel, and patch 12 allows KVM to be enabled on such
kernels.
Only patches 1 & 12 touch anything outside of MIPS KVM. Patch 1 in
particular needs some imput from general MIPS folk.
James Hogan (12):
MIPS: Fix definition of KSEGX() for 64-bit
MIPS: KVM: Use virt_to_phys() to get commpage PFN
MIPS: KVM: Use kmap instead of CKSEG0ADDR()
MIPS: KVM: Make entry code MIPS64 friendly
MIPS: KVM: Set CP0_Status.KX on MIPS64
MIPS: KVM: Use 64-bit CP0_EBase when appropriate
MIPS: KVM: Fail if ebase doesn't fit in CP0_EBase
MIPS: KVM: Fix 64-bit big endian dynamic translation
MIPS: KVM: Sign extend MFC0/RDHWR results
MIPS: KVM: Fix ptr->int cast via KVM_GUEST_KSEGX()
MIPS: KVM: Reset CP0_PageMask during host TLB flush
MIPS: Select HAVE_KVM for MIPS64_R{2,6}
arch/mips/Kconfig | 2 +
arch/mips/include/asm/addrspace.h | 2 +-
arch/mips/kvm/dyntrans.c | 27 +++++++++----
arch/mips/kvm/emulate.c | 7 ++--
arch/mips/kvm/entry.c | 83 +++++++++++++++++++++++++--------------
arch/mips/kvm/mips.c | 12 ++++++
arch/mips/kvm/mmu.c | 7 +++-
arch/mips/kvm/tlb.c | 4 +-
8 files changed, 102 insertions(+), 42 deletions(-)
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: "Radim Krčmář" <rkrcmar@redhat.com>
Cc: Ralf Baechle <ralf@linux-mips.org>
Cc: Maciej W. Rozycki <macro@linux-mips.org>
Cc: linux-mips@linux-mips.org
Cc: kvm@vger.kernel.org
--
2.4.10
^ permalink raw reply [flat|nested] 17+ messages in thread* [PATCH 01/12] MIPS: Fix definition of KSEGX() for 64-bit 2016-07-08 10:53 [PATCH 00/12] MIPS: KVM: 64-bit host support James Hogan @ 2016-07-08 10:53 ` James Hogan 2016-07-11 14:56 ` Maciej W. Rozycki 2016-07-11 20:23 ` [PATCH v2 " James Hogan 2016-07-08 10:53 ` [PATCH 02/12] MIPS: KVM: Use virt_to_phys() to get commpage PFN James Hogan ` (10 subsequent siblings) 11 siblings, 2 replies; 17+ messages in thread From: James Hogan @ 2016-07-08 10:53 UTC (permalink / raw) To: Paolo Bonzini, Ralf Baechle Cc: Radim Krčmář, James Hogan, Maciej W. Rozycki, linux-mips The KSEGX() macro is defined to 32-bit sign extend the address argument and logically AND the result with 0xe0000000, with the final result usually compared against one of the CKSEG macros. However the literal 0xe0000000 is unsigned as the high bit is set, and is therefore zero-extended on 64-bit kernels, resulting in the sign extension bits of the argument being masked to zero. This results in the odd situation where: KSEGX(CKSEG) != CKSEG (0xffffffff80000000 & 0x00000000e0000000) != 0xffffffff80000000) Fix this by 32-bit sign extending the 0xe0000000 literal using _ACAST32_. This will help some MIPS KVM code handling 32-bit guest addresses to work on 64-bit host kernels, but will also affect KSEGX in dec_kn01_be_backend() on a 64-bit DECstation kernel, and the SiByte DMA page ops KSEGX check in clear_page() and copy_page() on 64-bit SB1 kernels, neither of which appear to be designed with 64-bit segments in mind anyway. Signed-off-by: James Hogan <james.hogan@imgtec.com> Cc: Ralf Baechle <ralf@linux-mips.org> Cc: Maciej W. Rozycki <macro@linux-mips.org> Cc: linux-mips@linux-mips.org --- For the SiByte optimisations in arch/mips/mm/page.c, the KSEGX condition looks slightly questionable anyway - is it acceptable to 32-bit sign extend the pointer in that case before the comparison. Currently the effect of the zero-extended 0xe0000000 is to prevent the optimisation from happening on 64-bit kernels. Will this patch cause breakage due to the pointer possibly being in some other 64-bit segment and the optimisation suddenly being enabled? As for the DEC bus error handling usage, it doesn't seem to take 64-bit addresses into account anyway (which get 32-bit sign extended by KSEGX). The effect of the zero-extended 0xe0000000 is to cause the TLB lookup code to always take place with no TLB presence check, which seems already broken. --- arch/mips/include/asm/addrspace.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/mips/include/asm/addrspace.h b/arch/mips/include/asm/addrspace.h index 3b0e51d5a613..c5b04e752e97 100644 --- a/arch/mips/include/asm/addrspace.h +++ b/arch/mips/include/asm/addrspace.h @@ -45,7 +45,7 @@ /* * Returns the kernel segment base of a given address */ -#define KSEGX(a) ((_ACAST32_ (a)) & 0xe0000000) +#define KSEGX(a) ((_ACAST32_(a)) & _ACAST32_(0xe0000000)) /* * Returns the physical address of a CKSEGx / XKPHYS address -- 2.4.10 ^ permalink raw reply related [flat|nested] 17+ messages in thread
* Re: [PATCH 01/12] MIPS: Fix definition of KSEGX() for 64-bit 2016-07-08 10:53 ` [PATCH 01/12] MIPS: Fix definition of KSEGX() for 64-bit James Hogan @ 2016-07-11 14:56 ` Maciej W. Rozycki 2016-07-11 19:03 ` James Hogan 2016-07-11 20:23 ` [PATCH v2 " James Hogan 1 sibling, 1 reply; 17+ messages in thread From: Maciej W. Rozycki @ 2016-07-11 14:56 UTC (permalink / raw) To: James Hogan Cc: Paolo Bonzini, Ralf Baechle, Radim Krčmář, linux-mips Hi James, > This will help some MIPS KVM code handling 32-bit guest addresses to > work on 64-bit host kernels, but will also affect KSEGX in > dec_kn01_be_backend() on a 64-bit DECstation kernel, and the SiByte DMA > page ops KSEGX check in clear_page() and copy_page() on 64-bit SB1 > kernels, neither of which appear to be designed with 64-bit segments in > mind anyway. Thanks for the heads-up! This is not an issue however with `dec_kn01_be_backend', because the KN01 baseboard used with the DECstation 2100 and 3100 computers has an R2000 processor mounted in a permanent manner (no CPU daugthercard as with some later baseboards) and will therefore never run a 64-bit kernel. In fact I think kn01-berr.c would best only be built in 32-bit configurations. I never got to making such a clean-up though; I may look into it sometime as I have some 2100/3100 stuff outstanding. As to the SiByte platform I have no clue offhand; there's surely some stuff there across the port asking for a clean-up. I reckon using the data mover for page ops is a kernel configuration option and I may have never enabled it myself. Maciej ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH 01/12] MIPS: Fix definition of KSEGX() for 64-bit 2016-07-11 14:56 ` Maciej W. Rozycki @ 2016-07-11 19:03 ` James Hogan 0 siblings, 0 replies; 17+ messages in thread From: James Hogan @ 2016-07-11 19:03 UTC (permalink / raw) To: Maciej W. Rozycki Cc: Paolo Bonzini, Ralf Baechle, Radim Krčmář, linux-mips [-- Attachment #1: Type: text/plain, Size: 1760 bytes --] Hi Maciej, On Mon, Jul 11, 2016 at 03:56:09PM +0100, Maciej W. Rozycki wrote: > Hi James, > > > This will help some MIPS KVM code handling 32-bit guest addresses to > > work on 64-bit host kernels, but will also affect KSEGX in > > dec_kn01_be_backend() on a 64-bit DECstation kernel, and the SiByte DMA > > page ops KSEGX check in clear_page() and copy_page() on 64-bit SB1 > > kernels, neither of which appear to be designed with 64-bit segments in > > mind anyway. > > Thanks for the heads-up! > > This is not an issue however with `dec_kn01_be_backend', because the KN01 > baseboard used with the DECstation 2100 and 3100 computers has an R2000 > processor mounted in a permanent manner (no CPU daugthercard as with some > later baseboards) and will therefore never run a 64-bit kernel. In fact I > think kn01-berr.c would best only be built in 32-bit configurations. I Okay thanks, good to know. > never got to making such a clean-up though; I may look into it sometime as > I have some 2100/3100 stuff outstanding. > > As to the SiByte platform I have no clue offhand; there's surely some > stuff there across the port asking for a clean-up. I reckon using the > data mover for page ops is a kernel configuration option and I may have > never enabled it myself. Indeed, one that defaults to no and isn't enabled in any defconfigs. I think I'll update this patch to make that configuration depend on 32BIT, just in case any physical addresses of RAM have bits 31:29 = 0b100, which previously would have failed the test and fallen back to a CPU copy, but with this change would have carried on and mistranslated the pointer to a physical address on the assumption its in KSeg0. Cheers James [-- Attachment #2: Digital signature --] [-- Type: application/pgp-signature, Size: 819 bytes --] ^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH v2 01/12] MIPS: Fix definition of KSEGX() for 64-bit 2016-07-08 10:53 ` [PATCH 01/12] MIPS: Fix definition of KSEGX() for 64-bit James Hogan 2016-07-11 14:56 ` Maciej W. Rozycki @ 2016-07-11 20:23 ` James Hogan 2016-07-15 14:19 ` Ralf Baechle 1 sibling, 1 reply; 17+ messages in thread From: James Hogan @ 2016-07-11 20:23 UTC (permalink / raw) To: Paolo Bonzini, Ralf Baechle Cc: Radim Krčmář, James Hogan, Maciej W. Rozycki, linux-mips The KSEGX() macro is defined to 32-bit sign extend the address argument and logically AND the result with 0xe0000000, with the final result usually compared against one of the CKSEG macros. However the literal 0xe0000000 is unsigned as the high bit is set, and is therefore zero-extended on 64-bit kernels, resulting in the sign extension bits of the argument being masked to zero. This results in the odd situation where: KSEGX(CKSEG0) != CKSEG0 (0xffffffff80000000 & 0x00000000e0000000) != 0xffffffff80000000) Fix this by 32-bit sign extending the 0xe0000000 literal using _ACAST32_. This will help some MIPS KVM code handling 32-bit guest addresses to work on 64-bit host kernels, but will also affect a couple of other users: - KSEGX in dec_kn01_be_backend() on a 64-bit DECstation kernel. Maciej has confirmed this is not a valid combination. - The SiByte DMA page ops KSEGX check in clear_page() and copy_page() on 64-bit SB1 kernels, which appears not to be designed with 64-bit segments in mind anyway. This would (perhaps unintentionally) have always fallen back to the CPU copy on 64-bit kernels anyway, so we make this explicit by making CONFIG_SIBYTE_DMA_PAGEOPS depend on 32BIT, so the change of KSEGX behaviour can't break anything. Signed-off-by: James Hogan <james.hogan@imgtec.com> Cc: Ralf Baechle <ralf@linux-mips.org> Cc: Maciej W. Rozycki <macro@linux-mips.org> Cc: linux-mips@linux-mips.org --- Changes in v2: - Clarify that the DEC code in question shouldn't get used with 64-bit kernels (thanks Maciej). - Make SIBYTE_DMA_PAGEOPS depend on 32BIT so the dependence is explicit and so we don't break anything. - Correct CKSEG -> CKSEG0 in patch description. --- arch/mips/Kconfig | 2 +- arch/mips/include/asm/addrspace.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index ac91939b9b75..86a9abd398f5 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -2195,7 +2195,7 @@ config RM7000_CPU_SCACHE config SIBYTE_DMA_PAGEOPS bool "Use DMA to clear/copy pages" - depends on CPU_SB1 + depends on CPU_SB1 && 32BIT help Instead of using the CPU to zero and copy pages, use a Data Mover channel. These DMA channels are otherwise unused by the standard diff --git a/arch/mips/include/asm/addrspace.h b/arch/mips/include/asm/addrspace.h index 3b0e51d5a613..c5b04e752e97 100644 --- a/arch/mips/include/asm/addrspace.h +++ b/arch/mips/include/asm/addrspace.h @@ -45,7 +45,7 @@ /* * Returns the kernel segment base of a given address */ -#define KSEGX(a) ((_ACAST32_ (a)) & 0xe0000000) +#define KSEGX(a) ((_ACAST32_(a)) & _ACAST32_(0xe0000000)) /* * Returns the physical address of a CKSEGx / XKPHYS address -- 2.4.10 ^ permalink raw reply related [flat|nested] 17+ messages in thread
* Re: [PATCH v2 01/12] MIPS: Fix definition of KSEGX() for 64-bit 2016-07-11 20:23 ` [PATCH v2 " James Hogan @ 2016-07-15 14:19 ` Ralf Baechle 0 siblings, 0 replies; 17+ messages in thread From: Ralf Baechle @ 2016-07-15 14:19 UTC (permalink / raw) To: James Hogan Cc: Paolo Bonzini, Radim Krčmář, Maciej W. Rozycki, linux-mips On Mon, Jul 11, 2016 at 09:23:40PM +0100, James Hogan wrote: > The KSEGX() macro is defined to 32-bit sign extend the address argument > and logically AND the result with 0xe0000000, with the final result > usually compared against one of the CKSEG macros. However the literal > 0xe0000000 is unsigned as the high bit is set, and is therefore > zero-extended on 64-bit kernels, resulting in the sign extension bits of > the argument being masked to zero. This results in the odd situation > where: > > KSEGX(CKSEG0) != CKSEG0 > (0xffffffff80000000 & 0x00000000e0000000) != 0xffffffff80000000) > > Fix this by 32-bit sign extending the 0xe0000000 literal using > _ACAST32_. > > This will help some MIPS KVM code handling 32-bit guest addresses to > work on 64-bit host kernels, but will also affect a couple of other > users: > > - KSEGX in dec_kn01_be_backend() on a 64-bit DECstation kernel. Maciej > has confirmed this is not a valid combination. > > - The SiByte DMA page ops KSEGX check in clear_page() and copy_page() on > 64-bit SB1 kernels, which appears not to be designed with 64-bit > segments in mind anyway. This would (perhaps unintentionally) have > always fallen back to the CPU copy on 64-bit kernels anyway, so we > make this explicit by making CONFIG_SIBYTE_DMA_PAGEOPS depend on > 32BIT, so the change of KSEGX behaviour can't break anything. > > Signed-off-by: James Hogan <james.hogan@imgtec.com> > Cc: Ralf Baechle <ralf@linux-mips.org> > Cc: Maciej W. Rozycki <macro@linux-mips.org> > Cc: linux-mips@linux-mips.org Acked-by: Ralf Baechle <ralf@linux-mips.org> Ralf ^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH 02/12] MIPS: KVM: Use virt_to_phys() to get commpage PFN 2016-07-08 10:53 [PATCH 00/12] MIPS: KVM: 64-bit host support James Hogan 2016-07-08 10:53 ` [PATCH 01/12] MIPS: Fix definition of KSEGX() for 64-bit James Hogan @ 2016-07-08 10:53 ` James Hogan 2016-07-08 10:53 ` [PATCH 03/12] MIPS: KVM: Use kmap instead of CKSEG0ADDR() James Hogan ` (9 subsequent siblings) 11 siblings, 0 replies; 17+ messages in thread From: James Hogan @ 2016-07-08 10:53 UTC (permalink / raw) To: Paolo Bonzini, Ralf Baechle Cc: Radim Krčmář, James Hogan, linux-mips, kvm Calculate the PFN of the commpage using virt_to_phys() instead of CPHYSADDR(). This is more portable as kzalloc() may allocate from XKPhys instead of KSeg0 on 64-bit kernels, which CPHYSADDR() doesn't handle. This is sufficient for highmem kernels too since kzalloc() will allocate from lowmem in KSeg0. 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 --- arch/mips/kvm/tlb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/mips/kvm/tlb.c b/arch/mips/kvm/tlb.c index 9699352293e4..f5f8c2acae53 100644 --- a/arch/mips/kvm/tlb.c +++ b/arch/mips/kvm/tlb.c @@ -176,7 +176,7 @@ int kvm_mips_handle_commpage_tlb_fault(unsigned long badvaddr, unsigned long entrylo[2] = { 0, 0 }; unsigned int pair_idx; - pfn = CPHYSADDR(vcpu->arch.kseg0_commpage) >> PAGE_SHIFT; + pfn = PFN_DOWN(virt_to_phys(vcpu->arch.kseg0_commpage)); pair_idx = (badvaddr >> PAGE_SHIFT) & 1; entrylo[pair_idx] = mips3_paddr_to_tlbpfn(pfn << PAGE_SHIFT) | ((_page_cachable_default >> _CACHE_SHIFT) << ENTRYLO_C_SHIFT) | -- 2.4.10 ^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH 03/12] MIPS: KVM: Use kmap instead of CKSEG0ADDR() 2016-07-08 10:53 [PATCH 00/12] MIPS: KVM: 64-bit host support James Hogan 2016-07-08 10:53 ` [PATCH 01/12] MIPS: Fix definition of KSEGX() for 64-bit James Hogan 2016-07-08 10:53 ` [PATCH 02/12] MIPS: KVM: Use virt_to_phys() to get commpage PFN James Hogan @ 2016-07-08 10:53 ` James Hogan 2016-07-08 10:53 ` [PATCH 04/12] MIPS: KVM: Make entry code MIPS64 friendly James Hogan ` (8 subsequent siblings) 11 siblings, 0 replies; 17+ messages in thread From: James Hogan @ 2016-07-08 10:53 UTC (permalink / raw) To: Paolo Bonzini, Ralf Baechle Cc: Radim Krčmář, James Hogan, linux-mips, kvm There are several unportable uses of CKSEG0ADDR() in MIPS KVM, which implicitly assume that a host physical address will be in the low 512MB of the physical address space (accessible in KSeg0). These assumptions don't hold for highmem or on 64-bit kernels. When interpreting the guest physical address when reading or overwriting a trapping instruction, use kmap_atomic() to get a usable virtual address to access guest memory, which is portable to 64-bit and highmem kernels. 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 --- arch/mips/kvm/dyntrans.c | 17 +++++++++++------ arch/mips/kvm/mmu.c | 7 ++++++- 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/arch/mips/kvm/dyntrans.c b/arch/mips/kvm/dyntrans.c index 91ebd2b6034f..9a16ba2cb487 100644 --- a/arch/mips/kvm/dyntrans.c +++ b/arch/mips/kvm/dyntrans.c @@ -11,6 +11,7 @@ #include <linux/errno.h> #include <linux/err.h> +#include <linux/highmem.h> #include <linux/kvm_host.h> #include <linux/module.h> #include <linux/vmalloc.h> @@ -29,14 +30,18 @@ static int kvm_mips_trans_replace(struct kvm_vcpu *vcpu, u32 *opc, union mips_instruction replace) { - unsigned long kseg0_opc, flags; + unsigned long paddr, flags; + void *vaddr; if (KVM_GUEST_KSEGX(opc) == KVM_GUEST_KSEG0) { - kseg0_opc = - CKSEG0ADDR(kvm_mips_translate_guest_kseg0_to_hpa - (vcpu, (unsigned long) opc)); - memcpy((void *)kseg0_opc, (void *)&replace, sizeof(u32)); - local_flush_icache_range(kseg0_opc, kseg0_opc + 32); + paddr = kvm_mips_translate_guest_kseg0_to_hpa(vcpu, + (unsigned long)opc); + vaddr = kmap_atomic(pfn_to_page(PHYS_PFN(paddr))); + vaddr += paddr & ~PAGE_MASK; + memcpy(vaddr, (void *)&replace, sizeof(u32)); + local_flush_icache_range((unsigned long)vaddr, + (unsigned long)vaddr + 32); + kunmap_atomic(vaddr); } else if (KVM_GUEST_KSEGX((unsigned long) opc) == KVM_GUEST_KSEG23) { local_irq_save(flags); memcpy((void *)opc, (void *)&replace, sizeof(u32)); diff --git a/arch/mips/kvm/mmu.c b/arch/mips/kvm/mmu.c index ecead748de04..57319ee57c4f 100644 --- a/arch/mips/kvm/mmu.c +++ b/arch/mips/kvm/mmu.c @@ -9,6 +9,7 @@ * Authors: Sanjay Lal <sanjayl@kymasys.com> */ +#include <linux/highmem.h> #include <linux/kvm_host.h> #include <asm/mmu_context.h> @@ -330,6 +331,7 @@ u32 kvm_get_inst(u32 *opc, struct kvm_vcpu *vcpu) struct mips_coproc *cop0 = vcpu->arch.cop0; unsigned long paddr, flags, vpn2, asid; unsigned long va = (unsigned long)opc; + void *vaddr; u32 inst; int index; @@ -360,7 +362,10 @@ u32 kvm_get_inst(u32 *opc, struct kvm_vcpu *vcpu) local_irq_restore(flags); } else if (KVM_GUEST_KSEGX(va) == KVM_GUEST_KSEG0) { paddr = kvm_mips_translate_guest_kseg0_to_hpa(vcpu, va); - inst = *(u32 *) CKSEG0ADDR(paddr); + vaddr = kmap_atomic(pfn_to_page(PHYS_PFN(paddr))); + vaddr += paddr & ~PAGE_MASK; + inst = *(u32 *)vaddr; + kunmap_atomic(vaddr); } else { kvm_err("%s: illegal address: %p\n", __func__, opc); return KVM_INVALID_INST; -- 2.4.10 ^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH 04/12] MIPS: KVM: Make entry code MIPS64 friendly 2016-07-08 10:53 [PATCH 00/12] MIPS: KVM: 64-bit host support James Hogan ` (2 preceding siblings ...) 2016-07-08 10:53 ` [PATCH 03/12] MIPS: KVM: Use kmap instead of CKSEG0ADDR() James Hogan @ 2016-07-08 10:53 ` James Hogan 2016-07-08 10:53 ` [PATCH 05/12] MIPS: KVM: Set CP0_Status.KX on MIPS64 James Hogan ` (7 subsequent siblings) 11 siblings, 0 replies; 17+ messages in thread From: James Hogan @ 2016-07-08 10:53 UTC (permalink / raw) To: Paolo Bonzini, Ralf Baechle Cc: Radim Krčmář, James Hogan, linux-mips, kvm The MIPS KVM entry code (originally kvm_locore.S, later locore.S, and now entry.c) has never quite been right when built for 64-bit, using 32-bit instructions when 64-bit instructions were needed for handling 64-bit registers and pointers. Fix several cases of this now. The changes roughly fall into the following categories. - COP0 scratch registers contain guest register values and the VCPU pointer, and are themselves full width. Similarly CP0_EPC and CP0_BadVAddr registers are full width (even though technically we don't support 64-bit guest address spaces with trap & emulate KVM). Use MFC0/MTC0 for accessing them. - Handling of stack pointers and the VCPU pointer must match the pointer size of the kernel ABI (always o32 or n64), so use ADDIU. - The CPU number in thread_info, and the guest_{user,kernel}_asid arrays in kvm_vcpu_arch are all 32 bit integers, so use lw (instead of LW) to load them. 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 --- arch/mips/kvm/entry.c | 48 ++++++++++++++++++++++++------------------------ 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/arch/mips/kvm/entry.c b/arch/mips/kvm/entry.c index 75ba7c2ecb3d..f4556d0279c6 100644 --- a/arch/mips/kvm/entry.c +++ b/arch/mips/kvm/entry.c @@ -120,12 +120,12 @@ static void kvm_mips_build_save_scratch(u32 **p, unsigned int tmp, unsigned int frame) { /* Save the VCPU scratch register value in cp0_epc of the stack frame */ - uasm_i_mfc0(p, tmp, scratch_vcpu[0], scratch_vcpu[1]); + UASM_i_MFC0(p, tmp, scratch_vcpu[0], scratch_vcpu[1]); UASM_i_SW(p, tmp, offsetof(struct pt_regs, cp0_epc), frame); /* Save the temp scratch register value in cp0_cause of stack frame */ if (scratch_tmp[0] == 31) { - uasm_i_mfc0(p, tmp, scratch_tmp[0], scratch_tmp[1]); + UASM_i_MFC0(p, tmp, scratch_tmp[0], scratch_tmp[1]); UASM_i_SW(p, tmp, offsetof(struct pt_regs, cp0_cause), frame); } } @@ -138,11 +138,11 @@ static void kvm_mips_build_restore_scratch(u32 **p, unsigned int tmp, * kvm_mips_build_save_scratch(). */ UASM_i_LW(p, tmp, offsetof(struct pt_regs, cp0_epc), frame); - uasm_i_mtc0(p, tmp, scratch_vcpu[0], scratch_vcpu[1]); + UASM_i_MTC0(p, tmp, scratch_vcpu[0], scratch_vcpu[1]); if (scratch_tmp[0] == 31) { UASM_i_LW(p, tmp, offsetof(struct pt_regs, cp0_cause), frame); - uasm_i_mtc0(p, tmp, scratch_tmp[0], scratch_tmp[1]); + UASM_i_MTC0(p, tmp, scratch_tmp[0], scratch_tmp[1]); } } @@ -171,7 +171,7 @@ void *kvm_mips_build_vcpu_run(void *addr) */ /* k0/k1 not being used in host kernel context */ - uasm_i_addiu(&p, K1, SP, -(int)sizeof(struct pt_regs)); + UASM_i_ADDIU(&p, K1, SP, -(int)sizeof(struct pt_regs)); for (i = 16; i < 32; ++i) { if (i == 24) i = 28; @@ -186,10 +186,10 @@ void *kvm_mips_build_vcpu_run(void *addr) kvm_mips_build_save_scratch(&p, V1, K1); /* VCPU scratch register has pointer to vcpu */ - uasm_i_mtc0(&p, A1, scratch_vcpu[0], scratch_vcpu[1]); + UASM_i_MTC0(&p, A1, scratch_vcpu[0], scratch_vcpu[1]); /* Offset into vcpu->arch */ - uasm_i_addiu(&p, K1, A1, offsetof(struct kvm_vcpu, arch)); + UASM_i_ADDIU(&p, K1, A1, offsetof(struct kvm_vcpu, arch)); /* * Save the host stack to VCPU, used for exception processing @@ -252,7 +252,7 @@ static void *kvm_mips_build_enter_guest(void *addr) /* Set Guest EPC */ UASM_i_LW(&p, T0, offsetof(struct kvm_vcpu_arch, pc), K1); - uasm_i_mtc0(&p, T0, C0_EPC); + UASM_i_MTC0(&p, T0, C0_EPC); /* Set the ASID for the Guest Kernel */ UASM_i_LW(&p, T0, offsetof(struct kvm_vcpu_arch, cop0), K1); @@ -261,20 +261,20 @@ static void *kvm_mips_build_enter_guest(void *addr) uasm_i_andi(&p, T0, T0, KSU_USER | ST0_ERL | ST0_EXL); uasm_i_xori(&p, T0, T0, KSU_USER); uasm_il_bnez(&p, &r, T0, label_kernel_asid); - uasm_i_addiu(&p, T1, K1, + UASM_i_ADDIU(&p, T1, K1, offsetof(struct kvm_vcpu_arch, guest_kernel_asid)); /* else user */ - uasm_i_addiu(&p, T1, K1, + UASM_i_ADDIU(&p, T1, K1, offsetof(struct kvm_vcpu_arch, guest_user_asid)); uasm_l_kernel_asid(&l, p); /* t1: contains the base of the ASID array, need to get the cpu id */ /* smp_processor_id */ - UASM_i_LW(&p, T2, offsetof(struct thread_info, cpu), GP); + uasm_i_lw(&p, T2, offsetof(struct thread_info, cpu), GP); /* x4 */ uasm_i_sll(&p, T2, T2, 2); UASM_i_ADDU(&p, T3, T1, T2); - UASM_i_LW(&p, K0, 0, T3); + uasm_i_lw(&p, K0, 0, T3); #ifdef CONFIG_MIPS_ASID_BITS_VARIABLE /* x sizeof(struct cpuinfo_mips)/4 */ uasm_i_addiu(&p, T3, ZERO, sizeof(struct cpuinfo_mips)/4); @@ -344,11 +344,11 @@ void *kvm_mips_build_exception(void *addr, void *handler) memset(relocs, 0, sizeof(relocs)); /* Save guest k1 into scratch register */ - uasm_i_mtc0(&p, K1, scratch_tmp[0], scratch_tmp[1]); + UASM_i_MTC0(&p, K1, scratch_tmp[0], scratch_tmp[1]); /* Get the VCPU pointer from the VCPU scratch register */ - uasm_i_mfc0(&p, K1, scratch_vcpu[0], scratch_vcpu[1]); - uasm_i_addiu(&p, K1, K1, offsetof(struct kvm_vcpu, arch)); + UASM_i_MFC0(&p, K1, scratch_vcpu[0], scratch_vcpu[1]); + UASM_i_ADDIU(&p, K1, K1, offsetof(struct kvm_vcpu, arch)); /* Save guest k0 into VCPU structure */ UASM_i_SW(&p, K0, offsetof(struct kvm_vcpu_arch, gprs[K0]), K1); @@ -415,13 +415,13 @@ void *kvm_mips_build_exit(void *addr) /* Finally save guest k1 to VCPU */ uasm_i_ehb(&p); - uasm_i_mfc0(&p, T0, scratch_tmp[0], scratch_tmp[1]); + UASM_i_MFC0(&p, T0, scratch_tmp[0], scratch_tmp[1]); UASM_i_SW(&p, T0, offsetof(struct kvm_vcpu_arch, gprs[K1]), K1); /* Now that context has been saved, we can use other registers */ /* Restore vcpu */ - uasm_i_mfc0(&p, A1, scratch_vcpu[0], scratch_vcpu[1]); + UASM_i_MFC0(&p, A1, scratch_vcpu[0], scratch_vcpu[1]); uasm_i_move(&p, S1, A1); /* Restore run (vcpu->run) */ @@ -433,10 +433,10 @@ void *kvm_mips_build_exit(void *addr) * Save Host level EPC, BadVaddr and Cause to VCPU, useful to process * the exception */ - uasm_i_mfc0(&p, K0, C0_EPC); + UASM_i_MFC0(&p, K0, C0_EPC); UASM_i_SW(&p, K0, offsetof(struct kvm_vcpu_arch, pc), K1); - uasm_i_mfc0(&p, K0, C0_BADVADDR); + UASM_i_MFC0(&p, K0, C0_BADVADDR); UASM_i_SW(&p, K0, offsetof(struct kvm_vcpu_arch, host_cp0_badvaddr), K1); @@ -506,7 +506,7 @@ void *kvm_mips_build_exit(void *addr) UASM_i_LW(&p, SP, offsetof(struct kvm_vcpu_arch, host_stack), K1); /* Saved host state */ - uasm_i_addiu(&p, SP, SP, -(int)sizeof(struct pt_regs)); + UASM_i_ADDIU(&p, SP, SP, -(int)sizeof(struct pt_regs)); /* * XXXKYMA do we need to load the host ASID, maybe not because the @@ -529,7 +529,7 @@ void *kvm_mips_build_exit(void *addr) */ UASM_i_LA(&p, T9, (unsigned long)kvm_mips_handle_exit); uasm_i_jalr(&p, RA, T9); - uasm_i_addiu(&p, SP, SP, -CALLFRAME_SIZ); + UASM_i_ADDIU(&p, SP, SP, -CALLFRAME_SIZ); uasm_resolve_relocs(relocs, labels); @@ -569,7 +569,7 @@ static void *kvm_mips_build_ret_from_exit(void *addr) */ uasm_i_move(&p, K1, S1); - uasm_i_addiu(&p, K1, K1, offsetof(struct kvm_vcpu, arch)); + UASM_i_ADDIU(&p, K1, K1, offsetof(struct kvm_vcpu, arch)); /* * Check return value, should tell us if we are returning to the @@ -603,7 +603,7 @@ static void *kvm_mips_build_ret_to_guest(void *addr) u32 *p = addr; /* Put the saved pointer to vcpu (s1) back into the scratch register */ - uasm_i_mtc0(&p, S1, scratch_vcpu[0], scratch_vcpu[1]); + UASM_i_MTC0(&p, S1, scratch_vcpu[0], scratch_vcpu[1]); /* Load up the Guest EBASE to minimize the window where BEV is set */ UASM_i_LW(&p, T0, offsetof(struct kvm_vcpu_arch, guest_ebase), K1); @@ -645,7 +645,7 @@ static void *kvm_mips_build_ret_to_host(void *addr) /* EBASE is already pointing to Linux */ UASM_i_LW(&p, K1, offsetof(struct kvm_vcpu_arch, host_stack), K1); - uasm_i_addiu(&p, K1, K1, -(int)sizeof(struct pt_regs)); + UASM_i_ADDIU(&p, K1, K1, -(int)sizeof(struct pt_regs)); /* * r2/v0 is the return code, shift it down by 2 (arithmetic) -- 2.4.10 ^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH 05/12] MIPS: KVM: Set CP0_Status.KX on MIPS64 2016-07-08 10:53 [PATCH 00/12] MIPS: KVM: 64-bit host support James Hogan ` (3 preceding siblings ...) 2016-07-08 10:53 ` [PATCH 04/12] MIPS: KVM: Make entry code MIPS64 friendly James Hogan @ 2016-07-08 10:53 ` James Hogan 2016-07-08 10:53 ` [PATCH 06/12] MIPS: KVM: Use 64-bit CP0_EBase when appropriate James Hogan ` (6 subsequent siblings) 11 siblings, 0 replies; 17+ messages in thread From: James Hogan @ 2016-07-08 10:53 UTC (permalink / raw) To: Paolo Bonzini, Ralf Baechle Cc: Radim Krčmář, James Hogan, linux-mips, kvm Update the KVM entry code to set the CP0_Entry.KX bit on 64-bit kernels. This is important to allow the entry code, running in kernel mode, to access the full 64-bit address space right up to the point of entering the guest, and immediately after exiting the guest, so it can safely restore & save the guest context from 64-bit segments. 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 --- arch/mips/kvm/entry.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/arch/mips/kvm/entry.c b/arch/mips/kvm/entry.c index f4556d0279c6..c824bfc4daa0 100644 --- a/arch/mips/kvm/entry.c +++ b/arch/mips/kvm/entry.c @@ -61,6 +61,12 @@ #define CALLFRAME_SIZ 32 +#ifdef CONFIG_64BIT +#define ST0_KX_IF_64 ST0_KX +#else +#define ST0_KX_IF_64 0 +#endif + static unsigned int scratch_vcpu[2] = { C0_DDATA_LO }; static unsigned int scratch_tmp[2] = { C0_ERROREPC }; @@ -204,7 +210,7 @@ void *kvm_mips_build_vcpu_run(void *addr) * Setup status register for running the guest in UM, interrupts * are disabled */ - UASM_i_LA(&p, K0, ST0_EXL | KSU_USER | ST0_BEV); + UASM_i_LA(&p, K0, ST0_EXL | KSU_USER | ST0_BEV | ST0_KX_IF_64); uasm_i_mtc0(&p, K0, C0_STATUS); uasm_i_ehb(&p); @@ -217,7 +223,7 @@ void *kvm_mips_build_vcpu_run(void *addr) * interrupt mask as it was but make sure that timer interrupts * are enabled */ - uasm_i_addiu(&p, K0, ZERO, ST0_EXL | KSU_USER | ST0_IE); + uasm_i_addiu(&p, K0, ZERO, ST0_EXL | KSU_USER | ST0_IE | ST0_KX_IF_64); uasm_i_andi(&p, V0, V0, ST0_IM); uasm_i_or(&p, K0, K0, V0); uasm_i_mtc0(&p, K0, C0_STATUS); -- 2.4.10 ^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH 06/12] MIPS: KVM: Use 64-bit CP0_EBase when appropriate 2016-07-08 10:53 [PATCH 00/12] MIPS: KVM: 64-bit host support James Hogan ` (4 preceding siblings ...) 2016-07-08 10:53 ` [PATCH 05/12] MIPS: KVM: Set CP0_Status.KX on MIPS64 James Hogan @ 2016-07-08 10:53 ` James Hogan 2016-07-08 10:53 ` [PATCH 07/12] MIPS: KVM: Fail if ebase doesn't fit in CP0_EBase James Hogan ` (5 subsequent siblings) 11 siblings, 0 replies; 17+ messages in thread From: James Hogan @ 2016-07-08 10:53 UTC (permalink / raw) To: Paolo Bonzini, Ralf Baechle Cc: Radim Krčmář, James Hogan, linux-mips, kvm Update the KVM entry point to write CP0_EBase as a 64-bit register when it is 64-bits wide, and to set the WG (write gate) bit if it exists in order to write bits 63:30 (or 31:30 on MIPS32). Prior to MIPS64r6 it was UNDEFINED to perform a 64-bit read or write of a 32-bit COP0 register. Since this is dynamically generated code, generate the right type of access depending on whether the kernel is 64-bit and cpu_has_ebase_wg. 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 --- arch/mips/kvm/entry.c | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/arch/mips/kvm/entry.c b/arch/mips/kvm/entry.c index c824bfc4daa0..6a02b3a3fa65 100644 --- a/arch/mips/kvm/entry.c +++ b/arch/mips/kvm/entry.c @@ -153,6 +153,25 @@ static void kvm_mips_build_restore_scratch(u32 **p, unsigned int tmp, } /** + * build_set_exc_base() - Assemble code to write exception base address. + * @p: Code buffer pointer. + * @reg: Source register (generated code may set WG bit in @reg). + * + * Assemble code to modify the exception base address in the EBase register, + * using the appropriately sized access and setting the WG bit if necessary. + */ +static inline void build_set_exc_base(u32 **p, unsigned int reg) +{ + if (cpu_has_ebase_wg) { + /* Set WG so that all the bits get written */ + uasm_i_ori(p, reg, reg, MIPS_EBASE_WG); + UASM_i_MTC0(p, reg, C0_EBASE); + } else { + uasm_i_mtc0(p, reg, C0_EBASE); + } +} + +/** * kvm_mips_build_vcpu_run() - Assemble function to start running a guest VCPU. * @addr: Address to start writing code. * @@ -216,7 +235,7 @@ void *kvm_mips_build_vcpu_run(void *addr) /* load up the new EBASE */ UASM_i_LW(&p, K0, offsetof(struct kvm_vcpu_arch, guest_ebase), K1); - uasm_i_mtc0(&p, K0, C0_EBASE); + build_set_exc_base(&p, K0); /* * Now that the new EBASE has been loaded, unset BEV, set @@ -463,7 +482,7 @@ void *kvm_mips_build_exit(void *addr) UASM_i_LA_mostly(&p, K0, (long)&ebase); UASM_i_LW(&p, K0, uasm_rel_lo((long)&ebase), K0); - uasm_i_mtc0(&p, K0, C0_EBASE); + build_set_exc_base(&p, K0); if (raw_cpu_has_fpu) { /* @@ -620,7 +639,7 @@ static void *kvm_mips_build_ret_to_guest(void *addr) uasm_i_or(&p, K0, V1, AT); uasm_i_mtc0(&p, K0, C0_STATUS); uasm_i_ehb(&p); - uasm_i_mtc0(&p, T0, C0_EBASE); + build_set_exc_base(&p, T0); /* Setup status register for running guest in UM */ uasm_i_ori(&p, V1, V1, ST0_EXL | KSU_USER | ST0_IE); -- 2.4.10 ^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH 07/12] MIPS: KVM: Fail if ebase doesn't fit in CP0_EBase 2016-07-08 10:53 [PATCH 00/12] MIPS: KVM: 64-bit host support James Hogan ` (5 preceding siblings ...) 2016-07-08 10:53 ` [PATCH 06/12] MIPS: KVM: Use 64-bit CP0_EBase when appropriate James Hogan @ 2016-07-08 10:53 ` James Hogan 2016-07-08 10:53 ` [PATCH 08/12] MIPS: KVM: Fix 64-bit big endian dynamic translation James Hogan ` (4 subsequent siblings) 11 siblings, 0 replies; 17+ messages in thread From: James Hogan @ 2016-07-08 10:53 UTC (permalink / raw) To: Paolo Bonzini, Ralf Baechle Cc: Radim Krčmář, James Hogan, linux-mips, kvm Fail if the address of the allocated exception base doesn't fit into the CP0_EBase register. This can happen on MIPS64 if CP0_EBase.WG isn't implemented but RAM is available outside of the range of KSeg0. 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 --- arch/mips/kvm/mips.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/arch/mips/kvm/mips.c b/arch/mips/kvm/mips.c index 0d11d9595600..f01c9ce885f5 100644 --- a/arch/mips/kvm/mips.c +++ b/arch/mips/kvm/mips.c @@ -300,6 +300,18 @@ struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm, unsigned int id) kvm_debug("Allocated %d bytes for KVM Exception Handlers @ %p\n", ALIGN(size, PAGE_SIZE), gebase); + /* + * Check new ebase actually fits in CP0_EBase. The lack of a write gate + * limits us to the low 512MB of physical address space. If the memory + * we allocate is out of range, just give up now. + */ + if (!cpu_has_ebase_wg && virt_to_phys(gebase) >= 0x20000000) { + kvm_err("CP0_EBase.WG required for guest exception base %pK\n", + gebase); + err = -ENOMEM; + goto out_free_gebase; + } + /* Save new ebase */ vcpu->arch.guest_ebase = gebase; -- 2.4.10 ^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH 08/12] MIPS: KVM: Fix 64-bit big endian dynamic translation 2016-07-08 10:53 [PATCH 00/12] MIPS: KVM: 64-bit host support James Hogan ` (6 preceding siblings ...) 2016-07-08 10:53 ` [PATCH 07/12] MIPS: KVM: Fail if ebase doesn't fit in CP0_EBase James Hogan @ 2016-07-08 10:53 ` James Hogan 2016-07-08 10:53 ` [PATCH 09/12] MIPS: KVM: Sign extend MFC0/RDHWR results James Hogan ` (3 subsequent siblings) 11 siblings, 0 replies; 17+ messages in thread From: James Hogan @ 2016-07-08 10:53 UTC (permalink / raw) To: Paolo Bonzini, Ralf Baechle Cc: Radim Krčmář, James Hogan, linux-mips, kvm The MFC0 and MTC0 instructions in the guest which cause traps can be replaced with 32-bit loads and stores to the commpage, however on big endian 64-bit builds the offset needs to have 4 added so as to load/store the least significant half of the long instead of the most significant half. 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 --- arch/mips/kvm/dyntrans.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/arch/mips/kvm/dyntrans.c b/arch/mips/kvm/dyntrans.c index 9a16ba2cb487..c793ff19a8a8 100644 --- a/arch/mips/kvm/dyntrans.c +++ b/arch/mips/kvm/dyntrans.c @@ -103,6 +103,10 @@ int kvm_mips_trans_mfc0(union mips_instruction inst, u32 *opc, mfc0_inst.i_format.rt = inst.c0r_format.rt; mfc0_inst.i_format.simmediate = KVM_GUEST_COMMPAGE_ADDR | offsetof(struct kvm_mips_commpage, cop0.reg[rd][sel]); +#ifdef CONFIG_CPU_BIG_ENDIAN + if (sizeof(vcpu->arch.cop0->reg[0][0]) == 8) + mfc0_inst.i_format.simmediate |= 4; +#endif } return kvm_mips_trans_replace(vcpu, opc, mfc0_inst); @@ -121,6 +125,10 @@ int kvm_mips_trans_mtc0(union mips_instruction inst, u32 *opc, mtc0_inst.i_format.rt = inst.c0r_format.rt; mtc0_inst.i_format.simmediate = KVM_GUEST_COMMPAGE_ADDR | offsetof(struct kvm_mips_commpage, cop0.reg[rd][sel]); +#ifdef CONFIG_CPU_BIG_ENDIAN + if (sizeof(vcpu->arch.cop0->reg[0][0]) == 8) + mtc0_inst.i_format.simmediate |= 4; +#endif return kvm_mips_trans_replace(vcpu, opc, mtc0_inst); } -- 2.4.10 ^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH 09/12] MIPS: KVM: Sign extend MFC0/RDHWR results 2016-07-08 10:53 [PATCH 00/12] MIPS: KVM: 64-bit host support James Hogan ` (7 preceding siblings ...) 2016-07-08 10:53 ` [PATCH 08/12] MIPS: KVM: Fix 64-bit big endian dynamic translation James Hogan @ 2016-07-08 10:53 ` James Hogan 2016-07-08 10:53 ` [PATCH 10/12] MIPS: KVM: Fix ptr->int cast via KVM_GUEST_KSEGX() James Hogan ` (2 subsequent siblings) 11 siblings, 0 replies; 17+ messages in thread From: James Hogan @ 2016-07-08 10:53 UTC (permalink / raw) To: Paolo Bonzini, Ralf Baechle Cc: Radim Krčmář, James Hogan, linux-mips, kvm When emulating MFC0 instructions to load 32-bit values from guest COP0 registers and the RDHWR instruction to read the CC (Count) register, sign extend the result to comply with the MIPS64 architecture. The result must be in canonical 32-bit form or the guest may malfunction. 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 --- arch/mips/kvm/emulate.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/arch/mips/kvm/emulate.c b/arch/mips/kvm/emulate.c index be18dfe9ecaa..6eb52b9c9818 100644 --- a/arch/mips/kvm/emulate.c +++ b/arch/mips/kvm/emulate.c @@ -1072,14 +1072,15 @@ enum emulation_result kvm_mips_emulate_CP0(union mips_instruction inst, #endif /* Get reg */ if ((rd == MIPS_CP0_COUNT) && (sel == 0)) { - vcpu->arch.gprs[rt] = kvm_mips_read_count(vcpu); + vcpu->arch.gprs[rt] = + (s32)kvm_mips_read_count(vcpu); } else if ((rd == MIPS_CP0_ERRCTL) && (sel == 0)) { vcpu->arch.gprs[rt] = 0x0; #ifdef CONFIG_KVM_MIPS_DYN_TRANS kvm_mips_trans_mfc0(inst, opc, vcpu); #endif } else { - vcpu->arch.gprs[rt] = cop0->reg[rd][sel]; + vcpu->arch.gprs[rt] = (s32)cop0->reg[rd][sel]; #ifdef CONFIG_KVM_MIPS_DYN_TRANS kvm_mips_trans_mfc0(inst, opc, vcpu); @@ -2380,7 +2381,7 @@ enum emulation_result kvm_mips_handle_ri(u32 cause, u32 *opc, current_cpu_data.icache.linesz); break; case MIPS_HWR_CC: /* Read count register */ - arch->gprs[rt] = kvm_mips_read_count(vcpu); + arch->gprs[rt] = (s32)kvm_mips_read_count(vcpu); break; case MIPS_HWR_CCRES: /* Count register resolution */ switch (current_cpu_data.cputype) { -- 2.4.10 ^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH 10/12] MIPS: KVM: Fix ptr->int cast via KVM_GUEST_KSEGX() 2016-07-08 10:53 [PATCH 00/12] MIPS: KVM: 64-bit host support James Hogan ` (8 preceding siblings ...) 2016-07-08 10:53 ` [PATCH 09/12] MIPS: KVM: Sign extend MFC0/RDHWR results James Hogan @ 2016-07-08 10:53 ` James Hogan 2016-07-08 10:53 ` [PATCH 11/12] MIPS: KVM: Reset CP0_PageMask during host TLB flush James Hogan 2016-07-08 10:53 ` [PATCH 12/12] MIPS: Select HAVE_KVM for MIPS64_R{2,6} James Hogan 11 siblings, 0 replies; 17+ messages in thread From: James Hogan @ 2016-07-08 10:53 UTC (permalink / raw) To: Paolo Bonzini, Ralf Baechle Cc: Radim Krčmář, James Hogan, linux-mips, kvm kvm_mips_trans_replace() passes a pointer to KVM_GUEST_KSEGX(). This breaks on 64-bit builds due to the cast of that 64-bit pointer to a different sized 32-bit int. Cast the pointer argument to an unsigned long to work around the warning. 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 --- arch/mips/kvm/dyntrans.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/mips/kvm/dyntrans.c b/arch/mips/kvm/dyntrans.c index c793ff19a8a8..d280894915ed 100644 --- a/arch/mips/kvm/dyntrans.c +++ b/arch/mips/kvm/dyntrans.c @@ -33,7 +33,7 @@ static int kvm_mips_trans_replace(struct kvm_vcpu *vcpu, u32 *opc, unsigned long paddr, flags; void *vaddr; - if (KVM_GUEST_KSEGX(opc) == KVM_GUEST_KSEG0) { + if (KVM_GUEST_KSEGX((unsigned long)opc) == KVM_GUEST_KSEG0) { paddr = kvm_mips_translate_guest_kseg0_to_hpa(vcpu, (unsigned long)opc); vaddr = kmap_atomic(pfn_to_page(PHYS_PFN(paddr))); -- 2.4.10 ^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH 11/12] MIPS: KVM: Reset CP0_PageMask during host TLB flush 2016-07-08 10:53 [PATCH 00/12] MIPS: KVM: 64-bit host support James Hogan ` (9 preceding siblings ...) 2016-07-08 10:53 ` [PATCH 10/12] MIPS: KVM: Fix ptr->int cast via KVM_GUEST_KSEGX() James Hogan @ 2016-07-08 10:53 ` James Hogan 2016-07-08 10:53 ` [PATCH 12/12] MIPS: Select HAVE_KVM for MIPS64_R{2,6} James Hogan 11 siblings, 0 replies; 17+ messages in thread From: James Hogan @ 2016-07-08 10:53 UTC (permalink / raw) To: Paolo Bonzini, Ralf Baechle Cc: Radim Krčmář, James Hogan, linux-mips, kvm KVM sometimes flushes host TLB entries, reading each one to check if it corresponds to a guest KSeg0 address. In the absence of EntryHi.EHInv bits to invalidate the whole entry, the entries will be set to unique virtual addresses in KSeg0 (which is not TLB mapped), spaced 2*PAGE_SIZE apart. The TLB read however will clobber the CP0_PageMask register with whatever page size that TLB entry had, and that same page size will be written back into the TLB entry along with the unique address. This would cause breakage when transparent huge pages are enabled on 64-bit host kernels, since huge page entries will overlap other nearby entries when separated by only 2*PAGE_SIZE, causing a machine check exception. Fix this by restoring the old CP0_PageMask value (which should be set to the normal page size) after reading the TLB entry if we're going to go ahead and invalidate it. 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 --- arch/mips/kvm/tlb.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/mips/kvm/tlb.c b/arch/mips/kvm/tlb.c index f5f8c2acae53..254377d8e0b9 100644 --- a/arch/mips/kvm/tlb.c +++ b/arch/mips/kvm/tlb.c @@ -332,6 +332,8 @@ void kvm_mips_flush_host_tlb(int skip_kseg0) /* Don't blow away guest kernel entries */ if (KVM_GUEST_KSEGX(entryhi) == KVM_GUEST_KSEG0) continue; + + write_c0_pagemask(old_pagemask); } /* Make sure all entries differ. */ -- 2.4.10 ^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH 12/12] MIPS: Select HAVE_KVM for MIPS64_R{2,6} 2016-07-08 10:53 [PATCH 00/12] MIPS: KVM: 64-bit host support James Hogan ` (10 preceding siblings ...) 2016-07-08 10:53 ` [PATCH 11/12] MIPS: KVM: Reset CP0_PageMask during host TLB flush James Hogan @ 2016-07-08 10:53 ` James Hogan 11 siblings, 0 replies; 17+ messages in thread From: James Hogan @ 2016-07-08 10:53 UTC (permalink / raw) To: Paolo Bonzini, Ralf Baechle Cc: Radim Krčmář, James Hogan, linux-mips, kvm We are now able to support KVM T&E with MIPS32 guests on some MIPS64r2 and MIPS64r6 hosts, so select HAVE_KVM so it can be enabled. Signed-off-by: James Hogan <james.hogan@imgtec.com> Cc: Ralf Baechle <ralf@linux-mips.org> Cc: Paolo Bonzini <pbonzini@redhat.com> Cc: "Radim Krčmář" <rkrcmar@redhat.com> Cc: linux-mips@linux-mips.org Cc: kvm@vger.kernel.org --- arch/mips/Kconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index ac91939b9b75..29867139851e 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -1488,6 +1488,7 @@ config CPU_MIPS64_R2 select CPU_SUPPORTS_HIGHMEM select CPU_SUPPORTS_HUGEPAGES select CPU_SUPPORTS_MSA + select HAVE_KVM help Choose this option to build a kernel for release 2 or later of the MIPS64 architecture. Many modern embedded systems with a 64-bit @@ -1505,6 +1506,7 @@ config CPU_MIPS64_R6 select CPU_SUPPORTS_MSA select GENERIC_CSUM select MIPS_O32_FP64_SUPPORT if MIPS32_O32 + select HAVE_KVM help Choose this option to build a kernel for release 6 or later of the MIPS64 architecture. New MIPS processors, starting with the Warrior -- 2.4.10 ^ permalink raw reply related [flat|nested] 17+ messages in thread
end of thread, other threads:[~2016-07-15 14:19 UTC | newest]
Thread overview: 17+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2016-07-08 10:53 [PATCH 00/12] MIPS: KVM: 64-bit host support James Hogan
2016-07-08 10:53 ` [PATCH 01/12] MIPS: Fix definition of KSEGX() for 64-bit James Hogan
2016-07-11 14:56 ` Maciej W. Rozycki
2016-07-11 19:03 ` James Hogan
2016-07-11 20:23 ` [PATCH v2 " James Hogan
2016-07-15 14:19 ` Ralf Baechle
2016-07-08 10:53 ` [PATCH 02/12] MIPS: KVM: Use virt_to_phys() to get commpage PFN James Hogan
2016-07-08 10:53 ` [PATCH 03/12] MIPS: KVM: Use kmap instead of CKSEG0ADDR() James Hogan
2016-07-08 10:53 ` [PATCH 04/12] MIPS: KVM: Make entry code MIPS64 friendly James Hogan
2016-07-08 10:53 ` [PATCH 05/12] MIPS: KVM: Set CP0_Status.KX on MIPS64 James Hogan
2016-07-08 10:53 ` [PATCH 06/12] MIPS: KVM: Use 64-bit CP0_EBase when appropriate James Hogan
2016-07-08 10:53 ` [PATCH 07/12] MIPS: KVM: Fail if ebase doesn't fit in CP0_EBase James Hogan
2016-07-08 10:53 ` [PATCH 08/12] MIPS: KVM: Fix 64-bit big endian dynamic translation James Hogan
2016-07-08 10:53 ` [PATCH 09/12] MIPS: KVM: Sign extend MFC0/RDHWR results James Hogan
2016-07-08 10:53 ` [PATCH 10/12] MIPS: KVM: Fix ptr->int cast via KVM_GUEST_KSEGX() James Hogan
2016-07-08 10:53 ` [PATCH 11/12] MIPS: KVM: Reset CP0_PageMask during host TLB flush James Hogan
2016-07-08 10:53 ` [PATCH 12/12] MIPS: Select HAVE_KVM for MIPS64_R{2,6} James Hogan
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox