; ; Copyright (c) 2006-2008 Advanced Micro Devices,Inc. ("AMD"). ; ; This library is free software; you can redistribute it and/or modify ; it under the terms of the GNU Lesser General Public License as ; published by the Free Software Foundation; either version 2.1 of the ; License, or (at your option) any later version. ; ; This code is distributed in the hope that it will be useful, ; but WITHOUT ANY WARRANTY; without even the implied warranty of ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ; Lesser General Public License for more details. ; ; You should have received a copy of the GNU Lesser General ; Public License along with this library; if not, write to the ; Free Software Foundation, Inc., 59 Temple Place, Suite 330, ; Boston, MA 02111-1307 USA ; ;* Function: * ;* Routines related to MSRs. include VSA2.INC include DESCR.INC .model tiny,c .586p .CODE extern SMM_Header: SmiHeader ;*********************************************************************** ; Returns the high DWORD of an MSR. ; Usage: HighMsrValue = Read_MSR_HI(Msr_Address); ;*********************************************************************** Read_MSR_HI proc pascal \ Msr: dword mov ecx, [Msr] rdmsr mov ax, dx shr edx, 16 ret Read_MSR_HI endp ;*********************************************************************** ; Writes the high DWORD of an MSR. The low DWORD is preserved. ; Usage: Write_MSR_HI(Msr_Address, Data); ;*********************************************************************** Write_MSR_HI proc pascal \ Msr: dword, \ Data: dword mov ecx, [Msr] rdmsr ; Get low 32 bits mov edx, [Data] wrmsr ret Write_MSR_HI endp ;*********************************************************************** ; Returns the low DWORD of an MSR. ; Usage: LowMsrValue = Read_MSR_LO(Msr_Address); ;*********************************************************************** Read_MSR_LO proc pascal \ Msr: dword mov ecx, [Msr] rdmsr mov edx, eax shr edx, 16 ret Read_MSR_LO endp ;*********************************************************************** ; Writes the low DWORD of an MSR. The high DWORD is preserved. ; Usage: Write_MSR_LO(Msr_Address, Data); ;*********************************************************************** Write_MSR_LO proc pascal \ Msr: dword, \ Data: dword mov ecx, [Msr] rdmsr ; Get high 32 bits mov eax, [Data] wrmsr ret Write_MSR_LO endp ;*********************************************************************** ; Returns an MSR value in a buffer. ; Usage: Read_MSR(ULONG Msr, ULONG * Buffer); ;*********************************************************************** Read_MSR proc pascal \ Msr: dword, \ Buffer: PTR mov ecx, [Msr] rdmsr mov bx, [Buffer] mov [bx+0], eax mov [bx+4], edx ret Read_MSR endp ;*********************************************************************** ; Writes an MSR. ; Usage: Write_MSR(ULONG Msr, ULONG * Buffer); ;*********************************************************************** Write_MSR proc pascal \ Msr: dword, \ Buffer: PTR mov ecx, [Msr] mov bx, [Buffer] mov eax, [bx+0] mov edx, [bx+4] wrmsr ret Write_MSR endp ;*********************************************************************** ; Parses MSR_MBIU_CAP of an MBIU and returns descriptor counts in ; a byte buffer. ;*********************************************************************** Parse_Capabilities proc pascal \ Msr: PTR, \ Buffer: PTR mov bx, [Msr] mov eax, [bx+0] ; Get 1st dword of CAPABILITIES mov edx, [bx+4] ; Get 2nd dword of CAPABILITIES mov bx, [Buffer] mov cl, 6 ; Number of P2D descriptors NxtCount: mov ch, al and ch, 3Fh ; 6 bits per field mov [bx], ch inc bx shrd eax, edx, 6 ; Shift next field into LSBs shr edx, 6 dec cl jnz NxtCount mov ch, al ; Get NIOD_BM and ch, 3Fh mov [bx+1], ch shr eax, 6 ; Get NIOD_SC mov ch, al and ch, 3Fh mov [bx+2], ch shr eax, 9 ; Skip NCOH field mov ch, al and ch, 07h ; Get NPORTS mov [bx+3], ch shr ax, 9 ; Get NSTAT_CNT and al, 07h mov [bx+4], al ret Parse_Capabilities endp ;*********************************************************************** ; Extract the 3 main fields from a P2D descriptor ;*********************************************************************** Parse_Descriptor proc pascal uses edi \ P2D_Type: byte, \ Source: ptr, \ Dest: ptr mov bx, [Source] mov ecx, [bx] ; Get low MSR mov eax, ecx mov edx, [bx+4] ; Get high MSR cmp bl, IOD_BM je Descr_IO_BM shl ecx, 12 ; Extract 1st field shrd eax, edx, 20 ; Extract 2nd field shl eax, 12 xor dl, dl ; Extract 3rd field shl edx, 12-8 mov edi, edx ; EDI = Offset mov bl, [P2D_Type] ; Dispatch to correct descriptor parser cmp bl, P2D_BM je Descr_BM cmp bl, P2D_BMO je Descr_BMO cmp bl, P2D_BMK je Descr_BMK cmp bl, P2D_R je Descr_R cmp bl, P2D_RO je Descr_RO jmp Exit Descr_IO_BM: and ecx, 000FFFFFh ; ECX = IMASK shrd eax, edx, 20 ; EAX = IBASE xor edi, edi ; EDI = 00000000 Descr_BMO: ; Assume OFFSET == 0 Descr_BM: Descr_BMK: ; ECX = PMASK ; EAX = PBASE and eax, ecx ; Start = PBASE & PMASK mov edx, eax ; End = Start + ~PMASK not ecx add edx, ecx jmp StoreResult Descr_RO: ; Assume OFFSET == 0 Descr_R: ; ECX = PMIN ; EAX = PMAX xchg eax, ecx ; Start = PMIN mov edx, ecx ; End = PMAX or dx, 0FFFh StoreResult: mov bx, [Dest] mov [bx], eax ; Start mov [bx+4], edx ; End add edi, eax ; Physical = Start + Offset mov [bx+8], edi Exit: ret Parse_Descriptor endp ;*********************************************************************** ;*********************************************************************** MergeFields proc pascal \ Dest: PTR, \ Field1: DWORD, \ Field2: DWORD, \ Field3: DWORD mov bx, [Dest] ;// Descr->MsrData[0] = (PBase << 20) | (PMask & 0xFFFFF); ;// Descr->MsrData[1] = (PBase >> 12) | (POffset << 8); mov eax, [Field2] mov edx, eax shl eax, 20 mov ecx, [Field1] and ecx, 0FFFFFh or eax, ecx mov [bx], eax shr edx, 12 mov eax, [Field3] shl eax, 8 or eax, edx mov [bx+4], eax ret MergeFields endp ;*********************************************************************** ; Returns TRUE if Range is a power of 2 ;*********************************************************************** IsPowerOfTwo proc pascal \ Range: dword mov ebx, [Range] bsf eax, ebx ; Scan LSB to MSB bsr edx, ebx ; Scan MSB to LSB cmp al, dl ; Same bit found ? mov al, 0 ; No, return FALSE jne Exit mov al, 1 ; else return TRUE Exit: ret IsPowerOfTwo endp ;*********************************************************************** ; Returns index of first bit set when scanning from MSB to LSB ;*********************************************************************** BitScanReverse proc pascal \ Range: dword mov ebx, [Range] bsr eax, ebx ; Scan MSB to LSB ret BitScanReverse endp ;*********************************************************************** ; Returns index of first bit set when scanning from LSB to MSB ;*********************************************************************** BitScanForward proc pascal \ Range: dword mov ebx, [Range] bsf eax, ebx ; Scan LSB to MSB ret BitScanForward endp end