From: David Gibson <david@gibson.dropbear.id.au>
To: agraf@suse.de
Cc: qemu-ppc@nongnu.org, qemu-devel@nongnu.org,
David Gibson <david@gibson.dropbear.id.au>
Subject: [Qemu-devel] [PATCH 7/7] target-ppc: Synchronize VPA state with KVM
Date: Mon, 8 Apr 2013 15:08:22 +1000 [thread overview]
Message-ID: <1365397702-1515-8-git-send-email-david@gibson.dropbear.id.au> (raw)
In-Reply-To: <1365397702-1515-1-git-send-email-david@gibson.dropbear.id.au>
For PAPR guests, KVM tracks the various areas registered with the
H_REGISTER_VPA hypercall. For full emulation, of course, these are tracked
within qemu. At present these values are not synchronized. This is a
problem for reset (qemu's reset of the VPA address is not pushed to KVM)
and will also be a problem for savevm / migration.
The kernel now supports accessing the VPA state via the ONE_REG interface,
this patch adds code to qemu to use that interface to keep the qemu and
KVM ideas of the VPA state synchronized.
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
---
target-ppc/kvm.c | 120 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 120 insertions(+)
diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c
index 6a676cc..7d06ad9 100644
--- a/target-ppc/kvm.c
+++ b/target-ppc/kvm.c
@@ -63,6 +63,7 @@ static int cap_ppc_rma;
static int cap_spapr_tce;
static int cap_hior;
static int cap_one_reg;
+static int cap_papr;
/* XXX We have a race condition where we actually have a level triggered
* interrupt, but the infrastructure can't expose that yet, so the guest
@@ -95,6 +96,8 @@ int kvm_arch_init(KVMState *s)
cap_spapr_tce = kvm_check_extension(s, KVM_CAP_SPAPR_TCE);
cap_one_reg = kvm_check_extension(s, KVM_CAP_ONE_REG);
cap_hior = kvm_check_extension(s, KVM_CAP_PPC_HIOR);
+ /* Note: we don't set cap_papr here, because this capability is
+ * only activated after this by kvmppc_set_papr() */
if (!cap_interrupt_level) {
fprintf(stderr, "KVM: Couldn't find level irq capability. Expect the "
@@ -652,6 +655,103 @@ static int kvm_get_fp(CPUState *cs)
return 0;
}
+#if defined(TARGET_PPC64)
+static int kvm_get_vpa(CPUState *cs)
+{
+ PowerPCCPU *cpu = POWERPC_CPU(cs);
+ CPUPPCState *env = &cpu->env;
+ struct kvm_one_reg reg;
+ int ret;
+
+ reg.id = KVM_REG_PPC_VPA_ADDR;
+ reg.addr = (uintptr_t)&env->vpa_addr;
+ ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, ®);
+ if (ret < 0) {
+ dprintf("Unable to get VPA address from KVM: %s\n", strerror(errno));
+ return ret;
+ }
+
+ assert((uintptr_t)&env->slb_shadow_size
+ == ((uintptr_t)&env->slb_shadow_addr + 8));
+ reg.id = KVM_REG_PPC_VPA_SLB;
+ reg.addr = (uintptr_t)&env->slb_shadow_addr;
+ ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, ®);
+ if (ret < 0) {
+ dprintf("Unable to get SLB shadow state from KVM: %s\n",
+ strerror(errno));
+ return ret;
+ }
+
+ assert((uintptr_t)&env->dtl_size == ((uintptr_t)&env->dtl_addr + 8));
+ reg.id = KVM_REG_PPC_VPA_DTL;
+ reg.addr = (uintptr_t)&env->dtl_addr;
+ ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, ®);
+ if (ret < 0) {
+ dprintf("Unable to get dispatch trace log state from KVM: %s\n",
+ strerror(errno));
+ return ret;
+ }
+
+ return 0;
+}
+
+static int kvm_put_vpa(CPUState *cs)
+{
+ PowerPCCPU *cpu = POWERPC_CPU(cs);
+ CPUPPCState *env = &cpu->env;
+ struct kvm_one_reg reg;
+ int ret;
+
+ /* SLB shadow or DTL can't be registered unless a master VPA is
+ * registered. That means when restoring state, if a VPA *is*
+ * registered, we need to set that up first. If not, we need to
+ * deregister the others before deregistering the master VPA */
+ assert(env->vpa_addr || !(env->slb_shadow_addr || env->dtl_addr));
+
+ if (env->vpa_addr) {
+ reg.id = KVM_REG_PPC_VPA_ADDR;
+ reg.addr = (uintptr_t)&env->vpa_addr;
+ ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, ®);
+ if (ret < 0) {
+ dprintf("Unable to set VPA address to KVM: %s\n", strerror(errno));
+ return ret;
+ }
+ }
+
+ assert((uintptr_t)&env->slb_shadow_size
+ == ((uintptr_t)&env->slb_shadow_addr + 8));
+ reg.id = KVM_REG_PPC_VPA_SLB;
+ reg.addr = (uintptr_t)&env->slb_shadow_addr;
+ ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, ®);
+ if (ret < 0) {
+ dprintf("Unable to set SLB shadow state to KVM: %s\n", strerror(errno));
+ return ret;
+ }
+
+ assert((uintptr_t)&env->dtl_size == ((uintptr_t)&env->dtl_addr + 8));
+ reg.id = KVM_REG_PPC_VPA_DTL;
+ reg.addr = (uintptr_t)&env->dtl_addr;
+ ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, ®);
+ if (ret < 0) {
+ dprintf("Unable to set dispatch trace log state to KVM: %s\n",
+ strerror(errno));
+ return ret;
+ }
+
+ if (!env->vpa_addr) {
+ reg.id = KVM_REG_PPC_VPA_ADDR;
+ reg.addr = (uintptr_t)&env->vpa_addr;
+ ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, ®);
+ if (ret < 0) {
+ dprintf("Unable to set VPA address to KVM: %s\n", strerror(errno));
+ return ret;
+ }
+ }
+
+ return 0;
+}
+#endif /* TARGET_PPC64 */
+
int kvm_arch_put_registers(CPUState *cs, int level)
{
PowerPCCPU *cpu = POWERPC_CPU(cs);
@@ -752,6 +852,14 @@ int kvm_arch_put_registers(CPUState *cs, int level)
kvm_put_one_spr(cs, id, i);
}
}
+
+#ifdef TARGET_PPC64
+ if (cap_papr) {
+ if (kvm_put_vpa(cs) < 0) {
+ dprintf("Warning: Unable to set VPA information to KVM\n");
+ }
+ }
+#endif /* TARGET_PPC64 */
}
return ret;
@@ -953,6 +1061,14 @@ int kvm_arch_get_registers(CPUState *cs)
kvm_get_one_spr(cs, id, i);
}
}
+
+#ifdef TARGET_PPC64
+ if (cap_papr) {
+ if (kvm_get_vpa(cs) < 0) {
+ dprintf("Warning: Unable to get VPA information from KVM\n");
+ }
+ }
+#endif
}
return 0;
@@ -1301,6 +1417,10 @@ void kvmppc_set_papr(PowerPCCPU *cpu)
if (ret) {
cpu_abort(env, "This KVM version does not support PAPR\n");
}
+
+ /* Update the capability flag so we sync the right information
+ * with kvm */
+ cap_papr = 1;
}
void kvmppc_set_mpic_proxy(PowerPCCPU *cpu, int mpic_proxy)
--
1.7.10.4
next prev parent reply other threads:[~2013-04-08 5:14 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-04-08 5:08 [Qemu-devel] [0/7] Pending pseries updates David Gibson
2013-04-08 5:08 ` [Qemu-devel] [PATCH 1/7] pseries: Convert VIO code to QOM style type safe(ish) casts David Gibson
2013-04-08 5:08 ` [Qemu-devel] [PATCH 2/7] pseries: Generate device paths for VIO devices David Gibson
2013-04-08 5:08 ` [Qemu-devel] [PATCH 3/7] pseries: Fix incorrect calculation of RMA size in certain configurations David Gibson
2013-04-08 5:08 ` [Qemu-devel] [PATCH 4/7] pseries: Fixes and enhancements to L1 cache properties David Gibson
2013-04-08 5:08 ` [Qemu-devel] [PATCH 5/7] target-ppc: Add more stubs for POWER7 PMU registers David Gibson
2013-04-08 5:08 ` [Qemu-devel] [PATCH 6/7] pseries: Fix some small errors in XICS logic David Gibson
2013-04-08 5:08 ` David Gibson [this message]
2013-04-19 15:27 ` [Qemu-devel] [0/7] Pending pseries updates Alexander Graf
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1365397702-1515-8-git-send-email-david@gibson.dropbear.id.au \
--to=david@gibson.dropbear.id.au \
--cc=agraf@suse.de \
--cc=qemu-devel@nongnu.org \
--cc=qemu-ppc@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).