Commit 1daa1cfb authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'x86-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull x86 fixes from Thomas Gleixner:

 - the high latency PIT detection fix, which slipped through the cracks
   for rc1

 - a regression fix for the early printk mechanism

 - the x86 part to plug irq/vector related hotplug races

 - move the allocation of the espfix pages on cpu hotplug to non atomic
   context.  The current code triggers a might_sleep() warning.

 - a series of KASAN fixes addressing boot crashes and usability

 - a trivial typo fix for Kconfig help text

* 'x86-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
  x86/kconfig: Fix typo in the CONFIG_CMDLINE_BOOL help text
  x86/irq: Retrieve irq data after locking irq_desc
  x86/irq: Use proper locking in check_irq_vectors_for_cpu_disable()
  x86/irq: Plug irq vector hotplug race
  x86/earlyprintk: Allow early_printk() to use console style parameters like '115200n8'
  x86/espfix: Init espfix on the boot CPU side
  x86/espfix: Add 'cpu' parameter to init_espfix_ap()
  x86/kasan: Move KASAN_SHADOW_OFFSET to the arch Kconfig
  x86/kasan: Add message about KASAN being initialized
  x86/kasan: Fix boot crash on AMD processors
  x86/kasan: Flush TLBs after switching CR3
  x86/kasan: Fix KASAN shadow region page tables
  x86/init: Clear 'init_level4_pgt' earlier
  x86/tsc: Let high latency PIT fail fast in quick_pit_calibrate()
