summaryrefslogtreecommitdiffstats
path: root/sys/i386
diff options
context:
space:
mode:
authorjeff <jeff@FreeBSD.org>2009-06-23 22:42:39 +0000
committerjeff <jeff@FreeBSD.org>2009-06-23 22:42:39 +0000
commit5bc3a65e406b90cd9e2a47b79117e453bdb56413 (patch)
tree5644c551dea0298e335cc77383345323c6eb3662 /sys/i386
parentd8bf8e1e8ad280542b4de90763d6d552c4f27b3a (diff)
downloadFreeBSD-src-5bc3a65e406b90cd9e2a47b79117e453bdb56413.zip
FreeBSD-src-5bc3a65e406b90cd9e2a47b79117e453bdb56413.tar.gz
Implement a facility for dynamic per-cpu variables.
- Modules and kernel code alike may use DPCPU_DEFINE(), DPCPU_GET(), DPCPU_SET(), etc. akin to the statically defined PCPU_*. Requires only one extra instruction more than PCPU_* and is virtually the same as __thread for builtin and much faster for shared objects. DPCPU variables can be initialized when defined. - Modules are supported by relocating the module's per-cpu linker set over space reserved in the kernel. Modules may fail to load if there is insufficient space available. - Track space available for modules with a one-off extent allocator. Free may block for memory to allocate space for an extent. Reviewed by: jhb, rwatson, kan, sam, grehan, marius, marcel, stas
Diffstat (limited to 'sys/i386')
-rw-r--r--sys/i386/i386/elf_machdep.c2
-rw-r--r--sys/i386/i386/machdep.c13
-rw-r--r--sys/i386/i386/mp_machdep.c7
-rw-r--r--sys/i386/xen/mp_machdep.c1
4 files changed, 18 insertions, 5 deletions
diff --git a/sys/i386/i386/elf_machdep.c b/sys/i386/i386/elf_machdep.c
index 9f5e3a4..b68a73e 100644
--- a/sys/i386/i386/elf_machdep.c
+++ b/sys/i386/i386/elf_machdep.c
@@ -149,7 +149,7 @@ elf_reloc_internal(linker_file_t lf, Elf_Addr relocbase, const void *data,
if (local) {
if (rtype == R_386_RELATIVE) { /* A + B */
- addr = relocbase + addend;
+ addr = elf_relocaddr(lf, relocbase + addend);
if (*where != addr)
*where = addr;
}
diff --git a/sys/i386/i386/machdep.c b/sys/i386/i386/machdep.c
index a7177f7..abef65e 100644
--- a/sys/i386/i386/machdep.c
+++ b/sys/i386/i386/machdep.c
@@ -2448,7 +2448,7 @@ init386(first)
int first;
{
unsigned long gdtmachpfn;
- int error, gsel_tss, metadata_missing, x;
+ int error, gsel_tss, metadata_missing, x, pa;
struct pcpu *pc;
struct callback_register event = {
.type = CALLBACKTYPE_event,
@@ -2532,6 +2532,11 @@ init386(first)
GSEL(GCODE_SEL, SEL_KPL), (unsigned long)failsafe_callback);
#endif
pcpu_init(pc, 0, sizeof(struct pcpu));
+ for (pa = first; pa < first + DPCPU_SIZE; pa += PAGE_SIZE)
+ pmap_kenter(pa + KERNBASE, pa);
+ dpcpu_init((void *)(first + KERNBASE), 0);
+ first += DPCPU_SIZE;
+
PCPU_SET(prvspace, pc);
PCPU_SET(curthread, &thread0);
PCPU_SET(curpcb, thread0.td_pcb);
@@ -2665,7 +2670,7 @@ init386(first)
int first;
{
struct gate_descriptor *gdp;
- int gsel_tss, metadata_missing, x;
+ int gsel_tss, metadata_missing, x, pa;
struct pcpu *pc;
thread0.td_kstack = proc0kstack;
@@ -2718,6 +2723,10 @@ init386(first)
lgdt(&r_gdt);
pcpu_init(pc, 0, sizeof(struct pcpu));
+ for (pa = first; pa < first + DPCPU_SIZE; pa += PAGE_SIZE)
+ pmap_kenter(pa + KERNBASE, pa);
+ dpcpu_init((void *)(first + KERNBASE), 0);
+ first += DPCPU_SIZE;
PCPU_SET(prvspace, pc);
PCPU_SET(curthread, &thread0);
PCPU_SET(curpcb, thread0.td_pcb);
diff --git a/sys/i386/i386/mp_machdep.c b/sys/i386/i386/mp_machdep.c
index c233f25..0bfe91d 100644
--- a/sys/i386/i386/mp_machdep.c
+++ b/sys/i386/i386/mp_machdep.c
@@ -143,6 +143,7 @@ static int bootAP;
/* Free these after use */
void *bootstacks[MAXCPU];
+static void *dpcpu;
/* Hotwire a 0->4MB V==P mapping */
extern pt_entry_t *KPTphys;
@@ -610,6 +611,7 @@ init_secondary(void)
/* prime data page for it to use */
pcpu_init(pc, myid, sizeof(struct pcpu));
+ dpcpu_init(dpcpu, myid);
pc->pc_apic_id = cpu_apic_ids[myid];
pc->pc_prvspace = pc;
pc->pc_curthread = 0;
@@ -897,8 +899,9 @@ start_all_aps(void)
apic_id = cpu_apic_ids[cpu];
/* allocate and set up a boot stack data page */
- bootstacks[cpu] = (char *)kmem_alloc(kernel_map, KSTACK_PAGES * PAGE_SIZE);
-
+ bootstacks[cpu] =
+ (char *)kmem_alloc(kernel_map, KSTACK_PAGES * PAGE_SIZE);
+ dpcpu = (void *)kmem_alloc(kernel_map, DPCPU_SIZE);
/* setup a vector to our boot code */
*((volatile u_short *) WARMBOOT_OFF) = WARMBOOT_TARGET;
*((volatile u_short *) WARMBOOT_SEG) = (boot_address >> 4);
diff --git a/sys/i386/xen/mp_machdep.c b/sys/i386/xen/mp_machdep.c
index f16d25f..3aa03ce 100644
--- a/sys/i386/xen/mp_machdep.c
+++ b/sys/i386/xen/mp_machdep.c
@@ -744,6 +744,7 @@ start_all_aps(void)
/* Get per-cpu data */
pc = &__pcpu[bootAP];
pcpu_init(pc, bootAP, sizeof(struct pcpu));
+ dpcpu_init((void *)kmem_alloc(kernel_map, DPCPU_SIZE), bootAP);
pc->pc_apic_id = cpu_apic_ids[bootAP];
pc->pc_prvspace = pc;
pc->pc_curthread = 0;
OpenPOWER on IntegriCloud