.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
---|
1 | 2 | /* |
---|
2 | 3 | * Copyright(c) 2017 Intel Corporation. All rights reserved. |
---|
3 | | - * |
---|
4 | | - * This program is free software; you can redistribute it and/or modify |
---|
5 | | - * it under the terms of version 2 of the GNU General Public License as |
---|
6 | | - * published by the Free Software Foundation. |
---|
7 | | - * |
---|
8 | | - * This program is distributed in the hope that it will be useful, but |
---|
9 | | - * WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
10 | | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
---|
11 | | - * General Public License for more details. |
---|
12 | 4 | * |
---|
13 | 5 | * This code is based in part on work published here: |
---|
14 | 6 | * |
---|
.. | .. |
---|
42 | 34 | #include <asm/vsyscall.h> |
---|
43 | 35 | #include <asm/cmdline.h> |
---|
44 | 36 | #include <asm/pti.h> |
---|
45 | | -#include <asm/pgtable.h> |
---|
46 | | -#include <asm/pgalloc.h> |
---|
47 | 37 | #include <asm/tlbflush.h> |
---|
48 | 38 | #include <asm/desc.h> |
---|
49 | 39 | #include <asm/sections.h> |
---|
| 40 | +#include <asm/set_memory.h> |
---|
50 | 41 | |
---|
51 | 42 | #undef pr_fmt |
---|
52 | 43 | #define pr_fmt(fmt) "Kernel/User page tables isolation: " fmt |
---|
.. | .. |
---|
78 | 69 | pr_info("%s\n", reason); |
---|
79 | 70 | } |
---|
80 | 71 | |
---|
81 | | -enum pti_mode { |
---|
| 72 | +static enum pti_mode { |
---|
82 | 73 | PTI_AUTO = 0, |
---|
83 | 74 | PTI_FORCE_OFF, |
---|
84 | 75 | PTI_FORCE_ON |
---|
.. | .. |
---|
438 | 429 | } |
---|
439 | 430 | |
---|
440 | 431 | /* |
---|
441 | | - * Clone the CPU_ENTRY_AREA into the user space visible page table. |
---|
| 432 | + * Clone the CPU_ENTRY_AREA and associated data into the user space visible |
---|
| 433 | + * page table. |
---|
442 | 434 | */ |
---|
443 | 435 | static void __init pti_clone_user_shared(void) |
---|
444 | 436 | { |
---|
| 437 | + unsigned int cpu; |
---|
| 438 | + |
---|
445 | 439 | pti_clone_p4d(CPU_ENTRY_AREA_BASE); |
---|
| 440 | + |
---|
| 441 | + for_each_possible_cpu(cpu) { |
---|
| 442 | + /* |
---|
| 443 | + * The SYSCALL64 entry code needs to be able to find the |
---|
| 444 | + * thread stack and needs one word of scratch space in which |
---|
| 445 | + * to spill a register. All of this lives in the TSS, in |
---|
| 446 | + * the sp1 and sp2 slots. |
---|
| 447 | + * |
---|
| 448 | + * This is done for all possible CPUs during boot to ensure |
---|
| 449 | + * that it's propagated to all mms. |
---|
| 450 | + */ |
---|
| 451 | + |
---|
| 452 | + unsigned long va = (unsigned long)&per_cpu(cpu_tss_rw, cpu); |
---|
| 453 | + phys_addr_t pa = per_cpu_ptr_to_phys((void *)va); |
---|
| 454 | + pte_t *target_pte; |
---|
| 455 | + |
---|
| 456 | + target_pte = pti_user_pagetable_walk_pte(va); |
---|
| 457 | + if (WARN_ON(!target_pte)) |
---|
| 458 | + return; |
---|
| 459 | + |
---|
| 460 | + *target_pte = pfn_pte(pa >> PAGE_SHIFT, PAGE_KERNEL); |
---|
| 461 | + } |
---|
446 | 462 | } |
---|
447 | 463 | |
---|
448 | 464 | #else /* CONFIG_X86_64 */ |
---|
.. | .. |
---|
475 | 491 | } |
---|
476 | 492 | |
---|
477 | 493 | /* |
---|
478 | | - * Clone the populated PMDs of the entry and irqentry text and force it RO. |
---|
| 494 | + * Clone the populated PMDs of the entry text and force it RO. |
---|
479 | 495 | */ |
---|
480 | 496 | static void pti_clone_entry_text(void) |
---|
481 | 497 | { |
---|
482 | 498 | pti_clone_pgtable((unsigned long) __entry_text_start, |
---|
483 | | - (unsigned long) __irqentry_text_end, |
---|
| 499 | + (unsigned long) __entry_text_end, |
---|
484 | 500 | PTI_CLONE_PMD); |
---|
485 | 501 | |
---|
486 | 502 | /* |
---|
.. | .. |
---|
541 | 557 | } |
---|
542 | 558 | |
---|
543 | 559 | /* |
---|
544 | | - * This is the only user for these and it is not arch-generic |
---|
545 | | - * like the other set_memory.h functions. Just extern them. |
---|
546 | | - */ |
---|
547 | | -extern int set_memory_nonglobal(unsigned long addr, int numpages); |
---|
548 | | -extern int set_memory_global(unsigned long addr, int numpages); |
---|
549 | | - |
---|
550 | | -/* |
---|
551 | 560 | * For some configurations, map all of kernel text into the user page |
---|
552 | 561 | * tables. This reduces TLB misses, especially on non-PCID systems. |
---|
553 | 562 | */ |
---|
.. | .. |
---|
584 | 593 | set_memory_global(start, (end_global - start) >> PAGE_SHIFT); |
---|
585 | 594 | } |
---|
586 | 595 | |
---|
587 | | -void pti_set_kernel_image_nonglobal(void) |
---|
| 596 | +static void pti_set_kernel_image_nonglobal(void) |
---|
588 | 597 | { |
---|
589 | 598 | /* |
---|
590 | 599 | * The identity map is created with PMDs, regardless of the |
---|
.. | .. |
---|
608 | 617 | */ |
---|
609 | 618 | void __init pti_init(void) |
---|
610 | 619 | { |
---|
611 | | - if (!static_cpu_has(X86_FEATURE_PTI)) |
---|
| 620 | + if (!boot_cpu_has(X86_FEATURE_PTI)) |
---|
612 | 621 | return; |
---|
613 | 622 | |
---|
614 | 623 | pr_info("enabled\n"); |
---|