]> rtime.felk.cvut.cz Git - jailhouse.git/commitdiff
inmates: Add PCI demo using an Intel HDA
authorJan Kiszka <jan.kiszka@siemens.com>
Fri, 18 Jul 2014 08:21:40 +0000 (10:21 +0200)
committerJan Kiszka <jan.kiszka@siemens.com>
Tue, 22 Jul 2014 13:49:33 +0000 (15:49 +0200)
This demonstrates the setup of a PCI device including MSI.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
configs/pci-demo.c [new file with mode: 0644]
inmates/demos/x86/Makefile
inmates/demos/x86/pci-demo.c [new file with mode: 0644]

diff --git a/configs/pci-demo.c b/configs/pci-demo.c
new file mode 100644 (file)
index 0000000..b0ca65f
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+ * Jailhouse, a Linux-based partitioning hypervisor
+ *
+ * Minimal configuration for PCI demo inmate:
+ * 1 CPU, 1 MB RAM, 1 serial port, 1 Intel HDA PCI device
+ *
+ * Copyright (c) Siemens AG, 2014
+ *
+ * Authors:
+ *  Jan Kiszka <jan.kiszka@siemens.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.  See
+ * the COPYING file in the top-level directory.
+ */
+
+#include <linux/types.h>
+#include <jailhouse/cell-config.h>
+
+#define ARRAY_SIZE(a) sizeof(a) / sizeof(a[0])
+
+struct {
+       struct jailhouse_cell_desc cell;
+       __u64 cpus[1];
+       struct jailhouse_memory mem_regions[3];
+       __u8 pio_bitmap[0x2000];
+       struct jailhouse_pci_device pci_devices[1];
+} __attribute__((packed)) config = {
+       .cell = {
+               .name = "pci-demo",
+               .flags = JAILHOUSE_CELL_PASSIVE_COMMREG,
+
+               .cpu_set_size = sizeof(config.cpus),
+               .num_memory_regions = ARRAY_SIZE(config.mem_regions),
+               .num_irqchips = 0,
+               .pio_bitmap_size = ARRAY_SIZE(config.pio_bitmap),
+               .num_pci_devices = ARRAY_SIZE(config.pci_devices),
+       },
+
+       .cpus = {
+               0x4,
+       },
+
+       .mem_regions = {
+               /* RAM */ {
+                       .phys_start = 0x3be00000,
+                       .virt_start = 0,
+                       .size = 0x00100000,
+                       .flags = JAILHOUSE_MEM_READ | JAILHOUSE_MEM_WRITE |
+                               JAILHOUSE_MEM_EXECUTE | JAILHOUSE_MEM_LOADABLE,
+               },
+               /* communication region */ {
+                       .virt_start = 0x00100000,
+                       .size = 0x00001000,
+                       .flags = JAILHOUSE_MEM_READ | JAILHOUSE_MEM_WRITE |
+                               JAILHOUSE_MEM_COMM_REGION,
+               },
+               /* HDA BAR0 */ {
+                       .phys_start = 0xfebf0000,
+                       .virt_start = 0xfebf0000,
+                       .size = 0x00004000,
+                       .flags = JAILHOUSE_MEM_READ | JAILHOUSE_MEM_WRITE,
+               },
+       },
+
+       .pio_bitmap = {
+               [     0/8 ...  0x2f7/8] = -1,
+               [ 0x2f8/8 ...  0x2ff/8] = 0, /* serial2 */
+               [ 0x300/8 ... 0xdfff/8] = -1,
+               [0xe000/8 ... 0xe007/8] = 0, /* OXPCIe952 serial2 */
+               [0xe008/8 ... 0xffff/8] = -1,
+       },
+
+       .pci_devices = {
+               { /* Intel HDA @00:1b.0 */
+                       .type = JAILHOUSE_PCI_TYPE_DEVICE,
+                       .domain = 0x0000,
+                       .bus = 0x00,
+                       .devfn = 0xd8,
+               },
+       },
+};
index 7794b878b670943fb6d3d20708c484750353419b..4e82d75edeabda2b8b652406266c9bf2d4584068 100644 (file)
@@ -14,7 +14,8 @@ include $(INMATES_LIB)/Makefile.lib
 
 LIBDIR := ../../lib/x86
 
