public inbox for kvm@vger.kernel.org
 help / color / mirror / Atom feed
From: Rusty Russell <rusty-8n+1lVoiYb80n/F98K4Iww@public.gmane.org>
To: kvm-devel <kvm-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
Subject: [PATCH 5/5] kvm-lite qemu patch
Date: Thu, 06 Sep 2007 01:44:47 +1000	[thread overview]
Message-ID: <1189007087.10802.144.camel@localhost.localdomain> (raw)
In-Reply-To: <1189006973.10802.140.camel-bi+AKbBUZKY6gyzm1THtWbp2dZbC/Bob@public.gmane.org>

"-M pclite" requires -kernel, requires kvm.  Also changes --enable-kvm
to --disable-kvm (it's enabled on supported archs, so we need a disable
not an enable flag).

index d9292fe..bf4c8ba 100755
--- a/configure
+++ b/configure
@@ -84,7 +84,7 @@ target_cpu() {
 (cd qemu; ./configure --target-list=$(target_cpu)-softmmu --cc="$qemu_cc" \
     --disable-kqemu --extra-cflags="-I $PWD/../user" \
     --extra-ldflags="-L $PWD/../user" \
-    --enable-kvm --kernel-path="$libkvm_kerneldir" \
+    --kernel-path="$libkvm_kerneldir" \
     --enable-alsa \
     ${disable_gcc_check:+"--disable-gcc-check"} \
     --prefix="$prefix"
index 365b7fb..9455e3c 100755
--- a/qemu/configure
+++ b/qemu/configure
@@ -236,7 +236,7 @@ for opt do
   ;;
   --disable-kqemu) kqemu="no"
   ;;
-  --enable-kvm) kvm="yes"
+  --disable-kvm) kvm="no"
   ;;
   --enable-profiler) profiler="yes"
   ;;
@@ -286,7 +286,7 @@ echo ""
 echo "kqemu kernel acceleration support:"
 echo "  --disable-kqemu          disable kqemu support"
 echo "  --kernel-path=PATH       set the kernel path (configure probes it)"
-echo "  --enable-kvm             enable kernel virtual machine support"
+echo "  --disable-kvm            disable kernel virtual machine support"
 echo ""
 echo "Advanced options (experts only):"
 echo "  --source-path=PATH       path of source code [$source_path]"
index ae92173..c8520a6 100644
--- a/qemu/hw/pc.c
+++ b/qemu/hw/pc.c
@@ -820,6 +820,236 @@ static void pc_init_isa(int ram_size, int vga_ram_size, int boot_device,
              initrd_filename, 0);
 }
 
