-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathinstall.sh
More file actions
executable file
·272 lines (223 loc) · 8.63 KB
/
Copy pathinstall.sh
File metadata and controls
executable file
·272 lines (223 loc) · 8.63 KB
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
#!/bin/bash
set -euo pipefail
# =============================================================================
# Windows 11 KVM + PCI Passthrough Setup Script
# =============================================================================
# Host GPU: RX 7700 XT (05:00.0)
# Passthrough: RX 9070 XT (0f:00.0 + 0f:00.1)
# USB xHCI (11:00.3) - Razer, Arturia KeyLab, UGREEN BT
# VM: 32 vCPUs, 64GB RAM, 3TB disk, Secure Boot + TPM 2.0
# =============================================================================
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'
VM_NAME="win11"
VM_DIR="/var/lib/libvirt/images"
DISK_SIZE="5120" # GB
# Vendor:Device IDs (GPU only - unique IDs safe for vfio-pci.ids)
GPU_VGA_ID="1002:7550"
GPU_AUDIO_ID="1002:ab40"
# USB controller 11:00.3 [1022:149c] managed by libvirt (managed='yes' handles bind/unbind)
info() { echo -e "${GREEN}[INFO]${NC} $1"; }
warn() { echo -e "${YELLOW}[WARN]${NC} $1"; }
error() { echo -e "${RED}[ERROR]${NC} $1"; exit 1; }
check_root() {
[[ $EUID -eq 0 ]] || error "Este script debe ejecutarse como root: sudo ./install.sh"
}
install_packages() {
info "Instalando paquetes necesarios..."
dnf install -y \
qemu-kvm \
libvirt \
libvirt-daemon-kvm \
virt-manager \
virt-install \
edk2-ovmf \
swtpm \
swtpm-tools \
libguestfs-tools \
wimlib-utils \
xorriso \
dnsmasq
}
configure_iommu() {
info "Configurando IOMMU en el kernel..."
# Limpieza: 'amd_iommu=on' no es una opcion valida (los valores aceptados
# son off/fullflush/force_isolation/force_enable). Versiones anteriores
# de este script la añadian; en kernels <7.0 era ignorada silenciosamente,
# pero en Linux 7.0 el parser rechaza el init de AMD-Vi al verla, dejando
# la IOMMU sin inicializar y VFIO sin funcionar. La eliminamos siempre.
if grubby --info=ALL 2>/dev/null | grep -q "amd_iommu=on"; then
grubby --update-kernel=ALL --remove-args='amd_iommu=on'
warn "Eliminado 'amd_iommu=on' (invalido) del cmdline de todos los kernels"
fi
# AMD-Vi arranca por defecto si la CPU/BIOS soportan IOMMU.
# Solo necesitamos iommu=pt (passthrough) y el bind temprano de vfio-pci.
local needed_args="iommu=pt vfio-pci.ids=${GPU_VGA_ID},${GPU_AUDIO_ID}"
# grubby --args es idempotente: actualiza si cambia el valor, no duplica.
grubby --update-kernel=ALL --args="$needed_args"
info "Parametros del kernel asegurados: $needed_args"
}
configure_vfio() {
info "Configurando vfio-pci para la RX 9070 XT..."
local SCRIPT_DIR
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
local need_dracut=false
# Load vfio modules early
if ! diff -q "${SCRIPT_DIR}/configs/vfio-modules.conf" /etc/modules-load.d/vfio-pci.conf &>/dev/null; then
cp "${SCRIPT_DIR}/configs/vfio-modules.conf" /etc/modules-load.d/vfio-pci.conf
need_dracut=true
fi
# Bind GPU to vfio-pci by vendor:device ID
# Only GPU IDs here - USB controller shares IDs with host controllers
local new_modprobe
new_modprobe=$(GPU_VGA_ID="${GPU_VGA_ID}" GPU_AUDIO_ID="${GPU_AUDIO_ID}" \
envsubst '${GPU_VGA_ID} ${GPU_AUDIO_ID}' \
< "${SCRIPT_DIR}/configs/vfio-modprobe.conf.template")
if [ ! -f /etc/modprobe.d/vfio.conf ] || [ "$new_modprobe" != "$(cat /etc/modprobe.d/vfio.conf)" ]; then
echo "$new_modprobe" > /etc/modprobe.d/vfio.conf
need_dracut=true
fi
if $need_dracut; then
info "Regenerando initramfs..."
dracut -f --kver "$(uname -r)"
else
info "Configs vfio sin cambios, no es necesario regenerar initramfs"
fi
}
enable_services() {
info "Habilitando servicios de libvirt..."
systemctl enable --now libvirtd
systemctl enable --now virtlogd
}
configure_user() {
info "Configurando permisos de usuario..."
local REAL_USER="${SUDO_USER:-$USER}"
usermod -aG libvirt "$REAL_USER" 2>/dev/null || true
usermod -aG kvm "$REAL_USER" 2>/dev/null || true
# Configure libvirt to run QEMU as root for PCI passthrough
sed -i 's/^#\?user = .*/user = "root"/' /etc/libvirt/qemu.conf
sed -i 's/^#\?group = .*/group = "root"/' /etc/libvirt/qemu.conf
}
create_amd_drivers_iso() {
local AMD_ISO="${VM_DIR}/amd-drivers.iso"
local SCRIPT_DIR
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
local AMD_EXE
AMD_EXE=$(find "${SCRIPT_DIR}" -maxdepth 1 -name "*.exe" -path "*amd*adrenalin*" | head -1)
if [ -f "$AMD_ISO" ]; then
info "La ISO de drivers AMD ya existe: ${AMD_ISO}"
return
fi
if [ -z "$AMD_EXE" ]; then
warn "No se encuentra el instalador de AMD Adrenalin en ${SCRIPT_DIR}, saltando"
return
fi
info "Creando ISO con $(basename "$AMD_EXE")..."
mkisofs -o "$AMD_ISO" -J -r "$AMD_EXE" 2>&1 | tail -1
info "ISO de drivers AMD creada: ${AMD_ISO}"
}
create_autounattend_iso() {
info "Creando ISO con autounattend.xml..."
local SCRIPT_DIR
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
local ISO_IMG="${VM_DIR}/${VM_NAME}_autounattend.iso"
if [ ! -f "${SCRIPT_DIR}/autounattend.xml" ]; then
error "No se encuentra autounattend.xml en ${SCRIPT_DIR}"
fi
mkisofs -o "$ISO_IMG" -J -r "${SCRIPT_DIR}/autounattend.xml"
info "ISO creada: ${ISO_IMG}"
}
create_disk() {
info "Creando disco virtual de ${DISK_SIZE}GB..."
mkdir -p "$VM_DIR"
if [ ! -f "${VM_DIR}/${VM_NAME}.raw" ]; then
qemu-img create -f raw "${VM_DIR}/${VM_NAME}.raw" "${DISK_SIZE}G"
info "Disco creado: ${VM_DIR}/${VM_NAME}.raw"
else
warn "El disco ${VM_DIR}/${VM_NAME}.raw ya existe, no se sobreescribe"
fi
}
reset_vm() {
warn "Reseteando la VM '${VM_NAME}' — se borrara disco, NVRAM, TPM y floppy..."
# Apagar si esta corriendo
virsh destroy "${VM_NAME}" 2>/dev/null || true
# Eliminar definicion y NVRAM
virsh undefine "${VM_NAME}" --nvram 2>/dev/null || true
# Borrar disco, NVRAM, ISO autounattend y TPM
rm -f "${VM_DIR}/${VM_NAME}.raw"
rm -f "${VM_DIR}/${VM_NAME}.qcow2"
rm -f "${VM_DIR}/${VM_NAME}_VARS.fd"
rm -f "${VM_DIR}/${VM_NAME}_autounattend.iso"
rm -f "${VM_DIR}/amd-drivers.iso"
rm -rf "/var/lib/libvirt/swtpm/${VM_NAME}"
info "VM '${VM_NAME}' eliminada completamente"
}
create_vm() {
info "Definiendo la maquina virtual ${VM_NAME}..."
local SCRIPT_DIR
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
# Copy NVRAM template (each VM needs its own writable copy)
local OVMF_VARS="/usr/share/edk2/ovmf/OVMF_VARS_4M.secboot.qcow2"
local VM_VARS="${VM_DIR}/${VM_NAME}_VARS.fd"
if [ ! -f "$VM_VARS" ]; then
cp "$OVMF_VARS" "$VM_VARS"
info "NVRAM copiado a ${VM_VARS}"
fi
# Create TPM state directory
mkdir -p "/var/lib/libvirt/swtpm/${VM_NAME}"
# Redefinir siempre con el domain.xml actual
virsh undefine "${VM_NAME}" --nvram 2>/dev/null || true
virsh define "${SCRIPT_DIR}/domain.xml"
info "VM '${VM_NAME}' definida correctamente"
}
print_summary() {
echo ""
echo -e "${GREEN}=========================================${NC}"
echo -e "${GREEN} INSTALACION COMPLETADA${NC}"
echo -e "${GREEN}=========================================${NC}"
echo ""
echo "Dispositivos PCI para passthrough:"
echo " GPU: RX 9070 XT -> 0f:00.0 + 0f:00.1 (vfio-pci al boot)"
echo " USB: xHCI 11:00.3 -> bind/unbind gestionado por libvirt (managed='yes')"
echo ""
echo "VM: ${VM_NAME}"
echo " CPU: 32 vCPUs (16C/32T, host-passthrough)"
echo " RAM: 64 GB"
echo " Disco: ${DISK_SIZE} GB (qcow2)"
echo " UEFI: Secure Boot habilitado"
echo " TPM: 2.0 (swtpm emulado)"
echo ""
echo -e "${YELLOW}PASOS SIGUIENTES:${NC}"
echo " 1. REINICIA el sistema para activar IOMMU y vfio-pci"
echo " 2. Inicia la VM:"
echo " sudo virsh start ${VM_NAME}"
echo " 3. La instalacion de Windows cargara los drivers VirtIO automaticamente"
echo ""
echo -e "${YELLOW}NOTA:${NC} Al iniciar la VM, tus perifericos Razer, Arturia KeyLab"
echo " y UGREEN BT dejaran de funcionar en el host (pasan a la VM)."
echo " Al apagar la VM, vuelven al host automaticamente."
echo ""
}
# =============================================================================
# MAIN
# =============================================================================
RESET=false
if [[ "${1:-}" == "--reset" ]]; then
RESET=true
fi
check_root
install_packages
configure_iommu
configure_vfio
enable_services
configure_user
if $RESET; then
reset_vm
fi
create_amd_drivers_iso
create_autounattend_iso
create_disk
create_vm
print_summary