Patchwork Per process DSCR + somefixes (try#3)

login
register
mail settings
Submitter Alexey Kardashevskiy
Date Feb. 16, 2011, 5:38 a.m.
Message ID <4D5B62F2.3020709@au1.ibm.com>
Download mbox | patch
Permalink /patch/83338/
State Changes Requested
Delegated to: Benjamin Herrenschmidt
Headers show

Comments

Alexey Kardashevskiy - Feb. 16, 2011, 5:38 a.m.
step1: http://patchwork.ozlabs.org/patch/71489/
step2: http://patchwork.ozlabs.org/patch/81423/

In step2 I defined sysfs node as:

static SYSDEV_ATTR(dscr_default, 0600, show_dscr_default, 
store_dscr_default);

and it caused problems with rhel6.
Now it is:

static SYSDEV_CLASS_ATTR(dscr_default, 0600, show_dscr_default, 
store_dscr_default);

It works now on both 2.6.32 and 2.6.36 but is that correct?
Alexey Kardashevskiy - Feb. 21, 2011, 2:44 a.m.
RHEL6 problem was that it crashed when doing
echo 3 > /sys/devices/system/cpu/dscr_default
because access methods for SYSDEV_ATTR and SYSDEV_CLASS_ATTR have 
different number of parameters in RHEL6. It was not correct for 2.6.36 
either but the parameters number is the same for both SYSDEV_ATTR and 
SYSDEV_CLASS_ATTR and 2.6.36 simply forgave me.
Benjamin Herrenschmidt - March 2, 2011, 5:47 a.m.
On Wed, 2011-02-16 at 16:38 +1100, Alexey Kardashevskiy wrote:
> step1: http://patchwork.ozlabs.org/patch/71489/
> step2: http://patchwork.ozlabs.org/patch/81423/
> 
> In step2 I defined sysfs node as:
> 
> static SYSDEV_ATTR(dscr_default, 0600, show_dscr_default, 
> store_dscr_default);
> 
> and it caused problems with rhel6.
> Now it is:
> 
> static SYSDEV_CLASS_ATTR(dscr_default, 0600, show_dscr_default, 
> store_dscr_default);
> 
> It works now on both 2.6.32 and 2.6.36 but is that correct?

Ok, please resend with a proper changeset comment, something like that
would do:

<<
The DSCR (aka Data Stream Control Register) is supported on some
server PowerPC chips and allow some control over the prefetch
of data streams.

This patch allows the value to specified per thread by emulating
the corresponding mfspr and mtspr instructions. Children of such
threads inherit the value. Other threads use a default value that
can be specified in sysfs.
>>

And include your Signed-off-by: line.

BTW. I suppose it's an expected behaviour that thread created with a
given default value will keep that value even when the default is later
changed right ? And their descendents will use the same default as the
original thread, not the new default, at least that's how I read your
code :-) Maybe that should be documented somewhere...

Cheers,
Ben.
Alexey Kardashevskiy - March 2, 2011, 6:15 a.m.
On 02/03/11 16:47, Benjamin Herrenschmidt wrote:
> BTW. I suppose it's an expected behaviour that thread created with a
> given default value will keep that value even when the default is later
> changed right ? And their descendents will use the same default as the
> original thread, not the new default, at least that's how I read your
> code :-) Maybe that should be documented somewhere...
>    

That's right. The idea was to let one set of 
processes-which-do-not-access-dscr-directly to work+fork with one value 
and other set to work+fork with another value. I have no idea who and 
how is going to use it though. Hope the HPC team tells me if something 
is wrong :-)

Patch

diff -Nuar ../linus-before-dscr/arch/powerpc//include/asm/emulated_ops.h linus-dscr/arch/powerpc//include/asm/emulated_ops.h
--- ../linus-before-dscr/arch/powerpc//include/asm/emulated_ops.h	2010-10-27 14:25:45.000000000 +1100
+++ linus-dscr/arch/powerpc//include/asm/emulated_ops.h	2011-01-04 12:53:50.000000000 +1100
@@ -52,6 +52,10 @@ 
 #ifdef CONFIG_VSX
 	struct ppc_emulated_entry vsx;
 #endif
+#ifdef CONFIG_PPC64
+	struct ppc_emulated_entry mfdscr;
+	struct ppc_emulated_entry mtdscr;
+#endif
 } ppc_emulated;
 
 extern u32 ppc_warn_emulated;
diff -Nuar ../linus-before-dscr/arch/powerpc//include/asm/ppc-opcode.h linus-dscr/arch/powerpc//include/asm/ppc-opcode.h
--- ../linus-before-dscr/arch/powerpc//include/asm/ppc-opcode.h	2010-10-27 14:25:45.000000000 +1100
+++ linus-dscr/arch/powerpc//include/asm/ppc-opcode.h	2011-01-04 12:53:50.000000000 +1100
@@ -39,6 +39,10 @@ 
 #define PPC_INST_RFCI			0x4c000066
 #define PPC_INST_RFDI			0x4c00004e
 #define PPC_INST_RFMCI			0x4c00004c
