mirror of
https://github.com/zephyrproject-rtos/zephyr
synced 2025-08-25 19:56:37 +00:00
Implement a set of per-cpu trampoline stacks which all interrupts and exceptions will initially land on, and also as an intermediate stack for privilege changes as we need some stack space to swap page tables. Set up the special trampoline page which contains all the trampoline stacks, TSS, and GDT. This page needs to be present in the user page tables or interrupts don't work. CPU exceptions, with KPTI turned on, are treated as interrupts and not traps so that we have IRQs locked on exception entry. Add some additional macros for defining IDT entries. Add special handling of locore text/rodata sections when creating user mode page tables on x86-64. Restore qemu_x86_64 to use KPTI, and remove restrictions on enabling user mode on x86-64. Signed-off-by: Andrew Boie <andrew.p.boie@intel.com>
209 lines
4.7 KiB
Plaintext
209 lines
4.7 KiB
Plaintext
/*
|
|
* Copyright (c) 2019 Intel Corp.
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
#include <linker/linker-defs.h>
|
|
#include <linker/linker-tool.h>
|
|
|
|
#define ROMABLE_REGION RAM
|
|
#define RAMABLE_REGION RAM
|
|
|
|
#ifdef CONFIG_X86_MMU
|
|
#define MMU_PAGE_SIZE KB(4)
|
|
#define MMU_PAGE_ALIGN . = ALIGN(MMU_PAGE_SIZE);
|
|
#else
|
|
#define MMU_PAGE_ALIGN
|
|
#endif
|
|
|
|
ENTRY(CONFIG_KERNEL_ENTRY)
|
|
|
|
SECTIONS
|
|
{
|
|
/*
|
|
* The "locore" must be in the 64K of RAM, so that 16-bit code (with
|
|
* segment registers == 0x0000) and 32/64-bit code agree on addresses.
|
|
* ... there is no 16-bit code yet, but there will be when we add SMP.
|
|
*/
|
|
|
|
.locore 0x8000 : ALIGN(16)
|
|
{
|
|
_locore_start = .;
|
|
*(.locore)
|
|
*(.locore.*)
|
|
MMU_PAGE_ALIGN
|
|
_lorodata_start = .;
|
|
*(.lorodata)
|
|
MMU_PAGE_ALIGN
|
|
_lodata_start = .;
|
|
|
|
*(.lodata)
|
|
|
|
#ifdef CONFIG_X86_KPTI
|
|
/* Special page containing supervisor data that is still mapped in
|
|
* user mode page tables. GDT, TSSes, trampoline stack, and
|
|
* any LDT must go here as they always must live in a page that is
|
|
* marked 'present'. Still not directly user accessible, but
|
|
* no sensitive data should be here as Meltdown exploits may read it.
|
|
*
|
|
* On x86-64 the IDT is in rodata and doesn't need to be in the
|
|
* trampoline page.
|
|
*/
|
|
MMU_PAGE_ALIGN
|
|
z_shared_kernel_page_start = .;
|
|
#endif /* CONFIG_X86_KPTI */
|
|
|
|
*(.tss)
|
|
*(.gdt)
|
|
|
|
#ifdef CONFIG_X86_KPTI
|
|
*(.trampolines)
|
|
MMU_PAGE_ALIGN
|
|
z_shared_kernel_page_end = .;
|
|
|
|
ASSERT(z_shared_kernel_page_end - z_shared_kernel_page_start == 4096,
|
|
"shared kernel area is not one memory page");
|
|
#endif /* CONFIG_X86_KPTI */
|
|
|
|
MMU_PAGE_ALIGN
|
|
_lodata_end = .;
|
|
}
|
|
|
|
_locore_size = _lorodata_start - _locore_start;
|
|
_lorodata_size = _lodata_start - _lorodata_start;
|
|
_lodata_size = _lodata_end - _lodata_start;
|
|
|
|
/*
|
|
* The rest of the system is loaded in "normal" memory (typically
|
|
* placed above 1MB to avoid the by memory hole at 0x90000-0xFFFFF).
|
|
*/
|
|
|
|
SECTION_PROLOGUE(_TEXT_SECTION_NAME,,ALIGN(16))
|
|
{
|
|
_image_rom_start = .;
|
|
_image_text_start = .;
|
|
*(.text)
|
|
*(.text.*)
|
|
|
|
#include <linker/kobject-text.ld>
|
|
|
|
MMU_PAGE_ALIGN
|
|
} GROUP_LINK_IN(ROMABLE_REGION)
|
|
|
|
_image_text_end = .;
|
|
_image_text_size = _image_text_end - _image_text_start;
|
|
_image_rodata_start = .;
|
|
|
|
#include <linker/common-rom.ld>
|
|
|
|
SECTION_PROLOGUE(_RODATA_SECTION_NAME,,ALIGN(16))
|
|
{
|
|
*(.rodata)
|
|
*(.rodata.*)
|
|
|
|
#include <snippets-rodata.ld>
|
|
|
|
#ifdef CONFIG_CUSTOM_RODATA_LD
|
|
#include <custom-rodata.ld>
|
|
#endif /* CONFIG_CUSTOM_RODATA_LD */
|
|
|
|
#ifdef CONFIG_X86_MMU
|
|
. = ALIGN(8);
|
|
_mmu_region_list_start = .;
|
|
KEEP(*("._mmu_region.static.*"))
|
|
_mmu_region_list_end = .;
|
|
#endif /* CONFIG_X86_MMU */
|
|
|
|
#include <linker/kobject-rom.ld>
|
|
} GROUP_LINK_IN(ROMABLE_REGION)
|
|
|
|
#include <linker/cplusplus-rom.ld>
|
|
|
|
MMU_PAGE_ALIGN
|
|
_image_rodata_end = .;
|
|
_image_rodata_size = _image_rodata_end - _image_rodata_start;
|
|
_image_rom_end = .;
|
|
|
|
#ifdef CONFIG_USERSPACE
|
|
/* APP SHARED MEMORY REGION */
|
|
#define SMEM_PARTITION_ALIGN(size) MMU_PAGE_ALIGN
|
|
#define APP_SHARED_ALIGN MMU_PAGE_ALIGN
|
|
|
|
#include <app_smem.ld>
|
|
|
|
_image_ram_start = _app_smem_start;
|
|
_app_smem_size = _app_smem_end - _app_smem_start;
|
|
_app_smem_num_words = _app_smem_size >> 2;
|
|
_app_smem_rom_start = LOADADDR(_APP_SMEM_SECTION_NAME);
|
|
_app_smem_num_words = _app_smem_size >> 2;
|
|
#endif /* CONFIG_USERSPACE */
|
|
|
|
SECTION_PROLOGUE(_BSS_SECTION_NAME, (NOLOAD), ALIGN(16))
|
|
{
|
|
MMU_PAGE_ALIGN
|
|
#ifndef CONFIG_USERSPACE
|
|
_image_ram_start = .;
|
|
#endif
|
|
__kernel_ram_start = .;
|
|
__bss_start = .;
|
|
*(.bss)
|
|
*(.bss.*)
|
|
*(COMMON)
|
|
. = ALIGN(4); /* so __bss_num_dwords is exact */
|
|
__bss_end = .;
|
|
} GROUP_DATA_LINK_IN(RAMABLE_REGION, RAMABLE_REGION)
|
|
|
|
__bss_num_dwords = (__bss_end - __bss_start) >> 2;
|
|
|
|
SECTION_PROLOGUE(_NOINIT_SECTION_NAME, (NOLOAD), ALIGN(16))
|
|
{
|
|
*(.noinit)
|
|
*(.noinit.*)
|
|
#include <snippets-noinit.ld>
|
|
} GROUP_DATA_LINK_IN(RAMABLE_REGION, RAMABLE_REGION)
|
|
|
|
#include <snippets-sections.ld>
|
|
#ifdef CONFIG_CUSTOM_SECTIONS_LD
|
|
#include <custom-sections.ld>
|
|
#endif /* CONFIG_CUSTOM_SECTIONS_LD */
|
|
|
|
SECTION_PROLOGUE(_DATA_SECTION_NAME,,ALIGN(16))
|
|
{
|
|
*(.data)
|
|
*(.data.*)
|
|
#include <snippets-rwdata.ld>
|
|
#ifdef CONFIG_CUSTOM_RWDATA_LD
|
|
#include <custom-rwdata.ld>
|
|
#endif /* CONFIG_CUSTOM_RWDATA_LD */
|
|
} GROUP_DATA_LINK_IN(RAMABLE_REGION, ROMABLE_REGION)
|
|
|
|
#include <snippets-ram-sections.ld>
|
|
#include <linker/common-ram.ld>
|
|
#include <linker/cplusplus-ram.ld>
|
|
#include <linker/kobject.ld>
|
|
|
|
. = ALIGN(8);
|
|
MMU_PAGE_ALIGN
|
|
_image_ram_end = .;
|
|
_end = .;
|
|
|
|
/* All unused memory also owned by the kernel for heaps */
|
|
__kernel_ram_end = PHYS_RAM_ADDR + KB(DT_RAM_SIZE);
|
|
__kernel_ram_size = __kernel_ram_end - __kernel_ram_start;
|
|
|
|
#include <linker/debug-sections.ld>
|
|
|
|
/DISCARD/ :
|
|
{
|
|
*(.got)
|
|
*(.got.plt)
|
|
*(.igot)
|
|
*(.igot.plt)
|
|
*(.iplt)
|
|
*(.plt)
|
|
*(.note.GNU-stack)
|
|
*(.rel.*)
|
|
*(.rela.*)
|
|
}
|
|
}
|