1 | /*************************************************************************** |
---|
2 | * |
---|
3 | * Copyright (C) 2001 International Business Machines |
---|
4 | * All rights reserved. |
---|
5 | * |
---|
6 | * This file is part of the GPFS mmfslinux kernel module. |
---|
7 | * |
---|
8 | * Redistribution and use in source and binary forms, with or without |
---|
9 | * modification, are permitted provided that the following conditions |
---|
10 | * are met: |
---|
11 | * |
---|
12 | * 1. Redistributions of source code must retain the above copyright notice, |
---|
13 | * this list of conditions and the following disclaimer. |
---|
14 | * 2. Redistributions in binary form must reproduce the above copyright |
---|
15 | * notice, this list of conditions and the following disclaimer in the |
---|
16 | * documentation and/or other materials provided with the distribution. |
---|
17 | * 3. The name of the author may not be used to endorse or promote products |
---|
18 | * derived from this software without specific prior written |
---|
19 | * permission. |
---|
20 | * |
---|
21 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
---|
22 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
---|
23 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
---|
24 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
---|
25 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
---|
26 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; |
---|
27 | * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, |
---|
28 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR |
---|
29 | * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF |
---|
30 | * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
---|
31 | * |
---|
32 | *************************************************************************** */ |
---|
33 | /* @(#)13 1.45.1.2 src/avs/fs/mmfs/ts/kernext/ibm-linux/cxiIOBuffer-plat.h, mmfs, avs_rgpfs24, rgpfs24s007a 10/25/06 17:16:36 */ |
---|
34 | /* |
---|
35 | * Abstraction of an I/O buffer, Linux implementation |
---|
36 | * |
---|
37 | * Contents: |
---|
38 | * struct cxiKernelIOBufferDesc_t |
---|
39 | * struct cxiIOBufferAttachment_t |
---|
40 | * InitBufferAttachment |
---|
41 | * struct cxiContiguousBuffer_t |
---|
42 | * InitContiguousBuffer |
---|
43 | * EXTERNC int kxPinKernelIOBuffer |
---|
44 | * Methods for manipulating cxiIOBuffer_t's |
---|
45 | * #define __CXI_BUFFERS_ARE_CONTIGUOUS |
---|
46 | * GetDiskInfoX |
---|
47 | */ |
---|
48 | |
---|
49 | #ifndef _h_cxiIOBuffer_plat |
---|
50 | #define _h_cxiIOBuffer_plat |
---|
51 | |
---|
52 | #ifndef _h_cxiIOBuffer |
---|
53 | #error Platform header (XXX-plat.h) should not be included directly |
---|
54 | #endif |
---|
55 | |
---|
56 | /* Address of the first byte past the end of memory addressible by |
---|
57 | processes (PAGE_OFFSET), and routine to get this value from the kernel. |
---|
58 | Stacks are below this address. */ |
---|
59 | EXTERNC UIntPtr KernelBoundary; |
---|
60 | EXTERNC int kxGetKernelBoundary(UIntPtr* kBoundP); |
---|
61 | |
---|
62 | /* forward declarations */ |
---|
63 | struct page; |
---|
64 | |
---|
65 | /* User address space range used for page pool. */ |
---|
66 | #ifdef GPFS_ARCH_I386 |
---|
67 | #define LINUX_PAGE_POOL_BASE 0x44000000 |
---|
68 | #endif |
---|
69 | #ifdef GPFS_ARCH_POWER |
---|
70 | #define LINUX_PAGE_POOL_BASE 0x54000000 |
---|
71 | #endif |
---|
72 | #ifdef GPFS_ARCH_IA64 |
---|
73 | /* Use shared memory region after TM pool */ |
---|
74 | /* TM pool address + 4GB */ |
---|
75 | #define LINUX_PAGE_POOL_BASE 0x6000010100000000 |
---|
76 | #endif |
---|
77 | #ifdef GPFS_ARCH_PPC64 |
---|
78 | /* TM pool address + 2GB */ |
---|
79 | #define LINUX_PAGE_POOL_BASE 0x0000002080000000UL |
---|
80 | #endif |
---|
81 | #ifdef GPFS_ARCH_X86_64 |
---|
82 | /* TM pool address + 4GB */ |
---|
83 | #define LINUX_PAGE_POOL_BASE 0x0000005100000000UL |
---|
84 | #endif |
---|
85 | |
---|
86 | |
---|
87 | #define POOL_MMAP_CHUNK_SIZE 0x04000000 |
---|
88 | |
---|
89 | /* Address where token manager malloc pool begins */ |
---|
90 | #ifdef GPFS_ARCH_I386 |
---|
91 | # define TM_POOL_START 0x30000000 |
---|
92 | #endif |
---|
93 | #ifdef GPFS_ARCH_POWER |
---|
94 | # define TM_POOL_START 0x40000000 |
---|
95 | #endif |
---|
96 | #ifdef GPFS_ARCH_IA64 |
---|
97 | # define TM_POOL_START 0x6000010000000000 |
---|
98 | #endif |
---|
99 | #ifdef GPFS_ARCH_PPC64 |
---|
100 | /* this is the top portion of the brk area. We count on the |
---|
101 | daemon never growing big enough to get here. There's only |
---|
102 | 2TB of address space available in userspace on ppc64, so a |
---|
103 | completely safe spot is hard to find */ |
---|
104 | # define TM_POOL_START 0x0000002000000000UL |
---|
105 | #endif |
---|
106 | #ifdef GPFS_ARCH_X86_64 |
---|
107 | # define TM_POOL_START 0x0000005000000000UL |
---|
108 | #endif |
---|
109 | |
---|
110 | /* Buffers in user address space must be aligned to a boundary of this size |
---|
111 | in order to perform an I/O request. */ |
---|
112 | #define IOBUF_ALIGN_SIZE 512 |
---|
113 | |
---|
114 | /* Kernel data structure associated with an I/O buffer. I/O buffers that |
---|
115 | are pinned (or attached) point to one of these structures from their |
---|
116 | kernelIOBufferDescP field. It describes the physical pages occupied by |
---|
117 | the I/O buffer using Linux kiobufs. These are linked together in a |
---|
118 | global list anchored in the kernel so that pinned storage can be released |
---|
119 | when the GPFS daemon terminates abnormally. Each I/O buffer has one |
---|
120 | cxiKernelIOBufferDesc_t on this global list. However, since one |
---|
121 | cxiKernelIOBufferDesc_t can map at most PAGES_PER_KIBD pages, large I/O |
---|
122 | buffers require multiple cxiKernelIOBufferDesc_t's. */ |
---|
123 | struct cxiKernelIOBufferDesc_t |
---|
124 | { |
---|
125 | /* Daemon address for beginning of I/O buffer. This address must be |
---|
126 | aligned on a page boundary. */ |
---|
127 | char* kibdVaddr; |
---|
128 | |
---|
129 | /* Number of pages described by this cxiKernelIOBufferDesc_t. */ |
---|
130 | int kibdPages; |
---|
131 | |
---|
132 | /* Number of pages described by this chain of cxiKernelIOBufferDesc_t |
---|
133 | * Only valid for the first cxiKernelIOBufferDesc_t in the chain. |
---|
134 | */ |
---|
135 | int kibdTotalPages; |
---|
136 | |
---|
137 | /* List pointer. Used for a chain of cxiKernelIOBufferDesc_t's. */ |
---|
138 | struct cxiKernelIOBufferDesc_t* kibdNextP; |
---|
139 | |
---|
140 | /* An I/O buffer is described by a chain of cxiKernelIOBufferDesc_t, |
---|
141 | * of which the head descriptor is placed on a global list. Thus these |
---|
142 | * fields are only valid for the first cxiKernelIOBufferDesc_t in the |
---|
143 | * chain of descriptors. |
---|
144 | */ |
---|
145 | struct cxiKernelIOBufferDesc_t* gblNextP; |
---|
146 | struct cxiKernelIOBufferDesc_t* gblPrevP; |
---|
147 | |
---|
148 | #define PAGES_PER_KIBD (64*1024/PAGE_SIZE) /* 64K */ |
---|
149 | char* maplist[PAGES_PER_KIBD]; |
---|
150 | }; |
---|
151 | |
---|
152 | /* Struct that records the mapping within |
---|
153 | * the daemon address space. A group of these are allocated |
---|
154 | * as an array in the shared seg and the memory descriptor |
---|
155 | * vindex points to the appropriate element. |
---|
156 | */ |
---|
157 | struct cxiMemoryMapping_t |
---|
158 | { |
---|
159 | char *vaddr; /* daemon address mapping */ |
---|
160 | #ifdef SSEG_SWIZZLE_PTRS |
---|
161 | char *kvaddr; |
---|
162 | #endif |
---|
163 | int kBytes; /* size of the area in kilobytes */ |
---|
164 | short vindex; /* index in shared segment mapping array */ |
---|
165 | }; |
---|
166 | |
---|
167 | static inline void |
---|
168 | InitMemoryMapping(struct cxiMemoryMapping_t *mmP) |
---|
169 | { |
---|
170 | mmP->vaddr = NULL; |
---|
171 | mmP->kBytes = 0; |
---|
172 | mmP->vindex = -1; |
---|
173 | #ifdef SSEG_SWIZZLE_PTRS |
---|
174 | mmP->kvaddr = NULL; |
---|
175 | #endif |
---|
176 | } |
---|
177 | |
---|
178 | static inline Boolean |
---|
179 | IsMemoryMappingFree(struct cxiMemoryMapping_t *mmP) |
---|
180 | { |
---|
181 | if (mmP->kBytes == 0) |
---|
182 | return true; |
---|
183 | |
---|
184 | return false; |
---|
185 | } |
---|
186 | |
---|
187 | typedef struct cxiMemoryMapping_t cxiMemoryMapping_t; |
---|
188 | |
---|
189 | /* Initialization and termination routines. Called at module load |
---|
190 | and unload, respectively. */ |
---|
191 | EXTERNC void KibdModuleInit(); |
---|
192 | EXTERNC void KibdModuleTerm(); |
---|
193 | |
---|
194 | /* Create a cxiKernelIOBufferDesc_t object (or list of cxiKernelIOBufferDesc_t |
---|
195 | objects) describing an I/O buffer in the user address space of the |
---|
196 | calling process and link it onto the list of all such objects. Pins |
---|
197 | the user-level buffer. The buffer virtual address must be on a page |
---|
198 | boundary. The length can be arbitrarily large, but must be a multiple |
---|
199 | of the page size. Returns 0 if successful, non-zero if unsuccessful. |
---|
200 | */ |
---|
201 | EXTERNC int cxiKibdPin(char* vaddr, int len, |
---|
202 | struct cxiKernelIOBufferDesc_t** kibdPP); |
---|
203 | |
---|
204 | /* Remove a cxiKernelIOBufferDesc_t object from the list of all |
---|
205 | such objects, destroy it and all chained cxiKernelIOBufferDesc_t objects |
---|
206 | associated with it, and unpin the associated user-level buffer. */ |
---|
207 | EXTERNC void cxiKibdUnpin(struct cxiKernelIOBufferDesc_t* kibdP); |
---|
208 | |
---|
209 | /* Free all cxiKernelIOBufferDesc_t's, and unpin their underlying storage. */ |
---|
210 | EXTERNC void cxiKibdUnpinAll(); |
---|
211 | |
---|
212 | #ifdef MMAP_DIO |
---|
213 | |
---|
214 | /* Create a cxiKernelIOBufferDesc_t object for a page in user address space |
---|
215 | that is already pinned. The page will be mapped into kernel address |
---|
216 | space. This is used by mmap routines that want to do direct I/O from |
---|
217 | user page to disk. The cxiKernelIOBufferDesc_t that this routine |
---|
218 | creates can be passed to cxiKDoIO just like one that was created by |
---|
219 | cxiKibdPin. */ |
---|
220 | EXTERNC int cxiKibdPinmm(struct page *pageP, |
---|
221 | struct cxiKernelIOBufferDesc_t** kibdPP); |
---|
222 | |
---|
223 | /* Free a cxiKernelIOBufferDesc_t that was created by cxiKibdPinmm. */ |
---|
224 | EXTERNC void cxiKibdUnpinmm(struct page *pageP, |
---|
225 | struct cxiKernelIOBufferDesc_t* kibdP); |
---|
226 | #endif /* MMAP_DIO */ |
---|
227 | |
---|
228 | |
---|
229 | /* Handle that describes a particular cxiIOBuffer_t that has been attached. |
---|
230 | On Linux, this is a pointer to a cxiLinuxKernelIOBufferDesc_t. */ |
---|
231 | struct cxiIOBufferAttachment_t |
---|
232 | { |
---|
233 | struct cxiKernelIOBufferDesc_t* kDescP; |
---|
234 | }; |
---|
235 | |
---|
236 | |
---|
237 | /* Initialize a cxiIOBufferAttachment_t */ |
---|
238 | static inline void InitBufferAttachment(struct cxiIOBufferAttachment_t* baP) |
---|
239 | { |
---|
240 | baP->kDescP = NULL; |
---|
241 | }; |
---|
242 | |
---|
243 | |
---|
244 | |
---|
245 | /* Result of making a read-only copy of a portion of an I/O buffer. On |
---|
246 | Linux, this must record the base address of the copy buffer, if one was |
---|
247 | required. If data was mapped in place, the cxiContiguousBuffer_t records |
---|
248 | which page was kmapped. */ |
---|
249 | struct cxiContiguousBuffer_t |
---|
250 | { |
---|
251 | /* Base of storage allocated with vmalloc / kmalloc, or NULL if data is |
---|
252 | referenced in place. */ |
---|
253 | char* mallocedBaseP; |
---|
254 | |
---|
255 | /* True if storage pointed to be mallocedBaseP was allocated using |
---|
256 | kmalloc. If false, then vmalloc was used. */ |
---|
257 | Boolean usedKmalloc; |
---|
258 | |
---|
259 | /* Pointer used to remember which page to unmap, or NULL if data was copied |
---|
260 | to mallocedBaseP by mapContiguousRO. */ |
---|
261 | void* pageP; |
---|
262 | }; |
---|
263 | |
---|
264 | |
---|
265 | /* Initialize a cxiContiguousBuffer_t */ |
---|
266 | static inline void InitContiguousBuffer(struct cxiContiguousBuffer_t* cbP) |
---|
267 | { |
---|
268 | cbP->mallocedBaseP = NULL; |
---|
269 | cbP->usedKmalloc = false; |
---|
270 | cbP->pageP = NULL; |
---|
271 | } |
---|
272 | |
---|
273 | |
---|
274 | /* Kernel calls used by cxiK... routines to call the Kibd... routines */ |
---|
275 | EXTERNC int kxPinKernelIOBuffer(char* vaddr, int len, |
---|
276 | struct cxiKernelIOBufferDesc_t** pinnedPP); |
---|
277 | EXTERNC int kxUnpinKernelIOBuffer(struct cxiKernelIOBufferDesc_t* pinnedP); |
---|
278 | EXTERNC int kxUnpinAllKernelIOBuffers(); |
---|
279 | |
---|
280 | /* Methods for manipulating cxiIOBuffer_t's */ |
---|
281 | |
---|
282 | /* Return true if the fields describing the IOBuffer are self-consistent */ |
---|
283 | #define IOBUFFER_IS_CONSISTENT(IOBP) (true) |
---|
284 | |
---|
285 | /* Pin the pages belonging to this I/O buffer */ |
---|
286 | EXTERNC void KPinIOBuffer(struct cxiIOBuffer_t* iobP); |
---|
287 | |
---|
288 | /* Unpin the pages belonging to this I/O buffer */ |
---|
289 | EXTERNC void KUnpinIOBuffer(struct cxiIOBuffer_t* iobP); |
---|
290 | |
---|
291 | /* Split the kernel buffer descriptor into two adjacent I/O buffers */ |
---|
292 | EXTERNC void KSplitIOBuffer(struct cxiIOBuffer_t* iobP, int frontPages, |
---|
293 | struct cxiIOBuffer_t* rearBufP); |
---|
294 | |
---|
295 | /* Merge the kernel buffer descriptors of two adjacent I/O buffers. The |
---|
296 | I/O buffer p should be destroyed after this call, since its pages will |
---|
297 | be merged into the buffer *iobP. */ |
---|
298 | EXTERNC void KMergeIOBuffer(struct cxiIOBuffer_t* iobP, struct cxiIOBuffer_t* p); |
---|
299 | |
---|
300 | /* Read or write the given sectors from dev. Data should be placed into |
---|
301 | the I/O buffer beginning at byte offset bufOffset. Returns EOK |
---|
302 | on success, negative values on error. All of the data to be |
---|
303 | transferred will be in the first cxiKernelIOBufferDesc_t. */ |
---|
304 | EXTERNC int cxiKDoIO(struct cxiKernelIOBufferDesc_t* kibdP, |
---|
305 | Boolean isWrite, cxiDev_t dev, UInt64 startSector, |
---|
306 | int nSectors, int sectorSize, int bufOffset); |
---|
307 | |
---|
308 | |
---|
309 | /* On Linux, I/O buffers can be accessed at contiguous virtual addresses |
---|
310 | from the daemon process, but not from kernel code */ |
---|
311 | #ifndef _KERNEL |
---|
312 | #define __CXI_BUFFERS_ARE_CONTIGUOUS |
---|
313 | #endif |
---|
314 | |
---|
315 | /* Routine to set up the disk block size and get disk parameters */ |
---|
316 | EXTERNC int GetDiskInfoX(cxiDev_t devId, struct cxiDiskInfo_t* diskInfoP); |
---|
317 | |
---|
318 | #endif /* _h_cxiIOBuffer_plat */ |
---|
319 | |
---|