optionrom: add a DMA-enabled multiboot ROM
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>
This commit is contained in:
parent
f014c97459
commit
48972f8cad
@ -63,6 +63,7 @@ blobs = files(
|
|||||||
'petalogix-s3adsp1800.dtb',
|
'petalogix-s3adsp1800.dtb',
|
||||||
'petalogix-ml605.dtb',
|
'petalogix-ml605.dtb',
|
||||||
'multiboot.bin',
|
'multiboot.bin',
|
||||||
|
'multiboot_dma.bin',
|
||||||
'linuxboot.bin',
|
'linuxboot.bin',
|
||||||
'linuxboot_dma.bin',
|
'linuxboot_dma.bin',
|
||||||
'kvmvapic.bin',
|
'kvmvapic.bin',
|
||||||
|
BIN
pc-bios/multiboot_dma.bin
Normal file
BIN
pc-bios/multiboot_dma.bin
Normal file
Binary file not shown.
@ -2,7 +2,7 @@ include config.mak
|
|||||||
SRC_DIR := $(TOPSRC_DIR)/pc-bios/optionrom
|
SRC_DIR := $(TOPSRC_DIR)/pc-bios/optionrom
|
||||||
VPATH = $(SRC_DIR)
|
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
|
# Dummy command so that make thinks it has done something
|
||||||
@true
|
@true
|
||||||
|
|
||||||
@ -41,8 +41,6 @@ override CFLAGS += $(call cc-option, $(Wa)-32)
|
|||||||
LD_I386_EMULATION ?= elf_i386
|
LD_I386_EMULATION ?= elf_i386
|
||||||
override LDFLAGS = -m $(LD_I386_EMULATION) -T $(SRC_DIR)/flat.lds
|
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
|
pvh.img: pvh.o pvh_main.o
|
||||||
|
|
||||||
%.o: %.S
|
%.o: %.S
|
||||||
|
@ -68,7 +68,7 @@ run_multiboot:
|
|||||||
mov %eax, %es
|
mov %eax, %es
|
||||||
|
|
||||||
/* Read the bootinfo struct into RAM */
|
/* Read the bootinfo struct into RAM */
|
||||||
read_fw_blob(FW_CFG_INITRD)
|
read_fw_blob_dma(FW_CFG_INITRD)
|
||||||
|
|
||||||
/* FS = bootinfo_struct */
|
/* FS = bootinfo_struct */
|
||||||
read_fw FW_CFG_INITRD_ADDR
|
read_fw FW_CFG_INITRD_ADDR
|
||||||
@ -188,7 +188,7 @@ prot_mode:
|
|||||||
movl %eax, %gs
|
movl %eax, %gs
|
||||||
|
|
||||||
/* Read the kernel and modules into RAM */
|
/* 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 */
|
/* Jump off to the kernel */
|
||||||
read_fw FW_CFG_KERNEL_ENTRY
|
read_fw FW_CFG_KERNEL_ENTRY
|
||||||
|
2
pc-bios/optionrom/multiboot_dma.S
Normal file
2
pc-bios/optionrom/multiboot_dma.S
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
#define USE_FW_CFG_DMA 1
|
||||||
|
#include "multiboot.S"
|
@ -37,6 +37,17 @@
|
|||||||
#define BIOS_CFG_IOPORT_CFG 0x510
|
#define BIOS_CFG_IOPORT_CFG 0x510
|
||||||
#define BIOS_CFG_IOPORT_DATA 0x511
|
#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 */
|
/* Break the translation block flow so -d cpu shows us values */
|
||||||
#define DEBUG_HERE \
|
#define DEBUG_HERE \
|
||||||
jmp 1f; \
|
jmp 1f; \
|
||||||
@ -62,6 +73,61 @@
|
|||||||
bswap %eax
|
bswap %eax
|
||||||
.endm
|
.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) \
|
#define read_fw_blob_pre(var) \
|
||||||
read_fw var ## _SIZE; \
|
read_fw var ## _SIZE; \
|
||||||
mov %eax, %ecx; \
|
mov %eax, %ecx; \
|
||||||
|
Loading…
x
Reference in New Issue
Block a user