From nobody Fri Nov 7 15:32:27 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=redhat.com Return-Path: Received: from lists.gnu.org (209.51.188.17 [209.51.188.17]) by mx.zohomail.com with SMTPS id 1548205478567910.0432822062636; Tue, 22 Jan 2019 17:04:38 -0800 (PST) Received: from localhost ([127.0.0.1]:53117 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gm6xx-0008NS-FC for importer@patchew.org; Tue, 22 Jan 2019 20:04:29 -0500 Received: from eggs.gnu.org ([209.51.188.92]:50736) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gm6vk-0007Bu-CI for qemu-devel@nongnu.org; Tue, 22 Jan 2019 20:02:14 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1gm6vh-0002T3-JR for qemu-devel@nongnu.org; Tue, 22 Jan 2019 20:02:12 -0500 Received: from mail-wm1-x32e.google.com ([2a00:1450:4864:20::32e]:35706) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1gm6vh-0002Nb-AX for qemu-devel@nongnu.org; Tue, 22 Jan 2019 20:02:09 -0500 Received: by mail-wm1-x32e.google.com with SMTP id t200so403643wmt.0 for ; Tue, 22 Jan 2019 17:02:06 -0800 (PST) Received: from 640k.lan ([93.56.166.5]) by smtp.gmail.com with ESMTPSA id e17sm155062376wri.36.2019.01.22.17.02.03 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 22 Jan 2019 17:02:03 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=sender:from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=QirMGIyyJ8mPyffeQaMAhYCCUiHPI3baaFNQ4whC7Y4=; b=YQ3hqgCoo/8xDDLuWW/2EHFQRdbdYxSPW4/K8VIK9ckqhmYWpnMYSvwicj6bIFkksq ciF3kCVviyFUn6IlcROBVDDaREz1u0d/e3xbox8npkODmmMgN4Y8q6gOnfdTvSBq8ZHa auWheOk0lG46PDdshWI5PJMksBkDWXpD2QCm4kxUBYKq0N8blwBmC7zncpbjdfnxCgsg GHY3bFXu1gPlbXQQ6c2riORTkfOHrkCa/EiuMHMXb4DS95gjadmV+rNxjp9T9zmpf+ne o7XvtRZWbBcuIrZPVwlZ8iZMLa+7upX6CmLF51tFYR4Gmlld4Cru2v5JVW0oalsSkmYn wgAA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:from:to:cc:subject:date:message-id :in-reply-to:references:mime-version:content-transfer-encoding; bh=QirMGIyyJ8mPyffeQaMAhYCCUiHPI3baaFNQ4whC7Y4=; b=cL94qkjmijlDrWqQMw1Z8azDwnnFQHiCd3ncVZW72LYAw38CZu3mqaTlklazfNTQ5j mjA9g2cRw7E1pmPcq8gjlcJYtXlS2R+Cy8PciCzhl5Gny+riP0ckqJr7K2wMW9f1d1Zd UtOa1JM5PsweuJwotV/GBf/NhzGCW/h1Ugjoc4E0LRNGdoKAmrkrIlBQd7vblAIgya3k hvn2UB6uarp0sAK8J2CQM9YKxHvyAF2jbc5Tz/hD01+idXjO1d30J/xQt3WakB6YOhSO 7s7ZUP3KQ6pkuNc7wzT1zz4FE6grQ4/TeI/VFvvHdRib4lX6Sc2YgXrR18/sEpaVjtC5 U4ZQ== X-Gm-Message-State: AJcUukfc6Jwd7R0gHNBN3XrrIiNEM/CHKpDxEuxIWql7srgNuD+T98yf 32zR3VXkqkx5ziYUVLW6pQFis9ja X-Google-Smtp-Source: ALg8bN4QAbCeY7hTey6rkmo6t4be/UB4DyE/ojoxuPwa0Gr5USxIpfFhEY3KrABgyhWEsZqfexArkA== X-Received: by 2002:a1c:7409:: with SMTP id p9mr606096wmc.136.1548205325321; Tue, 22 Jan 2019 17:02:05 -0800 (PST) From: Paolo Bonzini To: qemu-devel@nongnu.org Date: Wed, 23 Jan 2019 02:02:00 +0100 Message-Id: <1548205322-36101-2-git-send-email-pbonzini@redhat.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1548205322-36101-1-git-send-email-pbonzini@redhat.com> References: <1548205322-36101-1-git-send-email-pbonzini@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2a00:1450:4864:20::32e Subject: [Qemu-devel] [PULL 29/51] linuxboot_dma: move common functions in a new header X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Stefano Garzarella Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: fail (Header signature does not verify) From: Stefano Garzarella In order to allow other option roms to use these common useful functions and definitions, this patch put them in two new C header files called optrom.h and optrom_fw_cfg.h. We also add useful out*() in*() functions for different size, and new fw_cfg functions to use when DMA feature is not available. Signed-off-by: Stefano Garzarella Reviewed-by: Stefan Hajnoczi Reviewed-by: Liam Merwick --- pc-bios/optionrom/linuxboot_dma.c | 102 +++++++---------------------------- pc-bios/optionrom/optrom.h | 110 ++++++++++++++++++++++++++++++++++= ++++ pc-bios/optionrom/optrom_fw_cfg.h | 92 +++++++++++++++++++++++++++++++ 3 files changed, 221 insertions(+), 83 deletions(-) create mode 100644 pc-bios/optionrom/optrom.h create mode 100644 pc-bios/optionrom/optrom_fw_cfg.h diff --git a/pc-bios/optionrom/linuxboot_dma.c b/pc-bios/optionrom/linuxboo= t_dma.c index f728dc8..cbcf667 100644 --- a/pc-bios/optionrom/linuxboot_dma.c +++ b/pc-bios/optionrom/linuxboot_dma.c @@ -58,21 +58,13 @@ asm( " jmp load_kernel\n" ); =20 -#define BIOS_CFG_DMA_ADDR_HIGH 0x514 -#define BIOS_CFG_DMA_ADDR_LOW 0x518 - -#define uint64_t unsigned long long -#define uint32_t unsigned int -#define uint16_t unsigned short - -#include "../../include/standard-headers/linux/qemu_fw_cfg.h" - -#define barrier() asm("" : : : "memory") - -static inline void outl(uint32_t value, uint16_t port) -{ - asm("outl %0, %w1" : : "a"(value), "Nd"(port)); -} +/* + * The includes of C headers must be after the asm block to avoid compiler + * errors. + */ +#include +#include "optrom.h" +#include "optrom_fw_cfg.h" =20 static inline void set_es(void *addr) { @@ -80,12 +72,6 @@ static inline void set_es(void *addr) asm("movl %0, %%es" : : "r"(seg)); } =20 -#ifdef __clang__ -#define ADDR32 -#else -#define ADDR32 "addr32 " -#endif - static inline uint16_t readw_es(uint16_t offset) { uint16_t val; @@ -108,56 +94,6 @@ static inline void writel_es(uint16_t offset, uint32_t = val) asm(ADDR32 "movl %0, %%es:(%1)" : : "r"(val), "r"((uint32_t)offset)); } =20 -static inline uint32_t bswap32(uint32_t x) -{ - asm("bswapl %0" : "=3Dr" (x) : "0" (x)); - return x; -} - -static inline uint64_t bswap64(uint64_t x) -{ - asm("bswapl %%eax; bswapl %%edx; xchg %%eax, %%edx" : "=3DA" (x) : "0"= (x)); - return x; -} - -static inline uint64_t cpu_to_be64(uint64_t x) -{ - return bswap64(x); -} - -static inline uint32_t cpu_to_be32(uint32_t x) -{ - return bswap32(x); -} - -static inline uint32_t be32_to_cpu(uint32_t x) -{ - return bswap32(x); -} - -/* clang is happy to inline this function, and bloats the - * ROM. - */ -static __attribute__((__noinline__)) -void bios_cfg_read_entry(void *buf, uint16_t entry, uint32_t len) -{ - struct fw_cfg_dma_access access; - uint32_t control =3D (entry << 16) | FW_CFG_DMA_CTL_SELECT - | FW_CFG_DMA_CTL_READ; - - access.address =3D cpu_to_be64((uint64_t)(uint32_t)buf); - access.length =3D cpu_to_be32(len); - access.control =3D cpu_to_be32(control); - - barrier(); - - outl(cpu_to_be32((uint32_t)&access), BIOS_CFG_DMA_ADDR_LOW); - - while (be32_to_cpu(access.control) & ~FW_CFG_DMA_CTL_ERROR) { - barrier(); - } -} - /* Return top of memory using BIOS function E801. */ static uint32_t get_e801_addr(void) { @@ -211,9 +147,9 @@ void load_kernel(void) uint32_t initrd_end_page, max_allowed_page; uint32_t segment_addr, stack_addr; =20 - bios_cfg_read_entry(&setup_addr, FW_CFG_SETUP_ADDR, 4); - bios_cfg_read_entry(&setup_size, FW_CFG_SETUP_SIZE, 4); - bios_cfg_read_entry(setup_addr, FW_CFG_SETUP_DATA, setup_size); + bios_cfg_read_entry_dma(&setup_addr, FW_CFG_SETUP_ADDR, 4); + bios_cfg_read_entry_dma(&setup_size, FW_CFG_SETUP_SIZE, 4); + bios_cfg_read_entry_dma(setup_addr, FW_CFG_SETUP_DATA, setup_size); =20 set_es(setup_addr); =20 @@ -223,8 +159,8 @@ void load_kernel(void) writel_es(0x22c, 0x37ffffff); } =20 - bios_cfg_read_entry(&initrd_addr, FW_CFG_INITRD_ADDR, 4); - bios_cfg_read_entry(&initrd_size, FW_CFG_INITRD_SIZE, 4); + bios_cfg_read_entry_dma(&initrd_addr, FW_CFG_INITRD_ADDR, 4); + bios_cfg_read_entry_dma(&initrd_size, FW_CFG_INITRD_SIZE, 4); =20 initrd_end_page =3D ((uint32_t)(initrd_addr + initrd_size) & -4096); max_allowed_page =3D (readl_es(0x22c) & -4096); @@ -239,15 +175,15 @@ void load_kernel(void) =20 } =20 - bios_cfg_read_entry(initrd_addr, FW_CFG_INITRD_DATA, initrd_size); + bios_cfg_read_entry_dma(initrd_addr, FW_CFG_INITRD_DATA, initrd_size); =20 - bios_cfg_read_entry(&kernel_addr, FW_CFG_KERNEL_ADDR, 4); - bios_cfg_read_entry(&kernel_size, FW_CFG_KERNEL_SIZE, 4); - bios_cfg_read_entry(kernel_addr, FW_CFG_KERNEL_DATA, kernel_size); + bios_cfg_read_entry_dma(&kernel_addr, FW_CFG_KERNEL_ADDR, 4); + bios_cfg_read_entry_dma(&kernel_size, FW_CFG_KERNEL_SIZE, 4); + bios_cfg_read_entry_dma(kernel_addr, FW_CFG_KERNEL_DATA, kernel_size); =20 - bios_cfg_read_entry(&cmdline_addr, FW_CFG_CMDLINE_ADDR, 4); - bios_cfg_read_entry(&cmdline_size, FW_CFG_CMDLINE_SIZE, 4); - bios_cfg_read_entry(cmdline_addr, FW_CFG_CMDLINE_DATA, cmdline_size); + bios_cfg_read_entry_dma(&cmdline_addr, FW_CFG_CMDLINE_ADDR, 4); + bios_cfg_read_entry_dma(&cmdline_size, FW_CFG_CMDLINE_SIZE, 4); + bios_cfg_read_entry_dma(cmdline_addr, FW_CFG_CMDLINE_DATA, cmdline_siz= e); =20 /* Boot linux */ segment_addr =3D ((uint32_t)setup_addr >> 4); diff --git a/pc-bios/optionrom/optrom.h b/pc-bios/optionrom/optrom.h new file mode 100644 index 0000000..3578192 --- /dev/null +++ b/pc-bios/optionrom/optrom.h @@ -0,0 +1,110 @@ +/* + * Common Option ROM Functions for C code + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + * + * Copyright (c) 2015-2019 Red Hat Inc. + * Authors: + * Marc Mar=C3=AD + * Richard W.M. Jones + * Stefano Garzarella + */ + +#ifndef OPTROM_H +#define OPTROM_H + +#include +#include "../../include/standard-headers/linux/qemu_fw_cfg.h" + +#define barrier() asm("" : : : "memory") + +#ifdef __clang__ +#define ADDR32 +#else +#define ADDR32 "addr32 " +#endif + +static inline void outb(uint8_t value, uint16_t port) +{ + asm volatile("outb %0, %w1" : : "a"(value), "Nd"(port)); +} + +static inline void outw(uint16_t value, uint16_t port) +{ + asm volatile("outw %0, %w1" : : "a"(value), "Nd"(port)); +} + +static inline void outl(uint32_t value, uint16_t port) +{ + asm volatile("outl %0, %w1" : : "a"(value), "Nd"(port)); +} + +static inline uint8_t inb(uint16_t port) +{ + uint8_t value; + + asm volatile("inb %w1, %0" : "=3Da"(value) : "Nd"(port)); + return value; +} + +static inline uint16_t inw(uint16_t port) +{ + uint16_t value; + + asm volatile("inw %w1, %0" : "=3Da"(value) : "Nd"(port)); + return value; +} + +static inline uint32_t inl(uint16_t port) +{ + uint32_t value; + + asm volatile("inl %w1, %0" : "=3Da"(value) : "Nd"(port)); + return value; +} + +static inline void insb(uint16_t port, uint8_t *buf, uint32_t len) +{ + asm volatile("rep insb %%dx, %%es:(%%edi)" + : "+c"(len), "+D"(buf) : "d"(port) : "memory"); +} + +static inline uint32_t bswap32(uint32_t x) +{ + asm("bswapl %0" : "=3Dr" (x) : "0" (x)); + return x; +} + +static inline uint64_t bswap64(uint64_t x) +{ + asm("bswapl %%eax; bswapl %%edx; xchg %%eax, %%edx" : "=3DA" (x) : "0"= (x)); + return x; +} + +static inline uint64_t cpu_to_be64(uint64_t x) +{ + return bswap64(x); +} + +static inline uint32_t cpu_to_be32(uint32_t x) +{ + return bswap32(x); +} + +static inline uint32_t be32_to_cpu(uint32_t x) +{ + return bswap32(x); +} + +#endif /* OPTROM_H */ diff --git a/pc-bios/optionrom/optrom_fw_cfg.h b/pc-bios/optionrom/optrom_f= w_cfg.h new file mode 100644 index 0000000..a3660a5 --- /dev/null +++ b/pc-bios/optionrom/optrom_fw_cfg.h @@ -0,0 +1,92 @@ +/* + * Common Option ROM Functions for fw_cfg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + * + * Copyright (c) 2015-2019 Red Hat Inc. + * Authors: + * Marc Mar=C3=AD + * Richard W.M. Jones + * Stefano Garzarella + */ + +#ifndef OPTROM_FW_CFG_H +#define OPTROM_FW_CFG_H + +#include "../../include/standard-headers/linux/qemu_fw_cfg.h" + +#define BIOS_CFG_IOPORT_CFG 0x510 +#define BIOS_CFG_IOPORT_DATA 0x511 +#define BIOS_CFG_DMA_ADDR_HIGH 0x514 +#define BIOS_CFG_DMA_ADDR_LOW 0x518 + +static __attribute__((unused)) +void bios_cfg_select(uint16_t key) +{ + outw(key, BIOS_CFG_IOPORT_CFG); +} + +static __attribute__((unused)) +void bios_cfg_read_entry_io(void *buf, uint16_t entry, uint32_t len) +{ + bios_cfg_select(entry); + insb(BIOS_CFG_IOPORT_DATA, buf, len); +} + +/* + * clang is happy to inline this function, and bloats the + * ROM. + */ +static __attribute__((__noinline__)) __attribute__((unused)) +void bios_cfg_read_entry_dma(void *buf, uint16_t entry, uint32_t len) +{ + struct fw_cfg_dma_access access; + uint32_t control =3D (entry << 16) | FW_CFG_DMA_CTL_SELECT + | FW_CFG_DMA_CTL_READ; + + access.address =3D cpu_to_be64((uint64_t)(uint32_t)buf); + access.length =3D cpu_to_be32(len); + access.control =3D cpu_to_be32(control); + + barrier(); + + outl(cpu_to_be32((uint32_t)&access), BIOS_CFG_DMA_ADDR_LOW); + + while (be32_to_cpu(access.control) & ~FW_CFG_DMA_CTL_ERROR) { + barrier(); + } +} + +static __attribute__((unused)) +void bios_cfg_read_entry(void *buf, uint16_t entry, uint32_t len, + uint32_t version) +{ + if (version & FW_CFG_VERSION_DMA) { + bios_cfg_read_entry_dma(buf, entry, len); + } else { + bios_cfg_read_entry_io(buf, entry, len); + } +} + +static __attribute__((unused)) +uint32_t bios_cfg_version(void) +{ + uint32_t version; + + bios_cfg_read_entry_io(&version, FW_CFG_ID, sizeof(version)); + + return version; +} + +#endif /* OPTROM_FW_CFG_H */ --=20 1.8.3.1