| // Copyright 2021 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef ZIRCON_KERNEL_LIB_ARCH_INCLUDE_LIB_ARCH_X86_SYSTEM_H_ |
| #define ZIRCON_KERNEL_LIB_ARCH_INCLUDE_LIB_ARCH_X86_SYSTEM_H_ |
| |
| #include <lib/arch/hwreg.h> |
| #include <lib/arch/intrin.h> |
| #include <lib/arch/sysreg.h> |
| |
| #include <optional> |
| |
| namespace arch { |
| |
| // This file defines hwreg accessor types for the main x86 system registers. |
| // These are all here in this file since there are only a few. Many more |
| // things are represented as MSR (see <lib/arch/x86/msr.h>). |
| // |
| // The names here are approximated from the Intel manual's wording introducing |
| // each register, since all the registers have opaque numeric names. This only |
| // defines the bit layouts and can be used portably. The HWREG_SYSREG types |
| // used to access the registers directly on hardware are declared in |
| // <lib/arch/sysreg.h>. Both headers must be included to use the accessors for |
| // specific registers with the right layout types. |
| |
| // [intel/vol3]: 2.5 Control Registers: CR0 |
| struct X86Cr0 : public SysRegBase<X86Cr0, uint64_t> { |
| DEF_RSVDZ_FIELD(63, 32); |
| DEF_BIT(31, pg); // Paging enabled |
| DEF_BIT(30, cd); // Cache disabled |
| DEF_BIT(29, nw); // Not write-through |
| // Bits [28:19] are reserved. |
| DEF_BIT(18, am); // Alignment mask (support alignment checking) |
| // Bit 17 is reserved. |
| DEF_BIT(16, wp); // Write protect (prevent supervisor writing to RO pages) |
| // Bits [15:6] are reserved. |
| DEF_BIT(5, ne); // Numeric error (control FPU exceptions) |
| DEF_BIT(4, et); // Extension type (reserved on modern CPUs, always 1) |
| DEF_BIT(3, ts); // Task switched (trap on FPU/MMX/SSE/etc reg access) |
| DEF_BIT(2, em); // Emulation (trap on FPU/MMX/SSE/etc instructions) |
| DEF_BIT(1, mp); // Monitor Coprocessor |
| DEF_BIT(0, pe); // Protection Enable (enable protected mode) |
| }; |
| |
| ARCH_X86_SYSREG(X86Cr0, "cr0"); |
| |
| // There is no CR1. |
| |
| // [intel/vol3]: 2.5 Control Registers: CR2 |
| struct X86Cr2 : public SysRegBase<X86Cr2> { |
| DEF_FIELD(63, 0, address); |
| }; |
| |
| ARCH_X86_SYSREG(X86Cr2, "cr2"); |
| |
| // [intel/vol3]: 2.5 Control Registers: CR3 |
| struct X86Cr3 : public SysRegBase<X86Cr3> { |
| DEF_UNSHIFTED_FIELD(63, 12, base); // 4k-aligned physical byte address. |
| |
| // Bits [12:5] and [2:0] are reserved and ignored, but "assumed to be zero". |
| // In case of future additions it's probably best to write them back as |
| // written rather than RSVDZ them. |
| |
| DEF_BIT(4, pcd); // Page-level Cache Disable |
| DEF_BIT(3, pwt); // Page-level Write-Through |
| }; |
| |
| ARCH_X86_SYSREG(X86Cr3, "cr3"); |
| |
| // [intel/vol3]: 2.5 Control Registers: CR4 |
| struct X86Cr4 : public SysRegBase<X86Cr4> { |
| DEF_RSVDZ_FIELD(63, 32); |
| |
| // The Intel manual lists these in ascending bit order instead of descending |
| // bit order like most other control registers, so we follow suit. |
| DEF_BIT(0, vme); // Virtual-8086 Mode Extensions |
| DEF_BIT(1, pvi); // Protected-Mode Virtual Interrupts |
| DEF_BIT(2, tsd); // Time Stamp Disable |
| DEF_BIT(3, de); // Debugging Extensions |
| DEF_BIT(4, pse); // Page Size Extensions |
| DEF_BIT(5, pae); // Physical Address Extension |
| DEF_BIT(6, mce); // Machine-Check Enable |
| DEF_BIT(7, pge); // Page Global Enable |
| DEF_BIT(8, pce); // Performance-Monitoring Counter Enable |
| DEF_BIT(9, osfxsr); // OS supports FXSAVE and FXRSTOR |
| DEF_BIT(10, osmmexcpt); // OS supports unmasked SIMD FP Exceptions |
| DEF_BIT(11, umip); // User-Mode Instruction Prevention |
| DEF_BIT(12, la57); // 57-bit linear addresses |
| DEF_BIT(13, vmxe); // VMX-Enable Bit |
| DEF_BIT(14, smxe); // SMX-Enable Bit |
| // Bit 15 is reserved. |
| DEF_BIT(16, fsgsbase); // FSGSBASE-Enable Bit |
| DEF_BIT(17, pcide); // PCID-Enable Bit |
| DEF_BIT(18, osxsave); // XSAVE and Processor Extended States-Enable Bit |
| // Bit 19 is reserved. |
| DEF_BIT(20, smep); // SMEP-Enable Bit |
| DEF_BIT(21, smap); // SMAP-Enable Bit |
| DEF_BIT(22, pke); // Enable protection keys for user-mode pages |
| DEF_BIT(23, cet); // Control-flow Enforcement Technology |
| DEF_BIT(24, pks); // Enable protection keys for supervisor-mode pages |
| |
| // Bits [31:25] are reserved. |
| }; |
| |
| ARCH_X86_SYSREG(X86Cr4, "cr4"); |
| |
| // There is no CR5, CR6, or CR7. |
| |
| // [Intel/vol3]: 2.5 Control Registers: CR8 |
| struct X86Cr8 : SysRegBase<X86Cr8> { |
| DEF_FIELD(3, 0, tpl); // Task Priority Level |
| }; |
| |
| ARCH_X86_SYSREG(X86Cr8, "cr8"); |
| |
| // [Intel/vol3]: 2.6 Extended Control Registers |
| struct X86Xcr0 : SysRegBase<X86Xcr0> { |
| // Bit 63 of XCR0 is reserved for future expansion and will not represent a |
| // processor state component. |
| DEF_RSVDZ_BIT(63); |
| |
| // The Intel manual lists these in ascending bit order instead of descending |
| // bit order like most other control registers, so we follow suit. |
| DEF_BIT(0, x87); |
| DEF_BIT(1, sse); |
| DEF_BIT(2, avx); |
| DEF_BIT(3, bndreg); |
| DEF_BIT(4, bndcsr); |
| DEF_BIT(5, opmask); |
| DEF_BIT(6, zmm_hi256); |
| DEF_BIT(7, hi16_zmm); |
| DEF_RSVDZ_BIT(8); |
| DEF_BIT(9, pkru); |
| |
| DEF_RSVDZ_FIELD(62, 10); // Reserved for future expansion. |
| }; |
| |
| // XCR0 is accessed differently than other system registers. It could have its |
| // own IO provider like MSRs, but making it a special case of the system |
| // registers fits better especially since there is only actually one XCR. |
| // ARCH_X86_SYSREG() in <lib/arch/sysreg.h> does these definitions for others. |
| #if defined(__Fuchsia__) && (defined(__x86_64__) || defined(__i386__)) |
| template <> |
| inline void SysReg::WriteRegister<X86Xcr0>(uint64_t value) { |
| _xsetbv(0, value); |
| } |
| |
| template <> |
| inline uint64_t SysReg::ReadRegister<X86Xcr0>() { |
| return _xgetbv(0); |
| } |
| #endif |
| |
| } // namespace arch |
| |
| #endif // ZIRCON_KERNEL_LIB_ARCH_INCLUDE_LIB_ARCH_X86_SYSTEM_H_ |