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); } if (debug_print) { printk(KERN_DEBUG "After WB checking\n"); for (i = 0; i < nr_range; i++) printk(KERN_DEBUG "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 & 1)) { /* Var MTRR contains UC entry below 1M? Skip it: */ printk(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); if (debug_print) { printk(KERN_DEBUG "After UC checking\n"); for (i = 0; i < RANGE_NUM; i++) { if (!range[i].end) continue; printk(KERN_DEBUG "MTRR MAP PFN: %016llx - %016llx\n", range[i].start, range[i].end); } } /* sort the ranges */ nr_range = clean_sort_range(range, RANGE_NUM); if (debug_print) { printk(KERN_DEBUG "After sorting\n"); for (i = 0; i < nr_range; i++) printk(KERN_DEBUG "MTRR MAP PFN: %016llx - %016llx\n", range[i].start, range[i].end); } return nr_range; }
static int __init x86_get_mtrr_mem_range(struct res_range *range, int nr_range, unsigned long extra_remove_base, unsigned long extra_remove_size) { unsigned long i, base, size; mtrr_type type; 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, nr_range, base, base + size - 1); } if (debug_print) { printk(KERN_DEBUG "After WB checking\n"); for (i = 0; i < nr_range; i++) printk(KERN_DEBUG "MTRR MAP PFN: %016lx - %016lx\n", range[i].start, range[i].end + 1); } /* 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; subtract_range(range, base, base + size - 1); } if (extra_remove_size) subtract_range(range, extra_remove_base, extra_remove_base + extra_remove_size - 1); /* get new range num */ nr_range = 0; for (i = 0; i < RANGE_NUM; i++) { if (!range[i].end) continue; nr_range++; } if (debug_print) { printk(KERN_DEBUG "After UC checking\n"); for (i = 0; i < nr_range; i++) printk(KERN_DEBUG "MTRR MAP PFN: %016lx - %016lx\n", range[i].start, range[i].end + 1); } /* sort the ranges */ sort(range, nr_range, sizeof(struct res_range), cmp_range, NULL); if (debug_print) { printk(KERN_DEBUG "After sorting\n"); for (i = 0; i < nr_range; i++) printk(KERN_DEBUG "MTRR MAP PFN: %016lx - %016lx\n", range[i].start, range[i].end + 1); } /* clear those is not used */ for (i = nr_range; i < RANGE_NUM; i++) memset(&range[i], 0, sizeof(range[i])); return nr_range; }
/* WB를 *range 배열에 merge하면서 정리해 넣고 * UC와 WP는 이 range 영역에서 빼고 정렬한다. */ 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; /* WB영역중 중첩되는 range를 합친다. */ for (i = 0; i < num_var_ranges; i++) { type = range_state[i].type; if (type != MTRR_TYPE_WRBACK) continue; /* WB가 아니면 패스 */ base = range_state[i].base_pfn; size = range_state[i].size_pfn; /* WB영역중에서 중첩되는 부분을 합쳐서 range 배열에 넣는다. */ nr_range = add_range_with_merge(range, RANGE_NUM, nr_range, base, base + size); } if (debug_print) { printk(KERN_DEBUG "After WB checking\n"); for (i = 0; i < nr_range; i++) printk(KERN_DEBUG "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; /* UC나 WP가 아니면 패스 */ 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; /* base는 4KB 단위다. 256 이하, 즉 1M 이하이면서 * fixed(1M) mtrr가 있으면서 enable인 예외상황을 가리킨다. * 즉 fixed mtrr과 variable mtrr이 중첩되서 생기는 버그 경고이다. */ if (base < (1<<(20-PAGE_SHIFT)) && mtrr_state.have_fixed && (mtrr_state.enabled & 1)) { /* Var MTRR contains UC entry below 1M? Skip it: */ printk(BIOS_BUG_MSG, i); if (base + size <= (1<<(20-PAGE_SHIFT))) continue; size -= (1<<(20-PAGE_SHIFT)) - base; base = 1<<(20-PAGE_SHIFT); } /* WB가 모인 range에서 UC, WP영역과 겹치는 부분을 뺀다. */ subtract_range(range, RANGE_NUM, base, base + size); } if (extra_remove_size) /* 인자로 들어온 4G 넘는 영역을 빼준다. */ subtract_range(range, RANGE_NUM, extra_remove_base, extra_remove_base + extra_remove_size); if (debug_print) { printk(KERN_DEBUG "After UC checking\n"); for (i = 0; i < RANGE_NUM; i++) { if (!range[i].end) continue; printk(KERN_DEBUG "MTRR MAP PFN: %016llx - %016llx\n", range[i].start, range[i].end); } } /* sort the ranges */ nr_range = clean_sort_range(range, RANGE_NUM); /* 정렬 */ if (debug_print) { printk(KERN_DEBUG "After sorting\n"); for (i = 0; i < nr_range; i++) printk(KERN_DEBUG "MTRR MAP PFN: %016llx - %016llx\n", range[i].start, range[i].end); } return nr_range; }
static int __init x86_get_mtrr_mem_range(struct res_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, nr_range, base, base + size - 1); } if (debug_print) { printk(KERN_DEBUG "After WB checking\n"); for (i = 0; i < nr_range; i++) printk(KERN_DEBUG "MTRR MAP PFN: %016lx - %016lx\n", range[i].start, range[i].end + 1); } 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 & 1)) { printk(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, base, base + size - 1); } if (extra_remove_size) subtract_range(range, extra_remove_base, extra_remove_base + extra_remove_size - 1); nr_range = 0; for (i = 0; i < RANGE_NUM; i++) { if (!range[i].end) continue; nr_range++; } if (debug_print) { printk(KERN_DEBUG "After UC checking\n"); for (i = 0; i < nr_range; i++) printk(KERN_DEBUG "MTRR MAP PFN: %016lx - %016lx\n", range[i].start, range[i].end + 1); } sort(range, nr_range, sizeof(struct res_range), cmp_range, NULL); if (debug_print) { printk(KERN_DEBUG "After sorting\n"); for (i = 0; i < nr_range; i++) printk(KERN_DEBUG "MTRR MAP PFN: %016lx - %016lx\n", range[i].start, range[i].end + 1); } for (i = nr_range; i < RANGE_NUM; i++) memset(&range[i], 0, sizeof(range[i])); return nr_range; }