]> git.karo-electronics.de Git - linux-beck.git/commitdiff
KVM: PPC: Disable NX for old magic page using guests
authorAlexander Graf <agraf@suse.de>
Sun, 11 May 2014 23:08:32 +0000 (01:08 +0200)
committerAlexander Graf <agraf@suse.de>
Fri, 30 May 2014 12:26:24 +0000 (14:26 +0200)
Old guests try to use the magic page, but map their trampoline code inside
of an NX region.

Since we can't fix those old kernels, try to detect whether the guest is sane
or not. If not, just disable NX functionality in KVM so that old guests at
least work at all. For newer guests, add a bit that we can set to keep NX
functionality available.

Signed-off-by: Alexander Graf <agraf@suse.de>
Documentation/virtual/kvm/ppc-pv.txt
arch/powerpc/include/asm/kvm_host.h
arch/powerpc/include/uapi/asm/kvm_para.h
arch/powerpc/kvm/book3s_64_mmu.c
arch/powerpc/kvm/powerpc.c

index 4643cde517c4a870b2ec4f97b517d6f566a8e303..319560646f3293020469c4cd2eddc5588cb2fac9 100644 (file)
@@ -94,10 +94,24 @@ a bitmap of available features inside the magic page.
 The following enhancements to the magic page are currently available:
 
   KVM_MAGIC_FEAT_SR            Maps SR registers r/w in the magic page
+  KVM_MAGIC_FEAT_MAS0_TO_SPRG7 Maps MASn, ESR, PIR and high SPRGs
 
 For enhanced features in the magic page, please check for the existence of the
 feature before using them!
 
+Magic page flags
+================
+
+In addition to features that indicate whether a host is capable of a particular
+feature we also have a channel for a guest to tell the guest whether it's capable
+of something. This is what we call "flags".
+
+Flags are passed to the host in the low 12 bits of the Effective Address.
+
+The following flags are currently available for a guest to expose:
+
+  MAGIC_PAGE_FLAG_NOT_MAPPED_NX Guest handles NX bits correclty wrt magic page
+
 MSR bits
 ========
 
index 29fbb554af5c8fed9ee9a76053e1fdcf17496f55..bb66d8b8efdf073fb2a54c39b9d1dd984be713cd 100644 (file)
@@ -631,6 +631,7 @@ struct kvm_vcpu_arch {
 #endif
        unsigned long magic_page_pa; /* phys addr to map the magic page to */
        unsigned long magic_page_ea; /* effect. addr to map the magic page to */
+       bool disable_kernel_nx;
 
        int irq_type;           /* one of KVM_IRQ_* */
        int irq_cpu_id;
index e3af3286a06801643a760fcbfa2afd116ad01053..91e42f09b323fac3199386eb58659f00e4fcdc7f 100644 (file)
@@ -82,10 +82,16 @@ struct kvm_vcpu_arch_shared {
 
 #define KVM_FEATURE_MAGIC_PAGE 1
 
+/* Magic page flags from host to guest */
+
 #define KVM_MAGIC_FEAT_SR              (1 << 0)
 
 /* MASn, ESR, PIR, and high SPRGs */
 #define KVM_MAGIC_FEAT_MAS0_TO_SPRG7   (1 << 1)
 
+/* Magic page flags from guest to host */
+
+#define MAGIC_PAGE_FLAG_NOT_MAPPED_NX  (1 << 0)
+
 
 #endif /* _UAPI__POWERPC_KVM_PARA_H__ */
index 278729f4df80a6e4d07b21a1f9b6187894cc6410..774a253ca4e1eaa2ab9c8277d22cbcae0d85f676 100644 (file)
@@ -313,6 +313,9 @@ do_second:
        gpte->raddr = (r & HPTE_R_RPN & ~eaddr_mask) | (eaddr & eaddr_mask);
        gpte->page_size = pgsize;
        gpte->may_execute = ((r & HPTE_R_N) ? false : true);
+       if (unlikely(vcpu->arch.disable_kernel_nx) &&
+           !(kvmppc_get_msr(vcpu) & MSR_PR))
+               gpte->may_execute = true;
        gpte->may_read = false;
        gpte->may_write = false;
 
index b4e15bf3ff88e4d624fc7b3af8031082ed244f4c..154f352c39ae42d0cf81ddc6f93ffb4df7456bc0 100644 (file)
@@ -177,8 +177,18 @@ int kvmppc_kvm_pv(struct kvm_vcpu *vcpu)
                vcpu->arch.shared_big_endian = shared_big_endian;
 #endif
 
-               vcpu->arch.magic_page_pa = param1;
-               vcpu->arch.magic_page_ea = param2;
+               if (!(param2 & MAGIC_PAGE_FLAG_NOT_MAPPED_NX)) {
+                       /*
+                        * Older versions of the Linux magic page code had
+                        * a bug where they would map their trampoline code
+                        * NX. If that's the case, remove !PR NX capability.
+                        */
+                       vcpu->arch.disable_kernel_nx = true;
+                       kvm_make_request(KVM_REQ_TLB_FLUSH, vcpu);
+               }
+
+               vcpu->arch.magic_page_pa = param1 & ~0xfffULL;
+               vcpu->arch.magic_page_ea = param2 & ~0xfffULL;
 
                r2 = KVM_MAGIC_FEAT_SR | KVM_MAGIC_FEAT_MAS0_TO_SPRG7;