Skip to content

Commit 8543ecc

Browse files
Vasily Gorbikhcahca
authored andcommitted
s390: Unmap early KASAN shadow on memory offlining
Teach the memory hotplug path to tear down KASAN shadow that was mapped during early boot when a memory block is offlined. Track for each sclp_mem whether its range was covered by the early KASAN shadow via an early_shadow_mapped flag. When such a block is deconfigured and removed via sclp_config_mem_store(), compute the corresponding shadow range and call vmemmap_free() to unmap the boot mapped shadow, then clear the flag. Using vmemmap_free() for the early shadow is safe despite the use of large mappings in the boot-time KASAN setup. The initial shadow is mapped with 1M and 2G pages, where possible. The minimum hotplug memory block size is 128M and always aligned (the identity mapping is at least 2G aligned), which corresponds to a 16M chunk of at least 1M aligned shadow. PMD-mapped 1M shadow pages therefore never need splitting, and PUD-mapped 2G shadow pages can now be split following the preceding changes. Relax the modify_pagetable() sanity check in vmem so that, with KASAN enabled, it may also operate on the KASAN shadow region in addition to the 1:1 mapping and vmemmap area. This allows the KASAN shadow unmapping to reuse the common vmem helpers. Signed-off-by: Vasily Gorbik <gor@linux.ibm.com> Reviewed-by: Heiko Carstens <hca@linux.ibm.com> Signed-off-by: Heiko Carstens <hca@linux.ibm.com>
1 parent 6a35d02 commit 8543ecc

2 files changed

Lines changed: 23 additions & 1 deletion

File tree

arch/s390/mm/vmem.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -437,9 +437,15 @@ static int modify_pagetable(unsigned long start, unsigned long end, bool add,
437437

438438
if (WARN_ON_ONCE(!PAGE_ALIGNED(start | end)))
439439
return -EINVAL;
440-
/* Don't mess with any tables not fully in 1:1 mapping & vmemmap area */
440+
/* Don't mess with any tables not fully in 1:1 mapping, vmemmap & kasan area */
441+
#ifdef CONFIG_KASAN
442+
if (WARN_ON_ONCE(!(start >= KASAN_SHADOW_START && end <= KASAN_SHADOW_END) &&
443+
end > __abs_lowcore))
444+
return -EINVAL;
445+
#else
441446
if (WARN_ON_ONCE(end > __abs_lowcore))
442447
return -EINVAL;
448+
#endif
443449
for (addr = start; addr < end; addr = next) {
444450
next = pgd_addr_end(addr, end);
445451
pgd = pgd_offset_k(addr);

drivers/s390/char/sclp_mem.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,9 @@ struct sclp_mem {
4444
unsigned int id;
4545
unsigned int memmap_on_memory;
4646
unsigned int config;
47+
#ifdef CONFIG_KASAN
48+
unsigned int early_shadow_mapped;
49+
#endif
4750
};
4851

4952
struct sclp_mem_arg {
@@ -244,6 +247,16 @@ static ssize_t sclp_config_mem_store(struct kobject *kobj, struct kobj_attribute
244247
put_device(&mem->dev);
245248
sclp_mem_change_state(addr, block_size, 0);
246249
__remove_memory(addr, block_size);
250+
#ifdef CONFIG_KASAN
251+
if (sclp_mem->early_shadow_mapped) {
252+
unsigned long start, end;
253+
254+
start = (unsigned long)kasan_mem_to_shadow(__va(addr));
255+
end = start + (block_size >> KASAN_SHADOW_SCALE_SHIFT);
256+
vmemmap_free(start, end, NULL);
257+
sclp_mem->early_shadow_mapped = 0;
258+
}
259+
#endif
247260
WRITE_ONCE(sclp_mem->config, 0);
248261
}
249262
out_unlock:
@@ -316,6 +329,9 @@ static int sclp_create_mem(struct sclp_mem *sclp_mem, struct kset *kset,
316329

317330
sclp_mem->memmap_on_memory = memmap_on_memory;
318331
sclp_mem->config = config;
332+
#ifdef CONFIG_KASAN
333+
sclp_mem->early_shadow_mapped = config;
334+
#endif
319335
sclp_mem->id = id;
320336
kobject_init(&sclp_mem->kobj, &ktype);
321337
rc = kobject_add(&sclp_mem->kobj, &kset->kobj, "memory%d", id);

0 commit comments

Comments
 (0)