Changeset View
Changeset View
Standalone View
Standalone View
head/sys/boot/efi/loader/arch/amd64/exc.S
Property | Old Value | New Value |
---|---|---|
svn:eol-style | null | native \ No newline at end of property |
svn:keywords | null | FreeBSD=%H \ No newline at end of property |
svn:mime-type | null | text/plain \ No newline at end of property |
/*- | |||||
* Copyright (c) 2016 The FreeBSD Foundation | |||||
* All rights reserved. | |||||
* | |||||
* This software was developed by Konstantin Belousov under sponsorship | |||||
* from the FreeBSD Foundation. | |||||
* | |||||
* 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. | |||||
* | |||||
* $FreeBSD$ | |||||
*/ | |||||
.macro EH N, err=1 | |||||
.align 8 | |||||
.globl EXC\N\()_handler | |||||
EXC\N\()_handler: | |||||
.if \err != 1 | |||||
pushq $0 | |||||
.endif | |||||
pushq %rax | |||||
pushq %rdx | |||||
pushq %rcx | |||||
movl $\N,%ecx | |||||
jmp all_handlers | |||||
.endm | |||||
.text | |||||
EH 0,0 | |||||
EH 1,0 | |||||
EH 2,0 | |||||
EH 3,0 | |||||
EH 4,0 | |||||
EH 5,0 | |||||
EH 6,0 | |||||
EH 7,0 | |||||
EH 8 | |||||
EH 9,0 | |||||
EH 10 | |||||
EH 11 | |||||
EH 12 | |||||
EH 13 | |||||
EH 14 | |||||
EH 16,0 | |||||
EH 17 | |||||
EH 18,0 | |||||
EH 19,0 | |||||
EH 20,0 | |||||
.globl exc_rsp | |||||
all_handlers: | |||||
cmpq %rsp,exc_rsp(%rip) | |||||
je exception | |||||
/* | |||||
* Interrupt, not exception. | |||||
* First, copy the hardware interrupt frame to the previous stack. | |||||
* Our handler always has private IST stack. | |||||
*/ | |||||
movq (6*8)(%rsp),%rax /* saved %rsp value, AKA old stack */ | |||||
subq (5*8),%rax | |||||
movq (3*8)(%rsp),%rdx /* copy %rip to old stack */ | |||||
movq %rdx,(%rax) | |||||
movq (4*8)(%rsp),%rdx /* copy %cs */ | |||||
movq %rdx,(1*8)(%rax) | |||||
movq (5*8)(%rsp),%rdx /* copy %rflags */ | |||||
movq %rdx,(2*8)(%rax) | |||||
movq (6*8)(%rsp),%rdx /* copy %rsp */ | |||||
movq %rdx,(3*8)(%rax) | |||||
movq (7*8)(%rsp),%rdx /* copy %ss */ | |||||
movq %rdx,(4*8)(%rax) | |||||
/* | |||||
* Now simulate invocation of the original interrupt handler | |||||
* with retq. We switch stacks and execute retq from the old | |||||
* stack since there is no free registers at the last moment. | |||||
*/ | |||||
subq $16,%rax | |||||
leaq fw_intr_handlers(%rip),%rdx | |||||
movq (%rdx,%rcx,8),%rdx /* push intr handler address on old stack */ | |||||
movq %rdx,8(%rax) | |||||
movq (2*8)(%rsp),%rcx /* saved %rax is put on top of old stack */ | |||||
movq %rcx,(%rax) | |||||
movq (%rsp),%rcx | |||||
movq 8(%rsp),%rdx | |||||
movq 32(%rsp),%rsp /* switch to old stack */ | |||||
popq %rax | |||||
retq | |||||
exception: | |||||
/* | |||||
* Form the struct trapframe on our IST stack. | |||||
* Skip three words, which are currently busy with temporal | |||||
* saves. | |||||
*/ | |||||
pushq %r15 | |||||
pushq %r14 | |||||
pushq %r13 | |||||
pushq %r12 | |||||
pushq %r11 | |||||
pushq %r10 | |||||
pushq %rbp | |||||
pushq %rbx | |||||
pushq $0 /* %rax */ | |||||
pushq %r9 | |||||
pushq %r8 | |||||
pushq $0 /* %rcx */ | |||||
pushq $0 /* %rdx */ | |||||
pushq %rsi | |||||
pushq %rdi | |||||
/* | |||||
* Move %rax, %rdx, %rcx values into the final location, | |||||
* from the three words which were skipped above. | |||||
*/ | |||||
movq 0x88(%rsp),%rax | |||||
movq %rax,0x30(%rsp) /* tf_rax */ | |||||
movq 0x78(%rsp),%rax | |||||
movq %rax,0x18(%rsp) /* tf_rcx */ | |||||
movq 0x80(%rsp),%rax | |||||
movq %rax,0x10(%rsp) /* tf_rdx */ | |||||
/* | |||||
* And fill the three words themself. | |||||
*/ | |||||
movq %cr2,%rax | |||||
movq %rax,0x80(%rsp) /* tf_addr */ | |||||
movl %ecx,0x78(%rsp) /* tf_trapno */ | |||||
movw %ds,0x8e(%rsp) | |||||
movw %es,0x8c(%rsp) | |||||
movw %fs,0x7c(%rsp) | |||||
movw %gs,0x7e(%rsp) | |||||
movw $0,0x88(%rsp) /* tf_flags */ | |||||
/* | |||||
* Call dump routine. | |||||
*/ | |||||
movq %rsp,%rdi | |||||
callq report_exc | |||||
/* | |||||
* Hang after reporting. Interrupts are already disabled. | |||||
*/ | |||||
1: | |||||
hlt | |||||
jmp 1b |