-INMATES := tiny-demo.bin apic-demo.bin ioapic-demo.bin 32-bit-demo.bin
+INMATES := tiny-demo.bin apic-demo.bin ioapic-demo.bin 32-bit-demo.bin \
+       pci-demo.bin
 
 tiny-demo-y := tiny-demo.o \
        $(LIBDIR)/header.o $(LIBDIR)/printk.o $(LIBDIR)/timing.o
@@ -31,4 +32,8 @@ $(eval $(call DECLARE_32_BIT,32-bit-demo))
 32-bit-demo-y := 32-bit-demo.o \
        $(LIBDIR)/header-32.o $(LIBDIR)/printk-32.o
 
+pci-demo-y := pci-demo.o \
+       $(LIBDIR)/header.o $(LIBDIR)/printk.o $(LIBDIR)/mem.o \
+       $(LIBDIR)/int.o $(LIBDIR)/pci.o $(LIBDIR)/timing.o
+
 $(eval $(call DECLARE_TARGETS,$(INMATES)))
diff --git a/inmates/demos/x86/pci-demo.c b/inmates/demos/x86/pci-demo.c
new file mode 100644 (file)
index 0000000..195f154
--- /dev/null
@@ -0,0 +1,86 @@
+/*
+ * Jailhouse, a Linux-based partitioning hypervisor
+ *
+ * Copyright (c) Siemens AG, 2014
+ *
+ * Authors:
+ *  Jan Kiszka <jan.kiszka@siemens.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.  See
+ * the COPYING file in the top-level directory.
+ *
+ *
+ * Append "-device intel-hda,addr=1b.0 -device hda-output" to the QEMU command
+ * line for testing in the virtual machine. Adjust configs/pci-demo.c for real
+ * machines as needed.
+ */
+
+#include <inmate.h>
+
+#ifdef CONFIG_UART_OXPCIE952
+#define UART_BASE              0xe000
+#else
+#define UART_BASE              0x2f8
+#endif
+
+#define IRQ_VECTOR             32
+
+#define HDA_GCTL               0x08
+#define HDA_WAKEEN             0x0c
+#define HDA_STATESTS           0x0e
+#define HDA_INTCTL             0x20
+
+static void *hdbar;
+
+static void irq_handler(void)
+{
+       u16 statests = mmio_read16(hdbar + HDA_STATESTS);
+
+       printk("HDA MSI received (STATESTS: %04x)\n", statests);
+       mmio_write16(hdbar + HDA_STATESTS, statests);
+}
+
+void inmate_main(void)
+{
+       u64 bar;
+       int bdf;
+
+       printk_uart_base = UART_BASE;
+
+       int_init();
+       int_set_handler(IRQ_VECTOR, irq_handler);
+
+       bdf = pci_find_device(PCI_ID_ANY, PCI_ID_ANY);
+       if (bdf < 0) {
+               printk("No device found!\n");
+               return;
+       }
+       printk("Found %04x:%04x at %02x:%02x.%x\n",
+              pci_read_config(bdf, PCI_CFG_VENDOR_ID, 2),
+              pci_read_config(bdf, PCI_CFG_DEVICE_ID, 2),
+              bdf >> 8, (bdf >> 3) & 0x1f, bdf & 0x3);
+
+       bar = pci_read_config(bdf, PCI_CFG_BAR, 4);
+       if ((bar & 0x6) == 0x4)
+               bar |= (u64)pci_read_config(bdf, PCI_CFG_BAR + 4, 4) << 32;
+       hdbar = (void *)(bar & ~0xfUL);
+       map_range(hdbar, PAGE_SIZE, MAP_UNCACHED);
+       printk("HDBAR at %p\n", hdbar);
+
+       pci_msi_set_vector(bdf, IRQ_VECTOR);
+
+       pci_write_config(bdf, PCI_CFG_COMMAND,
+                        PCI_CMD_MEM | PCI_CMD_MASTER, 2);
+
+       asm volatile("sti");
+
+       mmio_write16(hdbar + HDA_GCTL, 0);
+       delay_us(7000);
+       mmio_write16(hdbar + HDA_GCTL, 1);
+
+       mmio_write16(hdbar + HDA_WAKEEN, 0x0f);
+       mmio_write32(hdbar + HDA_INTCTL, (1 << 31) | (1 << 30));
+
+       while (1)
+               asm volatile("hlt");
+}