diff options
author | jhb <jhb@FreeBSD.org> | 2001-12-11 23:33:44 +0000 |
---|---|---|
committer | jhb <jhb@FreeBSD.org> | 2001-12-11 23:33:44 +0000 |
commit | 21b6b26912b00bb37f9f16080ba7d49241814935 (patch) | |
tree | c785835e70070309148a72c55669ff0bf043a20a /sys/amd64/include | |
parent | 279222ba62c185d7d7ec09017bb3e7760fd333f0 (diff) | |
download | FreeBSD-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.h | 6 | ||||
-rw-r--r-- | sys/amd64/include/cpu.h | 1 | ||||
-rw-r--r-- | sys/amd64/include/mptable.h | 16 | ||||
-rw-r--r-- | sys/amd64/include/pcpu.h | 138 | ||||
-rw-r--r-- | sys/amd64/include/proc.h | 1 |
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 { |