-
Notifications
You must be signed in to change notification settings - Fork 1
/
dotbash_devqemu
488 lines (431 loc) · 13.8 KB
/
dotbash_devqemu
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
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
#!/bin/bash
#
# .bashrc_devqemu
#
# Bash helpers for running development builds of QEMU
#
MY_USER=`id -u`
MY_GRP=`id -g`
USERSPEC="--userspec ${MY_USER}:${MY_GRP}"
# General paramters - these don't use QEMU env variables
: ${DEVQEMU_SRC:=$(find_directories "${HOME}/lsrc/qemu/qemu.git" "${HOME}/qemu.git")}
: ${DEVQEMU_ARCH:=arm}
DEVQEMU_HOST_ARCH=`uname -m`
# linux-user
DEVQEMU_BUILD=${DEVQEMU_SRC}/${DEVQEMU_ARCH}-linux-user
DEVQEMU_BIN=qemu-${DEVQEMU_ARCH}
DEVQEMU_ROOTFS_ROOT=/home/alex/lsrc/qemu/rootfs # Root of all rootfs
# softmmu
DEVQEMU_SYSBUILD=${DEVQEMU_SRC}/${DEVQEMU_ARCH}-softmmu
DEVQEMU_SYSBIN=qemu-system-${DEVQEMU_ARCH}
DEVQEMU_IMAGES_ROOT=/home/alex/lsrc/qemu/images # Image and disk files
DEVQEMU_SYSMACH="-machine type=virt -display none -smp 1 -m 4096"
DEVQEMU_SYSCPU="-cpu cortex-a15"
DEVQEMU_SYSOUT="-serial telnet:127.0.0.1:4444 -monitor stdio"
DEVQEMU_SYSKERN=${DEVQEMU_SYSKERN:=${DEVQEMU_IMAGES_ROOT}/aarch32-current-linux-kernel-only.img}
: ${DEVQEMU_SYSKERN_CMDLINE:="console=ttyAMA0"}
: ${DEVQEMU_SYSDISK:=""}
: ${DEVQEMU_SYSDISK_ROOT="/dev/vda1"}
DEVQEMU_NETWORK="-netdev user,id=unet,hostfwd=tcp::2222-:22 -device virtio-net-device,netdev=unet"
DEVQEMU_PROFILE=""
DEVQEMU_DEBUG=""
# Controls the initial launch - enabled it relies on binfmt_misc
DEVQEMU_BINFMT=0
: ${DEVQEMU_ROOTFS:=${DEVQEMU_ROOTFS_ROOT}/debian-unstable.arm64}
# Actual QEMU Environment Variables
# you need to ensure sudo is configured to allow them through
: ${QEMU_LOG_FILENAME:=/tmp/qemu.log}
: ${QEMU_LOG:="unimp"}
# unimp,int,exec,cpu,op,out_asm
#
# Run functions:
#
# devqemu_run, devqemu_run_as_root: launch linux-user shells in a rootfs
# devqemu_sysrun: launch a softmmu instance with a given kernel
#
# Return the "correct" path for a given binfmt binary
function devqemu_copy_binfmt_helper
{
BINFMT_HELPER=`update-binfmts --find $1`
# Check the helper matches our arch binary
HELPER_BASE=$(basename ${BINFMT_HELPER})
if [ "${HELPER_BASE}" != "${DEVQEMU_BIN}" ]; then
echo "/bin/false"
return
fi
HELPER_DIR=$(dirname ${BINFMT_HELPER})
mkdir -p ${DEVQEMU_ROOTFS}/${HELPER_DIR}
sudo cp ${DEVQEMU_BUILD}/${DEVQEMU_BIN} ${DEVQEMU_ROOTFS}/${HELPER_DIR}
echo "${BINFMT_HELPER}"
}
function devqemu_run
{
CMD=$(devqemu_copy_binfmt_helper ${DEVQEMU_ROOTFS}/$1)
if [ ${DEVQEMU_BINFMT} -eq 0 ]; then
echo "calling direct"
else
CMD=$1
shift
fi
echo "Using chroot: ${DEVQEMU_ROOTFS}"
export QEMU_LOG
export QEMU_LOG_FILENAME
echo "Env: QEMU_LOG=${QEMU_LOG}, QEMU_LOG_FILENAME=${QEMU_LOG_FILENAME}"
echo "Running: ${CMD} with $# args ($@)"
sudo ${DEVQEMU_PROFILE} chroot ${USERSPEC} ${DEVQEMU_ROOTFS} ${DEVQEMU_DEBUG} ${CMD} "$@"
}
function devqemu_run_as_root
{
echo "Copying ${DEVQEMU_BUILD}/${DEVQEMU_BIN} to ${DEVQEMU_ROOTFS}/bin/"
sudo cp ${DEVQEMU_BUILD}/${DEVQEMU_BIN} ${DEVQEMU_ROOTFS}/bin/
CMD="/bin/${DEVQEMU_BIN}"
echo "Using chroot: ${DEVQEMU_ROOTFS}"
export QEMU_LOG
export QEMU_LOG_FILENAME
echo "Env: QEMU_LOG=${QEMU_LOG}, QEMU_LOG_FILENAME=${QEMU_LOG_FILENAME}"
echo "Running: ${CMD} with $# args ($@)"
FINAL_CMD="${DEVQEMU_PROFILE} chroot ${DEVQEMU_ROOTFS} ${DEVQEMU_DEBUG} ${CMD} $@"
echo "sudo ${FINAL_CMD}"
sudo ${FINAL_CMD}
}
function devqemu_sysrun
{
QEMU_CMD="${DEVQEMU_SYSBUILD}/${DEVQEMU_SYSBIN}"
echo "Using system: ${QEMU_CMD}"
export QEMU_LOG
export QEMU_LOG_FILENAME
echo "Env: QEMU_LOG=${QEMU_LOG}, QEMU_LOG_FILENAME=${QEMU_LOG_FILENAME}"
if [ -n "${DEVQEMU_PRELOAD}" ]; then
export LD_PRELOAD="${DEVQEMU_PRELOAD}"
echo " LD_PRELOAD=${DEVQEMU_PRELOAD}"
fi
# Build up the run as an array, this keeps the arguments distinct to avoid having to mess with eval or other whitespace or quote tricks
QEMU_RUN=(${QEMU_CMD})
QEMU_RUN+=(${DEVQEMU_SYSMACH} ${DEVQEMU_SYSCPU} ${DEVQEMU_SYSOUT} ${DEVQEMU_NETWORK})
if [ -n "${DEVQEMU_SYSDISK}" ]; then
QEMU_RUN+=(-drive "file=${DEVQEMU_SYSDISK},id=myblock,index=0,if=none" -device "virtio-blk-device,drive=myblock")
QEMU_RUN+=(-append "${DEVQEMU_SYSKERN_CMDLINE} root=${DEVQEMU_SYSDISK_ROOT}")
else
QEMU_RUN+=(-append "${DEVQEMU_SYSKERN_CMDLINE}")
fi
QEMU_RUN+=(-kernel ${DEVQEMU_SYSKERN})
QEMU_RUN+=($@)
echo "Running \"\${QEMU_RUN[@]}\": ${QEMU_RUN[@]}"
${DEVQEMU_PROFILE} ${DEVQEMU_DEBUG} "${QEMU_RUN[@]}"
unset LD_PRELOAD
}
# Run an arbitary kernel image without the auto-magic gubbins, useful for KVM UNIT test type things
function devqemu_sysbin
{
QEMU_CMD="${DEVQEMU_SYSBUILD}/${DEVQEMU_SYSBIN}"
echo "Using system: ${QEMU_CMD}"
export QEMU_LOG
export QEMU_LOG_FILENAME
echo "Env: QEMU_LOG=${QEMU_LOG}, QEMU_LOG_FILENAME=${QEMU_LOG_FILENAME}"
if [ -n "${DEVQEMU_PRELOAD}" ]; then
export LD_PRELOAD="${DEVQEMU_PRELOAD}"
echo " LD_PRELOAD=${DEVQEMU_PRELOAD}"
fi
QEMU_RESULT_CHAR="-device virtio-serial-device -device virtconsole,chardev=ctd -chardev testdev,id=ctd"
QEMU_CMDLINE="${DEVQEMU_SYSMACH} ${DEVQEMU_SYSCPU} ${DEVQEMU_SYSOUT} ${QEMU_RESULT_CHAR} -kernel"
echo "Running: ${QEMU_CMD} ${QEMU_CMDLINE} ${KERN_CMD[@]} $@"
${DEVQEMU_PROFILE} ${DEVQEMU_DEBUG} ${QEMU_CMD} ${QEMU_CMDLINE} $@
unset LD_PRELOAD
}
#
# Common configuration functions for both user and system emulation
#
# Set the target architecture
function devqemu_arch
{
echo "Current ARCH=${DEVQEMU_ARCH}"
if [[ -n "$1" && -d "${DEVQEMU_SRC}/$1-softmmu" ]]; then
DEVQEMU_ARCH=${1}
else
read -e -p "ARCH:" NEW_ARCH
DEVQEMU_ARCH=${NEW_ARCH}
fi
DEVQEMU_BUILD=${DEVQEMU_SRC}/${DEVQEMU_ARCH}-linux-user
DEVQEMU_BIN=qemu-${DEVQEMU_ARCH}
DEVQEMU_SYSBUILD=${DEVQEMU_SRC}/${DEVQEMU_ARCH}-softmmu
DEVQEMU_SYSBIN=qemu-system-${DEVQEMU_ARCH}
case "${DEVQEMU_ARCH}" in
aarch64*)
DEVQEMU_SYSCPU="-cpu cortex-a57"
;;
arm*)
DEVQEMU_SYSCPU="-cpu cortex-a15"
;;
*)
# this will most likely fail
DEVQEMU_SYSCPU="-cpu ${DEVQEMU_ARCH}"
;;
esac
echo "New ARCH=${DEVQEMU_ARCH} (${DEVQEMU_SYSCPU})"
echo "With ${DEVQEMU_BIN} from ${DEVQEMU_BUILD}"
echo "With ${DEVQEMU_SYSBIN} from ${DEVQEMU_SYSBUILD}"
}
function devqemu_profile
{
OLD_DEVQEMU_PROFILE=${DEVQEMU_PROFILE}
if [[ -z "$@" ]]; then
unset DEVQEMU_PROFILE
echo "Disabled profiling of qemu"
else
DEVQEMU_PROFILE="$@"
echo "Using DEVQEMU_PROFILE=${DEVQEMU_PROFILE} (was ${OLD_DEVQEMU_PROFILE})"
fi
}
function devqemu_binfmt
{
if [ ${DEVQEMU_BINFMT} -eq 0 ]; then
DEVQEMU_BINFMT=1
else
DEVQEMU_BINFMT=0
fi
echo "DEVQEMU_BINFMT=${DEVQEMU_BINFMT}"
}
#
# Enable debugging of QEMU invocation
#
function devqemu_debug
{
OLD_DEVQEMU_DEBUG="${DEVQEMU_DEBUG}"
unset DEVQEMU_PRELOAD
if [[ -z "$@" ]]; then
unset DEVQEMU_DEBUG
echo "Disabled debugging qemu"
else
case "${1}" in
gdb*)
DEVQEMU_DEBUG="gdb --args "
;;
valgrind*)
DEVQEMU_DEBUG="valgrind -- "
;;
valmem*)
DEVQEMU_DEBUG="valgrind --smc-check=all-non-file --leak-check=full --log-file=valgrind-mem.log -- "
;;
mutrace*)
DEVQEMU_PRELOAD="/usr/lib/libbfd.so"
DEVQEMU_DEBUG="mutrace -d --hash-size=6000 -- "
;;
time*)
DEVQEMU_DEBUG="time "
;;
*)
# this will most likely fail
DEVQEMU_DEBUG="$@"
;;
esac
echo "Using DEVQEMU_DEBUG=${DEVQEMU_DEBUG} (was ${OLD_DEVQEMU_DEBUG})"
fi
}
function devqemu_log
{
OLD_QEMU_LOG=${QEMU_LOG}
if [ -z "$@" ]; then
unset QEMU_LOG
echo "Disabled QEMU_LOG"
else
QEMU_LOG=$@
echo "Set QEMU_LOG to ${QEMU_LOG} (were ${OLD_QEMU_LOG})"
fi
}
function devqemu_logfile
{
OLD_QEMU_LOG_FILENAME=${QEMU_LOG_FILENAME}
if [ -z "$@" ]; then
unset QEMU_LOG_FILENAME
echo "Disabled QEMU_LOG_FILENAME (debug will go to stderr)"
else
QEMU_LOG_FILENAME=$@
echo "Set QEMU_LOG_FILENAME to ${QEMU_LOG_FILENAME} (was ${OLD_QEMU_LOG_FILENAME})"
fi
}
#
# linux-user specific configuration
#
function devqemu_rootfs
{
OLD_DEVQEMU_ROOTFS=${DEVQEMU_ROOTFS}
CURRENT_PWD=`pwd`
if [[ -n "$1" && -d "${CURRENT_PWD}/$1" ]]; then
DEVQEMU_ROOTFS=${CURRENT_PWD}/${1%/}
else
cd ${DEVQEMU_ROOTFS_ROOT}
DIRS=`compgen -d`
read -e -p "dir:" NEW_ROOTFS
DEVQEMU_ROOTFS=${DEVQEMU_ROOTFS_ROOT}/${NEW_ROOTFS}
cd -
fi
echo "Set rootfs to ${DEVQEMU_ROOTFS} (was ${OLD_DEVQEMU_ROOTFS})"
}
function do_bind_mount
{
SRC=$1
DST=$2
for i in `cat /proc/mounts | cut -d' ' -f2`; do
if [ "x${DST}" = "x$i" ]; then
echo "Skipping already mounted ${DST}"
return
fi
done
sudo mkdir -p ${DST}
sudo mount -o bind ${SRC} ${DST}
echo "Mounted ${SRC} to ${DST}"
}
# Helper function to bind system dirs to a rootfs, also useful for general chroot stuff
function devqemu_bind_system
{
local chroot=$1
if [ -d $chroot ]; then
# Kernel pseudo filesystems
do_bind_mount /proc ${chroot}/proc
do_bind_mount /sys ${chroot}/sys
do_bind_mount /dev ${chroot}/dev
do_bind_mount /dev/pts ${chroot}/dev/pts
else
echo "need to specify a rootfs"
fi
}
function devqemu_setup_mounts
{
# Useful host hooks
do_bind_mount /home ${DEVQEMU_ROOTFS}/home
do_bind_mount /home/alex/lsrc/qemu/risu.git ${DEVQEMU_ROOTFS}/root/risu/
do_bind_mount /etc ${DEVQEMU_ROOTFS}/host-etc
# Multi-arch bits
do_bind_mount /lib/x86_64-linux-gnu ${DEVQEMU_ROOTFS}/lib/x86_64-linux-gnu
do_bind_mount /usr/lib/x86_64-linux-gnu ${DEVQEMU_ROOTFS}/usr/lib/x86_64-linux-gnu
echo "Setting up ld-linux loaders"
sudo mkdir -p ${DEVQEMU_ROOTFS}/lib64
for link in /lib64/*; do
linkname=`basename $link`
linkpath=`readlink $link`
echo "linking ${DEVQEMU_ROOTFS}/lib64/$linkname to $linkpath"
sudo ln -s $linkpath ${DEVQEMU_ROOTFS}/lib64/$linkname
done
if [ -n "$DEVQEMU_DEBUG" ]; then
echo "Copying valgrind"
mkdir -p ${DEVQEMU_ROOTFS}/usr/bin
cp /usr/bin/valgrind* ${DEVQEMU_ROOTFS}/usr/bin
fi
# Magic dirs
do_bind_mount /proc ${DEVQEMU_ROOTFS}/proc
do_bind_mount /dev ${DEVQEMU_ROOTFS}/dev
do_bind_mount /dev/pts ${DEVQEMU_ROOTFS}/dev/pts
do_bind_mount /tmp ${DEVQEMU_ROOTFS}/tmp
}
function devqemu_clear_mounts
{
sudo umount ${DEVQEMU_ROOTFS}/home
sudo umount ${DEVQEMU_ROOTFS}/root/risu/
sudo umount ${DEVQEMU_ROOTFS}/host-etc
sudo umount ${DEVQEMU_ROOTFS}/lib/x86_64-linux-gnu
sudo umount ${DEVQEMU_ROOTFS}/usr/lib/x86_64-linux-gnu
sudo umount ${DEVQEMU_ROOTFS}/proc
sudo umount ${DEVQEMU_ROOTFS}/dev
sudo umount ${DEVQEMU_ROOTFS}/dev/pts
sudo umount ${DEVQEMU_ROOTFS}/tmp
}
function devqemu_clear_all_mounts
{
for i in `cat /proc/mounts | cut -d' ' -f2`; do
if [[ $i == ${DEVQEMU_ROOTFS_ROOT}* ]]; then
sudo umount $i
fi
done
}
#
# System Emulation specific configuration
# select the disk
function devqemu_sysdisk
{
echo "Current DISK=${DEVQEMU_SYSDISK}"
if [[ -n "$1" && -f "$1" ]]; then
DEVQEMU_SYSDISK=$1
elif [[ -n "$1" && -d "${CURRENT_PWD}/$1" ]]; then
DEVQEMU_SYSDISK=${CURRENT_PWD}/${1%/}
else
cd ${DEVQEMU_IMAGES_ROOT}
DIRS=`compgen -f -G {*.qcow2}`
read -e -p "disk:" NEW_DISK
if [ -z $NEW_DISK ]; then
unset DEVQEMU_SYSDISK
else
DEVQEMU_SYSDISK=${DEVQEMU_IMAGES_ROOT}/${NEW_DISK}
fi
cd -
fi
echo "Set disk to ${DEVQEMU_SYSDISK}"
}
# Set the kernel image
function devqemu_syskern_cmdline
{
OLD_DEVQEMU_SYSKERN_CMDLINE=${DEVQEMU_SYSKERN_CMDLINE}
if [[ -n "$1" ]]; then
DEVQEMU_SYSKERN_CMDLINE="$@"
fi
echo "Set command line to ${DEVQEMU_SYSKERN_CMDLINE} (was ${OLD_DEVQEMU_SYSKERN_CMDLINE})"
}
function devqemu_syskern
{
OLD_DEVQEMU_SYSKERN=${DEVQEMU_SYSKERN}
if [[ -n "$1" && -f "$1" ]]; then
DEVQEMU_SYSKERN=${1}
else
cd ${DEVQEMU_IMAGES_ROOT}
DIRS=`compgen -f -G {*.img,*.axf}`
read -e -p "image:" NEW_KERN
DEVQEMU_SYSKERN=${DEVQEMU_IMAGES_ROOT}/${NEW_KERN}
cd -
fi
echo "Set kernel to ${DEVQEMU_SYSKERN} (was ${OLD_DEVQEMU_SYSKERN})"
}
function kill_qemu
{
DEVQEMU_PID_CMD="ps -o comm,pid -C $DEVQEMU_BIN | awk '\$1 == \"$DEVQEMU_BIN\" { print \$2 }'"
echo "DEVQEMU_PID_CMD=${DEVQEMU_PID_CMD}"
DEVQEMU_PID=`${DEVQEMU_PID_CMD}`
echo "kill -9 $DEVQEMU_PID"
}
function devqemu_help
{
$all_fns=`compgen -A function devqemu_`
echo <<EOF
The devqemu shell environment is a set of scripts for running development versions
of QEMU from the shell. The following functions are available:
$all_fns
EOF
}
# Dump the current status
function devqemu_status
{
echo "Current ARCH=${DEVQEMU_ARCH} (${DEVQEMU_SYSCPU})"
echo ""
echo "User Mode:"
echo "With ${DEVQEMU_BIN} from ${DEVQEMU_BUILD}"
echo "Copying for binfmt_misc: ${DEVQEMU_BINFMT}"
echo ""
echo "System Mode:"
echo "With ${DEVQEMU_SYSBIN} from ${DEVQEMU_SYSBUILD}"
echo "Current kernel: ${DEVQEMU_SYSKERN}"
echo " cmdline: ${DEVQEMU_SYSKERN_CMDLINE}"
if [ -n "${DEVQEMU_SYSDISK}" ]; then
echo "Current disk image: ${DEVQEMU_SYSDISK}"
fi
}
function devqemu
{
$cmdfn=devqemu_${1}
echo "testing: $cmdfn"
if [[ "type -t $cmdfn > /dev/null" ]]; then
$cmdfn
else
devqemu_help
fi
}
# reload alisas
alias .qemu=". ~/.bash_devqemu"
alias .devqemu=". ~/.bash_devqemu"