linux_dsm_epyc7002/arch/arm
Russell King f8f2a8522a ARM: vfp: fix a hole in VFP thread migration
Fix a hole in the VFP thread migration.  Lets define two threads.

Thread 1, we'll call 'interesting_thread' which is a thread which is
running on CPU0, using VFP (so vfp_current_hw_state[0] =
&interesting_thread->vfpstate) and gets migrated off to CPU1, where
it continues execution of VFP instructions.

Thread 2, we'll call 'new_cpu0_thread' which is the thread which takes
over on CPU0.  This has also been using VFP, and last used VFP on CPU0,
but doesn't use it again.

The following code will be executed twice:

		cpu = thread->cpu;

		/*
		 * On SMP, if VFP is enabled, save the old state in
		 * case the thread migrates to a different CPU. The
		 * restoring is done lazily.
		 */
		if ((fpexc & FPEXC_EN) && vfp_current_hw_state[cpu]) {
			vfp_save_state(vfp_current_hw_state[cpu], fpexc);
			vfp_current_hw_state[cpu]->hard.cpu = cpu;
		}
		/*
		 * Thread migration, just force the reloading of the
		 * state on the new CPU in case the VFP registers
		 * contain stale data.
		 */
		if (thread->vfpstate.hard.cpu != cpu)
			vfp_current_hw_state[cpu] = NULL;

The first execution will be on CPU0 to switch away from 'interesting_thread'.
interesting_thread->cpu will be 0.

So, vfp_current_hw_state[0] points at interesting_thread->vfpstate.
The hardware state will be saved, along with the CPU number (0) that
it was executing on.

'thread' will be 'new_cpu0_thread' with new_cpu0_thread->cpu = 0.
Also, because it was executing on CPU0, new_cpu0_thread->vfpstate.hard.cpu = 0,
and so the thread migration check is not triggered.

This means that vfp_current_hw_state[0] remains pointing at interesting_thread.

The second execution will be on CPU1 to switch _to_ 'interesting_thread'.
So, 'thread' will be 'interesting_thread' and interesting_thread->cpu now
will be 1.  The previous thread executing on CPU1 is not relevant to this
so we shall ignore that.

We get to the thread migration check.  Here, we discover that
interesting_thread->vfpstate.hard.cpu = 0, yet interesting_thread->cpu is
now 1, indicating thread migration.  We set vfp_current_hw_state[1] to
NULL.

So, at this point vfp_current_hw_state[] contains the following:

[0] = &interesting_thread->vfpstate
[1] = NULL

Our interesting thread now executes a VFP instruction, takes a fault
which loads the state into the VFP hardware.  Now, through the assembly
we now have:

[0] = &interesting_thread->vfpstate
[1] = &interesting_thread->vfpstate

