diff options
Diffstat (limited to 'arch/x86_64')
-rw-r--r-- | arch/x86_64/Kconfig | 4 | ||||
-rw-r--r-- | arch/x86_64/kernel/e820.c | 48 | ||||
-rw-r--r-- | arch/x86_64/kernel/setup.c | 1 | ||||
-rw-r--r-- | arch/x86_64/kernel/smpboot.c | 3 | ||||
-rw-r--r-- | arch/x86_64/kernel/suspend_asm.S | 2 | ||||
-rw-r--r-- | arch/x86_64/kernel/time.c | 37 | ||||
-rw-r--r-- | arch/x86_64/mm/fault.c | 6 | ||||
-rw-r--r-- | arch/x86_64/mm/init.c | 2 |
8 files changed, 91 insertions, 12 deletions
diff --git a/arch/x86_64/Kconfig b/arch/x86_64/Kconfig index 6cd4878625f1..581ce9af0ec8 100644 --- a/arch/x86_64/Kconfig +++ b/arch/x86_64/Kconfig | |||
@@ -24,6 +24,10 @@ config X86 | |||
24 | bool | 24 | bool |
25 | default y | 25 | default y |
26 | 26 | ||
27 | config ZONE_DMA32 | ||
28 | bool | ||
29 | default y | ||
30 | |||
27 | config LOCKDEP_SUPPORT | 31 | config LOCKDEP_SUPPORT |
28 | bool | 32 | bool |
29 | default y | 33 | default y |
diff --git a/arch/x86_64/kernel/e820.c b/arch/x86_64/kernel/e820.c index d6d7f731f6f0..708a3cd9a27e 100644 --- a/arch/x86_64/kernel/e820.c +++ b/arch/x86_64/kernel/e820.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <linux/string.h> | 16 | #include <linux/string.h> |
17 | #include <linux/kexec.h> | 17 | #include <linux/kexec.h> |
18 | #include <linux/module.h> | 18 | #include <linux/module.h> |
19 | #include <linux/mm.h> | ||
19 | 20 | ||
20 | #include <asm/pgtable.h> | 21 | #include <asm/pgtable.h> |
21 | #include <asm/page.h> | 22 | #include <asm/page.h> |
@@ -297,6 +298,53 @@ void __init e820_reserve_resources(void) | |||
297 | } | 298 | } |
298 | } | 299 | } |
299 | 300 | ||
301 | /* Mark pages corresponding to given address range as nosave */ | ||
302 | static void __init | ||
303 | e820_mark_nosave_range(unsigned long start, unsigned long end) | ||
304 | { | ||
305 | unsigned long pfn, max_pfn; | ||
306 | |||
307 | if (start >= end) | ||
308 | return; | ||
309 | |||
310 | printk("Nosave address range: %016lx - %016lx\n", start, end); | ||
311 | max_pfn = end >> PAGE_SHIFT; | ||
312 | for (pfn = start >> PAGE_SHIFT; pfn < max_pfn; pfn++) | ||
313 | if (pfn_valid(pfn)) | ||
314 | SetPageNosave(pfn_to_page(pfn)); | ||
315 | } | ||
316 | |||
317 | /* | ||
318 | * Find the ranges of physical addresses that do not correspond to | ||
319 | * e820 RAM areas and mark the corresponding pages as nosave for software | ||
320 | * suspend and suspend to RAM. | ||
321 | * | ||
322 | * This function requires the e820 map to be sorted and without any | ||
323 | * overlapping entries and assumes the first e820 area to be RAM. | ||
324 | */ | ||
325 | void __init e820_mark_nosave_regions(void) | ||
326 | { | ||
327 | int i; | ||
328 | unsigned long paddr; | ||
329 | |||
330 | paddr = round_down(e820.map[0].addr + e820.map[0].size, PAGE_SIZE); | ||
331 | for (i = 1; i < e820.nr_map; i++) { | ||
332 | struct e820entry *ei = &e820.map[i]; | ||
333 | |||
334 | if (paddr < ei->addr) | ||
335 | e820_mark_nosave_range(paddr, | ||
336 | round_up(ei->addr, PAGE_SIZE)); | ||
337 | |||
338 | paddr = round_down(ei->addr + ei->size, PAGE_SIZE); | ||
339 | if (ei->type != E820_RAM) | ||
340 | e820_mark_nosave_range(round_up(ei->addr, PAGE_SIZE), | ||
341 | paddr); | ||
342 | |||
343 | if (paddr >= (end_pfn << PAGE_SHIFT)) | ||
344 | break; | ||
345 | } | ||
346 | } | ||
347 | |||
300 | /* | 348 | /* |
301 | * Add a memory region to the kernel e820 map. | 349 | * Add a memory region to the kernel e820 map. |
302 | */ | 350 | */ |
diff --git a/arch/x86_64/kernel/setup.c b/arch/x86_64/kernel/setup.c index 34afad704824..4b39f0da17f3 100644 --- a/arch/x86_64/kernel/setup.c +++ b/arch/x86_64/kernel/setup.c | |||
@@ -689,6 +689,7 @@ void __init setup_arch(char **cmdline_p) | |||
689 | */ | 689 | */ |
690 | probe_roms(); | 690 | probe_roms(); |
691 | e820_reserve_resources(); | 691 | e820_reserve_resources(); |
692 | e820_mark_nosave_regions(); | ||
692 | 693 | ||
693 | request_resource(&iomem_resource, &video_ram_resource); | 694 | request_resource(&iomem_resource, &video_ram_resource); |
694 | 695 | ||
diff --git a/arch/x86_64/kernel/smpboot.c b/arch/x86_64/kernel/smpboot.c index 975380207b46..3ae9ffddddc0 100644 --- a/arch/x86_64/kernel/smpboot.c +++ b/arch/x86_64/kernel/smpboot.c | |||
@@ -46,9 +46,10 @@ | |||
46 | #include <linux/bootmem.h> | 46 | #include <linux/bootmem.h> |
47 | #include <linux/thread_info.h> | 47 | #include <linux/thread_info.h> |
48 | #include <linux/module.h> | 48 | #include <linux/module.h> |
49 | |||
50 | #include <linux/delay.h> | 49 | #include <linux/delay.h> |
51 | #include <linux/mc146818rtc.h> | 50 | #include <linux/mc146818rtc.h> |
51 | #include <linux/smp.h> | ||
52 | |||
52 | #include <asm/mtrr.h> | 53 | #include <asm/mtrr.h> |
53 | #include <asm/pgalloc.h> | 54 | #include <asm/pgalloc.h> |
54 | #include <asm/desc.h> | 55 | #include <asm/desc.h> |
diff --git a/arch/x86_64/kernel/suspend_asm.S b/arch/x86_64/kernel/suspend_asm.S index 320b6fb00cca..bfbe00763c68 100644 --- a/arch/x86_64/kernel/suspend_asm.S +++ b/arch/x86_64/kernel/suspend_asm.S | |||
@@ -54,7 +54,7 @@ ENTRY(restore_image) | |||
54 | movq %rcx, %cr3; | 54 | movq %rcx, %cr3; |
55 | movq %rax, %cr4; # turn PGE back on | 55 | movq %rax, %cr4; # turn PGE back on |
56 | 56 | ||
57 | movq pagedir_nosave(%rip), %rdx | 57 | movq restore_pblist(%rip), %rdx |
58 | loop: | 58 | loop: |
59 | testq %rdx, %rdx | 59 | testq %rdx, %rdx |
60 | jz done | 60 | jz done |
diff --git a/arch/x86_64/kernel/time.c b/arch/x86_64/kernel/time.c index 7a9b18224182..7700e6cd2bd9 100644 --- a/arch/x86_64/kernel/time.c +++ b/arch/x86_64/kernel/time.c | |||
@@ -1148,23 +1148,25 @@ int hpet_rtc_timer_init(void) | |||
1148 | hpet_rtc_int_freq = DEFAULT_RTC_INT_FREQ; | 1148 | hpet_rtc_int_freq = DEFAULT_RTC_INT_FREQ; |
1149 | 1149 | ||
1150 | local_irq_save(flags); | 1150 | local_irq_save(flags); |
1151 | |||
1151 | cnt = hpet_readl(HPET_COUNTER); | 1152 | cnt = hpet_readl(HPET_COUNTER); |
1152 | cnt += ((hpet_tick*HZ)/hpet_rtc_int_freq); | 1153 | cnt += ((hpet_tick*HZ)/hpet_rtc_int_freq); |
1153 | hpet_writel(cnt, HPET_T1_CMP); | 1154 | hpet_writel(cnt, HPET_T1_CMP); |
1154 | hpet_t1_cmp = cnt; | 1155 | hpet_t1_cmp = cnt; |
1155 | local_irq_restore(flags); | ||
1156 | 1156 | ||
1157 | cfg = hpet_readl(HPET_T1_CFG); | 1157 | cfg = hpet_readl(HPET_T1_CFG); |
1158 | cfg &= ~HPET_TN_PERIODIC; | 1158 | cfg &= ~HPET_TN_PERIODIC; |
1159 | cfg |= HPET_TN_ENABLE | HPET_TN_32BIT; | 1159 | cfg |= HPET_TN_ENABLE | HPET_TN_32BIT; |
1160 | hpet_writel(cfg, HPET_T1_CFG); | 1160 | hpet_writel(cfg, HPET_T1_CFG); |
1161 | 1161 | ||
1162 | local_irq_restore(flags); | ||
1163 | |||
1162 | return 1; | 1164 | return 1; |
1163 | } | 1165 | } |
1164 | 1166 | ||
1165 | static void hpet_rtc_timer_reinit(void) | 1167 | static void hpet_rtc_timer_reinit(void) |
1166 | { | 1168 | { |
1167 | unsigned int cfg, cnt; | 1169 | unsigned int cfg, cnt, ticks_per_int, lost_ints; |
1168 | 1170 | ||
1169 | if (unlikely(!(PIE_on | AIE_on | UIE_on))) { | 1171 | if (unlikely(!(PIE_on | AIE_on | UIE_on))) { |
1170 | cfg = hpet_readl(HPET_T1_CFG); | 1172 | cfg = hpet_readl(HPET_T1_CFG); |
@@ -1179,10 +1181,33 @@ static void hpet_rtc_timer_reinit(void) | |||
1179 | hpet_rtc_int_freq = DEFAULT_RTC_INT_FREQ; | 1181 | hpet_rtc_int_freq = DEFAULT_RTC_INT_FREQ; |
1180 | 1182 | ||
1181 | /* It is more accurate to use the comparator value than current count.*/ | 1183 | /* It is more accurate to use the comparator value than current count.*/ |
1182 | cnt = hpet_t1_cmp; | 1184 | ticks_per_int = hpet_tick * HZ / hpet_rtc_int_freq; |
1183 | cnt += hpet_tick*HZ/hpet_rtc_int_freq; | 1185 | hpet_t1_cmp += ticks_per_int; |
1184 | hpet_writel(cnt, HPET_T1_CMP); | 1186 | hpet_writel(hpet_t1_cmp, HPET_T1_CMP); |
1185 | hpet_t1_cmp = cnt; | 1187 | |
1188 | /* | ||
1189 | * If the interrupt handler was delayed too long, the write above tries | ||
1190 | * to schedule the next interrupt in the past and the hardware would | ||
1191 | * not interrupt until the counter had wrapped around. | ||
1192 | * So we have to check that the comparator wasn't set to a past time. | ||
1193 | */ | ||
1194 | cnt = hpet_readl(HPET_COUNTER); | ||
1195 | if (unlikely((int)(cnt - hpet_t1_cmp) > 0)) { | ||
1196 | lost_ints = (cnt - hpet_t1_cmp) / ticks_per_int + 1; | ||
1197 | /* Make sure that, even with the time needed to execute | ||
1198 | * this code, the next scheduled interrupt has been moved | ||
1199 | * back to the future: */ | ||
1200 | lost_ints++; | ||
1201 | |||
1202 | hpet_t1_cmp += lost_ints * ticks_per_int; | ||
1203 | hpet_writel(hpet_t1_cmp, HPET_T1_CMP); | ||
1204 | |||
1205 | if (PIE_on) | ||
1206 | PIE_count += lost_ints; | ||
1207 | |||
1208 | printk(KERN_WARNING "rtc: lost some interrupts at %ldHz.\n", | ||
1209 | hpet_rtc_int_freq); | ||
1210 | } | ||
1186 | } | 1211 | } |
1187 | 1212 | ||
1188 | /* | 1213 | /* |
diff --git a/arch/x86_64/mm/fault.c b/arch/x86_64/mm/fault.c index ac8ea66ccb94..4198798e1469 100644 --- a/arch/x86_64/mm/fault.c +++ b/arch/x86_64/mm/fault.c | |||
@@ -299,7 +299,7 @@ static int vmalloc_fault(unsigned long address) | |||
299 | if (pgd_none(*pgd)) | 299 | if (pgd_none(*pgd)) |
300 | set_pgd(pgd, *pgd_ref); | 300 | set_pgd(pgd, *pgd_ref); |
301 | else | 301 | else |
302 | BUG_ON(pgd_page(*pgd) != pgd_page(*pgd_ref)); | 302 | BUG_ON(pgd_page_vaddr(*pgd) != pgd_page_vaddr(*pgd_ref)); |
303 | 303 | ||
304 | /* Below here mismatches are bugs because these lower tables | 304 | /* Below here mismatches are bugs because these lower tables |
305 | are shared */ | 305 | are shared */ |
@@ -308,7 +308,7 @@ static int vmalloc_fault(unsigned long address) | |||
308 | pud_ref = pud_offset(pgd_ref, address); | 308 | pud_ref = pud_offset(pgd_ref, address); |
309 | if (pud_none(*pud_ref)) | 309 | if (pud_none(*pud_ref)) |
310 | return -1; | 310 | return -1; |
311 | if (pud_none(*pud) || pud_page(*pud) != pud_page(*pud_ref)) | 311 | if (pud_none(*pud) || pud_page_vaddr(*pud) != pud_page_vaddr(*pud_ref)) |
312 | BUG(); | 312 | BUG(); |
313 | pmd = pmd_offset(pud, address); | 313 | pmd = pmd_offset(pud, address); |
314 | pmd_ref = pmd_offset(pud_ref, address); | 314 | pmd_ref = pmd_offset(pud_ref, address); |
@@ -641,7 +641,7 @@ void vmalloc_sync_all(void) | |||
641 | if (pgd_none(*pgd)) | 641 | if (pgd_none(*pgd)) |
642 | set_pgd(pgd, *pgd_ref); | 642 | set_pgd(pgd, *pgd_ref); |
643 | else | 643 | else |
644 | BUG_ON(pgd_page(*pgd) != pgd_page(*pgd_ref)); | 644 | BUG_ON(pgd_page_vaddr(*pgd) != pgd_page_vaddr(*pgd_ref)); |
645 | } | 645 | } |
646 | spin_unlock(&pgd_lock); | 646 | spin_unlock(&pgd_lock); |
647 | set_bit(pgd_index(address), insync); | 647 | set_bit(pgd_index(address), insync); |
diff --git a/arch/x86_64/mm/init.c b/arch/x86_64/mm/init.c index d14fb2dfbfc4..52fd42c40c86 100644 --- a/arch/x86_64/mm/init.c +++ b/arch/x86_64/mm/init.c | |||
@@ -536,7 +536,7 @@ int memory_add_physaddr_to_nid(u64 start) | |||
536 | int arch_add_memory(int nid, u64 start, u64 size) | 536 | int arch_add_memory(int nid, u64 start, u64 size) |
537 | { | 537 | { |
538 | struct pglist_data *pgdat = NODE_DATA(nid); | 538 | struct pglist_data *pgdat = NODE_DATA(nid); |
539 | struct zone *zone = pgdat->node_zones + MAX_NR_ZONES-2; | 539 | struct zone *zone = pgdat->node_zones + ZONE_NORMAL; |
540 | unsigned long start_pfn = start >> PAGE_SHIFT; | 540 | unsigned long start_pfn = start >> PAGE_SHIFT; |
541 | unsigned long nr_pages = size >> PAGE_SHIFT; | 541 | unsigned long nr_pages = size >> PAGE_SHIFT; |
542 | int ret; | 542 | int ret; |