; CPUINFO - the maximum temperature of the CPU: TjMax of Intel with the ; digital sensor as Linux coretemp finds it, the limit of the hardware ; thermal control of AMD 10h to 16h as Linux k10temp tells it. The other ; CPUs do not tell it; the current temperature is for TASKMAN. ; ==================================================================== MSR_TEMP_TARGET = 0x1A2 ; TjMax in bits 23..16 MSR_PLATFORM_ID = 0x17 ; Core 2: the platform in bits 52..50 PLATFORM_MOBILE = 1 shl 28 ; in it, before Penryn MSR_EE = 0xEE ; Core, Core 2 EE_TJMAX = 1 shl 30 ; in it: TjMax tjmax_ee TJMAX = 100 ; Intel, if nothing tells it ; PCI on bus 0 for pci_read: the device shl 3 + the function, shl 8 PCI_HOST = 0 ; 00:00.0, the host bridge PCI_18_3 = ((0x18 shl 3) + 3) shl 8 ; the northbridge of AMD VENDOR_AMD = 0x1022 VENDOR_HYGON = 0x1D94 HTC = PCI_18_3 + 0x64 ; 10h to 16h: the hardware thermal control HTC_ENABLE = 1 shl 0 ; in it; its limit in bits 22..16, HTC_LIMIT_ZERO = 52 ; half degrees over this SMN_F15_INDEX = PCI_HOST + 0xB8 ; 15h from model 60h: SMN, the data at + 4 SMN_F15_HTC = 0xD8200C64 ; its HTC there struct CPU_TJMAX CPU_IDS ; CPU_IDS, then TjMax tjmax db ? ends ; ==================================================================== ; max_temp: the maximum temperature of the CPU, 0 if it does not tell it temp_init: mov esi, .cpus call cpu_handle ; also the end of the procedures below, their CF kept .done: ret ; the procedure of the maximum: the first row for the CPU .cpus: ; vendors family model stepping procedure CPU_HANDLER BY_INTEL, 6, 6, 0xE, 0xE, 0, 0xF, .core ; Yonah CPU_HANDLER BY_INTEL, 6, 6, 0xF, 0xF, 0, 3, .intel ; Merom before stepping 4: no MSR_EE CPU_HANDLER BY_INTEL, 6, 6, 0xF, 0x16, 0, 0xF, .merom CPU_HANDLER BY_INTEL, 6, 6, 0x17, 0x17, 0, 0xF, .penryn CPU_HANDLER BY_INTEL, 6, 6, 0x1C, 0x1C, 0, 0xF, .atom ; Diamondville, Pineview CPU_HANDLER BY_INTEL, 6, 6, 0x1D, 0x1D, 0, 0xF, .core ; Xeon 7400 Dunnington CPU_HANDLER BY_INTEL, 6, 6, 0x1A, 0xFF, 0, 0xF, .nehalem ; from Nehalem CPU_HANDLER BY_INTEL, 0x12, 0xFF, 0, 0xFF, 0, 0xF, .nehalem ; from Nova Lake, Diamond Rapids CPU_HANDLER BY_INTEL, 0, 0xFF, 0, 0xFF, 0, 0xF, .intel CPU_HANDLER BY_AMD + BY_HYGON, 0x15, 0x15, 0x60, 0xFF, 0, 0xF, .htc_smn CPU_HANDLER BY_AMD + BY_HYGON, 0x10, 0x16, 0, 0xFF, 0, 0xF, .htc dw 0 ; the end ; Intel with the digital sensor of the leaf 6: TjMax; out: CF = 1 ; without it .intel: mov eax, 6 call cpuid_leaf0 test al, LEAF6_DTS jz .none mov [max_temp], TJMAX clc ret .none: stc ret ; from Nehalem: TjMax from the CPU, of the older cores from ; pre_nehalem_tjmax; out: CF = 1 without the sensor .nehalem: call .intel jc .done mov esi, pre_nehalem_tjmax mov ebx, sizeof.CPU_TJMAX call cpu_find jc .tjmax movzx eax, [esi + CPU_TJMAX.tjmax] mov [max_temp], eax clc ret ; TjMax in TEMPERATURE_TARGET if it has one, else TJMAX .tjmax: mov edx, MSR_TEMP_TARGET call msr_read jc .sensor shr eax, 16 and eax, 0xFF jz .sensor mov [max_temp], eax .sensor: clc ret ; Atom Diamondville and Pineview: TjMax as from Nehalem, of Atom 230 ; and 330 by name, as in Linux coretemp .atom: call .nehalem jc .done mov esi, atom_tjmax call brand_value test eax, eax jz .done mov [max_temp], eax ret ; Core and Core 2 without TEMPERATURE_TARGET, as in Linux coretemp: ; TjMax tjmax_ee with EE_TJMAX, else TJMAX; MSR_EE on Merom only ; if it is mobile; mobile Penryn (the platform 5 or 7): 90 with ; EE_TJMAX, else 105 .merom: call .intel jc .done mov edx, MSR_PLATFORM_ID call msr_read jc .done test eax, PLATFORM_MOBILE jz .done jmp .ee .penryn: call .intel jc .done mov edx, MSR_PLATFORM_ID call msr_read jc .ee ; all zeros: the platform 0 shr edx, 50 - 32 and edx, 7 cmp edx, 5 je .penryn_mobile cmp edx, 7 jne .ee .penryn_mobile: mov [max_temp], 105 mov [tjmax_ee], 90 jmp .ee .core: call .intel jc .done .ee: mov edx, MSR_EE call msr_read jc .done test eax, EE_TJMAX jz .done mov eax, [tjmax_ee] mov [max_temp], eax ret ; 10h to 16h: the limit of the hardware thermal control if it is ; on, as the critical temperature of Linux k10temp; a half degree ; down. 15h from model 60h has it in SMN. .htc_smn: movi ecx, PCI_HOST call pci_amd jc .done mcall SF_PCI, SSF_WRITE_DWORD, SMN_F15_INDEX, SMN_F15_HTC mov ecx, SMN_F15_INDEX + 4 call pci_read jmp .htc_limit .htc: mov ecx, PCI_18_3 call pci_amd jc .done mov ecx, HTC call pci_read ; eax = HTC .htc_limit: test eax, HTC_ENABLE jz .done shr eax, 16 and eax, 0x7F shr eax, 1 add eax, HTC_LIMIT_ZERO mov [max_temp], eax ret ; the models from Nehalem's 1Ah on with an older core, without its ; TEMPERATURE_TARGET: the Atoms before Silvermont; their TjMax as in Linux ; coretemp pre_nehalem_tjmax: ; vendors family model stepping TjMax CPU_TJMAX BY_INTEL, 6, 6, 0x1C, 0x1C, 0xA, 0xA, 100 ; Atom Pineview CPU_TJMAX BY_INTEL, 6, 6, 0x1C, 0x1C, 0, 0xF, 90 ; Atom Diamondville CPU_TJMAX BY_INTEL, 6, 6, 0x26, 0x27, 0, 0xF, 90 ; Atom Lincroft, Penwell CPU_TJMAX BY_INTEL, 6, 6, 0x35, 0x35, 0, 0xF, 90 ; Atom Cloverview CPU_TJMAX BY_INTEL, 6, 6, 0x36, 0x36, 0, 0xF, 100 ; Atom Cedarview dw 0 ; the end ; the Atoms with their own TjMax by a part of the name, as in Linux ; coretemp; the names have their runs of spaces squeezed atom_tjmax: db 100, "cpu 230", 0 db 125, "cpu 330", 0 db 0 ; ecx = the device on bus 0, PCI_...; out: CF = 1 if it is not of AMD or ; Hygon; changes eax, ebx pci_amd: call pci_read cmp ax, VENDOR_AMD je .ours cmp ax, VENDOR_HYGON je .ours stc ret .ours: clc ret ; ecx = device shl 8 + register (PCI_...); bus 0: bh = 0 in ebx = ; SSF_READ_DWORD; out: eax; changes ebx pci_read: mcall SF_PCI, SSF_READ_DWORD ret ; ==================================================================== align 4 tjmax_ee dd 85 ; Core, Core 2: with EE_TJMAX uglobal align 4 max_temp dd ? ; degrees, 0: unknown endg