summaryrefslogtreecommitdiffstats
path: root/sys/amd64/include
diff options
context:
space:
mode:
authorjhb <jhb@FreeBSD.org>2001-12-11 23:33:44 +0000
committerjhb <jhb@FreeBSD.org>2001-12-11 23:33:44 +0000
commit21b6b26912b00bb37f9f16080ba7d49241814935 (patch)
treec785835e70070309148a72c55669ff0bf043a20a /sys/amd64/include
parent279222ba62c185d7d7ec09017bb3e7760fd333f0 (diff)
downloadFreeBSD-src-21b6b26912b00bb37f9f16080ba7d49241814935.zip
FreeBSD-src-21b6b26912b00bb37f9f16080ba7d49241814935.tar.gz
Overhaul the per-CPU support a bit:
- The MI portions of struct globaldata have been consolidated into a MI struct pcpu. The MD per-CPU data are specified via a macro defined in machine/pcpu.h. A macro was chosen over a struct mdpcpu so that the interface would be cleaner (PCPU_GET(my_md_field) vs. PCPU_GET(md.md_my_md_field)). - All references to globaldata are changed to pcpu instead. In a UP kernel, this data was stored as global variables which is where the original name came from. In an SMP world this data is per-CPU and ideally private to each CPU outside of the context of debuggers. This also included combining machine/globaldata.h and machine/globals.h into machine/pcpu.h. - The pointer to the thread using the FPU on i386 was renamed from npxthread to fpcurthread to be identical with other architectures. - Make the show pcpu ddb command MI with a MD callout to display MD fields. - The globaldata_register() function was renamed to pcpu_init() and now init's MI fields of a struct pcpu in addition to registering it with the internal array and list. - A pcpu_destroy() function was added to remove a struct pcpu from the internal array and list. Tested on: alpha, i386 Reviewed by: peter, jake
Diffstat (limited to 'sys/amd64/include')
-rw-r--r--sys/amd64/include/asmacros.h6
-rw-r--r--sys/amd64/include/cpu.h1
-rw-r--r--sys/amd64/include/mptable.h16
-rw-r--r--sys/amd64/include/pcpu.h138
-rw-r--r--sys/amd64/include/proc.h1
5 files changed, 113 insertions, 49 deletions
diff --git a/sys/amd64/include/asmacros.h b/sys/amd64/include/asmacros.h
index ec43cda..325e3d6 100644
--- a/sys/amd64/include/asmacros.h
+++ b/sys/amd64/include/asmacros.h
@@ -64,9 +64,9 @@
#define NON_GPROF_RET .byte 0xc3 /* opcode for `ret' */
#ifdef LOCORE
-#define PCPU(member) %fs:GD_ ## member
-#define PCPU_ADDR(member, reg) movl %fs:GD_PRVSPACE,reg; \
- addl $GD_ ## member,reg
+#define PCPU(member) %fs:PC_ ## member
+#define PCPU_ADDR(member, reg) movl %fs:PC_PRVSPACE,reg; \
+ addl $PC_ ## member,reg
#endif
#ifdef GPROF
diff --git a/sys/amd64/include/cpu.h b/sys/amd64/include/cpu.h
index a7783a0..10b9499 100644
--- a/sys/amd64/include/cpu.h
+++ b/sys/amd64/include/cpu.h
@@ -46,7 +46,6 @@
#include <machine/psl.h>
#include <machine/frame.h>
#include <machine/segments.h>
-#include <machine/globals.h>
/*
* definitions of cpu-dependent requirements
diff --git a/sys/amd64/include/mptable.h b/sys/amd64/include/mptable.h
index 13144b9..9d86dae 100644
--- a/sys/amd64/include/mptable.h
+++ b/sys/amd64/include/mptable.h
@@ -71,7 +71,6 @@
#include <machine/smptests.h> /** TEST_DEFAULT_CONFIG, TEST_TEST1 */
#include <machine/tss.h>
#include <machine/specialreg.h>
-#include <machine/globaldata.h>
#include <machine/privatespace.h>
#if defined(APIC_IO)
@@ -477,9 +476,9 @@ init_secondary(void)
gdt_segs[GPRIV_SEL].ssd_base = (int) &SMP_prvspace[myid];
gdt_segs[GPROC0_SEL].ssd_base =
- (int) &SMP_prvspace[myid].globaldata.gd_common_tss;
- SMP_prvspace[myid].globaldata.gd_prvspace =
- &SMP_prvspace[myid].globaldata;
+ (int) &SMP_prvspace[myid].pcpu.pc_common_tss;
+ SMP_prvspace[myid].pcpu.pc_prvspace =
+ &SMP_prvspace[myid].pcpu;
for (x = 0; x < NGDT; x++) {
ssdtosd(&gdt_segs[x], &gdt[myid * NGDT + x].sd);
@@ -1915,7 +1914,7 @@ start_all_aps(u_int boot_addr)
int x, i, pg;
u_char mpbiosreason;
u_long mpbioswarmvec;
- struct globaldata *gd;
+ struct pcpu *pc;
char *stack;
uintptr_t kptbase;
@@ -1955,10 +1954,10 @@ start_all_aps(u_int boot_addr)
pg = x * i386_btop(sizeof(struct privatespace));
/* allocate a new private data page */
- gd = (struct globaldata *)kmem_alloc(kernel_map, PAGE_SIZE);
+ pc = (struct pcpu *)kmem_alloc(kernel_map, PAGE_SIZE);
/* wire it into the private page table page */
- SMPpt[pg] = (pt_entry_t)(PG_V | PG_RW | vtophys(gd));
+ SMPpt[pg] = (pt_entry_t)(PG_V | PG_RW | vtophys(pc));
/* allocate and set up an idle stack data page */
stack = (char *)kmem_alloc(kernel_map, KSTACK_PAGES * PAGE_SIZE); /* XXXKSE */
@@ -1967,8 +1966,7 @@ start_all_aps(u_int boot_addr)
(PG_V | PG_RW | vtophys(PAGE_SIZE * i + stack));
/* prime data page for it to use */
- gd->gd_cpuid = x;
- globaldata_register(gd);
+ pcpu_init(pc, x, sizeof(struct pcpu));
/* setup a vector to our boot code */
*((volatile u_short *) WARMBOOT_OFF) = WARMBOOT_TARGET;
diff --git a/sys/amd64/include/pcpu.h b/sys/amd64/include/pcpu.h
index 46c26c4..5fecb98 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_ */
diff --git a/sys/amd64/include/proc.h b/sys/amd64/include/proc.h
index 911f6b8..5b50824 100644
--- a/sys/amd64/include/proc.h
+++ b/sys/amd64/include/proc.h
@@ -37,7 +37,6 @@
#ifndef _MACHINE_PROC_H_
#define _MACHINE_PROC_H_
-#include <machine/globals.h>
#include <machine/segments.h>
struct proc_ldt {
OpenPOWER on IntegriCloud