From 27f6bb783ba638e6aa2539a6c51ec96386dbf28f Mon Sep 17 00:00:00 2001
From: Timothy Pearson <tpearson@raptorengineeringinc.com>
Date: Mon, 18 May 2015 16:04:10 -0500
Subject: [PATCH 027/143] src/console: Add x86 romstage spinlock option and
 prink spinlock support

Change-Id: Ice42a0d3177736bf6e1bc601092e413601866f20
Signed-off-by: Timothy Pearson <tpearson@raptorengineeringinc.com>
---
 src/Kconfig                              |    4 ++++
 src/arch/x86/include/arch/smp/spinlock.h |   11 ++++++++++-
 src/console/printk.c                     |   19 +++++++++++++++++++
 src/cpu/amd/car/disable_cache_as_ram.c   |   10 ++++++++++
 src/cpu/amd/car/post_cache_as_ram.c      |   20 ++++++++++++++------
 5 files changed, 57 insertions(+), 7 deletions(-)

diff --git a/src/Kconfig b/src/Kconfig
index 368384d..5aa33d00 100644
--- a/src/Kconfig
+++ b/src/Kconfig
@@ -446,6 +446,10 @@ config HAVE_HARD_RESET
 	  This variable specifies whether a given board has a hard_reset
 	  function, no matter if it's provided by board code or chipset code.
 
+config HAVE_ROMSTAGE_CONSOLE_SPINLOCK
+	bool
+	default n
+
 config HAVE_MONOTONIC_TIMER
 	def_bool n
 	help
diff --git a/src/arch/x86/include/arch/smp/spinlock.h b/src/arch/x86/include/arch/smp/spinlock.h
index 32be2f2..3283540 100644
--- a/src/arch/x86/include/arch/smp/spinlock.h
+++ b/src/arch/x86/include/arch/smp/spinlock.h
@@ -1,7 +1,7 @@
 #ifndef ARCH_SMP_SPINLOCK_H
 #define ARCH_SMP_SPINLOCK_H
 
-#ifndef __PRE_RAM__
+#if !defined(__PRE_RAM__) || defined(CONFIG_HAVE_ROMSTAGE_CONSOLE_SPINLOCK)
 
 /*
  * Your basic SMP spinlocks, allowing only a single CPU anywhere
@@ -11,9 +11,18 @@ typedef struct {
 	volatile unsigned int lock;
 } spinlock_t;
 
+#ifdef __PRE_RAM__
+spinlock_t *romstage_console_lock(void);
+void initialize_romstage_console_lock(void);
+#endif
 
 #define SPIN_LOCK_UNLOCKED (spinlock_t) { 1 }
+
+#ifndef __PRE_RAM__
 #define DECLARE_SPIN_LOCK(x) static spinlock_t x = SPIN_LOCK_UNLOCKED;
+#else
+#define DECLARE_SPIN_LOCK(x)
+#endif
 
 /*
  * Simple spin lock operations.  There are two variants, one clears IRQ's
diff --git a/src/console/printk.c b/src/console/printk.c
index aab7ff5..5a23db0 100644
--- a/src/console/printk.c
+++ b/src/console/printk.c
@@ -2,6 +2,7 @@
  *  blatantly copied from linux/kernel/printk.c
  *
  *  Copyright (C) 1991, 1992  Linus Torvalds
+ *  Copyright (C) 2015 Timothy Pearson <tpearson@raptorengineeringinc.com>, Raptor Engineering
  *
  */
 
@@ -13,7 +14,13 @@
 #include <stddef.h>
 #include <trace.h>
 
+#if IS_ENABLED(CONFIG_HAVE_ROMSTAGE_CONSOLE_SPINLOCK)
+#ifndef __PRE_RAM__
 DECLARE_SPIN_LOCK(console_lock)
