diff options
Diffstat (limited to 'arch/x86/kernel')
-rw-r--r-- | arch/x86/kernel/acpi/boot.c | 31 | ||||
-rw-r--r-- | arch/x86/kernel/apic.c | 51 | ||||
-rw-r--r-- | arch/x86/kernel/dumpstack.c | 2 | ||||
-rw-r--r-- | arch/x86/kernel/early_printk.c | 2 | ||||
-rw-r--r-- | arch/x86/kernel/es7000_32.c | 9 | ||||
-rw-r--r-- | arch/x86/kernel/machine_kexec_64.c | 82 | ||||
-rw-r--r-- | arch/x86/kernel/relocate_kernel_64.S | 125 | ||||
-rw-r--r-- | arch/x86/kernel/trampoline_64.S | 19 |
8 files changed, 116 insertions, 205 deletions
diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c index bba162c81d5b..956c1dee6fbe 100644 --- a/arch/x86/kernel/acpi/boot.c +++ b/arch/x86/kernel/acpi/boot.c | |||
@@ -108,35 +108,18 @@ enum acpi_irq_model_id acpi_irq_model = ACPI_IRQ_MODEL_PIC; | |||
108 | */ | 108 | */ |
109 | char *__init __acpi_map_table(unsigned long phys, unsigned long size) | 109 | char *__init __acpi_map_table(unsigned long phys, unsigned long size) |
110 | { | 110 | { |
111 | unsigned long base, offset, mapped_size; | ||
112 | int idx; | ||
113 | 111 | ||
114 | if (!phys || !size) | 112 | if (!phys || !size) |
115 | return NULL; | 113 | return NULL; |
116 | 114 | ||
117 | if (phys+size <= (max_low_pfn_mapped << PAGE_SHIFT)) | 115 | return early_ioremap(phys, size); |
118 | return __va(phys); | 116 | } |
119 | 117 | void __init __acpi_unmap_table(char *map, unsigned long size) | |
120 | offset = phys & (PAGE_SIZE - 1); | 118 | { |
121 | mapped_size = PAGE_SIZE - offset; | 119 | if (!map || !size) |
122 | clear_fixmap(FIX_ACPI_END); | 120 | return; |
123 | set_fixmap(FIX_ACPI_END, phys); | ||
124 | base = fix_to_virt(FIX_ACPI_END); | ||
125 | |||
126 | /* | ||
127 | * Most cases can be covered by the below. | ||
128 | */ | ||
129 | idx = FIX_ACPI_END; | ||
130 | while (mapped_size < size) { | ||
131 | if (--idx < FIX_ACPI_BEGIN) | ||
132 | return NULL; /* cannot handle this */ | ||
133 | phys += PAGE_SIZE; | ||
134 | clear_fixmap(idx); | ||
135 | set_fixmap(idx, phys); | ||
136 | mapped_size += PAGE_SIZE; | ||
137 | } | ||
138 | 121 | ||
139 | return ((unsigned char *)base + offset); | 122 | early_iounmap(map, size); |
140 | } | 123 | } |
141 | 124 | ||
142 | #ifdef CONFIG_PCI_MMCONFIG | 125 | #ifdef CONFIG_PCI_MMCONFIG |
diff --git a/arch/x86/kernel/apic.c b/arch/x86/kernel/apic.c index 8bd801db24d9..cf2ca19e62da 100644 --- a/arch/x86/kernel/apic.c +++ b/arch/x86/kernel/apic.c | |||
@@ -555,7 +555,8 @@ static void __init lapic_cal_handler(struct clock_event_device *dev) | |||
555 | } | 555 | } |
556 | } | 556 | } |
557 | 557 | ||
558 | static int __init calibrate_by_pmtimer(long deltapm, long *delta) | 558 | static int __init |
559 | calibrate_by_pmtimer(long deltapm, long *delta, long *deltatsc) | ||
559 | { | 560 | { |
560 | const long pm_100ms = PMTMR_TICKS_PER_SEC / 10; | 561 | const long pm_100ms = PMTMR_TICKS_PER_SEC / 10; |
561 | const long pm_thresh = pm_100ms / 100; | 562 | const long pm_thresh = pm_100ms / 100; |
@@ -566,7 +567,7 @@ static int __init calibrate_by_pmtimer(long deltapm, long *delta) | |||
566 | return -1; | 567 | return -1; |
567 | #endif | 568 | #endif |
568 | 569 | ||
569 | apic_printk(APIC_VERBOSE, "... PM timer delta = %ld\n", deltapm); | 570 | apic_printk(APIC_VERBOSE, "... PM-Timer delta = %ld\n", deltapm); |
570 | 571 | ||
571 | /* Check, if the PM timer is available */ | 572 | /* Check, if the PM timer is available */ |
572 | if (!deltapm) | 573 | if (!deltapm) |
@@ -576,19 +577,30 @@ static int __init calibrate_by_pmtimer(long deltapm, long *delta) | |||
576 | 577 | ||
577 | if (deltapm > (pm_100ms - pm_thresh) && | 578 | if (deltapm > (pm_100ms - pm_thresh) && |
578 | deltapm < (pm_100ms + pm_thresh)) { | 579 | deltapm < (pm_100ms + pm_thresh)) { |
579 | apic_printk(APIC_VERBOSE, "... PM timer result ok\n"); | 580 | apic_printk(APIC_VERBOSE, "... PM-Timer result ok\n"); |
580 | } else { | 581 | return 0; |
581 | res = (((u64)deltapm) * mult) >> 22; | 582 | } |
582 | do_div(res, 1000000); | 583 | |
583 | pr_warning("APIC calibration not consistent " | 584 | res = (((u64)deltapm) * mult) >> 22; |
584 | "with PM Timer: %ldms instead of 100ms\n", | 585 | do_div(res, 1000000); |
585 | (long)res); | 586 | pr_warning("APIC calibration not consistent " |
586 | /* Correct the lapic counter value */ | 587 | "with PM-Timer: %ldms instead of 100ms\n",(long)res); |
587 | res = (((u64)(*delta)) * pm_100ms); | 588 | |
589 | /* Correct the lapic counter value */ | ||
590 | res = (((u64)(*delta)) * pm_100ms); | ||
591 | do_div(res, deltapm); | ||
592 | pr_info("APIC delta adjusted to PM-Timer: " | ||
593 | "%lu (%ld)\n", (unsigned long)res, *delta); | ||
594 | *delta = (long)res; | ||
595 | |||
596 | /* Correct the tsc counter value */ | ||
597 | if (cpu_has_tsc) { | ||
598 | res = (((u64)(*deltatsc)) * pm_100ms); | ||
588 | do_div(res, deltapm); | 599 | do_div(res, deltapm); |
589 | pr_info("APIC delta adjusted to PM-Timer: " | 600 | apic_printk(APIC_VERBOSE, "TSC delta adjusted to " |
590 | "%lu (%ld)\n", (unsigned long)res, *delta); | 601 | "PM-Timer: %lu (%ld) \n", |
591 | *delta = (long)res; | 602 | (unsigned long)res, *deltatsc); |
603 | *deltatsc = (long)res; | ||
592 | } | 604 | } |
593 | 605 | ||
594 | return 0; | 606 | return 0; |
@@ -599,7 +611,7 @@ static int __init calibrate_APIC_clock(void) | |||
599 | struct clock_event_device *levt = &__get_cpu_var(lapic_events); | 611 | struct clock_event_device *levt = &__get_cpu_var(lapic_events); |
600 | void (*real_handler)(struct clock_event_device *dev); | 612 | void (*real_handler)(struct clock_event_device *dev); |
601 | unsigned long deltaj; | 613 | unsigned long deltaj; |
602 | long delta; | 614 | long delta, deltatsc; |
603 | int pm_referenced = 0; | 615 | int pm_referenced = 0; |
604 | 616 | ||
605 | local_irq_disable(); | 617 | local_irq_disable(); |
@@ -629,9 +641,11 @@ static int __init calibrate_APIC_clock(void) | |||
629 | delta = lapic_cal_t1 - lapic_cal_t2; | 641 | delta = lapic_cal_t1 - lapic_cal_t2; |
630 | apic_printk(APIC_VERBOSE, "... lapic delta = %ld\n", delta); | 642 | apic_printk(APIC_VERBOSE, "... lapic delta = %ld\n", delta); |
631 | 643 | ||
644 | deltatsc = (long)(lapic_cal_tsc2 - lapic_cal_tsc1); | ||
645 | |||
632 | /* we trust the PM based calibration if possible */ | 646 | /* we trust the PM based calibration if possible */ |
633 | pm_referenced = !calibrate_by_pmtimer(lapic_cal_pm2 - lapic_cal_pm1, | 647 | pm_referenced = !calibrate_by_pmtimer(lapic_cal_pm2 - lapic_cal_pm1, |
634 | &delta); | 648 | &delta, &deltatsc); |
635 | 649 | ||
636 | /* Calculate the scaled math multiplication factor */ | 650 | /* Calculate the scaled math multiplication factor */ |
637 | lapic_clockevent.mult = div_sc(delta, TICK_NSEC * LAPIC_CAL_LOOPS, | 651 | lapic_clockevent.mult = div_sc(delta, TICK_NSEC * LAPIC_CAL_LOOPS, |
@@ -649,11 +663,10 @@ static int __init calibrate_APIC_clock(void) | |||
649 | calibration_result); | 663 | calibration_result); |
650 | 664 | ||
651 | if (cpu_has_tsc) { | 665 | if (cpu_has_tsc) { |
652 | delta = (long)(lapic_cal_tsc2 - lapic_cal_tsc1); | ||
653 | apic_printk(APIC_VERBOSE, "..... CPU clock speed is " | 666 | apic_printk(APIC_VERBOSE, "..... CPU clock speed is " |
654 | "%ld.%04ld MHz.\n", | 667 | "%ld.%04ld MHz.\n", |
655 | (delta / LAPIC_CAL_LOOPS) / (1000000 / HZ), | 668 | (deltatsc / LAPIC_CAL_LOOPS) / (1000000 / HZ), |
656 | (delta / LAPIC_CAL_LOOPS) % (1000000 / HZ)); | 669 | (deltatsc / LAPIC_CAL_LOOPS) % (1000000 / HZ)); |
657 | } | 670 | } |
658 | 671 | ||
659 | apic_printk(APIC_VERBOSE, "..... host bus clock speed is " | 672 | apic_printk(APIC_VERBOSE, "..... host bus clock speed is " |
diff --git a/arch/x86/kernel/dumpstack.c b/arch/x86/kernel/dumpstack.c index 6b1f6f6f8661..87d103ded1c3 100644 --- a/arch/x86/kernel/dumpstack.c +++ b/arch/x86/kernel/dumpstack.c | |||
@@ -99,7 +99,7 @@ print_context_stack(struct thread_info *tinfo, | |||
99 | frame = frame->next_frame; | 99 | frame = frame->next_frame; |
100 | bp = (unsigned long) frame; | 100 | bp = (unsigned long) frame; |
101 | } else { | 101 | } else { |
102 | ops->address(data, addr, bp == 0); | 102 | ops->address(data, addr, 0); |
103 | } | 103 | } |
104 | print_ftrace_graph_addr(addr, data, ops, tinfo, graph); | 104 | print_ftrace_graph_addr(addr, data, ops, tinfo, graph); |
105 | } | 105 | } |
diff --git a/arch/x86/kernel/early_printk.c b/arch/x86/kernel/early_printk.c index 504ad198e4ad..639ad98238a2 100644 --- a/arch/x86/kernel/early_printk.c +++ b/arch/x86/kernel/early_printk.c | |||
@@ -13,8 +13,8 @@ | |||
13 | #include <asm/setup.h> | 13 | #include <asm/setup.h> |
14 | #include <xen/hvc-console.h> | 14 | #include <xen/hvc-console.h> |
15 | #include <asm/pci-direct.h> | 15 | #include <asm/pci-direct.h> |
16 | #include <asm/pgtable.h> | ||
17 | #include <asm/fixmap.h> | 16 | #include <asm/fixmap.h> |
17 | #include <asm/pgtable.h> | ||
18 | #include <linux/usb/ehci_def.h> | 18 | #include <linux/usb/ehci_def.h> |
19 | 19 | ||
20 | /* Simple VGA output */ | 20 | /* Simple VGA output */ |
diff --git a/arch/x86/kernel/es7000_32.c b/arch/x86/kernel/es7000_32.c index d6184c12a182..55515d73d9c2 100644 --- a/arch/x86/kernel/es7000_32.c +++ b/arch/x86/kernel/es7000_32.c | |||
@@ -287,24 +287,31 @@ int __init find_unisys_acpi_oem_table(unsigned long *oem_addr) | |||
287 | { | 287 | { |
288 | struct acpi_table_header *header = NULL; | 288 | struct acpi_table_header *header = NULL; |
289 | int i = 0; | 289 | int i = 0; |
290 | acpi_size tbl_size; | ||
290 | 291 | ||
291 | while (ACPI_SUCCESS(acpi_get_table("OEM1", i++, &header))) { | 292 | while (ACPI_SUCCESS(acpi_get_table_with_size("OEM1", i++, &header, &tbl_size))) { |
292 | if (!memcmp((char *) &header->oem_id, "UNISYS", 6)) { | 293 | if (!memcmp((char *) &header->oem_id, "UNISYS", 6)) { |
293 | struct oem_table *t = (struct oem_table *)header; | 294 | struct oem_table *t = (struct oem_table *)header; |
294 | 295 | ||
295 | oem_addrX = t->OEMTableAddr; | 296 | oem_addrX = t->OEMTableAddr; |
296 | oem_size = t->OEMTableSize; | 297 | oem_size = t->OEMTableSize; |
298 | early_acpi_os_unmap_memory(header, tbl_size); | ||
297 | 299 | ||
298 | *oem_addr = (unsigned long)__acpi_map_table(oem_addrX, | 300 | *oem_addr = (unsigned long)__acpi_map_table(oem_addrX, |
299 | oem_size); | 301 | oem_size); |
300 | return 0; | 302 | return 0; |
301 | } | 303 | } |
304 | early_acpi_os_unmap_memory(header, tbl_size); | ||
302 | } | 305 | } |
303 | return -1; | 306 | return -1; |
304 | } | 307 | } |
305 | 308 | ||
306 | void __init unmap_unisys_acpi_oem_table(unsigned long oem_addr) | 309 | void __init unmap_unisys_acpi_oem_table(unsigned long oem_addr) |
307 | { | 310 | { |
311 | if (!oem_addr) | ||
312 | return; | ||
313 | |||
314 | __acpi_unmap_table((char *)oem_addr, oem_size); | ||
308 | } | 315 | } |
309 | #endif | 316 | #endif |
310 | 317 | ||
diff --git a/arch/x86/kernel/machine_kexec_64.c b/arch/x86/kernel/machine_kexec_64.c index c43caa3a91f3..6993d51b7fd8 100644 --- a/arch/x86/kernel/machine_kexec_64.c +++ b/arch/x86/kernel/machine_kexec_64.c | |||
@@ -18,15 +18,6 @@ | |||
18 | #include <asm/mmu_context.h> | 18 | #include <asm/mmu_context.h> |
19 | #include <asm/io.h> | 19 | #include <asm/io.h> |
20 | 20 | ||
21 | #define PAGE_ALIGNED __attribute__ ((__aligned__(PAGE_SIZE))) | ||
22 | static u64 kexec_pgd[512] PAGE_ALIGNED; | ||
23 | static u64 kexec_pud0[512] PAGE_ALIGNED; | ||
24 | static u64 kexec_pmd0[512] PAGE_ALIGNED; | ||
25 | static u64 kexec_pte0[512] PAGE_ALIGNED; | ||
26 | static u64 kexec_pud1[512] PAGE_ALIGNED; | ||
27 | static u64 kexec_pmd1[512] PAGE_ALIGNED; | ||
28 | static u64 kexec_pte1[512] PAGE_ALIGNED; | ||
29 | |||
30 | static void init_level2_page(pmd_t *level2p, unsigned long addr) | 21 | static void init_level2_page(pmd_t *level2p, unsigned long addr) |
31 | { | 22 | { |
32 | unsigned long end_addr; | 23 | unsigned long end_addr; |
@@ -107,12 +98,65 @@ out: | |||
107 | return result; | 98 | return result; |
108 | } | 99 | } |
109 | 100 | ||
101 | static void free_transition_pgtable(struct kimage *image) | ||
102 | { | ||
103 | free_page((unsigned long)image->arch.pud); | ||
104 | free_page((unsigned long)image->arch.pmd); | ||
105 | free_page((unsigned long)image->arch.pte); | ||
106 | } | ||
107 | |||
108 | static int init_transition_pgtable(struct kimage *image, pgd_t *pgd) | ||
109 | { | ||
110 | pud_t *pud; | ||
111 | pmd_t *pmd; | ||
112 | pte_t *pte; | ||
113 | unsigned long vaddr, paddr; | ||
114 | int result = -ENOMEM; | ||
115 | |||
116 | vaddr = (unsigned long)relocate_kernel; | ||
117 | paddr = __pa(page_address(image->control_code_page)+PAGE_SIZE); | ||
118 | pgd += pgd_index(vaddr); | ||
119 | if (!pgd_present(*pgd)) { | ||
120 | pud = (pud_t *)get_zeroed_page(GFP_KERNEL); | ||
121 | if (!pud) | ||
122 | goto err; | ||
123 | image->arch.pud = pud; | ||
124 | set_pgd(pgd, __pgd(__pa(pud) | _KERNPG_TABLE)); | ||
125 | } | ||
126 | pud = pud_offset(pgd, vaddr); | ||
127 | if (!pud_present(*pud)) { | ||
128 | pmd = (pmd_t *)get_zeroed_page(GFP_KERNEL); | ||
129 | if (!pmd) | ||
130 | goto err; | ||
131 | image->arch.pmd = pmd; | ||
132 | set_pud(pud, __pud(__pa(pmd) | _KERNPG_TABLE)); | ||
133 | } | ||
134 | pmd = pmd_offset(pud, vaddr); | ||
135 | if (!pmd_present(*pmd)) { | ||
136 | pte = (pte_t *)get_zeroed_page(GFP_KERNEL); | ||
137 | if (!pte) | ||
138 | goto err; | ||
139 | image->arch.pte = pte; | ||
140 | set_pmd(pmd, __pmd(__pa(pte) | _KERNPG_TABLE)); | ||
141 | } | ||
142 | pte = pte_offset_kernel(pmd, vaddr); | ||
143 | set_pte(pte, pfn_pte(paddr >> PAGE_SHIFT, PAGE_KERNEL_EXEC)); | ||
144 | return 0; | ||
145 | err: | ||
146 | free_transition_pgtable(image); | ||
147 | return result; | ||
148 | } | ||
149 | |||
110 | 150 | ||
111 | static int init_pgtable(struct kimage *image, unsigned long start_pgtable) | 151 | static int init_pgtable(struct kimage *image, unsigned long start_pgtable) |
112 | { | 152 | { |
113 | pgd_t *level4p; | 153 | pgd_t *level4p; |
154 | int result; | ||
114 | level4p = (pgd_t *)__va(start_pgtable); | 155 | level4p = (pgd_t *)__va(start_pgtable); |
115 | return init_level4_page(image, level4p, 0, max_pfn << PAGE_SHIFT); | 156 | result = init_level4_page(image, level4p, 0, max_pfn << PAGE_SHIFT); |
157 | if (result) | ||
158 | return result; | ||
159 | return init_transition_pgtable(image, level4p); | ||
116 | } | 160 | } |
117 | 161 | ||
118 | static void set_idt(void *newidt, u16 limit) | 162 | static void set_idt(void *newidt, u16 limit) |
@@ -174,7 +218,7 @@ int machine_kexec_prepare(struct kimage *image) | |||
174 | 218 | ||
175 | void machine_kexec_cleanup(struct kimage *image) | 219 | void machine_kexec_cleanup(struct kimage *image) |
176 | { | 220 | { |
177 | return; | 221 | free_transition_pgtable(image); |
178 | } | 222 | } |
179 | 223 | ||
180 | /* | 224 | /* |
@@ -195,22 +239,6 @@ void machine_kexec(struct kimage *image) | |||
195 | memcpy(control_page, relocate_kernel, PAGE_SIZE); | 239 | memcpy(control_page, relocate_kernel, PAGE_SIZE); |
196 | 240 | ||
197 | page_list[PA_CONTROL_PAGE] = virt_to_phys(control_page); | 241 | page_list[PA_CONTROL_PAGE] = virt_to_phys(control_page); |
198 | page_list[VA_CONTROL_PAGE] = (unsigned long)relocate_kernel; | ||
199 | page_list[PA_PGD] = virt_to_phys(&kexec_pgd); | ||
200 | page_list[VA_PGD] = (unsigned long)kexec_pgd; | ||
201 | page_list[PA_PUD_0] = virt_to_phys(&kexec_pud0); | ||
202 | page_list[VA_PUD_0] = (unsigned long)kexec_pud0; | ||
203 | page_list[PA_PMD_0] = virt_to_phys(&kexec_pmd0); | ||
204 | page_list[VA_PMD_0] = (unsigned long)kexec_pmd0; | ||
205 | page_list[PA_PTE_0] = virt_to_phys(&kexec_pte0); | ||
206 | page_list[VA_PTE_0] = (unsigned long)kexec_pte0; | ||
207 | page_list[PA_PUD_1] = virt_to_phys(&kexec_pud1); | ||
208 | page_list[VA_PUD_1] = (unsigned long)kexec_pud1; | ||
209 | page_list[PA_PMD_1] = virt_to_phys(&kexec_pmd1); | ||
210 | page_list[VA_PMD_1] = (unsigned long)kexec_pmd1; | ||
211 | page_list[PA_PTE_1] = virt_to_phys(&kexec_pte1); | ||
212 | page_list[VA_PTE_1] = (unsigned long)kexec_pte1; | ||
213 | |||
214 | page_list[PA_TABLE_PAGE] = | 242 | page_list[PA_TABLE_PAGE] = |
215 | (unsigned long)__pa(page_address(image->control_code_page)); | 243 | (unsigned long)__pa(page_address(image->control_code_page)); |
216 | 244 | ||
diff --git a/arch/x86/kernel/relocate_kernel_64.S b/arch/x86/kernel/relocate_kernel_64.S index f5afe665a82b..b0bbdd4829c9 100644 --- a/arch/x86/kernel/relocate_kernel_64.S +++ b/arch/x86/kernel/relocate_kernel_64.S | |||
@@ -29,122 +29,6 @@ relocate_kernel: | |||
29 | * %rdx start address | 29 | * %rdx start address |
30 | */ | 30 | */ |
31 | 31 | ||
32 | /* map the control page at its virtual address */ | ||
33 | |||
34 | movq $0x0000ff8000000000, %r10 /* mask */ | ||
35 | mov $(39 - 3), %cl /* bits to shift */ | ||
36 | movq PTR(VA_CONTROL_PAGE)(%rsi), %r11 /* address to map */ | ||
37 | |||
38 | movq %r11, %r9 | ||
39 | andq %r10, %r9 | ||
40 | shrq %cl, %r9 | ||
41 | |||
42 | movq PTR(VA_PGD)(%rsi), %r8 | ||
43 | addq %r8, %r9 | ||
44 | movq PTR(PA_PUD_0)(%rsi), %r8 | ||
45 | orq $PAGE_ATTR, %r8 | ||
46 | movq %r8, (%r9) | ||
47 | |||
48 | shrq $9, %r10 | ||
49 | sub $9, %cl | ||
50 | |||
51 | movq %r11, %r9 | ||
52 | andq %r10, %r9 | ||
53 | shrq %cl, %r9 | ||
54 | |||
55 | movq PTR(VA_PUD_0)(%rsi), %r8 | ||
56 | addq %r8, %r9 | ||
57 | movq PTR(PA_PMD_0)(%rsi), %r8 | ||
58 | orq $PAGE_ATTR, %r8 | ||
59 | movq %r8, (%r9) | ||
60 | |||
61 | shrq $9, %r10 | ||
62 | sub $9, %cl | ||
63 | |||
64 | movq %r11, %r9 | ||
65 | andq %r10, %r9 | ||
66 | shrq %cl, %r9 | ||
67 | |||
68 | movq PTR(VA_PMD_0)(%rsi), %r8 | ||
69 | addq %r8, %r9 | ||
70 | movq PTR(PA_PTE_0)(%rsi), %r8 | ||
71 | orq $PAGE_ATTR, %r8 | ||
72 | movq %r8, (%r9) | ||
73 | |||
74 | shrq $9, %r10 | ||
75 | sub $9, %cl | ||
76 | |||
77 | movq %r11, %r9 | ||
78 | andq %r10, %r9 | ||
79 | shrq %cl, %r9 | ||
80 | |||
81 | movq PTR(VA_PTE_0)(%rsi), %r8 | ||
82 | addq %r8, %r9 | ||
83 | movq PTR(PA_CONTROL_PAGE)(%rsi), %r8 | ||
84 | orq $PAGE_ATTR, %r8 | ||
85 | movq %r8, (%r9) | ||
86 | |||
87 | /* identity map the control page at its physical address */ | ||
88 | |||
89 | movq $0x0000ff8000000000, %r10 /* mask */ | ||
90 | mov $(39 - 3), %cl /* bits to shift */ | ||
91 | movq PTR(PA_CONTROL_PAGE)(%rsi), %r11 /* address to map */ | ||
92 | |||
93 | movq %r11, %r9 | ||
94 | andq %r10, %r9 | ||
95 | shrq %cl, %r9 | ||
96 | |||
97 | movq PTR(VA_PGD)(%rsi), %r8 | ||
98 | addq %r8, %r9 | ||
99 | movq PTR(PA_PUD_1)(%rsi), %r8 | ||
100 | orq $PAGE_ATTR, %r8 | ||
101 | movq %r8, (%r9) | ||
102 | |||
103 | shrq $9, %r10 | ||
104 | sub $9, %cl | ||
105 | |||
106 | movq %r11, %r9 | ||
107 | andq %r10, %r9 | ||
108 | shrq %cl, %r9 | ||
109 | |||
110 | movq PTR(VA_PUD_1)(%rsi), %r8 | ||
111 | addq %r8, %r9 | ||
112 | movq PTR(PA_PMD_1)(%rsi), %r8 | ||
113 | orq $PAGE_ATTR, %r8 | ||
114 | movq %r8, (%r9) | ||
115 | |||
116 | shrq $9, %r10 | ||
117 | sub $9, %cl | ||
118 | |||
119 | movq %r11, %r9 | ||
120 | andq %r10, %r9 | ||
121 | shrq %cl, %r9 | ||
122 | |||
123 | movq PTR(VA_PMD_1)(%rsi), %r8 | ||
124 | addq %r8, %r9 | ||
125 | movq PTR(PA_PTE_1)(%rsi), %r8 | ||
126 | orq $PAGE_ATTR, %r8 | ||
127 | movq %r8, (%r9) | ||
128 | |||
129 | shrq $9, %r10 | ||
130 | sub $9, %cl | ||
131 | |||
132 | movq %r11, %r9 | ||
133 | andq %r10, %r9 | ||
134 | shrq %cl, %r9 | ||
135 | |||
136 | movq PTR(VA_PTE_1)(%rsi), %r8 | ||
137 | addq %r8, %r9 | ||
138 | movq PTR(PA_CONTROL_PAGE)(%rsi), %r8 | ||
139 | orq $PAGE_ATTR, %r8 | ||
140 | movq %r8, (%r9) | ||
141 | |||
142 | relocate_new_kernel: | ||
143 | /* %rdi indirection_page | ||
144 | * %rsi page_list | ||
145 | * %rdx start address | ||
146 | */ | ||
147 | |||
148 | /* zero out flags, and disable interrupts */ | 32 | /* zero out flags, and disable interrupts */ |
149 | pushq $0 | 33 | pushq $0 |
150 | popfq | 34 | popfq |
@@ -156,9 +40,8 @@ relocate_new_kernel: | |||
156 | /* get physical address of page table now too */ | 40 | /* get physical address of page table now too */ |
157 | movq PTR(PA_TABLE_PAGE)(%rsi), %rcx | 41 | movq PTR(PA_TABLE_PAGE)(%rsi), %rcx |
158 | 42 | ||
159 | /* switch to new set of page tables */ | 43 | /* Switch to the identity mapped page tables */ |
160 | movq PTR(PA_PGD)(%rsi), %r9 | 44 | movq %rcx, %cr3 |
161 | movq %r9, %cr3 | ||
162 | 45 | ||
163 | /* setup a new stack at the end of the physical control page */ | 46 | /* setup a new stack at the end of the physical control page */ |
164 | lea PAGE_SIZE(%r8), %rsp | 47 | lea PAGE_SIZE(%r8), %rsp |
@@ -194,9 +77,7 @@ identity_mapped: | |||
194 | jmp 1f | 77 | jmp 1f |
195 | 1: | 78 | 1: |
196 | 79 | ||
197 | /* Switch to the identity mapped page tables, | 80 | /* Flush the TLB (needed?) */ |
198 | * and flush the TLB. | ||
199 | */ | ||
200 | movq %rcx, %cr3 | 81 | movq %rcx, %cr3 |
201 | 82 | ||
202 | /* Do the copies */ | 83 | /* Do the copies */ |
diff --git a/arch/x86/kernel/trampoline_64.S b/arch/x86/kernel/trampoline_64.S index 894293c598db..95a012a4664e 100644 --- a/arch/x86/kernel/trampoline_64.S +++ b/arch/x86/kernel/trampoline_64.S | |||
@@ -29,6 +29,7 @@ | |||
29 | #include <asm/page.h> | 29 | #include <asm/page.h> |
30 | #include <asm/msr.h> | 30 | #include <asm/msr.h> |
31 | #include <asm/segment.h> | 31 | #include <asm/segment.h> |
32 | #include <asm/processor-flags.h> | ||
32 | 33 | ||
33 | .section .rodata, "a", @progbits | 34 | .section .rodata, "a", @progbits |
34 | 35 | ||
@@ -37,7 +38,7 @@ | |||
37 | ENTRY(trampoline_data) | 38 | ENTRY(trampoline_data) |
38 | r_base = . | 39 | r_base = . |
39 | cli # We should be safe anyway | 40 | cli # We should be safe anyway |
40 | wbinvd | 41 | wbinvd |
41 | mov %cs, %ax # Code and data in the same place | 42 | mov %cs, %ax # Code and data in the same place |
42 | mov %ax, %ds | 43 | mov %ax, %ds |
43 | mov %ax, %es | 44 | mov %ax, %es |
@@ -73,9 +74,8 @@ r_base = . | |||
73 | lidtl tidt - r_base # load idt with 0, 0 | 74 | lidtl tidt - r_base # load idt with 0, 0 |
74 | lgdtl tgdt - r_base # load gdt with whatever is appropriate | 75 | lgdtl tgdt - r_base # load gdt with whatever is appropriate |
75 | 76 | ||
76 | xor %ax, %ax | 77 | mov $X86_CR0_PE, %ax # protected mode (PE) bit |
77 | inc %ax # protected mode (PE) bit | 78 | lmsw %ax # into protected mode |
78 | lmsw %ax # into protected mode | ||
79 | 79 | ||
80 | # flush prefetch and jump to startup_32 | 80 | # flush prefetch and jump to startup_32 |
81 | ljmpl *(startup_32_vector - r_base) | 81 | ljmpl *(startup_32_vector - r_base) |
@@ -86,9 +86,8 @@ startup_32: | |||
86 | movl $__KERNEL_DS, %eax # Initialize the %ds segment register | 86 | movl $__KERNEL_DS, %eax # Initialize the %ds segment register |
87 | movl %eax, %ds | 87 | movl %eax, %ds |
88 | 88 | ||
89 | xorl %eax, %eax | 89 | movl $X86_CR4_PAE, %eax |
90 | btsl $5, %eax # Enable PAE mode | 90 | movl %eax, %cr4 # Enable PAE mode |
91 | movl %eax, %cr4 | ||
92 | 91 | ||
93 | # Setup trampoline 4 level pagetables | 92 | # Setup trampoline 4 level pagetables |
94 | leal (trampoline_level4_pgt - r_base)(%esi), %eax | 93 | leal (trampoline_level4_pgt - r_base)(%esi), %eax |
@@ -99,9 +98,9 @@ startup_32: | |||
99 | xorl %edx, %edx | 98 | xorl %edx, %edx |
100 | wrmsr | 99 | wrmsr |
101 | 100 | ||
102 | xorl %eax, %eax | 101 | # Enable paging and in turn activate Long Mode |
103 | btsl $31, %eax # Enable paging and in turn activate Long Mode | 102 | # Enable protected mode |
104 | btsl $0, %eax # Enable protected mode | 103 | movl $(X86_CR0_PG | X86_CR0_PE), %eax |
105 | movl %eax, %cr0 | 104 | movl %eax, %cr0 |
106 | 105 | ||
107 | /* | 106 | /* |