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