qemu gcc4 patch and disable not compiling targets

git-svn-id: https://svn.disconnected-by-peer.at/svn/linamh/trunk/linamh@713 6952d904-891a-0410-993b-d76249ca496b
This commit is contained in:
geos_one
2009-01-24 11:03:18 +00:00
parent 6c60228733
commit 9d45f1936c
34 changed files with 4483 additions and 0 deletions

View File

@@ -0,0 +1,120 @@
# Send to upstream BOCHS
This ACPI BIOS patch provides:
- The PCI bus definition for PIC, HPET, RTC, SMC and OSYS and SMIF
- An PBLK which provides the size of the L2 and L3 caches
- If newer hardware like ICH6 IDE is found, init it
Signed-off-by: Alex Graf - http://alex.csgraf.de
Index: kvm-77/bios-mac/acpi-dsdt.dsl
===================================================================
--- kvm-77.orig/bios-mac/acpi-dsdt.dsl
+++ kvm-77/bios-mac/acpi-dsdt.dsl
@@ -78,6 +78,47 @@ DefinitionBlock (
/* PCI Bus definition */
Scope(\_SB) {
+ Device (HPET)
+ {
+ Name (_HID, EisaId ("PNP0103"))
+ Name (_CID, 0x010CD041)
+ Name (BUF0, ResourceTemplate ()
+ {
+ IRQNoFlags ()
+ {2}
+ IRQNoFlags ()
+ {8}
+ Memory32Fixed (ReadOnly,
+ 0xFED00000, // Address Base
+ 0x00000400, // Address Length
+ _Y16)
+ })
+ Method (_STA, 0, NotSerialized)
+ {
+ Return (0x0F)
+ }
+ Method (_CRS, 0, Serialized)
+ {
+ Return (BUF0)
+ }
+ }
+ Device (SMC)
+ {
+ Name (_HID, EisaId ("APP0001"))
+ Name (_CID, "smc-napa")
+ Name (_STA, 0x0B)
+ Name (_CRS, ResourceTemplate ()
+ {
+ IO (Decode16,
+ 0x0300, // Range Minimum
+ 0x0300, // Range Maximum
+ 0x01, // Alignment
+ 0x20, // Length
+ )
+ IRQNoFlags ()
+ {6}
+ })
+ }
Device(PCI0) {
Name (_HID, EisaId ("PNP0A03"))
Name (_ADR, 0x00)
Index: kvm-77/bios-mac/rombios32.c
===================================================================
--- kvm-77.orig/bios-mac/rombios32.c
+++ kvm-77/bios-mac/rombios32.c
@@ -628,6 +628,9 @@ void smp_probe(void)
#define PCI_DEVICE_ID_INTEL_82371AB_0 0x7110
#define PCI_DEVICE_ID_INTEL_82371AB 0x7111
#define PCI_DEVICE_ID_INTEL_82371AB_3 0x7113
+#define PCI_DEVICE_ID_INTEL_874079 0x27a0 /* i945GM Express Chipset */
+#define PCI_DEVICE_ID_INTEL_945GL 0x27b9 /* ICH7 LPC */
+#define PCI_DEVICE_ID_INTEL_ICH6IDE 0x269e
#define PCI_VENDOR_ID_IBM 0x1014
#define PCI_VENDOR_ID_APPLE 0x106b
@@ -641,7 +644,9 @@ static uint32_t pci_bios_io_addr;
static uint32_t pci_bios_mem_addr;
static uint32_t pci_bios_bigmem_addr;
/* host irqs corresponding to PCI irqs A-D */
-static uint8_t pci_irqs[4] = { 10, 10, 11, 11 };
+static uint8_t pci_irqs[4] = { 11, 10, 11, 10 };
+//static uint8_t pci_irqs[4] = { 10, 10, 11, 11 };
+//static uint8_t pci_irqs[4] = { 0x10, 0x11, 0x12, 0x13 };
static PCIDevice i440_pcidev;
static void pci_config_writel(PCIDevice *d, uint32_t addr, uint32_t val)
@@ -772,7 +777,9 @@ static void pci_bios_init_bridges(PCIDev
if (vendor_id == PCI_VENDOR_ID_INTEL &&
(device_id == PCI_DEVICE_ID_INTEL_82371SB_0 ||
- device_id == PCI_DEVICE_ID_INTEL_82371AB_0)) {
+ device_id == PCI_DEVICE_ID_INTEL_82371AB_0 ||
+ device_id == PCI_DEVICE_ID_INTEL_874079 ||
+ device_id == PCI_DEVICE_ID_INTEL_945GL)) {
int i, irq;
uint8_t elcr[2];
@@ -854,8 +861,9 @@ static void pci_bios_init_device(PCIDevi
case 0x0101:
if (vendor_id == PCI_VENDOR_ID_INTEL &&
(device_id == PCI_DEVICE_ID_INTEL_82371SB_1 ||
- device_id == PCI_DEVICE_ID_INTEL_82371AB)) {
- /* PIIX3/PIIX4 IDE */
+ device_id == PCI_DEVICE_ID_INTEL_82371AB ||
+ device_id == PCI_DEVICE_ID_INTEL_ICH6IDE)) {
+ /* PIIX3/PIIX4/ICH6 IDE */
pci_config_writew(d, 0x40, 0x8000); // enable IDE0
pci_config_writew(d, 0x42, 0x8000); // enable IDE1
goto default_map;
@@ -1559,6 +1567,13 @@ void acpi_bios_init(void)
acpi_build_table_header((struct acpi_table_header *)madt,
"APIC", madt_size, 1);
}
+ /* PBLK (CPU information structure) */
+ {
+ uint32_t *pblk = (void*) (0x410);
+ *pblk = 0;
+ ((char*)pblk)[4] = 64; /* size of the Level 2 cache */
+ ((char*)pblk)[5] = 0; /* size of the Level 3 cache */
+ }
}
/* SMBIOS entry point -- must be written to a 16-bit aligned address

View File

@@ -0,0 +1,13 @@
Index: kvm-77/kernel/x86/preempt.c
===================================================================
--- kvm-77.orig/kernel/x86/preempt.c
+++ kvm-77/kernel/x86/preempt.c
@@ -251,7 +251,7 @@ void preempt_notifier_sys_exit(void)
struct idt_desc idt_desc;
dprintk("\n");
- on_each_cpu(do_disable, NULL, 1, 1);
+ kvm_on_each_cpu(do_disable, NULL, 1);
asm ("sidt %0" : "=m"(idt_desc));
idt_desc.gates[1] = orig_int1_gate;
}

View File

@@ -0,0 +1,8 @@
--- a/user/test/x86/vmexit.c
+++ b/user/test/x86/vmexit.c
@@ -1,4 +1,4 @@
-
+int printf(const char *,...);
#include "printf.h"
static inline unsigned long long rdtsc()

View File

@@ -0,0 +1,130 @@
# Fixes boot with gfxboot of SUSE 10.0 till openSUSE 10.3 and other
# distributions which use this version of gfxboot.
# Has been discussed upstream, but upstream does not seem to care
# much and wants to go for full emulation of this, but it's a project
# for multible months to do that.
# Room for improvement: Should use an explicitly defined illegal
# instruction, not just one which happens to be illegal with current
# CPUs.
# Signed-off-by: Alex Graf - agraf@suse
===================================================================
Index: kernel/include/asm-x86/kvm_host.h
===================================================================
--- kernel/include/asm-x86/kvm_host.h.orig
+++ kernel/include/asm-x86/kvm_host.h
@@ -240,6 +240,7 @@ struct kvm_vcpu_arch {
u32 regs_avail;
u32 regs_dirty;
+ u16 backup_ss;
unsigned long cr0;
unsigned long cr2;
unsigned long cr3;
Index: kernel/x86/vmx.c
===================================================================
--- kernel/x86/vmx.c.orig
+++ kernel/x86/vmx.c
@@ -1301,8 +1301,10 @@ static void fix_pmode_dataseg(int seg, s
static void enter_pmode(struct kvm_vcpu *vcpu)
{
unsigned long flags;
+ unsigned long rip;
+ u8 opcodes[2];
struct vcpu_vmx *vmx = to_vmx(vcpu);
-
+
vmx->emulation_required = 1;
vcpu->arch.rmode.active = 0;
@@ -1328,12 +1330,39 @@ static void enter_pmode(struct kvm_vcpu
fix_pmode_dataseg(VCPU_SREG_GS, &vcpu->arch.rmode.gs);
fix_pmode_dataseg(VCPU_SREG_FS, &vcpu->arch.rmode.fs);
+ /* Save real mode SS */
+ vcpu->arch.backup_ss = vmcs_read16(GUEST_SS_SELECTOR);
+
vmcs_write16(GUEST_SS_SELECTOR, 0);
vmcs_write32(GUEST_SS_AR_BYTES, 0x93);
vmcs_write16(GUEST_CS_SELECTOR,
vmcs_read16(GUEST_CS_SELECTOR) & ~SELECTOR_RPL_MASK);
vmcs_write32(GUEST_CS_AR_BYTES, 0x9b);
+
+ /* VMX checks for SS.CPL = CS.CPL on VM entry, if we are in
+ * protected mode. This fails on the transistion from real mode
+ * to protected mode, as just after that, SS still contains the
+ * real mode segment, which does not know anything about CPLs.
+ *
+ * As far as I know only gfxboot exploits this feature, by using
+ * the old real mode SS value to find a new SS selector in protected
+ * mode. This happens using a mov %ss, %eax instruction, which we
+ * can patch to an invalid opcode and emulate later on, giving eax
+ * the real SS value, that existed before the protected mode
+ * switch. */
+ rip = kvm_rip_read(vcpu) + vmcs_readl(GUEST_CS_BASE) + 14;
+ emulator_read_std(rip, (void *)opcodes, 2, vcpu);
+
+ if ( opcodes[0] == 0x8c && opcodes[1] == 0xd0 ) {
+ vcpu_printf(vcpu, "%s: patching mov SS\n", __FUNCTION__);
+ opcodes[0] = 0x0f;
+ opcodes[1] = 0x0c;
+ if (emulator_write_emulated(rip, opcodes,
+ 2, vcpu) != X86EMUL_CONTINUE)
+ vcpu_printf(vcpu, "%s: unable to patch mov SS\n",
+ __FUNCTION__);
+ }
}
static gva_t rmode_tss_base(struct kvm *kvm)
Index: kernel/x86/x86.c
===================================================================
--- kernel/x86/x86.c.orig
+++ kernel/x86/x86.c
@@ -2444,13 +2444,14 @@ int emulate_instruction(struct kvm_vcpu
r = x86_decode_insn(&vcpu->arch.emulate_ctxt, &emulate_ops);
- /* Reject the instructions other than VMCALL/VMMCALL when
+ /* Reject the instructions other than VMCALL/VMMCALL/HACKS when
* try to emulate invalid opcode */
c = &vcpu->arch.emulate_ctxt.decode;
if ((emulation_type & EMULTYPE_TRAP_UD) &&
- (!(c->twobyte && c->b == 0x01 &&
+ ((!(c->twobyte && c->b == 0x01 &&
(c->modrm_reg == 0 || c->modrm_reg == 3) &&
- c->modrm_mod == 3 && c->modrm_rm == 1)))
+ c->modrm_mod == 3 && c->modrm_rm == 1)) &&
+ c->b != 0x0c))
return EMULATE_FAIL;
++vcpu->stat.insn_emulation;
Index: kernel/x86/x86_emulate.c
===================================================================
--- kernel/x86/x86_emulate.c.orig
+++ kernel/x86/x86_emulate.c
@@ -196,7 +196,7 @@ static u16 opcode_table[256] = {
static u16 twobyte_table[256] = {
/* 0x00 - 0x0F */
0, Group | GroupDual | Group7, 0, 0, 0, 0, ImplicitOps, 0,
- ImplicitOps, ImplicitOps, 0, 0, 0, ImplicitOps | ModRM, 0, 0,
+ ImplicitOps, ImplicitOps, 0, 0, ImplicitOps, ImplicitOps | ModRM, 0, 0,
/* 0x10 - 0x1F */
0, 0, 0, 0, 0, 0, 0, 0, ImplicitOps | ModRM, 0, 0, 0, 0, 0, 0, 0,
/* 0x20 - 0x2F */
@@ -1898,6 +1898,16 @@ twobyte_insn:
case 0x18: /* Grp16 (prefetch/nop) */
c->dst.type = OP_NONE;
break;
+ case 0x0c: /* Invalid (used to patch mov %ss, %eax) */
+ /* This opcode is declared invalid, according to the Intel
+ * specification. As it is only used on VMX, we do not have
+ * to take AMD instructions into account. For more
+ * information, why this is needed, please see
+ * vmx.c:enter_pmode.
+ */
+ c->dst.type = OP_NONE;
+ c->regs[VCPU_REGS_RAX] = ctxt->vcpu->arch.backup_ss;
+ break;
case 0x20: /* mov cr, reg */
if (c->modrm_mod != 3)
goto cannot_emulate;

View File

@@ -0,0 +1,14 @@
Index: kvm-75/kernel/x86/ioapic.c
===================================================================
--- kvm-75.orig/kernel/x86/ioapic.c
+++ kvm-75/kernel/x86/ioapic.c
@@ -274,7 +274,8 @@ void kvm_ioapic_set_irq(struct kvm_ioapi
if (irq >= 0 && irq < IOAPIC_NUM_PINS) {
entry = ioapic->redirtbl[irq];
- level ^= entry.fields.polarity;
+// polarity is always active high in qemu
+// level ^= entry.fields.polarity;
if (!level)
ioapic->irr &= ~mask;
else {

View File

@@ -0,0 +1,35 @@
# Quick patch until proper version is upstream, but is safe.
# Signed-off-by: Alex Graf - agraf@suse
Index: kvm-75/kernel/x86/x86.c
===================================================================
--- kvm-75.orig/kernel/x86/x86.c
+++ kvm-75/kernel/x86/x86.c
@@ -1260,7 +1260,7 @@ static int kvm_vcpu_ioctl_set_cpuid(stru
struct kvm_cpuid *cpuid,
struct kvm_cpuid_entry *entries)
{
- int r, i;
+ int r, i, n = 0;
struct kvm_cpuid_entry *cpuid_entries;
r = -E2BIG;
@@ -1280,8 +1280,17 @@ static int kvm_vcpu_ioctl_set_cpuid(stru
vcpu->arch.cpuid_entries[i].ebx = cpuid_entries[i].ebx;
vcpu->arch.cpuid_entries[i].ecx = cpuid_entries[i].ecx;
vcpu->arch.cpuid_entries[i].edx = cpuid_entries[i].edx;
- vcpu->arch.cpuid_entries[i].index = 0;
- vcpu->arch.cpuid_entries[i].flags = 0;
+ switch(vcpu->arch.cpuid_entries[i].function) {
+ case 4:
+ vcpu->arch.cpuid_entries[i].index = n;
+ vcpu->arch.cpuid_entries[i].flags = KVM_CPUID_FLAG_SIGNIFCANT_INDEX;
+ n++;
+ break;
+ default:
+ vcpu->arch.cpuid_entries[i].index = 0;
+ vcpu->arch.cpuid_entries[i].flags = 0;
+ break;
+ }
vcpu->arch.cpuid_entries[i].padding[0] = 0;
vcpu->arch.cpuid_entries[i].padding[1] = 0;
vcpu->arch.cpuid_entries[i].padding[2] = 0;

View File

@@ -0,0 +1,27 @@
Index: kvm-75/kernel/x86/x86.c
===================================================================
--- kvm-75.orig/kernel/x86/x86.c
+++ kvm-75/kernel/x86/x86.c
@@ -874,7 +874,11 @@ static int set_msr_mtrr(struct kvm_vcpu
int kvm_set_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 data)
{
+printk(KERN_INFO "MSR write: 0x%lx = 0x%llx\n", msr, data);
switch (msr) {
+ case 0xe2:
+ printk(KERN_INFO "CState MSR write: 0x%llx\n", data);
+ break;
case MSR_EFER:
set_efer(vcpu, data);
break;
@@ -1025,6 +1029,10 @@ int kvm_get_msr_common(struct kvm_vcpu *
case MSR_EFER:
data = vcpu->arch.shadow_efer;
break;
+ case 0xe2:
+ printk(KERN_INFO "CState MSR read: 0x0\n");
+ data = 0;
+ break;
case MSR_KVM_WALL_CLOCK:
data = vcpu->kvm->arch.wall_clock;
break;

View File

@@ -0,0 +1,21 @@
Index: kvm-75/qemu/qemu-kvm-x86.c
===================================================================
--- kvm-75.orig/qemu/qemu-kvm-x86.c
+++ kvm-75/qemu/qemu-kvm-x86.c
@@ -11,6 +11,7 @@
#include <string.h>
#include "hw/hw.h"
+#include "hw/boards.h"
#include "qemu-kvm.h"
#include <libkvm.h>
@@ -498,7 +499,7 @@ static void do_cpuid_ent(struct kvm_cpui
// isn't supported in compatibility mode on Intel. so advertise the
// actuall cpu, and say goodbye to migration between different vendors
// is you use compatibility mode.
- if (function == 0) {
+ if (function == 0 && current_machine != &mac_machine) {
uint32_t bcd[3];
host_cpuid(0, NULL, &bcd[0], &bcd[1], &bcd[2]);

View File

@@ -0,0 +1,44 @@
Index: kvm-75/kernel/x86/svm.c
===================================================================
--- kvm-75.orig/kernel/x86/svm.c
+++ kvm-75/kernel/x86/svm.c
@@ -50,12 +50,8 @@ MODULE_LICENSE("GPL");
#define DEBUGCTL_RESERVED_BITS (~(0x3fULL))
/* enable NPT for AMD64 and X86 with PAE */
-#if defined(CONFIG_X86_64) || defined(CONFIG_X86_PAE)
-static bool npt_enabled = true;
-#else
static bool npt_enabled = false;
-#endif
-static int npt = 1;
+static int npt = 0;
module_param(npt, int, S_IRUGO);
@@ -439,19 +435,19 @@ static __init int svm_hardware_setup(voi
svm_features = cpuid_edx(SVM_CPUID_FUNC);
- if (!svm_has(SVM_FEATURE_NPT))
- npt_enabled = false;
+ if (npt)
+ npt_enabled = true;
- if (npt_enabled && !npt) {
- printk(KERN_INFO "kvm: Nested Paging disabled\n");
+ if (!svm_has(SVM_FEATURE_NPT))
npt_enabled = false;
- }
if (npt_enabled) {
printk(KERN_INFO "kvm: Nested Paging enabled\n");
kvm_enable_tdp();
- } else
+ } else {
+ printk(KERN_INFO "kvm: Nested Paging disabled\n");
kvm_disable_tdp();
+ }
return 0;

View File

@@ -0,0 +1,62 @@
From: "Marcel Zumstein" <marcel.zumstein@oxinia.ch>
Subject: [Qemu-devel] AltGr and dead keys with VNC
In VNC mode, my AltGr key (mapped to ISO_Level3_Shift) and the dead keys
aren't supported. This patch adds XK_ISO_Level3_Shift (keysym 0xfe03) to
the keymap. Furthermore, it adds support for the dead keys, which were
for some reason present in the keymaps, but not in vnc_keysym.h. This is
relevant for VNC viewers that pass dead keys on to the guest system
(e.g. tightvnc does) and don't compose the accented letters themselves.
Index: qemu/keymaps/modifiers
===================================================================
--- qemu/keymaps/modifiers.orig
+++ qemu/keymaps/modifiers
@@ -3,6 +3,7 @@ Shift_L 0x2a
Alt_R 0xb8
Mode_switch 0xb8
+ISO_Level3_Shift 0xb8
Alt_L 0x38
Control_R 0x9d
Index: qemu/vnc_keysym.h
===================================================================
--- qemu/vnc_keysym.h.orig
+++ qemu/vnc_keysym.h
@@ -204,6 +204,7 @@ static const name2keysym_t name2keysym[]
{"EuroSign", 0x20ac}, /* XK_EuroSign */
/* modifiers */
+{"ISO_Level3_Shift", 0xfe03}, /* XK_ISO_Level3_Shift */
{"Control_L", 0xffe3}, /* XK_Control_L */
{"Control_R", 0xffe4}, /* XK_Control_R */
{"Alt_L", 0xffe9}, /* XK_Alt_L */
@@ -286,6 +287,27 @@ static const name2keysym_t name2keysym[]
{"Pause", 0xff13}, /* XK_Pause */
{"Escape", 0xff1b}, /* XK_Escape */
+/* dead keys */
+{"dead_grave", 0xfe50}, /* XK_dead_grave */
+{"dead_acute", 0xfe51}, /* XK_dead_acute */
+{"dead_circumflex", 0xfe52}, /* XK_dead_circumflex */
+{"dead_tilde", 0xfe53}, /* XK_dead_tilde */
+{"dead_macron", 0xfe54}, /* XK_dead_macron */
+{"dead_breve", 0xfe55}, /* XK_dead_breve */
+{"dead_abovedot", 0xfe56}, /* XK_dead_abovedot */
+{"dead_diaeresis", 0xfe57}, /* XK_dead_diaeresis */
+{"dead_abovering", 0xfe58}, /* XK_dead_abovering */
+{"dead_doubleacute", 0xfe59}, /* XK_dead_doubleacute */
+{"dead_caron", 0xfe5a}, /* XK_dead_caron */
+{"dead_cedilla", 0xfe5b}, /* XK_dead_cedilla */
+{"dead_ogonek", 0xfe5c}, /* XK_dead_ogonek */
+{"dead_iota", 0xfe5d}, /* XK_dead_iota */
+{"dead_voiced_sound", 0xfe5e}, /* XK_dead_voiced_sound */
+{"dead_semivoiced_sound", 0xfe5f}, /* XK_dead_semivoiced_sound */
+{"dead_belowdot", 0xfe60}, /* XK_dead_belowdot */
+{"dead_hook", 0xfe61}, /* XK_dead_hook */
+{"dead_horn", 0xfe62}, /* XK_dead_horn */
+
/* localized keys */
{"BackApostrophe", 0xff21},
{"Muhenkan", 0xff22},

View File

@@ -0,0 +1,545 @@
From 3be490091c2503d8b50f4a0ce1efe68004f65d3e Mon Sep 17 00:00:00 2001
From: Alexander Graf <agraf@suse.de>
Date: Tue, 4 Nov 2008 18:48:21 +0100
Subject: [PATCH] Activate Virtualization On Demand v3
X86 CPUs need to have some magic happening to enable the virtualization
extensions on them. This magic can result in unpleasant results for
users, like blocking other VMMs from working (vmx) or using invalid TLB
entries (svm).
Currently KVM activates virtualization when the respective kernel module
is loaded. This blocks us from autoloading KVM modules without breaking
other VMMs.
To circumvent this problem at least a bit, this patch introduces on
demand activation of virtualization. This means, that instead
virtualization is enabled on creation of the first virtual machine
and disabled on removal of the last one.
So using this, KVM can be easily autoloaded, while keeping other
hypervisors usable.
v2 adds returns to non-x86 hardware_enables and adds IA64 change
v3 changes:
- use spin_lock instead of atomics
- put locking to new functions hardware_{en,dis}able_all that get called
on VM creation/destruction
- remove usage counter checks where not necessary
- return -EINVAL for IA64 slot < 0 case
Signed-off-by: Alexander Graf <agraf@suse.de>
---
arch/ia64/kvm/kvm-ia64.c | 8 +++--
arch/powerpc/kvm/powerpc.c | 3 +-
arch/s390/kvm/kvm-s390.c | 3 +-
kernel/x86/svm.c | 13 +++++--
kernel/x86/vmx.c | 7 +++-
kernel/x86/x86.c | 4 +-
kernel/include/asm-x86/kvm_host.h | 2 +-
kernel/include/linux/kvm_host.h | 2 +-
virt/kvm/kvm_main.c | 75 ++++++++++++++++++++++++++++++++++++-------
9 files changed, 90 insertions(+), 27 deletions(-)
Index: kvm-78/kernel/ia64/kvm-ia64.c
===================================================================
--- kvm-78.orig/kernel/ia64/kvm-ia64.c
+++ kvm-78/kernel/ia64/kvm-ia64.c
@@ -138,7 +138,7 @@ long ia64_pal_vp_create(u64 *vpd, u64 *h
static DEFINE_SPINLOCK(vp_lock);
-void kvm_arch_hardware_enable(void *garbage)
+int kvm_arch_hardware_enable(void *garbage)
{
long status;
long tmp_base;
@@ -152,7 +152,7 @@ void kvm_arch_hardware_enable(void *garb
slot = ia64_itr_entry(0x3, KVM_VMM_BASE, pte, KVM_VMM_SHIFT);
local_irq_restore(saved_psr);
if (slot < 0)
- return;
+ return -EINVAL;
spin_lock(&vp_lock);
status = ia64_pal_vp_init_env(kvm_vsa_base ?
@@ -160,7 +160,7 @@ void kvm_arch_hardware_enable(void *garb
__pa(kvm_vm_buffer), KVM_VM_BUFFER_BASE, &tmp_base);
if (status != 0) {
printk(KERN_WARNING"kvm: Failed to Enable VT Support!!!!\n");
- return ;
+ return -EINVAL;
}
if (!kvm_vsa_base) {
@@ -169,6 +169,8 @@ void kvm_arch_hardware_enable(void *garb
}
spin_unlock(&vp_lock);
ia64_ptr_entry(0x3, slot);
+
+ return 0;
}
void kvm_arch_hardware_disable(void *garbage)
Index: kvm-78/kernel/x86/svm.c
===================================================================
--- kvm-78.orig/kernel/x86/svm.c
+++ kvm-78/kernel/x86/svm.c
@@ -300,7 +300,7 @@ static void svm_hardware_disable(void *g
wrmsrl(MSR_EFER, efer & ~MSR_EFER_SVME_MASK);
}
-static void svm_hardware_enable(void *garbage)
+static int svm_hardware_enable(void *garbage)
{
struct svm_cpu_data *svm_data;
@@ -309,16 +309,20 @@ static void svm_hardware_enable(void *ga
struct kvm_desc_struct *gdt;
int me = raw_smp_processor_id();
+ rdmsrl(MSR_EFER, efer);
+ if (efer & MSR_EFER_SVME_MASK)
+ return -EBUSY;
+
if (!has_svm()) {
printk(KERN_ERR "svm_cpu_init: err EOPNOTSUPP on %d\n", me);
- return;
+ return -EINVAL;
}
svm_data = per_cpu(svm_data, me);
if (!svm_data) {
printk(KERN_ERR "svm_cpu_init: svm_data is NULL on %d\n",
me);
- return;
+ return -EINVAL;
}
svm_data->asid_generation = 1;
@@ -329,11 +333,12 @@ static void svm_hardware_enable(void *ga
gdt = (struct kvm_desc_struct *)gdt_descr.address;
svm_data->tss_desc = (struct kvm_ldttss_desc *)(gdt + GDT_ENTRY_TSS);
- rdmsrl(MSR_EFER, efer);
wrmsrl(MSR_EFER, efer | MSR_EFER_SVME_MASK);
wrmsrl(MSR_VM_HSAVE_PA,
page_to_pfn(svm_data->save_area) << PAGE_SHIFT);
+
+ return 0;
}
static void svm_cpu_uninit(int cpu)
Index: kvm-78/kernel/x86/vmx.c
===================================================================
--- kvm-78.orig/kernel/x86/vmx.c
+++ kvm-78/kernel/x86/vmx.c
@@ -1090,12 +1090,15 @@ static __init int vmx_disabled_by_bios(v
/* locked but not enabled */
}
-static void hardware_enable(void *garbage)
+static int hardware_enable(void *garbage)
{
int cpu = raw_smp_processor_id();
u64 phys_addr = __pa(per_cpu(vmxarea, cpu));
u64 old;
+ if (read_cr4() & X86_CR4_VMXE)
+ return -EBUSY;
+
INIT_LIST_HEAD(&per_cpu(vcpus_on_cpu, cpu));
rdmsrl(MSR_IA32_FEATURE_CONTROL, old);
if ((old & (FEATURE_CONTROL_LOCKED |
@@ -1110,6 +1113,8 @@ static void hardware_enable(void *garbag
asm volatile (ASM_VMX_VMXON_RAX
: : "a"(&phys_addr), "m"(phys_addr)
: "memory", "cc");
+
+ return 0;
}
static void vmclear_local_vcpus(void)
Index: kvm-78/kernel/x86/x86.c
===================================================================
--- kvm-78.orig/kernel/x86/x86.c
+++ kvm-78/kernel/x86/x86.c
@@ -4077,9 +4077,9 @@ int kvm_arch_vcpu_reset(struct kvm_vcpu
return kvm_x86_ops->vcpu_reset(vcpu);
}
-void kvm_arch_hardware_enable(void *garbage)
+int kvm_arch_hardware_enable(void *garbage)
{
- kvm_x86_ops->hardware_enable(garbage);
+ return kvm_x86_ops->hardware_enable(garbage);
}
void kvm_arch_hardware_disable(void *garbage)
Index: kvm-78/kernel/include/asm-x86/kvm_host.h
===================================================================
--- kvm-78.orig/kernel/include/asm-x86/kvm_host.h
+++ kvm-78/kernel/include/asm-x86/kvm_host.h
@@ -453,7 +453,7 @@ struct descriptor_table {
struct kvm_x86_ops {
int (*cpu_has_kvm_support)(void); /* __init */
int (*disabled_by_bios)(void); /* __init */
- void (*hardware_enable)(void *dummy); /* __init */
+ int (*hardware_enable)(void *dummy); /* __init */
void (*hardware_disable)(void *dummy);
void (*check_processor_compatibility)(void *rtn);
int (*hardware_setup)(void); /* __init */
Index: kvm-78/kernel/include/linux/kvm_host.h
===================================================================
--- kvm-78.orig/kernel/include/linux/kvm_host.h
+++ kvm-78/kernel/include/linux/kvm_host.h
@@ -300,7 +300,7 @@ int kvm_arch_vcpu_setup(struct kvm_vcpu
void kvm_arch_vcpu_destroy(struct kvm_vcpu *vcpu);
int kvm_arch_vcpu_reset(struct kvm_vcpu *vcpu);
-void kvm_arch_hardware_enable(void *garbage);
+int kvm_arch_hardware_enable(void *garbage);
void kvm_arch_hardware_disable(void *garbage);
int kvm_arch_hardware_setup(void);
void kvm_arch_hardware_unsetup(void);
Index: kvm-78/kernel/x86/kvm_main.c
===================================================================
--- kvm-78.orig/kernel/x86/kvm_main.c
+++ kvm-78/kernel/x86/kvm_main.c
@@ -93,6 +93,8 @@ DEFINE_SPINLOCK(kvm_lock);
LIST_HEAD(vm_list);
static cpumask_t cpus_hardware_enabled;
+static int kvm_usage_count = 0;
+static DEFINE_SPINLOCK(kvm_usage_lock);
struct kmem_cache *kvm_vcpu_cache;
EXPORT_SYMBOL_GPL(kvm_vcpu_cache);
@@ -103,6 +105,8 @@ struct dentry *kvm_debugfs_dir;
static long kvm_vcpu_ioctl(struct file *file, unsigned int ioctl,
unsigned long arg);
+static int hardware_enable_all(void);
+static void hardware_disable_all(void);
bool kvm_rebooting;
@@ -592,19 +596,25 @@ static const struct mmu_notifier_ops kvm
static struct kvm *kvm_create_vm(void)
{
+ int r = 0;
struct kvm *kvm = kvm_arch_create_vm();
#ifdef KVM_COALESCED_MMIO_PAGE_OFFSET
struct page *page;
#endif
if (IS_ERR(kvm))
- goto out;
+ return kvm;
+
+ r = hardware_enable_all();
+ if (r) {
+ goto out_err;
+ }
#ifdef KVM_COALESCED_MMIO_PAGE_OFFSET
page = alloc_page(GFP_KERNEL | __GFP_ZERO);
if (!page) {
- kfree(kvm);
- return ERR_PTR(-ENOMEM);
+ r = -ENOMEM;
+ goto out_err;
}
kvm->coalesced_mmio_ring =
(struct kvm_coalesced_mmio_ring *)page_address(page);
@@ -612,15 +622,13 @@ static struct kvm *kvm_create_vm(void)
#if defined(CONFIG_MMU_NOTIFIER) && defined(KVM_ARCH_WANT_MMU_NOTIFIER)
{
- int err;
kvm->mmu_notifier.ops = &kvm_mmu_notifier_ops;
- err = mmu_notifier_register(&kvm->mmu_notifier, current->mm);
- if (err) {
+ r = mmu_notifier_register(&kvm->mmu_notifier, current->mm);
+ if (r) {
#ifdef KVM_COALESCED_MMIO_PAGE_OFFSET
put_page(page);
#endif
- kfree(kvm);
- return ERR_PTR(err);
+ goto out_err;
}
}
#endif
@@ -639,8 +647,12 @@ mmget(&kvm->mm->mm_count);
#ifdef KVM_COALESCED_MMIO_PAGE_OFFSET
kvm_coalesced_mmio_init(kvm);
#endif
-out:
return kvm;
+
+out_err:
+ hardware_disable_all();
+ kfree(kvm);
+ return ERR_PTR(r);
}
/*
@@ -689,6 +701,7 @@ static void kvm_destroy_vm(struct kvm *k
mmu_notifier_unregister(&kvm->mmu_notifier, kvm->mm);
#endif
kvm_arch_destroy_vm(kvm);
+ hardware_disable_all();
mmdrop(mm);
}
@@ -1796,14 +1809,40 @@ static struct miscdevice kvm_dev = {
&kvm_chardev_ops,
};
-static void hardware_enable(void *junk)
+static void hardware_enable(void *_r)
{
int cpu = raw_smp_processor_id();
+ int r;
+
+ /* If enabling a previous CPU failed already, let's not continue */
+ if (_r && *((int*)_r))
+ return;
if (cpu_isset(cpu, cpus_hardware_enabled))
return;
+ r = kvm_arch_hardware_enable(NULL);
+ if (_r)
+ *((int*)_r) = r;
+ if (r) {
+ printk(KERN_INFO "kvm: enabling virtualization on "
+ "CPU%d failed\n", cpu);
+ return;
+ }
+
cpu_set(cpu, cpus_hardware_enabled);
- kvm_arch_hardware_enable(NULL);
+}
+
+static int hardware_enable_all(void)
+{
+ int r = 0;
+
+ spin_lock(&kvm_usage_lock);
+ kvm_usage_count++;
+ if (kvm_usage_count == 1)
+ kvm_on_each_cpu(hardware_enable, &r, 1);
+ spin_unlock(&kvm_usage_lock);
+
+ return r;
}
static void hardware_disable(void *junk)
@@ -1816,6 +1855,18 @@ static void hardware_disable(void *junk)
kvm_arch_hardware_disable(NULL);
}
+static void hardware_disable_all(void)
+{
+ if (!kvm_usage_count)
+ return;
+
+ spin_lock(&kvm_usage_lock);
+ kvm_usage_count--;
+ if (!kvm_usage_count)
+ kvm_on_each_cpu(hardware_disable, NULL, 1);
+ spin_unlock(&kvm_usage_lock);
+}
+
static int kvm_cpu_hotplug(struct notifier_block *notifier, unsigned long val,
void *v)
{
@@ -2061,7 +2112,6 @@ int kvm_init(void *opaque, unsigned int
goto out_free_1;
}
- kvm_on_each_cpu(hardware_enable, NULL, 1);
r = register_cpu_notifier(&kvm_cpu_notifier);
if (r)
goto out_free_2;
@@ -2114,7 +2164,6 @@ out_free_3:
unregister_reboot_notifier(&kvm_reboot_notifier);
unregister_cpu_notifier(&kvm_cpu_notifier);
out_free_2:
- kvm_on_each_cpu(hardware_disable, NULL, 1);
out_free_1:
kvm_arch_hardware_unsetup();
out_free_0:
Index: kvm-78/kernel/ia64/kvm_main.c
===================================================================
--- kvm-78.orig/kernel/ia64/kvm_main.c
+++ kvm-78/kernel/ia64/kvm_main.c
@@ -93,6 +93,8 @@ DEFINE_SPINLOCK(kvm_lock);
LIST_HEAD(vm_list);
static cpumask_t cpus_hardware_enabled;
+static int kvm_usage_count = 0;
+static DEFINE_SPINLOCK(kvm_usage_lock);
struct kmem_cache *kvm_vcpu_cache;
EXPORT_SYMBOL_GPL(kvm_vcpu_cache);
@@ -103,6 +105,8 @@ struct dentry *kvm_debugfs_dir;
static long kvm_vcpu_ioctl(struct file *file, unsigned int ioctl,
unsigned long arg);
+static int hardware_enable_all(void);
+static void hardware_disable_all(void);
bool kvm_rebooting;
@@ -592,19 +596,25 @@ static const struct mmu_notifier_ops kvm
static struct kvm *kvm_create_vm(void)
{
+ int r = 0;
struct kvm *kvm = kvm_arch_create_vm();
#ifdef KVM_COALESCED_MMIO_PAGE_OFFSET
struct page *page;
#endif
if (IS_ERR(kvm))
- goto out;
+ return kvm;
+
+ r = hardware_enable_all();
+ if (r) {
+ goto out_err;
+ }
#ifdef KVM_COALESCED_MMIO_PAGE_OFFSET
page = alloc_page(GFP_KERNEL | __GFP_ZERO);
if (!page) {
- kfree(kvm);
- return ERR_PTR(-ENOMEM);
+ r = -ENOMEM;
+ goto out_err;
}
kvm->coalesced_mmio_ring =
(struct kvm_coalesced_mmio_ring *)page_address(page);
@@ -612,15 +622,13 @@ static struct kvm *kvm_create_vm(void)
#if defined(CONFIG_MMU_NOTIFIER) && defined(KVM_ARCH_WANT_MMU_NOTIFIER)
{
- int err;
kvm->mmu_notifier.ops = &kvm_mmu_notifier_ops;
- err = mmu_notifier_register(&kvm->mmu_notifier, current->mm);
- if (err) {
+ r = mmu_notifier_register(&kvm->mmu_notifier, current->mm);
+ if (r) {
#ifdef KVM_COALESCED_MMIO_PAGE_OFFSET
put_page(page);
#endif
- kfree(kvm);
- return ERR_PTR(err);
+ goto out_err;
}
}
#endif
@@ -639,8 +647,12 @@ static struct kvm *kvm_create_vm(void)
#ifdef KVM_COALESCED_MMIO_PAGE_OFFSET
kvm_coalesced_mmio_init(kvm);
#endif
-out:
return kvm;
+
+out_err:
+ hardware_disable_all();
+ kfree(kvm);
+ return ERR_PTR(r);
}
/*
@@ -689,6 +701,7 @@ static void kvm_destroy_vm(struct kvm *k
mmu_notifier_unregister(&kvm->mmu_notifier, kvm->mm);
#endif
kvm_arch_destroy_vm(kvm);
+ hardware_disable_all();
mmdrop(mm);
}
@@ -1796,14 +1809,40 @@ static struct miscdevice kvm_dev = {
&kvm_chardev_ops,
};
-static void hardware_enable(void *junk)
+static void hardware_enable(void *_r)
{
int cpu = raw_smp_processor_id();
+ int r;
+
+ /* If enabling a previous CPU failed already, let's not continue */
+ if (_r && *((int*)_r))
+ return;
if (cpu_isset(cpu, cpus_hardware_enabled))
return;
+ r = kvm_arch_hardware_enable(NULL);
+ if (_r)
+ *((int*)_r) = r;
+ if (r) {
+ printk(KERN_INFO "kvm: enabling virtualization on "
+ "CPU%d failed\n", cpu);
+ return;
+ }
+
cpu_set(cpu, cpus_hardware_enabled);
- kvm_arch_hardware_enable(NULL);
+}
+
+static int hardware_enable_all(void)
+{
+ int r = 0;
+
+ spin_lock(&kvm_usage_lock);
+ kvm_usage_count++;
+ if (kvm_usage_count == 1)
+ on_each_cpu(hardware_enable, &r, 1);
+ spin_unlock(&kvm_usage_lock);
+
+ return r;
}
static void hardware_disable(void *junk)
@@ -1816,6 +1855,18 @@ static void hardware_disable(void *junk)
kvm_arch_hardware_disable(NULL);
}
+static void hardware_disable_all(void)
+{
+ if (!kvm_usage_count)
+ return;
+
+ spin_lock(&kvm_usage_lock);
+ kvm_usage_count--;
+ if (!kvm_usage_count)
+ on_each_cpu(hardware_disable, NULL, 1);
+ spin_unlock(&kvm_usage_lock);
+}
+
static int kvm_cpu_hotplug(struct notifier_block *notifier, unsigned long val,
void *v)
{
@@ -2058,7 +2109,6 @@ int kvm_init(void *opaque, unsigned int
goto out_free_1;
}
- kvm_on_each_cpu(hardware_enable, NULL, 1);
r = register_cpu_notifier(&kvm_cpu_notifier);
if (r)
goto out_free_2;
@@ -2104,7 +2154,6 @@ out_free_3:
unregister_reboot_notifier(&kvm_reboot_notifier);
unregister_cpu_notifier(&kvm_cpu_notifier);
out_free_2:
- kvm_on_each_cpu(hardware_disable, NULL, 1);
out_free_1:
kvm_arch_hardware_unsetup();
out_free_0:

View File

@@ -0,0 +1,243 @@
#qemu-only -> submit upstream qemu
Index: kvm-75/qemu/Makefile.target
===================================================================
--- kvm-75.orig/qemu/Makefile.target
+++ kvm-75/qemu/Makefile.target
@@ -610,7 +610,7 @@ ifeq ($(TARGET_BASE_ARCH), i386)
OBJS+= ide.o pckbd.o ps2.o vga.o $(SOUND_HW) dma.o
OBJS+= fdc.o mc146818rtc.o serial.o i8259.o i8254.o pcspk.o pc.o
OBJS+= cirrus_vga.o apic.o parallel.o acpi.o piix_pci.o
-OBJS+= usb-uhci.o vmmouse.o vmport.o vmware_vga.o extboot.o hpet.o lpc.o
+OBJS+= usb-uhci.o vmmouse.o vmport.o vmware_vga.o extboot.o hpet.o lpc.o applesmc.o
ifeq ($(USE_KVM_PIT), 1)
OBJS+= i8254-kvm.o
endif
Index: kvm-75/qemu/hw/applesmc.c
===================================================================
--- /dev/null
+++ kvm-75/qemu/hw/applesmc.c
@@ -0,0 +1,171 @@
+/*
+ * Apple SMC controller
+ *
+ * Copyright (c) 2007 Alexander Graf
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * *****************************************************************
+ *
+ * In all Intel-based Apple hardware there is an SMC chip to control the
+ * backlight, fans and several other generic device parameters. It also
+ * contains the magic keys used to dongle Mac OS X to the device.
+ *
+ * This driver was mostly created by looking at the Linux AppleSMC driver
+ * implementation and does not support IRQ.
+ *
+ */
+
+#include "hw.h"
+#include "pci.h"
+#include "console.h"
+#include "qemu-timer.h"
+
+/* data port used by Apple SMC */
+#define APPLESMC_DATA_PORT 0x300
+/* command/status port used by Apple SMC */
+#define APPLESMC_CMD_PORT 0x304
+#define APPLESMC_NR_PORTS 32 /* 0x300-0x31f */
+#define APPLESMC_MAX_DATA_LENGTH 32
+
+#define APPLESMC_READ_CMD 0x10
+#define APPLESMC_WRITE_CMD 0x11
+#define APPLESMC_GET_KEY_BY_INDEX_CMD 0x12
+#define APPLESMC_GET_KEY_TYPE_CMD 0x13
+
+static char osk[64] = "This is a dummy key. Enter the real key using the -osk parameter";
+
+struct AppleSMCData {
+ uint8_t len;
+ char *key;
+ char *data;
+};
+
+static struct AppleSMCData data[] = {
+ { .key = "REV ", .len=6, .data="\0x01\0x13\0x0f\0x00\0x00\0x03" },
+ { .key = "OSK0", .len=32, .data=osk },
+ { .key = "OSK1", .len=32, .data=osk+32 },
+ { .key = "NATJ", .len=1, .data="\0" },
+ { .key = "MSSP", .len=1, .data="\0" },
+ { .key = "MSSD", .len=1, .data="\0x3" },
+ { .len=0 }
+};
+
+struct AppleSMCStatus {
+ uint8_t cmd;
+ uint8_t status;
+ uint8_t key[4];
+ uint8_t read_pos;
+ uint8_t data_len;
+ uint8_t data_pos;
+ uint8_t data[255];
+ uint8_t charactic[4];
+};
+
+static void applesmc_io_cmd_writeb(void *opaque, uint32_t addr, uint32_t val)
+{
+ struct AppleSMCStatus *s = (struct AppleSMCStatus *)opaque;
+ printf("APPLESMC: CMD Write B: %#x = %#x\n", addr, val);
+ switch(val) {
+ case APPLESMC_READ_CMD:
+ s->status = 0x0c;
+ break;
+ }
+ s->cmd = val;
+ s->read_pos = 0;
+ s->data_pos = 0;
+}
+
+static void applesmc_fill_data(struct AppleSMCStatus *s)
+{
+ struct AppleSMCData *d;
+ for(d=data; d->len; d++) {
+ uint32_t key_data = *((uint32_t*)d->key);
+ uint32_t key_current = *((uint32_t*)s->key);
+ if(key_data == key_current) {
+ printf("APPLESMC: Key matched (%s Len=%d Data=%s)\n", d->key, d->len, d->data);
+ memcpy(s->data, d->data, d->len);
+ return;
+ }
+ }
+}
+
+static void applesmc_io_data_writeb(void *opaque, uint32_t addr, uint32_t val)
+{
+ struct AppleSMCStatus *s = (struct AppleSMCStatus *)opaque;
+ printf("APPLESMC: DATA Write B: %#x = %#x\n", addr, val);
+ switch(s->cmd) {
+ case APPLESMC_READ_CMD:
+ if(s->read_pos < 4) {
+ s->key[s->read_pos] = val;
+ s->status = 0x04;
+ } else if(s->read_pos == 4) {
+ s->data_len = val;
+ s->status = 0x05;
+ s->data_pos = 0;
+ printf("APPLESMC: Key = %c%c%c%c Len = %d\n", s->key[0], s->key[1], s->key[2], s->key[3], val);
+ applesmc_fill_data(s);
+ }
+ s->read_pos++;
+ break;
+ }
+}
+
+static uint32_t applesmc_io_data_readb(void *opaque, uint32_t addr1)
+{
+ struct AppleSMCStatus *s = (struct AppleSMCStatus *)opaque;
+ uint8_t retval = 0;
+ switch(s->cmd) {
+ case APPLESMC_READ_CMD:
+ if(s->data_pos < s->data_len) {
+ retval = s->data[s->data_pos];
+ printf("APPLESMC: READ_DATA[%d] = %#hhx\n", s->data_pos, retval);
+ s->data_pos++;
+ if(s->data_pos == s->data_len) {
+ s->status = 0x00;
+ printf("APPLESMC: EOF\n");
+ } else
+ s->status = 0x05;
+ }
+ }
+ printf("APPLESMC: DATA Read b: %#x = %#x\n", addr1, retval);
+ return retval;
+}
+
+static uint32_t applesmc_io_cmd_readb(void *opaque, uint32_t addr1)
+{
+ printf("APPLESMC: CMD Read B: %#x\n", addr1);
+ return ((struct AppleSMCStatus*)opaque)->status;
+}
+
+void applesmc_setkey(char *key) {
+ if(strlen(key) == 64) {
+ memcpy(osk, key, 64);
+ }
+}
+
+void applesmc_init() {
+ struct ApleSMCStatus *s;
+ s = qemu_mallocz(sizeof(struct AppleSMCStatus));
+
+ if(osk[0] == 'T') {
+ printf("WARNING: Using AppleSMC with invalid key\n");
+ }
+ register_ioport_read(APPLESMC_DATA_PORT, 4, 1, applesmc_io_data_readb, s);
+ register_ioport_read(APPLESMC_CMD_PORT, 4, 1, applesmc_io_cmd_readb, s);
+ register_ioport_write(APPLESMC_DATA_PORT, 4, 1, applesmc_io_data_writeb, s);
+ register_ioport_write(APPLESMC_CMD_PORT, 4, 1, applesmc_io_cmd_writeb, s);
+}
+
Index: kvm-75/qemu/hw/pc.h
===================================================================
--- kvm-75.orig/qemu/hw/pc.h
+++ kvm-75/qemu/hw/pc.h
@@ -150,6 +150,10 @@ void pci_piix4_ide_init(PCIBus *bus, Blo
void isa_ne2000_init(int base, qemu_irq irq, NICInfo *nd);
+/* applesmc.c */
+void applesmc_init(void);
+void applesmc_setkey(char *key);
+
/* lpc.c */
void lpc_init(PCIBus *bus, int devfn, qemu_irq *pic);
Index: kvm-75/qemu/vl.c
===================================================================
--- kvm-75.orig/qemu/vl.c
+++ kvm-75/qemu/vl.c
@@ -8381,6 +8381,7 @@ static void help(int exitcode)
#endif
#ifdef TARGET_I386
"-no-fd-bootchk disable boot signature checking for floppy disks\n"
+ "-osk key set AppleSMC key\n"
#endif
"-m megs set virtual RAM size to megs MB [default=%d]\n"
"-smp n set the number of CPUs to 'n' [default=1]\n"
@@ -8547,6 +8548,7 @@ enum {
QEMU_OPTION_snapshot,
#ifdef TARGET_I386
QEMU_OPTION_no_fd_bootchk,
+ QEMU_OPTION_osk,
#endif
QEMU_OPTION_m,
QEMU_OPTION_nographic,
@@ -8648,6 +8650,7 @@ const QEMUOption qemu_options[] = {
{ "snapshot", 0, QEMU_OPTION_snapshot },
#ifdef TARGET_I386
{ "no-fd-bootchk", 0, QEMU_OPTION_no_fd_bootchk },
+ { "osk", HAS_ARG, QEMU_OPTION_osk },
#endif
{ "m", HAS_ARG, QEMU_OPTION_m },
{ "nographic", 0, QEMU_OPTION_nographic },
@@ -9360,6 +9363,9 @@ int main(int argc, char **argv)
case QEMU_OPTION_no_fd_bootchk:
fd_bootchk = 0;
break;
+ case QEMU_OPTION_osk:
+ applesmc_setkey(optarg);
+ break;
#endif
case QEMU_OPTION_net:
if (nb_net_clients >= MAX_NET_CLIENTS) {

View File

@@ -0,0 +1,58 @@
# Quick patch until proper version is upstream, but is safe.
# Signed-off-by: Alex Graf - agraf@suse
Index: kvm-75/qemu/qemu-kvm-x86.c
===================================================================
--- kvm-75.orig/qemu/qemu-kvm-x86.c
+++ kvm-75/qemu/qemu-kvm-x86.c
@@ -465,10 +465,11 @@ static void host_cpuid(uint32_t function
}
-static void do_cpuid_ent(struct kvm_cpuid_entry *e, uint32_t function,
+static void do_cpuid_ent(struct kvm_cpuid_entry *e, uint32_t function, uint32_t index,
CPUState *env)
{
env->regs[R_EAX] = function;
+ env->regs[R_ECX] = index;
qemu_kvm_cpuid_on_env(env);
e->function = function;
e->eax = env->regs[R_EAX];
@@ -554,7 +555,7 @@ int kvm_arch_qemu_init_env(CPUState *cen
#endif
int cpuid_nent = 0;
CPUState copy;
- uint32_t i, limit;
+ uint32_t i, j, limit;
copy = *cenv;
@@ -579,15 +580,26 @@ int kvm_arch_qemu_init_env(CPUState *cen
qemu_kvm_cpuid_on_env(&copy);
limit = copy.regs[R_EAX];
- for (i = 0; i <= limit; ++i)
- do_cpuid_ent(&cpuid_ent[cpuid_nent++], i, &copy);
+ for (i = 0; i <= limit; ++i) {
+ switch(i) {
+ case 4:
+ for(j = 0; ; j++) {
+ do_cpuid_ent(&cpuid_ent[cpuid_nent++], i, j, &copy);
+ if(!copy.regs[R_EAX]) break;
+ }
+ break;
+ default:
+ do_cpuid_ent(&cpuid_ent[cpuid_nent++], i, 0, &copy);
+ break;
+ }
+ }
copy.regs[R_EAX] = 0x80000000;
qemu_kvm_cpuid_on_env(&copy);
limit = copy.regs[R_EAX];
for (i = 0x80000000; i <= limit; ++i)
- do_cpuid_ent(&cpuid_ent[cpuid_nent++], i, &copy);
+ do_cpuid_ent(&cpuid_ent[cpuid_nent++], i, 0, &copy);
kvm_setup_cpuid(kvm_context, cenv->cpu_index, cpuid_nent, cpuid_ent);
return 0;

View File

@@ -0,0 +1,13 @@
Index: kvm-77/qemu/vl.c
===================================================================
--- kvm-77.orig/qemu/vl.c
+++ kvm-77/qemu/vl.c
@@ -162,7 +162,7 @@
#ifdef TARGET_PPC
#define DEFAULT_RAM_SIZE 144
#else
-#define DEFAULT_RAM_SIZE 128
+#define DEFAULT_RAM_SIZE 384
#endif
/* Max number of USB devices that can be specified on the commandline. */

View File

@@ -0,0 +1,341 @@
#qemu-only -> submit upstream qemu
Index: kvm-75/qemu/Makefile.target
===================================================================
--- kvm-75.orig/qemu/Makefile.target
+++ kvm-75/qemu/Makefile.target
@@ -610,7 +610,7 @@ ifeq ($(TARGET_BASE_ARCH), i386)
OBJS+= ide.o pckbd.o ps2.o vga.o $(SOUND_HW) dma.o
OBJS+= fdc.o mc146818rtc.o serial.o i8259.o i8254.o pcspk.o pc.o
OBJS+= cirrus_vga.o apic.o parallel.o acpi.o piix_pci.o
-OBJS+= usb-uhci.o vmmouse.o vmport.o vmware_vga.o extboot.o
+OBJS+= usb-uhci.o vmmouse.o vmport.o vmware_vga.o extboot.o hpet.o
ifeq ($(USE_KVM_PIT), 1)
OBJS+= i8254-kvm.o
endif
Index: kvm-75/qemu/hw/hpet.c
===================================================================
--- /dev/null
+++ kvm-75/qemu/hw/hpet.c
@@ -0,0 +1,322 @@
+/*
+ * High Precisition Event Timer emulation
+ *
+ * Copyright (c) 2007 Alexander Graf
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * *****************************************************************
+ *
+ * This driver attempts to emulate an HPET device in software. It is by no
+ * means complete and is prone to break on certain conditions.
+ *
+ */
+#include "hw.h"
+#include "console.h"
+#include "qemu-timer.h"
+
+#define HPET_DEBUG
+
+#define HPET_BASE 0xfed00000
+
+#define HPET_NUM_TIMERS 3
+#define HPET_TIMER_TYPE_LEVEL 1
+#define HPET_TIMER_TYPE_EDGE 0
+#define HPET_TIMER_DELIVERY_APIC 0
+#define HPET_TIMER_DELIVERY_FSB 1
+#define HPET_TIMER_CAP_FSB_INT_DEL (1 << 15)
+#define HPET_TIMER_CAP_PER_INT (1 << 4)
+
+struct HPETState;
+typedef struct HPETTimer {
+ QEMUTimer *timer;
+ struct HPETState *state;
+ uint8_t type;
+ uint8_t active;
+ uint8_t delivery;
+ uint8_t apic_port;
+ uint8_t periodic;
+ uint8_t enabled;
+ uint32_t comparator; // if(hpet_counter == comparator) IRQ();
+ qemu_irq irq;
+} HPETTimer;
+
+typedef struct HPETState {
+ uint64_t hpet_counter;
+ int64_t next_periodic_time;
+ uint8_t active;
+ qemu_irq *irqs;
+ HPETTimer timer[HPET_NUM_TIMERS];
+} HPETState;
+
+static void update_irq(struct HPETTimer *timer)
+{
+ qemu_set_irq(timer->irq, timer->active && timer->state->active);
+}
+
+static void update_irq_all(struct HPETState *s)
+{
+ int i;
+ for(i=0; i<HPET_NUM_TIMERS; i++)
+ update_irq(&s->timer[i]);
+}
+
+static void hpet_timer(void *opaque)
+{
+ HPETTimer *s = (HPETTimer*)opaque;
+ printf("hpet i!\n");
+ if(s->periodic) {
+ printf("periodic hpet!\n");
+ qemu_mod_timer(s->timer, qemu_get_clock(vm_clock) + ((s->comparator) * (ticks_per_sec * 99) / 100));
+ }
+ s->active = 1;
+ update_irq(s);
+}
+
+static void hpet_check(HPETTimer *s)
+{
+ if(s->enabled) {
+ if(s->periodic)
+ qemu_mod_timer(s->timer, qemu_get_clock(vm_clock) + s->comparator * (ticks_per_sec * 99) / 100);
+ else
+ qemu_mod_timer(s->timer, qemu_get_clock(vm_clock) + ((s->comparator - s->state->hpet_counter) * (ticks_per_sec * 99) / 100));
+ }
+}
+
+static uint32_t hpet_ram_readb(void *opaque, target_phys_addr_t addr)
+{
+#ifdef HPET_DEBUG
+ printf("qemu: hpet_read b at %#lx\n", addr);
+#endif
+ return 10;
+}
+
+static uint32_t hpet_ram_readw(void *opaque, target_phys_addr_t addr)
+{
+#ifdef HPET_DEBUG
+ printf("qemu: hpet_read w at %#lx\n", addr);
+#endif
+ return 10;
+}
+
+static uint32_t hpet_ram_readl(void *opaque, target_phys_addr_t addr)
+{
+ HPETState *s = (HPETState *)opaque;
+#ifdef HPET_DEBUG
+ printf("qemu: hpet_read l at %#lx\n", addr);
+#endif
+ switch(addr - HPET_BASE) {
+ case 0x00:
+ return 0x8086a201;
+ case 0x04:
+ return 0x0429b17f;
+ case 0x10:
+ case 0x14:
+ return 0;
+ case 0xf0:
+ return s->hpet_counter;
+ case 0xf4:
+ return 0;
+ case 0x20:
+ {
+ uint32_t retval = 0;
+ int i;
+ for(i=0; i<HPET_NUM_TIMERS; i++) {
+ if(s->timer[i].type == HPET_TIMER_TYPE_LEVEL)
+ retval |= s->timer[i].active << i;
+ }
+ return retval;
+ }
+ case 0x100 ... 0x3ff:
+ {
+ uint8_t timer_id = (addr - HPET_BASE - 0x100) / 0x20;
+ HPETTimer *timer = &s->timer[timer_id];
+
+ switch((addr - HPET_BASE - 0x100) % 0x20) {
+ case 0x0:
+ return ((timer->delivery == HPET_TIMER_DELIVERY_FSB) << 14)
+ | (timer->apic_port << 9)
+ | HPET_TIMER_CAP_PER_INT
+ | (timer->periodic << 3)
+ | (timer->enabled << 2)
+ | (timer->type << 1);
+ case 0x4: // Interrupt capabilities
+ return 0x00ff;
+ case 0x8: // comparator register
+ return timer->comparator;
+ case 0xc:
+ return 0x0;
+ }
+ }
+ break;
+ }
+
+#ifdef HPET_DEBUG
+ printf("qemu: invalid hpet_read l at %#x\n", addr);
+#endif
+ return 10;
+}
+
+static void hpet_ram_writeb(void *opaque, target_phys_addr_t addr,
+ uint32_t value)
+{
+#ifdef HPET_DEBUG
+ printf("qemu: invalid hpet_write b at %#x = %#x\n", addr, value);
+#endif
+}
+
+static void hpet_ram_writew(void *opaque, target_phys_addr_t addr,
+ uint32_t value)
+{
+#ifdef HPET_DEBUG
+ printf("qemu: invalid hpet_write w at %#x = %#x\n", addr, value);
+#endif
+}
+
+static void hpet_ram_writel(void *opaque, target_phys_addr_t addr,
+ uint32_t value)
+{
+ HPETState *s = (HPETState *)opaque;
+#ifdef HPET_DEBUG
+ printf("qemu: hpet_write l at %#x = %#x\n", addr, value);
+#endif
+ switch(addr - HPET_BASE) {
+ case 0x00:
+ return;
+ case 0x10:
+ case 0x14: // set interrupt enabled flag
+ if(value < 2) {
+ s->active = value;
+ update_irq_all(s);
+ } else {
+#ifdef HPET_DEBUG
+ printf("qemu: invalid hpet_write l at %#x = %#x\n", addr, value);
+#endif
+ }
+ break;
+ case 0x20:
+ {
+ int i;
+ for(i=0; i<HPET_NUM_TIMERS; i++) {
+ if(s->timer[i].type == HPET_TIMER_TYPE_LEVEL) {
+ if(value & (1 << i)) {
+ s->timer[i].active = 0;
+ update_irq(&s->timer[i]);
+ }
+ }
+ }
+ }
+ break;
+ case 0xf0:
+ s->hpet_counter = (s->hpet_counter & (0xffffffffULL << 32)) | value;
+#ifdef HPET_DEBUG
+ printf("qemu: HPET counter 0xf0 set to %#x -> %#llx\n", value, s->hpet_counter);
+#endif
+ break;
+ case 0xf4:
+ s->hpet_counter = (s->hpet_counter & 0xffffffffULL) | (((uint64_t)value) << 32);
+#ifdef HPET_DEBUG
+ printf("qemu: HPET counter 0xf4 set to %#x -> %#llx\n", value, s->hpet_counter);
+#endif
+ break;
+ case 0x100 ... 0x3ff:
+ {
+ uint8_t timer_id = (addr - HPET_BASE - 0x100) / 0x20;
+ HPETTimer *timer = &s->timer[timer_id];
+
+ switch((addr - HPET_BASE - 0x100) % 0x20) {
+ case 0x0:
+ if(value & 1) break; // reserved
+ timer->delivery = (value >> 14) & 1;
+ timer->apic_port = (value >> 9) & 16;
+ timer->irq = s->irqs[timer->apic_port];
+ timer->periodic = (value >> 3) & 1;
+ timer->enabled = (value >> 2) & 1;
+ timer->type = (value >> 1) & 1;
+#ifdef HPET_DEBUG
+ printf("qemu: hpet_write l at %#x = %#x\n", addr, value);
+#endif
+ hpet_check(timer);
+ break;
+#ifdef HPET_DEBUG
+ case 0x4: // Interrupt capabilities
+ printf("qemu: invalid hpet_write l at %#x = %#x\n", addr, value);
+ break;
+#endif
+ case 0x8: // comparator register
+ timer->comparator = value;
+ hpet_check(timer);
+ break;
+ case 0xc:
+#ifdef HPET_DEBUG
+ printf("qemu: invalid hpet_write l at %#x = %#x\n", addr, value);
+#endif
+ break;
+ }
+ }
+ default:
+ printf("qemu: invalid hpet_write l at %#x = %#x\n", addr, value);
+ }
+
+}
+
+static CPUReadMemoryFunc *hpet_ram_read[] = {
+ hpet_ram_readb,
+ hpet_ram_readw,
+ hpet_ram_readl,
+};
+
+static CPUWriteMemoryFunc *hpet_ram_write[] = {
+ hpet_ram_writeb,
+ hpet_ram_writew,
+ hpet_ram_writel,
+};
+
+
+void hpet_init(qemu_irq *irq) {
+ int iomemtype, i;
+ HPETState *s;
+
+ /* XXX this is a dirty hack for HPET support w/o LPC
+ Actually this is a config descriptor for the RCBA */
+ s = qemu_mallocz(sizeof(HPETState));
+ s->irqs = irq;
+
+ for(i=0; i<HPET_NUM_TIMERS; i++) {
+ HPETTimer *timer = &s->timer[i];
+ timer->comparator = 0xffffffff;
+ timer->state = s;
+ timer->timer = qemu_new_timer(vm_clock, hpet_timer, s->timer+i);
+ switch(i) {
+ case 0:
+ timer->apic_port = 2;
+ break;
+ case 1:
+ timer->apic_port = 8;
+ break;
+ default:
+ timer->apic_port = 0;
+ break;
+ }
+ s->timer[i].irq = irq[timer->apic_port];
+ }
+
+ /* HPET Area */
+
+ iomemtype = cpu_register_io_memory(0, hpet_ram_read,
+ hpet_ram_write, s);
+
+ cpu_register_physical_memory(HPET_BASE, 0x400, iomemtype);
+}

View File

@@ -0,0 +1,96 @@
#qemu-only -> submit upstream qemu
Index: kvm-75/qemu/hw/ide.c
===================================================================
--- kvm-75.orig/qemu/hw/ide.c
+++ kvm-75/qemu/hw/ide.c
@@ -462,6 +462,7 @@ static inline int media_is_cd(IDEState *
#define IDE_TYPE_PIIX3 0
#define IDE_TYPE_CMD646 1
#define IDE_TYPE_PIIX4 2
+#define IDE_TYPE_ICH6 3
/* CMD646 specific */
#define MRDMODE 0x71
@@ -3164,6 +3165,57 @@ void pci_piix3_ide_init(PCIBus *bus, Blo
qemu_register_reset(piix3_reset, d);
piix3_reset(d);
+
+ pci_register_io_region((PCIDevice *)d, 4, 0x10,
+ PCI_ADDRESS_SPACE_IO, bmdma_map);
+
+ ide_init2(&d->ide_if[0], hd_table[0], hd_table[1], pic[14]);
+ ide_init2(&d->ide_if[2], hd_table[2], hd_table[3], pic[15]);
+ ide_init_ioport(&d->ide_if[0], 0x1f0, 0x3f6);
+ ide_init_ioport(&d->ide_if[2], 0x170, 0x376);
+
+ for (i = 0; i < 4; i++)
+ if (hd_table[i])
+ hd_table[i]->devfn = d->dev.devfn;
+
+ register_savevm("ide", 0, 1, pci_ide_save, pci_ide_load, d);
+}
+
+
+/* hd_table must contain 4 block drivers */
+/* NOTE: for the ICH-6, the IRQs and IOports are hardcoded */
+void pci_ich6_ide_init(PCIBus *bus, BlockDriverState **hd_table, int devfn,
+ qemu_irq *pic)
+{
+ PCIIDEState *d;
+ uint8_t *pci_conf;
+ int i;
+
+ /* register a function 1 of ICH-6 */
+ d = (PCIIDEState *)pci_register_device(bus, "ICH-6 IDE",
+ sizeof(PCIIDEState),
+ devfn,
+ NULL, NULL);
+ d->type = IDE_TYPE_ICH6;
+
+ pci_conf = d->dev.config;
+ pci_conf[0x00] = 0x86; // Intel
+ pci_conf[0x01] = 0x80;
+ pci_conf[0x02] = 0x9e;
+ pci_conf[0x03] = 0x26;
+
+ pci_conf[0x09] = 0x80; // legacy ATA mode
+ pci_conf[0x0a] = 0x01; // class_sub = PCI_IDE
+ pci_conf[0x0b] = 0x01; // class_base = PCI_mass_storage
+ pci_conf[0x0e] = 0x00; // header_type
+
+ pci_conf[0x40] = 0;
+ pci_conf[0x41] = 0xf0; // primary port enabled
+ pci_conf[0x42] = 0;
+ pci_conf[0x43] = 0x00; // secondary port disabled
+
+ qemu_register_reset(piix3_reset, d);
+ piix3_reset(d);
pci_register_io_region((PCIDevice *)d, 4, 0x10,
PCI_ADDRESS_SPACE_IO, bmdma_map);
Index: kvm-75/qemu/hw/irq.c
===================================================================
--- kvm-75.orig/qemu/hw/irq.c
+++ kvm-75/qemu/hw/irq.c
@@ -35,6 +35,7 @@ void qemu_set_irq(qemu_irq irq, int leve
if (!irq)
return;
+//printf("IRQ set %#hhx = %#hhd using %p\n", irq->n, level, irq->handler);
irq->handler(irq->opaque, irq->n, level);
}
Index: kvm-75/qemu/hw/pc.h
===================================================================
--- kvm-75.orig/qemu/hw/pc.h
+++ kvm-75/qemu/hw/pc.h
@@ -145,6 +145,8 @@ void pci_piix3_ide_init(PCIBus *bus, Blo
qemu_irq *pic);
void pci_piix4_ide_init(PCIBus *bus, BlockDriverState **hd_table, int devfn,
qemu_irq *pic);
+void pci_ich6_ide_init(PCIBus *bus, BlockDriverState **hd_table, int devfn,
+ qemu_irq *pic);
/* ne2000.c */

View File

@@ -0,0 +1,196 @@
#qemu-only -> submit upstream qemu
Index: kvm-75/qemu/Makefile.target
===================================================================
--- kvm-75.orig/qemu/Makefile.target
+++ kvm-75/qemu/Makefile.target
@@ -610,7 +610,7 @@ ifeq ($(TARGET_BASE_ARCH), i386)
OBJS+= ide.o pckbd.o ps2.o vga.o $(SOUND_HW) dma.o
OBJS+= fdc.o mc146818rtc.o serial.o i8259.o i8254.o pcspk.o pc.o
OBJS+= cirrus_vga.o apic.o parallel.o acpi.o piix_pci.o
-OBJS+= usb-uhci.o vmmouse.o vmport.o vmware_vga.o extboot.o hpet.o
+OBJS+= usb-uhci.o vmmouse.o vmport.o vmware_vga.o extboot.o hpet.o lpc.o
ifeq ($(USE_KVM_PIT), 1)
OBJS+= i8254-kvm.o
endif
Index: kvm-75/qemu/hw/lpc.c
===================================================================
--- /dev/null
+++ kvm-75/qemu/hw/lpc.c
@@ -0,0 +1,163 @@
+/*
+ * Low Pin Count emulation
+ *
+ * Copyright (c) 2007 Alexander Graf
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * *****************************************************************
+ *
+ * This driver emulates an ICH-7 LPC partially. The LPC is basically the
+ * same as the ISA-bridge in the existing PIIX implementation, but
+ * more recent and includes support for HPET and Power Management.
+ *
+ */
+#include "hw.h"
+#include "pci.h"
+#include "console.h"
+
+#define RCBA_BASE 0xFED1C000
+
+void hpet_init(qemu_irq irq);
+
+static uint32_t rcba_ram_readl(void *opaque, target_phys_addr_t addr)
+{
+ printf("qemu: rcba_read l at %#lx\n", addr);
+ if(addr == RCBA_BASE + 0x3404) { /* This is the HPET config pointer */
+ printf("qemu: rcba_read HPET_CONFIG_POINTER\n");
+ return 0xf0; // enabled at 0xfed00000
+ } else if(addr == RCBA_BASE + 0x3410) { /* This is the HPET config pointer */
+ printf("qemu: rcba_read GCS\n");
+ return 0;
+ } else {
+ return 0x0;
+ }
+}
+
+static void rcba_ram_writel(void *opaque, target_phys_addr_t addr,
+ uint32_t value)
+{
+ printf("qemu: rcba_write l %#lx = %#x\n", addr, value);
+}
+
+static CPUReadMemoryFunc *rcba_ram_read[] = {
+ NULL,
+ NULL,
+ rcba_ram_readl,
+};
+
+static CPUWriteMemoryFunc *rcba_ram_write[] = {
+ NULL,
+ NULL,
+ rcba_ram_writel,
+};
+
+void lpc_init(PCIBus *bus, int devfn, qemu_irq *pic) {
+ int iomemtype;
+ uint8_t *pci_conf;
+ PCIDevice *d;
+
+ /* register a function 1 of PIIX3 */
+ d = (PCIDevice *)pci_register_device(bus, "LPC",
+ sizeof(PCIDevice),
+ 31 << 3,
+ NULL, NULL);
+ pci_conf = d->config;
+ pci_conf[0x00] = 0x86;
+ pci_conf[0x01] = 0x80;
+ pci_conf[0x02] = 0xb9;
+ pci_conf[0x03] = 0x27;
+ pci_conf[0x08] = 0x02; // Revision 2
+
+ pci_conf[0x0a] = 0x01; // PCI-to-ISA Bridge
+ pci_conf[0x0b] = 0x06; // Bridge
+
+ pci_conf[0x0e] = 0xf0;
+
+ // Subsystem
+ pci_conf[0x2c] = 0x86;
+ pci_conf[0x2d] = 0x80;
+ pci_conf[0x2e] = 0x70;
+ pci_conf[0x2f] = 0x72;
+
+ pci_conf[0x3d] = 0x03;
+
+ // PMBASE
+ pci_conf[0x40] = 0x01;
+ pci_conf[0x41] = 0x0b;
+
+ pci_conf[0xf0] = RCBA_BASE | 1; // enabled
+ pci_conf[0xf1] = RCBA_BASE << 8;
+ pci_conf[0xf2] = RCBA_BASE << 16;
+ pci_conf[0xf3] = RCBA_BASE << 24;
+
+
+ /* RCBA Area */
+
+ iomemtype = cpu_register_io_memory(0, rcba_ram_read,
+ rcba_ram_write, d);
+
+ cpu_register_physical_memory(RCBA_BASE, 0x4000, iomemtype);
+#if 0
+ cpu_register_physical_memory(0x00CDA000, 0x4000, iomemtype);
+#endif
+
+
+
+ pci_conf[0x04] = 0x07; // master, memory and I/O
+ pci_conf[0x05] = 0x00;
+ pci_conf[0x06] = 0x00;
+ pci_conf[0x07] = 0x02; // PCI_status_devsel_medium
+ pci_conf[0x4c] = 0x4d;
+ pci_conf[0x4e] = 0x03;
+ pci_conf[0x4f] = 0x00;
+ pci_conf[0x60] = 0x0a; // PCI A -> IRQ 10
+ pci_conf[0x61] = 0x0a; // PCI B -> IRQ 10
+ pci_conf[0x62] = 0x0b; // PCI C -> IRQ 11
+ pci_conf[0x63] = 0x0b; // PCI D -> IRQ 11
+ pci_conf[0x69] = 0x02;
+ pci_conf[0x70] = 0x80;
+ pci_conf[0x76] = 0x0c;
+ pci_conf[0x77] = 0x0c;
+ pci_conf[0x78] = 0x02;
+ pci_conf[0x79] = 0x00;
+ pci_conf[0x80] = 0x00;
+ pci_conf[0x82] = 0x00;
+ pci_conf[0xa0] = 0x08;
+ pci_conf[0xa2] = 0x00;
+ pci_conf[0xa3] = 0x00;
+ pci_conf[0xa4] = 0x00;
+ pci_conf[0xa5] = 0x00;
+ pci_conf[0xa6] = 0x00;
+ pci_conf[0xa7] = 0x00;
+ pci_conf[0xa8] = 0x0f;
+ pci_conf[0xaa] = 0x00;
+ pci_conf[0xab] = 0x00;
+ pci_conf[0xac] = 0x00;
+ pci_conf[0xae] = 0x00;
+
+// XXX hpet goes via apic
+ hpet_init(pic);
+
+#if 0
+ register_ioport_read(0x1000, 128, 1, pmbase_readb, d);
+ register_ioport_write(0x1000, 128, 1, pmbase_writeb, d);
+ register_ioport_read(0x1000, 64, 2, pmbase_readw, d);
+ register_ioport_write(0x1000, 64, 2, pmbase_writew, d);
+ register_ioport_read(0x1000, 32, 4, pmbase_readl, d);
+ register_ioport_write(0x1000, 32, 5, pmbase_writel, d);
+#endif
+}
+
Index: kvm-75/qemu/hw/pc.h
===================================================================
--- kvm-75.orig/qemu/hw/pc.h
+++ kvm-75/qemu/hw/pc.h
@@ -150,6 +150,9 @@ void pci_piix4_ide_init(PCIBus *bus, Blo
void isa_ne2000_init(int base, qemu_irq irq, NICInfo *nd);
+/* lpc.c */
+void lpc_init(PCIBus *bus, int devfn, qemu_irq *pic);
+
/* virtio-net.c */
PCIDevice *virtio_net_init(PCIBus *bus, NICInfo *nd, int devfn);

View File

@@ -0,0 +1,309 @@
#qemu-only -> submit upstream qemu, but improve first:
# undo rather hacky pci_enabled -> model > MODEL_ISA changes
# and replace checks wether to enable newer emulated Mac hardware
# depending in the bits in a bitfield which is passed pc_init1()
# like this: pc_init1(.... , ISA, ...)
# pc_init1(.... , PCI | IOAPIC | PIIX, .....
# pc_init1(.... , PCI | ICH6, LPC, SMC , ...)
Index: kvm-78/qemu/hw/pc.c
===================================================================
--- kvm-78.orig/qemu/hw/pc.c
+++ kvm-78/qemu/hw/pc.c
@@ -58,6 +58,12 @@ static PITState *pit;
static IOAPICState *ioapic;
static PCIDevice *i440fx_state;
+enum pc_model {
+ MODEL_ISA = 0,
+ MODEL_PCI = 1,
+ MODEL_MAC = 2
+};
+
static void ioport80_write(void *opaque, uint32_t addr, uint32_t data)
{
}
@@ -805,7 +811,7 @@ static void pc_init1(ram_addr_t ram_size
const char *boot_device, DisplayState *ds,
const char *kernel_filename, const char *kernel_cmdline,
const char *initrd_filename,
- int pci_enabled, const char *cpu_model)
+ int model, const char *cpu_model)
{
char buf[1024];
int ret, linux_boot, i;
@@ -833,15 +839,19 @@ static void pc_init1(ram_addr_t ram_size
/* init CPUs */
if (cpu_model == NULL) {
+ if(model == MODEL_MAC) {
+ cpu_model = "coreduo";
+ } else {
#ifdef TARGET_X86_64
- cpu_model = "qemu64";
+ cpu_model = "qemu64";
#else
- cpu_model = "qemu32";
+ cpu_model = "qemu32";
#endif
+ }
}
for(i = 0; i < smp_cpus; i++) {
- env = pc_new_cpu(i, cpu_model, pci_enabled);
+ env = pc_new_cpu(i, cpu_model, model > MODEL_ISA);
}
vmport_init();
@@ -880,8 +890,16 @@ static void pc_init1(ram_addr_t ram_size
vga_ram_addr = qemu_ram_alloc(vga_ram_size);
/* BIOS load */
- if (bios_name == NULL)
- bios_name = BIOS_FILENAME;
+ if (bios_name == NULL) {
+ switch(model) {
+ case MODEL_MAC:
+ bios_name = "bios-mac.bin";
+ break;
+ default:
+ bios_name = BIOS_FILENAME;
+ break;
+ }
+ }
snprintf(buf, sizeof(buf), "%s/%s", bios_dir, bios_name);
bios_size = get_image_size(buf);
if (bios_size <= 0 ||
@@ -956,7 +974,7 @@ static void pc_init1(ram_addr_t ram_size
i8259 = i8259_init(cpu_irq[0]);
ferr_irq = i8259[13];
- if (pci_enabled) {
+ if (model > MODEL_ISA) {
pci_bus = i440fx_init(&i440fx_state, i8259);
piix3_devfn = piix3_init(pci_bus, -1);
} else {
@@ -969,7 +987,7 @@ static void pc_init1(ram_addr_t ram_size
register_ioport_write(0xf0, 1, 1, ioportF0_write, NULL);
if (cirrus_vga_enabled) {
- if (pci_enabled) {
+ if (model > MODEL_ISA) {
pci_cirrus_vga_init(pci_bus,
ds, phys_ram_base + vga_ram_addr,
vga_ram_addr, vga_ram_size);
@@ -978,13 +996,13 @@ static void pc_init1(ram_addr_t ram_size
vga_ram_addr, vga_ram_size);
}
} else if (vmsvga_enabled) {
- if (pci_enabled)
+ if (model > MODEL_ISA)
pci_vmsvga_init(pci_bus, ds, phys_ram_base + vga_ram_addr,
vga_ram_addr, vga_ram_size);
else
fprintf(stderr, "%s: vmware_vga: no PCI bus\n", __FUNCTION__);
} else {
- if (pci_enabled) {
+ if (model > MODEL_ISA) {
pci_vga_init(pci_bus, ds, phys_ram_base + vga_ram_addr,
vga_ram_addr, vga_ram_size, 0, 0);
} else {
@@ -1000,8 +1018,13 @@ static void pc_init1(ram_addr_t ram_size
register_ioport_read(0x92, 1, 1, ioport92_read, NULL);
register_ioport_write(0x92, 1, 1, ioport92_write, NULL);
- if (pci_enabled) {
- ioapic = ioapic_init();
+ switch (model) {
+ case MODEL_MAC:
+ applesmc_init();
+ lpc_init(pci_bus, piix3_devfn, i8259);
+ case MODEL_PCI:
+ ioapic = ioapic_init();
+ break;
}
#ifdef USE_KVM_PIT
if (kvm_enabled() && qemu_kvm_pit_in_kernel())
@@ -1010,7 +1033,7 @@ static void pc_init1(ram_addr_t ram_size
#endif
pit = pit_init(0x40, i8259[0]);
pcspk_init(pit);
- if (pci_enabled) {
+ if (model > MODEL_ISA) {
pic_set_alt_irq_func(isa_pic, ioapic_set_irq, ioapic);
}
@@ -1031,15 +1054,22 @@ static void pc_init1(ram_addr_t ram_size
for(i = 0; i < nb_nics; i++) {
nd = &nd_table[i];
if (!nd->model) {
- if (pci_enabled) {
- nd->model = "rtl8139";
- } else {
- nd->model = "ne2k_isa";
+ switch(model) {
+ case MODEL_ISA:
+ nd->model = "ne2k_isa";
+ break;
+ case MODEL_MAC:
+ nd->model = "rtl8139";
+ nd->link = Link_10mbps;
+ break;
+ default:
+ nd->model = "ne2k_pci";
+ break;
}
}
if (strcmp(nd->model, "ne2k_isa") == 0) {
pc_init_ne2k_isa(nd, i8259);
- } else if (pci_enabled) {
+ } else if (model > MODEL_ISA) {
if (strcmp(nd->model, "?") == 0)
fprintf(stderr, "qemu: Supported ISA NICs: ne2k_isa\n");
if (!pci_nic_init(pci_bus, nd, -1))
@@ -1068,19 +1098,25 @@ static void pc_init1(ram_addr_t ram_size
hd[i] = NULL;
}
- if (pci_enabled) {
- pci_piix3_ide_init(pci_bus, hd, piix3_devfn + 1, i8259);
- } else {
- for(i = 0; i < MAX_IDE_BUS; i++) {
- isa_ide_init(ide_iobase[i], ide_iobase2[i], i8259[ide_irq[i]],
- hd[MAX_IDE_DEVS * i], hd[MAX_IDE_DEVS * i + 1]);
- }
+ switch(model) {
+ case MODEL_MAC:
+ pci_ich6_ide_init(pci_bus, hd, piix3_devfn + 1, i8259);
+ break;
+ case MODEL_PCI:
+ pci_piix3_ide_init(pci_bus, hd, piix3_devfn + 1, i8259);
+ break;
+ default:
+ for(i = 0; i < 2; i++) {
+ isa_ide_init(ide_iobase[i], ide_iobase2[i], i8259[ide_irq[i]],
+ hd[MAX_IDE_DEVS * i], hd[MAX_IDE_DEVS * i + 1]);
+ }
+ break;
}
i8042_init(i8259[1], i8259[12], 0x60);
DMA_init(0);
#ifdef HAS_AUDIO
- audio_init(pci_enabled ? pci_bus : NULL, i8259);
+ audio_init((model > MODEL_ISA) ? pci_bus : NULL, i8259);
#endif
for(i = 0; i < MAX_FD; i++) {
@@ -1094,11 +1130,11 @@ static void pc_init1(ram_addr_t ram_size
cmos_init(below_4g_mem_size, above_4g_mem_size, boot_device, hd);
- if (pci_enabled && usb_enabled) {
+ if ((model > MODEL_ISA) && usb_enabled) {
usb_uhci_piix3_init(pci_bus, piix3_devfn + 2);
}
- if (pci_enabled && acpi_enabled) {
+ if ((model > MODEL_ISA) && acpi_enabled) {
uint8_t *eeprom_buf = qemu_mallocz(8 * 256); /* XXX: make this persistent */
i2c_bus *smbus;
@@ -1113,7 +1149,7 @@ static void pc_init1(ram_addr_t ram_size
i440fx_init_memory_mappings(i440fx_state);
}
- if (pci_enabled) {
+ if (model > MODEL_ISA) {
int max_bus;
int bus, unit;
void *scsi;
@@ -1132,7 +1168,7 @@ static void pc_init1(ram_addr_t ram_size
}
/* Add virtio block devices */
- if (pci_enabled) {
+ if (model > MODEL_ISA) {
int index;
int unit_id = 0;
@@ -1155,10 +1191,22 @@ static void pc_init1(ram_addr_t ram_size
extboot_init(info->bdrv, 1);
}
- if (pci_enabled)
+ if (model > MODEL_ISA)
virtio_balloon_init(pci_bus);
}
+static void pc_init_mac(ram_addr_t ram_size, int vga_ram_size,
+ const char *boot_device, DisplayState *ds,
+ const char *kernel_filename,
+ const char *kernel_cmdline,
+ const char *initrd_filename,
+ const char *cpu_model)
+{
+ pc_init1(ram_size, vga_ram_size, boot_device, ds,
+ kernel_filename, kernel_cmdline,
+ initrd_filename, MODEL_MAC, cpu_model);
+}
+
static void pc_init_pci(ram_addr_t ram_size, int vga_ram_size,
const char *boot_device, DisplayState *ds,
const char *kernel_filename,
@@ -1168,7 +1216,7 @@ static void pc_init_pci(ram_addr_t ram_s
{
pc_init1(ram_size, vga_ram_size, boot_device, ds,
kernel_filename, kernel_cmdline,
- initrd_filename, 1, cpu_model);
+ initrd_filename, MODEL_PCI, cpu_model);
}
static void pc_init_isa(ram_addr_t ram_size, int vga_ram_size,
@@ -1180,7 +1228,7 @@ static void pc_init_isa(ram_addr_t ram_s
{
pc_init1(ram_size, vga_ram_size, boot_device, ds,
kernel_filename, kernel_cmdline,
- initrd_filename, 0, cpu_model);
+ initrd_filename, MODEL_ISA, cpu_model);
}
QEMUMachine pc_machine = {
@@ -1190,6 +1238,14 @@ QEMUMachine pc_machine = {
.ram_require = VGA_RAM_SIZE + PC_MAX_BIOS_SIZE,
.max_cpus = 255,
};
+
+QEMUMachine mac_machine = {
+ .name = "mac",
+ .desc = "Intel-Mac",
+ .init = pc_init_mac,
+ .ram_require = VGA_RAM_SIZE + PC_MAX_BIOS_SIZE,
+ .max_cpus = 255,
+};
QEMUMachine isapc_machine = {
.name = "isapc",
Index: kvm-78/qemu/hw/boards.h
===================================================================
--- kvm-78.orig/qemu/hw/boards.h
+++ kvm-78/qemu/hw/boards.h
@@ -33,6 +33,7 @@ extern QEMUMachine bareetraxfs_machine;
/* pc.c */
extern QEMUMachine pc_machine;
extern QEMUMachine isapc_machine;
+extern QEMUMachine mac_machine;
/* ppc.c */
extern QEMUMachine prep_machine;
Index: kvm-78/qemu/target-i386/machine.c
===================================================================
--- kvm-78.orig/qemu/target-i386/machine.c
+++ kvm-78/qemu/target-i386/machine.c
@@ -10,6 +10,7 @@ void register_machines(void)
{
qemu_register_machine(&pc_machine);
qemu_register_machine(&isapc_machine);
+ qemu_register_machine(&mac_machine);
}
static void cpu_put_seg(QEMUFile *f, SegmentCache *dt)

View File

@@ -0,0 +1,492 @@
Index: kvm-75/qemu/elf_ops.h
===================================================================
--- kvm-75.orig/qemu/elf_ops.h
+++ kvm-75/qemu/elf_ops.h
@@ -156,6 +156,10 @@ static int glue(load_elf, SZ)(int fd, in
}
if (ELF_MACHINE != ehdr.e_machine)
+#if (ELF_MACHINE == EM_X86_64) && !CONFIG_USER_ONLY
+ /* x86_64 systems can run i386 code as well */
+ if(ehdr.e_machine != EM_386)
+#endif
goto fail;
if (pentry)
Index: kvm-75/qemu/hw/pc.c
===================================================================
--- kvm-75.orig/qemu/hw/pc.c
+++ kvm-75/qemu/hw/pc.c
@@ -512,6 +512,416 @@ static long get_file_size(FILE *f)
return size;
}
+/* Generate an initial boot sector which sets state and jump to
+ a specified vector */
+static void generate_bootsect_multiboot(uint32_t mh_entry_addr, uint32_t bootinfo)
+{
+ uint8_t bootsect[512], *p, *pgdt, *pmmaploop;
+ uint32_t ip;
+ int i;
+ int hda;
+ int mmaploop;
+
+ hda = drive_get_index(IF_IDE, 0, 0);
+ if (hda == -1) {
+ fprintf(stderr, "A disk image must be given for 'hda' when booting "
+ "a Multiboot kernel\n");
+ exit(1);
+ }
+
+ memset(bootsect, 0, sizeof(bootsect));
+
+ /* Copy the MSDOS partition table if possible */
+ bdrv_read(drives_table[hda].bdrv, 0, bootsect, 1);
+
+ /* Make sure we have a partition signature */
+ bootsect[510] = 0x55;
+ bootsect[511] = 0xaa;
+
+ /* Actual code */
+ p = bootsect;
+ *p++ = 0xfa; /* CLI */
+ *p++ = 0xfc; /* CLD */
+
+ // 660f011528000000 lgdt [0x28]
+ *p++ = 0x66; /* 32-bit operand size */
+ *p++ = 0x67; /* 32-bit addr size */
+ *p++ = 0x0f; /* LGDT [0x128] */
+ *p++ = 0x01;
+ *p++ = 0x15;
+ pgdt=p; /* we calculate the gdt position later */
+ p+=4;
+
+ /* Initialize multiboot mmap structs using the 0x15(e820) */
+ *p++ = 0x31; /* XOR BX,BX */
+ *p++ = 0xdb;
+
+ *p++ = 0x66; /* 32-bit operand size */
+ *p++ = 0x67; /* 32-bit addr size */
+ *p++ = 0xbf; /* MOV EDI,0x9004 */
+ *p++ = 0x04;
+ *p++ = 0x90;
+ *p++ = 0x00;
+ *p++ = 0x00;
+
+ pmmaploop = p;
+ *p++ = 0x66; /* 32-bit operand size */
+ *p++ = 0x67; /* 32-bit addr size */
+ *p++ = 0xb8; /* MOV EAX,0x20 */
+ *p++ = 0x20;
+ *p++ = 0x00;
+ *p++ = 0x00;
+ *p++ = 0x00;
+
+ *p++ = 0x66; /* 32-bit operand size */
+ *p++ = 0x67; /* 32-bit addr size */
+ *p++ = 0x89; /* MOV -4(EDI),EAX */
+ *p++ = 0x47;
+ *p++ = 0xfc;
+
+ *p++ = 0x66; /* 32-bit operand size */
+ *p++ = 0x67; /* 32-bit addr size */
+ *p++ = 0xb8; /* MOV EAX,0x0000e820 */
+ *p++ = 0x20;
+ *p++ = 0xe8;
+ *p++ = 0x00;
+ *p++ = 0x00;
+
+ *p++ = 0x66; /* 32-bit operand size */
+ *p++ = 0x67; /* 32-bit addr size */
+ *p++ = 0xba; /* MOV EDX,0x534d4150 */
+ *p++ = 0x50;
+ *p++ = 0x41;
+ *p++ = 0x4d;
+ *p++ = 0x53;
+
+ *p++ = 0x66; /* 32-bit operand size */
+ *p++ = 0x67; /* 32-bit addr size */
+ *p++ = 0xb9; /* MOV ECX,0x20 */
+ *p++ = 0x20;
+ *p++ = 0x00;
+ *p++ = 0x00;
+ *p++ = 0x00;
+
+ *p++ = 0xcd; /* INT 0x15 */
+ *p++ = 0x15;
+
+ *p++ = 0x66; /* 32-bit operand size */
+ *p++ = 0x67; /* 32-bit addr size */
+ *p++ = 0xb8; /* MOV EAX, 0x24 */
+ *p++ = 0x24;
+ *p++ = 0x00;
+ *p++ = 0x00;
+ *p++ = 0x00;
+
+ *p++ = 0xf7; /* MUL AX, BX */
+ *p++ = 0xe3;
+
+ *p++ = 0x66; /* 32-bit operand size */
+ *p++ = 0x67; /* 32-bit addr size */
+ *p++ = 0x21; /* AND EBX, EBX */
+ *p++ = 0xdb;
+
+ /* don't store if bx = 0 */
+ *p++ = 0x66; /* 32-bit operand size */
+ *p++ = 0x67; /* 32-bit addr size */
+ *p++ = 0x0f; /* JZ next instruction */
+ *p++ = 0x84;
+ *p++ = 0x07;
+ *p++ = 0x00;
+ *p++ = 0x00;
+ *p++ = 0x00;
+
+ /* store the amount of blocks in the bootinfo struct */
+ *p++ = 0x66; /* 32-bit operand size */
+ *p++ = 0x67; /* 32-bit addr size */
+ *p++ = 0xa3; /* MOV [bootinfo+0x2c], EAX */
+ *p++ = (bootinfo+0x2c);
+ *p++ = (bootinfo+0x2c) >> 8;
+ *p++ = (bootinfo+0x2c) >> 16;
+ *p++ = (bootinfo+0x2c) >> 24;
+
+ *p++ = 0x66; /* 32-bit operand size */
+ *p++ = 0x67; /* 32-bit addr size */
+ *p++ = 0x05; /* ADD EAX, 0x9004 */
+ *p++ = 0x04;
+ *p++ = 0x90;
+ *p++ = 0x00;
+ *p++ = 0x00;
+
+ *p++ = 0x89; /* MOV DI, AX */
+ *p++ = 0xc7;
+
+ *p++ = 0x66; /* 32-bit operand size */
+ *p++ = 0x67; /* 32-bit addr size */
+ *p++ = 0x21; /* AND EBX, EBX */
+ *p++ = 0xdb;
+
+ /* process next entry */
+ *p++ = 0x66; /* 32-bit operand size */
+ *p++ = 0x67; /* 32-bit addr size */
+ *p++ = 0x0f; /* JNZ mmaploop */
+ *p++ = 0x85;
+ mmaploop = (int)((long)pmmaploop) - ((long)p) - 4;
+ *p++ = mmaploop;
+ *p++ = mmaploop >> 8;
+ *p++ = mmaploop >> 16;
+ *p++ = mmaploop >> 24;
+
+ /* get us to protected mode now */
+
+ *p++ = 0x66;
+ *p++ = 0xb8; /* MOV EAX,0x01 */
+ *p++ = 0x01;
+ *p++ = 0x00;
+ *p++ = 0x00;
+ *p++ = 0x00;
+
+ *p++ = 0x0f; /* MOV CR0,EAX */
+ *p++ = 0x22;
+ *p++ = 0xc0;
+
+ /* the JMP sets CS for us and gets us to 32-bit */
+ ip = 0x00007c00 + (p - bootsect) + 8; // set i to the IP after the JMP
+ *p++ = 0x66; /* 32-bit operand size */
+ *p++ = 0xea; /* JMP */
+ *p++ = ip; /* IP */
+ *p++ = ip >> 8;
+ *p++ = ip >> 16;
+ *p++ = ip >> 24;
+ *p++ = 0x08;
+ *p++ = 0x00;
+
+ /* initialize all other segments */
+ *p++ = 0xb8; /* MOV EAX,0x10 */
+ *p++ = 0x10;
+ *p++ = 0x00;
+ *p++ = 0x00;
+ *p++ = 0x00;
+ for (i = 0; i < 6; i++) {
+ if (i == 1) /* Skip CS */
+ continue;
+
+ *p++ = 0x8e; /* MOV <seg>,EAX */
+ *p++ = 0xc0 + (i << 3);
+ }
+
+ /* EBX contains a pointer to the bootinfo struct */
+ *p++ = 0xbb; /* MOV EBX,imm32 */
+ *p++ = bootinfo;
+ *p++ = bootinfo >> 8;
+ *p++ = bootinfo >> 16;
+ *p++ = bootinfo >> 24;
+
+ /* EAX has to contain the following magic */
+ *p++ = 0xb8; /* MOV EAX,0x2badb002 */
+ *p++ = 0x02;
+ *p++ = 0xb0;
+ *p++ = 0xad;
+ *p++ = 0x2b;
+
+ /* Jump off to the kernel */
+ *p++ = 0xea; /* JMP */
+ *p++ = mh_entry_addr; /* IP */
+ *p++ = mh_entry_addr >> 8;
+ *p++ = mh_entry_addr >> 16;
+ *p++ = mh_entry_addr >> 24;
+ *p++ = 0x08;
+ *p++ = 0x00;
+
+ { /* GDT loading */
+ uint32_t gdt_base = 0x00007c00 + (p - bootsect); // 0x00007c00 is the first IP;
+ uint32_t gdtr = gdt_base + 0x28;
+ uint8_t gdt[] = { // GDT base: 0x00000100
+ // 0x00
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ // 0x08: code segment (base=0, limit=0xfffff, type=32bit code exec/read, DPL=0, 4k)
+ 0xff, 0xff, 0x00, 0x00, 0x00, 0x9a, 0xcf, 0x00,
+ // 0x10: data segment (base=0, limit=0xfffff, type=32bit data read/write, DPL=0, 4k)
+ 0xff, 0xff, 0x00, 0x00, 0x00, 0x92, 0xcf, 0x00,
+ // 0x18: code segment (base=0, limit=0x0ffff, type=16bit code exec/read/conf, DPL=0, 1b)
+ 0xff, 0xff, 0x00, 0x00, 0x00, 0x9e, 0x00, 0x00,
+ // 0x20: data segment (base=0, limit=0x0ffff, type=16bit data read/write, DPL=0, 1b)
+ 0xff, 0xff, 0x00, 0x00, 0x00, 0x92, 0x00, 0x00,
+ // 0x28: gdtdesc
+ 0x27, 0x00, gdt_base, gdt_base >> 8, gdt_base >> 16, gdt_base >> 24
+ };
+
+ memcpy(p, gdt, sizeof(gdt));
+ p+=sizeof(gdt);
+ *pgdt++ = gdtr;
+ *pgdt++ = gdtr >> 8;
+ *pgdt++ = gdtr >> 16;
+ *pgdt++ = gdtr >> 24;
+ }
+
+ fprintf(stderr, "qemu: multiboot loader code is %d bytes long.\n", (int)(p-bootsect));
+
+ bdrv_set_boot_sector(drives_table[hda].bdrv, bootsect, sizeof(bootsect));
+}
+
+static int load_multiboot(FILE *f,
+ const char *kernel_filename,
+ const char *initrd_filename,
+ const char *kernel_cmdline,
+ uint8_t *header)
+{
+ int i, is_multiboot = 0;
+ uint32_t flags = 0;
+ uint32_t mh_entry_addr;
+ uint32_t mh_load_addr;
+ uint32_t mb_kernel_size;
+ uint32_t mb_bootinfo = 0x90000;
+ uint32_t tmp_size;
+
+ // Ok, let's see if it is a multiboot image
+ for(i = 0; i < 8144; i += 4) { // the header is 12x32bit long, so
+ // the latest entry may be 8192 - 48
+ if(ldl_p(header+i) == 0x1BADB002) {
+ uint32_t checksum = ldl_p(header+i+8);
+ flags = ldl_p(header+i+4);
+ checksum += flags;
+ checksum += (uint32_t)0x1BADB002;
+ if(!checksum) {
+ is_multiboot = 1;
+ break;
+ }
+ }
+ }
+
+ if(!is_multiboot) return 0; // no multiboot
+ fprintf(stderr, "qemu: I believe we found a multiboot image!\n");
+
+ if(flags & 0x00000004) { // MULTIBOOT_HEADER_HAS_VBE
+ fprintf(stderr, "qemu: multiboot knows VBE. we don't.\n");
+ }
+ if(!(flags & 0x00010000)) { // MULTIBOOT_HEADER_HAS_ADDR
+ uint64_t elf_entry;
+ int kernel_size;
+ fclose(f);
+ kernel_size = load_elf(kernel_filename, 0, &elf_entry, NULL, NULL);
+ if(kernel_size < 0) {
+ fprintf(stderr, "Error while loading elf kernel\n");
+ exit(1);
+ }
+ mh_load_addr = mh_entry_addr = elf_entry;
+ mb_kernel_size = kernel_size;
+
+ fprintf(stderr, "qemu: loading multiboot-elf kernel (%#x bytes) with entry %#zx\n",
+ mb_kernel_size, (size_t)mh_entry_addr);
+ } else {
+ /* Valid if mh_flags sets MULTIBOOT_HEADER_HAS_ADDR. */
+ uint32_t mh_header_addr = ldl_p(header+i+12);
+ mh_load_addr = ldl_p(header+i+16);
+ uint32_t mh_load_end_addr = ldl_p(header+i+20);
+ uint32_t mh_bss_end_addr = ldl_p(header+i+24);
+ uint8_t *mb_kernel_addr = phys_ram_base + (mh_load_addr);
+ uint32_t mb_kernel_text_offset = i - (mh_header_addr - mh_load_addr);
+
+ mh_entry_addr = ldl_p(header+i+28);
+ mb_kernel_size = get_file_size(f) - mb_kernel_text_offset;
+
+ /* Valid if mh_flags sets MULTIBOOT_HEADER_HAS_VBE.
+ uint32_t mh_mode_type = ldl_p(header+i+32);
+ uint32_t mh_width = ldl_p(header+i+36);
+ uint32_t mh_height = ldl_p(header+i+40);
+ uint32_t mh_depth = ldl_p(header+i+44); */
+
+ fprintf(stderr, "multiboot: mh_header_addr = %#x\n", mh_header_addr);
+ fprintf(stderr, "multiboot: mh_load_addr = %#x\n", mh_load_addr);
+ fprintf(stderr, "multiboot: mh_load_end_addr = %#x\n", mh_load_end_addr);
+ fprintf(stderr, "multiboot: mh_bss_end_addr = %#x\n", mh_bss_end_addr);
+
+ fseek(f, mb_kernel_text_offset, SEEK_SET);
+
+ fprintf(stderr, "qemu: loading multiboot kernel (%#x bytes) at %#zx\n",
+ mb_kernel_size, mb_kernel_addr - phys_ram_base);
+
+ if ((tmp_size=fread(mb_kernel_addr, 1, mb_kernel_size, f)) != mb_kernel_size) {
+ fprintf(stderr, "qemu: read error on multiboot kernel '%s' (%#x != %#x)\n", kernel_filename, tmp_size, mb_kernel_size);
+ exit(1);
+ }
+ fclose(f);
+ }
+
+
+ // load modules
+
+ stl_p(phys_ram_base + mb_bootinfo + 20, 0x0); // mods_count
+ if(initrd_filename) {
+ uint32_t mb_mod_info = mb_bootinfo + 0x100;
+ uint32_t mb_mod_cmdline = mb_bootinfo+ 0x300;
+ uint32_t mb_mod_start = mh_load_addr;
+ uint32_t mb_mod_length = mb_kernel_size;
+ char *next_initrd;
+ char *next_space;
+ int mb_mod_count = 0;
+
+ do {
+ next_initrd = strchr(initrd_filename, ',');
+ if(next_initrd)
+ *next_initrd = '\0';
+ /* if a space comes after the module filename, treat everything after that as parameters */
+ strcpy(phys_ram_base + mb_mod_cmdline, initrd_filename);
+ stl_p(phys_ram_base + mb_mod_info + 8, mb_mod_cmdline); // string
+ mb_mod_cmdline += strlen(initrd_filename) + 1;
+ if(next_space = strchr(initrd_filename, ' '))
+ *next_space = '\0';
+printf("multiboot loading module: %s\n", initrd_filename);
+ f = fopen(initrd_filename, "rb");
+ if(f) {
+ mb_mod_start = (mb_mod_start + mb_mod_length + (TARGET_PAGE_SIZE - 1))
+ & (TARGET_PAGE_MASK);
+ mb_mod_length = get_file_size(f);
+
+ if ((tmp_size=fread((phys_ram_base + mb_mod_start), 1, mb_mod_length, f))
+ != mb_mod_length) {
+ fprintf(stderr, "qemu: read error on multiboot module '%s' (%#x != %#x)\n",
+ initrd_filename, tmp_size, mb_mod_length);
+ exit(1);
+ }
+
+ mb_mod_count++;
+ stl_p(phys_ram_base + mb_mod_info + 0, mb_mod_start);
+ stl_p(phys_ram_base + mb_mod_info + 4, mb_mod_start + mb_mod_length);
+printf("mod_start: %#x\nmod_end: %#x\n", mb_mod_start, mb_mod_start + mb_mod_length);
+ stl_p(phys_ram_base + mb_mod_info + 12, 0x0); // reserved
+ }
+ initrd_filename = next_initrd+1;
+ mb_mod_info += 16;
+ } while(next_initrd);
+ stl_p(phys_ram_base + mb_bootinfo + 20, mb_mod_count); // mods_count
+ stl_p(phys_ram_base + mb_bootinfo + 24, mb_bootinfo + 0x100); // mods_addr
+ }
+
+ /* Commandline support */
+ stl_p(phys_ram_base + mb_bootinfo + 16, mb_bootinfo + 0x200);
+ strcpy((char*)(phys_ram_base + mb_bootinfo + 0x200), kernel_cmdline);
+
+ // the kernel is where we want it to be now
+
+#define MULTIBOOT_FLAGS_MEMORY (1 << 0)
+#define MULTIBOOT_FLAGS_BOOT_DEVICE (1 << 1)
+#define MULTIBOOT_FLAGS_CMDLINE (1 << 2)
+#define MULTIBOOT_FLAGS_MODULES (1 << 3)
+#define MULTIBOOT_FLAGS_MMAP (1 << 6)
+ stl_p(phys_ram_base + mb_bootinfo, MULTIBOOT_FLAGS_MEMORY
+ | MULTIBOOT_FLAGS_BOOT_DEVICE
+ | MULTIBOOT_FLAGS_CMDLINE
+ | MULTIBOOT_FLAGS_MODULES
+ | MULTIBOOT_FLAGS_MMAP);
+ stl_p(phys_ram_base + mb_bootinfo + 4, 640 * 1024); // mem_lower
+ stl_p(phys_ram_base + mb_bootinfo + 8, ram_size); // mem_upper
+ stl_p(phys_ram_base + mb_bootinfo + 12, 0x8001ffff); // XXX: use the -boot switch?
+ stl_p(phys_ram_base + mb_bootinfo + 48, 0x9000); // mmap_addr
+
+ fprintf(stderr, "multiboot: mh_entry_addr = %#x\n", mh_entry_addr);
+
+ generate_bootsect_multiboot(mh_entry_addr, mb_bootinfo);
+
+ return 1; // yes, we are multiboot
+}
+
static void load_linux(const char *kernel_filename,
const char *initrd_filename,
const char *kernel_cmdline)
@@ -522,7 +932,7 @@ static void load_linux(const char *kerne
uint16_t real_seg;
int setup_size, kernel_size, initrd_size, cmdline_size;
uint32_t initrd_max;
- uint8_t header[1024];
+ uint8_t header[8192];
target_phys_addr_t real_addr, prot_addr, cmdline_addr, initrd_addr;
FILE *f, *fi;
@@ -532,7 +942,7 @@ static void load_linux(const char *kerne
/* load the kernel header */
f = fopen(kernel_filename, "rb");
if (!f || !(kernel_size = get_file_size(f)) ||
- fread(header, 1, 1024, f) != 1024) {
+ fread(header, 1, 8192, f) != 8192) {
fprintf(stderr, "qemu: could not load kernel '%s'\n",
kernel_filename);
exit(1);
@@ -542,10 +952,15 @@ static void load_linux(const char *kerne
#if 0
fprintf(stderr, "header magic: %#x\n", ldl_p(header+0x202));
#endif
- if (ldl_p(header+0x202) == 0x53726448)
- protocol = lduw_p(header+0x206);
- else
- protocol = 0;
+ if (ldl_p(header+0x202) == 0x53726448) {
+ protocol = lduw_p(header+0x206);
+ } else {
+ // This looks like a multiboot kernel. If it is, let's stop
+ // treating it like Linux.
+ if(load_multiboot(f,kernel_filename,initrd_filename, kernel_cmdline, header))
+ return;
+ protocol = 0;
+ }
if (protocol < 0x200 || !(header[0x211] & 0x01)) {
/* Low kernel */
@@ -638,7 +1053,7 @@ static void load_linux(const char *kerne
}
/* store the finalized header and load the rest of the kernel */
- cpu_physical_memory_write(real_addr, header, 1024);
+ cpu_physical_memory_write(real_addr, header, 8192);
setup_size = header[0x1f1];
if (setup_size == 0)
@@ -647,7 +1062,7 @@ static void load_linux(const char *kerne
setup_size = (setup_size+1)*512;
kernel_size -= setup_size; /* Size of protected-mode code */
- if (!fread_targphys_ok(real_addr+1024, setup_size-1024, f) ||
+ if (!fread_targphys_ok(real_addr+8192, setup_size-8192, f) ||
!fread_targphys_ok(prot_addr, kernel_size, f)) {
fprintf(stderr, "qemu: read error on kernel '%s'\n",
kernel_filename);

View File

@@ -0,0 +1,14 @@
Index: kvm-78/qemu/vl.c
===================================================================
--- kvm-78.orig/qemu/vl.c
+++ kvm-78/qemu/vl.c
@@ -10057,7 +10057,8 @@ int main(int argc, char **argv)
if (kvm_enabled()) {
if (kvm_qemu_init() < 0) {
extern int kvm_allowed;
- fprintf(stderr, "Could not initialize KVM, will disable KVM support\n");
+ fprintf(stderr, "Could not initialize KVM. Do you have kvm-amd or kvm-intel modprobe'd?\nIf you want to use CPU emulation, start with -no-kvm.\n");
+ exit(1);
#ifdef NO_CPU_EMULATION
fprintf(stderr, "Compiled with --disable-cpu-emulation, exiting.\n");
exit(1);

View File

@@ -0,0 +1,109 @@
# Fix the Link detection in MacOS
# Author Alex Graf - agraf@suse
Index: kvm-75/qemu/hw/rtl8139.c
===================================================================
--- kvm-75.orig/qemu/hw/rtl8139.c
+++ kvm-75/qemu/hw/rtl8139.c
@@ -422,6 +422,9 @@ static void RTL8139TallyCounters_load(QE
/* Saves values of tally counters to VM state file */
static void RTL8139TallyCounters_save(QEMUFile* f, RTL8139TallyCounters *tally_counters);
+static uint32_t rtl8139_io_readb(void *opaque, uint8_t addr);
+static uint32_t rtl8139_io_readw(void *opaque, uint8_t addr);
+
typedef struct RTL8139State {
uint8_t phys[8]; /* mac address */
uint8_t mult[8]; /* multicast mask array */
@@ -462,6 +465,7 @@ typedef struct RTL8139State {
uint16_t CpCmd;
uint8_t TxThresh;
+ enum NICLink link;
PCIDevice *pci_dev;
VLANClientState *vc;
@@ -1227,7 +1231,7 @@ static void rtl8139_reset(RTL8139State *
s->Config0 = 0x0; /* No boot ROM */
s->Config1 = 0xC; /* IO mapped and MEM mapped registers available */
s->Config3 = 0x1; /* fast back-to-back compatible */
- s->Config5 = 0x0;
+ s->Config5 = Cfg5_LDPS;
s->CSCR = CSCR_F_LINK_100 | CSCR_HEART_BIT | CSCR_LD;
@@ -1251,6 +1255,13 @@ static void rtl8139_reset(RTL8139State *
s->TimerInt = 0;
s->TCTR_base = 0;
+ s->eeprom.contents[10] = s->Config0 | s->Config1 << 8;
+ s->eeprom.contents[6] = (rtl8139_io_readb(s, MediaStatus) & 0xc0) | ((rtl8139_io_readw(s, BasicModeCtrl) >> 8) & 0x23)
+ | (s->Config3 << 8);
+ s->eeprom.contents[12] = s->Config4 << 8;
+
+ s->eeprom.contents[15] = s->Config5 << 8;
+
/* reset tally counters */
RTL8139TallyCounters_clear(&s->tally_counters);
}
@@ -2846,7 +2857,7 @@ static uint32_t rtl8139_io_readb(void *o
break;
case MediaStatus:
- ret = 0xd0;
+ ret = 0xd0 | ((s->link == Link_10mbps) << 3);
DEBUG_PRINT(("RTL8139: MediaStatus read 0x%x\n", ret));
break;
@@ -3440,6 +3451,15 @@ PCIDevice *pci_rtl8139_init(PCIBus *bus,
s->pci_dev = (PCIDevice *)d;
memcpy(s->macaddr, nd->macaddr, 6);
+ switch(nd->link) {
+ case Link_10mbps:
+ case Link_100mbps:
+ s->link = nd->link;
+ break;
+ default:
+ s->link = Link_100mbps;
+ break;
+ }
rtl8139_reset(s);
s->vc = qemu_new_vlan_client(nd->vlan, rtl8139_receive,
rtl8139_can_receive, s);
Index: kvm-75/qemu/net.h
===================================================================
--- kvm-75.orig/qemu/net.h
+++ kvm-75/qemu/net.h
@@ -55,12 +55,20 @@ void net_client_uninit(NICInfo *nd);
#define MAX_NICS 8
+enum NICLink {
+ Link_default,
+ Link_10mbps,
+ Link_100mbps,
+ Link_1000mbps,
+};
+
struct NICInfo {
uint8_t macaddr[6];
const char *model;
VLANState *vlan;
int devfn;
int used;
+ enum NICLink link;
};
extern int nb_nics;
Index: kvm-75/qemu/vl.c
===================================================================
--- kvm-75.orig/qemu/vl.c
+++ kvm-75/qemu/vl.c
@@ -5555,6 +5555,7 @@ int net_client_init(const char *device,
}
nd->vlan = vlan;
nd->used = 1;
+ nd->link = Link_default;
nb_nics++;
vlan->nb_guest_devs++;
ret = idx;

View File

@@ -0,0 +1,13 @@
# Revert default caching mode back to write-back for now
# Signed-off-by: Bruce Rogers <brogers@novell.com>
--- kvm-78.orig/qemu/vl.c
+++ kvm-78/qemu/vl.c
@@ -5892,7 +5892,7 @@ int drive_init(struct drive_opt *arg, in
unit_id = -1;
translation = BIOS_ATA_TRANSLATION_AUTO;
index = -1;
- cache = 1;
+ cache = 2;
if (machine->use_scsi) {
type = IF_SCSI;