Files
kvmtool/bios.c
T
Cyrill Gorcunov 9292f77631 kvm, bios: Rework BIOS setup
This is a really huge rework of our primitive BIOS emulator.

The initial idea was to implement stack management in BIOS
irq handlers. In turn it ends up in re-factoring of all BIOS
code.

Some code details
-----------------

1) BIOS stack is placed at predefined constant memory address.
2) BIOS stack is only 64 bytes deep. It must be enough even for
   future irq handlers.
3) To be able to place irq handlers at almost arbitrary place of
   guest memory their start address must be 16 byte aligned.
   This makes easy to compute irq routines local variables addresses.
4) To eliminate address relocations in irq handlers code we use a
   special loader script.

TODO
----

- Still needs e820 map implements, int15 is dummy at moment

P.S. Thanks H. Peter Anvin for advices.

[ penberg@cs.helsinki.fi: cleanups ]
Signed-off-by: Cyrill Gorcunov <gorcunov@gmail.com>
Signed-off-by: Pekka Enberg <penberg@cs.helsinki.fi>
2015-06-01 16:39:40 +01:00

59 lines
1.5 KiB
C

#include "kvm/kvm.h"
#include "kvm/interrupt.h"
#include "kvm/util.h"
#include <string.h>
static void bios_setup_irq_handler(struct kvm *kvm, unsigned int address,
unsigned int irq, void *handler, unsigned int size)
{
struct real_intr_desc intr_desc;
void *p;
p = guest_flat_to_host(kvm, address);
memcpy(p, handler, size);
intr_desc = (struct real_intr_desc) {
.segment = REAL_SEGMENT(address),
.offset = REAL_OFFSET(address),
};
interrupt_table__set(&kvm->interrupt_table, &intr_desc, irq);
}
void setup_bios(struct kvm *kvm)
{
unsigned long address = MB_BIOS_BEGIN;
struct real_intr_desc intr_desc;
void *p;
/*
* 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);
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);
/*
* We don't have valid BIOS yet so we put one single memory
* region in 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);
p = guest_flat_to_host(kvm, 0);
interrupt_table__copy(&kvm->interrupt_table, p, REAL_INTR_SIZE);
}