+#ifdef USE_KVM
+/* FIXME: Run without paging and then turn it on, like normal Guest. */
+/* Once we know how much memory we have, we can construct simple linear page
+ * tables which set virtual == physical which will get the Guest far enough
+ * into the boot to create its own.
+ *
+ * We lay them out of the way, just below the initrd, which is why we need to
+ * know its offset (== mem if no initrd). */
+static unsigned long linear_pagetables(unsigned long mem,
+				       unsigned long initrd_offset)
+{
+	unsigned long pgdir, linear;
+	unsigned int mapped_pages, i, linear_pages;
+	unsigned int ptes_per_page = 1024;
+	unsigned long pageflags = PG_PRESENT_MASK|PG_RW_MASK;
+
+	mapped_pages = mem/TARGET_PAGE_SIZE;
+
+	/* Each PTE page can map ptes_per_page pages: how many do we need? */
+	linear_pages = (mapped_pages + ptes_per_page-1)/ptes_per_page;
+
+	/* We put the toplevel page directory page at the top of memory. */
+	pgdir = initrd_offset - TARGET_PAGE_SIZE;
+
+	/* Now we use the next linear_pages pages as pte pages */
+	linear = pgdir - linear_pages*TARGET_PAGE_SIZE;
+
+	/* Linear mapping is easy: put every page's address into the mapping in
+	 * order. */
+	for (i = 0; i < mapped_pages; i++)
+	    stl_raw(phys_ram_base + linear + i * sizeof(long),
+		    (i * TARGET_PAGE_SIZE) | pageflags);
+
+	/* The top level points to the linear page table pages above. */
+	for (i = 0; i < mapped_pages; i += ptes_per_page)
+	    stl_raw(phys_ram_base + pgdir + i/ptes_per_page * sizeof(long),
+		    (linear + i*4) | pageflags);
+
+	/* We return the top level (guest-physical) address: the kernel needs
+	 * to know where it is. */
+	return (unsigned long)pgdir;
+}
+
+static void hack_console_write(void *opaque, uint32_t addr, uint32_t val)
+{
+    printf("%c", val); fflush(stdout);
+}
+
+static void hack_timer_write(void *opaque, uint32_t addr, uint32_t val)
+{
+    QEMUTimer *irq_timer = opaque;
+
+    if (val == 0)
+        qemu_del_timer(irq_timer);
+    else
+	qemu_mod_timer(irq_timer, qemu_get_clock(vm_clock) + val);
+}
+
+/* FIXME: I don't think this is the right way to do an interrupt. */
+static void hack_timer_tick(void *opaque)
+{
+    first_cpu->hflags &= ~HF_HALTED_MASK;
+    if (kvm_inject_irq(kvm_context, 0, 32) != 0)
+	fprintf(stderr, "Failed to inject timer irq: %m\n");
+}
+
+static void pc_init_lite(int ram_size, int vga_ram_size, int boot_device,
+                        DisplayState *ds, const char **fd_filename, 
+                        int snapshot, 
+                        const char *kernel_filename, 
+                        const char *kernel_cmdline,
+                        const char *initrd_filename)
+{
+    int ret, initrd_size, i;
+    ram_addr_t initrd_offset;
+    CPUState *env;
+    uint8_t *video_mem;
+    QEMUTimer *irq_timer;
+
+    printf("Starting pc lite init\n");
+
+    if (!kernel_filename) {
+        fprintf(stderr, "qemu: pclite needs -kernel\n");
+        exit(1);
+    }
+
+    /* init CPUs */
+    for(i = 0; i < smp_cpus; i++) {
+        env = cpu_init();
+        if (i != 0)
+            env->hflags |= HF_HALTED_MASK;
+        if (smp_cpus > 1) {
+            /* XXX: enable it in all cases */
+            env->cpuid_features |= CPUID_APIC;
+	    /* FIXME */
+	    fprintf(stderr, "Sorry, SMP not supported");
+	    exit(1);
+        }
+	apic_init(env);
+        register_savevm("cpu", i, 4, cpu_save, cpu_load, env);
+        qemu_register_reset(main_cpu_reset, env);
+    }
+
+    printf("pc lite init: %u\n", __LINE__);
+    /* allocate RAM */
+    cpu_register_physical_memory(0, ram_size, 0);
+
+    /* FIXME: Wire this in somewhere? */
+    ioapic_init();
+
+#if 0
+    isa_pic = pic_init(pic_irq_request, first_cpu);
+    pit = pit_init(0x40, 0);
+    for(i = 0; i < MAX_SERIAL_PORTS; i++) {
+        if (serial_hds[i]) {
+            serial_init(&pic_set_irq_new, isa_pic,
+                        serial_io[i], serial_irq[i], serial_hds[i]);
+        }
+    }
+#endif
+
+    irq_timer = qemu_new_timer(vm_clock, hack_timer_tick, NULL);
+
+    register_ioport_write(0x1, 1, 1, hack_console_write, NULL);
+    register_ioport_write(0x2, 1, 4, hack_timer_write, irq_timer);
+
+    /* FIXME: kvm_create() "knows" the layout of x86 and doesn't map
+     * all the memory.  Map the video memory here. */
+    video_mem = kvm_create_phys_mem(kvm_context, 0xA0000, 0x20000, 2, 0, 1);
+    if (!video_mem)
+	exit(1);
+
+#if 0
+    register_ioport_write(0x3d4, 1, 1, hack_vga_console_write,
+			  phys_ram_base + 0xB8000);
+    register_ioport_write(0x3d5, 1, 1, hack_vga_console_write,
+			  phys_ram_base + 0xB8000);
+#endif
+
+    /* now we can load the kernel */
+    ret = load_kernel(kernel_filename, 
+		      phys_ram_base + KERNEL_LOAD_ADDR,
+		      phys_ram_base + KERNEL_PARAMS_ADDR);
+    if (ret < 0) {
+	fprintf(stderr, "qemu: could not load kernel '%s'\n", kernel_filename);
+	exit(1);
+    }
+
+    /* load initrd */
+    initrd_size = 0;
+    initrd_offset = ram_size;
+    if (initrd_filename) {
+	initrd_size = get_image_size (initrd_filename);
+	if (initrd_size > 0) {
+	    initrd_offset = (ram_size - initrd_size) & TARGET_PAGE_MASK;
+	    if (initrd_offset > MAX_INITRD_LOAD_ADDR)
+		initrd_offset = MAX_INITRD_LOAD_ADDR;
+
+	    if (initrd_size > ram_size
+		|| initrd_offset < KERNEL_LOAD_ADDR + ret) {
+		fprintf(stderr,
+			"qemu: memory too small for initial ram disk '%s'\n",
+			initrd_filename);
+		exit(1);
+	    }
+	    initrd_size = load_image(initrd_filename,
+				     phys_ram_base + initrd_offset);
+	}
+	if (initrd_size < 0) {
+	    fprintf(stderr, "qemu: could not load initial ram disk '%s'\n", 
+		    initrd_filename);
+	    exit(1);
+	}
+    }
+    if (initrd_size > 0) {
+	stl_raw(phys_ram_base + KERNEL_PARAMS_ADDR + 0x218, initrd_offset);
+	stl_raw(phys_ram_base + KERNEL_PARAMS_ADDR + 0x21c, initrd_size);
+    }
+    printf("pc lite init: %u\n", __LINE__);
+
+    /* Mug screen_info */
+    memset(phys_ram_base + KERNEL_PARAMS_ADDR, 0, 0x40);
+    pstrcpy(phys_ram_base + KERNEL_CMDLINE_ADDR, 4096,
+	    kernel_cmdline);
+    stw_raw(phys_ram_base + KERNEL_PARAMS_ADDR + 0x20, 0xA33F);
+    stw_raw(phys_ram_base + KERNEL_PARAMS_ADDR + 0x22,
+	    KERNEL_CMDLINE_ADDR - KERNEL_PARAMS_ADDR);
+    /* loader type */
+    stw_raw(phys_ram_base + KERNEL_PARAMS_ADDR + 0x210, 0x01);
+    
+    /* Platform: kvm-lite */
+    stl_raw(phys_ram_base + KERNEL_PARAMS_ADDR + 0x23c, 0x02);
+
+    env->eip = KERNEL_LOAD_ADDR;
+    env->eflags = 0x002;
+    env->regs[R_ESI] = KERNEL_PARAMS_ADDR;
+
+    /* The Linux boot header contains an "E820" memory map: ours is a simple,
+     * single region. */
+    stb_raw(phys_ram_base + KERNEL_PARAMS_ADDR + 0x1e8, 1);
+    /* Zero it out first. */
+    memset(phys_ram_base + KERNEL_PARAMS_ADDR + 0x2d0, 0, 20);
+    stl_raw(phys_ram_base + KERNEL_PARAMS_ADDR + 0x2d8, ram_size);
+    stl_raw(phys_ram_base + KERNEL_PARAMS_ADDR + 0x2e0, 1 /* RAM */);
+
+    /* KERNEL_CS ring 1 */
+    cpu_x86_load_seg_cache(env, R_CS, 12*8+1, 0, 0xffffffff, 0x00cf9b00);
+    /* KERNEL_DS ring 1 */
+    cpu_x86_load_seg_cache(env, R_DS, 13*8+1, 0, 0xffffffff, 0x00cf9300);
+    cpu_x86_load_seg_cache(env, R_SS, 13*8+1, 0, 0xffffffff, 0x00cf9300);
+    cpu_x86_load_seg_cache(env, R_ES, 13*8+1, 0, 0xffffffff, 0x00cf9300);
+
+    /* Page table pointer. */
+    env->cr[3] = linear_pagetables(ram_size, initrd_offset);
+
+    /* KVM code cares that CR0 is set correctly (lite doesn't). */
+    env->cr[0] = CR0_PG_MASK | CR0_WP_MASK | CR0_PE_MASK;
+
+    /* We seem to need to force KVM to get these regs now. */
+    kvm_load_registers(env);
+    printf("Done pc lite init\n");
+}
+
+QEMUMachine pclite_machine = {
+    "pclite",
+    "kvm-lite PC",
+    pc_init_lite,
+};
+#endif /* USE_KVM */
+
 QEMUMachine pc_machine = {
     "pc",
     "Standard PC",
@@ -831,3 +1061,4 @@ QEMUMachine isapc_machine = {
     "ISA-only PC",
     pc_init_isa,
 };
+
index 4ba93d8..a91eaa6 100644
--- a/qemu/qemu-kvm.c
+++ b/qemu/qemu-kvm.c
@@ -9,6 +9,7 @@
 #endif
 
 int kvm_allowed = KVM_ALLOWED_DEFAULT;
+int kvm_lite = 0;
 
 #ifdef USE_KVM
 
index bacda22..c27fcbb 100644
--- a/qemu/qemu-kvm.h
+++ b/qemu/qemu-kvm.h
@@ -24,6 +24,7 @@ void qemu_kvm_cpuid_on_env(CPUState *env);
 void kvm_update_after_sipi(CPUState *env);
 void kvm_update_interrupt_request(CPUState *env);
 
+extern int kvm_lite;
 
 #define ALIGN(x, y)  (((x)+(y)-1) & ~((y)-1))
 #define BITMAP_SIZE(m) (ALIGN(((m)>>TARGET_PAGE_BITS), HOST_LONG_BITS) / 8)
index 4ad39f1..cc43d06 100644
--- a/qemu/vl.c
+++ b/qemu/vl.c
@@ -6576,6 +6576,8 @@ enum {
     QEMU_OPTION_no_rtc,
 #endif
     QEMU_OPTION_cpu_vendor,
+/* FIXME: Better to probe for this. */
+    QEMU_OPTION_kvm_lite,
 };
 
 typedef struct QEMUOption {
@@ -6635,6 +6637,7 @@ const QEMUOption qemu_options[] = {
 #endif
 #ifdef USE_KVM
     { "no-kvm", 0, QEMU_OPTION_no_kvm },
+    { "kvm-lite", 0, QEMU_OPTION_kvm_lite },
 #endif
 #if defined(TARGET_PPC) || defined(TARGET_SPARC)
     { "g", 1, QEMU_OPTION_g },
@@ -6728,6 +6731,9 @@ void register_machines(void)
 #if defined(TARGET_I386)
     qemu_register_machine(&pc_machine);
     qemu_register_machine(&isapc_machine);
+#if defined(USE_KVM)
+    qemu_register_machine(&pclite_machine);
+#endif
 #elif defined(TARGET_PPC)
     qemu_register_machine(&heathrow_machine);
     qemu_register_machine(&core99_machine);
@@ -7344,6 +7350,9 @@ int main(int argc, char **argv)
 	    case QEMU_OPTION_no_kvm:
 		kvm_allowed = 0;
 		break;
+	    case QEMU_OPTION_kvm_lite:
+		kvm_lite = 1;
+		break;
 #endif
             case QEMU_OPTION_usb:
                 usb_enabled = 1;
@@ -7450,6 +7459,7 @@ int main(int argc, char **argv)
 	if (kvm_qemu_init() < 0) {
 	    fprintf(stderr, "Could not initialize KVM, will disable KVM support\n");
 	    kvm_allowed = 0;
+	    kvm_lite = 0;
 	}
     }
 #endif
index 43f56bd..9fd38ba 100644
--- a/qemu/vl.h
+++ b/qemu/vl.h
@@ -1099,6 +1099,7 @@ SMBusDevice *smbus_eeprom_device_init(uint8_t addr, uint8_t *buf);
 /* pc.c */
 extern QEMUMachine pc_machine;
 extern QEMUMachine isapc_machine;
+extern QEMUMachine pclite_machine;
 extern int fd_bootchk;
 
 void ioport_set_a20(int enable);



-------------------------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc.
Still grepping through log files to find problems?  Stop.
Now Search log events and configuration files using AJAX and a browser.
Download your FREE copy of Splunk now >>  http://get.splunk.com/

  parent reply	other threads:[~2007-09-05 15:44 UTC|newest]

Thread overview: 18+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2007-09-05 15:19 [PATCH 1/5] Clean up unloved invlpg: remove kvm_arch_ops.invlpg and tweak emulator Rusty Russell
     [not found] ` <1189005567.10802.127.camel-bi+AKbBUZKY6gyzm1THtWbp2dZbC/Bob@public.gmane.org>
2007-09-05 15:20   ` [PATCH 2/5] Keep control regs in sync Rusty Russell
     [not found]     ` <1189005638.10802.129.camel-bi+AKbBUZKY6gyzm1THtWbp2dZbC/Bob@public.gmane.org>
2007-09-05 15:21       ` [PATCH 3/5] Hoist SVM's get_cs_db_l_bits into core code Rusty Russell
     [not found]         ` <1189005692.10802.132.camel-bi+AKbBUZKY6gyzm1THtWbp2dZbC/Bob@public.gmane.org>
2007-09-05 15:42           ` [PATCH 4/5] kvm-lite: "The Unbearable Liteness" Rusty Russell
     [not found]             ` <1189006973.10802.140.camel-bi+AKbBUZKY6gyzm1THtWbp2dZbC/Bob@public.gmane.org>
2007-09-05 15:44               ` Rusty Russell [this message]
     [not found]                 ` <1189007087.10802.144.camel-bi+AKbBUZKY6gyzm1THtWbp2dZbC/Bob@public.gmane.org>
2007-09-05 17:02                   ` [PATCH 5/5] kvm-lite qemu patch Avi Kivity
2007-09-05 17:02                   ` Avi Kivity
     [not found]                     ` <46DEE137.5020102-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
2007-09-05 17:36                       ` Rusty Russell
     [not found]                         ` <1189013805.10802.168.camel-bi+AKbBUZKY6gyzm1THtWbp2dZbC/Bob@public.gmane.org>
2007-09-05 19:10                           ` Avi Kivity
2007-09-05 15:47               ` [PATCH 4/5] kvm-lite: "The Unbearable Liteness" Anthony Liguori
2007-09-05 16:16                 ` Rusty Russell
     [not found]                   ` <1189008968.10802.154.camel-bi+AKbBUZKY6gyzm1THtWbp2dZbC/Bob@public.gmane.org>
2007-09-05 16:21                     ` Anthony Liguori
2007-09-05 17:08                       ` Avi Kivity
2007-09-05 17:02               ` Avi Kivity
2007-09-09 11:22           ` [PATCH 3/5] Hoist SVM's get_cs_db_l_bits into core code Avi Kivity
2007-09-05 15:30   ` [PATCH 1/5] Clean up unloved invlpg: remove kvm_arch_ops.invlpg and tweak emulator Avi Kivity
     [not found]     ` <46DECBA7.7020905-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
2007-09-05 16:22       ` Rusty Russell
     [not found]         ` <1189009359.10802.157.camel-bi+AKbBUZKY6gyzm1THtWbp2dZbC/Bob@public.gmane.org>
2007-09-09 11:13           ` Avi Kivity

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1189007087.10802.144.camel@localhost.localdomain \
    --to=rusty-8n+1lvoiyb80n/f98k4iww@public.gmane.org \
    --cc=kvm-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f@public.gmane.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox