summaryrefslogtreecommitdiff
path: root/sys/amd64/include/pcpu.h
diff options
context:
space:
mode:
Diffstat (limited to 'sys/amd64/include/pcpu.h')
-rw-r--r--sys/amd64/include/pcpu.h138
1 files changed, 103 insertions, 35 deletions
diff --git a/sys/amd64/include/pcpu.h b/sys/amd64/include/pcpu.h
index 46c26c444fbf..5fecb9871e6f 100644
--- a/sys/amd64/include/pcpu.h
+++ b/sys/amd64/include/pcpu.h
@@ -26,54 +26,122 @@
* $FreeBSD$
*/
-#ifndef _MACHINE_GLOBALDATA_H_
-#define _MACHINE_GLOBALDATA_H_
+#ifndef _MACHINE_PCPU_H_
+#define _MACHINE_PCPU_H_
#ifdef _KERNEL
+#ifndef __GNUC__
+#error gcc is required to use this file
+#endif
+
#include <machine/segments.h>
#include <machine/tss.h>
-/* XXX */
-#ifdef KTR_PERCPU
-#include <sys/ktr.h>
-#endif
-
/*
- * This structure maps out the global data that needs to be kept on a
- * per-cpu basis. genassym uses this to generate offsets for the assembler
- * code, which also provides external symbols so that C can get at them as
- * though they were really globals.
- *
* The SMP parts are setup in pmap.c and locore.s for the BSP, and
* mp_machdep.c sets up the data for the AP's to "see" when they awake.
* The reason for doing it via a struct is so that an array of pointers
* to each CPU's data can be set up for things like "check curproc on all
* other processors"
*/
-struct globaldata {
- struct globaldata *gd_prvspace; /* Self-reference */
- struct thread *gd_curthread;
- struct thread *gd_npxthread;
- struct pcb *gd_curpcb;
- struct thread *gd_idlethread;
- struct timeval gd_switchtime;
- struct i386tss gd_common_tss;
- int gd_switchticks;
- struct segment_descriptor gd_common_tssd;
- struct segment_descriptor *gd_tss_gdt;
- int gd_currentldt;
- u_int gd_cpuid;
- u_int gd_other_cpus;
- SLIST_ENTRY(globaldata) gd_allcpu;
- struct lock_list_entry *gd_spinlocks;
-#ifdef KTR_PERCPU
- int gd_ktr_idx; /* Index into trace table */
- char *gd_ktr_buf;
- char gd_ktr_buf_data[KTR_SIZE];
-#endif
-};
+#define PCPU_MD_FIELDS \
+ struct pcpu *pc_prvspace; /* Self-reference */ \
+ struct i386tss pc_common_tss; \
+ struct segment_descriptor pc_common_tssd; \
+ struct segment_descriptor *pc_tss_gdt; \
+ int pc_currentldt
+
+/*
+ * Evaluates to the byte offset of the per-cpu variable name.
+ */
+#define __pcpu_offset(name) \
+ __offsetof(struct pcpu, name)
+
+/*
+ * Evaluates to the type of the per-cpu variable name.
+ */
+#define __pcpu_type(name) \
+ __typeof(((struct pcpu *)0)->name)
+
+/*
+ * Evaluates to the address of the per-cpu variable name.
+ */
+#define __PCPU_PTR(name) ({ \
+ __pcpu_type(name) *__p; \
+ \
+ __asm __volatile("movl %%fs:%1,%0; addl %2,%0" \
+ : "=r" (__p) \
+ : "m" (*(struct pcpu *)(__pcpu_offset(pc_prvspace))), \
+ "i" (__pcpu_offset(name))); \
+ \
+ __p; \
+})
+
+/*
+ * Evaluates to the value of the per-cpu variable name.
+ */
+#define __PCPU_GET(name) ({ \
+ __pcpu_type(name) __result; \
+ \
+ if (sizeof(__result) == 1) { \
+ u_char __b; \
+ __asm __volatile("movb %%fs:%1,%0" \
+ : "=r" (__b) \
+ : "m" (*(u_char *)(__pcpu_offset(name)))); \
+ __result = *(__pcpu_type(name) *)&__b; \
+ } else if (sizeof(__result) == 2) { \
+ u_short __w; \
+ __asm __volatile("movw %%fs:%1,%0" \
+ : "=r" (__w) \
+ : "m" (*(u_short *)(__pcpu_offset(name)))); \
+ __result = *(__pcpu_type(name) *)&__w; \
+ } else if (sizeof(__result) == 4) { \
+ u_int __i; \
+ __asm __volatile("movl %%fs:%1,%0" \
+ : "=r" (__i) \
+ : "m" (*(u_int *)(__pcpu_offset(name)))); \
+ __result = *(__pcpu_type(name) *)&__i; \
+ } else { \
+ __result = *__PCPU_PTR(name); \
+ } \
+ \
+ __result; \
+})
+
+/*
+ * Sets the value of the per-cpu variable name to value val.
+ */
+#define __PCPU_SET(name, val) ({ \
+ __pcpu_type(name) __val = (val); \
+ \
+ if (sizeof(__val) == 1) { \
+ u_char __b; \
+ __b = *(u_char *)&__val; \
+ __asm __volatile("movb %1,%%fs:%0" \
+ : "=m" (*(u_char *)(__pcpu_offset(name))) \
+ : "r" (__b)); \
+ } else if (sizeof(__val) == 2) { \
+ u_short __w; \
+ __w = *(u_short *)&__val; \
+ __asm __volatile("movw %1,%%fs:%0" \
+ : "=m" (*(u_short *)(__pcpu_offset(name))) \
+ : "r" (__w)); \
+ } else if (sizeof(__val) == 4) { \
+ u_int __i; \
+ __i = *(u_int *)&__val; \
+ __asm __volatile("movl %1,%%fs:%0" \
+ : "=m" (*(u_int *)(__pcpu_offset(name))) \
+ : "r" (__i)); \
+ } else { \
+ *__PCPU_PTR(name) = __val; \
+ } \
+})
+
+#define PCPU_GET(member) __PCPU_GET(pc_ ## member)
+#define PCPU_PTR(member) __PCPU_PTR(pc_ ## member)
+#define PCPU_SET(member, val) __PCPU_SET(pc_ ## member, val)
#endif /* _KERNEL */
-#endif /* ! _MACHINE_GLOBALDATA_H_ */
+#endif /* ! _MACHINE_PCPU_H_ */