kernel/x86: Initialize CR0 in the kernel more than the bootloader.
The bootloader is now only responsible for setting up Protected Mode and Paging. It otherwise preserves the existing CR0, and leaves setup to the kernel. The kernel now sets CR0 for each CPU in preboot_init_percpu(). Some redundant sets are removed from x86_init_fpu, which now panic()s in the case where we don't have a FPU, and avoids unnecessary prints. This fixes a massive oversight where CR0 was never reset on x86 systems booted using the EFI loader, except on the boot CPU! That meant that NUMERIC_ERROR and possibly even WRITE_PROTECT were simply not set on non-boot CPUs, unless the EFI BIOS had set them up already. (On the BIOS loader, smp_start_kernel() ran on all CPUs.) Fixes NVMM initialization on non-boot CPUs on Intel hardware.
This commit is contained in:
@@ -449,10 +449,14 @@
|
||||
| X86_EFLAGS_AUXILIARY_CARRY | X86_EFLAGS_ZERO | X86_EFLAGS_SIGN \
|
||||
| X86_EFLAGS_DIRECTION | X86_EFLAGS_OVERFLOW)
|
||||
|
||||
#define CR0_PAGING (1UL << 31)
|
||||
#define CR0_CACHE_DISABLE (1UL << 30)
|
||||
#define CR0_NOT_WRITE_THROUGH (1UL << 29)
|
||||
#define CR0_WRITE_PROTECT (1UL << 16)
|
||||
#define CR0_NUMERIC_ERROR (1UL << 5)
|
||||
#define CR0_FPU_EMULATION (1UL << 2)
|
||||
#define CR0_MONITOR_FPU (1UL << 1)
|
||||
#define CR0_PROTECTED_MODE (1UL << 0)
|
||||
|
||||
// Control Register CR4 flags §2.5
|
||||
// Intel® 64 and IA-32 Architectures Software Developer's Manual Volume 3A: System Programming Guide, Part 1
|
||||
|
||||
@@ -318,8 +318,6 @@ long_smp_start_kernel(void)
|
||||
{
|
||||
uint32 cpu = smp_get_current_cpu();
|
||||
|
||||
// Important. Make sure supervisor threads can fault on read only pages...
|
||||
asm("movl %%eax, %%cr0" : : "a" ((1 << 31) | (1 << 16) | (1 << 5) | 1));
|
||||
asm("cld");
|
||||
asm("fninit");
|
||||
enable_sse();
|
||||
|
||||
@@ -372,8 +372,6 @@ init_page_directory(void)
|
||||
// switch to the new pgdir and enable paging
|
||||
asm("movl %0, %%eax;"
|
||||
"movl %%eax, %%cr3;" : : "m" (sPageDirectory) : "eax");
|
||||
// Important. Make sure supervisor threads can fault on read only pages...
|
||||
asm("movl %%eax, %%cr0" : : "a" ((1 << 31) | (1 << 16) | (1 << 5) | 1));
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -89,8 +89,6 @@ smp_start_kernel(void)
|
||||
preloaded_elf32_image *image = static_cast<preloaded_elf32_image *>(
|
||||
gKernelArgs.kernel_image.Pointer());
|
||||
|
||||
// Important. Make sure supervisor threads can fault on read only pages...
|
||||
asm("movl %%eax, %%cr0" : : "a" ((1 << 31) | (1 << 16) | (1 << 5) | 1));
|
||||
asm("cld");
|
||||
asm("fninit");
|
||||
|
||||
|
||||
@@ -53,12 +53,9 @@ FUNCTION(arch_enter_kernel):
|
||||
movl %esi, %eax
|
||||
lgdt (%eax)
|
||||
|
||||
// initialize CR0
|
||||
// - bit #31: Enable Paging
|
||||
// - bit #16: Write Protect
|
||||
// - bit #5: Numeric Error Handling
|
||||
// - bit #0: Protected Mode
|
||||
movl $0x80010021, %eax
|
||||
movl %cr0, %eax
|
||||
orl $0x01, %eax // set the PE bit (0) to switch to protected mode
|
||||
orl $0x80000000, %eax // set the PG bit (31) to enable paging
|
||||
movl %eax, %cr0
|
||||
|
||||
// Set data segments.
|
||||
|
||||
@@ -181,9 +181,6 @@ arch_mmu_post_efi_setup(size_t memory_map_size,
|
||||
start, start + size, size);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Important. Make sure supervisor threads can fault on read only pages...
|
||||
asm("mov %%rax, %%cr0" : : "a" ((1 << 31) | (1 << 16) | (1 << 5) | 1));
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -350,7 +350,7 @@ x86_init_fpu(void)
|
||||
#ifndef __x86_64__
|
||||
if (!x86_check_feature(IA32_FEATURE_FPU, FEATURE_COMMON)) {
|
||||
// No FPU... time to install one in your 386?
|
||||
dprintf("%s: Warning: CPU has no reported FPU.\n", __func__);
|
||||
panic("CPU has no reported FPU!\n");
|
||||
gX86SwapFPUFunc = x86_noop_swap;
|
||||
return;
|
||||
}
|
||||
@@ -359,17 +359,13 @@ x86_init_fpu(void)
|
||||
|| !x86_check_feature(IA32_FEATURE_FXSR, FEATURE_COMMON)) {
|
||||
dprintf("%s: CPU has no SSE... just enabling FPU.\n", __func__);
|
||||
// we don't have proper SSE support, just enable FPU
|
||||
x86_write_cr0(x86_read_cr0() & ~(CR0_FPU_EMULATION | CR0_MONITOR_FPU));
|
||||
gX86SwapFPUFunc = x86_fnsave_swap;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
dprintf("%s: CPU has SSE... enabling FXSR and XMM.\n", __func__);
|
||||
#ifndef __x86_64__
|
||||
// enable OS support for SSE
|
||||
dprintf("%s: CPU has SSE... enabling FXSR and XMM.\n", __func__);
|
||||
x86_write_cr4(x86_read_cr4() | CR4_OS_FXSR | CR4_OS_XMM_EXCEPTION);
|
||||
x86_write_cr0(x86_read_cr0() & ~(CR0_FPU_EMULATION | CR0_MONITOR_FPU));
|
||||
|
||||
gX86SwapFPUFunc = x86_fxsave_swap;
|
||||
gHasSSE = true;
|
||||
@@ -1565,6 +1561,9 @@ x86_double_fault_get_cpu()
|
||||
status_t
|
||||
arch_cpu_preboot_init_percpu(kernel_args* args, int cpu)
|
||||
{
|
||||
// Reset CR0.
|
||||
x86_write_cr0(CR0_PROTECTED_MODE | CR0_PAGING | CR0_WRITE_PROTECT | CR0_NUMERIC_ERROR);
|
||||
|
||||
if (cpu == 0) {
|
||||
// We can't allocate pages at this stage in the boot process, only virtual addresses.
|
||||
sDoubleFaultStacks = vm_allocate_early(args,
|
||||
|
||||
Reference in New Issue
Block a user