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