Re: [Qemu-devel] [PATCH 1/1] pci-host: add educational driver
On 10/13/2014, 03:00 PM, Paolo Bonzini wrote: +static void edu_dma_timer(void *opaque) +{ +EduState *edu = opaque; +bool raise_irq = false; + +qemu_mutex_lock(edu-dma_mutex); dma_mutex and mutex and irq_mutex are not necessary. All I/O happens under the big QEMU lock (qemu_lock/unlock_iothread). I can certainly imagine that edu.c would be one of the first devices we make thread-safe, but... not yet. :) Hi, I finally got to it. I want to make sure that I understand this correctly. So even timers are protected by the BQL? thanks, -- js suse labs
Re: [Qemu-devel] [PATCH 1/1] pci-host: add educational driver
On 03/12/2014 16:11, Jiri Slaby wrote: On 10/13/2014, 03:00 PM, Paolo Bonzini wrote: +static void edu_dma_timer(void *opaque) +{ + EduState *edu = opaque; + bool raise_irq = false; + + qemu_mutex_lock(edu-dma_mutex); dma_mutex and mutex and irq_mutex are not necessary. All I/O happens under the big QEMU lock (qemu_lock/unlock_iothread). I can certainly imagine that edu.c would be one of the first devices we make thread-safe, but... not yet. :) Hi, I finally got to it. I want to make sure that I understand this correctly. So even timers are protected by the BQL? Everything, unless you create a separate thread. Paolo
Re: [Qemu-devel] [PATCH 1/1] pci-host: add educational driver
On 10/10/2014, 04:54 PM, Claudio Fontana wrote: Hello, On 10.10.2014 14:09, Jiri Slaby wrote: I am using qemu for teaching the Linux kernel at our university. I wrote a simple PCI device that can answer to writes/reads, generate interrupts and perform DMA. As I am dragging it locally over 2 years, I am sending it to you now. Signed-off-by: Jiri Slaby jsl...@suse.cz is this supposed to be architecture independent, or is it X86-specific? Hi, I did not plan it to be only x86 specific. If you see any problems, I will fix them. Also at first glance I see multiple 32bit variables used to hold addresses, is this 32bit-only? No, the DMA addresses are on purpose 32-bit: to teach the people always set the dma mask properly in the driver. This driver copies COMBO6x devices (liberouter.org) behaviour which I used until the cards got obsoleted (hard to find PCI-X slots nowadays). I can make this configurable if you wish. I wonder if this work could be merged / integrated with the Generic PCI host patches that are flying around since some time... Could you point me to some? thanks, -- js suse labs
Re: [Qemu-devel] [PATCH 1/1] pci-host: add educational driver
Il 10/10/2014 14:09, Jiri Slaby ha scritto: I am using qemu for teaching the Linux kernel at our university. I wrote a simple PCI device that can answer to writes/reads, generate interrupts and perform DMA. As I am dragging it locally over 2 years, I am sending it to you now. Signed-off-by: Jiri Slaby jsl...@suse.cz --- MAINTAINERS | 5 + hw/pci-host/Makefile.objs | 1 + hw/pci-host/edu.c | 336 ++ hw/pci-host is for PCI host bridges. You can put it in hw/misc. 3 files changed, 342 insertions(+) create mode 100644 hw/pci-host/edu.c diff --git a/MAINTAINERS b/MAINTAINERS index 206bf7ea4582..7f4e8591b74b 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -567,6 +567,11 @@ F: hw/xtensa/xtensa_lx60.c Devices --- +EDU +M: Jiri Slaby jsl...@suse.cz +S: Maintained +F: hw/pci-host/edu.c + IDE M: Kevin Wolf kw...@redhat.com M: Stefan Hajnoczi stefa...@redhat.com diff --git a/hw/pci-host/Makefile.objs b/hw/pci-host/Makefile.objs index bb65f9c4d2d0..b01f614ed248 100644 --- a/hw/pci-host/Makefile.objs +++ b/hw/pci-host/Makefile.objs @@ -13,5 +13,6 @@ common-obj-$(CONFIG_VERSATILE_PCI) += versatile.o common-obj-$(CONFIG_PCI_APB) += apb.o common-obj-$(CONFIG_FULONG) += bonito.o +common-obj-$(CONFIG_PCI) += edu.o Please add CONFIG_EDU=y to default-configs/pci.mak, and use CONFIG_EDU here. common-obj-$(CONFIG_PCI_PIIX) += piix.o common-obj-$(CONFIG_PCI_Q35) += q35.o diff --git a/hw/pci-host/edu.c b/hw/pci-host/edu.c new file mode 100644 index ..72e09dff6f5d --- /dev/null +++ b/hw/pci-host/edu.c @@ -0,0 +1,336 @@ +/* + * QEMU education PCI device + * + * Copyright (c) 2012 Jiri Slaby + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the Software), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include hw/pci/pci.h +#include qemu/timer.h + +#define DMA_START0x4 +#define DMA_SIZE 4096 +#define DMA_IRQ 0x0100 + +typedef struct { +PCIDevice pdev; +MemoryRegion mmio; + +QemuThread thread; +QemuMutex thr_mutex; +QemuCond thr_cond; +bool stopping; + +uint32_t addr4; +uint32_t fact; +#define EDU_STATUS_COMPUTING 0x1 +uint32_t status; + +uint32_t irq_status; +QemuMutex irq_mutex; + +#define EDU_DMA_RUN 0x1 +#define EDU_DMA_DIR(cmd) (((cmd) 0x2) 1) +# define EDU_DMA_FROM_PCI0 +# define EDU_DMA_TO_PCI 1 +#define EDU_DMA_IRQ 0x4 +struct dma_state { + uint32_t src; + uint32_t dst; + uint32_t cnt; + uint32_t cmd; +} dma; +QEMUTimer *dma_timer; +QemuMutex dma_mutex; +char dma_buf[DMA_SIZE]; +} EduState; + +static bool within(uint32_t addr, uint32_t start, uint32_t end) +{ + return start = addr addr end; +} + +static void check_range(uint32_t addr, uint32_t size1, uint32_t start, + uint32_t size2) +{ + uint32_t end1 = addr + size1; + uint32_t end2 = start + size2; + + if (within(addr, start, end2) + end1 addr within(end1, start, end2)) + return; + + hw_error(EDU: DMA range 0x%.8x-0x%.8x out of bounds (0x%.8x-0x%.8x)!, + addr, end1 - 1, start, end2 - 1); +} + +static void edu_dma_timer(void *opaque) +{ + EduState *edu = opaque; + bool raise_irq = false; + + qemu_mutex_lock(edu-dma_mutex); dma_mutex and mutex and irq_mutex are not necessary. All I/O happens under the big QEMU lock (qemu_lock/unlock_iothread). I can certainly imagine that edu.c would be one of the first devices we make thread-safe, but... not yet. :) + if (!(edu-dma.cmd EDU_DMA_RUN)) + goto end; + + if (EDU_DMA_DIR(edu-dma.cmd) == EDU_DMA_FROM_PCI) { + uint32_t dst = edu-dma.dst; + check_range(dst, edu-dma.cnt, DMA_START, DMA_SIZE); + dst -=
Re: [Qemu-devel] [PATCH 1/1] pci-host: add educational driver
Il 13/10/2014 10:32, Jiri Slaby ha scritto: No, the DMA addresses are on purpose 32-bit: to teach the people always set the dma mask properly in the driver. This driver copies COMBO6x devices (liberouter.org) behaviour which I used until the cards got obsoleted (hard to find PCI-X slots nowadays). I can make this configurable if you wish. Yeah, that would help (to avoid setting a bad example). You could have extra commands to switch between 32- and 64-bit DMA masks. Paolo
[Qemu-devel] [PATCH 1/1] pci-host: add educational driver
I am using qemu for teaching the Linux kernel at our university. I wrote a simple PCI device that can answer to writes/reads, generate interrupts and perform DMA. As I am dragging it locally over 2 years, I am sending it to you now. Signed-off-by: Jiri Slaby jsl...@suse.cz --- MAINTAINERS | 5 + hw/pci-host/Makefile.objs | 1 + hw/pci-host/edu.c | 336 ++ 3 files changed, 342 insertions(+) create mode 100644 hw/pci-host/edu.c diff --git a/MAINTAINERS b/MAINTAINERS index 206bf7ea4582..7f4e8591b74b 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -567,6 +567,11 @@ F: hw/xtensa/xtensa_lx60.c Devices --- +EDU +M: Jiri Slaby jsl...@suse.cz +S: Maintained +F: hw/pci-host/edu.c + IDE M: Kevin Wolf kw...@redhat.com M: Stefan Hajnoczi stefa...@redhat.com diff --git a/hw/pci-host/Makefile.objs b/hw/pci-host/Makefile.objs index bb65f9c4d2d0..b01f614ed248 100644 --- a/hw/pci-host/Makefile.objs +++ b/hw/pci-host/Makefile.objs @@ -13,5 +13,6 @@ common-obj-$(CONFIG_VERSATILE_PCI) += versatile.o common-obj-$(CONFIG_PCI_APB) += apb.o common-obj-$(CONFIG_FULONG) += bonito.o +common-obj-$(CONFIG_PCI) += edu.o common-obj-$(CONFIG_PCI_PIIX) += piix.o common-obj-$(CONFIG_PCI_Q35) += q35.o diff --git a/hw/pci-host/edu.c b/hw/pci-host/edu.c new file mode 100644 index ..72e09dff6f5d --- /dev/null +++ b/hw/pci-host/edu.c @@ -0,0 +1,336 @@ +/* + * QEMU education PCI device + * + * Copyright (c) 2012 Jiri Slaby + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the Software), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include hw/pci/pci.h +#include qemu/timer.h + +#define DMA_START 0x4 +#define DMA_SIZE 4096 +#define DMA_IRQ0x0100 + +typedef struct { +PCIDevice pdev; +MemoryRegion mmio; + +QemuThread thread; +QemuMutex thr_mutex; +QemuCond thr_cond; +bool stopping; + +uint32_t addr4; +uint32_t fact; +#define EDU_STATUS_COMPUTING 0x1 +uint32_t status; + +uint32_t irq_status; +QemuMutex irq_mutex; + +#define EDU_DMA_RUN0x1 +#define EDU_DMA_DIR(cmd) (((cmd) 0x2) 1) +# define EDU_DMA_FROM_PCI 0 +# define EDU_DMA_TO_PCI1 +#define EDU_DMA_IRQ0x4 +struct dma_state { + uint32_t src; + uint32_t dst; + uint32_t cnt; + uint32_t cmd; +} dma; +QEMUTimer *dma_timer; +QemuMutex dma_mutex; +char dma_buf[DMA_SIZE]; +} EduState; + +static bool within(uint32_t addr, uint32_t start, uint32_t end) +{ + return start = addr addr end; +} + +static void check_range(uint32_t addr, uint32_t size1, uint32_t start, + uint32_t size2) +{ + uint32_t end1 = addr + size1; + uint32_t end2 = start + size2; + + if (within(addr, start, end2) + end1 addr within(end1, start, end2)) + return; + + hw_error(EDU: DMA range 0x%.8x-0x%.8x out of bounds (0x%.8x-0x%.8x)!, + addr, end1 - 1, start, end2 - 1); +} + +static void edu_dma_timer(void *opaque) +{ + EduState *edu = opaque; + bool raise_irq = false; + + qemu_mutex_lock(edu-dma_mutex); + if (!(edu-dma.cmd EDU_DMA_RUN)) + goto end; + + if (EDU_DMA_DIR(edu-dma.cmd) == EDU_DMA_FROM_PCI) { + uint32_t dst = edu-dma.dst; + check_range(dst, edu-dma.cnt, DMA_START, DMA_SIZE); + dst -= DMA_START; + pci_dma_read(edu-pdev, edu-dma.src, edu-dma_buf + dst, + edu-dma.cnt); + } else { + uint32_t src = edu-dma.src; + check_range(src, edu-dma.cnt, DMA_START, DMA_SIZE); + src -= DMA_START; + pci_dma_write(edu-pdev, edu-dma.dst, edu-dma_buf + src, + edu-dma.cnt); + } + + edu-dma.cmd = ~EDU_DMA_RUN; + if (edu-dma.cmd EDU_DMA_IRQ) +
Re: [Qemu-devel] [PATCH 1/1] pci-host: add educational driver
Hello, On 10.10.2014 14:09, Jiri Slaby wrote: I am using qemu for teaching the Linux kernel at our university. I wrote a simple PCI device that can answer to writes/reads, generate interrupts and perform DMA. As I am dragging it locally over 2 years, I am sending it to you now. Signed-off-by: Jiri Slaby jsl...@suse.cz is this supposed to be architecture independent, or is it X86-specific? Also at first glance I see multiple 32bit variables used to hold addresses, is this 32bit-only? I wonder if this work could be merged / integrated with the Generic PCI host patches that are flying around since some time... Thanks, Claudio --- MAINTAINERS | 5 + hw/pci-host/Makefile.objs | 1 + hw/pci-host/edu.c | 336 ++ 3 files changed, 342 insertions(+) create mode 100644 hw/pci-host/edu.c diff --git a/MAINTAINERS b/MAINTAINERS index 206bf7ea4582..7f4e8591b74b 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -567,6 +567,11 @@ F: hw/xtensa/xtensa_lx60.c Devices --- +EDU +M: Jiri Slaby jsl...@suse.cz +S: Maintained +F: hw/pci-host/edu.c + IDE M: Kevin Wolf kw...@redhat.com M: Stefan Hajnoczi stefa...@redhat.com diff --git a/hw/pci-host/Makefile.objs b/hw/pci-host/Makefile.objs index bb65f9c4d2d0..b01f614ed248 100644 --- a/hw/pci-host/Makefile.objs +++ b/hw/pci-host/Makefile.objs @@ -13,5 +13,6 @@ common-obj-$(CONFIG_VERSATILE_PCI) += versatile.o common-obj-$(CONFIG_PCI_APB) += apb.o common-obj-$(CONFIG_FULONG) += bonito.o +common-obj-$(CONFIG_PCI) += edu.o common-obj-$(CONFIG_PCI_PIIX) += piix.o common-obj-$(CONFIG_PCI_Q35) += q35.o diff --git a/hw/pci-host/edu.c b/hw/pci-host/edu.c new file mode 100644 index ..72e09dff6f5d --- /dev/null +++ b/hw/pci-host/edu.c @@ -0,0 +1,336 @@ +/* + * QEMU education PCI device + * + * Copyright (c) 2012 Jiri Slaby + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the Software), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include hw/pci/pci.h +#include qemu/timer.h + +#define DMA_START0x4 +#define DMA_SIZE 4096 +#define DMA_IRQ 0x0100 + +typedef struct { +PCIDevice pdev; +MemoryRegion mmio; + +QemuThread thread; +QemuMutex thr_mutex; +QemuCond thr_cond; +bool stopping; + +uint32_t addr4; +uint32_t fact; +#define EDU_STATUS_COMPUTING 0x1 +uint32_t status; + +uint32_t irq_status; +QemuMutex irq_mutex; + +#define EDU_DMA_RUN 0x1 +#define EDU_DMA_DIR(cmd) (((cmd) 0x2) 1) +# define EDU_DMA_FROM_PCI0 +# define EDU_DMA_TO_PCI 1 +#define EDU_DMA_IRQ 0x4 +struct dma_state { + uint32_t src; + uint32_t dst; + uint32_t cnt; + uint32_t cmd; +} dma; +QEMUTimer *dma_timer; +QemuMutex dma_mutex; +char dma_buf[DMA_SIZE]; +} EduState; + +static bool within(uint32_t addr, uint32_t start, uint32_t end) +{ + return start = addr addr end; +} + +static void check_range(uint32_t addr, uint32_t size1, uint32_t start, + uint32_t size2) +{ + uint32_t end1 = addr + size1; + uint32_t end2 = start + size2; + + if (within(addr, start, end2) + end1 addr within(end1, start, end2)) + return; + + hw_error(EDU: DMA range 0x%.8x-0x%.8x out of bounds (0x%.8x-0x%.8x)!, + addr, end1 - 1, start, end2 - 1); +} + +static void edu_dma_timer(void *opaque) +{ + EduState *edu = opaque; + bool raise_irq = false; + + qemu_mutex_lock(edu-dma_mutex); + if (!(edu-dma.cmd EDU_DMA_RUN)) + goto end; + + if (EDU_DMA_DIR(edu-dma.cmd) == EDU_DMA_FROM_PCI) { + uint32_t dst = edu-dma.dst; + check_range(dst, edu-dma.cnt, DMA_START, DMA_SIZE); + dst -= DMA_START; + pci_dma_read(edu-pdev,