x86 Page Attribute Table (PAT) MSR support.
Reconfigure PAT to permit write-combining memory type to be assigned on a page-by-page basis. Changes PWT and PCD bit combinations in page table entries so that they correspond to the following format: PAT |PCD ||PWT ||| 000 WB Write Back (WB) 001 WC Write Combining (WC) 010 UC- Uncached (UC-) 011 UC Uncacheable (UC)
This commit is contained in:
@@ -113,6 +113,8 @@ static struct list_head handlers[256 - 32];
|
|||||||
extern char page_fault[], general_protection_exception[];
|
extern char page_fault[], general_protection_exception[];
|
||||||
extern char debug_exception[], int3_exception[];
|
extern char debug_exception[], int3_exception[];
|
||||||
|
|
||||||
|
uint64_t boot_pat_state = 0;
|
||||||
|
|
||||||
static void init_idt(void)
|
static void init_idt(void)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
@@ -326,6 +328,65 @@ void init_pstate_and_turbo(void)
|
|||||||
//print_msr(MSR_IA32_ENERGY_PERF_BIAS);
|
//print_msr(MSR_IA32_ENERGY_PERF_BIAS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum {
|
||||||
|
PAT_UC = 0, /* uncached */
|
||||||
|
PAT_WC = 1, /* Write combining */
|
||||||
|
PAT_WT = 4, /* Write Through */
|
||||||
|
PAT_WP = 5, /* Write Protected */
|
||||||
|
PAT_WB = 6, /* Write Back (default) */
|
||||||
|
PAT_UC_MINUS = 7, /* UC, but can be overriden by MTRR */
|
||||||
|
};
|
||||||
|
|
||||||
|
#define PAT(x, y) ((uint64_t)PAT_ ## y << ((x)*8))
|
||||||
|
|
||||||
|
void init_pat(void)
|
||||||
|
{
|
||||||
|
uint64_t pat;
|
||||||
|
uint64_t edx;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* An operating system or executive can detect the availability of the
|
||||||
|
* PAT by executing the CPUID instruction with a value of 1 in the EAX
|
||||||
|
* register. Support for the PAT is indicated by the PAT flag (bit 16
|
||||||
|
* of the values returned to EDX register). If the PAT is supported,
|
||||||
|
* the operating system or executive can use the IA32_PAT MSR to program
|
||||||
|
* the PAT. When memory types have been assigned to entries in the PAT,
|
||||||
|
* software can then use of the PAT-index bit (PAT) in the page-table and
|
||||||
|
* page-directory entries along with the PCD and PWT bits to assign memory
|
||||||
|
* types from the PAT to individual pages.
|
||||||
|
*/
|
||||||
|
|
||||||
|
asm volatile("cpuid" : "=d" (edx) : "a" (0x1) : "%rbx", "%rcx");
|
||||||
|
if (!(edx & ((uint64_t)1 << 16))) {
|
||||||
|
kprintf("PAT not supported.\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set PWT to Write-Combining. All other bits stay the same */
|
||||||
|
/* (Based on Linux' settings)
|
||||||
|
*
|
||||||
|
* PTE encoding used in Linux:
|
||||||
|
* PAT
|
||||||
|
* |PCD
|
||||||
|
* ||PWT
|
||||||
|
* |||
|
||||||
|
* 000 WB _PAGE_CACHE_WB
|
||||||
|
* 001 WC _PAGE_CACHE_WC
|
||||||
|
* 010 UC- _PAGE_CACHE_UC_MINUS
|
||||||
|
* 011 UC _PAGE_CACHE_UC
|
||||||
|
* PAT bit unused
|
||||||
|
*/
|
||||||
|
pat = PAT(0, WB) | PAT(1, WC) | PAT(2, UC_MINUS) | PAT(3, UC) |
|
||||||
|
PAT(4, WB) | PAT(5, WC) | PAT(6, UC_MINUS) | PAT(7, UC);
|
||||||
|
|
||||||
|
/* Boot CPU check */
|
||||||
|
if (!boot_pat_state)
|
||||||
|
boot_pat_state = rdmsr(MSR_IA32_CR_PAT);
|
||||||
|
|
||||||
|
wrmsr(MSR_IA32_CR_PAT, pat);
|
||||||
|
kprintf("PAT support detected and reconfigured.\n");
|
||||||
|
}
|
||||||
|
|
||||||
void init_lapic(void)
|
void init_lapic(void)
|
||||||
{
|
{
|
||||||
unsigned long baseaddr;
|
unsigned long baseaddr;
|
||||||
@@ -482,6 +543,7 @@ void init_cpu(void)
|
|||||||
init_syscall();
|
init_syscall();
|
||||||
x86_init_perfctr();
|
x86_init_perfctr();
|
||||||
init_pstate_and_turbo();
|
init_pstate_and_turbo();
|
||||||
|
init_pat();
|
||||||
}
|
}
|
||||||
|
|
||||||
void setup_x86(void)
|
void setup_x86(void)
|
||||||
|
|||||||
@@ -55,6 +55,8 @@
|
|||||||
#define MSR_IA32_MISC_ENABLE 0x000001a0
|
#define MSR_IA32_MISC_ENABLE 0x000001a0
|
||||||
#define MSR_IA32_ENERGY_PERF_BIAS 0x000001b0
|
#define MSR_IA32_ENERGY_PERF_BIAS 0x000001b0
|
||||||
#define MSR_NHM_TURBO_RATIO_LIMIT 0x000001ad
|
#define MSR_NHM_TURBO_RATIO_LIMIT 0x000001ad
|
||||||
|
#define MSR_IA32_CR_PAT 0x00000277
|
||||||
|
|
||||||
|
|
||||||
#define CVAL(event, mask) \
|
#define CVAL(event, mask) \
|
||||||
((((event) & 0xf00) << 24) | ((mask) << 8) | ((event) & 0xff))
|
((((event) & 0xf00) << 24) | ((mask) << 8) | ((event) & 0xff))
|
||||||
|
|||||||
Reference in New Issue
Block a user