generic.c 22.9 KB
Newer Older
1 2
/*
 * This only handles 32bit MTRR on 32bit hosts. This is strictly wrong
L
Lucas De Marchi 已提交
3
 * because MTRRs can span up to 40 bits (36bits on most modern x86)
4 5 6 7
 */
#define DEBUG

#include <linux/module.h>
L
Linus Torvalds 已提交
8
#include <linux/init.h>
9
#include <linux/io.h>
L
Linus Torvalds 已提交
10
#include <linux/mm.h>
11

D
Dave Jones 已提交
12
#include <asm/processor-flags.h>
13
#include <asm/cpufeature.h>
L
Linus Torvalds 已提交
14
#include <asm/tlbflush.h>
15 16
#include <asm/mtrr.h>
#include <asm/msr.h>
17
#include <asm/pat.h>
18

L
Linus Torvalds 已提交
19 20
#include "mtrr.h"

21
struct fixed_range_block {
22 23
	int base_msr;		/* start address of an MTRR block */
	int ranges;		/* number of MTRRs in this block  */
24 25 26
};

static struct fixed_range_block fixed_range_blocks[] = {
27 28 29
	{ MSR_MTRRfix64K_00000, 1 }, /* one   64k MTRR  */
	{ MSR_MTRRfix16K_80000, 2 }, /* two   16k MTRRs */
	{ MSR_MTRRfix4K_C0000,  8 }, /* eight  4k MTRRs */
30 31 32
	{}
};

L
Linus Torvalds 已提交
33
static unsigned long smp_changes_mask;
34
static int mtrr_state_set;
35
u64 mtrr_tom2;
L
Linus Torvalds 已提交
36

37
struct mtrr_state_type mtrr_state;
S
Sheng Yang 已提交
38 39
EXPORT_SYMBOL_GPL(mtrr_state);

40
/*
41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
 * BIOS is expected to clear MtrrFixDramModEn bit, see for example
 * "BIOS and Kernel Developer's Guide for the AMD Athlon 64 and AMD
 * Opteron Processors" (26094 Rev. 3.30 February 2006), section
 * "13.2.1.2 SYSCFG Register": "The MtrrFixDramModEn bit should be set
 * to 1 during BIOS initalization of the fixed MTRRs, then cleared to
 * 0 for operation."
 */
static inline void k8_check_syscfg_dram_mod_en(void)
{
	u32 lo, hi;

	if (!((boot_cpu_data.x86_vendor == X86_VENDOR_AMD) &&
	      (boot_cpu_data.x86 >= 0x0f)))
		return;

	rdmsr(MSR_K8_SYSCFG, lo, hi);
	if (lo & K8_MTRRFIXRANGE_DRAM_MODIFY) {
58
		pr_err(FW_WARN "MTRR: CPU %u: SYSCFG[MtrrFixDramModEn]"
59 60 61 62 63 64 65
		       " not cleared by BIOS, clearing this bit\n",
		       smp_processor_id());
		lo &= ~K8_MTRRFIXRANGE_DRAM_MODIFY;
		mtrr_wrmsr(MSR_K8_SYSCFG, lo, hi);
	}
}

66 67 68 69 70 71 72 73 74 75 76 77
/* Get the size of contiguous MTRR range */
static u64 get_mtrr_size(u64 mask)
{
	u64 size;

	mask >>= PAGE_SHIFT;
	mask |= size_or_mask;
	size = -mask;
	size <<= PAGE_SHIFT;
	return size;
}

78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104
/*
 * Check and return the effective type for MTRR-MTRR type overlap.
 * Returns 1 if the effective type is UNCACHEABLE, else returns 0
 */
static int check_type_overlap(u8 *prev, u8 *curr)
{
	if (*prev == MTRR_TYPE_UNCACHABLE || *curr == MTRR_TYPE_UNCACHABLE) {
		*prev = MTRR_TYPE_UNCACHABLE;
		*curr = MTRR_TYPE_UNCACHABLE;
		return 1;
	}

	if ((*prev == MTRR_TYPE_WRBACK && *curr == MTRR_TYPE_WRTHROUGH) ||
	    (*prev == MTRR_TYPE_WRTHROUGH && *curr == MTRR_TYPE_WRBACK)) {
		*prev = MTRR_TYPE_WRTHROUGH;
		*curr = MTRR_TYPE_WRTHROUGH;
	}

	if (*prev != *curr) {
		*prev = MTRR_TYPE_UNCACHABLE;
		*curr = MTRR_TYPE_UNCACHABLE;
		return 1;
	}

	return 0;
}

105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149
/**
 * mtrr_type_lookup_fixed - look up memory type in MTRR fixed entries
 *
 * Return the MTRR fixed memory type of 'start'.
 *
 * MTRR fixed entries are divided into the following ways:
 *  0x00000 - 0x7FFFF : This range is divided into eight 64KB sub-ranges
 *  0x80000 - 0xBFFFF : This range is divided into sixteen 16KB sub-ranges
 *  0xC0000 - 0xFFFFF : This range is divided into sixty-four 4KB sub-ranges
 *
 * Return Values:
 * MTRR_TYPE_(type)  - Matched memory type
 * MTRR_TYPE_INVALID - Unmatched
 */
