1 /*-
2  * Copyright (c) 1999 Luoqi Chen <luoqi@freebsd.org>
3  * Copyright (c) Peter Wemm <peter@netplex.com.au>
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25  * SUCH DAMAGE.
26  *
27  * $FreeBSD: stable/10/sys/ia64/include/pcpu.h 271239 2014-09-07 21:40:14Z marcel $
28  */
29 
30 #ifndef	_MACHINE_PCPU_H_
31 #define	_MACHINE_PCPU_H_
32 
33 #include <sys/sysctl.h>
34 #include <machine/pcb.h>
35 
36 struct pcpu_stats {
37 	u_long		pcs_nasts;		/* IPI_AST counter. */
38 	u_long		pcs_nclks;		/* Clock interrupt counter. */
39 	u_long		pcs_nextints;		/* ExtINT counter. */
40 	u_long		pcs_nhardclocks;	/* IPI_HARDCLOCK counter. */
41 	u_long		pcs_nhighfps;		/* IPI_HIGH_FP counter. */
42 	u_long		pcs_nhwints;		/* Hardware int. counter. */
43 	u_long		pcs_npreempts;		/* IPI_PREEMPT counter. */
44 	u_long		pcs_nrdvs;		/* IPI_RENDEZVOUS counter. */
45 	u_long		pcs_nstops;		/* IPI_STOP counter. */
46 	u_long		pcs_nstrays;		/* Stray interrupt counter. */
47 };
48 
49 struct pcpu_md {
50 	struct pcb	pcb;			/* Used by IPI_STOP */
51 	struct pmap	*current_pmap;		/* active pmap */
52 	vm_offset_t	vhpt;			/* Address of VHPT */
53 	uint64_t	lid;			/* local CPU ID */
54 	uint64_t	clock;			/* Clock counter. */
55 	uint64_t	clock_load;		/* Clock reload value. */
56 	uint32_t	clock_mode;		/* Clock ET mode */
57 	uint32_t	awake:1;		/* CPU is awake? */
58 	struct pcpu_stats stats;		/* Interrupt stats. */
59 	void		*xtrace_buffer;
60 	uint64_t	xtrace_tail;
61 #ifdef _KERNEL
62 	struct sysctl_ctx_list sysctl_ctx;
63 	struct sysctl_oid *sysctl_tree;
64 #endif
65 };
66 
67 #define	PCPU_MD_FIELDS							\
68 	uint32_t	pc_acpi_id;		/* ACPI CPU id. */	\
69 	struct pcpu_md	pc_md;			/* MD fields. */	\
70 	char		__pad[10*128]
71 
72 #ifdef _KERNEL
73 
74 #include <sys/systm.h>
75 
76 struct pcpu;
77 
78 register struct pcpu * volatile pcpup __asm__("r13");
79 
80 static __inline __pure2 struct thread *
__curthread(void)81 __curthread(void)
82 {
83 	struct thread *td;
84 
85 	__asm("ld8.acq %0=[r13]" : "=r"(td));
86 	return (td);
87 }
88 #define	curthread	(__curthread())
89 
90 #define	__pcpu_offset(name)	__offsetof(struct pcpu, name)
91 #define	__pcpu_type(name)	__typeof(((struct pcpu *)0)->name)
92 
93 #define	PCPU_ADD(name, val)					\
94     do {							\
95 	__pcpu_type(pc_ ## name) *nmp;				\
96 	critical_enter();					\
97 	__asm __volatile("add %0=%1,r13;;" :			\
98 	    "=r"(nmp) : "i"(__pcpu_offset(pc_ ## name)));	\
99 	*nmp += val;						\
100 	critical_exit();					\
101     } while (0)
102 
103 #define	PCPU_GET(name)						\
104     ({	__pcpu_type(pc_ ## name) *nmp;				\
105 	__pcpu_type(pc_ ## name) res;				\
106 	critical_enter();					\
107 	__asm __volatile("add %0=%1,r13;;" :			\
108 	    "=r"(nmp) : "i"(__pcpu_offset(pc_ ## name)));	\
109 	res = *nmp;						\
110 	critical_exit();					\
111 	res;							\
112     })
113 
114 #define	PCPU_INC(member)	PCPU_ADD(member, 1)
115 
116 #define	PCPU_PTR(name)						\
117     ({	__pcpu_type(pc_ ## name) *nmp;				\
118 	__asm __volatile("add %0=%1,r13;;" :			\
119 	    "=r"(nmp) : "i"(__pcpu_offset(pc_ ## name)));	\
120 	nmp;							\
121     })
122 
123 #define	PCPU_SET(name, val)					\
124     do {							\
125 	__pcpu_type(pc_ ## name) *nmp;				\
126 	critical_enter();					\
127 	__asm __volatile("add %0=%1,r13;;" :			\
128 	    "=r"(nmp) : "i"(__pcpu_offset(pc_ ## name)));	\
129 	*nmp = val;						\
130 	critical_exit();					\
131     } while (0)
132 
133 #endif	/* _KERNEL */
134 
135 #endif	/* !_MACHINE_PCPU_H_ */
136