blob: 89fff7d7a4f8ee1f69e0f9cd5ca9e478dafb7230 [file] [log] [blame]
// Copyright 2016 The Fuchsia Authors
// Copyright (c) 2009 Corey Tabaka
//
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file or at
// https://opensource.org/licenses/MIT
#include <asm.h>
#include <arch/x86/mp.h>
#include <err.h>
.text
/* This follows the x86-64 ABI, the parameters are stored in registers in the following order*/
/*
%rdi used to pass 1st argument
%rsi used to pass 2nd argument
%rdx used to pass 3rd argument and 2nd return register
%rcx used to pass 4th argument
%r8 used to pass 5th argument
%r9 used to pass 6th argument
%rax 1st return register
*/
/* void x86_idle(); */
FUNCTION(x86_idle)
pushf
popq %rax
andq $0x200, %rax
test %rax, %rax
je 1f /* don't halt if local interrupts are disabled */
hlt
1:
ret
END_FUNCTION(x86_idle)
/* zx_status_t read_msr_safe(uint32_t msr_id, uint64_t *val); */
FUNCTION(read_msr_safe)
// Set up MSR index
mov %rdi, %rcx
// Disable interrupts before touching percpu state
pushfq
cli
// Set up the GPF handler, in case the MSR doesn't exist
leaq .Lgpf_handler(%rip), %rax
movq %rax, %gs:PERCPU_GPF_RETURN_OFFSET
rdmsr
// Cleanup the GPF handler
movq $0, %gs:PERCPU_GPF_RETURN_OFFSET
// Restore interrupts if they were on before
popfq
// rdmsr returns value via edx:eax
shl $32, %rdx
or %rax, %rdx
mov %rdx, (%rsi)
mov $ZX_OK, %rax
ret
.Lgpf_handler:
// Cleanup GPF handler
movq $0, %gs:PERCPU_GPF_RETURN_OFFSET
// Restore interrupts if they were on before
popfq
mov $ZX_ERR_NOT_SUPPORTED, %rax
ret
END_FUNCTION(read_msr_safe)
/* void x86_mwait(); */
FUNCTION(x86_mwait)
pushf
popq %rax
andq $0x200, %rax
test %rax, %rax
je 1f /* don't halt if local interrupts are disabled */
// Clear the mwait hints and extension registers
xor %eax, %eax
xor %ecx, %ecx
mwait
1:
ret
END_FUNCTION(x86_mwait)
/* void x86_monitor(void* addr); */
FUNCTION(x86_monitor)
// Set the address to monitor
movq %rdi, %rax
// Clear the monitor extension and hints registers
xor %ecx, %ecx
xor %edx, %edx
monitor
ret
END_FUNCTION(x86_monitor)