+#define PPC_INST_MFSPR_DSCR		0x7c1102a6
+#define PPC_INST_MFSPR_DSCR_MASK	0xfc1fffff
+#define PPC_INST_MTSPR_DSCR		0x7c1103a6
+#define PPC_INST_MTSPR_DSCR_MASK	0xfc1fffff
 
 #define PPC_INST_STRING			0x7c00042a
 #define PPC_INST_STRING_MASK		0xfc0007fe
diff -Nuar ../linus-before-dscr/arch/powerpc//include/asm/processor.h linus-dscr/arch/powerpc//include/asm/processor.h
--- ../linus-before-dscr/arch/powerpc//include/asm/processor.h	2010-10-27 14:25:45.000000000 +1100
+++ linus-dscr/arch/powerpc//include/asm/processor.h	2011-02-02 10:36:21.000000000 +1100
@@ -240,6 +240,10 @@ 
 #ifdef CONFIG_KVM_BOOK3S_32_HANDLER
 	void*		kvm_shadow_vcpu; /* KVM internal data */
 #endif /* CONFIG_KVM_BOOK3S_32_HANDLER */
+#ifdef CONFIG_PPC64
+	unsigned long	dscr;
+	int		dscr_inherit;
+#endif
 };
 
 #define ARCH_MIN_TASKALIGN 16
diff -Nuar ../linus-before-dscr/arch/powerpc//kernel/asm-offsets.c linus-dscr/arch/powerpc//kernel/asm-offsets.c
--- ../linus-before-dscr/arch/powerpc//kernel/asm-offsets.c	2010-10-27 14:25:45.000000000 +1100
+++ linus-dscr/arch/powerpc//kernel/asm-offsets.c	2011-01-04 12:53:50.000000000 +1100
@@ -74,6 +74,7 @@ 
 	DEFINE(AUDITCONTEXT, offsetof(struct task_struct, audit_context));
 	DEFINE(SIGSEGV, SIGSEGV);
 	DEFINE(NMI_MASK, NMI_MASK);
+	DEFINE(THREAD_DSCR, offsetof(struct thread_struct, dscr));
 #else
 	DEFINE(THREAD_INFO, offsetof(struct task_struct, stack));
 #endif /* CONFIG_PPC64 */
diff -Nuar ../linus-before-dscr/arch/powerpc//kernel/entry_64.S linus-dscr/arch/powerpc//kernel/entry_64.S
--- ../linus-before-dscr/arch/powerpc//kernel/entry_64.S	2010-10-27 14:25:45.000000000 +1100
+++ linus-dscr/arch/powerpc//kernel/entry_64.S	2011-02-02 06:13:17.000000000 +1100
@@ -421,6 +421,12 @@ 
 	std	r24,THREAD_VRSAVE(r3)
 END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
 #endif /* CONFIG_ALTIVEC */
+#ifdef CONFIG_PPC64
+BEGIN_FTR_SECTION
+	mfspr	r25,SPRN_DSCR
+	std	r25,THREAD_DSCR(r3)
+END_FTR_SECTION_IFSET(CPU_FTR_DSCR)
+#endif
 	and.	r0,r0,r22
 	beq+	1f
 	andc	r22,r22,r0
@@ -522,6 +528,15 @@ 
 	mtspr	SPRN_VRSAVE,r0		/* if G4, restore VRSAVE reg */
 END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
 #endif /* CONFIG_ALTIVEC */
+#ifdef CONFIG_PPC64
+BEGIN_FTR_SECTION
+	ld	r0,THREAD_DSCR(r4)
+	cmpd	r0,r25
+	beq	1f
+	mtspr	SPRN_DSCR,r0
+1:	
+END_FTR_SECTION_IFSET(CPU_FTR_DSCR)
+#endif
 
 	/* r3-r13 are destroyed -- Cort */
 	REST_8GPRS(14, r1)
diff -Nuar ../linus-before-dscr/arch/powerpc//kernel/process.c linus-dscr/arch/powerpc//kernel/process.c
--- ../linus-before-dscr/arch/powerpc//kernel/process.c	2010-10-27 14:25:45.000000000 +1100
+++ linus-dscr/arch/powerpc//kernel/process.c	2011-02-16 16:27:37.000000000 +1100
@@ -700,6 +700,8 @@ 
 /*
  * Copy a thread..
  */
+extern unsigned long dscr_default; /* defined in arch/powerpc/kernel/sysfs.c */
+
 int copy_thread(unsigned long clone_flags, unsigned long usp,
 		unsigned long unused, struct task_struct *p,
 		struct pt_regs *regs)
@@ -767,6 +769,20 @@ 
 		p->thread.ksp_vsid = sp_vsid;
 	}
 #endif /* CONFIG_PPC_STD_MMU_64 */
