diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-05-25 18:59:38 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-05-25 18:59:38 -0400 |
commit | fa2af6e4fe0c4d2f8875d42625b25675e8584010 (patch) | |
tree | ef9a92949858ab763aa1bfda7cb11a5f7b84d123 /arch/tile/kernel/setup.c | |
parent | 109b9b0408e5f1dd327a44f446841a9fbe0bcd83 (diff) | |
parent | 1fcb78e9da714d96f65edd37b29dae3b1f7df508 (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/cmetcalf/linux-tile
Pull tile updates from Chris Metcalf:
"These changes cover a range of new arch/tile features and
optimizations. They've been through LKML review and on linux-next for
a month or so. There's also one bug-fix that just missed 3.4, which
I've marked for stable."
Fixed up trivial conflict in arch/tile/Kconfig (new added tile Kconfig
entries clashing with the generic timer/clockevents changes).
* git://git.kernel.org/pub/scm/linux/kernel/git/cmetcalf/linux-tile:
tile: default to tilegx_defconfig for ARCH=tile
tile: fix bug where fls(0) was not returning 0
arch/tile: mark TILEGX as not EXPERIMENTAL
tile/mm/fault.c: Port OOM changes to handle_page_fault
arch/tile: add descriptive text if the kernel reports a bad trap
arch/tile: allow querying cpu module information from the hypervisor
arch/tile: fix hardwall for tilegx and generalize for idn and ipi
arch/tile: support multiple huge page sizes dynamically
mm: add new arch_make_huge_pte() method for tile support
arch/tile: support kexec() for tilegx
arch/tile: support <asm/cachectl.h> header for cacheflush() syscall
arch/tile: Allow tilegx to build with either 16K or 64K page size
arch/tile: optimize get_user/put_user and friends
arch/tile: support building big-endian kernel
arch/tile: allow building Linux with transparent huge pages enabled
arch/tile: use interrupt critical sections less
Diffstat (limited to 'arch/tile/kernel/setup.c')
-rw-r--r-- | arch/tile/kernel/setup.c | 169 |
1 files changed, 115 insertions, 54 deletions
diff --git a/arch/tile/kernel/setup.c b/arch/tile/kernel/setup.c index 98d80eb49ddb..6098ccc59be2 100644 --- a/arch/tile/kernel/setup.c +++ b/arch/tile/kernel/setup.c | |||
@@ -28,6 +28,7 @@ | |||
28 | #include <linux/highmem.h> | 28 | #include <linux/highmem.h> |
29 | #include <linux/smp.h> | 29 | #include <linux/smp.h> |
30 | #include <linux/timex.h> | 30 | #include <linux/timex.h> |
31 | #include <linux/hugetlb.h> | ||
31 | #include <asm/setup.h> | 32 | #include <asm/setup.h> |
32 | #include <asm/sections.h> | 33 | #include <asm/sections.h> |
33 | #include <asm/cacheflush.h> | 34 | #include <asm/cacheflush.h> |
@@ -49,9 +50,6 @@ char chip_model[64] __write_once; | |||
49 | struct pglist_data node_data[MAX_NUMNODES] __read_mostly; | 50 | struct pglist_data node_data[MAX_NUMNODES] __read_mostly; |
50 | EXPORT_SYMBOL(node_data); | 51 | EXPORT_SYMBOL(node_data); |
51 | 52 | ||
52 | /* We only create bootmem data on node 0. */ | ||
53 | static bootmem_data_t __initdata node0_bdata; | ||
54 | |||
55 | /* Information on the NUMA nodes that we compute early */ | 53 | /* Information on the NUMA nodes that we compute early */ |
56 | unsigned long __cpuinitdata node_start_pfn[MAX_NUMNODES]; | 54 | unsigned long __cpuinitdata node_start_pfn[MAX_NUMNODES]; |
57 | unsigned long __cpuinitdata node_end_pfn[MAX_NUMNODES]; | 55 | unsigned long __cpuinitdata node_end_pfn[MAX_NUMNODES]; |
@@ -534,37 +532,96 @@ static void __init setup_memory(void) | |||
534 | #endif | 532 | #endif |
535 | } | 533 | } |
536 | 534 | ||
537 | static void __init setup_bootmem_allocator(void) | 535 | /* |
536 | * On 32-bit machines, we only put bootmem on the low controller, | ||
537 | * since PAs > 4GB can't be used in bootmem. In principle one could | ||
538 | * imagine, e.g., multiple 1 GB controllers all of which could support | ||
539 | * bootmem, but in practice using controllers this small isn't a | ||
540 | * particularly interesting scenario, so we just keep it simple and | ||
541 | * use only the first controller for bootmem on 32-bit machines. | ||
542 | */ | ||
543 | static inline int node_has_bootmem(int nid) | ||
538 | { | 544 | { |
539 | unsigned long bootmap_size, first_alloc_pfn, last_alloc_pfn; | 545 | #ifdef CONFIG_64BIT |
546 | return 1; | ||
547 | #else | ||
548 | return nid == 0; | ||
549 | #endif | ||
550 | } | ||
540 | 551 | ||
541 | /* Provide a node 0 bdata. */ | 552 | static inline unsigned long alloc_bootmem_pfn(int nid, |
542 | NODE_DATA(0)->bdata = &node0_bdata; | 553 | unsigned long size, |
554 | unsigned long goal) | ||
555 | { | ||
556 | void *kva = __alloc_bootmem_node(NODE_DATA(nid), size, | ||
557 | PAGE_SIZE, goal); | ||
558 | unsigned long pfn = kaddr_to_pfn(kva); | ||
559 | BUG_ON(goal && PFN_PHYS(pfn) != goal); | ||
560 | return pfn; | ||
561 | } | ||
543 | 562 | ||
544 | #ifdef CONFIG_PCI | 563 | static void __init setup_bootmem_allocator_node(int i) |
545 | /* Don't let boot memory alias the PCI region. */ | 564 | { |
546 | last_alloc_pfn = min(max_low_pfn, pci_reserve_start_pfn); | 565 | unsigned long start, end, mapsize, mapstart; |
566 | |||
567 | if (node_has_bootmem(i)) { | ||
568 | NODE_DATA(i)->bdata = &bootmem_node_data[i]; | ||
569 | } else { | ||
570 | /* Share controller zero's bdata for now. */ | ||
571 | NODE_DATA(i)->bdata = &bootmem_node_data[0]; | ||
572 | return; | ||
573 | } | ||
574 | |||
575 | /* Skip up to after the bss in node 0. */ | ||
576 | start = (i == 0) ? min_low_pfn : node_start_pfn[i]; | ||
577 | |||
578 | /* Only lowmem, if we're a HIGHMEM build. */ | ||
579 | #ifdef CONFIG_HIGHMEM | ||
580 | end = node_lowmem_end_pfn[i]; | ||
547 | #else | 581 | #else |
548 | last_alloc_pfn = max_low_pfn; | 582 | end = node_end_pfn[i]; |
549 | #endif | 583 | #endif |
550 | 584 | ||
551 | /* | 585 | /* No memory here. */ |
552 | * Initialize the boot-time allocator (with low memory only): | 586 | if (end == start) |
553 | * The first argument says where to put the bitmap, and the | 587 | return; |
554 | * second says where the end of allocatable memory is. | 588 | |
555 | */ | 589 | /* Figure out where the bootmem bitmap is located. */ |
556 | bootmap_size = init_bootmem(min_low_pfn, last_alloc_pfn); | 590 | mapsize = bootmem_bootmap_pages(end - start); |
591 | if (i == 0) { | ||
592 | /* Use some space right before the heap on node 0. */ | ||
593 | mapstart = start; | ||
594 | start += mapsize; | ||
595 | } else { | ||
596 | /* Allocate bitmap on node 0 to avoid page table issues. */ | ||
597 | mapstart = alloc_bootmem_pfn(0, PFN_PHYS(mapsize), 0); | ||
598 | } | ||
557 | 599 | ||
600 | /* Initialize a node. */ | ||
601 | init_bootmem_node(NODE_DATA(i), mapstart, start, end); | ||
602 | |||
603 | /* Free all the space back into the allocator. */ | ||
604 | free_bootmem(PFN_PHYS(start), PFN_PHYS(end - start)); | ||
605 | |||
606 | #if defined(CONFIG_PCI) | ||
558 | /* | 607 | /* |
559 | * Let the bootmem allocator use all the space we've given it | 608 | * Throw away any memory aliased by the PCI region. FIXME: this |
560 | * except for its own bitmap. | 609 | * is a temporary hack to work around bug 10502, and needs to be |
610 | * fixed properly. | ||
561 | */ | 611 | */ |
562 | first_alloc_pfn = min_low_pfn + PFN_UP(bootmap_size); | 612 | if (pci_reserve_start_pfn < end && pci_reserve_end_pfn > start) |
563 | if (first_alloc_pfn >= last_alloc_pfn) | 613 | reserve_bootmem(PFN_PHYS(pci_reserve_start_pfn), |
564 | early_panic("Not enough memory on controller 0 for bootmem\n"); | 614 | PFN_PHYS(pci_reserve_end_pfn - |
615 | pci_reserve_start_pfn), | ||
616 | BOOTMEM_EXCLUSIVE); | ||
617 | #endif | ||
618 | } | ||
565 | 619 | ||
566 | free_bootmem(PFN_PHYS(first_alloc_pfn), | 620 | static void __init setup_bootmem_allocator(void) |
567 | PFN_PHYS(last_alloc_pfn - first_alloc_pfn)); | 621 | { |
622 | int i; | ||
623 | for (i = 0; i < MAX_NUMNODES; ++i) | ||
624 | setup_bootmem_allocator_node(i); | ||
568 | 625 | ||
569 | #ifdef CONFIG_KEXEC | 626 | #ifdef CONFIG_KEXEC |
570 | if (crashk_res.start != crashk_res.end) | 627 | if (crashk_res.start != crashk_res.end) |
@@ -595,14 +652,6 @@ static int __init percpu_size(void) | |||
595 | return size; | 652 | return size; |
596 | } | 653 | } |
597 | 654 | ||
598 | static inline unsigned long alloc_bootmem_pfn(int size, unsigned long goal) | ||
599 | { | ||
600 | void *kva = __alloc_bootmem(size, PAGE_SIZE, goal); | ||
601 | unsigned long pfn = kaddr_to_pfn(kva); | ||
602 | BUG_ON(goal && PFN_PHYS(pfn) != goal); | ||
603 | return pfn; | ||
604 | } | ||
605 | |||
606 | static void __init zone_sizes_init(void) | 655 | static void __init zone_sizes_init(void) |
607 | { | 656 | { |
608 | unsigned long zones_size[MAX_NR_ZONES] = { 0 }; | 657 | unsigned long zones_size[MAX_NR_ZONES] = { 0 }; |
@@ -640,21 +689,22 @@ static void __init zone_sizes_init(void) | |||
640 | * though, there'll be no lowmem, so we just alloc_bootmem | 689 | * though, there'll be no lowmem, so we just alloc_bootmem |
641 | * the memmap. There will be no percpu memory either. | 690 | * the memmap. There will be no percpu memory either. |
642 | */ | 691 | */ |
643 | if (__pfn_to_highbits(start) == 0) { | 692 | if (i != 0 && cpu_isset(i, isolnodes)) { |
644 | /* In low PAs, allocate via bootmem. */ | 693 | node_memmap_pfn[i] = |
694 | alloc_bootmem_pfn(0, memmap_size, 0); | ||
695 | BUG_ON(node_percpu[i] != 0); | ||
696 | } else if (node_has_bootmem(start)) { | ||
645 | unsigned long goal = 0; | 697 | unsigned long goal = 0; |
646 | node_memmap_pfn[i] = | 698 | node_memmap_pfn[i] = |
647 | alloc_bootmem_pfn(memmap_size, goal); | 699 | alloc_bootmem_pfn(i, memmap_size, 0); |
648 | if (kdata_huge) | 700 | if (kdata_huge) |
649 | goal = PFN_PHYS(lowmem_end) - node_percpu[i]; | 701 | goal = PFN_PHYS(lowmem_end) - node_percpu[i]; |
650 | if (node_percpu[i]) | 702 | if (node_percpu[i]) |
651 | node_percpu_pfn[i] = | 703 | node_percpu_pfn[i] = |
652 | alloc_bootmem_pfn(node_percpu[i], goal); | 704 | alloc_bootmem_pfn(i, node_percpu[i], |
653 | } else if (cpu_isset(i, isolnodes)) { | 705 | goal); |
654 | node_memmap_pfn[i] = alloc_bootmem_pfn(memmap_size, 0); | ||
655 | BUG_ON(node_percpu[i] != 0); | ||
656 | } else { | 706 | } else { |
657 | /* In high PAs, just reserve some pages. */ | 707 | /* In non-bootmem zones, just reserve some pages. */ |
658 | node_memmap_pfn[i] = node_free_pfn[i]; | 708 | node_memmap_pfn[i] = node_free_pfn[i]; |
659 | node_free_pfn[i] += PFN_UP(memmap_size); | 709 | node_free_pfn[i] += PFN_UP(memmap_size); |
660 | if (!kdata_huge) { | 710 | if (!kdata_huge) { |
@@ -678,16 +728,9 @@ static void __init zone_sizes_init(void) | |||
678 | zones_size[ZONE_NORMAL] = end - start; | 728 | zones_size[ZONE_NORMAL] = end - start; |
679 | #endif | 729 | #endif |
680 | 730 | ||
681 | /* | 731 | /* Take zone metadata from controller 0 if we're isolnode. */ |
682 | * Everyone shares node 0's bootmem allocator, but | 732 | if (node_isset(i, isolnodes)) |
683 | * we use alloc_remap(), above, to put the actual | 733 | NODE_DATA(i)->bdata = &bootmem_node_data[0]; |
684 | * struct page array on the individual controllers, | ||
685 | * which is most of the data that we actually care about. | ||
686 | * We can't place bootmem allocators on the other | ||
687 | * controllers since the bootmem allocator can only | ||
688 | * operate on 32-bit physical addresses. | ||
689 | */ | ||
690 | NODE_DATA(i)->bdata = NODE_DATA(0)->bdata; | ||
691 | 734 | ||
692 | free_area_init_node(i, zones_size, start, NULL); | 735 | free_area_init_node(i, zones_size, start, NULL); |
693 | printk(KERN_DEBUG " Normal zone: %ld per-cpu pages\n", | 736 | printk(KERN_DEBUG " Normal zone: %ld per-cpu pages\n", |
@@ -870,6 +913,22 @@ subsys_initcall(topology_init); | |||
870 | 913 | ||
871 | #endif /* CONFIG_NUMA */ | 914 | #endif /* CONFIG_NUMA */ |
872 | 915 | ||
916 | /* | ||
917 | * Initialize hugepage support on this cpu. We do this on all cores | ||
918 | * early in boot: before argument parsing for the boot cpu, and after | ||
919 | * argument parsing but before the init functions run on the secondaries. | ||
920 | * So the values we set up here in the hypervisor may be overridden on | ||
921 | * the boot cpu as arguments are parsed. | ||
922 | */ | ||
923 | static __cpuinit void init_super_pages(void) | ||
924 | { | ||
925 | #ifdef CONFIG_HUGETLB_SUPER_PAGES | ||
926 | int i; | ||
927 | for (i = 0; i < HUGE_SHIFT_ENTRIES; ++i) | ||
928 | hv_set_pte_super_shift(i, huge_shift[i]); | ||
929 | #endif | ||
930 | } | ||
931 | |||
873 | /** | 932 | /** |
874 | * setup_cpu() - Do all necessary per-cpu, tile-specific initialization. | 933 | * setup_cpu() - Do all necessary per-cpu, tile-specific initialization. |
875 | * @boot: Is this the boot cpu? | 934 | * @boot: Is this the boot cpu? |
@@ -924,6 +983,8 @@ void __cpuinit setup_cpu(int boot) | |||
924 | /* Reset the network state on this cpu. */ | 983 | /* Reset the network state on this cpu. */ |
925 | reset_network_state(); | 984 | reset_network_state(); |
926 | #endif | 985 | #endif |
986 | |||
987 | init_super_pages(); | ||
927 | } | 988 | } |
928 | 989 | ||
929 | #ifdef CONFIG_BLK_DEV_INITRD | 990 | #ifdef CONFIG_BLK_DEV_INITRD |
@@ -1412,13 +1473,13 @@ void __init setup_per_cpu_areas(void) | |||
1412 | for (i = 0; i < size; i += PAGE_SIZE, ++pfn, ++pg) { | 1473 | for (i = 0; i < size; i += PAGE_SIZE, ++pfn, ++pg) { |
1413 | 1474 | ||
1414 | /* Update the vmalloc mapping and page home. */ | 1475 | /* Update the vmalloc mapping and page home. */ |
1415 | pte_t *ptep = | 1476 | unsigned long addr = (unsigned long)ptr + i; |
1416 | virt_to_pte(NULL, (unsigned long)ptr + i); | 1477 | pte_t *ptep = virt_to_pte(NULL, addr); |
1417 | pte_t pte = *ptep; | 1478 | pte_t pte = *ptep; |
1418 | BUG_ON(pfn != pte_pfn(pte)); | 1479 | BUG_ON(pfn != pte_pfn(pte)); |
1419 | pte = hv_pte_set_mode(pte, HV_PTE_MODE_CACHE_TILE_L3); | 1480 | pte = hv_pte_set_mode(pte, HV_PTE_MODE_CACHE_TILE_L3); |
1420 | pte = set_remote_cache_cpu(pte, cpu); | 1481 | pte = set_remote_cache_cpu(pte, cpu); |
1421 | set_pte(ptep, pte); | 1482 | set_pte_at(&init_mm, addr, ptep, pte); |
1422 | 1483 | ||
1423 | /* Update the lowmem mapping for consistency. */ | 1484 | /* Update the lowmem mapping for consistency. */ |
1424 | lowmem_va = (unsigned long)pfn_to_kaddr(pfn); | 1485 | lowmem_va = (unsigned long)pfn_to_kaddr(pfn); |
@@ -1431,7 +1492,7 @@ void __init setup_per_cpu_areas(void) | |||
1431 | BUG_ON(pte_huge(*ptep)); | 1492 | BUG_ON(pte_huge(*ptep)); |
1432 | } | 1493 | } |
1433 | BUG_ON(pfn != pte_pfn(*ptep)); | 1494 | BUG_ON(pfn != pte_pfn(*ptep)); |
1434 | set_pte(ptep, pte); | 1495 | set_pte_at(&init_mm, lowmem_va, ptep, pte); |
1435 | } | 1496 | } |
1436 | } | 1497 | } |
1437 | 1498 | ||