LinuxPPC-Dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [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 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 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 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 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 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 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 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 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 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

* Re: [PATCH SLUB 1/2] duplicate the cache name in saved_alias list
From: Glauber Costa @ 2012-06-25 11:10 UTC (permalink / raw)
  To: Li Zhong
  Cc: Christoph Lameter, LKML, Pekka Enberg, linux-mm, Paul Mackerras,
	Matt Mackall, PowerPC email list
In-Reply-To: <1340617984.13778.37.camel@ThinkPad-T420>

On 06/25/2012 01:53 PM, Li Zhong wrote:
> SLUB duplicates the cache name in kmem_cache_create(). However if the
> cache could be merged to others during early booting, the name pointer
> is saved in saved_alias list, and the string needs to be kept valid
> before slab_sysfs_init() is called.
>
> This patch tries to duplicate the cache name in saved_alias list, so
> that the cache name could be safely kfreed after calling
> kmem_cache_create(), if that name is kmalloced.
>
> Signed-off-by: Li Zhong <zhong@linux.vnet.ibm.com>
> ---
>   mm/slub.c |    6 ++++++
>   1 files changed, 6 insertions(+), 0 deletions(-)
>
> diff --git a/mm/slub.c b/mm/slub.c
> index 8c691fa..3dc8ed5 100644
> --- a/mm/slub.c
> +++ b/mm/slub.c
> @@ -5373,6 +5373,11 @@ static int sysfs_slab_alias(struct kmem_cache *s,
> const char *name)
>
>   	al->s = s;
>   	al->name = name;
> +	al->name = kstrdup(name, GFP_KERNEL);
> +	if (!al->name) {
> +		kfree(al);
> +		return -ENOMEM;
> +	}
>   	al->next = alias_list;
>   	alias_list = al;
>   	return 0;
> @@ -5409,6 +5414,7 @@ static int __init slab_sysfs_init(void)
>   		if (err)
>   			printk(KERN_ERR "SLUB: Unable to add boot slab alias"
>   					" %s to sysfs\n", s->name);
> +		kfree(al->name);
>   		kfree(al);
>   	}
>
>

What's unsafe about the current state of affairs ?
Whenever we alias, we'll increase the reference counter.
kmem_cache_destroy will only actually destroy the structure whenever 
that refcnt reaches zero.

This means that kfree shouldn't happen until then. So what is exactly 
that you are seeing?

Now, if you ask me, keeping the name around in user-visible files like 
/proc/slabinfo for caches that are removed already can be a bit 
confusing (that is because we don't add aliases to the slab_cache list)

If you want to touch this, one thing you can do is to keep a list of 
names bundled in an alias. If an alias is removed, you free that name. 
If that name is the representative name of the bundle, you move to the 
next one.

^ permalink raw reply

* Re: [PATCH SLUB 1/2] duplicate the cache name in saved_alias list
From: Wanlong Gao @ 2012-06-25 10:54 UTC (permalink / raw)
  To: Li Zhong
  Cc: Christoph Lameter, LKML, Pekka Enberg, linux-mm, Paul Mackerras,
	Matt Mackall, PowerPC email list
In-Reply-To: <1340617984.13778.37.camel@ThinkPad-T420>

On 06/25/2012 05:53 PM, Li Zhong wrote:
> SLUB duplicates the cache name in kmem_cache_create(). However if the
> cache could be merged to others during early booting, the name pointer
> is saved in saved_alias list, and the string needs to be kept valid
> before slab_sysfs_init() is called. 
> 
> This patch tries to duplicate the cache name in saved_alias list, so
> that the cache name could be safely kfreed after calling
> kmem_cache_create(), if that name is kmalloced. 
> 
> Signed-off-by: Li Zhong <zhong@linux.vnet.ibm.com>
> ---
>  mm/slub.c |    6 ++++++
>  1 files changed, 6 insertions(+), 0 deletions(-)
> 
> diff --git a/mm/slub.c b/mm/slub.c
> index 8c691fa..3dc8ed5 100644
> --- a/mm/slub.c
> +++ b/mm/slub.c
> @@ -5373,6 +5373,11 @@ static int sysfs_slab_alias(struct kmem_cache *s,
> const char *name)
>  
>  	al->s = s;
>  	al->name = name;
> +	al->name = kstrdup(name, GFP_KERNEL);

dup assigned the al->name ?


Thanks,
Wanlong Gao

> +	if (!al->name) {
> +		kfree(al);
> +		return -ENOMEM;
> +	}
>  	al->next = alias_list;
>  	alias_list = al;
>  	return 0;
> @@ -5409,6 +5414,7 @@ static int __init slab_sysfs_init(void)
>  		if (err)
>  			printk(KERN_ERR "SLUB: Unable to add boot slab alias"
>  					" %s to sysfs\n", s->name);
> +		kfree(al->name);
>  		kfree(al);
>  	}
>  
> 

^ permalink raw reply

* [PATCH powerpc 2/2] kfree the cache name  of pgtable cache if SLUB is used
From: Li Zhong @ 2012-06-25  9:54 UTC (permalink / raw)
  To: LKML
  Cc: Christoph Lameter, Pekka Enberg, linux-mm, Paul Mackerras,
	Matt Mackall, PowerPC email list
In-Reply-To: <1340617984.13778.37.camel@ThinkPad-T420>

This patch tries to kfree the cache name of pgtables cache if SLUB is
used, as SLUB duplicates the cache name, and the original one is leaked.

This patch depends on patch 1 -- (duplicate the cache name in
saved_alias list) in this mail thread. As the pgtables cache might be
merged to other caches. In this case, the name could be safely kfreed
after calling kmem_cache_create() with patch 1.

Signed-off-by: Li Zhong <zhong@linux.vnet.ibm.com>
---
 arch/powerpc/mm/init_64.c |    3 +++
 1 files changed, 3 insertions(+), 0 deletions(-)

