|
6 | 6 | #include <linux/swapfile.h> |
7 | 7 | #include <linux/swapops.h> |
8 | 8 | #include <linux/kmemleak.h> |
| 9 | +#include <linux/sched/task.h> |
9 | 10 |
|
10 | 11 | #include <asm/set_memory.h> |
11 | 12 | #include <asm/e820/api.h> |
|
23 | 24 | #include <asm/hypervisor.h> |
24 | 25 | #include <asm/cpufeature.h> |
25 | 26 | #include <asm/pti.h> |
| 27 | +#include <asm/text-patching.h> |
26 | 28 |
|
27 | 29 | /* |
28 | 30 | * We need to define the tracepoints somewhere, and tlb.c |
@@ -701,6 +703,41 @@ void __init init_mem_mapping(void) |
701 | 703 | early_memtest(0, max_pfn_mapped << PAGE_SHIFT); |
702 | 704 | } |
703 | 705 |
|
| 706 | +/* |
| 707 | + * Initialize an mm_struct to be used during poking and a pointer to be used |
| 708 | + * during patching. |
| 709 | + */ |
| 710 | +void __init poking_init(void) |
| 711 | +{ |
| 712 | + spinlock_t *ptl; |
| 713 | + pte_t *ptep; |
| 714 | + |
| 715 | + poking_mm = copy_init_mm(); |
| 716 | + BUG_ON(!poking_mm); |
| 717 | + |
| 718 | + /* |
| 719 | + * Randomize the poking address, but make sure that the following page |
| 720 | + * will be mapped at the same PMD. We need 2 pages, so find space for 3, |
| 721 | + * and adjust the address if the PMD ends after the first one. |
| 722 | + */ |
| 723 | + poking_addr = TASK_UNMAPPED_BASE; |
| 724 | + if (IS_ENABLED(CONFIG_RANDOMIZE_BASE)) |
| 725 | + poking_addr += (kaslr_get_random_long("Poking") & PAGE_MASK) % |
| 726 | + (TASK_SIZE - TASK_UNMAPPED_BASE - 3 * PAGE_SIZE); |
| 727 | + |
| 728 | + if (((poking_addr + PAGE_SIZE) & ~PMD_MASK) == 0) |
| 729 | + poking_addr += PAGE_SIZE; |
| 730 | + |
| 731 | + /* |
| 732 | + * We need to trigger the allocation of the page-tables that will be |
| 733 | + * needed for poking now. Later, poking may be performed in an atomic |
| 734 | + * section, which might cause allocation to fail. |
| 735 | + */ |
| 736 | + ptep = get_locked_pte(poking_mm, poking_addr, &ptl); |
| 737 | + BUG_ON(!ptep); |
| 738 | + pte_unmap_unlock(ptep, ptl); |
| 739 | +} |
| 740 | + |
704 | 741 | /* |
705 | 742 | * devmem_is_allowed() checks to see if /dev/mem access to a certain address |
706 | 743 | * is valid. The argument is a physical page number. |
|
0 commit comments