]> rtime.felk.cvut.cz Git - jailhouse.git/blob - inmates/demos/x86/pci-demo.c
inmates: Add PCI demo using an Intel HDA
[jailhouse.git] / inmates / demos / x86 / pci-demo.c
1 /*
2  * Jailhouse, a Linux-based partitioning hypervisor
3  *
4  * Copyright (c) Siemens AG, 2014
5  *
6  * Authors:
7  *  Jan Kiszka <jan.kiszka@siemens.com>
8  *
9  * This work is licensed under the terms of the GNU GPL, version 2.  See
10  * the COPYING file in the top-level directory.
11  *
12  *
13  * Append "-device intel-hda,addr=1b.0 -device hda-output" to the QEMU command
14  * line for testing in the virtual machine. Adjust configs/pci-demo.c for real
15  * machines as needed.
16  */
17
18 #include <inmate.h>
19
20 #ifdef CONFIG_UART_OXPCIE952
21 #define UART_BASE               0xe000
22 #else
23 #define UART_BASE               0x2f8
24 #endif
25
26 #define IRQ_VECTOR              32
27
28 #define HDA_GCTL                0x08
29 #define HDA_WAKEEN              0x0c
30 #define HDA_STATESTS            0x0e
31 #define HDA_INTCTL              0x20
32
33 static void *hdbar;
34
35 static void irq_handler(void)
36 {
37         u16 statests = mmio_read16(hdbar + HDA_STATESTS);
38
39         printk("HDA MSI received (STATESTS: %04x)\n", statests);
40         mmio_write16(hdbar + HDA_STATESTS, statests);
41 }
42
43 void inmate_main(void)
44 {
45         u64 bar;
46         int bdf;
47
48         printk_uart_base = UART_BASE;
49
50         int_init();
51         int_set_handler(IRQ_VECTOR, irq_handler);
52
53         bdf = pci_find_device(PCI_ID_ANY, PCI_ID_ANY);
54         if (bdf < 0) {
55                 printk("No device found!\n");
56                 return;
57         }
58         printk("Found %04x:%04x at %02x:%02x.%x\n",
59                pci_read_config(bdf, PCI_CFG_VENDOR_ID, 2),
60                pci_read_config(bdf, PCI_CFG_DEVICE_ID, 2),
61                bdf >> 8, (bdf >> 3) & 0x1f, bdf & 0x3);
62
63         bar = pci_read_config(bdf, PCI_CFG_BAR, 4);
64         if ((bar & 0x6) == 0x4)
65                 bar |= (u64)pci_read_config(bdf, PCI_CFG_BAR + 4, 4) << 32;
66         hdbar = (void *)(bar & ~0xfUL);
67         map_range(hdbar, PAGE_SIZE, MAP_UNCACHED);
68         printk("HDBAR at %p\n", hdbar);
69
70         pci_msi_set_vector(bdf, IRQ_VECTOR);
71
72         pci_write_config(bdf, PCI_CFG_COMMAND,
73                          PCI_CMD_MEM | PCI_CMD_MASTER, 2);
74
75         asm volatile("sti");
76
77         mmio_write16(hdbar + HDA_GCTL, 0);
78         delay_us(7000);
79         mmio_write16(hdbar + HDA_GCTL, 1);
80
81         mmio_write16(hdbar + HDA_WAKEEN, 0x0f);
82         mmio_write32(hdbar + HDA_INTCTL, (1 << 31) | (1 << 30));
83
84         while (1)
85                 asm volatile("hlt");
86 }