[arch][x86] add more comprehensive feature bit routine
Cache copies of the first few cpuid leaves from each bank at bootup if present. Add a fast routine to test feature bits out of this array.
This commit is contained in:
@@ -7,20 +7,21 @@
|
||||
* license that can be found in the LICENSE file or at
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
#include <lk/debug.h>
|
||||
#include <lk/trace.h>
|
||||
#include <sys/types.h>
|
||||
#include <lk/compiler.h>
|
||||
#include <arch.h>
|
||||
#include <arch/arch_ops.h>
|
||||
#include <arch/mmu.h>
|
||||
#include <arch/x86.h>
|
||||
#include <arch/x86/feature.h>
|
||||
#include <arch/x86/mmu.h>
|
||||
#include <assert.h>
|
||||
#include <kernel/vm.h>
|
||||
#include <lk/compiler.h>
|
||||
#include <lk/debug.h>
|
||||
#include <lk/err.h>
|
||||
#include <lk/trace.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <arch/mmu.h>
|
||||
#include <assert.h>
|
||||
#include <lk/err.h>
|
||||
#include <arch/arch_ops.h>
|
||||
#include <kernel/vm.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#define LOCAL_TRACE 0
|
||||
|
||||
@@ -684,9 +685,9 @@ void x86_mmu_early_init(void) {
|
||||
|
||||
/* Setting the SMEP & SMAP bit in CR4 */
|
||||
cr4 = x86_get_cr4();
|
||||
if (check_smep_avail())
|
||||
if (x86_feature_test(X86_FEATURE_SMEP))
|
||||
cr4 |= X86_CR4_SMEP;
|
||||
if (check_smap_avail())
|
||||
if (x86_feature_test(X86_FEATURE_SMAP))
|
||||
cr4 |=X86_CR4_SMAP;
|
||||
x86_set_cr4(cr4);
|
||||
|
||||
@@ -696,13 +697,10 @@ void x86_mmu_early_init(void) {
|
||||
write_msr(X86_MSR_IA32_EFER, efer_msr);
|
||||
|
||||
/* getting the address width from CPUID instr */
|
||||
/* Bits 07-00: Physical Address width info */
|
||||
/* Bits 15-08: Linear Address width info */
|
||||
uint32_t addr_width = x86_get_address_width();
|
||||
g_paddr_width = (uint8_t)(addr_width & 0xFF);
|
||||
g_vaddr_width = (uint8_t)((addr_width >> 8) & 0xFF);
|
||||
g_paddr_width = x86_get_paddr_width();
|
||||
g_vaddr_width = x86_get_vaddr_width();
|
||||
|
||||
LTRACEF("paddr_width %u vaddr_width %u\n", g_paddr_width, g_vaddr_width);
|
||||
dprintf(SPEW, "X86: paddr_width %u vaddr_width %u\n", g_paddr_width, g_vaddr_width);
|
||||
|
||||
/* unmap the lower identity mapping */
|
||||
kernel_pml4[0] = 0;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2019 Travis Geiselbrecht
|
||||
* Copyright 2016 The Fuchsia Authors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files
|
||||
@@ -26,14 +27,23 @@
|
||||
#include <lk/debug.h>
|
||||
#include <lk/trace.h>
|
||||
#include <arch/x86.h>
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
#define LOCAL_TRACE 0
|
||||
|
||||
enum x86_cpu_vendor __x86_cpu_vendor = X86_CPU_VENDOR_INTEL;
|
||||
enum x86_cpu_level __x86_cpu_level = X86_CPU_LEVEL_386; // start off assuming 386
|
||||
|
||||
bool has_cpuid = false;
|
||||
|
||||
/* a saved cache of three banks of cpuids loaded a boot */
|
||||
struct x86_cpuid_leaf saved_cpuids[__X86_MAX_SUPPORTED_CPUID + 1];
|
||||
struct x86_cpuid_leaf saved_cpuids_hyp[__X86_MAX_SUPPORTED_CPUID_HYP - X86_CPUID_HYP_BASE + 1];
|
||||
struct x86_cpuid_leaf saved_cpuids_ext[__X86_MAX_SUPPORTED_CPUID_EXT - X86_CPUID_EXT_BASE + 1];
|
||||
uint32_t max_cpuid_leaf = 0;
|
||||
uint32_t max_cpuid_leaf_extended = 0;
|
||||
uint32_t max_cpuid_leaf_hyp = 0;
|
||||
uint32_t max_cpuid_leaf_ext = 0;
|
||||
|
||||
static enum x86_cpu_vendor match_cpu_vendor_string(const char *str) {
|
||||
// from table at https://www.sandpile.org/x86/cpuid.htm#level_0000_0000h
|
||||
@@ -71,55 +81,66 @@ static enum x86_cpu_vendor match_cpu_vendor_string(const char *str) {
|
||||
}
|
||||
|
||||
static void x86_cpu_detect(void) {
|
||||
bool has_cpuid = false;
|
||||
if (X86_LEGACY) {
|
||||
// inspired by http://www.rcollins.org/ddj/Sep96/Sep96.html
|
||||
// try to detect a 486
|
||||
// set the EFLAGS.AC bit, see if it sets
|
||||
uint32_t flags = x86_save_flags();
|
||||
x86_restore_flags(flags | X86_FLAGS_AC);
|
||||
if (x86_save_flags() & X86_FLAGS_AC) {
|
||||
__x86_cpu_level = X86_CPU_LEVEL_486;
|
||||
|
||||
#if X86_LEGACY
|
||||
// inspired by http://www.rcollins.org/ddj/Sep96/Sep96.html
|
||||
// try to detect a 486
|
||||
// set the EFLAGS.AC bit, see if it sets
|
||||
uint32_t flags = x86_save_flags();
|
||||
x86_restore_flags(flags | X86_FLAGS_AC);
|
||||
if (x86_save_flags() & X86_FLAGS_AC) {
|
||||
__x86_cpu_level = X86_CPU_LEVEL_486;
|
||||
|
||||
// test EFLAGS.ID flag
|
||||
x86_restore_flags(flags | X86_FLAGS_ID);
|
||||
if (x86_save_flags() & X86_FLAGS_ID) {
|
||||
has_cpuid = true;
|
||||
// test EFLAGS.ID flag
|
||||
x86_restore_flags(flags | X86_FLAGS_ID);
|
||||
if (x86_save_flags() & X86_FLAGS_ID) {
|
||||
has_cpuid = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
// at least a pentium and has cpuid
|
||||
__x86_cpu_level = X86_CPU_LEVEL_PENTIUM;
|
||||
has_cpuid = true;
|
||||
uint32_t a, b, c, d;
|
||||
|
||||
// read the max basic cpuid leaf
|
||||
cpuid(0, &a, &b, &c, &d);
|
||||
max_cpuid_leaf = a;
|
||||
|
||||
// read the vendor string
|
||||
union {
|
||||
uint32_t reg[3];
|
||||
char str[13];
|
||||
} vs;
|
||||
vs.reg[0] = b;
|
||||
vs.reg[1] = d;
|
||||
vs.reg[2] = c;
|
||||
vs.str[12] = 0;
|
||||
__x86_cpu_vendor = match_cpu_vendor_string(vs.str);
|
||||
|
||||
// read max extended cpuid leaf
|
||||
cpuid(0x80000000, &a, &b, &c, &d);
|
||||
if (a >= 0x80000000) {
|
||||
max_cpuid_leaf_extended = a;
|
||||
} else {
|
||||
// at least a pentium and has cpuid
|
||||
__x86_cpu_level = X86_CPU_LEVEL_PENTIUM;
|
||||
has_cpuid = true;
|
||||
}
|
||||
|
||||
dprintf(SPEW, "x86: vendor string '%s'\n", vs.str);
|
||||
if (has_cpuid) {
|
||||
uint32_t a, b, c, d;
|
||||
|
||||
// read the max basic cpuid leaf
|
||||
cpuid(X86_CPUID_BASE, &a, &b, &c, &d);
|
||||
max_cpuid_leaf = a;
|
||||
|
||||
// read the vendor string
|
||||
union {
|
||||
uint32_t reg[3];
|
||||
char str[13];
|
||||
} vs;
|
||||
vs.reg[0] = b;
|
||||
vs.reg[1] = d;
|
||||
vs.reg[2] = c;
|
||||
vs.str[12] = 0;
|
||||
__x86_cpu_vendor = match_cpu_vendor_string(vs.str);
|
||||
|
||||
dprintf(SPEW, "x86: vendor string '%s' from cpuid\n", vs.str);
|
||||
|
||||
// read max extended cpuid leaf
|
||||
cpuid(X86_CPUID_EXT_BASE, &a, &b, &c, &d);
|
||||
if (a >= X86_CPUID_EXT_BASE) {
|
||||
max_cpuid_leaf_ext = a;
|
||||
}
|
||||
|
||||
// read max hypervisor leaf
|
||||
cpuid(X86_CPUID_HYP_BASE, &a, &b, &c, &d);
|
||||
if (a >= X86_CPUID_HYP_BASE) {
|
||||
max_cpuid_leaf_hyp = a;
|
||||
}
|
||||
} else {
|
||||
__x86_cpu_vendor = X86_CPU_VENDOR_INTEL; // intrinsically Intel without cpuid
|
||||
}
|
||||
|
||||
// do a quick cpu level detection using cpuid
|
||||
if (max_cpuid_leaf >= 1) {
|
||||
cpuid(1, &a, &b, &c, &d);
|
||||
if (has_cpuid && max_cpuid_leaf >= 1) {
|
||||
uint32_t a, b, c, d;
|
||||
cpuid(X86_CPUID_MODEL_FEATURES, &a, &b, &c, &d);
|
||||
|
||||
LTRACEF("cpuid leaf 1: %#x %#x %#x %#x\n", a, b, c, d);
|
||||
|
||||
@@ -156,15 +177,41 @@ static void x86_cpu_detect(void) {
|
||||
|
||||
// TODO: save this information for future use
|
||||
}
|
||||
#endif
|
||||
|
||||
dprintf(SPEW, "x86: detected cpu level %d has_cpuid %d\n", x86_get_cpu_level(), has_cpuid);
|
||||
if (has_cpuid) {
|
||||
dprintf(SPEW, "x86: max cpuid leaf %#x ext %#x\n", max_cpuid_leaf, max_cpuid_leaf_extended);
|
||||
dprintf(SPEW, "x86: max cpuid leaf %#x ext %#x hyp %#x\n",
|
||||
max_cpuid_leaf, max_cpuid_leaf_ext, max_cpuid_leaf_hyp);
|
||||
}
|
||||
|
||||
// cache a copy of the cpuid bits
|
||||
if (has_cpuid) {
|
||||
for (uint32_t i = 1; i <= max_cpuid_leaf; i++) {
|
||||
cpuid_c(i, 0, &saved_cpuids[i].a, &saved_cpuids[i].b, &saved_cpuids[i].c, &saved_cpuids[i].d);
|
||||
}
|
||||
|
||||
if (max_cpuid_leaf_ext > 0) {
|
||||
for (uint32_t i = X86_CPUID_EXT_BASE + 1; i - 1 < max_cpuid_leaf_ext; i++) {
|
||||
uint32_t index = i - X86_CPUID_EXT_BASE;
|
||||
cpuid_c(i, 0, &saved_cpuids_ext[index].a, &saved_cpuids_ext[index].b, &saved_cpuids_ext[index].c,
|
||||
&saved_cpuids_ext[index].d);
|
||||
}
|
||||
}
|
||||
|
||||
if (max_cpuid_leaf_hyp > 0) {
|
||||
for (uint32_t i = X86_CPUID_HYP_BASE + 1; i - 1 < max_cpuid_leaf_hyp; i++) {
|
||||
uint32_t index = i - X86_CPUID_HYP_BASE;
|
||||
cpuid_c(i, 0, &saved_cpuids_hyp[index].a, &saved_cpuids_hyp[index].b, &saved_cpuids_hyp[index].c,
|
||||
&saved_cpuids_hyp[index].d);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void x86_feature_init(void) {
|
||||
void x86_feature_early_init(void) {
|
||||
x86_cpu_detect();
|
||||
}
|
||||
|
||||
void x86_feature_init(void) {
|
||||
}
|
||||
|
||||
|
||||
@@ -24,7 +24,6 @@ __BEGIN_CDECLS
|
||||
#define PFEX_RSV 0x08
|
||||
#define PFEX_I 0x10
|
||||
#define X86_8BYTE_MASK 0xFFFFFFFF
|
||||
#define X86_CPUID_ADDR_WIDTH 0x80000008
|
||||
|
||||
struct x86_32_iframe {
|
||||
uint32_t di, si, bp, sp, bx, dx, cx, ax; // pushed by common handler using pusha
|
||||
@@ -419,31 +418,6 @@ static inline void cpuid_c(uint32_t leaf, uint32_t csel, uint32_t *a, uint32_t *
|
||||
: "a"(leaf), "c"(csel));
|
||||
}
|
||||
|
||||
static inline uint32_t x86_get_address_width(void) {
|
||||
uint32_t a, b, c, d;
|
||||
|
||||
cpuid(X86_CPUID_ADDR_WIDTH, &a, &b, &c, &d);
|
||||
|
||||
/* Extracting bit 15:8 from eax register */
|
||||
return ((a >> 8) & 0x0ff);
|
||||
}
|
||||
|
||||
static inline bool check_smep_avail(void) {
|
||||
uint32_t a, b, c, d;
|
||||
|
||||
cpuid_c(0x7, 0, &a, &b, &c, &d);
|
||||
|
||||
return ((b >> 0x06) & 0x1);
|
||||
}
|
||||
|
||||
static inline bool check_smap_avail(void) {
|
||||
uint32_t a, b, c, d;
|
||||
|
||||
cpuid_c(0x7, 0, &a, &b, &c, &d);
|
||||
|
||||
return ((b >> 0x13) & 0x1);
|
||||
}
|
||||
|
||||
static inline uint64_t read_msr (uint32_t msr_id) {
|
||||
uint64_t msr_read_val;
|
||||
uint32_t low_val;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2019 Travis Geiselbrecht
|
||||
* Copyright 2016 The Fuchsia Authors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files
|
||||
@@ -22,10 +23,15 @@
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <arch/x86.h>
|
||||
#include <inttypes.h>
|
||||
#include <lk/compiler.h>
|
||||
#include <stdbool.h>
|
||||
#include <assert.h>
|
||||
|
||||
__BEGIN_CDECLS
|
||||
|
||||
void x86_feature_early_init(void);
|
||||
void x86_feature_init(void);
|
||||
|
||||
enum x86_cpu_level {
|
||||
@@ -61,6 +67,196 @@ static inline enum x86_cpu_vendor x86_get_cpu_vendor(void) {
|
||||
return __x86_cpu_vendor;
|
||||
}
|
||||
|
||||
/* cpuid leaves */
|
||||
enum x86_cpuid_leaf_num {
|
||||
X86_CPUID_BASE = 0,
|
||||
X86_CPUID_MODEL_FEATURES = 0x1,
|
||||
X86_CPUID_CACHE_V1 = 0x2,
|
||||
X86_CPUID_CACHE_V2 = 0x4,
|
||||
X86_CPUID_MON = 0x5,
|
||||
X86_CPUID_THERMAL_AND_POWER = 0x6,
|
||||
X86_CPUID_EXTENDED_FEATURE_FLAGS = 0x7,
|
||||
X86_CPUID_PERFORMANCE_MONITORING = 0xa,
|
||||
X86_CPUID_TOPOLOGY = 0xb,
|
||||
X86_CPUID_XSAVE = 0xd,
|
||||
X86_CPUID_PT = 0x14,
|
||||
X86_CPUID_TSC = 0x15,
|
||||
__X86_MAX_SUPPORTED_CPUID = X86_CPUID_TSC,
|
||||
|
||||
X86_CPUID_HYP_BASE = 0x40000000,
|
||||
X86_CPUID_HYP_VENDOR = 0x40000000,
|
||||
X86_CPUID_KVM_FEATURES = 0x40000001,
|
||||
__X86_MAX_SUPPORTED_CPUID_HYP = X86_CPUID_KVM_FEATURES,
|
||||
|
||||
X86_CPUID_EXT_BASE = 0x80000000,
|
||||
X86_CPUID_BRAND = 0x80000002,
|
||||
X86_CPUID_ADDR_WIDTH = 0x80000008,
|
||||
X86_CPUID_AMD_TOPOLOGY = 0x8000001e,
|
||||
__X86_MAX_SUPPORTED_CPUID_EXT = X86_CPUID_AMD_TOPOLOGY,
|
||||
};
|
||||
|
||||
struct x86_cpuid_bit {
|
||||
enum x86_cpuid_leaf_num leaf_num;
|
||||
uint8_t word;
|
||||
uint8_t bit;
|
||||
};
|
||||
|
||||
#define X86_CPUID_BIT(leaf, word, bit) \
|
||||
(struct x86_cpuid_bit) { (enum x86_cpuid_leaf_num)(leaf), (word), (bit) }
|
||||
|
||||
struct x86_cpuid_leaf {
|
||||
uint32_t a;
|
||||
uint32_t b;
|
||||
uint32_t c;
|
||||
uint32_t d;
|
||||
};
|
||||
|
||||
extern struct x86_cpuid_leaf saved_cpuids[__X86_MAX_SUPPORTED_CPUID + 1];
|
||||
extern struct x86_cpuid_leaf saved_cpuids_hyp[__X86_MAX_SUPPORTED_CPUID_HYP - X86_CPUID_HYP_BASE + 1];
|
||||
extern struct x86_cpuid_leaf saved_cpuids_ext[__X86_MAX_SUPPORTED_CPUID_EXT - X86_CPUID_EXT_BASE + 1];
|
||||
extern uint32_t max_cpuid_leaf;
|
||||
extern uint32_t max_cpuid_leaf_hyp;
|
||||
extern uint32_t max_cpuid_leaf_ext;
|
||||
|
||||
static inline const struct x86_cpuid_leaf* x86_get_cpuid_leaf(enum x86_cpuid_leaf_num leaf) {
|
||||
if (leaf < X86_CPUID_HYP_BASE) {
|
||||
if (unlikely(leaf > max_cpuid_leaf))
|
||||
return NULL;
|
||||
|
||||
return &saved_cpuids[leaf];
|
||||
} else if (leaf < X86_CPUID_EXT_BASE) {
|
||||
if (unlikely(leaf > max_cpuid_leaf_hyp))
|
||||
return NULL;
|
||||
|
||||
return &saved_cpuids_hyp[(uint32_t)leaf - (uint32_t)X86_CPUID_HYP_BASE];
|
||||
} else {
|
||||
if (unlikely(leaf > max_cpuid_leaf_ext))
|
||||
return NULL;
|
||||
|
||||
return &saved_cpuids_ext[(uint32_t)leaf - (uint32_t)X86_CPUID_EXT_BASE];
|
||||
}
|
||||
}
|
||||
|
||||
static inline bool x86_feature_test(struct x86_cpuid_bit bit) {
|
||||
DEBUG_ASSERT(bit.word <= 3 && bit.bit <= 31);
|
||||
|
||||
if (bit.word > 3 || bit.bit > 31)
|
||||
return false;
|
||||
|
||||
const struct x86_cpuid_leaf* leaf = x86_get_cpuid_leaf(bit.leaf_num);
|
||||
if (!leaf)
|
||||
return false;
|
||||
|
||||
switch (bit.word) {
|
||||
case 0:
|
||||
return !!((1u << bit.bit) & leaf->a);
|
||||
case 1:
|
||||
return !!((1u << bit.bit) & leaf->b);
|
||||
case 2:
|
||||
return !!((1u << bit.bit) & leaf->c);
|
||||
case 3:
|
||||
return !!((1u << bit.bit) & leaf->d);
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/* feature bits for x86_feature_test */
|
||||
/* add feature bits to test here */
|
||||
/* format: X86_CPUID_BIT(cpuid leaf, register (eax-edx:0-3), bit) */
|
||||
#define X86_FEATURE_SSE3 X86_CPUID_BIT(0x1, 2, 0)
|
||||
#define X86_FEATURE_MON X86_CPUID_BIT(0x1, 2, 3)
|
||||
#define X86_FEATURE_VMX X86_CPUID_BIT(0x1, 2, 5)
|
||||
#define X86_FEATURE_TM2 X86_CPUID_BIT(0x1, 2, 8)
|
||||
#define X86_FEATURE_SSSE3 X86_CPUID_BIT(0x1, 2, 9)
|
||||
#define X86_FEATURE_PDCM X86_CPUID_BIT(0x1, 2, 15)
|
||||
#define X86_FEATURE_PCID X86_CPUID_BIT(0x1, 2, 17)
|
||||
#define X86_FEATURE_SSE4_1 X86_CPUID_BIT(0x1, 2, 19)
|
||||
#define X86_FEATURE_SSE4_2 X86_CPUID_BIT(0x1, 2, 20)
|
||||
#define X86_FEATURE_X2APIC X86_CPUID_BIT(0x1, 2, 21)
|
||||
#define X86_FEATURE_TSC_DEADLINE X86_CPUID_BIT(0x1, 2, 24)
|
||||
#define X86_FEATURE_AESNI X86_CPUID_BIT(0x1, 2, 25)
|
||||
#define X86_FEATURE_XSAVE X86_CPUID_BIT(0x1, 2, 26)
|
||||
#define X86_FEATURE_AVX X86_CPUID_BIT(0x1, 2, 28)
|
||||
#define X86_FEATURE_RDRAND X86_CPUID_BIT(0x1, 2, 30)
|
||||
#define X86_FEATURE_HYPERVISOR X86_CPUID_BIT(0x1, 2, 31)
|
||||
#define X86_FEATURE_FPU X86_CPUID_BIT(0x1, 3, 0)
|
||||
#define X86_FEATURE_PSE X86_CPUID_BIT(0x1, 3, 3)
|
||||
#define X86_FEATURE_PAE X86_CPUID_BIT(0x1, 3, 6)
|
||||
#define X86_FEATURE_APIC X86_CPUID_BIT(0x1, 3, 9)
|
||||
#define X86_FEATURE_SEP X86_CPUID_BIT(0x1, 3, 11)
|
||||
#define X86_FEATURE_PGE X86_CPUID_BIT(0x1, 3, 13)
|
||||
#define X86_FEATURE_PAT X86_CPUID_BIT(0x1, 3, 16)
|
||||
#define X86_FEATURE_PSE36 X86_CPUID_BIT(0x1, 3, 17)
|
||||
#define X86_FEATURE_CLFLUSH X86_CPUID_BIT(0x1, 3, 19)
|
||||
#define X86_FEATURE_ACPI X86_CPUID_BIT(0x1, 3, 22)
|
||||
#define X86_FEATURE_MMX X86_CPUID_BIT(0x1, 3, 23)
|
||||
#define X86_FEATURE_FXSR X86_CPUID_BIT(0x1, 3, 24)
|
||||
#define X86_FEATURE_SSE X86_CPUID_BIT(0x1, 3, 25)
|
||||
#define X86_FEATURE_SSE2 X86_CPUID_BIT(0x1, 3, 26)
|
||||
#define X86_FEATURE_TM X86_CPUID_BIT(0x1, 3, 29)
|
||||
#define X86_FEATURE_DTS X86_CPUID_BIT(0x6, 0, 0)
|
||||
#define X86_FEATURE_TURBO X86_CPUID_BIT(0x6, 0, 1)
|
||||
#define X86_FEATURE_PLN X86_CPUID_BIT(0x6, 0, 4)
|
||||
#define X86_FEATURE_PTM X86_CPUID_BIT(0x6, 0, 6)
|
||||
#define X86_FEATURE_HWP X86_CPUID_BIT(0x6, 0, 7)
|
||||
#define X86_FEATURE_HWP_NOT X86_CPUID_BIT(0x6, 0, 8)
|
||||
#define X86_FEATURE_HWP_ACT X86_CPUID_BIT(0x6, 0, 9)
|
||||
#define X86_FEATURE_HWP_PREF X86_CPUID_BIT(0x6, 0, 10)
|
||||
#define X86_FEATURE_TURBO_MAX X86_CPUID_BIT(0x6, 0, 14)
|
||||
#define X86_FEATURE_HW_FEEDBACK X86_CPUID_BIT(0x6, 2, 0)
|
||||
#define X86_FEATURE_PERF_BIAS X86_CPUID_BIT(0x6, 2, 3)
|
||||
#define X86_FEATURE_FSGSBASE X86_CPUID_BIT(0x7, 1, 0)
|
||||
#define X86_FEATURE_TSC_ADJUST X86_CPUID_BIT(0x7, 1, 1)
|
||||
#define X86_FEATURE_AVX2 X86_CPUID_BIT(0x7, 1, 5)
|
||||
#define X86_FEATURE_SMEP X86_CPUID_BIT(0x7, 1, 7)
|
||||
#define X86_FEATURE_ERMS X86_CPUID_BIT(0x7, 1, 9)
|
||||
#define X86_FEATURE_INVPCID X86_CPUID_BIT(0x7, 1, 10)
|
||||
#define X86_FEATURE_RDSEED X86_CPUID_BIT(0x7, 1, 18)
|
||||
#define X86_FEATURE_SMAP X86_CPUID_BIT(0x7, 1, 20)
|
||||
#define X86_FEATURE_CLFLUSHOPT X86_CPUID_BIT(0x7, 1, 23)
|
||||
#define X86_FEATURE_CLWB X86_CPUID_BIT(0x7, 1, 24)
|
||||
#define X86_FEATURE_PT X86_CPUID_BIT(0x7, 1, 25)
|
||||
#define X86_FEATURE_UMIP X86_CPUID_BIT(0x7, 2, 2)
|
||||
#define X86_FEATURE_PKU X86_CPUID_BIT(0x7, 2, 3)
|
||||
#define X86_FEATURE_MD_CLEAR X86_CPUID_BIT(0x7, 3, 10)
|
||||
#define X86_FEATURE_IBRS_IBPB X86_CPUID_BIT(0x7, 3, 26)
|
||||
#define X86_FEATURE_STIBP X86_CPUID_BIT(0x7, 3, 27)
|
||||
#define X86_FEATURE_L1D_FLUSH X86_CPUID_BIT(0x7, 3, 28)
|
||||
#define X86_FEATURE_ARCH_CAPABILITIES X86_CPUID_BIT(0x7, 3, 29)
|
||||
#define X86_FEATURE_SSBD X86_CPUID_BIT(0x7, 3, 31)
|
||||
|
||||
#define X86_FEATURE_KVM_PV_CLOCK X86_CPUID_BIT(0x40000001, 0, 3)
|
||||
#define X86_FEATURE_KVM_PV_EOI X86_CPUID_BIT(0x40000001, 0, 6)
|
||||
#define X86_FEATURE_KVM_PV_IPI X86_CPUID_BIT(0x40000001, 0, 11)
|
||||
#define X86_FEATURE_KVM_PV_CLOCK_STABLE X86_CPUID_BIT(0x40000001, 0, 24)
|
||||
|
||||
#define X86_FEATURE_AMD_TOPO X86_CPUID_BIT(0x80000001, 2, 22)
|
||||
#define X86_FEATURE_SYSCALL X86_CPUID_BIT(0x80000001, 3, 11)
|
||||
#define X86_FEATURE_NX X86_CPUID_BIT(0x80000001, 3, 20)
|
||||
#define X86_FEATURE_HUGE_PAGE X86_CPUID_BIT(0x80000001, 3, 26)
|
||||
#define X86_FEATURE_RDTSCP X86_CPUID_BIT(0x80000001, 3, 27)
|
||||
#define X86_FEATURE_INVAR_TSC X86_CPUID_BIT(0x80000007, 3, 8)
|
||||
|
||||
// accessor to read some fields out of a register
|
||||
static inline uint32_t x86_get_vaddr_width(void) {
|
||||
const struct x86_cpuid_leaf *leaf;
|
||||
|
||||
leaf = x86_get_cpuid_leaf(X86_CPUID_ADDR_WIDTH);
|
||||
if (!leaf) {
|
||||
return 0;
|
||||
}
|
||||
return (leaf->a >> 8) & 0xff;
|
||||
}
|
||||
|
||||
static inline uint32_t x86_get_paddr_width(void) {
|
||||
const struct x86_cpuid_leaf *leaf;
|
||||
|
||||
leaf = x86_get_cpuid_leaf(X86_CPUID_ADDR_WIDTH);
|
||||
if (!leaf) {
|
||||
return 0;
|
||||
}
|
||||
return leaf->a & 0xff;
|
||||
}
|
||||
|
||||
__END_CDECLS
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
#define X86_DIRTY_ACCESS_MASK 0xf9f
|
||||
#define X86_MMU_CACHE_DISABLE 0x010 /* C Cache disable */
|
||||
|
||||
#ifndef X86_LEGACY
|
||||
#if !X86_LEGACY
|
||||
/* default flags for inner page directory entries */
|
||||
#define X86_KERNEL_PD_FLAGS (X86_MMU_PG_RW | X86_MMU_PG_P)
|
||||
|
||||
|
||||
@@ -116,9 +116,11 @@ GLOBAL_DEFINES += X86_LEGACY=1
|
||||
else ifeq ($(SUBARCH),x86-32)
|
||||
ARCH_COMPILEFLAGS += -march=i686
|
||||
ARCH_OPTFLAGS := -O2
|
||||
GLOBAL_DEFINES += X86_LEGACY=0
|
||||
else ifeq ($(SUBARCH),x86-64)
|
||||
ARCH_COMPILEFLAGS += -march=x86-64
|
||||
ARCH_OPTFLAGS := -O2
|
||||
GLOBAL_DEFINES += X86_LEGACY=0
|
||||
endif
|
||||
|
||||
LIBGCC := $(shell $(TOOLCHAIN_PREFIX)gcc $(GLOBAL_COMPILEFLAGS) $(ARCH_COMPILEFLAGS) -print-libgcc-file-name)
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#include <platform/interrupts.h>
|
||||
#include <arch/ops.h>
|
||||
#include <arch/x86.h>
|
||||
#include <arch/x86/feature.h>
|
||||
#include <kernel/spinlock.h>
|
||||
#include "platform_p.h"
|
||||
#include <platform/pc.h>
|
||||
@@ -31,21 +32,15 @@ void lapic_init(void) {
|
||||
LTRACE_ENTRY;
|
||||
|
||||
// check feature bit 9 in edx of leaf 1 for presence of lapic
|
||||
uint32_t a, b, c, d;
|
||||
cpuid(0x1, &a, &b, &c, &d);
|
||||
LTRACEF("%#x %#x %#x %#x\n", a, b, c, d);
|
||||
|
||||
if ((d & (1 << 9)) == 0) {
|
||||
// no lapic detected
|
||||
return;
|
||||
}
|
||||
lapic_present = true;
|
||||
lapic_present = x86_feature_test(X86_FEATURE_APIC);
|
||||
}
|
||||
|
||||
void lapic_init_postvm(uint level) {
|
||||
if (!lapic_present)
|
||||
return;
|
||||
|
||||
dprintf(INFO, "X86: local apic detected\n");
|
||||
|
||||
// IA32_APIC_BASE_MSR
|
||||
uint64_t apic_base = read_msr(0x1b);
|
||||
LTRACEF("apic base %#llx\n", apic_base);
|
||||
@@ -53,7 +48,7 @@ void lapic_init_postvm(uint level) {
|
||||
// TODO: assert that it's enabled
|
||||
|
||||
apic_base &= ~0xfff;
|
||||
dprintf(INFO, "LAPIC: physical address %#llx\n", apic_base);
|
||||
dprintf(INFO, "X86: lapic physical address %#llx\n", apic_base);
|
||||
|
||||
// map the lapic into the kernel since it's not guaranteed that the physmap covers it
|
||||
status_t err = vmm_alloc_physical(vmm_get_kernel_aspace(), "lapic", PAGE_SIZE, (void **)&lapic_mmio, 0,
|
||||
|
||||
Reference in New Issue
Block a user