diff options
| author | Robert Morris <rtm@csail.mit.edu> | 2019-06-13 09:40:17 -0400 | 
|---|---|---|
| committer | Robert Morris <rtm@csail.mit.edu> | 2019-06-13 09:40:17 -0400 | 
| commit | ca39672a300196fb3ae4b05c469fa871fa7c13e8 (patch) | |
| tree | 0d0fd56db53284f009eca7298a8f1d559713275a /kernel | |
| parent | 4adf01692539c57c7612f105ecf3e8b5291ae018 (diff) | |
| download | xv6-labs-ca39672a300196fb3ae4b05c469fa871fa7c13e8.tar.gz xv6-labs-ca39672a300196fb3ae4b05c469fa871fa7c13e8.tar.bz2 xv6-labs-ca39672a300196fb3ae4b05c469fa871fa7c13e8.zip | |
clean up virtio code
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/memlayout.h | 4 | ||||
| -rw-r--r-- | kernel/plic.c | 4 | ||||
| -rw-r--r-- | kernel/trap.c | 2 | ||||
| -rw-r--r-- | kernel/virtio.h | 7 | ||||
| -rw-r--r-- | kernel/virtio_disk.c | 64 | ||||
| -rw-r--r-- | kernel/vm.c | 4 | 
6 files changed, 46 insertions, 39 deletions
| diff --git a/kernel/memlayout.h b/kernel/memlayout.h index e8c9aab..219c308 100644 --- a/kernel/memlayout.h +++ b/kernel/memlayout.h @@ -23,8 +23,8 @@  #define UART0_IRQ 10  // virtio mmio interface -#define VIRTIO 0x10001000 -#define VIRTIO_IRQ 1 // really the first of 8 units +#define VIRTIO0 0x10001000 +#define VIRTIO0_IRQ 1  // local interrupt controller, which contains the timer.  #define CLINT 0x2000000L diff --git a/kernel/plic.c b/kernel/plic.c index cc9a97e..b569492 100644 --- a/kernel/plic.c +++ b/kernel/plic.c @@ -13,7 +13,7 @@ plicinit(void)  {    // set desired IRQ priorities non-zero (otherwise disabled).    *(uint32*)(PLIC + UART0_IRQ*4) = 1; -  *(uint32*)(PLIC + VIRTIO_IRQ*4) = 1; +  *(uint32*)(PLIC + VIRTIO0_IRQ*4) = 1;  }  void @@ -22,7 +22,7 @@ plicinithart(void)    int hart = cpuid();    // set uart's enable bit for this hart's S-mode.  -  *(uint32*)PLIC_SENABLE(hart)= (1 << UART0_IRQ) | (1 << VIRTIO_IRQ); +  *(uint32*)PLIC_SENABLE(hart)= (1 << UART0_IRQ) | (1 << VIRTIO0_IRQ);    // set this hart's S-mode priority threshold to 0.    *(uint32*)PLIC_SPRIORITY(hart) = 0; diff --git a/kernel/trap.c b/kernel/trap.c index 13ad362..586f123 100644 --- a/kernel/trap.c +++ b/kernel/trap.c @@ -159,7 +159,7 @@ devintr()      if(irq == UART0_IRQ){        uartintr(); -    } else if(irq == VIRTIO_IRQ){ +    } else if(irq == VIRTIO0_IRQ){        virtio_disk_intr();      } diff --git a/kernel/virtio.h b/kernel/virtio.h index 258d107..bac215d 100644 --- a/kernel/virtio.h +++ b/kernel/virtio.h @@ -4,12 +4,15 @@  // only tested with qemu.  // this is the "legacy" virtio interface.  // +// the virtio spec: +// https://docs.oasis-open.org/virtio/virtio/v1.1/virtio-v1.1.pdf +//  // virtio mmio control registers, mapped starting at 0x10001000.  // from qemu virtio_mmio.h  #define VIRTIO_MMIO_MAGIC_VALUE		0x000 // 0x74726976 -#define VIRTIO_MMIO_VERSION		0x004 // 1 -- version, 1 is legacy -#define VIRTIO_MMIO_DEVICE_ID		0x008 // 2 -- block device type +#define VIRTIO_MMIO_VERSION		0x004 // version; 1 is legacy +#define VIRTIO_MMIO_DEVICE_ID		0x008 // device type; 1 is net, 2 is disk  #define VIRTIO_MMIO_VENDOR_ID		0x00c // 0x554d4551  #define VIRTIO_MMIO_DEVICE_FEATURES	0x010  #define VIRTIO_MMIO_DRIVER_FEATURES	0x020 diff --git a/kernel/virtio_disk.c b/kernel/virtio_disk.c index 558d3b0..6bcad9c 100644 --- a/kernel/virtio_disk.c +++ b/kernel/virtio_disk.c @@ -17,8 +17,8 @@  #include "buf.h"  #include "virtio.h" -// the address of a virtio mmio register. -#define R(off) ((volatile uint32 *)(VIRTIO + (off))) +// the address of virtio mmio register r. +#define R(r) ((volatile uint32 *)(VIRTIO0 + (r)))  struct spinlock virtio_disk_lock; @@ -45,6 +45,7 @@ static uint16 used_idx; // we've looked this far in used[2..NUM].  // indexed by first descriptor index of chain.  static struct {    struct buf *b; +  char status;  } info[NUM];  void @@ -54,8 +55,6 @@ virtio_disk_init(void)    initlock(&virtio_disk_lock, "virtio_disk"); -  // qemu's virtio-mmio.c -    if(*R(VIRTIO_MMIO_MAGIC_VALUE) != 0x74726976 ||       *R(VIRTIO_MMIO_VERSION) != 1 ||       *R(VIRTIO_MMIO_DEVICE_ID) != 2 || @@ -90,9 +89,7 @@ virtio_disk_init(void)    *R(VIRTIO_MMIO_GUEST_PAGE_SIZE) = PGSIZE; -  // qemu's hw/virtio/virtio.c - -  // initialize queue 0 +  // initialize queue 0.    *R(VIRTIO_MMIO_QUEUE_SEL) = 0;    uint32 max = *R(VIRTIO_MMIO_QUEUE_NUM_MAX);    if(max == 0) @@ -113,6 +110,8 @@ virtio_disk_init(void)    for(int i = 0; i < NUM; i++)      free[i] = 1; + +  // plic.c and trap.c arrange for interrupts from VIRTIO0_IRQ.  }  // find a free descriptor, mark it non-free, return its index. @@ -128,14 +127,30 @@ alloc_desc()    return -1;  } -void +// mark a descriptor as free. +static void  free_desc(int i)  {    if(i >= NUM)      panic("virtio_disk_intr 1");    if(free[i])      panic("virtio_disk_intr 2"); +  desc[i].addr = 0;    free[i] = 1; +  wakeup(&free[0]); +} + +// free a chain of descriptors. +static void +free_chain(int i) +{ +  while(1){ +    free_desc(i); +    if(desc[i].flags & VRING_DESC_F_NEXT) +      i = desc[i].next; +    else +      break; +  }  }  void @@ -145,7 +160,7 @@ virtio_disk_rw(struct buf *b)    acquire(&virtio_disk_lock); -  // the spec says that legacy block operations always use three +  // the spec says that legacy block operations use three    // descriptors: one for type/reserved/sector, one for    // the data, one for a 1-byte status result. @@ -158,7 +173,6 @@ virtio_disk_rw(struct buf *b)        if(idx[i] < 0){          for(int j = 0; j < i; j++)            free_desc(idx[j]); -        wakeup(&free[0]);          done = 0;          break;        } @@ -198,8 +212,8 @@ virtio_disk_rw(struct buf *b)    desc[idx[1]].flags |= VRING_DESC_F_NEXT;    desc[idx[1]].next = idx[2]; -  char status = 0; -  desc[idx[2]].addr = (uint64) &status; +  info[idx[0]].status = 0; +  desc[idx[2]].addr = (uint64) &info[idx[0]].status;    desc[idx[2]].len = 1;    desc[idx[2]].flags = VRING_DESC_F_WRITE; // device writes the status    desc[idx[2]].next = 0; @@ -232,16 +246,16 @@ virtio_disk_intr()    // uint16 flags    // uint16 idx    // array of VRingUsedElem - -  // XXX spec says to read INTERRUPT_STATUS and -  // write INTERRUPT_ACK +  volatile uint16 *idxp = (uint16 *)(used + 2); +  volatile struct VRingUsedElem *e0 = (struct VRingUsedElem *)(used + 4);    acquire(&virtio_disk_lock); -   -  while((used_idx % NUM) != (*(volatile uint16 *)(used+2) % NUM)){ -    struct VRingUsedElem *ue = (struct VRingUsedElem *) (used + 4 + 8*used_idx); -    // XXX check the one-byte status in the 3rd descriptor. +  while((used_idx % NUM) != (*idxp % NUM)){ +    volatile struct VRingUsedElem *ue = &e0[used_idx]; + +    if(info[ue->id].status != 0) +      panic("virtio_disk_intr status");      info[ue->id].b->flags |= B_VALID;      info[ue->id].b->flags &= ~B_DIRTY; @@ -249,17 +263,7 @@ virtio_disk_intr()      wakeup(info[ue->id].b);      info[ue->id].b = 0; - -    uint i = ue->id; -    while(1){ -      desc[i].addr = 0; -      free_desc(i); -      if(desc[i].flags & VRING_DESC_F_NEXT) -        i = desc[i].next; -      else -        break; -    } -    wakeup(&free[0]); +    free_chain(ue->id);      used_idx = (used_idx + 1) % NUM;    } diff --git a/kernel/vm.c b/kernel/vm.c index b6ca85b..580669f 100644 --- a/kernel/vm.c +++ b/kernel/vm.c @@ -31,8 +31,8 @@ kvminit()             UART0, PTE_R | PTE_W);    // virtio mmio disk interface -  mappages(kernel_pagetable, VIRTIO, PGSIZE, -           VIRTIO, PTE_R | PTE_W); +  mappages(kernel_pagetable, VIRTIO0, PGSIZE, +           VIRTIO0, PTE_R | PTE_W);    // CLINT    mappages(kernel_pagetable, CLINT, 0x10000, | 
