| // Copyright 2020 The Fuchsia Authors | |
| // | |
| // Use of this source code is governed by a MIT-style | |
| // license that can be found in the LICENSE file or at | |
| // https://opensource.org/licenses/MIT | |
| #include <lib/arch/asm.h> | |
| #include <lib/arch/ticks.h> | |
| #include <lib/arch/x86/cpuid-asm.h> | |
| #include <lib/arch/x86/msr.h> | |
| #include <zircon/tls.h> | |
| #include <phys/runtime/stack.h> | |
| // This is the entry point from the boot loader or thereabouts. | |
| // It receives one argument, in %rsi, usually a pointer (physical address). | |
| // | |
| // In a ZBI executable, this is where zbi_kernel_t::entry points and | |
| // %rsi holds the address of the data ZBI. | |
| .function _start, global | |
| // As early as possible collect the time stamp. | |
| sample_ticks | |
| // Disable asynchronous interrupts in case the boot loader left them on. | |
| cli | |
| // Zero the non-CS segment registers in case the bootloader left anything | |
| // there: DS, ES, and SS are vestigial; FS is unused in the kernel; GS will | |
| // be reset below. | |
| xor %eax, %eax | |
| mov %eax, %ds | |
| mov %eax, %es | |
| mov %eax, %fs | |
| mov %eax, %gs | |
| mov %eax, %ss | |
| // Clear any incoming stack pointer so it can't be used accidentally | |
| // before the proper stack is set up below. | |
| xor %esp, %esp | |
| // Clear frame pointer: at the root of the call stack. | |
| xor %ebp, %ebp | |
| // Save the timestamp since %rax must be clobbered below. | |
| mov %rax, %rbx | |
| // Clear bss. Note this assumes it's aligned to 8, which is ensured | |
| // by the bss declaration below. | |
| lea _edata(%rip), %rdi | |
| lea _end(%rip), %rcx | |
| sub %rdi, %rcx | |
| shr $3, %rcx | |
| xor %eax, %eax | |
| cld // Assume nothing. ABI requires that DF be clear. | |
| rep stosq | |
| // Save first argument to PhysMain in a call-saved register. | |
| // The time stamp is already safe in %rbx. | |
| mov %rsi, %r12 | |
| // Clear the IDT to zero address and zero limit, so any trap is sure to | |
| // get a triple-fault. We've just cleared the .bss containing the stack, | |
| // so these bytes are known to be zero. | |
| lidt boot_stack(%rip) | |
| // Get all the cpuid data in place. | |
| // This only needs the basic stack to call and return. | |
| lea (boot_stack + BOOT_STACK_SIZE)(%rip), %rsp | |
| call InitializeBootCpuid | |
| // Set up the secondary stacks and the thread pointer area. | |
| lea boot_thread_pointer(%rip), %rax | |
| // The wrgsbase instruction is more efficient when it's supported. But using | |
| // it requires both checking CPUID for its support and then enabling it in | |
| // %cr4. There is no real need to bother with any of that in assembly since | |
| // one wrmsr at boot is not costly enough to bother avoiding. The kernel can | |
| // check for and enable fsgsbase instructions easily and cleanly from C++ | |
| // before it does anything that is performance-sensitive enough to warrant | |
| // preferring them over the MSRs. | |
| wrmsr64 MSR_IA32_GS_BASE | |
| .Lstack_guard: | |
| // Use the best hardware randomness available for the stack canary value. | |
| testl $CPUID_EXTF_RDSEED, (gBootCpuidExtf + CPUID_EBX)(%rip) | |
| jnz .Lrdseed | |
| testl $CPUID_FEATURE_RDRAND, (gBootCpuidFeature + CPUID_ECX)(%rip) | |
| jnz .Lrdrand | |
| // The only "randomness" readily available is our own load address, so | |
| // swizzle that in with some arbitrary bits. | |
| lea _start(%rip), %rcx | |
| movabs $0xdeadbeef1ee2d00d, %rax | |
| xor %rcx, %rax | |
| jmp .Lstack_guard_write | |
| .Lrdrand: | |
| rdrand %rax | |
| jmp .Lstack_guard_write | |
| .Lrdseed: | |
| rdseed %rax | |
| .Lstack_guard_write: | |
| mov %rax, %gs:ZX_TLS_STACK_GUARD_OFFSET | |
| #if __has_feature(safe_stack) | |
| lea (boot_unsafe_stack + BOOT_STACK_SIZE)(%rip), %rax | |
| mov %rax, %gs:ZX_TLS_UNSAFE_SP_OFFSET | |
| #endif | |
| // Now the full C++ ABI is available. Apply our own relocations before | |
| // anything that might depend on them. The PhysMain arguments are safe in | |
| // call-saved %r12 and %rbx. | |
| call ApplyRelocationsToSelf | |
| // This could theoretically be a tail call since it's obliged never to | |
| // return, but it's nice to have the caller in a backtrace (and the call | |
| // implicitly adjusts the stack alignment as the ABI requires). | |
| mov %r12, %rdi | |
| mov %rbx, %rsi | |
| call CppPhysMain | |
| // Trap forever just in case it does return. | |
| 0:ud2 | |
| jmp 0b | |
| .end_function | |
| .object boot_thread_area, bss, local, align=8 | |
| #if ZX_TLS_UNSAFE_SP_OFFSET < ZX_TLS_STACK_GUARD_OFFSET | |
| .error "TLS ABI layout??" | |
| #endif | |
| .label boot_thread_pointer, global | |
| .skip ZX_TLS_UNSAFE_SP_OFFSET + 8 | |
| .end_object |