style(quickemu): correctly indent case statements
This commit is contained in:
parent
d7cc6e8115
commit
da6aa9fb2c
793
quickemu
793
quickemu
|
@ -299,14 +299,10 @@ function vm_boot() {
|
|||
if [ -e /sys/devices/system/cpu/smt/control ] && [ "${GUEST_CPU_CORES}" -ge 2 ]; then
|
||||
HOST_CPU_SMT=$(cat /sys/devices/system/cpu/smt/control)
|
||||
case ${HOST_CPU_SMT} in
|
||||
on)
|
||||
GUEST_CPU_THREADS=2
|
||||
GUEST_CPU_LOGICAL_CORES=$(( GUEST_CPU_CORES / GUEST_CPU_THREADS ))
|
||||
;;
|
||||
*)
|
||||
GUEST_CPU_THREADS=1
|
||||
GUEST_CPU_LOGICAL_CORES=${GUEST_CPU_CORES}
|
||||
;;
|
||||
on) GUEST_CPU_THREADS=2
|
||||
GUEST_CPU_LOGICAL_CORES=$(( GUEST_CPU_CORES / GUEST_CPU_THREADS ));;
|
||||
*) GUEST_CPU_THREADS=1
|
||||
GUEST_CPU_LOGICAL_CORES=${GUEST_CPU_CORES};;
|
||||
esac
|
||||
else
|
||||
GUEST_CPU_THREADS=1
|
||||
|
@ -400,29 +396,25 @@ function vm_boot() {
|
|||
# https://bugzilla.redhat.com/show_bug.cgi?id=1929357#c5
|
||||
if [ -n "${EFI_CODE}" ] || [ ! -e "${EFI_CODE}" ]; then
|
||||
case ${secureboot} in
|
||||
on)
|
||||
# shellcheck disable=SC2054,SC2140
|
||||
ovmfs=("/usr/share/OVMF/OVMF_CODE_4M.secboot.fd","/usr/share/OVMF/OVMF_VARS_4M.fd" \
|
||||
"/usr/share/edk2/ovmf/OVMF_CODE.secboot.fd","/usr/share/edk2/ovmf/OVMF_VARS.fd" \
|
||||
"/usr/share/OVMF/x64/OVMF_CODE.secboot.fd","/usr/share/OVMF/x64/OVMF_VARS.fd" \
|
||||
"/usr/share/edk2-ovmf/OVMF_CODE.secboot.fd","/usr/share/edk2-ovmf/OVMF_VARS.fd" \
|
||||
"/usr/share/qemu/ovmf-x86_64-smm-ms-code.bin","/usr/share/qemu/ovmf-x86_64-smm-ms-vars.bin" \
|
||||
"/usr/share/qemu/edk2-x86_64-secure-code.fd","/usr/share/qemu/edk2-x86_64-code.fd" \
|
||||
"/usr/share/edk2-ovmf/x64/OVMF_CODE.secboot.fd","/usr/share/edk2-ovmf/x64/OVMF_VARS.fd"
|
||||
)
|
||||
;;
|
||||
*)
|
||||
# shellcheck disable=SC2054,SC2140
|
||||
ovmfs=("/usr/share/OVMF/OVMF_CODE_4M.fd","/usr/share/OVMF/OVMF_VARS_4M.fd" \
|
||||
"/usr/share/edk2/ovmf/OVMF_CODE.fd","/usr/share/edk2/ovmf/OVMF_VARS.fd" \
|
||||
"/usr/share/OVMF/OVMF_CODE.fd","/usr/share/OVMF/OVMF_VARS.fd" \
|
||||
"/usr/share/OVMF/x64/OVMF_CODE.fd","/usr/share/OVMF/x64/OVMF_VARS.fd" \
|
||||
"/usr/share/edk2-ovmf/OVMF_CODE.fd","/usr/share/edk2-ovmf/OVMF_VARS.fd" \
|
||||
"/usr/share/qemu/ovmf-x86_64-4m-code.bin","/usr/share/qemu/ovmf-x86_64-4m-vars.bin" \
|
||||
"/usr/share/qemu/edk2-x86_64-code.fd","/usr/share/qemu/edk2-x86_64-code.fd" \
|
||||
"/usr/share/edk2-ovmf/x64/OVMF_CODE.fd","/usr/share/edk2-ovmf/x64/OVMF_VARS.fd"
|
||||
)
|
||||
;;
|
||||
on) # shellcheck disable=SC2054,SC2140
|
||||
ovmfs=("/usr/share/OVMF/OVMF_CODE_4M.secboot.fd","/usr/share/OVMF/OVMF_VARS_4M.fd" \
|
||||
"/usr/share/edk2/ovmf/OVMF_CODE.secboot.fd","/usr/share/edk2/ovmf/OVMF_VARS.fd" \
|
||||
"/usr/share/OVMF/x64/OVMF_CODE.secboot.fd","/usr/share/OVMF/x64/OVMF_VARS.fd" \
|
||||
"/usr/share/edk2-ovmf/OVMF_CODE.secboot.fd","/usr/share/edk2-ovmf/OVMF_VARS.fd" \
|
||||
"/usr/share/qemu/ovmf-x86_64-smm-ms-code.bin","/usr/share/qemu/ovmf-x86_64-smm-ms-vars.bin" \
|
||||
"/usr/share/qemu/edk2-x86_64-secure-code.fd","/usr/share/qemu/edk2-x86_64-code.fd" \
|
||||
"/usr/share/edk2-ovmf/x64/OVMF_CODE.secboot.fd","/usr/share/edk2-ovmf/x64/OVMF_VARS.fd"
|
||||
);;
|
||||
*) # shellcheck disable=SC2054,SC2140
|
||||
ovmfs=("/usr/share/OVMF/OVMF_CODE_4M.fd","/usr/share/OVMF/OVMF_VARS_4M.fd" \
|
||||
"/usr/share/edk2/ovmf/OVMF_CODE.fd","/usr/share/edk2/ovmf/OVMF_VARS.fd" \
|
||||
"/usr/share/OVMF/OVMF_CODE.fd","/usr/share/OVMF/OVMF_VARS.fd" \
|
||||
"/usr/share/OVMF/x64/OVMF_CODE.fd","/usr/share/OVMF/x64/OVMF_VARS.fd" \
|
||||
"/usr/share/edk2-ovmf/OVMF_CODE.fd","/usr/share/edk2-ovmf/OVMF_VARS.fd" \
|
||||
"/usr/share/qemu/ovmf-x86_64-4m-code.bin","/usr/share/qemu/ovmf-x86_64-4m-vars.bin" \
|
||||
"/usr/share/qemu/edk2-x86_64-code.fd","/usr/share/qemu/edk2-x86_64-code.fd" \
|
||||
"/usr/share/edk2-ovmf/x64/OVMF_CODE.fd","/usr/share/edk2-ovmf/x64/OVMF_VARS.fd"
|
||||
);;
|
||||
esac
|
||||
# Attempt each EFI_CODE file one by one, selecting the corresponding code and vars
|
||||
# when an existing file is found.
|
||||
|
@ -480,178 +472,168 @@ function vm_boot() {
|
|||
|
||||
# Make any OS specific adjustments
|
||||
case ${guest_os} in
|
||||
batocera|*bsd|freedos|haiku|linux*|*solaris)
|
||||
CPU="-cpu host,kvm=on"
|
||||
if [ "${HOST_CPU_VENDOR}" == "AuthenticAMD" ]; then
|
||||
CPU="${CPU},topoext"
|
||||
fi
|
||||
batocera|*bsd|freedos|haiku|linux*|*solaris)
|
||||
CPU="-cpu host,kvm=on"
|
||||
if [ "${HOST_CPU_VENDOR}" == "AuthenticAMD" ]; then
|
||||
CPU="${CPU},topoext"
|
||||
fi
|
||||
|
||||
if [ "${guest_os}" == "freebsd" ] || [ "${guest_os}" == "ghostbsd" ]; then
|
||||
MOUSE="usb"
|
||||
elif [ "${guest_os}" == "batocera" ] || [ "${guest_os}" == "freedos" ] || [ "${guest_os}" == "haiku" ]; then
|
||||
if [ "${guest_os}" == "freebsd" ] || [ "${guest_os}" == "ghostbsd" ]; then
|
||||
MOUSE="usb"
|
||||
elif [ "${guest_os}" == "batocera" ] || [ "${guest_os}" == "freedos" ] || [ "${guest_os}" == "haiku" ]; then
|
||||
MACHINE_TYPE="pc"
|
||||
NET_DEVICE="rtl8139"
|
||||
fi
|
||||
|
||||
if [ "${guest_os}" == "freedos" ] ; then
|
||||
# fix for #382
|
||||
SMM="on"
|
||||
SOUND_CARD="sb16"
|
||||
fi
|
||||
|
||||
if [[ "${guest_os}" == *"solaris" ]]; then
|
||||
MACHINE_TYPE="pc"
|
||||
USB_CONTROLLER="xhci"
|
||||
SOUND_CARD="ac97"
|
||||
fi
|
||||
|
||||
if [ -z "${disk_size}" ]; then
|
||||
disk_size="16G"
|
||||
fi
|
||||
;;
|
||||
kolibrios|reactos)
|
||||
CPU="-cpu qemu32,kvm=on"
|
||||
if [ "${HOST_CPU_VENDOR}" == "AuthenticAMD" ]; then
|
||||
CPU="${CPU},topoext"
|
||||
fi
|
||||
MACHINE_TYPE="pc"
|
||||
NET_DEVICE="rtl8139"
|
||||
fi
|
||||
case ${guest_os} in
|
||||
kolibrios) NET_DEVICE="rtl8139";;
|
||||
reactos) NET_DEVICE="e1000"
|
||||
KEYBOARD="ps2";;
|
||||
esac
|
||||
;;
|
||||
macos)
|
||||
# https://www.nicksherlock.com/2020/04/installing-macos-catalina-on-proxmox-with-opencore/
|
||||
# https://www.nicksherlock.com/2022/10/installing-macos-13-ventura-on-proxmox/
|
||||
# noTSX stops cpuid errors https://duckduckgo.com/?t=ffab&q=CPUID.07H%3AEBX.rtm+%5Bbit+11%5D&ia=web also cited by NickSherlock for Ventura install
|
||||
# Penryn https://github.com/search?q=repo%3Akholia%2FOSX-KVM%20%20GenuineIntel&type=code
|
||||
# https://en.wikipedia.org/wiki/MacOS_version_history#Releases
|
||||
# quickget current list: mojave catalina big-sur monterey ventura sonoma
|
||||
# A CPU with SSE4.1 support is required for >= macOS Sierra
|
||||
# A CPU with SSE4.2 support is required for >= macOS Catalina
|
||||
# A CPU with AVX2 support is required for >= macOS Ventura
|
||||
case ${macos_release} in
|
||||
ventura|sonoma)
|
||||
if check_cpu_flag sse4_2 && check_cpu_flag avx2; then
|
||||
CPU="-cpu Haswell-v4,kvm=on,vendor=GenuineIntel,+avx,+avx2,+sse,+sse2,+sse3,+sse4.2,vmware-cpuid-freq=on"
|
||||
else
|
||||
echo "ERROR! macOS ${macos_release} requires a CPU with SSE 4.2 and AVX2 support."
|
||||
exit 1
|
||||
fi;;
|
||||
catalina|big-sur|monterey)
|
||||
if check_cpu_flag sse4_2; then
|
||||
CPU="-cpu Haswell-v4,kvm=on,vendor=GenuineIntel,+avx,+sse,+sse2,+sse3,+sse4.2,vmware-cpuid-freq=on"
|
||||
else
|
||||
echo "ERROR! macOS ${macos_release} requires a CPU with SSE 4.2 support."
|
||||
exit 1
|
||||
fi;;
|
||||
*)
|
||||
if check_cpu_flag sse4_1; then
|
||||
CPU="-cpu Penryn,kvm=on,vendor=GenuineIntel,+avx,+sse,+sse2,+sse3,+sse4.1,vmware-cpuid-freq=on"
|
||||
else
|
||||
echo "ERROR! macOS ${macos_release} requires a CPU with SSE 4.1 support."
|
||||
exit 1
|
||||
fi;;
|
||||
esac
|
||||
|
||||
if [ "${guest_os}" == "freedos" ] ; then
|
||||
# fix for #382
|
||||
# https://www.techpowerup.com/cpu-specs/xeon-w-2140b.c2953 8 cores 16 threads # skylake server
|
||||
# https://en.wikipedia.org/wiki/IMac_Pro#Technical_specifications Orig: High Sierra Max: Sonoma
|
||||
# https://en.wikipedia.org/wiki/MacOS#Hardware_compatibility needs 8GB RAM
|
||||
# https://qemu.readthedocs.io/en/v9.0.0/system/qemu-cpu-models.html#important-cpu-features-for-amd-x86-hosts
|
||||
# https://www.reddit.com/r/hackintosh/comments/141wnjk/state_of_macos_14_sonoma_on_x86/
|
||||
for FLAG in abm adx aes amd-ssbd bmi1 bmi2 cx8 eist ept f16c fma invtsc \
|
||||
mmx movbe mpx pdpe1gb smep vaes vbmi2 vpclmulqdq \
|
||||
xgetbv1 xsave xsaveopt; do
|
||||
if check_cpu_flag "${FLAG}"; then
|
||||
CPU+=",+${FLAG}"
|
||||
fi
|
||||
done
|
||||
|
||||
OSK=$(echo "bheuneqjbexolgurfrjbeqfthneqrqcyrnfrqbagfgrny(p)NccyrPbzchgreVap" | tr 'A-Za-z' 'N-ZA-Mn-za-m')
|
||||
# Disable S3 support in the VM to prevent macOS suspending during install
|
||||
GUEST_TWEAKS="-global kvm-pit.lost_tick_policy=discard -global ICH9-LPC.disable_s3=1 -device isa-applesmc,osk=${OSK}"
|
||||
|
||||
# Disable High Precision Timer
|
||||
if [ "${QEMU_VER_SHORT}" -ge 70 ]; then
|
||||
MACHINE_TYPE+=",hpet=off"
|
||||
else
|
||||
GUEST_TWEAKS+=" -no-hpet"
|
||||
fi
|
||||
|
||||
# Tune Qemu optimisations based on the macOS release, or fallback to lowest
|
||||
# common supported options if none is specified.
|
||||
# * VirtIO Block Media doesn't work in High Sierra (at all) or the Mojave (Recovery Image)
|
||||
# * VirtIO Network is supported since Big Sur
|
||||
# * VirtIO Memory Balloning is supported since Big Sur (https://pmhahn.github.io/virtio-balloon/)
|
||||
# * VirtIO RNG is supported since Big Sur, but exposed to all guests by default.
|
||||
case ${macos_release} in
|
||||
catalina)
|
||||
BALLOON=""
|
||||
MAC_DISK_DEV="virtio-blk-pci"
|
||||
NET_DEVICE="vmxnet3"
|
||||
USB_HOST_PASSTHROUGH_CONTROLLER="usb-ehci";;
|
||||
big-sur|monterey|ventura|sonoma)
|
||||
BALLOON="-device virtio-balloon"
|
||||
MAC_DISK_DEV="virtio-blk-pci"
|
||||
NET_DEVICE="virtio-net"
|
||||
USB_HOST_PASSTHROUGH_CONTROLLER="nec-usb-xhci"
|
||||
GUEST_TWEAKS="${GUEST_TWEAKS} -global nec-usb-xhci.msi=off"
|
||||
USB_CONTROLLER="xhci";;
|
||||
*)
|
||||
# Backwards compatibility if no macos_release is specified.
|
||||
# Also safe catch all for High Sierra and Mojave
|
||||
BALLOON=""
|
||||
MAC_DISK_DEV="ide-hd,bus=ahci.2"
|
||||
NET_DEVICE="vmxnet3"
|
||||
USB_HOST_PASSTHROUGH_CONTROLLER="usb-ehci";;
|
||||
esac
|
||||
|
||||
if [ -z "${disk_size}" ]; then
|
||||
disk_size="96G"
|
||||
fi
|
||||
;;
|
||||
windows|windows-server)
|
||||
if [ "${QEMU_VER_SHORT}" -gt 60 ]; then
|
||||
CPU="-cpu host,kvm=on,+hypervisor,+invtsc,l3-cache=on,migratable=no,hv_passthrough"
|
||||
else
|
||||
CPU="-cpu host,kvm=on,+hypervisor,+invtsc,l3-cache=on,migratable=no,hv_frequencies,kvm_pv_unhalt,hv_reenlightenment,hv_relaxed,hv_spinlocks=8191,hv_stimer,hv_synic,hv_time,hv_vapic,hv_vendor_id=1234567890ab,hv_vpindex"
|
||||
fi
|
||||
if [ "${HOST_CPU_VENDOR}" == "AuthenticAMD" ]; then
|
||||
CPU="${CPU},topoext"
|
||||
fi
|
||||
# Disable S3 support in the VM to ensure Windows can boot with SecureBoot enabled
|
||||
# - https://wiki.archlinux.org/title/QEMU#VM_does_not_boot_when_using_a_Secure_Boot_enabled_OVMF
|
||||
GUEST_TWEAKS="-global kvm-pit.lost_tick_policy=discard -global ICH9-LPC.disable_s3=1"
|
||||
|
||||
# Disable High Precision Timer
|
||||
if [ "${QEMU_VER_SHORT}" -ge 70 ]; then
|
||||
MACHINE_TYPE+=",hpet=off"
|
||||
else
|
||||
GUEST_TWEAKS+=" -no-hpet"
|
||||
fi
|
||||
|
||||
if [ -z "${disk_size}" ]; then
|
||||
disk_size="64G"
|
||||
fi
|
||||
SMM="on"
|
||||
SOUND_CARD="sb16"
|
||||
fi
|
||||
|
||||
if [[ "${guest_os}" == *"solaris" ]]; then
|
||||
MACHINE_TYPE="pc"
|
||||
USB_CONTROLLER="xhci"
|
||||
SOUND_CARD="ac97"
|
||||
fi
|
||||
|
||||
if [ -z "${disk_size}" ]; then
|
||||
disk_size="16G"
|
||||
fi
|
||||
;;
|
||||
kolibrios|reactos)
|
||||
CPU="-cpu qemu32,kvm=on"
|
||||
if [ "${HOST_CPU_VENDOR}" == "AuthenticAMD" ]; then
|
||||
CPU="${CPU},topoext"
|
||||
fi
|
||||
MACHINE_TYPE="pc"
|
||||
case ${guest_os} in
|
||||
kolibrios) NET_DEVICE="rtl8139";;
|
||||
reactos)
|
||||
NET_DEVICE="e1000"
|
||||
KEYBOARD="ps2"
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
macos)
|
||||
# https://www.nicksherlock.com/2020/04/installing-macos-catalina-on-proxmox-with-opencore/
|
||||
# https://www.nicksherlock.com/2022/10/installing-macos-13-ventura-on-proxmox/
|
||||
# noTSX stops cpuid errors https://duckduckgo.com/?t=ffab&q=CPUID.07H%3AEBX.rtm+%5Bbit+11%5D&ia=web also cited by NickSherlock for Ventura install
|
||||
# Penryn https://github.com/search?q=repo%3Akholia%2FOSX-KVM%20%20GenuineIntel&type=code
|
||||
# https://en.wikipedia.org/wiki/MacOS_version_history#Releases
|
||||
# quickget current list: mojave catalina big-sur monterey ventura sonoma
|
||||
# A CPU with SSE4.1 support is required for >= macOS Sierra
|
||||
# A CPU with SSE4.2 support is required for >= macOS Catalina
|
||||
# A CPU with AVX2 support is required for >= macOS Ventura
|
||||
case ${macos_release} in
|
||||
ventura|sonoma)
|
||||
if check_cpu_flag sse4_2 && check_cpu_flag avx2; then
|
||||
CPU="-cpu Haswell-v4,kvm=on,vendor=GenuineIntel,+avx,+avx2,+sse,+sse2,+sse3,+sse4.2,vmware-cpuid-freq=on"
|
||||
else
|
||||
echo "ERROR! macOS ${macos_release} requires a CPU with SSE 4.2 and AVX2 support."
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
catalina|big-sur|monterey)
|
||||
if check_cpu_flag sse4_2; then
|
||||
CPU="-cpu Haswell-v4,kvm=on,vendor=GenuineIntel,+avx,+sse,+sse2,+sse3,+sse4.2,vmware-cpuid-freq=on"
|
||||
else
|
||||
echo "ERROR! macOS ${macos_release} requires a CPU with SSE 4.2 support."
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
if check_cpu_flag sse4_1; then
|
||||
CPU="-cpu Penryn,kvm=on,vendor=GenuineIntel,+avx,+sse,+sse2,+sse3,+sse4.1,vmware-cpuid-freq=on"
|
||||
else
|
||||
echo "ERROR! macOS ${macos_release} requires a CPU with SSE 4.1 support."
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
# https://www.techpowerup.com/cpu-specs/xeon-w-2140b.c2953 8 cores 16 threads # skylake server
|
||||
# https://en.wikipedia.org/wiki/IMac_Pro#Technical_specifications Orig: High Sierra Max: Sonoma
|
||||
# https://en.wikipedia.org/wiki/MacOS#Hardware_compatibility needs 8GB RAM
|
||||
# https://qemu.readthedocs.io/en/v9.0.0/system/qemu-cpu-models.html#important-cpu-features-for-amd-x86-hosts
|
||||
# https://www.reddit.com/r/hackintosh/comments/141wnjk/state_of_macos_14_sonoma_on_x86/
|
||||
for FLAG in abm adx aes amd-ssbd bmi1 bmi2 cx8 eist ept f16c fma invtsc \
|
||||
mmx movbe mpx pdpe1gb smep vaes vbmi2 vpclmulqdq \
|
||||
xgetbv1 xsave xsaveopt; do
|
||||
if check_cpu_flag "${FLAG}"; then
|
||||
CPU+=",+${FLAG}"
|
||||
fi
|
||||
done
|
||||
|
||||
OSK=$(echo "bheuneqjbexolgurfrjbeqfthneqrqcyrnfrqbagfgrny(p)NccyrPbzchgreVap" | tr 'A-Za-z' 'N-ZA-Mn-za-m')
|
||||
# Disable S3 support in the VM to prevent macOS suspending during install
|
||||
GUEST_TWEAKS="-global kvm-pit.lost_tick_policy=discard -global ICH9-LPC.disable_s3=1 -device isa-applesmc,osk=${OSK}"
|
||||
|
||||
# Disable High Precision Timer
|
||||
if [ "${QEMU_VER_SHORT}" -ge 70 ]; then
|
||||
MACHINE_TYPE+=",hpet=off"
|
||||
else
|
||||
GUEST_TWEAKS+=" -no-hpet"
|
||||
fi
|
||||
|
||||
# Tune Qemu optimisations based on the macOS release, or fallback to lowest
|
||||
# common supported options if none is specified.
|
||||
# * VirtIO Block Media doesn't work in High Sierra (at all) or the Mojave (Recovery Image)
|
||||
# * VirtIO Network is supported since Big Sur
|
||||
# * VirtIO Memory Balloning is supported since Big Sur (https://pmhahn.github.io/virtio-balloon/)
|
||||
# * VirtIO RNG is supported since Big Sur, but exposed to all guests by default.
|
||||
case ${macos_release} in
|
||||
catalina)
|
||||
BALLOON=""
|
||||
MAC_DISK_DEV="virtio-blk-pci"
|
||||
NET_DEVICE="vmxnet3"
|
||||
USB_HOST_PASSTHROUGH_CONTROLLER="usb-ehci"
|
||||
;;
|
||||
big-sur|monterey|ventura|sonoma)
|
||||
BALLOON="-device virtio-balloon"
|
||||
MAC_DISK_DEV="virtio-blk-pci"
|
||||
NET_DEVICE="virtio-net"
|
||||
USB_HOST_PASSTHROUGH_CONTROLLER="nec-usb-xhci"
|
||||
GUEST_TWEAKS="${GUEST_TWEAKS} -global nec-usb-xhci.msi=off"
|
||||
USB_CONTROLLER="xhci"
|
||||
;;
|
||||
*)
|
||||
# Backwards compatibility if no macos_release is specified.
|
||||
# Also safe catch all for High Sierra and Mojave
|
||||
BALLOON=""
|
||||
MAC_DISK_DEV="ide-hd,bus=ahci.2"
|
||||
NET_DEVICE="vmxnet3"
|
||||
USB_HOST_PASSTHROUGH_CONTROLLER="usb-ehci"
|
||||
;;
|
||||
esac
|
||||
|
||||
if [ -z "${disk_size}" ]; then
|
||||
disk_size="96G"
|
||||
fi
|
||||
;;
|
||||
windows|windows-server)
|
||||
if [ "${QEMU_VER_SHORT}" -gt 60 ]; then
|
||||
CPU="-cpu host,kvm=on,+hypervisor,+invtsc,l3-cache=on,migratable=no,hv_passthrough"
|
||||
else
|
||||
CPU="-cpu host,kvm=on,+hypervisor,+invtsc,l3-cache=on,migratable=no,hv_frequencies,kvm_pv_unhalt,hv_reenlightenment,hv_relaxed,hv_spinlocks=8191,hv_stimer,hv_synic,hv_time,hv_vapic,hv_vendor_id=1234567890ab,hv_vpindex"
|
||||
fi
|
||||
if [ "${HOST_CPU_VENDOR}" == "AuthenticAMD" ]; then
|
||||
CPU="${CPU},topoext"
|
||||
fi
|
||||
# Disable S3 support in the VM to ensure Windows can boot with SecureBoot enabled
|
||||
# - https://wiki.archlinux.org/title/QEMU#VM_does_not_boot_when_using_a_Secure_Boot_enabled_OVMF
|
||||
GUEST_TWEAKS="-global kvm-pit.lost_tick_policy=discard -global ICH9-LPC.disable_s3=1"
|
||||
|
||||
# Disable High Precision Timer
|
||||
if [ "${QEMU_VER_SHORT}" -ge 70 ]; then
|
||||
MACHINE_TYPE+=",hpet=off"
|
||||
else
|
||||
GUEST_TWEAKS+=" -no-hpet"
|
||||
fi
|
||||
|
||||
if [ -z "${disk_size}" ]; then
|
||||
disk_size="64G"
|
||||
fi
|
||||
SMM="on"
|
||||
;;
|
||||
*)
|
||||
CPU="-cpu host,kvm=on"
|
||||
NET_DEVICE="rtl8139"
|
||||
if [ -z "${disk_size}" ]; then
|
||||
disk_size="32G"
|
||||
fi
|
||||
echo "WARNING! Unrecognised guest OS: ${guest_os}"
|
||||
;;
|
||||
*) CPU="-cpu host,kvm=on"
|
||||
NET_DEVICE="rtl8139"
|
||||
if [ -z "${disk_size}" ]; then
|
||||
disk_size="32G"
|
||||
fi
|
||||
echo "WARNING! Unrecognised guest OS: ${guest_os}";;
|
||||
esac
|
||||
|
||||
echo " - Disk: ${disk_img} (${disk_size})"
|
||||
|
@ -659,10 +641,9 @@ function vm_boot() {
|
|||
# If there is no disk image, create a new image.
|
||||
mkdir -p "${VMDIR}" 2>/dev/null
|
||||
case ${preallocation} in
|
||||
off|metadata|falloc|full) true;;
|
||||
*)
|
||||
echo "ERROR! ${preallocation} is an unsupported disk preallocation option."
|
||||
exit 1;;
|
||||
off|metadata|falloc|full) true;;
|
||||
*) echo "ERROR! ${preallocation} is an unsupported disk preallocation option."
|
||||
exit 1;;
|
||||
esac
|
||||
|
||||
# https://blog.programster.org/qcow2-performance
|
||||
|
@ -727,8 +708,8 @@ function vm_boot() {
|
|||
# Setup the appropriate audio device based on the display output
|
||||
# https://www.kraxel.org/blog/2020/01/qemu-sound-audiodev/
|
||||
case ${OUTPUT} in
|
||||
none|spice|spice-app) AUDIO_DEV="spice,id=audio0";;
|
||||
*) AUDIO_DEV="pa,id=audio0";;
|
||||
none|spice|spice-app) AUDIO_DEV="spice,id=audio0";;
|
||||
*) AUDIO_DEV="pa,id=audio0";;
|
||||
esac
|
||||
|
||||
# Determine a sane resolution for Linux guests.
|
||||
|
@ -772,10 +753,8 @@ function vm_boot() {
|
|||
DISPLAY_DEVICE="vmware-svga"
|
||||
elif [ "${guest_os}" == "linux" ]; then
|
||||
case ${OUTPUT} in
|
||||
none|spice|spice-app)
|
||||
DISPLAY_DEVICE="virtio-gpu";;
|
||||
*)
|
||||
DISPLAY_DEVICE="virtio-vga";;
|
||||
none|spice|spice-app) DISPLAY_DEVICE="virtio-gpu";;
|
||||
*) DISPLAY_DEVICE="virtio-vga";;
|
||||
esac
|
||||
elif [ "${guest_os}" == "macos" ]; then
|
||||
# qxl-vga supports seamless mouse and sane resolutions if only one scanout
|
||||
|
@ -783,10 +762,10 @@ function vm_boot() {
|
|||
DISPLAY_DEVICE="qxl-vga"
|
||||
elif [ "${guest_os}" == "windows" ] || [ "${guest_os}" == "windows-server" ]; then
|
||||
case ${OUTPUT} in
|
||||
# virtio-gpu "works" with gtk but is limited to 1024x1024 and exhibits other issues.
|
||||
# https://kevinlocke.name/bits/2021/12/10/windows-11-guest-virtio-libvirt/#video
|
||||
gtk|none|spice) DISPLAY_DEVICE="qxl-vga";;
|
||||
sdl|spice-app) DISPLAY_DEVICE="virtio-vga";;
|
||||
# virtio-gpu "works" with gtk but is limited to 1024x1024 and exhibits other issues.
|
||||
# https://kevinlocke.name/bits/2021/12/10/windows-11-guest-virtio-libvirt/#video
|
||||
gtk|none|spice) DISPLAY_DEVICE="qxl-vga";;
|
||||
sdl|spice-app) DISPLAY_DEVICE="virtio-vga";;
|
||||
esac
|
||||
elif [ "${guest_os}" == "solaris" ]; then
|
||||
DISPLAY_DEVICE="vmware-svga"
|
||||
|
@ -796,11 +775,11 @@ function vm_boot() {
|
|||
|
||||
# Map Quickemu OUTPUT to QEMU -display
|
||||
case ${OUTPUT} in
|
||||
gtk) DISPLAY_RENDER="${OUTPUT},grab-on-hover=on,zoom-to-fit=off,gl=${gl}";;
|
||||
none|spice) DISPLAY_RENDER="none";;
|
||||
sdl) DISPLAY_RENDER="${OUTPUT},gl=${gl}";;
|
||||
spice-app) DISPLAY_RENDER="${OUTPUT},gl=${gl}";;
|
||||
*) DISPLAY_RENDER="${OUTPUT}";;
|
||||
gtk) DISPLAY_RENDER="${OUTPUT},grab-on-hover=on,zoom-to-fit=off,gl=${gl}";;
|
||||
none|spice) DISPLAY_RENDER="none";;
|
||||
sdl) DISPLAY_RENDER="${OUTPUT},gl=${gl}";;
|
||||
spice-app) DISPLAY_RENDER="${OUTPUT},gl=${gl}";;
|
||||
*) DISPLAY_RENDER="${OUTPUT}";;
|
||||
esac
|
||||
|
||||
# https://www.kraxel.org/blog/2021/05/virtio-gpu-qemu-graphics-update/
|
||||
|
@ -829,9 +808,9 @@ function vm_boot() {
|
|||
|
||||
# Allocate VRAM to VGA devices
|
||||
case ${DISPLAY_DEVICE} in
|
||||
bochs-display) VIDEO="${VIDEO},vgamem=67108864";;
|
||||
qxl|qxl-vga) VIDEO="${VIDEO},ram_size=65536,vram_size=65536,vgamem_mb=64";;
|
||||
ati-vga|cirrus-vga|VGA|vmware-svga) VIDEO="${VIDEO},vgamem_mb=64";;
|
||||
bochs-display) VIDEO="${VIDEO},vgamem=67108864";;
|
||||
qxl|qxl-vga) VIDEO="${VIDEO},ram_size=65536,vram_size=65536,vgamem_mb=64";;
|
||||
ati-vga|cirrus-vga|VGA|vmware-svga) VIDEO="${VIDEO},vgamem_mb=64";;
|
||||
esac
|
||||
|
||||
# Configure multiscreen if max_outputs was provided in the .conf file
|
||||
|
@ -938,15 +917,14 @@ function vm_boot() {
|
|||
|
||||
if [ -n "${PUBLIC}" ]; then
|
||||
case ${guest_os} in
|
||||
macos)
|
||||
if [ "${OUTPUT}" == "none" ] || [ "${OUTPUT}" == "spice" ] || [ "${OUTPUT}" == "spice-app" ]; then
|
||||
# Reference: https://gitlab.gnome.org/GNOME/phodav/-/issues/5
|
||||
echo " - WebDAV: On guest: build spice-webdavd (https://gitlab.gnome.org/GNOME/phodav/-/merge_requests/24)"
|
||||
echo " - WebDAV: On guest: Finder -> Connect to Server -> http://localhost:9843/"
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
echo " - WebDAV: On guest: dav://localhost:9843/";;
|
||||
macos)
|
||||
if [ "${OUTPUT}" == "none" ] || [ "${OUTPUT}" == "spice" ] || [ "${OUTPUT}" == "spice-app" ]; then
|
||||
# Reference: https://gitlab.gnome.org/GNOME/phodav/-/issues/5
|
||||
echo " - WebDAV: On guest: build spice-webdavd (https://gitlab.gnome.org/GNOME/phodav/-/merge_requests/24)"
|
||||
echo " - WebDAV: On guest: Finder -> Connect to Server -> http://localhost:9843/"
|
||||
fi;;
|
||||
*)
|
||||
echo " - WebDAV: On guest: dav://localhost:9843/";;
|
||||
esac
|
||||
fi
|
||||
|
||||
|
@ -1341,7 +1319,7 @@ function vm_boot() {
|
|||
if [ ${VM_UP} -eq 0 ]; then
|
||||
# Enable grab-on-hover for SDL: https://github.com/quickemu-project/quickemu/issues/541
|
||||
case "${OUTPUT}" in
|
||||
sdl) export SDL_MOUSE_FOCUS_CLICKTHROUGH=1;;
|
||||
sdl) export SDL_MOUSE_FOCUS_CLICKTHROUGH=1;;
|
||||
esac
|
||||
echo "${QEMU}" "${SHELL_ARGS}" "2>/dev/null" >> "${VMDIR}/${VMNAME}.sh"
|
||||
sed -i -e 's/ -/ \\\n -/g' "${VMDIR}/${VMNAME}.sh"
|
||||
|
@ -1544,18 +1522,15 @@ function monitor_send_cmd {
|
|||
fi
|
||||
|
||||
case "${monitor_channel}" in
|
||||
socket)
|
||||
echo -e " - Sending: ${MSG}"
|
||||
echo -e "${MSG}" | socat -,shut-down unix-connect:"${VM_MONITOR_SOCKETPATH}" 2>&1 > /dev/null
|
||||
;;
|
||||
telnet)
|
||||
echo -e " - Sending: ${MSG}"
|
||||
echo -e "${MSG}" | socat - tcp:"${MONITOR_TELNET_HOST}":"${MONITOR_TELNET_PORT}" 2>&1 > /dev/null
|
||||
;;
|
||||
*)
|
||||
echo "ERROR! This should never happen!"
|
||||
exit 1
|
||||
;;
|
||||
socket)
|
||||
echo -e " - Sending: ${MSG}"
|
||||
echo -e "${MSG}" | socat -,shut-down unix-connect:"${VM_MONITOR_SOCKETPATH}" 2>&1 > /dev/null;;
|
||||
telnet)
|
||||
echo -e " - Sending: ${MSG}"
|
||||
echo -e "${MSG}" | socat - tcp:"${MONITOR_TELNET_HOST}":"${MONITOR_TELNET_PORT}" 2>&1 > /dev/null;;
|
||||
*)
|
||||
echo "ERROR! This should never happen!"
|
||||
exit 1;;
|
||||
esac
|
||||
|
||||
return 0
|
||||
|
@ -1676,159 +1651,159 @@ if [ $# -lt 1 ]; then
|
|||
else
|
||||
while [ $# -gt 0 ]; do
|
||||
case "${1}" in
|
||||
-access|--access)
|
||||
ACCESS="${2}"
|
||||
shift
|
||||
shift;;
|
||||
-braille|--braille)
|
||||
BRAILLE="on"
|
||||
shift;;
|
||||
-delete|--delete|-delete-disk|--delete-disk)
|
||||
DELETE_DISK=1
|
||||
shift;;
|
||||
-delete-vm|--delete-vm)
|
||||
DELETE_VM=1
|
||||
shift;;
|
||||
-display|--display)
|
||||
OUTPUT="${2}"
|
||||
display_param_check
|
||||
shift
|
||||
shift;;
|
||||
-fullscreen|--fullscreen|-full-screen|--full-screen)
|
||||
FULLSCREEN="-full-screen"
|
||||
FULLSPICY="--full-screen"
|
||||
shift;;
|
||||
-ignore-msrs-always|--ignore-msrs-always)
|
||||
ignore_msrs_always
|
||||
exit;;
|
||||
-screen|--screen)
|
||||
SCREEN="${2}"
|
||||
shift
|
||||
shift;;
|
||||
-screenpct|--screenpct)
|
||||
if [ -n "${2##*[!0-9]*}" ] ; then
|
||||
if [[ ${2} -ge 25 && ${2} -lt 100 ]] ; then
|
||||
SCREENPCT=${2}
|
||||
-access|--access)
|
||||
ACCESS="${2}"
|
||||
shift
|
||||
shift;;
|
||||
-braille|--braille)
|
||||
BRAILLE="on"
|
||||
shift;;
|
||||
-delete|--delete|-delete-disk|--delete-disk)
|
||||
DELETE_DISK=1
|
||||
shift;;
|
||||
-delete-vm|--delete-vm)
|
||||
DELETE_VM=1
|
||||
shift;;
|
||||
-display|--display)
|
||||
OUTPUT="${2}"
|
||||
display_param_check
|
||||
shift
|
||||
shift;;
|
||||
-fullscreen|--fullscreen|-full-screen|--full-screen)
|
||||
FULLSCREEN="-full-screen"
|
||||
FULLSPICY="--full-screen"
|
||||
shift;;
|
||||
-ignore-msrs-always|--ignore-msrs-always)
|
||||
ignore_msrs_always
|
||||
exit;;
|
||||
-screen|--screen)
|
||||
SCREEN="${2}"
|
||||
shift
|
||||
shift;;
|
||||
-screenpct|--screenpct)
|
||||
if [ -n "${2##*[!0-9]*}" ] ; then
|
||||
if [[ ${2} -ge 25 && ${2} -lt 100 ]] ; then
|
||||
SCREENPCT=${2}
|
||||
else
|
||||
echo "screenpct invalid must be 25 <= pct < 100"
|
||||
usage
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
echo "screenpct invalid must be 25 <= pct < 100"
|
||||
echo "screenpct needs to be an integer in range 25 <= pct < 100"
|
||||
usage
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
echo "screenpct needs to be an integer in range 25 <= pct < 100"
|
||||
usage
|
||||
exit 1
|
||||
fi
|
||||
shift
|
||||
shift;;
|
||||
-snapshot|--snapshot)
|
||||
SNAPSHOT_ACTION="${2}"
|
||||
if [ -z "${SNAPSHOT_ACTION}" ]; then
|
||||
echo "ERROR! No snapshot action provided."
|
||||
exit 1
|
||||
fi
|
||||
shift
|
||||
SNAPSHOT_TAG="${2}"
|
||||
if [ -z "${SNAPSHOT_TAG}" ] && [ "${SNAPSHOT_ACTION}" != "info" ]; then
|
||||
echo "ERROR! No snapshot tag provided."
|
||||
exit 1
|
||||
fi
|
||||
shift
|
||||
shift;;
|
||||
-status-quo|--status-quo)
|
||||
STATUS_QUO="-snapshot"
|
||||
shift;;
|
||||
-shortcut|--shortcut)
|
||||
SHORTCUT=1
|
||||
shift;;
|
||||
-vm|--vm)
|
||||
VM="${2}"
|
||||
shift
|
||||
shift;;
|
||||
-viewer|--viewer)
|
||||
VIEWER="${2}"
|
||||
shift
|
||||
shift;;
|
||||
-width|--width)
|
||||
WIDTH="${2}"
|
||||
shift;
|
||||
shift;;
|
||||
-height|--height)
|
||||
HEIGHT="${2}"
|
||||
shift;
|
||||
shift;;
|
||||
-ssh-port|--ssh-port)
|
||||
SSH_PORT="${2}"
|
||||
shift;
|
||||
shift;;
|
||||
-spice-port|--spice-port)
|
||||
SPICE_PORT="${2}"
|
||||
shift;
|
||||
shift;;
|
||||
-public-dir|--public-dir)
|
||||
PUBLIC="${2}"
|
||||
shift;
|
||||
shift;;
|
||||
-monitor|--monitor)
|
||||
MONITOR="${2}"
|
||||
shift;
|
||||
shift;;
|
||||
-monitor-cmd|--monitor-cmd)
|
||||
MONITOR_CMD="${2}"
|
||||
shift;
|
||||
shift;;
|
||||
-monitor-telnet-host|--monitor-telnet-host)
|
||||
MONITOR_TELNET_HOST="${2}"
|
||||
shift;
|
||||
shift;;
|
||||
-monitor-telnet-port|--monitor-telnet-port)
|
||||
MONITOR_TELNET_PORT="${2}"
|
||||
shift;
|
||||
shift;;
|
||||
-serial|--serial)
|
||||
SERIAL="${2}"
|
||||
shift;
|
||||
shift;;
|
||||
-serial-telnet-host|--serial-telnet-host)
|
||||
SERIAL_TELNET_HOST="${2}"
|
||||
shift;
|
||||
shift;;
|
||||
-serial-telnet-port|--serial-telnet-port)
|
||||
SERIAL_TELNET_PORT="${2}"
|
||||
shift;
|
||||
shift;;
|
||||
-keyboard|--keyboard)
|
||||
KEYBOARD="${2}"
|
||||
shift;
|
||||
shift;;
|
||||
-keyboard_layout|--keyboard_layout)
|
||||
KEYBOARD_LAYOUT="${2}"
|
||||
shift;
|
||||
shift;;
|
||||
-mouse|--mouse)
|
||||
MOUSE="${2}"
|
||||
shift;
|
||||
shift;;
|
||||
-usb-controller|--usb-controller)
|
||||
USB_CONTROLLER="${2}"
|
||||
shift;
|
||||
shift;;
|
||||
-extra_args|--extra_args)
|
||||
EXTRA_ARGS="${2}"
|
||||
shift;
|
||||
shift;;
|
||||
-sound-card|--sound-card)
|
||||
SOUND_CARD="${2}"
|
||||
shift;
|
||||
shift;;
|
||||
-version|--version)
|
||||
echo "${VERSION}"
|
||||
exit;;
|
||||
-h|--h|-help|--help)
|
||||
usage;;
|
||||
*)
|
||||
echo "ERROR! \"${1}\" is not a supported parameter."
|
||||
usage;;
|
||||
shift
|
||||
shift;;
|
||||
-snapshot|--snapshot)
|
||||
SNAPSHOT_ACTION="${2}"
|
||||
if [ -z "${SNAPSHOT_ACTION}" ]; then
|
||||
echo "ERROR! No snapshot action provided."
|
||||
exit 1
|
||||
fi
|
||||
shift
|
||||
SNAPSHOT_TAG="${2}"
|
||||
if [ -z "${SNAPSHOT_TAG}" ] && [ "${SNAPSHOT_ACTION}" != "info" ]; then
|
||||
echo "ERROR! No snapshot tag provided."
|
||||
exit 1
|
||||
fi
|
||||
shift
|
||||
shift;;
|
||||
-status-quo|--status-quo)
|
||||
STATUS_QUO="-snapshot"
|
||||
shift;;
|
||||
-shortcut|--shortcut)
|
||||
SHORTCUT=1
|
||||
shift;;
|
||||
-vm|--vm)
|
||||
VM="${2}"
|
||||
shift
|
||||
shift;;
|
||||
-viewer|--viewer)
|
||||
VIEWER="${2}"
|
||||
shift
|
||||
shift;;
|
||||
-width|--width)
|
||||
WIDTH="${2}"
|
||||
shift;
|
||||
shift;;
|
||||
-height|--height)
|
||||
HEIGHT="${2}"
|
||||
shift;
|
||||
shift;;
|
||||
-ssh-port|--ssh-port)
|
||||
SSH_PORT="${2}"
|
||||
shift;
|
||||
shift;;
|
||||
-spice-port|--spice-port)
|
||||
SPICE_PORT="${2}"
|
||||
shift;
|
||||
shift;;
|
||||
-public-dir|--public-dir)
|
||||
PUBLIC="${2}"
|
||||
shift;
|
||||
shift;;
|
||||
-monitor|--monitor)
|
||||
MONITOR="${2}"
|
||||
shift;
|
||||
shift;;
|
||||
-monitor-cmd|--monitor-cmd)
|
||||
MONITOR_CMD="${2}"
|
||||
shift;
|
||||
shift;;
|
||||
-monitor-telnet-host|--monitor-telnet-host)
|
||||
MONITOR_TELNET_HOST="${2}"
|
||||
shift;
|
||||
shift;;
|
||||
-monitor-telnet-port|--monitor-telnet-port)
|
||||
MONITOR_TELNET_PORT="${2}"
|
||||
shift;
|
||||
shift;;
|
||||
-serial|--serial)
|
||||
SERIAL="${2}"
|
||||
shift;
|
||||
shift;;
|
||||
-serial-telnet-host|--serial-telnet-host)
|
||||
SERIAL_TELNET_HOST="${2}"
|
||||
shift;
|
||||
shift;;
|
||||
-serial-telnet-port|--serial-telnet-port)
|
||||
SERIAL_TELNET_PORT="${2}"
|
||||
shift;
|
||||
shift;;
|
||||
-keyboard|--keyboard)
|
||||
KEYBOARD="${2}"
|
||||
shift;
|
||||
shift;;
|
||||
-keyboard_layout|--keyboard_layout)
|
||||
KEYBOARD_LAYOUT="${2}"
|
||||
shift;
|
||||
shift;;
|
||||
-mouse|--mouse)
|
||||
MOUSE="${2}"
|
||||
shift;
|
||||
shift;;
|
||||
-usb-controller|--usb-controller)
|
||||
USB_CONTROLLER="${2}"
|
||||
shift;
|
||||
shift;;
|
||||
-extra_args|--extra_args)
|
||||
EXTRA_ARGS="${2}"
|
||||
shift;
|
||||
shift;;
|
||||
-sound-card|--sound-card)
|
||||
SOUND_CARD="${2}"
|
||||
shift;
|
||||
shift;;
|
||||
-version|--version)
|
||||
echo "${VERSION}"
|
||||
exit;;
|
||||
-h|--h|-help|--help)
|
||||
usage;;
|
||||
*)
|
||||
echo "ERROR! \"${1}\" is not a supported parameter."
|
||||
usage;;
|
||||
esac
|
||||
done
|
||||
fi
|
||||
|
@ -1986,24 +1961,24 @@ fi
|
|||
|
||||
if [ -n "${SNAPSHOT_ACTION}" ]; then
|
||||
case ${SNAPSHOT_ACTION} in
|
||||
apply)
|
||||
snapshot_apply "${SNAPSHOT_TAG}"
|
||||
snapshot_info
|
||||
exit;;
|
||||
create)
|
||||
snapshot_create "${SNAPSHOT_TAG}"
|
||||
snapshot_info
|
||||
exit;;
|
||||
delete)
|
||||
snapshot_delete "${SNAPSHOT_TAG}"
|
||||
snapshot_info
|
||||
exit;;
|
||||
info)
|
||||
snapshot_info
|
||||
exit;;
|
||||
*)
|
||||
echo "ERROR! \"${SNAPSHOT_ACTION}\" is not a supported snapshot action."
|
||||
usage;;
|
||||
apply)
|
||||
snapshot_apply "${SNAPSHOT_TAG}"
|
||||
snapshot_info
|
||||
exit;;
|
||||
create)
|
||||
snapshot_create "${SNAPSHOT_TAG}"
|
||||
snapshot_info
|
||||
exit;;
|
||||
delete)
|
||||
snapshot_delete "${SNAPSHOT_TAG}"
|
||||
snapshot_info
|
||||
exit;;
|
||||
info)
|
||||
snapshot_info
|
||||
exit;;
|
||||
*)
|
||||
echo "ERROR! \"${SNAPSHOT_ACTION}\" is not a supported snapshot action."
|
||||
usage;;
|
||||
esac
|
||||
fi
|
||||
|
||||
|
|
Loading…
Reference in New Issue