Changeset View
Standalone View
sys/amd64/amd64/kexec_tramp.S
- This file was added.
| /*- | |||||
| * SPDX-License-Identifier: BSD-2-Clause | |||||
| * | |||||
| * Copyright (c) 2025 Juniper Networks, Inc. | |||||
| * | |||||
| * Redistribution and use in source and binary forms, with or without | |||||
| * modification, are permitted provided that the following conditions | |||||
| * are met: | |||||
| * 1. Redistributions of source code must retain the above copyright | |||||
| * notice, this list of conditions and the following disclaimer. | |||||
| * 2. Redistributions in binary form must reproduce the above copyright | |||||
| * notice, this list of conditions and the following disclaimer in the | |||||
| * documentation and/or other materials provided with the distribution. | |||||
| * | |||||
| * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND | |||||
| * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |||||
| * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |||||
| * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE | |||||
| * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |||||
| * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |||||
| * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |||||
| * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |||||
| * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |||||
| * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |||||
| * SUCH DAMAGE. | |||||
| */ | |||||
| #include <machine/asmacros.h> | |||||
| #include <machine/specialreg.h> | |||||
| #include "assym.inc" | |||||
| /* | |||||
| * Take a pointer to the image, copy each segment, and jump to the trampoline. | |||||
| * | |||||
kib: This must be removed. | |||||
| * Assumptions: | |||||
| * - image is in safe memory | |||||
| * - We're already running out of the new "identity" map. | |||||
| * - All registers are free game, so go nuts | |||||
| * - Interrupts are disabled | |||||
Done Inline ActionsAlso note that interrupts must be disabled. kib: Also note that interrupts must be disabled. | |||||
| * - All APs are disabled | |||||
| */ | |||||
| ENTRY(kexec_do_reboot) | |||||
| /* | |||||
| r9: image pointer | |||||
| r10: segment pointer | |||||
| r11: segment counter | |||||
| */ | |||||
| leaq kexec_stack(%rip), %rsp | |||||
| /* Get the saved kexec_image. */ | |||||
| leaq kexec_saved_image(%rip), %rdi | |||||
| movq %rdi, %r9 | |||||
kibUnsubmitted Not Done Inline ActionsWhy do you load the address of kexec_saved_image into %rdi and then copy it into %r9? If you change %rdi to %r9 in line 52 below, I do not see other uses of %rdi with that value. kib: Why do you load the address of kexec_saved_image into %rdi and then copy it into %r9? If you… | |||||
| leaq KEXEC_SEGMENTS(%rdi), %r10 | |||||
| movq $KEXEC_SEGMENT_MAX, %r11 | |||||
| copy_segment: | |||||
Not Done Inline ActionsI do not quite follow this. Code overrides the argument with the address of the kexec_saved_image, and there is no way to restore the argument. Then why the argument is needed at all? kib: I do not quite follow this. Code overrides the argument with the address of the… | |||||
Not Done Inline ActionsThis is still not handled, or at least not explained. kib: This is still not handled, or at least not explained. | |||||
| movq 24(%r10), %rcx | |||||
kibUnsubmitted Not Done Inline ActionsWhat are these magic 24 and 16, 8 below? Please add a comment at least, if they cannot be symbolized. kib: What are these magic 24 and 16, 8 below? Please add a comment at least, if they cannot be… | |||||
| cmpq $0, %rcx | |||||
| je done | |||||
| shrq $3, %rcx | |||||
Not Done Inline Actions? kib: ? | |||||
Done Inline ActionsOops, this was debug from initial development that I forgot to remove. jhibbits: Oops, this was debug from initial development that I forgot to remove. | |||||
| movq 16(%r10), %rdi | |||||
| movq 8(%r10), %rsi | |||||
| rep | |||||
| movsq | |||||
| addq $KEXEC_STAGED_SEGMENT_SIZE, %r10 | |||||
| decq %r11 | |||||
Done Inline ActionsUse size suffixes consistently (see other comment) kib: Use size suffixes consistently (see other comment) | |||||
| cmpq $0, %r11 | |||||
kibUnsubmitted Not Done Inline Actionsdecq already sets the %rflags, so I do not think you need explicit cmpq kib: decq already sets the %rflags, so I do not think you need explicit cmpq | |||||
| jg copy_segment | |||||
| done: | |||||
| pushq KEXEC_ENTRY(%r9) | |||||
| ret | |||||
| fail: | |||||
| jmp fail | |||||
Not Done Inline ActionsSo mfence is still there, without explanation. I do not believe in magic. kib: So mfence is still there, without explanation. I do not believe in magic. | |||||
| END(kexec_do_reboot) | |||||
| ENTRY(kexec_do_reboot_trampoline) | |||||
Not Done Inline ActionsWhy is this needed? kib: Why is this needed? | |||||
| /* Set new page table, clears most of TLB. */ | |||||
Not Done Inline ActionsAnd this? kib: And this? | |||||
Done Inline ActionsIt's possible only one of the above is necessary. We ran into problems at reboot that looked cache related, so I went extreme paranoia. I'll test again removing each, and see if it still works correctly. jhibbits: It's possible only one of the above is necessary. We ran into problems at reboot that looked… | |||||
Not Done Inline ActionsI do not believe either of the instructions are needed. If their presence changes something, there is a bug somewhere else. kib: I do not believe either of the instructions are needed. If their presence changes something… | |||||
| movq %rdi, %cr3 | |||||
Not Done Inline ActionsYou removed mfence, but wbinvd is still there. kib: You removed mfence, but wbinvd is still there. | |||||
| /* Now flush the rest of the TLB, including global pages. */ | |||||
Done Inline ActionsSame there. kib: Same there. | |||||
| movq %cr4, %rax | |||||
| andq $~CR4_PGE, %rax | |||||
Not Done Inline ActionsNote that mov to %cr3 flushes TLB except PG_G entries, so the comment is somewhat misplaced. kib: Note that mov to %cr3 flushes TLB except PG_G entries, so the comment is somewhat misplaced. | |||||
Done Inline ActionsI'll put a blank line between the movq above and the comment, because the comment is for the %cr4 twiddling, which flushes the whole TLB including global pages. jhibbits: I'll put a blank line between the movq above and the comment, because the comment is for the… | |||||
| movq %rax, %cr4 | |||||
| jmp *%rsi | |||||
Not Done Inline ActionsSame question kib: Same question | |||||
Done Inline ActionsThis one may not be necessary, since everything is being done on this single core. I had added the wbinvd early on before noticing the problem I was experiencing was actually related to the TLB (PG_G entries not being flushed, so causing fun chaos). jhibbits: This one may not be necessary, since everything is being done on this single core. I had added… | |||||
Done Inline ActionsOther instructions use size suffix, I would write this one as andq too. kib: Other instructions use size suffix, I would write this one as `andq` too. | |||||
| END(kexec_do_reboot_trampoline) | |||||
| CNAME(kexec_saved_image): | |||||
| .globl kexec_saved_image | |||||
| .space KEXEC_IMAGE_SIZE | |||||
| .quad 0 | |||||
| /* We don't need more than quad, so just fill out the page. */ | |||||
| .p2align PAGE_SHIFT | |||||
| kexec_stack: | |||||
| CNAME(kexec_do_reboot_size): | |||||
| .globl kexec_do_reboot_size | |||||
| .quad . - kexec_do_reboot | |||||
This must be removed.