1/* 2 * Copyright 2021-2022 Haiku, Inc. All rights reserved. 3 * Released under the terms of the MIT License. 4 * 5 * Copyright 2008, Dustin Howett, dustin.howett@gmail.com. All rights reserved. 6 * Copyright 2004-2010, Axel D��rfler, axeld@pinc-software.de. 7 * Distributed under the terms of the MIT License. 8 * 9 * Copyright 2001, Travis Geiselbrecht. All rights reserved. 10 * Distributed under the terms of the NewOS License. 11 */ 12 13 14#include "arch_smp.h" 15 16#include <boot/stage2.h> 17 18 19//#define TRACE_SMP 20#ifdef TRACE_SMP 21# define TRACE(x...) dprintf(x) 22#else 23# define TRACE(x...) ; 24#endif 25 26 27extern "C" void long_smp_trampoline(void); 28extern "C" void long_smp_trampoline_args(void); 29extern "C" void long_smp_trampoline_end(void); 30extern "C" uint64 gLongGDTR; 31 32struct gdtr { 33 uint16 limit; 34 uint32 base; 35 unsigned char null[8]; 36 unsigned char code[8]; 37 unsigned char data[8]; 38} __attribute__((packed)); 39 40// Arguments passed to the SMP trampoline. 41struct long_trampoline_args { 42 uint32 trampoline; // Trampoline address 43 uint32 gdt32; // 32-bit GDTR 44 uint32 pml4; // 64-bit PML4 45 uint32 gdt64; // 64-bit GDTR 46 uint64 kernel_entry; // Kernel entry point 47 uint64 kernel_args; // Kernel arguments 48 uint64 current_cpu; // CPU number 49 uint64 stack_top; // Kernel stack 50 volatile uint64 sentinel; // Sentinel, AP sets to 0 when finished 51 52 // smp_boot_other_cpus puts the GDTR here. 53 struct gdtr gdtr; 54}; 55 56 57void 58copy_trampoline_code(uint64 trampolineCode, uint64 trampolineStack) 59{ 60 TRACE("copying the trampoline code to %p from %p\n", (char*)trampolineCode, (const void*)&long_smp_trampoline); 61 TRACE("size of trampoline code = %" PRIu64 " bytes\n", (uint64)&long_smp_trampoline_end - (uint64)&long_smp_trampoline); 62 memcpy((char *)trampolineCode, (const void*)&long_smp_trampoline, 63 (uint64)&long_smp_trampoline_end - (uint64)&long_smp_trampoline); 64} 65 66 67void 68prepare_trampoline_args(uint64 trampolineCode, uint64 trampolineStack, 69 uint32 pagedir, uint64 kernelEntry, addr_t virtKernelArgs, 70 uint32 currentCpu) 71{ 72 long_trampoline_args* args = (long_trampoline_args *)trampolineStack; 73 args->trampoline = trampolineCode; 74 75 args->gdt32 = (uint64) &args->gdtr; 76 args->gdtr.limit = 23; 77 args->gdtr.base = (uint32)(uint64)args->gdtr.null; 78 #define COPY_ARRAY(A, X0, X1, X2, X3, X4, X5, X6, X7) \ 79 { A[0] = X0; A[1] = X1; A[2] = X2; A[3] = X3; A[4] = X4; A[5] = X5; A[6] = X6; A[7] = X7; } 80 COPY_ARRAY(args->gdtr.null, 0, 0, 0, 0, 0, 0, 0, 0); 81 COPY_ARRAY(args->gdtr.code, 0xff, 0xff, 0, 0, 0, 0x9a, 0xcf, 0); 82 COPY_ARRAY(args->gdtr.data, 0xff, 0xff, 0, 0, 0, 0x92, 0xcf, 0); 83 #undef COPY_ARRAY 84 args->gdt64 = (uint32_t)(uint64_t)&gLongGDTR; 85 86 args->pml4 = pagedir; 87 args->kernel_entry = kernelEntry; 88 args->kernel_args = virtKernelArgs; 89 args->current_cpu = currentCpu; 90 args->stack_top = gKernelArgs.cpu_kstack[currentCpu].start 91 + gKernelArgs.cpu_kstack[currentCpu].size; 92 args->sentinel = 1; 93 94 // put the args in the right place 95 uint32 * args_ptr = 96 (uint32 *)(trampolineCode + (uint64)long_smp_trampoline_args - (uint64)long_smp_trampoline); 97 *args_ptr = (uint32)trampolineStack; 98} 99 100 101uint32 102get_sentinel(uint64 trampolineStack) 103{ 104 long_trampoline_args* args = (long_trampoline_args *)trampolineStack; 105 return args->sentinel; 106} 107