* [PATCH 02/26] KVM: PPC: Convert MSR to shared page
2010-06-25 23:24 ` Alexander Graf
(?)
@ 2010-06-25 23:24 ` Alexander Graf
-1 siblings, 0 replies; 227+ messages in thread
From: Alexander Graf @ 2010-06-25 23:24 UTC (permalink / raw)
To: kvm-ppc-u79uwXL29TY76Z2rM5mHXA; +Cc: KVM list, linuxppc-dev
One of the most obvious registers to share with the guest directly is the
MSR. The MSR contains the "interrupts enabled" flag which the guest has to
toggle in critical sections.
So in order to bring the overhead of interrupt en- and disabling down, let's
put msr into the shared page. Keep in mind that even though you can fully read
its contents, writing to it doesn't always update all state. There are a few
safe fields that don't require hypervisor interaction. See the guest
implementation that follows later for reference.
Signed-off-by: Alexander Graf <agraf@suse.de>
---
arch/powerpc/include/asm/kvm_host.h | 1 -
arch/powerpc/include/asm/kvm_para.h | 1 +
arch/powerpc/kernel/asm-offsets.c | 2 +-
arch/powerpc/kvm/44x_tlb.c | 8 ++--
arch/powerpc/kvm/book3s.c | 65 ++++++++++++++++--------------
arch/powerpc/kvm/book3s_32_mmu.c | 12 +++---
arch/powerpc/kvm/book3s_32_mmu_host.c | 4 +-
arch/powerpc/kvm/book3s_64_mmu.c | 12 +++---
arch/powerpc/kvm/book3s_64_mmu_host.c | 4 +-
arch/powerpc/kvm/book3s_emulate.c | 9 ++--
arch/powerpc/kvm/book3s_paired_singles.c | 7 ++-
arch/powerpc/kvm/booke.c | 20 +++++-----
arch/powerpc/kvm/booke.h | 6 +-
arch/powerpc/kvm/booke_emulate.c | 6 +-
arch/powerpc/kvm/booke_interrupts.S | 3 +-
arch/powerpc/kvm/e500_tlb.c | 12 +++---
arch/powerpc/kvm/e500_tlb.h | 2 +-
arch/powerpc/kvm/powerpc.c | 3 +-
18 files changed, 93 insertions(+), 84 deletions(-)
diff --git a/arch/powerpc/include/asm/kvm_host.h b/arch/powerpc/include/asm/kvm_host.h
index bca9391..249c242 100644
--- a/arch/powerpc/include/asm/kvm_host.h
+++ b/arch/powerpc/include/asm/kvm_host.h
@@ -210,7 +210,6 @@ struct kvm_vcpu_arch {
u32 cr;
#endif
- ulong msr;
#ifdef CONFIG_PPC_BOOK3S
ulong shadow_msr;
ulong hflags;
diff --git a/arch/powerpc/include/asm/kvm_para.h b/arch/powerpc/include/asm/kvm_para.h
index 1485ba8..a17dc52 100644
--- a/arch/powerpc/include/asm/kvm_para.h
+++ b/arch/powerpc/include/asm/kvm_para.h
@@ -23,6 +23,7 @@
#include <linux/types.h>
struct kvm_vcpu_arch_shared {
+ __u64 msr;
};
#ifdef __KERNEL__
diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c
index 944f593..a55d47e 100644
--- a/arch/powerpc/kernel/asm-offsets.c
+++ b/arch/powerpc/kernel/asm-offsets.c
@@ -394,13 +394,13 @@ int main(void)
DEFINE(VCPU_HOST_STACK, offsetof(struct kvm_vcpu, arch.host_stack));
DEFINE(VCPU_HOST_PID, offsetof(struct kvm_vcpu, arch.host_pid));
DEFINE(VCPU_GPRS, offsetof(struct kvm_vcpu, arch.gpr));
- DEFINE(VCPU_MSR, offsetof(struct kvm_vcpu, arch.msr));
DEFINE(VCPU_SPRG4, offsetof(struct kvm_vcpu, arch.sprg4));
DEFINE(VCPU_SPRG5, offsetof(struct kvm_vcpu, arch.sprg5));
DEFINE(VCPU_SPRG6, offsetof(struct kvm_vcpu, arch.sprg6));
DEFINE(VCPU_SPRG7, offsetof(struct kvm_vcpu, arch.sprg7));
DEFINE(VCPU_SHADOW_PID, offsetof(struct kvm_vcpu, arch.shadow_pid));
DEFINE(VCPU_SHARED, offsetof(struct kvm_vcpu, arch.shared));
+ DEFINE(VCPU_SHARED_MSR, offsetof(struct kvm_vcpu_arch_shared, msr));
/* book3s */
#ifdef CONFIG_PPC_BOOK3S
diff --git a/arch/powerpc/kvm/44x_tlb.c b/arch/powerpc/kvm/44x_tlb.c
index 8123125..4cbbca7 100644
--- a/arch/powerpc/kvm/44x_tlb.c
+++ b/arch/powerpc/kvm/44x_tlb.c
@@ -221,14 +221,14 @@ gpa_t kvmppc_mmu_xlate(struct kvm_vcpu *vcpu, unsigned int gtlb_index,
int kvmppc_mmu_itlb_index(struct kvm_vcpu *vcpu, gva_t eaddr)
{
- unsigned int as = !!(vcpu->arch.msr & MSR_IS);
+ unsigned int as = !!(vcpu->arch.shared->msr & MSR_IS);
return kvmppc_44x_tlb_index(vcpu, eaddr, vcpu->arch.pid, as);
}
int kvmppc_mmu_dtlb_index(struct kvm_vcpu *vcpu, gva_t eaddr)
{
- unsigned int as = !!(vcpu->arch.msr & MSR_DS);
+ unsigned int as = !!(vcpu->arch.shared->msr & MSR_DS);
return kvmppc_44x_tlb_index(vcpu, eaddr, vcpu->arch.pid, as);
}
@@ -353,7 +353,7 @@ void kvmppc_mmu_map(struct kvm_vcpu *vcpu, u64 gvaddr, gpa_t gpaddr,
stlbe.word1 = (hpaddr & 0xfffffc00) | ((hpaddr >> 32) & 0xf);
stlbe.word2 = kvmppc_44x_tlb_shadow_attrib(flags,
- vcpu->arch.msr & MSR_PR);
+ vcpu->arch.shared->msr & MSR_PR);
stlbe.tid = !(asid & 0xff);
/* Keep track of the reference so we can properly release it later. */
@@ -422,7 +422,7 @@ static int tlbe_is_host_safe(const struct kvm_vcpu *vcpu,
/* Does it match current guest AS? */
/* XXX what about IS != DS? */
- if (get_tlb_ts(tlbe) != !!(vcpu->arch.msr & MSR_IS))
+ if (get_tlb_ts(tlbe) != !!(vcpu->arch.shared->msr & MSR_IS))
return 0;
gpa = get_tlb_raddr(tlbe);
diff --git a/arch/powerpc/kvm/book3s.c b/arch/powerpc/kvm/book3s.c
index ba79b35..3dd3003 100644
--- a/arch/powerpc/kvm/book3s.c
+++ b/arch/powerpc/kvm/book3s.c
@@ -115,31 +115,31 @@ static u32 kvmppc_get_dec(struct kvm_vcpu *vcpu)
static void kvmppc_recalc_shadow_msr(struct kvm_vcpu *vcpu)
{
- vcpu->arch.shadow_msr = vcpu->arch.msr;
+ ulong smsr = vcpu->arch.shared->msr;
+
/* Guest MSR values */
- vcpu->arch.shadow_msr &= MSR_FE0 | MSR_FE1 | MSR_SF | MSR_SE |
- MSR_BE | MSR_DE;
+ smsr &= MSR_FE0 | MSR_FE1 | MSR_SF | MSR_SE | MSR_BE | MSR_DE;
/* Process MSR values */
- vcpu->arch.shadow_msr |= MSR_ME | MSR_RI | MSR_IR | MSR_DR | MSR_PR |
- MSR_EE;
+ smsr |= MSR_ME | MSR_RI | MSR_IR | MSR_DR | MSR_PR | MSR_EE;
/* External providers the guest reserved */
- vcpu->arch.shadow_msr |= (vcpu->arch.msr & vcpu->arch.guest_owned_ext);
+ smsr |= (vcpu->arch.shared->msr & vcpu->arch.guest_owned_ext);
/* 64-bit Process MSR values */
#ifdef CONFIG_PPC_BOOK3S_64
- vcpu->arch.shadow_msr |= MSR_ISF | MSR_HV;
+ smsr |= MSR_ISF | MSR_HV;
#endif
+ vcpu->arch.shadow_msr = smsr;
}
void kvmppc_set_msr(struct kvm_vcpu *vcpu, u64 msr)
{
- ulong old_msr = vcpu->arch.msr;
+ ulong old_msr = vcpu->arch.shared->msr;
#ifdef EXIT_DEBUG
printk(KERN_INFO "KVM: Set MSR to 0x%llx\n", msr);
#endif
msr &= to_book3s(vcpu)->msr_mask;
- vcpu->arch.msr = msr;
+ vcpu->arch.shared->msr = msr;
kvmppc_recalc_shadow_msr(vcpu);
if (msr & (MSR_WE|MSR_POW)) {
@@ -149,21 +149,21 @@ void kvmppc_set_msr(struct kvm_vcpu *vcpu, u64 msr)
}
}
- if ((vcpu->arch.msr & (MSR_PR|MSR_IR|MSR_DR)) !+ if ((vcpu->arch.shared->msr & (MSR_PR|MSR_IR|MSR_DR)) ! (old_msr & (MSR_PR|MSR_IR|MSR_DR))) {
kvmppc_mmu_flush_segments(vcpu);
kvmppc_mmu_map_segment(vcpu, kvmppc_get_pc(vcpu));
}
/* Preload FPU if it's enabled */
- if (vcpu->arch.msr & MSR_FP)
+ if (vcpu->arch.shared->msr & MSR_FP)
kvmppc_handle_ext(vcpu, BOOK3S_INTERRUPT_FP_UNAVAIL, MSR_FP);
}
void kvmppc_inject_interrupt(struct kvm_vcpu *vcpu, int vec, u64 flags)
{
vcpu->arch.srr0 = kvmppc_get_pc(vcpu);
- vcpu->arch.srr1 = vcpu->arch.msr | flags;
+ vcpu->arch.srr1 = vcpu->arch.shared->msr | flags;
kvmppc_set_pc(vcpu, to_book3s(vcpu)->hior + vec);
vcpu->arch.mmu.reset_msr(vcpu);
}
@@ -254,11 +254,11 @@ int kvmppc_book3s_irqprio_deliver(struct kvm_vcpu *vcpu, unsigned int priority)
switch (priority) {
case BOOK3S_IRQPRIO_DECREMENTER:
- deliver = vcpu->arch.msr & MSR_EE;
+ deliver = vcpu->arch.shared->msr & MSR_EE;
vec = BOOK3S_INTERRUPT_DECREMENTER;
break;
case BOOK3S_IRQPRIO_EXTERNAL:
- deliver = vcpu->arch.msr & MSR_EE;
+ deliver = vcpu->arch.shared->msr & MSR_EE;
vec = BOOK3S_INTERRUPT_EXTERNAL;
break;
case BOOK3S_IRQPRIO_SYSTEM_RESET:
@@ -437,7 +437,7 @@ static void kvmppc_patch_dcbz(struct kvm_vcpu *vcpu, struct kvmppc_pte *pte)
static int kvmppc_xlate(struct kvm_vcpu *vcpu, ulong eaddr, bool data,
struct kvmppc_pte *pte)
{
- int relocated = (vcpu->arch.msr & (data ? MSR_DR : MSR_IR));
+ int relocated = (vcpu->arch.shared->msr & (data ? MSR_DR : MSR_IR));
int r;
if (relocated) {
@@ -545,8 +545,8 @@ int kvmppc_handle_pagefault(struct kvm_run *run, struct kvm_vcpu *vcpu,
int page_found = 0;
struct kvmppc_pte pte;
bool is_mmio = false;
- bool dr = (vcpu->arch.msr & MSR_DR) ? true : false;
- bool ir = (vcpu->arch.msr & MSR_IR) ? true : false;
+ bool dr = (vcpu->arch.shared->msr & MSR_DR) ? true : false;
+ bool ir = (vcpu->arch.shared->msr & MSR_IR) ? true : false;
u64 vsid;
relocated = data ? dr : ir;
@@ -563,7 +563,7 @@ int kvmppc_handle_pagefault(struct kvm_run *run, struct kvm_vcpu *vcpu,
pte.vpage = eaddr >> 12;
}
- switch (vcpu->arch.msr & (MSR_DR|MSR_IR)) {
+ switch (vcpu->arch.shared->msr & (MSR_DR|MSR_IR)) {
case 0:
pte.vpage |= ((u64)VSID_REAL << (SID_SHIFT - 12));
break;
@@ -571,7 +571,7 @@ int kvmppc_handle_pagefault(struct kvm_run *run, struct kvm_vcpu *vcpu,
case MSR_IR:
vcpu->arch.mmu.esid_to_vsid(vcpu, eaddr >> SID_SHIFT, &vsid);
- if ((vcpu->arch.msr & (MSR_DR|MSR_IR)) = MSR_DR)
+ if ((vcpu->arch.shared->msr & (MSR_DR|MSR_IR)) = MSR_DR)
pte.vpage |= ((u64)VSID_REAL_DR << (SID_SHIFT - 12));
else
pte.vpage |= ((u64)VSID_REAL_IR << (SID_SHIFT - 12));
@@ -596,14 +596,16 @@ int kvmppc_handle_pagefault(struct kvm_run *run, struct kvm_vcpu *vcpu,
/* Page not found in guest PTE entries */
vcpu->arch.dear = kvmppc_get_fault_dar(vcpu);
to_book3s(vcpu)->dsisr = to_svcpu(vcpu)->fault_dsisr;
- vcpu->arch.msr |= (to_svcpu(vcpu)->shadow_srr1 & 0x00000000f8000000ULL);
+ vcpu->arch.shared->msr |+ (to_svcpu(vcpu)->shadow_srr1 & 0x00000000f8000000ULL);
kvmppc_book3s_queue_irqprio(vcpu, vec);
} else if (page_found = -EPERM) {
/* Storage protection */
vcpu->arch.dear = kvmppc_get_fault_dar(vcpu);
to_book3s(vcpu)->dsisr = to_svcpu(vcpu)->fault_dsisr & ~DSISR_NOHPTE;
to_book3s(vcpu)->dsisr |= DSISR_PROTFAULT;
- vcpu->arch.msr |= (to_svcpu(vcpu)->shadow_srr1 & 0x00000000f8000000ULL);
+ vcpu->arch.shared->msr |+ (to_svcpu(vcpu)->shadow_srr1 & 0x00000000f8000000ULL);
kvmppc_book3s_queue_irqprio(vcpu, vec);
} else if (page_found = -EINVAL) {
/* Page not found in guest SLB */
@@ -695,9 +697,11 @@ static int kvmppc_read_inst(struct kvm_vcpu *vcpu)
ret = kvmppc_ld(vcpu, &srr0, sizeof(u32), &last_inst, false);
if (ret = -ENOENT) {
- vcpu->arch.msr = kvmppc_set_field(vcpu->arch.msr, 33, 33, 1);
- vcpu->arch.msr = kvmppc_set_field(vcpu->arch.msr, 34, 36, 0);
- vcpu->arch.msr = kvmppc_set_field(vcpu->arch.msr, 42, 47, 0);
+ ulong msr = vcpu->arch.shared->msr;
+
+ msr = kvmppc_set_field(msr, 33, 33, 1);
+ msr = kvmppc_set_field(msr, 34, 36, 0);
+ vcpu->arch.shared->msr = kvmppc_set_field(msr, 42, 47, 0);
kvmppc_book3s_queue_irqprio(vcpu, BOOK3S_INTERRUPT_INST_STORAGE);
return EMULATE_AGAIN;
}
@@ -736,7 +740,7 @@ static int kvmppc_handle_ext(struct kvm_vcpu *vcpu, unsigned int exit_nr,
if (vcpu->arch.hflags & BOOK3S_HFLAG_PAIRED_SINGLE)
return RESUME_GUEST;
- if (!(vcpu->arch.msr & msr)) {
+ if (!(vcpu->arch.shared->msr & msr)) {
kvmppc_book3s_queue_irqprio(vcpu, exit_nr);
return RESUME_GUEST;
}
@@ -804,7 +808,7 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
if ((exit_nr != 0x900) && (exit_nr != 0x500))
printk(KERN_EMERG "exit_nr=0x%x | pc=0x%lx | dar=0x%lx | msr=0x%lx\n",
exit_nr, kvmppc_get_pc(vcpu), kvmppc_get_fault_dar(vcpu),
- vcpu->arch.msr);
+ vcpu->arch.shared->msr);
#endif
kvm_resched(vcpu);
switch (exit_nr) {
@@ -836,7 +840,8 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
kvmppc_mmu_pte_flush(vcpu, kvmppc_get_pc(vcpu), ~0xFFFUL);
r = RESUME_GUEST;
} else {
- vcpu->arch.msr |= to_svcpu(vcpu)->shadow_srr1 & 0x58000000;
+ vcpu->arch.shared->msr |+ to_svcpu(vcpu)->shadow_srr1 & 0x58000000;
kvmppc_book3s_queue_irqprio(vcpu, exit_nr);
kvmppc_mmu_pte_flush(vcpu, kvmppc_get_pc(vcpu), ~0xFFFUL);
r = RESUME_GUEST;
@@ -904,7 +909,7 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
program_interrupt:
flags = to_svcpu(vcpu)->shadow_srr1 & 0x1f0000ull;
- if (vcpu->arch.msr & MSR_PR) {
+ if (vcpu->arch.shared->msr & MSR_PR) {
#ifdef EXIT_DEBUG
printk(KERN_INFO "Userspace triggered 0x700 exception at 0x%lx (0x%x)\n", kvmppc_get_pc(vcpu), kvmppc_get_last_inst(vcpu));
#endif
@@ -1052,7 +1057,7 @@ int kvm_arch_vcpu_ioctl_get_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
regs->ctr = kvmppc_get_ctr(vcpu);
regs->lr = kvmppc_get_lr(vcpu);
regs->xer = kvmppc_get_xer(vcpu);
- regs->msr = vcpu->arch.msr;
+ regs->msr = vcpu->arch.shared->msr;
regs->srr0 = vcpu->arch.srr0;
regs->srr1 = vcpu->arch.srr1;
regs->pid = vcpu->arch.pid;
@@ -1358,7 +1363,7 @@ int __kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
local_irq_enable();
/* Preload FPU if it's enabled */
- if (vcpu->arch.msr & MSR_FP)
+ if (vcpu->arch.shared->msr & MSR_FP)
kvmppc_handle_ext(vcpu, BOOK3S_INTERRUPT_FP_UNAVAIL, MSR_FP);
ret = __kvmppc_vcpu_entry(kvm_run, vcpu);
diff --git a/arch/powerpc/kvm/book3s_32_mmu.c b/arch/powerpc/kvm/book3s_32_mmu.c
index 079760b..41130c8 100644
--- a/arch/powerpc/kvm/book3s_32_mmu.c
+++ b/arch/powerpc/kvm/book3s_32_mmu.c
@@ -133,7 +133,7 @@ static int kvmppc_mmu_book3s_32_xlate_bat(struct kvm_vcpu *vcpu, gva_t eaddr,
else
bat = &vcpu_book3s->ibat[i];
- if (vcpu->arch.msr & MSR_PR) {
+ if (vcpu->arch.shared->msr & MSR_PR) {
if (!bat->vp)
continue;
} else {
@@ -214,8 +214,8 @@ static int kvmppc_mmu_book3s_32_xlate_pte(struct kvm_vcpu *vcpu, gva_t eaddr,
pte->raddr = (pteg[i+1] & ~(0xFFFULL)) | (eaddr & 0xFFF);
pp = pteg[i+1] & 3;
- if ((sre->Kp && (vcpu->arch.msr & MSR_PR)) ||
- (sre->Ks && !(vcpu->arch.msr & MSR_PR)))
+ if ((sre->Kp && (vcpu->arch.shared->msr & MSR_PR)) ||
+ (sre->Ks && !(vcpu->arch.shared->msr & MSR_PR)))
pp |= 4;
pte->may_write = false;
@@ -334,7 +334,7 @@ static int kvmppc_mmu_book3s_32_esid_to_vsid(struct kvm_vcpu *vcpu, ulong esid,
struct kvmppc_sr *sr;
u64 gvsid = esid;
- if (vcpu->arch.msr & (MSR_DR|MSR_IR)) {
+ if (vcpu->arch.shared->msr & (MSR_DR|MSR_IR)) {
sr = find_sr(to_book3s(vcpu), ea);
if (sr->valid)
gvsid = sr->vsid;
@@ -343,7 +343,7 @@ static int kvmppc_mmu_book3s_32_esid_to_vsid(struct kvm_vcpu *vcpu, ulong esid,
/* In case we only have one of MSR_IR or MSR_DR set, let's put
that in the real-mode context (and hope RM doesn't access
high memory) */
- switch (vcpu->arch.msr & (MSR_DR|MSR_IR)) {
+ switch (vcpu->arch.shared->msr & (MSR_DR|MSR_IR)) {
case 0:
*vsid = VSID_REAL | esid;
break;
@@ -363,7 +363,7 @@ static int kvmppc_mmu_book3s_32_esid_to_vsid(struct kvm_vcpu *vcpu, ulong esid,
BUG();
}
- if (vcpu->arch.msr & MSR_PR)
+ if (vcpu->arch.shared->msr & MSR_PR)
*vsid |= VSID_PR;
return 0;
diff --git a/arch/powerpc/kvm/book3s_32_mmu_host.c b/arch/powerpc/kvm/book3s_32_mmu_host.c
index 0b51ef8..67b8c38 100644
--- a/arch/powerpc/kvm/book3s_32_mmu_host.c
+++ b/arch/powerpc/kvm/book3s_32_mmu_host.c
@@ -86,7 +86,7 @@ static struct kvmppc_sid_map *find_sid_vsid(struct kvm_vcpu *vcpu, u64 gvsid)
struct kvmppc_sid_map *map;
u16 sid_map_mask;
- if (vcpu->arch.msr & MSR_PR)
+ if (vcpu->arch.shared->msr & MSR_PR)
gvsid |= VSID_PR;
sid_map_mask = kvmppc_sid_hash(vcpu, gvsid);
@@ -253,7 +253,7 @@ static struct kvmppc_sid_map *create_sid_map(struct kvm_vcpu *vcpu, u64 gvsid)
u16 sid_map_mask;
static int backwards_map = 0;
- if (vcpu->arch.msr & MSR_PR)
+ if (vcpu->arch.shared->msr & MSR_PR)
gvsid |= VSID_PR;
/* We might get collisions that trap in preceding order, so let's
diff --git a/arch/powerpc/kvm/book3s_64_mmu.c b/arch/powerpc/kvm/book3s_64_mmu.c
index 4025ea2..58aa840 100644
--- a/arch/powerpc/kvm/book3s_64_mmu.c
+++ b/arch/powerpc/kvm/book3s_64_mmu.c
@@ -180,9 +180,9 @@ do_second:
goto no_page_found;
}
- if ((vcpu->arch.msr & MSR_PR) && slbe->Kp)
+ if ((vcpu->arch.shared->msr & MSR_PR) && slbe->Kp)
key = 4;
- else if (!(vcpu->arch.msr & MSR_PR) && slbe->Ks)
+ else if (!(vcpu->arch.shared->msr & MSR_PR) && slbe->Ks)
key = 4;
for (i=0; i<16; i+=2) {
@@ -381,7 +381,7 @@ static void kvmppc_mmu_book3s_64_slbia(struct kvm_vcpu *vcpu)
for (i = 1; i < vcpu_book3s->slb_nr; i++)
vcpu_book3s->slb[i].valid = false;
- if (vcpu->arch.msr & MSR_IR) {
+ if (vcpu->arch.shared->msr & MSR_IR) {
kvmppc_mmu_flush_segments(vcpu);
kvmppc_mmu_map_segment(vcpu, kvmppc_get_pc(vcpu));
}
@@ -446,13 +446,13 @@ static int kvmppc_mmu_book3s_64_esid_to_vsid(struct kvm_vcpu *vcpu, ulong esid,
struct kvmppc_slb *slb;
u64 gvsid = esid;
- if (vcpu->arch.msr & (MSR_DR|MSR_IR)) {
+ if (vcpu->arch.shared->msr & (MSR_DR|MSR_IR)) {
slb = kvmppc_mmu_book3s_64_find_slbe(to_book3s(vcpu), ea);
if (slb)
gvsid = slb->vsid;
}
- switch (vcpu->arch.msr & (MSR_DR|MSR_IR)) {
+ switch (vcpu->arch.shared->msr & (MSR_DR|MSR_IR)) {
case 0:
*vsid = VSID_REAL | esid;
break;
@@ -473,7 +473,7 @@ static int kvmppc_mmu_book3s_64_esid_to_vsid(struct kvm_vcpu *vcpu, ulong esid,
break;
}
- if (vcpu->arch.msr & MSR_PR)
+ if (vcpu->arch.shared->msr & MSR_PR)
*vsid |= VSID_PR;
return 0;
diff --git a/arch/powerpc/kvm/book3s_64_mmu_host.c b/arch/powerpc/kvm/book3s_64_mmu_host.c
index 384179a..71c1f90 100644
--- a/arch/powerpc/kvm/book3s_64_mmu_host.c
+++ b/arch/powerpc/kvm/book3s_64_mmu_host.c
@@ -66,7 +66,7 @@ static struct kvmppc_sid_map *find_sid_vsid(struct kvm_vcpu *vcpu, u64 gvsid)
struct kvmppc_sid_map *map;
u16 sid_map_mask;
- if (vcpu->arch.msr & MSR_PR)
+ if (vcpu->arch.shared->msr & MSR_PR)
gvsid |= VSID_PR;
sid_map_mask = kvmppc_sid_hash(vcpu, gvsid);
@@ -191,7 +191,7 @@ static struct kvmppc_sid_map *create_sid_map(struct kvm_vcpu *vcpu, u64 gvsid)
u16 sid_map_mask;
static int backwards_map = 0;
- if (vcpu->arch.msr & MSR_PR)
+ if (vcpu->arch.shared->msr & MSR_PR)
gvsid |= VSID_PR;
/* We might get collisions that trap in preceding order, so let's
diff --git a/arch/powerpc/kvm/book3s_emulate.c b/arch/powerpc/kvm/book3s_emulate.c
index c85f906..35d3c16 100644
--- a/arch/powerpc/kvm/book3s_emulate.c
+++ b/arch/powerpc/kvm/book3s_emulate.c
@@ -86,14 +86,15 @@ int kvmppc_core_emulate_op(struct kvm_run *run, struct kvm_vcpu *vcpu,
case 31:
switch (get_xop(inst)) {
case OP_31_XOP_MFMSR:
- kvmppc_set_gpr(vcpu, get_rt(inst), vcpu->arch.msr);
+ kvmppc_set_gpr(vcpu, get_rt(inst),
+ vcpu->arch.shared->msr);
break;
case OP_31_XOP_MTMSRD:
{
ulong rs = kvmppc_get_gpr(vcpu, get_rs(inst));
if (inst & 0x10000) {
- vcpu->arch.msr &= ~(MSR_RI | MSR_EE);
- vcpu->arch.msr |= rs & (MSR_RI | MSR_EE);
+ vcpu->arch.shared->msr &= ~(MSR_RI | MSR_EE);
+ vcpu->arch.shared->msr |= rs & (MSR_RI | MSR_EE);
} else
kvmppc_set_msr(vcpu, rs);
break;
@@ -204,7 +205,7 @@ int kvmppc_core_emulate_op(struct kvm_run *run, struct kvm_vcpu *vcpu,
ra = kvmppc_get_gpr(vcpu, get_ra(inst));
addr = (ra + rb) & ~31ULL;
- if (!(vcpu->arch.msr & MSR_SF))
+ if (!(vcpu->arch.shared->msr & MSR_SF))
addr &= 0xffffffff;
vaddr = addr;
diff --git a/arch/powerpc/kvm/book3s_paired_singles.c b/arch/powerpc/kvm/book3s_paired_singles.c
index 474f2e2..626e6ef 100644
--- a/arch/powerpc/kvm/book3s_paired_singles.c
+++ b/arch/powerpc/kvm/book3s_paired_singles.c
@@ -165,9 +165,10 @@ static inline void kvmppc_sync_qpr(struct kvm_vcpu *vcpu, int rt)
static void kvmppc_inject_pf(struct kvm_vcpu *vcpu, ulong eaddr, bool is_store)
{
u64 dsisr;
+ struct kvm_vcpu_arch_shared *shared = vcpu->arch.shared;
- vcpu->arch.msr = kvmppc_set_field(vcpu->arch.msr, 33, 36, 0);
- vcpu->arch.msr = kvmppc_set_field(vcpu->arch.msr, 42, 47, 0);
+ shared->msr = kvmppc_set_field(shared->msr, 33, 36, 0);
+ shared->msr = kvmppc_set_field(shared->msr, 42, 47, 0);
vcpu->arch.dear = eaddr;
/* Page Fault */
dsisr = kvmppc_set_field(0, 33, 33, 1);
@@ -658,7 +659,7 @@ int kvmppc_emulate_paired_single(struct kvm_run *run, struct kvm_vcpu *vcpu)
if (!kvmppc_inst_is_paired_single(vcpu, inst))
return EMULATE_FAIL;
- if (!(vcpu->arch.msr & MSR_FP)) {
+ if (!(vcpu->arch.shared->msr & MSR_FP)) {
kvmppc_book3s_queue_irqprio(vcpu, BOOK3S_INTERRUPT_FP_UNAVAIL);
return EMULATE_AGAIN;
}
diff --git a/arch/powerpc/kvm/booke.c b/arch/powerpc/kvm/booke.c
index 376b586..ddb4cac 100644
--- a/arch/powerpc/kvm/booke.c
+++ b/arch/powerpc/kvm/booke.c
@@ -62,7 +62,7 @@ void kvmppc_dump_vcpu(struct kvm_vcpu *vcpu)
{
int i;
- printk("pc: %08lx msr: %08lx\n", vcpu->arch.pc, vcpu->arch.msr);
+ printk("pc: %08lx msr: %08llx\n", vcpu->arch.pc, vcpu->arch.shared->msr);
printk("lr: %08lx ctr: %08lx\n", vcpu->arch.lr, vcpu->arch.ctr);
printk("srr0: %08lx srr1: %08lx\n", vcpu->arch.srr0, vcpu->arch.srr1);
@@ -169,34 +169,34 @@ static int kvmppc_booke_irqprio_deliver(struct kvm_vcpu *vcpu,
break;
case BOOKE_IRQPRIO_CRITICAL:
case BOOKE_IRQPRIO_WATCHDOG:
- allowed = vcpu->arch.msr & MSR_CE;
+ allowed = vcpu->arch.shared->msr & MSR_CE;
msr_mask = MSR_ME;
break;
case BOOKE_IRQPRIO_MACHINE_CHECK:
- allowed = vcpu->arch.msr & MSR_ME;
+ allowed = vcpu->arch.shared->msr & MSR_ME;
msr_mask = 0;
break;
case BOOKE_IRQPRIO_EXTERNAL:
case BOOKE_IRQPRIO_DECREMENTER:
case BOOKE_IRQPRIO_FIT:
- allowed = vcpu->arch.msr & MSR_EE;
+ allowed = vcpu->arch.shared->msr & MSR_EE;
msr_mask = MSR_CE|MSR_ME|MSR_DE;
break;
case BOOKE_IRQPRIO_DEBUG:
- allowed = vcpu->arch.msr & MSR_DE;
+ allowed = vcpu->arch.shared->msr & MSR_DE;
msr_mask = MSR_ME;
break;
}
if (allowed) {
vcpu->arch.srr0 = vcpu->arch.pc;
- vcpu->arch.srr1 = vcpu->arch.msr;
+ vcpu->arch.srr1 = vcpu->arch.shared->msr;
vcpu->arch.pc = vcpu->arch.ivpr | vcpu->arch.ivor[priority];
if (update_esr = true)
vcpu->arch.esr = vcpu->arch.queued_esr;
if (update_dear = true)
vcpu->arch.dear = vcpu->arch.queued_dear;
- kvmppc_set_msr(vcpu, vcpu->arch.msr & msr_mask);
+ kvmppc_set_msr(vcpu, vcpu->arch.shared->msr & msr_mask);
clear_bit(priority, &vcpu->arch.pending_exceptions);
}
@@ -265,7 +265,7 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
break;
case BOOKE_INTERRUPT_PROGRAM:
- if (vcpu->arch.msr & MSR_PR) {
+ if (vcpu->arch.shared->msr & MSR_PR) {
/* Program traps generated by user-level software must be handled
* by the guest kernel. */
kvmppc_core_queue_program(vcpu, vcpu->arch.fault_esr);
@@ -467,7 +467,7 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu)
{
vcpu->arch.pc = 0;
- vcpu->arch.msr = 0;
+ vcpu->arch.shared->msr = 0;
kvmppc_set_gpr(vcpu, 1, (16<<20) - 8); /* -8 for the callee-save LR slot */
vcpu->arch.shadow_pid = 1;
@@ -490,7 +490,7 @@ int kvm_arch_vcpu_ioctl_get_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
regs->ctr = vcpu->arch.ctr;
regs->lr = vcpu->arch.lr;
regs->xer = kvmppc_get_xer(vcpu);
- regs->msr = vcpu->arch.msr;
+ regs->msr = vcpu->arch.shared->msr;
regs->srr0 = vcpu->arch.srr0;
regs->srr1 = vcpu->arch.srr1;
regs->pid = vcpu->arch.pid;
diff --git a/arch/powerpc/kvm/booke.h b/arch/powerpc/kvm/booke.h
index d59bcca..88258ac 100644
--- a/arch/powerpc/kvm/booke.h
+++ b/arch/powerpc/kvm/booke.h
@@ -54,12 +54,12 @@ extern unsigned long kvmppc_booke_handlers;
* changing. */
static inline void kvmppc_set_msr(struct kvm_vcpu *vcpu, u32 new_msr)
{
- if ((new_msr & MSR_PR) != (vcpu->arch.msr & MSR_PR))
+ if ((new_msr & MSR_PR) != (vcpu->arch.shared->msr & MSR_PR))
kvmppc_mmu_priv_switch(vcpu, new_msr & MSR_PR);
- vcpu->arch.msr = new_msr;
+ vcpu->arch.shared->msr = new_msr;
- if (vcpu->arch.msr & MSR_WE) {
+ if (vcpu->arch.shared->msr & MSR_WE) {
kvm_vcpu_block(vcpu);
kvmppc_set_exit_type(vcpu, EMULATED_MTMSRWE_EXITS);
};
diff --git a/arch/powerpc/kvm/booke_emulate.c b/arch/powerpc/kvm/booke_emulate.c
index cbc790e..b115203 100644
--- a/arch/powerpc/kvm/booke_emulate.c
+++ b/arch/powerpc/kvm/booke_emulate.c
@@ -62,7 +62,7 @@ int kvmppc_booke_emulate_op(struct kvm_run *run, struct kvm_vcpu *vcpu,
case OP_31_XOP_MFMSR:
rt = get_rt(inst);
- kvmppc_set_gpr(vcpu, rt, vcpu->arch.msr);
+ kvmppc_set_gpr(vcpu, rt, vcpu->arch.shared->msr);
kvmppc_set_exit_type(vcpu, EMULATED_MFMSR_EXITS);
break;
@@ -74,13 +74,13 @@ int kvmppc_booke_emulate_op(struct kvm_run *run, struct kvm_vcpu *vcpu,
case OP_31_XOP_WRTEE:
rs = get_rs(inst);
- vcpu->arch.msr = (vcpu->arch.msr & ~MSR_EE)
+ vcpu->arch.shared->msr = (vcpu->arch.shared->msr & ~MSR_EE)
| (kvmppc_get_gpr(vcpu, rs) & MSR_EE);
kvmppc_set_exit_type(vcpu, EMULATED_WRTEE_EXITS);
break;
case OP_31_XOP_WRTEEI:
- vcpu->arch.msr = (vcpu->arch.msr & ~MSR_EE)
+ vcpu->arch.shared->msr = (vcpu->arch.shared->msr & ~MSR_EE)
| (inst & MSR_EE);
kvmppc_set_exit_type(vcpu, EMULATED_WRTEE_EXITS);
break;
diff --git a/arch/powerpc/kvm/booke_interrupts.S b/arch/powerpc/kvm/booke_interrupts.S
index 380a78c..0498469 100644
--- a/arch/powerpc/kvm/booke_interrupts.S
+++ b/arch/powerpc/kvm/booke_interrupts.S
@@ -415,7 +415,8 @@ lightweight_exit:
lwz r8, VCPU_GPR(r8)(r4)
lwz r3, VCPU_PC(r4)
mtsrr0 r3
- lwz r3, VCPU_MSR(r4)
+ lwz r3, VCPU_SHARED(r4)
+ lwz r3, VCPU_SHARED_MSR(r3)
oris r3, r3, KVMPPC_MSR_MASK@h
ori r3, r3, KVMPPC_MSR_MASK@l
mtsrr1 r3
diff --git a/arch/powerpc/kvm/e500_tlb.c b/arch/powerpc/kvm/e500_tlb.c
index f11ca0f..66845a5 100644
--- a/arch/powerpc/kvm/e500_tlb.c
+++ b/arch/powerpc/kvm/e500_tlb.c
@@ -317,10 +317,10 @@ static inline void kvmppc_e500_shadow_map(struct kvmppc_vcpu_e500 *vcpu_e500,
| MAS1_TID(get_tlb_tid(gtlbe)) | MAS1_TS | MAS1_VALID;
stlbe->mas2 = (gvaddr & MAS2_EPN)
| e500_shadow_mas2_attrib(gtlbe->mas2,
- vcpu_e500->vcpu.arch.msr & MSR_PR);
+ vcpu_e500->vcpu.arch.shared->msr & MSR_PR);
stlbe->mas3 = (hpaddr & MAS3_RPN)
| e500_shadow_mas3_attrib(gtlbe->mas3,
- vcpu_e500->vcpu.arch.msr & MSR_PR);
+ vcpu_e500->vcpu.arch.shared->msr & MSR_PR);
stlbe->mas7 = (hpaddr >> 32) & MAS7_RPN;
trace_kvm_stlb_write(index_of(tlbsel, esel), stlbe->mas1, stlbe->mas2,
@@ -579,28 +579,28 @@ int kvmppc_e500_emul_tlbwe(struct kvm_vcpu *vcpu)
int kvmppc_mmu_itlb_index(struct kvm_vcpu *vcpu, gva_t eaddr)
{
- unsigned int as = !!(vcpu->arch.msr & MSR_IS);
+ unsigned int as = !!(vcpu->arch.shared->msr & MSR_IS);
return kvmppc_e500_tlb_search(vcpu, eaddr, get_cur_pid(vcpu), as);
}
int kvmppc_mmu_dtlb_index(struct kvm_vcpu *vcpu, gva_t eaddr)
{
- unsigned int as = !!(vcpu->arch.msr & MSR_DS);
+ unsigned int as = !!(vcpu->arch.shared->msr & MSR_DS);
return kvmppc_e500_tlb_search(vcpu, eaddr, get_cur_pid(vcpu), as);
}
void kvmppc_mmu_itlb_miss(struct kvm_vcpu *vcpu)
{
- unsigned int as = !!(vcpu->arch.msr & MSR_IS);
+ unsigned int as = !!(vcpu->arch.shared->msr & MSR_IS);
kvmppc_e500_deliver_tlb_miss(vcpu, vcpu->arch.pc, as);
}
void kvmppc_mmu_dtlb_miss(struct kvm_vcpu *vcpu)
{
- unsigned int as = !!(vcpu->arch.msr & MSR_DS);
+ unsigned int as = !!(vcpu->arch.shared->msr & MSR_DS);
kvmppc_e500_deliver_tlb_miss(vcpu, vcpu->arch.fault_dear, as);
}
diff --git a/arch/powerpc/kvm/e500_tlb.h b/arch/powerpc/kvm/e500_tlb.h
index d28e301..458946b 100644
--- a/arch/powerpc/kvm/e500_tlb.h
+++ b/arch/powerpc/kvm/e500_tlb.h
@@ -171,7 +171,7 @@ static inline int tlbe_is_host_safe(const struct kvm_vcpu *vcpu,
/* Does it match current guest AS? */
/* XXX what about IS != DS? */
- if (get_tlb_ts(tlbe) != !!(vcpu->arch.msr & MSR_IS))
+ if (get_tlb_ts(tlbe) != !!(vcpu->arch.shared->msr & MSR_IS))
return 0;
gpa = get_tlb_raddr(tlbe);
diff --git a/arch/powerpc/kvm/powerpc.c b/arch/powerpc/kvm/powerpc.c
index 72a4ad8..22f6fa2 100644
--- a/arch/powerpc/kvm/powerpc.c
+++ b/arch/powerpc/kvm/powerpc.c
@@ -38,7 +38,8 @@
int kvm_arch_vcpu_runnable(struct kvm_vcpu *v)
{
- return !(v->arch.msr & MSR_WE) || !!(v->arch.pending_exceptions);
+ return !(v->arch.shared->msr & MSR_WE) ||
+ !!(v->arch.pending_exceptions);
}
--
1.6.0.2
^ permalink raw reply related [flat|nested] 227+ messages in thread* [PATCH 02/26] KVM: PPC: Convert MSR to shared page
@ 2010-06-25 23:24 ` Alexander Graf
0 siblings, 0 replies; 227+ messages in thread
From: Alexander Graf @ 2010-06-25 23:24 UTC (permalink / raw)
To: kvm-ppc-u79uwXL29TY76Z2rM5mHXA; +Cc: KVM list, linuxppc-dev
One of the most obvious registers to share with the guest directly is the
MSR. The MSR contains the "interrupts enabled" flag which the guest has to
toggle in critical sections.
So in order to bring the overhead of interrupt en- and disabling down, let's
put msr into the shared page. Keep in mind that even though you can fully read
its contents, writing to it doesn't always update all state. There are a few
safe fields that don't require hypervisor interaction. See the guest
implementation that follows later for reference.
Signed-off-by: Alexander Graf <agraf-l3A5Bk7waGM@public.gmane.org>
---
arch/powerpc/include/asm/kvm_host.h | 1 -
arch/powerpc/include/asm/kvm_para.h | 1 +
arch/powerpc/kernel/asm-offsets.c | 2 +-
arch/powerpc/kvm/44x_tlb.c | 8 ++--
arch/powerpc/kvm/book3s.c | 65 ++++++++++++++++--------------
arch/powerpc/kvm/book3s_32_mmu.c | 12 +++---
arch/powerpc/kvm/book3s_32_mmu_host.c | 4 +-
arch/powerpc/kvm/book3s_64_mmu.c | 12 +++---
arch/powerpc/kvm/book3s_64_mmu_host.c | 4 +-
arch/powerpc/kvm/book3s_emulate.c | 9 ++--
arch/powerpc/kvm/book3s_paired_singles.c | 7 ++-
arch/powerpc/kvm/booke.c | 20 +++++-----
arch/powerpc/kvm/booke.h | 6 +-
arch/powerpc/kvm/booke_emulate.c | 6 +-
arch/powerpc/kvm/booke_interrupts.S | 3 +-
arch/powerpc/kvm/e500_tlb.c | 12 +++---
arch/powerpc/kvm/e500_tlb.h | 2 +-
arch/powerpc/kvm/powerpc.c | 3 +-
18 files changed, 93 insertions(+), 84 deletions(-)
diff --git a/arch/powerpc/include/asm/kvm_host.h b/arch/powerpc/include/asm/kvm_host.h
index bca9391..249c242 100644
--- a/arch/powerpc/include/asm/kvm_host.h
+++ b/arch/powerpc/include/asm/kvm_host.h
@@ -210,7 +210,6 @@ struct kvm_vcpu_arch {
u32 cr;
#endif
- ulong msr;
#ifdef CONFIG_PPC_BOOK3S
ulong shadow_msr;
ulong hflags;
diff --git a/arch/powerpc/include/asm/kvm_para.h b/arch/powerpc/include/asm/kvm_para.h
index 1485ba8..a17dc52 100644
--- a/arch/powerpc/include/asm/kvm_para.h
+++ b/arch/powerpc/include/asm/kvm_para.h
@@ -23,6 +23,7 @@
#include <linux/types.h>
struct kvm_vcpu_arch_shared {
+ __u64 msr;
};
#ifdef __KERNEL__
diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c
index 944f593..a55d47e 100644
--- a/arch/powerpc/kernel/asm-offsets.c
+++ b/arch/powerpc/kernel/asm-offsets.c
@@ -394,13 +394,13 @@ int main(void)
DEFINE(VCPU_HOST_STACK, offsetof(struct kvm_vcpu, arch.host_stack));
DEFINE(VCPU_HOST_PID, offsetof(struct kvm_vcpu, arch.host_pid));
DEFINE(VCPU_GPRS, offsetof(struct kvm_vcpu, arch.gpr));
- DEFINE(VCPU_MSR, offsetof(struct kvm_vcpu, arch.msr));
DEFINE(VCPU_SPRG4, offsetof(struct kvm_vcpu, arch.sprg4));
DEFINE(VCPU_SPRG5, offsetof(struct kvm_vcpu, arch.sprg5));
DEFINE(VCPU_SPRG6, offsetof(struct kvm_vcpu, arch.sprg6));
DEFINE(VCPU_SPRG7, offsetof(struct kvm_vcpu, arch.sprg7));
DEFINE(VCPU_SHADOW_PID, offsetof(struct kvm_vcpu, arch.shadow_pid));
DEFINE(VCPU_SHARED, offsetof(struct kvm_vcpu, arch.shared));
+ DEFINE(VCPU_SHARED_MSR, offsetof(struct kvm_vcpu_arch_shared, msr));
/* book3s */
#ifdef CONFIG_PPC_BOOK3S
diff --git a/arch/powerpc/kvm/44x_tlb.c b/arch/powerpc/kvm/44x_tlb.c
index 8123125..4cbbca7 100644
--- a/arch/powerpc/kvm/44x_tlb.c
+++ b/arch/powerpc/kvm/44x_tlb.c
@@ -221,14 +221,14 @@ gpa_t kvmppc_mmu_xlate(struct kvm_vcpu *vcpu, unsigned int gtlb_index,
int kvmppc_mmu_itlb_index(struct kvm_vcpu *vcpu, gva_t eaddr)
{
- unsigned int as = !!(vcpu->arch.msr & MSR_IS);
+ unsigned int as = !!(vcpu->arch.shared->msr & MSR_IS);
return kvmppc_44x_tlb_index(vcpu, eaddr, vcpu->arch.pid, as);
}
int kvmppc_mmu_dtlb_index(struct kvm_vcpu *vcpu, gva_t eaddr)
{
- unsigned int as = !!(vcpu->arch.msr & MSR_DS);
+ unsigned int as = !!(vcpu->arch.shared->msr & MSR_DS);
return kvmppc_44x_tlb_index(vcpu, eaddr, vcpu->arch.pid, as);
}
@@ -353,7 +353,7 @@ void kvmppc_mmu_map(struct kvm_vcpu *vcpu, u64 gvaddr, gpa_t gpaddr,
stlbe.word1 = (hpaddr & 0xfffffc00) | ((hpaddr >> 32) & 0xf);
stlbe.word2 = kvmppc_44x_tlb_shadow_attrib(flags,
- vcpu->arch.msr & MSR_PR);
+ vcpu->arch.shared->msr & MSR_PR);
stlbe.tid = !(asid & 0xff);
/* Keep track of the reference so we can properly release it later. */
@@ -422,7 +422,7 @@ static int tlbe_is_host_safe(const struct kvm_vcpu *vcpu,
/* Does it match current guest AS? */
/* XXX what about IS != DS? */
- if (get_tlb_ts(tlbe) != !!(vcpu->arch.msr & MSR_IS))
+ if (get_tlb_ts(tlbe) != !!(vcpu->arch.shared->msr & MSR_IS))
return 0;
gpa = get_tlb_raddr(tlbe);
diff --git a/arch/powerpc/kvm/book3s.c b/arch/powerpc/kvm/book3s.c
index ba79b35..3dd3003 100644
--- a/arch/powerpc/kvm/book3s.c
+++ b/arch/powerpc/kvm/book3s.c
@@ -115,31 +115,31 @@ static u32 kvmppc_get_dec(struct kvm_vcpu *vcpu)
static void kvmppc_recalc_shadow_msr(struct kvm_vcpu *vcpu)
{
- vcpu->arch.shadow_msr = vcpu->arch.msr;
+ ulong smsr = vcpu->arch.shared->msr;
+
/* Guest MSR values */
- vcpu->arch.shadow_msr &= MSR_FE0 | MSR_FE1 | MSR_SF | MSR_SE |
- MSR_BE | MSR_DE;
+ smsr &= MSR_FE0 | MSR_FE1 | MSR_SF | MSR_SE | MSR_BE | MSR_DE;
/* Process MSR values */
- vcpu->arch.shadow_msr |= MSR_ME | MSR_RI | MSR_IR | MSR_DR | MSR_PR |
- MSR_EE;
+ smsr |= MSR_ME | MSR_RI | MSR_IR | MSR_DR | MSR_PR | MSR_EE;
/* External providers the guest reserved */
- vcpu->arch.shadow_msr |= (vcpu->arch.msr & vcpu->arch.guest_owned_ext);
+ smsr |= (vcpu->arch.shared->msr & vcpu->arch.guest_owned_ext);
/* 64-bit Process MSR values */
#ifdef CONFIG_PPC_BOOK3S_64
- vcpu->arch.shadow_msr |= MSR_ISF | MSR_HV;
+ smsr |= MSR_ISF | MSR_HV;
#endif
+ vcpu->arch.shadow_msr = smsr;
}
void kvmppc_set_msr(struct kvm_vcpu *vcpu, u64 msr)
{
- ulong old_msr = vcpu->arch.msr;
+ ulong old_msr = vcpu->arch.shared->msr;
#ifdef EXIT_DEBUG
printk(KERN_INFO "KVM: Set MSR to 0x%llx\n", msr);
#endif
msr &= to_book3s(vcpu)->msr_mask;
- vcpu->arch.msr = msr;
+ vcpu->arch.shared->msr = msr;
kvmppc_recalc_shadow_msr(vcpu);
if (msr & (MSR_WE|MSR_POW)) {
@@ -149,21 +149,21 @@ void kvmppc_set_msr(struct kvm_vcpu *vcpu, u64 msr)
}
}
- if ((vcpu->arch.msr & (MSR_PR|MSR_IR|MSR_DR)) !=
+ if ((vcpu->arch.shared->msr & (MSR_PR|MSR_IR|MSR_DR)) !=
(old_msr & (MSR_PR|MSR_IR|MSR_DR))) {
kvmppc_mmu_flush_segments(vcpu);
kvmppc_mmu_map_segment(vcpu, kvmppc_get_pc(vcpu));
}
/* Preload FPU if it's enabled */
- if (vcpu->arch.msr & MSR_FP)
+ if (vcpu->arch.shared->msr & MSR_FP)
kvmppc_handle_ext(vcpu, BOOK3S_INTERRUPT_FP_UNAVAIL, MSR_FP);
}
void kvmppc_inject_interrupt(struct kvm_vcpu *vcpu, int vec, u64 flags)
{
vcpu->arch.srr0 = kvmppc_get_pc(vcpu);
- vcpu->arch.srr1 = vcpu->arch.msr | flags;
+ vcpu->arch.srr1 = vcpu->arch.shared->msr | flags;
kvmppc_set_pc(vcpu, to_book3s(vcpu)->hior + vec);
vcpu->arch.mmu.reset_msr(vcpu);
}
@@ -254,11 +254,11 @@ int kvmppc_book3s_irqprio_deliver(struct kvm_vcpu *vcpu, unsigned int priority)
switch (priority) {
case BOOK3S_IRQPRIO_DECREMENTER:
- deliver = vcpu->arch.msr & MSR_EE;
+ deliver = vcpu->arch.shared->msr & MSR_EE;
vec = BOOK3S_INTERRUPT_DECREMENTER;
break;
case BOOK3S_IRQPRIO_EXTERNAL:
- deliver = vcpu->arch.msr & MSR_EE;
+ deliver = vcpu->arch.shared->msr & MSR_EE;
vec = BOOK3S_INTERRUPT_EXTERNAL;
break;
case BOOK3S_IRQPRIO_SYSTEM_RESET:
@@ -437,7 +437,7 @@ static void kvmppc_patch_dcbz(struct kvm_vcpu *vcpu, struct kvmppc_pte *pte)
static int kvmppc_xlate(struct kvm_vcpu *vcpu, ulong eaddr, bool data,
struct kvmppc_pte *pte)
{
- int relocated = (vcpu->arch.msr & (data ? MSR_DR : MSR_IR));
+ int relocated = (vcpu->arch.shared->msr & (data ? MSR_DR : MSR_IR));
int r;
if (relocated) {
@@ -545,8 +545,8 @@ int kvmppc_handle_pagefault(struct kvm_run *run, struct kvm_vcpu *vcpu,
int page_found = 0;
struct kvmppc_pte pte;
bool is_mmio = false;
- bool dr = (vcpu->arch.msr & MSR_DR) ? true : false;
- bool ir = (vcpu->arch.msr & MSR_IR) ? true : false;
+ bool dr = (vcpu->arch.shared->msr & MSR_DR) ? true : false;
+ bool ir = (vcpu->arch.shared->msr & MSR_IR) ? true : false;
u64 vsid;
relocated = data ? dr : ir;
@@ -563,7 +563,7 @@ int kvmppc_handle_pagefault(struct kvm_run *run, struct kvm_vcpu *vcpu,
pte.vpage = eaddr >> 12;
}
- switch (vcpu->arch.msr & (MSR_DR|MSR_IR)) {
+ switch (vcpu->arch.shared->msr & (MSR_DR|MSR_IR)) {
case 0:
pte.vpage |= ((u64)VSID_REAL << (SID_SHIFT - 12));
break;
@@ -571,7 +571,7 @@ int kvmppc_handle_pagefault(struct kvm_run *run, struct kvm_vcpu *vcpu,
case MSR_IR:
vcpu->arch.mmu.esid_to_vsid(vcpu, eaddr >> SID_SHIFT, &vsid);
- if ((vcpu->arch.msr & (MSR_DR|MSR_IR)) == MSR_DR)
+ if ((vcpu->arch.shared->msr & (MSR_DR|MSR_IR)) == MSR_DR)
pte.vpage |= ((u64)VSID_REAL_DR << (SID_SHIFT - 12));
else
pte.vpage |= ((u64)VSID_REAL_IR << (SID_SHIFT - 12));
@@ -596,14 +596,16 @@ int kvmppc_handle_pagefault(struct kvm_run *run, struct kvm_vcpu *vcpu,
/* Page not found in guest PTE entries */
vcpu->arch.dear = kvmppc_get_fault_dar(vcpu);
to_book3s(vcpu)->dsisr = to_svcpu(vcpu)->fault_dsisr;
- vcpu->arch.msr |= (to_svcpu(vcpu)->shadow_srr1 & 0x00000000f8000000ULL);
+ vcpu->arch.shared->msr |=
+ (to_svcpu(vcpu)->shadow_srr1 & 0x00000000f8000000ULL);
kvmppc_book3s_queue_irqprio(vcpu, vec);
} else if (page_found == -EPERM) {
/* Storage protection */
vcpu->arch.dear = kvmppc_get_fault_dar(vcpu);
to_book3s(vcpu)->dsisr = to_svcpu(vcpu)->fault_dsisr & ~DSISR_NOHPTE;
to_book3s(vcpu)->dsisr |= DSISR_PROTFAULT;
- vcpu->arch.msr |= (to_svcpu(vcpu)->shadow_srr1 & 0x00000000f8000000ULL);
+ vcpu->arch.shared->msr |=
+ (to_svcpu(vcpu)->shadow_srr1 & 0x00000000f8000000ULL);
kvmppc_book3s_queue_irqprio(vcpu, vec);
} else if (page_found == -EINVAL) {
/* Page not found in guest SLB */
@@ -695,9 +697,11 @@ static int kvmppc_read_inst(struct kvm_vcpu *vcpu)
ret = kvmppc_ld(vcpu, &srr0, sizeof(u32), &last_inst, false);
if (ret == -ENOENT) {
- vcpu->arch.msr = kvmppc_set_field(vcpu->arch.msr, 33, 33, 1);
- vcpu->arch.msr = kvmppc_set_field(vcpu->arch.msr, 34, 36, 0);
- vcpu->arch.msr = kvmppc_set_field(vcpu->arch.msr, 42, 47, 0);
+ ulong msr = vcpu->arch.shared->msr;
+
+ msr = kvmppc_set_field(msr, 33, 33, 1);
+ msr = kvmppc_set_field(msr, 34, 36, 0);
+ vcpu->arch.shared->msr = kvmppc_set_field(msr, 42, 47, 0);
kvmppc_book3s_queue_irqprio(vcpu, BOOK3S_INTERRUPT_INST_STORAGE);
return EMULATE_AGAIN;
}
@@ -736,7 +740,7 @@ static int kvmppc_handle_ext(struct kvm_vcpu *vcpu, unsigned int exit_nr,
if (vcpu->arch.hflags & BOOK3S_HFLAG_PAIRED_SINGLE)
return RESUME_GUEST;
- if (!(vcpu->arch.msr & msr)) {
+ if (!(vcpu->arch.shared->msr & msr)) {
kvmppc_book3s_queue_irqprio(vcpu, exit_nr);
return RESUME_GUEST;
}
@@ -804,7 +808,7 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
if ((exit_nr != 0x900) && (exit_nr != 0x500))
printk(KERN_EMERG "exit_nr=0x%x | pc=0x%lx | dar=0x%lx | msr=0x%lx\n",
exit_nr, kvmppc_get_pc(vcpu), kvmppc_get_fault_dar(vcpu),
- vcpu->arch.msr);
+ vcpu->arch.shared->msr);
#endif
kvm_resched(vcpu);
switch (exit_nr) {
@@ -836,7 +840,8 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
kvmppc_mmu_pte_flush(vcpu, kvmppc_get_pc(vcpu), ~0xFFFUL);
r = RESUME_GUEST;
} else {
- vcpu->arch.msr |= to_svcpu(vcpu)->shadow_srr1 & 0x58000000;
+ vcpu->arch.shared->msr |=
+ to_svcpu(vcpu)->shadow_srr1 & 0x58000000;
kvmppc_book3s_queue_irqprio(vcpu, exit_nr);
kvmppc_mmu_pte_flush(vcpu, kvmppc_get_pc(vcpu), ~0xFFFUL);
r = RESUME_GUEST;
@@ -904,7 +909,7 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
program_interrupt:
flags = to_svcpu(vcpu)->shadow_srr1 & 0x1f0000ull;
- if (vcpu->arch.msr & MSR_PR) {
+ if (vcpu->arch.shared->msr & MSR_PR) {
#ifdef EXIT_DEBUG
printk(KERN_INFO "Userspace triggered 0x700 exception at 0x%lx (0x%x)\n", kvmppc_get_pc(vcpu), kvmppc_get_last_inst(vcpu));
#endif
@@ -1052,7 +1057,7 @@ int kvm_arch_vcpu_ioctl_get_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
regs->ctr = kvmppc_get_ctr(vcpu);
regs->lr = kvmppc_get_lr(vcpu);
regs->xer = kvmppc_get_xer(vcpu);
- regs->msr = vcpu->arch.msr;
+ regs->msr = vcpu->arch.shared->msr;
regs->srr0 = vcpu->arch.srr0;
regs->srr1 = vcpu->arch.srr1;
regs->pid = vcpu->arch.pid;
@@ -1358,7 +1363,7 @@ int __kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
local_irq_enable();
/* Preload FPU if it's enabled */
- if (vcpu->arch.msr & MSR_FP)
+ if (vcpu->arch.shared->msr & MSR_FP)
kvmppc_handle_ext(vcpu, BOOK3S_INTERRUPT_FP_UNAVAIL, MSR_FP);
ret = __kvmppc_vcpu_entry(kvm_run, vcpu);
diff --git a/arch/powerpc/kvm/book3s_32_mmu.c b/arch/powerpc/kvm/book3s_32_mmu.c
index 079760b..41130c8 100644
--- a/arch/powerpc/kvm/book3s_32_mmu.c
+++ b/arch/powerpc/kvm/book3s_32_mmu.c
@@ -133,7 +133,7 @@ static int kvmppc_mmu_book3s_32_xlate_bat(struct kvm_vcpu *vcpu, gva_t eaddr,
else
bat = &vcpu_book3s->ibat[i];
- if (vcpu->arch.msr & MSR_PR) {
+ if (vcpu->arch.shared->msr & MSR_PR) {
if (!bat->vp)
continue;
} else {
@@ -214,8 +214,8 @@ static int kvmppc_mmu_book3s_32_xlate_pte(struct kvm_vcpu *vcpu, gva_t eaddr,
pte->raddr = (pteg[i+1] & ~(0xFFFULL)) | (eaddr & 0xFFF);
pp = pteg[i+1] & 3;
- if ((sre->Kp && (vcpu->arch.msr & MSR_PR)) ||
- (sre->Ks && !(vcpu->arch.msr & MSR_PR)))
+ if ((sre->Kp && (vcpu->arch.shared->msr & MSR_PR)) ||
+ (sre->Ks && !(vcpu->arch.shared->msr & MSR_PR)))
pp |= 4;
pte->may_write = false;
@@ -334,7 +334,7 @@ static int kvmppc_mmu_book3s_32_esid_to_vsid(struct kvm_vcpu *vcpu, ulong esid,
struct kvmppc_sr *sr;
u64 gvsid = esid;
- if (vcpu->arch.msr & (MSR_DR|MSR_IR)) {
+ if (vcpu->arch.shared->msr & (MSR_DR|MSR_IR)) {
sr = find_sr(to_book3s(vcpu), ea);
if (sr->valid)
gvsid = sr->vsid;
@@ -343,7 +343,7 @@ static int kvmppc_mmu_book3s_32_esid_to_vsid(struct kvm_vcpu *vcpu, ulong esid,
/* In case we only have one of MSR_IR or MSR_DR set, let's put
that in the real-mode context (and hope RM doesn't access
high memory) */
- switch (vcpu->arch.msr & (MSR_DR|MSR_IR)) {
+ switch (vcpu->arch.shared->msr & (MSR_DR|MSR_IR)) {
case 0:
*vsid = VSID_REAL | esid;
break;
@@ -363,7 +363,7 @@ static int kvmppc_mmu_book3s_32_esid_to_vsid(struct kvm_vcpu *vcpu, ulong esid,
BUG();
}
- if (vcpu->arch.msr & MSR_PR)
+ if (vcpu->arch.shared->msr & MSR_PR)
*vsid |= VSID_PR;
return 0;
diff --git a/arch/powerpc/kvm/book3s_32_mmu_host.c b/arch/powerpc/kvm/book3s_32_mmu_host.c
index 0b51ef8..67b8c38 100644
--- a/arch/powerpc/kvm/book3s_32_mmu_host.c
+++ b/arch/powerpc/kvm/book3s_32_mmu_host.c
@@ -86,7 +86,7 @@ static struct kvmppc_sid_map *find_sid_vsid(struct kvm_vcpu *vcpu, u64 gvsid)
struct kvmppc_sid_map *map;
u16 sid_map_mask;
- if (vcpu->arch.msr & MSR_PR)
+ if (vcpu->arch.shared->msr & MSR_PR)
gvsid |= VSID_PR;
sid_map_mask = kvmppc_sid_hash(vcpu, gvsid);
@@ -253,7 +253,7 @@ static struct kvmppc_sid_map *create_sid_map(struct kvm_vcpu *vcpu, u64 gvsid)
u16 sid_map_mask;
static int backwards_map = 0;
- if (vcpu->arch.msr & MSR_PR)
+ if (vcpu->arch.shared->msr & MSR_PR)
gvsid |= VSID_PR;
/* We might get collisions that trap in preceding order, so let's
diff --git a/arch/powerpc/kvm/book3s_64_mmu.c b/arch/powerpc/kvm/book3s_64_mmu.c
index 4025ea2..58aa840 100644
--- a/arch/powerpc/kvm/book3s_64_mmu.c
+++ b/arch/powerpc/kvm/book3s_64_mmu.c
@@ -180,9 +180,9 @@ do_second:
goto no_page_found;
}
- if ((vcpu->arch.msr & MSR_PR) && slbe->Kp)
+ if ((vcpu->arch.shared->msr & MSR_PR) && slbe->Kp)
key = 4;
- else if (!(vcpu->arch.msr & MSR_PR) && slbe->Ks)
+ else if (!(vcpu->arch.shared->msr & MSR_PR) && slbe->Ks)
key = 4;
for (i=0; i<16; i+=2) {
@@ -381,7 +381,7 @@ static void kvmppc_mmu_book3s_64_slbia(struct kvm_vcpu *vcpu)
for (i = 1; i < vcpu_book3s->slb_nr; i++)
vcpu_book3s->slb[i].valid = false;
- if (vcpu->arch.msr & MSR_IR) {
+ if (vcpu->arch.shared->msr & MSR_IR) {
kvmppc_mmu_flush_segments(vcpu);
kvmppc_mmu_map_segment(vcpu, kvmppc_get_pc(vcpu));
}
@@ -446,13 +446,13 @@ static int kvmppc_mmu_book3s_64_esid_to_vsid(struct kvm_vcpu *vcpu, ulong esid,
struct kvmppc_slb *slb;
u64 gvsid = esid;
- if (vcpu->arch.msr & (MSR_DR|MSR_IR)) {
+ if (vcpu->arch.shared->msr & (MSR_DR|MSR_IR)) {
slb = kvmppc_mmu_book3s_64_find_slbe(to_book3s(vcpu), ea);
if (slb)
gvsid = slb->vsid;
}
- switch (vcpu->arch.msr & (MSR_DR|MSR_IR)) {
+ switch (vcpu->arch.shared->msr & (MSR_DR|MSR_IR)) {
case 0:
*vsid = VSID_REAL | esid;
break;
@@ -473,7 +473,7 @@ static int kvmppc_mmu_book3s_64_esid_to_vsid(struct kvm_vcpu *vcpu, ulong esid,
break;
}
- if (vcpu->arch.msr & MSR_PR)
+ if (vcpu->arch.shared->msr & MSR_PR)
*vsid |= VSID_PR;
return 0;
diff --git a/arch/powerpc/kvm/book3s_64_mmu_host.c b/arch/powerpc/kvm/book3s_64_mmu_host.c
index 384179a..71c1f90 100644
--- a/arch/powerpc/kvm/book3s_64_mmu_host.c
+++ b/arch/powerpc/kvm/book3s_64_mmu_host.c
@@ -66,7 +66,7 @@ static struct kvmppc_sid_map *find_sid_vsid(struct kvm_vcpu *vcpu, u64 gvsid)
struct kvmppc_sid_map *map;
u16 sid_map_mask;
- if (vcpu->arch.msr & MSR_PR)
+ if (vcpu->arch.shared->msr & MSR_PR)
gvsid |= VSID_PR;
sid_map_mask = kvmppc_sid_hash(vcpu, gvsid);
@@ -191,7 +191,7 @@ static struct kvmppc_sid_map *create_sid_map(struct kvm_vcpu *vcpu, u64 gvsid)
u16 sid_map_mask;
static int backwards_map = 0;
- if (vcpu->arch.msr & MSR_PR)
+ if (vcpu->arch.shared->msr & MSR_PR)
gvsid |= VSID_PR;
/* We might get collisions that trap in preceding order, so let's
diff --git a/arch/powerpc/kvm/book3s_emulate.c b/arch/powerpc/kvm/book3s_emulate.c
index c85f906..35d3c16 100644
--- a/arch/powerpc/kvm/book3s_emulate.c
+++ b/arch/powerpc/kvm/book3s_emulate.c
@@ -86,14 +86,15 @@ int kvmppc_core_emulate_op(struct kvm_run *run, struct kvm_vcpu *vcpu,
case 31:
switch (get_xop(inst)) {
case OP_31_XOP_MFMSR:
- kvmppc_set_gpr(vcpu, get_rt(inst), vcpu->arch.msr);
+ kvmppc_set_gpr(vcpu, get_rt(inst),
+ vcpu->arch.shared->msr);
break;
case OP_31_XOP_MTMSRD:
{
ulong rs = kvmppc_get_gpr(vcpu, get_rs(inst));
if (inst & 0x10000) {
- vcpu->arch.msr &= ~(MSR_RI | MSR_EE);
- vcpu->arch.msr |= rs & (MSR_RI | MSR_EE);
+ vcpu->arch.shared->msr &= ~(MSR_RI | MSR_EE);
+ vcpu->arch.shared->msr |= rs & (MSR_RI | MSR_EE);
} else
kvmppc_set_msr(vcpu, rs);
break;
@@ -204,7 +205,7 @@ int kvmppc_core_emulate_op(struct kvm_run *run, struct kvm_vcpu *vcpu,
ra = kvmppc_get_gpr(vcpu, get_ra(inst));
addr = (ra + rb) & ~31ULL;
- if (!(vcpu->arch.msr & MSR_SF))
+ if (!(vcpu->arch.shared->msr & MSR_SF))
addr &= 0xffffffff;
vaddr = addr;
diff --git a/arch/powerpc/kvm/book3s_paired_singles.c b/arch/powerpc/kvm/book3s_paired_singles.c
index 474f2e2..626e6ef 100644
--- a/arch/powerpc/kvm/book3s_paired_singles.c
+++ b/arch/powerpc/kvm/book3s_paired_singles.c
@@ -165,9 +165,10 @@ static inline void kvmppc_sync_qpr(struct kvm_vcpu *vcpu, int rt)
static void kvmppc_inject_pf(struct kvm_vcpu *vcpu, ulong eaddr, bool is_store)
{
u64 dsisr;
+ struct kvm_vcpu_arch_shared *shared = vcpu->arch.shared;
- vcpu->arch.msr = kvmppc_set_field(vcpu->arch.msr, 33, 36, 0);
- vcpu->arch.msr = kvmppc_set_field(vcpu->arch.msr, 42, 47, 0);
+ shared->msr = kvmppc_set_field(shared->msr, 33, 36, 0);
+ shared->msr = kvmppc_set_field(shared->msr, 42, 47, 0);
vcpu->arch.dear = eaddr;
/* Page Fault */
dsisr = kvmppc_set_field(0, 33, 33, 1);
@@ -658,7 +659,7 @@ int kvmppc_emulate_paired_single(struct kvm_run *run, struct kvm_vcpu *vcpu)
if (!kvmppc_inst_is_paired_single(vcpu, inst))
return EMULATE_FAIL;
- if (!(vcpu->arch.msr & MSR_FP)) {
+ if (!(vcpu->arch.shared->msr & MSR_FP)) {
kvmppc_book3s_queue_irqprio(vcpu, BOOK3S_INTERRUPT_FP_UNAVAIL);
return EMULATE_AGAIN;
}
diff --git a/arch/powerpc/kvm/booke.c b/arch/powerpc/kvm/booke.c
index 376b586..ddb4cac 100644
--- a/arch/powerpc/kvm/booke.c
+++ b/arch/powerpc/kvm/booke.c
@@ -62,7 +62,7 @@ void kvmppc_dump_vcpu(struct kvm_vcpu *vcpu)
{
int i;
- printk("pc: %08lx msr: %08lx\n", vcpu->arch.pc, vcpu->arch.msr);
+ printk("pc: %08lx msr: %08llx\n", vcpu->arch.pc, vcpu->arch.shared->msr);
printk("lr: %08lx ctr: %08lx\n", vcpu->arch.lr, vcpu->arch.ctr);
printk("srr0: %08lx srr1: %08lx\n", vcpu->arch.srr0, vcpu->arch.srr1);
@@ -169,34 +169,34 @@ static int kvmppc_booke_irqprio_deliver(struct kvm_vcpu *vcpu,
break;
case BOOKE_IRQPRIO_CRITICAL:
case BOOKE_IRQPRIO_WATCHDOG:
- allowed = vcpu->arch.msr & MSR_CE;
+ allowed = vcpu->arch.shared->msr & MSR_CE;
msr_mask = MSR_ME;
break;
case BOOKE_IRQPRIO_MACHINE_CHECK:
- allowed = vcpu->arch.msr & MSR_ME;
+ allowed = vcpu->arch.shared->msr & MSR_ME;
msr_mask = 0;
break;
case BOOKE_IRQPRIO_EXTERNAL:
case BOOKE_IRQPRIO_DECREMENTER:
case BOOKE_IRQPRIO_FIT:
- allowed = vcpu->arch.msr & MSR_EE;
+ allowed = vcpu->arch.shared->msr & MSR_EE;
msr_mask = MSR_CE|MSR_ME|MSR_DE;
break;
case BOOKE_IRQPRIO_DEBUG:
- allowed = vcpu->arch.msr & MSR_DE;
+ allowed = vcpu->arch.shared->msr & MSR_DE;
msr_mask = MSR_ME;
break;
}
if (allowed) {
vcpu->arch.srr0 = vcpu->arch.pc;
- vcpu->arch.srr1 = vcpu->arch.msr;
+ vcpu->arch.srr1 = vcpu->arch.shared->msr;
vcpu->arch.pc = vcpu->arch.ivpr | vcpu->arch.ivor[priority];
if (update_esr == true)
vcpu->arch.esr = vcpu->arch.queued_esr;
if (update_dear == true)
vcpu->arch.dear = vcpu->arch.queued_dear;
- kvmppc_set_msr(vcpu, vcpu->arch.msr & msr_mask);
+ kvmppc_set_msr(vcpu, vcpu->arch.shared->msr & msr_mask);
clear_bit(priority, &vcpu->arch.pending_exceptions);
}
@@ -265,7 +265,7 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
break;
case BOOKE_INTERRUPT_PROGRAM:
- if (vcpu->arch.msr & MSR_PR) {
+ if (vcpu->arch.shared->msr & MSR_PR) {
/* Program traps generated by user-level software must be handled
* by the guest kernel. */
kvmppc_core_queue_program(vcpu, vcpu->arch.fault_esr);
@@ -467,7 +467,7 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu)
{
vcpu->arch.pc = 0;
- vcpu->arch.msr = 0;
+ vcpu->arch.shared->msr = 0;
kvmppc_set_gpr(vcpu, 1, (16<<20) - 8); /* -8 for the callee-save LR slot */
vcpu->arch.shadow_pid = 1;
@@ -490,7 +490,7 @@ int kvm_arch_vcpu_ioctl_get_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
regs->ctr = vcpu->arch.ctr;
regs->lr = vcpu->arch.lr;
regs->xer = kvmppc_get_xer(vcpu);
- regs->msr = vcpu->arch.msr;
+ regs->msr = vcpu->arch.shared->msr;
regs->srr0 = vcpu->arch.srr0;
regs->srr1 = vcpu->arch.srr1;
regs->pid = vcpu->arch.pid;
diff --git a/arch/powerpc/kvm/booke.h b/arch/powerpc/kvm/booke.h
index d59bcca..88258ac 100644
--- a/arch/powerpc/kvm/booke.h
+++ b/arch/powerpc/kvm/booke.h
@@ -54,12 +54,12 @@ extern unsigned long kvmppc_booke_handlers;
* changing. */
static inline void kvmppc_set_msr(struct kvm_vcpu *vcpu, u32 new_msr)
{
- if ((new_msr & MSR_PR) != (vcpu->arch.msr & MSR_PR))
+ if ((new_msr & MSR_PR) != (vcpu->arch.shared->msr & MSR_PR))
kvmppc_mmu_priv_switch(vcpu, new_msr & MSR_PR);
- vcpu->arch.msr = new_msr;
+ vcpu->arch.shared->msr = new_msr;
- if (vcpu->arch.msr & MSR_WE) {
+ if (vcpu->arch.shared->msr & MSR_WE) {
kvm_vcpu_block(vcpu);
kvmppc_set_exit_type(vcpu, EMULATED_MTMSRWE_EXITS);
};
diff --git a/arch/powerpc/kvm/booke_emulate.c b/arch/powerpc/kvm/booke_emulate.c
index cbc790e..b115203 100644
--- a/arch/powerpc/kvm/booke_emulate.c
+++ b/arch/powerpc/kvm/booke_emulate.c
@@ -62,7 +62,7 @@ int kvmppc_booke_emulate_op(struct kvm_run *run, struct kvm_vcpu *vcpu,
case OP_31_XOP_MFMSR:
rt = get_rt(inst);
- kvmppc_set_gpr(vcpu, rt, vcpu->arch.msr);
+ kvmppc_set_gpr(vcpu, rt, vcpu->arch.shared->msr);
kvmppc_set_exit_type(vcpu, EMULATED_MFMSR_EXITS);
break;
@@ -74,13 +74,13 @@ int kvmppc_booke_emulate_op(struct kvm_run *run, struct kvm_vcpu *vcpu,
case OP_31_XOP_WRTEE:
rs = get_rs(inst);
- vcpu->arch.msr = (vcpu->arch.msr & ~MSR_EE)
+ vcpu->arch.shared->msr = (vcpu->arch.shared->msr & ~MSR_EE)
| (kvmppc_get_gpr(vcpu, rs) & MSR_EE);
kvmppc_set_exit_type(vcpu, EMULATED_WRTEE_EXITS);
break;
case OP_31_XOP_WRTEEI:
- vcpu->arch.msr = (vcpu->arch.msr & ~MSR_EE)
+ vcpu->arch.shared->msr = (vcpu->arch.shared->msr & ~MSR_EE)
| (inst & MSR_EE);
kvmppc_set_exit_type(vcpu, EMULATED_WRTEE_EXITS);
break;
diff --git a/arch/powerpc/kvm/booke_interrupts.S b/arch/powerpc/kvm/booke_interrupts.S
index 380a78c..0498469 100644
--- a/arch/powerpc/kvm/booke_interrupts.S
+++ b/arch/powerpc/kvm/booke_interrupts.S
@@ -415,7 +415,8 @@ lightweight_exit:
lwz r8, VCPU_GPR(r8)(r4)
lwz r3, VCPU_PC(r4)
mtsrr0 r3
- lwz r3, VCPU_MSR(r4)
+ lwz r3, VCPU_SHARED(r4)
+ lwz r3, VCPU_SHARED_MSR(r3)
oris r3, r3, KVMPPC_MSR_MASK@h
ori r3, r3, KVMPPC_MSR_MASK@l
mtsrr1 r3
diff --git a/arch/powerpc/kvm/e500_tlb.c b/arch/powerpc/kvm/e500_tlb.c
index f11ca0f..66845a5 100644
--- a/arch/powerpc/kvm/e500_tlb.c
+++ b/arch/powerpc/kvm/e500_tlb.c
@@ -317,10 +317,10 @@ static inline void kvmppc_e500_shadow_map(struct kvmppc_vcpu_e500 *vcpu_e500,
| MAS1_TID(get_tlb_tid(gtlbe)) | MAS1_TS | MAS1_VALID;
stlbe->mas2 = (gvaddr & MAS2_EPN)
| e500_shadow_mas2_attrib(gtlbe->mas2,
- vcpu_e500->vcpu.arch.msr & MSR_PR);
+ vcpu_e500->vcpu.arch.shared->msr & MSR_PR);
stlbe->mas3 = (hpaddr & MAS3_RPN)
| e500_shadow_mas3_attrib(gtlbe->mas3,
- vcpu_e500->vcpu.arch.msr & MSR_PR);
+ vcpu_e500->vcpu.arch.shared->msr & MSR_PR);
stlbe->mas7 = (hpaddr >> 32) & MAS7_RPN;
trace_kvm_stlb_write(index_of(tlbsel, esel), stlbe->mas1, stlbe->mas2,
@@ -579,28 +579,28 @@ int kvmppc_e500_emul_tlbwe(struct kvm_vcpu *vcpu)
int kvmppc_mmu_itlb_index(struct kvm_vcpu *vcpu, gva_t eaddr)
{
- unsigned int as = !!(vcpu->arch.msr & MSR_IS);
+ unsigned int as = !!(vcpu->arch.shared->msr & MSR_IS);
return kvmppc_e500_tlb_search(vcpu, eaddr, get_cur_pid(vcpu), as);
}
int kvmppc_mmu_dtlb_index(struct kvm_vcpu *vcpu, gva_t eaddr)
{
- unsigned int as = !!(vcpu->arch.msr & MSR_DS);
+ unsigned int as = !!(vcpu->arch.shared->msr & MSR_DS);
return kvmppc_e500_tlb_search(vcpu, eaddr, get_cur_pid(vcpu), as);
}
void kvmppc_mmu_itlb_miss(struct kvm_vcpu *vcpu)
{
- unsigned int as = !!(vcpu->arch.msr & MSR_IS);
+ unsigned int as = !!(vcpu->arch.shared->msr & MSR_IS);
kvmppc_e500_deliver_tlb_miss(vcpu, vcpu->arch.pc, as);
}
void kvmppc_mmu_dtlb_miss(struct kvm_vcpu *vcpu)
{
- unsigned int as = !!(vcpu->arch.msr & MSR_DS);
+ unsigned int as = !!(vcpu->arch.shared->msr & MSR_DS);
kvmppc_e500_deliver_tlb_miss(vcpu, vcpu->arch.fault_dear, as);
}
diff --git a/arch/powerpc/kvm/e500_tlb.h b/arch/powerpc/kvm/e500_tlb.h
index d28e301..458946b 100644
--- a/arch/powerpc/kvm/e500_tlb.h
+++ b/arch/powerpc/kvm/e500_tlb.h
@@ -171,7 +171,7 @@ static inline int tlbe_is_host_safe(const struct kvm_vcpu *vcpu,
/* Does it match current guest AS? */
/* XXX what about IS != DS? */
- if (get_tlb_ts(tlbe) != !!(vcpu->arch.msr & MSR_IS))
+ if (get_tlb_ts(tlbe) != !!(vcpu->arch.shared->msr & MSR_IS))
return 0;
gpa = get_tlb_raddr(tlbe);
diff --git a/arch/powerpc/kvm/powerpc.c b/arch/powerpc/kvm/powerpc.c
index 72a4ad8..22f6fa2 100644
--- a/arch/powerpc/kvm/powerpc.c
+++ b/arch/powerpc/kvm/powerpc.c
@@ -38,7 +38,8 @@
int kvm_arch_vcpu_runnable(struct kvm_vcpu *v)
{
- return !(v->arch.msr & MSR_WE) || !!(v->arch.pending_exceptions);
+ return !(v->arch.shared->msr & MSR_WE) ||
+ !!(v->arch.pending_exceptions);
}
--
1.6.0.2
^ permalink raw reply related [flat|nested] 227+ messages in thread* [PATCH 02/26] KVM: PPC: Convert MSR to shared page
@ 2010-06-25 23:24 ` Alexander Graf
0 siblings, 0 replies; 227+ messages in thread
From: Alexander Graf @ 2010-06-25 23:24 UTC (permalink / raw)
To: kvm-ppc; +Cc: linuxppc-dev, KVM list
One of the most obvious registers to share with the guest directly is the
MSR. The MSR contains the "interrupts enabled" flag which the guest has to
toggle in critical sections.
So in order to bring the overhead of interrupt en- and disabling down, let's
put msr into the shared page. Keep in mind that even though you can fully read
its contents, writing to it doesn't always update all state. There are a few
safe fields that don't require hypervisor interaction. See the guest
implementation that follows later for reference.
Signed-off-by: Alexander Graf <agraf@suse.de>
---
arch/powerpc/include/asm/kvm_host.h | 1 -
arch/powerpc/include/asm/kvm_para.h | 1 +
arch/powerpc/kernel/asm-offsets.c | 2 +-
arch/powerpc/kvm/44x_tlb.c | 8 ++--
arch/powerpc/kvm/book3s.c | 65 ++++++++++++++++--------------
arch/powerpc/kvm/book3s_32_mmu.c | 12 +++---
arch/powerpc/kvm/book3s_32_mmu_host.c | 4 +-
arch/powerpc/kvm/book3s_64_mmu.c | 12 +++---
arch/powerpc/kvm/book3s_64_mmu_host.c | 4 +-
arch/powerpc/kvm/book3s_emulate.c | 9 ++--
arch/powerpc/kvm/book3s_paired_singles.c | 7 ++-
arch/powerpc/kvm/booke.c | 20 +++++-----
arch/powerpc/kvm/booke.h | 6 +-
arch/powerpc/kvm/booke_emulate.c | 6 +-
arch/powerpc/kvm/booke_interrupts.S | 3 +-
arch/powerpc/kvm/e500_tlb.c | 12 +++---
arch/powerpc/kvm/e500_tlb.h | 2 +-
arch/powerpc/kvm/powerpc.c | 3 +-
18 files changed, 93 insertions(+), 84 deletions(-)
diff --git a/arch/powerpc/include/asm/kvm_host.h b/arch/powerpc/include/asm/kvm_host.h
index bca9391..249c242 100644
--- a/arch/powerpc/include/asm/kvm_host.h
+++ b/arch/powerpc/include/asm/kvm_host.h
@@ -210,7 +210,6 @@ struct kvm_vcpu_arch {
u32 cr;
#endif
- ulong msr;
#ifdef CONFIG_PPC_BOOK3S
ulong shadow_msr;
ulong hflags;
diff --git a/arch/powerpc/include/asm/kvm_para.h b/arch/powerpc/include/asm/kvm_para.h
index 1485ba8..a17dc52 100644
--- a/arch/powerpc/include/asm/kvm_para.h
+++ b/arch/powerpc/include/asm/kvm_para.h
@@ -23,6 +23,7 @@
#include <linux/types.h>
struct kvm_vcpu_arch_shared {
+ __u64 msr;
};
#ifdef __KERNEL__
diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c
index 944f593..a55d47e 100644
--- a/arch/powerpc/kernel/asm-offsets.c
+++ b/arch/powerpc/kernel/asm-offsets.c
@@ -394,13 +394,13 @@ int main(void)
DEFINE(VCPU_HOST_STACK, offsetof(struct kvm_vcpu, arch.host_stack));
DEFINE(VCPU_HOST_PID, offsetof(struct kvm_vcpu, arch.host_pid));
DEFINE(VCPU_GPRS, offsetof(struct kvm_vcpu, arch.gpr));
- DEFINE(VCPU_MSR, offsetof(struct kvm_vcpu, arch.msr));
DEFINE(VCPU_SPRG4, offsetof(struct kvm_vcpu, arch.sprg4));
DEFINE(VCPU_SPRG5, offsetof(struct kvm_vcpu, arch.sprg5));
DEFINE(VCPU_SPRG6, offsetof(struct kvm_vcpu, arch.sprg6));
DEFINE(VCPU_SPRG7, offsetof(struct kvm_vcpu, arch.sprg7));
DEFINE(VCPU_SHADOW_PID, offsetof(struct kvm_vcpu, arch.shadow_pid));
DEFINE(VCPU_SHARED, offsetof(struct kvm_vcpu, arch.shared));
+ DEFINE(VCPU_SHARED_MSR, offsetof(struct kvm_vcpu_arch_shared, msr));
/* book3s */
#ifdef CONFIG_PPC_BOOK3S
diff --git a/arch/powerpc/kvm/44x_tlb.c b/arch/powerpc/kvm/44x_tlb.c
index 8123125..4cbbca7 100644
--- a/arch/powerpc/kvm/44x_tlb.c
+++ b/arch/powerpc/kvm/44x_tlb.c
@@ -221,14 +221,14 @@ gpa_t kvmppc_mmu_xlate(struct kvm_vcpu *vcpu, unsigned int gtlb_index,
int kvmppc_mmu_itlb_index(struct kvm_vcpu *vcpu, gva_t eaddr)
{
- unsigned int as = !!(vcpu->arch.msr & MSR_IS);
+ unsigned int as = !!(vcpu->arch.shared->msr & MSR_IS);
return kvmppc_44x_tlb_index(vcpu, eaddr, vcpu->arch.pid, as);
}
int kvmppc_mmu_dtlb_index(struct kvm_vcpu *vcpu, gva_t eaddr)
{
- unsigned int as = !!(vcpu->arch.msr & MSR_DS);
+ unsigned int as = !!(vcpu->arch.shared->msr & MSR_DS);
return kvmppc_44x_tlb_index(vcpu, eaddr, vcpu->arch.pid, as);
}
@@ -353,7 +353,7 @@ void kvmppc_mmu_map(struct kvm_vcpu *vcpu, u64 gvaddr, gpa_t gpaddr,
stlbe.word1 = (hpaddr & 0xfffffc00) | ((hpaddr >> 32) & 0xf);
stlbe.word2 = kvmppc_44x_tlb_shadow_attrib(flags,
- vcpu->arch.msr & MSR_PR);
+ vcpu->arch.shared->msr & MSR_PR);
stlbe.tid = !(asid & 0xff);
/* Keep track of the reference so we can properly release it later. */
@@ -422,7 +422,7 @@ static int tlbe_is_host_safe(const struct kvm_vcpu *vcpu,
/* Does it match current guest AS? */
/* XXX what about IS != DS? */
- if (get_tlb_ts(tlbe) != !!(vcpu->arch.msr & MSR_IS))
+ if (get_tlb_ts(tlbe) != !!(vcpu->arch.shared->msr & MSR_IS))
return 0;
gpa = get_tlb_raddr(tlbe);
diff --git a/arch/powerpc/kvm/book3s.c b/arch/powerpc/kvm/book3s.c
index ba79b35..3dd3003 100644
--- a/arch/powerpc/kvm/book3s.c
+++ b/arch/powerpc/kvm/book3s.c
@@ -115,31 +115,31 @@ static u32 kvmppc_get_dec(struct kvm_vcpu *vcpu)
static void kvmppc_recalc_shadow_msr(struct kvm_vcpu *vcpu)
{
- vcpu->arch.shadow_msr = vcpu->arch.msr;
+ ulong smsr = vcpu->arch.shared->msr;
+
/* Guest MSR values */
- vcpu->arch.shadow_msr &= MSR_FE0 | MSR_FE1 | MSR_SF | MSR_SE |
- MSR_BE | MSR_DE;
+ smsr &= MSR_FE0 | MSR_FE1 | MSR_SF | MSR_SE | MSR_BE | MSR_DE;
/* Process MSR values */
- vcpu->arch.shadow_msr |= MSR_ME | MSR_RI | MSR_IR | MSR_DR | MSR_PR |
- MSR_EE;
+ smsr |= MSR_ME | MSR_RI | MSR_IR | MSR_DR | MSR_PR | MSR_EE;
/* External providers the guest reserved */
- vcpu->arch.shadow_msr |= (vcpu->arch.msr & vcpu->arch.guest_owned_ext);
+ smsr |= (vcpu->arch.shared->msr & vcpu->arch.guest_owned_ext);
/* 64-bit Process MSR values */
#ifdef CONFIG_PPC_BOOK3S_64
- vcpu->arch.shadow_msr |= MSR_ISF | MSR_HV;
+ smsr |= MSR_ISF | MSR_HV;
#endif
+ vcpu->arch.shadow_msr = smsr;
}
void kvmppc_set_msr(struct kvm_vcpu *vcpu, u64 msr)
{
- ulong old_msr = vcpu->arch.msr;
+ ulong old_msr = vcpu->arch.shared->msr;
#ifdef EXIT_DEBUG
printk(KERN_INFO "KVM: Set MSR to 0x%llx\n", msr);
#endif
msr &= to_book3s(vcpu)->msr_mask;
- vcpu->arch.msr = msr;
+ vcpu->arch.shared->msr = msr;
kvmppc_recalc_shadow_msr(vcpu);
if (msr & (MSR_WE|MSR_POW)) {
@@ -149,21 +149,21 @@ void kvmppc_set_msr(struct kvm_vcpu *vcpu, u64 msr)
}
}
- if ((vcpu->arch.msr & (MSR_PR|MSR_IR|MSR_DR)) !=
+ if ((vcpu->arch.shared->msr & (MSR_PR|MSR_IR|MSR_DR)) !=
(old_msr & (MSR_PR|MSR_IR|MSR_DR))) {
kvmppc_mmu_flush_segments(vcpu);
kvmppc_mmu_map_segment(vcpu, kvmppc_get_pc(vcpu));
}
/* Preload FPU if it's enabled */
- if (vcpu->arch.msr & MSR_FP)
+ if (vcpu->arch.shared->msr & MSR_FP)
kvmppc_handle_ext(vcpu, BOOK3S_INTERRUPT_FP_UNAVAIL, MSR_FP);
}
void kvmppc_inject_interrupt(struct kvm_vcpu *vcpu, int vec, u64 flags)
{
vcpu->arch.srr0 = kvmppc_get_pc(vcpu);
- vcpu->arch.srr1 = vcpu->arch.msr | flags;
+ vcpu->arch.srr1 = vcpu->arch.shared->msr | flags;
kvmppc_set_pc(vcpu, to_book3s(vcpu)->hior + vec);
vcpu->arch.mmu.reset_msr(vcpu);
}
@@ -254,11 +254,11 @@ int kvmppc_book3s_irqprio_deliver(struct kvm_vcpu *vcpu, unsigned int priority)
switch (priority) {
case BOOK3S_IRQPRIO_DECREMENTER:
- deliver = vcpu->arch.msr & MSR_EE;
+ deliver = vcpu->arch.shared->msr & MSR_EE;
vec = BOOK3S_INTERRUPT_DECREMENTER;
break;
case BOOK3S_IRQPRIO_EXTERNAL:
- deliver = vcpu->arch.msr & MSR_EE;
+ deliver = vcpu->arch.shared->msr & MSR_EE;
vec = BOOK3S_INTERRUPT_EXTERNAL;
break;
case BOOK3S_IRQPRIO_SYSTEM_RESET:
@@ -437,7 +437,7 @@ static void kvmppc_patch_dcbz(struct kvm_vcpu *vcpu, struct kvmppc_pte *pte)
static int kvmppc_xlate(struct kvm_vcpu *vcpu, ulong eaddr, bool data,
struct kvmppc_pte *pte)
{
- int relocated = (vcpu->arch.msr & (data ? MSR_DR : MSR_IR));
+ int relocated = (vcpu->arch.shared->msr & (data ? MSR_DR : MSR_IR));
int r;
if (relocated) {
@@ -545,8 +545,8 @@ int kvmppc_handle_pagefault(struct kvm_run *run, struct kvm_vcpu *vcpu,
int page_found = 0;
struct kvmppc_pte pte;
bool is_mmio = false;
- bool dr = (vcpu->arch.msr & MSR_DR) ? true : false;
- bool ir = (vcpu->arch.msr & MSR_IR) ? true : false;
+ bool dr = (vcpu->arch.shared->msr & MSR_DR) ? true : false;
+ bool ir = (vcpu->arch.shared->msr & MSR_IR) ? true : false;
u64 vsid;
relocated = data ? dr : ir;
@@ -563,7 +563,7 @@ int kvmppc_handle_pagefault(struct kvm_run *run, struct kvm_vcpu *vcpu,
pte.vpage = eaddr >> 12;
}
- switch (vcpu->arch.msr & (MSR_DR|MSR_IR)) {
+ switch (vcpu->arch.shared->msr & (MSR_DR|MSR_IR)) {
case 0:
pte.vpage |= ((u64)VSID_REAL << (SID_SHIFT - 12));
break;
@@ -571,7 +571,7 @@ int kvmppc_handle_pagefault(struct kvm_run *run, struct kvm_vcpu *vcpu,
case MSR_IR:
vcpu->arch.mmu.esid_to_vsid(vcpu, eaddr >> SID_SHIFT, &vsid);
- if ((vcpu->arch.msr & (MSR_DR|MSR_IR)) == MSR_DR)
+ if ((vcpu->arch.shared->msr & (MSR_DR|MSR_IR)) == MSR_DR)
pte.vpage |= ((u64)VSID_REAL_DR << (SID_SHIFT - 12));
else
pte.vpage |= ((u64)VSID_REAL_IR << (SID_SHIFT - 12));
@@ -596,14 +596,16 @@ int kvmppc_handle_pagefault(struct kvm_run *run, struct kvm_vcpu *vcpu,
/* Page not found in guest PTE entries */
vcpu->arch.dear = kvmppc_get_fault_dar(vcpu);
to_book3s(vcpu)->dsisr = to_svcpu(vcpu)->fault_dsisr;
- vcpu->arch.msr |= (to_svcpu(vcpu)->shadow_srr1 & 0x00000000f8000000ULL);
+ vcpu->arch.shared->msr |=
+ (to_svcpu(vcpu)->shadow_srr1 & 0x00000000f8000000ULL);
kvmppc_book3s_queue_irqprio(vcpu, vec);
} else if (page_found == -EPERM) {
/* Storage protection */
vcpu->arch.dear = kvmppc_get_fault_dar(vcpu);
to_book3s(vcpu)->dsisr = to_svcpu(vcpu)->fault_dsisr & ~DSISR_NOHPTE;
to_book3s(vcpu)->dsisr |= DSISR_PROTFAULT;
- vcpu->arch.msr |= (to_svcpu(vcpu)->shadow_srr1 & 0x00000000f8000000ULL);
+ vcpu->arch.shared->msr |=
+ (to_svcpu(vcpu)->shadow_srr1 & 0x00000000f8000000ULL);
kvmppc_book3s_queue_irqprio(vcpu, vec);
} else if (page_found == -EINVAL) {
/* Page not found in guest SLB */
@@ -695,9 +697,11 @@ static int kvmppc_read_inst(struct kvm_vcpu *vcpu)
ret = kvmppc_ld(vcpu, &srr0, sizeof(u32), &last_inst, false);
if (ret == -ENOENT) {
- vcpu->arch.msr = kvmppc_set_field(vcpu->arch.msr, 33, 33, 1);
- vcpu->arch.msr = kvmppc_set_field(vcpu->arch.msr, 34, 36, 0);
- vcpu->arch.msr = kvmppc_set_field(vcpu->arch.msr, 42, 47, 0);
+ ulong msr = vcpu->arch.shared->msr;
+
+ msr = kvmppc_set_field(msr, 33, 33, 1);
+ msr = kvmppc_set_field(msr, 34, 36, 0);
+ vcpu->arch.shared->msr = kvmppc_set_field(msr, 42, 47, 0);
kvmppc_book3s_queue_irqprio(vcpu, BOOK3S_INTERRUPT_INST_STORAGE);
return EMULATE_AGAIN;
}
@@ -736,7 +740,7 @@ static int kvmppc_handle_ext(struct kvm_vcpu *vcpu, unsigned int exit_nr,
if (vcpu->arch.hflags & BOOK3S_HFLAG_PAIRED_SINGLE)
return RESUME_GUEST;
- if (!(vcpu->arch.msr & msr)) {
+ if (!(vcpu->arch.shared->msr & msr)) {
kvmppc_book3s_queue_irqprio(vcpu, exit_nr);
return RESUME_GUEST;
}
@@ -804,7 +808,7 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
if ((exit_nr != 0x900) && (exit_nr != 0x500))
printk(KERN_EMERG "exit_nr=0x%x | pc=0x%lx | dar=0x%lx | msr=0x%lx\n",
exit_nr, kvmppc_get_pc(vcpu), kvmppc_get_fault_dar(vcpu),
- vcpu->arch.msr);
+ vcpu->arch.shared->msr);
#endif
kvm_resched(vcpu);
switch (exit_nr) {
@@ -836,7 +840,8 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
kvmppc_mmu_pte_flush(vcpu, kvmppc_get_pc(vcpu), ~0xFFFUL);
r = RESUME_GUEST;
} else {
- vcpu->arch.msr |= to_svcpu(vcpu)->shadow_srr1 & 0x58000000;
+ vcpu->arch.shared->msr |=
+ to_svcpu(vcpu)->shadow_srr1 & 0x58000000;
kvmppc_book3s_queue_irqprio(vcpu, exit_nr);
kvmppc_mmu_pte_flush(vcpu, kvmppc_get_pc(vcpu), ~0xFFFUL);
r = RESUME_GUEST;
@@ -904,7 +909,7 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
program_interrupt:
flags = to_svcpu(vcpu)->shadow_srr1 & 0x1f0000ull;
- if (vcpu->arch.msr & MSR_PR) {
+ if (vcpu->arch.shared->msr & MSR_PR) {
#ifdef EXIT_DEBUG
printk(KERN_INFO "Userspace triggered 0x700 exception at 0x%lx (0x%x)\n", kvmppc_get_pc(vcpu), kvmppc_get_last_inst(vcpu));
#endif
@@ -1052,7 +1057,7 @@ int kvm_arch_vcpu_ioctl_get_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
regs->ctr = kvmppc_get_ctr(vcpu);
regs->lr = kvmppc_get_lr(vcpu);
regs->xer = kvmppc_get_xer(vcpu);
- regs->msr = vcpu->arch.msr;
+ regs->msr = vcpu->arch.shared->msr;
regs->srr0 = vcpu->arch.srr0;
regs->srr1 = vcpu->arch.srr1;
regs->pid = vcpu->arch.pid;
@@ -1358,7 +1363,7 @@ int __kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
local_irq_enable();
/* Preload FPU if it's enabled */
- if (vcpu->arch.msr & MSR_FP)
+ if (vcpu->arch.shared->msr & MSR_FP)
kvmppc_handle_ext(vcpu, BOOK3S_INTERRUPT_FP_UNAVAIL, MSR_FP);
ret = __kvmppc_vcpu_entry(kvm_run, vcpu);
diff --git a/arch/powerpc/kvm/book3s_32_mmu.c b/arch/powerpc/kvm/book3s_32_mmu.c
index 079760b..41130c8 100644
--- a/arch/powerpc/kvm/book3s_32_mmu.c
+++ b/arch/powerpc/kvm/book3s_32_mmu.c
@@ -133,7 +133,7 @@ static int kvmppc_mmu_book3s_32_xlate_bat(struct kvm_vcpu *vcpu, gva_t eaddr,
else
bat = &vcpu_book3s->ibat[i];
- if (vcpu->arch.msr & MSR_PR) {
+ if (vcpu->arch.shared->msr & MSR_PR) {
if (!bat->vp)
continue;
} else {
@@ -214,8 +214,8 @@ static int kvmppc_mmu_book3s_32_xlate_pte(struct kvm_vcpu *vcpu, gva_t eaddr,
pte->raddr = (pteg[i+1] & ~(0xFFFULL)) | (eaddr & 0xFFF);
pp = pteg[i+1] & 3;
- if ((sre->Kp && (vcpu->arch.msr & MSR_PR)) ||
- (sre->Ks && !(vcpu->arch.msr & MSR_PR)))
+ if ((sre->Kp && (vcpu->arch.shared->msr & MSR_PR)) ||
+ (sre->Ks && !(vcpu->arch.shared->msr & MSR_PR)))
pp |= 4;
pte->may_write = false;
@@ -334,7 +334,7 @@ static int kvmppc_mmu_book3s_32_esid_to_vsid(struct kvm_vcpu *vcpu, ulong esid,
struct kvmppc_sr *sr;
u64 gvsid = esid;
- if (vcpu->arch.msr & (MSR_DR|MSR_IR)) {
+ if (vcpu->arch.shared->msr & (MSR_DR|MSR_IR)) {
sr = find_sr(to_book3s(vcpu), ea);
if (sr->valid)
gvsid = sr->vsid;
@@ -343,7 +343,7 @@ static int kvmppc_mmu_book3s_32_esid_to_vsid(struct kvm_vcpu *vcpu, ulong esid,
/* In case we only have one of MSR_IR or MSR_DR set, let's put
that in the real-mode context (and hope RM doesn't access
high memory) */
- switch (vcpu->arch.msr & (MSR_DR|MSR_IR)) {
+ switch (vcpu->arch.shared->msr & (MSR_DR|MSR_IR)) {
case 0:
*vsid = VSID_REAL | esid;
break;
@@ -363,7 +363,7 @@ static int kvmppc_mmu_book3s_32_esid_to_vsid(struct kvm_vcpu *vcpu, ulong esid,
BUG();
}
- if (vcpu->arch.msr & MSR_PR)
+ if (vcpu->arch.shared->msr & MSR_PR)
*vsid |= VSID_PR;
return 0;
diff --git a/arch/powerpc/kvm/book3s_32_mmu_host.c b/arch/powerpc/kvm/book3s_32_mmu_host.c
index 0b51ef8..67b8c38 100644
--- a/arch/powerpc/kvm/book3s_32_mmu_host.c
+++ b/arch/powerpc/kvm/book3s_32_mmu_host.c
@@ -86,7 +86,7 @@ static struct kvmppc_sid_map *find_sid_vsid(struct kvm_vcpu *vcpu, u64 gvsid)
struct kvmppc_sid_map *map;
u16 sid_map_mask;
- if (vcpu->arch.msr & MSR_PR)
+ if (vcpu->arch.shared->msr & MSR_PR)
gvsid |= VSID_PR;
sid_map_mask = kvmppc_sid_hash(vcpu, gvsid);
@@ -253,7 +253,7 @@ static struct kvmppc_sid_map *create_sid_map(struct kvm_vcpu *vcpu, u64 gvsid)
u16 sid_map_mask;
static int backwards_map = 0;
- if (vcpu->arch.msr & MSR_PR)
+ if (vcpu->arch.shared->msr & MSR_PR)
gvsid |= VSID_PR;
/* We might get collisions that trap in preceding order, so let's
diff --git a/arch/powerpc/kvm/book3s_64_mmu.c b/arch/powerpc/kvm/book3s_64_mmu.c
index 4025ea2..58aa840 100644
--- a/arch/powerpc/kvm/book3s_64_mmu.c
+++ b/arch/powerpc/kvm/book3s_64_mmu.c
@@ -180,9 +180,9 @@ do_second:
goto no_page_found;
}
- if ((vcpu->arch.msr & MSR_PR) && slbe->Kp)
+ if ((vcpu->arch.shared->msr & MSR_PR) && slbe->Kp)
key = 4;
- else if (!(vcpu->arch.msr & MSR_PR) && slbe->Ks)
+ else if (!(vcpu->arch.shared->msr & MSR_PR) && slbe->Ks)
key = 4;
for (i=0; i<16; i+=2) {
@@ -381,7 +381,7 @@ static void kvmppc_mmu_book3s_64_slbia(struct kvm_vcpu *vcpu)
for (i = 1; i < vcpu_book3s->slb_nr; i++)
vcpu_book3s->slb[i].valid = false;
- if (vcpu->arch.msr & MSR_IR) {
+ if (vcpu->arch.shared->msr & MSR_IR) {
kvmppc_mmu_flush_segments(vcpu);
kvmppc_mmu_map_segment(vcpu, kvmppc_get_pc(vcpu));
}
@@ -446,13 +446,13 @@ static int kvmppc_mmu_book3s_64_esid_to_vsid(struct kvm_vcpu *vcpu, ulong esid,
struct kvmppc_slb *slb;
u64 gvsid = esid;
- if (vcpu->arch.msr & (MSR_DR|MSR_IR)) {
+ if (vcpu->arch.shared->msr & (MSR_DR|MSR_IR)) {
slb = kvmppc_mmu_book3s_64_find_slbe(to_book3s(vcpu), ea);
if (slb)
gvsid = slb->vsid;
}
- switch (vcpu->arch.msr & (MSR_DR|MSR_IR)) {
+ switch (vcpu->arch.shared->msr & (MSR_DR|MSR_IR)) {
case 0:
*vsid = VSID_REAL | esid;
break;
@@ -473,7 +473,7 @@ static int kvmppc_mmu_book3s_64_esid_to_vsid(struct kvm_vcpu *vcpu, ulong esid,
break;
}
- if (vcpu->arch.msr & MSR_PR)
+ if (vcpu->arch.shared->msr & MSR_PR)
*vsid |= VSID_PR;
return 0;
diff --git a/arch/powerpc/kvm/book3s_64_mmu_host.c b/arch/powerpc/kvm/book3s_64_mmu_host.c
index 384179a..71c1f90 100644
--- a/arch/powerpc/kvm/book3s_64_mmu_host.c
+++ b/arch/powerpc/kvm/book3s_64_mmu_host.c
@@ -66,7 +66,7 @@ static struct kvmppc_sid_map *find_sid_vsid(struct kvm_vcpu *vcpu, u64 gvsid)
struct kvmppc_sid_map *map;
u16 sid_map_mask;
- if (vcpu->arch.msr & MSR_PR)
+ if (vcpu->arch.shared->msr & MSR_PR)
gvsid |= VSID_PR;
sid_map_mask = kvmppc_sid_hash(vcpu, gvsid);
@@ -191,7 +191,7 @@ static struct kvmppc_sid_map *create_sid_map(struct kvm_vcpu *vcpu, u64 gvsid)
u16 sid_map_mask;
static int backwards_map = 0;
- if (vcpu->arch.msr & MSR_PR)
+ if (vcpu->arch.shared->msr & MSR_PR)
gvsid |= VSID_PR;
/* We might get collisions that trap in preceding order, so let's
diff --git a/arch/powerpc/kvm/book3s_emulate.c b/arch/powerpc/kvm/book3s_emulate.c
index c85f906..35d3c16 100644
--- a/arch/powerpc/kvm/book3s_emulate.c
+++ b/arch/powerpc/kvm/book3s_emulate.c
@@ -86,14 +86,15 @@ int kvmppc_core_emulate_op(struct kvm_run *run, struct kvm_vcpu *vcpu,
case 31:
switch (get_xop(inst)) {
case OP_31_XOP_MFMSR:
- kvmppc_set_gpr(vcpu, get_rt(inst), vcpu->arch.msr);
+ kvmppc_set_gpr(vcpu, get_rt(inst),
+ vcpu->arch.shared->msr);
break;
case OP_31_XOP_MTMSRD:
{
ulong rs = kvmppc_get_gpr(vcpu, get_rs(inst));
if (inst & 0x10000) {
- vcpu->arch.msr &= ~(MSR_RI | MSR_EE);
- vcpu->arch.msr |= rs & (MSR_RI | MSR_EE);
+ vcpu->arch.shared->msr &= ~(MSR_RI | MSR_EE);
+ vcpu->arch.shared->msr |= rs & (MSR_RI | MSR_EE);
} else
kvmppc_set_msr(vcpu, rs);
break;
@@ -204,7 +205,7 @@ int kvmppc_core_emulate_op(struct kvm_run *run, struct kvm_vcpu *vcpu,
ra = kvmppc_get_gpr(vcpu, get_ra(inst));
addr = (ra + rb) & ~31ULL;
- if (!(vcpu->arch.msr & MSR_SF))
+ if (!(vcpu->arch.shared->msr & MSR_SF))
addr &= 0xffffffff;
vaddr = addr;
diff --git a/arch/powerpc/kvm/book3s_paired_singles.c b/arch/powerpc/kvm/book3s_paired_singles.c
index 474f2e2..626e6ef 100644
--- a/arch/powerpc/kvm/book3s_paired_singles.c
+++ b/arch/powerpc/kvm/book3s_paired_singles.c
@@ -165,9 +165,10 @@ static inline void kvmppc_sync_qpr(struct kvm_vcpu *vcpu, int rt)
static void kvmppc_inject_pf(struct kvm_vcpu *vcpu, ulong eaddr, bool is_store)
{
u64 dsisr;
+ struct kvm_vcpu_arch_shared *shared = vcpu->arch.shared;
- vcpu->arch.msr = kvmppc_set_field(vcpu->arch.msr, 33, 36, 0);
- vcpu->arch.msr = kvmppc_set_field(vcpu->arch.msr, 42, 47, 0);
+ shared->msr = kvmppc_set_field(shared->msr, 33, 36, 0);
+ shared->msr = kvmppc_set_field(shared->msr, 42, 47, 0);
vcpu->arch.dear = eaddr;
/* Page Fault */
dsisr = kvmppc_set_field(0, 33, 33, 1);
@@ -658,7 +659,7 @@ int kvmppc_emulate_paired_single(struct kvm_run *run, struct kvm_vcpu *vcpu)
if (!kvmppc_inst_is_paired_single(vcpu, inst))
return EMULATE_FAIL;
- if (!(vcpu->arch.msr & MSR_FP)) {
+ if (!(vcpu->arch.shared->msr & MSR_FP)) {
kvmppc_book3s_queue_irqprio(vcpu, BOOK3S_INTERRUPT_FP_UNAVAIL);
return EMULATE_AGAIN;
}
diff --git a/arch/powerpc/kvm/booke.c b/arch/powerpc/kvm/booke.c
index 376b586..ddb4cac 100644
--- a/arch/powerpc/kvm/booke.c
+++ b/arch/powerpc/kvm/booke.c
@@ -62,7 +62,7 @@ void kvmppc_dump_vcpu(struct kvm_vcpu *vcpu)
{
int i;
- printk("pc: %08lx msr: %08lx\n", vcpu->arch.pc, vcpu->arch.msr);
+ printk("pc: %08lx msr: %08llx\n", vcpu->arch.pc, vcpu->arch.shared->msr);
printk("lr: %08lx ctr: %08lx\n", vcpu->arch.lr, vcpu->arch.ctr);
printk("srr0: %08lx srr1: %08lx\n", vcpu->arch.srr0, vcpu->arch.srr1);
@@ -169,34 +169,34 @@ static int kvmppc_booke_irqprio_deliver(struct kvm_vcpu *vcpu,
break;
case BOOKE_IRQPRIO_CRITICAL:
case BOOKE_IRQPRIO_WATCHDOG:
- allowed = vcpu->arch.msr & MSR_CE;
+ allowed = vcpu->arch.shared->msr & MSR_CE;
msr_mask = MSR_ME;
break;
case BOOKE_IRQPRIO_MACHINE_CHECK:
- allowed = vcpu->arch.msr & MSR_ME;
+ allowed = vcpu->arch.shared->msr & MSR_ME;
msr_mask = 0;
break;
case BOOKE_IRQPRIO_EXTERNAL:
case BOOKE_IRQPRIO_DECREMENTER:
case BOOKE_IRQPRIO_FIT:
- allowed = vcpu->arch.msr & MSR_EE;
+ allowed = vcpu->arch.shared->msr & MSR_EE;
msr_mask = MSR_CE|MSR_ME|MSR_DE;
break;
case BOOKE_IRQPRIO_DEBUG:
- allowed = vcpu->arch.msr & MSR_DE;
+ allowed = vcpu->arch.shared->msr & MSR_DE;
msr_mask = MSR_ME;
break;
}
if (allowed) {
vcpu->arch.srr0 = vcpu->arch.pc;
- vcpu->arch.srr1 = vcpu->arch.msr;
+ vcpu->arch.srr1 = vcpu->arch.shared->msr;
vcpu->arch.pc = vcpu->arch.ivpr | vcpu->arch.ivor[priority];
if (update_esr == true)
vcpu->arch.esr = vcpu->arch.queued_esr;
if (update_dear == true)
vcpu->arch.dear = vcpu->arch.queued_dear;
- kvmppc_set_msr(vcpu, vcpu->arch.msr & msr_mask);
+ kvmppc_set_msr(vcpu, vcpu->arch.shared->msr & msr_mask);
clear_bit(priority, &vcpu->arch.pending_exceptions);
}
@@ -265,7 +265,7 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
break;
case BOOKE_INTERRUPT_PROGRAM:
- if (vcpu->arch.msr & MSR_PR) {
+ if (vcpu->arch.shared->msr & MSR_PR) {
/* Program traps generated by user-level software must be handled
* by the guest kernel. */
kvmppc_core_queue_program(vcpu, vcpu->arch.fault_esr);
@@ -467,7 +467,7 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu)
{
vcpu->arch.pc = 0;
- vcpu->arch.msr = 0;
+ vcpu->arch.shared->msr = 0;
kvmppc_set_gpr(vcpu, 1, (16<<20) - 8); /* -8 for the callee-save LR slot */
vcpu->arch.shadow_pid = 1;
@@ -490,7 +490,7 @@ int kvm_arch_vcpu_ioctl_get_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
regs->ctr = vcpu->arch.ctr;
regs->lr = vcpu->arch.lr;
regs->xer = kvmppc_get_xer(vcpu);
- regs->msr = vcpu->arch.msr;
+ regs->msr = vcpu->arch.shared->msr;
regs->srr0 = vcpu->arch.srr0;
regs->srr1 = vcpu->arch.srr1;
regs->pid = vcpu->arch.pid;
diff --git a/arch/powerpc/kvm/booke.h b/arch/powerpc/kvm/booke.h
index d59bcca..88258ac 100644
--- a/arch/powerpc/kvm/booke.h
+++ b/arch/powerpc/kvm/booke.h
@@ -54,12 +54,12 @@ extern unsigned long kvmppc_booke_handlers;
* changing. */
static inline void kvmppc_set_msr(struct kvm_vcpu *vcpu, u32 new_msr)
{
- if ((new_msr & MSR_PR) != (vcpu->arch.msr & MSR_PR))
+ if ((new_msr & MSR_PR) != (vcpu->arch.shared->msr & MSR_PR))
kvmppc_mmu_priv_switch(vcpu, new_msr & MSR_PR);
- vcpu->arch.msr = new_msr;
+ vcpu->arch.shared->msr = new_msr;
- if (vcpu->arch.msr & MSR_WE) {
+ if (vcpu->arch.shared->msr & MSR_WE) {
kvm_vcpu_block(vcpu);
kvmppc_set_exit_type(vcpu, EMULATED_MTMSRWE_EXITS);
};
diff --git a/arch/powerpc/kvm/booke_emulate.c b/arch/powerpc/kvm/booke_emulate.c
index cbc790e..b115203 100644
--- a/arch/powerpc/kvm/booke_emulate.c
+++ b/arch/powerpc/kvm/booke_emulate.c
@@ -62,7 +62,7 @@ int kvmppc_booke_emulate_op(struct kvm_run *run, struct kvm_vcpu *vcpu,
case OP_31_XOP_MFMSR:
rt = get_rt(inst);
- kvmppc_set_gpr(vcpu, rt, vcpu->arch.msr);
+ kvmppc_set_gpr(vcpu, rt, vcpu->arch.shared->msr);
kvmppc_set_exit_type(vcpu, EMULATED_MFMSR_EXITS);
break;
@@ -74,13 +74,13 @@ int kvmppc_booke_emulate_op(struct kvm_run *run, struct kvm_vcpu *vcpu,
case OP_31_XOP_WRTEE:
rs = get_rs(inst);
- vcpu->arch.msr = (vcpu->arch.msr & ~MSR_EE)
+ vcpu->arch.shared->msr = (vcpu->arch.shared->msr & ~MSR_EE)
| (kvmppc_get_gpr(vcpu, rs) & MSR_EE);
kvmppc_set_exit_type(vcpu, EMULATED_WRTEE_EXITS);
break;
case OP_31_XOP_WRTEEI:
- vcpu->arch.msr = (vcpu->arch.msr & ~MSR_EE)
+ vcpu->arch.shared->msr = (vcpu->arch.shared->msr & ~MSR_EE)
| (inst & MSR_EE);
kvmppc_set_exit_type(vcpu, EMULATED_WRTEE_EXITS);
break;
diff --git a/arch/powerpc/kvm/booke_interrupts.S b/arch/powerpc/kvm/booke_interrupts.S
index 380a78c..0498469 100644
--- a/arch/powerpc/kvm/booke_interrupts.S
+++ b/arch/powerpc/kvm/booke_interrupts.S
@@ -415,7 +415,8 @@ lightweight_exit:
lwz r8, VCPU_GPR(r8)(r4)
lwz r3, VCPU_PC(r4)
mtsrr0 r3
- lwz r3, VCPU_MSR(r4)
+ lwz r3, VCPU_SHARED(r4)
+ lwz r3, VCPU_SHARED_MSR(r3)
oris r3, r3, KVMPPC_MSR_MASK@h
ori r3, r3, KVMPPC_MSR_MASK@l
mtsrr1 r3
diff --git a/arch/powerpc/kvm/e500_tlb.c b/arch/powerpc/kvm/e500_tlb.c
index f11ca0f..66845a5 100644
--- a/arch/powerpc/kvm/e500_tlb.c
+++ b/arch/powerpc/kvm/e500_tlb.c
@@ -317,10 +317,10 @@ static inline void kvmppc_e500_shadow_map(struct kvmppc_vcpu_e500 *vcpu_e500,
| MAS1_TID(get_tlb_tid(gtlbe)) | MAS1_TS | MAS1_VALID;
stlbe->mas2 = (gvaddr & MAS2_EPN)
| e500_shadow_mas2_attrib(gtlbe->mas2,
- vcpu_e500->vcpu.arch.msr & MSR_PR);
+ vcpu_e500->vcpu.arch.shared->msr & MSR_PR);
stlbe->mas3 = (hpaddr & MAS3_RPN)
| e500_shadow_mas3_attrib(gtlbe->mas3,
- vcpu_e500->vcpu.arch.msr & MSR_PR);
+ vcpu_e500->vcpu.arch.shared->msr & MSR_PR);
stlbe->mas7 = (hpaddr >> 32) & MAS7_RPN;
trace_kvm_stlb_write(index_of(tlbsel, esel), stlbe->mas1, stlbe->mas2,
@@ -579,28 +579,28 @@ int kvmppc_e500_emul_tlbwe(struct kvm_vcpu *vcpu)
int kvmppc_mmu_itlb_index(struct kvm_vcpu *vcpu, gva_t eaddr)
{
- unsigned int as = !!(vcpu->arch.msr & MSR_IS);
+ unsigned int as = !!(vcpu->arch.shared->msr & MSR_IS);
return kvmppc_e500_tlb_search(vcpu, eaddr, get_cur_pid(vcpu), as);
}
int kvmppc_mmu_dtlb_index(struct kvm_vcpu *vcpu, gva_t eaddr)
{
- unsigned int as = !!(vcpu->arch.msr & MSR_DS);
+ unsigned int as = !!(vcpu->arch.shared->msr & MSR_DS);
return kvmppc_e500_tlb_search(vcpu, eaddr, get_cur_pid(vcpu), as);
}
void kvmppc_mmu_itlb_miss(struct kvm_vcpu *vcpu)
{
- unsigned int as = !!(vcpu->arch.msr & MSR_IS);
+ unsigned int as = !!(vcpu->arch.shared->msr & MSR_IS);
kvmppc_e500_deliver_tlb_miss(vcpu, vcpu->arch.pc, as);
}
void kvmppc_mmu_dtlb_miss(struct kvm_vcpu *vcpu)
{
- unsigned int as = !!(vcpu->arch.msr & MSR_DS);
+ unsigned int as = !!(vcpu->arch.shared->msr & MSR_DS);
kvmppc_e500_deliver_tlb_miss(vcpu, vcpu->arch.fault_dear, as);
}
diff --git a/arch/powerpc/kvm/e500_tlb.h b/arch/powerpc/kvm/e500_tlb.h
index d28e301..458946b 100644
--- a/arch/powerpc/kvm/e500_tlb.h
+++ b/arch/powerpc/kvm/e500_tlb.h
@@ -171,7 +171,7 @@ static inline int tlbe_is_host_safe(const struct kvm_vcpu *vcpu,
/* Does it match current guest AS? */
/* XXX what about IS != DS? */
- if (get_tlb_ts(tlbe) != !!(vcpu->arch.msr & MSR_IS))
+ if (get_tlb_ts(tlbe) != !!(vcpu->arch.shared->msr & MSR_IS))
return 0;
gpa = get_tlb_raddr(tlbe);
diff --git a/arch/powerpc/kvm/powerpc.c b/arch/powerpc/kvm/powerpc.c
index 72a4ad8..22f6fa2 100644
--- a/arch/powerpc/kvm/powerpc.c
+++ b/arch/powerpc/kvm/powerpc.c
@@ -38,7 +38,8 @@
int kvm_arch_vcpu_runnable(struct kvm_vcpu *v)
{
- return !(v->arch.msr & MSR_WE) || !!(v->arch.pending_exceptions);
+ return !(v->arch.shared->msr & MSR_WE) ||
+ !!(v->arch.pending_exceptions);
}
--
1.6.0.2
^ permalink raw reply related [flat|nested] 227+ messages in thread[parent not found: <1277508314-915-3-git-send-email-agraf-l3A5Bk7waGM@public.gmane.org>]
* Re: [PATCH 02/26] KVM: PPC: Convert MSR to shared page
2010-06-25 23:24 ` Alexander Graf
(?)
@ 2010-06-27 8:16 ` Avi Kivity
-1 siblings, 0 replies; 227+ messages in thread
From: Avi Kivity @ 2010-06-27 8:16 UTC (permalink / raw)
To: Alexander Graf; +Cc: kvm-ppc-u79uwXL29TY76Z2rM5mHXA, KVM list, linuxppc-dev
On 06/26/2010 02:24 AM, Alexander Graf wrote:
> One of the most obvious registers to share with the guest directly is the
> MSR. The MSR contains the "interrupts enabled" flag which the guest has to
> toggle in critical sections.
>
> So in order to bring the overhead of interrupt en- and disabling down, let's
> put msr into the shared page. Keep in mind that even though you can fully read
> its contents, writing to it doesn't always update all state. There are a few
> safe fields that don't require hypervisor interaction. See the guest
> implementation that follows later for reference.
>
You mean, see the documentation for reference.
It should be possible to write the guest code looking only at the
documentation.
--
error compiling committee.c: too many arguments to function
^ permalink raw reply [flat|nested] 227+ messages in thread
* Re: [PATCH 02/26] KVM: PPC: Convert MSR to shared page
@ 2010-06-27 8:16 ` Avi Kivity
0 siblings, 0 replies; 227+ messages in thread
From: Avi Kivity @ 2010-06-27 8:16 UTC (permalink / raw)
To: Alexander Graf; +Cc: kvm-ppc-u79uwXL29TY76Z2rM5mHXA, KVM list, linuxppc-dev
On 06/26/2010 02:24 AM, Alexander Graf wrote:
> One of the most obvious registers to share with the guest directly is the
> MSR. The MSR contains the "interrupts enabled" flag which the guest has to
> toggle in critical sections.
>
> So in order to bring the overhead of interrupt en- and disabling down, let's
> put msr into the shared page. Keep in mind that even though you can fully read
> its contents, writing to it doesn't always update all state. There are a few
> safe fields that don't require hypervisor interaction. See the guest
> implementation that follows later for reference.
>
You mean, see the documentation for reference.
It should be possible to write the guest code looking only at the
documentation.
--
error compiling committee.c: too many arguments to function
^ permalink raw reply [flat|nested] 227+ messages in thread
* Re: [PATCH 02/26] KVM: PPC: Convert MSR to shared page
@ 2010-06-27 8:16 ` Avi Kivity
0 siblings, 0 replies; 227+ messages in thread
From: Avi Kivity @ 2010-06-27 8:16 UTC (permalink / raw)
To: Alexander Graf; +Cc: linuxppc-dev, KVM list, kvm-ppc
On 06/26/2010 02:24 AM, Alexander Graf wrote:
> One of the most obvious registers to share with the guest directly is the
> MSR. The MSR contains the "interrupts enabled" flag which the guest has to
> toggle in critical sections.
>
> So in order to bring the overhead of interrupt en- and disabling down, let's
> put msr into the shared page. Keep in mind that even though you can fully read
> its contents, writing to it doesn't always update all state. There are a few
> safe fields that don't require hypervisor interaction. See the guest
> implementation that follows later for reference.
>
You mean, see the documentation for reference.
It should be possible to write the guest code looking only at the
documentation.
--
error compiling committee.c: too many arguments to function
^ permalink raw reply [flat|nested] 227+ messages in thread
[parent not found: <4C2708EB.9020500-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>]
* Re: [PATCH 02/26] KVM: PPC: Convert MSR to shared page
2010-06-27 8:16 ` Avi Kivity
(?)
@ 2010-06-27 9:38 ` Alexander Graf
-1 siblings, 0 replies; 227+ messages in thread
From: Alexander Graf @ 2010-06-27 9:38 UTC (permalink / raw)
To: Avi Kivity
Cc: kvm-ppc-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, KVM list,
linuxppc-dev
Am 27.06.2010 um 10:16 schrieb Avi Kivity <avi@redhat.com>:
> On 06/26/2010 02:24 AM, Alexander Graf wrote:
>> One of the most obvious registers to share with the guest directly
>> is the
>> MSR. The MSR contains the "interrupts enabled" flag which the guest
>> has to
>> toggle in critical sections.
>>
>> So in order to bring the overhead of interrupt en- and disabling
>> down, let's
>> put msr into the shared page. Keep in mind that even though you can
>> fully read
>> its contents, writing to it doesn't always update all state. There
>> are a few
>> safe fields that don't require hypervisor interaction. See the guest
>> implementation that follows later for reference.
>>
>
>
> You mean, see the documentation for reference.
>
> It should be possible to write the guest code looking only at the
> documentation.
*shrug* since we're writing open source I don't mind telling people to
read code for a reference implemenration. If well written, that's more
comprehensible than documentation anyways :).
But either way, you can take a look at both - documentation and code,
yes.
What I really meant here is that the list of registers we patch should
be taken from the patch code. I didn't want to write out all of them
in the description.
Alex
^ permalink raw reply [flat|nested] 227+ messages in thread
* Re: [PATCH 02/26] KVM: PPC: Convert MSR to shared page
@ 2010-06-27 9:38 ` Alexander Graf
0 siblings, 0 replies; 227+ messages in thread
From: Alexander Graf @ 2010-06-27 9:38 UTC (permalink / raw)
To: Avi Kivity
Cc: kvm-ppc-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, KVM list,
linuxppc-dev
Am 27.06.2010 um 10:16 schrieb Avi Kivity <avi-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>:
> On 06/26/2010 02:24 AM, Alexander Graf wrote:
>> One of the most obvious registers to share with the guest directly
>> is the
>> MSR. The MSR contains the "interrupts enabled" flag which the guest
>> has to
>> toggle in critical sections.
>>
>> So in order to bring the overhead of interrupt en- and disabling
>> down, let's
>> put msr into the shared page. Keep in mind that even though you can
>> fully read
>> its contents, writing to it doesn't always update all state. There
>> are a few
>> safe fields that don't require hypervisor interaction. See the guest
>> implementation that follows later for reference.
>>
>
>
> You mean, see the documentation for reference.
>
> It should be possible to write the guest code looking only at the
> documentation.
*shrug* since we're writing open source I don't mind telling people to
read code for a reference implemenration. If well written, that's more
comprehensible than documentation anyways :).
But either way, you can take a look at both - documentation and code,
yes.
What I really meant here is that the list of registers we patch should
be taken from the patch code. I didn't want to write out all of them
in the description.
Alex
^ permalink raw reply [flat|nested] 227+ messages in thread
* Re: [PATCH 02/26] KVM: PPC: Convert MSR to shared page
@ 2010-06-27 9:38 ` Alexander Graf
0 siblings, 0 replies; 227+ messages in thread
From: Alexander Graf @ 2010-06-27 9:38 UTC (permalink / raw)
To: Avi Kivity; +Cc: linuxppc-dev, KVM list, kvm-ppc@vger.kernel.org
Am 27.06.2010 um 10:16 schrieb Avi Kivity <avi@redhat.com>:
> On 06/26/2010 02:24 AM, Alexander Graf wrote:
>> One of the most obvious registers to share with the guest directly
>> is the
>> MSR. The MSR contains the "interrupts enabled" flag which the guest
>> has to
>> toggle in critical sections.
>>
>> So in order to bring the overhead of interrupt en- and disabling
>> down, let's
>> put msr into the shared page. Keep in mind that even though you can
>> fully read
>> its contents, writing to it doesn't always update all state. There
>> are a few
>> safe fields that don't require hypervisor interaction. See the guest
>> implementation that follows later for reference.
>>
>
>
> You mean, see the documentation for reference.
>
> It should be possible to write the guest code looking only at the
> documentation.
*shrug* since we're writing open source I don't mind telling people to
read code for a reference implemenration. If well written, that's more
comprehensible than documentation anyways :).
But either way, you can take a look at both - documentation and code,
yes.
What I really meant here is that the list of registers we patch should
be taken from the patch code. I didn't want to write out all of them
in the description.
Alex
^ permalink raw reply [flat|nested] 227+ messages in thread
[parent not found: <651805F1-54AB-466F-8D23-D053D8082177-l3A5Bk7waGM@public.gmane.org>]
* Re: [PATCH 02/26] KVM: PPC: Convert MSR to shared page
2010-06-27 9:38 ` Alexander Graf
(?)
@ 2010-06-27 9:50 ` Avi Kivity
-1 siblings, 0 replies; 227+ messages in thread
From: Avi Kivity @ 2010-06-27 9:50 UTC (permalink / raw)
To: Alexander Graf
Cc: kvm-ppc-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, KVM list,
linuxppc-dev
On 06/27/2010 12:38 PM, Alexander Graf wrote:
>
> Am 27.06.2010 um 10:16 schrieb Avi Kivity <avi@redhat.com>:
>
>> On 06/26/2010 02:24 AM, Alexander Graf wrote:
>>> One of the most obvious registers to share with the guest directly
>>> is the
>>> MSR. The MSR contains the "interrupts enabled" flag which the guest
>>> has to
>>> toggle in critical sections.
>>>
>>> So in order to bring the overhead of interrupt en- and disabling
>>> down, let's
>>> put msr into the shared page. Keep in mind that even though you can
>>> fully read
>>> its contents, writing to it doesn't always update all state. There
>>> are a few
>>> safe fields that don't require hypervisor interaction. See the guest
>>> implementation that follows later for reference.
>>>
>>
>>
>> You mean, see the documentation for reference.
>>
>> It should be possible to write the guest code looking only at the
>> documentation.
>
> *shrug* since we're writing open source I don't mind telling people to
> read code for a reference implemenration.
It's impossible to infer from the source what's a guaranteed part of the
interface and what is just an implementation artifact. So people rely
on implementation artifacts (or even bugs) and that reduces our ability
to change things.
> If well written, that's more comprehensible than documentation anyways
> :).
If the documentation is poorly written, yes.
--
error compiling committee.c: too many arguments to function
^ permalink raw reply [flat|nested] 227+ messages in thread
* Re: [PATCH 02/26] KVM: PPC: Convert MSR to shared page
@ 2010-06-27 9:50 ` Avi Kivity
0 siblings, 0 replies; 227+ messages in thread
From: Avi Kivity @ 2010-06-27 9:50 UTC (permalink / raw)
To: Alexander Graf
Cc: kvm-ppc-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, KVM list,
linuxppc-dev
On 06/27/2010 12:38 PM, Alexander Graf wrote:
>
> Am 27.06.2010 um 10:16 schrieb Avi Kivity <avi-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>:
>
>> On 06/26/2010 02:24 AM, Alexander Graf wrote:
>>> One of the most obvious registers to share with the guest directly
>>> is the
>>> MSR. The MSR contains the "interrupts enabled" flag which the guest
>>> has to
>>> toggle in critical sections.
>>>
>>> So in order to bring the overhead of interrupt en- and disabling
>>> down, let's
>>> put msr into the shared page. Keep in mind that even though you can
>>> fully read
>>> its contents, writing to it doesn't always update all state. There
>>> are a few
>>> safe fields that don't require hypervisor interaction. See the guest
>>> implementation that follows later for reference.
>>>
>>
>>
>> You mean, see the documentation for reference.
>>
>> It should be possible to write the guest code looking only at the
>> documentation.
>
> *shrug* since we're writing open source I don't mind telling people to
> read code for a reference implemenration.
It's impossible to infer from the source what's a guaranteed part of the
interface and what is just an implementation artifact. So people rely
on implementation artifacts (or even bugs) and that reduces our ability
to change things.
> If well written, that's more comprehensible than documentation anyways
> :).
If the documentation is poorly written, yes.
--
error compiling committee.c: too many arguments to function
^ permalink raw reply [flat|nested] 227+ messages in thread
* Re: [PATCH 02/26] KVM: PPC: Convert MSR to shared page
@ 2010-06-27 9:50 ` Avi Kivity
0 siblings, 0 replies; 227+ messages in thread
From: Avi Kivity @ 2010-06-27 9:50 UTC (permalink / raw)
To: Alexander Graf; +Cc: linuxppc-dev, KVM list, kvm-ppc@vger.kernel.org
On 06/27/2010 12:38 PM, Alexander Graf wrote:
>
> Am 27.06.2010 um 10:16 schrieb Avi Kivity <avi@redhat.com>:
>
>> On 06/26/2010 02:24 AM, Alexander Graf wrote:
>>> One of the most obvious registers to share with the guest directly
>>> is the
>>> MSR. The MSR contains the "interrupts enabled" flag which the guest
>>> has to
>>> toggle in critical sections.
>>>
>>> So in order to bring the overhead of interrupt en- and disabling
>>> down, let's
>>> put msr into the shared page. Keep in mind that even though you can
>>> fully read
>>> its contents, writing to it doesn't always update all state. There
>>> are a few
>>> safe fields that don't require hypervisor interaction. See the guest
>>> implementation that follows later for reference.
>>>
>>
>>
>> You mean, see the documentation for reference.
>>
>> It should be possible to write the guest code looking only at the
>> documentation.
>
> *shrug* since we're writing open source I don't mind telling people to
> read code for a reference implemenration.
It's impossible to infer from the source what's a guaranteed part of the
interface and what is just an implementation artifact. So people rely
on implementation artifacts (or even bugs) and that reduces our ability
to change things.
> If well written, that's more comprehensible than documentation anyways
> :).
If the documentation is poorly written, yes.
--
error compiling committee.c: too many arguments to function
^ permalink raw reply [flat|nested] 227+ messages in thread
[parent not found: <4C271EE5.1060401-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>]
* Re: [PATCH 02/26] KVM: PPC: Convert MSR to shared page
2010-06-27 9:50 ` Avi Kivity
(?)
@ 2010-06-27 10:40 ` Alexander Graf
-1 siblings, 0 replies; 227+ messages in thread
From: Alexander Graf @ 2010-06-27 10:40 UTC (permalink / raw)
To: Avi Kivity
Cc: kvm-ppc-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, KVM list,
linuxppc-dev
Am 27.06.2010 um 11:50 schrieb Avi Kivity <avi@redhat.com>:
> On 06/27/2010 12:38 PM, Alexander Graf wrote:
>>
>> Am 27.06.2010 um 10:16 schrieb Avi Kivity <avi@redhat.com>:
>>
>>> On 06/26/2010 02:24 AM, Alexander Graf wrote:
>>>> One of the most obvious registers to share with the guest
>>>> directly is the
>>>> MSR. The MSR contains the "interrupts enabled" flag which the
>>>> guest has to
>>>> toggle in critical sections.
>>>>
>>>> So in order to bring the overhead of interrupt en- and disabling
>>>> down, let's
>>>> put msr into the shared page. Keep in mind that even though you
>>>> can fully read
>>>> its contents, writing to it doesn't always update all state.
>>>> There are a few
>>>> safe fields that don't require hypervisor interaction. See the
>>>> guest
>>>> implementation that follows later for reference.
>>>>
>>>
>>>
>>> You mean, see the documentation for reference.
>>>
>>> It should be possible to write the guest code looking only at the
>>> documentation.
>>
>> *shrug* since we're writing open source I don't mind telling people
>> to read code for a reference implemenration.
>
> It's impossible to infer from the source what's a guaranteed part of
> the interface and what is just an implementation artifact. So
> people rely on implementation artifacts (or even bugs) and that
> reduces our ability to change things.
>
>> If well written, that's more comprehensible than documentation
>> anyways :).
>
> If the documentation is poorly written, yes.
I think I start to agree. I guess i should just list all fields of the
MSR that are ok to modify inside the guest context.
Alex
^ permalink raw reply [flat|nested] 227+ messages in thread
* Re: [PATCH 02/26] KVM: PPC: Convert MSR to shared page
@ 2010-06-27 10:40 ` Alexander Graf
0 siblings, 0 replies; 227+ messages in thread
From: Alexander Graf @ 2010-06-27 10:40 UTC (permalink / raw)
To: Avi Kivity
Cc: kvm-ppc-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, KVM list,
linuxppc-dev
Am 27.06.2010 um 11:50 schrieb Avi Kivity <avi-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>:
> On 06/27/2010 12:38 PM, Alexander Graf wrote:
>>
>> Am 27.06.2010 um 10:16 schrieb Avi Kivity <avi-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>:
>>
>>> On 06/26/2010 02:24 AM, Alexander Graf wrote:
>>>> One of the most obvious registers to share with the guest
>>>> directly is the
>>>> MSR. The MSR contains the "interrupts enabled" flag which the
>>>> guest has to
>>>> toggle in critical sections.
>>>>
>>>> So in order to bring the overhead of interrupt en- and disabling
>>>> down, let's
>>>> put msr into the shared page. Keep in mind that even though you
>>>> can fully read
>>>> its contents, writing to it doesn't always update all state.
>>>> There are a few
>>>> safe fields that don't require hypervisor interaction. See the
>>>> guest
>>>> implementation that follows later for reference.
>>>>
>>>
>>>
>>> You mean, see the documentation for reference.
>>>
>>> It should be possible to write the guest code looking only at the
>>> documentation.
>>
>> *shrug* since we're writing open source I don't mind telling people
>> to read code for a reference implemenration.
>
> It's impossible to infer from the source what's a guaranteed part of
> the interface and what is just an implementation artifact. So
> people rely on implementation artifacts (or even bugs) and that
> reduces our ability to change things.
>
>> If well written, that's more comprehensible than documentation
>> anyways :).
>
> If the documentation is poorly written, yes.
I think I start to agree. I guess i should just list all fields of the
MSR that are ok to modify inside the guest context.
Alex
^ permalink raw reply [flat|nested] 227+ messages in thread
* Re: [PATCH 02/26] KVM: PPC: Convert MSR to shared page
@ 2010-06-27 10:40 ` Alexander Graf
0 siblings, 0 replies; 227+ messages in thread
From: Alexander Graf @ 2010-06-27 10:40 UTC (permalink / raw)
To: Avi Kivity; +Cc: linuxppc-dev, KVM list, kvm-ppc@vger.kernel.org
Am 27.06.2010 um 11:50 schrieb Avi Kivity <avi@redhat.com>:
> On 06/27/2010 12:38 PM, Alexander Graf wrote:
>>
>> Am 27.06.2010 um 10:16 schrieb Avi Kivity <avi@redhat.com>:
>>
>>> On 06/26/2010 02:24 AM, Alexander Graf wrote:
>>>> One of the most obvious registers to share with the guest
>>>> directly is the
>>>> MSR. The MSR contains the "interrupts enabled" flag which the
>>>> guest has to
>>>> toggle in critical sections.
>>>>
>>>> So in order to bring the overhead of interrupt en- and disabling
>>>> down, let's
>>>> put msr into the shared page. Keep in mind that even though you
>>>> can fully read
>>>> its contents, writing to it doesn't always update all state.
>>>> There are a few
>>>> safe fields that don't require hypervisor interaction. See the
>>>> guest
>>>> implementation that follows later for reference.
>>>>
>>>
>>>
>>> You mean, see the documentation for reference.
>>>
>>> It should be possible to write the guest code looking only at the
>>> documentation.
>>
>> *shrug* since we're writing open source I don't mind telling people
>> to read code for a reference implemenration.
>
> It's impossible to infer from the source what's a guaranteed part of
> the interface and what is just an implementation artifact. So
> people rely on implementation artifacts (or even bugs) and that
> reduces our ability to change things.
>
>> If well written, that's more comprehensible than documentation
>> anyways :).
>
> If the documentation is poorly written, yes.
I think I start to agree. I guess i should just list all fields of the
MSR that are ok to modify inside the guest context.
Alex
^ permalink raw reply [flat|nested] 227+ messages in thread
* [PATCH 04/26] KVM: PPC: Convert DAR to shared page.
2010-06-25 23:24 ` Alexander Graf
(?)
@ 2010-06-25 23:24 ` Alexander Graf
-1 siblings, 0 replies; 227+ messages in thread
From: Alexander Graf @ 2010-06-25 23:24 UTC (permalink / raw)
To: kvm-ppc-u79uwXL29TY76Z2rM5mHXA; +Cc: KVM list, linuxppc-dev
The DAR register contains the address a data page fault occured at. This
register behaves pretty much like a simple data storage register that gets
written to on data faults. There is no hypervisor interaction required on
read or write.
This patch converts all users of the current field to the shared page.
Signed-off-by: Alexander Graf <agraf@suse.de>
---
arch/powerpc/include/asm/kvm_host.h | 1 -
arch/powerpc/include/asm/kvm_para.h | 1 +
arch/powerpc/kvm/book3s.c | 14 +++++++-------
arch/powerpc/kvm/book3s_emulate.c | 6 +++---
arch/powerpc/kvm/book3s_paired_singles.c | 2 +-
arch/powerpc/kvm/booke.c | 2 +-
arch/powerpc/kvm/booke_emulate.c | 4 ++--
7 files changed, 15 insertions(+), 15 deletions(-)
diff --git a/arch/powerpc/include/asm/kvm_host.h b/arch/powerpc/include/asm/kvm_host.h
index 249c242..108dabc 100644
--- a/arch/powerpc/include/asm/kvm_host.h
+++ b/arch/powerpc/include/asm/kvm_host.h
@@ -230,7 +230,6 @@ struct kvm_vcpu_arch {
ulong csrr1;
ulong dsrr0;
ulong dsrr1;
- ulong dear;
ulong esr;
u32 dec;
u32 decar;
diff --git a/arch/powerpc/include/asm/kvm_para.h b/arch/powerpc/include/asm/kvm_para.h
index 9f7565b..ec72a1c 100644
--- a/arch/powerpc/include/asm/kvm_para.h
+++ b/arch/powerpc/include/asm/kvm_para.h
@@ -23,6 +23,7 @@
#include <linux/types.h>
struct kvm_vcpu_arch_shared {
+ __u64 dar;
__u64 msr;
__u32 dsisr;
};
diff --git a/arch/powerpc/kvm/book3s.c b/arch/powerpc/kvm/book3s.c
index 57fd73e..245bd2d 100644
--- a/arch/powerpc/kvm/book3s.c
+++ b/arch/powerpc/kvm/book3s.c
@@ -594,14 +594,14 @@ int kvmppc_handle_pagefault(struct kvm_run *run, struct kvm_vcpu *vcpu,
if (page_found = -ENOENT) {
/* Page not found in guest PTE entries */
- vcpu->arch.dear = kvmppc_get_fault_dar(vcpu);
+ vcpu->arch.shared->dar = kvmppc_get_fault_dar(vcpu);
vcpu->arch.shared->dsisr = to_svcpu(vcpu)->fault_dsisr;
vcpu->arch.shared->msr | (to_svcpu(vcpu)->shadow_srr1 & 0x00000000f8000000ULL);
kvmppc_book3s_queue_irqprio(vcpu, vec);
} else if (page_found = -EPERM) {
/* Storage protection */
- vcpu->arch.dear = kvmppc_get_fault_dar(vcpu);
+ vcpu->arch.shared->dar = kvmppc_get_fault_dar(vcpu);
vcpu->arch.shared->dsisr to_svcpu(vcpu)->fault_dsisr & ~DSISR_NOHPTE;
vcpu->arch.shared->dsisr |= DSISR_PROTFAULT;
@@ -610,7 +610,7 @@ int kvmppc_handle_pagefault(struct kvm_run *run, struct kvm_vcpu *vcpu,
kvmppc_book3s_queue_irqprio(vcpu, vec);
} else if (page_found = -EINVAL) {
/* Page not found in guest SLB */
- vcpu->arch.dear = kvmppc_get_fault_dar(vcpu);
+ vcpu->arch.shared->dar = kvmppc_get_fault_dar(vcpu);
kvmppc_book3s_queue_irqprio(vcpu, vec + 0x80);
} else if (!is_mmio &&
kvmppc_visible_gfn(vcpu, pte.raddr >> PAGE_SHIFT)) {
@@ -867,17 +867,17 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
if (to_svcpu(vcpu)->fault_dsisr & DSISR_NOHPTE) {
r = kvmppc_handle_pagefault(run, vcpu, dar, exit_nr);
} else {
- vcpu->arch.dear = dar;
+ vcpu->arch.shared->dar = dar;
vcpu->arch.shared->dsisr = to_svcpu(vcpu)->fault_dsisr;
kvmppc_book3s_queue_irqprio(vcpu, exit_nr);
- kvmppc_mmu_pte_flush(vcpu, vcpu->arch.dear, ~0xFFFUL);
+ kvmppc_mmu_pte_flush(vcpu, dar, ~0xFFFUL);
r = RESUME_GUEST;
}
break;
}
case BOOK3S_INTERRUPT_DATA_SEGMENT:
if (kvmppc_mmu_map_segment(vcpu, kvmppc_get_fault_dar(vcpu)) < 0) {
- vcpu->arch.dear = kvmppc_get_fault_dar(vcpu);
+ vcpu->arch.shared->dar = kvmppc_get_fault_dar(vcpu);
kvmppc_book3s_queue_irqprio(vcpu,
BOOK3S_INTERRUPT_DATA_SEGMENT);
}
@@ -997,7 +997,7 @@ program_interrupt:
if (kvmppc_read_inst(vcpu) = EMULATE_DONE) {
vcpu->arch.shared->dsisr = kvmppc_alignment_dsisr(vcpu,
kvmppc_get_last_inst(vcpu));
- vcpu->arch.dear = kvmppc_alignment_dar(vcpu,
+ vcpu->arch.shared->dar = kvmppc_alignment_dar(vcpu,
kvmppc_get_last_inst(vcpu));
kvmppc_book3s_queue_irqprio(vcpu, exit_nr);
}
diff --git a/arch/powerpc/kvm/book3s_emulate.c b/arch/powerpc/kvm/book3s_emulate.c
index 9982ff1..c147864 100644
--- a/arch/powerpc/kvm/book3s_emulate.c
+++ b/arch/powerpc/kvm/book3s_emulate.c
@@ -212,7 +212,7 @@ int kvmppc_core_emulate_op(struct kvm_run *run, struct kvm_vcpu *vcpu,
r = kvmppc_st(vcpu, &addr, 32, zeros, true);
if ((r = -ENOENT) || (r = -EPERM)) {
*advance = 0;
- vcpu->arch.dear = vaddr;
+ vcpu->arch.shared->dar = vaddr;
to_svcpu(vcpu)->fault_dar = vaddr;
dsisr = DSISR_ISSTORE;
@@ -330,7 +330,7 @@ int kvmppc_core_emulate_mtspr(struct kvm_vcpu *vcpu, int sprn, int rs)
vcpu->arch.shared->dsisr = spr_val;
break;
case SPRN_DAR:
- vcpu->arch.dear = spr_val;
+ vcpu->arch.shared->dar = spr_val;
break;
case SPRN_HIOR:
to_book3s(vcpu)->hior = spr_val;
@@ -443,7 +443,7 @@ int kvmppc_core_emulate_mfspr(struct kvm_vcpu *vcpu, int sprn, int rt)
kvmppc_set_gpr(vcpu, rt, vcpu->arch.shared->dsisr);
break;
case SPRN_DAR:
- kvmppc_set_gpr(vcpu, rt, vcpu->arch.dear);
+ kvmppc_set_gpr(vcpu, rt, vcpu->arch.shared->dar);
break;
case SPRN_HIOR:
kvmppc_set_gpr(vcpu, rt, to_book3s(vcpu)->hior);
diff --git a/arch/powerpc/kvm/book3s_paired_singles.c b/arch/powerpc/kvm/book3s_paired_singles.c
index 749dfbd..807576f 100644
--- a/arch/powerpc/kvm/book3s_paired_singles.c
+++ b/arch/powerpc/kvm/book3s_paired_singles.c
@@ -169,7 +169,7 @@ static void kvmppc_inject_pf(struct kvm_vcpu *vcpu, ulong eaddr, bool is_store)
shared->msr = kvmppc_set_field(shared->msr, 33, 36, 0);
shared->msr = kvmppc_set_field(shared->msr, 42, 47, 0);
- vcpu->arch.dear = eaddr;
+ shared->dar = eaddr;
/* Page Fault */
dsisr = kvmppc_set_field(0, 33, 33, 1);
if (is_store)
diff --git a/arch/powerpc/kvm/booke.c b/arch/powerpc/kvm/booke.c
index ddb4cac..5844bcf 100644
--- a/arch/powerpc/kvm/booke.c
+++ b/arch/powerpc/kvm/booke.c
@@ -195,7 +195,7 @@ static int kvmppc_booke_irqprio_deliver(struct kvm_vcpu *vcpu,
if (update_esr = true)
vcpu->arch.esr = vcpu->arch.queued_esr;
if (update_dear = true)
- vcpu->arch.dear = vcpu->arch.queued_dear;
+ vcpu->arch.shared->dar = vcpu->arch.queued_dear;
kvmppc_set_msr(vcpu, vcpu->arch.shared->msr & msr_mask);
clear_bit(priority, &vcpu->arch.pending_exceptions);
diff --git a/arch/powerpc/kvm/booke_emulate.c b/arch/powerpc/kvm/booke_emulate.c
index b115203..51ef453 100644
--- a/arch/powerpc/kvm/booke_emulate.c
+++ b/arch/powerpc/kvm/booke_emulate.c
@@ -105,7 +105,7 @@ int kvmppc_booke_emulate_mtspr(struct kvm_vcpu *vcpu, int sprn, int rs)
switch (sprn) {
case SPRN_DEAR:
- vcpu->arch.dear = spr_val; break;
+ vcpu->arch.shared->dar = spr_val; break;
case SPRN_ESR:
vcpu->arch.esr = spr_val; break;
case SPRN_DBCR0:
@@ -200,7 +200,7 @@ int kvmppc_booke_emulate_mfspr(struct kvm_vcpu *vcpu, int sprn, int rt)
case SPRN_IVPR:
kvmppc_set_gpr(vcpu, rt, vcpu->arch.ivpr); break;
case SPRN_DEAR:
- kvmppc_set_gpr(vcpu, rt, vcpu->arch.dear); break;
+ kvmppc_set_gpr(vcpu, rt, vcpu->arch.shared->dar); break;
case SPRN_ESR:
kvmppc_set_gpr(vcpu, rt, vcpu->arch.esr); break;
case SPRN_DBCR0:
--
1.6.0.2
^ permalink raw reply related [flat|nested] 227+ messages in thread* [PATCH 04/26] KVM: PPC: Convert DAR to shared page.
@ 2010-06-25 23:24 ` Alexander Graf
0 siblings, 0 replies; 227+ messages in thread
From: Alexander Graf @ 2010-06-25 23:24 UTC (permalink / raw)
To: kvm-ppc-u79uwXL29TY76Z2rM5mHXA; +Cc: KVM list, linuxppc-dev
The DAR register contains the address a data page fault occured at. This
register behaves pretty much like a simple data storage register that gets
written to on data faults. There is no hypervisor interaction required on
read or write.
This patch converts all users of the current field to the shared page.
Signed-off-by: Alexander Graf <agraf-l3A5Bk7waGM@public.gmane.org>
---
arch/powerpc/include/asm/kvm_host.h | 1 -
arch/powerpc/include/asm/kvm_para.h | 1 +
arch/powerpc/kvm/book3s.c | 14 +++++++-------
arch/powerpc/kvm/book3s_emulate.c | 6 +++---
arch/powerpc/kvm/book3s_paired_singles.c | 2 +-
arch/powerpc/kvm/booke.c | 2 +-
arch/powerpc/kvm/booke_emulate.c | 4 ++--
7 files changed, 15 insertions(+), 15 deletions(-)
diff --git a/arch/powerpc/include/asm/kvm_host.h b/arch/powerpc/include/asm/kvm_host.h
index 249c242..108dabc 100644
--- a/arch/powerpc/include/asm/kvm_host.h
+++ b/arch/powerpc/include/asm/kvm_host.h
@@ -230,7 +230,6 @@ struct kvm_vcpu_arch {
ulong csrr1;
ulong dsrr0;
ulong dsrr1;
- ulong dear;
ulong esr;
u32 dec;
u32 decar;
diff --git a/arch/powerpc/include/asm/kvm_para.h b/arch/powerpc/include/asm/kvm_para.h
index 9f7565b..ec72a1c 100644
--- a/arch/powerpc/include/asm/kvm_para.h
+++ b/arch/powerpc/include/asm/kvm_para.h
@@ -23,6 +23,7 @@
#include <linux/types.h>
struct kvm_vcpu_arch_shared {
+ __u64 dar;
__u64 msr;
__u32 dsisr;
};
diff --git a/arch/powerpc/kvm/book3s.c b/arch/powerpc/kvm/book3s.c
index 57fd73e..245bd2d 100644
--- a/arch/powerpc/kvm/book3s.c
+++ b/arch/powerpc/kvm/book3s.c
@@ -594,14 +594,14 @@ int kvmppc_handle_pagefault(struct kvm_run *run, struct kvm_vcpu *vcpu,
if (page_found == -ENOENT) {
/* Page not found in guest PTE entries */
- vcpu->arch.dear = kvmppc_get_fault_dar(vcpu);
+ vcpu->arch.shared->dar = kvmppc_get_fault_dar(vcpu);
vcpu->arch.shared->dsisr = to_svcpu(vcpu)->fault_dsisr;
vcpu->arch.shared->msr |=
(to_svcpu(vcpu)->shadow_srr1 & 0x00000000f8000000ULL);
kvmppc_book3s_queue_irqprio(vcpu, vec);
} else if (page_found == -EPERM) {
/* Storage protection */
- vcpu->arch.dear = kvmppc_get_fault_dar(vcpu);
+ vcpu->arch.shared->dar = kvmppc_get_fault_dar(vcpu);
vcpu->arch.shared->dsisr =
to_svcpu(vcpu)->fault_dsisr & ~DSISR_NOHPTE;
vcpu->arch.shared->dsisr |= DSISR_PROTFAULT;
@@ -610,7 +610,7 @@ int kvmppc_handle_pagefault(struct kvm_run *run, struct kvm_vcpu *vcpu,
kvmppc_book3s_queue_irqprio(vcpu, vec);
} else if (page_found == -EINVAL) {
/* Page not found in guest SLB */
- vcpu->arch.dear = kvmppc_get_fault_dar(vcpu);
+ vcpu->arch.shared->dar = kvmppc_get_fault_dar(vcpu);
kvmppc_book3s_queue_irqprio(vcpu, vec + 0x80);
} else if (!is_mmio &&
kvmppc_visible_gfn(vcpu, pte.raddr >> PAGE_SHIFT)) {
@@ -867,17 +867,17 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
if (to_svcpu(vcpu)->fault_dsisr & DSISR_NOHPTE) {
r = kvmppc_handle_pagefault(run, vcpu, dar, exit_nr);
} else {
- vcpu->arch.dear = dar;
+ vcpu->arch.shared->dar = dar;
vcpu->arch.shared->dsisr = to_svcpu(vcpu)->fault_dsisr;
kvmppc_book3s_queue_irqprio(vcpu, exit_nr);
- kvmppc_mmu_pte_flush(vcpu, vcpu->arch.dear, ~0xFFFUL);
+ kvmppc_mmu_pte_flush(vcpu, dar, ~0xFFFUL);
r = RESUME_GUEST;
}
break;
}
case BOOK3S_INTERRUPT_DATA_SEGMENT:
if (kvmppc_mmu_map_segment(vcpu, kvmppc_get_fault_dar(vcpu)) < 0) {
- vcpu->arch.dear = kvmppc_get_fault_dar(vcpu);
+ vcpu->arch.shared->dar = kvmppc_get_fault_dar(vcpu);
kvmppc_book3s_queue_irqprio(vcpu,
BOOK3S_INTERRUPT_DATA_SEGMENT);
}
@@ -997,7 +997,7 @@ program_interrupt:
if (kvmppc_read_inst(vcpu) == EMULATE_DONE) {
vcpu->arch.shared->dsisr = kvmppc_alignment_dsisr(vcpu,
kvmppc_get_last_inst(vcpu));
- vcpu->arch.dear = kvmppc_alignment_dar(vcpu,
+ vcpu->arch.shared->dar = kvmppc_alignment_dar(vcpu,
kvmppc_get_last_inst(vcpu));
kvmppc_book3s_queue_irqprio(vcpu, exit_nr);
}
diff --git a/arch/powerpc/kvm/book3s_emulate.c b/arch/powerpc/kvm/book3s_emulate.c
index 9982ff1..c147864 100644
--- a/arch/powerpc/kvm/book3s_emulate.c
+++ b/arch/powerpc/kvm/book3s_emulate.c
@@ -212,7 +212,7 @@ int kvmppc_core_emulate_op(struct kvm_run *run, struct kvm_vcpu *vcpu,
r = kvmppc_st(vcpu, &addr, 32, zeros, true);
if ((r == -ENOENT) || (r == -EPERM)) {
*advance = 0;
- vcpu->arch.dear = vaddr;
+ vcpu->arch.shared->dar = vaddr;
to_svcpu(vcpu)->fault_dar = vaddr;
dsisr = DSISR_ISSTORE;
@@ -330,7 +330,7 @@ int kvmppc_core_emulate_mtspr(struct kvm_vcpu *vcpu, int sprn, int rs)
vcpu->arch.shared->dsisr = spr_val;
break;
case SPRN_DAR:
- vcpu->arch.dear = spr_val;
+ vcpu->arch.shared->dar = spr_val;
break;
case SPRN_HIOR:
to_book3s(vcpu)->hior = spr_val;
@@ -443,7 +443,7 @@ int kvmppc_core_emulate_mfspr(struct kvm_vcpu *vcpu, int sprn, int rt)
kvmppc_set_gpr(vcpu, rt, vcpu->arch.shared->dsisr);
break;
case SPRN_DAR:
- kvmppc_set_gpr(vcpu, rt, vcpu->arch.dear);
+ kvmppc_set_gpr(vcpu, rt, vcpu->arch.shared->dar);
break;
case SPRN_HIOR:
kvmppc_set_gpr(vcpu, rt, to_book3s(vcpu)->hior);
diff --git a/arch/powerpc/kvm/book3s_paired_singles.c b/arch/powerpc/kvm/book3s_paired_singles.c
index 749dfbd..807576f 100644
--- a/arch/powerpc/kvm/book3s_paired_singles.c
+++ b/arch/powerpc/kvm/book3s_paired_singles.c
@@ -169,7 +169,7 @@ static void kvmppc_inject_pf(struct kvm_vcpu *vcpu, ulong eaddr, bool is_store)
shared->msr = kvmppc_set_field(shared->msr, 33, 36, 0);
shared->msr = kvmppc_set_field(shared->msr, 42, 47, 0);
- vcpu->arch.dear = eaddr;
+ shared->dar = eaddr;
/* Page Fault */
dsisr = kvmppc_set_field(0, 33, 33, 1);
if (is_store)
diff --git a/arch/powerpc/kvm/booke.c b/arch/powerpc/kvm/booke.c
index ddb4cac..5844bcf 100644
--- a/arch/powerpc/kvm/booke.c
+++ b/arch/powerpc/kvm/booke.c
@@ -195,7 +195,7 @@ static int kvmppc_booke_irqprio_deliver(struct kvm_vcpu *vcpu,
if (update_esr == true)
vcpu->arch.esr = vcpu->arch.queued_esr;
if (update_dear == true)
- vcpu->arch.dear = vcpu->arch.queued_dear;
+ vcpu->arch.shared->dar = vcpu->arch.queued_dear;
kvmppc_set_msr(vcpu, vcpu->arch.shared->msr & msr_mask);
clear_bit(priority, &vcpu->arch.pending_exceptions);
diff --git a/arch/powerpc/kvm/booke_emulate.c b/arch/powerpc/kvm/booke_emulate.c
index b115203..51ef453 100644
--- a/arch/powerpc/kvm/booke_emulate.c
+++ b/arch/powerpc/kvm/booke_emulate.c
@@ -105,7 +105,7 @@ int kvmppc_booke_emulate_mtspr(struct kvm_vcpu *vcpu, int sprn, int rs)
switch (sprn) {
case SPRN_DEAR:
- vcpu->arch.dear = spr_val; break;
+ vcpu->arch.shared->dar = spr_val; break;
case SPRN_ESR:
vcpu->arch.esr = spr_val; break;
case SPRN_DBCR0:
@@ -200,7 +200,7 @@ int kvmppc_booke_emulate_mfspr(struct kvm_vcpu *vcpu, int sprn, int rt)
case SPRN_IVPR:
kvmppc_set_gpr(vcpu, rt, vcpu->arch.ivpr); break;
case SPRN_DEAR:
- kvmppc_set_gpr(vcpu, rt, vcpu->arch.dear); break;
+ kvmppc_set_gpr(vcpu, rt, vcpu->arch.shared->dar); break;
case SPRN_ESR:
kvmppc_set_gpr(vcpu, rt, vcpu->arch.esr); break;
case SPRN_DBCR0:
--
1.6.0.2
^ permalink raw reply related [flat|nested] 227+ messages in thread* [PATCH 04/26] KVM: PPC: Convert DAR to shared page.
@ 2010-06-25 23:24 ` Alexander Graf
0 siblings, 0 replies; 227+ messages in thread
From: Alexander Graf @ 2010-06-25 23:24 UTC (permalink / raw)
To: kvm-ppc; +Cc: linuxppc-dev, KVM list
The DAR register contains the address a data page fault occured at. This
register behaves pretty much like a simple data storage register that gets
written to on data faults. There is no hypervisor interaction required on
read or write.
This patch converts all users of the current field to the shared page.
Signed-off-by: Alexander Graf <agraf@suse.de>
---
arch/powerpc/include/asm/kvm_host.h | 1 -
arch/powerpc/include/asm/kvm_para.h | 1 +
arch/powerpc/kvm/book3s.c | 14 +++++++-------
arch/powerpc/kvm/book3s_emulate.c | 6 +++---
arch/powerpc/kvm/book3s_paired_singles.c | 2 +-
arch/powerpc/kvm/booke.c | 2 +-
arch/powerpc/kvm/booke_emulate.c | 4 ++--
7 files changed, 15 insertions(+), 15 deletions(-)
diff --git a/arch/powerpc/include/asm/kvm_host.h b/arch/powerpc/include/asm/kvm_host.h
index 249c242..108dabc 100644
--- a/arch/powerpc/include/asm/kvm_host.h
+++ b/arch/powerpc/include/asm/kvm_host.h
@@ -230,7 +230,6 @@ struct kvm_vcpu_arch {
ulong csrr1;
ulong dsrr0;
ulong dsrr1;
- ulong dear;
ulong esr;
u32 dec;
u32 decar;
diff --git a/arch/powerpc/include/asm/kvm_para.h b/arch/powerpc/include/asm/kvm_para.h
index 9f7565b..ec72a1c 100644
--- a/arch/powerpc/include/asm/kvm_para.h
+++ b/arch/powerpc/include/asm/kvm_para.h
@@ -23,6 +23,7 @@
#include <linux/types.h>
struct kvm_vcpu_arch_shared {
+ __u64 dar;
__u64 msr;
__u32 dsisr;
};
diff --git a/arch/powerpc/kvm/book3s.c b/arch/powerpc/kvm/book3s.c
index 57fd73e..245bd2d 100644
--- a/arch/powerpc/kvm/book3s.c
+++ b/arch/powerpc/kvm/book3s.c
@@ -594,14 +594,14 @@ int kvmppc_handle_pagefault(struct kvm_run *run, struct kvm_vcpu *vcpu,
if (page_found == -ENOENT) {
/* Page not found in guest PTE entries */
- vcpu->arch.dear = kvmppc_get_fault_dar(vcpu);
+ vcpu->arch.shared->dar = kvmppc_get_fault_dar(vcpu);
vcpu->arch.shared->dsisr = to_svcpu(vcpu)->fault_dsisr;
vcpu->arch.shared->msr |=
(to_svcpu(vcpu)->shadow_srr1 & 0x00000000f8000000ULL);
kvmppc_book3s_queue_irqprio(vcpu, vec);
} else if (page_found == -EPERM) {
/* Storage protection */
- vcpu->arch.dear = kvmppc_get_fault_dar(vcpu);
+ vcpu->arch.shared->dar = kvmppc_get_fault_dar(vcpu);
vcpu->arch.shared->dsisr =
to_svcpu(vcpu)->fault_dsisr & ~DSISR_NOHPTE;
vcpu->arch.shared->dsisr |= DSISR_PROTFAULT;
@@ -610,7 +610,7 @@ int kvmppc_handle_pagefault(struct kvm_run *run, struct kvm_vcpu *vcpu,
kvmppc_book3s_queue_irqprio(vcpu, vec);
} else if (page_found == -EINVAL) {
/* Page not found in guest SLB */
- vcpu->arch.dear = kvmppc_get_fault_dar(vcpu);
+ vcpu->arch.shared->dar = kvmppc_get_fault_dar(vcpu);
kvmppc_book3s_queue_irqprio(vcpu, vec + 0x80);
} else if (!is_mmio &&
kvmppc_visible_gfn(vcpu, pte.raddr >> PAGE_SHIFT)) {
@@ -867,17 +867,17 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
if (to_svcpu(vcpu)->fault_dsisr & DSISR_NOHPTE) {
r = kvmppc_handle_pagefault(run, vcpu, dar, exit_nr);
} else {
- vcpu->arch.dear = dar;
+ vcpu->arch.shared->dar = dar;
vcpu->arch.shared->dsisr = to_svcpu(vcpu)->fault_dsisr;
kvmppc_book3s_queue_irqprio(vcpu, exit_nr);
- kvmppc_mmu_pte_flush(vcpu, vcpu->arch.dear, ~0xFFFUL);
+ kvmppc_mmu_pte_flush(vcpu, dar, ~0xFFFUL);
r = RESUME_GUEST;
}
break;
}
case BOOK3S_INTERRUPT_DATA_SEGMENT:
if (kvmppc_mmu_map_segment(vcpu, kvmppc_get_fault_dar(vcpu)) < 0) {
- vcpu->arch.dear = kvmppc_get_fault_dar(vcpu);
+ vcpu->arch.shared->dar = kvmppc_get_fault_dar(vcpu);
kvmppc_book3s_queue_irqprio(vcpu,
BOOK3S_INTERRUPT_DATA_SEGMENT);
}
@@ -997,7 +997,7 @@ program_interrupt:
if (kvmppc_read_inst(vcpu) == EMULATE_DONE) {
vcpu->arch.shared->dsisr = kvmppc_alignment_dsisr(vcpu,
kvmppc_get_last_inst(vcpu));
- vcpu->arch.dear = kvmppc_alignment_dar(vcpu,
+ vcpu->arch.shared->dar = kvmppc_alignment_dar(vcpu,
kvmppc_get_last_inst(vcpu));
kvmppc_book3s_queue_irqprio(vcpu, exit_nr);
}
diff --git a/arch/powerpc/kvm/book3s_emulate.c b/arch/powerpc/kvm/book3s_emulate.c
index 9982ff1..c147864 100644
--- a/arch/powerpc/kvm/book3s_emulate.c
+++ b/arch/powerpc/kvm/book3s_emulate.c
@@ -212,7 +212,7 @@ int kvmppc_core_emulate_op(struct kvm_run *run, struct kvm_vcpu *vcpu,
r = kvmppc_st(vcpu, &addr, 32, zeros, true);
if ((r == -ENOENT) || (r == -EPERM)) {
*advance = 0;
- vcpu->arch.dear = vaddr;
+ vcpu->arch.shared->dar = vaddr;
to_svcpu(vcpu)->fault_dar = vaddr;
dsisr = DSISR_ISSTORE;
@@ -330,7 +330,7 @@ int kvmppc_core_emulate_mtspr(struct kvm_vcpu *vcpu, int sprn, int rs)
vcpu->arch.shared->dsisr = spr_val;
break;
case SPRN_DAR:
- vcpu->arch.dear = spr_val;
+ vcpu->arch.shared->dar = spr_val;
break;
case SPRN_HIOR:
to_book3s(vcpu)->hior = spr_val;
@@ -443,7 +443,7 @@ int kvmppc_core_emulate_mfspr(struct kvm_vcpu *vcpu, int sprn, int rt)
kvmppc_set_gpr(vcpu, rt, vcpu->arch.shared->dsisr);
break;
case SPRN_DAR:
- kvmppc_set_gpr(vcpu, rt, vcpu->arch.dear);
+ kvmppc_set_gpr(vcpu, rt, vcpu->arch.shared->dar);
break;
case SPRN_HIOR:
kvmppc_set_gpr(vcpu, rt, to_book3s(vcpu)->hior);
diff --git a/arch/powerpc/kvm/book3s_paired_singles.c b/arch/powerpc/kvm/book3s_paired_singles.c
index 749dfbd..807576f 100644
--- a/arch/powerpc/kvm/book3s_paired_singles.c
+++ b/arch/powerpc/kvm/book3s_paired_singles.c
@@ -169,7 +169,7 @@ static void kvmppc_inject_pf(struct kvm_vcpu *vcpu, ulong eaddr, bool is_store)
shared->msr = kvmppc_set_field(shared->msr, 33, 36, 0);
shared->msr = kvmppc_set_field(shared->msr, 42, 47, 0);
- vcpu->arch.dear = eaddr;
+ shared->dar = eaddr;
/* Page Fault */
dsisr = kvmppc_set_field(0, 33, 33, 1);
if (is_store)
diff --git a/arch/powerpc/kvm/booke.c b/arch/powerpc/kvm/booke.c
index ddb4cac..5844bcf 100644
--- a/arch/powerpc/kvm/booke.c
+++ b/arch/powerpc/kvm/booke.c
@@ -195,7 +195,7 @@ static int kvmppc_booke_irqprio_deliver(struct kvm_vcpu *vcpu,
if (update_esr == true)
vcpu->arch.esr = vcpu->arch.queued_esr;
if (update_dear == true)
- vcpu->arch.dear = vcpu->arch.queued_dear;
+ vcpu->arch.shared->dar = vcpu->arch.queued_dear;
kvmppc_set_msr(vcpu, vcpu->arch.shared->msr & msr_mask);
clear_bit(priority, &vcpu->arch.pending_exceptions);
diff --git a/arch/powerpc/kvm/booke_emulate.c b/arch/powerpc/kvm/booke_emulate.c
index b115203..51ef453 100644
--- a/arch/powerpc/kvm/booke_emulate.c
+++ b/arch/powerpc/kvm/booke_emulate.c
@@ -105,7 +105,7 @@ int kvmppc_booke_emulate_mtspr(struct kvm_vcpu *vcpu, int sprn, int rs)
switch (sprn) {
case SPRN_DEAR:
- vcpu->arch.dear = spr_val; break;
+ vcpu->arch.shared->dar = spr_val; break;
case SPRN_ESR:
vcpu->arch.esr = spr_val; break;
case SPRN_DBCR0:
@@ -200,7 +200,7 @@ int kvmppc_booke_emulate_mfspr(struct kvm_vcpu *vcpu, int sprn, int rt)
case SPRN_IVPR:
kvmppc_set_gpr(vcpu, rt, vcpu->arch.ivpr); break;
case SPRN_DEAR:
- kvmppc_set_gpr(vcpu, rt, vcpu->arch.dear); break;
+ kvmppc_set_gpr(vcpu, rt, vcpu->arch.shared->dar); break;
case SPRN_ESR:
kvmppc_set_gpr(vcpu, rt, vcpu->arch.esr); break;
case SPRN_DBCR0:
--
1.6.0.2
^ permalink raw reply related [flat|nested] 227+ messages in thread
* [PATCH 08/26] KVM: PPC: Add PV guest critical sections
2010-06-25 23:24 ` Alexander Graf
(?)
@ 2010-06-25 23:24 ` Alexander Graf
-1 siblings, 0 replies; 227+ messages in thread
From: Alexander Graf @ 2010-06-25 23:24 UTC (permalink / raw)
To: kvm-ppc-u79uwXL29TY76Z2rM5mHXA; +Cc: KVM list, linuxppc-dev
When running in hooked code we need a way to disable interrupts without
clobbering any interrupts or exiting out to the hypervisor.
To achieve this, we have an additional critical field in the shared page. If
that field is equal to the r1 register of the guest, it tells the hypervisor
that we're in such a critical section and thus may not receive any interrupts.
Signed-off-by: Alexander Graf <agraf@suse.de>
---
arch/powerpc/include/asm/kvm_para.h | 1 +
arch/powerpc/kvm/book3s.c | 15 +++++++++++++--
arch/powerpc/kvm/booke.c | 12 ++++++++++++
3 files changed, 26 insertions(+), 2 deletions(-)
diff --git a/arch/powerpc/include/asm/kvm_para.h b/arch/powerpc/include/asm/kvm_para.h
index eaab306..d1fe9ae 100644
--- a/arch/powerpc/include/asm/kvm_para.h
+++ b/arch/powerpc/include/asm/kvm_para.h
@@ -23,6 +23,7 @@
#include <linux/types.h>
struct kvm_vcpu_arch_shared {
+ __u64 critical; /* Guest may not get interrupts if = r1 */
__u64 sprg0;
__u64 sprg1;
__u64 sprg2;
diff --git a/arch/powerpc/kvm/book3s.c b/arch/powerpc/kvm/book3s.c
index e8001c5..f0e8047 100644
--- a/arch/powerpc/kvm/book3s.c
+++ b/arch/powerpc/kvm/book3s.c
@@ -251,14 +251,25 @@ int kvmppc_book3s_irqprio_deliver(struct kvm_vcpu *vcpu, unsigned int priority)
int deliver = 1;
int vec = 0;
ulong flags = 0ULL;
+ ulong crit_raw = vcpu->arch.shared->critical;
+ ulong crit_r1 = kvmppc_get_gpr(vcpu, 1);
+ bool crit;
+
+ /* Truncate crit indicators in 32 bit mode */
+ if (!(vcpu->arch.shared->msr & MSR_SF)) {
+ crit_raw &= 0xffffffff;
+ crit_r1 &= 0xffffffff;
+ }
+
+ crit = (crit_raw = crit_r1);
switch (priority) {
case BOOK3S_IRQPRIO_DECREMENTER:
- deliver = vcpu->arch.shared->msr & MSR_EE;
+ deliver = (vcpu->arch.shared->msr & MSR_EE) && !crit;
vec = BOOK3S_INTERRUPT_DECREMENTER;
break;
case BOOK3S_IRQPRIO_EXTERNAL:
- deliver = vcpu->arch.shared->msr & MSR_EE;
+ deliver = (vcpu->arch.shared->msr & MSR_EE) && !crit;
vec = BOOK3S_INTERRUPT_EXTERNAL;
break;
case BOOK3S_IRQPRIO_SYSTEM_RESET:
diff --git a/arch/powerpc/kvm/booke.c b/arch/powerpc/kvm/booke.c
index e7d1216..485f8fa 100644
--- a/arch/powerpc/kvm/booke.c
+++ b/arch/powerpc/kvm/booke.c
@@ -147,6 +147,17 @@ static int kvmppc_booke_irqprio_deliver(struct kvm_vcpu *vcpu,
int allowed = 0;
ulong uninitialized_var(msr_mask);
bool update_esr = false, update_dear = false;
+ ulong crit_raw = vcpu->arch.shared->critical;
+ ulong crit_r1 = kvmppc_get_gpr(vcpu, 1);
+ bool crit;
+
+ /* Truncate crit indicators in 32 bit mode */
+ if (!(vcpu->arch.shared->msr & MSR_SF)) {
+ crit_raw &= 0xffffffff;
+ crit_r1 &= 0xffffffff;
+ }
+
+ crit = (crit_raw = crit_r1);
switch (priority) {
case BOOKE_IRQPRIO_DTLB_MISS:
@@ -181,6 +192,7 @@ static int kvmppc_booke_irqprio_deliver(struct kvm_vcpu *vcpu,
case BOOKE_IRQPRIO_DECREMENTER:
case BOOKE_IRQPRIO_FIT:
allowed = vcpu->arch.shared->msr & MSR_EE;
+ allowed = allowed && !crit;
msr_mask = MSR_CE|MSR_ME|MSR_DE;
break;
case BOOKE_IRQPRIO_DEBUG:
--
1.6.0.2
^ permalink raw reply related [flat|nested] 227+ messages in thread* [PATCH 08/26] KVM: PPC: Add PV guest critical sections
@ 2010-06-25 23:24 ` Alexander Graf
0 siblings, 0 replies; 227+ messages in thread
From: Alexander Graf @ 2010-06-25 23:24 UTC (permalink / raw)
To: kvm-ppc-u79uwXL29TY76Z2rM5mHXA; +Cc: KVM list, linuxppc-dev
When running in hooked code we need a way to disable interrupts without
clobbering any interrupts or exiting out to the hypervisor.
To achieve this, we have an additional critical field in the shared page. If
that field is equal to the r1 register of the guest, it tells the hypervisor
that we're in such a critical section and thus may not receive any interrupts.
Signed-off-by: Alexander Graf <agraf-l3A5Bk7waGM@public.gmane.org>
---
arch/powerpc/include/asm/kvm_para.h | 1 +
arch/powerpc/kvm/book3s.c | 15 +++++++++++++--
arch/powerpc/kvm/booke.c | 12 ++++++++++++
3 files changed, 26 insertions(+), 2 deletions(-)
diff --git a/arch/powerpc/include/asm/kvm_para.h b/arch/powerpc/include/asm/kvm_para.h
index eaab306..d1fe9ae 100644
--- a/arch/powerpc/include/asm/kvm_para.h
+++ b/arch/powerpc/include/asm/kvm_para.h
@@ -23,6 +23,7 @@
#include <linux/types.h>
struct kvm_vcpu_arch_shared {
+ __u64 critical; /* Guest may not get interrupts if == r1 */
__u64 sprg0;
__u64 sprg1;
__u64 sprg2;
diff --git a/arch/powerpc/kvm/book3s.c b/arch/powerpc/kvm/book3s.c
index e8001c5..f0e8047 100644
--- a/arch/powerpc/kvm/book3s.c
+++ b/arch/powerpc/kvm/book3s.c
@@ -251,14 +251,25 @@ int kvmppc_book3s_irqprio_deliver(struct kvm_vcpu *vcpu, unsigned int priority)
int deliver = 1;
int vec = 0;
ulong flags = 0ULL;
+ ulong crit_raw = vcpu->arch.shared->critical;
+ ulong crit_r1 = kvmppc_get_gpr(vcpu, 1);
+ bool crit;
+
+ /* Truncate crit indicators in 32 bit mode */
+ if (!(vcpu->arch.shared->msr & MSR_SF)) {
+ crit_raw &= 0xffffffff;
+ crit_r1 &= 0xffffffff;
+ }
+
+ crit = (crit_raw == crit_r1);
switch (priority) {
case BOOK3S_IRQPRIO_DECREMENTER:
- deliver = vcpu->arch.shared->msr & MSR_EE;
+ deliver = (vcpu->arch.shared->msr & MSR_EE) && !crit;
vec = BOOK3S_INTERRUPT_DECREMENTER;
break;
case BOOK3S_IRQPRIO_EXTERNAL:
- deliver = vcpu->arch.shared->msr & MSR_EE;
+ deliver = (vcpu->arch.shared->msr & MSR_EE) && !crit;
vec = BOOK3S_INTERRUPT_EXTERNAL;
break;
case BOOK3S_IRQPRIO_SYSTEM_RESET:
diff --git a/arch/powerpc/kvm/booke.c b/arch/powerpc/kvm/booke.c
index e7d1216..485f8fa 100644
--- a/arch/powerpc/kvm/booke.c
+++ b/arch/powerpc/kvm/booke.c
@@ -147,6 +147,17 @@ static int kvmppc_booke_irqprio_deliver(struct kvm_vcpu *vcpu,
int allowed = 0;
ulong uninitialized_var(msr_mask);
bool update_esr = false, update_dear = false;
+ ulong crit_raw = vcpu->arch.shared->critical;
+ ulong crit_r1 = kvmppc_get_gpr(vcpu, 1);
+ bool crit;
+
+ /* Truncate crit indicators in 32 bit mode */
+ if (!(vcpu->arch.shared->msr & MSR_SF)) {
+ crit_raw &= 0xffffffff;
+ crit_r1 &= 0xffffffff;
+ }
+
+ crit = (crit_raw == crit_r1);
switch (priority) {
case BOOKE_IRQPRIO_DTLB_MISS:
@@ -181,6 +192,7 @@ static int kvmppc_booke_irqprio_deliver(struct kvm_vcpu *vcpu,
case BOOKE_IRQPRIO_DECREMENTER:
case BOOKE_IRQPRIO_FIT:
allowed = vcpu->arch.shared->msr & MSR_EE;
+ allowed = allowed && !crit;
msr_mask = MSR_CE|MSR_ME|MSR_DE;
break;
case BOOKE_IRQPRIO_DEBUG:
--
1.6.0.2
^ permalink raw reply related [flat|nested] 227+ messages in thread* [PATCH 08/26] KVM: PPC: Add PV guest critical sections
@ 2010-06-25 23:24 ` Alexander Graf
0 siblings, 0 replies; 227+ messages in thread
From: Alexander Graf @ 2010-06-25 23:24 UTC (permalink / raw)
To: kvm-ppc; +Cc: linuxppc-dev, KVM list
When running in hooked code we need a way to disable interrupts without
clobbering any interrupts or exiting out to the hypervisor.
To achieve this, we have an additional critical field in the shared page. If
that field is equal to the r1 register of the guest, it tells the hypervisor
that we're in such a critical section and thus may not receive any interrupts.
Signed-off-by: Alexander Graf <agraf@suse.de>
---
arch/powerpc/include/asm/kvm_para.h | 1 +
arch/powerpc/kvm/book3s.c | 15 +++++++++++++--
arch/powerpc/kvm/booke.c | 12 ++++++++++++
3 files changed, 26 insertions(+), 2 deletions(-)
diff --git a/arch/powerpc/include/asm/kvm_para.h b/arch/powerpc/include/asm/kvm_para.h
index eaab306..d1fe9ae 100644
--- a/arch/powerpc/include/asm/kvm_para.h
+++ b/arch/powerpc/include/asm/kvm_para.h
@@ -23,6 +23,7 @@
#include <linux/types.h>
struct kvm_vcpu_arch_shared {
+ __u64 critical; /* Guest may not get interrupts if == r1 */
__u64 sprg0;
__u64 sprg1;
__u64 sprg2;
diff --git a/arch/powerpc/kvm/book3s.c b/arch/powerpc/kvm/book3s.c
index e8001c5..f0e8047 100644
--- a/arch/powerpc/kvm/book3s.c
+++ b/arch/powerpc/kvm/book3s.c
@@ -251,14 +251,25 @@ int kvmppc_book3s_irqprio_deliver(struct kvm_vcpu *vcpu, unsigned int priority)
int deliver = 1;
int vec = 0;
ulong flags = 0ULL;
+ ulong crit_raw = vcpu->arch.shared->critical;
+ ulong crit_r1 = kvmppc_get_gpr(vcpu, 1);
+ bool crit;
+
+ /* Truncate crit indicators in 32 bit mode */
+ if (!(vcpu->arch.shared->msr & MSR_SF)) {
+ crit_raw &= 0xffffffff;
+ crit_r1 &= 0xffffffff;
+ }
+
+ crit = (crit_raw == crit_r1);
switch (priority) {
case BOOK3S_IRQPRIO_DECREMENTER:
- deliver = vcpu->arch.shared->msr & MSR_EE;
+ deliver = (vcpu->arch.shared->msr & MSR_EE) && !crit;
vec = BOOK3S_INTERRUPT_DECREMENTER;
break;
case BOOK3S_IRQPRIO_EXTERNAL:
- deliver = vcpu->arch.shared->msr & MSR_EE;
+ deliver = (vcpu->arch.shared->msr & MSR_EE) && !crit;
vec = BOOK3S_INTERRUPT_EXTERNAL;
break;
case BOOK3S_IRQPRIO_SYSTEM_RESET:
diff --git a/arch/powerpc/kvm/booke.c b/arch/powerpc/kvm/booke.c
index e7d1216..485f8fa 100644
--- a/arch/powerpc/kvm/booke.c
+++ b/arch/powerpc/kvm/booke.c
@@ -147,6 +147,17 @@ static int kvmppc_booke_irqprio_deliver(struct kvm_vcpu *vcpu,
int allowed = 0;
ulong uninitialized_var(msr_mask);
bool update_esr = false, update_dear = false;
+ ulong crit_raw = vcpu->arch.shared->critical;
+ ulong crit_r1 = kvmppc_get_gpr(vcpu, 1);
+ bool crit;
+
+ /* Truncate crit indicators in 32 bit mode */
+ if (!(vcpu->arch.shared->msr & MSR_SF)) {
+ crit_raw &= 0xffffffff;
+ crit_r1 &= 0xffffffff;
+ }
+
+ crit = (crit_raw == crit_r1);
switch (priority) {
case BOOKE_IRQPRIO_DTLB_MISS:
@@ -181,6 +192,7 @@ static int kvmppc_booke_irqprio_deliver(struct kvm_vcpu *vcpu,
case BOOKE_IRQPRIO_DECREMENTER:
case BOOKE_IRQPRIO_FIT:
allowed = vcpu->arch.shared->msr & MSR_EE;
+ allowed = allowed && !crit;
msr_mask = MSR_CE|MSR_ME|MSR_DE;
break;
case BOOKE_IRQPRIO_DEBUG:
--
1.6.0.2
^ permalink raw reply related [flat|nested] 227+ messages in thread[parent not found: <1277508314-915-9-git-send-email-agraf-l3A5Bk7waGM@public.gmane.org>]
* Re: [PATCH 08/26] KVM: PPC: Add PV guest critical sections
2010-06-25 23:24 ` Alexander Graf
(?)
@ 2010-06-27 8:21 ` Avi Kivity
-1 siblings, 0 replies; 227+ messages in thread
From: Avi Kivity @ 2010-06-27 8:21 UTC (permalink / raw)
To: Alexander Graf; +Cc: kvm-ppc-u79uwXL29TY76Z2rM5mHXA, KVM list, linuxppc-dev
On 06/26/2010 02:24 AM, Alexander Graf wrote:
> When running in hooked code we need a way to disable interrupts without
> clobbering any interrupts or exiting out to the hypervisor.
>
> To achieve this, we have an additional critical field in the shared page. If
> that field is equal to the r1 register of the guest, it tells the hypervisor
> that we're in such a critical section and thus may not receive any interrupts.
>
Is r1 reserved for this purpose? Can't it match accidentally?
Why won't zero/nonzero work for this?
--
error compiling committee.c: too many arguments to function
^ permalink raw reply [flat|nested] 227+ messages in thread
* Re: [PATCH 08/26] KVM: PPC: Add PV guest critical sections
@ 2010-06-27 8:21 ` Avi Kivity
0 siblings, 0 replies; 227+ messages in thread
From: Avi Kivity @ 2010-06-27 8:21 UTC (permalink / raw)
To: Alexander Graf; +Cc: kvm-ppc-u79uwXL29TY76Z2rM5mHXA, KVM list, linuxppc-dev
On 06/26/2010 02:24 AM, Alexander Graf wrote:
> When running in hooked code we need a way to disable interrupts without
> clobbering any interrupts or exiting out to the hypervisor.
>
> To achieve this, we have an additional critical field in the shared page. If
> that field is equal to the r1 register of the guest, it tells the hypervisor
> that we're in such a critical section and thus may not receive any interrupts.
>
Is r1 reserved for this purpose? Can't it match accidentally?
Why won't zero/nonzero work for this?
--
error compiling committee.c: too many arguments to function
^ permalink raw reply [flat|nested] 227+ messages in thread
* Re: [PATCH 08/26] KVM: PPC: Add PV guest critical sections
@ 2010-06-27 8:21 ` Avi Kivity
0 siblings, 0 replies; 227+ messages in thread
From: Avi Kivity @ 2010-06-27 8:21 UTC (permalink / raw)
To: Alexander Graf; +Cc: linuxppc-dev, KVM list, kvm-ppc
On 06/26/2010 02:24 AM, Alexander Graf wrote:
> When running in hooked code we need a way to disable interrupts without
> clobbering any interrupts or exiting out to the hypervisor.
>
> To achieve this, we have an additional critical field in the shared page. If
> that field is equal to the r1 register of the guest, it tells the hypervisor
> that we're in such a critical section and thus may not receive any interrupts.
>
Is r1 reserved for this purpose? Can't it match accidentally?
Why won't zero/nonzero work for this?
--
error compiling committee.c: too many arguments to function
^ permalink raw reply [flat|nested] 227+ messages in thread
[parent not found: <4C2709F4.10805-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>]
* Re: [PATCH 08/26] KVM: PPC: Add PV guest critical sections
2010-06-27 8:21 ` Avi Kivity
(?)
@ 2010-06-27 9:40 ` Alexander Graf
-1 siblings, 0 replies; 227+ messages in thread
From: Alexander Graf @ 2010-06-27 9:40 UTC (permalink / raw)
To: Avi Kivity
Cc: kvm-ppc-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, KVM list,
linuxppc-dev
Am 27.06.2010 um 10:21 schrieb Avi Kivity <avi@redhat.com>:
> On 06/26/2010 02:24 AM, Alexander Graf wrote:
>> When running in hooked code we need a way to disable interrupts
>> without
>> clobbering any interrupts or exiting out to the hypervisor.
>>
>> To achieve this, we have an additional critical field in the shared
>> page. If
>> that field is equal to the r1 register of the guest, it tells the
>> hypervisor
>> that we're in such a critical section and thus may not receive any
>> interrupts.
>>
>
> Is r1 reserved for this purpose? Can't it match accidentally?
r1 is defined by the abi to be the stack.
>
> Why won't zero/nonzero work for this?
Because there is no store immediate opcode on powerpc :(.
Alex
^ permalink raw reply [flat|nested] 227+ messages in thread
* Re: [PATCH 08/26] KVM: PPC: Add PV guest critical sections
@ 2010-06-27 9:40 ` Alexander Graf
0 siblings, 0 replies; 227+ messages in thread
From: Alexander Graf @ 2010-06-27 9:40 UTC (permalink / raw)
To: Avi Kivity
Cc: kvm-ppc-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, KVM list,
linuxppc-dev
Am 27.06.2010 um 10:21 schrieb Avi Kivity <avi-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>:
> On 06/26/2010 02:24 AM, Alexander Graf wrote:
>> When running in hooked code we need a way to disable interrupts
>> without
>> clobbering any interrupts or exiting out to the hypervisor.
>>
>> To achieve this, we have an additional critical field in the shared
>> page. If
>> that field is equal to the r1 register of the guest, it tells the
>> hypervisor
>> that we're in such a critical section and thus may not receive any
>> interrupts.
>>
>
> Is r1 reserved for this purpose? Can't it match accidentally?
r1 is defined by the abi to be the stack.
>
> Why won't zero/nonzero work for this?
Because there is no store immediate opcode on powerpc :(.
Alex
^ permalink raw reply [flat|nested] 227+ messages in thread
* Re: [PATCH 08/26] KVM: PPC: Add PV guest critical sections
@ 2010-06-27 9:40 ` Alexander Graf
0 siblings, 0 replies; 227+ messages in thread
From: Alexander Graf @ 2010-06-27 9:40 UTC (permalink / raw)
To: Avi Kivity; +Cc: linuxppc-dev, KVM list, kvm-ppc@vger.kernel.org
Am 27.06.2010 um 10:21 schrieb Avi Kivity <avi@redhat.com>:
> On 06/26/2010 02:24 AM, Alexander Graf wrote:
>> When running in hooked code we need a way to disable interrupts
>> without
>> clobbering any interrupts or exiting out to the hypervisor.
>>
>> To achieve this, we have an additional critical field in the shared
>> page. If
>> that field is equal to the r1 register of the guest, it tells the
>> hypervisor
>> that we're in such a critical section and thus may not receive any
>> interrupts.
>>
>
> Is r1 reserved for this purpose? Can't it match accidentally?
r1 is defined by the abi to be the stack.
>
> Why won't zero/nonzero work for this?
Because there is no store immediate opcode on powerpc :(.
Alex
^ permalink raw reply [flat|nested] 227+ messages in thread
* Re: [PATCH 08/26] KVM: PPC: Add PV guest critical sections
2010-06-27 9:40 ` Alexander Graf
@ 2010-06-27 9:52 ` Avi Kivity
-1 siblings, 0 replies; 227+ messages in thread
From: Avi Kivity @ 2010-06-27 9:52 UTC (permalink / raw)
To: Alexander Graf; +Cc: linuxppc-dev, KVM list, kvm-ppc@vger.kernel.org
On 06/27/2010 12:40 PM, Alexander Graf wrote:
>
> Am 27.06.2010 um 10:21 schrieb Avi Kivity <avi@redhat.com>:
>
>> On 06/26/2010 02:24 AM, Alexander Graf wrote:
>>> When running in hooked code we need a way to disable interrupts without
>>> clobbering any interrupts or exiting out to the hypervisor.
>>>
>>> To achieve this, we have an additional critical field in the shared
>>> page. If
>>> that field is equal to the r1 register of the guest, it tells the
>>> hypervisor
>>> that we're in such a critical section and thus may not receive any
>>> interrupts.
>>>
>>
>> Is r1 reserved for this purpose? Can't it match accidentally?
>
> r1 is defined by the abi to be the stack.
Neat trick!
>>
>> Why won't zero/nonzero work for this?
>
> Because there is no store immediate opcode on powerpc :(.
Or inc/dec...
--
error compiling committee.c: too many arguments to function
^ permalink raw reply [flat|nested] 227+ messages in thread
* Re: [PATCH 08/26] KVM: PPC: Add PV guest critical sections
@ 2010-06-27 9:52 ` Avi Kivity
0 siblings, 0 replies; 227+ messages in thread
From: Avi Kivity @ 2010-06-27 9:52 UTC (permalink / raw)
To: Alexander Graf; +Cc: linuxppc-dev, KVM list, kvm-ppc@vger.kernel.org
On 06/27/2010 12:40 PM, Alexander Graf wrote:
>
> Am 27.06.2010 um 10:21 schrieb Avi Kivity <avi@redhat.com>:
>
>> On 06/26/2010 02:24 AM, Alexander Graf wrote:
>>> When running in hooked code we need a way to disable interrupts without
>>> clobbering any interrupts or exiting out to the hypervisor.
>>>
>>> To achieve this, we have an additional critical field in the shared
>>> page. If
>>> that field is equal to the r1 register of the guest, it tells the
>>> hypervisor
>>> that we're in such a critical section and thus may not receive any
>>> interrupts.
>>>
>>
>> Is r1 reserved for this purpose? Can't it match accidentally?
>
> r1 is defined by the abi to be the stack.
Neat trick!
>>
>> Why won't zero/nonzero work for this?
>
> Because there is no store immediate opcode on powerpc :(.
Or inc/dec...
--
error compiling committee.c: too many arguments to function
^ permalink raw reply [flat|nested] 227+ messages in thread
* Re: [PATCH 08/26] KVM: PPC: Add PV guest critical sections
2010-06-27 9:52 ` Avi Kivity
(?)
@ 2010-06-27 10:33 ` Alexander Graf
-1 siblings, 0 replies; 227+ messages in thread
From: Alexander Graf @ 2010-06-27 10:33 UTC (permalink / raw)
To: Avi Kivity; +Cc: kvm-ppc@vger.kernel.org, KVM list, linuxppc-dev
Am 27.06.2010 um 11:52 schrieb Avi Kivity <avi@redhat.com>:
> On 06/27/2010 12:40 PM, Alexander Graf wrote:
>>
>> Am 27.06.2010 um 10:21 schrieb Avi Kivity <avi@redhat.com>:
>>
>>> On 06/26/2010 02:24 AM, Alexander Graf wrote:
>>>> When running in hooked code we need a way to disable interrupts
>>>> without
>>>> clobbering any interrupts or exiting out to the hypervisor.
>>>>
>>>> To achieve this, we have an additional critical field in the
>>>> shared page. If
>>>> that field is equal to the r1 register of the guest, it tells the
>>>> hypervisor
>>>> that we're in such a critical section and thus may not receive
>>>> any interrupts.
>>>>
>>>
>>> Is r1 reserved for this purpose? Can't it match accidentally?
>>
>> r1 is defined by the abi to be the stack.
>
> Neat trick!
>
>>>
>>> Why won't zero/nonzero work for this?
>>
>> Because there is no store immediate opcode on powerpc :(.
>
> Or inc/dec...
Uh - huh? How would that help?
Alex
^ permalink raw reply [flat|nested] 227+ messages in thread
* Re: [PATCH 08/26] KVM: PPC: Add PV guest critical sections
@ 2010-06-27 10:33 ` Alexander Graf
0 siblings, 0 replies; 227+ messages in thread
From: Alexander Graf @ 2010-06-27 10:33 UTC (permalink / raw)
To: Avi Kivity; +Cc: kvm-ppc@vger.kernel.org, KVM list, linuxppc-dev
Am 27.06.2010 um 11:52 schrieb Avi Kivity <avi@redhat.com>:
> On 06/27/2010 12:40 PM, Alexander Graf wrote:
>>
>> Am 27.06.2010 um 10:21 schrieb Avi Kivity <avi@redhat.com>:
>>
>>> On 06/26/2010 02:24 AM, Alexander Graf wrote:
>>>> When running in hooked code we need a way to disable interrupts
>>>> without
>>>> clobbering any interrupts or exiting out to the hypervisor.
>>>>
>>>> To achieve this, we have an additional critical field in the
>>>> shared page. If
>>>> that field is equal to the r1 register of the guest, it tells the
>>>> hypervisor
>>>> that we're in such a critical section and thus may not receive
>>>> any interrupts.
>>>>
>>>
>>> Is r1 reserved for this purpose? Can't it match accidentally?
>>
>> r1 is defined by the abi to be the stack.
>
> Neat trick!
>
>>>
>>> Why won't zero/nonzero work for this?
>>
>> Because there is no store immediate opcode on powerpc :(.
>
> Or inc/dec...
Uh - huh? How would that help?
Alex
^ permalink raw reply [flat|nested] 227+ messages in thread
* Re: [PATCH 08/26] KVM: PPC: Add PV guest critical sections
@ 2010-06-27 10:33 ` Alexander Graf
0 siblings, 0 replies; 227+ messages in thread
From: Alexander Graf @ 2010-06-27 10:33 UTC (permalink / raw)
To: Avi Kivity; +Cc: linuxppc-dev, KVM list, kvm-ppc@vger.kernel.org
Am 27.06.2010 um 11:52 schrieb Avi Kivity <avi@redhat.com>:
> On 06/27/2010 12:40 PM, Alexander Graf wrote:
>>
>> Am 27.06.2010 um 10:21 schrieb Avi Kivity <avi@redhat.com>:
>>
>>> On 06/26/2010 02:24 AM, Alexander Graf wrote:
>>>> When running in hooked code we need a way to disable interrupts
>>>> without
>>>> clobbering any interrupts or exiting out to the hypervisor.
>>>>
>>>> To achieve this, we have an additional critical field in the
>>>> shared page. If
>>>> that field is equal to the r1 register of the guest, it tells the
>>>> hypervisor
>>>> that we're in such a critical section and thus may not receive
>>>> any interrupts.
>>>>
>>>
>>> Is r1 reserved for this purpose? Can't it match accidentally?
>>
>> r1 is defined by the abi to be the stack.
>
> Neat trick!
>
>>>
>>> Why won't zero/nonzero work for this?
>>
>> Because there is no store immediate opcode on powerpc :(.
>
> Or inc/dec...
Uh - huh? How would that help?
Alex
^ permalink raw reply [flat|nested] 227+ messages in thread
[parent not found: <DFC77851-3BE7-4746-93DE-287D5E27EF7D-l3A5Bk7waGM@public.gmane.org>]
* Re: [PATCH 08/26] KVM: PPC: Add PV guest critical sections
2010-06-27 10:33 ` Alexander Graf
(?)
@ 2010-06-27 10:59 ` Avi Kivity
-1 siblings, 0 replies; 227+ messages in thread
From: Avi Kivity @ 2010-06-27 10:59 UTC (permalink / raw)
To: Alexander Graf
Cc: kvm-ppc-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, KVM list,
linuxppc-dev
On 06/27/2010 01:33 PM, Alexander Graf wrote:
>> Or inc/dec...
>
>
> Uh - huh? How would that help?
inc shared->critical # disable interrupts
--
error compiling committee.c: too many arguments to function
^ permalink raw reply [flat|nested] 227+ messages in thread
* Re: [PATCH 08/26] KVM: PPC: Add PV guest critical sections
@ 2010-06-27 10:59 ` Avi Kivity
0 siblings, 0 replies; 227+ messages in thread
From: Avi Kivity @ 2010-06-27 10:59 UTC (permalink / raw)
To: Alexander Graf
Cc: kvm-ppc-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, KVM list,
linuxppc-dev
On 06/27/2010 01:33 PM, Alexander Graf wrote:
>> Or inc/dec...
>
>
> Uh - huh? How would that help?
inc shared->critical # disable interrupts
--
error compiling committee.c: too many arguments to function
^ permalink raw reply [flat|nested] 227+ messages in thread
* Re: [PATCH 08/26] KVM: PPC: Add PV guest critical sections
@ 2010-06-27 10:59 ` Avi Kivity
0 siblings, 0 replies; 227+ messages in thread
From: Avi Kivity @ 2010-06-27 10:59 UTC (permalink / raw)
To: Alexander Graf; +Cc: linuxppc-dev, KVM list, kvm-ppc@vger.kernel.org
On 06/27/2010 01:33 PM, Alexander Graf wrote:
>> Or inc/dec...
>
>
> Uh - huh? How would that help?
inc shared->critical # disable interrupts
--
error compiling committee.c: too many arguments to function
^ permalink raw reply [flat|nested] 227+ messages in thread
[parent not found: <4C272F08.8090709-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>]
* Re: [PATCH 08/26] KVM: PPC: Add PV guest critical sections
2010-06-27 10:59 ` Avi Kivity
(?)
@ 2010-06-27 11:49 ` Alexander Graf
-1 siblings, 0 replies; 227+ messages in thread
From: Alexander Graf @ 2010-06-27 11:49 UTC (permalink / raw)
To: Avi Kivity
Cc: kvm-ppc-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, KVM list,
linuxppc-dev
Am 27.06.2010 um 12:59 schrieb Avi Kivity <avi@redhat.com>:
> On 06/27/2010 01:33 PM, Alexander Graf wrote:
>>> Or inc/dec...
>>
>>
>> Uh - huh? How would that help?
>
> inc shared->critical # disable interrupts
There is no opcode in the ppc isa that acts on momery without
involving a register.
An inc would be:
ld rX, A(0)
addi rX, rX, 1
std rX, A(0)
Alex
>
^ permalink raw reply [flat|nested] 227+ messages in thread
* Re: [PATCH 08/26] KVM: PPC: Add PV guest critical sections
@ 2010-06-27 11:49 ` Alexander Graf
0 siblings, 0 replies; 227+ messages in thread
From: Alexander Graf @ 2010-06-27 11:49 UTC (permalink / raw)
To: Avi Kivity
Cc: kvm-ppc-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, KVM list,
linuxppc-dev
Am 27.06.2010 um 12:59 schrieb Avi Kivity <avi-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>:
> On 06/27/2010 01:33 PM, Alexander Graf wrote:
>>> Or inc/dec...
>>
>>
>> Uh - huh? How would that help?
>
> inc shared->critical # disable interrupts
There is no opcode in the ppc isa that acts on momery without
involving a register.
An inc would be:
ld rX, A(0)
addi rX, rX, 1
std rX, A(0)
Alex
>
^ permalink raw reply [flat|nested] 227+ messages in thread
* Re: [PATCH 08/26] KVM: PPC: Add PV guest critical sections
@ 2010-06-27 11:49 ` Alexander Graf
0 siblings, 0 replies; 227+ messages in thread
From: Alexander Graf @ 2010-06-27 11:49 UTC (permalink / raw)
To: Avi Kivity; +Cc: linuxppc-dev, KVM list, kvm-ppc@vger.kernel.org
Am 27.06.2010 um 12:59 schrieb Avi Kivity <avi@redhat.com>:
> On 06/27/2010 01:33 PM, Alexander Graf wrote:
>>> Or inc/dec...
>>
>>
>> Uh - huh? How would that help?
>
> inc shared->critical # disable interrupts
There is no opcode in the ppc isa that acts on momery without
involving a register.
An inc would be:
ld rX, A(0)
addi rX, rX, 1
std rX, A(0)
Alex
>
^ permalink raw reply [flat|nested] 227+ messages in thread
* Re: [PATCH 08/26] KVM: PPC: Add PV guest critical sections
2010-06-27 11:49 ` Alexander Graf
(?)
@ 2010-06-27 11:53 ` Avi Kivity
-1 siblings, 0 replies; 227+ messages in thread
From: Avi Kivity @ 2010-06-27 11:53 UTC (permalink / raw)
To: Alexander Graf; +Cc: kvm-ppc@vger.kernel.org, KVM list, linuxppc-dev
On 06/27/2010 02:49 PM, Alexander Graf wrote:
>
> Am 27.06.2010 um 12:59 schrieb Avi Kivity <avi@redhat.com>:
>
>> On 06/27/2010 01:33 PM, Alexander Graf wrote:
>>>> Or inc/dec...
>>>
>>>
>>> Uh - huh? How would that help?
>>
>> inc shared->critical # disable interrupts
>
> There is no opcode in the ppc isa that acts on momery without
> involving a register.
>
> An inc would be:
>
> ld rX, A(0)
> addi rX, rX, 1
> std rX, A(0)
Right, I was agreeing with you. I meant there was no inc/dec mem insns.
--
error compiling committee.c: too many arguments to function
^ permalink raw reply [flat|nested] 227+ messages in thread
* Re: [PATCH 08/26] KVM: PPC: Add PV guest critical sections
@ 2010-06-27 11:53 ` Avi Kivity
0 siblings, 0 replies; 227+ messages in thread
From: Avi Kivity @ 2010-06-27 11:53 UTC (permalink / raw)
To: Alexander Graf; +Cc: kvm-ppc@vger.kernel.org, KVM list, linuxppc-dev
On 06/27/2010 02:49 PM, Alexander Graf wrote:
>
> Am 27.06.2010 um 12:59 schrieb Avi Kivity <avi@redhat.com>:
>
>> On 06/27/2010 01:33 PM, Alexander Graf wrote:
>>>> Or inc/dec...
>>>
>>>
>>> Uh - huh? How would that help?
>>
>> inc shared->critical # disable interrupts
>
> There is no opcode in the ppc isa that acts on momery without
> involving a register.
>
> An inc would be:
>
> ld rX, A(0)
> addi rX, rX, 1
> std rX, A(0)
Right, I was agreeing with you. I meant there was no inc/dec mem insns.
--
error compiling committee.c: too many arguments to function
^ permalink raw reply [flat|nested] 227+ messages in thread
* Re: [PATCH 08/26] KVM: PPC: Add PV guest critical sections
@ 2010-06-27 11:53 ` Avi Kivity
0 siblings, 0 replies; 227+ messages in thread
From: Avi Kivity @ 2010-06-27 11:53 UTC (permalink / raw)
To: Alexander Graf; +Cc: linuxppc-dev, KVM list, kvm-ppc@vger.kernel.org
On 06/27/2010 02:49 PM, Alexander Graf wrote:
>
> Am 27.06.2010 um 12:59 schrieb Avi Kivity <avi@redhat.com>:
>
>> On 06/27/2010 01:33 PM, Alexander Graf wrote:
>>>> Or inc/dec...
>>>
>>>
>>> Uh - huh? How would that help?
>>
>> inc shared->critical # disable interrupts
>
> There is no opcode in the ppc isa that acts on momery without
> involving a register.
>
> An inc would be:
>
> ld rX, A(0)
> addi rX, rX, 1
> std rX, A(0)
Right, I was agreeing with you. I meant there was no inc/dec mem insns.
--
error compiling committee.c: too many arguments to function
^ permalink raw reply [flat|nested] 227+ messages in thread
[parent not found: <4C273BAD.2090305-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>]
* Re: [PATCH 08/26] KVM: PPC: Add PV guest critical sections
2010-06-27 11:53 ` Avi Kivity
(?)
@ 2010-06-27 12:06 ` Alexander Graf
-1 siblings, 0 replies; 227+ messages in thread
From: Alexander Graf @ 2010-06-27 12:06 UTC (permalink / raw)
To: Avi Kivity
Cc: kvm-ppc-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, KVM list,
linuxppc-dev
Am 27.06.2010 um 13:53 schrieb Avi Kivity <avi@redhat.com>:
> On 06/27/2010 02:49 PM, Alexander Graf wrote:
>>
>> Am 27.06.2010 um 12:59 schrieb Avi Kivity <avi@redhat.com>:
>>
>>> On 06/27/2010 01:33 PM, Alexander Graf wrote:
>>>>> Or inc/dec...
>>>>
>>>>
>>>> Uh - huh? How would that help?
>>>
>>> inc shared->critical # disable interrupts
>>
>> There is no opcode in the ppc isa that acts on momery without
>> involving a register.
>>
>> An inc would be:
>>
>> ld rX, A(0)
>> addi rX, rX, 1
>> std rX, A(0)
>
> Right, I was agreeing with you. I meant there was no inc/dec mem
> insns.
Ah, I see :). I think that's really the only point where I deem the
x86 isa superior :).
Alex
^ permalink raw reply [flat|nested] 227+ messages in thread
* Re: [PATCH 08/26] KVM: PPC: Add PV guest critical sections
@ 2010-06-27 12:06 ` Alexander Graf
0 siblings, 0 replies; 227+ messages in thread
From: Alexander Graf @ 2010-06-27 12:06 UTC (permalink / raw)
To: Avi Kivity
Cc: kvm-ppc-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, KVM list,
linuxppc-dev
Am 27.06.2010 um 13:53 schrieb Avi Kivity <avi-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>:
> On 06/27/2010 02:49 PM, Alexander Graf wrote:
>>
>> Am 27.06.2010 um 12:59 schrieb Avi Kivity <avi-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>:
>>
>>> On 06/27/2010 01:33 PM, Alexander Graf wrote:
>>>>> Or inc/dec...
>>>>
>>>>
>>>> Uh - huh? How would that help?
>>>
>>> inc shared->critical # disable interrupts
>>
>> There is no opcode in the ppc isa that acts on momery without
>> involving a register.
>>
>> An inc would be:
>>
>> ld rX, A(0)
>> addi rX, rX, 1
>> std rX, A(0)
>
> Right, I was agreeing with you. I meant there was no inc/dec mem
> insns.
Ah, I see :). I think that's really the only point where I deem the
x86 isa superior :).
Alex
^ permalink raw reply [flat|nested] 227+ messages in thread
* Re: [PATCH 08/26] KVM: PPC: Add PV guest critical sections
@ 2010-06-27 12:06 ` Alexander Graf
0 siblings, 0 replies; 227+ messages in thread
From: Alexander Graf @ 2010-06-27 12:06 UTC (permalink / raw)
To: Avi Kivity; +Cc: linuxppc-dev, KVM list, kvm-ppc@vger.kernel.org
Am 27.06.2010 um 13:53 schrieb Avi Kivity <avi@redhat.com>:
> On 06/27/2010 02:49 PM, Alexander Graf wrote:
>>
>> Am 27.06.2010 um 12:59 schrieb Avi Kivity <avi@redhat.com>:
>>
>>> On 06/27/2010 01:33 PM, Alexander Graf wrote:
>>>>> Or inc/dec...
>>>>
>>>>
>>>> Uh - huh? How would that help?
>>>
>>> inc shared->critical # disable interrupts
>>
>> There is no opcode in the ppc isa that acts on momery without
>> involving a register.
>>
>> An inc would be:
>>
>> ld rX, A(0)
>> addi rX, rX, 1
>> std rX, A(0)
>
> Right, I was agreeing with you. I meant there was no inc/dec mem
> insns.
Ah, I see :). I think that's really the only point where I deem the
x86 isa superior :).
Alex
^ permalink raw reply [flat|nested] 227+ messages in thread
* Re: [PATCH 08/26] KVM: PPC: Add PV guest critical sections
2010-06-27 12:06 ` Alexander Graf
@ 2010-06-27 22:03 ` Benjamin Herrenschmidt
-1 siblings, 0 replies; 227+ messages in thread
From: Benjamin Herrenschmidt @ 2010-06-27 22:03 UTC (permalink / raw)
To: Alexander Graf
Cc: kvm-ppc@vger.kernel.org, linuxppc-dev, Avi Kivity, KVM list
On Sun, 2010-06-27 at 14:06 +0200, Alexander Graf wrote:
> > Right, I was agreeing with you. I meant there was no inc/dec mem
> > insns.
>
> Ah, I see :). I think that's really the only point where I deem the
> x86 isa superior :).
Heh, well, that's a typical RISC thing tho. I think ARM and MIPS are
like PowerPC here at least :-)
Cheers,
Ben.
^ permalink raw reply [flat|nested] 227+ messages in thread
* Re: [PATCH 08/26] KVM: PPC: Add PV guest critical sections
@ 2010-06-27 22:03 ` Benjamin Herrenschmidt
0 siblings, 0 replies; 227+ messages in thread
From: Benjamin Herrenschmidt @ 2010-06-27 22:03 UTC (permalink / raw)
To: Alexander Graf
Cc: kvm-ppc@vger.kernel.org, linuxppc-dev, Avi Kivity, KVM list
On Sun, 2010-06-27 at 14:06 +0200, Alexander Graf wrote:
> > Right, I was agreeing with you. I meant there was no inc/dec mem
> > insns.
>
> Ah, I see :). I think that's really the only point where I deem the
> x86 isa superior :).
Heh, well, that's a typical RISC thing tho. I think ARM and MIPS are
like PowerPC here at least :-)
Cheers,
Ben.
^ permalink raw reply [flat|nested] 227+ messages in thread
* Re: [PATCH 08/26] KVM: PPC: Add PV guest critical sections
2010-06-25 23:24 ` Alexander Graf
(?)
@ 2010-06-27 10:03 ` Avi Kivity
-1 siblings, 0 replies; 227+ messages in thread
From: Avi Kivity @ 2010-06-27 10:03 UTC (permalink / raw)
To: Alexander Graf; +Cc: kvm-ppc-u79uwXL29TY76Z2rM5mHXA, KVM list, linuxppc-dev
On 06/26/2010 02:24 AM, Alexander Graf wrote:
> When running in hooked code we need a way to disable interrupts without
> clobbering any interrupts or exiting out to the hypervisor.
>
> To achieve this, we have an additional critical field in the shared page. If
> that field is equal to the r1 register of the guest, it tells the hypervisor
> that we're in such a critical section and thus may not receive any interrupts.
>
>
> --- a/arch/powerpc/kvm/book3s.c
> +++ b/arch/powerpc/kvm/book3s.c
> @@ -251,14 +251,25 @@ int kvmppc_book3s_irqprio_deliver(struct kvm_vcpu *vcpu, unsigned int priority)
> int deliver = 1;
> int vec = 0;
> ulong flags = 0ULL;
> + ulong crit_raw = vcpu->arch.shared->critical;
> + ulong crit_r1 = kvmppc_get_gpr(vcpu, 1);
> + bool crit;
> +
> + /* Truncate crit indicators in 32 bit mode */
> + if (!(vcpu->arch.shared->msr& MSR_SF)) {
> + crit_raw&= 0xffffffff;
> + crit_r1&= 0xffffffff;
> + }
> +
> + crit = (crit_raw = crit_r1);
>
I think you need to qualify that for supervisor mode only. Otherwise
guest userspace can guess the value of shared->critical and disable
interrupts.
--
error compiling committee.c: too many arguments to function
^ permalink raw reply [flat|nested] 227+ messages in thread* Re: [PATCH 08/26] KVM: PPC: Add PV guest critical sections
@ 2010-06-27 10:03 ` Avi Kivity
0 siblings, 0 replies; 227+ messages in thread
From: Avi Kivity @ 2010-06-27 10:03 UTC (permalink / raw)
To: Alexander Graf; +Cc: kvm-ppc-u79uwXL29TY76Z2rM5mHXA, KVM list, linuxppc-dev
On 06/26/2010 02:24 AM, Alexander Graf wrote:
> When running in hooked code we need a way to disable interrupts without
> clobbering any interrupts or exiting out to the hypervisor.
>
> To achieve this, we have an additional critical field in the shared page. If
> that field is equal to the r1 register of the guest, it tells the hypervisor
> that we're in such a critical section and thus may not receive any interrupts.
>
>
> --- a/arch/powerpc/kvm/book3s.c
> +++ b/arch/powerpc/kvm/book3s.c
> @@ -251,14 +251,25 @@ int kvmppc_book3s_irqprio_deliver(struct kvm_vcpu *vcpu, unsigned int priority)
> int deliver = 1;
> int vec = 0;
> ulong flags = 0ULL;
> + ulong crit_raw = vcpu->arch.shared->critical;
> + ulong crit_r1 = kvmppc_get_gpr(vcpu, 1);
> + bool crit;
> +
> + /* Truncate crit indicators in 32 bit mode */
> + if (!(vcpu->arch.shared->msr& MSR_SF)) {
> + crit_raw&= 0xffffffff;
> + crit_r1&= 0xffffffff;
> + }
> +
> + crit = (crit_raw == crit_r1);
>
I think you need to qualify that for supervisor mode only. Otherwise
guest userspace can guess the value of shared->critical and disable
interrupts.
--
error compiling committee.c: too many arguments to function
^ permalink raw reply [flat|nested] 227+ messages in thread* Re: [PATCH 08/26] KVM: PPC: Add PV guest critical sections
@ 2010-06-27 10:03 ` Avi Kivity
0 siblings, 0 replies; 227+ messages in thread
From: Avi Kivity @ 2010-06-27 10:03 UTC (permalink / raw)
To: Alexander Graf; +Cc: linuxppc-dev, KVM list, kvm-ppc
On 06/26/2010 02:24 AM, Alexander Graf wrote:
> When running in hooked code we need a way to disable interrupts without
> clobbering any interrupts or exiting out to the hypervisor.
>
> To achieve this, we have an additional critical field in the shared page. If
> that field is equal to the r1 register of the guest, it tells the hypervisor
> that we're in such a critical section and thus may not receive any interrupts.
>
>
> --- a/arch/powerpc/kvm/book3s.c
> +++ b/arch/powerpc/kvm/book3s.c
> @@ -251,14 +251,25 @@ int kvmppc_book3s_irqprio_deliver(struct kvm_vcpu *vcpu, unsigned int priority)
> int deliver = 1;
> int vec = 0;
> ulong flags = 0ULL;
> + ulong crit_raw = vcpu->arch.shared->critical;
> + ulong crit_r1 = kvmppc_get_gpr(vcpu, 1);
> + bool crit;
> +
> + /* Truncate crit indicators in 32 bit mode */
> + if (!(vcpu->arch.shared->msr& MSR_SF)) {
> + crit_raw&= 0xffffffff;
> + crit_r1&= 0xffffffff;
> + }
> +
> + crit = (crit_raw == crit_r1);
>
I think you need to qualify that for supervisor mode only. Otherwise
guest userspace can guess the value of shared->critical and disable
interrupts.
--
error compiling committee.c: too many arguments to function
^ permalink raw reply [flat|nested] 227+ messages in thread[parent not found: <4C27220D.7090508-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>]
* Re: [PATCH 08/26] KVM: PPC: Add PV guest critical sections
2010-06-27 10:03 ` Avi Kivity
(?)
@ 2010-06-27 10:35 ` Alexander Graf
-1 siblings, 0 replies; 227+ messages in thread
From: Alexander Graf @ 2010-06-27 10:35 UTC (permalink / raw)
To: Avi Kivity
Cc: kvm-ppc-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, KVM list,
linuxppc-dev
Am 27.06.2010 um 12:03 schrieb Avi Kivity <avi@redhat.com>:
> On 06/26/2010 02:24 AM, Alexander Graf wrote:
>> When running in hooked code we need a way to disable interrupts
>> without
>> clobbering any interrupts or exiting out to the hypervisor.
>>
>> To achieve this, we have an additional critical field in the shared
>> page. If
>> that field is equal to the r1 register of the guest, it tells the
>> hypervisor
>> that we're in such a critical section and thus may not receive any
>> interrupts.
>>
>>
>> --- a/arch/powerpc/kvm/book3s.c
>> +++ b/arch/powerpc/kvm/book3s.c
>> @@ -251,14 +251,25 @@ int kvmppc_book3s_irqprio_deliver(struct
>> kvm_vcpu *vcpu, unsigned int priority)
>> int deliver = 1;
>> int vec = 0;
>> ulong flags = 0ULL;
>> + ulong crit_raw = vcpu->arch.shared->critical;
>> + ulong crit_r1 = kvmppc_get_gpr(vcpu, 1);
>> + bool crit;
>> +
>> + /* Truncate crit indicators in 32 bit mode */
>> + if (!(vcpu->arch.shared->msr& MSR_SF)) {
>> + crit_raw&= 0xffffffff;
>> + crit_r1&= 0xffffffff;
>> + }
>> +
>> + crit = (crit_raw = crit_r1);
>>
>
> I think you need to qualify that for supervisor mode only.
> Otherwise guest userspace can guess the value of shared->critical
> and disable interrupts.
Yes, you're right. Good catch!
Alex
>
^ permalink raw reply [flat|nested] 227+ messages in thread* Re: [PATCH 08/26] KVM: PPC: Add PV guest critical sections
@ 2010-06-27 10:35 ` Alexander Graf
0 siblings, 0 replies; 227+ messages in thread
From: Alexander Graf @ 2010-06-27 10:35 UTC (permalink / raw)
To: Avi Kivity
Cc: kvm-ppc-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, KVM list,
linuxppc-dev
Am 27.06.2010 um 12:03 schrieb Avi Kivity <avi-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>:
> On 06/26/2010 02:24 AM, Alexander Graf wrote:
>> When running in hooked code we need a way to disable interrupts
>> without
>> clobbering any interrupts or exiting out to the hypervisor.
>>
>> To achieve this, we have an additional critical field in the shared
>> page. If
>> that field is equal to the r1 register of the guest, it tells the
>> hypervisor
>> that we're in such a critical section and thus may not receive any
>> interrupts.
>>
>>
>> --- a/arch/powerpc/kvm/book3s.c
>> +++ b/arch/powerpc/kvm/book3s.c
>> @@ -251,14 +251,25 @@ int kvmppc_book3s_irqprio_deliver(struct
>> kvm_vcpu *vcpu, unsigned int priority)
>> int deliver = 1;
>> int vec = 0;
>> ulong flags = 0ULL;
>> + ulong crit_raw = vcpu->arch.shared->critical;
>> + ulong crit_r1 = kvmppc_get_gpr(vcpu, 1);
>> + bool crit;
>> +
>> + /* Truncate crit indicators in 32 bit mode */
>> + if (!(vcpu->arch.shared->msr& MSR_SF)) {
>> + crit_raw&= 0xffffffff;
>> + crit_r1&= 0xffffffff;
>> + }
>> +
>> + crit = (crit_raw == crit_r1);
>>
>
> I think you need to qualify that for supervisor mode only.
> Otherwise guest userspace can guess the value of shared->critical
> and disable interrupts.
Yes, you're right. Good catch!
Alex
>
^ permalink raw reply [flat|nested] 227+ messages in thread* Re: [PATCH 08/26] KVM: PPC: Add PV guest critical sections
@ 2010-06-27 10:35 ` Alexander Graf
0 siblings, 0 replies; 227+ messages in thread
From: Alexander Graf @ 2010-06-27 10:35 UTC (permalink / raw)
To: Avi Kivity; +Cc: linuxppc-dev, KVM list, kvm-ppc@vger.kernel.org
Am 27.06.2010 um 12:03 schrieb Avi Kivity <avi@redhat.com>:
> On 06/26/2010 02:24 AM, Alexander Graf wrote:
>> When running in hooked code we need a way to disable interrupts
>> without
>> clobbering any interrupts or exiting out to the hypervisor.
>>
>> To achieve this, we have an additional critical field in the shared
>> page. If
>> that field is equal to the r1 register of the guest, it tells the
>> hypervisor
>> that we're in such a critical section and thus may not receive any
>> interrupts.
>>
>>
>> --- a/arch/powerpc/kvm/book3s.c
>> +++ b/arch/powerpc/kvm/book3s.c
>> @@ -251,14 +251,25 @@ int kvmppc_book3s_irqprio_deliver(struct
>> kvm_vcpu *vcpu, unsigned int priority)
>> int deliver = 1;
>> int vec = 0;
>> ulong flags = 0ULL;
>> + ulong crit_raw = vcpu->arch.shared->critical;
>> + ulong crit_r1 = kvmppc_get_gpr(vcpu, 1);
>> + bool crit;
>> +
>> + /* Truncate crit indicators in 32 bit mode */
>> + if (!(vcpu->arch.shared->msr& MSR_SF)) {
>> + crit_raw&= 0xffffffff;
>> + crit_r1&= 0xffffffff;
>> + }
>> +
>> + crit = (crit_raw == crit_r1);
>>
>
> I think you need to qualify that for supervisor mode only.
> Otherwise guest userspace can guess the value of shared->critical
> and disable interrupts.
Yes, you're right. Good catch!
Alex
>
^ permalink raw reply [flat|nested] 227+ messages in thread
* [PATCH 13/26] KVM: PPC: Magic Page Book3s support
2010-06-25 23:24 ` Alexander Graf
(?)
@ 2010-06-25 23:25 ` Alexander Graf
-1 siblings, 0 replies; 227+ messages in thread
From: Alexander Graf @ 2010-06-25 23:25 UTC (permalink / raw)
To: kvm-ppc-u79uwXL29TY76Z2rM5mHXA; +Cc: KVM list, linuxppc-dev
We need to override EA as well as PA lookups for the magic page. When the guest
tells us to project it, the magic page overrides any guest mappings.
In order to reflect that, we need to hook into all the MMU layers of KVM to
force map the magic page if necessary.
Signed-off-by: Alexander Graf <agraf@suse.de>
---
arch/powerpc/kvm/book3s.c | 7 +++++++
arch/powerpc/kvm/book3s_32_mmu.c | 16 ++++++++++++++++
arch/powerpc/kvm/book3s_32_mmu_host.c | 12 ++++++++++++
arch/powerpc/kvm/book3s_64_mmu.c | 30 +++++++++++++++++++++++++++++-
arch/powerpc/kvm/book3s_64_mmu_host.c | 12 ++++++++++++
5 files changed, 76 insertions(+), 1 deletions(-)
diff --git a/arch/powerpc/kvm/book3s.c b/arch/powerpc/kvm/book3s.c
index 2f55aa5..6ce7fa1 100644
--- a/arch/powerpc/kvm/book3s.c
+++ b/arch/powerpc/kvm/book3s.c
@@ -551,6 +551,13 @@ mmio:
static int kvmppc_visible_gfn(struct kvm_vcpu *vcpu, gfn_t gfn)
{
+ ulong mp_pa = vcpu->arch.magic_page_pa;
+
+ if (unlikely(mp_pa) &&
+ unlikely((mp_pa & KVM_RMO) >> PAGE_SHIFT = gfn)) {
+ return 1;
+ }
+
return kvm_is_visible_gfn(vcpu->kvm, gfn);
}
diff --git a/arch/powerpc/kvm/book3s_32_mmu.c b/arch/powerpc/kvm/book3s_32_mmu.c
index 41130c8..d2bd1a6 100644
--- a/arch/powerpc/kvm/book3s_32_mmu.c
+++ b/arch/powerpc/kvm/book3s_32_mmu.c
@@ -281,8 +281,24 @@ static int kvmppc_mmu_book3s_32_xlate(struct kvm_vcpu *vcpu, gva_t eaddr,
struct kvmppc_pte *pte, bool data)
{
int r;
+ ulong mp_ea = vcpu->arch.magic_page_ea;
pte->eaddr = eaddr;
+
+ /* Magic page override */
+ if (unlikely(mp_ea) &&
+ unlikely((eaddr & ~0xfffULL) = (mp_ea & ~0xfffULL)) &&
+ !(vcpu->arch.shared->msr & MSR_PR)) {
+ pte->vpage = kvmppc_mmu_book3s_32_ea_to_vp(vcpu, eaddr, data);
+ pte->raddr = vcpu->arch.magic_page_pa | (pte->raddr & 0xfff);
+ pte->raddr &= KVM_RMO;
+ pte->may_execute = true;
+ pte->may_read = true;
+ pte->may_write = true;
+
+ return 0;
+ }
+
r = kvmppc_mmu_book3s_32_xlate_bat(vcpu, eaddr, pte, data);
if (r < 0)
r = kvmppc_mmu_book3s_32_xlate_pte(vcpu, eaddr, pte, data, true);
diff --git a/arch/powerpc/kvm/book3s_32_mmu_host.c b/arch/powerpc/kvm/book3s_32_mmu_host.c
index 67b8c38..658d3e0 100644
--- a/arch/powerpc/kvm/book3s_32_mmu_host.c
+++ b/arch/powerpc/kvm/book3s_32_mmu_host.c
@@ -145,6 +145,16 @@ int kvmppc_mmu_map_page(struct kvm_vcpu *vcpu, struct kvmppc_pte *orig_pte)
bool primary = false;
bool evict = false;
struct hpte_cache *pte;
+ ulong mp_pa = vcpu->arch.magic_page_pa;
+
+ /* Magic page override */
+ if (unlikely(mp_pa) &&
+ unlikely((orig_pte->raddr & ~0xfffUL & KVM_RMO) =
+ (mp_pa & ~0xfffUL & KVM_RMO))) {
+ hpaddr = (pfn_t)virt_to_phys(vcpu->arch.shared);
+ get_page(pfn_to_page(hpaddr >> PAGE_SHIFT));
+ goto mapped;
+ }
/* Get host physical address for gpa */
hpaddr = gfn_to_pfn(vcpu->kvm, orig_pte->raddr >> PAGE_SHIFT);
@@ -155,6 +165,8 @@ int kvmppc_mmu_map_page(struct kvm_vcpu *vcpu, struct kvmppc_pte *orig_pte)
}
hpaddr <<= PAGE_SHIFT;
+mapped:
+
/* and write the mapping ea -> hpa into the pt */
vcpu->arch.mmu.esid_to_vsid(vcpu, orig_pte->eaddr >> SID_SHIFT, &vsid);
map = find_sid_vsid(vcpu, vsid);
diff --git a/arch/powerpc/kvm/book3s_64_mmu.c b/arch/powerpc/kvm/book3s_64_mmu.c
index 58aa840..4a2e5fc 100644
--- a/arch/powerpc/kvm/book3s_64_mmu.c
+++ b/arch/powerpc/kvm/book3s_64_mmu.c
@@ -163,6 +163,22 @@ static int kvmppc_mmu_book3s_64_xlate(struct kvm_vcpu *vcpu, gva_t eaddr,
bool found = false;
bool perm_err = false;
int second = 0;
+ ulong mp_ea = vcpu->arch.magic_page_ea;
+
+ /* Magic page override */
+ if (unlikely(mp_ea) &&
+ unlikely((eaddr & ~0xfffULL) = (mp_ea & ~0xfffULL)) &&
+ !(vcpu->arch.shared->msr & MSR_PR)) {
+ gpte->eaddr = eaddr;
+ gpte->vpage = kvmppc_mmu_book3s_64_ea_to_vp(vcpu, eaddr, data);
+ gpte->raddr = vcpu->arch.magic_page_pa | (gpte->raddr & 0xfff);
+ gpte->raddr &= KVM_RMO;
+ gpte->may_execute = true;
+ gpte->may_read = true;
+ gpte->may_write = true;
+
+ return 0;
+ }
slbe = kvmppc_mmu_book3s_64_find_slbe(vcpu_book3s, eaddr);
if (!slbe)
@@ -445,6 +461,7 @@ static int kvmppc_mmu_book3s_64_esid_to_vsid(struct kvm_vcpu *vcpu, ulong esid,
ulong ea = esid << SID_SHIFT;
struct kvmppc_slb *slb;
u64 gvsid = esid;
+ ulong mp_ea = vcpu->arch.magic_page_ea;
if (vcpu->arch.shared->msr & (MSR_DR|MSR_IR)) {
slb = kvmppc_mmu_book3s_64_find_slbe(to_book3s(vcpu), ea);
@@ -464,7 +481,7 @@ static int kvmppc_mmu_book3s_64_esid_to_vsid(struct kvm_vcpu *vcpu, ulong esid,
break;
case MSR_DR|MSR_IR:
if (!slb)
- return -ENOENT;
+ goto no_slb;
*vsid = gvsid;
break;
@@ -477,6 +494,17 @@ static int kvmppc_mmu_book3s_64_esid_to_vsid(struct kvm_vcpu *vcpu, ulong esid,
*vsid |= VSID_PR;
return 0;
+
+no_slb:
+ /* Catch magic page case */
+ if (unlikely(mp_ea) &&
+ unlikely(esid = (mp_ea >> SID_SHIFT)) &&
+ !(vcpu->arch.shared->msr & MSR_PR)) {
+ *vsid = VSID_REAL | esid;
+ return 0;
+ }
+
+ return -EINVAL;
}
static bool kvmppc_mmu_book3s_64_is_dcbz32(struct kvm_vcpu *vcpu)
diff --git a/arch/powerpc/kvm/book3s_64_mmu_host.c b/arch/powerpc/kvm/book3s_64_mmu_host.c
index 71c1f90..d880c88 100644
--- a/arch/powerpc/kvm/book3s_64_mmu_host.c
+++ b/arch/powerpc/kvm/book3s_64_mmu_host.c
@@ -99,6 +99,16 @@ int kvmppc_mmu_map_page(struct kvm_vcpu *vcpu, struct kvmppc_pte *orig_pte)
int vflags = 0;
int attempt = 0;
struct kvmppc_sid_map *map;
+ ulong mp_pa = vcpu->arch.magic_page_pa;
+
+ /* Magic page override */
+ if (unlikely(mp_pa) &&
+ unlikely((orig_pte->raddr & ~0xfffULL & KVM_RMO) =
+ (mp_pa & ~0xfffULL & KVM_RMO))) {
+ hpaddr = (pfn_t)virt_to_phys(vcpu->arch.shared);
+ get_page(pfn_to_page(hpaddr >> PAGE_SHIFT));
+ goto mapped;
+ }
/* Get host physical address for gpa */
hpaddr = gfn_to_pfn(vcpu->kvm, orig_pte->raddr >> PAGE_SHIFT);
@@ -114,6 +124,8 @@ int kvmppc_mmu_map_page(struct kvm_vcpu *vcpu, struct kvmppc_pte *orig_pte)
#error Unknown page size
#endif
+mapped:
+
/* and write the mapping ea -> hpa into the pt */
vcpu->arch.mmu.esid_to_vsid(vcpu, orig_pte->eaddr >> SID_SHIFT, &vsid);
map = find_sid_vsid(vcpu, vsid);
--
1.6.0.2
^ permalink raw reply related [flat|nested] 227+ messages in thread* [PATCH 13/26] KVM: PPC: Magic Page Book3s support
@ 2010-06-25 23:25 ` Alexander Graf
0 siblings, 0 replies; 227+ messages in thread
From: Alexander Graf @ 2010-06-25 23:25 UTC (permalink / raw)
To: kvm-ppc-u79uwXL29TY76Z2rM5mHXA; +Cc: KVM list, linuxppc-dev
We need to override EA as well as PA lookups for the magic page. When the guest
tells us to project it, the magic page overrides any guest mappings.
In order to reflect that, we need to hook into all the MMU layers of KVM to
force map the magic page if necessary.
Signed-off-by: Alexander Graf <agraf-l3A5Bk7waGM@public.gmane.org>
---
arch/powerpc/kvm/book3s.c | 7 +++++++
arch/powerpc/kvm/book3s_32_mmu.c | 16 ++++++++++++++++
arch/powerpc/kvm/book3s_32_mmu_host.c | 12 ++++++++++++
arch/powerpc/kvm/book3s_64_mmu.c | 30 +++++++++++++++++++++++++++++-
arch/powerpc/kvm/book3s_64_mmu_host.c | 12 ++++++++++++
5 files changed, 76 insertions(+), 1 deletions(-)
diff --git a/arch/powerpc/kvm/book3s.c b/arch/powerpc/kvm/book3s.c
index 2f55aa5..6ce7fa1 100644
--- a/arch/powerpc/kvm/book3s.c
+++ b/arch/powerpc/kvm/book3s.c
@@ -551,6 +551,13 @@ mmio:
static int kvmppc_visible_gfn(struct kvm_vcpu *vcpu, gfn_t gfn)
{
+ ulong mp_pa = vcpu->arch.magic_page_pa;
+
+ if (unlikely(mp_pa) &&
+ unlikely((mp_pa & KVM_RMO) >> PAGE_SHIFT == gfn)) {
+ return 1;
+ }
+
return kvm_is_visible_gfn(vcpu->kvm, gfn);
}
diff --git a/arch/powerpc/kvm/book3s_32_mmu.c b/arch/powerpc/kvm/book3s_32_mmu.c
index 41130c8..d2bd1a6 100644
--- a/arch/powerpc/kvm/book3s_32_mmu.c
+++ b/arch/powerpc/kvm/book3s_32_mmu.c
@@ -281,8 +281,24 @@ static int kvmppc_mmu_book3s_32_xlate(struct kvm_vcpu *vcpu, gva_t eaddr,
struct kvmppc_pte *pte, bool data)
{
int r;
+ ulong mp_ea = vcpu->arch.magic_page_ea;
pte->eaddr = eaddr;
+
+ /* Magic page override */
+ if (unlikely(mp_ea) &&
+ unlikely((eaddr & ~0xfffULL) == (mp_ea & ~0xfffULL)) &&
+ !(vcpu->arch.shared->msr & MSR_PR)) {
+ pte->vpage = kvmppc_mmu_book3s_32_ea_to_vp(vcpu, eaddr, data);
+ pte->raddr = vcpu->arch.magic_page_pa | (pte->raddr & 0xfff);
+ pte->raddr &= KVM_RMO;
+ pte->may_execute = true;
+ pte->may_read = true;
+ pte->may_write = true;
+
+ return 0;
+ }
+
r = kvmppc_mmu_book3s_32_xlate_bat(vcpu, eaddr, pte, data);
if (r < 0)
r = kvmppc_mmu_book3s_32_xlate_pte(vcpu, eaddr, pte, data, true);
diff --git a/arch/powerpc/kvm/book3s_32_mmu_host.c b/arch/powerpc/kvm/book3s_32_mmu_host.c
index 67b8c38..658d3e0 100644
--- a/arch/powerpc/kvm/book3s_32_mmu_host.c
+++ b/arch/powerpc/kvm/book3s_32_mmu_host.c
@@ -145,6 +145,16 @@ int kvmppc_mmu_map_page(struct kvm_vcpu *vcpu, struct kvmppc_pte *orig_pte)
bool primary = false;
bool evict = false;
struct hpte_cache *pte;
+ ulong mp_pa = vcpu->arch.magic_page_pa;
+
+ /* Magic page override */
+ if (unlikely(mp_pa) &&
+ unlikely((orig_pte->raddr & ~0xfffUL & KVM_RMO) ==
+ (mp_pa & ~0xfffUL & KVM_RMO))) {
+ hpaddr = (pfn_t)virt_to_phys(vcpu->arch.shared);
+ get_page(pfn_to_page(hpaddr >> PAGE_SHIFT));
+ goto mapped;
+ }
/* Get host physical address for gpa */
hpaddr = gfn_to_pfn(vcpu->kvm, orig_pte->raddr >> PAGE_SHIFT);
@@ -155,6 +165,8 @@ int kvmppc_mmu_map_page(struct kvm_vcpu *vcpu, struct kvmppc_pte *orig_pte)
}
hpaddr <<= PAGE_SHIFT;
+mapped:
+
/* and write the mapping ea -> hpa into the pt */
vcpu->arch.mmu.esid_to_vsid(vcpu, orig_pte->eaddr >> SID_SHIFT, &vsid);
map = find_sid_vsid(vcpu, vsid);
diff --git a/arch/powerpc/kvm/book3s_64_mmu.c b/arch/powerpc/kvm/book3s_64_mmu.c
index 58aa840..4a2e5fc 100644
--- a/arch/powerpc/kvm/book3s_64_mmu.c
+++ b/arch/powerpc/kvm/book3s_64_mmu.c
@@ -163,6 +163,22 @@ static int kvmppc_mmu_book3s_64_xlate(struct kvm_vcpu *vcpu, gva_t eaddr,
bool found = false;
bool perm_err = false;
int second = 0;
+ ulong mp_ea = vcpu->arch.magic_page_ea;
+
+ /* Magic page override */
+ if (unlikely(mp_ea) &&
+ unlikely((eaddr & ~0xfffULL) == (mp_ea & ~0xfffULL)) &&
+ !(vcpu->arch.shared->msr & MSR_PR)) {
+ gpte->eaddr = eaddr;
+ gpte->vpage = kvmppc_mmu_book3s_64_ea_to_vp(vcpu, eaddr, data);
+ gpte->raddr = vcpu->arch.magic_page_pa | (gpte->raddr & 0xfff);
+ gpte->raddr &= KVM_RMO;
+ gpte->may_execute = true;
+ gpte->may_read = true;
+ gpte->may_write = true;
+
+ return 0;
+ }
slbe = kvmppc_mmu_book3s_64_find_slbe(vcpu_book3s, eaddr);
if (!slbe)
@@ -445,6 +461,7 @@ static int kvmppc_mmu_book3s_64_esid_to_vsid(struct kvm_vcpu *vcpu, ulong esid,
ulong ea = esid << SID_SHIFT;
struct kvmppc_slb *slb;
u64 gvsid = esid;
+ ulong mp_ea = vcpu->arch.magic_page_ea;
if (vcpu->arch.shared->msr & (MSR_DR|MSR_IR)) {
slb = kvmppc_mmu_book3s_64_find_slbe(to_book3s(vcpu), ea);
@@ -464,7 +481,7 @@ static int kvmppc_mmu_book3s_64_esid_to_vsid(struct kvm_vcpu *vcpu, ulong esid,
break;
case MSR_DR|MSR_IR:
if (!slb)
- return -ENOENT;
+ goto no_slb;
*vsid = gvsid;
break;
@@ -477,6 +494,17 @@ static int kvmppc_mmu_book3s_64_esid_to_vsid(struct kvm_vcpu *vcpu, ulong esid,
*vsid |= VSID_PR;
return 0;
+
+no_slb:
+ /* Catch magic page case */
+ if (unlikely(mp_ea) &&
+ unlikely(esid == (mp_ea >> SID_SHIFT)) &&
+ !(vcpu->arch.shared->msr & MSR_PR)) {
+ *vsid = VSID_REAL | esid;
+ return 0;
+ }
+
+ return -EINVAL;
}
static bool kvmppc_mmu_book3s_64_is_dcbz32(struct kvm_vcpu *vcpu)
diff --git a/arch/powerpc/kvm/book3s_64_mmu_host.c b/arch/powerpc/kvm/book3s_64_mmu_host.c
index 71c1f90..d880c88 100644
--- a/arch/powerpc/kvm/book3s_64_mmu_host.c
+++ b/arch/powerpc/kvm/book3s_64_mmu_host.c
@@ -99,6 +99,16 @@ int kvmppc_mmu_map_page(struct kvm_vcpu *vcpu, struct kvmppc_pte *orig_pte)
int vflags = 0;
int attempt = 0;
struct kvmppc_sid_map *map;
+ ulong mp_pa = vcpu->arch.magic_page_pa;
+
+ /* Magic page override */
+ if (unlikely(mp_pa) &&
+ unlikely((orig_pte->raddr & ~0xfffULL & KVM_RMO) ==
+ (mp_pa & ~0xfffULL & KVM_RMO))) {
+ hpaddr = (pfn_t)virt_to_phys(vcpu->arch.shared);
+ get_page(pfn_to_page(hpaddr >> PAGE_SHIFT));
+ goto mapped;
+ }
/* Get host physical address for gpa */
hpaddr = gfn_to_pfn(vcpu->kvm, orig_pte->raddr >> PAGE_SHIFT);
@@ -114,6 +124,8 @@ int kvmppc_mmu_map_page(struct kvm_vcpu *vcpu, struct kvmppc_pte *orig_pte)
#error Unknown page size
#endif
+mapped:
+
/* and write the mapping ea -> hpa into the pt */
vcpu->arch.mmu.esid_to_vsid(vcpu, orig_pte->eaddr >> SID_SHIFT, &vsid);
map = find_sid_vsid(vcpu, vsid);
--
1.6.0.2
^ permalink raw reply related [flat|nested] 227+ messages in thread* [PATCH 13/26] KVM: PPC: Magic Page Book3s support
@ 2010-06-25 23:25 ` Alexander Graf
0 siblings, 0 replies; 227+ messages in thread
From: Alexander Graf @ 2010-06-25 23:25 UTC (permalink / raw)
To: kvm-ppc; +Cc: linuxppc-dev, KVM list
We need to override EA as well as PA lookups for the magic page. When the guest
tells us to project it, the magic page overrides any guest mappings.
In order to reflect that, we need to hook into all the MMU layers of KVM to
force map the magic page if necessary.
Signed-off-by: Alexander Graf <agraf@suse.de>
---
arch/powerpc/kvm/book3s.c | 7 +++++++
arch/powerpc/kvm/book3s_32_mmu.c | 16 ++++++++++++++++
arch/powerpc/kvm/book3s_32_mmu_host.c | 12 ++++++++++++
arch/powerpc/kvm/book3s_64_mmu.c | 30 +++++++++++++++++++++++++++++-
arch/powerpc/kvm/book3s_64_mmu_host.c | 12 ++++++++++++
5 files changed, 76 insertions(+), 1 deletions(-)
diff --git a/arch/powerpc/kvm/book3s.c b/arch/powerpc/kvm/book3s.c
index 2f55aa5..6ce7fa1 100644
--- a/arch/powerpc/kvm/book3s.c
+++ b/arch/powerpc/kvm/book3s.c
@@ -551,6 +551,13 @@ mmio:
static int kvmppc_visible_gfn(struct kvm_vcpu *vcpu, gfn_t gfn)
{
+ ulong mp_pa = vcpu->arch.magic_page_pa;
+
+ if (unlikely(mp_pa) &&
+ unlikely((mp_pa & KVM_RMO) >> PAGE_SHIFT == gfn)) {
+ return 1;
+ }
+
return kvm_is_visible_gfn(vcpu->kvm, gfn);
}
diff --git a/arch/powerpc/kvm/book3s_32_mmu.c b/arch/powerpc/kvm/book3s_32_mmu.c
index 41130c8..d2bd1a6 100644
--- a/arch/powerpc/kvm/book3s_32_mmu.c
+++ b/arch/powerpc/kvm/book3s_32_mmu.c
@@ -281,8 +281,24 @@ static int kvmppc_mmu_book3s_32_xlate(struct kvm_vcpu *vcpu, gva_t eaddr,
struct kvmppc_pte *pte, bool data)
{
int r;
+ ulong mp_ea = vcpu->arch.magic_page_ea;
pte->eaddr = eaddr;
+
+ /* Magic page override */
+ if (unlikely(mp_ea) &&
+ unlikely((eaddr & ~0xfffULL) == (mp_ea & ~0xfffULL)) &&
+ !(vcpu->arch.shared->msr & MSR_PR)) {
+ pte->vpage = kvmppc_mmu_book3s_32_ea_to_vp(vcpu, eaddr, data);
+ pte->raddr = vcpu->arch.magic_page_pa | (pte->raddr & 0xfff);
+ pte->raddr &= KVM_RMO;
+ pte->may_execute = true;
+ pte->may_read = true;
+ pte->may_write = true;
+
+ return 0;
+ }
+
r = kvmppc_mmu_book3s_32_xlate_bat(vcpu, eaddr, pte, data);
if (r < 0)
r = kvmppc_mmu_book3s_32_xlate_pte(vcpu, eaddr, pte, data, true);
diff --git a/arch/powerpc/kvm/book3s_32_mmu_host.c b/arch/powerpc/kvm/book3s_32_mmu_host.c
index 67b8c38..658d3e0 100644
--- a/arch/powerpc/kvm/book3s_32_mmu_host.c
+++ b/arch/powerpc/kvm/book3s_32_mmu_host.c
@@ -145,6 +145,16 @@ int kvmppc_mmu_map_page(struct kvm_vcpu *vcpu, struct kvmppc_pte *orig_pte)
bool primary = false;
bool evict = false;
struct hpte_cache *pte;
+ ulong mp_pa = vcpu->arch.magic_page_pa;
+
+ /* Magic page override */
+ if (unlikely(mp_pa) &&
+ unlikely((orig_pte->raddr & ~0xfffUL & KVM_RMO) ==
+ (mp_pa & ~0xfffUL & KVM_RMO))) {
+ hpaddr = (pfn_t)virt_to_phys(vcpu->arch.shared);
+ get_page(pfn_to_page(hpaddr >> PAGE_SHIFT));
+ goto mapped;
+ }
/* Get host physical address for gpa */
hpaddr = gfn_to_pfn(vcpu->kvm, orig_pte->raddr >> PAGE_SHIFT);
@@ -155,6 +165,8 @@ int kvmppc_mmu_map_page(struct kvm_vcpu *vcpu, struct kvmppc_pte *orig_pte)
}
hpaddr <<= PAGE_SHIFT;
+mapped:
+
/* and write the mapping ea -> hpa into the pt */
vcpu->arch.mmu.esid_to_vsid(vcpu, orig_pte->eaddr >> SID_SHIFT, &vsid);
map = find_sid_vsid(vcpu, vsid);
diff --git a/arch/powerpc/kvm/book3s_64_mmu.c b/arch/powerpc/kvm/book3s_64_mmu.c
index 58aa840..4a2e5fc 100644
--- a/arch/powerpc/kvm/book3s_64_mmu.c
+++ b/arch/powerpc/kvm/book3s_64_mmu.c
@@ -163,6 +163,22 @@ static int kvmppc_mmu_book3s_64_xlate(struct kvm_vcpu *vcpu, gva_t eaddr,
bool found = false;
bool perm_err = false;
int second = 0;
+ ulong mp_ea = vcpu->arch.magic_page_ea;
+
+ /* Magic page override */
+ if (unlikely(mp_ea) &&
+ unlikely((eaddr & ~0xfffULL) == (mp_ea & ~0xfffULL)) &&
+ !(vcpu->arch.shared->msr & MSR_PR)) {
+ gpte->eaddr = eaddr;
+ gpte->vpage = kvmppc_mmu_book3s_64_ea_to_vp(vcpu, eaddr, data);
+ gpte->raddr = vcpu->arch.magic_page_pa | (gpte->raddr & 0xfff);
+ gpte->raddr &= KVM_RMO;
+ gpte->may_execute = true;
+ gpte->may_read = true;
+ gpte->may_write = true;
+
+ return 0;
+ }
slbe = kvmppc_mmu_book3s_64_find_slbe(vcpu_book3s, eaddr);
if (!slbe)
@@ -445,6 +461,7 @@ static int kvmppc_mmu_book3s_64_esid_to_vsid(struct kvm_vcpu *vcpu, ulong esid,
ulong ea = esid << SID_SHIFT;
struct kvmppc_slb *slb;
u64 gvsid = esid;
+ ulong mp_ea = vcpu->arch.magic_page_ea;
if (vcpu->arch.shared->msr & (MSR_DR|MSR_IR)) {
slb = kvmppc_mmu_book3s_64_find_slbe(to_book3s(vcpu), ea);
@@ -464,7 +481,7 @@ static int kvmppc_mmu_book3s_64_esid_to_vsid(struct kvm_vcpu *vcpu, ulong esid,
break;
case MSR_DR|MSR_IR:
if (!slb)
- return -ENOENT;
+ goto no_slb;
*vsid = gvsid;
break;
@@ -477,6 +494,17 @@ static int kvmppc_mmu_book3s_64_esid_to_vsid(struct kvm_vcpu *vcpu, ulong esid,
*vsid |= VSID_PR;
return 0;
+
+no_slb:
+ /* Catch magic page case */
+ if (unlikely(mp_ea) &&
+ unlikely(esid == (mp_ea >> SID_SHIFT)) &&
+ !(vcpu->arch.shared->msr & MSR_PR)) {
+ *vsid = VSID_REAL | esid;
+ return 0;
+ }
+
+ return -EINVAL;
}
static bool kvmppc_mmu_book3s_64_is_dcbz32(struct kvm_vcpu *vcpu)
diff --git a/arch/powerpc/kvm/book3s_64_mmu_host.c b/arch/powerpc/kvm/book3s_64_mmu_host.c
index 71c1f90..d880c88 100644
--- a/arch/powerpc/kvm/book3s_64_mmu_host.c
+++ b/arch/powerpc/kvm/book3s_64_mmu_host.c
@@ -99,6 +99,16 @@ int kvmppc_mmu_map_page(struct kvm_vcpu *vcpu, struct kvmppc_pte *orig_pte)
int vflags = 0;
int attempt = 0;
struct kvmppc_sid_map *map;
+ ulong mp_pa = vcpu->arch.magic_page_pa;
+
+ /* Magic page override */
+ if (unlikely(mp_pa) &&
+ unlikely((orig_pte->raddr & ~0xfffULL & KVM_RMO) ==
+ (mp_pa & ~0xfffULL & KVM_RMO))) {
+ hpaddr = (pfn_t)virt_to_phys(vcpu->arch.shared);
+ get_page(pfn_to_page(hpaddr >> PAGE_SHIFT));
+ goto mapped;
+ }
/* Get host physical address for gpa */
hpaddr = gfn_to_pfn(vcpu->kvm, orig_pte->raddr >> PAGE_SHIFT);
@@ -114,6 +124,8 @@ int kvmppc_mmu_map_page(struct kvm_vcpu *vcpu, struct kvmppc_pte *orig_pte)
#error Unknown page size
#endif
+mapped:
+
/* and write the mapping ea -> hpa into the pt */
vcpu->arch.mmu.esid_to_vsid(vcpu, orig_pte->eaddr >> SID_SHIFT, &vsid);
map = find_sid_vsid(vcpu, vsid);
--
1.6.0.2
^ permalink raw reply related [flat|nested] 227+ messages in thread
* [PATCH 14/26] KVM: PPC: Magic Page BookE support
2010-06-25 23:24 ` Alexander Graf
(?)
@ 2010-06-25 23:25 ` Alexander Graf
-1 siblings, 0 replies; 227+ messages in thread
From: Alexander Graf @ 2010-06-25 23:25 UTC (permalink / raw)
To: kvm-ppc-u79uwXL29TY76Z2rM5mHXA; +Cc: KVM list, linuxppc-dev
As we now have Book3s support for the magic page, we also need BookE to
join in on the party.
This patch implements generic magic page logic for BookE and specific
TLB logic for e500. I didn't have any 440 around, so I didn't dare to
blindly try and write up broken code.
Signed-off-by: Alexander Graf <agraf@suse.de>
---
arch/powerpc/kvm/booke.c | 29 +++++++++++++++++++++++++++++
arch/powerpc/kvm/e500_tlb.c | 19 +++++++++++++++++--
2 files changed, 46 insertions(+), 2 deletions(-)
diff --git a/arch/powerpc/kvm/booke.c b/arch/powerpc/kvm/booke.c
index 2229df9..7957aa4 100644
--- a/arch/powerpc/kvm/booke.c
+++ b/arch/powerpc/kvm/booke.c
@@ -241,6 +241,31 @@ void kvmppc_core_deliver_interrupts(struct kvm_vcpu *vcpu)
vcpu->arch.shared->int_pending = 0;
}
+/* Check if a DTLB miss was on the magic page. Returns !0 if so. */
+int kvmppc_dtlb_magic_page(struct kvm_vcpu *vcpu, ulong eaddr)
+{
+ ulong mp_ea = vcpu->arch.magic_page_ea;
+ ulong gpaddr = vcpu->arch.magic_page_pa;
+ int gtlb_index = 11 | (1 << 16); /* Random number in TLB1 */
+
+ /* Check for existence of magic page */
+ if(likely(!mp_ea))
+ return 0;
+
+ /* Check if we're on the magic page */
+ if(likely((eaddr >> 12) != (mp_ea >> 12)))
+ return 0;
+
+ /* Don't map in user mode */
+ if(vcpu->arch.shared->msr & MSR_PR)
+ return 0;
+
+ kvmppc_mmu_map(vcpu, vcpu->arch.magic_page_ea, gpaddr, gtlb_index);
+ kvmppc_account_exit(vcpu, DTLB_VIRT_MISS_EXITS);
+
+ return 1;
+}
+
/**
* kvmppc_handle_exit
*
@@ -308,6 +333,7 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
r = RESUME_HOST;
break;
case EMULATE_FAIL:
+ case EMULATE_DO_MMIO:
/* XXX Deliver Program interrupt to guest. */
printk(KERN_CRIT "%s: emulation at %lx failed (%08x)\n",
__func__, vcpu->arch.pc, vcpu->arch.last_inst);
@@ -377,6 +403,9 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
gpa_t gpaddr;
gfn_t gfn;
+ if (kvmppc_dtlb_magic_page(vcpu, eaddr))
+ break;
+
/* Check the guest TLB. */
gtlb_index = kvmppc_mmu_dtlb_index(vcpu, eaddr);
if (gtlb_index < 0) {
diff --git a/arch/powerpc/kvm/e500_tlb.c b/arch/powerpc/kvm/e500_tlb.c
index 66845a5..f5582ca 100644
--- a/arch/powerpc/kvm/e500_tlb.c
+++ b/arch/powerpc/kvm/e500_tlb.c
@@ -295,9 +295,22 @@ static inline void kvmppc_e500_shadow_map(struct kvmppc_vcpu_e500 *vcpu_e500,
struct page *new_page;
struct tlbe *stlbe;
hpa_t hpaddr;
+ u32 mas2 = gtlbe->mas2;
+ u32 mas3 = gtlbe->mas3;
stlbe = &vcpu_e500->shadow_tlb[tlbsel][esel];
+ if ((vcpu_e500->vcpu.arch.magic_page_ea) &&
+ ((vcpu_e500->vcpu.arch.magic_page_pa >> PAGE_SHIFT) = gfn) &&
+ !(vcpu_e500->vcpu.arch.shared->msr & MSR_PR)) {
+ mas2 = 0;
+ mas3 = E500_TLB_SUPER_PERM_MASK;
+ hpaddr = virt_to_phys(vcpu_e500->vcpu.arch.shared);
+ new_page = pfn_to_page(hpaddr >> PAGE_SHIFT);
+ get_page(new_page);
+ goto mapped;
+ }
+
/* Get reference to new page. */
new_page = gfn_to_page(vcpu_e500->vcpu.kvm, gfn);
if (is_error_page(new_page)) {
@@ -305,6 +318,8 @@ static inline void kvmppc_e500_shadow_map(struct kvmppc_vcpu_e500 *vcpu_e500,
kvm_release_page_clean(new_page);
return;
}
+
+mapped:
hpaddr = page_to_phys(new_page);
/* Drop reference to old page. */
@@ -316,10 +331,10 @@ static inline void kvmppc_e500_shadow_map(struct kvmppc_vcpu_e500 *vcpu_e500,
stlbe->mas1 = MAS1_TSIZE(BOOK3E_PAGESZ_4K)
| MAS1_TID(get_tlb_tid(gtlbe)) | MAS1_TS | MAS1_VALID;
stlbe->mas2 = (gvaddr & MAS2_EPN)
- | e500_shadow_mas2_attrib(gtlbe->mas2,
+ | e500_shadow_mas2_attrib(mas2,
vcpu_e500->vcpu.arch.shared->msr & MSR_PR);
stlbe->mas3 = (hpaddr & MAS3_RPN)
- | e500_shadow_mas3_attrib(gtlbe->mas3,
+ | e500_shadow_mas3_attrib(mas3,
vcpu_e500->vcpu.arch.shared->msr & MSR_PR);
stlbe->mas7 = (hpaddr >> 32) & MAS7_RPN;
--
1.6.0.2
^ permalink raw reply related [flat|nested] 227+ messages in thread* [PATCH 14/26] KVM: PPC: Magic Page BookE support
@ 2010-06-25 23:25 ` Alexander Graf
0 siblings, 0 replies; 227+ messages in thread
From: Alexander Graf @ 2010-06-25 23:25 UTC (permalink / raw)
To: kvm-ppc-u79uwXL29TY76Z2rM5mHXA; +Cc: KVM list, linuxppc-dev
As we now have Book3s support for the magic page, we also need BookE to
join in on the party.
This patch implements generic magic page logic for BookE and specific
TLB logic for e500. I didn't have any 440 around, so I didn't dare to
blindly try and write up broken code.
Signed-off-by: Alexander Graf <agraf-l3A5Bk7waGM@public.gmane.org>
---
arch/powerpc/kvm/booke.c | 29 +++++++++++++++++++++++++++++
arch/powerpc/kvm/e500_tlb.c | 19 +++++++++++++++++--
2 files changed, 46 insertions(+), 2 deletions(-)
diff --git a/arch/powerpc/kvm/booke.c b/arch/powerpc/kvm/booke.c
index 2229df9..7957aa4 100644
--- a/arch/powerpc/kvm/booke.c
+++ b/arch/powerpc/kvm/booke.c
@@ -241,6 +241,31 @@ void kvmppc_core_deliver_interrupts(struct kvm_vcpu *vcpu)
vcpu->arch.shared->int_pending = 0;
}
+/* Check if a DTLB miss was on the magic page. Returns !0 if so. */
+int kvmppc_dtlb_magic_page(struct kvm_vcpu *vcpu, ulong eaddr)
+{
+ ulong mp_ea = vcpu->arch.magic_page_ea;
+ ulong gpaddr = vcpu->arch.magic_page_pa;
+ int gtlb_index = 11 | (1 << 16); /* Random number in TLB1 */
+
+ /* Check for existence of magic page */
+ if(likely(!mp_ea))
+ return 0;
+
+ /* Check if we're on the magic page */
+ if(likely((eaddr >> 12) != (mp_ea >> 12)))
+ return 0;
+
+ /* Don't map in user mode */
+ if(vcpu->arch.shared->msr & MSR_PR)
+ return 0;
+
+ kvmppc_mmu_map(vcpu, vcpu->arch.magic_page_ea, gpaddr, gtlb_index);
+ kvmppc_account_exit(vcpu, DTLB_VIRT_MISS_EXITS);
+
+ return 1;
+}
+
/**
* kvmppc_handle_exit
*
@@ -308,6 +333,7 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
r = RESUME_HOST;
break;
case EMULATE_FAIL:
+ case EMULATE_DO_MMIO:
/* XXX Deliver Program interrupt to guest. */
printk(KERN_CRIT "%s: emulation at %lx failed (%08x)\n",
__func__, vcpu->arch.pc, vcpu->arch.last_inst);
@@ -377,6 +403,9 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
gpa_t gpaddr;
gfn_t gfn;
+ if (kvmppc_dtlb_magic_page(vcpu, eaddr))
+ break;
+
/* Check the guest TLB. */
gtlb_index = kvmppc_mmu_dtlb_index(vcpu, eaddr);
if (gtlb_index < 0) {
diff --git a/arch/powerpc/kvm/e500_tlb.c b/arch/powerpc/kvm/e500_tlb.c
index 66845a5..f5582ca 100644
--- a/arch/powerpc/kvm/e500_tlb.c
+++ b/arch/powerpc/kvm/e500_tlb.c
@@ -295,9 +295,22 @@ static inline void kvmppc_e500_shadow_map(struct kvmppc_vcpu_e500 *vcpu_e500,
struct page *new_page;
struct tlbe *stlbe;
hpa_t hpaddr;
+ u32 mas2 = gtlbe->mas2;
+ u32 mas3 = gtlbe->mas3;
stlbe = &vcpu_e500->shadow_tlb[tlbsel][esel];
+ if ((vcpu_e500->vcpu.arch.magic_page_ea) &&
+ ((vcpu_e500->vcpu.arch.magic_page_pa >> PAGE_SHIFT) == gfn) &&
+ !(vcpu_e500->vcpu.arch.shared->msr & MSR_PR)) {
+ mas2 = 0;
+ mas3 = E500_TLB_SUPER_PERM_MASK;
+ hpaddr = virt_to_phys(vcpu_e500->vcpu.arch.shared);
+ new_page = pfn_to_page(hpaddr >> PAGE_SHIFT);
+ get_page(new_page);
+ goto mapped;
+ }
+
/* Get reference to new page. */
new_page = gfn_to_page(vcpu_e500->vcpu.kvm, gfn);
if (is_error_page(new_page)) {
@@ -305,6 +318,8 @@ static inline void kvmppc_e500_shadow_map(struct kvmppc_vcpu_e500 *vcpu_e500,
kvm_release_page_clean(new_page);
return;
}
+
+mapped:
hpaddr = page_to_phys(new_page);
/* Drop reference to old page. */
@@ -316,10 +331,10 @@ static inline void kvmppc_e500_shadow_map(struct kvmppc_vcpu_e500 *vcpu_e500,
stlbe->mas1 = MAS1_TSIZE(BOOK3E_PAGESZ_4K)
| MAS1_TID(get_tlb_tid(gtlbe)) | MAS1_TS | MAS1_VALID;
stlbe->mas2 = (gvaddr & MAS2_EPN)
- | e500_shadow_mas2_attrib(gtlbe->mas2,
+ | e500_shadow_mas2_attrib(mas2,
vcpu_e500->vcpu.arch.shared->msr & MSR_PR);
stlbe->mas3 = (hpaddr & MAS3_RPN)
- | e500_shadow_mas3_attrib(gtlbe->mas3,
+ | e500_shadow_mas3_attrib(mas3,
vcpu_e500->vcpu.arch.shared->msr & MSR_PR);
stlbe->mas7 = (hpaddr >> 32) & MAS7_RPN;
--
1.6.0.2
^ permalink raw reply related [flat|nested] 227+ messages in thread* [PATCH 14/26] KVM: PPC: Magic Page BookE support
@ 2010-06-25 23:25 ` Alexander Graf
0 siblings, 0 replies; 227+ messages in thread
From: Alexander Graf @ 2010-06-25 23:25 UTC (permalink / raw)
To: kvm-ppc; +Cc: linuxppc-dev, KVM list
As we now have Book3s support for the magic page, we also need BookE to
join in on the party.
This patch implements generic magic page logic for BookE and specific
TLB logic for e500. I didn't have any 440 around, so I didn't dare to
blindly try and write up broken code.
Signed-off-by: Alexander Graf <agraf@suse.de>
---
arch/powerpc/kvm/booke.c | 29 +++++++++++++++++++++++++++++
arch/powerpc/kvm/e500_tlb.c | 19 +++++++++++++++++--
2 files changed, 46 insertions(+), 2 deletions(-)
diff --git a/arch/powerpc/kvm/booke.c b/arch/powerpc/kvm/booke.c
index 2229df9..7957aa4 100644
--- a/arch/powerpc/kvm/booke.c
+++ b/arch/powerpc/kvm/booke.c
@@ -241,6 +241,31 @@ void kvmppc_core_deliver_interrupts(struct kvm_vcpu *vcpu)
vcpu->arch.shared->int_pending = 0;
}
+/* Check if a DTLB miss was on the magic page. Returns !0 if so. */
+int kvmppc_dtlb_magic_page(struct kvm_vcpu *vcpu, ulong eaddr)
+{
+ ulong mp_ea = vcpu->arch.magic_page_ea;
+ ulong gpaddr = vcpu->arch.magic_page_pa;
+ int gtlb_index = 11 | (1 << 16); /* Random number in TLB1 */
+
+ /* Check for existence of magic page */
+ if(likely(!mp_ea))
+ return 0;
+
+ /* Check if we're on the magic page */
+ if(likely((eaddr >> 12) != (mp_ea >> 12)))
+ return 0;
+
+ /* Don't map in user mode */
+ if(vcpu->arch.shared->msr & MSR_PR)
+ return 0;
+
+ kvmppc_mmu_map(vcpu, vcpu->arch.magic_page_ea, gpaddr, gtlb_index);
+ kvmppc_account_exit(vcpu, DTLB_VIRT_MISS_EXITS);
+
+ return 1;
+}
+
/**
* kvmppc_handle_exit
*
@@ -308,6 +333,7 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
r = RESUME_HOST;
break;
case EMULATE_FAIL:
+ case EMULATE_DO_MMIO:
/* XXX Deliver Program interrupt to guest. */
printk(KERN_CRIT "%s: emulation at %lx failed (%08x)\n",
__func__, vcpu->arch.pc, vcpu->arch.last_inst);
@@ -377,6 +403,9 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
gpa_t gpaddr;
gfn_t gfn;
+ if (kvmppc_dtlb_magic_page(vcpu, eaddr))
+ break;
+
/* Check the guest TLB. */
gtlb_index = kvmppc_mmu_dtlb_index(vcpu, eaddr);
if (gtlb_index < 0) {
diff --git a/arch/powerpc/kvm/e500_tlb.c b/arch/powerpc/kvm/e500_tlb.c
index 66845a5..f5582ca 100644
--- a/arch/powerpc/kvm/e500_tlb.c
+++ b/arch/powerpc/kvm/e500_tlb.c
@@ -295,9 +295,22 @@ static inline void kvmppc_e500_shadow_map(struct kvmppc_vcpu_e500 *vcpu_e500,
struct page *new_page;
struct tlbe *stlbe;
hpa_t hpaddr;
+ u32 mas2 = gtlbe->mas2;
+ u32 mas3 = gtlbe->mas3;
stlbe = &vcpu_e500->shadow_tlb[tlbsel][esel];
+ if ((vcpu_e500->vcpu.arch.magic_page_ea) &&
+ ((vcpu_e500->vcpu.arch.magic_page_pa >> PAGE_SHIFT) == gfn) &&
+ !(vcpu_e500->vcpu.arch.shared->msr & MSR_PR)) {
+ mas2 = 0;
+ mas3 = E500_TLB_SUPER_PERM_MASK;
+ hpaddr = virt_to_phys(vcpu_e500->vcpu.arch.shared);
+ new_page = pfn_to_page(hpaddr >> PAGE_SHIFT);
+ get_page(new_page);
+ goto mapped;
+ }
+
/* Get reference to new page. */
new_page = gfn_to_page(vcpu_e500->vcpu.kvm, gfn);
if (is_error_page(new_page)) {
@@ -305,6 +318,8 @@ static inline void kvmppc_e500_shadow_map(struct kvmppc_vcpu_e500 *vcpu_e500,
kvm_release_page_clean(new_page);
return;
}
+
+mapped:
hpaddr = page_to_phys(new_page);
/* Drop reference to old page. */
@@ -316,10 +331,10 @@ static inline void kvmppc_e500_shadow_map(struct kvmppc_vcpu_e500 *vcpu_e500,
stlbe->mas1 = MAS1_TSIZE(BOOK3E_PAGESZ_4K)
| MAS1_TID(get_tlb_tid(gtlbe)) | MAS1_TS | MAS1_VALID;
stlbe->mas2 = (gvaddr & MAS2_EPN)
- | e500_shadow_mas2_attrib(gtlbe->mas2,
+ | e500_shadow_mas2_attrib(mas2,
vcpu_e500->vcpu.arch.shared->msr & MSR_PR);
stlbe->mas3 = (hpaddr & MAS3_RPN)
- | e500_shadow_mas3_attrib(gtlbe->mas3,
+ | e500_shadow_mas3_attrib(mas3,
vcpu_e500->vcpu.arch.shared->msr & MSR_PR);
stlbe->mas7 = (hpaddr >> 32) & MAS7_RPN;
--
1.6.0.2
^ permalink raw reply related [flat|nested] 227+ messages in thread
* [PATCH 17/26] KVM: PPC: Generic KVM PV guest support
2010-06-25 23:24 ` Alexander Graf
(?)
@ 2010-06-25 23:25 ` Alexander Graf
-1 siblings, 0 replies; 227+ messages in thread
From: Alexander Graf @ 2010-06-25 23:25 UTC (permalink / raw)
To: kvm-ppc-u79uwXL29TY76Z2rM5mHXA; +Cc: KVM list, linuxppc-dev
We have all the hypervisor pieces in place now, but the guest parts are still
missing.
This patch implements basic awareness of KVM when running Linux as guest. It
doesn't do anything with it yet though.
Signed-off-by: Alexander Graf <agraf@suse.de>
---
arch/powerpc/kernel/Makefile | 2 ++
arch/powerpc/kernel/asm-offsets.c | 15 +++++++++++++++
arch/powerpc/kernel/kvm.c | 34 ++++++++++++++++++++++++++++++++++
arch/powerpc/kernel/kvm_emul.S | 27 +++++++++++++++++++++++++++
arch/powerpc/platforms/Kconfig | 10 ++++++++++
5 files changed, 88 insertions(+), 0 deletions(-)
create mode 100644 arch/powerpc/kernel/kvm.c
create mode 100644 arch/powerpc/kernel/kvm_emul.S
diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile
index 58d0572..2d7eb9e 100644
--- a/arch/powerpc/kernel/Makefile
+++ b/arch/powerpc/kernel/Makefile
@@ -125,6 +125,8 @@ ifneq ($(CONFIG_XMON)$(CONFIG_KEXEC),)
obj-y += ppc_save_regs.o
endif
+obj-$(CONFIG_KVM_GUEST) += kvm.o kvm_emul.o
+
# Disable GCOV in odd or sensitive code
GCOV_PROFILE_prom_init.o := n
GCOV_PROFILE_ftrace.o := n
diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c
index a55d47e..e3e740b 100644
--- a/arch/powerpc/kernel/asm-offsets.c
+++ b/arch/powerpc/kernel/asm-offsets.c
@@ -465,6 +465,21 @@ int main(void)
DEFINE(VCPU_FAULT_ESR, offsetof(struct kvm_vcpu, arch.fault_esr));
#endif /* CONFIG_PPC_BOOK3S */
#endif
+
+#ifdef CONFIG_KVM_GUEST
+ DEFINE(KVM_MAGIC_SCRATCH1, offsetof(struct kvm_vcpu_arch_shared,
+ scratch1));
+ DEFINE(KVM_MAGIC_SCRATCH2, offsetof(struct kvm_vcpu_arch_shared,
+ scratch2));
+ DEFINE(KVM_MAGIC_SCRATCH3, offsetof(struct kvm_vcpu_arch_shared,
+ scratch3));
+ DEFINE(KVM_MAGIC_INT, offsetof(struct kvm_vcpu_arch_shared,
+ int_pending));
+ DEFINE(KVM_MAGIC_MSR, offsetof(struct kvm_vcpu_arch_shared, msr));
+ DEFINE(KVM_MAGIC_CRITICAL, offsetof(struct kvm_vcpu_arch_shared,
+ critical));
+#endif
+
#ifdef CONFIG_44x
DEFINE(PGD_T_LOG2, PGD_T_LOG2);
DEFINE(PTE_T_LOG2, PTE_T_LOG2);
diff --git a/arch/powerpc/kernel/kvm.c b/arch/powerpc/kernel/kvm.c
new file mode 100644
index 0000000..2d8dd73
--- /dev/null
+++ b/arch/powerpc/kernel/kvm.c
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2010 SUSE Linux Products GmbH. All rights reserved.
+ *
+ * Authors:
+ * Alexander Graf <agraf@suse.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include <linux/kvm_host.h>
+#include <linux/init.h>
+#include <linux/kvm_para.h>
+#include <linux/slab.h>
+
+#include <asm/reg.h>
+#include <asm/kvm_ppc.h>
+#include <asm/sections.h>
+#include <asm/cacheflush.h>
+#include <asm/disassemble.h>
+
+#define KVM_MAGIC_PAGE (-4096L)
+#define magic_var(x) KVM_MAGIC_PAGE + offsetof(struct kvm_vcpu_arch_shared, x)
+
diff --git a/arch/powerpc/kernel/kvm_emul.S b/arch/powerpc/kernel/kvm_emul.S
new file mode 100644
index 0000000..c7b9fc9
--- /dev/null
+++ b/arch/powerpc/kernel/kvm_emul.S
@@ -0,0 +1,27 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Copyright SUSE Linux Products GmbH 2010
+ *
+ * Authors: Alexander Graf <agraf@suse.de>
+ */
+
+#include <asm/ppc_asm.h>
+#include <asm/kvm_asm.h>
+#include <asm/reg.h>
+#include <asm/page.h>
+#include <asm/asm-offsets.h>
+
+#define KVM_MAGIC_PAGE (-4096)
+
diff --git a/arch/powerpc/platforms/Kconfig b/arch/powerpc/platforms/Kconfig
index d1663db..1744349 100644
--- a/arch/powerpc/platforms/Kconfig
+++ b/arch/powerpc/platforms/Kconfig
@@ -21,6 +21,16 @@ source "arch/powerpc/platforms/44x/Kconfig"
source "arch/powerpc/platforms/40x/Kconfig"
source "arch/powerpc/platforms/amigaone/Kconfig"
+config KVM_GUEST
+ bool "KVM Guest support"
+ default y
+ ---help---
+ This option enables various optimizations for running under the KVM
+ hypervisor. Overhead for the kernel when not running inside KVM should
+ be minimal.
+
+ In case of doubt, say Y
+
config PPC_NATIVE
bool
depends on 6xx || PPC64
--
1.6.0.2
^ permalink raw reply related [flat|nested] 227+ messages in thread
* [PATCH 17/26] KVM: PPC: Generic KVM PV guest support
@ 2010-06-25 23:25 ` Alexander Graf
0 siblings, 0 replies; 227+ messages in thread
From: Alexander Graf @ 2010-06-25 23:25 UTC (permalink / raw)
To: kvm-ppc-u79uwXL29TY76Z2rM5mHXA; +Cc: KVM list, linuxppc-dev
We have all the hypervisor pieces in place now, but the guest parts are still
missing.
This patch implements basic awareness of KVM when running Linux as guest. It
doesn't do anything with it yet though.
Signed-off-by: Alexander Graf <agraf-l3A5Bk7waGM@public.gmane.org>
---
arch/powerpc/kernel/Makefile | 2 ++
arch/powerpc/kernel/asm-offsets.c | 15 +++++++++++++++
arch/powerpc/kernel/kvm.c | 34 ++++++++++++++++++++++++++++++++++
arch/powerpc/kernel/kvm_emul.S | 27 +++++++++++++++++++++++++++
arch/powerpc/platforms/Kconfig | 10 ++++++++++
5 files changed, 88 insertions(+), 0 deletions(-)
create mode 100644 arch/powerpc/kernel/kvm.c
create mode 100644 arch/powerpc/kernel/kvm_emul.S
diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile
index 58d0572..2d7eb9e 100644
--- a/arch/powerpc/kernel/Makefile
+++ b/arch/powerpc/kernel/Makefile
@@ -125,6 +125,8 @@ ifneq ($(CONFIG_XMON)$(CONFIG_KEXEC),)
obj-y += ppc_save_regs.o
endif
+obj-$(CONFIG_KVM_GUEST) += kvm.o kvm_emul.o
+
# Disable GCOV in odd or sensitive code
GCOV_PROFILE_prom_init.o := n
GCOV_PROFILE_ftrace.o := n
diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c
index a55d47e..e3e740b 100644
--- a/arch/powerpc/kernel/asm-offsets.c
+++ b/arch/powerpc/kernel/asm-offsets.c
@@ -465,6 +465,21 @@ int main(void)
DEFINE(VCPU_FAULT_ESR, offsetof(struct kvm_vcpu, arch.fault_esr));
#endif /* CONFIG_PPC_BOOK3S */
#endif
+
+#ifdef CONFIG_KVM_GUEST
+ DEFINE(KVM_MAGIC_SCRATCH1, offsetof(struct kvm_vcpu_arch_shared,
+ scratch1));
+ DEFINE(KVM_MAGIC_SCRATCH2, offsetof(struct kvm_vcpu_arch_shared,
+ scratch2));
+ DEFINE(KVM_MAGIC_SCRATCH3, offsetof(struct kvm_vcpu_arch_shared,
+ scratch3));
+ DEFINE(KVM_MAGIC_INT, offsetof(struct kvm_vcpu_arch_shared,
+ int_pending));
+ DEFINE(KVM_MAGIC_MSR, offsetof(struct kvm_vcpu_arch_shared, msr));
+ DEFINE(KVM_MAGIC_CRITICAL, offsetof(struct kvm_vcpu_arch_shared,
+ critical));
+#endif
+
#ifdef CONFIG_44x
DEFINE(PGD_T_LOG2, PGD_T_LOG2);
DEFINE(PTE_T_LOG2, PTE_T_LOG2);
diff --git a/arch/powerpc/kernel/kvm.c b/arch/powerpc/kernel/kvm.c
new file mode 100644
index 0000000..2d8dd73
--- /dev/null
+++ b/arch/powerpc/kernel/kvm.c
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2010 SUSE Linux Products GmbH. All rights reserved.
+ *
+ * Authors:
+ * Alexander Graf <agraf-l3A5Bk7waGM@public.gmane.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include <linux/kvm_host.h>
+#include <linux/init.h>
+#include <linux/kvm_para.h>
+#include <linux/slab.h>
+
+#include <asm/reg.h>
+#include <asm/kvm_ppc.h>
+#include <asm/sections.h>
+#include <asm/cacheflush.h>
+#include <asm/disassemble.h>
+
+#define KVM_MAGIC_PAGE (-4096L)
+#define magic_var(x) KVM_MAGIC_PAGE + offsetof(struct kvm_vcpu_arch_shared, x)
+
diff --git a/arch/powerpc/kernel/kvm_emul.S b/arch/powerpc/kernel/kvm_emul.S
new file mode 100644
index 0000000..c7b9fc9
--- /dev/null
+++ b/arch/powerpc/kernel/kvm_emul.S
@@ -0,0 +1,27 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Copyright SUSE Linux Products GmbH 2010
+ *
+ * Authors: Alexander Graf <agraf-l3A5Bk7waGM@public.gmane.org>
+ */
+
+#include <asm/ppc_asm.h>
+#include <asm/kvm_asm.h>
+#include <asm/reg.h>
+#include <asm/page.h>
+#include <asm/asm-offsets.h>
+
+#define KVM_MAGIC_PAGE (-4096)
+
diff --git a/arch/powerpc/platforms/Kconfig b/arch/powerpc/platforms/Kconfig
index d1663db..1744349 100644
--- a/arch/powerpc/platforms/Kconfig
+++ b/arch/powerpc/platforms/Kconfig
@@ -21,6 +21,16 @@ source "arch/powerpc/platforms/44x/Kconfig"
source "arch/powerpc/platforms/40x/Kconfig"
source "arch/powerpc/platforms/amigaone/Kconfig"
+config KVM_GUEST
+ bool "KVM Guest support"
+ default y
+ ---help---
+ This option enables various optimizations for running under the KVM
+ hypervisor. Overhead for the kernel when not running inside KVM should
+ be minimal.
+
+ In case of doubt, say Y
+
config PPC_NATIVE
bool
depends on 6xx || PPC64
--
1.6.0.2
^ permalink raw reply related [flat|nested] 227+ messages in thread
* [PATCH 17/26] KVM: PPC: Generic KVM PV guest support
@ 2010-06-25 23:25 ` Alexander Graf
0 siblings, 0 replies; 227+ messages in thread
From: Alexander Graf @ 2010-06-25 23:25 UTC (permalink / raw)
To: kvm-ppc; +Cc: linuxppc-dev, KVM list
We have all the hypervisor pieces in place now, but the guest parts are still
missing.
This patch implements basic awareness of KVM when running Linux as guest. It
doesn't do anything with it yet though.
Signed-off-by: Alexander Graf <agraf@suse.de>
---
arch/powerpc/kernel/Makefile | 2 ++
arch/powerpc/kernel/asm-offsets.c | 15 +++++++++++++++
arch/powerpc/kernel/kvm.c | 34 ++++++++++++++++++++++++++++++++++
arch/powerpc/kernel/kvm_emul.S | 27 +++++++++++++++++++++++++++
arch/powerpc/platforms/Kconfig | 10 ++++++++++
5 files changed, 88 insertions(+), 0 deletions(-)
create mode 100644 arch/powerpc/kernel/kvm.c
create mode 100644 arch/powerpc/kernel/kvm_emul.S
diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile
index 58d0572..2d7eb9e 100644
--- a/arch/powerpc/kernel/Makefile
+++ b/arch/powerpc/kernel/Makefile
@@ -125,6 +125,8 @@ ifneq ($(CONFIG_XMON)$(CONFIG_KEXEC),)
obj-y += ppc_save_regs.o
endif
+obj-$(CONFIG_KVM_GUEST) += kvm.o kvm_emul.o
+
# Disable GCOV in odd or sensitive code
GCOV_PROFILE_prom_init.o := n
GCOV_PROFILE_ftrace.o := n
diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c
index a55d47e..e3e740b 100644
--- a/arch/powerpc/kernel/asm-offsets.c
+++ b/arch/powerpc/kernel/asm-offsets.c
@@ -465,6 +465,21 @@ int main(void)
DEFINE(VCPU_FAULT_ESR, offsetof(struct kvm_vcpu, arch.fault_esr));
#endif /* CONFIG_PPC_BOOK3S */
#endif
+
+#ifdef CONFIG_KVM_GUEST
+ DEFINE(KVM_MAGIC_SCRATCH1, offsetof(struct kvm_vcpu_arch_shared,
+ scratch1));
+ DEFINE(KVM_MAGIC_SCRATCH2, offsetof(struct kvm_vcpu_arch_shared,
+ scratch2));
+ DEFINE(KVM_MAGIC_SCRATCH3, offsetof(struct kvm_vcpu_arch_shared,
+ scratch3));
+ DEFINE(KVM_MAGIC_INT, offsetof(struct kvm_vcpu_arch_shared,
+ int_pending));
+ DEFINE(KVM_MAGIC_MSR, offsetof(struct kvm_vcpu_arch_shared, msr));
+ DEFINE(KVM_MAGIC_CRITICAL, offsetof(struct kvm_vcpu_arch_shared,
+ critical));
+#endif
+
#ifdef CONFIG_44x
DEFINE(PGD_T_LOG2, PGD_T_LOG2);
DEFINE(PTE_T_LOG2, PTE_T_LOG2);
diff --git a/arch/powerpc/kernel/kvm.c b/arch/powerpc/kernel/kvm.c
new file mode 100644
index 0000000..2d8dd73
--- /dev/null
+++ b/arch/powerpc/kernel/kvm.c
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2010 SUSE Linux Products GmbH. All rights reserved.
+ *
+ * Authors:
+ * Alexander Graf <agraf@suse.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include <linux/kvm_host.h>
+#include <linux/init.h>
+#include <linux/kvm_para.h>
+#include <linux/slab.h>
+
+#include <asm/reg.h>
+#include <asm/kvm_ppc.h>
+#include <asm/sections.h>
+#include <asm/cacheflush.h>
+#include <asm/disassemble.h>
+
+#define KVM_MAGIC_PAGE (-4096L)
+#define magic_var(x) KVM_MAGIC_PAGE + offsetof(struct kvm_vcpu_arch_shared, x)
+
diff --git a/arch/powerpc/kernel/kvm_emul.S b/arch/powerpc/kernel/kvm_emul.S
new file mode 100644
index 0000000..c7b9fc9
--- /dev/null
+++ b/arch/powerpc/kernel/kvm_emul.S
@@ -0,0 +1,27 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Copyright SUSE Linux Products GmbH 2010
+ *
+ * Authors: Alexander Graf <agraf@suse.de>
+ */
+
+#include <asm/ppc_asm.h>
+#include <asm/kvm_asm.h>
+#include <asm/reg.h>
+#include <asm/page.h>
+#include <asm/asm-offsets.h>
+
+#define KVM_MAGIC_PAGE (-4096)
+
diff --git a/arch/powerpc/platforms/Kconfig b/arch/powerpc/platforms/Kconfig
index d1663db..1744349 100644
--- a/arch/powerpc/platforms/Kconfig
+++ b/arch/powerpc/platforms/Kconfig
@@ -21,6 +21,16 @@ source "arch/powerpc/platforms/44x/Kconfig"
source "arch/powerpc/platforms/40x/Kconfig"
source "arch/powerpc/platforms/amigaone/Kconfig"
+config KVM_GUEST
+ bool "KVM Guest support"
+ default y
+ ---help---
+ This option enables various optimizations for running under the KVM
+ hypervisor. Overhead for the kernel when not running inside KVM should
+ be minimal.
+
+ In case of doubt, say Y
+
config PPC_NATIVE
bool
depends on 6xx || PPC64
--
1.6.0.2
^ permalink raw reply related [flat|nested] 227+ messages in thread
* [PATCH 19/26] KVM: PPC: PV instructions to loads and stores
2010-06-25 23:24 ` Alexander Graf
(?)
@ 2010-06-25 23:25 ` Alexander Graf
-1 siblings, 0 replies; 227+ messages in thread
From: Alexander Graf @ 2010-06-25 23:25 UTC (permalink / raw)
To: kvm-ppc-u79uwXL29TY76Z2rM5mHXA; +Cc: KVM list, linuxppc-dev
Some instructions can simply be replaced by load and store instructions to
or from the magic page.
This patch replaces often called instructions that fall into the above category.
Signed-off-by: Alexander Graf <agraf@suse.de>
---
arch/powerpc/kernel/kvm.c | 111 +++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 111 insertions(+), 0 deletions(-)
diff --git a/arch/powerpc/kernel/kvm.c b/arch/powerpc/kernel/kvm.c
index d873bc6..b165b20 100644
--- a/arch/powerpc/kernel/kvm.c
+++ b/arch/powerpc/kernel/kvm.c
@@ -32,8 +32,65 @@
#define KVM_MAGIC_PAGE (-4096L)
#define magic_var(x) KVM_MAGIC_PAGE + offsetof(struct kvm_vcpu_arch_shared, x)
+#define KVM_INST_LWZ 0x80000000
+#define KVM_INST_STW 0x90000000
+#define KVM_INST_LD 0xe8000000
+#define KVM_INST_STD 0xf8000000
+#define KVM_INST_NOP 0x60000000
+#define KVM_INST_B 0x48000000
+#define KVM_INST_B_MASK 0x03ffffff
+#define KVM_INST_B_MAX 0x01ffffff
+
+#define KVM_MASK_RT 0x03e00000
+#define KVM_INST_MFMSR 0x7c0000a6
+#define KVM_INST_MFSPR_SPRG0 0x7c1042a6
+#define KVM_INST_MFSPR_SPRG1 0x7c1142a6
+#define KVM_INST_MFSPR_SPRG2 0x7c1242a6
+#define KVM_INST_MFSPR_SPRG3 0x7c1342a6
+#define KVM_INST_MFSPR_SRR0 0x7c1a02a6
+#define KVM_INST_MFSPR_SRR1 0x7c1b02a6
+#define KVM_INST_MFSPR_DAR 0x7c1302a6
+#define KVM_INST_MFSPR_DSISR 0x7c1202a6
+
+#define KVM_INST_MTSPR_SPRG0 0x7c1043a6
+#define KVM_INST_MTSPR_SPRG1 0x7c1143a6
+#define KVM_INST_MTSPR_SPRG2 0x7c1243a6
+#define KVM_INST_MTSPR_SPRG3 0x7c1343a6
+#define KVM_INST_MTSPR_SRR0 0x7c1a03a6
+#define KVM_INST_MTSPR_SRR1 0x7c1b03a6
+#define KVM_INST_MTSPR_DAR 0x7c1303a6
+#define KVM_INST_MTSPR_DSISR 0x7c1203a6
+
static bool kvm_patching_worked = true;
+static void kvm_patch_ins_ld(u32 *inst, long addr, u32 rt)
+{
+#ifdef CONFIG_64BIT
+ *inst = KVM_INST_LD | rt | (addr & 0x0000fffc);
+#else
+ *inst = KVM_INST_LWZ | rt | ((addr + 4) & 0x0000fffc);
+#endif
+}
+
+static void kvm_patch_ins_lwz(u32 *inst, long addr, u32 rt)
+{
+ *inst = KVM_INST_LWZ | rt | (addr & 0x0000ffff);
+}
+
+static void kvm_patch_ins_std(u32 *inst, long addr, u32 rt)
+{
+#ifdef CONFIG_64BIT
+ *inst = KVM_INST_STD | rt | (addr & 0x0000fffc);
+#else
+ *inst = KVM_INST_STW | rt | ((addr + 4) & 0x0000fffc);
+#endif
+}
+
+static void kvm_patch_ins_stw(u32 *inst, long addr, u32 rt)
+{
+ *inst = KVM_INST_STW | rt | (addr & 0x0000fffc);
+}
+
static void kvm_map_magic_page(void *data)
{
kvm_hypercall2(KVM_HC_PPC_MAP_MAGIC_PAGE,
@@ -48,6 +105,60 @@ static void kvm_check_ins(u32 *inst)
u32 inst_rt = _inst & KVM_MASK_RT;
switch (inst_no_rt) {
+ /* Loads */
+ case KVM_INST_MFMSR:
+ kvm_patch_ins_ld(inst, magic_var(msr), inst_rt);
+ break;
+ case KVM_INST_MFSPR_SPRG0:
+ kvm_patch_ins_ld(inst, magic_var(sprg0), inst_rt);
+ break;
+ case KVM_INST_MFSPR_SPRG1:
+ kvm_patch_ins_ld(inst, magic_var(sprg1), inst_rt);
+ break;
+ case KVM_INST_MFSPR_SPRG2:
+ kvm_patch_ins_ld(inst, magic_var(sprg2), inst_rt);
+ break;
+ case KVM_INST_MFSPR_SPRG3:
+ kvm_patch_ins_ld(inst, magic_var(sprg3), inst_rt);
+ break;
+ case KVM_INST_MFSPR_SRR0:
+ kvm_patch_ins_ld(inst, magic_var(srr0), inst_rt);
+ break;
+ case KVM_INST_MFSPR_SRR1:
+ kvm_patch_ins_ld(inst, magic_var(srr1), inst_rt);
+ break;
+ case KVM_INST_MFSPR_DAR:
+ kvm_patch_ins_ld(inst, magic_var(dar), inst_rt);
+ break;
+ case KVM_INST_MFSPR_DSISR:
+ kvm_patch_ins_lwz(inst, magic_var(dsisr), inst_rt);
+ break;
+
+ /* Stores */
+ case KVM_INST_MTSPR_SPRG0:
+ kvm_patch_ins_std(inst, magic_var(sprg0), inst_rt);
+ break;
+ case KVM_INST_MTSPR_SPRG1:
+ kvm_patch_ins_std(inst, magic_var(sprg1), inst_rt);
+ break;
+ case KVM_INST_MTSPR_SPRG2:
+ kvm_patch_ins_std(inst, magic_var(sprg2), inst_rt);
+ break;
+ case KVM_INST_MTSPR_SPRG3:
+ kvm_patch_ins_std(inst, magic_var(sprg3), inst_rt);
+ break;
+ case KVM_INST_MTSPR_SRR0:
+ kvm_patch_ins_std(inst, magic_var(srr0), inst_rt);
+ break;
+ case KVM_INST_MTSPR_SRR1:
+ kvm_patch_ins_std(inst, magic_var(srr1), inst_rt);
+ break;
+ case KVM_INST_MTSPR_DAR:
+ kvm_patch_ins_std(inst, magic_var(dar), inst_rt);
+ break;
+ case KVM_INST_MTSPR_DSISR:
+ kvm_patch_ins_stw(inst, magic_var(dsisr), inst_rt);
+ break;
}
switch (_inst) {
--
1.6.0.2
^ permalink raw reply related [flat|nested] 227+ messages in thread* [PATCH 19/26] KVM: PPC: PV instructions to loads and stores
@ 2010-06-25 23:25 ` Alexander Graf
0 siblings, 0 replies; 227+ messages in thread
From: Alexander Graf @ 2010-06-25 23:25 UTC (permalink / raw)
To: kvm-ppc-u79uwXL29TY76Z2rM5mHXA; +Cc: KVM list, linuxppc-dev
Some instructions can simply be replaced by load and store instructions to
or from the magic page.
This patch replaces often called instructions that fall into the above category.
Signed-off-by: Alexander Graf <agraf-l3A5Bk7waGM@public.gmane.org>
---
arch/powerpc/kernel/kvm.c | 111 +++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 111 insertions(+), 0 deletions(-)
diff --git a/arch/powerpc/kernel/kvm.c b/arch/powerpc/kernel/kvm.c
index d873bc6..b165b20 100644
--- a/arch/powerpc/kernel/kvm.c
+++ b/arch/powerpc/kernel/kvm.c
@@ -32,8 +32,65 @@
#define KVM_MAGIC_PAGE (-4096L)
#define magic_var(x) KVM_MAGIC_PAGE + offsetof(struct kvm_vcpu_arch_shared, x)
+#define KVM_INST_LWZ 0x80000000
+#define KVM_INST_STW 0x90000000
+#define KVM_INST_LD 0xe8000000
+#define KVM_INST_STD 0xf8000000
+#define KVM_INST_NOP 0x60000000
+#define KVM_INST_B 0x48000000
+#define KVM_INST_B_MASK 0x03ffffff
+#define KVM_INST_B_MAX 0x01ffffff
+
+#define KVM_MASK_RT 0x03e00000
+#define KVM_INST_MFMSR 0x7c0000a6
+#define KVM_INST_MFSPR_SPRG0 0x7c1042a6
+#define KVM_INST_MFSPR_SPRG1 0x7c1142a6
+#define KVM_INST_MFSPR_SPRG2 0x7c1242a6
+#define KVM_INST_MFSPR_SPRG3 0x7c1342a6
+#define KVM_INST_MFSPR_SRR0 0x7c1a02a6
+#define KVM_INST_MFSPR_SRR1 0x7c1b02a6
+#define KVM_INST_MFSPR_DAR 0x7c1302a6
+#define KVM_INST_MFSPR_DSISR 0x7c1202a6
+
+#define KVM_INST_MTSPR_SPRG0 0x7c1043a6
+#define KVM_INST_MTSPR_SPRG1 0x7c1143a6
+#define KVM_INST_MTSPR_SPRG2 0x7c1243a6
+#define KVM_INST_MTSPR_SPRG3 0x7c1343a6
+#define KVM_INST_MTSPR_SRR0 0x7c1a03a6
+#define KVM_INST_MTSPR_SRR1 0x7c1b03a6
+#define KVM_INST_MTSPR_DAR 0x7c1303a6
+#define KVM_INST_MTSPR_DSISR 0x7c1203a6
+
static bool kvm_patching_worked = true;
+static void kvm_patch_ins_ld(u32 *inst, long addr, u32 rt)
+{
+#ifdef CONFIG_64BIT
+ *inst = KVM_INST_LD | rt | (addr & 0x0000fffc);
+#else
+ *inst = KVM_INST_LWZ | rt | ((addr + 4) & 0x0000fffc);
+#endif
+}
+
+static void kvm_patch_ins_lwz(u32 *inst, long addr, u32 rt)
+{
+ *inst = KVM_INST_LWZ | rt | (addr & 0x0000ffff);
+}
+
+static void kvm_patch_ins_std(u32 *inst, long addr, u32 rt)
+{
+#ifdef CONFIG_64BIT
+ *inst = KVM_INST_STD | rt | (addr & 0x0000fffc);
+#else
+ *inst = KVM_INST_STW | rt | ((addr + 4) & 0x0000fffc);
+#endif
+}
+
+static void kvm_patch_ins_stw(u32 *inst, long addr, u32 rt)
+{
+ *inst = KVM_INST_STW | rt | (addr & 0x0000fffc);
+}
+
static void kvm_map_magic_page(void *data)
{
kvm_hypercall2(KVM_HC_PPC_MAP_MAGIC_PAGE,
@@ -48,6 +105,60 @@ static void kvm_check_ins(u32 *inst)
u32 inst_rt = _inst & KVM_MASK_RT;
switch (inst_no_rt) {
+ /* Loads */
+ case KVM_INST_MFMSR:
+ kvm_patch_ins_ld(inst, magic_var(msr), inst_rt);
+ break;
+ case KVM_INST_MFSPR_SPRG0:
+ kvm_patch_ins_ld(inst, magic_var(sprg0), inst_rt);
+ break;
+ case KVM_INST_MFSPR_SPRG1:
+ kvm_patch_ins_ld(inst, magic_var(sprg1), inst_rt);
+ break;
+ case KVM_INST_MFSPR_SPRG2:
+ kvm_patch_ins_ld(inst, magic_var(sprg2), inst_rt);
+ break;
+ case KVM_INST_MFSPR_SPRG3:
+ kvm_patch_ins_ld(inst, magic_var(sprg3), inst_rt);
+ break;
+ case KVM_INST_MFSPR_SRR0:
+ kvm_patch_ins_ld(inst, magic_var(srr0), inst_rt);
+ break;
+ case KVM_INST_MFSPR_SRR1:
+ kvm_patch_ins_ld(inst, magic_var(srr1), inst_rt);
+ break;
+ case KVM_INST_MFSPR_DAR:
+ kvm_patch_ins_ld(inst, magic_var(dar), inst_rt);
+ break;
+ case KVM_INST_MFSPR_DSISR:
+ kvm_patch_ins_lwz(inst, magic_var(dsisr), inst_rt);
+ break;
+
+ /* Stores */
+ case KVM_INST_MTSPR_SPRG0:
+ kvm_patch_ins_std(inst, magic_var(sprg0), inst_rt);
+ break;
+ case KVM_INST_MTSPR_SPRG1:
+ kvm_patch_ins_std(inst, magic_var(sprg1), inst_rt);
+ break;
+ case KVM_INST_MTSPR_SPRG2:
+ kvm_patch_ins_std(inst, magic_var(sprg2), inst_rt);
+ break;
+ case KVM_INST_MTSPR_SPRG3:
+ kvm_patch_ins_std(inst, magic_var(sprg3), inst_rt);
+ break;
+ case KVM_INST_MTSPR_SRR0:
+ kvm_patch_ins_std(inst, magic_var(srr0), inst_rt);
+ break;
+ case KVM_INST_MTSPR_SRR1:
+ kvm_patch_ins_std(inst, magic_var(srr1), inst_rt);
+ break;
+ case KVM_INST_MTSPR_DAR:
+ kvm_patch_ins_std(inst, magic_var(dar), inst_rt);
+ break;
+ case KVM_INST_MTSPR_DSISR:
+ kvm_patch_ins_stw(inst, magic_var(dsisr), inst_rt);
+ break;
}
switch (_inst) {
--
1.6.0.2
^ permalink raw reply related [flat|nested] 227+ messages in thread* [PATCH 19/26] KVM: PPC: PV instructions to loads and stores
@ 2010-06-25 23:25 ` Alexander Graf
0 siblings, 0 replies; 227+ messages in thread
From: Alexander Graf @ 2010-06-25 23:25 UTC (permalink / raw)
To: kvm-ppc; +Cc: linuxppc-dev, KVM list
Some instructions can simply be replaced by load and store instructions to
or from the magic page.
This patch replaces often called instructions that fall into the above category.
Signed-off-by: Alexander Graf <agraf@suse.de>
---
arch/powerpc/kernel/kvm.c | 111 +++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 111 insertions(+), 0 deletions(-)
diff --git a/arch/powerpc/kernel/kvm.c b/arch/powerpc/kernel/kvm.c
index d873bc6..b165b20 100644
--- a/arch/powerpc/kernel/kvm.c
+++ b/arch/powerpc/kernel/kvm.c
@@ -32,8 +32,65 @@
#define KVM_MAGIC_PAGE (-4096L)
#define magic_var(x) KVM_MAGIC_PAGE + offsetof(struct kvm_vcpu_arch_shared, x)
+#define KVM_INST_LWZ 0x80000000
+#define KVM_INST_STW 0x90000000
+#define KVM_INST_LD 0xe8000000
+#define KVM_INST_STD 0xf8000000
+#define KVM_INST_NOP 0x60000000
+#define KVM_INST_B 0x48000000
+#define KVM_INST_B_MASK 0x03ffffff
+#define KVM_INST_B_MAX 0x01ffffff
+
+#define KVM_MASK_RT 0x03e00000
+#define KVM_INST_MFMSR 0x7c0000a6
+#define KVM_INST_MFSPR_SPRG0 0x7c1042a6
+#define KVM_INST_MFSPR_SPRG1 0x7c1142a6
+#define KVM_INST_MFSPR_SPRG2 0x7c1242a6
+#define KVM_INST_MFSPR_SPRG3 0x7c1342a6
+#define KVM_INST_MFSPR_SRR0 0x7c1a02a6
+#define KVM_INST_MFSPR_SRR1 0x7c1b02a6
+#define KVM_INST_MFSPR_DAR 0x7c1302a6
+#define KVM_INST_MFSPR_DSISR 0x7c1202a6
+
+#define KVM_INST_MTSPR_SPRG0 0x7c1043a6
+#define KVM_INST_MTSPR_SPRG1 0x7c1143a6
+#define KVM_INST_MTSPR_SPRG2 0x7c1243a6
+#define KVM_INST_MTSPR_SPRG3 0x7c1343a6
+#define KVM_INST_MTSPR_SRR0 0x7c1a03a6
+#define KVM_INST_MTSPR_SRR1 0x7c1b03a6
+#define KVM_INST_MTSPR_DAR 0x7c1303a6
+#define KVM_INST_MTSPR_DSISR 0x7c1203a6
+
static bool kvm_patching_worked = true;
+static void kvm_patch_ins_ld(u32 *inst, long addr, u32 rt)
+{
+#ifdef CONFIG_64BIT
+ *inst = KVM_INST_LD | rt | (addr & 0x0000fffc);
+#else
+ *inst = KVM_INST_LWZ | rt | ((addr + 4) & 0x0000fffc);
+#endif
+}
+
+static void kvm_patch_ins_lwz(u32 *inst, long addr, u32 rt)
+{
+ *inst = KVM_INST_LWZ | rt | (addr & 0x0000ffff);
+}
+
+static void kvm_patch_ins_std(u32 *inst, long addr, u32 rt)
+{
+#ifdef CONFIG_64BIT
+ *inst = KVM_INST_STD | rt | (addr & 0x0000fffc);
+#else
+ *inst = KVM_INST_STW | rt | ((addr + 4) & 0x0000fffc);
+#endif
+}
+
+static void kvm_patch_ins_stw(u32 *inst, long addr, u32 rt)
+{
+ *inst = KVM_INST_STW | rt | (addr & 0x0000fffc);
+}
+
static void kvm_map_magic_page(void *data)
{
kvm_hypercall2(KVM_HC_PPC_MAP_MAGIC_PAGE,
@@ -48,6 +105,60 @@ static void kvm_check_ins(u32 *inst)
u32 inst_rt = _inst & KVM_MASK_RT;
switch (inst_no_rt) {
+ /* Loads */
+ case KVM_INST_MFMSR:
+ kvm_patch_ins_ld(inst, magic_var(msr), inst_rt);
+ break;
+ case KVM_INST_MFSPR_SPRG0:
+ kvm_patch_ins_ld(inst, magic_var(sprg0), inst_rt);
+ break;
+ case KVM_INST_MFSPR_SPRG1:
+ kvm_patch_ins_ld(inst, magic_var(sprg1), inst_rt);
+ break;
+ case KVM_INST_MFSPR_SPRG2:
+ kvm_patch_ins_ld(inst, magic_var(sprg2), inst_rt);
+ break;
+ case KVM_INST_MFSPR_SPRG3:
+ kvm_patch_ins_ld(inst, magic_var(sprg3), inst_rt);
+ break;
+ case KVM_INST_MFSPR_SRR0:
+ kvm_patch_ins_ld(inst, magic_var(srr0), inst_rt);
+ break;
+ case KVM_INST_MFSPR_SRR1:
+ kvm_patch_ins_ld(inst, magic_var(srr1), inst_rt);
+ break;
+ case KVM_INST_MFSPR_DAR:
+ kvm_patch_ins_ld(inst, magic_var(dar), inst_rt);
+ break;
+ case KVM_INST_MFSPR_DSISR:
+ kvm_patch_ins_lwz(inst, magic_var(dsisr), inst_rt);
+ break;
+
+ /* Stores */
+ case KVM_INST_MTSPR_SPRG0:
+ kvm_patch_ins_std(inst, magic_var(sprg0), inst_rt);
+ break;
+ case KVM_INST_MTSPR_SPRG1:
+ kvm_patch_ins_std(inst, magic_var(sprg1), inst_rt);
+ break;
+ case KVM_INST_MTSPR_SPRG2:
+ kvm_patch_ins_std(inst, magic_var(sprg2), inst_rt);
+ break;
+ case KVM_INST_MTSPR_SPRG3:
+ kvm_patch_ins_std(inst, magic_var(sprg3), inst_rt);
+ break;
+ case KVM_INST_MTSPR_SRR0:
+ kvm_patch_ins_std(inst, magic_var(srr0), inst_rt);
+ break;
+ case KVM_INST_MTSPR_SRR1:
+ kvm_patch_ins_std(inst, magic_var(srr1), inst_rt);
+ break;
+ case KVM_INST_MTSPR_DAR:
+ kvm_patch_ins_std(inst, magic_var(dar), inst_rt);
+ break;
+ case KVM_INST_MTSPR_DSISR:
+ kvm_patch_ins_stw(inst, magic_var(dsisr), inst_rt);
+ break;
}
switch (_inst) {
--
1.6.0.2
^ permalink raw reply related [flat|nested] 227+ messages in thread
* [PATCH 20/26] KVM: PPC: PV tlbsync to nop
2010-06-25 23:24 ` Alexander Graf
(?)
@ 2010-06-25 23:25 ` Alexander Graf
-1 siblings, 0 replies; 227+ messages in thread
From: Alexander Graf @ 2010-06-25 23:25 UTC (permalink / raw)
To: kvm-ppc-u79uwXL29TY76Z2rM5mHXA; +Cc: KVM list, linuxppc-dev
With our current MMU scheme we don't need to know about the tlbsync instruction.
So we can just nop it out.
Signed-off-by: Alexander Graf <agraf@suse.de>
---
arch/powerpc/kernel/kvm.c | 12 ++++++++++++
1 files changed, 12 insertions(+), 0 deletions(-)
diff --git a/arch/powerpc/kernel/kvm.c b/arch/powerpc/kernel/kvm.c
index b165b20..b091f94 100644
--- a/arch/powerpc/kernel/kvm.c
+++ b/arch/powerpc/kernel/kvm.c
@@ -61,6 +61,8 @@
#define KVM_INST_MTSPR_DAR 0x7c1303a6
#define KVM_INST_MTSPR_DSISR 0x7c1203a6
+#define KVM_INST_TLBSYNC 0x7c00046c
+
static bool kvm_patching_worked = true;
static void kvm_patch_ins_ld(u32 *inst, long addr, u32 rt)
@@ -91,6 +93,11 @@ static void kvm_patch_ins_stw(u32 *inst, long addr, u32 rt)
*inst = KVM_INST_STW | rt | (addr & 0x0000fffc);
}
+static void kvm_patch_ins_nop(u32 *inst)
+{
+ *inst = KVM_INST_NOP;
+}
+
static void kvm_map_magic_page(void *data)
{
kvm_hypercall2(KVM_HC_PPC_MAP_MAGIC_PAGE,
@@ -159,6 +166,11 @@ static void kvm_check_ins(u32 *inst)
case KVM_INST_MTSPR_DSISR:
kvm_patch_ins_stw(inst, magic_var(dsisr), inst_rt);
break;
+
+ /* Nops */
+ case KVM_INST_TLBSYNC:
+ kvm_patch_ins_nop(inst);
+ break;
}
switch (_inst) {
--
1.6.0.2
^ permalink raw reply related [flat|nested] 227+ messages in thread* [PATCH 20/26] KVM: PPC: PV tlbsync to nop
@ 2010-06-25 23:25 ` Alexander Graf
0 siblings, 0 replies; 227+ messages in thread
From: Alexander Graf @ 2010-06-25 23:25 UTC (permalink / raw)
To: kvm-ppc-u79uwXL29TY76Z2rM5mHXA; +Cc: KVM list, linuxppc-dev
With our current MMU scheme we don't need to know about the tlbsync instruction.
So we can just nop it out.
Signed-off-by: Alexander Graf <agraf-l3A5Bk7waGM@public.gmane.org>
---
arch/powerpc/kernel/kvm.c | 12 ++++++++++++
1 files changed, 12 insertions(+), 0 deletions(-)
diff --git a/arch/powerpc/kernel/kvm.c b/arch/powerpc/kernel/kvm.c
index b165b20..b091f94 100644
--- a/arch/powerpc/kernel/kvm.c
+++ b/arch/powerpc/kernel/kvm.c
@@ -61,6 +61,8 @@
#define KVM_INST_MTSPR_DAR 0x7c1303a6
#define KVM_INST_MTSPR_DSISR 0x7c1203a6
+#define KVM_INST_TLBSYNC 0x7c00046c
+
static bool kvm_patching_worked = true;
static void kvm_patch_ins_ld(u32 *inst, long addr, u32 rt)
@@ -91,6 +93,11 @@ static void kvm_patch_ins_stw(u32 *inst, long addr, u32 rt)
*inst = KVM_INST_STW | rt | (addr & 0x0000fffc);
}
+static void kvm_patch_ins_nop(u32 *inst)
+{
+ *inst = KVM_INST_NOP;
+}
+
static void kvm_map_magic_page(void *data)
{
kvm_hypercall2(KVM_HC_PPC_MAP_MAGIC_PAGE,
@@ -159,6 +166,11 @@ static void kvm_check_ins(u32 *inst)
case KVM_INST_MTSPR_DSISR:
kvm_patch_ins_stw(inst, magic_var(dsisr), inst_rt);
break;
+
+ /* Nops */
+ case KVM_INST_TLBSYNC:
+ kvm_patch_ins_nop(inst);
+ break;
}
switch (_inst) {
--
1.6.0.2
^ permalink raw reply related [flat|nested] 227+ messages in thread* [PATCH 20/26] KVM: PPC: PV tlbsync to nop
@ 2010-06-25 23:25 ` Alexander Graf
0 siblings, 0 replies; 227+ messages in thread
From: Alexander Graf @ 2010-06-25 23:25 UTC (permalink / raw)
To: kvm-ppc; +Cc: linuxppc-dev, KVM list
With our current MMU scheme we don't need to know about the tlbsync instruction.
So we can just nop it out.
Signed-off-by: Alexander Graf <agraf@suse.de>
---
arch/powerpc/kernel/kvm.c | 12 ++++++++++++
1 files changed, 12 insertions(+), 0 deletions(-)
diff --git a/arch/powerpc/kernel/kvm.c b/arch/powerpc/kernel/kvm.c
index b165b20..b091f94 100644
--- a/arch/powerpc/kernel/kvm.c
+++ b/arch/powerpc/kernel/kvm.c
@@ -61,6 +61,8 @@
#define KVM_INST_MTSPR_DAR 0x7c1303a6
#define KVM_INST_MTSPR_DSISR 0x7c1203a6
+#define KVM_INST_TLBSYNC 0x7c00046c
+
static bool kvm_patching_worked = true;
static void kvm_patch_ins_ld(u32 *inst, long addr, u32 rt)
@@ -91,6 +93,11 @@ static void kvm_patch_ins_stw(u32 *inst, long addr, u32 rt)
*inst = KVM_INST_STW | rt | (addr & 0x0000fffc);
}
+static void kvm_patch_ins_nop(u32 *inst)
+{
+ *inst = KVM_INST_NOP;
+}
+
static void kvm_map_magic_page(void *data)
{
kvm_hypercall2(KVM_HC_PPC_MAP_MAGIC_PAGE,
@@ -159,6 +166,11 @@ static void kvm_check_ins(u32 *inst)
case KVM_INST_MTSPR_DSISR:
kvm_patch_ins_stw(inst, magic_var(dsisr), inst_rt);
break;
+
+ /* Nops */
+ case KVM_INST_TLBSYNC:
+ kvm_patch_ins_nop(inst);
+ break;
}
switch (_inst) {
--
1.6.0.2
^ permalink raw reply related [flat|nested] 227+ messages in thread
* [PATCH 22/26] KVM: PPC: PV assembler helpers
2010-06-25 23:24 ` Alexander Graf
(?)
@ 2010-06-25 23:25 ` Alexander Graf
-1 siblings, 0 replies; 227+ messages in thread
From: Alexander Graf @ 2010-06-25 23:25 UTC (permalink / raw)
To: kvm-ppc-u79uwXL29TY76Z2rM5mHXA; +Cc: KVM list, linuxppc-dev
When we hook an instruction we need to make sure we don't clobber any of
the registers at that point. So we write them out to scratch space in the
magic page. To make sure we don't fall into a race with another piece of
hooked code, we need to disable interrupts.
To make the later patches and code in general easier readable, let's introduce
a set of defines that save and restore r30, r31 and cr. Let's also define some
helpers to read the lower 32 bits of a 64 bit field on 32 bit systems.
Signed-off-by: Alexander Graf <agraf@suse.de>
---
arch/powerpc/kernel/kvm_emul.S | 29 +++++++++++++++++++++++++++++
1 files changed, 29 insertions(+), 0 deletions(-)
diff --git a/arch/powerpc/kernel/kvm_emul.S b/arch/powerpc/kernel/kvm_emul.S
index c7b9fc9..7da835a 100644
--- a/arch/powerpc/kernel/kvm_emul.S
+++ b/arch/powerpc/kernel/kvm_emul.S
@@ -25,3 +25,32 @@
#define KVM_MAGIC_PAGE (-4096)
+#ifdef CONFIG_64BIT
+#define LL64(reg, offs, reg2) ld reg, (offs)(reg2)
+#define STL64(reg, offs, reg2) std reg, (offs)(reg2)
+#else
+#define LL64(reg, offs, reg2) lwz reg, (offs + 4)(reg2)
+#define STL64(reg, offs, reg2) stw reg, (offs + 4)(reg2)
+#endif
+
+#define SCRATCH_SAVE \
+ /* Enable critical section. We are critical if \
+ shared->critical = r1 */ \
+ STL64(r1, KVM_MAGIC_PAGE + KVM_MAGIC_CRITICAL, 0); \
+ \
+ /* Save state */ \
+ PPC_STL r31, (KVM_MAGIC_PAGE + KVM_MAGIC_SCRATCH1)(0); \
+ PPC_STL r30, (KVM_MAGIC_PAGE + KVM_MAGIC_SCRATCH2)(0); \
+ mfcr r31; \
+ stw r31, (KVM_MAGIC_PAGE + KVM_MAGIC_SCRATCH3)(0);
+
+#define SCRATCH_RESTORE \
+ /* Restore state */ \
+ PPC_LL r31, (KVM_MAGIC_PAGE + KVM_MAGIC_SCRATCH1)(0); \
+ lwz r30, (KVM_MAGIC_PAGE + KVM_MAGIC_SCRATCH3)(0); \
+ mtcr r30; \
+ PPC_LL r30, (KVM_MAGIC_PAGE + KVM_MAGIC_SCRATCH2)(0); \
+ \
+ /* Disable critical section. We are critical if \
+ shared->critical = r1 and r2 is always != r1 */ \
+ STL64(r2, KVM_MAGIC_PAGE + KVM_MAGIC_CRITICAL, 0);
--
1.6.0.2
^ permalink raw reply related [flat|nested] 227+ messages in thread
* [PATCH 22/26] KVM: PPC: PV assembler helpers
@ 2010-06-25 23:25 ` Alexander Graf
0 siblings, 0 replies; 227+ messages in thread
From: Alexander Graf @ 2010-06-25 23:25 UTC (permalink / raw)
To: kvm-ppc-u79uwXL29TY76Z2rM5mHXA; +Cc: KVM list, linuxppc-dev
When we hook an instruction we need to make sure we don't clobber any of
the registers at that point. So we write them out to scratch space in the
magic page. To make sure we don't fall into a race with another piece of
hooked code, we need to disable interrupts.
To make the later patches and code in general easier readable, let's introduce
a set of defines that save and restore r30, r31 and cr. Let's also define some
helpers to read the lower 32 bits of a 64 bit field on 32 bit systems.
Signed-off-by: Alexander Graf <agraf-l3A5Bk7waGM@public.gmane.org>
---
arch/powerpc/kernel/kvm_emul.S | 29 +++++++++++++++++++++++++++++
1 files changed, 29 insertions(+), 0 deletions(-)
diff --git a/arch/powerpc/kernel/kvm_emul.S b/arch/powerpc/kernel/kvm_emul.S
index c7b9fc9..7da835a 100644
--- a/arch/powerpc/kernel/kvm_emul.S
+++ b/arch/powerpc/kernel/kvm_emul.S
@@ -25,3 +25,32 @@
#define KVM_MAGIC_PAGE (-4096)
+#ifdef CONFIG_64BIT
+#define LL64(reg, offs, reg2) ld reg, (offs)(reg2)
+#define STL64(reg, offs, reg2) std reg, (offs)(reg2)
+#else
+#define LL64(reg, offs, reg2) lwz reg, (offs + 4)(reg2)
+#define STL64(reg, offs, reg2) stw reg, (offs + 4)(reg2)
+#endif
+
+#define SCRATCH_SAVE \
+ /* Enable critical section. We are critical if \
+ shared->critical == r1 */ \
+ STL64(r1, KVM_MAGIC_PAGE + KVM_MAGIC_CRITICAL, 0); \
+ \
+ /* Save state */ \
+ PPC_STL r31, (KVM_MAGIC_PAGE + KVM_MAGIC_SCRATCH1)(0); \
+ PPC_STL r30, (KVM_MAGIC_PAGE + KVM_MAGIC_SCRATCH2)(0); \
+ mfcr r31; \
+ stw r31, (KVM_MAGIC_PAGE + KVM_MAGIC_SCRATCH3)(0);
+
+#define SCRATCH_RESTORE \
+ /* Restore state */ \
+ PPC_LL r31, (KVM_MAGIC_PAGE + KVM_MAGIC_SCRATCH1)(0); \
+ lwz r30, (KVM_MAGIC_PAGE + KVM_MAGIC_SCRATCH3)(0); \
+ mtcr r30; \
+ PPC_LL r30, (KVM_MAGIC_PAGE + KVM_MAGIC_SCRATCH2)(0); \
+ \
+ /* Disable critical section. We are critical if \
+ shared->critical == r1 and r2 is always != r1 */ \
+ STL64(r2, KVM_MAGIC_PAGE + KVM_MAGIC_CRITICAL, 0);
--
1.6.0.2
^ permalink raw reply related [flat|nested] 227+ messages in thread
* [PATCH 22/26] KVM: PPC: PV assembler helpers
@ 2010-06-25 23:25 ` Alexander Graf
0 siblings, 0 replies; 227+ messages in thread
From: Alexander Graf @ 2010-06-25 23:25 UTC (permalink / raw)
To: kvm-ppc; +Cc: linuxppc-dev, KVM list
When we hook an instruction we need to make sure we don't clobber any of
the registers at that point. So we write them out to scratch space in the
magic page. To make sure we don't fall into a race with another piece of
hooked code, we need to disable interrupts.
To make the later patches and code in general easier readable, let's introduce
a set of defines that save and restore r30, r31 and cr. Let's also define some
helpers to read the lower 32 bits of a 64 bit field on 32 bit systems.
Signed-off-by: Alexander Graf <agraf@suse.de>
---
arch/powerpc/kernel/kvm_emul.S | 29 +++++++++++++++++++++++++++++
1 files changed, 29 insertions(+), 0 deletions(-)
diff --git a/arch/powerpc/kernel/kvm_emul.S b/arch/powerpc/kernel/kvm_emul.S
index c7b9fc9..7da835a 100644
--- a/arch/powerpc/kernel/kvm_emul.S
+++ b/arch/powerpc/kernel/kvm_emul.S
@@ -25,3 +25,32 @@
#define KVM_MAGIC_PAGE (-4096)
+#ifdef CONFIG_64BIT
+#define LL64(reg, offs, reg2) ld reg, (offs)(reg2)
+#define STL64(reg, offs, reg2) std reg, (offs)(reg2)
+#else
+#define LL64(reg, offs, reg2) lwz reg, (offs + 4)(reg2)
+#define STL64(reg, offs, reg2) stw reg, (offs + 4)(reg2)
+#endif
+
+#define SCRATCH_SAVE \
+ /* Enable critical section. We are critical if \
+ shared->critical == r1 */ \
+ STL64(r1, KVM_MAGIC_PAGE + KVM_MAGIC_CRITICAL, 0); \
+ \
+ /* Save state */ \
+ PPC_STL r31, (KVM_MAGIC_PAGE + KVM_MAGIC_SCRATCH1)(0); \
+ PPC_STL r30, (KVM_MAGIC_PAGE + KVM_MAGIC_SCRATCH2)(0); \
+ mfcr r31; \
+ stw r31, (KVM_MAGIC_PAGE + KVM_MAGIC_SCRATCH3)(0);
+
+#define SCRATCH_RESTORE \
+ /* Restore state */ \
+ PPC_LL r31, (KVM_MAGIC_PAGE + KVM_MAGIC_SCRATCH1)(0); \
+ lwz r30, (KVM_MAGIC_PAGE + KVM_MAGIC_SCRATCH3)(0); \
+ mtcr r30; \
+ PPC_LL r30, (KVM_MAGIC_PAGE + KVM_MAGIC_SCRATCH2)(0); \
+ \
+ /* Disable critical section. We are critical if \
+ shared->critical == r1 and r2 is always != r1 */ \
+ STL64(r2, KVM_MAGIC_PAGE + KVM_MAGIC_CRITICAL, 0);
--
1.6.0.2
^ permalink raw reply related [flat|nested] 227+ messages in thread
* [PATCH 24/26] KVM: PPC: PV mtmsrd L=0 and mtmsr
2010-06-25 23:24 ` Alexander Graf
(?)
@ 2010-06-25 23:25 ` Alexander Graf
-1 siblings, 0 replies; 227+ messages in thread
From: Alexander Graf @ 2010-06-25 23:25 UTC (permalink / raw)
To: kvm-ppc-u79uwXL29TY76Z2rM5mHXA; +Cc: KVM list, linuxppc-dev
There is also a form of mtmsr where all bits need to be addressed. While the
PPC64 Linux kernel behaves resonably well here, the PPC32 one never uses the
L=1 form but does mtmsr even for simple things like only changing EE.
So we need to hook into that one as well and check for a mask of bits that we
deem safe to change from within guest context.
Signed-off-by: Alexander Graf <agraf@suse.de>
---
arch/powerpc/kernel/kvm.c | 51 ++++++++++++++++++++++++
arch/powerpc/kernel/kvm_emul.S | 84 ++++++++++++++++++++++++++++++++++++++++
2 files changed, 135 insertions(+), 0 deletions(-)
diff --git a/arch/powerpc/kernel/kvm.c b/arch/powerpc/kernel/kvm.c
index 71153d0..3557bc8 100644
--- a/arch/powerpc/kernel/kvm.c
+++ b/arch/powerpc/kernel/kvm.c
@@ -62,7 +62,9 @@
#define KVM_INST_MTSPR_DSISR 0x7c1203a6
#define KVM_INST_TLBSYNC 0x7c00046c
+#define KVM_INST_MTMSRD_L0 0x7c000164
#define KVM_INST_MTMSRD_L1 0x7c010164
+#define KVM_INST_MTMSR 0x7c000124
static bool kvm_patching_worked = true;
static char kvm_tmp[1024 * 1024];
@@ -155,6 +157,49 @@ static void kvm_patch_ins_mtmsrd(u32 *inst, u32 rt)
*inst = KVM_INST_B | (distance_start & KVM_INST_B_MASK);
}
+extern u32 kvm_emulate_mtmsr_branch_offs;
+extern u32 kvm_emulate_mtmsr_reg1_offs;
+extern u32 kvm_emulate_mtmsr_reg2_offs;
+extern u32 kvm_emulate_mtmsr_reg3_offs;
+extern u32 kvm_emulate_mtmsr_orig_ins_offs;
+extern u32 kvm_emulate_mtmsr_len;
+extern u32 kvm_emulate_mtmsr[];
+
+static void kvm_patch_ins_mtmsr(u32 *inst, u32 rt)
+{
+ u32 *p;
+ int distance_start;
+ int distance_end;
+ ulong next_inst;
+
+ p = kvm_alloc(kvm_emulate_mtmsr_len * 4);
+ if (!p)
+ return;
+
+ /* Find out where we are and put everything there */
+ distance_start = (ulong)p - (ulong)inst;
+ next_inst = ((ulong)inst + 4);
+ distance_end = next_inst - (ulong)&p[kvm_emulate_mtmsr_branch_offs];
+
+ /* Make sure we only write valid b instructions */
+ if (distance_start > KVM_INST_B_MAX) {
+ kvm_patching_worked = false;
+ return;
+ }
+
+ /* Modify the chunk to fit the invocation */
+ memcpy(p, kvm_emulate_mtmsr, kvm_emulate_mtmsr_len * 4);
+ p[kvm_emulate_mtmsr_branch_offs] |= distance_end & KVM_INST_B_MASK;
+ p[kvm_emulate_mtmsr_reg1_offs] |= rt;
+ p[kvm_emulate_mtmsr_reg2_offs] |= rt;
+ p[kvm_emulate_mtmsr_reg3_offs] |= rt;
+ p[kvm_emulate_mtmsr_orig_ins_offs] = *inst;
+ flush_icache_range((ulong)p, (ulong)p + kvm_emulate_mtmsr_len * 4);
+
+ /* Patch the invocation */
+ *inst = KVM_INST_B | (distance_start & KVM_INST_B_MASK);
+}
+
static void kvm_map_magic_page(void *data)
{
kvm_hypercall2(KVM_HC_PPC_MAP_MAGIC_PAGE,
@@ -235,6 +280,12 @@ static void kvm_check_ins(u32 *inst)
if (get_rt(inst_rt) < 30)
kvm_patch_ins_mtmsrd(inst, inst_rt);
break;
+ case KVM_INST_MTMSR:
+ case KVM_INST_MTMSRD_L0:
+ /* We use r30 and r31 during the hook */
+ if (get_rt(inst_rt) < 30)
+ kvm_patch_ins_mtmsr(inst, inst_rt);
+ break;
}
switch (_inst) {
diff --git a/arch/powerpc/kernel/kvm_emul.S b/arch/powerpc/kernel/kvm_emul.S
index 25e6683..ccf5a42 100644
--- a/arch/powerpc/kernel/kvm_emul.S
+++ b/arch/powerpc/kernel/kvm_emul.S
@@ -110,3 +110,87 @@ kvm_emulate_mtmsrd_reg_offs:
.global kvm_emulate_mtmsrd_len
kvm_emulate_mtmsrd_len:
.long (kvm_emulate_mtmsrd_end - kvm_emulate_mtmsrd) / 4
+
+
+#define MSR_SAFE_BITS (MSR_EE | MSR_CE | MSR_ME | MSR_RI)
+#define MSR_CRITICAL_BITS ~MSR_SAFE_BITS
+
+.global kvm_emulate_mtmsr
+kvm_emulate_mtmsr:
+
+ SCRATCH_SAVE
+
+ /* Fetch old MSR in r31 */
+ LL64(r31, KVM_MAGIC_PAGE + KVM_MAGIC_MSR, 0)
+
+ /* Find the changed bits between old and new MSR */
+kvm_emulate_mtmsr_reg1:
+ xor r31, r0, r31
+
+ /* Check if we need to really do mtmsr */
+ LOAD_REG_IMMEDIATE(r30, MSR_CRITICAL_BITS)
+ and. r31, r31, r30
+
+ /* No critical bits changed? Maybe we can stay in the guest. */
+ beq maybe_stay_in_guest
+
+do_mtmsr:
+
+ SCRATCH_RESTORE
+
+ /* Just fire off the mtmsr if it's critical */
+kvm_emulate_mtmsr_orig_ins:
+ mtmsr r0
+
+ b kvm_emulate_mtmsr_branch
+
+maybe_stay_in_guest:
+
+ /* Check if we have to fetch an interrupt */
+ lwz r31, (KVM_MAGIC_PAGE + KVM_MAGIC_INT)(0)
+ cmpwi r31, 0
+ beq+ no_mtmsr
+
+ /* Check if we may trigger an interrupt */
+kvm_emulate_mtmsr_reg2:
+ andi. r31, r0, MSR_EE
+ beq no_mtmsr
+
+ b do_mtmsr
+
+no_mtmsr:
+
+ /* Put MSR into magic page because we don't call mtmsr */
+kvm_emulate_mtmsr_reg3:
+ STL64(r0, KVM_MAGIC_PAGE + KVM_MAGIC_MSR, 0)
+
+ SCRATCH_RESTORE
+
+ /* Go back to caller */
+kvm_emulate_mtmsr_branch:
+ b .
+kvm_emulate_mtmsr_end:
+
+.global kvm_emulate_mtmsr_branch_offs
+kvm_emulate_mtmsr_branch_offs:
+ .long (kvm_emulate_mtmsr_branch - kvm_emulate_mtmsr) / 4
+
+.global kvm_emulate_mtmsr_reg1_offs
+kvm_emulate_mtmsr_reg1_offs:
+ .long (kvm_emulate_mtmsr_reg1 - kvm_emulate_mtmsr) / 4
+
+.global kvm_emulate_mtmsr_reg2_offs
+kvm_emulate_mtmsr_reg2_offs:
+ .long (kvm_emulate_mtmsr_reg2 - kvm_emulate_mtmsr) / 4
+
+.global kvm_emulate_mtmsr_reg3_offs
+kvm_emulate_mtmsr_reg3_offs:
+ .long (kvm_emulate_mtmsr_reg3 - kvm_emulate_mtmsr) / 4
+
+.global kvm_emulate_mtmsr_orig_ins_offs
+kvm_emulate_mtmsr_orig_ins_offs:
+ .long (kvm_emulate_mtmsr_orig_ins - kvm_emulate_mtmsr) / 4
+
+.global kvm_emulate_mtmsr_len
+kvm_emulate_mtmsr_len:
+ .long (kvm_emulate_mtmsr_end - kvm_emulate_mtmsr) / 4
--
1.6.0.2
^ permalink raw reply related [flat|nested] 227+ messages in thread* [PATCH 24/26] KVM: PPC: PV mtmsrd L=0 and mtmsr
@ 2010-06-25 23:25 ` Alexander Graf
0 siblings, 0 replies; 227+ messages in thread
From: Alexander Graf @ 2010-06-25 23:25 UTC (permalink / raw)
To: kvm-ppc-u79uwXL29TY76Z2rM5mHXA; +Cc: KVM list, linuxppc-dev
There is also a form of mtmsr where all bits need to be addressed. While the
PPC64 Linux kernel behaves resonably well here, the PPC32 one never uses the
L=1 form but does mtmsr even for simple things like only changing EE.
So we need to hook into that one as well and check for a mask of bits that we
deem safe to change from within guest context.
Signed-off-by: Alexander Graf <agraf-l3A5Bk7waGM@public.gmane.org>
---
arch/powerpc/kernel/kvm.c | 51 ++++++++++++++++++++++++
arch/powerpc/kernel/kvm_emul.S | 84 ++++++++++++++++++++++++++++++++++++++++
2 files changed, 135 insertions(+), 0 deletions(-)
diff --git a/arch/powerpc/kernel/kvm.c b/arch/powerpc/kernel/kvm.c
index 71153d0..3557bc8 100644
--- a/arch/powerpc/kernel/kvm.c
+++ b/arch/powerpc/kernel/kvm.c
@@ -62,7 +62,9 @@
#define KVM_INST_MTSPR_DSISR 0x7c1203a6
#define KVM_INST_TLBSYNC 0x7c00046c
+#define KVM_INST_MTMSRD_L0 0x7c000164
#define KVM_INST_MTMSRD_L1 0x7c010164
+#define KVM_INST_MTMSR 0x7c000124
static bool kvm_patching_worked = true;
static char kvm_tmp[1024 * 1024];
@@ -155,6 +157,49 @@ static void kvm_patch_ins_mtmsrd(u32 *inst, u32 rt)
*inst = KVM_INST_B | (distance_start & KVM_INST_B_MASK);
}
+extern u32 kvm_emulate_mtmsr_branch_offs;
+extern u32 kvm_emulate_mtmsr_reg1_offs;
+extern u32 kvm_emulate_mtmsr_reg2_offs;
+extern u32 kvm_emulate_mtmsr_reg3_offs;
+extern u32 kvm_emulate_mtmsr_orig_ins_offs;
+extern u32 kvm_emulate_mtmsr_len;
+extern u32 kvm_emulate_mtmsr[];
+
+static void kvm_patch_ins_mtmsr(u32 *inst, u32 rt)
+{
+ u32 *p;
+ int distance_start;
+ int distance_end;
+ ulong next_inst;
+
+ p = kvm_alloc(kvm_emulate_mtmsr_len * 4);
+ if (!p)
+ return;
+
+ /* Find out where we are and put everything there */
+ distance_start = (ulong)p - (ulong)inst;
+ next_inst = ((ulong)inst + 4);
+ distance_end = next_inst - (ulong)&p[kvm_emulate_mtmsr_branch_offs];
+
+ /* Make sure we only write valid b instructions */
+ if (distance_start > KVM_INST_B_MAX) {
+ kvm_patching_worked = false;
+ return;
+ }
+
+ /* Modify the chunk to fit the invocation */
+ memcpy(p, kvm_emulate_mtmsr, kvm_emulate_mtmsr_len * 4);
+ p[kvm_emulate_mtmsr_branch_offs] |= distance_end & KVM_INST_B_MASK;
+ p[kvm_emulate_mtmsr_reg1_offs] |= rt;
+ p[kvm_emulate_mtmsr_reg2_offs] |= rt;
+ p[kvm_emulate_mtmsr_reg3_offs] |= rt;
+ p[kvm_emulate_mtmsr_orig_ins_offs] = *inst;
+ flush_icache_range((ulong)p, (ulong)p + kvm_emulate_mtmsr_len * 4);
+
+ /* Patch the invocation */
+ *inst = KVM_INST_B | (distance_start & KVM_INST_B_MASK);
+}
+
static void kvm_map_magic_page(void *data)
{
kvm_hypercall2(KVM_HC_PPC_MAP_MAGIC_PAGE,
@@ -235,6 +280,12 @@ static void kvm_check_ins(u32 *inst)
if (get_rt(inst_rt) < 30)
kvm_patch_ins_mtmsrd(inst, inst_rt);
break;
+ case KVM_INST_MTMSR:
+ case KVM_INST_MTMSRD_L0:
+ /* We use r30 and r31 during the hook */
+ if (get_rt(inst_rt) < 30)
+ kvm_patch_ins_mtmsr(inst, inst_rt);
+ break;
}
switch (_inst) {
diff --git a/arch/powerpc/kernel/kvm_emul.S b/arch/powerpc/kernel/kvm_emul.S
index 25e6683..ccf5a42 100644
--- a/arch/powerpc/kernel/kvm_emul.S
+++ b/arch/powerpc/kernel/kvm_emul.S
@@ -110,3 +110,87 @@ kvm_emulate_mtmsrd_reg_offs:
.global kvm_emulate_mtmsrd_len
kvm_emulate_mtmsrd_len:
.long (kvm_emulate_mtmsrd_end - kvm_emulate_mtmsrd) / 4
+
+
+#define MSR_SAFE_BITS (MSR_EE | MSR_CE | MSR_ME | MSR_RI)
+#define MSR_CRITICAL_BITS ~MSR_SAFE_BITS
+
+.global kvm_emulate_mtmsr
+kvm_emulate_mtmsr:
+
+ SCRATCH_SAVE
+
+ /* Fetch old MSR in r31 */
+ LL64(r31, KVM_MAGIC_PAGE + KVM_MAGIC_MSR, 0)
+
+ /* Find the changed bits between old and new MSR */
+kvm_emulate_mtmsr_reg1:
+ xor r31, r0, r31
+
+ /* Check if we need to really do mtmsr */
+ LOAD_REG_IMMEDIATE(r30, MSR_CRITICAL_BITS)
+ and. r31, r31, r30
+
+ /* No critical bits changed? Maybe we can stay in the guest. */
+ beq maybe_stay_in_guest
+
+do_mtmsr:
+
+ SCRATCH_RESTORE
+
+ /* Just fire off the mtmsr if it's critical */
+kvm_emulate_mtmsr_orig_ins:
+ mtmsr r0
+
+ b kvm_emulate_mtmsr_branch
+
+maybe_stay_in_guest:
+
+ /* Check if we have to fetch an interrupt */
+ lwz r31, (KVM_MAGIC_PAGE + KVM_MAGIC_INT)(0)
+ cmpwi r31, 0
+ beq+ no_mtmsr
+
+ /* Check if we may trigger an interrupt */
+kvm_emulate_mtmsr_reg2:
+ andi. r31, r0, MSR_EE
+ beq no_mtmsr
+
+ b do_mtmsr
+
+no_mtmsr:
+
+ /* Put MSR into magic page because we don't call mtmsr */
+kvm_emulate_mtmsr_reg3:
+ STL64(r0, KVM_MAGIC_PAGE + KVM_MAGIC_MSR, 0)
+
+ SCRATCH_RESTORE
+
+ /* Go back to caller */
+kvm_emulate_mtmsr_branch:
+ b .
+kvm_emulate_mtmsr_end:
+
+.global kvm_emulate_mtmsr_branch_offs
+kvm_emulate_mtmsr_branch_offs:
+ .long (kvm_emulate_mtmsr_branch - kvm_emulate_mtmsr) / 4
+
+.global kvm_emulate_mtmsr_reg1_offs
+kvm_emulate_mtmsr_reg1_offs:
+ .long (kvm_emulate_mtmsr_reg1 - kvm_emulate_mtmsr) / 4
+
+.global kvm_emulate_mtmsr_reg2_offs
+kvm_emulate_mtmsr_reg2_offs:
+ .long (kvm_emulate_mtmsr_reg2 - kvm_emulate_mtmsr) / 4
+
+.global kvm_emulate_mtmsr_reg3_offs
+kvm_emulate_mtmsr_reg3_offs:
+ .long (kvm_emulate_mtmsr_reg3 - kvm_emulate_mtmsr) / 4
+
+.global kvm_emulate_mtmsr_orig_ins_offs
+kvm_emulate_mtmsr_orig_ins_offs:
+ .long (kvm_emulate_mtmsr_orig_ins - kvm_emulate_mtmsr) / 4
+
+.global kvm_emulate_mtmsr_len
+kvm_emulate_mtmsr_len:
+ .long (kvm_emulate_mtmsr_end - kvm_emulate_mtmsr) / 4
--
1.6.0.2
^ permalink raw reply related [flat|nested] 227+ messages in thread* [PATCH 24/26] KVM: PPC: PV mtmsrd L=0 and mtmsr
@ 2010-06-25 23:25 ` Alexander Graf
0 siblings, 0 replies; 227+ messages in thread
From: Alexander Graf @ 2010-06-25 23:25 UTC (permalink / raw)
To: kvm-ppc; +Cc: linuxppc-dev, KVM list
There is also a form of mtmsr where all bits need to be addressed. While the
PPC64 Linux kernel behaves resonably well here, the PPC32 one never uses the
L=1 form but does mtmsr even for simple things like only changing EE.
So we need to hook into that one as well and check for a mask of bits that we
deem safe to change from within guest context.
Signed-off-by: Alexander Graf <agraf@suse.de>
---
arch/powerpc/kernel/kvm.c | 51 ++++++++++++++++++++++++
arch/powerpc/kernel/kvm_emul.S | 84 ++++++++++++++++++++++++++++++++++++++++
2 files changed, 135 insertions(+), 0 deletions(-)
diff --git a/arch/powerpc/kernel/kvm.c b/arch/powerpc/kernel/kvm.c
index 71153d0..3557bc8 100644
--- a/arch/powerpc/kernel/kvm.c
+++ b/arch/powerpc/kernel/kvm.c
@@ -62,7 +62,9 @@
#define KVM_INST_MTSPR_DSISR 0x7c1203a6
#define KVM_INST_TLBSYNC 0x7c00046c
+#define KVM_INST_MTMSRD_L0 0x7c000164
#define KVM_INST_MTMSRD_L1 0x7c010164
+#define KVM_INST_MTMSR 0x7c000124
static bool kvm_patching_worked = true;
static char kvm_tmp[1024 * 1024];
@@ -155,6 +157,49 @@ static void kvm_patch_ins_mtmsrd(u32 *inst, u32 rt)
*inst = KVM_INST_B | (distance_start & KVM_INST_B_MASK);
}
+extern u32 kvm_emulate_mtmsr_branch_offs;
+extern u32 kvm_emulate_mtmsr_reg1_offs;
+extern u32 kvm_emulate_mtmsr_reg2_offs;
+extern u32 kvm_emulate_mtmsr_reg3_offs;
+extern u32 kvm_emulate_mtmsr_orig_ins_offs;
+extern u32 kvm_emulate_mtmsr_len;
+extern u32 kvm_emulate_mtmsr[];
+
+static void kvm_patch_ins_mtmsr(u32 *inst, u32 rt)
+{
+ u32 *p;
+ int distance_start;
+ int distance_end;
+ ulong next_inst;
+
+ p = kvm_alloc(kvm_emulate_mtmsr_len * 4);
+ if (!p)
+ return;
+
+ /* Find out where we are and put everything there */
+ distance_start = (ulong)p - (ulong)inst;
+ next_inst = ((ulong)inst + 4);
+ distance_end = next_inst - (ulong)&p[kvm_emulate_mtmsr_branch_offs];
+
+ /* Make sure we only write valid b instructions */
+ if (distance_start > KVM_INST_B_MAX) {
+ kvm_patching_worked = false;
+ return;
+ }
+
+ /* Modify the chunk to fit the invocation */
+ memcpy(p, kvm_emulate_mtmsr, kvm_emulate_mtmsr_len * 4);
+ p[kvm_emulate_mtmsr_branch_offs] |= distance_end & KVM_INST_B_MASK;
+ p[kvm_emulate_mtmsr_reg1_offs] |= rt;
+ p[kvm_emulate_mtmsr_reg2_offs] |= rt;
+ p[kvm_emulate_mtmsr_reg3_offs] |= rt;
+ p[kvm_emulate_mtmsr_orig_ins_offs] = *inst;
+ flush_icache_range((ulong)p, (ulong)p + kvm_emulate_mtmsr_len * 4);
+
+ /* Patch the invocation */
+ *inst = KVM_INST_B | (distance_start & KVM_INST_B_MASK);
+}
+
static void kvm_map_magic_page(void *data)
{
kvm_hypercall2(KVM_HC_PPC_MAP_MAGIC_PAGE,
@@ -235,6 +280,12 @@ static void kvm_check_ins(u32 *inst)
if (get_rt(inst_rt) < 30)
kvm_patch_ins_mtmsrd(inst, inst_rt);
break;
+ case KVM_INST_MTMSR:
+ case KVM_INST_MTMSRD_L0:
+ /* We use r30 and r31 during the hook */
+ if (get_rt(inst_rt) < 30)
+ kvm_patch_ins_mtmsr(inst, inst_rt);
+ break;
}
switch (_inst) {
diff --git a/arch/powerpc/kernel/kvm_emul.S b/arch/powerpc/kernel/kvm_emul.S
index 25e6683..ccf5a42 100644
--- a/arch/powerpc/kernel/kvm_emul.S
+++ b/arch/powerpc/kernel/kvm_emul.S
@@ -110,3 +110,87 @@ kvm_emulate_mtmsrd_reg_offs:
.global kvm_emulate_mtmsrd_len
kvm_emulate_mtmsrd_len:
.long (kvm_emulate_mtmsrd_end - kvm_emulate_mtmsrd) / 4
+
+
+#define MSR_SAFE_BITS (MSR_EE | MSR_CE | MSR_ME | MSR_RI)
+#define MSR_CRITICAL_BITS ~MSR_SAFE_BITS
+
+.global kvm_emulate_mtmsr
+kvm_emulate_mtmsr:
+
+ SCRATCH_SAVE
+
+ /* Fetch old MSR in r31 */
+ LL64(r31, KVM_MAGIC_PAGE + KVM_MAGIC_MSR, 0)
+
+ /* Find the changed bits between old and new MSR */
+kvm_emulate_mtmsr_reg1:
+ xor r31, r0, r31
+
+ /* Check if we need to really do mtmsr */
+ LOAD_REG_IMMEDIATE(r30, MSR_CRITICAL_BITS)
+ and. r31, r31, r30
+
+ /* No critical bits changed? Maybe we can stay in the guest. */
+ beq maybe_stay_in_guest
+
+do_mtmsr:
+
+ SCRATCH_RESTORE
+
+ /* Just fire off the mtmsr if it's critical */
+kvm_emulate_mtmsr_orig_ins:
+ mtmsr r0
+
+ b kvm_emulate_mtmsr_branch
+
+maybe_stay_in_guest:
+
+ /* Check if we have to fetch an interrupt */
+ lwz r31, (KVM_MAGIC_PAGE + KVM_MAGIC_INT)(0)
+ cmpwi r31, 0
+ beq+ no_mtmsr
+
+ /* Check if we may trigger an interrupt */
+kvm_emulate_mtmsr_reg2:
+ andi. r31, r0, MSR_EE
+ beq no_mtmsr
+
+ b do_mtmsr
+
+no_mtmsr:
+
+ /* Put MSR into magic page because we don't call mtmsr */
+kvm_emulate_mtmsr_reg3:
+ STL64(r0, KVM_MAGIC_PAGE + KVM_MAGIC_MSR, 0)
+
+ SCRATCH_RESTORE
+
+ /* Go back to caller */
+kvm_emulate_mtmsr_branch:
+ b .
+kvm_emulate_mtmsr_end:
+
+.global kvm_emulate_mtmsr_branch_offs
+kvm_emulate_mtmsr_branch_offs:
+ .long (kvm_emulate_mtmsr_branch - kvm_emulate_mtmsr) / 4
+
+.global kvm_emulate_mtmsr_reg1_offs
+kvm_emulate_mtmsr_reg1_offs:
+ .long (kvm_emulate_mtmsr_reg1 - kvm_emulate_mtmsr) / 4
+
+.global kvm_emulate_mtmsr_reg2_offs
+kvm_emulate_mtmsr_reg2_offs:
+ .long (kvm_emulate_mtmsr_reg2 - kvm_emulate_mtmsr) / 4
+
+.global kvm_emulate_mtmsr_reg3_offs
+kvm_emulate_mtmsr_reg3_offs:
+ .long (kvm_emulate_mtmsr_reg3 - kvm_emulate_mtmsr) / 4
+
+.global kvm_emulate_mtmsr_orig_ins_offs
+kvm_emulate_mtmsr_orig_ins_offs:
+ .long (kvm_emulate_mtmsr_orig_ins - kvm_emulate_mtmsr) / 4
+
+.global kvm_emulate_mtmsr_len
+kvm_emulate_mtmsr_len:
+ .long (kvm_emulate_mtmsr_end - kvm_emulate_mtmsr) / 4
--
1.6.0.2
^ permalink raw reply related [flat|nested] 227+ messages in thread[parent not found: <1277508314-915-25-git-send-email-agraf-l3A5Bk7waGM@public.gmane.org>]
* Re: [PATCH 24/26] KVM: PPC: PV mtmsrd L=0 and mtmsr
2010-06-25 23:25 ` Alexander Graf
(?)
@ 2010-06-26 17:03 ` Segher Boessenkool
-1 siblings, 0 replies; 227+ messages in thread
From: Segher Boessenkool @ 2010-06-26 17:03 UTC (permalink / raw)
To: Alexander Graf; +Cc: kvm-ppc-u79uwXL29TY76Z2rM5mHXA, linuxppc-dev, KVM list
> There is also a form of mtmsr where all bits need to be addressed.
> While the
> PPC64 Linux kernel behaves resonably well here, the PPC32 one never
> uses the
> L=1 form but does mtmsr even for simple things like only changing EE.
You make it sound like the 32-bit kernel does something stupid, while
there is no other choice. The "L=1" thing only exists for 64-bit.
Segher
^ permalink raw reply [flat|nested] 227+ messages in thread
* Re: [PATCH 24/26] KVM: PPC: PV mtmsrd L=0 and mtmsr
@ 2010-06-26 17:03 ` Segher Boessenkool
0 siblings, 0 replies; 227+ messages in thread
From: Segher Boessenkool @ 2010-06-26 17:03 UTC (permalink / raw)
To: Alexander Graf; +Cc: kvm-ppc-u79uwXL29TY76Z2rM5mHXA, linuxppc-dev, KVM list
> There is also a form of mtmsr where all bits need to be addressed.
> While the
> PPC64 Linux kernel behaves resonably well here, the PPC32 one never
> uses the
> L=1 form but does mtmsr even for simple things like only changing EE.
You make it sound like the 32-bit kernel does something stupid, while
there is no other choice. The "L=1" thing only exists for 64-bit.
Segher
^ permalink raw reply [flat|nested] 227+ messages in thread
* Re: [PATCH 24/26] KVM: PPC: PV mtmsrd L=0 and mtmsr
@ 2010-06-26 17:03 ` Segher Boessenkool
0 siblings, 0 replies; 227+ messages in thread
From: Segher Boessenkool @ 2010-06-26 17:03 UTC (permalink / raw)
To: Alexander Graf; +Cc: linuxppc-dev, KVM list, kvm-ppc
> There is also a form of mtmsr where all bits need to be addressed.
> While the
> PPC64 Linux kernel behaves resonably well here, the PPC32 one never
> uses the
> L=1 form but does mtmsr even for simple things like only changing EE.
You make it sound like the 32-bit kernel does something stupid, while
there is no other choice. The "L=1" thing only exists for 64-bit.
Segher
^ permalink raw reply [flat|nested] 227+ messages in thread
[parent not found: <EDF0A567-C440-4F1B-9AF5-2E0F8203D566-XVmvHMARGAS8U2dJNN8I7kB+6BGkLq7r@public.gmane.org>]
* Re: [PATCH 24/26] KVM: PPC: PV mtmsrd L=0 and mtmsr
2010-06-26 17:03 ` Segher Boessenkool
(?)
@ 2010-06-27 9:10 ` Alexander Graf
-1 siblings, 0 replies; 227+ messages in thread
From: Alexander Graf @ 2010-06-27 9:10 UTC (permalink / raw)
To: Segher Boessenkool
Cc: kvm-ppc-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, linuxppc-dev,
KVM list
Am 26.06.2010 um 19:03 schrieb Segher Boessenkool <segher@kernel.crashing.org
>:
>> There is also a form of mtmsr where all bits need to be addressed.
>> While the
>> PPC64 Linux kernel behaves resonably well here, the PPC32 one never
>> uses the
>> L=1 form but does mtmsr even for simple things like only changing EE.
>
> You make it sound like the 32-bit kernel does something stupid, while
> there is no other choice. The "L=1" thing only exists for 64-bit.
Oh, so that's why :). That doesn't really change the fact that it's
very hard to distinguish between a mtmsr that only changes MSR_EE vs
one that changes MSR_IR for example :).
Alex
>
^ permalink raw reply [flat|nested] 227+ messages in thread
* Re: [PATCH 24/26] KVM: PPC: PV mtmsrd L=0 and mtmsr
@ 2010-06-27 9:10 ` Alexander Graf
0 siblings, 0 replies; 227+ messages in thread
From: Alexander Graf @ 2010-06-27 9:10 UTC (permalink / raw)
To: Segher Boessenkool
Cc: kvm-ppc-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, linuxppc-dev,
KVM list
Am 26.06.2010 um 19:03 schrieb Segher Boessenkool <segher-XVmvHMARGAS8U2dJNN8I7kB+6BGkLq7r@public.gmane.org
>:
>> There is also a form of mtmsr where all bits need to be addressed.
>> While the
>> PPC64 Linux kernel behaves resonably well here, the PPC32 one never
>> uses the
>> L=1 form but does mtmsr even for simple things like only changing EE.
>
> You make it sound like the 32-bit kernel does something stupid, while
> there is no other choice. The "L=1" thing only exists for 64-bit.
Oh, so that's why :). That doesn't really change the fact that it's
very hard to distinguish between a mtmsr that only changes MSR_EE vs
one that changes MSR_IR for example :).
Alex
>
^ permalink raw reply [flat|nested] 227+ messages in thread
* Re: [PATCH 24/26] KVM: PPC: PV mtmsrd L=0 and mtmsr
@ 2010-06-27 9:10 ` Alexander Graf
0 siblings, 0 replies; 227+ messages in thread
From: Alexander Graf @ 2010-06-27 9:10 UTC (permalink / raw)
To: Segher Boessenkool; +Cc: linuxppc-dev, KVM list, kvm-ppc@vger.kernel.org
Am 26.06.2010 um 19:03 schrieb Segher Boessenkool <segher@kernel.crashing.org
>:
>> There is also a form of mtmsr where all bits need to be addressed.
>> While the
>> PPC64 Linux kernel behaves resonably well here, the PPC32 one never
>> uses the
>> L=1 form but does mtmsr even for simple things like only changing EE.
>
> You make it sound like the 32-bit kernel does something stupid, while
> there is no other choice. The "L=1" thing only exists for 64-bit.
Oh, so that's why :). That doesn't really change the fact that it's
very hard to distinguish between a mtmsr that only changes MSR_EE vs
one that changes MSR_IR for example :).
Alex
>
^ permalink raw reply [flat|nested] 227+ messages in thread
* Re: [PATCH 24/26] KVM: PPC: PV mtmsrd L=0 and mtmsr
2010-06-27 9:10 ` Alexander Graf
(?)
@ 2010-06-29 7:37 ` Segher Boessenkool
-1 siblings, 0 replies; 227+ messages in thread
From: Segher Boessenkool @ 2010-06-29 7:37 UTC (permalink / raw)
To: Alexander Graf; +Cc: kvm-ppc@vger.kernel.org, linuxppc-dev, KVM list
>>> There is also a form of mtmsr where all bits need to be
>>> addressed. While the
>>> PPC64 Linux kernel behaves resonably well here, the PPC32 one
>>> never uses the
>>> L=1 form but does mtmsr even for simple things like only changing
>>> EE.
>>
>> You make it sound like the 32-bit kernel does something stupid, while
>> there is no other choice. The "L=1" thing only exists for 64-bit.
>
> Oh, so that's why :). That doesn't really change the fact that it's
> very hard to distinguish between a mtmsr that only changes MSR_EE
> vs one that changes MSR_IR for example :).
Hard to predict for the CPU as well, guess why there is a separate
instruction now :-P
By the way, L=1 _does_ exist for mtmsr; it's just that no 32-bit
"classic"
implementations support it.
Segher
^ permalink raw reply [flat|nested] 227+ messages in thread
* Re: [PATCH 24/26] KVM: PPC: PV mtmsrd L=0 and mtmsr
@ 2010-06-29 7:37 ` Segher Boessenkool
0 siblings, 0 replies; 227+ messages in thread
From: Segher Boessenkool @ 2010-06-29 7:37 UTC (permalink / raw)
To: Alexander Graf; +Cc: kvm-ppc@vger.kernel.org, linuxppc-dev, KVM list
>>> There is also a form of mtmsr where all bits need to be
>>> addressed. While the
>>> PPC64 Linux kernel behaves resonably well here, the PPC32 one
>>> never uses the
>>> L=1 form but does mtmsr even for simple things like only changing
>>> EE.
>>
>> You make it sound like the 32-bit kernel does something stupid, while
>> there is no other choice. The "L=1" thing only exists for 64-bit.
>
> Oh, so that's why :). That doesn't really change the fact that it's
> very hard to distinguish between a mtmsr that only changes MSR_EE
> vs one that changes MSR_IR for example :).
Hard to predict for the CPU as well, guess why there is a separate
instruction now :-P
By the way, L=1 _does_ exist for mtmsr; it's just that no 32-bit
"classic"
implementations support it.
Segher
^ permalink raw reply [flat|nested] 227+ messages in thread
* Re: [PATCH 24/26] KVM: PPC: PV mtmsrd L=0 and mtmsr
@ 2010-06-29 7:37 ` Segher Boessenkool
0 siblings, 0 replies; 227+ messages in thread
From: Segher Boessenkool @ 2010-06-29 7:37 UTC (permalink / raw)
To: Alexander Graf; +Cc: linuxppc-dev, KVM list, kvm-ppc@vger.kernel.org
>>> There is also a form of mtmsr where all bits need to be
>>> addressed. While the
>>> PPC64 Linux kernel behaves resonably well here, the PPC32 one
>>> never uses the
>>> L=1 form but does mtmsr even for simple things like only changing
>>> EE.
>>
>> You make it sound like the 32-bit kernel does something stupid, while
>> there is no other choice. The "L=1" thing only exists for 64-bit.
>
> Oh, so that's why :). That doesn't really change the fact that it's
> very hard to distinguish between a mtmsr that only changes MSR_EE
> vs one that changes MSR_IR for example :).
Hard to predict for the CPU as well, guess why there is a separate
instruction now :-P
By the way, L=1 _does_ exist for mtmsr; it's just that no 32-bit
"classic"
implementations support it.
Segher
^ permalink raw reply [flat|nested] 227+ messages in thread
* [PATCH 26/26] KVM: PPC: Add Documentation about PV interface
2010-06-25 23:24 ` Alexander Graf
(?)
@ 2010-06-25 23:25 ` Alexander Graf
-1 siblings, 0 replies; 227+ messages in thread
From: Alexander Graf @ 2010-06-25 23:25 UTC (permalink / raw)
To: kvm-ppc-u79uwXL29TY76Z2rM5mHXA; +Cc: KVM list, linuxppc-dev
We just introduced a new PV interface that screams for documentation. So here
it is - a shiny new and awesome text file describing the internal works of
the PPC KVM paravirtual interface.
Signed-off-by: Alexander Graf <agraf@suse.de>
---
Documentation/kvm/ppc-pv.txt | 164 ++++++++++++++++++++++++++++++++++++++++++
1 files changed, 164 insertions(+), 0 deletions(-)
create mode 100644 Documentation/kvm/ppc-pv.txt
diff --git a/Documentation/kvm/ppc-pv.txt b/Documentation/kvm/ppc-pv.txt
new file mode 100644
index 0000000..7cbcd51
--- /dev/null
+++ b/Documentation/kvm/ppc-pv.txt
@@ -0,0 +1,164 @@
+The PPC KVM paravirtual interface
+================+
+The basic execution principle by which KVM on PowerPC works is to run all kernel
+space code in PR=1 which is user space. This way we trap all privileged
+instructions and can emulate them accordingly.
+
+Unfortunately that is also the downfall. There are quite some privileged
+instructions that needlessly return us to the hypervisor even though they
+could be handled differently.
+
+This is what the PPC PV interface helps with. It takes privileged instructions
+and transforms them into unprivileged ones with some help from the hypervisor.
+This cuts down virtualization costs by about 50% on some of my benchmarks.
+
+The code for that interface can be found in arch/powerpc/kernel/kvm*
+
+Querying for existence
+===========
+
+To find out if we're running on KVM or not, we overlay the PVR register. Usually
+the PVR register contains an id that identifies your CPU type. If, however, you
+pass KVM_PVR_PARA in the register that you want the PVR result in, the register
+still contains KVM_PVR_PARA after the mfpvr call.
+
+ LOAD_REG_IMM(r5, KVM_PVR_PARA)
+ mfpvr r5
+ [r5 still contains KVM_PVR_PARA]
+
+Once determined to run under a PV capable KVM, you can now use hypercalls as
+described below.
+
+PPC hypercalls
+=======
+
+The only viable ways to reliably get from guest context to host context are:
+
+ 1) Call an invalid instruction
+ 2) Call the "sc" instruction with a parameter to "sc"
+ 3) Call the "sc" instruction with parameters in GPRs
+
+Method 1 is always a bad idea. Invalid instructions can be replaced later on
+by valid instructions, rendering the interface broken.
+
+Method 2 also has downfalls. If the parameter to "sc" is != 0 the spec is
+rather unclear if the sc is targeted directly for the hypervisor or the
+supervisor. It would also require that we read the syscall issuing instruction
+every time a syscall is issued, slowing down guest syscalls.
+
+Method 3 is what KVM uses. We pass magic constants (KVM_SC_MAGIC_R3 and
+KVM_SC_MAGIC_R4) in r3 and r4 respectively. If a syscall instruction with these
+magic values arrives from the guest's kernel mode, we take the syscall as a
+hypercall.
+
+The parameters are as follows:
+
+ r3 KVM_SC_MAGIC_R3
+ r4 KVM_SC_MAGIC_R4
+ r5 Hypercall number
+ r6 First parameter
+ r7 Second parameter
+ r8 Third parameter
+ r9 Fourth parameter
+
+Hypercall definitions are shared in generic code, so the same hypercall numbers
+apply for x86 and powerpc alike.
+
+The magic page
+=======
+
+To enable communication between the hypervisor and guest there is a new shared
+page that contains parts of supervisor visible register state. The guest can
+map this shared page using the KVM hypercall KVM_HC_PPC_MAP_MAGIC_PAGE.
+
+With this hypercall issued the guest always gets the magic page mapped at the
+desired location in effective and physical address space. For now, we always
+map the page to -4096. This way we can access it using absolute load and store
+functions. The following instruction reads the first field of the magic page:
+
+ ld rX, -4096(0)
+
+The interface is designed to be extensible should there be need later to add
+additional registers to the magic page. If you add fields to the magic page,
+also define a new hypercall feature to indicate that the host can give you more
+registers. Only if the host supports the additional features, make use of them.
+
+The magic page has the following layout as described in
+arch/powerpc/include/asm/kvm_para.h:
+
+struct kvm_vcpu_arch_shared {
+ __u64 scratch1;
+ __u64 scratch2;
+ __u64 scratch3;
+ __u64 critical; /* Guest may not get interrupts if = r1 */
+ __u64 sprg0;
+ __u64 sprg1;
+ __u64 sprg2;
+ __u64 sprg3;
+ __u64 srr0;
+ __u64 srr1;
+ __u64 dar;
+ __u64 msr;
+ __u32 dsisr;
+ __u32 int_pending; /* Tells the guest if we have an interrupt */
+};
+
+Additions to the page must only occur at the end. Struct fields are always 32
+bit aligned.
+
+Patched instructions
+==========
+
+The "ld" and "std" instructions are transormed to "lwz" and "stw" instructions
+respectively on 32 bit systems with an added offset of 4 to accomodate for big
+endianness.
+
+From To
+== =
+
+mfmsr rX ld rX, magic_page->msr
+mfsprg rX, 0 ld rX, magic_page->sprg0
+mfsprg rX, 1 ld rX, magic_page->sprg1
+mfsprg rX, 2 ld rX, magic_page->sprg2
+mfsprg rX, 3 ld rX, magic_page->sprg3
+mfsrr0 rX ld rX, magic_page->srr0
+mfsrr1 rX ld rX, magic_page->srr1
+mfdar rX ld rX, magic_page->dar
+mfdsisr rX ld rX, magic_page->dsisr
+
+mtmsr rX std rX, magic_page->msr
+mtsprg 0, rX std rX, magic_page->sprg0
+mtsprg 1, rX std rX, magic_page->sprg1
+mtsprg 2, rX std rX, magic_page->sprg2
+mtsprg 3, rX std rX, magic_page->sprg3
+mtsrr0 rX std rX, magic_page->srr0
+mtsrr1 rX std rX, magic_page->srr1
+mtdar rX std rX, magic_page->dar
+mtdsisr rX std rX, magic_page->dsisr
+
+tlbsync nop
+
+mtmsrd rX, 0 b <special mtmsr section>
+mtmsr b <special mtmsr section>
+
+mtmsrd rX, 1 b <special mtmsrd section>
+
+[BookE only]
+wrteei [0|1] b <special wrteei section>
+
+
+Some instructions require more logic to determine what's going on than a load
+or store instruction can deliver. To enable patching of those, we keep some
+RAM around where we can live translate instructions to. What happens is the
+following:
+
+ 1) copy emulation code to memory
+ 2) patch that code to fit the emulated instruction
+ 3) patch that code to return to the original pc + 4
+ 4) patch the original instruction to branch to the new code
+
+That way we can inject an arbitrary amount of code as replacement for a single
+instruction. This allows us to check for pending interrupts when setting EE=1
+for example.
+
--
1.6.0.2
^ permalink raw reply related [flat|nested] 227+ messages in thread* [PATCH 26/26] KVM: PPC: Add Documentation about PV interface
@ 2010-06-25 23:25 ` Alexander Graf
0 siblings, 0 replies; 227+ messages in thread
From: Alexander Graf @ 2010-06-25 23:25 UTC (permalink / raw)
To: kvm-ppc-u79uwXL29TY76Z2rM5mHXA; +Cc: KVM list, linuxppc-dev
We just introduced a new PV interface that screams for documentation. So here
it is - a shiny new and awesome text file describing the internal works of
the PPC KVM paravirtual interface.
Signed-off-by: Alexander Graf <agraf-l3A5Bk7waGM@public.gmane.org>
---
Documentation/kvm/ppc-pv.txt | 164 ++++++++++++++++++++++++++++++++++++++++++
1 files changed, 164 insertions(+), 0 deletions(-)
create mode 100644 Documentation/kvm/ppc-pv.txt
diff --git a/Documentation/kvm/ppc-pv.txt b/Documentation/kvm/ppc-pv.txt
new file mode 100644
index 0000000..7cbcd51
--- /dev/null
+++ b/Documentation/kvm/ppc-pv.txt
@@ -0,0 +1,164 @@
+The PPC KVM paravirtual interface
+=================================
+
+The basic execution principle by which KVM on PowerPC works is to run all kernel
+space code in PR=1 which is user space. This way we trap all privileged
+instructions and can emulate them accordingly.
+
+Unfortunately that is also the downfall. There are quite some privileged
+instructions that needlessly return us to the hypervisor even though they
+could be handled differently.
+
+This is what the PPC PV interface helps with. It takes privileged instructions
+and transforms them into unprivileged ones with some help from the hypervisor.
+This cuts down virtualization costs by about 50% on some of my benchmarks.
+
+The code for that interface can be found in arch/powerpc/kernel/kvm*
+
+Querying for existence
+======================
+
+To find out if we're running on KVM or not, we overlay the PVR register. Usually
+the PVR register contains an id that identifies your CPU type. If, however, you
+pass KVM_PVR_PARA in the register that you want the PVR result in, the register
+still contains KVM_PVR_PARA after the mfpvr call.
+
+ LOAD_REG_IMM(r5, KVM_PVR_PARA)
+ mfpvr r5
+ [r5 still contains KVM_PVR_PARA]
+
+Once determined to run under a PV capable KVM, you can now use hypercalls as
+described below.
+
+PPC hypercalls
+==============
+
+The only viable ways to reliably get from guest context to host context are:
+
+ 1) Call an invalid instruction
+ 2) Call the "sc" instruction with a parameter to "sc"
+ 3) Call the "sc" instruction with parameters in GPRs
+
+Method 1 is always a bad idea. Invalid instructions can be replaced later on
+by valid instructions, rendering the interface broken.
+
+Method 2 also has downfalls. If the parameter to "sc" is != 0 the spec is
+rather unclear if the sc is targeted directly for the hypervisor or the
+supervisor. It would also require that we read the syscall issuing instruction
+every time a syscall is issued, slowing down guest syscalls.
+
+Method 3 is what KVM uses. We pass magic constants (KVM_SC_MAGIC_R3 and
+KVM_SC_MAGIC_R4) in r3 and r4 respectively. If a syscall instruction with these
+magic values arrives from the guest's kernel mode, we take the syscall as a
+hypercall.
+
+The parameters are as follows:
+
+ r3 KVM_SC_MAGIC_R3
+ r4 KVM_SC_MAGIC_R4
+ r5 Hypercall number
+ r6 First parameter
+ r7 Second parameter
+ r8 Third parameter
+ r9 Fourth parameter
+
+Hypercall definitions are shared in generic code, so the same hypercall numbers
+apply for x86 and powerpc alike.
+
+The magic page
+==============
+
+To enable communication between the hypervisor and guest there is a new shared
+page that contains parts of supervisor visible register state. The guest can
+map this shared page using the KVM hypercall KVM_HC_PPC_MAP_MAGIC_PAGE.
+
+With this hypercall issued the guest always gets the magic page mapped at the
+desired location in effective and physical address space. For now, we always
+map the page to -4096. This way we can access it using absolute load and store
+functions. The following instruction reads the first field of the magic page:
+
+ ld rX, -4096(0)
+
+The interface is designed to be extensible should there be need later to add
+additional registers to the magic page. If you add fields to the magic page,
+also define a new hypercall feature to indicate that the host can give you more
+registers. Only if the host supports the additional features, make use of them.
+
+The magic page has the following layout as described in
+arch/powerpc/include/asm/kvm_para.h:
+
+struct kvm_vcpu_arch_shared {
+ __u64 scratch1;
+ __u64 scratch2;
+ __u64 scratch3;
+ __u64 critical; /* Guest may not get interrupts if == r1 */
+ __u64 sprg0;
+ __u64 sprg1;
+ __u64 sprg2;
+ __u64 sprg3;
+ __u64 srr0;
+ __u64 srr1;
+ __u64 dar;
+ __u64 msr;
+ __u32 dsisr;
+ __u32 int_pending; /* Tells the guest if we have an interrupt */
+};
+
+Additions to the page must only occur at the end. Struct fields are always 32
+bit aligned.
+
+Patched instructions
+====================
+
+The "ld" and "std" instructions are transormed to "lwz" and "stw" instructions
+respectively on 32 bit systems with an added offset of 4 to accomodate for big
+endianness.
+
+From To
+==== ==
+
+mfmsr rX ld rX, magic_page->msr
+mfsprg rX, 0 ld rX, magic_page->sprg0
+mfsprg rX, 1 ld rX, magic_page->sprg1
+mfsprg rX, 2 ld rX, magic_page->sprg2
+mfsprg rX, 3 ld rX, magic_page->sprg3
+mfsrr0 rX ld rX, magic_page->srr0
+mfsrr1 rX ld rX, magic_page->srr1
+mfdar rX ld rX, magic_page->dar
+mfdsisr rX ld rX, magic_page->dsisr
+
+mtmsr rX std rX, magic_page->msr
+mtsprg 0, rX std rX, magic_page->sprg0
+mtsprg 1, rX std rX, magic_page->sprg1
+mtsprg 2, rX std rX, magic_page->sprg2
+mtsprg 3, rX std rX, magic_page->sprg3
+mtsrr0 rX std rX, magic_page->srr0
+mtsrr1 rX std rX, magic_page->srr1
+mtdar rX std rX, magic_page->dar
+mtdsisr rX std rX, magic_page->dsisr
+
+tlbsync nop
+
+mtmsrd rX, 0 b <special mtmsr section>
+mtmsr b <special mtmsr section>
+
+mtmsrd rX, 1 b <special mtmsrd section>
+
+[BookE only]
+wrteei [0|1] b <special wrteei section>
+
+
+Some instructions require more logic to determine what's going on than a load
+or store instruction can deliver. To enable patching of those, we keep some
+RAM around where we can live translate instructions to. What happens is the
+following:
+
+ 1) copy emulation code to memory
+ 2) patch that code to fit the emulated instruction
+ 3) patch that code to return to the original pc + 4
+ 4) patch the original instruction to branch to the new code
+
+That way we can inject an arbitrary amount of code as replacement for a single
+instruction. This allows us to check for pending interrupts when setting EE=1
+for example.
+
--
1.6.0.2
^ permalink raw reply related [flat|nested] 227+ messages in thread* [PATCH 26/26] KVM: PPC: Add Documentation about PV interface
@ 2010-06-25 23:25 ` Alexander Graf
0 siblings, 0 replies; 227+ messages in thread
From: Alexander Graf @ 2010-06-25 23:25 UTC (permalink / raw)
To: kvm-ppc; +Cc: linuxppc-dev, KVM list
We just introduced a new PV interface that screams for documentation. So here
it is - a shiny new and awesome text file describing the internal works of
the PPC KVM paravirtual interface.
Signed-off-by: Alexander Graf <agraf@suse.de>
---
Documentation/kvm/ppc-pv.txt | 164 ++++++++++++++++++++++++++++++++++++++++++
1 files changed, 164 insertions(+), 0 deletions(-)
create mode 100644 Documentation/kvm/ppc-pv.txt
diff --git a/Documentation/kvm/ppc-pv.txt b/Documentation/kvm/ppc-pv.txt
new file mode 100644
index 0000000..7cbcd51
--- /dev/null
+++ b/Documentation/kvm/ppc-pv.txt
@@ -0,0 +1,164 @@
+The PPC KVM paravirtual interface
+=================================
+
+The basic execution principle by which KVM on PowerPC works is to run all kernel
+space code in PR=1 which is user space. This way we trap all privileged
+instructions and can emulate them accordingly.
+
+Unfortunately that is also the downfall. There are quite some privileged
+instructions that needlessly return us to the hypervisor even though they
+could be handled differently.
+
+This is what the PPC PV interface helps with. It takes privileged instructions
+and transforms them into unprivileged ones with some help from the hypervisor.
+This cuts down virtualization costs by about 50% on some of my benchmarks.
+
+The code for that interface can be found in arch/powerpc/kernel/kvm*
+
+Querying for existence
+======================
+
+To find out if we're running on KVM or not, we overlay the PVR register. Usually
+the PVR register contains an id that identifies your CPU type. If, however, you
+pass KVM_PVR_PARA in the register that you want the PVR result in, the register
+still contains KVM_PVR_PARA after the mfpvr call.
+
+ LOAD_REG_IMM(r5, KVM_PVR_PARA)
+ mfpvr r5
+ [r5 still contains KVM_PVR_PARA]
+
+Once determined to run under a PV capable KVM, you can now use hypercalls as
+described below.
+
+PPC hypercalls
+==============
+
+The only viable ways to reliably get from guest context to host context are:
+
+ 1) Call an invalid instruction
+ 2) Call the "sc" instruction with a parameter to "sc"
+ 3) Call the "sc" instruction with parameters in GPRs
+
+Method 1 is always a bad idea. Invalid instructions can be replaced later on
+by valid instructions, rendering the interface broken.
+
+Method 2 also has downfalls. If the parameter to "sc" is != 0 the spec is
+rather unclear if the sc is targeted directly for the hypervisor or the
+supervisor. It would also require that we read the syscall issuing instruction
+every time a syscall is issued, slowing down guest syscalls.
+
+Method 3 is what KVM uses. We pass magic constants (KVM_SC_MAGIC_R3 and
+KVM_SC_MAGIC_R4) in r3 and r4 respectively. If a syscall instruction with these
+magic values arrives from the guest's kernel mode, we take the syscall as a
+hypercall.
+
+The parameters are as follows:
+
+ r3 KVM_SC_MAGIC_R3
+ r4 KVM_SC_MAGIC_R4
+ r5 Hypercall number
+ r6 First parameter
+ r7 Second parameter
+ r8 Third parameter
+ r9 Fourth parameter
+
+Hypercall definitions are shared in generic code, so the same hypercall numbers
+apply for x86 and powerpc alike.
+
+The magic page
+==============
+
+To enable communication between the hypervisor and guest there is a new shared
+page that contains parts of supervisor visible register state. The guest can
+map this shared page using the KVM hypercall KVM_HC_PPC_MAP_MAGIC_PAGE.
+
+With this hypercall issued the guest always gets the magic page mapped at the
+desired location in effective and physical address space. For now, we always
+map the page to -4096. This way we can access it using absolute load and store
+functions. The following instruction reads the first field of the magic page:
+
+ ld rX, -4096(0)
+
+The interface is designed to be extensible should there be need later to add
+additional registers to the magic page. If you add fields to the magic page,
+also define a new hypercall feature to indicate that the host can give you more
+registers. Only if the host supports the additional features, make use of them.
+
+The magic page has the following layout as described in
+arch/powerpc/include/asm/kvm_para.h:
+
+struct kvm_vcpu_arch_shared {
+ __u64 scratch1;
+ __u64 scratch2;
+ __u64 scratch3;
+ __u64 critical; /* Guest may not get interrupts if == r1 */
+ __u64 sprg0;
+ __u64 sprg1;
+ __u64 sprg2;
+ __u64 sprg3;
+ __u64 srr0;
+ __u64 srr1;
+ __u64 dar;
+ __u64 msr;
+ __u32 dsisr;
+ __u32 int_pending; /* Tells the guest if we have an interrupt */
+};
+
+Additions to the page must only occur at the end. Struct fields are always 32
+bit aligned.
+
+Patched instructions
+====================
+
+The "ld" and "std" instructions are transormed to "lwz" and "stw" instructions
+respectively on 32 bit systems with an added offset of 4 to accomodate for big
+endianness.
+
+From To
+==== ==
+
+mfmsr rX ld rX, magic_page->msr
+mfsprg rX, 0 ld rX, magic_page->sprg0
+mfsprg rX, 1 ld rX, magic_page->sprg1
+mfsprg rX, 2 ld rX, magic_page->sprg2
+mfsprg rX, 3 ld rX, magic_page->sprg3
+mfsrr0 rX ld rX, magic_page->srr0
+mfsrr1 rX ld rX, magic_page->srr1
+mfdar rX ld rX, magic_page->dar
+mfdsisr rX ld rX, magic_page->dsisr
+
+mtmsr rX std rX, magic_page->msr
+mtsprg 0, rX std rX, magic_page->sprg0
+mtsprg 1, rX std rX, magic_page->sprg1
+mtsprg 2, rX std rX, magic_page->sprg2
+mtsprg 3, rX std rX, magic_page->sprg3
+mtsrr0 rX std rX, magic_page->srr0
+mtsrr1 rX std rX, magic_page->srr1
+mtdar rX std rX, magic_page->dar
+mtdsisr rX std rX, magic_page->dsisr
+
+tlbsync nop
+
+mtmsrd rX, 0 b <special mtmsr section>
+mtmsr b <special mtmsr section>
+
+mtmsrd rX, 1 b <special mtmsrd section>
+
+[BookE only]
+wrteei [0|1] b <special wrteei section>
+
+
+Some instructions require more logic to determine what's going on than a load
+or store instruction can deliver. To enable patching of those, we keep some
+RAM around where we can live translate instructions to. What happens is the
+following:
+
+ 1) copy emulation code to memory
+ 2) patch that code to fit the emulated instruction
+ 3) patch that code to return to the original pc + 4
+ 4) patch the original instruction to branch to the new code
+
+That way we can inject an arbitrary amount of code as replacement for a single
+instruction. This allows us to check for pending interrupts when setting EE=1
+for example.
+
--
1.6.0.2
^ permalink raw reply related [flat|nested] 227+ messages in thread* Re: [PATCH 26/26] KVM: PPC: Add Documentation about PV interface
2010-06-25 23:25 ` Alexander Graf
@ 2010-06-27 8:14 ` Avi Kivity
-1 siblings, 0 replies; 227+ messages in thread
From: Avi Kivity @ 2010-06-27 8:14 UTC (permalink / raw)
To: Alexander Graf; +Cc: linuxppc-dev, KVM list, kvm-ppc
On 06/26/2010 02:25 AM, Alexander Graf wrote:
> We just introduced a new PV interface that screams for documentation. So here
> it is - a shiny new and awesome text file describing the internal works of
> the PPC KVM paravirtual interface.
>
Good, that lets people who have no idea what they're talking about
participate in the review.
> +
> +PPC hypercalls
> +=======
> +
> +The only viable ways to reliably get from guest context to host context are:
> +
> + 1) Call an invalid instruction
> + 2) Call the "sc" instruction with a parameter to "sc"
> + 3) Call the "sc" instruction with parameters in GPRs
> +
> +Method 1 is always a bad idea. Invalid instructions can be replaced later on
> +by valid instructions, rendering the interface broken.
> +
> +Method 2 also has downfalls. If the parameter to "sc" is != 0 the spec is
> +rather unclear if the sc is targeted directly for the hypervisor or the
> +supervisor. It would also require that we read the syscall issuing instruction
> +every time a syscall is issued, slowing down guest syscalls.
> +
> +Method 3 is what KVM uses. We pass magic constants (KVM_SC_MAGIC_R3 and
> +KVM_SC_MAGIC_R4) in r3 and r4 respectively. If a syscall instruction with these
> +magic values arrives from the guest's kernel mode, we take the syscall as a
> +hypercall.
>
Is there any chance a normal syscall will have those values in r3 and r4?
If so, maybe it's better to use pc as they key for hypercalls. Let the
guest designate one instruction address as the hypercall call point; kvm
can easily check it and reflect it back to the guest if it doesn't match.
Is it valid and useful to issue sc from privileged mode anyway, except
for calling the hypervisor?
> +
> +The parameters are as follows:
> +
> + r3 KVM_SC_MAGIC_R3
> + r4 KVM_SC_MAGIC_R4
> + r5 Hypercall number
> + r6 First parameter
> + r7 Second parameter
> + r8 Third parameter
> + r9 Fourth parameter
> +
> +Hypercall definitions are shared in generic code, so the same hypercall numbers
> +apply for x86 and powerpc alike.
>
Addresses passed in hypercall paramters are guest physical addresses.
Do you have >32 bit physical addresses on 32-bit guests? if so, you'll
need to pass physical addresses in two registers.
> +
> +The magic page
> +=======
> +
> +To enable communication between the hypervisor and guest there is a new shared
> +page that contains parts of supervisor visible register state. The guest can
> +map this shared page using the KVM hypercall KVM_HC_PPC_MAP_MAGIC_PAGE.
> +
> +With this hypercall issued the guest always gets the magic page mapped at the
> +desired location in effective and physical address space. For now, we always
> +map the page to -4096. This way we can access it using absolute load and store
> +functions. The following instruction reads the first field of the magic page:
> +
> + ld rX, -4096(0)
>
Is the address guest controlled or host controlled?
> +
> +The interface is designed to be extensible should there be need later to add
> +additional registers to the magic page. If you add fields to the magic page,
> +also define a new hypercall feature to indicate that the host can give you more
> +registers. Only if the host supports the additional features, make use of them.
> +
> +The magic page has the following layout as described in
> +arch/powerpc/include/asm/kvm_para.h:
> +
> +struct kvm_vcpu_arch_shared {
> + __u64 scratch1;
> + __u64 scratch2;
> + __u64 scratch3;
> + __u64 critical; /* Guest may not get interrupts if = r1 */
>
Elaborate?
> + __u64 sprg0;
> + __u64 sprg1;
> + __u64 sprg2;
> + __u64 sprg3;
> + __u64 srr0;
> + __u64 srr1;
> + __u64 dar;
> + __u64 msr;
> + __u32 dsisr;
> + __u32 int_pending; /* Tells the guest if we have an interrupt */
> +};
> +
> +Additions to the page must only occur at the end. Struct fields are always 32
> +bit aligned.
> +
> +Patched instructions
> +==========
> +
> +The "ld" and "std" instructions are transormed to "lwz" and "stw" instructions
> +respectively on 32 bit systems with an added offset of 4 to accomodate for big
> +endianness.
>
Who does the patching? guest or host?
> +
> +From To
> +== =
> +
> +mfmsr rX ld rX, magic_page->msr
> +mfsprg rX, 0 ld rX, magic_page->sprg0
> +mfsprg rX, 1 ld rX, magic_page->sprg1
> +mfsprg rX, 2 ld rX, magic_page->sprg2
> +mfsprg rX, 3 ld rX, magic_page->sprg3
> +mfsrr0 rX ld rX, magic_page->srr0
> +mfsrr1 rX ld rX, magic_page->srr1
> +mfdar rX ld rX, magic_page->dar
> +mfdsisr rX ld rX, magic_page->dsisr
> +
> +mtmsr rX std rX, magic_page->msr
> +mtsprg 0, rX std rX, magic_page->sprg0
> +mtsprg 1, rX std rX, magic_page->sprg1
> +mtsprg 2, rX std rX, magic_page->sprg2
> +mtsprg 3, rX std rX, magic_page->sprg3
> +mtsrr0 rX std rX, magic_page->srr0
> +mtsrr1 rX std rX, magic_page->srr1
> +mtdar rX std rX, magic_page->dar
> +mtdsisr rX std rX, magic_page->dsisr
> +
> +tlbsync nop
> +
> +mtmsrd rX, 0 b <special mtmsr section>
> +mtmsr b <special mtmsr section>
> +
> +mtmsrd rX, 1 b <special mtmsrd section>
> +
> +[BookE only]
> +wrteei [0|1] b <special wrteei section>
>
Probably the guest, as only it can arrange for special * sections. Good.
> +
> +Some instructions require more logic to determine what's going on than a load
> +or store instruction can deliver. To enable patching of those, we keep some
> +RAM around where we can live translate instructions to. What happens is the
> +following:
> +
> + 1) copy emulation code to memory
> + 2) patch that code to fit the emulated instruction
> + 3) patch that code to return to the original pc + 4
> + 4) patch the original instruction to branch to the new code
> +
> +That way we can inject an arbitrary amount of code as replacement for a single
> +instruction. This allows us to check for pending interrupts when setting EE=1
> +for example.
> +
>
Or not.
What about transitions from paravirt to non-paravirt? For example, a
system reset.
--
error compiling committee.c: too many arguments to function
^ permalink raw reply [flat|nested] 227+ messages in thread* Re: [PATCH 26/26] KVM: PPC: Add Documentation about PV interface
@ 2010-06-27 8:14 ` Avi Kivity
0 siblings, 0 replies; 227+ messages in thread
From: Avi Kivity @ 2010-06-27 8:14 UTC (permalink / raw)
To: Alexander Graf; +Cc: linuxppc-dev, KVM list, kvm-ppc
On 06/26/2010 02:25 AM, Alexander Graf wrote:
> We just introduced a new PV interface that screams for documentation. So here
> it is - a shiny new and awesome text file describing the internal works of
> the PPC KVM paravirtual interface.
>
Good, that lets people who have no idea what they're talking about
participate in the review.
> +
> +PPC hypercalls
> +==============
> +
> +The only viable ways to reliably get from guest context to host context are:
> +
> + 1) Call an invalid instruction
> + 2) Call the "sc" instruction with a parameter to "sc"
> + 3) Call the "sc" instruction with parameters in GPRs
> +
> +Method 1 is always a bad idea. Invalid instructions can be replaced later on
> +by valid instructions, rendering the interface broken.
> +
> +Method 2 also has downfalls. If the parameter to "sc" is != 0 the spec is
> +rather unclear if the sc is targeted directly for the hypervisor or the
> +supervisor. It would also require that we read the syscall issuing instruction
> +every time a syscall is issued, slowing down guest syscalls.
> +
> +Method 3 is what KVM uses. We pass magic constants (KVM_SC_MAGIC_R3 and
> +KVM_SC_MAGIC_R4) in r3 and r4 respectively. If a syscall instruction with these
> +magic values arrives from the guest's kernel mode, we take the syscall as a
> +hypercall.
>
Is there any chance a normal syscall will have those values in r3 and r4?
If so, maybe it's better to use pc as they key for hypercalls. Let the
guest designate one instruction address as the hypercall call point; kvm
can easily check it and reflect it back to the guest if it doesn't match.
Is it valid and useful to issue sc from privileged mode anyway, except
for calling the hypervisor?
> +
> +The parameters are as follows:
> +
> + r3 KVM_SC_MAGIC_R3
> + r4 KVM_SC_MAGIC_R4
> + r5 Hypercall number
> + r6 First parameter
> + r7 Second parameter
> + r8 Third parameter
> + r9 Fourth parameter
> +
> +Hypercall definitions are shared in generic code, so the same hypercall numbers
> +apply for x86 and powerpc alike.
>
Addresses passed in hypercall paramters are guest physical addresses.
Do you have >32 bit physical addresses on 32-bit guests? if so, you'll
need to pass physical addresses in two registers.
> +
> +The magic page
> +==============
> +
> +To enable communication between the hypervisor and guest there is a new shared
> +page that contains parts of supervisor visible register state. The guest can
> +map this shared page using the KVM hypercall KVM_HC_PPC_MAP_MAGIC_PAGE.
> +
> +With this hypercall issued the guest always gets the magic page mapped at the
> +desired location in effective and physical address space. For now, we always
> +map the page to -4096. This way we can access it using absolute load and store
> +functions. The following instruction reads the first field of the magic page:
> +
> + ld rX, -4096(0)
>
Is the address guest controlled or host controlled?
> +
> +The interface is designed to be extensible should there be need later to add
> +additional registers to the magic page. If you add fields to the magic page,
> +also define a new hypercall feature to indicate that the host can give you more
> +registers. Only if the host supports the additional features, make use of them.
> +
> +The magic page has the following layout as described in
> +arch/powerpc/include/asm/kvm_para.h:
> +
> +struct kvm_vcpu_arch_shared {
> + __u64 scratch1;
> + __u64 scratch2;
> + __u64 scratch3;
> + __u64 critical; /* Guest may not get interrupts if == r1 */
>
Elaborate?
> + __u64 sprg0;
> + __u64 sprg1;
> + __u64 sprg2;
> + __u64 sprg3;
> + __u64 srr0;
> + __u64 srr1;
> + __u64 dar;
> + __u64 msr;
> + __u32 dsisr;
> + __u32 int_pending; /* Tells the guest if we have an interrupt */
> +};
> +
> +Additions to the page must only occur at the end. Struct fields are always 32
> +bit aligned.
> +
> +Patched instructions
> +====================
> +
> +The "ld" and "std" instructions are transormed to "lwz" and "stw" instructions
> +respectively on 32 bit systems with an added offset of 4 to accomodate for big
> +endianness.
>
Who does the patching? guest or host?
> +
> +From To
> +==== ==
> +
> +mfmsr rX ld rX, magic_page->msr
> +mfsprg rX, 0 ld rX, magic_page->sprg0
> +mfsprg rX, 1 ld rX, magic_page->sprg1
> +mfsprg rX, 2 ld rX, magic_page->sprg2
> +mfsprg rX, 3 ld rX, magic_page->sprg3
> +mfsrr0 rX ld rX, magic_page->srr0
> +mfsrr1 rX ld rX, magic_page->srr1
> +mfdar rX ld rX, magic_page->dar
> +mfdsisr rX ld rX, magic_page->dsisr
> +
> +mtmsr rX std rX, magic_page->msr
> +mtsprg 0, rX std rX, magic_page->sprg0
> +mtsprg 1, rX std rX, magic_page->sprg1
> +mtsprg 2, rX std rX, magic_page->sprg2
> +mtsprg 3, rX std rX, magic_page->sprg3
> +mtsrr0 rX std rX, magic_page->srr0
> +mtsrr1 rX std rX, magic_page->srr1
> +mtdar rX std rX, magic_page->dar
> +mtdsisr rX std rX, magic_page->dsisr
> +
> +tlbsync nop
> +
> +mtmsrd rX, 0 b <special mtmsr section>
> +mtmsr b <special mtmsr section>
> +
> +mtmsrd rX, 1 b <special mtmsrd section>
> +
> +[BookE only]
> +wrteei [0|1] b <special wrteei section>
>
Probably the guest, as only it can arrange for special * sections. Good.
> +
> +Some instructions require more logic to determine what's going on than a load
> +or store instruction can deliver. To enable patching of those, we keep some
> +RAM around where we can live translate instructions to. What happens is the
> +following:
> +
> + 1) copy emulation code to memory
> + 2) patch that code to fit the emulated instruction
> + 3) patch that code to return to the original pc + 4
> + 4) patch the original instruction to branch to the new code
> +
> +That way we can inject an arbitrary amount of code as replacement for a single
> +instruction. This allows us to check for pending interrupts when setting EE=1
> +for example.
> +
>
Or not.
What about transitions from paravirt to non-paravirt? For example, a
system reset.
--
error compiling committee.c: too many arguments to function
^ permalink raw reply [flat|nested] 227+ messages in thread[parent not found: <4C270876.2050806-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>]
* Re: [PATCH 26/26] KVM: PPC: Add Documentation about PV interface
2010-06-27 8:14 ` Avi Kivity
(?)
@ 2010-06-27 9:33 ` Alexander Graf
-1 siblings, 0 replies; 227+ messages in thread
From: Alexander Graf @ 2010-06-27 9:33 UTC (permalink / raw)
To: Avi Kivity
Cc: kvm-ppc-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, KVM list,
linuxppc-dev
Am 27.06.2010 um 10:14 schrieb Avi Kivity <avi@redhat.com>:
> On 06/26/2010 02:25 AM, Alexander Graf wrote:
>> We just introduced a new PV interface that screams for
>> documentation. So here
>> it is - a shiny new and awesome text file describing the internal
>> works of
>> the PPC KVM paravirtual interface.
>>
>
> Good, that lets people who have no idea what they're talking about
> participate in the review.
Heh, I knew you'd like this :).
>
>> +
>> +PPC hypercalls
>> +=======
>> +
>> +The only viable ways to reliably get from guest context to host
>> context are:
>> +
>> + 1) Call an invalid instruction
>> + 2) Call the "sc" instruction with a parameter to "sc"
>> + 3) Call the "sc" instruction with parameters in GPRs
>> +
>> +Method 1 is always a bad idea. Invalid instructions can be
>> replaced later on
>> +by valid instructions, rendering the interface broken.
>> +
>> +Method 2 also has downfalls. If the parameter to "sc" is != 0 the
>> spec is
>> +rather unclear if the sc is targeted directly for the hypervisor
>> or the
>> +supervisor. It would also require that we read the syscall issuing
>> instruction
>> +every time a syscall is issued, slowing down guest syscalls.
>> +
>> +Method 3 is what KVM uses. We pass magic constants
>> (KVM_SC_MAGIC_R3 and
>> +KVM_SC_MAGIC_R4) in r3 and r4 respectively. If a syscall
>> instruction with these
>> +magic values arrives from the guest's kernel mode, we take the
>> syscall as a
>> +hypercall.
>>
>
> Is there any chance a normal syscall will have those values in r3
> and r4?
r3 is the syscall number. So as long as the guest doesn't reuse that
value, we're safe. Since in general syscall numbers are not randomly
scattered throughout the number range, we should be ok here.
>
> If so, maybe it's better to use pc as they key for hypercalls. Let
> the guest designate one instruction address as the hypercall call
> point; kvm can easily check it and reflect it back to the guest if
> it doesn't match.
>
You mean the guest would tell the hv where the hypercall lies? That
would require a hypercall, no? Defining it statically is tricky. I
want to PV'nize osx using a kernel module later, so I don't have
control over the physical layout.
> Is it valid and useful to issue sc from privileged mode anyway,
> except for calling the hypervisor?
Same as a syscall on x86 really. The kernel can and does issue
syscalls within itself.
>
>> +
>> +The parameters are as follows:
>> +
>> + r3 KVM_SC_MAGIC_R3
>> + r4 KVM_SC_MAGIC_R4
>> + r5 Hypercall number
>> + r6 First parameter
>> + r7 Second parameter
>> + r8 Third parameter
>> + r9 Fourth parameter
>> +
>> +Hypercall definitions are shared in generic code, so the same
>> hypercall numbers
>> +apply for x86 and powerpc alike.
>>
>
> Addresses passed in hypercall paramters are guest physical addresses.
>
> Do you have >32 bit physical addresses on 32-bit guests? if so,
> you'll need to pass physical addresses in two registers.
I think theoretically it's possible. Will we ever support it?
Doubtful. Do we need to pass hogh memory addresses to the hv? Even
more doubtful.
If we hit such a case, I'd just disable the hypercall for 32 bit. Or
define param1 and param2 to contain the address if the guest is in 32-
bit mode. No need to always make all params 64 bit imho.
>
>> +
>> +The magic page
>> +=======
>> +
>> +To enable communication between the hypervisor and guest there is
>> a new shared
>> +page that contains parts of supervisor visible register state. The
>> guest can
>> +map this shared page using the KVM hypercall
>> KVM_HC_PPC_MAP_MAGIC_PAGE.
>> +
>> +With this hypercall issued the guest always gets the magic page
>> mapped at the
>> +desired location in effective and physical address space. For now,
>> we always
>> +map the page to -4096. This way we can access it using absolute
>> load and store
>> +functions. The following instruction reads the first field of the
>> magic page:
>> +
>> + ld rX, -4096(0)
>>
>
> Is the address guest controlled or host controlled?
Guest controlled. It's passed in to the map_magic_page hypercall.
>
>> +
>> +The interface is designed to be extensible should there be need
>> later to add
>> +additional registers to the magic page. If you add fields to the
>> magic page,
>> +also define a new hypercall feature to indicate that the host can
>> give you more
>> +registers. Only if the host supports the additional features, make
>> use of them.
>> +
>> +The magic page has the following layout as described in
>> +arch/powerpc/include/asm/kvm_para.h:
>> +
>> +struct kvm_vcpu_arch_shared {
>> + __u64 scratch1;
>> + __u64 scratch2;
>> + __u64 scratch3;
>> + __u64 critical; /* Guest may not get interrupts if =
>> r1 */
>>
>
> Elaborate?
I think I have a description in the respective patch. Probably a good
idea to add it to the documentation.
>
>> + __u64 sprg0;
>> + __u64 sprg1;
>> + __u64 sprg2;
>> + __u64 sprg3;
>> + __u64 srr0;
>> + __u64 srr1;
>> + __u64 dar;
>> + __u64 msr;
>> + __u32 dsisr;
>> + __u32 int_pending; /* Tells the guest if we have an
>> interrupt */
>> +};
>> +
>> +Additions to the page must only occur at the end. Struct fields
>> are always 32
>> +bit aligned.
>> +
>> +Patched instructions
>> +==========
>> +
>> +The "ld" and "std" instructions are transormed to "lwz" and "stw"
>> instructions
>> +respectively on 32 bit systems with an added offset of 4 to
>> accomodate for big
>> +endianness.
>>
>
> Who does the patching? guest or host?
All patching is done by the guest. Probably worth mentioning, yeah.
>
>> +
>> +From To
>> +== =
>> +
>> +mfmsr rX ld rX, magic_page->msr
>> +mfsprg rX, 0 ld rX, magic_page->sprg0
>> +mfsprg rX, 1 ld rX, magic_page->sprg1
>> +mfsprg rX, 2 ld rX, magic_page->sprg2
>> +mfsprg rX, 3 ld rX, magic_page->sprg3
>> +mfsrr0 rX ld rX, magic_page->srr0
>> +mfsrr1 rX ld rX, magic_page->srr1
>> +mfdar rX ld rX, magic_page->dar
>> +mfdsisr rX ld rX, magic_page->dsisr
>> +
>> +mtmsr rX std rX, magic_page->msr
>> +mtsprg 0, rX std rX, magic_page->sprg0
>> +mtsprg 1, rX std rX, magic_page->sprg1
>> +mtsprg 2, rX std rX, magic_page->sprg2
>> +mtsprg 3, rX std rX, magic_page->sprg3
>> +mtsrr0 rX std rX, magic_page->srr0
>> +mtsrr1 rX std rX, magic_page->srr1
>> +mtdar rX std rX, magic_page->dar
>> +mtdsisr rX std rX, magic_page->dsisr
>> +
>> +tlbsync nop
>> +
>> +mtmsrd rX, 0 b <special mtmsr section>
>> +mtmsr b <special mtmsr section>
>> +
>> +mtmsrd rX, 1 b <special mtmsrd section>
>> +
>> +[BookE only]
>> +wrteei [0|1] b <special wrteei section>
>>
>
> Probably the guest, as only it can arrange for special * sections.
> Good.
>
>> +
>> +Some instructions require more logic to determine what's going on
>> than a load
>> +or store instruction can deliver. To enable patching of those, we
>> keep some
>> +RAM around where we can live translate instructions to. What
>> happens is the
>> +following:
>> +
>> + 1) copy emulation code to memory
>> + 2) patch that code to fit the emulated instruction
>> + 3) patch that code to return to the original pc + 4
>> + 4) patch the original instruction to branch to the new code
>> +
>> +That way we can inject an arbitrary amount of code as replacement
>> for a single
>> +instruction. This allows us to check for pending interrupts when
>> setting EE=1
>> +for example.
>> +
>>
>
> Or not.
>
> What about transitions from paravirt to non-paravirt? For example,
> a system reset.
That ... eh ... good question. It would leave the map pending, but
everything still continues working.
I don't really know in kvm when a reset occured. So we have to make
qemu set the map to 0 on reset. Let's add then when we add migration
support and actually expose all those missing states to userspace.
Currently we only expose half the necessary state for migration
anyway :).
Alex
^ permalink raw reply [flat|nested] 227+ messages in thread* Re: [PATCH 26/26] KVM: PPC: Add Documentation about PV interface
@ 2010-06-27 9:33 ` Alexander Graf
0 siblings, 0 replies; 227+ messages in thread
From: Alexander Graf @ 2010-06-27 9:33 UTC (permalink / raw)
To: Avi Kivity
Cc: kvm-ppc-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, KVM list,
linuxppc-dev
Am 27.06.2010 um 10:14 schrieb Avi Kivity <avi-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>:
> On 06/26/2010 02:25 AM, Alexander Graf wrote:
>> We just introduced a new PV interface that screams for
>> documentation. So here
>> it is - a shiny new and awesome text file describing the internal
>> works of
>> the PPC KVM paravirtual interface.
>>
>
> Good, that lets people who have no idea what they're talking about
> participate in the review.
Heh, I knew you'd like this :).
>
>> +
>> +PPC hypercalls
>> +==============
>> +
>> +The only viable ways to reliably get from guest context to host
>> context are:
>> +
>> + 1) Call an invalid instruction
>> + 2) Call the "sc" instruction with a parameter to "sc"
>> + 3) Call the "sc" instruction with parameters in GPRs
>> +
>> +Method 1 is always a bad idea. Invalid instructions can be
>> replaced later on
>> +by valid instructions, rendering the interface broken.
>> +
>> +Method 2 also has downfalls. If the parameter to "sc" is != 0 the
>> spec is
>> +rather unclear if the sc is targeted directly for the hypervisor
>> or the
>> +supervisor. It would also require that we read the syscall issuing
>> instruction
>> +every time a syscall is issued, slowing down guest syscalls.
>> +
>> +Method 3 is what KVM uses. We pass magic constants
>> (KVM_SC_MAGIC_R3 and
>> +KVM_SC_MAGIC_R4) in r3 and r4 respectively. If a syscall
>> instruction with these
>> +magic values arrives from the guest's kernel mode, we take the
>> syscall as a
>> +hypercall.
>>
>
> Is there any chance a normal syscall will have those values in r3
> and r4?
r3 is the syscall number. So as long as the guest doesn't reuse that
value, we're safe. Since in general syscall numbers are not randomly
scattered throughout the number range, we should be ok here.
>
> If so, maybe it's better to use pc as they key for hypercalls. Let
> the guest designate one instruction address as the hypercall call
> point; kvm can easily check it and reflect it back to the guest if
> it doesn't match.
>
You mean the guest would tell the hv where the hypercall lies? That
would require a hypercall, no? Defining it statically is tricky. I
want to PV'nize osx using a kernel module later, so I don't have
control over the physical layout.
> Is it valid and useful to issue sc from privileged mode anyway,
> except for calling the hypervisor?
Same as a syscall on x86 really. The kernel can and does issue
syscalls within itself.
>
>> +
>> +The parameters are as follows:
>> +
>> + r3 KVM_SC_MAGIC_R3
>> + r4 KVM_SC_MAGIC_R4
>> + r5 Hypercall number
>> + r6 First parameter
>> + r7 Second parameter
>> + r8 Third parameter
>> + r9 Fourth parameter
>> +
>> +Hypercall definitions are shared in generic code, so the same
>> hypercall numbers
>> +apply for x86 and powerpc alike.
>>
>
> Addresses passed in hypercall paramters are guest physical addresses.
>
> Do you have >32 bit physical addresses on 32-bit guests? if so,
> you'll need to pass physical addresses in two registers.
I think theoretically it's possible. Will we ever support it?
Doubtful. Do we need to pass hogh memory addresses to the hv? Even
more doubtful.
If we hit such a case, I'd just disable the hypercall for 32 bit. Or
define param1 and param2 to contain the address if the guest is in 32-
bit mode. No need to always make all params 64 bit imho.
>
>> +
>> +The magic page
>> +==============
>> +
>> +To enable communication between the hypervisor and guest there is
>> a new shared
>> +page that contains parts of supervisor visible register state. The
>> guest can
>> +map this shared page using the KVM hypercall
>> KVM_HC_PPC_MAP_MAGIC_PAGE.
>> +
>> +With this hypercall issued the guest always gets the magic page
>> mapped at the
>> +desired location in effective and physical address space. For now,
>> we always
>> +map the page to -4096. This way we can access it using absolute
>> load and store
>> +functions. The following instruction reads the first field of the
>> magic page:
>> +
>> + ld rX, -4096(0)
>>
>
> Is the address guest controlled or host controlled?
Guest controlled. It's passed in to the map_magic_page hypercall.
>
>> +
>> +The interface is designed to be extensible should there be need
>> later to add
>> +additional registers to the magic page. If you add fields to the
>> magic page,
>> +also define a new hypercall feature to indicate that the host can
>> give you more
>> +registers. Only if the host supports the additional features, make
>> use of them.
>> +
>> +The magic page has the following layout as described in
>> +arch/powerpc/include/asm/kvm_para.h:
>> +
>> +struct kvm_vcpu_arch_shared {
>> + __u64 scratch1;
>> + __u64 scratch2;
>> + __u64 scratch3;
>> + __u64 critical; /* Guest may not get interrupts if ==
>> r1 */
>>
>
> Elaborate?
I think I have a description in the respective patch. Probably a good
idea to add it to the documentation.
>
>> + __u64 sprg0;
>> + __u64 sprg1;
>> + __u64 sprg2;
>> + __u64 sprg3;
>> + __u64 srr0;
>> + __u64 srr1;
>> + __u64 dar;
>> + __u64 msr;
>> + __u32 dsisr;
>> + __u32 int_pending; /* Tells the guest if we have an
>> interrupt */
>> +};
>> +
>> +Additions to the page must only occur at the end. Struct fields
>> are always 32
>> +bit aligned.
>> +
>> +Patched instructions
>> +====================
>> +
>> +The "ld" and "std" instructions are transormed to "lwz" and "stw"
>> instructions
>> +respectively on 32 bit systems with an added offset of 4 to
>> accomodate for big
>> +endianness.
>>
>
> Who does the patching? guest or host?
All patching is done by the guest. Probably worth mentioning, yeah.
>
>> +
>> +From To
>> +==== ==
>> +
>> +mfmsr rX ld rX, magic_page->msr
>> +mfsprg rX, 0 ld rX, magic_page->sprg0
>> +mfsprg rX, 1 ld rX, magic_page->sprg1
>> +mfsprg rX, 2 ld rX, magic_page->sprg2
>> +mfsprg rX, 3 ld rX, magic_page->sprg3
>> +mfsrr0 rX ld rX, magic_page->srr0
>> +mfsrr1 rX ld rX, magic_page->srr1
>> +mfdar rX ld rX, magic_page->dar
>> +mfdsisr rX ld rX, magic_page->dsisr
>> +
>> +mtmsr rX std rX, magic_page->msr
>> +mtsprg 0, rX std rX, magic_page->sprg0
>> +mtsprg 1, rX std rX, magic_page->sprg1
>> +mtsprg 2, rX std rX, magic_page->sprg2
>> +mtsprg 3, rX std rX, magic_page->sprg3
>> +mtsrr0 rX std rX, magic_page->srr0
>> +mtsrr1 rX std rX, magic_page->srr1
>> +mtdar rX std rX, magic_page->dar
>> +mtdsisr rX std rX, magic_page->dsisr
>> +
>> +tlbsync nop
>> +
>> +mtmsrd rX, 0 b <special mtmsr section>
>> +mtmsr b <special mtmsr section>
>> +
>> +mtmsrd rX, 1 b <special mtmsrd section>
>> +
>> +[BookE only]
>> +wrteei [0|1] b <special wrteei section>
>>
>
> Probably the guest, as only it can arrange for special * sections.
> Good.
>
>> +
>> +Some instructions require more logic to determine what's going on
>> than a load
>> +or store instruction can deliver. To enable patching of those, we
>> keep some
>> +RAM around where we can live translate instructions to. What
>> happens is the
>> +following:
>> +
>> + 1) copy emulation code to memory
>> + 2) patch that code to fit the emulated instruction
>> + 3) patch that code to return to the original pc + 4
>> + 4) patch the original instruction to branch to the new code
>> +
>> +That way we can inject an arbitrary amount of code as replacement
>> for a single
>> +instruction. This allows us to check for pending interrupts when
>> setting EE=1
>> +for example.
>> +
>>
>
> Or not.
>
> What about transitions from paravirt to non-paravirt? For example,
> a system reset.
That ... eh ... good question. It would leave the map pending, but
everything still continues working.
I don't really know in kvm when a reset occured. So we have to make
qemu set the map to 0 on reset. Let's add then when we add migration
support and actually expose all those missing states to userspace.
Currently we only expose half the necessary state for migration
anyway :).
Alex
^ permalink raw reply [flat|nested] 227+ messages in thread* Re: [PATCH 26/26] KVM: PPC: Add Documentation about PV interface
@ 2010-06-27 9:33 ` Alexander Graf
0 siblings, 0 replies; 227+ messages in thread
From: Alexander Graf @ 2010-06-27 9:33 UTC (permalink / raw)
To: Avi Kivity; +Cc: linuxppc-dev, KVM list, kvm-ppc@vger.kernel.org
Am 27.06.2010 um 10:14 schrieb Avi Kivity <avi@redhat.com>:
> On 06/26/2010 02:25 AM, Alexander Graf wrote:
>> We just introduced a new PV interface that screams for
>> documentation. So here
>> it is - a shiny new and awesome text file describing the internal
>> works of
>> the PPC KVM paravirtual interface.
>>
>
> Good, that lets people who have no idea what they're talking about
> participate in the review.
Heh, I knew you'd like this :).
>
>> +
>> +PPC hypercalls
>> +==============
>> +
>> +The only viable ways to reliably get from guest context to host
>> context are:
>> +
>> + 1) Call an invalid instruction
>> + 2) Call the "sc" instruction with a parameter to "sc"
>> + 3) Call the "sc" instruction with parameters in GPRs
>> +
>> +Method 1 is always a bad idea. Invalid instructions can be
>> replaced later on
>> +by valid instructions, rendering the interface broken.
>> +
>> +Method 2 also has downfalls. If the parameter to "sc" is != 0 the
>> spec is
>> +rather unclear if the sc is targeted directly for the hypervisor
>> or the
>> +supervisor. It would also require that we read the syscall issuing
>> instruction
>> +every time a syscall is issued, slowing down guest syscalls.
>> +
>> +Method 3 is what KVM uses. We pass magic constants
>> (KVM_SC_MAGIC_R3 and
>> +KVM_SC_MAGIC_R4) in r3 and r4 respectively. If a syscall
>> instruction with these
>> +magic values arrives from the guest's kernel mode, we take the
>> syscall as a
>> +hypercall.
>>
>
> Is there any chance a normal syscall will have those values in r3
> and r4?
r3 is the syscall number. So as long as the guest doesn't reuse that
value, we're safe. Since in general syscall numbers are not randomly
scattered throughout the number range, we should be ok here.
>
> If so, maybe it's better to use pc as they key for hypercalls. Let
> the guest designate one instruction address as the hypercall call
> point; kvm can easily check it and reflect it back to the guest if
> it doesn't match.
>
You mean the guest would tell the hv where the hypercall lies? That
would require a hypercall, no? Defining it statically is tricky. I
want to PV'nize osx using a kernel module later, so I don't have
control over the physical layout.
> Is it valid and useful to issue sc from privileged mode anyway,
> except for calling the hypervisor?
Same as a syscall on x86 really. The kernel can and does issue
syscalls within itself.
>
>> +
>> +The parameters are as follows:
>> +
>> + r3 KVM_SC_MAGIC_R3
>> + r4 KVM_SC_MAGIC_R4
>> + r5 Hypercall number
>> + r6 First parameter
>> + r7 Second parameter
>> + r8 Third parameter
>> + r9 Fourth parameter
>> +
>> +Hypercall definitions are shared in generic code, so the same
>> hypercall numbers
>> +apply for x86 and powerpc alike.
>>
>
> Addresses passed in hypercall paramters are guest physical addresses.
>
> Do you have >32 bit physical addresses on 32-bit guests? if so,
> you'll need to pass physical addresses in two registers.
I think theoretically it's possible. Will we ever support it?
Doubtful. Do we need to pass hogh memory addresses to the hv? Even
more doubtful.
If we hit such a case, I'd just disable the hypercall for 32 bit. Or
define param1 and param2 to contain the address if the guest is in 32-
bit mode. No need to always make all params 64 bit imho.
>
>> +
>> +The magic page
>> +==============
>> +
>> +To enable communication between the hypervisor and guest there is
>> a new shared
>> +page that contains parts of supervisor visible register state. The
>> guest can
>> +map this shared page using the KVM hypercall
>> KVM_HC_PPC_MAP_MAGIC_PAGE.
>> +
>> +With this hypercall issued the guest always gets the magic page
>> mapped at the
>> +desired location in effective and physical address space. For now,
>> we always
>> +map the page to -4096. This way we can access it using absolute
>> load and store
>> +functions. The following instruction reads the first field of the
>> magic page:
>> +
>> + ld rX, -4096(0)
>>
>
> Is the address guest controlled or host controlled?
Guest controlled. It's passed in to the map_magic_page hypercall.
>
>> +
>> +The interface is designed to be extensible should there be need
>> later to add
>> +additional registers to the magic page. If you add fields to the
>> magic page,
>> +also define a new hypercall feature to indicate that the host can
>> give you more
>> +registers. Only if the host supports the additional features, make
>> use of them.
>> +
>> +The magic page has the following layout as described in
>> +arch/powerpc/include/asm/kvm_para.h:
>> +
>> +struct kvm_vcpu_arch_shared {
>> + __u64 scratch1;
>> + __u64 scratch2;
>> + __u64 scratch3;
>> + __u64 critical; /* Guest may not get interrupts if ==
>> r1 */
>>
>
> Elaborate?
I think I have a description in the respective patch. Probably a good
idea to add it to the documentation.
>
>> + __u64 sprg0;
>> + __u64 sprg1;
>> + __u64 sprg2;
>> + __u64 sprg3;
>> + __u64 srr0;
>> + __u64 srr1;
>> + __u64 dar;
>> + __u64 msr;
>> + __u32 dsisr;
>> + __u32 int_pending; /* Tells the guest if we have an
>> interrupt */
>> +};
>> +
>> +Additions to the page must only occur at the end. Struct fields
>> are always 32
>> +bit aligned.
>> +
>> +Patched instructions
>> +====================
>> +
>> +The "ld" and "std" instructions are transormed to "lwz" and "stw"
>> instructions
>> +respectively on 32 bit systems with an added offset of 4 to
>> accomodate for big
>> +endianness.
>>
>
> Who does the patching? guest or host?
All patching is done by the guest. Probably worth mentioning, yeah.
>
>> +
>> +From To
>> +==== ==
>> +
>> +mfmsr rX ld rX, magic_page->msr
>> +mfsprg rX, 0 ld rX, magic_page->sprg0
>> +mfsprg rX, 1 ld rX, magic_page->sprg1
>> +mfsprg rX, 2 ld rX, magic_page->sprg2
>> +mfsprg rX, 3 ld rX, magic_page->sprg3
>> +mfsrr0 rX ld rX, magic_page->srr0
>> +mfsrr1 rX ld rX, magic_page->srr1
>> +mfdar rX ld rX, magic_page->dar
>> +mfdsisr rX ld rX, magic_page->dsisr
>> +
>> +mtmsr rX std rX, magic_page->msr
>> +mtsprg 0, rX std rX, magic_page->sprg0
>> +mtsprg 1, rX std rX, magic_page->sprg1
>> +mtsprg 2, rX std rX, magic_page->sprg2
>> +mtsprg 3, rX std rX, magic_page->sprg3
>> +mtsrr0 rX std rX, magic_page->srr0
>> +mtsrr1 rX std rX, magic_page->srr1
>> +mtdar rX std rX, magic_page->dar
>> +mtdsisr rX std rX, magic_page->dsisr
>> +
>> +tlbsync nop
>> +
>> +mtmsrd rX, 0 b <special mtmsr section>
>> +mtmsr b <special mtmsr section>
>> +
>> +mtmsrd rX, 1 b <special mtmsrd section>
>> +
>> +[BookE only]
>> +wrteei [0|1] b <special wrteei section>
>>
>
> Probably the guest, as only it can arrange for special * sections.
> Good.
>
>> +
>> +Some instructions require more logic to determine what's going on
>> than a load
>> +or store instruction can deliver. To enable patching of those, we
>> keep some
>> +RAM around where we can live translate instructions to. What
>> happens is the
>> +following:
>> +
>> + 1) copy emulation code to memory
>> + 2) patch that code to fit the emulated instruction
>> + 3) patch that code to return to the original pc + 4
>> + 4) patch the original instruction to branch to the new code
>> +
>> +That way we can inject an arbitrary amount of code as replacement
>> for a single
>> +instruction. This allows us to check for pending interrupts when
>> setting EE=1
>> +for example.
>> +
>>
>
> Or not.
>
> What about transitions from paravirt to non-paravirt? For example,
> a system reset.
That ... eh ... good question. It would leave the map pending, but
everything still continues working.
I don't really know in kvm when a reset occured. So we have to make
qemu set the map to 0 on reset. Let's add then when we add migration
support and actually expose all those missing states to userspace.
Currently we only expose half the necessary state for migration
anyway :).
Alex
^ permalink raw reply [flat|nested] 227+ messages in thread* Re: [PATCH 26/26] KVM: PPC: Add Documentation about PV interface
2010-06-27 9:33 ` Alexander Graf
@ 2010-06-28 7:18 ` Milton Miller
-1 siblings, 0 replies; 227+ messages in thread
From: Milton Miller @ 2010-06-28 7:18 UTC (permalink / raw)
To: Alexander Graf; +Cc: linuxppc-dev, Avi Kivity, kvm-ppc, KVM list
On Sun Jun 27 around 19:33:52 EST 2010 Alexander Graf wrote:
> Am 27.06.2010 um 10:14 schrieb Avi Kivity <avi at redhat.com>:
> > On 06/26/2010 02:25 AM, Alexander Graf wrote:
> > > +
> > > +PPC hypercalls
> > > +=======
> > > +
> > > +The only viable ways to reliably get from guest context to host
> > > context are:
> > > +
> > > + 1) Call an invalid instruction
> > > + 2) Call the "sc" instruction with a parameter to "sc"
> > > + 3) Call the "sc" instruction with parameters in GPRs
> > > +
> > > +Method 1 is always a bad idea. Invalid instructions can be
> > > replaced later on
> > > +by valid instructions, rendering the interface broken.
> > > +
> > > +Method 2 also has downfalls. If the parameter to "sc" is != 0 the
> > > spec is
> > > +rather unclear if the sc is targeted directly for the hypervisor
> > > or the
> > > +supervisor. It would also require that we read the syscall issuing
> > > instruction
> > > +every time a syscall is issued, slowing down guest syscalls.
> > > +
It goes to the hypervisor, and it would require the hypervisor to
return to the supervisor, but I believe it just returns to the user with
permission denied.
> > > +Method 3 is what KVM uses. We pass magic constants
> > > (KVM_SC_MAGIC_R3 and
> > > +KVM_SC_MAGIC_R4) in r3 and r4 respectively. If a syscall
> > > instruction with these
> > > +magic values arrives from the guest's kernel mode, we take the
> > > syscall as a
> > > +hypercall.
> > >
> >
> > Is there any chance a normal syscall will have those values in r3
> > and r4?
>
> r3 is the syscall number. So as long as the guest doesn't reuse that
> value, we're safe. Since in general syscall numbers are not randomly
> scattered throughout the number range, we should be ok here.
>
No, r0 has the system call number. Registers 3 and 4 are the first
2 args in c abi (or first 64 bit arg in 32 bit c abi), but the linux
syscall abi special. (In addition, it returns success or failure in
cr0).
> >
> > If so, maybe it's better to use pc as they key for hypercalls. Let
> > the guest designate one instruction address as the hypercall call
> > point; kvm can easily check it and reflect it back to the guest if
> > it doesn't match.
> >
>
> You mean the guest would tell the hv where the hypercall lies? That
> would require a hypercall, no? Defining it statically is tricky. I
> want to PV'nize osx using a kernel module later, so I don't have
> control over the physical layout.
>
> > Is it valid and useful to issue sc from privileged mode anyway,
> > except for calling the hypervisor?
>
> Same as a syscall on x86 really. The kernel can and does issue
> syscalls within itself.
>
>
I don't believe we support the kernel actually doing a syscall to itself
anymore, at least on powerpc. The callers call the underlying system
call function, or kernel_thread.
That said, I would suggest we allocate a syscall number for this, as it
would document the usage. (In additon to 0..nr_syscalls - 1 we have
0x1ebe in use).
Also, is there any desire to nest such emulation?
milton
^ permalink raw reply [flat|nested] 227+ messages in thread
* Re: [PATCH 26/26] KVM: PPC: Add Documentation about PV interface
@ 2010-06-28 7:18 ` Milton Miller
0 siblings, 0 replies; 227+ messages in thread
From: Milton Miller @ 2010-06-28 7:18 UTC (permalink / raw)
To: Alexander Graf; +Cc: linuxppc-dev, Avi Kivity, kvm-ppc, KVM list
On Sun Jun 27 around 19:33:52 EST 2010 Alexander Graf wrote:
> Am 27.06.2010 um 10:14 schrieb Avi Kivity <avi at redhat.com>:
> > On 06/26/2010 02:25 AM, Alexander Graf wrote:
> > > +
> > > +PPC hypercalls
> > > +==============
> > > +
> > > +The only viable ways to reliably get from guest context to host
> > > context are:
> > > +
> > > + 1) Call an invalid instruction
> > > + 2) Call the "sc" instruction with a parameter to "sc"
> > > + 3) Call the "sc" instruction with parameters in GPRs
> > > +
> > > +Method 1 is always a bad idea. Invalid instructions can be
> > > replaced later on
> > > +by valid instructions, rendering the interface broken.
> > > +
> > > +Method 2 also has downfalls. If the parameter to "sc" is != 0 the
> > > spec is
> > > +rather unclear if the sc is targeted directly for the hypervisor
> > > or the
> > > +supervisor. It would also require that we read the syscall issuing
> > > instruction
> > > +every time a syscall is issued, slowing down guest syscalls.
> > > +
It goes to the hypervisor, and it would require the hypervisor to
return to the supervisor, but I believe it just returns to the user with
permission denied.
> > > +Method 3 is what KVM uses. We pass magic constants
> > > (KVM_SC_MAGIC_R3 and
> > > +KVM_SC_MAGIC_R4) in r3 and r4 respectively. If a syscall
> > > instruction with these
> > > +magic values arrives from the guest's kernel mode, we take the
> > > syscall as a
> > > +hypercall.
> > >
> >
> > Is there any chance a normal syscall will have those values in r3
> > and r4?
>
> r3 is the syscall number. So as long as the guest doesn't reuse that
> value, we're safe. Since in general syscall numbers are not randomly
> scattered throughout the number range, we should be ok here.
>
No, r0 has the system call number. Registers 3 and 4 are the first
2 args in c abi (or first 64 bit arg in 32 bit c abi), but the linux
syscall abi special. (In addition, it returns success or failure in
cr0).
> >
> > If so, maybe it's better to use pc as they key for hypercalls. Let
> > the guest designate one instruction address as the hypercall call
> > point; kvm can easily check it and reflect it back to the guest if
> > it doesn't match.
> >
>
> You mean the guest would tell the hv where the hypercall lies? That
> would require a hypercall, no? Defining it statically is tricky. I
> want to PV'nize osx using a kernel module later, so I don't have
> control over the physical layout.
>
> > Is it valid and useful to issue sc from privileged mode anyway,
> > except for calling the hypervisor?
>
> Same as a syscall on x86 really. The kernel can and does issue
> syscalls within itself.
>
>
I don't believe we support the kernel actually doing a syscall to itself
anymore, at least on powerpc. The callers call the underlying system
call function, or kernel_thread.
That said, I would suggest we allocate a syscall number for this, as it
would document the usage. (In additon to 0..nr_syscalls - 1 we have
0x1ebe in use).
Also, is there any desire to nest such emulation?
milton
^ permalink raw reply [flat|nested] 227+ messages in thread
[parent not found: <1277709531_13308-qolCYAvwHvWlVDA81TZ6el6hYfS7NtTn@public.gmane.org>]
* Re: [PATCH 26/26] KVM: PPC: Add Documentation about PV interface
2010-06-28 7:18 ` Milton Miller
(?)
@ 2010-06-28 7:49 ` Alexander Graf
-1 siblings, 0 replies; 227+ messages in thread
From: Alexander Graf @ 2010-06-28 7:49 UTC (permalink / raw)
To: Milton Miller
Cc: Avi Kivity, kvm-ppc-u79uwXL29TY76Z2rM5mHXA, linuxppc-dev,
KVM list
On 28.06.2010, at 09:18, Milton Miller wrote:
> On Sun Jun 27 around 19:33:52 EST 2010 Alexander Graf wrote:
>> Am 27.06.2010 um 10:14 schrieb Avi Kivity <avi at redhat.com>:
>>> On 06/26/2010 02:25 AM, Alexander Graf wrote:
>
>>>> +
>>>> +PPC hypercalls
>>>> +=======
>>>> +
>>>> +The only viable ways to reliably get from guest context to host
>>>> context are:
>>>> +
>>>> + 1) Call an invalid instruction
>>>> + 2) Call the "sc" instruction with a parameter to "sc"
>>>> + 3) Call the "sc" instruction with parameters in GPRs
>>>> +
>>>> +Method 1 is always a bad idea. Invalid instructions can be
>>>> replaced later on
>>>> +by valid instructions, rendering the interface broken.
>>>> +
>>>> +Method 2 also has downfalls. If the parameter to "sc" is != 0 the
>>>> spec is
>>>> +rather unclear if the sc is targeted directly for the hypervisor
>>>> or the
>>>> +supervisor. It would also require that we read the syscall issuing
>>>> instruction
>>>> +every time a syscall is issued, slowing down guest syscalls.
>>>> +
>
> It goes to the hypervisor, and it would require the hypervisor to
> return to the supervisor, but I believe it just returns to the user with
> permission denied.
That's what I assumed, yeah :(.
>
>>>> +Method 3 is what KVM uses. We pass magic constants
>>>> (KVM_SC_MAGIC_R3 and
>>>> +KVM_SC_MAGIC_R4) in r3 and r4 respectively. If a syscall
>>>> instruction with these
>>>> +magic values arrives from the guest's kernel mode, we take the
>>>> syscall as a
>>>> +hypercall.
>>>>
>>>
>>> Is there any chance a normal syscall will have those values in r3
>>> and r4?
>>
>> r3 is the syscall number. So as long as the guest doesn't reuse that
>> value, we're safe. Since in general syscall numbers are not randomly
>> scattered throughout the number range, we should be ok here.
>>
>
> No, r0 has the system call number. Registers 3 and 4 are the first
> 2 args in c abi (or first 64 bit arg in 32 bit c abi), but the linux
> syscall abi special. (In addition, it returns success or failure in
> cr0).
Oh. Ahem :)
>
>>>
>>> If so, maybe it's better to use pc as they key for hypercalls. Let
>>> the guest designate one instruction address as the hypercall call
>>> point; kvm can easily check it and reflect it back to the guest if
>>> it doesn't match.
>>>
>>
>> You mean the guest would tell the hv where the hypercall lies? That
>> would require a hypercall, no? Defining it statically is tricky. I
>> want to PV'nize osx using a kernel module later, so I don't have
>> control over the physical layout.
>>
>>> Is it valid and useful to issue sc from privileged mode anyway,
>>> except for calling the hypervisor?
>>
>> Same as a syscall on x86 really. The kernel can and does issue
>> syscalls within itself.
>>
>>
>
> I don't believe we support the kernel actually doing a syscall to itself
> anymore, at least on powerpc. The callers call the underlying system
> call function, or kernel_thread.
>
> That said, I would suggest we allocate a syscall number for this, as it
> would document the usage. (In additon to 0..nr_syscalls - 1 we have
> 0x1ebe in use).
That's actually a pretty good idea.
>
> Also, is there any desire to nest such emulation?
Nesting should just work, right? Since we only accept hypercalls from PR=0 and guests run in PR=1, we get the sc interrupt in the l1 guest by then.
The only issue I'm aware of that completely breaks when using nested KVM on PPC is the MSR_IR != MSR_DR logic. We fetch the instruction we got an interrupt on for certain interrupts in the world switch handler by keeping MSR_IR=0, but setting MSR_DR=1. And KVM speeds up MSR_DR != MSR_IR by mapping both of them lazily in a special address space. So if you access the same page as instruction and as data, you get an invalid result.
Alex
^ permalink raw reply [flat|nested] 227+ messages in thread
* Re: [PATCH 26/26] KVM: PPC: Add Documentation about PV interface
@ 2010-06-28 7:49 ` Alexander Graf
0 siblings, 0 replies; 227+ messages in thread
From: Alexander Graf @ 2010-06-28 7:49 UTC (permalink / raw)
To: Milton Miller
Cc: Avi Kivity, kvm-ppc-u79uwXL29TY76Z2rM5mHXA, linuxppc-dev,
KVM list
On 28.06.2010, at 09:18, Milton Miller wrote:
> On Sun Jun 27 around 19:33:52 EST 2010 Alexander Graf wrote:
>> Am 27.06.2010 um 10:14 schrieb Avi Kivity <avi at redhat.com>:
>>> On 06/26/2010 02:25 AM, Alexander Graf wrote:
>
>>>> +
>>>> +PPC hypercalls
>>>> +==============
>>>> +
>>>> +The only viable ways to reliably get from guest context to host
>>>> context are:
>>>> +
>>>> + 1) Call an invalid instruction
>>>> + 2) Call the "sc" instruction with a parameter to "sc"
>>>> + 3) Call the "sc" instruction with parameters in GPRs
>>>> +
>>>> +Method 1 is always a bad idea. Invalid instructions can be
>>>> replaced later on
>>>> +by valid instructions, rendering the interface broken.
>>>> +
>>>> +Method 2 also has downfalls. If the parameter to "sc" is != 0 the
>>>> spec is
>>>> +rather unclear if the sc is targeted directly for the hypervisor
>>>> or the
>>>> +supervisor. It would also require that we read the syscall issuing
>>>> instruction
>>>> +every time a syscall is issued, slowing down guest syscalls.
>>>> +
>
> It goes to the hypervisor, and it would require the hypervisor to
> return to the supervisor, but I believe it just returns to the user with
> permission denied.
That's what I assumed, yeah :(.
>
>>>> +Method 3 is what KVM uses. We pass magic constants
>>>> (KVM_SC_MAGIC_R3 and
>>>> +KVM_SC_MAGIC_R4) in r3 and r4 respectively. If a syscall
>>>> instruction with these
>>>> +magic values arrives from the guest's kernel mode, we take the
>>>> syscall as a
>>>> +hypercall.
>>>>
>>>
>>> Is there any chance a normal syscall will have those values in r3
>>> and r4?
>>
>> r3 is the syscall number. So as long as the guest doesn't reuse that
>> value, we're safe. Since in general syscall numbers are not randomly
>> scattered throughout the number range, we should be ok here.
>>
>
> No, r0 has the system call number. Registers 3 and 4 are the first
> 2 args in c abi (or first 64 bit arg in 32 bit c abi), but the linux
> syscall abi special. (In addition, it returns success or failure in
> cr0).
Oh. Ahem :)
>
>>>
>>> If so, maybe it's better to use pc as they key for hypercalls. Let
>>> the guest designate one instruction address as the hypercall call
>>> point; kvm can easily check it and reflect it back to the guest if
>>> it doesn't match.
>>>
>>
>> You mean the guest would tell the hv where the hypercall lies? That
>> would require a hypercall, no? Defining it statically is tricky. I
>> want to PV'nize osx using a kernel module later, so I don't have
>> control over the physical layout.
>>
>>> Is it valid and useful to issue sc from privileged mode anyway,
>>> except for calling the hypervisor?
>>
>> Same as a syscall on x86 really. The kernel can and does issue
>> syscalls within itself.
>>
>>
>
> I don't believe we support the kernel actually doing a syscall to itself
> anymore, at least on powerpc. The callers call the underlying system
> call function, or kernel_thread.
>
> That said, I would suggest we allocate a syscall number for this, as it
> would document the usage. (In additon to 0..nr_syscalls - 1 we have
> 0x1ebe in use).
That's actually a pretty good idea.
>
> Also, is there any desire to nest such emulation?
Nesting should just work, right? Since we only accept hypercalls from PR=0 and guests run in PR=1, we get the sc interrupt in the l1 guest by then.
The only issue I'm aware of that completely breaks when using nested KVM on PPC is the MSR_IR != MSR_DR logic. We fetch the instruction we got an interrupt on for certain interrupts in the world switch handler by keeping MSR_IR=0, but setting MSR_DR=1. And KVM speeds up MSR_DR != MSR_IR by mapping both of them lazily in a special address space. So if you access the same page as instruction and as data, you get an invalid result.
Alex
^ permalink raw reply [flat|nested] 227+ messages in thread
* Re: [PATCH 26/26] KVM: PPC: Add Documentation about PV interface
@ 2010-06-28 7:49 ` Alexander Graf
0 siblings, 0 replies; 227+ messages in thread
From: Alexander Graf @ 2010-06-28 7:49 UTC (permalink / raw)
To: Milton Miller; +Cc: linuxppc-dev, Avi Kivity, kvm-ppc, KVM list
On 28.06.2010, at 09:18, Milton Miller wrote:
> On Sun Jun 27 around 19:33:52 EST 2010 Alexander Graf wrote:
>> Am 27.06.2010 um 10:14 schrieb Avi Kivity <avi at redhat.com>:
>>> On 06/26/2010 02:25 AM, Alexander Graf wrote:
>=20
>>>> +
>>>> +PPC hypercalls
>>>> +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
>>>> +
>>>> +The only viable ways to reliably get from guest context to host =20=
>>>> context are:
>>>> +
>>>> + 1) Call an invalid instruction
>>>> + 2) Call the "sc" instruction with a parameter to "sc"
>>>> + 3) Call the "sc" instruction with parameters in GPRs
>>>> +
>>>> +Method 1 is always a bad idea. Invalid instructions can be =20
>>>> replaced later on
>>>> +by valid instructions, rendering the interface broken.
>>>> +
>>>> +Method 2 also has downfalls. If the parameter to "sc" is !=3D 0 =
the =20
>>>> spec is
>>>> +rather unclear if the sc is targeted directly for the hypervisor =20=
>>>> or the
>>>> +supervisor. It would also require that we read the syscall issuing =
=20
>>>> instruction
>>>> +every time a syscall is issued, slowing down guest syscalls.
>>>> +
>=20
> It goes to the hypervisor, and it would require the hypervisor to
> return to the supervisor, but I believe it just returns to the user =
with
> permission denied.
That's what I assumed, yeah :(.
>=20
>>>> +Method 3 is what KVM uses. We pass magic constants =20
>>>> (KVM_SC_MAGIC_R3 and
>>>> +KVM_SC_MAGIC_R4) in r3 and r4 respectively. If a syscall =20
>>>> instruction with these
>>>> +magic values arrives from the guest's kernel mode, we take the =20
>>>> syscall as a
>>>> +hypercall.
>>>>=20
>>>=20
>>> Is there any chance a normal syscall will have those values in r3 =20=
>>> and r4?
>>=20
>> r3 is the syscall number. So as long as the guest doesn't reuse that =20=
>> value, we're safe. Since in general syscall numbers are not randomly =20=
>> scattered throughout the number range, we should be ok here.
>>=20
>=20
> No, r0 has the system call number. Registers 3 and 4 are the first
> 2 args in c abi (or first 64 bit arg in 32 bit c abi), but the linux
> syscall abi special. (In addition, it returns success or failure in
> cr0).
Oh. Ahem :)
>=20
>>>=20
>>> If so, maybe it's better to use pc as they key for hypercalls. Let =20=
>>> the guest designate one instruction address as the hypercall call =20=
>>> point; kvm can easily check it and reflect it back to the guest if =20=
>>> it doesn't match.
>>>=20
>>=20
>> You mean the guest would tell the hv where the hypercall lies? That =20=
>> would require a hypercall, no? Defining it statically is tricky. I =20=
>> want to PV'nize osx using a kernel module later, so I don't have =20
>> control over the physical layout.
>>=20
>>> Is it valid and useful to issue sc from privileged mode anyway, =20
>>> except for calling the hypervisor?
>>=20
>> Same as a syscall on x86 really. The kernel can and does issue =20
>> syscalls within itself.
>>=20
>>=20
>=20
> I don't believe we support the kernel actually doing a syscall to =
itself
> anymore, at least on powerpc. The callers call the underlying system
> call function, or kernel_thread.
>=20
> That said, I would suggest we allocate a syscall number for this, as =
it
> would document the usage. (In additon to 0..nr_syscalls - 1 we have
> 0x1ebe in use).
That's actually a pretty good idea.
>=20
> Also, is there any desire to nest such emulation?
Nesting should just work, right? Since we only accept hypercalls from =
PR=3D0 and guests run in PR=3D1, we get the sc interrupt in the l1 guest =
by then.
The only issue I'm aware of that completely breaks when using nested KVM =
on PPC is the MSR_IR !=3D MSR_DR logic. We fetch the instruction we got =
an interrupt on for certain interrupts in the world switch handler by =
keeping MSR_IR=3D0, but setting MSR_DR=3D1. And KVM speeds up MSR_DR !=3D =
MSR_IR by mapping both of them lazily in a special address space. So if =
you access the same page as instruction and as data, you get an invalid =
result.
Alex
^ permalink raw reply [flat|nested] 227+ messages in thread
[parent not found: <92F4A3F3-A89F-418D-BD4D-66E2489F2E42-l3A5Bk7waGM@public.gmane.org>]
* Re: [PATCH 26/26] KVM: PPC: Add Documentation about PV interface
2010-06-28 7:49 ` Alexander Graf
(?)
@ 2010-06-28 8:13 ` Avi Kivity
-1 siblings, 0 replies; 227+ messages in thread
From: Avi Kivity @ 2010-06-28 8:13 UTC (permalink / raw)
To: Alexander Graf
Cc: Milton Miller, kvm-ppc-u79uwXL29TY76Z2rM5mHXA, linuxppc-dev,
KVM list
On 06/28/2010 10:49 AM, Alexander Graf wrote:
>
>> I don't believe we support the kernel actually doing a syscall to itself
>> anymore, at least on powerpc. The callers call the underlying system
>> call function, or kernel_thread.
>>
>> That said, I would suggest we allocate a syscall number for this, as it
>> would document the usage. (In additon to 0..nr_syscalls - 1 we have
>> 0x1ebe in use).
>>
> That's actually a pretty good idea.
>
Since the syscall register is not architectual (or rather it is
architectural but Linux ignores it) I don't see the point. It would
work for Linux but may alias some random parameter for a different
guest. We need a reliable method of distinguishing between syscalls and
hypercalls. Matching pc would work (but is defeated by inlining) so
long as we find some other way of identifying the hc pc to the hypervisor.
--
error compiling committee.c: too many arguments to function
^ permalink raw reply [flat|nested] 227+ messages in thread
* Re: [PATCH 26/26] KVM: PPC: Add Documentation about PV interface
@ 2010-06-28 8:13 ` Avi Kivity
0 siblings, 0 replies; 227+ messages in thread
From: Avi Kivity @ 2010-06-28 8:13 UTC (permalink / raw)
To: Alexander Graf
Cc: Milton Miller, kvm-ppc-u79uwXL29TY76Z2rM5mHXA, linuxppc-dev,
KVM list
On 06/28/2010 10:49 AM, Alexander Graf wrote:
>
>> I don't believe we support the kernel actually doing a syscall to itself
>> anymore, at least on powerpc. The callers call the underlying system
>> call function, or kernel_thread.
>>
>> That said, I would suggest we allocate a syscall number for this, as it
>> would document the usage. (In additon to 0..nr_syscalls - 1 we have
>> 0x1ebe in use).
>>
> That's actually a pretty good idea.
>
Since the syscall register is not architectual (or rather it is
architectural but Linux ignores it) I don't see the point. It would
work for Linux but may alias some random parameter for a different
guest. We need a reliable method of distinguishing between syscalls and
hypercalls. Matching pc would work (but is defeated by inlining) so
long as we find some other way of identifying the hc pc to the hypervisor.
--
error compiling committee.c: too many arguments to function
^ permalink raw reply [flat|nested] 227+ messages in thread
* Re: [PATCH 26/26] KVM: PPC: Add Documentation about PV interface
@ 2010-06-28 8:13 ` Avi Kivity
0 siblings, 0 replies; 227+ messages in thread
From: Avi Kivity @ 2010-06-28 8:13 UTC (permalink / raw)
To: Alexander Graf; +Cc: linuxppc-dev, kvm-ppc, Milton Miller, KVM list
On 06/28/2010 10:49 AM, Alexander Graf wrote:
>
>> I don't believe we support the kernel actually doing a syscall to itself
>> anymore, at least on powerpc. The callers call the underlying system
>> call function, or kernel_thread.
>>
>> That said, I would suggest we allocate a syscall number for this, as it
>> would document the usage. (In additon to 0..nr_syscalls - 1 we have
>> 0x1ebe in use).
>>
> That's actually a pretty good idea.
>
Since the syscall register is not architectual (or rather it is
architectural but Linux ignores it) I don't see the point. It would
work for Linux but may alias some random parameter for a different
guest. We need a reliable method of distinguishing between syscalls and
hypercalls. Matching pc would work (but is defeated by inlining) so
long as we find some other way of identifying the hc pc to the hypervisor.
--
error compiling committee.c: too many arguments to function
^ permalink raw reply [flat|nested] 227+ messages in thread
[parent not found: <4C285991.1050303-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>]
* Re: [PATCH 26/26] KVM: PPC: Add Documentation about PV interface
2010-06-28 8:13 ` Avi Kivity
(?)
@ 2010-06-28 8:21 ` Alexander Graf
-1 siblings, 0 replies; 227+ messages in thread
From: Alexander Graf @ 2010-06-28 8:21 UTC (permalink / raw)
To: Avi Kivity
Cc: Milton Miller, kvm-ppc-u79uwXL29TY76Z2rM5mHXA, linuxppc-dev,
KVM list
On 28.06.2010, at 10:13, Avi Kivity wrote:
> On 06/28/2010 10:49 AM, Alexander Graf wrote:
>>
>>> I don't believe we support the kernel actually doing a syscall to itself
>>> anymore, at least on powerpc. The callers call the underlying system
>>> call function, or kernel_thread.
>>>
>>> That said, I would suggest we allocate a syscall number for this, as it
>>> would document the usage. (In additon to 0..nr_syscalls - 1 we have
>>> 0x1ebe in use).
>>>
>> That's actually a pretty good idea.
>>
>
> Since the syscall register is not architectual (or rather it is architectural but Linux ignores it) I don't see the point. It would work for Linux but may alias some random parameter for a different guest. We need a reliable method of distinguishing between syscalls and hypercalls. Matching pc would work (but is defeated by inlining) so long as we find some other way of identifying the hc pc to the hypervisor.
The other alternative I'd see is to reuse an instruction that is not sc. We could for example pull the mfpvr trick again, but pass a different magic value in the register this time that tells the hypervisor "this is a hypercall".
Or we could reserve a different SPR. But from what I've seen there are already quite a lot of SPRs out there. More than available numbers :).
The hypercall technique I used here is actually inspired by MOL. They use magic constants in r3 and r4 for their "OSI" identification. I'm frankly not sure what the best approach is, but considering that syscalls from the kernel lie in the guest kernel's hand, we could just declare any breakage a guest kernel bug.
Alex
^ permalink raw reply [flat|nested] 227+ messages in thread
* Re: [PATCH 26/26] KVM: PPC: Add Documentation about PV interface
@ 2010-06-28 8:21 ` Alexander Graf
0 siblings, 0 replies; 227+ messages in thread
From: Alexander Graf @ 2010-06-28 8:21 UTC (permalink / raw)
To: Avi Kivity
Cc: Milton Miller, kvm-ppc-u79uwXL29TY76Z2rM5mHXA, linuxppc-dev,
KVM list
On 28.06.2010, at 10:13, Avi Kivity wrote:
> On 06/28/2010 10:49 AM, Alexander Graf wrote:
>>
>>> I don't believe we support the kernel actually doing a syscall to itself
>>> anymore, at least on powerpc. The callers call the underlying system
>>> call function, or kernel_thread.
>>>
>>> That said, I would suggest we allocate a syscall number for this, as it
>>> would document the usage. (In additon to 0..nr_syscalls - 1 we have
>>> 0x1ebe in use).
>>>
>> That's actually a pretty good idea.
>>
>
> Since the syscall register is not architectual (or rather it is architectural but Linux ignores it) I don't see the point. It would work for Linux but may alias some random parameter for a different guest. We need a reliable method of distinguishing between syscalls and hypercalls. Matching pc would work (but is defeated by inlining) so long as we find some other way of identifying the hc pc to the hypervisor.
The other alternative I'd see is to reuse an instruction that is not sc. We could for example pull the mfpvr trick again, but pass a different magic value in the register this time that tells the hypervisor "this is a hypercall".
Or we could reserve a different SPR. But from what I've seen there are already quite a lot of SPRs out there. More than available numbers :).
The hypercall technique I used here is actually inspired by MOL. They use magic constants in r3 and r4 for their "OSI" identification. I'm frankly not sure what the best approach is, but considering that syscalls from the kernel lie in the guest kernel's hand, we could just declare any breakage a guest kernel bug.
Alex
^ permalink raw reply [flat|nested] 227+ messages in thread
* Re: [PATCH 26/26] KVM: PPC: Add Documentation about PV interface
@ 2010-06-28 8:21 ` Alexander Graf
0 siblings, 0 replies; 227+ messages in thread
From: Alexander Graf @ 2010-06-28 8:21 UTC (permalink / raw)
To: Avi Kivity; +Cc: linuxppc-dev, kvm-ppc, Milton Miller, KVM list
On 28.06.2010, at 10:13, Avi Kivity wrote:
> On 06/28/2010 10:49 AM, Alexander Graf wrote:
>>=20
>>> I don't believe we support the kernel actually doing a syscall to =
itself
>>> anymore, at least on powerpc. The callers call the underlying =
system
>>> call function, or kernel_thread.
>>>=20
>>> That said, I would suggest we allocate a syscall number for this, as =
it
>>> would document the usage. (In additon to 0..nr_syscalls - 1 we have
>>> 0x1ebe in use).
>>> =20
>> That's actually a pretty good idea.
>> =20
>=20
> Since the syscall register is not architectual (or rather it is =
architectural but Linux ignores it) I don't see the point. It would =
work for Linux but may alias some random parameter for a different =
guest. We need a reliable method of distinguishing between syscalls and =
hypercalls. Matching pc would work (but is defeated by inlining) so =
long as we find some other way of identifying the hc pc to the =
hypervisor.
The other alternative I'd see is to reuse an instruction that is not sc. =
We could for example pull the mfpvr trick again, but pass a different =
magic value in the register this time that tells the hypervisor "this is =
a hypercall".
Or we could reserve a different SPR. But from what I've seen there are =
already quite a lot of SPRs out there. More than available numbers :).
The hypercall technique I used here is actually inspired by MOL. They =
use magic constants in r3 and r4 for their "OSI" identification. I'm =
frankly not sure what the best approach is, but considering that =
syscalls from the kernel lie in the guest kernel's hand, we could just =
declare any breakage a guest kernel bug.
Alex
^ permalink raw reply [flat|nested] 227+ messages in thread
[parent not found: <4330E5DC-63C5-40EA-9E99-34EE58074D1A-l3A5Bk7waGM@public.gmane.org>]
* Re: [PATCH 26/26] KVM: PPC: Add Documentation about PV interface
2010-06-28 8:21 ` Alexander Graf
(?)
@ 2010-06-28 8:32 ` Avi Kivity
-1 siblings, 0 replies; 227+ messages in thread
From: Avi Kivity @ 2010-06-28 8:32 UTC (permalink / raw)
To: Alexander Graf
Cc: Milton Miller, kvm-ppc-u79uwXL29TY76Z2rM5mHXA, linuxppc-dev,
KVM list
On 06/28/2010 11:21 AM, Alexander Graf wrote:
>
> The other alternative I'd see is to reuse an instruction that is not sc. We could for example pull the mfpvr trick again, but pass a different magic value in the register this time that tells the hypervisor "this is a hypercall".
>
> Or we could reserve a different SPR. But from what I've seen there are already quite a lot of SPRs out there. More than available numbers :).
>
> The hypercall technique I used here is actually inspired by MOL. They use magic constants in r3 and r4 for their "OSI" identification. I'm frankly not sure what the best approach is, but considering that syscalls from the kernel lie in the guest kernel's hand, we could just declare any breakage a guest kernel bug.
>
>
Magic = liable to break without notice.
Given r0 is the architectural syscall number, and r3 is the Linux
syscall number, we can use a combination of r0 and r3, reserve r3 in
Linux, and hope that no one else uses our selection of r0.
Still smelly, but not as bad.
--
error compiling committee.c: too many arguments to function
^ permalink raw reply [flat|nested] 227+ messages in thread
* Re: [PATCH 26/26] KVM: PPC: Add Documentation about PV interface
@ 2010-06-28 8:32 ` Avi Kivity
0 siblings, 0 replies; 227+ messages in thread
From: Avi Kivity @ 2010-06-28 8:32 UTC (permalink / raw)
To: Alexander Graf
Cc: Milton Miller, kvm-ppc-u79uwXL29TY76Z2rM5mHXA, linuxppc-dev,
KVM list
On 06/28/2010 11:21 AM, Alexander Graf wrote:
>
> The other alternative I'd see is to reuse an instruction that is not sc. We could for example pull the mfpvr trick again, but pass a different magic value in the register this time that tells the hypervisor "this is a hypercall".
>
> Or we could reserve a different SPR. But from what I've seen there are already quite a lot of SPRs out there. More than available numbers :).
>
> The hypercall technique I used here is actually inspired by MOL. They use magic constants in r3 and r4 for their "OSI" identification. I'm frankly not sure what the best approach is, but considering that syscalls from the kernel lie in the guest kernel's hand, we could just declare any breakage a guest kernel bug.
>
>
Magic = liable to break without notice.
Given r0 is the architectural syscall number, and r3 is the Linux
syscall number, we can use a combination of r0 and r3, reserve r3 in
Linux, and hope that no one else uses our selection of r0.
Still smelly, but not as bad.
--
error compiling committee.c: too many arguments to function
^ permalink raw reply [flat|nested] 227+ messages in thread
* Re: [PATCH 26/26] KVM: PPC: Add Documentation about PV interface
@ 2010-06-28 8:32 ` Avi Kivity
0 siblings, 0 replies; 227+ messages in thread
From: Avi Kivity @ 2010-06-28 8:32 UTC (permalink / raw)
To: Alexander Graf; +Cc: linuxppc-dev, kvm-ppc, Milton Miller, KVM list
On 06/28/2010 11:21 AM, Alexander Graf wrote:
>
> The other alternative I'd see is to reuse an instruction that is not sc. We could for example pull the mfpvr trick again, but pass a different magic value in the register this time that tells the hypervisor "this is a hypercall".
>
> Or we could reserve a different SPR. But from what I've seen there are already quite a lot of SPRs out there. More than available numbers :).
>
> The hypercall technique I used here is actually inspired by MOL. They use magic constants in r3 and r4 for their "OSI" identification. I'm frankly not sure what the best approach is, but considering that syscalls from the kernel lie in the guest kernel's hand, we could just declare any breakage a guest kernel bug.
>
>
Magic = liable to break without notice.
Given r0 is the architectural syscall number, and r3 is the Linux
syscall number, we can use a combination of r0 and r3, reserve r3 in
Linux, and hope that no one else uses our selection of r0.
Still smelly, but not as bad.
--
error compiling committee.c: too many arguments to function
^ permalink raw reply [flat|nested] 227+ messages in thread
[parent not found: <1277508314-915-27-git-send-email-agraf-l3A5Bk7waGM@public.gmane.org>]
* Re: [PATCH 26/26] KVM: PPC: Add Documentation about PV interface
2010-06-25 23:25 ` Alexander Graf
(?)
@ 2010-06-27 8:34 ` Avi Kivity
-1 siblings, 0 replies; 227+ messages in thread
From: Avi Kivity @ 2010-06-27 8:34 UTC (permalink / raw)
To: Alexander Graf; +Cc: kvm-ppc-u79uwXL29TY76Z2rM5mHXA, KVM list, linuxppc-dev
On 06/26/2010 02:25 AM, Alexander Graf wrote:
> We just introduced a new PV interface that screams for documentation. So here
> it is - a shiny new and awesome text file describing the internal works of
> the PPC KVM paravirtual interface.
>
>
> +Querying for existence
> +===========
> +
> +To find out if we're running on KVM or not, we overlay the PVR register. Usually
> +the PVR register contains an id that identifies your CPU type. If, however, you
> +pass KVM_PVR_PARA in the register that you want the PVR result in, the register
> +still contains KVM_PVR_PARA after the mfpvr call.
> +
> + LOAD_REG_IMM(r5, KVM_PVR_PARA)
> + mfpvr r5
> + [r5 still contains KVM_PVR_PARA]
> +
> +Once determined to run under a PV capable KVM, you can now use hypercalls as
> +described below.
>
On x86 we allow host userspace to determine whether the guest sees the
paravirt interface (and what features are exposed). This allows you to
live migrate from a newer host to an older host, by not exposing the
newer features.
--
error compiling committee.c: too many arguments to function
^ permalink raw reply [flat|nested] 227+ messages in thread
* Re: [PATCH 26/26] KVM: PPC: Add Documentation about PV interface
@ 2010-06-27 8:34 ` Avi Kivity
0 siblings, 0 replies; 227+ messages in thread
From: Avi Kivity @ 2010-06-27 8:34 UTC (permalink / raw)
To: Alexander Graf; +Cc: kvm-ppc-u79uwXL29TY76Z2rM5mHXA, KVM list, linuxppc-dev
On 06/26/2010 02:25 AM, Alexander Graf wrote:
> We just introduced a new PV interface that screams for documentation. So here
> it is - a shiny new and awesome text file describing the internal works of
> the PPC KVM paravirtual interface.
>
>
> +Querying for existence
> +======================
> +
> +To find out if we're running on KVM or not, we overlay the PVR register. Usually
> +the PVR register contains an id that identifies your CPU type. If, however, you
> +pass KVM_PVR_PARA in the register that you want the PVR result in, the register
> +still contains KVM_PVR_PARA after the mfpvr call.
> +
> + LOAD_REG_IMM(r5, KVM_PVR_PARA)
> + mfpvr r5
> + [r5 still contains KVM_PVR_PARA]
> +
> +Once determined to run under a PV capable KVM, you can now use hypercalls as
> +described below.
>
On x86 we allow host userspace to determine whether the guest sees the
paravirt interface (and what features are exposed). This allows you to
live migrate from a newer host to an older host, by not exposing the
newer features.
--
error compiling committee.c: too many arguments to function
^ permalink raw reply [flat|nested] 227+ messages in thread
* Re: [PATCH 26/26] KVM: PPC: Add Documentation about PV interface
@ 2010-06-27 8:34 ` Avi Kivity
0 siblings, 0 replies; 227+ messages in thread
From: Avi Kivity @ 2010-06-27 8:34 UTC (permalink / raw)
To: Alexander Graf; +Cc: linuxppc-dev, KVM list, kvm-ppc
On 06/26/2010 02:25 AM, Alexander Graf wrote:
> We just introduced a new PV interface that screams for documentation. So here
> it is - a shiny new and awesome text file describing the internal works of
> the PPC KVM paravirtual interface.
>
>
> +Querying for existence
> +======================
> +
> +To find out if we're running on KVM or not, we overlay the PVR register. Usually
> +the PVR register contains an id that identifies your CPU type. If, however, you
> +pass KVM_PVR_PARA in the register that you want the PVR result in, the register
> +still contains KVM_PVR_PARA after the mfpvr call.
> +
> + LOAD_REG_IMM(r5, KVM_PVR_PARA)
> + mfpvr r5
> + [r5 still contains KVM_PVR_PARA]
> +
> +Once determined to run under a PV capable KVM, you can now use hypercalls as
> +described below.
>
On x86 we allow host userspace to determine whether the guest sees the
paravirt interface (and what features are exposed). This allows you to
live migrate from a newer host to an older host, by not exposing the
newer features.
--
error compiling committee.c: too many arguments to function
^ permalink raw reply [flat|nested] 227+ messages in thread
* Re: [PATCH 26/26] KVM: PPC: Add Documentation about PV interface
2010-06-27 8:34 ` Avi Kivity
(?)
@ 2010-06-27 9:49 ` Alexander Graf
-1 siblings, 0 replies; 227+ messages in thread
From: Alexander Graf @ 2010-06-27 9:49 UTC (permalink / raw)
To: Avi Kivity; +Cc: kvm-ppc@vger.kernel.org, KVM list, linuxppc-dev
Am 27.06.2010 um 10:34 schrieb Avi Kivity <avi@redhat.com>:
> On 06/26/2010 02:25 AM, Alexander Graf wrote:
>> We just introduced a new PV interface that screams for
>> documentation. So here
>> it is - a shiny new and awesome text file describing the internal
>> works of
>> the PPC KVM paravirtual interface.
>>
>>
>> +Querying for existence
>> +===========
>> +
>> +To find out if we're running on KVM or not, we overlay the PVR
>> register. Usually
>> +the PVR register contains an id that identifies your CPU type. If,
>> however, you
>> +pass KVM_PVR_PARA in the register that you want the PVR result in,
>> the register
>> +still contains KVM_PVR_PARA after the mfpvr call.
>> +
>> + LOAD_REG_IMM(r5, KVM_PVR_PARA)
>> + mfpvr r5
>> + [r5 still contains KVM_PVR_PARA]
>> +
>> +Once determined to run under a PV capable KVM, you can now use
>> hypercalls as
>> +described below.
>>
>
> On x86 we allow host userspace to determine whether the guest sees
> the paravirt interface (and what features are exposed). This allows
> you to live migrate from a newer host to an older host, by not
> exposing the newer features.
A very good idea indeed. Let's postpone that to when we expose enough
state to make live migration possible.
Alex
^ permalink raw reply [flat|nested] 227+ messages in thread
* Re: [PATCH 26/26] KVM: PPC: Add Documentation about PV interface
@ 2010-06-27 9:49 ` Alexander Graf
0 siblings, 0 replies; 227+ messages in thread
From: Alexander Graf @ 2010-06-27 9:49 UTC (permalink / raw)
To: Avi Kivity; +Cc: kvm-ppc@vger.kernel.org, KVM list, linuxppc-dev
Am 27.06.2010 um 10:34 schrieb Avi Kivity <avi@redhat.com>:
> On 06/26/2010 02:25 AM, Alexander Graf wrote:
>> We just introduced a new PV interface that screams for
>> documentation. So here
>> it is - a shiny new and awesome text file describing the internal
>> works of
>> the PPC KVM paravirtual interface.
>>
>>
>> +Querying for existence
>> +======================
>> +
>> +To find out if we're running on KVM or not, we overlay the PVR
>> register. Usually
>> +the PVR register contains an id that identifies your CPU type. If,
>> however, you
>> +pass KVM_PVR_PARA in the register that you want the PVR result in,
>> the register
>> +still contains KVM_PVR_PARA after the mfpvr call.
>> +
>> + LOAD_REG_IMM(r5, KVM_PVR_PARA)
>> + mfpvr r5
>> + [r5 still contains KVM_PVR_PARA]
>> +
>> +Once determined to run under a PV capable KVM, you can now use
>> hypercalls as
>> +described below.
>>
>
> On x86 we allow host userspace to determine whether the guest sees
> the paravirt interface (and what features are exposed). This allows
> you to live migrate from a newer host to an older host, by not
> exposing the newer features.
A very good idea indeed. Let's postpone that to when we expose enough
state to make live migration possible.
Alex
^ permalink raw reply [flat|nested] 227+ messages in thread
* Re: [PATCH 26/26] KVM: PPC: Add Documentation about PV interface
@ 2010-06-27 9:49 ` Alexander Graf
0 siblings, 0 replies; 227+ messages in thread
From: Alexander Graf @ 2010-06-27 9:49 UTC (permalink / raw)
To: Avi Kivity; +Cc: linuxppc-dev, KVM list, kvm-ppc@vger.kernel.org
Am 27.06.2010 um 10:34 schrieb Avi Kivity <avi@redhat.com>:
> On 06/26/2010 02:25 AM, Alexander Graf wrote:
>> We just introduced a new PV interface that screams for
>> documentation. So here
>> it is - a shiny new and awesome text file describing the internal
>> works of
>> the PPC KVM paravirtual interface.
>>
>>
>> +Querying for existence
>> +======================
>> +
>> +To find out if we're running on KVM or not, we overlay the PVR
>> register. Usually
>> +the PVR register contains an id that identifies your CPU type. If,
>> however, you
>> +pass KVM_PVR_PARA in the register that you want the PVR result in,
>> the register
>> +still contains KVM_PVR_PARA after the mfpvr call.
>> +
>> + LOAD_REG_IMM(r5, KVM_PVR_PARA)
>> + mfpvr r5
>> + [r5 still contains KVM_PVR_PARA]
>> +
>> +Once determined to run under a PV capable KVM, you can now use
>> hypercalls as
>> +described below.
>>
>
> On x86 we allow host userspace to determine whether the guest sees
> the paravirt interface (and what features are exposed). This allows
> you to live migrate from a newer host to an older host, by not
> exposing the newer features.
A very good idea indeed. Let's postpone that to when we expose enough
state to make live migration possible.
Alex
^ permalink raw reply [flat|nested] 227+ messages in thread