parents 7b732169 69711ca1
...@@ -254,6 +254,11 @@ config ARCH_SUPPORTS_OPTIMIZED_INLINING ...@@ -254,6 +254,11 @@ config ARCH_SUPPORTS_OPTIMIZED_INLINING
config ARCH_SUPPORTS_DEBUG_PAGEALLOC config ARCH_SUPPORTS_DEBUG_PAGEALLOC
def_bool y def_bool y
config KASAN_SHADOW_OFFSET
hex
depends on KASAN
default 0xdffffc0000000000
config HAVE_INTEL_TXT config HAVE_INTEL_TXT
def_bool y def_bool y
depends on INTEL_IOMMU && ACPI depends on INTEL_IOMMU && ACPI
...@@ -2015,7 +2020,7 @@ config CMDLINE_BOOL ...@@ -2015,7 +2020,7 @@ config CMDLINE_BOOL
To compile command line arguments into the kernel, To compile command line arguments into the kernel,
set this option to 'Y', then fill in the set this option to 'Y', then fill in the
the boot arguments in CONFIG_CMDLINE. boot arguments in CONFIG_CMDLINE.
Systems with fully functional boot loaders (i.e. non-embedded) Systems with fully functional boot loaders (i.e. non-embedded)
should leave this option set to 'N'. should leave this option set to 'N'.
......
...@@ -9,7 +9,7 @@ DECLARE_PER_CPU_READ_MOSTLY(unsigned long, espfix_stack); ...@@ -9,7 +9,7 @@ DECLARE_PER_CPU_READ_MOSTLY(unsigned long, espfix_stack);
DECLARE_PER_CPU_READ_MOSTLY(unsigned long, espfix_waddr); DECLARE_PER_CPU_READ_MOSTLY(unsigned long, espfix_waddr);
extern void init_espfix_bsp(void); extern void init_espfix_bsp(void);
extern void init_espfix_ap(void); extern void init_espfix_ap(int cpu);
#endif /* CONFIG_X86_64 */ #endif /* CONFIG_X86_64 */
......
...@@ -14,15 +14,11 @@ ...@@ -14,15 +14,11 @@
#ifndef __ASSEMBLY__ #ifndef __ASSEMBLY__
extern pte_t kasan_zero_pte[];
extern pte_t kasan_zero_pmd[];
extern pte_t kasan_zero_pud[];
#ifdef CONFIG_KASAN #ifdef CONFIG_KASAN
void __init kasan_map_early_shadow(pgd_t *pgd); void __init kasan_early_init(void);
void __init kasan_init(void); void __init kasan_init(void);
#else #else
static inline void kasan_map_early_shadow(pgd_t *pgd) { } static inline void kasan_early_init(void) { }
static inline void kasan_init(void) { } static inline void kasan_init(void) { }
#endif #endif
......
...@@ -409,12 +409,6 @@ static void __setup_vector_irq(int cpu) ...@@ -409,12 +409,6 @@ static void __setup_vector_irq(int cpu)
int irq, vector; int irq, vector;
struct apic_chip_data *data; struct apic_chip_data *data;
/*
* vector_lock will make sure that we don't run into irq vector
* assignments that might be happening on another cpu in parallel,
* while we setup our initial vector to irq mappings.
*/
raw_spin_lock(&vector_lock);
/* Mark the inuse vectors */ /* Mark the inuse vectors */
for_each_active_irq(irq) { for_each_active_irq(irq) {
data = apic_chip_data(irq_get_irq_data(irq)); data = apic_chip_data(irq_get_irq_data(irq));
...@@ -436,16 +430,16 @@ static void __setup_vector_irq(int cpu) ...@@ -436,16 +430,16 @@ static void __setup_vector_irq(int cpu)
if (!cpumask_test_cpu(cpu, data->domain)) if (!cpumask_test_cpu(cpu, data->domain))
per_cpu(vector_irq, cpu)[vector] = VECTOR_UNDEFINED; per_cpu(vector_irq, cpu)[vector] = VECTOR_UNDEFINED;
} }
raw_spin_unlock(&vector_lock);
} }
/* /*
* Setup the vector to irq mappings. * Setup the vector to irq mappings. Must be called with vector_lock held.
*/ */
void setup_vector_irq(int cpu) void setup_vector_irq(int cpu)
{ {
int irq; int irq;
lockdep_assert_held(&vector_lock);
/* /*
* On most of the platforms, legacy PIC delivers the interrupts on the * On most of the platforms, legacy PIC delivers the interrupts on the
* boot cpu. But there are certain platforms where PIC interrupts are * boot cpu. But there are certain platforms where PIC interrupts are
......
...@@ -175,7 +175,9 @@ static __init void early_serial_init(char *s) ...@@ -175,7 +175,9 @@ static __init void early_serial_init(char *s)
} }
if (*s) { if (*s) {
if (kstrtoul(s, 0, &baud) < 0 || baud == 0) baud = simple_strtoull(s, &e, 0);
if (baud == 0 || s == e)
baud = DEFAULT_BAUD; baud = DEFAULT_BAUD;
} }
......
...@@ -131,25 +131,24 @@ void __init init_espfix_bsp(void) ...@@ -131,25 +131,24 @@ void __init init_espfix_bsp(void)
init_espfix_random(); init_espfix_random();
/* The rest is the same as for any other processor */ /* The rest is the same as for any other processor */
init_espfix_ap(); init_espfix_ap(0);
} }
void init_espfix_ap(void) void init_espfix_ap(int cpu)
{ {
unsigned int cpu, page; unsigned int page;
unsigned long addr; unsigned long addr;
pud_t pud, *pud_p; pud_t pud, *pud_p;
pmd_t pmd, *pmd_p; pmd_t pmd, *pmd_p;
pte_t pte, *pte_p; pte_t pte, *pte_p;
int n; int n, node;
void *stack_page; void *stack_page;
pteval_t ptemask; pteval_t ptemask;
/* We only have to do this once... */ /* We only have to do this once... */
if (likely(this_cpu_read(espfix_stack))) if (likely(per_cpu(espfix_stack, cpu)))
return; /* Already initialized */ return; /* Already initialized */
cpu = smp_processor_id();
addr = espfix_base_addr(cpu); addr = espfix_base_addr(cpu);
page = cpu/ESPFIX_STACKS_PER_PAGE; page = cpu/ESPFIX_STACKS_PER_PAGE;
...@@ -165,12 +164,15 @@ void init_espfix_ap(void) ...@@ -165,12 +164,15 @@ void init_espfix_ap(void)
if (stack_page) if (stack_page)
goto unlock_done; goto unlock_done;
node = cpu_to_node(cpu);
ptemask = __supported_pte_mask; ptemask = __supported_pte_mask;
pud_p = &espfix_pud_page[pud_index(addr)]; pud_p = &espfix_pud_page[pud_index(addr)];
pud = *pud_p; pud = *pud_p;
if (!pud_present(pud)) { if (!pud_present(pud)) {
pmd_p = (pmd_t *)__get_free_page(PGALLOC_GFP); struct page *page = alloc_pages_node(node, PGALLOC_GFP, 0);
pmd_p = (pmd_t *)page_address(page);
pud = __pud(__pa(pmd_p) | (PGTABLE_PROT & ptemask)); pud = __pud(__pa(pmd_p) | (PGTABLE_PROT & ptemask));
paravirt_alloc_pmd(&init_mm, __pa(pmd_p) >> PAGE_SHIFT); paravirt_alloc_pmd(&init_mm, __pa(pmd_p) >> PAGE_SHIFT);
for (n = 0; n < ESPFIX_PUD_CLONES; n++) for (n = 0; n < ESPFIX_PUD_CLONES; n++)
...@@ -180,7 +182,9 @@ void init_espfix_ap(void) ...@@ -180,7 +182,9 @@ void init_espfix_ap(void)
pmd_p = pmd_offset(&pud, addr); pmd_p = pmd_offset(&pud, addr);
pmd = *pmd_p; pmd = *pmd_p;
if (!pmd_present(pmd)) { if (!pmd_present(pmd)) {
pte_p = (pte_t *)__get_free_page(PGALLOC_GFP); struct page *page = alloc_pages_node(node, PGALLOC_GFP, 0);
pte_p = (pte_t *)page_address(page);
pmd = __pmd(__pa(pte_p) | (PGTABLE_PROT & ptemask)); pmd = __pmd(__pa(pte_p) | (PGTABLE_PROT & ptemask));
paravirt_alloc_pte(&init_mm, __pa(pte_p) >> PAGE_SHIFT); paravirt_alloc_pte(&init_mm, __pa(pte_p) >> PAGE_SHIFT);
for (n = 0; n < ESPFIX_PMD_CLONES; n++) for (n = 0; n < ESPFIX_PMD_CLONES; n++)
...@@ -188,7 +192,7 @@ void init_espfix_ap(void) ...@@ -188,7 +192,7 @@ void init_espfix_ap(void)
} }
pte_p = pte_offset_kernel(&pmd, addr); pte_p = pte_offset_kernel(&pmd, addr);
stack_page = (void *)__get_free_page(GFP_KERNEL); stack_page = page_address(alloc_pages_node(node, GFP_KERNEL, 0));
pte = __pte(__pa(stack_page) | (__PAGE_KERNEL_RO & ptemask)); pte = __pte(__pa(stack_page) | (__PAGE_KERNEL_RO & ptemask));
for (n = 0; n < ESPFIX_PTE_CLONES; n++) for (n = 0; n < ESPFIX_PTE_CLONES; n++)
set_pte(&pte_p[n*PTE_STRIDE], pte); set_pte(&pte_p[n*PTE_STRIDE], pte);
...@@ -199,7 +203,7 @@ void init_espfix_ap(void) ...@@ -199,7 +203,7 @@ void init_espfix_ap(void)
unlock_done: unlock_done:
mutex_unlock(&espfix_init_mutex); mutex_unlock(&espfix_init_mutex);
done: done:
this_cpu_write(espfix_stack, addr); per_cpu(espfix_stack, cpu) = addr;
this_cpu_write(espfix_waddr, (unsigned long)stack_page per_cpu(espfix_waddr, cpu) = (unsigned long)stack_page
+ (addr & ~PAGE_MASK)); + (addr & ~PAGE_MASK);
} }
...@@ -161,11 +161,12 @@ asmlinkage __visible void __init x86_64_start_kernel(char * real_mode_data) ...@@ -161,11 +161,12 @@ asmlinkage __visible void __init x86_64_start_kernel(char * real_mode_data)
/* Kill off the identity-map trampoline */ /* Kill off the identity-map trampoline */
reset_early_page_tables(); reset_early_page_tables();
kasan_map_early_shadow(early_level4_pgt);
/* clear bss before set_intr_gate with early_idt_handler */
clear_bss(); clear_bss();
clear_page(init_level4_pgt);
kasan_early_init();
for (i = 0; i < NUM_EXCEPTION_VECTORS; i++) for (i = 0; i < NUM_EXCEPTION_VECTORS; i++)
set_intr_gate(i, early_idt_handler_array[i]); set_intr_gate(i, early_idt_handler_array[i]);
load_idt((const struct desc_ptr *)&idt_descr); load_idt((const struct desc_ptr *)&idt_descr);
...@@ -177,12 +178,9 @@ asmlinkage __visible void __init x86_64_start_kernel(char * real_mode_data) ...@@ -177,12 +178,9 @@ asmlinkage __visible void __init x86_64_start_kernel(char * real_mode_data)
*/ */
load_ucode_bsp(); load_ucode_bsp();
clear_page(init_level4_pgt);
/* set init_level4_pgt kernel high mapping*/ /* set init_level4_pgt kernel high mapping*/
init_level4_pgt[511] = early_level4_pgt[511]; init_level4_pgt[511] = early_level4_pgt[511];
kasan_map_early_shadow(init_level4_pgt);
x86_64_start_reservations(real_mode_data); x86_64_start_reservations(real_mode_data);
} }
......
...@@ -516,38 +516,9 @@ ENTRY(phys_base) ...@@ -516,38 +516,9 @@ ENTRY(phys_base)
/* This must match the first entry in level2_kernel_pgt */ /* This must match the first entry in level2_kernel_pgt */
.quad 0x0000000000000000 .quad 0x0000000000000000
#ifdef CONFIG_KASAN
#define FILL(VAL, COUNT) \
.rept (COUNT) ; \
.quad (VAL) ; \
.endr
NEXT_PAGE(kasan_zero_pte)
FILL(kasan_zero_page - __START_KERNEL_map + _KERNPG_TABLE, 512)
NEXT_PAGE(kasan_zero_pmd)
FILL(kasan_zero_pte - __START_KERNEL_map + _KERNPG_TABLE, 512)
NEXT_PAGE(kasan_zero_pud)
FILL(kasan_zero_pmd - __START_KERNEL_map + _KERNPG_TABLE, 512)
#undef FILL
#endif
#include "../../x86/xen/xen-head.S" #include "../../x86/xen/xen-head.S"
__PAGE_ALIGNED_BSS __PAGE_ALIGNED_BSS
NEXT_PAGE(empty_zero_page) NEXT_PAGE(empty_zero_page)
.skip PAGE_SIZE .skip PAGE_SIZE
#ifdef CONFIG_KASAN
/*
* This page used as early shadow. We don't use empty_zero_page
* at early stages, stack instrumentation could write some garbage
* to this page.
* Latter we reuse it as zero shadow for large ranges of memory
* that allowed to access, but not instrumented by kasan
* (vmalloc/vmemmap ...).
*/
NEXT_PAGE(kasan_zero_page)
.skip PAGE_SIZE
#endif
...@@ -347,14 +347,22 @@ int check_irq_vectors_for_cpu_disable(void) ...@@ -347,14 +347,22 @@ int check_irq_vectors_for_cpu_disable(void)
if (!desc) if (!desc)
continue; continue;
/*
* Protect against concurrent action removal,
* affinity changes etc.
*/
raw_spin_lock(&desc->lock);
data = irq_desc_get_irq_data(desc); data = irq_desc_get_irq_data(desc);
cpumask_copy(&affinity_new, data->affinity); cpumask_copy(&affinity_new, data->affinity);
cpumask_clear_cpu(this_cpu, &affinity_new); cpumask_clear_cpu(this_cpu, &affinity_new);
/* Do not count inactive or per-cpu irqs. */ /* Do not count inactive or per-cpu irqs. */
if (!irq_has_action(irq) || irqd_is_per_cpu(data)) if (!irq_has_action(irq) || irqd_is_per_cpu(data)) {
raw_spin_unlock(&desc->lock);
continue; continue;
}
raw_spin_unlock(&desc->lock);
/* /*
* A single irq may be mapped to multiple * A single irq may be mapped to multiple
* cpu's vector_irq[] (for example IOAPIC cluster * cpu's vector_irq[] (for example IOAPIC cluster
...@@ -385,6 +393,9 @@ int check_irq_vectors_for_cpu_disable(void) ...@@ -385,6 +393,9 @@ int check_irq_vectors_for_cpu_disable(void)
* vector. If the vector is marked in the used vectors * vector. If the vector is marked in the used vectors
* bitmap or an irq is assigned to it, we don't count * bitmap or an irq is assigned to it, we don't count
* it as available. * it as available.
*
* As this is an inaccurate snapshot anyway, we can do
* this w/o holding vector_lock.
*/ */
for (vector = FIRST_EXTERNAL_VECTOR; for (vector = FIRST_EXTERNAL_VECTOR;
vector < first_system_vector; vector++) { vector < first_system_vector; vector++) {
...@@ -486,6 +497,11 @@ void fixup_irqs(void) ...@@ -486,6 +497,11 @@ void fixup_irqs(void)
*/ */
mdelay(1); mdelay(1);
/*
* We can walk the vector array of this cpu without holding
* vector_lock because the cpu is already marked !online, so
* nothing else will touch it.
*/
for (vector = FIRST_EXTERNAL_VECTOR; vector < NR_VECTORS; vector++) { for (vector = FIRST_EXTERNAL_VECTOR; vector < NR_VECTORS; vector++) {
unsigned int irr; unsigned int irr;
...@@ -497,9 +513,9 @@ void fixup_irqs(void) ...@@ -497,9 +513,9 @@ void fixup_irqs(void)
irq = __this_cpu_read(vector_irq[vector]); irq = __this_cpu_read(vector_irq[vector]);
desc = irq_to_desc(irq); desc = irq_to_desc(irq);
raw_spin_lock(&desc->lock);
data = irq_desc_get_irq_data(desc); data = irq_desc_get_irq_data(desc);
chip = irq_data_get_irq_chip(data); chip = irq_data_get_irq_chip(data);
raw_spin_lock(&desc->lock);
if (chip->irq_retrigger) { if (chip->irq_retrigger) {
chip->irq_retrigger(data); chip->irq_retrigger(data);
__this_cpu_write(vector_irq[vector], VECTOR_RETRIGGERED); __this_cpu_write(vector_irq[vector], VECTOR_RETRIGGERED);
......
...@@ -170,11 +170,6 @@ static void smp_callin(void) ...@@ -170,11 +170,6 @@ static void smp_callin(void)
*/ */
apic_ap_setup(); apic_ap_setup();
/*
* Need to setup vector mappings before we enable interrupts.
*/
setup_vector_irq(smp_processor_id());
/* /*
* Save our processor parameters. Note: this information * Save our processor parameters. Note: this information
* is needed for clock calibration. * is needed for clock calibration.
...@@ -239,18 +234,13 @@ static void notrace start_secondary(void *unused) ...@@ -239,18 +234,13 @@ static void notrace start_secondary(void *unused)
check_tsc_sync_target(); check_tsc_sync_target();
/* /*
* Enable the espfix hack for this CPU * Lock vector_lock and initialize the vectors on this cpu
*/ * before setting the cpu online. We must set it online with
#ifdef CONFIG_X86_ESPFIX64 * vector_lock held to prevent a concurrent setup/teardown
init_espfix_ap(); * from seeing a half valid vector space.
#endif
/*
* We need to hold vector_lock so there the set of online cpus
* does not change while we are assigning vectors to cpus. Holding
* this lock ensures we don't half assign or remove an irq from a cpu.
*/ */
lock_vector_lock(); lock_vector_lock();
setup_vector_irq(smp_processor_id());
set_cpu_online(smp_processor_id(), true); set_cpu_online(smp_processor_id(), true);
unlock_vector_lock(); unlock_vector_lock();
cpu_set_state_online(smp_processor_id()); cpu_set_state_online(smp_processor_id());
...@@ -854,6 +844,13 @@ static int do_boot_cpu(int apicid, int cpu, struct task_struct *idle) ...@@ -854,6 +844,13 @@ static int do_boot_cpu(int apicid, int cpu, struct task_struct *idle)
initial_code = (unsigned long)start_secondary; initial_code = (unsigned long)start_secondary;
stack_start = idle->thread.sp; stack_start = idle->thread.sp;
/*
* Enable the espfix hack for this CPU
*/
#ifdef CONFIG_X86_ESPFIX64
init_espfix_ap(cpu);
#endif
/* So we see what's up */ /* So we see what's up */
announce_cpu(cpu, apicid); announce_cpu(cpu, apicid);
......
...@@ -598,10 +598,19 @@ static unsigned long quick_pit_calibrate(void) ...@@ -598,10 +598,19 @@ static unsigned long quick_pit_calibrate(void)
if (!pit_expect_msb(0xff-i, &delta, &d2)) if (!pit_expect_msb(0xff-i, &delta, &d2))
break; break;
delta -= tsc;
/*
* Extrapolate the error and fail fast if the error will
* never be below 500 ppm.
*/
if (i == 1 &&
d1 + d2 >= (delta * MAX_QUICK_PIT_ITERATIONS) >> 11)
return 0;
/* /*
* Iterate until the error is less than 500 ppm * Iterate until the error is less than 500 ppm
*/ */
delta -= tsc;
if (d1+d2 >= delta >> 11) if (d1+d2 >= delta >> 11)
continue; continue;
......
#define pr_fmt(fmt) "kasan: " fmt
#include <linux/bootmem.h> #include <linux/bootmem.h>
#include <linux/kasan.h> #include <linux/kasan.h>
#include <linux/kdebug.h> #include <linux/kdebug.h>
...@@ -11,7 +12,19 @@ ...@@ -11,7 +12,19 @@
extern pgd_t early_level4_pgt[PTRS_PER_PGD]; extern pgd_t early_level4_pgt[PTRS_PER_PGD];
extern struct range pfn_mapped[E820_X_MAX]; extern struct range pfn_mapped[E820_X_MAX];
extern unsigned char kasan_zero_page[PAGE_SIZE]; static pud_t kasan_zero_pud[PTRS_PER_PUD] __page_aligned_bss;
static pmd_t kasan_zero_pmd[PTRS_PER_PMD] __page_aligned_bss;
static pte_t kasan_zero_pte[PTRS_PER_PTE] __page_aligned_bss;
/*
* This page used as early shadow. We don't use empty_zero_page
* at early stages, stack instrumentation could write some garbage
* to this page.
* Latter we reuse it as zero shadow for large ranges of memory
* that allowed to access, but not instrumented by kasan
* (vmalloc/vmemmap ...).
*/
static unsigned char kasan_zero_page[PAGE_SIZE] __page_aligned_bss;
static int __init map_range(struct range *range) static int __init map_range(struct range *range)
{ {
...@@ -36,7 +49,7 @@ static void __init clear_pgds(unsigned long start, ...@@ -36,7 +49,7 @@ static void __init clear_pgds(unsigned long start,
pgd_clear(pgd_offset_k(start)); pgd_clear(pgd_offset_k(start));
} }
void __init kasan_map_early_shadow(pgd_t *pgd) static void __init kasan_map_early_shadow(pgd_t *pgd)
{ {
int i; int i;
unsigned long start = KASAN_SHADOW_START; unsigned long start = KASAN_SHADOW_START;
...@@ -73,7 +86,7 @@ static int __init zero_pmd_populate(pud_t *pud, unsigned long addr, ...@@ -73,7 +86,7 @@ static int __init zero_pmd_populate(pud_t *pud, unsigned long addr,
while (IS_ALIGNED(addr, PMD_SIZE) && addr + PMD_SIZE <= end) { while (IS_ALIGNED(addr, PMD_SIZE) && addr + PMD_SIZE <= end) {
WARN_ON(!pmd_none(*pmd)); WARN_ON(!pmd_none(*pmd));
set_pmd(pmd, __pmd(__pa_nodebug(kasan_zero_pte) set_pmd(pmd, __pmd(__pa_nodebug(kasan_zero_pte)
| __PAGE_KERNEL_RO)); | _KERNPG_TABLE));
addr += PMD_SIZE; addr += PMD_SIZE;
pmd = pmd_offset(pud, addr); pmd = pmd_offset(pud, addr);
} }
...@@ -99,7 +112,7 @@ static int __init zero_pud_populate(pgd_t *pgd, unsigned long addr, ...@@ -99,7 +112,7 @@ static int __init zero_pud_populate(pgd_t *pgd, unsigned long addr,
while (IS_ALIGNED(addr, PUD_SIZE) && addr + PUD_SIZE <= end) { while (IS_ALIGNED(addr, PUD_SIZE) && addr + PUD_SIZE <= end) {
WARN_ON(!pud_none(*pud)); WARN_ON(!pud_none(*pud));
set_pud(pud, __pud(__pa_nodebug(kasan_zero_pmd) set_pud(pud, __pud(__pa_nodebug(kasan_zero_pmd)
| __PAGE_KERNEL_RO)); | _KERNPG_TABLE));
addr += PUD_SIZE; addr += PUD_SIZE;
pud = pud_offset(pgd, addr); pud = pud_offset(pgd, addr);
} }
...@@ -124,7 +137,7 @@ static int __init zero_pgd_populate(unsigned long addr, unsigned long end) ...@@ -124,7 +137,7 @@ static int __init zero_pgd_populate(unsigned long addr, unsigned long end)
while (IS_ALIGNED(addr, PGDIR_SIZE) && addr + PGDIR_SIZE <= end) { while (IS_ALIGNED(addr, PGDIR_SIZE) && addr + PGDIR_SIZE <= end) {
WARN_ON(!pgd_none(*pgd)); WARN_ON(!pgd_none(*pgd));
set_pgd(pgd, __pgd(__pa_nodebug(kasan_zero_pud) set_pgd(pgd, __pgd(__pa_nodebug(kasan_zero_pud)
| __PAGE_KERNEL_RO)); | _KERNPG_TABLE));
addr += PGDIR_SIZE; addr += PGDIR_SIZE;
pgd = pgd_offset_k(addr); pgd = pgd_offset_k(addr);
} }
...@@ -166,6 +179,26 @@ static struct notifier_block kasan_die_notifier = { ...@@ -166,6 +179,26 @@ static struct notifier_block kasan_die_notifier = {
}; };
#endif #endif
void __init kasan_early_init(void)
{
int i;
pteval_t pte_val = __pa_nodebug(kasan_zero_page) | __PAGE_KERNEL;
pmdval_t pmd_val = __pa_nodebug(kasan_zero_pte) | _KERNPG_TABLE;
pudval_t pud_val = __pa_nodebug(kasan_zero_pmd) | _KERNPG_TABLE;
for (i = 0; i < PTRS_PER_PTE; i++)
kasan_zero_pte[i] = __pte(pte_val);
for (i = 0; i < PTRS_PER_PMD; i++)
kasan_zero_pmd[i] = __pmd(pmd_val);
for (i = 0; i < PTRS_PER_PUD; i++)
kasan_zero_pud[i] = __pud(pud_val);
kasan_map_early_shadow(early_level4_pgt);
kasan_map_early_shadow(init_level4_pgt);
}
void __init kasan_init(void) void __init kasan_init(void)
{ {
int i; int i;
...@@ -176,6 +209,7 @@ void __init kasan_init(void) ...@@ -176,6 +209,7 @@ void __init kasan_init(void)
memcpy(early_level4_pgt, init_level4_pgt, sizeof(early_level4_pgt)); memcpy(early_level4_pgt, init_level4_pgt, sizeof(early_level4_pgt));
load_cr3(early_level4_pgt); load_cr3(early_level4_pgt);
__flush_tlb_all();
clear_pgds(KASAN_SHADOW_START, KASAN_SHADOW_END); clear_pgds(KASAN_SHADOW_START, KASAN_SHADOW_END);
...@@ -202,5 +236,8 @@ void __init kasan_init(void) ...@@ -202,5 +236,8 @@ void __init kasan_init(void)
memset(kasan_zero_page, 0, PAGE_SIZE); memset(kasan_zero_page, 0, PAGE_SIZE);
load_cr3(init_level4_pgt); load_cr3(init_level4_pgt);
__flush_tlb_all();
init_task.kasan_depth = 0; init_task.kasan_depth = 0;
pr_info("Kernel address sanitizer initialized\n");
} }
...@@ -18,10 +18,6 @@ config KASAN ...@@ -18,10 +18,6 @@ config KASAN
For better error detection enable CONFIG_STACKTRACE, For better error detection enable CONFIG_STACKTRACE,
and add slub_debug=U to boot cmdline. and add slub_debug=U to boot cmdline.
config KASAN_SHADOW_OFFSET
hex
default 0xdffffc0000000000 if X86_64
choice choice
prompt "Instrumentation type" prompt "Instrumentation type"
depends on KASAN depends on KASAN
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment