From: Paolo Bonzini <pbonzini@redhat.com>
To: qemu-devel@nongnu.org
Cc: adam@l4re.org, marcus.haehnel@kernkonzept.com
Subject: [PATCH 2/3] optionrom: add a DMA-enabled multiboot ROM
Date: Wed, 20 Oct 2021 16:02:43 +0200 [thread overview]
Message-ID: <20211020140244.485249-3-pbonzini@redhat.com> (raw)
In-Reply-To: <20211020140244.485249-1-pbonzini@redhat.com>
From: Marcus Hähnel <marcus.haehnel@kernkonzept.com>
Add a new option rom for the multiboot loader, using DMA transfers to copy
data instead of "rep insb".
This significantly lowers QEMU's startup latency by a factor of about 40,
for example, going from 30sec to 0.8sec when loading modules of 120MB
in size.
Signed-off-by: Marcus Hähnel <marcus.haehnel@kernkonzept.com>
Signed-off-by: Adam Lackorzynski <adam@l4re.org>
[Modified to keep the non-DMA code depending on #ifdef USE_FW_CFG_DMA;
do not write below stack. - Paolo]
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
pc-bios/meson.build | 1 +
pc-bios/multiboot_dma.bin | Bin 0 -> 1024 bytes
pc-bios/optionrom/Makefile | 4 +-
pc-bios/optionrom/multiboot.S | 4 +-
pc-bios/optionrom/multiboot_dma.S | 2 +
pc-bios/optionrom/optionrom.h | 66 ++++++++++++++++++++++++++++++
6 files changed, 72 insertions(+), 5 deletions(-)
create mode 100644 pc-bios/multiboot_dma.bin
create mode 100644 pc-bios/optionrom/multiboot_dma.S
diff --git a/pc-bios/meson.build b/pc-bios/meson.build
index a44c9bc127..b40ff3f2bd 100644
--- a/pc-bios/meson.build
+++ b/pc-bios/meson.build
@@ -63,6 +63,7 @@ blobs = files(
'petalogix-s3adsp1800.dtb',
'petalogix-ml605.dtb',
'multiboot.bin',
+ 'multiboot_dma.bin',
'linuxboot.bin',
'linuxboot_dma.bin',
'kvmvapic.bin',
diff --git a/pc-bios/multiboot_dma.bin b/pc-bios/multiboot_dma.bin
new file mode 100644
index 0000000000000000000000000000000000000000..c0e2c3102a3358207c61d3ae113524fb6007abc3
GIT binary patch
literal 1024
zcmd^-v1=1i9LIlmUTlcNU1}{N5`u&{DAHSmq6iKdix;GHRxaNnR0A<Lc978Fk#IvN
zaS+5wQE+fL&*iQWa#czc94ZyL>R{3q;@~8~^LMo;4s!p158nI!-tWur_ul*P<{!&%
z=%3>xm5f`4Bq!!)`Rkwf;(oFd*qcAb=mhXX1)X>Bw-tylkUpR_ETXkH1AnO4L$nJ|
zWJui_M1kmKmTID)P`mI^=HM`~{VB1t1l_Ye=Lor4X5{8Gd)zzw_o4<6zLQJ!dr<pW
z;7%~ysSHL?*HHx*O%k}?fCyRL<7_RWt(4;Aqn}X}S>MolrKNZG2Z|kTOyaJIhYFc^
zFhhuQ9`r5fQLCrm#T4^_QylQ>8kgs;ZX9bIEiXb`8AIxu;?h~d%9izBkKht%WM1G*
z^E{W9(OT9dt5in2qF}|dPH>dL>{=sV#-U1<quUb@YkIW%niI?8-7fCz#695e<V=WZ
zrVCY?W~`3Hw@^=cHALr#9F2GOTYJ;??9d*-Vbsi+;lz|<$jMX#;lr6ov3qKNLH7(W
z+>yFoWnOtw14D$&k*SUtsT%wS`ki@#&rUrnmtuDv`PtJm(Kg?H$Pdc0CL@YCy4R<D
pT|LnIbg(BnP0#tqRx5M!bkkaD-nd?`H;YU4Yi6yHwD{k({tHC8FAx9#
literal 0
HcmV?d00001
diff --git a/pc-bios/optionrom/Makefile b/pc-bios/optionrom/Makefile
index 3482508a86..5d55d25acc 100644
--- a/pc-bios/optionrom/Makefile
+++ b/pc-bios/optionrom/Makefile
@@ -2,7 +2,7 @@ include config.mak
SRC_DIR := $(TOPSRC_DIR)/pc-bios/optionrom
VPATH = $(SRC_DIR)
-all: multiboot.bin linuxboot.bin linuxboot_dma.bin kvmvapic.bin pvh.bin
+all: multiboot.bin multiboot_dma.bin linuxboot.bin linuxboot_dma.bin kvmvapic.bin pvh.bin
# Dummy command so that make thinks it has done something
@true
@@ -41,8 +41,6 @@ override CFLAGS += $(call cc-option, $(Wa)-32)
LD_I386_EMULATION ?= elf_i386
override LDFLAGS = -m $(LD_I386_EMULATION) -T $(SRC_DIR)/flat.lds
-all: multiboot.bin linuxboot.bin linuxboot_dma.bin kvmvapic.bin pvh.bin
-
pvh.img: pvh.o pvh_main.o
%.o: %.S
diff --git a/pc-bios/optionrom/multiboot.S b/pc-bios/optionrom/multiboot.S
index b7efe4de34..181a4b03a3 100644
--- a/pc-bios/optionrom/multiboot.S
+++ b/pc-bios/optionrom/multiboot.S
@@ -68,7 +68,7 @@ run_multiboot:
mov %eax, %es
/* Read the bootinfo struct into RAM */
- read_fw_blob(FW_CFG_INITRD)
+ read_fw_blob_dma(FW_CFG_INITRD)
/* FS = bootinfo_struct */
read_fw FW_CFG_INITRD_ADDR
@@ -188,7 +188,7 @@ prot_mode:
movl %eax, %gs
/* Read the kernel and modules into RAM */
- read_fw_blob(FW_CFG_KERNEL)
+ read_fw_blob_dma(FW_CFG_KERNEL)
/* Jump off to the kernel */
read_fw FW_CFG_KERNEL_ENTRY
diff --git a/pc-bios/optionrom/multiboot_dma.S b/pc-bios/optionrom/multiboot_dma.S
new file mode 100644
index 0000000000..d809af3e23
--- /dev/null
+++ b/pc-bios/optionrom/multiboot_dma.S
@@ -0,0 +1,2 @@
+#define USE_FW_CFG_DMA 1
+#include "multiboot.S"
diff --git a/pc-bios/optionrom/optionrom.h b/pc-bios/optionrom/optionrom.h
index a2b612f1a7..8d74c0ddf3 100644
--- a/pc-bios/optionrom/optionrom.h
+++ b/pc-bios/optionrom/optionrom.h
@@ -37,6 +37,17 @@
#define BIOS_CFG_IOPORT_CFG 0x510
#define BIOS_CFG_IOPORT_DATA 0x511
+#define FW_CFG_DMA_CTL_ERROR 0x01
+#define FW_CFG_DMA_CTL_READ 0x02
+#define FW_CFG_DMA_CTL_SKIP 0x04
+#define FW_CFG_DMA_CTL_SELECT 0x08
+#define FW_CFG_DMA_CTL_WRITE 0x10
+
+#define FW_CFG_DMA_SIGNATURE 0x51454d5520434647ULL /* "QEMU CFG" */
+
+#define BIOS_CFG_DMA_ADDR_HIGH 0x514
+#define BIOS_CFG_DMA_ADDR_LOW 0x518
+
/* Break the translation block flow so -d cpu shows us values */
#define DEBUG_HERE \
jmp 1f; \
@@ -62,6 +73,61 @@
bswap %eax
.endm
+
+/*
+ * Read data from the fw_cfg device using DMA.
+ * Clobbers: %edx, %eax, ADDR, SIZE, memory[%esp-16] to memory[%esp]
+ */
+.macro read_fw_dma VAR, SIZE, ADDR
+ /* Address */
+ bswapl \ADDR
+ pushl \ADDR
+
+ /* We only support 32 bit target addresses */
+ xorl %eax, %eax
+ pushl %eax
+ mov $BIOS_CFG_DMA_ADDR_HIGH, %dx
+ outl %eax, (%dx)
+
+ /* Size */
+ bswapl \SIZE
+ pushl \SIZE
+
+ /* Control */
+ movl $(\VAR << 16) | (FW_CFG_DMA_CTL_READ | FW_CFG_DMA_CTL_SELECT), %eax
+ bswapl %eax
+ pushl %eax
+
+ movl %esp, %eax /* Address of the struct we generated */
+ bswapl %eax
+ mov $BIOS_CFG_DMA_ADDR_LOW, %dx
+ outl %eax, (%dx) /* Initiate DMA */
+
+1: mov (%esp), %eax /* Wait for completion */
+ bswapl %eax
+ testl $~FW_CFG_DMA_CTL_ERROR, %eax
+ jnz 1b
+ addl $16, %esp
+.endm
+
+
+/*
+ * Read a blob from the fw_cfg device using DMA
+ * Requires _ADDR, _SIZE and _DATA values for the parameter.
+ *
+ * Clobbers: %eax, %edx, %es, %ecx, %edi and adresses %esp-20 to %esp
+ */
+#ifdef USE_FW_CFG_DMA
+#define read_fw_blob_dma(var) \
+ read_fw var ## _SIZE; \
+ mov %eax, %ecx; \
+ read_fw var ## _ADDR; \
+ mov %eax, %edi ;\
+ read_fw_dma var ## _DATA, %ecx, %edi
+#else
+#define read_fw_blob_dma(var) read_fw_blob(var)
+#endif
+
#define read_fw_blob_pre(var) \
read_fw var ## _SIZE; \
mov %eax, %ecx; \
--
2.31.1
next prev parent reply other threads:[~2021-10-20 14:11 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-10-20 14:02 [PATCH v2 0/3] multiboot: Use DMA instead port-based transfer Paolo Bonzini
2021-10-20 14:02 ` [PATCH 1/3] target/i386: move linuxboot_dma_enabled to X86MachineState Paolo Bonzini
2021-10-20 19:13 ` Philippe Mathieu-Daudé
2021-10-20 14:02 ` Paolo Bonzini [this message]
2021-10-20 22:08 ` [PATCH 2/3] optionrom: add a DMA-enabled multiboot ROM Philippe Mathieu-Daudé
2021-10-20 14:02 ` [PATCH 3/3] target/i386: use DMA-enabled multiboot ROM for new-enough QEMU machine types Paolo Bonzini
2021-10-20 19:19 ` Philippe Mathieu-Daudé
2021-10-21 7:23 ` [PATCH v2 0/3] multiboot: Use DMA instead port-based transfer Stefano Garzarella
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20211020140244.485249-3-pbonzini@redhat.com \
--to=pbonzini@redhat.com \
--cc=adam@l4re.org \
--cc=marcus.haehnel@kernkonzept.com \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.