1// Copyright 2016 The Fuchsia Authors 2// Copyright (c) 2009 Corey Tabaka 3// 4// Use of this source code is governed by a MIT-style 5// license that can be found in the LICENSE file or at 6// https://opensource.org/licenses/MIT 7 8#include <asm.h> 9#include <arch/x86/mp.h> 10#include <err.h> 11 12.text 13 14/* This follows the x86-64 ABI, the parameters are stored in registers in the following order*/ 15/* 16%rdi used to pass 1st argument 17%rsi used to pass 2nd argument 18%rdx used to pass 3rd argument and 2nd return register 19%rcx used to pass 4th argument 20%r8 used to pass 5th argument 21%r9 used to pass 6th argument 22%rax 1st return register 23*/ 24 25/* void x86_idle(); */ 26FUNCTION(x86_idle) 27 pushf 28 popq %rax 29 andq $0x200, %rax 30 test %rax, %rax 31 je 1f /* don't halt if local interrupts are disabled */ 32 hlt 331: 34 ret 35END_FUNCTION(x86_idle) 36 37 38/* zx_status_t read_msr_safe(uint32_t msr_id, uint64_t *val); */ 39FUNCTION(read_msr_safe) 40 // Set up MSR index 41 mov %rdi, %rcx 42 43 // Disable interrupts before touching percpu state 44 pushfq 45 cli 46 47 // Set up the GPF handler, in case the MSR doesn't exist 48 leaq .Lgpf_handler(%rip), %rax 49 movq %rax, %gs:PERCPU_GPF_RETURN_OFFSET 50 rdmsr 51 52 // Cleanup the GPF handler 53 movq $0, %gs:PERCPU_GPF_RETURN_OFFSET 54 // Restore interrupts if they were on before 55 popfq 56 57 // rdmsr returns value via edx:eax 58 shl $32, %rdx 59 or %rax, %rdx 60 mov %rdx, (%rsi) 61 62 mov $ZX_OK, %rax 63 ret 64.Lgpf_handler: 65 // Cleanup GPF handler 66 movq $0, %gs:PERCPU_GPF_RETURN_OFFSET 67 // Restore interrupts if they were on before 68 popfq 69 70 mov $ZX_ERR_NOT_SUPPORTED, %rax 71 ret 72END_FUNCTION(read_msr_safe) 73 74/* void x86_mwait(); */ 75FUNCTION(x86_mwait) 76 pushf 77 popq %rax 78 andq $0x200, %rax 79 test %rax, %rax 80 je 1f /* don't halt if local interrupts are disabled */ 81 // Clear the mwait hints and extension registers 82 xor %eax, %eax 83 xor %ecx, %ecx 84 mwait 851: 86 ret 87END_FUNCTION(x86_mwait) 88 89/* void x86_monitor(void* addr); */ 90FUNCTION(x86_monitor) 91 // Set the address to monitor 92 movq %rdi, %rax 93 // Clear the monitor extension and hints registers 94 xor %ecx, %ecx 95 xor %edx, %edx 96 monitor 97 ret 98END_FUNCTION(x86_monitor) 99