[coreboot-gerrit] Change in coreboot[master]: [WIP]x86|mb/emulation/qemu-q35: 64bit ramstage support
Patrick Rudolph (Code Review)
gerrit at coreboot.org
Sat Nov 17 11:30:14 CET 2018
Hello Patrick Rudolph,
I'd like you to do a code review. Please visit
https://review.coreboot.org/29667
to review the following change.
Change subject: [WIP]x86|mb/emulation/qemu-q35: 64bit ramstage support
......................................................................
[WIP]x86|mb/emulation/qemu-q35: 64bit ramstage support
* Add mmu.c ported from arm64
* Generate 4 level page tables for long mode
* Enable long mode
* Activate long mode in c_start.S
* Some fixes for 64bit
* Add support for 64bit rmodule
Non working:
* Loading gdt and setting %ds
Signed-off-by: Patrick Rudolph <siro at das-labor.org>
Change-Id: If2f02a95b2f91ab51043d4e81054354f4a6eb5d5
---
M src/arch/x86/Kconfig
M src/arch/x86/Makefile.inc
M src/arch/x86/boot.c
M src/arch/x86/c_start.S
M src/arch/x86/exception.c
A src/arch/x86/include/arch/mmu.h
A src/arch/x86/mmu.c
M src/commonlib/include/commonlib/cbmem_id.h
M src/cpu/qemu-x86/Kconfig
M src/cpu/x86/Makefile.inc
M src/lib/timestamp.c
M src/mainboard/emulation/qemu-q35/Kconfig
M src/mainboard/emulation/qemu-q35/Makefile.inc
M src/mainboard/emulation/qemu-q35/romstage.c
M src/southbridge/intel/common/smi.c
M src/southbridge/intel/i82801ix/hdaudio.c
M src/southbridge/intel/i82801ix/lpc.c
M src/southbridge/intel/i82801ix/sata.c
M util/cbfstool/elf.h
M util/cbfstool/elfheaders.c
M util/cbfstool/rmodule.c
M util/xcompile/xcompile
22 files changed, 663 insertions(+), 14 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/67/29667/1
diff --git a/src/arch/x86/Kconfig b/src/arch/x86/Kconfig
index 7c8371e..ed07a05 100644
--- a/src/arch/x86/Kconfig
+++ b/src/arch/x86/Kconfig
@@ -330,3 +330,7 @@
config HAVE_CF9_RESET_PREPARE
bool
depends on HAVE_CF9_RESET
+
+config TTB_SIZE_KB
+ hex "Size of TTB"
+ default 0x1000
diff --git a/src/arch/x86/Makefile.inc b/src/arch/x86/Makefile.inc
index fcc57c5..c5cf625 100644
--- a/src/arch/x86/Makefile.inc
+++ b/src/arch/x86/Makefile.inc
@@ -398,7 +398,7 @@
$(objgenerated)/ramstage.o: $$(ramstage-objs) $(COMPILER_RT_ramstage) $$(ramstage-libs)
@printf " CC $(subst $(obj)/,,$(@))\n"
-ifeq ($(CONFIG_ARCH_ROMSTAGE_X86_32),y)
+ifeq ($(CONFIG_ARCH_RAMSTAGE_X86_32),y)
$(LD_ramstage) -m elf_i386 -r -o $@ $(COMPILER_RT_FLAGS_ramstage) --whole-archive --start-group $(filter-out %.ld,$(ramstage-objs)) $(ramstage-libs) --no-whole-archive $(COMPILER_RT_ramstage) --end-group
else
$(LD_ramstage) -m elf_x86_64 -r -o $@ $(COMPILER_RT_FLAGS_ramstage) --whole-archive --start-group $(filter-out %.ld,$(ramstage-objs)) $(ramstage-libs) --no-whole-archive $(COMPILER_RT_ramstage) --end-group
diff --git a/src/arch/x86/boot.c b/src/arch/x86/boot.c
index 2967cf6..fa98704 100644
--- a/src/arch/x86/boot.c
+++ b/src/arch/x86/boot.c
@@ -29,16 +29,17 @@
return 0;
}
+ #include <arch/mmu.h>
void arch_prog_run(struct prog *prog)
{
+ printk(BIOS_DEBUG, "Jumping to %p\n", (void*)prog_entry(prog));
__asm__ volatile (
#ifdef __x86_64__
"jmp *%%rdi\n"
#else
"jmp *%%edi\n"
#endif
-
:: "D"(prog_entry(prog))
);
}
diff --git a/src/arch/x86/c_start.S b/src/arch/x86/c_start.S
index 6426ef3..11b0145 100644
--- a/src/arch/x86/c_start.S
+++ b/src/arch/x86/c_start.S
@@ -12,6 +12,7 @@
*/
#include <cpu/x86/post_code.h>
+#include <arch/rom_segs.h>
/* Place the stack in the bss section. It's not necessary to define it in the
* the linker script. */
@@ -35,13 +36,57 @@
#else
.code32
#endif
+
.globl _start
_start:
+
cli
- lgdt %cs:gdtaddr
+#ifdef __x86_64__
+ /* Test for page tables installed */
+ mov %cr3, %eax
+ cmp $0, %eax
+ je longmode_setup_err
+
+ /* Test for long mode active (EFER.LMA = 1 EFER.LME = 1) */
+ movl $0xC0000080, %ecx // EFER MSR number.
+ rdmsr
+ andl $0x500, %eax
+ cmp $0x500, %eax
+ je longmode_active
+
+ /* Test for long mode disabled (EFER.LME = 0) */
+ cmp $0, %eax
+ je longmode_setup_err
+
+ /*
+ * Previous stage prepared long mode:
+ * + Long mode is enabled (EFER.LME = 1)
+ * + paging is disalbed
+ * + page tables are installed
+ */
+
+ /* Enable paging */
+ mov %cr0, %eax
+ orl $(1 <<31), %eax
+ mov %eax, %cr0
+
+ jmp longmode_active
+
+longmode_setup_err:
+ post_code(POST_DEAD_CODE) /* post ee */
+ hlt
+ jmp longmode_setup_err
+
+longmode_active:
+#endif
+
+ lgdt %cs:gdtaddr
+
#ifndef __x86_64__
+ /* Enable protected mode */
ljmp $0x10, $1f
#endif
+ /* Use flat data segment */
1: movl $0x18, %eax
movl %eax, %ds
movl %eax, %es
@@ -134,7 +179,7 @@
#endif
.data
-
+ .balign 8
/* This is the gdt for GCC part of coreboot.
* It is different from the gdt in ROMCC/ASM part of coreboot
* which is defined in entry32.inc
diff --git a/src/arch/x86/exception.c b/src/arch/x86/exception.c
index 0f42fdf..9dda706 100644
--- a/src/arch/x86/exception.c
+++ b/src/arch/x86/exception.c
@@ -516,7 +516,7 @@
"edi: %08x esi: %08x ebp: %08x esp: %08x\n",
logical_processor, (unsigned int)lapicid(),
info->vector, info->cs, info->eip,
- info->error_code, info->eflags, read_cr2(),
+ info->error_code, info->eflags, (unsigned int)read_cr2(),
info->eax, info->ebx, info->ecx, info->edx,
info->edi, info->esi, info->ebp, info->esp);
u8 *code = (u8 *)((uintptr_t)info->eip - (MDUMP_SIZE >> 1));
diff --git a/src/arch/x86/include/arch/mmu.h b/src/arch/x86/include/arch/mmu.h
new file mode 100644
index 0000000..c3bd3f7
--- /dev/null
+++ b/src/arch/x86/include/arch/mmu.h
@@ -0,0 +1,105 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright 2014 Google Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __ARCH_X86_MMU_H__
+#define __ARCH_X86_MMU_H__
+
+#include <types.h>
+
+/* Memory attributes for mmap regions
+ * These attributes act as tag values for memrange regions
+ */
+
+/* Descriptor attributes */
+
+#define DESC_MASK 0xeaf
+#define INVALID_DESC 0
+#define TABLE_DESC 0x623
+#define PAGE_DESC 0x4a3
+#define BLOCK_DESC 0x2a3
+
+#define AVAIL_SHIFT 9
+#define AVAIL_MASK (7 << AVAIL_SHIFT)
+#define AVAIL_INVAL 0
+#define AVAIL_TABLE 3
+#define AVAIL_PAGE 2
+#define AVAIL_BLOCK 1
+
+
+/* Block descriptor */
+#define BLOCK_NS (1 << 5)
+
+#define BLOCK_AP_RW (0 << 7)
+#define BLOCK_AP_RO (1 << 7)
+
+#define BLOCK_ACCESS (1 << 10)
+
+#define BLOCK_XN (1ULL << 54)
+
+#define BLOCK_SH_SHIFT (8)
+#define BLOCK_SH_NON_SHAREABLE (0 << BLOCK_SH_SHIFT)
+#define BLOCK_SH_UNPREDICTABLE (1 << BLOCK_SH_SHIFT)
+#define BLOCK_SH_OUTER_SHAREABLE (2 << BLOCK_SH_SHIFT)
+#define BLOCK_SH_INNER_SHAREABLE (3 << BLOCK_SH_SHIFT)
+
+/* Sentinel descriptor to mark first PTE of an unused table. It must be a value
+ * that cannot occur naturally as part of a page table. (Bits [1:0] = 0b00 makes
+ * this an unmapped page, but some page attribute bits are still set.) */
+#define UNUSED_DESC 0x6EbAAD0BBADbA000ULL
+
+/* XLAT Table Init Attributes */
+
+#define VA_START 0x0
+#define BITS_PER_VA 48
+/* Granule size of 4KB is being used */
+#define GRANULE_SIZE_SHIFT 12
+#define GRANULE_SIZE (1 << GRANULE_SIZE_SHIFT)
+#define XLAT_ADDR_MASK ((1ULL << BITS_PER_VA) - GRANULE_SIZE)
+#define GRANULE_SIZE_MASK ((1ULL << GRANULE_SIZE_SHIFT) - 1)
+
+#define BITS_RESOLVED_PER_LVL (GRANULE_SIZE_SHIFT - 3)
+#define L0_ADDR_SHIFT (GRANULE_SIZE_SHIFT + BITS_RESOLVED_PER_LVL * 3)
+#define L1_ADDR_SHIFT (GRANULE_SIZE_SHIFT + BITS_RESOLVED_PER_LVL * 2)
+#define L2_ADDR_SHIFT (GRANULE_SIZE_SHIFT + BITS_RESOLVED_PER_LVL * 1)
+#define L3_ADDR_SHIFT (GRANULE_SIZE_SHIFT + BITS_RESOLVED_PER_LVL * 0)
+
+#define L0_ADDR_MASK (((1ULL << BITS_RESOLVED_PER_LVL) - 1) << L0_ADDR_SHIFT)
+#define L1_ADDR_MASK (((1ULL << BITS_RESOLVED_PER_LVL) - 1) << L1_ADDR_SHIFT)
+#define L2_ADDR_MASK (((1ULL << BITS_RESOLVED_PER_LVL) - 1) << L2_ADDR_SHIFT)
+#define L3_ADDR_MASK (((1ULL << BITS_RESOLVED_PER_LVL) - 1) << L3_ADDR_SHIFT)
+
+/* These macros give the size of the region addressed by each entry of a xlat
+ table at any given level */
+#define L3_XLAT_SIZE (1ULL << L3_ADDR_SHIFT)
+#define L2_XLAT_SIZE (1ULL << L2_ADDR_SHIFT)
+#define L1_XLAT_SIZE (1ULL << L1_ADDR_SHIFT)
+#define L0_XLAT_SIZE (1ULL << L0_ADDR_SHIFT)
+
+#define PAT_UC 0
+#define PAT_WC 1
+#define PAT_WT 4
+#define PAT_WP 5
+#define PAT_WB 6
+#define PAT_UC_MINUS 7
+
+/* Initialize MMU registers and page table memory region. */
+void mmu_init(void);
+/* Install page tables and enable long mode */
+void mmu_install_pagetables(void);
+void mmu_config_range(uint64_t start, uint64_t size, uint64_t tag);
+/* Disable the MMU (which also disables dcache but not icache). */
+void mmu_disable(void);
+
+#endif /* __ARCH_X86_MMU_H__ */
diff --git a/src/arch/x86/mmu.c b/src/arch/x86/mmu.c
new file mode 100644
index 0000000..a0e3e78
--- /dev/null
+++ b/src/arch/x86/mmu.c
@@ -0,0 +1,403 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright 2014 Google Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <assert.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <symbols.h>
+
+#include <console/console.h>
+#include <arch/mmu.h>
+#include <arch/cache.h>
+#include <cpu/x86/msr.h>
+#include <cbmem.h>
+
+/* This just caches the next free table slot (okay to do since they fill up from
+ * bottom to top and can never be freed up again). It will reset to its initial
+ * value on stage transition, so we still need to check it for UNUSED_DESC. */
+static CAR_GLOBAL uint64_t *next_free_table;
+
+#define PTE_PRES (1ULL << 0)
+#define PTE_RW (1ULL << 1)
+#define PTE_US (1ULL << 2)
+#define PTE_PWT (1ULL << 3)
+#define PTE_PCD (1ULL << 4)
+#define PTE_A (1ULL << 5)
+#define PTE_D (1ULL << 6)
+#define PTE_PAT (1ULL << 7)
+#define PTE_G (1ULL << 8)
+#define PTE_XD (1ULL << 63)
+#define PDE_PS (1ULL << 7)
+
+#define BLOCK_INDEX_MASK (PTE_PWT | PTE_PCD | PTE_PRES | PTE_RW | PTE_A | PTE_D)
+#define BLOCK_INDEX_SHIFT 0
+#define BLOCK_INDEX_MEM_NORMAL (PTE_PRES | PTE_RW | PTE_A | PTE_D)
+
+static void print_tag(int level, uint64_t pat)
+{
+ switch (pat) {
+ case PAT_UC:
+ printk(level, "UC\n");
+ break;
+ case PAT_WC:
+ printk(level, "WC\n");
+ break;
+ case PAT_WT:
+ printk(level, "WT\n");
+ break;
+ case PAT_WP:
+ printk(level, "WP\n");
+ break;
+ case PAT_WB:
+ printk(level, "WB\n");
+ break;
+ case PAT_UC_MINUS:
+ printk(level, "UC-\n");
+ break;
+ default:
+ break;
+ }
+}
+
+static uint64_t pte_pat_flags(unsigned long pat)
+{
+ switch (pat) {
+ case PAT_UC:
+ return 0 | PTE_PCD | PTE_PWT;
+ case PAT_WC:
+ return 0 | 0 | PTE_PWT;
+ case PAT_WT:
+ return PTE_PAT | PTE_PCD | PTE_PWT;
+ case PAT_WP:
+ return PTE_PAT | 0 | PTE_PWT;
+ case PAT_WB:
+ return 0 | 0 | 0;
+ case PAT_UC_MINUS:
+ return 0 | PTE_PCD | 0;
+ default:
+ printk(BIOS_ERR, "PTE PAT defaulting to WB: %lx\n", pat);
+ return 0 | 0 | 0;
+ }
+}
+
+static u8 *ttb(void)
+{
+ return cbmem_find(CBMEM_ID_TTB);
+}
+
+static u8 *ettb(void)
+{
+ return (u8 *)cbmem_find(CBMEM_ID_TTB) + (CONFIG_TTB_SIZE_KB * 1024);
+}
+
+/* Func : get_block_attr
+ * Desc : Get block descriptor attributes based on the value of tag in memrange
+ * region
+ */
+static uint64_t get_block_attr(unsigned long tag, bool ps)
+{
+ uint64_t flags = PTE_PRES | PTE_RW | PTE_US | PTE_A | PTE_D;
+ flags |= pte_pat_flags(tag);
+ if (ps) {
+ if (flags & PTE_PAT) {
+ /* If PS=1 PAT is at position 12 instead of 7 */
+ flags &= ~PTE_PAT;
+ flags |= (PTE_PAT << 5);
+ }
+ flags |= PDE_PS;
+ }
+ return flags;
+}
+
+/* Func : setup_new_table
+ * Desc : Get next free table from TTB and set it up to match old parent entry.
+ */
+static uint64_t *setup_new_table(uint64_t desc, uint64_t xlat_size)
+{
+ while (next_free_table[0] != UNUSED_DESC) {
+ next_free_table += GRANULE_SIZE/sizeof(*next_free_table);
+ if (ettb() - (u8 *)next_free_table <= 0)
+ die("Ran out of page table space!");
+ }
+
+ uint64_t frame_base = desc & XLAT_ADDR_MASK;
+ printk(BIOS_DEBUG, "Backing address range [0x%llx:0x%llx) with new page"
+ " table @%p\n", frame_base, frame_base +
+ (xlat_size << BITS_RESOLVED_PER_LVL), next_free_table);
+
+ if (desc == INVALID_DESC) {
+ memset(next_free_table, 0, GRANULE_SIZE);
+ } else {
+ /* Can reuse old parent entry, but may need to adjust type. */
+ if (xlat_size == L3_XLAT_SIZE)
+ desc |= PAGE_DESC;
+
+ int i = 0;
+ for (; i < GRANULE_SIZE/sizeof(*next_free_table); i++) {
+ next_free_table[i] = desc;
+ desc += xlat_size;
+ }
+ }
+
+ return next_free_table;
+}
+
+/* Func: get_next_level_table
+ * Desc: Check if the table entry is a valid descriptor. If not, initialize new
+ * table, update the entry and return the table addr. If valid, return the addr
+ */
+static uint64_t *get_next_level_table(uint64_t *ptr, size_t xlat_size)
+{
+ uint64_t desc = *ptr;
+
+ if ((desc & DESC_MASK) != TABLE_DESC) {
+ uint64_t *new_table = setup_new_table(desc, xlat_size);
+ desc = ((uintptr_t)new_table) | TABLE_DESC;
+ *ptr = desc;
+ }
+ return (uint64_t *)(uintptr_t)(desc & XLAT_ADDR_MASK);
+}
+
+/*
+ Func : init_xlat_table
+ * Desc : Given a base address and size, it identifies the indices within
+ * different level XLAT tables which map the given base addr. Similar to table
+ * walk, except that all invalid entries during the walk are updated
+ * accordingly. On success, it returns the size of the block/page addressed by
+ * the final table.
+ */
+static uint64_t init_xlat_table(uint64_t base_addr,
+ uint64_t size,
+ uint64_t tag)
+{
+ uint64_t l0_index = (base_addr & L0_ADDR_MASK) >> L0_ADDR_SHIFT;
+ uint64_t l1_index = (base_addr & L1_ADDR_MASK) >> L1_ADDR_SHIFT;
+ uint64_t l2_index = (base_addr & L2_ADDR_MASK) >> L2_ADDR_SHIFT;
+ uint64_t l3_index = (base_addr & L3_ADDR_MASK) >> L3_ADDR_SHIFT;
+ uint64_t *table = (uint64_t *)ttb();
+ uint64_t desc;
+
+ /* check if CPU supports 1GB huge tables */
+ const bool hugepage_1gb = !!(cpuid_edx(0x80000001) & (1 << 26));
+
+ /* L0 entry stores a table descriptor (doesn't support blocks) */
+ table = get_next_level_table(&table[l0_index], L1_XLAT_SIZE);
+
+ /* L1 table lookup */
+ if ((size >= L1_XLAT_SIZE) &&
+ IS_ALIGNED(base_addr, (1UL << L1_ADDR_SHIFT)) &&
+ hugepage_1gb) {
+ /* If block address is aligned and size is greater than
+ * or equal to size addressed by each L1 entry, we can
+ * directly store a block desc */
+ desc = base_addr | BLOCK_DESC | get_block_attr(tag, 1);
+ table[l1_index] = desc;
+ /* L2 lookup is not required */
+ return L1_XLAT_SIZE;
+ }
+
+ /* L1 entry stores a table descriptor */
+ table = get_next_level_table(&table[l1_index], L2_XLAT_SIZE);
+
+ /* L2 table lookup */
+ if ((size >= L2_XLAT_SIZE) &&
+ IS_ALIGNED(base_addr, (1UL << L2_ADDR_SHIFT))) {
+ /* If block address is aligned and size is greater than
+ * or equal to size addressed by each L2 entry, we can
+ * directly store a block desc */
+ desc = base_addr | BLOCK_DESC | get_block_attr(tag, 1);
+ table[l2_index] = desc;
+ /* L3 lookup is not required */
+ return L2_XLAT_SIZE;
+ }
+
+ /* L2 entry stores a table descriptor */
+ table = get_next_level_table(&table[l2_index], L3_XLAT_SIZE);
+
+ /* L3 table lookup */
+ desc = base_addr | PAGE_DESC | get_block_attr(tag, 0);
+ table[l3_index] = desc;
+ return L3_XLAT_SIZE;
+}
+
+/* Func : sanity_check
+ * Desc : Check address/size alignment of a table or page.
+ */
+static void sanity_check(uint64_t addr, uint64_t size)
+{
+ assert(!(addr & GRANULE_SIZE_MASK) &&
+ !(size & GRANULE_SIZE_MASK) &&
+ (addr + size < (1ULL << BITS_PER_VA)) &&
+ size >= GRANULE_SIZE);
+}
+
+/* Func : get_pte
+ * Desc : Returns the page table entry governing a specific address. */
+static uint64_t get_pte(uint64_t addr)
+{
+ int shift = L0_ADDR_SHIFT;
+ /* Using pointer here is OK, as _ttb must be in 32bit space */
+ uint64_t *pte = (uint64_t *)ttb();
+ printk(BIOS_DEBUG, "%llx ", addr);
+
+ while (1) {
+ int index = ((uintptr_t)addr >> shift) &
+ ((1ULL << BITS_RESOLVED_PER_LVL) - 1);
+
+ switch ((pte[index] & AVAIL_MASK) >> AVAIL_SHIFT) {
+ case AVAIL_INVAL:
+ printk(BIOS_DEBUG, "INVAL ");break;
+ case AVAIL_TABLE:
+ printk(BIOS_DEBUG, "TABLE @ %llx\n", pte[index] & XLAT_ADDR_MASK);break;
+ case AVAIL_PAGE:
+ printk(BIOS_DEBUG, "PAGE %llx, %llx %llx\n", pte[index] & ((XLAT_ADDR_MASK<<1)),
+ (pte[index] & ((XLAT_ADDR_MASK<<1))) + (1ULL << shift) -1,pte[index] & 0xfff);break;
+
+ case AVAIL_BLOCK:
+ printk(BIOS_DEBUG, "BLOCK %llx, %llx %llx\n", pte[index] & ((XLAT_ADDR_MASK<<1)),
+ (pte[index] & ((XLAT_ADDR_MASK<<1))) + (1ULL << shift) -1,pte[index] & 0xfff);break;
+ }
+ //printk(BIOS_DEBUG, "pte[%d] =%llx\n", index, pte[index]);
+ if ((pte[index] & DESC_MASK) != TABLE_DESC ||
+ shift <= GRANULE_SIZE_SHIFT)
+ return pte[index];
+
+ pte = (uint64_t *)(uintptr_t)(pte[index] & XLAT_ADDR_MASK);
+ shift -= BITS_RESOLVED_PER_LVL;
+ }
+}
+
+/* Func : assert_correct_ttb_mapping
+ * Desc : Asserts that mapping for addr matches the access type used by the
+ * page table walk (i.e. addr is correctly mapped to be part of the TTB). */
+static void assert_correct_ttb_mapping(uint64_t addr)
+{
+ return;
+
+ uint64_t pte = get_pte(addr);
+ assert(((pte >> BLOCK_INDEX_SHIFT) & BLOCK_INDEX_MASK)
+ == BLOCK_INDEX_MEM_NORMAL);
+}
+
+/* Func : mmu_config_range
+ * Desc : This function repeatedly calls init_xlat_table with the base
+ * address. Based on size returned from init_xlat_table, base_addr is updated
+ * and subsequent calls are made for initializing the xlat table until the whole
+ * region is initialized.
+ */
+void mmu_config_range(uint64_t start, uint64_t size, uint64_t tag)
+{
+ uint64_t base_addr = start;
+ uint64_t temp_size = size;
+
+ printk(BIOS_INFO, "Mapping address range [0x%llx:0x%llx) as ",
+ start, start + size);
+ print_tag(BIOS_INFO, tag);
+
+ sanity_check(base_addr, temp_size);
+
+ while (temp_size)
+ temp_size -= init_xlat_table(base_addr + (size - temp_size),
+ temp_size, tag);
+
+}
+
+/* Func : mmu_init
+ * Desc : Initialize MMU registers and page table memory region. This must be
+ * called exactly ONCE PER BOOT before trying to configure any mappings.
+ */
+void mmu_init(void)
+{
+ next_free_table = cbmem_find(CBMEM_ID_TTB);
+ if (!next_free_table)
+ next_free_table = cbmem_add(CBMEM_ID_TTB, CONFIG_TTB_SIZE_KB * 1024);
+ if (!next_free_table)
+ die("Could not allocate memory for TTB\n");
+
+ /* Initially mark all table slots unused (first PTE == UNUSED_DESC). */
+ uint64_t *table = (uint64_t *)ttb();
+ for (; ettb() - (u8 *)table > 0; table += GRANULE_SIZE/sizeof(*table))
+ table[0] = UNUSED_DESC;
+
+ printk(BIOS_DEBUG, "Initialize the root table (L0)\n");
+ /* Initialize the root table (L0) to be completely unmapped. */
+ uint64_t *root = setup_new_table(INVALID_DESC, L0_XLAT_SIZE);
+ assert((u8 *)root == ttb());
+}
+
+/* Func : mmu_install_pagetables
+ * Desc : Install page tables, enable PAE and enable long mode.
+ * It does not enable paging and thus does not activate long mode!
+ */
+void mmu_install_pagetables(void)
+{
+ assert_correct_ttb_mapping((uintptr_t)ttb());
+ assert_correct_ttb_mapping((uintptr_t)ettb() - 1);
+
+ unsigned long long i;
+ for (i = 0x407a0000; i < 0x408a0000; i += (1024 * 1024)) {
+ uint64_t pte = get_pte(i);
+ if (pte == 5)
+ break;
+ }
+ /* Load the page table address */
+ write_cr3((uintptr_t)cbmem_find(CBMEM_ID_TTB));
+
+ printk(BIOS_INFO, "MMU: installed page tables\n");
+
+ CRx_TYPE cr0;
+ CRx_TYPE cr4;
+
+ /* Disable Paging */
+ cr0 = read_cr0();
+ cr0 &= ~CR0_PG;
+ write_cr0(cr0);
+
+ /* Enable PAE */
+ cr4 = read_cr4();
+ cr4 |= CR4_PAE;
+ write_cr4(cr4);
+
+ printk(BIOS_INFO, "MMU: enabled PAE\n");
+
+ #define MSR_EFER 0xc0000080 /* extended feature register */
+
+ /* Set the LM-bit */
+ msr_t msr = rdmsr(MSR_EFER);
+ msr.lo |= (1 << 8);
+ wrmsr(MSR_EFER, msr);
+
+ printk(BIOS_INFO, "MMU: enabled long mode\n");
+
+ /*
+ * Paging isn't enabled here!
+ * c_start.S will enable it to enter long mode.
+ */
+}
diff --git a/src/commonlib/include/commonlib/cbmem_id.h b/src/commonlib/include/commonlib/cbmem_id.h
index 042ea6e..366cb3e 100644
--- a/src/commonlib/include/commonlib/cbmem_id.h
+++ b/src/commonlib/include/commonlib/cbmem_id.h
@@ -62,6 +62,7 @@
#define CBMEM_ID_STAGEx_CACHE 0x57a9e100
#define CBMEM_ID_STAGEx_RAW 0x57a9e200
#define CBMEM_ID_STORAGE_DATA 0x53746f72
+#define CBMEM_ID_TTB 0x54544200
#define CBMEM_ID_TCPA_LOG 0x54435041
#define CBMEM_ID_TCPA_TCG_LOG 0x54445041
#define CBMEM_ID_TIMESTAMP 0x54494d45
diff --git a/src/cpu/qemu-x86/Kconfig b/src/cpu/qemu-x86/Kconfig
index 70cce9b..a90acf6 100644
--- a/src/cpu/qemu-x86/Kconfig
+++ b/src/cpu/qemu-x86/Kconfig
@@ -18,7 +18,8 @@
select ARCH_BOOTBLOCK_X86_32
select ARCH_VERSTAGE_X86_32
select ARCH_ROMSTAGE_X86_32
- select ARCH_RAMSTAGE_X86_32
+ #select ARCH_RAMSTAGE_X86_32
+ select ARCH_RAMSTAGE_X86_64
select SMP
select UDELAY_TSC
select C_ENVIRONMENT_BOOTBLOCK
diff --git a/src/cpu/x86/Makefile.inc b/src/cpu/x86/Makefile.inc
index 3e8a664..1c9b83e 100644
--- a/src/cpu/x86/Makefile.inc
+++ b/src/cpu/x86/Makefile.inc
@@ -4,7 +4,7 @@
endif
endif
-subdirs-y += pae
+#subdirs-y += pae
subdirs-$(CONFIG_PARALLEL_MP) += name
ramstage-$(CONFIG_PARALLEL_MP) += mp_init.c
ramstage-$(CONFIG_MIRROR_PAYLOAD_TO_RAM_BEFORE_LOADING) += mirror_payload.c
diff --git a/src/lib/timestamp.c b/src/lib/timestamp.c
index 105b696..e2c7450 100644
--- a/src/lib/timestamp.c
+++ b/src/lib/timestamp.c
@@ -178,7 +178,7 @@
tse->entry_stamp = ts_time - ts_table->base_time;
if (IS_ENABLED(CONFIG_TIMESTAMPS_ON_CONSOLE))
- printk(BIOS_SPEW, "Timestamp - %s: %" PRIu64 "\n",
+ printk(BIOS_SPEW, "Timestamp - %s: %llu\n",
timestamp_name(id), ts_time);
if (ts_table->num_entries == ts_table->max_entries)
diff --git a/src/mainboard/emulation/qemu-q35/Kconfig b/src/mainboard/emulation/qemu-q35/Kconfig
index 3be034a..f14867b 100644
--- a/src/mainboard/emulation/qemu-q35/Kconfig
+++ b/src/mainboard/emulation/qemu-q35/Kconfig
@@ -12,6 +12,7 @@
select MAINBOARD_HAS_NATIVE_VGA_INIT
select MAINBOARD_FORCE_NATIVE_VGA_INIT
select BOOTBLOCK_CONSOLE
+ select IDT_IN_EVERY_STAGE
config MAINBOARD_DIR
string
diff --git a/src/mainboard/emulation/qemu-q35/Makefile.inc b/src/mainboard/emulation/qemu-q35/Makefile.inc
index 1503220..65b8e70 100644
--- a/src/mainboard/emulation/qemu-q35/Makefile.inc
+++ b/src/mainboard/emulation/qemu-q35/Makefile.inc
@@ -2,4 +2,6 @@
ramstage-y += ../qemu-i440fx/memory.c
ramstage-y += ../qemu-i440fx/fw_cfg.c
romstage-y += ../qemu-i440fx/memory.c
+romstage-y += ../../../arch/x86/mmu.c
+
bootblock-y += bootblock.c
diff --git a/src/mainboard/emulation/qemu-q35/romstage.c b/src/mainboard/emulation/qemu-q35/romstage.c
index 2b8d935..592d33d 100644
--- a/src/mainboard/emulation/qemu-q35/romstage.c
+++ b/src/mainboard/emulation/qemu-q35/romstage.c
@@ -21,15 +21,27 @@
#include <timestamp.h>
#include <southbridge/intel/i82801ix/i82801ix.h>
#include <program_loading.h>
+#include <arch/mmu.h>
+#include <arch/exception.h>
+
+#include "../qemu-i440fx/memory.h"
asmlinkage void car_stage_entry(void)
{
i82801ix_early_init();
console_init();
+ exception_init();
- cbmem_recovery(0);
+ cbmem_initialize_empty();
timestamp_add_now(TS_START_ROMSTAGE);
+ mmu_init();
+ mmu_config_range(0, 0x100000000ULL, PAT_WT);
+ mmu_config_range(0, (uint64_t)qemu_get_memory_size() * 1024ULL, PAT_WB);
+ if (qemu_get_high_memory_size() > 0)
+ mmu_config_range(0x100000000ULL, (uint64_t)qemu_get_high_memory_size() * 1024ULL, PAT_WB);
+ mmu_install_pagetables();
+
run_ramstage();
}
diff --git a/src/southbridge/intel/common/smi.c b/src/southbridge/intel/common/smi.c
index 3c25556..b543b8b 100644
--- a/src/southbridge/intel/common/smi.c
+++ b/src/southbridge/intel/common/smi.c
@@ -150,7 +150,7 @@
"outb %%al, %%dx\n\t"
: /* ignore result */
: "a" (APM_CNT_GNVS_UPDATE),
- "b" ((u32)gnvs),
+ "b" ((u32)(uintptr_t)gnvs),
"d" (APM_CNT)
);
}
diff --git a/src/southbridge/intel/i82801ix/hdaudio.c b/src/southbridge/intel/i82801ix/hdaudio.c
index 607604b..b4cee46 100644
--- a/src/southbridge/intel/i82801ix/hdaudio.c
+++ b/src/southbridge/intel/i82801ix/hdaudio.c
@@ -278,7 +278,7 @@
// NOTE this will break as soon as the Azalia get's a bar above
// 4G. Is there anything we can do about it?
base = res2mmio(res, 0, 0);
- printk(BIOS_DEBUG, "Azalia: base = %08x\n", (u32)base);
+ printk(BIOS_DEBUG, "Azalia: base = %p\n", base);
codec_mask = codec_detect(base);
if (codec_mask) {
diff --git a/src/southbridge/intel/i82801ix/lpc.c b/src/southbridge/intel/i82801ix/lpc.c
index a69b879..5d7a226c 100644
--- a/src/southbridge/intel/i82801ix/lpc.c
+++ b/src/southbridge/intel/i82801ix/lpc.c
@@ -553,7 +553,7 @@
/* Add it to SSDT. */
acpigen_write_scope("\\");
- acpigen_write_name_dword("NVSA", (u32) gnvs);
+ acpigen_write_name_dword("NVSA", (u32) (uintptr_t)gnvs);
acpigen_pop_len();
}
}
diff --git a/src/southbridge/intel/i82801ix/sata.c b/src/southbridge/intel/i82801ix/sata.c
index dcdeeb4..71030948 100644
--- a/src/southbridge/intel/i82801ix/sata.c
+++ b/src/southbridge/intel/i82801ix/sata.c
@@ -32,7 +32,7 @@
u32 reg32;
/* Initialize AHCI memory-mapped space */
- u8 *abar = (u8 *)pci_read_config32(dev, PCI_BASE_ADDRESS_5);
+ u8 *abar = (u8 *)(uintptr_t)pci_read_config32(dev, PCI_BASE_ADDRESS_5);
printk(BIOS_DEBUG, "ABAR: %p\n", abar);
/* Set AHCI access mode.
diff --git a/util/cbfstool/elf.h b/util/cbfstool/elf.h
index a0bb35d..43fd7f3 100644
--- a/util/cbfstool/elf.h
+++ b/util/cbfstool/elf.h
@@ -1148,6 +1148,43 @@
/* Keep this the last entry. */
#define R_386_NUM 38
+/* AMD64 specific definitions. */
+#define R_AMD64_NONE 0 /* relocation types */
+#define R_AMD64_64 1
+#define R_AMD64_PC32 2
+#define R_AMD64_GOT32 3
+#define R_AMD64_PLT32 4
+#define R_AMD64_COPY 5
+#define R_AMD64_GLOB_DAT 6
+#define R_AMD64_JUMP_SLOT 7
+#define R_AMD64_RELATIVE 8
+#define R_AMD64_GOTPCREL 9
+#define R_AMD64_32 10
+#define R_AMD64_32S 11
+#define R_AMD64_16 12
+#define R_AMD64_PC16 13
+#define R_AMD64_8 14
+#define R_AMD64_PC8 15
+#define R_AMD64_DTPMOD64 16
+#define R_AMD64_DTPOFF64 17
+#define R_AMD64_TPOFF64 18
+#define R_AMD64_TLSGD 19
+#define R_AMD64_TLSLD 20
+#define R_AMD64_DTPOFF32 21
+#define R_AMD64_GOTTPOFF 22
+#define R_AMD64_TPOFF32 23
+#define R_AMD64_PC64 24
+#define R_AMD64_GOTOFF64 25
+#define R_AMD64_GOTPC32 26
+#define R_AMD64_GOT64 27 /* reserved for future expansion */
+#define R_AMD64_GOTPCREL64 28 /* reserved for future expansion */
+#define R_AMD64_GOTPC64 29 /* reserved for future expansion */
+#define R_AMD64_GOTPLT64 30 /* reserved for future expansion */
+#define R_AMD64_PLTOFF64 31 /* reserved for future expansion */
+#define R_AMD64_SIZE32 32
+#define R_AMD64_SIZE64 33
+#define R_AMD64_NUM 34
+
/* SUN SPARC specific definitions. */
/* Legal values for ST_TYPE subfield of st_info (symbol type). */
diff --git a/util/cbfstool/elfheaders.c b/util/cbfstool/elfheaders.c
index 9d02c30..8da54d0 100644
--- a/util/cbfstool/elfheaders.c
+++ b/util/cbfstool/elfheaders.c
@@ -1072,6 +1072,9 @@
case EM_386:
type = R_386_32;
break;
+ case EM_X86_64:
+ type = R_AMD64_64;
+ break;
case EM_ARM:
type = R_ARM_ABS32;
break;
diff --git a/util/cbfstool/rmodule.c b/util/cbfstool/rmodule.c
index 07957cb..b7969c9 100644
--- a/util/cbfstool/rmodule.c
+++ b/util/cbfstool/rmodule.c
@@ -43,6 +43,29 @@
return (type == R_386_32);
}
+static int valid_reloc_amd64(Elf64_Rela *rel)
+{
+ int type;
+
+ type = ELF64_R_TYPE(rel->r_info);
+
+ /* Only these 2 relocations are expected to be found. */
+ return (type == R_AMD64_64 ||
+ type == R_AMD64_PC64 ||
+ type == R_AMD64_32S ||
+ type == R_AMD64_32 ||
+ type == R_AMD64_PC32);
+}
+
+static int should_emit_amd64(Elf64_Rela *rel)
+{
+ int type;
+
+ type = ELF64_R_TYPE(rel->r_info);
+
+ return (type == R_AMD64_64);
+}
+
static int valid_reloc_arm(Elf64_Rela *rel)
{
int type;
@@ -100,6 +123,11 @@
.should_emit = should_emit_386,
},
{
+ .arch = EM_X86_64,
+ .valid_type = valid_reloc_amd64,
+ .should_emit = should_emit_amd64,
+ },
+ {
.arch = EM_ARM,
.valid_type = valid_reloc_arm,
.should_emit = should_emit_arm,
diff --git a/util/xcompile/xcompile b/util/xcompile/xcompile
index 6d82a4d..60d8a39 100755
--- a/util/xcompile/xcompile
+++ b/util/xcompile/xcompile
@@ -236,7 +236,13 @@
# The Quark processor doesn't support the instructions
# introduced with the Pentium 6 architecture, so allow it
# to use i586 instead.
-if [ "${TARCH}" = "x86_64" ] || [ "${TARCH}" = "x86_32" ]; then
+if [ "${TARCH}" = "x86_64" ]; then
+cat <<EOF
+ GCC_CFLAGS_${TARCH} += -march=core2
+EOF
+fi
+
+if [ "${TARCH}" = "x86_32" ]; then
cat <<EOF
ifneq (\$(CONFIG_USE_MARCH_586)\$(CONFIG_LP_USE_MARCH_586),)
--
To view, visit https://review.coreboot.org/29667
To unsubscribe, or for help writing mail filters, visit https://review.coreboot.org/settings
Gerrit-Project: coreboot
Gerrit-Branch: master
Gerrit-MessageType: newchange
Gerrit-Change-Id: If2f02a95b2f91ab51043d4e81054354f4a6eb5d5
Gerrit-Change-Number: 29667
Gerrit-PatchSet: 1
Gerrit-Owner: Patrick Rudolph <patrick.rudolph at 9elements.com>
Gerrit-Reviewer: Patrick Rudolph <siro at das-labor.org>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.coreboot.org/pipermail/coreboot-gerrit/attachments/20181117/eba871ed/attachment-0001.html>
More information about the coreboot-gerrit
mailing list