From: Ian Jackson Date: Wed, 19 Mar 2008 17:08:21 +0000 (+0000) Subject: WIP merge with xen-unstable X-Git-Tag: xen-3.3.0-rc1~226 X-Git-Url: http://xenbits.xensource.com/gitweb?a=commitdiff_plain;h=b2c3c6da823e38c369663e1aaf2b3b4b6487f207;p=qemu-xen-3.4-testing.git WIP merge with xen-unstable Includes new i8259.c, more or less completely merged pc.c, acpi adjustments, and various build system fixes. --- diff --git a/hw/pc.c b/hw/pc.c index fbbc7a0f..eb4be15a 100644 --- a/hw/pc.c +++ b/hw/pc.c @@ -50,6 +50,10 @@ static PITState *pit; static IOAPICState *ioapic; static PCIDevice *i440fx_state; +static void xen_relocator_hook(target_phys_addr_t prot_addr, uint16_t protocol, + uint8_t header[], int kernel_size); +#define smbus_eeprom_device_init (void) + static void ioport80_write(void *opaque, uint32_t addr, uint32_t data) { } @@ -90,7 +94,7 @@ void cpu_smm_update(CPUState *env) i440fx_set_smm(i440fx_state, (env->hflags >> HF_SMM_SHIFT) & 1); } - +#ifndef CONFIG_DM /* IRQ handling */ int cpu_get_pic_interrupt(CPUState *env) { @@ -117,6 +121,7 @@ static void pic_irq_request(void *opaque, int irq, int level) if (level && apic_accept_pic_intr(env)) cpu_interrupt(env, CPU_INTERRUPT_HARD); } +#endif /* !CONFIG_DM */ /* PC cmos mappings */ @@ -469,6 +474,7 @@ static void load_linux(const char *kernel_filename, const char *initrd_filename, const char *kernel_cmdline) { +#ifndef __ia64__ uint16_t protocol; uint32_t gpr[8]; uint16_t seg[6]; @@ -517,7 +523,7 @@ static void load_linux(const char *kernel_filename, prot_addr = 0x100000; } -#if 0 +#if 1 fprintf(stderr, "qemu: real_addr = %#zx\n" "qemu: cmdline_addr = %#zx\n" @@ -600,6 +606,8 @@ static void load_linux(const char *kernel_filename, setup_size = (setup_size+1)*512; kernel_size -= setup_size; /* Size of protected-mode code */ + xen_relocator_hook(prot_addr, protocol, header, kernel_size); + if (!fread_targphys_ok(real_addr+1024, setup_size-1024, f) || !fread_targphys_ok(prot_addr, kernel_size, f)) { fprintf(stderr, "qemu: read error on kernel '%s'\n", @@ -616,6 +624,7 @@ static void load_linux(const char *kernel_filename, gpr[4] = cmdline_addr-real_addr-16; /* SP (-16 is paranoia) */ generate_bootsect(gpr, seg, 0); +#endif } static void main_cpu_reset(void *opaque) @@ -719,12 +728,14 @@ static void pc_init1(int ram_size, int vga_ram_size, fprintf(stderr, "Unable to find x86 CPU definition\n"); exit(1); } +#ifndef CONFIG_DM if (i != 0) env->hflags |= HF_HALTED_MASK; if (smp_cpus > 1) { /* XXX: enable it in all cases */ env->cpuid_features |= CPUID_APIC; } +#endif /* !CONFIG_DM */ register_savevm("cpu", i, 4, cpu_save, cpu_load, env); qemu_register_reset(main_cpu_reset, env); if (pci_enabled) { @@ -733,6 +744,7 @@ static void pc_init1(int ram_size, int vga_ram_size, vmport_init(env); } +#ifndef CONFIG_DM /* allocate RAM */ ram_addr = qemu_ram_alloc(ram_size); cpu_register_physical_memory(0, ram_size, ram_addr); @@ -820,6 +832,7 @@ static void pc_init1(int ram_size, int vga_ram_size, /* map all the bios at the top of memory */ cpu_register_physical_memory((uint32_t)(-bios_size), bios_size, bios_offset | IO_MEM_ROM); +#endif /* !CONFIG_DM */ bochs_bios_init(); @@ -872,6 +885,7 @@ static void pc_init1(int ram_size, int vga_ram_size, register_ioport_read(0x92, 1, 1, ioport92_read, NULL); register_ioport_write(0x92, 1, 1, ioport92_write, NULL); +#ifndef CONFIG_DM if (pci_enabled) { ioapic = ioapic_init(); } @@ -880,6 +894,9 @@ static void pc_init1(int ram_size, int vga_ram_size, if (pci_enabled) { pic_set_alt_irq_func(isa_pic, ioapic_set_irq, ioapic); } +#endif /* !CONFIG_DM */ + if (pci_enabled) + pci_xen_platform_init(pci_bus); for(i = 0; i < MAX_SERIAL_PORTS; i++) { if (serial_hds[i]) { @@ -940,6 +957,11 @@ static void pc_init1(int ram_size, int vga_ram_size, } } +#ifdef HAS_TPM + if (has_tpm_device()) + tpm_tis_init(&i8259[11]); +#endif + i8042_init(i8259[1], i8259[12], 0x60); DMA_init(0); #ifdef HAS_AUDIO @@ -1030,3 +1052,134 @@ QEMUMachine isapc_machine = { "ISA-only PC", pc_init_isa, }; + + + + +/* + * Evil helper for non-relocatable kernels + * + * So it works out like this: + * + * 0x100000 - Xen HVM firmware lives here. Kernel wants to boot here + * + * You can't both live there and HVM firmware is needed first, thus + * our plan is + * + * 0x200000 - kernel is loaded here by QEMU + * 0x200000+kernel_size - helper code is put here by QEMU + * + * code32_switch in kernel header is set to point at out helper + * code at 0x200000+kernel_size + * + * Our helper basically does memmove(0x100000,0x200000,kernel_size) + * and then jmps to 0x1000000. + * + * So we've overwritten the HVM firmware (which was no longer + * needed) and the non-relocatable kernel can happily boot + * at its usual address. + * + * Simple, eh ? + * + * Well the assembler needed to do this is fairly short: + * + * # Load segments + * cld + * cli + * movl $0x18,%eax + * mov %ax,%ds + * mov %ax,%es + * mov %ax,%fs + * mov %ax,%gs + * mov %ax,%ss + * + * # Move the kernel into position + * xor %edx,%edx + *_doloop: + * movzbl 0x600000(%edx),%eax + * mov %al,0x100000(%edx) + * add $0x1,%edx + * cmp $0x500000,%edx + * jne _doloop + * + * # start kernel + * xorl %ebx,%ebx + * mov $0x100000,%ecx + * jmp *%ecx + * + */ +static void setup_relocator(target_phys_addr_t addr, target_phys_addr_t src, target_phys_addr_t dst, size_t len) +{ + /* Now this assembler corresponds to follow machine code, with our args from QEMU spliced in :-) */ + unsigned char buf[] = { + /* Load segments */ + 0xfc, /* cld */ + 0xfa, /* cli */ + 0xb8, 0x18, 0x00, 0x00, 0x00, /* mov $0x18,%eax */ + 0x8e, 0xd8, /* mov %eax,%ds */ + 0x8e, 0xc0, /* mov %eax,%es */ + 0x8e, 0xe0, /* mov %eax,%fs */ + 0x8e, 0xe8, /* mov %eax,%gs */ + 0x8e, 0xd0, /* mov %eax,%ss */ + 0x31, 0xd2, /* xor %edx,%edx */ + + /* Move the kernel into position */ + 0x0f, 0xb6, 0x82, (src&0xff), ((src>>8)&0xff), ((src>>16)&0xff), ((src>>24)&0xff), /* movzbl $src(%edx),%eax */ + 0x88, 0x82, (dst&0xff), ((dst>>8)&0xff), ((dst>>16)&0xff), ((dst>>24)&0xff), /* mov %al,$dst(%edx) */ + 0x83, 0xc2, 0x01, /* add $0x1,%edx */ + 0x81, 0xfa, (len&0xff), ((len>>8)&0xff), ((len>>16)&0xff), ((len>>24)&0xff), /* cmp $len,%edx */ + 0x75, 0xe8, /* jne 13 <_doloop> */ + + /* Start kernel */ + 0x31, 0xdb, /* xor %ebx,%ebx */ + 0xb9, (dst&0xff), ((dst>>8)&0xff), ((dst>>16)&0xff), ((dst>>24)&0xff), /* mov $dst,%ecx */ + 0xff, 0xe1, /* jmp *%ecx */ + }; + cpu_physical_memory_rw(addr, buf, sizeof(buf), 1); + fprintf(stderr, "qemu: helper at 0x%x of size %d bytes, to move kernel of %d bytes from 0x%x to 0x%x\n", + (int)addr, (int)sizeof(buf), (int)len, (int)src, (int)dst); +} + + +static void xen_relocator_hook(target_phys_addr_t prot_addr, uint16_t protocol, + uint8_t header[], int kernel_size) +{ + + /* Urgh, Xen's HVM firmware lives at 0x100000, but that's also the + * address Linux wants to start life at prior to relocatable support + */ + fprintf(stderr, "checking need for relocation, header protocol: %x\n", + protocol); + + if (prot_addr != 0x10000) { /* old low kernels are OK */ + target_phys_addr_t reloc_prot_addr = 0x20000; + + if (protocol >= 0x205 && (header[0x234] & 1)) { + /* Relocatable automatically */ + stl_p(header+0x214, reloc_prot_addr); + fprintf(stderr, "qemu: kernel is relocatable\n"); + } else { + /* Setup a helper which moves kernel back to + * its expected addr after firmware has got out + * of the way. We put a helper at reloc_prot_addr+kernel_size. + * It moves kernel from reloc_prot_addr to prot_addr and + * then jumps to prot_addr. Yes this is sick. + */ + fprintf(stderr, "qemu: kernel is NOT relocatable\n"); + stl_p(header+0x214, reloc_prot_addr + kernel_size); + setup_relocator(reloc_prot_addr + kernel_size, reloc_prot_addr, prot_addr, kernel_size); + } + } + + fprintf(stderr, "qemu: loading kernel real mode (%#x bytes) at %#zx\n", + setup_size-1024, real_addr); + fprintf(stderr, "qemu: loading kernel protected mode (%#x bytes) at %#zx\n", + kernel_size, reloc_prot_addr); +} + +#ifdef CONFIG_DM + +void vmport_init(CPUX86State *env) { } +void apic_init(CPUX86State *env) { } + +#endif /* CONFIG_DM */ diff --git a/hw/piix4acpi.c b/hw/piix4acpi.c index a4ebfc41..36d926f8 100644 --- a/hw/piix4acpi.c +++ b/hw/piix4acpi.c @@ -23,7 +23,10 @@ * THE SOFTWARE. */ -#include "vl.h" +#include "hw.h" +#include "pc.h" +#include "pci.h" + #include /* PM1a_CNT bits, as defined in the ACPI specification. */ @@ -497,7 +500,7 @@ void acpi_php_add(int pci_slot) #endif /* CONFIG_PASSTHROUGH */ /* PIIX4 acpi pci configuration space, func 2 */ -void pci_piix4_acpi_init(PCIBus *bus, int devfn) +void *piix4_pm_init(PCIBus *bus, int devfn) { PCIAcpiState *d; uint8_t *pci_conf; diff --git a/i386-dm/hooks.mak b/i386-dm/hooks.mak index 5d593f4e..64571b48 100644 --- a/i386-dm/hooks.mak +++ b/i386-dm/hooks.mak @@ -1,4 +1,3 @@ -OBJS += $(SOUND_HW) $(AUDIODRV) mixeng.o CPPFLAGS += -DHAS_AUDIO QEMU_PROG=qemu-dm include ../xen-hooks.mak diff --git a/i386-dm/i8259.c b/i386-dm/i8259.c new file mode 100644 index 00000000..4b7c044b --- /dev/null +++ b/i386-dm/i8259.c @@ -0,0 +1,51 @@ +/* Xen 8259 stub for interrupt controller emulation + * + * Copyright (c) 2003-2004 Fabrice Bellard + * Copyright (c) 2005 Intel corperation + * Copyright (c) 2008 Citrix / Xensource + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "hw.h" +#include "pc.h" + +#include +#include + +static void i8259_set_irq(void *opaque, int irq, int level) { + xc_hvm_set_isa_irq_level(xc_handle, domid, irq, level); +} + +qemu_irq *i8259_init(qemu_irq parent_irq) +{ + return qemu_allocate_irqs(i8259_set_irq, s, 16); +} + +#if 0 +void irq_info(void) +{ + term_printf("irq statistics not supported with Xen.\n"); +} + +void pic_info(void) +{ + term_printf("pic_info not supported with Xen .\n"); +} +#endif diff --git a/xen-config-host.mak b/xen-config-host.mak index 9e9b589f..696b269f 100644 --- a/xen-config-host.mak +++ b/xen-config-host.mak @@ -39,3 +39,5 @@ SDL_CFLAGS=-I/usr/include/SDL -D_GNU_SOURCE=1 -D_REENTRANT CONFIG_CURSES=yes CURSES_LIBS=-lcurses TOOLS=qemu-img$(EXESUF) + +TARGET_DIRS = i386-dm i386-stubdom diff --git a/xen-hooks.mak b/xen-hooks.mak index 86a692d2..de3ce375 100644 --- a/xen-hooks.mak +++ b/xen-hooks.mak @@ -9,14 +9,14 @@ endif QEMU_PROG=qemu-dm -CFLAGS += -Wno-unused -Werror +#CFLAGS += -Wno-unused -Wno-declaration-after-statement +# -Werror LIBS += -L../../libxc -lxenctrl -lxenguest LIBS += -L../../xenstore -lxenstore LDFLAGS := $(CFLAGS) $(LDFLAGS) -OBJS += loader.o OBJS += piix4acpi.o OBJS += xenstore.o OBJS += xen_platform.o @@ -26,6 +26,6 @@ OBJS += xenfb.o OBJS += xen_console.o OBJS += xen_machine_fv.o -BAD_OBJS += monitor.o +BAD_OBJS += loader.o monitor.o gdbstub.o acpi.o OBJS := $(filter-out $(BAD_OBJS), $(OBJS))