Files
VBoxGuest/services/heartbeat/heartbeat.inc
2026-03-04 22:03:47 +03:00

244 lines
7.8 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
; =============================================================================
; Модуль : VMMDev Heartbeat Service
; Назначение : Периодическая отправка heartbeat сигналов хосту для мониторинга
; Файл : vmmdev/heartbeat.inc
; Протокол : Прямые VMMDev запросы (БЕЗ HGCM)
; =============================================================================
svc_heartbeat_name db "HEARTBEAT", 0
; --- Heartbeat Data ---
align 4
vbox_hb_last_send_time dd 0 ; timer_ticks последней отправки
vbox_hb_tick_interval dd 100
vbox_hb_enabled dd 0
; Статические буферы для запросов
align 4
vmmdev_heartbeat_configure_s VMMDEV_HEARTBEAT_CONFIGURE \
<sizeof.VMMDEV_HEARTBEAT_CONFIGURE, \
VMMDEV_REQUEST_HEADER_VERSION, \
VMMDEV_REQ_HEARTBEAT_CONFIGURE, \
0, 0, 0>, \
0, 0, 0; интервал и enabled заполняются при вызове
align 4
vmmdev_heartbeat_s VMMDEV_GUEST_HEARTBEAT \
<sizeof.VMMDEV_GUEST_HEARTBEAT, \
VMMDEV_REQUEST_HEADER_VERSION, \
VMMDEV_REQ_GUEST_HEARTBEAT, \
0, 0, 0>
; vmmdev_heartbeat_init — Инициализация heartbeat подсистемы
proc vmmdev_heartbeat_init
DEBUGF 2, "[VBoxGuest] [Heartbeat] Initializing...\n"
; Получить физические адреса буферов
mov eax, vmmdev_heartbeat_configure_s
mov [vbox_device.heartbeat_config_virt], eax
invoke GetPhysAddr
mov [vbox_device.heartbeat_config_phys], eax
DEBUGF __DEBUG_HB__, "[VBoxGuest] [Heartbeat] Config packet: virt=0x%x, phys=0x%x\n", \
vmmdev_heartbeat_configure_s, eax
mov eax, vmmdev_heartbeat_s
mov [vbox_device.heartbeat_virt], eax
invoke GetPhysAddr
mov [vbox_device.heartbeat_phys], eax
DEBUGF __DEBUG_HB__, "[VBoxGuest] [Heartbeat] Send packet : virt=0x%x, phys=0x%x\n", \
vmmdev_heartbeat_s, eax
; Запросить конфигурацию у хоста
call vmmdev_heartbeat_configure
test eax, eax
jnz .failed
DEBUGF 2, "[VBoxGuest] [Heartbeat] Initialized successfully\n"
xor eax, eax
ret
.failed:
DEBUGF 2, "[VBoxGuest] [Heartbeat] Initialization failed: rc=0x%x\n", eax
ret
endp
; vmmdev_heartbeat_configure — Запросить настройки heartbeat у хоста и включить мониторинг
proc vmmdev_heartbeat_configure uses ebx edi
DEBUGF __DEBUG_HB__, "[VBoxGuest] [Heartbeat] Configuring...\n"
mov edi, [vbox_device.heartbeat_config_virt]
test edi, edi
jz .bad_ptr
; Заполнить запрос (header уже инициализирован статически)
; Обнулить rc перед отправкой
mov dword [edi + VMMDEV_HEARTBEAT_CONFIGURE.header.rc], 0
; Запросить у хоста интервал (0 = использовать дефолтный)
mov dword [edi + VMMDEV_HEARTBEAT_CONFIGURE.c_ns_interval], 0
mov dword [edi + VMMDEV_HEARTBEAT_CONFIGURE.c_ns_interval_high], 0
; Включить heartbeat
mov dword [edi + VMMDEV_HEARTBEAT_CONFIGURE.f_enabled], 1
; Отправить запрос
mov ebx, [vbox_device.heartbeat_config_phys]
stdcall vmmdev_send_request, ebx
; Проверить результат
mov eax, [edi + VMMDEV_HEARTBEAT_CONFIGURE.header.rc]
test eax, eax
js .error
; Получить интервал от хоста (если вернул)
mov eax, [edi + VMMDEV_HEARTBEAT_CONFIGURE.c_ns_interval]
mov edx, [edi + VMMDEV_HEARTBEAT_CONFIGURE.c_ns_interval_high]
; Конвертировать наносекунды в тики
; Предположим timer tick = 10ms = 10,000,000 ns
; Делим ns на 10,000,000 чтобы получить тики
test eax, eax
jz .use_default
test edx, edx
jnz .use_default ; Если интервал > 4.2 секунды, используем дефолт
; eax = наносекунды, конвертируем в тики (10ms)
; ticks = ns / 10,000,000
; правильное деление: 10,000,000 / 10,000 = 1000 (тики в 10ms)
mov ebx, 10000
xor edx, edx
div ebx ; eax = eax / 10000 (микросекунды)
mov ebx, 1000
xor edx, edx
div ebx ; eax = eax / 1000 (тики 10ms)
test eax, eax
jz .use_default
mov [vbox_hb_tick_interval], eax
DEBUGF __DEBUG_HB__, "[VBoxGuest] [Heartbeat] Interval set to %d ticks\n", eax
jmp .enabled
.use_default:
DEBUGF __DEBUG_HB__, "[VBoxGuest] [Heartbeat] Using default interval: %d ticks\n", \
[vbox_hb_tick_interval]
.enabled:
; Включить heartbeat
mov dword [vbox_hb_enabled], 1
DEBUGF 2, "[VBoxGuest] [Heartbeat] Enabled\n"
xor eax, eax
ret
.error:
DEBUGF 2, "[VBoxGuest] [Heartbeat] Configure failed: rc=0x%x\n", eax
ret
.bad_ptr:
DEBUGF 2, "[VBoxGuest] [Heartbeat] Configure: bad pointer\n"
mov eax, VERR_INVALID_POINTER
ret
endp
; vmmdev_heartbeat_send — Отправить heartbeat хосту
proc vmmdev_heartbeat_send uses ebx edi
mov edi, [vbox_device.heartbeat_virt]
mov ebx, [vbox_device.heartbeat_phys]
test edi, edi
jz .bad_ptr
test ebx, ebx
jz .bad_ptr
; Обнулить rc перед отправкой
mov dword [edi + VMMDEV_GUEST_HEARTBEAT.header.rc], 0
; DEBUGF __DEBUG_HB__, "[VBoxGuest] [Heartbeat] Sending...\n"
; Отправить запрос
stdcall vmmdev_send_request, ebx
; Проверить результат
mov eax, [edi + VMMDEV_GUEST_HEARTBEAT.header.rc]
test eax, eax
js .error
; DEBUGF __DEBUG_HB__, "[VBoxGuest] [Heartbeat] Sent successfully\n"
xor eax, eax
ret
.error:
DEBUGF 2, "[VBoxGuest] [Heartbeat] Send failed: rc=0x%x\n", eax
ret
.bad_ptr:
DEBUGF 2, "[VBoxGuest] [Heartbeat] Send: bad pointer virt=0x%x phys=0x%x\n", edi, ebx
mov eax, VERR_INVALID_POINTER
ret
endp
proc vmmdev_heartbeat_tick
cmp dword [vbox_hb_enabled], 0
je .done
invoke GetTimerTicks ; eax = timer_ticks
sub eax, [vbox_hb_last_send_time]
cmp eax, [vbox_hb_tick_interval]
jb .done
invoke GetTimerTicks ; eax = текущее время для обновления last_send_time
mov [vbox_hb_last_send_time], eax
call vmmdev_heartbeat_send
test eax, eax
jz .done
DEBUGF 2, "[VBoxGuest] [Heartbeat] Tick: send error 0x%x\n", eax
.done:
ret
endp
; vmmdev_heartbeat_disable — Отключить heartbeat (при выгрузке драйвера)
proc vmmdev_heartbeat_disable uses ebx edi
DEBUGF 2, "[VBoxGuest] [Heartbeat] Disabling...\n"
; Выключить локальный флаг
mov dword [vbox_hb_enabled], 0
mov edi, [vbox_device.heartbeat_config_virt]
test edi, edi
jz .bad_ptr
; Обнулить rc
mov dword [edi + VMMDEV_HEARTBEAT_CONFIGURE.header.rc], 0
; Отключить на хосте
mov dword [edi + VMMDEV_HEARTBEAT_CONFIGURE.f_enabled], 0
mov dword [edi + VMMDEV_HEARTBEAT_CONFIGURE.c_ns_interval], 0
mov dword [edi + VMMDEV_HEARTBEAT_CONFIGURE.c_ns_interval_high], 0
; Отправить запрос
mov ebx, [vbox_device.heartbeat_config_phys]
stdcall vmmdev_send_request, ebx
mov eax, [edi + VMMDEV_HEARTBEAT_CONFIGURE.header.rc]
test eax, eax
js .error
DEBUGF 2, "[VBoxGuest] [Heartbeat] Disabled\n"
xor eax, eax
ret
.error:
DEBUGF 2, "[VBoxGuest] [Heartbeat] Disable failed: rc=0x%x\n", eax
ret
.bad_ptr:
mov eax, VERR_INVALID_POINTER
ret
endp
REGISTER_SERVICE svc_heartbeat_name, 0, 0, \
vmmdev_heartbeat_init, 0, vmmdev_heartbeat_disable, 0, vmmdev_heartbeat_tick, AUTOSTART_HEARTBEAT