From patchwork Fri Feb 18 16:46:42 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Damien Hedde X-Patchwork-Id: 12751667 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 0A8B3C433F5 for ; Fri, 18 Feb 2022 16:51:09 +0000 (UTC) Received: from localhost ([::1]:58954 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1nL6TL-0002NO-Qm for qemu-devel@archiver.kernel.org; Fri, 18 Feb 2022 11:51:08 -0500 Received: from eggs.gnu.org ([209.51.188.92]:41958) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1nL6PS-00081o-Hm; Fri, 18 Feb 2022 11:47:06 -0500 Received: from beetle.greensocs.com ([5.135.226.135]:48182) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1nL6PQ-0007ZI-K2; Fri, 18 Feb 2022 11:47:06 -0500 Received: from crumble.bar.greensocs.com (unknown [172.17.10.6]) by beetle.greensocs.com (Postfix) with ESMTPS id DCB7B20898; Fri, 18 Feb 2022 16:47:01 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=greensocs.com; s=mail; t=1645202822; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=fTwQXv8aSQcofSMa0IHoyzLvta1LaHX+zhc2AwBgJog=; b=hiRvhiL7kMyxAHhM3XaBLatXedpfNzsBk2TOIoz4M1qblIAMvO3IMYm4/MzD+rzzLYuA95 yfULyihZ3+lk0tE1Yo7dOOTOUau8cxVs5fy3850h3pVpEno+iM2X5AmAmIm8P023bosbBk wXMF5Nm0DklVRNcQ4XkHgpEaWfE31+g= From: Damien Hedde To: qemu-devel@nongnu.org Subject: [PATCH 1/5] hw/riscv/riscv_hart: free the harts array when the object is finalized Date: Fri, 18 Feb 2022 17:46:42 +0100 Message-Id: <20220218164646.132112-2-damien.hedde@greensocs.com> X-Mailer: git-send-email 2.35.1 In-Reply-To: <20220218164646.132112-1-damien.hedde@greensocs.com> References: <20220218164646.132112-1-damien.hedde@greensocs.com> MIME-Version: 1.0 X-Spam: Yes Received-SPF: pass client-ip=5.135.226.135; envelope-from=damien.hedde@greensocs.com; helo=beetle.greensocs.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Damien Hedde , Palmer Dabbelt , Bin Meng , Alistair Francis , qemu-riscv@nongnu.org Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" The array is dynamically allocated by realize() depending on the number of harts. This clean-up removes memory leaks which would happen in the 'init->finalize' life-cycle use-case (happening when user creation is allowed). Signed-off-by: Damien Hedde --- hw/riscv/riscv_hart.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/hw/riscv/riscv_hart.c b/hw/riscv/riscv_hart.c index 613ea2aaa0..4aed6c2a59 100644 --- a/hw/riscv/riscv_hart.c +++ b/hw/riscv/riscv_hart.c @@ -66,6 +66,13 @@ static void riscv_harts_realize(DeviceState *dev, Error **errp) } } +static void riscv_harts_finalize(Object *obj) +{ + RISCVHartArrayState *s = RISCV_HART_ARRAY(obj); + + g_free(s->harts); +} + static void riscv_harts_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); @@ -79,6 +86,7 @@ static const TypeInfo riscv_harts_info = { .parent = TYPE_SYS_BUS_DEVICE, .instance_size = sizeof(RISCVHartArrayState), .class_init = riscv_harts_class_init, + .instance_finalize = riscv_harts_finalize, }; static void riscv_harts_register_types(void) From patchwork Fri Feb 18 16:46:43 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Damien Hedde X-Patchwork-Id: 12751668 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 3E56EC433EF for ; Fri, 18 Feb 2022 16:51:16 +0000 (UTC) Received: from localhost ([::1]:59082 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1nL6TS-0002SQ-PD for qemu-devel@archiver.kernel.org; Fri, 18 Feb 2022 11:51:14 -0500 Received: from eggs.gnu.org ([209.51.188.92]:41980) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1nL6PV-00083R-0w; Fri, 18 Feb 2022 11:47:09 -0500 Received: from beetle.greensocs.com ([5.135.226.135]:48200) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1nL6PR-0007ZY-Sa; Fri, 18 Feb 2022 11:47:08 -0500 Received: from crumble.bar.greensocs.com (unknown [172.17.10.6]) by beetle.greensocs.com (Postfix) with ESMTPS id 834672089E; Fri, 18 Feb 2022 16:47:03 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=greensocs.com; s=mail; t=1645202824; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=H4p+4KovWb/FJ5Zi+VtCTfrkAKtSSXwV+qbaQx93f+0=; b=TGUueIQgRUoWBihzKsvlHPLzUcNojs9+u5r/RE7AfOAk6YsOwPM5jkJTMMhw23Cg5P22g1 xll8VmF+AE79mxY8ApLiGfbeXaNmpOdUrrrmBdRqzhDiQbe3wi+9e9C6xiqEGo6mzQz4ka of4ez8rYfF4hicWixO7W8YNzAYsM0Rc= From: Damien Hedde To: qemu-devel@nongnu.org Subject: [PATCH 2/5] target/riscv: add riscv_cpu_release_claimed_interrupts function Date: Fri, 18 Feb 2022 17:46:43 +0100 Message-Id: <20220218164646.132112-3-damien.hedde@greensocs.com> X-Mailer: git-send-email 2.35.1 In-Reply-To: <20220218164646.132112-1-damien.hedde@greensocs.com> References: <20220218164646.132112-1-damien.hedde@greensocs.com> MIME-Version: 1.0 X-Spam: Yes Received-SPF: pass client-ip=5.135.226.135; envelope-from=damien.hedde@greensocs.com; helo=beetle.greensocs.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Damien Hedde , Palmer Dabbelt , Bin Meng , Alistair Francis , qemu-riscv@nongnu.org Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" This function will be used to undo an interrupt claim made by a previous call to riscv_cpu_claim_interrupts(). Signed-off-by: Damien Hedde --- target/riscv/cpu.h | 7 +++++++ target/riscv/cpu_helper.c | 8 ++++++++ 2 files changed, 15 insertions(+) diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index 8183fb86d5..9f0c432053 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -469,6 +469,13 @@ void riscv_cpu_list(void); bool riscv_cpu_exec_interrupt(CPUState *cs, int interrupt_request); void riscv_cpu_swap_hypervisor_regs(CPURISCVState *env); int riscv_cpu_claim_interrupts(RISCVCPU *cpu, uint64_t interrupts); + +/* + * riscv_cpu_release_unclaimed_interrupts: + * Release previously claimed interrupts by riscv_cpu_claim_interrupts(). + */ +void riscv_cpu_release_claimed_interrupts(RISCVCPU *cpu, uint64_t interrupts); + uint64_t riscv_cpu_update_mip(RISCVCPU *cpu, uint64_t mask, uint64_t value); #define BOOL_TO_MASK(x) (-!!(x)) /* helper for riscv_cpu_update_mip value */ void riscv_cpu_set_rdtime_fn(CPURISCVState *env, uint64_t (*fn)(uint32_t), diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c index 746335bfd6..170fed6dff 100644 --- a/target/riscv/cpu_helper.c +++ b/target/riscv/cpu_helper.c @@ -596,6 +596,14 @@ int riscv_cpu_claim_interrupts(RISCVCPU *cpu, uint64_t interrupts) } } +void riscv_cpu_release_claimed_interrupts(RISCVCPU *cpu, uint64_t interrupts) +{ + CPURISCVState *env = &cpu->env; + /* ensure all claimed interrupt are really there */ + g_assert((env->miclaim & interrupts) == interrupts); + env->miclaim &= ~interrupts; +} + uint64_t riscv_cpu_update_mip(RISCVCPU *cpu, uint64_t mask, uint64_t value) { CPURISCVState *env = &cpu->env; From patchwork Fri Feb 18 16:46:44 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Damien Hedde X-Patchwork-Id: 12751669 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id E1C5DC433EF for ; Fri, 18 Feb 2022 16:51:43 +0000 (UTC) Received: from localhost ([::1]:59536 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1nL6Tu-0002np-Rh for qemu-devel@archiver.kernel.org; Fri, 18 Feb 2022 11:51:43 -0500 Received: from eggs.gnu.org ([209.51.188.92]:42000) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1nL6PW-00085z-Ds; Fri, 18 Feb 2022 11:47:10 -0500 Received: from beetle.greensocs.com ([5.135.226.135]:48210) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1nL6PU-0007Zg-0A; Fri, 18 Feb 2022 11:47:10 -0500 Received: from crumble.bar.greensocs.com (unknown [172.17.10.6]) by beetle.greensocs.com (Postfix) with ESMTPS id 7735020896; Fri, 18 Feb 2022 16:47:05 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=greensocs.com; s=mail; t=1645202825; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=4xAX7SU4pUP9bh0Xw0cTOBSAO2Z9jvzl/Q7RYi9FiL0=; b=vB5QzmJQgoa8EfUH73F9HoPzEsDH4rpT73S13B6eCIeNyuvelFTmXkGK869psvcrqVcWro KuhTsHlFZa/CNPztWfeLL+tXImKdA+L+0SntDi7TOnh849JWUdIvd5ammGScIg3hW7lopj Q8ciccTb3HL6wk5Q6OvILB+SxTQzotw= From: Damien Hedde To: qemu-devel@nongnu.org Subject: [PATCH 3/5] hw/intc/sifive_plic: report errors and free allocated memory Date: Fri, 18 Feb 2022 17:46:44 +0100 Message-Id: <20220218164646.132112-4-damien.hedde@greensocs.com> X-Mailer: git-send-email 2.35.1 In-Reply-To: <20220218164646.132112-1-damien.hedde@greensocs.com> References: <20220218164646.132112-1-damien.hedde@greensocs.com> MIME-Version: 1.0 Received-SPF: pass client-ip=5.135.226.135; envelope-from=damien.hedde@greensocs.com; helo=beetle.greensocs.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Damien Hedde , Palmer Dabbelt , Bin Meng , Alistair Francis , qemu-riscv@nongnu.org Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" Add the instance_finalize() method to free the allocated arrays and make realize() method report errors instead of exiting. code in realize() is re-ordered to first check for errors and leave the object in a clean state. To achieve this, we do the following: + parse_hart_config and char_to_mode are refactored to return errors instead of exiting. + in case of interrupt claim failure, we now release the succesfully claimed ones. These clean-ups allow the following life-cycle use cases (happening when user creation is allowed) to execute as expected: + init -> finalize + init -> realize-failure -> finalize Signed-off-by: Damien Hedde --- hw/intc/sifive_plic.c | 90 +++++++++++++++++++++++++++++-------------- 1 file changed, 62 insertions(+), 28 deletions(-) diff --git a/hw/intc/sifive_plic.c b/hw/intc/sifive_plic.c index eebbcf33d4..8692ea6725 100644 --- a/hw/intc/sifive_plic.c +++ b/hw/intc/sifive_plic.c @@ -37,16 +37,20 @@ static bool addr_between(uint32_t addr, uint32_t base, uint32_t num) return addr >= base && addr - base < num; } -static PLICMode char_to_mode(char c) +static PLICMode char_to_mode(char c, bool *success) { + if (success) { + *success = true; + }; switch (c) { case 'U': return PLICMode_U; case 'S': return PLICMode_S; case 'H': return PLICMode_H; case 'M': return PLICMode_M; default: - error_report("plic: invalid mode '%c'", c); - exit(1); + g_assert(success != NULL); + *success = false; + return 0; } } @@ -260,7 +264,7 @@ static void sifive_plic_reset(DeviceState *dev) * "MS,MS" 2 harts, 0-1 with M and S mode * "M,MS,MS,MS,MS" 5 harts, 0 with M mode, 1-5 with M and S mode */ -static void parse_hart_config(SiFivePLICState *plic) +static bool parse_hart_config(SiFivePLICState *plic, Error **errp) { int addrid, hartid, modes; const char *p; @@ -275,11 +279,16 @@ static void parse_hart_config(SiFivePLICState *plic) modes = 0; hartid++; } else { - int m = 1 << char_to_mode(c); + bool mode_ok = false; + int m = 1 << char_to_mode(c, &mode_ok); + if (!mode_ok) { + error_setg(errp, "plic: invalid mode '%c'", c); + return false; + } if (modes == (modes | m)) { - error_report("plic: duplicate mode '%c' in config: %s", - c, plic->hart_config); - exit(1); + error_setg(errp, "plic: duplicate mode '%c' in config: %s", + c, plic->hart_config); + return false; } modes |= m; } @@ -302,10 +311,12 @@ static void parse_hart_config(SiFivePLICState *plic) } else { plic->addr_config[addrid].addrid = addrid; plic->addr_config[addrid].hartid = hartid; - plic->addr_config[addrid].mode = char_to_mode(c); + plic->addr_config[addrid].mode = char_to_mode(c, NULL); addrid++; } } + + return true; } static void sifive_plic_irq_request(void *opaque, int irq, int level) @@ -321,12 +332,34 @@ static void sifive_plic_realize(DeviceState *dev, Error **errp) SiFivePLICState *s = SIFIVE_PLIC(dev); int i; + if (!parse_hart_config(s, errp)) { + return; + } + + /* + * We can't allow the supervisor to control SEIP as this would allow the + * supervisor to clear a pending external interrupt which will result in + * lost a interrupt in the case a PLIC is attached. The SEIP bit must be + * hardware controlled when a PLIC is attached. + */ + for (i = 0; i < s->num_harts; i++) { + RISCVCPU *cpu = RISCV_CPU(qemu_get_cpu(s->hartid_base + i)); + if (riscv_cpu_claim_interrupts(cpu, MIP_SEIP) < 0) { + error_setg(errp, "SEIP (hartid %u) already claimed", + (unsigned) (s->hartid_base + i)); + /* release interrupts we already claimed */ + while (--i >= 0) { + cpu = RISCV_CPU(qemu_get_cpu(s->hartid_base + i)); + riscv_cpu_release_claimed_interrupts(cpu, MIP_SEIP); + } + return; + } + } + memory_region_init_io(&s->mmio, OBJECT(dev), &sifive_plic_ops, s, TYPE_SIFIVE_PLIC, s->aperture_size); sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->mmio); - parse_hart_config(s); - s->bitfield_words = (s->num_sources + 31) >> 5; s->num_enables = s->bitfield_words * s->num_addrs; s->source_priority = g_new0(uint32_t, s->num_sources); @@ -343,19 +376,6 @@ static void sifive_plic_realize(DeviceState *dev, Error **errp) s->m_external_irqs = g_malloc(sizeof(qemu_irq) * s->num_harts); qdev_init_gpio_out(dev, s->m_external_irqs, s->num_harts); - /* We can't allow the supervisor to control SEIP as this would allow the - * supervisor to clear a pending external interrupt which will result in - * lost a interrupt in the case a PLIC is attached. The SEIP bit must be - * hardware controlled when a PLIC is attached. - */ - for (i = 0; i < s->num_harts; i++) { - RISCVCPU *cpu = RISCV_CPU(qemu_get_cpu(s->hartid_base + i)); - if (riscv_cpu_claim_interrupts(cpu, MIP_SEIP) < 0) { - error_report("SEIP already claimed"); - exit(1); - } - } - msi_nonbroken = true; } @@ -380,6 +400,19 @@ static const VMStateDescription vmstate_sifive_plic = { } }; +static void sifive_plic_finalize(Object *obj) +{ + SiFivePLICState *s = SIFIVE_PLIC(obj); + + /* free allocated arrays during realize */ + g_free(s->addr_config); + g_free(s->source_priority); + g_free(s->target_priority); + g_free(s->pending); + g_free(s->claimed); + g_free(s->enable); +} + static Property sifive_plic_properties[] = { DEFINE_PROP_STRING("hart-config", SiFivePLICState, hart_config), DEFINE_PROP_UINT32("hartid-base", SiFivePLICState, hartid_base, 0), @@ -406,10 +439,11 @@ static void sifive_plic_class_init(ObjectClass *klass, void *data) } static const TypeInfo sifive_plic_info = { - .name = TYPE_SIFIVE_PLIC, - .parent = TYPE_SYS_BUS_DEVICE, - .instance_size = sizeof(SiFivePLICState), - .class_init = sifive_plic_class_init, + .name = TYPE_SIFIVE_PLIC, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(SiFivePLICState), + .class_init = sifive_plic_class_init, + .instance_finalize = sifive_plic_finalize, }; static void sifive_plic_register_types(void) From patchwork Fri Feb 18 16:46:45 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Damien Hedde X-Patchwork-Id: 12751670 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 47332C433F5 for ; Fri, 18 Feb 2022 16:59:08 +0000 (UTC) Received: from localhost ([::1]:38324 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1nL6b4-0007qU-OQ for qemu-devel@archiver.kernel.org; Fri, 18 Feb 2022 11:59:06 -0500 Received: from eggs.gnu.org ([209.51.188.92]:42002) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1nL6PW-000860-E5; Fri, 18 Feb 2022 11:47:10 -0500 Received: from beetle.greensocs.com ([5.135.226.135]:48222) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1nL6PU-0007Zn-12; Fri, 18 Feb 2022 11:47:10 -0500 Received: from crumble.bar.greensocs.com (unknown [172.17.10.6]) by beetle.greensocs.com (Postfix) with ESMTPS id 8AD4621CC1; Fri, 18 Feb 2022 16:47:06 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=greensocs.com; s=mail; t=1645202826; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=rot2Pl1QPDGByt+5HyOTER5H275oBzwReH0SWq5PrKs=; b=ad0enHKdjXazMYmfl7gkOLZkNFA5AmNeH9cWul9ZQoLN4NZm07INmG7GNaVgqQDqFXvbNn lDzlfqcRy7D1idPBLEIsUr/6Kf88hTxYR3zgBKO9e7AMPtQUeRvJ29XhBkYN4ru7lBXd6j Zcu8685gObRlqHc2Xg8osaYmi6JKp60= From: Damien Hedde To: qemu-devel@nongnu.org Subject: [PATCH 4/5] hw/intc/riscv_aclint: swi: report errors and free allocated memory Date: Fri, 18 Feb 2022 17:46:45 +0100 Message-Id: <20220218164646.132112-5-damien.hedde@greensocs.com> X-Mailer: git-send-email 2.35.1 In-Reply-To: <20220218164646.132112-1-damien.hedde@greensocs.com> References: <20220218164646.132112-1-damien.hedde@greensocs.com> MIME-Version: 1.0 Received-SPF: pass client-ip=5.135.226.135; envelope-from=damien.hedde@greensocs.com; helo=beetle.greensocs.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Damien Hedde , Palmer Dabbelt , Bin Meng , Alistair Francis , qemu-riscv@nongnu.org Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" Add the instance_finalize() method to free the allocated arrays and make realize() method report errors instead of exiting. This commit also move the 'num-harts' property check from riscv_aclint_swi_create() to realize(). Code in realize() is re-ordered to first check for errors and leave the object in a clean state. To achieve this, we do the following: + parse_hart_config and char_to_mode are refactored to return errors instead of exiting. + in case of interrupt claim failure, we release the succesfully claimed ones. These clean-ups allow the following life-cycle use cases (happening when user creation is allowed) to execute as expected: + init -> finalize + init -> realize-failure -> finalize Signed-off-by: Damien Hedde --- hw/intc/riscv_aclint.c | 54 +++++++++++++++++++++++++++++++----------- 1 file changed, 40 insertions(+), 14 deletions(-) diff --git a/hw/intc/riscv_aclint.c b/hw/intc/riscv_aclint.c index f1a5d3d284..4f66eeed0b 100644 --- a/hw/intc/riscv_aclint.c +++ b/hw/intc/riscv_aclint.c @@ -389,22 +389,48 @@ static void riscv_aclint_swi_realize(DeviceState *dev, Error **errp) RISCVAclintSwiState *swi = RISCV_ACLINT_SWI(dev); int i; + if (swi->num_harts > RISCV_ACLINT_MAX_HARTS) { + error_setg(errp, "invalid 'num-harts': max is %u", + RISCV_ACLINT_MAX_HARTS); + return; + } + + /* + * Claim software interrupt bits: + * + sswi==false -> MSIP + * + sswi==true -> SSIP + * We don't claim mip.SSIP because it is writeable by software + */ + if (!swi->sswi) { + for (i = 0; i < swi->num_harts; i++) { + RISCVCPU *cpu = RISCV_CPU(qemu_get_cpu(swi->hartid_base + i)); + if (riscv_cpu_claim_interrupts(cpu, MIP_MSIP) < 0) { + error_setg(errp, "MSIP (hartid %u) already claimed", + (unsigned) (swi->hartid_base + i)); + /* release interrupts we already claimed */ + while (--i >= 0) { + cpu = RISCV_CPU(qemu_get_cpu(swi->hartid_base + i)); + riscv_cpu_release_claimed_interrupts(cpu, MIP_MSIP); + } + return; + } + } + } + memory_region_init_io(&swi->mmio, OBJECT(dev), &riscv_aclint_swi_ops, swi, TYPE_RISCV_ACLINT_SWI, RISCV_ACLINT_SWI_SIZE); sysbus_init_mmio(SYS_BUS_DEVICE(dev), &swi->mmio); swi->soft_irqs = g_malloc(sizeof(qemu_irq) * swi->num_harts); qdev_init_gpio_out(dev, swi->soft_irqs, swi->num_harts); +} - /* Claim software interrupt bits */ - for (i = 0; i < swi->num_harts; i++) { - RISCVCPU *cpu = RISCV_CPU(qemu_get_cpu(swi->hartid_base + i)); - /* We don't claim mip.SSIP because it is writeable by software */ - if (riscv_cpu_claim_interrupts(cpu, swi->sswi ? 0 : MIP_MSIP) < 0) { - error_report("MSIP already claimed"); - exit(1); - } - } +static void riscv_aclint_swi_finalize(Object *obj) +{ + RISCVAclintSwiState *swi = RISCV_ACLINT_SWI(obj); + + /* free allocated area during realize */ + g_free(swi->soft_irqs); } static void riscv_aclint_swi_class_init(ObjectClass *klass, void *data) @@ -415,10 +441,11 @@ static void riscv_aclint_swi_class_init(ObjectClass *klass, void *data) } static const TypeInfo riscv_aclint_swi_info = { - .name = TYPE_RISCV_ACLINT_SWI, - .parent = TYPE_SYS_BUS_DEVICE, - .instance_size = sizeof(RISCVAclintSwiState), - .class_init = riscv_aclint_swi_class_init, + .name = TYPE_RISCV_ACLINT_SWI, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(RISCVAclintSwiState), + .class_init = riscv_aclint_swi_class_init, + .instance_finalize = riscv_aclint_swi_finalize, }; /* @@ -430,7 +457,6 @@ DeviceState *riscv_aclint_swi_create(hwaddr addr, uint32_t hartid_base, int i; DeviceState *dev = qdev_new(TYPE_RISCV_ACLINT_SWI); - assert(num_harts <= RISCV_ACLINT_MAX_HARTS); assert(!(addr & 0x3)); qdev_prop_set_uint32(dev, "hartid-base", hartid_base); From patchwork Fri Feb 18 16:46:46 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Damien Hedde X-Patchwork-Id: 12751671 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id EF21FC433EF for ; Fri, 18 Feb 2022 16:59:21 +0000 (UTC) Received: from localhost ([::1]:38810 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1nL6bI-0008Bo-TJ for qemu-devel@archiver.kernel.org; Fri, 18 Feb 2022 11:59:21 -0500 Received: from eggs.gnu.org ([209.51.188.92]:42014) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1nL6PY-00088u-5N; Fri, 18 Feb 2022 11:47:12 -0500 Received: from beetle.greensocs.com ([5.135.226.135]:48230) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1nL6PV-0007aA-W4; Fri, 18 Feb 2022 11:47:11 -0500 Received: from crumble.bar.greensocs.com (unknown [172.17.10.6]) by beetle.greensocs.com (Postfix) with ESMTPS id 2D78520898; Fri, 18 Feb 2022 16:47:08 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=greensocs.com; s=mail; t=1645202828; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=g4sr0IJti3TGhgwlPTvOYjRFvSZ9hztg7SR5KFeE83w=; b=3FxwdJ1N3Vhgk95zvNrO3bXB0XXz7X4Y/OtOobOZaekrE2szALsF0ZxBiXpONRBpammBai 6aKzwKeFWy2yVCBzzfq0xph+zOUTTVno0cUYoqSBmGAEVx+0fKiFI66+YjSXMChEuILFmE 6tO51tLrGLcnzJM4+4seUkybz5plLfE= From: Damien Hedde To: qemu-devel@nongnu.org Subject: [PATCH 5/5] hw/intc/riscv_aclint: mtimer: report errors and free allocated memory Date: Fri, 18 Feb 2022 17:46:46 +0100 Message-Id: <20220218164646.132112-6-damien.hedde@greensocs.com> X-Mailer: git-send-email 2.35.1 In-Reply-To: <20220218164646.132112-1-damien.hedde@greensocs.com> References: <20220218164646.132112-1-damien.hedde@greensocs.com> MIME-Version: 1.0 Received-SPF: pass client-ip=5.135.226.135; envelope-from=damien.hedde@greensocs.com; helo=beetle.greensocs.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Damien Hedde , Palmer Dabbelt , Bin Meng , Alistair Francis , qemu-riscv@nongnu.org Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" Add the instance_finalize() method to free the allocated arrays and make realize() method report errors instead of exiting. This commit also move the properties check from riscv_aclint_mtimer_create() to realize(). code in realize() is re-ordered to first check for errors and leave the object in a clean state. To achieve this, we do the following: + parse_hart_config and char_to_mode are refactored to return errors instead of exiting. + in case of interrupt claim failure, we now release the succesfully claimed ones. These clean-ups allow the following life-cycle use cases (happening when user creation is allowed) to execute as expected: + init -> finalize + init -> realize-failure -> finalize Signed-off-by: Damien Hedde --- hw/intc/riscv_aclint.c | 58 +++++++++++++++++++++++++++++++----------- 1 file changed, 43 insertions(+), 15 deletions(-) diff --git a/hw/intc/riscv_aclint.c b/hw/intc/riscv_aclint.c index 4f66eeed0b..bef2e1988b 100644 --- a/hw/intc/riscv_aclint.c +++ b/hw/intc/riscv_aclint.c @@ -231,21 +231,51 @@ static void riscv_aclint_mtimer_realize(DeviceState *dev, Error **errp) RISCVAclintMTimerState *s = RISCV_ACLINT_MTIMER(dev); int i; + if (s->num_harts > RISCV_ACLINT_MAX_HARTS) { + error_setg(errp, "invalid 'num-harts': max is %u", + RISCV_ACLINT_MAX_HARTS); + return; + } + + if (s->timecmp_base & 0x7) { + error_setg(errp, "invalid 'timecmp-base': must be aligned on 0x8"); + return; + } + + if (s->time_base & 0x7) { + error_setg(errp, "invalid 'time-base': must be aligned on 0x8"); + return; + } + + /* Claim timer interrupt bits */ + for (i = 0; i < s->num_harts; i++) { + RISCVCPU *cpu = RISCV_CPU(qemu_get_cpu(s->hartid_base + i)); + if (riscv_cpu_claim_interrupts(cpu, MIP_MTIP) < 0) { + error_setg(errp, "MTIP (hartid %u) already claimed", + (unsigned) (s->hartid_base + i)); + /* release interrupts we already claimed */ + while (--i >= 0) { + cpu = RISCV_CPU(qemu_get_cpu(s->hartid_base + i)); + riscv_cpu_release_claimed_interrupts(cpu, MIP_MTIP); + } + return; + } + } + memory_region_init_io(&s->mmio, OBJECT(dev), &riscv_aclint_mtimer_ops, s, TYPE_RISCV_ACLINT_MTIMER, s->aperture_size); sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->mmio); s->timer_irqs = g_malloc(sizeof(qemu_irq) * s->num_harts); qdev_init_gpio_out(dev, s->timer_irqs, s->num_harts); +} - /* Claim timer interrupt bits */ - for (i = 0; i < s->num_harts; i++) { - RISCVCPU *cpu = RISCV_CPU(qemu_get_cpu(s->hartid_base + i)); - if (riscv_cpu_claim_interrupts(cpu, MIP_MTIP) < 0) { - error_report("MTIP already claimed"); - exit(1); - } - } +static void riscv_aclint_mtimer_finalize(Object *obj) +{ + RISCVAclintMTimerState *s = RISCV_ACLINT_MTIMER(obj); + + /* free allocated area during realize */ + g_free(s->timer_irqs); } static void riscv_aclint_mtimer_class_init(ObjectClass *klass, void *data) @@ -256,10 +286,11 @@ static void riscv_aclint_mtimer_class_init(ObjectClass *klass, void *data) } static const TypeInfo riscv_aclint_mtimer_info = { - .name = TYPE_RISCV_ACLINT_MTIMER, - .parent = TYPE_SYS_BUS_DEVICE, - .instance_size = sizeof(RISCVAclintMTimerState), - .class_init = riscv_aclint_mtimer_class_init, + .name = TYPE_RISCV_ACLINT_MTIMER, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(RISCVAclintMTimerState), + .class_init = riscv_aclint_mtimer_class_init, + .instance_finalize = riscv_aclint_mtimer_finalize, }; /* @@ -273,10 +304,7 @@ DeviceState *riscv_aclint_mtimer_create(hwaddr addr, hwaddr size, int i; DeviceState *dev = qdev_new(TYPE_RISCV_ACLINT_MTIMER); - assert(num_harts <= RISCV_ACLINT_MAX_HARTS); assert(!(addr & 0x7)); - assert(!(timecmp_base & 0x7)); - assert(!(time_base & 0x7)); qdev_prop_set_uint32(dev, "hartid-base", hartid_base); qdev_prop_set_uint32(dev, "num-harts", num_harts);