static u8 mtrr_type_lookup_fixed(u64 start, u64 end)
{
	int idx;

	if (start >= 0x100000)
		return MTRR_TYPE_INVALID;

	/* 0x0 - 0x7FFFF */
	if (start < 0x80000) {
		idx = 0;
		idx += (start >> 16);
		return mtrr_state.fixed_ranges[idx];
	/* 0x80000 - 0xBFFFF */
	} else if (start < 0xC0000) {
		idx = 1 * 8;
		idx += ((start - 0x80000) >> 14);
		return mtrr_state.fixed_ranges[idx];
	}

	/* 0xC0000 - 0xFFFFF */
	idx = 3 * 8;
	idx += ((start - 0xC0000) >> 12);
	return mtrr_state.fixed_ranges[idx];
}

/**
 * mtrr_type_lookup_variable - look up memory type in MTRR variable entries
 *
 * Return Value:
 * MTRR_TYPE_(type) - Matched memory type or default memory type (unmatched)
 *
150
 * Output Arguments:
151 152 153
 * repeat - Set to 1 when [start:end] spanned across MTRR range and type
 *	    returned corresponds only to [start:*partial_end].  Caller has
 *	    to lookup again for [*partial_end:end].
154 155 156 157
 *
 * uniform - Set to 1 when an MTRR covers the region uniformly, i.e. the
 *	     region is fully covered by a single MTRR entry or the default
 *	     type.
158
 */
159
static u8 mtrr_type_lookup_variable(u64 start, u64 end, u64 *partial_end,
160
				    int *repeat, u8 *uniform)
161 162 163 164 165
{
	int i;
	u64 base, mask;
	u8 prev_match, curr_match;

166
	*repeat = 0;
167
	*uniform = 1;
168

169
	/* Make end inclusive instead of exclusive */
170 171
	end--;

172
	prev_match = MTRR_TYPE_INVALID;
173
	for (i = 0; i < num_var_ranges; ++i) {
174
		unsigned short start_state, end_state, inclusive;
175 176 177 178 179 180 181 182 183 184 185

		if (!(mtrr_state.var_ranges[i].mask_lo & (1 << 11)))
			continue;

		base = (((u64)mtrr_state.var_ranges[i].base_hi) << 32) +
		       (mtrr_state.var_ranges[i].base_lo & PAGE_MASK);
		mask = (((u64)mtrr_state.var_ranges[i].mask_hi) << 32) +
		       (mtrr_state.var_ranges[i].mask_lo & PAGE_MASK);

		start_state = ((start & mask) == (base & mask));
		end_state = ((end & mask) == (base & mask));
186
		inclusive = ((start < base) && (end > base));
187

188
		if ((start_state != end_state) || inclusive) {
189 190
			/*
			 * We have start:end spanning across an MTRR.
191 192 193 194 195 196 197 198 199
			 * We split the region into either
			 *
			 * - start_state:1
			 * (start:mtrr_end)(mtrr_end:end)
			 * - end_state:1
			 * (start:mtrr_start)(mtrr_start:end)
			 * - inclusive:1
			 * (start:mtrr_start)(mtrr_start:mtrr_end)(mtrr_end:end)
			 *
200
			 * depending on kind of overlap.
201 202 203 204 205 206
			 *
			 * Return the type of the first region and a pointer
			 * to the start of next region so that caller will be
			 * advised to lookup again after having adjusted start
			 * and end.
			 *
207 208
			 * Note: This way we handle overlaps with multiple
			 * entries and the default type properly.
209 210 211 212 213 214 215 216 217 218 219 220 221
			 */
			if (start_state)
				*partial_end = base + get_mtrr_size(mask);
			else
				*partial_end = base;

			if (unlikely(*partial_end <= start)) {
				WARN_ON(1);
				*partial_end = start + PAGE_SIZE;
			}

			end = *partial_end - 1; /* end is inclusive */
			*repeat = 1;
222
			*uniform = 0;
223
		}
224

225
		if ((start & mask) != (base & mask))
226 227 228
			continue;

		curr_match = mtrr_state.var_ranges[i].base_lo & 0xff;
229
		if (prev_match == MTRR_TYPE_INVALID) {
230 231 232 233
			prev_match = curr_match;
			continue;
		}

234
		*uniform = 0;
235 236
		if (check_type_overlap(&prev_match, &curr_match))
			return curr_match;
237 238
	}

239
	if (prev_match != MTRR_TYPE_INVALID)
240 241 242 243 244
		return prev_match;

	return mtrr_state.def_type;
}

245 246 247 248 249 250
/**
 * mtrr_type_lookup - look up memory type in MTRR
 *
 * Return Values:
 * MTRR_TYPE_(type)  - The effective MTRR type for the region
 * MTRR_TYPE_INVALID - MTRR is disabled
251 252 253 254 255
 *
 * Output Argument:
 * uniform - Set to 1 when an MTRR covers the region uniformly, i.e. the
 *	     region is fully covered by a single MTRR entry or the default
 *	     type.
256
 */
