Changeset 37444 in vbox for trunk/src/VBox/Devices
- Timestamp:
- Jun 14, 2011 2:34:52 PM (14 years ago)
- Location:
- trunk/src/VBox/Devices
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/PC/DevACPI.cpp
r37391 r37444 5 5 6 6 /* 7 * Copyright (C) 2006-20 09Oracle Corporation7 * Copyright (C) 2006-2011 Oracle Corporation 8 8 * 9 9 * This file is part of VirtualBox Open Source Edition (OSE), as … … 22 22 #include <VBox/vmm/pdmdev.h> 23 23 #include <VBox/vmm/pgm.h> 24 #include <VBox/vmm/dbgftrace.h> 24 25 #include <VBox/log.h> 25 26 #include <VBox/param.h> … … 52 53 * Defined Constants And Macros * 53 54 *******************************************************************************/ 55 #ifdef IN_RING3 56 /** Locks the device state, ring-3 only. */ 57 # define DEVACPI_LOCK_R3(a_pThis) \ 58 do { \ 59 int rcLock = PDMCritSectEnter(&(a_pThis)->CritSect, VERR_IGNORED); \ 60 AssertRC(rcLock); \ 61 } while (0) 62 #endif 63 /** Unlocks the device state (all contexts). */ 64 #define DEVACPI_UNLOCK(a_pThis) \ 65 do { PDMCritSectLeave(&(a_pThis)->CritSect); } while (0) 66 67 54 68 #define DEBUG_HEX 0x3000 55 69 #define DEBUG_CHR 0x3001 … … 198 212 { 199 213 PCIDevice dev; 214 /** Critical section protecting the ACPI state. */ 215 PDMCRITSECT CritSect; 216 200 217 uint16_t pm1a_en; 201 218 uint16_t pm1a_sts; … … 205 222 uint64_t u64PmTimerInitial; 206 223 uint64_t u64PmTimerLastSeen; 207 PTMTIMERR3 tsR3;208 PTMTIMERR0 tsR0;209 PTMTIMERRC tsRC;224 PTMTIMERR3 pPmTimerR3; 225 PTMTIMERR0 pPmTimerR0; 226 PTMTIMERRC pPmTimerRC; 210 227 211 228 uint32_t gpe0_en; … … 693 710 *******************************************************************************/ 694 711 RT_C_DECLS_BEGIN 695 PDMBOTHCBDECL(int) acpiPMTmrRead( PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb); 712 PDMBOTHCBDECL(int) acpiPMTmrRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb); 713 RT_C_DECLS_END 696 714 #ifdef IN_RING3 697 PDMBOTHCBDECL(int) acpiPm1aEnRead( PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb); 698 PDMBOTHCBDECL(int) acpiPM1aEnWrite( PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb); 699 PDMBOTHCBDECL(int) acpiPm1aStsRead( PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb); 700 PDMBOTHCBDECL(int) acpiPM1aStsWrite( PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb); 701 PDMBOTHCBDECL(int) acpiPm1aCtlRead( PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb); 702 PDMBOTHCBDECL(int) acpiPM1aCtlWrite( PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb); 703 PDMBOTHCBDECL(int) acpiSmiWrite( PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb); 704 PDMBOTHCBDECL(int) acpiBatIndexWrite( PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb); 705 PDMBOTHCBDECL(int) acpiBatDataRead( PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb); 706 PDMBOTHCBDECL(int) acpiSysInfoDataRead( PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb); 707 PDMBOTHCBDECL(int) acpiSysInfoDataWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb); 708 PDMBOTHCBDECL(int) acpiGpe0EnRead( PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb); 709 PDMBOTHCBDECL(int) acpiGpe0EnWrite( PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb); 710 PDMBOTHCBDECL(int) acpiGpe0StsRead( PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb); 711 PDMBOTHCBDECL(int) acpiGpe0StsWrite( PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb); 712 PDMBOTHCBDECL(int) acpiResetWrite( PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb); 715 static int acpiPlantTables(ACPIState *s); 716 #endif 717 718 #ifdef IN_RING3 719 720 /* SCI IRQ */ 721 DECLINLINE(void) acpiSetIrq(ACPIState *s, int level) 722 { 723 if (s->pm1a_ctl & SCI_EN) 724 PDMDevHlpPCISetIrq(s->pDevIns, -1, level); 725 } 726 727 DECLINLINE(uint32_t) pm1a_pure_en(uint32_t en) 728 { 729 return en & ~(RSR_EN | IGN_EN); 730 } 731 732 DECLINLINE(uint32_t) pm1a_pure_sts(uint32_t sts) 733 { 734 return sts & ~(RSR_STS | IGN_STS); 735 } 736 737 DECLINLINE(int) pm1a_level(ACPIState *s) 738 { 739 return (pm1a_pure_en(s->pm1a_en) & pm1a_pure_sts(s->pm1a_sts)) != 0; 740 } 741 742 DECLINLINE(int) gpe0_level(ACPIState *s) 743 { 744 return (s->gpe0_en & s->gpe0_sts) != 0; 745 } 746 747 /** 748 * Used by acpiPM1aStsWrite, acpiPM1aEnWrite, acpiPmTimer, 749 * acpiPort_PowerBuffonPress and acpiPort_SleepButtonPress to 750 * update the GPE0.STS and GPE0.EN registers and trigger IRQs. 751 * 752 * Caller must hold the state lock. 753 * 754 * @param pThis The ACPI instance. 755 * @param sts The new GPE0.STS value. 756 * @param en The new GPE0.EN value. 757 */ 758 static void update_pm1a(ACPIState *pThis, uint32_t sts, uint32_t en) 759 { 760 Assert(PDMCritSectIsOwner(&pThis->CritSect)); 761 762 if (gpe0_level(pThis)) 763 return; 764 765 int const old_level = pm1a_level(pThis); 766 int const new_level = (pm1a_pure_en(en) & pm1a_pure_sts(sts)) != 0; 767 768 Log(("update_pm1a() old=%x new=%x\n", old_level, new_level)); 769 770 pThis->pm1a_en = en; 771 pThis->pm1a_sts = sts; 772 773 if (new_level != old_level) 774 acpiSetIrq(pThis, new_level); 775 } 776 777 /** 778 * Used by acpiGpe0StsWrite, acpiGpe0EnWrite, acpiAttach and acpiDetach to 779 * update the GPE0.STS and GPE0.EN registers and trigger IRQs. 780 * 781 * Caller must hold the state lock. 782 * 783 * @param pThis The ACPI instance. 784 * @param sts The new GPE0.STS value. 785 * @param en The new GPE0.EN value. 786 */ 787 static void update_gpe0(ACPIState *pThis, uint32_t sts, uint32_t en) 788 { 789 Assert(PDMCritSectIsOwner(&pThis->CritSect)); 790 791 if (pm1a_level(pThis)) 792 return; 793 794 int const old_level = (pThis->gpe0_en & pThis->gpe0_sts) != 0; 795 int const new_level = (en & sts) != 0; 796 797 pThis->gpe0_en = en; 798 pThis->gpe0_sts = sts; 799 800 if (new_level != old_level) 801 acpiSetIrq(pThis, new_level); 802 } 803 804 /** 805 * Used by acpiPM1aCtlWrite to power off the VM. 806 * 807 * @param pThis The ACPI instance. 808 * @returns Strict VBox status code. 809 */ 810 static int acpiPowerOff(ACPIState *pThis) 811 { 812 int rc = PDMDevHlpVMPowerOff(pThis->pDevIns); 813 if (RT_FAILURE(rc)) 814 AssertMsgFailed(("Could not power down the VM. rc = %Rrc\n", rc)); 815 return rc; 816 } 817 818 /** 819 * Used by acpiPM1aCtlWrite to put the VM to sleep. 820 * 821 * @param pThis The ACPI instance. 822 * @returns Strict VBox status code. 823 */ 824 static int acpiSleep(ACPIState *pThis) 825 { 826 /* We must set WAK_STS on resume (includes restore) so the guest knows that 827 we've woken up and can continue executing code. The guest is probably 828 reading the PMSTS register in a loop to check this. */ 829 int rc; 830 pThis->fSetWakeupOnResume = true; 831 if (pThis->fSuspendToSavedState) 832 { 833 rc = PDMDevHlpVMSuspendSaveAndPowerOff(pThis->pDevIns); 834 if (rc != VERR_NOT_SUPPORTED) 835 AssertRC(rc); 836 else 837 { 838 LogRel(("ACPI: PDMDevHlpVMSuspendSaveAndPowerOff is not supported, falling back to suspend-only\n")); 839 rc = PDMDevHlpVMSuspend(pThis->pDevIns); 840 AssertRC(rc); 841 } 842 } 843 else 844 { 845 rc = PDMDevHlpVMSuspend(pThis->pDevIns); 846 AssertRC(rc); 847 } 848 return rc; 849 } 850 851 852 /** 853 * @interface_method_impl{PDMIACPIPORT,pfnPowerButtonPress} 854 */ 855 static DECLCALLBACK(int) acpiPort_PowerButtonPress(PPDMIACPIPORT pInterface) 856 { 857 ACPIState *pThis = RT_FROM_MEMBER(pInterface, ACPIState, IACPIPort); 858 DEVACPI_LOCK_R3(pThis); 859 860 Log(("acpiPort_PowerButtonPress: handled=%d status=%x\n", pThis->fPowerButtonHandled, pThis->pm1a_sts)); 861 pThis->fPowerButtonHandled = false; 862 update_pm1a(pThis, pThis->pm1a_sts | PWRBTN_STS, pThis->pm1a_en); 863 864 DEVACPI_UNLOCK(pThis); 865 return VINF_SUCCESS; 866 } 867 868 /** 869 * @interface_method_impl{PDMIACPIPORT,pfnGetPowerButtonHandled} 870 */ 871 static DECLCALLBACK(int) acpiPort_GetPowerButtonHandled(PPDMIACPIPORT pInterface, bool *pfHandled) 872 { 873 ACPIState *pThis = RT_FROM_MEMBER(pInterface, ACPIState, IACPIPort); 874 DEVACPI_LOCK_R3(pThis); 875 876 *pfHandled = pThis->fPowerButtonHandled; 877 878 DEVACPI_UNLOCK(pThis); 879 return VINF_SUCCESS; 880 } 881 882 /** 883 * @interface_method_impl{PDMIACPIPORT,pfnGetGuestEnteredACPIMode, Check if the 884 * Guest entered into G0 (working) or G1 (sleeping)} 885 */ 886 static DECLCALLBACK(int) acpiPort_GetGuestEnteredACPIMode(PPDMIACPIPORT pInterface, bool *pfEntered) 887 { 888 ACPIState *pThis = RT_FROM_MEMBER(pInterface, ACPIState, IACPIPort); 889 DEVACPI_LOCK_R3(pThis); 890 891 *pfEntered = (pThis->pm1a_ctl & SCI_EN) != 0; 892 893 DEVACPI_UNLOCK(pThis); 894 return VINF_SUCCESS; 895 } 896 897 /** 898 * @interface_method_impl{PDMIACPIPORT,pfnGetCpuStatus} 899 */ 900 static DECLCALLBACK(int) acpiPort_GetCpuStatus(PPDMIACPIPORT pInterface, unsigned uCpu, bool *pfLocked) 901 { 902 ACPIState *pThis = RT_FROM_MEMBER(pInterface, ACPIState, IACPIPort); 903 DEVACPI_LOCK_R3(pThis); 904 905 *pfLocked = VMCPUSET_IS_PRESENT(&pThis->CpuSetLocked, uCpu); 906 907 DEVACPI_UNLOCK(pThis); 908 return VINF_SUCCESS; 909 } 910 911 /** 912 * Send an ACPI sleep button event. 913 * 914 * @returns VBox status code 915 * @param pInterface Pointer to the interface structure containing the called function pointer. 916 */ 917 static DECLCALLBACK(int) acpiPort_SleepButtonPress(PPDMIACPIPORT pInterface) 918 { 919 ACPIState *pThis = RT_FROM_MEMBER(pInterface, ACPIState, IACPIPort); 920 DEVACPI_LOCK_R3(pThis); 921 922 update_pm1a(pThis, pThis->pm1a_sts | SLPBTN_STS, pThis->pm1a_en); 923 924 DEVACPI_UNLOCK(pThis); 925 return VINF_SUCCESS; 926 } 927 928 /** 929 * Used by acpiPmTimer to re-arm the PM timer. 930 * 931 * The caller is expected to either hold the clock lock or to have made sure 932 * the VM is resetting or loading state. 933 * 934 * @param pThis The ACPI instance. 935 * @param uNow The current time. 936 */ 937 static void acpiPmTimerReset(ACPIState *pThis, uint64_t uNow) 938 { 939 uint64_t uTimerFreq = TMTimerGetFreq(pThis->CTX_SUFF(pPmTimer)); 940 uint64_t uInterval = ASMMultU64ByU32DivByU32(0xffffffff, uTimerFreq, PM_TMR_FREQ); 941 TMTimerSet(pThis->pPmTimerR3, uNow + uInterval); 942 Log(("acpi: uInterval = %RU64\n", uInterval)); 943 } 944 945 /** 946 * @callback_method_impl{FNTMTIMERDEV, PM Timer callback} 947 */ 948 static DECLCALLBACK(void) acpiPmTimer(PPDMDEVINS pDevIns, PTMTIMER pTimer, void *pvUser) 949 { 950 ACPIState *pThis = (ACPIState *)pvUser; 951 Assert(TMTimerIsLockOwner(pThis->pPmTimerR3)); 952 953 DEVACPI_LOCK_R3(pThis); 954 Log(("acpi: pm timer sts %#x (%d), en %#x (%d)\n", 955 pThis->pm1a_sts, (pThis->pm1a_sts & TMR_STS) != 0, 956 pThis->pm1a_en, (pThis->pm1a_en & TMR_EN) != 0)); 957 update_pm1a(pThis, pThis->pm1a_sts | TMR_STS, pThis->pm1a_en); 958 DEVACPI_UNLOCK(pThis); 959 960 acpiPmTimerReset(pThis, TMTimerGet(pThis->pPmTimerR3)); 961 } 962 963 /** 964 * _BST method - used by acpiBatDataRead to implement BAT_STATUS_STATE and 965 * acpiLoadState. 966 * 967 * @returns VINF_SUCCESS. 968 * @param pThis The ACPI instance. 969 */ 970 static int acpiFetchBatteryStatus(ACPIState *pThis) 971 { 972 uint32_t *p = pThis->au8BatteryInfo; 973 bool fPresent; /* battery present? */ 974 PDMACPIBATCAPACITY hostRemainingCapacity; /* 0..100 */ 975 PDMACPIBATSTATE hostBatteryState; /* bitfield */ 976 uint32_t hostPresentRate; /* 0..1000 */ 977 int rc; 978 979 if (!pThis->pDrv) 980 return VINF_SUCCESS; 981 rc = pThis->pDrv->pfnQueryBatteryStatus(pThis->pDrv, &fPresent, &hostRemainingCapacity, 982 &hostBatteryState, &hostPresentRate); 983 AssertRC(rc); 984 985 /* default values */ 986 p[BAT_STATUS_STATE] = hostBatteryState; 987 p[BAT_STATUS_PRESENT_RATE] = hostPresentRate == ~0U ? 0xFFFFFFFF 988 : hostPresentRate * 50; /* mW */ 989 p[BAT_STATUS_REMAINING_CAPACITY] = 50000; /* mWh */ 990 p[BAT_STATUS_PRESENT_VOLTAGE] = 10000; /* mV */ 991 992 /* did we get a valid battery state? */ 993 if (hostRemainingCapacity != PDM_ACPI_BAT_CAPACITY_UNKNOWN) 994 p[BAT_STATUS_REMAINING_CAPACITY] = hostRemainingCapacity * 500; /* mWh */ 995 if (hostBatteryState == PDM_ACPI_BAT_STATE_CHARGED) 996 p[BAT_STATUS_PRESENT_RATE] = 0; /* mV */ 997 998 return VINF_SUCCESS; 999 } 1000 1001 /** 1002 * _BIF method - used by acpiBatDataRead to implement BAT_INFO_UNITS and 1003 * acpiLoadState. 1004 * 1005 * @returns VINF_SUCCESS. 1006 * @param pThis The ACPI instance. 1007 */ 1008 static int acpiFetchBatteryInfo(ACPIState *pThis) 1009 { 1010 uint32_t *p = pThis->au8BatteryInfo; 1011 1012 p[BAT_INFO_UNITS] = 0; /* mWh */ 1013 p[BAT_INFO_DESIGN_CAPACITY] = 50000; /* mWh */ 1014 p[BAT_INFO_LAST_FULL_CHARGE_CAPACITY] = 50000; /* mWh */ 1015 p[BAT_INFO_TECHNOLOGY] = BAT_TECH_PRIMARY; 1016 p[BAT_INFO_DESIGN_VOLTAGE] = 10000; /* mV */ 1017 p[BAT_INFO_DESIGN_CAPACITY_OF_WARNING] = 100; /* mWh */ 1018 p[BAT_INFO_DESIGN_CAPACITY_OF_LOW] = 50; /* mWh */ 1019 p[BAT_INFO_CAPACITY_GRANULARITY_1] = 1; /* mWh */ 1020 p[BAT_INFO_CAPACITY_GRANULARITY_2] = 1; /* mWh */ 1021 1022 return VINF_SUCCESS; 1023 } 1024 1025 /** 1026 * The _STA method - used by acpiBatDataRead to implement BAT_DEVICE_STATUS. 1027 * 1028 * @returns status mask or 0. 1029 * @param pThis The ACPI instance. 1030 */ 1031 static uint32_t acpiGetBatteryDeviceStatus(ACPIState *pThis) 1032 { 1033 bool fPresent; /* battery present? */ 1034 PDMACPIBATCAPACITY hostRemainingCapacity; /* 0..100 */ 1035 PDMACPIBATSTATE hostBatteryState; /* bitfield */ 1036 uint32_t hostPresentRate; /* 0..1000 */ 1037 int rc; 1038 1039 if (!pThis->pDrv) 1040 return 0; 1041 rc = pThis->pDrv->pfnQueryBatteryStatus(pThis->pDrv, &fPresent, &hostRemainingCapacity, 1042 &hostBatteryState, &hostPresentRate); 1043 AssertRC(rc); 1044 1045 return fPresent 1046 ? STA_DEVICE_PRESENT_MASK /* present */ 1047 | STA_DEVICE_ENABLED_MASK /* enabled and decodes its resources */ 1048 | STA_DEVICE_SHOW_IN_UI_MASK /* should be shown in UI */ 1049 | STA_DEVICE_FUNCTIONING_PROPERLY_MASK /* functioning properly */ 1050 | STA_BATTERY_PRESENT_MASK /* battery is present */ 1051 : 0; /* device not present */ 1052 } 1053 1054 /** 1055 * Used by acpiBatDataRead to implement BAT_POWER_SOURCE. 1056 * 1057 * @returns status. 1058 * @param pThis The ACPI instance. 1059 */ 1060 static uint32_t acpiGetPowerSource(ACPIState *pThis) 1061 { 1062 /* query the current power source from the host driver */ 1063 if (!pThis->pDrv) 1064 return AC_ONLINE; 1065 1066 PDMACPIPOWERSOURCE ps; 1067 int rc = pThis->pDrv->pfnQueryPowerSource(pThis->pDrv, &ps); 1068 AssertRC(rc); 1069 return ps == PDM_ACPI_POWER_SOURCE_BATTERY ? AC_OFFLINE : AC_ONLINE; 1070 } 1071 1072 /** 1073 * @callback_method_impl{FNIOMIOPORTOUT, Battery status index} 1074 */ 1075 PDMBOTHCBDECL(int) acpiBatIndexWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb) 1076 { 1077 Log(("acpiBatIndexWrite: %#x (%#x)\n", u32, u32 >> 2)); 1078 if (cb != 4) 1079 return PDMDevHlpDBGFStop(pDevIns, RT_SRC_POS, "cb=%d Port=%u u32=%#x\n", cb, Port, u32); 1080 1081 ACPIState *pThis = (ACPIState *)pvUser; 1082 DEVACPI_LOCK_R3(pThis); 1083 1084 u32 >>= pThis->u8IndexShift; 1085 /* see comment at the declaration of u8IndexShift */ 1086 if (pThis->u8IndexShift == 0 && u32 == (BAT_DEVICE_STATUS << 2)) 1087 { 1088 pThis->u8IndexShift = 2; 1089 u32 >>= 2; 1090 } 1091 Assert(u32 < BAT_INDEX_LAST); 1092 pThis->uBatteryIndex = u32; 1093 1094 DEVACPI_UNLOCK(pThis); 1095 return VINF_SUCCESS; 1096 } 1097 1098 /** 1099 * @callback_method_impl{FNIOMIOPORTIN, Battery status data} 1100 */ 1101 PDMBOTHCBDECL(int) acpiBatDataRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb) 1102 { 1103 if (cb != 4) 1104 return VERR_IOM_IOPORT_UNUSED; 1105 1106 ACPIState *pThis = (ACPIState *)pvUser; 1107 DEVACPI_LOCK_R3(pThis); 1108 1109 int rc = VINF_SUCCESS; 1110 switch (pThis->uBatteryIndex) 1111 { 1112 case BAT_STATUS_STATE: 1113 acpiFetchBatteryStatus(pThis); 1114 /* fall thru */ 1115 case BAT_STATUS_PRESENT_RATE: 1116 case BAT_STATUS_REMAINING_CAPACITY: 1117 case BAT_STATUS_PRESENT_VOLTAGE: 1118 *pu32 = pThis->au8BatteryInfo[pThis->uBatteryIndex]; 1119 break; 1120 1121 case BAT_INFO_UNITS: 1122 acpiFetchBatteryInfo(pThis); 1123 /* fall thru */ 1124 case BAT_INFO_DESIGN_CAPACITY: 1125 case BAT_INFO_LAST_FULL_CHARGE_CAPACITY: 1126 case BAT_INFO_TECHNOLOGY: 1127 case BAT_INFO_DESIGN_VOLTAGE: 1128 case BAT_INFO_DESIGN_CAPACITY_OF_WARNING: 1129 case BAT_INFO_DESIGN_CAPACITY_OF_LOW: 1130 case BAT_INFO_CAPACITY_GRANULARITY_1: 1131 case BAT_INFO_CAPACITY_GRANULARITY_2: 1132 *pu32 = pThis->au8BatteryInfo[pThis->uBatteryIndex]; 1133 break; 1134 1135 case BAT_DEVICE_STATUS: 1136 *pu32 = acpiGetBatteryDeviceStatus(pThis); 1137 break; 1138 1139 case BAT_POWER_SOURCE: 1140 *pu32 = acpiGetPowerSource(pThis); 1141 break; 1142 1143 default: 1144 rc = PDMDevHlpDBGFStop(pDevIns, RT_SRC_POS, "cb=%d Port=%u idx=%u\n", cb, Port, pThis->uBatteryIndex); 1145 *pu32 = UINT32_MAX; 1146 break; 1147 } 1148 1149 DEVACPI_UNLOCK(pThis); 1150 return rc; 1151 } 1152 1153 /** 1154 * @callback_method_impl{FNIOMIOPORTOUT, System info index} 1155 */ 1156 PDMBOTHCBDECL(int) acpiSysInfoIndexWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb) 1157 { 1158 Log(("acpiSysInfoIndexWrite: %#x (%#x)\n", u32, u32 >> 2)); 1159 if (cb != 4) 1160 return PDMDevHlpDBGFStop(pDevIns, RT_SRC_POS, "cb=%d Port=%u u32=%#x\n", cb, Port, u32); 1161 1162 ACPIState *pThis = (ACPIState *)pvUser; 1163 DEVACPI_LOCK_R3(pThis); 1164 1165 if (u32 == SYSTEM_INFO_INDEX_VALID || u32 == SYSTEM_INFO_INDEX_INVALID) 1166 pThis->uSystemInfoIndex = u32; 1167 else 1168 { 1169 /* see comment at the declaration of u8IndexShift */ 1170 if (u32 > SYSTEM_INFO_INDEX_END && pThis->u8IndexShift == 0) 1171 { 1172 if ((u32 >> 2) < SYSTEM_INFO_INDEX_END && (u32 & 0x3) == 0) 1173 pThis->u8IndexShift = 2; 1174 } 1175 1176 u32 >>= pThis->u8IndexShift; 1177 Assert(u32 < SYSTEM_INFO_INDEX_END); 1178 pThis->uSystemInfoIndex = u32; 1179 } 1180 1181 DEVACPI_UNLOCK(pThis); 1182 return VINF_SUCCESS; 1183 } 1184 1185 /** 1186 * @callback_method_impl{FNIOMIOPORTIN, System info data} 1187 */ 1188 PDMBOTHCBDECL(int) acpiSysInfoDataRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb) 1189 { 1190 if (cb != 4) 1191 return VERR_IOM_IOPORT_UNUSED; 1192 1193 ACPIState *pThis = (ACPIState *)pvUser; 1194 DEVACPI_LOCK_R3(pThis); 1195 1196 int rc = VINF_SUCCESS; 1197 unsigned const uSystemInfoIndex = pThis->uSystemInfoIndex; 1198 switch (uSystemInfoIndex) 1199 { 1200 case SYSTEM_INFO_INDEX_LOW_MEMORY_LENGTH: 1201 *pu32 = pThis->cbRamLow; 1202 break; 1203 1204 case SYSTEM_INFO_INDEX_HIGH_MEMORY_LENGTH: 1205 *pu32 = pThis->cbRamHigh >> 16; /* 64KB units */ 1206 Assert(((uint64_t)*pu32 << 16) == pThis->cbRamHigh); 1207 break; 1208 1209 case SYSTEM_INFO_INDEX_USE_IOAPIC: 1210 *pu32 = pThis->u8UseIOApic; 1211 break; 1212 1213 case SYSTEM_INFO_INDEX_HPET_STATUS: 1214 *pu32 = pThis->fUseHpet 1215 ? ( STA_DEVICE_PRESENT_MASK 1216 | STA_DEVICE_ENABLED_MASK 1217 | STA_DEVICE_SHOW_IN_UI_MASK 1218 | STA_DEVICE_FUNCTIONING_PROPERLY_MASK) 1219 : 0; 1220 break; 1221 1222 case SYSTEM_INFO_INDEX_SMC_STATUS: 1223 *pu32 = pThis->fUseSmc 1224 ? ( STA_DEVICE_PRESENT_MASK 1225 | STA_DEVICE_ENABLED_MASK 1226 /* no need to show this device in the UI */ 1227 | STA_DEVICE_FUNCTIONING_PROPERLY_MASK) 1228 : 0; 1229 break; 1230 1231 case SYSTEM_INFO_INDEX_FDC_STATUS: 1232 *pu32 = pThis->fUseFdc 1233 ? ( STA_DEVICE_PRESENT_MASK 1234 | STA_DEVICE_ENABLED_MASK 1235 | STA_DEVICE_SHOW_IN_UI_MASK 1236 | STA_DEVICE_FUNCTIONING_PROPERLY_MASK) 1237 : 0; 1238 break; 1239 1240 case SYSTEM_INFO_INDEX_NIC_ADDRESS: 1241 *pu32 = pThis->u32NicPciAddress; 1242 break; 1243 1244 case SYSTEM_INFO_INDEX_AUDIO_ADDRESS: 1245 *pu32 = pThis->u32AudioPciAddress; 1246 break; 1247 1248 case SYSTEM_INFO_INDEX_POWER_STATES: 1249 *pu32 = RT_BIT(0) | RT_BIT(5); /* S1 and S5 always exposed */ 1250 if (pThis->fS1Enabled) /* Optionally expose S1 and S4 */ 1251 *pu32 |= RT_BIT(1); 1252 if (pThis->fS4Enabled) 1253 *pu32 |= RT_BIT(4); 1254 break; 1255 1256 case SYSTEM_INFO_INDEX_IOC_ADDRESS: 1257 *pu32 = pThis->u32IocPciAddress; 1258 break; 1259 1260 case SYSTEM_INFO_INDEX_HBC_ADDRESS: 1261 *pu32 = pThis->u32HbcPciAddress; 1262 break; 1263 1264 case SYSTEM_INFO_INDEX_PCI_BASE: 1265 /** @todo couldn't MCFG be in 64-bit range? */ 1266 Assert(pThis->u64PciConfigMMioAddress < 0xffffffff); 1267 *pu32 = (uint32_t)pThis->u64PciConfigMMioAddress; 1268 break; 1269 1270 case SYSTEM_INFO_INDEX_PCI_LENGTH: 1271 /** @todo couldn't MCFG be in 64-bit range? */ 1272 Assert(pThis->u64PciConfigMMioLength< 0xffffffff); 1273 *pu32 = (uint32_t)pThis->u64PciConfigMMioLength; 1274 break; 1275 1276 /* This is only for compatibility with older saved states that 1277 may include ACPI code that read these values. Legacy is 1278 a wonderful thing, isn't it? :-) */ 1279 case SYSTEM_INFO_INDEX_CPU0_STATUS: 1280 case SYSTEM_INFO_INDEX_CPU1_STATUS: 1281 case SYSTEM_INFO_INDEX_CPU2_STATUS: 1282 case SYSTEM_INFO_INDEX_CPU3_STATUS: 1283 *pu32 = ( pThis->fShowCpu 1284 && pThis->uSystemInfoIndex - SYSTEM_INFO_INDEX_CPU0_STATUS < pThis->cCpus 1285 && VMCPUSET_IS_PRESENT(&pThis->CpuSetAttached, 1286 pThis->uSystemInfoIndex - SYSTEM_INFO_INDEX_CPU0_STATUS) ) 1287 ? ( STA_DEVICE_PRESENT_MASK 1288 | STA_DEVICE_ENABLED_MASK 1289 | STA_DEVICE_SHOW_IN_UI_MASK 1290 | STA_DEVICE_FUNCTIONING_PROPERLY_MASK) 1291 : 0; 1292 break; 1293 1294 case SYSTEM_INFO_INDEX_RTC_STATUS: 1295 *pu32 = pThis->fShowRtc 1296 ? ( STA_DEVICE_PRESENT_MASK 1297 | STA_DEVICE_ENABLED_MASK 1298 | STA_DEVICE_SHOW_IN_UI_MASK 1299 | STA_DEVICE_FUNCTIONING_PROPERLY_MASK) 1300 : 0; 1301 break; 1302 1303 case SYSTEM_INFO_INDEX_CPU_LOCKED: 1304 if (pThis->idCpuLockCheck < VMM_MAX_CPU_COUNT) 1305 { 1306 *pu32 = VMCPUSET_IS_PRESENT(&pThis->CpuSetLocked, pThis->idCpuLockCheck); 1307 pThis->idCpuLockCheck = UINT32_C(0xffffffff); /* Make the entry invalid */ 1308 } 1309 else 1310 { 1311 rc = PDMDevHlpDBGFStop(pDevIns, RT_SRC_POS, "CPU lock check protocol violation (idCpuLockCheck=%#x)\n", 1312 pThis->idCpuLockCheck); 1313 /* Always return locked status just to be safe */ 1314 *pu32 = 1; 1315 } 1316 break; 1317 1318 case SYSTEM_INFO_INDEX_CPU_EVENT_TYPE: 1319 *pu32 = pThis->u32CpuEventType; 1320 break; 1321 1322 case SYSTEM_INFO_INDEX_CPU_EVENT: 1323 *pu32 = pThis->u32CpuEvent; 1324 break; 1325 1326 case SYSTEM_INFO_INDEX_SERIAL0_IOBASE: 1327 *pu32 = pThis->uSerial0IoPortBase; 1328 break; 1329 1330 case SYSTEM_INFO_INDEX_SERIAL0_IRQ: 1331 *pu32 = pThis->uSerial0Irq; 1332 break; 1333 1334 case SYSTEM_INFO_INDEX_SERIAL1_IOBASE: 1335 *pu32 = pThis->uSerial1IoPortBase; 1336 break; 1337 1338 case SYSTEM_INFO_INDEX_SERIAL1_IRQ: 1339 *pu32 = pThis->uSerial1Irq; 1340 break; 1341 1342 case SYSTEM_INFO_INDEX_END: 1343 /** @todo why isn't this setting any output value? */ 1344 break; 1345 1346 /* Solaris 9 tries to read from this index */ 1347 case SYSTEM_INFO_INDEX_INVALID: 1348 *pu32 = 0; 1349 break; 1350 1351 default: 1352 *pu32 = UINT32_MAX; 1353 rc = PDMDevHlpDBGFStop(pDevIns, RT_SRC_POS, "cb=%d Port=%u idx=%u\n", cb, Port, pThis->uBatteryIndex); 1354 break; 1355 } 1356 1357 DEVACPI_UNLOCK(pThis); 1358 Log(("acpiSysInfoDataRead: idx=%d val=%#x (%d) rc=%Rrc\n", uSystemInfoIndex, *pu32, *pu32, rc)); 1359 return rc; 1360 } 1361 1362 /** 1363 * @callback_method_impl{FNIOMIOPORTOUT, System info data} 1364 */ 1365 PDMBOTHCBDECL(int) acpiSysInfoDataWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb) 1366 { 1367 ACPIState *pThis = (ACPIState *)pvUser; 1368 if (cb != 4) 1369 return PDMDevHlpDBGFStop(pDevIns, RT_SRC_POS, "cb=%d Port=%u u32=%#x idx=%u\n", cb, Port, u32, pThis->uSystemInfoIndex); 1370 1371 DEVACPI_LOCK_R3(pThis); 1372 Log(("addr=%#x cb=%d u32=%#x si=%#x\n", Port, cb, u32, pThis->uSystemInfoIndex)); 1373 1374 int rc = VINF_SUCCESS; 1375 switch (pThis->uSystemInfoIndex) 1376 { 1377 case SYSTEM_INFO_INDEX_INVALID: 1378 AssertMsg(u32 == 0xbadc0de, ("u32=%u\n", u32)); 1379 pThis->u8IndexShift = 0; 1380 break; 1381 1382 case SYSTEM_INFO_INDEX_VALID: 1383 AssertMsg(u32 == 0xbadc0de, ("u32=%u\n", u32)); 1384 pThis->u8IndexShift = 2; 1385 break; 1386 1387 case SYSTEM_INFO_INDEX_CPU_LOCK_CHECK: 1388 pThis->idCpuLockCheck = u32; 1389 break; 1390 1391 case SYSTEM_INFO_INDEX_CPU_LOCKED: 1392 if (u32 < pThis->cCpus) 1393 VMCPUSET_DEL(&pThis->CpuSetLocked, u32); /* Unlock the CPU */ 1394 else 1395 LogRel(("ACPI: CPU %u does not exist\n", u32)); 1396 break; 1397 1398 default: 1399 rc = PDMDevHlpDBGFStop(pDevIns, RT_SRC_POS, "cb=%d Port=%u u32=%#x idx=%u\n", cb, Port, u32, pThis->uSystemInfoIndex); 1400 break; 1401 } 1402 1403 DEVACPI_UNLOCK(pThis); 1404 return rc; 1405 } 1406 1407 /** 1408 * @callback_method_impl{FNIOMIOPORTIN, PM1a Enable} 1409 */ 1410 PDMBOTHCBDECL(int) acpiPm1aEnRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb) 1411 { 1412 if (cb != 2) 1413 return VERR_IOM_IOPORT_UNUSED; 1414 1415 ACPIState *pThis = (ACPIState *)pvUser; 1416 DEVACPI_LOCK_R3(pThis); 1417 1418 *pu32 = pThis->pm1a_en; 1419 1420 DEVACPI_UNLOCK(pThis); 1421 Log(("acpiPm1aEnRead -> %#x\n", *pu32)); 1422 return VINF_SUCCESS; 1423 } 1424 1425 /** 1426 * @callback_method_impl{FNIOMIOPORTOUT, PM1a Enable} 1427 */ 1428 PDMBOTHCBDECL(int) acpiPM1aEnWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb) 1429 { 1430 if (cb != 2 && cb != 4) 1431 return PDMDevHlpDBGFStop(pDevIns, RT_SRC_POS, "cb=%d Port=%u u32=%#x\n", cb, Port, u32); 1432 1433 ACPIState *pThis = (ACPIState *)pvUser; 1434 DEVACPI_LOCK_R3(pThis); 1435 1436 Log(("acpiPM1aEnWrite: %#x (%#x)\n", u32, u32 & ~(RSR_EN | IGN_EN) & 0xffff)); 1437 u32 &= ~(RSR_EN | IGN_EN); 1438 u32 &= 0xffff; 1439 update_pm1a(pThis, pThis->pm1a_sts, u32); 1440 1441 DEVACPI_UNLOCK(pThis); 1442 return VINF_SUCCESS; 1443 } 1444 1445 /** 1446 * @callback_method_impl{FNIOMIOPORTIN, PM1a Status} 1447 */ 1448 PDMBOTHCBDECL(int) acpiPm1aStsRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb) 1449 { 1450 if (cb != 2) 1451 { 1452 int rc = PDMDevHlpDBGFStop(pDevIns, RT_SRC_POS, "cb=%d Port=%u\n", cb, Port); 1453 return rc == VINF_SUCCESS ? VERR_IOM_IOPORT_UNUSED : rc; 1454 } 1455 1456 ACPIState *pThis = (ACPIState *)pvUser; 1457 DEVACPI_LOCK_R3(pThis); 1458 1459 *pu32 = pThis->pm1a_sts; 1460 1461 DEVACPI_UNLOCK(pThis); 1462 Log(("acpiPm1aStsRead: %#x\n", *pu32)); 1463 return VINF_SUCCESS; 1464 } 1465 1466 /** 1467 * @callback_method_impl{FNIOMIOPORTOUT, PM1a Status} 1468 */ 1469 PDMBOTHCBDECL(int) acpiPM1aStsWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb) 1470 { 1471 if (cb != 2 && cb != 4) 1472 return PDMDevHlpDBGFStop(pDevIns, RT_SRC_POS, "cb=%d Port=%u u32=%#x\n", cb, Port, u32); 1473 1474 ACPIState *pThis = (ACPIState *)pvUser; 1475 DEVACPI_LOCK_R3(pThis); 1476 1477 Log(("acpiPM1aStsWrite: %#x (%#x)\n", u32, u32 & ~(RSR_STS | IGN_STS) & 0xffff)); 1478 u32 &= 0xffff; 1479 if (u32 & PWRBTN_STS) 1480 pThis->fPowerButtonHandled = true; /* Remember that the guest handled the last power button event */ 1481 u32 = pThis->pm1a_sts & ~(u32 & ~(RSR_STS | IGN_STS)); 1482 update_pm1a(pThis, u32, pThis->pm1a_en); 1483 1484 DEVACPI_UNLOCK(pThis); 1485 return VINF_SUCCESS; 1486 } 1487 1488 /** 1489 * @callback_method_impl{FNIOMIOPORTIN, PM1a Control} 1490 */ 1491 PDMBOTHCBDECL(int) acpiPm1aCtlRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb) 1492 { 1493 if (cb != 2) 1494 { 1495 int rc = PDMDevHlpDBGFStop(pDevIns, RT_SRC_POS, "cb=%d Port=%u\n", cb, Port); 1496 return rc == VINF_SUCCESS ? VERR_IOM_IOPORT_UNUSED : rc; 1497 } 1498 1499 ACPIState *pThis = (ACPIState *)pvUser; 1500 DEVACPI_LOCK_R3(pThis); 1501 1502 *pu32 = pThis->pm1a_ctl; 1503 1504 DEVACPI_UNLOCK(pThis); 1505 Log(("acpiPm1aCtlRead: %#x\n", *pu32)); 1506 return VINF_SUCCESS; 1507 } 1508 1509 /** 1510 * @callback_method_impl{FNIOMIOPORTOUT, PM1a Control} 1511 */ 1512 PDMBOTHCBDECL(int) acpiPM1aCtlWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb) 1513 { 1514 if (cb != 2 && cb != 4) 1515 return PDMDevHlpDBGFStop(pDevIns, RT_SRC_POS, "cb=%d Port=%u u32=%#x\n", cb, Port, u32); 1516 1517 ACPIState *pThis = (ACPIState *)pvUser; 1518 DEVACPI_LOCK_R3(pThis); 1519 1520 Log(("acpiPM1aCtlWrite: %#x (%#x)\n", u32, u32 & ~(RSR_CNT | IGN_CNT) & 0xffff)); 1521 u32 &= 0xffff; 1522 pThis->pm1a_ctl = u32 & ~(RSR_CNT | IGN_CNT); 1523 1524 int rc = VINF_SUCCESS; 1525 uint32_t const uSleepState = (pThis->pm1a_ctl >> SLP_TYPx_SHIFT) & SLP_TYPx_MASK; 1526 if (uSleepState != pThis->uSleepState) 1527 { 1528 pThis->uSleepState = uSleepState; 1529 switch (uSleepState) 1530 { 1531 case 0x00: /* S0 */ 1532 break; 1533 1534 case 0x01: /* S1 */ 1535 if (pThis->fS1Enabled) 1536 { 1537 LogRel(("Entering S1 power state (powered-on suspend)\n")); 1538 rc = acpiSleep(pThis); 1539 break; 1540 } 1541 LogRel(("Ignoring guest attempt to enter S1 power state (powered-on suspend)!\n")); 1542 /* fall thru */ 1543 1544 case 0x04: /* S4 */ 1545 if (pThis->fS4Enabled) 1546 { 1547 LogRel(("Entering S4 power state (suspend to disk)\n")); 1548 rc = acpiPowerOff(pThis);/* Same behavior as S5 */ 1549 break; 1550 } 1551 LogRel(("Ignoring guest attempt to enter S4 power state (suspend to disk)!\n")); 1552 /* fall thru */ 1553 1554 case 0x05: /* S5 */ 1555 LogRel(("Entering S5 power state (power down)\n")); 1556 rc = acpiPowerOff(pThis); 1557 break; 1558 1559 default: 1560 rc = PDMDevHlpDBGFStop(pDevIns, RT_SRC_POS, "Unknown sleep state %#x (u32=%#x)\n", uSleepState, u32); 1561 break; 1562 } 1563 } 1564 1565 DEVACPI_UNLOCK(pThis); 1566 Log(("acpiPM1aCtlWrite: rc=%Rrc\n", rc)); 1567 return rc; 1568 } 1569 1570 #endif /* IN_RING3 */ 1571 1572 /** 1573 * @callback_method_impl{FNIOMIOPORTIN, PMTMR} 1574 * 1575 * @remarks Only I/O port currently implemented in all contexts. 1576 */ 1577 PDMBOTHCBDECL(int) acpiPMTmrRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb) 1578 { 1579 if (cb != 4) 1580 return VERR_IOM_IOPORT_UNUSED; 1581 1582 ACPIState *pThis = PDMINS_2_DATA(pDevIns, ACPIState *); 1583 1584 /* 1585 * We use the clock lock to serialize access to u64PmTimerInitial and to 1586 * make sure we get a reliable time from the clock. 1587 */ 1588 int rc = TMTimerLock(pThis->CTX_SUFF(pPmTimer), VINF_IOM_HC_IOPORT_READ); 1589 if (rc == VINF_SUCCESS) 1590 { 1591 uint64_t const u64PmTimerInitial = pThis->u64PmTimerInitial; 1592 uint64_t u64Now = TMTimerGet(pThis->CTX_SUFF(pPmTimer)); 1593 1594 /* 1595 * Make 100% sure time doesn't go backwards. 1596 */ 1597 uint64_t u64Seen; 1598 do 1599 { 1600 u64Seen = ASMAtomicReadU64(&pThis->u64PmTimerLastSeen); 1601 if (u64Now < u64Seen) 1602 { 1603 #ifdef DEBUG 1604 DBGFTRACE_PDM_U64_TAG(pDevIns, u64Now, "acpi bad"); 1605 # if 0 1606 RTTraceBufDisable(DBGFTRACE_PDM_TRACEBUF(pDevIns)); 1607 AssertFailed(); 1608 # endif 1609 #endif 1610 u64Now = u64Seen + 1; 1611 } 1612 } while (!ASMAtomicCmpXchgU64(&pThis->u64PmTimerLastSeen, u64Now, u64Seen)); 1613 1614 TMTimerUnlock(pThis->CTX_SUFF(pPmTimer)); 1615 1616 /* 1617 * Calculate the return value. 1618 */ 1619 DBGFTRACE_PDM_U64_TAG(pDevIns, u64Now, "acpi"); 1620 uint64_t u64Elapsed = u64Now - u64PmTimerInitial; 1621 *pu32 = ASMMultU64ByU32DivByU32(u64Elapsed, PM_TMR_FREQ, TMTimerGetFreq(pThis->CTX_SUFF(pPmTimer))); 1622 Log(("acpi: acpiPMTmrRead -> %#x\n", *pu32)); 1623 } 1624 1625 return rc; 1626 } 1627 1628 #ifdef IN_RING3 1629 1630 /** 1631 * @callback_method_impl{FNIOMIOPORTIN, GPE0 Status} 1632 */ 1633 PDMBOTHCBDECL(int) acpiGpe0StsRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb) 1634 { 1635 if (cb != 1) 1636 { 1637 int rc = PDMDevHlpDBGFStop(pDevIns, RT_SRC_POS, "cb=%d Port=%u\n", cb, Port); 1638 return rc == VINF_SUCCESS ? VERR_IOM_IOPORT_UNUSED : rc; 1639 } 1640 1641 ACPIState *pThis = (ACPIState *)pvUser; 1642 DEVACPI_LOCK_R3(pThis); 1643 1644 *pu32 = pThis->gpe0_sts & 0xff; 1645 1646 DEVACPI_UNLOCK(pThis); 1647 Log(("acpiGpe0StsRead: %#x\n", *pu32)); 1648 return VINF_SUCCESS; 1649 } 1650 1651 /** 1652 * @callback_method_impl{FNIOMIOPORTOUT, GPE0 Status} 1653 */ 1654 PDMBOTHCBDECL(int) acpiGpe0StsWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb) 1655 { 1656 if (cb != 1) 1657 return PDMDevHlpDBGFStop(pDevIns, RT_SRC_POS, "cb=%d Port=%u u32=%#x\n", cb, Port, u32); 1658 1659 ACPIState *pThis = (ACPIState *)pvUser; 1660 DEVACPI_LOCK_R3(pThis); 1661 1662 Log(("acpiGpe0StsWrite: %#x (%#x)\n", u32, pThis->gpe0_sts & ~u32)); 1663 u32 = pThis->gpe0_sts & ~u32; 1664 update_gpe0(pThis, u32, pThis->gpe0_en); 1665 1666 DEVACPI_UNLOCK(pThis); 1667 return VINF_SUCCESS; 1668 } 1669 1670 /** 1671 * @callback_method_impl{FNIOMIOPORTIN, GPE0 Enable} 1672 */ 1673 PDMBOTHCBDECL(int) acpiGpe0EnRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb) 1674 { 1675 if (cb != 1) 1676 { 1677 int rc = PDMDevHlpDBGFStop(pDevIns, RT_SRC_POS, "cb=%d Port=%u\n", cb, Port); 1678 return rc == VINF_SUCCESS ? VERR_IOM_IOPORT_UNUSED : rc; 1679 } 1680 1681 ACPIState *pThis = (ACPIState *)pvUser; 1682 DEVACPI_LOCK_R3(pThis); 1683 1684 *pu32 = pThis->gpe0_en & 0xff; 1685 1686 DEVACPI_UNLOCK(pThis); 1687 Log(("acpiGpe0EnRead: %#x\n", *pu32)); 1688 return VINF_SUCCESS; 1689 } 1690 1691 /** 1692 * @callback_method_impl{FNIOMIOPORTOUT, GPE0 Enable} 1693 */ 1694 PDMBOTHCBDECL(int) acpiGpe0EnWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb) 1695 { 1696 if (cb != 1) 1697 return PDMDevHlpDBGFStop(pDevIns, RT_SRC_POS, "cb=%d Port=%u u32=%#x\n", cb, Port, u32); 1698 1699 ACPIState *pThis = (ACPIState *)pvUser; 1700 DEVACPI_LOCK_R3(pThis); 1701 1702 Log(("acpiGpe0EnWrite: %#x\n", u32)); 1703 update_gpe0(pThis, pThis->gpe0_sts, u32); 1704 1705 DEVACPI_UNLOCK(pThis); 1706 return VINF_SUCCESS; 1707 } 1708 1709 /** 1710 * @callback_method_impl{FNIOMIOPORTOUT, SMI_CMD} 1711 */ 1712 PDMBOTHCBDECL(int) acpiSmiWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb) 1713 { 1714 Log(("acpiSmiWrite %#x\n", u32)); 1715 if (cb != 1) 1716 return PDMDevHlpDBGFStop(pDevIns, RT_SRC_POS, "cb=%d Port=%u u32=%#x\n", cb, Port, u32); 1717 1718 ACPIState *pThis = (ACPIState *)pvUser; 1719 DEVACPI_LOCK_R3(pThis); 1720 1721 if (u32 == ACPI_ENABLE) 1722 pThis->pm1a_ctl |= SCI_EN; 1723 else if (u32 == ACPI_DISABLE) 1724 pThis->pm1a_ctl &= ~SCI_EN; 1725 else 1726 Log(("acpiSmiWrite: %#x <- unknown value\n", u32)); 1727 1728 DEVACPI_UNLOCK(pThis); 1729 return VINF_SUCCESS; 1730 } 1731 1732 /** 1733 * @{FNIOMIOPORTOUT, ACPI_RESET_BLK} 1734 */ 1735 PDMBOTHCBDECL(int) acpiResetWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb) 1736 { 1737 Log(("acpiResetWrite: %#x\n", u32)); 1738 if (cb != 1) 1739 return PDMDevHlpDBGFStop(pDevIns, RT_SRC_POS, "cb=%d Port=%u u32=%#x\n", cb, Port, u32); 1740 1741 /* No state locking required. */ 1742 int rc = VINF_SUCCESS; 1743 if (u32 == ACPI_RESET_REG_VAL) 1744 rc = PDMDevHlpVMReset(pDevIns); 1745 else 1746 Log(("acpiResetWrite: %#x <- unknown value\n", u32)); 1747 1748 return rc; 1749 } 1750 713 1751 # ifdef DEBUG_ACPI 714 PDMBOTHCBDECL(int) acpiDhexWrite( PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb); 715 PDMBOTHCBDECL(int) acpiDchrWrite( PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb); 716 # endif 717 #endif /* IN_RING3 */ 718 RT_C_DECLS_END 719 720 721 #ifdef IN_RING3 722 723 static RTIOPORT acpiPmPort(ACPIState* pAcpi, int32_t offset) 724 { 725 Assert(pAcpi->uPmIoPortBase != 0); 1752 1753 /** 1754 * @callback_method_impl{FNIOMIOPORTOUT, Debug hex value logger} 1755 */ 1756 PDMBOTHCBDECL(int) acpiDhexWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb) 1757 { 1758 switch (cb) 1759 { 1760 case 1: 1761 Log(("%#x\n", u32 & 0xff)); 1762 break; 1763 case 2: 1764 Log(("%#6x\n", u32 & 0xffff)); 1765 case 4: 1766 Log(("%#10x\n", u32)); 1767 break; 1768 default: 1769 return PDMDevHlpDBGFStop(pDevIns, RT_SRC_POS, "cb=%d Port=%u u32=%#x\n", cb, Port, u32); 1770 } 1771 return VINF_SUCCESS; 1772 } 1773 1774 /** 1775 * @callback_method_impl{FNIOMIOPORTOUT, Debug char logger} 1776 */ 1777 PDMBOTHCBDECL(int) acpiDchrWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb) 1778 { 1779 switch (cb) 1780 { 1781 case 1: 1782 Log(("%c", u32 & 0xff)); 1783 break; 1784 default: 1785 return PDMDevHlpDBGFStop(pDevIns, RT_SRC_POS, "cb=%d Port=%u u32=%#x\n", cb, Port, u32); 1786 } 1787 return VINF_SUCCESS; 1788 } 1789 1790 # endif /* DEBUG_ACPI */ 1791 1792 /** 1793 * Used to calculate the value of a PM I/O port. 1794 * 1795 * @returns The actual I/O port value. 1796 * @param pThis The ACPI instance. 1797 * @param offset The offset into the I/O space, or -1 if invalid. 1798 */ 1799 static RTIOPORT acpiCalcPmPort(ACPIState *pThis, int32_t offset) 1800 { 1801 Assert(pThis->uPmIoPortBase != 0); 726 1802 727 1803 if (offset == -1) 728 1804 return 0; 729 1805 730 return RTIOPORT(pAcpi->uPmIoPortBase + offset); 731 } 732 733 /* Simple acpiChecksum: all the bytes must add up to 0. */ 734 static uint8_t acpiChecksum(const uint8_t * const data, size_t len) 735 { 736 uint8_t sum = 0; 737 for (size_t i = 0; i < len; ++i) 738 sum += data[i]; 739 return -sum; 740 } 741 1806 return (RTIOPORT)(pThis->uPmIoPortBase + offset); 1807 } 1808 1809 /** 1810 * Called by acpiLoadState and acpiUpdatePmHandlers to register the PM1a, PM 1811 * timer and GPE0 I/O ports. 1812 * 1813 * @returns VBox status code. 1814 * @param pThis The ACPI instance. 1815 */ 1816 static int acpiRegisterPmHandlers(ACPIState *pThis) 1817 { 1818 int rc = VINF_SUCCESS; 1819 1820 #define R(offset, cnt, writer, reader, description) \ 1821 do { \ 1822 rc = PDMDevHlpIOPortRegister(pThis->pDevIns, acpiCalcPmPort(pThis, offset), cnt, pThis, writer, reader, \ 1823 NULL, NULL, description); \ 1824 if (RT_FAILURE(rc)) \ 1825 return rc; \ 1826 } while (0) 1827 #define L (GPE0_BLK_LEN / 2) 1828 1829 R(PM1a_EVT_OFFSET+2, 1, acpiPM1aEnWrite, acpiPm1aEnRead, "ACPI PM1a Enable"); 1830 R(PM1a_EVT_OFFSET, 1, acpiPM1aStsWrite, acpiPm1aStsRead, "ACPI PM1a Status"); 1831 R(PM1a_CTL_OFFSET, 1, acpiPM1aCtlWrite, acpiPm1aCtlRead, "ACPI PM1a Control"); 1832 R(PM_TMR_OFFSET, 1, NULL, acpiPMTmrRead, "ACPI PM Timer"); 1833 R(GPE0_OFFSET + L, L, acpiGpe0EnWrite, acpiGpe0EnRead, "ACPI GPE0 Enable"); 1834 R(GPE0_OFFSET, L, acpiGpe0StsWrite, acpiGpe0StsRead, "ACPI GPE0 Status"); 1835 #undef L 1836 #undef R 1837 1838 /* register RC stuff */ 1839 if (pThis->fGCEnabled) 1840 { 1841 rc = PDMDevHlpIOPortRegisterRC(pThis->pDevIns, acpiCalcPmPort(pThis, PM_TMR_OFFSET), 1842 1, 0, NULL, "acpiPMTmrRead", 1843 NULL, NULL, "ACPI PM Timer"); 1844 AssertRCReturn(rc, rc); 1845 } 1846 1847 /* register R0 stuff */ 1848 if (pThis->fR0Enabled) 1849 { 1850 rc = PDMDevHlpIOPortRegisterR0(pThis->pDevIns, acpiCalcPmPort(pThis, PM_TMR_OFFSET), 1851 1, 0, NULL, "acpiPMTmrRead", 1852 NULL, NULL, "ACPI PM Timer"); 1853 AssertRCReturn(rc, rc); 1854 } 1855 1856 return rc; 1857 } 1858 1859 /** 1860 * Called by acpiLoadState and acpiUpdatePmHandlers to unregister the PM1a, PM 1861 * timer and GPE0 I/O ports. 1862 * 1863 * @returns VBox status code. 1864 * @param pThis The ACPI instance. 1865 */ 1866 static int acpiUnregisterPmHandlers(ACPIState *pThis) 1867 { 1868 #define U(offset, cnt) \ 1869 do { \ 1870 int rc = PDMDevHlpIOPortDeregister(pThis->pDevIns, acpiCalcPmPort(pThis, offset), cnt); \ 1871 AssertRCReturn(rc, rc); \ 1872 } while (0) 1873 #define L (GPE0_BLK_LEN / 2) 1874 1875 U(PM1a_EVT_OFFSET+2, 1); 1876 U(PM1a_EVT_OFFSET, 1); 1877 U(PM1a_CTL_OFFSET, 1); 1878 U(PM_TMR_OFFSET, 1); 1879 U(GPE0_OFFSET + L, L); 1880 U(GPE0_OFFSET, L); 1881 #undef L 1882 #undef U 1883 1884 return VINF_SUCCESS; 1885 } 1886 1887 /** 1888 * Called by acpiPciConfigWrite and acpiReset to change the location of the 1889 * PM1a, PM timer and GPE0 ports. 1890 * 1891 * @returns VBox status code. 1892 * 1893 * @param pThis The ACPI instance. 1894 * @param NewIoPortBase The new base address of the I/O ports. 1895 */ 1896 static int acpiUpdatePmHandlers(ACPIState *pThis, RTIOPORT NewIoPortBase) 1897 { 1898 Log(("acpi: rebasing PM 0x%x -> 0x%x\n", pThis->uPmIoPortBase, NewIoPortBase)); 1899 if (NewIoPortBase != pThis->uPmIoPortBase) 1900 { 1901 int rc = acpiUnregisterPmHandlers(pThis); 1902 if (RT_FAILURE(rc)) 1903 return rc; 1904 1905 pThis->uPmIoPortBase = NewIoPortBase; 1906 1907 rc = acpiRegisterPmHandlers(pThis); 1908 if (RT_FAILURE(rc)) 1909 return rc; 1910 1911 /* We have to update FADT table acccording to the new base */ 1912 rc = acpiPlantTables(pThis); 1913 AssertRC(rc); 1914 if (RT_FAILURE(rc)) 1915 return rc; 1916 } 1917 1918 return VINF_SUCCESS; 1919 } 1920 1921 1922 /** 1923 * Saved state structure description, version 4. 1924 */ 1925 static const SSMFIELD g_AcpiSavedStateFields4[] = 1926 { 1927 SSMFIELD_ENTRY(ACPIState, pm1a_en), 1928 SSMFIELD_ENTRY(ACPIState, pm1a_sts), 1929 SSMFIELD_ENTRY(ACPIState, pm1a_ctl), 1930 SSMFIELD_ENTRY(ACPIState, u64PmTimerInitial), 1931 SSMFIELD_ENTRY(ACPIState, gpe0_en), 1932 SSMFIELD_ENTRY(ACPIState, gpe0_sts), 1933 SSMFIELD_ENTRY(ACPIState, uBatteryIndex), 1934 SSMFIELD_ENTRY(ACPIState, uSystemInfoIndex), 1935 SSMFIELD_ENTRY(ACPIState, u64RamSize), 1936 SSMFIELD_ENTRY(ACPIState, u8IndexShift), 1937 SSMFIELD_ENTRY(ACPIState, u8UseIOApic), 1938 SSMFIELD_ENTRY(ACPIState, uSleepState), 1939 SSMFIELD_ENTRY_TERM() 1940 }; 1941 1942 /** 1943 * Saved state structure description, version 5. 1944 */ 1945 static const SSMFIELD g_AcpiSavedStateFields5[] = 1946 { 1947 SSMFIELD_ENTRY(ACPIState, pm1a_en), 1948 SSMFIELD_ENTRY(ACPIState, pm1a_sts), 1949 SSMFIELD_ENTRY(ACPIState, pm1a_ctl), 1950 SSMFIELD_ENTRY(ACPIState, u64PmTimerInitial), 1951 SSMFIELD_ENTRY(ACPIState, gpe0_en), 1952 SSMFIELD_ENTRY(ACPIState, gpe0_sts), 1953 SSMFIELD_ENTRY(ACPIState, uBatteryIndex), 1954 SSMFIELD_ENTRY(ACPIState, uSystemInfoIndex), 1955 SSMFIELD_ENTRY(ACPIState, uSleepState), 1956 SSMFIELD_ENTRY(ACPIState, u8IndexShift), 1957 SSMFIELD_ENTRY(ACPIState, uPmIoPortBase), 1958 SSMFIELD_ENTRY_TERM() 1959 }; 1960 1961 /** 1962 * Saved state structure description, version 6. 1963 */ 1964 static const SSMFIELD g_AcpiSavedStateFields6[] = 1965 { 1966 SSMFIELD_ENTRY(ACPIState, pm1a_en), 1967 SSMFIELD_ENTRY(ACPIState, pm1a_sts), 1968 SSMFIELD_ENTRY(ACPIState, pm1a_ctl), 1969 SSMFIELD_ENTRY(ACPIState, u64PmTimerInitial), 1970 SSMFIELD_ENTRY(ACPIState, gpe0_en), 1971 SSMFIELD_ENTRY(ACPIState, gpe0_sts), 1972 SSMFIELD_ENTRY(ACPIState, uBatteryIndex), 1973 SSMFIELD_ENTRY(ACPIState, uSystemInfoIndex), 1974 SSMFIELD_ENTRY(ACPIState, uSleepState), 1975 SSMFIELD_ENTRY(ACPIState, u8IndexShift), 1976 SSMFIELD_ENTRY(ACPIState, uPmIoPortBase), 1977 SSMFIELD_ENTRY(ACPIState, fSuspendToSavedState), 1978 SSMFIELD_ENTRY_TERM() 1979 }; 1980 1981 1982 /** 1983 * @callback_method_impl{FNSSMDEVSAVEEXEC} 1984 */ 1985 static DECLCALLBACK(int) acpiSaveState(PPDMDEVINS pDevIns, PSSMHANDLE pSSMHandle) 1986 { 1987 ACPIState *pThis = PDMINS_2_DATA(pDevIns, ACPIState *); 1988 return SSMR3PutStruct(pSSMHandle, pThis, &g_AcpiSavedStateFields6[0]); 1989 } 1990 1991 /** 1992 * @callback_method_impl{FNSSMDEVLOADEXEC} 1993 */ 1994 static DECLCALLBACK(int) acpiLoadState(PPDMDEVINS pDevIns, PSSMHANDLE pSSMHandle, 1995 uint32_t uVersion, uint32_t uPass) 1996 { 1997 ACPIState *pThis = PDMINS_2_DATA(pDevIns, ACPIState *); 1998 Assert(uPass == SSM_PASS_FINAL); NOREF(uPass); 1999 2000 /* 2001 * Unregister PM handlers, will register with actual base after state 2002 * successfully loaded. 2003 */ 2004 int rc = acpiUnregisterPmHandlers(pThis); 2005 if (RT_FAILURE(rc)) 2006 return rc; 2007 2008 switch (uVersion) 2009 { 2010 case 4: 2011 rc = SSMR3GetStruct(pSSMHandle, pThis, &g_AcpiSavedStateFields4[0]); 2012 break; 2013 case 5: 2014 rc = SSMR3GetStruct(pSSMHandle, pThis, &g_AcpiSavedStateFields5[0]); 2015 break; 2016 case 6: 2017 rc = SSMR3GetStruct(pSSMHandle, pThis, &g_AcpiSavedStateFields6[0]); 2018 break; 2019 default: 2020 rc = VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION; 2021 break; 2022 } 2023 if (RT_SUCCESS(rc)) 2024 { 2025 rc = acpiRegisterPmHandlers(pThis); 2026 if (RT_FAILURE(rc)) 2027 return rc; 2028 rc = acpiFetchBatteryStatus(pThis); 2029 if (RT_FAILURE(rc)) 2030 return rc; 2031 rc = acpiFetchBatteryInfo(pThis); 2032 if (RT_FAILURE(rc)) 2033 return rc; 2034 acpiPmTimerReset(pThis, TMTimerGet(pThis->pPmTimerR3)); 2035 } 2036 return rc; 2037 } 2038 2039 /** 2040 * @interface_method_impl{PDMIBASE,pfnQueryInterface} 2041 */ 2042 static DECLCALLBACK(void *) acpiQueryInterface(PPDMIBASE pInterface, const char *pszIID) 2043 { 2044 ACPIState *pThis = RT_FROM_MEMBER(pInterface, ACPIState, IBase); 2045 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pThis->IBase); 2046 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIACPIPORT, &pThis->IACPIPort); 2047 return NULL; 2048 } 2049 2050 /** 2051 * Calculate the check sum for some ACPI data before planting it. 2052 * 2053 * All the bytes must add up to 0. 2054 * 2055 * @returns check sum. 2056 * @param pvSrc What to check sum. 2057 * @param cbData The amount of data to checksum. 2058 */ 2059 static uint8_t acpiChecksum(const void * const pvSrc, size_t cbData) 2060 { 2061 uint8_t const *pbSrc = (uint8_t const *)pvSrc; 2062 uint8_t uSum = 0; 2063 for (size_t i = 0; i < cbData; ++i) 2064 uSum += pbSrc[i]; 2065 return -uSum; 2066 } 2067 2068 /** 2069 * Prepare a ACPI table header. 2070 */ 742 2071 static void acpiPrepareHeader(ACPITBLHEADER *header, const char au8Signature[4], 743 2072 uint32_t u32Length, uint8_t u8Revision) … … 754 2083 } 755 2084 2085 /** 2086 * Initialize a generic address structure (ACPIGENADDR). 2087 */ 756 2088 static void acpiWriteGenericAddr(ACPIGENADDR *g, uint8_t u8AddressSpaceId, 757 2089 uint8_t u8RegisterBitWidth, uint8_t u8RegisterBitOffset, … … 765 2097 } 766 2098 2099 /** 2100 * Wrapper around PDMDevHlpPhysWrite used when planting ACPI tables. 2101 */ 767 2102 static void acpiPhyscpy(ACPIState *s, RTGCPHYS32 dst, const void * const src, size_t size) 768 2103 { … … 770 2105 } 771 2106 772 /** Differentiated System Description Table (DSDT) */ 773 2107 /** 2108 * Plant the Differentiated System Description Table (DSDT). 2109 */ 774 2110 static void acpiSetupDSDT(ACPIState *s, RTGCPHYS32 addr, 775 2111 void* pPtr, size_t uDsdtLen) … … 778 2114 } 779 2115 780 /** Secondary System Description Table (SSDT) */ 781 2116 /** 2117 * Plan the Secondary System Description Table (SSDT). 2118 */ 782 2119 static void acpiSetupSSDT(ACPIState *s, RTGCPHYS32 addr, 783 2120 void* pPtr, size_t uSsdtLen) … … 786 2123 } 787 2124 788 /** Firmware ACPI Control Structure (FACS) */ 2125 /** 2126 * Plant the Firmware ACPI Control Structure (FACS). 2127 */ 789 2128 static void acpiSetupFACS(ACPIState *s, RTGCPHYS32 addr) 790 2129 { … … 804 2143 } 805 2144 806 /** Fixed ACPI Description Table (FADT aka FACP) */ 2145 /** 2146 * Plant the Fixed ACPI Description Table (FADT aka FACP). 2147 */ 807 2148 static void acpiSetupFADT(ACPIState *s, RTGCPHYS32 GCPhysAcpi1, RTGCPHYS32 GCPhysAcpi2, RTGCPHYS32 GCPhysFacs, RTGCPHYS GCPhysDsdt) 808 2149 { … … 822 2163 fadt.u8S4BIOSReq = 0; 823 2164 fadt.u8PStateCnt = 0; 824 fadt.u32PM1aEVTBLK = RT_H2LE_U32(acpi PmPort(s, PM1a_EVT_OFFSET));825 fadt.u32PM1bEVTBLK = RT_H2LE_U32(acpi PmPort(s, PM1b_EVT_OFFSET));826 fadt.u32PM1aCTLBLK = RT_H2LE_U32(acpi PmPort(s, PM1a_CTL_OFFSET));827 fadt.u32PM1bCTLBLK = RT_H2LE_U32(acpi PmPort(s, PM1b_CTL_OFFSET));828 fadt.u32PM2CTLBLK = RT_H2LE_U32(acpi PmPort(s, PM2_CTL_OFFSET));829 fadt.u32PMTMRBLK = RT_H2LE_U32(acpi PmPort(s, PM_TMR_OFFSET));830 fadt.u32GPE0BLK = RT_H2LE_U32(acpi PmPort(s, GPE0_OFFSET));831 fadt.u32GPE1BLK = RT_H2LE_U32(acpi PmPort(s, GPE1_OFFSET));2165 fadt.u32PM1aEVTBLK = RT_H2LE_U32(acpiCalcPmPort(s, PM1a_EVT_OFFSET)); 2166 fadt.u32PM1bEVTBLK = RT_H2LE_U32(acpiCalcPmPort(s, PM1b_EVT_OFFSET)); 2167 fadt.u32PM1aCTLBLK = RT_H2LE_U32(acpiCalcPmPort(s, PM1a_CTL_OFFSET)); 2168 fadt.u32PM1bCTLBLK = RT_H2LE_U32(acpiCalcPmPort(s, PM1b_CTL_OFFSET)); 2169 fadt.u32PM2CTLBLK = RT_H2LE_U32(acpiCalcPmPort(s, PM2_CTL_OFFSET)); 2170 fadt.u32PMTMRBLK = RT_H2LE_U32(acpiCalcPmPort(s, PM_TMR_OFFSET)); 2171 fadt.u32GPE0BLK = RT_H2LE_U32(acpiCalcPmPort(s, GPE0_OFFSET)); 2172 fadt.u32GPE1BLK = RT_H2LE_U32(acpiCalcPmPort(s, GPE1_OFFSET)); 832 2173 fadt.u8PM1EVTLEN = 4; 833 2174 fadt.u8PM1CTLLEN = 2; … … 862 2203 fadt.u64XFACS = RT_H2LE_U64((uint64_t)GCPhysFacs); 863 2204 fadt.u64XDSDT = RT_H2LE_U64((uint64_t)GCPhysDsdt); 864 acpiWriteGenericAddr(&fadt.X_PM1aEVTBLK, 1, 32, 0, 2, acpi PmPort(s, PM1a_EVT_OFFSET));865 acpiWriteGenericAddr(&fadt.X_PM1bEVTBLK, 0, 0, 0, 0, acpi PmPort(s, PM1b_EVT_OFFSET));866 acpiWriteGenericAddr(&fadt.X_PM1aCTLBLK, 1, 16, 0, 2, acpi PmPort(s, PM1a_CTL_OFFSET));867 acpiWriteGenericAddr(&fadt.X_PM1bCTLBLK, 0, 0, 0, 0, acpi PmPort(s, PM1b_CTL_OFFSET));868 acpiWriteGenericAddr(&fadt.X_PM2CTLBLK, 0, 0, 0, 0, acpi PmPort(s, PM2_CTL_OFFSET));869 acpiWriteGenericAddr(&fadt.X_PMTMRBLK, 1, 32, 0, 3, acpi PmPort(s, PM_TMR_OFFSET));870 acpiWriteGenericAddr(&fadt.X_GPE0BLK, 1, 16, 0, 1, acpi PmPort(s, GPE0_OFFSET));871 acpiWriteGenericAddr(&fadt.X_GPE1BLK, 0, 0, 0, 0, acpi PmPort(s, GPE1_OFFSET));872 fadt.header.u8Checksum = acpiChecksum( (uint8_t *)&fadt, sizeof(fadt));2205 acpiWriteGenericAddr(&fadt.X_PM1aEVTBLK, 1, 32, 0, 2, acpiCalcPmPort(s, PM1a_EVT_OFFSET)); 2206 acpiWriteGenericAddr(&fadt.X_PM1bEVTBLK, 0, 0, 0, 0, acpiCalcPmPort(s, PM1b_EVT_OFFSET)); 2207 acpiWriteGenericAddr(&fadt.X_PM1aCTLBLK, 1, 16, 0, 2, acpiCalcPmPort(s, PM1a_CTL_OFFSET)); 2208 acpiWriteGenericAddr(&fadt.X_PM1bCTLBLK, 0, 0, 0, 0, acpiCalcPmPort(s, PM1b_CTL_OFFSET)); 2209 acpiWriteGenericAddr(&fadt.X_PM2CTLBLK, 0, 0, 0, 0, acpiCalcPmPort(s, PM2_CTL_OFFSET)); 2210 acpiWriteGenericAddr(&fadt.X_PMTMRBLK, 1, 32, 0, 3, acpiCalcPmPort(s, PM_TMR_OFFSET)); 2211 acpiWriteGenericAddr(&fadt.X_GPE0BLK, 1, 16, 0, 1, acpiCalcPmPort(s, GPE0_OFFSET)); 2212 acpiWriteGenericAddr(&fadt.X_GPE1BLK, 0, 0, 0, 0, acpiCalcPmPort(s, GPE1_OFFSET)); 2213 fadt.header.u8Checksum = acpiChecksum(&fadt, sizeof(fadt)); 873 2214 acpiPhyscpy(s, GCPhysAcpi2, &fadt, sizeof(fadt)); 874 2215 … … 877 2218 fadt.u8IntModel = INT_MODEL_DUAL_PIC; 878 2219 fadt.header.u8Checksum = 0; /* Must be zeroed before recalculating checksum! */ 879 fadt.header.u8Checksum = acpiChecksum( (uint8_t *)&fadt, ACPITBLFADT_VERSION1_SIZE);2220 fadt.header.u8Checksum = acpiChecksum(&fadt, ACPITBLFADT_VERSION1_SIZE); 880 2221 acpiPhyscpy(s, GCPhysAcpi1, &fadt, ACPITBLFADT_VERSION1_SIZE); 881 2222 } 882 2223 883 2224 /** 884 * Root System Description Table. 885 * The RSDT and XSDT tables are basically identical. The only difference is 32 vs 64 bits 886 * addresses for description headers. RSDT is for ACPI 1.0. XSDT for ACPI 2.0 and up. 2225 * Plant the root System Description Table. 2226 * 2227 * The RSDT and XSDT tables are basically identical. The only difference is 32 2228 * vs 64 bits addresses for description headers. RSDT is for ACPI 1.0. XSDT for 2229 * ACPI 2.0 and up. 887 2230 */ 888 2231 static int acpiSetupRSDT(ACPIState *s, RTGCPHYS32 addr, unsigned int nb_entries, uint32_t *addrs) … … 901 2244 Log(("Setup RSDT: [%d] = %x\n", i, rsdt->u32Entry[i])); 902 2245 } 903 rsdt->header.u8Checksum = acpiChecksum( (uint8_t*)rsdt, size);2246 rsdt->header.u8Checksum = acpiChecksum(rsdt, size); 904 2247 acpiPhyscpy(s, addr, rsdt, size); 905 2248 RTMemFree(rsdt); … … 907 2250 } 908 2251 909 /** Extended System Description Table. */ 2252 /** 2253 * Plant the Extended System Description Table. 2254 */ 910 2255 static int acpiSetupXSDT(ACPIState *s, RTGCPHYS32 addr, unsigned int nb_entries, uint32_t *addrs) 911 2256 { … … 923 2268 Log(("Setup XSDT: [%d] = %RX64\n", i, xsdt->u64Entry[i])); 924 2269 } 925 xsdt->header.u8Checksum = acpiChecksum( (uint8_t*)xsdt, size);2270 xsdt->header.u8Checksum = acpiChecksum(xsdt, size); 926 2271 acpiPhyscpy(s, addr, xsdt, size); 927 2272 RTMemFree(xsdt); … … 929 2274 } 930 2275 931 /** Root System Description Pointer (RSDP) */ 2276 /** 2277 * Plant the Root System Description Pointer (RSDP). 2278 */ 932 2279 static void acpiSetupRSDP(ACPITBLRSDP *rsdp, RTGCPHYS32 GCPhysRsdt, RTGCPHYS GCPhysXsdt) 933 2280 { … … 939 2286 rsdp->u8Revision = ACPI_REVISION; 940 2287 rsdp->u32RSDT = RT_H2LE_U32(GCPhysRsdt); 941 rsdp->u8Checksum = acpiChecksum( (uint8_t*)rsdp, RT_OFFSETOF(ACPITBLRSDP, u32Length));2288 rsdp->u8Checksum = acpiChecksum(rsdp, RT_OFFSETOF(ACPITBLRSDP, u32Length)); 942 2289 943 2290 /* ACPI 2.0 part (XSDT) */ 944 2291 rsdp->u32Length = RT_H2LE_U32(sizeof(ACPITBLRSDP)); 945 2292 rsdp->u64XSDT = RT_H2LE_U64(GCPhysXsdt); 946 rsdp->u8ExtChecksum = acpiChecksum( (uint8_t*)rsdp, sizeof(ACPITBLRSDP));947 } 948 949 /** 950 * Multiple APIC Description Table.2293 rsdp->u8ExtChecksum = acpiChecksum(rsdp, sizeof(ACPITBLRSDP)); 2294 } 2295 2296 /** 2297 * Plant the Multiple APIC Description Table (MADT). 951 2298 * 952 * @note APIC without IO-APIC hangs Windows Vista therefore we setup both2299 * @note APIC without IO-APIC hangs Windows Vista therefore we setup both. 953 2300 * 954 * @todo All hardcoded, should set this up based on the actual VM config!!!!!2301 * @todo All hardcoded, should set this up based on the actual VM config!!!!! 955 2302 */ 956 2303 static void acpiSetupMADT(ACPIState *s, RTGCPHYS32 addr) … … 1022 2369 } 1023 2370 1024 1025 /** High Performance Event Timer (HPET) descriptor */ 2371 /** 2372 * Plant the High Performance Event Timer (HPET) descriptor. 2373 */ 1026 2374 static void acpiSetupHPET(ACPIState *s, RTGCPHYS32 addr) 1027 2375 { … … 1044 2392 hpet.u8Attributes = 0; 1045 2393 1046 hpet.aHeader.u8Checksum = acpiChecksum( (uint8_t *)&hpet, sizeof(hpet));2394 hpet.aHeader.u8Checksum = acpiChecksum(&hpet, sizeof(hpet)); 1047 2395 1048 2396 acpiPhyscpy(s, addr, (const uint8_t *)&hpet, sizeof(hpet)); 1049 2397 } 1050 2398 1051 /** MMCONFIG PCI config space access (MCFG) descriptor */ 1052 static void acpiSetupMCFG(ACPIState *s, RTGCPHYS32 addr) 1053 { 1054 struct { 2399 2400 /** 2401 * Used by acpiPlantTables to plant a MMCONFIG PCI config space access (MCFG) 2402 * descriptor. 2403 * 2404 * @param pThis The ACPI instance. 2405 * @param GCPhysDst Where to plant it. 2406 */ 2407 static void acpiSetupMCFG(ACPIState *pThis, RTGCPHYS32 GCPhysDst) 2408 { 2409 struct 2410 { 1055 2411 ACPITBLMCFG hdr; 1056 2412 ACPITBLMCFGENTRY entry; 1057 } tbl; 1058 1059 uint8_t u8StartBus = 0; 1060 uint8_t u8EndBus = (s->u64PciConfigMMioLength >> 20) - 1; 1061 1062 memset(&tbl, 0, sizeof(tbl)); 2413 } tbl; 2414 uint8_t u8StartBus = 0; 2415 uint8_t u8EndBus = (pThis->u64PciConfigMMioLength >> 20) - 1; 2416 2417 RT_ZERO(tbl); 1063 2418 1064 2419 acpiPrepareHeader(&tbl.hdr.aHeader, "MCFG", sizeof(tbl), 1); 1065 tbl.entry.u64BaseAddress = s->u64PciConfigMMioAddress;1066 tbl.entry.u8StartBus = u8StartBus;1067 tbl.entry.u8EndBus = u8EndBus;2420 tbl.entry.u64BaseAddress = pThis->u64PciConfigMMioAddress; 2421 tbl.entry.u8StartBus = u8StartBus; 2422 tbl.entry.u8EndBus = u8EndBus; 1068 2423 // u16PciSegmentGroup must match _SEG in ACPI table 1069 2424 1070 tbl.hdr.aHeader.u8Checksum = acpiChecksum((uint8_t *)&tbl, sizeof(tbl)); 1071 1072 acpiPhyscpy(s, addr, (const uint8_t *)&tbl, sizeof(tbl)); 1073 } 1074 1075 /* SCI IRQ */ 1076 DECLINLINE(void) acpiSetIrq(ACPIState *s, int level) 1077 { 1078 if (s->pm1a_ctl & SCI_EN) 1079 PDMDevHlpPCISetIrq(s->pDevIns, -1, level); 1080 } 1081 1082 DECLINLINE(uint32_t) pm1a_pure_en(uint32_t en) 1083 { 1084 return en & ~(RSR_EN | IGN_EN); 1085 } 1086 1087 DECLINLINE(uint32_t) pm1a_pure_sts(uint32_t sts) 1088 { 1089 return sts & ~(RSR_STS | IGN_STS); 1090 } 1091 1092 DECLINLINE(int) pm1a_level(ACPIState *s) 1093 { 1094 return (pm1a_pure_en(s->pm1a_en) & pm1a_pure_sts(s->pm1a_sts)) != 0; 1095 } 1096 1097 DECLINLINE(int) gpe0_level(ACPIState *s) 1098 { 1099 return (s->gpe0_en & s->gpe0_sts) != 0; 1100 } 1101 1102 static void update_pm1a(ACPIState *s, uint32_t sts, uint32_t en) 1103 { 1104 int old_level, new_level; 1105 1106 if (gpe0_level(s)) 1107 return; 1108 1109 old_level = pm1a_level(s); 1110 new_level = (pm1a_pure_en(en) & pm1a_pure_sts(sts)) != 0; 1111 1112 Log(("update_pm1a() old=%x new=%x\n", old_level, new_level)); 1113 1114 s->pm1a_en = en; 1115 s->pm1a_sts = sts; 1116 1117 if (new_level != old_level) 1118 acpiSetIrq(s, new_level); 1119 } 1120 1121 static void update_gpe0(ACPIState *s, uint32_t sts, uint32_t en) 1122 { 1123 int old_level, new_level; 1124 1125 if (pm1a_level(s)) 1126 return; 1127 1128 old_level = (s->gpe0_en & s->gpe0_sts) != 0; 1129 new_level = (en & sts) != 0; 1130 1131 s->gpe0_en = en; 1132 s->gpe0_sts = sts; 1133 1134 if (new_level != old_level) 1135 acpiSetIrq(s, new_level); 1136 } 1137 1138 static int acpiPowerDown(ACPIState *s) 1139 { 1140 int rc = PDMDevHlpVMPowerOff(s->pDevIns); 1141 if (RT_FAILURE(rc)) 1142 AssertMsgFailed(("Could not power down the VM. rc = %Rrc\n", rc)); 1143 return rc; 1144 } 1145 1146 static int acpiSleep(ACPIState *pThis) 1147 { 1148 int rc; 1149 1150 /* We must set WAK_STS on resume (includes restore) so the guest knows that 1151 we've woken up and can continue executing code. The guest is probably 1152 reading the PMSTS register in a loop to check this. */ 1153 pThis->fSetWakeupOnResume = true; 1154 if (pThis->fSuspendToSavedState) 1155 { 1156 rc = PDMDevHlpVMSuspendSaveAndPowerOff(pThis->pDevIns); 1157 if (rc != VERR_NOT_SUPPORTED) 1158 AssertRC(rc); 1159 else 1160 { 1161 LogRel(("ACPI: PDMDevHlpVMSuspendSaveAndPowerOff is not supported, falling back to suspend-only\n")); 1162 rc = PDMDevHlpVMSuspend(pThis->pDevIns); 1163 AssertRC(rc); 1164 } 1165 } 1166 else 1167 { 1168 rc = PDMDevHlpVMSuspend(pThis->pDevIns); 1169 AssertRC(rc); 1170 } 1171 return rc; 1172 } 1173 1174 /** Converts a ACPI port interface pointer to an ACPI state pointer. */ 1175 #define IACPIPORT_2_ACPISTATE(pInterface) ( (ACPIState*)((uintptr_t)pInterface - RT_OFFSETOF(ACPIState, IACPIPort)) ) 1176 1177 /** 1178 * Send an ACPI power off event. 2425 tbl.hdr.aHeader.u8Checksum = acpiChecksum(&tbl, sizeof(tbl)); 2426 2427 acpiPhyscpy(pThis, GCPhysDst, (const uint8_t *)&tbl, sizeof(tbl)); 2428 } 2429 2430 /** 2431 * Used by acpiPlantTables and acpiConstruct. 1179 2432 * 1180 * @returns VBox status code 1181 * @param pInterface Pointer to the interface structure containing the called function pointer. 1182 */ 1183 static DECLCALLBACK(int) acpiPowerButtonPress(PPDMIACPIPORT pInterface) 1184 { 1185 ACPIState *s = IACPIPORT_2_ACPISTATE(pInterface); 1186 Log(("acpiPowerButtonPress: handled=%d status=%x\n", s->fPowerButtonHandled, s->pm1a_sts)); 1187 s->fPowerButtonHandled = false; 1188 update_pm1a(s, s->pm1a_sts | PWRBTN_STS, s->pm1a_en); 1189 return VINF_SUCCESS; 1190 } 1191 1192 /** 1193 * Check if the ACPI power button event was handled. 1194 * 1195 * @returns VBox status code 1196 * @param pInterface Pointer to the interface structure containing the called function pointer. 1197 * @param pfHandled Return true if the power button event was handled by the guest. 1198 */ 1199 static DECLCALLBACK(int) acpiGetPowerButtonHandled(PPDMIACPIPORT pInterface, bool *pfHandled) 1200 { 1201 ACPIState *s = IACPIPORT_2_ACPISTATE(pInterface); 1202 *pfHandled = s->fPowerButtonHandled; 1203 return VINF_SUCCESS; 1204 } 1205 1206 /** 1207 * Check if the Guest entered into G0 (working) or G1 (sleeping). 1208 * 1209 * @returns VBox status code 1210 * @param pInterface Pointer to the interface structure containing the called function pointer. 1211 * @param pfEntered Return true if the guest entered the ACPI mode. 1212 */ 1213 static DECLCALLBACK(int) acpiGetGuestEnteredACPIMode(PPDMIACPIPORT pInterface, bool *pfEntered) 1214 { 1215 ACPIState *s = IACPIPORT_2_ACPISTATE(pInterface); 1216 *pfEntered = (s->pm1a_ctl & SCI_EN) != 0; 1217 return VINF_SUCCESS; 1218 } 1219 1220 static DECLCALLBACK(int) acpiGetCpuStatus(PPDMIACPIPORT pInterface, unsigned uCpu, bool *pfLocked) 1221 { 1222 ACPIState *s = IACPIPORT_2_ACPISTATE(pInterface); 1223 *pfLocked = VMCPUSET_IS_PRESENT(&s->CpuSetLocked, uCpu); 1224 return VINF_SUCCESS; 1225 } 1226 1227 /** 1228 * Send an ACPI sleep button event. 1229 * 1230 * @returns VBox status code 1231 * @param pInterface Pointer to the interface structure containing the called function pointer. 1232 */ 1233 static DECLCALLBACK(int) acpiSleepButtonPress(PPDMIACPIPORT pInterface) 1234 { 1235 ACPIState *s = IACPIPORT_2_ACPISTATE(pInterface); 1236 update_pm1a(s, s->pm1a_sts | SLPBTN_STS, s->pm1a_en); 1237 return VINF_SUCCESS; 1238 } 1239 1240 /* PM1a_EVT_BLK enable */ 1241 static uint32_t acpiPm1aEnReadw(ACPIState *s, uint32_t addr) 1242 { 1243 uint16_t val = s->pm1a_en; 1244 Log(("acpi: acpiPm1aEnReadw -> %#x\n", val)); 1245 return val; 1246 } 1247 1248 static void acpiPM1aEnWritew(ACPIState *s, uint32_t addr, uint32_t val) 1249 { 1250 Log(("acpi: acpiPM1aEnWritew <- %#x (%#x)\n", val, val & ~(RSR_EN | IGN_EN))); 1251 val &= ~(RSR_EN | IGN_EN); 1252 update_pm1a(s, s->pm1a_sts, val); 1253 } 1254 1255 /* PM1a_EVT_BLK status */ 1256 static uint32_t acpiPm1aStsReadw(ACPIState *s, uint32_t addr) 1257 { 1258 uint16_t val = s->pm1a_sts; 1259 Log(("acpi: acpiPm1aStsReadw -> %#x\n", val)); 1260 return val; 1261 } 1262 1263 static void acpiPM1aStsWritew(ACPIState *s, uint32_t addr, uint32_t val) 1264 { 1265 Log(("acpi: acpiPM1aStsWritew <- %#x (%#x)\n", val, val & ~(RSR_STS | IGN_STS))); 1266 if (val & PWRBTN_STS) 1267 s->fPowerButtonHandled = true; /* Remember that the guest handled the last power button event */ 1268 val = s->pm1a_sts & ~(val & ~(RSR_STS | IGN_STS)); 1269 update_pm1a(s, val, s->pm1a_en); 1270 } 1271 1272 /* PM1a_CTL_BLK */ 1273 static uint32_t acpiPm1aCtlReadw(ACPIState *s, uint32_t addr) 1274 { 1275 uint16_t val = s->pm1a_ctl; 1276 Log(("acpi: acpiPm1aCtlReadw -> %#x\n", val)); 1277 return val; 1278 } 1279 1280 static int acpiPM1aCtlWritew(ACPIState *s, uint32_t addr, uint32_t val) 1281 { 1282 uint32_t uSleepState; 1283 1284 Log(("acpi: acpiPM1aCtlWritew <- %#x (%#x)\n", val, val & ~(RSR_CNT | IGN_CNT))); 1285 s->pm1a_ctl = val & ~(RSR_CNT | IGN_CNT); 1286 1287 uSleepState = (s->pm1a_ctl >> SLP_TYPx_SHIFT) & SLP_TYPx_MASK; 1288 if (uSleepState != s->uSleepState) 1289 { 1290 s->uSleepState = uSleepState; 1291 switch (uSleepState) 1292 { 1293 case 0x00: /* S0 */ 1294 break; 1295 case 0x01: /* S1 */ 1296 if (s->fS1Enabled) 1297 { 1298 LogRel(("Entering S1 power state (powered-on suspend)\n")); 1299 return acpiSleep(s); 1300 } 1301 else 1302 LogRel(("Ignoring guest attempt to enter S1 power state (powered-on suspend)!\n")); 1303 case 0x04: /* S4 */ 1304 if (s->fS4Enabled) 1305 { 1306 LogRel(("Entering S4 power state (suspend to disk)\n")); 1307 return acpiPowerDown(s);/* Same behavior as S5 */ 1308 } 1309 else 1310 LogRel(("Ignoring guest attempt to enter S4 power state (suspend to disk)!\n")); 1311 case 0x05: /* S5 */ 1312 LogRel(("Entering S5 power state (power down)\n")); 1313 return acpiPowerDown(s); 1314 default: 1315 AssertMsgFailed(("Unknown sleep state %#x\n", uSleepState)); 1316 break; 1317 } 1318 } 1319 return VINF_SUCCESS; 1320 } 1321 1322 /* GPE0_BLK */ 1323 static uint32_t acpiGpe0EnReadb(ACPIState *s, uint32_t addr) 1324 { 1325 uint8_t val = s->gpe0_en; 1326 Log(("acpi: acpiGpe0EnReadl -> %#x\n", val)); 1327 return val; 1328 } 1329 1330 static void acpiGpe0EnWriteb(ACPIState *s, uint32_t addr, uint32_t val) 1331 { 1332 Log(("acpi: acpiGpe0EnWritel <- %#x\n", val)); 1333 update_gpe0(s, s->gpe0_sts, val); 1334 } 1335 1336 static uint32_t acpiGpe0StsReadb(ACPIState *s, uint32_t addr) 1337 { 1338 uint8_t val = s->gpe0_sts; 1339 Log(("acpi: acpiGpe0StsReadl -> %#x\n", val)); 1340 return val; 1341 } 1342 1343 static void acpiGpe0StsWriteb(ACPIState *s, uint32_t addr, uint32_t val) 1344 { 1345 val = s->gpe0_sts & ~val; 1346 update_gpe0(s, val, s->gpe0_en); 1347 Log(("acpi: acpiGpe0StsWritel <- %#x\n", val)); 1348 } 1349 1350 static int acpiResetWriteU8(ACPIState *s, uint32_t addr, uint32_t val) 1351 { 1352 int rc = VINF_SUCCESS; 1353 1354 Log(("ACPI: acpiResetWriteU8: %x %x\n", addr, val)); 1355 if (val == ACPI_RESET_REG_VAL) 1356 { 1357 # ifndef IN_RING3 1358 rc = VINF_IOM_HC_IOPORT_WRITE; 1359 # else /* IN_RING3 */ 1360 rc = PDMDevHlpVMReset(s->pDevIns); 1361 # endif /* !IN_RING3 */ 1362 } 1363 return rc; 1364 } 1365 1366 /* SMI */ 1367 static void acpiSmiWriteU8(ACPIState *s, uint32_t addr, uint32_t val) 1368 { 1369 Log(("acpi: acpiSmiWriteU8 %#x\n", val)); 1370 if (val == ACPI_ENABLE) 1371 s->pm1a_ctl |= SCI_EN; 1372 else if (val == ACPI_DISABLE) 1373 s->pm1a_ctl &= ~SCI_EN; 1374 else 1375 Log(("acpi: acpiSmiWriteU8 %#x <- unknown value\n", val)); 1376 } 1377 2433 * @returns Guest memory address. 2434 */ 1378 2435 static uint32_t find_rsdp_space(void) 1379 2436 { … … 1381 2438 } 1382 2439 1383 static int acpiPMTimerReset(ACPIState *s) 1384 { 1385 uint64_t interval, freq; 1386 1387 freq = TMTimerGetFreq(s->CTX_SUFF(ts)); 1388 interval = ASMMultU64ByU32DivByU32(0xffffffff, freq, PM_TMR_FREQ); 1389 Log(("interval = %RU64\n", interval)); 1390 TMTimerSet(s->CTX_SUFF(ts), TMTimerGet(s->CTX_SUFF(ts)) + interval); 1391 1392 return VINF_SUCCESS; 1393 } 1394 1395 static DECLCALLBACK(void) acpiTimer(PPDMDEVINS pDevIns, PTMTIMER pTimer, void *pvUser) 1396 { 1397 ACPIState *s = (ACPIState *)pvUser; 1398 1399 Log(("acpi: pm timer sts %#x (%d), en %#x (%d)\n", 1400 s->pm1a_sts, (s->pm1a_sts & TMR_STS) != 0, 1401 s->pm1a_en, (s->pm1a_en & TMR_EN) != 0)); 1402 1403 update_pm1a(s, s->pm1a_sts | TMR_STS, s->pm1a_en); 1404 acpiPMTimerReset(s); 1405 } 1406 1407 /** 1408 * _BST method. 1409 */ 1410 static int acpiFetchBatteryStatus(ACPIState *s) 1411 { 1412 uint32_t *p = s->au8BatteryInfo; 1413 bool fPresent; /* battery present? */ 1414 PDMACPIBATCAPACITY hostRemainingCapacity; /* 0..100 */ 1415 PDMACPIBATSTATE hostBatteryState; /* bitfield */ 1416 uint32_t hostPresentRate; /* 0..1000 */ 1417 int rc; 1418 1419 if (!s->pDrv) 1420 return VINF_SUCCESS; 1421 rc = s->pDrv->pfnQueryBatteryStatus(s->pDrv, &fPresent, &hostRemainingCapacity, 1422 &hostBatteryState, &hostPresentRate); 1423 AssertRC(rc); 1424 1425 /* default values */ 1426 p[BAT_STATUS_STATE] = hostBatteryState; 1427 p[BAT_STATUS_PRESENT_RATE] = hostPresentRate == ~0U ? 0xFFFFFFFF 1428 : hostPresentRate * 50; /* mW */ 1429 p[BAT_STATUS_REMAINING_CAPACITY] = 50000; /* mWh */ 1430 p[BAT_STATUS_PRESENT_VOLTAGE] = 10000; /* mV */ 1431 1432 /* did we get a valid battery state? */ 1433 if (hostRemainingCapacity != PDM_ACPI_BAT_CAPACITY_UNKNOWN) 1434 p[BAT_STATUS_REMAINING_CAPACITY] = hostRemainingCapacity * 500; /* mWh */ 1435 if (hostBatteryState == PDM_ACPI_BAT_STATE_CHARGED) 1436 p[BAT_STATUS_PRESENT_RATE] = 0; /* mV */ 1437 1438 return VINF_SUCCESS; 1439 } 1440 1441 /** 1442 * _BIF method. 1443 */ 1444 static int acpiFetchBatteryInfo(ACPIState *s) 1445 { 1446 uint32_t *p = s->au8BatteryInfo; 1447 1448 p[BAT_INFO_UNITS] = 0; /* mWh */ 1449 p[BAT_INFO_DESIGN_CAPACITY] = 50000; /* mWh */ 1450 p[BAT_INFO_LAST_FULL_CHARGE_CAPACITY] = 50000; /* mWh */ 1451 p[BAT_INFO_TECHNOLOGY] = BAT_TECH_PRIMARY; 1452 p[BAT_INFO_DESIGN_VOLTAGE] = 10000; /* mV */ 1453 p[BAT_INFO_DESIGN_CAPACITY_OF_WARNING] = 100; /* mWh */ 1454 p[BAT_INFO_DESIGN_CAPACITY_OF_LOW] = 50; /* mWh */ 1455 p[BAT_INFO_CAPACITY_GRANULARITY_1] = 1; /* mWh */ 1456 p[BAT_INFO_CAPACITY_GRANULARITY_2] = 1; /* mWh */ 1457 1458 return VINF_SUCCESS; 1459 } 1460 1461 /** 1462 * _STA method. 1463 */ 1464 static uint32_t acpiGetBatteryDeviceStatus(ACPIState *s) 1465 { 1466 bool fPresent; /* battery present? */ 1467 PDMACPIBATCAPACITY hostRemainingCapacity; /* 0..100 */ 1468 PDMACPIBATSTATE hostBatteryState; /* bitfield */ 1469 uint32_t hostPresentRate; /* 0..1000 */ 1470 int rc; 1471 1472 if (!s->pDrv) 1473 return 0; 1474 rc = s->pDrv->pfnQueryBatteryStatus(s->pDrv, &fPresent, &hostRemainingCapacity, 1475 &hostBatteryState, &hostPresentRate); 1476 AssertRC(rc); 1477 1478 return fPresent 1479 ? STA_DEVICE_PRESENT_MASK /* present */ 1480 | STA_DEVICE_ENABLED_MASK /* enabled and decodes its resources */ 1481 | STA_DEVICE_SHOW_IN_UI_MASK /* should be shown in UI */ 1482 | STA_DEVICE_FUNCTIONING_PROPERLY_MASK /* functioning properly */ 1483 | STA_BATTERY_PRESENT_MASK /* battery is present */ 1484 : 0; /* device not present */ 1485 } 1486 1487 static uint32_t acpiGetPowerSource(ACPIState *s) 1488 { 1489 PDMACPIPOWERSOURCE ps; 1490 1491 /* query the current power source from the host driver */ 1492 if (!s->pDrv) 1493 return AC_ONLINE; 1494 int rc = s->pDrv->pfnQueryPowerSource(s->pDrv, &ps); 1495 AssertRC(rc); 1496 return ps == PDM_ACPI_POWER_SOURCE_BATTERY ? AC_OFFLINE : AC_ONLINE; 1497 } 1498 1499 PDMBOTHCBDECL(int) acpiBatIndexWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb) 1500 { 1501 ACPIState *s = (ACPIState *)pvUser; 1502 1503 switch (cb) 1504 { 1505 case 4: 1506 u32 >>= s->u8IndexShift; 1507 /* see comment at the declaration of u8IndexShift */ 1508 if (s->u8IndexShift == 0 && u32 == (BAT_DEVICE_STATUS << 2)) 1509 { 1510 s->u8IndexShift = 2; 1511 u32 >>= 2; 1512 } 1513 Assert(u32 < BAT_INDEX_LAST); 1514 s->uBatteryIndex = u32; 1515 break; 1516 default: 1517 AssertMsgFailed(("Port=%#x cb=%d u32=%#x\n", Port, cb, u32)); 1518 break; 1519 } 1520 return VINF_SUCCESS; 1521 } 1522 1523 PDMBOTHCBDECL(int) acpiBatDataRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb) 1524 { 1525 ACPIState *s = (ACPIState *)pvUser; 1526 1527 switch (cb) 1528 { 1529 case 4: 1530 switch (s->uBatteryIndex) 1531 { 1532 case BAT_STATUS_STATE: 1533 acpiFetchBatteryStatus(s); 1534 case BAT_STATUS_PRESENT_RATE: 1535 case BAT_STATUS_REMAINING_CAPACITY: 1536 case BAT_STATUS_PRESENT_VOLTAGE: 1537 *pu32 = s->au8BatteryInfo[s->uBatteryIndex]; 1538 break; 1539 1540 case BAT_INFO_UNITS: 1541 acpiFetchBatteryInfo(s); 1542 case BAT_INFO_DESIGN_CAPACITY: 1543 case BAT_INFO_LAST_FULL_CHARGE_CAPACITY: 1544 case BAT_INFO_TECHNOLOGY: 1545 case BAT_INFO_DESIGN_VOLTAGE: 1546 case BAT_INFO_DESIGN_CAPACITY_OF_WARNING: 1547 case BAT_INFO_DESIGN_CAPACITY_OF_LOW: 1548 case BAT_INFO_CAPACITY_GRANULARITY_1: 1549 case BAT_INFO_CAPACITY_GRANULARITY_2: 1550 *pu32 = s->au8BatteryInfo[s->uBatteryIndex]; 1551 break; 1552 1553 case BAT_DEVICE_STATUS: 1554 *pu32 = acpiGetBatteryDeviceStatus(s); 1555 break; 1556 1557 case BAT_POWER_SOURCE: 1558 *pu32 = acpiGetPowerSource(s); 1559 break; 1560 1561 default: 1562 AssertMsgFailed(("Invalid battery index %d\n", s->uBatteryIndex)); 1563 break; 1564 } 1565 break; 1566 default: 1567 return VERR_IOM_IOPORT_UNUSED; 1568 } 1569 return VINF_SUCCESS; 1570 } 1571 1572 PDMBOTHCBDECL(int) acpiSysInfoIndexWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb) 1573 { 1574 ACPIState *s = (ACPIState *)pvUser; 1575 1576 Log(("system_index = %d, %d\n", u32, u32 >> 2)); 1577 switch (cb) 1578 { 1579 case 4: 1580 if (u32 == SYSTEM_INFO_INDEX_VALID || u32 == SYSTEM_INFO_INDEX_INVALID) 1581 s->uSystemInfoIndex = u32; 1582 else 1583 { 1584 /* see comment at the declaration of u8IndexShift */ 1585 if ((u32 > SYSTEM_INFO_INDEX_END) && (s->u8IndexShift == 0)) 1586 { 1587 if (((u32 >> 2) < SYSTEM_INFO_INDEX_END) && ((u32 & 0x3)) == 0) 1588 { 1589 s->u8IndexShift = 2; 1590 } 1591 } 1592 1593 u32 >>= s->u8IndexShift; 1594 Assert(u32 < SYSTEM_INFO_INDEX_END); 1595 s->uSystemInfoIndex = u32; 1596 } 1597 break; 1598 1599 default: 1600 AssertMsgFailed(("Port=%#x cb=%d u32=%#x\n", Port, cb, u32)); 1601 break; 1602 } 1603 return VINF_SUCCESS; 1604 } 1605 1606 PDMBOTHCBDECL(int) acpiSysInfoDataRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb) 1607 { 1608 ACPIState *s = (ACPIState *)pvUser; 1609 1610 switch (cb) 1611 { 1612 case 4: 1613 switch (s->uSystemInfoIndex) 1614 { 1615 case SYSTEM_INFO_INDEX_LOW_MEMORY_LENGTH: 1616 *pu32 = s->cbRamLow; 1617 break; 1618 1619 case SYSTEM_INFO_INDEX_HIGH_MEMORY_LENGTH: 1620 *pu32 = s->cbRamHigh >> 16; /* 64KB units */ 1621 Assert(((uint64_t)*pu32 << 16) == s->cbRamHigh); 1622 break; 1623 1624 case SYSTEM_INFO_INDEX_USE_IOAPIC: 1625 *pu32 = s->u8UseIOApic; 1626 break; 1627 1628 case SYSTEM_INFO_INDEX_HPET_STATUS: 1629 *pu32 = s->fUseHpet ? ( STA_DEVICE_PRESENT_MASK 1630 | STA_DEVICE_ENABLED_MASK 1631 | STA_DEVICE_SHOW_IN_UI_MASK 1632 | STA_DEVICE_FUNCTIONING_PROPERLY_MASK) 1633 : 0; 1634 break; 1635 1636 case SYSTEM_INFO_INDEX_SMC_STATUS: 1637 *pu32 = s->fUseSmc ? ( STA_DEVICE_PRESENT_MASK 1638 | STA_DEVICE_ENABLED_MASK 1639 /* no need to show this device in the UI */ 1640 | STA_DEVICE_FUNCTIONING_PROPERLY_MASK) 1641 : 0; 1642 break; 1643 1644 case SYSTEM_INFO_INDEX_FDC_STATUS: 1645 *pu32 = s->fUseFdc ? ( STA_DEVICE_PRESENT_MASK 1646 | STA_DEVICE_ENABLED_MASK 1647 | STA_DEVICE_SHOW_IN_UI_MASK 1648 | STA_DEVICE_FUNCTIONING_PROPERLY_MASK) 1649 : 0; 1650 break; 1651 1652 case SYSTEM_INFO_INDEX_NIC_ADDRESS: 1653 *pu32 = s->u32NicPciAddress; 1654 break; 1655 1656 case SYSTEM_INFO_INDEX_AUDIO_ADDRESS: 1657 *pu32 = s->u32AudioPciAddress; 1658 break; 1659 1660 case SYSTEM_INFO_INDEX_POWER_STATES: 1661 *pu32 = RT_BIT(0) | RT_BIT(5); /* S1 and S5 always exposed */ 1662 if (s->fS1Enabled) /* Optionally expose S1 and S4 */ 1663 *pu32 |= RT_BIT(1); 1664 if (s->fS4Enabled) 1665 *pu32 |= RT_BIT(4); 1666 break; 1667 1668 case SYSTEM_INFO_INDEX_IOC_ADDRESS: 1669 *pu32 = s->u32IocPciAddress; 1670 break; 1671 1672 case SYSTEM_INFO_INDEX_HBC_ADDRESS: 1673 *pu32 = s->u32HbcPciAddress; 1674 break; 1675 1676 case SYSTEM_INFO_INDEX_PCI_BASE: 1677 /** @todo: couldn't MCFG be in 64-bit range? */ 1678 Assert(s->u64PciConfigMMioAddress < 0xffffffff); 1679 *pu32 = (uint32_t)s->u64PciConfigMMioAddress; 1680 break; 1681 1682 case SYSTEM_INFO_INDEX_PCI_LENGTH: 1683 /** @todo: couldn't MCFG be in 64-bit range? */ 1684 Assert(s->u64PciConfigMMioLength< 0xffffffff); 1685 *pu32 = (uint32_t)s->u64PciConfigMMioLength; 1686 break; 1687 1688 /* This is only for compatibility with older saved states that 1689 may include ACPI code that read these values. Legacy is 1690 a wonderful thing, isn't it? :-) */ 1691 case SYSTEM_INFO_INDEX_CPU0_STATUS: 1692 case SYSTEM_INFO_INDEX_CPU1_STATUS: 1693 case SYSTEM_INFO_INDEX_CPU2_STATUS: 1694 case SYSTEM_INFO_INDEX_CPU3_STATUS: 1695 *pu32 = ( s->fShowCpu 1696 && s->uSystemInfoIndex - SYSTEM_INFO_INDEX_CPU0_STATUS < s->cCpus 1697 && VMCPUSET_IS_PRESENT(&s->CpuSetAttached, 1698 s->uSystemInfoIndex - SYSTEM_INFO_INDEX_CPU0_STATUS)) 1699 ? ( STA_DEVICE_PRESENT_MASK 1700 | STA_DEVICE_ENABLED_MASK 1701 | STA_DEVICE_SHOW_IN_UI_MASK 1702 | STA_DEVICE_FUNCTIONING_PROPERLY_MASK) 1703 : 0; 1704 break; 1705 1706 case SYSTEM_INFO_INDEX_RTC_STATUS: 1707 *pu32 = s->fShowRtc ? ( STA_DEVICE_PRESENT_MASK 1708 | STA_DEVICE_ENABLED_MASK 1709 | STA_DEVICE_SHOW_IN_UI_MASK 1710 | STA_DEVICE_FUNCTIONING_PROPERLY_MASK) 1711 : 0; 1712 break; 1713 1714 case SYSTEM_INFO_INDEX_CPU_LOCKED: 1715 { 1716 if (s->idCpuLockCheck < VMM_MAX_CPU_COUNT) 1717 { 1718 *pu32 = VMCPUSET_IS_PRESENT(&s->CpuSetLocked, s->idCpuLockCheck); 1719 s->idCpuLockCheck = UINT32_C(0xffffffff); /* Make the entry invalid */ 1720 } 1721 else 1722 { 1723 AssertMsgFailed(("ACPI: CPU lock check protocol violation\n")); 1724 /* Always return locked status just to be safe */ 1725 *pu32 = 1; 1726 } 1727 break; 1728 } 1729 1730 case SYSTEM_INFO_INDEX_CPU_EVENT_TYPE: 1731 *pu32 = s->u32CpuEventType; 1732 break; 1733 1734 case SYSTEM_INFO_INDEX_CPU_EVENT: 1735 *pu32 = s->u32CpuEvent; 1736 break; 1737 1738 case SYSTEM_INFO_INDEX_SERIAL0_IOBASE: 1739 *pu32 = s->uSerial0IoPortBase; 1740 break; 1741 1742 case SYSTEM_INFO_INDEX_SERIAL0_IRQ: 1743 *pu32 = s->uSerial0Irq; 1744 break; 1745 1746 case SYSTEM_INFO_INDEX_SERIAL1_IOBASE: 1747 *pu32 = s->uSerial1IoPortBase; 1748 break; 1749 1750 case SYSTEM_INFO_INDEX_SERIAL1_IRQ: 1751 *pu32 = s->uSerial1Irq; 1752 break; 1753 1754 case SYSTEM_INFO_INDEX_END: 1755 break; 1756 1757 /* Solaris 9 tries to read from this index */ 1758 case SYSTEM_INFO_INDEX_INVALID: 1759 *pu32 = 0; 1760 break; 1761 1762 default: 1763 AssertMsgFailed(("Invalid system info index %d\n", s->uSystemInfoIndex)); 1764 break; 1765 } 1766 break; 1767 1768 default: 1769 return VERR_IOM_IOPORT_UNUSED; 1770 } 1771 1772 Log(("index %d val %d\n", s->uSystemInfoIndex, *pu32)); 1773 return VINF_SUCCESS; 1774 } 1775 1776 PDMBOTHCBDECL(int) acpiSysInfoDataWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb) 1777 { 1778 ACPIState *s = (ACPIState *)pvUser; 1779 1780 Log(("addr=%#x cb=%d u32=%#x si=%#x\n", Port, cb, u32, s->uSystemInfoIndex)); 1781 1782 if (cb == 4) 1783 { 1784 switch (s->uSystemInfoIndex) 1785 { 1786 case SYSTEM_INFO_INDEX_INVALID: 1787 AssertMsg(u32 == 0xbadc0de, ("u32=%u\n", u32)); 1788 s->u8IndexShift = 0; 1789 break; 1790 1791 case SYSTEM_INFO_INDEX_VALID: 1792 AssertMsg(u32 == 0xbadc0de, ("u32=%u\n", u32)); 1793 s->u8IndexShift = 2; 1794 break; 1795 1796 case SYSTEM_INFO_INDEX_CPU_LOCK_CHECK: 1797 s->idCpuLockCheck = u32; 1798 break; 1799 1800 case SYSTEM_INFO_INDEX_CPU_LOCKED: 1801 if (u32 < s->cCpus) 1802 VMCPUSET_DEL(&s->CpuSetLocked, u32); /* Unlock the CPU */ 1803 else 1804 LogRel(("ACPI: CPU %u does not exist\n", u32)); 1805 break; 1806 1807 default: 1808 AssertMsgFailed(("Port=%#x cb=%d u32=%#x system_index=%#x\n", 1809 Port, cb, u32, s->uSystemInfoIndex)); 1810 break; 1811 } 1812 } 1813 else 1814 AssertMsgFailed(("Port=%#x cb=%d u32=%#x\n", Port, cb, u32)); 1815 return VINF_SUCCESS; 1816 } 1817 1818 /** @todo Don't call functions, but do the job in the read/write handlers 1819 * here! */ 1820 1821 /* IO Helpers */ 1822 PDMBOTHCBDECL(int) acpiPm1aEnRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb) 1823 { 1824 switch (cb) 1825 { 1826 case 2: 1827 *pu32 = acpiPm1aEnReadw((ACPIState*)pvUser, Port); 1828 break; 1829 default: 1830 return VERR_IOM_IOPORT_UNUSED; 1831 } 1832 return VINF_SUCCESS; 1833 } 1834 1835 PDMBOTHCBDECL(int) acpiPm1aStsRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb) 1836 { 1837 switch (cb) 1838 { 1839 case 2: 1840 *pu32 = acpiPm1aStsReadw((ACPIState*)pvUser, Port); 1841 break; 1842 default: 1843 AssertMsgFailed(("PM1 status read: width %d\n", cb)); 1844 return VERR_IOM_IOPORT_UNUSED; 1845 } 1846 return VINF_SUCCESS; 1847 } 1848 1849 PDMBOTHCBDECL(int) acpiPm1aCtlRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb) 1850 { 1851 switch (cb) 1852 { 1853 case 2: 1854 *pu32 = acpiPm1aCtlReadw((ACPIState*)pvUser, Port); 1855 break; 1856 default: 1857 AssertMsgFailed(("PM1 control read: width %d\n", cb)); 1858 return VERR_IOM_IOPORT_UNUSED; 1859 } 1860 return VINF_SUCCESS; 1861 } 1862 1863 PDMBOTHCBDECL(int) acpiPM1aEnWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb) 1864 { 1865 switch (cb) 1866 { 1867 case 2: 1868 acpiPM1aEnWritew((ACPIState*)pvUser, Port, u32); 1869 break; 1870 case 4: 1871 acpiPM1aEnWritew((ACPIState*)pvUser, Port, u32 & 0xffff); 1872 break; 1873 default: 1874 AssertMsgFailed(("Port=%#x cb=%d u32=%#x\n", Port, cb, u32)); 1875 break; 1876 } 1877 return VINF_SUCCESS; 1878 } 1879 1880 PDMBOTHCBDECL(int) acpiPM1aStsWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb) 1881 { 1882 switch (cb) 1883 { 1884 case 2: 1885 acpiPM1aStsWritew((ACPIState*)pvUser, Port, u32); 1886 break; 1887 case 4: 1888 acpiPM1aStsWritew((ACPIState*)pvUser, Port, u32 & 0xffff); 1889 break; 1890 default: 1891 AssertMsgFailed(("Port=%#x cb=%d u32=%#x\n", Port, cb, u32)); 1892 break; 1893 } 1894 return VINF_SUCCESS; 1895 } 1896 1897 PDMBOTHCBDECL(int) acpiPM1aCtlWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb) 1898 { 1899 switch (cb) 1900 { 1901 case 2: 1902 return acpiPM1aCtlWritew((ACPIState*)pvUser, Port, u32); 1903 case 4: 1904 return acpiPM1aCtlWritew((ACPIState*)pvUser, Port, u32 & 0xffff); 1905 default: 1906 AssertMsgFailed(("Port=%#x cb=%d u32=%#x\n", Port, cb, u32)); 1907 break; 1908 } 1909 return VINF_SUCCESS; 1910 } 1911 1912 #endif /* IN_RING3 */ 1913 1914 /** 1915 * PMTMR readable from host/guest. 1916 */ 1917 PDMBOTHCBDECL(int) acpiPMTmrRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb) 1918 { 1919 if (cb == 4) 1920 { 1921 ACPIState *s = PDMINS_2_DATA(pDevIns, ACPIState *); 1922 uint64_t u64Now = TMTimerGet(s->CTX_SUFF(ts)); 1923 uint64_t u64Seen; 1924 do 1925 { 1926 u64Seen = ASMAtomicReadU64(&s->u64PmTimerLastSeen); 1927 if (u64Now < u64Seen) 1928 u64Now = u64Seen + 1; 1929 } while (!ASMAtomicCmpXchgU64(&s->u64PmTimerLastSeen, u64Now, u64Seen)); 1930 1931 uint64_t u64Elapsed = u64Now - s->u64PmTimerInitial; 1932 *pu32 = ASMMultU64ByU32DivByU32(u64Elapsed, PM_TMR_FREQ, TMTimerGetFreq(s->CTX_SUFF(ts))); 1933 Log(("acpi: acpiPMTmrRead -> %#x\n", *pu32)); 1934 return VINF_SUCCESS; 1935 } 1936 return VERR_IOM_IOPORT_UNUSED; 1937 } 1938 1939 #ifdef IN_RING3 1940 1941 PDMBOTHCBDECL(int) acpiGpe0StsRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb) 1942 { 1943 switch (cb) 1944 { 1945 case 1: 1946 *pu32 = acpiGpe0StsReadb((ACPIState*)pvUser, Port); 1947 break; 1948 default: 1949 return VERR_IOM_IOPORT_UNUSED; 1950 } 1951 return VINF_SUCCESS; 1952 } 1953 1954 PDMBOTHCBDECL(int) acpiGpe0EnRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb) 1955 { 1956 switch (cb) 1957 { 1958 case 1: 1959 *pu32 = acpiGpe0EnReadb((ACPIState*)pvUser, Port); 1960 break; 1961 default: 1962 return VERR_IOM_IOPORT_UNUSED; 1963 } 1964 return VINF_SUCCESS; 1965 } 1966 1967 PDMBOTHCBDECL(int) acpiGpe0StsWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb) 1968 { 1969 switch (cb) 1970 { 1971 case 1: 1972 acpiGpe0StsWriteb((ACPIState*)pvUser, Port, u32); 1973 break; 1974 default: 1975 AssertMsgFailed(("Port=%#x cb=%d u32=%#x\n", Port, cb, u32)); 1976 break; 1977 } 1978 return VINF_SUCCESS; 1979 } 1980 1981 PDMBOTHCBDECL(int) acpiGpe0EnWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb) 1982 { 1983 switch (cb) 1984 { 1985 case 1: 1986 acpiGpe0EnWriteb((ACPIState*)pvUser, Port, u32); 1987 break; 1988 default: 1989 AssertMsgFailed(("Port=%#x cb=%d u32=%#x\n", Port, cb, u32)); 1990 break; 1991 } 1992 return VINF_SUCCESS; 1993 } 1994 1995 PDMBOTHCBDECL(int) acpiSmiWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb) 1996 { 1997 switch (cb) 1998 { 1999 case 1: 2000 acpiSmiWriteU8((ACPIState*)pvUser, Port, u32); 2001 break; 2002 default: 2003 AssertMsgFailed(("Port=%#x cb=%d u32=%#x\n", Port, cb, u32)); 2004 break; 2005 } 2006 return VINF_SUCCESS; 2007 } 2008 2009 PDMBOTHCBDECL(int) acpiResetWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb) 2010 { 2011 switch (cb) 2012 { 2013 case 1: 2014 return acpiResetWriteU8((ACPIState*)pvUser, Port, u32); 2015 default: 2016 AssertMsgFailed(("Port=%#x cb=%d u32=%#x\n", Port, cb, u32)); 2017 break; 2018 } 2019 return VINF_SUCCESS; 2020 } 2021 2022 #ifdef DEBUG_ACPI 2023 2024 PDMBOTHCBDECL(int) acpiDhexWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb) 2025 { 2026 switch (cb) 2027 { 2028 case 1: 2029 Log(("%#x\n", u32 & 0xff)); 2030 break; 2031 case 2: 2032 Log(("%#6x\n", u32 & 0xffff)); 2033 case 4: 2034 Log(("%#10x\n", u32)); 2035 break; 2036 default: 2037 AssertMsgFailed(("Port=%#x cb=%d u32=%#x\n", Port, cb, u32)); 2038 break; 2039 } 2040 return VINF_SUCCESS; 2041 } 2042 2043 PDMBOTHCBDECL(int) acpiDchrWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb) 2044 { 2045 switch (cb) 2046 { 2047 case 1: 2048 Log(("%c", u32 & 0xff)); 2049 break; 2050 default: 2051 AssertMsgFailed(("Port=%#x cb=%d u32=%#x\n", Port, cb, u32)); 2052 break; 2053 } 2054 return VINF_SUCCESS; 2055 } 2056 2057 #endif /* DEBUG_ACPI */ 2058 2059 static int acpiRegisterPmHandlers(ACPIState* pThis) 2060 { 2061 int rc = VINF_SUCCESS; 2062 2063 #define R(offset, cnt, writer, reader, description) \ 2064 do { \ 2065 rc = PDMDevHlpIOPortRegister(pThis->pDevIns, acpiPmPort(pThis, offset), cnt, pThis, writer, reader, \ 2066 NULL, NULL, description); \ 2067 if (RT_FAILURE(rc)) \ 2068 return rc; \ 2069 } while (0) 2070 #define L (GPE0_BLK_LEN / 2) 2071 2072 R(PM1a_EVT_OFFSET+2, 1, acpiPM1aEnWrite, acpiPm1aEnRead, "ACPI PM1a Enable"); 2073 R(PM1a_EVT_OFFSET, 1, acpiPM1aStsWrite, acpiPm1aStsRead, "ACPI PM1a Status"); 2074 R(PM1a_CTL_OFFSET, 1, acpiPM1aCtlWrite, acpiPm1aCtlRead, "ACPI PM1a Control"); 2075 R(PM_TMR_OFFSET, 1, NULL, acpiPMTmrRead, "ACPI PM Timer"); 2076 R(GPE0_OFFSET + L, L, acpiGpe0EnWrite, acpiGpe0EnRead, "ACPI GPE0 Enable"); 2077 R(GPE0_OFFSET, L, acpiGpe0StsWrite, acpiGpe0StsRead, "ACPI GPE0 Status"); 2078 #undef L 2079 #undef R 2080 2081 /* register RC stuff */ 2082 if (pThis->fGCEnabled) 2083 { 2084 rc = PDMDevHlpIOPortRegisterRC(pThis->pDevIns, acpiPmPort(pThis, PM_TMR_OFFSET), 2085 1, 0, NULL, "acpiPMTmrRead", 2086 NULL, NULL, "ACPI PM Timer"); 2087 AssertRCReturn(rc, rc); 2088 } 2089 2090 /* register R0 stuff */ 2091 if (pThis->fR0Enabled) 2092 { 2093 rc = PDMDevHlpIOPortRegisterR0(pThis->pDevIns, acpiPmPort(pThis, PM_TMR_OFFSET), 2094 1, 0, NULL, "acpiPMTmrRead", 2095 NULL, NULL, "ACPI PM Timer"); 2096 AssertRCReturn(rc, rc); 2097 } 2098 2099 return rc; 2100 } 2101 2102 static int acpiUnregisterPmHandlers(ACPIState *pThis) 2103 { 2104 #define U(offset, cnt) \ 2105 do { \ 2106 int rc = PDMDevHlpIOPortDeregister(pThis->pDevIns, acpiPmPort(pThis, offset), cnt); \ 2107 AssertRCReturn(rc, rc); \ 2108 } while (0) 2109 #define L (GPE0_BLK_LEN / 2) 2110 2111 U(PM1a_EVT_OFFSET+2, 1); 2112 U(PM1a_EVT_OFFSET, 1); 2113 U(PM1a_CTL_OFFSET, 1); 2114 U(PM_TMR_OFFSET, 1); 2115 U(GPE0_OFFSET + L, L); 2116 U(GPE0_OFFSET, L); 2117 #undef L 2118 #undef U 2119 2120 return VINF_SUCCESS; 2121 } 2122 2123 /** 2124 * Saved state structure description, version 4. 2125 */ 2126 static const SSMFIELD g_AcpiSavedStateFields4[] = 2127 { 2128 SSMFIELD_ENTRY(ACPIState, pm1a_en), 2129 SSMFIELD_ENTRY(ACPIState, pm1a_sts), 2130 SSMFIELD_ENTRY(ACPIState, pm1a_ctl), 2131 SSMFIELD_ENTRY(ACPIState, u64PmTimerInitial), 2132 SSMFIELD_ENTRY(ACPIState, gpe0_en), 2133 SSMFIELD_ENTRY(ACPIState, gpe0_sts), 2134 SSMFIELD_ENTRY(ACPIState, uBatteryIndex), 2135 SSMFIELD_ENTRY(ACPIState, uSystemInfoIndex), 2136 SSMFIELD_ENTRY(ACPIState, u64RamSize), 2137 SSMFIELD_ENTRY(ACPIState, u8IndexShift), 2138 SSMFIELD_ENTRY(ACPIState, u8UseIOApic), 2139 SSMFIELD_ENTRY(ACPIState, uSleepState), 2140 SSMFIELD_ENTRY_TERM() 2141 }; 2142 2143 /** 2144 * Saved state structure description, version 5. 2145 */ 2146 static const SSMFIELD g_AcpiSavedStateFields5[] = 2147 { 2148 SSMFIELD_ENTRY(ACPIState, pm1a_en), 2149 SSMFIELD_ENTRY(ACPIState, pm1a_sts), 2150 SSMFIELD_ENTRY(ACPIState, pm1a_ctl), 2151 SSMFIELD_ENTRY(ACPIState, u64PmTimerInitial), 2152 SSMFIELD_ENTRY(ACPIState, gpe0_en), 2153 SSMFIELD_ENTRY(ACPIState, gpe0_sts), 2154 SSMFIELD_ENTRY(ACPIState, uBatteryIndex), 2155 SSMFIELD_ENTRY(ACPIState, uSystemInfoIndex), 2156 SSMFIELD_ENTRY(ACPIState, uSleepState), 2157 SSMFIELD_ENTRY(ACPIState, u8IndexShift), 2158 SSMFIELD_ENTRY(ACPIState, uPmIoPortBase), 2159 SSMFIELD_ENTRY_TERM() 2160 }; 2161 2162 /** 2163 * Saved state structure description, version 6. 2164 */ 2165 static const SSMFIELD g_AcpiSavedStateFields6[] = 2166 { 2167 SSMFIELD_ENTRY(ACPIState, pm1a_en), 2168 SSMFIELD_ENTRY(ACPIState, pm1a_sts), 2169 SSMFIELD_ENTRY(ACPIState, pm1a_ctl), 2170 SSMFIELD_ENTRY(ACPIState, u64PmTimerInitial), 2171 SSMFIELD_ENTRY(ACPIState, gpe0_en), 2172 SSMFIELD_ENTRY(ACPIState, gpe0_sts), 2173 SSMFIELD_ENTRY(ACPIState, uBatteryIndex), 2174 SSMFIELD_ENTRY(ACPIState, uSystemInfoIndex), 2175 SSMFIELD_ENTRY(ACPIState, uSleepState), 2176 SSMFIELD_ENTRY(ACPIState, u8IndexShift), 2177 SSMFIELD_ENTRY(ACPIState, uPmIoPortBase), 2178 SSMFIELD_ENTRY(ACPIState, fSuspendToSavedState), 2179 SSMFIELD_ENTRY_TERM() 2180 }; 2181 2182 2183 /** 2184 * @callback_method_impl{FNSSMDEVSAVEEXEC} 2185 */ 2186 static DECLCALLBACK(int) acpiSaveState(PPDMDEVINS pDevIns, PSSMHANDLE pSSMHandle) 2187 { 2188 ACPIState *pThis = PDMINS_2_DATA(pDevIns, ACPIState *); 2189 return SSMR3PutStruct(pSSMHandle, pThis, &g_AcpiSavedStateFields6[0]); 2190 } 2191 2192 /** 2193 * @callback_method_impl{FNSSMDEVLOADEXEC} 2194 */ 2195 static DECLCALLBACK(int) acpiLoadState(PPDMDEVINS pDevIns, PSSMHANDLE pSSMHandle, 2196 uint32_t uVersion, uint32_t uPass) 2197 { 2198 ACPIState *pThis = PDMINS_2_DATA(pDevIns, ACPIState *); 2199 Assert(uPass == SSM_PASS_FINAL); NOREF(uPass); 2200 2201 /* 2202 * Unregister PM handlers, will register with actual base after state 2203 * successfully loaded. 2204 */ 2205 int rc = acpiUnregisterPmHandlers(pThis); 2206 if (RT_FAILURE(rc)) 2207 return rc; 2208 2209 switch (uVersion) 2210 { 2211 case 4: 2212 rc = SSMR3GetStruct(pSSMHandle, pThis, &g_AcpiSavedStateFields4[0]); 2213 break; 2214 case 5: 2215 rc = SSMR3GetStruct(pSSMHandle, pThis, &g_AcpiSavedStateFields5[0]); 2216 break; 2217 case 6: 2218 rc = SSMR3GetStruct(pSSMHandle, pThis, &g_AcpiSavedStateFields6[0]); 2219 break; 2220 default: 2221 rc = VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION; 2222 break; 2223 } 2224 if (RT_SUCCESS(rc)) 2225 { 2226 rc = acpiRegisterPmHandlers(pThis); 2227 if (RT_FAILURE(rc)) 2228 return rc; 2229 rc = acpiFetchBatteryStatus(pThis); 2230 if (RT_FAILURE(rc)) 2231 return rc; 2232 rc = acpiFetchBatteryInfo(pThis); 2233 if (RT_FAILURE(rc)) 2234 return rc; 2235 rc = acpiPMTimerReset(pThis); 2236 if (RT_FAILURE(rc)) 2237 return rc; 2238 } 2239 return rc; 2240 } 2241 2242 /** 2243 * @interface_method_impl{PDMIBASE,pfnQueryInterface} 2244 */ 2245 static DECLCALLBACK(void *) acpiQueryInterface(PPDMIBASE pInterface, const char *pszIID) 2246 { 2247 ACPIState *pThis = RT_FROM_MEMBER(pInterface, ACPIState, IBase); 2248 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pThis->IBase); 2249 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIACPIPORT, &pThis->IACPIPort); 2250 return NULL; 2251 } 2252 2253 /** 2254 * Create the ACPI tables. 2440 /** 2441 * Create the ACPI tables in guest memory. 2255 2442 */ 2256 2443 static int acpiPlantTables(ACPIState *s) … … 2258 2445 int rc; 2259 2446 RTGCPHYS32 GCPhysCur, GCPhysRsdt, GCPhysXsdt, GCPhysFadtAcpi1, GCPhysFadtAcpi2, GCPhysFacs, GCPhysDsdt; 2260 RTGCPHYS32 GCPhysHpet = 0, GCPhysApic = 0, GCPhysSsdt = 0, GCPhysMcfg = 0; 2447 RTGCPHYS32 GCPhysHpet = 0; 2448 RTGCPHYS32 GCPhysApic = 0; 2449 RTGCPHYS32 GCPhysSsdt = 0; 2450 RTGCPHYS32 GCPhysMcfg = 0; 2261 2451 uint32_t addend = 0; 2262 2452 RTGCPHYS32 aGCPhysRsdt[8]; 2263 2453 RTGCPHYS32 aGCPhysXsdt[8]; 2264 uint32_t cAddr, iMadt = 0, iHpet = 0, iSsdt = 0, iMcfg = 0; 2454 uint32_t cAddr; 2455 uint32_t iMadt = 0; 2456 uint32_t iHpet = 0; 2457 uint32_t iSsdt = 0; 2458 uint32_t iMcfg = 0; 2265 2459 size_t cbRsdt = sizeof(ACPITBLHEADER); 2266 2460 size_t cbXsdt = sizeof(ACPITBLHEADER); … … 2342 2536 } 2343 2537 2344 void * pSsdtCode = NULL;2538 void *pvSsdtCode = NULL; 2345 2539 size_t cbSsdtSize = 0; 2346 rc = acpiPrepareSsdt(s->pDevIns, &p SsdtCode, &cbSsdtSize);2540 rc = acpiPrepareSsdt(s->pDevIns, &pvSsdtCode, &cbSsdtSize); 2347 2541 if (RT_FAILURE(rc)) 2348 2542 return rc; … … 2353 2547 GCPhysDsdt = GCPhysCur; 2354 2548 2355 void * pDsdtCode = NULL;2549 void *pvDsdtCode = NULL; 2356 2550 size_t cbDsdtSize = 0; 2357 rc = acpiPrepareDsdt(s->pDevIns, &p DsdtCode, &cbDsdtSize);2551 rc = acpiPrepareDsdt(s->pDevIns, &pvDsdtCode, &cbDsdtSize); 2358 2552 if (RT_FAILURE(rc)) 2359 2553 return rc; … … 2380 2574 2381 2575 acpiSetupRSDP((ACPITBLRSDP*)s->au8RSDPPage, GCPhysRsdt + addend, GCPhysXsdt + addend); 2382 acpiSetupDSDT(s, GCPhysDsdt + addend, p DsdtCode, cbDsdtSize);2383 acpiCleanupDsdt(s->pDevIns, p DsdtCode);2576 acpiSetupDSDT(s, GCPhysDsdt + addend, pvDsdtCode, cbDsdtSize); 2577 acpiCleanupDsdt(s->pDevIns, pvDsdtCode); 2384 2578 acpiSetupFACS(s, GCPhysFacs + addend); 2385 2579 acpiSetupFADT(s, GCPhysFadtAcpi1 + addend, GCPhysFadtAcpi2 + addend, GCPhysFacs + addend, GCPhysDsdt + addend); … … 2406 2600 } 2407 2601 2408 acpiSetupSSDT(s, GCPhysSsdt + addend, p SsdtCode, cbSsdtSize);2409 acpiCleanupSsdt(s->pDevIns, p SsdtCode);2602 acpiSetupSSDT(s, GCPhysSsdt + addend, pvSsdtCode, cbSsdtSize); 2603 acpiCleanupSsdt(s->pDevIns, pvSsdtCode); 2410 2604 aGCPhysRsdt[iSsdt] = GCPhysSsdt + addend; 2411 2605 aGCPhysXsdt[iSsdt] = GCPhysSsdt + addend; … … 2417 2611 } 2418 2612 2419 static int acpiUpdatePmHandlers(ACPIState *pThis, RTIOPORT uNewBase) 2420 { 2421 Log(("acpi: rebasing PM 0x%x -> 0x%x\n", pThis->uPmIoPortBase, uNewBase)); 2422 if (uNewBase != pThis->uPmIoPortBase) 2423 { 2424 int rc; 2425 2426 rc = acpiUnregisterPmHandlers(pThis); 2427 if (RT_FAILURE(rc)) 2428 return rc; 2429 2430 pThis->uPmIoPortBase = uNewBase; 2431 2432 rc = acpiRegisterPmHandlers(pThis); 2433 if (RT_FAILURE(rc)) 2434 return rc; 2435 2436 /* We have to update FADT table acccording to the new base */ 2437 rc = acpiPlantTables(pThis); 2438 AssertRC(rc); 2439 if (RT_FAILURE(rc)) 2440 return rc; 2441 } 2442 2443 return VINF_SUCCESS; 2444 } 2445 2446 static uint32_t acpiPciConfigRead(PPCIDEVICE pPciDev, uint32_t Address, unsigned cb) 2613 /** 2614 * @callback_method_impl{FNPCICONFIGREAD} 2615 */ 2616 static DECLCALLBACK(uint32_t) acpiPciConfigRead(PPCIDEVICE pPciDev, uint32_t Address, unsigned cb) 2447 2617 { 2448 2618 PPDMDEVINS pDevIns = pPciDev->pDevIns; 2449 ACPIState * pThis= PDMINS_2_DATA(pDevIns, ACPIState *);2619 ACPIState *pThis = PDMINS_2_DATA(pDevIns, ACPIState *); 2450 2620 2451 2621 Log2(("acpi: PCI config read: 0x%x (%d)\n", Address, cb)); 2452 2453 2622 return pThis->pfnAcpiPciConfigRead(pPciDev, Address, cb); 2454 2623 } 2455 2624 2456 static void acpiPciConfigWrite(PPCIDEVICE pPciDev, uint32_t Address, uint32_t u32Value, unsigned cb) 2625 /** 2626 * @callback_method_impl{FNPCICONFIGWRITE} 2627 */ 2628 static DECLCALLBACK(void) acpiPciConfigWrite(PPCIDEVICE pPciDev, uint32_t Address, uint32_t u32Value, unsigned cb) 2457 2629 { 2458 2630 PPDMDEVINS pDevIns = pPciDev->pDevIns; … … 2460 2632 2461 2633 Log2(("acpi: PCI config write: 0x%x -> 0x%x (%d)\n", u32Value, Address, cb)); 2462 2634 DEVACPI_LOCK_R3(pThis); 2463 2635 2464 2636 if (Address == VBOX_PCI_INTERRUPT_LINE) … … 2476 2648 if (pPciDev->config[0x80] & 0x1) 2477 2649 { 2478 int rc; 2479 2480 RTIOPORT uNewBase = RTIOPORT(PCIDevGetDWord(pPciDev, 0x40)); 2481 uNewBase &= 0xffc0; 2482 2483 rc = acpiUpdatePmHandlers(pThis, uNewBase); 2650 RTIOPORT NewIoPortBase = (RTIOPORT)PCIDevGetDWord(pPciDev, 0x40); 2651 NewIoPortBase &= 0xffc0; 2652 2653 int rc = acpiUpdatePmHandlers(pThis, NewIoPortBase); 2484 2654 AssertRC(rc); 2485 2655 } 2486 2656 } 2657 2658 DEVACPI_UNLOCK(pThis); 2487 2659 } 2488 2660 … … 2500 2672 { 2501 2673 ACPIState *s = PDMINS_2_DATA(pDevIns, ACPIState *); 2502 2503 2674 LogFlow(("acpiAttach: pDevIns=%p iLUN=%u fFlags=%#x\n", pDevIns, iLUN, fFlags)); 2504 2675 … … 2509 2680 2510 2681 /* Check if it was already attached */ 2511 if (VMCPUSET_IS_PRESENT(&s->CpuSetAttached, iLUN)) 2512 return VINF_SUCCESS; 2513 2514 PPDMIBASE IBaseTmp; 2515 int rc = PDMDevHlpDriverAttach(pDevIns, iLUN, &s->IBase, &IBaseTmp, "ACPI CPU"); 2516 2517 if (RT_SUCCESS(rc)) 2518 { 2519 /* Enable the CPU */ 2520 VMCPUSET_ADD(&s->CpuSetAttached, iLUN); 2521 2522 /* 2523 * Lock the CPU because we don't know if the guest will use it or not. 2524 * Prevents ejection while the CPU is still used 2525 */ 2526 VMCPUSET_ADD(&s->CpuSetLocked, iLUN); 2527 s->u32CpuEventType = CPU_EVENT_TYPE_ADD; 2528 s->u32CpuEvent = iLUN; 2529 /* Notify the guest */ 2530 update_gpe0(s, s->gpe0_sts | 0x2, s->gpe0_en); 2531 } 2682 int rc = VINF_SUCCESS; 2683 DEVACPI_LOCK_R3(s); 2684 if (!VMCPUSET_IS_PRESENT(&s->CpuSetAttached, iLUN)) 2685 { 2686 PPDMIBASE IBaseTmp; 2687 rc = PDMDevHlpDriverAttach(pDevIns, iLUN, &s->IBase, &IBaseTmp, "ACPI CPU"); 2688 if (RT_SUCCESS(rc)) 2689 { 2690 /* Enable the CPU */ 2691 VMCPUSET_ADD(&s->CpuSetAttached, iLUN); 2692 2693 /* 2694 * Lock the CPU because we don't know if the guest will use it or not. 2695 * Prevents ejection while the CPU is still used 2696 */ 2697 VMCPUSET_ADD(&s->CpuSetLocked, iLUN); 2698 s->u32CpuEventType = CPU_EVENT_TYPE_ADD; 2699 s->u32CpuEvent = iLUN; 2700 2701 /* Notify the guest */ 2702 update_gpe0(s, s->gpe0_sts | 0x2, s->gpe0_en); 2703 } 2704 } 2705 DEVACPI_UNLOCK(s); 2532 2706 return rc; 2533 2707 } … … 2550 2724 2551 2725 /* Check if it was already detached */ 2726 DEVACPI_LOCK_R3(s); 2552 2727 if (VMCPUSET_IS_PRESENT(&s->CpuSetAttached, iLUN)) 2553 2728 { 2554 AssertMsgReturnVoid(!(VMCPUSET_IS_PRESENT(&s->CpuSetLocked, iLUN)), ("CPU is still locked by the guest\n")); 2555 2556 /* Disable the CPU */ 2557 VMCPUSET_DEL(&s->CpuSetAttached, iLUN); 2558 s->u32CpuEventType = CPU_EVENT_TYPE_REMOVE; 2559 s->u32CpuEvent = iLUN; 2560 /* Notify the guest */ 2561 update_gpe0(s, s->gpe0_sts | 0x2, s->gpe0_en); 2562 } 2729 if (!VMCPUSET_IS_PRESENT(&s->CpuSetLocked, iLUN)) 2730 { 2731 /* Disable the CPU */ 2732 VMCPUSET_DEL(&s->CpuSetAttached, iLUN); 2733 s->u32CpuEventType = CPU_EVENT_TYPE_REMOVE; 2734 s->u32CpuEvent = iLUN; 2735 2736 /* Notify the guest */ 2737 update_gpe0(s, s->gpe0_sts | 0x2, s->gpe0_en); 2738 } 2739 else 2740 AssertMsgFailed(("CPU is still locked by the guest\n")); 2741 } 2742 DEVACPI_UNLOCK(s); 2563 2743 } 2564 2744 … … 2582 2762 static DECLCALLBACK(void) acpiReset(PPDMDEVINS pDevIns) 2583 2763 { 2584 ACPIState * s = PDMINS_2_DATA(pDevIns, ACPIState *);2585 2586 s->pm1a_en = 0;2587 s->pm1a_sts = 0;2588 s->pm1a_ctl = 0;2589 s->u64PmTimerInitial = TMTimerGet(s->CTX_SUFF(ts));2590 acpiP MTimerReset(s);2591 s->uBatteryIndex = 0;2592 s->uSystemInfoIndex = 0;2593 s->gpe0_en = 0;2594 s->gpe0_sts = 0;2595 s->uSleepState = 0;2764 ACPIState *pThis = PDMINS_2_DATA(pDevIns, ACPIState *); 2765 2766 pThis->pm1a_en = 0; 2767 pThis->pm1a_sts = 0; 2768 pThis->pm1a_ctl = 0; 2769 pThis->u64PmTimerInitial = TMTimerGet(pThis->pPmTimerR3); 2770 acpiPmTimerReset(pThis, pThis->u64PmTimerInitial); 2771 pThis->uBatteryIndex = 0; 2772 pThis->uSystemInfoIndex = 0; 2773 pThis->gpe0_en = 0; 2774 pThis->gpe0_sts = 0; 2775 pThis->uSleepState = 0; 2596 2776 2597 2777 /** @todo Should we really reset PM base? */ 2598 acpiUpdatePmHandlers( s, PM_PORT_BASE);2599 2600 acpiPlantTables( s);2778 acpiUpdatePmHandlers(pThis, PM_PORT_BASE); 2779 2780 acpiPlantTables(pThis); 2601 2781 } 2602 2782 … … 2606 2786 static DECLCALLBACK(void) acpiRelocate(PPDMDEVINS pDevIns, RTGCINTPTR offDelta) 2607 2787 { 2608 ACPIState * s = PDMINS_2_DATA(pDevIns, ACPIState *);2609 s->tsRC = TMTimerRCPtr(s->CTX_SUFF(ts));2788 ACPIState *pThis = PDMINS_2_DATA(pDevIns, ACPIState *); 2789 pThis->pPmTimerRC = TMTimerRCPtr(pThis->pPmTimerR3); 2610 2790 } 2611 2791 … … 2619 2799 PDMDEV_CHECK_VERSIONS_RETURN(pDevIns); 2620 2800 2621 /* Validate and read the configuration. */ 2801 /* 2802 * Init data and set defaults. 2803 */ 2804 /** @todo move more of the code up! */ 2805 2806 pDevIns->pCritSectR3 = PDMDevHlpCritSectGetNop(pDevIns); 2807 int rc = PDMDevHlpCritSectInit(pDevIns, &s->CritSect, RT_SRC_POS, "acpi"); 2808 AssertRCReturn(rc, rc); 2809 2810 /* 2811 * Validate and read the configuration. 2812 */ 2622 2813 if (!CFGMR3AreValuesValid(pCfg, 2623 2814 "RamSize\0" … … 2655 2846 2656 2847 /* query whether we are supposed to present an IOAPIC */ 2657 intrc = CFGMR3QueryU8Def(pCfg, "IOAPIC", &s->u8UseIOApic, 1);2848 rc = CFGMR3QueryU8Def(pCfg, "IOAPIC", &s->u8UseIOApic, 1); 2658 2849 if (RT_FAILURE(rc)) 2659 2850 return PDMDEV_SET_ERROR(pDevIns, rc, … … 2795 2986 s->IBase.pfnQueryInterface = acpiQueryInterface; 2796 2987 /* IACPIPort */ 2797 s->IACPIPort.pfnSleepButtonPress = acpi SleepButtonPress;2798 s->IACPIPort.pfnPowerButtonPress = acpiPo werButtonPress;2799 s->IACPIPort.pfnGetPowerButtonHandled = acpi GetPowerButtonHandled;2800 s->IACPIPort.pfnGetGuestEnteredACPIMode = acpi GetGuestEnteredACPIMode;2801 s->IACPIPort.pfnGetCpuStatus = acpi GetCpuStatus;2988 s->IACPIPort.pfnSleepButtonPress = acpiPort_SleepButtonPress; 2989 s->IACPIPort.pfnPowerButtonPress = acpiPort_PowerButtonPress; 2990 s->IACPIPort.pfnGetPowerButtonHandled = acpiPort_GetPowerButtonHandled; 2991 s->IACPIPort.pfnGetGuestEnteredACPIMode = acpiPort_GetGuestEnteredACPIMode; 2992 s->IACPIPort.pfnGetCpuStatus = acpiPort_GetCpuStatus; 2802 2993 2803 2994 VMCPUSET_EMPTY(&s->CpuSetAttached); … … 2887 3078 #undef R 2888 3079 2889 rc = PDMDevHlpTMTimerCreate(pDevIns, TMCLOCK_VIRTUAL_SYNC, acpi Timer, dev,2890 TMTIMER_FLAGS_ DEFAULT_CRIT_SECT, "ACPI Timer", &s->tsR3);3080 rc = PDMDevHlpTMTimerCreate(pDevIns, TMCLOCK_VIRTUAL_SYNC, acpiPmTimer, dev, 3081 TMTIMER_FLAGS_NO_CRIT_SECT, "ACPI PM Timer", &s->pPmTimerR3); 2891 3082 if (RT_FAILURE(rc)) 2892 3083 { … … 2895 3086 } 2896 3087 2897 s-> tsR0 = TMTimerR0Ptr(s->tsR3);2898 s-> tsRC = TMTimerRCPtr(s->tsR3);2899 s->u64PmTimerInitial = TMTimerGet(s-> tsR3);2900 acpiP MTimerReset(s);3088 s->pPmTimerR0 = TMTimerR0Ptr(s->pPmTimerR3); 3089 s->pPmTimerRC = TMTimerRCPtr(s->pPmTimerR3); 3090 s->u64PmTimerInitial = TMTimerGet(s->pPmTimerR3); 3091 acpiPmTimerReset(s, s->u64PmTimerInitial); 2901 3092 2902 3093 PCIDevSetVendorId(dev, 0x8086); /* Intel */ -
trunk/src/VBox/Devices/testcase/tstDeviceStructSizeRC.cpp
r37430 r37444 481 481 GEN_CHECK_OFF(ACPIState, pm1a_ctl); 482 482 GEN_CHECK_OFF(ACPIState, u64PmTimerInitial); 483 GEN_CHECK_OFF(ACPIState, tsR3);484 GEN_CHECK_OFF(ACPIState, tsR0);485 GEN_CHECK_OFF(ACPIState, tsRC);483 GEN_CHECK_OFF(ACPIState, pPmTimerR3); 484 GEN_CHECK_OFF(ACPIState, pPmTimerR0); 485 GEN_CHECK_OFF(ACPIState, pPmTimerRC); 486 486 GEN_CHECK_OFF(ACPIState, gpe0_en); 487 487 GEN_CHECK_OFF(ACPIState, gpe0_sts);
Note:
See TracChangeset
for help on using the changeset viewer.