CPU1 stops due to ptrace (and so saves its VFP state) using the thread
switch code above), and CPU0 calls vfp_sync_hwstate().

	if (vfp_current_hw_state[cpu] == &thread->vfpstate) {
		vfp_save_state(&thread->vfpstate, fpexc | FPEXC_EN);

BANG, we corrupt interesting_thread's VFP state by overwriting the
more up-to-date state saved by CPU1 with the old VFP state from CPU0.

Fix this by ensuring that we have sane semantics for the various state
describing variables:

1. vfp_current_hw_state[] points to the current owner of the context
   information stored in each CPUs hardware, or NULL if that state
   information is invalid.
2. thread->vfpstate.hard.cpu always contains the most recent CPU number
   which the state was loaded into or NR_CPUS if no CPU owns the state.

So, for a particular CPU to be a valid owner of the VFP state for a
particular thread t, two things must be true:

 vfp_current_hw_state[cpu] == &t->vfpstate && t->vfpstate.hard.cpu == cpu.

and that is valid from the moment a CPU loads the saved VFP context
into the hardware.  This gives clear and consistent semantics to
interpreting these variables.

This patch also fixes thread copying, ensuring that t->vfpstate.hard.cpu
is invalidated, otherwise CPU0 may believe it was the last owner.  The
hole can happen thus:

- thread1 runs on CPU2 using VFP, migrates to CPU3, exits and thread_info
  freed.
- New thread allocated from a previously running thread on CPU2, reusing
  memory for thread1 and copying vfp.hard.cpu.

At this point, the following are true:

	new_thread1->vfpstate.hard.cpu == 2
	&new_thread1->vfpstate == vfp_current_hw_state[2]

Lastly, this also addresses thread flushing in a similar way to thread
copying.  Hole is:

- thread runs on CPU0, using VFP, migrates to CPU1 but does not use VFP.
- thread calls execve(), so thread flush happens, leaving
  vfp_current_hw_state[0] intact.  This vfpstate is memset to 0 causing
  thread->vfpstate.hard.cpu = 0.
- thread migrates back to CPU0 before using VFP.

At this point, the following are true:

	thread->vfpstate.hard.cpu == 0
	&thread->vfpstate == vfp_current_hw_state[0]

Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
2011-07-09 17:22:12 +01:00
..
boot ARM: 6961/1: zImage: Add build-time check for correctly-sized proc_type entries 2011-06-21 11:33:20 +01:00
common Merge branch 'for-rmk' of git://git.kernel.org/pub/scm/linux/kernel/git/kgene/linux-samsung into devel-stable 2011-05-25 21:47:48 +01:00
configs rtc: fix build warnings in defconfigs 2011-06-15 20:04:02 -07:00
include/asm ARM: 6959/1: SMP build fix for entry-macro-multi.S 2011-06-17 11:25:03 +01:00
kernel ARM: vfp: fix a hole in VFP thread migration 2011-07-09 17:22:12 +01:00
lib ARM: 6945/1: Add unwinding support for division functions 2011-05-27 22:56:53 +01:00
mach-at91 AT91: Change nand buswidth logic to match hardware default configuration 2011-07-04 23:22:25 +02:00
mach-bcmring ARM: bcmring: convert to use sp804 clockevents 2011-05-23 18:04:54 +01:00
mach-clps711x arm: Fold irq_set_chip/irq_set_handler 2011-03-29 14:47:58 +02:00
mach-cns3xxx
mach-davinci davinci: make PCM platform devices static 2011-06-08 14:41:37 +05:30
mach-dove ARM: dove: Consolidate mpp code with platform mpp. 2011-05-16 15:49:31 -04:00
mach-ebsa110 arm: Fold irq_set_chip/irq_set_handler 2011-03-29 14:47:58 +02:00
mach-ep93xx ep93xx: set DMA masks for the ep93xx_eth 2011-06-11 16:25:15 -07:00
mach-exynos4 Merge branch 'tty-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty-2.6 2011-06-28 11:14:55 -07:00
mach-footbridge ARM: footbridge: fix clock event support 2011-06-11 00:46:17 +01:00
mach-gemini Merge git://git.infradead.org/mtd-2.6 2011-05-27 20:06:53 -07:00
mach-h720x ARM: 6962/1: mach-h720x: fix build error 2011-06-17 11:25:03 +01:00
mach-imx ARM: imx: move mx3 support to mach-imx 2011-05-19 13:11:38 +02:00
mach-integrator Merge branches 'consolidate-clksrc', 'consolidate-flash', 'consolidate-generic', 'consolidate-smp', 'consolidate-stmp' and 'consolidate-zones' into consolidate 2011-05-23 18:05:10 +01:00
mach-iop13xx Fix common misspellings 2011-03-31 11:26:23 -03:00
mach-iop32x ARM: zImage: remove the static qualifier from global data variables 2011-05-07 00:08:02 -04:00
mach-iop33x ARM: zImage: remove the static qualifier from global data variables 2011-05-07 00:08:02 -04:00
mach-ixp4xx Merge git://git.infradead.org/mtd-2.6 2011-05-27 20:06:53 -07:00
mach-ixp23xx arm: Fold irq_set_chip/irq_set_handler 2011-03-29 14:47:58 +02:00
mach-ixp2000 arm: Fold irq_set_chip/irq_set_handler 2011-03-29 14:47:58 +02:00
mach-kirkwood ARM: orion: Refactor the MPP code common in the orion platform 2011-05-16 15:25:54 -04:00
mach-ks8695 arm: Fold irq_set_chip/irq_set_handler 2011-03-29 14:47:58 +02:00
mach-l7200/include/mach
mach-loki ARM: orion: Consolidate ethernet platform data 2011-05-16 15:06:01 -04:00
mach-lpc32xx clocksource: convert ARM 32-bit up counting clocksources 2011-05-23 18:04:51 +01:00
mach-mmp Merge branch 'zImage_fixes' of git://git.linaro.org/people/nico/linux into devel-stable 2011-05-07 08:34:02 +01:00
mach-msm msm: timer: Fix DGT rate on 8960 and 8660 2011-06-20 16:30:07 -07:00
mach-mv78xx0 ARM: orion: Refactor the MPP code common in the orion platform 2011-05-16 15:25:54 -04:00
mach-mx5 ARM: mxc: don't allow to compile together i.MX51 and i.MX53 2011-05-19 13:11:30 +02:00
mach-mxs arm: mxs: include asm/processor.h for cpu_relax() 2011-06-06 09:50:04 +02:00
mach-netx ARM: 6827/1: mach-netx: delete hardcoded periphid 2011-05-26 10:33:34 +01:00
mach-nomadik gpio: move Nomadik GPIO driver to drivers/gpio 2011-05-26 17:30:03 -06:00
mach-nuc93x ARM: zImage: remove the static qualifier from global data variables 2011-05-07 00:08:02 -04:00
mach-omap1 OMAP1: PM: register notifiers with generic clock ops even when !PM_RUNTIME 2011-06-14 05:53:18 -07:00
mach-omap2 Merge branch 'fixes-v3.0-rc3' into devel-fixes 2011-06-14 05:53:42 -07:00
mach-orion5x ARM: orion5x: Refactor mpp code to use common orion platform mpp. 2011-05-16 15:42:59 -04:00
mach-pnx4008 arm: Cleanup the irq namespace 2011-03-29 14:47:57 +02:00
mach-pxa gpio: include linux/gpio.h where needed 2011-06-16 08:40:44 -06:00
mach-realview Merge branches 'consolidate-clksrc', 'consolidate-flash', 'consolidate-generic', 'consolidate-smp', 'consolidate-stmp' and 'consolidate-zones' into consolidate 2011-05-23 18:05:10 +01:00
mach-rpc ARM: zImage: remove the static qualifier from global data variables 2011-05-07 00:08:02 -04:00
mach-s3c24a0/include/mach
mach-s3c64xx Merge branch 'for-rmk' of git://git.kernel.org/pub/scm/linux/kernel/git/kgene/linux-samsung into devel-stable 2011-05-25 21:47:48 +01:00
mach-s3c2400
mach-s3c2410 ARM: S3C2410: remove the now empty mach-s3c2410/irq.c 2011-06-03 18:36:53 -07:00
mach-s3c2412 ARM / Samsung: Use struct syscore_ops for "core" power management 2011-04-24 19:16:10 +02:00
mach-s3c2416 Merge branch 'usb-next' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb-2.6 2011-05-23 12:33:02 -07:00
mach-s3c2440 ARM / Samsung: Use struct syscore_ops for "core" power management 2011-04-24 19:16:10 +02:00
mach-s3c2443 arm: Fold irq_set_chip/irq_set_handler 2011-03-29 14:47:58 +02:00
mach-s5p64x0 ARM: zImage: remove the static qualifier from global data variables 2011-05-07 00:08:02 -04:00
mach-s5pc100 gpio: Move the s5pc100 GPIO to drivers/gpio 2011-05-26 17:33:41 -06:00
mach-s5pv210 ARM: S5PV210: Fix possible null pointer dereference 2011-06-01 15:06:35 -07:00
mach-sa1100 Merge branches 'consolidate-clksrc', 'consolidate-flash', 'consolidate-generic', 'consolidate-smp', 'consolidate-stmp' and 'consolidate-zones' into consolidate 2011-05-23 18:05:10 +01:00
mach-shark ARM: use ARM_DMA_ZONE_SIZE to adjust the zone sizes 2011-05-12 08:36:53 +01:00
mach-shmobile ARM: mach-shmobile: make a struct in board-ap4evb.c static 2011-06-30 14:37:06 +09:00
mach-spear3xx ARM: 6931/1: SPEAr3xx: Rework KConfig to allow all boards to be compiled in 2011-05-20 22:34:25 +01:00
mach-spear6xx ARM: 6934/1: SPEAr6xx: Rework Kconfig for single image solution 2011-05-20 22:34:25 +01:00
mach-tcc8k clocksource: convert ARM 32-bit up counting clocksources 2011-05-23 18:04:51 +01:00
mach-tegra ARM: Tegra: Harmony: Fix conflicting GPIO numbering 2011-06-04 15:51:52 -07:00
mach-u300 ARM: 6949/2: mach-u300: fix compilaton warning in IO accessors 2011-06-09 10:15:06 +01:00
mach-ux500 Merge branch 'tty-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty-2.6 2011-06-28 11:14:55 -07:00
mach-versatile Merge branches 'consolidate-clksrc', 'consolidate-flash', 'consolidate-generic', 'consolidate-smp', 'consolidate-stmp' and 'consolidate-zones' into consolidate 2011-05-23 18:05:10 +01:00
mach-vexpress ARM: 6946/1: vexpress: move v2m clock init to init_early 2011-06-06 10:56:09 +01:00
mach-vt8500 arm: Fold irq_set_chip/irq_set_handler 2011-03-29 14:47:58 +02:00
mach-w90x900 Merge branch 'devel-stable' into for-linus 2011-05-23 19:28:04 +01:00
mm ARM: pm: ensure ARMv7 CPUs save and restore the TLS register 2011-06-24 08:47:09 +01:00
nwfpe
oprofile
plat-iop ARM: 6969/1: plat-iop: fix build error 2011-06-21 11:33:21 +01:00
plat-mxc ARM: mx51/sdma: Check the chip revision in run-time 2011-06-06 09:50:04 +02:00
plat-nomadik gpio/nomadik: fix sleepmode for elder Nomadik 2011-06-09 15:03:38 -06:00
plat-omap Merge branch 'fixes-v3.0-rc3' into devel-fixes 2011-06-14 05:53:42 -07:00
plat-orion Merge branch 'devel-stable' into for-linus 2011-05-23 19:28:04 +01:00
plat-pxa ARM / PXA: Use struct syscore_ops for "core" power management 2011-04-24 19:16:09 +02:00
plat-s3c24xx ARM: S3C24XX: Move s3c24xx_irq_syscore_ops to plat-s3c24xx/irq.c 2011-06-03 18:36:52 -07:00
plat-s5p ARM: SAMSUNG: Remove unused onenand plat functions 2011-06-03 16:45:02 -07:00
plat-samsung Merge branch 'tty-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty-2.6 2011-06-28 11:14:55 -07:00
plat-spear Merge branches 'consolidate', 'ep93xx', 'fixes', 'misc', 'mmci', 'remove' and 'spear' into for-linus 2011-05-23 19:27:40 +01:00
plat-tcc
plat-versatile ARM: consolidate SMP cross call implementation 2011-05-23 16:53:17 +01:00
tools ARM: Update mach-types 2011-05-14 21:36:55 +01:00
vfp ARM: vfp: fix a hole in VFP thread migration 2011-07-09 17:22:12 +01:00
Kconfig Merge branches 'devel', 'devel-stable' and 'fixes' into for-linus 2011-05-27 22:59:57 +01:00
Kconfig-nommu Fix common misspellings 2011-03-31 11:26:23 -03:00
Kconfig.debug lib: consolidate DEBUG_STACK_USAGE option 2011-05-25 08:39:54 -07:00
Makefile Merge branch 'for-rmk' of git://git.kernel.org/pub/scm/linux/kernel/git/kgene/linux-samsung into devel-stable 2011-05-25 21:47:48 +01:00