diff options
author | jeff <jeff@FreeBSD.org> | 2009-06-23 22:42:39 +0000 |
---|---|---|
committer | jeff <jeff@FreeBSD.org> | 2009-06-23 22:42:39 +0000 |
commit | 5bc3a65e406b90cd9e2a47b79117e453bdb56413 (patch) | |
tree | 5644c551dea0298e335cc77383345323c6eb3662 /sys/i386 | |
parent | d8bf8e1e8ad280542b4de90763d6d552c4f27b3a (diff) | |
download | FreeBSD-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.c | 2 | ||||
-rw-r--r-- | sys/i386/i386/machdep.c | 13 | ||||
-rw-r--r-- | sys/i386/i386/mp_machdep.c | 7 | ||||
-rw-r--r-- | sys/i386/xen/mp_machdep.c | 1 |
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; |