2 * MTRR (Memory Type Range Register) cleanup
4 * Copyright (C) 2009 Yinghai Lu
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Library General Public License for more details.
16 * You should have received a copy of the GNU Library General Public
17 * License along with this library; if not, write to the Free
18 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 #include <linux/module.h>
21 #include <linux/init.h>
22 #include <linux/pci.h>
23 #include <linux/smp.h>
24 #include <linux/cpu.h>
25 #include <linux/mutex.h>
26 #include <linux/uaccess.h>
27 #include <linux/kvm_para.h>
28 #include <linux/range.h>
30 #include <asm/processor.h>
37 struct var_mtrr_range_state
{
38 unsigned long base_pfn
;
39 unsigned long size_pfn
;
43 struct var_mtrr_state
{
44 unsigned long range_startk
;
45 unsigned long range_sizek
;
46 unsigned long chunk_sizek
;
47 unsigned long gran_sizek
;
51 /* Should be related to MTRR_VAR_RANGES nums */
54 static struct range __initdata range
[RANGE_NUM
];
55 static int __initdata nr_range
;
57 static struct var_mtrr_range_state __initdata range_state
[RANGE_NUM
];
59 static int __initdata debug_print
;
60 #define Dprintk(x...) do { if (debug_print) printk(KERN_DEBUG x); } while (0)
62 #define BIOS_BUG_MSG KERN_WARNING \
63 "WARNING: BIOS bug: VAR MTRR %d contains strange UC entry under 1M, check with your system vendor!\n"
66 x86_get_mtrr_mem_range(struct range
*range
, int nr_range
,
67 unsigned long extra_remove_base
,
68 unsigned long extra_remove_size
)
70 unsigned long base
, size
;
74 for (i
= 0; i
< num_var_ranges
; i
++) {
75 type
= range_state
[i
].type
;
76 if (type
!= MTRR_TYPE_WRBACK
)
78 base
= range_state
[i
].base_pfn
;
79 size
= range_state
[i
].size_pfn
;
80 nr_range
= add_range_with_merge(range
, RANGE_NUM
, nr_range
,
84 printk(KERN_DEBUG
"After WB checking\n");
85 for (i
= 0; i
< nr_range
; i
++)
86 printk(KERN_DEBUG
"MTRR MAP PFN: %016llx - %016llx\n",
87 range
[i
].start
, range
[i
].end
);
90 /* Take out UC ranges: */
91 for (i
= 0; i
< num_var_ranges
; i
++) {
92 type
= range_state
[i
].type
;
93 if (type
!= MTRR_TYPE_UNCACHABLE
&&
94 type
!= MTRR_TYPE_WRPROT
)
96 size
= range_state
[i
].size_pfn
;
99 base
= range_state
[i
].base_pfn
;
100 if (base
< (1<<(20-PAGE_SHIFT
)) && mtrr_state
.have_fixed
&&
101 (mtrr_state
.enabled
& MTRR_STATE_MTRR_ENABLED
) &&
102 (mtrr_state
.enabled
& MTRR_STATE_MTRR_FIXED_ENABLED
)) {
103 /* Var MTRR contains UC entry below 1M? Skip it: */
104 printk(BIOS_BUG_MSG
, i
);
105 if (base
+ size
<= (1<<(20-PAGE_SHIFT
)))
107 size
-= (1<<(20-PAGE_SHIFT
)) - base
;
108 base
= 1<<(20-PAGE_SHIFT
);
110 subtract_range(range
, RANGE_NUM
, base
, base
+ size
);
112 if (extra_remove_size
)
113 subtract_range(range
, RANGE_NUM
, extra_remove_base
,
114 extra_remove_base
+ extra_remove_size
);
117 printk(KERN_DEBUG
"After UC checking\n");
118 for (i
= 0; i
< RANGE_NUM
; i
++) {
121 printk(KERN_DEBUG
"MTRR MAP PFN: %016llx - %016llx\n",
122 range
[i
].start
, range
[i
].end
);
126 /* sort the ranges */
127 nr_range
= clean_sort_range(range
, RANGE_NUM
);
129 printk(KERN_DEBUG
"After sorting\n");
130 for (i
= 0; i
< nr_range
; i
++)
131 printk(KERN_DEBUG
"MTRR MAP PFN: %016llx - %016llx\n",
132 range
[i
].start
, range
[i
].end
);
138 #ifdef CONFIG_MTRR_SANITIZER
140 static unsigned long __init
sum_ranges(struct range
*range
, int nr_range
)
142 unsigned long sum
= 0;
145 for (i
= 0; i
< nr_range
; i
++)
146 sum
+= range
[i
].end
- range
[i
].start
;
151 static int enable_mtrr_cleanup __initdata
=
152 CONFIG_MTRR_SANITIZER_ENABLE_DEFAULT
;
154 static int __init
disable_mtrr_cleanup_setup(char *str
)
156 enable_mtrr_cleanup
= 0;
159 early_param("disable_mtrr_cleanup", disable_mtrr_cleanup_setup
);
161 static int __init
enable_mtrr_cleanup_setup(char *str
)
163 enable_mtrr_cleanup
= 1;
166 early_param("enable_mtrr_cleanup", enable_mtrr_cleanup_setup
);
168 static int __init
mtrr_cleanup_debug_setup(char *str
)
173 early_param("mtrr_cleanup_debug", mtrr_cleanup_debug_setup
);
176 set_var_mtrr(unsigned int reg
, unsigned long basek
, unsigned long sizek
,
177 unsigned char type
, unsigned int address_bits
)
179 u32 base_lo
, base_hi
, mask_lo
, mask_hi
;
183 fill_mtrr_var_range(reg
, 0, 0, 0, 0);
187 mask
= (1ULL << address_bits
) - 1;
188 mask
&= ~((((u64
)sizek
) << 10) - 1);
190 base
= ((u64
)basek
) << 10;
195 base_lo
= base
& ((1ULL<<32) - 1);
196 base_hi
= base
>> 32;
198 mask_lo
= mask
& ((1ULL<<32) - 1);
199 mask_hi
= mask
>> 32;
201 fill_mtrr_var_range(reg
, base_lo
, base_hi
, mask_lo
, mask_hi
);
205 save_var_mtrr(unsigned int reg
, unsigned long basek
, unsigned long sizek
,
208 range_state
[reg
].base_pfn
= basek
>> (PAGE_SHIFT
- 10);
209 range_state
[reg
].size_pfn
= sizek
>> (PAGE_SHIFT
- 10);
210 range_state
[reg
].type
= type
;
213 static void __init
set_var_mtrr_all(unsigned int address_bits
)
215 unsigned long basek
, sizek
;
219 for (reg
= 0; reg
< num_var_ranges
; reg
++) {
220 basek
= range_state
[reg
].base_pfn
<< (PAGE_SHIFT
- 10);
221 sizek
= range_state
[reg
].size_pfn
<< (PAGE_SHIFT
- 10);
222 type
= range_state
[reg
].type
;
224 set_var_mtrr(reg
, basek
, sizek
, type
, address_bits
);
228 static unsigned long to_size_factor(unsigned long sizek
, char *factorp
)
230 unsigned long base
= sizek
;
233 if (base
& ((1<<10) - 1)) {
234 /* Not MB-aligned: */
236 } else if (base
& ((1<<20) - 1)) {
249 static unsigned int __init
250 range_to_mtrr(unsigned int reg
, unsigned long range_startk
,
251 unsigned long range_sizek
, unsigned char type
)
253 if (!range_sizek
|| (reg
>= num_var_ranges
))
256 while (range_sizek
) {
257 unsigned long max_align
, align
;
260 /* Compute the maximum size with which we can make a range: */
262 max_align
= __ffs(range_startk
);
264 max_align
= BITS_PER_LONG
- 1;
266 align
= __fls(range_sizek
);
267 if (align
> max_align
)
270 sizek
= 1UL << align
;
272 char start_factor
= 'K', size_factor
= 'K';
273 unsigned long start_base
, size_base
;
275 start_base
= to_size_factor(range_startk
, &start_factor
);
276 size_base
= to_size_factor(sizek
, &size_factor
);
278 Dprintk("Setting variable MTRR %d, "
279 "base: %ld%cB, range: %ld%cB, type %s\n",
280 reg
, start_base
, start_factor
,
281 size_base
, size_factor
,
282 (type
== MTRR_TYPE_UNCACHABLE
) ? "UC" :
283 ((type
== MTRR_TYPE_WRBACK
) ? "WB" : "Other")
286 save_var_mtrr(reg
++, range_startk
, sizek
, type
);
287 range_startk
+= sizek
;
288 range_sizek
-= sizek
;
289 if (reg
>= num_var_ranges
)
295 static unsigned __init
296 range_to_mtrr_with_hole(struct var_mtrr_state
*state
, unsigned long basek
,
299 unsigned long hole_basek
, hole_sizek
;
300 unsigned long second_basek
, second_sizek
;
301 unsigned long range0_basek
, range0_sizek
;
302 unsigned long range_basek
, range_sizek
;
303 unsigned long chunk_sizek
;
304 unsigned long gran_sizek
;
310 chunk_sizek
= state
->chunk_sizek
;
311 gran_sizek
= state
->gran_sizek
;
313 /* Align with gran size, prevent small block used up MTRRs: */
314 range_basek
= ALIGN(state
->range_startk
, gran_sizek
);
315 if ((range_basek
> basek
) && basek
)
318 state
->range_sizek
-= (range_basek
- state
->range_startk
);
319 range_sizek
= ALIGN(state
->range_sizek
, gran_sizek
);
321 while (range_sizek
> state
->range_sizek
) {
322 range_sizek
-= gran_sizek
;
326 state
->range_sizek
= range_sizek
;
328 /* Try to append some small hole: */
329 range0_basek
= state
->range_startk
;
330 range0_sizek
= ALIGN(state
->range_sizek
, chunk_sizek
);
333 if (range0_sizek
== state
->range_sizek
) {
334 Dprintk("rangeX: %016lx - %016lx\n",
336 (range0_basek
+ state
->range_sizek
)<<10);
337 state
->reg
= range_to_mtrr(state
->reg
, range0_basek
,
338 state
->range_sizek
, MTRR_TYPE_WRBACK
);
342 /* Only cut back when it is not the last: */
344 while (range0_basek
+ range0_sizek
> (basek
+ sizek
)) {
345 if (range0_sizek
>= chunk_sizek
)
346 range0_sizek
-= chunk_sizek
;
356 range_basek
= range0_basek
+ range0_sizek
;
358 /* One hole in the middle: */
359 if (range_basek
> basek
&& range_basek
<= (basek
+ sizek
))
360 second_sizek
= range_basek
- basek
;
362 if (range0_sizek
> state
->range_sizek
) {
364 /* One hole in middle or at the end: */
365 hole_sizek
= range0_sizek
- state
->range_sizek
- second_sizek
;
367 /* Hole size should be less than half of range0 size: */
368 if (hole_sizek
>= (range0_sizek
>> 1) &&
369 range0_sizek
>= chunk_sizek
) {
370 range0_sizek
-= chunk_sizek
;
379 Dprintk("range0: %016lx - %016lx\n",
381 (range0_basek
+ range0_sizek
)<<10);
382 state
->reg
= range_to_mtrr(state
->reg
, range0_basek
,
383 range0_sizek
, MTRR_TYPE_WRBACK
);
386 if (range0_sizek
< state
->range_sizek
) {
387 /* Need to handle left over range: */
388 range_sizek
= state
->range_sizek
- range0_sizek
;
390 Dprintk("range: %016lx - %016lx\n",
392 (range_basek
+ range_sizek
)<<10);
394 state
->reg
= range_to_mtrr(state
->reg
, range_basek
,
395 range_sizek
, MTRR_TYPE_WRBACK
);
399 hole_basek
= range_basek
- hole_sizek
- second_sizek
;
400 Dprintk("hole: %016lx - %016lx\n",
402 (hole_basek
+ hole_sizek
)<<10);
403 state
->reg
= range_to_mtrr(state
->reg
, hole_basek
,
404 hole_sizek
, MTRR_TYPE_UNCACHABLE
);
411 set_var_mtrr_range(struct var_mtrr_state
*state
, unsigned long base_pfn
,
412 unsigned long size_pfn
)
414 unsigned long basek
, sizek
;
415 unsigned long second_sizek
= 0;
417 if (state
->reg
>= num_var_ranges
)
420 basek
= base_pfn
<< (PAGE_SHIFT
- 10);
421 sizek
= size_pfn
<< (PAGE_SHIFT
- 10);
423 /* See if I can merge with the last range: */
424 if ((basek
<= 1024) ||
425 (state
->range_startk
+ state
->range_sizek
== basek
)) {
426 unsigned long endk
= basek
+ sizek
;
427 state
->range_sizek
= endk
- state
->range_startk
;
430 /* Write the range mtrrs: */
431 if (state
->range_sizek
!= 0)
432 second_sizek
= range_to_mtrr_with_hole(state
, basek
, sizek
);
434 /* Allocate an msr: */
435 state
->range_startk
= basek
+ second_sizek
;
436 state
->range_sizek
= sizek
- second_sizek
;
439 /* Mininum size of mtrr block that can take hole: */
440 static u64 mtrr_chunk_size __initdata
= (256ULL<<20);
442 static int __init
parse_mtrr_chunk_size_opt(char *p
)
446 mtrr_chunk_size
= memparse(p
, &p
);
449 early_param("mtrr_chunk_size", parse_mtrr_chunk_size_opt
);
451 /* Granularity of mtrr of block: */
452 static u64 mtrr_gran_size __initdata
;
454 static int __init
parse_mtrr_gran_size_opt(char *p
)
458 mtrr_gran_size
= memparse(p
, &p
);
461 early_param("mtrr_gran_size", parse_mtrr_gran_size_opt
);
463 static unsigned long nr_mtrr_spare_reg __initdata
=
464 CONFIG_MTRR_SANITIZER_SPARE_REG_NR_DEFAULT
;
466 static int __init
parse_mtrr_spare_reg(char *arg
)
469 nr_mtrr_spare_reg
= simple_strtoul(arg
, NULL
, 0);
472 early_param("mtrr_spare_reg_nr", parse_mtrr_spare_reg
);
475 x86_setup_var_mtrrs(struct range
*range
, int nr_range
,
476 u64 chunk_size
, u64 gran_size
)
478 struct var_mtrr_state var_state
;
482 var_state
.range_startk
= 0;
483 var_state
.range_sizek
= 0;
485 var_state
.chunk_sizek
= chunk_size
>> 10;
486 var_state
.gran_sizek
= gran_size
>> 10;
488 memset(range_state
, 0, sizeof(range_state
));
490 /* Write the range: */
491 for (i
= 0; i
< nr_range
; i
++) {
492 set_var_mtrr_range(&var_state
, range
[i
].start
,
493 range
[i
].end
- range
[i
].start
);
496 /* Write the last range: */
497 if (var_state
.range_sizek
!= 0)
498 range_to_mtrr_with_hole(&var_state
, 0, 0);
500 num_reg
= var_state
.reg
;
501 /* Clear out the extra MTRR's: */
502 while (var_state
.reg
< num_var_ranges
) {
503 save_var_mtrr(var_state
.reg
, 0, 0, 0);
510 struct mtrr_cleanup_result
{
511 unsigned long gran_sizek
;
512 unsigned long chunk_sizek
;
513 unsigned long lose_cover_sizek
;
514 unsigned int num_reg
;
519 * gran_size: 64K, 128K, 256K, 512K, 1M, 2M, ..., 2G
520 * chunk size: gran_size, ..., 2G
521 * so we need (1+16)*8
523 #define NUM_RESULT 136
524 #define PSHIFT (PAGE_SHIFT - 10)
526 static struct mtrr_cleanup_result __initdata result
[NUM_RESULT
];
527 static unsigned long __initdata min_loss_pfn
[RANGE_NUM
];
529 static void __init
print_out_mtrr_range_state(void)
531 char start_factor
= 'K', size_factor
= 'K';
532 unsigned long start_base
, size_base
;
536 for (i
= 0; i
< num_var_ranges
; i
++) {
538 size_base
= range_state
[i
].size_pfn
<< (PAGE_SHIFT
- 10);
542 size_base
= to_size_factor(size_base
, &size_factor
),
543 start_base
= range_state
[i
].base_pfn
<< (PAGE_SHIFT
- 10);
544 start_base
= to_size_factor(start_base
, &start_factor
),
545 type
= range_state
[i
].type
;
547 printk(KERN_DEBUG
"reg %d, base: %ld%cB, range: %ld%cB, type %s\n",
548 i
, start_base
, start_factor
,
549 size_base
, size_factor
,
550 (type
== MTRR_TYPE_UNCACHABLE
) ? "UC" :
551 ((type
== MTRR_TYPE_WRPROT
) ? "WP" :
552 ((type
== MTRR_TYPE_WRBACK
) ? "WB" : "Other"))
557 static int __init
mtrr_need_cleanup(void)
562 /* Extra one for all 0: */
563 int num
[MTRR_NUM_TYPES
+ 1];
565 /* Check entries number: */
566 memset(num
, 0, sizeof(num
));
567 for (i
= 0; i
< num_var_ranges
; i
++) {
568 type
= range_state
[i
].type
;
569 size
= range_state
[i
].size_pfn
;
570 if (type
>= MTRR_NUM_TYPES
)
573 type
= MTRR_NUM_TYPES
;
577 /* Check if we got UC entries: */
578 if (!num
[MTRR_TYPE_UNCACHABLE
])
581 /* Check if we only had WB and UC */
582 if (num
[MTRR_TYPE_WRBACK
] + num
[MTRR_TYPE_UNCACHABLE
] !=
583 num_var_ranges
- num
[MTRR_NUM_TYPES
])
589 static unsigned long __initdata range_sums
;
592 mtrr_calc_range_state(u64 chunk_size
, u64 gran_size
,
593 unsigned long x_remove_base
,
594 unsigned long x_remove_size
, int i
)
597 * range_new should really be an automatic variable, but
598 * putting 4096 bytes on the stack is frowned upon, to put it
599 * mildly. It is safe to make it a static __initdata variable,
600 * since mtrr_calc_range_state is only called during init and
601 * there's no way it will call itself recursively.
603 static struct range range_new
[RANGE_NUM
] __initdata
;
604 unsigned long range_sums_new
;
608 /* Convert ranges to var ranges state: */
609 num_reg
= x86_setup_var_mtrrs(range
, nr_range
, chunk_size
, gran_size
);
611 /* We got new setting in range_state, check it: */
612 memset(range_new
, 0, sizeof(range_new
));
613 nr_range_new
= x86_get_mtrr_mem_range(range_new
, 0,
614 x_remove_base
, x_remove_size
);
615 range_sums_new
= sum_ranges(range_new
, nr_range_new
);
617 result
[i
].chunk_sizek
= chunk_size
>> 10;
618 result
[i
].gran_sizek
= gran_size
>> 10;
619 result
[i
].num_reg
= num_reg
;
621 if (range_sums
< range_sums_new
) {
622 result
[i
].lose_cover_sizek
= (range_sums_new
- range_sums
) << PSHIFT
;
625 result
[i
].lose_cover_sizek
= (range_sums
- range_sums_new
) << PSHIFT
;
628 /* Double check it: */
629 if (!result
[i
].bad
&& !result
[i
].lose_cover_sizek
) {
630 if (nr_range_new
!= nr_range
|| memcmp(range
, range_new
, sizeof(range
)))
634 if (!result
[i
].bad
&& (range_sums
- range_sums_new
< min_loss_pfn
[num_reg
]))
635 min_loss_pfn
[num_reg
] = range_sums
- range_sums_new
;
638 static void __init
mtrr_print_out_one_result(int i
)
640 unsigned long gran_base
, chunk_base
, lose_base
;
641 char gran_factor
, chunk_factor
, lose_factor
;
643 gran_base
= to_size_factor(result
[i
].gran_sizek
, &gran_factor
);
644 chunk_base
= to_size_factor(result
[i
].chunk_sizek
, &chunk_factor
);
645 lose_base
= to_size_factor(result
[i
].lose_cover_sizek
, &lose_factor
);
647 pr_info("%sgran_size: %ld%c \tchunk_size: %ld%c \t",
648 result
[i
].bad
? "*BAD*" : " ",
649 gran_base
, gran_factor
, chunk_base
, chunk_factor
);
650 pr_cont("num_reg: %d \tlose cover RAM: %s%ld%c\n",
651 result
[i
].num_reg
, result
[i
].bad
? "-" : "",
652 lose_base
, lose_factor
);
655 static int __init
mtrr_search_optimal_index(void)
661 if (nr_mtrr_spare_reg
>= num_var_ranges
)
662 nr_mtrr_spare_reg
= num_var_ranges
- 1;
665 for (i
= num_var_ranges
- nr_mtrr_spare_reg
; i
> 0; i
--) {
666 if (!min_loss_pfn
[i
])
671 if (num_reg_good
!= -1) {
672 for (i
= 0; i
< NUM_RESULT
; i
++) {
673 if (!result
[i
].bad
&&
674 result
[i
].num_reg
== num_reg_good
&&
675 !result
[i
].lose_cover_sizek
) {
685 int __init
mtrr_cleanup(unsigned address_bits
)
687 unsigned long x_remove_base
, x_remove_size
;
688 unsigned long base
, size
, def
, dummy
;
689 u64 chunk_size
, gran_size
;
694 if (!is_cpu(INTEL
) || enable_mtrr_cleanup
< 1)
697 rdmsr(MSR_MTRRdefType
, def
, dummy
);
699 if (def
!= MTRR_TYPE_UNCACHABLE
)
702 /* Get it and store it aside: */
703 memset(range_state
, 0, sizeof(range_state
));
704 for (i
= 0; i
< num_var_ranges
; i
++) {
705 mtrr_if
->get(i
, &base
, &size
, &type
);
706 range_state
[i
].base_pfn
= base
;
707 range_state
[i
].size_pfn
= size
;
708 range_state
[i
].type
= type
;
711 /* Check if we need handle it and can handle it: */
712 if (!mtrr_need_cleanup())
715 /* Print original var MTRRs at first, for debugging: */
716 printk(KERN_DEBUG
"original variable MTRRs\n");
717 print_out_mtrr_range_state();
719 memset(range
, 0, sizeof(range
));
721 x_remove_base
= 1 << (32 - PAGE_SHIFT
);
723 x_remove_size
= (mtrr_tom2
>> PAGE_SHIFT
) - x_remove_base
;
726 * [0, 1M) should always be covered by var mtrr with WB
727 * and fixed mtrrs should take effect before var mtrr for it:
729 nr_range
= add_range_with_merge(range
, RANGE_NUM
, 0, 0,
730 1ULL<<(20 - PAGE_SHIFT
));
731 /* add from var mtrr at last */
732 nr_range
= x86_get_mtrr_mem_range(range
, nr_range
,
733 x_remove_base
, x_remove_size
);
735 range_sums
= sum_ranges(range
, nr_range
);
736 printk(KERN_INFO
"total RAM covered: %ldM\n",
737 range_sums
>> (20 - PAGE_SHIFT
));
739 if (mtrr_chunk_size
&& mtrr_gran_size
) {
741 mtrr_calc_range_state(mtrr_chunk_size
, mtrr_gran_size
,
742 x_remove_base
, x_remove_size
, i
);
744 mtrr_print_out_one_result(i
);
746 if (!result
[i
].bad
) {
747 set_var_mtrr_all(address_bits
);
748 printk(KERN_DEBUG
"New variable MTRRs\n");
749 print_out_mtrr_range_state();
752 printk(KERN_INFO
"invalid mtrr_gran_size or mtrr_chunk_size, "
753 "will find optimal one\n");
757 memset(min_loss_pfn
, 0xff, sizeof(min_loss_pfn
));
758 memset(result
, 0, sizeof(result
));
759 for (gran_size
= (1ULL<<16); gran_size
< (1ULL<<32); gran_size
<<= 1) {
761 for (chunk_size
= gran_size
; chunk_size
< (1ULL<<32);
767 mtrr_calc_range_state(chunk_size
, gran_size
,
768 x_remove_base
, x_remove_size
, i
);
770 mtrr_print_out_one_result(i
);
771 printk(KERN_INFO
"\n");
778 /* Try to find the optimal index: */
779 index_good
= mtrr_search_optimal_index();
781 if (index_good
!= -1) {
782 printk(KERN_INFO
"Found optimal setting for mtrr clean up\n");
784 mtrr_print_out_one_result(i
);
786 /* Convert ranges to var ranges state: */
787 chunk_size
= result
[i
].chunk_sizek
;
789 gran_size
= result
[i
].gran_sizek
;
791 x86_setup_var_mtrrs(range
, nr_range
, chunk_size
, gran_size
);
792 set_var_mtrr_all(address_bits
);
793 printk(KERN_DEBUG
"New variable MTRRs\n");
794 print_out_mtrr_range_state();
798 for (i
= 0; i
< NUM_RESULT
; i
++)
799 mtrr_print_out_one_result(i
);
802 printk(KERN_INFO
"mtrr_cleanup: can not find optimal value\n");
803 printk(KERN_INFO
"please specify mtrr_gran_size/mtrr_chunk_size\n");
808 int __init
mtrr_cleanup(unsigned address_bits
)
814 static int disable_mtrr_trim
;
816 static int __init
disable_mtrr_trim_setup(char *str
)
818 disable_mtrr_trim
= 1;
821 early_param("disable_mtrr_trim", disable_mtrr_trim_setup
);
824 * Newer AMD K8s and later CPUs have a special magic MSR way to force WB
825 * for memory >4GB. Check for that here.
826 * Note this won't check if the MTRRs < 4GB where the magic bit doesn't
827 * apply to are wrong, but so far we don't know of any such case in the wild.
829 #define Tom2Enabled (1U << 21)
830 #define Tom2ForceMemTypeWB (1U << 22)
832 int __init
amd_special_default_mtrr(void)
836 if (boot_cpu_data
.x86_vendor
!= X86_VENDOR_AMD
)
838 if (boot_cpu_data
.x86
< 0xf)
840 /* In case some hypervisor doesn't pass SYSCFG through: */
841 if (rdmsr_safe(MSR_K8_SYSCFG
, &l
, &h
) < 0)
844 * Memory between 4GB and top of mem is forced WB by this magic bit.
845 * Reserved before K8RevF, but should be zero there.
847 if ((l
& (Tom2Enabled
| Tom2ForceMemTypeWB
)) ==
848 (Tom2Enabled
| Tom2ForceMemTypeWB
))
854 real_trim_memory(unsigned long start_pfn
, unsigned long limit_pfn
)
856 u64 trim_start
, trim_size
;
858 trim_start
= start_pfn
;
859 trim_start
<<= PAGE_SHIFT
;
861 trim_size
= limit_pfn
;
862 trim_size
<<= PAGE_SHIFT
;
863 trim_size
-= trim_start
;
865 return e820_update_range(trim_start
, trim_size
, E820_RAM
, E820_RESERVED
);
869 * mtrr_trim_uncached_memory - trim RAM not covered by MTRRs
870 * @end_pfn: ending page frame number
872 * Some buggy BIOSes don't setup the MTRRs properly for systems with certain
873 * memory configurations. This routine checks that the highest MTRR matches
874 * the end of memory, to make sure the MTRRs having a write back type cover
875 * all of the memory the kernel is intending to use. If not, it'll trim any
876 * memory off the end by adjusting end_pfn, removing it from the kernel's
877 * allocation pools, warning the user with an obnoxious message.
879 int __init
mtrr_trim_uncached_memory(unsigned long end_pfn
)
881 unsigned long i
, base
, size
, highest_pfn
= 0, def
, dummy
;
884 /* extra one for all 0 */
885 int num
[MTRR_NUM_TYPES
+ 1];
888 * Make sure we only trim uncachable memory on machines that
889 * support the Intel MTRR architecture:
891 if (!is_cpu(INTEL
) || disable_mtrr_trim
)
894 rdmsr(MSR_MTRRdefType
, def
, dummy
);
896 if (def
!= MTRR_TYPE_UNCACHABLE
)
899 /* Get it and store it aside: */
900 memset(range_state
, 0, sizeof(range_state
));
901 for (i
= 0; i
< num_var_ranges
; i
++) {
902 mtrr_if
->get(i
, &base
, &size
, &type
);
903 range_state
[i
].base_pfn
= base
;
904 range_state
[i
].size_pfn
= size
;
905 range_state
[i
].type
= type
;
908 /* Find highest cached pfn: */
909 for (i
= 0; i
< num_var_ranges
; i
++) {
910 type
= range_state
[i
].type
;
911 if (type
!= MTRR_TYPE_WRBACK
)
913 base
= range_state
[i
].base_pfn
;
914 size
= range_state
[i
].size_pfn
;
915 if (highest_pfn
< base
+ size
)
916 highest_pfn
= base
+ size
;
919 /* kvm/qemu doesn't have mtrr set right, don't trim them all: */
921 printk(KERN_INFO
"CPU MTRRs all blank - virtualized system.\n");
925 /* Check entries number: */
926 memset(num
, 0, sizeof(num
));
927 for (i
= 0; i
< num_var_ranges
; i
++) {
928 type
= range_state
[i
].type
;
929 if (type
>= MTRR_NUM_TYPES
)
931 size
= range_state
[i
].size_pfn
;
933 type
= MTRR_NUM_TYPES
;
937 /* No entry for WB? */
938 if (!num
[MTRR_TYPE_WRBACK
])
941 /* Check if we only had WB and UC: */
942 if (num
[MTRR_TYPE_WRBACK
] + num
[MTRR_TYPE_UNCACHABLE
] !=
943 num_var_ranges
- num
[MTRR_NUM_TYPES
])
946 memset(range
, 0, sizeof(range
));
949 range
[nr_range
].start
= (1ULL<<(32 - PAGE_SHIFT
));
950 range
[nr_range
].end
= mtrr_tom2
>> PAGE_SHIFT
;
951 if (highest_pfn
< range
[nr_range
].end
)
952 highest_pfn
= range
[nr_range
].end
;
955 nr_range
= x86_get_mtrr_mem_range(range
, nr_range
, 0, 0);
957 /* Check the head: */
960 total_trim_size
+= real_trim_memory(0, range
[0].start
);
962 /* Check the holes: */
963 for (i
= 0; i
< nr_range
- 1; i
++) {
964 if (range
[i
].end
< range
[i
+1].start
)
965 total_trim_size
+= real_trim_memory(range
[i
].end
,
971 if (range
[i
].end
< end_pfn
)
972 total_trim_size
+= real_trim_memory(range
[i
].end
,
975 if (total_trim_size
) {
976 pr_warning("WARNING: BIOS bug: CPU MTRRs don't cover all of memory, losing %lluMB of RAM.\n", total_trim_size
>> 20);
978 if (!changed_by_mtrr_cleanup
)
981 pr_info("update e820 for mtrr\n");