05.2 virtio introduction

59
VIRTIO Yi-Man Ma & Chang-Jung Lin 2011 / 01 / 05 1 Thursday, January 5, 12

Upload: zenixls2

Post on 25-Jun-2015

2.705 views

Category:

Technology


9 download

DESCRIPTION

ARM Virtualization

TRANSCRIPT

Page 1: 05.2 virtio introduction

VIRTIOYi-Man Ma & Chang-Jung Lin

2011 / 01 / 051Thursday, January 5, 12

Page 2: 05.2 virtio introduction

Agenda

Introduction

Architecture

VirtQueue & Vring

Five APIs

Adding a new Virtio Device / Driver

2Thursday, January 5, 12

Page 3: 05.2 virtio introduction

INTRODUCTION

3Thursday, January 5, 12

Page 4: 05.2 virtio introduction

Introduction

Create a shortcut to deal with IO Request

Coalesced IO Request by VirtQueue

4Thursday, January 5, 12

Page 5: 05.2 virtio introduction

Introduction

Device emulation in full virtualization

and paravirtualization environments

Guest operating system

Hardware

Traps

Device emulationHypervisor

(Full virtualization)

Guest operating system

Hardware

Interfaces

Device emulationHypervisor

(Full virtualization)

Para-drivers

5Thursday, January 5, 12

Page 6: 05.2 virtio introduction

ARCHITECTURE

6Thursday, January 5, 12

Page 7: 05.2 virtio introduction

Architecture

KVM

Hardware

QEMU

GUEST1

Host

QEMU

GUEST2

OtherProcesses

Transport Transport

7Thursday, January 5, 12

Page 8: 05.2 virtio introduction

Architecture

Guest

QEMU

Virtio Driver

Virtio Device

Virtio PCI Controller

Virtio PCI Controller

TransportVring

8Thursday, January 5, 12

Page 9: 05.2 virtio introduction

VIRTQUEUE & VRING

9Thursday, January 5, 12

Page 10: 05.2 virtio introduction

VirtQueue

Each Device have it’s own virtqueues.

Queue Requests

10Thursday, January 5, 12

Page 11: 05.2 virtio introduction

Vring

Each virtqueue have it’s own vring.

Memory Mapped between QEMU & Guest

Actual memory layout for queue

11Thursday, January 5, 12

Page 12: 05.2 virtio introduction

Guest

QEMU

Virtio Driver

Virtio Device

Virtio PCI Controller

Virtio PCI Controller

TransportVring

VirtQueue

Find virtqueue

Vring

Alloc Vring

Vring GPA

12Thursday, January 5, 12

Page 13: 05.2 virtio introduction

Virt queue Read

Vring

Virtio Driver

Virtio Device

VirtQueue

Vring

Virt queue Write

Vring

13Thursday, January 5, 12

Page 14: 05.2 virtio introduction

Virt queue Read

Vring

Virtio Driver

Virtio Device

VirtQueue

Vring

Virt queue Write

Vring

14Thursday, January 5, 12

Page 15: 05.2 virtio introduction

Virt queue Read

Vring

Virtio Driver

Virtio Device

VirtQueue

Vring

Virt queue Write

Vring

Add Buf

In Outdata

15Thursday, January 5, 12

Page 16: 05.2 virtio introduction

Virt queue Read

Vring

Virtio Driver

Virtio Device

VirtQueue

Vring

Virt queue Write

Vring

Kick

In Outdata

16Thursday, January 5, 12

Page 17: 05.2 virtio introduction

Virt queue Read

Vring

Virtio Driver

Virtio Device

VirtQueue

Vring

Virt queue Write

Vring In Outdata

POP

17Thursday, January 5, 12

Page 18: 05.2 virtio introduction

Virt queue Read

Vring

Virtio Driver

Virtio Device

VirtQueue

Vring

Virt queue Write

Vring In Outdata

Push

18Thursday, January 5, 12

Page 19: 05.2 virtio introduction

Virt queue Read

Vring

Virtio Driver