257
u8 mtrr_type_lookup(u64 start, u64 end, u8 *uniform)
258
{
259
	u8 type, prev_type, is_uniform = 1, dummy;
260 261 262
	int repeat;
	u64 partial_end;

263 264 265 266 267 268 269 270 271 272 273 274
	if (!mtrr_state_set)
		return MTRR_TYPE_INVALID;

	if (!(mtrr_state.enabled & MTRR_STATE_MTRR_ENABLED))
		return MTRR_TYPE_INVALID;

	/*
	 * Look up the fixed ranges first, which take priority over
	 * the variable ranges.
	 */
	if ((start < 0x100000) &&
	    (mtrr_state.have_fixed) &&
275 276 277 278 279
	    (mtrr_state.enabled & MTRR_STATE_MTRR_FIXED_ENABLED)) {
		is_uniform = 0;
		type = mtrr_type_lookup_fixed(start, end);
		goto out;
	}
280 281 282 283 284

	/*
	 * Look up the variable ranges.  Look of multiple ranges matching
	 * this address and pick type as per MTRR precedence.
	 */
285 286
	type = mtrr_type_lookup_variable(start, end, &partial_end,
					 &repeat, &is_uniform);
287 288 289 290

	/*
	 * Common path is with repeat = 0.
	 * However, we can have cases where [start:end] spans across some
291 292
	 * MTRR ranges and/or the default type.  Do repeated lookups for
	 * that case here.
293 294 295 296
	 */
	while (repeat) {
		prev_type = type;
		start = partial_end;
297 298 299
		is_uniform = 0;
		type = mtrr_type_lookup_variable(start, end, &partial_end,
						 &repeat, &dummy);
300 301

		if (check_type_overlap(&prev_type, &type))
302
			goto out;
303 304
	}

305
	if (mtrr_tom2 && (start >= (1ULL<<32)) && (end < mtrr_tom2))
306
		type = MTRR_TYPE_WRBACK;
307

308 309
out:
	*uniform = is_uniform;
310 311 312
	return type;
}

313
/* Get the MSR pair relating to a var range */
314
static void
L
Linus Torvalds 已提交
315 316 317 318 319 320
get_mtrr_var_range(unsigned int index, struct mtrr_var_range *vr)
{
	rdmsr(MTRRphysBase_MSR(index), vr->base_lo, vr->base_hi);
	rdmsr(MTRRphysMask_MSR(index), vr->mask_lo, vr->mask_hi);
}

321
/* Fill the MSR pair relating to a var range */
322 323 324 325 326 327 328 329 330 331 332 333 334
void fill_mtrr_var_range(unsigned int index,
		u32 base_lo, u32 base_hi, u32 mask_lo, u32 mask_hi)
{
	struct mtrr_var_range *vr;

	vr = mtrr_state.var_ranges;

	vr[index].base_lo = base_lo;
	vr[index].base_hi = base_hi;
	vr[index].mask_lo = mask_lo;
	vr[index].mask_hi = mask_hi;
}

335
static void get_fixed_ranges(mtrr_type *frs)
L
Linus Torvalds 已提交
336
{
337
	unsigned int *p = (unsigned int *)frs;
L
Linus Torvalds 已提交
338 339
	int i;

340 341
	k8_check_syscfg_dram_mod_en();

342
	rdmsr(MSR_MTRRfix64K_00000, p[0], p[1]);
L
Linus Torvalds 已提交
343 344

	for (i = 0; i < 2; i++)
345
		rdmsr(MSR_MTRRfix16K_80000 + i, p[2 + i * 2], p[3 + i * 2]);
L
Linus Torvalds 已提交
346
	for (i = 0; i < 8; i++)
347
		rdmsr(MSR_MTRRfix4K_C0000 + i, p[6 + i * 2], p[7 + i * 2]);
L
Linus Torvalds 已提交
348 349
}

350 351
void mtrr_save_fixed_ranges(void *info)
{
352
	if (boot_cpu_has(X86_FEATURE_MTRR))
A
Andrew Morton 已提交
353
		get_fixed_ranges(mtrr_state.fixed_ranges);
354 355
}

356 357 358 359 360 361 362 363 364
static unsigned __initdata last_fixed_start;
static unsigned __initdata last_fixed_end;
static mtrr_type __initdata last_fixed_type;

static void __init print_fixed_last(void)
{
	if (!last_fixed_end)
		return;

365 366
	pr_debug("  %05X-%05X %s\n", last_fixed_start,
		 last_fixed_end - 1, mtrr_attrib_to_str(last_fixed_type));
367 368 369 370 371

	last_fixed_end = 0;
}

static void __init update_fixed_last(unsigned base, unsigned end,
372
				     mtrr_type type)
373 374 375 376 377 378
{
	last_fixed_start = base;
	last_fixed_end = end;
	last_fixed_type = type;
}

