]> rtime.felk.cvut.cz Git - jailhouse.git/blob - inmates/demos/x86/apic-demo.c
8df3bb5cc1d6b62d9291ffe80323df4768edfdf5
[jailhouse.git] / inmates / demos / x86 / apic-demo.c
1 /*
2  * Jailhouse, a Linux-based partitioning hypervisor
3  *
4  * Copyright (c) Siemens AG, 2013
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 #include <inmate.h>
14
15 #ifdef CONFIG_UART_OXPCIE952
16 #define UART_BASE               0xe010
17 #else
18 #define UART_BASE               0x3f8
19 #endif
20 #define UART_LSR                0x5
21 #define UART_LSR_THRE           0x20
22 #define UART_IDLE_LOOPS         100
23
24 #define APIC_TIMER_VECTOR       32
25
26 static unsigned long expected_time;
27 static unsigned long min = -1, max;
28
29 static void irq_handler(void)
30 {
31         unsigned long delta;
32
33         delta = tsc_read() - expected_time;
34         if (delta < min)
35                 min = delta;
36         if (delta > max)
37                 max = delta;
38         printk("Timer fired, jitter: %6ld ns, min: %6ld ns, max: %6ld ns\n",
39                delta, min, max);
40
41         expected_time += 100 * NS_PER_MSEC;
42         apic_timer_set(expected_time - tsc_read());
43 }
44
45 static void init_apic(void)
46 {
47         unsigned long apic_freq_khz;
48
49         int_init();
50         int_set_handler(APIC_TIMER_VECTOR, irq_handler);
51
52         apic_freq_khz = apic_timer_init(APIC_TIMER_VECTOR);
53         printk("Calibrated APIC frequency: %lu kHz\n", apic_freq_khz);
54
55         expected_time = tsc_read() + NS_PER_MSEC;
56         apic_timer_set(NS_PER_MSEC);
57
58         asm volatile("sti");
59 }
60
61 void inmate_main(void)
62 {
63         bool allow_terminate = false;
64         bool terminate = false;
65         unsigned long tsc_freq;
66         unsigned int n;
67
68         printk_uart_base = UART_BASE;
69         do {
70                 for (n = 0; n < UART_IDLE_LOOPS; n++)
71                         if (!(inb(UART_BASE + UART_LSR) & UART_LSR_THRE))
72                                 break;
73         } while (n < UART_IDLE_LOOPS);
74
75         comm_region->cell_state = JAILHOUSE_CELL_RUNNING_LOCKED;
76
77         tsc_freq = tsc_init();
78         printk("Calibrated TSC frequency: %lu.%03u kHz\n", tsc_freq / 1000,
79                tsc_freq % 1000);
80
81         init_apic();
82
83         while (!terminate) {
84                 asm volatile("hlt");
85
86                 switch (comm_region->msg_to_cell) {
87                 case JAILHOUSE_MSG_SHUTDOWN_REQUEST:
88                         if (!allow_terminate) {
89                                 printk("Rejecting first shutdown request - "
90                                        "try again!\n");
91                                 jailhouse_send_reply_from_cell(comm_region,
92                                                 JAILHOUSE_MSG_REQUEST_DENIED);
93                                 allow_terminate = true;
94                         } else
95                                 terminate = true;
96                         break;
97                 default:
98                         jailhouse_send_reply_from_cell(comm_region,
99                                         JAILHOUSE_MSG_UNKNOWN);
100                         break;
101                 }
102         }
103
104         printk("Stopped APIC demo\n");
105         comm_region->cell_state = JAILHOUSE_CELL_SHUT_DOWN;
106 }