Consolidate reset API, add generic reset_prepare mechanism

There are many good reasons why we may want to run some sort of generic
callback before we're executing a reset. Unfortunateley, that is really
hard right now: code that wants to reset simply calls the hard_reset()
function (or one of its ill-differentiated cousins) which is directly
implemented by a myriad of different mainboards, northbridges, SoCs,
etc. More recent x86 SoCs have tried to solve the problem in their own
little corner of soc/intel/common, but it's really something that would
benefit all of coreboot.

This patch expands the concept onto all boards: hard_reset() and friends
get implemented in a generic location where they can run hooks before
calling the platform-specific implementation that is now called
do_hard_reset(). The existing Intel reset_prepare() gets generalized as
soc_reset_prepare() (and other hooks for arch, mainboard, etc. can now
easily be added later if necessary). We will also use this central point
to ensure all platforms flush their cache before reset, which is
generally useful for all cases where we're trying to persist information
in RAM across reboots (like the new persistent CBMEM console does).

Also remove cpu_reset() completely since it's not used anywhere and
doesn't seem very useful compared to the others.

Change-Id: I41b89ce4a923102f0748922496e1dd9bce8a610f
Signed-off-by: Julius Werner <jwerner@chromium.org>
Reviewed-on: https://review.coreboot.org/19789
Reviewed-by: Aaron Durbin <adurbin@chromium.org>
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Furquan Shaikh <furquan@google.com>
This commit is contained in:
Julius Werner
2017-05-18 16:03:26 -07:00
parent d9762f70ac
commit 01f9aa5e54
66 changed files with 181 additions and 143 deletions

View File

@ -1,15 +1,30 @@
#ifndef RESET_H
#define RESET_H
#if CONFIG_HAVE_HARD_RESET
void hard_reset(void);
#else
#define hard_reset() do {} while (0)
#endif
void soft_reset(void);
void cpu_reset(void);
/* Some Intel SoCs use a special reset that is specific to SoC */
void global_reset(void);
/* Some Intel SoCs may need to prepare/wait before reset */
void reset_prepare(void);
/* Generic reset functions. Call from code that wants to trigger a reset. */
/* Super-hard reset specific to some Intel SoCs. */
__attribute__((noreturn)) void global_reset(void);
/* Full board reset. Resets SoC and most/all board components (e.g. DRAM). */
__attribute__((noreturn)) void hard_reset(void);
/* Board reset. Resets SoC some board components (e.g. TPM but not DRAM). */
__attribute__((noreturn)) void soft_reset(void);
/* Reset implementations. Implement these in SoC or mainboard code. Implement
at least hard_reset() if possible, others fall back to it if necessary. */
void do_global_reset(void);
void do_hard_reset(void);
void do_soft_reset(void);
enum reset_type { /* listed in order of softness */
GLOBAL_RESET,
HARD_RESET,
SOFT_RESET,
};
/* Callback that an SoC may override to perform special actions before reset.
Take into account that softer resets may fall back to harder resets if not
implemented... this will *not* trigger another callback! */
void soc_reset_prepare(enum reset_type reset_type);
#endif

View File

@ -223,6 +223,13 @@ romstage-y += halt.c
ramstage-y += halt.c
smm-y += halt.c
bootblock-y += reset.c
verstage-y += reset.c
romstage-y += reset.c
postcar-y += reset.c
ramstage-y += reset.c
smm-y += reset.c
postcar-y += bootmode.c
postcar-y += boot_device.c
postcar-y += cbfs.c

59
src/lib/reset.c Normal file
View File

