static void ram_probe(void) { dprintf(3, "Find memory size\n"); if (CONFIG_COREBOOT) { coreboot_setup(); } else if (usingXen()) { xen_setup(); } else { // On emulators, get memory size from nvram. u32 rs = ((inb_cmos(CMOS_MEM_EXTMEM2_LOW) << 16) | (inb_cmos(CMOS_MEM_EXTMEM2_HIGH) << 24)); if (rs) rs += 16 * 1024 * 1024; else rs = (((inb_cmos(CMOS_MEM_EXTMEM_LOW) << 10) | (inb_cmos(CMOS_MEM_EXTMEM_HIGH) << 18)) + 1 * 1024 * 1024); RamSize = rs; add_e820(0, rs, E820_RAM); // Check for memory over 4Gig u64 high = ((inb_cmos(CMOS_MEM_HIGHMEM_LOW) << 16) | ((u32)inb_cmos(CMOS_MEM_HIGHMEM_MID) << 24) | ((u64)inb_cmos(CMOS_MEM_HIGHMEM_HIGH) << 32)); RamSizeOver4G = high; add_e820(0x100000000ull, high, E820_RAM); /* reserve 256KB BIOS area at the end of 4 GB */ add_e820(0xfffc0000, 256*1024, E820_RESERVED); } // Don't declare any memory between 0xa0000 and 0x100000 add_e820(BUILD_LOWRAM_END, BUILD_BIOS_ADDR-BUILD_LOWRAM_END, E820_HOLE); // Mark known areas as reserved. add_e820(BUILD_BIOS_ADDR, BUILD_BIOS_SIZE, E820_RESERVED); u32 count = qemu_cfg_e820_entries(); if (count) { struct e820_reservation entry; int i; for (i = 0; i < count; i++) { qemu_cfg_e820_load_next(&entry); add_e820(entry.address, entry.length, entry.type); } } else if (kvm_para_available()) { // Backwards compatibility - provide hard coded range. // 4 pages before the bios, 3 pages for vmx tss pages, the // other page for EPT real mode pagetable add_e820(0xfffbc000, 4*4096, E820_RESERVED); } dprintf(1, "Ram Size=0x%08x (0x%016llx high)\n", RamSize, RamSizeOver4G); }
static void init_bios_tables(void) { if (CONFIG_COREBOOT) { coreboot_copy_biostable(); return; } if (usingXen()) { xen_copy_biostables(); return; } create_pirtable(); mptable_init(); smbios_init(); acpi_bios_init(); }
/* Fill in hypercall transfer pages. */ void xen_init_hypercalls(void) { u32 eax, ebx, ecx, edx; xen_extraversion_t extraversion; unsigned long i; if (!usingXen()) return; cpuid(xen_cpuid_base + 2, &eax, &ebx, &ecx, &edx); xen_hypercall_page = (unsigned long)memalign_high(PAGE_SIZE, eax*PAGE_SIZE); if (!xen_hypercall_page) panic("unable to allocate Xen hypercall page\n"); dprintf(1, "Allocated Xen hypercall page at %lx\n", xen_hypercall_page); for ( i = 0; i < eax; i++ ) wrmsr(ebx, xen_hypercall_page + (i << 12) + i); /* Print version information. */ cpuid(xen_cpuid_base + 1, &eax, &ebx, &ecx, &edx); hypercall_xen_version(XENVER_extraversion, extraversion); dprintf(1, "Detected Xen v%u.%u%s\n", eax >> 16, eax & 0xffff, extraversion); }
void mtrr_setup(void) { if (!CONFIG_MTRR_INIT || CONFIG_COREBOOT || usingXen()) return; u32 eax, ebx, ecx, edx, cpuid_features; cpuid(1, &eax, &ebx, &ecx, &cpuid_features); if (!(cpuid_features & CPUID_MTRR)) return; if (!(cpuid_features & CPUID_MSR)) return; dprintf(3, "init mtrr\n"); u32 mtrr_cap = rdmsr(MSR_MTRRcap); int vcnt = mtrr_cap & 0xff; int fix = mtrr_cap & 0x100; if (!vcnt || !fix) return; // Disable MTRRs wrmsr_smp(MSR_MTRRdefType, 0); // Set fixed MTRRs union u64b { u8 valb[8]; u64 val; } u; u.val = 0; int i; for (i = 0; i < 8; i++) if (RamSize >= 65536 * (i + 1)) u.valb[i] = MTRR_MEMTYPE_WB; wrmsr_smp(MSR_MTRRfix64K_00000, u.val); u.val = 0; for (i = 0; i < 8; i++) if (RamSize >= 0x80000 + 16384 * (i + 1)) u.valb[i] = MTRR_MEMTYPE_WB; wrmsr_smp(MSR_MTRRfix16K_80000, u.val); wrmsr_smp(MSR_MTRRfix16K_A0000, 0); // 0xA0000-0xC0000 is uncached int j; for (j = 0; j < 8; j++) { u.val = 0; for (i = 0; i < 8; i++) if (RamSize >= 0xC0000 + j * 0x8000 + 4096 * (i + 1)) u.valb[i] = MTRR_MEMTYPE_WP; wrmsr_smp(MSR_MTRRfix4K_C0000 + j, u.val); } // Set variable MTRRs int phys_bits = 36; cpuid(0x80000000u, &eax, &ebx, &ecx, &edx); if (eax >= 0x80000008) { /* Get physical bits from leaf 0x80000008 (if available) */ cpuid(0x80000008u, &eax, &ebx, &ecx, &edx); phys_bits = eax & 0xff; } u64 phys_mask = ((1ull << phys_bits) - 1); for (i=0; i<vcnt; i++) { wrmsr_smp(MTRRphysBase_MSR(i), 0); wrmsr_smp(MTRRphysMask_MSR(i), 0); } /* Mark 3.5-4GB as UC, anything not specified defaults to WB */ wrmsr_smp(MTRRphysBase_MSR(0), BUILD_MAX_HIGHMEM | MTRR_MEMTYPE_UC); wrmsr_smp(MTRRphysMask_MSR(0) , (-((1ull<<32)-BUILD_MAX_HIGHMEM) & phys_mask) | 0x800); // Enable fixed and variable MTRRs; set default type. wrmsr_smp(MSR_MTRRdefType, 0xc00 | MTRR_MEMTYPE_WB); }