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:47 +0300 [thread overview]
Message-ID: <46DEE137.5020102@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/
next prev 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
2007-09-05 17:02 ` Avi Kivity [this message]
[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=46DEE137.5020102@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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.