summaryrefslogtreecommitdiffstats
path: root/src/build/debug/Hostboot
diff options
context:
space:
mode:
authorMissy Connell <missyc@us.ibm.com>2012-06-14 15:30:05 -0500
committerA. Patrick Williams III <iawillia@us.ibm.com>2012-07-12 11:48:41 -0500
commit994ed56575ca157296750f5e2c8153471c2253af (patch)
tree3d08c3bbb848e83214eced13f60efdf2e5742523 /src/build/debug/Hostboot
parent4bf57814b214bd8d2d730d27955898b1f9cd1e43 (diff)
downloadblackbird-hostboot-994ed56575ca157296750f5e2c8153471c2253af.tar.gz
blackbird-hostboot-994ed56575ca157296750f5e2c8153471c2253af.zip
VMM tools support
Added Support for the following Debug VMM tools: VirtToPhys - given a virtual address will return physical addr There are options to get more debug info or display the SPTE PrintVMM - prints out all segments,and their blocks Change-Id: I9fb150804c91489e3c5d2ae2bfa129d534f198ba RTC: 35306 Reviewed-on: http://gfw160.austin.ibm.com:8080/gerrit/1217 Tested-by: Jenkins Server Reviewed-by: Daniel M. Crowell <dcrowell@us.ibm.com> Reviewed-by: A. Patrick Williams III <iawillia@us.ibm.com>
Diffstat (limited to 'src/build/debug/Hostboot')
-rw-r--r--src/build/debug/Hostboot/PrintVMM.pm167
-rw-r--r--src/build/debug/Hostboot/VirtToPhys.pm87
-rwxr-xr-xsrc/build/debug/Hostboot/_DebugFrameworkVMM.pm912
3 files changed, 1166 insertions, 0 deletions
diff --git a/src/build/debug/Hostboot/PrintVMM.pm b/src/build/debug/Hostboot/PrintVMM.pm
new file mode 100644
index 000000000..fcb3a2230
--- /dev/null
+++ b/src/build/debug/Hostboot/PrintVMM.pm
@@ -0,0 +1,167 @@
+# IBM_PROLOG_BEGIN_TAG
+# This is an automatically generated prolog.
+#
+# $Source: src/build/debug/Hostboot/PrintVMM.pm $
+#
+# IBM CONFIDENTIAL
+#
+# COPYRIGHT International Business Machines Corp. 2012
+#
+# p1
+#
+# Object Code Only (OCO) source materials
+# Licensed Internal Code Source Materials
+# IBM HostBoot Licensed Internal Code
+#
+# The source code for this program is not published or other-
+# wise divested of its trade secrets, irrespective of what has
+# been deposited with the U.S. Copyright Office.
+#
+# Origin: 30
+#
+# IBM_PROLOG_END_TAGuse strict;
+
+use strict;
+use Hostboot::_DebugFrameworkVMM;
+package Hostboot::PrintVMM;
+use Exporter;
+use integer;
+our @EXPORT_OK = ('main');
+
+
+
+sub main
+{
+ ::userDisplay "PrintVMM module.\n";
+
+ my ($packName,$args) = @_;
+
+ my $phyAddr = Hostboot::_DebugFrameworkVMM::NotFound;
+ my $debug = 0;
+ my $displaySPTE = 0;
+ my $displayAll = 1;
+ my $displayBase = 0;
+ my $displayStack = 0;
+ my $displayDevice = 0;
+
+ if (defined $args->{"debug"})
+ {
+ $debug = 1;
+ }
+
+ if (defined $args->{"base"})
+ {
+ $displayBase = 1;
+ $displayAll = 0;
+ }
+
+ if (defined $args->{"stack"})
+ {
+ $displayStack = 1;
+ $displayAll = 0;
+ }
+
+ if (defined $args->{"device"})
+ {
+ $displayDevice = 1;
+ $displayAll = 0;
+ }
+
+ # Get the device segment address
+ my @segment_manager_addr =
+ ::findSymbolAddress("Singleton<SegmentManager>::instance()::instance");
+
+ if (not defined @segment_manager_addr)
+ {
+ ::userDisplay " VirtualToPhy: Cannot find Device Segment symbol.\n"; die;
+ }
+
+ my $baseSegmentPtr =
+ ::read64 ($segment_manager_addr[0] +
+ Hostboot::_DebugFrameworkVMM::SEGMGR_BASE_SEGMENT_OFFSET, 8);
+
+ my $StackSegmentPtr =
+ ::read64 ($segment_manager_addr[0] +
+ Hostboot::_DebugFrameworkVMM::SEGMGR_STACK_SEGMENT_OFFSET, 8);
+
+ my $DeviceSegmentPtr =
+ ::read64 ($segment_manager_addr[0] +
+ Hostboot::_DebugFrameworkVMM::SEGMGR_FIRSTDEVICE_SEGMENT_OFFSET, 8);
+
+ if (($displayBase) || ($displayAll))
+ {
+ ::userDisplay "\n-------------\n";
+ ::userDisplay "BASE SEGMENT\n";
+ ::userDisplay "-------------\n";
+
+
+ if ($baseSegmentPtr == 0)
+ {
+ ::userDisplay " PrintVMM: No Segment Pointer. Have you run yet?\n"; die;
+ }
+
+ Hostboot::_DebugFrameworkVMM::printBaseSegment($baseSegmentPtr);
+ }
+
+ if (($displayStack) || ($displayAll))
+ {
+
+ ::userDisplay "\n-------------\n";
+ ::userDisplay "STACK SEGMENT\n";
+ ::userDisplay "-------------\n";
+
+ if ($StackSegmentPtr == 0)
+ {
+ ::userDisplay " PrintVMM: No Segment Pointer. Have you run yet?\n"; die;
+ }
+
+ my $StackSegBaseAddr = ::read64($StackSegmentPtr +
+ Hostboot::_DebugFrameworkVMM::STACKSEGMENT_BASEADDR_OFFSET, 8);
+
+ ::userDisplay (sprintf " Stack Segment base addr=%X\n" , $StackSegBaseAddr);
+
+ my $firststackptr = ::read64 ($StackSegmentPtr +
+ Hostboot::_DebugFrameworkVMM::STACKSEGMENT_FIRST_STACK_OFFSET, 8);
+
+ Hostboot::_DebugFrameworkVMM::printStackSegment($firststackptr);
+
+ }
+
+ if (($displayDevice) || ($displayAll))
+ {
+
+ ::userDisplay "\n---------------\n";
+ ::userDisplay "DEVICE SEGMENTS\n";
+ ::userDisplay "---------------\n";
+
+ if ($DeviceSegmentPtr == 0)
+ {
+ ::userDisplay " PrintVMM: No Segment Pointer. Have you run yet?\n"; die;
+ }
+ #Pass in address of the pointer to the first device segment in the segment manager
+ # This routine will loop through all possible device semgnets and print their info.
+ Hostboot::_DebugFrameworkVMM::printDeviceSegments($segment_manager_addr[0] +
+ Hostboot::_DebugFrameworkVMM::SEGMGR_FIRSTDEVICE_SEGMENT_OFFSET);
+
+
+ }
+
+ return 0;
+}
+
+
+
+sub helpInfo
+{
+ my %info = (
+ name => "PrintVMM",
+ intro => ["Print out the VMM mapping. "],
+ options => {
+ "debug" => ["More debug output."],
+ "base" => ["Prints out BASE segment info."],
+ "stack" => ["Prints out STACK segment info."],
+ "device" => ["Prints out Device segment info."],
+ },
+
+ );
+}
diff --git a/src/build/debug/Hostboot/VirtToPhys.pm b/src/build/debug/Hostboot/VirtToPhys.pm
new file mode 100644
index 000000000..8a55c53d5
--- /dev/null
+++ b/src/build/debug/Hostboot/VirtToPhys.pm
@@ -0,0 +1,87 @@
+ # IBM_PROLOG_BEGIN_TAG
+ # This is an automatically generated prolog.
+ #
+ # $Source: src/build/debug/Hostboot/VirtToPhys.pm $
+ #
+ # IBM CONFIDENTIAL
+ #
+ # COPYRIGHT International Business Machines Corp. 2012
+ #
+ # p1
+ #
+ # Object Code Only (OCO) source materials
+ # Licensed Internal Code Source Materials
+ # IBM HostBoot Licensed Internal Code
+ #
+ # The source code for this program is not published or other-
+ # wise divested of its trade secrets, irrespective of what has
+ # been deposited with the U.S. Copyright Office.
+ #
+ # Origin: 30
+ #
+ # IBM_PROLOG_END_TAG
+ #
+
+use strict;
+use Hostboot::_DebugFrameworkVMM;
+package Hostboot::VirtToPhys;
+use Exporter;
+use integer;
+our @EXPORT_OK = ('main');
+
+
+
+sub main
+{
+ #::userDisplay "VirtToPhys module.\n";
+
+ my ($packName,$args) = @_;
+
+ my $phyAddr = Hostboot::_DebugFrameworkVMM::NotFound;
+ my $debug = 0;
+ my $displaySPTE = 0;
+
+ if (defined $args->{"debug"})
+ {
+ $debug = 1;
+ }
+
+
+ if (defined $args->{"showSPTE"})
+ {
+ $displaySPTE = 1;
+ }
+
+ # Parse 'vaddr' argument.
+ if (not defined $args->{"vaddr"})
+ {
+ ::userDisplay "ERROR.. Did not pass in Virtual Address.\n";
+ die;
+ }
+
+ my $vaddr = hex($args->{"vaddr"});
+
+ if ($debug)
+ {
+ ::userDisplay (sprintf "\n Virtual Address = %X\n" , $vaddr);
+ }
+
+ $phyAddr = Hostboot::_DebugFrameworkVMM::getPhysicalAddr($vaddr, $debug, $displaySPTE);
+
+ return $phyAddr;
+}
+
+
+sub helpInfo
+{
+ my %info = (
+ name => "VirtToPhys",
+ intro => ["Take a virtual address and return its physical address"],
+ options => {
+ "vaddr=<number>" => ["Virtual Address "],
+ "debug" => ["More debug output."],
+ "displaySPTE" => ["Display the SPTE for the VA passed in"],
+ },
+
+ );
+}
diff --git a/src/build/debug/Hostboot/_DebugFrameworkVMM.pm b/src/build/debug/Hostboot/_DebugFrameworkVMM.pm
new file mode 100755
index 000000000..f8fb15488
--- /dev/null
+++ b/src/build/debug/Hostboot/_DebugFrameworkVMM.pm
@@ -0,0 +1,912 @@
+#!/usr/bin/perl
+# IBM_PROLOG_BEGIN_TAG
+# This is an automatically generated prolog.
+#
+# $Source: src/build/debug/Hostboot/_DebugFrameworkVMM.pm $
+#
+# IBM CONFIDENTIAL
+#
+# COPYRIGHT International Business Machines Corp. 2011-2012
+#
+# p1
+#
+# Object Code Only (OCO) source materials
+# Licensed Internal Code Source Materials
+# IBM HostBoot Licensed Internal Code
+#
+# The source code for this program is not published or other-
+# wise divested of its trade secrets, irrespective of what has
+# been deposited with the U.S. Copyright Office.
+#
+# Origin: 30
+#
+# IBM_PROLOG_END_TAG
+# _DebugFrameworkVMM.pm
+#
+# This module is a set of utility functions for the debug framework, which
+# should be common across all debug framework environments.
+#
+# The module provides the functions listed below in @EXPORT.
+#
+# A debug framework environment is expected to implement the following
+# functions:
+# * getIsTest() - Is the image loaded a test image or normal?
+# * getImgPath() - Path to the .../img/ directory containing debug files.
+# * readData(addr,size) - Read a blob of memory.
+# * userDisplay(varargs-of-mixed) - Display things to the user.
+#
+
+use strict;
+use integer;
+
+
+package Hostboot::_DebugFrameworkVMM;
+use Exporter 'import';
+
+our @EXPORT = (
+ 'displaySPTE',
+ 'getPhysicalAddr',
+ 'printBaseSegment',
+ 'printStackSegment',
+ 'printDeviceSegments'
+ );
+
+
+use constant NotFound => 'not found';
+use constant NotPresent => 'not present';
+
+use constant SEGMGR_BASE_SEGMENT_OFFSET => 0;
+use constant SEGMGR_STACK_SEGMENT_OFFSET => 8;
+use constant SEGMGR_FIRSTDEVICE_SEGMENT_OFFSET => 16;
+
+use constant BASESEGMENT_BASEADDR_OFFSET => 8;
+use constant BASESEGMENT_BLOCK_OFFSET => 16;
+use constant BASESEGMENT_PHY_SIZE_OFFSET => 24;
+
+use constant STACKSEGMENT_BASEADDR_OFFSET => 8;
+use constant STACKSEGMENT_FIRST_STACK_OFFSET => 16;
+
+use constant DEVICESEGMENT_BASEADDR_OFFSET => 8;
+use constant DEVICESEGMENT_BLOCK_OFFSET => 16;
+use constant DEVICESEGMENT_BLOCK_SIZE => 24;
+
+use constant STACK_NEXT_STACK_OFFSET => 0;
+use constant STACK_PREV_STACK_OFFEST => 8;
+use constant STACK_KEY_OFFSET => 16;
+use constant STACK_BLOCKPTR_OFFSET => 24;
+
+use constant MMIO_STRUCT_SEGADDR_OFFSET => 0;
+use constant MMIO_STRUCT_SEGSIZE_OFFSET => 8;
+
+use constant BLOCK_BASE_ADDR => 0;
+use constant BLOCK_SIZE_OFFSET => 8;
+use constant BLOCK_PARENT_SEGMENTPTR_OFFSET => 16;
+use constant BLOCK_NEXTPTR_OFFSET => 24;
+use constant BLOCK_SPTE_OFFSET => 32;
+
+
+
+our @EXPORT_OK = ('NotFound');
+our @EXPORT_OK = ('NotPresent');
+our @EXPORT_OK = ('SEGMGR_BASE_SEGMENT_OFFSET',
+ 'SEGMGR_STACK_SEGMENT_OFFSET',
+ 'SEGMGR_FIRSTDEVICE_SEGMENT_OFFSET',
+ 'STACKSEGMENT_BASEADDR_OFFSET',
+ 'STACKSEGMENT_FIRST_STACK_OFFSET',
+ );
+
+
+# @sub displaySPTE
+#
+# Display in PSTE entry info
+#
+# @param Address of the SPTE entry
+#
+sub displaySPTE
+{
+ my $vaddr = shift;
+ my $SPTE_entry = shift;
+
+ my $SPTEaddr = $SPTE_entry & 0xFFFFF000;
+
+ ::userDisplay"\n===================================================\n";
+ ::userDisplay (sprintf "SPTE Entry for VirtualAddr=%X\n" , $vaddr);
+ ::userDisplay (sprintf " Starting Physical Addr of the page =: %X\n"
+ , $SPTEaddr);
+
+ ::userDisplay (sprintf " present = %X\n" , ($SPTE_entry &
+ 0x00000800) >>
+ 11 );
+
+ ::userDisplay (sprintf " readable = %X\n" , ($SPTE_entry &
+ 0x00000400) >>
+ 10 );
+
+ ::userDisplay (sprintf " writable = %X\n" , ($SPTE_entry &
+ 0x00000200) >>
+ 9 );
+
+ ::userDisplay (sprintf " executable= %X\n" , ($SPTE_entry &
+ 0x00000100) >>
+ 8 );
+
+ ::userDisplay (sprintf " trackWrite= %X\n" , ($SPTE_entry &
+ 0x00000080) >>
+ 7 );
+
+ ::userDisplay (sprintf " dirty = %X\n" , ($SPTE_entry &
+ 0x00000040) >>
+ 6 );
+
+ ::userDisplay (sprintf " AllocateFromZero=%X\n" , ($SPTE_entry &
+ 0x00000020) >>
+ 5 );
+
+ ::userDisplay (sprintf " last Access= %X\n" , ($SPTE_entry &
+ 0x0000001C) >>
+ 2 );
+
+ ::userDisplay"===================================================\n";
+
+}
+
+
+# @sub findBlock
+#
+# Given a block and an address, find the block the address
+# is part of.
+#
+# @param Ptr to the first block
+# @param address we are looking for
+# @param debug variable to indicate debug mode
+# @return Ptr to block
+#
+sub findBlock
+{
+
+ my $block_ptr = shift;
+ my $vaddr = shift;
+ my $debug = shift;
+ my $block_found = 0;
+
+ while (($block_ptr != 0) && ($block_found == 0))
+ {
+ #Get the base address of the block
+ my $block_base_addr = ::read64 ($block_ptr + BLOCK_BASE_ADDR, 8);
+
+ #Get the size of the block
+ my $block_size = ::read64 ($block_ptr + BLOCK_SIZE_OFFSET, 8);
+
+ # check that va is in the block range
+ if (($vaddr <= $block_base_addr + $block_size) &&
+ ($vaddr >= $block_base_addr))
+ {
+ $block_found = 1;
+ }
+
+ my $next_block_ptr = ::read64 ($block_ptr + BLOCK_NEXTPTR_OFFSET, 8);
+
+ #::userDisplay (sprintf " findBlock:: Next block ptr: %X\n\n" ,
+ # $next_block_ptr);
+
+
+ if ($block_found == 0)
+ {
+ $block_ptr = $next_block_ptr;
+ }
+ else
+ {
+ if ($debug)
+ {
+ #::userDisplay " findBlock: found a matching block \n";
+ #::userDisplay (sprintf " findblock - vaddr= %X\n" , $vaddr);
+ ::userDisplay (sprintf " Block ptr: %X\n" , $block_ptr);
+ ::userDisplay (sprintf " Found block base addr =%X\n" ,
+ $block_base_addr);
+ ::userDisplay (sprintf " Found block block size=%X\n" ,
+ $block_size);
+
+ }
+ }
+ }
+
+return $block_ptr;
+}
+
+
+# @sub findStack
+#
+# Given a Stack ptr from a list of stack and an address,
+# find which stack this address is part of
+#
+# @param Ptr to the first stack entry
+# @param address we are looking for
+# @param debug var to indicate debug mode (1 = debug on)
+# @return Ptr to stack
+#
+sub findStack
+{
+ my $stackptr = shift;
+ my $vaddr = shift;
+ my $debug = shift;
+ my $found = 0;
+
+ # the stack key
+ my $Megabyte = 1024*1024;
+
+ my $stackkey = $vaddr & ~((8 * $Megabyte) - 1);
+
+
+ do
+ {
+ #if ($debug)
+ #{
+ # ::userDisplay (sprintf "\n findStack: Stack Pointer =%X\n" ,
+ # $stackptr);
+ # ::userDisplay (sprintf
+ # " findStack: stackkey we are looking for: %X\n" , $stackkey);
+
+ # ::userDisplay (sprintf " findStack: stackKey in Memory=%X\n" ,
+ # ::read64 ($stackptr + 16, 8));
+ #}
+
+ if (::read64 ($stackptr + STACK_KEY_OFFSET, 8) == $stackkey)
+ {
+ $found = 1;
+
+ if ($debug)
+ {
+ ::userDisplay (sprintf "\n Stack Pointer=%X\n" , $stackptr);
+ }
+ }
+ else
+ {
+ # Get the next stack pointer..
+ $stackptr = ::read64 ($stackptr + STACK_NEXT_STACK_OFFSET, 8);
+ }
+
+ }while((!$found) && ($stackptr != 0));
+
+ if (!$found)
+ {
+ if ($debug)
+ {
+ ::userDisplay
+ (sprintf" findStack: Did not find a stack entry for v addr: %X\n" , $vaddr);
+ }
+
+ $stackptr = 0;
+ }
+
+return $stackptr
+}
+
+
+
+# @sub getPhyAddrfromSPTE
+#
+# Find the SPTE for that vaddr and return the physical addr
+#
+# @param Address of the SPTE entry
+# @param address we are looking for
+# @param debug var to indicate debug mode (1 = debug on)
+# @return physical address
+#
+sub getPhyAddrfromSPTE
+{
+ my $block_ptr = shift;
+ my $vaddr = shift;
+ my $debug = shift;
+ my $displaySPTE = shift;
+
+ my $paddr = NotFound;
+
+ my $SPTE_ptr = ::read64 ($block_ptr + BLOCK_SPTE_OFFSET, 8);
+
+ #Get the base address of the block
+ my $block_base_addr = ::read64 ($block_ptr + BLOCK_BASE_ADDR, 8);
+
+ my $index = ($vaddr - $block_base_addr)/4096;
+
+ my $spteindex = $index*4;
+
+ my $SPTE_entry = ::read32 ($SPTE_ptr + $spteindex, 4);
+
+ if ($debug)
+ {
+ ::userDisplay (sprintf " The SPTE ptr is: %X\n" , $SPTE_ptr);
+ #::userDisplay (sprintf
+ #" getPhyAddrfromSPTE: The index is: %X\n\n" ,$index);
+
+ #::userDisplay (sprintf
+ #" getPhyAddrfromSPTE: The SPTE index is: %X\n\n" , $spteindex);
+
+ ::userDisplay (sprintf " The SPTE entry contents is: %X\n" ,
+ $SPTE_entry);
+ }
+
+ # if found present
+ if ($SPTE_entry & 0x00000800)
+ {
+ my $addrmask = 0xFFFFF000;
+
+ my $SPTEaddr = $SPTE_entry & $addrmask;
+
+ my $addrOffset = ($vaddr - $block_base_addr)%4096;
+
+ $paddr = $SPTEaddr + $addrOffset;
+
+ }
+ else
+ {
+ $paddr = NotPresent;
+ }
+
+ if ($displaySPTE)
+ {
+ Hostboot::_DebugFrameworkVMM::displaySPTE($vaddr, $SPTE_entry);
+ }
+
+
+ return $paddr;
+
+}
+
+
+# @sub getPhysicalAddr
+#
+# Find the physical address in the VMM from a VA passed in.
+#
+# @param address we are looking for
+# @param debug var to indicate debug mode (1 = debug on)
+# @return physical address
+#
+sub getPhysicalAddr
+{
+ my $vaddr = shift;
+ my $debug = shift;
+ my $displaySPTE = shift;
+
+ my $phyAddr = NotFound;
+
+ # Determine the index into the segment list
+ my $segmentIndex = $vaddr >> 40;
+
+ #if ($debug)
+ #{
+ # ::userDisplay (sprintf " stackIndex = : %X\n" , $segmentIndex);
+ #}
+
+ # Get the device segment address
+ my @segment_manager_addr =
+ ::findSymbolAddress("Singleton<SegmentManager>::instance()::instance");
+
+
+ if (not defined @segment_manager_addr)
+ {
+ ::userDisplay " VirtualToPhy: Cannot find Device Segment symbol.\n";
+ die;
+ }
+
+
+ # if the stack index equal 0..then the address is part of the base segment
+ if ($segmentIndex == 0)
+ {
+ if ($debug)
+ {
+ ::userDisplay" In BASE SEGMENT address range\n\n";
+ }
+
+ my $base_segment_addr = ::read64 ($segment_manager_addr[0], 8);
+
+ my $block_ptr = ::read64 ($base_segment_addr + BASESEGMENT_BLOCK_OFFSET, 8);
+
+
+ # check that we have a valid block pointer..
+ if ($block_ptr != 0)
+ {
+ if ($debug)
+ {
+ ::userDisplay (sprintf " Base Segment symbol address: %X\n"
+ , $base_segment_addr);
+
+ ::userDisplay (sprintf " Base Segment block_ptr: %X\n" ,
+ $block_ptr);
+
+ }
+
+ #Call function to get the correct block for the VA
+ my $block_ptr = Hostboot::_DebugFrameworkVMM::findBlock($block_ptr,
+ $vaddr,
+ $debug);
+
+
+ #if ($debug)
+ #{
+ # ::userDisplay (sprintf " Block ptr: %X\n" , $block_ptr);
+ #}
+
+ if ($block_ptr == 0)
+ {
+ ::userDisplay (sprintf
+ " VirtualToPhy: Did not find a block for v addr: %X\n" , $vaddr);
+
+ die;
+ }
+
+ # get the physical address from SPTE entry in this block
+ # pass the block pointer, Virtual address and debug flag..
+ # if debug is on we print more detail about the entry
+ $phyAddr =
+ Hostboot::_DebugFrameworkVMM::getPhyAddrfromSPTE($block_ptr,
+ $vaddr, $debug,
+ $displaySPTE);
+
+ }
+ else
+ {
+ ::userDisplay
+ " VirtualToPhy: BaseSegment - no valid pointer... Have you run yet?\n\n";
+ die;
+ }
+ }
+ elsif ($segmentIndex == 1)
+ {
+
+ if ($debug)
+ {
+ ::userDisplay" In STACK SEGMENT Range\n\n";
+ }
+
+ my $stack_segment_addr = ::read64 ($segment_manager_addr[0] +
+ SEGMGR_STACK_SEGMENT_OFFSET, 8);
+
+
+ # get the pointer to the first segment..
+ my $firststackptr = ::read64 ($stack_segment_addr +
+ STACKSEGMENT_FIRST_STACK_OFFSET, 8);
+
+
+ if ($firststackptr == 0)
+ {
+ ::userDisplay
+ " VirtualToPhy: No Stack Pointer. Have you run yet?\n"; die;
+
+ }
+
+ if ($debug)
+ {
+ ::userDisplay (sprintf " Segment symbol address=%X\n" ,
+ $stack_segment_addr);
+
+ ::userDisplay (sprintf " Stackheadptr=%X\n" , $firststackptr);
+ }
+
+ my $stackptr = 0;
+
+ #Call function to get the correct block for the VA
+ $stackptr = Hostboot::_DebugFrameworkVMM::findStack($firststackptr,
+ $vaddr, $debug);
+
+
+ if ($stackptr == 0)
+ {
+ ::userDisplay (sprintf
+ " VirtualToPhy:Did not find a stack for v addr: %X\n" , $vaddr);
+
+ die;
+ }
+
+ my $firstblockptr = ::read64 ($stackptr + STACK_BLOCKPTR_OFFSET, 8);
+
+ if ($firstblockptr == 0)
+ {
+ ::userDisplay " No BlockPtr found.\n"; die;
+ }
+
+ #Call function to get the correct block for the VA
+ my $block_ptr = Hostboot::_DebugFrameworkVMM::findBlock($firstblockptr,
+ $vaddr, $debug);
+
+
+ #if ($debug)
+ #{
+ # ::userDisplay (sprintf " Block ptr=%X\n\n" , $block_ptr);
+ #}
+
+ if ($block_ptr == 0)
+ {
+ ::userDisplay (sprintf
+ " VirtualToPhy: Did not find a block for v addr: %X\n" , $vaddr);
+
+ die;
+ }
+
+ # get the physical address from SPTE entry in this block
+ # pass the block pointer, Virtual address and debug flag.. if debug
+ # is on we print more detail about the entry
+ $phyAddr = Hostboot::_DebugFrameworkVMM::getPhyAddrfromSPTE($block_ptr,
+ $vaddr,
+ $debug,
+ $displaySPTE);
+
+ }
+
+ # there are a max number of 16 segments allowed.. But we currently only propogate
+ # 2-10 in the code.. But leaving the full range in here in case that changes.
+ elsif (($segmentIndex > 1) && ($segmentIndex < 16))
+ {
+ if ($debug)
+ {
+ ::userDisplay" In DEVICE SEGMENT Range\n\n";
+ }
+
+ # Get the pointer to the specific device segment
+ my $deviceSegmentPtr = ::read64 ($segment_manager_addr[0] +
+ (8*$segmentIndex), 8);
+
+
+ # check to see that we have a valid segment ptr - if not print error
+ if ($deviceSegmentPtr != 0)
+ {
+ my $segmentbaseaddr = ::read64($deviceSegmentPtr +
+ DEVICESEGMENT_BASEADDR_OFFSET , 8);
+
+
+ my $segment_ea = $vaddr - $segmentbaseaddr;
+
+ my $terabyte = 1024*1024*1024*1024;
+
+ my $idx = $segment_ea / ($terabyte / 32);
+
+ if ($idx < 32)
+ {
+ my $segmentDevBlckAddr =::read64($deviceSegmentPtr +
+ DEVICESEGMENT_BLOCK_OFFSET
+ +(16*$idx), 8);
+
+ my $segmentSize =::read64($deviceSegmentPtr +
+ DEVICESEGMENT_BLOCK_SIZE +(16*$idx),
+ 8);
+
+ if ($debug)
+ {
+
+ ::userDisplay
+ (sprintf" VirtualToPhy: Device Segment base Vaddress=%X\n" , $segmentbaseaddr);
+
+ ::userDisplay (sprintf" segment_EA = %X\n" , $segment_ea);
+ ::userDisplay (sprintf" mmio index = %X\n" , $idx);
+ ::userDisplay
+ (sprintf" VirtualToPhy: Segment DeviceBlock Phy address = %X\n" , $segmentDevBlckAddr);
+
+ ::userDisplay (sprintf " VirtualToPhy: Segment size = %X\n" , $segmentSize);
+ }
+
+ if ($segmentDevBlckAddr != 0)
+ {
+ my $deviceoffset = $segment_ea - ($idx * ($terabyte / 32));
+
+ if ($debug)
+ {
+ ::userDisplay (sprintf " device offset = %X\n" , $deviceoffset);
+ }
+
+ $phyAddr = $segmentDevBlckAddr + $deviceoffset;
+ }
+ else
+ {
+ ::userDisplay (" \n Physical address equals 0\n");
+ }
+ }
+ else
+ {
+ ::userDisplay " Bad index.. address is not right.\n"; die;
+ }
+ }
+ else
+ {
+ ::userDisplay (" \n No valid Device pointers. Have you run yet? \n");
+ }
+ }
+ else
+ {
+ ::userDisplay (" \nVirtualToPhy: ERROR.. VA Address is out of range.\n");
+ }
+
+ if (($phyAddr eq Hostboot::_DebugFrameworkVMM::NotFound) ||
+ ($phyAddr eq Hostboot::_DebugFrameworkVMM::NotPresent))
+ {
+ ::userDisplay ("\n The Physical Address = $phyAddr\n");
+ }
+ else
+ {
+ ::userDisplay (sprintf "\n The Physical Address = %X\n\n" , $phyAddr);
+ }
+
+ return $phyAddr;
+}
+
+
+
+
+# @sub printBaseSegment
+#
+# Print out info on the base segment
+#
+# @param Address of the base segment
+#
+sub printBaseSegment
+{
+ my $base_segment_addr = shift;
+
+ #::userDisplay (sprintf " printBaseSegment: baseAddr: %X\n" ,$base_segment_addr);
+
+ # base segment address is 8 bytes (after Virtual Function Table ptr)
+ my $seg_base_addr =
+ ::read64 $base_segment_addr+BASESEGMENT_BASEADDR_OFFSET;
+
+ my $seg_phys_size =
+ ::read64 ($base_segment_addr + BASESEGMENT_PHY_SIZE_OFFSET, 8);
+
+ ::userDisplay(" Base Segment Info: \n");
+ ::userDisplay (sprintf " Base Address: %X\n" , $seg_base_addr);
+
+ #::userDisplay" isBaseSegment: BaseSegment phys size: $seg_phys_size\n";
+
+ #::userDisplay (sprintf " printBaseSegment: phys size: %X\n" ,$seg_phys_size);
+
+
+ my $blockPtr = ::read64 $base_segment_addr+BASESEGMENT_BLOCK_OFFSET;
+
+ ::userDisplay (sprintf " Block Ptr =: %X\n" , $blockPtr);
+
+ printBlock($blockPtr);
+
+}
+
+# @sub printStackSegment
+#
+# Print out info on the stack segment passed in
+#
+# @param Address of the Stack we need to work with
+#
+sub printStackSegment
+{
+ my $stackptr = shift;
+ my $i = 0;
+
+ #::userDisplay (sprintf " printStackSegment: Base Ptr %X\n" , $stackptr);
+
+ while($stackptr != 0)
+ {
+ ::userDisplay (sprintf "\n StackSegment[%X]\n" , $i);
+
+ ::userDisplay" --------------\n";
+ my $Megabyte = 1024*1024;
+
+ my $localkey = ::read64 ($stackptr + STACK_KEY_OFFSET, 8);
+ ::userDisplay (sprintf " StackKey: %X\n" , $localkey);
+
+ my $taskId = ($localkey - (1024*1024*$Megabyte))/ (8*$Megabyte);
+ ::userDisplay (sprintf " taskId: %X\n" , $taskId);
+
+ my $bottomOffset = (64 + 128 * ($taskId % 61)) * 1024;
+ #::userDisplay (sprintf " bottomOffset: %X\n" , $bottomOffset);
+
+ my $topOffset = $bottomOffset + (256 * 1024) - 8;
+ #::userDisplay (sprintf " topOffset: %X\n" , $topOffset);
+
+ # my $topAddr = $stackkey + $bottomOffset;
+ my $topAddr = $localkey + $topOffset;
+
+ #::userDisplay (sprintf " topAddr: %X\n" , $topAddr);
+
+ ::userDisplay (sprintf " STACK topAddr: %X\n" , $topAddr);
+
+ my $bottomAddr = $localkey + $bottomOffset;
+ ::userDisplay (sprintf " STACK bottomAddr: %X\n" , $bottomAddr);
+
+ # need to print the block information from here too..
+
+ printBlock(::read64 ($stackptr + STACK_BLOCKPTR_OFFSET, 8));
+
+ $stackptr = ::read64 ($stackptr + STACK_NEXT_STACK_OFFSET, 8);
+
+ $i = $i + 1;
+ }
+
+}
+
+
+# @sub printBlock
+#
+# Given a block and an address, find the block the address
+# is part of.
+#
+# @param Ptr to the first block
+# @param address we are looking for
+#
+sub printBlock
+{
+
+ my $block_ptr = shift;
+ my $i = 0;
+
+ while ($block_ptr != 0)
+ {
+ ::userDisplay (sprintf "\n *Block[%X]\n" , $i);
+
+ #Get the base address of the block
+ #my $block_base_addr = ::read64 ($block_ptr, 8);
+
+ ::userDisplay (sprintf " Block Base Address: %X\n" ,::read64
+ ($block_ptr + BLOCK_BASE_ADDR, 8));
+
+
+ ::userDisplay (sprintf " Block Size: %X\n" ,::read64
+ ($block_ptr + BLOCK_SIZE_OFFSET, 8));
+
+
+ my $next_block_ptr = ::read64 ($block_ptr + BLOCK_NEXTPTR_OFFSET, 8);
+
+ #::userDisplay (sprintf " Next Block Pointer: %X\n" , $next_block_ptr);
+ ::userDisplay (sprintf " SPTE entry: %X\n" , ::read64
+ ($block_ptr + BLOCK_SPTE_OFFSET, 8));
+
+
+ my $pages = (::read64 ($block_ptr + 8, 8)) / 4096;
+
+ my $presentcount =
+ Hostboot::_DebugFrameworkVMM::getNumPresentPages(::read64 ($block_ptr
+ +
+ BLOCK_SPTE_OFFSET, 8), $pages);
+
+ ::userDisplay" SPTE Entries: ";
+ ::userDisplay (sprintf "Total=%d" , $pages);
+ ::userDisplay (sprintf " Present=%d\n" , $presentcount);
+
+ $block_ptr = $next_block_ptr;
+
+ $i = $i+1;
+ }
+
+return 0;
+}
+
+
+# @sub getNumPresentPages
+#
+# Find the number of SPTE entries that are present.
+#
+# @param Address of the SPTE entry
+#
+sub getNumPresentPages
+{
+ my $SPTE_ptr = shift;
+ my $pages = shift;
+
+ my $presentcount = 0;
+
+ my $i = 0;
+
+ while( $i<$pages)
+ {
+ my $SPTE_entry = ::read32 ($SPTE_ptr + $i, 4);
+
+ # if found present
+ if ($SPTE_entry & 0x00000800)
+ {
+
+#::userDisplay(sprintf" getPhyAddrfromSPTE: FOUND PRESENT The SPTE entry: %X\n\n" , $SPTE_entry);
+
+ $presentcount++
+ }
+
+ $i = $i+1;
+ }
+
+ return $presentcount;
+
+}
+
+
+# @sub printDeviceSegments
+#
+# Pass in a pointer to the address of the first device segment.
+# This routine loops through all device segments and prints out
+# their info.
+# In addition each individual device segment could have
+# up to 32 mmio devices populated so this routine will print
+# out those as well.
+#
+# @param Ptr to the Address of the First Device segment
+# we need to work with from the segment manager
+#
+sub printDeviceSegments
+{
+ my $firstdevicesegmentaddr = shift;
+ my $i = 0;
+
+ # ::userDisplay (sprintf " stack address: Base Ptr %X\n" ,
+ # $firstdevicesegmentaddr);
+
+
+ my $maxdevices = 14;
+
+ my $curdevice = 0;
+
+ # loop through all possible devices.. up to max which is 14
+ while ($curdevice < $maxdevices)
+ {
+ my $deviceSegmentPtr =::read64 ($firstdevicesegmentaddr + (8 *
+ $curdevice),
+ 8);
+
+
+ # ::userDisplay (sprintf " devicesegmentPtr: Base Ptr %X\n" ,
+ # $deviceSegmentPtr);
+
+ my $segmentbaseaddr =::read64($deviceSegmentPtr +
+ DEVICESEGMENT_BASEADDR_OFFSET, 8);
+
+ # If the device segment is valid, then print out its info and
+ # check for MMIO devices populated.
+ if ($deviceSegmentPtr != 0)
+ {
+ #::userDisplay (sprintf " segmentbaseaddr: %X\n" , $segmentbaseaddr);
+ if($segmentbaseaddr != 0)
+ {
+
+ ::userDisplay (sprintf "\n DeviceSegment[%X]\n" ,
+ $curdevice);
+
+ ::userDisplay" ---------------\n";
+ ::userDisplay (sprintf " Base VAddress: %X\n" ,
+ $segmentbaseaddr);
+
+
+ my $mmiostructptr = $deviceSegmentPtr +
+ DEVICESEGMENT_BLOCK_OFFSET;
+
+ my $maxmmiodevices = 32;
+ my $curmmiodevice = 0;
+
+ # loop through all mmio devices max of 32 per device segment.
+ while($curmmiodevice < $maxmmiodevices)
+ {
+ my $segmentPhyAddr =::read64($mmiostructptr +
+ $curmmiodevice*16 +
+ MMIO_STRUCT_SEGADDR_OFFSET, 8);
+
+ my $segmentSize =::read64($mmiostructptr + $curmmiodevice*16
+ + MMIO_STRUCT_SEGSIZE_OFFSET, 8);
+
+ if ($segmentPhyAddr != 0)
+ {
+
+ ::userDisplay (sprintf "\n *MMIOdevice[%X]\n" ,
+ $curmmiodevice);
+
+ ::userDisplay (sprintf
+ " MMio device Phy Address: %X\n" , $segmentPhyAddr);
+
+ ::userDisplay (sprintf
+ " MMio Device Size: %X\n" ,
+ $segmentSize);
+
+ }
+
+ $curmmiodevice = $curmmiodevice + 1;
+ }
+
+ }
+ }
+ $curdevice = $curdevice + 1;
+ }
+
+}
+
+
+
+__END__
OpenPOWER on IntegriCloud