diff options
Diffstat (limited to 'arch/x86/kernel/cpu/mtrr/state.c')
-rw-r--r-- | arch/x86/kernel/cpu/mtrr/state.c | 79 |
1 files changed, 79 insertions, 0 deletions
diff --git a/arch/x86/kernel/cpu/mtrr/state.c b/arch/x86/kernel/cpu/mtrr/state.c new file mode 100644 index 00000000000..c9014ca4a57 --- /dev/null +++ b/arch/x86/kernel/cpu/mtrr/state.c | |||
@@ -0,0 +1,79 @@ | |||
1 | #include <linux/mm.h> | ||
2 | #include <linux/init.h> | ||
3 | #include <asm/io.h> | ||
4 | #include <asm/mtrr.h> | ||
5 | #include <asm/msr.h> | ||
6 | #include <asm-i386/processor-cyrix.h> | ||
7 | #include "mtrr.h" | ||
8 | |||
9 | |||
10 | /* Put the processor into a state where MTRRs can be safely set */ | ||
11 | void set_mtrr_prepare_save(struct set_mtrr_context *ctxt) | ||
12 | { | ||
13 | unsigned int cr0; | ||
14 | |||
15 | /* Disable interrupts locally */ | ||
16 | local_irq_save(ctxt->flags); | ||
17 | |||
18 | if (use_intel() || is_cpu(CYRIX)) { | ||
19 | |||
20 | /* Save value of CR4 and clear Page Global Enable (bit 7) */ | ||
21 | if ( cpu_has_pge ) { | ||
22 | ctxt->cr4val = read_cr4(); | ||
23 | write_cr4(ctxt->cr4val & ~X86_CR4_PGE); | ||
24 | } | ||
25 | |||
26 | /* Disable and flush caches. Note that wbinvd flushes the TLBs as | ||
27 | a side-effect */ | ||
28 | cr0 = read_cr0() | 0x40000000; | ||
29 | wbinvd(); | ||
30 | write_cr0(cr0); | ||
31 | wbinvd(); | ||
32 | |||
33 | if (use_intel()) | ||
34 | /* Save MTRR state */ | ||
35 | rdmsr(MTRRdefType_MSR, ctxt->deftype_lo, ctxt->deftype_hi); | ||
36 | else | ||
37 | /* Cyrix ARRs - everything else were excluded at the top */ | ||
38 | ctxt->ccr3 = getCx86(CX86_CCR3); | ||
39 | } | ||
40 | } | ||
41 | |||
42 | void set_mtrr_cache_disable(struct set_mtrr_context *ctxt) | ||
43 | { | ||
44 | if (use_intel()) | ||
45 | /* Disable MTRRs, and set the default type to uncached */ | ||
46 | mtrr_wrmsr(MTRRdefType_MSR, ctxt->deftype_lo & 0xf300UL, | ||
47 | ctxt->deftype_hi); | ||
48 | else if (is_cpu(CYRIX)) | ||
49 | /* Cyrix ARRs - everything else were excluded at the top */ | ||
50 | setCx86(CX86_CCR3, (ctxt->ccr3 & 0x0f) | 0x10); | ||
51 | } | ||
52 | |||
53 | /* Restore the processor after a set_mtrr_prepare */ | ||
54 | void set_mtrr_done(struct set_mtrr_context *ctxt) | ||
55 | { | ||
56 | if (use_intel() || is_cpu(CYRIX)) { | ||
57 | |||
58 | /* Flush caches and TLBs */ | ||
59 | wbinvd(); | ||
60 | |||
61 | /* Restore MTRRdefType */ | ||
62 | if (use_intel()) | ||
63 | /* Intel (P6) standard MTRRs */ | ||
64 | mtrr_wrmsr(MTRRdefType_MSR, ctxt->deftype_lo, ctxt->deftype_hi); | ||
65 | else | ||
66 | /* Cyrix ARRs - everything else was excluded at the top */ | ||
67 | setCx86(CX86_CCR3, ctxt->ccr3); | ||
68 | |||
69 | /* Enable caches */ | ||
70 | write_cr0(read_cr0() & 0xbfffffff); | ||
71 | |||
72 | /* Restore value of CR4 */ | ||
73 | if ( cpu_has_pge ) | ||
74 | write_cr4(ctxt->cr4val); | ||
75 | } | ||
76 | /* Re-enable interrupts locally (if enabled previously) */ | ||
77 | local_irq_restore(ctxt->flags); | ||
78 | } | ||
79 | |||