From 3a24c754250dd2c58496916e71e3cdd09878a84f Mon Sep 17 00:00:00 2001 From: "Justin M. Forbes" Date: Mon, 20 Aug 2018 06:57:23 -0500 Subject: Linux v4.17.17 --- foreshadow.patch | 10118 ----------------------------------------------------- kernel.spec | 10 +- sources | 2 +- 3 files changed, 6 insertions(+), 10124 deletions(-) delete mode 100644 foreshadow.patch diff --git a/foreshadow.patch b/foreshadow.patch deleted file mode 100644 index fe950eebb..000000000 --- a/foreshadow.patch +++ /dev/null @@ -1,10118 +0,0 @@ -From 66509a276c8c1d19ee3f661a41b418d101c57d29 Mon Sep 17 00:00:00 2001 -From: Helge Deller -Date: Sat, 28 Jul 2018 11:47:17 +0200 -Subject: parisc: Enable CONFIG_MLONGCALLS by default - -From: Helge Deller - -commit 66509a276c8c1d19ee3f661a41b418d101c57d29 upstream. - -Enable the -mlong-calls compiler option by default, because otherwise in most -cases linking the vmlinux binary fails due to truncations of R_PARISC_PCREL22F -relocations. This fixes building the 64-bit defconfig. - -Cc: stable@vger.kernel.org # 4.0+ -Signed-off-by: Helge Deller -Signed-off-by: Greg Kroah-Hartman - ---- - arch/parisc/Kconfig | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/arch/parisc/Kconfig -+++ b/arch/parisc/Kconfig -@@ -199,7 +199,7 @@ config PREFETCH - - config MLONGCALLS - bool "Enable the -mlong-calls compiler option for big kernels" -- def_bool y if (!MODULES) -+ default y - depends on PA8X00 - help - If you configure the kernel to include many drivers built-in instead -From fedb8da96355f5f64353625bf96dc69423ad1826 Mon Sep 17 00:00:00 2001 -From: John David Anglin -Date: Sun, 5 Aug 2018 13:30:31 -0400 -Subject: parisc: Define mb() and add memory barriers to assembler unlock sequences -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -From: John David Anglin - -commit fedb8da96355f5f64353625bf96dc69423ad1826 upstream. - -For years I thought all parisc machines executed loads and stores in -order. However, Jeff Law recently indicated on gcc-patches that this is -not correct. There are various degrees of out-of-order execution all the -way back to the PA7xxx processor series (hit-under-miss). The PA8xxx -series has full out-of-order execution for both integer operations, and -loads and stores. - -This is described in the following article: -http://web.archive.org/web/20040214092531/http://www.cpus.hp.com/technical_references/advperf.shtml - -For this reason, we need to define mb() and to insert a memory barrier -before the store unlocking spinlocks. This ensures that all memory -accesses are complete prior to unlocking. The ldcw instruction performs -the same function on entry. - -Signed-off-by: John David Anglin -Cc: stable@vger.kernel.org # 4.0+ -Signed-off-by: Helge Deller -Signed-off-by: Greg Kroah-Hartman - ---- - arch/parisc/include/asm/barrier.h | 32 ++++++++++++++++++++++++++++++++ - arch/parisc/kernel/entry.S | 2 ++ - arch/parisc/kernel/pacache.S | 1 + - arch/parisc/kernel/syscall.S | 4 ++++ - 4 files changed, 39 insertions(+) - ---- /dev/null -+++ b/arch/parisc/include/asm/barrier.h -@@ -0,0 +1,32 @@ -+/* SPDX-License-Identifier: GPL-2.0 */ -+#ifndef __ASM_BARRIER_H -+#define __ASM_BARRIER_H -+ -+#ifndef __ASSEMBLY__ -+ -+/* The synchronize caches instruction executes as a nop on systems in -+ which all memory references are performed in order. */ -+#define synchronize_caches() __asm__ __volatile__ ("sync" : : : "memory") -+ -+#if defined(CONFIG_SMP) -+#define mb() do { synchronize_caches(); } while (0) -+#define rmb() mb() -+#define wmb() mb() -+#define dma_rmb() mb() -+#define dma_wmb() mb() -+#else -+#define mb() barrier() -+#define rmb() barrier() -+#define wmb() barrier() -+#define dma_rmb() barrier() -+#define dma_wmb() barrier() -+#endif -+ -+#define __smp_mb() mb() -+#define __smp_rmb() mb() -+#define __smp_wmb() mb() -+ -+#include -+ -+#endif /* !__ASSEMBLY__ */ -+#endif /* __ASM_BARRIER_H */ ---- a/arch/parisc/kernel/entry.S -+++ b/arch/parisc/kernel/entry.S -@@ -482,6 +482,8 @@ - .macro tlb_unlock0 spc,tmp - #ifdef CONFIG_SMP - or,COND(=) %r0,\spc,%r0 -+ sync -+ or,COND(=) %r0,\spc,%r0 - stw \spc,0(\tmp) - #endif - .endm ---- a/arch/parisc/kernel/pacache.S -+++ b/arch/parisc/kernel/pacache.S -@@ -353,6 +353,7 @@ ENDPROC_CFI(flush_data_cache_local) - .macro tlb_unlock la,flags,tmp - #ifdef CONFIG_SMP - ldi 1,\tmp -+ sync - stw \tmp,0(\la) - mtsm \flags - #endif ---- a/arch/parisc/kernel/syscall.S -+++ b/arch/parisc/kernel/syscall.S -@@ -633,6 +633,7 @@ cas_action: - sub,<> %r28, %r25, %r0 - 2: stw,ma %r24, 0(%r26) - /* Free lock */ -+ sync - stw,ma %r20, 0(%sr2,%r20) - #if ENABLE_LWS_DEBUG - /* Clear thread register indicator */ -@@ -647,6 +648,7 @@ cas_action: - 3: - /* Error occurred on load or store */ - /* Free lock */ -+ sync - stw %r20, 0(%sr2,%r20) - #if ENABLE_LWS_DEBUG - stw %r0, 4(%sr2,%r20) -@@ -848,6 +850,7 @@ cas2_action: - - cas2_end: - /* Free lock */ -+ sync - stw,ma %r20, 0(%sr2,%r20) - /* Enable interrupts */ - ssm PSW_SM_I, %r0 -@@ -858,6 +861,7 @@ cas2_end: - 22: - /* Error occurred on load or store */ - /* Free lock */ -+ sync - stw %r20, 0(%sr2,%r20) - ssm PSW_SM_I, %r0 - ldo 1(%r0),%r28 -From 3c53776e29f81719efcf8f7a6e30cdf753bee94d Mon Sep 17 00:00:00 2001 -From: Linus Torvalds -Date: Mon, 8 Jan 2018 11:51:04 -0800 -Subject: Mark HI and TASKLET softirq synchronous - -From: Linus Torvalds - -commit 3c53776e29f81719efcf8f7a6e30cdf753bee94d upstream. - -Way back in 4.9, we committed 4cd13c21b207 ("softirq: Let ksoftirqd do -its job"), and ever since we've had small nagging issues with it. For -example, we've had: - - 1ff688209e2e ("watchdog: core: make sure the watchdog_worker is not deferred") - 8d5755b3f77b ("watchdog: softdog: fire watchdog even if softirqs do not get to run") - 217f69743681 ("net: busy-poll: allow preemption in sk_busy_loop()") - -all of which worked around some of the effects of that commit. - -The DVB people have also complained that the commit causes excessive USB -URB latencies, which seems to be due to the USB code using tasklets to -schedule USB traffic. This seems to be an issue mainly when already -living on the edge, but waiting for ksoftirqd to handle it really does -seem to cause excessive latencies. - -Now Hanna Hawa reports that this issue isn't just limited to USB URB and -DVB, but also causes timeout problems for the Marvell SoC team: - - "I'm facing kernel panic issue while running raid 5 on sata disks - connected to Macchiatobin (Marvell community board with Armada-8040 - SoC with 4 ARMv8 cores of CA72) Raid 5 built with Marvell DMA engine - and async_tx mechanism (ASYNC_TX_DMA [=y]); the DMA driver (mv_xor_v2) - uses a tasklet to clean the done descriptors from the queue" - -The latency problem causes a panic: - - mv_xor_v2 f0400000.xor: dma_sync_wait: timeout! - Kernel panic - not syncing: async_tx_quiesce: DMA error waiting for transaction - -We've discussed simply just reverting the original commit entirely, and -also much more involved solutions (with per-softirq threads etc). This -patch is intentionally stupid and fairly limited, because the issue -still remains, and the other solutions either got sidetracked or had -other issues. - -We should probably also consider the timer softirqs to be synchronous -and not be delayed to ksoftirqd (since they were the issue with the -earlier watchdog problems), but that should be done as a separate patch. -This does only the tasklet cases. - -Reported-and-tested-by: Hanna Hawa -Reported-and-tested-by: Josef Griebichler -Reported-by: Mauro Carvalho Chehab -Cc: Alan Stern -Cc: Greg Kroah-Hartman -Cc: Eric Dumazet -Cc: Ingo Molnar -Signed-off-by: Linus Torvalds -Signed-off-by: Greg Kroah-Hartman - ---- - kernel/softirq.c | 12 ++++++++---- - 1 file changed, 8 insertions(+), 4 deletions(-) - ---- a/kernel/softirq.c -+++ b/kernel/softirq.c -@@ -79,12 +79,16 @@ static void wakeup_softirqd(void) - - /* - * If ksoftirqd is scheduled, we do not want to process pending softirqs -- * right now. Let ksoftirqd handle this at its own rate, to get fairness. -+ * right now. Let ksoftirqd handle this at its own rate, to get fairness, -+ * unless we're doing some of the synchronous softirqs. - */ --static bool ksoftirqd_running(void) -+#define SOFTIRQ_NOW_MASK ((1 << HI_SOFTIRQ) | (1 << TASKLET_SOFTIRQ)) -+static bool ksoftirqd_running(unsigned long pending) - { - struct task_struct *tsk = __this_cpu_read(ksoftirqd); - -+ if (pending & SOFTIRQ_NOW_MASK) -+ return false; - return tsk && (tsk->state == TASK_RUNNING); - } - -@@ -329,7 +333,7 @@ asmlinkage __visible void do_softirq(voi - - pending = local_softirq_pending(); - -- if (pending && !ksoftirqd_running()) -+ if (pending && !ksoftirqd_running(pending)) - do_softirq_own_stack(); - - local_irq_restore(flags); -@@ -356,7 +360,7 @@ void irq_enter(void) - - static inline void invoke_softirq(void) - { -- if (ksoftirqd_running()) -+ if (ksoftirqd_running(local_softirq_pending())) - return; - - if (!force_irqthreads) { -From 2610e88946632afb78aa58e61f11368ac4c0af7b Mon Sep 17 00:00:00 2001 -From: "Isaac J. Manjarres" -Date: Tue, 17 Jul 2018 12:35:29 -0700 -Subject: stop_machine: Disable preemption after queueing stopper threads - -From: Isaac J. Manjarres - -commit 2610e88946632afb78aa58e61f11368ac4c0af7b upstream. - -This commit: - - 9fb8d5dc4b64 ("stop_machine, Disable preemption when waking two stopper threads") - -does not fully address the race condition that can occur -as follows: - -On one CPU, call it CPU 3, thread 1 invokes -cpu_stop_queue_two_works(2, 3,...), and the execution is such -that thread 1 queues the works for migration/2 and migration/3, -and is preempted after releasing the locks for migration/2 and -migration/3, but before waking the threads. - -Then, On CPU 2, a kworker, call it thread 2, is running, -and it invokes cpu_stop_queue_two_works(1, 2,...), such that -thread 2 queues the works for migration/1 and migration/2. -Meanwhile, on CPU 3, thread 1 resumes execution, and wakes -migration/2 and migration/3. This means that when CPU 2 -releases the locks for migration/1 and migration/2, but before -it wakes those threads, it can be preempted by migration/2. - -If thread 2 is preempted by migration/2, then migration/2 will -execute the first work item successfully, since migration/3 -was woken up by CPU 3, but when it goes to execute the second -work item, it disables preemption, calls multi_cpu_stop(), -and thus, CPU 2 will wait forever for migration/1, which should -have been woken up by thread 2. However migration/1 cannot be -woken up by thread 2, since it is a kworker, so it is affine to -CPU 2, but CPU 2 is running migration/2 with preemption -disabled, so thread 2 will never run. - -Disable preemption after queueing works for stopper threads -to ensure that the operation of queueing the works and waking -the stopper threads is atomic. - -Co-Developed-by: Prasad Sodagudi -Co-Developed-by: Pavankumar Kondeti -Signed-off-by: Isaac J. Manjarres -Signed-off-by: Prasad Sodagudi -Signed-off-by: Pavankumar Kondeti -Signed-off-by: Peter Zijlstra (Intel) -Cc: Linus Torvalds -Cc: Peter Zijlstra -Cc: Thomas Gleixner -Cc: bigeasy@linutronix.de -Cc: gregkh@linuxfoundation.org -Cc: matt@codeblueprint.co.uk -Fixes: 9fb8d5dc4b64 ("stop_machine, Disable preemption when waking two stopper threads") -Link: http://lkml.kernel.org/r/1531856129-9871-1-git-send-email-isaacm@codeaurora.org -Signed-off-by: Ingo Molnar -Signed-off-by: Greg Kroah-Hartman - ---- - kernel/stop_machine.c | 10 +++++++++- - 1 file changed, 9 insertions(+), 1 deletion(-) - ---- a/kernel/stop_machine.c -+++ b/kernel/stop_machine.c -@@ -260,6 +260,15 @@ retry: - err = 0; - __cpu_stop_queue_work(stopper1, work1, &wakeq); - __cpu_stop_queue_work(stopper2, work2, &wakeq); -+ /* -+ * The waking up of stopper threads has to happen -+ * in the same scheduling context as the queueing. -+ * Otherwise, there is a possibility of one of the -+ * above stoppers being woken up by another CPU, -+ * and preempting us. This will cause us to n ot -+ * wake up the other stopper forever. -+ */ -+ preempt_disable(); - unlock: - raw_spin_unlock(&stopper2->lock); - raw_spin_unlock_irq(&stopper1->lock); -@@ -271,7 +280,6 @@ unlock: - } - - if (!err) { -- preempt_disable(); - wake_up_q(&wakeq); - preempt_enable(); - } -From 840d719604b0925ca23dde95f1767e4528668369 Mon Sep 17 00:00:00 2001 -From: Daniel Bristot de Oliveira -Date: Fri, 20 Jul 2018 11:16:30 +0200 -Subject: sched/deadline: Update rq_clock of later_rq when pushing a task - -From: Daniel Bristot de Oliveira - -commit 840d719604b0925ca23dde95f1767e4528668369 upstream. - -Daniel Casini got this warn while running a DL task here at RetisLab: - - [ 461.137582] ------------[ cut here ]------------ - [ 461.137583] rq->clock_update_flags < RQCF_ACT_SKIP - [ 461.137599] WARNING: CPU: 4 PID: 2354 at kernel/sched/sched.h:967 assert_clock_updated.isra.32.part.33+0x17/0x20 - [a ton of modules] - [ 461.137646] CPU: 4 PID: 2354 Comm: label_image Not tainted 4.18.0-rc4+ #3 - [ 461.137647] Hardware name: ASUS All Series/Z87-K, BIOS 0801 09/02/2013 - [ 461.137649] RIP: 0010:assert_clock_updated.isra.32.part.33+0x17/0x20 - [ 461.137649] Code: ff 48 89 83 08 09 00 00 eb c6 66 0f 1f 84 00 00 00 00 00 55 48 c7 c7 98 7a 6c a5 c6 05 bc 0d 54 01 01 48 89 e5 e8 a9 84 fb ff <0f> 0b 5d c3 0f 1f 44 00 00 0f 1f 44 00 00 83 7e 60 01 74 0a 48 3b - [ 461.137673] RSP: 0018:ffffa77e08cafc68 EFLAGS: 00010082 - [ 461.137674] RAX: 0000000000000000 RBX: ffff8b3fc1702d80 RCX: 0000000000000006 - [ 461.137674] RDX: 0000000000000007 RSI: 0000000000000096 RDI: ffff8b3fded164b0 - [ 461.137675] RBP: ffffa77e08cafc68 R08: 0000000000000026 R09: 0000000000000339 - [ 461.137676] R10: ffff8b3fd060d410 R11: 0000000000000026 R12: ffffffffa4e14e20 - [ 461.137677] R13: ffff8b3fdec22940 R14: ffff8b3fc1702da0 R15: ffff8b3fdec22940 - [ 461.137678] FS: 00007efe43ee5700(0000) GS:ffff8b3fded00000(0000) knlGS:0000000000000000 - [ 461.137679] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 - [ 461.137680] CR2: 00007efe30000010 CR3: 0000000301744003 CR4: 00000000001606e0 - [ 461.137680] Call Trace: - [ 461.137684] push_dl_task.part.46+0x3bc/0x460 - [ 461.137686] task_woken_dl+0x60/0x80 - [ 461.137689] ttwu_do_wakeup+0x4f/0x150 - [ 461.137690] ttwu_do_activate+0x77/0x80 - [ 461.137692] try_to_wake_up+0x1d6/0x4c0 - [ 461.137693] wake_up_q+0x32/0x70 - [ 461.137696] do_futex+0x7e7/0xb50 - [ 461.137698] __x64_sys_futex+0x8b/0x180 - [ 461.137701] do_syscall_64+0x5a/0x110 - [ 461.137703] entry_SYSCALL_64_after_hwframe+0x44/0xa9 - [ 461.137705] RIP: 0033:0x7efe4918ca26 - [ 461.137705] Code: 00 00 00 74 17 49 8b 48 20 44 8b 59 10 41 83 e3 30 41 83 fb 20 74 1e be 85 00 00 00 41 ba 01 00 00 00 41 b9 01 00 00 04 0f 05 <48> 3d 01 f0 ff ff 73 1f 31 c0 c3 be 8c 00 00 00 49 89 c8 4d 31 d2 - [ 461.137738] RSP: 002b:00007efe43ee4928 EFLAGS: 00000283 ORIG_RAX: 00000000000000ca - [ 461.137739] RAX: ffffffffffffffda RBX: 0000000005094df0 RCX: 00007efe4918ca26 - [ 461.137740] RDX: 0000000000000001 RSI: 0000000000000085 RDI: 0000000005094e24 - [ 461.137741] RBP: 00007efe43ee49c0 R08: 0000000005094e20 R09: 0000000004000001 - [ 461.137741] R10: 0000000000000001 R11: 0000000000000283 R12: 0000000000000000 - [ 461.137742] R13: 0000000005094df8 R14: 0000000000000001 R15: 0000000000448a10 - [ 461.137743] ---[ end trace 187df4cad2bf7649 ]--- - -This warning happened in the push_dl_task(), because -__add_running_bw()->cpufreq_update_util() is getting the rq_clock of -the later_rq before its update, which takes place at activate_task(). -The fix then is to update the rq_clock before calling add_running_bw(). - -To avoid double rq_clock_update() call, we set ENQUEUE_NOCLOCK flag to -activate_task(). - -Reported-by: Daniel Casini -Signed-off-by: Daniel Bristot de Oliveira -Signed-off-by: Peter Zijlstra (Intel) -Acked-by: Juri Lelli -Cc: Clark Williams -Cc: Linus Torvalds -Cc: Luca Abeni -Cc: Peter Zijlstra -Cc: Steven Rostedt -Cc: Thomas Gleixner -Cc: Tommaso Cucinotta -Fixes: e0367b12674b sched/deadline: Move CPU frequency selection triggering points -Link: http://lkml.kernel.org/r/ca31d073a4788acf0684a8b255f14fea775ccf20.1532077269.git.bristot@redhat.com -Signed-off-by: Ingo Molnar -Signed-off-by: Greg Kroah-Hartman - ---- - kernel/sched/deadline.c | 8 +++++++- - 1 file changed, 7 insertions(+), 1 deletion(-) - ---- a/kernel/sched/deadline.c -+++ b/kernel/sched/deadline.c -@@ -2090,8 +2090,14 @@ retry: - sub_rq_bw(&next_task->dl, &rq->dl); - set_task_cpu(next_task, later_rq->cpu); - add_rq_bw(&next_task->dl, &later_rq->dl); -+ -+ /* -+ * Update the later_rq clock here, because the clock is used -+ * by the cpufreq_update_util() inside __add_running_bw(). -+ */ -+ update_rq_clock(later_rq); - add_running_bw(&next_task->dl, &later_rq->dl); -- activate_task(later_rq, next_task, 0); -+ activate_task(later_rq, next_task, ENQUEUE_NOCLOCK); - ret = 1; - - resched_curr(later_rq); -From 4f7a7beaee77275671654f7b9f3f9e73ca16ec65 Mon Sep 17 00:00:00 2001 -From: Minchan Kim -Date: Fri, 10 Aug 2018 17:23:10 -0700 -Subject: zram: remove BD_CAP_SYNCHRONOUS_IO with writeback feature - -From: Minchan Kim - -commit 4f7a7beaee77275671654f7b9f3f9e73ca16ec65 upstream. - -If zram supports writeback feature, it's no longer a -BD_CAP_SYNCHRONOUS_IO device beause zram does asynchronous IO operations -for incompressible pages. - -Do not pretend to be synchronous IO device. It makes the system very -sluggish due to waiting for IO completion from upper layers. - -Furthermore, it causes a user-after-free problem because swap thinks the -opearion is done when the IO functions returns so it can free the page -(e.g., lock_page_or_retry and goto out_release in do_swap_page) but in -fact, IO is asynchronous so the driver could access a just freed page -afterward. - -This patch fixes the problem. - - BUG: Bad page state in process qemu-system-x86 pfn:3dfab21 - page:ffffdfb137eac840 count:0 mapcount:0 mapping:0000000000000000 index:0x1 - flags: 0x17fffc000000008(uptodate) - raw: 017fffc000000008 dead000000000100 dead000000000200 0000000000000000 - raw: 0000000000000001 0000000000000000 00000000ffffffff 0000000000000000 - page dumped because: PAGE_FLAGS_CHECK_AT_PREP flag set - bad because of flags: 0x8(uptodate) - CPU: 4 PID: 1039 Comm: qemu-system-x86 Tainted: G B 4.18.0-rc5+ #1 - Hardware name: Supermicro Super Server/X10SRL-F, BIOS 2.0b 05/02/2017 - Call Trace: - dump_stack+0x5c/0x7b - bad_page+0xba/0x120 - get_page_from_freelist+0x1016/0x1250 - __alloc_pages_nodemask+0xfa/0x250 - alloc_pages_vma+0x7c/0x1c0 - do_swap_page+0x347/0x920 - __handle_mm_fault+0x7b4/0x1110 - handle_mm_fault+0xfc/0x1f0 - __get_user_pages+0x12f/0x690 - get_user_pages_unlocked+0x148/0x1f0 - __gfn_to_pfn_memslot+0xff/0x3c0 [kvm] - try_async_pf+0x87/0x230 [kvm] - tdp_page_fault+0x132/0x290 [kvm] - kvm_mmu_page_fault+0x74/0x570 [kvm] - kvm_arch_vcpu_ioctl_run+0x9b3/0x1990 [kvm] - kvm_vcpu_ioctl+0x388/0x5d0 [kvm] - do_vfs_ioctl+0xa2/0x630 - ksys_ioctl+0x70/0x80 - __x64_sys_ioctl+0x16/0x20 - do_syscall_64+0x55/0x100 - entry_SYSCALL_64_after_hwframe+0x44/0xa9 - -Link: https://lore.kernel.org/lkml/0516ae2d-b0fd-92c5-aa92-112ba7bd32fc@contabo.de/ -Link: http://lkml.kernel.org/r/20180802051112.86174-1-minchan@kernel.org -[minchan@kernel.org: fix changelog, add comment] - Link: https://lore.kernel.org/lkml/0516ae2d-b0fd-92c5-aa92-112ba7bd32fc@contabo.de/ - Link: http://lkml.kernel.org/r/20180802051112.86174-1-minchan@kernel.org - Link: http://lkml.kernel.org/r/20180805233722.217347-1-minchan@kernel.org -[akpm@linux-foundation.org: coding-style fixes] -Signed-off-by: Minchan Kim -Reported-by: Tino Lehnig -Tested-by: Tino Lehnig -Cc: Sergey Senozhatsky -Cc: Jens Axboe -Cc: [4.15+] -Signed-off-by: Andrew Morton -Signed-off-by: Linus Torvalds -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/block/zram/zram_drv.c | 15 ++++++++++++++- - 1 file changed, 14 insertions(+), 1 deletion(-) - ---- a/drivers/block/zram/zram_drv.c -+++ b/drivers/block/zram/zram_drv.c -@@ -280,7 +280,8 @@ static void reset_bdev(struct zram *zram - zram->backing_dev = NULL; - zram->old_block_size = 0; - zram->bdev = NULL; -- -+ zram->disk->queue->backing_dev_info->capabilities |= -+ BDI_CAP_SYNCHRONOUS_IO; - kvfree(zram->bitmap); - zram->bitmap = NULL; - } -@@ -382,6 +383,18 @@ static ssize_t backing_dev_store(struct - zram->backing_dev = backing_dev; - zram->bitmap = bitmap; - zram->nr_pages = nr_pages; -+ /* -+ * With writeback feature, zram does asynchronous IO so it's no longer -+ * synchronous device so let's remove synchronous io flag. Othewise, -+ * upper layer(e.g., swap) could wait IO completion rather than -+ * (submit and return), which will cause system sluggish. -+ * Furthermore, when the IO function returns(e.g., swap_readpage), -+ * upper layer expects IO was done so it could deallocate the page -+ * freely but in fact, IO is going on so finally could cause -+ * use-after-free when the IO is really done. -+ */ -+ zram->disk->queue->backing_dev_info->capabilities &= -+ ~BDI_CAP_SYNCHRONOUS_IO; - up_write(&zram->init_lock); - - pr_info("setup backing device %s\n", file_name); -From d472b3a6cf63cd31cae1ed61930f07e6cd6671b5 Mon Sep 17 00:00:00 2001 -From: Juergen Gross -Date: Thu, 9 Aug 2018 16:42:16 +0200 -Subject: xen/netfront: don't cache skb_shinfo() - -From: Juergen Gross - -commit d472b3a6cf63cd31cae1ed61930f07e6cd6671b5 upstream. - -skb_shinfo() can change when calling __pskb_pull_tail(): Don't cache -its return value. - -Cc: stable@vger.kernel.org -Signed-off-by: Juergen Gross -Reviewed-by: Wei Liu -Signed-off-by: David S. Miller -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/net/xen-netfront.c | 8 ++++---- - 1 file changed, 4 insertions(+), 4 deletions(-) - ---- a/drivers/net/xen-netfront.c -+++ b/drivers/net/xen-netfront.c -@@ -894,7 +894,6 @@ static RING_IDX xennet_fill_frags(struct - struct sk_buff *skb, - struct sk_buff_head *list) - { -- struct skb_shared_info *shinfo = skb_shinfo(skb); - RING_IDX cons = queue->rx.rsp_cons; - struct sk_buff *nskb; - -@@ -903,15 +902,16 @@ static RING_IDX xennet_fill_frags(struct - RING_GET_RESPONSE(&queue->rx, ++cons); - skb_frag_t *nfrag = &skb_shinfo(nskb)->frags[0]; - -- if (shinfo->nr_frags == MAX_SKB_FRAGS) { -+ if (skb_shinfo(skb)->nr_frags == MAX_SKB_FRAGS) { - unsigned int pull_to = NETFRONT_SKB_CB(skb)->pull_to; - - BUG_ON(pull_to <= skb_headlen(skb)); - __pskb_pull_tail(skb, pull_to - skb_headlen(skb)); - } -- BUG_ON(shinfo->nr_frags >= MAX_SKB_FRAGS); -+ BUG_ON(skb_shinfo(skb)->nr_frags >= MAX_SKB_FRAGS); - -- skb_add_rx_frag(skb, shinfo->nr_frags, skb_frag_page(nfrag), -+ skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags, -+ skb_frag_page(nfrag), - rx->offset, rx->status, PAGE_SIZE); - - skb_shinfo(nskb)->nr_frags = 0; -From 7c81c71730456845e6212dccbf00098faa66740f Mon Sep 17 00:00:00 2001 -From: Daniel Borkmann -Date: Wed, 8 Aug 2018 19:23:14 +0200 -Subject: bpf, sockmap: fix leak in bpf_tcp_sendmsg wait for mem path - -From: Daniel Borkmann - -commit 7c81c71730456845e6212dccbf00098faa66740f upstream. - -In bpf_tcp_sendmsg() the sk_alloc_sg() may fail. In the case of -ENOMEM, it may also mean that we've partially filled the scatterlist -entries with pages. Later jumping to sk_stream_wait_memory() -we could further fail with an error for several reasons, however -we miss to call free_start_sg() if the local sk_msg_buff was used. - -Fixes: 4f738adba30a ("bpf: create tcp_bpf_ulp allowing BPF to monitor socket TX/RX data") -Signed-off-by: Daniel Borkmann -Acked-by: John Fastabend -Signed-off-by: Alexei Starovoitov -Signed-off-by: Greg Kroah-Hartman - ---- - kernel/bpf/sockmap.c | 7 +++++-- - 1 file changed, 5 insertions(+), 2 deletions(-) - ---- a/kernel/bpf/sockmap.c -+++ b/kernel/bpf/sockmap.c -@@ -947,7 +947,7 @@ static int bpf_tcp_sendmsg(struct sock * - timeo = sock_sndtimeo(sk, msg->msg_flags & MSG_DONTWAIT); - - while (msg_data_left(msg)) { -- struct sk_msg_buff *m; -+ struct sk_msg_buff *m = NULL; - bool enospc = false; - int copy; - -@@ -1015,8 +1015,11 @@ wait_for_sndbuf: - set_bit(SOCK_NOSPACE, &sk->sk_socket->flags); - wait_for_memory: - err = sk_stream_wait_memory(sk, &timeo); -- if (err) -+ if (err) { -+ if (m && m != psock->cork) -+ free_start_sg(sk, m); - goto out_err; -+ } - } - out_err: - if (err < 0) -From 5121700b346b6160ccc9411194e3f1f417c340d1 Mon Sep 17 00:00:00 2001 -From: Daniel Borkmann -Date: Wed, 8 Aug 2018 19:23:13 +0200 -Subject: bpf, sockmap: fix bpf_tcp_sendmsg sock error handling - -From: Daniel Borkmann - -commit 5121700b346b6160ccc9411194e3f1f417c340d1 upstream. - -While working on bpf_tcp_sendmsg() code, I noticed that when a -sk->sk_err is set we error out with err = sk->sk_err. However -this is problematic since sk->sk_err is a positive error value -and therefore we will neither go into sk_stream_error() nor will -we report an error back to user space. I had this case with EPIPE -and user space was thinking sendmsg() succeeded since EPIPE is -a positive value, thinking we submitted 32 bytes. Fix it by -negating the sk->sk_err value. - -Fixes: 4f738adba30a ("bpf: create tcp_bpf_ulp allowing BPF to monitor socket TX/RX data") -Signed-off-by: Daniel Borkmann -Acked-by: John Fastabend -Signed-off-by: Alexei Starovoitov -Signed-off-by: Greg Kroah-Hartman - ---- - kernel/bpf/sockmap.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/kernel/bpf/sockmap.c -+++ b/kernel/bpf/sockmap.c -@@ -952,7 +952,7 @@ static int bpf_tcp_sendmsg(struct sock * - int copy; - - if (sk->sk_err) { -- err = sk->sk_err; -+ err = -sk->sk_err; - goto out_err; - } - -From 1214fd7b497400d200e3f4e64e2338b303a20949 Mon Sep 17 00:00:00 2001 -From: Bart Van Assche -Date: Thu, 2 Aug 2018 10:44:42 -0700 -Subject: scsi: sr: Avoid that opening a CD-ROM hangs with runtime power management enabled - -From: Bart Van Assche - -commit 1214fd7b497400d200e3f4e64e2338b303a20949 upstream. - -Surround scsi_execute() calls with scsi_autopm_get_device() and -scsi_autopm_put_device(). Note: removing sr_mutex protection from the -scsi_cd_get() and scsi_cd_put() calls is safe because the purpose of -sr_mutex is to serialize cdrom_*() calls. - -This patch avoids that complaints similar to the following appear in the -kernel log if runtime power management is enabled: - -INFO: task systemd-udevd:650 blocked for more than 120 seconds. - Not tainted 4.18.0-rc7-dbg+ #1 -"echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message. -systemd-udevd D28176 650 513 0x00000104 -Call Trace: -__schedule+0x444/0xfe0 -schedule+0x4e/0xe0 -schedule_preempt_disabled+0x18/0x30 -__mutex_lock+0x41c/0xc70 -mutex_lock_nested+0x1b/0x20 -__blkdev_get+0x106/0x970 -blkdev_get+0x22c/0x5a0 -blkdev_open+0xe9/0x100 -do_dentry_open.isra.19+0x33e/0x570 -vfs_open+0x7c/0xd0 -path_openat+0x6e3/0x1120 -do_filp_open+0x11c/0x1c0 -do_sys_open+0x208/0x2d0 -__x64_sys_openat+0x59/0x70 -do_syscall_64+0x77/0x230 -entry_SYSCALL_64_after_hwframe+0x49/0xbe - -Signed-off-by: Bart Van Assche -Cc: Maurizio Lombardi -Cc: Johannes Thumshirn -Cc: Alan Stern -Cc: -Tested-by: Johannes Thumshirn -Reviewed-by: Johannes Thumshirn -Signed-off-by: Martin K. Petersen -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/scsi/sr.c | 29 +++++++++++++++++++++-------- - 1 file changed, 21 insertions(+), 8 deletions(-) - ---- a/drivers/scsi/sr.c -+++ b/drivers/scsi/sr.c -@@ -523,18 +523,26 @@ static int sr_init_command(struct scsi_c - static int sr_block_open(struct block_device *bdev, fmode_t mode) - { - struct scsi_cd *cd; -+ struct scsi_device *sdev; - int ret = -ENXIO; - -+ cd = scsi_cd_get(bdev->bd_disk); -+ if (!cd) -+ goto out; -+ -+ sdev = cd->device; -+ scsi_autopm_get_device(sdev); - check_disk_change(bdev); - - mutex_lock(&sr_mutex); -- cd = scsi_cd_get(bdev->bd_disk); -- if (cd) { -- ret = cdrom_open(&cd->cdi, bdev, mode); -- if (ret) -- scsi_cd_put(cd); -- } -+ ret = cdrom_open(&cd->cdi, bdev, mode); - mutex_unlock(&sr_mutex); -+ -+ scsi_autopm_put_device(sdev); -+ if (ret) -+ scsi_cd_put(cd); -+ -+out: - return ret; - } - -@@ -562,6 +570,8 @@ static int sr_block_ioctl(struct block_d - if (ret) - goto out; - -+ scsi_autopm_get_device(sdev); -+ - /* - * Send SCSI addressing ioctls directly to mid level, send other - * ioctls to cdrom/block level. -@@ -570,15 +580,18 @@ static int sr_block_ioctl(struct block_d - case SCSI_IOCTL_GET_IDLUN: - case SCSI_IOCTL_GET_BUS_NUMBER: - ret = scsi_ioctl(sdev, cmd, argp); -- goto out; -+ goto put; - } - - ret = cdrom_ioctl(&cd->cdi, bdev, mode, cmd, arg); - if (ret != -ENOSYS) -- goto out; -+ goto put; - - ret = scsi_ioctl(sdev, cmd, argp); - -+put: -+ scsi_autopm_put_device(sdev); -+ - out: - mutex_unlock(&sr_mutex); - return ret; -From 5e53be8e476a3397ed5383c23376f299555a2b43 Mon Sep 17 00:00:00 2001 -From: Quinn Tran -Date: Thu, 26 Jul 2018 16:34:44 -0700 -Subject: scsi: qla2xxx: Fix memory leak for allocating abort IOCB - -From: Quinn Tran - -commit 5e53be8e476a3397ed5383c23376f299555a2b43 upstream. - -In the case of IOCB QFull, Initiator code can leave behind a stale pointer -to an SRB structure on the outstanding command array. - -Fixes: 82de802ad46e ("scsi: qla2xxx: Preparation for Target MQ.") -Cc: stable@vger.kernel.org #v4.16+ -Signed-off-by: Quinn Tran -Signed-off-by: Himanshu Madhani -Signed-off-by: Martin K. Petersen -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/scsi/qla2xxx/qla_iocb.c | 53 ++++++++++++++++++++-------------------- - 1 file changed, 27 insertions(+), 26 deletions(-) - ---- a/drivers/scsi/qla2xxx/qla_iocb.c -+++ b/drivers/scsi/qla2xxx/qla_iocb.c -@@ -2130,34 +2130,11 @@ __qla2x00_alloc_iocbs(struct qla_qpair * - req_cnt = 1; - handle = 0; - -- if (!sp) -- goto skip_cmd_array; -- -- /* Check for room in outstanding command list. */ -- handle = req->current_outstanding_cmd; -- for (index = 1; index < req->num_outstanding_cmds; index++) { -- handle++; -- if (handle == req->num_outstanding_cmds) -- handle = 1; -- if (!req->outstanding_cmds[handle]) -- break; -- } -- if (index == req->num_outstanding_cmds) { -- ql_log(ql_log_warn, vha, 0x700b, -- "No room on outstanding cmd array.\n"); -- goto queuing_error; -- } -- -- /* Prep command array. */ -- req->current_outstanding_cmd = handle; -- req->outstanding_cmds[handle] = sp; -- sp->handle = handle; -- -- /* Adjust entry-counts as needed. */ -- if (sp->type != SRB_SCSI_CMD) -+ if (sp && (sp->type != SRB_SCSI_CMD)) { -+ /* Adjust entry-counts as needed. */ - req_cnt = sp->iocbs; -+ } - --skip_cmd_array: - /* Check for room on request queue. */ - if (req->cnt < req_cnt + 2) { - if (qpair->use_shadow_reg) -@@ -2183,6 +2160,28 @@ skip_cmd_array: - if (req->cnt < req_cnt + 2) - goto queuing_error; - -+ if (sp) { -+ /* Check for room in outstanding command list. */ -+ handle = req->current_outstanding_cmd; -+ for (index = 1; index < req->num_outstanding_cmds; index++) { -+ handle++; -+ if (handle == req->num_outstanding_cmds) -+ handle = 1; -+ if (!req->outstanding_cmds[handle]) -+ break; -+ } -+ if (index == req->num_outstanding_cmds) { -+ ql_log(ql_log_warn, vha, 0x700b, -+ "No room on outstanding cmd array.\n"); -+ goto queuing_error; -+ } -+ -+ /* Prep command array. */ -+ req->current_outstanding_cmd = handle; -+ req->outstanding_cmds[handle] = sp; -+ sp->handle = handle; -+ } -+ - /* Prep packet */ - req->cnt -= req_cnt; - pkt = req->ring_ptr; -@@ -2195,6 +2194,8 @@ skip_cmd_array: - pkt->handle = handle; - } - -+ return pkt; -+ - queuing_error: - qpair->tgt_counters.num_alloc_iocb_failed++; - return pkt; -From b5b1404d0815894de0690de8a1ab58269e56eae6 Mon Sep 17 00:00:00 2001 -From: Linus Torvalds -Date: Sun, 12 Aug 2018 12:19:42 -0700 -Subject: init: rename and re-order boot_cpu_state_init() - -From: Linus Torvalds - -commit b5b1404d0815894de0690de8a1ab58269e56eae6 upstream. - -This is purely a preparatory patch for upcoming changes during the 4.19 -merge window. - -We have a function called "boot_cpu_state_init()" that isn't really -about the bootup cpu state: that is done much earlier by the similarly -named "boot_cpu_init()" (note lack of "state" in name). - -This function initializes some hotplug CPU state, and needs to run after -the percpu data has been properly initialized. It even has a comment to -that effect. - -Except it _doesn't_ actually run after the percpu data has been properly -initialized. On x86 it happens to do that, but on at least arm and -arm64, the percpu base pointers are initialized by the arch-specific -'smp_prepare_boot_cpu()' hook, which ran _after_ boot_cpu_state_init(). - -This had some unexpected results, and in particular we have a patch -pending for the merge window that did the obvious cleanup of using -'this_cpu_write()' in the cpu hotplug init code: - - - per_cpu_ptr(&cpuhp_state, smp_processor_id())->state = CPUHP_ONLINE; - + this_cpu_write(cpuhp_state.state, CPUHP_ONLINE); - -which is obviously the right thing to do. Except because of the -ordering issue, it actually failed miserably and unexpectedly on arm64. - -So this just fixes the ordering, and changes the name of the function to -be 'boot_cpu_hotplug_init()' to make it obvious that it's about cpu -hotplug state, because the core CPU state was supposed to have already -been done earlier. - -Marked for stable, since the (not yet merged) patch that will show this -problem is marked for stable. - -Reported-by: Vlastimil Babka -Reported-by: Mian Yousaf Kaukab -Suggested-by: Catalin Marinas -Acked-by: Thomas Gleixner -Cc: Will Deacon -Cc: stable@kernel.org -Signed-off-by: Linus Torvalds -Signed-off-by: Greg Kroah-Hartman - ---- - include/linux/cpu.h | 2 +- - init/main.c | 2 +- - kernel/cpu.c | 2 +- - 3 files changed, 3 insertions(+), 3 deletions(-) - ---- a/include/linux/cpu.h -+++ b/include/linux/cpu.h -@@ -30,7 +30,7 @@ struct cpu { - }; - - extern void boot_cpu_init(void); --extern void boot_cpu_state_init(void); -+extern void boot_cpu_hotplug_init(void); - extern void cpu_init(void); - extern void trap_init(void); - ---- a/init/main.c -+++ b/init/main.c -@@ -561,8 +561,8 @@ asmlinkage __visible void __init start_k - setup_command_line(command_line); - setup_nr_cpu_ids(); - setup_per_cpu_areas(); -- boot_cpu_state_init(); - smp_prepare_boot_cpu(); /* arch-specific boot-cpu hooks */ -+ boot_cpu_hotplug_init(); - - build_all_zonelists(NULL); - page_alloc_init(); ---- a/kernel/cpu.c -+++ b/kernel/cpu.c -@@ -2010,7 +2010,7 @@ void __init boot_cpu_init(void) - /* - * Must be called _AFTER_ setting up the per_cpu areas - */ --void __init boot_cpu_state_init(void) -+void __init boot_cpu_hotplug_init(void) - { - per_cpu_ptr(&cpuhp_state, smp_processor_id())->state = CPUHP_ONLINE; - } -From 90bad5e05bcdb0308cfa3d3a60f5c0b9c8e2efb3 Mon Sep 17 00:00:00 2001 -From: Al Viro -Date: Mon, 6 Aug 2018 09:03:58 -0400 -Subject: root dentries need RCU-delayed freeing - -From: Al Viro - -commit 90bad5e05bcdb0308cfa3d3a60f5c0b9c8e2efb3 upstream. - -Since mountpoint crossing can happen without leaving lazy mode, -root dentries do need the same protection against having their -memory freed without RCU delay as everything else in the tree. - -It's partially hidden by RCU delay between detaching from the -mount tree and dropping the vfsmount reference, but the starting -point of pathwalk can be on an already detached mount, in which -case umount-caused RCU delay has already passed by the time the -lazy pathwalk grabs rcu_read_lock(). If the starting point -happens to be at the root of that vfsmount *and* that vfsmount -covers the entire filesystem, we get trouble. - -Fixes: 48a066e72d97 ("RCU'd vsfmounts") -Cc: stable@vger.kernel.org -Signed-off-by: Al Viro -Signed-off-by: Greg Kroah-Hartman - ---- - fs/dcache.c | 6 ++++-- - 1 file changed, 4 insertions(+), 2 deletions(-) - ---- a/fs/dcache.c -+++ b/fs/dcache.c -@@ -1954,10 +1954,12 @@ struct dentry *d_make_root(struct inode - - if (root_inode) { - res = d_alloc_anon(root_inode->i_sb); -- if (res) -+ if (res) { -+ res->d_flags |= DCACHE_RCUACCESS; - d_instantiate(res, root_inode); -- else -+ } else { - iput(root_inode); -+ } - } - return res; - } -From 4c0d7cd5c8416b1ef41534d19163cb07ffaa03ab Mon Sep 17 00:00:00 2001 -From: Al Viro -Date: Thu, 9 Aug 2018 10:15:54 -0400 -Subject: make sure that __dentry_kill() always invalidates d_seq, unhashed or not - -From: Al Viro - -commit 4c0d7cd5c8416b1ef41534d19163cb07ffaa03ab upstream. - -RCU pathwalk relies upon the assumption that anything that changes -->d_inode of a dentry will invalidate its ->d_seq. That's almost -true - the one exception is that the final dput() of already unhashed -dentry does *not* touch ->d_seq at all. Unhashing does, though, -so for anything we'd found by RCU dcache lookup we are fine. -Unfortunately, we can *start* with an unhashed dentry or jump into -it. - -We could try and be careful in the (few) places where that could -happen. Or we could just make the final dput() invalidate the damn -thing, unhashed or not. The latter is much simpler and easier to -backport, so let's do it that way. - -Reported-by: "Dae R. Jeong" -Cc: stable@vger.kernel.org -Signed-off-by: Al Viro -Signed-off-by: Greg Kroah-Hartman - ---- - fs/dcache.c | 7 ++----- - 1 file changed, 2 insertions(+), 5 deletions(-) - ---- a/fs/dcache.c -+++ b/fs/dcache.c -@@ -358,14 +358,11 @@ static void dentry_unlink_inode(struct d - __releases(dentry->d_inode->i_lock) - { - struct inode *inode = dentry->d_inode; -- bool hashed = !d_unhashed(dentry); - -- if (hashed) -- raw_write_seqcount_begin(&dentry->d_seq); -+ raw_write_seqcount_begin(&dentry->d_seq); - __d_clear_type_and_inode(dentry); - hlist_del_init(&dentry->d_u.d_alias); -- if (hashed) -- raw_write_seqcount_end(&dentry->d_seq); -+ raw_write_seqcount_end(&dentry->d_seq); - spin_unlock(&dentry->d_lock); - spin_unlock(&inode->i_lock); - if (!inode->i_nlink) -From 9ea0a46ca2c318fcc449c1e6b62a7230a17888f1 Mon Sep 17 00:00:00 2001 -From: Al Viro -Date: Thu, 9 Aug 2018 17:21:17 -0400 -Subject: fix mntput/mntput race - -From: Al Viro - -commit 9ea0a46ca2c318fcc449c1e6b62a7230a17888f1 upstream. - -mntput_no_expire() does the calculation of total refcount under mount_lock; -unfortunately, the decrement (as well as all increments) are done outside -of it, leading to false positives in the "are we dropping the last reference" -test. Consider the following situation: - * mnt is a lazy-umounted mount, kept alive by two opened files. One -of those files gets closed. Total refcount of mnt is 2. On CPU 42 -mntput(mnt) (called from __fput()) drops one reference, decrementing component - * After it has looked at component #0, the process on CPU 0 does -mntget(), incrementing component #0, gets preempted and gets to run again - -on CPU 69. There it does mntput(), which drops the reference (component #69) -and proceeds to spin on mount_lock. - * On CPU 42 our first mntput() finishes counting. It observes the -decrement of component #69, but not the increment of component #0. As the -result, the total it gets is not 1 as it should've been - it's 0. At which -point we decide that vfsmount needs to be killed and proceed to free it and -shut the filesystem down. However, there's still another opened file -on that filesystem, with reference to (now freed) vfsmount, etc. and we are -screwed. - -It's not a wide race, but it can be reproduced with artificial slowdown of -the mnt_get_count() loop, and it should be easier to hit on SMP KVM setups. - -Fix consists of moving the refcount decrement under mount_lock; the tricky -part is that we want (and can) keep the fast case (i.e. mount that still -has non-NULL ->mnt_ns) entirely out of mount_lock. All places that zero -mnt->mnt_ns are dropping some reference to mnt and they call synchronize_rcu() -before that mntput(). IOW, if mntput() observes (under rcu_read_lock()) -a non-NULL ->mnt_ns, it is guaranteed that there is another reference yet to -be dropped. - -Reported-by: Jann Horn -Tested-by: Jann Horn -Fixes: 48a066e72d97 ("RCU'd vsfmounts") -Cc: stable@vger.kernel.org -Signed-off-by: Al Viro -Signed-off-by: Greg Kroah-Hartman - ---- - fs/namespace.c | 14 ++++++++++++-- - 1 file changed, 12 insertions(+), 2 deletions(-) - ---- a/fs/namespace.c -+++ b/fs/namespace.c -@@ -1195,12 +1195,22 @@ static DECLARE_DELAYED_WORK(delayed_mntp - static void mntput_no_expire(struct mount *mnt) - { - rcu_read_lock(); -- mnt_add_count(mnt, -1); -- if (likely(mnt->mnt_ns)) { /* shouldn't be the last one */ -+ if (likely(READ_ONCE(mnt->mnt_ns))) { -+ /* -+ * Since we don't do lock_mount_hash() here, -+ * ->mnt_ns can change under us. However, if it's -+ * non-NULL, then there's a reference that won't -+ * be dropped until after an RCU delay done after -+ * turning ->mnt_ns NULL. So if we observe it -+ * non-NULL under rcu_read_lock(), the reference -+ * we are dropping is not the final one. -+ */ -+ mnt_add_count(mnt, -1); - rcu_read_unlock(); - return; - } - lock_mount_hash(); -+ mnt_add_count(mnt, -1); - if (mnt_get_count(mnt)) { - rcu_read_unlock(); - unlock_mount_hash(); -From 119e1ef80ecfe0d1deb6378d4ab41f5b71519de1 Mon Sep 17 00:00:00 2001 -From: Al Viro -Date: Thu, 9 Aug 2018 17:51:32 -0400 -Subject: fix __legitimize_mnt()/mntput() race - -From: Al Viro - -commit 119e1ef80ecfe0d1deb6378d4ab41f5b71519de1 upstream. - -__legitimize_mnt() has two problems - one is that in case of success -the check of mount_lock is not ordered wrt preceding increment of -refcount, making it possible to have successful __legitimize_mnt() -on one CPU just before the otherwise final mntpu() on another, -with __legitimize_mnt() not seeing mntput() taking the lock and -mntput() not seeing the increment done by __legitimize_mnt(). -Solved by a pair of barriers. - -Another is that failure of __legitimize_mnt() on the second -read_seqretry() leaves us with reference that'll need to be -dropped by caller; however, if that races with final mntput() -we can end up with caller dropping rcu_read_lock() and doing -mntput() to release that reference - with the first mntput() -having freed the damn thing just as rcu_read_lock() had been -dropped. Solution: in "do mntput() yourself" failure case -grab mount_lock, check if MNT_DOOMED has been set by racing -final mntput() that has missed our increment and if it has - -undo the increment and treat that as "failure, caller doesn't -need to drop anything" case. - -It's not easy to hit - the final mntput() has to come right -after the first read_seqretry() in __legitimize_mnt() *and* -manage to miss the increment done by __legitimize_mnt() before -the second read_seqretry() in there. The things that are almost -impossible to hit on bare hardware are not impossible on SMP -KVM, though... - -Reported-by: Oleg Nesterov -Fixes: 48a066e72d97 ("RCU'd vsfmounts") -Cc: stable@vger.kernel.org -Signed-off-by: Al Viro -Signed-off-by: Greg Kroah-Hartman - ---- - fs/namespace.c | 14 ++++++++++++++ - 1 file changed, 14 insertions(+) - ---- a/fs/namespace.c -+++ b/fs/namespace.c -@@ -659,12 +659,21 @@ int __legitimize_mnt(struct vfsmount *ba - return 0; - mnt = real_mount(bastard); - mnt_add_count(mnt, 1); -+ smp_mb(); // see mntput_no_expire() - if (likely(!read_seqretry(&mount_lock, seq))) - return 0; - if (bastard->mnt_flags & MNT_SYNC_UMOUNT) { - mnt_add_count(mnt, -1); - return 1; - } -+ lock_mount_hash(); -+ if (unlikely(bastard->mnt_flags & MNT_DOOMED)) { -+ mnt_add_count(mnt, -1); -+ unlock_mount_hash(); -+ return 1; -+ } -+ unlock_mount_hash(); -+ /* caller will mntput() */ - return -1; - } - -@@ -1210,6 +1219,11 @@ static void mntput_no_expire(struct moun - return; - } - lock_mount_hash(); -+ /* -+ * make sure that if __legitimize_mnt() has not seen us grab -+ * mount_lock, we'll see their refcount increment here. -+ */ -+ smp_mb(); - mnt_add_count(mnt, -1); - if (mnt_get_count(mnt)) { - rcu_read_unlock(); -From 1bcfe0564044be578841744faea1c2f46adc8178 Mon Sep 17 00:00:00 2001 -From: Oleksij Rempel -Date: Fri, 15 Jun 2018 09:41:29 +0200 -Subject: ARM: dts: imx6sx: fix irq for pcie bridge - -From: Oleksij Rempel - -commit 1bcfe0564044be578841744faea1c2f46adc8178 upstream. - -Use the correct IRQ line for the MSI controller in the PCIe host -controller. Apparently a different IRQ line is used compared to other -i.MX6 variants. Without this change MSI IRQs aren't properly propagated -to the upstream interrupt controller. - -Signed-off-by: Oleksij Rempel -Reviewed-by: Lucas Stach -Fixes: b1d17f68e5c5 ("ARM: dts: imx: add initial imx6sx device tree source") -Signed-off-by: Shawn Guo -Signed-off-by: Amit Pundir -Signed-off-by: Greg Kroah-Hartman - ---- - arch/arm/boot/dts/imx6sx.dtsi | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/arch/arm/boot/dts/imx6sx.dtsi -+++ b/arch/arm/boot/dts/imx6sx.dtsi -@@ -1351,7 +1351,7 @@ - ranges = <0x81000000 0 0 0x08f80000 0 0x00010000 /* downstream I/O */ - 0x82000000 0 0x08000000 0x08000000 0 0x00f00000>; /* non-prefetchable memory */ - num-lanes = <1>; -- interrupts = ; -+ interrupts = ; - interrupt-names = "msi"; - #interrupt-cells = <1>; - interrupt-map-mask = <0 0 0 0x7>; -From 5800dc5c19f34e6e03b5adab1282535cb102fafd Mon Sep 17 00:00:00 2001 -From: Peter Zijlstra -Date: Fri, 3 Aug 2018 16:41:39 +0200 -Subject: x86/paravirt: Fix spectre-v2 mitigations for paravirt guests - -From: Peter Zijlstra - -commit 5800dc5c19f34e6e03b5adab1282535cb102fafd upstream. - -Nadav reported that on guests we're failing to rewrite the indirect -calls to CALLEE_SAVE paravirt functions. In particular the -pv_queued_spin_unlock() call is left unpatched and that is all over the -place. This obviously wrecks Spectre-v2 mitigation (for paravirt -guests) which relies on not actually having indirect calls around. - -The reason is an incorrect clobber test in paravirt_patch_call(); this -function rewrites an indirect call with a direct call to the _SAME_ -function, there is no possible way the clobbers can be different -because of this. - -Therefore remove this clobber check. Also put WARNs on the other patch -failure case (not enough room for the instruction) which I've not seen -trigger in my (limited) testing. - -Three live kernel image disassemblies for lock_sock_nested (as a small -function that illustrates the problem nicely). PRE is the current -situation for guests, POST is with this patch applied and NATIVE is with -or without the patch for !guests. - -PRE: - -(gdb) disassemble lock_sock_nested -Dump of assembler code for function lock_sock_nested: - 0xffffffff817be970 <+0>: push %rbp - 0xffffffff817be971 <+1>: mov %rdi,%rbp - 0xffffffff817be974 <+4>: push %rbx - 0xffffffff817be975 <+5>: lea 0x88(%rbp),%rbx - 0xffffffff817be97c <+12>: callq 0xffffffff819f7160 <_cond_resched> - 0xffffffff817be981 <+17>: mov %rbx,%rdi - 0xffffffff817be984 <+20>: callq 0xffffffff819fbb00 <_raw_spin_lock_bh> - 0xffffffff817be989 <+25>: mov 0x8c(%rbp),%eax - 0xffffffff817be98f <+31>: test %eax,%eax - 0xffffffff817be991 <+33>: jne 0xffffffff817be9ba - 0xffffffff817be993 <+35>: movl $0x1,0x8c(%rbp) - 0xffffffff817be99d <+45>: mov %rbx,%rdi - 0xffffffff817be9a0 <+48>: callq *0xffffffff822299e8 - 0xffffffff817be9a7 <+55>: pop %rbx - 0xffffffff817be9a8 <+56>: pop %rbp - 0xffffffff817be9a9 <+57>: mov $0x200,%esi - 0xffffffff817be9ae <+62>: mov $0xffffffff817be993,%rdi - 0xffffffff817be9b5 <+69>: jmpq 0xffffffff81063ae0 <__local_bh_enable_ip> - 0xffffffff817be9ba <+74>: mov %rbp,%rdi - 0xffffffff817be9bd <+77>: callq 0xffffffff817be8c0 <__lock_sock> - 0xffffffff817be9c2 <+82>: jmp 0xffffffff817be993 -End of assembler dump. - -POST: - -(gdb) disassemble lock_sock_nested -Dump of assembler code for function lock_sock_nested: - 0xffffffff817be970 <+0>: push %rbp - 0xffffffff817be971 <+1>: mov %rdi,%rbp - 0xffffffff817be974 <+4>: push %rbx - 0xffffffff817be975 <+5>: lea 0x88(%rbp),%rbx - 0xffffffff817be97c <+12>: callq 0xffffffff819f7160 <_cond_resched> - 0xffffffff817be981 <+17>: mov %rbx,%rdi - 0xffffffff817be984 <+20>: callq 0xffffffff819fbb00 <_raw_spin_lock_bh> - 0xffffffff817be989 <+25>: mov 0x8c(%rbp),%eax - 0xffffffff817be98f <+31>: test %eax,%eax - 0xffffffff817be991 <+33>: jne 0xffffffff817be9ba - 0xffffffff817be993 <+35>: movl $0x1,0x8c(%rbp) - 0xffffffff817be99d <+45>: mov %rbx,%rdi - 0xffffffff817be9a0 <+48>: callq 0xffffffff810a0c20 <__raw_callee_save___pv_queued_spin_unlock> - 0xffffffff817be9a5 <+53>: xchg %ax,%ax - 0xffffffff817be9a7 <+55>: pop %rbx - 0xffffffff817be9a8 <+56>: pop %rbp - 0xffffffff817be9a9 <+57>: mov $0x200,%esi - 0xffffffff817be9ae <+62>: mov $0xffffffff817be993,%rdi - 0xffffffff817be9b5 <+69>: jmpq 0xffffffff81063aa0 <__local_bh_enable_ip> - 0xffffffff817be9ba <+74>: mov %rbp,%rdi - 0xffffffff817be9bd <+77>: callq 0xffffffff817be8c0 <__lock_sock> - 0xffffffff817be9c2 <+82>: jmp 0xffffffff817be993 -End of assembler dump. - -NATIVE: - -(gdb) disassemble lock_sock_nested -Dump of assembler code for function lock_sock_nested: - 0xffffffff817be970 <+0>: push %rbp - 0xffffffff817be971 <+1>: mov %rdi,%rbp - 0xffffffff817be974 <+4>: push %rbx - 0xffffffff817be975 <+5>: lea 0x88(%rbp),%rbx - 0xffffffff817be97c <+12>: callq 0xffffffff819f7160 <_cond_resched> - 0xffffffff817be981 <+17>: mov %rbx,%rdi - 0xffffffff817be984 <+20>: callq 0xffffffff819fbb00 <_raw_spin_lock_bh> - 0xffffffff817be989 <+25>: mov 0x8c(%rbp),%eax - 0xffffffff817be98f <+31>: test %eax,%eax - 0xffffffff817be991 <+33>: jne 0xffffffff817be9ba - 0xffffffff817be993 <+35>: movl $0x1,0x8c(%rbp) - 0xffffffff817be99d <+45>: mov %rbx,%rdi - 0xffffffff817be9a0 <+48>: movb $0x0,(%rdi) - 0xffffffff817be9a3 <+51>: nopl 0x0(%rax) - 0xffffffff817be9a7 <+55>: pop %rbx - 0xffffffff817be9a8 <+56>: pop %rbp - 0xffffffff817be9a9 <+57>: mov $0x200,%esi - 0xffffffff817be9ae <+62>: mov $0xffffffff817be993,%rdi - 0xffffffff817be9b5 <+69>: jmpq 0xffffffff81063ae0 <__local_bh_enable_ip> - 0xffffffff817be9ba <+74>: mov %rbp,%rdi - 0xffffffff817be9bd <+77>: callq 0xffffffff817be8c0 <__lock_sock> - 0xffffffff817be9c2 <+82>: jmp 0xffffffff817be993 -End of assembler dump. - - -Fixes: 63f70270ccd9 ("[PATCH] i386: PARAVIRT: add common patching machinery") -Fixes: 3010a0663fd9 ("x86/paravirt, objtool: Annotate indirect calls") -Reported-by: Nadav Amit -Signed-off-by: Peter Zijlstra (Intel) -Signed-off-by: Thomas Gleixner -Reviewed-by: Juergen Gross -Cc: Konrad Rzeszutek Wilk -Cc: Boris Ostrovsky -Cc: David Woodhouse -Cc: stable@vger.kernel.org -Signed-off-by: Greg Kroah-Hartman - ---- - arch/x86/kernel/paravirt.c | 14 ++++++++++---- - 1 file changed, 10 insertions(+), 4 deletions(-) - ---- a/arch/x86/kernel/paravirt.c -+++ b/arch/x86/kernel/paravirt.c -@@ -88,10 +88,12 @@ unsigned paravirt_patch_call(void *insnb - struct branch *b = insnbuf; - unsigned long delta = (unsigned long)target - (addr+5); - -- if (tgt_clobbers & ~site_clobbers) -- return len; /* target would clobber too much for this site */ -- if (len < 5) -+ if (len < 5) { -+#ifdef CONFIG_RETPOLINE -+ WARN_ONCE("Failing to patch indirect CALL in %ps\n", (void *)addr); -+#endif - return len; /* call too long for patch site */ -+ } - - b->opcode = 0xe8; /* call */ - b->delta = delta; -@@ -106,8 +108,12 @@ unsigned paravirt_patch_jmp(void *insnbu - struct branch *b = insnbuf; - unsigned long delta = (unsigned long)target - (addr+5); - -- if (len < 5) -+ if (len < 5) { -+#ifdef CONFIG_RETPOLINE -+ WARN_ONCE("Failing to patch indirect JMP in %ps\n", (void *)addr); -+#endif - return len; /* call too long for patch site */ -+ } - - b->opcode = 0xe9; /* jmp */ - b->delta = delta; -From fdf82a7856b32d905c39afc85e34364491e46346 Mon Sep 17 00:00:00 2001 -From: Jiri Kosina -Date: Thu, 26 Jul 2018 13:14:55 +0200 -Subject: x86/speculation: Protect against userspace-userspace spectreRSB - -From: Jiri Kosina - -commit fdf82a7856b32d905c39afc85e34364491e46346 upstream. - -The article "Spectre Returns! Speculation Attacks using the Return Stack -Buffer" [1] describes two new (sub-)variants of spectrev2-like attacks, -making use solely of the RSB contents even on CPUs that don't fallback to -BTB on RSB underflow (Skylake+). - -Mitigate userspace-userspace attacks by always unconditionally filling RSB on -context switch when the generic spectrev2 mitigation has been enabled. - -[1] https://arxiv.org/pdf/1807.07940.pdf - -Signed-off-by: Jiri Kosina -Signed-off-by: Thomas Gleixner -Reviewed-by: Josh Poimboeuf -Acked-by: Tim Chen -Cc: Konrad Rzeszutek Wilk -Cc: Borislav Petkov -Cc: David Woodhouse -Cc: Peter Zijlstra -Cc: Linus Torvalds -Cc: stable@vger.kernel.org -Link: https://lkml.kernel.org/r/nycvar.YFH.7.76.1807261308190.997@cbobk.fhfr.pm -Signed-off-by: Greg Kroah-Hartman - ---- - arch/x86/kernel/cpu/bugs.c | 38 +++++++------------------------------- - 1 file changed, 7 insertions(+), 31 deletions(-) - ---- a/arch/x86/kernel/cpu/bugs.c -+++ b/arch/x86/kernel/cpu/bugs.c -@@ -311,23 +311,6 @@ static enum spectre_v2_mitigation_cmd __ - return cmd; - } - --/* Check for Skylake-like CPUs (for RSB handling) */ --static bool __init is_skylake_era(void) --{ -- if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL && -- boot_cpu_data.x86 == 6) { -- switch (boot_cpu_data.x86_model) { -- case INTEL_FAM6_SKYLAKE_MOBILE: -- case INTEL_FAM6_SKYLAKE_DESKTOP: -- case INTEL_FAM6_SKYLAKE_X: -- case INTEL_FAM6_KABYLAKE_MOBILE: -- case INTEL_FAM6_KABYLAKE_DESKTOP: -- return true; -- } -- } -- return false; --} -- - static void __init spectre_v2_select_mitigation(void) - { - enum spectre_v2_mitigation_cmd cmd = spectre_v2_parse_cmdline(); -@@ -388,22 +371,15 @@ retpoline_auto: - pr_info("%s\n", spectre_v2_strings[mode]); - - /* -- * If neither SMEP nor PTI are available, there is a risk of -- * hitting userspace addresses in the RSB after a context switch -- * from a shallow call stack to a deeper one. To prevent this fill -- * the entire RSB, even when using IBRS. -+ * If spectre v2 protection has been enabled, unconditionally fill -+ * RSB during a context switch; this protects against two independent -+ * issues: - * -- * Skylake era CPUs have a separate issue with *underflow* of the -- * RSB, when they will predict 'ret' targets from the generic BTB. -- * The proper mitigation for this is IBRS. If IBRS is not supported -- * or deactivated in favour of retpolines the RSB fill on context -- * switch is required. -+ * - RSB underflow (and switch to BTB) on Skylake+ -+ * - SpectreRSB variant of spectre v2 on X86_BUG_SPECTRE_V2 CPUs - */ -- if ((!boot_cpu_has(X86_FEATURE_PTI) && -- !boot_cpu_has(X86_FEATURE_SMEP)) || is_skylake_era()) { -- setup_force_cpu_cap(X86_FEATURE_RSB_CTXSW); -- pr_info("Spectre v2 mitigation: Filling RSB on context switch\n"); -- } -+ setup_force_cpu_cap(X86_FEATURE_RSB_CTXSW); -+ pr_info("Spectre v2 / SpectreRSB mitigation: Filling RSB on context switch\n"); - - /* Initialize Indirect Branch Prediction Barrier if supported */ - if (boot_cpu_has(X86_FEATURE_IBPB)) { -From 0ea063306eecf300fcf06d2f5917474b580f666f Mon Sep 17 00:00:00 2001 -From: Masami Hiramatsu -Date: Sat, 28 Apr 2018 21:37:03 +0900 -Subject: kprobes/x86: Fix %p uses in error messages - -From: Masami Hiramatsu - -commit 0ea063306eecf300fcf06d2f5917474b580f666f upstream. - -Remove all %p uses in error messages in kprobes/x86. - -Signed-off-by: Masami Hiramatsu -Cc: Ananth N Mavinakayanahalli -Cc: Anil S Keshavamurthy -Cc: Arnd Bergmann -Cc: David Howells -Cc: David S . Miller -Cc: Heiko Carstens -Cc: Jon Medhurst -Cc: Linus Torvalds -Cc: Peter Zijlstra -Cc: Thomas Gleixner -Cc: Thomas Richter -Cc: Tobin C . Harding -Cc: Will Deacon -Cc: acme@kernel.org -Cc: akpm@linux-foundation.org -Cc: brueckner@linux.vnet.ibm.com -Cc: linux-arch@vger.kernel.org -Cc: rostedt@goodmis.org -Cc: schwidefsky@de.ibm.com -Cc: stable@vger.kernel.org -Link: https://lkml.kernel.org/lkml/152491902310.9916.13355297638917767319.stgit@devbox -Signed-off-by: Ingo Molnar -Signed-off-by: Greg Kroah-Hartman - ---- - arch/x86/kernel/kprobes/core.c | 5 +---- - 1 file changed, 1 insertion(+), 4 deletions(-) - ---- a/arch/x86/kernel/kprobes/core.c -+++ b/arch/x86/kernel/kprobes/core.c -@@ -395,8 +395,6 @@ int __copy_instruction(u8 *dest, u8 *src - - (u8 *) real; - if ((s64) (s32) newdisp != newdisp) { - pr_err("Kprobes error: new displacement does not fit into s32 (%llx)\n", newdisp); -- pr_err("\tSrc: %p, Dest: %p, old disp: %x\n", -- src, real, insn->displacement.value); - return 0; - } - disp = (u8 *) dest + insn_offset_displacement(insn); -@@ -640,8 +638,7 @@ static int reenter_kprobe(struct kprobe - * Raise a BUG or we'll continue in an endless reentering loop - * and eventually a stack overflow. - */ -- printk(KERN_WARNING "Unrecoverable kprobe detected at %p.\n", -- p->addr); -+ pr_err("Unrecoverable kprobe detected.\n"); - dump_kprobe(p); - BUG(); - default: -From 208cbb32558907f68b3b2a081ca2337ac3744794 Mon Sep 17 00:00:00 2001 -From: Nick Desaulniers -Date: Fri, 3 Aug 2018 10:05:50 -0700 -Subject: x86/irqflags: Provide a declaration for native_save_fl - -From: Nick Desaulniers - -commit 208cbb32558907f68b3b2a081ca2337ac3744794 upstream. - -It was reported that the commit d0a8d9378d16 is causing users of gcc < 4.9 -to observe -Werror=missing-prototypes errors. - -Indeed, it seems that: -extern inline unsigned long native_save_fl(void) { return 0; } - -compiled with -Werror=missing-prototypes produces this warning in gcc < -4.9, but not gcc >= 4.9. - -Fixes: d0a8d9378d16 ("x86/paravirt: Make native_save_fl() extern inline"). -Reported-by: David Laight -Reported-by: Jean Delvare -Signed-off-by: Nick Desaulniers -Signed-off-by: Thomas Gleixner -Cc: hpa@zytor.com -Cc: jgross@suse.com -Cc: kstewart@linuxfoundation.org -Cc: gregkh@linuxfoundation.org -Cc: boris.ostrovsky@oracle.com -Cc: astrachan@google.com -Cc: mka@chromium.org -Cc: arnd@arndb.de -Cc: tstellar@redhat.com -Cc: sedat.dilek@gmail.com -Cc: David.Laight@aculab.com -Cc: stable@vger.kernel.org -Link: https://lkml.kernel.org/r/20180803170550.164688-1-ndesaulniers@google.com -Signed-off-by: Greg Kroah-Hartman - ---- - arch/x86/include/asm/irqflags.h | 2 ++ - 1 file changed, 2 insertions(+) - ---- a/arch/x86/include/asm/irqflags.h -+++ b/arch/x86/include/asm/irqflags.h -@@ -13,6 +13,8 @@ - * Interrupt control: - */ - -+/* Declaration required for gcc < 4.9 to prevent -Werror=missing-prototypes */ -+extern inline unsigned long native_save_fl(void); - extern inline unsigned long native_save_fl(void) - { - unsigned long flags; -From foo@baz Tue Aug 14 13:43:10 CEST 2018 -From: Andi Kleen -Date: Wed, 13 Jun 2018 15:48:21 -0700 -Subject: x86/speculation/l1tf: Increase 32bit PAE __PHYSICAL_PAGE_SHIFT - -From: Andi Kleen - -commit 50896e180c6aa3a9c61a26ced99e15d602666a4c upstream - -L1 Terminal Fault (L1TF) is a speculation related vulnerability. The CPU -speculates on PTE entries which do not have the PRESENT bit set, if the -content of the resulting physical address is available in the L1D cache. - -The OS side mitigation makes sure that a !PRESENT PTE entry points to a -physical address outside the actually existing and cachable memory -space. This is achieved by inverting the upper bits of the PTE. Due to the -address space limitations this only works for 64bit and 32bit PAE kernels, -but not for 32bit non PAE. - -This mitigation applies to both host and guest kernels, but in case of a -64bit host (hypervisor) and a 32bit PAE guest, inverting the upper bits of -the PAE address space (44bit) is not enough if the host has more than 43 -bits of populated memory address space, because the speculation treats the -PTE content as a physical host address bypassing EPT. - -The host (hypervisor) protects itself against the guest by flushing L1D as -needed, but pages inside the guest are not protected against attacks from -other processes inside the same guest. - -For the guest the inverted PTE mask has to match the host to provide the -full protection for all pages the host could possibly map into the -guest. The hosts populated address space is not known to the guest, so the -mask must cover the possible maximal host address space, i.e. 52 bit. - -On 32bit PAE the maximum PTE mask is currently set to 44 bit because that -is the limit imposed by 32bit unsigned long PFNs in the VMs. This limits -the mask to be below what the host could possible use for physical pages. - -The L1TF PROT_NONE protection code uses the PTE masks to determine which -bits to invert to make sure the higher bits are set for unmapped entries to -prevent L1TF speculation attacks against EPT inside guests. - -In order to invert all bits that could be used by the host, increase -__PHYSICAL_PAGE_SHIFT to 52 to match 64bit. - -The real limit for a 32bit PAE kernel is still 44 bits because all Linux -PTEs are created from unsigned long PFNs, so they cannot be higher than 44 -bits on a 32bit kernel. So these extra PFN bits should be never set. The -only users of this macro are using it to look at PTEs, so it's safe. - -[ tglx: Massaged changelog ] - -Signed-off-by: Andi Kleen -Signed-off-by: Thomas Gleixner -Reviewed-by: Josh Poimboeuf -Acked-by: Michal Hocko -Acked-by: Dave Hansen -Signed-off-by: Greg Kroah-Hartman ---- - arch/x86/include/asm/page_32_types.h | 9 +++++++-- - 1 file changed, 7 insertions(+), 2 deletions(-) - ---- a/arch/x86/include/asm/page_32_types.h -+++ b/arch/x86/include/asm/page_32_types.h -@@ -29,8 +29,13 @@ - #define N_EXCEPTION_STACKS 1 - - #ifdef CONFIG_X86_PAE --/* 44=32+12, the limit we can fit into an unsigned long pfn */ --#define __PHYSICAL_MASK_SHIFT 44 -+/* -+ * This is beyond the 44 bit limit imposed by the 32bit long pfns, -+ * but we need the full mask to make sure inverted PROT_NONE -+ * entries have all the host bits set in a guest. -+ * The real limit is still 44 bits. -+ */ -+#define __PHYSICAL_MASK_SHIFT 52 - #define __VIRTUAL_MASK_SHIFT 32 - - #else /* !CONFIG_X86_PAE */ -From foo@baz Tue Aug 14 13:43:10 CEST 2018 -From: Linus Torvalds -Date: Wed, 13 Jun 2018 15:48:22 -0700 -Subject: x86/speculation/l1tf: Change order of offset/type in swap entry - -From: Linus Torvalds - -commit bcd11afa7adad8d720e7ba5ef58bdcd9775cf45f upstream - -If pages are swapped out, the swap entry is stored in the corresponding -PTE, which has the Present bit cleared. CPUs vulnerable to L1TF speculate -on PTE entries which have the present bit set and would treat the swap -entry as phsyical address (PFN). To mitigate that the upper bits of the PTE -must be set so the PTE points to non existent memory. - -The swap entry stores the type and the offset of a swapped out page in the -PTE. type is stored in bit 9-13 and offset in bit 14-63. The hardware -ignores the bits beyond the phsyical address space limit, so to make the -mitigation effective its required to start 'offset' at the lowest possible -bit so that even large swap offsets do not reach into the physical address -space limit bits. - -Move offset to bit 9-58 and type to bit 59-63 which are the bits that -hardware generally doesn't care about. - -That, in turn, means that if you on desktop chip with only 40 bits of -physical addressing, now that the offset starts at bit 9, there needs to be -30 bits of offset actually *in use* until bit 39 ends up being set, which -means when inverted it will again point into existing memory. - -So that's 4 terabyte of swap space (because the offset is counted in pages, -so 30 bits of offset is 42 bits of actual coverage). With bigger physical -addressing, that obviously grows further, until the limit of the offset is -hit (at 50 bits of offset - 62 bits of actual swap file coverage). - -This is a preparatory change for the actual swap entry inversion to protect -against L1TF. - -[ AK: Updated description and minor tweaks. Split into two parts ] -[ tglx: Massaged changelog ] - -Signed-off-by: Linus Torvalds -Signed-off-by: Andi Kleen -Signed-off-by: Thomas Gleixner -Tested-by: Andi Kleen -Reviewed-by: Josh Poimboeuf -Acked-by: Michal Hocko -Acked-by: Vlastimil Babka -Acked-by: Dave Hansen -Signed-off-by: Greg Kroah-Hartman ---- - arch/x86/include/asm/pgtable_64.h | 31 ++++++++++++++++++++----------- - 1 file changed, 20 insertions(+), 11 deletions(-) - ---- a/arch/x86/include/asm/pgtable_64.h -+++ b/arch/x86/include/asm/pgtable_64.h -@@ -273,7 +273,7 @@ static inline int pgd_large(pgd_t pgd) { - * - * | ... | 11| 10| 9|8|7|6|5| 4| 3|2| 1|0| <- bit number - * | ... |SW3|SW2|SW1|G|L|D|A|CD|WT|U| W|P| <- bit names -- * | OFFSET (14->63) | TYPE (9-13) |0|0|X|X| X| X|X|SD|0| <- swp entry -+ * | TYPE (59-63) | OFFSET (9-58) |0|0|X|X| X| X|X|SD|0| <- swp entry - * - * G (8) is aliased and used as a PROT_NONE indicator for - * !present ptes. We need to start storing swap entries above -@@ -287,19 +287,28 @@ static inline int pgd_large(pgd_t pgd) { - * Bit 7 in swp entry should be 0 because pmd_present checks not only P, - * but also L and G. - */ --#define SWP_TYPE_FIRST_BIT (_PAGE_BIT_PROTNONE + 1) --#define SWP_TYPE_BITS 5 --/* Place the offset above the type: */ --#define SWP_OFFSET_FIRST_BIT (SWP_TYPE_FIRST_BIT + SWP_TYPE_BITS) -+#define SWP_TYPE_BITS 5 -+ -+#define SWP_OFFSET_FIRST_BIT (_PAGE_BIT_PROTNONE + 1) -+ -+/* We always extract/encode the offset by shifting it all the way up, and then down again */ -+#define SWP_OFFSET_SHIFT (SWP_OFFSET_FIRST_BIT+SWP_TYPE_BITS) - - #define MAX_SWAPFILES_CHECK() BUILD_BUG_ON(MAX_SWAPFILES_SHIFT > SWP_TYPE_BITS) - --#define __swp_type(x) (((x).val >> (SWP_TYPE_FIRST_BIT)) \ -- & ((1U << SWP_TYPE_BITS) - 1)) --#define __swp_offset(x) ((x).val >> SWP_OFFSET_FIRST_BIT) --#define __swp_entry(type, offset) ((swp_entry_t) { \ -- ((type) << (SWP_TYPE_FIRST_BIT)) \ -- | ((offset) << SWP_OFFSET_FIRST_BIT) }) -+/* Extract the high bits for type */ -+#define __swp_type(x) ((x).val >> (64 - SWP_TYPE_BITS)) -+ -+/* Shift up (to get rid of type), then down to get value */ -+#define __swp_offset(x) ((x).val << SWP_TYPE_BITS >> SWP_OFFSET_SHIFT) -+ -+/* -+ * Shift the offset up "too far" by TYPE bits, then down again -+ */ -+#define __swp_entry(type, offset) ((swp_entry_t) { \ -+ ((unsigned long)(offset) << SWP_OFFSET_SHIFT >> SWP_TYPE_BITS) \ -+ | ((unsigned long)(type) << (64-SWP_TYPE_BITS)) }) -+ - #define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val((pte)) }) - #define __pmd_to_swp_entry(pmd) ((swp_entry_t) { pmd_val((pmd)) }) - #define __swp_entry_to_pte(x) ((pte_t) { .pte = (x).val }) -From foo@baz Tue Aug 14 13:43:10 CEST 2018 -From: Linus Torvalds -Date: Wed, 13 Jun 2018 15:48:23 -0700 -Subject: x86/speculation/l1tf: Protect swap entries against L1TF - -From: Linus Torvalds - -commit 2f22b4cd45b67b3496f4aa4c7180a1271c6452f6 upstream - -With L1 terminal fault the CPU speculates into unmapped PTEs, and resulting -side effects allow to read the memory the PTE is pointing too, if its -values are still in the L1 cache. - -For swapped out pages Linux uses unmapped PTEs and stores a swap entry into -them. - -To protect against L1TF it must be ensured that the swap entry is not -pointing to valid memory, which requires setting higher bits (between bit -36 and bit 45) that are inside the CPUs physical address space, but outside -any real memory. - -To do this invert the offset to make sure the higher bits are always set, -as long as the swap file is not too big. - -Note there is no workaround for 32bit !PAE, or on systems which have more -than MAX_PA/2 worth of memory. The later case is very unlikely to happen on -real systems. - -[AK: updated description and minor tweaks by. Split out from the original - patch ] - -Signed-off-by: Linus Torvalds -Signed-off-by: Andi Kleen -Signed-off-by: Thomas Gleixner -Tested-by: Andi Kleen -Reviewed-by: Josh Poimboeuf -Acked-by: Michal Hocko -Acked-by: Vlastimil Babka -Acked-by: Dave Hansen -Signed-off-by: Greg Kroah-Hartman ---- - arch/x86/include/asm/pgtable_64.h | 11 ++++++++--- - 1 file changed, 8 insertions(+), 3 deletions(-) - ---- a/arch/x86/include/asm/pgtable_64.h -+++ b/arch/x86/include/asm/pgtable_64.h -@@ -273,7 +273,7 @@ static inline int pgd_large(pgd_t pgd) { - * - * | ... | 11| 10| 9|8|7|6|5| 4| 3|2| 1|0| <- bit number - * | ... |SW3|SW2|SW1|G|L|D|A|CD|WT|U| W|P| <- bit names -- * | TYPE (59-63) | OFFSET (9-58) |0|0|X|X| X| X|X|SD|0| <- swp entry -+ * | TYPE (59-63) | ~OFFSET (9-58) |0|0|X|X| X| X|X|SD|0| <- swp entry - * - * G (8) is aliased and used as a PROT_NONE indicator for - * !present ptes. We need to start storing swap entries above -@@ -286,6 +286,9 @@ static inline int pgd_large(pgd_t pgd) { - * - * Bit 7 in swp entry should be 0 because pmd_present checks not only P, - * but also L and G. -+ * -+ * The offset is inverted by a binary not operation to make the high -+ * physical bits set. - */ - #define SWP_TYPE_BITS 5 - -@@ -300,13 +303,15 @@ static inline int pgd_large(pgd_t pgd) { - #define __swp_type(x) ((x).val >> (64 - SWP_TYPE_BITS)) - - /* Shift up (to get rid of type), then down to get value */ --#define __swp_offset(x) ((x).val << SWP_TYPE_BITS >> SWP_OFFSET_SHIFT) -+#define __swp_offset(x) (~(x).val << SWP_TYPE_BITS >> SWP_OFFSET_SHIFT) - - /* - * Shift the offset up "too far" by TYPE bits, then down again -+ * The offset is inverted by a binary not operation to make the high -+ * physical bits set. - */ - #define __swp_entry(type, offset) ((swp_entry_t) { \ -- ((unsigned long)(offset) << SWP_OFFSET_SHIFT >> SWP_TYPE_BITS) \ -+ (~(unsigned long)(offset) << SWP_OFFSET_SHIFT >> SWP_TYPE_BITS) \ - | ((unsigned long)(type) << (64-SWP_TYPE_BITS)) }) - - #define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val((pte)) }) -From foo@baz Tue Aug 14 13:43:10 CEST 2018 -From: Andi Kleen -Date: Wed, 13 Jun 2018 15:48:24 -0700 -Subject: x86/speculation/l1tf: Protect PROT_NONE PTEs against speculation - -From: Andi Kleen - -commit 6b28baca9b1f0d4a42b865da7a05b1c81424bd5c upstream - -When PTEs are set to PROT_NONE the kernel just clears the Present bit and -preserves the PFN, which creates attack surface for L1TF speculation -speculation attacks. - -This is important inside guests, because L1TF speculation bypasses physical -page remapping. While the host has its own migitations preventing leaking -data from other VMs into the guest, this would still risk leaking the wrong -page inside the current guest. - -This uses the same technique as Linus' swap entry patch: while an entry is -is in PROTNONE state invert the complete PFN part part of it. This ensures -that the the highest bit will point to non existing memory. - -The invert is done by pte/pmd_modify and pfn/pmd/pud_pte for PROTNONE and -pte/pmd/pud_pfn undo it. - -This assume that no code path touches the PFN part of a PTE directly -without using these primitives. - -This doesn't handle the case that MMIO is on the top of the CPU physical -memory. If such an MMIO region was exposed by an unpriviledged driver for -mmap it would be possible to attack some real memory. However this -situation is all rather unlikely. - -For 32bit non PAE the inversion is not done because there are really not -enough bits to protect anything. - -Q: Why does the guest need to be protected when the HyperVisor already has - L1TF mitigations? - -A: Here's an example: - - Physical pages 1 2 get mapped into a guest as - GPA 1 -> PA 2 - GPA 2 -> PA 1 - through EPT. - - The L1TF speculation ignores the EPT remapping. - - Now the guest kernel maps GPA 1 to process A and GPA 2 to process B, and - they belong to different users and should be isolated. - - A sets the GPA 1 PA 2 PTE to PROT_NONE to bypass the EPT remapping and - gets read access to the underlying physical page. Which in this case - points to PA 2, so it can read process B's data, if it happened to be in - L1, so isolation inside the guest is broken. - - There's nothing the hypervisor can do about this. This mitigation has to - be done in the guest itself. - -[ tglx: Massaged changelog ] - -Signed-off-by: Andi Kleen -Signed-off-by: Thomas Gleixner -Reviewed-by: Josh Poimboeuf -Acked-by: Michal Hocko -Acked-by: Vlastimil Babka -Acked-by: Dave Hansen -Signed-off-by: Greg Kroah-Hartman ---- - arch/x86/include/asm/pgtable-2level.h | 17 +++++++++++++ - arch/x86/include/asm/pgtable-3level.h | 2 + - arch/x86/include/asm/pgtable-invert.h | 32 ++++++++++++++++++++++++ - arch/x86/include/asm/pgtable.h | 44 +++++++++++++++++++++++----------- - arch/x86/include/asm/pgtable_64.h | 2 + - 5 files changed, 84 insertions(+), 13 deletions(-) - create mode 100644 arch/x86/include/asm/pgtable-invert.h - ---- a/arch/x86/include/asm/pgtable-2level.h -+++ b/arch/x86/include/asm/pgtable-2level.h -@@ -95,4 +95,21 @@ static inline unsigned long pte_bitop(un - #define __pte_to_swp_entry(pte) ((swp_entry_t) { (pte).pte_low }) - #define __swp_entry_to_pte(x) ((pte_t) { .pte = (x).val }) - -+/* No inverted PFNs on 2 level page tables */ -+ -+static inline u64 protnone_mask(u64 val) -+{ -+ return 0; -+} -+ -+static inline u64 flip_protnone_guard(u64 oldval, u64 val, u64 mask) -+{ -+ return val; -+} -+ -+static inline bool __pte_needs_invert(u64 val) -+{ -+ return false; -+} -+ - #endif /* _ASM_X86_PGTABLE_2LEVEL_H */ ---- a/arch/x86/include/asm/pgtable-3level.h -+++ b/arch/x86/include/asm/pgtable-3level.h -@@ -295,4 +295,6 @@ static inline pte_t gup_get_pte(pte_t *p - return pte; - } - -+#include -+ - #endif /* _ASM_X86_PGTABLE_3LEVEL_H */ ---- /dev/null -+++ b/arch/x86/include/asm/pgtable-invert.h -@@ -0,0 +1,32 @@ -+/* SPDX-License-Identifier: GPL-2.0 */ -+#ifndef _ASM_PGTABLE_INVERT_H -+#define _ASM_PGTABLE_INVERT_H 1 -+ -+#ifndef __ASSEMBLY__ -+ -+static inline bool __pte_needs_invert(u64 val) -+{ -+ return (val & (_PAGE_PRESENT|_PAGE_PROTNONE)) == _PAGE_PROTNONE; -+} -+ -+/* Get a mask to xor with the page table entry to get the correct pfn. */ -+static inline u64 protnone_mask(u64 val) -+{ -+ return __pte_needs_invert(val) ? ~0ull : 0; -+} -+ -+static inline u64 flip_protnone_guard(u64 oldval, u64 val, u64 mask) -+{ -+ /* -+ * When a PTE transitions from NONE to !NONE or vice-versa -+ * invert the PFN part to stop speculation. -+ * pte_pfn undoes this when needed. -+ */ -+ if (__pte_needs_invert(oldval) != __pte_needs_invert(val)) -+ val = (val & ~mask) | (~val & mask); -+ return val; -+} -+ -+#endif /* __ASSEMBLY__ */ -+ -+#endif ---- a/arch/x86/include/asm/pgtable.h -+++ b/arch/x86/include/asm/pgtable.h -@@ -185,19 +185,29 @@ static inline int pte_special(pte_t pte) - return pte_flags(pte) & _PAGE_SPECIAL; - } - -+/* Entries that were set to PROT_NONE are inverted */ -+ -+static inline u64 protnone_mask(u64 val); -+ - static inline unsigned long pte_pfn(pte_t pte) - { -- return (pte_val(pte) & PTE_PFN_MASK) >> PAGE_SHIFT; -+ unsigned long pfn = pte_val(pte); -+ pfn ^= protnone_mask(pfn); -+ return (pfn & PTE_PFN_MASK) >> PAGE_SHIFT; - } - - static inline unsigned long pmd_pfn(pmd_t pmd) - { -- return (pmd_val(pmd) & pmd_pfn_mask(pmd)) >> PAGE_SHIFT; -+ unsigned long pfn = pmd_val(pmd); -+ pfn ^= protnone_mask(pfn); -+ return (pfn & pmd_pfn_mask(pmd)) >> PAGE_SHIFT; - } - - static inline unsigned long pud_pfn(pud_t pud) - { -- return (pud_val(pud) & pud_pfn_mask(pud)) >> PAGE_SHIFT; -+ unsigned long pfn = pud_val(pud); -+ pfn ^= protnone_mask(pfn); -+ return (pfn & pud_pfn_mask(pud)) >> PAGE_SHIFT; - } - - static inline unsigned long p4d_pfn(p4d_t p4d) -@@ -545,25 +555,33 @@ static inline pgprotval_t check_pgprot(p - - static inline pte_t pfn_pte(unsigned long page_nr, pgprot_t pgprot) - { -- return __pte(((phys_addr_t)page_nr << PAGE_SHIFT) | -- check_pgprot(pgprot)); -+ phys_addr_t pfn = page_nr << PAGE_SHIFT; -+ pfn ^= protnone_mask(pgprot_val(pgprot)); -+ pfn &= PTE_PFN_MASK; -+ return __pte(pfn | check_pgprot(pgprot)); - } - - static inline pmd_t pfn_pmd(unsigned long page_nr, pgprot_t pgprot) - { -- return __pmd(((phys_addr_t)page_nr << PAGE_SHIFT) | -- check_pgprot(pgprot)); -+ phys_addr_t pfn = page_nr << PAGE_SHIFT; -+ pfn ^= protnone_mask(pgprot_val(pgprot)); -+ pfn &= PHYSICAL_PMD_PAGE_MASK; -+ return __pmd(pfn | check_pgprot(pgprot)); - } - - static inline pud_t pfn_pud(unsigned long page_nr, pgprot_t pgprot) - { -- return __pud(((phys_addr_t)page_nr << PAGE_SHIFT) | -- check_pgprot(pgprot)); -+ phys_addr_t pfn = page_nr << PAGE_SHIFT; -+ pfn ^= protnone_mask(pgprot_val(pgprot)); -+ pfn &= PHYSICAL_PUD_PAGE_MASK; -+ return __pud(pfn | check_pgprot(pgprot)); - } - -+static inline u64 flip_protnone_guard(u64 oldval, u64 val, u64 mask); -+ - static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) - { -- pteval_t val = pte_val(pte); -+ pteval_t val = pte_val(pte), oldval = val; - - /* - * Chop off the NX bit (if present), and add the NX portion of -@@ -571,17 +589,17 @@ static inline pte_t pte_modify(pte_t pte - */ - val &= _PAGE_CHG_MASK; - val |= check_pgprot(newprot) & ~_PAGE_CHG_MASK; -- -+ val = flip_protnone_guard(oldval, val, PTE_PFN_MASK); - return __pte(val); - } - - static inline pmd_t pmd_modify(pmd_t pmd, pgprot_t newprot) - { -- pmdval_t val = pmd_val(pmd); -+ pmdval_t val = pmd_val(pmd), oldval = val; - - val &= _HPAGE_CHG_MASK; - val |= check_pgprot(newprot) & ~_HPAGE_CHG_MASK; -- -+ val = flip_protnone_guard(oldval, val, PHYSICAL_PMD_PAGE_MASK); - return __pmd(val); - } - ---- a/arch/x86/include/asm/pgtable_64.h -+++ b/arch/x86/include/asm/pgtable_64.h -@@ -357,5 +357,7 @@ static inline bool gup_fast_permitted(un - return true; - } - -+#include -+ - #endif /* !__ASSEMBLY__ */ - #endif /* _ASM_X86_PGTABLE_64_H */ -From foo@baz Tue Aug 14 13:43:10 CEST 2018 -From: Andi Kleen -Date: Wed, 13 Jun 2018 15:48:25 -0700 -Subject: x86/speculation/l1tf: Make sure the first page is always reserved - -From: Andi Kleen - -commit 10a70416e1f067f6c4efda6ffd8ea96002ac4223 upstream - -The L1TF workaround doesn't make any attempt to mitigate speculate accesses -to the first physical page for zeroed PTEs. Normally it only contains some -data from the early real mode BIOS. - -It's not entirely clear that the first page is reserved in all -configurations, so add an extra reservation call to make sure it is really -reserved. In most configurations (e.g. with the standard reservations) -it's likely a nop. - -Signed-off-by: Andi Kleen -Signed-off-by: Thomas Gleixner -Reviewed-by: Josh Poimboeuf -Acked-by: Dave Hansen -Signed-off-by: Greg Kroah-Hartman ---- - arch/x86/kernel/setup.c | 6 ++++++ - 1 file changed, 6 insertions(+) - ---- a/arch/x86/kernel/setup.c -+++ b/arch/x86/kernel/setup.c -@@ -823,6 +823,12 @@ void __init setup_arch(char **cmdline_p) - memblock_reserve(__pa_symbol(_text), - (unsigned long)__bss_stop - (unsigned long)_text); - -+ /* -+ * Make sure page 0 is always reserved because on systems with -+ * L1TF its contents can be leaked to user processes. -+ */ -+ memblock_reserve(0, PAGE_SIZE); -+ - early_reserve_initrd(); - - /* -From foo@baz Tue Aug 14 13:43:10 CEST 2018 -From: Andi Kleen -Date: Wed, 13 Jun 2018 15:48:26 -0700 -Subject: x86/speculation/l1tf: Add sysfs reporting for l1tf - -From: Andi Kleen - -commit 17dbca119312b4e8173d4e25ff64262119fcef38 upstream - -L1TF core kernel workarounds are cheap and normally always enabled, However -they still should be reported in sysfs if the system is vulnerable or -mitigated. Add the necessary CPU feature/bug bits. - -- Extend the existing checks for Meltdowns to determine if the system is - vulnerable. All CPUs which are not vulnerable to Meltdown are also not - vulnerable to L1TF - -- Check for 32bit non PAE and emit a warning as there is no practical way - for mitigation due to the limited physical address bits - -- If the system has more than MAX_PA/2 physical memory the invert page - workarounds don't protect the system against the L1TF attack anymore, - because an inverted physical address will also point to valid - memory. Print a warning in this case and report that the system is - vulnerable. - -Add a function which returns the PFN limit for the L1TF mitigation, which -will be used in follow up patches for sanity and range checks. - -[ tglx: Renamed the CPU feature bit to L1TF_PTEINV ] - -Signed-off-by: Andi Kleen -Signed-off-by: Thomas Gleixner -Reviewed-by: Josh Poimboeuf -Acked-by: Dave Hansen -Signed-off-by: Greg Kroah-Hartman ---- - arch/x86/include/asm/cpufeatures.h | 2 + - arch/x86/include/asm/processor.h | 5 ++++ - arch/x86/kernel/cpu/bugs.c | 40 +++++++++++++++++++++++++++++++++++++ - arch/x86/kernel/cpu/common.c | 20 ++++++++++++++++++ - drivers/base/cpu.c | 8 +++++++ - include/linux/cpu.h | 2 + - 6 files changed, 77 insertions(+) - ---- a/arch/x86/include/asm/cpufeatures.h -+++ b/arch/x86/include/asm/cpufeatures.h -@@ -219,6 +219,7 @@ - #define X86_FEATURE_IBPB ( 7*32+26) /* Indirect Branch Prediction Barrier */ - #define X86_FEATURE_STIBP ( 7*32+27) /* Single Thread Indirect Branch Predictors */ - #define X86_FEATURE_ZEN ( 7*32+28) /* "" CPU is AMD family 0x17 (Zen) */ -+#define X86_FEATURE_L1TF_PTEINV ( 7*32+29) /* "" L1TF workaround PTE inversion */ - - /* Virtualization flags: Linux defined, word 8 */ - #define X86_FEATURE_TPR_SHADOW ( 8*32+ 0) /* Intel TPR Shadow */ -@@ -371,5 +372,6 @@ - #define X86_BUG_SPECTRE_V1 X86_BUG(15) /* CPU is affected by Spectre variant 1 attack with conditional branches */ - #define X86_BUG_SPECTRE_V2 X86_BUG(16) /* CPU is affected by Spectre variant 2 attack with indirect branches */ - #define X86_BUG_SPEC_STORE_BYPASS X86_BUG(17) /* CPU is affected by speculative store bypass attack */ -+#define X86_BUG_L1TF X86_BUG(18) /* CPU is affected by L1 Terminal Fault */ - - #endif /* _ASM_X86_CPUFEATURES_H */ ---- a/arch/x86/include/asm/processor.h -+++ b/arch/x86/include/asm/processor.h -@@ -181,6 +181,11 @@ extern const struct seq_operations cpuin - - extern void cpu_detect(struct cpuinfo_x86 *c); - -+static inline unsigned long l1tf_pfn_limit(void) -+{ -+ return BIT(boot_cpu_data.x86_phys_bits - 1 - PAGE_SHIFT) - 1; -+} -+ - extern void early_cpu_init(void); - extern void identify_boot_cpu(void); - extern void identify_secondary_cpu(struct cpuinfo_x86 *); ---- a/arch/x86/kernel/cpu/bugs.c -+++ b/arch/x86/kernel/cpu/bugs.c -@@ -27,9 +27,11 @@ - #include - #include - #include -+#include - - static void __init spectre_v2_select_mitigation(void); - static void __init ssb_select_mitigation(void); -+static void __init l1tf_select_mitigation(void); - - /* - * Our boot-time value of the SPEC_CTRL MSR. We read it once so that any -@@ -81,6 +83,8 @@ void __init check_bugs(void) - */ - ssb_select_mitigation(); - -+ l1tf_select_mitigation(); -+ - #ifdef CONFIG_X86_32 - /* - * Check whether we are able to run this kernel safely on SMP. -@@ -205,6 +209,32 @@ static void x86_amd_ssb_disable(void) - wrmsrl(MSR_AMD64_LS_CFG, msrval); - } - -+static void __init l1tf_select_mitigation(void) -+{ -+ u64 half_pa; -+ -+ if (!boot_cpu_has_bug(X86_BUG_L1TF)) -+ return; -+ -+#if CONFIG_PGTABLE_LEVELS == 2 -+ pr_warn("Kernel not compiled for PAE. No mitigation for L1TF\n"); -+ return; -+#endif -+ -+ /* -+ * This is extremely unlikely to happen because almost all -+ * systems have far more MAX_PA/2 than RAM can be fit into -+ * DIMM slots. -+ */ -+ half_pa = (u64)l1tf_pfn_limit() << PAGE_SHIFT; -+ if (e820__mapped_any(half_pa, ULLONG_MAX - half_pa, E820_TYPE_RAM)) { -+ pr_warn("System has more than MAX_PA/2 memory. L1TF mitigation not effective.\n"); -+ return; -+ } -+ -+ setup_force_cpu_cap(X86_FEATURE_L1TF_PTEINV); -+} -+ - #ifdef RETPOLINE - static bool spectre_v2_bad_module; - -@@ -657,6 +687,11 @@ static ssize_t cpu_show_common(struct de - case X86_BUG_SPEC_STORE_BYPASS: - return sprintf(buf, "%s\n", ssb_strings[ssb_mode]); - -+ case X86_BUG_L1TF: -+ if (boot_cpu_has(X86_FEATURE_L1TF_PTEINV)) -+ return sprintf(buf, "Mitigation: Page Table Inversion\n"); -+ break; -+ - default: - break; - } -@@ -683,4 +718,9 @@ ssize_t cpu_show_spec_store_bypass(struc - { - return cpu_show_common(dev, attr, buf, X86_BUG_SPEC_STORE_BYPASS); - } -+ -+ssize_t cpu_show_l1tf(struct device *dev, struct device_attribute *attr, char *buf) -+{ -+ return cpu_show_common(dev, attr, buf, X86_BUG_L1TF); -+} - #endif ---- a/arch/x86/kernel/cpu/common.c -+++ b/arch/x86/kernel/cpu/common.c -@@ -958,6 +958,21 @@ static const __initconst struct x86_cpu_ - {} - }; - -+static const __initconst struct x86_cpu_id cpu_no_l1tf[] = { -+ /* in addition to cpu_no_speculation */ -+ { X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_SILVERMONT1 }, -+ { X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_SILVERMONT2 }, -+ { X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_AIRMONT }, -+ { X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_MERRIFIELD }, -+ { X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_MOOREFIELD }, -+ { X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_GOLDMONT }, -+ { X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_DENVERTON }, -+ { X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_GEMINI_LAKE }, -+ { X86_VENDOR_INTEL, 6, INTEL_FAM6_XEON_PHI_KNL }, -+ { X86_VENDOR_INTEL, 6, INTEL_FAM6_XEON_PHI_KNM }, -+ {} -+}; -+ - static void __init cpu_set_bug_bits(struct cpuinfo_x86 *c) - { - u64 ia32_cap = 0; -@@ -983,6 +998,11 @@ static void __init cpu_set_bug_bits(stru - return; - - setup_force_cpu_bug(X86_BUG_CPU_MELTDOWN); -+ -+ if (x86_match_cpu(cpu_no_l1tf)) -+ return; -+ -+ setup_force_cpu_bug(X86_BUG_L1TF); - } - - /* ---- a/drivers/base/cpu.c -+++ b/drivers/base/cpu.c -@@ -540,16 +540,24 @@ ssize_t __weak cpu_show_spec_store_bypas - return sprintf(buf, "Not affected\n"); - } - -+ssize_t __weak cpu_show_l1tf(struct device *dev, -+ struct device_attribute *attr, char *buf) -+{ -+ return sprintf(buf, "Not affected\n"); -+} -+ - static DEVICE_ATTR(meltdown, 0444, cpu_show_meltdown, NULL); - static DEVICE_ATTR(spectre_v1, 0444, cpu_show_spectre_v1, NULL); - static DEVICE_ATTR(spectre_v2, 0444, cpu_show_spectre_v2, NULL); - static DEVICE_ATTR(spec_store_bypass, 0444, cpu_show_spec_store_bypass, NULL); -+static DEVICE_ATTR(l1tf, 0444, cpu_show_l1tf, NULL); - - static struct attribute *cpu_root_vulnerabilities_attrs[] = { - &dev_attr_meltdown.attr, - &dev_attr_spectre_v1.attr, - &dev_attr_spectre_v2.attr, - &dev_attr_spec_store_bypass.attr, -+ &dev_attr_l1tf.attr, - NULL - }; - ---- a/include/linux/cpu.h -+++ b/include/linux/cpu.h -@@ -55,6 +55,8 @@ extern ssize_t cpu_show_spectre_v2(struc - struct device_attribute *attr, char *buf); - extern ssize_t cpu_show_spec_store_bypass(struct device *dev, - struct device_attribute *attr, char *buf); -+extern ssize_t cpu_show_l1tf(struct device *dev, -+ struct device_attribute *attr, char *buf); - - extern __printf(4, 5) - struct device *cpu_device_create(struct device *parent, void *drvdata, -From foo@baz Tue Aug 14 13:43:10 CEST 2018 -From: Andi Kleen -Date: Wed, 13 Jun 2018 15:48:27 -0700 -Subject: x86/speculation/l1tf: Disallow non privileged high MMIO PROT_NONE mappings - -From: Andi Kleen - -commit 42e4089c7890725fcd329999252dc489b72f2921 upstream - -For L1TF PROT_NONE mappings are protected by inverting the PFN in the page -table entry. This sets the high bits in the CPU's address space, thus -making sure to point to not point an unmapped entry to valid cached memory. - -Some server system BIOSes put the MMIO mappings high up in the physical -address space. If such an high mapping was mapped to unprivileged users -they could attack low memory by setting such a mapping to PROT_NONE. This -could happen through a special device driver which is not access -protected. Normal /dev/mem is of course access protected. - -To avoid this forbid PROT_NONE mappings or mprotect for high MMIO mappings. - -Valid page mappings are allowed because the system is then unsafe anyways. - -It's not expected that users commonly use PROT_NONE on MMIO. But to -minimize any impact this is only enforced if the mapping actually refers to -a high MMIO address (defined as the MAX_PA-1 bit being set), and also skip -the check for root. - -For mmaps this is straight forward and can be handled in vm_insert_pfn and -in remap_pfn_range(). - -For mprotect it's a bit trickier. At the point where the actual PTEs are -accessed a lot of state has been changed and it would be difficult to undo -on an error. Since this is a uncommon case use a separate early page talk -walk pass for MMIO PROT_NONE mappings that checks for this condition -early. For non MMIO and non PROT_NONE there are no changes. - -Signed-off-by: Andi Kleen -Signed-off-by: Thomas Gleixner -Reviewed-by: Josh Poimboeuf -Acked-by: Dave Hansen -Signed-off-by: Greg Kroah-Hartman ---- - arch/x86/include/asm/pgtable.h | 8 ++++++ - arch/x86/mm/mmap.c | 21 +++++++++++++++++ - include/asm-generic/pgtable.h | 12 ++++++++++ - mm/memory.c | 37 ++++++++++++++++++++++-------- - mm/mprotect.c | 49 +++++++++++++++++++++++++++++++++++++++++ - 5 files changed, 117 insertions(+), 10 deletions(-) - ---- a/arch/x86/include/asm/pgtable.h -+++ b/arch/x86/include/asm/pgtable.h -@@ -1338,6 +1338,14 @@ static inline bool pud_access_permitted( - return __pte_access_permitted(pud_val(pud), write); - } - -+#define __HAVE_ARCH_PFN_MODIFY_ALLOWED 1 -+extern bool pfn_modify_allowed(unsigned long pfn, pgprot_t prot); -+ -+static inline bool arch_has_pfn_modify_check(void) -+{ -+ return boot_cpu_has_bug(X86_BUG_L1TF); -+} -+ - #include - #endif /* __ASSEMBLY__ */ - ---- a/arch/x86/mm/mmap.c -+++ b/arch/x86/mm/mmap.c -@@ -240,3 +240,24 @@ int valid_mmap_phys_addr_range(unsigned - - return phys_addr_valid(addr + count - 1); - } -+ -+/* -+ * Only allow root to set high MMIO mappings to PROT_NONE. -+ * This prevents an unpriv. user to set them to PROT_NONE and invert -+ * them, then pointing to valid memory for L1TF speculation. -+ * -+ * Note: for locked down kernels may want to disable the root override. -+ */ -+bool pfn_modify_allowed(unsigned long pfn, pgprot_t prot) -+{ -+ if (!boot_cpu_has_bug(X86_BUG_L1TF)) -+ return true; -+ if (!__pte_needs_invert(pgprot_val(prot))) -+ return true; -+ /* If it's real memory always allow */ -+ if (pfn_valid(pfn)) -+ return true; -+ if (pfn > l1tf_pfn_limit() && !capable(CAP_SYS_ADMIN)) -+ return false; -+ return true; -+} ---- a/include/asm-generic/pgtable.h -+++ b/include/asm-generic/pgtable.h -@@ -1097,4 +1097,16 @@ static inline void init_espfix_bsp(void) - #endif - #endif - -+#ifndef __HAVE_ARCH_PFN_MODIFY_ALLOWED -+static inline bool pfn_modify_allowed(unsigned long pfn, pgprot_t prot) -+{ -+ return true; -+} -+ -+static inline bool arch_has_pfn_modify_check(void) -+{ -+ return false; -+} -+#endif -+ - #endif /* _ASM_GENERIC_PGTABLE_H */ ---- a/mm/memory.c -+++ b/mm/memory.c -@@ -1891,6 +1891,9 @@ int vm_insert_pfn_prot(struct vm_area_st - if (addr < vma->vm_start || addr >= vma->vm_end) - return -EFAULT; - -+ if (!pfn_modify_allowed(pfn, pgprot)) -+ return -EACCES; -+ - track_pfn_insert(vma, &pgprot, __pfn_to_pfn_t(pfn, PFN_DEV)); - - ret = insert_pfn(vma, addr, __pfn_to_pfn_t(pfn, PFN_DEV), pgprot, -@@ -1926,6 +1929,9 @@ static int __vm_insert_mixed(struct vm_a - - track_pfn_insert(vma, &pgprot, pfn); - -+ if (!pfn_modify_allowed(pfn_t_to_pfn(pfn), pgprot)) -+ return -EACCES; -+ - /* - * If we don't have pte special, then we have to use the pfn_valid() - * based VM_MIXEDMAP scheme (see vm_normal_page), and thus we *must* -@@ -1973,6 +1979,7 @@ static int remap_pte_range(struct mm_str - { - pte_t *pte; - spinlock_t *ptl; -+ int err = 0; - - pte = pte_alloc_map_lock(mm, pmd, addr, &ptl); - if (!pte) -@@ -1980,12 +1987,16 @@ static int remap_pte_range(struct mm_str - arch_enter_lazy_mmu_mode(); - do { - BUG_ON(!pte_none(*pte)); -+ if (!pfn_modify_allowed(pfn, prot)) { -+ err = -EACCES; -+ break; -+ } - set_pte_at(mm, addr, pte, pte_mkspecial(pfn_pte(pfn, prot))); - pfn++; - } while (pte++, addr += PAGE_SIZE, addr != end); - arch_leave_lazy_mmu_mode(); - pte_unmap_unlock(pte - 1, ptl); -- return 0; -+ return err; - } - - static inline int remap_pmd_range(struct mm_struct *mm, pud_t *pud, -@@ -1994,6 +2005,7 @@ static inline int remap_pmd_range(struct - { - pmd_t *pmd; - unsigned long next; -+ int err; - - pfn -= addr >> PAGE_SHIFT; - pmd = pmd_alloc(mm, pud, addr); -@@ -2002,9 +2014,10 @@ static inline int remap_pmd_range(struct - VM_BUG_ON(pmd_trans_huge(*pmd)); - do { - next = pmd_addr_end(addr, end); -- if (remap_pte_range(mm, pmd, addr, next, -- pfn + (addr >> PAGE_SHIFT), prot)) -- return -ENOMEM; -+ err = remap_pte_range(mm, pmd, addr, next, -+ pfn + (addr >> PAGE_SHIFT), prot); -+ if (err) -+ return err; - } while (pmd++, addr = next, addr != end); - return 0; - } -@@ -2015,6 +2028,7 @@ static inline int remap_pud_range(struct - { - pud_t *pud; - unsigned long next; -+ int err; - - pfn -= addr >> PAGE_SHIFT; - pud = pud_alloc(mm, p4d, addr); -@@ -2022,9 +2036,10 @@ static inline int remap_pud_range(struct - return -ENOMEM; - do { - next = pud_addr_end(addr, end); -- if (remap_pmd_range(mm, pud, addr, next, -- pfn + (addr >> PAGE_SHIFT), prot)) -- return -ENOMEM; -+ err = remap_pmd_range(mm, pud, addr, next, -+ pfn + (addr >> PAGE_SHIFT), prot); -+ if (err) -+ return err; - } while (pud++, addr = next, addr != end); - return 0; - } -@@ -2035,6 +2050,7 @@ static inline int remap_p4d_range(struct - { - p4d_t *p4d; - unsigned long next; -+ int err; - - pfn -= addr >> PAGE_SHIFT; - p4d = p4d_alloc(mm, pgd, addr); -@@ -2042,9 +2058,10 @@ static inline int remap_p4d_range(struct - return -ENOMEM; - do { - next = p4d_addr_end(addr, end); -- if (remap_pud_range(mm, p4d, addr, next, -- pfn + (addr >> PAGE_SHIFT), prot)) -- return -ENOMEM; -+ err = remap_pud_range(mm, p4d, addr, next, -+ pfn + (addr >> PAGE_SHIFT), prot); -+ if (err) -+ return err; - } while (p4d++, addr = next, addr != end); - return 0; - } ---- a/mm/mprotect.c -+++ b/mm/mprotect.c -@@ -306,6 +306,42 @@ unsigned long change_protection(struct v - return pages; - } - -+static int prot_none_pte_entry(pte_t *pte, unsigned long addr, -+ unsigned long next, struct mm_walk *walk) -+{ -+ return pfn_modify_allowed(pte_pfn(*pte), *(pgprot_t *)(walk->private)) ? -+ 0 : -EACCES; -+} -+ -+static int prot_none_hugetlb_entry(pte_t *pte, unsigned long hmask, -+ unsigned long addr, unsigned long next, -+ struct mm_walk *walk) -+{ -+ return pfn_modify_allowed(pte_pfn(*pte), *(pgprot_t *)(walk->private)) ? -+ 0 : -EACCES; -+} -+ -+static int prot_none_test(unsigned long addr, unsigned long next, -+ struct mm_walk *walk) -+{ -+ return 0; -+} -+ -+static int prot_none_walk(struct vm_area_struct *vma, unsigned long start, -+ unsigned long end, unsigned long newflags) -+{ -+ pgprot_t new_pgprot = vm_get_page_prot(newflags); -+ struct mm_walk prot_none_walk = { -+ .pte_entry = prot_none_pte_entry, -+ .hugetlb_entry = prot_none_hugetlb_entry, -+ .test_walk = prot_none_test, -+ .mm = current->mm, -+ .private = &new_pgprot, -+ }; -+ -+ return walk_page_range(start, end, &prot_none_walk); -+} -+ - int - mprotect_fixup(struct vm_area_struct *vma, struct vm_area_struct **pprev, - unsigned long start, unsigned long end, unsigned long newflags) -@@ -324,6 +360,19 @@ mprotect_fixup(struct vm_area_struct *vm - } - - /* -+ * Do PROT_NONE PFN permission checks here when we can still -+ * bail out without undoing a lot of state. This is a rather -+ * uncommon case, so doesn't need to be very optimized. -+ */ -+ if (arch_has_pfn_modify_check() && -+ (vma->vm_flags & (VM_PFNMAP|VM_MIXEDMAP)) && -+ (newflags & (VM_READ|VM_WRITE|VM_EXEC)) == 0) { -+ error = prot_none_walk(vma, start, end, newflags); -+ if (error) -+ return error; -+ } -+ -+ /* - * If we make a private mapping writable we increase our commit; - * but (without finer accounting) cannot reduce our commit if we - * make it unwritable again. hugetlb mapping were accounted for -From foo@baz Tue Aug 14 13:43:10 CEST 2018 -From: Andi Kleen -Date: Wed, 13 Jun 2018 15:48:28 -0700 -Subject: x86/speculation/l1tf: Limit swap file size to MAX_PA/2 - -From: Andi Kleen - -commit 377eeaa8e11fe815b1d07c81c4a0e2843a8c15eb upstream - -For the L1TF workaround its necessary to limit the swap file size to below -MAX_PA/2, so that the higher bits of the swap offset inverted never point -to valid memory. - -Add a mechanism for the architecture to override the swap file size check -in swapfile.c and add a x86 specific max swapfile check function that -enforces that limit. - -The check is only enabled if the CPU is vulnerable to L1TF. - -In VMs with 42bit MAX_PA the typical limit is 2TB now, on a native system -with 46bit PA it is 32TB. The limit is only per individual swap file, so -it's always possible to exceed these limits with multiple swap files or -partitions. - -Signed-off-by: Andi Kleen -Signed-off-by: Thomas Gleixner -Reviewed-by: Josh Poimboeuf -Acked-by: Michal Hocko -Acked-by: Dave Hansen -Signed-off-by: Greg Kroah-Hartman ---- - arch/x86/mm/init.c | 15 +++++++++++++++ - include/linux/swapfile.h | 2 ++ - mm/swapfile.c | 46 ++++++++++++++++++++++++++++++---------------- - 3 files changed, 47 insertions(+), 16 deletions(-) - ---- a/arch/x86/mm/init.c -+++ b/arch/x86/mm/init.c -@@ -4,6 +4,8 @@ - #include - #include - #include /* for max_low_pfn */ -+#include -+#include - - #include - #include -@@ -880,3 +882,16 @@ void update_cache_mode_entry(unsigned en - __cachemode2pte_tbl[cache] = __cm_idx2pte(entry); - __pte2cachemode_tbl[entry] = cache; - } -+ -+unsigned long max_swapfile_size(void) -+{ -+ unsigned long pages; -+ -+ pages = generic_max_swapfile_size(); -+ -+ if (boot_cpu_has_bug(X86_BUG_L1TF)) { -+ /* Limit the swap file size to MAX_PA/2 for L1TF workaround */ -+ pages = min_t(unsigned long, l1tf_pfn_limit() + 1, pages); -+ } -+ return pages; -+} ---- a/include/linux/swapfile.h -+++ b/include/linux/swapfile.h -@@ -10,5 +10,7 @@ extern spinlock_t swap_lock; - extern struct plist_head swap_active_head; - extern struct swap_info_struct *swap_info[]; - extern int try_to_unuse(unsigned int, bool, unsigned long); -+extern unsigned long generic_max_swapfile_size(void); -+extern unsigned long max_swapfile_size(void); - - #endif /* _LINUX_SWAPFILE_H */ ---- a/mm/swapfile.c -+++ b/mm/swapfile.c -@@ -2909,6 +2909,35 @@ static int claim_swapfile(struct swap_in - return 0; - } - -+ -+/* -+ * Find out how many pages are allowed for a single swap device. There -+ * are two limiting factors: -+ * 1) the number of bits for the swap offset in the swp_entry_t type, and -+ * 2) the number of bits in the swap pte, as defined by the different -+ * architectures. -+ * -+ * In order to find the largest possible bit mask, a swap entry with -+ * swap type 0 and swap offset ~0UL is created, encoded to a swap pte, -+ * decoded to a swp_entry_t again, and finally the swap offset is -+ * extracted. -+ * -+ * This will mask all the bits from the initial ~0UL mask that can't -+ * be encoded in either the swp_entry_t or the architecture definition -+ * of a swap pte. -+ */ -+unsigned long generic_max_swapfile_size(void) -+{ -+ return swp_offset(pte_to_swp_entry( -+ swp_entry_to_pte(swp_entry(0, ~0UL)))) + 1; -+} -+ -+/* Can be overridden by an architecture for additional checks. */ -+__weak unsigned long max_swapfile_size(void) -+{ -+ return generic_max_swapfile_size(); -+} -+ - static unsigned long read_swap_header(struct swap_info_struct *p, - union swap_header *swap_header, - struct inode *inode) -@@ -2944,22 +2973,7 @@ static unsigned long read_swap_header(st - p->cluster_next = 1; - p->cluster_nr = 0; - -- /* -- * Find out how many pages are allowed for a single swap -- * device. There are two limiting factors: 1) the number -- * of bits for the swap offset in the swp_entry_t type, and -- * 2) the number of bits in the swap pte as defined by the -- * different architectures. In order to find the -- * largest possible bit mask, a swap entry with swap type 0 -- * and swap offset ~0UL is created, encoded to a swap pte, -- * decoded to a swp_entry_t again, and finally the swap -- * offset is extracted. This will mask all the bits from -- * the initial ~0UL mask that can't be encoded in either -- * the swp_entry_t or the architecture definition of a -- * swap pte. -- */ -- maxpages = swp_offset(pte_to_swp_entry( -- swp_entry_to_pte(swp_entry(0, ~0UL)))) + 1; -+ maxpages = max_swapfile_size(); - last_page = swap_header->info.last_page; - if (!last_page) { - pr_warn("Empty swap-file\n"); -From foo@baz Tue Aug 14 13:43:10 CEST 2018 -From: Konrad Rzeszutek Wilk -Date: Wed, 20 Jun 2018 16:42:57 -0400 -Subject: x86/bugs: Move the l1tf function and define pr_fmt properly - -From: Konrad Rzeszutek Wilk - -commit 56563f53d3066afa9e63d6c997bf67e76a8b05c0 upstream - -The pr_warn in l1tf_select_mitigation would have used the prior pr_fmt -which was defined as "Spectre V2 : ". - -Move the function to be past SSBD and also define the pr_fmt. - -Fixes: 17dbca119312 ("x86/speculation/l1tf: Add sysfs reporting for l1tf") -Signed-off-by: Konrad Rzeszutek Wilk -Signed-off-by: Thomas Gleixner -Signed-off-by: Greg Kroah-Hartman ---- - arch/x86/kernel/cpu/bugs.c | 55 +++++++++++++++++++++++---------------------- - 1 file changed, 29 insertions(+), 26 deletions(-) - ---- a/arch/x86/kernel/cpu/bugs.c -+++ b/arch/x86/kernel/cpu/bugs.c -@@ -209,32 +209,6 @@ static void x86_amd_ssb_disable(void) - wrmsrl(MSR_AMD64_LS_CFG, msrval); - } - --static void __init l1tf_select_mitigation(void) --{ -- u64 half_pa; -- -- if (!boot_cpu_has_bug(X86_BUG_L1TF)) -- return; -- --#if CONFIG_PGTABLE_LEVELS == 2 -- pr_warn("Kernel not compiled for PAE. No mitigation for L1TF\n"); -- return; --#endif -- -- /* -- * This is extremely unlikely to happen because almost all -- * systems have far more MAX_PA/2 than RAM can be fit into -- * DIMM slots. -- */ -- half_pa = (u64)l1tf_pfn_limit() << PAGE_SHIFT; -- if (e820__mapped_any(half_pa, ULLONG_MAX - half_pa, E820_TYPE_RAM)) { -- pr_warn("System has more than MAX_PA/2 memory. L1TF mitigation not effective.\n"); -- return; -- } -- -- setup_force_cpu_cap(X86_FEATURE_L1TF_PTEINV); --} -- - #ifdef RETPOLINE - static bool spectre_v2_bad_module; - -@@ -660,6 +634,35 @@ void x86_spec_ctrl_setup_ap(void) - x86_amd_ssb_disable(); - } - -+#undef pr_fmt -+#define pr_fmt(fmt) "L1TF: " fmt -+static void __init l1tf_select_mitigation(void) -+{ -+ u64 half_pa; -+ -+ if (!boot_cpu_has_bug(X86_BUG_L1TF)) -+ return; -+ -+#if CONFIG_PGTABLE_LEVELS == 2 -+ pr_warn("Kernel not compiled for PAE. No mitigation for L1TF\n"); -+ return; -+#endif -+ -+ /* -+ * This is extremely unlikely to happen because almost all -+ * systems have far more MAX_PA/2 than RAM can be fit into -+ * DIMM slots. -+ */ -+ half_pa = (u64)l1tf_pfn_limit() << PAGE_SHIFT; -+ if (e820__mapped_any(half_pa, ULLONG_MAX - half_pa, E820_TYPE_RAM)) { -+ pr_warn("System has more than MAX_PA/2 memory. L1TF mitigation not effective.\n"); -+ return; -+ } -+ -+ setup_force_cpu_cap(X86_FEATURE_L1TF_PTEINV); -+} -+#undef pr_fmt -+ - #ifdef CONFIG_SYSFS - - static ssize_t cpu_show_common(struct device *dev, struct device_attribute *attr, -From foo@baz Tue Aug 14 13:43:10 CEST 2018 -From: Peter Zijlstra -Date: Tue, 29 May 2018 16:43:46 +0200 -Subject: sched/smt: Update sched_smt_present at runtime - -From: Peter Zijlstra - -commit ba2591a5993eabcc8e874e30f361d8ffbb10d6d4 upstream - -The static key sched_smt_present is only updated at boot time when SMT -siblings have been detected. Booting with maxcpus=1 and bringing the -siblings online after boot rebuilds the scheduling domains correctly but -does not update the static key, so the SMT code is not enabled. - -Let the key be updated in the scheduler CPU hotplug code to fix this. - -Signed-off-by: Peter Zijlstra -Signed-off-by: Thomas Gleixner -Reviewed-by: Konrad Rzeszutek Wilk -Acked-by: Ingo Molnar -Signed-off-by: Greg Kroah-Hartman ---- - kernel/sched/core.c | 30 ++++++++++++------------------ - kernel/sched/fair.c | 1 + - 2 files changed, 13 insertions(+), 18 deletions(-) - ---- a/kernel/sched/core.c -+++ b/kernel/sched/core.c -@@ -5788,6 +5788,18 @@ int sched_cpu_activate(unsigned int cpu) - struct rq *rq = cpu_rq(cpu); - struct rq_flags rf; - -+#ifdef CONFIG_SCHED_SMT -+ /* -+ * The sched_smt_present static key needs to be evaluated on every -+ * hotplug event because at boot time SMT might be disabled when -+ * the number of booted CPUs is limited. -+ * -+ * If then later a sibling gets hotplugged, then the key would stay -+ * off and SMT scheduling would never be functional. -+ */ -+ if (cpumask_weight(cpu_smt_mask(cpu)) > 1) -+ static_branch_enable_cpuslocked(&sched_smt_present); -+#endif - set_cpu_active(cpu, true); - - if (sched_smp_initialized) { -@@ -5885,22 +5897,6 @@ int sched_cpu_dying(unsigned int cpu) - } - #endif - --#ifdef CONFIG_SCHED_SMT --DEFINE_STATIC_KEY_FALSE(sched_smt_present); -- --static void sched_init_smt(void) --{ -- /* -- * We've enumerated all CPUs and will assume that if any CPU -- * has SMT siblings, CPU0 will too. -- */ -- if (cpumask_weight(cpu_smt_mask(0)) > 1) -- static_branch_enable(&sched_smt_present); --} --#else --static inline void sched_init_smt(void) { } --#endif -- - void __init sched_init_smp(void) - { - sched_init_numa(); -@@ -5922,8 +5918,6 @@ void __init sched_init_smp(void) - init_sched_rt_class(); - init_sched_dl_class(); - -- sched_init_smt(); -- - sched_smp_initialized = true; - } - ---- a/kernel/sched/fair.c -+++ b/kernel/sched/fair.c -@@ -6183,6 +6183,7 @@ static inline int find_idlest_cpu(struct - } - - #ifdef CONFIG_SCHED_SMT -+DEFINE_STATIC_KEY_FALSE(sched_smt_present); - - static inline void set_idle_cores(int cpu, int val) - { -From foo@baz Tue Aug 14 13:43:10 CEST 2018 -From: Thomas Gleixner -Date: Tue, 29 May 2018 17:50:22 +0200 -Subject: x86/smp: Provide topology_is_primary_thread() - -From: Thomas Gleixner - -commit 6a4d2657e048f096c7ffcad254010bd94891c8c0 upstream - -If the CPU is supporting SMT then the primary thread can be found by -checking the lower APIC ID bits for zero. smp_num_siblings is used to build -the mask for the APIC ID bits which need to be taken into account. - -This uses the MPTABLE or ACPI/MADT supplied APIC ID, which can be different -than the initial APIC ID in CPUID. But according to AMD the lower bits have -to be consistent. Intel gave a tentative confirmation as well. - -Preparatory patch to support disabling SMT at boot/runtime. - -Signed-off-by: Thomas Gleixner -Reviewed-by: Konrad Rzeszutek Wilk -Acked-by: Ingo Molnar -Signed-off-by: Greg Kroah-Hartman ---- - arch/x86/include/asm/apic.h | 6 ++++++ - arch/x86/include/asm/topology.h | 4 +++- - arch/x86/kernel/apic/apic.c | 15 +++++++++++++++ - arch/x86/kernel/smpboot.c | 9 +++++++++ - 4 files changed, 33 insertions(+), 1 deletion(-) - ---- a/arch/x86/include/asm/apic.h -+++ b/arch/x86/include/asm/apic.h -@@ -502,6 +502,12 @@ extern int default_check_phys_apicid_pre - - #endif /* CONFIG_X86_LOCAL_APIC */ - -+#ifdef CONFIG_SMP -+bool apic_id_is_primary_thread(unsigned int id); -+#else -+static inline bool apic_id_is_primary_thread(unsigned int id) { return false; } -+#endif -+ - extern void irq_enter(void); - extern void irq_exit(void); - ---- a/arch/x86/include/asm/topology.h -+++ b/arch/x86/include/asm/topology.h -@@ -123,13 +123,15 @@ static inline int topology_max_smt_threa - } - - int topology_update_package_map(unsigned int apicid, unsigned int cpu); --extern int topology_phys_to_logical_pkg(unsigned int pkg); -+int topology_phys_to_logical_pkg(unsigned int pkg); -+bool topology_is_primary_thread(unsigned int cpu); - #else - #define topology_max_packages() (1) - static inline int - topology_update_package_map(unsigned int apicid, unsigned int cpu) { return 0; } - static inline int topology_phys_to_logical_pkg(unsigned int pkg) { return 0; } - static inline int topology_max_smt_threads(void) { return 1; } -+static inline bool topology_is_primary_thread(unsigned int cpu) { return true; } - #endif - - static inline void arch_fix_phys_package_id(int num, u32 slot) ---- a/arch/x86/kernel/apic/apic.c -+++ b/arch/x86/kernel/apic/apic.c -@@ -2192,6 +2192,21 @@ static int cpuid_to_apicid[] = { - [0 ... NR_CPUS - 1] = -1, - }; - -+/** -+ * apic_id_is_primary_thread - Check whether APIC ID belongs to a primary thread -+ * @id: APIC ID to check -+ */ -+bool apic_id_is_primary_thread(unsigned int apicid) -+{ -+ u32 mask; -+ -+ if (smp_num_siblings == 1) -+ return true; -+ /* Isolate the SMT bit(s) in the APICID and check for 0 */ -+ mask = (1U << (fls(smp_num_siblings) - 1)) - 1; -+ return !(apicid & mask); -+} -+ - /* - * Should use this API to allocate logical CPU IDs to keep nr_logical_cpuids - * and cpuid_to_apicid[] synchronized. ---- a/arch/x86/kernel/smpboot.c -+++ b/arch/x86/kernel/smpboot.c -@@ -273,6 +273,15 @@ static void notrace start_secondary(void - } - - /** -+ * topology_is_primary_thread - Check whether CPU is the primary SMT thread -+ * @cpu: CPU to check -+ */ -+bool topology_is_primary_thread(unsigned int cpu) -+{ -+ return apic_id_is_primary_thread(per_cpu(x86_cpu_to_apicid, cpu)); -+} -+ -+/** - * topology_phys_to_logical_pkg - Map a physical package id to a logical - * - * Returns logical package id or -1 if not found -From foo@baz Tue Aug 14 13:43:10 CEST 2018 -From: Thomas Gleixner -Date: Thu, 21 Jun 2018 10:37:20 +0200 -Subject: x86/topology: Provide topology_smt_supported() - -From: Thomas Gleixner - -commit f048c399e0f7490ab7296bc2c255d37eb14a9675 upstream - -Provide information whether SMT is supoorted by the CPUs. Preparatory patch -for SMT control mechanism. - -Suggested-by: Dave Hansen -Signed-off-by: Thomas Gleixner -Acked-by: Ingo Molnar -Signed-off-by: Greg Kroah-Hartman ---- - arch/x86/include/asm/topology.h | 2 ++ - arch/x86/kernel/smpboot.c | 8 ++++++++ - 2 files changed, 10 insertions(+) - ---- a/arch/x86/include/asm/topology.h -+++ b/arch/x86/include/asm/topology.h -@@ -125,6 +125,7 @@ static inline int topology_max_smt_threa - int topology_update_package_map(unsigned int apicid, unsigned int cpu); - int topology_phys_to_logical_pkg(unsigned int pkg); - bool topology_is_primary_thread(unsigned int cpu); -+bool topology_smt_supported(void); - #else - #define topology_max_packages() (1) - static inline int -@@ -132,6 +133,7 @@ topology_update_package_map(unsigned int - static inline int topology_phys_to_logical_pkg(unsigned int pkg) { return 0; } - static inline int topology_max_smt_threads(void) { return 1; } - static inline bool topology_is_primary_thread(unsigned int cpu) { return true; } -+static inline bool topology_smt_supported(void) { return false; } - #endif - - static inline void arch_fix_phys_package_id(int num, u32 slot) ---- a/arch/x86/kernel/smpboot.c -+++ b/arch/x86/kernel/smpboot.c -@@ -282,6 +282,14 @@ bool topology_is_primary_thread(unsigned - } - - /** -+ * topology_smt_supported - Check whether SMT is supported by the CPUs -+ */ -+bool topology_smt_supported(void) -+{ -+ return smp_num_siblings > 1; -+} -+ -+/** - * topology_phys_to_logical_pkg - Map a physical package id to a logical - * - * Returns logical package id or -1 if not found -From foo@baz Tue Aug 14 13:43:10 CEST 2018 -From: Thomas Gleixner -Date: Tue, 29 May 2018 19:05:25 +0200 -Subject: cpu/hotplug: Make bringup/teardown of smp threads symmetric - -From: Thomas Gleixner - -commit c4de65696d865c225fda3b9913b31284ea65ea96 upstream - -The asymmetry caused a warning to trigger if the bootup was stopped in state -CPUHP_AP_ONLINE_IDLE. The warning no longer triggers as kthread_park() can -now be invoked on already or still parked threads. But there is still no -reason to have this be asymmetric. - -Signed-off-by: Thomas Gleixner -Reviewed-by: Konrad Rzeszutek Wilk -Acked-by: Ingo Molnar -Signed-off-by: Greg Kroah-Hartman ---- - kernel/cpu.c | 3 +-- - 1 file changed, 1 insertion(+), 2 deletions(-) - ---- a/kernel/cpu.c -+++ b/kernel/cpu.c -@@ -754,7 +754,6 @@ static int takedown_cpu(unsigned int cpu - - /* Park the smpboot threads */ - kthread_park(per_cpu_ptr(&cpuhp_state, cpu)->thread); -- smpboot_park_threads(cpu); - - /* - * Prevent irq alloc/free while the dying cpu reorganizes the -@@ -1332,7 +1331,7 @@ static struct cpuhp_step cpuhp_hp_states - [CPUHP_AP_SMPBOOT_THREADS] = { - .name = "smpboot/threads:online", - .startup.single = smpboot_unpark_threads, -- .teardown.single = NULL, -+ .teardown.single = smpboot_park_threads, - }, - [CPUHP_AP_IRQ_AFFINITY_ONLINE] = { - .name = "irq/affinity:online", -From foo@baz Tue Aug 14 13:43:10 CEST 2018 -From: Thomas Gleixner -Date: Tue, 29 May 2018 17:49:05 +0200 -Subject: cpu/hotplug: Split do_cpu_down() - -From: Thomas Gleixner - -commit cc1fe215e1efa406b03aa4389e6269b61342dec5 upstream - -Split out the inner workings of do_cpu_down() to allow reuse of that -function for the upcoming SMT disabling mechanism. - -No functional change. - -Signed-off-by: Thomas Gleixner -Reviewed-by: Konrad Rzeszutek Wilk -Acked-by: Ingo Molnar -Signed-off-by: Greg Kroah-Hartman ---- - kernel/cpu.c | 17 ++++++++--------- - 1 file changed, 8 insertions(+), 9 deletions(-) - ---- a/kernel/cpu.c -+++ b/kernel/cpu.c -@@ -906,20 +906,19 @@ out: - return ret; - } - -+static int cpu_down_maps_locked(unsigned int cpu, enum cpuhp_state target) -+{ -+ if (cpu_hotplug_disabled) -+ return -EBUSY; -+ return _cpu_down(cpu, 0, target); -+} -+ - static int do_cpu_down(unsigned int cpu, enum cpuhp_state target) - { - int err; - - cpu_maps_update_begin(); -- -- if (cpu_hotplug_disabled) { -- err = -EBUSY; -- goto out; -- } -- -- err = _cpu_down(cpu, 0, target); -- --out: -+ err = cpu_down_maps_locked(cpu, target); - cpu_maps_update_done(); - return err; - } -From foo@baz Tue Aug 14 13:43:10 CEST 2018 -From: Thomas Gleixner -Date: Tue, 29 May 2018 17:48:27 +0200 -Subject: cpu/hotplug: Provide knobs to control SMT - -From: Thomas Gleixner - -commit 05736e4ac13c08a4a9b1ef2de26dd31a32cbee57 upstream - -Provide a command line and a sysfs knob to control SMT. - -The command line options are: - - 'nosmt': Enumerate secondary threads, but do not online them - - 'nosmt=force': Ignore secondary threads completely during enumeration - via MP table and ACPI/MADT. - -The sysfs control file has the following states (read/write): - - 'on': SMT is enabled. Secondary threads can be freely onlined - 'off': SMT is disabled. Secondary threads, even if enumerated - cannot be onlined - 'forceoff': SMT is permanentely disabled. Writes to the control - file are rejected. - 'notsupported': SMT is not supported by the CPU - -The command line option 'nosmt' sets the sysfs control to 'off'. This -can be changed to 'on' to reenable SMT during runtime. - -The command line option 'nosmt=force' sets the sysfs control to -'forceoff'. This cannot be changed during runtime. - -When SMT is 'on' and the control file is changed to 'off' then all online -secondary threads are offlined and attempts to online a secondary thread -later on are rejected. - -When SMT is 'off' and the control file is changed to 'on' then secondary -threads can be onlined again. The 'off' -> 'on' transition does not -automatically online the secondary threads. - -When the control file is set to 'forceoff', the behaviour is the same as -setting it to 'off', but the operation is irreversible and later writes to -the control file are rejected. - -When the control status is 'notsupported' then writes to the control file -are rejected. - -Signed-off-by: Thomas Gleixner -Reviewed-by: Konrad Rzeszutek Wilk -Acked-by: Ingo Molnar -Signed-off-by: Greg Kroah-Hartman ---- - Documentation/ABI/testing/sysfs-devices-system-cpu | 20 ++ - Documentation/admin-guide/kernel-parameters.txt | 8 - arch/Kconfig | 3 - arch/x86/Kconfig | 1 - include/linux/cpu.h | 13 + - kernel/cpu.c | 170 +++++++++++++++++++++ - 6 files changed, 215 insertions(+) - ---- a/Documentation/ABI/testing/sysfs-devices-system-cpu -+++ b/Documentation/ABI/testing/sysfs-devices-system-cpu -@@ -490,3 +490,23 @@ Description: Information about CPU vulne - "Not affected" CPU is not affected by the vulnerability - "Vulnerable" CPU is affected and no mitigation in effect - "Mitigation: $M" CPU is affected and mitigation $M is in effect -+ -+What: /sys/devices/system/cpu/smt -+ /sys/devices/system/cpu/smt/active -+ /sys/devices/system/cpu/smt/control -+Date: June 2018 -+Contact: Linux kernel mailing list -+Description: Control Symetric Multi Threading (SMT) -+ -+ active: Tells whether SMT is active (enabled and siblings online) -+ -+ control: Read/write interface to control SMT. Possible -+ values: -+ -+ "on" SMT is enabled -+ "off" SMT is disabled -+ "forceoff" SMT is force disabled. Cannot be changed. -+ "notsupported" SMT is not supported by the CPU -+ -+ If control status is "forceoff" or "notsupported" writes -+ are rejected. ---- a/Documentation/admin-guide/kernel-parameters.txt -+++ b/Documentation/admin-guide/kernel-parameters.txt -@@ -2675,6 +2675,14 @@ - nosmt [KNL,S390] Disable symmetric multithreading (SMT). - Equivalent to smt=1. - -+ [KNL,x86] Disable symmetric multithreading (SMT). -+ nosmt=force: Force disable SMT, similar to disabling -+ it in the BIOS except that some of the -+ resource partitioning effects which are -+ caused by having SMT enabled in the BIOS -+ cannot be undone. Depending on the CPU -+ type this might have a performance impact. -+ - nospectre_v2 [X86] Disable all mitigations for the Spectre variant 2 - (indirect branch prediction) vulnerability. System may - allow data leaks with this option, which is equivalent ---- a/arch/Kconfig -+++ b/arch/Kconfig -@@ -13,6 +13,9 @@ config KEXEC_CORE - config HAVE_IMA_KEXEC - bool - -+config HOTPLUG_SMT -+ bool -+ - config OPROFILE - tristate "OProfile system profiling" - depends on PROFILING ---- a/arch/x86/Kconfig -+++ b/arch/x86/Kconfig -@@ -183,6 +183,7 @@ config X86 - select HAVE_SYSCALL_TRACEPOINTS - select HAVE_UNSTABLE_SCHED_CLOCK - select HAVE_USER_RETURN_NOTIFIER -+ select HOTPLUG_SMT if SMP - select IRQ_FORCED_THREADING - select PCI_LOCKLESS_CONFIG - select PERF_EVENTS ---- a/include/linux/cpu.h -+++ b/include/linux/cpu.h -@@ -168,4 +168,17 @@ void cpuhp_report_idle_dead(void); - static inline void cpuhp_report_idle_dead(void) { } - #endif /* #ifdef CONFIG_HOTPLUG_CPU */ - -+enum cpuhp_smt_control { -+ CPU_SMT_ENABLED, -+ CPU_SMT_DISABLED, -+ CPU_SMT_FORCE_DISABLED, -+ CPU_SMT_NOT_SUPPORTED, -+}; -+ -+#if defined(CONFIG_SMP) && defined(CONFIG_HOTPLUG_SMT) -+extern enum cpuhp_smt_control cpu_smt_control; -+#else -+# define cpu_smt_control (CPU_SMT_ENABLED) -+#endif -+ - #endif /* _LINUX_CPU_H_ */ ---- a/kernel/cpu.c -+++ b/kernel/cpu.c -@@ -933,6 +933,29 @@ EXPORT_SYMBOL(cpu_down); - #define takedown_cpu NULL - #endif /*CONFIG_HOTPLUG_CPU*/ - -+#ifdef CONFIG_HOTPLUG_SMT -+enum cpuhp_smt_control cpu_smt_control __read_mostly = CPU_SMT_ENABLED; -+ -+static int __init smt_cmdline_disable(char *str) -+{ -+ cpu_smt_control = CPU_SMT_DISABLED; -+ if (str && !strcmp(str, "force")) { -+ pr_info("SMT: Force disabled\n"); -+ cpu_smt_control = CPU_SMT_FORCE_DISABLED; -+ } -+ return 0; -+} -+early_param("nosmt", smt_cmdline_disable); -+ -+static inline bool cpu_smt_allowed(unsigned int cpu) -+{ -+ return cpu_smt_control == CPU_SMT_ENABLED || -+ topology_is_primary_thread(cpu); -+} -+#else -+static inline bool cpu_smt_allowed(unsigned int cpu) { return true; } -+#endif -+ - /** - * notify_cpu_starting(cpu) - Invoke the callbacks on the starting CPU - * @cpu: cpu that just started -@@ -1056,6 +1079,10 @@ static int do_cpu_up(unsigned int cpu, e - err = -EBUSY; - goto out; - } -+ if (!cpu_smt_allowed(cpu)) { -+ err = -EPERM; -+ goto out; -+ } - - err = _cpu_up(cpu, 0, target); - out: -@@ -1904,10 +1931,153 @@ static const struct attribute_group cpuh - NULL - }; - -+#ifdef CONFIG_HOTPLUG_SMT -+ -+static const char *smt_states[] = { -+ [CPU_SMT_ENABLED] = "on", -+ [CPU_SMT_DISABLED] = "off", -+ [CPU_SMT_FORCE_DISABLED] = "forceoff", -+ [CPU_SMT_NOT_SUPPORTED] = "notsupported", -+}; -+ -+static ssize_t -+show_smt_control(struct device *dev, struct device_attribute *attr, char *buf) -+{ -+ return snprintf(buf, PAGE_SIZE - 2, "%s\n", smt_states[cpu_smt_control]); -+} -+ -+static void cpuhp_offline_cpu_device(unsigned int cpu) -+{ -+ struct device *dev = get_cpu_device(cpu); -+ -+ dev->offline = true; -+ /* Tell user space about the state change */ -+ kobject_uevent(&dev->kobj, KOBJ_OFFLINE); -+} -+ -+static int cpuhp_smt_disable(enum cpuhp_smt_control ctrlval) -+{ -+ int cpu, ret = 0; -+ -+ cpu_maps_update_begin(); -+ for_each_online_cpu(cpu) { -+ if (topology_is_primary_thread(cpu)) -+ continue; -+ ret = cpu_down_maps_locked(cpu, CPUHP_OFFLINE); -+ if (ret) -+ break; -+ /* -+ * As this needs to hold the cpu maps lock it's impossible -+ * to call device_offline() because that ends up calling -+ * cpu_down() which takes cpu maps lock. cpu maps lock -+ * needs to be held as this might race against in kernel -+ * abusers of the hotplug machinery (thermal management). -+ * -+ * So nothing would update device:offline state. That would -+ * leave the sysfs entry stale and prevent onlining after -+ * smt control has been changed to 'off' again. This is -+ * called under the sysfs hotplug lock, so it is properly -+ * serialized against the regular offline usage. -+ */ -+ cpuhp_offline_cpu_device(cpu); -+ } -+ if (!ret) -+ cpu_smt_control = ctrlval; -+ cpu_maps_update_done(); -+ return ret; -+} -+ -+static void cpuhp_smt_enable(void) -+{ -+ cpu_maps_update_begin(); -+ cpu_smt_control = CPU_SMT_ENABLED; -+ cpu_maps_update_done(); -+} -+ -+static ssize_t -+store_smt_control(struct device *dev, struct device_attribute *attr, -+ const char *buf, size_t count) -+{ -+ int ctrlval, ret; -+ -+ if (sysfs_streq(buf, "on")) -+ ctrlval = CPU_SMT_ENABLED; -+ else if (sysfs_streq(buf, "off")) -+ ctrlval = CPU_SMT_DISABLED; -+ else if (sysfs_streq(buf, "forceoff")) -+ ctrlval = CPU_SMT_FORCE_DISABLED; -+ else -+ return -EINVAL; -+ -+ if (cpu_smt_control == CPU_SMT_FORCE_DISABLED) -+ return -EPERM; -+ -+ if (cpu_smt_control == CPU_SMT_NOT_SUPPORTED) -+ return -ENODEV; -+ -+ ret = lock_device_hotplug_sysfs(); -+ if (ret) -+ return ret; -+ -+ if (ctrlval != cpu_smt_control) { -+ switch (ctrlval) { -+ case CPU_SMT_ENABLED: -+ cpuhp_smt_enable(); -+ break; -+ case CPU_SMT_DISABLED: -+ case CPU_SMT_FORCE_DISABLED: -+ ret = cpuhp_smt_disable(ctrlval); -+ break; -+ } -+ } -+ -+ unlock_device_hotplug(); -+ return ret ? ret : count; -+} -+static DEVICE_ATTR(control, 0644, show_smt_control, store_smt_control); -+ -+static ssize_t -+show_smt_active(struct device *dev, struct device_attribute *attr, char *buf) -+{ -+ bool active = topology_max_smt_threads() > 1; -+ -+ return snprintf(buf, PAGE_SIZE - 2, "%d\n", active); -+} -+static DEVICE_ATTR(active, 0444, show_smt_active, NULL); -+ -+static struct attribute *cpuhp_smt_attrs[] = { -+ &dev_attr_control.attr, -+ &dev_attr_active.attr, -+ NULL -+}; -+ -+static const struct attribute_group cpuhp_smt_attr_group = { -+ .attrs = cpuhp_smt_attrs, -+ .name = "smt", -+ NULL -+}; -+ -+static int __init cpu_smt_state_init(void) -+{ -+ if (!topology_smt_supported()) -+ cpu_smt_control = CPU_SMT_NOT_SUPPORTED; -+ -+ return sysfs_create_group(&cpu_subsys.dev_root->kobj, -+ &cpuhp_smt_attr_group); -+} -+ -+#else -+static inline int cpu_smt_state_init(void) { return 0; } -+#endif -+ - static int __init cpuhp_sysfs_init(void) - { - int cpu, ret; - -+ ret = cpu_smt_state_init(); -+ if (ret) -+ return ret; -+ - ret = sysfs_create_group(&cpu_subsys.dev_root->kobj, - &cpuhp_cpu_root_attr_group); - if (ret) -From foo@baz Tue Aug 14 13:43:10 CEST 2018 -From: Thomas Gleixner -Date: Wed, 6 Jun 2018 00:36:15 +0200 -Subject: x86/cpu: Remove the pointless CPU printout - -From: Thomas Gleixner - -commit 55e6d279abd92cfd7576bba031e7589be8475edb upstream - -The value of this printout is dubious at best and there is no point in -having it in two different places along with convoluted ways to reach it. - -Remove it completely. - -Signed-off-by: Thomas Gleixner -Reviewed-by: Konrad Rzeszutek Wilk -Acked-by: Ingo Molnar -Signed-off-by: Greg Kroah-Hartman ---- - arch/x86/kernel/cpu/common.c | 20 +++++--------------- - arch/x86/kernel/cpu/topology.c | 11 ----------- - 2 files changed, 5 insertions(+), 26 deletions(-) - ---- a/arch/x86/kernel/cpu/common.c -+++ b/arch/x86/kernel/cpu/common.c -@@ -643,13 +643,12 @@ void detect_ht(struct cpuinfo_x86 *c) - #ifdef CONFIG_SMP - u32 eax, ebx, ecx, edx; - int index_msb, core_bits; -- static bool printed; - - if (!cpu_has(c, X86_FEATURE_HT)) - return; - - if (cpu_has(c, X86_FEATURE_CMP_LEGACY)) -- goto out; -+ return; - - if (cpu_has(c, X86_FEATURE_XTOPOLOGY)) - return; -@@ -658,14 +657,14 @@ void detect_ht(struct cpuinfo_x86 *c) - - smp_num_siblings = (ebx & 0xff0000) >> 16; - -+ if (!smp_num_siblings) -+ smp_num_siblings = 1; -+ - if (smp_num_siblings == 1) { - pr_info_once("CPU0: Hyper-Threading is disabled\n"); -- goto out; -+ return; - } - -- if (smp_num_siblings <= 1) -- goto out; -- - index_msb = get_count_order(smp_num_siblings); - c->phys_proc_id = apic->phys_pkg_id(c->initial_apicid, index_msb); - -@@ -677,15 +676,6 @@ void detect_ht(struct cpuinfo_x86 *c) - - c->cpu_core_id = apic->phys_pkg_id(c->initial_apicid, index_msb) & - ((1 << core_bits) - 1); -- --out: -- if (!printed && (c->x86_max_cores * smp_num_siblings) > 1) { -- pr_info("CPU: Physical Processor ID: %d\n", -- c->phys_proc_id); -- pr_info("CPU: Processor Core ID: %d\n", -- c->cpu_core_id); -- printed = 1; -- } - #endif - } - ---- a/arch/x86/kernel/cpu/topology.c -+++ b/arch/x86/kernel/cpu/topology.c -@@ -33,7 +33,6 @@ void detect_extended_topology(struct cpu - unsigned int eax, ebx, ecx, edx, sub_index; - unsigned int ht_mask_width, core_plus_mask_width; - unsigned int core_select_mask, core_level_siblings; -- static bool printed; - - if (c->cpuid_level < 0xb) - return; -@@ -86,15 +85,5 @@ void detect_extended_topology(struct cpu - c->apicid = apic->phys_pkg_id(c->initial_apicid, 0); - - c->x86_max_cores = (core_level_siblings / smp_num_siblings); -- -- if (!printed) { -- pr_info("CPU: Physical Processor ID: %d\n", -- c->phys_proc_id); -- if (c->x86_max_cores > 1) -- pr_info("CPU: Processor Core ID: %d\n", -- c->cpu_core_id); -- printed = 1; -- } -- return; - #endif - } -From foo@baz Tue Aug 14 13:43:10 CEST 2018 -From: Thomas Gleixner -Date: Wed, 6 Jun 2018 00:47:10 +0200 -Subject: x86/cpu/AMD: Remove the pointless detect_ht() call - -From: Thomas Gleixner - -commit 44ca36de56d1bf196dca2eb67cd753a46961ffe6 upstream - -Real 32bit AMD CPUs do not have SMT and the only value of the call was to -reach the magic printout which got removed. - -Signed-off-by: Thomas Gleixner -Reviewed-by: Konrad Rzeszutek Wilk -Acked-by: Ingo Molnar -Signed-off-by: Greg Kroah-Hartman ---- - arch/x86/kernel/cpu/amd.c | 4 ---- - 1 file changed, 4 deletions(-) - ---- a/arch/x86/kernel/cpu/amd.c -+++ b/arch/x86/kernel/cpu/amd.c -@@ -867,10 +867,6 @@ static void init_amd(struct cpuinfo_x86 - srat_detect_node(c); - } - --#ifdef CONFIG_X86_32 -- detect_ht(c); --#endif -- - init_amd_cacheinfo(c); - - if (c->x86 >= 0xf) -From foo@baz Tue Aug 14 13:43:10 CEST 2018 -From: Thomas Gleixner -Date: Wed, 6 Jun 2018 00:53:57 +0200 -Subject: x86/cpu/common: Provide detect_ht_early() - -From: Thomas Gleixner - -commit 545401f4448a807b963ff17b575e0a393e68b523 upstream - -To support force disabling of SMT it's required to know the number of -thread siblings early. detect_ht() cannot be called before the APIC driver -is selected, so split out the part which initializes smp_num_siblings. - -Signed-off-by: Thomas Gleixner -Reviewed-by: Konrad Rzeszutek Wilk -Acked-by: Ingo Molnar -Signed-off-by: Greg Kroah-Hartman ---- - arch/x86/kernel/cpu/common.c | 24 ++++++++++++++---------- - arch/x86/kernel/cpu/cpu.h | 1 + - 2 files changed, 15 insertions(+), 10 deletions(-) - ---- a/arch/x86/kernel/cpu/common.c -+++ b/arch/x86/kernel/cpu/common.c -@@ -638,32 +638,36 @@ static void cpu_detect_tlb(struct cpuinf - tlb_lld_4m[ENTRIES], tlb_lld_1g[ENTRIES]); - } - --void detect_ht(struct cpuinfo_x86 *c) -+int detect_ht_early(struct cpuinfo_x86 *c) - { - #ifdef CONFIG_SMP - u32 eax, ebx, ecx, edx; -- int index_msb, core_bits; - - if (!cpu_has(c, X86_FEATURE_HT)) -- return; -+ return -1; - - if (cpu_has(c, X86_FEATURE_CMP_LEGACY)) -- return; -+ return -1; - - if (cpu_has(c, X86_FEATURE_XTOPOLOGY)) -- return; -+ return -1; - - cpuid(1, &eax, &ebx, &ecx, &edx); - - smp_num_siblings = (ebx & 0xff0000) >> 16; -+ if (smp_num_siblings == 1) -+ pr_info_once("CPU0: Hyper-Threading is disabled\n"); -+#endif -+ return 0; -+} - -- if (!smp_num_siblings) -- smp_num_siblings = 1; -+void detect_ht(struct cpuinfo_x86 *c) -+{ -+#ifdef CONFIG_SMP -+ int index_msb, core_bits; - -- if (smp_num_siblings == 1) { -- pr_info_once("CPU0: Hyper-Threading is disabled\n"); -+ if (detect_ht_early(c) < 0) - return; -- } - - index_msb = get_count_order(smp_num_siblings); - c->phys_proc_id = apic->phys_pkg_id(c->initial_apicid, index_msb); ---- a/arch/x86/kernel/cpu/cpu.h -+++ b/arch/x86/kernel/cpu/cpu.h -@@ -47,6 +47,7 @@ extern const struct cpu_dev *const __x86 - - extern void get_cpu_cap(struct cpuinfo_x86 *c); - extern void cpu_detect_cache_sizes(struct cpuinfo_x86 *c); -+extern int detect_ht_early(struct cpuinfo_x86 *c); - - unsigned int aperfmperf_get_khz(int cpu); - -From foo@baz Tue Aug 14 13:43:10 CEST 2018 -From: Thomas Gleixner -Date: Wed, 6 Jun 2018 00:55:39 +0200 -Subject: x86/cpu/topology: Provide detect_extended_topology_early() - -From: Thomas Gleixner - -commit 95f3d39ccf7aaea79d1ffdac1c887c2e100ec1b6 upstream - -To support force disabling of SMT it's required to know the number of -thread siblings early. detect_extended_topology() cannot be called before -the APIC driver is selected, so split out the part which initializes -smp_num_siblings. - -Signed-off-by: Thomas Gleixner -Reviewed-by: Konrad Rzeszutek Wilk -Acked-by: Ingo Molnar -Signed-off-by: Greg Kroah-Hartman ---- - arch/x86/kernel/cpu/cpu.h | 1 + - arch/x86/kernel/cpu/topology.c | 30 ++++++++++++++++++++++++------ - 2 files changed, 25 insertions(+), 6 deletions(-) - ---- a/arch/x86/kernel/cpu/cpu.h -+++ b/arch/x86/kernel/cpu/cpu.h -@@ -47,6 +47,7 @@ extern const struct cpu_dev *const __x86 - - extern void get_cpu_cap(struct cpuinfo_x86 *c); - extern void cpu_detect_cache_sizes(struct cpuinfo_x86 *c); -+extern int detect_extended_topology_early(struct cpuinfo_x86 *c); - extern int detect_ht_early(struct cpuinfo_x86 *c); - - unsigned int aperfmperf_get_khz(int cpu); ---- a/arch/x86/kernel/cpu/topology.c -+++ b/arch/x86/kernel/cpu/topology.c -@@ -27,15 +27,13 @@ - * exists, use it for populating initial_apicid and cpu topology - * detection. - */ --void detect_extended_topology(struct cpuinfo_x86 *c) -+int detect_extended_topology_early(struct cpuinfo_x86 *c) - { - #ifdef CONFIG_SMP -- unsigned int eax, ebx, ecx, edx, sub_index; -- unsigned int ht_mask_width, core_plus_mask_width; -- unsigned int core_select_mask, core_level_siblings; -+ unsigned int eax, ebx, ecx, edx; - - if (c->cpuid_level < 0xb) -- return; -+ return -1; - - cpuid_count(0xb, SMT_LEVEL, &eax, &ebx, &ecx, &edx); - -@@ -43,7 +41,7 @@ void detect_extended_topology(struct cpu - * check if the cpuid leaf 0xb is actually implemented. - */ - if (ebx == 0 || (LEAFB_SUBTYPE(ecx) != SMT_TYPE)) -- return; -+ return -1; - - set_cpu_cap(c, X86_FEATURE_XTOPOLOGY); - -@@ -51,10 +49,30 @@ void detect_extended_topology(struct cpu - * initial apic id, which also represents 32-bit extended x2apic id. - */ - c->initial_apicid = edx; -+ smp_num_siblings = LEVEL_MAX_SIBLINGS(ebx); -+#endif -+ return 0; -+} -+ -+/* -+ * Check for extended topology enumeration cpuid leaf 0xb and if it -+ * exists, use it for populating initial_apicid and cpu topology -+ * detection. -+ */ -+void detect_extended_topology(struct cpuinfo_x86 *c) -+{ -+#ifdef CONFIG_SMP -+ unsigned int eax, ebx, ecx, edx, sub_index; -+ unsigned int ht_mask_width, core_plus_mask_width; -+ unsigned int core_select_mask, core_level_siblings; -+ -+ if (detect_extended_topology_early(c) < 0) -+ return; - - /* - * Populate HT related information from sub-leaf level 0. - */ -+ cpuid_count(0xb, SMT_LEVEL, &eax, &ebx, &ecx, &edx); - core_level_siblings = smp_num_siblings = LEVEL_MAX_SIBLINGS(ebx); - core_plus_mask_width = ht_mask_width = BITS_SHIFT_NEXT_LEVEL(eax); - -From foo@baz Tue Aug 14 13:43:10 CEST 2018 -From: Thomas Gleixner -Date: Wed, 6 Jun 2018 01:00:55 +0200 -Subject: x86/cpu/intel: Evaluate smp_num_siblings early - -From: Thomas Gleixner - -commit 1910ad5624968f93be48e8e265513c54d66b897c upstream - -Make use of the new early detection function to initialize smp_num_siblings -on the boot cpu before the MP-Table or ACPI/MADT scan happens. That's -required for force disabling SMT. - -Signed-off-by: Thomas Gleixner -Reviewed-by: Konrad Rzeszutek Wilk -Acked-by: Ingo Molnar -Signed-off-by: Greg Kroah-Hartman ---- - arch/x86/kernel/cpu/intel.c | 7 +++++++ - 1 file changed, 7 insertions(+) - ---- a/arch/x86/kernel/cpu/intel.c -+++ b/arch/x86/kernel/cpu/intel.c -@@ -301,6 +301,13 @@ static void early_init_intel(struct cpui - } - - check_mpx_erratum(c); -+ -+ /* -+ * Get the number of SMT siblings early from the extended topology -+ * leaf, if available. Otherwise try the legacy SMT detection. -+ */ -+ if (detect_extended_topology_early(c) < 0) -+ detect_ht_early(c); - } - - #ifdef CONFIG_X86_32 -From foo@baz Tue Aug 14 13:43:10 CEST 2018 -From: Borislav Petkov -Date: Fri, 15 Jun 2018 20:48:39 +0200 -Subject: x86/CPU/AMD: Do not check CPUID max ext level before parsing SMP info - -From: Borislav Petkov - -commit 119bff8a9c9bb00116a844ec68be7bc4b1c768f5 upstream - -Old code used to check whether CPUID ext max level is >= 0x80000008 because -that last leaf contains the number of cores of the physical CPU. The three -functions called there now do not depend on that leaf anymore so the check -can go. - -Signed-off-by: Borislav Petkov -Signed-off-by: Thomas Gleixner -Acked-by: Ingo Molnar -Signed-off-by: Greg Kroah-Hartman ---- - arch/x86/kernel/cpu/amd.c | 7 ++----- - 1 file changed, 2 insertions(+), 5 deletions(-) - ---- a/arch/x86/kernel/cpu/amd.c -+++ b/arch/x86/kernel/cpu/amd.c -@@ -861,11 +861,8 @@ static void init_amd(struct cpuinfo_x86 - - cpu_detect_cache_sizes(c); - -- /* Multi core CPU? */ -- if (c->extended_cpuid_level >= 0x80000008) { -- amd_detect_cmp(c); -- srat_detect_node(c); -- } -+ amd_detect_cmp(c); -+ srat_detect_node(c); - - init_amd_cacheinfo(c); - -From foo@baz Tue Aug 14 13:43:10 CEST 2018 -From: Thomas Gleixner -Date: Wed, 6 Jun 2018 00:57:38 +0200 -Subject: x86/cpu/AMD: Evaluate smp_num_siblings early - -From: Thomas Gleixner - -commit 1e1d7e25fd759eddf96d8ab39d0a90a1979b2d8c upstream - -To support force disabling of SMT it's required to know the number of -thread siblings early. amd_get_topology() cannot be called before the APIC -driver is selected, so split out the part which initializes -smp_num_siblings and invoke it from amd_early_init(). - -Signed-off-by: Thomas Gleixner -Acked-by: Ingo Molnar -Signed-off-by: Greg Kroah-Hartman ---- - arch/x86/kernel/cpu/amd.c | 13 +++++++++++++ - 1 file changed, 13 insertions(+) - ---- a/arch/x86/kernel/cpu/amd.c -+++ b/arch/x86/kernel/cpu/amd.c -@@ -315,6 +315,17 @@ static void legacy_fixup_core_id(struct - c->cpu_core_id %= cus_per_node; - } - -+ -+static void amd_get_topology_early(struct cpuinfo_x86 *c) -+{ -+ if (boot_cpu_has(X86_FEATURE_TOPOEXT)) { -+ u32 eax, ebx, ecx, edx; -+ -+ cpuid(0x8000001e, &eax, &ebx, &ecx, &edx); -+ smp_num_siblings = ((ebx >> 8) & 0xff) + 1; -+ } -+} -+ - /* - * Fixup core topology information for - * (1) AMD multi-node processors -@@ -694,6 +705,8 @@ static void early_init_amd(struct cpuinf - set_cpu_bug(c, X86_BUG_AMD_E400); - - early_detect_mem_encrypt(c); -+ -+ amd_get_topology_early(c); - } - - static void init_amd_k8(struct cpuinfo_x86 *c) -From foo@baz Tue Aug 14 13:43:10 CEST 2018 -From: Thomas Gleixner -Date: Tue, 5 Jun 2018 14:00:11 +0200 -Subject: x86/apic: Ignore secondary threads if nosmt=force - -From: Thomas Gleixner - -commit 2207def700f902f169fc237b717252c326f9e464 upstream - -nosmt on the kernel command line merely prevents the onlining of the -secondary SMT siblings. - -nosmt=force makes the APIC detection code ignore the secondary SMT siblings -completely, so they even do not show up as possible CPUs. That reduces the -amount of memory allocations for per cpu variables and saves other -resources from being allocated too large. - -This is not fully equivalent to disabling SMT in the BIOS because the low -level SMT enabling in the BIOS can result in partitioning of resources -between the siblings, which is not undone by just ignoring them. Some CPUs -can use the full resources when their sibling is not onlined, but this is -depending on the CPU family and model and it's not well documented whether -this applies to all partitioned resources. That means depending on the -workload disabling SMT in the BIOS might result in better performance. - -Linus analysis of the Intel manual: - - The intel optimization manual is not very clear on what the partitioning - rules are. - - I find: - - "In general, the buffers for staging instructions between major pipe - stages are partitioned. These buffers include µop queues after the - execution trace cache, the queues after the register rename stage, the - reorder buffer which stages instructions for retirement, and the load - and store buffers. - - In the case of load and store buffers, partitioning also provided an - easier implementation to maintain memory ordering for each logical - processor and detect memory ordering violations" - - but some of that partitioning may be relaxed if the HT thread is "not - active": - - "In Intel microarchitecture code name Sandy Bridge, the micro-op queue - is statically partitioned to provide 28 entries for each logical - processor, irrespective of software executing in single thread or - multiple threads. If one logical processor is not active in Intel - microarchitecture code name Ivy Bridge, then a single thread executing - on that processor core can use the 56 entries in the micro-op queue" - - but I do not know what "not active" means, and how dynamic it is. Some of - that partitioning may be entirely static and depend on the early BIOS - disabling of HT, and even if we park the cores, the resources will just be - wasted. - -Signed-off-by: Thomas Gleixner -Reviewed-by: Konrad Rzeszutek Wilk -Acked-by: Ingo Molnar -Signed-off-by: Greg Kroah-Hartman ---- - arch/x86/include/asm/apic.h | 2 ++ - arch/x86/kernel/acpi/boot.c | 3 ++- - arch/x86/kernel/apic/apic.c | 19 +++++++++++++++++++ - 3 files changed, 23 insertions(+), 1 deletion(-) - ---- a/arch/x86/include/asm/apic.h -+++ b/arch/x86/include/asm/apic.h -@@ -504,8 +504,10 @@ extern int default_check_phys_apicid_pre - - #ifdef CONFIG_SMP - bool apic_id_is_primary_thread(unsigned int id); -+bool apic_id_disabled(unsigned int id); - #else - static inline bool apic_id_is_primary_thread(unsigned int id) { return false; } -+static inline bool apic_id_disabled(unsigned int id) { return false; } - #endif - - extern void irq_enter(void); ---- a/arch/x86/kernel/acpi/boot.c -+++ b/arch/x86/kernel/acpi/boot.c -@@ -181,7 +181,8 @@ static int acpi_register_lapic(int id, u - } - - if (!enabled) { -- ++disabled_cpus; -+ if (!apic_id_disabled(id)) -+ ++disabled_cpus; - return -EINVAL; - } - ---- a/arch/x86/kernel/apic/apic.c -+++ b/arch/x86/kernel/apic/apic.c -@@ -2207,6 +2207,16 @@ bool apic_id_is_primary_thread(unsigned - return !(apicid & mask); - } - -+/** -+ * apic_id_disabled - Check whether APIC ID is disabled via SMT control -+ * @id: APIC ID to check -+ */ -+bool apic_id_disabled(unsigned int id) -+{ -+ return (cpu_smt_control == CPU_SMT_FORCE_DISABLED && -+ !apic_id_is_primary_thread(id)); -+} -+ - /* - * Should use this API to allocate logical CPU IDs to keep nr_logical_cpuids - * and cpuid_to_apicid[] synchronized. -@@ -2302,6 +2312,15 @@ int generic_processor_info(int apicid, i - return -EINVAL; - } - -+ /* -+ * If SMT is force disabled and the APIC ID belongs to -+ * a secondary thread, ignore it. -+ */ -+ if (apic_id_disabled(apicid)) { -+ pr_info_once("Ignoring secondary SMT threads\n"); -+ return -EINVAL; -+ } -+ - if (apicid == boot_cpu_physical_apicid) { - /* - * x86_bios_cpu_apicid is required to have processors listed -From foo@baz Tue Aug 14 13:43:10 CEST 2018 -From: Vlastimil Babka -Date: Thu, 21 Jun 2018 12:36:29 +0200 -Subject: x86/speculation/l1tf: Extend 64bit swap file size limit - -From: Vlastimil Babka - -commit 1a7ed1ba4bba6c075d5ad61bb75e3fbc870840d6 upstream - -The previous patch has limited swap file size so that large offsets cannot -clear bits above MAX_PA/2 in the pte and interfere with L1TF mitigation. - -It assumed that offsets are encoded starting with bit 12, same as pfn. But -on x86_64, offsets are encoded starting with bit 9. - -Thus the limit can be raised by 3 bits. That means 16TB with 42bit MAX_PA -and 256TB with 46bit MAX_PA. - -Fixes: 377eeaa8e11f ("x86/speculation/l1tf: Limit swap file size to MAX_PA/2") -Signed-off-by: Vlastimil Babka -Signed-off-by: Thomas Gleixner -Signed-off-by: Greg Kroah-Hartman ---- - arch/x86/mm/init.c | 10 +++++++++- - 1 file changed, 9 insertions(+), 1 deletion(-) - ---- a/arch/x86/mm/init.c -+++ b/arch/x86/mm/init.c -@@ -891,7 +891,15 @@ unsigned long max_swapfile_size(void) - - if (boot_cpu_has_bug(X86_BUG_L1TF)) { - /* Limit the swap file size to MAX_PA/2 for L1TF workaround */ -- pages = min_t(unsigned long, l1tf_pfn_limit() + 1, pages); -+ unsigned long l1tf_limit = l1tf_pfn_limit() + 1; -+ /* -+ * We encode swap offsets also with 3 bits below those for pfn -+ * which makes the usable limit higher. -+ */ -+#ifdef CONFIG_X86_64 -+ l1tf_limit <<= PAGE_SHIFT - SWP_OFFSET_FIRST_BIT; -+#endif -+ pages = min_t(unsigned long, l1tf_limit, pages); - } - return pages; - } -From foo@baz Tue Aug 14 13:43:10 CEST 2018 -From: Konrad Rzeszutek Wilk -Date: Wed, 20 Jun 2018 16:42:58 -0400 -Subject: x86/cpufeatures: Add detection of L1D cache flush support. - -From: Konrad Rzeszutek Wilk - -commit 11e34e64e4103955fc4568750914c75d65ea87ee upstream - -336996-Speculative-Execution-Side-Channel-Mitigations.pdf defines a new MSR -(IA32_FLUSH_CMD) which is detected by CPUID.7.EDX[28]=1 bit being set. - -This new MSR "gives software a way to invalidate structures with finer -granularity than other architectual methods like WBINVD." - -A copy of this document is available at - https://bugzilla.kernel.org/show_bug.cgi?id=199511 - -Signed-off-by: Konrad Rzeszutek Wilk -Signed-off-by: Thomas Gleixner -Signed-off-by: Greg Kroah-Hartman ---- - arch/x86/include/asm/cpufeatures.h | 1 + - 1 file changed, 1 insertion(+) - ---- a/arch/x86/include/asm/cpufeatures.h -+++ b/arch/x86/include/asm/cpufeatures.h -@@ -340,6 +340,7 @@ - #define X86_FEATURE_PCONFIG (18*32+18) /* Intel PCONFIG */ - #define X86_FEATURE_SPEC_CTRL (18*32+26) /* "" Speculation Control (IBRS + IBPB) */ - #define X86_FEATURE_INTEL_STIBP (18*32+27) /* "" Single Thread Indirect Branch Predictors */ -+#define X86_FEATURE_FLUSH_L1D (18*32+28) /* Flush L1D cache */ - #define X86_FEATURE_ARCH_CAPABILITIES (18*32+29) /* IA32_ARCH_CAPABILITIES MSR (Intel) */ - #define X86_FEATURE_SPEC_CTRL_SSBD (18*32+31) /* "" Speculative Store Bypass Disable */ - -From foo@baz Tue Aug 14 13:43:10 CEST 2018 -From: Borislav Petkov -Date: Fri, 22 Jun 2018 11:34:11 +0200 -Subject: x86/CPU/AMD: Move TOPOEXT reenablement before reading smp_num_siblings - -From: Borislav Petkov - -commit 7ce2f0393ea2396142b7faf6ee9b1f3676d08a5f upstream - -The TOPOEXT reenablement is a workaround for broken BIOSen which didn't -enable the CPUID bit. amd_get_topology_early(), however, relies on -that bit being set so that it can read out the CPUID leaf and set -smp_num_siblings properly. - -Move the reenablement up to early_init_amd(). While at it, simplify -amd_get_topology_early(). - -Signed-off-by: Borislav Petkov -Signed-off-by: Thomas Gleixner -Signed-off-by: Greg Kroah-Hartman ---- - arch/x86/kernel/cpu/amd.c | 37 +++++++++++++++++-------------------- - 1 file changed, 17 insertions(+), 20 deletions(-) - ---- a/arch/x86/kernel/cpu/amd.c -+++ b/arch/x86/kernel/cpu/amd.c -@@ -318,12 +318,8 @@ static void legacy_fixup_core_id(struct - - static void amd_get_topology_early(struct cpuinfo_x86 *c) - { -- if (boot_cpu_has(X86_FEATURE_TOPOEXT)) { -- u32 eax, ebx, ecx, edx; -- -- cpuid(0x8000001e, &eax, &ebx, &ecx, &edx); -- smp_num_siblings = ((ebx >> 8) & 0xff) + 1; -- } -+ if (cpu_has(c, X86_FEATURE_TOPOEXT)) -+ smp_num_siblings = ((cpuid_ebx(0x8000001e) >> 8) & 0xff) + 1; - } - - /* -@@ -344,7 +340,6 @@ static void amd_get_topology(struct cpui - cpuid(0x8000001e, &eax, &ebx, &ecx, &edx); - - node_id = ecx & 0xff; -- smp_num_siblings = ((ebx >> 8) & 0xff) + 1; - - if (c->x86 == 0x15) - c->cu_id = ebx & 0xff; -@@ -635,6 +630,7 @@ clear_sev: - - static void early_init_amd(struct cpuinfo_x86 *c) - { -+ u64 value; - u32 dummy; - - early_init_amd_mc(c); -@@ -706,6 +702,20 @@ static void early_init_amd(struct cpuinf - - early_detect_mem_encrypt(c); - -+ /* Re-enable TopologyExtensions if switched off by BIOS */ -+ if (c->x86 == 0x15 && -+ (c->x86_model >= 0x10 && c->x86_model <= 0x6f) && -+ !cpu_has(c, X86_FEATURE_TOPOEXT)) { -+ -+ if (msr_set_bit(0xc0011005, 54) > 0) { -+ rdmsrl(0xc0011005, value); -+ if (value & BIT_64(54)) { -+ set_cpu_cap(c, X86_FEATURE_TOPOEXT); -+ pr_info_once(FW_INFO "CPU: Re-enabling disabled Topology Extensions Support.\n"); -+ } -+ } -+ } -+ - amd_get_topology_early(c); - } - -@@ -798,19 +808,6 @@ static void init_amd_bd(struct cpuinfo_x - { - u64 value; - -- /* re-enable TopologyExtensions if switched off by BIOS */ -- if ((c->x86_model >= 0x10) && (c->x86_model <= 0x6f) && -- !cpu_has(c, X86_FEATURE_TOPOEXT)) { -- -- if (msr_set_bit(0xc0011005, 54) > 0) { -- rdmsrl(0xc0011005, value); -- if (value & BIT_64(54)) { -- set_cpu_cap(c, X86_FEATURE_TOPOEXT); -- pr_info_once(FW_INFO "CPU: Re-enabling disabled Topology Extensions Support.\n"); -- } -- } -- } -- - /* - * The way access filter has a performance penalty on some workloads. - * Disable it on the affected CPUs. -From foo@baz Tue Aug 14 13:43:10 CEST 2018 -From: Vlastimil Babka -Date: Fri, 22 Jun 2018 17:39:33 +0200 -Subject: x86/speculation/l1tf: Protect PAE swap entries against L1TF - -From: Vlastimil Babka - -commit 0d0f6249058834ffe1ceaad0bb31464af66f6e7a upstream - -The PAE 3-level paging code currently doesn't mitigate L1TF by flipping the -offset bits, and uses the high PTE word, thus bits 32-36 for type, 37-63 for -offset. The lower word is zeroed, thus systems with less than 4GB memory are -safe. With 4GB to 128GB the swap type selects the memory locations vulnerable -to L1TF; with even more memory, also the swap offfset influences the address. -This might be a problem with 32bit PAE guests running on large 64bit hosts. - -By continuing to keep the whole swap entry in either high or low 32bit word of -PTE we would limit the swap size too much. Thus this patch uses the whole PAE -PTE with the same layout as the 64bit version does. The macros just become a -bit tricky since they assume the arch-dependent swp_entry_t to be 32bit. - -Signed-off-by: Vlastimil Babka -Signed-off-by: Thomas Gleixner -Acked-by: Michal Hocko -Signed-off-by: Greg Kroah-Hartman ---- - arch/x86/include/asm/pgtable-3level.h | 35 ++++++++++++++++++++++++++++++++-- - arch/x86/mm/init.c | 2 - - 2 files changed, 34 insertions(+), 3 deletions(-) - ---- a/arch/x86/include/asm/pgtable-3level.h -+++ b/arch/x86/include/asm/pgtable-3level.h -@@ -241,12 +241,43 @@ static inline pud_t native_pudp_get_and_ - #endif - - /* Encode and de-code a swap entry */ -+#define SWP_TYPE_BITS 5 -+ -+#define SWP_OFFSET_FIRST_BIT (_PAGE_BIT_PROTNONE + 1) -+ -+/* We always extract/encode the offset by shifting it all the way up, and then down again */ -+#define SWP_OFFSET_SHIFT (SWP_OFFSET_FIRST_BIT + SWP_TYPE_BITS) -+ - #define MAX_SWAPFILES_CHECK() BUILD_BUG_ON(MAX_SWAPFILES_SHIFT > 5) - #define __swp_type(x) (((x).val) & 0x1f) - #define __swp_offset(x) ((x).val >> 5) - #define __swp_entry(type, offset) ((swp_entry_t){(type) | (offset) << 5}) --#define __pte_to_swp_entry(pte) ((swp_entry_t){ (pte).pte_high }) --#define __swp_entry_to_pte(x) ((pte_t){ { .pte_high = (x).val } }) -+ -+/* -+ * Normally, __swp_entry() converts from arch-independent swp_entry_t to -+ * arch-dependent swp_entry_t, and __swp_entry_to_pte() just stores the result -+ * to pte. But here we have 32bit swp_entry_t and 64bit pte, and need to use the -+ * whole 64 bits. Thus, we shift the "real" arch-dependent conversion to -+ * __swp_entry_to_pte() through the following helper macro based on 64bit -+ * __swp_entry(). -+ */ -+#define __swp_pteval_entry(type, offset) ((pteval_t) { \ -+ (~(pteval_t)(offset) << SWP_OFFSET_SHIFT >> SWP_TYPE_BITS) \ -+ | ((pteval_t)(type) << (64 - SWP_TYPE_BITS)) }) -+ -+#define __swp_entry_to_pte(x) ((pte_t){ .pte = \ -+ __swp_pteval_entry(__swp_type(x), __swp_offset(x)) }) -+/* -+ * Analogically, __pte_to_swp_entry() doesn't just extract the arch-dependent -+ * swp_entry_t, but also has to convert it from 64bit to the 32bit -+ * intermediate representation, using the following macros based on 64bit -+ * __swp_type() and __swp_offset(). -+ */ -+#define __pteval_swp_type(x) ((unsigned long)((x).pte >> (64 - SWP_TYPE_BITS))) -+#define __pteval_swp_offset(x) ((unsigned long)(~((x).pte) << SWP_TYPE_BITS >> SWP_OFFSET_SHIFT)) -+ -+#define __pte_to_swp_entry(pte) (__swp_entry(__pteval_swp_type(pte), \ -+ __pteval_swp_offset(pte))) - - #define gup_get_pte gup_get_pte - /* ---- a/arch/x86/mm/init.c -+++ b/arch/x86/mm/init.c -@@ -896,7 +896,7 @@ unsigned long max_swapfile_size(void) - * We encode swap offsets also with 3 bits below those for pfn - * which makes the usable limit higher. - */ --#ifdef CONFIG_X86_64 -+#if CONFIG_PGTABLE_LEVELS > 2 - l1tf_limit <<= PAGE_SHIFT - SWP_OFFSET_FIRST_BIT; - #endif - pages = min_t(unsigned long, l1tf_limit, pages); -From foo@baz Tue Aug 14 13:43:10 CEST 2018 -From: Michal Hocko -Date: Wed, 27 Jun 2018 17:46:50 +0200 -Subject: x86/speculation/l1tf: Fix up pte->pfn conversion for PAE - -From: Michal Hocko - -commit e14d7dfb41f5807a0c1c26a13f2b8ef16af24935 upstream - -Jan has noticed that pte_pfn and co. resp. pfn_pte are incorrect for -CONFIG_PAE because phys_addr_t is wider than unsigned long and so the -pte_val reps. shift left would get truncated. Fix this up by using proper -types. - -Fixes: 6b28baca9b1f ("x86/speculation/l1tf: Protect PROT_NONE PTEs against speculation") -Reported-by: Jan Beulich -Signed-off-by: Michal Hocko -Signed-off-by: Thomas Gleixner -Acked-by: Vlastimil Babka -Signed-off-by: Greg Kroah-Hartman ---- - arch/x86/include/asm/pgtable.h | 12 ++++++------ - 1 file changed, 6 insertions(+), 6 deletions(-) - ---- a/arch/x86/include/asm/pgtable.h -+++ b/arch/x86/include/asm/pgtable.h -@@ -191,21 +191,21 @@ static inline u64 protnone_mask(u64 val) - - static inline unsigned long pte_pfn(pte_t pte) - { -- unsigned long pfn = pte_val(pte); -+ phys_addr_t pfn = pte_val(pte); - pfn ^= protnone_mask(pfn); - return (pfn & PTE_PFN_MASK) >> PAGE_SHIFT; - } - - static inline unsigned long pmd_pfn(pmd_t pmd) - { -- unsigned long pfn = pmd_val(pmd); -+ phys_addr_t pfn = pmd_val(pmd); - pfn ^= protnone_mask(pfn); - return (pfn & pmd_pfn_mask(pmd)) >> PAGE_SHIFT; - } - - static inline unsigned long pud_pfn(pud_t pud) - { -- unsigned long pfn = pud_val(pud); -+ phys_addr_t pfn = pud_val(pud); - pfn ^= protnone_mask(pfn); - return (pfn & pud_pfn_mask(pud)) >> PAGE_SHIFT; - } -@@ -555,7 +555,7 @@ static inline pgprotval_t check_pgprot(p - - static inline pte_t pfn_pte(unsigned long page_nr, pgprot_t pgprot) - { -- phys_addr_t pfn = page_nr << PAGE_SHIFT; -+ phys_addr_t pfn = (phys_addr_t)page_nr << PAGE_SHIFT; - pfn ^= protnone_mask(pgprot_val(pgprot)); - pfn &= PTE_PFN_MASK; - return __pte(pfn | check_pgprot(pgprot)); -@@ -563,7 +563,7 @@ static inline pte_t pfn_pte(unsigned lon - - static inline pmd_t pfn_pmd(unsigned long page_nr, pgprot_t pgprot) - { -- phys_addr_t pfn = page_nr << PAGE_SHIFT; -+ phys_addr_t pfn = (phys_addr_t)page_nr << PAGE_SHIFT; - pfn ^= protnone_mask(pgprot_val(pgprot)); - pfn &= PHYSICAL_PMD_PAGE_MASK; - return __pmd(pfn | check_pgprot(pgprot)); -@@ -571,7 +571,7 @@ static inline pmd_t pfn_pmd(unsigned lon - - static inline pud_t pfn_pud(unsigned long page_nr, pgprot_t pgprot) - { -- phys_addr_t pfn = page_nr << PAGE_SHIFT; -+ phys_addr_t pfn = (phys_addr_t)page_nr << PAGE_SHIFT; - pfn ^= protnone_mask(pgprot_val(pgprot)); - pfn &= PHYSICAL_PUD_PAGE_MASK; - return __pud(pfn | check_pgprot(pgprot)); -From foo@baz Tue Aug 14 13:43:10 CEST 2018 -From: Thomas Gleixner -Date: Fri, 29 Jun 2018 16:05:47 +0200 -Subject: Revert "x86/apic: Ignore secondary threads if nosmt=force" - -From: Thomas Gleixner - -commit 506a66f374891ff08e064a058c446b336c5ac760 upstream - -Dave Hansen reported, that it's outright dangerous to keep SMT siblings -disabled completely so they are stuck in the BIOS and wait for SIPI. - -The reason is that Machine Check Exceptions are broadcasted to siblings and -the soft disabled sibling has CR4.MCE = 0. If a MCE is delivered to a -logical core with CR4.MCE = 0, it asserts IERR#, which shuts down or -reboots the machine. The MCE chapter in the SDM contains the following -blurb: - - Because the logical processors within a physical package are tightly - coupled with respect to shared hardware resources, both logical - processors are notified of machine check errors that occur within a - given physical processor. If machine-check exceptions are enabled when - a fatal error is reported, all the logical processors within a physical - package are dispatched to the machine-check exception handler. If - machine-check exceptions are disabled, the logical processors enter the - shutdown state and assert the IERR# signal. When enabling machine-check - exceptions, the MCE flag in control register CR4 should be set for each - logical processor. - -Reverting the commit which ignores siblings at enumeration time solves only -half of the problem. The core cpuhotplug logic needs to be adjusted as -well. - -This thoughtful engineered mechanism also turns the boot process on all -Intel HT enabled systems into a MCE lottery. MCE is enabled on the boot CPU -before the secondary CPUs are brought up. Depending on the number of -physical cores the window in which this situation can happen is smaller or -larger. On a HSW-EX it's about 750ms: - -MCE is enabled on the boot CPU: - -[ 0.244017] mce: CPU supports 22 MCE banks - -The corresponding sibling #72 boots: - -[ 1.008005] .... node #0, CPUs: #72 - -That means if an MCE hits on physical core 0 (logical CPUs 0 and 72) -between these two points the machine is going to shutdown. At least it's a -known safe state. - -It's obvious that the early boot can be hit by an MCE as well and then runs -into the same situation because MCEs are not yet enabled on the boot CPU. -But after enabling them on the boot CPU, it does not make any sense to -prevent the kernel from recovering. - -Adjust the nosmt kernel parameter documentation as well. - -Reverts: 2207def700f9 ("x86/apic: Ignore secondary threads if nosmt=force") -Reported-by: Dave Hansen -Signed-off-by: Thomas Gleixner -Tested-by: Tony Luck -Signed-off-by: Greg Kroah-Hartman ---- - Documentation/admin-guide/kernel-parameters.txt | 8 ++------ - arch/x86/include/asm/apic.h | 2 -- - arch/x86/kernel/acpi/boot.c | 3 +-- - arch/x86/kernel/apic/apic.c | 19 ------------------- - 4 files changed, 3 insertions(+), 29 deletions(-) - ---- a/Documentation/admin-guide/kernel-parameters.txt -+++ b/Documentation/admin-guide/kernel-parameters.txt -@@ -2676,12 +2676,8 @@ - Equivalent to smt=1. - - [KNL,x86] Disable symmetric multithreading (SMT). -- nosmt=force: Force disable SMT, similar to disabling -- it in the BIOS except that some of the -- resource partitioning effects which are -- caused by having SMT enabled in the BIOS -- cannot be undone. Depending on the CPU -- type this might have a performance impact. -+ nosmt=force: Force disable SMT, cannot be undone -+ via the sysfs control file. - - nospectre_v2 [X86] Disable all mitigations for the Spectre variant 2 - (indirect branch prediction) vulnerability. System may ---- a/arch/x86/include/asm/apic.h -+++ b/arch/x86/include/asm/apic.h -@@ -504,10 +504,8 @@ extern int default_check_phys_apicid_pre - - #ifdef CONFIG_SMP - bool apic_id_is_primary_thread(unsigned int id); --bool apic_id_disabled(unsigned int id); - #else - static inline bool apic_id_is_primary_thread(unsigned int id) { return false; } --static inline bool apic_id_disabled(unsigned int id) { return false; } - #endif - - extern void irq_enter(void); ---- a/arch/x86/kernel/acpi/boot.c -+++ b/arch/x86/kernel/acpi/boot.c -@@ -181,8 +181,7 @@ static int acpi_register_lapic(int id, u - } - - if (!enabled) { -- if (!apic_id_disabled(id)) -- ++disabled_cpus; -+ ++disabled_cpus; - return -EINVAL; - } - ---- a/arch/x86/kernel/apic/apic.c -+++ b/arch/x86/kernel/apic/apic.c -@@ -2207,16 +2207,6 @@ bool apic_id_is_primary_thread(unsigned - return !(apicid & mask); - } - --/** -- * apic_id_disabled - Check whether APIC ID is disabled via SMT control -- * @id: APIC ID to check -- */ --bool apic_id_disabled(unsigned int id) --{ -- return (cpu_smt_control == CPU_SMT_FORCE_DISABLED && -- !apic_id_is_primary_thread(id)); --} -- - /* - * Should use this API to allocate logical CPU IDs to keep nr_logical_cpuids - * and cpuid_to_apicid[] synchronized. -@@ -2312,15 +2302,6 @@ int generic_processor_info(int apicid, i - return -EINVAL; - } - -- /* -- * If SMT is force disabled and the APIC ID belongs to -- * a secondary thread, ignore it. -- */ -- if (apic_id_disabled(apicid)) { -- pr_info_once("Ignoring secondary SMT threads\n"); -- return -EINVAL; -- } -- - if (apicid == boot_cpu_physical_apicid) { - /* - * x86_bios_cpu_apicid is required to have processors listed -From foo@baz Tue Aug 14 13:43:10 CEST 2018 -From: Thomas Gleixner -Date: Fri, 29 Jun 2018 16:05:48 +0200 -Subject: cpu/hotplug: Boot HT siblings at least once - -From: Thomas Gleixner - -commit 0cc3cd21657be04cb0559fe8063f2130493f92cf upstream - -Due to the way Machine Check Exceptions work on X86 hyperthreads it's -required to boot up _all_ logical cores at least once in order to set the -CR4.MCE bit. - -So instead of ignoring the sibling threads right away, let them boot up -once so they can configure themselves. After they came out of the initial -boot stage check whether its a "secondary" sibling and cancel the operation -which puts the CPU back into offline state. - -Reported-by: Dave Hansen -Signed-off-by: Thomas Gleixner -Tested-by: Tony Luck -Signed-off-by: Greg Kroah-Hartman ---- - kernel/cpu.c | 72 +++++++++++++++++++++++++++++++++++++++-------------------- - 1 file changed, 48 insertions(+), 24 deletions(-) - ---- a/kernel/cpu.c -+++ b/kernel/cpu.c -@@ -60,6 +60,7 @@ struct cpuhp_cpu_state { - bool rollback; - bool single; - bool bringup; -+ bool booted_once; - struct hlist_node *node; - struct hlist_node *last; - enum cpuhp_state cb_state; -@@ -342,6 +343,40 @@ void cpu_hotplug_enable(void) - EXPORT_SYMBOL_GPL(cpu_hotplug_enable); - #endif /* CONFIG_HOTPLUG_CPU */ - -+#ifdef CONFIG_HOTPLUG_SMT -+enum cpuhp_smt_control cpu_smt_control __read_mostly = CPU_SMT_ENABLED; -+ -+static int __init smt_cmdline_disable(char *str) -+{ -+ cpu_smt_control = CPU_SMT_DISABLED; -+ if (str && !strcmp(str, "force")) { -+ pr_info("SMT: Force disabled\n"); -+ cpu_smt_control = CPU_SMT_FORCE_DISABLED; -+ } -+ return 0; -+} -+early_param("nosmt", smt_cmdline_disable); -+ -+static inline bool cpu_smt_allowed(unsigned int cpu) -+{ -+ if (cpu_smt_control == CPU_SMT_ENABLED) -+ return true; -+ -+ if (topology_is_primary_thread(cpu)) -+ return true; -+ -+ /* -+ * On x86 it's required to boot all logical CPUs at least once so -+ * that the init code can get a chance to set CR4.MCE on each -+ * CPU. Otherwise, a broadacasted MCE observing CR4.MCE=0b on any -+ * core will shutdown the machine. -+ */ -+ return !per_cpu(cpuhp_state, cpu).booted_once; -+} -+#else -+static inline bool cpu_smt_allowed(unsigned int cpu) { return true; } -+#endif -+ - static inline enum cpuhp_state - cpuhp_set_state(struct cpuhp_cpu_state *st, enum cpuhp_state target) - { -@@ -422,6 +457,16 @@ static int bringup_wait_for_ap(unsigned - stop_machine_unpark(cpu); - kthread_unpark(st->thread); - -+ /* -+ * SMT soft disabling on X86 requires to bring the CPU out of the -+ * BIOS 'wait for SIPI' state in order to set the CR4.MCE bit. The -+ * CPU marked itself as booted_once in cpu_notify_starting() so the -+ * cpu_smt_allowed() check will now return false if this is not the -+ * primary sibling. -+ */ -+ if (!cpu_smt_allowed(cpu)) -+ return -ECANCELED; -+ - if (st->target <= CPUHP_AP_ONLINE_IDLE) - return 0; - -@@ -933,29 +978,6 @@ EXPORT_SYMBOL(cpu_down); - #define takedown_cpu NULL - #endif /*CONFIG_HOTPLUG_CPU*/ - --#ifdef CONFIG_HOTPLUG_SMT --enum cpuhp_smt_control cpu_smt_control __read_mostly = CPU_SMT_ENABLED; -- --static int __init smt_cmdline_disable(char *str) --{ -- cpu_smt_control = CPU_SMT_DISABLED; -- if (str && !strcmp(str, "force")) { -- pr_info("SMT: Force disabled\n"); -- cpu_smt_control = CPU_SMT_FORCE_DISABLED; -- } -- return 0; --} --early_param("nosmt", smt_cmdline_disable); -- --static inline bool cpu_smt_allowed(unsigned int cpu) --{ -- return cpu_smt_control == CPU_SMT_ENABLED || -- topology_is_primary_thread(cpu); --} --#else --static inline bool cpu_smt_allowed(unsigned int cpu) { return true; } --#endif -- - /** - * notify_cpu_starting(cpu) - Invoke the callbacks on the starting CPU - * @cpu: cpu that just started -@@ -970,6 +992,7 @@ void notify_cpu_starting(unsigned int cp - int ret; - - rcu_cpu_starting(cpu); /* Enables RCU usage on this CPU. */ -+ st->booted_once = true; - while (st->state < target) { - st->state++; - ret = cpuhp_invoke_callback(cpu, st->state, true, NULL, NULL); -@@ -2180,5 +2203,6 @@ void __init boot_cpu_init(void) - */ - void __init boot_cpu_hotplug_init(void) - { -- per_cpu_ptr(&cpuhp_state, smp_processor_id())->state = CPUHP_ONLINE; -+ this_cpu_write(cpuhp_state.booted_once, true); -+ this_cpu_write(cpuhp_state.state, CPUHP_ONLINE); - } -From foo@baz Tue Aug 14 13:43:11 CEST 2018 -From: Konrad Rzeszutek Wilk -Date: Wed, 20 Jun 2018 11:29:53 -0400 -Subject: x86/KVM: Warn user if KVM is loaded SMT and L1TF CPU bug being present - -From: Konrad Rzeszutek Wilk - -commit 26acfb666a473d960f0fd971fe68f3e3ad16c70b upstream - -If the L1TF CPU bug is present we allow the KVM module to be loaded as the -major of users that use Linux and KVM have trusted guests and do not want a -broken setup. - -Cloud vendors are the ones that are uncomfortable with CVE 2018-3620 and as -such they are the ones that should set nosmt to one. - -Setting 'nosmt' means that the system administrator also needs to disable -SMT (Hyper-threading) in the BIOS, or via the 'nosmt' command line -parameter, or via the /sys/devices/system/cpu/smt/control. See commit -05736e4ac13c ("cpu/hotplug: Provide knobs to control SMT"). - -Other mitigations are to use task affinity, cpu sets, interrupt binding, -etc - anything to make sure that _only_ the same guests vCPUs are running -on sibling threads. - -Signed-off-by: Konrad Rzeszutek Wilk -Signed-off-by: Thomas Gleixner -Signed-off-by: Greg Kroah-Hartman ---- - Documentation/admin-guide/kernel-parameters.txt | 6 ++++++ - arch/x86/kvm/vmx.c | 13 +++++++++++++ - kernel/cpu.c | 1 + - 3 files changed, 20 insertions(+) - ---- a/Documentation/admin-guide/kernel-parameters.txt -+++ b/Documentation/admin-guide/kernel-parameters.txt -@@ -1937,6 +1937,12 @@ - [KVM,ARM] Allow use of GICv4 for direct injection of - LPIs. - -+ kvm-intel.nosmt=[KVM,Intel] If the L1TF CPU bug is present (CVE-2018-3620) -+ and the system has SMT (aka Hyper-Threading) enabled then -+ don't allow guests to be created. -+ -+ Default is 0 (allow guests to be created). -+ - kvm-intel.ept= [KVM,Intel] Disable extended page tables - (virtualized MMU) support on capable Intel chips. - Default is 1 (enabled) ---- a/arch/x86/kvm/vmx.c -+++ b/arch/x86/kvm/vmx.c -@@ -71,6 +71,9 @@ static const struct x86_cpu_id vmx_cpu_i - }; - MODULE_DEVICE_TABLE(x86cpu, vmx_cpu_id); - -+static bool __read_mostly nosmt; -+module_param(nosmt, bool, S_IRUGO); -+ - static bool __read_mostly enable_vpid = 1; - module_param_named(vpid, enable_vpid, bool, 0444); - -@@ -10142,10 +10145,20 @@ free_vcpu: - return ERR_PTR(err); - } - -+#define L1TF_MSG "SMT enabled with L1TF CPU bug present. Refer to CVE-2018-3620 for details.\n" -+ - static int vmx_vm_init(struct kvm *kvm) - { - if (!ple_gap) - kvm->arch.pause_in_guest = true; -+ -+ if (boot_cpu_has(X86_BUG_L1TF) && cpu_smt_control == CPU_SMT_ENABLED) { -+ if (nosmt) { -+ pr_err(L1TF_MSG); -+ return -EOPNOTSUPP; -+ } -+ pr_warn(L1TF_MSG); -+ } - return 0; - } - ---- a/kernel/cpu.c -+++ b/kernel/cpu.c -@@ -345,6 +345,7 @@ EXPORT_SYMBOL_GPL(cpu_hotplug_enable); - - #ifdef CONFIG_HOTPLUG_SMT - enum cpuhp_smt_control cpu_smt_control __read_mostly = CPU_SMT_ENABLED; -+EXPORT_SYMBOL_GPL(cpu_smt_control); - - static int __init smt_cmdline_disable(char *str) - { -From foo@baz Tue Aug 14 13:43:11 CEST 2018 -From: Konrad Rzeszutek Wilk -Date: Mon, 2 Jul 2018 12:29:30 +0200 -Subject: x86/KVM/VMX: Add module argument for L1TF mitigation - -From: Konrad Rzeszutek Wilk - -commit a399477e52c17e148746d3ce9a483f681c2aa9a0 upstream - -Add a mitigation mode parameter "vmentry_l1d_flush" for CVE-2018-3620, aka -L1 terminal fault. The valid arguments are: - - - "always" L1D cache flush on every VMENTER. - - "cond" Conditional L1D cache flush, explained below - - "never" Disable the L1D cache flush mitigation - -"cond" is trying to avoid L1D cache flushes on VMENTER if the code executed -between VMEXIT and VMENTER is considered safe, i.e. is not bringing any -interesting information into L1D which might exploited. - -[ tglx: Split out from a larger patch ] - -Signed-off-by: Konrad Rzeszutek Wilk -Signed-off-by: Thomas Gleixner -Signed-off-by: Greg Kroah-Hartman ---- - Documentation/admin-guide/kernel-parameters.txt | 12 ++++ - arch/x86/kvm/vmx.c | 59 ++++++++++++++++++++++++ - 2 files changed, 71 insertions(+) - ---- a/Documentation/admin-guide/kernel-parameters.txt -+++ b/Documentation/admin-guide/kernel-parameters.txt -@@ -1964,6 +1964,18 @@ - (virtualized real and unpaged mode) on capable - Intel chips. Default is 1 (enabled) - -+ kvm-intel.vmentry_l1d_flush=[KVM,Intel] Mitigation for L1 Terminal Fault -+ CVE-2018-3620. -+ -+ Valid arguments: never, cond, always -+ -+ always: L1D cache flush on every VMENTER. -+ cond: Flush L1D on VMENTER only when the code between -+ VMEXIT and VMENTER can leak host memory. -+ never: Disables the mitigation -+ -+ Default is cond (do L1 cache flush in specific instances) -+ - kvm-intel.vpid= [KVM,Intel] Disable Virtual Processor Identification - feature (tagged TLBs) on capable Intel chips. - Default is 1 (enabled) ---- a/arch/x86/kvm/vmx.c -+++ b/arch/x86/kvm/vmx.c -@@ -191,6 +191,54 @@ module_param(ple_window_max, uint, 0444) - - extern const ulong vmx_return; - -+static DEFINE_STATIC_KEY_FALSE(vmx_l1d_should_flush); -+ -+/* These MUST be in sync with vmentry_l1d_param order. */ -+enum vmx_l1d_flush_state { -+ VMENTER_L1D_FLUSH_NEVER, -+ VMENTER_L1D_FLUSH_COND, -+ VMENTER_L1D_FLUSH_ALWAYS, -+}; -+ -+static enum vmx_l1d_flush_state __read_mostly vmentry_l1d_flush = VMENTER_L1D_FLUSH_COND; -+ -+static const struct { -+ const char *option; -+ enum vmx_l1d_flush_state cmd; -+} vmentry_l1d_param[] = { -+ {"never", VMENTER_L1D_FLUSH_NEVER}, -+ {"cond", VMENTER_L1D_FLUSH_COND}, -+ {"always", VMENTER_L1D_FLUSH_ALWAYS}, -+}; -+ -+static int vmentry_l1d_flush_set(const char *s, const struct kernel_param *kp) -+{ -+ unsigned int i; -+ -+ if (!s) -+ return -EINVAL; -+ -+ for (i = 0; i < ARRAY_SIZE(vmentry_l1d_param); i++) { -+ if (!strcmp(s, vmentry_l1d_param[i].option)) { -+ vmentry_l1d_flush = vmentry_l1d_param[i].cmd; -+ return 0; -+ } -+ } -+ -+ return -EINVAL; -+} -+ -+static int vmentry_l1d_flush_get(char *s, const struct kernel_param *kp) -+{ -+ return sprintf(s, "%s\n", vmentry_l1d_param[vmentry_l1d_flush].option); -+} -+ -+static const struct kernel_param_ops vmentry_l1d_flush_ops = { -+ .set = vmentry_l1d_flush_set, -+ .get = vmentry_l1d_flush_get, -+}; -+module_param_cb(vmentry_l1d_flush, &vmentry_l1d_flush_ops, &vmentry_l1d_flush, S_IRUGO); -+ - struct kvm_vmx { - struct kvm kvm; - -@@ -12881,6 +12929,15 @@ static struct kvm_x86_ops vmx_x86_ops __ - .enable_smi_window = enable_smi_window, - }; - -+static void __init vmx_setup_l1d_flush(void) -+{ -+ if (vmentry_l1d_flush == VMENTER_L1D_FLUSH_NEVER || -+ !boot_cpu_has_bug(X86_BUG_L1TF)) -+ return; -+ -+ static_branch_enable(&vmx_l1d_should_flush); -+} -+ - static int __init vmx_init(void) - { - int r; -@@ -12914,6 +12971,8 @@ static int __init vmx_init(void) - } - #endif - -+ vmx_setup_l1d_flush(); -+ - r = kvm_init(&vmx_x86_ops, sizeof(struct vcpu_vmx), - __alignof__(struct vcpu_vmx), THIS_MODULE); - if (r) -From foo@baz Tue Aug 14 13:43:11 CEST 2018 -From: Paolo Bonzini -Date: Mon, 2 Jul 2018 12:47:38 +0200 -Subject: x86/KVM/VMX: Add L1D flush algorithm - -From: Paolo Bonzini - -commit a47dd5f06714c844b33f3b5f517b6f3e81ce57b5 upstream - -To mitigate the L1 Terminal Fault vulnerability it's required to flush L1D -on VMENTER to prevent rogue guests from snooping host memory. - -CPUs will have a new control MSR via a microcode update to flush L1D with a -single MSR write, but in the absence of microcode a fallback to a software -based flush algorithm is required. - -Add a software flush loop which is based on code from Intel. - -[ tglx: Split out from combo patch ] -[ bpetkov: Polish the asm code ] - -Signed-off-by: Paolo Bonzini -Signed-off-by: Konrad Rzeszutek Wilk -Signed-off-by: Thomas Gleixner -Signed-off-by: Greg Kroah-Hartman ---- - arch/x86/kvm/vmx.c | 71 +++++++++++++++++++++++++++++++++++++++++++++++++---- - 1 file changed, 66 insertions(+), 5 deletions(-) - ---- a/arch/x86/kvm/vmx.c -+++ b/arch/x86/kvm/vmx.c -@@ -9333,6 +9333,46 @@ static int vmx_handle_exit(struct kvm_vc - } - } - -+/* -+ * Software based L1D cache flush which is used when microcode providing -+ * the cache control MSR is not loaded. -+ * -+ * The L1D cache is 32 KiB on Nehalem and later microarchitectures, but to -+ * flush it is required to read in 64 KiB because the replacement algorithm -+ * is not exactly LRU. This could be sized at runtime via topology -+ * information but as all relevant affected CPUs have 32KiB L1D cache size -+ * there is no point in doing so. -+ */ -+#define L1D_CACHE_ORDER 4 -+static void *vmx_l1d_flush_pages; -+ -+static void __maybe_unused vmx_l1d_flush(void) -+{ -+ int size = PAGE_SIZE << L1D_CACHE_ORDER; -+ -+ asm volatile( -+ /* First ensure the pages are in the TLB */ -+ "xorl %%eax, %%eax\n" -+ ".Lpopulate_tlb:\n\t" -+ "movzbl (%[empty_zp], %%" _ASM_AX "), %%ecx\n\t" -+ "addl $4096, %%eax\n\t" -+ "cmpl %%eax, %[size]\n\t" -+ "jne .Lpopulate_tlb\n\t" -+ "xorl %%eax, %%eax\n\t" -+ "cpuid\n\t" -+ /* Now fill the cache */ -+ "xorl %%eax, %%eax\n" -+ ".Lfill_cache:\n" -+ "movzbl (%[empty_zp], %%" _ASM_AX "), %%ecx\n\t" -+ "addl $64, %%eax\n\t" -+ "cmpl %%eax, %[size]\n\t" -+ "jne .Lfill_cache\n\t" -+ "lfence\n" -+ :: [empty_zp] "r" (vmx_l1d_flush_pages), -+ [size] "r" (size) -+ : "eax", "ebx", "ecx", "edx"); -+} -+ - static void update_cr8_intercept(struct kvm_vcpu *vcpu, int tpr, int irr) - { - struct vmcs12 *vmcs12 = get_vmcs12(vcpu); -@@ -12929,13 +12969,29 @@ static struct kvm_x86_ops vmx_x86_ops __ - .enable_smi_window = enable_smi_window, - }; - --static void __init vmx_setup_l1d_flush(void) -+static int __init vmx_setup_l1d_flush(void) - { -+ struct page *page; -+ - if (vmentry_l1d_flush == VMENTER_L1D_FLUSH_NEVER || - !boot_cpu_has_bug(X86_BUG_L1TF)) -- return; -+ return 0; -+ -+ page = alloc_pages(GFP_KERNEL, L1D_CACHE_ORDER); -+ if (!page) -+ return -ENOMEM; - -+ vmx_l1d_flush_pages = page_address(page); - static_branch_enable(&vmx_l1d_should_flush); -+ return 0; -+} -+ -+static void vmx_free_l1d_flush_pages(void) -+{ -+ if (vmx_l1d_flush_pages) { -+ free_pages((unsigned long)vmx_l1d_flush_pages, L1D_CACHE_ORDER); -+ vmx_l1d_flush_pages = NULL; -+ } - } - - static int __init vmx_init(void) -@@ -12971,12 +13027,16 @@ static int __init vmx_init(void) - } - #endif - -- vmx_setup_l1d_flush(); -+ r = vmx_setup_l1d_flush(); -+ if (r) -+ return r; - - r = kvm_init(&vmx_x86_ops, sizeof(struct vcpu_vmx), -- __alignof__(struct vcpu_vmx), THIS_MODULE); -- if (r) -+ __alignof__(struct vcpu_vmx), THIS_MODULE); -+ if (r) { -+ vmx_free_l1d_flush_pages(); - return r; -+ } - - #ifdef CONFIG_KEXEC_CORE - rcu_assign_pointer(crash_vmclear_loaded_vmcss, -@@ -13017,6 +13077,7 @@ static void __exit vmx_exit(void) - static_branch_disable(&enable_evmcs); - } - #endif -+ vmx_free_l1d_flush_pages(); - } - - module_init(vmx_init) -From foo@baz Tue Aug 14 13:43:11 CEST 2018 -From: Paolo Bonzini -Date: Mon, 2 Jul 2018 13:03:48 +0200 -Subject: x86/KVM/VMX: Add L1D MSR based flush - -From: Paolo Bonzini - -commit 3fa045be4c720146b18a19cea7a767dc6ad5df94 upstream - -336996-Speculative-Execution-Side-Channel-Mitigations.pdf defines a new MSR -(IA32_FLUSH_CMD aka 0x10B) which has similar write-only semantics to other -MSRs defined in the document. - -The semantics of this MSR is to allow "finer granularity invalidation of -caching structures than existing mechanisms like WBINVD. It will writeback -and invalidate the L1 data cache, including all cachelines brought in by -preceding instructions, without invalidating all caches (eg. L2 or -LLC). Some processors may also invalidate the first level level instruction -cache on a L1D_FLUSH command. The L1 data and instruction caches may be -shared across the logical processors of a core." - -Use it instead of the loop based L1 flush algorithm. - -A copy of this document is available at - https://bugzilla.kernel.org/show_bug.cgi?id=199511 - -[ tglx: Avoid allocating pages when the MSR is available ] - -Signed-off-by: Paolo Bonzini -Signed-off-by: Konrad Rzeszutek Wilk -Signed-off-by: Thomas Gleixner -Signed-off-by: Greg Kroah-Hartman ---- - arch/x86/include/asm/msr-index.h | 6 ++++++ - arch/x86/kvm/vmx.c | 15 +++++++++++---- - 2 files changed, 17 insertions(+), 4 deletions(-) - ---- a/arch/x86/include/asm/msr-index.h -+++ b/arch/x86/include/asm/msr-index.h -@@ -76,6 +76,12 @@ - * control required. - */ - -+#define MSR_IA32_FLUSH_CMD 0x0000010b -+#define L1D_FLUSH (1 << 0) /* -+ * Writeback and invalidate the -+ * L1 data cache. -+ */ -+ - #define MSR_IA32_BBL_CR_CTL 0x00000119 - #define MSR_IA32_BBL_CR_CTL3 0x0000011e - ---- a/arch/x86/kvm/vmx.c -+++ b/arch/x86/kvm/vmx.c -@@ -9350,6 +9350,11 @@ static void __maybe_unused vmx_l1d_flush - { - int size = PAGE_SIZE << L1D_CACHE_ORDER; - -+ if (static_cpu_has(X86_FEATURE_FLUSH_L1D)) { -+ wrmsrl(MSR_IA32_FLUSH_CMD, L1D_FLUSH); -+ return; -+ } -+ - asm volatile( - /* First ensure the pages are in the TLB */ - "xorl %%eax, %%eax\n" -@@ -12977,11 +12982,13 @@ static int __init vmx_setup_l1d_flush(vo - !boot_cpu_has_bug(X86_BUG_L1TF)) - return 0; - -- page = alloc_pages(GFP_KERNEL, L1D_CACHE_ORDER); -- if (!page) -- return -ENOMEM; -+ if (!boot_cpu_has(X86_FEATURE_FLUSH_L1D)) { -+ page = alloc_pages(GFP_KERNEL, L1D_CACHE_ORDER); -+ if (!page) -+ return -ENOMEM; -+ vmx_l1d_flush_pages = page_address(page); -+ } - -- vmx_l1d_flush_pages = page_address(page); - static_branch_enable(&vmx_l1d_should_flush); - return 0; - } -From foo@baz Tue Aug 14 13:43:11 CEST 2018 -From: Paolo Bonzini -Date: Mon, 2 Jul 2018 13:07:14 +0200 -Subject: x86/KVM/VMX: Add L1D flush logic - -From: Paolo Bonzini - -commit c595ceee45707f00f64f61c54fb64ef0cc0b4e85 upstream - -Add the logic for flushing L1D on VMENTER. The flush depends on the static -key being enabled and the new l1tf_flush_l1d flag being set. - -The flags is set: - - Always, if the flush module parameter is 'always' - - - Conditionally at: - - Entry to vcpu_run(), i.e. after executing user space - - - From the sched_in notifier, i.e. when switching to a vCPU thread. - - - From vmexit handlers which are considered unsafe, i.e. where - sensitive data can be brought into L1D: - - - The emulator, which could be a good target for other speculative - execution-based threats, - - - The MMU, which can bring host page tables in the L1 cache. - - - External interrupts - - - Nested operations that require the MMU (see above). That is - vmptrld, vmptrst, vmclear,vmwrite,vmread. - - - When handling invept,invvpid - -[ tglx: Split out from combo patch and reduced to a single flag ] - -Signed-off-by: Paolo Bonzini -Signed-off-by: Konrad Rzeszutek Wilk -Signed-off-by: Thomas Gleixner -Signed-off-by: Greg Kroah-Hartman ---- - arch/x86/include/asm/kvm_host.h | 4 ++++ - arch/x86/kvm/mmu.c | 1 + - arch/x86/kvm/vmx.c | 22 +++++++++++++++++++++- - arch/x86/kvm/x86.c | 8 ++++++++ - 4 files changed, 34 insertions(+), 1 deletion(-) - ---- a/arch/x86/include/asm/kvm_host.h -+++ b/arch/x86/include/asm/kvm_host.h -@@ -711,6 +711,9 @@ struct kvm_vcpu_arch { - - /* be preempted when it's in kernel-mode(cpl=0) */ - bool preempted_in_kernel; -+ -+ /* Flush the L1 Data cache for L1TF mitigation on VMENTER */ -+ bool l1tf_flush_l1d; - }; - - struct kvm_lpage_info { -@@ -879,6 +882,7 @@ struct kvm_vcpu_stat { - u64 signal_exits; - u64 irq_window_exits; - u64 nmi_window_exits; -+ u64 l1d_flush; - u64 halt_exits; - u64 halt_successful_poll; - u64 halt_attempted_poll; ---- a/arch/x86/kvm/mmu.c -+++ b/arch/x86/kvm/mmu.c -@@ -3836,6 +3836,7 @@ int kvm_handle_page_fault(struct kvm_vcp - { - int r = 1; - -+ vcpu->arch.l1tf_flush_l1d = true; - switch (vcpu->arch.apf.host_apf_reason) { - default: - trace_kvm_page_fault(fault_address, error_code); ---- a/arch/x86/kvm/vmx.c -+++ b/arch/x86/kvm/vmx.c -@@ -9346,9 +9346,20 @@ static int vmx_handle_exit(struct kvm_vc - #define L1D_CACHE_ORDER 4 - static void *vmx_l1d_flush_pages; - --static void __maybe_unused vmx_l1d_flush(void) -+static void vmx_l1d_flush(struct kvm_vcpu *vcpu) - { - int size = PAGE_SIZE << L1D_CACHE_ORDER; -+ bool always; -+ -+ /* -+ * If the mitigation mode is 'flush always', keep the flush bit -+ * set, otherwise clear it. It gets set again either from -+ * vcpu_run() or from one of the unsafe VMEXIT handlers. -+ */ -+ always = vmentry_l1d_flush == VMENTER_L1D_FLUSH_ALWAYS; -+ vcpu->arch.l1tf_flush_l1d = always; -+ -+ vcpu->stat.l1d_flush++; - - if (static_cpu_has(X86_FEATURE_FLUSH_L1D)) { - wrmsrl(MSR_IA32_FLUSH_CMD, L1D_FLUSH); -@@ -9622,6 +9633,7 @@ static void vmx_handle_external_intr(str - [ss]"i"(__KERNEL_DS), - [cs]"i"(__KERNEL_CS) - ); -+ vcpu->arch.l1tf_flush_l1d = true; - } - } - STACK_FRAME_NON_STANDARD(vmx_handle_external_intr); -@@ -9879,6 +9891,11 @@ static void __noclone vmx_vcpu_run(struc - evmcs_rsp = static_branch_unlikely(&enable_evmcs) ? - (unsigned long)¤t_evmcs->host_rsp : 0; - -+ if (static_branch_unlikely(&vmx_l1d_should_flush)) { -+ if (vcpu->arch.l1tf_flush_l1d) -+ vmx_l1d_flush(vcpu); -+ } -+ - asm( - /* Store host registers */ - "push %%" _ASM_DX "; push %%" _ASM_BP ";" -@@ -11748,6 +11765,9 @@ static int nested_vmx_run(struct kvm_vcp - if (ret) - return ret; - -+ /* Hide L1D cache contents from the nested guest. */ -+ vmx->vcpu.arch.l1tf_flush_l1d = true; -+ - /* - * If we're entering a halted L2 vcpu and the L2 vcpu won't be woken - * by event injection, halt vcpu. ---- a/arch/x86/kvm/x86.c -+++ b/arch/x86/kvm/x86.c -@@ -194,6 +194,7 @@ struct kvm_stats_debugfs_item debugfs_en - { "irq_injections", VCPU_STAT(irq_injections) }, - { "nmi_injections", VCPU_STAT(nmi_injections) }, - { "req_event", VCPU_STAT(req_event) }, -+ { "l1d_flush", VCPU_STAT(l1d_flush) }, - { "mmu_shadow_zapped", VM_STAT(mmu_shadow_zapped) }, - { "mmu_pte_write", VM_STAT(mmu_pte_write) }, - { "mmu_pte_updated", VM_STAT(mmu_pte_updated) }, -@@ -4870,6 +4871,9 @@ static int emulator_write_std(struct x86 - int kvm_write_guest_virt_system(struct kvm_vcpu *vcpu, gva_t addr, void *val, - unsigned int bytes, struct x86_exception *exception) - { -+ /* kvm_write_guest_virt_system can pull in tons of pages. */ -+ vcpu->arch.l1tf_flush_l1d = true; -+ - return kvm_write_guest_virt_helper(addr, val, bytes, vcpu, - PFERR_WRITE_MASK, exception); - } -@@ -6046,6 +6050,8 @@ int x86_emulate_instruction(struct kvm_v - bool writeback = true; - bool write_fault_to_spt = vcpu->arch.write_fault_to_shadow_pgtable; - -+ vcpu->arch.l1tf_flush_l1d = true; -+ - /* - * Clear write_fault_to_shadow_pgtable here to ensure it is - * never reused. -@@ -7575,6 +7581,7 @@ static int vcpu_run(struct kvm_vcpu *vcp - struct kvm *kvm = vcpu->kvm; - - vcpu->srcu_idx = srcu_read_lock(&kvm->srcu); -+ vcpu->arch.l1tf_flush_l1d = true; - - for (;;) { - if (kvm_vcpu_running(vcpu)) { -@@ -8694,6 +8701,7 @@ void kvm_arch_vcpu_uninit(struct kvm_vcp - - void kvm_arch_sched_in(struct kvm_vcpu *vcpu, int cpu) - { -+ vcpu->arch.l1tf_flush_l1d = true; - kvm_x86_ops->sched_in(vcpu, cpu); - } - -From foo@baz Tue Aug 14 13:43:11 CEST 2018 -From: Konrad Rzeszutek Wilk -Date: Wed, 20 Jun 2018 13:58:37 -0400 -Subject: x86/KVM/VMX: Split the VMX MSR LOAD structures to have an host/guest numbers - -From: Konrad Rzeszutek Wilk - -commit 33966dd6b2d2c352fae55412db2ea8cfff5df13a upstream - -There is no semantic change but this change allows an unbalanced amount of -MSRs to be loaded on VMEXIT and VMENTER, i.e. the number of MSRs to save or -restore on VMEXIT or VMENTER may be different. - -Signed-off-by: Konrad Rzeszutek Wilk -Signed-off-by: Thomas Gleixner -Signed-off-by: Greg Kroah-Hartman ---- - arch/x86/kvm/vmx.c | 65 ++++++++++++++++++++++++++++------------------------- - 1 file changed, 35 insertions(+), 30 deletions(-) - ---- a/arch/x86/kvm/vmx.c -+++ b/arch/x86/kvm/vmx.c -@@ -642,6 +642,11 @@ static inline int pi_test_sn(struct pi_d - (unsigned long *)&pi_desc->control); - } - -+struct vmx_msrs { -+ unsigned int nr; -+ struct vmx_msr_entry val[NR_AUTOLOAD_MSRS]; -+}; -+ - struct vcpu_vmx { - struct kvm_vcpu vcpu; - unsigned long host_rsp; -@@ -675,9 +680,8 @@ struct vcpu_vmx { - struct loaded_vmcs *loaded_vmcs; - bool __launched; /* temporary, used in vmx_vcpu_run */ - struct msr_autoload { -- unsigned nr; -- struct vmx_msr_entry guest[NR_AUTOLOAD_MSRS]; -- struct vmx_msr_entry host[NR_AUTOLOAD_MSRS]; -+ struct vmx_msrs guest; -+ struct vmx_msrs host; - } msr_autoload; - struct { - int loaded; -@@ -2256,18 +2260,18 @@ static void clear_atomic_switch_msr(stru - } - break; - } -- -- for (i = 0; i < m->nr; ++i) -- if (m->guest[i].index == msr) -+ for (i = 0; i < m->guest.nr; ++i) -+ if (m->guest.val[i].index == msr) - break; - -- if (i == m->nr) -+ if (i == m->guest.nr) - return; -- --m->nr; -- m->guest[i] = m->guest[m->nr]; -- m->host[i] = m->host[m->nr]; -- vmcs_write32(VM_ENTRY_MSR_LOAD_COUNT, m->nr); -- vmcs_write32(VM_EXIT_MSR_LOAD_COUNT, m->nr); -+ --m->guest.nr; -+ --m->host.nr; -+ m->guest.val[i] = m->guest.val[m->guest.nr]; -+ m->host.val[i] = m->host.val[m->host.nr]; -+ vmcs_write32(VM_ENTRY_MSR_LOAD_COUNT, m->guest.nr); -+ vmcs_write32(VM_EXIT_MSR_LOAD_COUNT, m->host.nr); - } - - static void add_atomic_switch_msr_special(struct vcpu_vmx *vmx, -@@ -2319,24 +2323,25 @@ static void add_atomic_switch_msr(struct - wrmsrl(MSR_IA32_PEBS_ENABLE, 0); - } - -- for (i = 0; i < m->nr; ++i) -- if (m->guest[i].index == msr) -+ for (i = 0; i < m->guest.nr; ++i) -+ if (m->guest.val[i].index == msr) - break; - - if (i == NR_AUTOLOAD_MSRS) { - printk_once(KERN_WARNING "Not enough msr switch entries. " - "Can't add msr %x\n", msr); - return; -- } else if (i == m->nr) { -- ++m->nr; -- vmcs_write32(VM_ENTRY_MSR_LOAD_COUNT, m->nr); -- vmcs_write32(VM_EXIT_MSR_LOAD_COUNT, m->nr); -+ } else if (i == m->guest.nr) { -+ ++m->guest.nr; -+ ++m->host.nr; -+ vmcs_write32(VM_ENTRY_MSR_LOAD_COUNT, m->guest.nr); -+ vmcs_write32(VM_EXIT_MSR_LOAD_COUNT, m->host.nr); - } - -- m->guest[i].index = msr; -- m->guest[i].value = guest_val; -- m->host[i].index = msr; -- m->host[i].value = host_val; -+ m->guest.val[i].index = msr; -+ m->guest.val[i].value = guest_val; -+ m->host.val[i].index = msr; -+ m->host.val[i].value = host_val; - } - - static bool update_transition_efer(struct vcpu_vmx *vmx, int efer_offset) -@@ -6092,9 +6097,9 @@ static void vmx_vcpu_setup(struct vcpu_v - - vmcs_write32(VM_EXIT_MSR_STORE_COUNT, 0); - vmcs_write32(VM_EXIT_MSR_LOAD_COUNT, 0); -- vmcs_write64(VM_EXIT_MSR_LOAD_ADDR, __pa(vmx->msr_autoload.host)); -+ vmcs_write64(VM_EXIT_MSR_LOAD_ADDR, __pa(vmx->msr_autoload.host.val)); - vmcs_write32(VM_ENTRY_MSR_LOAD_COUNT, 0); -- vmcs_write64(VM_ENTRY_MSR_LOAD_ADDR, __pa(vmx->msr_autoload.guest)); -+ vmcs_write64(VM_ENTRY_MSR_LOAD_ADDR, __pa(vmx->msr_autoload.guest.val)); - - if (vmcs_config.vmentry_ctrl & VM_ENTRY_LOAD_IA32_PAT) - vmcs_write64(GUEST_IA32_PAT, vmx->vcpu.arch.pat); -@@ -11128,10 +11133,10 @@ static void prepare_vmcs02_full(struct k - * Set the MSR load/store lists to match L0's settings. - */ - vmcs_write32(VM_EXIT_MSR_STORE_COUNT, 0); -- vmcs_write32(VM_EXIT_MSR_LOAD_COUNT, vmx->msr_autoload.nr); -- vmcs_write64(VM_EXIT_MSR_LOAD_ADDR, __pa(vmx->msr_autoload.host)); -- vmcs_write32(VM_ENTRY_MSR_LOAD_COUNT, vmx->msr_autoload.nr); -- vmcs_write64(VM_ENTRY_MSR_LOAD_ADDR, __pa(vmx->msr_autoload.guest)); -+ vmcs_write32(VM_EXIT_MSR_LOAD_COUNT, vmx->msr_autoload.host.nr); -+ vmcs_write64(VM_EXIT_MSR_LOAD_ADDR, __pa(vmx->msr_autoload.host.val)); -+ vmcs_write32(VM_ENTRY_MSR_LOAD_COUNT, vmx->msr_autoload.guest.nr); -+ vmcs_write64(VM_ENTRY_MSR_LOAD_ADDR, __pa(vmx->msr_autoload.guest.val)); - - set_cr4_guest_host_mask(vmx); - -@@ -12281,8 +12286,8 @@ static void nested_vmx_vmexit(struct kvm - vmx_segment_cache_clear(vmx); - - /* Update any VMCS fields that might have changed while L2 ran */ -- vmcs_write32(VM_EXIT_MSR_LOAD_COUNT, vmx->msr_autoload.nr); -- vmcs_write32(VM_ENTRY_MSR_LOAD_COUNT, vmx->msr_autoload.nr); -+ vmcs_write32(VM_EXIT_MSR_LOAD_COUNT, vmx->msr_autoload.host.nr); -+ vmcs_write32(VM_ENTRY_MSR_LOAD_COUNT, vmx->msr_autoload.guest.nr); - vmcs_write64(TSC_OFFSET, vcpu->arch.tsc_offset); - if (vmx->hv_deadline_tsc == -1) - vmcs_clear_bits(PIN_BASED_VM_EXEC_CONTROL, -From foo@baz Tue Aug 14 13:43:11 CEST 2018 -From: Konrad Rzeszutek Wilk -Date: Wed, 20 Jun 2018 20:11:39 -0400 -Subject: x86/KVM/VMX: Add find_msr() helper function - -From: Konrad Rzeszutek Wilk - -commit ca83b4a7f2d068da79a029d323024aa45decb250 upstream - -.. to help find the MSR on either the guest or host MSR list. - -Signed-off-by: Konrad Rzeszutek Wilk -Signed-off-by: Thomas Gleixner -Signed-off-by: Greg Kroah-Hartman ---- - arch/x86/kvm/vmx.c | 31 ++++++++++++++++++------------- - 1 file changed, 18 insertions(+), 13 deletions(-) - ---- a/arch/x86/kvm/vmx.c -+++ b/arch/x86/kvm/vmx.c -@@ -2237,9 +2237,20 @@ static void clear_atomic_switch_msr_spec - vm_exit_controls_clearbit(vmx, exit); - } - -+static int find_msr(struct vmx_msrs *m, unsigned int msr) -+{ -+ unsigned int i; -+ -+ for (i = 0; i < m->nr; ++i) { -+ if (m->val[i].index == msr) -+ return i; -+ } -+ return -ENOENT; -+} -+ - static void clear_atomic_switch_msr(struct vcpu_vmx *vmx, unsigned msr) - { -- unsigned i; -+ int i; - struct msr_autoload *m = &vmx->msr_autoload; - - switch (msr) { -@@ -2260,11 +2271,8 @@ static void clear_atomic_switch_msr(stru - } - break; - } -- for (i = 0; i < m->guest.nr; ++i) -- if (m->guest.val[i].index == msr) -- break; -- -- if (i == m->guest.nr) -+ i = find_msr(&m->guest, msr); -+ if (i < 0) - return; - --m->guest.nr; - --m->host.nr; -@@ -2288,7 +2296,7 @@ static void add_atomic_switch_msr_specia - static void add_atomic_switch_msr(struct vcpu_vmx *vmx, unsigned msr, - u64 guest_val, u64 host_val) - { -- unsigned i; -+ int i; - struct msr_autoload *m = &vmx->msr_autoload; - - switch (msr) { -@@ -2323,16 +2331,13 @@ static void add_atomic_switch_msr(struct - wrmsrl(MSR_IA32_PEBS_ENABLE, 0); - } - -- for (i = 0; i < m->guest.nr; ++i) -- if (m->guest.val[i].index == msr) -- break; -- -+ i = find_msr(&m->guest, msr); - if (i == NR_AUTOLOAD_MSRS) { - printk_once(KERN_WARNING "Not enough msr switch entries. " - "Can't add msr %x\n", msr); - return; -- } else if (i == m->guest.nr) { -- ++m->guest.nr; -+ } else if (i < 0) { -+ i = m->guest.nr++; - ++m->host.nr; - vmcs_write32(VM_ENTRY_MSR_LOAD_COUNT, m->guest.nr); - vmcs_write32(VM_EXIT_MSR_LOAD_COUNT, m->host.nr); -From foo@baz Tue Aug 14 13:43:11 CEST 2018 -From: Konrad Rzeszutek Wilk -Date: Wed, 20 Jun 2018 22:00:47 -0400 -Subject: x86/KVM/VMX: Separate the VMX AUTOLOAD guest/host number accounting - -From: Konrad Rzeszutek Wilk - -commit 3190709335dd31fe1aeeebfe4ffb6c7624ef971f upstream - -This allows to load a different number of MSRs depending on the context: -VMEXIT or VMENTER. - -Signed-off-by: Konrad Rzeszutek Wilk -Signed-off-by: Thomas Gleixner -Signed-off-by: Greg Kroah-Hartman ---- - arch/x86/kvm/vmx.c | 29 +++++++++++++++++++---------- - 1 file changed, 19 insertions(+), 10 deletions(-) - ---- a/arch/x86/kvm/vmx.c -+++ b/arch/x86/kvm/vmx.c -@@ -2273,12 +2273,18 @@ static void clear_atomic_switch_msr(stru - } - i = find_msr(&m->guest, msr); - if (i < 0) -- return; -+ goto skip_guest; - --m->guest.nr; -- --m->host.nr; - m->guest.val[i] = m->guest.val[m->guest.nr]; -- m->host.val[i] = m->host.val[m->host.nr]; - vmcs_write32(VM_ENTRY_MSR_LOAD_COUNT, m->guest.nr); -+ -+skip_guest: -+ i = find_msr(&m->host, msr); -+ if (i < 0) -+ return; -+ -+ --m->host.nr; -+ m->host.val[i] = m->host.val[m->host.nr]; - vmcs_write32(VM_EXIT_MSR_LOAD_COUNT, m->host.nr); - } - -@@ -2296,7 +2302,7 @@ static void add_atomic_switch_msr_specia - static void add_atomic_switch_msr(struct vcpu_vmx *vmx, unsigned msr, - u64 guest_val, u64 host_val) - { -- int i; -+ int i, j; - struct msr_autoload *m = &vmx->msr_autoload; - - switch (msr) { -@@ -2332,21 +2338,24 @@ static void add_atomic_switch_msr(struct - } - - i = find_msr(&m->guest, msr); -- if (i == NR_AUTOLOAD_MSRS) { -+ j = find_msr(&m->host, msr); -+ if (i == NR_AUTOLOAD_MSRS || j == NR_AUTOLOAD_MSRS) { - printk_once(KERN_WARNING "Not enough msr switch entries. " - "Can't add msr %x\n", msr); - return; -- } else if (i < 0) { -+ } -+ if (i < 0) { - i = m->guest.nr++; -- ++m->host.nr; - vmcs_write32(VM_ENTRY_MSR_LOAD_COUNT, m->guest.nr); -+ } -+ if (j < 0) { -+ j = m->host.nr++; - vmcs_write32(VM_EXIT_MSR_LOAD_COUNT, m->host.nr); - } -- - m->guest.val[i].index = msr; - m->guest.val[i].value = guest_val; -- m->host.val[i].index = msr; -- m->host.val[i].value = host_val; -+ m->host.val[j].index = msr; -+ m->host.val[j].value = host_val; - } - - static bool update_transition_efer(struct vcpu_vmx *vmx, int efer_offset) -From foo@baz Tue Aug 14 13:43:11 CEST 2018 -From: Konrad Rzeszutek Wilk -Date: Wed, 20 Jun 2018 22:01:22 -0400 -Subject: x86/KVM/VMX: Extend add_atomic_switch_msr() to allow VMENTER only MSRs - -From: Konrad Rzeszutek Wilk - -commit 989e3992d2eca32c3f1404f2bc91acda3aa122d8 upstream - -The IA32_FLUSH_CMD MSR needs only to be written on VMENTER. Extend -add_atomic_switch_msr() with an entry_only parameter to allow storing the -MSR only in the guest (ENTRY) MSR array. - -Signed-off-by: Konrad Rzeszutek Wilk -Signed-off-by: Thomas Gleixner -Signed-off-by: Greg Kroah-Hartman ---- - arch/x86/kvm/vmx.c | 22 ++++++++++++++-------- - 1 file changed, 14 insertions(+), 8 deletions(-) - ---- a/arch/x86/kvm/vmx.c -+++ b/arch/x86/kvm/vmx.c -@@ -2300,9 +2300,9 @@ static void add_atomic_switch_msr_specia - } - - static void add_atomic_switch_msr(struct vcpu_vmx *vmx, unsigned msr, -- u64 guest_val, u64 host_val) -+ u64 guest_val, u64 host_val, bool entry_only) - { -- int i, j; -+ int i, j = 0; - struct msr_autoload *m = &vmx->msr_autoload; - - switch (msr) { -@@ -2338,7 +2338,9 @@ static void add_atomic_switch_msr(struct - } - - i = find_msr(&m->guest, msr); -- j = find_msr(&m->host, msr); -+ if (!entry_only) -+ j = find_msr(&m->host, msr); -+ - if (i == NR_AUTOLOAD_MSRS || j == NR_AUTOLOAD_MSRS) { - printk_once(KERN_WARNING "Not enough msr switch entries. " - "Can't add msr %x\n", msr); -@@ -2348,12 +2350,16 @@ static void add_atomic_switch_msr(struct - i = m->guest.nr++; - vmcs_write32(VM_ENTRY_MSR_LOAD_COUNT, m->guest.nr); - } -+ m->guest.val[i].index = msr; -+ m->guest.val[i].value = guest_val; -+ -+ if (entry_only) -+ return; -+ - if (j < 0) { - j = m->host.nr++; - vmcs_write32(VM_EXIT_MSR_LOAD_COUNT, m->host.nr); - } -- m->guest.val[i].index = msr; -- m->guest.val[i].value = guest_val; - m->host.val[j].index = msr; - m->host.val[j].value = host_val; - } -@@ -2399,7 +2405,7 @@ static bool update_transition_efer(struc - guest_efer &= ~EFER_LME; - if (guest_efer != host_efer) - add_atomic_switch_msr(vmx, MSR_EFER, -- guest_efer, host_efer); -+ guest_efer, host_efer, false); - return false; - } else { - guest_efer &= ~ignore_bits; -@@ -3845,7 +3851,7 @@ static int vmx_set_msr(struct kvm_vcpu * - vcpu->arch.ia32_xss = data; - if (vcpu->arch.ia32_xss != host_xss) - add_atomic_switch_msr(vmx, MSR_IA32_XSS, -- vcpu->arch.ia32_xss, host_xss); -+ vcpu->arch.ia32_xss, host_xss, false); - else - clear_atomic_switch_msr(vmx, MSR_IA32_XSS); - break; -@@ -9815,7 +9821,7 @@ static void atomic_switch_perf_msrs(stru - clear_atomic_switch_msr(vmx, msrs[i].msr); - else - add_atomic_switch_msr(vmx, msrs[i].msr, msrs[i].guest, -- msrs[i].host); -+ msrs[i].host, false); - } - - static void vmx_arm_hv_timer(struct kvm_vcpu *vcpu) -From foo@baz Tue Aug 14 13:43:11 CEST 2018 -From: Konrad Rzeszutek Wilk -Date: Thu, 28 Jun 2018 17:10:36 -0400 -Subject: x86/KVM/VMX: Use MSR save list for IA32_FLUSH_CMD if required - -From: Konrad Rzeszutek Wilk - -commit 390d975e0c4e60ce70d4157e0dd91ede37824603 upstream - -If the L1D flush module parameter is set to 'always' and the IA32_FLUSH_CMD -MSR is available, optimize the VMENTER code with the MSR save list. - -Signed-off-by: Konrad Rzeszutek Wilk -Signed-off-by: Thomas Gleixner -Signed-off-by: Greg Kroah-Hartman ---- - arch/x86/kvm/vmx.c | 42 +++++++++++++++++++++++++++++++++++++----- - 1 file changed, 37 insertions(+), 5 deletions(-) - ---- a/arch/x86/kvm/vmx.c -+++ b/arch/x86/kvm/vmx.c -@@ -6045,6 +6045,16 @@ static void ept_set_mmio_spte_mask(void) - VMX_EPT_MISCONFIG_WX_VALUE); - } - -+static bool vmx_l1d_use_msr_save_list(void) -+{ -+ if (!enable_ept || !boot_cpu_has_bug(X86_BUG_L1TF) || -+ static_cpu_has(X86_FEATURE_HYPERVISOR) || -+ !static_cpu_has(X86_FEATURE_FLUSH_L1D)) -+ return false; -+ -+ return vmentry_l1d_flush == VMENTER_L1D_FLUSH_ALWAYS; -+} -+ - #define VMX_XSS_EXIT_BITMAP 0 - /* - * Sets up the vmcs for emulated real mode. -@@ -6160,6 +6170,12 @@ static void vmx_vcpu_setup(struct vcpu_v - vmcs_write64(PML_ADDRESS, page_to_phys(vmx->pml_pg)); - vmcs_write16(GUEST_PML_INDEX, PML_ENTITY_NUM - 1); - } -+ /* -+ * If flushing the L1D cache on every VMENTER is enforced and the -+ * MSR is available, use the MSR save list. -+ */ -+ if (vmx_l1d_use_msr_save_list()) -+ add_atomic_switch_msr(vmx, MSR_IA32_FLUSH_CMD, L1D_FLUSH, 0, true); - } - - static void vmx_vcpu_reset(struct kvm_vcpu *vcpu, bool init_event) -@@ -9377,11 +9393,26 @@ static void vmx_l1d_flush(struct kvm_vcp - bool always; - - /* -- * If the mitigation mode is 'flush always', keep the flush bit -- * set, otherwise clear it. It gets set again either from -- * vcpu_run() or from one of the unsafe VMEXIT handlers. -+ * This code is only executed when: -+ * - the flush mode is 'cond' -+ * - the flush mode is 'always' and the flush MSR is not -+ * available -+ * -+ * If the CPU has the flush MSR then clear the flush bit because -+ * 'always' mode is handled via the MSR save list. -+ * -+ * If the MSR is not avaibable then act depending on the mitigation -+ * mode: If 'flush always', keep the flush bit set, otherwise clear -+ * it. -+ * -+ * The flush bit gets set again either from vcpu_run() or from one -+ * of the unsafe VMEXIT handlers. - */ -- always = vmentry_l1d_flush == VMENTER_L1D_FLUSH_ALWAYS; -+ if (static_cpu_has(X86_FEATURE_FLUSH_L1D)) -+ always = false; -+ else -+ always = vmentry_l1d_flush == VMENTER_L1D_FLUSH_ALWAYS; -+ - vcpu->arch.l1tf_flush_l1d = always; - - vcpu->stat.l1d_flush++; -@@ -13024,7 +13055,8 @@ static int __init vmx_setup_l1d_flush(vo - struct page *page; - - if (vmentry_l1d_flush == VMENTER_L1D_FLUSH_NEVER || -- !boot_cpu_has_bug(X86_BUG_L1TF)) -+ !boot_cpu_has_bug(X86_BUG_L1TF) || -+ vmx_l1d_use_msr_save_list()) - return 0; - - if (!boot_cpu_has(X86_FEATURE_FLUSH_L1D)) { -From foo@baz Tue Aug 14 13:43:11 CEST 2018 -From: Thomas Gleixner -Date: Sat, 7 Jul 2018 11:40:18 +0200 -Subject: cpu/hotplug: Online siblings when SMT control is turned on - -From: Thomas Gleixner - -commit 215af5499d9e2b55f111d2431ea20218115f29b3 upstream - -Writing 'off' to /sys/devices/system/cpu/smt/control offlines all SMT -siblings. Writing 'on' merily enables the abilify to online them, but does -not online them automatically. - -Make 'on' more useful by onlining all offline siblings. - -Signed-off-by: Thomas Gleixner -Signed-off-by: Greg Kroah-Hartman ---- - kernel/cpu.c | 26 ++++++++++++++++++++++++-- - 1 file changed, 24 insertions(+), 2 deletions(-) - ---- a/kernel/cpu.c -+++ b/kernel/cpu.c -@@ -1979,6 +1979,15 @@ static void cpuhp_offline_cpu_device(uns - kobject_uevent(&dev->kobj, KOBJ_OFFLINE); - } - -+static void cpuhp_online_cpu_device(unsigned int cpu) -+{ -+ struct device *dev = get_cpu_device(cpu); -+ -+ dev->offline = false; -+ /* Tell user space about the state change */ -+ kobject_uevent(&dev->kobj, KOBJ_ONLINE); -+} -+ - static int cpuhp_smt_disable(enum cpuhp_smt_control ctrlval) - { - int cpu, ret = 0; -@@ -2011,11 +2020,24 @@ static int cpuhp_smt_disable(enum cpuhp_ - return ret; - } - --static void cpuhp_smt_enable(void) -+static int cpuhp_smt_enable(void) - { -+ int cpu, ret = 0; -+ - cpu_maps_update_begin(); - cpu_smt_control = CPU_SMT_ENABLED; -+ for_each_present_cpu(cpu) { -+ /* Skip online CPUs and CPUs on offline nodes */ -+ if (cpu_online(cpu) || !node_online(cpu_to_node(cpu))) -+ continue; -+ ret = _cpu_up(cpu, 0, CPUHP_ONLINE); -+ if (ret) -+ break; -+ /* See comment in cpuhp_smt_disable() */ -+ cpuhp_online_cpu_device(cpu); -+ } - cpu_maps_update_done(); -+ return ret; - } - - static ssize_t -@@ -2046,7 +2068,7 @@ store_smt_control(struct device *dev, st - if (ctrlval != cpu_smt_control) { - switch (ctrlval) { - case CPU_SMT_ENABLED: -- cpuhp_smt_enable(); -+ ret = cpuhp_smt_enable(); - break; - case CPU_SMT_DISABLED: - case CPU_SMT_FORCE_DISABLED: -From foo@baz Tue Aug 14 13:43:11 CEST 2018 -From: Thomas Gleixner -Date: Fri, 13 Jul 2018 16:23:16 +0200 -Subject: x86/litf: Introduce vmx status variable - -From: Thomas Gleixner - -commit 72c6d2db64fa18c996ece8f06e499509e6c9a37e upstream - -Store the effective mitigation of VMX in a status variable and use it to -report the VMX state in the l1tf sysfs file. - -Signed-off-by: Thomas Gleixner -Tested-by: Jiri Kosina -Reviewed-by: Greg Kroah-Hartman -Reviewed-by: Josh Poimboeuf -Link: https://lkml.kernel.org/r/20180713142322.433098358@linutronix.de -Signed-off-by: Greg Kroah-Hartman ---- - arch/x86/include/asm/vmx.h | 9 +++++++++ - arch/x86/kernel/cpu/bugs.c | 36 ++++++++++++++++++++++++++++++++++-- - arch/x86/kvm/vmx.c | 22 +++++++++++----------- - 3 files changed, 54 insertions(+), 13 deletions(-) - ---- a/arch/x86/include/asm/vmx.h -+++ b/arch/x86/include/asm/vmx.h -@@ -574,4 +574,13 @@ enum vm_instruction_error_number { - VMXERR_INVALID_OPERAND_TO_INVEPT_INVVPID = 28, - }; - -+enum vmx_l1d_flush_state { -+ VMENTER_L1D_FLUSH_AUTO, -+ VMENTER_L1D_FLUSH_NEVER, -+ VMENTER_L1D_FLUSH_COND, -+ VMENTER_L1D_FLUSH_ALWAYS, -+}; -+ -+extern enum vmx_l1d_flush_state l1tf_vmx_mitigation; -+ - #endif ---- a/arch/x86/kernel/cpu/bugs.c -+++ b/arch/x86/kernel/cpu/bugs.c -@@ -22,6 +22,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -636,6 +637,12 @@ void x86_spec_ctrl_setup_ap(void) - - #undef pr_fmt - #define pr_fmt(fmt) "L1TF: " fmt -+ -+#if IS_ENABLED(CONFIG_KVM_INTEL) -+enum vmx_l1d_flush_state l1tf_vmx_mitigation __ro_after_init = VMENTER_L1D_FLUSH_AUTO; -+EXPORT_SYMBOL_GPL(l1tf_vmx_mitigation); -+#endif -+ - static void __init l1tf_select_mitigation(void) - { - u64 half_pa; -@@ -665,6 +672,32 @@ static void __init l1tf_select_mitigatio - - #ifdef CONFIG_SYSFS - -+#define L1TF_DEFAULT_MSG "Mitigation: PTE Inversion" -+ -+#if IS_ENABLED(CONFIG_KVM_INTEL) -+static const char *l1tf_vmx_states[] = { -+ [VMENTER_L1D_FLUSH_AUTO] = "auto", -+ [VMENTER_L1D_FLUSH_NEVER] = "vulnerable", -+ [VMENTER_L1D_FLUSH_COND] = "conditional cache flushes", -+ [VMENTER_L1D_FLUSH_ALWAYS] = "cache flushes", -+}; -+ -+static ssize_t l1tf_show_state(char *buf) -+{ -+ if (l1tf_vmx_mitigation == VMENTER_L1D_FLUSH_AUTO) -+ return sprintf(buf, "%s\n", L1TF_DEFAULT_MSG); -+ -+ return sprintf(buf, "%s; VMX: SMT %s, L1D %s\n", L1TF_DEFAULT_MSG, -+ cpu_smt_control == CPU_SMT_ENABLED ? "vulnerable" : "disabled", -+ l1tf_vmx_states[l1tf_vmx_mitigation]); -+} -+#else -+static ssize_t l1tf_show_state(char *buf) -+{ -+ return sprintf(buf, "%s\n", L1TF_DEFAULT_MSG); -+} -+#endif -+ - static ssize_t cpu_show_common(struct device *dev, struct device_attribute *attr, - char *buf, unsigned int bug) - { -@@ -692,9 +725,8 @@ static ssize_t cpu_show_common(struct de - - case X86_BUG_L1TF: - if (boot_cpu_has(X86_FEATURE_L1TF_PTEINV)) -- return sprintf(buf, "Mitigation: Page Table Inversion\n"); -+ return l1tf_show_state(buf); - break; -- - default: - break; - } ---- a/arch/x86/kvm/vmx.c -+++ b/arch/x86/kvm/vmx.c -@@ -193,19 +193,13 @@ extern const ulong vmx_return; - - static DEFINE_STATIC_KEY_FALSE(vmx_l1d_should_flush); - --/* These MUST be in sync with vmentry_l1d_param order. */ --enum vmx_l1d_flush_state { -- VMENTER_L1D_FLUSH_NEVER, -- VMENTER_L1D_FLUSH_COND, -- VMENTER_L1D_FLUSH_ALWAYS, --}; -- - static enum vmx_l1d_flush_state __read_mostly vmentry_l1d_flush = VMENTER_L1D_FLUSH_COND; - - static const struct { - const char *option; - enum vmx_l1d_flush_state cmd; - } vmentry_l1d_param[] = { -+ {"auto", VMENTER_L1D_FLUSH_AUTO}, - {"never", VMENTER_L1D_FLUSH_NEVER}, - {"cond", VMENTER_L1D_FLUSH_COND}, - {"always", VMENTER_L1D_FLUSH_ALWAYS}, -@@ -13054,8 +13048,12 @@ static int __init vmx_setup_l1d_flush(vo - { - struct page *page; - -+ if (!boot_cpu_has_bug(X86_BUG_L1TF)) -+ return 0; -+ -+ l1tf_vmx_mitigation = vmentry_l1d_flush; -+ - if (vmentry_l1d_flush == VMENTER_L1D_FLUSH_NEVER || -- !boot_cpu_has_bug(X86_BUG_L1TF) || - vmx_l1d_use_msr_save_list()) - return 0; - -@@ -13070,12 +13068,14 @@ static int __init vmx_setup_l1d_flush(vo - return 0; - } - --static void vmx_free_l1d_flush_pages(void) -+static void vmx_cleanup_l1d_flush(void) - { - if (vmx_l1d_flush_pages) { - free_pages((unsigned long)vmx_l1d_flush_pages, L1D_CACHE_ORDER); - vmx_l1d_flush_pages = NULL; - } -+ /* Restore state so sysfs ignores VMX */ -+ l1tf_vmx_mitigation = VMENTER_L1D_FLUSH_AUTO; - } - - static int __init vmx_init(void) -@@ -13118,7 +13118,7 @@ static int __init vmx_init(void) - r = kvm_init(&vmx_x86_ops, sizeof(struct vcpu_vmx), - __alignof__(struct vcpu_vmx), THIS_MODULE); - if (r) { -- vmx_free_l1d_flush_pages(); -+ vmx_cleanup_l1d_flush(); - return r; - } - -@@ -13161,7 +13161,7 @@ static void __exit vmx_exit(void) - static_branch_disable(&enable_evmcs); - } - #endif -- vmx_free_l1d_flush_pages(); -+ vmx_cleanup_l1d_flush(); - } - - module_init(vmx_init) -From foo@baz Tue Aug 14 13:43:11 CEST 2018 -From: Thomas Gleixner -Date: Fri, 13 Jul 2018 16:23:17 +0200 -Subject: x86/kvm: Drop L1TF MSR list approach - -From: Thomas Gleixner - -commit 2f055947ae5e2741fb2dc5bba1033c417ccf4faa upstream - -The VMX module parameter to control the L1D flush should become -writeable. - -The MSR list is set up at VM init per guest VCPU, but the run time -switching is based on a static key which is global. Toggling the MSR list -at run time might be feasible, but for now drop this optimization and use -the regular MSR write to make run-time switching possible. - -The default mitigation is the conditional flush anyway, so for extra -paranoid setups this will add some small overhead, but the extra code -executed is in the noise compared to the flush itself. - -Aside of that the EPT disabled case is not handled correctly at the moment -and the MSR list magic is in the way for fixing that as well. - -If it's really providing a significant advantage, then this needs to be -revisited after the code is correct and the control is writable. - -Signed-off-by: Thomas Gleixner -Tested-by: Jiri Kosina -Reviewed-by: Greg Kroah-Hartman -Reviewed-by: Josh Poimboeuf -Link: https://lkml.kernel.org/r/20180713142322.516940445@linutronix.de -Signed-off-by: Greg Kroah-Hartman ---- - arch/x86/kvm/vmx.c | 43 +++++++------------------------------------ - 1 file changed, 7 insertions(+), 36 deletions(-) - ---- a/arch/x86/kvm/vmx.c -+++ b/arch/x86/kvm/vmx.c -@@ -6039,16 +6039,6 @@ static void ept_set_mmio_spte_mask(void) - VMX_EPT_MISCONFIG_WX_VALUE); - } - --static bool vmx_l1d_use_msr_save_list(void) --{ -- if (!enable_ept || !boot_cpu_has_bug(X86_BUG_L1TF) || -- static_cpu_has(X86_FEATURE_HYPERVISOR) || -- !static_cpu_has(X86_FEATURE_FLUSH_L1D)) -- return false; -- -- return vmentry_l1d_flush == VMENTER_L1D_FLUSH_ALWAYS; --} -- - #define VMX_XSS_EXIT_BITMAP 0 - /* - * Sets up the vmcs for emulated real mode. -@@ -6164,12 +6154,6 @@ static void vmx_vcpu_setup(struct vcpu_v - vmcs_write64(PML_ADDRESS, page_to_phys(vmx->pml_pg)); - vmcs_write16(GUEST_PML_INDEX, PML_ENTITY_NUM - 1); - } -- /* -- * If flushing the L1D cache on every VMENTER is enforced and the -- * MSR is available, use the MSR save list. -- */ -- if (vmx_l1d_use_msr_save_list()) -- add_atomic_switch_msr(vmx, MSR_IA32_FLUSH_CMD, L1D_FLUSH, 0, true); - } - - static void vmx_vcpu_reset(struct kvm_vcpu *vcpu, bool init_event) -@@ -9387,26 +9371,14 @@ static void vmx_l1d_flush(struct kvm_vcp - bool always; - - /* -- * This code is only executed when: -- * - the flush mode is 'cond' -- * - the flush mode is 'always' and the flush MSR is not -- * available -- * -- * If the CPU has the flush MSR then clear the flush bit because -- * 'always' mode is handled via the MSR save list. -- * -- * If the MSR is not avaibable then act depending on the mitigation -- * mode: If 'flush always', keep the flush bit set, otherwise clear -- * it. -+ * This code is only executed when the the flush mode is 'cond' or -+ * 'always' - * -- * The flush bit gets set again either from vcpu_run() or from one -- * of the unsafe VMEXIT handlers. -+ * If 'flush always', keep the flush bit set, otherwise clear -+ * it. The flush bit gets set again either from vcpu_run() or from -+ * one of the unsafe VMEXIT handlers. - */ -- if (static_cpu_has(X86_FEATURE_FLUSH_L1D)) -- always = false; -- else -- always = vmentry_l1d_flush == VMENTER_L1D_FLUSH_ALWAYS; -- -+ always = vmentry_l1d_flush == VMENTER_L1D_FLUSH_ALWAYS; - vcpu->arch.l1tf_flush_l1d = always; - - vcpu->stat.l1d_flush++; -@@ -13053,8 +13025,7 @@ static int __init vmx_setup_l1d_flush(vo - - l1tf_vmx_mitigation = vmentry_l1d_flush; - -- if (vmentry_l1d_flush == VMENTER_L1D_FLUSH_NEVER || -- vmx_l1d_use_msr_save_list()) -+ if (vmentry_l1d_flush == VMENTER_L1D_FLUSH_NEVER) - return 0; - - if (!boot_cpu_has(X86_FEATURE_FLUSH_L1D)) { -From foo@baz Tue Aug 14 13:43:11 CEST 2018 -From: Thomas Gleixner -Date: Fri, 13 Jul 2018 16:23:18 +0200 -Subject: x86/l1tf: Handle EPT disabled state proper - -From: Thomas Gleixner - -commit a7b9020b06ec6d7c3f3b0d4ef1a9eba12654f4f7 upstream - -If Extended Page Tables (EPT) are disabled or not supported, no L1D -flushing is required. The setup function can just avoid setting up the L1D -flush for the EPT=n case. - -Invoke it after the hardware setup has be done and enable_ept has the -correct state and expose the EPT disabled state in the mitigation status as -well. - -Signed-off-by: Thomas Gleixner -Tested-by: Jiri Kosina -Reviewed-by: Greg Kroah-Hartman -Reviewed-by: Josh Poimboeuf -Link: https://lkml.kernel.org/r/20180713142322.612160168@linutronix.de -Signed-off-by: Greg Kroah-Hartman ---- - arch/x86/include/asm/vmx.h | 1 - arch/x86/kernel/cpu/bugs.c | 9 ++-- - arch/x86/kvm/vmx.c | 89 ++++++++++++++++++++++++--------------------- - 3 files changed, 54 insertions(+), 45 deletions(-) - ---- a/arch/x86/include/asm/vmx.h -+++ b/arch/x86/include/asm/vmx.h -@@ -579,6 +579,7 @@ enum vmx_l1d_flush_state { - VMENTER_L1D_FLUSH_NEVER, - VMENTER_L1D_FLUSH_COND, - VMENTER_L1D_FLUSH_ALWAYS, -+ VMENTER_L1D_FLUSH_EPT_DISABLED, - }; - - extern enum vmx_l1d_flush_state l1tf_vmx_mitigation; ---- a/arch/x86/kernel/cpu/bugs.c -+++ b/arch/x86/kernel/cpu/bugs.c -@@ -676,10 +676,11 @@ static void __init l1tf_select_mitigatio - - #if IS_ENABLED(CONFIG_KVM_INTEL) - static const char *l1tf_vmx_states[] = { -- [VMENTER_L1D_FLUSH_AUTO] = "auto", -- [VMENTER_L1D_FLUSH_NEVER] = "vulnerable", -- [VMENTER_L1D_FLUSH_COND] = "conditional cache flushes", -- [VMENTER_L1D_FLUSH_ALWAYS] = "cache flushes", -+ [VMENTER_L1D_FLUSH_AUTO] = "auto", -+ [VMENTER_L1D_FLUSH_NEVER] = "vulnerable", -+ [VMENTER_L1D_FLUSH_COND] = "conditional cache flushes", -+ [VMENTER_L1D_FLUSH_ALWAYS] = "cache flushes", -+ [VMENTER_L1D_FLUSH_EPT_DISABLED] = "EPT disabled", - }; - - static ssize_t l1tf_show_state(char *buf) ---- a/arch/x86/kvm/vmx.c -+++ b/arch/x86/kvm/vmx.c -@@ -13023,6 +13023,11 @@ static int __init vmx_setup_l1d_flush(vo - if (!boot_cpu_has_bug(X86_BUG_L1TF)) - return 0; - -+ if (!enable_ept) { -+ l1tf_vmx_mitigation = VMENTER_L1D_FLUSH_EPT_DISABLED; -+ return 0; -+ } -+ - l1tf_vmx_mitigation = vmentry_l1d_flush; - - if (vmentry_l1d_flush == VMENTER_L1D_FLUSH_NEVER) -@@ -13049,6 +13054,41 @@ static void vmx_cleanup_l1d_flush(void) - l1tf_vmx_mitigation = VMENTER_L1D_FLUSH_AUTO; - } - -+static void vmx_exit(void) -+{ -+#ifdef CONFIG_KEXEC_CORE -+ RCU_INIT_POINTER(crash_vmclear_loaded_vmcss, NULL); -+ synchronize_rcu(); -+#endif -+ -+ kvm_exit(); -+ -+#if IS_ENABLED(CONFIG_HYPERV) -+ if (static_branch_unlikely(&enable_evmcs)) { -+ int cpu; -+ struct hv_vp_assist_page *vp_ap; -+ /* -+ * Reset everything to support using non-enlightened VMCS -+ * access later (e.g. when we reload the module with -+ * enlightened_vmcs=0) -+ */ -+ for_each_online_cpu(cpu) { -+ vp_ap = hv_get_vp_assist_page(cpu); -+ -+ if (!vp_ap) -+ continue; -+ -+ vp_ap->current_nested_vmcs = 0; -+ vp_ap->enlighten_vmentry = 0; -+ } -+ -+ static_branch_disable(&enable_evmcs); -+ } -+#endif -+ vmx_cleanup_l1d_flush(); -+} -+module_exit(vmx_exit); -+ - static int __init vmx_init(void) - { - int r; -@@ -13082,14 +13122,17 @@ static int __init vmx_init(void) - } - #endif - -- r = vmx_setup_l1d_flush(); -+ r = kvm_init(&vmx_x86_ops, sizeof(struct vcpu_vmx), -+ __alignof__(struct vcpu_vmx), THIS_MODULE); - if (r) - return r; - -- r = kvm_init(&vmx_x86_ops, sizeof(struct vcpu_vmx), -- __alignof__(struct vcpu_vmx), THIS_MODULE); -+ /* -+ * Must be called after kvm_init() so enable_ept is properly set up -+ */ -+ r = vmx_setup_l1d_flush(); - if (r) { -- vmx_cleanup_l1d_flush(); -+ vmx_exit(); - return r; - } - -@@ -13100,40 +13143,4 @@ static int __init vmx_init(void) - - return 0; - } -- --static void __exit vmx_exit(void) --{ --#ifdef CONFIG_KEXEC_CORE -- RCU_INIT_POINTER(crash_vmclear_loaded_vmcss, NULL); -- synchronize_rcu(); --#endif -- -- kvm_exit(); -- --#if IS_ENABLED(CONFIG_HYPERV) -- if (static_branch_unlikely(&enable_evmcs)) { -- int cpu; -- struct hv_vp_assist_page *vp_ap; -- /* -- * Reset everything to support using non-enlightened VMCS -- * access later (e.g. when we reload the module with -- * enlightened_vmcs=0) -- */ -- for_each_online_cpu(cpu) { -- vp_ap = hv_get_vp_assist_page(cpu); -- -- if (!vp_ap) -- continue; -- -- vp_ap->current_nested_vmcs = 0; -- vp_ap->enlighten_vmentry = 0; -- } -- -- static_branch_disable(&enable_evmcs); -- } --#endif -- vmx_cleanup_l1d_flush(); --} -- --module_init(vmx_init) --module_exit(vmx_exit) -+module_init(vmx_init); -From foo@baz Tue Aug 14 13:43:11 CEST 2018 -From: Thomas Gleixner -Date: Fri, 13 Jul 2018 16:23:19 +0200 -Subject: x86/kvm: Move l1tf setup function - -From: Thomas Gleixner - -commit 7db92e165ac814487264632ab2624e832f20ae38 upstream - -In preparation of allowing run time control for L1D flushing, move the -setup code to the module parameter handler. - -In case of pre module init parsing, just store the value and let vmx_init() -do the actual setup after running kvm_init() so that enable_ept is having -the correct state. - -During run-time invoke it directly from the parameter setter to prepare for -run-time control. - -Signed-off-by: Thomas Gleixner -Tested-by: Jiri Kosina -Reviewed-by: Greg Kroah-Hartman -Reviewed-by: Josh Poimboeuf -Link: https://lkml.kernel.org/r/20180713142322.694063239@linutronix.de -Signed-off-by: Greg Kroah-Hartman ---- - arch/x86/kvm/vmx.c | 125 +++++++++++++++++++++++++++++++++-------------------- - 1 file changed, 78 insertions(+), 47 deletions(-) - ---- a/arch/x86/kvm/vmx.c -+++ b/arch/x86/kvm/vmx.c -@@ -193,7 +193,8 @@ extern const ulong vmx_return; - - static DEFINE_STATIC_KEY_FALSE(vmx_l1d_should_flush); - --static enum vmx_l1d_flush_state __read_mostly vmentry_l1d_flush = VMENTER_L1D_FLUSH_COND; -+/* Storage for pre module init parameter parsing */ -+static enum vmx_l1d_flush_state __read_mostly vmentry_l1d_flush_param = VMENTER_L1D_FLUSH_AUTO; - - static const struct { - const char *option; -@@ -205,33 +206,85 @@ static const struct { - {"always", VMENTER_L1D_FLUSH_ALWAYS}, - }; - --static int vmentry_l1d_flush_set(const char *s, const struct kernel_param *kp) -+#define L1D_CACHE_ORDER 4 -+static void *vmx_l1d_flush_pages; -+ -+static int vmx_setup_l1d_flush(enum vmx_l1d_flush_state l1tf) - { -- unsigned int i; -+ struct page *page; - -- if (!s) -- return -EINVAL; -+ /* If set to 'auto' select 'cond' */ -+ if (l1tf == VMENTER_L1D_FLUSH_AUTO) -+ l1tf = VMENTER_L1D_FLUSH_COND; - -- for (i = 0; i < ARRAY_SIZE(vmentry_l1d_param); i++) { -- if (!strcmp(s, vmentry_l1d_param[i].option)) { -- vmentry_l1d_flush = vmentry_l1d_param[i].cmd; -- return 0; -- } -+ if (!enable_ept) { -+ l1tf_vmx_mitigation = VMENTER_L1D_FLUSH_EPT_DISABLED; -+ return 0; - } - -+ if (l1tf != VMENTER_L1D_FLUSH_NEVER && !vmx_l1d_flush_pages && -+ !boot_cpu_has(X86_FEATURE_FLUSH_L1D)) { -+ page = alloc_pages(GFP_KERNEL, L1D_CACHE_ORDER); -+ if (!page) -+ return -ENOMEM; -+ vmx_l1d_flush_pages = page_address(page); -+ } -+ -+ l1tf_vmx_mitigation = l1tf; -+ -+ if (l1tf != VMENTER_L1D_FLUSH_NEVER) -+ static_branch_enable(&vmx_l1d_should_flush); -+ return 0; -+} -+ -+static int vmentry_l1d_flush_parse(const char *s) -+{ -+ unsigned int i; -+ -+ if (s) { -+ for (i = 0; i < ARRAY_SIZE(vmentry_l1d_param); i++) { -+ if (!strcmp(s, vmentry_l1d_param[i].option)) -+ return vmentry_l1d_param[i].cmd; -+ } -+ } - return -EINVAL; - } - -+static int vmentry_l1d_flush_set(const char *s, const struct kernel_param *kp) -+{ -+ int l1tf; -+ -+ if (!boot_cpu_has(X86_BUG_L1TF)) -+ return 0; -+ -+ l1tf = vmentry_l1d_flush_parse(s); -+ if (l1tf < 0) -+ return l1tf; -+ -+ /* -+ * Has vmx_init() run already? If not then this is the pre init -+ * parameter parsing. In that case just store the value and let -+ * vmx_init() do the proper setup after enable_ept has been -+ * established. -+ */ -+ if (l1tf_vmx_mitigation == VMENTER_L1D_FLUSH_AUTO) { -+ vmentry_l1d_flush_param = l1tf; -+ return 0; -+ } -+ -+ return vmx_setup_l1d_flush(l1tf); -+} -+ - static int vmentry_l1d_flush_get(char *s, const struct kernel_param *kp) - { -- return sprintf(s, "%s\n", vmentry_l1d_param[vmentry_l1d_flush].option); -+ return sprintf(s, "%s\n", vmentry_l1d_param[l1tf_vmx_mitigation].option); - } - - static const struct kernel_param_ops vmentry_l1d_flush_ops = { - .set = vmentry_l1d_flush_set, - .get = vmentry_l1d_flush_get, - }; --module_param_cb(vmentry_l1d_flush, &vmentry_l1d_flush_ops, &vmentry_l1d_flush, S_IRUGO); -+module_param_cb(vmentry_l1d_flush, &vmentry_l1d_flush_ops, NULL, S_IRUGO); - - struct kvm_vmx { - struct kvm kvm; -@@ -9378,7 +9431,7 @@ static void vmx_l1d_flush(struct kvm_vcp - * it. The flush bit gets set again either from vcpu_run() or from - * one of the unsafe VMEXIT handlers. - */ -- always = vmentry_l1d_flush == VMENTER_L1D_FLUSH_ALWAYS; -+ always = l1tf_vmx_mitigation == VMENTER_L1D_FLUSH_ALWAYS; - vcpu->arch.l1tf_flush_l1d = always; - - vcpu->stat.l1d_flush++; -@@ -13016,34 +13069,6 @@ static struct kvm_x86_ops vmx_x86_ops __ - .enable_smi_window = enable_smi_window, - }; - --static int __init vmx_setup_l1d_flush(void) --{ -- struct page *page; -- -- if (!boot_cpu_has_bug(X86_BUG_L1TF)) -- return 0; -- -- if (!enable_ept) { -- l1tf_vmx_mitigation = VMENTER_L1D_FLUSH_EPT_DISABLED; -- return 0; -- } -- -- l1tf_vmx_mitigation = vmentry_l1d_flush; -- -- if (vmentry_l1d_flush == VMENTER_L1D_FLUSH_NEVER) -- return 0; -- -- if (!boot_cpu_has(X86_FEATURE_FLUSH_L1D)) { -- page = alloc_pages(GFP_KERNEL, L1D_CACHE_ORDER); -- if (!page) -- return -ENOMEM; -- vmx_l1d_flush_pages = page_address(page); -- } -- -- static_branch_enable(&vmx_l1d_should_flush); -- return 0; --} -- - static void vmx_cleanup_l1d_flush(void) - { - if (vmx_l1d_flush_pages) { -@@ -13128,12 +13153,18 @@ static int __init vmx_init(void) - return r; - - /* -- * Must be called after kvm_init() so enable_ept is properly set up -- */ -- r = vmx_setup_l1d_flush(); -- if (r) { -- vmx_exit(); -- return r; -+ * Must be called after kvm_init() so enable_ept is properly set -+ * up. Hand the parameter mitigation value in which was stored in -+ * the pre module init parser. If no parameter was given, it will -+ * contain 'auto' which will be turned into the default 'cond' -+ * mitigation mode. -+ */ -+ if (boot_cpu_has(X86_BUG_L1TF)) { -+ r = vmx_setup_l1d_flush(vmentry_l1d_flush_param); -+ if (r) { -+ vmx_exit(); -+ return r; -+ } - } - - #ifdef CONFIG_KEXEC_CORE -From foo@baz Tue Aug 14 13:43:11 CEST 2018 -From: Thomas Gleixner -Date: Fri, 13 Jul 2018 16:23:20 +0200 -Subject: x86/kvm: Add static key for flush always - -From: Thomas Gleixner - -commit 4c6523ec59fe895ea352a650218a6be0653910b1 upstream - -Avoid the conditional in the L1D flush control path. - -Signed-off-by: Thomas Gleixner -Tested-by: Jiri Kosina -Reviewed-by: Greg Kroah-Hartman -Reviewed-by: Josh Poimboeuf -Link: https://lkml.kernel.org/r/20180713142322.790914912@linutronix.de -Signed-off-by: Greg Kroah-Hartman ---- - arch/x86/kvm/vmx.c | 16 +++++++++++----- - 1 file changed, 11 insertions(+), 5 deletions(-) - ---- a/arch/x86/kvm/vmx.c -+++ b/arch/x86/kvm/vmx.c -@@ -192,6 +192,7 @@ module_param(ple_window_max, uint, 0444) - extern const ulong vmx_return; - - static DEFINE_STATIC_KEY_FALSE(vmx_l1d_should_flush); -+static DEFINE_STATIC_KEY_FALSE(vmx_l1d_flush_always); - - /* Storage for pre module init parameter parsing */ - static enum vmx_l1d_flush_state __read_mostly vmentry_l1d_flush_param = VMENTER_L1D_FLUSH_AUTO; -@@ -232,8 +233,12 @@ static int vmx_setup_l1d_flush(enum vmx_ - - l1tf_vmx_mitigation = l1tf; - -- if (l1tf != VMENTER_L1D_FLUSH_NEVER) -- static_branch_enable(&vmx_l1d_should_flush); -+ if (l1tf == VMENTER_L1D_FLUSH_NEVER) -+ return 0; -+ -+ static_branch_enable(&vmx_l1d_should_flush); -+ if (l1tf == VMENTER_L1D_FLUSH_ALWAYS) -+ static_branch_enable(&vmx_l1d_flush_always); - return 0; - } - -@@ -9421,7 +9426,6 @@ static void *vmx_l1d_flush_pages; - static void vmx_l1d_flush(struct kvm_vcpu *vcpu) - { - int size = PAGE_SIZE << L1D_CACHE_ORDER; -- bool always; - - /* - * This code is only executed when the the flush mode is 'cond' or -@@ -9431,8 +9435,10 @@ static void vmx_l1d_flush(struct kvm_vcp - * it. The flush bit gets set again either from vcpu_run() or from - * one of the unsafe VMEXIT handlers. - */ -- always = l1tf_vmx_mitigation == VMENTER_L1D_FLUSH_ALWAYS; -- vcpu->arch.l1tf_flush_l1d = always; -+ if (static_branch_unlikely(&vmx_l1d_flush_always)) -+ vcpu->arch.l1tf_flush_l1d = true; -+ else -+ vcpu->arch.l1tf_flush_l1d = false; - - vcpu->stat.l1d_flush++; - -From foo@baz Tue Aug 14 13:43:11 CEST 2018 -From: Thomas Gleixner -Date: Fri, 13 Jul 2018 16:23:21 +0200 -Subject: x86/kvm: Serialize L1D flush parameter setter - -From: Thomas Gleixner - -commit dd4bfa739a72508b75760b393d129ed7b431daab upstream - -Writes to the parameter files are not serialized at the sysfs core -level, so local serialization is required. - -Signed-off-by: Thomas Gleixner -Tested-by: Jiri Kosina -Reviewed-by: Greg Kroah-Hartman -Reviewed-by: Josh Poimboeuf -Link: https://lkml.kernel.org/r/20180713142322.873642605@linutronix.de -Signed-off-by: Greg Kroah-Hartman ---- - arch/x86/kvm/vmx.c | 8 ++++++-- - 1 file changed, 6 insertions(+), 2 deletions(-) - ---- a/arch/x86/kvm/vmx.c -+++ b/arch/x86/kvm/vmx.c -@@ -193,6 +193,7 @@ extern const ulong vmx_return; - - static DEFINE_STATIC_KEY_FALSE(vmx_l1d_should_flush); - static DEFINE_STATIC_KEY_FALSE(vmx_l1d_flush_always); -+static DEFINE_MUTEX(vmx_l1d_flush_mutex); - - /* Storage for pre module init parameter parsing */ - static enum vmx_l1d_flush_state __read_mostly vmentry_l1d_flush_param = VMENTER_L1D_FLUSH_AUTO; -@@ -257,7 +258,7 @@ static int vmentry_l1d_flush_parse(const - - static int vmentry_l1d_flush_set(const char *s, const struct kernel_param *kp) - { -- int l1tf; -+ int l1tf, ret; - - if (!boot_cpu_has(X86_BUG_L1TF)) - return 0; -@@ -277,7 +278,10 @@ static int vmentry_l1d_flush_set(const c - return 0; - } - -- return vmx_setup_l1d_flush(l1tf); -+ mutex_lock(&vmx_l1d_flush_mutex); -+ ret = vmx_setup_l1d_flush(l1tf); -+ mutex_unlock(&vmx_l1d_flush_mutex); -+ return ret; - } - - static int vmentry_l1d_flush_get(char *s, const struct kernel_param *kp) -From foo@baz Tue Aug 14 13:43:11 CEST 2018 -From: Thomas Gleixner -Date: Fri, 13 Jul 2018 16:23:22 +0200 -Subject: x86/kvm: Allow runtime control of L1D flush - -From: Thomas Gleixner - -commit 895ae47f9918833c3a880fbccd41e0692b37e7d9 upstream - -All mitigation modes can be switched at run time with a static key now: - - - Use sysfs_streq() instead of strcmp() to handle the trailing new line - from sysfs writes correctly. - - Make the static key management handle multiple invocations properly. - - Set the module parameter file to RW - -Signed-off-by: Thomas Gleixner -Tested-by: Jiri Kosina -Reviewed-by: Greg Kroah-Hartman -Reviewed-by: Josh Poimboeuf -Link: https://lkml.kernel.org/r/20180713142322.954525119@linutronix.de -Signed-off-by: Greg Kroah-Hartman ---- - arch/x86/kernel/cpu/bugs.c | 2 +- - arch/x86/kvm/vmx.c | 13 ++++++++----- - 2 files changed, 9 insertions(+), 6 deletions(-) - ---- a/arch/x86/kernel/cpu/bugs.c -+++ b/arch/x86/kernel/cpu/bugs.c -@@ -639,7 +639,7 @@ void x86_spec_ctrl_setup_ap(void) - #define pr_fmt(fmt) "L1TF: " fmt - - #if IS_ENABLED(CONFIG_KVM_INTEL) --enum vmx_l1d_flush_state l1tf_vmx_mitigation __ro_after_init = VMENTER_L1D_FLUSH_AUTO; -+enum vmx_l1d_flush_state l1tf_vmx_mitigation = VMENTER_L1D_FLUSH_AUTO; - EXPORT_SYMBOL_GPL(l1tf_vmx_mitigation); - #endif - ---- a/arch/x86/kvm/vmx.c -+++ b/arch/x86/kvm/vmx.c -@@ -234,12 +234,15 @@ static int vmx_setup_l1d_flush(enum vmx_ - - l1tf_vmx_mitigation = l1tf; - -- if (l1tf == VMENTER_L1D_FLUSH_NEVER) -- return 0; -+ if (l1tf != VMENTER_L1D_FLUSH_NEVER) -+ static_branch_enable(&vmx_l1d_should_flush); -+ else -+ static_branch_disable(&vmx_l1d_should_flush); - -- static_branch_enable(&vmx_l1d_should_flush); - if (l1tf == VMENTER_L1D_FLUSH_ALWAYS) - static_branch_enable(&vmx_l1d_flush_always); -+ else -+ static_branch_disable(&vmx_l1d_flush_always); - return 0; - } - -@@ -249,7 +252,7 @@ static int vmentry_l1d_flush_parse(const - - if (s) { - for (i = 0; i < ARRAY_SIZE(vmentry_l1d_param); i++) { -- if (!strcmp(s, vmentry_l1d_param[i].option)) -+ if (sysfs_streq(s, vmentry_l1d_param[i].option)) - return vmentry_l1d_param[i].cmd; - } - } -@@ -293,7 +296,7 @@ static const struct kernel_param_ops vme - .set = vmentry_l1d_flush_set, - .get = vmentry_l1d_flush_get, - }; --module_param_cb(vmentry_l1d_flush, &vmentry_l1d_flush_ops, NULL, S_IRUGO); -+module_param_cb(vmentry_l1d_flush, &vmentry_l1d_flush_ops, NULL, 0644); - - struct kvm_vmx { - struct kvm kvm; -From foo@baz Tue Aug 14 13:43:11 CEST 2018 -From: Jiri Kosina -Date: Fri, 13 Jul 2018 16:23:23 +0200 -Subject: cpu/hotplug: Expose SMT control init function - -From: Jiri Kosina - -commit 8e1b706b6e819bed215c0db16345568864660393 upstream - -The L1TF mitigation will gain a commend line parameter which allows to set -a combination of hypervisor mitigation and SMT control. - -Expose cpu_smt_disable() so the command line parser can tweak SMT settings. - -[ tglx: Split out of larger patch and made it preserve an already existing - force off state ] - -Signed-off-by: Jiri Kosina -Signed-off-by: Thomas Gleixner -Tested-by: Jiri Kosina -Reviewed-by: Greg Kroah-Hartman -Reviewed-by: Josh Poimboeuf -Link: https://lkml.kernel.org/r/20180713142323.039715135@linutronix.de -Signed-off-by: Greg Kroah-Hartman ---- - include/linux/cpu.h | 2 ++ - kernel/cpu.c | 16 +++++++++++++--- - 2 files changed, 15 insertions(+), 3 deletions(-) - ---- a/include/linux/cpu.h -+++ b/include/linux/cpu.h -@@ -177,8 +177,10 @@ enum cpuhp_smt_control { - - #if defined(CONFIG_SMP) && defined(CONFIG_HOTPLUG_SMT) - extern enum cpuhp_smt_control cpu_smt_control; -+extern void cpu_smt_disable(bool force); - #else - # define cpu_smt_control (CPU_SMT_ENABLED) -+static inline void cpu_smt_disable(bool force) { } - #endif - - #endif /* _LINUX_CPU_H_ */ ---- a/kernel/cpu.c -+++ b/kernel/cpu.c -@@ -347,13 +347,23 @@ EXPORT_SYMBOL_GPL(cpu_hotplug_enable); - enum cpuhp_smt_control cpu_smt_control __read_mostly = CPU_SMT_ENABLED; - EXPORT_SYMBOL_GPL(cpu_smt_control); - --static int __init smt_cmdline_disable(char *str) -+void __init cpu_smt_disable(bool force) - { -- cpu_smt_control = CPU_SMT_DISABLED; -- if (str && !strcmp(str, "force")) { -+ if (cpu_smt_control == CPU_SMT_FORCE_DISABLED || -+ cpu_smt_control == CPU_SMT_NOT_SUPPORTED) -+ return; -+ -+ if (force) { - pr_info("SMT: Force disabled\n"); - cpu_smt_control = CPU_SMT_FORCE_DISABLED; -+ } else { -+ cpu_smt_control = CPU_SMT_DISABLED; - } -+} -+ -+static int __init smt_cmdline_disable(char *str) -+{ -+ cpu_smt_disable(str && !strcmp(str, "force")); - return 0; - } - early_param("nosmt", smt_cmdline_disable); -From foo@baz Tue Aug 14 13:43:11 CEST 2018 -From: Thomas Gleixner -Date: Fri, 13 Jul 2018 16:23:24 +0200 -Subject: cpu/hotplug: Set CPU_SMT_NOT_SUPPORTED early - -From: Thomas Gleixner - -commit fee0aede6f4739c87179eca76136f83210953b86 upstream - -The CPU_SMT_NOT_SUPPORTED state is set (if the processor does not support -SMT) when the sysfs SMT control file is initialized. - -That was fine so far as this was only required to make the output of the -control file correct and to prevent writes in that case. - -With the upcoming l1tf command line parameter, this needs to be set up -before the L1TF mitigation selection and command line parsing happens. - -Signed-off-by: Thomas Gleixner -Tested-by: Jiri Kosina -Reviewed-by: Greg Kroah-Hartman -Reviewed-by: Josh Poimboeuf -Link: https://lkml.kernel.org/r/20180713142323.121795971@linutronix.de -Signed-off-by: Greg Kroah-Hartman ---- - arch/x86/kernel/cpu/bugs.c | 6 ++++++ - include/linux/cpu.h | 2 ++ - kernel/cpu.c | 13 ++++++++++--- - 3 files changed, 18 insertions(+), 3 deletions(-) - ---- a/arch/x86/kernel/cpu/bugs.c -+++ b/arch/x86/kernel/cpu/bugs.c -@@ -58,6 +58,12 @@ void __init check_bugs(void) - { - identify_boot_cpu(); - -+ /* -+ * identify_boot_cpu() initialized SMT support information, let the -+ * core code know. -+ */ -+ cpu_smt_check_topology(); -+ - if (!IS_ENABLED(CONFIG_SMP)) { - pr_info("CPU: "); - print_cpu_info(&boot_cpu_data); ---- a/include/linux/cpu.h -+++ b/include/linux/cpu.h -@@ -178,9 +178,11 @@ enum cpuhp_smt_control { - #if defined(CONFIG_SMP) && defined(CONFIG_HOTPLUG_SMT) - extern enum cpuhp_smt_control cpu_smt_control; - extern void cpu_smt_disable(bool force); -+extern void cpu_smt_check_topology(void); - #else - # define cpu_smt_control (CPU_SMT_ENABLED) - static inline void cpu_smt_disable(bool force) { } -+static inline void cpu_smt_check_topology(void) { } - #endif - - #endif /* _LINUX_CPU_H_ */ ---- a/kernel/cpu.c -+++ b/kernel/cpu.c -@@ -361,6 +361,16 @@ void __init cpu_smt_disable(bool force) - } - } - -+/* -+ * The decision whether SMT is supported can only be done after the full -+ * CPU identification. Called from architecture code. -+ */ -+void __init cpu_smt_check_topology(void) -+{ -+ if (!topology_smt_supported()) -+ cpu_smt_control = CPU_SMT_NOT_SUPPORTED; -+} -+ - static int __init smt_cmdline_disable(char *str) - { - cpu_smt_disable(str && !strcmp(str, "force")); -@@ -2115,9 +2125,6 @@ static const struct attribute_group cpuh - - static int __init cpu_smt_state_init(void) - { -- if (!topology_smt_supported()) -- cpu_smt_control = CPU_SMT_NOT_SUPPORTED; -- - return sysfs_create_group(&cpu_subsys.dev_root->kobj, - &cpuhp_smt_attr_group); - } -From foo@baz Tue Aug 14 13:43:11 CEST 2018 -From: Jiri Kosina -Date: Fri, 13 Jul 2018 16:23:25 +0200 -Subject: x86/bugs, kvm: Introduce boot-time control of L1TF mitigations - -From: Jiri Kosina - -commit d90a7a0ec83fb86622cd7dae23255d3c50a99ec8 upstream - -Introduce the 'l1tf=' kernel command line option to allow for boot-time -switching of mitigation that is used on processors affected by L1TF. - -The possible values are: - - full - Provides all available mitigations for the L1TF vulnerability. Disables - SMT and enables all mitigations in the hypervisors. SMT control via - /sys/devices/system/cpu/smt/control is still possible after boot. - Hypervisors will issue a warning when the first VM is started in - a potentially insecure configuration, i.e. SMT enabled or L1D flush - disabled. - - full,force - Same as 'full', but disables SMT control. Implies the 'nosmt=force' - command line option. sysfs control of SMT and the hypervisor flush - control is disabled. - - flush - Leaves SMT enabled and enables the conditional hypervisor mitigation. - Hypervisors will issue a warning when the first VM is started in a - potentially insecure configuration, i.e. SMT enabled or L1D flush - disabled. - - flush,nosmt - Disables SMT and enables the conditional hypervisor mitigation. SMT - control via /sys/devices/system/cpu/smt/control is still possible - after boot. If SMT is reenabled or flushing disabled at runtime - hypervisors will issue a warning. - - flush,nowarn - Same as 'flush', but hypervisors will not warn when - a VM is started in a potentially insecure configuration. - - off - Disables hypervisor mitigations and doesn't emit any warnings. - -Default is 'flush'. - -Let KVM adhere to these semantics, which means: - - - 'lt1f=full,force' : Performe L1D flushes. No runtime control - possible. - - - 'l1tf=full' - - 'l1tf-flush' - - 'l1tf=flush,nosmt' : Perform L1D flushes and warn on VM start if - SMT has been runtime enabled or L1D flushing - has been run-time enabled - - - 'l1tf=flush,nowarn' : Perform L1D flushes and no warnings are emitted. - - - 'l1tf=off' : L1D flushes are not performed and no warnings - are emitted. - -KVM can always override the L1D flushing behavior using its 'vmentry_l1d_flush' -module parameter except when lt1f=full,force is set. - -This makes KVM's private 'nosmt' option redundant, and as it is a bit -non-systematic anyway (this is something to control globally, not on -hypervisor level), remove that option. - -Add the missing Documentation entry for the l1tf vulnerability sysfs file -while at it. - -Signed-off-by: Jiri Kosina -Signed-off-by: Thomas Gleixner -Tested-by: Jiri Kosina -Reviewed-by: Greg Kroah-Hartman -Reviewed-by: Josh Poimboeuf -Link: https://lkml.kernel.org/r/20180713142323.202758176@linutronix.de -Signed-off-by: Greg Kroah-Hartman ---- - Documentation/ABI/testing/sysfs-devices-system-cpu | 4 + - Documentation/admin-guide/kernel-parameters.txt | 68 +++++++++++++++++++-- - arch/x86/include/asm/processor.h | 12 +++ - arch/x86/kernel/cpu/bugs.c | 44 +++++++++++++ - arch/x86/kvm/vmx.c | 56 +++++++++++++---- - 5 files changed, 165 insertions(+), 19 deletions(-) - ---- a/Documentation/ABI/testing/sysfs-devices-system-cpu -+++ b/Documentation/ABI/testing/sysfs-devices-system-cpu -@@ -479,6 +479,7 @@ What: /sys/devices/system/cpu/vulnerabi - /sys/devices/system/cpu/vulnerabilities/spectre_v1 - /sys/devices/system/cpu/vulnerabilities/spectre_v2 - /sys/devices/system/cpu/vulnerabilities/spec_store_bypass -+ /sys/devices/system/cpu/vulnerabilities/l1tf - Date: January 2018 - Contact: Linux kernel mailing list - Description: Information about CPU vulnerabilities -@@ -491,6 +492,9 @@ Description: Information about CPU vulne - "Vulnerable" CPU is affected and no mitigation in effect - "Mitigation: $M" CPU is affected and mitigation $M is in effect - -+ Details about the l1tf file can be found in -+ Documentation/admin-guide/l1tf.rst -+ - What: /sys/devices/system/cpu/smt - /sys/devices/system/cpu/smt/active - /sys/devices/system/cpu/smt/control ---- a/Documentation/admin-guide/kernel-parameters.txt -+++ b/Documentation/admin-guide/kernel-parameters.txt -@@ -1937,12 +1937,6 @@ - [KVM,ARM] Allow use of GICv4 for direct injection of - LPIs. - -- kvm-intel.nosmt=[KVM,Intel] If the L1TF CPU bug is present (CVE-2018-3620) -- and the system has SMT (aka Hyper-Threading) enabled then -- don't allow guests to be created. -- -- Default is 0 (allow guests to be created). -- - kvm-intel.ept= [KVM,Intel] Disable extended page tables - (virtualized MMU) support on capable Intel chips. - Default is 1 (enabled) -@@ -1980,6 +1974,68 @@ - feature (tagged TLBs) on capable Intel chips. - Default is 1 (enabled) - -+ l1tf= [X86] Control mitigation of the L1TF vulnerability on -+ affected CPUs -+ -+ The kernel PTE inversion protection is unconditionally -+ enabled and cannot be disabled. -+ -+ full -+ Provides all available mitigations for the -+ L1TF vulnerability. Disables SMT and -+ enables all mitigations in the -+ hypervisors, i.e. unconditional L1D flush. -+ -+ SMT control and L1D flush control via the -+ sysfs interface is still possible after -+ boot. Hypervisors will issue a warning -+ when the first VM is started in a -+ potentially insecure configuration, -+ i.e. SMT enabled or L1D flush disabled. -+ -+ full,force -+ Same as 'full', but disables SMT and L1D -+ flush runtime control. Implies the -+ 'nosmt=force' command line option. -+ (i.e. sysfs control of SMT is disabled.) -+ -+ flush -+ Leaves SMT enabled and enables the default -+ hypervisor mitigation, i.e. conditional -+ L1D flush. -+ -+ SMT control and L1D flush control via the -+ sysfs interface is still possible after -+ boot. Hypervisors will issue a warning -+ when the first VM is started in a -+ potentially insecure configuration, -+ i.e. SMT enabled or L1D flush disabled. -+ -+ flush,nosmt -+ -+ Disables SMT and enables the default -+ hypervisor mitigation. -+ -+ SMT control and L1D flush control via the -+ sysfs interface is still possible after -+ boot. Hypervisors will issue a warning -+ when the first VM is started in a -+ potentially insecure configuration, -+ i.e. SMT enabled or L1D flush disabled. -+ -+ flush,nowarn -+ Same as 'flush', but hypervisors will not -+ warn when a VM is started in a potentially -+ insecure configuration. -+ -+ off -+ Disables hypervisor mitigations and doesn't -+ emit any warnings. -+ -+ Default is 'flush'. -+ -+ For details see: Documentation/admin-guide/l1tf.rst -+ - l2cr= [PPC] - - l3cr= [PPC] ---- a/arch/x86/include/asm/processor.h -+++ b/arch/x86/include/asm/processor.h -@@ -991,4 +991,16 @@ bool xen_set_default_idle(void); - void stop_this_cpu(void *dummy); - void df_debug(struct pt_regs *regs, long error_code); - void microcode_check(void); -+ -+enum l1tf_mitigations { -+ L1TF_MITIGATION_OFF, -+ L1TF_MITIGATION_FLUSH_NOWARN, -+ L1TF_MITIGATION_FLUSH, -+ L1TF_MITIGATION_FLUSH_NOSMT, -+ L1TF_MITIGATION_FULL, -+ L1TF_MITIGATION_FULL_FORCE -+}; -+ -+extern enum l1tf_mitigations l1tf_mitigation; -+ - #endif /* _ASM_X86_PROCESSOR_H */ ---- a/arch/x86/kernel/cpu/bugs.c -+++ b/arch/x86/kernel/cpu/bugs.c -@@ -644,7 +644,11 @@ void x86_spec_ctrl_setup_ap(void) - #undef pr_fmt - #define pr_fmt(fmt) "L1TF: " fmt - -+/* Default mitigation for L1TF-affected CPUs */ -+enum l1tf_mitigations l1tf_mitigation __ro_after_init = L1TF_MITIGATION_FLUSH; - #if IS_ENABLED(CONFIG_KVM_INTEL) -+EXPORT_SYMBOL_GPL(l1tf_mitigation); -+ - enum vmx_l1d_flush_state l1tf_vmx_mitigation = VMENTER_L1D_FLUSH_AUTO; - EXPORT_SYMBOL_GPL(l1tf_vmx_mitigation); - #endif -@@ -656,6 +660,20 @@ static void __init l1tf_select_mitigatio - if (!boot_cpu_has_bug(X86_BUG_L1TF)) - return; - -+ switch (l1tf_mitigation) { -+ case L1TF_MITIGATION_OFF: -+ case L1TF_MITIGATION_FLUSH_NOWARN: -+ case L1TF_MITIGATION_FLUSH: -+ break; -+ case L1TF_MITIGATION_FLUSH_NOSMT: -+ case L1TF_MITIGATION_FULL: -+ cpu_smt_disable(false); -+ break; -+ case L1TF_MITIGATION_FULL_FORCE: -+ cpu_smt_disable(true); -+ break; -+ } -+ - #if CONFIG_PGTABLE_LEVELS == 2 - pr_warn("Kernel not compiled for PAE. No mitigation for L1TF\n"); - return; -@@ -674,6 +692,32 @@ static void __init l1tf_select_mitigatio - - setup_force_cpu_cap(X86_FEATURE_L1TF_PTEINV); - } -+ -+static int __init l1tf_cmdline(char *str) -+{ -+ if (!boot_cpu_has_bug(X86_BUG_L1TF)) -+ return 0; -+ -+ if (!str) -+ return -EINVAL; -+ -+ if (!strcmp(str, "off")) -+ l1tf_mitigation = L1TF_MITIGATION_OFF; -+ else if (!strcmp(str, "flush,nowarn")) -+ l1tf_mitigation = L1TF_MITIGATION_FLUSH_NOWARN; -+ else if (!strcmp(str, "flush")) -+ l1tf_mitigation = L1TF_MITIGATION_FLUSH; -+ else if (!strcmp(str, "flush,nosmt")) -+ l1tf_mitigation = L1TF_MITIGATION_FLUSH_NOSMT; -+ else if (!strcmp(str, "full")) -+ l1tf_mitigation = L1TF_MITIGATION_FULL; -+ else if (!strcmp(str, "full,force")) -+ l1tf_mitigation = L1TF_MITIGATION_FULL_FORCE; -+ -+ return 0; -+} -+early_param("l1tf", l1tf_cmdline); -+ - #undef pr_fmt - - #ifdef CONFIG_SYSFS ---- a/arch/x86/kvm/vmx.c -+++ b/arch/x86/kvm/vmx.c -@@ -71,9 +71,6 @@ static const struct x86_cpu_id vmx_cpu_i - }; - MODULE_DEVICE_TABLE(x86cpu, vmx_cpu_id); - --static bool __read_mostly nosmt; --module_param(nosmt, bool, S_IRUGO); -- - static bool __read_mostly enable_vpid = 1; - module_param_named(vpid, enable_vpid, bool, 0444); - -@@ -215,15 +212,31 @@ static int vmx_setup_l1d_flush(enum vmx_ - { - struct page *page; - -- /* If set to 'auto' select 'cond' */ -- if (l1tf == VMENTER_L1D_FLUSH_AUTO) -- l1tf = VMENTER_L1D_FLUSH_COND; -- - if (!enable_ept) { - l1tf_vmx_mitigation = VMENTER_L1D_FLUSH_EPT_DISABLED; - return 0; - } - -+ /* If set to auto use the default l1tf mitigation method */ -+ if (l1tf == VMENTER_L1D_FLUSH_AUTO) { -+ switch (l1tf_mitigation) { -+ case L1TF_MITIGATION_OFF: -+ l1tf = VMENTER_L1D_FLUSH_NEVER; -+ break; -+ case L1TF_MITIGATION_FLUSH_NOWARN: -+ case L1TF_MITIGATION_FLUSH: -+ case L1TF_MITIGATION_FLUSH_NOSMT: -+ l1tf = VMENTER_L1D_FLUSH_COND; -+ break; -+ case L1TF_MITIGATION_FULL: -+ case L1TF_MITIGATION_FULL_FORCE: -+ l1tf = VMENTER_L1D_FLUSH_ALWAYS; -+ break; -+ } -+ } else if (l1tf_mitigation == L1TF_MITIGATION_FULL_FORCE) { -+ l1tf = VMENTER_L1D_FLUSH_ALWAYS; -+ } -+ - if (l1tf != VMENTER_L1D_FLUSH_NEVER && !vmx_l1d_flush_pages && - !boot_cpu_has(X86_FEATURE_FLUSH_L1D)) { - page = alloc_pages(GFP_KERNEL, L1D_CACHE_ORDER); -@@ -10343,19 +10356,36 @@ free_vcpu: - return ERR_PTR(err); - } - --#define L1TF_MSG "SMT enabled with L1TF CPU bug present. Refer to CVE-2018-3620 for details.\n" -+#define L1TF_MSG_SMT "L1TF CPU bug present and SMT on, data leak possible. See CVE-2018-3646 and https://www.kernel.org/doc/html/latest/admin-guide/l1tf.html for details.\n" -+#define L1TF_MSG_L1D "L1TF CPU bug present and virtualization mitigation disabled, data leak possible. See CVE-2018-3646 and https://www.kernel.org/doc/html/latest/admin-guide/l1tf.html for details.\n" - - static int vmx_vm_init(struct kvm *kvm) - { - if (!ple_gap) - kvm->arch.pause_in_guest = true; - -- if (boot_cpu_has(X86_BUG_L1TF) && cpu_smt_control == CPU_SMT_ENABLED) { -- if (nosmt) { -- pr_err(L1TF_MSG); -- return -EOPNOTSUPP; -+ if (boot_cpu_has(X86_BUG_L1TF) && enable_ept) { -+ switch (l1tf_mitigation) { -+ case L1TF_MITIGATION_OFF: -+ case L1TF_MITIGATION_FLUSH_NOWARN: -+ /* 'I explicitly don't care' is set */ -+ break; -+ case L1TF_MITIGATION_FLUSH: -+ case L1TF_MITIGATION_FLUSH_NOSMT: -+ case L1TF_MITIGATION_FULL: -+ /* -+ * Warn upon starting the first VM in a potentially -+ * insecure environment. -+ */ -+ if (cpu_smt_control == CPU_SMT_ENABLED) -+ pr_warn_once(L1TF_MSG_SMT); -+ if (l1tf_vmx_mitigation == VMENTER_L1D_FLUSH_NEVER) -+ pr_warn_once(L1TF_MSG_L1D); -+ break; -+ case L1TF_MITIGATION_FULL_FORCE: -+ /* Flush is enforced */ -+ break; - } -- pr_warn(L1TF_MSG); - } - return 0; - } -From foo@baz Tue Aug 14 13:43:11 CEST 2018 -From: Thomas Gleixner -Date: Fri, 13 Jul 2018 16:23:26 +0200 -Subject: Documentation: Add section about CPU vulnerabilities - -From: Thomas Gleixner - -commit 3ec8ce5d866ec6a08a9cfab82b62acf4a830b35f upstream - -Add documentation for the L1TF vulnerability and the mitigation mechanisms: - - - Explain the problem and risks - - Document the mitigation mechanisms - - Document the command line controls - - Document the sysfs files - -Signed-off-by: Thomas Gleixner -Reviewed-by: Greg Kroah-Hartman -Reviewed-by: Josh Poimboeuf -Acked-by: Linus Torvalds -Link: https://lkml.kernel.org/r/20180713142323.287429944@linutronix.de -Signed-off-by: Greg Kroah-Hartman ---- - Documentation/admin-guide/index.rst | 9 - Documentation/admin-guide/l1tf.rst | 591 ++++++++++++++++++++++++++++++++++++ - 2 files changed, 600 insertions(+) - create mode 100644 Documentation/admin-guide/l1tf.rst - ---- a/Documentation/admin-guide/index.rst -+++ b/Documentation/admin-guide/index.rst -@@ -17,6 +17,15 @@ etc. - kernel-parameters - devices - -+This section describes CPU vulnerabilities and provides an overview of the -+possible mitigations along with guidance for selecting mitigations if they -+are configurable at compile, boot or run time. -+ -+.. toctree:: -+ :maxdepth: 1 -+ -+ l1tf -+ - Here is a set of documents aimed at users who are trying to track down - problems and bugs in particular. - ---- /dev/null -+++ b/Documentation/admin-guide/l1tf.rst -@@ -0,0 +1,591 @@ -+L1TF - L1 Terminal Fault -+======================== -+ -+L1 Terminal Fault is a hardware vulnerability which allows unprivileged -+speculative access to data which is available in the Level 1 Data Cache -+when the page table entry controlling the virtual address, which is used -+for the access, has the Present bit cleared or other reserved bits set. -+ -+Affected processors -+------------------- -+ -+This vulnerability affects a wide range of Intel processors. The -+vulnerability is not present on: -+ -+ - Processors from AMD, Centaur and other non Intel vendors -+ -+ - Older processor models, where the CPU family is < 6 -+ -+ - A range of Intel ATOM processors (Cedarview, Cloverview, Lincroft, -+ Penwell, Pineview, Slivermont, Airmont, Merrifield) -+ -+ - The Intel Core Duo Yonah variants (2006 - 2008) -+ -+ - The Intel XEON PHI family -+ -+ - Intel processors which have the ARCH_CAP_RDCL_NO bit set in the -+ IA32_ARCH_CAPABILITIES MSR. If the bit is set the CPU is not affected -+ by the Meltdown vulnerability either. These CPUs should become -+ available by end of 2018. -+ -+Whether a processor is affected or not can be read out from the L1TF -+vulnerability file in sysfs. See :ref:`l1tf_sys_info`. -+ -+Related CVEs -+------------ -+ -+The following CVE entries are related to the L1TF vulnerability: -+ -+ ============= ================= ============================== -+ CVE-2018-3615 L1 Terminal Fault SGX related aspects -+ CVE-2018-3620 L1 Terminal Fault OS, SMM related aspects -+ CVE-2018-3646 L1 Terminal Fault Virtualization related aspects -+ ============= ================= ============================== -+ -+Problem -+------- -+ -+If an instruction accesses a virtual address for which the relevant page -+table entry (PTE) has the Present bit cleared or other reserved bits set, -+then speculative execution ignores the invalid PTE and loads the referenced -+data if it is present in the Level 1 Data Cache, as if the page referenced -+by the address bits in the PTE was still present and accessible. -+ -+While this is a purely speculative mechanism and the instruction will raise -+a page fault when it is retired eventually, the pure act of loading the -+data and making it available to other speculative instructions opens up the -+opportunity for side channel attacks to unprivileged malicious code, -+similar to the Meltdown attack. -+ -+While Meltdown breaks the user space to kernel space protection, L1TF -+allows to attack any physical memory address in the system and the attack -+works across all protection domains. It allows an attack of SGX and also -+works from inside virtual machines because the speculation bypasses the -+extended page table (EPT) protection mechanism. -+ -+ -+Attack scenarios -+---------------- -+ -+1. Malicious user space -+^^^^^^^^^^^^^^^^^^^^^^^ -+ -+ Operating Systems store arbitrary information in the address bits of a -+ PTE which is marked non present. This allows a malicious user space -+ application to attack the physical memory to which these PTEs resolve. -+ In some cases user-space can maliciously influence the information -+ encoded in the address bits of the PTE, thus making attacks more -+ deterministic and more practical. -+ -+ The Linux kernel contains a mitigation for this attack vector, PTE -+ inversion, which is permanently enabled and has no performance -+ impact. The kernel ensures that the address bits of PTEs, which are not -+ marked present, never point to cacheable physical memory space. -+ -+ A system with an up to date kernel is protected against attacks from -+ malicious user space applications. -+ -+2. Malicious guest in a virtual machine -+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -+ -+ The fact that L1TF breaks all domain protections allows malicious guest -+ OSes, which can control the PTEs directly, and malicious guest user -+ space applications, which run on an unprotected guest kernel lacking the -+ PTE inversion mitigation for L1TF, to attack physical host memory. -+ -+ A special aspect of L1TF in the context of virtualization is symmetric -+ multi threading (SMT). The Intel implementation of SMT is called -+ HyperThreading. The fact that Hyperthreads on the affected processors -+ share the L1 Data Cache (L1D) is important for this. As the flaw allows -+ only to attack data which is present in L1D, a malicious guest running -+ on one Hyperthread can attack the data which is brought into the L1D by -+ the context which runs on the sibling Hyperthread of the same physical -+ core. This context can be host OS, host user space or a different guest. -+ -+ If the processor does not support Extended Page Tables, the attack is -+ only possible, when the hypervisor does not sanitize the content of the -+ effective (shadow) page tables. -+ -+ While solutions exist to mitigate these attack vectors fully, these -+ mitigations are not enabled by default in the Linux kernel because they -+ can affect performance significantly. The kernel provides several -+ mechanisms which can be utilized to address the problem depending on the -+ deployment scenario. The mitigations, their protection scope and impact -+ are described in the next sections. -+ -+ The default mitigations and the rationale for chosing them are explained -+ at the end of this document. See :ref:`default_mitigations`. -+ -+.. _l1tf_sys_info: -+ -+L1TF system information -+----------------------- -+ -+The Linux kernel provides a sysfs interface to enumerate the current L1TF -+status of the system: whether the system is vulnerable, and which -+mitigations are active. The relevant sysfs file is: -+ -+/sys/devices/system/cpu/vulnerabilities/l1tf -+ -+The possible values in this file are: -+ -+ =========================== =============================== -+ 'Not affected' The processor is not vulnerable -+ 'Mitigation: PTE Inversion' The host protection is active -+ =========================== =============================== -+ -+If KVM/VMX is enabled and the processor is vulnerable then the following -+information is appended to the 'Mitigation: PTE Inversion' part: -+ -+ - SMT status: -+ -+ ===================== ================ -+ 'VMX: SMT vulnerable' SMT is enabled -+ 'VMX: SMT disabled' SMT is disabled -+ ===================== ================ -+ -+ - L1D Flush mode: -+ -+ ================================ ==================================== -+ 'L1D vulnerable' L1D flushing is disabled -+ -+ 'L1D conditional cache flushes' L1D flush is conditionally enabled -+ -+ 'L1D cache flushes' L1D flush is unconditionally enabled -+ ================================ ==================================== -+ -+The resulting grade of protection is discussed in the following sections. -+ -+ -+Host mitigation mechanism -+------------------------- -+ -+The kernel is unconditionally protected against L1TF attacks from malicious -+user space running on the host. -+ -+ -+Guest mitigation mechanisms -+--------------------------- -+ -+.. _l1d_flush: -+ -+1. L1D flush on VMENTER -+^^^^^^^^^^^^^^^^^^^^^^^ -+ -+ To make sure that a guest cannot attack data which is present in the L1D -+ the hypervisor flushes the L1D before entering the guest. -+ -+ Flushing the L1D evicts not only the data which should not be accessed -+ by a potentially malicious guest, it also flushes the guest -+ data. Flushing the L1D has a performance impact as the processor has to -+ bring the flushed guest data back into the L1D. Depending on the -+ frequency of VMEXIT/VMENTER and the type of computations in the guest -+ performance degradation in the range of 1% to 50% has been observed. For -+ scenarios where guest VMEXIT/VMENTER are rare the performance impact is -+ minimal. Virtio and mechanisms like posted interrupts are designed to -+ confine the VMEXITs to a bare minimum, but specific configurations and -+ application scenarios might still suffer from a high VMEXIT rate. -+ -+ The kernel provides two L1D flush modes: -+ - conditional ('cond') -+ - unconditional ('always') -+ -+ The conditional mode avoids L1D flushing after VMEXITs which execute -+ only audited code pathes before the corresponding VMENTER. These code -+ pathes have beed verified that they cannot expose secrets or other -+ interesting data to an attacker, but they can leak information about the -+ address space layout of the hypervisor. -+ -+ Unconditional mode flushes L1D on all VMENTER invocations and provides -+ maximum protection. It has a higher overhead than the conditional -+ mode. The overhead cannot be quantified correctly as it depends on the -+ work load scenario and the resulting number of VMEXITs. -+ -+ The general recommendation is to enable L1D flush on VMENTER. The kernel -+ defaults to conditional mode on affected processors. -+ -+ **Note**, that L1D flush does not prevent the SMT problem because the -+ sibling thread will also bring back its data into the L1D which makes it -+ attackable again. -+ -+ L1D flush can be controlled by the administrator via the kernel command -+ line and sysfs control files. See :ref:`mitigation_control_command_line` -+ and :ref:`mitigation_control_kvm`. -+ -+.. _guest_confinement: -+ -+2. Guest VCPU confinement to dedicated physical cores -+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -+ -+ To address the SMT problem, it is possible to make a guest or a group of -+ guests affine to one or more physical cores. The proper mechanism for -+ that is to utilize exclusive cpusets to ensure that no other guest or -+ host tasks can run on these cores. -+ -+ If only a single guest or related guests run on sibling SMT threads on -+ the same physical core then they can only attack their own memory and -+ restricted parts of the host memory. -+ -+ Host memory is attackable, when one of the sibling SMT threads runs in -+ host OS (hypervisor) context and the other in guest context. The amount -+ of valuable information from the host OS context depends on the context -+ which the host OS executes, i.e. interrupts, soft interrupts and kernel -+ threads. The amount of valuable data from these contexts cannot be -+ declared as non-interesting for an attacker without deep inspection of -+ the code. -+ -+ **Note**, that assigning guests to a fixed set of physical cores affects -+ the ability of the scheduler to do load balancing and might have -+ negative effects on CPU utilization depending on the hosting -+ scenario. Disabling SMT might be a viable alternative for particular -+ scenarios. -+ -+ For further information about confining guests to a single or to a group -+ of cores consult the cpusets documentation: -+ -+ https://www.kernel.org/doc/Documentation/cgroup-v1/cpusets.txt -+ -+.. _interrupt_isolation: -+ -+3. Interrupt affinity -+^^^^^^^^^^^^^^^^^^^^^ -+ -+ Interrupts can be made affine to logical CPUs. This is not universally -+ true because there are types of interrupts which are truly per CPU -+ interrupts, e.g. the local timer interrupt. Aside of that multi queue -+ devices affine their interrupts to single CPUs or groups of CPUs per -+ queue without allowing the administrator to control the affinities. -+ -+ Moving the interrupts, which can be affinity controlled, away from CPUs -+ which run untrusted guests, reduces the attack vector space. -+ -+ Whether the interrupts with are affine to CPUs, which run untrusted -+ guests, provide interesting data for an attacker depends on the system -+ configuration and the scenarios which run on the system. While for some -+ of the interrupts it can be assumed that they wont expose interesting -+ information beyond exposing hints about the host OS memory layout, there -+ is no way to make general assumptions. -+ -+ Interrupt affinity can be controlled by the administrator via the -+ /proc/irq/$NR/smp_affinity[_list] files. Limited documentation is -+ available at: -+ -+ https://www.kernel.org/doc/Documentation/IRQ-affinity.txt -+ -+.. _smt_control: -+ -+4. SMT control -+^^^^^^^^^^^^^^ -+ -+ To prevent the SMT issues of L1TF it might be necessary to disable SMT -+ completely. Disabling SMT can have a significant performance impact, but -+ the impact depends on the hosting scenario and the type of workloads. -+ The impact of disabling SMT needs also to be weighted against the impact -+ of other mitigation solutions like confining guests to dedicated cores. -+ -+ The kernel provides a sysfs interface to retrieve the status of SMT and -+ to control it. It also provides a kernel command line interface to -+ control SMT. -+ -+ The kernel command line interface consists of the following options: -+ -+ =========== ========================================================== -+ nosmt Affects the bring up of the secondary CPUs during boot. The -+ kernel tries to bring all present CPUs online during the -+ boot process. "nosmt" makes sure that from each physical -+ core only one - the so called primary (hyper) thread is -+ activated. Due to a design flaw of Intel processors related -+ to Machine Check Exceptions the non primary siblings have -+ to be brought up at least partially and are then shut down -+ again. "nosmt" can be undone via the sysfs interface. -+ -+ nosmt=force Has the same effect as "nosmt' but it does not allow to -+ undo the SMT disable via the sysfs interface. -+ =========== ========================================================== -+ -+ The sysfs interface provides two files: -+ -+ - /sys/devices/system/cpu/smt/control -+ - /sys/devices/system/cpu/smt/active -+ -+ /sys/devices/system/cpu/smt/control: -+ -+ This file allows to read out the SMT control state and provides the -+ ability to disable or (re)enable SMT. The possible states are: -+ -+ ============== =================================================== -+ on SMT is supported by the CPU and enabled. All -+ logical CPUs can be onlined and offlined without -+ restrictions. -+ -+ off SMT is supported by the CPU and disabled. Only -+ the so called primary SMT threads can be onlined -+ and offlined without restrictions. An attempt to -+ online a non-primary sibling is rejected -+ -+ forceoff Same as 'off' but the state cannot be controlled. -+ Attempts to write to the control file are rejected. -+ -+ notsupported The processor does not support SMT. It's therefore -+ not affected by the SMT implications of L1TF. -+ Attempts to write to the control file are rejected. -+ ============== =================================================== -+ -+ The possible states which can be written into this file to control SMT -+ state are: -+ -+ - on -+ - off -+ - forceoff -+ -+ /sys/devices/system/cpu/smt/active: -+ -+ This file reports whether SMT is enabled and active, i.e. if on any -+ physical core two or more sibling threads are online. -+ -+ SMT control is also possible at boot time via the l1tf kernel command -+ line parameter in combination with L1D flush control. See -+ :ref:`mitigation_control_command_line`. -+ -+5. Disabling EPT -+^^^^^^^^^^^^^^^^ -+ -+ Disabling EPT for virtual machines provides full mitigation for L1TF even -+ with SMT enabled, because the effective page tables for guests are -+ managed and sanitized by the hypervisor. Though disabling EPT has a -+ significant performance impact especially when the Meltdown mitigation -+ KPTI is enabled. -+ -+ EPT can be disabled in the hypervisor via the 'kvm-intel.ept' parameter. -+ -+There is ongoing research and development for new mitigation mechanisms to -+address the performance impact of disabling SMT or EPT. -+ -+.. _mitigation_control_command_line: -+ -+Mitigation control on the kernel command line -+--------------------------------------------- -+ -+The kernel command line allows to control the L1TF mitigations at boot -+time with the option "l1tf=". The valid arguments for this option are: -+ -+ ============ ============================================================= -+ full Provides all available mitigations for the L1TF -+ vulnerability. Disables SMT and enables all mitigations in -+ the hypervisors, i.e. unconditional L1D flushing -+ -+ SMT control and L1D flush control via the sysfs interface -+ is still possible after boot. Hypervisors will issue a -+ warning when the first VM is started in a potentially -+ insecure configuration, i.e. SMT enabled or L1D flush -+ disabled. -+ -+ full,force Same as 'full', but disables SMT and L1D flush runtime -+ control. Implies the 'nosmt=force' command line option. -+ (i.e. sysfs control of SMT is disabled.) -+ -+ flush Leaves SMT enabled and enables the default hypervisor -+ mitigation, i.e. conditional L1D flushing -+ -+ SMT control and L1D flush control via the sysfs interface -+ is still possible after boot. Hypervisors will issue a -+ warning when the first VM is started in a potentially -+ insecure configuration, i.e. SMT enabled or L1D flush -+ disabled. -+ -+ flush,nosmt Disables SMT and enables the default hypervisor mitigation, -+ i.e. conditional L1D flushing. -+ -+ SMT control and L1D flush control via the sysfs interface -+ is still possible after boot. Hypervisors will issue a -+ warning when the first VM is started in a potentially -+ insecure configuration, i.e. SMT enabled or L1D flush -+ disabled. -+ -+ flush,nowarn Same as 'flush', but hypervisors will not warn when a VM is -+ started in a potentially insecure configuration. -+ -+ off Disables hypervisor mitigations and doesn't emit any -+ warnings. -+ ============ ============================================================= -+ -+The default is 'flush'. For details about L1D flushing see :ref:`l1d_flush`. -+ -+ -+.. _mitigation_control_kvm: -+ -+Mitigation control for KVM - module parameter -+------------------------------------------------------------- -+ -+The KVM hypervisor mitigation mechanism, flushing the L1D cache when -+entering a guest, can be controlled with a module parameter. -+ -+The option/parameter is "kvm-intel.vmentry_l1d_flush=". It takes the -+following arguments: -+ -+ ============ ============================================================== -+ always L1D cache flush on every VMENTER. -+ -+ cond Flush L1D on VMENTER only when the code between VMEXIT and -+ VMENTER can leak host memory which is considered -+ interesting for an attacker. This still can leak host memory -+ which allows e.g. to determine the hosts address space layout. -+ -+ never Disables the mitigation -+ ============ ============================================================== -+ -+The parameter can be provided on the kernel command line, as a module -+parameter when loading the modules and at runtime modified via the sysfs -+file: -+ -+/sys/module/kvm_intel/parameters/vmentry_l1d_flush -+ -+The default is 'cond'. If 'l1tf=full,force' is given on the kernel command -+line, then 'always' is enforced and the kvm-intel.vmentry_l1d_flush -+module parameter is ignored and writes to the sysfs file are rejected. -+ -+ -+Mitigation selection guide -+-------------------------- -+ -+1. No virtualization in use -+^^^^^^^^^^^^^^^^^^^^^^^^^^^ -+ -+ The system is protected by the kernel unconditionally and no further -+ action is required. -+ -+2. Virtualization with trusted guests -+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -+ -+ If the guest comes from a trusted source and the guest OS kernel is -+ guaranteed to have the L1TF mitigations in place the system is fully -+ protected against L1TF and no further action is required. -+ -+ To avoid the overhead of the default L1D flushing on VMENTER the -+ administrator can disable the flushing via the kernel command line and -+ sysfs control files. See :ref:`mitigation_control_command_line` and -+ :ref:`mitigation_control_kvm`. -+ -+ -+3. Virtualization with untrusted guests -+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -+ -+3.1. SMT not supported or disabled -+"""""""""""""""""""""""""""""""""" -+ -+ If SMT is not supported by the processor or disabled in the BIOS or by -+ the kernel, it's only required to enforce L1D flushing on VMENTER. -+ -+ Conditional L1D flushing is the default behaviour and can be tuned. See -+ :ref:`mitigation_control_command_line` and :ref:`mitigation_control_kvm`. -+ -+3.2. EPT not supported or disabled -+"""""""""""""""""""""""""""""""""" -+ -+ If EPT is not supported by the processor or disabled in the hypervisor, -+ the system is fully protected. SMT can stay enabled and L1D flushing on -+ VMENTER is not required. -+ -+ EPT can be disabled in the hypervisor via the 'kvm-intel.ept' parameter. -+ -+3.3. SMT and EPT supported and active -+""""""""""""""""""""""""""""""""""""" -+ -+ If SMT and EPT are supported and active then various degrees of -+ mitigations can be employed: -+ -+ - L1D flushing on VMENTER: -+ -+ L1D flushing on VMENTER is the minimal protection requirement, but it -+ is only potent in combination with other mitigation methods. -+ -+ Conditional L1D flushing is the default behaviour and can be tuned. See -+ :ref:`mitigation_control_command_line` and :ref:`mitigation_control_kvm`. -+ -+ - Guest confinement: -+ -+ Confinement of guests to a single or a group of physical cores which -+ are not running any other processes, can reduce the attack surface -+ significantly, but interrupts, soft interrupts and kernel threads can -+ still expose valuable data to a potential attacker. See -+ :ref:`guest_confinement`. -+ -+ - Interrupt isolation: -+ -+ Isolating the guest CPUs from interrupts can reduce the attack surface -+ further, but still allows a malicious guest to explore a limited amount -+ of host physical memory. This can at least be used to gain knowledge -+ about the host address space layout. The interrupts which have a fixed -+ affinity to the CPUs which run the untrusted guests can depending on -+ the scenario still trigger soft interrupts and schedule kernel threads -+ which might expose valuable information. See -+ :ref:`interrupt_isolation`. -+ -+The above three mitigation methods combined can provide protection to a -+certain degree, but the risk of the remaining attack surface has to be -+carefully analyzed. For full protection the following methods are -+available: -+ -+ - Disabling SMT: -+ -+ Disabling SMT and enforcing the L1D flushing provides the maximum -+ amount of protection. This mitigation is not depending on any of the -+ above mitigation methods. -+ -+ SMT control and L1D flushing can be tuned by the command line -+ parameters 'nosmt', 'l1tf', 'kvm-intel.vmentry_l1d_flush' and at run -+ time with the matching sysfs control files. See :ref:`smt_control`, -+ :ref:`mitigation_control_command_line` and -+ :ref:`mitigation_control_kvm`. -+ -+ - Disabling EPT: -+ -+ Disabling EPT provides the maximum amount of protection as well. It is -+ not depending on any of the above mitigation methods. SMT can stay -+ enabled and L1D flushing is not required, but the performance impact is -+ significant. -+ -+ EPT can be disabled in the hypervisor via the 'kvm-intel.ept' -+ parameter. -+ -+ -+.. _default_mitigations: -+ -+Default mitigations -+------------------- -+ -+ The kernel default mitigations for vulnerable processors are: -+ -+ - PTE inversion to protect against malicious user space. This is done -+ unconditionally and cannot be controlled. -+ -+ - L1D conditional flushing on VMENTER when EPT is enabled for -+ a guest. -+ -+ The kernel does not by default enforce the disabling of SMT, which leaves -+ SMT systems vulnerable when running untrusted guests with EPT enabled. -+ -+ The rationale for this choice is: -+ -+ - Force disabling SMT can break existing setups, especially with -+ unattended updates. -+ -+ - If regular users run untrusted guests on their machine, then L1TF is -+ just an add on to other malware which might be embedded in an untrusted -+ guest, e.g. spam-bots or attacks on the local network. -+ -+ There is no technical way to prevent a user from running untrusted code -+ on their machines blindly. -+ -+ - It's technically extremely unlikely and from today's knowledge even -+ impossible that L1TF can be exploited via the most popular attack -+ mechanisms like JavaScript because these mechanisms have no way to -+ control PTEs. If this would be possible and not other mitigation would -+ be possible, then the default might be different. -+ -+ - The administrators of cloud and hosting setups have to carefully -+ analyze the risk for their scenarios and make the appropriate -+ mitigation choices, which might even vary across their deployed -+ machines and also result in other changes of their overall setup. -+ There is no way for the kernel to provide a sensible default for this -+ kind of scenarios. -From foo@baz Tue Aug 14 13:43:11 CEST 2018 -From: Jiri Kosina -Date: Sat, 14 Jul 2018 21:56:13 +0200 -Subject: x86/speculation/l1tf: Unbreak !__HAVE_ARCH_PFN_MODIFY_ALLOWED architectures - -From: Jiri Kosina - -commit 6c26fcd2abfe0a56bbd95271fce02df2896cfd24 upstream - -pfn_modify_allowed() and arch_has_pfn_modify_check() are outside of the -!__ASSEMBLY__ section in include/asm-generic/pgtable.h, which confuses -assembler on archs that don't have __HAVE_ARCH_PFN_MODIFY_ALLOWED (e.g. -ia64) and breaks build: - - include/asm-generic/pgtable.h: Assembler messages: - include/asm-generic/pgtable.h:538: Error: Unknown opcode `static inline bool pfn_modify_allowed(unsigned long pfn,pgprot_t prot)' - include/asm-generic/pgtable.h:540: Error: Unknown opcode `return true' - include/asm-generic/pgtable.h:543: Error: Unknown opcode `static inline bool arch_has_pfn_modify_check(void)' - include/asm-generic/pgtable.h:545: Error: Unknown opcode `return false' - arch/ia64/kernel/entry.S:69: Error: `mov' does not fit into bundle - -Move those two static inlines into the !__ASSEMBLY__ section so that they -don't confuse the asm build pass. - -Fixes: 42e4089c7890 ("x86/speculation/l1tf: Disallow non privileged high MMIO PROT_NONE mappings") -Signed-off-by: Jiri Kosina -Signed-off-by: Thomas Gleixner -Signed-off-by: Greg Kroah-Hartman ---- - include/asm-generic/pgtable.h | 24 ++++++++++++------------ - 1 file changed, 12 insertions(+), 12 deletions(-) - ---- a/include/asm-generic/pgtable.h -+++ b/include/asm-generic/pgtable.h -@@ -1083,6 +1083,18 @@ int phys_mem_access_prot_allowed(struct - static inline void init_espfix_bsp(void) { } - #endif - -+#ifndef __HAVE_ARCH_PFN_MODIFY_ALLOWED -+static inline bool pfn_modify_allowed(unsigned long pfn, pgprot_t prot) -+{ -+ return true; -+} -+ -+static inline bool arch_has_pfn_modify_check(void) -+{ -+ return false; -+} -+#endif /* !_HAVE_ARCH_PFN_MODIFY_ALLOWED */ -+ - #endif /* !__ASSEMBLY__ */ - - #ifndef io_remap_pfn_range -@@ -1097,16 +1109,4 @@ static inline void init_espfix_bsp(void) - #endif - #endif - --#ifndef __HAVE_ARCH_PFN_MODIFY_ALLOWED --static inline bool pfn_modify_allowed(unsigned long pfn, pgprot_t prot) --{ -- return true; --} -- --static inline bool arch_has_pfn_modify_check(void) --{ -- return false; --} --#endif -- - #endif /* _ASM_GENERIC_PGTABLE_H */ -From foo@baz Tue Aug 14 13:43:11 CEST 2018 -From: Nicolai Stange -Date: Wed, 18 Jul 2018 19:07:38 +0200 -Subject: x86/KVM/VMX: Initialize the vmx_l1d_flush_pages' content - -From: Nicolai Stange - -commit 288d152c23dcf3c09da46c5c481903ca10ebfef7 upstream - -The slow path in vmx_l1d_flush() reads from vmx_l1d_flush_pages in order -to evict the L1d cache. - -However, these pages are never cleared and, in theory, their data could be -leaked. - -More importantly, KSM could merge a nested hypervisor's vmx_l1d_flush_pages -to fewer than 1 << L1D_CACHE_ORDER host physical pages and this would break -the L1d flushing algorithm: L1D on x86_64 is tagged by physical addresses. - -Fix this by initializing the individual vmx_l1d_flush_pages with a -different pattern each. - -Rename the "empty_zp" asm constraint identifier in vmx_l1d_flush() to -"flush_pages" to reflect this change. - -Fixes: a47dd5f06714 ("x86/KVM/VMX: Add L1D flush algorithm") -Signed-off-by: Nicolai Stange -Signed-off-by: Thomas Gleixner -Signed-off-by: Greg Kroah-Hartman ---- - arch/x86/kvm/vmx.c | 17 ++++++++++++++--- - 1 file changed, 14 insertions(+), 3 deletions(-) - ---- a/arch/x86/kvm/vmx.c -+++ b/arch/x86/kvm/vmx.c -@@ -211,6 +211,7 @@ static void *vmx_l1d_flush_pages; - static int vmx_setup_l1d_flush(enum vmx_l1d_flush_state l1tf) - { - struct page *page; -+ unsigned int i; - - if (!enable_ept) { - l1tf_vmx_mitigation = VMENTER_L1D_FLUSH_EPT_DISABLED; -@@ -243,6 +244,16 @@ static int vmx_setup_l1d_flush(enum vmx_ - if (!page) - return -ENOMEM; - vmx_l1d_flush_pages = page_address(page); -+ -+ /* -+ * Initialize each page with a different pattern in -+ * order to protect against KSM in the nested -+ * virtualization case. -+ */ -+ for (i = 0; i < 1u << L1D_CACHE_ORDER; ++i) { -+ memset(vmx_l1d_flush_pages + i * PAGE_SIZE, i + 1, -+ PAGE_SIZE); -+ } - } - - l1tf_vmx_mitigation = l1tf; -@@ -9471,7 +9482,7 @@ static void vmx_l1d_flush(struct kvm_vcp - /* First ensure the pages are in the TLB */ - "xorl %%eax, %%eax\n" - ".Lpopulate_tlb:\n\t" -- "movzbl (%[empty_zp], %%" _ASM_AX "), %%ecx\n\t" -+ "movzbl (%[flush_pages], %%" _ASM_AX "), %%ecx\n\t" - "addl $4096, %%eax\n\t" - "cmpl %%eax, %[size]\n\t" - "jne .Lpopulate_tlb\n\t" -@@ -9480,12 +9491,12 @@ static void vmx_l1d_flush(struct kvm_vcp - /* Now fill the cache */ - "xorl %%eax, %%eax\n" - ".Lfill_cache:\n" -- "movzbl (%[empty_zp], %%" _ASM_AX "), %%ecx\n\t" -+ "movzbl (%[flush_pages], %%" _ASM_AX "), %%ecx\n\t" - "addl $64, %%eax\n\t" - "cmpl %%eax, %[size]\n\t" - "jne .Lfill_cache\n\t" - "lfence\n" -- :: [empty_zp] "r" (vmx_l1d_flush_pages), -+ :: [flush_pages] "r" (vmx_l1d_flush_pages), - [size] "r" (size) - : "eax", "ebx", "ecx", "edx"); - } -From foo@baz Tue Aug 14 13:43:11 CEST 2018 -From: Tony Luck -Date: Thu, 19 Jul 2018 13:49:58 -0700 -Subject: Documentation/l1tf: Fix typos - -From: Tony Luck - -commit 1949f9f49792d65dba2090edddbe36a5f02e3ba3 upstream - -Fix spelling and other typos - -Signed-off-by: Tony Luck -Signed-off-by: Thomas Gleixner -Signed-off-by: Greg Kroah-Hartman ---- - Documentation/admin-guide/l1tf.rst | 14 +++++++------- - 1 file changed, 7 insertions(+), 7 deletions(-) - ---- a/Documentation/admin-guide/l1tf.rst -+++ b/Documentation/admin-guide/l1tf.rst -@@ -17,7 +17,7 @@ vulnerability is not present on: - - Older processor models, where the CPU family is < 6 - - - A range of Intel ATOM processors (Cedarview, Cloverview, Lincroft, -- Penwell, Pineview, Slivermont, Airmont, Merrifield) -+ Penwell, Pineview, Silvermont, Airmont, Merrifield) - - - The Intel Core Duo Yonah variants (2006 - 2008) - -@@ -113,7 +113,7 @@ Attack scenarios - deployment scenario. The mitigations, their protection scope and impact - are described in the next sections. - -- The default mitigations and the rationale for chosing them are explained -+ The default mitigations and the rationale for choosing them are explained - at the end of this document. See :ref:`default_mitigations`. - - .. _l1tf_sys_info: -@@ -191,15 +191,15 @@ Guest mitigation mechanisms - - unconditional ('always') - - The conditional mode avoids L1D flushing after VMEXITs which execute -- only audited code pathes before the corresponding VMENTER. These code -- pathes have beed verified that they cannot expose secrets or other -+ only audited code paths before the corresponding VMENTER. These code -+ paths have been verified that they cannot expose secrets or other - interesting data to an attacker, but they can leak information about the - address space layout of the hypervisor. - - Unconditional mode flushes L1D on all VMENTER invocations and provides - maximum protection. It has a higher overhead than the conditional - mode. The overhead cannot be quantified correctly as it depends on the -- work load scenario and the resulting number of VMEXITs. -+ workload scenario and the resulting number of VMEXITs. - - The general recommendation is to enable L1D flush on VMENTER. The kernel - defaults to conditional mode on affected processors. -@@ -262,7 +262,7 @@ Guest mitigation mechanisms - Whether the interrupts with are affine to CPUs, which run untrusted - guests, provide interesting data for an attacker depends on the system - configuration and the scenarios which run on the system. While for some -- of the interrupts it can be assumed that they wont expose interesting -+ of the interrupts it can be assumed that they won't expose interesting - information beyond exposing hints about the host OS memory layout, there - is no way to make general assumptions. - -@@ -299,7 +299,7 @@ Guest mitigation mechanisms - to be brought up at least partially and are then shut down - again. "nosmt" can be undone via the sysfs interface. - -- nosmt=force Has the same effect as "nosmt' but it does not allow to -+ nosmt=force Has the same effect as "nosmt" but it does not allow to - undo the SMT disable via the sysfs interface. - =========== ========================================================== - -From foo@baz Tue Aug 14 13:43:11 CEST 2018 -From: Josh Poimboeuf -Date: Wed, 25 Jul 2018 10:36:45 +0200 -Subject: cpu/hotplug: detect SMT disabled by BIOS - -From: Josh Poimboeuf - -commit 73d5e2b472640b1fcdb61ae8be389912ef211bda upstream - -If SMT is disabled in BIOS, the CPU code doesn't properly detect it. -The /sys/devices/system/cpu/smt/control file shows 'on', and the 'l1tf' -vulnerabilities file shows SMT as vulnerable. - -Fix it by forcing 'cpu_smt_control' to CPU_SMT_NOT_SUPPORTED in such a -case. Unfortunately the detection can only be done after bringing all -the CPUs online, so we have to overwrite any previous writes to the -variable. - -Reported-by: Joe Mario -Tested-by: Jiri Kosina -Fixes: f048c399e0f7 ("x86/topology: Provide topology_smt_supported()") -Signed-off-by: Josh Poimboeuf -Signed-off-by: Peter Zijlstra -Signed-off-by: Greg Kroah-Hartman ---- - kernel/cpu.c | 9 +++++++++ - 1 file changed, 9 insertions(+) - ---- a/kernel/cpu.c -+++ b/kernel/cpu.c -@@ -2125,6 +2125,15 @@ static const struct attribute_group cpuh - - static int __init cpu_smt_state_init(void) - { -+ /* -+ * If SMT was disabled by BIOS, detect it here, after the CPUs have -+ * been brought online. This ensures the smt/l1tf sysfs entries are -+ * consistent with reality. Note this may overwrite cpu_smt_control's -+ * previous setting. -+ */ -+ if (topology_max_smt_threads() == 1) -+ cpu_smt_control = CPU_SMT_NOT_SUPPORTED; -+ - return sysfs_create_group(&cpu_subsys.dev_root->kobj, - &cpuhp_smt_attr_group); - } -From foo@baz Tue Aug 14 13:43:11 CEST 2018 -From: Nicolai Stange -Date: Sat, 21 Jul 2018 22:16:56 +0200 -Subject: x86/KVM/VMX: Don't set l1tf_flush_l1d to true from vmx_l1d_flush() - -From: Nicolai Stange - -commit 379fd0c7e6a391e5565336a646f19f218fb98c6c upstream - -vmx_l1d_flush() gets invoked only if l1tf_flush_l1d is true. There's no -point in setting l1tf_flush_l1d to true from there again. - -Signed-off-by: Nicolai Stange -Signed-off-by: Thomas Gleixner -Signed-off-by: Greg Kroah-Hartman ---- - arch/x86/kvm/vmx.c | 14 +++++++------- - 1 file changed, 7 insertions(+), 7 deletions(-) - ---- a/arch/x86/kvm/vmx.c -+++ b/arch/x86/kvm/vmx.c -@@ -9461,15 +9461,15 @@ static void vmx_l1d_flush(struct kvm_vcp - /* - * This code is only executed when the the flush mode is 'cond' or - * 'always' -- * -- * If 'flush always', keep the flush bit set, otherwise clear -- * it. The flush bit gets set again either from vcpu_run() or from -- * one of the unsafe VMEXIT handlers. - */ -- if (static_branch_unlikely(&vmx_l1d_flush_always)) -- vcpu->arch.l1tf_flush_l1d = true; -- else -+ if (!static_branch_unlikely(&vmx_l1d_flush_always)) { -+ /* -+ * Clear the flush bit, it gets set again either from -+ * vcpu_run() or from one of the unsafe VMEXIT -+ * handlers. -+ */ - vcpu->arch.l1tf_flush_l1d = false; -+ } - - vcpu->stat.l1d_flush++; - -From foo@baz Tue Aug 14 13:43:11 CEST 2018 -From: Nicolai Stange -Date: Sat, 21 Jul 2018 22:25:00 +0200 -Subject: x86/KVM/VMX: Replace 'vmx_l1d_flush_always' with 'vmx_l1d_flush_cond' - -From: Nicolai Stange - -commit 427362a142441f08051369db6fbe7f61c73b3dca upstream - -The vmx_l1d_flush_always static key is only ever evaluated if -vmx_l1d_should_flush is enabled. In that case however, there are only two -L1d flushing modes possible: "always" and "conditional". - -The "conditional" mode's implementation tends to require more sophisticated -logic than the "always" mode. - -Avoid inverted logic by replacing the 'vmx_l1d_flush_always' static key -with a 'vmx_l1d_flush_cond' one. - -There is no change in functionality. - -Signed-off-by: Nicolai Stange -Signed-off-by: Thomas Gleixner -Signed-off-by: Greg Kroah-Hartman ---- - arch/x86/kvm/vmx.c | 10 +++++----- - 1 file changed, 5 insertions(+), 5 deletions(-) - ---- a/arch/x86/kvm/vmx.c -+++ b/arch/x86/kvm/vmx.c -@@ -189,7 +189,7 @@ module_param(ple_window_max, uint, 0444) - extern const ulong vmx_return; - - static DEFINE_STATIC_KEY_FALSE(vmx_l1d_should_flush); --static DEFINE_STATIC_KEY_FALSE(vmx_l1d_flush_always); -+static DEFINE_STATIC_KEY_FALSE(vmx_l1d_flush_cond); - static DEFINE_MUTEX(vmx_l1d_flush_mutex); - - /* Storage for pre module init parameter parsing */ -@@ -263,10 +263,10 @@ static int vmx_setup_l1d_flush(enum vmx_ - else - static_branch_disable(&vmx_l1d_should_flush); - -- if (l1tf == VMENTER_L1D_FLUSH_ALWAYS) -- static_branch_enable(&vmx_l1d_flush_always); -+ if (l1tf == VMENTER_L1D_FLUSH_COND) -+ static_branch_enable(&vmx_l1d_flush_cond); - else -- static_branch_disable(&vmx_l1d_flush_always); -+ static_branch_disable(&vmx_l1d_flush_cond); - return 0; - } - -@@ -9462,7 +9462,7 @@ static void vmx_l1d_flush(struct kvm_vcp - * This code is only executed when the the flush mode is 'cond' or - * 'always' - */ -- if (!static_branch_unlikely(&vmx_l1d_flush_always)) { -+ if (static_branch_likely(&vmx_l1d_flush_cond)) { - /* - * Clear the flush bit, it gets set again either from - * vcpu_run() or from one of the unsafe VMEXIT -From foo@baz Tue Aug 14 13:43:11 CEST 2018 -From: Nicolai Stange -Date: Sat, 21 Jul 2018 22:35:28 +0200 -Subject: x86/KVM/VMX: Move the l1tf_flush_l1d test to vmx_l1d_flush() - -From: Nicolai Stange - -commit 5b6ccc6c3b1a477fbac9ec97a0b4c1c48e765209 upstream - -Currently, vmx_vcpu_run() checks if l1tf_flush_l1d is set and invokes -vmx_l1d_flush() if so. - -This test is unncessary for the "always flush L1D" mode. - -Move the check to vmx_l1d_flush()'s conditional mode code path. - -Notes: -- vmx_l1d_flush() is likely to get inlined anyway and thus, there's no - extra function call. - -- This inverts the (static) branch prediction, but there hadn't been any - explicit likely()/unlikely() annotations before and so it stays as is. - -Signed-off-by: Nicolai Stange -Signed-off-by: Thomas Gleixner -Signed-off-by: Greg Kroah-Hartman ---- - arch/x86/kvm/vmx.c | 10 ++++++---- - 1 file changed, 6 insertions(+), 4 deletions(-) - ---- a/arch/x86/kvm/vmx.c -+++ b/arch/x86/kvm/vmx.c -@@ -9463,12 +9463,16 @@ static void vmx_l1d_flush(struct kvm_vcp - * 'always' - */ - if (static_branch_likely(&vmx_l1d_flush_cond)) { -+ bool flush_l1d = vcpu->arch.l1tf_flush_l1d; -+ - /* - * Clear the flush bit, it gets set again either from - * vcpu_run() or from one of the unsafe VMEXIT - * handlers. - */ - vcpu->arch.l1tf_flush_l1d = false; -+ if (!flush_l1d) -+ return; - } - - vcpu->stat.l1d_flush++; -@@ -10003,10 +10007,8 @@ static void __noclone vmx_vcpu_run(struc - evmcs_rsp = static_branch_unlikely(&enable_evmcs) ? - (unsigned long)¤t_evmcs->host_rsp : 0; - -- if (static_branch_unlikely(&vmx_l1d_should_flush)) { -- if (vcpu->arch.l1tf_flush_l1d) -- vmx_l1d_flush(vcpu); -- } -+ if (static_branch_unlikely(&vmx_l1d_should_flush)) -+ vmx_l1d_flush(vcpu); - - asm( - /* Store host registers */ -From foo@baz Tue Aug 14 13:43:11 CEST 2018 -From: Nicolai Stange -Date: Fri, 27 Jul 2018 12:46:29 +0200 -Subject: x86/irq: Demote irq_cpustat_t::__softirq_pending to u16 - -From: Nicolai Stange - -commit 9aee5f8a7e30330d0a8f4c626dc924ca5590aba5 upstream - -An upcoming patch will extend KVM's L1TF mitigation in conditional mode -to also cover interrupts after VMEXITs. For tracking those, stores to a -new per-cpu flag from interrupt handlers will become necessary. - -In order to improve cache locality, this new flag will be added to x86's -irq_cpustat_t. - -Make some space available there by shrinking the ->softirq_pending bitfield -from 32 to 16 bits: the number of bits actually used is only NR_SOFTIRQS, -i.e. 10. - -Suggested-by: Paolo Bonzini -Signed-off-by: Nicolai Stange -Signed-off-by: Thomas Gleixner -Reviewed-by: Paolo Bonzini -Signed-off-by: Greg Kroah-Hartman ---- - arch/x86/include/asm/hardirq.h | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/arch/x86/include/asm/hardirq.h -+++ b/arch/x86/include/asm/hardirq.h -@@ -6,7 +6,7 @@ - #include - - typedef struct { -- unsigned int __softirq_pending; -+ u16 __softirq_pending; - unsigned int __nmi_count; /* arch dependent */ - #ifdef CONFIG_X86_LOCAL_APIC - unsigned int apic_timer_irqs; /* arch dependent */ -From foo@baz Tue Aug 14 13:43:11 CEST 2018 -From: Nicolai Stange -Date: Fri, 27 Jul 2018 13:22:16 +0200 -Subject: x86/KVM/VMX: Introduce per-host-cpu analogue of l1tf_flush_l1d - -From: Nicolai Stange - -commit 45b575c00d8e72d69d75dd8c112f044b7b01b069 upstream - -Part of the L1TF mitigation for vmx includes flushing the L1D cache upon -VMENTRY. - -L1D flushes are costly and two modes of operations are provided to users: -"always" and the more selective "conditional" mode. - -If operating in the latter, the cache would get flushed only if a host side -code path considered unconfined had been traversed. "Unconfined" in this -context means that it might have pulled in sensitive data like user data -or kernel crypto keys. - -The need for L1D flushes is tracked by means of the per-vcpu flag -l1tf_flush_l1d. KVM exit handlers considered unconfined set it. A -vmx_l1d_flush() subsequently invoked before the next VMENTER will conduct a -L1d flush based on its value and reset that flag again. - -Currently, interrupts delivered "normally" while in root operation between -VMEXIT and VMENTER are not taken into account. Part of the reason is that -these don't leave any traces and thus, the vmx code is unable to tell if -any such has happened. - -As proposed by Paolo Bonzini, prepare for tracking all interrupts by -introducing a new per-cpu flag, "kvm_cpu_l1tf_flush_l1d". It will be in -strong analogy to the per-vcpu ->l1tf_flush_l1d. - -A later patch will make interrupt handlers set it. - -For the sake of cache locality, group kvm_cpu_l1tf_flush_l1d into x86' -per-cpu irq_cpustat_t as suggested by Peter Zijlstra. - -Provide the helpers kvm_set_cpu_l1tf_flush_l1d(), -kvm_clear_cpu_l1tf_flush_l1d() and kvm_get_cpu_l1tf_flush_l1d(). Make them -trivial resp. non-existent for !CONFIG_KVM_INTEL as appropriate. - -Let vmx_l1d_flush() handle kvm_cpu_l1tf_flush_l1d in the same way as -l1tf_flush_l1d. - -Suggested-by: Paolo Bonzini -Suggested-by: Peter Zijlstra -Signed-off-by: Nicolai Stange -Signed-off-by: Thomas Gleixner -Reviewed-by: Paolo Bonzini -Signed-off-by: Greg Kroah-Hartman ---- - arch/x86/include/asm/hardirq.h | 23 +++++++++++++++++++++++ - arch/x86/kvm/vmx.c | 17 +++++++++++++---- - 2 files changed, 36 insertions(+), 4 deletions(-) - ---- a/arch/x86/include/asm/hardirq.h -+++ b/arch/x86/include/asm/hardirq.h -@@ -7,6 +7,9 @@ - - typedef struct { - u16 __softirq_pending; -+#if IS_ENABLED(CONFIG_KVM_INTEL) -+ u8 kvm_cpu_l1tf_flush_l1d; -+#endif - unsigned int __nmi_count; /* arch dependent */ - #ifdef CONFIG_X86_LOCAL_APIC - unsigned int apic_timer_irqs; /* arch dependent */ -@@ -66,4 +69,24 @@ extern u64 arch_irq_stat_cpu(unsigned in - extern u64 arch_irq_stat(void); - #define arch_irq_stat arch_irq_stat - -+ -+#if IS_ENABLED(CONFIG_KVM_INTEL) -+static inline void kvm_set_cpu_l1tf_flush_l1d(void) -+{ -+ __this_cpu_write(irq_stat.kvm_cpu_l1tf_flush_l1d, 1); -+} -+ -+static inline void kvm_clear_cpu_l1tf_flush_l1d(void) -+{ -+ __this_cpu_write(irq_stat.kvm_cpu_l1tf_flush_l1d, 0); -+} -+ -+static inline bool kvm_get_cpu_l1tf_flush_l1d(void) -+{ -+ return __this_cpu_read(irq_stat.kvm_cpu_l1tf_flush_l1d); -+} -+#else /* !IS_ENABLED(CONFIG_KVM_INTEL) */ -+static inline void kvm_set_cpu_l1tf_flush_l1d(void) { } -+#endif /* IS_ENABLED(CONFIG_KVM_INTEL) */ -+ - #endif /* _ASM_X86_HARDIRQ_H */ ---- a/arch/x86/kvm/vmx.c -+++ b/arch/x86/kvm/vmx.c -@@ -9463,14 +9463,23 @@ static void vmx_l1d_flush(struct kvm_vcp - * 'always' - */ - if (static_branch_likely(&vmx_l1d_flush_cond)) { -- bool flush_l1d = vcpu->arch.l1tf_flush_l1d; -+ bool flush_l1d; - - /* -- * Clear the flush bit, it gets set again either from -- * vcpu_run() or from one of the unsafe VMEXIT -- * handlers. -+ * Clear the per-vcpu flush bit, it gets set again -+ * either from vcpu_run() or from one of the unsafe -+ * VMEXIT handlers. - */ -+ flush_l1d = vcpu->arch.l1tf_flush_l1d; - vcpu->arch.l1tf_flush_l1d = false; -+ -+ /* -+ * Clear the per-cpu flush bit, it gets set again from -+ * the interrupt handlers. -+ */ -+ flush_l1d |= kvm_get_cpu_l1tf_flush_l1d(); -+ kvm_clear_cpu_l1tf_flush_l1d(); -+ - if (!flush_l1d) - return; - } -From foo@baz Tue Aug 14 13:43:11 CEST 2018 -From: Nicolai Stange -Date: Sun, 29 Jul 2018 12:15:33 +0200 -Subject: x86: Don't include linux/irq.h from asm/hardirq.h - -From: Nicolai Stange - -commit 447ae316670230d7d29430e2cbf1f5db4f49d14c upstream - -The next patch in this series will have to make the definition of -irq_cpustat_t available to entering_irq(). - -Inclusion of asm/hardirq.h into asm/apic.h would cause circular header -dependencies like - - asm/smp.h - asm/apic.h - asm/hardirq.h - linux/irq.h - linux/topology.h - linux/smp.h - asm/smp.h - -or - - linux/gfp.h - linux/mmzone.h - asm/mmzone.h - asm/mmzone_64.h - asm/smp.h - asm/apic.h - asm/hardirq.h - linux/irq.h - linux/irqdesc.h - linux/kobject.h - linux/sysfs.h - linux/kernfs.h - linux/idr.h - linux/gfp.h - -and others. - -This causes compilation errors because of the header guards becoming -effective in the second inclusion: symbols/macros that had been defined -before wouldn't be available to intermediate headers in the #include chain -anymore. - -A possible workaround would be to move the definition of irq_cpustat_t -into its own header and include that from both, asm/hardirq.h and -asm/apic.h. - -However, this wouldn't solve the real problem, namely asm/harirq.h -unnecessarily pulling in all the linux/irq.h cruft: nothing in -asm/hardirq.h itself requires it. Also, note that there are some other -archs, like e.g. arm64, which don't have that #include in their -asm/hardirq.h. - -Remove the linux/irq.h #include from x86' asm/hardirq.h. - -Fix resulting compilation errors by adding appropriate #includes to *.c -files as needed. - -Note that some of these *.c files could be cleaned up a bit wrt. to their -set of #includes, but that should better be done from separate patches, if -at all. - -Signed-off-by: Nicolai Stange -Signed-off-by: Thomas Gleixner -Signed-off-by: Greg Kroah-Hartman ---- - arch/x86/include/asm/dmi.h | 2 +- - arch/x86/include/asm/hardirq.h | 1 - - arch/x86/include/asm/kvm_host.h | 1 + - arch/x86/kernel/apic/apic.c | 1 + - arch/x86/kernel/apic/io_apic.c | 1 + - arch/x86/kernel/apic/msi.c | 1 + - arch/x86/kernel/apic/vector.c | 1 + - arch/x86/kernel/fpu/core.c | 1 + - arch/x86/kernel/hpet.c | 1 + - arch/x86/kernel/i8259.c | 1 + - arch/x86/kernel/idt.c | 1 + - arch/x86/kernel/irq.c | 1 + - arch/x86/kernel/irq_32.c | 1 + - arch/x86/kernel/irq_64.c | 1 + - arch/x86/kernel/irqinit.c | 1 + - arch/x86/kernel/smpboot.c | 1 + - arch/x86/kernel/time.c | 1 + - arch/x86/mm/pti.c | 1 + - arch/x86/platform/intel-mid/device_libs/platform_mrfld_wdt.c | 1 + - arch/x86/xen/enlighten.c | 1 + - drivers/gpu/drm/i915/i915_pmu.c | 1 + - drivers/gpu/drm/i915/intel_lpe_audio.c | 1 + - drivers/pci/host/pci-hyperv.c | 2 ++ - 23 files changed, 23 insertions(+), 2 deletions(-) - ---- a/arch/x86/include/asm/dmi.h -+++ b/arch/x86/include/asm/dmi.h -@@ -4,8 +4,8 @@ - - #include - #include -+#include - --#include - #include - - static __always_inline __init void *dmi_alloc(unsigned len) ---- a/arch/x86/include/asm/hardirq.h -+++ b/arch/x86/include/asm/hardirq.h -@@ -3,7 +3,6 @@ - #define _ASM_X86_HARDIRQ_H - - #include --#include - - typedef struct { - u16 __softirq_pending; ---- a/arch/x86/include/asm/kvm_host.h -+++ b/arch/x86/include/asm/kvm_host.h -@@ -17,6 +17,7 @@ - #include - #include - #include -+#include - - #include - #include ---- a/arch/x86/kernel/apic/apic.c -+++ b/arch/x86/kernel/apic/apic.c -@@ -56,6 +56,7 @@ - #include - #include - #include -+#include - - unsigned int num_processors; - ---- a/arch/x86/kernel/apic/io_apic.c -+++ b/arch/x86/kernel/apic/io_apic.c -@@ -33,6 +33,7 @@ - - #include - #include -+#include - #include - #include - #include ---- a/arch/x86/kernel/apic/msi.c -+++ b/arch/x86/kernel/apic/msi.c -@@ -12,6 +12,7 @@ - */ - #include - #include -+#include - #include - #include - #include ---- a/arch/x86/kernel/apic/vector.c -+++ b/arch/x86/kernel/apic/vector.c -@@ -11,6 +11,7 @@ - * published by the Free Software Foundation. - */ - #include -+#include - #include - #include - #include ---- a/arch/x86/kernel/fpu/core.c -+++ b/arch/x86/kernel/fpu/core.c -@@ -10,6 +10,7 @@ - #include - #include - #include -+#include - - #include - #include ---- a/arch/x86/kernel/hpet.c -+++ b/arch/x86/kernel/hpet.c -@@ -1,6 +1,7 @@ - #include - #include - #include -+#include - #include - #include - #include ---- a/arch/x86/kernel/i8259.c -+++ b/arch/x86/kernel/i8259.c -@@ -5,6 +5,7 @@ - #include - #include - #include -+#include - #include - #include - #include ---- a/arch/x86/kernel/idt.c -+++ b/arch/x86/kernel/idt.c -@@ -8,6 +8,7 @@ - #include - #include - #include -+#include - - struct idt_data { - unsigned int vector; ---- a/arch/x86/kernel/irq.c -+++ b/arch/x86/kernel/irq.c -@@ -10,6 +10,7 @@ - #include - #include - #include -+#include - - #include - #include ---- a/arch/x86/kernel/irq_32.c -+++ b/arch/x86/kernel/irq_32.c -@@ -11,6 +11,7 @@ - - #include - #include -+#include - #include - #include - #include ---- a/arch/x86/kernel/irq_64.c -+++ b/arch/x86/kernel/irq_64.c -@@ -11,6 +11,7 @@ - - #include - #include -+#include - #include - #include - #include ---- a/arch/x86/kernel/irqinit.c -+++ b/arch/x86/kernel/irqinit.c -@@ -5,6 +5,7 @@ - #include - #include - #include -+#include - #include - #include - #include ---- a/arch/x86/kernel/smpboot.c -+++ b/arch/x86/kernel/smpboot.c -@@ -80,6 +80,7 @@ - #include - #include - #include -+#include - - /* Number of siblings per CPU package */ - int smp_num_siblings = 1; ---- a/arch/x86/kernel/time.c -+++ b/arch/x86/kernel/time.c -@@ -12,6 +12,7 @@ - - #include - #include -+#include - #include - #include - #include ---- a/arch/x86/mm/pti.c -+++ b/arch/x86/mm/pti.c -@@ -45,6 +45,7 @@ - #include - #include - #include -+#include - - #undef pr_fmt - #define pr_fmt(fmt) "Kernel/User page tables isolation: " fmt ---- a/arch/x86/platform/intel-mid/device_libs/platform_mrfld_wdt.c -+++ b/arch/x86/platform/intel-mid/device_libs/platform_mrfld_wdt.c -@@ -18,6 +18,7 @@ - #include - #include - #include -+#include - - #define TANGIER_EXT_TIMER0_MSI 12 - ---- a/arch/x86/xen/enlighten.c -+++ b/arch/x86/xen/enlighten.c -@@ -3,6 +3,7 @@ - #endif - #include - #include -+#include - - #include - #include ---- a/drivers/gpu/drm/i915/i915_pmu.c -+++ b/drivers/gpu/drm/i915/i915_pmu.c -@@ -24,6 +24,7 @@ - - #include - #include -+#include - - #include "i915_drv.h" - #include "i915_pmu.h" ---- a/drivers/gpu/drm/i915/intel_lpe_audio.c -+++ b/drivers/gpu/drm/i915/intel_lpe_audio.c -@@ -62,6 +62,7 @@ - - #include - #include -+#include - #include - #include - ---- a/drivers/pci/host/pci-hyperv.c -+++ b/drivers/pci/host/pci-hyperv.c -@@ -43,6 +43,8 @@ - #include - #include - #include -+#include -+ - #include - #include - #include -From foo@baz Tue Aug 14 13:43:11 CEST 2018 -From: Nicolai Stange -Date: Sun, 29 Jul 2018 13:06:04 +0200 -Subject: x86/irq: Let interrupt handlers set kvm_cpu_l1tf_flush_l1d - -From: Nicolai Stange - -commit ffcba43ff66c7dab34ec700debd491d2a4d319b4 upstream - -The last missing piece to having vmx_l1d_flush() take interrupts after -VMEXIT into account is to set the kvm_cpu_l1tf_flush_l1d per-cpu flag on -irq entry. - -Issue calls to kvm_set_cpu_l1tf_flush_l1d() from entering_irq(), -ipi_entering_ack_irq(), smp_reschedule_interrupt() and -uv_bau_message_interrupt(). - -Suggested-by: Paolo Bonzini -Signed-off-by: Nicolai Stange -Signed-off-by: Thomas Gleixner -Signed-off-by: Greg Kroah-Hartman ---- - arch/x86/include/asm/apic.h | 3 +++ - arch/x86/kernel/smp.c | 1 + - arch/x86/platform/uv/tlb_uv.c | 1 + - 3 files changed, 5 insertions(+) - ---- a/arch/x86/include/asm/apic.h -+++ b/arch/x86/include/asm/apic.h -@@ -10,6 +10,7 @@ - #include - #include - #include -+#include - - #define ARCH_APICTIMER_STOPS_ON_C3 1 - -@@ -514,6 +515,7 @@ extern void irq_exit(void); - static inline void entering_irq(void) - { - irq_enter(); -+ kvm_set_cpu_l1tf_flush_l1d(); - } - - static inline void entering_ack_irq(void) -@@ -526,6 +528,7 @@ static inline void ipi_entering_ack_irq( - { - irq_enter(); - ack_APIC_irq(); -+ kvm_set_cpu_l1tf_flush_l1d(); - } - - static inline void exiting_irq(void) ---- a/arch/x86/kernel/smp.c -+++ b/arch/x86/kernel/smp.c -@@ -261,6 +261,7 @@ __visible void __irq_entry smp_reschedul - { - ack_APIC_irq(); - inc_irq_stat(irq_resched_count); -+ kvm_set_cpu_l1tf_flush_l1d(); - - if (trace_resched_ipi_enabled()) { - /* ---- a/arch/x86/platform/uv/tlb_uv.c -+++ b/arch/x86/platform/uv/tlb_uv.c -@@ -1285,6 +1285,7 @@ void uv_bau_message_interrupt(struct pt_ - struct msg_desc msgdesc; - - ack_APIC_irq(); -+ kvm_set_cpu_l1tf_flush_l1d(); - time_start = get_cycles(); - - bcp = &per_cpu(bau_control, smp_processor_id()); -From foo@baz Tue Aug 14 13:43:11 CEST 2018 -From: Nicolai Stange -Date: Sun, 22 Jul 2018 13:38:18 +0200 -Subject: x86/KVM/VMX: Don't set l1tf_flush_l1d from vmx_handle_external_intr() - -From: Nicolai Stange - -commit 18b57ce2eb8c8b9a24174a89250cf5f57c76ecdc upstream - -For VMEXITs caused by external interrupts, vmx_handle_external_intr() -indirectly calls into the interrupt handlers through the host's IDT. - -It follows that these interrupts get accounted for in the -kvm_cpu_l1tf_flush_l1d per-cpu flag. - -The subsequently executed vmx_l1d_flush() will thus be aware that some -interrupts have happened and conduct a L1d flush anyway. - -Setting l1tf_flush_l1d from vmx_handle_external_intr() isn't needed -anymore. Drop it. - -Signed-off-by: Nicolai Stange -Signed-off-by: Thomas Gleixner -Signed-off-by: Greg Kroah-Hartman ---- - arch/x86/kvm/vmx.c | 1 - - 1 file changed, 1 deletion(-) - ---- a/arch/x86/kvm/vmx.c -+++ b/arch/x86/kvm/vmx.c -@@ -9758,7 +9758,6 @@ static void vmx_handle_external_intr(str - [ss]"i"(__KERNEL_DS), - [cs]"i"(__KERNEL_CS) - ); -- vcpu->arch.l1tf_flush_l1d = true; - } - } - STACK_FRAME_NON_STANDARD(vmx_handle_external_intr); -From foo@baz Tue Aug 14 13:43:11 CEST 2018 -From: Thomas Gleixner -Date: Sun, 5 Aug 2018 17:06:12 +0200 -Subject: Documentation/l1tf: Remove Yonah processors from not vulnerable list - -From: Thomas Gleixner - -commit 58331136136935c631c2b5f06daf4c3006416e91 upstream - -Dave reported, that it's not confirmed that Yonah processors are -unaffected. Remove them from the list. - -Reported-by: ave Hansen -Signed-off-by: Thomas Gleixner -Signed-off-by: Greg Kroah-Hartman ---- - Documentation/admin-guide/l1tf.rst | 2 -- - 1 file changed, 2 deletions(-) - ---- a/Documentation/admin-guide/l1tf.rst -+++ b/Documentation/admin-guide/l1tf.rst -@@ -19,8 +19,6 @@ vulnerability is not present on: - - A range of Intel ATOM processors (Cedarview, Cloverview, Lincroft, - Penwell, Pineview, Silvermont, Airmont, Merrifield) - -- - The Intel Core Duo Yonah variants (2006 - 2008) -- - - The Intel XEON PHI family - - - Intel processors which have the ARCH_CAP_RDCL_NO bit set in the -From foo@baz Tue Aug 14 13:43:11 CEST 2018 -From: Paolo Bonzini -Date: Sun, 5 Aug 2018 16:07:45 +0200 -Subject: x86/speculation: Simplify sysfs report of VMX L1TF vulnerability - -From: Paolo Bonzini - -commit ea156d192f5257a5bf393d33910d3b481bf8a401 upstream - -Three changes to the content of the sysfs file: - - - If EPT is disabled, L1TF cannot be exploited even across threads on the - same core, and SMT is irrelevant. - - - If mitigation is completely disabled, and SMT is enabled, print "vulnerable" - instead of "vulnerable, SMT vulnerable" - - - Reorder the two parts so that the main vulnerability state comes first - and the detail on SMT is second. - -Signed-off-by: Paolo Bonzini -Signed-off-by: Thomas Gleixner -Signed-off-by: Greg Kroah-Hartman ---- - arch/x86/kernel/cpu/bugs.c | 12 +++++++++--- - 1 file changed, 9 insertions(+), 3 deletions(-) - ---- a/arch/x86/kernel/cpu/bugs.c -+++ b/arch/x86/kernel/cpu/bugs.c -@@ -738,9 +738,15 @@ static ssize_t l1tf_show_state(char *buf - if (l1tf_vmx_mitigation == VMENTER_L1D_FLUSH_AUTO) - return sprintf(buf, "%s\n", L1TF_DEFAULT_MSG); - -- return sprintf(buf, "%s; VMX: SMT %s, L1D %s\n", L1TF_DEFAULT_MSG, -- cpu_smt_control == CPU_SMT_ENABLED ? "vulnerable" : "disabled", -- l1tf_vmx_states[l1tf_vmx_mitigation]); -+ if (l1tf_vmx_mitigation == VMENTER_L1D_FLUSH_EPT_DISABLED || -+ (l1tf_vmx_mitigation == VMENTER_L1D_FLUSH_NEVER && -+ cpu_smt_control == CPU_SMT_ENABLED)) -+ return sprintf(buf, "%s; VMX: %s\n", L1TF_DEFAULT_MSG, -+ l1tf_vmx_states[l1tf_vmx_mitigation]); -+ -+ return sprintf(buf, "%s; VMX: %s, SMT %s\n", L1TF_DEFAULT_MSG, -+ l1tf_vmx_states[l1tf_vmx_mitigation], -+ cpu_smt_control == CPU_SMT_ENABLED ? "vulnerable" : "disabled"); - } - #else - static ssize_t l1tf_show_state(char *buf) -From foo@baz Tue Aug 14 13:43:11 CEST 2018 -From: Paolo Bonzini -Date: Sun, 5 Aug 2018 16:07:46 +0200 -Subject: x86/speculation: Use ARCH_CAPABILITIES to skip L1D flush on vmentry - -From: Paolo Bonzini - -commit 8e0b2b916662e09dd4d09e5271cdf214c6b80e62 upstream - -Bit 3 of ARCH_CAPABILITIES tells a hypervisor that L1D flush on vmentry is -not needed. Add a new value to enum vmx_l1d_flush_state, which is used -either if there is no L1TF bug at all, or if bit 3 is set in ARCH_CAPABILITIES. - -Signed-off-by: Paolo Bonzini -Signed-off-by: Thomas Gleixner -Signed-off-by: Greg Kroah-Hartman ---- - arch/x86/include/asm/msr-index.h | 1 + - arch/x86/include/asm/vmx.h | 1 + - arch/x86/kernel/cpu/bugs.c | 1 + - arch/x86/kvm/vmx.c | 10 ++++++++++ - 4 files changed, 13 insertions(+) - ---- a/arch/x86/include/asm/msr-index.h -+++ b/arch/x86/include/asm/msr-index.h -@@ -70,6 +70,7 @@ - #define MSR_IA32_ARCH_CAPABILITIES 0x0000010a - #define ARCH_CAP_RDCL_NO (1 << 0) /* Not susceptible to Meltdown */ - #define ARCH_CAP_IBRS_ALL (1 << 1) /* Enhanced IBRS support */ -+#define ARCH_CAP_SKIP_VMENTRY_L1DFLUSH (1 << 3) /* Skip L1D flush on vmentry */ - #define ARCH_CAP_SSB_NO (1 << 4) /* - * Not susceptible to Speculative Store Bypass - * attack, so no Speculative Store Bypass ---- a/arch/x86/include/asm/vmx.h -+++ b/arch/x86/include/asm/vmx.h -@@ -580,6 +580,7 @@ enum vmx_l1d_flush_state { - VMENTER_L1D_FLUSH_COND, - VMENTER_L1D_FLUSH_ALWAYS, - VMENTER_L1D_FLUSH_EPT_DISABLED, -+ VMENTER_L1D_FLUSH_NOT_REQUIRED, - }; - - extern enum vmx_l1d_flush_state l1tf_vmx_mitigation; ---- a/arch/x86/kernel/cpu/bugs.c -+++ b/arch/x86/kernel/cpu/bugs.c -@@ -731,6 +731,7 @@ static const char *l1tf_vmx_states[] = { - [VMENTER_L1D_FLUSH_COND] = "conditional cache flushes", - [VMENTER_L1D_FLUSH_ALWAYS] = "cache flushes", - [VMENTER_L1D_FLUSH_EPT_DISABLED] = "EPT disabled", -+ [VMENTER_L1D_FLUSH_NOT_REQUIRED] = "flush not necessary" - }; - - static ssize_t l1tf_show_state(char *buf) ---- a/arch/x86/kvm/vmx.c -+++ b/arch/x86/kvm/vmx.c -@@ -218,6 +218,16 @@ static int vmx_setup_l1d_flush(enum vmx_ - return 0; - } - -+ if (boot_cpu_has(X86_FEATURE_ARCH_CAPABILITIES)) { -+ u64 msr; -+ -+ rdmsrl(MSR_IA32_ARCH_CAPABILITIES, msr); -+ if (msr & ARCH_CAP_SKIP_VMENTRY_L1DFLUSH) { -+ l1tf_vmx_mitigation = VMENTER_L1D_FLUSH_NOT_REQUIRED; -+ return 0; -+ } -+ } -+ - /* If set to auto use the default l1tf mitigation method */ - if (l1tf == VMENTER_L1D_FLUSH_AUTO) { - switch (l1tf_mitigation) { -From foo@baz Tue Aug 14 13:43:11 CEST 2018 -From: Paolo Bonzini -Date: Sun, 5 Aug 2018 16:07:47 +0200 -Subject: KVM: VMX: Tell the nested hypervisor to skip L1D flush on vmentry - -From: Paolo Bonzini - -commit 5b76a3cff011df2dcb6186c965a2e4d809a05ad4 upstream - -When nested virtualization is in use, VMENTER operations from the nested -hypervisor into the nested guest will always be processed by the bare metal -hypervisor, and KVM's "conditional cache flushes" mode in particular does a -flush on nested vmentry. Therefore, include the "skip L1D flush on -vmentry" bit in KVM's suggested ARCH_CAPABILITIES setting. - -Add the relevant Documentation. - -Signed-off-by: Paolo Bonzini -Signed-off-by: Thomas Gleixner -Signed-off-by: Greg Kroah-Hartman ---- - Documentation/admin-guide/l1tf.rst | 21 +++++++++++++++++++++ - arch/x86/include/asm/kvm_host.h | 1 + - arch/x86/kvm/vmx.c | 3 +-- - arch/x86/kvm/x86.c | 26 +++++++++++++++++++++++++- - 4 files changed, 48 insertions(+), 3 deletions(-) - ---- a/Documentation/admin-guide/l1tf.rst -+++ b/Documentation/admin-guide/l1tf.rst -@@ -546,6 +546,27 @@ available: - EPT can be disabled in the hypervisor via the 'kvm-intel.ept' - parameter. - -+3.4. Nested virtual machines -+"""""""""""""""""""""""""""" -+ -+When nested virtualization is in use, three operating systems are involved: -+the bare metal hypervisor, the nested hypervisor and the nested virtual -+machine. VMENTER operations from the nested hypervisor into the nested -+guest will always be processed by the bare metal hypervisor. If KVM is the -+bare metal hypervisor it wiil: -+ -+ - Flush the L1D cache on every switch from the nested hypervisor to the -+ nested virtual machine, so that the nested hypervisor's secrets are not -+ exposed to the nested virtual machine; -+ -+ - Flush the L1D cache on every switch from the nested virtual machine to -+ the nested hypervisor; this is a complex operation, and flushing the L1D -+ cache avoids that the bare metal hypervisor's secrets are exposed to the -+ nested virtual machine; -+ -+ - Instruct the nested hypervisor to not perform any L1D cache flush. This -+ is an optimization to avoid double L1D flushing. -+ - - .. _default_mitigations: - ---- a/arch/x86/include/asm/kvm_host.h -+++ b/arch/x86/include/asm/kvm_host.h -@@ -1415,6 +1415,7 @@ int kvm_cpu_get_interrupt(struct kvm_vcp - void kvm_vcpu_reset(struct kvm_vcpu *vcpu, bool init_event); - void kvm_vcpu_reload_apic_access_page(struct kvm_vcpu *vcpu); - -+u64 kvm_get_arch_capabilities(void); - void kvm_define_shared_msr(unsigned index, u32 msr); - int kvm_set_shared_msr(unsigned index, u64 val, u64 mask); - ---- a/arch/x86/kvm/vmx.c -+++ b/arch/x86/kvm/vmx.c -@@ -6232,8 +6232,7 @@ static void vmx_vcpu_setup(struct vcpu_v - ++vmx->nmsrs; - } - -- if (boot_cpu_has(X86_FEATURE_ARCH_CAPABILITIES)) -- rdmsrl(MSR_IA32_ARCH_CAPABILITIES, vmx->arch_capabilities); -+ vmx->arch_capabilities = kvm_get_arch_capabilities(); - - vm_exit_controls_init(vmx, vmcs_config.vmexit_ctrl); - ---- a/arch/x86/kvm/x86.c -+++ b/arch/x86/kvm/x86.c -@@ -1098,11 +1098,35 @@ static u32 msr_based_features[] = { - - static unsigned int num_msr_based_features; - -+u64 kvm_get_arch_capabilities(void) -+{ -+ u64 data; -+ -+ rdmsrl_safe(MSR_IA32_ARCH_CAPABILITIES, &data); -+ -+ /* -+ * If we're doing cache flushes (either "always" or "cond") -+ * we will do one whenever the guest does a vmlaunch/vmresume. -+ * If an outer hypervisor is doing the cache flush for us -+ * (VMENTER_L1D_FLUSH_NESTED_VM), we can safely pass that -+ * capability to the guest too, and if EPT is disabled we're not -+ * vulnerable. Overall, only VMENTER_L1D_FLUSH_NEVER will -+ * require a nested hypervisor to do a flush of its own. -+ */ -+ if (l1tf_vmx_mitigation != VMENTER_L1D_FLUSH_NEVER) -+ data |= ARCH_CAP_SKIP_VMENTRY_L1DFLUSH; -+ -+ return data; -+} -+EXPORT_SYMBOL_GPL(kvm_get_arch_capabilities); -+ - static int kvm_get_msr_feature(struct kvm_msr_entry *msr) - { - switch (msr->index) { -- case MSR_IA32_UCODE_REV: - case MSR_IA32_ARCH_CAPABILITIES: -+ msr->data = kvm_get_arch_capabilities(); -+ break; -+ case MSR_IA32_UCODE_REV: - rdmsrl_safe(msr->index, &msr->data); - break; - default: -From foo@baz Tue Aug 14 13:43:11 CEST 2018 -From: Thomas Gleixner -Date: Tue, 7 Aug 2018 08:19:57 +0200 -Subject: cpu/hotplug: Fix SMT supported evaluation - -From: Thomas Gleixner - -commit bc2d8d262cba5736332cbc866acb11b1c5748aa9 upstream - -Josh reported that the late SMT evaluation in cpu_smt_state_init() sets -cpu_smt_control to CPU_SMT_NOT_SUPPORTED in case that 'nosmt' was supplied -on the kernel command line as it cannot differentiate between SMT disabled -by BIOS and SMT soft disable via 'nosmt'. That wreckages the state and -makes the sysfs interface unusable. - -Rework this so that during bringup of the non boot CPUs the availability of -SMT is determined in cpu_smt_allowed(). If a newly booted CPU is not a -'primary' thread then set the local cpu_smt_available marker and evaluate -this explicitely right after the initial SMP bringup has finished. - -SMT evaulation on x86 is a trainwreck as the firmware has all the -information _before_ booting the kernel, but there is no interface to query -it. - -Fixes: 73d5e2b47264 ("cpu/hotplug: detect SMT disabled by BIOS") -Reported-by: Josh Poimboeuf -Signed-off-by: Thomas Gleixner -Signed-off-by: Greg Kroah-Hartman ---- - arch/x86/kernel/cpu/bugs.c | 2 +- - include/linux/cpu.h | 2 ++ - kernel/cpu.c | 41 ++++++++++++++++++++++++++++------------- - kernel/smp.c | 2 ++ - 4 files changed, 33 insertions(+), 14 deletions(-) - ---- a/arch/x86/kernel/cpu/bugs.c -+++ b/arch/x86/kernel/cpu/bugs.c -@@ -62,7 +62,7 @@ void __init check_bugs(void) - * identify_boot_cpu() initialized SMT support information, let the - * core code know. - */ -- cpu_smt_check_topology(); -+ cpu_smt_check_topology_early(); - - if (!IS_ENABLED(CONFIG_SMP)) { - pr_info("CPU: "); ---- a/include/linux/cpu.h -+++ b/include/linux/cpu.h -@@ -178,10 +178,12 @@ enum cpuhp_smt_control { - #if defined(CONFIG_SMP) && defined(CONFIG_HOTPLUG_SMT) - extern enum cpuhp_smt_control cpu_smt_control; - extern void cpu_smt_disable(bool force); -+extern void cpu_smt_check_topology_early(void); - extern void cpu_smt_check_topology(void); - #else - # define cpu_smt_control (CPU_SMT_ENABLED) - static inline void cpu_smt_disable(bool force) { } -+static inline void cpu_smt_check_topology_early(void) { } - static inline void cpu_smt_check_topology(void) { } - #endif - ---- a/kernel/cpu.c -+++ b/kernel/cpu.c -@@ -347,6 +347,8 @@ EXPORT_SYMBOL_GPL(cpu_hotplug_enable); - enum cpuhp_smt_control cpu_smt_control __read_mostly = CPU_SMT_ENABLED; - EXPORT_SYMBOL_GPL(cpu_smt_control); - -+static bool cpu_smt_available __read_mostly; -+ - void __init cpu_smt_disable(bool force) - { - if (cpu_smt_control == CPU_SMT_FORCE_DISABLED || -@@ -363,14 +365,28 @@ void __init cpu_smt_disable(bool force) - - /* - * The decision whether SMT is supported can only be done after the full -- * CPU identification. Called from architecture code. -+ * CPU identification. Called from architecture code before non boot CPUs -+ * are brought up. - */ --void __init cpu_smt_check_topology(void) -+void __init cpu_smt_check_topology_early(void) - { - if (!topology_smt_supported()) - cpu_smt_control = CPU_SMT_NOT_SUPPORTED; - } - -+/* -+ * If SMT was disabled by BIOS, detect it here, after the CPUs have been -+ * brought online. This ensures the smt/l1tf sysfs entries are consistent -+ * with reality. cpu_smt_available is set to true during the bringup of non -+ * boot CPUs when a SMT sibling is detected. Note, this may overwrite -+ * cpu_smt_control's previous setting. -+ */ -+void __init cpu_smt_check_topology(void) -+{ -+ if (!cpu_smt_available) -+ cpu_smt_control = CPU_SMT_NOT_SUPPORTED; -+} -+ - static int __init smt_cmdline_disable(char *str) - { - cpu_smt_disable(str && !strcmp(str, "force")); -@@ -380,10 +396,18 @@ early_param("nosmt", smt_cmdline_disable - - static inline bool cpu_smt_allowed(unsigned int cpu) - { -- if (cpu_smt_control == CPU_SMT_ENABLED) -+ if (topology_is_primary_thread(cpu)) - return true; - -- if (topology_is_primary_thread(cpu)) -+ /* -+ * If the CPU is not a 'primary' thread and the booted_once bit is -+ * set then the processor has SMT support. Store this information -+ * for the late check of SMT support in cpu_smt_check_topology(). -+ */ -+ if (per_cpu(cpuhp_state, cpu).booted_once) -+ cpu_smt_available = true; -+ -+ if (cpu_smt_control == CPU_SMT_ENABLED) - return true; - - /* -@@ -2125,15 +2149,6 @@ static const struct attribute_group cpuh - - static int __init cpu_smt_state_init(void) - { -- /* -- * If SMT was disabled by BIOS, detect it here, after the CPUs have -- * been brought online. This ensures the smt/l1tf sysfs entries are -- * consistent with reality. Note this may overwrite cpu_smt_control's -- * previous setting. -- */ -- if (topology_max_smt_threads() == 1) -- cpu_smt_control = CPU_SMT_NOT_SUPPORTED; -- - return sysfs_create_group(&cpu_subsys.dev_root->kobj, - &cpuhp_smt_attr_group); - } ---- a/kernel/smp.c -+++ b/kernel/smp.c -@@ -584,6 +584,8 @@ void __init smp_init(void) - num_nodes, (num_nodes > 1 ? "s" : ""), - num_cpus, (num_cpus > 1 ? "s" : "")); - -+ /* Final decision about SMT support */ -+ cpu_smt_check_topology(); - /* Any cleanup work */ - smp_cpus_done(setup_max_cpus); - } -From foo@baz Tue Aug 14 13:43:11 CEST 2018 -From: Andi Kleen -Date: Tue, 7 Aug 2018 15:09:36 -0700 -Subject: x86/speculation/l1tf: Invert all not present mappings - -From: Andi Kleen - -commit f22cc87f6c1f771b57c407555cfefd811cdd9507 upstream - -For kernel mappings PAGE_PROTNONE is not necessarily set for a non present -mapping, but the inversion logic explicitely checks for !PRESENT and -PROT_NONE. - -Remove the PROT_NONE check and make the inversion unconditional for all not -present mappings. - -Signed-off-by: Andi Kleen -Signed-off-by: Thomas Gleixner -Signed-off-by: Greg Kroah-Hartman ---- - arch/x86/include/asm/pgtable-invert.h | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/arch/x86/include/asm/pgtable-invert.h -+++ b/arch/x86/include/asm/pgtable-invert.h -@@ -6,7 +6,7 @@ - - static inline bool __pte_needs_invert(u64 val) - { -- return (val & (_PAGE_PRESENT|_PAGE_PROTNONE)) == _PAGE_PROTNONE; -+ return !(val & _PAGE_PRESENT); - } - - /* Get a mask to xor with the page table entry to get the correct pfn. */ -From foo@baz Tue Aug 14 13:43:11 CEST 2018 -From: Andi Kleen -Date: Tue, 7 Aug 2018 15:09:37 -0700 -Subject: x86/speculation/l1tf: Make pmd/pud_mknotpresent() invert - -From: Andi Kleen - -commit 0768f91530ff46683e0b372df14fd79fe8d156e5 upstream - -Some cases in THP like: - - MADV_FREE - - mprotect - - split - -mark the PMD non present for temporarily to prevent races. The window for -an L1TF attack in these contexts is very small, but it wants to be fixed -for correctness sake. - -Use the proper low level functions for pmd/pud_mknotpresent() to address -this. - -Signed-off-by: Andi Kleen -Signed-off-by: Thomas Gleixner -Signed-off-by: Greg Kroah-Hartman ---- - arch/x86/include/asm/pgtable.h | 22 ++++++++++++---------- - 1 file changed, 12 insertions(+), 10 deletions(-) - ---- a/arch/x86/include/asm/pgtable.h -+++ b/arch/x86/include/asm/pgtable.h -@@ -410,11 +410,6 @@ static inline pmd_t pmd_mkwrite(pmd_t pm - return pmd_set_flags(pmd, _PAGE_RW); - } - --static inline pmd_t pmd_mknotpresent(pmd_t pmd) --{ -- return pmd_clear_flags(pmd, _PAGE_PRESENT | _PAGE_PROTNONE); --} -- - static inline pud_t pud_set_flags(pud_t pud, pudval_t set) - { - pudval_t v = native_pud_val(pud); -@@ -469,11 +464,6 @@ static inline pud_t pud_mkwrite(pud_t pu - return pud_set_flags(pud, _PAGE_RW); - } - --static inline pud_t pud_mknotpresent(pud_t pud) --{ -- return pud_clear_flags(pud, _PAGE_PRESENT | _PAGE_PROTNONE); --} -- - #ifdef CONFIG_HAVE_ARCH_SOFT_DIRTY - static inline int pte_soft_dirty(pte_t pte) - { -@@ -577,6 +567,18 @@ static inline pud_t pfn_pud(unsigned lon - return __pud(pfn | check_pgprot(pgprot)); - } - -+static inline pmd_t pmd_mknotpresent(pmd_t pmd) -+{ -+ return pfn_pmd(pmd_pfn(pmd), -+ __pgprot(pmd_flags(pmd) & ~(_PAGE_PRESENT|_PAGE_PROTNONE))); -+} -+ -+static inline pud_t pud_mknotpresent(pud_t pud) -+{ -+ return pfn_pud(pud_pfn(pud), -+ __pgprot(pud_flags(pud) & ~(_PAGE_PRESENT|_PAGE_PROTNONE))); -+} -+ - static inline u64 flip_protnone_guard(u64 oldval, u64 val, u64 mask); - - static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) -From foo@baz Tue Aug 14 13:43:11 CEST 2018 -From: Andi Kleen -Date: Tue, 7 Aug 2018 15:09:39 -0700 -Subject: x86/mm/pat: Make set_memory_np() L1TF safe - -From: Andi Kleen - -commit 958f79b9ee55dfaf00c8106ed1c22a2919e0028b upstream - -set_memory_np() is used to mark kernel mappings not present, but it has -it's own open coded mechanism which does not have the L1TF protection of -inverting the address bits. - -Replace the open coded PTE manipulation with the L1TF protecting low level -PTE routines. - -Passes the CPA self test. - -Signed-off-by: Andi Kleen -Signed-off-by: Thomas Gleixner -Signed-off-by: Greg Kroah-Hartman ---- - arch/x86/mm/pageattr.c | 8 ++++---- - 1 file changed, 4 insertions(+), 4 deletions(-) - ---- a/arch/x86/mm/pageattr.c -+++ b/arch/x86/mm/pageattr.c -@@ -1014,8 +1014,8 @@ static long populate_pmd(struct cpa_data - - pmd = pmd_offset(pud, start); - -- set_pmd(pmd, __pmd(cpa->pfn << PAGE_SHIFT | _PAGE_PSE | -- massage_pgprot(pmd_pgprot))); -+ set_pmd(pmd, pmd_mkhuge(pfn_pmd(cpa->pfn, -+ canon_pgprot(pmd_pgprot)))); - - start += PMD_SIZE; - cpa->pfn += PMD_SIZE >> PAGE_SHIFT; -@@ -1087,8 +1087,8 @@ static int populate_pud(struct cpa_data - * Map everything starting from the Gb boundary, possibly with 1G pages - */ - while (boot_cpu_has(X86_FEATURE_GBPAGES) && end - start >= PUD_SIZE) { -- set_pud(pud, __pud(cpa->pfn << PAGE_SHIFT | _PAGE_PSE | -- massage_pgprot(pud_pgprot))); -+ set_pud(pud, pud_mkhuge(pfn_pud(cpa->pfn, -+ canon_pgprot(pud_pgprot)))); - - start += PUD_SIZE; - cpa->pfn += PUD_SIZE >> PAGE_SHIFT; -From foo@baz Tue Aug 14 13:43:11 CEST 2018 -From: Andi Kleen -Date: Tue, 7 Aug 2018 15:09:38 -0700 -Subject: x86/mm/kmmio: Make the tracer robust against L1TF - -From: Andi Kleen - -commit 1063711b57393c1999248cccb57bebfaf16739e7 upstream - -The mmio tracer sets io mapping PTEs and PMDs to non present when enabled -without inverting the address bits, which makes the PTE entry vulnerable -for L1TF. - -Make it use the right low level macros to actually invert the address bits -to protect against L1TF. - -In principle this could be avoided because MMIO tracing is not likely to be -enabled on production machines, but the fix is straigt forward and for -consistency sake it's better to get rid of the open coded PTE manipulation. - -Signed-off-by: Andi Kleen -Signed-off-by: Thomas Gleixner -Signed-off-by: Greg Kroah-Hartman ---- - arch/x86/mm/kmmio.c | 25 +++++++++++++++---------- - 1 file changed, 15 insertions(+), 10 deletions(-) - ---- a/arch/x86/mm/kmmio.c -+++ b/arch/x86/mm/kmmio.c -@@ -126,24 +126,29 @@ static struct kmmio_fault_page *get_kmmi - - static void clear_pmd_presence(pmd_t *pmd, bool clear, pmdval_t *old) - { -+ pmd_t new_pmd; - pmdval_t v = pmd_val(*pmd); - if (clear) { -- *old = v & _PAGE_PRESENT; -- v &= ~_PAGE_PRESENT; -- } else /* presume this has been called with clear==true previously */ -- v |= *old; -- set_pmd(pmd, __pmd(v)); -+ *old = v; -+ new_pmd = pmd_mknotpresent(*pmd); -+ } else { -+ /* Presume this has been called with clear==true previously */ -+ new_pmd = __pmd(*old); -+ } -+ set_pmd(pmd, new_pmd); - } - - static void clear_pte_presence(pte_t *pte, bool clear, pteval_t *old) - { - pteval_t v = pte_val(*pte); - if (clear) { -- *old = v & _PAGE_PRESENT; -- v &= ~_PAGE_PRESENT; -- } else /* presume this has been called with clear==true previously */ -- v |= *old; -- set_pte_atomic(pte, __pte(v)); -+ *old = v; -+ /* Nothing should care about address */ -+ pte_clear(&init_mm, 0, pte); -+ } else { -+ /* Presume this has been called with clear==true previously */ -+ set_pte_atomic(pte, __pte(*old)); -+ } - } - - static int clear_page_presence(struct kmmio_fault_page *f, bool clear) -From foo@baz Tue Aug 14 13:43:11 CEST 2018 -From: Arnaldo Carvalho de Melo -Date: Fri, 1 Jun 2018 10:42:31 -0300 -Subject: tools headers: Synchronize prctl.h ABI header - -From: Arnaldo Carvalho de Melo - -commit 63b89a19cc9ef911dcc64d41b60930c346eee0c0 upstream - -To pick up changes from: - - $ git log --oneline -2 -i include/uapi/linux/prctl.h - 356e4bfff2c5 prctl: Add force disable speculation - b617cfc85816 prctl: Add speculation control prctls - - $ tools/perf/trace/beauty/prctl_option.sh > before.c - $ cp include/uapi/linux/prctl.h tools/include/uapi/linux/prctl.h - $ tools/perf/trace/beauty/prctl_option.sh > after.c - $ diff -u before.c after.c -# --- before.c 2018-06-01 10:39:53.834073962 -0300 -# +++ after.c 2018-06-01 10:42:11.307985394 -0300 - @@ -35,6 +35,8 @@ - [42] = "GET_THP_DISABLE", - [45] = "SET_FP_MODE", - [46] = "GET_FP_MODE", - + [52] = "GET_SPECULATION_CTRL", - + [53] = "SET_SPECULATION_CTRL", - }; - static const char *prctl_set_mm_options[] = { - [1] = "START_CODE", - $ - -This will be used by 'perf trace' to show these strings when beautifying -the prctl syscall args. At some point we'll be able to say something -like: - - 'perf trace --all-cpus -e prctl(option=*SPEC*)' - -To filter by arg by name. - - This silences this warning when building tools/perf: - - Warning: Kernel ABI header at 'tools/include/uapi/linux/prctl.h' differs from latest version at 'include/uapi/linux/prctl.h' - -Cc: Adrian Hunter -Cc: David Ahern -Cc: Jiri Olsa -Cc: Namhyung Kim -Cc: Thomas Gleixner -Cc: Wang Nan -Link: https://lkml.kernel.org/n/tip-zztsptwhc264r8wg44tqh5gp@git.kernel.org -Signed-off-by: Arnaldo Carvalho de Melo -Signed-off-by: David Woodhouse -Signed-off-by: Greg Kroah-Hartman ---- - tools/include/uapi/linux/prctl.h | 12 ++++++++++++ - 1 file changed, 12 insertions(+) - ---- a/tools/include/uapi/linux/prctl.h -+++ b/tools/include/uapi/linux/prctl.h -@@ -207,4 +207,16 @@ struct prctl_mm_map { - # define PR_SVE_VL_LEN_MASK 0xffff - # define PR_SVE_VL_INHERIT (1 << 17) /* inherit across exec */ - -+/* Per task speculation control */ -+#define PR_GET_SPECULATION_CTRL 52 -+#define PR_SET_SPECULATION_CTRL 53 -+/* Speculation control variants */ -+# define PR_SPEC_STORE_BYPASS 0 -+/* Return and control values for PR_SET/GET_SPECULATION_CTRL */ -+# define PR_SPEC_NOT_AFFECTED 0 -+# define PR_SPEC_PRCTL (1UL << 0) -+# define PR_SPEC_ENABLE (1UL << 1) -+# define PR_SPEC_DISABLE (1UL << 2) -+# define PR_SPEC_FORCE_DISABLE (1UL << 3) -+ - #endif /* _LINUX_PRCTL_H */ -From foo@baz Tue Aug 14 13:43:11 CEST 2018 -From: David Woodhouse -Date: Wed, 8 Aug 2018 11:00:16 +0100 -Subject: tools headers: Synchronise x86 cpufeatures.h for L1TF additions - -From: David Woodhouse - -commit e24f14b0ff985f3e09e573ba1134bfdf42987e05 upstream - -[ ... and some older changes in the 4.17.y backport too ...] -Signed-off-by: David Woodhouse -Signed-off-by: Greg Kroah-Hartman ---- - tools/arch/x86/include/asm/cpufeatures.h | 23 +++++++++++++++++------ - 1 file changed, 17 insertions(+), 6 deletions(-) - ---- a/tools/arch/x86/include/asm/cpufeatures.h -+++ b/tools/arch/x86/include/asm/cpufeatures.h -@@ -198,7 +198,6 @@ - #define X86_FEATURE_CAT_L2 ( 7*32+ 5) /* Cache Allocation Technology L2 */ - #define X86_FEATURE_CDP_L3 ( 7*32+ 6) /* Code and Data Prioritization L3 */ - #define X86_FEATURE_INVPCID_SINGLE ( 7*32+ 7) /* Effectively INVPCID && CR4.PCIDE=1 */ -- - #define X86_FEATURE_HW_PSTATE ( 7*32+ 8) /* AMD HW-PState */ - #define X86_FEATURE_PROC_FEEDBACK ( 7*32+ 9) /* AMD ProcFeedbackInterface */ - #define X86_FEATURE_SME ( 7*32+10) /* AMD Secure Memory Encryption */ -@@ -207,13 +206,20 @@ - #define X86_FEATURE_RETPOLINE_AMD ( 7*32+13) /* "" AMD Retpoline mitigation for Spectre variant 2 */ - #define X86_FEATURE_INTEL_PPIN ( 7*32+14) /* Intel Processor Inventory Number */ - #define X86_FEATURE_CDP_L2 ( 7*32+15) /* Code and Data Prioritization L2 */ -- -+#define X86_FEATURE_MSR_SPEC_CTRL ( 7*32+16) /* "" MSR SPEC_CTRL is implemented */ -+#define X86_FEATURE_SSBD ( 7*32+17) /* Speculative Store Bypass Disable */ - #define X86_FEATURE_MBA ( 7*32+18) /* Memory Bandwidth Allocation */ - #define X86_FEATURE_RSB_CTXSW ( 7*32+19) /* "" Fill RSB on context switches */ - #define X86_FEATURE_SEV ( 7*32+20) /* AMD Secure Encrypted Virtualization */ -- - #define X86_FEATURE_USE_IBPB ( 7*32+21) /* "" Indirect Branch Prediction Barrier enabled */ - #define X86_FEATURE_USE_IBRS_FW ( 7*32+22) /* "" Use IBRS during runtime firmware calls */ -+#define X86_FEATURE_SPEC_STORE_BYPASS_DISABLE ( 7*32+23) /* "" Disable Speculative Store Bypass. */ -+#define X86_FEATURE_LS_CFG_SSBD ( 7*32+24) /* "" AMD SSBD implementation via LS_CFG MSR */ -+#define X86_FEATURE_IBRS ( 7*32+25) /* Indirect Branch Restricted Speculation */ -+#define X86_FEATURE_IBPB ( 7*32+26) /* Indirect Branch Prediction Barrier */ -+#define X86_FEATURE_STIBP ( 7*32+27) /* Single Thread Indirect Branch Predictors */ -+#define X86_FEATURE_ZEN ( 7*32+28) /* "" CPU is AMD family 0x17 (Zen) */ -+#define X86_FEATURE_L1TF_PTEINV ( 7*32+29) /* "" L1TF workaround PTE inversion */ - - /* Virtualization flags: Linux defined, word 8 */ - #define X86_FEATURE_TPR_SHADOW ( 8*32+ 0) /* Intel TPR Shadow */ -@@ -274,9 +280,10 @@ - #define X86_FEATURE_CLZERO (13*32+ 0) /* CLZERO instruction */ - #define X86_FEATURE_IRPERF (13*32+ 1) /* Instructions Retired Count */ - #define X86_FEATURE_XSAVEERPTR (13*32+ 2) /* Always save/restore FP error pointers */ --#define X86_FEATURE_IBPB (13*32+12) /* Indirect Branch Prediction Barrier */ --#define X86_FEATURE_IBRS (13*32+14) /* Indirect Branch Restricted Speculation */ --#define X86_FEATURE_STIBP (13*32+15) /* Single Thread Indirect Branch Predictors */ -+#define X86_FEATURE_AMD_IBPB (13*32+12) /* "" Indirect Branch Prediction Barrier */ -+#define X86_FEATURE_AMD_IBRS (13*32+14) /* "" Indirect Branch Restricted Speculation */ -+#define X86_FEATURE_AMD_STIBP (13*32+15) /* "" Single Thread Indirect Branch Predictors */ -+#define X86_FEATURE_VIRT_SSBD (13*32+25) /* Virtualized Speculative Store Bypass Disable */ - - /* Thermal and Power Management Leaf, CPUID level 0x00000006 (EAX), word 14 */ - #define X86_FEATURE_DTHERM (14*32+ 0) /* Digital Thermal Sensor */ -@@ -333,7 +340,9 @@ - #define X86_FEATURE_PCONFIG (18*32+18) /* Intel PCONFIG */ - #define X86_FEATURE_SPEC_CTRL (18*32+26) /* "" Speculation Control (IBRS + IBPB) */ - #define X86_FEATURE_INTEL_STIBP (18*32+27) /* "" Single Thread Indirect Branch Predictors */ -+#define X86_FEATURE_FLUSH_L1D (18*32+28) /* Flush L1D cache */ - #define X86_FEATURE_ARCH_CAPABILITIES (18*32+29) /* IA32_ARCH_CAPABILITIES MSR (Intel) */ -+#define X86_FEATURE_SPEC_CTRL_SSBD (18*32+31) /* "" Speculative Store Bypass Disable */ - - /* - * BUG word(s) -@@ -363,5 +372,7 @@ - #define X86_BUG_CPU_MELTDOWN X86_BUG(14) /* CPU is affected by meltdown attack and needs kernel page table isolation */ - #define X86_BUG_SPECTRE_V1 X86_BUG(15) /* CPU is affected by Spectre variant 1 attack with conditional branches */ - #define X86_BUG_SPECTRE_V2 X86_BUG(16) /* CPU is affected by Spectre variant 2 attack with indirect branches */ -+#define X86_BUG_SPEC_STORE_BYPASS X86_BUG(17) /* CPU is affected by speculative store bypass attack */ -+#define X86_BUG_L1TF X86_BUG(18) /* CPU is affected by L1 Terminal Fault */ - - #endif /* _ASM_X86_CPUFEATURES_H */ -From foo@baz Tue Aug 14 13:43:11 CEST 2018 -From: Josh Poimboeuf -Date: Fri, 10 Aug 2018 08:31:10 +0100 -Subject: x86/microcode: Allow late microcode loading with SMT disabled - -From: Josh Poimboeuf - -commit 07d981ad4cf1e78361c6db1c28ee5ba105f96cc1 upstream - -The kernel unnecessarily prevents late microcode loading when SMT is -disabled. It should be safe to allow it if all the primary threads are -online. - -Signed-off-by: Josh Poimboeuf -Acked-by: Borislav Petkov -Signed-off-by: David Woodhouse -Signed-off-by: Greg Kroah-Hartman ---- - arch/x86/kernel/cpu/microcode/core.c | 16 ++++++++++++---- - 1 file changed, 12 insertions(+), 4 deletions(-) - ---- a/arch/x86/kernel/cpu/microcode/core.c -+++ b/arch/x86/kernel/cpu/microcode/core.c -@@ -509,12 +509,20 @@ static struct platform_device *microcode - - static int check_online_cpus(void) - { -- if (num_online_cpus() == num_present_cpus()) -- return 0; -+ unsigned int cpu; - -- pr_err("Not all CPUs online, aborting microcode update.\n"); -+ /* -+ * Make sure all CPUs are online. It's fine for SMT to be disabled if -+ * all the primary threads are still online. -+ */ -+ for_each_present_cpu(cpu) { -+ if (topology_is_primary_thread(cpu) && !cpu_online(cpu)) { -+ pr_err("Not all CPUs online, aborting microcode update.\n"); -+ return -EINVAL; -+ } -+ } - -- return -EINVAL; -+ return 0; - } - - static atomic_t late_cpus_in; -From d0055f351e647f33f3b0329bff022213bf8aa085 Mon Sep 17 00:00:00 2001 -From: Vlastimil Babka -Date: Tue, 14 Aug 2018 23:38:57 +0200 -Subject: x86/smp: fix non-SMP broken build due to redefinition of apic_id_is_primary_thread -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -From: Vlastimil Babka - -commit d0055f351e647f33f3b0329bff022213bf8aa085 upstream. - -The function has an inline "return false;" definition with CONFIG_SMP=n -but the "real" definition is also visible leading to "redefinition of -‘apic_id_is_primary_thread’" compiler error. - -Guard it with #ifdef CONFIG_SMP - -Signed-off-by: Vlastimil Babka -Fixes: 6a4d2657e048 ("x86/smp: Provide topology_is_primary_thread()") -Cc: stable@vger.kernel.org -Signed-off-by: Linus Torvalds -Signed-off-by: Greg Kroah-Hartman - ---- - arch/x86/kernel/apic/apic.c | 2 ++ - 1 file changed, 2 insertions(+) - ---- a/arch/x86/kernel/apic/apic.c -+++ b/arch/x86/kernel/apic/apic.c -@@ -2193,6 +2193,7 @@ static int cpuid_to_apicid[] = { - [0 ... NR_CPUS - 1] = -1, - }; - -+#ifdef CONFIG_SMP - /** - * apic_id_is_primary_thread - Check whether APIC ID belongs to a primary thread - * @id: APIC ID to check -@@ -2207,6 +2208,7 @@ bool apic_id_is_primary_thread(unsigned - mask = (1U << (fls(smp_num_siblings) - 1)) - 1; - return !(apicid & mask); - } -+#endif - - /* - * Should use this API to allocate logical CPU IDs to keep nr_logical_cpuids -From 269777aa530f3438ec1781586cdac0b5fe47b061 Mon Sep 17 00:00:00 2001 -From: Abel Vesa -Date: Wed, 15 Aug 2018 00:26:00 +0300 -Subject: cpu/hotplug: Non-SMP machines do not make use of booted_once - -From: Abel Vesa - -commit 269777aa530f3438ec1781586cdac0b5fe47b061 upstream. - -Commit 0cc3cd21657b ("cpu/hotplug: Boot HT siblings at least once") -breaks non-SMP builds. - -[ I suspect the 'bool' fields should just be made to be bitfields and be - exposed regardless of configuration, but that's a separate cleanup - that I'll leave to the owners of this file for later. - Linus ] - -Fixes: 0cc3cd21657b ("cpu/hotplug: Boot HT siblings at least once") -Cc: Dave Hansen -Cc: Thomas Gleixner -Cc: Tony Luck -Signed-off-by: Abel Vesa -Signed-off-by: Linus Torvalds -Signed-off-by: Greg Kroah-Hartman - ---- - kernel/cpu.c | 2 ++ - 1 file changed, 2 insertions(+) - ---- a/kernel/cpu.c -+++ b/kernel/cpu.c -@@ -2267,6 +2267,8 @@ void __init boot_cpu_init(void) - */ - void __init boot_cpu_hotplug_init(void) - { -+#ifdef CONFIG_SMP - this_cpu_write(cpuhp_state.booted_once, true); -+#endif - this_cpu_write(cpuhp_state.state, CPUHP_ONLINE); - } -From 792adb90fa724ce07c0171cbc96b9215af4b1045 Mon Sep 17 00:00:00 2001 -From: Vlastimil Babka -Date: Tue, 14 Aug 2018 20:50:47 +0200 -Subject: x86/init: fix build with CONFIG_SWAP=n - -From: Vlastimil Babka - -commit 792adb90fa724ce07c0171cbc96b9215af4b1045 upstream. - -The introduction of generic_max_swapfile_size and arch-specific versions has -broken linking on x86 with CONFIG_SWAP=n due to undefined reference to -'generic_max_swapfile_size'. Fix it by compiling the x86-specific -max_swapfile_size() only with CONFIG_SWAP=y. - -Reported-by: Tomas Pruzina -Fixes: 377eeaa8e11f ("x86/speculation/l1tf: Limit swap file size to MAX_PA/2") -Signed-off-by: Vlastimil Babka -Cc: stable@vger.kernel.org -Signed-off-by: Linus Torvalds -Signed-off-by: Greg Kroah-Hartman - ---- - arch/x86/mm/init.c | 2 ++ - 1 file changed, 2 insertions(+) - ---- a/arch/x86/mm/init.c -+++ b/arch/x86/mm/init.c -@@ -883,6 +883,7 @@ void update_cache_mode_entry(unsigned en - __pte2cachemode_tbl[entry] = cache; - } - -+#ifdef CONFIG_SWAP - unsigned long max_swapfile_size(void) - { - unsigned long pages; -@@ -903,3 +904,4 @@ unsigned long max_swapfile_size(void) - } - return pages; - } -+#endif diff --git a/kernel.spec b/kernel.spec index 924752c81..bacc5af0e 100644 --- a/kernel.spec +++ b/kernel.spec @@ -42,7 +42,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 202 +%global baserelease 200 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -54,7 +54,7 @@ Summary: The Linux kernel %if 0%{?released_kernel} # Do we have a -stable update to apply? -%define stable_update 14 +%define stable_update 17 # Set rpm version accordingly %if 0%{?stable_update} %define stablerev %{stable_update} @@ -665,9 +665,6 @@ Patch523: 0001-xfs-More-robust-inode-extent-count-validation.patch # rhbz 1597333 # Patch526: xhci-Fix-perceived-dead-host-due-to-runtime-suspend-.patch -# CVE-2018-3620 CVE-2018-3646 rhbz 1585005 1615998 -Patch524: foreshadow.patch - # END OF PATCH DEFINITIONS %endif @@ -1917,6 +1914,9 @@ fi # # %changelog +* Mon Aug 20 2018 Justin M. Forbes - 4.17.17-200 +- Linux v4.17.17 + * Wed Aug 15 2018 Justin M. Forbes - 4.17.14-202 - Include missing Forshadow patches diff --git a/sources b/sources index 68740e077..a356f416e 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ SHA512 (linux-4.17.tar.xz) = 4d9de340a26155a89ea8773131c76220cc2057f2b5d031b467b60e8b14c1842518e2d60a863d8c695f0f7640f3f18d43826201984a238dade857b6cef79837db -SHA512 (patch-4.17.14.xz) = 99b76b9305868a93139d9e977ee244c02ada7e3966856a1c559c049dff4543cd39595b723d9fc9b8f27ffef9ff0e4b28bcfbdb28738d5e19342473336553eb27 +SHA512 (patch-4.17.17.xz) = 29cd38c11b235cd7fc4eb5c519034916fa6afce7bcf6193382b4d501b2df67afa790eca972bc5f0403e626ef4be5b0dba4a60affa4450de687af3778ae4c135a -- cgit From d9b24fa3d23f03602c30aac0162bdecc8bfd808d Mon Sep 17 00:00:00 2001 From: "Justin M. Forbes" Date: Mon, 20 Aug 2018 08:58:36 -0500 Subject: Fix CVE-2018-15471 rhbz 1610555 1618414 --- kernel.spec | 4 ++++ xsa270.patch | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+) create mode 100644 xsa270.patch diff --git a/kernel.spec b/kernel.spec index bacc5af0e..3499fafba 100644 --- a/kernel.spec +++ b/kernel.spec @@ -665,6 +665,9 @@ Patch523: 0001-xfs-More-robust-inode-extent-count-validation.patch # rhbz 1597333 # Patch526: xhci-Fix-perceived-dead-host-due-to-runtime-suspend-.patch +# CVE-2018-15471 rhbz 1610555 1618414 +Patch524: xsa270.patch + # END OF PATCH DEFINITIONS %endif @@ -1916,6 +1919,7 @@ fi %changelog * Mon Aug 20 2018 Justin M. Forbes - 4.17.17-200 - Linux v4.17.17 +- Fix CVE-2018-15471 (rhbz 1610555 1618414) * Wed Aug 15 2018 Justin M. Forbes - 4.17.14-202 - Include missing Forshadow patches diff --git a/xsa270.patch b/xsa270.patch new file mode 100644 index 000000000..867896f9d --- /dev/null +++ b/xsa270.patch @@ -0,0 +1,55 @@ +From: Jan Beulich +Subject: xen-netback: fix input validation in xenvif_set_hash_mapping() + +Both len and off are frontend specified values, so we need to make +sure there's no overflow when adding the two for the bounds check. We +also want to avoid undefined behavior and hence use off to index into +->hash.mapping[] only after bounds checking. This at the same time +allows to take care of not applying off twice for the bounds checking +against vif->num_queues. + +It is also insufficient to bounds check copy_op.len, as this is len +truncated to 16 bits. + +This is XSA-270. + +Reported-by: Felix Wilhelm +Signed-off-by: Jan Beulich +Reviewed-by: Paul Durrant +Tested-by: Paul Durrant +--- +The bounds checking against vif->num_queues also occurs too early afaict +(it should be done after the grant copy). I have patches ready as public +follow-ups for both this and the (at least latent) issue of the mapping +array crossing a page boundary. + +--- a/drivers/net/xen-netback/hash.c ++++ b/drivers/net/xen-netback/hash.c +@@ -332,20 +332,22 @@ u32 xenvif_set_hash_mapping_size(struct + u32 xenvif_set_hash_mapping(struct xenvif *vif, u32 gref, u32 len, + u32 off) + { +- u32 *mapping = &vif->hash.mapping[off]; ++ u32 *mapping = vif->hash.mapping; + struct gnttab_copy copy_op = { + .source.u.ref = gref, + .source.domid = vif->domid, +- .dest.u.gmfn = virt_to_gfn(mapping), + .dest.domid = DOMID_SELF, +- .dest.offset = xen_offset_in_page(mapping), +- .len = len * sizeof(u32), ++ .len = len * sizeof(*mapping), + .flags = GNTCOPY_source_gref + }; + +- if ((off + len > vif->hash.size) || copy_op.len > XEN_PAGE_SIZE) ++ if ((off + len < off) || (off + len > vif->hash.size) || ++ len > XEN_PAGE_SIZE / sizeof(*mapping)) + return XEN_NETIF_CTRL_STATUS_INVALID_PARAMETER; + ++ copy_op.dest.u.gmfn = virt_to_gfn(mapping + off); ++ copy_op.dest.offset = xen_offset_in_page(mapping + off); ++ + while (len-- != 0) + if (mapping[off++] >= vif->num_queues) + return XEN_NETIF_CTRL_STATUS_INVALID_PARAMETER; -- cgit