1/**
2 * \file
3 * \brief X86 inline asm utilities and defines
4 */
5
6/*
7 * Copyright (c) 2007, 2008, 2009, 2010, 2011, ETH Zurich.
8 * All rights reserved.
9 *
10 * This file is distributed under the terms in the attached LICENSE file.
11 * If you do not find this file, copies can be found by writing to:
12 * ETH Zurich D-INFK, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group.
13 */
14
15#ifndef __X86_H
16#define __X86_H
17
18#include <barrelfish_kpi/types.h>
19#include <barrelfish_kpi/cpu.h>
20#include <arch/x86/x86.h>
21#include <barrelfish_kpi/cpu_arch.h>
22
23/***** RFLAGS flags *****/
24
25/* Fixed flags */
26#define RFLAGS_ALWAYS1  (1 << 1)
27
28/* Status/Control flags */
29#define RFLAGS_CF       (1 << 0)
30#define RFLAGS_PF       (1 << 2)
31#define RFLAGS_AF       (1 << 4)
32#define RFLAGS_ZF       (1 << 6)
33#define RFLAGS_SF       (1 << 7)
34#define RFLAGS_DF       (1 << 10)
35#define RFLAGS_OF       (1 << 11)
36
37/* System flags */
38#define RFLAGS_TF       (1 << 8)
39#define RFLAGS_IF       (1 << 9)
40#define RFLAGS_NT       (1 << 14)
41#define RFLAGS_RF       (1 << 16)
42#define RFLAGS_VM       (1 << 17)
43#define RFLAGS_AC       (1 << 18)
44#define RFLAGS_VIF      (1 << 19)
45#define RFLAGS_VIP      (1 << 20)
46#define RFLAGS_ID       (1 << 21)
47
48/* I/O privilege flags */
49#define RFLAGS_IOPL0    (0 << 12)
50#define RFLAGS_IOPL1    (1 << 12)
51#define RFLAGS_IOPL2    (2 << 12)
52#define RFLAGS_IOPL3    (3 << 12)
53
54/**
55 * State of RFLAGS when executing a user-space program: Enable interrupts
56 */
57#define USER_RFLAGS     (RFLAGS_ALWAYS1 | RFLAGS_IF)
58
59/**
60 * Allowed RFLAGS in user-space. Used when resuming programs.
61 */
62#define USER_RFLAGS_MASK \
63    (RFLAGS_CF | RFLAGS_PF | RFLAGS_AF | RFLAGS_ZF | RFLAGS_SF | RFLAGS_DF | \
64     RFLAGS_OF)
65
66/**
67 * Start address of kernel image in physical memory. This is passed to
68 * the linker also. The bootloader will load us there.
69 */
70#define START_KERNEL_PHYS X86_64_START_KERNEL_PHYS
71
72#ifndef __ASSEMBLER__
73
74/**
75 * Registers automatically saved on kernel stack by CPU
76 */
77enum x86_64_cpu_save_registers {
78    X86_SAVE_RIP, X86_SAVE_CS, X86_SAVE_EFLAGS, X86_SAVE_RSP, X86_SAVE_SS,
79    X86_SAVE_AREA_SIZE
80};
81
82/** \brief Enable FPU */
83static inline void enable_fpu(void)
84{
85    uint64_t cr0, cr4;
86    uint32_t mxcsr_value = 0x1f80;
87
88    __asm__ __volatile__("mov %%cr0, %%rax" : "=a" (cr0) : );
89    //clear EM
90    cr0 &= ~(1 << 2);
91    //set MP
92    cr0 |= (1 << 1);
93    //set NE
94    cr0 |= (1 << 5);
95    //clear TS
96    cr0 &= ~(1 << 3);
97    __asm__ __volatile__("mov %%rax,%%cr0" : : "a" (cr0));
98    //set OSFXSR
99    __asm__ __volatile__("mov %%cr4, %%rax" : "=a" (cr4) : );
100    cr4 |= (1 << 9);
101    __asm__ __volatile__("mov %%rax,%%cr4" : : "a" (cr4));
102    __asm volatile ("fninit                    \n\t"
103                    "ldmxcsr    %[mxcsr_value] \n\t"
104                    : : [mxcsr_value] "m" (mxcsr_value));
105}
106
107static inline void monitor(lvaddr_t base, uint32_t extensions, uint32_t hints)
108{
109    __asm volatile("monitor"
110                   : // No output
111                   :
112                   "a" (base),
113                   "c" (extensions),
114                   "d" (hints)
115                   );
116}
117
118static inline void mwait(uint32_t hints, uint32_t extensions)
119{
120    __asm volatile("mwait"
121                   : // No output
122                   :
123                   "a" (hints),
124                   "c" (extensions)
125                   );
126}
127
128#endif //__ASSEMBLER__
129
130#endif //__X86_H
131