kernel - Fix crypto boots and rescue boots
authorMatthew Dillon <dillon@apollo.backplane.com>
Sat, 12 Jul 2014 18:49:13 +0000 (11:49 -0700)
committerMatthew Dillon <dillon@apollo.backplane.com>
Sat, 12 Jul 2014 18:49:13 +0000 (11:49 -0700)
* The kernel text+data+bss is too big, the loader's 64MB heap can't fit
  it plus modules plus the initrd image any more.  Fix by reducing the
  kernel's BSS.

* Reduce the BSS allocation for CPU_prvspace[] from 11MB (45056 x 256 cpus)
  to ~45056 for the BSP and dynamically allocate the globaldata space for
  the APs.  Also saves ~11MB of ram or so on normal systems.

* Reduce the BSS allocation for cpu_map_entry_init[].  Only the BSP needs
  MAXCPU+1 pre-cached vm_map_entry structures.  The APs can make due with
  8 or so before the VM system comes up sufficiently to dynamically allocate
  these structures.  This saves around ~6.5MB of ram on normal systems.

sys/ddb/db_ps.c
sys/platform/pc64/include/globaldata.h
sys/platform/pc64/x86_64/global.s
sys/platform/pc64/x86_64/machdep.c
sys/platform/pc64/x86_64/mp_machdep.c
sys/vm/vm_map.c

