blob: 6dea5a1788e3cebd465ec7c446c5e9a53e441e47 [file] [log] [blame]
// Copyright 2021 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/x86/boot-cpuid.h>
#include <lib/arch/x86/extension.h>
#include <lib/arch/x86/system.h>
#include <lib/page-table/types.h>
#include <zircon/assert.h>
#include <hwreg/x86msr.h>
#include <phys/allocation.h>
#include <phys/page-table.h>
#include <phys/symbolize.h>
#include "address-space.h"
void ArchSetUpAddressSpaceEarly() {}
void ArchSetUpAddressSpaceLate() {
ZX_ASSERT_MSG(arch::BootCpuid<arch::CpuidAmdFeatureFlagsD>().lm(),
"CPU does not support 64-bit mode!");
ZX_ASSERT_MSG(arch::BootCpuid<arch::CpuidFeatureFlagsD>().pse(), "x86-64 requires PSE support!");
ZX_ASSERT_MSG(arch::BootCpuid<arch::CpuidFeatureFlagsD>().pae(), "x86-64 requires PAE support!");
ZX_ASSERT_MSG(arch::BootCpuid<arch::CpuidAmdFeatureFlagsD>().nx(), "x86-64 requires NX support!");
ZX_ASSERT_MSG(arch::BootCpuid<arch::CpuidFeatureFlagsD>().fxsr(), "x86-64 requires SSE support!");
// Configure the CPU for the 64-bit (4-level) style of page tables. The
// LME and PAE bits together enable the 64-bit page table format even
// when executing in 32-bit mode. OSFXSR enables SSE instructions, which
// x86-64 CPUs always support; the compiler might generate those under
// the -msse switch, which is necessary for it to generate the cmpxchg8b
// instruction, which is used in the page-table code.
hwreg::X86MsrIo msr;
auto efer = arch::X86ExtendedFeatureEnableRegisterMsr::Get().ReadFrom(&msr);
efer.set_lme(true) // Enable Long mode (x86-64).
.set_nxe(true) // Enable No-Execute bit in page table entries.
.WriteTo(&msr);
arch::X86Cr4::Read()
.set_pse(true) // Enable 32-bit 4M pages, required for 64-bit.
.set_pae(true) // Enable 64-bit-wide page table entries.
.set_osfxsr(true) // Enable SSE-related instructions.
.set_la57(false) // 4-level, not 5-level.
.Write();
// Set up the identity-mapping page tables. This installs the %cr3 pointer.
//
// On x86-32, the page tables are set up before paging is enabled, so there is
// no bootstrapping issue with accessing page table memory. Conversely, the
// fixed .bss location based on the fixed 1 MiB load address may overlap with
// areas that should be reserved. So it's preferable to go directly to the
// physical page allocator that respects explicitly reserved ranges.
AllocationMemoryManager manager(Allocation::GetPool());
InstallIdentityMapPageTables(manager);
// Now actually turn on paging. This affects us immediately in 32-bit mode,
// as well as being mandatory for 64-bit mode.
printf("%s: Enabling MMU with x86-64 page tables... ", ProgramName());
arch::X86Cr0::Read().set_pg(true).Write();
ZX_ASSERT(efer.ReadFrom(&msr).lma());
printf("Long mode active!\n");
}