Commit 19f1537b authored by Rusty Russell's avatar Rusty Russell

Lguest support for Virtio

This makes lguest able to use the virtio devices.

We change the device descriptor page from a simple array to a variable
length "type, config_len, status, config data..." format, and
implement virtio_config_ops to read from that config data.

We use the virtio ring implementation for an efficient Guest <-> Host
virtqueue mechanism, and the new LHCALL_NOTIFY hypercall to kick the
host when it changes.

We also use LHCALL_NOTIFY on kernel addresses for very very early
console output.  We could have another hypercall, but this hack works
quite well.
Signed-off-by: default avatarRusty Russell <rusty@rustcorp.com.au>
parent 15045275
...@@ -2,8 +2,13 @@ config LGUEST_GUEST ...@@ -2,8 +2,13 @@ config LGUEST_GUEST
bool "Lguest guest support" bool "Lguest guest support"
select PARAVIRT select PARAVIRT
depends on !X86_PAE depends on !X86_PAE
select VIRTIO
select VIRTIO_RING select VIRTIO_RING
select VIRTIO_CONSOLE
help help
Lguest is a tiny in-kernel hypervisor. Selecting this will Lguest is a tiny in-kernel hypervisor. Selecting this will
allow your kernel to boot under lguest. This option will increase allow your kernel to boot under lguest. This option will increase
your kernel size by about 6k. If in doubt, say N. your kernel size by about 6k. If in doubt, say N.
If you say Y here, make sure you say Y (or M) to the virtio block
and net drivers which lguest needs.
...@@ -55,6 +55,7 @@ ...@@ -55,6 +55,7 @@
#include <linux/clockchips.h> #include <linux/clockchips.h>
#include <linux/lguest.h> #include <linux/lguest.h>
#include <linux/lguest_launcher.h> #include <linux/lguest_launcher.h>
#include <linux/virtio_console.h>
#include <asm/paravirt.h> #include <asm/paravirt.h>
#include <asm/param.h> #include <asm/param.h>
#include <asm/page.h> #include <asm/page.h>
...@@ -849,6 +850,23 @@ static __init char *lguest_memory_setup(void) ...@@ -849,6 +850,23 @@ static __init char *lguest_memory_setup(void)
return "LGUEST"; return "LGUEST";
} }
/* Before virtqueues are set up, we use LHCALL_NOTIFY on normal memory to
* produce console output. */
static __init int early_put_chars(u32 vtermno, const char *buf, int count)
{
char scratch[17];
unsigned int len = count;
if (len > sizeof(scratch) - 1)
len = sizeof(scratch) - 1;
scratch[len] = '\0';
memcpy(scratch, buf, len);
hcall(LHCALL_NOTIFY, __pa(scratch), 0, 0);
/* This routine returns the number of bytes actually written. */
return len;
}
/*G:050 /*G:050
* Patching (Powerfully Placating Performance Pedants) * Patching (Powerfully Placating Performance Pedants)
* *
...@@ -1048,6 +1066,9 @@ __init void lguest_init(void *boot) ...@@ -1048,6 +1066,9 @@ __init void lguest_init(void *boot)
* adapted for lguest's use. */ * adapted for lguest's use. */
add_preferred_console("hvc", 0, NULL); add_preferred_console("hvc", 0, NULL);
/* Register our very early console. */
virtio_cons_early_init(early_put_chars);
/* Last of all, we set the power management poweroff hook to point to /* Last of all, we set the power management poweroff hook to point to
* the Guest routine to power off. */ * the Guest routine to power off. */
pm_power_off = lguest_power_off; pm_power_off = lguest_power_off;
......
# Guest requires the device configuration and probing code.
obj-$(CONFIG_LGUEST_GUEST) += lguest_device.o
# Host requires the other files, which can be a module. # Host requires the other files, which can be a module.
obj-$(CONFIG_LGUEST) += lg.o obj-$(CONFIG_LGUEST) += lg.o
lg-y = core.o hypercalls.o page_tables.o interrupts_and_traps.o \ lg-y = core.o hypercalls.o page_tables.o interrupts_and_traps.o \
......
This diff is collapsed.
...@@ -22,37 +22,28 @@ ...@@ -22,37 +22,28 @@
* complex burden for the Host and suboptimal for the Guest, so we have our own * complex burden for the Host and suboptimal for the Guest, so we have our own
* "lguest" bus and simple drivers. * "lguest" bus and simple drivers.
* *
* Devices are described by an array of LGUEST_MAX_DEVICES of these structs, * Devices are described by a simplified ID, a status byte, and some "config"
* placed by the Launcher just above the top of physical memory: * bytes which describe this device's configuration. This is placed by the
* Launcher just above the top of physical memory:
*/ */
struct lguest_device_desc { struct lguest_device_desc {
/* The device type: console, network, disk etc. */ /* The device type: console, network, disk etc. Type 0 terminates. */
__u16 type; __u8 type;
#define LGUEST_DEVICE_T_CONSOLE 1 /* The number of bytes of the config array. */
#define LGUEST_DEVICE_T_NET 2 __u8 config_len;
#define LGUEST_DEVICE_T_BLOCK 3 /* A status byte, written by the Guest. */
__u8 status;
/* The specific features of this device: these depends on device type __u8 config[0];
* except for LGUEST_DEVICE_F_RANDOMNESS. */ };
__u16 features;
#define LGUEST_NET_F_NOCSUM 0x4000 /* Don't bother checksumming */
#define LGUEST_DEVICE_F_RANDOMNESS 0x8000 /* IRQ is fairly random */
/* This is how the Guest reports status of the device: the Host can set
* LGUEST_DEVICE_S_REMOVED to indicate removal, but the rest are only
* ever manipulated by the Guest, and only ever set. */
__u16 status;
/* 256 and above are device specific. */
#define LGUEST_DEVICE_S_ACKNOWLEDGE 1 /* We have seen device. */
#define LGUEST_DEVICE_S_DRIVER 2 /* We have found a driver */
#define LGUEST_DEVICE_S_DRIVER_OK 4 /* Driver says OK! */
#define LGUEST_DEVICE_S_REMOVED 8 /* Device has gone away. */
#define LGUEST_DEVICE_S_REMOVED_ACK 16 /* Driver has been told. */
#define LGUEST_DEVICE_S_FAILED 128 /* Something actually failed */
/* Each device exists somewhere in Guest physical memory, over some /*D:135 This is how we expect the device configuration field for a virtqueue
* number of pages. */ * (type VIRTIO_CONFIG_F_VIRTQUEUE) to be laid out: */
__u16 num_pages; struct lguest_vqconfig {
/* The number of entries in the virtio_ring */
__u16 num;
/* The interrupt we get when something happens. */
__u16 irq;
/* The page number of the virtio ring for this device. */
__u32 pfn; __u32 pfn;
}; };
/*:*/ /*:*/
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment