s-macke / jor1k

Online OR1K Emulator running Linux
http://jor1k.com
BSD 2-Clause "Simplified" License
1.73k stars 196 forks source link

Need help with Virtio #80

Closed facekapow closed 9 years ago

facekapow commented 9 years ago

Hey! Look, I help out with the runtimejs project (don't know if you know about it, but anyways) and I need some help with virtio-blk. There isn't any documentation mentioning headers for reads or writes, but QEMU errors and gives me this: virtio-blk missing headers. My code (data is another Uint8Array):

var u8 = new Uint8Array(3 + data.length + 1); // + 1 is for `status`, written by the device
u8[0] = 0; // type: read
u8[1] = 0; // priority: low
u8[2] = 1; // sector: 1
for (var i = 0; i < data.length; i++) {
  u8[3 + i] = data[i];
}

requestQueue.placeBuffers([u8], true); // this places the buffer into the device's request queue

I've been banging my head on this issue (not literally, of course) and I need it in order to have disk access. Any ideas? I know this has nothing to do with this project, but you wrote an interface in javascript from virtio to the block device (I looked at the source), so I thought maybe you'd know.

s-macke commented 9 years ago

Hi,

no I am not famiiiar with runtimejs. But sounds interesting. You can find the spec of the block virtio device here: http://docs.oasis-open.org/virtio/virtio/v1.0/csprd01/virtio-v1.0-csprd01.html#x1-1120002 I have implemented it myself here: https://github.com/s-macke/jor1k/blob/master/js/worker/dev/virtio/block.js

For me it looks like you assume, that each part of the header has a size of 1 byte. That is wrong. Type is a 32 bit value, priority (which is noot defined for me) has a size of 32 bit and sector is a 64-bit value. I use code called Marshall and Unmarshall to read/write these values. For example: marshall.Unmarshall2(["w", "w", "d"], GetByte);

facekapow commented 9 years ago

I've adapted your Marshall function to this:

function convert(typelist, input, struct, offset) {
  var item;
  var size = 0;
  for (var i=0; i < typelist.length; i++) {
    item = input[i];
    switch (typelist[i]) {
      case "w":
        struct[offset++] = item & 0xFF;
        struct[offset++] = (item >> 8) & 0xFF;
        struct[offset++] = (item >> 16) & 0xFF;
        struct[offset++] = (item >> 24) & 0xFF;
        size += 4;
        break;
      case "d": // double word
        struct[offset++] = item & 0xFF;
        struct[offset++] = (item >> 8) & 0xFF;
        struct[offset++] = (item >> 16) & 0xFF;
        struct[offset++] = (item >> 24) & 0xFF;
        struct[offset++] = 0x0;
        struct[offset++] = 0x0;
        struct[offset++] = 0x0;
        struct[offset++] = 0x0;
        size += 8;
        break;
    }
    // this is all I need
  }
  return size;
}

Given the following I still get the error, is QEMU's implementation different?

var head = new Uint8Array(16);

convert(["w", "w", "d"], [0, 0, 1], head);

Or should I be using 'd' instead of 'w', and 'q' instead of 'd'? I'm using QEMU system-x86_64.

s-macke commented 9 years ago

Looks Ok for me. You should set the offset to 0. And I am not sure, if it is Ok, to have zero bytes to read/write. Because that seems to be the case. Maybe enlarge the transferred size to to 512+16;

"w" and "d" are Ok.

facekapow commented 9 years ago

Thanks for your help, but QEMU still keeps whining. I'll figure it out sooner or later. Thanks again.

s-macke commented 9 years ago

Virtio is a complicated protocol. There might be another problem somewhere.