Initial commit of OpenSPARC T2 architecture model.
[OpenSPARC-T2-SAM] / obp / obp / dev / sun4v-devices / vnet / methods.fth
CommitLineData
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 ============================================
42id: @(#)methods.fth 1.5 07/06/22
43purpose:
44copyright: Copyright 2007 Sun Microsystems, Inc. All rights reserved.
45copyright: Use is subject to license terms.
46
47headerless
48
49fload ${BP}/dev/sun4v-devices/ldc/methods.fth
50
51false value debug-vnet?
52false value debug-tcp?
53
54fload ${BP}/dev/sun4v-devices/vcommon/vio-struct.fth
55fload ${BP}/dev/sun4v-devices/vcommon/vio-methods.fth
56
57vdev-net-client to current-vio-dev
58h# 1000 value vnet-sid \ Variable to hold sequence id
590 value vnet-seq \ seq# for the next request
600 value cur-vnet-seq \ seq# of the current request
610 value vnet-tmpbuf
62d# 200 value vnet-retries \ Variable to hold number of retries
630 value vnet-opened? \ Variable to indicate if vnet has established
64 \ connection with vswitch
65
66d# 1514 constant frame-size
67
680 value rx-buffer \ Transmit buffer
690 value tx-buffer \ receive buffer
70
718 pagesize 0 claim to rx-buffer
728 pagesize 0 claim to tx-buffer
73
740 value vnet-descr-buf \ Variable to hold Vnet descritor buffer
75
76/vnet-attr-msg /vnet-descr-msg max value /vnet-descr-buf
770 value obp-tftp
780 value ldc-up? \ flag, Set if LDC is up
79
806 buffer: mac-buf \ Variable to hold MAC Address
81
820 value vn-ldcid \ Variable to hold LDC id
83
84: inspect-vnet-port-nodes ( nptr -- )
85 dup " switch-port" ascii v md-find-prop if ( port-ptr ptr|0 )
86 " fwd" ascii a md-find-prop ( ldc-nptr|0 )
87 dup if
88 md-decode-prop drop ( ldc-nptr )
89 " id" ascii v md-find-prop ( idptr|0 )
90 dup if
91 md-decode-prop drop to vn-ldcid
92 else
93 drop
94 then
95 else
96 drop
97 then
98 else
99 drop
100 then
101;
102
103: look-for-vn-ldcid ( -- )
104 ['] inspect-vnet-port-nodes my-node md-applyto-fwds
105;
106
107look-for-vn-ldcid
108
109: init-obp-tftp ( tftp-args$ -- okay? )
110 " obp-tftp" $open-package dup to obp-tftp ( pkg )
111 if
112 true
113 else
114 cmn-warn[ " Can't open OBP standard TFTP package" ]cmn-end
115 false
116 then
117;
118
119\ The service domain may be down or rebooting... Keep retrying for 5 minutes
120: open-vnet-ldc ( -- error? )
121 get-msecs d# 300.000 + \ 5 minutes later
122 begin ( finish-time )
123 get-msecs over < ( finish-time keep-trying? )
124 while ( finish-time )
125 vn-ldcid ldc-mode-unreliable ldc-open if ( finish-time )
126 true to ldc-up? ( finish-time )
127 drop false exit ( false )
128 then ( finish-time )
129 cmn-warn[
130 " Timeout connecting to virtual switch... retrying"
131 ]cmn-end
132 d# 5000 ms ( finish-time )
133 repeat
134 cmn-warn[ " Unable to connect to virtual switch" ]cmn-end
135 drop true ( true )
136;
137
138: close-vnet-ldc ( -- )
139 ldc-close 0 to ldc-up?
140;
141
142: receive-ready? ( -- ready? )
143 ldc-pkt-available?
144;
145
146\ Only update seqid upon successful return because Solaris counter part
147\ doesn't like new seqid if OBP higher level module do retries
148: send-to-ldc ( buf len -- #sent )
149 debug-vnet? if
150 cr ." vnet write : " 2dup swap u. u. cr
151 then
152 0 vnet-retries 0 do ( buf len status )
153 drop 2dup ( buf len buf len )
154 ldc-write ( buf len #sent status )
155 dup HV-EOK <> if ( buf len #sent status )
156 dup HV-EWOULDBLOCK <> if ( buf len #sent status )
157 dup LDC-NOTUP = if ( buf len #sent status )
158 cmn-warn[ " Sending packet to LDC but LDC is Not Up!" ]cmn-end
159 2drop 2drop 0 unloop exit ( 0 )
160 then
161 cmn-warn[ " Sending packet to LDC, status: %d" ]cmn-end
162 3drop 0 unloop exit
163 then
164 else ( buf len #sent status )
165 cur-vnet-seq 1+ to vnet-seq
166 drop nip nip unloop exit ( #sent )
167 then
168 nip ( buf len status )
169 \ Every 20 loops, roughly 20 seconds (ldc-write can take @ 1s),
170 \ print a retrying message
171 i 1+ d# 20 mod 0= if
172 cmn-warn[
173 " Timeout sending package to LDC ... retrying"
174 ]cmn-end
175 then
176 loop ( buf len status )
177 3drop 0
178 cmn-warn[ " Sending packet to LDC timed out!" ]cmn-end
179;
180
181: receive-from-ldc ( buf len -- #bytes )
182 0 vnet-retries 0 do ( buf len status )
183 drop 2dup ( buf len buf len )
184 ldc-read ( buf len alen status )
185 dup HV-EOK <> if ( buf len alen status )
186 dup HV-EWOULDBLOCK <> if ( buf len alen status )
187 dup LDC-NOTUP = if ( buf len alen status )
188 cmn-warn[
189 " Receiving packet from LDC but LDC is Not Up!"
190 ]cmn-end
191 2drop 2drop 0 unloop exit ( 0 )
192 then
193 cmn-warn[ " Receiving packet from LDC, status: %d" ]cmn-end 3drop 0 unloop exit ( 0 )
194 then
195 else ( buf len alen status )
196 \ If vnet-opened? is false and if we get EOK with Length = 0 then
197 \ treat it as EWOULDBLOCK at LDC layer and just retry
198 over vnet-opened? or if ( buf len alen status )
199 drop nip nip unloop exit ( alen )
200 then
201 then
202 nip ( buf len status )
203 \ Every 20 loops, roughly 20 seconds (ldc-read can take @ 1s),
204 \ print a retrying message
205 i 1+ d# 20 mod 0= if
206 cmn-warn[
207 " Timeout receiving packet from LDC ... retrying"
208 ]cmn-end
209 then
210 loop ( buf len status )
211 3drop 0
212 cmn-warn[ " Receiving packet from LDC timed out!" ]cmn-end
213;
214' receive-from-ldc is retrieve-packet
215
216: receive ( -- len' )
217 rx-buffer frame-size receive-from-ldc
218;
219
220: ldc-copy-in ( buf cookie size -- len )
221 0 vnet-retries 0 do ( buf cookie size status )
222 drop 3dup
223 ldc-copy-in ( buf cookie size len status )
224 dup HV-EOK <> if
225 dup HV-EWOULDBLOCK <> if
226 cmn-warn[ " Vnet-copy-in: status: %d" ]cmn-end
227 2drop 2drop 0 unloop exit
228 then
229 else
230 drop nip nip nip unloop exit ( len )
231 then ( buf cookie size len status )
232 nip
233 loop ( buf cookie size status )
234 2drop 2drop 0
235 cmn-warn[ " ldc-copy-in timed out!" ]cmn-end
236;
237
238: send-vnet-ver-msg ( -- ok? )
239 vnet-descr-buf /vio-ver-msg erase
240
241 \ vnet session id is only updated once during version negotiation
242 vnet-sid 1+ dup to vnet-sid
243 vnet-descr-buf >vio-sid l!
244
245 vio-msg-type-ctrl vio-subtype-info vio-ver-info
246 vnet-descr-buf set-vio-msg-tag
247
248 vdev-net-client vnet-minor vnet-major
249 vnet-descr-buf set-vio-msg-ver
250
251 vnet-descr-buf /vio-ver-msg send-to-ldc
252 /vio-ver-msg =
253;
254
255' send-vnet-ver-msg is send-vio-ver-msg
256
257\ The ack parameter may be ack or nack
258: send-vnet-ack-msg ( buf ack -- ok? )
259 over >vio-subtype c! ( buf )
260 vnet-sid over >vio-sid l! ( buf )
261 /vio-ver-msg send-to-ldc ( rlen )
262 /vio-ver-msg =
263;
264
265' send-vnet-ack-msg is send-vio-ack-msg
266
267: vnet-compatible-ver? ( buf -- yes? )
268 dup >vio-ver-major w@ vnet-major = ( buf flag1 )
269 swap >vio-ver-minor w@ vnet-minor = ( flag1 flag2 )
270 and
271;
272
273' vnet-compatible-ver? is vio-compatible-ver?
274
275: get-vnet-mac ( -- x )
276 mac-buf x@ xlsplit swap lwsplit nip swap lwsplit -rot wljoin swap lxjoin
277;
278
279\ Send our attributes
280: send-vnet-attr ( -- ok? )
281 vnet-descr-buf /vnet-attr-msg erase ( )
282
283 vio-msg-type-ctrl vio-subtype-info vio-attr-info
284 vnet-descr-buf set-vio-msg-tag ( )
285 vnet-sid vnet-descr-buf >vio-sid l! ( )
286
287 vnet-descr-buf frame-size over >vnet-attr-mtu x! ( buf )
288 1 over >vnet-ack-freq w! ( buf )
289
290 get-vnet-mac over >vnet-attr-addr x! ( buf )
291 addr-type-mac over >vnet-addr-type c! ( buf )
292 vio-desc-mode swap >vnet-xfer-mode c! ( )
293
294 vnet-descr-buf /vnet-attr-msg send-to-ldc ( rlen )
295 /vnet-attr-msg =
296;
297' send-vnet-attr is send-vio-attr
298
299: send-vnet-rdx ( buf -- ok? )
300 dup /vnet-attr-msg erase ( buf )
301 >r vio-msg-type-ctrl vio-subtype-info vio-rdx
302 r@ set-vio-msg-tag ( R: buf )
303 vnet-sid r@ >vio-sid l! ( R: buf )
304 r> /vnet-attr-msg send-to-ldc ( rlen )
305 /vnet-attr-msg =
306;
307
308' send-vnet-rdx is send-vio-rdx
309
310\ Stages:
311\ Version negotiation -> Vnet Attr info -> Dring info -> RDX
312: init-vnet-conn ( -- ok? )
313 debug-vnet? if ." Vnet version negotiation... " cr then
314 vnet-descr-buf version-negotiation if
315 debug-vnet? if ." Vnet Attr Exchange..." cr then
316 vnet-descr-buf /vnet-attr-msg vio-exchange-attr if
317 true exit
318 then
319 then
320 false
321;
322
323\ Set up sid and seq
324: set-descr-req-header ( type stype env -- )
325 vnet-descr-buf /vnet-descr-msg erase ( type stype env )
326
327 vnet-descr-buf set-vio-msg-tag ( )
328 vnet-sid vnet-descr-buf >vio-sid l! ( )
329
330 vnet-seq vnet-descr-buf >vnet-seq x! ( )
331 vnet-seq to cur-vnet-seq ( )
332;
333
334: send-descr-req ( len -- ok? )
335 vnet-descr-buf over send-to-ldc = ( ok? )
336;
337
338: fill-in-vnet-args ( len cadr #ck -- )
339 2dup 4 pick vnet-descr-buf >vnet-cookie ( len cadr #ck cadr #ck len buf )
340 fill-in-vio-cookie ( len cadr #ck )
341 nip vnet-descr-buf tuck ( len buf #ck buf )
342 >vnet-ctrl-#cookies l! ( len buf )
343 >vnet-ctrl-nbytes l! ( )
344;
345
346\ Fill in & send the cookie pkt, number of cookies may vary
347: vnet-xmit-msg ( len cadr #ck -- ok? )
348 vio-msg-type-data vio-subtype-info vio-desc-data
349 set-descr-req-header ( len cadr #ck )
350 dup 2swap rot ( #ck len cadr #ck )
351 fill-in-vnet-args ( #ck )
352 /ldc-mem-cookie * /vnet-descr-short + ( slen )
353 send-descr-req ( ok? )
354;
355
356\ map-table entry should be page aligned, copy output to tx-buffer and
357\ add tx-buffer to the map table
358: vnet-xmit ( buf len -- #sent )
359 tuck tx-buffer swap move ( len )
360 debug-vnet? if
361 ." vnet xmit buf: len: " tx-buffer 2dup u. u. cr over
362 " dump" evaluate
363 then
364 tx-buffer 2dup over ( len buf len buf len )
365 ldc-add-map-table-entries ( len buf len cadr #ck )
366 vnet-xmit-msg if ( len buf )
367 drop
368 else
369 cmn-warn[ " Can't send vnet write request!" ]cmn-end
370 2drop 0
371 then
372;
373
374\ Check to see if tag DATA/INFO/OBP_DATA, ctrl flag is READY
375: vnet-data-pkt? ( -- yes? )
376 vnet-descr-buf get-vio-msg-tag ( env subt type )
377 vio-desc-data vio-subtype-info vio-msg-type-data vio-tag-match? ( yes? )
378;
379
380
381\ If two cookies span contiguous pages the ldc framework will only give us
382\ one extra-large cookie with a size that overflows into the next page
383: supercookie? ( ck -- supercookie? )
384 dup >ldc-mem-csize x@ ( ck total-size )
385 swap >ldc-mem-caddr x@ ( total-size ck-adr )
386 dup pagesize round-up swap - ( total-size next-page )
387 dup if ( total-size next-page )
388 \ total-size spans two pages?
389 > ( true|false )
390 else
391 \ already page aligned
392 nip ( false )
393 then
394;
395
396\ An ethernet frame (NON-JUMBO) can span at most 2 pages
397\ so we split the cookie into hypervisor-edible cookies
398: split-supercookie ( ck -- ck0 sz0 ck1 sz1 )
399 dup >ldc-mem-csize x@ >r ( ck ) ( r: total-size )
400 >ldc-mem-caddr x@ ( ck0 ) ( r: total-size )
401 dup pagesize round-up over - ( ck0 sz0 ) ( r: total-size )
402 2dup + ( ck0 sz0 ck1 ) ( r: total-size )
403 over r> swap - ( ck0 sz0 ck1 sz1 )
404;
405
406\ recreate the vnet-descr-buf with the weenie cookies
407: sort-supercookies ( ck -- )
408 dup supercookie? if
409 split-supercookie 2swap ( ck1 sz1 ck0 sz0 )
410 vnet-descr-buf ( ck1 sz1 ck0 sz0 buf )
411 2 over >vnet-ctrl-#cookies l! ( ck1 sz1 ck0 sz0 buf )
412 >vnet-cookie ( ck1 sz1 ck0 sz0 buf )
413 tuck >ldc-mem-csize x! ( ck1 sz1 ck0 buf )
414 tuck >ldc-mem-caddr x! ( ck1 sz1 buf )
415 /ldc-mem-cookie + ( ck1 sz1 buf' )
416 tuck >ldc-mem-csize x! ( ck1 buf' )
417 >ldc-mem-caddr x!
418 else
419 drop
420 then
421;
422
423\ Read cookies, copy in data
424\ Even though we have at most 2 cookies right now, put in a loop
425\ so that it can handle more cookies in the future
426: vnet-copy-in ( buf len -- rlen )
427 vnet-descr-buf >vnet-cookie sort-supercookies ( buf len )
428 vnet-descr-buf >vnet-ctrl-nbytes l@ ( buf len rlen )
429 \ Copy multiple cookies
430 min 0 -rot ( rlen buf len' )
431 vnet-descr-buf >vnet-ctrl-#cookies l@ 0 do ( rlen buf len' )
432 vnet-descr-buf >vnet-cookie
433 /ldc-mem-cookie i * + ( rlen buf len' addr )
434 dup >ldc-mem-caddr x@ ( rlen buf len' addr ck )
435 swap >ldc-mem-csize x@ ( rlen buf len' ck size )
436
437 debug-vnet? if
438 dup ." Retrieved cookie size: " u. cr
439 then
440
441 rx-buffer -rot ldc-copy-in ( rlen buf len' clen )
442
443 debug-vnet? if
444 dup ." ldc copy in cookie size: " u. cr
445 rx-buffer over " dump" evaluate
446 then
447
448 \ For alignment, cookie size maybe bigger than requested size
449 over min >r ( rlen buf len' ) ( R: clen' )
450 over rx-buffer swap r@ move ( rlen buf len' ) ( R: clen' )
451 r@ - swap r@ + rot r> + ( len'' buf' rlen' )
452 -rot swap ( rlen' buf' len'' )
453 loop
454 2drop ( rlen )
455;
456
457\ Send back ACK packet
458: vnet-send-ack ( idx #ck -- )
459 vio-msg-type-data vio-subtype-ack vio-desc-data ( idx #ck )
460 set-descr-req-header ( idx #ck )
461 swap vnet-descr-buf >vnet-desc-hdl x! ( #ck )
462 /ldc-mem-cookie * /vnet-descr-short + ( slen )
463 send-descr-req drop
464;
465
466\ Read a packet if it's available, skip the ACK packets, for DATA packet,
467\ Send an ACK packet after the memory content is retrieved.
468: vnet-poll ( buf len -- #rcvd )
469 begin
470 vnet-descr-buf /vnet-descr-msg retrieve-packet ( buf len rlen )
471 dup 0= if nip nip exit then ( 0 )
472 drop vnet-data-pkt? ( buf len yes? )
473 until
474
475 vnet-copy-in ( #rcvd )
476 vnet-descr-buf dup >vnet-desc-hdl x@ ( #rcvd buf idx )
477 swap >vnet-ctrl-#cookies l@ ( #rcvd idx #ck )
478 vnet-send-ack ( #rcvd )
479;
480
481: short-send ( buf,len -- error? )
482 tuck vnet-xmit ( len #sent )
483 <>
484;
485
486\ Dump pkts with 0x800 (IP), 0x11 (UDP) and port 0x44 (BOOTP/DHCP)
487: dump-udp-bootp ( pkt len -- pkt len )
488 dup if ( pkt len )
489 over d# 12 + w@ h# 800 = if ( pkt len )
490 over d# 23 + c@ h# 11 = if ( pkt len )
491 over d# 36 + w@ h# 44 = if
492 ." udp pkt received!" cr
493 2dup " dump" evaluate cr
494 then
495 then
496 then
497 then
498;
499
500\ offset 34: source port (2 bytes)
501\ 36: destination port (2 bytes)
502\ 38: seq number (4 bytes)
503\ 42: ack number (4 bytes)
504: dump-tcp-headers ( pkt len -- pkt len )
505 dup if ( pkt len )
506 over d# 12 + w@ h# 800 = if ( pkt len )
507 over d# 23 + c@ d# 6 = if ( pkt len )
508 over d# 34 + w@ u. over d# 36 + w@ u.
509 over d# 38 + w@ >r over d# 40 + w@ r> wljoin u.
510 over d# 42 + w@ >r over d# 44 + w@ r> wljoin u. cr
511 then
512 then
513 then
514;
515
516\ Allocate vnet descriptor buffer
517: allocate-vnet-descr-buf
518 8 /vnet-descr-buf 0 claim to vnet-descr-buf ( )
519;
520
521\ Release and reset vnet descriptor buffer
522: deallocate-vnet-descr-buf
523 /vnet-descr-buf vnet-descr-buf release ( )
524 0 to vnet-descr-buf
525;
526
527external
528
529: open ( -- ok? )
530 open-vnet-ldc if ( )
531 false exit ( false )
532 then
533
534 " local-mac-address" get-my-property if ( adr len | )
535 cmn-warn[ " Can not find local-mac-address property" ]cmn-end
536 false exit ( false )
537 then ( adr len )
538 over mac-address comp 0= if ( adr len )
539 \ Save a copy of mac address to mac-buf, used in vnet version negotiation
540 2dup mac-buf swap cmove ( adr len )
541 " mac-address" property ( )
542 else ( adr len )
543 cmn-warn[ " MAC Address does not match local-mac-address, " cmn-append
544 " Virtual Networks do not support variable local-mac-address? = false."
545 ]cmn-end
546 2drop false exit ( false )
547 then
548
549 allocate-vnet-descr-buf ( )
550
551 my-args init-obp-tftp 0= if
552 deallocate-vnet-descr-buf ( )
553 close-vnet-ldc ( )
554 false exit ( false )
555 then
556
557 init-vnet-conn 0= if ( )
558 deallocate-vnet-descr-buf ( )
559 obp-tftp ?dup if close-package then ( )
560 close-vnet-ldc ( )
561 false exit ( false )
562 then
563
564 debug-vnet? if ( )
565 ." mac-address shows: " ( )
566 mac-address bounds do i c@ u. loop cr ( )
567 then
568
569 true to vnet-opened? ( )
570 true ( true )
571;
572
573: close ( -- )
574 deallocate-vnet-descr-buf ( )
575
576 obp-tftp ?dup if close-package then
577 ldc-up? if
578 close-vnet-ldc
579 then
580
581 false to vnet-opened?
582;
583
584: read ( buf,len -- -2|len )
585 receive-ready? 0= if 2drop -2 exit then
586
587 over swap ( buf buf len )
588 vnet-poll ?dup 0= if -2 then ( buf len' )
589
590 debug-tcp? if ( buf len' )
591 dump-udp-bootp ( buf len' )
592 dump-tcp-headers ( buf len' )
593 nip ( len' )
594 else
595 nip ( len' )
596 then
597;
598
599: write ( buf,len -- len )
600 vnet-xmit
601;
602
603: load ( adr -- len )
604 " load" obp-tftp $call-method
605;
606
607: watch-net ( -- )
608 open 0= if exit then
609 frame-size alloc-mem to vnet-tmpbuf
610
611 ." Looking for Ethernet packets." cr
612 ." '.' is a good packet. 'X' is a bad packet." cr
613 ." Type any key to stop." cr
614
615 begin
616 key? 0=
617 while
618 receive-ready? if
619 vnet-tmpbuf frame-size vnet-poll if ." ." else ." X" then
620 then
621 repeat
622 key drop
623
624 vnet-tmpbuf frame-size free-mem
625 close
626;
627
628headerless