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