diff --git a/arch/powerpc/mm/init_64.c b/arch/powerpc/mm/init_64.c
index 620b7ac..c9d2a7f 100644
--- a/arch/powerpc/mm/init_64.c
+++ b/arch/powerpc/mm/init_64.c
@@ -130,6 +130,9 @@ void pgtable_cache_add(unsigned shift, void
(*ctor)(void *))
 	align = max_t(unsigned long, align, minalign);
 	name = kasprintf(GFP_KERNEL, "pgtable-2^%d", shift);
 	new = kmem_cache_create(name, table_size, align, 0, ctor);
+#ifdef CONFIG_SLUB
+	kfree(name); /* SLUB duplicates the cache name */
+#endif
 	PGT_CACHE(shift) = new;
 
 	pr_debug("Allocated pgtable cache for order %d\n", shift);
-- 
1.7.1

^ permalink raw reply related

* [PATCH SLUB 1/2] duplicate the cache name in saved_alias list
From: Li Zhong @ 2012-06-25  9:53 UTC (permalink / raw)
  To: LKML
  Cc: Christoph Lameter, Pekka Enberg, linux-mm, Paul Mackerras,
	Matt Mackall, PowerPC email list

SLUB duplicates the cache name in kmem_cache_create(). However if the
cache could be merged to others during early booting, the name pointer
is saved in saved_alias list, and the string needs to be kept valid
before slab_sysfs_init() is called. 

This patch tries to duplicate the cache name in saved_alias list, so
that the cache name could be safely kfreed after calling
kmem_cache_create(), if that name is kmalloced. 

Signed-off-by: Li Zhong <zhong@linux.vnet.ibm.com>
---
 mm/slub.c |    6 ++++++
 1 files changed, 6 insertions(+), 0 deletions(-)

diff --git a/mm/slub.c b/mm/slub.c
index 8c691fa..3dc8ed5 100644
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -5373,6 +5373,11 @@ static int sysfs_slab_alias(struct kmem_cache *s,
const char *name)
 
 	al->s = s;
 	al->name = name;
+	al->name = kstrdup(name, GFP_KERNEL);
+	if (!al->name) {
+		kfree(al);
+		return -ENOMEM;
+	}
 	al->next = alias_list;
 	alias_list = al;
 	return 0;
@@ -5409,6 +5414,7 @@ static int __init slab_sysfs_init(void)
 		if (err)
 			printk(KERN_ERR "SLUB: Unable to add boot slab alias"
 					" %s to sysfs\n", s->name);
+		kfree(al->name);
 		kfree(al);
 	}
 
-- 
1.7.1

^ permalink raw reply related

* Re: [PATCH] powerpc: Add VDSO version of getcpu
From: Benjamin Herrenschmidt @ 2012-06-25  9:44 UTC (permalink / raw)
  To: Anton Blanchard; +Cc: linuxppc-dev, paulus
In-Reply-To: <20120625115540.2a7ad9c5@kryten>

On Mon, 2012-06-25 at 11:55 +1000, Anton Blanchard wrote:
> We had a request for a fast method of getting CPU and NUMA node IDs
> from userspace. Ben suggested we use SPRG3 which is userspace
> readable. This is a quick hack to try that out.
> 
> I have a glibc patch to implement sched_getcpu using this. Testing
> on a POWER7:
> 
> baseline: 538 cycles 
> vdso:      30 cycles
> 
> Signed-off-by: Anton Blanchard <anton@samba.org>
> ---
> 
> Outstanding issues:
> 
> - Do we have any KVM issues?

Yes we do. We need to restore SPRG3 somewhere in book3s_hv_rmhandlers.S
or it will remain to the value set by the guest. I suggest storing the
"proper" value in the PACA at boot time so we avoid having to save it
on each guest entry.

On the other hand, paulus was thinking of a hack for some other type
of process that might want to use SPRG3... (and set it using a syscall)
in which case we'd have to disable the getcpu optimization for those and
actually context switch SPRG3.. dunno what happened with that code.

Cheers,
Ben.,