+#ifdef CONFIG_PPC64 
+	if (cpu_has_feature(CPU_FTR_DSCR)) {
+		if (current->thread.dscr_inherit) {
+			p->thread.dscr_inherit = 1;
+			p->thread.dscr = current->thread.dscr;
+		} else if (0 != dscr_default) {
+			p->thread.dscr_inherit = 1;
+			p->thread.dscr = dscr_default;
+		} else {
+			p->thread.dscr_inherit = 0;
+			p->thread.dscr = 0;
+		}
+	}
+#endif
 
 	/*
 	 * The PPC64 ABI makes use of a TOC to contain function 
diff -Nuar ../linus-before-dscr/arch/powerpc//kernel/sysfs.c linus-dscr/arch/powerpc//kernel/sysfs.c
--- ../linus-before-dscr/arch/powerpc//kernel/sysfs.c	2010-10-27 14:25:45.000000000 +1100
+++ linus-dscr/arch/powerpc//kernel/sysfs.c	2011-02-16 16:27:58.000000000 +1100
@@ -182,6 +182,41 @@ 
 static SYSDEV_ATTR(spurr, 0600, show_spurr, NULL);
 static SYSDEV_ATTR(dscr, 0600, show_dscr, store_dscr);
 static SYSDEV_ATTR(purr, 0600, show_purr, store_purr);
+
+unsigned long dscr_default = 0;
+EXPORT_SYMBOL(dscr_default);
+
+static ssize_t show_dscr_default(struct sysdev_class *class,
+		struct sysdev_class_attribute *attr, char *buf)
+{
+	return sprintf(buf, "%lx\n", dscr_default);
+}
+
+static ssize_t __used store_dscr_default(struct sysdev_class *class,
+		struct sysdev_class_attribute *attr, const char *buf,
+		size_t count)
+{
+	unsigned long val;
+	int ret = 0;
+	
+	ret = sscanf(buf, "%lx", &val);
+	if (ret != 1)
+		return -EINVAL;
+	dscr_default = val;
+
+	return count;
+}
+
+static SYSDEV_CLASS_ATTR(dscr_default, 0600,
+		show_dscr_default, store_dscr_default);
+
+static void sysfs_create_dscr_default(void)
+{
+	int err = 0;
+	if (cpu_has_feature(CPU_FTR_DSCR))
+		err = sysfs_create_file(&cpu_sysdev_class.kset.kobj,
+			&attr_dscr_default.attr);
+}
 #endif /* CONFIG_PPC64 */
 
 #ifdef HAS_PPC_PMC_PA6T
@@ -617,6 +652,9 @@ 
 		if (cpu_online(cpu))
 			register_cpu_online(cpu);
 	}
+#ifdef CONFIG_PPC64
+	sysfs_create_dscr_default();
+#endif /* CONFIG_PPC64 */
 
 	return 0;
 }
diff -Nuar ../linus-before-dscr/arch/powerpc//kernel/traps.c linus-dscr/arch/powerpc//kernel/traps.c
--- ../linus-before-dscr/arch/powerpc//kernel/traps.c	2010-10-27 14:25:45.000000000 +1100
+++ linus-dscr/arch/powerpc//kernel/traps.c	2011-02-16 16:00:18.000000000 +1100
@@ -919,6 +919,26 @@ 
 		return emulate_isel(regs, instword);
 	}
 
+#ifdef CONFIG_PPC64
+	/* Emulate the mfspr rD, DSCR. */
+	if (((instword & PPC_INST_MFSPR_DSCR_MASK) == PPC_INST_MFSPR_DSCR) &&
+			cpu_has_feature(CPU_FTR_DSCR)) {
+		PPC_WARN_EMULATED(mfdscr, regs);
+		rd = (instword >> 21) & 0x1f;
+		regs->gpr[rd] = mfspr(SPRN_DSCR);
+		return 0;
+	}
+	/* Emulate the mtspr DSCR, rD. */
+	if (((instword & PPC_INST_MTSPR_DSCR_MASK) == PPC_INST_MTSPR_DSCR) &&
+			cpu_has_feature(CPU_FTR_DSCR)) {
+		PPC_WARN_EMULATED(mtdscr, regs);
+		rd = (instword >> 21) & 0x1f;
+		mtspr(SPRN_DSCR, regs->gpr[rd]);
+		current->thread.dscr_inherit = 1;
+		return 0;
+	}
+#endif
+
 	return -EINVAL;
 }
 
@@ -1516,6 +1536,10 @@ 
 #ifdef CONFIG_VSX
 	WARN_EMULATED_SETUP(vsx),
 #endif
+#ifdef CONFIG_PPC64
+	WARN_EMULATED_SETUP(mfdscr),
+	WARN_EMULATED_SETUP(mtdscr),
+#endif
 };
 
 u32 ppc_warn_emulated;