arch/x86/kernel/cpu/mtrr/cleanup.c

Source file repositories/reference/linux-study-clean/arch/x86/kernel/cpu/mtrr/cleanup.c

File Facts

System
Linux kernel
Corpus path
arch/x86/kernel/cpu/mtrr/cleanup.c
Extension
.c
Size
24537 bytes
Lines
969
Domain
Architecture Layer
Bucket
arch/x86
Inferred role
Architecture Layer: implementation source
Status
source implementation candidate

Why This File Exists

CPU and platform-specific kernel glue: boot entry, traps, syscall entry, interrupts, page tables, context switch, and low-level barriers.

Dependency Surface

Detected Declarations

Annotated Snippet

struct var_mtrr_range_state {
	unsigned long	base_pfn;
	unsigned long	size_pfn;
	mtrr_type	type;
};

struct var_mtrr_state {
	unsigned long	range_startk;
	unsigned long	range_sizek;
	unsigned long	chunk_sizek;
	unsigned long	gran_sizek;
	unsigned int	reg;
};

/* Should be related to MTRR_VAR_RANGES nums */
#define RANGE_NUM				256

static struct range __initdata		range[RANGE_NUM];
static int __initdata				nr_range;

static struct var_mtrr_range_state __initdata	range_state[RANGE_NUM];

#define BIOS_BUG_MSG \
	"WARNING: BIOS bug: VAR MTRR %d contains strange UC entry under 1M, check with your system vendor!\n"

static int __init
x86_get_mtrr_mem_range(struct range *range, int nr_range,
		       unsigned long extra_remove_base,
		       unsigned long extra_remove_size)
{
	unsigned long base, size;
	mtrr_type type;
	int i;

	for (i = 0; i < num_var_ranges; i++) {
		type = range_state[i].type;
		if (type != MTRR_TYPE_WRBACK)
			continue;
		base = range_state[i].base_pfn;
		size = range_state[i].size_pfn;
		nr_range = add_range_with_merge(range, RANGE_NUM, nr_range,
						base, base + size);
	}

	Dprintk("After WB checking\n");
	for (i = 0; i < nr_range; i++)
		Dprintk("MTRR MAP PFN: %016llx - %016llx\n",
			 range[i].start, range[i].end);

	/* Take out UC ranges: */
	for (i = 0; i < num_var_ranges; i++) {
		type = range_state[i].type;
		if (type != MTRR_TYPE_UNCACHABLE &&
		    type != MTRR_TYPE_WRPROT)
			continue;
		size = range_state[i].size_pfn;
		if (!size)
			continue;
		base = range_state[i].base_pfn;
		if (base < (1<<(20-PAGE_SHIFT)) && mtrr_state.have_fixed &&
		    (mtrr_state.enabled & MTRR_STATE_MTRR_ENABLED) &&
		    (mtrr_state.enabled & MTRR_STATE_MTRR_FIXED_ENABLED)) {
			/* Var MTRR contains UC entry below 1M? Skip it: */
			pr_warn(BIOS_BUG_MSG, i);
			if (base + size <= (1<<(20-PAGE_SHIFT)))
				continue;
			size -= (1<<(20-PAGE_SHIFT)) - base;
			base = 1<<(20-PAGE_SHIFT);
		}
		subtract_range(range, RANGE_NUM, base, base + size);
	}
	if (extra_remove_size)
		subtract_range(range, RANGE_NUM, extra_remove_base,
				 extra_remove_base + extra_remove_size);

	Dprintk("After UC checking\n");
	for (i = 0; i < RANGE_NUM; i++) {
		if (!range[i].end)
			continue;

		Dprintk("MTRR MAP PFN: %016llx - %016llx\n",
			 range[i].start, range[i].end);
	}

	/* sort the ranges */
	nr_range = clean_sort_range(range, RANGE_NUM);

	Dprintk("After sorting\n");
	for (i = 0; i < nr_range; i++)
		Dprintk("MTRR MAP PFN: %016llx - %016llx\n",

Annotation

Implementation Notes