> - This will only work with 64 bit kernels for now, do we need to come up
>   with a scheme for 32 bit?
> 
> - Implement 32 bit userspace version (running on 64 bit kernels)
> 
> Index: linux-build/arch/powerpc/include/asm/reg.h
> ===================================================================
> --- linux-build.orig/arch/powerpc/include/asm/reg.h	2012-06-25 10:05:52.193076424 +1000
> +++ linux-build/arch/powerpc/include/asm/reg.h	2012-06-25 10:09:02.932316659 +1000
> @@ -491,6 +491,7 @@
>  #define SPRN_SPRG1	0x111	/* Special Purpose Register General 1 */
>  #define SPRN_SPRG2	0x112	/* Special Purpose Register General 2 */
>  #define SPRN_SPRG3	0x113	/* Special Purpose Register General 3 */
> +#define SPRN_USPRG3	0x103	/* SPRG3 userspace read */
>  #define SPRN_SPRG4	0x114	/* Special Purpose Register General 4 */
>  #define SPRN_SPRG5	0x115	/* Special Purpose Register General 5 */
>  #define SPRN_SPRG6	0x116	/* Special Purpose Register General 6 */
> @@ -753,14 +754,14 @@
>   * 64-bit server:
>   *	- SPRG0 unused (reserved for HV on Power4)
>   *	- SPRG2 scratch for exception vectors
> - *	- SPRG3 unused (user visible)
> + *	- SPRG3 CPU and NUMA node for VDSO getcpu (user visible)
>   *      - HSPRG0 stores PACA in HV mode
>   *      - HSPRG1 scratch for "HV" exceptions
>   *
>   * 64-bit embedded
>   *	- SPRG0 generic exception scratch
>   *	- SPRG2 TLB exception stack
> - *	- SPRG3 unused (user visible)
> + *	- SPRG3 CPU and NUMA node for VDSO getcpu (user visible)
>   *	- SPRG4 unused (user visible)
>   *	- SPRG6 TLB miss scratch (user visible, sorry !)
>   *	- SPRG7 critical exception scratch
> Index: linux-build/arch/powerpc/kernel/vdso.c
> ===================================================================
> --- linux-build.orig/arch/powerpc/kernel/vdso.c	2012-06-25 10:05:52.229077036 +1000
> +++ linux-build/arch/powerpc/kernel/vdso.c	2012-06-25 10:12:50.256171890 +1000
> @@ -706,6 +706,25 @@ static void __init vdso_setup_syscall_ma
>  	}
>  }
>  
> +#ifdef CONFIG_PPC64
> +int __cpuinit vdso_getcpu_init(void)
> +{
> +	unsigned long cpu, node;
> +
> +	/*
> +	 * SPRG3 contains the CPU in the bottom 32 bits and the NUMA node in the
> +	 * top 32 bits.
> +	 */
> +	cpu = get_cpu();
> +	node = cpu_to_node(cpu);
> +	mtspr(SPRN_SPRG3, cpu | (node << 32));
> +	put_cpu();
> +
> +	return 0;
> +}
> +/* We need to call this before SMP init */
> +early_initcall(vdso_getcpu_init);
> +#endif
>  
>  static int __init vdso_init(void)
>  {
> Index: linux-build/arch/powerpc/kernel/vdso64/Makefile
> ===================================================================
> --- linux-build.orig/arch/powerpc/kernel/vdso64/Makefile	2012-06-25 10:05:52.209076696 +1000
> +++ linux-build/arch/powerpc/kernel/vdso64/Makefile	2012-06-25 10:05:53.737102674 +1000
> @@ -1,6 +1,6 @@
>  # List of files in the vdso, has to be asm only for now
>  
> -obj-vdso64 = sigtramp.o gettimeofday.o datapage.o cacheflush.o note.o
> +obj-vdso64 = sigtramp.o gettimeofday.o datapage.o cacheflush.o note.o getcpu.o
>  
>  # Build rules
>  
> Index: linux-build/arch/powerpc/kernel/vdso64/vdso64.lds.S
> ===================================================================
> --- linux-build.orig/arch/powerpc/kernel/vdso64/vdso64.lds.S	2012-06-25 10:05:52.217076832 +1000
> +++ linux-build/arch/powerpc/kernel/vdso64/vdso64.lds.S	2012-06-25 10:05:53.737102674 +1000
> @@ -146,6 +146,7 @@ VERSION
>  		__kernel_sync_dicache;
>  		__kernel_sync_dicache_p5;
>  		__kernel_sigtramp_rt64;
> +		__kernel_getcpu;
>  
>  	local: *;
>  	};
> Index: linux-build/arch/powerpc/kernel/vdso64/getcpu.S
> ===================================================================
> --- /dev/null	1970-01-01 00:00:00.000000000 +0000
> +++ linux-build/arch/powerpc/kernel/vdso64/getcpu.S	2012-06-25 10:09:11.796467121 +1000
> @@ -0,0 +1,44 @@
> +/*
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
> + *
> + * Copyright (C) IBM Corporation, 2012
> + *
> + * Author: Anton Blanchard <anton@au.ibm.com>
> + */
> +#include <asm/ppc_asm.h>
> +#include <asm/vdso.h>
> +
> +	.text
> +/*
> + * Exact prototype of getcpu
> + *
> + * int __kernel_getcpu(unsigned *cpu, unsigned *node);
> + *
> + */
> +V_FUNCTION_BEGIN(__kernel_getcpu)
> +  .cfi_startproc
> +	mfspr	r5,SPRN_USPRG3
> +	cmpdi	cr0,r3,0
> +	cmpdi	cr1,r4,0
> +	srdi	r6,r5,32
> +	beq	cr0,1f
> +	stw	r5,0(r3)
> +1:	beq	cr1,2f
> +	stw	r6,0(r4)
> +2:	crclr	cr0*4+so
> +	li	r3,0			/* always success */
> +	blr
> +  .cfi_endproc
> +V_FUNCTION_END(__kernel_getcpu)
> Index: linux-build/arch/powerpc/kernel/smp.c
> ===================================================================
> --- linux-build.orig/arch/powerpc/kernel/smp.c	2012-06-25 10:05:52.197076492 +1000
> +++ linux-build/arch/powerpc/kernel/smp.c	2012-06-25 10:13:54.897266908 +1000
> @@ -48,6 +48,7 @@
>  #ifdef CONFIG_PPC64
>  #include <asm/paca.h>
>  #endif
> +#include <asm/vdso.h>
>  #include <asm/debug.h>
>  
>  #ifdef DEBUG
> @@ -570,6 +571,8 @@ void __devinit start_secondary(void *unu
>  #ifdef CONFIG_PPC64
>  	if (system_state == SYSTEM_RUNNING)
>  		vdso_data->processorCount++;
> +
> +	vdso_getcpu_init();
>  #endif
>  	ipi_call_lock();
>  	notify_cpu_starting(cpu);
> Index: linux-build/arch/powerpc/include/asm/vdso.h
> ===================================================================
> --- linux-build.orig/arch/powerpc/include/asm/vdso.h	2012-06-25 10:05:52.181076220 +1000
> +++ linux-build/arch/powerpc/include/asm/vdso.h	2012-06-25 10:05:53.737102674 +1000
> @@ -22,6 +22,8 @@ extern unsigned long vdso64_rt_sigtramp;
>  extern unsigned long vdso32_sigtramp;
>  extern unsigned long vdso32_rt_sigtramp;
>  
> +int __cpuinit vdso_getcpu_init(void);
> +
>  #else /* __ASSEMBLY__ */
>  
>  #ifdef __VDSO64__

^ permalink raw reply

* Re: [PATCH] bluetooth: opcode field of sent commands is little endian.
From: Michel Dänzer @ 2012-06-25  9:33 UTC (permalink / raw)
  To: David Laight
  Cc: linux-bluetooth, Marcel Holtmann, Johan Hedberg, linuxppc-dev
In-Reply-To: <AE90C24D6B3A694183C094C60CF0A2F6026B6F62@saturn3.aculab.com>

On Mon, 2012-06-25 at 10:20 +0100, David Laight wrote:=20
> > > > Fine with me, though FWIW that not only doesn't use
> > > > __constant_cpu_to_le16() but actually swaps the non-constant value.
> > >=20
> > > Don't see what point you are trying to make here. Swapping the value
> > > from the actual command structure is always fine with me.
> >=20
> > The point is that the result of swapping a constant value is just
> > another constant value, whereas the fix in mainline swaps a value from
> > memory. Not a big deal.
>=20
> Surely, but surely, the definition of cpu_to_le16() uses
> gcc 'magic' to determine that the argument is a constant
> and then automatically selects the 'constant' form.

It can only do that if the argument is constant in the first place
though. :)