379 380
static void __init
print_fixed(unsigned base, unsigned step, const mtrr_type *types)
J
Jan Beulich 已提交
381 382 383
{
	unsigned i;

384 385 386 387 388 389 390 391 392 393 394 395 396
	for (i = 0; i < 8; ++i, ++types, base += step) {
		if (last_fixed_end == 0) {
			update_fixed_last(base, base + step, *types);
			continue;
		}
		if (last_fixed_end == base && last_fixed_type == *types) {
			last_fixed_end = base + step;
			continue;
		}
		/* new segments: gap or different type */
		print_fixed_last();
		update_fixed_last(base, base + step, *types);
	}
J
Jan Beulich 已提交
397 398
}

399 400 401
static void prepare_set(void);
static void post_set(void);

Y
Yinghai Lu 已提交
402 403 404 405 406
static void __init print_mtrr_state(void)
{
	unsigned int i;
	int high_width;

407 408
	pr_debug("MTRR default type: %s\n",
		 mtrr_attrib_to_str(mtrr_state.def_type));
Y
Yinghai Lu 已提交
409
	if (mtrr_state.have_fixed) {
410
		pr_debug("MTRR fixed ranges %sabled:\n",
411 412 413
			((mtrr_state.enabled & MTRR_STATE_MTRR_ENABLED) &&
			 (mtrr_state.enabled & MTRR_STATE_MTRR_FIXED_ENABLED)) ?
			 "en" : "dis");
Y
Yinghai Lu 已提交
414 415
		print_fixed(0x00000, 0x10000, mtrr_state.fixed_ranges + 0);
		for (i = 0; i < 2; ++i)
416 417
			print_fixed(0x80000 + i * 0x20000, 0x04000,
				    mtrr_state.fixed_ranges + (i + 1) * 8);
Y
Yinghai Lu 已提交
418
		for (i = 0; i < 8; ++i)
419 420
			print_fixed(0xC0000 + i * 0x08000, 0x01000,
				    mtrr_state.fixed_ranges + (i + 3) * 8);
421 422 423

		/* tail */
		print_fixed_last();
Y
Yinghai Lu 已提交
424
	}
425
	pr_debug("MTRR variable ranges %sabled:\n",
426
		 mtrr_state.enabled & MTRR_STATE_MTRR_ENABLED ? "en" : "dis");
427
	high_width = (__ffs64(size_or_mask) - (32 - PAGE_SHIFT) + 3) / 4;
428

Y
Yinghai Lu 已提交
429 430
	for (i = 0; i < num_var_ranges; ++i) {
		if (mtrr_state.var_ranges[i].mask_lo & (1 << 11))
431 432 433 434 435 436 437 438 439
			pr_debug("  %u base %0*X%05X000 mask %0*X%05X000 %s\n",
				 i,
				 high_width,
				 mtrr_state.var_ranges[i].base_hi,
				 mtrr_state.var_ranges[i].base_lo >> 12,
				 high_width,
				 mtrr_state.var_ranges[i].mask_hi,
				 mtrr_state.var_ranges[i].mask_lo >> 12,
				 mtrr_attrib_to_str(mtrr_state.var_ranges[i].base_lo & 0xff));
Y
Yinghai Lu 已提交
440
		else
441
			pr_debug("  %u disabled\n", i);
Y
Yinghai Lu 已提交
442
	}
443 444
	if (mtrr_tom2)
		pr_debug("TOM2: %016llx aka %lldM\n", mtrr_tom2, mtrr_tom2>>20);
Y
Yinghai Lu 已提交
445 446
}

447
/* Grab all of the MTRR state for this CPU into *state */
448
bool __init get_mtrr_state(void)
L
Linus Torvalds 已提交
449 450
{
	struct mtrr_var_range *vrs;
451
	unsigned long flags;
452 453
	unsigned lo, dummy;
	unsigned int i;
L
Linus Torvalds 已提交
454 455 456

	vrs = mtrr_state.var_ranges;

457
	rdmsr(MSR_MTRRcap, lo, dummy);
J
Jan Beulich 已提交
458 459
	mtrr_state.have_fixed = (lo >> 8) & 1;

L
Linus Torvalds 已提交
460 461
	for (i = 0; i < num_var_ranges; i++)
		get_mtrr_var_range(i, &vrs[i]);
J
Jan Beulich 已提交
462 463
	if (mtrr_state.have_fixed)
		get_fixed_ranges(mtrr_state.fixed_ranges);
L
Linus Torvalds 已提交
464

465
	rdmsr(MSR_MTRRdefType, lo, dummy);
L
Linus Torvalds 已提交
466 467
	mtrr_state.def_type = (lo & 0xff);
	mtrr_state.enabled = (lo & 0xc00) >> 10;
J
Jan Beulich 已提交
468

469
	if (amd_special_default_mtrr()) {
470
		unsigned low, high;
471

472
		/* TOP_MEM2 */
473
		rdmsr(MSR_K8_TOP_MEM2, low, high);
474 475 476
		mtrr_tom2 = high;
		mtrr_tom2 <<= 32;
		mtrr_tom2 |= low;
Y
Yinghai Lu 已提交
477
		mtrr_tom2 &= 0xffffff800000ULL;
478
	}
Y
Yinghai Lu 已提交
479 480 481

	print_mtrr_state();

482 483 484 485 486 487 488 489 490 491
	mtrr_state_set = 1;

	/* PAT setup for BP. We need to go through sync steps here */
	local_irq_save(flags);
	prepare_set();

	pat_init();

	post_set();
	local_irq_restore(flags);
492 493

	return !!(mtrr_state.enabled & MTRR_STATE_MTRR_ENABLED);
L
Linus Torvalds 已提交
494 495
}

