2 #include "kvm/boot-protocol.h"
4 #include "kvm/interrupt.h"
10 #include "bios/bios-rom.h"
13 unsigned long address
;
19 #define BIOS_IRQ_PA_ADDR(name) (MB_BIOS_BEGIN + BIOS_OFFSET__##name)
20 #define BIOS_IRQ_FUNC(name) ((char *)&bios_rom[BIOS_OFFSET__##name])
21 #define BIOS_IRQ_SIZE(name) (BIOS_ENTRY_SIZE(BIOS_OFFSET__##name))
23 #define DEFINE_BIOS_IRQ_HANDLER(_irq, _handler) \
26 .address = BIOS_IRQ_PA_ADDR(_handler), \
27 .handler = BIOS_IRQ_FUNC(_handler), \
28 .size = BIOS_IRQ_SIZE(_handler), \
31 static struct irq_handler bios_irq_handlers
[] = {
32 DEFINE_BIOS_IRQ_HANDLER(0x10, bios_int10
),
33 DEFINE_BIOS_IRQ_HANDLER(0x15, bios_int15
),
36 static void setup_irq_handler(struct kvm
*kvm
, struct irq_handler
*handler
)
38 struct real_intr_desc intr_desc
;
41 p
= guest_flat_to_host(kvm
, handler
->address
);
42 memcpy(p
, handler
->handler
, handler
->size
);
44 intr_desc
= (struct real_intr_desc
) {
45 .segment
= REAL_SEGMENT(MB_BIOS_BEGIN
),
46 .offset
= handler
->address
- MB_BIOS_BEGIN
,
49 DIE_IF((handler
->address
- MB_BIOS_BEGIN
) > (unsigned long)0xffff);
51 interrupt_table__set(&kvm
->interrupt_table
, &intr_desc
, handler
->irq
);
55 * e820_setup - setup some simple E820 memory map
56 * @kvm - guest system descriptor
58 static void e820_setup(struct kvm
*kvm
)
61 struct e820entry
*mem_map
;
64 e820
= guest_flat_to_host(kvm
, E820_MAP_START
);
67 mem_map
[i
++] = (struct e820entry
) {
68 .addr
= REAL_MODE_IVT_BEGIN
,
69 .size
= EBDA_START
- REAL_MODE_IVT_BEGIN
,
72 mem_map
[i
++] = (struct e820entry
) {
74 .size
= VGA_RAM_BEGIN
- EBDA_START
,
75 .type
= E820_RESERVED
,
77 mem_map
[i
++] = (struct e820entry
) {
78 .addr
= MB_BIOS_BEGIN
,
79 .size
= MB_BIOS_END
- MB_BIOS_BEGIN
,
80 .type
= E820_RESERVED
,
82 if (kvm
->ram_size
< KVM_32BIT_GAP_START
) {
83 mem_map
[i
++] = (struct e820entry
) {
84 .addr
= BZ_KERNEL_START
,
85 .size
= kvm
->ram_size
- BZ_KERNEL_START
,
89 mem_map
[i
++] = (struct e820entry
) {
90 .addr
= BZ_KERNEL_START
,
91 .size
= KVM_32BIT_GAP_START
- BZ_KERNEL_START
,
94 mem_map
[i
++] = (struct e820entry
) {
95 .addr
= 0x100000000ULL
,
96 .size
= kvm
->ram_size
- KVM_32BIT_GAP_START
,
101 BUILD_BUG_ON(i
> E820_X_MAX
);
107 * setup_bios - inject BIOS into guest memory
108 * @kvm - guest system descriptor
110 void setup_bios(struct kvm
*kvm
)
112 unsigned long address
= MB_BIOS_BEGIN
;
113 struct real_intr_desc intr_desc
;
118 * before anything else -- clean some known areas
119 * we definitely don't want any trash here
121 p
= guest_flat_to_host(kvm
, BDA_START
);
122 memset(p
, 0, BDA_END
- BDA_START
);
124 p
= guest_flat_to_host(kvm
, EBDA_START
);
125 memset(p
, 0, EBDA_END
- EBDA_START
);
127 p
= guest_flat_to_host(kvm
, MB_BIOS_BEGIN
);
128 memset(p
, 0, MB_BIOS_END
- MB_BIOS_BEGIN
);
130 p
= guest_flat_to_host(kvm
, VGA_ROM_BEGIN
);
131 memset(p
, 0, VGA_ROM_END
- VGA_ROM_BEGIN
);
133 /* just copy the bios rom into the place */
134 p
= guest_flat_to_host(kvm
, MB_BIOS_BEGIN
);
135 memcpy(p
, bios_rom
, bios_rom_size
);
137 /* E820 memory map must be present */
141 * Setup a *fake* real mode vector table, it has only
142 * one real hadler which does just iret
144 address
= BIOS_IRQ_PA_ADDR(bios_intfake
);
145 intr_desc
= (struct real_intr_desc
) {
146 .segment
= REAL_SEGMENT(MB_BIOS_BEGIN
),
147 .offset
= address
- MB_BIOS_BEGIN
,
149 interrupt_table__setup(&kvm
->interrupt_table
, &intr_desc
);
151 for (i
= 0; i
< ARRAY_SIZE(bios_irq_handlers
); i
++)
152 setup_irq_handler(kvm
, &bios_irq_handlers
[i
]);
155 p
= guest_flat_to_host(kvm
, 0);
156 interrupt_table__copy(&kvm
->interrupt_table
, p
, REAL_INTR_SIZE
);