Subversion Repositories HelenOS

Rev

Rev 2452 | Rev 3902 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. /*
  2.  * Copyright (c) 2005 Jakub Jermar
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  *
  9.  * - Redistributions of source code must retain the above copyright
  10.  *   notice, this list of conditions and the following disclaimer.
  11.  * - Redistributions in binary form must reproduce the above copyright
  12.  *   notice, this list of conditions and the following disclaimer in the
  13.  *   documentation and/or other materials provided with the distribution.
  14.  * - The name of the author may not be used to endorse or promote products
  15.  *   derived from this software without specific prior written permission.
  16.  *
  17.  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  18.  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  19.  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  20.  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  21.  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  22.  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  23.  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  24.  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  25.  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  26.  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  27.  */
  28.  
  29. /** @addtogroup amd64  
  30.  * @{
  31.  */
  32. /** @file
  33.  */
  34.  
  35. #ifndef KERN_amd64_ASM_H_
  36. #define KERN_amd64_ASM_H_
  37.  
  38. #include <config.h>
  39.  
  40. extern void asm_delay_loop(uint32_t t);
  41. extern void asm_fake_loop(uint32_t t);
  42.  
  43. /** Return base address of current stack.
  44.  *
  45.  * Return the base address of the current stack.
  46.  * The stack is assumed to be STACK_SIZE bytes long.
  47.  * The stack must start on page boundary.
  48.  */
  49. static inline uintptr_t get_stack_base(void)
  50. {
  51.     uintptr_t v;
  52.    
  53.     asm volatile ("andq %%rsp, %0\n" : "=r" (v) : "0" (~((uint64_t)STACK_SIZE-1)));
  54.    
  55.     return v;
  56. }
  57.  
  58. static inline void cpu_sleep(void)
  59. {
  60.     asm volatile ("hlt\n");
  61. }
  62.  
  63. static inline void cpu_halt(void)
  64. {
  65.     asm volatile ("hlt\n");
  66. }
  67.  
  68.  
  69. /** Byte from port
  70.  *
  71.  * Get byte from port
  72.  *
  73.  * @param port Port to read from
  74.  * @return Value read
  75.  */
  76. static inline uint8_t inb(uint16_t port)
  77. {
  78.     uint8_t val;
  79.  
  80.     asm volatile ("inb %w1, %b0 \n" : "=a" (val) : "d" (port));
  81.     return val;
  82. }
  83.  
  84. /** Byte to port
  85.  *
  86.  * Output byte to port
  87.  *
  88.  * @param port Port to write to
  89.  * @param val Value to write
  90.  */
  91. static inline void outb(uint16_t port, uint8_t val)
  92. {
  93.     asm volatile ("outb %b0, %w1\n" : : "a" (val), "d" (port));
  94. }
  95.  
  96. /** Swap Hidden part of GS register with visible one */
  97. static inline void swapgs(void)
  98. {
  99.     asm volatile("swapgs");
  100. }
  101.  
  102. /** Enable interrupts.
  103.  *
  104.  * Enable interrupts and return previous
  105.  * value of EFLAGS.
  106.  *
  107.  * @return Old interrupt priority level.
  108.  */
  109. static inline ipl_t interrupts_enable(void) {
  110.     ipl_t v;
  111.     __asm__ volatile (
  112.         "pushfq\n"
  113.         "popq %0\n"
  114.         "sti\n"
  115.         : "=r" (v)
  116.     );
  117.     return v;
  118. }
  119.  
  120. /** Disable interrupts.
  121.  *
  122.  * Disable interrupts and return previous
  123.  * value of EFLAGS.
  124.  *
  125.  * @return Old interrupt priority level.
  126.  */
  127. static inline ipl_t interrupts_disable(void) {
  128.     ipl_t v;
  129.     __asm__ volatile (
  130.         "pushfq\n"
  131.         "popq %0\n"
  132.         "cli\n"
  133.         : "=r" (v)
  134.         );
  135.     return v;
  136. }
  137.  
  138. /** Restore interrupt priority level.
  139.  *
  140.  * Restore EFLAGS.
  141.  *
  142.  * @param ipl Saved interrupt priority level.
  143.  */
  144. static inline void interrupts_restore(ipl_t ipl) {
  145.     __asm__ volatile (
  146.         "pushq %0\n"
  147.         "popfq\n"
  148.         : : "r" (ipl)
  149.         );
  150. }
  151.  
  152. /** Return interrupt priority level.
  153.  *
  154.  * Return EFLAFS.
  155.  *
  156.  * @return Current interrupt priority level.
  157.  */
  158. static inline ipl_t interrupts_read(void) {
  159.     ipl_t v;
  160.     __asm__ volatile (
  161.         "pushfq\n"
  162.         "popq %0\n"
  163.         : "=r" (v)
  164.     );
  165.     return v;
  166. }
  167.  
  168. /** Write to MSR */
  169. static inline void write_msr(uint32_t msr, uint64_t value)
  170. {
  171.     __asm__ volatile (
  172.         "wrmsr;" : : "c" (msr),
  173.         "a" ((uint32_t)(value)),
  174.         "d" ((uint32_t)(value >> 32))
  175.         );
  176. }
  177.  
  178. static inline unative_t read_msr(uint32_t msr)
  179. {
  180.     uint32_t ax, dx;
  181.  
  182.     __asm__ volatile (
  183.         "rdmsr;" : "=a"(ax), "=d"(dx) : "c" (msr)
  184.         );
  185.     return ((uint64_t)dx << 32) | ax;
  186. }
  187.  
  188.  
  189. /** Enable local APIC
  190.  *
  191.  * Enable local APIC in MSR.
  192.  */
  193. static inline void enable_l_apic_in_msr()
  194. {
  195.     __asm__ volatile (
  196.         "movl $0x1b, %%ecx\n"
  197.         "rdmsr\n"
  198.         "orl $(1<<11),%%eax\n"
  199.         "orl $(0xfee00000),%%eax\n"
  200.         "wrmsr\n"
  201.         :
  202.         :
  203.         :"%eax","%ecx","%edx"
  204.         );
  205. }
  206.  
  207. static inline uintptr_t * get_ip()
  208. {
  209.     uintptr_t *ip;
  210.  
  211.     __asm__ volatile (
  212.         "mov %%rip, %0"
  213.         : "=r" (ip)
  214.         );
  215.     return ip;
  216. }
  217.  
  218. /** Invalidate TLB Entry.
  219.  *
  220.  * @param addr Address on a page whose TLB entry is to be invalidated.
  221.  */
  222. static inline void invlpg(uintptr_t addr)
  223. {
  224.     __asm__ volatile ("invlpg %0\n" :: "m" (*((unative_t *)addr)));
  225. }
  226.  
  227. /** Load GDTR register from memory.
  228.  *
  229.  * @param gdtr_reg Address of memory from where to load GDTR.
  230.  */
  231. static inline void gdtr_load(struct ptr_16_64 *gdtr_reg)
  232. {
  233.     __asm__ volatile ("lgdtq %0\n" : : "m" (*gdtr_reg));
  234. }
  235.  
  236. /** Store GDTR register to memory.
  237.  *
  238.  * @param gdtr_reg Address of memory to where to load GDTR.
  239.  */
  240. static inline void gdtr_store(struct ptr_16_64 *gdtr_reg)
  241. {
  242.     __asm__ volatile ("sgdtq %0\n" : : "m" (*gdtr_reg));
  243. }
  244.  
  245. /** Load IDTR register from memory.
  246.  *
  247.  * @param idtr_reg Address of memory from where to load IDTR.
  248.  */
  249. static inline void idtr_load(struct ptr_16_64 *idtr_reg)
  250. {
  251.     __asm__ volatile ("lidtq %0\n" : : "m" (*idtr_reg));
  252. }
  253.  
  254. /** Load TR from descriptor table.
  255.  *
  256.  * @param sel Selector specifying descriptor of TSS segment.
  257.  */
  258. static inline void tr_load(uint16_t sel)
  259. {
  260.     __asm__ volatile ("ltr %0" : : "r" (sel));
  261. }
  262.  
  263. #define GEN_READ_REG(reg) static inline unative_t read_ ##reg (void) \
  264.     { \
  265.     unative_t res; \
  266.     __asm__ volatile ("movq %%" #reg ", %0" : "=r" (res) ); \
  267.     return res; \
  268.     }
  269.  
  270. #define GEN_WRITE_REG(reg) static inline void write_ ##reg (unative_t regn) \
  271.     { \
  272.     __asm__ volatile ("movq %0, %%" #reg : : "r" (regn)); \
  273.     }
  274.  
  275. GEN_READ_REG(cr0)
  276. GEN_READ_REG(cr2)
  277. GEN_READ_REG(cr3)
  278. GEN_WRITE_REG(cr3)
  279.  
  280. GEN_READ_REG(dr0)
  281. GEN_READ_REG(dr1)
  282. GEN_READ_REG(dr2)
  283. GEN_READ_REG(dr3)
  284. GEN_READ_REG(dr6)
  285. GEN_READ_REG(dr7)
  286.  
  287. GEN_WRITE_REG(dr0)
  288. GEN_WRITE_REG(dr1)
  289. GEN_WRITE_REG(dr2)
  290. GEN_WRITE_REG(dr3)
  291. GEN_WRITE_REG(dr6)
  292. GEN_WRITE_REG(dr7)
  293.  
  294. extern size_t interrupt_handler_size;
  295. extern void interrupt_handlers(void);
  296.  
  297. #endif
  298.  
  299. /** @}
  300.  */
  301.