Subversion Repositories HelenOS

Rev

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

  1. /*
  2.  * Copyright (c) 2001-2004 Jakub Jermar
  3.  * Copyright (c) 2005 Sergey Bondari
  4.  * All rights reserved.
  5.  *
  6.  * Redistribution and use in source and binary forms, with or without
  7.  * modification, are permitted provided that the following conditions
  8.  * are met:
  9.  *
  10.  * - Redistributions of source code must retain the above copyright
  11.  *   notice, this list of conditions and the following disclaimer.
  12.  * - Redistributions in binary form must reproduce the above copyright
  13.  *   notice, this list of conditions and the following disclaimer in the
  14.  *   documentation and/or other materials provided with the distribution.
  15.  * - The name of the author may not be used to endorse or promote products
  16.  *   derived from this software without specific prior written permission.
  17.  *
  18.  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  19.  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  20.  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  21.  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  22.  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  23.  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  24.  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  25.  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  26.  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  27.  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  28.  */
  29.  
  30. /** @addtogroup ia32
  31.  * @{
  32.  */
  33. /** @file
  34.  */
  35.  
  36. #ifndef KERN_ia32_ASM_H_
  37. #define KERN_ia32_ASM_H_
  38.  
  39. #include <arch/pm.h>
  40. #include <arch/types.h>
  41. #include <config.h>
  42.  
  43. extern uint32_t interrupt_handler_size;
  44.  
  45. extern void paging_on(void);
  46.  
  47. extern void interrupt_handlers(void);
  48.  
  49. extern void enable_l_apic_in_msr(void);
  50.  
  51.  
  52. extern void asm_delay_loop(uint32_t t);
  53. extern void asm_fake_loop(uint32_t t);
  54.  
  55.  
  56. /** Halt CPU
  57.  *
  58.  * Halt the current CPU until interrupt event.
  59.  *
  60.  */
  61. static inline void cpu_halt(void)
  62. {
  63.     asm volatile ("hlt\n");
  64. }
  65.  
  66. static inline void cpu_sleep(void)
  67. {
  68.     asm volatile ("hlt\n");
  69. }
  70.  
  71. #define GEN_READ_REG(reg) static inline unative_t read_ ##reg (void) \
  72.     { \
  73.         unative_t res; \
  74.         asm volatile ( \
  75.             "movl %%" #reg ", %[res]" \
  76.             : [res] "=r" (res) \
  77.         ); \
  78.         return res; \
  79.     }
  80.  
  81. #define GEN_WRITE_REG(reg) static inline void write_ ##reg (unative_t regn) \
  82.     { \
  83.         asm volatile ( \
  84.             "movl %[regn], %%" #reg \
  85.             :: [regn] "r" (regn) \
  86.         ); \
  87.     }
  88.  
  89. GEN_READ_REG(cr0)
  90. GEN_READ_REG(cr2)
  91. GEN_READ_REG(cr3)
  92. GEN_WRITE_REG(cr3)
  93.  
  94. GEN_READ_REG(dr0)
  95. GEN_READ_REG(dr1)
  96. GEN_READ_REG(dr2)
  97. GEN_READ_REG(dr3)
  98. GEN_READ_REG(dr6)
  99. GEN_READ_REG(dr7)
  100.  
  101. GEN_WRITE_REG(dr0)
  102. GEN_WRITE_REG(dr1)
  103. GEN_WRITE_REG(dr2)
  104. GEN_WRITE_REG(dr3)
  105. GEN_WRITE_REG(dr6)
  106. GEN_WRITE_REG(dr7)
  107.  
  108. /** Byte to port
  109.  *
  110.  * Output byte to port
  111.  *
  112.  * @param port Port to write to
  113.  * @param val Value to write
  114.  *
  115.  */
  116. static inline void pio_write_8(ioport8_t *port, uint8_t val)
  117. {
  118.     asm volatile (
  119.         "outb %b[val], %w[port]\n"
  120.         :: [val] "a" (val), [port] "d" (port)
  121.     );
  122. }
  123.  
  124. /** Word to port
  125.  *
  126.  * Output word to port
  127.  *
  128.  * @param port Port to write to
  129.  * @param val Value to write
  130.  *
  131.  */
  132. static inline void pio_write_16(ioport16_t *port, uint16_t val)
  133. {
  134.     asm volatile (
  135.         "outw %w[val], %w[port]\n"
  136.         :: [val] "a" (val), [port] "d" (port)
  137.     );
  138. }
  139.  
  140. /** Double word to port
  141.  *
  142.  * Output double word to port
  143.  *
  144.  * @param port Port to write to
  145.  * @param val Value to write
  146.  *
  147.  */
  148. static inline void pio_write_32(ioport32_t *port, uint32_t val)
  149. {
  150.     asm volatile (
  151.         "outl %[val], %w[port]\n"
  152.         :: [val] "a" (val), [port] "d" (port)
  153.     );
  154. }
  155.  
  156. /** Byte from port
  157.  *
  158.  * Get byte from port
  159.  *
  160.  * @param port Port to read from
  161.  * @return Value read
  162.  *
  163.  */
  164. static inline uint8_t pio_read_8(ioport8_t *port)
  165. {
  166.     uint8_t val;
  167.    
  168.     asm volatile (
  169.         "inb %w[port], %b[val]\n"
  170.         : [val] "=a" (val)
  171.         : [port] "d" (port)
  172.     );
  173.    
  174.     return val;
  175. }
  176.  
  177. /** Word from port
  178.  *
  179.  * Get word from port
  180.  *
  181.  * @param port Port to read from
  182.  * @return Value read
  183.  *
  184.  */
  185. static inline uint16_t pio_read_16(ioport16_t *port)
  186. {
  187.     uint16_t val;
  188.    
  189.     asm volatile (
  190.         "inw %w[port], %w[val]\n"
  191.         : [val] "=a" (val)
  192.         : [port] "d" (port)
  193.     );
  194.    
  195.     return val;
  196. }
  197.  
  198. /** Double word from port
  199.  *
  200.  * Get double word from port
  201.  *
  202.  * @param port Port to read from
  203.  * @return Value read
  204.  *
  205.  */
  206. static inline uint32_t pio_read_32(ioport32_t *port)
  207. {
  208.     uint32_t val;
  209.    
  210.     asm volatile (
  211.         "inl %w[port], %[val]\n"
  212.         : [val] "=a" (val)
  213.         : [port] "d" (port)
  214.     );
  215.    
  216.     return val;
  217. }
  218.  
  219. /** Enable interrupts.
  220.  *
  221.  * Enable interrupts and return previous
  222.  * value of EFLAGS.
  223.  *
  224.  * @return Old interrupt priority level.
  225.  *
  226.  */
  227. static inline ipl_t interrupts_enable(void)
  228. {
  229.     ipl_t v;
  230.    
  231.     asm volatile (
  232.         "pushf\n"
  233.         "popl %[v]\n"
  234.         "sti\n"
  235.         : [v] "=r" (v)
  236.     );
  237.    
  238.     return v;
  239. }
  240.  
  241. /** Disable interrupts.
  242.  *
  243.  * Disable interrupts and return previous
  244.  * value of EFLAGS.
  245.  *
  246.  * @return Old interrupt priority level.
  247.  *
  248.  */
  249. static inline ipl_t interrupts_disable(void)
  250. {
  251.     ipl_t v;
  252.    
  253.     asm volatile (
  254.         "pushf\n"
  255.         "popl %[v]\n"
  256.         "cli\n"
  257.         : [v] "=r" (v)
  258.     );
  259.    
  260.     return v;
  261. }
  262.  
  263. /** Restore interrupt priority level.
  264.  *
  265.  * Restore EFLAGS.
  266.  *
  267.  * @param ipl Saved interrupt priority level.
  268.  *
  269.  */
  270. static inline void interrupts_restore(ipl_t ipl)
  271. {
  272.     asm volatile (
  273.         "pushl %[ipl]\n"
  274.         "popf\n"
  275.         :: [ipl] "r" (ipl)
  276.     );
  277. }
  278.  
  279. /** Return interrupt priority level.
  280.  *
  281.  * @return EFLAFS.
  282.  *
  283.  */
  284. static inline ipl_t interrupts_read(void)
  285. {
  286.     ipl_t v;
  287.    
  288.     asm volatile (
  289.         "pushf\n"
  290.         "popl %[v]\n"
  291.         : [v] "=r" (v)
  292.     );
  293.    
  294.     return v;
  295. }
  296.  
  297. /** Write to MSR */
  298. static inline void write_msr(uint32_t msr, uint64_t value)
  299. {
  300.     asm volatile (
  301.         "wrmsr"
  302.         :: "c" (msr), "a" ((uint32_t) (value)),
  303.            "d" ((uint32_t) (value >> 32))
  304.     );
  305. }
  306.  
  307. static inline uint64_t read_msr(uint32_t msr)
  308. {
  309.     uint32_t ax, dx;
  310.    
  311.     asm volatile (
  312.         "rdmsr"
  313.         : "=a" (ax), "=d" (dx)
  314.         : "c" (msr)
  315.     );
  316.    
  317.     return ((uint64_t) dx << 32) | ax;
  318. }
  319.  
  320.  
  321. /** Return base address of current stack
  322.  *
  323.  * Return the base address of the current stack.
  324.  * The stack is assumed to be STACK_SIZE bytes long.
  325.  * The stack must start on page boundary.
  326.  *
  327.  */
  328. static inline uintptr_t get_stack_base(void)
  329. {
  330.     uintptr_t v;
  331.    
  332.     asm volatile (
  333.         "andl %%esp, %[v]\n"
  334.         : [v] "=r" (v)
  335.         : "0" (~(STACK_SIZE - 1))
  336.     );
  337.    
  338.     return v;
  339. }
  340.  
  341. /** Return current IP address */
  342. static inline uintptr_t * get_ip()
  343. {
  344.     uintptr_t *ip;
  345.    
  346.     asm volatile (
  347.         "mov %%eip, %[ip]"
  348.         : [ip] "=r" (ip)
  349.     );
  350.    
  351.     return ip;
  352. }
  353.  
  354. /** Invalidate TLB Entry.
  355.  *
  356.  * @param addr Address on a page whose TLB entry is to be invalidated.
  357.  *
  358.  */
  359. static inline void invlpg(uintptr_t addr)
  360. {
  361.     asm volatile (
  362.         "invlpg %[addr]\n"
  363.         :: [addr] "m" (*(unative_t *) addr)
  364.     );
  365. }
  366.  
  367. /** Load GDTR register from memory.
  368.  *
  369.  * @param gdtr_reg Address of memory from where to load GDTR.
  370.  *
  371.  */
  372. static inline void gdtr_load(ptr_16_32_t *gdtr_reg)
  373. {
  374.     asm volatile (
  375.         "lgdtl %[gdtr_reg]\n"
  376.         :: [gdtr_reg] "m" (*gdtr_reg)
  377.     );
  378. }
  379.  
  380. /** Store GDTR register to memory.
  381.  *
  382.  * @param gdtr_reg Address of memory to where to load GDTR.
  383.  *
  384.  */
  385. static inline void gdtr_store(ptr_16_32_t *gdtr_reg)
  386. {
  387.     asm volatile (
  388.         "sgdtl %[gdtr_reg]\n"
  389.         :: [gdtr_reg] "m" (*gdtr_reg)
  390.     );
  391. }
  392.  
  393. /** Load IDTR register from memory.
  394.  *
  395.  * @param idtr_reg Address of memory from where to load IDTR.
  396.  *
  397.  */
  398. static inline void idtr_load(ptr_16_32_t *idtr_reg)
  399. {
  400.     asm volatile (
  401.         "lidtl %[idtr_reg]\n"
  402.         :: [idtr_reg] "m" (*idtr_reg)
  403.     );
  404. }
  405.  
  406. /** Load TR from descriptor table.
  407.  *
  408.  * @param sel Selector specifying descriptor of TSS segment.
  409.  *
  410.  */
  411. static inline void tr_load(uint16_t sel)
  412. {
  413.     asm volatile (
  414.         "ltr %[sel]"
  415.         :: [sel] "r" (sel)
  416.     );
  417. }
  418.  
  419. #endif
  420.  
  421. /** @}
  422.  */
  423.