Intel VTX

Тема в разделе "WASM.X64", создана пользователем Synth, 12 фев 2008.

  1. Synth

    Synth New Member

    Публикаций:
    0
    Регистрация:
    29 окт 2007
    Сообщения:
    50
    кто-то работал с интеловских VTX? у кого-то получилось запустить?
     
  2. IceStudent

    IceStudent Active Member

    Публикаций:
    0
    Регистрация:
    2 окт 2003
    Сообщения:
    4.300
    Адрес:
    Ukraine
  3. rei3er

    rei3er maxim

    Публикаций:
    0
    Регистрация:
    15 янв 2007
    Сообщения:
    917
    Адрес:
    minsk
    получилось
     
  4. k3internal

    k3internal New Member

    Публикаций:
    0
    Регистрация:
    11 янв 2007
    Сообщения:
    607
    каэш получилось.
     
  5. Synth

    Synth New Member

    Публикаций:
    0
    Регистрация:
    29 окт 2007
    Сообщения:
    50
    у меня такая проблема.
    я инициализирую VMCS. вроде всё делаю по даташиту. по крайней мере не выдаётся ошибка о неправильной инициализации контрольной области или области хоста.

    затем делаю vmlaunch ... и всё виснет. не бсодит, а именно виснет, ввиду чего капец осложняется отладка, ибо не видно почему произошло зависание.

    задачу я себе поставил написать что-то вроде bluepill'а, только для интела. т.е. сделать гипервизор, который бы выходил на определённых ивентах из оригинальной винды (х64), выполняющейся в виртуальном режиме, ну и выводил бы что-то в дебаг.
    для гипервизора выделяю отдельный стек.
    у меня есть подозрение что зависает по причине какой-то неправильной инициализации сегментных селекторов.
    я беру селекторы, парсю гдт, заношу базу, лимит и аттрибуты, а селектору перед записью в VMCS делаю (& ~7), поскольку в даташите написано, что TI и RPL должны быть равны 0.

    может ли кто-то выложить код инициализации VMCS? думаю что ошибка где-то в инициализации гостевой части.
     
  6. rei3er

    rei3er maxim

    Публикаций:
    0
    Регистрация:
    15 янв 2007
    Сообщения:
    917
    Адрес:
    minsk
    Synth
    без кода помочь трудно
    выкладывай весь код
     
  7. Synth

    Synth New Member

    Публикаций:
    0
    Регистрация:
    29 окт 2007
    Сообщения:
    50
    мой код инициализации VMCS
    Код (Text):
    1.     ULONG64 vmx_basic_msr = __readmsr(MSR_IA32_VMX_BASIC);
    2.     ULONG32 vmcs_revision_id = (ULONG32)vmx_basic_msr;
    3.  
    4.     PVMCS p_vmcs = (PVMCS)ExAllocatePool(NonPagedPool, VMCS_SIZE);
    5.     if (!p_vmcs)
    6.     {
    7.         DBG_PRINT(("Cannot allocate memory for VMCS region!"));
    8.         DBG_PRINT(("Cannot initialize VMCS!"));
    9.         DBG_END((0));
    10.         return FALSE;
    11.     }
    12.     memset((PVOID)p_vmcs, 0, VMCS_SIZE);
    13.     p_vmcs->vmcs_revision_id = vmcs_revision_id;
    14.  
    15.     PHYSICAL_ADDRESS pa_vmcs = MmGetPhysicalAddress((PVOID)p_vmcs);
    16.  
    17.     _vmclear(&pa_vmcs);
    18.     _vmptrld(&pa_vmcs);
    19.  
    20.     ULONG64 hypervisor_stack_top = (ULONG64)ExAllocatePool(NonPagedPool, KERNEL_STACK_SIZE);
    21.     memset((PVOID)hypervisor_stack_top, 0, KERNEL_STACK_SIZE);
    22.     ULONG64 hypervisor_stack_bottom = hypervisor_stack_top + KERNEL_STACK_SIZE;
    23.  
    24.     SEGMENT_SELECTOR es;
    25.     SEGMENT_SELECTOR cs;
    26.     SEGMENT_SELECTOR ss;
    27.     SEGMENT_SELECTOR ds;
    28.     SEGMENT_SELECTOR fs;
    29.     SEGMENT_SELECTOR gs;
    30.     SEGMENT_SELECTOR tr;
    31.     SEGMENT_SELECTOR ldt;
    32.     segment_selector_init(&es,  RegGetEs(),       GetGdtBase());
    33.     segment_selector_init(&cs,  RegGetCs(),       GetGdtBase());
    34.     segment_selector_init(&ss,  RegGetSs(),       GetGdtBase());
    35.     segment_selector_init(&ds,  RegGetDs(),       GetGdtBase());
    36.     segment_selector_init(&fs,  RegGetFs(),       GetGdtBase());
    37.     segment_selector_init(&gs,  RegGetGs(),       GetGdtBase());
    38.     segment_selector_init(&tr,  GetTrSelector(),  GetGdtBase());
    39.     segment_selector_init(&ldt, GetLDTSelector(), GetGdtBase());
    40.  
    41.     // init guest state area
    42.     _vmwrite(GUEST_CR0, __readcr0());
    43.     _vmwrite(GUEST_CR3, __readcr3());
    44.     _vmwrite(GUEST_CR4, __readcr4());
    45.     _vmwrite(GUEST_DR7, RegGetDr7());
    46.  
    47.     _vmwrite(GUEST_GDTR_BASE, GetGdtBase());
    48.     _vmwrite(GUEST_GDTR_LIMIT, GetGdtLimit());
    49.     _vmwrite(GUEST_IDTR_BASE, GetIdtBase());
    50.     _vmwrite(GUEST_IDTR_LIMIT, GetIdtLimit());
    51.  
    52.     _vmwrite(GUEST_LDTR_BASE, ldt.base);
    53.     _vmwrite(GUEST_LDTR_LIMIT, ldt.limit);
    54.     _vmwrite(GUEST_LDTR_AR_BYTES, ldt.ar.all);
    55.     _vmwrite(GUEST_LDTR_SELECTOR, ldt.selector.all);
    56.  
    57.     _vmwrite(GUEST_TR_BASE, tr.base);
    58.     _vmwrite(GUEST_TR_LIMIT, tr.limit);
    59.     _vmwrite(GUEST_TR_AR_BYTES, tr.ar.all);
    60.     _vmwrite(GUEST_TR_SELECTOR, tr.selector.all);
    61.    
    62.     _vmwrite(GUEST_ES_SELECTOR, es.selector.all);
    63.     _vmwrite(GUEST_ES_LIMIT, es.limit);
    64.     _vmwrite(GUEST_ES_AR_BYTES, es.ar.all);
    65.     _vmwrite(GUEST_ES_BASE, es.base);
    66.  
    67.     _vmwrite(GUEST_CS_SELECTOR, cs.selector.all);
    68.     _vmwrite(GUEST_CS_LIMIT, cs.limit);
    69.     _vmwrite(GUEST_CS_AR_BYTES, cs.ar.all);
    70.     _vmwrite(GUEST_CS_BASE, cs.base);
    71.  
    72.     _vmwrite(GUEST_SS_SELECTOR, ss.selector.all);
    73.     _vmwrite(GUEST_SS_LIMIT, ss.limit);
    74.     _vmwrite(GUEST_SS_AR_BYTES, ss.ar.all);
    75.     _vmwrite(GUEST_SS_BASE, ss.base);
    76.  
    77.     _vmwrite(GUEST_DS_SELECTOR, ds.selector.all);
    78.     _vmwrite(GUEST_DS_LIMIT, ds.limit);
    79.     _vmwrite(GUEST_DS_AR_BYTES, ds.ar.all);
    80.     _vmwrite(GUEST_DS_BASE, ds.base);
    81.  
    82.     _vmwrite(GUEST_FS_SELECTOR, fs.selector.all);
    83.     _vmwrite(GUEST_FS_LIMIT, fs.limit);
    84.     _vmwrite(GUEST_FS_AR_BYTES, fs.ar.all);
    85.     _vmwrite(GUEST_FS_BASE, fs.base);
    86.  
    87.     _vmwrite(GUEST_GS_SELECTOR, gs.selector.all);
    88.     _vmwrite(GUEST_GS_LIMIT, gs.limit);
    89.     _vmwrite(GUEST_GS_AR_BYTES, gs.ar.all);
    90.     _vmwrite(GUEST_GS_BASE, gs.base);
    91.  
    92.     _vmwrite(GUEST_IA32_DEBUGCTL, __readmsr(MSR_IA32_DEBUGCTL));
    93.  
    94.     _vmwrite(GUEST_SYSENTER_CS,  __readmsr(MSR_IA32_SYSENTER_CS));
    95.     _vmwrite(GUEST_SYSENTER_ESP, __readmsr(MSR_IA32_SYSENTER_ESP));
    96.     _vmwrite(GUEST_SYSENTER_EIP, __readmsr(MSR_IA32_SYSENTER_EIP));
    97.  
    98.     _vmwrite(VMCS_LINK_POINTER, 0xffffffffffffffff); /* VMCS link pointer (64 bits). This field is included for future expansion. Software
    99.                                                      should set this field to FFFFFFFF_FFFFFFFFH to avoid VM-entry failures (see
    100.                                                      Section 22.3.1.5)*/
    101.    
    102.     // init host state area
    103.     _vmwrite(HOST_CR0, __readcr0());
    104.     _vmwrite(HOST_CR3, __readcr3());
    105.     _vmwrite(HOST_CR4, __readcr4());
    106.     _vmwrite(HOST_RSP, hypervisor_stack_bottom);
    107.  
    108.     _vmwrite(HOST_ES_SELECTOR, es.selector.all & ~7);
    109.     _vmwrite(HOST_DS_SELECTOR, ds.selector.all & ~7);
    110.     _vmwrite(HOST_CS_SELECTOR, cs.selector.all & ~7);
    111.     _vmwrite(HOST_SS_SELECTOR, ss.selector.all & ~7);
    112.     _vmwrite(HOST_FS_SELECTOR, fs.selector.all & ~7);
    113.     _vmwrite(HOST_GS_SELECTOR, gs.selector.all & ~7);
    114.     _vmwrite(HOST_TR_SELECTOR, tr.selector.all & ~7);
    115.  
    116.     _vmwrite(HOST_FS_BASE, fs.base);
    117.     _vmwrite(HOST_GS_BASE, gs.base);
    118.     _vmwrite(HOST_TR_BASE, tr.base);
    119.     _vmwrite(HOST_GDTR_BASE, GetGdtBase());
    120.     _vmwrite(HOST_IDTR_BASE, GetIdtBase());
    121.  
    122.     _vmwrite(HOST_IA32_SYSENTER_ESP, __readmsr(MSR_IA32_SYSENTER_ESP));
    123.     _vmwrite(HOST_IA32_SYSENTER_EIP, __readmsr(MSR_IA32_SYSENTER_EIP));
    124.     _vmwrite(HOST_IA32_SYSENTER_CS,  __readmsr(MSR_IA32_SYSENTER_CS));
    125.  
    126.  
    127.     // init VM-EXECUTION CONTROL FIELDS
    128.     ULONG64 vmx_pinbased_ctls_msr   = __readmsr(MSR_IA32_VMX_PINBASED_CTLS);
    129.     ULONG64 vmx_procbased_ctls_msr  = __readmsr(MSR_IA32_VMX_PROCBASED_CTLS);
    130.     ULONG64 vmx_exit_ctls_msr       = __readmsr(MSR_IA32_VMX_EXIT_CTLS);
    131.     ULONG64 vmx_entry_ctls_msr      = __readmsr(MSR_IA32_VMX_ENTRY_CTLS);
    132.  
    133.     ULONG32 vmx_pinbased_ctls       = (ULONG32)vmx_pinbased_ctls_msr;// & (ULONG32)(vmx_pinbased_ctls_msr >> 32);
    134.     ULONG32 vmx_procbased_ctls      = (ULONG32)vmx_procbased_ctls_msr;// & (ULONG32)(vmx_procbased_ctls_msr >> 32);
    135.     ULONG32 vmx_exit_ctls           = (ULONG32)vmx_exit_ctls_msr;
    136.     ULONG32 vmx_entry_ctls          = (ULONG32)vmx_entry_ctls_msr;
    137.     vmx_exit_ctls   |= EXIT_CTRLS_HOST_ADDR_SPACE_SIZE;
    138.     vmx_entry_ctls  |= ENTRY_CTRLS_IA32E_MODE_GUEST;
    139.  
    140.     _vmwrite(PIN_BASED_VM_EXEC_CONTROL, vmx_pinbased_ctls);
    141.     _vmwrite(CPU_BASED_VM_EXEC_CONTROL1, vmx_procbased_ctls);
    142.     _vmwrite(VM_EXIT_CONTROLS, vmx_exit_ctls);
    143.     _vmwrite(VM_ENTRY_CONTROLS, vmx_entry_ctls);
    144.  
    145.     _vmwrite(CR0_GUEST_HOST_MASK, 0xffffffffffffffff);
    146.     _vmwrite(CR4_GUEST_HOST_MASK, 0xffffffffffffffff);
    147.     _vmwrite(CR0_READ_SHADOW, __readcr0());
    148.     _vmwrite(CR4_READ_SHADOW, __readcr4());
    после инициализации вызываю процедуру subvert();
    Код (Text):
    1. subvert PROC
    2.         push_all
    3.  
    4.         mov             rdx, offset __vmlaunch_done
    5.         mov             rcx, GUESR_RIP
    6.         call            _vmwrite
    7.  
    8.         mov             rdx, rsp
    9.         mov             rcx, GUESR_RSP
    10.         call            _vmwrite
    11.  
    12.         mov             rdx, offset vmx_on_exit
    13.         mov             rcx, HOST_RIP
    14.         call            _vmwrite
    15.  
    16.         cli
    17.  
    18.         pushfq
    19.         pop             rdx
    20.         mov             rcx, GUEST_RFLAGS
    21.         call            _vmwrite
    22.  
    23.         vmlaunch
    24.  
    25. ALIGN 16
    26.  
    27.     __vmlaunch_done:
    28.         jc              __vmlaunch_cflag
    29.         jz              __vmlaunch_zflag
    30.  
    31.         mov             qword ptr [rsp], 0
    32.  
    33.     __vmlaunch_ret:
    34.         pop_all
    35.         sti
    36.         ret
    37.  
    38.     __vmlaunch_cflag:
    39.         mov             qword ptr [rsp], 1              ; rax == 1 -- cflag
    40.         jmp             __vmlaunch_ret
    41.  
    42.     __vmlaunch_zflag:
    43.         mov             qword ptr [rsp], 2              ; rax == 2 -- zflag
    44.         jmp             __vmlaunch_ret
    45. subvert ENDP
    46.  
    47.  
    48.  
    49.  
    50.  
    51. vmx_on_exit PROC
    52.         push_all
    53.  
    54.         mov                 ax, cs
    55.         and                 ax, 3                           ; cpl == 0 ?
    56.         jz                  __vm_exit_start
    57.         swapgs
    58.        
    59.     __vm_exit_start:
    60.         sub                 rsp, 20h
    61.         call                vmx_exit_dispatcher
    62.         add                 rsp, 20h
    63.  
    64.         mov                 ax, cs
    65.         and                 ax, 3                           ; cpl == 0 ?
    66.         jz                  __vm_exit_end
    67.         swapgs
    68.     __vm_exit_end:
    69.  
    70.         mov                 rcx, GUESR_RIP
    71.         call                _vmread
    72.  
    73.         mov                 rdx, rax
    74.  
    75.         mov                 rcx, VM_EXIT_INSTRUCTION_LEN
    76.         call                _vmread
    77.        
    78.         add                 rdx, rax
    79.         mov                 rcx, GUESR_RIP
    80.         call                _vmwrite  
    81.  
    82.         pop_all
    83.  
    84.         vmresume
    85. vmx_on_exit ENDP
    ну и как бы после выполнения сабвёрта комп виснет намертво. без бсода.
    никак не соображу где копать...
     
  8. k3internal

    k3internal New Member

    Публикаций:
    0
    Регистрация:
    11 янв 2007
    Сообщения:
    607
    Synth
    ты чем ладишь ?
     
  9. IceStudent

    IceStudent Active Member

    Публикаций:
    0
    Регистрация:
    2 окт 2003
    Сообщения:
    4.300
    Адрес:
    Ukraine
    k3internal
    А чем там можно ладить? Только удалённая отладка по кабелю.. Софтварные эмуляторы вряд ли уже умеют эмулировать виртуализацию.
     
  10. Synth

    Synth New Member

    Публикаций:
    0
    Регистрация:
    29 окт 2007
    Сообщения:
    50
    а всё таки дельные идеи какие-то будут? читаю исходники ксена и мне всё больше кажется что я неправильно инициализирую сегменты...
     
  11. rei3er

    rei3er maxim

    Публикаций:
    0
    Регистрация:
    15 янв 2007
    Сообщения:
    917
    Адрес:
    minsk
    Synth
    1. у тебя MP-система?
    2. во всех следующих случаях затирается последний сохраненный (push_all) регистр
    3. зачем эти инструкции?
    CPL будет равен нулю в любом случае
     
  12. Synth

    Synth New Member

    Публикаций:
    0
    Регистрация:
    29 окт 2007
    Сообщения:
    50
    1. система МР. я это учитываю, процессоры переключаю отдельно. код доставки на процессор для простоты опустил.

    2. mov qword ptr [rsp] - я же там в комментариях написал - rax. последний сохранённый регистр, через который обратно передаётся код результата выполнения vmlaunch.

    3. да, тут я немного просчитался, поскольку переносил код с работающего SVMа. тут надо по другому... но тем не менее без этого кода тоже не работает.

    господа, если у вас всё получилось, то выложите хоть кто-то код своей инициализации...
     
  13. rei3er

    rei3er maxim

    Публикаций:
    0
    Регистрация:
    15 янв 2007
    Сообщения:
    917
    Адрес:
    minsk
    Synth
    при выполнении vmlaunch возможно 3 варианта действий
    1. на первом этапе проверок VMCS произошла ошибка => переход на __vmlaunch_done и завершение функции с ошибкой
    2. vmlaunch завершился успешно => переход в VMX non-root
    3. на втором этапе проверок VMCS произошла ошибка => загрузка host-состояния и переход на vmx_on_exit
    в первом случае зависания быть не может по определению
    в третьем случае поле VM-Exit Reason в VMCS содержит код ошибки, а VM-Exit Qualification - описание ошибки
    при этом IF в RFLAGS сброшен
    поэтому, если где-то в vmx_exit_dispatcher, возможно потенциальное зацикливание, возможно и зависание
    аналогичная ситуация и во-втором случае, если осуществляется VM-Exit
     
  14. rei3er

    rei3er maxim

    Публикаций:
    0
    Регистрация:
    15 янв 2007
    Сообщения:
    917
    Адрес:
    minsk
    насчет MP
    у тебя точно все процессоры инициализированы (vmxon) перед vmlaunch?
     
  15. Synth

    Synth New Member

    Публикаций:
    0
    Регистрация:
    29 окт 2007
    Сообщения:
    50
    1. так и происходит если преднамеренно не инициализировать какое-то важное поле.

    3. сейчас в vmx_exit_dispatcher просто вызывается KeBugCheck, никакого зацикливания быть не может. скорее всего сюда мы никогда не заходим, поскольку виснем намертво.

    МП учтён сто процентов. ибо SVM от AMD мне удалось запустить на многопроцессорной машине. работает идеально.
    все vmxon есть, всё работает. проверено.

    попробую ещё раз попросить код... если не хотите светить - скиньте в личку. мне просто надо сравнить и я сам пойму в чём у меня ошибка.
     
  16. IceStudent

    IceStudent Active Member

    Публикаций:
    0
    Регистрация:
    2 окт 2003
    Сообщения:
    4.300
    Адрес:
    Ukraine
    rei3er
    А вот насчёт МР - где-то видел пример vmx, который поставлялся в виде отдельного драйвера под каждый процессор. Мне непонятна работа системы в промежутке между переходом первого ядра и всех остальных. Возможна ли нормальная работа системы (ОС), когда одно ядро переключили в VMX-on состояние (или даже перешли в vmx non-root), а остальные ядра работают как есть?
     
  17. rei3er

    rei3er maxim

    Публикаций:
    0
    Регистрация:
    15 янв 2007
    Сообщения:
    917
    Адрес:
    minsk
    не проверял, но думаю да, работать будет
    в этом случае, однако, любая генерация виртуализируемым CPU неперехватываемого гипервизором IPI (когда для целевого CPU не включено расширение VMX) может привести к потере контроля над гостевой ОС или детекту гипервизора
    после включения VMX CPU находится в режиме VMX root
    при этом нет никакой активной VM
    т. е вообще проблемы нету
    после того, как код включения VMX отработает на каждом CPU, можно запускать какую-либо VM
     
  18. Synth

    Synth New Member

    Публикаций:
    0
    Регистрация:
    29 окт 2007
    Сообщения:
    50
    стоп. а вы уверены в том что сначала надо сделать vmxon на каждом процессоре, а уже потом переводить кого-то в виртуальный режим? на мой взгляд это не обязательно.
    например SVM прекрасно работает только на одном ядре. никаких нарушений в стабильности работы винды в таком режиме я не выявил.

    но это мы отвлеклись от темы. дельные советы по поводу того, почему у меня может виснуть? посмотрите, так ли у вас инициализируются сегментные селекторы?
     
  19. rei3er

    rei3er maxim

    Публикаций:
    0
    Регистрация:
    15 янв 2007
    Сообщения:
    917
    Адрес:
    minsk
    читай мой пост выше
    поставь отладочный вывод на __vmlaunch_done и vmx_on_exit
    я же код отправил
     
  20. Synth

    Synth New Member

    Публикаций:
    0
    Регистрация:
    29 окт 2007
    Сообщения:
    50
    да, код получил, просто не заметил. завтра проверю, ибо компа с VTXом щас нет под рукой