summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/x86/include/asm/cache.h67
-rw-r--r--arch/x86/include/asm/msr.h24
-rw-r--r--arch/x86/lib/zimage.c15
-rw-r--r--board/chromebook-x86/coreboot/coreboot.c18
4 files changed, 124 insertions, 0 deletions
diff --git a/arch/x86/include/asm/cache.h b/arch/x86/include/asm/cache.h
new file mode 100644
index 00000000000..21e17f97df4
--- /dev/null
+++ b/arch/x86/include/asm/cache.h
@@ -0,0 +1,67 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2004 Eric W. Biederman
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef CPU_X86_ASM_CACHE
+#define CPU_X86_ASM_CACHE
+
+/* The memory clobber prevents the GCC from reordering the read/write order
+ * of CR0
+ */
+static inline unsigned long read_cr0(void)
+{
+ unsigned long cr0;
+ asm volatile ("movl %%cr0, %0" : "=r" (cr0) : : "memory");
+ return cr0;
+}
+
+static inline void write_cr0(unsigned long cr0)
+{
+ asm volatile ("movl %0, %%cr0" : : "r" (cr0) : "memory");
+}
+
+static inline void wbinvd(void)
+{
+ asm volatile ("wbinvd" : : : "memory");
+}
+
+static inline void invd(void)
+{
+ asm volatile("invd" : : : "memory");
+}
+
+static inline void enable_cache(void)
+{
+ unsigned long cr0;
+ cr0 = read_cr0();
+ cr0 &= 0x9fffffff;
+ write_cr0(cr0);
+}
+
+static inline void disable_cache(void)
+{
+ /* Disable and write back the cache */
+ unsigned long cr0;
+ cr0 = read_cr0();
+ cr0 |= 0x40000000;
+ wbinvd();
+ write_cr0(cr0);
+ wbinvd();
+}
+
+#endif /* CPU_X86_ASM_CACHE */
diff --git a/arch/x86/include/asm/msr.h b/arch/x86/include/asm/msr.h
new file mode 100644
index 00000000000..e8e2e4172bc
--- /dev/null
+++ b/arch/x86/include/asm/msr.h
@@ -0,0 +1,24 @@
+#ifndef CPU_X86_ASM_MSR_H
+#define CPU_X86_ASM_MSR_H
+
+static inline uint64_t rdmsr(unsigned index)
+{
+ uint64_t result;
+ asm volatile (
+ "rdmsr"
+ : "=A" (result)
+ : "c" (index)
+ );
+ return result;
+}
+
+static inline void wrmsr(unsigned index, uint64_t msr)
+{
+ asm volatile (
+ "wrmsr"
+ : /* No outputs */
+ : "c" (index), "A" (msr)
+ );
+}
+
+#endif /* CPU_X86_ASM_MSR_H */
diff --git a/arch/x86/lib/zimage.c b/arch/x86/lib/zimage.c
index 353abbcb08c..e6ce69353c9 100644
--- a/arch/x86/lib/zimage.c
+++ b/arch/x86/lib/zimage.c
@@ -285,8 +285,23 @@ int setup_zimage(struct boot_params *setup_base, char *cmd_line, int auto_boot,
return 0;
}
+/*
+ * Implement a weak default function for boards that optionally
+ * need to clean up the system before jumping to the kernel.
+ */
+int __board_final_cleanup(void)
+{
+ /* As default, don't skip */
+ return 0;
+}
+int board_final_cleanup(void)
+ __attribute__((weak, alias("__board_final_cleanup")));
+
+
void boot_zimage(void *setup_base, void *load_address)
{
+ board_final_cleanup();
+
printf("\nStarting kernel ...\n\n");
timestamp_add_now(TS_U_BOOT_START_KERNEL);
diff --git a/board/chromebook-x86/coreboot/coreboot.c b/board/chromebook-x86/coreboot/coreboot.c
index 9f7d6e091a1..dace515ea46 100644
--- a/board/chromebook-x86/coreboot/coreboot.c
+++ b/board/chromebook-x86/coreboot/coreboot.c
@@ -38,6 +38,8 @@
#include <chromeos/cros_gpio.h>
#include <chromeos/common.h>
#include <asm/io.h>
+#include <asm/msr.h>
+#include <asm/cache.h>
#include <coreboot/timestamp.h>
#ifdef CONFIG_HW_WATCHDOG
#include <watchdog.h>
@@ -190,6 +192,22 @@ int board_i8042_skip(void)
return fdt_decode_get_config_int(gd->blob, "skip-i8042", 0);
}
+#define MTRRphysBase_MSR(reg) (0x200 + 2 * (reg))
+#define MTRRphysMask_MSR(reg) (0x200 + 2 * (reg) + 1)
+
+int board_final_cleanup(void)
+{
+ /* Un-cache the ROM so the kernel has one
+ * more MTRR available.
+ */
+ disable_cache();
+ wrmsr(MTRRphysBase_MSR(7), 0);
+ wrmsr(MTRRphysMask_MSR(7), 0);
+ enable_cache();
+
+ return 0;
+}
+
#ifdef CONFIG_HW_WATCHDOG
void hw_watchdog_reset(void)
{