diff options
Diffstat (limited to 'arch/ppc64')
-rw-r--r-- | arch/ppc64/kernel/mpic.c | 4 | ||||
-rw-r--r-- | arch/ppc64/kernel/vdso.c | 12 | ||||
-rw-r--r-- | arch/ppc64/mm/imalloc.c | 5 | ||||
-rw-r--r-- | arch/ppc64/mm/init.c | 87 |
4 files changed, 93 insertions, 15 deletions
diff --git a/arch/ppc64/kernel/mpic.c b/arch/ppc64/kernel/mpic.c index cc262a05ddb4..5f5bc73754d9 100644 --- a/arch/ppc64/kernel/mpic.c +++ b/arch/ppc64/kernel/mpic.c | |||
@@ -506,8 +506,8 @@ struct mpic * __init mpic_alloc(unsigned long phys_addr, | |||
506 | mpic->senses_count = senses_count; | 506 | mpic->senses_count = senses_count; |
507 | 507 | ||
508 | /* Map the global registers */ | 508 | /* Map the global registers */ |
509 | mpic->gregs = ioremap(phys_addr + MPIC_GREG_BASE, 0x1000); | 509 | mpic->gregs = ioremap(phys_addr + MPIC_GREG_BASE, 0x2000); |
510 | mpic->tmregs = mpic->gregs + (MPIC_TIMER_BASE >> 2); | 510 | mpic->tmregs = mpic->gregs + ((MPIC_TIMER_BASE - MPIC_GREG_BASE) >> 2); |
511 | BUG_ON(mpic->gregs == NULL); | 511 | BUG_ON(mpic->gregs == NULL); |
512 | 512 | ||
513 | /* Reset */ | 513 | /* Reset */ |
diff --git a/arch/ppc64/kernel/vdso.c b/arch/ppc64/kernel/vdso.c index efa985f05aca..4aacf521e3e4 100644 --- a/arch/ppc64/kernel/vdso.c +++ b/arch/ppc64/kernel/vdso.c | |||
@@ -176,13 +176,13 @@ static struct page * vdso_vma_nopage(struct vm_area_struct * vma, | |||
176 | return NOPAGE_SIGBUS; | 176 | return NOPAGE_SIGBUS; |
177 | 177 | ||
178 | /* | 178 | /* |
179 | * Last page is systemcfg, special handling here, no get_page() a | 179 | * Last page is systemcfg. |
180 | * this is a reserved page | ||
181 | */ | 180 | */ |
182 | if ((vma->vm_end - address) <= PAGE_SIZE) | 181 | if ((vma->vm_end - address) <= PAGE_SIZE) |
183 | return virt_to_page(systemcfg); | 182 | pg = virt_to_page(systemcfg); |
183 | else | ||
184 | pg = virt_to_page(vbase + offset); | ||
184 | 185 | ||
185 | pg = virt_to_page(vbase + offset); | ||
186 | get_page(pg); | 186 | get_page(pg); |
187 | DBG(" ->page count: %d\n", page_count(pg)); | 187 | DBG(" ->page count: %d\n", page_count(pg)); |
188 | 188 | ||
@@ -259,7 +259,7 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, int executable_stack) | |||
259 | * gettimeofday will be totally dead. It's fine to use that for setting | 259 | * gettimeofday will be totally dead. It's fine to use that for setting |
260 | * breakpoints in the vDSO code pages though | 260 | * breakpoints in the vDSO code pages though |
261 | */ | 261 | */ |
262 | vma->vm_flags = VM_READ | VM_EXEC | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC; | 262 | vma->vm_flags = VM_READ | VM_EXEC | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC | VM_RESERVED; |
263 | vma->vm_flags |= mm->def_flags; | 263 | vma->vm_flags |= mm->def_flags; |
264 | vma->vm_page_prot = protection_map[vma->vm_flags & 0x7]; | 264 | vma->vm_page_prot = protection_map[vma->vm_flags & 0x7]; |
265 | vma->vm_ops = &vdso_vmops; | 265 | vma->vm_ops = &vdso_vmops; |
@@ -603,6 +603,8 @@ void __init vdso_init(void) | |||
603 | ClearPageReserved(pg); | 603 | ClearPageReserved(pg); |
604 | get_page(pg); | 604 | get_page(pg); |
605 | } | 605 | } |
606 | |||
607 | get_page(virt_to_page(systemcfg)); | ||
606 | } | 608 | } |
607 | 609 | ||
608 | int in_gate_area_no_task(unsigned long addr) | 610 | int in_gate_area_no_task(unsigned long addr) |
diff --git a/arch/ppc64/mm/imalloc.c b/arch/ppc64/mm/imalloc.c index c65b87b92756..f4ca29cf5364 100644 --- a/arch/ppc64/mm/imalloc.c +++ b/arch/ppc64/mm/imalloc.c | |||
@@ -300,12 +300,7 @@ void im_free(void * addr) | |||
300 | for (p = &imlist ; (tmp = *p) ; p = &tmp->next) { | 300 | for (p = &imlist ; (tmp = *p) ; p = &tmp->next) { |
301 | if (tmp->addr == addr) { | 301 | if (tmp->addr == addr) { |
302 | *p = tmp->next; | 302 | *p = tmp->next; |
303 | |||
304 | /* XXX: do we need the lock? */ | ||
305 | spin_lock(&init_mm.page_table_lock); | ||
306 | unmap_vm_area(tmp); | 303 | unmap_vm_area(tmp); |
307 | spin_unlock(&init_mm.page_table_lock); | ||
308 | |||
309 | kfree(tmp); | 304 | kfree(tmp); |
310 | up(&imlist_sem); | 305 | up(&imlist_sem); |
311 | return; | 306 | return; |
diff --git a/arch/ppc64/mm/init.c b/arch/ppc64/mm/init.c index be64b157afce..e2bd7776622f 100644 --- a/arch/ppc64/mm/init.c +++ b/arch/ppc64/mm/init.c | |||
@@ -104,6 +104,8 @@ void show_mem(void) | |||
104 | show_free_areas(); | 104 | show_free_areas(); |
105 | printk("Free swap: %6ldkB\n", nr_swap_pages<<(PAGE_SHIFT-10)); | 105 | printk("Free swap: %6ldkB\n", nr_swap_pages<<(PAGE_SHIFT-10)); |
106 | for_each_pgdat(pgdat) { | 106 | for_each_pgdat(pgdat) { |
107 | unsigned long flags; | ||
108 | pgdat_resize_lock(pgdat, &flags); | ||
107 | for (i = 0; i < pgdat->node_spanned_pages; i++) { | 109 | for (i = 0; i < pgdat->node_spanned_pages; i++) { |
108 | page = pgdat_page_nr(pgdat, i); | 110 | page = pgdat_page_nr(pgdat, i); |
109 | total++; | 111 | total++; |
@@ -114,6 +116,7 @@ void show_mem(void) | |||
114 | else if (page_count(page)) | 116 | else if (page_count(page)) |
115 | shared += page_count(page) - 1; | 117 | shared += page_count(page) - 1; |
116 | } | 118 | } |
119 | pgdat_resize_unlock(pgdat, &flags); | ||
117 | } | 120 | } |
118 | printk("%ld pages of RAM\n", total); | 121 | printk("%ld pages of RAM\n", total); |
119 | printk("%ld reserved pages\n", reserved); | 122 | printk("%ld reserved pages\n", reserved); |
@@ -155,7 +158,6 @@ static int map_io_page(unsigned long ea, unsigned long pa, int flags) | |||
155 | unsigned long vsid; | 158 | unsigned long vsid; |
156 | 159 | ||
157 | if (mem_init_done) { | 160 | if (mem_init_done) { |
158 | spin_lock(&init_mm.page_table_lock); | ||
159 | pgdp = pgd_offset_k(ea); | 161 | pgdp = pgd_offset_k(ea); |
160 | pudp = pud_alloc(&init_mm, pgdp, ea); | 162 | pudp = pud_alloc(&init_mm, pgdp, ea); |
161 | if (!pudp) | 163 | if (!pudp) |
@@ -163,12 +165,11 @@ static int map_io_page(unsigned long ea, unsigned long pa, int flags) | |||
163 | pmdp = pmd_alloc(&init_mm, pudp, ea); | 165 | pmdp = pmd_alloc(&init_mm, pudp, ea); |
164 | if (!pmdp) | 166 | if (!pmdp) |
165 | return -ENOMEM; | 167 | return -ENOMEM; |
166 | ptep = pte_alloc_kernel(&init_mm, pmdp, ea); | 168 | ptep = pte_alloc_kernel(pmdp, ea); |
167 | if (!ptep) | 169 | if (!ptep) |
168 | return -ENOMEM; | 170 | return -ENOMEM; |
169 | set_pte_at(&init_mm, ea, ptep, pfn_pte(pa >> PAGE_SHIFT, | 171 | set_pte_at(&init_mm, ea, ptep, pfn_pte(pa >> PAGE_SHIFT, |
170 | __pgprot(flags))); | 172 | __pgprot(flags))); |
171 | spin_unlock(&init_mm.page_table_lock); | ||
172 | } else { | 173 | } else { |
173 | unsigned long va, vpn, hash, hpteg; | 174 | unsigned long va, vpn, hash, hpteg; |
174 | 175 | ||
@@ -649,11 +650,14 @@ void __init mem_init(void) | |||
649 | #endif | 650 | #endif |
650 | 651 | ||
651 | for_each_pgdat(pgdat) { | 652 | for_each_pgdat(pgdat) { |
653 | unsigned long flags; | ||
654 | pgdat_resize_lock(pgdat, &flags); | ||
652 | for (i = 0; i < pgdat->node_spanned_pages; i++) { | 655 | for (i = 0; i < pgdat->node_spanned_pages; i++) { |
653 | page = pgdat_page_nr(pgdat, i); | 656 | page = pgdat_page_nr(pgdat, i); |
654 | if (PageReserved(page)) | 657 | if (PageReserved(page)) |
655 | reservedpages++; | 658 | reservedpages++; |
656 | } | 659 | } |
660 | pgdat_resize_unlock(pgdat, &flags); | ||
657 | } | 661 | } |
658 | 662 | ||
659 | codesize = (unsigned long)&_etext - (unsigned long)&_stext; | 663 | codesize = (unsigned long)&_etext - (unsigned long)&_stext; |
@@ -867,3 +871,80 @@ pgprot_t phys_mem_access_prot(struct file *file, unsigned long addr, | |||
867 | return vma_prot; | 871 | return vma_prot; |
868 | } | 872 | } |
869 | EXPORT_SYMBOL(phys_mem_access_prot); | 873 | EXPORT_SYMBOL(phys_mem_access_prot); |
874 | |||
875 | #ifdef CONFIG_MEMORY_HOTPLUG | ||
876 | |||
877 | void online_page(struct page *page) | ||
878 | { | ||
879 | ClearPageReserved(page); | ||
880 | free_cold_page(page); | ||
881 | totalram_pages++; | ||
882 | num_physpages++; | ||
883 | } | ||
884 | |||
885 | /* | ||
886 | * This works only for the non-NUMA case. Later, we'll need a lookup | ||
887 | * to convert from real physical addresses to nid, that doesn't use | ||
888 | * pfn_to_nid(). | ||
889 | */ | ||
890 | int __devinit add_memory(u64 start, u64 size) | ||
891 | { | ||
892 | struct pglist_data *pgdata = NODE_DATA(0); | ||
893 | struct zone *zone; | ||
894 | unsigned long start_pfn = start >> PAGE_SHIFT; | ||
895 | unsigned long nr_pages = size >> PAGE_SHIFT; | ||
896 | |||
897 | /* this should work for most non-highmem platforms */ | ||
898 | zone = pgdata->node_zones; | ||
899 | |||
900 | return __add_pages(zone, start_pfn, nr_pages); | ||
901 | |||
902 | return 0; | ||
903 | } | ||
904 | |||
905 | /* | ||
906 | * First pass at this code will check to determine if the remove | ||
907 | * request is within the RMO. Do not allow removal within the RMO. | ||
908 | */ | ||
909 | int __devinit remove_memory(u64 start, u64 size) | ||
910 | { | ||
911 | struct zone *zone; | ||
912 | unsigned long start_pfn, end_pfn, nr_pages; | ||
913 | |||
914 | start_pfn = start >> PAGE_SHIFT; | ||
915 | nr_pages = size >> PAGE_SHIFT; | ||
916 | end_pfn = start_pfn + nr_pages; | ||
917 | |||
918 | printk("%s(): Attempting to remove memoy in range " | ||
919 | "%lx to %lx\n", __func__, start, start+size); | ||
920 | /* | ||
921 | * check for range within RMO | ||
922 | */ | ||
923 | zone = page_zone(pfn_to_page(start_pfn)); | ||
924 | |||
925 | printk("%s(): memory will be removed from " | ||
926 | "the %s zone\n", __func__, zone->name); | ||
927 | |||
928 | /* | ||
929 | * not handling removing memory ranges that | ||
930 | * overlap multiple zones yet | ||
931 | */ | ||
932 | if (end_pfn > (zone->zone_start_pfn + zone->spanned_pages)) | ||
933 | goto overlap; | ||
934 | |||
935 | /* make sure it is NOT in RMO */ | ||
936 | if ((start < lmb.rmo_size) || ((start+size) < lmb.rmo_size)) { | ||
937 | printk("%s(): range to be removed must NOT be in RMO!\n", | ||
938 | __func__); | ||
939 | goto in_rmo; | ||
940 | } | ||
941 | |||
942 | return __remove_pages(zone, start_pfn, nr_pages); | ||
943 | |||
944 | overlap: | ||
945 | printk("%s(): memory range to be removed overlaps " | ||
946 | "multiple zones!!!\n", __func__); | ||
947 | in_rmo: | ||
948 | return -1; | ||
949 | } | ||
950 | #endif /* CONFIG_MEMORY_HOTPLUG */ | ||