summaryrefslogtreecommitdiff
path: root/usr/src/uts/i86pc/sys/machcpuvar.h
blob: 772f3112cb4439c5a68fd2f7f564b5f0421f8c75 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License (the "License").
 * You may not use this file except in compliance with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */
/*
 * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 */
/*
 * Copyright 2019 Joyent, Inc.
 */

#ifndef	_SYS_MACHCPUVAR_H
#define	_SYS_MACHCPUVAR_H

#ifdef	__cplusplus
extern "C" {
#endif

#include <sys/inttypes.h>
#include <sys/x_call.h>
#include <sys/tss.h>
#include <sys/segments.h>
#include <sys/rm_platter.h>
#include <sys/avintr.h>
#include <sys/pte.h>
#include <sys/stddef.h>
#include <sys/debug.h>
#include <sys/cpuvar.h>

#ifndef	_ASM
/*
 * On a virtualized platform a virtual cpu may not be actually
 * on a physical cpu, especially in situations where a configuration has
 * more vcpus than pcpus.  This function tells us (if it's able) if the
 * specified vcpu is currently running on a pcpu.  Note if it is not
 * known or not able to determine, it will return the unknown state.
 */
#define	VCPU_STATE_UNKNOWN	0
#define	VCPU_ON_PCPU		1
#define	VCPU_NOT_ON_PCPU	2

extern int vcpu_on_pcpu(processorid_t);

/*
 * Machine specific fields of the cpu struct
 * defined in common/sys/cpuvar.h.
 *
 * Note:  This is kinda kludgy but seems to be the best
 * of our alternatives.
 */

struct cpuid_info;
struct cpu_ucode_info;
struct cmi_hdl;

/*
 * A note about the hypervisor affinity bits: a one bit in the affinity mask
 * means the corresponding event channel is allowed to be serviced
 * by this cpu.
 */
struct xen_evt_data {
	ulong_t		pending_sel[PIL_MAX + 1]; /* event array selectors */
	ulong_t		pending_evts[PIL_MAX + 1][sizeof (ulong_t) * 8];
	ulong_t		evt_affinity[sizeof (ulong_t) * 8]; /* service on cpu */
};

enum fast_syscall_state {
	FSS_DISABLED		= 0,
	FSS_ASYSC_ENABLED	= (1 << 0),
	FSS_SEP_ENABLED		= (1 << 1)
};

struct kpti_frame {
	uint64_t	kf_lower_redzone;

	/* Stashed value of %cr3 when we entered the trampoline. */
	greg_t		kf_tr_cr3;

	/*
	 * We use %r13-r14 as scratch registers in the trampoline code,
	 * so stash those here "below" the rest of the stack so they can be
	 * pushed/popped if needed.
	 */
	greg_t		kf_r14;
	greg_t		kf_r13;

	/*
	 * Part of this struct is used as the HW stack frame when taking an
	 * interrupt on the user page table. The CPU is going to push a bunch
	 * of regs onto the stack pointer set in the TSS/IDT (which we set to
	 * &kf_rsp here).
	 *
	 * This is only a temporary holding area for them (we'll move them over
	 * to the real interrupt stack once we've set %cr3).
	 *
	 * Note that these must be cleared during a process switch on this cpu.
	 */
	greg_t		kf_err;		/* Bottom of initial hw stack frame */
	greg_t		kf_rip;
	greg_t		kf_cs;
	greg_t		kf_rflags;
	greg_t		kf_rsp;
	greg_t		kf_ss;

	greg_t		kf_tr_rsp;	/* Top of HW stack frame */
	/* We also write this with the %rsp value on tramp entry */

	/* Written to 0x1 when this kpti_frame is in use. */
	uint64_t	kf_tr_flag;

	uint64_t	kf_middle_redzone;

	/*
	 * The things we need to write to %cr3 to change between page tables.
	 * These live "above" the HW stack.
	 */
	greg_t		kf_kernel_cr3;
	greg_t		kf_user_cr3;
	greg_t		kf_tr_ret_rsp;

	uint64_t	kf_unused;		/* For 16-byte align */

	uint64_t	kf_upper_redzone;
};

typedef struct cpu_smt {
	lock_t cs_lock;
	char cs_pad[56];
	struct cpu *cs_sib;
	volatile uint64_t cs_intr_depth;
	volatile uint64_t cs_state;
	volatile uint64_t cs_sibstate;
} cpu_smt_t;

/*
 * This first value, MACHCPU_SIZE is the size of all the members in the cpu_t
 * AND struct machcpu, before we get to the mcpu_pad and the kpti area.
 * The KPTI is used to contain per-CPU data that is visible in both sets of
 * page-tables, and hence must be page-aligned and page-sized. See
 * hat_pcp_setup().
 *
 * There are CTASSERTs in os/intr.c that verify this all works out.
 */
#define	MACHCPU_SIZE	(1568 + 696)
#define	MACHCPU_PAD	(MMU_PAGESIZE - MACHCPU_SIZE)
#define	MACHCPU_PAD2	(MMU_PAGESIZE - 16 - 3 * sizeof (struct kpti_frame))

struct	machcpu {
	/*
	 * x_call fields - used for interprocessor cross calls
	 */
	struct xc_msg	*xc_msgbox;
	struct xc_msg	*xc_curmsg;
	struct xc_msg	*xc_free;
	xc_data_t	xc_data;
	uint32_t	xc_wait_cnt;
	volatile uint32_t xc_work_cnt;

	int		mcpu_nodeid;		/* node-id */
	int		mcpu_pri;		/* CPU priority */

	struct hat	*mcpu_current_hat; /* cpu's current hat */

	struct hat_cpu_info	*mcpu_hat_info;

	volatile ulong_t	mcpu_tlb_info;

	/* i86 hardware table addresses that cannot be shared */

	user_desc_t	*mcpu_gdt;	/* GDT */
	gate_desc_t	*mcpu_idt;	/* current IDT */

	tss_t		*mcpu_tss;	/* TSS */
	void		*mcpu_ldt;
	size_t		mcpu_ldt_len;

	kmutex_t	mcpu_ppaddr_mutex;
	caddr_t		mcpu_caddr1;	/* per cpu CADDR1 */
	caddr_t		mcpu_caddr2;	/* per cpu CADDR2 */
	uint64_t	mcpu_caddr1pte;
	uint64_t	mcpu_caddr2pte;

	struct softint	mcpu_softinfo;
	uint64_t	pil_high_start[HIGH_LEVELS];
	uint64_t	intrstat[PIL_MAX + 1][2];

	struct cpuid_info	 *mcpu_cpi;

#if defined(__amd64)
	greg_t	mcpu_rtmp_rsp;		/* syscall: temporary %rsp stash */
	greg_t	mcpu_rtmp_r15;		/* syscall: temporary %r15 stash */
#endif

	struct vcpu_info *mcpu_vcpu_info;
	uint64_t	mcpu_gdtpa;	/* hypervisor: GDT physical address */

	uint16_t mcpu_intr_pending;	/* hypervisor: pending intrpt levels */
	uint16_t mcpu_ec_mbox;		/* hypervisor: evtchn_dev mailbox */
	struct xen_evt_data *mcpu_evt_pend; /* hypervisor: pending events */

	volatile uint32_t *mcpu_mwait;	/* MONITOR/MWAIT buffer */
	void (*mcpu_idle_cpu)(void);	/* idle function */
	uint16_t mcpu_idle_type;	/* CPU next idle type */
	uint16_t max_cstates;		/* supported max cstates */

	enum fast_syscall_state	mcpu_fast_syscall_state;

	struct cpu_ucode_info	*mcpu_ucode_info;

	void			*mcpu_pm_mach_state;
	struct cmi_hdl		*mcpu_cmi_hdl;
	void			*mcpu_mach_ctx_ptr;

	/*
	 * A stamp that is unique per processor and changes
	 * whenever an interrupt happens. Userful for detecting
	 * if a section of code gets interrupted.
	 * The high order 16 bits will hold the cpu->cpu_id.
	 * The low order bits will be incremented on every interrupt.
	 */
	volatile uint32_t	mcpu_istamp;

	cpu_smt_t		mcpu_smt;

	char			mcpu_pad[MACHCPU_PAD];

	/* This is the start of the page */
	char			mcpu_pad2[MACHCPU_PAD2];
	struct kpti_frame	mcpu_kpti;
	struct kpti_frame	mcpu_kpti_flt;
	struct kpti_frame	mcpu_kpti_dbg;
	char			mcpu_pad3[16];
};

#define	NINTR_THREADS	(LOCK_LEVEL-1)	/* number of interrupt threads */
#define	MWAIT_HALTED	(1)		/* mcpu_mwait set when halting */
#define	MWAIT_RUNNING	(0)		/* mcpu_mwait set to wakeup */
#define	MWAIT_WAKEUP_IPI	(2)	/* need IPI to wakeup */
#define	MWAIT_WAKEUP(cpu)	(*((cpu)->cpu_m.mcpu_mwait) = MWAIT_RUNNING)

#endif	/* _ASM */

/* Please DON'T add any more of this namespace-poisoning sewage here */

#define	cpu_nodeid cpu_m.mcpu_nodeid
#define	cpu_pri cpu_m.mcpu_pri
#define	cpu_current_hat cpu_m.mcpu_current_hat
#define	cpu_hat_info cpu_m.mcpu_hat_info
#define	cpu_ppaddr_mutex cpu_m.mcpu_ppaddr_mutex
#define	cpu_gdt cpu_m.mcpu_gdt
#define	cpu_idt cpu_m.mcpu_idt
#define	cpu_tss cpu_m.mcpu_tss
#define	cpu_caddr1 cpu_m.mcpu_caddr1
#define	cpu_caddr2 cpu_m.mcpu_caddr2
#define	cpu_softinfo cpu_m.mcpu_softinfo
#define	cpu_caddr1pte cpu_m.mcpu_caddr1pte
#define	cpu_caddr2pte cpu_m.mcpu_caddr2pte

#ifdef	__cplusplus
}
#endif

#endif	/* _SYS_MACHCPUVAR_H */