@ -0,0 +1,59 @@
/*
* This file is part of the coreboot project.
*
* Copyright 2017 Google, 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.
*/
#include <arch/cache.h>
#include <console/console.h>
#include <halt.h>
#include <reset.h>
__attribute__((noreturn)) static void __hard_reset(void) {
if (IS_ENABLED(CONFIG_HAVE_HARD_RESET))
do_hard_reset();
else
printk(BIOS_CRIT, "No hard_reset implementation, hanging...\n");
halt();
}
/* Not all platforms implement all reset types. Fall back to hard_reset. */
__attribute__((weak)) void do_global_reset(void) { __hard_reset(); }
__attribute__((weak)) void do_soft_reset(void) { __hard_reset(); }
__attribute__((weak)) void soc_reset_prepare(enum reset_type rt) { /* no-op */ }
void global_reset(void)
{
printk(BIOS_INFO, "%s() called!\n", __func__);
soc_reset_prepare(GLOBAL_RESET);
dcache_clean_all();
do_global_reset();
halt();
}
void hard_reset(void)
{
printk(BIOS_INFO, "%s() called!\n", __func__);
soc_reset_prepare(HARD_RESET);
dcache_clean_all();
__hard_reset();
}
void soft_reset(void)
{
printk(BIOS_INFO, "%s() called!\n", __func__);
soc_reset_prepare(SOFT_RESET);
dcache_clean_all();
do_soft_reset();
halt();
}

View File

@ -55,7 +55,7 @@ int spd_read_byte(unsigned int device, unsigned int address)
}
#include <reset.h>
void soft_reset(void)
void do_soft_reset(void)
{
uint8_t tmp;

View File

@ -55,7 +55,7 @@ int spd_read_byte(unsigned device, unsigned address)
}
#include <reset.h>
void soft_reset(void)
void do_soft_reset(void)
{
uint8_t tmp;

View File

@ -53,7 +53,7 @@ int spd_read_byte(unsigned device, unsigned address)
}
#include <reset.h>
void soft_reset(void)
void do_soft_reset(void)
{
uint8_t tmp;

View File

@ -81,7 +81,7 @@ static void ldtstop_sb(void)
#include "cpu/amd/model_fxx/fidvid.c"
#include "northbridge/amd/amdk8/resourcemap.c"
void soft_reset(void)
void do_soft_reset(void)
{
uint8_t tmp;

View File

@ -64,7 +64,7 @@ int spd_read_byte(unsigned device, unsigned address)
#include "cpu/amd/model_fxx/fidvid.c"
#include "northbridge/amd/amdk8/resourcemap.c"
void soft_reset(void)
void do_soft_reset(void)
{
uint8_t tmp;

View File

@ -18,8 +18,7 @@
#include <gpio.h>
#include <reset.h>
void hard_reset(void)
void do_hard_reset(void)
{
gpio_output(GPIO(I5), 0);
while(1);
}

View File

@ -19,7 +19,7 @@
#include <soc/iomap.h>
#include <reset.h>
void hard_reset(void)
void do_hard_reset(void)
{
/*
* At boot time the boot loaders would have set a magic cookie

View File

@ -18,9 +18,7 @@
#include "board.h"
void hard_reset(void)
void do_hard_reset(void)
{
gpio_output(GPIO_RESET, 1);
while (1)
;
}

View File

@ -17,8 +17,7 @@
#include <gpio.h>
#include <reset.h>
void hard_reset(void)
void do_hard_reset(void)
{
gpio_output(GPIO(I5), 0);
while(1);
}

View File

@ -17,8 +17,7 @@
#include <gpio.h>
#include <reset.h>
void hard_reset(void)
void do_hard_reset(void)
{
gpio_output(GPIO(I5), 0);
while(1);
}

View File

@ -17,8 +17,7 @@
#include <gpio.h>
#include <reset.h>
void hard_reset(void)
void do_hard_reset(void)
{
gpio_output(GPIO(I5), 0);
while(1);
}

View File

@ -15,8 +15,6 @@
#include <reset.h>
void hard_reset(void)
void do_hard_reset(void)
{
while (1)
;
}

View File

@ -16,7 +16,7 @@
#include <reset.h>
#include <soc/reset.h>
void hard_reset(void)
void do_hard_reset(void)
{
mvmap2315_reset();
}

View File

@ -18,9 +18,7 @@
#include "gpio.h"
void hard_reset(void)
void do_hard_reset(void)
{
gpio_output(AP_SYS_RESET_L, 0);
while (1)
;
}

View File

@ -37,12 +37,9 @@ static void wdog_reset(void)
write32(APCS_WDT0_BITE_TIME, RESET_WDT_BITE_TIME);
write32(APCS_WDT0_EN, 1);
write32(APCS_WDT0_CPU0_WDOG_EXPIRED_ENABLE, 1);
for (;;)
;
}
void hard_reset(void)
void do_hard_reset(void)
{
wdog_reset();
}

View File

@ -19,8 +19,7 @@
#include "board.h"
void hard_reset(void)
void do_hard_reset(void)
{
gpio_output(GPIO_RESET, 1);
while (1);
}

View File

@ -19,8 +19,7 @@
#include "board.h"
void hard_reset(void)
void do_hard_reset(void)
{
gpio_output(GPIO_RESET, 1);
while (1);
}

View File

@ -19,9 +19,7 @@
#include "board.h"
void hard_reset(void)
void do_hard_reset(void)
{
gpio_output(GPIO_RESET, 1);
while (1)
;
}

View File

@ -16,7 +16,7 @@
#include <arch/io.h>
#include <reset.h>
void hard_reset(void)
void do_hard_reset(void)
{
outb((1 << 2) | (1 << 1), 0xcf9);
}

View File

@ -43,7 +43,7 @@ static uint64_t uma_memory_size = 0;
* remapping mechanism will overflow, the effects of which are unknown.
*/
void hard_reset(void)
void do_hard_reset(void)
{
outb((1 << 2) | (1 << 1), 0xcf9);
}

View File

@ -16,6 +16,6 @@
#include <arch/io.h>
#include <reset.h>
void hard_reset(void)
void do_hard_reset(void)
{
}

View File

@ -20,7 +20,7 @@
#define PISTACHIO_WD_ADDR 0xB8102100
#define PISTACHIO_WD_SW_RST_OFFSET 0x0000
void hard_reset(void)
void do_hard_reset(void)
{
/* Generate system reset */
write32(PISTACHIO_WD_ADDR + PISTACHIO_WD_SW_RST_OFFSET, 0x1);

View File

@ -23,13 +23,13 @@
#define CSE_WAIT_MAX_MS 1000
void global_reset(void)
void do_global_reset(void)
{
global_reset_enable(1);
hard_reset();
do_hard_reset();
}
void reset_prepare(void)
void soc_reset_prepare(enum reset_type reset_type)
{
struct stopwatch sw;

View File

@ -29,13 +29,13 @@ void warm_reset(void)
outb(RST_CPU | SYS_RST, RST_CNT);
}
void soft_reset(void)
void do_soft_reset(void)
{
/* Sends INIT# to CPU */
outb(RST_CPU, RST_CNT);
}
void hard_reset(void)
void do_hard_reset(void)
{
/* Don't power cycle on hard_reset(). It's not really clear what the
* semantics should be for the meaning of hard_reset(). */

View File

@ -28,12 +28,12 @@
* with ETR[20] set.
*/
void soft_reset(void)
void do_soft_reset(void)
{
outb(0x04, 0xcf9);
}
void hard_reset(void)
void do_hard_reset(void)
{
outb(0x06, 0xcf9);
}

View File

@ -25,39 +25,16 @@
#define RST_CPU (1 << 2)
#define SYS_RST (1 << 1)
#ifdef __ROMCC__
#define WEAK
#else
#define WEAK __attribute__((weak))
#endif
void WEAK reset_prepare(void) { /* do nothing */ }
#if IS_ENABLED(CONFIG_HAVE_HARD_RESET)
void hard_reset(void)
void do_hard_reset(void)
{
reset_prepare();
/* S0->S5->S0 trip. */
outb(RST_CPU | SYS_RST | FULL_RST, RST_CNT);
while (1)
hlt();
}
#endif
void soft_reset(void)
void do_soft_reset(void)
{
reset_prepare();
/* PMC_PLTRST# asserted. */
outb(RST_CPU | SYS_RST, RST_CNT);
while (1)
hlt();
}
void cpu_reset(void)
{
reset_prepare();
/* Sends INIT# to CPU */
outb(RST_CPU, RST_CNT);
while (1)
hlt();
}

View File

@ -29,13 +29,13 @@ void warm_reset(void)
outb(RST_CPU | SYS_RST, RST_CNT);
}
void soft_reset(void)
void do_soft_reset(void)
{
/* Sends INIT# to CPU */
outb(RST_CPU, RST_CNT);
}
void hard_reset(void)
void do_hard_reset(void)
{
/* Don't power cycle on hard_reset(). It's not really clear what the
* semantics should be for the meaning of hard_reset(). */

View File

@ -23,7 +23,7 @@ void warm_reset(void)
outb(0x06, 0xcf9);
}
void hard_reset(void)
void do_hard_reset(void)
{
warm_reset();
}

View File

@ -17,12 +17,12 @@
#include <arch/io.h>
#include <reset.h>
void soft_reset(void)
void do_soft_reset(void)
{
outb(0x04, 0xcf9);
}
void hard_reset(void)
void do_hard_reset(void)
{
outb(0x02, 0xcf9);
outb(0x06, 0xcf9);

View File

@ -41,7 +41,7 @@ static void do_force_global_reset(void)
hard_reset();
}
void global_reset(void)
void do_global_reset(void)
{
if (send_global_reset() != 0) {
/* If ME unable to reset platform then

View File

@ -57,10 +57,7 @@ int mtk_wdt_init(void)
return wdt_sta;
}
void hard_reset(void)
void do_hard_reset(void)
{
write32(&mt8173_wdt->wdt_swrst, MTK_WDT_SWRST_KEY);
while (1)
;
}

View File

@ -39,7 +39,7 @@ void power_reset(void)
setbits_le32(&exynos_power->sw_reset, 1);
}
void hard_reset(void)
void do_hard_reset(void)
{
power_reset();
}

View File

@ -21,7 +21,7 @@
#include <northbridge/amd/amdk8/reset_test.c>
void hard_reset(void)
void do_hard_reset(void)
{
set_bios_reset();
/* Try rebooting through port 0xcf9 */

View File

@ -38,7 +38,7 @@ static void enable_cf9(void)
enable_cf9_x(sbbusn, sbdn);
}
void hard_reset(void)
void do_hard_reset(void)
{
set_bios_reset();
/* reset */
@ -71,7 +71,7 @@ static void soft_reset_x(unsigned sbbusn, unsigned sbdn)
}
void soft_reset(void)
void do_soft_reset(void)
{
unsigned sblk = get_sblk();

View File

@ -37,7 +37,7 @@ static pci_devfn_t pci_io_locate_device_on_bus(unsigned pci_id, unsigned bus)
#include "../../../northbridge/amd/amdk8/reset_test.c"
void hard_reset(void)
void do_hard_reset(void)
{
pci_devfn_t dev;
unsigned bus;

View File

@ -40,7 +40,7 @@ static inline void set_bios_reset(void)
}
}
void hard_reset(void)
void do_hard_reset(void)
{
set_bios_reset();
/* Try rebooting through port 0xcf9 */
@ -50,7 +50,7 @@ void hard_reset(void)
}
//SbReset();
void soft_reset(void)
void do_soft_reset(void)
{
set_bios_reset();
/* link reset */

View File

@ -40,7 +40,7 @@ static inline void set_bios_reset(void)
}
}
void hard_reset(void)
void do_hard_reset(void)
{
set_bios_reset();
/* Try rebooting through port 0xcf9 */
@ -50,7 +50,7 @@ void hard_reset(void)
}
//SbReset();
void soft_reset(void)
void do_soft_reset(void)
{
set_bios_reset();
/* link reset */

View File

@ -40,7 +40,7 @@ static inline void set_bios_reset(void)
}
}
void hard_reset(void)
void do_hard_reset(void)
{
set_bios_reset();
/* Try rebooting through port 0xcf9 */
@ -50,7 +50,7 @@ void hard_reset(void)
}
//SbReset();
void soft_reset(void)
void do_soft_reset(void)
{
set_bios_reset();
/* link reset */

View File

@ -21,7 +21,7 @@
#include <northbridge/amd/amdk8/reset_test.c>
void hard_reset(void)
void do_hard_reset(void)
{
set_bios_reset();
/* Try rebooting through port 0xcf9 */

View File

@ -173,7 +173,7 @@ static void enable_fid_change_on_sb(u32 sbbusn, u32 sbdn)
}
}
void hard_reset(void)
void do_hard_reset(void)
{
set_bios_reset();
@ -182,7 +182,7 @@ void hard_reset(void)
outb(0x0e, 0x0cf9);
}
void soft_reset(void)
void do_soft_reset(void)
{
set_bios_reset();
/* link reset */

View File

@ -21,7 +21,7 @@
#include <northbridge/amd/amdk8/reset_test.c>
void hard_reset(void)
void do_hard_reset(void)
{
set_bios_reset();
/* Try rebooting through port 0xcf9 */

View File

@ -44,7 +44,7 @@ static void set_bios_reset(void)
}
}
void hard_reset(void)
void do_hard_reset(void)
{
set_bios_reset();
@ -56,7 +56,7 @@ void hard_reset(void)
outb((0 << 3) | (1 << 2) | (1 << 1), 0xcf9);
}
void soft_reset(void)
void do_soft_reset(void)
{
set_bios_reset();
/* link reset */

View File

@ -220,7 +220,7 @@ static void enable_fid_change_on_sb(u32 sbbusn, u32 sbdn)
pmio_write(0x81, byte);
}
void hard_reset(void)
void do_hard_reset(void)
{
set_bios_reset();
@ -229,7 +229,7 @@ void hard_reset(void)
outb(0x0e, 0x0cf9);
}
void soft_reset(void)
void do_soft_reset(void)
{
set_bios_reset();
/* link reset */

View File

@ -21,7 +21,7 @@
#include <northbridge/amd/amdk8/reset_test.c>
void hard_reset(void)
void do_hard_reset(void)
{
set_bios_reset();
/* Try rebooting through port 0xcf9 */

View File

@ -105,7 +105,7 @@ void ldtstop_sb(void)
}
void hard_reset(void)
void do_hard_reset(void)
{
bcm5785_enable_wdt_port_cf9();
@ -116,7 +116,7 @@ void hard_reset(void)
outb(0x0e, 0x0cf9);
}
void soft_reset(void)
void do_soft_reset(void)
{
bcm5785_enable_wdt_port_cf9();

View File

@ -21,7 +21,7 @@
#include "../../../northbridge/amd/amdk8/reset_test.c"
void hard_reset(void)
void do_hard_reset(void)
{
set_bios_reset();
/* Try rebooting through port 0xcf9 */

View File

@ -17,12 +17,12 @@
#include <arch/io.h>
#include <reset.h>
void soft_reset(void)
void do_soft_reset(void)
{
outb(0x04, 0xcf9);
}
void hard_reset(void)
void do_hard_reset(void)
{
outb(0x06, 0xcf9);
}

View File

@ -18,12 +18,12 @@
#include <arch/io.h>
#include <reset.h>
void soft_reset(void)
void do_soft_reset(void)
{
outb(0x04, 0xcf9);
}
void hard_reset(void)
void do_hard_reset(void)
{
outb(0x06, 0xcf9);
}

View File

@ -18,12 +18,12 @@
#include <arch/io.h>
#include <reset.h>
void soft_reset(void)
void do_soft_reset(void)
{
outb(0x04, 0xcf9);
}
void hard_reset(void)
void do_hard_reset(void)
{
outb(0x06, 0xcf9);
}

View File

@ -18,12 +18,12 @@
#include <arch/io.h>
#include <reset.h>
void soft_reset(void)
void do_soft_reset(void)
{
hard_reset();
}
void hard_reset(void)
void do_hard_reset(void)
{
outb(0x02, 0xcf9);
outb(0x06, 0xcf9);

View File

@ -17,7 +17,7 @@
#include <arch/io.h>
#include <reset.h>
void hard_reset(void)
void do_hard_reset(void)
{
outb(0x06, 0xcf9);
}

View File

@ -17,7 +17,7 @@
#include <reset.h>
#include <arch/io.h>
void hard_reset(void)
void do_hard_reset(void)
{
/* Try rebooting through port 0xcf9. */
outb((1 << 2) | (1 << 1), 0xcf9);

View File

@ -17,7 +17,7 @@
#include <arch/io.h>
#include <reset.h>
void hard_reset(void)
void do_hard_reset(void)
{
/* Try rebooting through port 0xcf9. */
outb((1 << 2) | (1 << 1), 0xcf9);

View File

@ -16,7 +16,7 @@
#include <arch/io.h>
#include <reset.h>
void hard_reset(void)
void do_hard_reset(void)
{
/* Try rebooting through port 0xcf9 */
outb((0 << 3) | (1 << 2) | (1 << 1), 0xcf9);

View File

@ -17,20 +17,20 @@
#include <arch/io.h>
#include <reset.h>
void soft_reset(void)
void do_soft_reset(void)
{
outb(0x04, 0xcf9);
}
#if 0
void hard_reset(void)
void do_hard_reset(void)
{
/* Try rebooting through port 0xcf9. */
outb((1 << 2) | (1 << 1), 0xcf9);
}
#endif
void hard_reset(void)
void do_hard_reset(void)
{
outb(0x02, 0xcf9);
outb(0x06, 0xcf9);

View File

@ -17,12 +17,12 @@
#include <arch/io.h>
#include <reset.h>
void soft_reset(void)
void do_soft_reset(void)
{
outb(0x04, 0xcf9);
}
void hard_reset(void)
void do_hard_reset(void)
{
outb(0x06, 0xcf9);
}

View File

@ -310,7 +310,7 @@ static int ck804_early_setup_x(void)
return set_ht_link_ck804(4);
}
void hard_reset(void)
void do_hard_reset(void)
{
set_bios_reset();
@ -319,7 +319,7 @@ void hard_reset(void)
outb(0x0e, 0x0cf9);
}
void soft_reset(void)
void do_soft_reset(void)
{
set_bios_reset();

View File

@ -357,7 +357,7 @@ static int ck804_early_setup_x(void)
return set_ht_link_ck804(4);
}
void hard_reset(void)
void do_hard_reset(void)
{
set_bios_reset();
@ -366,7 +366,7 @@ void hard_reset(void)
outb(0x0e, 0x0cf9);
}
void soft_reset(void)
void do_soft_reset(void)
{
set_bios_reset();

View File

@ -21,7 +21,7 @@
#include "../../../northbridge/amd/amdk8/reset_test.c"
void hard_reset(void)
void do_hard_reset(void)
{
set_bios_reset();
/* Try rebooting through port 0xcf9. */

View File

@ -25,7 +25,7 @@
#endif
#include "mcp55.h"
void soft_reset(void)
void do_soft_reset(void)
{
set_bios_reset();
/* link reset */
@ -33,7 +33,7 @@ void soft_reset(void)
outb(0x06, 0x0cf9);
}
void hard_reset(void)
void do_hard_reset(void)
{
set_bios_reset();

View File

@ -24,7 +24,7 @@
#include "../../../northbridge/amd/amdk8/reset_test.c"
void hard_reset(void)
void do_hard_reset(void)
{
set_bios_reset();
/* Try rebooting through port 0xcf9 */

View File

@ -29,7 +29,7 @@ static unsigned get_sbdn(unsigned bus)
return (dev>>15) & 0x1f;
}
void hard_reset(void)
void do_hard_reset(void)
{
set_bios_reset();
@ -44,7 +44,7 @@ static void enable_fid_change_on_sb(unsigned sbbusn, unsigned sbdn)
/* set VFSMAF ( VID/FID System Management Action Field) to 2 */
}
void soft_reset(void)
void do_soft_reset(void)
{
set_bios_reset();

View File

@ -24,7 +24,7 @@
#include "../../../northbridge/amd/amdk8/reset_test.c"
void hard_reset(void)
void do_hard_reset(void)
{
set_bios_reset();
/* Try rebooting through port 0xcf9 */