blob: de2d502e68e2c9b0846c8c16c6658d901e462eef [file] [log] [blame]
Jakob Vukalovic70ba6332023-07-11 10:52:22 +01001#!/bin/bash
2
Jakob Vukalovic2d0cae52023-07-20 12:01:27 +01003# Copyright 2023 Google Inc. All rights reserved.
Jakob Vukalovic70ba6332023-07-11 10:52:22 +01004#
5# Licensed under the Apache License, Version 2.0 (the "License");
6# you may not use this file except in compliance with the License.
7# You may obtain a copy of the License at
8#
9# http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS,
13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14# See the License for the specific language governing permissions and
15# limitations under the License.
16
17# prepare_device_vfio.sh: prepares a device for VFIO assignment by binding a VFIO driver to it
18
19adb="${ADB:="adb"}" # ADB command to use
20vfio_dir="/dev/vfio"
21platform_bus="/sys/bus/platform"
22vfio_reset_required="/sys/module/vfio_platform/parameters/reset_required"
23vfio_noiommu_param="/sys/module/vfio/parameters/enable_unsafe_noiommu_mode"
24vfio_unsafe_interrupts_param="/sys/module/vfio_iommu_type1/parameters/allow_unsafe_interrupts"
25
26function print_help() {
27 echo "prepare_device_vfio.sh prepares a device for VFIO assignment"
28 echo ""
29 echo " Usage:"
30 echo " $0 DEVICE_NAME"
31 echo " Prepare device DEVICE_NAME for VFIO assignment."
32 echo ""
33 echo " help - prints this help message"
34}
35
36function cmd() {
37 $adb shell $@
38}
39
40function tcmd() {
41 trap "echo \"Error: adb shell command '$@' failed\" ; exit 1" ERR
42 $adb shell $@
43}
44
45function ensure_root() {
46 # Check user id
47 if [ $(cmd "id -u") != 0 ]; then
48 read -p "Must run as root; restart ADBD? [y/n] " answer
49 case $answer in
50 [Yy]* )
51 $adb root && $adb wait-for-device && sleep 3 || exit 1
52 ;;
53 * )
54 exit 1
55 esac
56 fi
57}
58
59function check_vfio() {
60 cmd "[ -c $vfio_dir/vfio ]"
61 if [ $? -ne 0 ]; then
62 echo "cannot find $vfio_dir/vfio"
63 exit 1
64 fi
65
66 cmd "[ -d $platform_bus/drivers/vfio-platform ]"
67 if [ $? -ne 0 ]; then
68 echo "VFIO-platform is not supported"
69 exit 1
70 fi
71}
72
73function check_device() {
74 cmd "[ -d $device_sys ]"
75 if [ $? -ne 0 ]; then
76 echo "no device $device ($device_sys)"
77 exit 1
78 fi
79}
80
81function get_device_iommu_group() {
82 local group=$(cmd "basename \$(readlink \"$device_sys/iommu_group\")")
83 if [ $? -eq 0 ]; then
84 echo $group
85 else
86 echo ""
87 fi
88}
89
90function misc_setup() {
91 # VFIO NOIOMMU check
92 if [ -z "$group" ]; then
93 echo "$device_sys does not have an IOMMU group - setting $vfio_noiommu_param"
94 tcmd "echo y > \"$vfio_noiommu_param\""
95 fi
96
97 # Disable SELinux to allow virtualizationmanager and crosvm to access sysfs
98 echo "[*WARN*] setenforce=0: SELinux is disabled"
99 tcmd "setenforce 0"
100
101 # Samsung IOMMU does not report interrupt remapping support, so enable unsafe uinterrupts
102 if [ -n "$group" ]; then
103 local iommu_drv=$(cmd "basename \$(readlink \"$device_sys/iommu/device/driver\")")
104 if [ "$iommu_drv" = "samsung-sysmmu-v9" ]; then
105 tcmd "echo y > \"$vfio_unsafe_interrupts_param\""
106 fi
107 fi
108}
109
110function bind_vfio_driver() {
111 # Check if non-VFIO driver is currently bound, ie unbinding is needed
112 cmd "[ -e \"$device_driver\" ] && \
113 [ ! \$(basename \$(readlink \"$device_driver\")) = \"vfio-platform\" ]"
114 if [ $? -eq 0 ]; then
115 # Unbind current driver
116 tcmd "echo \"$device\" > \"$device_driver/unbind\""
117 fi
118
119 # Bind to VFIO driver
120 cmd "[ ! -e \"$device_driver\" ]"
121 if [ $? -eq 0 ]; then
122 # Bind vfio-platform driver
123 tcmd "echo \"vfio-platform\" > \"$device_sys/driver_override\""
124 tcmd "echo \"$device\" > \"$platform_bus/drivers_probe\""
125 sleep 2
126 fi
127}
128
129function verify_vfio_driver() {
130 # Verify new VFIO file structure
131 group=$(get_device_iommu_group)
132 if [ -z "$group" ]; then
133 echo "cannot setup VFIO-NOIOMMU for $device_sys"
134 exit 1
135 fi
136
137 cmd "[ ! -c \"$vfio_dir/$group\" ] || \
138 [ ! -e \"$device_driver\" ] || \
139 [ ! \$(basename \$(readlink \"$device_driver\")) = \"vfio-platform\" ]"
140 if [ $? -eq 0 ]; then
141 echo "could not bind $device to VFIO platform driver"
142
143 if [ $(cmd "cat $vfio_reset_required") = Y ]; then
144 echo "VFIO device reset handler must be registered. Either unset $vfio_reset_required, \
145or register a reset handler for $device_sys"
146 fi
147 exit 1
148 fi
149}
150
151function prepare_device() {
152 device="$1"
153 device_sys="/sys/bus/platform/devices/$device"
154 device_driver="$device_sys/driver"
155
156 ensure_root
157 check_vfio
158 check_device
159 group=$(get_device_iommu_group)
160 misc_setup
161
162 bind_vfio_driver
163 verify_vfio_driver
164
165 echo "Device: $device_sys"
166 echo "IOMMU group: $group"
167 echo "VFIO group file: $vfio_dir/$group"
168 echo "Ready!"
169}
170
171cmd=$1
172
173case $cmd in
174 ""|help) print_help ;;
175 *) prepare_device "$cmd" $@ ;;
176esac