Virtio Device

VirtQueue

Vring

Virt queue Write

Vring In Outdata

Get Buf

19Thursday, January 5, 12

Page 20: 05.2 virtio introduction

FIVE APIS

20Thursday, January 5, 12

Page 21: 05.2 virtio introduction

Five APIs

add_buf

kick

get_buf

disable_cb

enable_cb

21Thursday, January 5, 12

Page 22: 05.2 virtio introduction

Five APIs

add_buf

expose buffer to other end

get_buf

get the next used buffer

add & get buf

22Thursday, January 5, 12

Page 23: 05.2 virtio introduction

Five APIs

kick

update after add_buf

notify QEMU to deal with the data

kick

23Thursday, January 5, 12

Page 24: 05.2 virtio introduction

Five APIs

disable_cb

disable callbacks

not necessarily synchronous

unreliable and only useful as an optimization

enable_cb

restart callbacks after disable_cb

CB relative

24Thursday, January 5, 12

Page 25: 05.2 virtio introduction

NEW DEVICE / DRIVER

25Thursday, January 5, 12

Page 26: 05.2 virtio introduction

New Driver

include/linux/virtio_ids.h

include/linux/virtio.h

include/linux/virtio_[device].h

drivers/virtio/virtio_[device].c

drivers/virtio/virtio_pci.c

26Thursday, January 5, 12

Page 27: 05.2 virtio introduction

New Device

hw/virtio-[device].c

hw/virtio-[device].h

hw/pci.h

hw/virtio_pci.c

27Thursday, January 5, 12

Page 28: 05.2 virtio introduction

Architecture

Guest

QEMU

Virtio Driver

Virtio Device

Virtio PCI Controller

Virtio PCI Controller

TransportVring

28Thursday, January 5, 12

Page 29: 05.2 virtio introduction

Virtio PCI Controller

New Device

Modify qemu-src/hw/pci.h

#define PCI_DEVICE_ID_VIRTIO_[device] 0x1004

add device id

29Thursday, January 5, 12

Page 30: 05.2 virtio introduction

Virtio PCI Controller

New Device

Modify qemu-src/hw/virtio-pci.c

static int virtio_[device]_init_pci(PCIDevice *pci_dev){ VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev); VirtIODevice *vdev; vdev = virtio_[device]_init(&pci_dev->qdev); if (!vdev) { return -1; } virtio_init_pci(proxy, vdev); return 0;}

initial handler

30Thursday, January 5, 12

Page 31: 05.2 virtio introduction

Virtio PCI Controller

New Device

Modify qemu-src/hw/virtio-pci.cstatic int virtio_[device]_exit_pci (PCIDevice *pci_dev){ VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);

virtio_pci_stop_ioeventfd(proxy); virtio_[device]_exit(proxy->vdev);

return virtio_exit_pci(pci_dev);}

exit handler

31Thursday, January 5, 12

Page 32: 05.2 virtio introduction

Virtio PCI Controller

New Device