--=20
Earthling Michel D=E4nzer           |                   http://www.amd.com
Libre software enthusiast         |          Debian, X and DRI developer

^ permalink raw reply

* RE: [PATCH] bluetooth: opcode field of sent commands is little endian.
From: David Laight @ 2012-06-25  9:20 UTC (permalink / raw)
  To: Michel Dänzer, Marcel Holtmann
  Cc: linux-bluetooth, Johan Hedberg, linuxppc-dev
In-Reply-To: <1340609570.5461.50.camel@thor.local>

=20
> > > Fine with me, though FWIW that not only doesn't use
> > > __constant_cpu_to_le16() but actually swaps the non-constant =
value.
> >=20
> > Don't see what point you are trying to make here. Swapping the value
> > from the actual command structure is always fine with me.
>=20
> The point is that the result of swapping a constant value is just
> another constant value, whereas the fix in mainline swaps a value from
> memory. Not a big deal.

Surely, but surely, the definition of cpu_to_le16() uses
gcc 'magic' to determine that the argument is a constant
and then automatically selects the 'constant' form.

	David

^ permalink raw reply

* Re: [PATCH] bluetooth: opcode field of sent commands is little endian.
From: Andrei Emeltchenko @ 2012-06-25  8:02 UTC (permalink / raw)
  To: Michel Dänzer, Gustavo Padovan
  Cc: linux-bluetooth, Marcel Holtmann, Johan Hedberg, linuxppc-dev
In-Reply-To: <1340609570.5461.50.camel@thor.local>

Hi Michel,

On Mon, Jun 25, 2012 at 09:32:50AM +0200, Michel Dänzer wrote:
> > > Also, it would have been nice if that fix was promoted to stable, so I
> > > wouldn't have had to spend a good part of the weekend bisecting...
> > 
> > Thinks like this happen. However after you bisected the issue you could
> > have just checked what is in Linus' or bluetooth-next tree.
> 
> You're probably right. It just didn't occur to me that someone would
> have fixed this but not forwarded the fix to stable, because I generally
> do that. :}

Sorry for that, this and bunch of other fixes for byte order bugs needs to
be promoted to stable.

> Will you submit the fix to stable, or should I?

I added Gustavo to CC as he usually makes pull requests.

Best regards 
Andrei Emeltchenko 

^ permalink raw reply

* Re: [PATCH] bluetooth: opcode field of sent commands is little endian.
From: Michel Dänzer @ 2012-06-25  7:32 UTC (permalink / raw)
  To: Marcel Holtmann; +Cc: linux-bluetooth, Johan Hedberg, linuxppc-dev
In-Reply-To: <1340608972.29898.13.camel@aeonflux>

On Mon, 2012-06-25 at 00:22 -0700, Marcel Holtmann wrote:=20
> Hi Michel,
>=20
> > > > Fixes built-in Bluetooth not working on Apple PowerBooks, regressio=
n from
> > > > commit 75fb0e324daa48ec458fb5c2960eb07b80cfad9d ('Bluetooth: Fix in=
it sequence
> > > > for some CSR based controllers').
> > > >=20
> > > > Cc: stable@vger.kernel.org [v3.4]
> > > > Signed-off-by: Michel D=E4nzer <michel@daenzer.net>
> > > > ---
> > > >  net/bluetooth/hci_core.c |    2 +-
> > > >  1 file changed, 1 insertion(+), 1 deletion(-)
> > > >=20
> > > > diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
> > > > index d6dc44c..e039e3d 100644
> > > > --- a/net/bluetooth/hci_core.c
> > > > +++ b/net/bluetooth/hci_core.c
> > > > @@ -92,7 +92,7 @@ void hci_req_complete(struct hci_dev *hdev, __u16=
 cmd, int result)
> > > >  		 * command.
> > > >  		 */
> > > > =20
> > > > -		if (cmd !=3D HCI_OP_RESET || sent->opcode =3D=3D HCI_OP_RESET)
> > > > +		if (cmd !=3D HCI_OP_RESET || sent->opcode =3D=3D cpu_to_le16(HCI=
_OP_RESET))
> > > >  			return;
> > >=20
> > > actually you could use __constant_cpu_to_le16() here.
> >=20
> > Yes, but I checked and that's not used anywhere in the bluetooth code
> > yet, so I thought I'd stay consistent for now.
>=20
> not sure what code you are looking at, but I count 18 occurrences and we
> have been fixing the ones we missed initially.

Okay, good then. As you probably noticed from the rest of my posts, I
only checked up to 3.4.


> > > That said, this got actually fixed differently upstream. So I prefer =
if
> > > that patch gets merged into stable and not this one.
> > >=20
> > > commit 1036b89042df96e71c0cb941be212f8053ecccc0
> > > Author: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
> > > Date:   Mon Mar 12 15:59:33 2012 +0200
> > >=20
> > >     Bluetooth: Fix opcode access in hci_complete
> >=20
> > Fine with me, though FWIW that not only doesn't use
> > __constant_cpu_to_le16() but actually swaps the non-constant value.
>=20
> Don't see what point you are trying to make here. Swapping the value
> from the actual command structure is always fine with me.

The point is that the result of swapping a constant value is just
another constant value, whereas the fix in mainline swaps a value from
memory. Not a big deal.


> > Also, it would have been nice if that fix was promoted to stable, so I
> > wouldn't have had to spend a good part of the weekend bisecting...
>=20
> Thinks like this happen. However after you bisected the issue you could
> have just checked what is in Linus' or bluetooth-next tree.

You're probably right. It just didn't occur to me that someone would
have fixed this but not forwarded the fix to stable, because I generally
do that. :}


Will you submit the fix to stable, or should I?


--=20
Earthling Michel D=E4nzer           |                   http://www.amd.com
Libre software enthusiast         |          Debian, X and DRI developer

^ permalink raw reply

