Changeset View
Standalone View
sys/amd64/amd64/machdep.c
Show First 20 Lines • Show All 1,271 Lines • ▼ Show 20 Lines | #endif | ||||||||
/* | /* | ||||||||
* Make hole for "AP -> long mode" bootstrap code. The | * Make hole for "AP -> long mode" bootstrap code. The | ||||||||
* mp_bootaddress vector is only available when the kernel | * mp_bootaddress vector is only available when the kernel | ||||||||
* is configured to support APs and APs for the system start | * is configured to support APs and APs for the system start | ||||||||
* in real mode mode (e.g. SMP bare metal). | * in real mode mode (e.g. SMP bare metal). | ||||||||
*/ | */ | ||||||||
#ifdef SMP | #ifdef SMP | ||||||||
mp_bootaddress(physmap, &physmap_idx); | alloc_ap_trampoline(physmap, &physmap_idx); | ||||||||
#endif | #endif | ||||||||
/* call pmap initialization to make new kernel address space */ | /* call pmap initialization to make new kernel address space */ | ||||||||
pmap_bootstrap(&first); | pmap_bootstrap(&first); | ||||||||
/* | /* | ||||||||
* Size up each available chunk of physical memory. | * Size up each available chunk of physical memory. | ||||||||
* | * | ||||||||
▲ Show 20 Lines • Show All 304 Lines • ▼ Show 20 Lines | |||||||||
u_int64_t | u_int64_t | ||||||||
hammer_time(u_int64_t modulep, u_int64_t physfree) | hammer_time(u_int64_t modulep, u_int64_t physfree) | ||||||||
{ | { | ||||||||
caddr_t kmdp; | caddr_t kmdp; | ||||||||
int gsel_tss, x; | int gsel_tss, x; | ||||||||
struct pcpu *pc; | struct pcpu *pc; | ||||||||
struct xstate_hdr *xhdr; | struct xstate_hdr *xhdr; | ||||||||
u_int64_t rsp0; | uint64_t cr3, rsp0; | ||||||||
pml4_entry_t *pml4e; | |||||||||
pdp_entry_t *pdpe; | |||||||||
pd_entry_t *pde; | |||||||||
char *env; | char *env; | ||||||||
struct user_segment_descriptor *gdt; | struct user_segment_descriptor *gdt; | ||||||||
struct region_descriptor r_gdt; | struct region_descriptor r_gdt; | ||||||||
size_t kstack0_sz; | size_t kstack0_sz; | ||||||||
int late_console; | int late_console; | ||||||||
bool efi_boot; | bool efi_boot; | ||||||||
TSRAW(&thread0, TS_ENTER, __func__, NULL); | TSRAW(&thread0, TS_ENTER, __func__, NULL); | ||||||||
/* | |||||||||
* Calculate kernphys by inspecting page table created by loader. | |||||||||
* The assumptions: | |||||||||
* - kernel is mapped at KERNBASE, backed by contiguous phys memory | |||||||||
* aligned at 2M, below 4G (the latter is important for AP startup) | |||||||||
markjUnsubmitted Done Inline Actions
markj: | |||||||||
* - there is a 2M hole at KERNBASE | |||||||||
* - kernel is mapped with 2M superpages | |||||||||
* - all participating memory, i.e. kernel, modules, metadata, | |||||||||
* page table is accessible by pre-created 1:1 mapping | |||||||||
* (right now loader creates 1:1 mapping for lower 4G, and all | |||||||||
* memory is from there) | |||||||||
* - there is a usable memory block right after the end of the | |||||||||
* mapped kernel and all modules/metadata, pointed to by | |||||||||
* physfree, for early allocations | |||||||||
*/ | |||||||||
cr3 = rcr3(); | |||||||||
pml4e = (pml4_entry_t *)(cr3 & ~PAGE_MASK) + pmap_pml4e_index( | |||||||||
Done Inline ActionsOut of paranoia, perhaps CR3_PCID_SAVE should be masked off too. markj: Out of paranoia, perhaps CR3_PCID_SAVE should be masked off too. | |||||||||
Done Inline ActionsI am quite sure that we cannot read CR3_PCID_SAVE back from %CR3. It is not defined in SDM as a bit in the register, Intel only talks about 'operation that has bit 63 set in the source operand' as something that preserves TLB. In fact, we already relay on that in when storing SAVED_UCR3. Also, loader does not enable PCID at all, and I am sure that firmware cannot safely pass control to OS with PCID enabled either. I can add it if you insist, but this is excessive IMO. kib: I am quite sure that we cannot read CR3_PCID_SAVE back from %CR3. It is not defined in SDM as… | |||||||||
Done Inline ActionsOk, I don't insist at all. I just wondered if it would be sensible to mask off any upper flag bits, but I didn't look at the CR3 layout closely. markj: Ok, I don't insist at all. I just wondered if it would be sensible to mask off any upper flag… | |||||||||
(vm_offset_t)hammer_time); | |||||||||
pdpe = (pdp_entry_t *)(*pml4e & ~PAGE_MASK) + pmap_pdpe_index( | |||||||||
(vm_offset_t)hammer_time); | |||||||||
pde = (pd_entry_t *)(*pdpe & ~PAGE_MASK) + pmap_pde_index( | |||||||||
(vm_offset_t)hammer_time); | |||||||||
kernphys = (vm_paddr_t)(*pde & ~PDRMASK) - | |||||||||
(((vm_paddr_t)hammer_time - KERNBASE) & ~PDRMASK); | |||||||||
Done Inline ActionsLogically, shouldn't it be (vm_paddr_t)((vm_offset_t)hammer_time - KERNBASE)? markj: Logically, shouldn't it be `(vm_paddr_t)((vm_offset_t)hammer_time - KERNBASE)`? | |||||||||
/* Fix-up for 2M hole */ | |||||||||
physfree += kernphys; | |||||||||
kernphys += NBPDR; | |||||||||
kmdp = init_ops.parse_preload_data(modulep); | kmdp = init_ops.parse_preload_data(modulep); | ||||||||
efi_boot = preload_search_info(kmdp, MODINFO_METADATA | | efi_boot = preload_search_info(kmdp, MODINFO_METADATA | | ||||||||
MODINFOMD_EFI_MAP) != NULL; | MODINFOMD_EFI_MAP) != NULL; | ||||||||
if (!efi_boot) { | if (!efi_boot) { | ||||||||
/* Tell the bios to warmboot next time */ | /* Tell the bios to warmboot next time */ | ||||||||
atomic_store_short((u_short *)0x472, 0x1234); | atomic_store_short((u_short *)0x472, 0x1234); | ||||||||
Show All 29 Lines | hammer_time(u_int64_t modulep, u_int64_t physfree) | ||||||||
* This may be done better later if it gets more high level | * This may be done better later if it gets more high level | ||||||||
* components in it. If so just link td->td_proc here. | * components in it. If so just link td->td_proc here. | ||||||||
*/ | */ | ||||||||
proc_linkup0(&proc0, &thread0); | proc_linkup0(&proc0, &thread0); | ||||||||
/* Init basic tunables, hz etc */ | /* Init basic tunables, hz etc */ | ||||||||
init_param1(); | init_param1(); | ||||||||
thread0.td_kstack = physfree + KERNBASE; | thread0.td_kstack = physfree - kernphys + KERNBASE + NBPDR; | ||||||||
Done Inline ActionsIMO it would be nice to provide a KERNSTART or kernvirt (corresponding to kernphys) equal to KERNBASE+NBPDR. markj: IMO it would be nice to provide a KERNSTART or kernvirt (corresponding to kernphys) equal to… | |||||||||
Done Inline ActionsYes, I pondered this as well. kib: Yes, I pondered this as well. | |||||||||
thread0.td_kstack_pages = kstack_pages; | thread0.td_kstack_pages = kstack_pages; | ||||||||
kstack0_sz = thread0.td_kstack_pages * PAGE_SIZE; | kstack0_sz = thread0.td_kstack_pages * PAGE_SIZE; | ||||||||
bzero((void *)thread0.td_kstack, kstack0_sz); | bzero((void *)thread0.td_kstack, kstack0_sz); | ||||||||
physfree += kstack0_sz; | physfree += kstack0_sz; | ||||||||
/* | /* | ||||||||
* Initialize enough of thread0 for delayed invalidation to | * Initialize enough of thread0 for delayed invalidation to | ||||||||
* work very early. Rely on thread0.td_base_pri | * work very early. Rely on thread0.td_base_pri | ||||||||
Show All 20 Lines | hammer_time(u_int64_t modulep, u_int64_t physfree) | ||||||||
r_gdt.rd_limit = NGDT * sizeof(gdt[0]) - 1; | r_gdt.rd_limit = NGDT * sizeof(gdt[0]) - 1; | ||||||||
r_gdt.rd_base = (long)gdt; | r_gdt.rd_base = (long)gdt; | ||||||||
lgdt(&r_gdt); | lgdt(&r_gdt); | ||||||||
wrmsr(MSR_FSBASE, 0); /* User value */ | wrmsr(MSR_FSBASE, 0); /* User value */ | ||||||||
wrmsr(MSR_GSBASE, (u_int64_t)pc); | wrmsr(MSR_GSBASE, (u_int64_t)pc); | ||||||||
wrmsr(MSR_KGSBASE, 0); /* User value while in the kernel */ | wrmsr(MSR_KGSBASE, 0); /* User value while in the kernel */ | ||||||||
dpcpu_init((void *)(physfree + KERNBASE), 0); | dpcpu_init((void *)(physfree - kernphys + KERNBASE + NBPDR), 0); | ||||||||
physfree += DPCPU_SIZE; | physfree += DPCPU_SIZE; | ||||||||
amd64_bsp_pcpu_init1(pc); | amd64_bsp_pcpu_init1(pc); | ||||||||
/* Non-late cninit() and printf() can be moved up to here. */ | /* Non-late cninit() and printf() can be moved up to here. */ | ||||||||
/* | /* | ||||||||
* Initialize mutexes. | * Initialize mutexes. | ||||||||
* | * | ||||||||
* icu_lock: in order to allow an interrupt to occur in a critical | * icu_lock: in order to allow an interrupt to occur in a critical | ||||||||
▲ Show 20 Lines • Show All 1,109 Lines • Show Last 20 Lines |