mirror of
https://github.com/clearlinux/kvmtool.git
synced 2026-09-06 05:31:50 +00:00
kvm, bios: BIOS code redesign
Instead of keeping bios code in various bin junks make it to host in one binary blob. This blob gets copied to a predefined place at startup and IVT handlers set as appropriate. Also we need to generate header file which will contain BIOS tourine offsets for symbols being used. Signed-off-by: Cyrill Gorcunov <gorcunov@gmail.com>
This commit is contained in:
committed by
Will Deacon
parent
307a9af02d
commit
28ce0d664b
@@ -18,9 +18,7 @@ OBJS += main.o
|
||||
OBJS += mmio.o
|
||||
OBJS += util.o
|
||||
OBJS += bios.o
|
||||
OBJS += bios/intfake.o
|
||||
OBJS += bios/int10.o
|
||||
OBJS += bios/int15.o
|
||||
OBJS += bios/bios.o
|
||||
|
||||
uname_M := $(shell uname -m | sed -e s/i.86/i386/)
|
||||
ifeq ($(uname_M),i386)
|
||||
@@ -69,34 +67,22 @@ $(OBJS):
|
||||
BIOS_CFLAGS += -m32
|
||||
BIOS_CFLAGS += -march=i386
|
||||
BIOS_CFLAGS += -mregparm=3
|
||||
bios/intfake.o: bios/intfake.S bios/intfake-real.S
|
||||
$(E) " CC " $@
|
||||
$(Q) $(CC) $(CFLAGS) $(BIOS_CFLAGS) -c -s bios/intfake-real.S -o bios/intfake-real.o
|
||||
$(E) " LD " $@
|
||||
$(Q) ld -T bios/bios-strip.ld.S -o bios/intfake-real.bin.elf bios/intfake-real.o
|
||||
$(E) " OBJCOPY " $@
|
||||
$(Q) objcopy -O binary -j .text bios/intfake-real.bin.elf bios/intfake-real.bin
|
||||
$(Q) $(CC) $(CFLAGS) -c bios/intfake.S -o bios/intfake.o
|
||||
|
||||
bios/int10.o: bios/int10.S bios/int10-real.S
|
||||
bios.o: bios/bios-rom.bin
|
||||
bios/bios.o: bios/bios.S bios/bios-rom.bin
|
||||
$(E) " CC " $@
|
||||
$(Q) $(CC) $(CFLAGS) $(BIOS_CFLAGS) -c -s bios/int10-real.S -o bios/int10-real.o
|
||||
$(E) " LD " $@
|
||||
$(Q) ld -T bios/bios-strip.ld.S -o bios/int10-real.bin.elf bios/int10-real.o
|
||||
$(E) " OBJCOPY " $@
|
||||
$(Q) objcopy -O binary -j .text bios/int10-real.bin.elf bios/int10-real.bin
|
||||
$(Q) $(CC) $(CFLAGS) -c bios/int10.S -o bios/int10.o
|
||||
|
||||
bios/int15.o: bios/int10.S bios/int15-real.S
|
||||
$(Q) $(CC) -c $(CFLAGS) bios/bios.S -o bios/bios.o
|
||||
|
||||
bios/bios-rom.bin: bios/bios-rom.S bios/e820.c
|
||||
$(E) " CC " $@
|
||||
$(Q) $(CC) -include code16gcc.h $(CFLAGS) $(BIOS_CFLAGS) -c -s bios/e820.c -o bios/e820.o
|
||||
$(E) " CC " $@
|
||||
$(Q) $(CC) $(CFLAGS) $(BIOS_CFLAGS) -c -s bios/int15-real.S -o bios/int15-real.o
|
||||
$(Q) $(CC) $(CFLAGS) $(BIOS_CFLAGS) -c -s bios/bios-rom.S -o bios/bios-rom.o
|
||||
$(E) " LD " $@
|
||||
$(Q) ld -T bios/bios-strip.ld.S -o bios/int15-real.bin.elf bios/int15-real.o bios/e820.o
|
||||
$(Q) ld -T bios/rom.ld.S -o bios/bios-rom.bin.elf bios/bios-rom.o bios/e820.o
|
||||
$(E) " OBJCOPY " $@
|
||||
$(Q) objcopy -O binary -j .text bios/int15-real.bin.elf bios/int15-real.bin
|
||||
$(Q) $(CC) $(CFLAGS) -c bios/int15.S -o bios/int15.o
|
||||
$(Q) objcopy -O binary -j .text bios/bios-rom.bin.elf bios/bios-rom.bin
|
||||
$(E) " NM " $@
|
||||
$(Q) cd bios && sh gen-offsets.sh > bios-rom.h && cd ..
|
||||
|
||||
check: $(PROGRAM)
|
||||
$(MAKE) -C tests
|
||||
@@ -108,6 +94,7 @@ clean:
|
||||
$(Q) rm -f bios/*.bin
|
||||
$(Q) rm -f bios/*.elf
|
||||
$(Q) rm -f bios/*.o
|
||||
$(Q) rm -f bios/bios-rom.h
|
||||
$(Q) rm -f $(OBJS) $(PROGRAM)
|
||||
.PHONY: clean
|
||||
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "bios/bios-rom.h"
|
||||
|
||||
static void bios_setup_irq_handler(struct kvm *kvm, unsigned int address,
|
||||
unsigned int irq, void *handler, unsigned int size)
|
||||
{
|
||||
@@ -19,40 +21,44 @@ static void bios_setup_irq_handler(struct kvm *kvm, unsigned int address,
|
||||
interrupt_table__set(&kvm->interrupt_table, &intr_desc, irq);
|
||||
}
|
||||
|
||||
#define BIOS_IRQ_ADDR(name) (MB_BIOS_BEGIN + BIOS_OFFSET__##name)
|
||||
#define BIOS_IRQ_FUNC(name) ((char *)&bios_rom[BIOS_OFFSET__##name])
|
||||
#define BIOS_IRQ_SIZE(name) (BIOS_ENTRY_SIZE(BIOS_OFFSET__##name))
|
||||
|
||||
void setup_bios(struct kvm *kvm)
|
||||
{
|
||||
unsigned long address = MB_BIOS_BEGIN;
|
||||
struct real_intr_desc intr_desc;
|
||||
void *p;
|
||||
|
||||
/* just copy the bios rom into the place */
|
||||
p = guest_flat_to_host(kvm, MB_BIOS_BEGIN);
|
||||
memcpy(p, bios_rom, bios_rom_size);
|
||||
|
||||
/*
|
||||
* Setup a *fake* real mode vector table, it has only
|
||||
* one real hadler which does just iret
|
||||
*/
|
||||
address = BIOS_NEXT_IRQ_ADDR(address, 0);
|
||||
p = guest_flat_to_host(kvm, address);
|
||||
memcpy(p, bios_intfake, bios_intfake_size);
|
||||
address = BIOS_IRQ_ADDR(bios_intfake);
|
||||
intr_desc = (struct real_intr_desc) {
|
||||
.segment = REAL_SEGMENT(address),
|
||||
.offset = REAL_OFFSET(address),
|
||||
};
|
||||
interrupt_table__setup(&kvm->interrupt_table, &intr_desc);
|
||||
|
||||
/*
|
||||
* int 0x10
|
||||
*/
|
||||
address = BIOS_NEXT_IRQ_ADDR(address, bios_intfake_size);
|
||||
bios_setup_irq_handler(kvm, address, 0x10, bios_int10, bios_int10_size);
|
||||
/* int 0x10 */
|
||||
address = BIOS_IRQ_ADDR(bios_int10);
|
||||
bios_setup_irq_handler(kvm, address, 0x10, BIOS_IRQ_FUNC(bios_int10), BIOS_IRQ_SIZE(bios_int10));
|
||||
|
||||
/*
|
||||
* We don't have valid BIOS yet so we put one single memory
|
||||
* region in e820 memory map
|
||||
* e820 memory map
|
||||
*
|
||||
* int 0x15
|
||||
*/
|
||||
address = BIOS_NEXT_IRQ_ADDR(address, bios_int10_size);
|
||||
bios_setup_irq_handler(kvm, address, 0x15, bios_int15, bios_int15_size);
|
||||
address = BIOS_IRQ_ADDR(bios_int15);
|
||||
bios_setup_irq_handler(kvm, address, 0x15, BIOS_IRQ_FUNC(bios_int15), BIOS_IRQ_SIZE(bios_int15));
|
||||
|
||||
/* we almost done */
|
||||
p = guest_flat_to_host(kvm, 0);
|
||||
interrupt_table__copy(&kvm->interrupt_table, p, REAL_INTR_SIZE);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* IRQ 0x10 handler - output in video memory
|
||||
* Our pretty trivial BIOS emulation
|
||||
*/
|
||||
|
||||
#include <kvm/bios.h>
|
||||
@@ -10,6 +10,13 @@
|
||||
|
||||
#include "macro.S"
|
||||
|
||||
/*
|
||||
* fake interrupt handler, nothing can be faster ever
|
||||
*/
|
||||
ENTRY(bios_intfake)
|
||||
IRET
|
||||
ENTRY_END(bios_intfake)
|
||||
|
||||
/*
|
||||
* int 10 - video - write character and advance cursor (tty write)
|
||||
* ah = 0eh
|
||||
@@ -19,10 +26,10 @@
|
||||
*
|
||||
* We ignore bx settings
|
||||
*/
|
||||
ENTRY(___int10)
|
||||
ENTRY(bios_int10)
|
||||
cli
|
||||
test $0x0e, %ah
|
||||
jne out
|
||||
jne 1f
|
||||
|
||||
/*
|
||||
* put char in AL at current cursor and
|
||||
@@ -49,16 +56,51 @@ putchar_new:
|
||||
pop %fs
|
||||
|
||||
stack_restore
|
||||
out:
|
||||
1:
|
||||
sti
|
||||
IRET
|
||||
/*
|
||||
* private IRQ data
|
||||
*/
|
||||
cursor: .long 0
|
||||
ENTRY_END(bios_int10)
|
||||
|
||||
#define EFLAGS_CF (1 << 0)
|
||||
|
||||
ENTRY(bios_int15)
|
||||
cmp $0xE820, %eax
|
||||
jne 1f
|
||||
|
||||
pushw %fs
|
||||
|
||||
pushl %edx
|
||||
pushl %ecx
|
||||
pushl %edi
|
||||
pushl %ebx
|
||||
pushl %eax
|
||||
|
||||
xor %ax, %ax
|
||||
mov %ax, %fs
|
||||
|
||||
movl %esp, %eax
|
||||
call e820_query_map
|
||||
|
||||
popl %eax
|
||||
popl %ebx
|
||||
popl %edi
|
||||
popl %ecx
|
||||
popl %edx
|
||||
|
||||
popw %fs
|
||||
|
||||
/* Clear CF */
|
||||
andl $~EFLAGS_CF, 0x4(%esp)
|
||||
1:
|
||||
IRET
|
||||
ENTRY_END(bios_int15)
|
||||
|
||||
GLOBAL(__locals)
|
||||
|
||||
/*
|
||||
* must be last in this file
|
||||
*/
|
||||
#include "local.S"
|
||||
ENTRY_END(___int10_end)
|
||||
|
||||
END(__locals)
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
#include <kvm/assembly.h>
|
||||
|
||||
.org 0
|
||||
#ifdef CONFIG_X86_64
|
||||
.code64
|
||||
#else
|
||||
.code32
|
||||
#endif
|
||||
|
||||
GLOBAL(bios_rom)
|
||||
.incbin "bios/bios-rom.bin"
|
||||
END(bios_rom)
|
||||
@@ -0,0 +1,13 @@
|
||||
#!/bin/sh
|
||||
|
||||
echo "/* Autogenerated file, don't edit */"
|
||||
echo "#ifndef BIOS_OFFSETS_H"
|
||||
echo "#define BIOS_OFFSETS_H"
|
||||
|
||||
echo ""
|
||||
echo "#define BIOS_ENTRY_SIZE(name) (name##_end - name)"
|
||||
echo ""
|
||||
|
||||
nm bios-rom.bin.elf | grep ' [:Tt:] ' | awk '{ print "#define BIOS_OFFSET__" $3 " 0x" $1; }'
|
||||
|
||||
echo "#endif"
|
||||
@@ -1,12 +0,0 @@
|
||||
#include <kvm/bios.h>
|
||||
#include <kvm/assembly.h>
|
||||
|
||||
.org 0
|
||||
#ifdef CONFIG_X86_64
|
||||
.code64
|
||||
#else
|
||||
.code32
|
||||
#endif
|
||||
GLOBAL(bios_int10)
|
||||
.incbin "bios/int10-real.bin"
|
||||
GLOBAL(bios_int10_end)
|
||||
@@ -1,50 +0,0 @@
|
||||
/*
|
||||
* IRQ 0x15 handler - e820 memory map
|
||||
*/
|
||||
|
||||
#include <kvm/bios.h>
|
||||
#include <kvm/assembly.h>
|
||||
|
||||
.org 0
|
||||
.code16gcc
|
||||
|
||||
#include "macro.S"
|
||||
|
||||
#define EFLAGS_CF (1 << 0)
|
||||
|
||||
ENTRY(___int15)
|
||||
cmp $0xE820, %eax
|
||||
jne out
|
||||
|
||||
pushw %fs
|
||||
|
||||
pushl %edx
|
||||
pushl %ecx
|
||||
pushl %edi
|
||||
pushl %ebx
|
||||
pushl %eax
|
||||
|
||||
xor %ax, %ax
|
||||
mov %ax, %fs
|
||||
|
||||
movl %esp, %eax
|
||||
call e820_query_map
|
||||
|
||||
popl %eax
|
||||
popl %ebx
|
||||
popl %edi
|
||||
popl %ecx
|
||||
popl %edx
|
||||
|
||||
popw %fs
|
||||
|
||||
/* Clear CF */
|
||||
andl $~EFLAGS_CF, 0x4(%esp)
|
||||
out:
|
||||
IRET
|
||||
|
||||
/*
|
||||
* must be last in this file
|
||||
*/
|
||||
#include "local.S"
|
||||
ENTRY_END(___int15_end)
|
||||
@@ -1,12 +0,0 @@
|
||||
#include <kvm/bios.h>
|
||||
#include <kvm/assembly.h>
|
||||
|
||||
.org 0
|
||||
#ifdef CONFIG_X86_64
|
||||
.code64
|
||||
#else
|
||||
.code32
|
||||
#endif
|
||||
GLOBAL(bios_int15)
|
||||
.incbin "bios/int15-real.bin"
|
||||
GLOBAL(bios_int15_end)
|
||||
@@ -1,15 +0,0 @@
|
||||
/*
|
||||
* BIOS fake interrupt stub, it does nothing
|
||||
* and lockless
|
||||
*/
|
||||
|
||||
#include <kvm/bios.h>
|
||||
#include <kvm/assembly.h>
|
||||
|
||||
.org 0
|
||||
.code16gcc
|
||||
|
||||
ENTRY(___intfake)
|
||||
IRET
|
||||
GLOBAL(___intfake_end)
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
#include <kvm/bios.h>
|
||||
#include <kvm/assembly.h>
|
||||
|
||||
.org 0
|
||||
#ifdef CONFIG_X86_64
|
||||
.code64
|
||||
#else
|
||||
.code32
|
||||
#endif
|
||||
GLOBAL(bios_intfake)
|
||||
.incbin "bios/intfake-real.bin"
|
||||
GLOBAL(bios_intfake_end)
|
||||
@@ -11,7 +11,8 @@
|
||||
.globl name; \
|
||||
name:
|
||||
|
||||
#define ENTRY_END(name)
|
||||
#define ENTRY_END(name) GLOBAL(name##_end)
|
||||
#define END(name) GLOBAL(name##_end)
|
||||
|
||||
/*
|
||||
* gas produces size override prefix with which
|
||||
|
||||
@@ -3,18 +3,10 @@
|
||||
|
||||
struct kvm;
|
||||
|
||||
extern char bios_intfake[0];
|
||||
extern char bios_intfake_end[0];
|
||||
extern char bios_rom[0];
|
||||
extern char bios_rom_end[0];
|
||||
|
||||
extern char bios_int10[0];
|
||||
extern char bios_int10_end[0];
|
||||
|
||||
extern char bios_int15[0];
|
||||
extern char bios_int15_end[0];
|
||||
|
||||
#define bios_intfake_size (bios_intfake_end - bios_intfake)
|
||||
#define bios_int10_size (bios_int10_end - bios_int10)
|
||||
#define bios_int15_size (bios_int15_end - bios_int15)
|
||||
#define bios_rom_size (bios_rom_end - bios_rom)
|
||||
|
||||
extern void setup_bios(struct kvm *kvm);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user