]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/x86/acpica/acpi_wakeup.c
Add Intel Spec Store Bypass Disable control.
[FreeBSD/FreeBSD.git] / sys / x86 / acpica / acpi_wakeup.c
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3  *
4  * Copyright (c) 2001 Takanori Watanabe <takawata@jp.freebsd.org>
5  * Copyright (c) 2001-2012 Mitsuru IWASAKI <iwasaki@jp.freebsd.org>
6  * Copyright (c) 2003 Peter Wemm
7  * Copyright (c) 2008-2012 Jung-uk Kim <jkim@FreeBSD.org>
8  * All rights reserved.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
23  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29  * SUCH DAMAGE.
30  */
31
32 #include <sys/cdefs.h>
33 __FBSDID("$FreeBSD$");
34
35 #if defined(__amd64__)
36 #define DEV_APIC
37 #else
38 #include "opt_apic.h"
39 #endif
40
41 #include <sys/param.h>
42 #include <sys/bus.h>
43 #include <sys/eventhandler.h>
44 #include <sys/kernel.h>
45 #include <sys/malloc.h>
46 #include <sys/memrange.h>
47 #include <sys/smp.h>
48 #include <sys/systm.h>
49
50 #include <vm/vm.h>
51 #include <vm/pmap.h>
52
53 #include <machine/clock.h>
54 #include <machine/cpu.h>
55 #include <machine/intr_machdep.h>
56 #include <x86/mca.h>
57 #include <machine/pcb.h>
58 #include <machine/specialreg.h>
59 #include <machine/md_var.h>
60
61 #ifdef DEV_APIC
62 #include <x86/apicreg.h>
63 #include <x86/apicvar.h>
64 #endif
65 #ifdef SMP
66 #include <machine/smp.h>
67 #include <machine/vmparam.h>
68 #endif
69
70 #include <contrib/dev/acpica/include/acpi.h>
71
72 #include <dev/acpica/acpivar.h>
73
74 #include "acpi_wakecode.h"
75 #include "acpi_wakedata.h"
76
77 /* Make sure the code is less than a page and leave room for the stack. */
78 CTASSERT(sizeof(wakecode) < PAGE_SIZE - 1024);
79
80 extern int              acpi_resume_beep;
81 extern int              acpi_reset_video;
82 extern int              acpi_susp_bounce;
83
84 #ifdef SMP
85 extern struct susppcb   **susppcbs;
86 static cpuset_t         suspcpus;
87 #else
88 static struct susppcb   **susppcbs;
89 #endif
90
91 static void             *acpi_alloc_wakeup_handler(void **);
92 static void             acpi_stop_beep(void *);
93
94 #ifdef SMP
95 static int              acpi_wakeup_ap(struct acpi_softc *, int);
96 static void             acpi_wakeup_cpus(struct acpi_softc *);
97 #endif
98
99 #ifdef __amd64__
100 #define ACPI_WAKEPAGES  4
101 #else
102 #define ACPI_WAKEPAGES  1
103 #endif
104
105 #define WAKECODE_FIXUP(offset, type, val)       do {    \
106         type    *addr;                                  \
107         addr = (type *)(sc->acpi_wakeaddr + (offset));  \
108         *addr = val;                                    \
109 } while (0)
110
111 static void
112 acpi_stop_beep(void *arg)
113 {
114
115         if (acpi_resume_beep != 0)
116                 timer_spkr_release();
117 }
118
119 #ifdef SMP
120 static int
121 acpi_wakeup_ap(struct acpi_softc *sc, int cpu)
122 {
123         struct pcb *pcb;
124         int             vector = (sc->acpi_wakephys >> 12) & 0xff;
125         int             apic_id = cpu_apic_ids[cpu];
126         int             ms;
127
128         pcb = &susppcbs[cpu]->sp_pcb;
129         WAKECODE_FIXUP(wakeup_pcb, struct pcb *, pcb);
130         WAKECODE_FIXUP(wakeup_gdt, uint16_t, pcb->pcb_gdt.rd_limit);
131         WAKECODE_FIXUP(wakeup_gdt + 2, uint64_t, pcb->pcb_gdt.rd_base);
132
133         ipi_startup(apic_id, vector);
134
135         /* Wait up to 5 seconds for it to resume. */
136         for (ms = 0; ms < 5000; ms++) {
137                 if (!CPU_ISSET(cpu, &suspended_cpus))
138                         return (1);     /* return SUCCESS */
139                 DELAY(1000);
140         }
141         return (0);             /* return FAILURE */
142 }
143
144 #define WARMBOOT_TARGET         0
145 #ifdef __amd64__
146 #define WARMBOOT_OFF            (KERNBASE + 0x0467)
147 #define WARMBOOT_SEG            (KERNBASE + 0x0469)
148 #else /* __i386__ */
149 #define WARMBOOT_OFF            (PMAP_MAP_LOW + 0x0467)
150 #define WARMBOOT_SEG            (PMAP_MAP_LOW + 0x0469)
151 #endif
152
153 #define CMOS_REG                (0x70)
154 #define CMOS_DATA               (0x71)
155 #define BIOS_RESET              (0x0f)
156 #define BIOS_WARM               (0x0a)
157
158 static void
159 acpi_wakeup_cpus(struct acpi_softc *sc)
160 {
161         uint32_t        mpbioswarmvec;
162         int             cpu;
163         u_char          mpbiosreason;
164
165         /* save the current value of the warm-start vector */
166         mpbioswarmvec = *((uint32_t *)WARMBOOT_OFF);
167         outb(CMOS_REG, BIOS_RESET);
168         mpbiosreason = inb(CMOS_DATA);
169
170         /* setup a vector to our boot code */
171         *((volatile u_short *)WARMBOOT_OFF) = WARMBOOT_TARGET;
172         *((volatile u_short *)WARMBOOT_SEG) = sc->acpi_wakephys >> 4;
173         outb(CMOS_REG, BIOS_RESET);
174         outb(CMOS_DATA, BIOS_WARM);     /* 'warm-start' */
175
176         /* Wake up each AP. */
177         for (cpu = 1; cpu < mp_ncpus; cpu++) {
178                 if (!CPU_ISSET(cpu, &suspcpus))
179                         continue;
180                 if (acpi_wakeup_ap(sc, cpu) == 0) {
181                         /* restore the warmstart vector */
182                         *(uint32_t *)WARMBOOT_OFF = mpbioswarmvec;
183                         panic("acpi_wakeup: failed to resume AP #%d (PHY #%d)",
184                             cpu, cpu_apic_ids[cpu]);
185                 }
186         }
187
188 #ifdef __i386__
189         /*
190          * Remove the identity mapping of low memory for all CPUs and sync
191          * the TLB for the BSP.  The APs are now spinning in
192          * cpususpend_handler() and we will release them soon.  Then each
193          * will invalidate its TLB.
194          */
195         PTD[KPTDI] = 0;
196         invltlb_glob();
197 #endif
198
199         /* restore the warmstart vector */
200         *(uint32_t *)WARMBOOT_OFF = mpbioswarmvec;
201
202         outb(CMOS_REG, BIOS_RESET);
203         outb(CMOS_DATA, mpbiosreason);
204 }
205 #endif
206
207 int
208 acpi_sleep_machdep(struct acpi_softc *sc, int state)
209 {
210         ACPI_STATUS     status;
211         struct pcb      *pcb;
212 #ifdef __amd64__
213         struct pcpu *pc;
214         int i;
215 #endif
216
217         if (sc->acpi_wakeaddr == 0ul)
218                 return (-1);    /* couldn't alloc wake memory */
219
220 #ifdef SMP
221         suspcpus = all_cpus;
222         CPU_CLR(PCPU_GET(cpuid), &suspcpus);
223 #endif
224
225         if (acpi_resume_beep != 0)
226                 timer_spkr_acquire();
227
228         AcpiSetFirmwareWakingVector(sc->acpi_wakephys, 0);
229
230         intr_suspend();
231
232         pcb = &susppcbs[0]->sp_pcb;
233         if (savectx(pcb)) {
234 #ifdef __amd64__
235                 fpususpend(susppcbs[0]->sp_fpususpend);
236 #else
237                 npxsuspend(susppcbs[0]->sp_fpususpend);
238 #endif
239 #ifdef SMP
240                 if (!CPU_EMPTY(&suspcpus) && suspend_cpus(suspcpus) == 0) {
241                         device_printf(sc->acpi_dev, "Failed to suspend APs\n");
242                         return (0);     /* couldn't sleep */
243                 }
244 #endif
245 #ifdef __amd64__
246                 hw_ibrs_active = 0;
247                 hw_ssb_active = 0;
248                 cpu_stdext_feature3 = 0;
249                 CPU_FOREACH(i) {
250                         pc = pcpu_find(i);
251                         pc->pc_ibpb_set = 0;
252                 }
253 #endif
254
255                 WAKECODE_FIXUP(resume_beep, uint8_t, (acpi_resume_beep != 0));
256                 WAKECODE_FIXUP(reset_video, uint8_t, (acpi_reset_video != 0));
257
258 #ifdef __amd64__
259                 WAKECODE_FIXUP(wakeup_efer, uint64_t, rdmsr(MSR_EFER) &
260                     ~(EFER_LMA));
261 #else
262                 WAKECODE_FIXUP(wakeup_cr4, register_t, pcb->pcb_cr4);
263 #endif
264                 WAKECODE_FIXUP(wakeup_pcb, struct pcb *, pcb);
265                 WAKECODE_FIXUP(wakeup_gdt, uint16_t, pcb->pcb_gdt.rd_limit);
266                 WAKECODE_FIXUP(wakeup_gdt + 2, uint64_t, pcb->pcb_gdt.rd_base);
267
268 #ifdef __i386__
269                 /*
270                  * Map some low memory with virt == phys for ACPI wakecode
271                  * to use to jump to high memory after enabling paging. This
272                  * is the same as for similar jump in locore, except the
273                  * jump is a single instruction, and we know its address
274                  * more precisely so only need a single PTD, and we have to
275                  * be careful to use the kernel map (PTD[0] is for curthread
276                  * which may be a user thread in deprecated APIs).
277                  */
278                 PTD[KPTDI] = PTD[LOWPTDI];
279 #endif
280
281                 /* Call ACPICA to enter the desired sleep state */
282                 if (state == ACPI_STATE_S4 && sc->acpi_s4bios)
283                         status = AcpiEnterSleepStateS4bios();
284                 else
285                         status = AcpiEnterSleepState(state);
286                 if (ACPI_FAILURE(status)) {
287                         device_printf(sc->acpi_dev,
288                             "AcpiEnterSleepState failed - %s\n",
289                             AcpiFormatException(status));
290                         return (0);     /* couldn't sleep */
291                 }
292
293                 if (acpi_susp_bounce)
294                         resumectx(pcb);
295
296                 for (;;)
297                         ia32_pause();
298         } else {
299 #ifdef __amd64__
300                 fpuresume(susppcbs[0]->sp_fpususpend);
301 #else
302                 npxresume(susppcbs[0]->sp_fpususpend);
303 #endif
304         }
305
306         return (1);     /* wakeup successfully */
307 }
308
309 int
310 acpi_wakeup_machdep(struct acpi_softc *sc, int state, int sleep_result,
311     int intr_enabled)
312 {
313
314         if (sleep_result == -1)
315                 return (sleep_result);
316
317         if (!intr_enabled) {
318                 /* Wakeup MD procedures in interrupt disabled context */
319                 if (sleep_result == 1) {
320                         pmap_init_pat();
321                         initializecpu();
322                         PCPU_SET(switchtime, 0);
323                         PCPU_SET(switchticks, ticks);
324 #ifdef DEV_APIC
325                         lapic_xapic_mode();
326 #endif
327 #ifdef SMP
328                         if (!CPU_EMPTY(&suspcpus))
329                                 acpi_wakeup_cpus(sc);
330 #endif
331                 }
332
333 #ifdef SMP
334                 if (!CPU_EMPTY(&suspcpus))
335                         resume_cpus(suspcpus);
336 #endif
337                 mca_resume();
338 #ifdef __amd64__
339                 if (vmm_resume_p != NULL)
340                         vmm_resume_p();
341 #endif
342                 intr_resume(/*suspend_cancelled*/false);
343
344                 AcpiSetFirmwareWakingVector(0, 0);
345         } else {
346                 /* Wakeup MD procedures in interrupt enabled context */
347                 if (sleep_result == 1 && mem_range_softc.mr_op != NULL &&
348                     mem_range_softc.mr_op->reinit != NULL)
349                         mem_range_softc.mr_op->reinit(&mem_range_softc);
350         }
351
352         return (sleep_result);
353 }
354
355 static void *
356 acpi_alloc_wakeup_handler(void *wakepages[ACPI_WAKEPAGES])
357 {
358         int             i;
359
360         memset(wakepages, 0, ACPI_WAKEPAGES * sizeof(*wakepages));
361
362         /*
363          * Specify the region for our wakeup code.  We want it in the low 1 MB
364          * region, excluding real mode IVT (0-0x3ff), BDA (0x400-0x4ff), EBDA
365          * (less than 128KB, below 0xa0000, must be excluded by SMAP and DSDT),
366          * and ROM area (0xa0000 and above).  The temporary page tables must be
367          * page-aligned.
368          */
369         for (i = 0; i < ACPI_WAKEPAGES; i++) {
370                 wakepages[i] = contigmalloc(PAGE_SIZE, M_DEVBUF, M_NOWAIT,
371                     0x500, 0xa0000, PAGE_SIZE, 0ul);
372                 if (wakepages[i] == NULL) {
373                         printf("%s: can't alloc wake memory\n", __func__);
374                         goto freepages;
375                 }
376         }
377         if (EVENTHANDLER_REGISTER(power_resume, acpi_stop_beep, NULL,
378             EVENTHANDLER_PRI_LAST) == NULL) {
379                 printf("%s: can't register event handler\n", __func__);
380                 goto freepages;
381         }
382         susppcbs = malloc(mp_ncpus * sizeof(*susppcbs), M_DEVBUF, M_WAITOK);
383         for (i = 0; i < mp_ncpus; i++) {
384                 susppcbs[i] = malloc(sizeof(**susppcbs), M_DEVBUF, M_WAITOK);
385                 susppcbs[i]->sp_fpususpend = alloc_fpusave(M_WAITOK);
386         }
387
388         return (wakepages);
389
390 freepages:
391         for (i = 0; i < ACPI_WAKEPAGES; i++)
392                 if (wakepages[i] != NULL)
393                         contigfree(wakepages[i], PAGE_SIZE, M_DEVBUF);
394         return (NULL);
395 }
396
397 void
398 acpi_install_wakeup_handler(struct acpi_softc *sc)
399 {
400         static void     *wakeaddr;
401         void            *wakepages[ACPI_WAKEPAGES];
402 #ifdef __amd64__
403         uint64_t        *pt4, *pt3, *pt2;
404         vm_paddr_t      pt4pa, pt3pa, pt2pa;
405         int             i;
406 #endif
407
408         if (wakeaddr != NULL)
409                 return;
410
411         if (acpi_alloc_wakeup_handler(wakepages) == NULL)
412                 return;
413
414         wakeaddr = wakepages[0];
415         sc->acpi_wakeaddr = (vm_offset_t)wakeaddr;
416         sc->acpi_wakephys = vtophys(wakeaddr);
417
418 #ifdef __amd64__
419         pt4 = wakepages[1];
420         pt3 = wakepages[2];
421         pt2 = wakepages[3];
422         pt4pa = vtophys(pt4);
423         pt3pa = vtophys(pt3);
424         pt2pa = vtophys(pt2);
425 #endif
426
427         bcopy(wakecode, (void *)sc->acpi_wakeaddr, sizeof(wakecode));
428
429         /* Patch GDT base address, ljmp targets. */
430         WAKECODE_FIXUP((bootgdtdesc + 2), uint32_t,
431             sc->acpi_wakephys + bootgdt);
432         WAKECODE_FIXUP((wakeup_sw32 + 2), uint32_t,
433             sc->acpi_wakephys + wakeup_32);
434 #ifdef __amd64__
435         WAKECODE_FIXUP((wakeup_sw64 + 1), uint32_t,
436             sc->acpi_wakephys + wakeup_64);
437         WAKECODE_FIXUP(wakeup_pagetables, uint32_t, pt4pa);
438 #endif
439
440         /* Save pointers to some global data. */
441         WAKECODE_FIXUP(wakeup_ret, void *, resumectx);
442 #ifndef __amd64__
443 #if defined(PAE) || defined(PAE_TABLES)
444         WAKECODE_FIXUP(wakeup_cr3, register_t, vtophys(kernel_pmap->pm_pdpt));
445 #else
446         WAKECODE_FIXUP(wakeup_cr3, register_t, vtophys(kernel_pmap->pm_pdir));
447 #endif
448
449 #else /* __amd64__ */
450         /* Create the initial 1GB replicated page tables */
451         for (i = 0; i < 512; i++) {
452                 /*
453                  * Each slot of the level 4 pages points
454                  * to the same level 3 page
455                  */
456                 pt4[i] = (uint64_t)pt3pa;
457                 pt4[i] |= PG_V | PG_RW | PG_U;
458
459                 /*
460                  * Each slot of the level 3 pages points
461                  * to the same level 2 page
462                  */
463                 pt3[i] = (uint64_t)pt2pa;
464                 pt3[i] |= PG_V | PG_RW | PG_U;
465
466                 /* The level 2 page slots are mapped with 2MB pages for 1GB. */
467                 pt2[i] = i * (2 * 1024 * 1024);
468                 pt2[i] |= PG_V | PG_RW | PG_PS | PG_U;
469         }
470 #endif /* !__amd64__ */
471
472         if (bootverbose)
473                 device_printf(sc->acpi_dev, "wakeup code va %#jx pa %#jx\n",
474                     (uintmax_t)sc->acpi_wakeaddr, (uintmax_t)sc->acpi_wakephys);
475 }