Modify qemu-src/hw/virtio-pci.cstatic PCIDeviceInfo virtio_info[] = { { .qdev.name = "virtio-[device]-pci", .qdev.alias = "virtio-[device]", .init = virtio_[device]_init_pci, .exit = virtio_[device]_exit_pci, .device_id = PCI_DEVICE_ID_VIRTIO_[device], .qdev.props = (Property[]) { DEFINE_VIRTIO_COMMON_FEATURES( VirtIOPCIProxy, host_features), DEFINE_PROP_END_OF_LIST(), }, ...... (Skip)

add device info

32Thursday, January 5, 12

Page 33: 05.2 virtio introduction

Architecture

Guest

QEMU

Virtio Driver

Virtio Device

Virtio PCI Controller

Virtio PCI Controller

TransportVring

33Thursday, January 5, 12

Page 34: 05.2 virtio introduction

New Device

Add virtio-[device].c, virtio[device].h

Put them under the directory qemu-src/hw/

Virtio Device

34Thursday, January 5, 12

Page 35: 05.2 virtio introduction

New Device Virtio Device

#ifndef _QEMU_VIRTIO_[device]_H

#include "virtio.h“

#define _QEMU_VIRTIO_[device]_H#define VIRTIO_ID_[device] [num] //ID for your device

VirtIODevice *virtio_[device]_init(DeviceState *dev);void virtio_[device]_exit(VirtIODevice *vdev);

#endif

virtio-[device

].h

35Thursday, January 5, 12

Page 36: 05.2 virtio introduction

New Device Virtio Device

#include <qemu-common.h>#include "qemu-error.h"#include "virtio-[device].h"#include "virtio.h"

virtio-[device

].c

struct virtio_[device]_config { int config;} ;

typedef struct VirtIO[device]{ VirtIODevice vdev; VirtQueue *vq[num]; DeviceState *qdev; int status;} VirtIO[device];

36Thursday, January 5, 12

Page 37: 05.2 virtio introduction

New Device Virtio Device

struct VirtIODevice { ........... uint32_t (*get_features)(VirtIODevice *vdev, uint32_t requested_features); uint32_t (*bad_features)(VirtIODevice *vdev); void (*set_features)(VirtIODevice *vdev, uint32_t val); void (*get_config)(VirtIODevice *vdev, uint8_t *config); void (*set_config)(VirtIODevice *vdev, const uint8_t *config); void (*reset)(VirtIODevice *vdev); void (*set_status)(VirtIODevice *vdev, uint8_t val); .......} ;

virtio stru

cture

37Thursday, January 5, 12

Page 38: 05.2 virtio introduction

New Device Virtio Device

static VirtIO[device] *to_virtio_[device](VirtIODevice *vdev) //Get device defined by yourselfstatic uint32_t virtio_[device]_ get_features (VirtIODevice *vdev, uint32_t features);static uint32_t virtio_[device]_ bad_features (VirtIODevice *vdev);static void virtio_[device]_ set_features (VirtIODevice *vdev, uint32_t val);static void virtio_[device]_ get_config (VirtIODevice *vdev, uint8_t *config);static void virtio_[device]_ set_config (VirtIODevice *vdev, const uint8_t *config);

need implement

38Thursday, January 5, 12

Page 39: 05.2 virtio introduction

static void virtio_[device]_ reset (VirtIODevice *vdev);static void virtio_[device]_ set_status (VirtIODevice *vdev, uint8_t val);

VirtIODevice *virtio_[device]_init(DeviceState *dev); //Initialize your devicevoid virtio_[device]_exit (VirtIODevice *vdev);

static void virtio_[device]_save(QEMUFile *f, void *opaque);static int virtio_[device]_load(QEMUFile *f, void *opaque, int version_id);

static void virtio_[device]_handle_out(VirtIODevice *vdev, VirtQueue *vq);

New Device Virtio Deviceneed implement

39Thursday, January 5, 12

Page 40: 05.2 virtio introduction

New Device

static uint32_t virtio_[device]_ get_features (VirtIODevice *vdev, uint32_t features){ VirtIO[device] *n = to_virtio_[device](vdev); return features;}static uint32_t virtio_[device]_ bad_features (VirtIODevice *vdev){ uint32_t features = 0; return features;}static void virtio_[device]_ set_features (VirtIODevice *vdev, uint32_t val){ VirtIOMy *n = to_virtio_[device](vdev);}

Virtio Deviceabout features

40Thursday, January 5, 12

Page 41: 05.2 virtio introduction

New Device Virtio Deviceabout co

nfig

static void virtio_[device]_ get_config (VirtIODevice *vdev, uint8_t *config){ VirtIO[device] *n = to_virtio_[device](vdev); struct virtio_[device]_config cfg; stw_p(&cfg.config, n->status); memcpy(config, &cfg, sizeof(cfg));}static void virtio_[device]_ set_config (VirtIODevice *vdev, const uint8_t *config){ VirtIO[de vice] *n = to_virtio_[device](vdev); struct virtio_[device]_config cfg;}

41Thursday, January 5, 12

Page 42: 05.2 virtio introduction

New Device Virtio Deviceset & reset

static void virtio_[device]_ reset (VirtIODevice *vdev){}

static void virtio_[device]_ set_status (VirtIODevice *vdev, uint8_t val){ VirtIO[device] *n = to_virtio_my(vdev);}

42Thursday, January 5, 12

Page 43: 05.2 virtio introduction

New Device

VirtIODevice *virtio_[device]_init(DeviceState *dev) { VirtIO[device] *s;

s = (VirtIO[device]*)virtio_common_init("virtio-[device]", VIRTIO_ID_[device], sizeof(struct virtio_[device]_config), sizeof(VirtIO[device])); s->vdev.get_config = virtio_[device]get_config; s->vdev.set_config = virtio_[device]_set_config; s->vdev.get_features = virtio_[device]_get_features; s->vdev.set_features = virtio_[device]_set_features; s->vdev.bad_features = virtio_[device]_bad_features; s->vdev.reset = virtio_[device]_reset; s->vdev.set_status = virtio_[device]_set_status;

.....

initial device Virtio Device

43Thursday, January 5, 12

Page 44: 05.2 virtio introduction

New Device

..... s->vdev.set_status = virtio_[device]_set_status; s->vq[0] = virtio_add_queue(&s->vdev, 1024, virtio_[device]_handle_out1); s->vq[1] = virtio_add_queue(&s->vdev, 1024, virtio_[device]_handle_out2); s->qdev = dev; s->status = 99; register_savevm(dev, "virtio-[device]”, 0, 2, virtio_[device]_save, virtio_[device]_load, s);

return &s->vdev;}

initial device Virtio Device

44Thursday, January 5, 12

Page 45: 05.2 virtio introduction

New Deviceexit device

void virtio_[device]_exit (VirtIODevice *vdev){ VirtIO[device] *s = to_virtio_[device](vdev); unregister_savevm(s->qdev, "virtio-[device]“ , s);}

Virtio Device

45Thursday, January 5, 12

Page 46: 05.2 virtio introduction

New Device

save & load Virtio Device

static void virtio_[device]_save(QEMUFile *f, void *opaque){ VirtIO[device] *n = opaque; virtio_save(&n->vdev, f);}static int virtio_[device]_load(QEMUFile *f, void *opaque, int version_id){ VirtIO[device] *n = opaque; virtio_load(&n->vdev, f); return 0;}

46Thursday, January 5, 12

Page 47: 05.2 virtio introduction

New Device

data handler

Virtio Device

static void virtio_[device]_handle_out(VirtIODevice *vdev, VirtQueue *vq){ VirtIO[device] *n = to_virtio_my(vdev); VirtQueueElement elem1, elem2; int K; memset(&elem1, 0, sizeof(elem1)); memset(&elem2, 0, sizeof(elem2)); virtqueue_pop(vq, &elem1); if(memcmp(&elem1, &elem2, sizeof(elem1))) printf("something happened!!!\n"); K = *((int*)elem1.out_sg[0].iov_base) + 1; memcpy(elem1.in_sg[0].iov_base, &K, sizeof(int)); virtqueue_push(vq, &elem1, sizeof(int));}

47Thursday, January 5, 12

Page 48: 05.2 virtio introduction

Architecture

Guest

QEMU

Virtio Driver

Virtio Device

Virtio PCI Controller

Virtio PCI Controller

TransportVring

48Thursday, January 5, 12

Page 49: 05.2 virtio introduction

New Driver

Virtio Driver

Modify kernel-src/include/linux/virtio-ids.h

device id

#define VIRTIO_ID_[device] number

Should be the same number as defined in qemu

49Thursday, January 5, 12

Page 50: 05.2 virtio introduction

New Driver

Virtio Driver

#include "linux/virtio.h“#include "linux/virtio_ids.h“#include "linux/virtio_pci.h“#include "virtio.h"static struct virtio_device_id id_table[] = { {VIRTIO_ID_[device], VIRTIO_DEV_ANY_ID}, {0}};struct virtio_[device]{ int size; void* data; void* mapbuf; struct semaphore sem; struct cdev cdev; struct virtio_device *vdev; struct virtqueue *vq[2];} my_cdev;

50Thursday, January 5, 12

Page 51: 05.2 virtio introduction

New Driver

Virtio Driver

define structure

static struct virtio_driver virtio_[device]_driver = { .feature_table = features, .feature_table_size = ARRAY_SIZE(features), .driver.name = KBUILD_MODNAME, .driver.owner = THIS_MODULE, .id_table = id_table, .probe = my_probe, .remove = __devexit_p(my_remove),};

51Thursday, January 5, 12

Page 52: 05.2 virtio introduction

New Driver

Virtio Driver

Register & unregister driver - two APIs

register_virtio_driver(&virtio_[device]_driver);

unregister_virtio_driver(&virtio_[device]_driver);

52Thursday, January 5, 12

Page 53: 05.2 virtio introduction

Architecture

Guest

QEMU

Virtio Driver

Virtio Device

Virtio PCI Controller

Virtio PCI Controller

TransportVring

53Thursday, January 5, 12

Page 54: 05.2 virtio introduction

Communication

Vringdrive

r side

char * buffer1, buffer2;int* A[2] = {buffer1, buffer2};struct scatterlist sg[2]; /*0 for output, 1 for input*/struct virtqueue *vq[2];const char *names[2] = { “[Q1]“ , “[Q2]“ };vq_callback_t *cb[2] = {NULL, NULL};

vdev->config->find_vqs(vdev, 2, vq, cb, names);my_cdev.vq[0] = vq[0];my_cdev.vq[1] = vq[1];

Declare necessary parameter

Find virtqueue

54Thursday, January 5, 12

Page 55: 05.2 virtio introduction

Communication

Vringdrive

r side

Send data to qemu

Get data from qemu

sg_init_table(sg, ARRAY_SIZE(sg));sg_set_buf(&sg[0], buffer1, [count]);sg_set_buf(&sg[1], buffer2, [count]);virtqueue_add_buf(myc->vq[0], sg, /*out*/1, /*in*/1, A);virtqueue_kick(myc->vq[0]);

virtqueue_get_buf(myc->vq[0], &len);

55Thursday, January 5, 12

Page 56: 05.2 virtio introduction

Communication

Vringdevice

side

s->vq[0] = virtio_add_queue(&s->vdev, 1024, virtio_[device]_handle_out1);s->vq[1] = virtio_add_queue(&s->vdev, 1024, virtio_[device]_handle_out2);

VirtQueueElement elem1, elem2;memset(&elem1, 0, sizeof(elem1));memset(&elem2, 0, sizeof(elem2));

Set virtqueue handler @init function

Declare variable for data @virtqueue handler

56Thursday, January 5, 12

Page 57: 05.2 virtio introduction

Communication

Vringdevice

side

typedef struct VirtQueueElement{ unsigned int index; unsigned int out_num; unsigned int in_num; target_phys_addr_t in_addr[VIRTQUEUE_MAX_SIZE]; target_phys_addr_t out_addr[VIRTQUEUE_MAX_SIZE]; struct iovec in_sg[VIRTQUEUE_MAX_SIZE]; struct iovec out_sg[VIRTQUEUE_MAX_SIZE];} VirtQueueElement;

VirtQueueElement

57Thursday, January 5, 12

Page 58: 05.2 virtio introduction

Communication

Vringdevice

side

virtqueue_pop(vq, &elem1);

if(memcmp(&elem1, &elem2, sizeof(elem1))) do something;

memcpy(elem1.in_sg[0].iov_base, &data, sizeof(data));

elem1.in_sg[0].iov_len = sizeof(data);virtqueue_push(vq, &elem1, sizeof(data));

Pop

Check if data exist

Put data to elem

Push data back to guest

58Thursday, January 5, 12