123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264 |
- /*
- * cpu.h
- *
- * Copyright (C) 2016 Aleksandar Andrejevic <theflash@sdf.lonestar.org>
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
- #ifndef _CPU_H_
- #define _CPU_H_
- #include <sdk/defs.h>
- #include <sdk/cpu.h>
- #define CPU_CONTROL_FLAG_PE (1 << 0)
- #define CPU_CONTROL_FLAG_MP (1 << 1)
- #define CPU_CONTROL_FLAG_EM (1 << 2)
- #define CPU_CONTROL_FLAG_TS (1 << 3)
- #define CPU_CONTROL_FLAG_ET (1 << 4)
- #define CPU_CONTROL_FLAG_NE (1 << 5)
- #define CPU_CONTROL_FLAG_WP (1 << 16)
- #define CPU_CONTROL_FLAG_AM (1 << 18)
- #define CPU_CONTROL_FLAG_NW (1 << 29)
- #define CPU_CONTROL_FLAG_CD (1 << 30)
- #define CPU_CONTROL_FLAG_PG (1 << 31)
- #define CPU_FEATURE_FLAG_VME (1 << 0)
- #define CPU_FEATURE_FLAG_PVI (1 << 1)
- #define CPU_FEATURE_FLAG_TSD (1 << 2)
- #define CPU_FEATURE_FLAG_DE (1 << 3)
- #define CPU_FEATURE_FLAG_PSE (1 << 4)
- #define CPU_FEATURE_FLAG_PAE (1 << 5)
- #define CPU_FEATURE_FLAG_MCE (1 << 6)
- #define CPU_FEATURE_FLAG_PGE (1 << 7)
- #define CPU_FEATURE_FLAG_PCE (1 << 8)
- #define CPU_FEATURE_FLAG_OSXFSR (1 << 9)
- #define CPU_FEATURE_FLAG_OSXMMEXCPT (1 << 10)
- #define CPU_FEATURE_FLAG_UMIP (1 << 11)
- #define CPU_FEATURE_FLAG_LA57 (1 << 12)
- #define CPU_FEATURE_FLAG_VMXE (1 << 13)
- #define CPU_FEATURE_FLAG_SMXE (1 << 14)
- #define CPU_FEATURE_FLAG_FSGSBASE (1 << 16)
- #define CPU_FEATURE_FLAG_PCIDE (1 << 17)
- #define CPU_FEATURE_FLAG_OSXSAVE (1 << 18)
- #define CPU_FEATURE_FLAG_SMEP (1 << 20)
- #define CPU_FEATURE_FLAG_SMAP (1 << 21)
- #define CPU_FEATURE_FLAG_PKE (1 << 22)
- enum
- {
- FPU_NOT_PRESENT = 0,
- FPU_LEGACY,
- FPU_XFSR,
- };
- typedef word_t port_t;
- #define IO_PORT_FUNCTIONS(type, prefix) \
- static inline type##_t cpu_read_port_##type(port_t port) \
- { \
- type##_t value; \
- __asm__ volatile ("in %1, %0\n" : "=a"(value) : "Nd"(port)); \
- return value; \
- } \
- \
- static inline void cpu_write_port_##type(port_t port, type##_t value) \
- { \
- __asm__ volatile ("out %0, %1\n" :: "a"(value), "Nd"(port)); \
- } \
- \
- static inline void cpu_read_port_buffer_##type(port_t port, type##_t *buffer, size_t size) \
- { \
- __asm__ volatile("cld\n" \
- "rep; ins" prefix "\n" \
- :"+D"(buffer), "+c"(size) \
- : "d"(port) \
- : "cc"); \
- } \
- \
- static inline void cpu_write_port_buffer_##type(port_t port, const type##_t *buffer, size_t size) \
- { \
- __asm__ volatile("cld\n" \
- "rep; outs " prefix "\n" \
- : "+S"(buffer), "+c"(size) \
- : "d"(port) \
- : "cc"); \
- }
- IO_PORT_FUNCTIONS(byte, "b")
- IO_PORT_FUNCTIONS(word, "w")
- IO_PORT_FUNCTIONS(dword, "l")
- static inline uintptr_t cpu_read_master_control_register(void)
- {
- uintptr_t value;
- __asm__ volatile ("movl %%cr0, %0"
- : "=r"((dword_t)value) /* output */
- : /* input */
- : /* clobber */);
- return value;
- }
- static inline void cpu_write_master_control_register(uintptr_t value)
- {
- __asm__ volatile ("movl %0, %%cr0"
- : /* output */
- : "r"((dword_t)value) /* input */
- : /* clobber */);
- }
- static inline uintptr_t cpu_read_faulting_address(void)
- {
- uintptr_t value;
- __asm__ volatile ("movl %%cr2, %0"
- : "=r"((dword_t)value) /* output */
- : /* input */
- : /* clobber */);
- return value;
- }
- static inline uintptr_t cpu_read_page_table_register(void)
- {
- uintptr_t value;
- __asm__ volatile ("movl %%cr3, %0"
- : "=r"((dword_t)value) /* output */
- : /* input */
- : /* clobber */);
- return value;
- }
- static inline void cpu_write_page_table_register(uintptr_t value)
- {
- __asm__ volatile ("movl %0, %%cr3"
- : /* output */
- : "r"((dword_t)value) /* input */
- : /* clobber */);
- }
- static inline uintptr_t cpu_read_feature_register(void)
- {
- uintptr_t value;
- __asm__ volatile ("movl %%cr4, %0"
- : "=r"((dword_t)value) /* output */
- : /* input */
- : /* clobber */);
- return value;
- }
- static inline void cpu_write_feature_register(uintptr_t value)
- {
- __asm__ volatile ("movl %0, %%cr4"
- : /* output */
- : "r"((dword_t)value) /* input */
- : /* clobber */);
- }
- static inline bool_t cpu_enable_interrupts(void)
- {
- dword_t flags;
- __asm__ volatile ("pushf\n"
- "sti\n"
- "pop %0"
- : "=g"(flags) /* output */
- : /* input */
- : /* clobber */);
- return !!(flags & CPU_STATUS_FLAG_IF);
- }
- static inline bool_t cpu_disable_interrupts(void)
- {
- dword_t flags;
- __asm__ volatile ("pushf\n"
- "cli\n"
- "pop %0"
- : "=g"(flags) /* output */
- : /* input */
- : /* clobber */);
- return !!(flags & CPU_STATUS_FLAG_IF);
- }
- static inline void cpu_set_interrupt_table(void *base, word_t size)
- {
- struct
- {
- word_t length;
- void *base;
- } __attribute__((__packed__)) idtr = { size - 1, base };
- __asm__ volatile ("lidt %0"
- : /* output */
- : "m"(idtr) /* input */
- : /* clobber */);
- }
- static inline void cpu_invalidate_tlb(void *address)
- {
- __asm__ volatile ("invlpg (%0)"
- : /* output */
- : "r"(address) /* input */
- : "memory" /* clobber */);
- }
- static inline void cpu_halt(void)
- {
- __asm__ volatile ("hlt");
- }
- extern int cpu_fpu_present;
- extern byte_t cpu_max_physical_bits;
- static inline void cpu_save_fpu_state(void *state)
- {
- switch (cpu_fpu_present)
- {
- case FPU_LEGACY:
- asm volatile ("fsave %0"
- : "=m"(*(byte_t*)state) /* output */
- : /* input */
- : /* clobber */);
- break;
- case FPU_XFSR:
- asm volatile ("fxsave %0"
- : "=m"(*(byte_t*)state) /* output */
- : /* input */
- : /* clobber */);
- break;
- }
- }
- static inline void cpu_restore_fpu_state(void *state)
- {
- switch (cpu_fpu_present)
- {
- case FPU_LEGACY:
- asm volatile ("frstor %0"
- : /* output */
- : "m"(*(byte_t*)state) /* input */
- : /* clobber */);
- break;
- case FPU_XFSR:
- asm volatile ("fxrstor %0"
- : /* output */
- : "m"(*(byte_t*)state) /* input */
- : /* clobber */);
- break;
- }
- }
- void cpu_init(void);
- #endif
|