Re: [Qemu-devel] [PATCH 1/1] pci-host: add educational driver

2014-12-03 Thread Jiri Slaby
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

2014-12-03 Thread Paolo Bonzini


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

2014-10-13 Thread Jiri Slaby
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

2014-10-13 Thread Paolo Bonzini
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

2014-10-13 Thread Paolo Bonzini
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

2014-10-10 Thread Jiri Slaby
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

2014-10-10 Thread Claudio Fontana
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,