public inbox for kvm@vger.kernel.org
 help / color / mirror / Atom feed
From: Avi Kivity <avi-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
To: Rusty Russell <rusty-8n+1lVoiYb80n/F98K4Iww@public.gmane.org>
Cc: kvm-devel <kvm-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
Subject: Re: [PATCH 5/5] kvm-lite qemu patch
Date: Wed, 05 Sep 2007 20:02:31 +0300	[thread overview]
Message-ID: <46DEE127.80702@qumranet.com> (raw)
In-Reply-To: <1189007087.10802.144.camel-bi+AKbBUZKY6gyzm1THtWbp2dZbC/Bob@public.gmane.org>

Rusty Russell wrote:
> "-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).
> +#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 */
> +
>   

Most of this hunk should go into a separate file.

It would also be nice to support the hypercalls in qemu, so we can run 
without kernel support (on non-x86 hardware, for example).



-- 
Any sufficiently difficult bug is indistinguishable from a feature.


-------------------------------------------------------------------------
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 17:02 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               ` [PATCH 5/5] kvm-lite qemu patch Rusty Russell
     [not found]                 ` <1189007087.10802.144.camel-bi+AKbBUZKY6gyzm1THtWbp2dZbC/Bob@public.gmane.org>
2007-09-05 17:02                   ` Avi Kivity [this message]
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=46DEE127.80702@qumranet.com \
    --to=avi-atkuwr5tajbwk0htik3j/w@public.gmane.org \
    --cc=kvm-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f@public.gmane.org \
    --cc=rusty-8n+1lVoiYb80n/F98K4Iww@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