]> rtime.felk.cvut.cz Git - jailhouse.git/blob - inmates/demos/x86/apic-demo.c
inmates: x86: Add optional cache pollution to apic-demo
[jailhouse.git] / inmates / demos / x86 / apic-demo.c
1 /*
2  * Jailhouse, a Linux-based partitioning hypervisor
3  *
4  * Copyright (c) Siemens AG, 2013-2016
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 #define CMDLINE_BUFFER_SIZE     256
16 CMDLINE_BUFFER(CMDLINE_BUFFER_SIZE);
17
18 #define POLLUTE_CACHE_SIZE      (512 * 1024)
19
20 #ifdef CONFIG_UART_OXPCIE952
21 #define UART_BASE               0xe010
22 #else
23 #define UART_BASE               0x3f8
24 #endif
25 #define UART_LSR                0x5
26 #define UART_LSR_THRE           0x20
27 #define UART_IDLE_LOOPS         100
28
29 #define APIC_TIMER_VECTOR       32
30
31 static unsigned long expected_time;
32 static unsigned long min = -1, max;
33
34 static void irq_handler(void)
35 {
36         unsigned long delta;
37
38         delta = tsc_read() - expected_time;
39         if (delta < min)
40                 min = delta;
41         if (delta > max)
42                 max = delta;
43         printk("Timer fired, jitter: %6ld ns, min: %6ld ns, max: %6ld ns\n",
44                delta, min, max);
45
46         expected_time += 100 * NS_PER_MSEC;
47         apic_timer_set(expected_time - tsc_read());
48 }
49
50 static void init_apic(void)
51 {
52         unsigned long apic_freq_khz;
53
54         int_init();
55         int_set_handler(APIC_TIMER_VECTOR, irq_handler);
56
57         apic_freq_khz = apic_timer_init(APIC_TIMER_VECTOR);
58         printk("Calibrated APIC frequency: %lu kHz\n", apic_freq_khz);
59
60         expected_time = tsc_read() + NS_PER_MSEC;
61         apic_timer_set(NS_PER_MSEC);
62
63         asm volatile("sti");
64 }
65
66 static void pollute_cache(void)
67 {
68         char *mem = (char *)HEAP_BASE;
69         unsigned long cpu_cache_line_size, ebx;
70         unsigned long n;
71
72         asm volatile("cpuid" : "=b" (ebx) : "a" (1)
73                 : "rcx", "rdx", "memory");
74         cpu_cache_line_size = (ebx & 0xff00) >> 5;
75
76         for (n = 0; n < POLLUTE_CACHE_SIZE; n += cpu_cache_line_size)
77                 mem[n] ^= 0xAA;
78 }
79
80 void inmate_main(void)
81 {
82         bool allow_terminate = false;
83         bool terminate = false;
84         unsigned long tsc_freq;
85         bool cache_pollution;
86         unsigned int n;
87
88         printk_uart_base = UART_BASE;
89         do {
90                 for (n = 0; n < UART_IDLE_LOOPS; n++)
91                         if (!(inb(UART_BASE + UART_LSR) & UART_LSR_THRE))
92                                 break;
93         } while (n < UART_IDLE_LOOPS);
94
95         comm_region->cell_state = JAILHOUSE_CELL_RUNNING_LOCKED;
96
97         cache_pollution = cmdline_parse_bool("pollute_cache");
98         if (cache_pollution)
99                 printk("Cache pollution enabled\n");
100
101         tsc_freq = tsc_init();
102         printk("Calibrated TSC frequency: %lu.%03u kHz\n", tsc_freq / 1000,
103                tsc_freq % 1000);
104
105         init_apic();
106
107         while (!terminate) {
108                 asm volatile("hlt");
109
110                 if (cache_pollution)
111                         pollute_cache();
112
113                 switch (comm_region->msg_to_cell) {
114                 case JAILHOUSE_MSG_SHUTDOWN_REQUEST:
115                         if (!allow_terminate) {
116                                 printk("Rejecting first shutdown request - "
117                                        "try again!\n");
118                                 jailhouse_send_reply_from_cell(comm_region,
119                                                 JAILHOUSE_MSG_REQUEST_DENIED);
120                                 allow_terminate = true;
121                         } else
122                                 terminate = true;
123                         break;
124                 default:
125                         jailhouse_send_reply_from_cell(comm_region,
126                                         JAILHOUSE_MSG_UNKNOWN);
127                         break;
128                 }
129         }
130
131         printk("Stopped APIC demo\n");
132         comm_region->cell_state = JAILHOUSE_CELL_SHUT_DOWN;
133 }