mirror of
https://github.com/edk2-porting/linux-next.git
synced 2024-12-20 11:13:58 +08:00
powerpc: Per process DSCR + some fixes (try#4)
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 be 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 - /sys/devices/system/cpu/dscr_default. If a thread starts with non default value in the sysfs entry, all children threads inherit this non default value even if the sysfs value is changed later. Signed-off-by: Alexey Kardashevskiy <aik@au1.ibm.com> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
This commit is contained in:
parent
f0aae3238f
commit
efcac6589a
@ -52,6 +52,10 @@ extern struct ppc_emulated {
|
||||
#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;
|
||||
|
@ -41,6 +41,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
|
||||
|
@ -238,6 +238,10 @@ struct thread_struct {
|
||||
#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
|
||||
|
@ -74,6 +74,7 @@ int main(void)
|
||||
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 */
|
||||
|
@ -421,6 +421,12 @@ BEGIN_FTR_SECTION
|
||||
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 @@ BEGIN_FTR_SECTION
|
||||
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)
|
||||
|
@ -702,6 +702,8 @@ void prepare_to_copy(struct task_struct *tsk)
|
||||
/*
|
||||
* 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)
|
||||
@ -769,6 +771,20 @@ int copy_thread(unsigned long clone_flags, unsigned long usp,
|
||||
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
|
||||
|
@ -182,6 +182,41 @@ static SYSDEV_ATTR(mmcra, 0600, show_mmcra, store_mmcra);
|
||||
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 @@ static int __init topology_init(void)
|
||||
if (cpu_online(cpu))
|
||||
register_cpu_online(cpu);
|
||||
}
|
||||
#ifdef CONFIG_PPC64
|
||||
sysfs_create_dscr_default();
|
||||
#endif /* CONFIG_PPC64 */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -909,6 +909,26 @@ static int emulate_instruction(struct pt_regs *regs)
|
||||
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;
|
||||
}
|
||||
|
||||
@ -1506,6 +1526,10 @@ struct ppc_emulated ppc_emulated = {
|
||||
#ifdef CONFIG_VSX
|
||||
WARN_EMULATED_SETUP(vsx),
|
||||
#endif
|
||||
#ifdef CONFIG_PPC64
|
||||
WARN_EMULATED_SETUP(mfdscr),
|
||||
WARN_EMULATED_SETUP(mtdscr),
|
||||
#endif
|
||||
};
|
||||
|
||||
u32 ppc_warn_emulated;
|
||||
|
Loading…
Reference in New Issue
Block a user