/* Is called from entry code, so must be noinstr */
noinstr struct cpu_entry_area *get_cpu_entry_area(int cpu)
{ unsignedlong va = CPU_ENTRY_AREA_PER_CPU + cea_offset(cpu) * CPU_ENTRY_AREA_SIZE;
BUILD_BUG_ON(sizeof(struct cpu_entry_area) % PAGE_SIZE != 0);
/* * The cpu_entry_area is shared between the user and kernel * page tables. All of its ptes can safely be global. * _PAGE_GLOBAL gets reused to help indicate PROT_NONE for * non-present PTEs, so be careful not to set it in that * case to avoid confusion.
*/ if (boot_cpu_has(X86_FEATURE_PGE) &&
(pgprot_val(flags) & _PAGE_PRESENT))
pte = pte_set_flags(pte, _PAGE_GLOBAL);
cea = &get_cpu_entry_area(cpu)->cpu_debug_buffers; /* * Force the population of PMDs for not yet allocated per cpu * memory like debug store buffers.
*/
npages = sizeof(struct debug_store_buffers) / PAGE_SIZE; for (; npages; npages--, cea += PAGE_SIZE)
cea_set_pte(cea, 0, PAGE_NONE); #endif
}
/* * The exceptions stack mappings in the per cpu area are protected * by guard pages so each stack must be mapped separately. DB2 is * not mapped; it just exists to catch triple nesting of #DB.
*/
cea_map_stack(DF);
cea_map_stack(NMI);
cea_map_stack(DB);
cea_map_stack(MCE);
/* Setup the fixmap mappings only once per-processor */ staticvoid __init setup_cpu_entry_area(unsignedint cpu)
{ struct cpu_entry_area *cea = get_cpu_entry_area(cpu); #ifdef CONFIG_X86_64 /* On 64-bit systems, we use a read-only fixmap GDT and TSS. */
pgprot_t gdt_prot = PAGE_KERNEL_RO;
pgprot_t tss_prot = PAGE_KERNEL_RO; #else /* * On 32-bit systems, the GDT cannot be read-only because * our double fault handler uses a task gate, and entering through * a task gate needs to change an available TSS to busy. If the * GDT is read-only, that will triple fault. The TSS cannot be * read-only because the CPU writes to it on task switches.
*/
pgprot_t gdt_prot = PAGE_KERNEL;
pgprot_t tss_prot = PAGE_KERNEL; #endif
/* * The Intel SDM says (Volume 3, 7.2.1): * * Avoid placing a page boundary in the part of the TSS that the * processor reads during a task switch (the first 104 bytes). The * processor may not correctly perform address translations if a * boundary occurs in this area. During a task switch, the processor * reads and writes into the first 104 bytes of each TSS (using * contiguous physical addresses beginning with the physical address * of the first byte of the TSS). So, after TSS access begins, if * part of the 104 bytes is not physically contiguous, the processor * will access incorrect information without generating a page-fault * exception. * * There are also a lot of errata involving the TSS spanning a page * boundary. Assert that we're not doing that.
*/
BUILD_BUG_ON((offsetof(struct tss_struct, x86_tss) ^
offsetofend(struct tss_struct, x86_tss)) & PAGE_MASK);
BUILD_BUG_ON(sizeof(struct tss_struct) % PAGE_SIZE != 0); /* * VMX changes the host TR limit to 0x67 after a VM exit. This is * okay, since 0x67 covers the size of struct x86_hw_tss. Make sure * that this is correct.
*/
BUILD_BUG_ON(offsetof(struct tss_struct, x86_tss) != 0);
BUILD_BUG_ON(sizeof(struct x86_hw_tss) != 0x68);
/* The +1 is for the readonly IDT: */
BUILD_BUG_ON((CPU_ENTRY_AREA_PAGES+1)*PAGE_SIZE != CPU_ENTRY_AREA_MAP_SIZE);
BUG_ON(CPU_ENTRY_AREA_BASE & ~PMD_MASK);
start = CPU_ENTRY_AREA_BASE;
end = start + CPU_ENTRY_AREA_MAP_SIZE;
/* Careful here: start + PMD_SIZE might wrap around */ for (; start < end && start >= CPU_ENTRY_AREA_BASE; start += PMD_SIZE)
populate_extra_pte(start); #endif
}
/* * This is the last essential update to swapper_pgdir which needs * to be synchronized to initial_page_table on 32bit.
*/
sync_initial_page_table();
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.