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:

committed by
Benjamin Herrenschmidt

parent
39a360ef72
commit
1739ea9e13
@@ -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;
|
||||
}
|
||||
|
Reference in New Issue
Block a user