Subversion Repositories HelenOS

Rev

Rev 4345 | 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. #include <arch/types.h>
  40. #include <typedefs.h>
  41.  
  42. extern void asm_delay_loop(uint32_t t);
  43. extern void asm_fake_loop(uint32_t t);
  44.  
  45. /** Return base address of current stack.
  46.  *
  47.  * Return the base address of the current stack.
  48.  * The stack is assumed to be STACK_SIZE bytes long.
  49.  * The stack must start on page boundary.
  50.  *
  51.  */
  52. static inline uintptr_t get_stack_base(void)
  53. {
  54.     uintptr_t v;
  55.    
  56.     asm volatile (
  57.         "andq %%rsp, %[v]\n"
  58.         : [v] "=r" (v)
  59.         : "0" (~((uint64_t) STACK_SIZE-1))
  60.     );
  61.    
  62.     return v;
  63. }
  64.  
  65. static inline void cpu_sleep(void)
  66. {
  67.     asm volatile ("hlt\n");
  68. }
  69.  
  70. static inline void cpu_halt(void)
  71. {
  72.     asm volatile (
  73.         "0:\n"
  74.         "   hlt\n"
  75.         "   jmp 0b\n"
  76.     );
  77. }
  78.  
  79.  
  80. /** Byte from port
  81.  *
  82.  * Get byte from port
  83.  *
  84.  * @param port Port to read from
  85.  * @return Value read
  86.  *
  87.  */
  88. static inline uint8_t pio_read_8(ioport8_t *port)
  89. {
  90.     uint8_t val;
  91.    
  92.     asm volatile (
  93.         "inb %w[port], %b[val]\n"
  94.         : [val] "=a" (val)
  95.         : [port] "d" (port)
  96.     );
  97.    
  98.     return val;
  99. }
  100.  
  101. /** Word from port
  102.  *
  103.  * Get word from port
  104.  *
  105.  * @param port Port to read from
  106.  * @return Value read
  107.  *
  108.  */
  109. static inline uint16_t pio_read_16(ioport16_t *port)
  110. {
  111.     uint16_t val;
  112.    
  113.     asm volatile (
  114.         "inw %w[port], %w[val]\n"
  115.         : [val] "=a" (val)
  116.         : [port] "d" (port)
  117.     );
  118.    
  119.     return val;
  120. }
  121.  
  122. /** Double word from port
  123.  *
  124.  * Get double word from port
  125.  *
  126.  * @param port Port to read from
  127.  * @return Value read
  128.  *
  129.  */
  130. static inline uint32_t pio_read_32(ioport32_t *port)
  131. {
  132.     uint32_t val;
  133.    
  134.     asm volatile (
  135.         "inl %w[port], %[val]\n"
  136.         : [val] "=a" (val)
  137.         : [port] "d" (port)
  138.     );
  139.    
  140.     return val;
  141. }
  142.  
  143. /** Byte to port
  144.  *
  145.  * Output byte to port
  146.  *
  147.  * @param port Port to write to
  148.  * @param val Value to write
  149.  *
  150.  */
  151. static inline void pio_write_8(ioport8_t *port, uint8_t val)
  152. {
  153.     asm volatile (
  154.         "outb %b[val], %w[port]\n"
  155.         :: [val] "a" (val), [port] "d" (port)
  156.     );
  157. }
  158.  
  159. /** Word to port
  160.  *
  161.  * Output word to port
  162.  *
  163.  * @param port Port to write to
  164.  * @param val Value to write
  165.  *
  166.  */
  167. static inline void pio_write_16(ioport16_t *port, uint16_t val)
  168. {
  169.     asm volatile (
  170.         "outw %w[val], %w[port]\n"
  171.         :: [val] "a" (val), [port] "d" (port)
  172.     );
  173. }
  174.  
  175. /** Double word to port
  176.  *
  177.  * Output double word to port
  178.  *
  179.  * @param port Port to write to
  180.  * @param val Value to write
  181.  *
  182.  */
  183. static inline void pio_write_32(ioport32_t *port, uint32_t val)
  184. {
  185.     asm volatile (
  186.         "outl %[val], %w[port]\n"
  187.         :: [val] "a" (val), [port] "d" (port)
  188.     );
  189. }
  190.  
  191. /** Swap Hidden part of GS register with visible one */
  192. static inline void swapgs(void)
  193. {
  194.     asm volatile("swapgs");
  195. }
  196.  
  197. /** Enable interrupts.
  198.  *
  199.  * Enable interrupts and return previous
  200.  * value of EFLAGS.
  201.  *
  202.  * @return Old interrupt priority level.
  203.  *
  204.  */
  205. static inline ipl_t interrupts_enable(void) {
  206.     ipl_t v;
  207.    
  208.     asm volatile (
  209.         "pushfq\n"
  210.         "popq %[v]\n"
  211.         "sti\n"
  212.         : [v] "=r" (v)
  213.     );
  214.    
  215.     return v;
  216. }
  217.  
  218. /** Disable interrupts.
  219.  *
  220.  * Disable interrupts and return previous
  221.  * value of EFLAGS.
  222.  *
  223.  * @return Old interrupt priority level.
  224.  *
  225.  */
  226. static inline ipl_t interrupts_disable(void) {
  227.     ipl_t v;
  228.    
  229.     asm volatile (
  230.         "pushfq\n"
  231.         "popq %[v]\n"
  232.         "cli\n"
  233.         : [v] "=r" (v)
  234.     );
  235.    
  236.     return v;
  237. }
  238.  
  239. /** Restore interrupt priority level.
  240.  *
  241.  * Restore EFLAGS.
  242.  *
  243.  * @param ipl Saved interrupt priority level.
  244.  *
  245.  */
  246. static inline void interrupts_restore(ipl_t ipl) {
  247.     asm volatile (
  248.         "pushq %[ipl]\n"
  249.         "popfq\n"
  250.         :: [ipl] "r" (ipl)
  251.     );
  252. }
  253.  
  254. /** Return interrupt priority level.
  255.  *
  256.  * Return EFLAFS.
  257.  *
  258.  * @return Current interrupt priority level.
  259.  *
  260.  */
  261. static inline ipl_t interrupts_read(void) {
  262.     ipl_t v;
  263.    
  264.     asm volatile (
  265.         "pushfq\n"
  266.         "popq %[v]\n"
  267.         : [v] "=r" (v)
  268.     );
  269.    
  270.     return v;
  271. }
  272.  
  273. /** Write to MSR */
  274. static inline void write_msr(uint32_t msr, uint64_t value)
  275. {
  276.     asm volatile (
  277.         "wrmsr\n"
  278.         :: "c" (msr),
  279.            "a" ((uint32_t) (value)),
  280.            "d" ((uint32_t) (value >> 32))
  281.     );
  282. }
  283.  
  284. static inline unative_t read_msr(uint32_t msr)
  285. {
  286.     uint32_t ax, dx;
  287.    
  288.     asm volatile (
  289.         "rdmsr\n"
  290.         : "=a" (ax), "=d" (dx)
  291.         : "c" (msr)
  292.     );
  293.    
  294.     return ((uint64_t) dx << 32) | ax;
  295. }
  296.  
  297.  
  298. /** Enable local APIC
  299.  *
  300.  * Enable local APIC in MSR.
  301.  *
  302.  */
  303. static inline void enable_l_apic_in_msr()
  304. {
  305.     asm volatile (
  306.         "movl $0x1b, %%ecx\n"
  307.         "rdmsr\n"
  308.         "orl $(1 << 11),%%eax\n"
  309.         "orl $(0xfee00000),%%eax\n"
  310.         "wrmsr\n"
  311.         ::: "%eax","%ecx","%edx"
  312.     );
  313. }
  314.  
  315. static inline uintptr_t * get_ip()
  316. {
  317.     uintptr_t *ip;
  318.    
  319.     asm volatile (
  320.         "mov %%rip, %[ip]"
  321.         : [ip] "=r" (ip)
  322.     );
  323.    
  324.     return ip;
  325. }
  326.  
  327. /** Invalidate TLB Entry.
  328.  *
  329.  * @param addr Address on a page whose TLB entry is to be invalidated.
  330.  *
  331.  */
  332. static inline void invlpg(uintptr_t addr)
  333. {
  334.     asm volatile (
  335.         "invlpg %[addr]\n"
  336.         :: [addr] "m" (*((unative_t *) addr))
  337.     );
  338. }
  339.  
  340. /** Load GDTR register from memory.
  341.  *
  342.  * @param gdtr_reg Address of memory from where to load GDTR.
  343.  *
  344.  */
  345. static inline void gdtr_load(ptr_16_64_t *gdtr_reg)
  346. {
  347.     asm volatile (
  348.         "lgdtq %[gdtr_reg]\n"
  349.         :: [gdtr_reg] "m" (*gdtr_reg)
  350.     );
  351. }
  352.  
  353. /** Store GDTR register to memory.
  354.  *
  355.  * @param gdtr_reg Address of memory to where to load GDTR.
  356.  *
  357.  */
  358. static inline void gdtr_store(ptr_16_64_t *gdtr_reg)
  359. {
  360.     asm volatile (
  361.         "sgdtq %[gdtr_reg]\n"
  362.         :: [gdtr_reg] "m" (*gdtr_reg)
  363.     );
  364. }
  365.  
  366. /** Load IDTR register from memory.
  367.  *
  368.  * @param idtr_reg Address of memory from where to load IDTR.
  369.  *
  370.  */
  371. static inline void idtr_load(ptr_16_64_t *idtr_reg)
  372. {
  373.     asm volatile (
  374.         "lidtq %[idtr_reg]\n"
  375.         :: [idtr_reg] "m" (*idtr_reg));
  376. }
  377.  
  378. /** Load TR from descriptor table.
  379.  *
  380.  * @param sel Selector specifying descriptor of TSS segment.
  381.  *
  382.  */
  383. static inline void tr_load(uint16_t sel)
  384. {
  385.     asm volatile (
  386.         "ltr %[sel]"
  387.         :: [sel] "r" (sel)
  388.     );
  389. }
  390.  
  391. #define GEN_READ_REG(reg) static inline unative_t read_ ##reg (void) \
  392.     { \
  393.         unative_t res; \
  394.         asm volatile ( \
  395.             "movq %%" #reg ", %[res]" \
  396.             : [res] "=r" (res) \
  397.         ); \
  398.         return res; \
  399.     }
  400.  
  401. #define GEN_WRITE_REG(reg) static inline void write_ ##reg (unative_t regn) \
  402.     { \
  403.         asm volatile ( \
  404.             "movq %[regn], %%" #reg \
  405.             :: [regn] "r" (regn) \
  406.         ); \
  407.     }
  408.  
  409. GEN_READ_REG(cr0)
  410. GEN_READ_REG(cr2)
  411. GEN_READ_REG(cr3)
  412. GEN_WRITE_REG(cr3)
  413.  
  414. GEN_READ_REG(dr0)
  415. GEN_READ_REG(dr1)
  416. GEN_READ_REG(dr2)
  417. GEN_READ_REG(dr3)
  418. GEN_READ_REG(dr6)
  419. GEN_READ_REG(dr7)
  420.  
  421. GEN_WRITE_REG(dr0)
  422. GEN_WRITE_REG(dr1)
  423. GEN_WRITE_REG(dr2)
  424. GEN_WRITE_REG(dr3)
  425. GEN_WRITE_REG(dr6)
  426. GEN_WRITE_REG(dr7)
  427.  
  428. extern size_t interrupt_handler_size;
  429. extern void interrupt_handlers(void);
  430.  
  431. #endif
  432.  
  433. /** @}
  434.  */
  435.