Hello, In order to understand why a particular OS using the BIOS 'apm' module is able to poweroff on VMWare but not on VirtualBox(v4.3.38.1), we analyzed the VirtualBox module at source level. The OS is using 32-bit protected interface of APM to issue power off command to APM module of VirtualBox. Our analysis is that the issue is in VirtualBox’s implementation of APM’s ‘power off’ in 32-bit protected mode. Please see the detailed explanation below: In 32-bit protected mode when, user issues power off command then the Guest OS calls the function ‘apm_pm32_entry’ of VirtualBox to change the power state to power off. The function ‘apm_pm32_entry’ in VirtualBox then calls function ‘apm_pm16_entry_from_32’ to handle the user call. This function validates the arguments and calls function ‘apm_worker’ to do the actual work: <snip> ; APM function dispatch table apm_disp: dw offset apmf_disconnect ; 04h dw offset apmf_idle ; 05h dw offset apmf_busy ; 06h dw offset apmf_set_state ; 07h dw offset apmf_enable ; 08h dw offset apmf_restore ; 09h dw offset apmf_get_status ; 0Ah dw offset apmf_get_event ; 0Bh dw offset apmf_pwr_state ; 0Ch dw offset apmf_dev_pm ; 0Dh dw offset apmf_version ; 0Eh dw offset apmf_engage ; 0Fh dw offset apmf_get_caps ; 10h apm_disp_end: apm_worker proc near sti ; TODO ?? necessary ?? push ax ; check if function is supported... xor ah, ah sub al, 4 mov bp, ax shl bp, 1 cmp al, (apm_disp_end - apm_disp) / 2 pop ax mov ah, 53h ; put back APM function jae apmw_bad_func ; validate function range jmp apm_disp[bp] ; and dispatch apmf_disconnect: ; function 04h jmp apmw_success apmf_idle: ; function 05h sti hlt jmp apmw_success apmf_busy: ; function 06h ; jmp apmw_success apmf_set_state: ; function 07h ; jmp apmw_success apmf_enable: ; function 08h jmp apmw_success apmf_restore: ; function 09h ; jmp apmw_success apmf_get_status: ; function 0Ah jmp apmw_bad_func apmf_get_event: ; function 0Bh mov ah, 80h jmp apmw_failure apmf_pwr_state: ; function 0Ch apmf_dev_pm: ; function 0Dh jmp apmw_bad_func apmf_version: ; function 0Eh mov ax, 0102h jmp apmw_success apmf_engage: ; function 0Fh ; TODO do something? jmp apmw_success apmf_get_caps: ; function 10h mov bl, 0 ; no batteries mov cx, 0 ; no special caps jmp apmw_success apmw_success: clc ; successful return ret apmw_bad_func: mov ah, 09h ; unrecognized device ID - generic apmw_failure: stc ; error for unsupported functions ret apm_worker endp </snip> The power off event corresponds to function value 0x7. So, from the dispatch table the code jumps to tag ‘apmf_set_state’. As we can see in above code for this tag code simply calls ‘apmw_success’ which returns the call back. So, for 32-bit protected mode interface and for the power off event VirtualBox is not actually powering off the system but simply returns the calls back as success. Due, to this the OS system does not power off on VirtualBox We also cross checked the 32-bit protected code on QEMU’s seabios. In seabios the 32-bit protected mode function is ‘entry_apm32’ in file ‘romlayout.S’. This function then calls the function ‘handle_apm’ to handle the APM call: <snip> void VISIBLE16 VISIBLE32SEG handle_apm(struct bregs *regs) { debug_enter(regs, DEBUG_HDL_apm); handle_1553(regs); } void handle_1553(struct bregs *regs) { if (! CONFIG_APMBIOS) { set_code_invalid(regs, RET_EUNSUPPORTED); return; } //debug_stub(regs); switch (regs->al) { case 0x00: handle_155300(regs); break; case 0x01: handle_155301(regs); break; case 0x02: handle_155302(regs); break; case 0x03: handle_155303(regs); break; case 0x04: handle_155304(regs); break; case 0x05: handle_155305(regs); break; case 0x06: handle_155306(regs); break; case 0x07: handle_155307(regs); break; case 0x08: handle_155308(regs); break; case 0x0a: handle_15530a(regs); break; case 0x0b: handle_15530b(regs); break; case 0x0e: handle_15530e(regs); break; case 0x0f: handle_15530f(regs); break; case 0x10: handle_155310(regs); break; default: handle_1553XX(regs); break; } } // APM Set Power State static void handle_155307(struct bregs *regs) { if (regs->bx != 1) { set_success(regs); return; } switch (regs->cx) { case 1: dprintf(1, "APM standby request\n"); break; case 2: dprintf(1, "APM suspend request\n"); break; case 3: apm_shutdown(); break; } set_success(regs); } void apm_shutdown(void) { u16 pm1a_cnt = GET_GLOBAL(acpi_pm1a_cnt); if (pm1a_cnt) outw(0x2000, pm1a_cnt); irq_disable(); for (;;) hlt(); } </snip> So, QEMU issues an internal ACPI request to power off the system when user issues a power off in 32-bit protected mode. However, the real mode interface of APM module works fine in VirtualBox. When user issues power off command and since this is not 32-bit protected mode the function ‘apm_pm32_entry’ is not called instead call comes to function ‘apm_function’ with AL set to 0x7 and CX set to 0x3: <snip> case APM_SET_PWR: // @todo: validate device ID // @todo: validate current connection state switch (CX) { case APM_PS_STANDBY: apm_out_str("Standby", APM_PORT); break; case APM_PS_SUSPEND: apm_out_str("Suspend", APM_PORT); break; case APM_PS_OFF: apm_out_str("Shutdown", APM_PORT); /* Should not return. */ break; default: SET_AH(APM_ERR_INVAL_PARAM); SET_CF(); } break; </snip> In this case the code writes a string “Shutdown” on port APM_PORT i.e 0x8900. This port number is polled by VirtualBox Bochs BIOS. On receiving data on this port the function ‘pcbiosIOPortWrite’ in file ‘DevPcBios.cpp’ is called. It handles it as follows: <snip> /* * Bochs BIOS shutdown request. */ if (cb == 1 && Port == 0x8900) { static const unsigned char szShutdown[] = "Shutdown"; PDEVPCBIOS pThis = PDMINS_2_DATA(pDevIns, PDEVPCBIOS); if (u32 == szShutdown[pThis->iShutdown]) { pThis->iShutdown++; if (pThis->iShutdown == 8) { pThis->iShutdown = 0; LogRel(("PcBios: 8900h shutdown request\n")); return PDMDevHlpVMPowerOff(pDevIns); } } else pThis->iShutdown = 0; return VINF_SUCCESS; } </snip> As we can see it issues a power off request if the string received on port is “Shutdown”. If you can provide your inputs on following points then it will be very helpful to u 1. Have you come across a similar issue and what would be your suggestion on fixing this? 2. We think that the fix should be in VirtualBox and is this something you can do or we can do or we need to raise this issue with VirtualBox. Please suggest? Regards, Ashutosh +91 9899653573 _______________________________________________ freebsd-emulation@freebsd.org mailing list https://lists.freebsd.org/mailman/listinfo/freebsd-emulation To unsubscribe, send any mail to "freebsd-emulation-unsubscr...@freebsd.org"