diff --git a/arch/x86/core/intel64.cmake b/arch/x86/core/intel64.cmake index f6097e5476a..056ae2c595d 100644 --- a/arch/x86/core/intel64.cmake +++ b/arch/x86/core/intel64.cmake @@ -1,3 +1,14 @@ # Copyright (c) 2019 Intel Corp. # SPDX-License-Identifier: Apache-2.0 +# +# XXX: When using the Intel toolchain, cmake doesn't recognize .S files +# automatically, and I can't be bothered to figure out how to fix this. +# + +set_property(SOURCE intel64/locore.S PROPERTY LANGUAGE ASM) + +zephyr_library_sources( + intel64/locore.S + intel64/thread.c +) diff --git a/arch/x86/core/intel64/locore.S b/arch/x86/core/intel64/locore.S new file mode 100644 index 00000000000..58a1f131493 --- /dev/null +++ b/arch/x86/core/intel64/locore.S @@ -0,0 +1,156 @@ +/* + * Copyright (c) 2019 Intel Corporation + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include + +#define NR_IDT_VECTOR 256 /* full IDT, we're not short of RAM */ +#define IRQ_STACK_SIZE 4096 /* must be a multiple of 16 */ + +.section .locore,"ax" +.code32 + +.globl __start +__start: + + /* + * multiboot starts us here in 32-bit flat mode with interrupts + * and paging disabled. first, switch to our own GDT and stack. + */ + + lgdt gdt48 + lidt idt48 + jmpl $X86_KERNEL_CS_32, $1f +1: movw $X86_KERNEL_DS_32, %ax + movw %ax, %ds + movw %ax, %ss + movw %ax, %es + movw %ax, %fs + movw %ax, %gs + + movl $(irq_stack + IRQ_STACK_SIZE), %esp + + /* + * transition to long mode, by the book. + */ + + movl %cr4, %eax /* enable PAE */ + orl $CR4_PAE, %eax + movl %eax, %cr4 + + movl $pml4, %eax /* load page base */ + movl %eax, %cr3 + + movl $X86_EFER_MSR, %ecx /* enable long mode */ + rdmsr + orl $X86_EFER_MSR_LME, %eax + wrmsr + + movl %cr0, %eax /* enable paging */ + orl $CR0_PG, %eax + movl %eax, %cr0 + + /* + * jump into long mode, reload the segment registers (again). + */ + + jmpl $X86_KERNEL_CS_64, $1f +.code64 +1: movl $X86_KERNEL_DS_64, %eax + movw %ax, %ds + movw %ax, %es + movw %ax, %ss + movw %ax, %fs + movw %ax, %gs + + /* + * func() is just a placeholder C function. don't replace CALL + * with JMP; we must honor the ABI stack alignment requirements. + */ + + call func + +stop: jmp stop + +/* + * The multiboot header is identical (for obvious reasons) to the 32-bit + * version in ia32/crt0.S. They should be refactored into a common file. + */ + +#ifdef CONFIG_X86_MULTIBOOT + .align 4 + .long X86_MULTIBOOT_HEADER_MAGIC + .long X86_MULTIBOOT_HEADER_FLAGS + .long -(X86_MULTIBOOT_HEADER_MAGIC + X86_MULTIBOOT_HEADER_FLAGS) +#ifdef CONFIG_X86_MULTIBOOT_FRAMEBUF + .fill 5,4,0 /* (unused exec layout) */ + .long 0 /* linear graphics mode */ + .long CONFIG_X86_MULTIBOOT_FRAMEBUF_X /* width */ + .long CONFIG_X86_MULTIBOOT_FRAMEBUF_Y /* height */ + .long 32 /* depth */ +#endif /* CONFIG_X86_MULTIBOOT_FRAMEBUF */ +#endif + +/* + * GDT - a single GDT is shared by all threads (and, eventually, all CPUs). + * This layout must agree with the selectors in intel64/kernel_arch_data.h. + */ + +.align 8 + +gdt: + .word 0, 0, 0, 0 /* 0x00: null descriptor */ + .word 0xFFFF, 0, 0x9A00, 0x00CF /* 0x08: 32-bit kernel code */ + .word 0xFFFF, 0, 0x9200, 0x00CF /* 0x10: 32-bit kernel data */ + .word 0, 0, 0x9800, 0x0020 /* 0x18: 64-bit kernel code */ + +gdt48: + .word (gdt48 - gdt - 1) + .long gdt + +/* + * IDT. Empty for now. + */ + +.align 8 + +idt: .fill (NR_IDT_VECTOR*16), 1, 0 +idt48: + .word (idt48 - idt - 1) + .long idt + +/* + * Page tables. Long mode requires them, but we don't implement any memory + * protection yet, so these simply identity-map the first 4GB w/ 1GB pages. + */ + +.align 4096 + +pml4: + .long pdp + 0x03 /* 0x03 = R/W, P */ + .long 0 + .fill 4088, 1, 0 + +pdp: .long 0x00000183 /* 0x183 = G, 1GB, R/W, P */ + .long 0 + .long 0x40000183 + .long 0 + .long 0x80000183 + .long 0 + .long 0xC0000183 + .long 0 + .fill 4064, 1, 0 + +/* + * For now, the "IRQ stack" is just used as a scratch stack during + * early kernel initialization. + */ + +.align 16 +irq_stack: + .fill IRQ_STACK_SIZE, 1, 0xFF + diff --git a/arch/x86/core/intel64/thread.c b/arch/x86/core/intel64/thread.c new file mode 100644 index 00000000000..b6be0727956 --- /dev/null +++ b/arch/x86/core/intel64/thread.c @@ -0,0 +1,10 @@ +/* + * Copyright (c) 2019 Intel Corporation + * SPDX-License-Identifier: Apache-2.0 + */ + +void func(void) +{ + for (;;) { + } +} diff --git a/arch/x86/include/intel64/kernel_arch_data.h b/arch/x86/include/intel64/kernel_arch_data.h index 4cc3275cd19..5b495ed1d02 100644 --- a/arch/x86/include/intel64/kernel_arch_data.h +++ b/arch/x86/include/intel64/kernel_arch_data.h @@ -6,4 +6,13 @@ #ifndef ZEPHYR_ARCH_X86_INCLUDE_INTEL64_KERNEL_ARCH_DATA_H_ #define ZEPHYR_ARCH_X86_INCLUDE_INTEL64_KERNEL_ARCH_DATA_H_ +/* + * GDT selectors - these must agree with the GDT layout in locore.S. + */ + +#define X86_KERNEL_CS_32 0x08 /* 32-bit kernel code */ +#define X86_KERNEL_DS_32 0x10 /* 32-bit kernel data */ +#define X86_KERNEL_CS_64 0x18 /* 64-bit kernel code */ +#define X86_KERNEL_DS_64 0x00 /* 64-bit kernel data (null!) */ + #endif /* ZEPHYR_ARCH_X86_INCLUDE_INTEL64_KERNEL_ARCH_DATA_H_ */ diff --git a/arch/x86/include/intel64/kernel_arch_func.h b/arch/x86/include/intel64/kernel_arch_func.h index edb2646e6d5..0fd73a53ab6 100644 --- a/arch/x86/include/intel64/kernel_arch_func.h +++ b/arch/x86/include/intel64/kernel_arch_func.h @@ -6,4 +6,21 @@ #ifndef ZEPHYR_ARCH_X86_INCLUDE_INTEL64_KERNEL_ARCH_FUNC_H_ #define ZEPHYR_ARCH_X86_INCLUDE_INTEL64_KERNEL_ARCH_FUNC_H_ +#ifndef _ASMLANGUAGE + +#define z_is_in_isr() (0) + +static ALWAYS_INLINE void +z_set_thread_return_value(struct k_thread *thread, unsigned int value) +{ + /* nothing */ ; +} + +static inline void kernel_arch_init(void) +{ + /* nothing */ ; +} + +#endif /* _ASMLANGUAGE */ + #endif /* ZEPHYR_ARCH_X86_INCLUDE_INTEL64_KERNEL_ARCH_FUNC_H_ */ diff --git a/arch/x86/include/intel64/kernel_arch_thread.h b/arch/x86/include/intel64/kernel_arch_thread.h index 56373d3d015..ee16357e64c 100644 --- a/arch/x86/include/intel64/kernel_arch_thread.h +++ b/arch/x86/include/intel64/kernel_arch_thread.h @@ -6,4 +6,11 @@ #ifndef ZEPHYR_ARCH_X86_INCLUDE_INTEL64_KERNEL_ARCH_THREAD_H_ #define ZEPHYR_ARCH_X86_INCLUDE_INTEL64_KERNEL_ARCH_THREAD_H_ +#ifndef _ASMLANGUAGE + +struct _callee_saved { }; +struct _thread_arch { }; + +#endif /* _ASMLANGUAGE */ + #endif /* ZEPHYR_ARCH_X86_INCLUDE_INTEL64_KERNEL_ARCH_THREAD_H_ */ diff --git a/arch/x86/intel64.cmake b/arch/x86/intel64.cmake index bc6d571e12c..24062d27f4f 100644 --- a/arch/x86/intel64.cmake +++ b/arch/x86/intel64.cmake @@ -1,4 +1,6 @@ # Copyright (c) 2019 Intel Corp. # SPDX-License-Identifier: Apache-2.0 -message(FATAL_ERROR "nice try, no Intel64 support yet") +zephyr_cc_option(-m64) + +add_subdirectory(core) diff --git a/include/arch/x86/intel64/arch.h b/include/arch/x86/intel64/arch.h index d50b8708607..9216d476a29 100644 --- a/include/arch/x86/intel64/arch.h +++ b/include/arch/x86/intel64/arch.h @@ -3,7 +3,32 @@ * SPDX-License-Identifier: Apache-2.0 */ +/* + * dummies for now + */ + #ifndef ZEPHYR_INCLUDE_ARCH_X86_INTEL64_ARCH_H_ #define ZEPHYR_INCLUDE_ARCH_X86_INTEL64_ARCH_H_ +#define Z_ARCH_THREAD_STACK_DEFINE(sym, size) \ + struct _k_thread_stack_element sym[size] + +#define Z_ARCH_THREAD_STACK_SIZEOF(sym) sizeof(sym) +#define Z_ARCH_THREAD_STACK_BUFFER(sym) ((char *) sym) + +#define Z_IRQ_TO_INTERRUPT_VECTOR(irq) (0) +#define Z_ARCH_IRQ_CONNECT(irq_p, priority_p, isr_p, isr_param_p, flags_p) + +#define z_arch_irq_lock() (0) +#define z_arch_irq_unlock(k) + +#define z_x86_msr_read(a) (0) + +#define sys_read8(x) (0) +#define sys_read32(x) (0) +#define sys_in32(x) (0) +#define sys_write8(x,y) +#define sys_write32(x,y) +#define sys_out32(x, y) + #endif /* ZEPHYR_INCLUDE_ARCH_X86_INTEL64_ARCH_H_ */ diff --git a/include/arch/x86/intel64/linker.ld b/include/arch/x86/intel64/linker.ld new file mode 100644 index 00000000000..819a7cf964f --- /dev/null +++ b/include/arch/x86/intel64/linker.ld @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2019 Intel Corp. + * SPDX-License-Identifier: Apache-2.0 + */ + +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) + *(.locore.*) + } + + /* + * The parts of the system that don't benefit from being in the locore + * start at the 1MB mark, otherwise the system size would be artificially + * clamped by the ISA memory hole/ROM space at 0x90000-0xFFFFF. + */ + + .text 0x100000 : ALIGN(16) + { + *(.text) + *(.text.*) + *(.rodata.*) + } + + /DISCARD/ : + { + *(.comment*) + *(.debug*) + *(.got*) + *(.igot.*) + *(.iplt) + *(.note.GNU-stack) + *(.rela.*) + } +} diff --git a/soc/x86/apollo_lake/linker.ld b/soc/x86/apollo_lake/linker.ld index 6a10c7dd8d2..b6d7703c090 100644 --- a/soc/x86/apollo_lake/linker.ld +++ b/soc/x86/apollo_lake/linker.ld @@ -1,5 +1,6 @@ /* * Copyright (c) 2011-2014, Wind River Systems, Inc. + * Copyright (c) 2019 Intel Corp. * * SPDX-License-Identifier: Apache-2.0 */ @@ -7,6 +8,12 @@ #include #include +#ifdef CONFIG_X86_LONGMODE + +#include + +#else /* IA32 */ + #define PHYS_LOAD_ADDR DT_PHYS_RAM_ADDR #define PHYS_RAM_ADDR DT_PHYS_RAM_ADDR @@ -25,3 +32,4 @@ MEMORY #include +#endif /* CONFIG_X86_LONGMODE */