]> rtime.felk.cvut.cz Git - jailhouse.git/blob - inmates/demos/x86/e1000-demo.c
inmates: pci: allow pci_find_device to discover multiple devices
[jailhouse.git] / inmates / demos / x86 / e1000-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 e1000,addr=19,netdev=..." to the QEMU command line for
14  * testing in the virtual machine. Adjust configs/e1000-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 E1000_REG_CTRL          0x0000
27 # define E1000_CTRL_LRST        (1 << 3)
28 # define E1000_CTRL_ASDE        (1 << 5)
29 # define E1000_CTRL_SLU         (1 << 6)
30 # define E1000_CTRL_FRCSPD      (1 << 12)
31 # define E1000_CTRL_RST         (1 << 26)
32 #define E1000_REG_STATUS        0x0008
33 # define E1000_STATUS_LU        (1 << 1)
34 #define E1000_REG_EERD          0x0014
35 # define E1000_EERD_START       (1 << 0)
36 # define E1000_EERD_DONE        (1 << 4)
37 # define E1000_EERD_ADDR_SHIFT  8
38 # define E1000_EERD_DATA_SHIFT  16
39 #define E1000_REG_RCTL          0x0100
40 # define E1000_RCTL_EN          (1 << 1)
41 # define E1000_RCTL_BAM         (1 << 15)
42 # define E1000_RCTL_BSIZE_2048  (0 << 16)
43 # define E1000_RCTL_SECRC       (1 << 26)
44 #define E1000_REG_TCTL          0x0400
45 # define E1000_TCTL_EN          (1 << 1)
46 # define E1000_TCTL_PSP         (1 << 3)
47 # define E1000_TCTL_CT_DEF      (0xf << 4)
48 # define E1000_TCTL_COLD_DEF    (0x40 << 12)
49 #define E1000_REG_TIPG          0x0410
50 # define E1000_TIPG_IPGT_DEF    (10 << 0)
51 # define E1000_TIPG_IPGR1_DEF   (10 << 10)
52 # define E1000_TIPG_IPGR2_DEF   (10 << 20)
53 #define E1000_REG_RDBAL         0x2800
54 #define E1000_REG_RDBAH         0x2804
55 #define E1000_REG_RDLEN         0x2808
56 #define E1000_REG_RDH           0x2810
57 #define E1000_REG_RDT           0x2818
58 #define E1000_REG_TDBAL         0x3800
59 #define E1000_REG_TDBAH         0x3804
60 #define E1000_REG_TDLEN         0x3808
61 #define E1000_REG_TDH           0x3810
62 #define E1000_REG_TDT           0x3818
63 #define E1000_REG_RAL           0x5400
64 #define E1000_REG_RAH           0x5404
65 # define E1000_RAH_AV           (1 << 31)
66
67 struct eth_header {
68         u8      dst[6];
69         u8      src[6];
70         u16     type;
71         u8      data[];
72 } __attribute__((packed));
73
74 #define FRAME_TYPE_ANNOUNCE     0x004a
75 #define FRAME_TYPE_TARGET_ROLE  0x014a
76 #define FRAME_TYPE_PING         0x024a
77 #define FRAME_TYPE_PONG         0x034a
78
79 struct e1000_rxd {
80         u64     addr;
81         u16     len;
82         u16     crc;
83         u8      dd:1,
84                 eop:1,
85                 ixsm:1,
86                 vp:1,
87                 udpcs:1,
88                 tcpcs:1,
89                 ipcs:1,
90                 pif:1;
91         u8      errors;
92         u16     vlan_tag;
93 } __attribute__((packed));
94
95 struct e1000_txd {
96         u64     addr;
97         u16     len;
98         u8      cso;
99         u8      eop:1,
100                 ifcs:1,
101                 ic:1,
102                 rs:1,
103                 rps:1,
104                 dext:1,
105                 vle:1,
106                 ide:1;
107         u8      dd:1,
108                 ec:1,
109                 lc:1,
110                 tu:1,
111                 rsv:4;
112         u8      css;
113         u16     special;
114 } __attribute__((packed));
115
116 #define RX_DESCRIPTORS          8
117 #define RX_BUFFER_SIZE          2048
118 #define TX_DESCRIPTORS          8
119
120 static void *mmiobar;
121 static u8 buffer[RX_DESCRIPTORS * RX_BUFFER_SIZE];
122 static struct e1000_rxd rx_ring[RX_DESCRIPTORS];
123 static struct e1000_txd tx_ring[TX_DESCRIPTORS];
124 static unsigned int rx_idx, tx_idx;
125 static struct eth_header tx_packet;
126
127 static void send_packet(void *buffer, unsigned int size)
128 {
129         unsigned int idx = tx_idx;
130
131         memset(&tx_ring[idx], 0, sizeof(struct e1000_txd));
132         tx_ring[idx].addr = (unsigned long)buffer;
133         tx_ring[idx].len = size;
134         tx_ring[idx].rs = 1;
135         tx_ring[idx].ifcs = 1;
136         tx_ring[idx].eop = 1;
137
138         tx_idx = (tx_idx + 1) % TX_DESCRIPTORS;
139         mmio_write32(mmiobar + E1000_REG_TDT, tx_idx);
140
141         while (!tx_ring[idx].dd)
142                 cpu_relax();
143 }
144
145 static struct eth_header *packet_received(void)
146 {
147         if (rx_ring[rx_idx].dd)
148                 return (struct eth_header *)rx_ring[rx_idx].addr;
149
150         cpu_relax();
151         return NULL;
152 }
153
154 static void packet_reception_done(void)
155 {
156         unsigned int idx = rx_idx;
157
158         rx_ring[idx].dd = 0;
159         rx_idx = (rx_idx + 1) % RX_DESCRIPTORS;
160         mmio_write32(mmiobar + E1000_REG_RDT, idx);
161 }
162
163 void inmate_main(void)
164 {
165         enum { ROLE_UNDEFINED, ROLE_CONTROLLER, ROLE_TARGET } role;
166         unsigned long min = -1, max = 0, rtt;
167         struct eth_header *rx_packet;
168         unsigned long long start;
169         bool first_round = true;
170         unsigned int n;
171         u32 eerd, val;
172         u8 mac[6];
173         u64 bar;
174         int bdf;
175
176         printk_uart_base = UART_BASE;
177
178         bdf = pci_find_device(PCI_ID_ANY, PCI_ID_ANY, 0);
179         if (bdf < 0) {
180                 printk("No device found!\n");
181                 return;
182         }
183         printk("Found %04x:%04x at %02x:%02x.%x\n",
184                pci_read_config(bdf, PCI_CFG_VENDOR_ID, 2),
185                pci_read_config(bdf, PCI_CFG_DEVICE_ID, 2),
186                bdf >> 8, (bdf >> 3) & 0x1f, bdf & 0x3);
187
188         bar = pci_read_config(bdf, PCI_CFG_BAR, 4);
189         if ((bar & 0x6) == 0x4)
190                 bar |= (u64)pci_read_config(bdf, PCI_CFG_BAR + 4, 4) << 32;
191         mmiobar = (void *)(bar & ~0xfUL);
192         map_range(mmiobar, 128 * 1024, MAP_UNCACHED);
193         printk("MMIO register BAR at %p\n", mmiobar);
194
195         pci_write_config(bdf, PCI_CFG_COMMAND,
196                          PCI_CMD_MEM | PCI_CMD_MASTER, 2);
197
198         mmio_write32(mmiobar + E1000_REG_CTRL, E1000_CTRL_RST);
199         delay_us(20000);
200
201         val = mmio_read32(mmiobar + E1000_REG_CTRL);
202         val &= ~(E1000_CTRL_LRST | E1000_CTRL_FRCSPD);
203         val |= E1000_CTRL_ASDE | E1000_CTRL_SLU;
204         mmio_write32(mmiobar + E1000_REG_CTRL, val);
205         printk("Reset done, waiting for link...");
206
207         while (!(mmio_read32(mmiobar + E1000_REG_STATUS) & E1000_STATUS_LU))
208                 cpu_relax();
209         printk(" ok\n");
210
211         if (mmio_read32(mmiobar + E1000_REG_RAH) & E1000_RAH_AV) {
212                 *(u32 *)mac = mmio_read32(mmiobar + E1000_REG_RAL);
213                 *(u16 *)&mac[4] = mmio_read32(mmiobar + E1000_REG_RAH);
214         } else {
215                 for (n = 0; n < 3; n++) {
216                         mmio_write32(mmiobar + E1000_REG_EERD,
217                                      E1000_EERD_START |
218                                      (n << E1000_EERD_ADDR_SHIFT));
219                         do {
220                                 eerd = mmio_read32(mmiobar + E1000_REG_EERD);
221                                 cpu_relax();
222                         } while (!(eerd & E1000_EERD_DONE));
223                         mac[n * 2] = (u8)(eerd >> E1000_EERD_DATA_SHIFT);
224                         mac[n * 2 + 1] =
225                                 (u8)(eerd >> (E1000_EERD_DATA_SHIFT + 8));
226                 }
227         }
228
229         printk("MAC: %02x:%02x:%02x:%02x:%02x:%02x\n",
230                mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
231
232         mmio_write32(mmiobar + E1000_REG_RAL, *(u32 *)mac);
233         mmio_write32(mmiobar + E1000_REG_RAH, *(u16 *)&mac[4] | E1000_RAH_AV);
234
235         for (n = 0; n < RX_DESCRIPTORS; n++)
236                 rx_ring[n].addr = (unsigned long)&buffer[n * RX_BUFFER_SIZE];
237         mmio_write32(mmiobar + E1000_REG_RDBAL, (unsigned long)&rx_ring);
238         mmio_write32(mmiobar + E1000_REG_RDBAH, 0);
239         mmio_write32(mmiobar + E1000_REG_RDLEN, sizeof(rx_ring));
240         mmio_write32(mmiobar + E1000_REG_RDH, 0);
241         mmio_write32(mmiobar + E1000_REG_RDT, RX_DESCRIPTORS - 1);
242
243         val = mmio_read32(mmiobar + E1000_REG_RCTL);
244         val |= E1000_RCTL_EN | E1000_RCTL_BAM | E1000_RCTL_BSIZE_2048 |
245                 E1000_RCTL_SECRC;
246         mmio_write32(mmiobar + E1000_REG_RCTL, val);
247
248         mmio_write32(mmiobar + E1000_REG_TDBAL, (unsigned long)&tx_ring);
249         mmio_write32(mmiobar + E1000_REG_TDBAH, 0);
250         mmio_write32(mmiobar + E1000_REG_TDLEN, sizeof(tx_ring));
251         mmio_write32(mmiobar + E1000_REG_TDH, 0);
252         mmio_write32(mmiobar + E1000_REG_TDT, 0);
253
254         val = mmio_read32(mmiobar + E1000_REG_TCTL);
255         val |= E1000_TCTL_EN | E1000_TCTL_PSP | E1000_TCTL_CT_DEF |
256                 E1000_TCTL_COLD_DEF;
257         mmio_write32(mmiobar + E1000_REG_TCTL, val);
258         mmio_write32(mmiobar + E1000_REG_TIPG,
259                      E1000_TIPG_IPGT_DEF | E1000_TIPG_IPGR1_DEF |
260                      E1000_TIPG_IPGR2_DEF);
261
262         role = ROLE_UNDEFINED;
263
264         memcpy(tx_packet.src, mac, sizeof(tx_packet.src));
265         memset(tx_packet.dst, 0xff, sizeof(tx_packet.dst));
266         tx_packet.type = FRAME_TYPE_ANNOUNCE;
267         send_packet(&tx_packet, sizeof(tx_packet));
268
269         start = pm_timer_read();
270         while (pm_timer_read() - start < NS_PER_MSEC &&
271                role == ROLE_UNDEFINED) {
272                 rx_packet = packet_received();
273                 if (!rx_packet)
274                         continue;
275
276                 if (rx_packet->type == FRAME_TYPE_TARGET_ROLE) {
277                         role = ROLE_TARGET;
278                         memcpy(tx_packet.dst, rx_packet->src,
279                                sizeof(tx_packet.dst));
280                 }
281                 packet_reception_done();
282         }
283
284         if (role == ROLE_UNDEFINED) {
285                 role = ROLE_CONTROLLER;
286                 printk("Waiting for peer\n");
287                 while (1) {
288                         rx_packet = packet_received();
289                         if (!rx_packet)
290                                 continue;
291
292                         if (rx_packet->type == FRAME_TYPE_ANNOUNCE) {
293                                 memcpy(tx_packet.dst, rx_packet->src,
294                                        sizeof(tx_packet.dst));
295                                 packet_reception_done();
296
297                                 tx_packet.type = FRAME_TYPE_TARGET_ROLE;
298                                 send_packet(&tx_packet, sizeof(tx_packet));
299                                 break;
300                         } else {
301                                 packet_reception_done();
302                         }
303                 }
304         }
305
306         mmio_write32(mmiobar + E1000_REG_RCTL,
307                      mmio_read32(mmiobar + E1000_REG_RCTL) & ~E1000_RCTL_BAM);
308
309         if (role == ROLE_CONTROLLER) {
310                 printk("Running as controller\n");
311                 tx_packet.type = FRAME_TYPE_PING;
312                 while (1) {
313                         start = pm_timer_read();
314                         send_packet(&tx_packet, sizeof(tx_packet));
315
316                         do
317                                 rx_packet = packet_received();
318                         while (!rx_packet ||
319                                rx_packet->type != FRAME_TYPE_PONG);
320                         packet_reception_done();
321
322                         if (!first_round) {
323                                 rtt = pm_timer_read() - start;
324                                 if (rtt < min)
325                                         min = rtt;
326                                 if (rtt > max)
327                                         max = rtt;
328                                 printk("Received pong, RTT: %6ld ns, "
329                                        "min: %6ld ns, max: %6ld ns\n",
330                                        rtt, min, max);
331                         }
332                         first_round = false;
333                         delay_us(100000);
334                 }
335         } else {
336                 printk("Running as target\n");
337                 tx_packet.type = FRAME_TYPE_PONG;
338                 while (1) {
339                         rx_packet = packet_received();
340                         if (!rx_packet || rx_packet->type != FRAME_TYPE_PING)
341                                 continue;
342                         packet_reception_done();
343                         send_packet(&tx_packet, sizeof(tx_packet));
344                 }
345         }
346 }