diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2008-12-30 20:37:25 -0500 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-12-30 20:37:25 -0500 |
| commit | ab70537c32a3245325b48774664da588904e47f2 (patch) | |
| tree | fdb4447e520bd34dd8696fdd3b976075414d8555 | |
| parent | 14a3c4ab0e58d143c7928c9eb2f2610205e13bf2 (diff) | |
| parent | bda53cd510b6777ced652ba279020bb7b414b744 (diff) | |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/rusty/linux-2.6-for-linus
* git://git.kernel.org/pub/scm/linux/kernel/git/rusty/linux-2.6-for-linus:
lguest: struct device - replace bus_id with dev_name()
lguest: move the initial guest page table creation code to the host
kvm-s390: implement config_changed for virtio on s390
virtio_console: support console resizing
virtio: add PCI device release() function
virtio_blk: fix type warning
virtio: block: dynamic maximum segments
virtio: set max_segment_size and max_sectors to infinite.
virtio: avoid implicit use of Linux page size in balloon interface
virtio: hand virtio ring alignment as argument to vring_new_virtqueue
virtio: use KVM_S390_VIRTIO_RING_ALIGN instead of relying on pagesize
virtio: use LGUEST_VRING_ALIGN instead of relying on pagesize
virtio: Don't use PAGE_SIZE for vring alignment in virtio_pci.
virtio: rename 'pagesize' arg to vring_init/vring_size
virtio: Don't use PAGE_SIZE in virtio_pci.c
virtio: struct device - replace bus_id with dev_name(), dev_set_name()
virtio-pci queue allocation not page-aligned
| -rw-r--r-- | Documentation/lguest/lguest.c | 66 | ||||
| -rw-r--r-- | arch/s390/include/asm/kvm_virtio.h | 4 | ||||
| -rw-r--r-- | arch/x86/lguest/i386_head.S | 15 | ||||
| -rw-r--r-- | drivers/block/virtio_blk.c | 41 | ||||
| -rw-r--r-- | drivers/char/hvc_console.c | 1 | ||||
| -rw-r--r-- | drivers/char/virtio_console.c | 30 | ||||
| -rw-r--r-- | drivers/lguest/lg.h | 2 | ||||
| -rw-r--r-- | drivers/lguest/lguest_device.c | 8 | ||||
| -rw-r--r-- | drivers/lguest/lguest_user.c | 13 | ||||
| -rw-r--r-- | drivers/lguest/page_tables.c | 72 | ||||
| -rw-r--r-- | drivers/s390/kvm/kvm_virtio.c | 34 | ||||
| -rw-r--r-- | drivers/virtio/virtio.c | 2 | ||||
| -rw-r--r-- | drivers/virtio/virtio_balloon.c | 13 | ||||
| -rw-r--r-- | drivers/virtio/virtio_pci.c | 43 | ||||
| -rw-r--r-- | drivers/virtio/virtio_ring.c | 3 | ||||
| -rw-r--r-- | include/linux/lguest_launcher.h | 6 | ||||
| -rw-r--r-- | include/linux/virtio_balloon.h | 3 | ||||
| -rw-r--r-- | include/linux/virtio_console.h | 11 | ||||
| -rw-r--r-- | include/linux/virtio_pci.h | 8 | ||||
| -rw-r--r-- | include/linux/virtio_ring.h | 13 |
20 files changed, 253 insertions, 135 deletions
diff --git a/Documentation/lguest/lguest.c b/Documentation/lguest/lguest.c index 804520633fcf..f2dbbf3bdeab 100644 --- a/Documentation/lguest/lguest.c +++ b/Documentation/lguest/lguest.c | |||
| @@ -481,51 +481,6 @@ static unsigned long load_initrd(const char *name, unsigned long mem) | |||
| 481 | /* We return the initrd size. */ | 481 | /* We return the initrd size. */ |
| 482 | return len; | 482 | return len; |
| 483 | } | 483 | } |
| 484 | |||
| 485 | /* Once we know how much memory we have we can construct simple linear page | ||
| 486 | * tables which set virtual == physical which will get the Guest far enough | ||
| 487 | * into the boot to create its own. | ||
| 488 | * | ||
| 489 | * We lay them out of the way, just below the initrd (which is why we need to | ||
| 490 | * know its size here). */ | ||
| 491 | static unsigned long setup_pagetables(unsigned long mem, | ||
| 492 | unsigned long initrd_size) | ||
| 493 | { | ||
| 494 | unsigned long *pgdir, *linear; | ||
| 495 | unsigned int mapped_pages, i, linear_pages; | ||
| 496 | unsigned int ptes_per_page = getpagesize()/sizeof(void *); | ||
| 497 | |||
| 498 | mapped_pages = mem/getpagesize(); | ||
| 499 | |||
| 500 | /* Each PTE page can map ptes_per_page pages: how many do we need? */ | ||
| 501 | linear_pages = (mapped_pages + ptes_per_page-1)/ptes_per_page; | ||
| 502 | |||
| 503 | /* We put the toplevel page directory page at the top of memory. */ | ||
| 504 | pgdir = from_guest_phys(mem) - initrd_size - getpagesize(); | ||
| 505 | |||
| 506 | /* Now we use the next linear_pages pages as pte pages */ | ||
| 507 | linear = (void *)pgdir - linear_pages*getpagesize(); | ||
| 508 | |||
| 509 | /* Linear mapping is easy: put every page's address into the mapping in | ||
| 510 | * order. PAGE_PRESENT contains the flags Present, Writable and | ||
| 511 | * Executable. */ | ||
| 512 | for (i = 0; i < mapped_pages; i++) | ||
| 513 | linear[i] = ((i * getpagesize()) | PAGE_PRESENT); | ||
| 514 | |||
| 515 | /* The top level points to the linear page table pages above. */ | ||
| 516 | for (i = 0; i < mapped_pages; i += ptes_per_page) { | ||
| 517 | pgdir[i/ptes_per_page] | ||
| 518 | = ((to_guest_phys(linear) + i*sizeof(void *)) | ||
| 519 | | PAGE_PRESENT); | ||
| 520 | } | ||
| 521 | |||
| 522 | verbose("Linear mapping of %u pages in %u pte pages at %#lx\n", | ||
| 523 | mapped_pages, linear_pages, to_guest_phys(linear)); | ||
| 524 | |||
| 525 | /* We return the top level (guest-physical) address: the kernel needs | ||
| 526 | * to know where it is. */ | ||
| 527 | return to_guest_phys(pgdir); | ||
| 528 | } | ||
| 529 | /*:*/ | 484 | /*:*/ |
| 530 | 485 | ||
| 531 | /* Simple routine to roll all the commandline arguments together with spaces | 486 | /* Simple routine to roll all the commandline arguments together with spaces |
| @@ -548,13 +503,13 @@ static void concat(char *dst, char *args[]) | |||
| 548 | 503 | ||
| 549 | /*L:185 This is where we actually tell the kernel to initialize the Guest. We | 504 | /*L:185 This is where we actually tell the kernel to initialize the Guest. We |
| 550 | * saw the arguments it expects when we looked at initialize() in lguest_user.c: | 505 | * saw the arguments it expects when we looked at initialize() in lguest_user.c: |
| 551 | * the base of Guest "physical" memory, the top physical page to allow, the | 506 | * the base of Guest "physical" memory, the top physical page to allow and the |
| 552 | * top level pagetable and the entry point for the Guest. */ | 507 | * entry point for the Guest. */ |
| 553 | static int tell_kernel(unsigned long pgdir, unsigned long start) | 508 | static int tell_kernel(unsigned long start) |
| 554 | { | 509 | { |
| 555 | unsigned long args[] = { LHREQ_INITIALIZE, | 510 | unsigned long args[] = { LHREQ_INITIALIZE, |
| 556 | (unsigned long)guest_base, | 511 | (unsigned long)guest_base, |
| 557 | guest_limit / getpagesize(), pgdir, start }; | 512 | guest_limit / getpagesize(), start }; |
| 558 | int fd; | 513 | int fd; |
| 559 | 514 | ||
| 560 | verbose("Guest: %p - %p (%#lx)\n", | 515 | verbose("Guest: %p - %p (%#lx)\n", |
| @@ -1030,7 +985,7 @@ static void update_device_status(struct device *dev) | |||
| 1030 | /* Zero out the virtqueues. */ | 985 | /* Zero out the virtqueues. */ |
| 1031 | for (vq = dev->vq; vq; vq = vq->next) { | 986 | for (vq = dev->vq; vq; vq = vq->next) { |
| 1032 | memset(vq->vring.desc, 0, | 987 | memset(vq->vring.desc, 0, |
| 1033 | vring_size(vq->config.num, getpagesize())); | 988 | vring_size(vq->config.num, LGUEST_VRING_ALIGN)); |
| 1034 | lg_last_avail(vq) = 0; | 989 | lg_last_avail(vq) = 0; |
| 1035 | } | 990 | } |
| 1036 | } else if (dev->desc->status & VIRTIO_CONFIG_S_FAILED) { | 991 | } else if (dev->desc->status & VIRTIO_CONFIG_S_FAILED) { |
| @@ -1211,7 +1166,7 @@ static void add_virtqueue(struct device *dev, unsigned int num_descs, | |||
| 1211 | void *p; | 1166 | void *p; |
| 1212 | 1167 | ||
| 1213 | /* First we need some memory for this virtqueue. */ | 1168 | /* First we need some memory for this virtqueue. */ |
| 1214 | pages = (vring_size(num_descs, getpagesize()) + getpagesize() - 1) | 1169 | pages = (vring_size(num_descs, LGUEST_VRING_ALIGN) + getpagesize() - 1) |
| 1215 | / getpagesize(); | 1170 | / getpagesize(); |
| 1216 | p = get_pages(pages); | 1171 | p = get_pages(pages); |
| 1217 | 1172 | ||
| @@ -1228,7 +1183,7 @@ static void add_virtqueue(struct device *dev, unsigned int num_descs, | |||
| 1228 | vq->config.pfn = to_guest_phys(p) / getpagesize(); | 1183 | vq->config.pfn = to_guest_phys(p) / getpagesize(); |
| 1229 | 1184 | ||
| 1230 | /* Initialize the vring. */ | 1185 | /* Initialize the vring. */ |
| 1231 | vring_init(&vq->vring, num_descs, p, getpagesize()); | 1186 | vring_init(&vq->vring, num_descs, p, LGUEST_VRING_ALIGN); |
| 1232 | 1187 | ||
| 1233 | /* Append virtqueue to this device's descriptor. We use | 1188 | /* Append virtqueue to this device's descriptor. We use |
| 1234 | * device_config() to get the end of the device's current virtqueues; | 1189 | * device_config() to get the end of the device's current virtqueues; |
| @@ -1941,7 +1896,7 @@ int main(int argc, char *argv[]) | |||
| 1941 | { | 1896 | { |
| 1942 | /* Memory, top-level pagetable, code startpoint and size of the | 1897 | /* Memory, top-level pagetable, code startpoint and size of the |
| 1943 | * (optional) initrd. */ | 1898 | * (optional) initrd. */ |
| 1944 | unsigned long mem = 0, pgdir, start, initrd_size = 0; | 1899 | unsigned long mem = 0, start, initrd_size = 0; |
| 1945 | /* Two temporaries and the /dev/lguest file descriptor. */ | 1900 | /* Two temporaries and the /dev/lguest file descriptor. */ |
| 1946 | int i, c, lguest_fd; | 1901 | int i, c, lguest_fd; |
| 1947 | /* The boot information for the Guest. */ | 1902 | /* The boot information for the Guest. */ |
| @@ -2040,9 +1995,6 @@ int main(int argc, char *argv[]) | |||
| 2040 | boot->hdr.type_of_loader = 0xFF; | 1995 | boot->hdr.type_of_loader = 0xFF; |
| 2041 | } | 1996 | } |
| 2042 | 1997 | ||
| 2043 | /* Set up the initial linear pagetables, starting below the initrd. */ | ||
| 2044 | pgdir = setup_pagetables(mem, initrd_size); | ||
| 2045 | |||
| 2046 | /* The Linux boot header contains an "E820" memory map: ours is a | 1998 | /* The Linux boot header contains an "E820" memory map: ours is a |
| 2047 | * simple, single region. */ | 1999 | * simple, single region. */ |
| 2048 | boot->e820_entries = 1; | 2000 | boot->e820_entries = 1; |
| @@ -2064,7 +2016,7 @@ int main(int argc, char *argv[]) | |||
| 2064 | 2016 | ||
| 2065 | /* We tell the kernel to initialize the Guest: this returns the open | 2017 | /* We tell the kernel to initialize the Guest: this returns the open |
| 2066 | * /dev/lguest file descriptor. */ | 2018 | * /dev/lguest file descriptor. */ |
| 2067 | lguest_fd = tell_kernel(pgdir, start); | 2019 | lguest_fd = tell_kernel(start); |
| 2068 | 2020 | ||
| 2069 | /* We clone off a thread, which wakes the Launcher whenever one of the | 2021 | /* We clone off a thread, which wakes the Launcher whenever one of the |
| 2070 | * input file descriptors needs attention. We call this the Waker, and | 2022 | * input file descriptors needs attention. We call this the Waker, and |
diff --git a/arch/s390/include/asm/kvm_virtio.h b/arch/s390/include/asm/kvm_virtio.h index c13568b9351c..0503936f101f 100644 --- a/arch/s390/include/asm/kvm_virtio.h +++ b/arch/s390/include/asm/kvm_virtio.h | |||
| @@ -50,6 +50,10 @@ struct kvm_vqconfig { | |||
| 50 | #define KVM_S390_VIRTIO_RESET 1 | 50 | #define KVM_S390_VIRTIO_RESET 1 |
| 51 | #define KVM_S390_VIRTIO_SET_STATUS 2 | 51 | #define KVM_S390_VIRTIO_SET_STATUS 2 |
| 52 | 52 | ||
| 53 | /* The alignment to use between consumer and producer parts of vring. | ||
| 54 | * This is pagesize for historical reasons. */ | ||
| 55 | #define KVM_S390_VIRTIO_RING_ALIGN 4096 | ||
| 56 | |||
| 53 | #ifdef __KERNEL__ | 57 | #ifdef __KERNEL__ |
| 54 | /* early virtio console setup */ | 58 | /* early virtio console setup */ |
| 55 | #ifdef CONFIG_S390_GUEST | 59 | #ifdef CONFIG_S390_GUEST |
diff --git a/arch/x86/lguest/i386_head.S b/arch/x86/lguest/i386_head.S index 5c7cef34c9e7..10b9bd35a8ff 100644 --- a/arch/x86/lguest/i386_head.S +++ b/arch/x86/lguest/i386_head.S | |||
| @@ -30,21 +30,6 @@ ENTRY(lguest_entry) | |||
| 30 | movl $lguest_data - __PAGE_OFFSET, %edx | 30 | movl $lguest_data - __PAGE_OFFSET, %edx |
| 31 | int $LGUEST_TRAP_ENTRY | 31 | int $LGUEST_TRAP_ENTRY |
| 32 | 32 | ||
| 33 | /* The Host put the toplevel pagetable in lguest_data.pgdir. The movsl | ||
| 34 | * instruction uses %esi implicitly as the source for the copy we're | ||
| 35 | * about to do. */ | ||
| 36 | movl lguest_data - __PAGE_OFFSET + LGUEST_DATA_pgdir, %esi | ||
| 37 | |||
| 38 | /* Copy first 32 entries of page directory to __PAGE_OFFSET entries. | ||
| 39 | * This means the first 128M of kernel memory will be mapped at | ||
| 40 | * PAGE_OFFSET where the kernel expects to run. This will get it far | ||
| 41 | * enough through boot to switch to its own pagetables. */ | ||
| 42 | movl $32, %ecx | ||
| 43 | movl %esi, %edi | ||
| 44 | addl $((__PAGE_OFFSET >> 22) * 4), %edi | ||
| 45 | rep | ||
| 46 | movsl | ||
| 47 | |||
| 48 | /* Set up the initial stack so we can run C code. */ | 33 | /* Set up the initial stack so we can run C code. */ |
| 49 | movl $(init_thread_union+THREAD_SIZE),%esp | 34 | movl $(init_thread_union+THREAD_SIZE),%esp |
| 50 | 35 | ||
diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c index f151592ecf73..5d34764c8a87 100644 --- a/drivers/block/virtio_blk.c +++ b/drivers/block/virtio_blk.c | |||
| @@ -6,7 +6,6 @@ | |||
| 6 | #include <linux/virtio_blk.h> | 6 | #include <linux/virtio_blk.h> |
| 7 | #include <linux/scatterlist.h> | 7 | #include <linux/scatterlist.h> |
| 8 | 8 | ||
| 9 | #define VIRTIO_MAX_SG (3+MAX_PHYS_SEGMENTS) | ||
| 10 | #define PART_BITS 4 | 9 | #define PART_BITS 4 |
| 11 | 10 | ||
| 12 | static int major, index; | 11 | static int major, index; |
| @@ -26,8 +25,11 @@ struct virtio_blk | |||
| 26 | 25 | ||
| 27 | mempool_t *pool; | 26 | mempool_t *pool; |
| 28 | 27 | ||
| 28 | /* What host tells us, plus 2 for header & tailer. */ | ||
| 29 | unsigned int sg_elems; | ||
| 30 | |||
| 29 | /* Scatterlist: can be too big for stack. */ | 31 | /* Scatterlist: can be too big for stack. */ |
| 30 | struct scatterlist sg[VIRTIO_MAX_SG]; | 32 | struct scatterlist sg[/*sg_elems*/]; |
| 31 | }; | 33 | }; |
| 32 | 34 | ||
| 33 | struct virtblk_req | 35 | struct virtblk_req |
| @@ -97,8 +99,6 @@ static bool do_req(struct request_queue *q, struct virtio_blk *vblk, | |||
| 97 | if (blk_barrier_rq(vbr->req)) | 99 | if (blk_barrier_rq(vbr->req)) |
| 98 | vbr->out_hdr.type |= VIRTIO_BLK_T_BARRIER; | 100 | vbr->out_hdr.type |= VIRTIO_BLK_T_BARRIER; |
| 99 | 101 | ||
| 100 | /* This init could be done at vblk creation time */ | ||
| 101 | sg_init_table(vblk->sg, VIRTIO_MAX_SG); | ||
| 102 | sg_set_buf(&vblk->sg[0], &vbr->out_hdr, sizeof(vbr->out_hdr)); | 102 | sg_set_buf(&vblk->sg[0], &vbr->out_hdr, sizeof(vbr->out_hdr)); |
| 103 | num = blk_rq_map_sg(q, vbr->req, vblk->sg+1); | 103 | num = blk_rq_map_sg(q, vbr->req, vblk->sg+1); |
| 104 | sg_set_buf(&vblk->sg[num+1], &vbr->status, sizeof(vbr->status)); | 104 | sg_set_buf(&vblk->sg[num+1], &vbr->status, sizeof(vbr->status)); |
| @@ -130,7 +130,7 @@ static void do_virtblk_request(struct request_queue *q) | |||
| 130 | 130 | ||
| 131 | while ((req = elv_next_request(q)) != NULL) { | 131 | while ((req = elv_next_request(q)) != NULL) { |
| 132 | vblk = req->rq_disk->private_data; | 132 | vblk = req->rq_disk->private_data; |
| 133 | BUG_ON(req->nr_phys_segments > ARRAY_SIZE(vblk->sg)); | 133 | BUG_ON(req->nr_phys_segments + 2 > vblk->sg_elems); |
| 134 | 134 | ||
| 135 | /* If this request fails, stop queue and wait for something to | 135 | /* If this request fails, stop queue and wait for something to |
| 136 | finish to restart it. */ | 136 | finish to restart it. */ |
| @@ -196,12 +196,22 @@ static int virtblk_probe(struct virtio_device *vdev) | |||
| 196 | int err; | 196 | int err; |
| 197 | u64 cap; | 197 | u64 cap; |
| 198 | u32 v; | 198 | u32 v; |
| 199 | u32 blk_size; | 199 | u32 blk_size, sg_elems; |
| 200 | 200 | ||
| 201 | if (index_to_minor(index) >= 1 << MINORBITS) | 201 | if (index_to_minor(index) >= 1 << MINORBITS) |
| 202 | return -ENOSPC; | 202 | return -ENOSPC; |
| 203 | 203 | ||
| 204 | vdev->priv = vblk = kmalloc(sizeof(*vblk), GFP_KERNEL); | 204 | /* We need to know how many segments before we allocate. */ |
| 205 | err = virtio_config_val(vdev, VIRTIO_BLK_F_SEG_MAX, | ||
| 206 | offsetof(struct virtio_blk_config, seg_max), | ||
| 207 | &sg_elems); | ||
| 208 | if (err) | ||
| 209 | sg_elems = 1; | ||
| 210 | |||
| 211 | /* We need an extra sg elements at head and tail. */ | ||
| 212 | sg_elems += 2; | ||
| 213 | vdev->priv = vblk = kmalloc(sizeof(*vblk) + | ||
| 214 | sizeof(vblk->sg[0]) * sg_elems, GFP_KERNEL); | ||
| 205 | if (!vblk) { | 215 | if (!vblk) { |
| 206 | err = -ENOMEM; | 216 | err = -ENOMEM; |
| 207 | goto out; | 217 | goto out; |
| @@ -210,6 +220,8 @@ static int virtblk_probe(struct virtio_device *vdev) | |||
| 210 | INIT_LIST_HEAD(&vblk->reqs); | 220 | INIT_LIST_HEAD(&vblk->reqs); |
| 211 | spin_lock_init(&vblk->lock); | 221 | spin_lock_init(&vblk->lock); |
| 212 | vblk->vdev = vdev; | 222 | vblk->vdev = vdev; |
| 223 | vblk->sg_elems = sg_elems; | ||
| 224 | sg_init_table(vblk->sg, vblk->sg_elems); | ||
| 213 | 225 | ||
| 214 | /* We expect one virtqueue, for output. */ | 226 | /* We expect one virtqueue, for output. */ |
| 215 | vblk->vq = vdev->config->find_vq(vdev, 0, blk_done); | 227 | vblk->vq = vdev->config->find_vq(vdev, 0, blk_done); |
| @@ -279,6 +291,13 @@ static int virtblk_probe(struct virtio_device *vdev) | |||
| 279 | } | 291 | } |
| 280 | set_capacity(vblk->disk, cap); | 292 | set_capacity(vblk->disk, cap); |
| 281 | 293 | ||
| 294 | /* We can handle whatever the host told us to handle. */ | ||
| 295 | blk_queue_max_phys_segments(vblk->disk->queue, vblk->sg_elems-2); | ||
| 296 | blk_queue_max_hw_segments(vblk->disk->queue, vblk->sg_elems-2); | ||
| 297 | |||
| 298 | /* No real sector limit. */ | ||
| 299 | blk_queue_max_sectors(vblk->disk->queue, -1U); | ||
| 300 | |||
| 282 | /* Host can optionally specify maximum segment size and number of | 301 | /* Host can optionally specify maximum segment size and number of |
| 283 | * segments. */ | 302 | * segments. */ |
| 284 | err = virtio_config_val(vdev, VIRTIO_BLK_F_SIZE_MAX, | 303 | err = virtio_config_val(vdev, VIRTIO_BLK_F_SIZE_MAX, |
| @@ -286,12 +305,8 @@ static int virtblk_probe(struct virtio_device *vdev) | |||
| 286 | &v); | 305 | &v); |
| 287 | if (!err) | 306 | if (!err) |
| 288 | blk_queue_max_segment_size(vblk->disk->queue, v); | 307 | blk_queue_max_segment_size(vblk->disk->queue, v); |
| 289 | 308 | else | |
| 290 | err = virtio_config_val(vdev, VIRTIO_BLK_F_SEG_MAX, | 309 | blk_queue_max_segment_size(vblk->disk->queue, -1U); |
| 291 | offsetof(struct virtio_blk_config, seg_max), | ||
| 292 | &v); | ||
| 293 | if (!err) | ||
| 294 | blk_queue_max_hw_segments(vblk->disk->queue, v); | ||
| 295 | 310 | ||
| 296 | /* Host can optionally specify the block size of the device */ | 311 | /* Host can optionally specify the block size of the device */ |
| 297 | err = virtio_config_val(vdev, VIRTIO_BLK_F_BLK_SIZE, | 312 | err = virtio_config_val(vdev, VIRTIO_BLK_F_BLK_SIZE, |
diff --git a/drivers/char/hvc_console.c b/drivers/char/hvc_console.c index fb57f67bb427..0587b66d6fc7 100644 --- a/drivers/char/hvc_console.c +++ b/drivers/char/hvc_console.c | |||
| @@ -695,6 +695,7 @@ void hvc_resize(struct hvc_struct *hp, struct winsize ws) | |||
| 695 | hp->ws = ws; | 695 | hp->ws = ws; |
| 696 | schedule_work(&hp->tty_resize); | 696 | schedule_work(&hp->tty_resize); |
| 697 | } | 697 | } |
| 698 | EXPORT_SYMBOL_GPL(hvc_resize); | ||
| 698 | 699 | ||
| 699 | /* | 700 | /* |
| 700 | * This kthread is either polling or interrupt driven. This is determined by | 701 | * This kthread is either polling or interrupt driven. This is determined by |
diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c index 3fb0d2c88ba5..ff6f5a4b58fb 100644 --- a/drivers/char/virtio_console.c +++ b/drivers/char/virtio_console.c | |||
| @@ -138,12 +138,33 @@ int __init virtio_cons_early_init(int (*put_chars)(u32, const char *, int)) | |||
| 138 | } | 138 | } |
| 139 | 139 | ||
| 140 | /* | 140 | /* |
| 141 | * virtio console configuration. This supports: | ||
| 142 | * - console resize | ||
| 143 | */ | ||
| 144 | static void virtcons_apply_config(struct virtio_device *dev) | ||
| 145 | { | ||
| 146 | struct winsize ws; | ||
| 147 | |||
| 148 | if (virtio_has_feature(dev, VIRTIO_CONSOLE_F_SIZE)) { | ||
| 149 | dev->config->get(dev, | ||
| 150 | offsetof(struct virtio_console_config, cols), | ||
| 151 | &ws.ws_col, sizeof(u16)); | ||
| 152 | dev->config->get(dev, | ||
| 153 | offsetof(struct virtio_console_config, rows), | ||
| 154 | &ws.ws_row, sizeof(u16)); | ||
| 155 | hvc_resize(hvc, ws); | ||
| 156 | } | ||
| 157 | } | ||
| 158 | |||
| 159 | /* | ||
| 141 | * we support only one console, the hvc struct is a global var | 160 | * we support only one console, the hvc struct is a global var |
| 142 | * There is no need to do anything | 161 | * We set the configuration at this point, since we now have a tty |
| 143 | */ | 162 | */ |
| 144 | static int notifier_add_vio(struct hvc_struct *hp, int data) | 163 | static int notifier_add_vio(struct hvc_struct *hp, int data) |
| 145 | { | 164 | { |
| 146 | hp->irq_requested = 1; | 165 | hp->irq_requested = 1; |
| 166 | virtcons_apply_config(vdev); | ||
| 167 | |||
| 147 | return 0; | 168 | return 0; |
| 148 | } | 169 | } |
| 149 | 170 | ||
| @@ -234,11 +255,18 @@ static struct virtio_device_id id_table[] = { | |||
| 234 | { 0 }, | 255 | { 0 }, |
| 235 | }; | 256 | }; |
| 236 | 257 | ||
| 258 | static unsigned int features[] = { | ||
| 259 | VIRTIO_CONSOLE_F_SIZE, | ||
| 260 | }; | ||
| 261 | |||
| 237 | static struct virtio_driver virtio_console = { | 262 | static struct virtio_driver virtio_console = { |
| 263 | .feature_table = features, | ||
| 264 | .feature_table_size = ARRAY_SIZE(features), | ||
| 238 | .driver.name = KBUILD_MODNAME, | 265 | .driver.name = KBUILD_MODNAME, |
| 239 | .driver.owner = THIS_MODULE, | 266 | .driver.owner = THIS_MODULE, |
| 240 | .id_table = id_table, | 267 | .id_table = id_table, |
| 241 | .probe = virtcons_probe, | 268 | .probe = virtcons_probe, |
| 269 | .config_changed = virtcons_apply_config, | ||
| 242 | }; | 270 | }; |
| 243 | 271 | ||
| 244 | static int __init init(void) | 272 | static int __init init(void) |
diff --git a/drivers/lguest/lg.h b/drivers/lguest/lg.h index 5faefeaf6790..f2c641e0bdde 100644 --- a/drivers/lguest/lg.h +++ b/drivers/lguest/lg.h | |||
| @@ -164,7 +164,7 @@ void copy_gdt(const struct lg_cpu *cpu, struct desc_struct *gdt); | |||
| 164 | void copy_gdt_tls(const struct lg_cpu *cpu, struct desc_struct *gdt); | 164 | void copy_gdt_tls(const struct lg_cpu *cpu, struct desc_struct *gdt); |
| 165 | 165 | ||
| 166 | /* page_tables.c: */ | 166 | /* page_tables.c: */ |
| 167 | int init_guest_pagetable(struct lguest *lg, unsigned long pgtable); | 167 | int init_guest_pagetable(struct lguest *lg); |
| 168 | void free_guest_pagetable(struct lguest *lg); | 168 | void free_guest_pagetable(struct lguest *lg); |
| 169 | void guest_new_pagetable(struct lg_cpu *cpu, unsigned long pgtable); | 169 | void guest_new_pagetable(struct lg_cpu *cpu, unsigned long pgtable); |
| 170 | void guest_set_pmd(struct lguest *lg, unsigned long gpgdir, u32 i); | 170 | void guest_set_pmd(struct lguest *lg, unsigned long gpgdir, u32 i); |
diff --git a/drivers/lguest/lguest_device.c b/drivers/lguest/lguest_device.c index a661bbdae3d6..915da6b8c924 100644 --- a/drivers/lguest/lguest_device.c +++ b/drivers/lguest/lguest_device.c | |||
| @@ -250,7 +250,7 @@ static struct virtqueue *lg_find_vq(struct virtio_device *vdev, | |||
| 250 | /* Figure out how many pages the ring will take, and map that memory */ | 250 | /* Figure out how many pages the ring will take, and map that memory */ |
| 251 | lvq->pages = lguest_map((unsigned long)lvq->config.pfn << PAGE_SHIFT, | 251 | lvq->pages = lguest_map((unsigned long)lvq->config.pfn << PAGE_SHIFT, |
| 252 | DIV_ROUND_UP(vring_size(lvq->config.num, | 252 | DIV_ROUND_UP(vring_size(lvq->config.num, |
| 253 | PAGE_SIZE), | 253 | LGUEST_VRING_ALIGN), |
| 254 | PAGE_SIZE)); | 254 | PAGE_SIZE)); |
| 255 | if (!lvq->pages) { | 255 | if (!lvq->pages) { |
| 256 | err = -ENOMEM; | 256 | err = -ENOMEM; |
| @@ -259,8 +259,8 @@ static struct virtqueue *lg_find_vq(struct virtio_device *vdev, | |||
| 259 | 259 | ||
| 260 | /* OK, tell virtio_ring.c to set up a virtqueue now we know its size | 260 | /* OK, tell virtio_ring.c to set up a virtqueue now we know its size |
| 261 | * and we've got a pointer to its pages. */ | 261 | * and we've got a pointer to its pages. */ |
| 262 | vq = vring_new_virtqueue(lvq->config.num, vdev, lvq->pages, | 262 | vq = vring_new_virtqueue(lvq->config.num, LGUEST_VRING_ALIGN, |
| 263 | lg_notify, callback); | 263 | vdev, lvq->pages, lg_notify, callback); |
| 264 | if (!vq) { | 264 | if (!vq) { |
| 265 | err = -ENOMEM; | 265 | err = -ENOMEM; |
| 266 | goto unmap; | 266 | goto unmap; |
| @@ -272,7 +272,7 @@ static struct virtqueue *lg_find_vq(struct virtio_device *vdev, | |||
| 272 | * the interrupt as a source of randomness: it'd be nice to have that | 272 | * the interrupt as a source of randomness: it'd be nice to have that |
| 273 | * back.. */ | 273 | * back.. */ |
| 274 | err = request_irq(lvq->config.irq, vring_interrupt, IRQF_SHARED, | 274 | err = request_irq(lvq->config.irq, vring_interrupt, IRQF_SHARED, |
| 275 | vdev->dev.bus_id, vq); | 275 | dev_name(&vdev->dev), vq); |
| 276 | if (err) | 276 | if (err) |
| 277 | goto destroy_vring; | 277 | goto destroy_vring; |
| 278 | 278 | ||
diff --git a/drivers/lguest/lguest_user.c b/drivers/lguest/lguest_user.c index e73a000473cc..34bc017b8b3c 100644 --- a/drivers/lguest/lguest_user.c +++ b/drivers/lguest/lguest_user.c | |||
| @@ -146,7 +146,7 @@ static int lg_cpu_start(struct lg_cpu *cpu, unsigned id, unsigned long start_ip) | |||
| 146 | return 0; | 146 | return 0; |
| 147 | } | 147 | } |
| 148 | 148 | ||
| 149 | /*L:020 The initialization write supplies 4 pointer sized (32 or 64 bit) | 149 | /*L:020 The initialization write supplies 3 pointer sized (32 or 64 bit) |
| 150 | * values (in addition to the LHREQ_INITIALIZE value). These are: | 150 | * values (in addition to the LHREQ_INITIALIZE value). These are: |
| 151 | * | 151 | * |
| 152 | * base: The start of the Guest-physical memory inside the Launcher memory. | 152 | * base: The start of the Guest-physical memory inside the Launcher memory. |
| @@ -155,9 +155,6 @@ static int lg_cpu_start(struct lg_cpu *cpu, unsigned id, unsigned long start_ip) | |||
| 155 | * allowed to access. The Guest memory lives inside the Launcher, so it sets | 155 | * allowed to access. The Guest memory lives inside the Launcher, so it sets |
| 156 | * this to ensure the Guest can only reach its own memory. | 156 | * this to ensure the Guest can only reach its own memory. |
| 157 | * | 157 | * |
| 158 | * pgdir: The (Guest-physical) address of the top of the initial Guest | ||
| 159 | * pagetables (which are set up by the Launcher). | ||
| 160 | * | ||
| 161 | * start: The first instruction to execute ("eip" in x86-speak). | 158 | * start: The first instruction to execute ("eip" in x86-speak). |
| 162 | */ | 159 | */ |
| 163 | static int initialize(struct file *file, const unsigned long __user *input) | 160 | static int initialize(struct file *file, const unsigned long __user *input) |
| @@ -166,7 +163,7 @@ static int initialize(struct file *file, const unsigned long __user *input) | |||
| 166 | * Guest. */ | 163 | * Guest. */ |
| 167 | struct lguest *lg; | 164 | struct lguest *lg; |
| 168 | int err; | 165 | int err; |
| 169 | unsigned long args[4]; | 166 | unsigned long args[3]; |
| 170 | 167 | ||
| 171 | /* We grab the Big Lguest lock, which protects against multiple | 168 | /* We grab the Big Lguest lock, which protects against multiple |
| 172 | * simultaneous initializations. */ | 169 | * simultaneous initializations. */ |
| @@ -192,14 +189,14 @@ static int initialize(struct file *file, const unsigned long __user *input) | |||
| 192 | lg->mem_base = (void __user *)args[0]; | 189 | lg->mem_base = (void __user *)args[0]; |
| 193 | lg->pfn_limit = args[1]; | 190 | lg->pfn_limit = args[1]; |
| 194 | 191 | ||
| 195 | /* This is the first cpu (cpu 0) and it will start booting at args[3] */ | 192 | /* This is the first cpu (cpu 0) and it will start booting at args[2] */ |
| 196 | err = lg_cpu_start(&lg->cpus[0], 0, args[3]); | 193 | err = lg_cpu_start(&lg->cpus[0], 0, args[2]); |
| 197 | if (err) | 194 | if (err) |
| 198 | goto release_guest; | 195 | goto release_guest; |
| 199 | 196 | ||
| 200 | /* Initialize the Guest's shadow page tables, using the toplevel | 197 | /* Initialize the Guest's shadow page tables, using the toplevel |
| 201 | * address the Launcher gave us. This allocates memory, so can fail. */ | 198 | * address the Launcher gave us. This allocates memory, so can fail. */ |
| 202 | err = init_guest_pagetable(lg, args[2]); | 199 | err = init_guest_pagetable(lg); |
| 203 | if (err) | 200 | if (err) |
| 204 | goto free_regs; | 201 | goto free_regs; |
| 205 | 202 | ||
diff --git a/drivers/lguest/page_tables.c b/drivers/lguest/page_tables.c index 81d0c6053447..576a8318221c 100644 --- a/drivers/lguest/page_tables.c +++ b/drivers/lguest/page_tables.c | |||
| @@ -14,6 +14,7 @@ | |||
| 14 | #include <linux/percpu.h> | 14 | #include <linux/percpu.h> |
| 15 | #include <asm/tlbflush.h> | 15 | #include <asm/tlbflush.h> |
| 16 | #include <asm/uaccess.h> | 16 | #include <asm/uaccess.h> |
| 17 | #include <asm/bootparam.h> | ||
| 17 | #include "lg.h" | 18 | #include "lg.h" |
| 18 | 19 | ||
| 19 | /*M:008 We hold reference to pages, which prevents them from being swapped. | 20 | /*M:008 We hold reference to pages, which prevents them from being swapped. |
| @@ -581,15 +582,82 @@ void guest_set_pmd(struct lguest *lg, unsigned long gpgdir, u32 idx) | |||
| 581 | release_pgd(lg, lg->pgdirs[pgdir].pgdir + idx); | 582 | release_pgd(lg, lg->pgdirs[pgdir].pgdir + idx); |
| 582 | } | 583 | } |
| 583 | 584 | ||
| 585 | /* Once we know how much memory we have we can construct simple identity | ||
| 586 | * (which set virtual == physical) and linear mappings | ||
| 587 | * which will get the Guest far enough into the boot to create its own. | ||
| 588 | * | ||
| 589 | * We lay them out of the way, just below the initrd (which is why we need to | ||
| 590 | * know its size here). */ | ||
| 591 | static unsigned long setup_pagetables(struct lguest *lg, | ||
| 592 | unsigned long mem, | ||
| 593 | unsigned long initrd_size) | ||
| 594 | { | ||
| 595 | pgd_t __user *pgdir; | ||
| 596 | pte_t __user *linear; | ||
| 597 | unsigned int mapped_pages, i, linear_pages, phys_linear; | ||
| 598 | unsigned long mem_base = (unsigned long)lg->mem_base; | ||
| 599 | |||
| 600 | /* We have mapped_pages frames to map, so we need | ||
| 601 | * linear_pages page tables to map them. */ | ||
| 602 | mapped_pages = mem / PAGE_SIZE; | ||
| 603 | linear_pages = (mapped_pages + PTRS_PER_PTE - 1) / PTRS_PER_PTE; | ||
| 604 | |||
| 605 | /* We put the toplevel page directory page at the top of memory. */ | ||
| 606 | pgdir = (pgd_t *)(mem + mem_base - initrd_size - PAGE_SIZE); | ||
| 607 | |||
| 608 | /* Now we use the next linear_pages pages as pte pages */ | ||
| 609 | linear = (void *)pgdir - linear_pages * PAGE_SIZE; | ||
| 610 | |||
| 611 | /* Linear mapping is easy: put every page's address into the | ||
| 612 | * mapping in order. */ | ||
| 613 | for (i = 0; i < mapped_pages; i++) { | ||
| 614 | pte_t pte; | ||
| 615 | pte = pfn_pte(i, __pgprot(_PAGE_PRESENT|_PAGE_RW|_PAGE_USER)); | ||
| 616 | if (copy_to_user(&linear[i], &pte, sizeof(pte)) != 0) | ||
| 617 | return -EFAULT; | ||
| 618 | } | ||
| 619 | |||
| 620 | /* The top level points to the linear page table pages above. | ||
| 621 | * We setup the identity and linear mappings here. */ | ||
| 622 | phys_linear = (unsigned long)linear - mem_base; | ||
| 623 | for (i = 0; i < mapped_pages; i += PTRS_PER_PTE) { | ||
| 624 | pgd_t pgd; | ||
| 625 | pgd = __pgd((phys_linear + i * sizeof(pte_t)) | | ||
| 626 | (_PAGE_PRESENT | _PAGE_RW | _PAGE_USER)); | ||
| 627 | |||
| 628 | if (copy_to_user(&pgdir[i / PTRS_PER_PTE], &pgd, sizeof(pgd)) | ||
| 629 | || copy_to_user(&pgdir[pgd_index(PAGE_OFFSET) | ||
| 630 | + i / PTRS_PER_PTE], | ||
| 631 | &pgd, sizeof(pgd))) | ||
| 632 | return -EFAULT; | ||
| 633 | } | ||
| 634 | |||
| 635 | /* We return the top level (guest-physical) address: remember where | ||
| 636 | * this is. */ | ||
| 637 | return (unsigned long)pgdir - mem_base; | ||
| 638 | } | ||
| 639 | |||
| 584 | /*H:500 (vii) Setting up the page tables initially. | 640 | /*H:500 (vii) Setting up the page tables initially. |
| 585 | * | 641 | * |
| 586 | * When a Guest is first created, the Launcher tells us where the toplevel of | 642 | * When a Guest is first created, the Launcher tells us where the toplevel of |
| 587 | * its first page table is. We set some things up here: */ | 643 | * its first page table is. We set some things up here: */ |
| 588 | int init_guest_pagetable(struct lguest *lg, unsigned long pgtable) | 644 | int init_guest_pagetable(struct lguest *lg) |
| 589 | { | 645 | { |
| 646 | u64 mem; | ||
| 647 | u32 initrd_size; | ||
| 648 | struct boot_params __user *boot = (struct boot_params *)lg->mem_base; | ||
| 649 | |||
| 650 | /* Get the Guest memory size and the ramdisk size from the boot header | ||
| 651 | * located at lg->mem_base (Guest address 0). */ | ||
| 652 | if (copy_from_user(&mem, &boot->e820_map[0].size, sizeof(mem)) | ||
| 653 | || get_user(initrd_size, &boot->hdr.ramdisk_size)) | ||
| 654 | return -EFAULT; | ||
| 655 | |||
| 590 | /* We start on the first shadow page table, and give it a blank PGD | 656 | /* We start on the first shadow page table, and give it a blank PGD |
| 591 | * page. */ | 657 | * page. */ |
| 592 | lg->pgdirs[0].gpgdir = pgtable; | 658 | lg->pgdirs[0].gpgdir = setup_pagetables(lg, mem, initrd_size); |
| 659 | if (IS_ERR_VALUE(lg->pgdirs[0].gpgdir)) | ||
| 660 | return lg->pgdirs[0].gpgdir; | ||
| 593 | lg->pgdirs[0].pgdir = (pgd_t *)get_zeroed_page(GFP_KERNEL); | 661 | lg->pgdirs[0].pgdir = (pgd_t *)get_zeroed_page(GFP_KERNEL); |
| 594 | if (!lg->pgdirs[0].pgdir) | 662 | if (!lg->pgdirs[0].pgdir) |
| 595 | return -ENOMEM; | 663 | return -ENOMEM; |
diff --git a/drivers/s390/kvm/kvm_virtio.c b/drivers/s390/kvm/kvm_virtio.c index 3d442444c618..28c90b89f2b4 100644 --- a/drivers/s390/kvm/kvm_virtio.c +++ b/drivers/s390/kvm/kvm_virtio.c | |||
| @@ -188,11 +188,13 @@ static struct virtqueue *kvm_find_vq(struct virtio_device *vdev, | |||
| 188 | config = kvm_vq_config(kdev->desc)+index; | 188 | config = kvm_vq_config(kdev->desc)+index; |
| 189 | 189 | ||
| 190 | err = vmem_add_mapping(config->address, | 190 | err = vmem_add_mapping(config->address, |
| 191 | vring_size(config->num, PAGE_SIZE)); | 191 | vring_size(config->num, |
| 192 | KVM_S390_VIRTIO_RING_ALIGN)); | ||
| 192 | if (err) | 193 | if (err) |
| 193 | goto out; | 194 | goto out; |
| 194 | 195 | ||
| 195 | vq = vring_new_virtqueue(config->num, vdev, (void *) config->address, | 196 | vq = vring_new_virtqueue(config->num, KVM_S390_VIRTIO_RING_ALIGN, |
| 197 | vdev, (void *) config->address, | ||
| 196 | kvm_notify, callback); | 198 | kvm_notify, callback); |
| 197 | if (!vq) { | 199 | if (!vq) { |
| 198 | err = -ENOMEM; | 200 | err = -ENOMEM; |
| @@ -209,7 +211,8 @@ static struct virtqueue *kvm_find_vq(struct virtio_device *vdev, | |||
| 209 | return vq; | 211 | return vq; |
| 210 | unmap: | 212 | unmap: |
| 211 | vmem_remove_mapping(config->address, | 213 | vmem_remove_mapping(config->address, |
| 212 | vring_size(config->num, PAGE_SIZE)); | 214 | vring_size(config->num, |
| 215 | KVM_S390_VIRTIO_RING_ALIGN)); | ||
| 213 | out: | 216 | out: |
| 214 | return ERR_PTR(err); | 217 | return ERR_PTR(err); |
| 215 | } | 218 | } |
| @@ -220,7 +223,8 @@ static void kvm_del_vq(struct virtqueue *vq) | |||
| 220 | 223 | ||
| 221 | vring_del_virtqueue(vq); | 224 | vring_del_virtqueue(vq); |
| 222 | vmem_remove_mapping(config->address, | 225 | vmem_remove_mapping(config->address, |
| 223 | vring_size(config->num, PAGE_SIZE)); | 226 | vring_size(config->num, |
| 227 | KVM_S390_VIRTIO_RING_ALIGN)); | ||
| 224 | } | 228 | } |
| 225 | 229 | ||
| 226 | /* | 230 | /* |
| @@ -295,13 +299,29 @@ static void scan_devices(void) | |||
| 295 | */ | 299 | */ |
| 296 | static void kvm_extint_handler(u16 code) | 300 | static void kvm_extint_handler(u16 code) |
| 297 | { | 301 | { |
| 298 | void *data = (void *) *(long *) __LC_PFAULT_INTPARM; | 302 | struct virtqueue *vq; |
| 299 | u16 subcode = S390_lowcore.cpu_addr; | 303 | u16 subcode; |
| 304 | int config_changed; | ||
| 300 | 305 | ||
| 306 | subcode = S390_lowcore.cpu_addr; | ||
| 301 | if ((subcode & 0xff00) != VIRTIO_SUBCODE_64) | 307 | if ((subcode & 0xff00) != VIRTIO_SUBCODE_64) |
| 302 | return; | 308 | return; |
| 303 | 309 | ||
| 304 | vring_interrupt(0, data); | 310 | /* The LSB might be overloaded, we have to mask it */ |
| 311 | vq = (struct virtqueue *) ((*(long *) __LC_PFAULT_INTPARM) & ~1UL); | ||
| 312 | |||
| 313 | /* We use the LSB of extparam, to decide, if this interrupt is a config | ||
| 314 | * change or a "standard" interrupt */ | ||
| 315 | config_changed = (*(int *) __LC_EXT_PARAMS & 1); | ||
| 316 | |||
| 317 | if (config_changed) { | ||
| 318 | struct virtio_driver *drv; | ||
| 319 | drv = container_of(vq->vdev->dev.driver, | ||
| 320 | struct virtio_driver, driver); | ||
| 321 | if (drv->config_changed) | ||
| 322 | drv->config_changed(vq->vdev); | ||
| 323 | } else | ||
| 324 | vring_interrupt(0, vq); | ||
| 305 | } | 325 | } |
| 306 | 326 | ||
| 307 | /* | 327 | /* |
diff --git a/drivers/virtio/virtio.c b/drivers/virtio/virtio.c index 5b78fd0aff0a..018c070a357f 100644 --- a/drivers/virtio/virtio.c +++ b/drivers/virtio/virtio.c | |||
| @@ -176,7 +176,7 @@ int register_virtio_device(struct virtio_device *dev) | |||
| 176 | 176 | ||
| 177 | /* Assign a unique device index and hence name. */ | 177 | /* Assign a unique device index and hence name. */ |
| 178 | dev->index = dev_index++; | 178 | dev->index = dev_index++; |
| 179 | sprintf(dev->dev.bus_id, "virtio%u", dev->index); | 179 | dev_set_name(&dev->dev, "virtio%u", dev->index); |
| 180 | 180 | ||
| 181 | /* We always start by resetting the device, in case a previous | 181 | /* We always start by resetting the device, in case a previous |
| 182 | * driver messed it up. This also tests that code path a little. */ | 182 | * driver messed it up. This also tests that code path a little. */ |
diff --git a/drivers/virtio/virtio_balloon.c b/drivers/virtio/virtio_balloon.c index 62eab43152d2..59268266b79a 100644 --- a/drivers/virtio/virtio_balloon.c +++ b/drivers/virtio/virtio_balloon.c | |||
| @@ -56,6 +56,15 @@ static struct virtio_device_id id_table[] = { | |||
| 56 | { 0 }, | 56 | { 0 }, |
| 57 | }; | 57 | }; |
| 58 | 58 | ||
| 59 | static u32 page_to_balloon_pfn(struct page *page) | ||
| 60 | { | ||
| 61 | unsigned long pfn = page_to_pfn(page); | ||
| 62 | |||
| 63 | BUILD_BUG_ON(PAGE_SHIFT < VIRTIO_BALLOON_PFN_SHIFT); | ||
| 64 | /* Convert pfn from Linux page size to balloon page size. */ | ||
| 65 | return pfn >> (PAGE_SHIFT - VIRTIO_BALLOON_PFN_SHIFT); | ||
| 66 | } | ||
| 67 | |||
| 59 | static void balloon_ack(struct virtqueue *vq) | 68 | static void balloon_ack(struct virtqueue *vq) |
| 60 | { | 69 | { |
| 61 | struct virtio_balloon *vb; | 70 | struct virtio_balloon *vb; |
| @@ -99,7 +108,7 @@ static void fill_balloon(struct virtio_balloon *vb, size_t num) | |||
| 99 | msleep(200); | 108 | msleep(200); |
| 100 | break; | 109 | break; |
| 101 | } | 110 | } |
| 102 | vb->pfns[vb->num_pfns] = page_to_pfn(page); | 111 | vb->pfns[vb->num_pfns] = page_to_balloon_pfn(page); |
| 103 | totalram_pages--; | 112 | totalram_pages--; |
| 104 | vb->num_pages++; | 113 | vb->num_pages++; |
| 105 | list_add(&page->lru, &vb->pages); | 114 | list_add(&page->lru, &vb->pages); |
| @@ -132,7 +141,7 @@ static void leak_balloon(struct virtio_balloon *vb, size_t num) | |||
| 132 | for (vb->num_pfns = 0; vb->num_pfns < num; vb->num_pfns++) { | 141 | for (vb->num_pfns = 0; vb->num_pfns < num; vb->num_pfns++) { |
| 133 | page = list_first_entry(&vb->pages, struct page, lru); | 142 | page = list_first_entry(&vb->pages, struct page, lru); |
| 134 | list_del(&page->lru); | 143 | list_del(&page->lru); |
| 135 | vb->pfns[vb->num_pfns] = page_to_pfn(page); | 144 | vb->pfns[vb->num_pfns] = page_to_balloon_pfn(page); |
| 136 | vb->num_pages--; | 145 | vb->num_pages--; |
| 137 | } | 146 | } |
| 138 | 147 | ||
diff --git a/drivers/virtio/virtio_pci.c b/drivers/virtio/virtio_pci.c index c7dc37c7cce9..265fdf2d1276 100644 --- a/drivers/virtio/virtio_pci.c +++ b/drivers/virtio/virtio_pci.c | |||
| @@ -75,7 +75,7 @@ MODULE_DEVICE_TABLE(pci, virtio_pci_id_table); | |||
| 75 | * would make more sense for virtio to not insist on having it's own device. */ | 75 | * would make more sense for virtio to not insist on having it's own device. */ |
| 76 | static struct device virtio_pci_root = { | 76 | static struct device virtio_pci_root = { |
| 77 | .parent = NULL, | 77 | .parent = NULL, |
| 78 | .bus_id = "virtio-pci", | 78 | .init_name = "virtio-pci", |
| 79 | }; | 79 | }; |
| 80 | 80 | ||
| 81 | /* Convert a generic virtio device to our structure */ | 81 | /* Convert a generic virtio device to our structure */ |
| @@ -216,7 +216,7 @@ static struct virtqueue *vp_find_vq(struct virtio_device *vdev, unsigned index, | |||
| 216 | struct virtio_pci_device *vp_dev = to_vp_device(vdev); | 216 | struct virtio_pci_device *vp_dev = to_vp_device(vdev); |
| 217 | struct virtio_pci_vq_info *info; | 217 | struct virtio_pci_vq_info *info; |
| 218 | struct virtqueue *vq; | 218 | struct virtqueue *vq; |
| 219 | unsigned long flags; | 219 | unsigned long flags, size; |
| 220 | u16 num; | 220 | u16 num; |
| 221 | int err; | 221 | int err; |
| 222 | 222 | ||
| @@ -237,19 +237,20 @@ static struct virtqueue *vp_find_vq(struct virtio_device *vdev, unsigned index, | |||
| 237 | info->queue_index = index; | 237 | info->queue_index = index; |
| 238 | info->num = num; | 238 | info->num = num; |
| 239 | 239 | ||
| 240 | info->queue = kzalloc(PAGE_ALIGN(vring_size(num,PAGE_SIZE)), GFP_KERNEL); | 240 | size = PAGE_ALIGN(vring_size(num, VIRTIO_PCI_VRING_ALIGN)); |
| 241 | info->queue = alloc_pages_exact(size, GFP_KERNEL|__GFP_ZERO); | ||
| 241 | if (info->queue == NULL) { | 242 | if (info->queue == NULL) { |
| 242 | err = -ENOMEM; | 243 | err = -ENOMEM; |
| 243 | goto out_info; | 244 | goto out_info; |
| 244 | } | 245 | } |
| 245 | 246 | ||
| 246 | /* activate the queue */ | 247 | /* activate the queue */ |
| 247 | iowrite32(virt_to_phys(info->queue) >> PAGE_SHIFT, | 248 | iowrite32(virt_to_phys(info->queue) >> VIRTIO_PCI_QUEUE_ADDR_SHIFT, |
| 248 | vp_dev->ioaddr + VIRTIO_PCI_QUEUE_PFN); | 249 | vp_dev->ioaddr + VIRTIO_PCI_QUEUE_PFN); |
| 249 | 250 | ||
| 250 | /* create the vring */ | 251 | /* create the vring */ |
| 251 | vq = vring_new_virtqueue(info->num, vdev, info->queue, | 252 | vq = vring_new_virtqueue(info->num, VIRTIO_PCI_VRING_ALIGN, |
| 252 | vp_notify, callback); | 253 | vdev, info->queue, vp_notify, callback); |
| 253 | if (!vq) { | 254 | if (!vq) { |
| 254 | err = -ENOMEM; | 255 | err = -ENOMEM; |
| 255 | goto out_activate_queue; | 256 | goto out_activate_queue; |
| @@ -266,7 +267,7 @@ static struct virtqueue *vp_find_vq(struct virtio_device *vdev, unsigned index, | |||
| 266 | 267 | ||
| 267 | out_activate_queue: | 268 | out_activate_queue: |
| 268 | iowrite32(0, vp_dev->ioaddr + VIRTIO_PCI_QUEUE_PFN); | 269 | iowrite32(0, vp_dev->ioaddr + VIRTIO_PCI_QUEUE_PFN); |
| 269 | kfree(info->queue); | 270 | free_pages_exact(info->queue, size); |
| 270 | out_info: | 271 | out_info: |
| 271 | kfree(info); | 272 | kfree(info); |
| 272 | return ERR_PTR(err); | 273 | return ERR_PTR(err); |
| @@ -277,7 +278,7 @@ static void vp_del_vq(struct virtqueue *vq) | |||
| 277 | { | 278 | { |
| 278 | struct virtio_pci_device *vp_dev = to_vp_device(vq->vdev); | 279 | struct virtio_pci_device *vp_dev = to_vp_device(vq->vdev); |
| 279 | struct virtio_pci_vq_info *info = vq->priv; | 280 | struct virtio_pci_vq_info *info = vq->priv; |
| 280 | unsigned long flags; | 281 | unsigned long flags, size; |
| 281 | 282 | ||
| 282 | spin_lock_irqsave(&vp_dev->lock, flags); | 283 | spin_lock_irqsave(&vp_dev->lock, flags); |
| 283 | list_del(&info->node); | 284 | list_del(&info->node); |
| @@ -289,7 +290,8 @@ static void vp_del_vq(struct virtqueue *vq) | |||
| 289 | iowrite16(info->queue_index, vp_dev->ioaddr + VIRTIO_PCI_QUEUE_SEL); | 290 | iowrite16(info->queue_index, vp_dev->ioaddr + VIRTIO_PCI_QUEUE_SEL); |
| 290 | iowrite32(0, vp_dev->ioaddr + VIRTIO_PCI_QUEUE_PFN); | 291 | iowrite32(0, vp_dev->ioaddr + VIRTIO_PCI_QUEUE_PFN); |
| 291 | 292 | ||
| 292 | kfree(info->queue); | 293 | size = PAGE_ALIGN(vring_size(info->num, VIRTIO_PCI_VRING_ALIGN)); |
| 294 | free_pages_exact(info->queue, size); | ||
| 293 | kfree(info); | 295 | kfree(info); |
| 294 | } | 296 | } |
| 295 | 297 | ||
| @@ -305,6 +307,20 @@ static struct virtio_config_ops virtio_pci_config_ops = { | |||
| 305 | .finalize_features = vp_finalize_features, | 307 | .finalize_features = vp_finalize_features, |
| 306 | }; | 308 | }; |
| 307 | 309 | ||
| 310 | static void virtio_pci_release_dev(struct device *_d) | ||
| 311 | { | ||
| 312 | struct virtio_device *dev = container_of(_d, struct virtio_device, dev); | ||
| 313 | struct virtio_pci_device *vp_dev = to_vp_device(dev); | ||
| 314 | struct pci_dev *pci_dev = vp_dev->pci_dev; | ||
| 315 | |||
| 316 | free_irq(pci_dev->irq, vp_dev); | ||
| 317 | pci_set_drvdata(pci_dev, NULL); | ||
| 318 | pci_iounmap(pci_dev, vp_dev->ioaddr); | ||
| 319 | pci_release_regions(pci_dev); | ||
| 320 | pci_disable_device(pci_dev); | ||
| 321 | kfree(vp_dev); | ||
| 322 | } | ||
| 323 | |||
| 308 | /* the PCI probing function */ | 324 | /* the PCI probing function */ |
| 309 | static int __devinit virtio_pci_probe(struct pci_dev *pci_dev, | 325 | static int __devinit virtio_pci_probe(struct pci_dev *pci_dev, |
| 310 | const struct pci_device_id *id) | 326 | const struct pci_device_id *id) |
| @@ -328,6 +344,7 @@ static int __devinit virtio_pci_probe(struct pci_dev *pci_dev, | |||
| 328 | return -ENOMEM; | 344 | return -ENOMEM; |
| 329 | 345 | ||
| 330 | vp_dev->vdev.dev.parent = &virtio_pci_root; | 346 | vp_dev->vdev.dev.parent = &virtio_pci_root; |
| 347 | vp_dev->vdev.dev.release = virtio_pci_release_dev; | ||
| 331 | vp_dev->vdev.config = &virtio_pci_config_ops; | 348 | vp_dev->vdev.config = &virtio_pci_config_ops; |
| 332 | vp_dev->pci_dev = pci_dev; | 349 | vp_dev->pci_dev = pci_dev; |
| 333 | INIT_LIST_HEAD(&vp_dev->virtqueues); | 350 | INIT_LIST_HEAD(&vp_dev->virtqueues); |
| @@ -357,7 +374,7 @@ static int __devinit virtio_pci_probe(struct pci_dev *pci_dev, | |||
| 357 | 374 | ||
| 358 | /* register a handler for the queue with the PCI device's interrupt */ | 375 | /* register a handler for the queue with the PCI device's interrupt */ |
| 359 | err = request_irq(vp_dev->pci_dev->irq, vp_interrupt, IRQF_SHARED, | 376 | err = request_irq(vp_dev->pci_dev->irq, vp_interrupt, IRQF_SHARED, |
| 360 | vp_dev->vdev.dev.bus_id, vp_dev); | 377 | dev_name(&vp_dev->vdev.dev), vp_dev); |
| 361 | if (err) | 378 | if (err) |
| 362 | goto out_set_drvdata; | 379 | goto out_set_drvdata; |
| 363 | 380 | ||
| @@ -387,12 +404,6 @@ static void __devexit virtio_pci_remove(struct pci_dev *pci_dev) | |||
| 387 | struct virtio_pci_device *vp_dev = pci_get_drvdata(pci_dev); | 404 | struct virtio_pci_device *vp_dev = pci_get_drvdata(pci_dev); |
| 388 | 405 | ||
| 389 | unregister_virtio_device(&vp_dev->vdev); | 406 | unregister_virtio_device(&vp_dev->vdev); |
| 390 | free_irq(pci_dev->irq, vp_dev); | ||
| 391 | pci_set_drvdata(pci_dev, NULL); | ||
| 392 | pci_iounmap(pci_dev, vp_dev->ioaddr); | ||
| 393 | pci_release_regions(pci_dev); | ||
| 394 | pci_disable_device(pci_dev); | ||
| 395 | kfree(vp_dev); | ||
| 396 | } | 407 | } |
| 397 | 408 | ||
| 398 | #ifdef CONFIG_PM | 409 | #ifdef CONFIG_PM |
diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c index 6eb5303fed11..5777196bf6c9 100644 --- a/drivers/virtio/virtio_ring.c +++ b/drivers/virtio/virtio_ring.c | |||
| @@ -274,6 +274,7 @@ static struct virtqueue_ops vring_vq_ops = { | |||
| 274 | }; | 274 | }; |
| 275 | 275 | ||
| 276 | struct virtqueue *vring_new_virtqueue(unsigned int num, | 276 | struct virtqueue *vring_new_virtqueue(unsigned int num, |
| 277 | unsigned int vring_align, | ||
| 277 | struct virtio_device *vdev, | 278 | struct virtio_device *vdev, |
| 278 | void *pages, | 279 | void *pages, |
| 279 | void (*notify)(struct virtqueue *), | 280 | void (*notify)(struct virtqueue *), |
| @@ -292,7 +293,7 @@ struct virtqueue *vring_new_virtqueue(unsigned int num, | |||
| 292 | if (!vq) | 293 | if (!vq) |
| 293 | return NULL; | 294 | return NULL; |
| 294 | 295 | ||
| 295 | vring_init(&vq->vring, num, pages, PAGE_SIZE); | 296 | vring_init(&vq->vring, num, pages, vring_align); |
| 296 | vq->vq.callback = callback; | 297 | vq->vq.callback = callback; |
| 297 | vq->vq.vdev = vdev; | 298 | vq->vq.vdev = vdev; |
| 298 | vq->vq.vq_ops = &vring_vq_ops; | 299 | vq->vq.vq_ops = &vring_vq_ops; |
diff --git a/include/linux/lguest_launcher.h b/include/linux/lguest_launcher.h index e7217dc58f39..a53407a4165c 100644 --- a/include/linux/lguest_launcher.h +++ b/include/linux/lguest_launcher.h | |||
| @@ -54,9 +54,13 @@ struct lguest_vqconfig { | |||
| 54 | /* Write command first word is a request. */ | 54 | /* Write command first word is a request. */ |
| 55 | enum lguest_req | 55 | enum lguest_req |
| 56 | { | 56 | { |
| 57 | LHREQ_INITIALIZE, /* + base, pfnlimit, pgdir, start */ | 57 | LHREQ_INITIALIZE, /* + base, pfnlimit, start */ |
| 58 | LHREQ_GETDMA, /* No longer used */ | 58 | LHREQ_GETDMA, /* No longer used */ |
| 59 | LHREQ_IRQ, /* + irq */ | 59 | LHREQ_IRQ, /* + irq */ |
| 60 | LHREQ_BREAK, /* + on/off flag (on blocks until someone does off) */ | 60 | LHREQ_BREAK, /* + on/off flag (on blocks until someone does off) */ |
| 61 | }; | 61 | }; |
| 62 | |||
| 63 | /* The alignment to use between consumer and producer parts of vring. | ||
| 64 | * x86 pagesize for historical reasons. */ | ||
| 65 | #define LGUEST_VRING_ALIGN 4096 | ||
| 62 | #endif /* _LINUX_LGUEST_LAUNCHER */ | 66 | #endif /* _LINUX_LGUEST_LAUNCHER */ |
diff --git a/include/linux/virtio_balloon.h b/include/linux/virtio_balloon.h index c30c7bfbf39b..8726ff77763e 100644 --- a/include/linux/virtio_balloon.h +++ b/include/linux/virtio_balloon.h | |||
| @@ -10,6 +10,9 @@ | |||
| 10 | /* The feature bitmap for virtio balloon */ | 10 | /* The feature bitmap for virtio balloon */ |
| 11 | #define VIRTIO_BALLOON_F_MUST_TELL_HOST 0 /* Tell before reclaiming pages */ | 11 | #define VIRTIO_BALLOON_F_MUST_TELL_HOST 0 /* Tell before reclaiming pages */ |
| 12 | 12 | ||
| 13 | /* Size of a PFN in the balloon interface. */ | ||
| 14 | #define VIRTIO_BALLOON_PFN_SHIFT 12 | ||
| 15 | |||
| 13 | struct virtio_balloon_config | 16 | struct virtio_balloon_config |
| 14 | { | 17 | { |
| 15 | /* Number of pages host wants Guest to give up. */ | 18 | /* Number of pages host wants Guest to give up. */ |
diff --git a/include/linux/virtio_console.h b/include/linux/virtio_console.h index 19a0da0dba41..7615ffcdd555 100644 --- a/include/linux/virtio_console.h +++ b/include/linux/virtio_console.h | |||
| @@ -7,6 +7,17 @@ | |||
| 7 | /* The ID for virtio console */ | 7 | /* The ID for virtio console */ |
| 8 | #define VIRTIO_ID_CONSOLE 3 | 8 | #define VIRTIO_ID_CONSOLE 3 |
| 9 | 9 | ||
| 10 | /* Feature bits */ | ||
| 11 | #define VIRTIO_CONSOLE_F_SIZE 0 /* Does host provide console size? */ | ||
| 12 | |||
| 13 | struct virtio_console_config { | ||
| 14 | /* colums of the screens */ | ||
| 15 | __u16 cols; | ||
| 16 | /* rows of the screens */ | ||
| 17 | __u16 rows; | ||
| 18 | } __attribute__((packed)); | ||
| 19 | |||
| 20 | |||
| 10 | #ifdef __KERNEL__ | 21 | #ifdef __KERNEL__ |
| 11 | int __init virtio_cons_early_init(int (*put_chars)(u32, const char *, int)); | 22 | int __init virtio_cons_early_init(int (*put_chars)(u32, const char *, int)); |
| 12 | #endif /* __KERNEL__ */ | 23 | #endif /* __KERNEL__ */ |
diff --git a/include/linux/virtio_pci.h b/include/linux/virtio_pci.h index cdef35742932..cd0fd5d181a6 100644 --- a/include/linux/virtio_pci.h +++ b/include/linux/virtio_pci.h | |||
| @@ -53,4 +53,12 @@ | |||
| 53 | 53 | ||
| 54 | /* Virtio ABI version, this must match exactly */ | 54 | /* Virtio ABI version, this must match exactly */ |
| 55 | #define VIRTIO_PCI_ABI_VERSION 0 | 55 | #define VIRTIO_PCI_ABI_VERSION 0 |
| 56 | |||
| 57 | /* How many bits to shift physical queue address written to QUEUE_PFN. | ||
| 58 | * 12 is historical, and due to x86 page size. */ | ||
| 59 | #define VIRTIO_PCI_QUEUE_ADDR_SHIFT 12 | ||
| 60 | |||
| 61 | /* The alignment to use between consumer and producer parts of vring. | ||
| 62 | * x86 pagesize again. */ | ||
| 63 | #define VIRTIO_PCI_VRING_ALIGN 4096 | ||
| 56 | #endif | 64 | #endif |
diff --git a/include/linux/virtio_ring.h b/include/linux/virtio_ring.h index c4a598fb3826..71e03722fb59 100644 --- a/include/linux/virtio_ring.h +++ b/include/linux/virtio_ring.h | |||
| @@ -83,7 +83,7 @@ struct vring { | |||
| 83 | * __u16 avail_idx; | 83 | * __u16 avail_idx; |
| 84 | * __u16 available[num]; | 84 | * __u16 available[num]; |
| 85 | * | 85 | * |
| 86 | * // Padding to the next page boundary. | 86 | * // Padding to the next align boundary. |
| 87 | * char pad[]; | 87 | * char pad[]; |
| 88 | * | 88 | * |
| 89 | * // A ring of used descriptor heads with free-running index. | 89 | * // A ring of used descriptor heads with free-running index. |
| @@ -93,19 +93,19 @@ struct vring { | |||
| 93 | * }; | 93 | * }; |
| 94 | */ | 94 | */ |
| 95 | static inline void vring_init(struct vring *vr, unsigned int num, void *p, | 95 | static inline void vring_init(struct vring *vr, unsigned int num, void *p, |
| 96 | unsigned long pagesize) | 96 | unsigned long align) |
| 97 | { | 97 | { |
| 98 | vr->num = num; | 98 | vr->num = num; |
| 99 | vr->desc = p; | 99 | vr->desc = p; |
| 100 | vr->avail = p + num*sizeof(struct vring_desc); | 100 | vr->avail = p + num*sizeof(struct vring_desc); |
| 101 | vr->used = (void *)(((unsigned long)&vr->avail->ring[num] + pagesize-1) | 101 | vr->used = (void *)(((unsigned long)&vr->avail->ring[num] + align-1) |
| 102 | & ~(pagesize - 1)); | 102 | & ~(align - 1)); |
| 103 | } | 103 | } |
| 104 | 104 | ||
| 105 | static inline unsigned vring_size(unsigned int num, unsigned long pagesize) | 105 | static inline unsigned vring_size(unsigned int num, unsigned long align) |
| 106 | { | 106 | { |
| 107 | return ((sizeof(struct vring_desc) * num + sizeof(__u16) * (2 + num) | 107 | return ((sizeof(struct vring_desc) * num + sizeof(__u16) * (2 + num) |
| 108 | + pagesize - 1) & ~(pagesize - 1)) | 108 | + align - 1) & ~(align - 1)) |
| 109 | + sizeof(__u16) * 2 + sizeof(struct vring_used_elem) * num; | 109 | + sizeof(__u16) * 2 + sizeof(struct vring_used_elem) * num; |
| 110 | } | 110 | } |
| 111 | 111 | ||
| @@ -115,6 +115,7 @@ struct virtio_device; | |||
| 115 | struct virtqueue; | 115 | struct virtqueue; |
| 116 | 116 | ||
| 117 | struct virtqueue *vring_new_virtqueue(unsigned int num, | 117 | struct virtqueue *vring_new_virtqueue(unsigned int num, |
| 118 | unsigned int vring_align, | ||
| 118 | struct virtio_device *vdev, | 119 | struct virtio_device *vdev, |
| 119 | void *pages, | 120 | void *pages, |
| 120 | void (*notify)(struct virtqueue *vq), | 121 | void (*notify)(struct virtqueue *vq), |
