aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/fast-reboot.c64
-rw-r--r--core/init.c14
-rw-r--r--hw/xive.c32
-rw-r--r--include/interrupts.h1
-rw-r--r--include/xive.h1
5 files changed, 79 insertions, 33 deletions
diff --git a/core/fast-reboot.c b/core/fast-reboot.c
index 2f1a500..1c76c08 100644
--- a/core/fast-reboot.c
+++ b/core/fast-reboot.c
@@ -24,10 +24,12 @@
#include <cec.h>
#include <timebase.h>
#include <pci.h>
+#include <xive.h>
#include <chip.h>
#include <chiptod.h>
#include <ipmi.h>
#include <direct-controls.h>
+#include <nvram.h>
/* Flag tested by the OPAL entry code */
static volatile bool fast_boot_release;
@@ -73,8 +75,13 @@ void fast_reboot(void)
struct cpu_thread *cpu;
static int fast_reboot_count = 0;
+ if (proc_gen == proc_gen_p9) {
+ if (!nvram_query_eq("experimental-fast-reset","feeling-lucky"))
+ return;
+ }
+
if (!chip_quirk(QUIRK_MAMBO_CALLOUTS) &&
- proc_gen != proc_gen_p8) {
+ (proc_gen != proc_gen_p8 && proc_gen != proc_gen_p9)) {
prlog(PR_DEBUG,
"RESET: Fast reboot not available on this CPU\n");
return;
@@ -168,20 +175,24 @@ static void cleanup_cpu_state(void)
/* XXX Update the SLW copies ! Also dbl check HIDs etc... */
init_shared_sprs();
- /* If somebody was in fast_sleep, we may have a workaround
- * to undo
- */
- if (cpu->in_fast_sleep) {
- prlog(PR_DEBUG, "RESET: CPU 0x%04x in fast sleep"
- " undoing workarounds...\n", cpu->pir);
- fast_sleep_exit();
+ if (proc_gen == proc_gen_p8) {
+ /* If somebody was in fast_sleep, we may have a
+ * workaround to undo
+ */
+ if (cpu->in_fast_sleep) {
+ prlog(PR_DEBUG, "RESET: CPU 0x%04x in fast sleep"
+ " undoing workarounds...\n", cpu->pir);
+ fast_sleep_exit();
+ }
+
+ /* The TLB surely contains garbage.
+ * P9 clears TLBs in cpu_fast_reboot_complete
+ */
+ cleanup_local_tlb();
}
/* And we might have lost TB sync */
chiptod_wakeup_resync();
-
- /* The TLB surely contains garbage */
- cleanup_local_tlb();
}
/* Per-thread additional cleanup */
@@ -248,15 +259,19 @@ void __noreturn fast_reboot_entry(void)
{
prlog(PR_DEBUG, "RESET: CPU 0x%04x reset in\n", this_cpu()->pir);
- /* We reset our ICP first ! Otherwise we might get stray interrupts
- * when unsplitting
- */
- reset_cpu_icp();
+ if (proc_gen == proc_gen_p9) {
+ reset_cpu_xive();
+ } else if (proc_gen == proc_gen_p8) {
+ /* We reset our ICP first ! Otherwise we might get stray
+ * interrupts when unsplitting
+ */
+ reset_cpu_icp();
- /* If we are split, we need to unsplit. Since that can send us
- * to NAP, which will come back via reset, we do it now
- */
- check_split_core();
+ /* If we are split, we need to unsplit. Since that can send us
+ * to NAP, which will come back via reset, we do it now
+ */
+ check_split_core();
+ }
sync();
this_cpu()->state = cpu_state_present;
@@ -285,6 +300,10 @@ void __noreturn fast_reboot_entry(void)
*/
cpu_state_wait_all_others(cpu_state_present, 0);
+ if (proc_gen == proc_gen_p9) {
+ xive_reset();
+ }
+
prlog(PR_INFO, "RESET: Releasing secondaries...\n");
/* Release everybody */
@@ -322,8 +341,11 @@ void __noreturn fast_reboot_entry(void)
/* Poke the consoles (see comments in the code there) */
fsp_console_reset();
- /* Reset/EOI the PSI interrupt */
- psi_irq_reset();
+ if (proc_gen == proc_gen_p8) {
+ /* XXX */
+ /* Reset/EOI the PSI interrupt */
+ psi_irq_reset();
+ }
/* Remove all PCI devices */
pci_reset();
diff --git a/core/init.c b/core/init.c
index 0fdd7f0..2eeba75 100644
--- a/core/init.c
+++ b/core/init.c
@@ -502,6 +502,13 @@ void __noreturn load_and_boot_kernel(bool is_reboot)
/* Wait for FW VPD data read to complete */
fsp_code_update_wait_vpd(true);
+ /*
+ * OCC takes few secs to boot. Call this as late as
+ * as possible to avoid delay.
+ */
+ occ_pstates_init();
+ occ_sensors_init();
+
} else {
/* fdt will be rebuilt */
free(fdt);
@@ -512,13 +519,6 @@ void __noreturn load_and_boot_kernel(bool is_reboot)
fsp_console_select_stdout();
- /*
- * OCC takes few secs to boot. Call this as late as
- * as possible to avoid delay.
- */
- occ_pstates_init();
- occ_sensors_init();
-
/* Use nvram bootargs over device tree */
cmdline = nvram_query("bootargs");
if (cmdline) {
diff --git a/hw/xive.c b/hw/xive.c
index e81fe49..c7d6e62 100644
--- a/hw/xive.c
+++ b/hw/xive.c
@@ -4608,14 +4608,20 @@ static void xive_reset_mask_source_cb(struct irq_source *is,
}
}
-static int64_t opal_xive_reset(uint64_t version)
+void reset_cpu_xive(void)
{
- struct proc_chip *chip;
+ struct cpu_thread *c = this_cpu();
+ struct xive_cpu_state *xs = c->xstate;
- prlog(PR_DEBUG, "XIVE reset, version: %d...\n", (int)version);
+ xs->cppr = 0;
+ out_8(xs->tm_ring1 + TM_QW3_HV_PHYS + TM_CPPR, 0);
- if (version > 1)
- return OPAL_PARAMETER;
+ in_be64(xs->tm_ring1 + TM_SPC_PULL_POOL_CTX);
+}
+
+static int64_t __xive_reset(uint64_t version)
+{
+ struct proc_chip *chip;
xive_mode = version;
@@ -4651,6 +4657,22 @@ static int64_t opal_xive_reset(uint64_t version)
return OPAL_SUCCESS;
}
+/* Called by fast reboot */
+int64_t xive_reset(void)
+{
+ return __xive_reset(XIVE_MODE_EMU);
+}
+
+static int64_t opal_xive_reset(uint64_t version)
+{
+ prlog(PR_DEBUG, "XIVE reset, version: %d...\n", (int)version);
+
+ if (version > 1)
+ return OPAL_PARAMETER;
+
+ return __xive_reset(version);
+}
+
static int64_t opal_xive_free_vp_block(uint64_t vp_base)
{
uint32_t blk, idx, i, j, count;
diff --git a/include/interrupts.h b/include/interrupts.h
index 0376e8f..b412812 100644
--- a/include/interrupts.h
+++ b/include/interrupts.h
@@ -316,6 +316,7 @@ extern uint32_t get_ics_phandle(void);
struct cpu_thread;
extern void reset_cpu_icp(void);
+extern void reset_cpu_xive(void);
extern void icp_send_eoi(uint32_t interrupt);
extern void icp_prep_for_pm(void);
extern void icp_kick_cpu(struct cpu_thread *cpu);
diff --git a/include/xive.h b/include/xive.h
index ae7bb0b..2880720 100644
--- a/include/xive.h
+++ b/include/xive.h
@@ -470,6 +470,7 @@ struct xive_vp {
#define XIVE_IRQ_ERROR 0xffffffff
void init_xive(void);
+int64_t xive_reset(void);
/* Allocate a chunk of HW sources */
uint32_t xive_alloc_hw_irqs(uint32_t chip_id, uint32_t count, uint32_t align);