496
/* Some BIOS's are messed up and don't set all MTRRs the same! */
L
Linus Torvalds 已提交
497 498 499 500 501 502 503
void __init mtrr_state_warn(void)
{
	unsigned long mask = smp_changes_mask;

	if (!mask)
		return;
	if (mask & MTRR_CHANGE_MASK_FIXED)
504
		pr_warn("mtrr: your CPUs had inconsistent fixed MTRR settings\n");
L
Linus Torvalds 已提交
505
	if (mask & MTRR_CHANGE_MASK_VARIABLE)
506
		pr_warn("mtrr: your CPUs had inconsistent variable MTRR settings\n");
L
Linus Torvalds 已提交
507
	if (mask & MTRR_CHANGE_MASK_DEFTYPE)
508
		pr_warn("mtrr: your CPUs had inconsistent MTRRdefType settings\n");
509

510 511
	pr_info("mtrr: probably your BIOS does not setup all CPUs.\n");
	pr_info("mtrr: corrected configuration.\n");
L
Linus Torvalds 已提交
512 513
}

514 515 516 517 518
/*
 * Doesn't attempt to pass an error out to MTRR users
 * because it's quite complicated in some cases and probably not
 * worth it because the best error handling is to ignore it.
 */
L
Linus Torvalds 已提交
519 520
void mtrr_wrmsr(unsigned msr, unsigned a, unsigned b)
{
521
	if (wrmsr_safe(msr, a, b) < 0) {
522
		pr_err("MTRR: CPU %u: Writing MSR %x to %x:%x failed\n",
L
Linus Torvalds 已提交
523
			smp_processor_id(), msr, a, b);
524
	}
L
Linus Torvalds 已提交
525 526
}

527
/**
528 529
 * set_fixed_range - checks & updates a fixed-range MTRR if it
 *		     differs from the value it should have
530 531 532
 * @msr: MSR address of the MTTR which should be checked and updated
 * @changed: pointer which indicates whether the MTRR needed to be changed
 * @msrwords: pointer to the MSR values which the MSR should have
533
 */
534
static void set_fixed_range(int msr, bool *changed, unsigned int *msrwords)
535 536 537 538 539 540 541
{
	unsigned lo, hi;

	rdmsr(msr, lo, hi);

	if (lo != msrwords[0] || hi != msrwords[1]) {
		mtrr_wrmsr(msr, msrwords[0], msrwords[1]);
542
		*changed = true;
543 544 545
	}
}

546 547 548 549 550 551 552 553
/**
 * generic_get_free_region - Get a free MTRR.
 * @base: The starting (base) address of the region.
 * @size: The size (in bytes) of the region.
 * @replace_reg: mtrr index to be replaced; set to invalid value if none.
 *
 * Returns: The index of the region on success, else negative on error.
 */
554 555
int
generic_get_free_region(unsigned long base, unsigned long size, int replace_reg)
L
Linus Torvalds 已提交
556
{
J
Jan Beulich 已提交
557
	unsigned long lbase, lsize;
558 559
	mtrr_type ltype;
	int i, max;
L
Linus Torvalds 已提交
560 561

	max = num_var_ranges;
J
Jan Beulich 已提交
562 563
	if (replace_reg >= 0 && replace_reg < max)
		return replace_reg;
564

L
Linus Torvalds 已提交
565 566 567 568 569
	for (i = 0; i < max; ++i) {
		mtrr_if->get(i, &lbase, &lsize, &ltype);
		if (lsize == 0)
			return i;
	}
570

L
Linus Torvalds 已提交
571 572 573
	return -ENOSPC;
}

A
Adrian Bunk 已提交
574
static void generic_get_mtrr(unsigned int reg, unsigned long *base,
J
Jan Beulich 已提交
575
			     unsigned long *size, mtrr_type *type)
