From patchwork Wed Oct 28 17:20:34 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: "Gabriel L. Somlo" X-Patchwork-Id: 537493 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id A0BC1141351 for ; Thu, 29 Oct 2015 04:23:31 +1100 (AEDT) Received: from localhost ([::1]:39596 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ZrURd-0006Tt-6A for incoming@patchwork.ozlabs.org; Wed, 28 Oct 2015 13:23:29 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:50786) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ZrUOy-0001sw-BD for qemu-devel@nongnu.org; Wed, 28 Oct 2015 13:20:45 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ZrUOu-0000zM-5Z for qemu-devel@nongnu.org; Wed, 28 Oct 2015 13:20:44 -0400 Received: from relay-05.andrew.cmu.edu ([128.2.157.12]:44027 helo=relay.andrew.cmu.edu) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ZrUOt-0000z2-Mc for qemu-devel@nongnu.org; Wed, 28 Oct 2015 13:20:40 -0400 Received: from HEDWIG.ini.cmu.edu (HEDWIG.INI.CMU.EDU [128.2.16.51]) by relay.andrew.cmu.edu (8.14.7/8.14.7) with ESMTP id t9SHKbiS025045; Wed, 28 Oct 2015 13:20:37 -0400 From: "Gabriel L. Somlo" To: qemu-devel@nongnu.org Date: Wed, 28 Oct 2015 13:20:34 -0400 Message-Id: <1446052836-31737-3-git-send-email-somlo@cmu.edu> X-Mailer: git-send-email 2.4.3 In-Reply-To: <1446052836-31737-1-git-send-email-somlo@cmu.edu> References: <1446052836-31737-1-git-send-email-somlo@cmu.edu> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.74 on 128.2.157.12 X-MIME-Autoconverted: from 8bit to quoted-printable by relay.andrew.cmu.edu id t9SHKbiS025045 X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.4.x X-Received-From: 128.2.157.12 Cc: peter.maydell@linaro.org, jordan.l.justen@intel.com, kraxel@redhat.com, pbonzini@redhat.com, markmb@redhat.com, lersek@redhat.com Subject: [Qemu-devel] [PATCH v2 2/4] fw_cfg: amend callback behavior spec to once per select X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Currently, the fw_cfg internal API specifies that if an item was set up with a read callback, the callback must be run each time a byte is read from the item. This behavior is both wasteful (most items do not have a read callback set), and impractical for bulk transfers (e.g., DMA read). At the time of this writing, the only items configured with a callback are "/etc/table-loader", "/etc/acpi/tables", and "/etc/acpi/rsdp". They all share the same callback functions: virt_acpi_build_update() on arm (in hw/arm/virt-acpi-build.c), and acpi_build_update() on i386 (in hw/i386/acpi.c). Both of these callbacks are one-shot (i.e. they return without doing anything at all after the first time they are called on each distinct item). This patch amends the specification for fw_cfg_add_file_callback() to state that any available read callback will only be invoked once each time the item is selected. This change has no practical effect on the current behavior of QEMU, and it enables us to significantly optimize the behavior of fw_cfg reads during guest firmware setup, eliminating a large amount of redundant callback checks and invocations. Cc: Laszlo Ersek Cc: Gerd Hoffmann Cc: Marc MarĂ­ Signed-off-by: Gabriel Somlo --- hw/nvram/fw_cfg.c | 16 ++++++++-------- include/hw/nvram/fw_cfg.h | 8 ++------ 2 files changed, 10 insertions(+), 14 deletions(-) diff --git a/hw/nvram/fw_cfg.c b/hw/nvram/fw_cfg.c index 73b0a81..31fa5c8 100644 --- a/hw/nvram/fw_cfg.c +++ b/hw/nvram/fw_cfg.c @@ -252,7 +252,8 @@ static void fw_cfg_write(FWCfgState *s, uint8_t value) static int fw_cfg_select(FWCfgState *s, uint16_t key) { - int ret; + int arch, ret; + FWCfgEntry *e; s->cur_offset = 0; if ((key & FW_CFG_ENTRY_MASK) >= FW_CFG_MAX_ENTRY) { @@ -261,6 +262,12 @@ static int fw_cfg_select(FWCfgState *s, uint16_t key) } else { s->cur_entry = key; ret = 1; + /* entry successfully selected, now run callback if present */ + arch = !!(key & FW_CFG_ARCH_LOCAL); + e = &s->entries[arch][key & FW_CFG_ENTRY_MASK]; + if (e->read_callback) { + e->read_callback(e->callback_opaque, s->cur_offset); + } } trace_fw_cfg_select(s, key, ret); @@ -276,9 +283,6 @@ static uint8_t fw_cfg_read(FWCfgState *s) if (s->cur_entry == FW_CFG_INVALID || !e->data || s->cur_offset >= e->len) ret = 0; else { - if (e->read_callback) { - e->read_callback(e->callback_opaque, s->cur_offset); - } ret = e->data[s->cur_offset++]; } @@ -371,10 +375,6 @@ static void fw_cfg_dma_transfer(FWCfgState *s) len = (e->len - s->cur_offset); } - if (e->read_callback) { - e->read_callback(e->callback_opaque, s->cur_offset); - } - /* If the access is not a read access, it will be a skip access, * tested before. */ diff --git a/include/hw/nvram/fw_cfg.h b/include/hw/nvram/fw_cfg.h index 422e2e9..47ff118 100644 --- a/include/hw/nvram/fw_cfg.h +++ b/include/hw/nvram/fw_cfg.h @@ -183,12 +183,8 @@ void fw_cfg_add_file(FWCfgState *s, const char *filename, void *data, * structure residing at key value FW_CFG_FILE_DIR, containing the item name, * data size, and assigned selector key value. * Additionally, set a callback function (and argument) to be called each - * time a byte is read by the guest from this particular item, or once per - * each DMA guest read operation. - * NOTE: In addition to the opaque argument set here, the callback function - * takes the current data offset as an additional argument, allowing it the - * option of only acting upon specific offset values (e.g., 0, before the - * first data byte of the selected item is returned to the guest). + * time this item is selected (by having its selector key written to the + * fw_cfg control register). */ void fw_cfg_add_file_callback(FWCfgState *s, const char *filename, FWCfgReadCallback callback, void *callback_opaque,