+#endif
+#else
+DECLARE_SPIN_LOCK(console_lock)
+#endif
 
 void do_putchar(unsigned char byte)
 {
@@ -39,7 +46,13 @@ int do_printk(int msg_level, const char *fmt, ...)
 #endif
 
 	DISABLE_TRACE;
+#ifdef __PRE_RAM__
+#if IS_ENABLED(CONFIG_HAVE_ROMSTAGE_CONSOLE_SPINLOCK)
+	spin_lock(romstage_console_lock());
+#endif
+#else
 	spin_lock(&console_lock);
+#endif
 
 	va_start(args, fmt);
 	i = vtxprintf(wrap_putchar, fmt, args, NULL);
@@ -47,7 +60,13 @@ int do_printk(int msg_level, const char *fmt, ...)
 
 	console_tx_flush();
 
+#ifdef __PRE_RAM__
+#if IS_ENABLED(CONFIG_HAVE_ROMSTAGE_CONSOLE_SPINLOCK)
+	spin_unlock(romstage_console_lock());
+#endif
+#else
 	spin_unlock(&console_lock);
+#endif
 	ENABLE_TRACE;
 
 	return i;
diff --git a/src/cpu/amd/car/disable_cache_as_ram.c b/src/cpu/amd/car/disable_cache_as_ram.c
index 3b464b8..5eccf79 100644
--- a/src/cpu/amd/car/disable_cache_as_ram.c
+++ b/src/cpu/amd/car/disable_cache_as_ram.c
@@ -24,6 +24,16 @@
 
 #include <cpu/x86/cache.h>
 
+static inline __attribute__((always_inline)) uint32_t amd_fam1x_cpu_family(void)
+{
+	uint32_t family;
+
+	family = cpuid_eax(0x80000001);
+	family = ((family & 0xf00000) >> 16) | ((family & 0xf00) >> 8);
+
+	return family;
+}
+
 static inline __attribute__((always_inline)) void disable_cache_as_ram(void)
 {
 	msr_t msr;
diff --git a/src/cpu/amd/car/post_cache_as_ram.c b/src/cpu/amd/car/post_cache_as_ram.c
index e265de1..257b41a 100644
--- a/src/cpu/amd/car/post_cache_as_ram.c
+++ b/src/cpu/amd/car/post_cache_as_ram.c
@@ -84,6 +84,10 @@ static void prepare_ramstage_region(void *resume_backup_memory)
 		memset_((void*)0, 0, CONFIG_RAMTOP - backup_top);
 	}
 
+#if IS_ENABLED(CONFIG_HAVE_ROMSTAGE_CONSOLE_SPINLOCK)
+	initialize_romstage_console_lock();
+#endif
+
 	print_car_debug("Done\n");
 }
 
@@ -92,18 +96,19 @@ static void prepare_ramstage_region(void *resume_backup_memory)
 static void vErrata343(void)
 {
 #ifdef BU_CFG2_MSR
-    msr_t msr;
-    unsigned int uiMask = 0xFFFFFFF7;
+	msr_t msr;
+	unsigned int uiMask = 0xFFFFFFF7;
 
-    msr = rdmsr(BU_CFG2_MSR);
-    msr.hi &= uiMask; // set bit 35 to 0
-    wrmsr(BU_CFG2_MSR, msr);
+	msr = rdmsr(BU_CFG2_MSR);
+	msr.hi &= uiMask;	// IcDisSpecTlbWr (bit 35) = 0
+	wrmsr(BU_CFG2_MSR, msr);
 #endif
 }
 
 void post_cache_as_ram(void)
 {
 	void *resume_backup_memory = NULL;
+	uint32_t family = amd_fam1x_cpu_family();
 
 	struct romstage_handoff *handoff;
 	handoff = romstage_handoff_find_or_add();
@@ -120,7 +125,10 @@ void post_cache_as_ram(void)
 	prepare_romstage_ramstack(resume_backup_memory);
 
 	/* from here don't store more data in CAR */
-	vErrata343();
+	if (family < 0x6f) {
+		/* Family 10h or earlier */
+		vErrata343();
+	}
 
 	size_t car_size = car_data_size();
 	void *migrated_car = (void *)(CONFIG_RAMTOP - car_size);
-- 
1.7.9.5

