-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathwindows7vm.sh
executable file
·274 lines (222 loc) · 8.65 KB
/
windows7vm.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
#!/usr/bin/env bash
# vim:ts=4:sw=4:sts=4:et:ft=sh:
set -euo pipefail
shopt -s nullglob globstar
err() {
say "$@" >&2
}
say() {
echo "[$(date +"%Y-%m-%dT%H:%M:%S%z")]: $*"
}
# QEMU 2.12 finally removed the `-usbdevice` option; `-device usb-host` has taken
# its place with a slightly different syntax. This is just a helper function
# that takes the 'old' product pairs, and returns them in the proper usb-host
# option format.
#
# vendorproductpair_to_qemu "0001:0002" #=> "vendorid=0x0001,productid=0x0002"
#
vendorproductpair_to_qemu() {
local vendorproductpair="$1"
echo -n "vendorid=0x$(echo "$vendorproductpair" | cut -c1-4),productid=0x$(echo "$vendorproductpair" | cut -c6-10)"
}
# Arbitrary VM name
vmname="win7"
# Your host username (you can run this as root, but check README and/or just edit
# this script for that)
username="$(whoami)"
# Your host machine hostname (for Synergy; note that your Synergy server
# inside the VM needs to be setup to expect this client)
hostname="$(hostname)"
# Drives being used. Make sure the Windows drive is first
drives=("$(realpath "/dev/disk/by-id/ata-M4-CT256M4SSD2_00000000123609151EB7")")
# "$(realpath "/dev/disk/by-id/ata-WDC_WD2500KS-00MJB0_WD-WCANK8625812")")
# TAP interface being created/bridged. Name it whatever
veth="vmtap0"
# Name of an existing bridge that already includes your internet connection
bridge="bridge0"
# GPU BIOS ROM (not necessary currently)
#romfile="/data/vms/nvidia_msi_gtx970.rom"
# USB keyboard ID (check lsusb)
#keyboard_id="1b1c:1b07"
#keyboard_id="045e:00db"
keyboard_id="04d9:0296"
# USB mouse ID (check lsusb)
#mouse_id="046d:c085"
mouse_id="04a5:8001"
# USB microphone ID
microphone_id="0d8c:0005"
# USB network dongle
usb_network_id="0b95:1790"
# GPU VFIO ids (check your iommu groups)
vfio_id_1="2e:00.0"
vfio_id_2="2e:00.1"
# Default primary monitor, also the one to be used by the VM
primary_monitor="DisplayPort-0"
primary_monitor_resolution="2560x1440"
# Secondary monitor that remains
secondary_monitor="DisplayPort-2"
secondary_monitor_resolution="2560x1440"
# Guest VM IP (for synergy)
vm_ip=""
if lsusb | grep -q "$usb_network_id"; then
#vm_ip="192.168.0.131"
vm_ip="192.168.178.24"
else
vm_ip="192.168.0.239"
fi
# PulseAudio output
# You can find your sink/source by running:
# $ pactl list
#pulseaudio_sink="alsa_output.pci-0000_30_00.3.analog-stereo"
#pulseaudio_sink="bluez_sink.00_16_94_21_C1_07.a2dp_sink"
# PulseAudio input
# NOTE: This is completely useless. Also passing microphone through via USB
# instead
#pulseaudio_source="alsa_input.usb-BLUE_MICROPHONE_Blue_Snowball_201705-00.analog-mono"
# Socket for QEMU console
socket="$HOME/qemu-$vmname.sock"
if [ -e "$socket" ]; then
err "✗ Bailing because a QEMU socket file exists for this VM at '$socket'."
err " Was there an unclean shutdown, or is the VM already running?"
exit 1
fi
##############################################################################
# Standard PulseAudio ENV variables
#export QEMU_AUDIO_DRV="pa"
#export QEMU_PA_SAMPLES=4096
#export QEMU_PA_SINK="$pulseaudio_sink"
#export QEMU_PA_SOURCE="$pulseaudio_source"
# Uncomment if running as root
#export QEMU_PA_SERVER="/run/user/1000/pulse/native"
##############################################################################
setup() {
say "Beginning VM setup"
# Remove these if running as root
for drive in "${drives[@]}"; do
say "---> Fixing $drive permissions"
sudo chmod g-w "$drive"
sudo chown "$username" "$drive"
done
unset drive
say "Creating $veth tap device"
sudo ip tuntap add dev "$veth" mode tap
# user $username group kvm
sudo ip link set "$veth" up
#sudo ip addr add 192.168.0.223 dev "$veth"
say "Adding $veth to $bridge"
sudo brctl addif "$bridge" "$veth"
say "Starting synergy"
synergyc --debug ERROR --name "$hostname" "$vm_ip"
say "Switching displays"
xrandr --output "$primary_monitor" --off
xrandr --output "$secondary_monitor" --mode "$secondary_monitor_resolution" --pos 0x0 --primary
#say "Setting up Looking Glass"
#sudo touch /dev/shm/looking-glass
#sudo chown "$username":kvm /dev/shm/looking-glass
#sudo chmod 660 /dev/shm/looking-glass
}
teardown() {
# Still care if things fail here, but the whole list should be run through.
set +e
say "Removing $veth from $bridge"
sudo brctl delif "$bridge" "$veth"
say "Removing $veth tap device"
sudo ip link set "$veth" down
sudo ip tuntap del dev "$veth" mode tap
say "Terminating synergy"
killall synergyc
say "Restoring displays"
xrandr --output "$primary_monitor" --mode "$primary_monitor_resolution" --pos 0x0 --primary
xrandr --output "$secondary_monitor" --mode "$secondary_monitor_resolution" --pos "$(echo -n "$primary_monitor_resolution" | sed 's/x.*//g')"x0
# These might not be necessary for you, but after shutting down the VM and
# regaining control of these USB devices, these settings (keymap, mouse sens)
# need to be re-set also...
say "Restoring USB keyboard and mouse settings (layout, rates, sensitivity)"
setxkbmap be -option caps:none
xset r rate 350 40
xset m 0 0
# Change this to the name of your mouse (if needed at all)
while read -r mouse_id; do
xinput set-prop "$mouse_id" 'libinput Accel Speed' 0 >/dev/null 2<&1
done <<< "$(xinput list | grep "ZOWIE" | awk '{print $9}' | sed "s/id=//")"
if [ -e "$socket" ]; then
say "Removing zombie socket"
rm -f "$socket"
fi
say "✓ VM teardown completed"
set -e
}
quit() {
# Install openbsd-netcat for this.
echo "system_powerdown" | nc -U "$socket"
err "✗ Terminated"
}
run_qemu() {
say "Starting QEMU"
drive_options=""
for i in "${!drives[@]}"; do
drive_options=" $drive_options -drive file=${drives[$i]},if=virtio,index=$i"
done
unset i
usb_devices="-device usb-host,$(vendorproductpair_to_qemu "$keyboard_id") -device usb-host,$(vendorproductpair_to_qemu "$mouse_id") -device usb-host,$(vendorproductpair_to_qemu "$microphone_id")"
# USB->Ethernet dongle
if lsusb | grep -q "$usb_network_id"; then
usb_devices="$usb_devices -device usb-host,$(vendorproductpair_to_qemu "$usb_network_id")"
fi
# Note that kvm=off and hv_vendor_id=whatever on the -cpu line are only
# necessary for nvidia GPUs, to prevent their drivers from self-sabotaging
# once they detect a virtualized environment (Error 43).
exec taskset -c 1,3,4,7,8-15 qemu-system-x86_64 \
-enable-kvm \
-m 8G \
-soundhw hda \
-cpu host,kvm=off,hv_relaxed,hv_spinlocks=0x1fff,hv_vapic,hv_time,hv_vendor_id=whatever \
-smp cores=6,threads=2,sockets=1,maxcpus=12 \
$drive_options \
-bios /usr/share/qemu/bios.bin \
-machine q35,accel=kvm \
-name $vmname \
-net nic,macaddr=52:54:0F:1E:3D:4C,model=virtio \
-net tap,ifname=$veth,script=no,downscript=no,vhost=on \
-usb $usb_devices \
-device usb-kbd -device usb-mouse \
-device vfio-pci,host=$vfio_id_1,multifunction=on,x-vga=on \
-device vfio-pci,host=$vfio_id_2 \
-audiodev pa,id=pa1,server=/run/user/1000/pulse/native \
-nographic \
-vga none \
-monitor unix:$socket,server,nowait
#-vcpu vcpunum=0,affinity=1 \
#-vcpu vcpunum=1,affinity=3 \
#-vcpu vcpunum=2,affinity=5 \
#-vcpu vcpunum=3,affinity=7 \
#-vcpu vcpunum=4,affinity=8 \
#-vcpu vcpunum=5,affinity=9 \
#-vcpu vcpunum=6,affinity=10 \
#-vcpu vcpunum=7,affinity=11 \
#-vcpu vcpunum=8,affinity=12 \
#-vcpu vcpunum=9,affinity=13 \
#-vcpu vcpunum=10,affinity=14 \
#-vcpu vcpunum=11,affinity=15 \
#-netdev tap,fd=25,id=hostnet0 \
#-device rtl8139,netdev=hostnet0,id=net0,mac=52:54:0F:1E:3D:4C,bus=pci.0,addr=0x3 \
#-device ivshmem-plain,memdev=ivshmem \
#-object memory-backend-file,id=ivshmem,share=on,mem-path=/dev/shm/looking-glass,size=32M \
#-device vfio-pci,host=$vfio_id_1,multifunction=on,romfile=$romfile,x-vga=on \
#-device virtio-mouse-pci,id=input0 \
#-device virtio-keyboard-pci,id=input1 \
#-object input-linux,id=mouse1,evdev=$mouse \
#-object input-linux,id=kbd1,evdev=$kbd2 \
#-object input-linux,id=kbd2,evdev=$kbd,grab_all=on,repeat=on \
#-net bridge,br=$bridge \
#-net user \
#-net user,hostfwd=tcp::42323-:24800 \
#-rtc base=localtime,clock=host \
}
##############################################################################
# Run stuff
setup
(run_qemu) &
trap "teardown" EXIT ERR INT
trap "quit" TERM
wait