mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-12-22 11:09:48 +07:00
b02faed15d
AddressSanitizer instrumentation can significantly bloat the stack, and with GCC 7 this can result in stack overflows at boot time in some configurations. We can avoid this by doubling our stack size when KASAN is in use, as is already done on x86 (and has been since KASAN was introduced). Regardless of other patches to decrease KASAN's stack utilization, kernels built with KASAN will always require more stack space than those built without, and we should take this into account. Signed-off-by: Mark Rutland <mark.rutland@arm.com> Cc: Will Deacon <will.deacon@arm.com> Cc: Suzuki K Poulose <suzuki.poulose@arm.com> Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
326 lines
9.7 KiB
C
326 lines
9.7 KiB
C
/*
|
|
* Based on arch/arm/include/asm/memory.h
|
|
*
|
|
* Copyright (C) 2000-2002 Russell King
|
|
* Copyright (C) 2012 ARM Ltd.
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License version 2 as
|
|
* published by the Free Software Foundation.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*
|
|
* Note: this file should not be included by non-asm/.h files
|
|
*/
|
|
#ifndef __ASM_MEMORY_H
|
|
#define __ASM_MEMORY_H
|
|
|
|
#include <linux/compiler.h>
|
|
#include <linux/const.h>
|
|
#include <linux/types.h>
|
|
#include <asm/bug.h>
|
|
#include <asm/page-def.h>
|
|
#include <asm/sizes.h>
|
|
|
|
/*
|
|
* Allow for constants defined here to be used from assembly code
|
|
* by prepending the UL suffix only with actual C code compilation.
|
|
*/
|
|
#define UL(x) _AC(x, UL)
|
|
|
|
/*
|
|
* Size of the PCI I/O space. This must remain a power of two so that
|
|
* IO_SPACE_LIMIT acts as a mask for the low bits of I/O addresses.
|
|
*/
|
|
#define PCI_IO_SIZE SZ_16M
|
|
|
|
/*
|
|
* Log2 of the upper bound of the size of a struct page. Used for sizing
|
|
* the vmemmap region only, does not affect actual memory footprint.
|
|
* We don't use sizeof(struct page) directly since taking its size here
|
|
* requires its definition to be available at this point in the inclusion
|
|
* chain, and it may not be a power of 2 in the first place.
|
|
*/
|
|
#define STRUCT_PAGE_MAX_SHIFT 6
|
|
|
|
/*
|
|
* VMEMMAP_SIZE - allows the whole linear region to be covered by
|
|
* a struct page array
|
|
*/
|
|
#define VMEMMAP_SIZE (UL(1) << (VA_BITS - PAGE_SHIFT - 1 + STRUCT_PAGE_MAX_SHIFT))
|
|
|
|
/*
|
|
* PAGE_OFFSET - the virtual address of the start of the linear map (top
|
|
* (VA_BITS - 1))
|
|
* KIMAGE_VADDR - the virtual address of the start of the kernel image
|
|
* VA_BITS - the maximum number of bits for virtual addresses.
|
|
* VA_START - the first kernel virtual address.
|
|
* TASK_SIZE - the maximum size of a user space task.
|
|
* TASK_UNMAPPED_BASE - the lower boundary of the mmap VM area.
|
|
*/
|
|
#define VA_BITS (CONFIG_ARM64_VA_BITS)
|
|
#define VA_START (UL(0xffffffffffffffff) - \
|
|
(UL(1) << VA_BITS) + 1)
|
|
#define PAGE_OFFSET (UL(0xffffffffffffffff) - \
|
|
(UL(1) << (VA_BITS - 1)) + 1)
|
|
#define KIMAGE_VADDR (MODULES_END)
|
|
#define MODULES_END (MODULES_VADDR + MODULES_VSIZE)
|
|
#define MODULES_VADDR (VA_START + KASAN_SHADOW_SIZE)
|
|
#define MODULES_VSIZE (SZ_128M)
|
|
#define VMEMMAP_START (PAGE_OFFSET - VMEMMAP_SIZE)
|
|
#define PCI_IO_END (VMEMMAP_START - SZ_2M)
|
|
#define PCI_IO_START (PCI_IO_END - PCI_IO_SIZE)
|
|
#define FIXADDR_TOP (PCI_IO_START - SZ_2M)
|
|
#define TASK_SIZE_64 (UL(1) << VA_BITS)
|
|
|
|
#ifdef CONFIG_COMPAT
|
|
#define TASK_SIZE_32 UL(0x100000000)
|
|
#define TASK_SIZE (test_thread_flag(TIF_32BIT) ? \
|
|
TASK_SIZE_32 : TASK_SIZE_64)
|
|
#define TASK_SIZE_OF(tsk) (test_tsk_thread_flag(tsk, TIF_32BIT) ? \
|
|
TASK_SIZE_32 : TASK_SIZE_64)
|
|
#else
|
|
#define TASK_SIZE TASK_SIZE_64
|
|
#endif /* CONFIG_COMPAT */
|
|
|
|
#define TASK_UNMAPPED_BASE (PAGE_ALIGN(TASK_SIZE / 4))
|
|
|
|
#define KERNEL_START _text
|
|
#define KERNEL_END _end
|
|
|
|
/*
|
|
* KASAN requires 1/8th of the kernel virtual address space for the shadow
|
|
* region. KASAN can bloat the stack significantly, so double the (minimum)
|
|
* stack size when KASAN is in use.
|
|
*/
|
|
#ifdef CONFIG_KASAN
|
|
#define KASAN_SHADOW_SIZE (UL(1) << (VA_BITS - 3))
|
|
#define KASAN_THREAD_SHIFT 1
|
|
#else
|
|
#define KASAN_SHADOW_SIZE (0)
|
|
#define KASAN_THREAD_SHIFT 0
|
|
#endif
|
|
|
|
#define MIN_THREAD_SHIFT (14 + KASAN_THREAD_SHIFT)
|
|
|
|
/*
|
|
* VMAP'd stacks are allocated at page granularity, so we must ensure that such
|
|
* stacks are a multiple of page size.
|
|
*/
|
|
#if defined(CONFIG_VMAP_STACK) && (MIN_THREAD_SHIFT < PAGE_SHIFT)
|
|
#define THREAD_SHIFT PAGE_SHIFT
|
|
#else
|
|
#define THREAD_SHIFT MIN_THREAD_SHIFT
|
|
#endif
|
|
|
|
#if THREAD_SHIFT >= PAGE_SHIFT
|
|
#define THREAD_SIZE_ORDER (THREAD_SHIFT - PAGE_SHIFT)
|
|
#endif
|
|
|
|
#define THREAD_SIZE (UL(1) << THREAD_SHIFT)
|
|
|
|
/*
|
|
* By aligning VMAP'd stacks to 2 * THREAD_SIZE, we can detect overflow by
|
|
* checking sp & (1 << THREAD_SHIFT), which we can do cheaply in the entry
|
|
* assembly.
|
|
*/
|
|
#ifdef CONFIG_VMAP_STACK
|
|
#define THREAD_ALIGN (2 * THREAD_SIZE)
|
|
#else
|
|
#define THREAD_ALIGN THREAD_SIZE
|
|
#endif
|
|
|
|
#define IRQ_STACK_SIZE THREAD_SIZE
|
|
|
|
#define OVERFLOW_STACK_SIZE SZ_4K
|
|
|
|
/*
|
|
* Alignment of kernel segments (e.g. .text, .data).
|
|
*/
|
|
#if defined(CONFIG_DEBUG_ALIGN_RODATA)
|
|
/*
|
|
* 4 KB granule: 1 level 2 entry
|
|
* 16 KB granule: 128 level 3 entries, with contiguous bit
|
|
* 64 KB granule: 32 level 3 entries, with contiguous bit
|
|
*/
|
|
#define SEGMENT_ALIGN SZ_2M
|
|
#else
|
|
/*
|
|
* 4 KB granule: 16 level 3 entries, with contiguous bit
|
|
* 16 KB granule: 4 level 3 entries, without contiguous bit
|
|
* 64 KB granule: 1 level 3 entry
|
|
*/
|
|
#define SEGMENT_ALIGN SZ_64K
|
|
#endif
|
|
|
|
/*
|
|
* Memory types available.
|
|
*/
|
|
#define MT_DEVICE_nGnRnE 0
|
|
#define MT_DEVICE_nGnRE 1
|
|
#define MT_DEVICE_GRE 2
|
|
#define MT_NORMAL_NC 3
|
|
#define MT_NORMAL 4
|
|
#define MT_NORMAL_WT 5
|
|
|
|
/*
|
|
* Memory types for Stage-2 translation
|
|
*/
|
|
#define MT_S2_NORMAL 0xf
|
|
#define MT_S2_DEVICE_nGnRE 0x1
|
|
|
|
#ifdef CONFIG_ARM64_4K_PAGES
|
|
#define IOREMAP_MAX_ORDER (PUD_SHIFT)
|
|
#else
|
|
#define IOREMAP_MAX_ORDER (PMD_SHIFT)
|
|
#endif
|
|
|
|
#ifdef CONFIG_BLK_DEV_INITRD
|
|
#define __early_init_dt_declare_initrd(__start, __end) \
|
|
do { \
|
|
initrd_start = (__start); \
|
|
initrd_end = (__end); \
|
|
} while (0)
|
|
#endif
|
|
|
|
#ifndef __ASSEMBLY__
|
|
|
|
#include <linux/bitops.h>
|
|
#include <linux/mmdebug.h>
|
|
|
|
extern s64 memstart_addr;
|
|
/* PHYS_OFFSET - the physical address of the start of memory. */
|
|
#define PHYS_OFFSET ({ VM_BUG_ON(memstart_addr & 1); memstart_addr; })
|
|
|
|
/* the virtual base of the kernel image (minus TEXT_OFFSET) */
|
|
extern u64 kimage_vaddr;
|
|
|
|
/* the offset between the kernel virtual and physical mappings */
|
|
extern u64 kimage_voffset;
|
|
|
|
static inline unsigned long kaslr_offset(void)
|
|
{
|
|
return kimage_vaddr - KIMAGE_VADDR;
|
|
}
|
|
|
|
/*
|
|
* Allow all memory at the discovery stage. We will clip it later.
|
|
*/
|
|
#define MIN_MEMBLOCK_ADDR 0
|
|
#define MAX_MEMBLOCK_ADDR U64_MAX
|
|
|
|
/*
|
|
* PFNs are used to describe any physical page; this means
|
|
* PFN 0 == physical address 0.
|
|
*
|
|
* This is the PFN of the first RAM page in the kernel
|
|
* direct-mapped view. We assume this is the first page
|
|
* of RAM in the mem_map as well.
|
|
*/
|
|
#define PHYS_PFN_OFFSET (PHYS_OFFSET >> PAGE_SHIFT)
|
|
|
|
/*
|
|
* Physical vs virtual RAM address space conversion. These are
|
|
* private definitions which should NOT be used outside memory.h
|
|
* files. Use virt_to_phys/phys_to_virt/__pa/__va instead.
|
|
*/
|
|
|
|
|
|
/*
|
|
* The linear kernel range starts in the middle of the virtual adddress
|
|
* space. Testing the top bit for the start of the region is a
|
|
* sufficient check.
|
|
*/
|
|
#define __is_lm_address(addr) (!!((addr) & BIT(VA_BITS - 1)))
|
|
|
|
#define __lm_to_phys(addr) (((addr) & ~PAGE_OFFSET) + PHYS_OFFSET)
|
|
#define __kimg_to_phys(addr) ((addr) - kimage_voffset)
|
|
|
|
#define __virt_to_phys_nodebug(x) ({ \
|
|
phys_addr_t __x = (phys_addr_t)(x); \
|
|
__is_lm_address(__x) ? __lm_to_phys(__x) : \
|
|
__kimg_to_phys(__x); \
|
|
})
|
|
|
|
#define __pa_symbol_nodebug(x) __kimg_to_phys((phys_addr_t)(x))
|
|
|
|
#ifdef CONFIG_DEBUG_VIRTUAL
|
|
extern phys_addr_t __virt_to_phys(unsigned long x);
|
|
extern phys_addr_t __phys_addr_symbol(unsigned long x);
|
|
#else
|
|
#define __virt_to_phys(x) __virt_to_phys_nodebug(x)
|
|
#define __phys_addr_symbol(x) __pa_symbol_nodebug(x)
|
|
#endif
|
|
|
|
#define __phys_to_virt(x) ((unsigned long)((x) - PHYS_OFFSET) | PAGE_OFFSET)
|
|
#define __phys_to_kimg(x) ((unsigned long)((x) + kimage_voffset))
|
|
|
|
/*
|
|
* Convert a page to/from a physical address
|
|
*/
|
|
#define page_to_phys(page) (__pfn_to_phys(page_to_pfn(page)))
|
|
#define phys_to_page(phys) (pfn_to_page(__phys_to_pfn(phys)))
|
|
|
|
/*
|
|
* Note: Drivers should NOT use these. They are the wrong
|
|
* translation for translating DMA addresses. Use the driver
|
|
* DMA support - see dma-mapping.h.
|
|
*/
|
|
#define virt_to_phys virt_to_phys
|
|
static inline phys_addr_t virt_to_phys(const volatile void *x)
|
|
{
|
|
return __virt_to_phys((unsigned long)(x));
|
|
}
|
|
|
|
#define phys_to_virt phys_to_virt
|
|
static inline void *phys_to_virt(phys_addr_t x)
|
|
{
|
|
return (void *)(__phys_to_virt(x));
|
|
}
|
|
|
|
/*
|
|
* Drivers should NOT use these either.
|
|
*/
|
|
#define __pa(x) __virt_to_phys((unsigned long)(x))
|
|
#define __pa_symbol(x) __phys_addr_symbol(RELOC_HIDE((unsigned long)(x), 0))
|
|
#define __pa_nodebug(x) __virt_to_phys_nodebug((unsigned long)(x))
|
|
#define __va(x) ((void *)__phys_to_virt((phys_addr_t)(x)))
|
|
#define pfn_to_kaddr(pfn) __va((pfn) << PAGE_SHIFT)
|
|
#define virt_to_pfn(x) __phys_to_pfn(__virt_to_phys((unsigned long)(x)))
|
|
#define sym_to_pfn(x) __phys_to_pfn(__pa_symbol(x))
|
|
|
|
/*
|
|
* virt_to_page(k) convert a _valid_ virtual address to struct page *
|
|
* virt_addr_valid(k) indicates whether a virtual address is valid
|
|
*/
|
|
#define ARCH_PFN_OFFSET ((unsigned long)PHYS_PFN_OFFSET)
|
|
|
|
#ifndef CONFIG_SPARSEMEM_VMEMMAP
|
|
#define virt_to_page(kaddr) pfn_to_page(__pa(kaddr) >> PAGE_SHIFT)
|
|
#define _virt_addr_valid(kaddr) pfn_valid(__pa(kaddr) >> PAGE_SHIFT)
|
|
#else
|
|
#define __virt_to_pgoff(kaddr) (((u64)(kaddr) & ~PAGE_OFFSET) / PAGE_SIZE * sizeof(struct page))
|
|
#define __page_to_voff(kaddr) (((u64)(kaddr) & ~VMEMMAP_START) * PAGE_SIZE / sizeof(struct page))
|
|
|
|
#define page_to_virt(page) ((void *)((__page_to_voff(page)) | PAGE_OFFSET))
|
|
#define virt_to_page(vaddr) ((struct page *)((__virt_to_pgoff(vaddr)) | VMEMMAP_START))
|
|
|
|
#define _virt_addr_valid(kaddr) pfn_valid((((u64)(kaddr) & ~PAGE_OFFSET) \
|
|
+ PHYS_OFFSET) >> PAGE_SHIFT)
|
|
#endif
|
|
#endif
|
|
|
|
#define _virt_addr_is_linear(kaddr) (((u64)(kaddr)) >= PAGE_OFFSET)
|
|
#define virt_addr_valid(kaddr) (_virt_addr_is_linear(kaddr) && \
|
|
_virt_addr_valid(kaddr))
|
|
|
|
#include <asm-generic/memory_model.h>
|
|
|
|
#endif
|