diff --git a/.gitignore b/.gitignore index fe754f0..07216f3 100644 --- a/.gitignore +++ b/.gitignore @@ -12,4 +12,6 @@ initcode initcode.out kernelmemfs mkfs +kernel/kernel +user/usys.S .gdbinit diff --git a/kernel/virtio.h b/kernel/virtio.h index c142af9..03b53a9 100644 --- a/kernel/virtio.h +++ b/kernel/virtio.h @@ -43,6 +43,10 @@ #define VIRTIO_RING_F_INDIRECT_DESC 28 #define VIRTIO_RING_F_EVENT_IDX 29 +// this many virtio descriptors. +// must be a power of two. +#define NUM 8 + struct VRingDesc { uint64 addr; uint32 len; @@ -60,3 +64,9 @@ struct VRingUsedElem { // for disk ops #define VIRTIO_BLK_T_IN 0 // read the disk #define VIRTIO_BLK_T_OUT 1 // write the disk + +struct UsedArea { + uint16 flags; + uint16 id; + struct VRingUsedElem elems[NUM]; +}; diff --git a/kernel/virtio_disk.c b/kernel/virtio_disk.c index 6bcad9c..855c902 100644 --- a/kernel/virtio_disk.c +++ b/kernel/virtio_disk.c @@ -22,10 +22,6 @@ struct spinlock virtio_disk_lock; -// this many virtio descriptors. -// must be a power of two. -#define NUM 8 - // memory for virtio descriptors &c for queue 0. // this is a global instead of allocated because it has // to be multiple contiguous pages, which kalloc() @@ -34,7 +30,7 @@ __attribute__ ((aligned (PGSIZE))) static char pages[2*PGSIZE]; static struct VRingDesc *desc; static uint16 *avail; -static char *used; +static struct UsedArea *used; // our own book-keeping. static char free[NUM]; // is a descriptor free? @@ -106,7 +102,7 @@ virtio_disk_init(void) desc = (struct VRingDesc *) pages; avail = (uint16*)(((char*)desc) + NUM*sizeof(struct VRingDesc)); - used = pages + PGSIZE; + used = (struct UsedArea *) (pages + PGSIZE); for(int i = 0; i < NUM; i++) free[i] = 1; @@ -153,6 +149,21 @@ free_chain(int i) } } +static int +alloc3_desc(int *idx) +{ + for(int i = 0; i < 3; i++){ + idx[i] = alloc_desc(); + if(idx[i] < 0){ + for(int j = 0; j < i; j++) + free_desc(idx[j]); + return -1; + break; + } + } + return 0; +} + void virtio_disk_rw(struct buf *b) { @@ -167,21 +178,12 @@ virtio_disk_rw(struct buf *b) // allocate the three descriptors. int idx[3]; while(1){ - int done = 1; - for(int i = 0; i < 3; i++){ - idx[i] = alloc_desc(); - if(idx[i] < 0){ - for(int j = 0; j < i; j++) - free_desc(idx[j]); - done = 0; - break; - } - } - if(done) + if(alloc3_desc(idx) == 0) { break; + } sleep(&free[0], &virtio_disk_lock); } - + // format the three descriptors. // qemu's virtio-blk.c reads them. @@ -242,28 +244,21 @@ virtio_disk_rw(struct buf *b) void virtio_disk_intr() { - // the used area is: - // uint16 flags - // uint16 idx - // array of VRingUsedElem - volatile uint16 *idxp = (uint16 *)(used + 2); - volatile struct VRingUsedElem *e0 = (struct VRingUsedElem *)(used + 4); - acquire(&virtio_disk_lock); - while((used_idx % NUM) != (*idxp % NUM)){ - volatile struct VRingUsedElem *ue = &e0[used_idx]; + while((used_idx % NUM) != (used->id % NUM)){ + int id = used->elems[used_idx].id; - if(info[ue->id].status != 0) + if(info[id].status != 0) panic("virtio_disk_intr status"); - info[ue->id].b->flags |= B_VALID; - info[ue->id].b->flags &= ~B_DIRTY; + info[id].b->flags |= B_VALID; + info[id].b->flags &= ~B_DIRTY; - wakeup(info[ue->id].b); + wakeup(info[id].b); - info[ue->id].b = 0; - free_chain(ue->id); + info[id].b = 0; + free_chain(id); used_idx = (used_idx + 1) % NUM; }