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/
next prev 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