Message ID | 4D5B62F2.3020709@au1.ibm.com (mailing list archive) |
---|---|
State | Changes Requested |
Delegated to: | Benjamin Herrenschmidt |
Headers | show |
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.
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.
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 :-)
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;