* Re: [PATCH] bluetooth: opcode field of sent commands is little endian.
From: Marcel Holtmann @ 2012-06-25  7:22 UTC (permalink / raw)
  To: Michel Dänzer; +Cc: linux-bluetooth, Johan Hedberg, linuxppc-dev
In-Reply-To: <1340607965.5461.40.camel@thor.local>

Hi Michel,

> > > Fixes built-in Bluetooth not working on Apple PowerBooks, regression from
> > > commit 75fb0e324daa48ec458fb5c2960eb07b80cfad9d ('Bluetooth: Fix init sequence
> > > for some CSR based controllers').
> > > 
> > > Cc: stable@vger.kernel.org [v3.4]
> > > Signed-off-by: Michel Dänzer <michel@daenzer.net>
> > > ---
> > >  net/bluetooth/hci_core.c |    2 +-
> > >  1 file changed, 1 insertion(+), 1 deletion(-)
> > > 
> > > diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
> > > index d6dc44c..e039e3d 100644
> > > --- a/net/bluetooth/hci_core.c
> > > +++ b/net/bluetooth/hci_core.c
> > > @@ -92,7 +92,7 @@ void hci_req_complete(struct hci_dev *hdev, __u16 cmd, int result)
> > >  		 * command.
> > >  		 */
> > >  
> > > -		if (cmd != HCI_OP_RESET || sent->opcode == HCI_OP_RESET)
> > > +		if (cmd != HCI_OP_RESET || sent->opcode == cpu_to_le16(HCI_OP_RESET))
> > >  			return;
> > 
> > actually you could use __constant_cpu_to_le16() here.
> 
> Yes, but I checked and that's not used anywhere in the bluetooth code
> yet, so I thought I'd stay consistent for now.

not sure what code you are looking at, but I count 18 occurrences and we
have been fixing the ones we missed initially.

> > That said, this got actually fixed differently upstream. So I prefer if
> > that patch gets merged into stable and not this one.
> > 
> > commit 1036b89042df96e71c0cb941be212f8053ecccc0
> > Author: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
> > Date:   Mon Mar 12 15:59:33 2012 +0200
> > 
> >     Bluetooth: Fix opcode access in hci_complete
> 
> Fine with me, though FWIW that not only doesn't use
> __constant_cpu_to_le16() but actually swaps the non-constant value.

Don't see what point you are trying to make here. Swapping the value
from the actual command structure is always fine with me.

> Also, it would have been nice if that fix was promoted to stable, so I
> wouldn't have had to spend a good part of the weekend bisecting...

Thinks like this happen. However after you bisected the issue you could
have just checked what is in Linus' or bluetooth-next tree. Since the
first thing I did is go through bluetooth-next and check if we have not
fixed that yet.

Regards

Marcel

^ permalink raw reply

* Re: [PATCH] bluetooth: opcode field of sent commands is little endian.
From: Michel Dänzer @ 2012-06-25  7:06 UTC (permalink / raw)
  To: Marcel Holtmann; +Cc: linux-bluetooth, Johan Hedberg, linuxppc-dev
In-Reply-To: <1340607113.29898.3.camel@aeonflux>

On Son, 2012-06-24 at 23:51 -0700, Marcel Holtmann wrote:=20
> Hi Michel,
>=20
> > Fixes built-in Bluetooth not working on Apple PowerBooks, regression fr=
om
> > commit 75fb0e324daa48ec458fb5c2960eb07b80cfad9d ('Bluetooth: Fix init s=
equence
> > for some CSR based controllers').
> >=20
> > Cc: stable@vger.kernel.org [v3.4]
> > Signed-off-by: Michel D=E4nzer <michel@daenzer.net>
> > ---
> >  net/bluetooth/hci_core.c |    2 +-
> >  1 file changed, 1 insertion(+), 1 deletion(-)
> >=20
> > diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
> > index d6dc44c..e039e3d 100644
> > --- a/net/bluetooth/hci_core.c
> > +++ b/net/bluetooth/hci_core.c
> > @@ -92,7 +92,7 @@ void hci_req_complete(struct hci_dev *hdev, __u16 cmd=
, int result)
> >  		 * command.
> >  		 */
> > =20
> > -		if (cmd !=3D HCI_OP_RESET || sent->opcode =3D=3D HCI_OP_RESET)
> > +		if (cmd !=3D HCI_OP_RESET || sent->opcode =3D=3D cpu_to_le16(HCI_OP_=
RESET))
> >  			return;
>=20
> actually you could use __constant_cpu_to_le16() here.

Yes, but I checked and that's not used anywhere in the bluetooth code
yet, so I thought I'd stay consistent for now.


> That said, this got actually fixed differently upstream. So I prefer if
> that patch gets merged into stable and not this one.
>=20
> commit 1036b89042df96e71c0cb941be212f8053ecccc0
> Author: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
> Date:   Mon Mar 12 15:59:33 2012 +0200
>=20
>     Bluetooth: Fix opcode access in hci_complete

Fine with me, though FWIW that not only doesn't use
__constant_cpu_to_le16() but actually swaps the non-constant value.

Also, it would have been nice if that fix was promoted to stable, so I
wouldn't have had to spend a good part of the weekend bisecting...


> In general patches need to get into Linus' tree first before you can
> even request them for stable.

I know, that's why I only put the stable tag in commit logs but don't
submit patches there via e-mail.


--=20
Earthling Michel D=E4nzer           |                   http://www.amd.com
Libre software enthusiast         |          Debian, X and DRI developer

^ permalink raw reply

* Re: [PATCH] bluetooth: opcode field of sent commands is little endian.
From: Marcel Holtmann @ 2012-06-25  6:51 UTC (permalink / raw)
  To: Michel Dänzer; +Cc: linux-bluetooth, Johan Hedberg, linuxppc-dev
In-Reply-To: <1340606319-32187-1-git-send-email-michel@daenzer.net>

Hi Michel,

> Fixes built-in Bluetooth not working on Apple PowerBooks, regression from
> commit 75fb0e324daa48ec458fb5c2960eb07b80cfad9d ('Bluetooth: Fix init sequence
> for some CSR based controllers').
> 
> Cc: stable@vger.kernel.org [v3.4]
> Signed-off-by: Michel Dänzer <michel@daenzer.net>
> ---
>  net/bluetooth/hci_core.c |    2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
> index d6dc44c..e039e3d 100644
> --- a/net/bluetooth/hci_core.c
> +++ b/net/bluetooth/hci_core.c
> @@ -92,7 +92,7 @@ void hci_req_complete(struct hci_dev *hdev, __u16 cmd, int result)
>  		 * command.
>  		 */
>  
> -		if (cmd != HCI_OP_RESET || sent->opcode == HCI_OP_RESET)
> +		if (cmd != HCI_OP_RESET || sent->opcode == cpu_to_le16(HCI_OP_RESET))
>  			return;

actually you could use __constant_cpu_to_le16() here.

That said, this got actually fixed differently upstream. So I prefer if
that patch gets merged into stable and not this one.

commit 1036b89042df96e71c0cb941be212f8053ecccc0
Author: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
Date:   Mon Mar 12 15:59:33 2012 +0200

    Bluetooth: Fix opcode access in hci_complete

In general patches need to get into Linus' tree first before you can
even request them for stable.

Regards

Marcel

^ permalink raw reply

* Re: [PATCH v2 1/1] of: reform prom_update_property function
From: Benjamin Herrenschmidt @ 2012-06-25  6:46 UTC (permalink / raw)
  To: Dong Aisheng
  Cc: devicetree-discuss, linux-kernel, rob.herring, paulus,
	linuxppc-dev
In-Reply-To: <1340605714-25206-1-git-send-email-b29396@freescale.com>

On Mon, 2012-06-25 at 14:28 +0800, Dong Aisheng wrote:
> From: Dong Aisheng <dong.aisheng@linaro.org>
> 
> prom_update_property() currently fails if the property doesn't
> actually exist yet which isn't what we want. Change to add-or-update
> instead of update-only, then we can remove a lot duplicated lines.
> 
> Suggested-by: Grant Likely <grant.likely@secretlab.ca>
> Signed-off-by: Dong Aisheng <dong.aisheng@linaro.org>
> ---

Grand, should I merge that via the powerpc tree or will you take care of
it ?

Acked-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>

Cheers,
Ben.

> ChangeLog v1->v2:
> * keep reconfig.c behavior the same as before after changes
> ---
>  arch/powerpc/platforms/85xx/p1022_ds.c    |    8 +-------
>  arch/powerpc/platforms/pseries/mobility.c |    8 +-------
>  arch/powerpc/platforms/pseries/reconfig.c |   16 ++++++----------
>  drivers/of/base.c                         |   15 +++++++++++----
>  fs/proc/proc_devtree.c                    |    5 +++++
>  include/linux/of.h                        |    3 +--
>  6 files changed, 25 insertions(+), 30 deletions(-)
> 
> diff --git a/arch/powerpc/platforms/85xx/p1022_ds.c b/arch/powerpc/platforms/85xx/p1022_ds.c
> index f700c81..d66631c 100644
> --- a/arch/powerpc/platforms/85xx/p1022_ds.c
> +++ b/arch/powerpc/platforms/85xx/p1022_ds.c
> @@ -348,13 +348,7 @@ void __init p1022_ds_pic_init(void)
>   */
>  static void __init disable_one_node(struct device_node *np, struct property *new)
>  {
> -	struct property *old;
> -
> -	old = of_find_property(np, new->name, NULL);
> -	if (old)
> -		prom_update_property(np, new, old);
> -	else
> -		prom_add_property(np, new);
> +	prom_update_property(np, new);
>  }
>  
>  /* TRUE if there is a "video=fslfb" command-line parameter. */
> diff --git a/arch/powerpc/platforms/pseries/mobility.c b/arch/powerpc/platforms/pseries/mobility.c
> index 029a562..dd30b12 100644
> --- a/arch/powerpc/platforms/pseries/mobility.c
> +++ b/arch/powerpc/platforms/pseries/mobility.c
> @@ -67,7 +67,6 @@ static int update_dt_property(struct device_node *dn, struct property **prop,
>  			      const char *name, u32 vd, char *value)
>  {
>  	struct property *new_prop = *prop;
> -	struct property *old_prop;
>  	int more = 0;
>  
>  	/* A negative 'vd' value indicates that only part of the new property
> @@ -117,12 +116,7 @@ static int update_dt_property(struct device_node *dn, struct property **prop,
>  	}
>  
>  	if (!more) {
> -		old_prop = of_find_property(dn, new_prop->name, NULL);
> -		if (old_prop)
> -			prom_update_property(dn, new_prop, old_prop);
> -		else
> -			prom_add_property(dn, new_prop);
> -
> +		prom_update_property(dn, new_prop);
>  		new_prop = NULL;
>  	}
>  
> diff --git a/arch/powerpc/platforms/pseries/reconfig.c b/arch/powerpc/platforms/pseries/reconfig.c
> index 7b3bf76..db1b7b1 100644
> --- a/arch/powerpc/platforms/pseries/reconfig.c
> +++ b/arch/powerpc/platforms/pseries/reconfig.c
> @@ -432,7 +432,7 @@ static int do_update_property(char *buf, size_t bufsize)
>  	unsigned char *value;
>  	char *name, *end, *next_prop;
>  	int rc, length;
> -	struct property *newprop, *oldprop;
> +	struct property *newprop;
>  	buf = parse_node(buf, bufsize, &np);
>  	end = buf + bufsize;
>  
> @@ -443,6 +443,9 @@ static int do_update_property(char *buf, size_t bufsize)
>  	if (!next_prop)
>  		return -EINVAL;
>  
> +	if (!strlen(name)
> +		return -ENODEV;
> +
>  	newprop = new_property(name, length, value, NULL);
>  	if (!newprop)
>  		return -ENOMEM;
> @@ -450,18 +453,11 @@ static int do_update_property(char *buf, size_t bufsize)
>  	if (!strcmp(name, "slb-size") || !strcmp(name, "ibm,slb-size"))
>  		slb_set_size(*(int *)value);
>  
> -	oldprop = of_find_property(np, name,NULL);
> -	if (!oldprop) {
> -		if (strlen(name))
> -			return prom_add_property(np, newprop);
> -		return -ENODEV;
> -	}
> -
>  	upd_value.node = np;
>  	upd_value.property = newprop;
>  	pSeries_reconfig_notify(PSERIES_UPDATE_PROPERTY, &upd_value);
>  
> -	rc = prom_update_property(np, newprop, oldprop);
> +	rc = prom_update_property(np, newprop);
>  	if (rc)
>  		return rc;
>  
> @@ -486,7 +482,7 @@ static int do_update_property(char *buf, size_t bufsize)
>  
>  		rc = pSeries_reconfig_notify(action, value);
>  		if (rc) {
> -			prom_update_property(np, oldprop, newprop);
> +			prom_update_property(np, newprop);
>  			return rc;
>  		}
>  	}
> diff --git a/drivers/of/base.c b/drivers/of/base.c
> index d9bfd49..a14f109 100644
> --- a/drivers/of/base.c
> +++ b/drivers/of/base.c
> @@ -1051,7 +1051,8 @@ int prom_remove_property(struct device_node *np, struct property *prop)
>  }
>  
>  /*
> - * prom_update_property - Update a property in a node.
> + * prom_update_property - Update a property in a node, if the property does
> + * not exist, add it.
>   *
>   * Note that we don't actually remove it, since we have given out
>   * who-knows-how-many pointers to the data using get-property.
> @@ -1059,13 +1060,19 @@ int prom_remove_property(struct device_node *np, struct property *prop)
>   * and add the new property to the property list
>   */
>  int prom_update_property(struct device_node *np,
> -			 struct property *newprop,
> -			 struct property *oldprop)
> +			 struct property *newprop)
>  {
> -	struct property **next;
> +	struct property **next, *oldprop;
>  	unsigned long flags;
>  	int found = 0;
>  
> +	if (!newprop->name)
> +		return -EINVAL;
> +
> +	oldprop = of_find_property(np, newprop->name, NULL);
> +	if (!oldprop)
> +		return prom_add_property(np, newprop);
> +
>  	write_lock_irqsave(&devtree_lock, flags);
>  	next = &np->properties;
>  	while (*next) {
> diff --git a/fs/proc/proc_devtree.c b/fs/proc/proc_devtree.c
> index 927cbd1..df7dd08 100644
> --- a/fs/proc/proc_devtree.c
> +++ b/fs/proc/proc_devtree.c
> @@ -101,6 +101,11 @@ void proc_device_tree_update_prop(struct proc_dir_entry *pde,
>  {
>  	struct proc_dir_entry *ent;
>  
> +	if (!oldprop) {
> +		proc_device_tree_add_prop(pde, newprop);
> +		return;
> +	}
> +
>  	for (ent = pde->subdir; ent != NULL; ent = ent->next)
>  		if (ent->data == oldprop)
>  			break;
> diff --git a/include/linux/of.h b/include/linux/of.h
> index 2ec1083..b27c871 100644
> --- a/include/linux/of.h
> +++ b/include/linux/of.h
> @@ -260,8 +260,7 @@ extern int of_machine_is_compatible(const char *compat);
>  extern int prom_add_property(struct device_node* np, struct property* prop);
>  extern int prom_remove_property(struct device_node *np, struct property *prop);
>  extern int prom_update_property(struct device_node *np,
> -				struct property *newprop,
> -				struct property *oldprop);
> +				struct property *newprop);
>  
>  #if defined(CONFIG_OF_DYNAMIC)
>  /* For updating the device tree at runtime */

^ permalink raw reply

* [PATCH] bluetooth: opcode field of sent commands is little endian.
From: Michel Dänzer @ 2012-06-25  6:38 UTC (permalink / raw)
  To: Johan Hedberg, Marcel Holtmann; +Cc: linux-bluetooth, linuxppc-dev

Fixes built-in Bluetooth not working on Apple PowerBooks, regression from
commit 75fb0e324daa48ec458fb5c2960eb07b80cfad9d ('Bluetooth: Fix init sequence
for some CSR based controllers').

Cc: stable@vger.kernel.org [v3.4]
Signed-off-by: Michel Dänzer <michel@daenzer.net>
---
 net/bluetooth/hci_core.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index d6dc44c..e039e3d 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -92,7 +92,7 @@ void hci_req_complete(struct hci_dev *hdev, __u16 cmd, int result)
 		 * command.
 		 */
 
-		if (cmd != HCI_OP_RESET || sent->opcode == HCI_OP_RESET)
+		if (cmd != HCI_OP_RESET || sent->opcode == cpu_to_le16(HCI_OP_RESET))
 			return;
 
 		skb = skb_clone(hdev->sent_cmd, GFP_ATOMIC);
-- 
1.7.10.4

^ permalink raw reply related

* [PATCH v2 1/1] of: reform prom_update_property function
From: Dong Aisheng @ 2012-06-25  6:28 UTC (permalink / raw)
  To: linux-kernel; +Cc: devicetree-discuss, rob.herring, paulus, linuxppc-dev

From: Dong Aisheng <dong.aisheng@linaro.org>

prom_update_property() currently fails if the property doesn't
actually exist yet which isn't what we want. Change to add-or-update
instead of update-only, then we can remove a lot duplicated lines.

Suggested-by: Grant Likely <grant.likely@secretlab.ca>
Signed-off-by: Dong Aisheng <dong.aisheng@linaro.org>
---
ChangeLog v1->v2:
* keep reconfig.c behavior the same as before after changes
---
 arch/powerpc/platforms/85xx/p1022_ds.c    |    8 +-------
 arch/powerpc/platforms/pseries/mobility.c |    8 +-------
 arch/powerpc/platforms/pseries/reconfig.c |   16 ++++++----------
 drivers/of/base.c                         |   15 +++++++++++----
 fs/proc/proc_devtree.c                    |    5 +++++
 include/linux/of.h                        |    3 +--
 6 files changed, 25 insertions(+), 30 deletions(-)

diff --git a/arch/powerpc/platforms/85xx/p1022_ds.c b/arch/powerpc/platforms/85xx/p1022_ds.c
index f700c81..d66631c 100644
--- a/arch/powerpc/platforms/85xx/p1022_ds.c
+++ b/arch/powerpc/platforms/85xx/p1022_ds.c
@@ -348,13 +348,7 @@ void __init p1022_ds_pic_init(void)
  */
 static void __init disable_one_node(struct device_node *np, struct property *new)
 {
-	struct property *old;
-
-	old = of_find_property(np, new->name, NULL);
-	if (old)
-		prom_update_property(np, new, old);
-	else
-		prom_add_property(np, new);
+	prom_update_property(np, new);
 }
 
 /* TRUE if there is a "video=fslfb" command-line parameter. */
diff --git a/arch/powerpc/platforms/pseries/mobility.c b/arch/powerpc/platforms/pseries/mobility.c
index 029a562..dd30b12 100644
--- a/arch/powerpc/platforms/pseries/mobility.c
+++ b/arch/powerpc/platforms/pseries/mobility.c
@@ -67,7 +67,6 @@ static int update_dt_property(struct device_node *dn, struct property **prop,
 			      const char *name, u32 vd, char *value)
 {
 	struct property *new_prop = *prop;
-	struct property *old_prop;
 	int more = 0;
 
 	/* A negative 'vd' value indicates that only part of the new property
@@ -117,12 +116,7 @@ static int update_dt_property(struct device_node *dn, struct property **prop,
 	}
 
 	if (!more) {
-		old_prop = of_find_property(dn, new_prop->name, NULL);
-		if (old_prop)
-			prom_update_property(dn, new_prop, old_prop);
-		else
-			prom_add_property(dn, new_prop);
-
+		prom_update_property(dn, new_prop);
 		new_prop = NULL;
 	}
 
diff --git a/arch/powerpc/platforms/pseries/reconfig.c b/arch/powerpc/platforms/pseries/reconfig.c
index 7b3bf76..db1b7b1 100644
--- a/arch/powerpc/platforms/pseries/reconfig.c
+++ b/arch/powerpc/platforms/pseries/reconfig.c
@@ -432,7 +432,7 @@ static int do_update_property(char *buf, size_t bufsize)
 	unsigned char *value;
 	char *name, *end, *next_prop;
 	int rc, length;
-	struct property *newprop, *oldprop;
+	struct property *newprop;
 	buf = parse_node(buf, bufsize, &np);
 	end = buf + bufsize;
 
@@ -443,6 +443,9 @@ static int do_update_property(char *buf, size_t bufsize)
 	if (!next_prop)
 		return -EINVAL;
 
+	if (!strlen(name)
+		return -ENODEV;
+
 	newprop = new_property(name, length, value, NULL);
 	if (!newprop)
 		return -ENOMEM;
@@ -450,18 +453,11 @@ static int do_update_property(char *buf, size_t bufsize)
 	if (!strcmp(name, "slb-size") || !strcmp(name, "ibm,slb-size"))
 		slb_set_size(*(int *)value);
 
-	oldprop = of_find_property(np, name,NULL);
-	if (!oldprop) {
-		if (strlen(name))
-			return prom_add_property(np, newprop);
-		return -ENODEV;
-	}
-
 	upd_value.node = np;
 	upd_value.property = newprop;
 	pSeries_reconfig_notify(PSERIES_UPDATE_PROPERTY, &upd_value);
 
-	rc = prom_update_property(np, newprop, oldprop);
+	rc = prom_update_property(np, newprop);
 	if (rc)
 		return rc;
 
@@ -486,7 +482,7 @@ static int do_update_property(char *buf, size_t bufsize)
 
 		rc = pSeries_reconfig_notify(action, value);
 		if (rc) {
-			prom_update_property(np, oldprop, newprop);
+			prom_update_property(np, newprop);
 			return rc;
 		}
 	}
diff --git a/drivers/of/base.c b/drivers/of/base.c
index d9bfd49..a14f109 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -1051,7 +1051,8 @@ int prom_remove_property(struct device_node *np, struct property *prop)
 }
 
 /*
- * prom_update_property - Update a property in a node.
+ * prom_update_property - Update a property in a node, if the property does
+ * not exist, add it.
  *
  * Note that we don't actually remove it, since we have given out
  * who-knows-how-many pointers to the data using get-property.
@@ -1059,13 +1060,19 @@ int prom_remove_property(struct device_node *np, struct property *prop)
  * and add the new property to the property list
  */
 int prom_update_property(struct device_node *np,
-			 struct property *newprop,
-			 struct property *oldprop)
+			 struct property *newprop)
 {
-	struct property **next;
+	struct property **next, *oldprop;
 	unsigned long flags;
 	int found = 0;
 
+	if (!newprop->name)
+		return -EINVAL;
+
+	oldprop = of_find_property(np, newprop->name, NULL);
+	if (!oldprop)
+		return prom_add_property(np, newprop);
+
 	write_lock_irqsave(&devtree_lock, flags);
 	next = &np->properties;
 	while (*next) {
diff --git a/fs/proc/proc_devtree.c b/fs/proc/proc_devtree.c
index 927cbd1..df7dd08 100644
--- a/fs/proc/proc_devtree.c
+++ b/fs/proc/proc_devtree.c
@@ -101,6 +101,11 @@ void proc_device_tree_update_prop(struct proc_dir_entry *pde,
 {
 	struct proc_dir_entry *ent;
 
+	if (!oldprop) {
+		proc_device_tree_add_prop(pde, newprop);
+		return;
+	}
+
 	for (ent = pde->subdir; ent != NULL; ent = ent->next)
 		if (ent->data == oldprop)
 			break;
diff --git a/include/linux/of.h b/include/linux/of.h
index 2ec1083..b27c871 100644
--- a/include/linux/of.h
+++ b/include/linux/of.h
@@ -260,8 +260,7 @@ extern int of_machine_is_compatible(const char *compat);
 extern int prom_add_property(struct device_node* np, struct property* prop);
 extern int prom_remove_property(struct device_node *np, struct property *prop);
 extern int prom_update_property(struct device_node *np,
-				struct property *newprop,
-				struct property *oldprop);
+				struct property *newprop);
 
 #if defined(CONFIG_OF_DYNAMIC)
 /* For updating the device tree at runtime */
-- 
1.7.0.4

^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox