* [RFC PATCH 03/17] KVM: PPC64: booke: Add EPCR support in sregs
From: Mihai Caraman @ 2012-06-25 12:26 UTC (permalink / raw)
To: kvm-ppc, kvm, linuxppc-dev, qemu-ppc; +Cc: Mihai Caraman
In-Reply-To: <1340627195-11544-1-git-send-email-mihai.caraman@freescale.com>
Add KVM_SREGS_E_64 feature and EPCR spr support in get/set sregs
for 64-bit hosts.
Signed-off-by: Mihai Caraman <mihai.caraman@freescale.com>
---
arch/powerpc/kvm/booke.c | 14 ++++++++++++++
1 files changed, 14 insertions(+), 0 deletions(-)
diff --git a/arch/powerpc/kvm/booke.c b/arch/powerpc/kvm/booke.c
index f9fa260..d15c4b5 100644
--- a/arch/powerpc/kvm/booke.c
+++ b/arch/powerpc/kvm/booke.c
@@ -1052,6 +1052,9 @@ static void get_sregs_base(struct kvm_vcpu *vcpu,
u64 tb = get_tb();
sregs->u.e.features |= KVM_SREGS_E_BASE;
+#ifdef CONFIG_64BIT
+ sregs->u.e.features |= KVM_SREGS_E_64;
+#endif
sregs->u.e.csrr0 = vcpu->arch.csrr0;
sregs->u.e.csrr1 = vcpu->arch.csrr1;
@@ -1063,6 +1066,9 @@ static void get_sregs_base(struct kvm_vcpu *vcpu,
sregs->u.e.dec = kvmppc_get_dec(vcpu, tb);
sregs->u.e.tb = tb;
sregs->u.e.vrsave = vcpu->arch.vrsave;
+#ifdef CONFIG_64BIT
+ sregs->u.e.epcr = vcpu->arch.epcr;
+#endif
}
static int set_sregs_base(struct kvm_vcpu *vcpu,
@@ -1071,6 +1077,11 @@ static int set_sregs_base(struct kvm_vcpu *vcpu,
if (!(sregs->u.e.features & KVM_SREGS_E_BASE))
return 0;
+#ifdef CONFIG_64BIT
+ if (!(sregs->u.e.features & KVM_SREGS_E_64))
+ return 0;
+#endif
+
vcpu->arch.csrr0 = sregs->u.e.csrr0;
vcpu->arch.csrr1 = sregs->u.e.csrr1;
vcpu->arch.mcsr = sregs->u.e.mcsr;
@@ -1078,6 +1089,9 @@ static int set_sregs_base(struct kvm_vcpu *vcpu,
set_guest_dear(vcpu, sregs->u.e.dear);
vcpu->arch.vrsave = sregs->u.e.vrsave;
kvmppc_set_tcr(vcpu, sregs->u.e.tcr);
+#ifdef CONFIG_64BIT
+ kvmppc_set_epcr(vcpu, sregs->u.e.epcr);
+#endif
if (sregs->u.e.update_special & KVM_SREGS_E_UPDATE_DEC) {
vcpu->arch.dec = sregs->u.e.dec;
--
1.7.4.1
^ permalink raw reply related
* [RFC PATCH 04/17] KVM: PPC64: booke: Add guest computation mode for irq delivery
From: Mihai Caraman @ 2012-06-25 12:26 UTC (permalink / raw)
To: kvm-ppc, kvm, linuxppc-dev, qemu-ppc; +Cc: Mihai Caraman
In-Reply-To: <1340627195-11544-1-git-send-email-mihai.caraman@freescale.com>
When delivering guest IRQs, update MSR computaion mode according to guest
interrupt computation mode found in EPCR.
Signed-off-by: Mihai Caraman <mihai.caraman@freescale.com>
---
arch/powerpc/kvm/booke.c | 8 +++++++-
1 files changed, 7 insertions(+), 1 deletions(-)
diff --git a/arch/powerpc/kvm/booke.c b/arch/powerpc/kvm/booke.c
index d15c4b5..93b48e0 100644
--- a/arch/powerpc/kvm/booke.c
+++ b/arch/powerpc/kvm/booke.c
@@ -287,6 +287,7 @@ static int kvmppc_booke_irqprio_deliver(struct kvm_vcpu *vcpu,
bool crit;
bool keep_irq = false;
enum int_class int_class;
+ ulong msr_cm = 0;
/* Truncate crit indicators in 32 bit mode */
if (!(vcpu->arch.shared->msr & MSR_SF)) {
@@ -299,6 +300,10 @@ static int kvmppc_booke_irqprio_deliver(struct kvm_vcpu *vcpu,
/* ... and we're in supervisor mode */
crit = crit && !(vcpu->arch.shared->msr & MSR_PR);
+#ifdef CONFIG_64BIT
+ msr_cm = vcpu->arch.epcr & SPRN_EPCR_ICM ? MSR_CM : 0;
+#endif
+
if (priority == BOOKE_IRQPRIO_EXTERNAL_LEVEL) {
priority = BOOKE_IRQPRIO_EXTERNAL;
keep_irq = true;
@@ -381,7 +386,8 @@ static int kvmppc_booke_irqprio_deliver(struct kvm_vcpu *vcpu,
set_guest_esr(vcpu, vcpu->arch.queued_esr);
if (update_dear == true)
set_guest_dear(vcpu, vcpu->arch.queued_dear);
- kvmppc_set_msr(vcpu, vcpu->arch.shared->msr & msr_mask);
+ kvmppc_set_msr(vcpu, (vcpu->arch.shared->msr & msr_mask)
+ | msr_cm);
if (!keep_irq)
clear_bit(priority, &vcpu->arch.pending_exceptions);
--
1.7.4.1
^ permalink raw reply related
* [RFC PATCH 05/17] KVM: PPC: booke: Extend MAS2 EPN mask for 64-bit
From: Mihai Caraman @ 2012-06-25 12:26 UTC (permalink / raw)
To: kvm-ppc, kvm, linuxppc-dev, qemu-ppc; +Cc: Mihai Caraman
In-Reply-To: <1340627195-11544-1-git-send-email-mihai.caraman@freescale.com>
Extend MAS2 EPN mask for 64-bit hosts, to retain most significant bits.
Change get tlb eaddr to use this mask.
Signed-off-by: Mihai Caraman <mihai.caraman@freescale.com>
---
arch/powerpc/include/asm/mmu-book3e.h | 2 +-
arch/powerpc/kvm/e500.h | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/arch/powerpc/include/asm/mmu-book3e.h b/arch/powerpc/include/asm/mmu-book3e.h
index eeabcdb..99d43e0 100644
--- a/arch/powerpc/include/asm/mmu-book3e.h
+++ b/arch/powerpc/include/asm/mmu-book3e.h
@@ -59,7 +59,7 @@
#define MAS1_TSIZE_SHIFT 7
#define MAS1_TSIZE(x) (((x) << MAS1_TSIZE_SHIFT) & MAS1_TSIZE_MASK)
-#define MAS2_EPN 0xFFFFF000
+#define MAS2_EPN (~0xFFFUL)
#define MAS2_X0 0x00000040
#define MAS2_X1 0x00000020
#define MAS2_W 0x00000010
diff --git a/arch/powerpc/kvm/e500.h b/arch/powerpc/kvm/e500.h
index aa8b814..3e31098 100644
--- a/arch/powerpc/kvm/e500.h
+++ b/arch/powerpc/kvm/e500.h
@@ -155,7 +155,7 @@ get_tlb_size(const struct kvm_book3e_206_tlb_entry *tlbe)
static inline gva_t get_tlb_eaddr(const struct kvm_book3e_206_tlb_entry *tlbe)
{
- return tlbe->mas2 & 0xfffff000;
+ return tlbe->mas2 & MAS2_EPN;
}
static inline u64 get_tlb_bytes(const struct kvm_book3e_206_tlb_entry *tlbe)
--
1.7.4.1
^ permalink raw reply related
* [RFC PATCH 13/17] PowerPC: booke64: Use SPRG0/3 scratch for bolted TLB miss & crit int
From: Mihai Caraman @ 2012-06-25 12:26 UTC (permalink / raw)
To: kvm-ppc, kvm, linuxppc-dev, qemu-ppc; +Cc: Mihai Caraman
In-Reply-To: <1340627195-11544-1-git-send-email-mihai.caraman@freescale.com>
Embedded.Hypervisor category defines GSPRG0..3 physical registers for guests.
Avoid SPRG4-7 usage as scratch in host exception handlers, otherwise guest
SPRG4-7 registers will be clobbered.
For bolted TLB miss exception handlers, which is the version currently
supported by KVM, use SPRN_SPRG_GEN_SCRATCH (aka SPRG0) instead of
SPRN_SPRG_TLB_SCRATCH (aka SPRG6) and replace TLB with GEN PACA slots to
keep consitency.
For critical exception handler use SPRG3 instead of SPRG7.
Signed-off-by: Mihai Caraman <mihai.caraman@freescale.com>
---
arch/powerpc/include/asm/exception-64e.h | 14 +++++++-------
arch/powerpc/include/asm/reg.h | 6 +++---
arch/powerpc/mm/tlb_low_64e.S | 28 ++++++++++++++--------------
3 files changed, 24 insertions(+), 24 deletions(-)
diff --git a/arch/powerpc/include/asm/exception-64e.h b/arch/powerpc/include/asm/exception-64e.h
index ac13add..c90a9a4 100644
--- a/arch/powerpc/include/asm/exception-64e.h
+++ b/arch/powerpc/include/asm/exception-64e.h
@@ -38,8 +38,11 @@
*/
-/* We are out of SPRGs so we save some things in the PACA. The normal
- * exception frame is smaller than the CRIT or MC one though
+/* We are out of SPRGs so we save some things in the 8 slots available in PACA.
+ * The normal exception frame is smaller than the CRIT or MC one though
+ *
+ * Bolted TLB miss exception variant also uses these slots which in combination
+ * with pgd and kernel_pgd fits in one 64-byte cache line.
*/
#define EX_R1 (0 * 8)
#define EX_CR (1 * 8)
@@ -47,13 +50,10 @@
#define EX_R11 (3 * 8)
#define EX_R14 (4 * 8)
#define EX_R15 (5 * 8)
+#define EX_R16 (6 * 8)
/*
- * The TLB miss exception uses different slots.
- *
- * The bolted variant uses only the first six fields,
- * which in combination with pgd and kernel_pgd fits in
- * one 64-byte cache line.
+ * PACA slots offset for standard TLB miss exception.
*/
#define EX_TLB_R10 ( 0 * 8)
diff --git a/arch/powerpc/include/asm/reg.h b/arch/powerpc/include/asm/reg.h
index f0cb7f4..51c14a7 100644
--- a/arch/powerpc/include/asm/reg.h
+++ b/arch/powerpc/include/asm/reg.h
@@ -760,10 +760,10 @@
* 64-bit embedded
* - SPRG0 generic exception scratch
* - SPRG2 TLB exception stack
- * - SPRG3 unused (user visible)
+ * - SPRG3 critical exception scratch (user visible)
* - SPRG4 unused (user visible)
* - SPRG6 TLB miss scratch (user visible, sorry !)
- * - SPRG7 critical exception scratch
+ * - SPRG7 unused (user visible)
* - SPRG8 machine check exception scratch
* - SPRG9 debug exception scratch
*
@@ -857,7 +857,7 @@
#ifdef CONFIG_PPC_BOOK3E_64
#define SPRN_SPRG_MC_SCRATCH SPRN_SPRG8
-#define SPRN_SPRG_CRIT_SCRATCH SPRN_SPRG7
+#define SPRN_SPRG_CRIT_SCRATCH SPRN_SPRG3
#define SPRN_SPRG_DBG_SCRATCH SPRN_SPRG9
#define SPRN_SPRG_TLB_EXFRAME SPRN_SPRG2
#define SPRN_SPRG_TLB_SCRATCH SPRN_SPRG6
diff --git a/arch/powerpc/mm/tlb_low_64e.S b/arch/powerpc/mm/tlb_low_64e.S
index 88feaaa..4192ade 100644
--- a/arch/powerpc/mm/tlb_low_64e.S
+++ b/arch/powerpc/mm/tlb_low_64e.S
@@ -40,36 +40,36 @@
**********************************************************************/
.macro tlb_prolog_bolted intnum addr
- mtspr SPRN_SPRG_TLB_SCRATCH,r13
+ mtspr SPRN_SPRG_GEN_SCRATCH,r13
mfspr r13,SPRN_SPRG_PACA
- std r10,PACA_EXTLB+EX_TLB_R10(r13)
+ std r10,PACA_EXGEN+EX_R10(r13)
mfcr r10
- std r11,PACA_EXTLB+EX_TLB_R11(r13)
+ std r11,PACA_EXGEN+EX_R11(r13)
#ifdef CONFIG_KVM_BOOKE_HV
BEGIN_FTR_SECTION
mfspr r11, SPRN_SRR1
END_FTR_SECTION_IFSET(CPU_FTR_EMB_HV)
#endif
DO_KVM \intnum, SPRN_SRR1
- std r16,PACA_EXTLB+EX_TLB_R16(r13)
+ std r16,PACA_EXGEN+EX_R16(r13)
mfspr r16,\addr /* get faulting address */
- std r14,PACA_EXTLB+EX_TLB_R14(r13)
+ std r14,PACA_EXGEN+EX_R14(r13)
ld r14,PACAPGD(r13)
- std r15,PACA_EXTLB+EX_TLB_R15(r13)
- std r10,PACA_EXTLB+EX_TLB_CR(r13)
+ std r15,PACA_EXGEN+EX_R15(r13)
+ std r10,PACA_EXGEN+EX_CR(r13)
TLB_MISS_PROLOG_STATS_BOLTED
.endm
.macro tlb_epilog_bolted
- ld r14,PACA_EXTLB+EX_TLB_CR(r13)
- ld r10,PACA_EXTLB+EX_TLB_R10(r13)
- ld r11,PACA_EXTLB+EX_TLB_R11(r13)
+ ld r14,PACA_EXGEN+EX_CR(r13)
+ ld r10,PACA_EXGEN+EX_R10(r13)
+ ld r11,PACA_EXGEN+EX_R11(r13)
mtcr r14
- ld r14,PACA_EXTLB+EX_TLB_R14(r13)
- ld r15,PACA_EXTLB+EX_TLB_R15(r13)
+ ld r14,PACA_EXGEN+EX_R14(r13)
+ ld r15,PACA_EXGEN+EX_R15(r13)
TLB_MISS_RESTORE_STATS_BOLTED
- ld r16,PACA_EXTLB+EX_TLB_R16(r13)
- mfspr r13,SPRN_SPRG_TLB_SCRATCH
+ ld r16,PACA_EXGEN+EX_R16(r13)
+ mfspr r13,SPRN_SPRG_GEN_SCRATCH
.endm
/* Data TLB miss */
--
1.7.4.1
^ permalink raw reply related
* [RFC PATCH 02/17] KVM: PPC64: booke: Add EPCR support in mtspr/mfspr emulation
From: Mihai Caraman @ 2012-06-25 12:26 UTC (permalink / raw)
To: kvm-ppc, kvm, linuxppc-dev, qemu-ppc; +Cc: Mihai Caraman
In-Reply-To: <1340627195-11544-1-git-send-email-mihai.caraman@freescale.com>
Add EPCR support in booke mtspr/mfspr emulation. EPCR register is defined
only for 64-bit and HV categories, so it shoud be available only on 64-bit
virtual processors. Undefine the support for 32-bit builds.
Define a reusable setter function for vcpu's EPCR.
Signed-off-by: Mihai Caraman <mihai.caraman@freescale.com>
---
arch/powerpc/kvm/booke.c | 12 +++++++++++-
arch/powerpc/kvm/booke.h | 6 ++++++
arch/powerpc/kvm/booke_emulate.c | 13 ++++++++++++-
3 files changed, 29 insertions(+), 2 deletions(-)
diff --git a/arch/powerpc/kvm/booke.c b/arch/powerpc/kvm/booke.c
index 72f13f4..f9fa260 100644
--- a/arch/powerpc/kvm/booke.c
+++ b/arch/powerpc/kvm/booke.c
@@ -13,7 +13,7 @@
* Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Copyright IBM Corp. 2007
- * Copyright 2010-2011 Freescale Semiconductor, Inc.
+ * Copyright 2010-2012 Freescale Semiconductor, Inc.
*
* Authors: Hollis Blanchard <hollisb@us.ibm.com>
* Christian Ehrhardt <ehrhardt@linux.vnet.ibm.com>
@@ -1243,6 +1243,16 @@ void kvmppc_core_commit_memory_region(struct kvm *kvm,
{
}
+#ifdef CONFIG_64BIT
+void kvmppc_set_epcr(struct kvm_vcpu *vcpu, u32 new_epcr)
+{
+ vcpu->arch.epcr = new_epcr;
+ vcpu->arch.shadow_epcr &= ~SPRN_EPCR_GICM;
+ if (vcpu->arch.epcr & SPRN_EPCR_ICM)
+ vcpu->arch.shadow_epcr |= SPRN_EPCR_GICM;
+}
+#endif
+
void kvmppc_set_tcr(struct kvm_vcpu *vcpu, u32 new_tcr)
{
vcpu->arch.tcr = new_tcr;
diff --git a/arch/powerpc/kvm/booke.h b/arch/powerpc/kvm/booke.h
index ba61974..e05b48f 100644
--- a/arch/powerpc/kvm/booke.h
+++ b/arch/powerpc/kvm/booke.h
@@ -69,6 +69,12 @@ extern unsigned long kvmppc_booke_handlers;
void kvmppc_set_msr(struct kvm_vcpu *vcpu, u32 new_msr);
void kvmppc_mmu_msr_notify(struct kvm_vcpu *vcpu, u32 old_msr);
+#ifdef CONFIG_64BIT
+void kvmppc_set_epcr(struct kvm_vcpu *vcpu, u32 new_epcr);
+#else
+static inline void kvmppc_set_epcr(struct kvm_vcpu *vcpu, u32 new_epcr) {}
+#endif
+
void kvmppc_set_tcr(struct kvm_vcpu *vcpu, u32 new_tcr);
void kvmppc_set_tsr_bits(struct kvm_vcpu *vcpu, u32 tsr_bits);
void kvmppc_clr_tsr_bits(struct kvm_vcpu *vcpu, u32 tsr_bits);
diff --git a/arch/powerpc/kvm/booke_emulate.c b/arch/powerpc/kvm/booke_emulate.c
index 6c76397..9cf2b95f 100644
--- a/arch/powerpc/kvm/booke_emulate.c
+++ b/arch/powerpc/kvm/booke_emulate.c
@@ -13,7 +13,7 @@
* Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Copyright IBM Corp. 2008
- * Copyright 2011 Freescale Semiconductor, Inc.
+ * Copyright 2011-2012 Freescale Semiconductor, Inc.
*
* Authors: Hollis Blanchard <hollisb@us.ibm.com>
*/
@@ -207,6 +207,12 @@ int kvmppc_booke_emulate_mtspr(struct kvm_vcpu *vcpu, int sprn, ulong spr_val)
case SPRN_IVOR15:
vcpu->arch.ivor[BOOKE_IRQPRIO_DEBUG] = spr_val;
break;
+#ifdef CONFIG_64BIT
+ case SPRN_EPCR:
+ kvmppc_set_epcr(vcpu, spr_val);
+ mtspr(SPRN_EPCR, vcpu->arch.shadow_epcr);
+ break;
+#endif
default:
emulated = EMULATE_FAIL;
@@ -293,6 +299,11 @@ int kvmppc_booke_emulate_mfspr(struct kvm_vcpu *vcpu, int sprn, ulong *spr_val)
case SPRN_IVOR15:
*spr_val = vcpu->arch.ivor[BOOKE_IRQPRIO_DEBUG];
break;
+#ifdef CONFIG_64BIT
+ case SPRN_EPCR:
+ *spr_val = vcpu->arch.epcr;
+ break;
+#endif
default:
emulated = EMULATE_FAIL;
--
1.7.4.1
^ permalink raw reply related
* [RFC PATCH 17/17] KVM: PPC: booke: Fix get_tb() compile error on 64-bit
From: Mihai Caraman @ 2012-06-25 12:26 UTC (permalink / raw)
To: kvm-ppc, kvm, linuxppc-dev, qemu-ppc; +Cc: Mihai Caraman
In-Reply-To: <1340627195-11544-1-git-send-email-mihai.caraman@freescale.com>
Include header file for get_tb() declaration.
Signed-off-by: Mihai Caraman <mihai.caraman@freescale.com>
---
arch/powerpc/kvm/booke.c | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
diff --git a/arch/powerpc/kvm/booke.c b/arch/powerpc/kvm/booke.c
index db05692..a427031 100644
--- a/arch/powerpc/kvm/booke.c
+++ b/arch/powerpc/kvm/booke.c
@@ -36,6 +36,7 @@
#include <asm/dbell.h>
#include <asm/hw_irq.h>
#include <asm/irq.h>
+#include <asm/time.h>
#include "timing.h"
#include "booke.h"
--
1.7.4.1
^ permalink raw reply related
* [RFC PATCH 06/17] KVM: PPC: e500: Add emulation helper for getting instruction ea
From: Mihai Caraman @ 2012-06-25 12:26 UTC (permalink / raw)
To: kvm-ppc, kvm, linuxppc-dev, qemu-ppc; +Cc: Mihai Caraman
In-Reply-To: <1340627195-11544-1-git-send-email-mihai.caraman@freescale.com>
Add emulation helper for getting instruction ea and refactor tlb instruction
emulation to use it.
Signed-off-by: Mihai Caraman <mihai.caraman@freescale.com>
---
arch/powerpc/kvm/e500.h | 6 +++---
arch/powerpc/kvm/e500_emulate.c | 21 ++++++++++++++++++---
arch/powerpc/kvm/e500_tlb.c | 23 ++++++-----------------
3 files changed, 27 insertions(+), 23 deletions(-)
diff --git a/arch/powerpc/kvm/e500.h b/arch/powerpc/kvm/e500.h
index 3e31098..70bfed4 100644
--- a/arch/powerpc/kvm/e500.h
+++ b/arch/powerpc/kvm/e500.h
@@ -130,9 +130,9 @@ int kvmppc_e500_emul_mt_mmucsr0(struct kvmppc_vcpu_e500 *vcpu_e500,
ulong value);
int kvmppc_e500_emul_tlbwe(struct kvm_vcpu *vcpu);
int kvmppc_e500_emul_tlbre(struct kvm_vcpu *vcpu);
-int kvmppc_e500_emul_tlbivax(struct kvm_vcpu *vcpu, int ra, int rb);
-int kvmppc_e500_emul_tlbilx(struct kvm_vcpu *vcpu, int rt, int ra, int rb);
-int kvmppc_e500_emul_tlbsx(struct kvm_vcpu *vcpu, int rb);
+int kvmppc_e500_emul_tlbivax(struct kvm_vcpu *vcpu, gva_t ea);
+int kvmppc_e500_emul_tlbilx(struct kvm_vcpu *vcpu, int rt, gva_t ea);
+int kvmppc_e500_emul_tlbsx(struct kvm_vcpu *vcpu, gva_t ea);
int kvmppc_e500_tlb_init(struct kvmppc_vcpu_e500 *vcpu_e500);
void kvmppc_e500_tlb_uninit(struct kvmppc_vcpu_e500 *vcpu_e500);
diff --git a/arch/powerpc/kvm/e500_emulate.c b/arch/powerpc/kvm/e500_emulate.c
index 8b99e07..81288f7 100644
--- a/arch/powerpc/kvm/e500_emulate.c
+++ b/arch/powerpc/kvm/e500_emulate.c
@@ -82,6 +82,17 @@ static int kvmppc_e500_emul_msgsnd(struct kvm_vcpu *vcpu, int rb)
}
#endif
+static inline ulong kvmppc_get_ea_indexed(struct kvm_vcpu *vcpu, int ra, int rb)
+{
+ ulong ea;
+
+ ea = kvmppc_get_gpr(vcpu, rb);
+ if (ra)
+ ea += kvmppc_get_gpr(vcpu, ra);
+
+ return ea;
+}
+
int kvmppc_core_emulate_op(struct kvm_run *run, struct kvm_vcpu *vcpu,
unsigned int inst, int *advance)
{
@@ -89,6 +100,7 @@ int kvmppc_core_emulate_op(struct kvm_run *run, struct kvm_vcpu *vcpu,
int ra = get_ra(inst);
int rb = get_rb(inst);
int rt = get_rt(inst);
+ gva_t ea;
switch (get_op(inst)) {
case 31:
@@ -113,15 +125,18 @@ int kvmppc_core_emulate_op(struct kvm_run *run, struct kvm_vcpu *vcpu,
break;
case XOP_TLBSX:
- emulated = kvmppc_e500_emul_tlbsx(vcpu,rb);
+ ea = kvmppc_get_ea_indexed(vcpu, ra, rb);
+ emulated = kvmppc_e500_emul_tlbsx(vcpu, ea);
break;
case XOP_TLBILX:
- emulated = kvmppc_e500_emul_tlbilx(vcpu, rt, ra, rb);
+ ea = kvmppc_get_ea_indexed(vcpu, ra, rb);
+ emulated = kvmppc_e500_emul_tlbilx(vcpu, rt, ea);
break;
case XOP_TLBIVAX:
- emulated = kvmppc_e500_emul_tlbivax(vcpu, ra, rb);
+ ea = kvmppc_get_ea_indexed(vcpu, ra, rb);
+ emulated = kvmppc_e500_emul_tlbivax(vcpu, ea);
break;
default:
diff --git a/arch/powerpc/kvm/e500_tlb.c b/arch/powerpc/kvm/e500_tlb.c
index c510fc9..2175a58 100644
--- a/arch/powerpc/kvm/e500_tlb.c
+++ b/arch/powerpc/kvm/e500_tlb.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008-2011 Freescale Semiconductor, Inc. All rights reserved.
+ * Copyright (C) 2008-2012 Freescale Semiconductor, Inc. All rights reserved.
*
* Author: Yu Liu, yu.liu@freescale.com
* Scott Wood, scottwood@freescale.com
@@ -680,14 +680,11 @@ int kvmppc_e500_emul_mt_mmucsr0(struct kvmppc_vcpu_e500 *vcpu_e500, ulong value)
return EMULATE_DONE;
}
-int kvmppc_e500_emul_tlbivax(struct kvm_vcpu *vcpu, int ra, int rb)
+int kvmppc_e500_emul_tlbivax(struct kvm_vcpu *vcpu, gva_t ea)
{
struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu);
unsigned int ia;
int esel, tlbsel;
- gva_t ea;
-
- ea = ((ra) ? kvmppc_get_gpr(vcpu, ra) : 0) + kvmppc_get_gpr(vcpu, rb);
ia = (ea >> 2) & 0x1;
@@ -731,14 +728,9 @@ static void tlbilx_all(struct kvmppc_vcpu_e500 *vcpu_e500, int tlbsel,
}
static void tlbilx_one(struct kvmppc_vcpu_e500 *vcpu_e500, int pid,
- int ra, int rb)
+ gva_t ea)
{
int tlbsel, esel;
- gva_t ea;
-
- ea = kvmppc_get_gpr(&vcpu_e500->vcpu, rb);
- if (ra)
- ea += kvmppc_get_gpr(&vcpu_e500->vcpu, ra);
for (tlbsel = 0; tlbsel < 2; tlbsel++) {
esel = kvmppc_e500_tlb_index(vcpu_e500, ea, tlbsel, pid, -1);
@@ -750,7 +742,7 @@ static void tlbilx_one(struct kvmppc_vcpu_e500 *vcpu_e500, int pid,
}
}
-int kvmppc_e500_emul_tlbilx(struct kvm_vcpu *vcpu, int rt, int ra, int rb)
+int kvmppc_e500_emul_tlbilx(struct kvm_vcpu *vcpu, int rt, gva_t ea)
{
struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu);
int pid = get_cur_spid(vcpu);
@@ -759,7 +751,7 @@ int kvmppc_e500_emul_tlbilx(struct kvm_vcpu *vcpu, int rt, int ra, int rb)
tlbilx_all(vcpu_e500, 0, pid, rt);
tlbilx_all(vcpu_e500, 1, pid, rt);
} else if (rt == 3) {
- tlbilx_one(vcpu_e500, pid, ra, rb);
+ tlbilx_one(vcpu_e500, pid, ea);
}
return EMULATE_DONE;
@@ -784,16 +776,13 @@ int kvmppc_e500_emul_tlbre(struct kvm_vcpu *vcpu)
return EMULATE_DONE;
}
-int kvmppc_e500_emul_tlbsx(struct kvm_vcpu *vcpu, int rb)
+int kvmppc_e500_emul_tlbsx(struct kvm_vcpu *vcpu, gva_t ea)
{
struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu);
int as = !!get_cur_sas(vcpu);
unsigned int pid = get_cur_spid(vcpu);
int esel, tlbsel;
struct kvm_book3e_206_tlb_entry *gtlbe = NULL;
- gva_t ea;
-
- ea = kvmppc_get_gpr(vcpu, rb);
for (tlbsel = 0; tlbsel < 2; tlbsel++) {
esel = kvmppc_e500_tlb_index(vcpu_e500, ea, tlbsel, pid, as);
--
1.7.4.1
^ permalink raw reply related
* [RFC PATCH 16/17] KVM: PPC: e500: Silence bogus GCC warning in tlb code
From: Mihai Caraman @ 2012-06-25 12:26 UTC (permalink / raw)
To: kvm-ppc, kvm, linuxppc-dev, qemu-ppc; +Cc: Mihai Caraman
In-Reply-To: <1340627195-11544-1-git-send-email-mihai.caraman@freescale.com>
64-bit GCC 4.5.1 warns about an uninitialized variable which was guarded
by a flag. Initialize the variable to make it happy.
Signed-off-by: Mihai Caraman <mihai.caraman@freescale.com>
---
arch/powerpc/kvm/e500_tlb.c | 3 ++-
1 files changed, 2 insertions(+), 1 deletions(-)
diff --git a/arch/powerpc/kvm/e500_tlb.c b/arch/powerpc/kvm/e500_tlb.c
index 3ed4e7d..6286fbd 100644
--- a/arch/powerpc/kvm/e500_tlb.c
+++ b/arch/powerpc/kvm/e500_tlb.c
@@ -412,7 +412,8 @@ static inline void kvmppc_e500_shadow_map(struct kvmppc_vcpu_e500 *vcpu_e500,
struct tlbe_ref *ref)
{
struct kvm_memory_slot *slot;
- unsigned long pfn, hva;
+ unsigned long pfn = 0; /* shut up 64-bit GCC */
+ unsigned long hva;
int pfnmap = 0;
int tsize = BOOK3E_PAGESZ_4K;
--
1.7.4.1
^ permalink raw reply related
* [RFC PATCH 09/17] KVM: PPC64: booke: Hard disable interrupts when entering guest
From: Mihai Caraman @ 2012-06-25 12:26 UTC (permalink / raw)
To: kvm-ppc, kvm, linuxppc-dev, qemu-ppc; +Cc: Mihai Caraman
In-Reply-To: <1340627195-11544-1-git-send-email-mihai.caraman@freescale.com>
64-bit host runs with lazy interrupt disabling, so local_irq_disable() does
not disable interrupts right away and does not protect against preemption
required by __kvmppc_vcpu_run(). Define a macro for 64-bit to use
hard_irq_disable().
Signed-off-by: Mihai Caraman <mihai.caraman@freescale.com>
---
arch/powerpc/kvm/booke.c | 14 ++++++++++----
1 files changed, 10 insertions(+), 4 deletions(-)
diff --git a/arch/powerpc/kvm/booke.c b/arch/powerpc/kvm/booke.c
index 93b48e0..db05692 100644
--- a/arch/powerpc/kvm/booke.c
+++ b/arch/powerpc/kvm/booke.c
@@ -45,6 +45,12 @@ unsigned long kvmppc_booke_handlers;
#define VM_STAT(x) offsetof(struct kvm, stat.x), KVM_STAT_VM
#define VCPU_STAT(x) offsetof(struct kvm_vcpu, stat.x), KVM_STAT_VCPU
+#ifdef CONFIG_64BIT
+#define _hard_irq_disable() hard_irq_disable()
+#else
+#define _hard_irq_disable() local_irq_disable()
+#endif
+
struct kvm_stats_debugfs_item debugfs_entries[] = {
{ "mmio", VCPU_STAT(mmio_exits) },
{ "dcr", VCPU_STAT(dcr_exits) },
@@ -456,7 +462,7 @@ int kvmppc_core_prepare_to_enter(struct kvm_vcpu *vcpu)
local_irq_enable();
kvm_vcpu_block(vcpu);
clear_bit(KVM_REQ_UNHALT, &vcpu->requests);
- local_irq_disable();
+ _hard_irq_disable();
kvmppc_set_exit_type(vcpu, EMULATED_MTMSRWE_EXITS);
r = 1;
@@ -480,7 +486,7 @@ static int kvmppc_prepare_to_enter(struct kvm_vcpu *vcpu)
if (need_resched()) {
local_irq_enable();
cond_resched();
- local_irq_disable();
+ _hard_irq_disable();
continue;
}
@@ -515,7 +521,7 @@ int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
return -EINVAL;
}
- local_irq_disable();
+ _hard_irq_disable();
if (kvmppc_prepare_to_enter(vcpu)) {
kvm_run->exit_reason = KVM_EXIT_INTR;
ret = -EINTR;
@@ -955,7 +961,7 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
* aren't already exiting to userspace for some other reason.
*/
if (!(r & RESUME_HOST)) {
- local_irq_disable();
+ _hard_irq_disable();
if (kvmppc_prepare_to_enter(vcpu)) {
run->exit_reason = KVM_EXIT_INTR;
r = (-EINTR << 2) | RESUME_HOST | (r & RESUME_FLAG_NV);
--
1.7.4.1
^ permalink raw reply related
* [RFC PATCH 12/17] PowerPC: booke64: Add DO_KVM kernel hooks
From: Mihai Caraman @ 2012-06-25 12:26 UTC (permalink / raw)
To: kvm-ppc, kvm, linuxppc-dev, qemu-ppc; +Cc: Mihai Caraman
In-Reply-To: <1340627195-11544-1-git-send-email-mihai.caraman@freescale.com>
Hook DO_KVM macro to 64-bit booke in a optimal way similar to 32-bit booke
see head_fsl_booke.S file. Extend interrupt handlers' parameter list with
interrupt vector numbers to accomodate the macro. Rework Guest Doorbell
handler to use the proper GSRRx save/restore registers.
Only the bolted version of tlb miss handers is addressed now.
Signed-off-by: Mihai Caraman <mihai.caraman@freescale.com>
---
arch/powerpc/kernel/exceptions-64e.S | 114 ++++++++++++++++++++++++----------
arch/powerpc/mm/tlb_low_64e.S | 14 +++-
2 files changed, 92 insertions(+), 36 deletions(-)
diff --git a/arch/powerpc/kernel/exceptions-64e.S b/arch/powerpc/kernel/exceptions-64e.S
index 06f7aec..a60f81f 100644
--- a/arch/powerpc/kernel/exceptions-64e.S
+++ b/arch/powerpc/kernel/exceptions-64e.S
@@ -25,6 +25,8 @@
#include <asm/ppc-opcode.h>
#include <asm/mmu.h>
#include <asm/hw_irq.h>
+#include <asm/kvm_asm.h>
+#include <asm/kvm_booke_hv_asm.h>
/* XXX This will ultimately add space for a special exception save
* structure used to save things like SRR0/SRR1, SPRGs, MAS, etc...
@@ -34,13 +36,24 @@
*/
#define SPECIAL_EXC_FRAME_SIZE INT_FRAME_SIZE
+#ifdef CONFIG_KVM_BOOKE_HV
+#define KVM_BOOKE_HV_MFSPR(reg, spr) \
+ BEGIN_FTR_SECTION \
+ mfspr reg, spr; \
+ END_FTR_SECTION_IFSET(CPU_FTR_EMB_HV)
+#else
+#define KVM_BOOKE_HV_MFSPR(reg, spr)
+#endif
+
/* Exception prolog code for all exceptions */
-#define EXCEPTION_PROLOG(n, type, srr0, srr1, addition) \
+#define EXCEPTION_PROLOG(n, intnum, type, srr0, srr1, addition) \
mtspr SPRN_SPRG_##type##_SCRATCH,r13; /* get spare registers */ \
mfspr r13,SPRN_SPRG_PACA; /* get PACA */ \
std r10,PACA_EX##type+EX_R10(r13); \
std r11,PACA_EX##type+EX_R11(r13); \
mfcr r10; /* save CR */ \
+ KVM_BOOKE_HV_MFSPR(r11,srr1); \
+ DO_KVM intnum,srr1; \
addition; /* additional code for that exc. */ \
std r1,PACA_EX##type+EX_R1(r13); /* save old r1 in the PACA */ \
stw r10,PACA_EX##type+EX_CR(r13); /* save old CR in the PACA */ \
@@ -69,17 +82,21 @@
ld r1,PACA_MC_STACK(r13); \
subi r1,r1,SPECIAL_EXC_FRAME_SIZE;
-#define NORMAL_EXCEPTION_PROLOG(n, addition) \
- EXCEPTION_PROLOG(n, GEN, SPRN_SRR0, SPRN_SRR1, addition##_GEN(n))
+#define NORMAL_EXCEPTION_PROLOG(n, intnum, addition) \
+ EXCEPTION_PROLOG(n, intnum, GEN, SPRN_SRR0, SPRN_SRR1, \
+ addition##_GEN(n))
-#define CRIT_EXCEPTION_PROLOG(n, addition) \
- EXCEPTION_PROLOG(n, CRIT, SPRN_CSRR0, SPRN_CSRR1, addition##_CRIT(n))
+#define CRIT_EXCEPTION_PROLOG(n, intnum, addition) \
+ EXCEPTION_PROLOG(n, intnum, CRIT, SPRN_CSRR0, SPRN_CSRR1, \
+ addition##_CRIT(n))
-#define DBG_EXCEPTION_PROLOG(n, addition) \
- EXCEPTION_PROLOG(n, DBG, SPRN_DSRR0, SPRN_DSRR1, addition##_DBG(n))
+#define DBG_EXCEPTION_PROLOG(n, intnum, addition) \
+ EXCEPTION_PROLOG(n, intnum, DBG, SPRN_DSRR0, SPRN_DSRR1, \
+ addition##_DBG(n))
-#define MC_EXCEPTION_PROLOG(n, addition) \
- EXCEPTION_PROLOG(n, MC, SPRN_MCSRR0, SPRN_MCSRR1, addition##_MC(n))
+#define MC_EXCEPTION_PROLOG(n, intnum, addition) \
+ EXCEPTION_PROLOG(n, intnum, MC, SPRN_MCSRR0, SPRN_MCSRR1, \
+ addition##_MC(n))
/* Variants of the "addition" argument for the prolog
@@ -226,9 +243,9 @@ exc_##n##_bad_stack: \
1:
-#define MASKABLE_EXCEPTION(trapnum, label, hdlr, ack) \
+#define MASKABLE_EXCEPTION(trapnum, intnum, label, hdlr, ack) \
START_EXCEPTION(label); \
- NORMAL_EXCEPTION_PROLOG(trapnum, PROLOG_ADDITION_MASKABLE) \
+ NORMAL_EXCEPTION_PROLOG(trapnum, intnum, PROLOG_ADDITION_MASKABLE)\
EXCEPTION_COMMON(trapnum, PACA_EXGEN, INTS_DISABLE) \
ack(r8); \
CHECK_NAPPING(); \
@@ -279,7 +296,8 @@ interrupt_end_book3e:
/* Critical Input Interrupt */
START_EXCEPTION(critical_input);
- CRIT_EXCEPTION_PROLOG(0x100, PROLOG_ADDITION_NONE)
+ CRIT_EXCEPTION_PROLOG(0x100, BOOKE_INTERRUPT_CRITICAL,
+ PROLOG_ADDITION_NONE)
// EXCEPTION_COMMON(0x100, PACA_EXCRIT, INTS_DISABLE)
// bl special_reg_save_crit
// CHECK_NAPPING();
@@ -290,7 +308,8 @@ interrupt_end_book3e:
/* Machine Check Interrupt */
START_EXCEPTION(machine_check);
- MC_EXCEPTION_PROLOG(0x200, PROLOG_ADDITION_NONE)
+ MC_EXCEPTION_PROLOG(0x200, BOOKE_INTERRUPT_MACHINE_CHECK,
+ PROLOG_ADDITION_NONE)
// EXCEPTION_COMMON(0x200, PACA_EXMC, INTS_DISABLE)
// bl special_reg_save_mc
// addi r3,r1,STACK_FRAME_OVERHEAD
@@ -301,7 +320,8 @@ interrupt_end_book3e:
/* Data Storage Interrupt */
START_EXCEPTION(data_storage)
- NORMAL_EXCEPTION_PROLOG(0x300, PROLOG_ADDITION_2REGS)
+ NORMAL_EXCEPTION_PROLOG(0x300, BOOKE_INTERRUPT_DATA_STORAGE,
+ PROLOG_ADDITION_2REGS)
mfspr r14,SPRN_DEAR
mfspr r15,SPRN_ESR
EXCEPTION_COMMON(0x300, PACA_EXGEN, INTS_DISABLE)
@@ -309,18 +329,21 @@ interrupt_end_book3e:
/* Instruction Storage Interrupt */
START_EXCEPTION(instruction_storage);
- NORMAL_EXCEPTION_PROLOG(0x400, PROLOG_ADDITION_2REGS)
+ NORMAL_EXCEPTION_PROLOG(0x400, BOOKE_INTERRUPT_INST_STORAGE,
+ PROLOG_ADDITION_2REGS)
li r15,0
mr r14,r10
EXCEPTION_COMMON(0x400, PACA_EXGEN, INTS_DISABLE)
b storage_fault_common
/* External Input Interrupt */
- MASKABLE_EXCEPTION(0x500, external_input, .do_IRQ, ACK_NONE)
+ MASKABLE_EXCEPTION(0x500, BOOKE_INTERRUPT_EXTERNAL,
+ external_input, .do_IRQ, ACK_NONE)
/* Alignment */
START_EXCEPTION(alignment);
- NORMAL_EXCEPTION_PROLOG(0x600, PROLOG_ADDITION_2REGS)
+ NORMAL_EXCEPTION_PROLOG(0x600, BOOKE_INTERRUPT_ALIGNMENT,
+ PROLOG_ADDITION_2REGS)
mfspr r14,SPRN_DEAR
mfspr r15,SPRN_ESR
EXCEPTION_COMMON(0x600, PACA_EXGEN, INTS_KEEP)
@@ -328,7 +351,8 @@ interrupt_end_book3e:
/* Program Interrupt */
START_EXCEPTION(program);
- NORMAL_EXCEPTION_PROLOG(0x700, PROLOG_ADDITION_1REG)
+ NORMAL_EXCEPTION_PROLOG(0x700, BOOKE_INTERRUPT_PROGRAM,
+ PROLOG_ADDITION_1REG)
mfspr r14,SPRN_ESR
EXCEPTION_COMMON(0x700, PACA_EXGEN, INTS_DISABLE)
std r14,_DSISR(r1)
@@ -340,7 +364,8 @@ interrupt_end_book3e:
/* Floating Point Unavailable Interrupt */
START_EXCEPTION(fp_unavailable);
- NORMAL_EXCEPTION_PROLOG(0x800, PROLOG_ADDITION_NONE)
+ NORMAL_EXCEPTION_PROLOG(0x800, BOOKE_INTERRUPT_FP_UNAVAIL,
+ PROLOG_ADDITION_NONE)
/* we can probably do a shorter exception entry for that one... */
EXCEPTION_COMMON(0x800, PACA_EXGEN, INTS_KEEP)
ld r12,_MSR(r1)
@@ -355,14 +380,17 @@ interrupt_end_book3e:
b .ret_from_except
/* Decrementer Interrupt */
- MASKABLE_EXCEPTION(0x900, decrementer, .timer_interrupt, ACK_DEC)
+ MASKABLE_EXCEPTION(0x900, BOOKE_INTERRUPT_DECREMENTER,
+ decrementer, .timer_interrupt, ACK_DEC)
/* Fixed Interval Timer Interrupt */
- MASKABLE_EXCEPTION(0x980, fixed_interval, .unknown_exception, ACK_FIT)
+ MASKABLE_EXCEPTION(0x980, BOOKE_INTERRUPT_FIT,
+ fixed_interval, .unknown_exception, ACK_FIT)
/* Watchdog Timer Interrupt */
START_EXCEPTION(watchdog);
- CRIT_EXCEPTION_PROLOG(0x9f0, PROLOG_ADDITION_NONE)
+ CRIT_EXCEPTION_PROLOG(0x9f0, BOOKE_INTERRUPT_WATCHDOG,
+ PROLOG_ADDITION_NONE)
// EXCEPTION_COMMON(0x9f0, PACA_EXCRIT, INTS_DISABLE)
// bl special_reg_save_crit
// CHECK_NAPPING();
@@ -381,7 +409,8 @@ interrupt_end_book3e:
/* Auxiliary Processor Unavailable Interrupt */
START_EXCEPTION(ap_unavailable);
- NORMAL_EXCEPTION_PROLOG(0xf20, PROLOG_ADDITION_NONE)
+ NORMAL_EXCEPTION_PROLOG(0xf20, BOOKE_INTERRUPT_AP_UNAVAIL,
+ PROLOG_ADDITION_NONE)
EXCEPTION_COMMON(0xf20, PACA_EXGEN, INTS_DISABLE)
bl .save_nvgprs
addi r3,r1,STACK_FRAME_OVERHEAD
@@ -390,7 +419,8 @@ interrupt_end_book3e:
/* Debug exception as a critical interrupt*/
START_EXCEPTION(debug_crit);
- CRIT_EXCEPTION_PROLOG(0xd00, PROLOG_ADDITION_2REGS)
+ CRIT_EXCEPTION_PROLOG(0xd00, BOOKE_INTERRUPT_DEBUG,
+ PROLOG_ADDITION_2REGS)
/*
* If there is a single step or branch-taken exception in an
@@ -455,7 +485,8 @@ kernel_dbg_exc:
/* Debug exception as a debug interrupt*/
START_EXCEPTION(debug_debug);
- DBG_EXCEPTION_PROLOG(0xd08, PROLOG_ADDITION_2REGS)
+ DBG_EXCEPTION_PROLOG(0xd00, BOOKE_INTERRUPT_DEBUG,
+ PROLOG_ADDITION_2REGS)
/*
* If there is a single step or branch-taken exception in an
@@ -516,18 +547,21 @@ kernel_dbg_exc:
b .ret_from_except
START_EXCEPTION(perfmon);
- NORMAL_EXCEPTION_PROLOG(0x260, PROLOG_ADDITION_NONE)
+ NORMAL_EXCEPTION_PROLOG(0x260, BOOKE_INTERRUPT_PERFORMANCE_MONITOR,
+ PROLOG_ADDITION_NONE)
EXCEPTION_COMMON(0x260, PACA_EXGEN, INTS_DISABLE)
addi r3,r1,STACK_FRAME_OVERHEAD
bl .performance_monitor_exception
b .ret_from_except_lite
/* Doorbell interrupt */
- MASKABLE_EXCEPTION(0x280, doorbell, .doorbell_exception, ACK_NONE)
+ MASKABLE_EXCEPTION(0x280, BOOKE_INTERRUPT_DOORBELL,
+ doorbell, .doorbell_exception, ACK_NONE)
/* Doorbell critical Interrupt */
START_EXCEPTION(doorbell_crit);
- CRIT_EXCEPTION_PROLOG(0x2a0, PROLOG_ADDITION_NONE)
+ CRIT_EXCEPTION_PROLOG(0x2a0, BOOKE_INTERRUPT_DOORBELL_CRITICAL,
+ PROLOG_ADDITION_NONE)
// EXCEPTION_COMMON(0x2a0, PACA_EXCRIT, INTS_DISABLE)
// bl special_reg_save_crit
// CHECK_NAPPING();
@@ -536,12 +570,24 @@ kernel_dbg_exc:
// b ret_from_crit_except
b .
-/* Guest Doorbell */
- MASKABLE_EXCEPTION(0x2c0, guest_doorbell, .unknown_exception, ACK_NONE)
+/*
+ * Guest doorbell interrupt
+ * This general exception use GSRRx save/restore registers
+ */
+ START_EXCEPTION(guest_doorbell);
+ EXCEPTION_PROLOG(0x2c0, BOOKE_INTERRUPT_GUEST_DBELL, GEN,
+ SPRN_GSRR0, SPRN_GSRR1, PROLOG_ADDITION_NONE)
+ EXCEPTION_COMMON(0x2c0, PACA_EXGEN, INTS_KEEP)
+ addi r3,r1,STACK_FRAME_OVERHEAD
+ bl .save_nvgprs
+ INTS_RESTORE_HARD
+ bl .unknown_exception
+ b .ret_from_except
/* Guest Doorbell critical Interrupt */
START_EXCEPTION(guest_doorbell_crit);
- CRIT_EXCEPTION_PROLOG(0x2e0, PROLOG_ADDITION_NONE)
+ CRIT_EXCEPTION_PROLOG(0x2e0, BOOKE_INTERRUPT_GUEST_DBELL_CRIT,
+ PROLOG_ADDITION_NONE)
// EXCEPTION_COMMON(0x2e0, PACA_EXCRIT, INTS_DISABLE)
// bl special_reg_save_crit
// CHECK_NAPPING();
@@ -552,7 +598,8 @@ kernel_dbg_exc:
/* Hypervisor call */
START_EXCEPTION(hypercall);
- NORMAL_EXCEPTION_PROLOG(0x310, PROLOG_ADDITION_NONE)
+ NORMAL_EXCEPTION_PROLOG(0x310, BOOKE_INTERRUPT_HV_SYSCALL,
+ PROLOG_ADDITION_NONE)
EXCEPTION_COMMON(0x310, PACA_EXGEN, INTS_KEEP)
addi r3,r1,STACK_FRAME_OVERHEAD
bl .save_nvgprs
@@ -562,7 +609,8 @@ kernel_dbg_exc:
/* Embedded Hypervisor priviledged */
START_EXCEPTION(ehpriv);
- NORMAL_EXCEPTION_PROLOG(0x320, PROLOG_ADDITION_NONE)
+ NORMAL_EXCEPTION_PROLOG(0x320, BOOKE_INTERRUPT_HV_PRIV,
+ PROLOG_ADDITION_NONE)
EXCEPTION_COMMON(0x320, PACA_EXGEN, INTS_KEEP)
addi r3,r1,STACK_FRAME_OVERHEAD
bl .save_nvgprs
diff --git a/arch/powerpc/mm/tlb_low_64e.S b/arch/powerpc/mm/tlb_low_64e.S
index ff672bd..88feaaa 100644
--- a/arch/powerpc/mm/tlb_low_64e.S
+++ b/arch/powerpc/mm/tlb_low_64e.S
@@ -20,6 +20,8 @@
#include <asm/pgtable.h>
#include <asm/exception-64e.h>
#include <asm/ppc-opcode.h>
+#include <asm/kvm_asm.h>
+#include <asm/kvm_booke_hv_asm.h>
#ifdef CONFIG_PPC_64K_PAGES
#define VPTE_PMD_SHIFT (PTE_INDEX_SIZE+1)
@@ -37,12 +39,18 @@
* *
**********************************************************************/
-.macro tlb_prolog_bolted addr
+.macro tlb_prolog_bolted intnum addr
mtspr SPRN_SPRG_TLB_SCRATCH,r13
mfspr r13,SPRN_SPRG_PACA
std r10,PACA_EXTLB+EX_TLB_R10(r13)
mfcr r10
std r11,PACA_EXTLB+EX_TLB_R11(r13)
+#ifdef CONFIG_KVM_BOOKE_HV
+BEGIN_FTR_SECTION
+ mfspr r11, SPRN_SRR1
+END_FTR_SECTION_IFSET(CPU_FTR_EMB_HV)
+#endif
+ DO_KVM \intnum, SPRN_SRR1
std r16,PACA_EXTLB+EX_TLB_R16(r13)
mfspr r16,\addr /* get faulting address */
std r14,PACA_EXTLB+EX_TLB_R14(r13)
@@ -66,7 +74,7 @@
/* Data TLB miss */
START_EXCEPTION(data_tlb_miss_bolted)
- tlb_prolog_bolted SPRN_DEAR
+ tlb_prolog_bolted BOOKE_INTERRUPT_DTLB_MISS SPRN_DEAR
/* We need _PAGE_PRESENT and _PAGE_ACCESSED set */
@@ -214,7 +222,7 @@ itlb_miss_fault_bolted:
/* Instruction TLB miss */
START_EXCEPTION(instruction_tlb_miss_bolted)
- tlb_prolog_bolted SPRN_SRR0
+ tlb_prolog_bolted BOOKE_INTERRUPT_ITLB_MISS SPRN_SRR0
rldicl. r10,r16,64-PGTABLE_EADDR_SIZE,PGTABLE_EADDR_SIZE+4
srdi r15,r16,60 /* get region */
--
1.7.4.1
^ permalink raw reply related
* [RFC PATCH 14/17] KVM: PPC32: bookehv: Remove GET_VCPU macro from exception handler
From: Mihai Caraman @ 2012-06-25 12:26 UTC (permalink / raw)
To: kvm-ppc, kvm, linuxppc-dev, qemu-ppc; +Cc: Mihai Caraman
In-Reply-To: <1340627195-11544-1-git-send-email-mihai.caraman@freescale.com>
GET_VCPU define will not be implemented for 64-bit for performance reasons
so get rid of it also on 32-bit.
Signed-off-by: Mihai Caraman <mihai.caraman@freescale.com>
---
arch/powerpc/kvm/bookehv_interrupts.S | 7 ++-----
1 files changed, 2 insertions(+), 5 deletions(-)
diff --git a/arch/powerpc/kvm/bookehv_interrupts.S b/arch/powerpc/kvm/bookehv_interrupts.S
index 6048a00..dff8ed4 100644
--- a/arch/powerpc/kvm/bookehv_interrupts.S
+++ b/arch/powerpc/kvm/bookehv_interrupts.S
@@ -32,9 +32,6 @@
#include "../kernel/head_booke.h" /* for THREAD_NORMSAVE() */
-#define GET_VCPU(vcpu, thread) \
- PPC_LL vcpu, THREAD_KVM_VCPU(thread)
-
#define LONGBYTES (BITS_PER_LONG / 8)
#define VCPU_GPR(n) (VCPU_GPRS + (n * LONGBYTES))
@@ -210,7 +207,7 @@
*/
.macro kvm_handler intno srr0, srr1, flags
_GLOBAL(kvmppc_handler_\intno\()_\srr1)
- GET_VCPU(r11, r10)
+ PPC_LL r11, THREAD_KVM_VCPU(r10)
PPC_STL r3, VCPU_GPR(r3)(r11)
mfspr r3, SPRN_SPRG_RSCRATCH0
PPC_STL r4, VCPU_GPR(r4)(r11)
@@ -237,7 +234,7 @@ _GLOBAL(kvmppc_handler_\intno\()_\srr1)
.macro kvm_lvl_handler intno scratch srr0, srr1, flags
_GLOBAL(kvmppc_handler_\intno\()_\srr1)
mfspr r10, SPRN_SPRG_THREAD
- GET_VCPU(r11, r10)
+ PPC_LL r11, THREAD_KVM_VCPU(r10)
PPC_STL r3, VCPU_GPR(r3)(r11)
mfspr r3, \scratch
PPC_STL r4, VCPU_GPR(r4)(r11)
--
1.7.4.1
^ permalink raw reply related
* [RFC PATCH 10/17] PowerPC: booke64: Refactor exception prolog for save/restore regs
From: Mihai Caraman @ 2012-06-25 12:26 UTC (permalink / raw)
To: kvm-ppc, kvm, linuxppc-dev, qemu-ppc; +Cc: Mihai Caraman
In-Reply-To: <1340627195-11544-1-git-send-email-mihai.caraman@freescale.com>
Refactor exception prolog to allow save/restore register parameters. Add
addition none definition for exception prolog usage.
This is needed for exceptions like Guest Doorbell that use GSRRx regsiters
which do not map on exception type.
Signed-off-by: Mihai Caraman <mihai.caraman@freescale.com>
---
arch/powerpc/kernel/exceptions-64e.S | 23 ++++++++---------------
1 files changed, 8 insertions(+), 15 deletions(-)
diff --git a/arch/powerpc/kernel/exceptions-64e.S b/arch/powerpc/kernel/exceptions-64e.S
index 7215cc2..52aa96b 100644
--- a/arch/powerpc/kernel/exceptions-64e.S
+++ b/arch/powerpc/kernel/exceptions-64e.S
@@ -35,7 +35,7 @@
#define SPECIAL_EXC_FRAME_SIZE INT_FRAME_SIZE
/* Exception prolog code for all exceptions */
-#define EXCEPTION_PROLOG(n, type, addition) \
+#define EXCEPTION_PROLOG(n, type, srr0, srr1, addition) \
mtspr SPRN_SPRG_##type##_SCRATCH,r13; /* get spare registers */ \
mfspr r13,SPRN_SPRG_PACA; /* get PACA */ \
std r10,PACA_EX##type+EX_R10(r13); \
@@ -44,54 +44,47 @@
addition; /* additional code for that exc. */ \
std r1,PACA_EX##type+EX_R1(r13); /* save old r1 in the PACA */ \
stw r10,PACA_EX##type+EX_CR(r13); /* save old CR in the PACA */ \
- mfspr r11,SPRN_##type##_SRR1;/* what are we coming from */ \
+ mfspr r11,srr1;/* what are we coming from */ \
type##_SET_KSTACK; /* get special stack if necessary */\
andi. r10,r11,MSR_PR; /* save stack pointer */ \
beq 1f; /* branch around if supervisor */ \
ld r1,PACAKSAVE(r13); /* get kernel stack coming from usr */\
1: cmpdi cr1,r1,0; /* check if SP makes sense */ \
bge- cr1,exc_##n##_bad_stack;/* bad stack (TODO: out of line) */ \
- mfspr r10,SPRN_##type##_SRR0; /* read SRR0 before touching stack */
+ mfspr r10,srr0; /* read SRR0 before touching stack */
/* Exception type-specific macros */
#define GEN_SET_KSTACK \
subi r1,r1,INT_FRAME_SIZE; /* alloc frame on kernel stack */
-#define SPRN_GEN_SRR0 SPRN_SRR0
-#define SPRN_GEN_SRR1 SPRN_SRR1
#define CRIT_SET_KSTACK \
ld r1,PACA_CRIT_STACK(r13); \
subi r1,r1,SPECIAL_EXC_FRAME_SIZE;
-#define SPRN_CRIT_SRR0 SPRN_CSRR0
-#define SPRN_CRIT_SRR1 SPRN_CSRR1
#define DBG_SET_KSTACK \
ld r1,PACA_DBG_STACK(r13); \
subi r1,r1,SPECIAL_EXC_FRAME_SIZE;
-#define SPRN_DBG_SRR0 SPRN_DSRR0
-#define SPRN_DBG_SRR1 SPRN_DSRR1
#define MC_SET_KSTACK \
ld r1,PACA_MC_STACK(r13); \
subi r1,r1,SPECIAL_EXC_FRAME_SIZE;
-#define SPRN_MC_SRR0 SPRN_MCSRR0
-#define SPRN_MC_SRR1 SPRN_MCSRR1
#define NORMAL_EXCEPTION_PROLOG(n, addition) \
- EXCEPTION_PROLOG(n, GEN, addition##_GEN(n))
+ EXCEPTION_PROLOG(n, GEN, SPRN_SRR0, SPRN_SRR1, addition##_GEN(n))
#define CRIT_EXCEPTION_PROLOG(n, addition) \
- EXCEPTION_PROLOG(n, CRIT, addition##_CRIT(n))
+ EXCEPTION_PROLOG(n, CRIT, SPRN_CSRR0, SPRN_CSRR1, addition##_CRIT(n))
#define DBG_EXCEPTION_PROLOG(n, addition) \
- EXCEPTION_PROLOG(n, DBG, addition##_DBG(n))
+ EXCEPTION_PROLOG(n, DBG, SPRN_DSRR0, SPRN_DSRR1, addition##_DBG(n))
#define MC_EXCEPTION_PROLOG(n, addition) \
- EXCEPTION_PROLOG(n, MC, addition##_MC(n))
+ EXCEPTION_PROLOG(n, MC, SPRN_MCSRR0, SPRN_MCSRR1, addition##_MC(n))
/* Variants of the "addition" argument for the prolog
*/
+#define PROLOG_ADDITION_NONE
#define PROLOG_ADDITION_NONE_GEN(n)
#define PROLOG_ADDITION_NONE_CRIT(n)
#define PROLOG_ADDITION_NONE_DBG(n)
--
1.7.4.1
^ permalink raw reply related
* [RFC PATCH 00/17] KVM: PPC: 64-bit Book3E support
From: Mihai Caraman @ 2012-06-25 12:26 UTC (permalink / raw)
To: kvm-ppc, kvm, linuxppc-dev, qemu-ppc; +Cc: Mihai Caraman
This patchset adds 64-bit Book3E PowerPC support to KVM. It is intended
as a request for comment for scratch register changes and for the support
limited to bolted TLB miss exception handlers.
This work was validated on Freescale's e5500 cores using P5020DS boards.
This patchset is based on Alex G. kvm-ppc-next branch. For a ready to use
git tree, please check here:
git://github.com/mcaraman/kvm.git 64-bit-booke
Current limitations:
- 64-bit guests must be configured without KVM support. CPU_FTR_EMB_HV setup
for 64-bit non-hv will be addressed soon in a different patchset.
Prerequisite patches, availabe on top of the git tree:
- commit 7cd1afad10d981cbf4a0c8738bf7f5c0add0e50f:
Make hard_irq_disable() actually hard-disable interrupts
- commit 9a5a0b80cf7e09bd6fadf1a66f27579d0f6d2795, required to run 32-bit
guests on e5500 cores:
powerpc/e5500: Set r5 to point to cpu spec in setup_cpu_e5500()
- commit 6c04342ba5ad7723d8b07d2ad4800607c0985c35, required to run 64-bit
SMP guests:
KVM: PPC: bookehv64: Add support for std/ld emulation
This patchset requires a qemu with e5500 support. For a ready to use git tree,
please check here:
git://repo.or.cz/qemu/agraf.git ppc-e5500
To use qemu run:
$ qemu-system-ppc64 -M mpc8544ds -cpu e5500 -nographic -kernel uImage \
-machine dt_compatible=fsl,,P5020DS
Mike
Mihai Caraman (17):
KVM: PPC64: booke: Set interrupt computation mode for 64-bit host
KVM: PPC64: booke: Add EPCR support in mtspr/mfspr emulation
KVM: PPC64: booke: Add EPCR support in sregs
KVM: PPC64: booke: Add guest computation mode for irq delivery
KVM: PPC: booke: Extend MAS2 EPN mask for 64-bit
KVM: PPC: e500: Add emulation helper for getting instruction ea
KVM: PPC: e500: Mask ea's high 32-bits in 32/64 instr emulation
KVM: PPC: e500mc: Fix tlbilx emulation for 64-bit guests
KVM: PPC64: booke: Hard disable interrupts when entering guest
PowerPC: booke64: Refactor exception prolog for save/restore regs
PowerPC: booke64: Fix machine check handler to use the right prolog
PowerPC: booke64: Add DO_KVM kernel hooks
PowerPC: booke64: Use SPRG0/3 scratch for bolted TLB miss & crit int
KVM: PPC32: bookehv: Remove GET_VCPU macro from exception handler
KVM: PPC64: bookehv: Add support for interrupt handling
KVM: PPC: e500: Silence bogus GCC warning in tlb code
KVM: PPC: booke: Fix get_tb() compile error on 64-bit
arch/powerpc/include/asm/exception-64e.h | 14 ++--
arch/powerpc/include/asm/kvm_booke_hv_asm.h | 12 +++-
arch/powerpc/include/asm/mmu-book3e.h | 2 +-
arch/powerpc/include/asm/reg.h | 6 +-
arch/powerpc/kernel/exceptions-64e.S | 127 ++++++++++++++++++---------
arch/powerpc/kvm/booke.c | 49 +++++++++--
arch/powerpc/kvm/booke.h | 6 ++
arch/powerpc/kvm/booke_emulate.c | 13 +++-
arch/powerpc/kvm/bookehv_interrupts.S | 127 ++++++++++++++++++++++++---
arch/powerpc/kvm/e500.h | 8 +-
arch/powerpc/kvm/e500_emulate.c | 26 +++++-
arch/powerpc/kvm/e500_tlb.c | 28 ++----
arch/powerpc/kvm/e500mc.c | 8 ++-
arch/powerpc/mm/tlb_low_64e.S | 42 +++++----
14 files changed, 347 insertions(+), 121 deletions(-)
--
1.7.4.1
^ permalink raw reply
* [RFC PATCH 07/17] KVM: PPC: e500: Mask ea's high 32-bits in 32/64 instr emulation
From: Mihai Caraman @ 2012-06-25 12:26 UTC (permalink / raw)
To: kvm-ppc, kvm, linuxppc-dev, qemu-ppc; +Cc: Mihai Caraman
In-Reply-To: <1340627195-11544-1-git-send-email-mihai.caraman@freescale.com>
Mask high 32 bits of effective address in emulation layer, for guests running
in 32-bit mode.
MAS2's high-order 32 bits represents the upper 32 bits of the effective address
of the page. Mask it too for tlbwe instruction emulation.
Signed-off-by: Mihai Caraman <mihai.caraman@freescale.com>
---
arch/powerpc/kvm/e500_emulate.c | 5 ++++-
arch/powerpc/kvm/e500_tlb.c | 2 ++
2 files changed, 6 insertions(+), 1 deletions(-)
diff --git a/arch/powerpc/kvm/e500_emulate.c b/arch/powerpc/kvm/e500_emulate.c
index 81288f7..94305db 100644
--- a/arch/powerpc/kvm/e500_emulate.c
+++ b/arch/powerpc/kvm/e500_emulate.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008-2011 Freescale Semiconductor, Inc. All rights reserved.
+ * Copyright (C) 2008-2012 Freescale Semiconductor, Inc. All rights reserved.
*
* Author: Yu Liu, <yu.liu@freescale.com>
*
@@ -90,6 +90,9 @@ static inline ulong kvmppc_get_ea_indexed(struct kvm_vcpu *vcpu, int ra, int rb)
if (ra)
ea += kvmppc_get_gpr(vcpu, ra);
+ if (!(vcpu->arch.shared->msr & MSR_CM))
+ ea &= 0xffffffffUL;
+
return ea;
}
diff --git a/arch/powerpc/kvm/e500_tlb.c b/arch/powerpc/kvm/e500_tlb.c
index 2175a58..3ed4e7d 100644
--- a/arch/powerpc/kvm/e500_tlb.c
+++ b/arch/powerpc/kvm/e500_tlb.c
@@ -862,6 +862,8 @@ int kvmppc_e500_emul_tlbwe(struct kvm_vcpu *vcpu)
gtlbe->mas1 = vcpu->arch.shared->mas1;
gtlbe->mas2 = vcpu->arch.shared->mas2;
+ if (!(vcpu->arch.shared->msr & MSR_CM))
+ gtlbe->mas2 &= 0xffffffffUL;
gtlbe->mas7_3 = vcpu->arch.shared->mas7_3;
trace_kvm_booke206_gtlb_write(vcpu->arch.shared->mas0, gtlbe->mas1,
--
1.7.4.1
^ permalink raw reply related
* [RFC PATCH 15/17] KVM: PPC64: bookehv: Add support for interrupt handling
From: Mihai Caraman @ 2012-06-25 12:26 UTC (permalink / raw)
To: kvm-ppc, kvm, linuxppc-dev, qemu-ppc; +Cc: Mihai Caraman
In-Reply-To: <1340627195-11544-1-git-send-email-mihai.caraman@freescale.com>
Add bookehv interrupt handling support for 64-bit hosts. Change common stack
layout to refer PPC_LR_STKOFF kernel constant. Dispatch the 64-bit execution
flow to the existing kvm_handler_common asm macro. Update input register
values documentation.
Only the bolted version of TLB miss exception handlers is supported now.
Signed-off-by: Mihai Caraman <mihai.caraman@freescale.com>
---
arch/powerpc/include/asm/kvm_booke_hv_asm.h | 12 +++-
arch/powerpc/kvm/bookehv_interrupts.S | 120 +++++++++++++++++++++++++--
2 files changed, 122 insertions(+), 10 deletions(-)
diff --git a/arch/powerpc/include/asm/kvm_booke_hv_asm.h b/arch/powerpc/include/asm/kvm_booke_hv_asm.h
index 30a600f..8be6f87 100644
--- a/arch/powerpc/include/asm/kvm_booke_hv_asm.h
+++ b/arch/powerpc/include/asm/kvm_booke_hv_asm.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2010-2011 Freescale Semiconductor, Inc.
+ * Copyright 2010-2012 Freescale Semiconductor, Inc.
*
* 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
@@ -17,6 +17,7 @@
* there are no exceptions for which we fall through directly to
* the normal host handler.
*
+ * 32-bit host
* Expected inputs (normal exceptions):
* SCRATCH0 = saved r10
* r10 = thread struct
@@ -33,6 +34,15 @@
* *(r8 + GPR9) = saved r9
* *(r8 + GPR10) = saved r10 (r10 not yet clobbered)
* *(r8 + GPR11) = saved r11
+ *
+ * 64-bit host
+ * Expected inputs (exception types GEN/DBG/CRIT/MC):
+ * r13 = PACA_POINTER
+ * r10 = saved CR
+ * SPRN_SPRG_##type##_SCRATCH = saved r13
+ * *(r13 + PACA_EX##type + EX_R10) = saved r10
+ * *(r13 + PACA_EX##type + EX_R11) = saved r11
+ * Only the bolted version of TLB miss exception handlers is supported now.
*/
.macro DO_KVM intno srr1
#ifdef CONFIG_KVM_BOOKE_HV
diff --git a/arch/powerpc/kvm/bookehv_interrupts.S b/arch/powerpc/kvm/bookehv_interrupts.S
index dff8ed4..04097de 100644
--- a/arch/powerpc/kvm/bookehv_interrupts.S
+++ b/arch/powerpc/kvm/bookehv_interrupts.S
@@ -12,10 +12,11 @@
* along with this program; if not, write to the Free Software
* Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * Copyright (C) 2010-2011 Freescale Semiconductor, Inc.
+ * Copyright (C) 2010-2012 Freescale Semiconductor, Inc.
*
* Author: Varun Sethi <varun.sethi@freescale.com>
* Author: Scott Wood <scotwood@freescale.com>
+ * Author: Mihai Caraman <mihai.caraman@freescale.com>
*
* This file is derived from arch/powerpc/kvm/booke_interrupts.S
*/
@@ -30,7 +31,11 @@
#include <asm/bitsperlong.h>
#include <asm/thread_info.h>
+#ifdef CONFIG_64BIT
+#include <asm/exception-64e.h>
+#else
#include "../kernel/head_booke.h" /* for THREAD_NORMSAVE() */
+#endif
#define LONGBYTES (BITS_PER_LONG / 8)
@@ -38,20 +43,21 @@
#define VCPU_GUEST_SPRG(n) (VCPU_GUEST_SPRGS + (n * LONGBYTES))
/* The host stack layout: */
-#define HOST_R1 (0 * LONGBYTES) /* Implied by stwu. */
-#define HOST_CALLEE_LR (1 * LONGBYTES)
-#define HOST_RUN (2 * LONGBYTES) /* struct kvm_run */
+#define HOST_R1 0 /* Implied by stwu. */
+#define HOST_CALLEE_LR PPC_LR_STKOFF
+#define HOST_RUN (HOST_CALLEE_LR + LONGBYTES)
/*
* r2 is special: it holds 'current', and it made nonvolatile in the
* kernel with the -ffixed-r2 gcc option.
*/
-#define HOST_R2 (3 * LONGBYTES)
-#define HOST_CR (4 * LONGBYTES)
-#define HOST_NV_GPRS (5 * LONGBYTES)
+#define HOST_R2 (HOST_RUN + LONGBYTES)
+#define HOST_CR (HOST_R2 + LONGBYTES)
+#define HOST_NV_GPRS (HOST_CR + LONGBYTES)
#define HOST_NV_GPR(n) (HOST_NV_GPRS + ((n - 14) * LONGBYTES))
#define HOST_MIN_STACK_SIZE (HOST_NV_GPR(31) + LONGBYTES)
#define HOST_STACK_SIZE ((HOST_MIN_STACK_SIZE + 15) & ~15) /* Align. */
-#define HOST_STACK_LR (HOST_STACK_SIZE + LONGBYTES) /* In caller stack frame. */
+/* LR in caller stack frame. */
+#define HOST_STACK_LR (HOST_STACK_SIZE + PPC_LR_STKOFF)
#define NEED_EMU 0x00000001 /* emulation -- save nv regs */
#define NEED_DEAR 0x00000002 /* save faulting DEAR */
@@ -202,6 +208,102 @@
b kvmppc_resume_host
.endm
+#ifdef CONFIG_64BIT
+/*
+ * For input register values, see arch/powerpc/include/asm/kvm_booke_hv_asm.h
+ */
+.macro kvm_handler intno scratch, paca_ex, ex_r10, ex_r11, srr0, srr1, flags
+ _GLOBAL(kvmppc_handler_\intno\()_\srr1)
+ mr r11, r4
+ /*
+ * Get vcpu from Paca: paca->__current.thread->kvm_vcpu
+ */
+ PPC_LL r4, PACACURRENT(r13)
+ PPC_LL r4, (THREAD + THREAD_KVM_VCPU)(r4)
+ stw r10, VCPU_CR(r4)
+ PPC_STL r11, VCPU_GPR(r4)(r4)
+ PPC_STL r5, VCPU_GPR(r5)(r4)
+ mfspr r5, \scratch
+ PPC_STL r6, VCPU_GPR(r6)(r4)
+ PPC_STL r8, VCPU_GPR(r8)(r4)
+ PPC_STL r9, VCPU_GPR(r9)(r4)
+ PPC_STL r5, VCPU_GPR(r13)(r4)
+ PPC_LL r6, (\paca_ex + \ex_r10)(r13)
+ PPC_LL r8, (\paca_ex + \ex_r11)(r13)
+ PPC_STL r3, VCPU_GPR(r3)(r4)
+ PPC_STL r7, VCPU_GPR(r7)(r4)
+ PPC_STL r12, VCPU_GPR(r12)(r4)
+ PPC_STL r6, VCPU_GPR(r10)(r4)
+ PPC_STL r8, VCPU_GPR(r11)(r4)
+ mfctr r5
+ PPC_STL r5, VCPU_CTR(r4)
+ mfspr r5, \srr0
+ mfspr r6, \srr1
+ kvm_handler_common \intno, \srr0, \flags
+.endm
+
+#define EX_PARAMS(type) \
+ SPRN_SPRG_##type##_SCRATCH, \
+ PACA_EX##type, \
+ EX_R10, \
+ EX_R11
+
+kvm_handler BOOKE_INTERRUPT_CRITICAL, EX_PARAMS(CRIT), \
+ SPRN_CSRR0, SPRN_CSRR1, 0
+kvm_handler BOOKE_INTERRUPT_MACHINE_CHECK, EX_PARAMS(MC), \
+ SPRN_MCSRR0, SPRN_MCSRR1, 0
+kvm_handler BOOKE_INTERRUPT_DATA_STORAGE, EX_PARAMS(GEN), \
+ SPRN_SRR0, SPRN_SRR1,(NEED_EMU | NEED_DEAR | NEED_ESR)
+kvm_handler BOOKE_INTERRUPT_INST_STORAGE, EX_PARAMS(GEN), \
+ SPRN_SRR0, SPRN_SRR1, NEED_ESR
+kvm_handler BOOKE_INTERRUPT_EXTERNAL, EX_PARAMS(GEN), \
+ SPRN_SRR0, SPRN_SRR1, 0
+kvm_handler BOOKE_INTERRUPT_ALIGNMENT, EX_PARAMS(GEN), \
+ SPRN_SRR0, SPRN_SRR1,(NEED_DEAR | NEED_ESR)
+kvm_handler BOOKE_INTERRUPT_PROGRAM, EX_PARAMS(GEN), \
+ SPRN_SRR0, SPRN_SRR1,NEED_ESR
+kvm_handler BOOKE_INTERRUPT_FP_UNAVAIL, EX_PARAMS(GEN), \
+ SPRN_SRR0, SPRN_SRR1, 0
+kvm_handler BOOKE_INTERRUPT_AP_UNAVAIL, EX_PARAMS(GEN), \
+ SPRN_SRR0, SPRN_SRR1, 0
+kvm_handler BOOKE_INTERRUPT_DECREMENTER, EX_PARAMS(GEN), \
+ SPRN_SRR0, SPRN_SRR1, 0
+kvm_handler BOOKE_INTERRUPT_FIT, EX_PARAMS(GEN), \
+ SPRN_SRR0, SPRN_SRR1, 0
+kvm_handler BOOKE_INTERRUPT_WATCHDOG, EX_PARAMS(CRIT),\
+ SPRN_CSRR0, SPRN_CSRR1, 0
+/*
+ * Only bolted TLB miss exception handlers are supported for now
+ */
+kvm_handler BOOKE_INTERRUPT_DTLB_MISS, EX_PARAMS(GEN), \
+ SPRN_SRR0, SPRN_SRR1, (NEED_EMU | NEED_DEAR | NEED_ESR)
+kvm_handler BOOKE_INTERRUPT_ITLB_MISS, EX_PARAMS(GEN), \
+ SPRN_SRR0, SPRN_SRR1, 0
+kvm_handler BOOKE_INTERRUPT_SPE_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), \
+ SPRN_SRR0, SPRN_SRR1, 0
+kvm_handler BOOKE_INTERRUPT_PERFORMANCE_MONITOR, EX_PARAMS(GEN), \
+ SPRN_SRR0, SPRN_SRR1, 0
+kvm_handler BOOKE_INTERRUPT_DOORBELL, EX_PARAMS(GEN), \
+ SPRN_SRR0, SPRN_SRR1, 0
+kvm_handler BOOKE_INTERRUPT_DOORBELL_CRITICAL, EX_PARAMS(CRIT), \
+ SPRN_CSRR0, SPRN_CSRR1, 0
+kvm_handler BOOKE_INTERRUPT_HV_PRIV, EX_PARAMS(GEN), \
+ SPRN_SRR0, SPRN_SRR1, NEED_EMU
+kvm_handler BOOKE_INTERRUPT_HV_SYSCALL, EX_PARAMS(GEN), \
+ SPRN_SRR0, SPRN_SRR1, 0
+kvm_handler BOOKE_INTERRUPT_GUEST_DBELL, EX_PARAMS(GEN), \
+ SPRN_GSRR0, SPRN_GSRR1, 0
+kvm_handler BOOKE_INTERRUPT_GUEST_DBELL_CRIT, EX_PARAMS(CRIT), \
+ SPRN_CSRR0, SPRN_CSRR1, 0
+kvm_handler BOOKE_INTERRUPT_DEBUG, EX_PARAMS(DBG), \
+ SPRN_DSRR0, SPRN_DSRR1, 0
+kvm_handler BOOKE_INTERRUPT_DEBUG, EX_PARAMS(CRIT), \
+ SPRN_CSRR0, SPRN_CSRR1, 0
+#else
/*
* For input register values, see arch/powerpc/include/asm/kvm_booke_hv_asm.h
*/
@@ -296,7 +398,7 @@ kvm_lvl_handler BOOKE_INTERRUPT_DEBUG, \
SPRN_SPRG_RSCRATCH_CRIT, SPRN_CSRR0, SPRN_CSRR1, 0
kvm_lvl_handler BOOKE_INTERRUPT_DEBUG, \
SPRN_SPRG_RSCRATCH_DBG, SPRN_DSRR0, SPRN_DSRR1, 0
-
+#endif
/* Registers:
* SPRG_SCRATCH0: guest r10
--
1.7.4.1
^ permalink raw reply related
* [RFC PATCH 01/17] KVM: PPC64: booke: Set interrupt computation mode for 64-bit host
From: Mihai Caraman @ 2012-06-25 12:26 UTC (permalink / raw)
To: kvm-ppc, kvm, linuxppc-dev, qemu-ppc; +Cc: Mihai Caraman
In-Reply-To: <1340627195-11544-1-git-send-email-mihai.caraman@freescale.com>
64-bit host needs to remain in 64-bit mode when an exception take place.
Set interrupt computaion mode in EPCR register.
Signed-off-by: Mihai Caraman <mihai.caraman@freescale.com>
---
arch/powerpc/kvm/e500mc.c | 5 ++++-
1 files changed, 4 insertions(+), 1 deletions(-)
diff --git a/arch/powerpc/kvm/e500mc.c b/arch/powerpc/kvm/e500mc.c
index fe6c1de..db97ee3 100644
--- a/arch/powerpc/kvm/e500mc.c
+++ b/arch/powerpc/kvm/e500mc.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 Freescale Semiconductor, Inc. All rights reserved.
+ * Copyright (C) 2010,2012 Freescale Semiconductor, Inc. All rights reserved.
*
* Author: Varun Sethi, <varun.sethi@freescale.com>
*
@@ -183,6 +183,9 @@ int kvmppc_core_vcpu_setup(struct kvm_vcpu *vcpu)
vcpu->arch.shadow_epcr = SPRN_EPCR_DSIGS | SPRN_EPCR_DGTMI | \
SPRN_EPCR_DUVD;
+#ifdef CONFIG_64BIT
+ vcpu->arch.shadow_epcr |= SPRN_EPCR_ICM;
+#endif
vcpu->arch.shadow_msrp = MSRP_UCLEP | MSRP_DEP | MSRP_PMMP;
vcpu->arch.eplc = EPC_EGS | (vcpu->kvm->arch.lpid << EPC_ELPID_SHIFT);
vcpu->arch.epsc = vcpu->arch.eplc;
--
1.7.4.1
^ permalink raw reply related
* [RFC PATCH 11/17] PowerPC: booke64: Fix machine check handler to use the right prolog
From: Mihai Caraman @ 2012-06-25 12:26 UTC (permalink / raw)
To: kvm-ppc, kvm, linuxppc-dev, qemu-ppc; +Cc: Mihai Caraman
In-Reply-To: <1340627195-11544-1-git-send-email-mihai.caraman@freescale.com>
Machine check exception handler was using a wrong prolog. Hypervisors, like
KVM, which are called early from the exception handler rely on the interrupt
source.
Signed-off-by: Mihai Caraman <mihai.caraman@freescale.com>
---
arch/powerpc/kernel/exceptions-64e.S | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/arch/powerpc/kernel/exceptions-64e.S b/arch/powerpc/kernel/exceptions-64e.S
index 52aa96b..06f7aec 100644
--- a/arch/powerpc/kernel/exceptions-64e.S
+++ b/arch/powerpc/kernel/exceptions-64e.S
@@ -290,7 +290,7 @@ interrupt_end_book3e:
/* Machine Check Interrupt */
START_EXCEPTION(machine_check);
- CRIT_EXCEPTION_PROLOG(0x200, PROLOG_ADDITION_NONE)
+ MC_EXCEPTION_PROLOG(0x200, PROLOG_ADDITION_NONE)
// EXCEPTION_COMMON(0x200, PACA_EXMC, INTS_DISABLE)
// bl special_reg_save_mc
// addi r3,r1,STACK_FRAME_OVERHEAD
--
1.7.4.1
^ permalink raw reply related
* [RFC PATCH 08/17] KVM: PPC: e500mc: Fix tlbilx emulation for 64-bit guests
From: Mihai Caraman @ 2012-06-25 12:26 UTC (permalink / raw)
To: kvm-ppc, kvm, linuxppc-dev, qemu-ppc; +Cc: Mihai Caraman
In-Reply-To: <1340627195-11544-1-git-send-email-mihai.caraman@freescale.com>
tlbilxva emulation was using an u32 variable for guest effective address.
Replace it with gva_t type to handle 64-bit guests.
Signed-off-by: Mihai Caraman <mihai.caraman@freescale.com>
---
arch/powerpc/kvm/e500mc.c | 3 ++-
1 files changed, 2 insertions(+), 1 deletions(-)
diff --git a/arch/powerpc/kvm/e500mc.c b/arch/powerpc/kvm/e500mc.c
index db97ee3..1f89d26 100644
--- a/arch/powerpc/kvm/e500mc.c
+++ b/arch/powerpc/kvm/e500mc.c
@@ -57,7 +57,8 @@ void kvmppc_e500_tlbil_one(struct kvmppc_vcpu_e500 *vcpu_e500,
struct kvm_book3e_206_tlb_entry *gtlbe)
{
unsigned int tid, ts;
- u32 val, eaddr, lpid;
+ gva_t eaddr;
+ u32 val, lpid;
unsigned long flags;
ts = get_tlb_ts(gtlbe);
--
1.7.4.1
^ permalink raw reply related
* Re: [RFC PATCH 03/17] KVM: PPC64: booke: Add EPCR support in sregs
From: Avi Kivity @ 2012-06-25 12:59 UTC (permalink / raw)
To: Mihai Caraman; +Cc: qemu-ppc, linuxppc-dev, kvm, kvm-ppc
In-Reply-To: <1340627195-11544-4-git-send-email-mihai.caraman@freescale.com>
On 06/25/2012 03:26 PM, Mihai Caraman wrote:
> Add KVM_SREGS_E_64 feature and EPCR spr support in get/set sregs
> for 64-bit hosts.
>
> Signed-off-by: Mihai Caraman <mihai.caraman@freescale.com>
> ---
> arch/powerpc/kvm/booke.c | 14 ++++++++++++++
> 1 files changed, 14 insertions(+), 0 deletions(-)
>
> diff --git a/arch/powerpc/kvm/booke.c b/arch/powerpc/kvm/booke.c
> index f9fa260..d15c4b5 100644
> --- a/arch/powerpc/kvm/booke.c
> +++ b/arch/powerpc/kvm/booke.c
> @@ -1052,6 +1052,9 @@ static void get_sregs_base(struct kvm_vcpu *vcpu,
> u64 tb = get_tb();
>
> sregs->u.e.features |= KVM_SREGS_E_BASE;
> +#ifdef CONFIG_64BIT
> + sregs->u.e.features |= KVM_SREGS_E_64;
> +#endif
>
This is an ABI, but I see no trace of it in Documentation.
--
error compiling committee.c: too many arguments to function
^ permalink raw reply
* RE: [RFC PATCH 03/17] KVM: PPC64: booke: Add EPCR support in sregs
From: Caraman Mihai Claudiu-B02008 @ 2012-06-25 13:24 UTC (permalink / raw)
To: Avi Kivity
Cc: qemu-ppc@nongnu.org, linuxppc-dev@lists.ozlabs.org,
kvm@vger.kernel.org, kvm-ppc@vger.kernel.org
In-Reply-To: <4FE860CC.6080903@redhat.com>
> -----Original Message-----
> From: Avi Kivity [mailto:avi@redhat.com]
> Sent: Monday, June 25, 2012 4:00 PM
> To: Caraman Mihai Claudiu-B02008
> Cc: kvm-ppc@vger.kernel.org; kvm@vger.kernel.org; linuxppc-
> dev@lists.ozlabs.org; qemu-ppc@nongnu.org
> Subject: Re: [RFC PATCH 03/17] KVM: PPC64: booke: Add EPCR support in
> sregs
>=20
> On 06/25/2012 03:26 PM, Mihai Caraman wrote:
> > Add KVM_SREGS_E_64 feature and EPCR spr support in get/set sregs for
> > 64-bit hosts.
> >
> > Signed-off-by: Mihai Caraman <mihai.caraman@freescale.com>
> > ---
> > arch/powerpc/kvm/booke.c | 14 ++++++++++++++
> > 1 files changed, 14 insertions(+), 0 deletions(-)
> >
> > diff --git a/arch/powerpc/kvm/booke.c b/arch/powerpc/kvm/booke.c index
> > f9fa260..d15c4b5 100644
> > --- a/arch/powerpc/kvm/booke.c
> > +++ b/arch/powerpc/kvm/booke.c
> > @@ -1052,6 +1052,9 @@ static void get_sregs_base(struct kvm_vcpu *vcpu,
> > u64 tb =3D get_tb();
> >
> > sregs->u.e.features |=3D KVM_SREGS_E_BASE;
> > +#ifdef CONFIG_64BIT
> > + sregs->u.e.features |=3D KVM_SREGS_E_64; #endif
> >
>=20
> This is an ABI, but I see no trace of it in Documentation.
The ppc sregs documentation in api.txt redirects to arch/powerpc/include/as=
m/kvm.h.
Isn't this enough?
Mike
^ permalink raw reply
* Re: [RFC PATCH 03/17] KVM: PPC64: booke: Add EPCR support in sregs
From: Avi Kivity @ 2012-06-25 13:36 UTC (permalink / raw)
To: Caraman Mihai Claudiu-B02008
Cc: qemu-ppc@nongnu.org, linuxppc-dev@lists.ozlabs.org,
kvm@vger.kernel.org, kvm-ppc@vger.kernel.org
In-Reply-To: <300B73AA675FCE4A93EB4FC1D42459FF14F93A@039-SN2MPN1-013.039d.mgd.msft.net>
On 06/25/2012 04:24 PM, Caraman Mihai Claudiu-B02008 wrote:
>> -----Original Message-----
>> From: Avi Kivity [mailto:avi@redhat.com]
>> Sent: Monday, June 25, 2012 4:00 PM
>> To: Caraman Mihai Claudiu-B02008
>> Cc: kvm-ppc@vger.kernel.org; kvm@vger.kernel.org; linuxppc-
>> dev@lists.ozlabs.org; qemu-ppc@nongnu.org
>> Subject: Re: [RFC PATCH 03/17] KVM: PPC64: booke: Add EPCR support in
>> sregs
>>
>> On 06/25/2012 03:26 PM, Mihai Caraman wrote:
>> > Add KVM_SREGS_E_64 feature and EPCR spr support in get/set sregs for
>> > 64-bit hosts.
>> >
>> > Signed-off-by: Mihai Caraman <mihai.caraman@freescale.com>
>> > ---
>> > arch/powerpc/kvm/booke.c | 14 ++++++++++++++
>> > 1 files changed, 14 insertions(+), 0 deletions(-)
>> >
>> > diff --git a/arch/powerpc/kvm/booke.c b/arch/powerpc/kvm/booke.c index
>> > f9fa260..d15c4b5 100644
>> > --- a/arch/powerpc/kvm/booke.c
>> > +++ b/arch/powerpc/kvm/booke.c
>> > @@ -1052,6 +1052,9 @@ static void get_sregs_base(struct kvm_vcpu *vcpu,
>> > u64 tb = get_tb();
>> >
>> > sregs->u.e.features |= KVM_SREGS_E_BASE;
>> > +#ifdef CONFIG_64BIT
>> > + sregs->u.e.features |= KVM_SREGS_E_64; #endif
>> >
>>
>> This is an ABI, but I see no trace of it in Documentation.
>
> The ppc sregs documentation in api.txt redirects to arch/powerpc/include/asm/kvm.h.
> Isn't this enough?
I guess it's okay.
--
error compiling committee.c: too many arguments to function
^ permalink raw reply
* [PATCH 4/8] ppc/pnv: initialize DMA for PEs
From: Gavin Shan @ 2012-06-25 15:43 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Gavin Shan
In-Reply-To: <1340639001-28152-1-git-send-email-shangw@linux.vnet.ibm.com>
The patch introduces additional wrapper function to call the original
implementation so that the DMA can be configured for all existing PEs.
Signed-off-by: Gavin Shan <shangw@linux.vnet.ibm.com>
Reviewed-by: Ram Pai <linuxram@us.ibm.com>
Reviewed-by: Richard Yang <weiyang@linux.vnet.ibm.com>
---
arch/powerpc/platforms/powernv/pci-ioda.c | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/arch/powerpc/platforms/powernv/pci-ioda.c b/arch/powerpc/platforms/powernv/pci-ioda.c
index 1071820..f0ae647 100644
--- a/arch/powerpc/platforms/powernv/pci-ioda.c
+++ b/arch/powerpc/platforms/powernv/pci-ioda.c
@@ -1243,10 +1243,20 @@ static void __devinit pnv_pci_ioda_setup_seg(void)
}
}
+static void __devinit pnv_pci_ioda_setup_DMA(void)
+{
+ struct pci_controller *hose, *tmp;
+
+ list_for_each_entry_safe(hose, tmp, &hose_list, list_node) {
+ pnv_ioda_setup_dma(hose->private_data);
+ }
+}
+
static void __devinit pnv_pci_ioda_fixup(void)
{
pnv_pci_ioda_setup_PEs();
pnv_pci_ioda_setup_seg();
+ pnv_pci_ioda_setup_DMA();
}
/* Prevent enabling devices for which we couldn't properly
--
1.7.9.5
^ permalink raw reply related
* [PATCH 8/8] ppc/pnv: remove unused functions
From: Gavin Shan @ 2012-06-25 15:43 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Gavin Shan
In-Reply-To: <1340639001-28152-1-git-send-email-shangw@linux.vnet.ibm.com>
We don't need them anymore. The patch removes those functions.
Signed-off-by: Gavin Shan <shangw@linux.vnet.ibm.com>
Reviewed-by: Ram Pai <linuxram@us.ibm.com>
Reviewed-by: Richard Yang <weiyang@linux.vnet.ibm.com>
---
arch/powerpc/platforms/powernv/pci-ioda.c | 441 -----------------------------
1 file changed, 441 deletions(-)
diff --git a/arch/powerpc/platforms/powernv/pci-ioda.c b/arch/powerpc/platforms/powernv/pci-ioda.c
index 1368804..a40071f 100644
--- a/arch/powerpc/platforms/powernv/pci-ioda.c
+++ b/arch/powerpc/platforms/powernv/pci-ioda.c
@@ -35,14 +35,6 @@
#include "powernv.h"
#include "pci.h"
-struct resource_wrap {
- struct list_head link;
- resource_size_t size;
- resource_size_t align;
- struct pci_dev *dev; /* Set if it's a device */
- struct pci_bus *bus; /* Set if it's a bridge */
-};
-
static int __pe_printk(const char *level, const struct pnv_ioda_pe *pe,
struct va_format *vaf)
{
@@ -78,273 +70,6 @@ define_pe_printk_level(pe_err, KERN_ERR);
define_pe_printk_level(pe_warn, KERN_WARNING);
define_pe_printk_level(pe_info, KERN_INFO);
-
-/* Calculate resource usage & alignment requirement of a single
- * device. This will also assign all resources within the device
- * for a given type starting at 0 for the biggest one and then
- * assigning in decreasing order of size.
- */
-static void __devinit pnv_ioda_calc_dev(struct pci_dev *dev, unsigned int flags,
- resource_size_t *size,
- resource_size_t *align)
-{
- resource_size_t start;
- struct resource *r;
- int i;
-
- pr_devel(" -> CDR %s\n", pci_name(dev));
-
- *size = *align = 0;
-
- /* Clear the resources out and mark them all unset */
- for (i = 0; i <= PCI_ROM_RESOURCE; i++) {
- r = &dev->resource[i];
- if (!(r->flags & flags))
- continue;
- if (r->start) {
- r->end -= r->start;
- r->start = 0;
- }
- r->flags |= IORESOURCE_UNSET;
- }
-
- /* We currently keep all memory resources together, we
- * will handle prefetch & 64-bit separately in the future
- * but for now we stick everybody in M32
- */
- start = 0;
- for (;;) {
- resource_size_t max_size = 0;
- int max_no = -1;
-
- /* Find next biggest resource */
- for (i = 0; i <= PCI_ROM_RESOURCE; i++) {
- r = &dev->resource[i];
- if (!(r->flags & IORESOURCE_UNSET) ||
- !(r->flags & flags))
- continue;
- if (resource_size(r) > max_size) {
- max_size = resource_size(r);
- max_no = i;
- }
- }
- if (max_no < 0)
- break;
- r = &dev->resource[max_no];
- if (max_size > *align)
- *align = max_size;
- *size += max_size;
- r->start = start;
- start += max_size;
- r->end = r->start + max_size - 1;
- r->flags &= ~IORESOURCE_UNSET;
- pr_devel(" -> R%d %016llx..%016llx\n",
- max_no, r->start, r->end);
- }
- pr_devel(" <- CDR %s size=%llx align=%llx\n",
- pci_name(dev), *size, *align);
-}
-
-/* Allocate a resource "wrap" for a given device or bridge and
- * insert it at the right position in the sorted list
- */
-static void __devinit pnv_ioda_add_wrap(struct list_head *list,
- struct pci_bus *bus,
- struct pci_dev *dev,
- resource_size_t size,
- resource_size_t align)
-{
- struct resource_wrap *w1, *w = kzalloc(sizeof(*w), GFP_KERNEL);
-
- w->size = size;
- w->align = align;
- w->dev = dev;
- w->bus = bus;
-
- list_for_each_entry(w1, list, link) {
- if (w1->align < align) {
- list_add_tail(&w->link, &w1->link);
- return;
- }
- }
- list_add_tail(&w->link, list);
-}
-
-/* Offset device resources of a given type */
-static void __devinit pnv_ioda_offset_dev(struct pci_dev *dev,
- unsigned int flags,
- resource_size_t offset)
-{
- struct resource *r;
- int i;
-
- pr_devel(" -> ODR %s [%x] +%016llx\n", pci_name(dev), flags, offset);
-
- for (i = 0; i <= PCI_ROM_RESOURCE; i++) {
- r = &dev->resource[i];
- if (r->flags & flags) {
- dev->resource[i].start += offset;
- dev->resource[i].end += offset;
- }
- }
-
- pr_devel(" <- ODR %s [%x] +%016llx\n", pci_name(dev), flags, offset);
-}
-
-/* Offset bus resources (& all children) of a given type */
-static void __devinit pnv_ioda_offset_bus(struct pci_bus *bus,
- unsigned int flags,
- resource_size_t offset)
-{
- struct resource *r;
- struct pci_dev *dev;
- struct pci_bus *cbus;
- int i;
-
- pr_devel(" -> OBR %s [%x] +%016llx\n",
- bus->self ? pci_name(bus->self) : "root", flags, offset);
-
- pci_bus_for_each_resource(bus, r, i) {
- if (r && (r->flags & flags)) {
- r->start += offset;
- r->end += offset;
- }
- }
- list_for_each_entry(dev, &bus->devices, bus_list)
- pnv_ioda_offset_dev(dev, flags, offset);
- list_for_each_entry(cbus, &bus->children, node)
- pnv_ioda_offset_bus(cbus, flags, offset);
-
- pr_devel(" <- OBR %s [%x]\n",
- bus->self ? pci_name(bus->self) : "root", flags);
-}
-
-/* This is the guts of our IODA resource allocation. This is called
- * recursively for each bus in the system. It calculates all the
- * necessary size and requirements for children and assign them
- * resources such that:
- *
- * - Each function fits in it's own contiguous set of IO/M32
- * segment
- *
- * - All segments behind a P2P bridge are contiguous and obey
- * alignment constraints of those bridges
- */
-static void __devinit pnv_ioda_calc_bus(struct pci_bus *bus, unsigned int flags,
- resource_size_t *size,
- resource_size_t *align)
-{
- struct pci_controller *hose = pci_bus_to_host(bus);
- struct pnv_phb *phb = hose->private_data;
- resource_size_t dev_size, dev_align, start;
- resource_size_t min_align, min_balign;
- struct pci_dev *cdev;
- struct pci_bus *cbus;
- struct list_head head;
- struct resource_wrap *w;
- unsigned int bres;
-
- *size = *align = 0;
-
- pr_devel("-> CBR %s [%x]\n",
- bus->self ? pci_name(bus->self) : "root", flags);
-
- /* Calculate alignment requirements based on the type
- * of resource we are working on
- */
- if (flags & IORESOURCE_IO) {
- bres = 0;
- min_align = phb->ioda.io_segsize;
- min_balign = 0x1000;
- } else {
- bres = 1;
- min_align = phb->ioda.m32_segsize;
- min_balign = 0x100000;
- }
-
- /* Gather all our children resources ordered by alignment */
- INIT_LIST_HEAD(&head);
-
- /* - Busses */
- list_for_each_entry(cbus, &bus->children, node) {
- pnv_ioda_calc_bus(cbus, flags, &dev_size, &dev_align);
- pnv_ioda_add_wrap(&head, cbus, NULL, dev_size, dev_align);
- }
-
- /* - Devices */
- list_for_each_entry(cdev, &bus->devices, bus_list) {
- pnv_ioda_calc_dev(cdev, flags, &dev_size, &dev_align);
- /* Align them to segment size */
- if (dev_align < min_align)
- dev_align = min_align;
- pnv_ioda_add_wrap(&head, NULL, cdev, dev_size, dev_align);
- }
- if (list_empty(&head))
- goto empty;
-
- /* Now we can do two things: assign offsets to them within that
- * level and get our total alignment & size requirements. The
- * assignment algorithm is going to be uber-trivial for now, we
- * can try to be smarter later at filling out holes.
- */
- if (bus->self) {
- /* No offset for downstream bridges */
- start = 0;
- } else {
- /* Offset from the root */
- if (flags & IORESOURCE_IO)
- /* Don't hand out IO 0 */
- start = hose->io_resource.start + 0x1000;
- else
- start = hose->mem_resources[0].start;
- }
- while(!list_empty(&head)) {
- w = list_first_entry(&head, struct resource_wrap, link);
- list_del(&w->link);
- if (w->size) {
- if (start) {
- start = ALIGN(start, w->align);
- if (w->dev)
- pnv_ioda_offset_dev(w->dev,flags,start);
- else if (w->bus)
- pnv_ioda_offset_bus(w->bus,flags,start);
- }
- if (w->align > *align)
- *align = w->align;
- }
- start += w->size;
- kfree(w);
- }
- *size = start;
-
- /* Align and setup bridge resources */
- *align = max_t(resource_size_t, *align,
- max_t(resource_size_t, min_align, min_balign));
- *size = ALIGN(*size,
- max_t(resource_size_t, min_align, min_balign));
- empty:
- /* Only setup P2P's, not the PHB itself */
- if (bus->self) {
- struct resource *res = bus->resource[bres];
-
- if (WARN_ON(res == NULL))
- return;
-
- /*
- * FIXME: We should probably export and call
- * pci_bridge_check_ranges() to properly re-initialize
- * the PCI portion of the flags here, and to detect
- * what the bridge actually supports.
- */
- res->start = 0;
- res->flags = (*size) ? flags : 0;
- res->end = (*size) ? (*size - 1) : 0;
- }
-
- pr_devel("<- CBR %s [%x] *size=%016llx *align=%016llx\n",
- bus->self ? pci_name(bus->self) : "root", flags,*size,*align);
-}
-
static struct pci_dn *pnv_ioda_get_pdn(struct pci_dev *dev)
{
struct device_node *np;
@@ -355,172 +80,6 @@ static struct pci_dn *pnv_ioda_get_pdn(struct pci_dev *dev)
return PCI_DN(np);
}
-static void __devinit pnv_ioda_setup_pe_segments(struct pci_dev *dev)
-{
- struct pci_controller *hose = pci_bus_to_host(dev->bus);
- struct pnv_phb *phb = hose->private_data;
- struct pci_dn *pdn = pnv_ioda_get_pdn(dev);
- unsigned int pe, i;
- resource_size_t pos;
- struct resource io_res;
- struct resource m32_res;
- struct pci_bus_region region;
- int rc;
-
- /* Anything not referenced in the device-tree gets PE#0 */
- pe = pdn ? pdn->pe_number : 0;
-
- /* Calculate the device min/max */
- io_res.start = m32_res.start = (resource_size_t)-1;
- io_res.end = m32_res.end = 0;
- io_res.flags = IORESOURCE_IO;
- m32_res.flags = IORESOURCE_MEM;
-
- for (i = 0; i <= PCI_ROM_RESOURCE; i++) {
- struct resource *r = NULL;
- if (dev->resource[i].flags & IORESOURCE_IO)
- r = &io_res;
- if (dev->resource[i].flags & IORESOURCE_MEM)
- r = &m32_res;
- if (!r)
- continue;
- if (dev->resource[i].start < r->start)
- r->start = dev->resource[i].start;
- if (dev->resource[i].end > r->end)
- r->end = dev->resource[i].end;
- }
-
- /* Setup IO segments */
- if (io_res.start < io_res.end) {
- pcibios_resource_to_bus(dev, ®ion, &io_res);
- pos = region.start;
- i = pos / phb->ioda.io_segsize;
- while(i < phb->ioda.total_pe && pos <= region.end) {
- if (phb->ioda.io_segmap[i]) {
- pr_err("%s: Trying to use IO seg #%d which is"
- " already used by PE# %d\n",
- pci_name(dev), i,
- phb->ioda.io_segmap[i]);
- /* XXX DO SOMETHING TO DISABLE DEVICE ? */
- break;
- }
- phb->ioda.io_segmap[i] = pe;
- rc = opal_pci_map_pe_mmio_window(phb->opal_id, pe,
- OPAL_IO_WINDOW_TYPE,
- 0, i);
- if (rc != OPAL_SUCCESS) {
- pr_err("%s: OPAL error %d setting up mapping"
- " for IO seg# %d\n",
- pci_name(dev), rc, i);
- /* XXX DO SOMETHING TO DISABLE DEVICE ? */
- break;
- }
- pos += phb->ioda.io_segsize;
- i++;
- };
- }
-
- /* Setup M32 segments */
- if (m32_res.start < m32_res.end) {
- pcibios_resource_to_bus(dev, ®ion, &m32_res);
- pos = region.start;
- i = pos / phb->ioda.m32_segsize;
- while(i < phb->ioda.total_pe && pos <= region.end) {
- if (phb->ioda.m32_segmap[i]) {
- pr_err("%s: Trying to use M32 seg #%d which is"
- " already used by PE# %d\n",
- pci_name(dev), i,
- phb->ioda.m32_segmap[i]);
- /* XXX DO SOMETHING TO DISABLE DEVICE ? */
- break;
- }
- phb->ioda.m32_segmap[i] = pe;
- rc = opal_pci_map_pe_mmio_window(phb->opal_id, pe,
- OPAL_M32_WINDOW_TYPE,
- 0, i);
- if (rc != OPAL_SUCCESS) {
- pr_err("%s: OPAL error %d setting up mapping"
- " for M32 seg# %d\n",
- pci_name(dev), rc, i);
- /* XXX DO SOMETHING TO DISABLE DEVICE ? */
- break;
- }
- pos += phb->ioda.m32_segsize;
- i++;
- }
- }
-}
-
-/* Check if a resource still fits in the total IO or M32 range
- * for a given PHB
- */
-static int __devinit pnv_ioda_resource_fit(struct pci_controller *hose,
- struct resource *r)
-{
- struct resource *bounds;
-
- if (r->flags & IORESOURCE_IO)
- bounds = &hose->io_resource;
- else if (r->flags & IORESOURCE_MEM)
- bounds = &hose->mem_resources[0];
- else
- return 1;
-
- if (r->start >= bounds->start && r->end <= bounds->end)
- return 1;
- r->flags = 0;
- return 0;
-}
-
-static void __devinit pnv_ioda_update_resources(struct pci_bus *bus)
-{
- struct pci_controller *hose = pci_bus_to_host(bus);
- struct pci_bus *cbus;
- struct pci_dev *cdev;
- unsigned int i;
-
- /* We used to clear all device enables here. However it looks like
- * clearing MEM enable causes Obsidian (IPR SCS) to go bonkers,
- * and shoot fatal errors to the PHB which in turns fences itself
- * and we can't recover from that ... yet. So for now, let's leave
- * the enables as-is and hope for the best.
- */
-
- /* Check if bus resources fit in our IO or M32 range */
- for (i = 0; bus->self && (i < 2); i++) {
- struct resource *r = bus->resource[i];
- if (r && !pnv_ioda_resource_fit(hose, r))
- pr_err("%s: Bus %d resource %d disabled, no room\n",
- pci_name(bus->self), bus->number, i);
- }
-
- /* Update self if it's not a PHB */
- if (bus->self)
- pci_setup_bridge(bus);
-
- /* Update child devices */
- list_for_each_entry(cdev, &bus->devices, bus_list) {
- /* Check if resource fits, if not, disabled it */
- for (i = 0; i <= PCI_ROM_RESOURCE; i++) {
- struct resource *r = &cdev->resource[i];
- if (!pnv_ioda_resource_fit(hose, r))
- pr_err("%s: Resource %d disabled, no room\n",
- pci_name(cdev), i);
- }
-
- /* Assign segments */
- pnv_ioda_setup_pe_segments(cdev);
-
- /* Update HW BARs */
- for (i = 0; i <= PCI_ROM_RESOURCE; i++)
- pci_update_resource(cdev, i);
- }
-
- /* Update child busses */
- list_for_each_entry(cbus, &bus->children, node)
- pnv_ioda_update_resources(cbus);
-}
-
static int __devinit pnv_ioda_alloc_pe(struct pnv_phb *phb)
{
unsigned long pe;
--
1.7.9.5
^ permalink raw reply related
* [PATCH 6/8] ppc/pnv: fix overrunning segment tracing array
From: Gavin Shan @ 2012-06-25 15:43 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Gavin Shan
In-Reply-To: <1340639001-28152-1-git-send-email-shangw@linux.vnet.ibm.com>
There're 2 arrays introduced to trace which PE has occupied the
corresponding resource (I/O or MMIO) segment. However, we didn't
allocate enough memory for them and that possiblly leads to PE
descriptor corruption.
The patch fixes that by allocating enough memory for those 2 arrays.
Signed-off-by: Gavin Shan <shangw@linux.vnet.ibm.com>
---
arch/powerpc/platforms/powernv/pci-ioda.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/arch/powerpc/platforms/powernv/pci-ioda.c b/arch/powerpc/platforms/powernv/pci-ioda.c
index 052a50f..ed8cf09 100644
--- a/arch/powerpc/platforms/powernv/pci-ioda.c
+++ b/arch/powerpc/platforms/powernv/pci-ioda.c
@@ -1375,9 +1375,9 @@ void __init pnv_pci_init_ioda1_phb(struct device_node *np)
/* Allocate aux data & arrays */
size = _ALIGN_UP(phb->ioda.total_pe / 8, sizeof(unsigned long));
m32map_off = size;
- size += phb->ioda.total_pe;
+ size += phb->ioda.total_pe * sizeof(phb->ioda.m32_segmap[0]);
iomap_off = size;
- size += phb->ioda.total_pe;
+ size += phb->ioda.total_pe * sizeof(phb->ioda.io_segmap[0]);
pemap_off = size;
size += phb->ioda.total_pe * sizeof(struct pnv_ioda_pe);
aux = alloc_bootmem(size);
--
1.7.9.5
^ permalink raw reply related
* [PATCH 2/8] ppc/pnv: PE list based on creation order
From: Gavin Shan @ 2012-06-25 15:43 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Gavin Shan
In-Reply-To: <1340639001-28152-1-git-send-email-shangw@linux.vnet.ibm.com>
The resource (I/O and MMIO) will be assigned on basis of PE from
top to bottom so that we can implement the trick here: the resource
that has been assigned to parent PE could be taken by child PE if
necessary.
The current implementation already has PE list per PHB basis, but
the list doesn't meet our requirment: tracing PE based on their
cration time from top to bottom. So the patch does rename for the
DMA based PE list and introduces the list to trace the PEs sequentially
based on their creation time.
Signed-off-by: Gavin Shan <shangw@linux.vnet.ibm.com>
---
arch/powerpc/platforms/powernv/pci-ioda.c | 12 ++++++++----
arch/powerpc/platforms/powernv/pci.h | 10 ++++++++--
2 files changed, 16 insertions(+), 6 deletions(-)
diff --git a/arch/powerpc/platforms/powernv/pci-ioda.c b/arch/powerpc/platforms/powernv/pci-ioda.c
index 1504795..6a7672e 100644
--- a/arch/powerpc/platforms/powernv/pci-ioda.c
+++ b/arch/powerpc/platforms/powernv/pci-ioda.c
@@ -657,13 +657,13 @@ static void __devinit pnv_ioda_link_pe_by_weight(struct pnv_phb *phb,
{
struct pnv_ioda_pe *lpe;
- list_for_each_entry(lpe, &phb->ioda.pe_list, link) {
+ list_for_each_entry(lpe, &phb->ioda.pe_dma_list, dma_link) {
if (lpe->dma_weight < pe->dma_weight) {
- list_add_tail(&pe->link, &lpe->link);
+ list_add_tail(&pe->dma_link, &lpe->dma_link);
return;
}
}
- list_add_tail(&pe->link, &phb->ioda.pe_list);
+ list_add_tail(&pe->dma_link, &phb->ioda.pe_dma_list);
}
static unsigned int pnv_ioda_dma_weight(struct pci_dev *dev)
@@ -830,6 +830,9 @@ static void __devinit pnv_ioda_setup_bus_PE(struct pci_bus *bus, int all)
/* Associate it with all child devices */
pnv_ioda_setup_same_PE(bus, pe);
+ /* Put PE to the list */
+ list_add_tail(&pe->list, &phb->ioda.pe_list);
+
/* Account for one DMA PE if at least one DMA capable device exist
* below the bridge
*/
@@ -1013,7 +1016,7 @@ static void __devinit pnv_ioda_setup_dma(struct pnv_phb *phb)
remaining = phb->ioda.tce32_count;
tw = phb->ioda.dma_weight;
base = 0;
- list_for_each_entry(pe, &phb->ioda.pe_list, link) {
+ list_for_each_entry(pe, &phb->ioda.pe_dma_list, dma_link) {
if (!pe->dma_weight)
continue;
if (!remaining) {
@@ -1269,6 +1272,7 @@ void __init pnv_pci_init_ioda1_phb(struct device_node *np)
phb->ioda.pe_array = aux + pemap_off;
set_bit(0, phb->ioda.pe_alloc);
+ INIT_LIST_HEAD(&phb->ioda.pe_dma_list);
INIT_LIST_HEAD(&phb->ioda.pe_list);
/* Calculate how many 32-bit TCE segments we have */
diff --git a/arch/powerpc/platforms/powernv/pci.h b/arch/powerpc/platforms/powernv/pci.h
index 0cb760c..b70720b 100644
--- a/arch/powerpc/platforms/powernv/pci.h
+++ b/arch/powerpc/platforms/powernv/pci.h
@@ -59,7 +59,8 @@ struct pnv_ioda_pe {
int mve_number;
/* Link in list of PE#s */
- struct list_head link;
+ struct list_head dma_link;
+ struct list_head list;
};
struct pnv_phb {
@@ -107,6 +108,11 @@ struct pnv_phb {
unsigned int *io_segmap;
struct pnv_ioda_pe *pe_array;
+ /* Sorted list of used PE's based
+ * on the sequence of creation
+ */
+ struct list_head pe_list;
+
/* Reverse map of PEs, will have to extend if
* we are to support more than 256 PEs, indexed
* bus { bus, devfn }
@@ -125,7 +131,7 @@ struct pnv_phb {
/* Sorted list of used PE's, sorted at
* boot for resource allocation purposes
*/
- struct list_head pe_list;
+ struct list_head pe_dma_list;
} ioda;
};
--
1.7.9.5
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox