Implemented VIA specific MTRR functionality - untested, though.
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@15560 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -6,5 +6,5 @@ KernelAddon generic_x86 : kernel cpu :
|
|||||||
generic_x86.cpp
|
generic_x86.cpp
|
||||||
intel.cpp
|
intel.cpp
|
||||||
# amd.cpp
|
# amd.cpp
|
||||||
# via.cpp
|
via.cpp
|
||||||
;
|
;
|
||||||
|
|||||||
@@ -15,6 +15,6 @@
|
|||||||
module_info *modules[] = {
|
module_info *modules[] = {
|
||||||
(module_info *)&gIntelModule,
|
(module_info *)&gIntelModule,
|
||||||
// (module_info *)&gAMDModule,
|
// (module_info *)&gAMDModule,
|
||||||
// (module_info *)&gVIAModule,
|
(module_info *)&gVIAModule,
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -22,12 +22,10 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#define IA32_MTRR_FEATURE (1UL << 12)
|
|
||||||
#define IA32_MTRR_ENABLE (1UL << 11)
|
#define IA32_MTRR_ENABLE (1UL << 11)
|
||||||
#define IA32_MTRR_ENABLE_FIXED (1UL << 10)
|
#define IA32_MTRR_ENABLE_FIXED (1UL << 10)
|
||||||
#define IA32_MTRR_VALID_RANGE (1UL << 11)
|
#define IA32_MTRR_VALID_RANGE (1UL << 11)
|
||||||
|
|
||||||
#define MTRR_MASK (0xffffffff & (B_PAGE_SIZE - 1))
|
|
||||||
|
|
||||||
struct mtrr_capabilities {
|
struct mtrr_capabilities {
|
||||||
mtrr_capabilities(uint64 value) { *(uint64 *)this = value; }
|
mtrr_capabilities(uint64 value) { *(uint64 *)this = value; }
|
||||||
@@ -48,7 +46,7 @@ intel_count_mtrrs(void)
|
|||||||
{
|
{
|
||||||
cpuid_info cpuInfo;
|
cpuid_info cpuInfo;
|
||||||
if (get_cpuid(&cpuInfo, 1, 0) != B_OK
|
if (get_cpuid(&cpuInfo, 1, 0) != B_OK
|
||||||
|| (cpuInfo.eax_1.features & IA32_MTRR_FEATURE) == 0)
|
|| (cpuInfo.eax_1.features & IA32_FEATURE_MTRR) == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
mtrr_capabilities capabilities(x86_read_msr(IA32_MSR_MTRR_CAPABILITIES));
|
mtrr_capabilities capabilities(x86_read_msr(IA32_MSR_MTRR_CAPABILITIES));
|
||||||
|
|||||||
@@ -9,24 +9,107 @@
|
|||||||
|
|
||||||
#include "via.h"
|
#include "via.h"
|
||||||
|
|
||||||
|
#include <KernelExport.h>
|
||||||
|
#include <OS.h>
|
||||||
|
#include <arch_cpu.h>
|
||||||
|
|
||||||
|
|
||||||
|
#define TRACE_MTRR
|
||||||
|
#ifdef TRACE_MTRR
|
||||||
|
# define TRACE(x) dprintf x
|
||||||
|
#else
|
||||||
|
# define TRACE(x) ;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#define IA32_MTRR_ENABLE (1UL << 11)
|
||||||
|
#define IA32_MTRR_ENABLE_FIXED (1UL << 10)
|
||||||
|
#define IA32_MTRR_VALID_RANGE (1UL << 11)
|
||||||
|
|
||||||
|
|
||||||
|
static uint64 kPhysicalMask = ((1ULL << 36) - 1) & ~(B_PAGE_SIZE - 1);;
|
||||||
|
|
||||||
|
|
||||||
static uint32
|
static uint32
|
||||||
via_count_mtrrs(void)
|
via_count_mtrrs(void)
|
||||||
{
|
{
|
||||||
return 0;
|
cpuid_info cpuInfo;
|
||||||
|
if (get_cpuid(&cpuInfo, 1, 0) != B_OK
|
||||||
|
|| (cpuInfo.eax_1.features & IA32_FEATURE_MTRR) == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
// IA32_MSR_MTRR_CAPABILITIES doesn't exist on VIA CPUs
|
||||||
|
return 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
via_init_mtrrs(void)
|
||||||
|
{
|
||||||
|
// disable and clear all MTRRs
|
||||||
|
// (we leave the fixed MTRRs as is)
|
||||||
|
// TODO: check if the fixed MTRRs are set on all CPUs identically?
|
||||||
|
|
||||||
|
x86_write_msr(IA32_MSR_MTRR_DEFAULT_TYPE,
|
||||||
|
x86_read_msr(IA32_MSR_MTRR_DEFAULT_TYPE) & ~IA32_MTRR_ENABLE);
|
||||||
|
|
||||||
|
for (uint32 i = via_count_mtrrs(); i-- > 0;) {
|
||||||
|
if (x86_read_msr(IA32_MSR_MTRR_PHYSICAL_MASK_0 + i * 2) & IA32_MTRR_VALID_RANGE)
|
||||||
|
x86_write_msr(IA32_MSR_MTRR_PHYSICAL_MASK_0 + i * 2, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// but turn on variable MTRR functionality
|
||||||
|
|
||||||
|
x86_write_msr(IA32_MSR_MTRR_DEFAULT_TYPE,
|
||||||
|
x86_read_msr(IA32_MSR_MTRR_DEFAULT_TYPE) | IA32_MTRR_ENABLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
via_set_mtrr(uint32 index, uint64 base, uint64 length, uint8 type)
|
||||||
|
{
|
||||||
|
index *= 2;
|
||||||
|
// there are two registers per slot
|
||||||
|
|
||||||
|
uint64 mask = length - 1;
|
||||||
|
mask = ~mask & kPhysicalMask;
|
||||||
|
|
||||||
|
TRACE(("MTRR %ld: new mask %Lx)\n", index, mask));
|
||||||
|
TRACE((" mask test base: %Lx)\n", mask & base));
|
||||||
|
TRACE((" mask test middle: %Lx)\n", mask & (base + length / 2)));
|
||||||
|
TRACE((" mask test end: %Lx)\n", mask & (base + length)));
|
||||||
|
|
||||||
|
// First, disable MTRR
|
||||||
|
|
||||||
|
x86_write_msr(IA32_MSR_MTRR_PHYSICAL_MASK_0 + index, 0);
|
||||||
|
|
||||||
|
if (base != 0 || mask != 0 || type != 0) {
|
||||||
|
// then fill in the new values, and enable it again
|
||||||
|
|
||||||
|
x86_write_msr(IA32_MSR_MTRR_PHYSICAL_BASE_0 + index,
|
||||||
|
(base & ~(B_PAGE_SIZE - 1)) | type);
|
||||||
|
x86_write_msr(IA32_MSR_MTRR_PHYSICAL_MASK_0 + index,
|
||||||
|
mask | IA32_MTRR_VALID_RANGE);
|
||||||
|
} else {
|
||||||
|
// reset base as well
|
||||||
|
x86_write_msr(IA32_MSR_MTRR_PHYSICAL_BASE_0 + index, 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static status_t
|
static status_t
|
||||||
via_set_mtrr(uint32 index, addr_t base, addr_t length, uint32 type)
|
via_get_mtrr(uint32 index, uint64 *_base, uint64 *_length, uint8 *_type)
|
||||||
{
|
{
|
||||||
return B_OK;
|
uint64 mask = x86_read_msr(IA32_MSR_MTRR_PHYSICAL_MASK_0 + index * 2);
|
||||||
}
|
if ((mask & IA32_MTRR_VALID_RANGE) == 0)
|
||||||
|
return B_ERROR;
|
||||||
|
|
||||||
|
uint64 base = x86_read_msr(IA32_MSR_MTRR_PHYSICAL_BASE_0 + index * 2);
|
||||||
|
|
||||||
|
*_base = base & ~(B_PAGE_SIZE - 1);
|
||||||
|
*_length = (~mask & kPhysicalMask) + 1;
|
||||||
|
*_type = base & 0xff;
|
||||||
|
|
||||||
static status_t
|
|
||||||
via_unset_mtrr(uint32 index)
|
|
||||||
{
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -41,6 +124,25 @@ via_init(void)
|
|||||||
if ((info.cpu_type & B_CPU_x86_VENDOR_MASK) != B_CPU_VIA_IDT_x86)
|
if ((info.cpu_type & B_CPU_x86_VENDOR_MASK) != B_CPU_VIA_IDT_x86)
|
||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
|
|
||||||
|
if (x86_read_msr(IA32_MSR_MTRR_DEFAULT_TYPE) & IA32_MTRR_ENABLE) {
|
||||||
|
TRACE(("MTRR enabled\n"));
|
||||||
|
} else {
|
||||||
|
TRACE(("MTRR disabled\n"));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (uint32 i = 0; i < via_count_mtrrs(); i++) {
|
||||||
|
uint64 base;
|
||||||
|
uint64 length;
|
||||||
|
uint8 type;
|
||||||
|
if (via_get_mtrr(i, &base, &length, &type) == B_OK) {
|
||||||
|
TRACE((" %ld: 0x%Lx, 0x%Lx, %u\n", i, base, length, type));
|
||||||
|
} else {
|
||||||
|
TRACE((" %ld: empty\n", i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: dump fixed ranges as well
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -74,6 +176,8 @@ x86_cpu_module_info gVIAModule = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
via_count_mtrrs,
|
via_count_mtrrs,
|
||||||
|
via_init_mtrrs,
|
||||||
|
|
||||||
via_set_mtrr,
|
via_set_mtrr,
|
||||||
via_unset_mtrr,
|
via_get_mtrr,
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user