[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Qemu-devel] virtio documentation or BSD licensed driver?
From: |
higepon |
Subject: |
Re: [Qemu-devel] virtio documentation or BSD licensed driver? |
Date: |
Sun, 10 May 2009 23:08:59 +0900 |
Hi.
With your kind advice,
finally I succeeded in writing to virtio-console on QEMU from my OS.
But there are a few things I don't understand about vring_avail struct.
On Rusty Russell's article "virtio: Towards a De-Facto Standard For
Virtual I/O Devices".
He explained like following.
struct vring_avail
{
__u16 flags;
__u16 idx;
__u16 ring[NUM];
};
> The available ring consists of a free-running index, an interrupt
> suppression flag, and an array of indices into the
> descriptor table (representing the heads of buffers).
(1) What does it mean "free-running index"?
And what value guest should set to idx? The index of head of
available descriptor?
(2) What value guest should set to ring[NUM].
I've Googled these things, but there are few documents about them.
Here is my whole code.
If I did something wrong, I appreciate your pointing me out.
int main(int argc, char* argv[])
{
// 1. Device probe
PciInf pciInf;
Pci pci;
pci.CheckPciExist(PCI_VENDOR_ID_REDHAT_QUMRANET,
PCI_DEVICE_ID_VIRTIO_CONSOLE, &pciInf);
if (!pciInf.isExist) {
printf("device not found\n");
exit(-1);
}
printf("device found\n");
printf("baseAdress=%x\n", pciInf.baseAdress);
printf("irqLine=%x\n", pciInf.irqLine);
const uintptr_t baseAddress = pciInf.baseAdress & ~1;
// 2. reset the device
outp8(baseAddress + VIRTIO_PCI_STATUS, 0); // 0: reset
printf("[virtio] isr=%x\n", inp8(baseAddress + VIRTIO_PCI_ISR));
// clear ISR.
// 3. IRQ receiver
monapi_set_irq(pciInf.irqLine, MONAPI_TRUE, MONAPI_TRUE);
syscall_set_irq_receiver(pciInf.irqLine, SYS_MASK_INTERRUPT);
// 4. Select the queue to use
outp16(baseAddress + VIRTIO_PCI_QUEUE_SEL, 1); // 0: read queue,
1: write queue
// 5. how many descriptors do the queue have?
const int numberOfDesc = inp16(baseAddress + VIRTIO_PCI_QUEUE_NUM);
printf("[virtio] numberOfDesc=%d\n", numberOfDesc);
ASSERT(numberOfDesc > 0);
// 6. Check wheter the queue is already set vring (necessary?).
uint16_t pfn = inp16(baseAddress + VIRTIO_PCI_QUEUE_PFN);
if (pfn != 0) {
printf("[virtio] pfn=%x\n", pfn);
exit(-1);
}
// 7. setup vring
const int MAX_QUEUE_SIZE = PAGE_MASK + vring_size(MAX_QUEUE_NUM);
printf("[virtio] MAX_QUEUE_SIZE=%d\n", MAX_QUEUE_SIZE);
uint8_t queueData[MAX_QUEUE_SIZE];
memset(queueData, 0, MAX_QUEUE_SIZE);
struct vring vring;
vring.num = numberOfDesc;
// page align is required
const uintptr_t physicalAddress =
syscall_get_physical_address((uintptr_t)queueData, NULL);
printf("[virtio] physicalAddress=%x\n", physicalAddress);
const uintptr_t alignedAddress = (physicalAddress + PAGE_MASK) & ~PAGE_MASK;
printf("[virtio] alignedAddress=%x\n", alignedAddress);
ASSERT((alignedAddress % PAGE_SIZE) == 0);
// vring.desc is page aligned
vring.desc = (struct vring_desc*)(queueData + alignedAddress -
physicalAddress);
// make linked ring
for (uintptr_t i = 0; i < vring.num; i++) {
vring.desc[i].next = i + 1;
}
vring.desc[vring.num - 1].next = 0;
// vring.avail is follow after the array of desc
vring.avail = (struct vring_avail *)&vring.desc[numberOfDesc];
// vring.used is also page aligned
const uintptr_t usedPhysicalAddress =
syscall_get_physical_address((uintptr_t)&(vring.avail->ring[numberOfDesc]),
NULL);
const uintptr_t usedAligendAddress = (usedPhysicalAddress +
PAGE_MASK) & ~PAGE_MASK;
ASSERT((usedAligendAddress % PAGE_SIZE) == 0);
vring.used = (struct
vring_used*)((uintptr_t)&(vring.avail->ring[numberOfDesc]) +
usedAligendAddress - usedPhysicalAddress);
// 9. set up pfn
printf("[virtio] set up PFN\n");
outp32(baseAddress + VIRTIO_PCI_QUEUE_PFN,
syscall_get_physical_address((uintptr_t)vring.desc, NULL) >> 12);
// 10. prepare the data to write
uint8_t data[PAGE_SIZE * 2];
const uintptr_t phys = syscall_get_physical_address((uintptr_t)data, NULL);
const uintptr_t aphys = (phys+ PAGE_MASK) & ~PAGE_MASK;
char* p = (char*) (data + aphys - phys);
strcpy(p, "Hello, World");
// 11. set the data to vring
vring.desc[0].flags = 0; // no next
vring.desc[0].addr = syscall_get_physical_address((uintptr_t)p, NULL);
vring.desc[0].len = strlen(p) + 1;
vring.avail->idx = 1; // ??????
// 12. Notify!
printf("[virtio] vring.used->idx = %d \n", vring.used->idx);
outp16(baseAddress + VIRTIO_PCI_QUEUE_NOTIFY, 1);
// 13. wait notification from host
MessageInfo msg;
Message::receive(&msg);
switch (msg.header)
{
case MSG_INTERRUPTED:
{
printf("[virtio] Interrupt comes\n");
// clear ISR.
const uint8_t isr = inp8(baseAddress + VIRTIO_PCI_ISR);
printf("[virtio] isr=%x\n", isr);
monapi_set_irq(pciInf.irqLine, MONAPI_TRUE, MONAPI_TRUE);
break;
}
default:
printf("[virtio] uknown message\n");
break;
}
// if data is written, idx 0 => 1
printf("[virtio] vring.used->idx = %d \n", vring.used->idx);
}
Cheers.
On Mon, May 4, 2009 at 7:36 PM, higepon <address@hidden> wrote:
> Hi.
>
> I really appreciate your help. Thanks.
> That's what I want to know about.
>
>> 2) Think of virtio-net as just another (sophisticated) PCI driver and
>> look at its implemenation
>> in qemu. Although qemu is not BSD licensed, your work is unlikely to
>> be considered a derivative
>> of qemu since you are implementing a driver for that virtual
>> "hardware", not another copy it.
>
> Maybe this is suitable for my OS.
>
>> The BSD virtio headers, the paper and the virtio-net qemu
>> implementation should be enough to
>> allow you to write a driver for your OS imho (it is already more info
>> than you typically get for
>> real hardware)
>
> Okay I will start from reading the paper.
>
>> P.S., in practice I believe several developers for other OSes look at
>> the sources of linux drivers
>> as sort of a really good documentation for hardware, even if the
>> license of their OS is incompatible.
>> IANAL and all that, but I 'd be really suprised if you got sued for
>> porting virtio-net to your hobby OS :)
>
> Interesting and resonable.
> But Since Mona OS is my life work, i want to avoid from license problems.
>
>
> Cheers.
>