L
Linus Torvalds 已提交
576
{
577 578 579
	u32 mask_lo, mask_hi, base_lo, base_hi;
	unsigned int hi;
	u64 tmp, mask;
L
Linus Torvalds 已提交
580

Y
Yinghai Lu 已提交
581 582 583 584
	/*
	 * get_mtrr doesn't need to update mtrr_state, also it could be called
	 * from any cpu, so try to print it out directly.
	 */
585
	get_cpu();
586

L
Linus Torvalds 已提交
587
	rdmsr(MTRRphysMask_MSR(reg), mask_lo, mask_hi);
Y
Yinghai Lu 已提交
588

L
Linus Torvalds 已提交
589
	if ((mask_lo & 0x800) == 0) {
590
		/*  Invalid (i.e. free) range */
L
Linus Torvalds 已提交
591 592 593
		*base = 0;
		*size = 0;
		*type = 0;
594
		goto out_put_cpu;
L
Linus Torvalds 已提交
595 596 597 598
	}

	rdmsr(MTRRphysBase_MSR(reg), base_lo, base_hi);

599
	/* Work out the shifted address mask: */
600 601
	tmp = (u64)mask_hi << (32 - PAGE_SHIFT) | mask_lo >> PAGE_SHIFT;
	mask = size_or_mask | tmp;
602 603

	/* Expand tmp with high bits to all 1s: */
604
	hi = fls64(tmp);
Y
Yinghai Lu 已提交
605
	if (hi > 0) {
606
		tmp |= ~((1ULL<<(hi - 1)) - 1);
Y
Yinghai Lu 已提交
607

608
		if (tmp != mask) {
609
			pr_warn("mtrr: your BIOS has configured an incorrect mask, fixing it.\n");
610
			add_taint(TAINT_FIRMWARE_WORKAROUND, LOCKDEP_STILL_OK);
611
			mask = tmp;
Y
Yinghai Lu 已提交
612 613
		}
	}
L
Linus Torvalds 已提交
614

615 616 617 618
	/*
	 * This works correctly if size is a power of two, i.e. a
	 * contiguous range:
	 */
619 620
	*size = -mask;
	*base = (u64)base_hi << (32 - PAGE_SHIFT) | base_lo >> PAGE_SHIFT;
L
Linus Torvalds 已提交
621
	*type = base_lo & 0xff;
Y
Yinghai Lu 已提交
622

623 624
out_put_cpu:
	put_cpu();
L
Linus Torvalds 已提交
625 626
}

627
/**
628 629
 * set_fixed_ranges - checks & updates the fixed-range MTRRs if they
 *		      differ from the saved set
630
 * @frs: pointer to fixed-range MTRR values, saved by get_fixed_ranges()
631
 */
632
static int set_fixed_ranges(mtrr_type *frs)
L
Linus Torvalds 已提交
633
{
634
	unsigned long long *saved = (unsigned long long *)frs;
635
	bool changed = false;
636
	int block = -1, range;
L
Linus Torvalds 已提交
637

638 639
	k8_check_syscfg_dram_mod_en();

640 641 642 643 644
	while (fixed_range_blocks[++block].ranges) {
		for (range = 0; range < fixed_range_blocks[block].ranges; range++)
			set_fixed_range(fixed_range_blocks[block].base_msr + range,
					&changed, (unsigned int *)saved++);
	}
L
Linus Torvalds 已提交
645 646 647 648

	return changed;
}

649 650 651 652
/*
 * Set the MSR pair relating to a var range.
 * Returns true if changes are made.
 */
653
static bool set_mtrr_var_ranges(unsigned int index, struct mtrr_var_range *vr)
L
Linus Torvalds 已提交
654 655
{
	unsigned int lo, hi;
656
	bool changed = false;
L
Linus Torvalds 已提交
657 658 659

	rdmsr(MTRRphysBase_MSR(index), lo, hi);
	if ((vr->base_lo & 0xfffff0ffUL) != (lo & 0xfffff0ffUL)
660 661
	    || (vr->base_hi & (size_and_mask >> (32 - PAGE_SHIFT))) !=
		(hi & (size_and_mask >> (32 - PAGE_SHIFT)))) {
662

L
Linus Torvalds 已提交
663
		mtrr_wrmsr(MTRRphysBase_MSR(index), vr->base_lo, vr->base_hi);
664
		changed = true;
L
Linus Torvalds 已提交
665 666 667 668 669
	}

	rdmsr(MTRRphysMask_MSR(index), lo, hi);

	if ((vr->mask_lo & 0xfffff800UL) != (lo & 0xfffff800UL)
670 671
	    || (vr->mask_hi & (size_and_mask >> (32 - PAGE_SHIFT))) !=
		(hi & (size_and_mask >> (32 - PAGE_SHIFT)))) {
L
Linus Torvalds 已提交
672
		mtrr_wrmsr(MTRRphysMask_MSR(index), vr->mask_lo, vr->mask_hi);
673
		changed = true;
L
Linus Torvalds 已提交
674 675 676 677
	}
	return changed;
}

J
Jan Beulich 已提交
678 679
static u32 deftype_lo, deftype_hi;

680 681 682 683 684 685
/**
 * set_mtrr_state - Set the MTRR state for this CPU.
 *
 * NOTE: The CPU must already be in a safe state for MTRR changes.
 * RETURNS: 0 if no changes made, else a mask indicating what was changed.
 */
