Migrate fsp_206ax to SMM_MODULES
This gets rid of ugly tseg_relocate for fsp_bd82x6x.
This is adaptation of a3e41c0896
Change-Id: I4e80e6e98d3a6da3e3e480e9368fae1b3ed67cd6
Signed-off-by: Vladimir Serbinenko <phcoder@gmail.com>
Reviewed-on: http://review.coreboot.org/10353
Tested-by: build bot (Jenkins)
Reviewed-by: Aaron Durbin <adurbin@chromium.org>
			
			
This commit is contained in:
		@@ -37,6 +37,7 @@ config CPU_SPECIFIC_OPTIONS
 | 
			
		||||
	select SSE2
 | 
			
		||||
	select UDELAY_LAPIC
 | 
			
		||||
	select SMM_TSEG
 | 
			
		||||
	select SMM_MODULES
 | 
			
		||||
	select SUPPORT_CPU_UCODE_IN_CBFS if HAVE_FSP_BIN
 | 
			
		||||
	select PARALLEL_CPU_INIT
 | 
			
		||||
	select TSC_SYNC_MFENCE
 | 
			
		||||
 
 | 
			
		||||
@@ -13,3 +13,5 @@ ifneq ($(wildcard $(shell readlink -f "$(top)/$(CONFIG_MICROCODE_INCLUDE_PATH)")
 | 
			
		||||
CPPFLAGS_common += -I$(CONFIG_MICROCODE_INCLUDE_PATH)
 | 
			
		||||
endif
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
ramstage-$(CONFIG_HAVE_SMI_HANDLER) += smmrelocate.c
 | 
			
		||||
 
 | 
			
		||||
@@ -106,6 +106,7 @@ void intel_model_206ax_finalize_smm(void);
 | 
			
		||||
/* Configure power limits for turbo mode */
 | 
			
		||||
void set_power_limits(u8 power_limit_1_time);
 | 
			
		||||
int cpu_config_tdp_levels(void);
 | 
			
		||||
void smm_relocate(void);
 | 
			
		||||
#endif
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										333
									
								
								src/cpu/intel/fsp_model_206ax/smmrelocate.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										333
									
								
								src/cpu/intel/fsp_model_206ax/smmrelocate.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,333 @@
 | 
			
		||||
/*
 | 
			
		||||
 * This file is part of the coreboot project.
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright (C) 2013 ChromeOS Authors
 | 
			
		||||
 *
 | 
			
		||||
 * 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 <types.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include <device/device.h>
 | 
			
		||||
#include <device/pci.h>
 | 
			
		||||
#include <cpu/cpu.h>
 | 
			
		||||
#include <cpu/x86/cache.h>
 | 
			
		||||
#include <cpu/x86/msr.h>
 | 
			
		||||
#include <cpu/x86/mtrr.h>
 | 
			
		||||
#include <cpu/x86/smm.h>
 | 
			
		||||
#include <console/console.h>
 | 
			
		||||
#include <northbridge/intel/fsp_sandybridge/northbridge.h>
 | 
			
		||||
#include <southbridge/intel/fsp_bd82x6x/pch.h>
 | 
			
		||||
#include "model_206ax.h"
 | 
			
		||||
 | 
			
		||||
#define EMRRphysBase_MSR 0x1f4
 | 
			
		||||
#define EMRRphysMask_MSR 0x1f5
 | 
			
		||||
#define UNCORE_EMRRphysBase_MSR 0x2f4
 | 
			
		||||
#define UNCORE_EMRRphysMask_MSR 0x2f5
 | 
			
		||||
 | 
			
		||||
#define CORE_THREAD_COUNT_MSR 0x35
 | 
			
		||||
 | 
			
		||||
#define SMRR_SUPPORTED (1<<11)
 | 
			
		||||
#define EMRR_SUPPORTED (1<<12)
 | 
			
		||||
 | 
			
		||||
struct smm_relocation_params {
 | 
			
		||||
	u32 smram_base;
 | 
			
		||||
	u32 smram_size;
 | 
			
		||||
	u32 ied_base;
 | 
			
		||||
	u32 ied_size;
 | 
			
		||||
	msr_t smrr_base;
 | 
			
		||||
	msr_t smrr_mask;
 | 
			
		||||
	msr_t emrr_base;
 | 
			
		||||
	msr_t emrr_mask;
 | 
			
		||||
	msr_t uncore_emrr_base;
 | 
			
		||||
	msr_t uncore_emrr_mask;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* This gets filled in and used during relocation. */
 | 
			
		||||
static struct smm_relocation_params smm_reloc_params;
 | 
			
		||||
 | 
			
		||||
static inline void write_smrr(struct smm_relocation_params *relo_params)
 | 
			
		||||
{
 | 
			
		||||
	printk(BIOS_DEBUG, "Writing SMRR. base = 0x%08x, mask=0x%08x\n",
 | 
			
		||||
	       relo_params->smrr_base.lo, relo_params->smrr_mask.lo);
 | 
			
		||||
	wrmsr(SMRRphysBase_MSR, relo_params->smrr_base);
 | 
			
		||||
	wrmsr(SMRRphysMask_MSR, relo_params->smrr_mask);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline void write_emrr(struct smm_relocation_params *relo_params)
 | 
			
		||||
{
 | 
			
		||||
	printk(BIOS_DEBUG, "Writing EMRR. base = 0x%08x, mask=0x%08x\n",
 | 
			
		||||
	       relo_params->emrr_base.lo, relo_params->emrr_mask.lo);
 | 
			
		||||
	wrmsr(EMRRphysBase_MSR, relo_params->emrr_base);
 | 
			
		||||
	wrmsr(EMRRphysMask_MSR, relo_params->emrr_mask);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline void write_uncore_emrr(struct smm_relocation_params *relo_params)
 | 
			
		||||
{
 | 
			
		||||
	printk(BIOS_DEBUG,
 | 
			
		||||
	       "Writing UNCORE_EMRR. base = 0x%08x, mask=0x%08x\n",
 | 
			
		||||
	       relo_params->uncore_emrr_base.lo,
 | 
			
		||||
	       relo_params->uncore_emrr_mask.lo);
 | 
			
		||||
	wrmsr(UNCORE_EMRRphysBase_MSR, relo_params->uncore_emrr_base);
 | 
			
		||||
	wrmsr(UNCORE_EMRRphysMask_MSR, relo_params->uncore_emrr_mask);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* The relocation work is actually performed in SMM context, but the code
 | 
			
		||||
 * resides in the ramstage module. This occurs by trampolining from the default
 | 
			
		||||
 * SMRAM entry point to here. */
 | 
			
		||||
static void asmlinkage cpu_smm_do_relocation(void *arg)
 | 
			
		||||
{
 | 
			
		||||
	em64t101_smm_state_save_area_t *save_state;
 | 
			
		||||
	msr_t mtrr_cap;
 | 
			
		||||
	struct smm_relocation_params *relo_params;
 | 
			
		||||
	const struct smm_module_params *p;
 | 
			
		||||
	const struct smm_runtime *runtime;
 | 
			
		||||
	int cpu;
 | 
			
		||||
 | 
			
		||||
	p = arg;
 | 
			
		||||
	runtime = p->runtime;
 | 
			
		||||
	relo_params = p->arg;
 | 
			
		||||
	cpu = p->cpu;
 | 
			
		||||
 | 
			
		||||
	if (cpu >= CONFIG_MAX_CPUS) {
 | 
			
		||||
		printk(BIOS_CRIT,
 | 
			
		||||
		       "Invalid CPU number assigned in SMM stub: %d\n", cpu);
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	printk(BIOS_DEBUG, "In relocation handler: cpu %d\n", cpu);
 | 
			
		||||
 | 
			
		||||
	/* All threads need to set IEDBASE and SMBASE in the save state area.
 | 
			
		||||
	 * Since one thread runs at a time during the relocation the save state
 | 
			
		||||
	 * is the same for all cpus. */
 | 
			
		||||
	save_state = (void *)(runtime->smbase + SMM_DEFAULT_SIZE -
 | 
			
		||||
                              runtime->save_state_size);
 | 
			
		||||
 | 
			
		||||
	/* The relocated handler runs with all CPUs concurrently. Therefore
 | 
			
		||||
	 * stagger the entry points adjusting SMBASE downwards by save state
 | 
			
		||||
	 * size * CPU num. */
 | 
			
		||||
	save_state->smbase = relo_params->smram_base -
 | 
			
		||||
	                     cpu * runtime->save_state_size;
 | 
			
		||||
	save_state->iedbase = relo_params->ied_base;
 | 
			
		||||
 | 
			
		||||
	printk(BIOS_DEBUG, "New SMBASE=0x%08x IEDBASE=0x%08x @ %p\n",
 | 
			
		||||
	       save_state->smbase, save_state->iedbase, save_state);
 | 
			
		||||
 | 
			
		||||
	/* Write EMRR and SMRR MSRs based on indicated support. */
 | 
			
		||||
	mtrr_cap = rdmsr(MTRRcap_MSR);
 | 
			
		||||
	if (mtrr_cap.lo & SMRR_SUPPORTED)
 | 
			
		||||
		write_smrr(relo_params);
 | 
			
		||||
 | 
			
		||||
	if (mtrr_cap.lo & EMRR_SUPPORTED) {
 | 
			
		||||
		write_emrr(relo_params);
 | 
			
		||||
		/* UNCORE_EMRR msrs are package level. Therefore, only
 | 
			
		||||
		 * configure these MSRs on the BSP. */
 | 
			
		||||
		if (cpu == 0)
 | 
			
		||||
			write_uncore_emrr(relo_params);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	southbridge_clear_smi_status();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static u32 northbridge_get_base_reg(device_t dev, int reg)
 | 
			
		||||
{
 | 
			
		||||
	u32 value;
 | 
			
		||||
 | 
			
		||||
	value = pci_read_config32(dev, reg);
 | 
			
		||||
	/* Base registers are at 1MiB granularity. */
 | 
			
		||||
	value &= ~((1 << 20) - 1);
 | 
			
		||||
	return value;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void fill_in_relocation_params(device_t dev,
 | 
			
		||||
                                      struct smm_relocation_params *params)
 | 
			
		||||
{
 | 
			
		||||
	u32 tseg_size;
 | 
			
		||||
	u32 tsegmb;
 | 
			
		||||
	u32 bgsm;
 | 
			
		||||
	u32 emrr_base;
 | 
			
		||||
	u32 emrr_size;
 | 
			
		||||
	int phys_bits;
 | 
			
		||||
	/* All range registers are aligned to 4KiB */
 | 
			
		||||
	const u32 rmask = ~((1 << 12) - 1);
 | 
			
		||||
 | 
			
		||||
	/* Some of the range registers are dependent on the number of physical
 | 
			
		||||
	 * address bits supported. */
 | 
			
		||||
	phys_bits = cpuid_eax(0x80000008) & 0xff;
 | 
			
		||||
 | 
			
		||||
	/* The range bounded by the TSEGMB and BGSM registers encompasses the
 | 
			
		||||
	 * SMRAM range as well as the IED range. However, the SMRAM available
 | 
			
		||||
	 * to the handler is 4MiB since the IEDRAM lives TSEGMB + 4MiB.
 | 
			
		||||
	 */
 | 
			
		||||
	tsegmb = northbridge_get_base_reg(dev, TSEG);
 | 
			
		||||
	bgsm = northbridge_get_base_reg(dev, BGSM);
 | 
			
		||||
	tseg_size = bgsm - tsegmb;
 | 
			
		||||
 | 
			
		||||
	params->smram_base = tsegmb;
 | 
			
		||||
	params->smram_size = 4 << 20;
 | 
			
		||||
	params->ied_base = tsegmb + params->smram_size;
 | 
			
		||||
	params->ied_size = tseg_size - params->smram_size;
 | 
			
		||||
 | 
			
		||||
	/* SMRR has 32-bits of valid address aligned to 4KiB. */
 | 
			
		||||
	params->smrr_base.lo = (params->smram_base & rmask) | MTRR_TYPE_WRBACK;
 | 
			
		||||
	params->smrr_base.hi = 0;
 | 
			
		||||
	params->smrr_mask.lo = (~(tseg_size - 1) & rmask) | MTRRphysMaskValid;
 | 
			
		||||
	params->smrr_mask.hi = 0;
 | 
			
		||||
 | 
			
		||||
	/* The EMRR and UNCORE_EMRR are at IEDBASE + 2MiB */
 | 
			
		||||
	emrr_base = (params->ied_base + (2 << 20)) & rmask;
 | 
			
		||||
	emrr_size = params->ied_size - (2 << 20);
 | 
			
		||||
 | 
			
		||||
	/* EMRR has 46 bits of valid address aligned to 4KiB. It's dependent
 | 
			
		||||
	 * on the number of physical address bits supported. */
 | 
			
		||||
	params->emrr_base.lo = emrr_base | MTRR_TYPE_WRBACK;
 | 
			
		||||
	params->emrr_base.hi = 0;
 | 
			
		||||
	params->emrr_mask.lo = (~(emrr_size - 1) & rmask) | MTRRphysMaskValid;
 | 
			
		||||
	params->emrr_mask.hi = (1 << (phys_bits - 32)) - 1;
 | 
			
		||||
 | 
			
		||||
	/* UNCORE_EMRR has 39 bits of valid address aligned to 4KiB. */
 | 
			
		||||
	params->uncore_emrr_base.lo = emrr_base;
 | 
			
		||||
	params->uncore_emrr_base.hi = 0;
 | 
			
		||||
	params->uncore_emrr_mask.lo = (~(emrr_size - 1) & rmask) |
 | 
			
		||||
	                              MTRRphysMaskValid;
 | 
			
		||||
	params->uncore_emrr_mask.hi = (1 << (39 - 32)) - 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int install_relocation_handler(int num_cpus,
 | 
			
		||||
                                      struct smm_relocation_params *relo_params)
 | 
			
		||||
{
 | 
			
		||||
	/* The default SMM entry happens serially at the default location.
 | 
			
		||||
	 * Therefore, there is only 1 concurrent save state area. Set the
 | 
			
		||||
	 * stack size to the save state size, and call into the
 | 
			
		||||
	 * do_relocation handler. */
 | 
			
		||||
	int save_state_size = sizeof(em64t101_smm_state_save_area_t);
 | 
			
		||||
	struct smm_loader_params smm_params = {
 | 
			
		||||
		.per_cpu_stack_size = save_state_size,
 | 
			
		||||
		.num_concurrent_stacks = num_cpus,
 | 
			
		||||
		.per_cpu_save_state_size = save_state_size,
 | 
			
		||||
		.num_concurrent_save_states = 1,
 | 
			
		||||
		.handler = &cpu_smm_do_relocation,
 | 
			
		||||
		.handler_arg = (void *)relo_params,
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	return smm_setup_relocation_handler(&smm_params);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void setup_ied_area(struct smm_relocation_params *params)
 | 
			
		||||
{
 | 
			
		||||
	char *ied_base;
 | 
			
		||||
 | 
			
		||||
	struct ied_header ied = {
 | 
			
		||||
		.signature = "INTEL RSVD",
 | 
			
		||||
		.size = params->ied_size,
 | 
			
		||||
		.reserved = {0},
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	ied_base = (void *)params->ied_base;
 | 
			
		||||
 | 
			
		||||
	/* Place IED header at IEDBASE. */
 | 
			
		||||
	memcpy(ied_base, &ied, sizeof(ied));
 | 
			
		||||
 | 
			
		||||
	/* Zero out 32KiB at IEDBASE + 1MiB */
 | 
			
		||||
	memset(ied_base + (1 << 20), 0, (32 << 10));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int install_permanent_handler(int num_cpus,
 | 
			
		||||
                                     struct smm_relocation_params *relo_params)
 | 
			
		||||
{
 | 
			
		||||
	/* There are num_cpus concurrent stacks and num_cpus concurrent save
 | 
			
		||||
	 * state areas. Lastly, set the stack size to the save state size. */
 | 
			
		||||
	int save_state_size = sizeof(em64t101_smm_state_save_area_t);
 | 
			
		||||
	struct smm_loader_params smm_params = {
 | 
			
		||||
		.per_cpu_stack_size = save_state_size,
 | 
			
		||||
		.num_concurrent_stacks = num_cpus,
 | 
			
		||||
		.per_cpu_save_state_size = save_state_size,
 | 
			
		||||
		.num_concurrent_save_states = num_cpus,
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	printk(BIOS_DEBUG, "Installing SMM handler to 0x%08x\n",
 | 
			
		||||
	       relo_params->smram_base);
 | 
			
		||||
	return smm_load_module((void *)relo_params->smram_base,
 | 
			
		||||
	                       relo_params->smram_size, &smm_params);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int cpu_smm_setup(void)
 | 
			
		||||
{
 | 
			
		||||
	device_t dev;
 | 
			
		||||
	int num_cpus;
 | 
			
		||||
	msr_t msr;
 | 
			
		||||
 | 
			
		||||
	printk(BIOS_DEBUG, "Setting up SMI for CPU\n");
 | 
			
		||||
 | 
			
		||||
	dev = dev_find_slot(0, PCI_DEVFN(0, 0));
 | 
			
		||||
 | 
			
		||||
	fill_in_relocation_params(dev, &smm_reloc_params);
 | 
			
		||||
 | 
			
		||||
	setup_ied_area(&smm_reloc_params);
 | 
			
		||||
 | 
			
		||||
	msr = rdmsr(CORE_THREAD_COUNT_MSR);
 | 
			
		||||
	num_cpus = msr.lo & 0xffff;
 | 
			
		||||
	if (num_cpus > CONFIG_MAX_CPUS) {
 | 
			
		||||
		printk(BIOS_CRIT,
 | 
			
		||||
		       "Error: Hardware CPUs (%d) > MAX_CPUS (%d)\n",
 | 
			
		||||
		       num_cpus, CONFIG_MAX_CPUS);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (install_relocation_handler(num_cpus, &smm_reloc_params)) {
 | 
			
		||||
		printk(BIOS_CRIT, "SMM Relocation handler install failed.\n");
 | 
			
		||||
		return -1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (install_permanent_handler(num_cpus, &smm_reloc_params)) {
 | 
			
		||||
		printk(BIOS_CRIT, "SMM Permanent handler install failed.\n");
 | 
			
		||||
		return -1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Ensure the SMM handlers hit DRAM before performing first SMI. */
 | 
			
		||||
	/* TODO(adurbin): Is this really needed? */
 | 
			
		||||
	wbinvd();
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void smm_init(void)
 | 
			
		||||
{
 | 
			
		||||
	/* Return early if CPU SMM setup failed. */
 | 
			
		||||
	if (cpu_smm_setup())
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	southbridge_smm_init();
 | 
			
		||||
 | 
			
		||||
	/* Initiate first SMI to kick off SMM-context relocation. Note: this
 | 
			
		||||
	 * SMI being triggered here queues up an SMI in the APs which are in
 | 
			
		||||
	 * wait-for-SIPI state. Once an AP gets an SIPI it will service the SMI
 | 
			
		||||
	 * at the SMM_DEFAULT_BASE before jumping to startup vector. */
 | 
			
		||||
	southbridge_trigger_smi();
 | 
			
		||||
 | 
			
		||||
	printk(BIOS_DEBUG, "Relocation complete.\n");
 | 
			
		||||
 | 
			
		||||
	/* Lock down the SMRAM space. */
 | 
			
		||||
	smm_lock();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void smm_lock(void)
 | 
			
		||||
{
 | 
			
		||||
	/* LOCK the SMM memory window and enable normal SMM.
 | 
			
		||||
	 * After running this function, only a full reset can
 | 
			
		||||
	 * make the SMM registers writable again.
 | 
			
		||||
	 */
 | 
			
		||||
	printk(BIOS_DEBUG, "Locking SMM.\n");
 | 
			
		||||
	pci_write_config8(dev_find_slot(0, PCI_DEVFN(0, 0)), SMRAM,
 | 
			
		||||
			D_LCK | G_SMRAME | C_BASE_SEG);
 | 
			
		||||
}
 | 
			
		||||
@@ -36,8 +36,6 @@
 | 
			
		||||
#include "../../../southbridge/intel/i82801dx/i82801dx.h"
 | 
			
		||||
#elif CONFIG_SOUTHBRIDGE_INTEL_SCH
 | 
			
		||||
#include "../../../southbridge/intel/sch/sch.h"
 | 
			
		||||
#elif CONFIG_SOUTHBRIDGE_INTEL_FSP_BD82X6X
 | 
			
		||||
#include "../../../southbridge/intel/fsp_bd82x6x/pch.h"
 | 
			
		||||
#elif CONFIG_SOUTHBRIDGE_INTEL_I82801IX
 | 
			
		||||
#include "../../../southbridge/intel/i82801ix/i82801ix.h"
 | 
			
		||||
#else
 | 
			
		||||
@@ -45,15 +43,7 @@
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if CONFIG_SMM_TSEG
 | 
			
		||||
 | 
			
		||||
#if CONFIG_NORTHBRIDGE_INTEL_FSP_SANDYBRIDGE || CONFIG_NORTHBRIDGE_INTEL_FSP_IVYBRIDGE
 | 
			
		||||
#include <northbridge/intel/fsp_sandybridge/northbridge.h>
 | 
			
		||||
#define TSEG_BAR (DEFAULT_PCIEXBAR | TSEG)
 | 
			
		||||
#else
 | 
			
		||||
#error "Northbridge must define TSEG_BAR."
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#include <cpu/x86/mtrr.h>
 | 
			
		||||
#error "Don't use this file with TSEG."
 | 
			
		||||
 | 
			
		||||
#endif /* CONFIG_SMM_TSEG */
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -102,6 +102,7 @@
 | 
			
		||||
 | 
			
		||||
#define TOM		0xa0
 | 
			
		||||
#define TOUUD		0xa8	/* Top of Upper Usable DRAM */
 | 
			
		||||
#define BGSM		0xb4	/* Base GTT Stolen Memory */
 | 
			
		||||
#define TSEG		0xb8	/* TSEG base */
 | 
			
		||||
#define TOLUD		0xbc	/* Top of Low Used Memory */
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -42,7 +42,6 @@
 | 
			
		||||
#define NMI_OFF	0
 | 
			
		||||
 | 
			
		||||
#define ENABLE_ACPI_MODE_IN_COREBOOT	0
 | 
			
		||||
#define TEST_SMM_FLASH_LOCKDOWN		0
 | 
			
		||||
 | 
			
		||||
typedef struct southbridge_intel_fsp_bd82x6x_config config_t;
 | 
			
		||||
 | 
			
		||||
@@ -405,58 +404,20 @@ static void enable_hpet(void)
 | 
			
		||||
	RCBA32(HPTC) = reg32;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#if CONFIG_HAVE_SMI_HANDLER
 | 
			
		||||
static void pch_lock_smm(struct device *dev)
 | 
			
		||||
static void pch_set_acpi_mode(void)
 | 
			
		||||
{
 | 
			
		||||
#if TEST_SMM_FLASH_LOCKDOWN
 | 
			
		||||
	u8 reg8;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
	if (!acpi_is_wakeup_s3()) {
 | 
			
		||||
	if (!acpi_is_wakeup_s3() && CONFIG_HAVE_SMI_HANDLER) {
 | 
			
		||||
#if ENABLE_ACPI_MODE_IN_COREBOOT
 | 
			
		||||
		printk(BIOS_DEBUG, "Enabling ACPI via APMC:\n");
 | 
			
		||||
		outb(0xe1, 0xb2); // Enable ACPI mode
 | 
			
		||||
		outb(APM_CNT_ACPI_ENABLE, APM_CNT); // Enable ACPI mode
 | 
			
		||||
		printk(BIOS_DEBUG, "done.\n");
 | 
			
		||||
#else
 | 
			
		||||
		printk(BIOS_DEBUG, "Disabling ACPI via APMC:\n");
 | 
			
		||||
		outb(0x1e, 0xb2); // Disable ACPI mode
 | 
			
		||||
		outb(APM_CNT_ACPI_DISABLE, APM_CNT); // Disable ACPI mode
 | 
			
		||||
		printk(BIOS_DEBUG, "done.\n");
 | 
			
		||||
#endif
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Don't allow evil boot loaders, kernels, or
 | 
			
		||||
	 * userspace applications to deceive us:
 | 
			
		||||
	 */
 | 
			
		||||
	smm_lock();
 | 
			
		||||
 | 
			
		||||
#if TEST_SMM_FLASH_LOCKDOWN
 | 
			
		||||
	/* Now try this: */
 | 
			
		||||
	printk(BIOS_DEBUG, "Locking BIOS to RO... ");
 | 
			
		||||
	reg8 = pci_read_config8(dev, 0xdc);	/* BIOS_CNTL */
 | 
			
		||||
	printk(BIOS_DEBUG, " BLE: %s; BWE: %s\n", (reg8&2)?"on":"off",
 | 
			
		||||
			(reg8&1)?"rw":"ro");
 | 
			
		||||
	reg8 &= ~(1 << 0);			/* clear BIOSWE */
 | 
			
		||||
	pci_write_config8(dev, 0xdc, reg8);
 | 
			
		||||
	reg8 |= (1 << 1);			/* set BLE */
 | 
			
		||||
	pci_write_config8(dev, 0xdc, reg8);
 | 
			
		||||
	printk(BIOS_DEBUG, "ok.\n");
 | 
			
		||||
	reg8 = pci_read_config8(dev, 0xdc);	/* BIOS_CNTL */
 | 
			
		||||
	printk(BIOS_DEBUG, " BLE: %s; BWE: %s\n", (reg8&2)?"on":"off",
 | 
			
		||||
			(reg8&1)?"rw":"ro");
 | 
			
		||||
 | 
			
		||||
	printk(BIOS_DEBUG, "Writing:\n");
 | 
			
		||||
	*(volatile u8 *)0xfff00000 = 0x00;
 | 
			
		||||
	printk(BIOS_DEBUG, "Testing:\n");
 | 
			
		||||
	reg8 |= (1 << 0);			/* set BIOSWE */
 | 
			
		||||
	pci_write_config8(dev, 0xdc, reg8);
 | 
			
		||||
 | 
			
		||||
	reg8 = pci_read_config8(dev, 0xdc);	/* BIOS_CNTL */
 | 
			
		||||
	printk(BIOS_DEBUG, " BLE: %s; BWE: %s\n", (reg8&2)?"on":"off",
 | 
			
		||||
			(reg8&1)?"rw":"ro");
 | 
			
		||||
	printk(BIOS_DEBUG, "Done.\n");
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
static void pch_disable_smm_only_flashing(struct device *dev)
 | 
			
		||||
{
 | 
			
		||||
@@ -541,9 +502,7 @@ static void lpc_init(struct device *dev)
 | 
			
		||||
 | 
			
		||||
	pch_disable_smm_only_flashing(dev);
 | 
			
		||||
 | 
			
		||||
#if CONFIG_HAVE_SMI_HANDLER
 | 
			
		||||
	pch_lock_smm(dev);
 | 
			
		||||
#endif
 | 
			
		||||
	pch_set_acpi_mode();
 | 
			
		||||
 | 
			
		||||
	pch_fixups(dev);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -64,6 +64,11 @@ void intel_pch_finalize_smm(void);
 | 
			
		||||
#if !defined(__ASSEMBLER__) && !defined(__ROMCC__)
 | 
			
		||||
#if !defined(__PRE_RAM__) && !defined(__SMM__)
 | 
			
		||||
#include "chip.h"
 | 
			
		||||
/* These helpers are for performing SMM relocation. */
 | 
			
		||||
void southbridge_smm_init(void);
 | 
			
		||||
void southbridge_trigger_smi(void);
 | 
			
		||||
void southbridge_clear_smi_status(void);
 | 
			
		||||
 | 
			
		||||
int pch_silicon_revision(void);
 | 
			
		||||
int pch_silicon_type(void);
 | 
			
		||||
int pch_silicon_supported(int type, int rev);
 | 
			
		||||
 
 | 
			
		||||
@@ -29,13 +29,6 @@
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include "pch.h"
 | 
			
		||||
 | 
			
		||||
#if CONFIG_NORTHBRIDGE_INTEL_FSP_SANDYBRIDGE || CONFIG_NORTHBRIDGE_INTEL_FSP_IVYBRIDGE
 | 
			
		||||
#include "northbridge/intel/fsp_sandybridge/northbridge.h"
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
extern unsigned char _binary_smm_start;
 | 
			
		||||
extern unsigned char _binary_smm_size;
 | 
			
		||||
 | 
			
		||||
/* While we read PMBASE dynamically in case it changed, let's
 | 
			
		||||
 * initialize it with a sane value
 | 
			
		||||
 */
 | 
			
		||||
@@ -231,15 +224,18 @@ static void smi_set_eos(void)
 | 
			
		||||
	outb(reg8, pmbase + SMI_EN);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
extern uint8_t smm_relocation_start, smm_relocation_end;
 | 
			
		||||
 | 
			
		||||
static void smm_relocate(void)
 | 
			
		||||
void southbridge_smm_init(void)
 | 
			
		||||
{
 | 
			
		||||
	u32 smi_en;
 | 
			
		||||
	u16 pm1_en;
 | 
			
		||||
	u32 gpe0_en;
 | 
			
		||||
 | 
			
		||||
	printk(BIOS_DEBUG, "Initializing SMM handler...");
 | 
			
		||||
#if CONFIG_ELOG
 | 
			
		||||
	/* Log events from chipset before clearing */
 | 
			
		||||
	pch_log_state();
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
	printk(BIOS_DEBUG, "Initializing southbridge SMI...");
 | 
			
		||||
 | 
			
		||||
	pmbase = pci_read_config32(dev_find_slot(0, PCI_DEVFN(0x1f, 0)),
 | 
			
		||||
							PMBASE) & 0xff80;
 | 
			
		||||
@@ -252,10 +248,6 @@ static void smm_relocate(void)
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* copy the SMM relocation code */
 | 
			
		||||
	memcpy((void *)0x38000, &smm_relocation_start,
 | 
			
		||||
			&smm_relocation_end - &smm_relocation_start);
 | 
			
		||||
 | 
			
		||||
	printk(BIOS_DEBUG, "\n");
 | 
			
		||||
	dump_smi_status(reset_smi_status());
 | 
			
		||||
	dump_pm1_status(reset_pm1_status());
 | 
			
		||||
@@ -304,7 +296,10 @@ static void smm_relocate(void)
 | 
			
		||||
	smi_en |= EOS | GBL_SMI_EN;
 | 
			
		||||
 | 
			
		||||
	outl(smi_en, pmbase + SMI_EN);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void southbridge_trigger_smi(void)
 | 
			
		||||
{
 | 
			
		||||
	/**
 | 
			
		||||
	 * There are several methods of raising a controlled SMI# via
 | 
			
		||||
	 * software, among them:
 | 
			
		||||
@@ -323,76 +318,16 @@ static void smm_relocate(void)
 | 
			
		||||
	outb(0x00, 0xb2);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int smm_handler_copied = 0;
 | 
			
		||||
 | 
			
		||||
static void smm_install(void)
 | 
			
		||||
void southbridge_clear_smi_status(void)
 | 
			
		||||
{
 | 
			
		||||
	device_t dev = dev_find_slot(0, PCI_DEVFN(0, 0));
 | 
			
		||||
	u32 smm_base = 0xa0000;
 | 
			
		||||
	struct ied_header ied = {
 | 
			
		||||
		.signature = "INTEL RSVD",
 | 
			
		||||
		.size = IED_SIZE,
 | 
			
		||||
		.reserved = {0},
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	/* The first CPU running this gets to copy the SMM handler. But not all
 | 
			
		||||
	 * of them.
 | 
			
		||||
	 */
 | 
			
		||||
	if (smm_handler_copied)
 | 
			
		||||
		return;
 | 
			
		||||
	smm_handler_copied = 1;
 | 
			
		||||
 | 
			
		||||
	/* enable the SMM memory window */
 | 
			
		||||
	pci_write_config8(dev, SMRAM, D_OPEN | G_SMRAME | C_BASE_SEG);
 | 
			
		||||
 | 
			
		||||
#if CONFIG_SMM_TSEG
 | 
			
		||||
	smm_base = pci_read_config32(dev, TSEG) & ~1;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
	/* copy the real SMM handler */
 | 
			
		||||
	printk(BIOS_DEBUG, "Installing SMM handler to 0x%08x\n", smm_base);
 | 
			
		||||
	memcpy((void *)smm_base, &_binary_smm_start, (size_t)&_binary_smm_size);
 | 
			
		||||
 | 
			
		||||
	/* copy the IED header into place */
 | 
			
		||||
	if (CONFIG_SMM_TSEG_SIZE > IED_SIZE) {
 | 
			
		||||
		/* Top of TSEG region */
 | 
			
		||||
		smm_base += CONFIG_SMM_TSEG_SIZE - IED_SIZE;
 | 
			
		||||
		printk(BIOS_DEBUG, "Installing IED header to 0x%08x\n",
 | 
			
		||||
		       smm_base);
 | 
			
		||||
		memcpy((void *)smm_base, &ied, sizeof(ied));
 | 
			
		||||
	}
 | 
			
		||||
	wbinvd();
 | 
			
		||||
 | 
			
		||||
	/* close the SMM memory window and enable normal SMM */
 | 
			
		||||
	pci_write_config8(dev, SMRAM, G_SMRAME | C_BASE_SEG);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void smm_init(void)
 | 
			
		||||
{
 | 
			
		||||
#if CONFIG_ELOG
 | 
			
		||||
	/* Log events from chipset before clearing */
 | 
			
		||||
	pch_log_state();
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
	/* Put SMM code to 0xa0000 */
 | 
			
		||||
	smm_install();
 | 
			
		||||
 | 
			
		||||
	/* Put relocation code to 0x38000 and relocate SMBASE */
 | 
			
		||||
	smm_relocate();
 | 
			
		||||
 | 
			
		||||
	/* We're done. Make sure SMIs can happen! */
 | 
			
		||||
	smi_set_eos();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void smm_lock(void)
 | 
			
		||||
{
 | 
			
		||||
	/* LOCK the SMM memory window and enable normal SMM.
 | 
			
		||||
	 * After running this function, only a full reset can
 | 
			
		||||
	 * make the SMM registers writable again.
 | 
			
		||||
	 */
 | 
			
		||||
	printk(BIOS_DEBUG, "Locking SMM.\n");
 | 
			
		||||
	pci_write_config8(dev_find_slot(0, PCI_DEVFN(0, 0)), SMRAM,
 | 
			
		||||
			D_LCK | G_SMRAME | C_BASE_SEG);
 | 
			
		||||
	/* Clear SMI status */
 | 
			
		||||
	reset_smi_status();
 | 
			
		||||
 
 | 
			
		||||
	/* Clear PM1 status */
 | 
			
		||||
	reset_pm1_status();
 | 
			
		||||
 
 | 
			
		||||
	/* Set EOS bit so other SMIs can occur. */
 | 
			
		||||
 	smi_set_eos();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void smm_setup_structures(void *gnvs, void *tcg, void *smi1)
 | 
			
		||||
 
 | 
			
		||||
@@ -51,28 +51,12 @@ static u8 smm_initialized = 0;
 | 
			
		||||
/* GNVS needs to be updated by an 0xEA PM Trap (B2) after it has been located
 | 
			
		||||
 * by coreboot.
 | 
			
		||||
 */
 | 
			
		||||
static global_nvs_t *gnvs = (global_nvs_t *)0x0;
 | 
			
		||||
static global_nvs_t *gnvs;
 | 
			
		||||
global_nvs_t *smm_get_gnvs(void)
 | 
			
		||||
{
 | 
			
		||||
	return gnvs;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#if CONFIG_SMM_TSEG
 | 
			
		||||
static u32 tseg_base = 0;
 | 
			
		||||
u32 smi_get_tseg_base(void)
 | 
			
		||||
{
 | 
			
		||||
	if (!tseg_base)
 | 
			
		||||
		tseg_base = pcie_read_config32(PCI_DEV(0, 0, 0), TSEG) & ~1;
 | 
			
		||||
	return tseg_base;
 | 
			
		||||
}
 | 
			
		||||
void tseg_relocate(void **ptr)
 | 
			
		||||
{
 | 
			
		||||
	/* Adjust pointer with TSEG base */
 | 
			
		||||
	if (*ptr && *ptr < (void*)smi_get_tseg_base())
 | 
			
		||||
		*ptr = (void *)(((u8*)*ptr) + smi_get_tseg_base());
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief read and clear PM1_STS
 | 
			
		||||
 * @return PM1_STS register
 | 
			
		||||
@@ -323,7 +307,7 @@ static void southbridge_gate_memory_reset(void)
 | 
			
		||||
	outl(reg32, gpiobase + GP_LVL2);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void southbridge_smi_sleep(unsigned int node, smm_state_save_area_t *state_save)
 | 
			
		||||
static void southbridge_smi_sleep(void)
 | 
			
		||||
{
 | 
			
		||||
	u8 reg8;
 | 
			
		||||
	u32 reg32;
 | 
			
		||||
@@ -338,8 +322,6 @@ static void southbridge_smi_sleep(unsigned int node, smm_state_save_area_t *stat
 | 
			
		||||
	outb(tmp70, 0x70);
 | 
			
		||||
	outb(tmp72, 0x72);
 | 
			
		||||
 | 
			
		||||
	void (*mainboard_sleep)(u8 slp_typ) = mainboard_smi_sleep;
 | 
			
		||||
 | 
			
		||||
	/* First, disable further SMIs */
 | 
			
		||||
	reg8 = inb(pmbase + SMI_EN);
 | 
			
		||||
	reg8 &= ~SLP_SMI_EN;
 | 
			
		||||
@@ -351,8 +333,7 @@ static void southbridge_smi_sleep(unsigned int node, smm_state_save_area_t *stat
 | 
			
		||||
	slp_typ = (reg32 >> 10) & 7;
 | 
			
		||||
 | 
			
		||||
	/* Do any mainboard sleep handling */
 | 
			
		||||
	tseg_relocate((void **)&mainboard_sleep);
 | 
			
		||||
	mainboard_sleep(slp_typ-2);
 | 
			
		||||
	mainboard_smi_sleep(slp_typ-2);
 | 
			
		||||
 | 
			
		||||
#if CONFIG_ELOG_GSMI
 | 
			
		||||
	/* Log S3, S4, and S5 entry */
 | 
			
		||||
@@ -428,13 +409,11 @@ static void southbridge_smi_sleep(unsigned int node, smm_state_save_area_t *stat
 | 
			
		||||
static em64t101_smm_state_save_area_t *smi_apmc_find_state_save(u8 cmd)
 | 
			
		||||
{
 | 
			
		||||
	em64t101_smm_state_save_area_t *state;
 | 
			
		||||
	u32 base = smi_get_tseg_base() + 0x8000 + 0x7d00;
 | 
			
		||||
	int node;
 | 
			
		||||
 | 
			
		||||
	/* Check all nodes looking for the one that issued the IO */
 | 
			
		||||
	for (node = 0; node < CONFIG_MAX_CPUS; node++) {
 | 
			
		||||
		state = (em64t101_smm_state_save_area_t *)
 | 
			
		||||
			(base - (node * 0x400));
 | 
			
		||||
		state = smm_get_save_state(node);
 | 
			
		||||
 | 
			
		||||
		/* Check for Synchronous IO (bit0==1) */
 | 
			
		||||
		if (!(state->io_misc_info & (1 << 0)))
 | 
			
		||||
@@ -481,11 +460,10 @@ static void southbridge_smi_gsmi(void)
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
static void southbridge_smi_apmc(unsigned int node, smm_state_save_area_t *state_save)
 | 
			
		||||
static void southbridge_smi_apmc(void)
 | 
			
		||||
{
 | 
			
		||||
	u32 pmctrl;
 | 
			
		||||
	u8 reg8;
 | 
			
		||||
	int (*mainboard_apmc)(u8 apmc) = mainboard_smi_apmc;
 | 
			
		||||
	em64t101_smm_state_save_area_t *state;
 | 
			
		||||
 | 
			
		||||
	/* Emulate B2 register as the FADT / Linux expects it */
 | 
			
		||||
@@ -538,11 +516,10 @@ static void southbridge_smi_apmc(unsigned int node, smm_state_save_area_t *state
 | 
			
		||||
#endif
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	tseg_relocate((void **)&mainboard_apmc);
 | 
			
		||||
	mainboard_apmc(reg8);
 | 
			
		||||
	mainboard_smi_apmc(reg8);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void southbridge_smi_pm1(unsigned int node, smm_state_save_area_t *state_save)
 | 
			
		||||
static void southbridge_smi_pm1(void)
 | 
			
		||||
{
 | 
			
		||||
	u16 pm1_sts;
 | 
			
		||||
 | 
			
		||||
@@ -563,7 +540,7 @@ static void southbridge_smi_pm1(unsigned int node, smm_state_save_area_t *state_
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void southbridge_smi_gpe0(unsigned int node, smm_state_save_area_t *state_save)
 | 
			
		||||
static void southbridge_smi_gpe0(void)
 | 
			
		||||
{
 | 
			
		||||
	u32 gpe0_sts;
 | 
			
		||||
 | 
			
		||||
@@ -571,17 +548,15 @@ static void southbridge_smi_gpe0(unsigned int node, smm_state_save_area_t *state
 | 
			
		||||
	dump_gpe0_status(gpe0_sts);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void southbridge_smi_gpi(unsigned int node, smm_state_save_area_t *state_save)
 | 
			
		||||
static void southbridge_smi_gpi(void)
 | 
			
		||||
{
 | 
			
		||||
	void (*mainboard_gpi)(u32 gpi_sts) = mainboard_smi_gpi;
 | 
			
		||||
	u16 reg16;
 | 
			
		||||
	reg16 = inw(pmbase + ALT_GP_SMI_STS);
 | 
			
		||||
	outw(reg16, pmbase + ALT_GP_SMI_STS);
 | 
			
		||||
 | 
			
		||||
	reg16 &= inw(pmbase + ALT_GP_SMI_EN);
 | 
			
		||||
 | 
			
		||||
	tseg_relocate((void **)&mainboard_gpi);
 | 
			
		||||
	mainboard_gpi(reg16);
 | 
			
		||||
	mainboard_smi_gpi(reg16);
 | 
			
		||||
 | 
			
		||||
	if (reg16)
 | 
			
		||||
		printk(BIOS_DEBUG, "GPI (mask %04x)\n",reg16);
 | 
			
		||||
@@ -589,7 +564,7 @@ static void southbridge_smi_gpi(unsigned int node, smm_state_save_area_t *state_
 | 
			
		||||
	outw(reg16, pmbase + ALT_GP_SMI_STS);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void southbridge_smi_mc(unsigned int node, smm_state_save_area_t *state_save)
 | 
			
		||||
static void southbridge_smi_mc(void)
 | 
			
		||||
{
 | 
			
		||||
	u32 reg32;
 | 
			
		||||
 | 
			
		||||
@@ -604,7 +579,7 @@ static void southbridge_smi_mc(unsigned int node, smm_state_save_area_t *state_s
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static void southbridge_smi_tco(unsigned int node, smm_state_save_area_t *state_save)
 | 
			
		||||
static void southbridge_smi_tco(void)
 | 
			
		||||
{
 | 
			
		||||
	u32 tco_sts;
 | 
			
		||||
 | 
			
		||||
@@ -641,7 +616,7 @@ static void southbridge_smi_tco(unsigned int node, smm_state_save_area_t *state_
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void southbridge_smi_periodic(unsigned int node, smm_state_save_area_t *state_save)
 | 
			
		||||
static void southbridge_smi_periodic(void)
 | 
			
		||||
{
 | 
			
		||||
	u32 reg32;
 | 
			
		||||
 | 
			
		||||
@@ -654,7 +629,7 @@ static void southbridge_smi_periodic(unsigned int node, smm_state_save_area_t *s
 | 
			
		||||
	printk(BIOS_DEBUG, "Periodic SMI.\n");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void southbridge_smi_monitor(unsigned int node, smm_state_save_area_t *state_save)
 | 
			
		||||
static void southbridge_smi_monitor(void)
 | 
			
		||||
{
 | 
			
		||||
#define IOTRAP(x) (trap_sts & (1 << x))
 | 
			
		||||
	u32 trap_sts, trap_cycle;
 | 
			
		||||
@@ -708,8 +683,7 @@ static void southbridge_smi_monitor(unsigned int node, smm_state_save_area_t *st
 | 
			
		||||
#undef IOTRAP
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
typedef void (*smi_handler_t)(unsigned int node,
 | 
			
		||||
		smm_state_save_area_t *state_save);
 | 
			
		||||
typedef void (*smi_handler_t)(void);
 | 
			
		||||
 | 
			
		||||
static smi_handler_t southbridge_smi[32] = {
 | 
			
		||||
	NULL,			  //  [0] reserved
 | 
			
		||||
@@ -753,7 +727,7 @@ static smi_handler_t southbridge_smi[32] = {
 | 
			
		||||
 * @param state_save
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
void southbridge_smi_handler(unsigned int node, smm_state_save_area_t *state_save)
 | 
			
		||||
void southbridge_smi_handler(void)
 | 
			
		||||
{
 | 
			
		||||
	int i, dump = 0;
 | 
			
		||||
	u32 smi_sts;
 | 
			
		||||
@@ -770,15 +744,7 @@ void southbridge_smi_handler(unsigned int node, smm_state_save_area_t *state_sav
 | 
			
		||||
	for (i = 0; i < 31; i++) {
 | 
			
		||||
		if (smi_sts & (1 << i)) {
 | 
			
		||||
			if (southbridge_smi[i]) {
 | 
			
		||||
#if CONFIG_SMM_TSEG
 | 
			
		||||
				smi_handler_t handler = (smi_handler_t)
 | 
			
		||||
					((u8*)southbridge_smi[i] +
 | 
			
		||||
					 smi_get_tseg_base());
 | 
			
		||||
				if (handler)
 | 
			
		||||
					handler(node, state_save);
 | 
			
		||||
#else
 | 
			
		||||
				southbridge_smi[i](node, state_save);
 | 
			
		||||
#endif
 | 
			
		||||
				southbridge_smi[i]();
 | 
			
		||||
			} else {
 | 
			
		||||
				printk(BIOS_DEBUG, "SMI_STS[%d] occured, but no "
 | 
			
		||||
						"handler available.\n", i);
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user