powerpc: Fix regression of per-CPU DSCR setting

Since commit "efcac65 powerpc: Per process DSCR + some fixes (try#4)"
it is no longer possible to set the DSCR on a per-CPU basis.

The old behaviour was to minipulate the DSCR SPR directly but this is no
longer sufficient: the value is quickly overwritten by context switching.

This patch stores the per-CPU DSCR value in a kernel variable rather than
directly in the SPR and it is used whenever a process has not set the DSCR
itself. The sysfs interface (/sys/devices/system/cpu/cpuN/dscr) is unchanged.

Writes to the old global default (/sys/devices/system/cpu/dscr_default)
now set all of the per-CPU values and reads return the last written value.

The new per-CPU default is added to the paca_struct and is used everywhere
outside of sysfs.c instead of the old global default.

Signed-off-by: Sam Bobroff <sam.bobroff@au1.ibm.com>
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
This commit is contained in:
Sam bobroff
2014-05-21 16:32:38 +10:00
committed by Benjamin Herrenschmidt
parent 39a360ef72
commit 1739ea9e13
6 changed files with 29 additions and 35 deletions

View File

@@ -484,7 +484,6 @@ SYSFS_PMCSETUP(pmc8, SPRN_PMC8);
SYSFS_PMCSETUP(mmcra, SPRN_MMCRA);
SYSFS_SPRSETUP(purr, SPRN_PURR);
SYSFS_SPRSETUP(spurr, SPRN_SPURR);
SYSFS_SPRSETUP(dscr, SPRN_DSCR);
SYSFS_SPRSETUP(pir, SPRN_PIR);
/*
@@ -494,12 +493,27 @@ SYSFS_SPRSETUP(pir, SPRN_PIR);
*/
static DEVICE_ATTR(mmcra, 0600, show_mmcra, store_mmcra);
static DEVICE_ATTR(spurr, 0400, show_spurr, NULL);
static DEVICE_ATTR(dscr, 0600, show_dscr, store_dscr);
static DEVICE_ATTR(purr, 0400, show_purr, store_purr);
static DEVICE_ATTR(pir, 0400, show_pir, NULL);
unsigned long dscr_default = 0;
EXPORT_SYMBOL(dscr_default);
static unsigned long dscr_default;
static void read_dscr(void *val)
{
*(unsigned long *)val = get_paca()->dscr_default;
}
static void write_dscr(void *val)
{
get_paca()->dscr_default = *(unsigned long *)val;
if (!current->thread.dscr_inherit) {
current->thread.dscr = *(unsigned long *)val;
mtspr(SPRN_DSCR, *(unsigned long *)val);
}
}
SYSFS_SPRSETUP_SHOW_STORE(dscr);
static DEVICE_ATTR(dscr, 0600, show_dscr, store_dscr);
static void add_write_permission_dev_attr(struct device_attribute *attr)
{
@@ -512,14 +526,6 @@ static ssize_t show_dscr_default(struct device *dev,
return sprintf(buf, "%lx\n", dscr_default);
}
static void update_dscr(void *dummy)
{
if (!current->thread.dscr_inherit) {
current->thread.dscr = dscr_default;
mtspr(SPRN_DSCR, dscr_default);
}
}
static ssize_t __used store_dscr_default(struct device *dev,
struct device_attribute *attr, const char *buf,
size_t count)
@@ -532,7 +538,7 @@ static ssize_t __used store_dscr_default(struct device *dev,
return -EINVAL;
dscr_default = val;
on_each_cpu(update_dscr, NULL, 1);
on_each_cpu(write_dscr, &val, 1);
return count;
}