From patchwork Tue Oct 12 10:55:18 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nicholas Piggin X-Patchwork-Id: 1539727 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: bilbo.ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20210112 header.b=QBggx0R4; dkim-atps=neutral Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.ozlabs.org (client-ip=112.213.38.117; helo=lists.ozlabs.org; envelope-from=skiboot-bounces+incoming=patchwork.ozlabs.org@lists.ozlabs.org; receiver=) Received: from lists.ozlabs.org (lists.ozlabs.org [112.213.38.117]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits)) (No client certificate requested) by bilbo.ozlabs.org (Postfix) with ESMTPS id 4HTCHp1gC1z9sNH for ; Tue, 12 Oct 2021 21:55:34 +1100 (AEDT) Received: from boromir.ozlabs.org (localhost [IPv6:::1]) by lists.ozlabs.org (Postfix) with ESMTP id 4HTCHn65D0z2yNQ for ; Tue, 12 Oct 2021 21:55:33 +1100 (AEDT) Authentication-Results: lists.ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20210112 header.b=QBggx0R4; dkim-atps=neutral X-Original-To: skiboot@lists.ozlabs.org Delivered-To: skiboot@lists.ozlabs.org Authentication-Results: lists.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=gmail.com (client-ip=2607:f8b0:4864:20::102f; helo=mail-pj1-x102f.google.com; envelope-from=npiggin@gmail.com; receiver=) Authentication-Results: lists.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20210112 header.b=QBggx0R4; dkim-atps=neutral Received: from mail-pj1-x102f.google.com (mail-pj1-x102f.google.com [IPv6:2607:f8b0:4864:20::102f]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by lists.ozlabs.org (Postfix) with ESMTPS id 4HTCHh50d4z2yJ7 for ; Tue, 12 Oct 2021 21:55:27 +1100 (AEDT) Received: by mail-pj1-x102f.google.com with SMTP id om14so3517474pjb.5 for ; Tue, 12 Oct 2021 03:55:27 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=YMYxAYN73JQ5ARLKkUaDPUR41GOA0j3uub9LHYreHS4=; b=QBggx0R4d56Ykg/P+ilG9fwCZruowEohoyrRsRk0JjmYIMT3hTDCJa25PNQGsSDkK4 dp6jS8RA8ympIP57IFA2GYP9Dz+Uy1PNYka6Ue7Sse3/g0cPLDFSE3nCp3eGmTVdaMz3 YUUIhmiF7WBkEN28BXn+peOYUNwDKzP6WXCNtYvxQHqCCV3NJIEBkpfDWpyV/3PqXpj3 EvSr2wsK+hrj02kQOLMDG3jCVfg9pHbtwu7jvv40sPU0gAeAnQvL9/pcXudqYh9eXEUv BuLOpeP/rH2cs490/Rwd05E4EsuPLMI/srPAl3JJovt8pb7QGOpr12aVw8QCaYYAySw+ 1vNg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=YMYxAYN73JQ5ARLKkUaDPUR41GOA0j3uub9LHYreHS4=; b=scFkYIhQ/A/pOk3CLcS/tqcOXbTRquuF1nHI0R9fjCpJE/T6338wJGV0b/5lcCGBxY Mr/ffHKR4sTFC9rckF1NVGlvcpujzp8H9VdB4Ec1aPG5shR03peLaOOhyc6aNsY5gu32 7uN1qZ1te9vQKmR8jLjDMlDAwnZGRZF8Q3QBrC1xf4FXqzSPl7haWtVJ/yO0HbxDR4KU Us/iaLAs+9JXsN8Drp30hIC/fi6NqfuTFn8fU2swmT7L1LEEes7IEKuuTMunRCWAWh6f HR14blZOFKtQ0PsEO6gcXgc24In/35eLQTdErRol75jRWf2uWzX1QItWGgaEQozNcoeL 6QAQ== X-Gm-Message-State: AOAM533UYzX9wzzSMq0ebuoYTXX0KPjcDFpQnZZL6L2YmGINtXPWHdQa wi9zfPbGO876e7fzP503XMI13sON6N8/zw== X-Google-Smtp-Source: ABdhPJzkDJwRY4p6cGJ0Np7Fe5pMARX3pi8QsrsjSCynifDbirFnZQ3DUhvh4kZ85xFU0wIoPYAnLw== X-Received: by 2002:a17:902:7243:b0:13f:505b:5710 with SMTP id c3-20020a170902724300b0013f505b5710mr3669543pll.36.1634036124169; Tue, 12 Oct 2021 03:55:24 -0700 (PDT) Received: from bobo.ozlabs.ibm.com (14-203-144-177.static.tpgi.com.au. [14.203.144.177]) by smtp.gmail.com with ESMTPSA id q21sm2372988pjg.55.2021.10.12.03.55.22 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 12 Oct 2021 03:55:23 -0700 (PDT) From: Nicholas Piggin To: skiboot@lists.ozlabs.org Date: Tue, 12 Oct 2021 20:55:18 +1000 Message-Id: <20211012105518.261835-1-npiggin@gmail.com> X-Mailer: git-send-email 2.23.0 MIME-Version: 1.0 Subject: [Skiboot] [PATCH] HBRT: fix clobbered r16 when host services handlers are called X-BeenThere: skiboot@lists.ozlabs.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Mailing list for skiboot development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: skiboot-bounces+incoming=patchwork.ozlabs.org@lists.ozlabs.org Sender: "Skiboot" Skiboot is using r16 as a fixed register containing this CPU pointer, but we can be called back into from hostboot via the host services interface, where r16 may have been set by hostboot. Switch this back to skiboot's CPU pointer before running host services handlers, and then restore it to the hostboot value before returning. Fixes: 11ce9612b3aa ("move the __this_cpu register to r16, reserve r13-r15") Reported-by: Frederic Barrat Signed-off-by: Nicholas Piggin Reviewed-by: Frederic Barrat Tested-by: Frederic Barrat --- Frederic tested an earlier version of this patch successfully but I made a change since then so I've left of the Tested-by tag. Thanks, Nick asm/head.S | 10 +++ include/skiboot.h | 5 ++ platforms/ibm-fsp/hostservices.c | 125 +++++++++++++++++++++++++++++-- 3 files changed, 134 insertions(+), 6 deletions(-) diff --git a/asm/head.S b/asm/head.S index fa8933b14..e968ac6b2 100644 --- a/asm/head.S +++ b/asm/head.S @@ -1124,3 +1124,13 @@ start_kernel_secondary: mtspr SPR_HSRR1,%r10 mfspr %r3,SPR_PIR hrfid + +.global restore_cpu_ptr_r16 +restore_cpu_ptr_r16: + GET_CPU() + blr + +.global set_cpu_ptr_r16 +set_cpu_ptr_r16: + mr %r16,%r3 + blr diff --git a/include/skiboot.h b/include/skiboot.h index df11934f6..4f4a00574 100644 --- a/include/skiboot.h +++ b/include/skiboot.h @@ -163,6 +163,11 @@ extern void start_kernel32(uint64_t entry, void* fdt, uint64_t mem_top) __noreturn; extern void start_kernel_secondary(uint64_t entry) __noreturn; +/* Re-set r16 register with CPU pointer, based on stack (r1) value */ +extern void restore_cpu_ptr_r16(void); +/* Set r16 register with value in 'r16' parameter */ +extern void set_cpu_ptr_r16(uint64_t r16); + /* Get description of machine from HDAT and create device-tree */ extern int parse_hdat(bool is_opal); diff --git a/platforms/ibm-fsp/hostservices.c b/platforms/ibm-fsp/hostservices.c index accc0989a..1aab668d0 100644 --- a/platforms/ibm-fsp/hostservices.c +++ b/platforms/ibm-fsp/hostservices.c @@ -168,6 +168,27 @@ struct runtime_interfaces { void (*reserved[32])(void); }; +/* + * The host interfaces are called by hostboot, which considers r16 a regular + * non-volatile register that it may have used at the time of the call. + * Skiboot requires r16 to be set to the CPU pointer while it runs. So the + * host interface handlers must save HBRT's r16, switch r16 to the CPU pointer, + * do their thing, and then restore HBRT's r16 value before returning. + */ +static uint64_t host_interface_pre_fixup(void) +{ + uint64_t r16 = (uint64_t)__this_cpu; + + restore_cpu_ptr_r16(); + + return r16; +} + +static void host_interface_post_fixup(uint64_t r16) +{ + set_cpu_ptr_r16(r16); +} + static struct runtime_interfaces *hservice_runtime; static char *hbrt_con_buf = (char *)HBRT_CON_START; @@ -187,6 +208,7 @@ static struct memcons hbrt_memcons __section(".data.memcons") = { static void hservice_putc(char c) { + uint64_t r16 = host_interface_pre_fixup(); uint32_t opos; hbrt_con_buf[hbrt_con_pos++] = c; @@ -207,15 +229,20 @@ static void hservice_putc(char c) opos |= MEMCONS_OUT_POS_WRAP; lwsync(); hbrt_memcons.out_pos = cpu_to_be32(opos); + + host_interface_post_fixup(r16); } static void hservice_puts(const char *str) { + uint64_t r16 = host_interface_pre_fixup(); char c; while((c = *(str++)) != 0) hservice_putc(c); hservice_putc(10); + + host_interface_post_fixup(r16); } static void hservice_mark(void) @@ -226,28 +253,48 @@ static void hservice_mark(void) static void hservice_assert(void) { + uint64_t r16 = host_interface_pre_fixup(); + /** * @fwts-label HBRTassert * @fwts-advice HBRT triggered assert: you need to debug HBRT */ prlog(PR_EMERG, "HBRT: Assertion from hostservices\n"); abort(); + /* Should not be reached... */ + host_interface_post_fixup(r16); } static void *hservice_malloc(size_t size) { - return malloc(size); + uint64_t r16 = host_interface_pre_fixup(); + void *mem; + + mem = malloc(size); + + host_interface_post_fixup(r16); + + return mem; } static void hservice_free(void *ptr) { + uint64_t r16 = host_interface_pre_fixup(); free(ptr); + host_interface_post_fixup(r16); } static void *hservice_realloc(void *ptr, size_t size) { - return realloc(ptr, size); + uint64_t r16 = host_interface_pre_fixup(); + void *mem; + + mem = realloc(ptr, size); + + host_interface_post_fixup(r16); + + return mem; } struct hbrt_elog_ent { @@ -319,6 +366,7 @@ static void hservice_start_elog_send(void) int hservice_send_error_log(uint32_t plid, uint32_t dsize, void *data) { + uint64_t r16 = host_interface_pre_fixup(); struct hbrt_elog_ent *ent; void *abuf; @@ -327,6 +375,9 @@ int hservice_send_error_log(uint32_t plid, uint32_t dsize, void *data) /* We only know how to send error logs to FSP */ if (!fsp_present()) { prerror("HBRT: Warning, error log from HBRT discarded !\n"); + + host_interface_post_fixup(r16); + return OPAL_UNSUPPORTED; } if (dsize > PSI_DMA_HBRT_LOG_WRITE_BUF_SZ) { @@ -341,6 +392,9 @@ int hservice_send_error_log(uint32_t plid, uint32_t dsize, void *data) ent = zalloc(sizeof(struct hbrt_elog_ent)); if (!ent) { unlock(&hbrt_elog_lock); + + host_interface_post_fixup(r16); + return OPAL_NO_MEM; } @@ -349,6 +403,9 @@ int hservice_send_error_log(uint32_t plid, uint32_t dsize, void *data) if (!abuf) { free(ent); unlock(&hbrt_elog_lock); + + host_interface_post_fixup(r16); + return OPAL_NO_MEM; } memset(abuf, 0, PSI_DMA_HBRT_LOG_WRITE_BUF_SZ); @@ -361,21 +418,36 @@ int hservice_send_error_log(uint32_t plid, uint32_t dsize, void *data) hservice_start_elog_send(); unlock(&hbrt_elog_lock); + host_interface_post_fixup(r16); + return 0; } static int hservice_scom_read(uint64_t chip_id, uint64_t addr, void *buf) { - return xscom_read(chip_id, addr, buf); + uint64_t r16 = host_interface_pre_fixup(); + int ret; + + ret = xscom_read(chip_id, addr, buf); + + host_interface_post_fixup(r16); + + return ret; } static int hservice_scom_write(uint64_t chip_id, uint64_t addr, const void *buf) { + uint64_t r16 = host_interface_pre_fixup(); uint64_t val; + int ret; memcpy(&val, buf, sizeof(val)); - return xscom_write(chip_id, addr, val); + ret = xscom_write(chip_id, addr, val); + + host_interface_post_fixup(r16); + + return ret; } struct hbrt_lid { @@ -475,6 +547,7 @@ void hservices_lid_preload(void) static int hservice_lid_load(uint32_t lid, void **buf, size_t *len) { + uint64_t r16 = host_interface_pre_fixup(); struct hbrt_lid *hlid; prlog(PR_INFO, "HBRT: Lid load request for 0x%08x\n", lid); @@ -494,14 +567,24 @@ static int hservice_lid_load(uint32_t lid, void **buf, size_t *len) *len = hlid->len; prlog(PR_DEBUG, "HBRT: LID Serviced from cache," " %x, len=0x%lx\n", hlid->id, hlid->len); + + host_interface_post_fixup(r16); + return 0; } } + + host_interface_post_fixup(r16); + return -ENOENT; } static int hservice_lid_unload(void *buf __unused) { + uint64_t r16 = host_interface_pre_fixup(); + + host_interface_post_fixup(r16); + /* We do nothing as the LID is held in cache */ return 0; } @@ -526,15 +609,19 @@ static uint64_t hservice_get_reserved_mem(const char *name) static void hservice_nanosleep(uint64_t i_seconds, uint64_t i_nano_seconds) { + uint64_t r16 = host_interface_pre_fixup(); struct timespec ts; ts.tv_sec = i_seconds; ts.tv_nsec = i_nano_seconds; nanosleep_nopoll(&ts, NULL); + + host_interface_post_fixup(r16); } int hservice_wakeup(uint32_t i_core, uint32_t i_mode) { + uint64_t r16 = host_interface_pre_fixup(); struct cpu_thread *cpu; int rc = OPAL_SUCCESS; @@ -556,6 +643,8 @@ int hservice_wakeup(uint32_t i_core, uint32_t i_mode) i_core <<= 2; break; default: + host_interface_post_fixup(r16); + return OPAL_UNSUPPORTED; } @@ -563,32 +652,49 @@ int hservice_wakeup(uint32_t i_core, uint32_t i_mode) switch(i_mode) { case 0: /* Assert special wakeup */ cpu = find_cpu_by_pir(i_core); - if (!cpu) + if (!cpu) { + host_interface_post_fixup(r16); + return OPAL_PARAMETER; + } prlog(PR_TRACE, "HBRT: Special wakeup assert for core 0x%x," " count=%d\n", i_core, cpu->hbrt_spec_wakeup); if (cpu->hbrt_spec_wakeup == 0) rc = dctl_set_special_wakeup(cpu); if (rc == 0) cpu->hbrt_spec_wakeup++; + + host_interface_post_fixup(r16); + return rc; + case 1: /* Deassert special wakeup */ cpu = find_cpu_by_pir(i_core); - if (!cpu) + if (!cpu) { + host_interface_post_fixup(r16); + return OPAL_PARAMETER; + } prlog(PR_TRACE, "HBRT: Special wakeup release for core" " 0x%x, count=%d\n", i_core, cpu->hbrt_spec_wakeup); if (cpu->hbrt_spec_wakeup == 0) { prerror("HBRT: Special wakeup clear" " on core 0x%x with count=0\n", i_core); + + host_interface_post_fixup(r16); + return OPAL_WRONG_STATE; } /* What to do with count on errors ? */ cpu->hbrt_spec_wakeup--; if (cpu->hbrt_spec_wakeup == 0) rc = dctl_clear_special_wakeup(cpu); + + host_interface_post_fixup(r16); + return rc; + case 2: /* Clear all special wakeups */ prlog(PR_DEBUG, "HBRT: Special wakeup release for all cores\n"); for_each_cpu(cpu) { @@ -598,8 +704,15 @@ int hservice_wakeup(uint32_t i_core, uint32_t i_mode) dctl_clear_special_wakeup(cpu); } } + + host_interface_post_fixup(r16); + return OPAL_SUCCESS; + default: + + host_interface_post_fixup(r16); + return OPAL_PARAMETER; } }