J
Jan Beulich 已提交
686
static unsigned long set_mtrr_state(void)
L
Linus Torvalds 已提交
687 688
{
	unsigned long change_mask = 0;
689
	unsigned int i;
L
Linus Torvalds 已提交
690

691
	for (i = 0; i < num_var_ranges; i++) {
L
Linus Torvalds 已提交
692 693
		if (set_mtrr_var_ranges(i, &mtrr_state.var_ranges[i]))
			change_mask |= MTRR_CHANGE_MASK_VARIABLE;
694
	}
L
Linus Torvalds 已提交
695

J
Jan Beulich 已提交
696
	if (mtrr_state.have_fixed && set_fixed_ranges(mtrr_state.fixed_ranges))
L
Linus Torvalds 已提交
697 698
		change_mask |= MTRR_CHANGE_MASK_FIXED;

699 700 701 702
	/*
	 * Set_mtrr_restore restores the old value of MTRRdefType,
	 * so to set it we fiddle with the saved value:
	 */
L
Linus Torvalds 已提交
703 704
	if ((deftype_lo & 0xff) != mtrr_state.def_type
	    || ((deftype_lo & 0xc00) >> 10) != mtrr_state.enabled) {
705 706 707

		deftype_lo = (deftype_lo & ~0xcff) | mtrr_state.def_type |
			     (mtrr_state.enabled << 10);
L
Linus Torvalds 已提交
708 709 710 711 712 713 714
		change_mask |= MTRR_CHANGE_MASK_DEFTYPE;
	}

	return change_mask;
}


715
static unsigned long cr4;
716
static DEFINE_RAW_SPINLOCK(set_atomicity_lock);
L
Linus Torvalds 已提交
717 718

/*
719 720 721 722 723
 * Since we are disabling the cache don't allow any interrupts,
 * they would run extremely slow and would only increase the pain.
 *
 * The caller must ensure that local interrupts are disabled and
 * are reenabled after post_set() has been called.
L
Linus Torvalds 已提交
724
 */
725
static void prepare_set(void) __acquires(set_atomicity_lock)
L
Linus Torvalds 已提交
726 727 728
{
	unsigned long cr0;

729 730 731 732 733 734
	/*
	 * Note that this is not ideal
	 * since the cache is only flushed/disabled for this CPU while the
	 * MTRRs are changed, but changing this requires more invasive
	 * changes to the way the kernel boots
	 */
L
Linus Torvalds 已提交
735

736
	raw_spin_lock(&set_atomicity_lock);
L
Linus Torvalds 已提交
737

738
	/* Enter the no-fill (CD=1, NW=0) cache mode and flush caches. */
D
Dave Jones 已提交
739
	cr0 = read_cr0() | X86_CR0_CD;
L
Linus Torvalds 已提交
740 741 742
	write_cr0(cr0);
	wbinvd();

743 744
	/* Save value of CR4 and clear Page Global Enable (bit 7) */
	if (cpu_has_pge) {
745 746
		cr4 = __read_cr4();
		__write_cr4(cr4 & ~X86_CR4_PGE);
L
Linus Torvalds 已提交
747 748 749
	}

	/* Flush all TLBs via a mov %cr3, %reg; mov %reg, %cr3 */
750
	count_vm_tlb_event(NR_TLB_LOCAL_FLUSH_ALL);
L
Linus Torvalds 已提交
751 752
	__flush_tlb();

753
	/* Save MTRR state */
754
	rdmsr(MSR_MTRRdefType, deftype_lo, deftype_hi);
L
Linus Torvalds 已提交
755

756
	/* Disable MTRRs, and set the default type to uncached */
757
	mtrr_wrmsr(MSR_MTRRdefType, deftype_lo & ~0xcff, deftype_hi);
758
	wbinvd();
L
Linus Torvalds 已提交
759 760
}

761
static void post_set(void) __releases(set_atomicity_lock)
L
Linus Torvalds 已提交
762
{
763
	/* Flush TLBs (no need to flush caches - they are disabled) */
764
	count_vm_tlb_event(NR_TLB_LOCAL_FLUSH_ALL);
L
Linus Torvalds 已提交
765 766 767
	__flush_tlb();

	/* Intel (P6) standard MTRRs */
768
	mtrr_wrmsr(MSR_MTRRdefType, deftype_lo, deftype_hi);
769 770

	/* Enable caches */
771
	write_cr0(read_cr0() & ~X86_CR0_CD);
L
Linus Torvalds 已提交
772

773 774
	/* Restore value of CR4 */
	if (cpu_has_pge)
775
		__write_cr4(cr4);
776
	raw_spin_unlock(&set_atomicity_lock);
L
Linus Torvalds 已提交
777 778 779 780 781 782 783 784 785 786 787
}

static void generic_set_all(void)
{
	unsigned long mask, count;
	unsigned long flags;

	local_irq_save(flags);
	prepare_set();

	/* Actually set the state */
J
Jan Beulich 已提交
788
	mask = set_mtrr_state();
L
Linus Torvalds 已提交
789

790 791 792
	/* also set PAT */
	pat_init();

L
Linus Torvalds 已提交
793 794 795
	post_set();
	local_irq_restore(flags);

796
	/* Use the atomic bitops to update the global mask */
L
Linus Torvalds 已提交
797 798 799 800 801
	for (count = 0; count < sizeof mask * 8; ++count) {
		if (mask & 0x01)
			set_bit(count, &smp_changes_mask);
		mask >>= 1;
	}
802

L
Linus Torvalds 已提交
803 804
}

