]> xenbits.xensource.com Git - qemu-xen-4.6-testing.git/commitdiff
WIP merge with xen-unstable
authorIan Jackson <iwj@mariner.uk.xensource.com>
Wed, 19 Mar 2008 17:08:21 +0000 (17:08 +0000)
committerIan Jackson <Ian.Jackson@eu.citrix.com>
Mon, 12 May 2008 11:20:10 +0000 (12:20 +0100)
Includes new i8259.c, more or less completely merged pc.c, acpi
adjustments, and various build system fixes.

hw/pc.c
hw/piix4acpi.c
i386-dm/hooks.mak
i386-dm/i8259.c [new file with mode: 0644]
xen-config-host.mak
xen-hooks.mak

diff --git a/hw/pc.c b/hw/pc.c
index fbbc7a0f1852c4552087f76cf021daa5fd245bff..eb4be15a773dbd4957cdf25c7bd239da123e428e 100644 (file)
--- 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 */
index a4ebfc4163f6b495c3573766a89555000ff4d39b..36d926f876d1ae2f9b0245d2f91447c8131286f3 100644 (file)
  * THE SOFTWARE.
  */
 
-#include "vl.h"
+#include "hw.h"
+#include "pc.h"
+#include "pci.h"
+
 #include <xen/hvm/ioreq.h>
 
 /* 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;
index 5d593f4e945cbd9183fd5c75071856b17d1cc76f..64571b48147d6dd2ad888462d9295ab7b6a775bf 100644 (file)
@@ -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 (file)
index 0000000..4b7c044
--- /dev/null
@@ -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 <xen/hvm/ioreq.h>
+#include <stdio.h>
+
+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
index 9e9b589f4e0175f74cc5585f5b72d5aa14f46b0d..696b269f57fd60186dcb346f8c4b69fb036c7459 100644 (file)
@@ -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
index 86a692d2e09e271015d1fbbf4ba45f324b9b7e10..de3ce3751bbdfc87b0453751ed208ca03c4eda60 100644 (file)
@@ -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))