[Skiboot] [RFC PATCH 8/9] OPAL V4: initial OS-operations (traps, printf)
Gautham R Shenoy
ego at linux.vnet.ibm.com
Wed May 6 15:37:57 AEST 2020
Hello Nicholas,
On Sat, May 02, 2020 at 09:36:48PM +1000, Nicholas Piggin wrote:
> This completes OPAL V4, where the OS can provide servies to OPAL.
>
> To start with for this patch, the OS is to provide printf console and
> logging support, and trap handling and decoding.
>
> When the OS calls OPAL_REGISTER_OS_OPS, skiboot patches its traps back
> in, for the OS to handle. It sets the console to raw mode (introduced in
> an earlier patch) and no longer uses its console facilities. It calls
> the OS to log messages.
>
> Other services may be added to the size-versioned structure.
>
> The benefit of this is that 1) OPAL messages get into kernel log
> facilities, and 2) Linux's path to the console is much shorter, with
> no locks or buffering between the kernel and the uart MMIO. Things like
> xmon and BUG printing are careful to be as reliable as possible, I've
> encountered times when the skiboot console code trips us up here.
>
> Other OS facilities that may be useful:
>
> - Sleep facilities, which could abstract away highly implementation
> specific idle sleep, and expose calls for a simple generic OPAL
> driver.
>
> - ftrace and/or kprobes facilities.
>
> - perf interrupts.
>
> - Lockup watchdog interrupts.
>
> - Timer facilities. Skiboot could request an OS timer is scheduled which
> then makes an OPAL call with an opaque pointer which skiboot can then
> use to run functions asynchronously, for example.
>
> - Interrupt enable... possibly not, we'd rather keep calls as short as
> possible. Except perhaps for watchog and perf interrupts.
>
> Signed-off-by: Nicholas Piggin <npiggin at gmail.com>
[..snip..]
> diff --git a/core/opal.c b/core/opal.c
> index 7fb4fae86..5454cac67 100644
> --- a/core/opal.c
> +++ b/core/opal.c
> @@ -23,6 +23,7 @@
> #include <elf-abi.h>
> #include <errorlog.h>
> #include <occ.h>
> +#include <mem_region.h>
>
> /* Pending events to signal via opal_poll_events */
> uint64_t opal_pending_events;
> @@ -471,6 +472,53 @@ out:
> return ret;
> }
>
> +bool opal_v4_os = false;
> +struct os_ops os_ops;
> +
> +static int64_t opal_register_os_ops(struct opal_os_ops *ops, uint64_t size)
> +{
> + struct cpu_thread *cpu;
> +
> + if (size < 8)
> + return OPAL_PARAMETER;
> +
> + for_each_cpu(cpu) {
> + if (cpu == this_cpu())
> + continue;
> + if (cpu->state == cpu_state_os)
> + return OPAL_BUSY;
> + }
> +
Is this check to ensure that the OS calls register_os_ops() before the
secondaries are woken up? If so, when we introduce a os_stop()
callback, it should be registered prior to idle_init() in the Kernel.
> + if (opal_v4_os)
> + return OPAL_WRONG_STATE;
> +
> + if (!verify_romem()) {
> + prlog(PR_NOTICE, "OPAL checksums did not match\n");
> + disable_fast_reboot("Inconsistent firmware romem checksum");
> + return OPAL_WRONG_STATE;
> + }
> +
> + /* v4 must handle OPAL traps */
> + patch_traps(true);
> +
> + if (size >= 8) {
> + os_ops.os_printf = (void *)be64_to_cpu(ops->os_printf);
> + set_opal_console_to_raw();
At this point, we are invoking set_opal_raw_console() only called for
mambo_opal_raw_con, but not for uart_opal_raw_con. Do we need that if
we want to run this series on a P9 machine ?
> + }
> +
> + checksum_romem();
> +
> + opal_v4_os = true;
> +
> + return OPAL_SUCCESS;
> +}
> +opal_call(OPAL_REGISTER_OS_OPS, opal_register_os_ops, 2);
> +
> +void os_printf(uint32_t log_level, const char *str)
> +{
> + os_ops.os_printf(log_level, str);
> +}
> +
> void add_opal_node(void)
> {
> uint64_t base, entry, size;
> diff --git a/include/mem_region.h b/include/mem_region.h
> index 47c3bd70c..f56eef2d8 100644
> --- a/include/mem_region.h
> +++ b/include/mem_region.h
> @@ -73,6 +73,7 @@ struct mem_region *find_mem_region(const char *name);
> bool mem_range_is_reserved(uint64_t start, uint64_t size);
>
> /* Read-only memory checksum */
> +void checksum_romem(void);
> bool verify_romem(void);
>
> #endif /* __MEMORY_REGION */
> diff --git a/include/opal-api.h b/include/opal-api.h
> index e5142f121..139dc1d43 100644
> --- a/include/opal-api.h
> +++ b/include/opal-api.h
> @@ -231,7 +231,8 @@
> #define OPAL_SYM_TO_ADDR 182
> #define OPAL_REPORT_TRAP 183
> #define OPAL_FIND_VM_AREA 184
> -#define OPAL_LAST 184
> +#define OPAL_REGISTER_OS_OPS 185
> +#define OPAL_LAST 185
>
> #define QUIESCE_HOLD 1 /* Spin all calls at entry */
> #define QUIESCE_REJECT 2 /* Fail all calls with OPAL_BUSY */
> @@ -1275,6 +1276,10 @@ struct opal_vm_area {
> __be64 vm_flags;
> };
>
> +struct opal_os_ops {
> + __be64 os_printf; /* void printf(int32_t level, const char *str) */
> +};
> +
> #endif /* __ASSEMBLY__ */
>
> #endif /* __OPAL_API_H */
> diff --git a/include/opal-internal.h b/include/opal-internal.h
> index f6ca7ac32..64f372489 100644
> --- a/include/opal-internal.h
> +++ b/include/opal-internal.h
> @@ -18,6 +18,15 @@ struct opal_table_entry {
> u32 nargs;
> };
>
> +struct os_ops {
> + void (*os_printf)(uint32_t log_level, const char *str);
> +};
> +
> +extern bool opal_v4_os;
> +extern struct os_ops os_ops;
> +
> +extern void os_printf(uint32_t log_level, const char *str);
> +
> #ifdef __CHECKER__
> #define __opal_func_test_arg(__func, __nargs) 0
> #else
> --
> 2.23.0
>
> _______________________________________________
> Skiboot mailing list
> Skiboot at lists.ozlabs.org
> https://lists.ozlabs.org/listinfo/skiboot
More information about the Skiboot
mailing list