diff --git a/sys/amd64/amd64/machdep.c b/sys/amd64/amd64/machdep.c index 6993dea..39d1757 100644 --- a/sys/amd64/amd64/machdep.c +++ b/sys/amd64/amd64/machdep.c @@ -1430,7 +1430,8 @@ hammer_time(u_int64_t modulep, u_int64_t physfree) wrmsr(MSR_GSBASE, (u_int64_t)pc); wrmsr(MSR_KGSBASE, 0); /* User value while in the kernel */ - pcpu_init(pc, 0, sizeof(struct pcpu)); + pcpu_init(pc, (void *)(physfree + KERNBASE), 0, sizeof(struct pcpu)); + physfree += DPCPU_SIZE; PCPU_SET(prvspace, pc); PCPU_SET(curthread, &thread0); PCPU_SET(curpcb, thread0.td_pcb); diff --git a/sys/amd64/amd64/mp_machdep.c b/sys/amd64/amd64/mp_machdep.c index a989d10..36736f2 100644 --- a/sys/amd64/amd64/mp_machdep.c +++ b/sys/amd64/amd64/mp_machdep.c @@ -93,9 +93,10 @@ static int bootAP; /* Free these after use */ void *bootstacks[MAXCPU]; -/* Temporary holder for double fault stack */ +/* Temporary variables for init_secondary() */ char *doublefault_stack; char *nmi_stack; +void *dpcpu; /* Hotwire a 0->4MB V==P mapping */ extern pt_entry_t *KPTphys; @@ -589,7 +590,7 @@ init_secondary(void) pc = &__pcpu[cpu]; /* prime data page for it to use */ - pcpu_init(pc, cpu, sizeof(struct pcpu)); + pcpu_init(pc, dpcpu, cpu, sizeof(struct pcpu)); pc->pc_apic_id = cpu_apic_ids[cpu]; pc->pc_prvspace = pc; pc->pc_curthread = 0; @@ -885,6 +886,7 @@ start_all_aps(void) bootstacks[cpu] = (void *)kmem_alloc(kernel_map, KSTACK_PAGES * PAGE_SIZE); doublefault_stack = (char *)kmem_alloc(kernel_map, PAGE_SIZE); nmi_stack = (char *)kmem_alloc(kernel_map, PAGE_SIZE); + dpcpu = (void *)kmem_alloc(kernel_map, DPCPU_SIZE); bootSTK = (char *)bootstacks[cpu] + KSTACK_PAGES * PAGE_SIZE - 8; bootAP = cpu; diff --git a/sys/arm/at91/at91_machdep.c b/sys/arm/at91/at91_machdep.c index af7f97c..3fb1604 100644 --- a/sys/arm/at91/at91_machdep.c +++ b/sys/arm/at91/at91_machdep.c @@ -226,10 +226,11 @@ initarm(void *arg, void *arg2) boot_arg2 = arg2; set_cpufuncs(); lastaddr = fake_preload_metadata(); - pcpu_init(pcpup, 0, sizeof(struct pcpu)); + freemempos = (lastaddr + PAGE_MASK) & ~PAGE_MASK; + pcpu_init(pcpup, (void *)freemempos, 0, sizeof(struct pcpu)); + freemempos += DPCPU_SIZE; PCPU_SET(curthread, &thread0); - freemempos = (lastaddr + PAGE_MASK) & ~PAGE_MASK; /* Define a macro to simplify memory allocation */ #define valloc_pages(var, np) \ alloc_pages((var).pv_va, (np)); \ diff --git a/sys/arm/mv/mv_machdep.c b/sys/arm/mv/mv_machdep.c index 1c00eb5..5d42b18 100644 --- a/sys/arm/mv/mv_machdep.c +++ b/sys/arm/mv/mv_machdep.c @@ -425,7 +425,9 @@ initarm(void *mdp, void *unused __unused) if (platform_pmap_init() != 0) return (NULL); - pcpu_init(pcpup, 0, sizeof(struct pcpu)); + freemempos = (lastaddr + PAGE_MASK) & ~PAGE_MASK; + pcpu_init(pcpup, (void *)freemempos, 0, sizeof(struct pcpu)); + freemempos += DPCPU_SIZE; PCPU_SET(curthread, &thread0); /* Calculate number of L2 tables needed for mapping vm_page_array */ @@ -442,7 +444,6 @@ initarm(void *mdp, void *unused __unused) l2size = (l2size + 3) & ~3; #define KERNEL_TEXT_BASE (KERNBASE) - freemempos = (lastaddr + PAGE_MASK) & ~PAGE_MASK; /* Define a macro to simplify memory allocation */ #define valloc_pages(var, np) \ diff --git a/sys/arm/sa11x0/assabet_machdep.c b/sys/arm/sa11x0/assabet_machdep.c index 71d71da..8a9ee34 100644 --- a/sys/arm/sa11x0/assabet_machdep.c +++ b/sys/arm/sa11x0/assabet_machdep.c @@ -222,16 +222,17 @@ initarm(void *arg, void *arg2) set_cpufuncs(); lastaddr = fake_preload_metadata(); physmem = memsize / PAGE_SIZE; - pc = &__pcpu; - pcpu_init(pc, 0, sizeof(struct pcpu)); - PCPU_SET(curthread, &thread0); - physical_start = (vm_offset_t) KERNBASE; physical_end = lastaddr; physical_freestart = (((vm_offset_t)physical_end) + PAGE_MASK) & ~PAGE_MASK; md_addr.pv_va = md_addr.pv_pa = MDROOT_ADDR; freemempos = (vm_offset_t)round_page(physical_freestart); memset((void *)freemempos, 0, 256*1024); + pc = &__pcpu; + pcpu_init(pc, (void *)freemempos, 0, sizeof(struct pcpu)); + freemempos += DPCPU_SIZE; + PCPU_SET(curthread, &thread0); + /* Define a macro to simplify memory allocation */ #define valloc_pages(var, np) \ alloc_pages((var).pv_pa, (np)); \ diff --git a/sys/arm/xscale/i80321/ep80219_machdep.c b/sys/arm/xscale/i80321/ep80219_machdep.c index 77fad07..3fe2580 100644 --- a/sys/arm/xscale/i80321/ep80219_machdep.c +++ b/sys/arm/xscale/i80321/ep80219_machdep.c @@ -197,10 +197,11 @@ initarm(void *arg, void *arg2) set_cpufuncs(); lastaddr = fake_preload_metadata(); - pcpu_init(pcpup, 0, sizeof(struct pcpu)); + freemempos = 0xa0200000; + freemempos -= DPCPU_SIZE; + pcpu_init(pcpup, (void *)freemempos, 0, sizeof(struct pcpu)); PCPU_SET(curthread, &thread0); - freemempos = 0xa0200000; /* Define a macro to simplify memory allocation */ #define valloc_pages(var, np) \ alloc_pages((var).pv_pa, (np)); \ diff --git a/sys/arm/xscale/i80321/iq31244_machdep.c b/sys/arm/xscale/i80321/iq31244_machdep.c index ba0fd93..065473c 100644 --- a/sys/arm/xscale/i80321/iq31244_machdep.c +++ b/sys/arm/xscale/i80321/iq31244_machdep.c @@ -198,10 +198,11 @@ initarm(void *arg, void *arg2) set_cpufuncs(); lastaddr = fake_preload_metadata(); - pcpu_init(pcpup, 0, sizeof(struct pcpu)); + freemempos = 0xa0200000; + freemempos -= DPCPU_SIZE; + pcpu_init(pcpup, (void *)freemempos, sizeof(struct pcpu)); PCPU_SET(curthread, &thread0); - freemempos = 0xa0200000; /* Define a macro to simplify memory allocation */ #define valloc_pages(var, np) \ alloc_pages((var).pv_pa, (np)); \ diff --git a/sys/arm/xscale/i8134x/crb_machdep.c b/sys/arm/xscale/i8134x/crb_machdep.c index 909a1cd..0220629 100644 --- a/sys/arm/xscale/i8134x/crb_machdep.c +++ b/sys/arm/xscale/i8134x/crb_machdep.c @@ -194,10 +194,11 @@ initarm(void *arg, void *arg2) set_cpufuncs(); lastaddr = fake_preload_metadata(); - pcpu_init(pcpup, 0, sizeof(struct pcpu)); + freemempos = 0x00200000; + freemempos -= DPCPU_SIZE; + pcpu_init(pcpup, (void *)freemempos, 0, sizeof(struct pcpu)); PCPU_SET(curthread, &thread0); - freemempos = 0x00200000; /* Define a macro to simplify memory allocation */ #define valloc_pages(var, np) \ alloc_pages((var).pv_pa, (np)); \ diff --git a/sys/arm/xscale/ixp425/avila_machdep.c b/sys/arm/xscale/ixp425/avila_machdep.c index d199796..fd290c5 100644 --- a/sys/arm/xscale/ixp425/avila_machdep.c +++ b/sys/arm/xscale/ixp425/avila_machdep.c @@ -236,7 +236,9 @@ initarm(void *arg, void *arg2) set_cpufuncs(); /* NB: sets cputype */ lastaddr = fake_preload_metadata(); - pcpu_init(pcpup, 0, sizeof(struct pcpu)); + freemempos = KERNPHYSADDR; + freemempos -= DPCPU_SIZE; + pcpu_init(pcpup, (void *)freemempos, 0, sizeof(struct pcpu)); PCPU_SET(curthread, &thread0); /* @@ -248,7 +250,6 @@ initarm(void *arg, void *arg2) * write-through). Note this leaves a gap for expansion * (or might be repurposed). */ - freemempos = KERNPHYSADDR; /* macros to simplify initial memory allocation */ #define alloc_pages(var, np) do { \ diff --git a/sys/arm/xscale/pxa/pxa_machdep.c b/sys/arm/xscale/pxa/pxa_machdep.c index f3b137e..da5abc4 100644 --- a/sys/arm/xscale/pxa/pxa_machdep.c +++ b/sys/arm/xscale/pxa/pxa_machdep.c @@ -179,10 +179,11 @@ initarm(void *arg, void *arg2) set_cpufuncs(); lastaddr = fake_preload_metadata(); - pcpu_init(pcpup, 0, sizeof(struct pcpu)); + freemempos = 0xa0200000; + freemempos -= DPCPU_SIZE; + pcpu_init(pcpup, (void *)freemempos, 0, sizeof(struct pcpu)); PCPU_SET(curthread, &thread0); - freemempos = 0xa0200000; /* Define a macro to simplify memory allocation */ #define valloc_pages(var, np) \ alloc_pages((var).pv_pa, (np)); \ diff --git a/sys/i386/i386/locore.s b/sys/i386/i386/locore.s index 94ac670..aaa90e6 100644 --- a/sys/i386/i386/locore.s +++ b/sys/i386/i386/locore.s @@ -121,6 +121,12 @@ vm86phystk: .long 0 /* PA of vm86/bios stack */ vm86paddr: .long 0 /* address of vm86 region */ vm86pa: .long 0 /* phys addr of vm86 region */ + .globl __start_set_pcpu, __stop_set_pcpu + .globl dpcpu0_base +dpcpu0_pa: .long 0 +dpcpu0_base: .long 0 +dpcpu0_sz: .long 0 + #ifdef PC98 .globl pc98_system_parameter pc98_system_parameter: @@ -735,6 +741,22 @@ no_kernend: addl $KERNBASE, %esi movl %esi, R(proc0kstack) +/* Calculate the size of dpcpu0 */ + movl $__stop_set_pcpu,%eax + subl $__start_set_pcpu,%eax + addl $(PAGE_SIZE-1),%eax + andl $~(PAGE_SIZE-1),%eax + movl %eax,R(dpcpu0_sz) + +/* Inlined ALLOCPAGES to allocate dpcpu0 */ + movl R(physfree), %esi + addl %esi, %eax + movl %eax, R(physfree) + + movl %esi, R(dpcpu0_pa) + addl $KERNBASE, %esi + movl %esi, R(dpcpu0_base) + ALLOCPAGES(1) /* vm86/bios stack */ movl %esi,R(vm86phystk) @@ -793,6 +815,10 @@ no_kernend: movl $NPGPTD, %ecx fillkptphys($PG_RW) + movl R(dpcpu0_pa), %eax + movl R(dpcpu0_sz), %ecx + fillkptphys($PG_RW) + /* Map proc0's KSTACK in the physical way ... */ movl R(p0kpa), %eax movl $(KSTACK_PAGES), %ecx diff --git a/sys/i386/i386/machdep.c b/sys/i386/i386/machdep.c index e64bcd2..77ac947 100644 --- a/sys/i386/i386/machdep.c +++ b/sys/i386/i386/machdep.c @@ -2369,6 +2369,8 @@ do_next: PT_UPDATES_FLUSH(); } +extern unsigned long dpcpu0_base; + #ifdef XEN #define MTOPSIZE (1<<(14 + PAGE_SHIFT)) @@ -2460,7 +2462,8 @@ init386(first) (unsigned long)Xhypervisor_callback, GSEL(GCODE_SEL, SEL_KPL), (unsigned long)failsafe_callback); #endif - pcpu_init(pc, 0, sizeof(struct pcpu)); + pcpu_init(pc, (void *)(first + KERNBASE), 0, sizeof(struct pcpu)); + first += DPCPU_SIZE; PCPU_SET(prvspace, pc); PCPU_SET(curthread, &thread0); PCPU_SET(curpcb, thread0.td_pcb); @@ -2643,7 +2646,7 @@ init386(first) mtx_init(&dt_lock, "descriptor tables", NULL, MTX_SPIN); lgdt(&r_gdt); - pcpu_init(pc, 0, sizeof(struct pcpu)); + pcpu_init(pc, (void *)dpcpu0_base, 0, sizeof(struct pcpu)); 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..3fbccc0 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; @@ -609,7 +610,7 @@ init_secondary(void) pc = &__pcpu[myid]; /* prime data page for it to use */ - pcpu_init(pc, myid, sizeof(struct pcpu)); + pcpu_init(pc, dpcpu, myid, sizeof(struct pcpu)); pc->pc_apic_id = cpu_apic_ids[myid]; pc->pc_prvspace = pc; pc->pc_curthread = 0; @@ -897,8 +898,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/i386/pmap.c b/sys/i386/i386/pmap.c index 5d7dc97..2162b65 100644 --- a/sys/i386/i386/pmap.c +++ b/sys/i386/i386/pmap.c @@ -414,6 +414,8 @@ pmap_bootstrap(vm_paddr_t firstaddr) mtx_init(&sysmaps->lock, "SYSMAPS", NULL, MTX_DEF); SYSMAP(caddr_t, sysmaps->CMAP1, sysmaps->CADDR1, 1) SYSMAP(caddr_t, sysmaps->CMAP2, sysmaps->CADDR2, 1) + *(sysmaps->CMAP1) = 0; + *(sysmaps->CMAP2) = 0; } SYSMAP(caddr_t, CMAP1, CADDR1, 1) SYSMAP(caddr_t, CMAP3, CADDR3, 1) diff --git a/sys/i386/xen/mp_machdep.c b/sys/i386/xen/mp_machdep.c index f16d25f..04468b9 100644 --- a/sys/i386/xen/mp_machdep.c +++ b/sys/i386/xen/mp_machdep.c @@ -743,7 +743,8 @@ start_all_aps(void) /* Get per-cpu data */ pc = &__pcpu[bootAP]; - pcpu_init(pc, bootAP, sizeof(struct pcpu)); + pcpu_init(pc, (void *)kmem_alloc(kernel_map, DPCPU_SIZE), + bootAP, sizeof(struct pcpu)); pc->pc_apic_id = cpu_apic_ids[bootAP]; pc->pc_prvspace = pc; pc->pc_curthread = 0; diff --git a/sys/ia64/ia64/machdep.c b/sys/ia64/ia64/machdep.c index dda1a08..8bc260c 100644 --- a/sys/ia64/ia64/machdep.c +++ b/sys/ia64/ia64/machdep.c @@ -647,13 +647,26 @@ ia64_init(void) bootverbose = 1; /* + * Find the beginning and end of the kernel. + */ + kernstart = trunc_page(kernel_text); +#ifdef DDB + ksym_start = bootinfo.bi_symtab; + ksym_end = bootinfo.bi_esymtab; + kernend = (vm_offset_t)round_page(ksym_end); +#else + kernend = (vm_offset_t)round_page(_end); +#endif + + /* * Setup the PCPU data for the bootstrap processor. It is needed * by printf(). Also, since printf() has critical sections, we * need to initialize at least pc_curthread. */ pcpup = &pcpu0; ia64_set_k4((u_int64_t)pcpup); - pcpu_init(pcpup, 0, sizeof(pcpu0)); + pcpu_init(pcpup, (void *)kernend, 0, sizeof(pcpu0)); + kernend += DPCPU_SIZE; PCPU_SET(curthread, &thread0); /* @@ -682,18 +695,6 @@ ia64_init(void) ia64_sal_init(); calculate_frequencies(); - /* - * Find the beginning and end of the kernel. - */ - kernstart = trunc_page(kernel_text); -#ifdef DDB - ksym_start = bootinfo.bi_symtab; - ksym_end = bootinfo.bi_esymtab; - kernend = (vm_offset_t)round_page(ksym_end); -#else - kernend = (vm_offset_t)round_page(_end); -#endif - /* But if the bootstrap tells us otherwise, believe it! */ if (bootinfo.bi_kernend) kernend = round_page(bootinfo.bi_kernend); diff --git a/sys/ia64/ia64/mp_machdep.c b/sys/ia64/ia64/mp_machdep.c index 6dba43a..f61d5c8 100644 --- a/sys/ia64/ia64/mp_machdep.c +++ b/sys/ia64/ia64/mp_machdep.c @@ -207,6 +207,7 @@ cpu_mp_add(u_int acpiid, u_int apicid, u_int apiceid) { struct pcpu *pc; u_int64_t lid; + void *dpcpu; /* Ignore any processor numbers outside our range */ if (acpiid > mp_maxid) @@ -224,7 +225,8 @@ cpu_mp_add(u_int acpiid, u_int apicid, u_int apiceid) if (acpiid != 0) { pc = (struct pcpu *)malloc(sizeof(*pc), M_SMP, M_WAITOK); - pcpu_init(pc, acpiid, sizeof(*pc)); + dpcpu = (void *)kmem_alloc(kernel_map, DPCPU_SIZE); + pcpu_init(pc, dpcpu, acpiid, sizeof(*pc)); } else pc = pcpup; diff --git a/sys/kern/subr_pcpu.c b/sys/kern/subr_pcpu.c index 74082c2..c0f7d24 100644 --- a/sys/kern/subr_pcpu.c +++ b/sys/kern/subr_pcpu.c @@ -56,6 +56,9 @@ __FBSDID("$FreeBSD$"); #include #include +DPCPU_DEFINE(int, id); + +uintptr_t dpcpu_ptrs[MAXCPU]; struct pcpu *cpuid_to_pcpu[MAXCPU]; struct cpuhead cpuhead = SLIST_HEAD_INITIALIZER(cpuhead); @@ -63,7 +66,7 @@ struct cpuhead cpuhead = SLIST_HEAD_INITIALIZER(cpuhead); * Initialize the MI portions of a struct pcpu. */ void -pcpu_init(struct pcpu *pcpu, int cpuid, size_t size) +pcpu_init(struct pcpu *pcpu, void *dpcpu, int cpuid, size_t size) { bzero(pcpu, size); @@ -71,6 +74,7 @@ pcpu_init(struct pcpu *pcpu, int cpuid, size_t size) ("pcpu_init: invalid cpuid %d", cpuid)); pcpu->pc_cpuid = cpuid; pcpu->pc_cpumask = 1 << cpuid; + pcpu->pc_dynamic = (uintptr_t)dpcpu; cpuid_to_pcpu[cpuid] = pcpu; SLIST_INSERT_HEAD(&cpuhead, pcpu, pc_allcpu); cpu_pcpu_init(pcpu, cpuid, size); @@ -80,6 +84,17 @@ pcpu_init(struct pcpu *pcpu, int cpuid, size_t size) snprintf(pcpu->pc_name, sizeof(pcpu->pc_name), "CPU %d", cpuid); #endif + /* + * Initialize defaults from our linker section. + */ + memcpy(dpcpu, (void *)DPCPU_START, DPCPU_SIZE); + + /* + * Place it in the global pcpu array. + */ + dpcpu_ptrs[pcpu->pc_cpuid] = pcpu->pc_dynamic; + + DPCPU_ID_SET(pcpu->pc_cpuid, id, pcpu->pc_cpuid); } /* @@ -91,6 +106,7 @@ pcpu_destroy(struct pcpu *pcpu) SLIST_REMOVE(&cpuhead, pcpu, pcpu, pc_allcpu); cpuid_to_pcpu[pcpu->pc_cpuid] = NULL; + dpcpu_ptrs[pcpu->pc_cpuid] = 0; } /* @@ -110,7 +126,9 @@ show_pcpu(struct pcpu *pc) { struct thread *td; - db_printf("cpuid = %d\n", pc->pc_cpuid); + db_printf("cpuid = %d (%d)\n", + pc->pc_cpuid, DPCPU_ID_GET(pc->pc_cpuid, id)); + db_printf("curcpuid = %d\n", DPCPU_GET(id)); db_printf("curthread = "); td = pc->pc_curthread; if (td != NULL) diff --git a/sys/mips/mips/mp_machdep.c b/sys/mips/mips/mp_machdep.c index 3f7d731..6380145 100644 --- a/sys/mips/mips/mp_machdep.c +++ b/sys/mips/mips/mp_machdep.c @@ -224,12 +224,14 @@ static int smp_start_secondary(int cpuid) { struct pcpu *pcpu; + void *dpcpu; int i; if (bootverbose) printf("smp_start_secondary: starting cpu %d\n", cpuid); - pcpu_init(&__pcpu[cpuid], cpuid, sizeof(struct pcpu)); + dpcpu = (void *)kmem_alloc(kernel_map, DPCPU_SIZE); + pcpu_init(&__pcpu[cpuid], dpcpu, cpuid, sizeof(struct pcpu)); if (bootverbose) printf("smp_start_secondary: cpu %d started\n", cpuid); diff --git a/sys/pc98/pc98/machdep.c b/sys/pc98/pc98/machdep.c index 0025a8a..2720256 100644 --- a/sys/pc98/pc98/machdep.c +++ b/sys/pc98/pc98/machdep.c @@ -2009,7 +2009,9 @@ init386(first) mtx_init(&dt_lock, "descriptor tables", NULL, MTX_SPIN); lgdt(&r_gdt); - pcpu_init(pc, 0, sizeof(struct pcpu)); + pcpu_init(pc, (void *)(first + KERNBASE), 0, sizeof(struct pcpu)); + first += DPCPU_SIZE; + PCPU_SET(prvspace, pc); PCPU_SET(curthread, &thread0); PCPU_SET(curpcb, thread0.td_pcb); diff --git a/sys/powerpc/aim/machdep.c b/sys/powerpc/aim/machdep.c index 5d2665a..3dfa8fc 100644 --- a/sys/powerpc/aim/machdep.c +++ b/sys/powerpc/aim/machdep.c @@ -278,7 +278,8 @@ powerpc_init(u_int startkernel, u_int endkernel, u_int basekernel, void *mdp) ksym_end = MD_FETCH(kmdp, MODINFOMD_ESYM, uintptr_t); #endif } - } + } else + end = endkernel; /* * Init params/tunables that can be overridden by the loader @@ -295,7 +296,8 @@ powerpc_init(u_int startkernel, u_int endkernel, u_int basekernel, void *mdp) * Set up per-cpu data. */ pc = __pcpu; - pcpu_init(pc, 0, sizeof(struct pcpu)); + pcpu_init(pc, (void *)end, 0, sizeof(struct pcpu)); + end += DPCPU_SIZE; pc->pc_curthread = &thread0; pc->pc_cpuid = 0; @@ -488,7 +490,7 @@ powerpc_init(u_int startkernel, u_int endkernel, u_int basekernel, void *mdp) else pmap_mmu_install(MMU_TYPE_OEA, BUS_PROBE_GENERIC); - pmap_bootstrap(startkernel, endkernel); + pmap_bootstrap(startkernel, end); mtmsr(mfmsr() | PSL_IR|PSL_DR|PSL_ME|PSL_RI); isync(); diff --git a/sys/powerpc/booke/machdep.c b/sys/powerpc/booke/machdep.c index 8787098..45a3deb 100644 --- a/sys/powerpc/booke/machdep.c +++ b/sys/powerpc/booke/machdep.c @@ -390,7 +390,8 @@ e500_init(u_int32_t startkernel, u_int32_t endkernel, void *mdp) /* Set up per-cpu data and store the pointer in SPR general 0. */ pc = &__pcpu[0]; - pcpu_init(pc, 0, sizeof(struct pcpu)); + pcpu_init(pc, (void *)end, 0, sizeof(struct pcpu)); + end += DPCPU_SIZE; pc->pc_curthread = &thread0; __asm __volatile("mtsprg 0, %0" :: "r"(pc)); diff --git a/sys/powerpc/powerpc/mp_machdep.c b/sys/powerpc/powerpc/mp_machdep.c index 986259f..1428ae5 100644 --- a/sys/powerpc/powerpc/mp_machdep.c +++ b/sys/powerpc/powerpc/mp_machdep.c @@ -146,8 +146,11 @@ cpu_mp_start(void) goto next; } if (cpu.cr_cpuid != bsp.cr_cpuid) { + void *dpcpu; + pc = &__pcpu[cpu.cr_cpuid]; - pcpu_init(pc, cpu.cr_cpuid, sizeof(*pc)); + dpcpu = (void *)kmem_alloc(kernel_map, DPCPU_SIZE); + pcpu_init(pc, dpcpu, cpu.cr_cpuid, sizeof(*pc)); } else { pc = pcpup; pc->pc_cpuid = bsp.cr_cpuid; diff --git a/sys/sparc64/sparc64/machdep.c b/sys/sparc64/sparc64/machdep.c index 164a8b3..52f0ebc 100644 --- a/sys/sparc64/sparc64/machdep.c +++ b/sys/sparc64/sparc64/machdep.c @@ -301,6 +301,15 @@ sparc64_init(caddr_t mdp, u_long o1, u_long o2, u_long o3, ofw_vec_t *vec) } } + /* + * Sanity check the kernel end, which is important. + */ + if (end == 0) { + printf("sparc64_init: warning, kernel end not specified.\n" + "Attempting to continue anyway.\n"); + end = (vm_offset_t)_end; + } + init_param1(); /* @@ -315,7 +324,8 @@ sparc64_init(caddr_t mdp, u_long o1, u_long o2, u_long o3, ofw_vec_t *vec) * or it'll zero it out from under us. */ pc = (struct pcpu *)(pcpu0 + (PCPU_PAGES * PAGE_SIZE)) - 1; - pcpu_init(pc, 0, sizeof(struct pcpu)); + pcpu_init(pc, (void *)end, 0, sizeof(struct pcpu)); + end += DPCPU_SIZE; pc->pc_addr = (vm_offset_t)pcpu0; pc->pc_mid = UPA_CR_GET_MID(ldxa(0, ASI_UPA_CONFIG_REG)); pc->pc_tlb_ctx = TLB_CTX_USER_MIN; @@ -374,15 +384,6 @@ sparc64_init(caddr_t mdp, u_long o1, u_long o2, u_long o3, ofw_vec_t *vec) } /* - * Sanity check the kernel end, which is important. - */ - if (end == 0) { - printf("sparc64_init: warning, kernel end not specified.\n" - "Attempting to continue anyway.\n"); - end = (vm_offset_t)_end; - } - - /* * Determine the TLB slot maxima, which are expected to be * equal across all CPUs. * NB: for Cheetah-class CPUs, these properties only refer diff --git a/sys/sparc64/sparc64/mp_machdep.c b/sys/sparc64/sparc64/mp_machdep.c index ee4ffe7..d211c1e 100644 --- a/sys/sparc64/sparc64/mp_machdep.c +++ b/sys/sparc64/sparc64/mp_machdep.c @@ -289,7 +289,8 @@ cpu_mp_start(void) va = kmem_alloc(kernel_map, PCPU_PAGES * PAGE_SIZE); pc = (struct pcpu *)(va + (PCPU_PAGES * PAGE_SIZE)) - 1; - pcpu_init(pc, cpuid, sizeof(*pc)); + pcpu_init(pc, (void *)kmem_alloc(kernel_map, DPCPU_SIZE), + cpuid, sizeof(*pc)); pc->pc_addr = va; pc->pc_clock = clock; pc->pc_mid = mid; diff --git a/sys/sun4v/sun4v/machdep.c b/sys/sun4v/sun4v/machdep.c index 7975040..48accdc 100644 --- a/sys/sun4v/sun4v/machdep.c +++ b/sys/sun4v/sun4v/machdep.c @@ -339,6 +339,15 @@ sparc64_init(caddr_t mdp, u_long o1, u_long o2, u_long o3, ofw_vec_t *vec) } } + /* + * Sanity check the kernel end, which is important. + */ + if (end == 0) { + printf("sparc64_init: warning, kernel end not specified.\n" + "Attempting to continue anyway.\n"); + end = (vm_offset_t)_end; + } + if (boothowto & RB_VERBOSE) bootverbose = 1; @@ -385,7 +394,8 @@ sparc64_init(caddr_t mdp, u_long o1, u_long o2, u_long o3, ofw_vec_t *vec) * it'll zero it out from under us. */ pc = (struct pcpu *)(pcpu0 + (PCPU_PAGES * PAGE_SIZE)) - 1; - pcpu_init(pc, 0, sizeof(struct pcpu)); + pcpu_init(pc, (void *)end, 0, sizeof(struct pcpu)); + end += DPCPU_SIZE; pc->pc_curthread = &thread0; pc->pc_addr = (vm_offset_t)pcpu0; @@ -405,15 +415,6 @@ sparc64_init(caddr_t mdp, u_long o1, u_long o2, u_long o3, ofw_vec_t *vec) panic("sparc64_init"); } - /* - * Sanity check the kernel end, which is important. - */ - if (end == 0) { - printf("sparc64_init: warning, kernel end not specified.\n" - "Attempting to continue anyway.\n"); - end = (vm_offset_t)_end; - } - cpu_block_copy = bcopy; cpu_block_zero = bzero; diff --git a/sys/sun4v/sun4v/mp_machdep.c b/sys/sun4v/sun4v/mp_machdep.c index 5f4f632..cd7b4d3 100644 --- a/sys/sun4v/sun4v/mp_machdep.c +++ b/sys/sun4v/sun4v/mp_machdep.c @@ -323,7 +323,8 @@ cpu_mp_start(void) #endif va = kmem_alloc(kernel_map, PCPU_PAGES * PAGE_SIZE); pc = (struct pcpu *)(va + (PCPU_PAGES * PAGE_SIZE)) - 1; - pcpu_init(pc, cpuid, sizeof(*pc)); + pcpu_init(pc, (void *)kmem_alloc(kernel_map, DPCPU_SIZE), + cpuid, sizeof(*pc)); pc->pc_addr = va; all_cpus |= 1 << cpuid; diff --git a/sys/sys/pcpu.h b/sys/sys/pcpu.h index dc26c1a..ab9c4ef 100644 --- a/sys/sys/pcpu.h +++ b/sys/sys/pcpu.h @@ -45,6 +45,61 @@ struct pcb; struct thread; +/* + * Define a set for pcpu data. + * + * We don't use SET_DECLARE because it defines the set as 'a' when we + * want 'aw'. GCC considers uninitialized data in a seperate section + * writable and there is no generic zero initializer that works for + * structs and scalars. + */ +extern uintptr_t *__start_set_pcpu; +extern uintptr_t *__stop_set_pcpu; +__asm__(".section set_pcpu, \"aw\", @progbits"); +__asm__(".previous"); + +/* + * Array of dynamic pcpu base values. Indexed by id. + */ +extern uintptr_t dpcpu_ptrs[]; + +/* + * Convenience defines. + */ +#define DPCPU_NAME(n) pcpu_entry_##n +#define DPCPU_START (uintptr_t)&__start_set_pcpu +#define DPCPU_STOP (uintptr_t)&__stop_set_pcpu +#define DPCPU_SIZE roundup2(DPCPU_STOP - DPCPU_START, PAGE_SIZE) +#define DPCPU_OFFSET(n) ((uintptr_t)&DPCPU_NAME(n) - DPCPU_START) + +/* + * Declaration and definition. + */ +#define DPCPU_DECLARE(t, n) extern t DPCPU_NAME(n) +#define DPCPU_DEFINE(t, n) t DPCPU_NAME(n) __section("set_pcpu") __used + +/* + * Accessors with a given base. + */ +#define _DPCPU_PTR(b, n) \ + (__typeof(DPCPU_NAME(n))*)((b) + DPCPU_OFFSET(n)) +#define _DPCPU_GET(b, n) (*_DPCPU_PTR(b, n)) +#define _DPCPU_SET(b, n, v) (*_DPCPU_PTR(b, n) = v) + +/* + * Accessors for the current cpu. + */ +#define DPCPU_PTR(n) _DPCPU_PTR(PCPU_GET(dynamic), n) +#define DPCPU_GET(n) (*DPCPU_PTR(n)) +#define DPCPU_SET(n, v) (*DPCPU_PTR(n) = v) + +/* + * Accessors for remote cpus. + */ +#define DPCPU_ID_PTR(i, n) _DPCPU_PTR(dpcpu_ptrs[(i)], n) +#define DPCPU_ID_GET(i, n) (*DPCPU_ID_PTR(i, n)) +#define DPCPU_ID_SET(i, n, v) (*DPCPU_ID_PTR(i, n) = v) + /* * XXXUPS remove as soon as we have per cpu variable * linker sets and can define rm_queue in _rm_lock.h @@ -93,6 +148,11 @@ struct pcpu { struct rm_queue pc_rm_queue; /* + * Dynamic per-cpu data area. + */ + uintptr_t pc_dynamic; + + /* * Keep MD fields last, so that CPU-specific variations on a * single architecture don't result in offset variations of * the machine-independent fields of the pcpu. Even though @@ -132,7 +192,7 @@ void db_show_mdpcpu(struct pcpu *pcpu); void pcpu_destroy(struct pcpu *pcpu); struct pcpu *pcpu_find(u_int cpuid); -void pcpu_init(struct pcpu *pcpu, int cpuid, size_t size); +void pcpu_init(struct pcpu *pcpu, void *dpcpu, int cpuid, size_t size); #endif /* _KERNEL */