LCOV - code coverage report
Current view: top level - arch/x86/include/asm - io.h (source / functions) Hit Total Coverage
Test: combined.info Lines: 16 24 66.7 %
Date: 2022-04-01 14:58:12 Functions: 0 0 -
Branches: 29 267 10.9 %

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: GPL-2.0 */
       2                 :            : #ifndef _ASM_X86_IO_H
       3                 :            : #define _ASM_X86_IO_H
       4                 :            : 
       5                 :            : /*
       6                 :            :  * This file contains the definitions for the x86 IO instructions
       7                 :            :  * inb/inw/inl/outb/outw/outl and the "string versions" of the same
       8                 :            :  * (insb/insw/insl/outsb/outsw/outsl). You can also use "pausing"
       9                 :            :  * versions of the single-IO instructions (inb_p/inw_p/..).
      10                 :            :  *
      11                 :            :  * This file is not meant to be obfuscating: it's just complicated
      12                 :            :  * to (a) handle it all in a way that makes gcc able to optimize it
      13                 :            :  * as well as possible and (b) trying to avoid writing the same thing
      14                 :            :  * over and over again with slight variations and possibly making a
      15                 :            :  * mistake somewhere.
      16                 :            :  */
      17                 :            : 
      18                 :            : /*
      19                 :            :  * Thanks to James van Artsdalen for a better timing-fix than
      20                 :            :  * the two short jumps: using outb's to a nonexistent port seems
      21                 :            :  * to guarantee better timings even on fast machines.
      22                 :            :  *
      23                 :            :  * On the other hand, I'd like to be sure of a non-existent port:
      24                 :            :  * I feel a bit unsafe about using 0x80 (should be safe, though)
      25                 :            :  *
      26                 :            :  *              Linus
      27                 :            :  */
      28                 :            : 
      29                 :            :  /*
      30                 :            :   *  Bit simplified and optimized by Jan Hubicka
      31                 :            :   *  Support of BIGMEM added by Gerhard Wichert, Siemens AG, July 1999.
      32                 :            :   *
      33                 :            :   *  isa_memset_io, isa_memcpy_fromio, isa_memcpy_toio added,
      34                 :            :   *  isa_read[wl] and isa_write[wl] fixed
      35                 :            :   *  - Arnaldo Carvalho de Melo <acme@conectiva.com.br>
      36                 :            :   */
      37                 :            : 
      38                 :            : #define ARCH_HAS_IOREMAP_WC
      39                 :            : #define ARCH_HAS_IOREMAP_WT
      40                 :            : 
      41                 :            : #include <linux/string.h>
      42                 :            : #include <linux/compiler.h>
      43                 :            : #include <asm/page.h>
      44                 :            : #include <asm/early_ioremap.h>
      45                 :            : #include <asm/pgtable_types.h>
      46                 :            : 
      47                 :            : #define build_mmio_read(name, size, type, reg, barrier) \
      48                 :            : static inline type name(const volatile void __iomem *addr) \
      49                 :            : { type ret; asm volatile("mov" size " %1,%0":reg (ret) \
      50                 :            : :"m" (*(volatile type __force *)addr) barrier); return ret; }
      51                 :            : 
      52                 :            : #define build_mmio_write(name, size, type, reg, barrier) \
      53                 :            : static inline void name(type val, volatile void __iomem *addr) \
      54                 :            : { asm volatile("mov" size " %0,%1": :reg (val), \
      55                 :            : "m" (*(volatile type __force *)addr) barrier); }
      56                 :            : 
      57   [ -  -  #  #  :        522 : build_mmio_read(readb, "b", unsigned char, "=q", :"memory")
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                      # ]
      58   [ -  +  -  +  :         33 : build_mmio_read(readw, "w", unsigned short, "=r", :"memory")
          #  #  #  #  #  
          #  #  #  #  #  
             #  #  #  # ]
      59   [ +  +  -  +  :        568 : build_mmio_read(readl, "l", unsigned int, "=r", :"memory")
          -  +  -  +  -  
          +  -  -  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
      60                 :            : 
      61                 :          0 : build_mmio_read(__readb, "b", unsigned char, "=q", )
      62         [ #  # ]:          0 : build_mmio_read(__readw, "w", unsigned short, "=r", )
      63                 :          0 : build_mmio_read(__readl, "l", unsigned int, "=r", )
      64                 :            : 
      65                 :        843 : build_mmio_write(writeb, "b", unsigned char, "q", :"memory")
      66                 :         30 : build_mmio_write(writew, "w", unsigned short, "r", :"memory")
      67                 :        769 : build_mmio_write(writel, "l", unsigned int, "r", :"memory")
      68                 :            : 
      69                 :          0 : build_mmio_write(__writeb, "b", unsigned char, "q", )
      70                 :          0 : build_mmio_write(__writew, "w", unsigned short, "r", )
      71                 :          0 : build_mmio_write(__writel, "l", unsigned int, "r", )
      72                 :            : 
      73                 :            : #define readb readb
      74                 :            : #define readw readw
      75                 :            : #define readl readl
      76                 :            : #define readb_relaxed(a) __readb(a)
      77                 :            : #define readw_relaxed(a) __readw(a)
      78                 :            : #define readl_relaxed(a) __readl(a)
      79                 :            : #define __raw_readb __readb
      80                 :            : #define __raw_readw __readw
      81                 :            : #define __raw_readl __readl
      82                 :            : 
      83                 :            : #define writeb writeb
      84                 :            : #define writew writew
      85                 :            : #define writel writel
      86                 :            : #define writeb_relaxed(v, a) __writeb(v, a)
      87                 :            : #define writew_relaxed(v, a) __writew(v, a)
      88                 :            : #define writel_relaxed(v, a) __writel(v, a)
      89                 :            : #define __raw_writeb __writeb
      90                 :            : #define __raw_writew __writew
      91                 :            : #define __raw_writel __writel
      92                 :            : 
      93                 :            : #ifdef CONFIG_X86_64
      94                 :            : 
      95   [ -  +  -  +  :       3127 : build_mmio_read(readq, "q", u64, "=r", :"memory")
          -  -  -  -  -  
             -  -  -  -  
                      - ]
      96                 :          0 : build_mmio_read(__readq, "q", u64, "=r", )
      97                 :       3404 : build_mmio_write(writeq, "q", u64, "r", :"memory")
      98                 :          0 : build_mmio_write(__writeq, "q", u64, "r", )
      99                 :            : 
     100                 :            : #define readq_relaxed(a)        __readq(a)
     101                 :            : #define writeq_relaxed(v, a)    __writeq(v, a)
     102                 :            : 
     103                 :            : #define __raw_readq             __readq
     104                 :            : #define __raw_writeq            __writeq
     105                 :            : 
     106                 :            : /* Let people know that we have them */
     107                 :            : #define readq                   readq
     108                 :            : #define writeq                  writeq
     109                 :            : 
     110                 :            : #endif
     111                 :            : 
     112                 :            : #define ARCH_HAS_VALID_PHYS_ADDR_RANGE
     113                 :            : extern int valid_phys_addr_range(phys_addr_t addr, size_t size);
     114                 :            : extern int valid_mmap_phys_addr_range(unsigned long pfn, size_t size);
     115                 :            : 
     116                 :            : /**
     117                 :            :  *      virt_to_phys    -       map virtual addresses to physical
     118                 :            :  *      @address: address to remap
     119                 :            :  *
     120                 :            :  *      The returned physical address is the physical (CPU) mapping for
     121                 :            :  *      the memory address given. It is only valid to use this function on
     122                 :            :  *      addresses directly mapped or allocated via kmalloc.
     123                 :            :  *
     124                 :            :  *      This function does not give bus mappings for DMA transfers. In
     125                 :            :  *      almost all conceivable cases a device driver should not be using
     126                 :            :  *      this function
     127                 :            :  */
     128                 :            : 
     129                 :         57 : static inline phys_addr_t virt_to_phys(volatile void *address)
     130                 :            : {
     131   [ +  -  #  #  :         57 :         return __pa(address);
          #  #  #  #  #  
                #  #  # ]
     132                 :            : }
     133                 :            : #define virt_to_phys virt_to_phys
     134                 :            : 
     135                 :            : /**
     136                 :            :  *      phys_to_virt    -       map physical address to virtual
     137                 :            :  *      @address: address to remap
     138                 :            :  *
     139                 :            :  *      The returned virtual address is a current CPU mapping for
     140                 :            :  *      the memory address given. It is only valid to use this function on
     141                 :            :  *      addresses that have a kernel mapping
     142                 :            :  *
     143                 :            :  *      This function does not handle bus mappings for DMA transfers. In
     144                 :            :  *      almost all conceivable cases a device driver should not be using
     145                 :            :  *      this function
     146                 :            :  */
     147                 :            : 
     148                 :       3768 : static inline void *phys_to_virt(phys_addr_t address)
     149                 :            : {
     150   [ +  +  -  +  :       3765 :         return __va(address);
             #  #  #  # ]
     151                 :            : }
     152                 :            : #define phys_to_virt phys_to_virt
     153                 :            : 
     154                 :            : /*
     155                 :            :  * Change "struct page" to physical address.
     156                 :            :  */
     157                 :            : #define page_to_phys(page)    ((dma_addr_t)page_to_pfn(page) << PAGE_SHIFT)
     158                 :            : 
     159                 :            : /*
     160                 :            :  * ISA I/O bus memory addresses are 1:1 with the physical address.
     161                 :            :  * However, we truncate the address to unsigned int to avoid undesirable
     162                 :            :  * promitions in legacy drivers.
     163                 :            :  */
     164                 :            : static inline unsigned int isa_virt_to_bus(volatile void *address)
     165                 :            : {
     166                 :            :         return (unsigned int)virt_to_phys(address);
     167                 :            : }
     168                 :            : #define isa_bus_to_virt         phys_to_virt
     169                 :            : 
     170                 :            : /*
     171                 :            :  * However PCI ones are not necessarily 1:1 and therefore these interfaces
     172                 :            :  * are forbidden in portable PCI drivers.
     173                 :            :  *
     174                 :            :  * Allow them on x86 for legacy drivers, though.
     175                 :            :  */
     176                 :            : #define virt_to_bus virt_to_phys
     177                 :            : #define bus_to_virt phys_to_virt
     178                 :            : 
     179                 :            : /*
     180                 :            :  * The default ioremap() behavior is non-cached; if you need something
     181                 :            :  * else, you probably want one of the following.
     182                 :            :  */
     183                 :            : extern void __iomem *ioremap_uc(resource_size_t offset, unsigned long size);
     184                 :            : #define ioremap_uc ioremap_uc
     185                 :            : extern void __iomem *ioremap_cache(resource_size_t offset, unsigned long size);
     186                 :            : #define ioremap_cache ioremap_cache
     187                 :            : extern void __iomem *ioremap_prot(resource_size_t offset, unsigned long size, unsigned long prot_val);
     188                 :            : #define ioremap_prot ioremap_prot
     189                 :            : extern void __iomem *ioremap_encrypted(resource_size_t phys_addr, unsigned long size);
     190                 :            : #define ioremap_encrypted ioremap_encrypted
     191                 :            : 
     192                 :            : /**
     193                 :            :  * ioremap     -   map bus memory into CPU space
     194                 :            :  * @offset:    bus address of the memory
     195                 :            :  * @size:      size of the resource to map
     196                 :            :  *
     197                 :            :  * ioremap performs a platform specific sequence of operations to
     198                 :            :  * make bus memory CPU accessible via the readb/readw/readl/writeb/
     199                 :            :  * writew/writel functions and the other mmio helpers. The returned
     200                 :            :  * address is not guaranteed to be usable directly as a virtual
     201                 :            :  * address.
     202                 :            :  *
     203                 :            :  * If the area you are trying to map is a PCI BAR you should have a
     204                 :            :  * look at pci_iomap().
     205                 :            :  */
     206                 :            : void __iomem *ioremap(resource_size_t offset, unsigned long size);
     207                 :            : #define ioremap ioremap
     208                 :            : 
     209                 :            : extern void iounmap(volatile void __iomem *addr);
     210                 :            : #define iounmap iounmap
     211                 :            : 
     212                 :            : extern void set_iounmap_nonlazy(void);
     213                 :            : 
     214                 :            : #ifdef __KERNEL__
     215                 :            : 
     216                 :            : void memcpy_fromio(void *, const volatile void __iomem *, size_t);
     217                 :            : void memcpy_toio(volatile void __iomem *, const void *, size_t);
     218                 :            : void memset_io(volatile void __iomem *, int, size_t);
     219                 :            : 
     220                 :            : #define memcpy_fromio memcpy_fromio
     221                 :            : #define memcpy_toio memcpy_toio
     222                 :            : #define memset_io memset_io
     223                 :            : 
     224                 :            : #include <asm-generic/iomap.h>
     225                 :            : 
     226                 :            : /*
     227                 :            :  * ISA space is 'always mapped' on a typical x86 system, no need to
     228                 :            :  * explicitly ioremap() it. The fact that the ISA IO space is mapped
     229                 :            :  * to PAGE_OFFSET is pure coincidence - it does not mean ISA values
     230                 :            :  * are physical addresses. The following constant pointer can be
     231                 :            :  * used as the IO-area pointer (it can be iounmapped as well, so the
     232                 :            :  * analogy with PCI is quite large):
     233                 :            :  */
     234                 :            : #define __ISA_IO_base ((char __iomem *)(PAGE_OFFSET))
     235                 :            : 
     236                 :            : #endif /* __KERNEL__ */
     237                 :            : 
     238                 :            : extern void native_io_delay(void);
     239                 :            : 
     240                 :            : extern int io_delay_type;
     241                 :            : extern void io_delay_init(void);
     242                 :            : 
     243                 :            : #if defined(CONFIG_PARAVIRT)
     244                 :            : #include <asm/paravirt.h>
     245                 :            : #else
     246                 :            : 
     247                 :            : static inline void slow_down_io(void)
     248                 :            : {
     249                 :            :         native_io_delay();
     250                 :            : #ifdef REALLY_SLOW_IO
     251                 :            :         native_io_delay();
     252                 :            :         native_io_delay();
     253                 :            :         native_io_delay();
     254                 :            : #endif
     255                 :            : }
     256                 :            : 
     257                 :            : #endif
     258                 :            : 
     259                 :            : #ifdef CONFIG_AMD_MEM_ENCRYPT
     260                 :            : #include <linux/jump_label.h>
     261                 :            : 
     262                 :            : extern struct static_key_false sev_enable_key;
     263                 :            : static inline bool sev_key_active(void)
     264                 :            : {
     265                 :            :         return static_branch_unlikely(&sev_enable_key);
     266                 :            : }
     267                 :            : 
     268                 :            : #else /* !CONFIG_AMD_MEM_ENCRYPT */
     269                 :            : 
     270                 :        254 : static inline bool sev_key_active(void) { return false; }
     271                 :            : 
     272                 :            : #endif /* CONFIG_AMD_MEM_ENCRYPT */
     273                 :            : 
     274                 :            : #define BUILDIO(bwl, bw, type)                                          \
     275                 :            : static inline void out##bwl(unsigned type value, int port)              \
     276                 :            : {                                                                       \
     277                 :            :         asm volatile("out" #bwl " %" #bw "0, %w1"                 \
     278                 :            :                      : : "a"(value), "Nd"(port));                   \
     279                 :            : }                                                                       \
     280                 :            :                                                                         \
     281                 :            : static inline unsigned type in##bwl(int port)                           \
     282                 :            : {                                                                       \
     283                 :            :         unsigned type value;                                            \
     284                 :            :         asm volatile("in" #bwl " %w1, %" #bw "0"                  \
     285                 :            :                      : "=a"(value) : "Nd"(port));                   \
     286                 :            :         return value;                                                   \
     287                 :            : }                                                                       \
     288                 :            :                                                                         \
     289                 :            : static inline void out##bwl##_p(unsigned type value, int port)          \
     290                 :            : {                                                                       \
     291                 :            :         out##bwl(value, port);                                          \
     292                 :            :         slow_down_io();                                                 \
     293                 :            : }                                                                       \
     294                 :            :                                                                         \
     295                 :            : static inline unsigned type in##bwl##_p(int port)                       \
     296                 :            : {                                                                       \
     297                 :            :         unsigned type value = in##bwl(port);                            \
     298                 :            :         slow_down_io();                                                 \
     299                 :            :         return value;                                                   \
     300                 :            : }                                                                       \
     301                 :            :                                                                         \
     302                 :            : static inline void outs##bwl(int port, const void *addr, unsigned long count) \
     303                 :            : {                                                                       \
     304                 :            :         if (sev_key_active()) {                                         \
     305                 :            :                 unsigned type *value = (unsigned type *)addr;           \
     306                 :            :                 while (count) {                                         \
     307                 :            :                         out##bwl(*value, port);                         \
     308                 :            :                         value++;                                        \
     309                 :            :                         count--;                                        \
     310                 :            :                 }                                                       \
     311                 :            :         } else {                                                        \
     312                 :            :                 asm volatile("rep; outs" #bwl                         \
     313                 :            :                              : "+S"(addr), "+c"(count)                      \
     314                 :            :                              : "d"(port) : "memory");                       \
     315                 :            :         }                                                               \
     316                 :            : }                                                                       \
     317                 :            :                                                                         \
     318                 :            : static inline void ins##bwl(int port, void *addr, unsigned long count)  \
     319                 :            : {                                                                       \
     320                 :            :         if (sev_key_active()) {                                         \
     321                 :            :                 unsigned type *value = (unsigned type *)addr;           \
     322                 :            :                 while (count) {                                         \
     323                 :            :                         *value = in##bwl(port);                         \
     324                 :            :                         value++;                                        \
     325                 :            :                         count--;                                        \
     326                 :            :                 }                                                       \
     327                 :            :         } else {                                                        \
     328                 :            :                 asm volatile("rep; ins" #bwl                          \
     329                 :            :                              : "+D"(addr), "+c"(count)                      \
     330                 :            :                              : "d"(port) : "memory");                       \
     331                 :            :         }                                                               \
     332                 :            : }
     333                 :            : 
     334   [ +  +  -  -  :     293353 : BUILDIO(b, b, char)
          -  +  +  -  -  
          +  +  +  -  +  
          -  +  -  +  -  
          -  -  +  -  +  
                   -  + ]
     335   [ #  #  #  #  :       1229 : BUILDIO(w, w, short)
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                #  #  # ]
     336   [ +  +  #  # ]:       7144 : BUILDIO(l, , int)
     337                 :            : 
     338                 :            : #define inb inb
     339                 :            : #define inw inw
     340                 :            : #define inl inl
     341                 :            : #define inb_p inb_p
     342                 :            : #define inw_p inw_p
     343                 :            : #define inl_p inl_p
     344                 :            : #define insb insb
     345                 :            : #define insw insw
     346                 :            : #define insl insl
     347                 :            : 
     348                 :            : #define outb outb
     349                 :            : #define outw outw
     350                 :            : #define outl outl
     351                 :            : #define outb_p outb_p
     352                 :            : #define outw_p outw_p
     353                 :            : #define outl_p outl_p
     354                 :            : #define outsb outsb
     355                 :            : #define outsw outsw
     356                 :            : #define outsl outsl
     357                 :            : 
     358                 :            : extern void *xlate_dev_mem_ptr(phys_addr_t phys);
     359                 :            : extern void unxlate_dev_mem_ptr(phys_addr_t phys, void *addr);
     360                 :            : 
     361                 :            : #define xlate_dev_mem_ptr xlate_dev_mem_ptr
     362                 :            : #define unxlate_dev_mem_ptr unxlate_dev_mem_ptr
     363                 :            : 
     364                 :            : extern int ioremap_change_attr(unsigned long vaddr, unsigned long size,
     365                 :            :                                 enum page_cache_mode pcm);
     366                 :            : extern void __iomem *ioremap_wc(resource_size_t offset, unsigned long size);
     367                 :            : #define ioremap_wc ioremap_wc
     368                 :            : extern void __iomem *ioremap_wt(resource_size_t offset, unsigned long size);
     369                 :            : #define ioremap_wt ioremap_wt
     370                 :            : 
     371                 :            : extern bool is_early_ioremap_ptep(pte_t *ptep);
     372                 :            : 
     373                 :            : #define IO_SPACE_LIMIT 0xffff
     374                 :            : 
     375                 :            : #include <asm-generic/io.h>
     376                 :            : #undef PCI_IOBASE
     377                 :            : 
     378                 :            : #ifdef CONFIG_MTRR
     379                 :            : extern int __must_check arch_phys_wc_index(int handle);
     380                 :            : #define arch_phys_wc_index arch_phys_wc_index
     381                 :            : 
     382                 :            : extern int __must_check arch_phys_wc_add(unsigned long base,
     383                 :            :                                          unsigned long size);
     384                 :            : extern void arch_phys_wc_del(int handle);
     385                 :            : #define arch_phys_wc_add arch_phys_wc_add
     386                 :            : #endif
     387                 :            : 
     388                 :            : #ifdef CONFIG_X86_PAT
     389                 :            : extern int arch_io_reserve_memtype_wc(resource_size_t start, resource_size_t size);
     390                 :            : extern void arch_io_free_memtype_wc(resource_size_t start, resource_size_t size);
     391                 :            : #define arch_io_reserve_memtype_wc arch_io_reserve_memtype_wc
     392                 :            : #endif
     393                 :            : 
     394                 :            : extern bool arch_memremap_can_ram_remap(resource_size_t offset,
     395                 :            :                                         unsigned long size,
     396                 :            :                                         unsigned long flags);
     397                 :            : #define arch_memremap_can_ram_remap arch_memremap_can_ram_remap
     398                 :            : 
     399                 :            : extern bool phys_mem_access_encrypted(unsigned long phys_addr,
     400                 :            :                                       unsigned long size);
     401                 :            : 
     402                 :            : /**
     403                 :            :  * iosubmit_cmds512 - copy data to single MMIO location, in 512-bit units
     404                 :            :  * @__dst: destination, in MMIO space (must be 512-bit aligned)
     405                 :            :  * @src: source
     406                 :            :  * @count: number of 512 bits quantities to submit
     407                 :            :  *
     408                 :            :  * Submit data from kernel space to MMIO space, in units of 512 bits at a
     409                 :            :  * time.  Order of access is not guaranteed, nor is a memory barrier
     410                 :            :  * performed afterwards.
     411                 :            :  *
     412                 :            :  * Warning: Do not use this helper unless your driver has checked that the CPU
     413                 :            :  * instruction is supported on the platform.
     414                 :            :  */
     415                 :            : static inline void iosubmit_cmds512(void __iomem *__dst, const void *src,
     416                 :            :                                     size_t count)
     417                 :            : {
     418                 :            :         /*
     419                 :            :          * Note that this isn't an "on-stack copy", just definition of "dst"
     420                 :            :          * as a pointer to 64-bytes of stuff that is going to be overwritten.
     421                 :            :          * In the MOVDIR64B case that may be needed as you can use the
     422                 :            :          * MOVDIR64B instruction to copy arbitrary memory around. This trick
     423                 :            :          * lets the compiler know how much gets clobbered.
     424                 :            :          */
     425                 :            :         volatile struct { char _[64]; } *dst = __dst;
     426                 :            :         const u8 *from = src;
     427                 :            :         const u8 *end = from + count * 64;
     428                 :            : 
     429                 :            :         while (from < end) {
     430                 :            :                 /* MOVDIR64B [rdx], rax */
     431                 :            :                 asm volatile(".byte 0x66, 0x0f, 0x38, 0xf8, 0x02"
     432                 :            :                              : "=m" (dst)
     433                 :            :                              : "d" (from), "a" (dst));
     434                 :            :                 from += 64;
     435                 :            :         }
     436                 :            : }
     437                 :            : 
     438                 :            : #endif /* _ASM_X86_IO_H */

Generated by: LCOV version 1.14