cachemap.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:4k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*
  2.  * BK Id: %F% %I% %G% %U% %#%
  3.  *
  4.  *  PowerPC version derived from arch/arm/mm/consistent.c
  5.  *    Copyright (C) 2001 Dan Malek (dmalek@jlc.net)
  6.  *
  7.  *  linux/arch/arm/mm/consistent.c
  8.  *
  9.  *  Copyright (C) 2000 Russell King
  10.  *
  11.  * Consistent memory allocators.  Used for DMA devices that want to
  12.  * share uncached memory with the processor core.  The function return
  13.  * is the virtual address and 'dma_handle' is the physical address.
  14.  * Mostly stolen from the ARM port, with some changes for PowerPC.
  15.  * -- Dan
  16.  *
  17.  * This program is free software; you can redistribute it and/or modify
  18.  * it under the terms of the GNU General Public License version 2 as
  19.  * published by the Free Software Foundation.
  20.  */
  21. #include <linux/config.h>
  22. #include <linux/module.h>
  23. #include <linux/signal.h>
  24. #include <linux/sched.h>
  25. #include <linux/kernel.h>
  26. #include <linux/errno.h>
  27. #include <linux/string.h>
  28. #include <linux/types.h>
  29. #include <linux/ptrace.h>
  30. #include <linux/mman.h>
  31. #include <linux/mm.h>
  32. #include <linux/swap.h>
  33. #include <linux/stddef.h>
  34. #include <linux/vmalloc.h>
  35. #include <linux/init.h>
  36. #include <linux/delay.h>
  37. #include <linux/bootmem.h>
  38. #include <linux/highmem.h>
  39. #include <linux/pci.h>
  40. #include <asm/pgalloc.h>
  41. #include <asm/prom.h>
  42. #include <asm/io.h>
  43. #include <asm/hardirq.h>
  44. #include <asm/mmu_context.h>
  45. #include <asm/pgtable.h>
  46. #include <asm/mmu.h>
  47. #include <asm/uaccess.h>
  48. #include <asm/smp.h>
  49. #include <asm/machdep.h>
  50. extern int get_pteptr(struct mm_struct *mm, unsigned long addr, pte_t **ptep);
  51. void *consistent_alloc(int gfp, size_t size, dma_addr_t *dma_handle)
  52. {
  53. int order, rsize;
  54. unsigned long page;
  55. void *ret;
  56. pte_t *pte;
  57. if (in_interrupt())
  58. BUG();
  59. /* Only allocate page size areas.
  60. */
  61. size = PAGE_ALIGN(size);
  62. order = get_order(size);
  63. page = __get_free_pages(gfp, order);
  64. if (!page) {
  65. BUG();
  66. return NULL;
  67. }
  68. /*
  69.  * we need to ensure that there are no cachelines in use,
  70.  * or worse dirty in this area.
  71.  */
  72. invalidate_dcache_range(page, page + size);
  73. ret = (void *)page;
  74. *dma_handle = virt_to_bus(ret);
  75. /* Chase down all of the PTEs and mark them uncached.
  76. */
  77. rsize = (int)size;
  78. while (rsize > 0) {
  79. if (get_pteptr(&init_mm, page, &pte)) {
  80. pte_val(*pte) |= _PAGE_NO_CACHE | _PAGE_GUARDED;
  81. flush_tlb_page(find_vma(&init_mm,page),page);
  82. }
  83. else {
  84. BUG();
  85. return NULL;
  86. }
  87. page += PAGE_SIZE;
  88. rsize -= PAGE_SIZE;
  89. }
  90. return ret;
  91. }
  92. /*
  93.  * free page(s) as defined by the above mapping.
  94.  * The caller has to tell us the size so we can free the proper number
  95.  * of pages.  We can't vmalloc() a new space for these pages and simply
  96.  * call vfree() like some other architectures because we could end up
  97.  * with aliased cache lines (or at least a cache line with the wrong
  98.  * attributes).  This can happen when the PowerPC speculative loads
  99.  * across page boundaries.
  100.  */
  101. void consistent_free(void *vaddr, size_t size)
  102. {
  103. int order, rsize;
  104. unsigned long addr;
  105. pte_t *pte;
  106. if (in_interrupt())
  107. BUG();
  108. size = PAGE_ALIGN(size);
  109. order = get_order(size);
  110. /* Chase down all of the PTEs and mark them cached again.
  111. */
  112. addr = (unsigned long)vaddr;
  113. rsize = (int)size;
  114. while (rsize > 0) {
  115. if (get_pteptr(&init_mm, addr, &pte)) {
  116. pte_val(*pte) &= ~(_PAGE_NO_CACHE | _PAGE_GUARDED);
  117. flush_tlb_page(find_vma(&init_mm,addr),addr);
  118. }
  119. else {
  120. BUG();
  121. return;
  122. }
  123. addr += PAGE_SIZE;
  124. rsize -= PAGE_SIZE;
  125. }
  126. free_pages((unsigned long)vaddr, order);
  127. }
  128. /*
  129.  * make an area consistent.
  130.  */
  131. void consistent_sync(void *vaddr, size_t size, int direction)
  132. {
  133. unsigned long start = (unsigned long)vaddr;
  134. unsigned long end   = start + size;
  135. switch (direction) {
  136. case PCI_DMA_NONE:
  137. BUG();
  138. case PCI_DMA_FROMDEVICE: /* invalidate only */
  139. invalidate_dcache_range(start, end);
  140. break;
  141. case PCI_DMA_TODEVICE: /* writeback only */
  142. clean_dcache_range(start, end);
  143. break;
  144. case PCI_DMA_BIDIRECTIONAL: /* writeback and invalidate */
  145. flush_dcache_range(start, end);
  146. break;
  147. }
  148. }