From patchwork Thu Jun 8 22:18:15 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Curtis Malainey X-Patchwork-Id: 13272957 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 alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) (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 D8ACDC7EE25 for ; Thu, 8 Jun 2023 22:20:08 +0000 (UTC) Received: from alsa1.perex.cz (alsa1.perex.cz [207.180.221.201]) (using TLSv1.2 with cipher ADH-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by alsa0.perex.cz (Postfix) with ESMTPS id ED8CC6C1; Fri, 9 Jun 2023 00:19:15 +0200 (CEST) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz ED8CC6C1 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1686262806; bh=qrONA1YvHRyjKpWYANRMf4h3hWq7juhzopMG9+uY5es=; h=From:To:Cc:Subject:Date:List-Id:List-Archive:List-Help:List-Owner: List-Post:List-Subscribe:List-Unsubscribe:From; b=BplWuM7VadsmyRgl7s8x62LYeu9ctnWx99RIcTogR4L/raPu0EUYxYOq4JX8WtGhe l0UVmcy7t/o709EdoT1QiLJjtJUSaPrFBFu9JWQJdI0A7iGkae9G+aO7y/5KLBaQxA 2+JbLuTTOpPaKKJifvAy/eCV43Ou6LE1uT4j7DHo= Received: by alsa1.perex.cz (Postfix, from userid 50401) id 8190BF80548; Fri, 9 Jun 2023 00:18:53 +0200 (CEST) Received: from mailman-core.alsa-project.org (mailman-core.alsa-project.org [10.254.200.10]) by alsa1.perex.cz (Postfix) with ESMTP id 27CFAF80494; Fri, 9 Jun 2023 00:18:53 +0200 (CEST) Received: by alsa1.perex.cz (Postfix, from userid 50401) id 36E30F80199; Fri, 9 Jun 2023 00:18:49 +0200 (CEST) Received: from mail-pf1-x436.google.com (mail-pf1-x436.google.com [IPv6:2607:f8b0:4864:20::436]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id 23EB2F800C8 for ; Fri, 9 Jun 2023 00:18:33 +0200 (CEST) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz 23EB2F800C8 Authentication-Results: alsa1.perex.cz; dkim=pass (1024-bit key, unprotected) header.d=chromium.org header.i=@chromium.org header.a=rsa-sha256 header.s=google header.b=jOPcpthT Received: by mail-pf1-x436.google.com with SMTP id d2e1a72fcca58-65292f79456so863958b3a.2 for ; Thu, 08 Jun 2023 15:18:33 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; t=1686262711; x=1688854711; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:from:to:cc:subject:date:message-id:reply-to; bh=Ky2eL8st8jozX37OGoV09JoInUi6PYM9R0069A5z+Ls=; b=jOPcpthTfIRnHGHXkFhKNnPavqy8zAmuywMkem/Pys0ZzvW5RqOuZcNXs0d8NjKdR9 4eJKaBJmsZ3ozOLeUmlRYK+KN3qdBUUk7uF7KbhoQeJ+PMsSSu/Sntl0oxtISUDQlaiY XZS/hIWYMrERIDsOv55NQg8xoJqvxQ5VCmsa4= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1686262711; x=1688854711; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=Ky2eL8st8jozX37OGoV09JoInUi6PYM9R0069A5z+Ls=; b=Qj27XarbgXufp4BwJKG0QWYHrAgocIATjZg8RjPYNs9886BVkoXLMdcDJQtkp/AACY dlU1k5PdmYpUk3c+EqMjHFX7nOoKj0Zg7eedf42k2M8OOtAKMlBMRz+mz0zZvogBx0dF jmZCRP6u3q6Ch7RfJbDDQcKGyLRGS65LDIYCteZtxjrqB7VoP8XZM4dW3Y6vZDPwvS/D qzA5T31CQGwjrK10B/aNFyD2cqkZ5P7aBWX0IZbRG/XyezybBtNJN+JTY3UMYmgDNZys uU8o9y7yA0hC1tBytaMTTJLwQid7Be020rhiq1doDhRskw7NDklKq3G4dzgObigBEDoy 7GLQ== X-Gm-Message-State: AC+VfDybTzo7o0hulh+uAwXL0qi1j6Qw3k2U2DnNemFbAJ40NLBEkDkk iWa+chm9QXK7lx7i5xvmBzEkhOpedanMqdP8/w== X-Google-Smtp-Source: ACHHUZ4PPs1O96GAHFMhb80HHkCXgki5ykjUZmc30n2Lyn1Chk31gnpvAN/vqTXUB4lITNAgEfcWhQ== X-Received: by 2002:a05:6a20:2d10:b0:107:1f22:10d5 with SMTP id g16-20020a056a202d1000b001071f2210d5mr4998085pzl.52.1686262710475; Thu, 08 Jun 2023 15:18:30 -0700 (PDT) Received: from localhost ([2620:15c:9d:4:4e2b:3200:7e2c:cb0]) by smtp.gmail.com with UTF8SMTPSA id m12-20020a63580c000000b0053b92b26412sm1667435pgb.14.2023.06.08.15.18.29 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Thu, 08 Jun 2023 15:18:30 -0700 (PDT) From: cujomalainey@chromium.org To: alsa-devel@alsa-project.org Cc: Curtis Malainey , Ranjani Sridharan , Pierre-Louis Bossart , =?utf-8?q?P?= =?utf-8?q?=C3=A9ter_Ujfalusi?= , Liam Girdwood , Bard Liao , Daniel Baluta , Kai Vehmanen , Mark Brown , Jaroslav Kysela , Takashi Iwai Subject: [PATCH 1/2] ASoC: SOF: Refactor rx function for fuzzing Date: Thu, 8 Jun 2023 15:18:15 -0700 Message-ID: <20230608221822.2825786-1-cujomalainey@chromium.org> X-Mailer: git-send-email 2.41.0.162.gfafddb0af9-goog MIME-Version: 1.0 Message-ID-Hash: RG26TJHUZH2GLNGULEOL4JC2SQZ6UESH X-Message-ID-Hash: RG26TJHUZH2GLNGULEOL4JC2SQZ6UESH X-MailFrom: cujomalainey@chromium.org X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; emergency; loop; banned-address; member-moderation; header-match-alsa-devel.alsa-project.org-0; header-match-alsa-devel.alsa-project.org-1; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; digests; suspicious-header X-Mailman-Version: 3.3.8 Precedence: list List-Id: "Alsa-devel mailing list for ALSA developers - http://www.alsa-project.org" Archived-At: List-Archive: List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: From: Curtis Malainey Refactor the function so reading the data is done outside the work function so fuzzing can pass data directly into the work callbacks. Also expose the inner function outside the module so we can call it from the injector. Signed-off-by: Curtis Malainey Reviewed-by: Ranjani Sridharan Reviewed-by: Pierre-Louis Bossart Reviewed-by: Péter Ujfalusi --- sound/soc/sof/ipc3-priv.h | 2 ++ sound/soc/sof/ipc3.c | 63 ++++++++++++++++++++++++--------------- 2 files changed, 41 insertions(+), 24 deletions(-) diff --git a/sound/soc/sof/ipc3-priv.h b/sound/soc/sof/ipc3-priv.h index f5044202f3c5a..0bbca418e67e6 100644 --- a/sound/soc/sof/ipc3-priv.h +++ b/sound/soc/sof/ipc3-priv.h @@ -28,6 +28,8 @@ int sof_ipc3_validate_fw_version(struct snd_sof_dev *sdev); /* dtrace position update */ int ipc3_dtrace_posn_update(struct snd_sof_dev *sdev, struct sof_ipc_dma_trace_posn *posn); +/* RX handler backend */ +void sof_ipc3_do_rx_work(struct snd_sof_dev *sdev, struct sof_ipc_cmd_hdr *hdr, void *msg_buf); /* dtrace platform callback wrappers */ static inline int sof_dtrace_host_init(struct snd_sof_dev *sdev, diff --git a/sound/soc/sof/ipc3.c b/sound/soc/sof/ipc3.c index c677677420939..ec1ac0fb2d9f8 100644 --- a/sound/soc/sof/ipc3.c +++ b/sound/soc/sof/ipc3.c @@ -954,31 +954,21 @@ static void ipc3_trace_message(struct snd_sof_dev *sdev, void *msg_buf) } } -/* DSP firmware has sent host a message */ -static void sof_ipc3_rx_msg(struct snd_sof_dev *sdev) +void sof_ipc3_do_rx_work(struct snd_sof_dev *sdev, struct sof_ipc_cmd_hdr *hdr, void *msg_buf) { ipc3_rx_callback rx_callback = NULL; - struct sof_ipc_cmd_hdr hdr; - void *msg_buf; u32 cmd; int err; - /* read back header */ - err = snd_sof_ipc_msg_data(sdev, NULL, &hdr, sizeof(hdr)); - if (err < 0) { - dev_warn(sdev->dev, "failed to read IPC header: %d\n", err); - return; - } + ipc3_log_header(sdev->dev, "ipc rx", hdr->cmd); - if (hdr.size < sizeof(hdr) || hdr.size > SOF_IPC_MSG_MAX_SIZE) { + if (hdr->size < sizeof(hdr) || hdr->size > SOF_IPC_MSG_MAX_SIZE) { dev_err(sdev->dev, "The received message size is invalid: %u\n", - hdr.size); + hdr->size); return; } - ipc3_log_header(sdev->dev, "ipc rx", hdr.cmd); - - cmd = hdr.cmd & SOF_GLB_TYPE_MASK; + cmd = hdr->cmd & SOF_GLB_TYPE_MASK; /* check message type */ switch (cmd) { @@ -1016,6 +1006,36 @@ static void sof_ipc3_rx_msg(struct snd_sof_dev *sdev) break; } + /* Call local handler for the message */ + if (rx_callback) + rx_callback(sdev, msg_buf); + + /* Notify registered clients */ + sof_client_ipc_rx_dispatcher(sdev, msg_buf); + + ipc3_log_header(sdev->dev, "ipc rx done", hdr->cmd); +} +EXPORT_SYMBOL(sof_ipc3_do_rx_work); + +/* DSP firmware has sent host a message */ +static void sof_ipc3_rx_msg(struct snd_sof_dev *sdev) +{ + struct sof_ipc_cmd_hdr hdr; + void *msg_buf; + int err; + + /* read back header */ + err = snd_sof_ipc_msg_data(sdev, NULL, &hdr, sizeof(hdr)); + if (err < 0) { + dev_warn(sdev->dev, "failed to read IPC header: %d\n", err); + return; + } + + if (hdr.size < sizeof(hdr)) { + dev_err(sdev->dev, "The received message size is invalid\n"); + return; + } + /* read the full message */ msg_buf = kmalloc(hdr.size, GFP_KERNEL); if (!msg_buf) @@ -1024,18 +1044,13 @@ static void sof_ipc3_rx_msg(struct snd_sof_dev *sdev) err = snd_sof_ipc_msg_data(sdev, NULL, msg_buf, hdr.size); if (err < 0) { dev_err(sdev->dev, "%s: Failed to read message: %d\n", __func__, err); - } else { - /* Call local handler for the message */ - if (rx_callback) - rx_callback(sdev, msg_buf); - - /* Notify registered clients */ - sof_client_ipc_rx_dispatcher(sdev, msg_buf); + kfree(msg_buf); + return; } - kfree(msg_buf); + sof_ipc3_do_rx_work(sdev, &hdr, msg_buf); - ipc3_log_header(sdev->dev, "ipc rx done", hdr.cmd); + kfree(msg_buf); } static int sof_ipc3_set_core_state(struct snd_sof_dev *sdev, int core_idx, bool on) From patchwork Thu Jun 8 22:18:16 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Curtis Malainey X-Patchwork-Id: 13272958 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 alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) (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 EAB49C7EE23 for ; Thu, 8 Jun 2023 22:20:36 +0000 (UTC) Received: from alsa1.perex.cz (alsa1.perex.cz [207.180.221.201]) (using TLSv1.2 with cipher ADH-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by alsa0.perex.cz (Postfix) with ESMTPS id 9A421825; Fri, 9 Jun 2023 00:19:44 +0200 (CEST) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz 9A421825 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1686262834; bh=3DBRlx2NxSnA6NJ8HFQLMriYLzCJmMXiy4qm67FNlIk=; h=From:To:Cc:Subject:Date:In-Reply-To:References:List-Id: List-Archive:List-Help:List-Owner:List-Post:List-Subscribe: List-Unsubscribe:From; b=m1uvRmpTL/ymWPGZAELPunqwTSFmb8v1w+SL70TTBUnT2hNW3NNeWBQyS7Ax+z7RJ Qmx6mahJ7+yXVOPEbHcf4eXP8+NRjX8tvg3nm50BMCkLdCeZ+xYrgK1FV3psZIcVXz JrQEp8NP0AX13kBlB3fk9P40BCZqS5KHDdOyXmb8= Received: by alsa1.perex.cz (Postfix, from userid 50401) id 5168BF80549; Fri, 9 Jun 2023 00:19:15 +0200 (CEST) Received: from mailman-core.alsa-project.org (mailman-core.alsa-project.org [10.254.200.10]) by alsa1.perex.cz (Postfix) with ESMTP id B2401F80549; Fri, 9 Jun 2023 00:19:14 +0200 (CEST) Received: by alsa1.perex.cz (Postfix, from userid 50401) id 7CACCF80549; Fri, 9 Jun 2023 00:19:11 +0200 (CEST) Received: from mail-pf1-x429.google.com (mail-pf1-x429.google.com [IPv6:2607:f8b0:4864:20::429]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id 23E4EF80520 for ; Fri, 9 Jun 2023 00:18:47 +0200 (CEST) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz 23E4EF80520 Authentication-Results: alsa1.perex.cz; dkim=pass (1024-bit key, unprotected) header.d=chromium.org header.i=@chromium.org header.a=rsa-sha256 header.s=google header.b=Vegwzt0k Received: by mail-pf1-x429.google.com with SMTP id d2e1a72fcca58-650c8cb68aeso933064b3a.3 for ; Thu, 08 Jun 2023 15:18:47 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; t=1686262725; x=1688854725; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=e+cMdbZhW0Wcsi54eHFr6fOPrRXt/DqtLKCDv50m+tA=; b=Vegwzt0kxPCBcNMxLShjdOnCxhwH2zxv2t4crDVba9RiOWqVtfwErHPIwYWdkTwrsq NOPH6297RfK1kfjao4erZyGbUHTz0/NvTxRPThcvQziNXWwrGVcZzVhkcpmO3PtXI7zv rLKqWDrzCLH2Eek/y89yn9D5S459u5M4BnQu0= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1686262725; x=1688854725; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=e+cMdbZhW0Wcsi54eHFr6fOPrRXt/DqtLKCDv50m+tA=; b=OSR4xkwbMsPs7bkqlkDpEOQiU6yjyKQwOZS0wxC7DbGA+NzwgJ1VA5gAmoSBzpf3bK 1XOeLHJwnYLRa15N6e2sEPcftE52lh9X5Z+pLZf7r89eYbbAUpnSQW0ic8C0+crPpZgk zOCGUlRtg402j5A5zvXOHo7wbf81HKVypZW+TfFLLewBay3Zu8R0O6bmlnCOccng0YOZ bhBsOiHk2atdOtbaM4JBRp/h7upZJvxkSPtcLxcCJRRX5XCevC65skawnXu9na3coV3J IKFhLlleNkQehZAmM/UznNRSJr8AYAnfVWgn2UKIY+dVGciDMg2NZ2Bzv4FdaoPR8nL+ KjoQ== X-Gm-Message-State: AC+VfDwjag0I0xwCr0uPHhZYIWOluvFbkaSI5W2qRB2IQv8dfXqu/O1T KP2IhzjAB0wMhUKXGGberxTQV/IVDvOQ7KVTFQ== X-Google-Smtp-Source: ACHHUZ7d15Ht1ImVg4AyZmq8AjTmsMugIch861POLcb835jIHc9eReTFiUveQUNTSdqLdop6xyFZmQ== X-Received: by 2002:a05:6a20:4425:b0:10e:e218:d3f0 with SMTP id ce37-20020a056a20442500b0010ee218d3f0mr5577054pzb.54.1686262725352; Thu, 08 Jun 2023 15:18:45 -0700 (PDT) Received: from localhost ([2620:15c:9d:4:4e2b:3200:7e2c:cb0]) by smtp.gmail.com with UTF8SMTPSA id o18-20020a639212000000b00502ecb91940sm1693889pgd.55.2023.06.08.15.18.44 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Thu, 08 Jun 2023 15:18:45 -0700 (PDT) From: cujomalainey@chromium.org To: alsa-devel@alsa-project.org Cc: Curtis Malainey , Ranjani Sridharan , Pierre-Louis Bossart , =?utf-8?q?P?= =?utf-8?q?=C3=A9ter_Ujfalusi?= , Liam Girdwood , Bard Liao , Daniel Baluta , Kai Vehmanen , Mark Brown , Jaroslav Kysela , Takashi Iwai Subject: [PATCH 2/2] ASoC: SOF: Add IPC3 Kernel Injector Date: Thu, 8 Jun 2023 15:18:16 -0700 Message-ID: <20230608221822.2825786-2-cujomalainey@chromium.org> X-Mailer: git-send-email 2.41.0.162.gfafddb0af9-goog In-Reply-To: <20230608221822.2825786-1-cujomalainey@chromium.org> References: <20230608221822.2825786-1-cujomalainey@chromium.org> MIME-Version: 1.0 Message-ID-Hash: NDGDOJMGBHMFVYJ47DJEHXOOSCBV4ZCA X-Message-ID-Hash: NDGDOJMGBHMFVYJ47DJEHXOOSCBV4ZCA X-MailFrom: cujomalainey@chromium.org X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; emergency; loop; banned-address; member-moderation; header-match-alsa-devel.alsa-project.org-0; header-match-alsa-devel.alsa-project.org-1; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; digests; suspicious-header X-Mailman-Version: 3.3.8 Precedence: list List-Id: "Alsa-devel mailing list for ALSA developers - http://www.alsa-project.org" Archived-At: List-Archive: List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: From: Curtis Malainey Add debugfs path to fake a malicious firmware message for fuzzing purposes. Skip IPC4 for initial integration Signed-off-by: Curtis Malainey Reviewed-by: Ranjani Sridharan Reviewed-by: Pierre-Louis Bossart Reviewed-by: Péter Ujfalusi --- sound/soc/sof/Kconfig | 11 ++ sound/soc/sof/Makefile | 2 + .../soc/sof/sof-client-ipc-kernel-injector.c | 162 ++++++++++++++++++ sound/soc/sof/sof-client.c | 52 ++++++ sound/soc/sof/sof-client.h | 1 + 5 files changed, 228 insertions(+) create mode 100644 sound/soc/sof/sof-client-ipc-kernel-injector.c diff --git a/sound/soc/sof/Kconfig b/sound/soc/sof/Kconfig index a2725188f4ce4..80361139a49ad 100644 --- a/sound/soc/sof/Kconfig +++ b/sound/soc/sof/Kconfig @@ -236,6 +236,17 @@ config SND_SOC_SOF_DEBUG_IPC_MSG_INJECTOR Say Y if you want to enable the IPC message injector. If unsure, select "N". +config SND_SOC_SOF_DEBUG_IPC_KERNEL_INJECTOR + tristate "SOF enable IPC kernel injector" + depends on SND_SOC_SOF + select SND_SOC_SOF_CLIENT + help + This option enables the IPC kernel injector which can be used to send + crafted IPC messages to the kernel to test its robustness against + DSP messages. + Say Y if you want to enable the IPC kernel injector. + If unsure, select "N". + config SND_SOC_SOF_DEBUG_RETAIN_DSP_CONTEXT bool "SOF retain DSP context on any FW exceptions" help diff --git a/sound/soc/sof/Makefile b/sound/soc/sof/Makefile index 308d876399163..744d40bd8c8ba 100644 --- a/sound/soc/sof/Makefile +++ b/sound/soc/sof/Makefile @@ -26,6 +26,7 @@ snd-sof-of-objs := sof-of-dev.o snd-sof-ipc-flood-test-objs := sof-client-ipc-flood-test.o snd-sof-ipc-msg-injector-objs := sof-client-ipc-msg-injector.o +snd-sof-ipc-kernel-injector-objs := sof-client-ipc-kernel-injector.o snd-sof-probes-objs := sof-client-probes.o ifneq ($(CONFIG_SND_SOC_SOF_IPC3),) snd-sof-probes-objs += sof-client-probes-ipc3.o @@ -49,6 +50,7 @@ obj-$(CONFIG_SND_SOC_SOF_PCI_DEV) += snd-sof-pci.o obj-$(CONFIG_SND_SOC_SOF_DEBUG_IPC_FLOOD_TEST) += snd-sof-ipc-flood-test.o obj-$(CONFIG_SND_SOC_SOF_DEBUG_IPC_MSG_INJECTOR) += snd-sof-ipc-msg-injector.o +obj-$(CONFIG_SND_SOC_SOF_DEBUG_IPC_KERNEL_INJECTOR) += snd-sof-ipc-kernel-injector.o obj-$(CONFIG_SND_SOC_SOF_DEBUG_PROBES) += snd-sof-probes.o obj-$(CONFIG_SND_SOC_SOF_INTEL_TOPLEVEL) += intel/ diff --git a/sound/soc/sof/sof-client-ipc-kernel-injector.c b/sound/soc/sof/sof-client-ipc-kernel-injector.c new file mode 100644 index 0000000000000..ad0ed2d570a91 --- /dev/null +++ b/sound/soc/sof/sof-client-ipc-kernel-injector.c @@ -0,0 +1,162 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// Copyright(c) 2023 Google Inc. All rights reserved. +// +// Author: Curtis Malainey +// + +#include +#include +#include +#include +#include +#include + +#include "sof-client.h" + +#define SOF_IPC_CLIENT_SUSPEND_DELAY_MS 3000 + +struct sof_msg_inject_priv { + struct dentry *kernel_dfs_file; + size_t max_msg_size; + + void *kernel_buffer; +}; + +static int sof_msg_inject_dfs_open(struct inode *inode, struct file *file) +{ + int ret = debugfs_file_get(file->f_path.dentry); + + if (unlikely(ret)) + return ret; + + ret = simple_open(inode, file); + if (ret) + debugfs_file_put(file->f_path.dentry); + + return ret; +} + +static ssize_t sof_kernel_msg_inject_dfs_write(struct file *file, const char __user *buffer, + size_t count, loff_t *ppos) +{ + struct sof_client_dev *cdev = file->private_data; + struct sof_msg_inject_priv *priv = cdev->data; + struct sof_ipc_cmd_hdr *hdr = priv->kernel_buffer; + struct device *dev = &cdev->auxdev.dev; + ssize_t size; + int ret; + + if (*ppos) + return 0; + + size = simple_write_to_buffer(priv->kernel_buffer, priv->max_msg_size, + ppos, buffer, count); + if (size < 0) + return size; + if (size != count) + return -EFAULT; + + ret = pm_runtime_resume_and_get(dev); + if (ret < 0 && ret != -EACCES) { + dev_err_ratelimited(dev, "debugfs write failed to resume %d\n", ret); + return ret; + } + + sof_client_ipc_rx_message(cdev, hdr, priv->kernel_buffer); + + pm_runtime_mark_last_busy(dev); + ret = pm_runtime_put_autosuspend(dev); + if (ret < 0) + dev_err_ratelimited(dev, "debugfs write failed to idle %d\n", ret); + + return count; +}; + +static int sof_msg_inject_dfs_release(struct inode *inode, struct file *file) +{ + debugfs_file_put(file->f_path.dentry); + + return 0; +} + +static const struct file_operations sof_kernel_msg_inject_fops = { + .open = sof_msg_inject_dfs_open, + .write = sof_kernel_msg_inject_dfs_write, + .release = sof_msg_inject_dfs_release, + + .owner = THIS_MODULE, +}; + +static int sof_msg_inject_probe(struct auxiliary_device *auxdev, + const struct auxiliary_device_id *id) +{ + struct sof_client_dev *cdev = auxiliary_dev_to_sof_client_dev(auxdev); + struct dentry *debugfs_root = sof_client_get_debugfs_root(cdev); + struct device *dev = &auxdev->dev; + struct sof_msg_inject_priv *priv; + size_t alloc_size; + + /* allocate memory for client data */ + priv = devm_kzalloc(&auxdev->dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + priv->max_msg_size = sof_client_get_ipc_max_payload_size(cdev); + alloc_size = priv->max_msg_size; + priv->kernel_buffer = devm_kmalloc(dev, alloc_size, GFP_KERNEL); + + if (!priv->kernel_buffer) + return -ENOMEM; + + cdev->data = priv; + + priv->kernel_dfs_file = debugfs_create_file("kernel_ipc_msg_inject", 0644, + debugfs_root, cdev, + &sof_kernel_msg_inject_fops); + + /* enable runtime PM */ + pm_runtime_set_autosuspend_delay(dev, SOF_IPC_CLIENT_SUSPEND_DELAY_MS); + pm_runtime_use_autosuspend(dev); + pm_runtime_set_active(dev); + pm_runtime_enable(dev); + pm_runtime_mark_last_busy(dev); + pm_runtime_idle(dev); + + return 0; +} + +static void sof_msg_inject_remove(struct auxiliary_device *auxdev) +{ + struct sof_client_dev *cdev = auxiliary_dev_to_sof_client_dev(auxdev); + struct sof_msg_inject_priv *priv = cdev->data; + + pm_runtime_disable(&auxdev->dev); + + debugfs_remove(priv->kernel_dfs_file); +} + +static const struct auxiliary_device_id sof_msg_inject_client_id_table[] = { + { .name = "snd_sof.kernel_injector" }, + {}, +}; +MODULE_DEVICE_TABLE(auxiliary, sof_msg_inject_client_id_table); + +/* + * No need for driver pm_ops as the generic pm callbacks in the auxiliary bus + * type are enough to ensure that the parent SOF device resumes to bring the DSP + * back to D0. + * Driver name will be set based on KBUILD_MODNAME. + */ +static struct auxiliary_driver sof_msg_inject_client_drv = { + .probe = sof_msg_inject_probe, + .remove = sof_msg_inject_remove, + + .id_table = sof_msg_inject_client_id_table, +}; + +module_auxiliary_driver(sof_msg_inject_client_drv); + +MODULE_DESCRIPTION("SOF IPC Kernel Injector Client Driver"); +MODULE_LICENSE("GPL"); +MODULE_IMPORT_NS(SND_SOC_SOF_CLIENT); diff --git a/sound/soc/sof/sof-client.c b/sound/soc/sof/sof-client.c index d6b7caa0cf031..284de96e779c6 100644 --- a/sound/soc/sof/sof-client.c +++ b/sound/soc/sof/sof-client.c @@ -16,6 +16,7 @@ #include "ops.h" #include "sof-client.h" #include "sof-priv.h" +#include "ipc3-priv.h" #include "ipc4-priv.h" /** @@ -126,6 +127,29 @@ static inline int sof_register_ipc_msg_injector(struct snd_sof_dev *sdev) static inline void sof_unregister_ipc_msg_injector(struct snd_sof_dev *sdev) {} #endif /* CONFIG_SND_SOC_SOF_DEBUG_IPC_MSG_INJECTOR */ +#if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_IPC_KERNEL_INJECTOR) +static int sof_register_ipc_kernel_injector(struct snd_sof_dev *sdev) +{ + /* Only IPC3 supported right now */ + if (sdev->pdata->ipc_type != SOF_IPC) + return 0; + + return sof_client_dev_register(sdev, "kernel_injector", 0, NULL, 0); +} + +static void sof_unregister_ipc_kernel_injector(struct snd_sof_dev *sdev) +{ + sof_client_dev_unregister(sdev, "kernel_injector", 0); +} +#else +static inline int sof_register_ipc_kernel_injector(struct snd_sof_dev *sdev) +{ + return 0; +} + +static inline void sof_unregister_ipc_kernel_injector(struct snd_sof_dev *sdev) {} +#endif /* CONFIG_SND_SOC_SOF_DEBUG_IPC_KERNEL_INJECTOR */ + int sof_register_clients(struct snd_sof_dev *sdev) { int ret; @@ -146,6 +170,12 @@ int sof_register_clients(struct snd_sof_dev *sdev) goto err_msg_injector; } + ret = sof_register_ipc_kernel_injector(sdev); + if (ret) { + dev_err(sdev->dev, "IPC kernel injector client registration failed\n"); + goto err_kernel_injector; + } + /* Platform depndent client device registration */ if (sof_ops(sdev) && sof_ops(sdev)->register_ipc_clients) @@ -154,6 +184,9 @@ int sof_register_clients(struct snd_sof_dev *sdev) if (!ret) return 0; + sof_unregister_ipc_kernel_injector(sdev); + +err_kernel_injector: sof_unregister_ipc_msg_injector(sdev); err_msg_injector: @@ -167,6 +200,7 @@ void sof_unregister_clients(struct snd_sof_dev *sdev) if (sof_ops(sdev) && sof_ops(sdev)->unregister_ipc_clients) sof_ops(sdev)->unregister_ipc_clients(sdev); + sof_unregister_ipc_kernel_injector(sdev); sof_unregister_ipc_msg_injector(sdev); sof_unregister_ipc_flood_test(sdev); } @@ -269,6 +303,24 @@ int sof_client_ipc_tx_message(struct sof_client_dev *cdev, void *ipc_msg, } EXPORT_SYMBOL_NS_GPL(sof_client_ipc_tx_message, SND_SOC_SOF_CLIENT); +int sof_client_ipc_rx_message(struct sof_client_dev *cdev, void *ipc_msg, void *msg_buf) +{ + if (cdev->sdev->pdata->ipc_type == SOF_IPC) { + struct sof_ipc_cmd_hdr *hdr = ipc_msg; + + if (hdr->size < sizeof(hdr)) { + dev_err(cdev->sdev->dev, "The received message size is invalid\n"); + return -EINVAL; + } + + sof_ipc3_do_rx_work(cdev->sdev, ipc_msg, msg_buf); + return 0; + } + + return -EOPNOTSUPP; +} +EXPORT_SYMBOL_NS_GPL(sof_client_ipc_rx_message, SND_SOC_SOF_CLIENT); + int sof_client_ipc_set_get_data(struct sof_client_dev *cdev, void *ipc_msg, bool set) { diff --git a/sound/soc/sof/sof-client.h b/sound/soc/sof/sof-client.h index 10571d1ea9a77..b6ccc2cd69e52 100644 --- a/sound/soc/sof/sof-client.h +++ b/sound/soc/sof/sof-client.h @@ -75,5 +75,6 @@ int sof_client_register_fw_state_handler(struct sof_client_dev *cdev, sof_client_fw_state_callback callback); void sof_client_unregister_fw_state_handler(struct sof_client_dev *cdev); enum sof_fw_state sof_client_get_fw_state(struct sof_client_dev *cdev); +int sof_client_ipc_rx_message(struct sof_client_dev *cdev, void *ipc_msg, void *msg_buf); #endif /* __SOC_SOF_CLIENT_H */