* [PATCH v3 0/5] KVM: PPC: Book3e: AltiVec support
@ 2014-08-05 10:39 Mihai Caraman
2014-08-05 10:39 ` [PATCH v3 1/5] KVM: PPC: Book3e: Increase FPU laziness Mihai Caraman
` (4 more replies)
0 siblings, 5 replies; 9+ messages in thread
From: Mihai Caraman @ 2014-08-05 10:39 UTC (permalink / raw)
To: kvm-ppc; +Cc: kvm, Mihai Caraman
Add KVM Book3e AltiVec support and enable e6500 core.
Changes:
v3:
- use distinct SPE/AltiVec exception handlers
- make ONE_REG AltiVec support powerpc generic
- add ONE_REG IVORs support
v2:
- integrate Paul's FP/VMX/VSX changes that landed in kvm-ppc-queue
in January and take into account feedback
Mihai Caraman (5):
KVM: PPC: Book3e: Increase FPU laziness
KVM: PPC: Book3e: Add AltiVec support
KVM: PPC: Move ONE_REG AltiVec support to powerpc
KVM: PPC: Booke: Add ONE_REG IVORs support
KVM: PPC: Book3e: Enable e6500 core
arch/powerpc/include/uapi/asm/kvm.h | 29 +++
arch/powerpc/kvm/book3s.c | 151 +++++-----------
arch/powerpc/kvm/booke.c | 331 ++++++++++++++++++++++++++++------
arch/powerpc/kvm/booke.h | 39 +---
arch/powerpc/kvm/bookehv_interrupts.S | 10 +-
arch/powerpc/kvm/e500.c | 42 ++++-
arch/powerpc/kvm/e500_emulate.c | 18 ++
arch/powerpc/kvm/e500mc.c | 44 ++++-
arch/powerpc/kvm/powerpc.c | 97 ++++++++++
9 files changed, 554 insertions(+), 207 deletions(-)
--
1.7.11.7
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH v3 1/5] KVM: PPC: Book3e: Increase FPU laziness
2014-08-05 10:39 [PATCH v3 0/5] KVM: PPC: Book3e: AltiVec support Mihai Caraman
@ 2014-08-05 10:39 ` Mihai Caraman
2014-08-05 10:39 ` [PATCH v3 2/5] KVM: PPC: Book3e: Add AltiVec support Mihai Caraman
` (3 subsequent siblings)
4 siblings, 0 replies; 9+ messages in thread
From: Mihai Caraman @ 2014-08-05 10:39 UTC (permalink / raw)
To: kvm-ppc; +Cc: kvm, Mihai Caraman
Increase FPU laziness by calling kvmppc_load_guest_fp() just before
returning to guest instead of each sched in. Without this improvement
an interrupt may also claim floting point corrupting guest state.
Signed-off-by: Mihai Caraman <mihai.caraman@freescale.com>
---
v3:
- no changes
v2:
- remove fpu_active
- add descriptive comments
arch/powerpc/kvm/booke.c | 43 ++++++++++++++++++++++++++++++++++++-------
arch/powerpc/kvm/booke.h | 34 ----------------------------------
arch/powerpc/kvm/e500mc.c | 2 --
3 files changed, 36 insertions(+), 43 deletions(-)
diff --git a/arch/powerpc/kvm/booke.c b/arch/powerpc/kvm/booke.c
index b4c89fa..0c6f616 100644
--- a/arch/powerpc/kvm/booke.c
+++ b/arch/powerpc/kvm/booke.c
@@ -124,6 +124,40 @@ static void kvmppc_vcpu_sync_spe(struct kvm_vcpu *vcpu)
}
#endif
+/*
+ * Load up guest vcpu FP state if it's needed.
+ * It also set the MSR_FP in thread so that host know
+ * we're holding FPU, and then host can help to save
+ * guest vcpu FP state if other threads require to use FPU.
+ * This simulates an FP unavailable fault.
+ *
+ * It requires to be called with preemption disabled.
+ */
+static inline void kvmppc_load_guest_fp(struct kvm_vcpu *vcpu)
+{
+#ifdef CONFIG_PPC_FPU
+ if (!(current->thread.regs->msr & MSR_FP)) {
+ enable_kernel_fp();
+ load_fp_state(&vcpu->arch.fp);
+ current->thread.fp_save_area = &vcpu->arch.fp;
+ current->thread.regs->msr |= MSR_FP;
+ }
+#endif
+}
+
+/*
+ * Save guest vcpu FP state into thread.
+ * It requires to be called with preemption disabled.
+ */
+static inline void kvmppc_save_guest_fp(struct kvm_vcpu *vcpu)
+{
+#ifdef CONFIG_PPC_FPU
+ if (current->thread.regs->msr & MSR_FP)
+ giveup_fpu(current);
+ current->thread.fp_save_area = NULL;
+#endif
+}
+
static void kvmppc_vcpu_sync_fpu(struct kvm_vcpu *vcpu)
{
#if defined(CONFIG_PPC_FPU) && !defined(CONFIG_KVM_BOOKE_HV)
@@ -654,12 +688,8 @@ int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
/*
* Since we can't trap on MSR_FP in GS-mode, we consider the guest
- * as always using the FPU. Kernel usage of FP (via
- * enable_kernel_fp()) in this thread must not occur while
- * vcpu->fpu_active is set.
+ * as always using the FPU.
*/
- vcpu->fpu_active = 1;
-
kvmppc_load_guest_fp(vcpu);
#endif
@@ -683,8 +713,6 @@ int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
#ifdef CONFIG_PPC_FPU
kvmppc_save_guest_fp(vcpu);
-
- vcpu->fpu_active = 0;
#endif
out:
@@ -1188,6 +1216,7 @@ out:
else {
/* interrupts now hard-disabled */
kvmppc_fix_ee_before_entry();
+ kvmppc_load_guest_fp(vcpu);
}
}
diff --git a/arch/powerpc/kvm/booke.h b/arch/powerpc/kvm/booke.h
index f753543..e73d513 100644
--- a/arch/powerpc/kvm/booke.h
+++ b/arch/powerpc/kvm/booke.h
@@ -116,40 +116,6 @@ extern int kvmppc_core_emulate_mtspr_e500(struct kvm_vcpu *vcpu, int sprn,
extern int kvmppc_core_emulate_mfspr_e500(struct kvm_vcpu *vcpu, int sprn,
ulong *spr_val);
-/*
- * Load up guest vcpu FP state if it's needed.
- * It also set the MSR_FP in thread so that host know
- * we're holding FPU, and then host can help to save
- * guest vcpu FP state if other threads require to use FPU.
- * This simulates an FP unavailable fault.
- *
- * It requires to be called with preemption disabled.
- */
-static inline void kvmppc_load_guest_fp(struct kvm_vcpu *vcpu)
-{
-#ifdef CONFIG_PPC_FPU
- if (vcpu->fpu_active && !(current->thread.regs->msr & MSR_FP)) {
- enable_kernel_fp();
- load_fp_state(&vcpu->arch.fp);
- current->thread.fp_save_area = &vcpu->arch.fp;
- current->thread.regs->msr |= MSR_FP;
- }
-#endif
-}
-
-/*
- * Save guest vcpu FP state into thread.
- * It requires to be called with preemption disabled.
- */
-static inline void kvmppc_save_guest_fp(struct kvm_vcpu *vcpu)
-{
-#ifdef CONFIG_PPC_FPU
- if (vcpu->fpu_active && (current->thread.regs->msr & MSR_FP))
- giveup_fpu(current);
- current->thread.fp_save_area = NULL;
-#endif
-}
-
static inline void kvmppc_clear_dbsr(void)
{
mtspr(SPRN_DBSR, mfspr(SPRN_DBSR));
diff --git a/arch/powerpc/kvm/e500mc.c b/arch/powerpc/kvm/e500mc.c
index 164bad2..67c06eb 100644
--- a/arch/powerpc/kvm/e500mc.c
+++ b/arch/powerpc/kvm/e500mc.c
@@ -145,8 +145,6 @@ static void kvmppc_core_vcpu_load_e500mc(struct kvm_vcpu *vcpu, int cpu)
kvmppc_e500_tlbil_all(vcpu_e500);
__get_cpu_var(last_vcpu_of_lpid)[vcpu->kvm->arch.lpid] = vcpu;
}
-
- kvmppc_load_guest_fp(vcpu);
}
static void kvmppc_core_vcpu_put_e500mc(struct kvm_vcpu *vcpu)
--
1.7.11.7
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH v3 2/5] KVM: PPC: Book3e: Add AltiVec support
2014-08-05 10:39 [PATCH v3 0/5] KVM: PPC: Book3e: AltiVec support Mihai Caraman
2014-08-05 10:39 ` [PATCH v3 1/5] KVM: PPC: Book3e: Increase FPU laziness Mihai Caraman
@ 2014-08-05 10:39 ` Mihai Caraman
2014-08-12 11:45 ` Alexander Graf
2014-08-05 10:39 ` [PATCH v3 3/5] KVM: PPC: Move ONE_REG AltiVec support to powerpc Mihai Caraman
` (2 subsequent siblings)
4 siblings, 1 reply; 9+ messages in thread
From: Mihai Caraman @ 2014-08-05 10:39 UTC (permalink / raw)
To: kvm-ppc; +Cc: kvm, Mihai Caraman
Add KVM Book3e AltiVec support. KVM Book3e FPU support gracefully reuse host
infrastructure so follow the same approach for AltiVec.
Keep SPE/AltiVec exception handlers distinct using CONFIG_KVM_E500V2.
Signed-off-by: Mihai Caraman <mihai.caraman@freescale.com>
---
v3:
- use distinct SPE/AltiVec exception handlers
v2:
- integrate Paul's FP/VMX/VSX changes
arch/powerpc/kvm/booke.c | 73 +++++++++++++++++++++++++++++++++++
arch/powerpc/kvm/booke.h | 5 +++
arch/powerpc/kvm/bookehv_interrupts.S | 10 +++--
arch/powerpc/kvm/e500_emulate.c | 18 +++++++++
4 files changed, 102 insertions(+), 4 deletions(-)
diff --git a/arch/powerpc/kvm/booke.c b/arch/powerpc/kvm/booke.c
index 0c6f616..c5cca09 100644
--- a/arch/powerpc/kvm/booke.c
+++ b/arch/powerpc/kvm/booke.c
@@ -168,6 +168,40 @@ static void kvmppc_vcpu_sync_fpu(struct kvm_vcpu *vcpu)
#endif
}
+/*
+ * Simulate AltiVec unavailable fault to load guest state
+ * from thread to AltiVec unit.
+ * It requires to be called with preemption disabled.
+ */
+static inline void kvmppc_load_guest_altivec(struct kvm_vcpu *vcpu)
+{
+#ifdef CONFIG_ALTIVEC
+ if (cpu_has_feature(CPU_FTR_ALTIVEC)) {
+ if (!(current->thread.regs->msr & MSR_VEC)) {
+ enable_kernel_altivec();
+ load_vr_state(&vcpu->arch.vr);
+ current->thread.vr_save_area = &vcpu->arch.vr;
+ current->thread.regs->msr |= MSR_VEC;
+ }
+ }
+#endif
+}
+
+/*
+ * Save guest vcpu AltiVec state into thread.
+ * It requires to be called with preemption disabled.
+ */
+static inline void kvmppc_save_guest_altivec(struct kvm_vcpu *vcpu)
+{
+#ifdef CONFIG_ALTIVEC
+ if (cpu_has_feature(CPU_FTR_ALTIVEC)) {
+ if (current->thread.regs->msr & MSR_VEC)
+ giveup_altivec(current);
+ current->thread.vr_save_area = NULL;
+ }
+#endif
+}
+
static void kvmppc_vcpu_sync_debug(struct kvm_vcpu *vcpu)
{
/* Synchronize guest's desire to get debug interrupts into shadow MSR */
@@ -375,9 +409,14 @@ static int kvmppc_booke_irqprio_deliver(struct kvm_vcpu *vcpu,
case BOOKE_IRQPRIO_ITLB_MISS:
case BOOKE_IRQPRIO_SYSCALL:
case BOOKE_IRQPRIO_FP_UNAVAIL:
+#ifdef CONFIG_KVM_E500V2
case BOOKE_IRQPRIO_SPE_UNAVAIL:
case BOOKE_IRQPRIO_SPE_FP_DATA:
case BOOKE_IRQPRIO_SPE_FP_ROUND:
+#else
+ case BOOKE_IRQPRIO_ALTIVEC_UNAVAIL:
+ case BOOKE_IRQPRIO_ALTIVEC_ASSIST:
+#endif
case BOOKE_IRQPRIO_AP_UNAVAIL:
allowed = 1;
msr_mask = MSR_CE | MSR_ME | MSR_DE;
@@ -693,6 +732,17 @@ int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
kvmppc_load_guest_fp(vcpu);
#endif
+#ifdef CONFIG_ALTIVEC
+ /* Save userspace AltiVec state in stack */
+ if (cpu_has_feature(CPU_FTR_ALTIVEC))
+ enable_kernel_altivec();
+ /*
+ * Since we can't trap on MSR_VEC in GS-mode, we consider the guest
+ * as always using the AltiVec.
+ */
+ kvmppc_load_guest_altivec(vcpu);
+#endif
+
/* Switch to guest debug context */
debug = vcpu->arch.shadow_dbg_reg;
switch_booke_debug_regs(&debug);
@@ -715,6 +765,10 @@ int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
kvmppc_save_guest_fp(vcpu);
#endif
+#ifdef CONFIG_ALTIVEC
+ kvmppc_save_guest_altivec(vcpu);
+#endif
+
out:
vcpu->mode = OUTSIDE_GUEST_MODE;
return ret;
@@ -999,6 +1053,7 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
r = RESUME_GUEST;
break;
+#ifdef CONFIG_KVM_E500V2
#ifdef CONFIG_SPE
case BOOKE_INTERRUPT_SPE_UNAVAIL: {
if (vcpu->arch.shared->msr & MSR_SPE)
@@ -1040,7 +1095,24 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
run->hw.hardware_exit_reason = exit_nr;
r = RESUME_HOST;
break;
+#endif /* !CONFIG_SPE */
+#else
+/*
+ * On cores with Vector category, KVM is loaded only if CONFIG_ALTIVEC,
+ * see kvmppc_core_check_processor_compat().
+ */
+#ifdef CONFIG_ALTIVEC
+ case BOOKE_INTERRUPT_ALTIVEC_UNAVAIL:
+ kvmppc_booke_queue_irqprio(vcpu, BOOKE_IRQPRIO_ALTIVEC_UNAVAIL);
+ r = RESUME_GUEST;
+ break;
+
+ case BOOKE_INTERRUPT_ALTIVEC_ASSIST:
+ kvmppc_booke_queue_irqprio(vcpu, BOOKE_IRQPRIO_ALTIVEC_ASSIST);
+ r = RESUME_GUEST;
+ break;
#endif
+#endif /* !CONFIG_KVM_E500V2 */
case BOOKE_INTERRUPT_DATA_STORAGE:
kvmppc_core_queue_data_storage(vcpu, vcpu->arch.fault_dear,
@@ -1217,6 +1289,7 @@ out:
/* interrupts now hard-disabled */
kvmppc_fix_ee_before_entry();
kvmppc_load_guest_fp(vcpu);
+ kvmppc_load_guest_altivec(vcpu);
}
}
diff --git a/arch/powerpc/kvm/booke.h b/arch/powerpc/kvm/booke.h
index e73d513..ce5b543 100644
--- a/arch/powerpc/kvm/booke.h
+++ b/arch/powerpc/kvm/booke.h
@@ -32,9 +32,14 @@
#define BOOKE_IRQPRIO_ALIGNMENT 2
#define BOOKE_IRQPRIO_PROGRAM 3
#define BOOKE_IRQPRIO_FP_UNAVAIL 4
+#ifdef CONFIG_KVM_E500V2
#define BOOKE_IRQPRIO_SPE_UNAVAIL 5
#define BOOKE_IRQPRIO_SPE_FP_DATA 6
#define BOOKE_IRQPRIO_SPE_FP_ROUND 7
+#else
+#define BOOKE_IRQPRIO_ALTIVEC_UNAVAIL 5
+#define BOOKE_IRQPRIO_ALTIVEC_ASSIST 6
+#endif
#define BOOKE_IRQPRIO_SYSCALL 8
#define BOOKE_IRQPRIO_AP_UNAVAIL 9
#define BOOKE_IRQPRIO_DTLB_MISS 10
diff --git a/arch/powerpc/kvm/bookehv_interrupts.S b/arch/powerpc/kvm/bookehv_interrupts.S
index e9fa56a..1d7c4d6 100644
--- a/arch/powerpc/kvm/bookehv_interrupts.S
+++ b/arch/powerpc/kvm/bookehv_interrupts.S
@@ -256,11 +256,9 @@ kvm_handler BOOKE_INTERRUPT_DTLB_MISS, EX_PARAMS_TLB, \
SPRN_SRR0, SPRN_SRR1, (NEED_EMU | NEED_DEAR | NEED_ESR)
kvm_handler BOOKE_INTERRUPT_ITLB_MISS, EX_PARAMS_TLB, \
SPRN_SRR0, SPRN_SRR1, 0
-kvm_handler BOOKE_INTERRUPT_SPE_UNAVAIL, EX_PARAMS(GEN), \
+kvm_handler BOOKE_INTERRUPT_ALTIVEC_UNAVAIL, EX_PARAMS(GEN), \
SPRN_SRR0, SPRN_SRR1, 0
-kvm_handler BOOKE_INTERRUPT_SPE_FP_DATA, EX_PARAMS(GEN), \
- SPRN_SRR0, SPRN_SRR1, 0
-kvm_handler BOOKE_INTERRUPT_SPE_FP_ROUND, EX_PARAMS(GEN), \
+kvm_handler BOOKE_INTERRUPT_ALTIVEC_ASSIST, EX_PARAMS(GEN), \
SPRN_SRR0, SPRN_SRR1, 0
kvm_handler BOOKE_INTERRUPT_PERFORMANCE_MONITOR, EX_PARAMS(GEN), \
SPRN_SRR0, SPRN_SRR1, 0
@@ -361,6 +359,10 @@ kvm_lvl_handler BOOKE_INTERRUPT_WATCHDOG, \
kvm_handler BOOKE_INTERRUPT_DTLB_MISS, \
SPRN_SRR0, SPRN_SRR1, (NEED_EMU | NEED_DEAR | NEED_ESR)
kvm_handler BOOKE_INTERRUPT_ITLB_MISS, SPRN_SRR0, SPRN_SRR1, 0
+/*
+ * TODO: SPE handlers should be available only for e500v2 cores.
+ * HV does not target e500v2 so remove them after kernel cleanup.
+ */
kvm_handler BOOKE_INTERRUPT_SPE_UNAVAIL, SPRN_SRR0, SPRN_SRR1, 0
kvm_handler BOOKE_INTERRUPT_SPE_FP_DATA, SPRN_SRR0, SPRN_SRR1, 0
kvm_handler BOOKE_INTERRUPT_SPE_FP_ROUND, SPRN_SRR0, SPRN_SRR1, 0
diff --git a/arch/powerpc/kvm/e500_emulate.c b/arch/powerpc/kvm/e500_emulate.c
index c99c40e..e6e0429 100644
--- a/arch/powerpc/kvm/e500_emulate.c
+++ b/arch/powerpc/kvm/e500_emulate.c
@@ -259,6 +259,7 @@ int kvmppc_core_emulate_mtspr_e500(struct kvm_vcpu *vcpu, int sprn, ulong spr_va
break;
/* extra exceptions */
+#ifdef CONFIG_KVM_E500V2
case SPRN_IVOR32:
vcpu->arch.ivor[BOOKE_IRQPRIO_SPE_UNAVAIL] = spr_val;
break;
@@ -268,6 +269,14 @@ int kvmppc_core_emulate_mtspr_e500(struct kvm_vcpu *vcpu, int sprn, ulong spr_va
case SPRN_IVOR34:
vcpu->arch.ivor[BOOKE_IRQPRIO_SPE_FP_ROUND] = spr_val;
break;
+#else
+ case SPRN_IVOR32:
+ vcpu->arch.ivor[BOOKE_IRQPRIO_ALTIVEC_UNAVAIL] = spr_val;
+ break;
+ case SPRN_IVOR33:
+ vcpu->arch.ivor[BOOKE_IRQPRIO_ALTIVEC_ASSIST] = spr_val;
+ break;
+#endif
case SPRN_IVOR35:
vcpu->arch.ivor[BOOKE_IRQPRIO_PERFORMANCE_MONITOR] = spr_val;
break;
@@ -381,6 +390,7 @@ int kvmppc_core_emulate_mfspr_e500(struct kvm_vcpu *vcpu, int sprn, ulong *spr_v
break;
/* extra exceptions */
+#ifdef CONFIG_KVM_E500V2
case SPRN_IVOR32:
*spr_val = vcpu->arch.ivor[BOOKE_IRQPRIO_SPE_UNAVAIL];
break;
@@ -390,6 +400,14 @@ int kvmppc_core_emulate_mfspr_e500(struct kvm_vcpu *vcpu, int sprn, ulong *spr_v
case SPRN_IVOR34:
*spr_val = vcpu->arch.ivor[BOOKE_IRQPRIO_SPE_FP_ROUND];
break;
+#else
+ case SPRN_IVOR32:
+ *spr_val = vcpu->arch.ivor[BOOKE_IRQPRIO_ALTIVEC_UNAVAIL];
+ break;
+ case SPRN_IVOR33:
+ *spr_val = vcpu->arch.ivor[BOOKE_IRQPRIO_ALTIVEC_ASSIST];
+ break;
+#endif
case SPRN_IVOR35:
*spr_val = vcpu->arch.ivor[BOOKE_IRQPRIO_PERFORMANCE_MONITOR];
break;
--
1.7.11.7
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH v3 3/5] KVM: PPC: Move ONE_REG AltiVec support to powerpc
2014-08-05 10:39 [PATCH v3 0/5] KVM: PPC: Book3e: AltiVec support Mihai Caraman
2014-08-05 10:39 ` [PATCH v3 1/5] KVM: PPC: Book3e: Increase FPU laziness Mihai Caraman
2014-08-05 10:39 ` [PATCH v3 2/5] KVM: PPC: Book3e: Add AltiVec support Mihai Caraman
@ 2014-08-05 10:39 ` Mihai Caraman
2014-08-12 11:47 ` Alexander Graf
2014-08-05 10:39 ` [PATCH v3 4/5] KVM: PPC: Booke: Add ONE_REG IVORs support Mihai Caraman
2014-08-05 10:39 ` [PATCH v3 5/5] KVM: PPC: Book3E: Enable e6500 core Mihai Caraman
4 siblings, 1 reply; 9+ messages in thread
From: Mihai Caraman @ 2014-08-05 10:39 UTC (permalink / raw)
To: kvm-ppc; +Cc: kvm, Mihai Caraman
Make ONE_REG AltiVec support common across server and embedded implementations
moving kvm_vcpu_ioctl_get_one_reg() and kvm_vcpu_ioctl_set_one_reg() functions
to powerpc layer.
Signed-off-by: Mihai Caraman <mihai.caraman@freescale.com>
---
v3:
- make ONE_REG AltiVec support powerpc generic
v2:
- add comment describing VCSR register representation in KVM vs kernel
arch/powerpc/include/uapi/asm/kvm.h | 5 ++
arch/powerpc/kvm/book3s.c | 151 +++++++++++-------------------------
arch/powerpc/kvm/booke.c | 85 ++++++++------------
arch/powerpc/kvm/powerpc.c | 97 +++++++++++++++++++++++
4 files changed, 179 insertions(+), 159 deletions(-)
diff --git a/arch/powerpc/include/uapi/asm/kvm.h b/arch/powerpc/include/uapi/asm/kvm.h
index e0e49db..7a27ff0 100644
--- a/arch/powerpc/include/uapi/asm/kvm.h
+++ b/arch/powerpc/include/uapi/asm/kvm.h
@@ -476,6 +476,11 @@ struct kvm_get_htab_header {
/* FP and vector status/control registers */
#define KVM_REG_PPC_FPSCR (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x80)
+/*
+ * VSCR register is documented as a 32-bit register in the ISA, but it can
+ * only be accesses via a vector register. Expose VSCR as a 32-bit register
+ * even though the kernel represents it as a 128-bit vector.
+ */
#define KVM_REG_PPC_VSCR (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x81)
/* Virtual processor areas */
diff --git a/arch/powerpc/kvm/book3s.c b/arch/powerpc/kvm/book3s.c
index dd03f6b..1b5adda 100644
--- a/arch/powerpc/kvm/book3s.c
+++ b/arch/powerpc/kvm/book3s.c
@@ -535,174 +535,111 @@ int kvm_arch_vcpu_ioctl_set_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu)
return -ENOTSUPP;
}
-int kvm_vcpu_ioctl_get_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg)
+int kvmppc_get_one_reg(struct kvm_vcpu *vcpu, u64 id,
+ union kvmppc_one_reg *val)
{
- int r;
- union kvmppc_one_reg val;
- int size;
+ int r = 0;
long int i;
- size = one_reg_size(reg->id);
- if (size > sizeof(val))
- return -EINVAL;
-
- r = vcpu->kvm->arch.kvm_ops->get_one_reg(vcpu, reg->id, &val);
+ r = vcpu->kvm->arch.kvm_ops->get_one_reg(vcpu, id, val);
if (r == -EINVAL) {
r = 0;
- switch (reg->id) {
+ switch (id) {
case KVM_REG_PPC_DAR:
- val = get_reg_val(reg->id, kvmppc_get_dar(vcpu));
+ *val = get_reg_val(id, kvmppc_get_dar(vcpu));
break;
case KVM_REG_PPC_DSISR:
- val = get_reg_val(reg->id, kvmppc_get_dsisr(vcpu));
+ *val = get_reg_val(id, kvmppc_get_dsisr(vcpu));
break;
case KVM_REG_PPC_FPR0 ... KVM_REG_PPC_FPR31:
- i = reg->id - KVM_REG_PPC_FPR0;
- val = get_reg_val(reg->id, VCPU_FPR(vcpu, i));
+ i = id - KVM_REG_PPC_FPR0;
+ *val = get_reg_val(id, VCPU_FPR(vcpu, i));
break;
case KVM_REG_PPC_FPSCR:
- val = get_reg_val(reg->id, vcpu->arch.fp.fpscr);
- break;
-#ifdef CONFIG_ALTIVEC
- case KVM_REG_PPC_VR0 ... KVM_REG_PPC_VR31:
- if (!cpu_has_feature(CPU_FTR_ALTIVEC)) {
- r = -ENXIO;
- break;
- }
- val.vval = vcpu->arch.vr.vr[reg->id - KVM_REG_PPC_VR0];
+ *val = get_reg_val(id, vcpu->arch.fp.fpscr);
break;
- case KVM_REG_PPC_VSCR:
- if (!cpu_has_feature(CPU_FTR_ALTIVEC)) {
- r = -ENXIO;
- break;
- }
- val = get_reg_val(reg->id, vcpu->arch.vr.vscr.u[3]);
- break;
- case KVM_REG_PPC_VRSAVE:
- val = get_reg_val(reg->id, vcpu->arch.vrsave);
- break;
-#endif /* CONFIG_ALTIVEC */
#ifdef CONFIG_VSX
case KVM_REG_PPC_VSR0 ... KVM_REG_PPC_VSR31:
if (cpu_has_feature(CPU_FTR_VSX)) {
- long int i = reg->id - KVM_REG_PPC_VSR0;
- val.vsxval[0] = vcpu->arch.fp.fpr[i][0];
- val.vsxval[1] = vcpu->arch.fp.fpr[i][1];
+ i = id - KVM_REG_PPC_VSR0;
+ val->vsxval[0] = vcpu->arch.fp.fpr[i][0];
+ val->vsxval[1] = vcpu->arch.fp.fpr[i][1];
} else {
r = -ENXIO;
}
break;
#endif /* CONFIG_VSX */
- case KVM_REG_PPC_DEBUG_INST: {
- u32 opcode = INS_TW;
- r = copy_to_user((u32 __user *)(long)reg->addr,
- &opcode, sizeof(u32));
+ case KVM_REG_PPC_DEBUG_INST:
+ *val = get_reg_val(id, INS_TW);
break;
- }
#ifdef CONFIG_KVM_XICS
case KVM_REG_PPC_ICP_STATE:
if (!vcpu->arch.icp) {
r = -ENXIO;
break;
}
- val = get_reg_val(reg->id, kvmppc_xics_get_icp(vcpu));
+ *val = get_reg_val(id, kvmppc_xics_get_icp(vcpu));
break;
#endif /* CONFIG_KVM_XICS */
case KVM_REG_PPC_FSCR:
- val = get_reg_val(reg->id, vcpu->arch.fscr);
+ *val = get_reg_val(id, vcpu->arch.fscr);
break;
case KVM_REG_PPC_TAR:
- val = get_reg_val(reg->id, vcpu->arch.tar);
+ *val = get_reg_val(id, vcpu->arch.tar);
break;
case KVM_REG_PPC_EBBHR:
- val = get_reg_val(reg->id, vcpu->arch.ebbhr);
+ *val = get_reg_val(id, vcpu->arch.ebbhr);
break;
case KVM_REG_PPC_EBBRR:
- val = get_reg_val(reg->id, vcpu->arch.ebbrr);
+ *val = get_reg_val(id, vcpu->arch.ebbrr);
break;
case KVM_REG_PPC_BESCR:
- val = get_reg_val(reg->id, vcpu->arch.bescr);
+ *val = get_reg_val(id, vcpu->arch.bescr);
break;
case KVM_REG_PPC_VTB:
- val = get_reg_val(reg->id, vcpu->arch.vtb);
+ *val = get_reg_val(id, vcpu->arch.vtb);
break;
case KVM_REG_PPC_IC:
- val = get_reg_val(reg->id, vcpu->arch.ic);
+ *val = get_reg_val(id, vcpu->arch.ic);
break;
default:
r = -EINVAL;
break;
}
}
- if (r)
- return r;
-
- if (copy_to_user((char __user *)(unsigned long)reg->addr, &val, size))
- r = -EFAULT;
return r;
}
-int kvm_vcpu_ioctl_set_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg)
+int kvmppc_set_one_reg(struct kvm_vcpu *vcpu, u64 id,
+ union kvmppc_one_reg *val)
{
- int r;
- union kvmppc_one_reg val;
- int size;
+ int r = 0;
long int i;
- size = one_reg_size(reg->id);
- if (size > sizeof(val))
- return -EINVAL;
-
- if (copy_from_user(&val, (char __user *)(unsigned long)reg->addr, size))
- return -EFAULT;
-
- r = vcpu->kvm->arch.kvm_ops->set_one_reg(vcpu, reg->id, &val);
+ r = vcpu->kvm->arch.kvm_ops->set_one_reg(vcpu, id, val);
if (r == -EINVAL) {
r = 0;
- switch (reg->id) {
+ switch (id) {
case KVM_REG_PPC_DAR:
- kvmppc_set_dar(vcpu, set_reg_val(reg->id, val));
+ kvmppc_set_dar(vcpu, set_reg_val(id, *val));
break;
case KVM_REG_PPC_DSISR:
- kvmppc_set_dsisr(vcpu, set_reg_val(reg->id, val));
+ kvmppc_set_dsisr(vcpu, set_reg_val(id, *val));
break;
case KVM_REG_PPC_FPR0 ... KVM_REG_PPC_FPR31:
- i = reg->id - KVM_REG_PPC_FPR0;
- VCPU_FPR(vcpu, i) = set_reg_val(reg->id, val);
+ i = id - KVM_REG_PPC_FPR0;
+ VCPU_FPR(vcpu, i) = set_reg_val(id, *val);
break;
case KVM_REG_PPC_FPSCR:
- vcpu->arch.fp.fpscr = set_reg_val(reg->id, val);
- break;
-#ifdef CONFIG_ALTIVEC
- case KVM_REG_PPC_VR0 ... KVM_REG_PPC_VR31:
- if (!cpu_has_feature(CPU_FTR_ALTIVEC)) {
- r = -ENXIO;
- break;
- }
- vcpu->arch.vr.vr[reg->id - KVM_REG_PPC_VR0] = val.vval;
- break;
- case KVM_REG_PPC_VSCR:
- if (!cpu_has_feature(CPU_FTR_ALTIVEC)) {
- r = -ENXIO;
- break;
- }
- vcpu->arch.vr.vscr.u[3] = set_reg_val(reg->id, val);
- break;
- case KVM_REG_PPC_VRSAVE:
- if (!cpu_has_feature(CPU_FTR_ALTIVEC)) {
- r = -ENXIO;
- break;
- }
- vcpu->arch.vrsave = set_reg_val(reg->id, val);
+ vcpu->arch.fp.fpscr = set_reg_val(id, *val);
break;
-#endif /* CONFIG_ALTIVEC */
#ifdef CONFIG_VSX
case KVM_REG_PPC_VSR0 ... KVM_REG_PPC_VSR31:
if (cpu_has_feature(CPU_FTR_VSX)) {
- long int i = reg->id - KVM_REG_PPC_VSR0;
- vcpu->arch.fp.fpr[i][0] = val.vsxval[0];
- vcpu->arch.fp.fpr[i][1] = val.vsxval[1];
+ i = id - KVM_REG_PPC_VSR0;
+ vcpu->arch.fp.fpr[i][0] = val->vsxval[0];
+ vcpu->arch.fp.fpr[i][1] = val->vsxval[1];
} else {
r = -ENXIO;
}
@@ -715,29 +652,29 @@ int kvm_vcpu_ioctl_set_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg)
break;
}
r = kvmppc_xics_set_icp(vcpu,
- set_reg_val(reg->id, val));
+ set_reg_val(id, *val));
break;
#endif /* CONFIG_KVM_XICS */
case KVM_REG_PPC_FSCR:
- vcpu->arch.fscr = set_reg_val(reg->id, val);
+ vcpu->arch.fscr = set_reg_val(id, *val);
break;
case KVM_REG_PPC_TAR:
- vcpu->arch.tar = set_reg_val(reg->id, val);
+ vcpu->arch.tar = set_reg_val(id, *val);
break;
case KVM_REG_PPC_EBBHR:
- vcpu->arch.ebbhr = set_reg_val(reg->id, val);
+ vcpu->arch.ebbhr = set_reg_val(id, *val);
break;
case KVM_REG_PPC_EBBRR:
- vcpu->arch.ebbrr = set_reg_val(reg->id, val);
+ vcpu->arch.ebbrr = set_reg_val(id, *val);
break;
case KVM_REG_PPC_BESCR:
- vcpu->arch.bescr = set_reg_val(reg->id, val);
+ vcpu->arch.bescr = set_reg_val(id, *val);
break;
case KVM_REG_PPC_VTB:
- vcpu->arch.vtb = set_reg_val(reg->id, val);
+ vcpu->arch.vtb = set_reg_val(id, *val);
break;
case KVM_REG_PPC_IC:
- vcpu->arch.ic = set_reg_val(reg->id, val);
+ vcpu->arch.ic = set_reg_val(id, *val);
break;
default:
r = -EINVAL;
diff --git a/arch/powerpc/kvm/booke.c b/arch/powerpc/kvm/booke.c
index c5cca09..4fe7f68 100644
--- a/arch/powerpc/kvm/booke.c
+++ b/arch/powerpc/kvm/booke.c
@@ -1559,144 +1559,125 @@ int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu,
return vcpu->kvm->arch.kvm_ops->set_sregs(vcpu, sregs);
}
-int kvm_vcpu_ioctl_get_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg)
+int kvmppc_get_one_reg(struct kvm_vcpu *vcpu, u64 id,
+ union kvmppc_one_reg *val)
{
int r = 0;
- union kvmppc_one_reg val;
- int size;
- size = one_reg_size(reg->id);
- if (size > sizeof(val))
- return -EINVAL;
-
- switch (reg->id) {
+ switch (id) {
case KVM_REG_PPC_IAC1:
- val = get_reg_val(reg->id, vcpu->arch.dbg_reg.iac1);
+ *val = get_reg_val(id, vcpu->arch.dbg_reg.iac1);
break;
case KVM_REG_PPC_IAC2:
- val = get_reg_val(reg->id, vcpu->arch.dbg_reg.iac2);
+ *val = get_reg_val(id, vcpu->arch.dbg_reg.iac2);
break;
#if CONFIG_PPC_ADV_DEBUG_IACS > 2
case KVM_REG_PPC_IAC3:
- val = get_reg_val(reg->id, vcpu->arch.dbg_reg.iac3);
+ *val = get_reg_val(id, vcpu->arch.dbg_reg.iac3);
break;
case KVM_REG_PPC_IAC4:
- val = get_reg_val(reg->id, vcpu->arch.dbg_reg.iac4);
+ *val = get_reg_val(id, vcpu->arch.dbg_reg.iac4);
break;
#endif
case KVM_REG_PPC_DAC1:
- val = get_reg_val(reg->id, vcpu->arch.dbg_reg.dac1);
+ *val = get_reg_val(id, vcpu->arch.dbg_reg.dac1);
break;
case KVM_REG_PPC_DAC2:
- val = get_reg_val(reg->id, vcpu->arch.dbg_reg.dac2);
+ *val = get_reg_val(id, vcpu->arch.dbg_reg.dac2);
break;
case KVM_REG_PPC_EPR: {
u32 epr = kvmppc_get_epr(vcpu);
- val = get_reg_val(reg->id, epr);
+ *val = get_reg_val(id, epr);
break;
}
#if defined(CONFIG_64BIT)
case KVM_REG_PPC_EPCR:
- val = get_reg_val(reg->id, vcpu->arch.epcr);
+ *val = get_reg_val(id, vcpu->arch.epcr);
break;
#endif
case KVM_REG_PPC_TCR:
- val = get_reg_val(reg->id, vcpu->arch.tcr);
+ *val = get_reg_val(id, vcpu->arch.tcr);
break;
case KVM_REG_PPC_TSR:
- val = get_reg_val(reg->id, vcpu->arch.tsr);
+ *val = get_reg_val(id, vcpu->arch.tsr);
break;
case KVM_REG_PPC_DEBUG_INST:
- val = get_reg_val(reg->id, KVMPPC_INST_EHPRIV_DEBUG);
+ *val = get_reg_val(id, KVMPPC_INST_EHPRIV_DEBUG);
break;
case KVM_REG_PPC_VRSAVE:
- val = get_reg_val(reg->id, vcpu->arch.vrsave);
+ *val = get_reg_val(id, vcpu->arch.vrsave);
break;
default:
- r = vcpu->kvm->arch.kvm_ops->get_one_reg(vcpu, reg->id, &val);
+ r = vcpu->kvm->arch.kvm_ops->get_one_reg(vcpu, id, val);
break;
}
- if (r)
- return r;
-
- if (copy_to_user((char __user *)(unsigned long)reg->addr, &val, size))
- r = -EFAULT;
-
return r;
}
-int kvm_vcpu_ioctl_set_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg)
+int kvmppc_set_one_reg(struct kvm_vcpu *vcpu, u64 id,
+ union kvmppc_one_reg *val)
{
int r = 0;
- union kvmppc_one_reg val;
- int size;
-
- size = one_reg_size(reg->id);
- if (size > sizeof(val))
- return -EINVAL;
-
- if (copy_from_user(&val, (char __user *)(unsigned long)reg->addr, size))
- return -EFAULT;
- switch (reg->id) {
+ switch (id) {
case KVM_REG_PPC_IAC1:
- vcpu->arch.dbg_reg.iac1 = set_reg_val(reg->id, val);
+ vcpu->arch.dbg_reg.iac1 = set_reg_val(id, *val);
break;
case KVM_REG_PPC_IAC2:
- vcpu->arch.dbg_reg.iac2 = set_reg_val(reg->id, val);
+ vcpu->arch.dbg_reg.iac2 = set_reg_val(id, *val);
break;
#if CONFIG_PPC_ADV_DEBUG_IACS > 2
case KVM_REG_PPC_IAC3:
- vcpu->arch.dbg_reg.iac3 = set_reg_val(reg->id, val);
+ vcpu->arch.dbg_reg.iac3 = set_reg_val(id, *val);
break;
case KVM_REG_PPC_IAC4:
- vcpu->arch.dbg_reg.iac4 = set_reg_val(reg->id, val);
+ vcpu->arch.dbg_reg.iac4 = set_reg_val(id, *val);
break;
#endif
case KVM_REG_PPC_DAC1:
- vcpu->arch.dbg_reg.dac1 = set_reg_val(reg->id, val);
+ vcpu->arch.dbg_reg.dac1 = set_reg_val(id, *val);
break;
case KVM_REG_PPC_DAC2:
- vcpu->arch.dbg_reg.dac2 = set_reg_val(reg->id, val);
+ vcpu->arch.dbg_reg.dac2 = set_reg_val(id, *val);
break;
case KVM_REG_PPC_EPR: {
- u32 new_epr = set_reg_val(reg->id, val);
+ u32 new_epr = set_reg_val(id, *val);
kvmppc_set_epr(vcpu, new_epr);
break;
}
#if defined(CONFIG_64BIT)
case KVM_REG_PPC_EPCR: {
- u32 new_epcr = set_reg_val(reg->id, val);
+ u32 new_epcr = set_reg_val(id, *val);
kvmppc_set_epcr(vcpu, new_epcr);
break;
}
#endif
case KVM_REG_PPC_OR_TSR: {
- u32 tsr_bits = set_reg_val(reg->id, val);
+ u32 tsr_bits = set_reg_val(id, *val);
kvmppc_set_tsr_bits(vcpu, tsr_bits);
break;
}
case KVM_REG_PPC_CLEAR_TSR: {
- u32 tsr_bits = set_reg_val(reg->id, val);
+ u32 tsr_bits = set_reg_val(id, *val);
kvmppc_clr_tsr_bits(vcpu, tsr_bits);
break;
}
case KVM_REG_PPC_TSR: {
- u32 tsr = set_reg_val(reg->id, val);
+ u32 tsr = set_reg_val(id, *val);
kvmppc_set_tsr(vcpu, tsr);
break;
}
case KVM_REG_PPC_TCR: {
- u32 tcr = set_reg_val(reg->id, val);
+ u32 tcr = set_reg_val(id, *val);
kvmppc_set_tcr(vcpu, tcr);
break;
}
case KVM_REG_PPC_VRSAVE:
- vcpu->arch.vrsave = set_reg_val(reg->id, val);
+ vcpu->arch.vrsave = set_reg_val(id, *val);
break;
default:
- r = vcpu->kvm->arch.kvm_ops->set_one_reg(vcpu, reg->id, &val);
+ r = vcpu->kvm->arch.kvm_ops->set_one_reg(vcpu, id, val);
break;
}
diff --git a/arch/powerpc/kvm/powerpc.c b/arch/powerpc/kvm/powerpc.c
index 288b4bb..2e10ddb 100644
--- a/arch/powerpc/kvm/powerpc.c
+++ b/arch/powerpc/kvm/powerpc.c
@@ -927,6 +927,103 @@ int kvmppc_handle_store(struct kvm_run *run, struct kvm_vcpu *vcpu,
}
EXPORT_SYMBOL_GPL(kvmppc_handle_store);
+int kvm_vcpu_ioctl_get_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg)
+{
+ int r = 0;
+ union kvmppc_one_reg val;
+ int size;
+
+ size = one_reg_size(reg->id);
+ if (size > sizeof(val))
+ return -EINVAL;
+
+ r = kvmppc_get_one_reg(vcpu, reg->id, &val);
+ if (r == -EINVAL) {
+ r = 0;
+ switch (reg->id) {
+#ifdef CONFIG_ALTIVEC
+ case KVM_REG_PPC_VR0 ... KVM_REG_PPC_VR31:
+ if (!cpu_has_feature(CPU_FTR_ALTIVEC)) {
+ r = -ENXIO;
+ break;
+ }
+ val.vval = vcpu->arch.vr.vr[reg->id - KVM_REG_PPC_VR0];
+ break;
+ case KVM_REG_PPC_VSCR:
+ if (!cpu_has_feature(CPU_FTR_ALTIVEC)) {
+ r = -ENXIO;
+ break;
+ }
+ val = get_reg_val(reg->id, vcpu->arch.vr.vscr.u[3]);
+ break;
+ case KVM_REG_PPC_VRSAVE:
+ val = get_reg_val(reg->id, vcpu->arch.vrsave);
+ break;
+#endif /* CONFIG_ALTIVEC */
+ default:
+ r = -EINVAL;
+ break;
+ }
+ }
+
+ if (r)
+ return r;
+
+ if (copy_to_user((char __user *)(unsigned long)reg->addr, &val, size))
+ r = -EFAULT;
+
+ return r;
+}
+
+int kvm_vcpu_ioctl_set_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg)
+{
+ int r;
+ union kvmppc_one_reg val;
+ int size;
+
+ size = one_reg_size(reg->id);
+ if (size > sizeof(val))
+ return -EINVAL;
+
+ if (copy_from_user(&val, (char __user *)(unsigned long)reg->addr, size))
+ return -EFAULT;
+
+ r = kvmppc_set_one_reg(vcpu, reg->id, &val);
+ if (r == -EINVAL) {
+ r = 0;
+ switch (reg->id) {
+#ifdef CONFIG_ALTIVEC
+ case KVM_REG_PPC_VR0 ... KVM_REG_PPC_VR31:
+ if (!cpu_has_feature(CPU_FTR_ALTIVEC)) {
+ r = -ENXIO;
+ break;
+ }
+ vcpu->arch.vr.vr[reg->id - KVM_REG_PPC_VR0] = val.vval;
+ break;
+ case KVM_REG_PPC_VSCR:
+ if (!cpu_has_feature(CPU_FTR_ALTIVEC)) {
+ r = -ENXIO;
+ break;
+ }
+ vcpu->arch.vr.vscr.u[3] = set_reg_val(reg->id, val);
+ break;
+ case KVM_REG_PPC_VRSAVE:
+ if (!cpu_has_feature(CPU_FTR_ALTIVEC)) {
+ r = -ENXIO;
+ break;
+ }
+ vcpu->arch.vrsave = set_reg_val(reg->id, val);
+ break;
+#endif /* CONFIG_ALTIVEC */
+ default:
+ r = -EINVAL;
+ break;
+ }
+ }
+
+ return r;
+}
+
int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *run)
{
int r;
--
1.7.11.7
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH v3 4/5] KVM: PPC: Booke: Add ONE_REG IVORs support
2014-08-05 10:39 [PATCH v3 0/5] KVM: PPC: Book3e: AltiVec support Mihai Caraman
` (2 preceding siblings ...)
2014-08-05 10:39 ` [PATCH v3 3/5] KVM: PPC: Move ONE_REG AltiVec support to powerpc Mihai Caraman
@ 2014-08-05 10:39 ` Mihai Caraman
2014-08-12 11:48 ` Alexander Graf
2014-08-05 10:39 ` [PATCH v3 5/5] KVM: PPC: Book3E: Enable e6500 core Mihai Caraman
4 siblings, 1 reply; 9+ messages in thread
From: Mihai Caraman @ 2014-08-05 10:39 UTC (permalink / raw)
To: kvm-ppc; +Cc: kvm, Mihai Caraman
Add ONE_REG IVORs support, with IVORs 0-15 and 35 booke common.
Signed-off-by: Mihai Caraman <mihai.caraman@freescale.com>
---
v3:
- new patch
arch/powerpc/include/uapi/asm/kvm.h | 24 +++++++
arch/powerpc/kvm/booke.c | 132 ++++++++++++++++++++++++++++++++++++
arch/powerpc/kvm/e500.c | 42 +++++++++++-
arch/powerpc/kvm/e500mc.c | 32 +++++++++
4 files changed, 228 insertions(+), 2 deletions(-)
diff --git a/arch/powerpc/include/uapi/asm/kvm.h b/arch/powerpc/include/uapi/asm/kvm.h
index 7a27ff0..174fed0 100644
--- a/arch/powerpc/include/uapi/asm/kvm.h
+++ b/arch/powerpc/include/uapi/asm/kvm.h
@@ -563,6 +563,30 @@ struct kvm_get_htab_header {
#define KVM_REG_PPC_WORT (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xb9)
#define KVM_REG_PPC_SPRG9 (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xba)
+/* Booke IVOR registers */
+#define KVM_REG_PPC_IVOR0 (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0xc0)
+#define KVM_REG_PPC_IVOR1 (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0xc1)
+#define KVM_REG_PPC_IVOR2 (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0xc2)
+#define KVM_REG_PPC_IVOR3 (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0xc3)
+#define KVM_REG_PPC_IVOR4 (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0xc4)
+#define KVM_REG_PPC_IVOR5 (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0xc5)
+#define KVM_REG_PPC_IVOR6 (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0xc6)
+#define KVM_REG_PPC_IVOR7 (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0xc7)
+#define KVM_REG_PPC_IVOR8 (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0xc8)
+#define KVM_REG_PPC_IVOR9 (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0xc9)
+#define KVM_REG_PPC_IVOR10 (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0xca)
+#define KVM_REG_PPC_IVOR11 (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0xcb)
+#define KVM_REG_PPC_IVOR12 (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0xcc)
+#define KVM_REG_PPC_IVOR13 (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0xcd)
+#define KVM_REG_PPC_IVOR14 (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0xce)
+#define KVM_REG_PPC_IVOR15 (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0xcf)
+#define KVM_REG_PPC_IVOR32 (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0xd0)
+#define KVM_REG_PPC_IVOR33 (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0xd1)
+#define KVM_REG_PPC_IVOR34 (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0xd2)
+#define KVM_REG_PPC_IVOR35 (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0xd3)
+#define KVM_REG_PPC_IVOR36 (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0xd4)
+#define KVM_REG_PPC_IVOR37 (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0xd5)
+
/* Transactional Memory checkpointed state:
* This is all GPRs, all VSX regs and a subset of SPRs
*/
diff --git a/arch/powerpc/kvm/booke.c b/arch/powerpc/kvm/booke.c
index 4fe7f68..ffa82a5 100644
--- a/arch/powerpc/kvm/booke.c
+++ b/arch/powerpc/kvm/booke.c
@@ -1565,6 +1565,72 @@ int kvmppc_get_one_reg(struct kvm_vcpu *vcpu, u64 id,
int r = 0;
switch (id) {
+ case KVM_REG_PPC_IVOR0:
+ *val = get_reg_val(id,
+ vcpu->arch.ivor[BOOKE_IRQPRIO_CRITICAL]);
+ break;
+ case KVM_REG_PPC_IVOR1:
+ *val = get_reg_val(id,
+ vcpu->arch.ivor[BOOKE_IRQPRIO_MACHINE_CHECK]);
+ break;
+ case KVM_REG_PPC_IVOR2:
+ *val = get_reg_val(id,
+ vcpu->arch.ivor[BOOKE_IRQPRIO_DATA_STORAGE]);
+ break;
+ case KVM_REG_PPC_IVOR3:
+ *val = get_reg_val(id,
+ vcpu->arch.ivor[BOOKE_IRQPRIO_INST_STORAGE]);
+ break;
+ case KVM_REG_PPC_IVOR4:
+ *val = get_reg_val(id,
+ vcpu->arch.ivor[BOOKE_IRQPRIO_EXTERNAL]);
+ break;
+ case KVM_REG_PPC_IVOR5:
+ *val = get_reg_val(id,
+ vcpu->arch.ivor[BOOKE_IRQPRIO_ALIGNMENT]);
+ break;
+ case KVM_REG_PPC_IVOR6:
+ *val = get_reg_val(id, vcpu->arch.ivor[BOOKE_IRQPRIO_PROGRAM]);
+ break;
+ case KVM_REG_PPC_IVOR7:
+ *val = get_reg_val(id,
+ vcpu->arch.ivor[BOOKE_IRQPRIO_FP_UNAVAIL]);
+ break;
+ case KVM_REG_PPC_IVOR8:
+ *val = get_reg_val(id,
+ vcpu->arch.ivor[BOOKE_IRQPRIO_CRITICAL]);
+ break;
+ case KVM_REG_PPC_IVOR9:
+ *val = get_reg_val(id,
+ vcpu->arch.ivor[BOOKE_IRQPRIO_AP_UNAVAIL]);
+ break;
+ case KVM_REG_PPC_IVOR10:
+ *val = get_reg_val(id,
+ vcpu->arch.ivor[BOOKE_IRQPRIO_DECREMENTER]);
+ break;
+ case KVM_REG_PPC_IVOR11:
+ *val = get_reg_val(id, vcpu->arch.ivor[BOOKE_IRQPRIO_FIT]);
+ break;
+ case KVM_REG_PPC_IVOR12:
+ *val = get_reg_val(id,
+ vcpu->arch.ivor[BOOKE_IRQPRIO_WATCHDOG]);
+ break;
+ case KVM_REG_PPC_IVOR13:
+ *val = get_reg_val(id,
+ vcpu->arch.ivor[BOOKE_IRQPRIO_DTLB_MISS]);
+ break;
+ case KVM_REG_PPC_IVOR14:
+ *val = get_reg_val(id,
+ vcpu->arch.ivor[BOOKE_IRQPRIO_ITLB_MISS]);
+ break;
+ case KVM_REG_PPC_IVOR15:
+ *val = get_reg_val(id,
+ vcpu->arch.ivor[BOOKE_IRQPRIO_DEBUG]);
+ break;
+ case KVM_REG_PPC_IVOR35:
+ *val = get_reg_val(id,
+ vcpu->arch.ivor[BOOKE_IRQPRIO_PERFORMANCE_MONITOR]);
+ break;
case KVM_REG_PPC_IAC1:
*val = get_reg_val(id, vcpu->arch.dbg_reg.iac1);
break;
@@ -1621,6 +1687,72 @@ int kvmppc_set_one_reg(struct kvm_vcpu *vcpu, u64 id,
int r = 0;
switch (id) {
+ case KVM_REG_PPC_IVOR0:
+ vcpu->arch.ivor[BOOKE_IRQPRIO_CRITICAL] =
+ set_reg_val(id, *val);
+ break;
+ case KVM_REG_PPC_IVOR1:
+ vcpu->arch.ivor[BOOKE_IRQPRIO_MACHINE_CHECK] =
+ set_reg_val(id, *val);
+ break;
+ case KVM_REG_PPC_IVOR2:
+ vcpu->arch.ivor[BOOKE_IRQPRIO_DATA_STORAGE] =
+ set_reg_val(id, *val);
+ break;
+ case KVM_REG_PPC_IVOR3:
+ vcpu->arch.ivor[BOOKE_IRQPRIO_INST_STORAGE] =
+ set_reg_val(id, *val);
+ break;
+ case KVM_REG_PPC_IVOR4:
+ vcpu->arch.ivor[BOOKE_IRQPRIO_EXTERNAL] =
+ set_reg_val(id, *val);
+ break;
+ case KVM_REG_PPC_IVOR5:
+ vcpu->arch.ivor[BOOKE_IRQPRIO_ALIGNMENT] =
+ set_reg_val(id, *val);
+ break;
+ case KVM_REG_PPC_IVOR6:
+ vcpu->arch.ivor[BOOKE_IRQPRIO_PROGRAM] =
+ set_reg_val(id, *val);
+ break;
+ case KVM_REG_PPC_IVOR7:
+ vcpu->arch.ivor[BOOKE_IRQPRIO_FP_UNAVAIL] =
+ set_reg_val(id, *val);
+ break;
+ case KVM_REG_PPC_IVOR8:
+ vcpu->arch.ivor[BOOKE_IRQPRIO_CRITICAL] =
+ set_reg_val(id, *val);
+ break;
+ case KVM_REG_PPC_IVOR9:
+ vcpu->arch.ivor[BOOKE_IRQPRIO_AP_UNAVAIL] =
+ set_reg_val(id, *val);
+ break;
+ case KVM_REG_PPC_IVOR10:
+ vcpu->arch.ivor[BOOKE_IRQPRIO_DECREMENTER] =
+ set_reg_val(id, *val);
+ break;
+ case KVM_REG_PPC_IVOR11:
+ vcpu->arch.ivor[BOOKE_IRQPRIO_FIT] = set_reg_val(id, *val);
+ break;
+ case KVM_REG_PPC_IVOR12:
+ vcpu->arch.ivor[BOOKE_IRQPRIO_WATCHDOG] =
+ set_reg_val(id, *val);
+ break;
+ case KVM_REG_PPC_IVOR13:
+ vcpu->arch.ivor[BOOKE_IRQPRIO_DTLB_MISS] =
+ set_reg_val(id, *val);
+ break;
+ case KVM_REG_PPC_IVOR14:
+ vcpu->arch.ivor[BOOKE_IRQPRIO_ITLB_MISS] =
+ set_reg_val(id, *val);
+ break;
+ case KVM_REG_PPC_IVOR15:
+ vcpu->arch.ivor[BOOKE_IRQPRIO_DEBUG] = set_reg_val(id, *val);
+ break;
+ case KVM_REG_PPC_IVOR35:
+ vcpu->arch.ivor[BOOKE_IRQPRIO_PERFORMANCE_MONITOR] =
+ set_reg_val(id, *val);
+ break;
case KVM_REG_PPC_IAC1:
vcpu->arch.dbg_reg.iac1 = set_reg_val(id, *val);
break;
diff --git a/arch/powerpc/kvm/e500.c b/arch/powerpc/kvm/e500.c
index 2e02ed8..08f61bf 100644
--- a/arch/powerpc/kvm/e500.c
+++ b/arch/powerpc/kvm/e500.c
@@ -433,14 +433,52 @@ static int kvmppc_core_set_sregs_e500(struct kvm_vcpu *vcpu,
static int kvmppc_get_one_reg_e500(struct kvm_vcpu *vcpu, u64 id,
union kvmppc_one_reg *val)
{
- int r = kvmppc_get_one_reg_e500_tlb(vcpu, id, val);
+ int r = 0;
+
+ switch (id) {
+ case KVM_REG_PPC_IVOR32:
+ *val = get_reg_val(id,
+ vcpu->arch.ivor[BOOKE_IRQPRIO_SPE_UNAVAIL]);
+ break;
+ case KVM_REG_PPC_IVOR33:
+ *val = get_reg_val(id,
+ vcpu->arch.ivor[BOOKE_IRQPRIO_SPE_FP_DATA]);
+ break;
+ case KVM_REG_PPC_IVOR34:
+ *val = get_reg_val(id,
+ vcpu->arch.ivor[BOOKE_IRQPRIO_SPE_FP_ROUND]);
+ break;
+ default:
+ r = kvmppc_get_one_reg_e500_tlb(vcpu, id, val);
+ break;
+ }
+
return r;
}
static int kvmppc_set_one_reg_e500(struct kvm_vcpu *vcpu, u64 id,
union kvmppc_one_reg *val)
{
- int r = kvmppc_get_one_reg_e500_tlb(vcpu, id, val);
+ int r = 0;
+
+ switch (id) {
+ case KVM_REG_PPC_IVOR32:
+ vcpu->arch.ivor[BOOKE_IRQPRIO_SPE_UNAVAIL] =
+ set_reg_val(id, *val);
+ break;
+ case KVM_REG_PPC_IVOR33:
+ vcpu->arch.ivor[BOOKE_IRQPRIO_SPE_FP_DATA] =
+ set_reg_val(id, *val);
+ break;
+ case KVM_REG_PPC_IVOR34:
+ vcpu->arch.ivor[BOOKE_IRQPRIO_SPE_FP_ROUND] =
+ set_reg_val(id, *val);
+ break;
+ default:
+ r = kvmppc_get_one_reg_e500_tlb(vcpu, id, val);
+ break;
+ }
+
return r;
}
diff --git a/arch/powerpc/kvm/e500mc.c b/arch/powerpc/kvm/e500mc.c
index 67c06eb..19dd927 100644
--- a/arch/powerpc/kvm/e500mc.c
+++ b/arch/powerpc/kvm/e500mc.c
@@ -268,6 +268,22 @@ static int kvmppc_get_one_reg_e500mc(struct kvm_vcpu *vcpu, u64 id,
int r = 0;
switch (id) {
+ case KVM_REG_PPC_IVOR32:
+ *val = get_reg_val(id,
+ vcpu->arch.ivor[BOOKE_IRQPRIO_ALTIVEC_UNAVAIL]);
+ break;
+ case KVM_REG_PPC_IVOR33:
+ *val = get_reg_val(id,
+ vcpu->arch.ivor[BOOKE_IRQPRIO_ALTIVEC_ASSIST]);
+ break;
+ case KVM_REG_PPC_IVOR36:
+ *val = get_reg_val(id,
+ vcpu->arch.ivor[BOOKE_IRQPRIO_DBELL]);
+ break;
+ case KVM_REG_PPC_IVOR37:
+ *val = get_reg_val(id,
+ vcpu->arch.ivor[BOOKE_IRQPRIO_DBELL_CRIT]);
+ break;
case KVM_REG_PPC_SPRG9:
*val = get_reg_val(id, vcpu->arch.sprg9);
break;
@@ -284,6 +300,22 @@ static int kvmppc_set_one_reg_e500mc(struct kvm_vcpu *vcpu, u64 id,
int r = 0;
switch (id) {
+ case KVM_REG_PPC_IVOR32:
+ vcpu->arch.ivor[BOOKE_IRQPRIO_ALTIVEC_UNAVAIL] =
+ set_reg_val(id, *val);
+ break;
+ case KVM_REG_PPC_IVOR33:
+ vcpu->arch.ivor[BOOKE_IRQPRIO_ALTIVEC_ASSIST] =
+ set_reg_val(id, *val);
+ break;
+ case KVM_REG_PPC_IVOR36:
+ vcpu->arch.ivor[BOOKE_IRQPRIO_DBELL] =
+ set_reg_val(id, *val);
+ break;
+ case KVM_REG_PPC_IVOR37:
+ vcpu->arch.ivor[BOOKE_IRQPRIO_DBELL_CRIT] =
+ set_reg_val(id, *val);
+ break;
case KVM_REG_PPC_SPRG9:
vcpu->arch.sprg9 = set_reg_val(id, *val);
break;
--
1.7.11.7
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH v3 5/5] KVM: PPC: Book3E: Enable e6500 core
2014-08-05 10:39 [PATCH v3 0/5] KVM: PPC: Book3e: AltiVec support Mihai Caraman
` (3 preceding siblings ...)
2014-08-05 10:39 ` [PATCH v3 4/5] KVM: PPC: Booke: Add ONE_REG IVORs support Mihai Caraman
@ 2014-08-05 10:39 ` Mihai Caraman
4 siblings, 0 replies; 9+ messages in thread
From: Mihai Caraman @ 2014-08-05 10:39 UTC (permalink / raw)
To: kvm-ppc; +Cc: kvm, Mihai Caraman
Now that AltiVec support is in place enable e6500 core.
Signed-off-by: Mihai Caraman <mihai.caraman@freescale.com>
---
v2-v3:
- no changes
arch/powerpc/kvm/e500mc.c | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/arch/powerpc/kvm/e500mc.c b/arch/powerpc/kvm/e500mc.c
index 19dd927..aa48dc3 100644
--- a/arch/powerpc/kvm/e500mc.c
+++ b/arch/powerpc/kvm/e500mc.c
@@ -177,6 +177,16 @@ int kvmppc_core_check_processor_compat(void)
r = 0;
else if (strcmp(cur_cpu_spec->cpu_name, "e5500") == 0)
r = 0;
+#ifdef CONFIG_ALTIVEC
+ /*
+ * Since guests have the priviledge to enable AltiVec, we need AltiVec
+ * support in the host to save/restore their context.
+ * Don't use CPU_FTR_ALTIVEC to identify cores with AltiVec unit
+ * because it's cleared in the absence of CONFIG_ALTIVEC!
+ */
+ else if (strcmp(cur_cpu_spec->cpu_name, "e6500") == 0)
+ r = 0;
+#endif
else
r = -ENOTSUPP;
--
1.7.11.7
^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [PATCH v3 2/5] KVM: PPC: Book3e: Add AltiVec support
2014-08-05 10:39 ` [PATCH v3 2/5] KVM: PPC: Book3e: Add AltiVec support Mihai Caraman
@ 2014-08-12 11:45 ` Alexander Graf
0 siblings, 0 replies; 9+ messages in thread
From: Alexander Graf @ 2014-08-12 11:45 UTC (permalink / raw)
To: Mihai Caraman, kvm-ppc; +Cc: kvm
On 05.08.14 12:39, Mihai Caraman wrote:
> Add KVM Book3e AltiVec support. KVM Book3e FPU support gracefully reuse host
> infrastructure so follow the same approach for AltiVec.
>
> Keep SPE/AltiVec exception handlers distinct using CONFIG_KVM_E500V2.
>
> Signed-off-by: Mihai Caraman <mihai.caraman@freescale.com>
> ---
> v3:
> - use distinct SPE/AltiVec exception handlers
>
> v2:
> - integrate Paul's FP/VMX/VSX changes
>
> arch/powerpc/kvm/booke.c | 73 +++++++++++++++++++++++++++++++++++
> arch/powerpc/kvm/booke.h | 5 +++
> arch/powerpc/kvm/bookehv_interrupts.S | 10 +++--
> arch/powerpc/kvm/e500_emulate.c | 18 +++++++++
> 4 files changed, 102 insertions(+), 4 deletions(-)
>
> diff --git a/arch/powerpc/kvm/booke.c b/arch/powerpc/kvm/booke.c
> index 0c6f616..c5cca09 100644
> --- a/arch/powerpc/kvm/booke.c
> +++ b/arch/powerpc/kvm/booke.c
> @@ -168,6 +168,40 @@ static void kvmppc_vcpu_sync_fpu(struct kvm_vcpu *vcpu)
> #endif
> }
>
> +/*
> + * Simulate AltiVec unavailable fault to load guest state
> + * from thread to AltiVec unit.
> + * It requires to be called with preemption disabled.
> + */
> +static inline void kvmppc_load_guest_altivec(struct kvm_vcpu *vcpu)
> +{
> +#ifdef CONFIG_ALTIVEC
> + if (cpu_has_feature(CPU_FTR_ALTIVEC)) {
> + if (!(current->thread.regs->msr & MSR_VEC)) {
> + enable_kernel_altivec();
> + load_vr_state(&vcpu->arch.vr);
> + current->thread.vr_save_area = &vcpu->arch.vr;
> + current->thread.regs->msr |= MSR_VEC;
> + }
> + }
> +#endif
> +}
> +
> +/*
> + * Save guest vcpu AltiVec state into thread.
> + * It requires to be called with preemption disabled.
> + */
> +static inline void kvmppc_save_guest_altivec(struct kvm_vcpu *vcpu)
> +{
> +#ifdef CONFIG_ALTIVEC
> + if (cpu_has_feature(CPU_FTR_ALTIVEC)) {
> + if (current->thread.regs->msr & MSR_VEC)
> + giveup_altivec(current);
> + current->thread.vr_save_area = NULL;
> + }
> +#endif
> +}
> +
> static void kvmppc_vcpu_sync_debug(struct kvm_vcpu *vcpu)
> {
> /* Synchronize guest's desire to get debug interrupts into shadow MSR */
> @@ -375,9 +409,14 @@ static int kvmppc_booke_irqprio_deliver(struct kvm_vcpu *vcpu,
> case BOOKE_IRQPRIO_ITLB_MISS:
> case BOOKE_IRQPRIO_SYSCALL:
> case BOOKE_IRQPRIO_FP_UNAVAIL:
> +#ifdef CONFIG_KVM_E500V2
Why not use your new SPE_POSSIBLE define?
> case BOOKE_IRQPRIO_SPE_UNAVAIL:
> case BOOKE_IRQPRIO_SPE_FP_DATA:
> case BOOKE_IRQPRIO_SPE_FP_ROUND:
> +#else
We only ever support altivec capable CPUs with CONFIG_ALTIVEC, no? So
just make this a new #ifdef CONFIG_ALTIVEC
> + case BOOKE_IRQPRIO_ALTIVEC_UNAVAIL:
> + case BOOKE_IRQPRIO_ALTIVEC_ASSIST:
> +#endif
> case BOOKE_IRQPRIO_AP_UNAVAIL:
> allowed = 1;
> msr_mask = MSR_CE | MSR_ME | MSR_DE;
> @@ -693,6 +732,17 @@ int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
> kvmppc_load_guest_fp(vcpu);
> #endif
>
> +#ifdef CONFIG_ALTIVEC
> + /* Save userspace AltiVec state in stack */
> + if (cpu_has_feature(CPU_FTR_ALTIVEC))
> + enable_kernel_altivec();
> + /*
> + * Since we can't trap on MSR_VEC in GS-mode, we consider the guest
> + * as always using the AltiVec.
> + */
> + kvmppc_load_guest_altivec(vcpu);
> +#endif
> +
> /* Switch to guest debug context */
> debug = vcpu->arch.shadow_dbg_reg;
> switch_booke_debug_regs(&debug);
> @@ -715,6 +765,10 @@ int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
> kvmppc_save_guest_fp(vcpu);
> #endif
>
> +#ifdef CONFIG_ALTIVEC
> + kvmppc_save_guest_altivec(vcpu);
> +#endif
> +
> out:
> vcpu->mode = OUTSIDE_GUEST_MODE;
> return ret;
> @@ -999,6 +1053,7 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
> r = RESUME_GUEST;
> break;
>
> +#ifdef CONFIG_KVM_E500V2
Why? We're already guarded by CONFIG_SPE
> #ifdef CONFIG_SPE
> case BOOKE_INTERRUPT_SPE_UNAVAIL: {
> if (vcpu->arch.shared->msr & MSR_SPE)
> @@ -1040,7 +1095,24 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
> run->hw.hardware_exit_reason = exit_nr;
> r = RESUME_HOST;
> break;
> +#endif /* !CONFIG_SPE */
> +#else
> +/*
> + * On cores with Vector category, KVM is loaded only if CONFIG_ALTIVEC,
> + * see kvmppc_core_check_processor_compat().
> + */
> +#ifdef CONFIG_ALTIVEC
... and CONFIG_ALTIVEC
> + case BOOKE_INTERRUPT_ALTIVEC_UNAVAIL:
> + kvmppc_booke_queue_irqprio(vcpu, BOOKE_IRQPRIO_ALTIVEC_UNAVAIL);
> + r = RESUME_GUEST;
> + break;
> +
> + case BOOKE_INTERRUPT_ALTIVEC_ASSIST:
> + kvmppc_booke_queue_irqprio(vcpu, BOOKE_IRQPRIO_ALTIVEC_ASSIST);
> + r = RESUME_GUEST;
> + break;
> #endif
> +#endif /* !CONFIG_KVM_E500V2 */
>
> case BOOKE_INTERRUPT_DATA_STORAGE:
> kvmppc_core_queue_data_storage(vcpu, vcpu->arch.fault_dear,
> @@ -1217,6 +1289,7 @@ out:
> /* interrupts now hard-disabled */
> kvmppc_fix_ee_before_entry();
> kvmppc_load_guest_fp(vcpu);
> + kvmppc_load_guest_altivec(vcpu);
> }
> }
>
> diff --git a/arch/powerpc/kvm/booke.h b/arch/powerpc/kvm/booke.h
> index e73d513..ce5b543 100644
> --- a/arch/powerpc/kvm/booke.h
> +++ b/arch/powerpc/kvm/booke.h
> @@ -32,9 +32,14 @@
> #define BOOKE_IRQPRIO_ALIGNMENT 2
> #define BOOKE_IRQPRIO_PROGRAM 3
> #define BOOKE_IRQPRIO_FP_UNAVAIL 4
> +#ifdef CONFIG_KVM_E500V2
Same comments as above
> #define BOOKE_IRQPRIO_SPE_UNAVAIL 5
> #define BOOKE_IRQPRIO_SPE_FP_DATA 6
> #define BOOKE_IRQPRIO_SPE_FP_ROUND 7
> +#else
> +#define BOOKE_IRQPRIO_ALTIVEC_UNAVAIL 5
> +#define BOOKE_IRQPRIO_ALTIVEC_ASSIST 6
> +#endif
> #define BOOKE_IRQPRIO_SYSCALL 8
> #define BOOKE_IRQPRIO_AP_UNAVAIL 9
> #define BOOKE_IRQPRIO_DTLB_MISS 10
> diff --git a/arch/powerpc/kvm/bookehv_interrupts.S b/arch/powerpc/kvm/bookehv_interrupts.S
> index e9fa56a..1d7c4d6 100644
> --- a/arch/powerpc/kvm/bookehv_interrupts.S
> +++ b/arch/powerpc/kvm/bookehv_interrupts.S
> @@ -256,11 +256,9 @@ kvm_handler BOOKE_INTERRUPT_DTLB_MISS, EX_PARAMS_TLB, \
> SPRN_SRR0, SPRN_SRR1, (NEED_EMU | NEED_DEAR | NEED_ESR)
> kvm_handler BOOKE_INTERRUPT_ITLB_MISS, EX_PARAMS_TLB, \
> SPRN_SRR0, SPRN_SRR1, 0
> -kvm_handler BOOKE_INTERRUPT_SPE_UNAVAIL, EX_PARAMS(GEN), \
> +kvm_handler BOOKE_INTERRUPT_ALTIVEC_UNAVAIL, EX_PARAMS(GEN), \
> SPRN_SRR0, SPRN_SRR1, 0
> -kvm_handler BOOKE_INTERRUPT_SPE_FP_DATA, EX_PARAMS(GEN), \
> - SPRN_SRR0, SPRN_SRR1, 0
> -kvm_handler BOOKE_INTERRUPT_SPE_FP_ROUND, EX_PARAMS(GEN), \
> +kvm_handler BOOKE_INTERRUPT_ALTIVEC_ASSIST, EX_PARAMS(GEN), \
> SPRN_SRR0, SPRN_SRR1, 0
> kvm_handler BOOKE_INTERRUPT_PERFORMANCE_MONITOR, EX_PARAMS(GEN), \
> SPRN_SRR0, SPRN_SRR1, 0
> @@ -361,6 +359,10 @@ kvm_lvl_handler BOOKE_INTERRUPT_WATCHDOG, \
> kvm_handler BOOKE_INTERRUPT_DTLB_MISS, \
> SPRN_SRR0, SPRN_SRR1, (NEED_EMU | NEED_DEAR | NEED_ESR)
> kvm_handler BOOKE_INTERRUPT_ITLB_MISS, SPRN_SRR0, SPRN_SRR1, 0
> +/*
> + * TODO: SPE handlers should be available only for e500v2 cores.
> + * HV does not target e500v2 so remove them after kernel cleanup.
> + */
Let's do the cleanup first, then apply these patches.
> kvm_handler BOOKE_INTERRUPT_SPE_UNAVAIL, SPRN_SRR0, SPRN_SRR1, 0
> kvm_handler BOOKE_INTERRUPT_SPE_FP_DATA, SPRN_SRR0, SPRN_SRR1, 0
> kvm_handler BOOKE_INTERRUPT_SPE_FP_ROUND, SPRN_SRR0, SPRN_SRR1, 0
> diff --git a/arch/powerpc/kvm/e500_emulate.c b/arch/powerpc/kvm/e500_emulate.c
> index c99c40e..e6e0429 100644
> --- a/arch/powerpc/kvm/e500_emulate.c
> +++ b/arch/powerpc/kvm/e500_emulate.c
> @@ -259,6 +259,7 @@ int kvmppc_core_emulate_mtspr_e500(struct kvm_vcpu *vcpu, int sprn, ulong spr_va
> break;
>
> /* extra exceptions */
> +#ifdef CONFIG_KVM_E500V2
Same comments as above
> case SPRN_IVOR32:
> vcpu->arch.ivor[BOOKE_IRQPRIO_SPE_UNAVAIL] = spr_val;
> break;
> @@ -268,6 +269,14 @@ int kvmppc_core_emulate_mtspr_e500(struct kvm_vcpu *vcpu, int sprn, ulong spr_va
> case SPRN_IVOR34:
> vcpu->arch.ivor[BOOKE_IRQPRIO_SPE_FP_ROUND] = spr_val;
> break;
> +#else
> + case SPRN_IVOR32:
> + vcpu->arch.ivor[BOOKE_IRQPRIO_ALTIVEC_UNAVAIL] = spr_val;
> + break;
> + case SPRN_IVOR33:
> + vcpu->arch.ivor[BOOKE_IRQPRIO_ALTIVEC_ASSIST] = spr_val;
> + break;
> +#endif
> case SPRN_IVOR35:
> vcpu->arch.ivor[BOOKE_IRQPRIO_PERFORMANCE_MONITOR] = spr_val;
> break;
> @@ -381,6 +390,7 @@ int kvmppc_core_emulate_mfspr_e500(struct kvm_vcpu *vcpu, int sprn, ulong *spr_v
> break;
>
> /* extra exceptions */
> +#ifdef CONFIG_KVM_E500V2
Here too.
Alex
> case SPRN_IVOR32:
> *spr_val = vcpu->arch.ivor[BOOKE_IRQPRIO_SPE_UNAVAIL];
> break;
> @@ -390,6 +400,14 @@ int kvmppc_core_emulate_mfspr_e500(struct kvm_vcpu *vcpu, int sprn, ulong *spr_v
> case SPRN_IVOR34:
> *spr_val = vcpu->arch.ivor[BOOKE_IRQPRIO_SPE_FP_ROUND];
> break;
> +#else
> + case SPRN_IVOR32:
> + *spr_val = vcpu->arch.ivor[BOOKE_IRQPRIO_ALTIVEC_UNAVAIL];
> + break;
> + case SPRN_IVOR33:
> + *spr_val = vcpu->arch.ivor[BOOKE_IRQPRIO_ALTIVEC_ASSIST];
> + break;
> +#endif
> case SPRN_IVOR35:
> *spr_val = vcpu->arch.ivor[BOOKE_IRQPRIO_PERFORMANCE_MONITOR];
> break;
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH v3 3/5] KVM: PPC: Move ONE_REG AltiVec support to powerpc
2014-08-05 10:39 ` [PATCH v3 3/5] KVM: PPC: Move ONE_REG AltiVec support to powerpc Mihai Caraman
@ 2014-08-12 11:47 ` Alexander Graf
0 siblings, 0 replies; 9+ messages in thread
From: Alexander Graf @ 2014-08-12 11:47 UTC (permalink / raw)
To: Mihai Caraman, kvm-ppc; +Cc: kvm
On 05.08.14 12:39, Mihai Caraman wrote:
> Make ONE_REG AltiVec support common across server and embedded implementations
> moving kvm_vcpu_ioctl_get_one_reg() and kvm_vcpu_ioctl_set_one_reg() functions
> to powerpc layer.
>
> Signed-off-by: Mihai Caraman <mihai.caraman@freescale.com>
Please split this into 2 separate patches, one that makes ONE_REG
generic and one that moves Altivec from book3s into the generic version.
Alex
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH v3 4/5] KVM: PPC: Booke: Add ONE_REG IVORs support
2014-08-05 10:39 ` [PATCH v3 4/5] KVM: PPC: Booke: Add ONE_REG IVORs support Mihai Caraman
@ 2014-08-12 11:48 ` Alexander Graf
0 siblings, 0 replies; 9+ messages in thread
From: Alexander Graf @ 2014-08-12 11:48 UTC (permalink / raw)
To: Mihai Caraman, kvm-ppc; +Cc: kvm
On 05.08.14 12:39, Mihai Caraman wrote:
> Add ONE_REG IVORs support, with IVORs 0-15 and 35 booke common.
>
> Signed-off-by: Mihai Caraman <mihai.caraman@freescale.com>
> ---
> v3:
> - new patch
>
> arch/powerpc/include/uapi/asm/kvm.h | 24 +++++++
> arch/powerpc/kvm/booke.c | 132 ++++++++++++++++++++++++++++++++++++
> arch/powerpc/kvm/e500.c | 42 +++++++++++-
> arch/powerpc/kvm/e500mc.c | 32 +++++++++
> 4 files changed, 228 insertions(+), 2 deletions(-)
>
> diff --git a/arch/powerpc/include/uapi/asm/kvm.h b/arch/powerpc/include/uapi/asm/kvm.h
> index 7a27ff0..174fed0 100644
> --- a/arch/powerpc/include/uapi/asm/kvm.h
> +++ b/arch/powerpc/include/uapi/asm/kvm.h
> @@ -563,6 +563,30 @@ struct kvm_get_htab_header {
> #define KVM_REG_PPC_WORT (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xb9)
> #define KVM_REG_PPC_SPRG9 (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xba)
>
> +/* Booke IVOR registers */
> +#define KVM_REG_PPC_IVOR0 (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0xc0)
> +#define KVM_REG_PPC_IVOR1 (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0xc1)
> +#define KVM_REG_PPC_IVOR2 (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0xc2)
> +#define KVM_REG_PPC_IVOR3 (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0xc3)
> +#define KVM_REG_PPC_IVOR4 (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0xc4)
> +#define KVM_REG_PPC_IVOR5 (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0xc5)
> +#define KVM_REG_PPC_IVOR6 (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0xc6)
> +#define KVM_REG_PPC_IVOR7 (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0xc7)
> +#define KVM_REG_PPC_IVOR8 (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0xc8)
> +#define KVM_REG_PPC_IVOR9 (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0xc9)
> +#define KVM_REG_PPC_IVOR10 (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0xca)
> +#define KVM_REG_PPC_IVOR11 (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0xcb)
> +#define KVM_REG_PPC_IVOR12 (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0xcc)
> +#define KVM_REG_PPC_IVOR13 (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0xcd)
> +#define KVM_REG_PPC_IVOR14 (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0xce)
> +#define KVM_REG_PPC_IVOR15 (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0xcf)
> +#define KVM_REG_PPC_IVOR32 (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0xd0)
> +#define KVM_REG_PPC_IVOR33 (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0xd1)
> +#define KVM_REG_PPC_IVOR34 (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0xd2)
> +#define KVM_REG_PPC_IVOR35 (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0xd3)
> +#define KVM_REG_PPC_IVOR36 (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0xd4)
> +#define KVM_REG_PPC_IVOR37 (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0xd5)
These should also get mentioned in Documentation/virtual/kvm/api.txt.
Otherwise looks nice :).
Alex
^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2014-08-12 11:48 UTC | newest]
Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-08-05 10:39 [PATCH v3 0/5] KVM: PPC: Book3e: AltiVec support Mihai Caraman
2014-08-05 10:39 ` [PATCH v3 1/5] KVM: PPC: Book3e: Increase FPU laziness Mihai Caraman
2014-08-05 10:39 ` [PATCH v3 2/5] KVM: PPC: Book3e: Add AltiVec support Mihai Caraman
2014-08-12 11:45 ` Alexander Graf
2014-08-05 10:39 ` [PATCH v3 3/5] KVM: PPC: Move ONE_REG AltiVec support to powerpc Mihai Caraman
2014-08-12 11:47 ` Alexander Graf
2014-08-05 10:39 ` [PATCH v3 4/5] KVM: PPC: Booke: Add ONE_REG IVORs support Mihai Caraman
2014-08-12 11:48 ` Alexander Graf
2014-08-05 10:39 ` [PATCH v3 5/5] KVM: PPC: Book3E: Enable e6500 core Mihai Caraman
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox