xref: /netbsd-src/sys/arch/amd64/include/cpu.h (revision 23c8222edbfb0f0932d88a8351d3a0cf817dfb9e)
1 /*	$NetBSD: cpu.h,v 1.6 2004/09/25 11:08:47 yamt Exp $	*/
2 
3 /*-
4  * Copyright (c) 1990 The Regents of the University of California.
5  * All rights reserved.
6  *
7  * This code is derived from software contributed to Berkeley by
8  * William Jolitz.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  * 3. Neither the name of the University nor the names of its contributors
19  *    may be used to endorse or promote products derived from this software
20  *    without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32  * SUCH DAMAGE.
33  *
34  *	@(#)cpu.h	5.4 (Berkeley) 5/9/91
35  */
36 
37 #ifndef _AMD64_CPU_H_
38 #define _AMD64_CPU_H_
39 
40 #if defined(_KERNEL)
41 #if defined(_KERNEL_OPT)
42 #include "opt_multiprocessor.h"
43 #include "opt_lockdebug.h"
44 #endif
45 
46 /*
47  * Definitions unique to x86-64 cpu support.
48  */
49 #include <machine/frame.h>
50 #include <machine/segments.h>
51 #include <machine/tss.h>
52 #include <machine/intrdefs.h>
53 #include <x86/cacheinfo.h>
54 
55 #include <sys/device.h>
56 #include <sys/lock.h>
57 #include <sys/cpu_data.h>
58 #include <sys/cc_microtime.h>
59 
60 struct cpu_info {
61 	struct device *ci_dev;
62 	struct cpu_info *ci_self;
63 	struct cpu_data ci_data;	/* MI per-cpu data */
64 	struct cc_microtime_state ci_cc;/* cc_microtime state */
65 	struct cpu_info *ci_next;
66 
67 	struct lwp *ci_curlwp;
68 	struct simplelock ci_slock;
69 	u_int ci_cpuid;
70 	u_int ci_apicid;
71 
72 	u_int64_t ci_scratch;
73 
74 	struct lwp *ci_fpcurlwp;
75 	int ci_fpsaving;
76 
77 	volatile u_int32_t ci_tlb_ipi_mask;
78 
79 	struct pcb *ci_curpcb;
80 	struct pcb *ci_idle_pcb;
81 	int ci_idle_tss_sel;
82 
83 	struct intrsource *ci_isources[MAX_INTR_SOURCES];
84 	u_int32_t	ci_ipending;
85 	int		ci_ilevel;
86 	int		ci_idepth;
87 	u_int32_t	ci_imask[NIPL];
88 	u_int32_t	ci_iunmask[NIPL];
89 
90 	paddr_t 	ci_idle_pcb_paddr;
91 	u_int		ci_flags;
92 	u_int32_t	ci_ipis;
93 
94 	u_int32_t	ci_feature_flags;
95 	u_int32_t	ci_signature;
96 	u_int64_t	ci_tsc_freq;
97 
98 	struct cpu_functions *ci_func;
99 	void (*cpu_setup) __P((struct cpu_info *));
100 	void (*ci_info) __P((struct cpu_info *));
101 
102 	int		ci_want_resched;
103 	int		ci_astpending;
104 	struct trapframe *ci_ddb_regs;
105 
106 	struct x86_cache_info ci_cinfo[CAI_COUNT];
107 
108 	char		*ci_gdt;
109 
110 	struct x86_64_tss	ci_doubleflt_tss;
111 	struct x86_64_tss	ci_ddbipi_tss;
112 
113 	char *ci_doubleflt_stack;
114 	char *ci_ddbipi_stack;
115 
116 	struct evcnt ci_ipi_events[X86_NIPI];
117 };
118 
119 #define CPUF_BSP	0x0001		/* CPU is the original BSP */
120 #define CPUF_AP		0x0002		/* CPU is an AP */
121 #define CPUF_SP		0x0004		/* CPU is only processor */
122 #define CPUF_PRIMARY	0x0008		/* CPU is active primary processor */
123 
124 #define CPUF_PRESENT	0x1000		/* CPU is present */
125 #define CPUF_RUNNING	0x2000		/* CPU is running */
126 #define CPUF_PAUSE	0x4000		/* CPU is paused in DDB */
127 #define CPUF_GO		0x8000		/* CPU should start running */
128 
129 
130 extern struct cpu_info cpu_info_primary;
131 extern struct cpu_info *cpu_info_list;
132 
133 #define CPU_INFO_ITERATOR		int
134 #define CPU_INFO_FOREACH(cii, ci)	cii = 0, ci = cpu_info_list; \
135 					ci != NULL; ci = ci->ci_next
136 
137 #if defined(MULTIPROCESSOR)
138 
139 #define X86_MAXPROCS		32	/* bitmask; can be bumped to 64 */
140 
141 #define CPU_STARTUP(_ci)	((_ci)->ci_func->start(_ci))
142 #define CPU_STOP(_ci)		((_ci)->ci_func->stop(_ci))
143 #define CPU_START_CLEANUP(_ci)	((_ci)->ci_func->cleanup(_ci))
144 
145 #define curcpu()	({struct cpu_info *__ci;                  \
146 			asm volatile("movq %%gs:8,%0" : "=r" (__ci)); \
147 			__ci;})
148 #define cpu_number()	(curcpu()->ci_cpuid)
149 
150 #define CPU_IS_PRIMARY(ci)	((ci)->ci_flags & CPUF_PRIMARY)
151 
152 extern struct cpu_info *cpu_info[X86_MAXPROCS];
153 
154 void cpu_boot_secondary_processors __P((void));
155 void cpu_init_idle_pcbs __P((void));
156 
157 
158 /*
159  * Preempt the current process if in interrupt from user mode,
160  * or after the current trap/syscall if in system mode.
161  */
162 extern void need_resched __P((struct cpu_info *));
163 
164 #else /* !MULTIPROCESSOR */
165 
166 #define X86_MAXPROCS		1
167 
168 extern struct cpu_info cpu_info_primary;
169 
170 #define curcpu()		(&cpu_info_primary)
171 
172 /*
173  * definitions of cpu-dependent requirements
174  * referenced in generic code
175  */
176 #define	cpu_number()		0
177 #define CPU_IS_PRIMARY(ci)	1
178 
179 /*
180  * Preempt the current process if in interrupt from user mode,
181  * or after the current trap/syscall if in system mode.
182  */
183 
184 #define need_resched(ci)						\
185 do {									\
186 	struct cpu_info *__ci = (ci);					\
187 	__ci->ci_want_resched = 1;					\
188 	if (__ci->ci_curlwp != NULL)					\
189 		aston(__ci->ci_curlwp->l_proc);				\
190 } while (/*CONSTCOND*/0)
191 
192 #endif
193 
194 #define aston(p)	((p)->p_md.md_astpending = 1)
195 
196 extern u_int32_t cpus_attached;
197 
198 #define curpcb		curcpu()->ci_curpcb
199 #define curlwp		curcpu()->ci_curlwp
200 
201 /*
202  * Arguments to hardclock, softclock and statclock
203  * encapsulate the previous machine state in an opaque
204  * clockframe; for now, use generic intrframe.
205  */
206 #define clockframe intrframe
207 
208 #define	CLKF_USERMODE(frame)	USERMODE((frame)->if_cs, (frame)->if_rflags)
209 #define CLKF_BASEPRI(frame)	(0)
210 #define CLKF_PC(frame)		((frame)->if_rip)
211 #define CLKF_INTR(frame)	(curcpu()->ci_idepth > 1)
212 
213 /*
214  * This is used during profiling to integrate system time.  It can safely
215  * assume that the process is resident.
216  */
217 #define LWP_PC(l)		((l)->l_md.md_regs->tf_rip)
218 
219 /*
220  * Give a profiling tick to the current process when the user profiling
221  * buffer pages are invalid.  On the i386, request an ast to send us
222  * through trap(), marking the proc as needing a profiling tick.
223  */
224 #define	need_proftick(p)	((p)->p_flag |= P_OWEUPC, aston(p))
225 
226 /*
227  * Notify the current process (p) that it has a signal pending,
228  * process as soon as possible.
229  */
230 #define	signotify(p)		aston(p)
231 
232 /*
233  * We need a machine-independent name for this.
234  */
235 extern void (*delay_func) __P((int));
236 struct timeval;
237 extern void (*microtime_func) __P((struct timeval *));
238 
239 #define DELAY(x)		(*delay_func)(x)
240 #define delay(x)		(*delay_func)(x)
241 #define microtime(tv)		(*microtime_func)(tv)
242 
243 
244 /*
245  * pull in #defines for kinds of processors
246  */
247 
248 extern int biosbasemem;
249 extern int biosextmem;
250 extern int cpu;
251 extern int cpu_feature;
252 extern int cpu_id;
253 extern char cpu_vendor[];
254 extern int cpuid_level;
255 
256 /* identcpu.c */
257 
258 void	identifycpu __P((struct cpu_info *));
259 void cpu_probe_features __P((struct cpu_info *));
260 
261 /* machdep.c */
262 void	delay __P((int));
263 void	dumpconf __P((void));
264 int	cpu_maxproc __P((void));
265 void	cpu_reset __P((void));
266 void	x86_64_proc0_tss_ldt_init __P((void));
267 void	x86_64_init_pcb_tss_ldt __P((struct cpu_info *));
268 void	cpu_proc_fork __P((struct proc *, struct proc *));
269 
270 struct region_descriptor;
271 void	lgdt __P((struct region_descriptor *));
272 void	fillw __P((short, void *, size_t));
273 
274 struct pcb;
275 void	savectx __P((struct pcb *));
276 void	switch_exit __P((struct lwp *, void (*)(struct lwp *)));
277 void	proc_trampoline __P((void));
278 void	child_trampoline __P((void));
279 
280 /* clock.c */
281 void	initrtclock __P((void));
282 void	startrtclock __P((void));
283 void	i8254_delay __P((int));
284 void	i8254_microtime __P((struct timeval *));
285 void	i8254_initclocks __P((void));
286 
287 void cpu_init_msrs __P((struct cpu_info *));
288 
289 
290 /* vm_machdep.c */
291 int kvtop __P((caddr_t));
292 
293 /* trap.c */
294 void	child_return __P((void *));
295 
296 /* consinit.c */
297 void kgdb_port_init __P((void));
298 
299 /* bus_machdep.c */
300 void x86_bus_space_init __P((void));
301 void x86_bus_space_mallocok __P((void));
302 
303 #endif /* _KERNEL */
304 
305 #include <machine/psl.h>
306 
307 /*
308  * CTL_MACHDEP definitions.
309  */
310 #define	CPU_CONSDEV		1	/* dev_t: console terminal device */
311 #define	CPU_BIOSBASEMEM		2	/* int: bios-reported base mem (K) */
312 #define	CPU_BIOSEXTMEM		3	/* int: bios-reported ext. mem (K) */
313 #define	CPU_NKPDE		4	/* int: number of kernel PDEs */
314 #define	CPU_BOOTED_KERNEL	5	/* string: booted kernel name */
315 #define CPU_DISKINFO		6	/* disk geometry information */
316 #define CPU_FPU_PRESENT		7	/* FPU is present */
317 #define	CPU_MAXID		8	/* number of valid machdep ids */
318 
319 #define	CTL_MACHDEP_NAMES { \
320 	{ 0, 0 }, \
321 	{ "console_device", CTLTYPE_STRUCT }, \
322 	{ "biosbasemem", CTLTYPE_INT }, \
323 	{ "biosextmem", CTLTYPE_INT }, \
324 	{ "nkpde", CTLTYPE_INT }, \
325 	{ "booted_kernel", CTLTYPE_STRING }, \
326 	{ "diskinfo", CTLTYPE_STRUCT }, \
327 	{ "fpu_present", CTLTYPE_INT }, \
328 }
329 
330 
331 /*
332  * Structure for CPU_DISKINFO sysctl call.
333  * XXX this should be somewhere else.
334  */
335 #define MAX_BIOSDISKS	16
336 
337 struct disklist {
338 	int dl_nbiosdisks;			   /* number of bios disks */
339 	struct biosdisk_info {
340 		int bi_dev;			   /* BIOS device # (0x80 ..) */
341 		int bi_cyl;			   /* cylinders on disk */
342 		int bi_head;			   /* heads per track */
343 		int bi_sec;			   /* sectors per track */
344 		u_int64_t bi_lbasecs;		   /* total sec. (iff ext13) */
345 #define BIFLAG_INVALID		0x01
346 #define BIFLAG_EXTINT13		0x02
347 		int bi_flags;
348 	} dl_biosdisks[MAX_BIOSDISKS];
349 
350 	int dl_nnativedisks;			   /* number of native disks */
351 	struct nativedisk_info {
352 		char ni_devname[16];		   /* native device name */
353 		int ni_nmatches; 		   /* # of matches w/ BIOS */
354 		int ni_biosmatches[MAX_BIOSDISKS]; /* indices in dl_biosdisks */
355 	} dl_nativedisks[1];			   /* actually longer */
356 };
357 
358 #endif /* !_AMD64_CPU_H_ */
359