]> rtime.felk.cvut.cz Git - jailhouse.git/blob - hypervisor/arch/x86/include/asm/percpu.h
core: Add support for per-CPU statistics
[jailhouse.git] / hypervisor / arch / x86 / include / asm / percpu.h
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 #ifndef _JAILHOUSE_ASM_PERCPU_H
14 #define _JAILHOUSE_ASM_PERCPU_H
15
16 #include <asm/types.h>
17 #include <asm/paging.h>
18 #include <asm/processor.h>
19
20 #include <jailhouse/hypercall.h>
21
22 #define NUM_ENTRY_REGS                  6
23
24 /* Keep in sync with struct per_cpu! */
25 #define PERCPU_SIZE_SHIFT               14
26 #define PERCPU_STACK_END                PAGE_SIZE
27 #define PERCPU_LINUX_SP                 PERCPU_STACK_END
28
29 #ifndef __ASSEMBLY__
30
31 #include <asm/cell.h>
32 #include <asm/spinlock.h>
33
34 struct vmcs {
35         u32 revision_id:31;
36         u32 shadow_indicator:1;
37         u32 abort_indicator;
38         u64 data[(PAGE_SIZE - 4 - 4) / 8];
39 } __attribute__((packed));
40
41 struct per_cpu {
42         /* Keep these two in sync with defines above! */
43         u8 stack[PAGE_SIZE];
44         unsigned long linux_sp;
45
46         unsigned int cpu_id;
47         u32 apic_id;
48         struct cell *cell;
49
50         u32 stats[JAILHOUSE_NUM_CPU_STATS];
51
52         struct desc_table_reg linux_gdtr;
53         struct desc_table_reg linux_idtr;
54         unsigned long linux_reg[NUM_ENTRY_REGS];
55         unsigned long linux_ip;
56         unsigned long linux_cr3;
57         struct segment linux_cs;
58         struct segment linux_ds;
59         struct segment linux_es;
60         struct segment linux_fs;
61         struct segment linux_gs;
62         struct segment linux_tss;
63         unsigned long linux_efer;
64         unsigned long linux_sysenter_cs;
65         unsigned long linux_sysenter_eip;
66         unsigned long linux_sysenter_esp;
67         bool initialized;
68         enum { VMXOFF = 0, VMXON, VMCS_READY } vmx_state;
69
70         /*
71          * protects the following per_cpu fields (unless CPU is stopped):
72          *  - stop_cpu
73          *  - cpu_stopped (except for spinning on it to become true)
74          *  - wait_for_sipi
75          *  - init_signaled
76          *  - sipi_vector
77          *  - flush_caches
78          */
79         spinlock_t control_lock;
80
81         volatile bool stop_cpu;
82         volatile bool wait_for_sipi;
83         volatile bool cpu_stopped;
84         bool init_signaled;
85         int sipi_vector;
86         bool flush_virt_caches;
87         bool shutdown_cpu;
88         int shutdown_state;
89         bool failed;
90
91         struct vmcs vmxon_region __attribute__((aligned(PAGE_SIZE)));
92         struct vmcs vmcs __attribute__((aligned(PAGE_SIZE)));
93 } __attribute__((aligned(PAGE_SIZE)));
94
95 static inline struct per_cpu *per_cpu(unsigned int cpu)
96 {
97         struct per_cpu *cpu_data;
98
99         asm volatile(
100                 "lea __page_pool(%%rip),%0\n\t"
101                 "add %1,%0\n\t"
102                 : "=&qm" (cpu_data)
103                 : "qm" ((unsigned long)cpu << PERCPU_SIZE_SHIFT));
104         return cpu_data;
105 }
106
107 /* Validate defines */
108 #define CHECK_ASSUMPTION(assume)        ((void)sizeof(char[1 - 2*!(assume)]))
109
110 static inline void __check_assumptions(void)
111 {
112         struct per_cpu cpu_data;
113
114         CHECK_ASSUMPTION(sizeof(struct per_cpu) == (1 << PERCPU_SIZE_SHIFT));
115         CHECK_ASSUMPTION(sizeof(cpu_data.stack) == PERCPU_STACK_END);
116         CHECK_ASSUMPTION(__builtin_offsetof(struct per_cpu, linux_sp) ==
117                          PERCPU_LINUX_SP);
118 }
119 #endif /* !__ASSEMBLY__ */
120
121 #endif /* !_JAILHOUSE_ASM_PERCPU_H */