summaryrefslogtreecommitdiffstats
path: root/sys/powerpc
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/powerpc
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/powerpc')
-rw-r--r--sys/powerpc/aim/mmu_oea.c15
-rw-r--r--sys/powerpc/aim/mmu_oea64.c15
-rw-r--r--sys/powerpc/booke/pmap.c6
-rw-r--r--sys/powerpc/powerpc/elf_machdep.c2
-rw-r--r--sys/powerpc/powerpc/mp_machdep.c4
5 files changed, 41 insertions, 1 deletions
diff --git a/sys/powerpc/aim/mmu_oea.c b/sys/powerpc/aim/mmu_oea.c
index 7eb4beb..bbf2e04 100644
--- a/sys/powerpc/aim/mmu_oea.c
+++ b/sys/powerpc/aim/mmu_oea.c
@@ -669,6 +669,7 @@ moea_bootstrap(mmu_t mmup, vm_offset_t kernelstart, vm_offset_t kernelend)
int ofw_mappings;
vm_size_t size, physsz, hwphyssz;
vm_offset_t pa, va, off;
+ void *dpcpu;
/*
* Set up BAT0 to map the lowest 256 MB area
@@ -938,6 +939,20 @@ moea_bootstrap(mmu_t mmup, vm_offset_t kernelstart, vm_offset_t kernelend)
pa += PAGE_SIZE;
va += PAGE_SIZE;
}
+
+ /*
+ * Allocate virtual address space for the dynamic percpu area.
+ */
+ pa = moea_bootstrap_alloc(DPCPU_SIZE, PAGE_SIZE);
+ dpcpu = (void *)virtual_avail;
+ va = virtual_avail;
+ virtual_avail += DPCPU_SIZE;
+ while (va < virtual_avail) {
+ moea_kenter(mmup, va, pa);;
+ pa += PAGE_SIZE;
+ va += PAGE_SIZE;
+ }
+ dpcpu_init(dpcpu, 0);
}
/*
diff --git a/sys/powerpc/aim/mmu_oea64.c b/sys/powerpc/aim/mmu_oea64.c
index 4590363..9f28332 100644
--- a/sys/powerpc/aim/mmu_oea64.c
+++ b/sys/powerpc/aim/mmu_oea64.c
@@ -726,6 +726,7 @@ moea64_bridge_bootstrap(mmu_t mmup, vm_offset_t kernelstart, vm_offset_t kernele
vm_size_t size, physsz, hwphyssz;
vm_offset_t pa, va, off;
uint32_t msr;
+ void *dpcpu;
/* We don't have a direct map since there is no BAT */
hw_direct_map = 0;
@@ -1027,6 +1028,20 @@ moea64_bridge_bootstrap(mmu_t mmup, vm_offset_t kernelstart, vm_offset_t kernele
pa += PAGE_SIZE;
va += PAGE_SIZE;
}
+
+ /*
+ * Allocate virtual address space for the dynamic percpu area.
+ */
+ pa = moea64_bootstrap_alloc(DPCPU_SIZE, PAGE_SIZE);
+ dpcpu = (void *)virtual_avail;
+ va = virtual_avail;
+ virtual_avail += DPCPU_SIZE;
+ while (va < virtual_avail) {
+ moea64_kenter(mmup, va, pa);;
+ pa += PAGE_SIZE;
+ va += PAGE_SIZE;
+ }
+ dpcpu_init(dpcpu, 0);
}
/*
diff --git a/sys/powerpc/booke/pmap.c b/sys/powerpc/booke/pmap.c
index 904424d..d96c09a 100644
--- a/sys/powerpc/booke/pmap.c
+++ b/sys/powerpc/booke/pmap.c
@@ -963,6 +963,7 @@ mmu_booke_bootstrap(mmu_t mmu, vm_offset_t start, vm_offset_t kernelend)
vm_size_t physsz, hwphyssz, kstack0_sz;
vm_offset_t kernel_pdir, kstack0, va;
vm_paddr_t kstack0_phys;
+ void *dpcpu;
pte_t *pte;
debugf("mmu_booke_bootstrap: entered\n");
@@ -988,6 +989,11 @@ mmu_booke_bootstrap(mmu_t mmu, vm_offset_t start, vm_offset_t kernelend)
data_end = round_page(data_end);
+ /* Allocate the dynamic per-cpu area. */
+ dpcpu = (void *)data_end;
+ data_end += DPCPU_SIZE;
+ dpcpu_init(dpcpu, 0);
+
/* Allocate space for ptbl_bufs. */
ptbl_bufs = (struct ptbl_buf *)data_end;
data_end += sizeof(struct ptbl_buf) * PTBL_BUFS;
diff --git a/sys/powerpc/powerpc/elf_machdep.c b/sys/powerpc/powerpc/elf_machdep.c
index 4946b44..fdf830a 100644
--- a/sys/powerpc/powerpc/elf_machdep.c
+++ b/sys/powerpc/powerpc/elf_machdep.c
@@ -194,7 +194,7 @@ elf_reloc_internal(linker_file_t lf, Elf_Addr relocbase, const void *data,
break;
case R_PPC_RELATIVE: /* word32 B + A */
- *where = relocbase + addend;
+ *where = elf_relocaddr(lf, relocbase + addend);
break;
default:
diff --git a/sys/powerpc/powerpc/mp_machdep.c b/sys/powerpc/powerpc/mp_machdep.c
index 986259f..5516739 100644
--- a/sys/powerpc/powerpc/mp_machdep.c
+++ b/sys/powerpc/powerpc/mp_machdep.c
@@ -146,8 +146,12 @@ cpu_mp_start(void)
goto next;
}
if (cpu.cr_cpuid != bsp.cr_cpuid) {
+ void *dpcpu;
+
pc = &__pcpu[cpu.cr_cpuid];
+ dpcpu = (void *)kmem_alloc(kernel_map, DPCPU_SIZE);
pcpu_init(pc, cpu.cr_cpuid, sizeof(*pc));
+ dpcpu_init(dpcpu, cpu.cr_cpuid);
} else {
pc = pcpup;
pc->pc_cpuid = bsp.cr_cpuid;
OpenPOWER on IntegriCloud