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/init.h>
21 #include <linux/pci.h>
22 #include <linux/smp.h>
23 #include <linux/cpu.h>
24 #include <linux/mutex.h>
25 #include <linux/uaccess.h>
26 #include <linux/kvm_para.h>
27 #include <linux/range.h>
29 #include <asm/processor.h>
30 #include <asm/e820/api.h>
36 struct var_mtrr_range_state
{
37 unsigned long base_pfn
;
38 unsigned long size_pfn
;
42 struct var_mtrr_state
{
43 unsigned long range_startk
;
44 unsigned long range_sizek
;
45 unsigned long chunk_sizek
;
46 unsigned long gran_sizek
;
50 /* Should be related to MTRR_VAR_RANGES nums */
53 static struct range __initdata range
[RANGE_NUM
];
54 static int __initdata nr_range
;
56 static struct var_mtrr_range_state __initdata range_state
[RANGE_NUM
];
58 static int __initdata debug_print
;
59 #define Dprintk(x...) do { if (debug_print) pr_debug(x); } while (0)
61 #define BIOS_BUG_MSG \
62 "WARNING: BIOS bug: VAR MTRR %d contains strange UC entry under 1M, check with your system vendor!\n"
65 x86_get_mtrr_mem_range(struct range
*range
, int nr_range
,
66 unsigned long extra_remove_base
,
67 unsigned long extra_remove_size
)
69 unsigned long base
, size
;
73 for (i
= 0; i
< num_var_ranges
; i
++) {
74 type
= range_state
[i
].type
;
75 if (type
!= MTRR_TYPE_WRBACK
)
77 base
= range_state
[i
].base_pfn
;
78 size
= range_state
[i
].size_pfn
;
79 nr_range
= add_range_with_merge(range
, RANGE_NUM
, nr_range
,
83 pr_debug("After WB checking\n");
84 for (i
= 0; i
< nr_range
; i
++)
85 pr_debug("MTRR MAP PFN: %016llx - %016llx\n",
86 range
[i
].start
, range
[i
].end
);
89 /* Take out UC ranges: */
90 for (i
= 0; i
< num_var_ranges
; i
++) {
91 type
= range_state
[i
].type
;
92 if (type
!= MTRR_TYPE_UNCACHABLE
&&
93 type
!= MTRR_TYPE_WRPROT
)
95 size
= range_state
[i
].size_pfn
;
98 base
= range_state
[i
].base_pfn
;
99 if (base
< (1<<(20-PAGE_SHIFT
)) && mtrr_state
.have_fixed
&&
100 (mtrr_state
.enabled
& MTRR_STATE_MTRR_ENABLED
) &&
101 (mtrr_state
.enabled
& MTRR_STATE_MTRR_FIXED_ENABLED
)) {
102 /* Var MTRR contains UC entry below 1M? Skip it: */
103 pr_warn(BIOS_BUG_MSG
, i
);
104 if (base
+ size
<= (1<<(20-PAGE_SHIFT
)))
106 size
-= (1<<(20-PAGE_SHIFT
)) - base
;
107 base
= 1<<(20-PAGE_SHIFT
);
109 subtract_range(range
, RANGE_NUM
, base
, base
+ size
);
111 if (extra_remove_size
)
112 subtract_range(range
, RANGE_NUM
, extra_remove_base
,
113 extra_remove_base
+ extra_remove_size
);
116 pr_debug("After UC checking\n");
117 for (i
= 0; i
< RANGE_NUM
; i
++) {
120 pr_debug("MTRR MAP PFN: %016llx - %016llx\n",
121 range
[i
].start
, range
[i
].end
);
125 /* sort the ranges */
126 nr_range
= clean_sort_range(range
, RANGE_NUM
);
128 pr_debug("After sorting\n");
129 for (i
= 0; i
< nr_range
; i
++)
130 pr_debug("MTRR MAP PFN: %016llx - %016llx\n",
131 range
[i
].start
, range
[i
].end
);
137 #ifdef CONFIG_MTRR_SANITIZER
139 static unsigned long __init
sum_ranges(struct range
*range
, int nr_range
)
141 unsigned long sum
= 0;
144 for (i
= 0; i
< nr_range
; i
++)
145 sum
+= range
[i
].end
- range
[i
].start
;
150 static int enable_mtrr_cleanup __initdata
=
151 CONFIG_MTRR_SANITIZER_ENABLE_DEFAULT
;
153 static int __init
disable_mtrr_cleanup_setup(char *str
)
155 enable_mtrr_cleanup
= 0;
158 early_param("disable_mtrr_cleanup", disable_mtrr_cleanup_setup
);
160 static int __init
enable_mtrr_cleanup_setup(char *str
)
162 enable_mtrr_cleanup
= 1;
165 early_param("enable_mtrr_cleanup", enable_mtrr_cleanup_setup
);
167 static int __init
mtrr_cleanup_debug_setup(char *str
)
172 early_param("mtrr_cleanup_debug", mtrr_cleanup_debug_setup
);
175 set_var_mtrr(unsigned int reg
, unsigned long basek
, unsigned long sizek
,
176 unsigned char type
, unsigned int address_bits
)
178 u32 base_lo
, base_hi
, mask_lo
, mask_hi
;
182 fill_mtrr_var_range(reg
, 0, 0, 0, 0);
186 mask
= (1ULL << address_bits
) - 1;
187 mask
&= ~((((u64
)sizek
) << 10) - 1);
189 base
= ((u64
)basek
) << 10;
194 base_lo
= base
& ((1ULL<<32) - 1);
195 base_hi
= base
>> 32;
197 mask_lo
= mask
& ((1ULL<<32) - 1);
198 mask_hi
= mask
>> 32;
200 fill_mtrr_var_range(reg
, base_lo
, base_hi
, mask_lo
, mask_hi
);
204 save_var_mtrr(unsigned int reg
, unsigned long basek
, unsigned long sizek
,
207 range_state
[reg
].base_pfn
= basek
>> (PAGE_SHIFT
- 10);
208 range_state
[reg
].size_pfn
= sizek
>> (PAGE_SHIFT
- 10);
209 range_state
[reg
].type
= type
;
212 static void __init
set_var_mtrr_all(unsigned int address_bits
)
214 unsigned long basek
, sizek
;
218 for (reg
= 0; reg
< num_var_ranges
; reg
++) {
219 basek
= range_state
[reg
].base_pfn
<< (PAGE_SHIFT
- 10);
220 sizek
= range_state
[reg
].size_pfn
<< (PAGE_SHIFT
- 10);
221 type
= range_state
[reg
].type
;
223 set_var_mtrr(reg
, basek
, sizek
, type
, address_bits
);
227 static unsigned long to_size_factor(unsigned long sizek
, char *factorp
)
229 unsigned long base
= sizek
;
232 if (base
& ((1<<10) - 1)) {
233 /* Not MB-aligned: */
235 } else if (base
& ((1<<20) - 1)) {
248 static unsigned int __init
249 range_to_mtrr(unsigned int reg
, unsigned long range_startk
,
250 unsigned long range_sizek
, unsigned char type
)
252 if (!range_sizek
|| (reg
>= num_var_ranges
))
255 while (range_sizek
) {
256 unsigned long max_align
, align
;
259 /* Compute the maximum size with which we can make a range: */
261 max_align
= __ffs(range_startk
);
263 max_align
= BITS_PER_LONG
- 1;
265 align
= __fls(range_sizek
);
266 if (align
> max_align
)
269 sizek
= 1UL << align
;
271 char start_factor
= 'K', size_factor
= 'K';
272 unsigned long start_base
, size_base
;
274 start_base
= to_size_factor(range_startk
, &start_factor
);
275 size_base
= to_size_factor(sizek
, &size_factor
);
277 Dprintk("Setting variable MTRR %d, "
278 "base: %ld%cB, range: %ld%cB, type %s\n",
279 reg
, start_base
, start_factor
,
280 size_base
, size_factor
,
281 (type
== MTRR_TYPE_UNCACHABLE
) ? "UC" :
282 ((type
== MTRR_TYPE_WRBACK
) ? "WB" : "Other")
285 save_var_mtrr(reg
++, range_startk
, sizek
, type
);
286 range_startk
+= sizek
;
287 range_sizek
-= sizek
;
288 if (reg
>= num_var_ranges
)
294 static unsigned __init
295 range_to_mtrr_with_hole(struct var_mtrr_state
*state
, unsigned long basek
,
298 unsigned long hole_basek
, hole_sizek
;
299 unsigned long second_basek
, second_sizek
;
300 unsigned long range0_basek
, range0_sizek
;
301 unsigned long range_basek
, range_sizek
;
302 unsigned long chunk_sizek
;
303 unsigned long gran_sizek
;
309 chunk_sizek
= state
->chunk_sizek
;
310 gran_sizek
= state
->gran_sizek
;
312 /* Align with gran size, prevent small block used up MTRRs: */
313 range_basek
= ALIGN(state
->range_startk
, gran_sizek
);
314 if ((range_basek
> basek
) && basek
)
317 state
->range_sizek
-= (range_basek
- state
->range_startk
);
318 range_sizek
= ALIGN(state
->range_sizek
, gran_sizek
);
320 while (range_sizek
> state
->range_sizek
) {
321 range_sizek
-= gran_sizek
;
325 state
->range_sizek
= range_sizek
;
327 /* Try to append some small hole: */
328 range0_basek
= state
->range_startk
;
329 range0_sizek
= ALIGN(state
->range_sizek
, chunk_sizek
);
332 if (range0_sizek
== state
->range_sizek
) {
333 Dprintk("rangeX: %016lx - %016lx\n",
335 (range0_basek
+ state
->range_sizek
)<<10);
336 state
->reg
= range_to_mtrr(state
->reg
, range0_basek
,
337 state
->range_sizek
, MTRR_TYPE_WRBACK
);
341 /* Only cut back when it is not the last: */
343 while (range0_basek
+ range0_sizek
> (basek
+ sizek
)) {
344 if (range0_sizek
>= chunk_sizek
)
345 range0_sizek
-= chunk_sizek
;
355 range_basek
= range0_basek
+ range0_sizek
;
357 /* One hole in the middle: */
358 if (range_basek
> basek
&& range_basek
<= (basek
+ sizek
))
359 second_sizek
= range_basek
- basek
;
361 if (range0_sizek
> state
->range_sizek
) {
363 /* One hole in middle or at the end: */
364 hole_sizek
= range0_sizek
- state
->range_sizek
- second_sizek
;
366 /* Hole size should be less than half of range0 size: */
367 if (hole_sizek
>= (range0_sizek
>> 1) &&
368 range0_sizek
>= chunk_sizek
) {
369 range0_sizek
-= chunk_sizek
;
378 Dprintk("range0: %016lx - %016lx\n",
380 (range0_basek
+ range0_sizek
)<<10);
381 state
->reg
= range_to_mtrr(state
->reg
, range0_basek
,
382 range0_sizek
, MTRR_TYPE_WRBACK
);
385 if (range0_sizek
< state
->range_sizek
) {
386 /* Need to handle left over range: */
387 range_sizek
= state
->range_sizek
- range0_sizek
;
389 Dprintk("range: %016lx - %016lx\n",
391 (range_basek
+ range_sizek
)<<10);
393 state
->reg
= range_to_mtrr(state
->reg
, range_basek
,
394 range_sizek
, MTRR_TYPE_WRBACK
);
398 hole_basek
= range_basek
- hole_sizek
- second_sizek
;
399 Dprintk("hole: %016lx - %016lx\n",
401 (hole_basek
+ hole_sizek
)<<10);
402 state
->reg
= range_to_mtrr(state
->reg
, hole_basek
,
403 hole_sizek
, MTRR_TYPE_UNCACHABLE
);
410 set_var_mtrr_range(struct var_mtrr_state
*state
, unsigned long base_pfn
,
411 unsigned long size_pfn
)
413 unsigned long basek
, sizek
;
414 unsigned long second_sizek
= 0;
416 if (state
->reg
>= num_var_ranges
)
419 basek
= base_pfn
<< (PAGE_SHIFT
- 10);
420 sizek
= size_pfn
<< (PAGE_SHIFT
- 10);
422 /* See if I can merge with the last range: */
423 if ((basek
<= 1024) ||
424 (state
->range_startk
+ state
->range_sizek
== basek
)) {
425 unsigned long endk
= basek
+ sizek
;
426 state
->range_sizek
= endk
- state
->range_startk
;
429 /* Write the range mtrrs: */
430 if (state
->range_sizek
!= 0)
431 second_sizek
= range_to_mtrr_with_hole(state
, basek
, sizek
);
433 /* Allocate an msr: */
434 state
->range_startk
= basek
+ second_sizek
;
435 state
->range_sizek
= sizek
- second_sizek
;
438 /* Mininum size of mtrr block that can take hole: */
439 static u64 mtrr_chunk_size __initdata
= (256ULL<<20);
441 static int __init
parse_mtrr_chunk_size_opt(char *p
)
445 mtrr_chunk_size
= memparse(p
, &p
);
448 early_param("mtrr_chunk_size", parse_mtrr_chunk_size_opt
);
450 /* Granularity of mtrr of block: */
451 static u64 mtrr_gran_size __initdata
;
453 static int __init
parse_mtrr_gran_size_opt(char *p
)
457 mtrr_gran_size
= memparse(p
, &p
);
460 early_param("mtrr_gran_size", parse_mtrr_gran_size_opt
);
462 static unsigned long nr_mtrr_spare_reg __initdata
=
463 CONFIG_MTRR_SANITIZER_SPARE_REG_NR_DEFAULT
;
465 static int __init
parse_mtrr_spare_reg(char *arg
)
468 nr_mtrr_spare_reg
= simple_strtoul(arg
, NULL
, 0);
471 early_param("mtrr_spare_reg_nr", parse_mtrr_spare_reg
);
474 x86_setup_var_mtrrs(struct range
*range
, int nr_range
,
475 u64 chunk_size
, u64 gran_size
)
477 struct var_mtrr_state var_state
;
481 var_state
.range_startk
= 0;
482 var_state
.range_sizek
= 0;
484 var_state
.chunk_sizek
= chunk_size
>> 10;
485 var_state
.gran_sizek
= gran_size
>> 10;
487 memset(range_state
, 0, sizeof(range_state
));
489 /* Write the range: */
490 for (i
= 0; i
< nr_range
; i
++) {
491 set_var_mtrr_range(&var_state
, range
[i
].start
,
492 range
[i
].end
- range
[i
].start
);
495 /* Write the last range: */
496 if (var_state
.range_sizek
!= 0)
497 range_to_mtrr_with_hole(&var_state
, 0, 0);
499 num_reg
= var_state
.reg
;
500 /* Clear out the extra MTRR's: */
501 while (var_state
.reg
< num_var_ranges
) {
502 save_var_mtrr(var_state
.reg
, 0, 0, 0);
509 struct mtrr_cleanup_result
{
510 unsigned long gran_sizek
;
511 unsigned long chunk_sizek
;
512 unsigned long lose_cover_sizek
;
513 unsigned int num_reg
;
518 * gran_size: 64K, 128K, 256K, 512K, 1M, 2M, ..., 2G
519 * chunk size: gran_size, ..., 2G
520 * so we need (1+16)*8
522 #define NUM_RESULT 136
523 #define PSHIFT (PAGE_SHIFT - 10)
525 static struct mtrr_cleanup_result __initdata result
[NUM_RESULT
];
526 static unsigned long __initdata min_loss_pfn
[RANGE_NUM
];
528 static void __init
print_out_mtrr_range_state(void)
530 char start_factor
= 'K', size_factor
= 'K';
531 unsigned long start_base
, size_base
;
535 for (i
= 0; i
< num_var_ranges
; i
++) {
537 size_base
= range_state
[i
].size_pfn
<< (PAGE_SHIFT
- 10);
541 size_base
= to_size_factor(size_base
, &size_factor
),
542 start_base
= range_state
[i
].base_pfn
<< (PAGE_SHIFT
- 10);
543 start_base
= to_size_factor(start_base
, &start_factor
),
544 type
= range_state
[i
].type
;
546 pr_debug("reg %d, base: %ld%cB, range: %ld%cB, type %s\n",
547 i
, start_base
, start_factor
,
548 size_base
, size_factor
,
549 (type
== MTRR_TYPE_UNCACHABLE
) ? "UC" :
550 ((type
== MTRR_TYPE_WRPROT
) ? "WP" :
551 ((type
== MTRR_TYPE_WRBACK
) ? "WB" : "Other"))
556 static int __init
mtrr_need_cleanup(void)
561 /* Extra one for all 0: */
562 int num
[MTRR_NUM_TYPES
+ 1];
564 /* Check entries number: */
565 memset(num
, 0, sizeof(num
));
566 for (i
= 0; i
< num_var_ranges
; i
++) {
567 type
= range_state
[i
].type
;
568 size
= range_state
[i
].size_pfn
;
569 if (type
>= MTRR_NUM_TYPES
)
572 type
= MTRR_NUM_TYPES
;
576 /* Check if we got UC entries: */
577 if (!num
[MTRR_TYPE_UNCACHABLE
])
580 /* Check if we only had WB and UC */
581 if (num
[MTRR_TYPE_WRBACK
] + num
[MTRR_TYPE_UNCACHABLE
] !=
582 num_var_ranges
- num
[MTRR_NUM_TYPES
])
588 static unsigned long __initdata range_sums
;
591 mtrr_calc_range_state(u64 chunk_size
, u64 gran_size
,
592 unsigned long x_remove_base
,
593 unsigned long x_remove_size
, int i
)
596 * range_new should really be an automatic variable, but
597 * putting 4096 bytes on the stack is frowned upon, to put it
598 * mildly. It is safe to make it a static __initdata variable,
599 * since mtrr_calc_range_state is only called during init and
600 * there's no way it will call itself recursively.
602 static struct range range_new
[RANGE_NUM
] __initdata
;
603 unsigned long range_sums_new
;
607 /* Convert ranges to var ranges state: */
608 num_reg
= x86_setup_var_mtrrs(range
, nr_range
, chunk_size
, gran_size
);
610 /* We got new setting in range_state, check it: */
611 memset(range_new
, 0, sizeof(range_new
));
612 nr_range_new
= x86_get_mtrr_mem_range(range_new
, 0,
613 x_remove_base
, x_remove_size
);
614 range_sums_new
= sum_ranges(range_new
, nr_range_new
);
616 result
[i
].chunk_sizek
= chunk_size
>> 10;
617 result
[i
].gran_sizek
= gran_size
>> 10;
618 result
[i
].num_reg
= num_reg
;
620 if (range_sums
< range_sums_new
) {
621 result
[i
].lose_cover_sizek
= (range_sums_new
- range_sums
) << PSHIFT
;
624 result
[i
].lose_cover_sizek
= (range_sums
- range_sums_new
) << PSHIFT
;
627 /* Double check it: */
628 if (!result
[i
].bad
&& !result
[i
].lose_cover_sizek
) {
629 if (nr_range_new
!= nr_range
|| memcmp(range
, range_new
, sizeof(range
)))
633 if (!result
[i
].bad
&& (range_sums
- range_sums_new
< min_loss_pfn
[num_reg
]))
634 min_loss_pfn
[num_reg
] = range_sums
- range_sums_new
;
637 static void __init
mtrr_print_out_one_result(int i
)
639 unsigned long gran_base
, chunk_base
, lose_base
;
640 char gran_factor
, chunk_factor
, lose_factor
;
642 gran_base
= to_size_factor(result
[i
].gran_sizek
, &gran_factor
);
643 chunk_base
= to_size_factor(result
[i
].chunk_sizek
, &chunk_factor
);
644 lose_base
= to_size_factor(result
[i
].lose_cover_sizek
, &lose_factor
);
646 pr_info("%sgran_size: %ld%c \tchunk_size: %ld%c \t",
647 result
[i
].bad
? "*BAD*" : " ",
648 gran_base
, gran_factor
, chunk_base
, chunk_factor
);
649 pr_cont("num_reg: %d \tlose cover RAM: %s%ld%c\n",
650 result
[i
].num_reg
, result
[i
].bad
? "-" : "",
651 lose_base
, lose_factor
);
654 static int __init
mtrr_search_optimal_index(void)
660 if (nr_mtrr_spare_reg
>= num_var_ranges
)
661 nr_mtrr_spare_reg
= num_var_ranges
- 1;
664 for (i
= num_var_ranges
- nr_mtrr_spare_reg
; i
> 0; i
--) {
665 if (!min_loss_pfn
[i
])
670 if (num_reg_good
!= -1) {
671 for (i
= 0; i
< NUM_RESULT
; i
++) {
672 if (!result
[i
].bad
&&
673 result
[i
].num_reg
== num_reg_good
&&
674 !result
[i
].lose_cover_sizek
) {
684 int __init
mtrr_cleanup(unsigned address_bits
)
686 unsigned long x_remove_base
, x_remove_size
;
687 unsigned long base
, size
, def
, dummy
;
688 u64 chunk_size
, gran_size
;
693 if (!is_cpu(INTEL
) || enable_mtrr_cleanup
< 1)
696 rdmsr(MSR_MTRRdefType
, def
, dummy
);
698 if (def
!= MTRR_TYPE_UNCACHABLE
)
701 /* Get it and store it aside: */
702 memset(range_state
, 0, sizeof(range_state
));
703 for (i
= 0; i
< num_var_ranges
; i
++) {
704 mtrr_if
->get(i
, &base
, &size
, &type
);
705 range_state
[i
].base_pfn
= base
;
706 range_state
[i
].size_pfn
= size
;
707 range_state
[i
].type
= type
;
710 /* Check if we need handle it and can handle it: */
711 if (!mtrr_need_cleanup())
714 /* Print original var MTRRs at first, for debugging: */
715 pr_debug("original variable MTRRs\n");
716 print_out_mtrr_range_state();
718 memset(range
, 0, sizeof(range
));
720 x_remove_base
= 1 << (32 - PAGE_SHIFT
);
722 x_remove_size
= (mtrr_tom2
>> PAGE_SHIFT
) - x_remove_base
;
725 * [0, 1M) should always be covered by var mtrr with WB
726 * and fixed mtrrs should take effect before var mtrr for it:
728 nr_range
= add_range_with_merge(range
, RANGE_NUM
, 0, 0,
729 1ULL<<(20 - PAGE_SHIFT
));
730 /* add from var mtrr at last */
731 nr_range
= x86_get_mtrr_mem_range(range
, nr_range
,
732 x_remove_base
, x_remove_size
);
734 range_sums
= sum_ranges(range
, nr_range
);
735 pr_info("total RAM covered: %ldM\n",
736 range_sums
>> (20 - PAGE_SHIFT
));
738 if (mtrr_chunk_size
&& mtrr_gran_size
) {
740 mtrr_calc_range_state(mtrr_chunk_size
, mtrr_gran_size
,
741 x_remove_base
, x_remove_size
, i
);
743 mtrr_print_out_one_result(i
);
745 if (!result
[i
].bad
) {
746 set_var_mtrr_all(address_bits
);
747 pr_debug("New variable MTRRs\n");
748 print_out_mtrr_range_state();
751 pr_info("invalid mtrr_gran_size or mtrr_chunk_size, will find optimal one\n");
755 memset(min_loss_pfn
, 0xff, sizeof(min_loss_pfn
));
756 memset(result
, 0, sizeof(result
));
757 for (gran_size
= (1ULL<<16); gran_size
< (1ULL<<32); gran_size
<<= 1) {
759 for (chunk_size
= gran_size
; chunk_size
< (1ULL<<32);
765 mtrr_calc_range_state(chunk_size
, gran_size
,
766 x_remove_base
, x_remove_size
, i
);
768 mtrr_print_out_one_result(i
);
776 /* Try to find the optimal index: */
777 index_good
= mtrr_search_optimal_index();
779 if (index_good
!= -1) {
780 pr_info("Found optimal setting for mtrr clean up\n");
782 mtrr_print_out_one_result(i
);
784 /* Convert ranges to var ranges state: */
785 chunk_size
= result
[i
].chunk_sizek
;
787 gran_size
= result
[i
].gran_sizek
;
789 x86_setup_var_mtrrs(range
, nr_range
, chunk_size
, gran_size
);
790 set_var_mtrr_all(address_bits
);
791 pr_debug("New variable MTRRs\n");
792 print_out_mtrr_range_state();
796 for (i
= 0; i
< NUM_RESULT
; i
++)
797 mtrr_print_out_one_result(i
);
800 pr_info("mtrr_cleanup: can not find optimal value\n");
801 pr_info("please specify mtrr_gran_size/mtrr_chunk_size\n");
806 int __init
mtrr_cleanup(unsigned address_bits
)
812 static int disable_mtrr_trim
;
814 static int __init
disable_mtrr_trim_setup(char *str
)
816 disable_mtrr_trim
= 1;
819 early_param("disable_mtrr_trim", disable_mtrr_trim_setup
);
822 * Newer AMD K8s and later CPUs have a special magic MSR way to force WB
823 * for memory >4GB. Check for that here.
824 * Note this won't check if the MTRRs < 4GB where the magic bit doesn't
825 * apply to are wrong, but so far we don't know of any such case in the wild.
827 #define Tom2Enabled (1U << 21)
828 #define Tom2ForceMemTypeWB (1U << 22)
830 int __init
amd_special_default_mtrr(void)
834 if (boot_cpu_data
.x86_vendor
!= X86_VENDOR_AMD
)
836 if (boot_cpu_data
.x86
< 0xf)
838 /* In case some hypervisor doesn't pass SYSCFG through: */
839 if (rdmsr_safe(MSR_K8_SYSCFG
, &l
, &h
) < 0)
842 * Memory between 4GB and top of mem is forced WB by this magic bit.
843 * Reserved before K8RevF, but should be zero there.
845 if ((l
& (Tom2Enabled
| Tom2ForceMemTypeWB
)) ==
846 (Tom2Enabled
| Tom2ForceMemTypeWB
))
852 real_trim_memory(unsigned long start_pfn
, unsigned long limit_pfn
)
854 u64 trim_start
, trim_size
;
856 trim_start
= start_pfn
;
857 trim_start
<<= PAGE_SHIFT
;
859 trim_size
= limit_pfn
;
860 trim_size
<<= PAGE_SHIFT
;
861 trim_size
-= trim_start
;
863 return e820__range_update(trim_start
, trim_size
, E820_TYPE_RAM
, E820_TYPE_RESERVED
);
867 * mtrr_trim_uncached_memory - trim RAM not covered by MTRRs
868 * @end_pfn: ending page frame number
870 * Some buggy BIOSes don't setup the MTRRs properly for systems with certain
871 * memory configurations. This routine checks that the highest MTRR matches
872 * the end of memory, to make sure the MTRRs having a write back type cover
873 * all of the memory the kernel is intending to use. If not, it'll trim any
874 * memory off the end by adjusting end_pfn, removing it from the kernel's
875 * allocation pools, warning the user with an obnoxious message.
877 int __init
mtrr_trim_uncached_memory(unsigned long end_pfn
)
879 unsigned long i
, base
, size
, highest_pfn
= 0, def
, dummy
;
882 /* extra one for all 0 */
883 int num
[MTRR_NUM_TYPES
+ 1];
886 * Make sure we only trim uncachable memory on machines that
887 * support the Intel MTRR architecture:
889 if (!is_cpu(INTEL
) || disable_mtrr_trim
)
892 rdmsr(MSR_MTRRdefType
, def
, dummy
);
894 if (def
!= MTRR_TYPE_UNCACHABLE
)
897 /* Get it and store it aside: */
898 memset(range_state
, 0, sizeof(range_state
));
899 for (i
= 0; i
< num_var_ranges
; i
++) {
900 mtrr_if
->get(i
, &base
, &size
, &type
);
901 range_state
[i
].base_pfn
= base
;
902 range_state
[i
].size_pfn
= size
;
903 range_state
[i
].type
= type
;
906 /* Find highest cached pfn: */
907 for (i
= 0; i
< num_var_ranges
; i
++) {
908 type
= range_state
[i
].type
;
909 if (type
!= MTRR_TYPE_WRBACK
)
911 base
= range_state
[i
].base_pfn
;
912 size
= range_state
[i
].size_pfn
;
913 if (highest_pfn
< base
+ size
)
914 highest_pfn
= base
+ size
;
917 /* kvm/qemu doesn't have mtrr set right, don't trim them all: */
919 pr_info("CPU MTRRs all blank - virtualized system.\n");
923 /* Check entries number: */
924 memset(num
, 0, sizeof(num
));
925 for (i
= 0; i
< num_var_ranges
; i
++) {
926 type
= range_state
[i
].type
;
927 if (type
>= MTRR_NUM_TYPES
)
929 size
= range_state
[i
].size_pfn
;
931 type
= MTRR_NUM_TYPES
;
935 /* No entry for WB? */
936 if (!num
[MTRR_TYPE_WRBACK
])
939 /* Check if we only had WB and UC: */
940 if (num
[MTRR_TYPE_WRBACK
] + num
[MTRR_TYPE_UNCACHABLE
] !=
941 num_var_ranges
- num
[MTRR_NUM_TYPES
])
944 memset(range
, 0, sizeof(range
));
947 range
[nr_range
].start
= (1ULL<<(32 - PAGE_SHIFT
));
948 range
[nr_range
].end
= mtrr_tom2
>> PAGE_SHIFT
;
949 if (highest_pfn
< range
[nr_range
].end
)
950 highest_pfn
= range
[nr_range
].end
;
953 nr_range
= x86_get_mtrr_mem_range(range
, nr_range
, 0, 0);
955 /* Check the head: */
958 total_trim_size
+= real_trim_memory(0, range
[0].start
);
960 /* Check the holes: */
961 for (i
= 0; i
< nr_range
- 1; i
++) {
962 if (range
[i
].end
< range
[i
+1].start
)
963 total_trim_size
+= real_trim_memory(range
[i
].end
,
969 if (range
[i
].end
< end_pfn
)
970 total_trim_size
+= real_trim_memory(range
[i
].end
,
973 if (total_trim_size
) {
974 pr_warn("WARNING: BIOS bug: CPU MTRRs don't cover all of memory, losing %lluMB of RAM.\n",
975 total_trim_size
>> 20);
977 if (!changed_by_mtrr_cleanup
)
980 pr_info("update e820 for mtrr\n");
981 e820__update_table_print();