[Pdbg] [PATCH 2/3] libpdbg/p10chip: add basic thread direct controls
Joel Stanley
joel at jms.id.au
Mon Jan 11 15:56:26 AEDT 2021
On Mon, 21 Dec 2020 at 10:18, Nicholas Piggin <npiggin at gmail.com> wrote:
>
> This adds support for stop, start, sreset.
>
> Signed-off-by: Nicholas Piggin <npiggin at gmail.com>
Reviewed-by: Joel Stanley <joel at jms.id.au>
> ---
> libpdbg/p10_fapi_targets.c | 20 --------
> libpdbg/p10chip.c | 101 +++++++++++++++++++++++++++++++++++++
> 2 files changed, 101 insertions(+), 20 deletions(-)
>
> diff --git a/libpdbg/p10_fapi_targets.c b/libpdbg/p10_fapi_targets.c
> index 6023389..0f16735 100644
> --- a/libpdbg/p10_fapi_targets.c
> +++ b/libpdbg/p10_fapi_targets.c
> @@ -488,25 +488,6 @@ static struct chiplet p10_chiplet = {
> };
> DECLARE_HW_UNIT(p10_chiplet);
>
> -static int p10_thread_probe(struct pdbg_target *target)
> -{
> - struct thread *thread = target_to_thread(target);
> -
> - thread->id = pdbg_target_index(target);
> -
> - return 0;
> -}
> -
> -static struct thread p10_thread = {
> - .target = {
> - .name = "POWER10 Thread",
> - .compatible = "ibm,power10-thread",
> - .class = "thread",
> - .probe = p10_thread_probe,
> - },
> -};
> -DECLARE_HW_UNIT(p10_thread);
> -
> static uint64_t no_translate(struct pdbg_target *target, uint64_t addr)
> {
> /* No translation performed */
> @@ -540,6 +521,5 @@ static void register_p10_fapi_targets(void)
> pdbg_hwunit_register(PDBG_DEFAULT_BACKEND, &p10_pauc_hw_unit);
> pdbg_hwunit_register(PDBG_DEFAULT_BACKEND, &p10_pau_hw_unit);
> pdbg_hwunit_register(PDBG_DEFAULT_BACKEND, &p10_chiplet_hw_unit);
> - pdbg_hwunit_register(PDBG_DEFAULT_BACKEND, &p10_thread_hw_unit);
> pdbg_hwunit_register(PDBG_DEFAULT_BACKEND, &p10_fc_hw_unit);
> }
> diff --git a/libpdbg/p10chip.c b/libpdbg/p10chip.c
> index f26e4ca..87d34e5 100644
> --- a/libpdbg/p10chip.c
> +++ b/libpdbg/p10chip.c
> @@ -22,8 +22,16 @@
> #include "chip.h"
> #include "debug.h"
>
> +/*
> + * NOTE!
> + * All timeouts and scom procedures in general through the file should be kept
> + * in synch with skiboot (e.g., core/direct-controls.c) as far as possible.
> + * If you fix a bug here, fix it in skiboot, and vice versa.
> + */
> +
> #define P10_CORE_THREAD_STATE 0x28412
> #define P10_THREAD_INFO 0x28413
> +#define P10_DIRECT_CONTROL 0x28449
> #define P10_RAS_STATUS 0x28454
>
> /* PCB Slave registers */
> @@ -31,6 +39,7 @@
> #define SPECIAL_WKUP_DONE PPC_BIT(1)
> #define QME_SPWU_FSP 0xE8834
>
> +#define RAS_STATUS_TIMEOUT 100 /* 100ms */
> #define SPECIAL_WKUP_TIMEOUT 100 /* 100ms */
>
> static int thread_read(struct thread *thread, uint64_t addr, uint64_t *data)
> @@ -40,6 +49,13 @@ static int thread_read(struct thread *thread, uint64_t addr, uint64_t *data)
> return pib_read(core, addr, data);
> }
>
> +static uint64_t thread_write(struct thread *thread, uint64_t addr, uint64_t data)
> +{
> + struct pdbg_target *chip = pdbg_target_require_parent("core", &thread->target);
> +
> + return pib_write(chip, addr, data);
> +}
> +
> struct thread_state p10_thread_state(struct thread *thread)
> {
> struct thread_state thread_state;
> @@ -89,6 +105,90 @@ struct thread_state p10_thread_state(struct thread *thread)
> return thread_state;
> }
>
> +static int p10_thread_probe(struct pdbg_target *target)
> +{
> + struct thread *thread = target_to_thread(target);
> +
> + thread->id = pdbg_target_index(target);
> + thread->status = thread->state(thread);
> +
> + return 0;
> +}
> +
> +static void p10_thread_release(struct pdbg_target *target)
> +{
> + struct core *core = target_to_core(pdbg_target_require_parent("core", target));
> + struct thread *thread = target_to_thread(target);
> +
> + if (thread->status.quiesced)
> + /* This thread is still quiesced so don't release spwkup */
> + core->release_spwkup = false;
> +}
> +
> +static int p10_thread_start(struct thread *thread)
> +{
> + if (!(thread->status.quiesced))
> + return 1;
> +
> + if ((!(thread->status.active)) ||
> + (thread->status.sleep_state == PDBG_THREAD_STATE_STOP)) {
> + /* Inactive or active and stopped: Clear Maint */
> + thread_write(thread, P10_DIRECT_CONTROL, PPC_BIT(3 + 8*thread->id));
> + } else {
> + /* Active and not stopped: Start */
> + thread_write(thread, P10_DIRECT_CONTROL, PPC_BIT(6 + 8*thread->id));
> + }
> +
> + thread->status = thread->state(thread);
> +
> + return 0;
> +}
> +
> +static int p10_thread_stop(struct thread *thread)
> +{
> + int i = 0;
> +
> + thread_write(thread, P10_DIRECT_CONTROL, PPC_BIT(7 + 8*thread->id));
> + while (!(thread->state(thread).quiesced)) {
> + usleep(1000);
> + if (i++ > RAS_STATUS_TIMEOUT) {
> + PR_ERROR("Unable to quiesce thread\n");
> + break;
> + }
> + }
> + thread->status = thread->state(thread);
> +
> + return 0;
> +}
> +
> +static int p10_thread_sreset(struct thread *thread)
> +{
> + /* Can only sreset if a thread is quiesced */
> + if (!(thread->status.quiesced))
> + return 1;
> +
> + thread_write(thread, P10_DIRECT_CONTROL, PPC_BIT(4 + 8*thread->id));
> +
> + thread->status = thread->state(thread);
> +
> + return 0;
> +}
> +
> +static struct thread p10_thread = {
> + .target = {
> + .name = "POWER10 Thread",
> + .compatible = "ibm,power10-thread",
> + .class = "thread",
> + .probe = p10_thread_probe,
> + .release = p10_thread_release,
> + },
> + .state = p10_thread_state,
> + .start = p10_thread_start,
> + .stop = p10_thread_stop,
> + .sreset = p10_thread_sreset,
> +};
> +DECLARE_HW_UNIT(p10_thread);
> +
> static int p10_core_probe(struct pdbg_target *target)
> {
> struct core *core = target_to_core(target);
> @@ -190,5 +290,6 @@ DECLARE_HW_UNIT(p10_core);
> __attribute__((constructor))
> static void register_p10chip(void)
> {
> + pdbg_hwunit_register(PDBG_DEFAULT_BACKEND, &p10_thread_hw_unit);
> pdbg_hwunit_register(PDBG_DEFAULT_BACKEND, &p10_core_hw_unit);
> }
> --
> 2.23.0
>
> --
> Pdbg mailing list
> Pdbg at lists.ozlabs.org
> https://lists.ozlabs.org/listinfo/pdbg
More information about the Pdbg
mailing list