aboutsummaryrefslogtreecommitdiff
path: root/src/cpu/amd
diff options
context:
space:
mode:
authorMarc Jones <marc.jones@amd.com>2007-12-19 01:32:08 +0000
committerMarc Jones <marc.jones@amd.com>2007-12-19 01:32:08 +0000
commit8ae8c8822068ef1722c08073ffa4ecc25633cbee (patch)
tree8c7bbf2f7b791081e486439a9b7ffb2fd6e649ac /src/cpu/amd
parent2006b38fed2f5f3680de1736f7fc878823f2f93b (diff)
Initial AMD Barcelona support for rev Bx.
These are the core files for HyperTransport, DDR2 Memory, and multi-core initialization. Signed-off-by: Marc Jones <marc.jones@amd.com> Reviewed-by: Jordan Crouse <jordan.crouse@amd.com> Acked-by: Myles Watson <myles@pel.cs.byu.edu> git-svn-id: svn://svn.coreboot.org/coreboot/trunk@3014 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1
Diffstat (limited to 'src/cpu/amd')
-rw-r--r--src/cpu/amd/car/cache_as_ram.inc204
-rw-r--r--src/cpu/amd/microcode/microcode.c17
-rw-r--r--src/cpu/amd/model_10xxx/Config.lb40
-rw-r--r--src/cpu/amd/model_10xxx/apic_timer.c55
-rw-r--r--src/cpu/amd/model_10xxx/fidvid.c455
-rw-r--r--src/cpu/amd/model_10xxx/fidvid_common.c312
-rw-r--r--src/cpu/amd/model_10xxx/init_cpus.c553
-rw-r--r--src/cpu/amd/model_10xxx/mc_patch_01000018.h163
-rw-r--r--src/cpu/amd/model_10xxx/mc_patch_01000020.h163
-rw-r--r--src/cpu/amd/model_10xxx/mc_patch_01000033.h163
-rw-r--r--src/cpu/amd/model_10xxx/mc_patch_01000035.h163
-rw-r--r--src/cpu/amd/model_10xxx/model_10xxx_init.c463
-rw-r--r--src/cpu/amd/model_10xxx/pstate.c456
-rw-r--r--src/cpu/amd/model_10xxx/update_microcode.c90
-rw-r--r--src/cpu/amd/quadcore/Config.lb20
-rw-r--r--src/cpu/amd/quadcore/amd_sibling.c122
-rw-r--r--src/cpu/amd/quadcore/quadcore.c102
-rw-r--r--src/cpu/amd/quadcore/quadcore_id.c79
-rw-r--r--src/cpu/amd/socket_F_1207/Config.lb57
-rw-r--r--src/cpu/amd/socket_F_1207/chip.h23
-rw-r--r--src/cpu/amd/socket_F_1207/socket_F_1207.c25
21 files changed, 3695 insertions, 30 deletions
diff --git a/src/cpu/amd/car/cache_as_ram.inc b/src/cpu/amd/car/cache_as_ram.inc
index 53c34303ff..748223a06b 100644
--- a/src/cpu/amd/car/cache_as_ram.inc
+++ b/src/cpu/amd/car/cache_as_ram.inc
@@ -1,6 +1,6 @@
/*
* This file is part of the LinuxBIOS project.
- *
+ *
* Copyright (C) 2005-2007 Advanced Micro Devices, Inc.
*
* This program is free software; you can redistribute it and/or modify
@@ -15,23 +15,30 @@
* 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
- */
-
+ */
+
#define CacheSize DCACHE_RAM_SIZE
#define CacheBase (0xd0000 - CacheSize)
-
+
/* leave some space for global variable to pass to RAM stage */
#define GlobalVarSize DCACHE_RAM_GLOBAL_VAR_SIZE
+#if CAR_FAM10 == 1
+#define CacheSizeAPStack 0x400 /* 1K */
+#endif
+
#include <cpu/x86/mtrr.h>
#include <cpu/amd/mtrr.h>
/* Save the BIST result */
movl %eax, %ebp
- /* for normal part %ebx already contain cpu_init_detected from fallback call */
+ /*for normal part %ebx already contain cpu_init_detected from fallback call */
cache_as_ram_setup:
+
+ movb $0xA0, %al
+ outb %al, $0x80
/* hope we can skip the double set for normal part */
#if ((HAVE_FAILOVER_BOOT == 1) && (USE_FAILOVER_IMAGE == 1)) || ((HAVE_FAILOVER_BOOT == 0) && (USE_FALLBACK_IMAGE == 1))
@@ -42,6 +49,53 @@ cache_as_ram_setup:
andl $(1 << 11), %eax
movl %eax, %ebx /* We store the status */
+#if CAR_FAM10 == 1
+ /* for GH, CAR need to set DRAM Base/Limit Registers to direct that to node0 */
+
+ /* Only BSP needed, for other nodes set during HT/memory init. */
+ /* So we need to check if it is BSP */
+ movl $0x1b, %ecx
+ rdmsr
+ bt $8, %eax /*BSC */
+ jnc CAR_FAM10_out
+
+ /* Enable RT tables on BSP */
+ movl $0x8000c06c, %eax
+ movw $0xcf8, %dx
+ outl %eax, %dx
+ addw $4, %dx
+ inl %dx, %eax
+ btr $0, %eax
+ outl %eax, %dx
+
+ /* Setup temporary DRAM map: [0,16M) bit 0-23 */
+ movl $0x8000c144, %eax
+ movw $0xcf8, %dx
+ outl %eax, %dx
+ addw $4, %dx
+ movl $0, %eax
+ outl %eax, %dx
+
+ movl $0x8000c140, %eax
+ movw $0xcf8, %dx
+ outl %eax, %dx
+ addw $4, %dx
+ movl $3, %eax
+ outl %eax, %dx
+
+CAR_FAM10_out:
+
+#endif
+
+#if CAR_FAM10 == 1
+ /* Errata 193: Disable clean copybacks to L3 cache to allow cached ROM.
+ Re-enable it in after RAM is initialized and before CAR is disabled */
+ movl $0xc001102a, %ecx
+ rdmsr
+ bts $15, %eax
+ wrmsr
+#endif
+
/* Set MtrrFixDramModEn for clear fixed mtrr */
enable_fixed_mtrr_dram_modify:
movl $SYSCFG_MSR, %ecx
@@ -53,7 +107,7 @@ enable_fixed_mtrr_dram_modify:
/* Clear all MTRRs */
xorl %edx, %edx
movl $fixed_mtrr_msr, %esi
-
+
clear_fixed_var_mtrr:
lodsl (%esi), %eax
testl %eax, %eax
@@ -68,9 +122,14 @@ clear_fixed_var_mtrr_out:
#if CacheSize == 0x10000
/* enable caching for 64K using fixed mtrr */
- movl $0x268, %ecx /* fix4k_c0000 */
- movl $0x06060606, %eax /* WB IO type */
- movl %eax, %edx
+ movl $0x268, %ecx /* fix4k_c0000*/
+ #if CAR_FAM10 == 1
+ movl $0x1e1e1e1e, %edx /* WB MEM type */
+ #else
+ movl $0x06060606, %edx /* WB IO type */
+ #endif
+
+ movl %edx, %eax
wrmsr
movl $0x269, %ecx
wrmsr
@@ -78,38 +137,62 @@ clear_fixed_var_mtrr_out:
#if CacheSize == 0xc000
/* enable caching for 16K using fixed mtrr */
- movl $0x268, %ecx /* fix4k_c4000 */
- movl $0x06060606, %edx /* WB IO type */
+ movl $0x268, %ecx /* fix4k_c4000*/
+ #if CAR_FAM10 == 1
+ movl $0x1e1e1e1e, %edx /* WB MEM type */
+ #else
+ movl $0x06060606, %edx /* WB IO type */
+ #endif
xorl %eax, %eax
wrmsr
/* enable caching for 32K using fixed mtrr */
- movl $0x269, %ecx /* fix4k_c8000 */
- movl $0x06060606, %eax /* WB IO type */
- movl %eax, %edx
+ movl $0x269, %ecx /* fix4k_c8000*/
+ #if CAR_FAM10 == 1
+ movl $0x1e1e1e1e, %edx /* WB MEM type */
+ #else
+ movl $0x06060606, %edx /* WB IO type */
+ #endif
+ movl %edx, %eax
wrmsr
#endif
#if CacheSize == 0x8000
/* enable caching for 32K using fixed mtrr */
- movl $0x269, %ecx /* fix4k_c8000 */
- movl $0x06060606, %eax /* WB IO type */
- movl %eax, %edx
+ movl $0x269, %ecx /* fix4k_c8000*/
+ #if CAR_FAM10 == 1
+ movl $0x1e1e1e1e, %edx /* WB MEM type */
+ #else
+ movl $0x06060606, %edx /* WB IO type */
+ #endif
+ movl %edx, %eax
wrmsr
#endif
#if CacheSize < 0x8000
/* enable caching for 16K/8K/4K using fixed mtrr */
movl $0x269, %ecx /* fix4k_cc000*/
-#if CacheSize == 0x4000
+ #if CacheSize == 0x4000
+ #if CAR_FAM10 == 1
+ movl $0x1e1e1e1e, %edx /* WB MEM type */
+ #else
movl $0x06060606, %edx /* WB IO type */
-#endif
-#if CacheSize == 0x2000
+ #endif
+ #endif
+ #if CacheSize == 0x2000
+ #if CAR_FAM10 == 1
+ movl $0x1e1e0000, %edx /* WB MEM type */
+ #else
movl $0x06060000, %edx /* WB IO type */
-#endif
-#if CacheSize == 0x1000
+ #endif
+ #endif
+ #if CacheSize == 0x1000
+ #if CAR_FAM10 == 1
+ movl $0x1e000000, %edx /* WB MEM type */
+ #else
movl $0x06000000, %edx /* WB IO type */
-#endif
+ #endif
+ #endif
xorl %eax, %eax
wrmsr
#endif
@@ -160,13 +243,27 @@ clear_fixed_var_mtrr_out:
wrmsr
#endif
+ movb $0xA1, %al
+ outb %al, $0x80
+
/* enable cache */
movl %cr0, %eax
andl $0x9fffffff, %eax
movl %eax, %cr0
-#if ((HAVE_FAILOVER_BOOT == 1) && (USE_FAILOVER_IMAGE == 1)) || ((HAVE_FAILOVER_BOOT == 0) && (USE_FALLBACK_IMAGE == 1))
+#if CAR_FAM10 == 1
+ /* So we need to check if it is BSP */
+ movl $0x1b, %ecx
+ rdmsr
+ bt $8, %eax /*BSC */
+ jnc CAR_FAM10_ap
+#endif
+
+ movb $0xA2, %al
+ outb %al, $0x80
+
+#if ((HAVE_FAILOVER_BOOT == 1) && (USE_FAILOVER_IMAGE == 1)) || ((HAVE_FAILOVER_BOOT == 0) && (USE_FALLBACK_IMAGE == 1))
/* Read the range with lodsl*/
cld
movl $CacheBase, %esi
@@ -183,10 +280,64 @@ clear_fixed_var_mtrr_out:
/* set up the stack pointer */
movl $(CacheBase + CacheSize - GlobalVarSize), %eax
movl %eax, %esp
+
+ movb $0xA3, %al
+ outb %al, $0x80
+
+#if CAR_FAM10 == 1
+
+ jmp CAR_FAM10_ap_out
+CAR_FAM10_ap:
+ /* need to set stack pointer for AP */
+ /* it will be from CacheBase + (CacheSize - GlobalVarSize)/2 - (NodeID<<CoreIDbits + CoreID) * CacheSizeAPStack*/
+ /* So need to get the NodeID and CoreID at first */
+ /* If NB_CFG bit 54 is set just use initial apicid, otherwise need to reverse it */
+
+ /* store our init detected */
+ movl %ebx, %esi
+
+ /* get the coreid bits at first */
+ movl $0x80000008, %eax
+ cpuid
+ shrl $12, %ecx
+ andl $0x0f, %ecx
+ movl %ecx, %edi
+
+ /* get the initial apic id */
+ movl $1, %eax
+ cpuid
+ shrl $24, %ebx
+
+ /* get the nb cfg bit 54 */
+ movl $0xc001001f, %ecx /* NB_CFG_MSR */
+ rdmsr
+ movl %edi, %ecx /* CoreID bits */
+ bt $(54-32), %edx
+ jc roll_cfg
+ rolb %cl, %bl
+roll_cfg:
+
+ /* calculate stack pointer */
+ movl $CacheSizeAPStack, %eax
+ mull %ebx
+ movl $(CacheBase + (CacheSize - GlobalVarSize)/2), %esp
+ subl %eax, %esp
+
+ /* retrive init detected */
+ movl %esi, %ebx
+
+ movb $0xA4, %al
+ outb %al, $0x80
+
+CAR_FAM10_ap_out:
+#endif
+
+ movb $0xA5, %al
+ outb %al, $0x80
/* Restore the BIST result */
movl %ebp, %eax
-
+
/* We need to set ebp ? No need */
movl %esp, %ebp
pushl %ebx /* init detected */
@@ -194,6 +345,9 @@ clear_fixed_var_mtrr_out:
call cache_as_ram_main
/* We will not go back */
+ movb $0xAF, %al /* Should never see this postcode */
+ outb %al, $0x80
+
fixed_mtrr_msr:
.long 0x250, 0x258, 0x259
.long 0x268, 0x269, 0x26A
diff --git a/src/cpu/amd/microcode/microcode.c b/src/cpu/amd/microcode/microcode.c
index 3f0105cf92..0bbded08d4 100644
--- a/src/cpu/amd/microcode/microcode.c
+++ b/src/cpu/amd/microcode/microcode.c
@@ -17,6 +17,8 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
+#ifndef __ROMCC__
+
#include <stdint.h>
#include <console/console.h>
#include <cpu/cpu.h>
@@ -24,6 +26,8 @@
#include <cpu/amd/microcode.h>
#include <cpu/x86/cache.h>
+#endif
+
struct microcode {
u32 date_code;
u32 patch_id;
@@ -56,8 +60,11 @@ struct microcode {
static int need_apply_patch(struct microcode *m, u32 equivalent_processor_rev_id)
{
- if (m->processor_rev_id != equivalent_processor_rev_id) return 0;
-
+ if (m->processor_rev_id != equivalent_processor_rev_id) {
+ printk_debug("microcode: rev id does not match this patch.\n");
+ printk_debug("microcode: Not updated! Fix microcode_updates[] \n");
+ return 0;
+ }
if (m->nb_dev_id) {
//look at the device id, if not found return;
//if(m->nb_rev_id != installed_nb_rev_id) return 0;
@@ -86,7 +93,7 @@ void amd_update_microcode(void *microcode_updates, u32 equivalent_processor_rev_
msr = rdmsr(0x8b);
patch_id = msr.lo;
- printk_debug("microcode: equivalent processor rev id = 0x%04x, patch id = 0x%08x\n", equivalent_processor_rev_id, patch_id);
+ printk_debug("microcode: equivalent rev id = 0x%04x, current patch id = 0x%08x\n", equivalent_processor_rev_id, patch_id);
m = microcode_updates;
@@ -100,13 +107,13 @@ void amd_update_microcode(void *microcode_updates, u32 equivalent_processor_rev_
wrmsr(0xc0010020, msr);
- printk_debug("microcode: patch id that want to apply= 0x%08x\n", m->patch_id);
+ printk_debug("microcode: patch id to apply = 0x%08x\n", m->patch_id);
//read the patch_id again
msr = rdmsr(0x8b);
new_patch_id = msr.lo;
- printk_debug("microcode: updated to patch id = 0x%08x %s\r\n", new_patch_id , (new_patch_id == m->patch_id)?" success":" fail" );
+ printk_debug("microcode: updated to patch id = 0x%08x %s\n", new_patch_id , (new_patch_id == m->patch_id)?" success\n":" fail\n" );
break;
}
c += 2048;
diff --git a/src/cpu/amd/model_10xxx/Config.lb b/src/cpu/amd/model_10xxx/Config.lb
new file mode 100644
index 0000000000..afd03603b2
--- /dev/null
+++ b/src/cpu/amd/model_10xxx/Config.lb
@@ -0,0 +1,40 @@
+#
+# This file is part of the LinuxBIOS project.
+#
+# Copyright (C) 2007 Advanced Micro Devices, 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.
+#
+# 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
+#
+
+uses HAVE_INIT_TIMER
+uses HAVE_MOVNTI
+uses CPU_ADDR_BITS
+
+default HAVE_INIT_TIMER=1
+default HAVE_MOVNTI=1
+default CPU_ADDR_BITS=48
+dir /cpu/x86/tsc
+dir /cpu/x86/fpu
+dir /cpu/x86/mmx
+dir /cpu/x86/sse
+dir /cpu/x86/lapic
+dir /cpu/x86/cache
+dir /cpu/x86/pae
+dir /cpu/amd/mtrr
+dir /cpu/amd/quadcore
+dir /cpu/amd/microcode
+driver model_10xxx_init.o
+object update_microcode.o
+object apic_timer.o
+object pstate.o
diff --git a/src/cpu/amd/model_10xxx/apic_timer.c b/src/cpu/amd/model_10xxx/apic_timer.c
new file mode 100644
index 0000000000..46cff61584
--- /dev/null
+++ b/src/cpu/amd/model_10xxx/apic_timer.c
@@ -0,0 +1,55 @@
+/*
+ * This file is part of the LinuxBIOS project.
+ *
+ * Copyright (C) 2007 Advanced Micro Devices, 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.
+ *
+ * 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
+ */
+
+#include <stdint.h>
+#include <delay.h>
+#include <cpu/x86/msr.h>
+#include <cpu/x86/lapic.h>
+
+/* NOTE: We use the APIC TIMER register is to hold flags for AP init during
+ * pre-memory init (ROMCC). Don't use init_timer() and udelay is redirected
+ * to udelay_tsc().
+ */
+
+
+void init_timer(void)
+{
+ /* Set the apic timer to no interrupts and periodic mode */
+ lapic_write(LAPIC_LVTT, (1 << 17)|(1<< 16)|(0 << 12)|(0 << 0));
+
+ /* Set the divider to 1, no divider */
+ lapic_write(LAPIC_TDCR, LAPIC_TDR_DIV_1);
+
+ /* Set the initial counter to 0xffffffff */
+ lapic_write(LAPIC_TMICT, 0xffffffff);
+
+}
+
+
+void udelay(u32 usecs)
+{
+ u32 start, value, ticks;
+ /* Calculate the number of ticks to run, our FSB runs a 200Mhz */
+ ticks = usecs * 200;
+ start = lapic_read(LAPIC_TMCCT);
+ do {
+ value = lapic_read(LAPIC_TMCCT);
+ } while((start - value) < ticks);
+
+}
diff --git a/src/cpu/amd/model_10xxx/fidvid.c b/src/cpu/amd/model_10xxx/fidvid.c
new file mode 100644
index 0000000000..8b2169b32d
--- /dev/null
+++ b/src/cpu/amd/model_10xxx/fidvid.c
@@ -0,0 +1,455 @@
+/*
+ * This file is part of the LinuxBIOS project.
+ *
+ * Copyright (C) 2007 Advanced Micro Devices, 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.
+ *
+ * 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
+ */
+
+#if FAM10_SET_FIDVID == 1
+
+#define FAM10_SET_FIDVID_DEBUG 1
+
+// if we are tight of CAR stack, disable it
+#define FAM10_SET_FIDVID_STORE_AP_APICID_AT_FIRST 1
+
+static inline void print_debug_fv(const char *str, u32 val)
+{
+#if FAM10_SET_FIDVID_DEBUG == 1
+ printk_debug("%s%x\n", str, val);
+#endif
+}
+
+static inline void print_debug_fv_8(const char *str, u8 val)
+{
+#if FAM10_SET_FIDVID_DEBUG == 1
+ printk_debug("%s%02x\n", str, val);
+#endif
+}
+
+static inline void print_debug_fv_64(const char *str, u32 val, u32 val2)
+{
+#if FAM10_SET_FIDVID_DEBUG == 1
+ printk_debug("%s%x%x\n", str, val, val2);
+#endif
+}
+
+
+static void enable_fid_change(u8 fid)
+{
+ u32 dword;
+ u32 nodes;
+ device_t dev;
+ int i;
+
+ nodes = ((pci_read_config32(PCI_DEV(CBB, CDB, 0), 0x60) >> 4) & 7) + 1;
+
+ for(i = 0; i < nodes; i++) {
+ dev = NODE_PCI(i,3);
+ dword = pci_read_config32(dev, 0xd4);
+ dword &= ~0x1F;
+ dword |= (u32) fid & 0x1F;
+ dword |= 1 << 5; // enable
+ pci_write_config32(dev, 0xd4, dword);
+ printk_debug("FID Change Node:%02x, F3xD4: %08x \n", i, dword);
+ }
+}
+
+static void prep_fid_change(void)
+{
+ u32 dword;
+ u32 nodes;
+ device_t dev;
+ int i;
+
+ /* This needs to be run before any Pstate changes are requested */
+
+ nodes = ((pci_read_config32(PCI_DEV(CBB, CDB, 0), 0x60) >> 4) & 7) + 1;
+
+ for(i = 0; i < nodes; i++) {
+ printk_debug("Node:%02x \n", i);
+ dev = NODE_PCI(i,3);
+
+ dword = pci_read_config32(dev, 0xa0);
+ dword &= ~(1<<29);
+ dword |= ((~dword >> 8) & 1) << 29; // SlamVidMode is the inverse to the PviMode
+ dword |= PLLLOCK_DFT_L; /* Force per BKDG */
+ pci_write_config32(dev, 0xa0, dword);
+ printk_debug(" F3xA0: %08x \n", dword);
+
+ dword = pci_read_config32(dev, 0xd8);
+ dword &= ~0x77;
+ dword |= (1<<4) | 6; // VSRampTime, and VSSlamTime
+ dword |= 3 << 24; // ReConDel set to 3 per BKDG
+ pci_write_config32(dev, 0xd8, dword);
+ printk_debug(" F3xD8: %08x \n", dword);
+
+ dword = pci_read_config32(dev, 0xd4);
+ dword &= 0x1F;
+ dword |= 0xC331AF00; // per BKDG
+ pci_write_config32(dev, 0xd4, dword);
+ printk_debug(" F3xD4: %08x \n", dword);
+
+ dword = pci_read_config32(dev, 0xdc);
+ dword |= 0x5 << 12; // NbsynPtrAdj set to 0x5 per BKDG (needs reset)
+ pci_write_config32(dev, 0xdc, dword);
+ printk_debug(" F3xDC: %08x \n", dword);
+
+ // Rev B settings - FIXME: support other revs.
+ dword = 0xA0E641E6;
+ pci_write_config32(dev, 0x84, dword);
+ printk_debug(" F3x84: %08x \n", dword);
+
+ dword = 0xE600A681;
+ pci_write_config32(dev, 0x80, dword);
+ printk_debug(" F3x80: %08x \n", dword);
+
+ }
+}
+
+
+#include "fidvid_common.c"
+
+
+
+static void init_fidvid_ap(u32 bsp_apicid, u32 apicid, u32 nodeid, u32 coreid)
+{
+
+ msr_t msr;
+ device_t dev;
+ u8 vid_max;
+ u8 fid_max;
+ u8 startup_pstate;
+ u8 nb_cof_vid_update;
+ u8 pvimode;
+ u32 reg1fc;
+ u32 dword;
+ u32 send;
+
+ printk_debug("FIDVID on AP: %02x\n", apicid);
+
+ /* Only support single plane system at this time. */
+ /* Steps 1-6 of BIOS NB COF and VID Configuration
+ * for Single-Plane PVI Systems
+ */
+ dev = NODE_PCI(nodeid,3);
+ reg1fc = pci_read_config32(dev, 0x1FC);
+ nb_cof_vid_update = reg1fc & 1;
+ if (nb_cof_vid_update) {
+ /* Get fused settings */
+ dword = pci_read_config32(dev, 0xa0);
+ pvimode = (dword >> 8) & 1;
+
+ vid_max = (reg1fc >> 7) & 0x7F; // per node
+ fid_max = (reg1fc >> 2) & 0x1F; // per system
+
+ if (pvimode) {
+ /* FIXME: support daul plane mode */
+ die("PVImode not supported\n");
+ /* fidmax = vidmax - (reg1fc >> 17) & 0x1F;
+ fidmax = fidmax + (reg1fc >> 14) & 0x03;
+ */
+ }
+
+ } else {
+ /* Use current values */
+ msr = rdmsr(0xc0010071);
+ fid_max = ((msr.hi >> (59-32)) & 0x1f); //max nb fid
+ vid_max = ((msr.hi >> (35-32)) & 0x7f); //max vid
+ }
+
+ /* Note this is the single plane setup. Need to add dual plane path */
+ msr = rdmsr(0xc0010071);
+ startup_pstate = (msr.hi >> (32-32)) & 0x07;
+
+
+ /* Copy startup pstate to P1 and P0 MSRs. Set the maxvid for this node in P0.
+ Then transition to P1 for corex and P0 for core0. */
+ msr = rdmsr(0xC0010064 + startup_pstate);
+ wrmsr(0xC0010065, msr);
+ wrmsr(0xC0010064, msr);
+
+ msr.lo &= ~0xFE000000; // clear nbvid
+ msr.lo |= vid_max << 25;
+ wrmsr(0xC0010064, msr);
+
+ // Transition to P1 for all APs and P0 for core0.
+ msr = rdmsr(0xC0010062);
+ msr.lo = (msr.lo & ~0x07) | 1;
+ wrmsr(0xC0010062, msr);
+
+ // Wait for P1 to set.
+ do {
+ msr = rdmsr(0xC0010063);
+ } while (msr.lo != 1);
+
+ if (coreid == 0) {
+ msr.lo = msr.lo & ~0x07;
+ wrmsr(0xC0010062, msr);
+ // Wait for P0 to set.
+ do {
+ msr = rdmsr(0xC0010063);
+ } while (msr.lo != 0);
+ }
+
+
+ send = (nb_cof_vid_update << 16) | (fid_max << 8);
+ send |= (apicid << 24); // ap apicid
+
+ // Send signal to BSP about this AP max fid
+ // This also indicates this AP is ready for warm reset (if required).
+ lapic_write(LAPIC_MSG_REG, send | 1);
+}
+
+static u32 calc_common_fid(u32 fid_packed, u32 fid_packed_new)
+{
+ u32 fidmax;
+ u32 fidmax_new;
+
+ fidmax = (fid_packed >> 8) & 0xFF;
+
+ fidmax_new = (fid_packed_new >> 8) & 0xFF;
+
+ if(fidmax > fidmax_new) {
+ fidmax = fidmax_new;
+ }
+
+ fid_packed &= 0xFF << 16;
+ fid_packed |= (fidmax << 8);
+ fid_packed |= fid_packed_new & (0xFF << 16); // set nb_cof_vid_update
+
+ return fid_packed;
+}
+
+struct fidvid_st {
+ u32 common_fid;
+};
+
+static void init_fidvid_bsp_stage1(u32 ap_apicid, void *gp )
+{
+ u32 readback = 0;
+ u32 timeout = 1;
+
+ struct fidvid_st *fvp = gp;
+ int loop;
+
+ print_debug_fv("Wait for AP stage 1: ap_apicid = ", ap_apicid);
+
+ loop = 100000;
+ while(--loop > 0) {
+ if(lapic_remote_read(ap_apicid, LAPIC_MSG_REG, &readback) != 0) continue;
+ if((readback & 0x3f) == 1) {
+ timeout = 0;
+ break; //target ap is in stage 1
+ }
+ }
+
+ if(timeout) {
+ print_initcpu8("fidvid_bsp_stage1: time out while reading from ap ", ap_apicid);
+ return;
+ }
+
+ print_debug_fv("\treadback = ", readback);
+
+ fvp->common_fid = calc_common_fid(fvp->common_fid, readback);
+
+ print_debug_fv("\tcommon_fid(packed) = ", fvp->common_fid);
+
+}
+
+
+static void init_fidvid_stage2(u32 apicid, u32 nodeid)
+{
+ msr_t msr;
+ device_t dev;
+ u32 reg1fc;
+ u8 StartupPstate;
+ u8 nbvid;
+ int i;
+
+ /* After warm reset finish the fid/vid setup for all cores. */
+ dev = NODE_PCI(nodeid,3);
+ reg1fc = pci_read_config32(dev, 0x1FC);
+ nbvid = (reg1fc >> 7) & 0x7F;
+
+ if (reg1fc & 0x02) { // NbVidUpdateAll ?
+ for( i = 0; i < 5; i++) {
+ msr = rdmsr(0xC0010064 + i);
+ if ((msr.hi >> 31) & 1) { // PstateEn?
+ msr.lo &= ~(0x7F << 25);
+ msr.lo |= (nbvid & 0x7F) << 25;
+ }
+ }
+ } else {
+ for( i = 0; i < 5; i++) {
+ msr = rdmsr(0xC0010064 + i);
+ if (((msr.hi >> 31) & 1) && (((msr.lo >> 22) & 1) == 0)) { // PstateEn and PDid == 0?
+ msr.lo &= ~(0x7F << 25);
+ msr.lo |= (nbvid & 0x7F) << 25;
+ }
+ }
+ }
+
+ // For each processor in the system, transition all cores to StartupPstate
+ msr = rdmsr(0xC0010071);
+ StartupPstate = msr.hi >> (32-32) & 0x03;
+ msr = rdmsr(0xC0010062);
+ msr.lo = StartupPstate;
+ wrmsr(0xC0010062, msr);
+}
+
+
+#if FAM10_SET_FIDVID_STORE_AP_APICID_AT_FIRST == 1
+struct ap_apicid_st {
+ u32 num;
+ // it could use 256 bytes for 64 node quad core system
+ u8 apicid[NODE_NUMS * 4];
+};
+
+static void store_ap_apicid(unsigned ap_apicid, void *gp)
+{
+ struct ap_apicid_st *p = gp;
+
+ p->apicid[p->num++] = ap_apicid;
+
+}
+#endif
+
+
+static int init_fidvid_bsp(u32 bsp_apicid, u32 nodes)
+{
+#if FAM10_SET_FIDVID_STORE_AP_APICID_AT_FIRST == 1
+ struct ap_apicid_st ap_apicidx;
+ u32 i;
+#endif
+ struct fidvid_st fv;
+ msr_t msr;
+ device_t dev;
+ u8 vid_max;
+ u8 fid_max;
+ u8 startup_pstate;
+ u8 nb_cof_vid_update;
+ u32 reg1fc;
+ u32 dword;
+ u8 pvimode;
+
+ printk_debug("FIDVID on BSP, APIC_id: %02x\n", bsp_apicid);
+
+ /* FIXME: Only support single plane system at this time. */
+ /* Steps 1-6 of BIOS NB COF and VID Configuration
+ * for Single-Plane PVI Systems
+ */
+ dev = NODE_PCI(0,3); // nodeid for the BSP is 0
+ reg1fc = pci_read_config32(dev, 0x1FC);
+ nb_cof_vid_update = reg1fc & 1;
+ if (nb_cof_vid_update) {
+ /* Get fused settings */
+ dword = pci_read_config32(dev, 0xa0);
+ pvimode = (dword >> 8) & 1;
+
+ vid_max = (reg1fc >> 7) & 0x7F; // per node
+ fid_max = (reg1fc >> 2) & 0x1F; // per system
+
+ if (pvimode) {
+ /* FIXME: support daul plane mode */
+ die("PVImode not supported\n");
+ /* fidmax = vidmax - (reg1fc >> 17) & 0x1F;
+ fidmax = fidmax + (reg1fc >> 14) & 0x03;
+ */
+ }
+
+ } else {
+ /* Use current values */
+ msr = rdmsr(0xc0010071);
+ fid_max = ((msr.hi >> (59-32)) & 0x1f); //max nb fid
+ vid_max = ((msr.hi >> (35-32)) & 0x7f); //max vid
+ }
+
+ /* Note this is the single plane setup. Need to add dual plane path */
+ msr = rdmsr(0xc0010071);
+ startup_pstate = (msr.hi >> (32-32)) & 0x07;
+
+
+ /* Copy startup pstate to P1 and P0 MSRs. Set the maxvid for this node in P0.
+ Then transition to P1 for corex and P0 for core0. */
+ msr = rdmsr(0xC0010064 + startup_pstate);
+ wrmsr(0xC0010065, msr);
+ wrmsr(0xC0010064, msr);
+
+ msr.lo &= ~0xFE000000; // clear nbvid
+ msr.lo |= vid_max << 25;
+ wrmsr(0xC0010064, msr);
+
+ // Transition to P1 and then P0 for core0.
+ msr = rdmsr(0xC0010062);
+ msr.lo = (msr.lo & ~0x07) | 1;
+ wrmsr(0xC0010062, msr);
+
+ // Wait for P1 to set.
+ do {
+ msr = rdmsr(0xC0010063);
+ } while (msr.lo != 1);
+
+ msr.lo = msr.lo & ~0x07;
+ wrmsr(0xC0010062, msr);
+ // Wait for P0 to set.
+ do {
+ msr = rdmsr(0xC0010063);
+ } while (msr.lo != 0);
+
+
+ fv.common_fid = (nb_cof_vid_update << 16) | (fid_max << 8) ;
+ print_debug_fv("BSP fid = ", fv.common_fid);
+
+#if FAM10_SET_FIDVID_STORE_AP_APICID_AT_FIRST == 1 && FAM10_SET_FIDVID_CORE0_ONLY == 0
+ /* For all APs (We know the APIC ID of all APs even when the APIC ID
+ is lifted) remote read from AP LAPIC_MSG_REG about max fid.
+ Then calculate the common max fid that can be used for all
+ APs and BSP */
+ ap_apicidx.num = 0;
+
+ for_each_ap(bsp_apicid, FAM10_SET_FIDVID_CORE_RANGE, store_ap_apicid, &ap_apicidx);
+
+ for(i = 0; i < ap_apicidx.num; i++) {
+ init_fidvid_bsp_stage1(ap_apicidx.apicid[i], &fv);
+ }
+#else
+ for_each_ap(bsp_apicid, FAM10_SET_FIDVID_CORE0_ONLY, init_fidvid_bsp_stage1, &fv);
+#endif
+
+ print_debug_fv("common_fid = ", fv.common_fid);
+
+ if (fv.common_fid & ~(0xFF << 16)) { // check nb_cof_vid_update
+
+ // Enable the common fid and other settings.
+ enable_fid_change((fv.common_fid >> 8) & 0x1F);
+
+ // nbfid change need warm reset, so reset at first
+ return 1;
+ }
+
+ return 0; // No FID/VID changes. Don't reset
+}
+static void set_p0(void)
+{
+ msr_t msr;
+
+ // Transition P0 for calling core.
+ msr = rdmsr(0xC0010062);
+ msr.lo = (msr.lo & ~0x07);
+ wrmsr(0xC0010062, msr);
+
+ // Don't bother to wait around for the P state to change.
+}
+#endif
diff --git a/src/cpu/amd/model_10xxx/fidvid_common.c b/src/cpu/amd/model_10xxx/fidvid_common.c
new file mode 100644
index 0000000000..c863334eda
--- /dev/null
+++ b/src/cpu/amd/model_10xxx/fidvid_common.c
@@ -0,0 +1,312 @@
+/*
+ * This file is part of the LinuxBIOS project.
+ *
+ * Copyright (C) 2007 Advanced Micro Devices, 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.
+ *
+ * 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
+ */
+
+
+#include <cpu/x86/tsc.h>
+
+
+static u32 get_vstime(u32 nodeid, u32 slam)
+{
+ u32 val;
+ u32 v;
+ device_t dev;
+
+#if defined(__ROMCC__)
+ dev = NODE_PCI(nodeid, 3);
+#else
+ dev = get_node_pci(nodeid, 3);
+#endif
+
+ val = pci_read_config32(dev, 0xd8);
+
+ val >>= slam?0:4;
+ val &= 7;
+
+ switch (val) {
+ case 4: v = 60; break;
+ case 5: v = 100; break;
+ case 6: v = 200; break;
+ case 7: v = 500; break;
+ default:
+ v = (val+1)*10; // in us
+ }
+
+ return v;
+}
+
+static void udelay_tsc(u32 us)
+{
+ /* Use TSC to delay because it is fixed, ie. it will not changed with p-states.
+ * Also, We use the APIC TIMER register is to hold flags for AP init.
+ */
+ u32 dword;
+ tsc_t tsc, tsc1, tscd;
+ u32 d = 0x00000200; //800Mhz or 200Mhz or 1.6G or get the NBFID at first
+ u32 dn = 0x1000000/2; // howmany us need to use hi
+
+ tscd.hi = us/dn;
+ tscd.lo = (us - tscd.hi * dn) * d;
+
+ tsc1 = rdtsc();
+ dword = tsc1.lo + tscd.lo;
+ if((dword<tsc1.lo) || (dword<tscd.lo)) {
+ tsc1.hi++;
+ }
+ tsc1.lo = dword;
+ tsc1.hi+= tscd.hi;
+
+ do {
+ tsc = rdtsc();
+ } while ((tsc.hi>tsc1.hi) || ((tsc.hi==tsc1.hi) && (tsc.lo>tsc1.lo)));
+
+}
+
+#ifdef __ROMCC__
+void udelay(u32 usecs)
+{
+ udelay_tsc(usecs);
+}
+#endif
+
+static u32 set_vid(u32 newvid, u32 bit_offset, u32 nodeid, u32 coreid)
+{
+ u32 val;
+ msr_t msr;
+ u32 curvid;
+ u32 slam;
+ u32 delay;
+ u32 count = 3;
+ device_t dev;
+
+ msr = rdmsr(0xc0010071);//status
+ curvid = (msr.lo >> bit_offset) & 0x7f; // seven bits
+
+ if(newvid == curvid) return curvid;
+
+#if defined(__ROMCC__)
+ dev = NODE_PCI(nodeid, 3);
+#else
+ dev = get_node_pci(nodeid, 3);
+#endif
+
+ val = pci_read_config32(dev, 0xa0);
+
+ slam = (val >> 29) & 1;
+ delay = get_vstime(nodeid, slam);
+
+ if(!slam) {
+ if(curvid>newvid) {
+ count = (curvid - newvid) * 2;
+ } else {
+ count = (newvid - curvid) * 2;
+ }
+ }
+
+ while(count-->0) {
+ if(slam) {
+ curvid = newvid;
+ }
+ else { //ramp
+ if(curvid>newvid) {
+ curvid--;
+ } else {
+ curvid++;
+ }
+ }
+
+ msr = rdmsr(0xc0010070); //control
+ msr.lo &= ~(0x7f<<bit_offset);
+ msr.lo |= (curvid<<bit_offset);
+ wrmsr(0xc0010070, msr); // how about all copys, APIC or PCI conf space?
+
+ udelay_tsc(delay);
+
+ msr = rdmsr(0xc0010071);//status
+ curvid = (msr.lo >> bit_offset) & 0x7f; // seven bits
+
+ if(curvid == newvid) break;
+
+ }
+
+ return curvid;
+}
+
+
+static u32 set_nb_vid(u32 newvid, u32 nodeid, u32 coreid)
+{
+ return set_vid(newvid, 25, nodeid, coreid);
+}
+
+
+static u32 set_core_vid(u32 newvid, u32 nodeid, u32 coreid)
+{
+ return set_vid(newvid, 9, nodeid, coreid);
+}
+
+
+static unsigned set_cof(u32 val, u32 mask, u32 nodeid, u32 coreid)
+{
+ msr_t msr;
+ int count = 3;
+
+ val &= mask;
+
+ // FIXME: What is count for? Why 3 times? What about node and core id?
+ while(count-- > 0) {
+
+ msr = rdmsr(0xc0010071);
+ msr.lo &= mask;
+ if(msr.lo == val) break;
+
+ msr = rdmsr(0xc0010070);
+ msr.lo &= ~(mask);
+ msr.lo |= val;
+ wrmsr(0xc0010070, msr);
+ }
+
+ return msr.lo;
+}
+
+static u32 set_core_cof(u32 fid, u32 did, u32 nodeid, u32 coreid)
+{
+ u32 val;
+ u32 mask;
+
+ mask = (7<<6) | 0x3f;
+ val = ((did & 7)<<6) | (fid & 0x3f);
+
+ return set_cof(val, mask, nodeid, coreid);
+
+}
+
+
+static u32 set_nb_cof(u32 did, u32 nodeid, u32 coreid) // fid need warmreset
+{
+ u32 val;
+ u32 mask;
+
+ mask = 1<<22;
+ val = (did & 1)<<22;
+
+ return set_cof(val, mask, nodeid, coreid);
+
+}
+
+
+/* set vid and cof for core and nb after warm reset is not started by BIOS */
+static void set_core_nb_max_pstate_after_other_warm_reset(u32 nodeid, u32 coreid) // P0
+{
+ msr_t msr;
+ u32 val;
+ u32 vid;
+ u32 mask;
+ u32 did;
+ device_t dev;
+
+ msr = rdmsr(0xc0010064);
+
+#if defined(__ROMCC__)
+ dev = NODE_PCI(nodeid, 3);
+#else
+ dev = get_node_pci(nodeid, 3);
+#endif
+
+ val = pci_read_config32(dev, 0xa0);
+ if((val>>8) & 1) { // PVI
+ vid = (msr.lo >> 25) & 0x7f;
+ } else { //SVI
+ vid = (msr.lo >> 9) & 0x7f;
+ }
+ set_core_vid(vid, nodeid, coreid);
+
+ mask = (0x7<<6) | 0x3f;
+ val = msr.lo & mask;
+ set_cof(val, mask, nodeid, coreid);
+
+ //set nb cof and vid
+ did = (msr.lo >> 22) & 1;
+ vid = (msr.lo >> 25) & 0x7f;
+ if(did) {
+ set_nb_cof(did, nodeid, coreid);
+ set_nb_vid(vid, nodeid, coreid);
+ } else {
+ set_nb_vid(vid, nodeid, coreid);
+ set_nb_cof(did, nodeid, coreid);
+ }
+
+ //set the p state
+ msr.hi = 0;
+ msr.lo = 0;
+ wrmsr(0xc0010062, msr);
+
+}
+
+
+/* set vid and cof for core and nb after warm reset is not started by BIOS */
+static void set_core_nb_min_pstate_after_other_warm_reset(u32 nodeid, u32 coreid) // Px
+{
+ msr_t msr;
+ u32 val;
+ u32 vid;
+ u32 mask;
+ u32 did;
+ u32 pstate;
+ device_t dev;
+
+#if defined(__ROMCC__)
+ dev = NODE_PCI(nodeid, 3);
+#else
+ dev = get_node_pci(nodeid, 3);
+#endif
+
+
+ val = pci_read_config32(dev, 0xdc); //PstateMaxVal
+
+ pstate = (val >> 8) & 0x7;
+
+ msr = rdmsr(0xc0010064 + pstate);
+
+ mask = (7<<6) | 0x3f;
+ val = msr.lo & mask;
+ set_cof(val, mask, nodeid, coreid);
+
+ val = pci_read_config32(dev, 0xa0);
+ if((val>>8) & 1) { // PVI
+ vid = (msr.lo>>25) & 0x7f;
+ } else { //SVI
+ vid = (msr.lo>>9) & 0x7f;
+ }
+ set_core_vid(vid, nodeid, coreid);
+
+ //set nb cof and vid
+ did = (msr.lo >> 22) & 1;
+ vid = (msr.lo >> 25) & 0x7f;
+ if(did) {
+ set_nb_cof(did, nodeid, coreid);
+ set_nb_vid(vid, nodeid, coreid);
+ } else {
+ set_nb_vid(vid, nodeid, coreid);
+ set_nb_cof(did, nodeid, coreid);
+ }
+
+ //set the p state
+ msr.hi = 0;
+ msr.lo = pstate;
+ wrmsr(0xc0010062, msr);
+}
diff --git a/src/cpu/amd/model_10xxx/init_cpus.c b/src/cpu/amd/model_10xxx/init_cpus.c
new file mode 100644
index 0000000000..8a0513cf18
--- /dev/null
+++ b/src/cpu/amd/model_10xxx/init_cpus.c
@@ -0,0 +1,553 @@
+/*
+ * This file is part of the LinuxBIOS project.
+ *
+ * Copyright (C) 2007 Advanced Micro Devices, 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.
+ *
+ * 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
+ */
+
+
+//it takes the ENABLE_APIC_EXT_ID and APIC_ID_OFFSET and LIFT_BSP_APIC_ID
+#ifndef FAM10_SET_FIDVID
+ #define FAM10_SET_FIDVID 1
+#endif
+
+#ifndef FAM10_SET_FIDVID_CORE0_ONLY
+ /* MSR FIDVID_CTL and FIDVID_STATUS are shared by cores,
+ Need to do every AP to set common FID/VID*/
+ #define FAM10_SET_FIDVID_CORE0_ONLY 0
+#endif
+
+
+static inline void print_initcpu8 (const char *strval, u8 val)
+{
+ printk_debug("%s%02x\n", strval, val);
+}
+
+static inline void print_initcpu8_nocr (const char *strval, u8 val)
+{
+ printk_debug("%s%02x", strval, val);
+}
+
+
+static inline void print_initcpu16 (const char *strval, u16 val)
+{
+ printk_debug("%s%04x\n", strval, val);
+}
+
+
+static inline void print_initcpu(const char *strval, u32 val)
+{
+ printk_debug("%s%08x\n", strval, val);
+}
+
+
+static void prep_fid_change(void);
+static void init_fidvid_stage2(u32 apicid, u32 nodeid);
+
+#if PCI_IO_CFG_EXT == 1
+static inline void set_EnableCf8ExtCfg(void)
+{
+ // set the NB_CFG[46]=1;
+ msr_t msr;
+ msr = rdmsr(NB_CFG_MSR);
+ // EnableCf8ExtCfg: We need that to access PCI_IO_CFG_EXT 4K range
+ msr.hi |= (1<<(46-32));
+ wrmsr(NB_CFG_MSR, msr);
+}
+#else
+static inline void set_EnableCf8ExtCfg(void) { }
+#endif
+
+
+/*[39:8] */
+#define PCI_MMIO_BASE 0xfe000000
+/* because we will use gs to store hi, so need to make sure lo can start
+ from 0, So PCI_MMIO_BASE & 0x00ffffff should be equal to 0*/
+
+static inline void set_pci_mmio_conf_reg(void)
+{
+#if MMCONF_SUPPORT
+ msr_t msr;
+ msr = rdmsr(0xc0010058);
+ msr.lo &= ~(0xfff00000 | (0xf << 2));
+ // 256 bus per segment, MMIO reg will be 4G , enable MMIO Config space
+ msr.lo |= ((8+PCI_BUS_SEGN_BITS) << 2) | (1 << 0);
+ msr.hi &= ~(0x0000ffff);
+ msr.hi |= (PCI_MMIO_BASE >> (32-8));
+ wrmsr(0xc0010058, msr); // MMIO Config Base Address Reg
+
+ //mtrr for that range?
+// set_var_mtrr_x(7, PCI_MMIO_BASE<<8, PCI_MMIO_BASE>>(32-8), 0x00000000, 0x01, MTRR_TYPE_UNCACHEABLE);
+
+ set_wrap32dis();
+
+ msr.hi = (PCI_MMIO_BASE >> (32-8));
+ msr.lo = 0;
+ wrmsr(0xc0000101, msr); //GS_Base Reg
+
+
+
+#endif
+}
+
+
+typedef void (*process_ap_t)(u32 apicid, void *gp);
+
+//core_range = 0 : all cores
+//core range = 1 : core 0 only
+//core range = 2 : cores other than core0
+
+static void for_each_ap(u32 bsp_apicid, u32 core_range,
+ process_ap_t process_ap, void *gp)
+{
+ // here assume the OS don't change our apicid
+ u32 ap_apicid;
+
+ u32 nodes;
+ u32 siblings;
+ u32 disable_siblings;
+ u32 cores_found;
+ u32 nb_cfg_54;
+ int i,j;
+ u32 ApicIdCoreIdSize;
+
+ /* get_nodes define in ht_wrapper.c */
+ nodes = get_nodes();
+
+ disable_siblings = !CONFIG_LOGICAL_CPUS;
+
+#if CONFIG_LOGICAL_CPUS == 1
+ if(read_option(CMOS_VSTART_quad_core, CMOS_VLEN_quad_core, 0) != 0) { // 0 mean quad core
+ disable_siblings = 1;
+ }
+#endif
+
+ /* Assume that all node are same stepping, otherwise we can use use
+ nb_cfg_54 from bsp for all nodes */
+ nb_cfg_54 = read_nb_cfg_54();
+
+ ApicIdCoreIdSize = (cpuid_ecx(0x80000008) >> 12 & 0xf);
+ if(ApicIdCoreIdSize) {
+ siblings = ((1 << ApicIdCoreIdSize) - 1);
+ } else {
+ siblings = 3; //quad core
+ }
+
+ for (i = 0; i < nodes; i++) {
+ cores_found = get_core_num_in_bsp(i);
+
+ u32 jstart, jend;
+
+ if (core_range == 2) {
+ jstart = 1;
+ } else {
+ jstart = 0;
+ }
+
+ if (disable_siblings || (core_range==1)) {
+ jend = 0;
+ } else {
+ jend = cores_found;
+ }
+
+
+ for (j = jstart; j <= jend; j++) {
+ ap_apicid = i * (nb_cfg_54 ? (siblings + 1):1) + j * (nb_cfg_54 ? 1:64);
+
+ #if (ENABLE_APIC_EXT_ID == 1) && (APIC_ID_OFFSET > 0)
+ #if LIFT_BSP_APIC_ID == 0
+ if( (i != 0) || (j != 0)) /* except bsp */
+ #endif
+ ap_apicid += APIC_ID_OFFSET;
+ #endif
+
+ if(ap_apicid == bsp_apicid) continue;
+
+ process_ap(ap_apicid, gp);
+
+ }
+ }
+}
+
+/* FIXME: Duplicate of what is in lapic.h? */
+static inline int lapic_remote_read(int apicid, int reg, u32 *pvalue)
+{
+ int timeout;
+ u32 status;
+ int result;
+ lapic_wait_icr_idle();
+ lapic_write(LAPIC_ICR2, SET_LAPIC_DEST_FIELD(apicid));
+ lapic_write(LAPIC_ICR, LAPIC_DM_REMRD | (reg >> 4));
+ timeout = 0;
+
+ do {
+ status = lapic_read(LAPIC_ICR) & LAPIC_ICR_BUSY;
+ } while (status == LAPIC_ICR_BUSY && timeout++ < 1000);
+
+ timeout = 0;
+ do {
+ status = lapic_read(LAPIC_ICR) & LAPIC_ICR_RR_MASK;
+ } while (status == LAPIC_ICR_RR_INPROG && timeout++ < 1000);
+
+ result = -1;
+
+ if (status == LAPIC_ICR_RR_VALID) {
+ *pvalue = lapic_read(LAPIC_RRR);
+ result = 0;
+ }
+ return result;
+}
+
+
+/* Use the LAPIC timer count register to hold each cores init status */
+#define LAPIC_MSG_REG 0x380
+
+
+#if FAM10_SET_FIDVID == 1
+static void init_fidvid_ap(u32 bsp_apicid, u32 apicid, u32 nodeid, u32 coreid);
+#endif
+
+static inline __attribute__((always_inline)) void print_apicid_nodeid_coreid(u32 apicid, struct node_core_id id, const char *str)
+{
+ printk_debug("%s --- { APICID = %02x NODEID = %02x COREID = %02x} ---\n", str, apicid, id.nodeid, id.coreid);
+}
+
+
+static unsigned wait_cpu_state(u32 apicid, u32 state)
+{
+ u32 readback = 0;
+ u32 timeout = 1;
+ int loop = 4000000;
+ while (--loop > 0) {
+ if (lapic_remote_read(apicid, LAPIC_MSG_REG, &readback) != 0) continue;
+ if ((readback & 0x3f) == state) {
+ timeout = 0;
+ break; //target cpu is in stage started
+ }
+ }
+ if (timeout) {
+ if (readback) {
+ timeout = readback;
+ }
+ }
+
+ return timeout;
+}
+
+
+static void wait_ap_started(u32 ap_apicid, void *gp )
+{
+ u32 timeout;
+ timeout = wait_cpu_state(ap_apicid, 0x13); // started
+ if(timeout) {
+ print_initcpu8_nocr("* AP ", ap_apicid);
+ print_initcpu(" didn't start timeout:", timeout);
+ }
+ else {
+ print_initcpu8_nocr("AP started: ", ap_apicid);
+ }
+}
+
+
+static void wait_all_aps_started(u32 bsp_apicid)
+{
+ for_each_ap(bsp_apicid, 0 , wait_ap_started, (void *)0);
+}
+
+
+static void wait_all_other_cores_started(u32 bsp_apicid)
+{
+ // all aps other than core0
+ print_debug("started ap apicid: ");
+ for_each_ap(bsp_apicid, 2 , wait_ap_started, (void *)0);
+ print_debug("\n");
+}
+
+
+static void allow_all_aps_stop(u32 bsp_apicid)
+{
+ /* Called by the BSP to indicate AP can stop */
+
+ /* FIXME Do APs use this?
+ Looks like wait_till_sysinfo_in_ram is used instead. */
+
+ // allow aps to stop use 6 bits for state
+ lapic_write(LAPIC_MSG_REG, (bsp_apicid << 24) | 0x14);
+}
+
+
+static void STOP_CAR_AND_CPU()
+{
+ disable_cache_as_ram(); // inline
+ stop_this_cpu();
+}
+
+
+#ifndef MEM_TRAIN_SEQ
+#define MEM_TRAIN_SEQ 0
+#endif
+
+#if RAMINIT_SYSINFO == 1
+static u32 init_cpus(u32 cpu_init_detectedx ,struct sys_info *sysinfo)
+#else
+static u32 init_cpus(u32 cpu_init_detectedx)
+#endif
+{
+ u32 bsp_apicid = 0;
+ u32 apicid;
+ struct node_core_id id;
+
+ /*
+ * already set early mtrr in cache_as_ram.inc
+ */
+
+ /* enable access pci conf via mmio*/
+ set_pci_mmio_conf_reg();
+
+ /* that is from initial apicid, we need nodeid and coreid
+ later */
+ id = get_node_core_id_x();
+
+ /* NB_CFG MSR is shared between cores, so we need make sure
+ core0 is done at first --- use wait_all_core0_started */
+ if(id.coreid == 0) {
+ set_apicid_cpuid_lo(); /* only set it on core0 */
+ set_EnableCf8ExtCfg(); /* only set it on core0 */
+ #if (ENABLE_APIC_EXT_ID == 1)
+ enable_apic_ext_id(id.nodeid);
+ #endif
+ }
+
+ enable_lapic();
+
+
+#if (ENABLE_APIC_EXT_ID == 1) && (APIC_ID_OFFSET > 0)
+ u32 initial_apicid = get_initial_apicid();
+
+ #if LIFT_BSP_APIC_ID == 0
+ if( initial_apicid != 0 ) // other than bsp
+ #endif
+ {
+ /* use initial apic id to lift it */
+ u32 dword = lapic_read(LAPIC_ID);
+ dword &= ~(0xff << 24);
+ dword |= (((initial_apicid + APIC_ID_OFFSET) & 0xff) << 24);
+
+ lapic_write(LAPIC_ID, dword);
+ }
+
+ #if LIFT_BSP_APIC_ID == 1
+ bsp_apicid += APIC_ID_OFFSET;
+ #endif
+
+#endif
+
+ /* get the apicid, it may be lifted already */
+ apicid = lapicid();
+
+ // show our apicid, nodeid, and coreid
+ if( id.coreid==0 ) {
+ if (id.nodeid!=0) //all core0 except bsp
+ print_apicid_nodeid_coreid(apicid, id, " core0: ");
+ }
+ else { //all other cores
+ print_apicid_nodeid_coreid(apicid, id, " corex: ");
+ }
+
+
+ if (cpu_init_detectedx) {
+ print_apicid_nodeid_coreid(apicid, id, "\n\n\nINIT detected from ");
+ print_debug("\nIssuing SOFT_RESET...\n");
+ soft_reset();
+ }
+
+ if(id.coreid == 0) {
+ if(!(warm_reset_detect(id.nodeid))) //FIXME: INIT is checked above but check for more resets?
+ distinguish_cpu_resets(id.nodeid); // Also indicates we are started
+ }
+
+ // Mark the core as started.
+ lapic_write(LAPIC_MSG_REG, (apicid << 24) | 0x13);
+
+
+ if(apicid != bsp_apicid) {
+#if FAM10_SET_FIDVID == 1
+ #if (CONFIG_LOGICAL_CPUS == 1) && (FAM10_SET_FIDVID_CORE0_ONLY == 1)
+ // Run on all AP for proper FID/VID setup.
+ if(id.coreid == 0 ) // only need set fid for core0
+ #endif
+ {
+ // check warm(bios) reset to call stage2 otherwise do stage1
+ if (warm_reset_detect(id.nodeid)) {
+ printk_debug("init_fidvid_stage2 apicid: %02x\n", apicid);
+ init_fidvid_stage2(apicid, id.nodeid);
+ } else {
+ printk_debug("init_fidvid_ap(stage1) apicid: %02x\n", apicid);
+ init_fidvid_ap(bsp_apicid, apicid, id.nodeid, id.coreid);
+ }
+ }
+#endif
+
+ /* AP is ready, Wait for the BSP to get memory configured */
+ /* FIXME: many cores spinning on node0 pci register seems to be bad.
+ * Why do we need to wait? These APs are just going to go sit in a hlt.
+ */
+ //wait_till_sysinfo_in_ram();
+
+ set_init_ram_access();
+
+ STOP_CAR_AND_CPU();
+ printk_debug("\nAP %02x should be halted but you are reading this....\n", apicid);
+ }
+
+ return bsp_apicid;
+}
+
+
+static u32 is_core0_started(u32 nodeid)
+{
+ u32 htic;
+ device_t device;
+ device = NODE_PCI(nodeid, 0);
+ htic = pci_read_config32(device, HT_INIT_CONTROL);
+ htic &= HTIC_ColdR_Detect;
+ return htic;
+}
+
+
+static void wait_all_core0_started(void)
+{
+ /* When core0 is started, it will distingush_cpu_resets
+ . So wait for that to finish */
+ u32 i;
+ u32 nodes = get_nodes();
+
+ printk_debug("Wait all core0s started \n");
+ for(i=1;i<nodes;i++) { // skip bsp, because it is running on bsp
+ while(!is_core0_started(i)) {}
+ print_initcpu8(" Core0 started on node: ", i);
+ }
+ printk_debug("Wait all core0s started done\n");
+}
+#if CONFIG_MAX_PHYSICAL_CPUS > 1
+/**
+ * void start_node(u32 node)
+ *
+ * start the core0 in node, so it can generate HT packet to feature code.
+ *
+ * This function starts the AP nodes core0s. wait_all_core0_started() in
+ * cache_as_ram_auto.c waits for all the AP to be finished before continuing
+ * system init.
+ */
+static void start_node(u8 node)
+{
+ u32 val;
+
+ /* Enable routing table */
+ printk_debug("Start node %02x", node);
+
+#if CAR_FAM10 == 1
+ /* For CAR_FAM10 support, we need to set Dram base/limit for the new node */
+ pci_write_config32(NODE_MP(node), 0x44, 0);
+ pci_write_config32(NODE_MP(node), 0x40, 3);
+#endif
+
+ /* Allow APs to make requests (ROM fetch) */
+ val=pci_read_config32(NODE_HT(node), 0x6c);
+ val &= ~(1 << 1);
+ pci_write_config32(NODE_HT(node), 0x6c, val);
+
+ printk_debug(" done.\n");
+}
+
+
+/**
+ * static void setup_remote_node(u32 node)
+ *
+ * Copy the BSP Adress Map to each AP.
+ */
+static void setup_remote_node(u8 node)
+{
+ /* There registers can be used with F1x114_x Address Map at the
+ same time, So must set them even 32 node */
+ static const u16 pci_reg[] = {
+ /* DRAM Base/Limits Registers */
+ 0x44, 0x4c, 0x54, 0x5c, 0x64, 0x6c, 0x74, 0x7c,
+ 0x40, 0x48, 0x50, 0x58, 0x60, 0x68, 0x70, 0x78,
+ 0x144, 0x14c, 0x154, 0x15c, 0x164, 0x16c, 0x174, 0x17c,
+ 0x140, 0x148, 0x150, 0x158, 0x160, 0x168, 0x170, 0x178,
+ /* MMIO Base/Limits Registers */
+ 0x84, 0x8c, 0x94, 0x9c, 0xa4, 0xac, 0xb4, 0xbc,
+ 0x80, 0x88, 0x90, 0x98, 0xa0, 0xa8, 0xb0, 0xb8,
+ /* IO Base/Limits Registers */
+ 0xc4, 0xcc, 0xd4, 0xdc,
+ 0xc0, 0xc8, 0xd0, 0xd8,
+ /* Configuration Map Registers */
+ 0xe0, 0xe4, 0xe8, 0xec,
+ };
+ u16 i;
+
+ printk_debug("setup_remote_node: %02x", node);
+
+ /* copy the default resource map from node 0 */
+ for(i = 0; i < sizeof(pci_reg)/sizeof(pci_reg[0]); i++) {
+ u32 value;
+ u16 reg;
+ reg = pci_reg[i];
+ value = pci_read_config32(NODE_MP(0), reg);
+ pci_write_config32(NODE_MP(node), reg, value);
+
+ }
+ printk_debug(" done\n");
+}
+#endif
+/**
+ * finalize_node_setup()
+ *
+ * Do any additional post HT init
+ *
+ * This could really be moved to cache_as_ram_auto.c since it really isn't HT init.
+ */
+void finalize_node_setup(struct sys_info *sysinfo)
+{
+ u8 i;
+ u8 nodes = get_nodes();
+ u32 reg;
+
+#if RAMINIT_SYSINFO == 1
+ /* read Node0 F0_0x64 bit [8:10] to find out SbLink # */
+ reg = pci_read_config32(NODE_HT(0), 0x64);
+ sysinfo->sblk = (reg>>8) & 7;
+ sysinfo->sbbusn = 0;
+ sysinfo->nodes = nodes;
+ sysinfo->sbdn = get_sbdn(sysinfo->sbbusn);
+#endif
+
+ setup_link_trans_cntrl();
+
+#if FAM10_SET_FIDVID == 1
+ // Prep each node for FID/VID setup.
+ prep_fid_change();
+#endif
+
+#if CONFIG_MAX_PHYSICAL_CPUS > 1
+ /* Skip the BSP, start at node 1 */
+ for(i=1; i<nodes; i++) {
+ setup_remote_node(i);
+ start_node(i);
+ }
+#endif
+}
+
diff --git a/src/cpu/amd/model_10xxx/mc_patch_01000018.h b/src/cpu/amd/model_10xxx/mc_patch_01000018.h
new file mode 100644
index 0000000000..eebe89b92b
--- /dev/null
+++ b/src/cpu/amd/model_10xxx/mc_patch_01000018.h
@@ -0,0 +1,163 @@
+/*
+ ============================================================
+ (c) Advanced Micro Devices, Inc., 2004-2005
+
+ The enclosed microcode is intended to be used with AMD
+ Microprocessors. You may copy, view and install the
+ enclosed microcode only for development and deployment of
+ firmware, BIOS, or operating system code for computer
+ systems that contain AMD processors. You are not
+ authorized to use the enclosed microcode for any other
+ purpose.
+
+ THE MICROCODE IS PROVIDED "AS IS" WITHOUT ANY EXPRESS OR
+ IMPLIED WARRANTY OF ANY KIND, INCLUDING BUT NOT LIMITED TO
+ WARRANTIES OF MERCHANTABILITY, NON- INFRINGEMENT,
+ TITLE,FITNESS FOR ANY PARTICULAR PURPOSE, OR WARRANTIES
+ ARISING FROM CONDUCT, COURSE OF DEALING, OR USAGE OF TRADE.
+ AMD does not assume any responsibility for any errors which
+ may appear in this microcode or any other related
+ information provided to you by AMD, or result from use of
+ this microcode. AMD is not obligated to furnish, support,
+ or make any further information, software, technical
+ information, know-how, or show-how available related to this
+ microcode.
+
+ The microcode is provided with "RESTRICTED RIGHTS." Use,
+ duplication, or disclosure by the U.S. Government is subject
+ to the restrictions as set forth in FAR 52.227-14 and
+ DFAR252.227-7013, et seq., or its successor. Use of the
+ microcode by the U.S. Government constitutes
+ acknowledgement of AMD's proprietary rights in them.
+ ============================================================
+*/
+
+0x07, 0x20, 0x08, 0x02, 0x18, 0x00, 0x00, 0x01, 0x00, 0x80, 0x20, 0x00,
+0x66, 0x70, 0x30, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x10, 0x00, 0x00, 0x00, 0xaa, 0xaa, 0xaa, 0x44, 0x06, 0x00, 0x00,
+0xff, 0xff, 0xff, 0xff, 0xa4, 0x06, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
+0x72, 0x09, 0x00, 0x00, 0x70, 0x09, 0x00, 0x00, 0x9b, 0x0b, 0x00, 0x00,
+0xff, 0xff, 0xff, 0xff, 0xff, 0x81, 0x7f, 0x00, 0xc3, 0x3f, 0x80, 0x37,
+0xfc, 0x07, 0xfe, 0x01, 0x0d, 0xff, 0x00, 0xfe, 0xf0, 0x1f, 0xf8, 0x07,
+0x37, 0xfc, 0x03, 0xf8, 0xc0, 0xff, 0xf7, 0x00, 0x80, 0xff, 0xc0, 0x3f,
+0x9b, 0xe1, 0x1f, 0xc0, 0x00, 0xfe, 0x03, 0xff, 0xff, 0x86, 0x7f, 0x00,
+0x03, 0xf8, 0x0f, 0xfc, 0xfc, 0x1b, 0xfe, 0x01, 0x00, 0x40, 0x37, 0x6b,
+0xff, 0xfb, 0xfd, 0xff, 0x57, 0x7d, 0xf0, 0xcd, 0xff, 0x1f, 0xb7, 0xfe,
+0xc0, 0xcf, 0xc3, 0x3f, 0xff, 0x01, 0xff, 0xf7, 0x00, 0x02, 0x07, 0xff,
+0x35, 0x00, 0x90, 0x8b, 0xf0, 0x0f, 0xe0, 0x3f, 0x07, 0xf0, 0x6f, 0xf8,
+0xc0, 0x3f, 0x80, 0xff, 0x1f, 0xc0, 0xbf, 0xe1, 0x03, 0xff, 0x00, 0xfe,
+0x7f, 0x00, 0xff, 0x86, 0xff, 0x1e, 0x00, 0xf8, 0x1f, 0xf8, 0x07, 0xf0,
+0xfc, 0x03, 0x78, 0x33, 0x7f, 0xe0, 0x1f, 0xc0, 0xf0, 0x0f, 0xe0, 0xdf,
+0xff, 0x81, 0x7f, 0x00, 0xc3, 0x3f, 0x80, 0x7f, 0xfc, 0x7f, 0x0f, 0x00,
+0xf8, 0x0f, 0xfc, 0x03, 0x19, 0xfe, 0x01, 0xbc, 0xe0, 0x3f, 0xf0, 0x0f,
+0x6f, 0xf8, 0x07, 0xf0, 0x80, 0xff, 0xc0, 0x3f, 0xbf, 0xe1, 0x1f, 0xc0,
+0x00, 0xb4, 0xb2, 0x06, 0xbf, 0xdf, 0xff, 0xff, 0xd5, 0x07, 0xdf, 0x7c,
+0x67, 0xb2, 0xe7, 0xf9, 0xfc, 0x3c, 0xfc, 0x03, 0x1f, 0xf0, 0x7f, 0xff,
+0x20, 0x70, 0xf0, 0x0f, 0x03, 0x00, 0xed, 0x58, 0xff, 0x00, 0xfe, 0x03,
+0x00, 0xff, 0x86, 0x7f, 0xfc, 0x03, 0xf8, 0x0f, 0x01, 0xfc, 0x1b, 0xfe,
+0xf0, 0x0f, 0xe0, 0x3f, 0x07, 0xf0, 0x6f, 0xf8, 0xef, 0x01, 0x80, 0xff,
+0xff, 0xff, 0x29, 0x2a, 0x5f, 0xd0, 0xc1, 0xc3, 0xff, 0xff, 0xb3, 0xdd,
+0xff, 0x7e, 0xfd, 0x0f, 0x1f, 0xf8, 0x57, 0xf6, 0xbc, 0x63, 0x2d, 0x3c,
+0x03, 0xd4, 0x00, 0x40, 0xff, 0xd7, 0xbf, 0xb7, 0xe1, 0xdf, 0xeb, 0xe7,
+0xef, 0xff, 0xff, 0x57, 0x87, 0x7f, 0xbf, 0xea, 0xfa, 0x0f, 0xfc, 0x03,
+0x1f, 0xbe, 0xf5, 0xfc, 0x80, 0x02, 0x4b, 0x00, 0x8a, 0xca, 0xff, 0x7f,
+0xf0, 0xf0, 0x17, 0x74, 0x6c, 0xf7, 0xff, 0xff, 0xff, 0xc3, 0xbf, 0x5f,
+0x95, 0xfd, 0x07, 0xfe, 0x0b, 0x0f, 0xef, 0x58, 0x00, 0xd0, 0x00, 0x35,
+0xab, 0xea, 0xff, 0xfb, 0x05, 0x78, 0xf4, 0x67, 0xff, 0xd5, 0xfb, 0xff,
+0xaf, 0xfa, 0xe1, 0xdf, 0xff, 0x80, 0xfe, 0x03, 0x3d, 0xff, 0x87, 0x6f,
+0x12, 0x00, 0xa0, 0xc0, 0xff, 0x0f, 0xf0, 0xaf, 0x03, 0xf8, 0x3f, 0xfc,
+0xff, 0x2f, 0xc0, 0xff, 0x2d, 0x65, 0xff, 0xf0, 0x0d, 0xfe, 0x04, 0xb6,
+0x2f, 0x03, 0xad, 0xc3, 0x51, 0x0d, 0x00, 0x8c, 0xff, 0xfe, 0x03, 0xf8,
+0xff, 0xb9, 0xc9, 0x19, 0x3f, 0xf0, 0x0f, 0xe0, 0xf8, 0x07, 0xf0, 0x6f,
+0xff, 0xc0, 0x3f, 0x80, 0xe1, 0x1f, 0xc0, 0xbf, 0xf2, 0xb9, 0x06, 0x00,
+0xfc, 0x07, 0xfe, 0x01, 0x0d, 0xff, 0x00, 0xfe, 0xf0, 0x1f, 0xf8, 0x07,
+0x37, 0xfc, 0x03, 0xf8, 0xc0, 0x7f, 0xe0, 0x1f, 0xdf, 0xf0, 0x0f, 0xe0,
+0x00, 0xff, 0xdf, 0x03, 0x00, 0xfe, 0x03, 0xff, 0xff, 0x86, 0x7f, 0x00,
+0x03, 0xf8, 0x0f, 0xfc, 0xfc, 0x1b, 0xfe, 0x01, 0x0f, 0xe0, 0x3f, 0xf0,
+0xf0, 0x6f, 0xf8, 0x07, 0x01, 0x80, 0xff, 0xef, 0x7f, 0x00, 0xff, 0x81,
+0x80, 0x7f, 0xc3, 0x3f, 0xfe, 0x01, 0xfc, 0x07, 0x00, 0xfe, 0x0d, 0xff,
+0xf8, 0x07, 0xf0, 0x1f, 0x03, 0xf8, 0x37, 0xfc, 0xd7, 0x00, 0x40, 0x34,
+0xc0, 0x3f, 0x80, 0xff, 0x1f, 0xc0, 0xbf, 0xe1, 0x03, 0xff, 0x00, 0xfe,
+0x7f, 0x00, 0xff, 0x86, 0x0f, 0xfc, 0x03, 0xf8, 0xfe, 0x01, 0xfc, 0x1b,
+0x9a, 0x6b, 0x00, 0x00, 0x7f, 0xe0, 0x1f, 0xc0, 0xf0, 0x0f, 0xe0, 0xdf,
+0xff, 0x81, 0x7f, 0x00, 0xc3, 0x3f, 0x80, 0x7f, 0xfc, 0x07, 0xfe, 0x01,
+0x0d, 0xff, 0x00, 0xfe, 0xf0, 0xff, 0x3d, 0x00, 0xf4, 0x3f, 0xf0, 0xaf,
+0x72, 0xf8, 0x55, 0xaa, 0xd2, 0x7b, 0xcf, 0x3f, 0xfc, 0xe1, 0x5b, 0xa9,
+0x80, 0xff, 0x93, 0xff, 0x81, 0x87, 0x7f, 0x00, 0x00, 0xf8, 0xff, 0x1e,
+0x67, 0xf2, 0x1f, 0xf8, 0xfc, 0x3c, 0xfc, 0x03, 0x1f, 0xc0, 0x7f, 0xe0,
+0xe0, 0xdf, 0xf0, 0x0f, 0x7f, 0x00, 0xff, 0x81, 0x80, 0x7f, 0xc3, 0x3f,
+0x0f, 0x00, 0xdc, 0x7f, 0xfe, 0x73, 0xfb, 0xff, 0xf4, 0x22, 0x1f, 0xde,
+0xc0, 0x9f, 0x40, 0x5d, 0x63, 0xc0, 0x75, 0xf8, 0xe5, 0x3f, 0xb5, 0xff,
+0xdd, 0xef, 0xf8, 0xe1, 0xbf, 0x07, 0x00, 0xfe, 0x7f, 0xff, 0x9d, 0xfc,
+0xff, 0x00, 0x3f, 0x0f, 0xfe, 0xff, 0x7f, 0xf2, 0xfc, 0x03, 0xfc, 0x3c,
+0xff, 0xff, 0x3f, 0xc0, 0xf0, 0xfd, 0x64, 0xf0, 0x08, 0x90, 0x00, 0x00,
+0xfe, 0xbf, 0xff, 0xdc, 0x87, 0x37, 0xae, 0x88, 0xfb, 0x0f, 0xfc, 0x33,
+0x1f, 0xfe, 0x98, 0x96, 0xcd, 0xff, 0xff, 0x5f, 0x7e, 0x78, 0xa7, 0xba,
+0x00, 0x04, 0x48, 0x00, 0x00, 0xff, 0x81, 0x7f, 0xf2, 0xc3, 0x3b, 0x13,
+0xfd, 0xfd, 0x37, 0xff, 0x3f, 0x0f, 0xff, 0x7e, 0xd6, 0xf7, 0xff, 0xfd,
+0xe5, 0x3b, 0xfc, 0x71, 0x00, 0x80, 0xff, 0xef, 0x3f, 0x80, 0xff, 0xc0,
+0xc0, 0xbf, 0xe1, 0x1f, 0xff, 0x00, 0xfe, 0x03, 0x00, 0xff, 0x86, 0x7f,
+0xfc, 0x03, 0xf8, 0x0f, 0x01, 0xfc, 0x1b, 0xfe, 0x7b, 0x00, 0xe0, 0xff,
+0xe0, 0x1f, 0xc0, 0x7f, 0x0f, 0xe0, 0xdf, 0xf0, 0x81, 0x7f, 0x00, 0xff,
+0x3f, 0x80, 0x7f, 0xc3, 0x07, 0xfe, 0x01, 0xfc, 0xff, 0x00, 0xfe, 0x0d,
+0xff, 0x3d, 0x00, 0xf0, 0x3f, 0xf0, 0x0f, 0xe0, 0xf8, 0x07, 0xf0, 0x6f,
+0xff, 0xc0, 0x3f, 0x80, 0xe1, 0x1f, 0xc0, 0xbf, 0xfe, 0x03, 0xff, 0x00,
+0x86, 0x7f, 0x00, 0xff, 0xf8, 0xff, 0x1e, 0x00, 0xf0, 0x1f, 0xf8, 0x07,
+0x37, 0xfc, 0x03, 0xf8, 0xc0, 0x7f, 0xe0, 0x1f, 0xdf, 0xf0, 0x0f, 0xe0,
+0x00, 0xff, 0x81, 0x7f, 0x7f, 0xc3, 0x3f, 0x80, 0x00, 0xfc, 0x7f, 0x0f,
+0x03, 0xf8, 0x0f, 0xfc, 0xfc, 0x1b, 0xfe, 0x01, 0x0f, 0xe0, 0x3f, 0xf0,
+0xf0, 0x6f, 0xf8, 0x07, 0x3f, 0x80, 0xff, 0xc0, 0xc0, 0xbf, 0xe1, 0x1f,
+0x07, 0x00, 0xfe, 0xbf, 0xfe, 0x01, 0xfc, 0x07, 0x00, 0xfe, 0x0d, 0xff,
+0xf8, 0x07, 0xf0, 0x1f, 0x03, 0xf8, 0x37, 0xfc, 0xe0, 0x1f, 0xc0, 0x7f,
+0x0f, 0xe0, 0xdf, 0xf0, 0xdf, 0x03, 0x00, 0xff, 0x03, 0xff, 0x00, 0xfe,
+0x7f, 0x00, 0xff, 0x86, 0x0f, 0xfc, 0x03, 0xf8, 0xfe, 0x01, 0xfc, 0x1b,
+0x3f, 0xf0, 0x0f, 0xe0, 0xf8, 0x07, 0xf0, 0x6f, 0xff, 0xef, 0x01, 0x80,
+
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+
diff --git a/src/cpu/amd/model_10xxx/mc_patch_01000020.h b/src/cpu/amd/model_10xxx/mc_patch_01000020.h
new file mode 100644
index 0000000000..0cf207d08b
--- /dev/null
+++ b/src/cpu/amd/model_10xxx/mc_patch_01000020.h
@@ -0,0 +1,163 @@
+/*
+ ============================================================
+ (c) Advanced Micro Devices, Inc., 2004-2005
+
+ The enclosed microcode is intended to be used with AMD
+ Microprocessors. You may copy, view and install the
+ enclosed microcode only for development and deployment of
+ firmware, BIOS, or operating system code for computer
+ systems that contain AMD processors. You are not
+ authorized to use the enclosed microcode for any other
+ purpose.
+
+ THE MICROCODE IS PROVIDED "AS IS" WITHOUT ANY EXPRESS OR
+ IMPLIED WARRANTY OF ANY KIND, INCLUDING BUT NOT LIMITED TO
+ WARRANTIES OF MERCHANTABILITY, NON- INFRINGEMENT,
+ TITLE,FITNESS FOR ANY PARTICULAR PURPOSE, OR WARRANTIES
+ ARISING FROM CONDUCT, COURSE OF DEALING, OR USAGE OF TRADE.
+ AMD does not assume any responsibility for any errors which
+ may appear in this microcode or any other related
+ information provided to you by AMD, or result from use of
+ this microcode. AMD is not obligated to furnish, support,
+ or make any further information, software, technical
+ information, know-how, or show-how available related to this
+ microcode.
+
+ The microcode is provided with "RESTRICTED RIGHTS." Use,
+ duplication, or disclosure by the U.S. Government is subject
+ to the restrictions as set forth in FAR 52.227-14 and
+ DFAR252.227-7013, et seq., or its successor. Use of the
+ microcode by the U.S. Government constitutes
+ acknowledgement of AMD's proprietary rights in them.
+ ============================================================
+*/
+
+0x07, 0x20, 0x26, 0x03, 0x20, 0x00, 0x00, 0x01, 0x00, 0x80, 0x20, 0x00,
+0x66, 0x68, 0x30, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
+0x00, 0x10, 0x00, 0x00, 0x00, 0xaa, 0xaa, 0xaa, 0x44, 0x06, 0x00, 0x00,
+0xff, 0xff, 0xff, 0xff, 0xa4, 0x06, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
+0x72, 0x09, 0x00, 0x00, 0x70, 0x09, 0x00, 0x00, 0x9b, 0x0b, 0x00, 0x00,
+0xff, 0xff, 0xff, 0xff, 0xff, 0x81, 0x7f, 0x00, 0xc3, 0x3f, 0x80, 0x37,
+0xfc, 0x07, 0xfe, 0x01, 0x0d, 0xff, 0x00, 0xfe, 0xf0, 0x1f, 0xf8, 0x07,
+0x37, 0xfc, 0x03, 0xf8, 0xc0, 0xff, 0xf7, 0x00, 0x80, 0xff, 0xc0, 0x3f,
+0x9b, 0xe1, 0x1f, 0xc0, 0x00, 0xfe, 0x03, 0xff, 0xff, 0x86, 0x7f, 0x00,
+0x03, 0xf8, 0x0f, 0xfc, 0xfc, 0x1b, 0xfe, 0x01, 0x00, 0x40, 0x37, 0x6b,
+0xff, 0xfb, 0xfd, 0xff, 0x57, 0x7d, 0xf0, 0xcd, 0xff, 0x1f, 0xb7, 0xfe,
+0xc0, 0xcf, 0xc3, 0x3f, 0xff, 0x01, 0xff, 0xf7, 0x00, 0x02, 0x07, 0xff,
+0x35, 0x00, 0x90, 0x8b, 0xf0, 0x0f, 0xe0, 0x3f, 0x07, 0xf0, 0x6f, 0xf8,
+0xc0, 0x3f, 0x80, 0xff, 0x1f, 0xc0, 0xbf, 0xe1, 0x03, 0xff, 0x00, 0xfe,
+0x7f, 0x00, 0xff, 0x86, 0xff, 0x1e, 0x00, 0xf8, 0x1f, 0xf8, 0x07, 0xf0,
+0xfc, 0x03, 0x78, 0x33, 0x7f, 0xe0, 0x1f, 0xc0, 0xf0, 0x0f, 0xe0, 0xdf,
+0xff, 0x81, 0x7f, 0x00, 0xc3, 0x3f, 0x80, 0x7f, 0xfc, 0x7f, 0x0f, 0x00,
+0xf8, 0x0f, 0xfc, 0x03, 0x19, 0xfe, 0x01, 0xbc, 0xe0, 0x3f, 0xf0, 0x0f,
+0x6f, 0xf8, 0x07, 0xf0, 0x80, 0xff, 0xc0, 0x3f, 0xbf, 0xe1, 0x1f, 0xc0,
+0x00, 0xb4, 0xb2, 0x06, 0xbf, 0xdf, 0xff, 0xff, 0xd5, 0x07, 0xdf, 0x7c,
+0x67, 0xb2, 0xe7, 0xf9, 0xfc, 0x3c, 0xfc, 0x03, 0x1f, 0xf0, 0x7f, 0xff,
+0x20, 0x70, 0xf0, 0x0f, 0x03, 0x00, 0xed, 0x58, 0xff, 0x00, 0xfe, 0x03,
+0x00, 0xff, 0x86, 0x7f, 0xfc, 0x03, 0xf8, 0x0f, 0x01, 0xfc, 0x1b, 0xfe,
+0xf0, 0x0f, 0xe0, 0x3f, 0x07, 0xf0, 0x6f, 0xf8, 0xef, 0x01, 0x80, 0xff,
+0xff, 0xff, 0x29, 0x2a, 0x5f, 0xd0, 0xc1, 0xc3, 0xff, 0xff, 0xb3, 0xdd,
+0xff, 0x7e, 0xfd, 0x0f, 0x1f, 0xf8, 0x57, 0xf6, 0xbc, 0x63, 0x2d, 0x3c,
+0x03, 0xd4, 0x00, 0x40, 0xff, 0xd7, 0xbf, 0xb7, 0xe1, 0xdf, 0xeb, 0xe7,
+0xef, 0xff, 0xff, 0x57, 0x87, 0x7f, 0xbf, 0xea, 0xfa, 0x0f, 0xfc, 0x03,
+0x1f, 0xbe, 0xf5, 0xfc, 0x80, 0x02, 0x4b, 0x00, 0x8a, 0xca, 0xff, 0x7f,
+0xf0, 0xf0, 0x17, 0x74, 0x6c, 0xef, 0xff, 0xff, 0xff, 0xc3, 0xbf, 0x5f,
+0x95, 0xfd, 0x07, 0xfe, 0x0b, 0x0f, 0xef, 0x58, 0x00, 0xd0, 0x00, 0x35,
+0xab, 0xea, 0xff, 0xfb, 0x05, 0x78, 0xf4, 0x67, 0xff, 0xd5, 0xfb, 0xff,
+0xaf, 0xfa, 0xe1, 0xdf, 0xff, 0x80, 0xfe, 0x03, 0x3d, 0xff, 0x87, 0x6f,
+0x12, 0x00, 0xa0, 0xc0, 0xff, 0x0f, 0xf0, 0xaf, 0x03, 0xf8, 0x3f, 0xfc,
+0xff, 0x2f, 0xc0, 0xff, 0x2d, 0x65, 0xff, 0xf0, 0x0d, 0xfe, 0x04, 0xb6,
+0x2f, 0x03, 0xad, 0xc3, 0x51, 0x0d, 0x00, 0x8c, 0xff, 0xfe, 0x03, 0xf8,
+0xff, 0xb9, 0xc9, 0x19, 0x3f, 0xf0, 0x0f, 0xe0, 0xf8, 0x07, 0xf0, 0x6f,
+0xff, 0xc0, 0x3f, 0x80, 0xe1, 0x1f, 0xc0, 0xbf, 0xf2, 0xb9, 0x06, 0x00,
+0xfc, 0x07, 0xfe, 0x01, 0x0d, 0xff, 0x00, 0xfe, 0xf0, 0x1f, 0xf8, 0x07,
+0x37, 0xfc, 0x03, 0xf8, 0xc0, 0x7f, 0xe0, 0x1f, 0xdf, 0xf0, 0x0f, 0xe0,
+0x00, 0xff, 0xdf, 0x03, 0x00, 0xfe, 0x03, 0xff, 0xff, 0x86, 0x7f, 0x00,
+0x03, 0xf8, 0x0f, 0xfc, 0xfc, 0x1b, 0xfe, 0x01, 0x0f, 0xe0, 0x3f, 0xf0,
+0xf0, 0x6f, 0xf8, 0x07, 0x01, 0x80, 0xff, 0xef, 0x7f, 0x00, 0xff, 0x81,
+0x80, 0x7f, 0xc3, 0x3f, 0xfe, 0x01, 0xfc, 0x07, 0x00, 0xfe, 0x0d, 0xff,
+0xf8, 0x07, 0xf0, 0x1f, 0x03, 0xf8, 0x37, 0xfc, 0xd7, 0x00, 0x40, 0x34,
+0xc0, 0x3f, 0x80, 0xff, 0x1f, 0xc0, 0xbf, 0xe1, 0x03, 0xff, 0x00, 0xfe,
+0x7f, 0x00, 0xff, 0x86, 0x0f, 0xfc, 0x03, 0xf8, 0xfe, 0x01, 0xfc, 0x1b,
+0x9a, 0x6b, 0x00, 0x00, 0x7f, 0xe0, 0x1f, 0xc0, 0xf0, 0x0f, 0xe0, 0xdf,
+0xff, 0x81, 0x7f, 0x00, 0xc3, 0x3f, 0x80, 0x7f, 0xfc, 0x07, 0xfe, 0x01,
+0x0d, 0xff, 0x00, 0xfe, 0xf0, 0xff, 0x3d, 0x00, 0xf4, 0x3f, 0xf0, 0xaf,
+0x72, 0xf8, 0x55, 0xaa, 0xd2, 0x7b, 0xcf, 0x3f, 0xfc, 0xe1, 0x5b, 0xa9,
+0x80, 0xff, 0x93, 0xff, 0x81, 0x87, 0x7f, 0x00, 0x00, 0xf8, 0xff, 0x1e,
+0x67, 0xf2, 0x1f, 0xf8, 0xfc, 0x3c, 0xfc, 0x03, 0x1f, 0xc0, 0x7f, 0xe0,
+0xe0, 0xdf, 0xf0, 0x0f, 0x7f, 0x00, 0xff, 0x81, 0x80, 0x7f, 0xc3, 0x3f,
+0x0f, 0x00, 0xdc, 0x7f, 0xfe, 0x73, 0xfb, 0xff, 0xf4, 0x22, 0x1f, 0xde,
+0xc0, 0x9f, 0x40, 0x5d, 0x63, 0xc0, 0x75, 0xf8, 0xe5, 0x3f, 0xb5, 0xff,
+0xdd, 0xef, 0xf8, 0xe1, 0xbf, 0x07, 0x00, 0xfe, 0x7f, 0xff, 0x9d, 0xfc,
+0xff, 0x00, 0x3f, 0x0f, 0xfe, 0xff, 0x7f, 0xf2, 0xfc, 0x03, 0xfc, 0x3c,
+0xff, 0xff, 0x3f, 0xc0, 0xf0, 0xfd, 0x64, 0xf0, 0x08, 0x90, 0x00, 0x00,
+0xfe, 0xbf, 0xff, 0xdc, 0x87, 0x37, 0xae, 0x88, 0xfb, 0x0f, 0xfc, 0x33,
+0x1f, 0xfe, 0x98, 0x96, 0xcd, 0xff, 0xff, 0x5f, 0x7e, 0x78, 0xa7, 0xba,
+0x00, 0x04, 0x48, 0x00, 0x00, 0xff, 0x81, 0x7f, 0xf2, 0xc3, 0x3b, 0x13,
+0xfd, 0xfd, 0x37, 0xff, 0x3f, 0x0f, 0xff, 0x7e, 0xd6, 0xf7, 0xff, 0xfd,
+0xe5, 0x3b, 0xfc, 0x71, 0x00, 0x80, 0xff, 0xef, 0x3f, 0x80, 0xff, 0xc0,
+0xc0, 0xbf, 0xe1, 0x1f, 0xff, 0x00, 0xfe, 0x03, 0x00, 0xff, 0x86, 0x7f,
+0xfc, 0x03, 0xf8, 0x0f, 0x01, 0xfc, 0x1b, 0xfe, 0x7b, 0x00, 0xe0, 0xff,
+0xe0, 0x1f, 0xc0, 0x7f, 0x0f, 0xe0, 0xdf, 0xf0, 0x81, 0x7f, 0x00, 0xff,
+0x3f, 0x80, 0x7f, 0xc3, 0x07, 0xfe, 0x01, 0xfc, 0xff, 0x00, 0xfe, 0x0d,
+0xff, 0x3d, 0x00, 0xf0, 0x3f, 0xf0, 0x0f, 0xe0, 0xf8, 0x07, 0xf0, 0x6f,
+0xff, 0xc0, 0x3f, 0x80, 0xe1, 0x1f, 0xc0, 0xbf, 0xfe, 0x03, 0xff, 0x00,
+0x86, 0x7f, 0x00, 0xff, 0xf8, 0xff, 0x1e, 0x00, 0xf0, 0x1f, 0xf8, 0x07,
+0x37, 0xfc, 0x03, 0xf8, 0xc0, 0x7f, 0xe0, 0x1f, 0xdf, 0xf0, 0x0f, 0xe0,
+0x00, 0xff, 0x81, 0x7f, 0x7f, 0xc3, 0x3f, 0x80, 0x00, 0xfc, 0x7f, 0x0f,
+0x03, 0xf8, 0x0f, 0xfc, 0xfc, 0x1b, 0xfe, 0x01, 0x0f, 0xe0, 0x3f, 0xf0,
+0xf0, 0x6f, 0xf8, 0x07, 0x3f, 0x80, 0xff, 0xc0, 0xc0, 0xbf, 0xe1, 0x1f,
+0x07, 0x00, 0xfe, 0xbf, 0xfe, 0x01, 0xfc, 0x07, 0x00, 0xfe, 0x0d, 0xff,
+0xf8, 0x07, 0xf0, 0x1f, 0x03, 0xf8, 0x37, 0xfc, 0xe0, 0x1f, 0xc0, 0x7f,
+0x0f, 0xe0, 0xdf, 0xf0, 0xdf, 0x03, 0x00, 0xff, 0x03, 0xff, 0x00, 0xfe,
+0x7f, 0x00, 0xff, 0x86, 0x0f, 0xfc, 0x03, 0xf8, 0xfe, 0x01, 0xfc, 0x1b,
+0x3f, 0xf0, 0x0f, 0xe0, 0xf8, 0x07, 0xf0, 0x6f, 0xff, 0xef, 0x01, 0x80,
+
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+
diff --git a/src/cpu/amd/model_10xxx/mc_patch_01000033.h b/src/cpu/amd/model_10xxx/mc_patch_01000033.h
new file mode 100644
index 0000000000..d115c9f17f
--- /dev/null
+++ b/src/cpu/amd/model_10xxx/mc_patch_01000033.h
@@ -0,0 +1,163 @@
+/*
+ ============================================================
+ (c) Advanced Micro Devices, Inc., 2004-2005
+
+ The enclosed microcode is intended to be used with AMD
+ Microprocessors. You may copy, view and install the
+ enclosed microcode only for development and deployment of
+ firmware, BIOS, or operating system code for computer
+ systems that contain AMD processors. You are not
+ authorized to use the enclosed microcode for any other
+ purpose.
+
+ THE MICROCODE IS PROVIDED "AS IS" WITHOUT ANY EXPRESS OR
+ IMPLIED WARRANTY OF ANY KIND, INCLUDING BUT NOT LIMITED TO
+ WARRANTIES OF MERCHANTABILITY, NON- INFRINGEMENT,
+ TITLE,FITNESS FOR ANY PARTICULAR PURPOSE, OR WARRANTIES
+ ARISING FROM CONDUCT, COURSE OF DEALING, OR USAGE OF TRADE.
+ AMD does not assume any responsibility for any errors which
+ may appear in this microcode or any other related
+ information provided to you by AMD, or result from use of
+ this microcode. AMD is not obligated to furnish, support,
+ or make any further information, software, technical
+ information, know-how, or show-how available related to this
+ microcode.
+
+ The microcode is provided with "RESTRICTED RIGHTS." Use,
+ duplication, or disclosure by the U.S. Government is subject
+ to the restrictions as set forth in FAR 52.227-14 and
+ DFAR252.227-7013, et seq., or its successor. Use of the
+ microcode by the U.S. Government constitutes
+ acknowledgement of AMD's proprietary rights in them.
+ ============================================================
+*/
+
+0x07, 0x20, 0x27, 0x06, 0x33, 0x00, 0x00, 0x01, 0x00, 0x80, 0x20, 0x00,
+0xDE, 0x76, 0xD5, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x20, 0x10, 0x00, 0x00, 0x00, 0xAA, 0xAA, 0xAA, 0x70, 0x09, 0x00, 0x00,
+0x49, 0x01, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xC1, 0x08, 0x00, 0x00,
+0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+0xFF, 0xFF, 0xFF, 0xFF, 0x2A, 0xFF, 0xFF, 0x29, 0xC3, 0x5F, 0xD0, 0xC1,
+0xBD, 0xFF, 0xFF, 0xB3, 0x0F, 0xFF, 0x7E, 0xFD, 0xF6, 0x1F, 0xF8, 0x57,
+0x3C, 0xBC, 0x63, 0x2D, 0x80, 0x96, 0xD6, 0x00, 0xAA, 0xFF, 0xEF, 0xAF,
+0xE0, 0xD1, 0x9F, 0x15, 0x57, 0xEF, 0xFF, 0xFF, 0xEA, 0x87, 0x7F, 0xBF,
+0x03, 0xFA, 0x0F, 0xFC, 0xFC, 0x1F, 0xBE, 0xF5, 0x00, 0xE0, 0x4A, 0x4B,
+0x7F, 0xC8, 0xFF, 0xF7, 0xB4, 0xF8, 0xF0, 0x2F, 0xFF, 0x1F, 0xC5, 0xFE,
+0xC0, 0xCF, 0xC3, 0x3F, 0xFF, 0x03, 0xD4, 0xFF, 0x40, 0xC8, 0x0F, 0xEF,
+0x3D, 0x00, 0xF0, 0xFF, 0xFB, 0xAF, 0xE5, 0xBF, 0xD7, 0xFA, 0x3F, 0xF8,
+0xEB, 0x3F, 0x97, 0xFF, 0x9F, 0xEB, 0xFF, 0xE0, 0x97, 0xFF, 0x5E, 0xFE,
+0x7F, 0xAE, 0xFA, 0x83, 0xC9, 0x1A, 0x00, 0x08, 0x9F, 0xFC, 0x07, 0xF0,
+0x7C, 0x7B, 0xD9, 0x1F, 0x7F, 0xE0, 0x1F, 0xC0, 0xF0, 0x0F, 0xE0, 0xDF,
+0xFF, 0x81, 0x7F, 0x00, 0xC3, 0x3F, 0x80, 0x7F, 0xFC, 0x7F, 0x0F, 0x00,
+0xF8, 0x0F, 0xFC, 0x03, 0x1B, 0xFE, 0x01, 0xFC, 0xE0, 0x3F, 0xF0, 0x0F,
+0x6F, 0xF8, 0x07, 0xF0, 0x80, 0xFF, 0xC0, 0x3F, 0xBF, 0xE1, 0x1F, 0xC0,
+0x00, 0xFE, 0xBF, 0x07, 0x01, 0xFC, 0x67, 0xEB, 0x00, 0x07, 0xFE, 0xDE,
+0xFF, 0x02, 0x00, 0xE0, 0xFD, 0x3F, 0xBC, 0x63, 0xFF, 0x8B, 0xFF, 0xFF,
+0xF5, 0x7F, 0xF0, 0xEF, 0x03, 0x00, 0x3D, 0x57, 0xFF, 0x58, 0xFE, 0xBF,
+0xAC, 0x7C, 0x83, 0x3F, 0xFF, 0x7F, 0xF9, 0xE2, 0x01, 0x7E, 0x1E, 0xFE,
+0x1B, 0x0F, 0xE0, 0xBF, 0xF7, 0xF6, 0x3A, 0xF0, 0xAF, 0x01, 0x80, 0xB4,
+0x81, 0x7F, 0x00, 0xFF, 0x3F, 0x80, 0x7F, 0xC3, 0x07, 0xFE, 0x01, 0xFC,
+0xFF, 0x00, 0xFE, 0x0D, 0x1F, 0xF8, 0x07, 0xF0, 0xFC, 0x03, 0xF8, 0x37,
+0xFF, 0xF7, 0x00, 0xC0, 0xFF, 0xC0, 0x3F, 0x80, 0xE1, 0x1F, 0xC0, 0xBF,
+0xFE, 0x03, 0xFF, 0x00, 0x86, 0x7F, 0x00, 0xFF, 0xF8, 0x0F, 0xFC, 0x03,
+0x1B, 0xFE, 0x01, 0xFC, 0xE0, 0xFF, 0x7B, 0x00, 0xC0, 0x7F, 0xE0, 0x1F,
+0xDF, 0xF0, 0x0F, 0xE0, 0x00, 0xFF, 0x81, 0x7F, 0x7F, 0xC3, 0x3F, 0x80,
+0x01, 0xFC, 0x07, 0xFE, 0xFE, 0x0D, 0xFF, 0x00, 0x00, 0xF0, 0xFF, 0x3D,
+0x0F, 0xE0, 0x3F, 0xF0, 0xF0, 0x6F, 0xF8, 0x07, 0x3F, 0x80, 0xFF, 0xC0,
+0xC0, 0xBF, 0xE1, 0x1F, 0xFF, 0x00, 0xFE, 0x03, 0x00, 0xFF, 0x86, 0x7F,
+0x1E, 0x00, 0xF8, 0xFF, 0xF8, 0x07, 0xF0, 0x1F, 0x03, 0xF8, 0x37, 0xFC,
+0xE0, 0x1F, 0xC0, 0x7F, 0x0F, 0xE0, 0xDF, 0xF0, 0x81, 0x7F, 0x00, 0xFF,
+0x3F, 0x80, 0x7F, 0xC3, 0x7F, 0x0F, 0x00, 0xFC, 0x0F, 0xFC, 0x03, 0xF8,
+0xFE, 0x01, 0xFC, 0x1B, 0x3F, 0xF0, 0x0F, 0xE0, 0xF8, 0x07, 0xF0, 0x6F,
+0xFF, 0xC0, 0x3F, 0x80, 0xE1, 0x1F, 0xC0, 0xBF, 0xFE, 0xBF, 0x07, 0x00,
+0xFC, 0x07, 0xFE, 0x01, 0x0D, 0xFF, 0x00, 0xFE, 0xF0, 0x1F, 0xF8, 0x07,
+0x37, 0xFC, 0x03, 0xF8, 0xC0, 0x7F, 0xE0, 0x1F, 0xDF, 0xF0, 0x0F, 0xE0,
+0x00, 0xFF, 0xDF, 0x03, 0x00, 0xFE, 0x03, 0xFF, 0xFF, 0x86, 0x7F, 0x00,
+0x03, 0xF8, 0x0F, 0xFC, 0xFC, 0x1B, 0xFE, 0x01, 0x0F, 0xE0, 0x3F, 0xF0,
+0xF0, 0x6F, 0xF8, 0x07, 0x01, 0x80, 0xFF, 0xEF, 0x7F, 0x00, 0xFF, 0x81,
+0x80, 0x7F, 0xC3, 0x3F, 0xFE, 0x01, 0xFC, 0x07, 0x00, 0xFE, 0x0D, 0xFF,
+0xF8, 0x07, 0xF0, 0x1F, 0x03, 0xF8, 0x37, 0xFC, 0xD7, 0x00, 0x40, 0x34,
+0xC0, 0x3F, 0x80, 0xFF, 0x1F, 0xC0, 0xBF, 0xE1, 0x03, 0xFF, 0x00, 0xFE,
+0x7F, 0x00, 0xFF, 0x86, 0x0F, 0xFC, 0x03, 0xF8, 0xFE, 0x01, 0xFC, 0x1B,
+0x9A, 0x6B, 0x00, 0x00, 0x7F, 0xE0, 0x1F, 0xC0, 0xF0, 0x0F, 0xE0, 0xDF,
+0xFF, 0x81, 0x7F, 0x00, 0xC3, 0x3F, 0x80, 0x7F, 0xFC, 0x07, 0xFE, 0x01,
+0x0D, 0xFF, 0x00, 0xFE, 0xF0, 0xFF, 0x3D, 0x00, 0xE0, 0x3F, 0xF0, 0x0F,
+0x6F, 0xF8, 0x07, 0xF0, 0x80, 0xFF, 0xC0, 0x3F, 0xBF, 0xE1, 0x1F, 0xC0,
+0x00, 0xFE, 0x03, 0xFF, 0xFF, 0x86, 0x7F, 0x00, 0x00, 0xF8, 0xFF, 0x1E,
+0x07, 0xF0, 0x1F, 0xF8, 0xF8, 0x37, 0xFC, 0x03, 0x1F, 0xC0, 0x7F, 0xE0,
+0xE0, 0xDF, 0xF0, 0x0F, 0x7F, 0x00, 0xFF, 0x81, 0x80, 0x7F, 0xC3, 0x3F,
+0x0F, 0x00, 0xFC, 0x7F, 0xFC, 0x03, 0xF8, 0x0F, 0x01, 0xFC, 0x1B, 0xFE,
+0xF0, 0x0F, 0xE0, 0x3F, 0x07, 0xF0, 0x6F, 0xF8, 0xC0, 0x3F, 0x80, 0xFF,
+0x1F, 0xC0, 0xBF, 0xE1, 0xBF, 0x07, 0x00, 0xFE, 0x07, 0xFE, 0x01, 0xFC,
+0xFF, 0x00, 0xFE, 0x0D, 0x1F, 0xF8, 0x07, 0xF0, 0xFC, 0x03, 0xF8, 0x37,
+0x7F, 0xE0, 0x1F, 0xC0, 0xF0, 0x0F, 0xE0, 0xDF, 0xFF, 0xDF, 0x03, 0x00,
+0xFE, 0x03, 0xFF, 0x00, 0x86, 0x7F, 0x00, 0xFF, 0xF8, 0x0F, 0xFC, 0x03,
+0x1B, 0xFE, 0x01, 0xFC, 0xE0, 0x3F, 0xF0, 0x0F, 0x6F, 0xF8, 0x07, 0xF0,
+0x80, 0xFF, 0xEF, 0x01, 0x00, 0xFF, 0x81, 0x7F, 0x7F, 0xC3, 0x3F, 0x80,
+0x01, 0xFC, 0x07, 0xFE, 0xFE, 0x0D, 0xFF, 0x00, 0x07, 0xF0, 0x1F, 0xF8,
+0xF8, 0x37, 0xFC, 0x03, 0x00, 0xC0, 0xFF, 0xF7, 0x3F, 0x80, 0xFF, 0xC0,
+0xC0, 0xBF, 0xE1, 0x1F, 0xFF, 0x00, 0xFE, 0x03, 0x00, 0xFF, 0x86, 0x7F,
+0xFC, 0x03, 0xF8, 0x0F, 0x01, 0xFC, 0x1B, 0xFE, 0x7B, 0x00, 0xE0, 0xFF,
+0xE0, 0x1F, 0xC0, 0x7F, 0x0F, 0xE0, 0xDF, 0xF0, 0x81, 0x7F, 0x00, 0xFF,
+0x3F, 0x80, 0x7F, 0xC3, 0x07, 0xFE, 0x01, 0xFC, 0xFF, 0x00, 0xFE, 0x0D,
+0xFF, 0x3D, 0x00, 0xF0, 0x3F, 0xF0, 0x0F, 0xE0, 0xF8, 0x07, 0xF0, 0x6F,
+0xFF, 0xC0, 0x3F, 0x80, 0xE1, 0x1F, 0xC0, 0xBF, 0xFE, 0x03, 0xFF, 0x00,
+0x86, 0x7F, 0x00, 0xFF, 0xF8, 0xFF, 0x1E, 0x00, 0xF0, 0x1F, 0xF8, 0x07,
+0x37, 0xFC, 0x03, 0xF8, 0xC0, 0x7F, 0xE0, 0x1F, 0xDF, 0xF0, 0x0F, 0xE0,
+0x00, 0xFF, 0x81, 0x7F, 0x7F, 0xC3, 0x3F, 0x80, 0x00, 0xFC, 0x7F, 0x0F,
+0x03, 0xF8, 0x0F, 0xFC, 0xFC, 0x1B, 0xFE, 0x01, 0x0F, 0xE0, 0x3F, 0xF0,
+0xF0, 0x6F, 0xF8, 0x07, 0x3F, 0x80, 0xFF, 0xC0, 0xC0, 0xBF, 0xE1, 0x1F,
+0x07, 0x00, 0xFE, 0xBF, 0xFE, 0x01, 0xFC, 0x07, 0x00, 0xFE, 0x0D, 0xFF,
+0xF8, 0x07, 0xF0, 0x1F, 0x03, 0xF8, 0x37, 0xFC, 0xE0, 0x1F, 0xC0, 0x7F,
+0x0F, 0xE0, 0xDF, 0xF0, 0xDF, 0x03, 0x00, 0xFF, 0x03, 0xFF, 0x00, 0xFE,
+0x7F, 0x00, 0xFF, 0x86, 0x0F, 0xFC, 0x03, 0xF8, 0xFE, 0x01, 0xFC, 0x1B,
+0x3F, 0xF0, 0x0F, 0xE0, 0xF8, 0x07, 0xF0, 0x6F, 0xFF, 0xEF, 0x01, 0x80,
+
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+
diff --git a/src/cpu/amd/model_10xxx/mc_patch_01000035.h b/src/cpu/amd/model_10xxx/mc_patch_01000035.h
new file mode 100644
index 0000000000..5081bfaa0e
--- /dev/null
+++ b/src/cpu/amd/model_10xxx/mc_patch_01000035.h
@@ -0,0 +1,163 @@
+/*
+ ============================================================
+ (c) Advanced Micro Devices, Inc., 2004-2005
+
+ The enclosed microcode is intended to be used with AMD
+ Microprocessors. You may copy, view and install the
+ enclosed microcode only for development and deployment of
+ firmware, BIOS, or operating system code for computer
+ systems that contain AMD processors. You are not
+ authorized to use the enclosed microcode for any other
+ purpose.
+
+ THE MICROCODE IS PROVIDED "AS IS" WITHOUT ANY EXPRESS OR
+ IMPLIED WARRANTY OF ANY KIND, INCLUDING BUT NOT LIMITED TO
+ WARRANTIES OF MERCHANTABILITY, NON- INFRINGEMENT,
+ TITLE,FITNESS FOR ANY PARTICULAR PURPOSE, OR WARRANTIES
+ ARISING FROM CONDUCT, COURSE OF DEALING, OR USAGE OF TRADE.
+ AMD does not assume any responsibility for any errors which
+ may appear in this microcode or any other related
+ information provided to you by AMD, or result from use of
+ this microcode. AMD is not obligated to furnish, support,
+ or make any further information, software, technical
+ information, know-how, or show-how available related to this
+ microcode.
+
+ The microcode is provided with "RESTRICTED RIGHTS." Use,
+ duplication, or disclosure by the U.S. Government is subject
+ to the restrictions as set forth in FAR 52.227-14 and
+ DFAR252.227-7013, et seq., or its successor. Use of the
+ microcode by the U.S. Government constitutes
+ acknowledgement of AMD's proprietary rights in them.
+ ============================================================
+*/
+
+0x07, 0x20, 0x23, 0x07, 0x35, 0x00, 0x00, 0x01, 0x00, 0x80, 0x20, 0x00,
+0xDE, 0x76, 0xD5, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x22, 0x10, 0x00, 0x00, 0x00, 0xAA, 0xAA, 0xAA, 0x70, 0x09, 0x00, 0x00,
+0x49, 0x01, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xC1, 0x08, 0x00, 0x00,
+0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+0xFF, 0xFF, 0xFF, 0xFF, 0x2A, 0xFF, 0xFF, 0x29, 0xC3, 0x5F, 0xD0, 0xC1,
+0xBD, 0xFF, 0xFF, 0xB3, 0x0F, 0xFF, 0x7E, 0xFD, 0xF6, 0x1F, 0xF8, 0x57,
+0x3C, 0xBC, 0x63, 0x2D, 0x80, 0x96, 0xD6, 0x00, 0xAA, 0xFF, 0xEF, 0xAF,
+0xE0, 0xD1, 0x9F, 0x15, 0x57, 0xEF, 0xFF, 0xFF, 0xEA, 0x87, 0x7F, 0xBF,
+0x03, 0xFA, 0x0F, 0xFC, 0xFC, 0x1F, 0xBE, 0xF5, 0x00, 0xE0, 0x4A, 0x4B,
+0x7F, 0xC8, 0xFF, 0xF7, 0xB4, 0xF8, 0xF0, 0x2F, 0xFF, 0x1F, 0xC5, 0xFE,
+0xC0, 0xCF, 0xC3, 0x3F, 0xFF, 0x03, 0xD4, 0xFF, 0x40, 0xC8, 0x0F, 0xEF,
+0x3D, 0x00, 0xF0, 0xFF, 0xFB, 0xAF, 0xE5, 0xBF, 0xD7, 0xFA, 0x3F, 0xF8,
+0xEB, 0x3F, 0x97, 0xFF, 0x9F, 0xEB, 0xFF, 0xE0, 0x97, 0xFF, 0x5E, 0xFE,
+0x7F, 0xAE, 0xFA, 0x83, 0xC9, 0x1A, 0x00, 0x08, 0x9F, 0xFC, 0x07, 0xF0,
+0x7C, 0x7B, 0xD9, 0x1F, 0x7F, 0xE0, 0x1F, 0xC0, 0xF0, 0x0F, 0xE0, 0xDF,
+0xFF, 0x81, 0x7F, 0x00, 0xC3, 0x3F, 0x80, 0x7F, 0xFC, 0x7F, 0x0F, 0x00,
+0xF8, 0x0F, 0xFC, 0x03, 0x1B, 0xFE, 0x01, 0xFC, 0xE0, 0x3F, 0xF0, 0x0F,
+0x6F, 0xF8, 0x07, 0xF0, 0x80, 0xFF, 0xC0, 0x3F, 0xBF, 0xE1, 0x1F, 0xC0,
+0x00, 0xFE, 0xBF, 0x07, 0x01, 0xFC, 0x67, 0xEB, 0x00, 0x07, 0xFE, 0xDE,
+0xFF, 0x02, 0x00, 0xE0, 0xFD, 0x3F, 0xBC, 0x63, 0xFF, 0x8B, 0xFF, 0xFF,
+0xF5, 0x7F, 0xF0, 0xEF, 0x03, 0x00, 0x3D, 0x57, 0xFF, 0x58, 0xFE, 0xBF,
+0xAC, 0x7C, 0x83, 0x3F, 0xFF, 0x7F, 0xF9, 0xE2, 0x01, 0x7E, 0x1E, 0xFE,
+0x1B, 0x0F, 0xE0, 0xBF, 0xF7, 0xF6, 0x3A, 0xF0, 0xAF, 0x01, 0x80, 0xB4,
+0x81, 0x7F, 0x00, 0xFF, 0x3F, 0x80, 0x7F, 0xC3, 0x07, 0xFE, 0x01, 0xFC,
+0xFF, 0x00, 0xFE, 0x0D, 0x1F, 0xF8, 0x07, 0xF0, 0xFC, 0x03, 0xF8, 0x37,
+0xFF, 0xF7, 0x00, 0xC0, 0xFF, 0xC0, 0x3F, 0x80, 0xE1, 0x1F, 0xC0, 0xBF,
+0xFE, 0x03, 0xFF, 0x00, 0x86, 0x7F, 0x00, 0xFF, 0xF8, 0x0F, 0xFC, 0x03,
+0x1B, 0xFE, 0x01, 0xFC, 0xE0, 0xFF, 0x7B, 0x00, 0xC0, 0x7F, 0xE0, 0x1F,
+0xDF, 0xF0, 0x0F, 0xE0, 0x00, 0xFF, 0x81, 0x7F, 0x7F, 0xC3, 0x3F, 0x80,
+0x01, 0xFC, 0x07, 0xFE, 0xFE, 0x0D, 0xFF, 0x00, 0x00, 0xF0, 0xFF, 0x3D,
+0x0F, 0xE0, 0x3F, 0xF0, 0xF0, 0x6F, 0xF8, 0x07, 0x3F, 0x80, 0xFF, 0xC0,
+0xC0, 0xBF, 0xE1, 0x1F, 0xFF, 0x00, 0xFE, 0x03, 0x00, 0xFF, 0x86, 0x7F,
+0x1E, 0x00, 0xF8, 0xFF, 0xF8, 0x07, 0xF0, 0x1F, 0x03, 0xF8, 0x37, 0xFC,
+0xE0, 0x1F, 0xC0, 0x7F, 0x0F, 0xE0, 0xDF, 0xF0, 0x81, 0x7F, 0x00, 0xFF,
+0x3F, 0x80, 0x7F, 0xC3, 0x7F, 0x0F, 0x00, 0xFC, 0x0F, 0xFC, 0x03, 0xF8,
+0xFE, 0x01, 0xFC, 0x1B, 0x3F, 0xF0, 0x0F, 0xE0, 0xF8, 0x07, 0xF0, 0x6F,
+0xFF, 0xC0, 0x3F, 0x80, 0xE1, 0x1F, 0xC0, 0xBF, 0xFE, 0xBF, 0x07, 0x00,
+0xFC, 0x07, 0xFE, 0x01, 0x0D, 0xFF, 0x00, 0xFE, 0xF0, 0x1F, 0xF8, 0x07,
+0x37, 0xFC, 0x03, 0xF8, 0xC0, 0x7F, 0xE0, 0x1F, 0xDF, 0xF0, 0x0F, 0xE0,
+0x00, 0xFF, 0xDF, 0x03, 0x00, 0xFE, 0x03, 0xFF, 0xFF, 0x86, 0x7F, 0x00,
+0x03, 0xF8, 0x0F, 0xFC, 0xFC, 0x1B, 0xFE, 0x01, 0x0F, 0xE0, 0x3F, 0xF0,
+0xF0, 0x6F, 0xF8, 0x07, 0x01, 0x80, 0xFF, 0xEF, 0x7F, 0x00, 0xFF, 0x81,
+0x80, 0x7F, 0xC3, 0x3F, 0xFE, 0x01, 0xFC, 0x07, 0x00, 0xFE, 0x0D, 0xFF,
+0xF8, 0x07, 0xF0, 0x1F, 0x03, 0xF8, 0x37, 0xFC, 0xD7, 0x00, 0x40, 0x34,
+0xC0, 0x3F, 0x80, 0xFF, 0x1F, 0xC0, 0xBF, 0xE1, 0x03, 0xFF, 0x00, 0xFE,
+0x7F, 0x00, 0xFF, 0x86, 0x0F, 0xFC, 0x03, 0xF8, 0xFE, 0x01, 0xFC, 0x1B,
+0x9A, 0x6B, 0x00, 0x00, 0x7F, 0xE0, 0x1F, 0xC0, 0xF0, 0x0F, 0xE0, 0xDF,
+0xFF, 0x81, 0x7F, 0x00, 0xC3, 0x3F, 0x80, 0x7F, 0xFC, 0x07, 0xFE, 0x01,
+0x0D, 0xFF, 0x00, 0xFE, 0xF0, 0xFF, 0x3D, 0x00, 0xE0, 0x3F, 0xF0, 0x0F,
+0x6F, 0xF8, 0x07, 0xF0, 0x80, 0xFF, 0xC0, 0x3F, 0xBF, 0xE1, 0x1F, 0xC0,
+0x00, 0xFE, 0x03, 0xFF, 0xFF, 0x86, 0x7F, 0x00, 0x00, 0xF8, 0xFF, 0x1E,
+0x07, 0xF0, 0x1F, 0xF8, 0xF8, 0x37, 0xFC, 0x03, 0x1F, 0xC0, 0x7F, 0xE0,
+0xE0, 0xDF, 0xF0, 0x0F, 0x7F, 0x00, 0xFF, 0x81, 0x80, 0x7F, 0xC3, 0x3F,
+0x0F, 0x00, 0xFC, 0x7F, 0xFC, 0x03, 0xF8, 0x0F, 0x01, 0xFC, 0x1B, 0xFE,
+0xF0, 0x0F, 0xE0, 0x3F, 0x07, 0xF0, 0x6F, 0xF8, 0xC0, 0x3F, 0x80, 0xFF,
+0x1F, 0xC0, 0xBF, 0xE1, 0xBF, 0x07, 0x00, 0xFE, 0x07, 0xFE, 0x01, 0xFC,
+0xFF, 0x00, 0xFE, 0x0D, 0x1F, 0xF8, 0x07, 0xF0, 0xFC, 0x03, 0xF8, 0x37,
+0x7F, 0xE0, 0x1F, 0xC0, 0xF0, 0x0F, 0xE0, 0xDF, 0xFF, 0xDF, 0x03, 0x00,
+0xFE, 0x03, 0xFF, 0x00, 0x86, 0x7F, 0x00, 0xFF, 0xF8, 0x0F, 0xFC, 0x03,
+0x1B, 0xFE, 0x01, 0xFC, 0xE0, 0x3F, 0xF0, 0x0F, 0x6F, 0xF8, 0x07, 0xF0,
+0x80, 0xFF, 0xEF, 0x01, 0x00, 0xFF, 0x81, 0x7F, 0x7F, 0xC3, 0x3F, 0x80,
+0x01, 0xFC, 0x07, 0xFE, 0xFE, 0x0D, 0xFF, 0x00, 0x07, 0xF0, 0x1F, 0xF8,
+0xF8, 0x37, 0xFC, 0x03, 0x00, 0xC0, 0xFF, 0xF7, 0x3F, 0x80, 0xFF, 0xC0,
+0xC0, 0xBF, 0xE1, 0x1F, 0xFF, 0x00, 0xFE, 0x03, 0x00, 0xFF, 0x86, 0x7F,
+0xFC, 0x03, 0xF8, 0x0F, 0x01, 0xFC, 0x1B, 0xFE, 0x7B, 0x00, 0xE0, 0xFF,
+0xE0, 0x1F, 0xC0, 0x7F, 0x0F, 0xE0, 0xDF, 0xF0, 0x81, 0x7F, 0x00, 0xFF,
+0x3F, 0x80, 0x7F, 0xC3, 0x07, 0xFE, 0x01, 0xFC, 0xFF, 0x00, 0xFE, 0x0D,
+0xFF, 0x3D, 0x00, 0xF0, 0x3F, 0xF0, 0x0F, 0xE0, 0xF8, 0x07, 0xF0, 0x6F,
+0xFF, 0xC0, 0x3F, 0x80, 0xE1, 0x1F, 0xC0, 0xBF, 0xFE, 0x03, 0xFF, 0x00,
+0x86, 0x7F, 0x00, 0xFF, 0xF8, 0xFF, 0x1E, 0x00, 0xF0, 0x1F, 0xF8, 0x07,
+0x37, 0xFC, 0x03, 0xF8, 0xC0, 0x7F, 0xE0, 0x1F, 0xDF, 0xF0, 0x0F, 0xE0,
+0x00, 0xFF, 0x81, 0x7F, 0x7F, 0xC3, 0x3F, 0x80, 0x00, 0xFC, 0x7F, 0x0F,
+0x03, 0xF8, 0x0F, 0xFC, 0xFC, 0x1B, 0xFE, 0x01, 0x0F, 0xE0, 0x3F, 0xF0,
+0xF0, 0x6F, 0xF8, 0x07, 0x3F, 0x80, 0xFF, 0xC0, 0xC0, 0xBF, 0xE1, 0x1F,
+0x07, 0x00, 0xFE, 0xBF, 0xFE, 0x01, 0xFC, 0x07, 0x00, 0xFE, 0x0D, 0xFF,
+0xF8, 0x07, 0xF0, 0x1F, 0x03, 0xF8, 0x37, 0xFC, 0xE0, 0x1F, 0xC0, 0x7F,
+0x0F, 0xE0, 0xDF, 0xF0, 0xDF, 0x03, 0x00, 0xFF, 0x03, 0xFF, 0x00, 0xFE,
+0x7F, 0x00, 0xFF, 0x86, 0x0F, 0xFC, 0x03, 0xF8, 0xFE, 0x01, 0xFC, 0x1B,
+0x3F, 0xF0, 0x0F, 0xE0, 0xF8, 0x07, 0xF0, 0x6F, 0xFF, 0xEF, 0x01, 0x80,
+
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+
diff --git a/src/cpu/amd/model_10xxx/model_10xxx_init.c b/src/cpu/amd/model_10xxx/model_10xxx_init.c
new file mode 100644
index 0000000000..013c315081
--- /dev/null
+++ b/src/cpu/amd/model_10xxx/model_10xxx_init.c
@@ -0,0 +1,463 @@
+/*
+ * This file is part of the LinuxBIOS project.
+ *
+ * Copyright (C) 2007 Advanced Micro Devices, 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.
+ *
+ * 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
+ */
+
+#include <console/console.h>
+#include <cpu/x86/msr.h>
+#include <cpu/amd/mtrr.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <string.h>
+#include <cpu/x86/msr.h>
+#include <cpu/x86/pae.h>
+#include <pc80/mc146818rtc.h>
+#include <cpu/x86/lapic.h>
+
+#include "../../../northbridge/amd/amdfam10/amdfam10.h"
+
+#include <cpu/amd/model_10xxx_rev.h>
+#include <cpu/cpu.h>
+#include <cpu/x86/cache.h>
+#include <cpu/x86/mtrr.h>
+#include <cpu/x86/mem.h>
+
+#include <cpu/amd/quadcore.h>
+
+#include <cpu/amd/model_10xxx_msr.h>
+
+extern void prep_pstates_all(void);
+extern void init_pstates(device_t dev, u32 nodeid, u32 coreid);
+extern device_t get_node_pci(u32 nodeid, u32 fn);
+
+
+
+void cpus_ready_for_init(void)
+{
+ prep_pstates_all();
+#if MEM_TRAIN_SEQ == 1
+ struct sys_info *sysinfox = (struct sys_info *)((CONFIG_LB_MEM_TOPK<<10) - DCACHE_RAM_GLOBAL_VAR_SIZE);
+ // wait for ap memory to trained
+ wait_all_core0_mem_trained(sysinfox);
+#endif
+}
+
+
+#define MCI_STATUS 0x401
+
+
+static inline msr_t rdmsr_amd(u32 index)
+{
+ msr_t result;
+ __asm__ __volatile__ (
+ "rdmsr"
+ : "=a" (result.lo), "=d" (result.hi)
+ : "c" (index), "D" (0x9c5a203a)
+ );
+ return result;
+}
+
+
+static inline void wrmsr_amd(u32 index, msr_t msr)
+{
+ __asm__ __volatile__ (
+ "wrmsr"
+ : /* No outputs */
+ : "c" (index), "a" (msr.lo), "d" (msr.hi), "D" (0x9c5a203a)
+ );
+}
+
+
+#define MTRR_COUNT 8
+#define ZERO_CHUNK_KB 0x800UL /* 2M */
+#define TOLM_KB 0x400000UL
+
+struct mtrr {
+ msr_t base;
+ msr_t mask;
+};
+
+
+struct mtrr_state {
+ struct mtrr mtrrs[MTRR_COUNT];
+ msr_t top_mem, top_mem2;
+ msr_t def_type;
+};
+
+
+static void save_mtrr_state(struct mtrr_state *state)
+{
+ int i;
+ for(i = 0; i < MTRR_COUNT; i++) {
+ state->mtrrs[i].base = rdmsr(MTRRphysBase_MSR(i));
+ state->mtrrs[i].mask = rdmsr(MTRRphysMask_MSR(i));
+ }
+ state->top_mem = rdmsr(TOP_MEM);
+ state->top_mem2 = rdmsr(TOP_MEM2);
+ state->def_type = rdmsr(MTRRdefType_MSR);
+}
+
+
+static void restore_mtrr_state(struct mtrr_state *state)
+{
+ int i;
+ disable_cache();
+
+ for(i = 0; i < MTRR_COUNT; i++) {
+ wrmsr(MTRRphysBase_MSR(i), state->mtrrs[i].base);
+ wrmsr(MTRRphysMask_MSR(i), state->mtrrs[i].mask);
+ }
+ wrmsr(TOP_MEM, state->top_mem);
+ wrmsr(TOP_MEM2, state->top_mem2);
+ wrmsr(MTRRdefType_MSR, state->def_type);
+
+ enable_cache();
+}
+
+
+#if 0
+static void print_mtrr_state(struct mtrr_state *state)
+{
+ int i;
+ for(i = 0; i < MTRR_COUNT; i++) {
+ printk_debug("var mtrr %d: %08x%08x mask: %08x%08x\n",
+ i,
+ state->mtrrs[i].base.hi, state->mtrrs[i].base.lo,
+ state->mtrrs[i].mask.hi, state->mtrrs[i].mask.lo);
+ }
+ printk_debug("top_mem: %08x%08x\n",
+ state->top_mem.hi, state->top_mem.lo);
+ printk_debug("top_mem2: %08x%08x\n",
+ state->top_mem2.hi, state->top_mem2.lo);
+ printk_debug("def_type: %08x%08x\n",
+ state->def_type.hi, state->def_type.lo);
+}
+#endif
+
+
+static void set_init_ecc_mtrrs(void)
+{
+ msr_t msr;
+ int i;
+ disable_cache();
+
+ /* First clear all of the msrs to be safe */
+ for(i = 0; i < MTRR_COUNT; i++) {
+ msr_t zero;
+ zero.lo = zero.hi = 0;
+ wrmsr(MTRRphysBase_MSR(i), zero);
+ wrmsr(MTRRphysMask_MSR(i), zero);
+ }
+
+ /* Write back cache the first 1MB */
+ msr.hi = 0x00000000;
+ msr.lo = 0x00000000 | MTRR_TYPE_WRBACK;
+ wrmsr(MTRRphysBase_MSR(0), msr);
+ msr.hi = 0x000000ff;
+ msr.lo = ~((CONFIG_LB_MEM_TOPK << 10) - 1) | 0x800;
+ wrmsr(MTRRphysMask_MSR(0), msr);
+
+ /* Set the default type to write combining */
+ msr.hi = 0x00000000;
+ msr.lo = 0xc00 | MTRR_TYPE_WRCOMB;
+ wrmsr(MTRRdefType_MSR, msr);
+
+ /* Set TOP_MEM to 4G */
+ msr.hi = 0x00000001;
+ msr.lo = 0x00000000;
+ wrmsr(TOP_MEM, msr);
+
+ enable_cache();
+}
+
+
+static inline void clear_2M_ram(unsigned long basek, struct mtrr_state *mtrr_state)
+{
+ unsigned long limitk;
+ unsigned long size;
+ void *addr;
+
+ /* Report every 64M */
+ if ((basek % (64*1024)) == 0) {
+
+ /* Restore the normal state */
+ map_2M_page(0);
+ restore_mtrr_state(mtrr_state);
+ enable_lapic();
+
+ /* Print a status message */
+ printk_debug("%c", (basek >= TOLM_KB)?'+':'-');
+
+ /* Return to the initialization state */
+ set_init_ecc_mtrrs();
+ disable_lapic();
+
+ }
+
+ limitk = (basek + ZERO_CHUNK_KB) & ~(ZERO_CHUNK_KB - 1);
+
+ size = (limitk - basek) << 10;
+ addr = map_2M_page(basek >> 11);
+ if (addr == MAPPING_ERROR) {
+ printk_err("Cannot map page: %x\n", basek >> 11);
+ return;
+ }
+
+ /* clear memory 2M (limitk - basek) */
+ addr = (void *)(((u32)addr) | ((basek & 0x7ff) << 10));
+ clear_memory(addr, size);
+}
+
+
+static void init_ecc_memory(u32 node_id)
+{
+ unsigned long startk, begink, endk;
+ unsigned long hole_startk = 0;
+ unsigned long basek;
+ struct mtrr_state mtrr_state;
+
+ device_t f1_dev, f2_dev, f3_dev;
+ int enable_scrubbing;
+ u32 dcl;
+
+ f1_dev = get_node_pci(node_id, 1);
+
+ if (!f1_dev) {
+ die("Cannot find cpu function 1\n");
+ }
+ f2_dev = get_node_pci(node_id, 2);
+ if (!f2_dev) {
+ die("Cannot find cpu function 2\n");
+ }
+ f3_dev = get_node_pci(node_id, 3);
+ if (!f3_dev) {
+ die("Cannot find cpu function 3\n");
+ }
+
+ /* See if we scrubbing should be enabled */
+ enable_scrubbing = 1;
+ get_option(&enable_scrubbing, "hw_scrubber");
+
+ /* Enable cache scrubbing at the lowest possible rate */
+ if (enable_scrubbing) {
+ pci_write_config32(f3_dev, DRAM_SCRUB_RATE_CTRL,
+ (SCRUB_84ms << 16) | (SCRUB_84ms << 8) | (SCRUB_NONE << 0));
+ } else {
+ pci_write_config32(f3_dev, DRAM_SCRUB_RATE_CTRL,
+ (SCRUB_NONE << 16) | (SCRUB_NONE << 8) | (SCRUB_NONE << 0));
+ printk_debug("Scrubbing Disabled\n");
+ }
+
+
+ /* If ecc support is not enabled don't touch memory */
+ dcl = pci_read_config32(f2_dev, DRAM_CONFIG_LOW);
+ if (!(dcl & DCL_DimmEccEn)) {
+ printk_debug("ECC Disabled\n");
+ return;
+ }
+
+ startk = (pci_read_config32(f1_dev, 0x40 + (node_id*8)) & 0xffff0000) >> 2;
+ endk = ((pci_read_config32(f1_dev, 0x44 + (node_id*8)) & 0xffff0000) >> 2) + 0x4000;
+
+#if HW_MEM_HOLE_SIZEK != 0
+ u32 val;
+ val = pci_read_config32(f1_dev, 0xf0);
+ if(val & 1) {
+ hole_startk = ((val & (0xff<<24)) >> 10);
+ }
+#endif
+
+
+ /* Don't start too early */
+ begink = startk;
+ if (begink < CONFIG_LB_MEM_TOPK) {
+ begink = CONFIG_LB_MEM_TOPK;
+ }
+
+ printk_debug("Clearing memory %uK - %uK: ", begink, endk);
+
+ /* Save the normal state */
+ save_mtrr_state(&mtrr_state);
+
+ /* Switch to the init ecc state */
+ set_init_ecc_mtrrs();
+ disable_lapic();
+
+ /* Walk through 2M chunks and zero them */
+#if HW_MEM_HOLE_SIZEK != 0
+ /* here hole_startk can not be equal to begink, never. Also hole_startk is in 2M boundary, 64M? */
+ if ( (hole_startk != 0) && ((begink < hole_startk) && (endk>(4*1024*1024)))) {
+ for(basek = begink; basek < hole_startk;
+ basek = ((basek + ZERO_CHUNK_KB) & ~(ZERO_CHUNK_KB - 1)))
+ {
+ clear_2M_ram(basek, &mtrr_state);
+ }
+ for(basek = 4*1024*1024; basek < endk;
+ basek = ((basek + ZERO_CHUNK_KB) & ~(ZERO_CHUNK_KB - 1)))
+ {
+ clear_2M_ram(basek, &mtrr_state);
+ }
+ } else
+#endif
+ for(basek = begink; basek < endk;
+ basek = ((basek + ZERO_CHUNK_KB) & ~(ZERO_CHUNK_KB - 1))) {
+ clear_2M_ram(basek, &mtrr_state);
+ }
+
+
+ /* Restore the normal state */
+ map_2M_page(0);
+ restore_mtrr_state(&mtrr_state);
+ enable_lapic();
+
+ /* Set the scrub base address registers */
+ pci_write_config32(f3_dev, DRAM_SCRUB_ADDR_LOW, startk << 10);
+ pci_write_config32(f3_dev, DRAM_SCRUB_ADDR_HIGH, startk >> 22);
+
+ /* Enable the scrubber? */
+ if (enable_scrubbing) {
+ /* Enable scrubbing at the lowest possible rate */
+ pci_write_config32(f3_dev, DRAM_SCRUB_RATE_CTRL,
+ (SCRUB_84ms << 16) | (SCRUB_84ms << 8) | (SCRUB_84ms << 0));
+ }
+
+ printk_debug(" done\n");
+}
+
+
+static inline void fam10_errata(void)
+{
+ msr_t msr;
+ /* FIXME: Is doing errata here too late? */
+
+ /* 298 : FIXME: Fixed in B3/C1 */
+/* msr = rdmsr(0xC0010015);
+ msr.lo |= 1 << 3;
+ wrmsr(0xC0010015, msr);
+
+ msr = rdmsr(0xC0010023);
+ msr.lo |= 1 << 1;
+ wrmsr(0xC0010023, msr);
+*/
+}
+
+static void smash1Gpages(void)
+{
+ msr_t msr;
+
+ /* 1G pages are smashed and installed in the TLB as 2M pages.
+ BIOS must set this bit for revision B. */
+ /* FIXME: What about RevC? */
+
+ msr = rdmsr(0xC001102A);
+ msr.lo |= 1 << 29;
+ wrmsr(0xC001102A, msr);
+
+}
+
+extern void update_microcode(u32 cpu_deviceid);
+
+
+void model_10xxx_init(device_t dev)
+{
+ unsigned long i;
+ msr_t msr;
+ struct node_core_id id;
+#if CONFIG_LOGICAL_CPUS == 1
+ unsigned siblings;
+#endif
+
+ /* Turn on caching if we haven't already */
+ x86_enable_cache();
+ amd_setup_mtrrs();
+ x86_mtrr_check();
+
+
+ /* Update the microcode */
+ update_microcode(dev->device);
+
+ disable_cache();
+
+ /* zero the machine check error status registers */
+ msr.lo = 0;
+ msr.hi = 0;
+ for(i=0; i < 5; i++) {
+ wrmsr(MCI_STATUS + (i * 4),msr);
+ }
+
+ fam10_errata();
+
+ enable_cache();
+
+ /* Enable the local cpu apics */
+ setup_lapic();
+
+#if CONFIG_LOGICAL_CPUS == 1
+ siblings = cpuid_ecx(0x80000008) & 0xff;
+
+ if (siblings > 0) {
+ msr = rdmsr_amd(CPU_ID_FEATURES_MSR);
+ msr.lo |= 1 << 28;
+ wrmsr_amd(CPU_ID_FEATURES_MSR, msr);
+
+ msr = rdmsr_amd(LOGICAL_CPUS_NUM_MSR);
+ msr.lo = (siblings+1)<<16;
+ wrmsr_amd(LOGICAL_CPUS_NUM_MSR, msr);
+
+ msr = rdmsr_amd(CPU_ID_EXT_FEATURES_MSR);
+ msr.hi |= 1<<(33-32);
+ wrmsr_amd(CPU_ID_EXT_FEATURES_MSR, msr);
+ }
+ printk_debug("siblings = %02d, ", siblings);
+#endif
+
+ id = get_node_core_id(read_nb_cfg_54()); // pre e0 nb_cfg_54 can not be set
+
+ printk_debug("nodeid = %02d, coreid = %02d\n", id.nodeid, id.coreid);
+
+ init_pstates(dev, id.nodeid, id.coreid); // is it a good place? some cores are clearing their ram
+
+ /* Is this a bad location? In particular can another node prefecth
+ * data from this node before we have initialized it?
+ */
+ if (id.coreid == 0) init_ecc_memory(id.nodeid); // only do it for core 0
+
+#if CONFIG_LOGICAL_CPUS==1
+ /* Start up my cpu siblings */
+// if(id.coreid==0) amd_sibling_init(dev); // Don't need core1 is already be put in the CPU BUS in bus_cpu_scan
+#endif
+
+ smash1Gpages();
+}
+
+static struct device_operations cpu_dev_ops = {
+ .init = model_10xxx_init,
+};
+static struct cpu_device_id cpu_table[] = {
+//AMD_GH_SUPPORT
+ { X86_VENDOR_AMD, 0x100f00 }, /* SH-F0 L1 */
+ { X86_VENDOR_AMD, 0x100f10 }, /* M2 */
+ { X86_VENDOR_AMD, 0x100f20 }, /* S1g1 */
+ { X86_VENDOR_AMD, 0x100f21 },
+ { X86_VENDOR_AMD, 0x100f2A },
+ { X86_VENDOR_AMD, 0x100f22 },
+ { 0, 0 },
+};
+static struct cpu_driver model_10xxx __cpu_driver = {
+ .ops = &cpu_dev_ops,
+ .id_table = cpu_table,
+};
diff --git a/src/cpu/amd/model_10xxx/pstate.c b/src/cpu/amd/model_10xxx/pstate.c
new file mode 100644
index 0000000000..a3545a0d74
--- /dev/null
+++ b/src/cpu/amd/model_10xxx/pstate.c
@@ -0,0 +1,456 @@
+/*
+ * This file is part of the LinuxBIOS project.
+ *
+ * Copyright (C) 2007 Advanced Micro Devices, 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.
+ *
+ * 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
+ */
+
+#include <console/console.h>
+#include <cpu/x86/msr.h>
+#include <cpu/amd/mtrr.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <string.h>
+#include <cpu/x86/msr.h>
+#include <cpu/x86/pae.h>
+#include <pc80/mc146818rtc.h>
+#include <cpu/x86/lapic.h>
+
+#include "../../../northbridge/amd/amdfam10/amdfam10.h"
+
+#include <cpu/amd/model_10xxx_rev.h>
+#include <cpu/cpu.h>
+#include <cpu/x86/cache.h>
+#include <cpu/x86/mtrr.h>
+#include <cpu/x86/mem.h>
+
+#include <cpu/amd/quadcore.h>
+
+#include <cpu/amd/model_10xxx_msr.h>
+#include <cpu/amd/amdfam10_sysconf.h>
+
+extern device_t get_node_pci(u32 nodeid, u32 fn);
+
+#include "fidvid_common.c"
+
+#define PSTATES_DEBUG 0
+
+
+
+static void inline dump_msr_pstates(u32 nodes)
+{
+#if PSTATES_DEBUG==1
+ int i, j;
+ for(j=0; j<5; j++) {
+ printk_debug("P%d:", j);
+ for(i=0;i<nodes;i++) {
+ printk_debug(" [%08x %08x] ", sysconf.msr_pstate[i*5+j].hi, sysconf.msr_pstate[i*5+j].lo);
+ }
+ printk_debug("\n");
+ }
+#endif
+}
+
+
+static void inline dump_p(const char *p_c, u32 nodes, u32 *p)
+{
+#if PSTATES_DEBUG==1
+ int i, j;
+ printk_debug(p_c);
+ printk_debug("p:");
+ for(i=0;i<nodes;i++) {
+ printk_debug(" %d ", p[i]);
+ }
+ printk_debug("\n");
+
+#endif
+}
+
+
+//according the pstate and make it work conformed to mixed conf system
+static u32 get_pwrvalue(u32 val)
+{
+ u32 times;
+ switch((val>>8)&3) {
+ case 0: times = 1000; break;
+ case 1: times = 100; break;
+ case 2: times = 10; break;
+ default:
+ //error
+ times = 1;
+ }
+
+ return (val & 0xff) * times;
+
+}
+
+
+static u32 get_powerstep(u32 val)
+{
+ u32 time;
+ if(val<4) {time = (4 - val)*100;}
+ else if(val<8) { time = (9+4-val)*10;}
+ else { time = (10+8-val) * 5; }
+
+ return time;
+
+}
+
+
+static u32 get_plllocktime(u32 val)
+{
+ u32 time;
+ switch(val) {
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ time = val+1; break;
+ case 4: time = 8; break;
+ case 5: time = 16; break;
+ default:
+ //erro2
+ time = 1;
+ }
+ return time;
+}
+
+
+static void disable_pstate(u32 nodes, u32 *p)
+{
+ int i;
+
+ for(i=0;i<nodes; i++) {
+ sysconf.msr_pstate[i*5+p[i]].hi &= ~(1<<(63-32));
+ }
+}
+
+
+static void match_pstate(u32 nodes, u32 *p)
+{
+ int i;
+ u32 corecof_min, pwrvalue_max, pwrval_max;
+ u32 enable;
+ enable = (sysconf.msr_pstate[0*5+p[0]].hi >> 31);
+ if(!enable) {
+ disable_pstate(nodes, p);
+ return;
+ }
+ corecof_min = ((sysconf.msr_pstate[0*5+p[0]].lo & 0x3f) + 0x10)>>((sysconf.msr_pstate[0*5+p[0]].lo>>6) & 7);
+ pwrval_max = sysconf.msr_pstate[0*5+p[0]].hi & 0x3ff;
+ pwrvalue_max = get_pwrvalue(pwrval_max);
+
+ for(i=1; i<nodes; i++) {
+ enable = (sysconf.msr_pstate[0*5+p[i]].hi >> 31);
+ if(!enable) {
+ disable_pstate(nodes, p);
+ return;
+ }
+
+ u32 coredid = ((sysconf.msr_pstate[i*5+p[i]].lo>>6) & 7);
+ u32 corecof = ((sysconf.msr_pstate[i*5+p[i]].lo & 0x3f) + 0x10)>>coredid;
+ if(corecof<corecof_min) corecof_min = corecof;
+ u32 pwrval, pwrvalue;
+ pwrval = sysconf.msr_pstate[i*5+p[i]].hi & 0x3ff;
+ pwrvalue = get_pwrvalue(pwrval);
+ if(pwrvalue>pwrvalue_max) {
+ pwrvalue_max = pwrvalue;
+ pwrval_max = pwrval;
+ }
+ }
+
+ for(i=0; i<nodes; i++) {
+ u32 coredid = ((sysconf.msr_pstate[i*5+p[i]].lo>>6) & 7);
+ u32 corefid = (corecof_min<<coredid);
+ while(corefid<0x10) {
+ coredid++;
+ corefid = (corecof_min<<coredid);
+ }
+ sysconf.msr_pstate[i*5+p[i]].lo &= ~(0x1ff);
+ sysconf.msr_pstate[i*5+p[i]].lo |= (corefid - 0x10) | (coredid << 6);
+ sysconf.msr_pstate[i*5+p[i]].hi &= ~(0x3ff);
+ sysconf.msr_pstate[i*5+p[i]].hi |= pwrval_max;
+ }
+}
+
+
+static void match_pstates(u32 nodes, u32 *p, u32 *px)
+{
+ int i;
+ int j;
+ u32 p_int[NODE_NUMS];
+
+ int jj=1;
+ u32 end = 0;
+ for(i=0;i<nodes; i++) {
+ p_int[i] = px[i];
+ }
+ while(1){
+ for(i=0;i<nodes; i++) {
+ if(px[i]<=(p[i]+jj)) {
+ end = 1;
+ break;
+ }
+ }
+ if(!end) {
+ for(i=0; i<nodes; i++) {
+ p_int[i] = px[i] - jj;
+ }
+ match_pstate(nodes, p_int);
+ dump_p("P int\n", nodes, p_int);
+ jj++;
+ }
+ else {
+ for(i=0;i<nodes; i++) {
+ for(j=p[i]+1; j<p_int[i]; j++) {
+ sysconf.msr_pstate[i*5+j].hi &= ~(1<<(63-32));
+ }
+ }
+ break;
+ }
+ }
+}
+
+
+void prep_pstates_all(void)
+{
+ device_t f3_dev[NODE_NUMS], f4_dev[NODE_NUMS];
+ u32 p[NODE_NUMS];
+ u32 p_htc[NODE_NUMS];
+ u32 p_lowest[NODE_NUMS];
+ u32 htc_cap = 1;
+ u32 lowest_htc_equal = 0;
+
+ u32 nodes = sysconf.nodes;
+ int i;
+ int j;
+ u32 val;
+ u32 nbdid;
+ u32 nbvid0;
+ u32 nbvid1;
+
+ for(i=0;i<nodes; i++) { // get the value from F4x1F0:E0 or we can get that msr in CAR stage...
+ f3_dev[i] = get_node_pci(i, 3);
+ f4_dev[i] = get_node_pci(i, 4);
+ }
+
+ for(i=0;i<nodes; i++) { // get the value from F4x1F0:E0 or we can get that msr in CAR stage...
+ val = pci_read_config32(f4_dev[i], 0x1f4);
+ nbvid0 = val & 0x3f;
+ nbvid1 = (val>>7) & 0x3f;
+ for(j=0; j<5; j++) {
+ val = pci_read_config32(f4_dev[i], 0x1e0 + (j<<2));
+ nbdid = ((val>>16) & 1);
+ sysconf.msr_pstate[i*5+j].lo = (val & 0xffff) | (nbdid<<22) | ((nbdid?nbvid1:nbvid0)<<25);
+ sysconf.msr_pstate[i*5+j].hi = (((val>>17) & 0x3ff) << (32-32)) | (((val>>27) & 1)<<(63-32));
+ }
+ }
+
+ dump_msr_pstates(nodes);
+
+ sysconf.needs_update_pstate_msrs = 0; // normal case for all sockets are installed same conf CPU
+
+ for(i=1; (i<nodes) && (!sysconf.needs_update_pstate_msrs); i++) {
+ for(j=0; j<5; j++) {
+ if((sysconf.msr_pstate[i*5+j].lo != sysconf.msr_pstate[0*5+j].lo) || (sysconf.msr_pstate[i*5+j].hi != sysconf.msr_pstate[0*5+j].hi)) {
+ sysconf.needs_update_pstate_msrs = 1;
+ break;
+ }
+ }
+ }
+
+ if(sysconf.needs_update_pstate_msrs) {
+
+ // update msr_pstate for mixed conf
+
+ //P0
+ /* Match P0 cpu cof for all cpu cores to the lowest P0 cpu cof value in the coherent fabric, and match P0 power for all cpu cores to the highest P0 power value */
+ for(i=0;i<nodes; i++) p[i] = 0;
+ match_pstate(nodes, p);
+ dump_p("P0\n", nodes, p);
+ dump_msr_pstates(nodes);
+
+
+ //p_htc
+ for(i=0;i<nodes; i++) {
+ val = pci_read_config32(f3_dev[i], 0xe8); //htc cap
+ if(!(val & (1<<10))) {
+ htc_cap = 0;
+ break;
+ }
+
+ //HtcPstateLimit
+ val = pci_read_config32(f3_dev[i], 0x64);
+ p_htc[i] = (((val>>28) & 7));
+ if(p_htc[i] == 0) {
+ val |= 1<<28;
+ pci_write_config32(f3_dev[i], 0x64, val);
+ val = pci_read_config32(f3_dev[i], 0x68); //stc
+ val &= ~(7<<28);
+ val |= (1<<28);
+ pci_write_config32(f3_dev[i], 0x68, val);
+
+ p_htc[i] = 1;
+ }
+ }
+ if(htc_cap) {
+ match_pstate(nodes, p_htc);
+
+ dump_p("P_htc\n", nodes, p_htc);
+ dump_msr_pstates(nodes);
+ }
+
+ //p_lowest
+ for(i=0;i<nodes; i++) {
+ p_lowest[i] = 0;
+ for(j=1; j<5; j++) {
+ if(sysconf.msr_pstate[i*5+j].hi & (1<<(63-32))) {
+ p_lowest[i] = j;
+ }
+ }
+ // PstateMaxVal
+ val = pci_read_config32(f3_dev[i], 0xdc);
+ if(p_lowest[i]>((val>>8) & 7)) {
+ val &= ~(7<<8);
+ val |= (p_lowest[i])<<8;
+ pci_write_config32(f3_dev[i], 0xdc, val);
+ }
+ else {
+ p_lowest[i] = (val>>8) & 7;
+ }
+ }
+ if(htc_cap) {
+ for(i=0;i<nodes; i++) {
+ if(p_lowest[i]==p_htc[i]){
+ lowest_htc_equal = 1;
+ break;
+ }
+ }
+ }
+ if(lowest_htc_equal) {
+ for(i=0;i<nodes; i++) {
+ // PstateMaxVal
+ val = pci_read_config32(f3_dev[i], 0xdc);
+ val &= ~(7<<8);
+ val |= p_htc[i];
+ pci_write_config32(f3_dev[i], 0xdc, val);
+ for(j=p_htc[i]+1; j<5; j++) {
+ sysconf.msr_pstate[i*5+j].hi &= ~(1<<(63-32));
+ }
+ }
+ } else {
+ match_pstate(nodes, p_lowest);
+ for(i=0; i<nodes; i++) {
+ for(j=p_lowest[i]+1; j<5; j++) {
+ sysconf.msr_pstate[i*5+j].hi &= ~(1<<(63-32));
+ }
+ }
+
+ }
+
+ dump_p("Px\n", nodes, p_lowest);
+ dump_msr_pstates(nodes);
+
+
+ if(htc_cap) {
+ //p_up_int
+ match_pstates(nodes, p, p_htc);
+
+ dump_msr_pstates(nodes);
+
+ //p_lower_int
+ match_pstates(nodes, p_htc, p_lowest);
+ } else {
+ match_pstates(nodes, p, p_lowest);
+ }
+
+ dump_msr_pstates(nodes);
+
+ }
+
+ // fill data into p_state
+ for(i=0; i<nodes; i++) {
+ sysconf.p_state_num = 0;
+ u32 corefid_equal = 1;
+ u32 corefid;
+ corefid = (sysconf.msr_pstate[i*5+0].lo & 0x3f);
+ for(j=1; j<5; j++) {
+ msr_t *msr_pstate;
+ msr_pstate = &(sysconf.msr_pstate[i*5+j]);
+ if(!(msr_pstate->hi & (1<<(63-32)) )) continue;
+ if((msr_pstate->lo & 0x3f) != corefid) {
+ corefid_equal = 0;
+ break;
+ }
+ }
+ for(j=0; j<5; j++) {
+ struct p_state_t *p_state;
+ msr_t *msr_pstate;
+ msr_pstate = &sysconf.msr_pstate[i*5+j];
+ if(!(msr_pstate->hi & (1<<(63-32)) )) continue;
+ p_state = &sysconf.p_state[i*5+sysconf.p_state_num];
+ u32 coredid = ((msr_pstate->lo>>6) & 7);
+ u32 corecof = ((msr_pstate->lo & 0x3f) + 0x10)>>coredid;
+ p_state->corefreq = corecof;
+
+ u32 pwrval, pwrvalue;
+ pwrval = msr_pstate->hi & 0x3ff;
+ pwrvalue = get_pwrvalue(pwrval);
+ p_state->power = pwrvalue;
+
+ u32 lat;
+ val = pci_read_config32(f3_dev[i], 0xd4);
+ lat = 15 * (get_powerstep((val>>24)& 0xf)+get_powerstep((val>>20)& 0xf)) /1000;
+ if(!corefid_equal) {
+ val = pci_read_config32(f3_dev[i], 0xa0);
+ lat += get_plllocktime((val >> 11 ) & 7);
+ }
+ p_state->transition_lat = lat;
+ p_state->busmaster_lat = lat;
+
+ p_state->control = j;
+ p_state->status = j;
+
+ sysconf.p_state_num++;
+ }
+ // don't need look at other nodes
+ if(!sysconf.p_state_num) break;
+ }
+}
+
+
+//it will update pstates info from ram into MSR
+void init_pstates(device_t dev, u32 nodeid, u32 coreid)
+{
+ int j;
+ msr_t msr;
+
+ if(sysconf.needs_update_pstate_msrs) {
+ for(j=0; j < 5; j++) {
+ wrmsr(0xC0010064 + j, sysconf.msr_pstate[nodeid * 5 + j]);
+ }
+ }
+
+ /* Set TSC Freq Select: TSC increments at the rate of the core P-state 0 */
+ msr = rdmsr(0xC0010015);
+ msr.lo |= 1 << 24;
+ wrmsr(0xC0010015, msr);
+
+ // Enter the state P0
+ //FIXME I don't think that this works correctly. May depend on early fid/vid setup.
+ if(sysconf.p_state_num)
+ set_core_nb_max_pstate_after_other_warm_reset(nodeid, coreid);
+
+}
diff --git a/src/cpu/amd/model_10xxx/update_microcode.c b/src/cpu/amd/model_10xxx/update_microcode.c
new file mode 100644
index 0000000000..285abfadf6
--- /dev/null
+++ b/src/cpu/amd/model_10xxx/update_microcode.c
@@ -0,0 +1,90 @@
+/*
+ * This file is part of the LinuxBIOS project.
+ *
+ * Copyright (C) 2007 Advanced Micro Devices, 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.
+ *
+ * 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 __ROMCC__
+#include <console/console.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <string.h>
+
+#include <cpu/amd/microcode.h>
+#endif
+
+static const u8 microcode_updates[] __attribute__ ((aligned(16))) = {
+
+#ifdef __ROMCC__
+
+ // Barcelona revAx
+// #include "mc_patch_01000020.h"
+
+ // Barcelona revBx
+ #include "mc_patch_01000033.h"
+
+ // Barcelona rev Cx??
+// #include "mc_patch_01000035.h"
+
+#endif
+ /* Dummy terminator */
+ 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0,
+};
+
+static u32 get_equivalent_processor_rev_id(u32 orig_id) {
+ static unsigned id_mapping_table[] = {
+ 0x100f00, 0x1000,
+ 0x100f01, 0x1000,
+ 0x100f02, 0x1000,
+ 0x100f20, 0x1020,
+ 0x100f21, 0x1020,
+ 0x100f2A, 0x1020,
+ 0x100f22, 0x1022,
+ };
+
+ u32 new_id;
+ int i;
+
+ new_id = 0;
+
+ for (i = 0; i < sizeof(id_mapping_table); i += 2 ) {
+ if(id_mapping_table[i]==orig_id) {
+ new_id = id_mapping_table[i + 1];
+ break;
+ }
+ }
+
+ return new_id;
+
+}
+
+void update_microcode(u32 cpu_deviceid)
+{
+ u32 equivalent_processor_rev_id;
+
+ /* Update the microcode */
+ equivalent_processor_rev_id = get_equivalent_processor_rev_id(cpu_deviceid );
+ if (equivalent_processor_rev_id != 0) {
+ amd_update_microcode((void *) microcode_updates, equivalent_processor_rev_id);
+ } else {
+ printk_debug("microcode: rev id not found. Skipping microcode patch!\n");
+ }
+
+}
diff --git a/src/cpu/amd/quadcore/Config.lb b/src/cpu/amd/quadcore/Config.lb
new file mode 100644
index 0000000000..d0dbaadd94
--- /dev/null
+++ b/src/cpu/amd/quadcore/Config.lb
@@ -0,0 +1,20 @@
+#
+# This file is part of the LinuxBIOS project.
+#
+# Copyright (C) 2007 Advanced Micro Devices, 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.
+#
+# 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
+#
+
+object amd_sibling.o
diff --git a/src/cpu/amd/quadcore/amd_sibling.c b/src/cpu/amd/quadcore/amd_sibling.c
new file mode 100644
index 0000000000..4ed770d981
--- /dev/null
+++ b/src/cpu/amd/quadcore/amd_sibling.c
@@ -0,0 +1,122 @@
+/*
+ * This file is part of the LinuxBIOS project.
+ *
+ * Copyright (C) 2007 Advanced Micro Devices, 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.
+ *
+ * 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
+ */
+
+
+#include <console/console.h>
+#include <cpu/cpu.h>
+#include <cpu/x86/lapic.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <pc80/mc146818rtc.h>
+#include <smp/spinlock.h>
+#include <cpu/x86/mtrr.h>
+#include <cpu/amd/model_10xxx_msr.h>
+#include <cpu/amd/model_10xxx_rev.h>
+#include <cpu/amd/amdfam10_sysconf.h>
+
+extern device_t get_node_pci(u32 nodeid, u32 fn);
+
+#if 0
+static int first_time = 1;
+#endif
+
+#include "quadcore_id.c"
+
+static u32 get_max_siblings(u32 nodes)
+{
+ device_t dev;
+ u32 nodeid;
+ u32 siblings=0;
+
+ //get max siblings from all the nodes
+ for(nodeid=0; nodeid<nodes; nodeid++){
+ int j;
+ dev = get_node_pci(nodeid, 3);
+ j = (pci_read_config32(dev, 0xe8) >> 12) & 3;
+ if(siblings < j) {
+ siblings = j;
+ }
+ }
+
+ return siblings;
+}
+
+
+static void enable_apic_ext_id(u32 nodes)
+{
+ device_t dev;
+ u32 nodeid;
+
+ //enable APIC_EXIT_ID all the nodes
+ for(nodeid=0; nodeid<nodes; nodeid++){
+ u32 val;
+ dev = get_node_pci(nodeid, 0);
+ val = pci_read_config32(dev, 0x68);
+ val |= (1<<17)|(1<<18);
+ pci_write_config32(dev, 0x68, val);
+ }
+}
+
+
+u32 get_apicid_base(u32 ioapic_num)
+{
+ u32 apicid_base;
+ u32 siblings;
+ u32 nb_cfg_54;
+
+ u32 disable_siblings = !CONFIG_LOGICAL_CPUS;
+
+ get_option(&disable_siblings, "quad_core");
+
+ siblings = get_max_siblings(sysconf.nodes);
+
+ if(sysconf.bsp_apicid > 0) { // io apic could start from 0
+ return 0;
+ } else if (sysconf.enabled_apic_ext_id) { // enabled ext id but bsp = 0
+ return 1;
+ }
+
+ nb_cfg_54 = read_nb_cfg_54();
+
+
+ //contruct apicid_base
+
+ if((!disable_siblings) && (siblings>0) ) {
+ /* for 8 way dual core, we will used up apicid 16:16, actualy
+ 16 is not allowed by current kernel and the kernel will try
+ to get one that is small than 16 to make io apic work. I don't
+ know when the kernel can support 256 apic id.
+ (APIC_EXT_ID is enabled) */
+
+ //4:10 for two way 8:12 for four way 16:16 for eight way
+ //Use CONFIG_MAX_PHYSICAL_CPUS instead of nodes for better consistency?
+ apicid_base = nb_cfg_54 ? (siblings+1) * sysconf.nodes : 8 * siblings + sysconf.nodes;
+
+ } else {
+ apicid_base = sysconf.nodes;
+ }
+
+ if((apicid_base+ioapic_num-1)>0xf) {
+ // We need to enable APIC EXT ID
+ printk_spew("if the IO APIC device doesn't support 256 apic id, \r\n you need to set ENABLE_APIC_EXT_ID in MB Option.lb so you can spare 16 id for ioapic\r\n");
+ enable_apic_ext_id(sysconf.nodes);
+ }
+
+ return apicid_base;
+}
diff --git a/src/cpu/amd/quadcore/quadcore.c b/src/cpu/amd/quadcore/quadcore.c
new file mode 100644
index 0000000000..c08b2090ae
--- /dev/null
+++ b/src/cpu/amd/quadcore/quadcore.c
@@ -0,0 +1,102 @@
+/*
+ * This file is part of the LinuxBIOS project.
+ *
+ * Copyright (C) 2007 Advanced Micro Devices, 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.
+ *
+ * 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 SET_NB_CFG_54
+ #define SET_NB_CFG_54 1
+#endif
+
+#include "cpu/amd/quadcore/quadcore_id.c"
+
+static inline u32 get_core_num_in_bsp(u32 nodeid)
+{
+ u32 dword;
+ dword = pci_read_config32(NODE_PCI(nodeid, 3), 0xe8);
+ dword >>= 12;
+ dword &= 3;
+ return dword;
+}
+
+#if SET_NB_CFG_54 == 1
+static inline u8 set_apicid_cpuid_lo(void)
+{
+ // set the NB_CFG[54]=1; why the OS will be happy with that ???
+ msr_t msr;
+ msr = rdmsr(NB_CFG_MSR);
+ msr.hi |= (1<<(54-32)); // InitApicIdCpuIdLo
+ wrmsr(NB_CFG_MSR, msr);
+
+ return 1;
+}
+#else
+
+static inline void set_apicid_cpuid_lo(void) { }
+
+#endif
+
+
+static inline void real_start_other_core(u32 nodeid, u32 cores)
+{
+ u32 dword;
+
+ printk_debug("Start other core - nodeid: %02x cores: %02x\n", nodeid, cores);
+
+ /* set PCI_DEV(0, 0x18+nodeid, 3), 0x44 bit 27 to redirect all MC4
+ accesses and error logging to core0 */
+ dword = pci_read_config32(NODE_PCI(nodeid, 3), 0x44);
+ dword |= 1 << 27; // NbMcaToMstCpuEn bit
+ pci_write_config32(NODE_PCI(nodeid, 3), 0x44, dword);
+ // set PCI_DEV(0, 0x18+nodeid, 0), 0x68 bit 5 to start core1
+ dword = pci_read_config32(NODE_PCI(nodeid, 0), 0x68);
+ dword |= 1 << 5;
+ pci_write_config32(NODE_PCI(nodeid, 0), 0x68, dword);
+
+ if(cores > 1) {
+ dword = pci_read_config32(NODE_PCI(nodeid, 0), 0x168);
+ dword |= (1 << 0); // core2
+ if(cores > 2) { // core3
+ dword |= (1 << 1);
+ }
+ pci_write_config32(NODE_PCI(nodeid, 0), 0x168, dword);
+ }
+}
+
+//it is running on core0 of node0
+static inline void start_other_cores(void)
+{
+ u32 nodes;
+ u32 nodeid;
+
+ // disable quad_core
+ if (read_option(CMOS_VSTART_quad_core, CMOS_VLEN_quad_core, 0) != 0) {
+ printk_debug("Skip additional core init\n");
+ return;
+ }
+
+ nodes = get_nodes();
+
+ for (nodeid = 0; nodeid < nodes; nodeid++) {
+ u32 cores = get_core_num_in_bsp(nodeid);
+ printk_debug("init node: %02x cores: %02x \n", nodeid, cores);
+ if (cores > 0) {
+ real_start_other_core(nodeid, cores);
+ }
+ }
+
+}
diff --git a/src/cpu/amd/quadcore/quadcore_id.c b/src/cpu/amd/quadcore/quadcore_id.c
new file mode 100644
index 0000000000..e556d699ab
--- /dev/null
+++ b/src/cpu/amd/quadcore/quadcore_id.c
@@ -0,0 +1,79 @@
+/*
+ * This file is part of the LinuxBIOS project.
+ *
+ * Copyright (C) 2007 Advanced Micro Devices, 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.
+ *
+ * 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
+ */
+
+
+#include <arch/cpu.h>
+#include <cpu/amd/quadcore.h>
+#ifdef __ROMCC__
+#include <cpu/amd/model_10xxx_msr.h>
+#endif
+
+//called by bus_cpu_scan too
+u32 read_nb_cfg_54(void)
+{
+ msr_t msr;
+ msr = rdmsr(NB_CFG_MSR);
+ return ( ( msr.hi >> (54-32)) & 1);
+}
+
+static inline u32 get_initial_apicid(void)
+{
+ return ((cpuid_ebx(1) >> 24) & 0xff);
+}
+
+//called by amd_siblings too
+#define CORE_ID_BIT 2
+#define NODE_ID_BIT 6
+struct node_core_id get_node_core_id(u32 nb_cfg_54)
+{
+ struct node_core_id id;
+ u32 core_id_bits;
+
+ u32 ApicIdCoreIdSize = (cpuid_ecx(0x80000008)>>12 & 0xf);
+ if(ApicIdCoreIdSize) {
+ core_id_bits = ApicIdCoreIdSize;
+ } else {
+ core_id_bits = CORE_ID_BIT; //quad core
+ }
+
+ // get the apicid via cpuid(1) ebx[31:24]
+ if( nb_cfg_54) {
+ // when NB_CFG[54] is set, nodeid = ebx[31:26], coreid = ebx[25:24]
+ id.coreid = (cpuid_ebx(1) >> 24) & 0xff;
+ id.nodeid = (id.coreid>>core_id_bits);
+ id.coreid &= ((1<<core_id_bits)-1);
+ } else {
+ // when NB_CFG[54] is clear, nodeid = ebx[29:24], coreid = ebx[31:30]
+ id.nodeid = (cpuid_ebx(1) >> 24) & 0xff;
+ id.coreid = (id.nodeid>>NODE_ID_BIT);
+ id.nodeid &= ((1<<NODE_ID_BIT)-1);
+ }
+ return id;
+}
+
+static inline u32 get_core_num(void)
+{
+ return (cpuid_ecx(0x80000008) & 0xff);
+}
+
+static inline struct node_core_id get_node_core_id_x(void) {
+
+ return get_node_core_id( read_nb_cfg_54() );
+}
+
diff --git a/src/cpu/amd/socket_F_1207/Config.lb b/src/cpu/amd/socket_F_1207/Config.lb
new file mode 100644
index 0000000000..6f87b315f2
--- /dev/null
+++ b/src/cpu/amd/socket_F_1207/Config.lb
@@ -0,0 +1,57 @@
+#
+# This file is part of the LinuxBIOS project.
+#
+# Copyright (C) 2007 Advanced Micro Devices, 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.
+#
+# 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
+#
+
+uses CONFIG_CHIP_NAME
+uses PCI_IO_CFG_EXT
+uses MMCONF_SUPPORT
+uses HT3_SUPPORT
+uses EXT_RT_TBL_SUPPORT
+uses EXT_CONF_SUPPORT
+uses DIMM_SUPPORT
+uses CPU_SOCKET_TYPE
+uses CBB
+uses CDB
+uses PCI_BUS_SEGN_BITS
+uses CAR_FAM10
+
+if CONFIG_CHIP_NAME
+ config chip.h
+end
+
+default PCI_IO_CFG_EXT=1
+
+default HT3_SUPPORT=1
+default EXT_RT_TBL_SUPPORT=0
+default EXT_CONF_SUPPORT=0
+default DIMM_SUPPORT=0x0104 #DDR2 and REG
+default CPU_SOCKET_TYPE=0x10
+
+default CAR_FAM10=1
+
+if EXT_RT_TBL_SUPPORT
+ default CBB=0xff
+ default CDB=0
+end
+
+#default MMCONF_SUPPORT=1
+#default MMCONF_SUPPORT_DEFAULT=1
+
+object socket_F_1207.o
+
+dir /cpu/amd/model_10xxx
diff --git a/src/cpu/amd/socket_F_1207/chip.h b/src/cpu/amd/socket_F_1207/chip.h
new file mode 100644
index 0000000000..7f794512c2
--- /dev/null
+++ b/src/cpu/amd/socket_F_1207/chip.h
@@ -0,0 +1,23 @@
+/*
+ * This file is part of the LinuxBIOS project.
+ *
+ * Copyright (C) 2007 Advanced Micro Devices, 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.
+ *
+ * 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
+ */
+
+extern struct chip_operations cpu_amd_socket_F_1207_ops;
+
+struct cpu_amd_socket_F_1207_config {
+};
diff --git a/src/cpu/amd/socket_F_1207/socket_F_1207.c b/src/cpu/amd/socket_F_1207/socket_F_1207.c
new file mode 100644
index 0000000000..fa51f2028f
--- /dev/null
+++ b/src/cpu/amd/socket_F_1207/socket_F_1207.c
@@ -0,0 +1,25 @@
+/*
+ * This file is part of the LinuxBIOS project.
+ *
+ * Copyright (C) 2007 Advanced Micro Devices, 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.
+ *
+ * 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
+ */
+
+#include <device/device.h>
+#include "chip.h"
+
+struct chip_operations cpu_amd_socket_F_1207_ops = {
+ CHIP_NAME("socket F_1207")
+};