pci: align ioport unmap error handling to ioport map
[dpdk.git] / tools / setup.sh
1 #! /bin/bash
2
3 #   BSD LICENSE
4 #
5 #   Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
6 #   All rights reserved.
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 #     * Redistributions of source code must retain the above copyright
13 #       notice, this list of conditions and the following disclaimer.
14 #     * Redistributions in binary form must reproduce the above copyright
15 #       notice, this list of conditions and the following disclaimer in
16 #       the documentation and/or other materials provided with the
17 #       distribution.
18 #     * Neither the name of Intel Corporation nor the names of its
19 #       contributors may be used to endorse or promote products derived
20 #       from this software without specific prior written permission.
21 #
22 #   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23 #   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24 #   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
25 #   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
26 #   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27 #   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
28 #   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29 #   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30 #   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31 #   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
32 #   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33
34 #
35 # Run with "source /path/to/setup.sh"
36 #
37
38 #
39 # Change to DPDK directory ( <this-script's-dir>/.. ), and export it as RTE_SDK
40 #
41 cd $(dirname ${BASH_SOURCE[0]})/..
42 export RTE_SDK=$PWD
43 echo "------------------------------------------------------------------------------"
44 echo " RTE_SDK exported as $RTE_SDK"
45 echo "------------------------------------------------------------------------------"
46
47 #
48 # Application EAL parameters for setting memory options (amount/channels/ranks).
49 #
50 EAL_PARAMS='-n 4'
51
52 #
53 # Sets QUIT variable so script will finish.
54 #
55 quit()
56 {
57         QUIT=$1
58 }
59
60 # Shortcut for quit.
61 q()
62 {
63         quit
64 }
65
66 #
67 # Sets up environmental variables for ICC.
68 #
69 setup_icc()
70 {
71         DEFAULT_PATH=/opt/intel/bin/iccvars.sh
72         param=$1
73         shpath=`which iccvars.sh 2> /dev/null`
74         if [ $? -eq 0 ] ; then
75                 echo "Loading iccvars.sh from $shpath for $param"
76                 source $shpath $param
77         elif [ -f $DEFAULT_PATH ] ; then
78                 echo "Loading iccvars.sh from $DEFAULT_PATH for $param"
79                 source $DEFAULT_PATH $param
80         else
81                 echo "## ERROR: cannot find 'iccvars.sh' script to set up ICC."
82                 echo "##     To fix, please add the directory that contains"
83                 echo "##     iccvars.sh  to your 'PATH' environment variable."
84                 quit
85         fi
86 }
87
88 #
89 # Sets RTE_TARGET and does a "make install".
90 #
91 setup_target()
92 {
93         option=$1
94         export RTE_TARGET=${TARGETS[option]}
95
96         compiler=${RTE_TARGET##*-}
97         if [ "$compiler" == "icc" ] ; then
98                 platform=${RTE_TARGET%%-*}
99                 if [ "$platform" == "x86_64" ] ; then
100                         setup_icc intel64
101                 else
102                         setup_icc ia32
103                 fi
104         fi
105         if [ "$QUIT" == "0" ] ; then
106                 make install T=${RTE_TARGET}
107         fi
108         echo "------------------------------------------------------------------------------"
109         echo " RTE_TARGET exported as $RTE_TARGET"
110         echo "------------------------------------------------------------------------------"
111 }
112
113 #
114 # Creates hugepage filesystem.
115 #
116 create_mnt_huge()
117 {
118         echo "Creating /mnt/huge and mounting as hugetlbfs"
119         sudo mkdir -p /mnt/huge
120
121         grep -s '/mnt/huge' /proc/mounts > /dev/null
122         if [ $? -ne 0 ] ; then
123                 sudo mount -t hugetlbfs nodev /mnt/huge
124         fi
125 }
126
127 #
128 # Removes hugepage filesystem.
129 #
130 remove_mnt_huge()
131 {
132         echo "Unmounting /mnt/huge and removing directory"
133         grep -s '/mnt/huge' /proc/mounts > /dev/null
134         if [ $? -eq 0 ] ; then
135                 sudo umount /mnt/huge
136         fi
137
138         if [ -d /mnt/huge ] ; then
139                 sudo rm -R /mnt/huge
140         fi
141 }
142
143 #
144 # Unloads igb_uio.ko.
145 #
146 remove_igb_uio_module()
147 {
148         echo "Unloading any existing DPDK UIO module"
149         /sbin/lsmod | grep -s igb_uio > /dev/null
150         if [ $? -eq 0 ] ; then
151                 sudo /sbin/rmmod igb_uio
152         fi
153 }
154
155 #
156 # Loads new igb_uio.ko (and uio module if needed).
157 #
158 load_igb_uio_module()
159 {
160         if [ ! -f $RTE_SDK/$RTE_TARGET/kmod/igb_uio.ko ];then
161                 echo "## ERROR: Target does not have the DPDK UIO Kernel Module."
162                 echo "       To fix, please try to rebuild target."
163                 return
164         fi
165
166         remove_igb_uio_module
167
168         /sbin/lsmod | grep -s uio > /dev/null
169         if [ $? -ne 0 ] ; then
170                 modinfo uio > /dev/null
171                 if [ $? -eq 0 ]; then
172                         echo "Loading uio module"
173                         sudo /sbin/modprobe uio
174                 fi
175         fi
176
177         # UIO may be compiled into kernel, so it may not be an error if it can't
178         # be loaded.
179
180         echo "Loading DPDK UIO module"
181         sudo /sbin/insmod $RTE_SDK/$RTE_TARGET/kmod/igb_uio.ko
182         if [ $? -ne 0 ] ; then
183                 echo "## ERROR: Could not load kmod/igb_uio.ko."
184                 quit
185         fi
186 }
187
188 #
189 # Unloads VFIO modules.
190 #
191 remove_vfio_module()
192 {
193         echo "Unloading any existing VFIO module"
194         /sbin/lsmod | grep -s vfio > /dev/null
195         if [ $? -eq 0 ] ; then
196                 sudo /sbin/rmmod vfio-pci
197                 sudo /sbin/rmmod vfio_iommu_type1
198                 sudo /sbin/rmmod vfio
199         fi
200 }
201
202 #
203 # Loads new vfio-pci (and vfio module if needed).
204 #
205 load_vfio_module()
206 {
207         remove_vfio_module
208
209         VFIO_PATH="kernel/drivers/vfio/pci/vfio-pci.ko"
210
211         echo "Loading VFIO module"
212         /sbin/lsmod | grep -s vfio_pci > /dev/null
213         if [ $? -ne 0 ] ; then
214                 if [ -f /lib/modules/$(uname -r)/$VFIO_PATH ] ; then
215                         sudo /sbin/modprobe vfio-pci
216                 fi
217         fi
218
219         # make sure regular users can read /dev/vfio
220         echo "chmod /dev/vfio"
221         sudo chmod a+x /dev/vfio
222         if [ $? -ne 0 ] ; then
223                 echo "FAIL"
224                 quit
225         fi
226         echo "OK"
227
228         # check if /dev/vfio/vfio exists - that way we
229         # know we either loaded the module, or it was
230         # compiled into the kernel
231         if [ ! -e /dev/vfio/vfio ] ; then
232                 echo "## ERROR: VFIO not found!"
233         fi
234 }
235
236 #
237 # Unloads the rte_kni.ko module.
238 #
239 remove_kni_module()
240 {
241         echo "Unloading any existing DPDK KNI module"
242         /sbin/lsmod | grep -s rte_kni > /dev/null
243         if [ $? -eq 0 ] ; then
244                 sudo /sbin/rmmod rte_kni
245         fi
246 }
247
248 #
249 # Loads the rte_kni.ko module.
250 #
251 load_kni_module()
252 {
253     # Check that the KNI module is already built.
254         if [ ! -f $RTE_SDK/$RTE_TARGET/kmod/rte_kni.ko ];then
255                 echo "## ERROR: Target does not have the DPDK KNI Module."
256                 echo "       To fix, please try to rebuild target."
257                 return
258         fi
259
260     # Unload existing version if present.
261         remove_kni_module
262
263     # Now try load the KNI module.
264         echo "Loading DPDK KNI module"
265         sudo /sbin/insmod $RTE_SDK/$RTE_TARGET/kmod/rte_kni.ko
266         if [ $? -ne 0 ] ; then
267                 echo "## ERROR: Could not load kmod/rte_kni.ko."
268                 quit
269         fi
270 }
271
272 #
273 # Sets appropriate permissions on /dev/vfio/* files
274 #
275 set_vfio_permissions()
276 {
277         # make sure regular users can read /dev/vfio
278         echo "chmod /dev/vfio"
279         sudo chmod a+x /dev/vfio
280         if [ $? -ne 0 ] ; then
281                 echo "FAIL"
282                 quit
283         fi
284         echo "OK"
285
286         # make sure regular user can access everything inside /dev/vfio
287         echo "chmod /dev/vfio/*"
288         sudo chmod 0666 /dev/vfio/*
289         if [ $? -ne 0 ] ; then
290                 echo "FAIL"
291                 quit
292         fi
293         echo "OK"
294
295         # since permissions are only to be set when running as
296         # regular user, we only check ulimit here
297         #
298         # warn if regular user is only allowed
299         # to memlock <64M of memory
300         MEMLOCK_AMNT=`ulimit -l`
301
302         if [ "$MEMLOCK_AMNT" != "unlimited" ] ; then
303                 MEMLOCK_MB=`expr $MEMLOCK_AMNT / 1024`
304                 echo ""
305                 echo "Current user memlock limit: ${MEMLOCK_MB} MB"
306                 echo ""
307                 echo "This is the maximum amount of memory you will be"
308                 echo "able to use with DPDK and VFIO if run as current user."
309                 echo -n "To change this, please adjust limits.conf memlock "
310                 echo "limit for current user."
311
312                 if [ $MEMLOCK_AMNT -lt 65536 ] ; then
313                         echo ""
314                         echo "## WARNING: memlock limit is less than 64MB"
315                         echo -n "## DPDK with VFIO may not be able to initialize "
316                         echo "if run as current user."
317                 fi
318         fi
319 }
320
321 #
322 # Removes all reserved hugepages.
323 #
324 clear_huge_pages()
325 {
326         echo > .echo_tmp
327         for d in /sys/devices/system/node/node? ; do
328                 echo "echo 0 > $d/hugepages/hugepages-2048kB/nr_hugepages" >> .echo_tmp
329         done
330         echo "Removing currently reserved hugepages"
331         sudo sh .echo_tmp
332         rm -f .echo_tmp
333
334         remove_mnt_huge
335 }
336
337 #
338 # Creates hugepages.
339 #
340 set_non_numa_pages()
341 {
342         clear_huge_pages
343
344         echo ""
345         echo "  Input the number of 2MB pages"
346         echo "  Example: to have 128MB of hugepages available, enter '64' to"
347         echo "  reserve 64 * 2MB pages"
348         echo -n "Number of pages: "
349         read Pages
350
351         echo "echo $Pages > /sys/kernel/mm/hugepages/hugepages-2048kB/nr_hugepages" > .echo_tmp
352
353         echo "Reserving hugepages"
354         sudo sh .echo_tmp
355         rm -f .echo_tmp
356
357         create_mnt_huge
358 }
359
360 #
361 # Creates hugepages on specific NUMA nodes.
362 #
363 set_numa_pages()
364 {
365         clear_huge_pages
366
367         echo ""
368         echo "  Input the number of 2MB pages for each node"
369         echo "  Example: to have 128MB of hugepages available per node,"
370         echo "  enter '64' to reserve 64 * 2MB pages on each node"
371
372         echo > .echo_tmp
373         for d in /sys/devices/system/node/node? ; do
374                 node=$(basename $d)
375                 echo -n "Number of pages for $node: "
376                 read Pages
377                 echo "echo $Pages > $d/hugepages/hugepages-2048kB/nr_hugepages" >> .echo_tmp
378         done
379         echo "Reserving hugepages"
380         sudo sh .echo_tmp
381         rm -f .echo_tmp
382
383         create_mnt_huge
384 }
385
386 #
387 # Run unit test application.
388 #
389 run_test_app()
390 {
391         echo ""
392         echo "  Enter hex bitmask of cores to execute test app on"
393         echo "  Example: to execute app on cores 0 to 7, enter 0xff"
394         echo -n "bitmask: "
395         read Bitmask
396         echo "Launching app"
397         sudo ${RTE_TARGET}/app/test -c $Bitmask $EAL_PARAMS
398 }
399
400 #
401 # Run unit testpmd application.
402 #
403 run_testpmd_app()
404 {
405         echo ""
406         echo "  Enter hex bitmask of cores to execute testpmd app on"
407         echo "  Example: to execute app on cores 0 to 7, enter 0xff"
408         echo -n "bitmask: "
409         read Bitmask
410         echo "Launching app"
411         sudo ${RTE_TARGET}/app/testpmd -c $Bitmask $EAL_PARAMS -- -i
412 }
413
414 #
415 # Print hugepage information.
416 #
417 grep_meminfo()
418 {
419         grep -i huge /proc/meminfo
420 }
421
422 #
423 # Calls dpdk_nic_bind.py --status to show the NIC and what they
424 # are all bound to, in terms of drivers.
425 #
426 show_nics()
427 {
428         if  /sbin/lsmod | grep -q -e igb_uio -e vfio_pci; then
429                 ${RTE_SDK}/tools/dpdk_nic_bind.py --status
430         else
431                 echo "# Please load the 'igb_uio' or 'vfio-pci' kernel module before "
432                 echo "# querying or adjusting NIC device bindings"
433         fi
434 }
435
436 #
437 # Uses dpdk_nic_bind.py to move devices to work with vfio-pci
438 #
439 bind_nics_to_vfio()
440 {
441         if /sbin/lsmod  | grep -q vfio_pci ; then
442                 ${RTE_SDK}/tools/dpdk_nic_bind.py --status
443                 echo ""
444                 echo -n "Enter PCI address of device to bind to VFIO driver: "
445                 read PCI_PATH
446                 sudo ${RTE_SDK}/tools/dpdk_nic_bind.py -b vfio-pci $PCI_PATH &&
447                         echo "OK"
448         else
449                 echo "# Please load the 'vfio-pci' kernel module before querying or "
450                 echo "# adjusting NIC device bindings"
451         fi
452 }
453
454 #
455 # Uses dpdk_nic_bind.py to move devices to work with igb_uio
456 #
457 bind_nics_to_igb_uio()
458 {
459         if  /sbin/lsmod  | grep -q igb_uio ; then
460                 ${RTE_SDK}/tools/dpdk_nic_bind.py --status
461                 echo ""
462                 echo -n "Enter PCI address of device to bind to IGB UIO driver: "
463                 read PCI_PATH
464                 sudo ${RTE_SDK}/tools/dpdk_nic_bind.py -b igb_uio $PCI_PATH && echo "OK"
465         else
466                 echo "# Please load the 'igb_uio' kernel module before querying or "
467                 echo "# adjusting NIC device bindings"
468         fi
469 }
470
471 #
472 # Uses dpdk_nic_bind.py to move devices to work with kernel drivers again
473 #
474 unbind_nics()
475 {
476         ${RTE_SDK}/tools/dpdk_nic_bind.py --status
477         echo ""
478         echo -n "Enter PCI address of device to unbind: "
479         read PCI_PATH
480         echo ""
481         echo -n "Enter name of kernel driver to bind the device to: "
482         read DRV
483         sudo ${RTE_SDK}/tools/dpdk_nic_bind.py -b $DRV $PCI_PATH && echo "OK"
484 }
485
486 #
487 # Options for building a target. Note that this step MUST be first as it sets
488 # up TARGETS[] starting from 1, and this is accessed in setup_target using the
489 # user entered option.
490 #
491 step1_func()
492 {
493         TITLE="Select the DPDK environment to build"
494         CONFIG_NUM=1
495         for cfg in config/defconfig_* ; do
496                 cfg=${cfg/config\/defconfig_/}
497                 TEXT[$CONFIG_NUM]="$cfg"
498                 TARGETS[$CONFIG_NUM]=$cfg
499                 FUNC[$CONFIG_NUM]="setup_target"
500                 let "CONFIG_NUM+=1"
501         done
502 }
503
504 #
505 # Options for setting up environment.
506 #
507 step2_func()
508 {
509         TITLE="Setup linuxapp environment"
510
511         TEXT[1]="Insert IGB UIO module"
512         FUNC[1]="load_igb_uio_module"
513
514         TEXT[2]="Insert VFIO module"
515         FUNC[2]="load_vfio_module"
516
517         TEXT[3]="Insert KNI module"
518         FUNC[3]="load_kni_module"
519
520         TEXT[4]="Setup hugepage mappings for non-NUMA systems"
521         FUNC[4]="set_non_numa_pages"
522
523         TEXT[5]="Setup hugepage mappings for NUMA systems"
524         FUNC[5]="set_numa_pages"
525
526         TEXT[6]="Display current Ethernet device settings"
527         FUNC[6]="show_nics"
528
529         TEXT[7]="Bind Ethernet device to IGB UIO module"
530         FUNC[7]="bind_nics_to_igb_uio"
531
532         TEXT[8]="Bind Ethernet device to VFIO module"
533         FUNC[8]="bind_nics_to_vfio"
534
535         TEXT[9]="Setup VFIO permissions"
536         FUNC[9]="set_vfio_permissions"
537 }
538
539 #
540 # Options for running applications.
541 #
542 step3_func()
543 {
544         TITLE="Run test application for linuxapp environment"
545
546         TEXT[1]="Run test application (\$RTE_TARGET/app/test)"
547         FUNC[1]="run_test_app"
548
549         TEXT[2]="Run testpmd application in interactive mode (\$RTE_TARGET/app/testpmd)"
550         FUNC[2]="run_testpmd_app"
551 }
552
553 #
554 # Other options
555 #
556 step4_func()
557 {
558         TITLE="Other tools"
559
560         TEXT[1]="List hugepage info from /proc/meminfo"
561         FUNC[1]="grep_meminfo"
562
563 }
564
565 #
566 # Options for cleaning up the system
567 #
568 step5_func()
569 {
570         TITLE="Uninstall and system cleanup"
571
572         TEXT[1]="Unbind NICs from IGB UIO or VFIO driver"
573         FUNC[1]="unbind_nics"
574
575         TEXT[2]="Remove IGB UIO module"
576         FUNC[2]="remove_igb_uio_module"
577
578         TEXT[3]="Remove VFIO module"
579         FUNC[3]="remove_vfio_module"
580
581         TEXT[4]="Remove KNI module"
582         FUNC[4]="remove_kni_module"
583
584         TEXT[5]="Remove hugepage mappings"
585         FUNC[5]="clear_huge_pages"
586 }
587
588 STEPS[1]="step1_func"
589 STEPS[2]="step2_func"
590 STEPS[3]="step3_func"
591 STEPS[4]="step4_func"
592 STEPS[5]="step5_func"
593
594 QUIT=0
595
596 while [ "$QUIT" == "0" ]; do
597         OPTION_NUM=1
598
599         for s in $(seq ${#STEPS[@]}) ; do
600                 ${STEPS[s]}
601
602                 echo "----------------------------------------------------------"
603                 echo " Step $s: ${TITLE}"
604                 echo "----------------------------------------------------------"
605
606                 for i in $(seq ${#TEXT[@]}) ; do
607                         echo "[$OPTION_NUM] ${TEXT[i]}"
608                         OPTIONS[$OPTION_NUM]=${FUNC[i]}
609                         let "OPTION_NUM+=1"
610                 done
611
612                 # Clear TEXT and FUNC arrays before next step
613                 unset TEXT
614                 unset FUNC
615
616                 echo ""
617         done
618
619         echo "[$OPTION_NUM] Exit Script"
620         OPTIONS[$OPTION_NUM]="quit"
621         echo ""
622         echo -n "Option: "
623         read our_entry
624         echo ""
625         ${OPTIONS[our_entry]} ${our_entry}
626
627         if [ "$QUIT" == "0" ] ; then
628                 echo
629                 echo -n "Press enter to continue ..."; read
630         fi
631
632 done