X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=src%2Fcpu%2Fx86%2Fsmm%2Fsmihandler.c;h=bbed0f195ef9bd0954d4ecf3b690e44f433097f9;hb=3aa067f595115a62afdfc9acc33f08e9c96da850;hp=96eb5895561e3072c36112c8ddfbca00163a2c2a;hpb=0867062412dd4bfe5a556e5f3fd85ba5b682d79b;p=coreboot.git diff --git a/src/cpu/x86/smm/smihandler.c b/src/cpu/x86/smm/smihandler.c index 96eb58955..bbed0f195 100644 --- a/src/cpu/x86/smm/smihandler.c +++ b/src/cpu/x86/smm/smihandler.c @@ -1,7 +1,7 @@ /* * This file is part of the coreboot project. * - * Copyright (C) 2008 coresystems GmbH + * Copyright (C) 2008-2009 coresystems GmbH * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -25,14 +25,11 @@ #include #include -void southbridge_smi_set_eos(void); - -#define DEBUG_SMI - +#if !CONFIG_SMM_TSEG /* TSEG handler locks in assembly */ typedef enum { SMI_LOCKED, SMI_UNLOCKED } smi_semaphore; /* SMI multiprocessing semaphore */ -static volatile smi_semaphore smi_handler_status = SMI_UNLOCKED; +static volatile smi_semaphore smi_handler_status __attribute__ ((aligned (4))) = SMI_UNLOCKED; static int smi_obtain_lock(void) { @@ -50,7 +47,7 @@ static int smi_obtain_lock(void) return (ret == SMI_UNLOCKED); } -static void smi_release_lock(void) +void smi_release_lock(void) { asm volatile ( "movb %1, %%al\n" @@ -60,6 +57,7 @@ static void smi_release_lock(void) : "eax" ); } +#endif #define LAPIC_ID 0xfee00020 static inline __attribute__((always_inline)) unsigned long nodeid(void) @@ -67,72 +65,12 @@ static inline __attribute__((always_inline)) unsigned long nodeid(void) return (*((volatile unsigned long *)(LAPIC_ID)) >> 24); } -/* ********************* smi_util ************************* */ - -/* Data */ -#define UART_RBR 0x00 -#define UART_TBR 0x00 - -/* Control */ -#define UART_IER 0x01 -#define UART_IIR 0x02 -#define UART_FCR 0x02 -#define UART_LCR 0x03 -#define UART_MCR 0x04 -#define UART_DLL 0x00 -#define UART_DLM 0x01 - -/* Status */ -#define UART_LSR 0x05 -#define UART_MSR 0x06 -#define UART_SCR 0x07 - -static int uart_can_tx_byte(void) -{ - return inb(CONFIG_TTYS0_BASE + UART_LSR) & 0x20; -} - -static void uart_wait_to_tx_byte(void) -{ - while(!uart_can_tx_byte()) - ; -} - -static void uart_wait_until_sent(void) -{ - while(!(inb(CONFIG_TTYS0_BASE + UART_LSR) & 0x40)) - ; -} - -static void uart_tx_byte(unsigned char data) -{ - uart_wait_to_tx_byte(); - outb(data, CONFIG_TTYS0_BASE + UART_TBR); - /* Make certain the data clears the fifos */ - uart_wait_until_sent(); -} - -void console_tx_flush(void) -{ - uart_wait_to_tx_byte(); -} - -void console_tx_byte(unsigned char byte) -{ - if (byte == '\n') - uart_tx_byte('\r'); - uart_tx_byte(byte); -} - -/* ********************* smi_util ************************* */ - - void io_trap_handler(int smif) { /* If a handler function handled a given IO trap, it * shall return a non-zero value */ - printk_debug("SMI function trap 0x%x: ", smif); + printk(BIOS_DEBUG, "SMI function trap 0x%x: ", smif); if (southbridge_io_trap_handler(smif)) return; @@ -140,7 +78,7 @@ void io_trap_handler(int smif) if (mainboard_io_trap_handler(smif)) return; - printk_debug("Unknown function\n"); + printk(BIOS_DEBUG, "Unknown function\n"); } /** @@ -151,6 +89,24 @@ static void smi_set_eos(void) southbridge_smi_set_eos(); } +static u32 pci_orig; + +/** + * @brief Backup PCI address to make sure we do not mess up the OS + */ +static void smi_backup_pci_address(void) +{ + pci_orig = inl(0xcf8); +} + +/** + * @brief Restore PCI address previously backed up + */ +static void smi_restore_pci_address(void) +{ + outl(pci_orig, 0xcf8); +} + /** * @brief Interrupt handler for SMI# * @@ -162,27 +118,38 @@ void smi_handler(u32 smm_revision) unsigned int node; smm_state_save_area_t state_save; +#if !CONFIG_SMM_TSEG /* Are we ok to execute the handler? */ - if (!smi_obtain_lock()) + if (!smi_obtain_lock()) { + /* For security reasons we don't release the other CPUs + * until the CPU with the lock is actually done + */ + while (smi_handler_status == SMI_LOCKED) { + asm volatile ( + ".byte 0xf3, 0x90\n" /* hint a CPU we are in spinlock (PAUSE instruction, REP NOP) */ + ); + } return; + } +#endif + + smi_backup_pci_address(); node=nodeid(); -#ifdef DEBUG_SMI - console_loglevel = CONFIG_DEFAULT_CONSOLE_LOGLEVEL; -#else - console_loglevel = 1; -#endif + console_init(); - printk_spew("\nSMI# #%d\n", node); + printk(BIOS_SPEW, "\nSMI# #%d\n", node); switch (smm_revision) { + case 0x00030002: case 0x00030007: state_save.type = LEGACY; state_save.legacy_state_save = (legacy_smm_state_save_area_t *) (0xa8000 + 0x7e00 - (node * 0x400)); break; case 0x00030100: + case 0x00030101: /* SandyBridge */ state_save.type = EM64T; state_save.em64t_state_save = (em64t_smm_state_save_area_t *) (0xa8000 + 0x7d00 - (node * 0x400)); @@ -193,21 +160,27 @@ void smi_handler(u32 smm_revision) (0xa8000 + 0x7e00 - (node * 0x400)); break; default: - printk_debug("smm_revision: 0x%08x\n", smm_revision); - printk_debug("SMI# not supported on your CPU\n"); + printk(BIOS_DEBUG, "smm_revision: 0x%08x\n", smm_revision); + printk(BIOS_DEBUG, "SMI# not supported on your CPU\n"); /* Don't release lock, so no further SMI will happen, * if we don't handle it anyways. */ return; } - /* Call chipset specific SMI handlers. This would be the place to - * add a CPU or northbridge specific SMI handler, too - */ + /* Call chipset specific SMI handlers. */ + if (cpu_smi_handler) + cpu_smi_handler(node, &state_save); + if (northbridge_smi_handler) + northbridge_smi_handler(node, &state_save); + if (southbridge_smi_handler) + southbridge_smi_handler(node, &state_save); - southbridge_smi_handler(node, &state_save); + smi_restore_pci_address(); +#if !CONFIG_SMM_TSEG smi_release_lock(); +#endif /* De-assert SMI# signal to allow another SMI */ smi_set_eos();