Commit f3383cf8 authored by Alexander Graf's avatar Alexander Graf

KVM: PPC: Disable NX for old magic page using guests

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: default avatarAlexander Graf <agraf@suse.de>
parent 1f365bb0
...@@ -94,10 +94,24 @@ a bitmap of available features inside the magic page. ...@@ -94,10 +94,24 @@ a bitmap of available features inside the magic page.
The following enhancements to the magic page are currently available: 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_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 For enhanced features in the magic page, please check for the existence of the
feature before using them! 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 MSR bits
======== ========
......
...@@ -631,6 +631,7 @@ struct kvm_vcpu_arch { ...@@ -631,6 +631,7 @@ struct kvm_vcpu_arch {
#endif #endif
unsigned long magic_page_pa; /* phys addr to map the magic page to */ 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 */ 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_type; /* one of KVM_IRQ_* */
int irq_cpu_id; int irq_cpu_id;
......
...@@ -82,10 +82,16 @@ struct kvm_vcpu_arch_shared { ...@@ -82,10 +82,16 @@ struct kvm_vcpu_arch_shared {
#define KVM_FEATURE_MAGIC_PAGE 1 #define KVM_FEATURE_MAGIC_PAGE 1
/* Magic page flags from host to guest */
#define KVM_MAGIC_FEAT_SR (1 << 0) #define KVM_MAGIC_FEAT_SR (1 << 0)
/* MASn, ESR, PIR, and high SPRGs */ /* MASn, ESR, PIR, and high SPRGs */
#define KVM_MAGIC_FEAT_MAS0_TO_SPRG7 (1 << 1) #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__ */ #endif /* _UAPI__POWERPC_KVM_PARA_H__ */
...@@ -313,6 +313,9 @@ static int kvmppc_mmu_book3s_64_xlate(struct kvm_vcpu *vcpu, gva_t eaddr, ...@@ -313,6 +313,9 @@ static int kvmppc_mmu_book3s_64_xlate(struct kvm_vcpu *vcpu, gva_t eaddr,
gpte->raddr = (r & HPTE_R_RPN & ~eaddr_mask) | (eaddr & eaddr_mask); gpte->raddr = (r & HPTE_R_RPN & ~eaddr_mask) | (eaddr & eaddr_mask);
gpte->page_size = pgsize; gpte->page_size = pgsize;
gpte->may_execute = ((r & HPTE_R_N) ? false : true); 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_read = false;
gpte->may_write = false; gpte->may_write = false;
......
...@@ -177,8 +177,18 @@ int kvmppc_kvm_pv(struct kvm_vcpu *vcpu) ...@@ -177,8 +177,18 @@ int kvmppc_kvm_pv(struct kvm_vcpu *vcpu)
vcpu->arch.shared_big_endian = shared_big_endian; vcpu->arch.shared_big_endian = shared_big_endian;
#endif #endif
vcpu->arch.magic_page_pa = param1; if (!(param2 & MAGIC_PAGE_FLAG_NOT_MAPPED_NX)) {
vcpu->arch.magic_page_ea = param2; /*
* 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; r2 = KVM_MAGIC_FEAT_SR | KVM_MAGIC_FEAT_MAS0_TO_SPRG7;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment