1 /* SPDX-License-Identifier: GPL-2.0-only */
2 /*
3 * pv/domain.h
4 *
5 * PV guest interface definitions
6 *
7 * Copyright (C) 2017 Wei Liu <wei.liu2@citrix.com>
8 */
9
10 #ifndef __X86_PV_DOMAIN_H__
11 #define __X86_PV_DOMAIN_H__
12
13 #include <xen/sched.h>
14
15 #ifdef CONFIG_PV32
16 extern int8_t opt_pv32;
17 #else
18 # define opt_pv32 false
19 #endif
20
21 /*
22 * PCID values for the address spaces of 64-bit pv domains:
23 *
24 * We are using 4 PCID values for a 64 bit pv domain subject to XPTI:
25 * - hypervisor active and guest in kernel mode PCID 0
26 * - hypervisor active and guest in user mode PCID 1
27 * - guest active and in kernel mode PCID 2
28 * - guest active and in user mode PCID 3
29 *
30 * Without XPTI only 2 values are used:
31 * - guest in kernel mode PCID 0
32 * - guest in user mode PCID 1
33 */
34
35 #define PCID_PV_PRIV 0x0000 /* Used for other domains, too. */
36 #define PCID_PV_USER 0x0001
37 #define PCID_PV_XPTI 0x0002 /* To be ORed to above values. */
38
39 /*
40 * Return additional PCID specific cr3 bits.
41 *
42 * Note that X86_CR3_NOFLUSH will not be readable in cr3. Anyone consuming
43 * v->arch.cr3 should mask away X86_CR3_NOFLUSH and X86_CR3_PCIDMASK in case
44 * the value is used to address the root page table.
45 */
get_pcid_bits(const struct vcpu * v,bool is_xpti)46 static inline unsigned long get_pcid_bits(const struct vcpu *v, bool is_xpti)
47 {
48 #ifdef CONFIG_PV
49 return X86_CR3_NOFLUSH | (is_xpti ? PCID_PV_XPTI : 0) |
50 ((v->arch.flags & TF_kernel_mode) ? PCID_PV_PRIV : PCID_PV_USER);
51 #else
52 ASSERT_UNREACHABLE();
53 return 0;
54 #endif
55 }
56
57 #ifdef CONFIG_PV
58
59 void pv_vcpu_destroy(struct vcpu *v);
60 int pv_vcpu_initialise(struct vcpu *v);
61 void pv_domain_destroy(struct domain *d);
62 int pv_domain_initialise(struct domain *d);
63
64 /*
65 * Bits which a PV guest can toggle in its view of cr4. Some are loaded into
66 * hardware, while some are fully emulated.
67 */
68 #define PV_CR4_GUEST_MASK \
69 (X86_CR4_TSD | X86_CR4_DE | X86_CR4_FSGSBASE | X86_CR4_OSXSAVE)
70
71 /* Bits which a PV guest may observe from the real hardware settings. */
72 #define PV_CR4_GUEST_VISIBLE_MASK \
73 (X86_CR4_PAE | X86_CR4_MCE | X86_CR4_OSFXSR | X86_CR4_OSXMMEXCPT)
74
75 /* Given a new cr4 value, construct the resulting guest-visible cr4 value. */
76 unsigned long pv_fixup_guest_cr4(const struct vcpu *v, unsigned long cr4);
77
78 /* Create a cr4 value to load into hardware, based on vcpu settings. */
79 unsigned long pv_make_cr4(const struct vcpu *v);
80
81 /* See hvm_{get,set}_reg() for description. */
82 uint64_t pv_get_reg(struct vcpu *v, unsigned int reg);
83 void pv_set_reg(struct vcpu *v, unsigned int reg, uint64_t val);
84
85 bool xpti_pcid_enabled(void);
86
87 #else /* !CONFIG_PV */
88
89 #include <xen/errno.h>
90
pv_vcpu_destroy(struct vcpu * v)91 static inline void pv_vcpu_destroy(struct vcpu *v) {}
pv_vcpu_initialise(struct vcpu * v)92 static inline int pv_vcpu_initialise(struct vcpu *v) { return -EOPNOTSUPP; }
pv_domain_destroy(struct domain * d)93 static inline void pv_domain_destroy(struct domain *d) {}
pv_domain_initialise(struct domain * d)94 static inline int pv_domain_initialise(struct domain *d) { return -EOPNOTSUPP; }
95
pv_make_cr4(const struct vcpu * v)96 static inline unsigned long pv_make_cr4(const struct vcpu *v) { return ~0UL; }
97
pv_get_reg(struct vcpu * v,unsigned int reg)98 static inline uint64_t pv_get_reg(struct vcpu *v, unsigned int reg)
99 {
100 ASSERT_UNREACHABLE();
101 return 0;
102 }
pv_set_reg(struct vcpu * v,unsigned int reg,uint64_t val)103 static inline void pv_set_reg(struct vcpu *v, unsigned int reg, uint64_t val)
104 {
105 ASSERT_UNREACHABLE();
106 }
107
108 #endif /* CONFIG_PV */
109
110 void cf_check paravirt_ctxt_switch_from(struct vcpu *v);
111 void cf_check paravirt_ctxt_switch_to(struct vcpu *v);
112
113 #endif /* __X86_PV_DOMAIN_H__ */
114
115 /*
116 * Local variables:
117 * mode: C
118 * c-file-style: "BSD"
119 * c-basic-offset: 4
120 * tab-width: 4
121 * indent-tabs-mode: nil
122 * End:
123 */
124