📄 setup.c
字号:
/* * Setup lowcore for boot cpu */ lc_pages = sizeof(void *) == 8 ? 2 : 1; lc = (struct _lowcore *) __alloc_bootmem(lc_pages * PAGE_SIZE, lc_pages * PAGE_SIZE, 0); memset(lc, 0, lc_pages * PAGE_SIZE); lc->restart_psw.mask = PSW_BASE_BITS | PSW_DEFAULT_KEY; lc->restart_psw.addr = PSW_ADDR_AMODE | (unsigned long) restart_int_handler; if (switch_amode) lc->restart_psw.mask |= PSW_ASC_HOME; lc->external_new_psw.mask = psw_kernel_bits; lc->external_new_psw.addr = PSW_ADDR_AMODE | (unsigned long) ext_int_handler; lc->svc_new_psw.mask = psw_kernel_bits | PSW_MASK_IO | PSW_MASK_EXT; lc->svc_new_psw.addr = PSW_ADDR_AMODE | (unsigned long) system_call; lc->program_new_psw.mask = psw_kernel_bits; lc->program_new_psw.addr = PSW_ADDR_AMODE | (unsigned long)pgm_check_handler; lc->mcck_new_psw.mask = psw_kernel_bits & ~PSW_MASK_MCHECK & ~PSW_MASK_DAT; lc->mcck_new_psw.addr = PSW_ADDR_AMODE | (unsigned long) mcck_int_handler; lc->io_new_psw.mask = psw_kernel_bits; lc->io_new_psw.addr = PSW_ADDR_AMODE | (unsigned long) io_int_handler; lc->ipl_device = S390_lowcore.ipl_device; lc->jiffy_timer = -1LL; lc->kernel_stack = ((unsigned long) &init_thread_union) + THREAD_SIZE; lc->async_stack = (unsigned long) __alloc_bootmem(ASYNC_SIZE, ASYNC_SIZE, 0) + ASYNC_SIZE; lc->panic_stack = (unsigned long) __alloc_bootmem(PAGE_SIZE, PAGE_SIZE, 0) + PAGE_SIZE; lc->current_task = (unsigned long) init_thread_union.thread_info.task; lc->thread_info = (unsigned long) &init_thread_union;#ifndef CONFIG_64BIT if (MACHINE_HAS_IEEE) { lc->extended_save_area_addr = (__u32) __alloc_bootmem(PAGE_SIZE, PAGE_SIZE, 0); /* enable extended save area */ __ctl_set_bit(14, 29); }#endif set_prefix((u32)(unsigned long) lc);}static void __initsetup_resources(void){ struct resource *res, *sub_res; int i; code_resource.start = (unsigned long) &_text; code_resource.end = (unsigned long) &_etext - 1; data_resource.start = (unsigned long) &_etext; data_resource.end = (unsigned long) &_edata - 1; for (i = 0; i < MEMORY_CHUNKS && memory_chunk[i].size > 0; i++) { res = alloc_bootmem_low(sizeof(struct resource)); res->flags = IORESOURCE_BUSY | IORESOURCE_MEM; switch (memory_chunk[i].type) { case CHUNK_READ_WRITE: res->name = "System RAM"; break; case CHUNK_READ_ONLY: res->name = "System ROM"; res->flags |= IORESOURCE_READONLY; break; default: res->name = "reserved"; } res->start = memory_chunk[i].addr; res->end = memory_chunk[i].addr + memory_chunk[i].size - 1; request_resource(&iomem_resource, res); if (code_resource.start >= res->start && code_resource.start <= res->end && code_resource.end > res->end) { sub_res = alloc_bootmem_low(sizeof(struct resource)); memcpy(sub_res, &code_resource, sizeof(struct resource)); sub_res->end = res->end; code_resource.start = res->end + 1; request_resource(res, sub_res); } if (code_resource.start >= res->start && code_resource.start <= res->end && code_resource.end <= res->end) request_resource(res, &code_resource); if (data_resource.start >= res->start && data_resource.start <= res->end && data_resource.end > res->end) { sub_res = alloc_bootmem_low(sizeof(struct resource)); memcpy(sub_res, &data_resource, sizeof(struct resource)); sub_res->end = res->end; data_resource.start = res->end + 1; request_resource(res, sub_res); } if (data_resource.start >= res->start && data_resource.start <= res->end && data_resource.end <= res->end) request_resource(res, &data_resource); }}unsigned long real_memory_size;EXPORT_SYMBOL_GPL(real_memory_size);static void __init setup_memory_end(void){ unsigned long memory_size; unsigned long max_mem, max_phys; int i;#if defined(CONFIG_ZFCPDUMP) || defined(CONFIG_ZFCPDUMP_MODULE) if (ipl_info.type == IPL_TYPE_FCP_DUMP) memory_end = ZFCPDUMP_HSA_SIZE;#endif memory_size = 0; max_phys = VMALLOC_END_INIT - VMALLOC_MIN_SIZE; memory_end &= PAGE_MASK; max_mem = memory_end ? min(max_phys, memory_end) : max_phys; for (i = 0; i < MEMORY_CHUNKS; i++) { struct mem_chunk *chunk = &memory_chunk[i]; real_memory_size = max(real_memory_size, chunk->addr + chunk->size); if (chunk->addr >= max_mem) { memset(chunk, 0, sizeof(*chunk)); continue; } if (chunk->addr + chunk->size > max_mem) chunk->size = max_mem - chunk->addr; memory_size = max(memory_size, chunk->addr + chunk->size); } if (!memory_end) memory_end = memory_size;}static void __initsetup_memory(void){ unsigned long bootmap_size; unsigned long start_pfn, end_pfn; int i; /* * partially used pages are not usable - thus * we are rounding upwards: */ start_pfn = PFN_UP(__pa(&_end)); end_pfn = max_pfn = PFN_DOWN(memory_end);#ifdef CONFIG_BLK_DEV_INITRD /* * Move the initrd in case the bitmap of the bootmem allocater * would overwrite it. */ if (INITRD_START && INITRD_SIZE) { unsigned long bmap_size; unsigned long start; bmap_size = bootmem_bootmap_pages(end_pfn - start_pfn + 1); bmap_size = PFN_PHYS(bmap_size); if (PFN_PHYS(start_pfn) + bmap_size > INITRD_START) { start = PFN_PHYS(start_pfn) + bmap_size + PAGE_SIZE; if (start + INITRD_SIZE > memory_end) { printk("initrd extends beyond end of memory " "(0x%08lx > 0x%08lx)\n" "disabling initrd\n", start + INITRD_SIZE, memory_end); INITRD_START = INITRD_SIZE = 0; } else { printk("Moving initrd (0x%08lx -> 0x%08lx, " "size: %ld)\n", INITRD_START, start, INITRD_SIZE); memmove((void *) start, (void *) INITRD_START, INITRD_SIZE); INITRD_START = start; } } }#endif /* * Initialize the boot-time allocator */ bootmap_size = init_bootmem(start_pfn, end_pfn); /* * Register RAM areas with the bootmem allocator. */ for (i = 0; i < MEMORY_CHUNKS && memory_chunk[i].size > 0; i++) { unsigned long start_chunk, end_chunk, pfn; if (memory_chunk[i].type != CHUNK_READ_WRITE) continue; start_chunk = PFN_DOWN(memory_chunk[i].addr); end_chunk = start_chunk + PFN_DOWN(memory_chunk[i].size) - 1; end_chunk = min(end_chunk, end_pfn); if (start_chunk >= end_chunk) continue; add_active_range(0, start_chunk, end_chunk); pfn = max(start_chunk, start_pfn); for (; pfn <= end_chunk; pfn++) page_set_storage_key(PFN_PHYS(pfn), PAGE_DEFAULT_KEY); } psw_set_key(PAGE_DEFAULT_KEY); free_bootmem_with_active_regions(0, max_pfn); /* * Reserve memory used for lowcore/command line/kernel image. */ reserve_bootmem(0, (unsigned long)_ehead); reserve_bootmem((unsigned long)_stext, PFN_PHYS(start_pfn) - (unsigned long)_stext); /* * Reserve the bootmem bitmap itself as well. We do this in two * steps (first step was init_bootmem()) because this catches * the (very unlikely) case of us accidentally initializing the * bootmem allocator with an invalid RAM area. */ reserve_bootmem(start_pfn << PAGE_SHIFT, bootmap_size);#ifdef CONFIG_BLK_DEV_INITRD if (INITRD_START && INITRD_SIZE) { if (INITRD_START + INITRD_SIZE <= memory_end) { reserve_bootmem(INITRD_START, INITRD_SIZE); initrd_start = INITRD_START; initrd_end = initrd_start + INITRD_SIZE; } else { printk("initrd extends beyond end of memory " "(0x%08lx > 0x%08lx)\ndisabling initrd\n", initrd_start + INITRD_SIZE, memory_end); initrd_start = initrd_end = 0; } }#endif}static __init unsigned int stfl(void){ asm volatile( " .insn s,0xb2b10000,0(0)\n" /* stfl */ "0:\n" EX_TABLE(0b,0b)); return S390_lowcore.stfl_fac_list;}static __init int stfle(unsigned long long *list, int doublewords){ typedef struct { unsigned long long _[doublewords]; } addrtype; register unsigned long __nr asm("0") = doublewords - 1; asm volatile(".insn s,0xb2b00000,%0" /* stfle */ : "=m" (*(addrtype *) list), "+d" (__nr) : : "cc"); return __nr + 1;}/* * Setup hardware capabilities. */static void __init setup_hwcaps(void){ static const int stfl_bits[6] = { 0, 2, 7, 17, 19, 21 }; struct cpuinfo_S390 *cpuinfo = &S390_lowcore.cpu_data; unsigned long long facility_list_extended; unsigned int facility_list; int i; facility_list = stfl(); /* * The store facility list bits numbers as found in the principles * of operation are numbered with bit 1UL<<31 as number 0 to * bit 1UL<<0 as number 31. * Bit 0: instructions named N3, "backported" to esa-mode * Bit 2: z/Architecture mode is active * Bit 7: the store-facility-list-extended facility is installed * Bit 17: the message-security assist is installed * Bit 19: the long-displacement facility is installed * Bit 21: the extended-immediate facility is installed * These get translated to: * HWCAP_S390_ESAN3 bit 0, HWCAP_S390_ZARCH bit 1, * HWCAP_S390_STFLE bit 2, HWCAP_S390_MSA bit 3, * HWCAP_S390_LDISP bit 4, and HWCAP_S390_EIMM bit 5. */ for (i = 0; i < 6; i++) if (facility_list & (1UL << (31 - stfl_bits[i]))) elf_hwcap |= 1UL << i; /* * Check for additional facilities with store-facility-list-extended. * stfle stores doublewords (8 byte) with bit 1ULL<<63 as bit 0 * and 1ULL<<0 as bit 63. Bits 0-31 contain the same information * as stored by stfl, bits 32-xxx contain additional facilities. * How many facility words are stored depends on the number of * doublewords passed to the instruction. The additional facilites * are: * Bit 43: decimal floating point facility is installed * translated to: * HWCAP_S390_DFP bit 6. */ if ((elf_hwcap & (1UL << 2)) && stfle(&facility_list_extended, 1) > 0) { if (facility_list_extended & (1ULL << (64 - 43))) elf_hwcap |= 1UL << 6; } switch (cpuinfo->cpu_id.machine) { case 0x9672:#if !defined(CONFIG_64BIT) default: /* Use "g5" as default for 31 bit kernels. */#endif strcpy(elf_platform, "g5"); break; case 0x2064: case 0x2066:#if defined(CONFIG_64BIT) default: /* Use "z900" as default for 64 bit kernels. */#endif strcpy(elf_platform, "z900"); break; case 0x2084: case 0x2086: strcpy(elf_platform, "z990"); break; case 0x2094: strcpy(elf_platform, "z9-109"); break; }}/* * Setup function called from init/main.c just after the banner * was printed. */void __initsetup_arch(char **cmdline_p){ /* * print what head.S has found out about the machine */#ifndef CONFIG_64BIT printk((MACHINE_IS_VM) ? "We are running under VM (31 bit mode)\n" : "We are running native (31 bit mode)\n"); printk((MACHINE_HAS_IEEE) ? "This machine has an IEEE fpu\n" : "This machine has no IEEE fpu\n");#else /* CONFIG_64BIT */ printk((MACHINE_IS_VM) ? "We are running under VM (64 bit mode)\n" : "We are running native (64 bit mode)\n");#endif /* CONFIG_64BIT */ /* Save unparsed command line copy for /proc/cmdline */ strlcpy(boot_command_line, COMMAND_LINE, COMMAND_LINE_SIZE); *cmdline_p = COMMAND_LINE; *(*cmdline_p + COMMAND_LINE_SIZE - 1) = '\0'; ROOT_DEV = Root_RAM0; init_mm.start_code = PAGE_OFFSET; init_mm.end_code = (unsigned long) &_etext; init_mm.end_data = (unsigned long) &_edata; init_mm.brk = (unsigned long) &_end; if (MACHINE_HAS_MVCOS) memcpy(&uaccess, &uaccess_mvcos, sizeof(uaccess)); else memcpy(&uaccess, &uaccess_std, sizeof(uaccess)); parse_early_param(); setup_ipl_info(); setup_memory_end(); setup_addressing_mode(); setup_memory(); setup_resources(); setup_lowcore(); cpu_init(); __cpu_logical_map[0] = S390_lowcore.cpu_data.cpu_addr; smp_setup_cpu_possible_map(); /* * Setup capabilities (ELF_HWCAP & ELF_PLATFORM). */ setup_hwcaps(); /* * Create kernel page tables and switch to virtual addressing. */ paging_init(); /* Setup default console */ conmode_default(); /* Setup zfcpdump support */ setup_zfcpdump(console_devno);}void __cpuinit print_cpu_info(struct cpuinfo_S390 *cpuinfo){ printk("cpu %d "#ifdef CONFIG_SMP "phys_idx=%d "#endif "vers=%02X ident=%06X machine=%04X unused=%04X\n", cpuinfo->cpu_nr,#ifdef CONFIG_SMP cpuinfo->cpu_addr,#endif cpuinfo->cpu_id.version, cpuinfo->cpu_id.ident, cpuinfo->cpu_id.machine, cpuinfo->cpu_id.unused);}/* * show_cpuinfo - Get information on one CPU for use by procfs. */static int show_cpuinfo(struct seq_file *m, void *v){ static const char *hwcap_str[7] = { "esan3", "zarch", "stfle", "msa", "ldisp", "eimm", "dfp" }; struct cpuinfo_S390 *cpuinfo; unsigned long n = (unsigned long) v - 1; int i; s390_adjust_jiffies(); preempt_disable(); if (!n) { seq_printf(m, "vendor_id : IBM/S390\n" "# processors : %i\n" "bogomips per cpu: %lu.%02lu\n", num_online_cpus(), loops_per_jiffy/(500000/HZ), (loops_per_jiffy/(5000/HZ))%100); seq_puts(m, "features\t: "); for (i = 0; i < 7; i++) if (hwcap_str[i] && (elf_hwcap & (1UL << i))) seq_printf(m, "%s ", hwcap_str[i]); seq_puts(m, "\n"); } if (cpu_online(n)) {#ifdef CONFIG_SMP if (smp_processor_id() == n) cpuinfo = &S390_lowcore.cpu_data; else cpuinfo = &lowcore_ptr[n]->cpu_data;#else cpuinfo = &S390_lowcore.cpu_data;#endif seq_printf(m, "processor %li: " "version = %02X, " "identification = %06X, " "machine = %04X\n", n, cpuinfo->cpu_id.version, cpuinfo->cpu_id.ident, cpuinfo->cpu_id.machine); } preempt_enable(); return 0;}static void *c_start(struct seq_file *m, loff_t *pos){ return *pos < NR_CPUS ? (void *)((unsigned long) *pos + 1) : NULL;}static void *c_next(struct seq_file *m, void *v, loff_t *pos){ ++*pos; return c_start(m, pos);}static void c_stop(struct seq_file *m, void *v){}struct seq_operations cpuinfo_op = { .start = c_start, .next = c_next, .stop = c_stop, .show = show_cpuinfo,};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -