aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'pc-bios')
-rw-r--r--pc-bios/bios-vista.diff17
-rw-r--r--pc-bios/bochs-manifest24
-rw-r--r--pc-bios/openbios-sparcbin0 -> 506966 bytes
-rw-r--r--pc-bios/optionrom/Makefile2
-rw-r--r--pc-bios/optionrom/extboot.S695
-rw-r--r--pc-bios/optionrom/vapic.S315
-rwxr-xr-xpc-bios/vapic.binbin0 -> 8960 bytes
-rw-r--r--pc-bios/vgabios-cirrus.binbin35840 -> 35840 bytes
-rw-r--r--pc-bios/vgabios.binbin38400 -> 39936 bytes
9 files changed, 1053 insertions, 0 deletions
diff --git a/pc-bios/bios-vista.diff b/pc-bios/bios-vista.diff
new file mode 100644
index 000000000..684a3105e
--- /dev/null
+++ b/pc-bios/bios-vista.diff
@@ -0,0 +1,17 @@
+Index: rombios32.c
+===================================================================
+RCS file: /cvsroot/bochs/bochs/bios/rombios32.c,v
+retrieving revision 1.9
+diff -u -w -r1.9 rombios32.c
+--- rombios32.c 20 Feb 2007 09:36:55 -0000 1.9
++++ rombios32.c 2 May 2007 06:07:31 -0000
+@@ -1191,7 +1191,7 @@
+ {
+ memcpy(h->signature, sig, 4);
+ h->length = cpu_to_le32(len);
+- h->revision = 0;
++ h->revision = 1;
+ #ifdef BX_QEMU
+ memcpy(h->oem_id, "QEMU ", 6);
+ memcpy(h->oem_table_id, "QEMU", 4);
+
diff --git a/pc-bios/bochs-manifest b/pc-bios/bochs-manifest
new file mode 100644
index 000000000..1b25aa412
--- /dev/null
+++ b/pc-bios/bochs-manifest
@@ -0,0 +1,24 @@
+.cvsignore 1.2
+BIOS-bochs-latest 1.145
+BIOS-bochs-legacy 1.9
+Makefile.in 1.26
+VGABIOS-elpin-2.40 1.4
+VGABIOS-elpin-LICENSE 1.3
+VGABIOS-lgpl-README 1.9
+VGABIOS-lgpl-latest 1.13
+VGABIOS-lgpl-latest-cirrus 1.5
+VGABIOS-lgpl-latest-cirrus-debug 1.5
+VGABIOS-lgpl-latest-debug 1.9
+acpi-dsdt.dsl 1.1
+acpi-dsdt.hex 1.1
+apmbios.S 1.5
+bios_usage 1.1
+biossums.c 1.3
+makesym.perl 1.1
+notes 1.1
+rombios.c 1.178
+rombios.h 1.4
+rombios32.c 1.9
+rombios32.ld 1.1
+rombios32start.S 1.3
+usage.cc 1.4
diff --git a/pc-bios/openbios-sparc b/pc-bios/openbios-sparc
new file mode 100644
index 000000000..7a729aa81
--- /dev/null
+++ b/pc-bios/openbios-sparc
Binary files differ
diff --git a/pc-bios/optionrom/Makefile b/pc-bios/optionrom/Makefile
index 54db88249..84c77018d 100644
--- a/pc-bios/optionrom/Makefile
+++ b/pc-bios/optionrom/Makefile
@@ -15,6 +15,8 @@ QEMU_CFLAGS = $(CFLAGS)
build-all: multiboot.bin linuxboot.bin
+build-all: extboot.bin vapic.bin
+
%.img: %.o
$(call quiet-command,$(LD) -Ttext 0 -e _start -s -o $@ $<," Building $(TARGET_DIR)$@")
diff --git a/pc-bios/optionrom/extboot.S b/pc-bios/optionrom/extboot.S
new file mode 100644
index 000000000..1e60f6878
--- /dev/null
+++ b/pc-bios/optionrom/extboot.S
@@ -0,0 +1,695 @@
+/*
+ * Extended Boot Option ROM
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Copyright IBM Corporation, 2007
+ * Authors: Anthony Liguori <aliguori@us.ibm.com>
+ */
+
+.code16
+.text
+ .global _start
+_start:
+ .short 0xaa55
+ .byte (_end - _start) / 512
+ push %eax
+ push %ds
+
+ /* setup ds so we can access the IVT */
+ xor %ax, %ax
+ mov %ax, %ds
+
+ /* there is one more bootable HD */
+ incb 0x0475
+
+ /* save old int 19 */
+ mov (0x19*4), %eax
+ mov %eax, %cs:old_int19
+
+ /* install out int 19 handler */
+ movw $int19_handler, (0x19*4)
+ mov %cs, (0x19*4+2)
+
+ pop %ds
+ pop %eax
+ lret
+
+int19_handler:
+ push %eax
+ push %bx
+ push %cx
+ push %dx
+ push %ds
+
+ /* setup ds to access IVT */
+ xor %ax, %ax
+ mov %ax, %ds
+
+ movw $0x404, %dx
+ inb %dx, %al
+ cmp $1, %al
+ je 1f
+ cmp $2, %al
+ je 2f
+ jmp 3f
+
+1: /* hook int13: intb(0x404) == 1 */
+ /* save old int 13 to int 2c */
+ mov (0x13*4), %eax
+ mov %eax, %cs:old_int13
+
+ /* install our int 13 handler */
+ movw $int13_handler, (0x13*4)
+ mov %cs, (0x13*4+2)
+ jmp 3f
+
+2: /* linux boot: intb(0x404) == 2 */
+ cli
+ cld
+ mov $0x9000, %ax
+ mov %ax, %ds
+ mov %ax, %es
+ mov %ax, %fs
+ mov %ax, %gs
+ mov %ax, %ss
+ mov $0x8ffe, %sp
+ ljmp $0x9000 + 0x20, $0
+
+3: /* fall through: inb(0x404) == 0 */
+ /* restore previous int $0x19 handler */
+ mov %cs:old_int19,%eax
+ mov %eax,(0x19*4)
+
+ pop %ds
+ pop %dx
+ pop %cx
+ pop %bx
+ pop %eax
+ ljmpw *%cs:old_int19
+
+#define FLAGS_CF 0x01
+
+/* The two macro below clear/set the carry flag to indicate the status
+ * of the interrupt execution. It is not enough to issue a clc/stc instruction,
+ * since the value of the flags register will be overwritten by whatever is
+ * in the stack frame
+ */
+.macro clc_stack
+ push %bp
+ mov %sp, %bp
+ /* 8 = 2 (bp, just pushed) + 2 (ip) + 3 (real mode interrupt frame) */
+ and $(~FLAGS_CF), 8(%bp)
+ pop %bp
+.endm
+
+.macro stc_stack
+ push %bp
+ /* 8 = 2 (bp, just pushed) + 2 (ip) + 3 (real mode interrupt frame) */
+ or $(FLAGS_CF), 8(%bp)
+ pop %bp
+.endm
+
+/* we clobber %bx */
+.macro alloca size
+ push %ds
+ push %bp
+ mov %sp, %bp /* remember the current stack position */
+
+ mov %ss, %bx
+ mov %bx, %ds
+
+ sub \size, %sp
+ and $(~0x0F), %sp
+ mov %sp, %bx
+
+ push %bp
+ mov 0(%bp), %bp
+.endm
+
+/* we clobber %bp */
+.macro allocbpa size
+ mov %sp, %bp /* remember the current stack position */
+ sub \size, %sp
+ and $(~0x0F), %sp
+ push %bp
+ mov %sp, %bp
+ add $2, %bp
+.endm
+
+.macro freea
+ pop %sp
+ add $2, %sp
+ pop %ds
+.endm
+
+.macro freebpa
+ pop %sp
+.endm
+
+.macro dump reg
+ push %ax
+ push %dx
+
+ mov \reg, %ax
+ mov $0x406, %dx
+ outw %ax, %dx
+
+ pop %dx
+ pop %ax
+.endm
+
+.macro callout value
+ push %bp
+ push %bx
+ mov %sp, %bp
+ alloca $16
+ push %ax
+ push %dx
+
+ mov %ax, 0(%bx) /* ax */
+ mov 0(%bp), %ax /* bx */
+ mov %ax, 2(%bx)
+ mov %cx, 4(%bx) /* cx */
+ mov %dx, 6(%bx) /* dx */
+ mov %si, 8(%bx) /* si */
+ mov %ds, 10(%bx) /* ds */
+ mov %es, 12(%bx) /* ds */
+ movw \value, 14(%bx) /* value */
+
+ mov %bx, %ax
+ shr $4, %ax
+ mov %ds, %dx
+ add %dx, %ax
+
+ mov $0x407, %dx
+ outw %ax, %dx
+
+ pop %dx
+ pop %ax
+ freea
+ pop %bx
+ pop %bp
+.endm
+
+send_command:
+ push %bp
+ mov %sp, %bp
+ push %ax
+ push %bx
+ push %dx
+
+ mov 4(%bp), %ax
+ shr $4, %ax
+ and $0x0FFF, %ax
+ mov %ss, %bx
+ add %bx, %ax
+
+ mov $0x405, %dx
+ outw %ax, %dx
+
+ pop %dx
+ pop %bx
+ pop %ax
+ pop %bp
+
+ push %ax
+ mov 2(%bx), %ax
+ pop %ax
+
+ ret
+
+add32: /* lo, hi, lo, hi */
+ push %bp
+ mov %sp, %bp
+
+ movw 4(%bp), %cx /* hi */
+ movw 6(%bp), %dx /* lo */
+
+ add 10(%bp), %dx
+ jnc 1f
+ add $1, %cx
+1: add 8(%bp), %cx
+
+ pop %bp
+ ret
+
+mul32: /* lo, hi, lo, hi */
+ /* 10(%bp), 8(%bp), 6(%bp), 4(%bp) */
+ push %bp
+ mov %sp, %bp
+ push %ax
+ push %bx
+
+ xor %cx, %cx
+ xor %dx, %dx
+
+ /* for (i = 0; i < 16;) */
+ xor %bx, %bx
+0:
+ cmp $16, %bx
+ jge 2f
+
+ mov 6(%bp), %ax
+ and $1, %ax
+ cmp $1, %ax
+ jne 1f
+ push 10(%bp)
+ push 8(%bp)
+ push %dx
+ push %cx
+ call add32
+ add $8, %sp
+1:
+ shlw $1, 8(%bp)
+ movw 10(%bp), %ax
+ and $0x8000, %ax
+ cmp $0x8000, %ax
+ jne 1f
+ orw $1, 8(%bp)
+1:
+ shlw $1, 10(%bp)
+ shrw $1, 6(%bp)
+
+ /* i++) { */
+ add $1, %bx
+ jmp 0b
+
+2:
+ pop %bx
+ pop %ax
+ pop %bp
+ ret
+
+disk_reset:
+ movb $0, %ah
+ clc_stack
+ ret
+
+/* this really should be a function, not a macro but i'm lazy */
+.macro read_write_disk_sectors cmd
+ push %ax
+ push %bx
+ push %cx
+ push %dx
+ push %si
+
+ push %bp
+ sub $10, %sp
+ mov %sp, %bp
+
+ /* save nb_sectors */
+ mov %al, 6(%bp)
+ movb $0, 7(%bp)
+
+ /* save buffer */
+ mov %bx, 8(%bp)
+
+ /* cylinders */
+ xor %ax, %ax
+ mov %cl, %al
+ shl $2, %ax
+ and $0x300, %ax
+ mov %ch, %al
+ mov %ax, 0(%bp)
+
+ /* heads */
+ xor %ax, %ax
+ mov %dh, %al
+ mov %ax, 2(%bp)
+
+ /* sectors - 1 */
+ xor %ax, %ax
+ mov %cl, %al
+ and $0x3F, %al
+ sub $1, %ax
+ mov %ax, 4(%bp)
+
+ alloca $16
+
+ movw $0, 0(%bx) /* read c,h,s */
+ push %bx
+ call send_command
+ add $2, %sp
+
+ mov 6(%bx), %ax /* total_sectors */
+ mov 2(%bp), %si /* *= heads */
+ mul %si
+ add 4(%bp), %ax /* += sectors - 1 */
+
+ push 4(%bx) /* total_heads */
+ push $0
+ push 6(%bx) /* total_sectors */
+ push $0
+ call mul32
+ add $8, %sp
+
+ push 0(%bp) /* cylinders */
+ push $0
+ push %dx
+ push %cx
+ call mul32
+ add $8, %sp
+
+ add %ax, %dx
+ jnc 1f
+ add $1, %cx
+1:
+ freea
+
+ alloca $16
+
+ movw \cmd, 0(%bx) /* read */
+ movw 6(%bp), %ax /* nb_sectors */
+ movw %ax, 2(%bx)
+ movw %es, 4(%bx) /* segment */
+ movw 8(%bp), %ax /* offset */
+ mov %ax, 6(%bx)
+ movw %dx, 8(%bx) /* sector */
+ movw %cx, 10(%bx)
+ movw $0, 12(%bx)
+ movw $0, 14(%bx)
+
+ push %bx
+ call send_command
+ add $2, %sp
+
+ freea
+
+ add $10, %sp
+ pop %bp
+
+ pop %si
+ pop %dx
+ pop %cx
+ pop %bx
+ pop %ax
+
+ mov $0, %ah
+ clc_stack
+ ret
+.endm
+
+read_disk_sectors:
+ read_write_disk_sectors $0x01
+
+write_disk_sectors:
+ read_write_disk_sectors $0x02
+
+read_disk_drive_parameters:
+ push %bx
+
+ /* allocate memory for packet, pointer gets returned in bx */
+ alloca $16
+
+ /* issue command */
+ movw $0, 0(%bx) /* cmd = 0, read c,h,s */
+ push %bx
+ call send_command
+ add $2, %sp
+
+ /* normalize sector value */
+ movb 6(%bx), %cl
+ andb $0x3F, %cl
+ movb %cl, 6(%bx)
+
+ /* normalize cylinders */
+ subw $2, 2(%bx)
+
+ /* normalize heads */
+ subw $1, 4(%bx)
+
+ /* return code */
+ mov $0, %ah
+
+ /* cylinders */
+ movb 2(%bx), %ch
+ movb 3(%bx), %cl
+ shlb $6, %cl
+ andb $0xC0, %cl
+
+ /* sectors */
+ orb 6(%bx), %cl
+
+ /* heads */
+ movb 4(%bx), %dh
+
+ /* drives */
+ movb $1, %dl
+
+ /* status */
+ mov $0, %ah
+
+ freea
+
+ pop %bx
+
+ /* do this last since it's the most sensitive */
+ clc_stack
+ ret
+
+alternate_disk_reset:
+ movb $0, %ah
+ clc_stack
+ ret
+
+read_disk_drive_size:
+ push %bx
+ alloca $16
+
+ movw $0, 0(%bx) /* cmd = 0, read c,h,s */
+ push %bx
+ call send_command
+ add $2, %sp
+
+ /* cylinders - 1 to cx:dx */
+ mov 2(%bx), %dx
+ xor %cx, %cx
+ sub $1, %dx
+
+ /* heads */
+ push 4(%bx)
+ push $0
+ push %dx
+ push %cx
+ call mul32
+ add $8, %sp
+
+ /* sectors */
+ push 6(%bx)
+ push $0
+ push %dx
+ push %cx
+ call mul32
+ add $8, %sp
+
+ /* status */
+ mov $3, %ah
+
+ freea
+ pop %bx
+
+ clc_stack
+ ret
+
+check_if_extensions_present:
+ mov $0x30, %ah
+ mov $0xAA55, %bx
+ mov $0x07, %cx
+ clc_stack
+ ret
+
+.macro extended_read_write_sectors cmd
+ cmpb $10, 0(%si)
+ jg 1f
+ mov $1, %ah
+ stc_stack
+ ret
+1:
+ push %ax
+ push %bp
+ allocbpa $16
+
+ movw \cmd, 0(%bp) /* read */
+ movw 2(%si), %ax /* nb_sectors */
+ movw %ax, 2(%bp)
+ movw 4(%si), %ax /* offset */
+ movw %ax, 6(%bp)
+ movw 6(%si), %ax /* segment */
+ movw %ax, 4(%bp)
+ movw 8(%si), %ax /* block */
+ movw %ax, 8(%bp)
+ movw 10(%si), %ax
+ movw %ax, 10(%bp)
+ movw 12(%si), %ax
+ movw %ax, 12(%bp)
+ movw 14(%si), %ax
+ movw %ax, 14(%bp)
+
+ push %bp
+ call send_command
+ add $2, %sp
+
+ freebpa
+ pop %bp
+ pop %ax
+
+ mov $0, %ah
+ clc_stack
+ ret
+.endm
+
+extended_read_sectors:
+ extended_read_write_sectors $0x01
+
+extended_write_sectors:
+ extended_read_write_sectors $0x02
+
+get_extended_drive_parameters:
+ push %ax
+ push %bp
+ push %cx
+ push %dx
+
+ allocbpa $16
+
+ movw $0, 0(%bp) /* read c,h,s */
+ push %bp
+ call send_command
+ add $2, %sp
+
+ /* write size */
+ movw $26, 0(%si)
+
+ /* set flags to 2 */
+ movw $2, 2(%si)
+
+ /* cylinders */
+ mov 2(%bp), %ax
+ mov %ax, 4(%si)
+ xor %ax, %ax
+ mov %ax, 6(%si)
+
+ /* heads */
+ mov 4(%bp), %ax
+ mov %ax, 8(%si)
+ xor %ax, %ax
+ mov %ax, 10(%si)
+
+ /* sectors */
+ mov 6(%bp), %ax
+ mov %ax, 12(%si)
+ xor %ax, %ax
+ mov %ax, 14(%si)
+
+ /* set total number of sectors */
+ mov 8(%bp), %ax
+ mov %ax, 16(%si)
+ mov 10(%bp), %ax
+ mov %ax, 18(%si)
+ mov 12(%bp), %ax
+ mov %ax, 20(%si)
+ mov 14(%bp), %ax
+ mov %ax, 22(%si)
+
+ /* number of bytes per sector */
+ movw $512, 24(%si)
+
+ freebpa
+
+ pop %dx
+ pop %cx
+ pop %bp
+ pop %ax
+
+ mov $0, %ah
+ clc_stack
+ ret
+
+terminate_disk_emulation:
+ mov $1, %ah
+ stc_stack
+ ret
+
+int13_handler:
+ cmp $0x80, %dl
+ je 1f
+ ljmpw *%cs:old_int13
+1:
+ cmp $0x0, %ah
+ jne 1f
+ call disk_reset
+ iret
+1:
+ cmp $0x2, %ah
+ jne 1f
+ call read_disk_sectors
+ iret
+1:
+ cmp $0x8, %ah
+ jne 1f
+ call read_disk_drive_parameters
+ iret
+1:
+ cmp $0x15, %ah
+ jne 1f
+ call read_disk_drive_size
+ iret
+1:
+ cmp $0x41, %ah
+ jne 1f
+ call check_if_extensions_present
+ iret
+1:
+ cmp $0x42, %ah
+ jne 1f
+ call extended_read_sectors
+ iret
+1:
+ cmp $0x48, %ah
+ jne 1f
+ call get_extended_drive_parameters
+ iret
+1:
+ cmp $0x4b, %ah
+ jne 1f
+ call terminate_disk_emulation
+ iret
+1:
+ cmp $0x0d, %ah
+ jne 1f
+ call alternate_disk_reset
+ iret
+1:
+ cmp $0x03, %ah
+ jne 1f
+ call write_disk_sectors
+ iret
+1:
+ cmp $0x43, %ah
+ jne 1f
+ call extended_write_sectors
+ iret
+1:
+ int $0x18 /* boot failed */
+ iret
+
+/* Variables */
+.align 4, 0
+old_int13: .long 0
+old_int19: .long 0
+
+.align 512, 0
+_end:
diff --git a/pc-bios/optionrom/vapic.S b/pc-bios/optionrom/vapic.S
new file mode 100644
index 000000000..afe98a9ca
--- /dev/null
+++ b/pc-bios/optionrom/vapic.S
@@ -0,0 +1,315 @@
+ .text 0
+ .code16
+.global _start
+_start:
+ .short 0xaa55
+ .byte (_end - _start) / 512
+ mov $vapic_base, %ax
+ out %ax, $0x7e
+ lret
+
+ .code32
+vapic_size = 2*4096
+
+.macro fixup delta=-4
+777:
+ .text 1
+ .long 777b + \delta - vapic_base
+ .text 0
+.endm
+
+.macro reenable_vtpr
+ out %al, $0x7e
+.endm
+
+.text 1
+ fixup_start = .
+.text 0
+
+.align 16
+
+vapic_base:
+ .ascii "kvm aPiC"
+
+ /* relocation data */
+ .long vapic_base ; fixup
+ .long fixup_start ; fixup
+ .long fixup_end ; fixup
+
+ .long vapic ; fixup
+ .long vapic_size
+vcpu_shift:
+ .long 0
+real_tpr:
+ .long 0
+ .long up_set_tpr ; fixup
+ .long up_set_tpr_eax ; fixup
+ .long up_get_tpr_eax ; fixup
+ .long up_get_tpr_ecx ; fixup
+ .long up_get_tpr_edx ; fixup
+ .long up_get_tpr_ebx ; fixup
+ .long 0 /* esp. won't work. */
+ .long up_get_tpr_ebp ; fixup
+ .long up_get_tpr_esi ; fixup
+ .long up_get_tpr_edi ; fixup
+ .long up_get_tpr_stack ; fixup
+ .long mp_set_tpr ; fixup
+ .long mp_set_tpr_eax ; fixup
+ .long mp_get_tpr_eax ; fixup
+ .long mp_get_tpr_ecx ; fixup
+ .long mp_get_tpr_edx ; fixup
+ .long mp_get_tpr_ebx ; fixup
+ .long 0 /* esp. won't work. */
+ .long mp_get_tpr_ebp ; fixup
+ .long mp_get_tpr_esi ; fixup
+ .long mp_get_tpr_edi ; fixup
+ .long mp_get_tpr_stack ; fixup
+
+.macro kvm_hypercall
+ .byte 0x0f, 0x01, 0xc1
+.endm
+
+kvm_hypercall_vapic_poll_irq = 1
+
+pcr_cpu = 0x51
+
+.align 64
+
+mp_get_tpr_eax:
+ pushf
+ cli
+ reenable_vtpr
+ push %ecx
+
+ fs/movzbl pcr_cpu, %eax
+
+ mov vcpu_shift, %ecx ; fixup
+ shl %cl, %eax
+ testb $1, vapic+4(%eax) ; fixup delta=-5
+ jz mp_get_tpr_bad
+ movzbl vapic(%eax), %eax ; fixup
+
+mp_get_tpr_out:
+ pop %ecx
+ popf
+ ret
+
+mp_get_tpr_bad:
+ mov real_tpr, %eax ; fixup
+ mov (%eax), %eax
+ jmp mp_get_tpr_out
+
+mp_get_tpr_ebx:
+ mov %eax, %ebx
+ call mp_get_tpr_eax
+ xchg %eax, %ebx
+ ret
+
+mp_get_tpr_ecx:
+ mov %eax, %ecx
+ call mp_get_tpr_eax
+ xchg %eax, %ecx
+ ret
+
+mp_get_tpr_edx:
+ mov %eax, %edx
+ call mp_get_tpr_eax
+ xchg %eax, %edx
+ ret
+
+mp_get_tpr_esi:
+ mov %eax, %esi
+ call mp_get_tpr_eax
+ xchg %eax, %esi
+ ret
+
+mp_get_tpr_edi:
+ mov %eax, %edi
+ call mp_get_tpr_edi
+ xchg %eax, %edi
+ ret
+
+mp_get_tpr_ebp:
+ mov %eax, %ebp
+ call mp_get_tpr_eax
+ xchg %eax, %ebp
+ ret
+
+mp_get_tpr_stack:
+ call mp_get_tpr_eax
+ xchg %eax, 4(%esp)
+ ret
+
+mp_set_tpr_eax:
+ push %eax
+ call mp_set_tpr
+ ret
+
+mp_set_tpr:
+ pushf
+ push %eax
+ push %ecx
+ push %edx
+ push %ebx
+ cli
+ reenable_vtpr
+
+mp_set_tpr_failed:
+ fs/movzbl pcr_cpu, %edx
+
+ mov vcpu_shift, %ecx ; fixup
+ shl %cl, %edx
+
+ testb $1, vapic+4(%edx) ; fixup delta=-5
+ jz mp_set_tpr_bad
+
+ mov vapic(%edx), %eax ; fixup
+
+ mov %eax, %ebx
+ mov 24(%esp), %bl
+
+ /* %ebx = new vapic (%bl = tpr, %bh = isr, %b3 = irr) */
+
+ lock cmpxchg %ebx, vapic(%edx) ; fixup
+ jnz mp_set_tpr_failed
+
+ /* compute ppr */
+ cmp %bh, %bl
+ jae mp_tpr_is_bigger
+mp_isr_is_bigger:
+ mov %bh, %bl
+mp_tpr_is_bigger:
+ /* %bl = ppr */
+ mov %bl, %ch /* ch = ppr */
+ rol $8, %ebx
+ /* now: %bl = irr, %bh = ppr */
+ cmp %bh, %bl
+ ja mp_set_tpr_poll_irq
+
+mp_set_tpr_out:
+ pop %ebx
+ pop %edx
+ pop %ecx
+ pop %eax
+ popf
+ ret $4
+
+mp_set_tpr_poll_irq:
+ mov $kvm_hypercall_vapic_poll_irq, %eax
+ kvm_hypercall
+ jmp mp_set_tpr_out
+
+mp_set_tpr_bad:
+ mov 24(%esp), %ecx
+ mov real_tpr, %eax ; fixup
+ mov %ecx, (%eax)
+ jmp mp_set_tpr_out
+
+up_get_tpr_eax:
+ reenable_vtpr
+ movzbl vapic, %eax ; fixup
+ ret
+
+up_get_tpr_ebx:
+ reenable_vtpr
+ movzbl vapic, %ebx ; fixup
+ ret
+
+up_get_tpr_ecx:
+ reenable_vtpr
+ movzbl vapic, %ecx ; fixup
+ ret
+
+up_get_tpr_edx:
+ reenable_vtpr
+ movzbl vapic, %edx ; fixup
+ ret
+
+up_get_tpr_esi:
+ reenable_vtpr
+ movzbl vapic, %esi ; fixup
+ ret
+
+up_get_tpr_edi:
+ reenable_vtpr
+ movzbl vapic, %edi ; fixup
+ ret
+
+up_get_tpr_ebp:
+ reenable_vtpr
+ movzbl vapic, %ebp ; fixup
+ ret
+
+up_get_tpr_stack:
+ reenable_vtpr
+ movzbl vapic, %eax ; fixup
+ xchg %eax, 4(%esp)
+ ret
+
+up_set_tpr_eax:
+ push %eax
+ call up_set_tpr
+ ret
+
+up_set_tpr:
+ pushf
+ push %eax
+ push %ecx
+ push %ebx
+ reenable_vtpr
+
+up_set_tpr_failed:
+ mov vapic, %eax ; fixup
+
+ mov %eax, %ebx
+ mov 20(%esp), %bl
+
+ /* %ebx = new vapic (%bl = tpr, %bh = isr, %b3 = irr) */
+
+ lock cmpxchg %ebx, vapic ; fixup
+ jnz up_set_tpr_failed
+
+ /* compute ppr */
+ cmp %bh, %bl
+ jae up_tpr_is_bigger
+up_isr_is_bigger:
+ mov %bh, %bl
+up_tpr_is_bigger:
+ /* %bl = ppr */
+ mov %bl, %ch /* ch = ppr */
+ rol $8, %ebx
+ /* now: %bl = irr, %bh = ppr */
+ cmp %bh, %bl
+ ja up_set_tpr_poll_irq
+
+up_set_tpr_out:
+ pop %ebx
+ pop %ecx
+ pop %eax
+ popf
+ ret $4
+
+up_set_tpr_poll_irq:
+ mov $kvm_hypercall_vapic_poll_irq, %eax
+ kvm_hypercall
+ jmp up_set_tpr_out
+
+.text 1
+ fixup_end = .
+.text 0
+
+/*
+ * vapic format:
+ * per-vcpu records of size 2^vcpu shift.
+ * byte 0: tpr (r/w)
+ * byte 1: highest in-service interrupt (isr) (r/o); bits 3:0 are zero
+ * byte 2: zero (r/o)
+ * byte 3: highest pending interrupt (irr) (r/o)
+ */
+.text 2
+
+.align 128
+
+vapic:
+. = . + vapic_size
+_end:
diff --git a/pc-bios/vapic.bin b/pc-bios/vapic.bin
new file mode 100755
index 000000000..35f0cf2a3
--- /dev/null
+++ b/pc-bios/vapic.bin
Binary files differ
diff --git a/pc-bios/vgabios-cirrus.bin b/pc-bios/vgabios-cirrus.bin
index 4fa8f99f7..7007bf093 100644
--- a/pc-bios/vgabios-cirrus.bin
+++ b/pc-bios/vgabios-cirrus.bin
Binary files differ
diff --git a/pc-bios/vgabios.bin b/pc-bios/vgabios.bin
index fa6f815fc..c38c62ae3 100644
--- a/pc-bios/vgabios.bin
+++ b/pc-bios/vgabios.bin
Binary files differ