1/* 2 * Copyright (c) 2009 Apple Inc. All rights reserved. 3 * 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. The rights granted to you under the License 10 * may not be used to create, or enable the creation or redistribution of, 11 * unlawful or unlicensed copies of an Apple operating system, or to 12 * circumvent, violate, or enable the circumvention or violation of, any 13 * terms of an Apple operating system software license agreement. 14 * 15 * Please obtain a copy of the License at 16 * http://www.opensource.apple.com/apsl/ and read it before using this file. 17 * 18 * The Original Code and all software distributed under the License are 19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 23 * Please see the License for the specific language governing rights and 24 * limitations under the License. 25 * 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 27 */ 28 29#include <i386/asm.h> 30#include <i386/asm64.h> 31 32#include <assym.s> 33 34/* 35 * Copy "count" bytes from "src" to %rsp, using 36 * "tmpindex" for a scratch counter and %rax 37 */ 38#define COPY_STACK(src, count, tmpindex) \ 39 mov $0, tmpindex /* initial scratch counter */ ; \ 401: \ 41 mov 0(src,tmpindex,1), %rax /* copy one 64-bit word from source... */ ; \ 42 mov %rax, 0(%rsp,tmpindex,1) /* ... to stack */ ; \ 43 add $8, tmpindex /* increment counter */ ; \ 44 cmp count, tmpindex /* exit it stack has been copied */ ; \ 45 jne 1b 46 47/* 48 void 49 pal_efi_call_in_64bit_mode_asm(uint64_t func, 50 struct pal_efi_registers *efi_reg, 51 void *stack_contents, 52 size_t stack_contents_size) 53 54 * Switch from compatibility mode to long mode, and 55 * then execute the function pointer with the specified 56 * register and stack contents (based at %rsp). Afterwards, 57 * collect the return value, restore the original state, 58 * and return. 59*/ 60ENTRY(_pal_efi_call_in_64bit_mode_asm) 61 FRAME 62 63 /* save non-volatile registers */ 64 push %rbx 65 push %r12 66 push %r13 67 push %r14 68 push %r15 69 70 /* save parameters that we will need later */ 71 push %rsi 72 push %rcx 73 74 sub $8, %rsp /* align to 16-byte boundary */ 75 /* efi_reg in %rsi */ 76 /* stack_contents into %rdx */ 77 /* s_c_s into %rcx */ 78 sub %rcx, %rsp /* make room for stack contents */ 79 80 COPY_STACK(%rdx, %rcx, %r8) 81 82 /* load efi_reg into real registers */ 83 mov 0(%rsi), %rcx 84 mov 8(%rsi), %rdx 85 mov 16(%rsi), %r8 86 mov 24(%rsi), %r9 87 mov 32(%rsi), %rax 88 89 /* func pointer in %rdi */ 90 call *%rdi /* call EFI runtime */ 91 92 mov -48(%rbp), %rsi /* load efi_reg into %esi */ 93 mov %rax, 32(%rsi) /* save RAX back */ 94 95 mov -56(%rbp), %rcx /* load s_c_s into %rcx */ 96 add %rcx, %rsp /* discard stack contents */ 97 add $8, %rsp /* restore stack pointer */ 98 99 pop %rcx 100 pop %rsi 101 pop %r15 102 pop %r14 103 pop %r13 104 pop %r12 105 pop %rbx 106 107 EMARF 108 ret 109 110/* 111 void 112 pal_efi_call_in_32bit_mode_asm(uint32_t func, 113 struct pal_efi_registers *efi_reg, 114 void *stack_contents, 115 size_t stack_contents_size) 116 117*/ 118ENTRY(_pal_efi_call_in_32bit_mode_asm) 119 FRAME 120 121 /* save non-volatile registers */ 122 push %rbx 123 push %r12 124 push %r13 125 push %r14 126 push %r15 127 128 /* save parameters that we will need later */ 129 push %rsi 130 push %rcx 131 132 push %rbp /* save %rbp and align to 16-byte boundary */ 133 /* efi_reg in %rsi */ 134 /* stack_contents into %rdx */ 135 /* s_c_s into %rcx */ 136 sub %rcx, %rsp /* make room for stack contents */ 137 138 COPY_STACK(%rdx, %rcx, %r8) 139 140 /* 141 * Here in long-mode, with high kernel addresses, 142 * but with the kernel double-mapped in the bottom 4GB. 143 * We now switch to compat mode and call into EFI. 144 */ 145 ENTER_COMPAT_MODE() 146 147 call *%edi /* call EFI runtime */ 148 149 ENTER_64BIT_MODE() 150 151 mov -48(%rbp), %rsi /* load efi_reg into %esi */ 152 mov %rax, 32(%rsi) /* save RAX back */ 153 154 mov -56(%rbp), %rcx /* load s_c_s into %rcx */ 155 add %rcx, %rsp /* discard stack contents */ 156 pop %rbp /* restore full 64-bit frame pointer */ 157 /* which the 32-bit EFI will have truncated */ 158 /* our full %rsp will be restored by EMARF */ 159 pop %rcx 160 pop %rsi 161 pop %r15 162 pop %r14 163 pop %r13 164 pop %r12 165 pop %rbx 166 167 EMARF 168 ret 169 170 171 172/* 173 * void _pal_rtc_nanotime_store( 174 * uint64_t tsc, // %rdi 175 * uint64_t nsec, // %rsi 176 * uint32_t scale, // %rdx 177 * uint32_t shift, // %rcx 178 * rtc_nanotime_t *dst); // %r8 179 */ 180ENTRY(_pal_rtc_nanotime_store) 181 movl RNT_GENERATION(%r8),%eax /* get current generation */ 182 movl $0,RNT_GENERATION(%r8) /* flag data as being updated */ 183 movq %rdi,RNT_TSC_BASE(%r8) 184 movq %rsi,RNT_NS_BASE(%r8) 185 movl %edx,RNT_SCALE(%r8) 186 movl %ecx,RNT_SHIFT(%r8) 187 188 incl %eax /* next generation */ 189 jnz 1f 190 incl %eax /* skip 0, which is a flag */ 1911: movl %eax,RNT_GENERATION(%r8) /* update generation */ 192 193 ret 194 195