setup.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:16k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. /*
  2.  * Architecture-specific setup.
  3.  *
  4.  * Copyright (C) 1998-2001 Hewlett-Packard Co
  5.  * David Mosberger-Tang <davidm@hpl.hp.com>
  6.  * Copyright (C) 1998, 1999, 2001 Stephane Eranian <eranian@hpl.hp.com>
  7.  * Copyright (C) 2000, Rohit Seth <rohit.seth@intel.com>
  8.  * Copyright (C) 1999 VA Linux Systems
  9.  * Copyright (C) 1999 Walt Drummond <drummond@valinux.com>
  10.  *
  11.  * 11/12/01 D.Mosberger Convert get_cpuinfo() to seq_file based show_cpuinfo().
  12.  * 04/04/00 D.Mosberger renamed cpu_initialized to cpu_online_map
  13.  * 03/31/00 R.Seth cpu_initialized and current->processor fixes
  14.  * 02/04/00 D.Mosberger some more get_cpuinfo fixes...
  15.  * 02/01/00 R.Seth fixed get_cpuinfo for SMP
  16.  * 01/07/99 S.Eranian added the support for command line argument
  17.  * 06/24/99 W.Drummond added boot_cpu_data.
  18.  */
  19. #include <linux/config.h>
  20. #include <linux/init.h>
  21. #include <linux/bootmem.h>
  22. #include <linux/delay.h>
  23. #include <linux/kernel.h>
  24. #include <linux/reboot.h>
  25. #include <linux/sched.h>
  26. #include <linux/seq_file.h>
  27. #include <linux/string.h>
  28. #include <linux/threads.h>
  29. #include <linux/console.h>
  30. #include <asm/acpi-ext.h>
  31. #include <asm/ia32.h>
  32. #include <asm/page.h>
  33. #include <asm/machvec.h>
  34. #include <asm/processor.h>
  35. #include <asm/sal.h>
  36. #include <asm/system.h>
  37. #include <asm/efi.h>
  38. #include <asm/mca.h>
  39. #include <asm/smp.h>
  40. #ifdef CONFIG_BLK_DEV_RAM
  41. # include <linux/blk.h>
  42. #endif
  43. #if defined(CONFIG_SMP) && (IA64_CPU_SIZE > PAGE_SIZE)
  44. # error "struct cpuinfo_ia64 too big!"
  45. #endif
  46. #define MIN(a,b) ((a) < (b) ? (a) : (b))
  47. #define MAX(a,b) ((a) > (b) ? (a) : (b))
  48. extern char _end;
  49. #ifdef CONFIG_NUMA
  50.  struct cpuinfo_ia64 *boot_cpu_data;
  51. #else
  52.  struct cpuinfo_ia64 _cpu_data[NR_CPUS] __attribute__ ((section ("__special_page_section")));
  53. #endif
  54. unsigned long ia64_cycles_per_usec;
  55. struct ia64_boot_param *ia64_boot_param;
  56. struct screen_info screen_info;
  57. unsigned long ia64_iobase; /* virtual address for I/O accesses */
  58. #define COMMAND_LINE_SIZE 512
  59. char saved_command_line[COMMAND_LINE_SIZE]; /* used in proc filesystem */
  60. /*
  61.  * Entries defined so far:
  62.  *  - boot param structure itself
  63.  *  - memory map
  64.  *  - initrd (optional)
  65.  *  - command line string
  66.  *  - kernel code & data
  67.  *
  68.  * More could be added if necessary
  69.  */
  70. #define IA64_MAX_RSVD_REGIONS 5
  71. struct rsvd_region {
  72. unsigned long start; /* virtual address of beginning of element */
  73. unsigned long end; /* virtual address of end of element + 1 */
  74. };
  75. /*
  76.  * We use a special marker for the end of memory and it uses the extra (+1) slot
  77.  */
  78. static struct rsvd_region rsvd_region[IA64_MAX_RSVD_REGIONS + 1];
  79. static int num_rsvd_regions;
  80. static unsigned long bootmap_start; /* physical address where the bootmem map is located */
  81. static int
  82. find_max_pfn (unsigned long start, unsigned long end, void *arg)
  83. {
  84. unsigned long *max_pfn = arg, pfn;
  85. pfn = (PAGE_ALIGN(end - 1) - PAGE_OFFSET) >> PAGE_SHIFT;
  86. if (pfn > *max_pfn)
  87. *max_pfn = pfn;
  88. return 0;
  89. }
  90. #define IGNORE_PFN0 1 /* XXX fix me: ignore pfn 0 until TLB miss handler is updated... */
  91. /*
  92.  * Free available memory based on the primitive map created from
  93.  * the boot parameters. This routine does not assume the incoming
  94.  * segments are sorted.
  95.  */
  96. static int
  97. free_available_memory (unsigned long start, unsigned long end, void *arg)
  98. {
  99. unsigned long range_start, range_end, prev_start;
  100. int i;
  101. #if IGNORE_PFN0
  102. if (start == PAGE_OFFSET) {
  103. printk("warning: skipping physical page 0n");
  104. start += PAGE_SIZE;
  105. if (start >= end) return 0;
  106. }
  107. #endif
  108. /*
  109.  * lowest possible address(walker uses virtual)
  110.  */
  111. prev_start = PAGE_OFFSET;
  112. for (i = 0; i < num_rsvd_regions; ++i) {
  113. range_start = MAX(start, prev_start);
  114. range_end   = MIN(end, rsvd_region[i].start);
  115. if (range_start < range_end)
  116. free_bootmem(__pa(range_start), range_end - range_start);
  117. /* nothing more available in this segment */
  118. if (range_end == end) return 0;
  119. prev_start = rsvd_region[i].end;
  120. }
  121. /* end of memory marker allows full processing inside loop body */
  122. return 0;
  123. }
  124. static int
  125. find_bootmap_location (unsigned long start, unsigned long end, void *arg)
  126. {
  127. unsigned long needed = *(unsigned long *)arg;
  128. unsigned long range_start, range_end, free_start;
  129. int i;
  130. #if IGNORE_PFN0
  131. if (start == PAGE_OFFSET) {
  132. start += PAGE_SIZE;
  133. if (start >= end) return 0;
  134. }
  135. #endif
  136. free_start = PAGE_OFFSET;
  137. for (i = 0; i < num_rsvd_regions; i++) {
  138. range_start = MAX(start, free_start);
  139. range_end   = MIN(end, rsvd_region[i].start);
  140. if (range_end <= range_start) continue; /* skip over empty range */
  141.         if (range_end - range_start >= needed) {
  142. bootmap_start = __pa(range_start);
  143. return 1; /* done */
  144. }
  145. /* nothing more available in this segment */
  146. if (range_end == end) return 0;
  147. free_start = rsvd_region[i].end;
  148. }
  149. return 0;
  150. }
  151. static void
  152. sort_regions (struct rsvd_region *rsvd_region, int max)
  153. {
  154. int j;
  155. /* simple bubble sorting */
  156. while (max--) {
  157. for (j = 0; j < max; ++j) {
  158. if (rsvd_region[j].start > rsvd_region[j+1].start) {
  159. struct rsvd_region tmp;
  160. tmp = rsvd_region[j];
  161. rsvd_region[j] = rsvd_region[j + 1];
  162. rsvd_region[j + 1] = tmp;
  163. }
  164. }
  165. }
  166. }
  167. static void
  168. find_memory (void)
  169. {
  170. # define KERNEL_END ((unsigned long) &_end)
  171. unsigned long bootmap_size;
  172. unsigned long max_pfn;
  173. int n = 0;
  174. /*
  175.  * none of the entries in this table overlap
  176.  */
  177. rsvd_region[n].start = (unsigned long) ia64_boot_param;
  178. rsvd_region[n].end   = rsvd_region[n].start + sizeof(*ia64_boot_param);
  179. n++;
  180. rsvd_region[n].start = (unsigned long) __va(ia64_boot_param->efi_memmap);
  181. rsvd_region[n].end   = rsvd_region[n].start + ia64_boot_param->efi_memmap_size;
  182. n++;
  183. rsvd_region[n].start = (unsigned long) __va(ia64_boot_param->command_line);
  184. rsvd_region[n].end   = (rsvd_region[n].start
  185. + strlen(__va(ia64_boot_param->command_line)) + 1);
  186. n++;
  187. rsvd_region[n].start = KERNEL_START;
  188. rsvd_region[n].end   = KERNEL_END;
  189. n++;
  190. #ifdef CONFIG_BLK_DEV_INITRD
  191. if (ia64_boot_param->initrd_start) {
  192. rsvd_region[n].start = (unsigned long)__va(ia64_boot_param->initrd_start);
  193. rsvd_region[n].end   = rsvd_region[n].start + ia64_boot_param->initrd_size;
  194. n++;
  195. }
  196. #endif
  197. /* end of memory marker */
  198. rsvd_region[n].start = ~0UL;
  199. rsvd_region[n].end   = ~0UL;
  200. n++;
  201. num_rsvd_regions = n;
  202. sort_regions(rsvd_region, num_rsvd_regions);
  203. /* first find highest page frame number */
  204. max_pfn = 0;
  205. efi_memmap_walk(find_max_pfn, &max_pfn);
  206. /* how many bytes to cover all the pages */
  207. bootmap_size = bootmem_bootmap_pages(max_pfn) << PAGE_SHIFT;
  208. /* look for a location to hold the bootmap */
  209. bootmap_start = ~0UL;
  210. efi_memmap_walk(find_bootmap_location, &bootmap_size);
  211. if (bootmap_start == ~0UL)
  212. panic("Cannot find %ld bytes for bootmapn", bootmap_size);
  213. bootmap_size = init_bootmem(bootmap_start >> PAGE_SHIFT, max_pfn);
  214. /* Free all available memory, then mark bootmem-map as being in use.  */
  215. efi_memmap_walk(free_available_memory, 0);
  216. reserve_bootmem(bootmap_start, bootmap_size);
  217. #ifdef CONFIG_BLK_DEV_INITRD
  218. if (ia64_boot_param->initrd_start) {
  219. initrd_start = (unsigned long)__va(ia64_boot_param->initrd_start);
  220. initrd_end   = initrd_start+ia64_boot_param->initrd_size;
  221. printk("Initial ramdisk at: 0x%lx (%lu bytes)n",
  222.        initrd_start, ia64_boot_param->initrd_size);
  223. }
  224. #endif
  225. }
  226. void __init
  227. setup_arch (char **cmdline_p)
  228. {
  229. extern unsigned long ia64_iobase;
  230. unw_init();
  231. *cmdline_p = __va(ia64_boot_param->command_line);
  232. strncpy(saved_command_line, *cmdline_p, sizeof(saved_command_line));
  233. saved_command_line[COMMAND_LINE_SIZE-1] = ''; /* for safety */
  234. efi_init();
  235. find_memory();
  236. #if 0
  237. /* XXX fix me */
  238. init_mm.start_code = (unsigned long) &_stext;
  239. init_mm.end_code = (unsigned long) &_etext;
  240. init_mm.end_data = (unsigned long) &_edata;
  241. init_mm.brk = (unsigned long) &_end;
  242. code_resource.start = virt_to_bus(&_text);
  243. code_resource.end = virt_to_bus(&_etext) - 1;
  244. data_resource.start = virt_to_bus(&_etext);
  245. data_resource.end = virt_to_bus(&_edata) - 1;
  246. #endif
  247. /* process SAL system table: */
  248. ia64_sal_init(efi.sal_systab);
  249. /*
  250.  *  Set `iobase' to the appropriate address in region 6
  251.  *    (uncached access range)
  252.  *
  253.  *  The EFI memory map is the "prefered" location to get the I/O port
  254.  *  space base, rather the relying on AR.KR0. This should become more
  255.  *  clear in future SAL specs. We'll fall back to getting it out of
  256.  *  AR.KR0 if no appropriate entry is found in the memory map.
  257.  */
  258. ia64_iobase = efi_get_iobase();
  259. if (ia64_iobase)
  260. /* set AR.KR0 since this is all we use it for anyway */
  261. ia64_set_kr(IA64_KR_IO_BASE, ia64_iobase);
  262. else {
  263. ia64_iobase = ia64_get_kr(IA64_KR_IO_BASE);
  264. printk("No I/O port range found in EFI memory map, falling back to AR.KR0n");
  265. printk("I/O port base = 0x%lxn", ia64_iobase);
  266. }
  267. ia64_iobase = __IA64_UNCACHED_OFFSET | (ia64_iobase & ~PAGE_OFFSET);
  268. #ifdef CONFIG_SMP
  269. cpu_physical_id(0) = hard_smp_processor_id();
  270. #endif
  271. cpu_init(); /* initialize the bootstrap CPU */
  272. #ifdef CONFIG_IA64_GENERIC
  273. machvec_init(acpi_get_sysname());
  274. #endif
  275. if (efi.acpi20) {
  276. /* Parse the ACPI 2.0 tables */
  277. acpi20_parse(efi.acpi20);
  278. } else if (efi.acpi) {
  279. /* Parse the ACPI tables */
  280. acpi_parse(efi.acpi);
  281. }
  282. #ifdef CONFIG_VT
  283. # if defined(CONFIG_VGA_CONSOLE)
  284. conswitchp = &vga_con;
  285. # elif defined(CONFIG_DUMMY_CONSOLE)
  286. conswitchp = &dummy_con;
  287. # endif
  288. #endif
  289. #ifdef CONFIG_IA64_MCA
  290. /* enable IA-64 Machine Check Abort Handling */
  291. ia64_mca_init();
  292. #endif
  293. platform_setup(cmdline_p);
  294. paging_init();
  295. unw_create_gate_table();
  296. }
  297. /*
  298.  * Display cpu info for all cpu's.
  299.  */
  300. static int
  301. show_cpuinfo (struct seq_file *m, void *v)
  302. {
  303. #ifdef CONFIG_SMP
  304. # define lpj c->loops_per_jiffy
  305. #else
  306. # define lpj loops_per_jiffy
  307. #endif
  308. char family[32], features[128], *cp;
  309. struct cpuinfo_ia64 *c = v;
  310. unsigned long mask, cpu = c - cpu_data(0);
  311. #ifdef CONFIG_SMP
  312. if (!(cpu_online_map & (1 << cpu)))
  313. return 0;
  314. #endif
  315. mask = c->features;
  316. switch (c->family) {
  317.       case 0x07: memcpy(family, "Itanium", 8); break;
  318.       case 0x1f: memcpy(family, "McKinley", 9); break;
  319.       default: sprintf(family, "%u", c->family); break;
  320. }
  321. /* build the feature string: */
  322. memcpy(features, " standard", 10);
  323. cp = features;
  324. if (mask & 1) {
  325. strcpy(cp, " branchlong");
  326. cp = strchr(cp, '');
  327. mask &= ~1UL;
  328. }
  329. if (mask)
  330. sprintf(cp, " 0x%lx", mask);
  331. seq_printf(m,
  332.    "processor  : %lun"
  333.    "vendor     : %sn"
  334.    "arch       : IA-64n"
  335.    "family     : %sn"
  336.    "model      : %un"
  337.    "revision   : %un"
  338.    "archrev    : %un"
  339.    "features   :%sn" /* don't change this---it _is_ right! */
  340.    "cpu number : %lun"
  341.    "cpu regs   : %un"
  342.    "cpu MHz    : %lu.%06lun"
  343.    "itc MHz    : %lu.%06lun"
  344.    "BogoMIPS   : %lu.%02lunn",
  345.    cpu, c->vendor, family, c->model, c->revision, c->archrev,
  346.    features, c->ppn, c->number,
  347.    c->proc_freq / 1000000, c->proc_freq % 1000000,
  348.    c->itc_freq / 1000000, c->itc_freq % 1000000,
  349.    lpj*HZ/500000, (lpj*HZ/5000) % 100);
  350. return 0;
  351. }
  352. static void *
  353. c_start (struct seq_file *m, loff_t *pos)
  354. {
  355. return *pos < NR_CPUS ? cpu_data(*pos) : NULL;
  356. }
  357. static void *
  358. c_next (struct seq_file *m, void *v, loff_t *pos)
  359. {
  360. ++*pos;
  361. return c_start(m, pos);
  362. }
  363. static void
  364. c_stop (struct seq_file *m, void *v)
  365. {
  366. }
  367. struct seq_operations cpuinfo_op = {
  368. start: c_start,
  369. next: c_next,
  370. stop: c_stop,
  371. show: show_cpuinfo
  372. };
  373. void
  374. identify_cpu (struct cpuinfo_ia64 *c)
  375. {
  376. union {
  377. unsigned long bits[5];
  378. struct {
  379. /* id 0 & 1: */
  380. char vendor[16];
  381. /* id 2 */
  382. u64 ppn; /* processor serial number */
  383. /* id 3: */
  384. unsigned number :  8;
  385. unsigned revision :  8;
  386. unsigned model :  8;
  387. unsigned family :  8;
  388. unsigned archrev :  8;
  389. unsigned reserved : 24;
  390. /* id 4: */
  391. u64 features;
  392. } field;
  393. } cpuid;
  394. pal_vm_info_1_u_t vm1;
  395. pal_vm_info_2_u_t vm2;
  396. pal_status_t status;
  397. unsigned long impl_va_msb = 50, phys_addr_size = 44; /* Itanium defaults */
  398. int i;
  399. for (i = 0; i < 5; ++i)
  400. cpuid.bits[i] = ia64_get_cpuid(i);
  401. memcpy(c->vendor, cpuid.field.vendor, 16);
  402. c->ppn = cpuid.field.ppn;
  403. c->number = cpuid.field.number;
  404. c->revision = cpuid.field.revision;
  405. c->model = cpuid.field.model;
  406. c->family = cpuid.field.family;
  407. c->archrev = cpuid.field.archrev;
  408. c->features = cpuid.field.features;
  409. status = ia64_pal_vm_summary(&vm1, &vm2);
  410. if (status == PAL_STATUS_SUCCESS) {
  411. impl_va_msb = vm2.pal_vm_info_2_s.impl_va_msb;
  412. phys_addr_size = vm1.pal_vm_info_1_s.phys_add_size;
  413. }
  414. printk("CPU %d: %lu virtual and %lu physical address bitsn",
  415.        smp_processor_id(), impl_va_msb + 1, phys_addr_size);
  416. c->unimpl_va_mask = ~((7L<<61) | ((1L << (impl_va_msb + 1)) - 1));
  417. c->unimpl_pa_mask = ~((1L<<63) | ((1L << phys_addr_size) - 1));
  418. }
  419. /*
  420.  * cpu_init() initializes state that is per-CPU.  This function acts
  421.  * as a 'CPU state barrier', nothing should get across.
  422.  */
  423. void
  424. cpu_init (void)
  425. {
  426. extern void __init ia64_mmu_init (void *);
  427. unsigned long num_phys_stacked;
  428. pal_vm_info_2_u_t vmi;
  429. unsigned int max_ctx;
  430. struct cpuinfo_ia64 *my_cpu_data;
  431. #ifdef CONFIG_NUMA
  432. int cpu, order;
  433. /*
  434.  * If NUMA is configured, the cpu_data array is not preallocated. The boot cpu
  435.  * allocates entries for every possible cpu. As the remaining cpus come online,
  436.  * they reallocate a new cpu_data structure on their local node. This extra work
  437.  * is required because some boot code references all cpu_data structures
  438.  * before the cpus are actually started.
  439.  */
  440. if (!boot_cpu_data) {
  441. my_cpu_data = alloc_bootmem_pages_node(NODE_DATA(numa_node_id()),
  442.        sizeof(struct cpuinfo_ia64));
  443. boot_cpu_data = my_cpu_data;
  444. my_cpu_data->cpu_data[0] = my_cpu_data;
  445. for (cpu = 1; cpu < NR_CPUS; ++cpu)
  446. my_cpu_data->cpu_data[cpu]
  447. = alloc_bootmem_pages_node(NODE_DATA(numa_node_id()),
  448.    sizeof(struct cpuinfo_ia64));
  449. for (cpu = 1; cpu < NR_CPUS; ++cpu)
  450. memcpy(my_cpu_data->cpu_data[cpu]->cpu_data_ptrs,
  451.        my_cpu_data->cpu_data, sizeof(my_cpu_data->cpu_data));
  452. } else {
  453. order = get_order(sizeof(struct cpuinfo_ia64));
  454. my_cpu_data = page_address(alloc_pages_node(numa_node_id(), GFP_KERNEL, order));
  455. memcpy(my_cpu_data, boot_cpu_data->cpu_data[smp_processor_id()],
  456.        sizeof(struct cpuinfo_ia64));
  457. __free_pages(virt_to_page(boot_cpu_data->cpu_data[smp_processor_id()]),
  458.      order);
  459. for (cpu = 0; cpu < NR_CPUS; ++cpu)
  460. boot_cpu_data->cpu_data[cpu]->cpu_data[smp_processor_id()] = my_cpu_data;
  461. }
  462. #else
  463. my_cpu_data = cpu_data(smp_processor_id());
  464. #endif
  465. /*
  466.  * We can't pass "local_cpu_data" to identify_cpu() because we haven't called
  467.  * ia64_mmu_init() yet.  And we can't call ia64_mmu_init() first because it
  468.  * depends on the data returned by identify_cpu().  We break the dependency by
  469.  * accessing cpu_data() the old way, through identity mapped space.
  470.  */
  471. identify_cpu(my_cpu_data);
  472. /* Clear the stack memory reserved for pt_regs: */
  473. memset(ia64_task_regs(current), 0, sizeof(struct pt_regs));
  474. /*
  475.  * Initialize default control register to defer all speculative faults.  The
  476.  * kernel MUST NOT depend on a particular setting of these bits (in other words,
  477.  * the kernel must have recovery code for all speculative accesses).  Turn on
  478.  * dcr.lc as per recommendation by the architecture team.  Most IA-32 apps
  479.  * shouldn't be affected by this (moral: keep your ia32 locks aligned and you'll
  480.  * be fine).
  481.  */
  482. ia64_set_dcr(  IA64_DCR_DM | IA64_DCR_DP | IA64_DCR_DK | IA64_DCR_DX | IA64_DCR_DR
  483.      | IA64_DCR_DA | IA64_DCR_DD | IA64_DCR_LC);
  484. #ifndef CONFIG_SMP
  485. ia64_set_fpu_owner(0);
  486. #endif
  487. atomic_inc(&init_mm.mm_count);
  488. current->active_mm = &init_mm;
  489. ia64_mmu_init(my_cpu_data);
  490. #ifdef CONFIG_IA32_SUPPORT
  491. /* initialize global ia32 state - CR0 and CR4 */
  492. asm volatile ("mov ar.cflg = %0" :: "r" (((ulong) IA32_CR4 << 32) | IA32_CR0));
  493. #endif
  494. /* disable all local interrupt sources: */
  495. ia64_set_itv(1 << 16);
  496. ia64_set_lrr0(1 << 16);
  497. ia64_set_lrr1(1 << 16);
  498. ia64_set_pmv(1 << 16);
  499. ia64_set_cmcv(1 << 16);
  500. /* clear TPR & XTP to enable all interrupt classes: */
  501. ia64_set_tpr(0);
  502. #ifdef CONFIG_SMP
  503. normal_xtp();
  504. #endif
  505. /* set ia64_ctx.max_rid to the maximum RID that is supported by all CPUs: */
  506. if (ia64_pal_vm_summary(NULL, &vmi) == 0)
  507. max_ctx = (1U << (vmi.pal_vm_info_2_s.rid_size - 3)) - 1;
  508. else {
  509. printk("cpu_init: PAL VM summary failed, assuming 18 RID bitsn");
  510. max_ctx = (1U << 15) - 1; /* use architected minimum */
  511. }
  512. while (max_ctx < ia64_ctx.max_ctx) {
  513. unsigned int old = ia64_ctx.max_ctx;
  514. if (cmpxchg(&ia64_ctx.max_ctx, old, max_ctx) == old)
  515. break;
  516. }
  517. if (ia64_pal_rse_info(&num_phys_stacked, 0) != 0) {
  518. printk ("cpu_init: PAL RSE info failed, assuming 96 physical stacked regsn");
  519. num_phys_stacked = 96;
  520. }
  521. local_cpu_data->phys_stacked_size_p8 = num_phys_stacked*8 + 8;
  522. }