index aaab223..63dfeb9 100644 (file)
@@ -102,7 +102,7 @@ db_ps(db_expr_t dummy1, boolean_t dummy2, db_expr_t dummy3, char *dummy4)
         * Dump running threads
         */
        for (cpuidx = 0; cpuidx < ncpus; ++cpuidx) {
-           struct globaldata *gd = &CPU_prvspace[cpuidx].mdglobaldata.mi;
+           struct globaldata *gd = globaldata_find(cpuidx);
            thread_t td;
            int j;
 
index 0c40928..4c5efa3 100644 (file)
@@ -129,7 +129,7 @@ struct privatespace {
 
 #ifdef _KERNEL
 
-extern struct privatespace CPU_prvspace[];
+extern struct privatespace *CPU_prvspace[];
 
 #endif
 
index fcdc193..4cd9d07 100644 (file)
         * segment.
         */
        .data
-#if JG
-       .globl  CPU_prvspace, lapic
-       .set    CPU_prvspace,(MPPTDI << PDRSHIFT)
-       /* JG TODO check for correctness */
-       .set    lapic,CPU_prvspace + (NPTEPG-1) * PAGE_SIZE
-#endif
 
        .globl  globaldata
        .set    globaldata,0
index cf6ffe3..630e6e7 100644 (file)
@@ -159,7 +159,8 @@ SYSINIT(cpu_finish, SI_BOOT2_FINISH_CPU, SI_ORDER_FIRST, cpu_finish, NULL)
 extern vm_offset_t ksym_start, ksym_end;
 #endif
 
-struct privatespace CPU_prvspace[MAXCPU] __aligned(4096); /* XXX */
+struct privatespace CPU_prvspace_bsp __aligned(4096);
+struct privatespace *CPU_prvspace[MAXCPU] = { &CPU_prvspace_bsp };
 
 int    _udatasel, _ucodesel, _ucode32sel;
 u_long atdevbase;
@@ -1917,7 +1918,7 @@ hammer_time(u_int64_t modulep, u_int64_t physfree)
        /*
         * Prevent lowering of the ipl if we call tsleep() early.
         */
-       gd = &CPU_prvspace[0].mdglobaldata;
+       gd = &CPU_prvspace[0]->mdglobaldata;
        bzero(gd, sizeof(*gd));
 
        /*
@@ -1977,9 +1978,9 @@ hammer_time(u_int64_t modulep, u_int64_t physfree)
         * make gdt memory segments
         */
        gdt_segs[GPROC0_SEL].ssd_base =
-               (uintptr_t) &CPU_prvspace[0].mdglobaldata.gd_common_tss;
+               (uintptr_t) &CPU_prvspace[0]->mdglobaldata.gd_common_tss;
 
-       gd->mi.gd_prvspace = &CPU_prvspace[0];
+       gd->mi.gd_prvspace = CPU_prvspace[0];
 
        for (x = 0; x < NGDT; x++) {
                if (x != GPROC0_SEL && x != (GPROC0_SEL + 1))
@@ -2184,13 +2185,20 @@ cpu_gdinit(struct mdglobaldata *gd, int cpu)
        *(void **)gd->mi.gd_idlethread.td_sp = cpu_idle_restore;
 }
 
+/*
+ * We only have to check for DMAP bounds, the globaldata space is
+ * actually part of the kernel_map so we don't have to waste time
+ * checking CPU_prvspace[*].
+ */
 int
 is_globaldata_space(vm_offset_t saddr, vm_offset_t eaddr)
 {
+#if 0
        if (saddr >= (vm_offset_t)&CPU_prvspace[0] &&
            eaddr <= (vm_offset_t)&CPU_prvspace[MAXCPU]) {
                return (TRUE);
        }
+#endif
        if (saddr >= DMAP_MIN_ADDRESS && eaddr <= DMAP_MAX_ADDRESS)
                return (TRUE);
        return (FALSE);
@@ -2200,7 +2208,7 @@ struct globaldata *
 globaldata_find(int cpu)
 {
        KKASSERT(cpu >= 0 && cpu < ncpus);
-       return(&CPU_prvspace[cpu].mdglobaldata.mi);
+       return(&CPU_prvspace[cpu]->mdglobaldata.mi);
 }
 
 int
index ffd399e..fedecdc 100644 (file)
@@ -235,7 +235,7 @@ init_secondary(void)
        struct mdglobaldata *md;
        struct privatespace *ps;
 
-       ps = &CPU_prvspace[myid];
+       ps = CPU_prvspace[myid];
 
        gdt_segs[GPROC0_SEL].ssd_base =
                (long) &ps->mdglobaldata.gd_common_tss;
@@ -347,6 +347,7 @@ start_all_aps(u_int boot_addr)
 {
        vm_offset_t va = boot_address + KERNBASE;
        u_int64_t *pt4, *pt3, *pt2;
+       int     pssize;
        int     x, i;
        int     shift;
        int     smicount;
@@ -433,15 +434,15 @@ start_all_aps(u_int boot_addr)
        for (x = 1; x <= naps; ++x) {
                /* This is a bit verbose, it will go away soon.  */
 
+               pssize = sizeof(struct privatespace);
+               ps = (void *)kmem_alloc(&kernel_map, pssize);
+               CPU_prvspace[x] = ps;
 #if 0
-               /* allocate new private data page(s) */
-               gd = (struct mdglobaldata *)kmem_alloc(&kernel_map, 
-                               MDGLOBALDATA_BASEALLOC_SIZE);
+               kprintf("ps %d %p %d\n", x, ps, pssize);
 #endif
-
-               gd = &CPU_prvspace[x].mdglobaldata;     /* official location */
-               bzero(gd, sizeof(*gd));
-               gd->mi.gd_prvspace = ps = &CPU_prvspace[x];
+               bzero(ps, pssize);
+               gd = &ps->mdglobaldata;
+               gd->mi.gd_prvspace = ps;
 
                /* prime data page for it to use */
                mi_gdinit(&gd->mi, x);
index 537c95a..b488606 100644 (file)
@@ -141,14 +141,16 @@ struct sysref_class vmspace_sysref_class = {
  * per-cpu page table cross mappings are initialized in early boot
  * and might require a considerable number of vm_map_entry structures.
  */
-#define VMEPERCPU      (MAXCPU+1)
+#define MAPENTRYBSP_CACHE      (MAXCPU+1)
+#define MAPENTRYAP_CACHE       8
 
 static struct vm_zone mapentzone_store, mapzone_store;
 static vm_zone_t mapentzone, mapzone;
 static struct vm_object mapentobj, mapobj;
 
 static struct vm_map_entry map_entry_init[MAX_MAPENT];
-static struct vm_map_entry cpu_map_entry_init[MAXCPU][VMEPERCPU];
+static struct vm_map_entry cpu_map_entry_init_bsp[MAPENTRYBSP_CACHE];
+static struct vm_map_entry cpu_map_entry_init_ap[MAXCPU][MAPENTRYAP_CACHE];
 static struct vm_map map_init[MAX_KMAP];
 
 static int randomize_mmap;
@@ -628,16 +630,27 @@ vm_map_entry_allocate_object(vm_map_entry_t entry)
  * vm_map_entry_reserve().
  *
  * Called from the low level boot code only (for each cpu)
+ *
+ * WARNING! Take care not to have too-big a static/BSS structure here
+ *         as MAXCPU can be 256+, otherwise the loader's 64MB heap
+ *         can get blown out by the kernel plus the initrd image.
  */
 void
 vm_map_entry_reserve_cpu_init(globaldata_t gd)
 {
        vm_map_entry_t entry;
+       int count;
        int i;
 
        gd->gd_vme_avail -= MAP_RESERVE_COUNT * 2;
-       entry = &cpu_map_entry_init[gd->gd_cpuid][0];
-       for (i = 0; i < VMEPERCPU; ++i, ++entry) {
+       if (gd->gd_cpuid == 0) {
+               entry = &cpu_map_entry_init_bsp[0];
+               count = MAPENTRYBSP_CACHE;
+       } else {
+               entry = &cpu_map_entry_init_ap[gd->gd_cpuid][0];
+               count = MAPENTRYAP_CACHE;
+       }
+       for (i = 0; i < count; ++i, ++entry) {
                entry->next = gd->gd_vme_base;
                gd->gd_vme_base = entry;
        }