Deleted Added
sdiff udiff text old ( 122829 ) new ( 122833 )
full compact
1/*-
2 * Copyright (c) Peter Wemm <peter@netplex.com.au>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
26 * $FreeBSD: head/sys/amd64/include/pcpu.h 122833 2003-11-17 04:40:58Z bde $
27 */
28
29#ifndef _MACHINE_PCPU_H_
30#define _MACHINE_PCPU_H_
31
32#ifdef _KERNEL
33
34/*
35 * The SMP parts are setup in pmap.c and locore.s for the BSP, and
36 * mp_machdep.c sets up the data for the AP's to "see" when they awake.
37 * The reason for doing it via a struct is so that an array of pointers
38 * to each CPU's data can be set up for things like "check curproc on all
39 * other processors"
40 */
41#define PCPU_MD_FIELDS \
42 struct pcpu *pc_prvspace; /* Self-reference */ \
43 register_t pc_scratch_rsp; /* User %rsp in syscall */ \
44 u_int pc_acpi_id /* ACPI CPU id */
45
46#if defined(lint)
47
48extern struct pcpu *pcpup;
49
50#define PCPU_GET(member) (pcpup->pc_ ## member)
51#define PCPU_PTR(member) (&pcpup->pc_ ## member)
52#define PCPU_SET(member,value) (pcpup->pc_ ## member = (value))
53
54#elif defined(__GNUC__)
55
56/*
57 * Evaluates to the byte offset of the per-cpu variable name.
58 */
59#define __pcpu_offset(name) \
60 __offsetof(struct pcpu, name)
61
62/*
63 * Evaluates to the type of the per-cpu variable name.
64 */
65#define __pcpu_type(name) \
66 __typeof(((struct pcpu *)0)->name)
67
68/*
69 * Evaluates to the address of the per-cpu variable name.
70 */
71#define __PCPU_PTR(name) __extension__ ({ \
72 __pcpu_type(name) *__p; \
73 \
74 __asm __volatile("movq %%gs:%1,%0; addq %2,%0" \
75 : "=r" (__p) \
76 : "m" (*(struct pcpu *)(__pcpu_offset(pc_prvspace))), \
77 "i" (__pcpu_offset(name))); \
78 \
79 __p; \
80})
81
82/*
83 * Evaluates to the value of the per-cpu variable name.
84 */
85#define __PCPU_GET(name) __extension__ ({ \
86 __pcpu_type(name) __result; \
87 \
88 if (sizeof(__result) == 1) { \
89 u_char __b; \
90 __asm __volatile("movb %%gs:%1,%0" \
91 : "=r" (__b) \
92 : "m" (*(u_char *)(__pcpu_offset(name)))); \
93 __result = *(__pcpu_type(name) *)&__b; \
94 } else if (sizeof(__result) == 2) { \
95 u_short __w; \
96 __asm __volatile("movw %%gs:%1,%0" \
97 : "=r" (__w) \
98 : "m" (*(u_short *)(__pcpu_offset(name)))); \
99 __result = *(__pcpu_type(name) *)&__w; \
100 } else if (sizeof(__result) == 4) { \
101 u_int __i; \
102 __asm __volatile("movl %%gs:%1,%0" \
103 : "=r" (__i) \
104 : "m" (*(u_int *)(__pcpu_offset(name)))); \
105 __result = *(__pcpu_type(name) *)&__i; \
106 } else if (sizeof(__result) == 8) { \
107 u_long __l; \
108 __asm __volatile("movq %%gs:%1,%0" \
109 : "=r" (__l) \
110 : "m" (*(u_long *)(__pcpu_offset(name)))); \
111 __result = *(__pcpu_type(name) *)&__l; \
112 } else { \
113 __result = *__PCPU_PTR(name); \
114 } \
115 \
116 __result; \
117})
118
119/*
120 * Sets the value of the per-cpu variable name to value val.
121 */
122#define __PCPU_SET(name, val) { \
123 __pcpu_type(name) __val = (val); \
124 \
125 if (sizeof(__val) == 1) { \
126 u_char __b; \
127 __b = *(u_char *)&__val; \
128 __asm __volatile("movb %1,%%gs:%0" \
129 : "=m" (*(u_char *)(__pcpu_offset(name))) \
130 : "r" (__b)); \
131 } else if (sizeof(__val) == 2) { \
132 u_short __w; \
133 __w = *(u_short *)&__val; \
134 __asm __volatile("movw %1,%%gs:%0" \
135 : "=m" (*(u_short *)(__pcpu_offset(name))) \
136 : "r" (__w)); \
137 } else if (sizeof(__val) == 4) { \
138 u_int __i; \
139 __i = *(u_int *)&__val; \
140 __asm __volatile("movl %1,%%gs:%0" \
141 : "=m" (*(u_int *)(__pcpu_offset(name))) \
142 : "r" (__i)); \
143 } else if (sizeof(__val) == 8) { \
144 u_long __l; \
145 __l = *(u_long *)&__val; \
146 __asm __volatile("movq %1,%%gs:%0" \
147 : "=m" (*(u_long *)(__pcpu_offset(name))) \
148 : "r" (__l)); \
149 } else { \
150 *__PCPU_PTR(name) = __val; \
151 } \
152}
153
154#define PCPU_GET(member) __PCPU_GET(pc_ ## member)
155#define PCPU_PTR(member) __PCPU_PTR(pc_ ## member)
156#define PCPU_SET(member, val) __PCPU_SET(pc_ ## member, val)
157
158#else
159#error gcc or lint is required to use this file
160#endif
161
162#endif /* _KERNEL */
163
164#endif /* ! _MACHINE_PCPU_H_ */