Commit | Line | Data |
---|---|---|
920dae64 AT |
1 | \ ========== Copyright Header Begin ========================================== |
2 | \ | |
3 | \ Hypervisor Software File: methods.fth | |
4 | \ | |
5 | \ Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. | |
6 | \ | |
7 | \ - Do no alter or remove copyright notices | |
8 | \ | |
9 | \ - Redistribution and use of this software in source and binary forms, with | |
10 | \ or without modification, are permitted provided that the following | |
11 | \ conditions are met: | |
12 | \ | |
13 | \ - Redistribution of source code must retain the above copyright notice, | |
14 | \ this list of conditions and the following disclaimer. | |
15 | \ | |
16 | \ - Redistribution in binary form must reproduce the above copyright notice, | |
17 | \ this list of conditions and the following disclaimer in the | |
18 | \ documentation and/or other materials provided with the distribution. | |
19 | \ | |
20 | \ Neither the name of Sun Microsystems, Inc. or the names of contributors | |
21 | \ may be used to endorse or promote products derived from this software | |
22 | \ without specific prior written permission. | |
23 | \ | |
24 | \ This software is provided "AS IS," without a warranty of any kind. | |
25 | \ ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, | |
26 | \ INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A | |
27 | \ PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN | |
28 | \ MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR | |
29 | \ ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR | |
30 | \ DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN | |
31 | \ OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR | |
32 | \ FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE | |
33 | \ DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, | |
34 | \ ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF | |
35 | \ SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. | |
36 | \ | |
37 | \ You acknowledge that this software is not designed, licensed or | |
38 | \ intended for use in the design, construction, operation or maintenance of | |
39 | \ any nuclear facility. | |
40 | \ | |
41 | \ ========== Copyright Header End ============================================ | |
42 | id: @(#)methods.fth 1.5 07/04/10 | |
43 | purpose: Virtual Disk driver methods | |
44 | copyright: Copyright 2007 Sun Microsystems, Inc. All Rights Reserved | |
45 | copyright: Use is subject to license terms. | |
46 | ||
47 | external | |
48 | ||
49 | d# 512 constant block-size | |
50 | ||
51 | : dma-alloc ( size -- vaddr ) pagesize swap 0 claim ; | |
52 | : dma-free ( vaddr size -- ) swap release ; | |
53 | : dma-sync ( virt-addr dev-addr size -- ) 3drop ; | |
54 | : dma-map-out ( vaddr devaddr n -- ) 3drop ; | |
55 | : dma-map-in ( vaddr size cache? -- devaddr ) | |
56 | 2drop | |
57 | ; | |
58 | ||
59 | headerless | |
60 | ||
61 | /vdisk-attr-msg /vdsk-descr-msg max value /vdsk-descr-buf \ Size of the descr | |
62 | \ buffer is max of attr and descr | |
63 | \ structures. | |
64 | h# 8000 value /max-transfer \ Maximum transfer size is 32k bytes | |
65 | ||
66 | fload ${BP}/dev/sun4v-devices/ldc/methods.fth | |
67 | ||
68 | \ If the vDisk client does not use the VTOC service, it must specify a value | |
69 | \ of 0xff for the slice field for read and write transactions so that the | |
70 | \ server knows that the offset specified is the absolute offset relative to | |
71 | \ the start of a disk. See VIO specification for details. | |
72 | ||
73 | h# ff constant use-absolute-disk-offset | |
74 | ||
75 | vdev-disk-client to current-vio-dev | |
76 | 0 value debug-vdisk? \ Debug message enabler | |
77 | vd-disk-type-unk value vd-disk-type \ Stores type of virtual disk, unknown, disk or slice | |
78 | 1 value use-block-read? | |
79 | ||
80 | 8 value vdsk-sid \ Variable to hold sequence ID | |
81 | d# 200 value vd-retries \ Variable to hold # of retries | |
82 | 0 value vdsk-descr-buf \ Variable to hold vdisk descriptor buffer | |
83 | ||
84 | 0 value offset-low \ Low Offset to start of partition | |
85 | 0 value offset-high \ High Offset to start of partition | |
86 | 0 value label-package \ Stores ihandle for label package | |
87 | 0 value deblocker \ Stores ihandle for deblocker package | |
88 | 0 value ldc-up? \ flag, Set if LDC is up | |
89 | 0 value vdsk-seq \ Sequence# for the next request | |
90 | 0 value cur-vdsk-seq \ Sequence# of the current request | |
91 | ||
92 | : init-deblocker ( -- okay? ) | |
93 | " " " deblocker" $open-package to deblocker | |
94 | deblocker if | |
95 | true | |
96 | else | |
97 | cmn-error[ " Can't open deblocker package" ]cmn-end false | |
98 | then | |
99 | ; | |
100 | ||
101 | : init-label-package ( -- okay? ) | |
102 | 0 to offset-high 0 to offset-low | |
103 | my-args " disk-label" $open-package dup to label-package | |
104 | if | |
105 | 0 0 " offset" label-package $call-method to offset-high to offset-low | |
106 | true | |
107 | else | |
108 | cmn-error[ " Can't open disk label package" ]cmn-end false | |
109 | then | |
110 | ; | |
111 | ||
112 | \ The service domain may be down or rebooting... Keep retrying for 5 minutes | |
113 | : open-vdisk-ldc ( -- error? ) | |
114 | get-msecs d# 300.000 + \ 5 minutes later | |
115 | begin ( finish-time ) | |
116 | get-msecs over < ( finish-time keep-trying? ) | |
117 | while ( finish-time ) | |
118 | vd-ldcid ldc-mode-unreliable ldc-open if ( finish-time ) | |
119 | true to ldc-up? ( finish-time ) | |
120 | drop false exit ( false ) | |
121 | then ( finish-time ) | |
122 | cmn-warn[ | |
123 | " Timeout connecting to virtual disk server... retrying" | |
124 | ]cmn-end | |
125 | d# 5000 ms ( finish-time ) | |
126 | repeat | |
127 | cmn-warn[ " Unable to connect to virtual disk server" ]cmn-end | |
128 | drop true ( true ) | |
129 | ; | |
130 | ||
131 | : close-vdisk-ldc ( -- ) | |
132 | ldc-close 0 to ldc-up? | |
133 | ; | |
134 | ||
135 | \ Retry a few times if EWOULDBLOCK, print out warning message if didn't get EOK. | |
136 | \ Only update seqid upon successful return because Solaris counter part | |
137 | \ doesn't like new seqid if OBP higher level SW do retries | |
138 | : send-to-ldc ( buf len -- #bytes ) | |
139 | 0 vd-retries 0 do ( buf len status ) | |
140 | drop 2dup ( buf len buf len ) | |
141 | ldc-write ( buf len #bytes status ) | |
142 | dup HV-EOK <> if ( buf len #bytes status ) | |
143 | dup HV-EWOULDBLOCK <> if ( buf len #bytes status ) | |
144 | dup LDC-NOTUP = if ( buf len #bytes status ) | |
145 | cmn-warn[ " Sending packet to LDC but LDC is Not Up!" ]cmn-end | |
146 | 2drop 2drop 0 unloop exit ( 0 ) | |
147 | then | |
148 | cmn-warn[ " Sending packet to LDC, status: %d" ]cmn-end | |
149 | 3drop 0 unloop exit ( 0 ) | |
150 | then | |
151 | else ( buf len #bytes status ) | |
152 | cur-vdsk-seq 1+ to vdsk-seq | |
153 | drop nip nip unloop exit ( #bytes ) | |
154 | then | |
155 | nip ( buf len status ) | |
156 | \ Every 20 loops, roughly 20 seconds (ldc-write can take @ 1s), | |
157 | \ print a retrying message | |
158 | i 1+ d# 20 mod 0= if | |
159 | cmn-warn[ | |
160 | " Timeout sending package to LDC ... retrying" | |
161 | ]cmn-end | |
162 | then | |
163 | loop ( buf len status ) | |
164 | 3drop 0 | |
165 | cmn-warn[ " Sending packet to LDC timed out!" ]cmn-end | |
166 | ; | |
167 | ||
168 | ||
169 | : receive-from-ldc ( buf len -- #bytes ) | |
170 | 0 vd-retries 0 do ( buf len status ) | |
171 | drop 2dup ldc-read ( buf len #bytes status ) | |
172 | dup HV-EOK <> if ( buf len #bytes status ) | |
173 | dup HV-EWOULDBLOCK <> if ( buf len #bytes status ) | |
174 | dup LDC-NOTUP = if ( buf len #bytes status ) | |
175 | cmn-warn[ | |
176 | " Receiving packet from LDC but LDC is Not Up!" | |
177 | ]cmn-end | |
178 | 2drop 2drop 0 unloop exit ( 0 ) | |
179 | then | |
180 | cmn-warn[ " Receiving packet from LDC, status: %d" ]cmn-end | |
181 | 3drop 0 unloop exit ( 0 ) | |
182 | then | |
183 | else ( buf len #bytes status ) | |
184 | \ Treat EOK with length = 0 same as EWOULDBLOCK at LDC layer | |
185 | \ in which case just retry | |
186 | over if ( buf len #bytes status ) | |
187 | drop nip nip unloop exit ( #bytes ) | |
188 | then | |
189 | then ( buf len #bytes status ) | |
190 | nip ( buf len status ) | |
191 | \ Every 20 loops, roughly 20 seconds (ldc-read can take @ 1s), | |
192 | \ print a retrying message | |
193 | i 1+ d# 20 mod 0= if | |
194 | cmn-warn[ | |
195 | " Timeout receiving packet from LDC ... retrying" | |
196 | ]cmn-end | |
197 | then | |
198 | loop ( buf len status ) | |
199 | 3drop 0 | |
200 | cmn-warn[ " Receiving packet from LDC timed out!" ]cmn-end | |
201 | ; | |
202 | ||
203 | ' receive-from-ldc is retrieve-packet | |
204 | ||
205 | \ Set up vio-msg-tag, sid and seq | |
206 | : set-descr-req-header ( -- ) | |
207 | vdsk-descr-buf /vdsk-descr-msg erase ( ) | |
208 | ||
209 | vio-msg-type-data vio-subtype-info vio-desc-data ( type stype env ) | |
210 | vdsk-descr-buf set-vio-msg-tag ( ) | |
211 | vdsk-sid vdsk-descr-buf tuck >vio-sid l! ( buf ) | |
212 | ||
213 | vd-disk-type over >vdsk-slice c! ( buf ) | |
214 | vdsk-seq swap 2dup >vdsk-seq x! ( seq buf ) | |
215 | >vdsk-reqid x! ( ) | |
216 | vdsk-seq to cur-vdsk-seq | |
217 | ; | |
218 | ||
219 | : send-descr-req ( -- ok? ) | |
220 | vdsk-descr-buf /vdsk-descr-msg send-to-ldc ( len ) | |
221 | /vdsk-descr-msg = ( ok? ) | |
222 | ; | |
223 | ||
224 | \ Send VDS in-band descriptor ring request | |
225 | : send-descr-read-req ( size offset cadr ck# -- ok? ) | |
226 | set-descr-req-header ( size offset cadr ck# ) | |
227 | 2swap over swap ( cadr ck# size size offset ) | |
228 | block-size / ( cadr ck# size size boffset ) | |
229 | vdsk-descr-buf tuck >vdsk-addr x! ( cadr ck# size size buf ) | |
230 | tuck >vdsk-nbytes x! ( cadr ck# size buf ) | |
231 | vdsi-bread over >vdsk-operation c! ( cadr ck# size buf ) | |
232 | vdsk-#cookies over >vdsk-#cookies l! ( cadr ck# size buf ) | |
233 | >vdsk-cookie fill-in-vio-cookie ( ) | |
234 | send-descr-req | |
235 | ; | |
236 | ||
237 | : vdsk-ack-msg? ( -- yes? ) | |
238 | vdsk-descr-buf get-vio-msg-tag ( env stype type ) | |
239 | vio-desc-data vio-subtype-ack vio-msg-type-data ( desc subtype msg-type ) | |
240 | vio-tag-match? 0= if ( ) | |
241 | false exit ( false ) | |
242 | then | |
243 | ||
244 | vdsk-descr-buf >vdsk-seq x@ ( seq ) | |
245 | ||
246 | cur-vdsk-seq = if ( ) | |
247 | \ Status follows the definition in /usr/include/sys/errno.h | |
248 | vdsk-descr-buf >vdsk-status l@ 0= ( yes? ) | |
249 | else | |
250 | cmn-warn[ " vdisk response packet out of sequence" ]cmn-end | |
251 | false ( false ) | |
252 | then | |
253 | ; | |
254 | ||
255 | \ Get an ACK for our request | |
256 | \ The receive-from-ldc times out in @ 3 minute. Try one additional | |
257 | \ time in case do not get descr-ack the first time around. | |
258 | : get-descr-ack? ( -- yes? ) | |
259 | 2 0 do ( ) | |
260 | vdsk-descr-buf /vdsk-descr-msg receive-from-ldc ( rlen ) | |
261 | /vdsk-descr-msg = if ( ) | |
262 | vdsk-ack-msg? if ( ) | |
263 | true unloop exit ( true ) | |
264 | then | |
265 | then | |
266 | loop false ( false ) | |
267 | ; | |
268 | ||
269 | : disk-read ( size addr offset -- #bytes ) | |
270 | debug-vdisk? if 3dup ." disk-read: offset addr size: " u. u. u. cr then | |
271 | >r >r dup dup r> swap r> -rot ( size size offset addr size) | |
272 | ldc-add-map-table-entries ( size size offset cadr ck# ) | |
273 | debug-vdisk? if 2dup ." #cookie cookie-addr " u. u. cr then | |
274 | ( size size offset cadr ck# ) | |
275 | send-descr-read-req if ( #bytes ) | |
276 | get-descr-ack? 0= if ( #bytes ) | |
277 | drop 0 ( 0 ) | |
278 | then | |
279 | else ( #bytes ) | |
280 | cmn-warn[ " Can't send vdisk read request!" ]cmn-end | |
281 | drop 0 ( 0 ) | |
282 | then ( #bytes|0 ) | |
283 | ; | |
284 | ||
285 | \ Fill in version negotiation pkt content and send out | |
286 | : send-vdsk-ver-msg ( -- ok? ) | |
287 | vdsk-descr-buf /vio-ver-msg erase ( ) | |
288 | ||
289 | \ vdsk session id is only updated once during version negotiation | |
290 | vdsk-sid 1+ dup to vdsk-sid ( sid ) | |
291 | vdsk-descr-buf >vio-sid l! ( ) | |
292 | ||
293 | vio-msg-type-ctrl vio-subtype-info vio-ver-info ( msg-type sub-type ver ) | |
294 | vdsk-descr-buf set-vio-msg-tag ( ) | |
295 | ||
296 | vdev-disk-client vdisk-minor vdisk-major ( dev-type minor major ) | |
297 | vdsk-descr-buf set-vio-msg-ver ( ) | |
298 | ||
299 | vdsk-descr-buf /vio-ver-msg ( buf len ) | |
300 | send-to-ldc ( #bytes ) | |
301 | ||
302 | /vio-ver-msg = ( ok? ) | |
303 | ; | |
304 | ||
305 | ' send-vdsk-ver-msg is send-vio-ver-msg | |
306 | ||
307 | \ The ack parameter may be ack or nack | |
308 | : send-vdsk-ack-msg ( buf ack -- ok? ) | |
309 | over >vio-subtype c! ( buf ) | |
310 | vdsk-sid over >vio-sid l! ( buf ) | |
311 | /vio-ver-msg send-to-ldc ( len ) | |
312 | /vio-ver-msg = | |
313 | ; | |
314 | ||
315 | ' send-vdsk-ack-msg is send-vio-ack-msg | |
316 | ||
317 | : vdsk-compatible-ver? ( buf -- yes? ) | |
318 | dup >vio-ver-major w@ vdisk-major = ( buf flag1 ) | |
319 | swap >vio-ver-minor w@ vdisk-minor = ( flag1 flag2 ) | |
320 | and ( yes? ) | |
321 | ; | |
322 | ||
323 | ' vdsk-compatible-ver? is vio-compatible-ver? | |
324 | ||
325 | \ Send our attributes | |
326 | : send-vdsk-attr ( -- ok? ) | |
327 | vdsk-descr-buf /vdisk-attr-msg erase ( ) | |
328 | vio-msg-type-ctrl vio-subtype-info vio-attr-info ( msf-type subtype attr ) | |
329 | vdsk-descr-buf set-vio-msg-tag ( ) | |
330 | vdsk-sid vdsk-descr-buf >vio-sid l! ( ) | |
331 | ||
332 | vdsk-descr-buf /max-transfer block-size / over >vdisk-mtu x! ( buf ) | |
333 | block-size over >vdisk-bsize l! ( buf ) | |
334 | vio-desc-mode swap >vdisk-xfer-mode c! ( ) | |
335 | ||
336 | vdsk-descr-buf /vdisk-attr-msg send-to-ldc ( #bytes ) | |
337 | /vdisk-attr-msg = ( ok? ) | |
338 | ; | |
339 | ' send-vdsk-attr is send-vio-attr | |
340 | ||
341 | : send-vdsk-rdx ( buf -- ok? ) | |
342 | dup /vdisk-attr-msg erase ( buf ) | |
343 | >r vio-msg-type-ctrl vio-subtype-info vio-rdx ( msg-type subtype rdx ) ( r: buf ) | |
344 | r@ set-vio-msg-tag ( ) ( r: buf ) | |
345 | vdsk-sid r@ >vio-sid l! ( ) | |
346 | r> /vdisk-attr-msg send-to-ldc ( #bytes ) | |
347 | /vdisk-attr-msg = ( ok? ) | |
348 | ; | |
349 | ||
350 | ' send-vdsk-rdx is send-vio-rdx | |
351 | ||
352 | \ Inspect VDS attributes, if vdisk-type is type-disk then set slice to use | |
353 | \ an absolute disk offset | |
354 | : (update-vd-disk-type ( buf -- ) | |
355 | >vdisk-type c@ vd-disk-type-disk = if ( ) | |
356 | use-absolute-disk-offset to vd-disk-type ( ) | |
357 | then | |
358 | ; | |
359 | ||
360 | ' (update-vd-disk-type is update-vd-disk-type | |
361 | ||
362 | \ Stages: | |
363 | \ Version negotiation -> Vdisk Attr info -> Dring info -> RDX | |
364 | : init-vdsk-conn ( -- ok? ) | |
365 | vdsk-descr-buf version-negotiation if ( ) | |
366 | vdsk-descr-buf /vdisk-attr-msg vio-exchange-attr if ( ) | |
367 | true exit ( true ) | |
368 | then | |
369 | then | |
370 | cmn-warn[ " Communication error with Virtual Disk Server!" ]cmn-end | |
371 | false ( false ) | |
372 | ; | |
373 | ||
374 | \ The disk writes are not supported, just return 0 bytes written | |
375 | : disk-write ( size raddr offset -- #bytes ) | |
376 | 3drop 0 | |
377 | ; | |
378 | ||
379 | headerless | |
380 | : r/w-blocks ( addr block# #blocks read? -- #read/#written ) | |
381 | >r block-size * -rot ( size addr block# ) ( r: read? ) | |
382 | block-size * ( size addr offset ) ( r: read? ) | |
383 | r> if ( size addr offset ) | |
384 | disk-read ( #bytes ) | |
385 | else ( size addr offset ) | |
386 | disk-write ( #bytes ) | |
387 | then ( #bytes ) | |
388 | block-size / ( #read|#written ) | |
389 | ; | |
390 | ||
391 | \ Allocate vdisk descriptor buffer | |
392 | : allocate-vdsk-descr-buf | |
393 | 8 /vdsk-descr-buf 0 claim to vdsk-descr-buf ( ) | |
394 | ; | |
395 | ||
396 | \ Release and reset vdisk descriptor buffer | |
397 | : deallocate-vdsk-descr-buf | |
398 | /vdsk-descr-buf vdsk-descr-buf release ( ) | |
399 | 0 to vdsk-descr-buf | |
400 | ; | |
401 | ||
402 | external | |
403 | \ These three methods are called by the deblocker. | |
404 | ||
405 | : max-transfer ( -- #bytes ) /max-transfer ; | |
406 | : read-blocks ( addr block# #blocks -- #read ) true r/w-blocks ; | |
407 | : write-blocks ( addr block# #blocks -- #written ) false r/w-blocks ; | |
408 | ||
409 | : #blocks ( -- true | n false ) true ; | |
410 | ||
411 | : open ( -- flag ) | |
412 | open-vdisk-ldc if | |
413 | false exit ( false ) | |
414 | then | |
415 | ||
416 | allocate-vdsk-descr-buf ( ) | |
417 | ||
418 | init-deblocker 0= if | |
419 | deallocate-vdsk-descr-buf ( ) | |
420 | close-vdisk-ldc ( ) | |
421 | false exit ( false ) | |
422 | then | |
423 | debug-vdisk? if ." deblocker opened." cr then ( ) | |
424 | ||
425 | init-vdsk-conn 0= if ( ) | |
426 | deallocate-vdsk-descr-buf ( ) | |
427 | deblocker close-package ( ) | |
428 | close-vdisk-ldc ( ) | |
429 | false exit ( false ) | |
430 | then | |
431 | ||
432 | init-label-package 0= if ( ) | |
433 | deallocate-vdsk-descr-buf ( ) | |
434 | deblocker close-package ( ) | |
435 | close-vdisk-ldc ( ) | |
436 | false exit ( false ) | |
437 | then | |
438 | true ( true ) | |
439 | debug-vdisk? if ." label pkg opened." cr then ( true ) | |
440 | ; | |
441 | ||
442 | : close ( -- ) | |
443 | deallocate-vdsk-descr-buf ( ) | |
444 | ||
445 | label-package ?dup if ( ) | |
446 | close-package ( ) | |
447 | then | |
448 | deblocker ?dup if ( ) | |
449 | close-package ( ) | |
450 | then | |
451 | ldc-up? if ( ) | |
452 | close-vdisk-ldc | |
453 | then | |
454 | ; | |
455 | ||
456 | : seek ( offset.low offset.high -- okay? ) | |
457 | offset-low offset-high d+ " seek" deblocker $call-method ( okay? ) | |
458 | ; | |
459 | ||
460 | : read ( addr len -- actual-len ) | |
461 | " read" deblocker $call-method ( actual-len ) | |
462 | ; | |
463 | ||
464 | : write ( addr len -- actual-len ) | |
465 | " write" deblocker $call-method ( actual-len ) | |
466 | ; | |
467 | ||
468 | : load ( addr -- size ) | |
469 | " load" label-package $call-method ( size ) | |
470 | ; | |
471 | ||
472 | : size ( -- d.size ) | |
473 | " size" label-package $call-method ( d.size ) | |
474 | ; | |
475 | ||
476 | headerless |