| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: cpu.c,v 1.130.2.2 2018/03/07 14:50:57 martin Exp $ */ | | 1 | /* $NetBSD: cpu.c,v 1.130.2.3 2018/03/08 11:33:15 martin Exp $ */ |
2 | | | 2 | |
3 | /*- | | 3 | /*- |
4 | * Copyright (c) 2000-2012 NetBSD Foundation, Inc. | | 4 | * Copyright (c) 2000-2012 NetBSD Foundation, Inc. |
5 | * All rights reserved. | | 5 | * All rights reserved. |
6 | * | | 6 | * |
7 | * This code is derived from software contributed to The NetBSD Foundation | | 7 | * This code is derived from software contributed to The NetBSD Foundation |
8 | * by Bill Sommerfeld of RedBack Networks Inc, and by Andrew Doran. | | 8 | * by Bill Sommerfeld of RedBack Networks Inc, and by Andrew Doran. |
9 | * | | 9 | * |
10 | * Redistribution and use in source and binary forms, with or without | | 10 | * Redistribution and use in source and binary forms, with or without |
11 | * modification, are permitted provided that the following conditions | | 11 | * modification, are permitted provided that the following conditions |
12 | * are met: | | 12 | * are met: |
13 | * 1. Redistributions of source code must retain the above copyright | | 13 | * 1. Redistributions of source code must retain the above copyright |
14 | * notice, this list of conditions and the following disclaimer. | | 14 | * notice, this list of conditions and the following disclaimer. |
| @@ -52,27 +52,27 @@ | | | @@ -52,27 +52,27 @@ |
52 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | | 52 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
53 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | | 53 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
54 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR AND CONTRIBUTORS BE LIABLE | | 54 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR AND CONTRIBUTORS BE LIABLE |
55 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | | 55 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
56 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | | 56 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
57 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | | 57 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
58 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | | 58 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
59 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | | 59 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
60 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | | 60 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
61 | * SUCH DAMAGE. | | 61 | * SUCH DAMAGE. |
62 | */ | | 62 | */ |
63 | | | 63 | |
64 | #include <sys/cdefs.h> | | 64 | #include <sys/cdefs.h> |
65 | __KERNEL_RCSID(0, "$NetBSD: cpu.c,v 1.130.2.2 2018/03/07 14:50:57 martin Exp $"); | | 65 | __KERNEL_RCSID(0, "$NetBSD: cpu.c,v 1.130.2.3 2018/03/08 11:33:15 martin Exp $"); |
66 | | | 66 | |
67 | #include "opt_ddb.h" | | 67 | #include "opt_ddb.h" |
68 | #include "opt_mpbios.h" /* for MPDEBUG */ | | 68 | #include "opt_mpbios.h" /* for MPDEBUG */ |
69 | #include "opt_mtrr.h" | | 69 | #include "opt_mtrr.h" |
70 | #include "opt_multiprocessor.h" | | 70 | #include "opt_multiprocessor.h" |
71 | | | 71 | |
72 | #include "lapic.h" | | 72 | #include "lapic.h" |
73 | #include "ioapic.h" | | 73 | #include "ioapic.h" |
74 | | | 74 | |
75 | #include <sys/param.h> | | 75 | #include <sys/param.h> |
76 | #include <sys/proc.h> | | 76 | #include <sys/proc.h> |
77 | #include <sys/systm.h> | | 77 | #include <sys/systm.h> |
78 | #include <sys/device.h> | | 78 | #include <sys/device.h> |
| @@ -154,51 +154,47 @@ CFATTACH_DECL2_NEW(cpu, sizeof(struct cp | | | @@ -154,51 +154,47 @@ CFATTACH_DECL2_NEW(cpu, sizeof(struct cp |
154 | * point at it. | | 154 | * point at it. |
155 | */ | | 155 | */ |
156 | #ifdef TRAPLOG | | 156 | #ifdef TRAPLOG |
157 | struct tlog tlog_primary; | | 157 | struct tlog tlog_primary; |
158 | #endif | | 158 | #endif |
159 | struct cpu_info cpu_info_primary __aligned(CACHE_LINE_SIZE) = { | | 159 | struct cpu_info cpu_info_primary __aligned(CACHE_LINE_SIZE) = { |
160 | .ci_dev = 0, | | 160 | .ci_dev = 0, |
161 | .ci_self = &cpu_info_primary, | | 161 | .ci_self = &cpu_info_primary, |
162 | .ci_idepth = -1, | | 162 | .ci_idepth = -1, |
163 | .ci_curlwp = &lwp0, | | 163 | .ci_curlwp = &lwp0, |
164 | .ci_curldt = -1, | | 164 | .ci_curldt = -1, |
165 | #ifdef TRAPLOG | | 165 | #ifdef TRAPLOG |
166 | .ci_tlog_base = &tlog_primary, | | 166 | .ci_tlog_base = &tlog_primary, |
167 | #endif /* !TRAPLOG */ | | 167 | #endif |
168 | }; | | 168 | }; |
169 | | | 169 | |
170 | struct cpu_info *cpu_info_list = &cpu_info_primary; | | 170 | struct cpu_info *cpu_info_list = &cpu_info_primary; |
171 | | | 171 | |
172 | static void cpu_set_tss_gates(struct cpu_info *); | | | |
173 | | | | |
174 | #ifdef i386 | | 172 | #ifdef i386 |
175 | static void tss_init(struct i386tss *, void *, void *); | | 173 | void cpu_set_tss_gates(struct cpu_info *); |
176 | #endif | | 174 | #endif |
177 | | | 175 | |
178 | static void cpu_init_idle_lwp(struct cpu_info *); | | 176 | static void cpu_init_idle_lwp(struct cpu_info *); |
179 | | | 177 | |
180 | uint32_t cpu_feature[7] __read_mostly; /* X86 CPUID feature bits */ | | 178 | uint32_t cpu_feature[7] __read_mostly; /* X86 CPUID feature bits */ |
181 | /* [0] basic features cpuid.1:%edx | | 179 | /* [0] basic features cpuid.1:%edx |
182 | * [1] basic features cpuid.1:%ecx (CPUID2_xxx bits) | | 180 | * [1] basic features cpuid.1:%ecx (CPUID2_xxx bits) |
183 | * [2] extended features cpuid:80000001:%edx | | 181 | * [2] extended features cpuid:80000001:%edx |
184 | * [3] extended features cpuid:80000001:%ecx | | 182 | * [3] extended features cpuid:80000001:%ecx |
185 | * [4] VIA padlock features | | 183 | * [4] VIA padlock features |
186 | * [5] structured extended features cpuid.7:%ebx | | 184 | * [5] structured extended features cpuid.7:%ebx |
187 | * [6] structured extended features cpuid.7:%ecx | | 185 | * [6] structured extended features cpuid.7:%ecx |
188 | */ | | 186 | */ |
189 | | | 187 | |
190 | extern char x86_64_doubleflt_stack[]; | | | |
191 | | | | |
192 | #ifdef MULTIPROCESSOR | | 188 | #ifdef MULTIPROCESSOR |
193 | bool x86_mp_online; | | 189 | bool x86_mp_online; |
194 | paddr_t mp_trampoline_paddr = MP_TRAMPOLINE; | | 190 | paddr_t mp_trampoline_paddr = MP_TRAMPOLINE; |
195 | #endif | | 191 | #endif |
196 | #if NLAPIC > 0 | | 192 | #if NLAPIC > 0 |
197 | static vaddr_t cmos_data_mapping; | | 193 | static vaddr_t cmos_data_mapping; |
198 | #endif | | 194 | #endif |
199 | struct cpu_info *cpu_starting; | | 195 | struct cpu_info *cpu_starting; |
200 | | | 196 | |
201 | #ifdef MULTIPROCESSOR | | 197 | #ifdef MULTIPROCESSOR |
202 | void cpu_hatch(void *); | | 198 | void cpu_hatch(void *); |
203 | static void cpu_boot_secondary(struct cpu_info *ci); | | 199 | static void cpu_boot_secondary(struct cpu_info *ci); |
204 | static void cpu_start_secondary(struct cpu_info *ci); | | 200 | static void cpu_start_secondary(struct cpu_info *ci); |
| @@ -385,27 +381,29 @@ cpu_attach(device_t parent, device_t sel | | | @@ -385,27 +381,29 @@ cpu_attach(device_t parent, device_t sel |
385 | ci->ci_pmap = pmap_kernel(); | | 381 | ci->ci_pmap = pmap_kernel(); |
386 | ci->ci_tlbstate = TLBSTATE_STALE; | | 382 | ci->ci_tlbstate = TLBSTATE_STALE; |
387 | | | 383 | |
388 | /* | | 384 | /* |
389 | * Boot processor may not be attached first, but the below | | 385 | * Boot processor may not be attached first, but the below |
390 | * must be done to allow booting other processors. | | 386 | * must be done to allow booting other processors. |
391 | */ | | 387 | */ |
392 | if (!again) { | | 388 | if (!again) { |
393 | atomic_or_32(&ci->ci_flags, CPUF_PRESENT | CPUF_PRIMARY); | | 389 | atomic_or_32(&ci->ci_flags, CPUF_PRESENT | CPUF_PRIMARY); |
394 | /* Basic init. */ | | 390 | /* Basic init. */ |
395 | cpu_intr_init(ci); | | 391 | cpu_intr_init(ci); |
396 | cpu_get_tsc_freq(ci); | | 392 | cpu_get_tsc_freq(ci); |
397 | cpu_init(ci); | | 393 | cpu_init(ci); |
| | | 394 | #ifdef i386 |
398 | cpu_set_tss_gates(ci); | | 395 | cpu_set_tss_gates(ci); |
| | | 396 | #endif |
399 | pmap_cpu_init_late(ci); | | 397 | pmap_cpu_init_late(ci); |
400 | #if NLAPIC > 0 | | 398 | #if NLAPIC > 0 |
401 | if (caa->cpu_role != CPU_ROLE_SP) { | | 399 | if (caa->cpu_role != CPU_ROLE_SP) { |
402 | /* Enable lapic. */ | | 400 | /* Enable lapic. */ |
403 | lapic_enable(); | | 401 | lapic_enable(); |
404 | lapic_set_lvt(); | | 402 | lapic_set_lvt(); |
405 | lapic_calibrate_timer(ci); | | 403 | lapic_calibrate_timer(ci); |
406 | } | | 404 | } |
407 | #endif | | 405 | #endif |
408 | /* Make sure DELAY() is initialized. */ | | 406 | /* Make sure DELAY() is initialized. */ |
409 | DELAY(1); | | 407 | DELAY(1); |
410 | again = true; | | 408 | again = true; |
411 | } | | 409 | } |
| @@ -424,27 +422,29 @@ cpu_attach(device_t parent, device_t sel | | | @@ -424,27 +422,29 @@ cpu_attach(device_t parent, device_t sel |
424 | atomic_or_32(&ci->ci_flags, CPUF_BSP); | | 422 | atomic_or_32(&ci->ci_flags, CPUF_BSP); |
425 | cpu_identify(ci); | | 423 | cpu_identify(ci); |
426 | x86_errata(); | | 424 | x86_errata(); |
427 | x86_cpu_idle_init(); | | 425 | x86_cpu_idle_init(); |
428 | break; | | 426 | break; |
429 | | | 427 | |
430 | #ifdef MULTIPROCESSOR | | 428 | #ifdef MULTIPROCESSOR |
431 | case CPU_ROLE_AP: | | 429 | case CPU_ROLE_AP: |
432 | /* | | 430 | /* |
433 | * report on an AP | | 431 | * report on an AP |
434 | */ | | 432 | */ |
435 | cpu_intr_init(ci); | | 433 | cpu_intr_init(ci); |
436 | gdt_alloc_cpu(ci); | | 434 | gdt_alloc_cpu(ci); |
| | | 435 | #ifdef i386 |
437 | cpu_set_tss_gates(ci); | | 436 | cpu_set_tss_gates(ci); |
| | | 437 | #endif |
438 | pmap_cpu_init_late(ci); | | 438 | pmap_cpu_init_late(ci); |
439 | cpu_start_secondary(ci); | | 439 | cpu_start_secondary(ci); |
440 | if (ci->ci_flags & CPUF_PRESENT) { | | 440 | if (ci->ci_flags & CPUF_PRESENT) { |
441 | struct cpu_info *tmp; | | 441 | struct cpu_info *tmp; |
442 | | | 442 | |
443 | cpu_identify(ci); | | 443 | cpu_identify(ci); |
444 | tmp = cpu_info_list; | | 444 | tmp = cpu_info_list; |
445 | while (tmp->ci_next) | | 445 | while (tmp->ci_next) |
446 | tmp = tmp->ci_next; | | 446 | tmp = tmp->ci_next; |
447 | | | 447 | |
448 | tmp->ci_next = ci; | | 448 | tmp->ci_next = ci; |
449 | } | | 449 | } |
450 | break; | | 450 | break; |
| @@ -491,27 +491,26 @@ cpu_defer(device_t self) | | | @@ -491,27 +491,26 @@ cpu_defer(device_t self) |
491 | } | | 491 | } |
492 | | | 492 | |
493 | static int | | 493 | static int |
494 | cpu_rescan(device_t self, const char *ifattr, const int *locators) | | 494 | cpu_rescan(device_t self, const char *ifattr, const int *locators) |
495 | { | | 495 | { |
496 | struct cpu_softc *sc = device_private(self); | | 496 | struct cpu_softc *sc = device_private(self); |
497 | struct cpufeature_attach_args cfaa; | | 497 | struct cpufeature_attach_args cfaa; |
498 | struct cpu_info *ci = sc->sc_info; | | 498 | struct cpu_info *ci = sc->sc_info; |
499 | | | 499 | |
500 | memset(&cfaa, 0, sizeof(cfaa)); | | 500 | memset(&cfaa, 0, sizeof(cfaa)); |
501 | cfaa.ci = ci; | | 501 | cfaa.ci = ci; |
502 | | | 502 | |
503 | if (ifattr_match(ifattr, "cpufeaturebus")) { | | 503 | if (ifattr_match(ifattr, "cpufeaturebus")) { |
504 | | | | |
505 | if (ci->ci_frequency == NULL) { | | 504 | if (ci->ci_frequency == NULL) { |
506 | cfaa.name = "frequency"; | | 505 | cfaa.name = "frequency"; |
507 | ci->ci_frequency = config_found_ia(self, | | 506 | ci->ci_frequency = config_found_ia(self, |
508 | "cpufeaturebus", &cfaa, NULL); | | 507 | "cpufeaturebus", &cfaa, NULL); |
509 | } | | 508 | } |
510 | | | 509 | |
511 | if (ci->ci_padlock == NULL) { | | 510 | if (ci->ci_padlock == NULL) { |
512 | cfaa.name = "padlock"; | | 511 | cfaa.name = "padlock"; |
513 | ci->ci_padlock = config_found_ia(self, | | 512 | ci->ci_padlock = config_found_ia(self, |
514 | "cpufeaturebus", &cfaa, NULL); | | 513 | "cpufeaturebus", &cfaa, NULL); |
515 | } | | 514 | } |
516 | | | 515 | |
517 | if (ci->ci_temperature == NULL) { | | 516 | if (ci->ci_temperature == NULL) { |
| @@ -798,43 +797,43 @@ cpu_boot_secondary(struct cpu_info *ci) | | | @@ -798,43 +797,43 @@ cpu_boot_secondary(struct cpu_info *ci) |
798 | * this processor will enter the idle loop and start looking for work. | | 797 | * this processor will enter the idle loop and start looking for work. |
799 | */ | | 798 | */ |
800 | void | | 799 | void |
801 | cpu_hatch(void *v) | | 800 | cpu_hatch(void *v) |
802 | { | | 801 | { |
803 | struct cpu_info *ci = (struct cpu_info *)v; | | 802 | struct cpu_info *ci = (struct cpu_info *)v; |
804 | struct pcb *pcb; | | 803 | struct pcb *pcb; |
805 | int s, i; | | 804 | int s, i; |
806 | | | 805 | |
807 | cpu_init_msrs(ci, true); | | 806 | cpu_init_msrs(ci, true); |
808 | cpu_probe(ci); | | 807 | cpu_probe(ci); |
809 | | | 808 | |
810 | ci->ci_data.cpu_cc_freq = cpu_info_primary.ci_data.cpu_cc_freq; | | 809 | ci->ci_data.cpu_cc_freq = cpu_info_primary.ci_data.cpu_cc_freq; |
811 | /* cpu_get_tsc_freq(ci); */ | | 810 | /* cpu_get_tsc_freq(ci); */ |
812 | | | 811 | |
813 | KDASSERT((ci->ci_flags & CPUF_PRESENT) == 0); | | 812 | KDASSERT((ci->ci_flags & CPUF_PRESENT) == 0); |
814 | | | 813 | |
815 | /* | | 814 | /* |
816 | * Synchronize time stamp counters. Invalidate cache and do twice | | 815 | * Synchronize time stamp counters. Invalidate cache and do twice |
817 | * to try and minimize possible cache effects. Note that interrupts | | 816 | * to try and minimize possible cache effects. Note that interrupts |
818 | * are off at this point. | | 817 | * are off at this point. |
819 | */ | | 818 | */ |
820 | wbinvd(); | | 819 | wbinvd(); |
821 | atomic_or_32(&ci->ci_flags, CPUF_PRESENT); | | 820 | atomic_or_32(&ci->ci_flags, CPUF_PRESENT); |
822 | tsc_sync_ap(ci); | | 821 | tsc_sync_ap(ci); |
823 | | | 822 | |
824 | /* | | 823 | /* |
825 | * Wait to be brought online. Use 'monitor/mwait' if available, | | 824 | * Wait to be brought online. Use 'monitor/mwait' if available, |
826 | * in order to make the TSC drift as much as possible. so that | | 825 | * in order to make the TSC drift as much as possible. so that |
827 | * we can detect it later. If not available, try 'pause'. | | 826 | * we can detect it later. If not available, try 'pause'. |
828 | * We'd like to use 'hlt', but we have interrupts off. | | 827 | * We'd like to use 'hlt', but we have interrupts off. |
829 | */ | | 828 | */ |
830 | while ((ci->ci_flags & CPUF_GO) == 0) { | | 829 | while ((ci->ci_flags & CPUF_GO) == 0) { |
831 | if ((cpu_feature[1] & CPUID2_MONITOR) != 0) { | | 830 | if ((cpu_feature[1] & CPUID2_MONITOR) != 0) { |
832 | x86_monitor(&ci->ci_flags, 0, 0); | | 831 | x86_monitor(&ci->ci_flags, 0, 0); |
833 | if ((ci->ci_flags & CPUF_GO) != 0) { | | 832 | if ((ci->ci_flags & CPUF_GO) != 0) { |
834 | continue; | | 833 | continue; |
835 | } | | 834 | } |
836 | x86_mwait(0, 0); | | 835 | x86_mwait(0, 0); |
837 | } else { | | 836 | } else { |
838 | /* | | 837 | /* |
839 | * XXX The loop repetition count could be a lot higher, but | | 838 | * XXX The loop repetition count could be a lot higher, but |
840 | * XXX currently qemu emulator takes a _very_long_time_ to | | 839 | * XXX currently qemu emulator takes a _very_long_time_ to |
| @@ -923,119 +922,45 @@ cpu_debug_dump(void) | | | @@ -923,119 +922,45 @@ cpu_debug_dump(void) |
923 | } | | 922 | } |
924 | } | | 923 | } |
925 | #endif | | 924 | #endif |
926 | | | 925 | |
927 | #if NLAPIC > 0 | | 926 | #if NLAPIC > 0 |
928 | static void | | 927 | static void |
929 | cpu_copy_trampoline(void) | | 928 | cpu_copy_trampoline(void) |
930 | { | | 929 | { |
931 | /* | | 930 | /* |
932 | * Copy boot code. | | 931 | * Copy boot code. |
933 | */ | | 932 | */ |
934 | extern u_char cpu_spinup_trampoline[]; | | 933 | extern u_char cpu_spinup_trampoline[]; |
935 | extern u_char cpu_spinup_trampoline_end[]; | | 934 | extern u_char cpu_spinup_trampoline_end[]; |
936 | | | 935 | |
937 | vaddr_t mp_trampoline_vaddr; | | 936 | vaddr_t mp_trampoline_vaddr; |
938 | | | 937 | |
939 | mp_trampoline_vaddr = uvm_km_alloc(kernel_map, PAGE_SIZE, 0, | | 938 | mp_trampoline_vaddr = uvm_km_alloc(kernel_map, PAGE_SIZE, 0, |
940 | UVM_KMF_VAONLY); | | 939 | UVM_KMF_VAONLY); |
941 | | | 940 | |
942 | pmap_kenter_pa(mp_trampoline_vaddr, mp_trampoline_paddr, | | 941 | pmap_kenter_pa(mp_trampoline_vaddr, mp_trampoline_paddr, |
943 | VM_PROT_READ | VM_PROT_WRITE, 0); | | 942 | VM_PROT_READ | VM_PROT_WRITE, 0); |
944 | pmap_update(pmap_kernel()); | | 943 | pmap_update(pmap_kernel()); |
945 | memcpy((void *)mp_trampoline_vaddr, | | 944 | memcpy((void *)mp_trampoline_vaddr, |
946 | cpu_spinup_trampoline, | | 945 | cpu_spinup_trampoline, |
947 | cpu_spinup_trampoline_end - cpu_spinup_trampoline); | | 946 | cpu_spinup_trampoline_end - cpu_spinup_trampoline); |
948 | | | 947 | |
949 | pmap_kremove(mp_trampoline_vaddr, PAGE_SIZE); | | 948 | pmap_kremove(mp_trampoline_vaddr, PAGE_SIZE); |
950 | pmap_update(pmap_kernel()); | | 949 | pmap_update(pmap_kernel()); |
951 | uvm_km_free(kernel_map, mp_trampoline_vaddr, PAGE_SIZE, UVM_KMF_VAONLY); | | 950 | uvm_km_free(kernel_map, mp_trampoline_vaddr, PAGE_SIZE, UVM_KMF_VAONLY); |
952 | } | | 951 | } |
953 | #endif | | 952 | #endif |
954 | | | 953 | |
955 | #ifdef i386 | | | |
956 | static void | | | |
957 | tss_init(struct i386tss *tss, void *stack, void *func) | | | |
958 | { | | | |
959 | KASSERT(curcpu()->ci_pmap == pmap_kernel()); | | | |
960 | | | | |
961 | memset(tss, 0, sizeof *tss); | | | |
962 | tss->tss_esp0 = tss->tss_esp = (int)((char *)stack + USPACE - 16); | | | |
963 | tss->tss_ss0 = GSEL(GDATA_SEL, SEL_KPL); | | | |
964 | tss->__tss_cs = GSEL(GCODE_SEL, SEL_KPL); | | | |
965 | tss->tss_fs = GSEL(GCPU_SEL, SEL_KPL); | | | |
966 | tss->tss_gs = tss->__tss_es = tss->__tss_ds = | | | |
967 | tss->__tss_ss = GSEL(GDATA_SEL, SEL_KPL); | | | |
968 | /* %cr3 contains the value associated to pmap_kernel */ | | | |
969 | tss->tss_cr3 = rcr3(); | | | |
970 | tss->tss_esp = (int)((char *)stack + USPACE - 16); | | | |
971 | tss->tss_ldt = GSEL(GLDT_SEL, SEL_KPL); | | | |
972 | tss->__tss_eflags = PSL_MBO | PSL_NT; /* XXX not needed? */ | | | |
973 | tss->__tss_eip = (int)func; | | | |
974 | } | | | |
975 | | | | |
976 | /* XXX */ | | | |
977 | #define IDTVEC(name) __CONCAT(X, name) | | | |
978 | typedef void (vector)(void); | | | |
979 | extern vector IDTVEC(tss_trap08); | | | |
980 | #if defined(DDB) && defined(MULTIPROCESSOR) | | | |
981 | extern vector Xintrddbipi, Xx2apic_intrddbipi; | | | |
982 | extern int ddb_vec; | | | |
983 | #endif | | | |
984 | | | | |
985 | static void | | | |
986 | cpu_set_tss_gates(struct cpu_info *ci) | | | |
987 | { | | | |
988 | struct segment_descriptor sd; | | | |
989 | | | | |
990 | ci->ci_doubleflt_stack = (char *)uvm_km_alloc(kernel_map, USPACE, 0, | | | |
991 | UVM_KMF_WIRED); | | | |
992 | tss_init(&ci->ci_doubleflt_tss, ci->ci_doubleflt_stack, | | | |
993 | IDTVEC(tss_trap08)); | | | |
994 | setsegment(&sd, &ci->ci_doubleflt_tss, sizeof(struct i386tss) - 1, | | | |
995 | SDT_SYS386TSS, SEL_KPL, 0, 0); | | | |
996 | ci->ci_gdt[GTRAPTSS_SEL].sd = sd; | | | |
997 | setgate(&idt[8], NULL, 0, SDT_SYSTASKGT, SEL_KPL, | | | |
998 | GSEL(GTRAPTSS_SEL, SEL_KPL)); | | | |
999 | | | | |
1000 | #if defined(DDB) && defined(MULTIPROCESSOR) | | | |
1001 | /* | | | |
1002 | * Set up separate handler for the DDB IPI, so that it doesn't | | | |
1003 | * stomp on a possibly corrupted stack. | | | |
1004 | * | | | |
1005 | * XXX overwriting the gate set in db_machine_init. | | | |
1006 | * Should rearrange the code so that it's set only once. | | | |
1007 | */ | | | |
1008 | ci->ci_ddbipi_stack = (char *)uvm_km_alloc(kernel_map, USPACE, 0, | | | |
1009 | UVM_KMF_WIRED); | | | |
1010 | tss_init(&ci->ci_ddbipi_tss, ci->ci_ddbipi_stack, | | | |
1011 | x2apic_mode ? Xx2apic_intrddbipi : Xintrddbipi); | | | |
1012 | | | | |
1013 | setsegment(&sd, &ci->ci_ddbipi_tss, sizeof(struct i386tss) - 1, | | | |
1014 | SDT_SYS386TSS, SEL_KPL, 0, 0); | | | |
1015 | ci->ci_gdt[GIPITSS_SEL].sd = sd; | | | |
1016 | | | | |
1017 | setgate(&idt[ddb_vec], NULL, 0, SDT_SYSTASKGT, SEL_KPL, | | | |
1018 | GSEL(GIPITSS_SEL, SEL_KPL)); | | | |
1019 | #endif | | | |
1020 | } | | | |
1021 | #else | | | |
1022 | static void | | | |
1023 | cpu_set_tss_gates(struct cpu_info *ci) | | | |
1024 | { | | | |
1025 | | | | |
1026 | } | | | |
1027 | #endif /* i386 */ | | | |
1028 | | | | |
1029 | #ifdef MULTIPROCESSOR | | 954 | #ifdef MULTIPROCESSOR |
1030 | int | | 955 | int |
1031 | mp_cpu_start(struct cpu_info *ci, paddr_t target) | | 956 | mp_cpu_start(struct cpu_info *ci, paddr_t target) |
1032 | { | | 957 | { |
1033 | unsigned short dwordptr[2]; | | 958 | unsigned short dwordptr[2]; |
1034 | int error; | | 959 | int error; |
1035 | | | 960 | |
1036 | /* | | 961 | /* |
1037 | * Bootstrap code must be addressable in real mode | | 962 | * Bootstrap code must be addressable in real mode |
1038 | * and it must be page aligned. | | 963 | * and it must be page aligned. |
1039 | */ | | 964 | */ |
1040 | KASSERT(target < 0x10000 && target % PAGE_SIZE == 0); | | 965 | KASSERT(target < 0x10000 && target % PAGE_SIZE == 0); |
1041 | | | 966 | |
| @@ -1295,27 +1220,27 @@ cpu_load_pmap(struct pmap *pmap, struct | | | @@ -1295,27 +1220,27 @@ cpu_load_pmap(struct pmap *pmap, struct |
1295 | | | 1220 | |
1296 | /* | | 1221 | /* |
1297 | * disable interrupts to block TLB shootdowns, which can reload cr3. | | 1222 | * disable interrupts to block TLB shootdowns, which can reload cr3. |
1298 | * while this doesn't block NMIs, it's probably ok as NMIs unlikely | | 1223 | * while this doesn't block NMIs, it's probably ok as NMIs unlikely |
1299 | * reload cr3. | | 1224 | * reload cr3. |
1300 | */ | | 1225 | */ |
1301 | interrupts_enabled = (x86_read_flags() & PSL_I) != 0; | | 1226 | interrupts_enabled = (x86_read_flags() & PSL_I) != 0; |
1302 | if (interrupts_enabled) | | 1227 | if (interrupts_enabled) |
1303 | x86_disable_intr(); | | 1228 | x86_disable_intr(); |
1304 | | | 1229 | |
1305 | for (i = 0 ; i < PDP_SIZE; i++) { | | 1230 | for (i = 0 ; i < PDP_SIZE; i++) { |
1306 | l3_pd[i] = pmap->pm_pdirpa[i] | PG_V; | | 1231 | l3_pd[i] = pmap->pm_pdirpa[i] | PG_V; |
1307 | } | | 1232 | } |
1308 | | | 1233 | |
1309 | if (interrupts_enabled) | | 1234 | if (interrupts_enabled) |
1310 | x86_enable_intr(); | | 1235 | x86_enable_intr(); |
1311 | tlbflush(); | | 1236 | tlbflush(); |
1312 | #else /* PAE */ | | 1237 | #else /* PAE */ |
1313 | lcr3(pmap_pdirpa(pmap, 0)); | | 1238 | lcr3(pmap_pdirpa(pmap, 0)); |
1314 | #endif /* PAE */ | | 1239 | #endif /* PAE */ |
1315 | } | | 1240 | } |
1316 | | | 1241 | |
1317 | /* | | 1242 | /* |
1318 | * Notify all other cpus to halt. | | 1243 | * Notify all other cpus to halt. |
1319 | */ | | 1244 | */ |
1320 | | | 1245 | |
1321 | void | | 1246 | void |