1#!/bin/bash 2# 3# Copyright (C) 2022 Intel Corporation. 4# 5# SPDX-License-Identifier: BSD-3-Clause 6# 7 8# Helper functions 9 10function probe_modules() { 11 modprobe pci_stub 12} 13 14function offline_cpus() { 15 # Each parameter of this function is considered the APIC ID (as is reported in /proc/cpuinfo, in decimal) of a CPU 16 # assigned to a post-launched RTVM. 17 for i in $*; do 18 processor_id=$(grep -B 15 "apicid.*: ${i}$" /proc/cpuinfo | grep "^processor" | head -n 1 | cut -d ' ' -f 2) 19 if [ -z ${processor_id} ]; then 20 continue 21 fi 22 if [ "${processor_id}" = "0" ]; then 23 echo "Warning: processor 0 can't be offline, there may be unexpect error!" >> /dev/stderr 24 continue 25 fi 26 cpu_path="/sys/devices/system/cpu/cpu${processor_id}" 27 if [ -f ${cpu_path}/online ]; then 28 online=`cat ${cpu_path}/online` 29 echo cpu${processor_id} online=${online} >> /dev/stderr 30 if [ "${online}" = "1" ]; then 31 echo 0 > ${cpu_path}/online 32 online=`cat ${cpu_path}/online` 33 # during boot time, cpu hotplug may be disabled by pci_device_probe during a pci module insmod 34 while [ "${online}" = "1" ]; do 35 sleep 1 36 echo 0 > ${cpu_path}/online 37 online=`cat ${cpu_path}/online` 38 done 39 echo ${processor_id} > /sys/devices/virtual/misc/acrn_hsm/remove_cpu 40 fi 41 fi 42 done 43} 44 45function unbind_device() { 46 physical_bdf=$1 47 48 vendor_id=$(cat /sys/bus/pci/devices/${physical_bdf}/vendor) 49 device_id=$(cat /sys/bus/pci/devices/${physical_bdf}/device) 50 51 echo $(printf "%04x %04x" ${vendor_id} ${device_id}) > /sys/bus/pci/drivers/pci-stub/new_id 52 echo ${physical_bdf} > /sys/bus/pci/devices/${physical_bdf}/driver/unbind 53 echo ${physical_bdf} > /sys/bus/pci/drivers/pci-stub/bind 54} 55 56function create_tap() { 57 # create a unique tap device for each VM 58 tap=$1 59 tap_exist=$(ip a show dev $tap) 60 if [ "$tap_exist"x != "x" ]; then 61 echo "$tap TAP device already available, reusing it." 62 else 63 ip tuntap add dev $tap mode tap 64 fi 65 66 # if acrn-br0 exists, add VM's unique tap device under it 67 br_exist=$(ip a | grep acrn-br0 | awk '{print $1}') 68 if [ "$br_exist"x != "x" -a "$tap_exist"x = "x" ]; then 69 echo "acrn-br0 bridge already exists, adding new $tap TAP device to it..." 70 ip link set "$tap" master acrn-br0 71 ip link set dev "$tap" down 72 ip link set dev "$tap" up 73 fi 74} 75 76function mount_partition() { 77 partition=$1 78 79 tmpdir=`mktemp -d` 80 mount ${partition} ${tmpdir} 81 echo ${tmpdir} 82} 83 84function unmount_partition() { 85 tmpdir=$1 86 87 umount ${tmpdir} 88 rmdir ${tmpdir} 89} 90 91# Generators of device model parameters 92 93function add_cpus() { 94 # Each parameter of this function is considered the apicid of processor (as is reported in /proc/cpuinfo) of 95 # a CPU assigned to a post-launched RTVM. 96 97 if [ "${vm_type}" = "RTVM" ] || [ "${scheduler}" = "SCHED_NOOP" ] || [ "${own_pcpu}" = "y" ]; then 98 offline_cpus $* 99 fi 100 101 cpu_list=$(local IFS=, ; echo "$*") 102 echo -n "--cpu_affinity ${cpu_list}" 103} 104 105function add_interrupt_storm_monitor() { 106 threshold_per_sec=$1 107 probe_period_in_sec=$2 108 inject_delay_in_ms=$3 109 delay_duration_in_ms=$4 110 111 echo -n "--intr_monitor ${threshold_per_sec},${probe_period_in_sec},${inject_delay_in_ms},${delay_duration_in_ms}" 112} 113 114function add_logger_settings() { 115 loggers=() 116 117 for conf in $*; do 118 logger=${conf%=*} 119 level=${conf#*=} 120 loggers+=("${logger},level=${level}") 121 done 122 123 cmd_param=$(local IFS=';' ; echo "${loggers[*]}") 124 echo -n "--logger_setting ${cmd_param}" 125} 126 127function add_virtual_device() { 128 slot=$1 129 kind=$2 130 options=$3 131 132 if [ "${kind}" = "virtio-net" ]; then 133 # Create the tap device 134 if [[ ${options} =~ tap=([^,]+) ]]; then 135 tap_conf="${BASH_REMATCH[1]}" 136 create_tap "${tap_conf}" >&2 137 fi 138 fi 139 140 if [ "${kind}" = "virtio-input" ]; then 141 options=$* 142 if [[ "${options}" =~ id:([a-zA-Z0-9_\-]*) ]]; then 143 unique_identifier="${BASH_REMATCH[1]}" 144 options=${options/",id:${unique_identifier}"/''} 145 fi 146 147 if [[ "${options}" =~ (Device name: )(.*),( Device physical path: )(.*) ]]; then 148 device_name="${BASH_REMATCH[2]}" 149 phys_name="${BASH_REMATCH[4]}" 150 local IFS=$'\n' 151 device_name_paths=$(grep -r "${device_name}" /sys/class/input/event*/device/name) 152 phys_paths=$(grep -r "${phys_name}" /sys/class/input/event*/device/phys) 153 fi 154 155 if [ -n "${device_name_paths}" ] && [ -n "${phys_paths}" ]; then 156 for device_path in ${device_name_paths}; do 157 for phys_path in ${phys_paths}; do 158 if [ "${device_path%/device*}" = "${phys_path%/device*}" ]; then 159 event_path=${device_path} 160 if [[ ${event_path} =~ event([0-9]+) ]]; then 161 event_num="${BASH_REMATCH[1]}" 162 options="/dev/input/event${event_num}" 163 break 164 fi 165 fi 166 done 167 done 168 fi 169 170 if [[ ${options} =~ event([0-9]+) ]]; then 171 echo "${options} input device path is available in the service vm." >> /dev/stderr 172 else 173 echo "${options} input device path is not found in the service vm." >> /dev/stderr 174 return 175 fi 176 177 if [ -n "${options}" ] && [ -n "${unique_identifier}" ]; then 178 options="${options},${unique_identifier}" 179 fi 180 181 fi 182 183 echo -n "-s ${slot},${kind}" 184 if [ -n "${options}" ]; then 185 echo -n ",${options}" 186 fi 187} 188 189function add_passthrough_device() { 190 slot=$1 191 physical_bdf=$2 192 options=$3 193 194 unbind_device ${physical_bdf%,*} 195 196 # bus, device and function as decimal integers 197 bus_temp=${physical_bdf#*:}; bus=$((16#${bus_temp%:*})) 198 dev_temp=${physical_bdf##*:}; dev=$((16#${dev_temp%.*})) 199 fun=$((16#${physical_bdf#*.})) 200 201 echo -n "-s " 202 printf '%s,passthru,%x/%x/%x' ${slot} ${bus} ${dev} ${fun} 203 if [ -n "${options}" ]; then 204 echo -n ",${options}" 205 fi 206} 207