114 lines
2.9 KiB
C
114 lines
2.9 KiB
C
/*
|
|
* @author xamidev <xamidev@riseup.net>
|
|
* @brief x86 architecture-dependant initialization
|
|
* @license GPL-3.0-only
|
|
*/
|
|
|
|
#include <arch/gdt.h>
|
|
#include <stdint.h>
|
|
#include <arch/x86.h>
|
|
#include <kernel.h>
|
|
#include <mem/utils.h>
|
|
|
|
/*
|
|
* x86_overwrite_pat - Set PAT to WC
|
|
*
|
|
* This function overwrites the 1st Page Attribute
|
|
* Table entry, to enable the Write-Combining property
|
|
* when we map memory regions later on.
|
|
* The framebuffer will be mapped with WC, which makes
|
|
* memory access significantly faster by using burst
|
|
* operations.
|
|
*/
|
|
|
|
static void x86_overwrite_pat()
|
|
{
|
|
uint64_t pat = rdmsr(0x277);
|
|
pat &= ~(0xFFULL << 8); // Clear PAT1
|
|
pat |= (0x01ULL << 8); // PAT1 = 0x01 (WC)
|
|
wrmsr(0x277, pat);
|
|
}
|
|
|
|
/*
|
|
* x86_enable_fpu - Enable Floating Point Unit
|
|
*
|
|
* This function enables the Floating Point Unit,
|
|
* which allows the CPU to do floating point
|
|
* operations.
|
|
*
|
|
* Here we do not check for FPU support but we
|
|
* should. However most processors support it.
|
|
*/
|
|
static void x86_enable_fpu()
|
|
{
|
|
size_t cr4;
|
|
__asm__ volatile("mov %%cr4, %0" : "=r"(cr4));
|
|
cr4 |= 0x200;
|
|
__asm__ volatile("mov %0, %%cr4" :: "r"(cr4));
|
|
uint16_t cw = 0x37F; // control word
|
|
asm volatile("fldcw %0" :: "m"(cw));
|
|
}
|
|
|
|
/*
|
|
* x86_arch_init - Initialize x86 CPU structures
|
|
*
|
|
* This function is responsible for overriding a PAT entry
|
|
* (to put the framebuffer area in WC mode) only.
|
|
*
|
|
* Later, all architecture-dependant init (GDT, IDT, TSS, ...)
|
|
* should be initialized here, and separate function pointers
|
|
* should be set up for each arch.
|
|
*/
|
|
void x86_arch_init()
|
|
{
|
|
x86_overwrite_pat();
|
|
x86_enable_fpu();
|
|
x86_cpu_identification();
|
|
idt_init();
|
|
gdt_init();
|
|
}
|
|
|
|
/*
|
|
* cpu_supports_brandstring - Does the CPU support brand strings?
|
|
*
|
|
* Return:
|
|
* true - if it does
|
|
* false - if it doesn't
|
|
*/
|
|
bool cpu_supports_brandstring() {
|
|
uint32_t eax, ebx, ecx, edx;
|
|
cpuid(0x80000000, &eax, &ebx, &ecx, &edx);
|
|
|
|
if (eax < 0x80000004) {
|
|
return false;
|
|
} else {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* x86_cpu_idenfitication - get info about the CPU
|
|
*
|
|
* This function displays the CPU vendor name or the
|
|
* extended "brand string" if it's supported, on
|
|
* debug output.
|
|
*/
|
|
void x86_cpu_identification()
|
|
{
|
|
if (cpu_supports_brandstring()) {
|
|
uint32_t regs[12];
|
|
// Some CPUs don't return null-terminated values so we do it as a failsafe default
|
|
char str[sizeof(regs)+1] = {0};
|
|
cpuid(0x80000002, ®s[0], ®s[1], ®s[2], ®s[3]);
|
|
cpuid(0x80000003, ®s[4], ®s[5], ®s[6], ®s[7]);
|
|
cpuid(0x80000004, ®s[8], ®s[9], ®s[10], ®s[11]);
|
|
|
|
memcpy(str, regs, sizeof(regs));
|
|
str[sizeof(regs)] = '\0';
|
|
DEBUG("CPU: %s", str);
|
|
} else {
|
|
char vendor_string[13] = {0};
|
|
cpuid_get_vendor_string(vendor_string);
|
|
DEBUG("CPU vendor is: %s", vendor_string);
|
|
}
|
|
} |