805 806 807 808 809 810 811 812 813 814
/**
 * generic_set_mtrr - set variable MTRR register on the local CPU.
 *
 * @reg: The register to set.
 * @base: The base address of the region.
 * @size: The size of the region. If this is 0 the region is disabled.
 * @type: The type of the region.
 *
 * Returns nothing.
 */
L
Linus Torvalds 已提交
815 816 817 818
static void generic_set_mtrr(unsigned int reg, unsigned long base,
			     unsigned long size, mtrr_type type)
{
	unsigned long flags;
S
Shaohua Li 已提交
819 820 821
	struct mtrr_var_range *vr;

	vr = &mtrr_state.var_ranges[reg];
L
Linus Torvalds 已提交
822 823 824 825 826

	local_irq_save(flags);
	prepare_set();

	if (size == 0) {
827 828 829 830
		/*
		 * The invalid bit is kept in the mask, so we simply
		 * clear the relevant mask register to disable a range.
		 */
L
Linus Torvalds 已提交
831
		mtrr_wrmsr(MTRRphysMask_MSR(reg), 0, 0);
S
Shaohua Li 已提交
832
		memset(vr, 0, sizeof(struct mtrr_var_range));
L
Linus Torvalds 已提交
833
	} else {
S
Shaohua Li 已提交
834 835 836 837 838 839 840
		vr->base_lo = base << PAGE_SHIFT | type;
		vr->base_hi = (base & size_and_mask) >> (32 - PAGE_SHIFT);
		vr->mask_lo = -size << PAGE_SHIFT | 0x800;
		vr->mask_hi = (-size & size_and_mask) >> (32 - PAGE_SHIFT);

		mtrr_wrmsr(MTRRphysBase_MSR(reg), vr->base_lo, vr->base_hi);
		mtrr_wrmsr(MTRRphysMask_MSR(reg), vr->mask_lo, vr->mask_hi);
L
Linus Torvalds 已提交
841 842 843 844 845 846
	}

	post_set();
	local_irq_restore(flags);
}

847 848
int generic_validate_add_page(unsigned long base, unsigned long size,
			      unsigned int type)
L
Linus Torvalds 已提交
849 850 851
{
	unsigned long lbase, last;

852 853 854 855
	/*
	 * For Intel PPro stepping <= 7
	 * must be 4 MiB aligned and not touch 0x70000000 -> 0x7003FFFF
	 */
L
Linus Torvalds 已提交
856 857 858 859
	if (is_cpu(INTEL) && boot_cpu_data.x86 == 6 &&
	    boot_cpu_data.x86_model == 1 &&
	    boot_cpu_data.x86_mask <= 7) {
		if (base & ((1 << (22 - PAGE_SHIFT)) - 1)) {
860
			pr_warn("mtrr: base(0x%lx000) is not 4 MiB aligned\n", base);
L
Linus Torvalds 已提交
861 862
			return -EINVAL;
		}
863
		if (!(base + size < 0x70000 || base > 0x7003F) &&
L
Linus Torvalds 已提交
864 865
		    (type == MTRR_TYPE_WRCOMB
		     || type == MTRR_TYPE_WRBACK)) {
866
			pr_warn("mtrr: writable mtrr between 0x70000000 and 0x7003FFFF may hang the CPU.\n");
L
Linus Torvalds 已提交
867 868 869 870
			return -EINVAL;
		}
	}

871 872 873 874
	/*
	 * Check upper bits of base and last are equal and lower bits are 0
	 * for base and 1 for last
	 */
L
Linus Torvalds 已提交
875 876
	last = base + size - 1;
	for (lbase = base; !(lbase & 1) && (last & 1);
877 878
	     lbase = lbase >> 1, last = last >> 1)
		;
L
Linus Torvalds 已提交
879
	if (lbase != last) {
880
		pr_warn("mtrr: base(0x%lx000) is not aligned on a size(0x%lx000) boundary\n", base, size);
L
Linus Torvalds 已提交
881 882 883 884 885 886 887 888
		return -EINVAL;
	}
	return 0;
}

static int generic_have_wrcomb(void)
{
	unsigned long config, dummy;
889
	rdmsr(MSR_MTRRcap, config, dummy);
890
	return config & (1 << 10);
L
Linus Torvalds 已提交
891 892 893 894 895 896 897
}

int positive_have_wrcomb(void)
{
	return 1;
}

898 899
/*
 * Generic structure...
L
Linus Torvalds 已提交
900
 */
901
const struct mtrr_ops generic_mtrr_ops = {
902 903 904 905 906 907 908
	.use_intel_if		= 1,
	.set_all		= generic_set_all,
	.get			= generic_get_mtrr,
	.get_free_region	= generic_get_free_region,
	.set			= generic_set_mtrr,
	.validate_add_page	= generic_validate_add_page,
	.have_wrcomb		= generic_have_wrcomb,
L
Linus Torvalds 已提交
909
};