Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1739ea9e authored by Sam bobroff's avatar Sam bobroff Committed by Benjamin Herrenschmidt
Browse files

powerpc: Fix regression of per-CPU DSCR setting



Since commit "efcac658 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: default avatarSam Bobroff <sam.bobroff@au1.ibm.com>
Signed-off-by: default avatarBenjamin Herrenschmidt <benh@kernel.crashing.org>
parent 39a360ef
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -92,7 +92,10 @@ struct paca_struct {
	struct slb_shadow *slb_shadow_ptr;
	struct dtl_entry *dispatch_log;
	struct dtl_entry *dispatch_log_end;
#endif /* CONFIG_PPC_STD_MMU_64 */
	u64 dscr_default;		/* per-CPU default DSCR */

#ifdef CONFIG_PPC_STD_MMU_64
	/*
	 * Now, starting in cacheline 2, the exception save areas
	 */
+1 −0
Original line number Diff line number Diff line
@@ -247,6 +247,7 @@ int main(void)
#endif
	DEFINE(PACAHWCPUID, offsetof(struct paca_struct, hw_cpu_id));
	DEFINE(PACAKEXECSTATE, offsetof(struct paca_struct, kexec_state));
	DEFINE(PACA_DSCR, offsetof(struct paca_struct, dscr_default));
	DEFINE(PACA_STARTTIME, offsetof(struct paca_struct, starttime));
	DEFINE(PACA_STARTTIME_USER, offsetof(struct paca_struct, starttime_user));
	DEFINE(PACA_USER_TIME, offsetof(struct paca_struct, user_time));
+1 −8
Original line number Diff line number Diff line
@@ -387,12 +387,6 @@ _GLOBAL(ret_from_kernel_thread)
	li	r3,0
	b	syscall_exit

	.section	".toc","aw"
DSCR_DEFAULT:
	.tc dscr_default[TC],dscr_default

	.section	".text"

/*
 * This routine switches between two different tasks.  The process
 * state of one is saved on its kernel stack.  Then the state
@@ -577,11 +571,10 @@ END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
#ifdef CONFIG_PPC64
BEGIN_FTR_SECTION
	lwz	r6,THREAD_DSCR_INHERIT(r4)
	ld	r7,DSCR_DEFAULT@toc(2)
	ld	r0,THREAD_DSCR(r4)
	cmpwi	r6,0
	bne	1f
	ld	r0,0(r7)
	ld	r0,PACA_DSCR(r13)
1:
BEGIN_FTR_SECTION_NESTED(70)
	mfspr	r8, SPRN_FSCR
+19 −13
Original line number Diff line number Diff line
@@ -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;
}
+4 −12
Original line number Diff line number Diff line
@@ -78,12 +78,6 @@ _GLOBAL(tm_abort)
	TABORT(R3)
	blr

	.section	".toc","aw"
DSCR_DEFAULT:
	.tc dscr_default[TC],dscr_default

	.section	".text"

/* void tm_reclaim(struct thread_struct *thread,
 *                 unsigned long orig_msr,
 *		   uint8_t cause)
@@ -298,9 +292,8 @@ dont_backup_fp:
	mtlr	r0
	ld	r2, STK_GOT(r1)

	/* Load system default DSCR */
	ld	r4, DSCR_DEFAULT@toc(r2)
	ld	r0, 0(r4)
	/* Load CPU's default DSCR */
	ld	r0, PACA_DSCR(r13)
	mtspr	SPRN_DSCR, r0

	blr
@@ -479,9 +472,8 @@ restore_gprs:
	mtlr	r0
	ld	r2, STK_GOT(r1)

	/* Load system default DSCR */
	ld	r4, DSCR_DEFAULT@toc(r2)
	ld	r0, 0(r4)
	/* Load CPU's default DSCR */
	ld	r0, PACA_DSCR(r13)
	mtspr	SPRN_DSCR, r0

	blr
Loading