Print this page
de-linting of .s files
m
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/uts/i86pc/ml/cpr_wakecode.s
+++ new/usr/src/uts/i86pc/ml/cpr_wakecode.s
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21 /*
22 22 * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
↓ open down ↓ |
22 lines elided |
↑ open up ↑ |
23 23 * Copyright 2019 Joyent, Inc.
24 24 */
25 25
26 26 #include <sys/asm_linkage.h>
27 27 #include <sys/asm_misc.h>
28 28 #include <sys/regset.h>
29 29 #include <sys/privregs.h>
30 30 #include <sys/x86_archext.h>
31 31 #include <sys/cpr_wakecode.h>
32 32
33 -#if !defined(__lint)
34 33 #include <sys/segments.h>
35 34 #include "assym.h"
36 -#endif
37 35
38 36 #ifdef DEBUG
39 37 #define LED 1
40 38 #define SERIAL 1
41 39 #endif /* DEBUG */
42 40
43 41 #ifdef DEBUG
44 42 #define COM1 0x3f8
45 43 #define COM2 0x2f8
46 44 #define WC_COM COM2 /* either COM1 or COM2 */
47 45 #define WC_LED 0x80 /* diagnostic led port ON motherboard */
48 46
49 47 /*
50 48 * defined as offsets from the data register
51 49 */
52 50 #define DLL 0 /* divisor latch (lsb) */
53 51 #define DLH 1 /* divisor latch (msb) */
54 52 #define LCR 3 /* line control register */
55 53 #define MCR 4 /* modem control register */
56 54
57 55
58 56 #define DLAB 0x80 /* divisor latch access bit */
59 57 #define B9600L 0X0c /* lsb bit pattern for 9600 baud */
60 58 #define B9600H 0X0 /* hsb bit pattern for 9600 baud */
61 59 #define DTR 0x01 /* Data Terminal Ready */
62 60 #define RTS 0x02 /* Request To Send */
63 61 #define STOP1 0x00 /* 1 stop bit */
64 62 #define BITS8 0x03 /* 8 bits per char */
65 63
66 64 #endif /* DEBUG */
67 65
68 66 /*
↓ open down ↓ |
22 lines elided |
↑ open up ↑ |
69 67 * This file contains the low level routines involved in getting
70 68 * into and out of ACPI S3, including those needed for restarting
71 69 * the non-boot cpus.
72 70 *
73 71 * Our assumptions:
74 72 *
75 73 * Our actions:
76 74 *
77 75 */
78 76
79 -#if defined(lint) || defined(__lint)
80 -
81 -/*ARGSUSED*/
82 -int
83 -wc_save_context(wc_cpu_t *pcpu)
84 -{ return 0; }
85 -
86 -#else /* lint */
87 -
88 -#if defined(__amd64)
89 -
90 77 ENTRY_NP(wc_save_context)
91 78
92 79 movq (%rsp), %rdx / return address
93 80 movq %rdx, WC_RETADDR(%rdi)
94 81 pushq %rbp
95 82 movq %rsp,%rbp
96 83
97 84 movq %rdi, WC_VIRTADDR(%rdi)
98 85 movq %rdi, WC_RDI(%rdi)
99 86
100 87 movq %rdx, WC_RDX(%rdi)
101 88
102 89 / stash everything else we need
103 90 sgdt WC_GDT(%rdi)
104 91 sidt WC_IDT(%rdi)
105 92 sldt WC_LDT(%rdi)
106 93 str WC_TR(%rdi)
107 94
108 95 movq %cr0, %rdx
109 96 movq %rdx, WC_CR0(%rdi)
110 97 movq %cr3, %rdx
111 98 movq %rdx, WC_CR3(%rdi)
112 99 movq %cr4, %rdx
113 100 movq %rdx, WC_CR4(%rdi)
114 101 movq %cr8, %rdx
115 102 movq %rdx, WC_CR8(%rdi)
116 103
117 104 movq %r8, WC_R8(%rdi)
118 105 movq %r9, WC_R9(%rdi)
119 106 movq %r10, WC_R10(%rdi)
120 107 movq %r11, WC_R11(%rdi)
121 108 movq %r12, WC_R12(%rdi)
122 109 movq %r13, WC_R13(%rdi)
123 110 movq %r14, WC_R14(%rdi)
124 111 movq %r15, WC_R15(%rdi)
125 112 movq %rax, WC_RAX(%rdi)
126 113 movq %rbp, WC_RBP(%rdi)
127 114 movq %rbx, WC_RBX(%rdi)
128 115 movq %rcx, WC_RCX(%rdi)
129 116 movq %rsi, WC_RSI(%rdi)
130 117 movq %rsp, WC_RSP(%rdi)
131 118
132 119 movw %ss, WC_SS(%rdi)
133 120 movw %cs, WC_CS(%rdi)
134 121 movw %ds, WC_DS(%rdi)
135 122 movw %es, WC_ES(%rdi)
136 123
137 124 movq $0, %rcx / save %fs register
138 125 movw %fs, %cx
139 126 movq %rcx, WC_FS(%rdi)
140 127
141 128 movl $MSR_AMD_FSBASE, %ecx
142 129 rdmsr
143 130 movl %eax, WC_FSBASE(%rdi)
144 131 movl %edx, WC_FSBASE+4(%rdi)
145 132
146 133 movq $0, %rcx / save %gs register
147 134 movw %gs, %cx
148 135 movq %rcx, WC_GS(%rdi)
149 136
150 137 movl $MSR_AMD_GSBASE, %ecx / save gsbase msr
151 138 rdmsr
152 139 movl %eax, WC_GSBASE(%rdi)
153 140 movl %edx, WC_GSBASE+4(%rdi)
154 141
155 142 movl $MSR_AMD_KGSBASE, %ecx / save kgsbase msr
156 143 rdmsr
157 144 movl %eax, WC_KGSBASE(%rdi)
158 145 movl %edx, WC_KGSBASE+4(%rdi)
159 146
160 147 movq %gs:CPU_ID, %rax / save current cpu id
161 148 movq %rax, WC_CPU_ID(%rdi)
162 149
163 150 pushfq
164 151 popq WC_EFLAGS(%rdi)
165 152
166 153 wbinvd / flush the cache
↓ open down ↓ |
67 lines elided |
↑ open up ↑ |
167 154 mfence
168 155
169 156 movq $1, %rax / at suspend return 1
170 157
171 158 leave
172 159
173 160 ret
174 161
175 162 SET_SIZE(wc_save_context)
176 163
177 -#elif defined(__i386)
178 164
179 - ENTRY_NP(wc_save_context)
180 -
181 - movl 4(%esp), %eax / wc_cpu_t *
182 - movl %eax, WC_VIRTADDR(%eax)
183 -
184 - movl (%esp), %edx / return address
185 - movl %edx, WC_RETADDR(%eax)
186 -
187 - str WC_TR(%eax) / stash everything else we need
188 - sgdt WC_GDT(%eax)
189 - sldt WC_LDT(%eax)
190 - sidt WC_IDT(%eax)
191 -
192 - movl %cr0, %edx
193 - movl %edx, WC_CR0(%eax)
194 - movl %cr3, %edx
195 - movl %edx, WC_CR3(%eax)
196 - movl %cr4, %edx
197 - movl %edx, WC_CR4(%eax)
198 -
199 - movl %ebx, WC_EBX(%eax)
200 - movl %edi, WC_EDI(%eax)
201 - movl %esi, WC_ESI(%eax)
202 - movl %ebp, WC_EBP(%eax)
203 - movl %esp, WC_ESP(%eax)
204 -
205 - movw %ss, WC_SS(%eax)
206 - movw %cs, WC_CS(%eax)
207 - movw %ds, WC_DS(%eax)
208 - movw %es, WC_ES(%eax)
209 - movw %fs, WC_FS(%eax)
210 - movw %gs, WC_GS(%eax)
211 -
212 - pushfl
213 - popl WC_EFLAGS(%eax)
214 -
215 - pushl %gs:CPU_ID / save current cpu id
216 - popl WC_CPU_ID(%eax)
217 -
218 - wbinvd / flush the cache
219 - mfence
220 -
221 - movl $1, %eax / at suspend return 1
222 - ret
223 -
224 - SET_SIZE(wc_save_context)
225 -
226 -#endif /* __amd64 */
227 -
228 -#endif /* lint */
229 -
230 -
231 165 /*
232 166 * Our assumptions:
233 167 * - We are running in real mode.
234 168 * - Interrupts are disabled.
235 169 *
236 170 * Our actions:
237 171 * - We start using our GDT by loading correct values in the
238 172 * selector registers (cs=KCS_SEL, ds=es=ss=KDS_SEL, fs=KFS_SEL,
239 173 * gs=KGS_SEL).
240 174 * - We change over to using our IDT.
241 175 * - We load the default LDT into the hardware LDT register.
242 176 * - We load the default TSS into the hardware task register.
243 177 * - We restore registers
244 178 * - We return to original caller (a la setjmp)
245 179 */
246 180
247 -#if defined(lint) || defined(__lint)
248 -
249 -void
250 -wc_rm_start(void)
251 -{}
252 -
253 -void
254 -wc_rm_end(void)
255 -{}
256 -
257 -#else /* lint */
258 -
259 -#if defined(__amd64)
260 -
261 181 ENTRY_NP(wc_rm_start)
262 182
263 183 /*
264 184 * For the Sun Studio 10 assembler we needed to do a .code32 and
265 185 * mentally invert the meaning of the addr16 and data16 prefixes to
266 186 * get 32-bit access when generating code to be executed in 16-bit
267 187 * mode (sigh...)
268 188 *
269 189 * This code, despite always being built with GNU as, has inherited
270 190 * the conceptual damage.
271 191 */
272 192
273 193 .code32
274 194
275 195 cli
276 196 movw %cs, %ax
277 197 movw %ax, %ds / establish ds ...
278 198 movw %ax, %ss / ... and ss:esp
279 199 D16 movl $WC_STKSTART, %esp
280 200 / using the following value blows up machines! - DO NOT USE
281 201 / D16 movl 0xffc, %esp
282 202
283 203
284 204 #if LED
285 205 D16 movl $WC_LED, %edx
286 206 D16 movb $0xd1, %al
287 207 outb (%dx)
288 208 #endif
289 209
290 210 #if SERIAL
291 211 D16 movl $WC_COM, %edx
292 212 D16 movb $0x61, %al
293 213 outb (%dx)
294 214 #endif
295 215
296 216 D16 call cominit
297 217
298 218 /*
299 219 * Enable protected-mode, write protect, and alignment mask
300 220 * %cr0 has already been initialsed to zero
301 221 */
302 222 movl %cr0, %eax
303 223 D16 orl $_CONST(CR0_PE|CR0_WP|CR0_AM), %eax
304 224 movl %eax, %cr0
305 225
306 226 /*
307 227 * Do a jmp immediately after writing to cr0 when enabling protected
308 228 * mode to clear the real mode prefetch queue (per Intel's docs)
309 229 */
310 230 jmp pestart
311 231 pestart:
312 232
313 233 #if LED
314 234 D16 movl $WC_LED, %edx
315 235 D16 movb $0xd2, %al
316 236 outb (%dx)
317 237 #endif
318 238
319 239 #if SERIAL
320 240 D16 movl $WC_COM, %edx
321 241 D16 movb $0x62, %al
322 242 outb (%dx)
323 243 #endif
324 244
325 245 /*
326 246 * 16-bit protected mode is now active, so prepare to turn on long
327 247 * mode
328 248 */
329 249
330 250 #if LED
331 251 D16 movl $WC_LED, %edx
332 252 D16 movb $0xd3, %al
333 253 outb (%dx)
334 254 #endif
335 255
336 256 #if SERIAL
337 257 D16 movl $WC_COM, %edx
338 258 D16 movb $0x63, %al
339 259 outb (%dx)
340 260 #endif
341 261
342 262 /*
343 263 * Add any initial cr4 bits
344 264 */
345 265 movl %cr4, %eax
346 266 A16 D16 orl CR4OFF, %eax
347 267
348 268 /*
349 269 * Enable PAE mode (CR4.PAE)
350 270 */
351 271 D16 orl $CR4_PAE, %eax
352 272 movl %eax, %cr4
353 273
354 274 #if LED
355 275 D16 movl $WC_LED, %edx
356 276 D16 movb $0xd4, %al
357 277 outb (%dx)
358 278 #endif
359 279
360 280 #if SERIAL
361 281 D16 movl $WC_COM, %edx
362 282 D16 movb $0x64, %al
363 283 outb (%dx)
364 284 #endif
365 285
366 286 /*
367 287 * Point cr3 to the 64-bit long mode page tables.
368 288 *
369 289 * Note that these MUST exist in 32-bit space, as we don't have
370 290 * a way to load %cr3 with a 64-bit base address for the page tables
371 291 * until the CPU is actually executing in 64-bit long mode.
372 292 */
373 293 A16 D16 movl CR3OFF, %eax
374 294 movl %eax, %cr3
375 295
376 296 /*
377 297 * Set long mode enable in EFER (EFER.LME = 1)
378 298 */
379 299 D16 movl $MSR_AMD_EFER, %ecx
380 300 rdmsr
381 301
382 302 D16 orl $AMD_EFER_LME, %eax
383 303 wrmsr
384 304
385 305 #if LED
386 306 D16 movl $WC_LED, %edx
387 307 D16 movb $0xd5, %al
388 308 outb (%dx)
389 309 #endif
390 310
391 311 #if SERIAL
392 312 D16 movl $WC_COM, %edx
393 313 D16 movb $0x65, %al
394 314 outb (%dx)
395 315 #endif
396 316
397 317 /*
398 318 * Finally, turn on paging (CR0.PG = 1) to activate long mode.
399 319 */
400 320 movl %cr0, %eax
401 321 D16 orl $CR0_PG, %eax
402 322 movl %eax, %cr0
403 323
404 324 /*
405 325 * The instruction after enabling paging in CR0 MUST be a branch.
406 326 */
407 327 jmp long_mode_active
408 328
409 329 long_mode_active:
410 330
411 331 #if LED
412 332 D16 movl $WC_LED, %edx
413 333 D16 movb $0xd6, %al
414 334 outb (%dx)
415 335 #endif
416 336
417 337 #if SERIAL
418 338 D16 movl $WC_COM, %edx
419 339 D16 movb $0x66, %al
420 340 outb (%dx)
421 341 #endif
422 342
423 343 /*
424 344 * Long mode is now active but since we're still running with the
425 345 * original 16-bit CS we're actually in 16-bit compatability mode.
426 346 *
427 347 * We have to load an intermediate GDT and IDT here that we know are
428 348 * in 32-bit space before we can use the kernel's GDT and IDT, which
429 349 * may be in the 64-bit address space, and since we're in compatability
430 350 * mode, we only have access to 16 and 32-bit instructions at the
431 351 * moment.
432 352 */
433 353 A16 D16 lgdt TEMPGDTOFF /* load temporary GDT */
434 354 A16 D16 lidt TEMPIDTOFF /* load temporary IDT */
435 355
436 356
437 357 /*
438 358 * Do a far transfer to 64-bit mode. Set the CS selector to a 64-bit
439 359 * long mode selector (CS.L=1) in the temporary 32-bit GDT and jump
440 360 * to the real mode platter address of wc_long_mode_64 as until the
441 361 * 64-bit CS is in place we don't have access to 64-bit instructions
442 362 * and thus can't reference a 64-bit %rip.
443 363 */
444 364
445 365 #if LED
446 366 D16 movl $WC_LED, %edx
447 367 D16 movb $0xd7, %al
448 368 outb (%dx)
449 369 #endif
450 370
451 371 #if SERIAL
452 372 D16 movl $WC_COM, %edx
453 373 D16 movb $0x67, %al
454 374 outb (%dx)
455 375 #endif
456 376
457 377 D16 pushl $TEMP_CS64_SEL
458 378 A16 D16 pushl LM64OFF
459 379
460 380 D16 lret
461 381
462 382
463 383 /*
464 384 * Support routine to re-initialize VGA subsystem
465 385 */
466 386 vgainit:
467 387 D16 ret
468 388
469 389 /*
470 390 * Support routine to re-initialize keyboard (which is USB - help!)
471 391 */
472 392 kbdinit:
473 393 D16 ret
474 394
475 395 /*
476 396 * Support routine to re-initialize COM ports to something sane
477 397 */
478 398 cominit:
479 399 / init COM1 & COM2
480 400
481 401 #if DEBUG
482 402 /*
483 403 * on debug kernels we need to initialize COM1 & COM2 here, so that
484 404 * we can get debug output before the asy driver has resumed
485 405 */
486 406
487 407 / select COM1
488 408 D16 movl $_CONST(COM1+LCR), %edx
489 409 D16 movb $DLAB, %al / divisor latch
490 410 outb (%dx)
491 411
492 412 D16 movl $_CONST(COM1+DLL), %edx / divisor latch lsb
493 413 D16 movb $B9600L, %al / divisor latch
494 414 outb (%dx)
495 415
496 416 D16 movl $_CONST(COM1+DLH), %edx / divisor latch hsb
497 417 D16 movb $B9600H, %al / divisor latch
498 418 outb (%dx)
499 419
500 420 D16 movl $_CONST(COM1+LCR), %edx / select COM1
501 421 D16 movb $_CONST(STOP1|BITS8), %al / 1 stop bit, 8bit word len
502 422 outb (%dx)
503 423
504 424 D16 movl $_CONST(COM1+MCR), %edx / select COM1
505 425 D16 movb $_CONST(RTS|DTR), %al / data term ready & req to send
506 426 outb (%dx)
507 427
508 428 / select COM2
509 429 D16 movl $_CONST(COM2+LCR), %edx
510 430 D16 movb $DLAB, %al / divisor latch
511 431 outb (%dx)
512 432
513 433 D16 movl $_CONST(COM2+DLL), %edx / divisor latch lsb
514 434 D16 movb $B9600L, %al / divisor latch
515 435 outb (%dx)
516 436
517 437 D16 movl $_CONST(COM2+DLH), %edx / divisor latch hsb
518 438 D16 movb $B9600H, %al / divisor latch
519 439 outb (%dx)
520 440
521 441 D16 movl $_CONST(COM2+LCR), %edx / select COM1
522 442 D16 movb $_CONST(STOP1|BITS8), %al / 1 stop bit, 8bit word len
523 443 outb (%dx)
524 444
525 445 D16 movl $_CONST(COM2+MCR), %edx / select COM1
526 446 D16 movb $_CONST(RTS|DTR), %al / data term ready & req to send
527 447 outb (%dx)
528 448 #endif /* DEBUG */
529 449
530 450 D16 ret
531 451
532 452 .code64
533 453
534 454 .globl wc_long_mode_64
535 455 wc_long_mode_64:
536 456
537 457 #if LED
538 458 movw $WC_LED, %dx
539 459 movb $0xd8, %al
540 460 outb (%dx)
541 461 #endif
542 462
543 463 #if SERIAL
544 464 movw $WC_COM, %dx
545 465 movb $0x68, %al
546 466 outb (%dx)
547 467 #endif
548 468
549 469 /*
550 470 * We are now running in long mode with a 64-bit CS (EFER.LMA=1,
551 471 * CS.L=1) so we now have access to 64-bit instructions.
552 472 *
553 473 * First, set the 64-bit GDT base.
554 474 */
555 475 .globl rm_platter_pa
556 476 movl rm_platter_pa, %eax
557 477
558 478 lgdtq GDTROFF(%rax) /* load 64-bit GDT */
559 479
560 480 /*
561 481 * Save the CPU number in %r11; get the value here since it's saved in
562 482 * the real mode platter.
563 483 */
564 484 / JAN
565 485 / the following is wrong! need to figure out MP systems
566 486 / movl CPUNOFF(%rax), %r11d
567 487
568 488 /*
569 489 * Add rm_platter_pa to %rsp to point it to the same location as seen
570 490 * from 64-bit mode.
571 491 */
572 492 addq %rax, %rsp
573 493
574 494 /*
575 495 * Now do an lretq to load CS with the appropriate selector for the
576 496 * kernel's 64-bit GDT and to start executing 64-bit setup code at the
577 497 * virtual address where boot originally loaded this code rather than
578 498 * the copy in the real mode platter's rm_code array as we've been
579 499 * doing so far.
580 500 */
581 501
582 502 #if LED
583 503 movw $WC_LED, %dx
584 504 movb $0xd9, %al
585 505 outb (%dx)
586 506 #endif
587 507
588 508 / JAN this should produce 'i' but we get 'g' instead ???
589 509 #if SERIAL
590 510 movw $WC_COM, %dx
591 511 movb $0x69, %al
592 512 outb (%dx)
593 513 #endif
594 514
595 515 pushq $KCS_SEL
596 516 pushq $kernel_wc_code
597 517 lretq
598 518
599 519 .globl kernel_wc_code
600 520 kernel_wc_code:
601 521
602 522 #if LED
603 523 movw $WC_LED, %dx
604 524 movb $0xda, %al
605 525 outb (%dx)
606 526 #endif
607 527
608 528 / JAN this should produce 'j' but we get 'g' instead ???
609 529 #if SERIAL
610 530 movw $WC_COM, %dx
611 531 movb $0x6a, %al
612 532 outb (%dx)
613 533 #endif
614 534
615 535 /*
616 536 * Complete the balance of the setup we need to before executing
617 537 * 64-bit kernel code (namely init rsp, TSS, LGDT, FS and GS).
618 538 */
619 539 .globl rm_platter_va
620 540 movq rm_platter_va, %rbx
621 541 addq $WC_CPU, %rbx
622 542
623 543 #if LED
624 544 movw $WC_LED, %dx
625 545 movb $0xdb, %al
626 546 outb (%dx)
627 547 #endif
628 548
629 549 #if SERIAL
630 550 movw $WC_COM, %dx
631 551 movw $0x6b, %ax
632 552 outb (%dx)
633 553 #endif
634 554
635 555 /*
636 556 * restore the rest of the registers
637 557 */
638 558
639 559 lidtq WC_IDT(%rbx)
640 560
641 561 #if LED
642 562 movw $WC_LED, %dx
643 563 movb $0xdc, %al
644 564 outb (%dx)
645 565 #endif
646 566
647 567 #if SERIAL
648 568 movw $WC_COM, %dx
649 569 movw $0x6c, %ax
650 570 outb (%dx)
651 571 #endif
652 572
653 573 /*
654 574 * restore the rest of the registers
655 575 */
656 576
657 577 movw $KDS_SEL, %ax
658 578 movw %ax, %ds
659 579 movw %ax, %es
660 580 movw %ax, %ss
661 581
662 582 /*
663 583 * Before proceeding, enable usage of the page table NX bit if
664 584 * that's how the page tables are set up.
665 585 */
666 586 bt $X86FSET_NX, x86_featureset(%rip)
667 587 jnc 1f
668 588 movl $MSR_AMD_EFER, %ecx
669 589 rdmsr
670 590 orl $AMD_EFER_NXE, %eax
671 591 wrmsr
672 592 1:
673 593
674 594 movq WC_CR4(%rbx), %rax / restore full cr4 (with Global Enable)
675 595 movq %rax, %cr4
676 596
677 597 lldt WC_LDT(%rbx)
678 598 movzwq WC_TR(%rbx), %rax / clear TSS busy bit
679 599 addq WC_GDT+2(%rbx), %rax
680 600 andl $0xfffffdff, 4(%rax)
681 601 movq 4(%rax), %rcx
682 602 ltr WC_TR(%rbx)
683 603
684 604 #if LED
685 605 movw $WC_LED, %dx
686 606 movb $0xdd, %al
687 607 outb (%dx)
688 608 #endif
689 609
690 610 #if SERIAL
691 611 movw $WC_COM, %dx
692 612 movw $0x6d, %ax
693 613 outb (%dx)
694 614 #endif
695 615
696 616 / restore %fsbase %gsbase %kgbase registers using wrmsr instruction
697 617
698 618 movq WC_FS(%rbx), %rcx / restore fs register
699 619 movw %cx, %fs
700 620
701 621 movl $MSR_AMD_FSBASE, %ecx
702 622 movl WC_FSBASE(%rbx), %eax
703 623 movl WC_FSBASE+4(%rbx), %edx
704 624 wrmsr
705 625
706 626 movq WC_GS(%rbx), %rcx / restore gs register
707 627 movw %cx, %gs
708 628
709 629 movl $MSR_AMD_GSBASE, %ecx / restore gsbase msr
710 630 movl WC_GSBASE(%rbx), %eax
711 631 movl WC_GSBASE+4(%rbx), %edx
712 632 wrmsr
713 633
714 634 movl $MSR_AMD_KGSBASE, %ecx / restore kgsbase msr
715 635 movl WC_KGSBASE(%rbx), %eax
716 636 movl WC_KGSBASE+4(%rbx), %edx
717 637 wrmsr
718 638
719 639 movq WC_CR0(%rbx), %rdx
720 640 movq %rdx, %cr0
721 641 movq WC_CR3(%rbx), %rdx
722 642 movq %rdx, %cr3
723 643 movq WC_CR8(%rbx), %rdx
724 644 movq %rdx, %cr8
725 645
726 646 #if LED
727 647 movw $WC_LED, %dx
728 648 movb $0xde, %al
729 649 outb (%dx)
730 650 #endif
731 651
732 652 #if SERIAL
733 653 movw $WC_COM, %dx
734 654 movb $0x6e, %al
735 655 outb (%dx)
736 656 #endif
737 657
738 658 /*
739 659 * if we are not running on the boot CPU restore stack contents by
740 660 * calling i_cpr_restore_stack(curthread, save_stack);
741 661 */
742 662 movq %rsp, %rbp
743 663 call i_cpr_bootcpuid
744 664 cmpl %eax, WC_CPU_ID(%rbx)
745 665 je 2f
746 666
747 667 movq %gs:CPU_THREAD, %rdi
748 668 movq WC_SAVED_STACK(%rbx), %rsi
749 669 call i_cpr_restore_stack
750 670 2:
751 671
752 672 movq WC_RSP(%rbx), %rsp / restore stack pointer
753 673
754 674 /*
755 675 * APIC initialization
756 676 */
757 677 movq %rsp, %rbp
758 678
759 679 /*
760 680 * skip iff function pointer is NULL
761 681 */
762 682 cmpq $0, ap_mlsetup
763 683 je 3f
764 684 leaq ap_mlsetup, %rax
765 685 INDIRECT_CALL_REG(rax)
766 686 3:
767 687
768 688 leaq cpr_start_cpu_func, %rax
769 689 INDIRECT_CALL_REG(rax)
770 690
771 691 / restore %rbx to the value it ahd before we called the functions above
772 692 movq rm_platter_va, %rbx
773 693 addq $WC_CPU, %rbx
774 694
775 695 movq WC_R8(%rbx), %r8
776 696 movq WC_R9(%rbx), %r9
777 697 movq WC_R10(%rbx), %r10
778 698 movq WC_R11(%rbx), %r11
779 699 movq WC_R12(%rbx), %r12
780 700 movq WC_R13(%rbx), %r13
781 701 movq WC_R14(%rbx), %r14
782 702 movq WC_R15(%rbx), %r15
783 703 / movq WC_RAX(%rbx), %rax
784 704 movq WC_RBP(%rbx), %rbp
785 705 movq WC_RCX(%rbx), %rcx
786 706 / movq WC_RDX(%rbx), %rdx
787 707 movq WC_RDI(%rbx), %rdi
788 708 movq WC_RSI(%rbx), %rsi
789 709
790 710
791 711 / assume that %cs does not need to be restored
792 712 / %ds, %es & %ss are ignored in 64bit mode
793 713 movw WC_SS(%rbx), %ss
794 714 movw WC_DS(%rbx), %ds
795 715 movw WC_ES(%rbx), %es
796 716
797 717 #if LED
798 718 movw $WC_LED, %dx
799 719 movb $0xdf, %al
800 720 outb (%dx)
801 721 #endif
802 722
803 723 #if SERIAL
804 724 movw $WC_COM, %dx
805 725 movb $0x6f, %al
806 726 outb (%dx)
807 727 #endif
808 728
809 729
810 730 movq WC_RBP(%rbx), %rbp
811 731 movq WC_RSP(%rbx), %rsp
812 732
813 733 #if LED
814 734 movw $WC_LED, %dx
815 735 movb $0xe0, %al
816 736 outb (%dx)
817 737 #endif
818 738
819 739 #if SERIAL
820 740 movw $WC_COM, %dx
821 741 movb $0x70, %al
822 742 outb (%dx)
823 743 #endif
824 744
825 745
826 746 movq WC_RCX(%rbx), %rcx
827 747
828 748 pushq WC_EFLAGS(%rbx) / restore flags
829 749 popfq
830 750
831 751 #if LED
832 752 movw $WC_LED, %dx
833 753 movb $0xe1, %al
834 754 outb (%dx)
835 755 #endif
836 756
837 757 #if SERIAL
838 758 movw $WC_COM, %dx
839 759 movb $0x71, %al
840 760 outb (%dx)
841 761 #endif
842 762
843 763 /*
844 764 * can not use outb after this point, because doing so would mean using
845 765 * %dx which would modify %rdx which is restored here
846 766 */
847 767
848 768 movq %rbx, %rax
849 769 movq WC_RDX(%rax), %rdx
850 770 movq WC_RBX(%rax), %rbx
851 771
852 772 leave
853 773
854 774 movq WC_RETADDR(%rax), %rax
855 775 movq %rax, (%rsp) / return to caller of wc_save_context
856 776
857 777 xorl %eax, %eax / at wakeup return 0
858 778 ret
859 779
860 780
861 781 SET_SIZE(wc_rm_start)
862 782
863 783 ENTRY_NP(asmspin)
↓ open down ↓ |
593 lines elided |
↑ open up ↑ |
864 784
865 785 movl %edi, %ecx
866 786 A1:
867 787 loop A1
868 788
869 789 SET_SIZE(asmspin)
870 790
871 791 .globl wc_rm_end
872 792 wc_rm_end:
873 793 nop
874 -
875 -#elif defined(__i386)
876 -
877 - ENTRY_NP(wc_rm_start)
878 -
879 -/entry: jmp entry / stop here for HDT
880 -
881 - cli
882 - movw %cs, %ax
883 - movw %ax, %ds / establish ds ...
884 - movw %ax, %ss / ... and ss:esp
885 - D16 movl $WC_STKSTART, %esp
886 -
887 -#if LED
888 - D16 movl $WC_LED, %edx
889 - D16 movb $0xd1, %al
890 - outb (%dx)
891 -#endif
892 -
893 -#if SERIAL
894 - D16 movl $WC_COM, %edx
895 - D16 movb $0x61, %al
896 - outb (%dx)
897 -#endif
898 -
899 -
900 - D16 call vgainit
901 - D16 call kbdinit
902 - D16 call cominit
903 -
904 -#if LED
905 - D16 movl $WC_LED, %edx
906 - D16 movb $0xd2, %al
907 - outb (%dx)
908 -#endif
909 -
910 -#if SERIAL
911 - D16 movl $WC_COM, %edx
912 - D16 movb $0x62, %al
913 - outb (%dx)
914 -#endif
915 -
916 - D16 A16 movl $WC_CPU, %ebx / base add of wc_cpu_t
917 -
918 -#if LED
919 - D16 movb $0xd3, %al
920 - outb $WC_LED
921 -#endif
922 -
923 -#if SERIAL
924 - D16 movl $WC_COM, %edx
925 - D16 movb $0x63, %al
926 - outb (%dx)
927 -#endif
928 -
929 - D16 A16 movl %cs:WC_DS(%ebx), %edx / %ds post prot/paging transit
930 -
931 -#if LED
932 - D16 movb $0xd4, %al
933 - outb $WC_LED
934 -#endif
935 -
936 - D16 A16 lgdt %cs:WC_GDT(%ebx) / restore gdt and idtr
937 - D16 A16 lidt %cs:WC_IDT(%ebx)
938 -
939 -#if LED
940 - D16 movb $0xd5, %al
941 - outb $WC_LED
942 -#endif
943 -
944 - D16 A16 movl %cs:WC_CR4(%ebx), %eax / restore cr4
945 - D16 andl $_BITNOT(CR4_PGE), %eax / don't set Global Enable yet
946 - movl %eax, %cr4
947 -
948 -#if LED
949 - D16 movb $0xd6, %al
950 - outb $WC_LED
951 -#endif
952 -
953 - D16 A16 movl %cs:WC_CR3(%ebx), %eax / set PDPT
954 - movl %eax, %cr3
955 -
956 -#if LED
957 - D16 movb $0xd7, %al
958 - outb $WC_LED
959 -#endif
960 -
961 - D16 A16 movl %cs:WC_CR0(%ebx), %eax / enable prot/paging, etc.
962 - movl %eax, %cr0
963 -
964 -#if LED
965 - D16 movb $0xd8, %al
966 - outb $WC_LED
967 -#endif
968 -
969 - D16 A16 movl %cs:WC_VIRTADDR(%ebx), %ebx / virtaddr of wc_cpu_t
970 -
971 -#if LED
972 - D16 movb $0xd9, %al
973 - outb $WC_LED
974 -#endif
975 -
976 -#if LED
977 - D16 movb $0xda, %al
978 - outb $WC_LED
979 -#endif
980 -
981 - jmp flush / flush prefetch queue
982 -flush:
983 - D16 pushl $KCS_SEL
984 - D16 pushl $kernel_wc_code
985 - D16 lret / re-appear at kernel_wc_code
986 -
987 -
988 -/*
989 - * Support routine to re-initialize VGA subsystem
990 - */
991 -vgainit:
992 - D16 ret
993 -
994 -/*
995 - * Support routine to re-initialize keyboard (which is USB - help!)
996 - */
997 -kbdinit:
998 - D16 ret
999 -
1000 -/*
1001 - * Support routine to re-initialize COM ports to something sane for debug output
1002 - */
1003 -cominit:
1004 -#if DEBUG
1005 -/*
1006 - * on debug kernels we need to initialize COM1 & COM2 here, so that
1007 - * we can get debug output before the asy driver has resumed
1008 - */
1009 -
1010 -/ select COM1
1011 - D16 movl $_CONST(COM1+LCR), %edx
1012 - D16 movb $DLAB, %al / divisor latch
1013 - outb (%dx)
1014 -
1015 - D16 movl $_CONST(COM1+DLL), %edx / divisor latch lsb
1016 - D16 movb $B9600L, %al / divisor latch
1017 - outb (%dx)
1018 -
1019 - D16 movl $_CONST(COM1+DLH), %edx / divisor latch hsb
1020 - D16 movb $B9600H, %al / divisor latch
1021 - outb (%dx)
1022 -
1023 - D16 movl $_CONST(COM1+LCR), %edx / select COM1
1024 - D16 movb $_CONST(STOP1|BITS8), %al / 1 stop bit, 8bit word len
1025 - outb (%dx)
1026 -
1027 - D16 movl $_CONST(COM1+MCR), %edx / select COM1
1028 - D16 movb $_CONST(RTS|DTR), %al / 1 stop bit, 8bit word len
1029 - outb (%dx)
1030 -
1031 -/ select COM2
1032 - D16 movl $_CONST(COM2+LCR), %edx
1033 - D16 movb $DLAB, %al / divisor latch
1034 - outb (%dx)
1035 -
1036 - D16 movl $_CONST(COM2+DLL), %edx / divisor latch lsb
1037 - D16 movb $B9600L, %al / divisor latch
1038 - outb (%dx)
1039 -
1040 - D16 movl $_CONST(COM2+DLH), %edx / divisor latch hsb
1041 - D16 movb $B9600H, %al / divisor latch
1042 - outb (%dx)
1043 -
1044 - D16 movl $_CONST(COM2+LCR), %edx / select COM1
1045 - D16 movb $_CONST(STOP1|BITS8), %al / 1 stop bit, 8bit word len
1046 - outb (%dx)
1047 -
1048 - D16 movl $_CONST(COM2+MCR), %edx / select COM1
1049 - D16 movb $_CONST(RTS|DTR), %al / 1 stop bit, 8bit word len
1050 - outb (%dx)
1051 -#endif /* DEBUG */
1052 -
1053 - D16 ret
1054 -
1055 - .globl wc_rm_end
1056 -wc_rm_end:
1057 - nop
1058 -
1059 - .globl kernel_wc_code
1060 -kernel_wc_code:
1061 - / At this point we are with kernel's cs and proper eip.
1062 - / We will be executing not from the copy in real mode platter,
1063 - / but from the original code where boot loaded us.
1064 - / By this time GDT and IDT are loaded as is cr0, cr3 and cr4.
1065 - / %ebx is wc_cpu
1066 - / %dx is our ds
1067 -
1068 -#if LED
1069 - D16 movb $0xdb, %al
1070 - outb $WC_LED
1071 -#endif
1072 -
1073 -/ got here OK
1074 -
1075 - movw %dx, %ds / $KDS_SEL
1076 -
1077 -#if LED
1078 - movb $0xdc, %al
1079 - outb $WC_LED
1080 -#endif
1081 -
1082 - /*
1083 - * Before proceeding, enable usage of the page table NX bit if
1084 - * that's how the page tables are set up.
1085 - */
1086 - bt $X86FSET_NX, x86_featureset
1087 - jnc 1f
1088 - movl $MSR_AMD_EFER, %ecx
1089 - rdmsr
1090 - orl $AMD_EFER_NXE, %eax
1091 - wrmsr
1092 -1:
1093 -
1094 - movl WC_CR4(%ebx), %eax / restore full cr4 (with Global Enable)
1095 - movl %eax, %cr4
1096 -
1097 -
1098 - lldt WC_LDT(%ebx) / $LDT_SEL
1099 -
1100 - movzwl WC_TR(%ebx), %eax / clear TSS busy bit
1101 - addl WC_GDT+2(%ebx), %eax
1102 - andl $_BITNOT(0x200), 4(%eax)
1103 - ltr WC_TR(%ebx) / $UTSS_SEL
1104 -
1105 - movw WC_SS(%ebx), %ss / restore segment registers
1106 - movw WC_ES(%ebx), %es
1107 - movw WC_FS(%ebx), %fs
1108 - movw WC_GS(%ebx), %gs
1109 -
1110 - /*
1111 - * set the stack pointer to point into the identity mapped page
1112 - * temporarily, so we can make function calls
1113 - */
1114 - .globl rm_platter_va
1115 - movl rm_platter_va, %eax
1116 - movl $WC_STKSTART, %esp
1117 - addl %eax, %esp
1118 - movl %esp, %ebp
1119 -
1120 - /*
1121 - * if we are not running on the boot CPU restore stack contents by
1122 - * calling i_cpr_restore_stack(curthread, save_stack);
1123 - */
1124 - call i_cpr_bootcpuid
1125 - cmpl %eax, WC_CPU_ID(%ebx)
1126 - je 2f
1127 -
1128 - pushl WC_SAVED_STACK(%ebx)
1129 - pushl %gs:CPU_THREAD
1130 - call i_cpr_restore_stack
1131 - addl $0x10, %esp
1132 -2:
1133 -
1134 - movl WC_ESP(%ebx), %esp
1135 - movl %esp, %ebp
1136 -
1137 - movl WC_RETADDR(%ebx), %eax / return to caller of wc_save_context
1138 - movl %eax, (%esp)
1139 -
1140 - /*
1141 - * APIC initialization, skip iff function pointer is NULL
1142 - */
1143 - cmpl $0, ap_mlsetup
1144 - je 3f
1145 - call *ap_mlsetup
1146 -3:
1147 -
1148 - call *cpr_start_cpu_func
1149 -
1150 - pushl WC_EFLAGS(%ebx) / restore flags
1151 - popfl
1152 -
1153 - movl WC_EDI(%ebx), %edi / restore general registers
1154 - movl WC_ESI(%ebx), %esi
1155 - movl WC_EBP(%ebx), %ebp
1156 - movl WC_EBX(%ebx), %ebx
1157 -
1158 -/exit: jmp exit / stop here for HDT
1159 -
1160 - xorl %eax, %eax / at wakeup return 0
1161 - ret
1162 -
1163 - SET_SIZE(wc_rm_start)
1164 -
1165 -
1166 -#endif /* defined(__amd64) */
1167 -
1168 -#endif /* lint */
1169 794
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX