AnsweredAssumed Answered

Virtual address mapping during hypervisor initialization.

Question asked by Travis Wheatley on Jun 20, 2013
Latest reply on Jun 28, 2013 by Scott Wood

I am trying to bring up hypervisor on a P4080PCIe board. During initialization the hypervisor code maps the physical address of the device trees and then reads the fdt header information to determine the size of the tree. I have verified that the physical addresses are being passed into the initialization function properly and have verified that the device trees have valid headers. However, after calling map_phys() the data at the resulting virtual address is not what is expected.

 

I could use some help in figuring out where to look for the root cause of physical to virtual address mapping issues.

 

Following is a more detailed description of the behavior along with code snippets and log information:

 

During boot time I am receiving the message: "panic: fdt too large" error". This message is found in the hypervisor code in a function called map_fdt located in the init.c file. This function reads the .fdt header in the device tree blob and uses it to calculate the total size of the device tree.

 

I can use u-boot to dump the fdt header information of both the hardware .dtb as well as the guest .dtb files and find them both to contain valid totalsize members. However, in the hypervisor map_fdt function these values are not being read correctly. I put some debug print statements in this function and have found that the physical addresses of the .dtb files are getting passed in properly. However, the function calls a "map_phys" function to get a virtual address for the device trees. This virtual address is then used as the location from which to read the fdt header info.

 

So... that tells me that the virtual address mapping is going awry. The obvious questions is what could cause this virtual addressing operation to go wrong? Could it be some initialization problem with u-boot?

 

--------------------------------------------------------------------------------------------

 

Here is the hypervisor function from init.c (with my debug print statements):

 

static void *map_fdt(phys_addr_t treephys)

{

       const size_t mapsize = 4 * 1024 * 1024;

       phys_addr_t mapaddr = treephys & ~((phys_addr_t)mapsize - 1);

       size_t len = mapsize;

       size_t total = 0;

       void *vaddr;

 

printf("TRW - in %s: treephys = %x\n",__FUNCTION__,(unsigned int)treephys);

printf("TRW - in %s: mapaddr = %x\n",__FUNCTION__,(unsigned int)mapaddr);

printf("TRW - in %s: mapsize = %x\n",__FUNCTION__,(unsigned int)mapsize);

 

       /* Map guarded, as we don't know where the end of memory is yet. */

       vaddr = map_phys(TEMPTLB1, mapaddr, temp_mapping[0], &len,

                        TLB_TSIZE_4M, TLB_MAS2_MEM | MAS2_G, TLB_MAS3_KDATA);

       map_phys(TEMPTLB2, mapaddr + mapsize, temp_mapping[0] + mapsize,

                &len, TLB_TSIZE_4M, TLB_MAS2_MEM | MAS2_G, TLB_MAS3_KDATA);

 

       vaddr += treephys & (mapsize - 1);

 

printf("ftd_totalsize(vaddr) = %x\n",fdt_totalsize(vaddr));

 

       /* We handle trees that straddle one 4MiB boundary, but we

        * don't support trees larger than 4MiB.

        */

       if (mapsize * 2 - (treephys & (mapsize - 1)) < fdt_totalsize(vaddr)) {

               if (cpu->crashing)

                       return NULL;

 

               panic("fdt too large: %zu bytes\n", fdt_totalsize(vaddr));

       }

 

       return vaddr;

}

 

-------------------------------------------------------------------------------------

 

Here is the header information for both the hardware and hypervisor device trees:

 

=> fdt addr e8800000                                                           

=> fdt header                                                                  

magic:                  0xd00dfeed                                             

totalsize:              0x9694 (38548)                                         

off_dt_struct:          0xb8                                                   

off_dt_strings:         0x90b0                                                 

off_mem_rsvmap:         0x28                                                   

version:                17                                                     

last_comp_version:      16                                                     

boot_cpuid_phys:        0x0                                                    

size_dt_strings:        0x5e4                                                  

size_dt_struct:         0x8ff8                                                 

number mem_rsv:         0x0                                                    

 

=> fdt addr e8900000                                                           

=> fdt header                                                                  

magic:                  0xd00dfeed                                             

totalsize:              0xc92 (3218)                                           

off_dt_struct:          0x38                                                   

off_dt_strings:         0xbbc                                                  

off_mem_rsvmap:         0x28                                                   

version:                17                                                     

last_comp_version:      16                                                     

boot_cpuid_phys:        0xfeedbeef                                             

size_dt_strings:        0xd6                                                   

size_dt_struct:         0xb84                                                  

number mem_rsv:         0x0                                                    

 

=>

 

----------------------------------------------------------------------------------------------------

 

And last but not least, here is the output of the boot process with the debug print statements showing things going awry in the map_fdt function:

 

=> setenv bootargs config-addr=0xe8900000                                      

=> bootm e8700000 - e8800000                                                   

WARNING: adjusting available memory to 30000000                                

## Booting kernel from Legacy Image at e8700000 ...                            

  Image Name:                                                                 

  Created:      2013-06-19  14:29:31 UTC                                      

  Image Type:   PowerPC Linux Kernel Image (uncompressed)                     

  Data Size:    420000 Bytes = 410.2 KiB                                      

  Load Address: 00000000                                                      

  Entry Point:  00000000                                                      

  Verifying Checksum ... OK                                                   

## Flattened Device Tree blob at e8800000                                      

  Booting using the fdt blob at 0xe8800000                                    

  Loading Kernel Image ... OK                                                 

OK                                                                             

  Loading Device Tree to 00ff3000, end 00fff693 ... OK                        

=======================================                                        

Freescale Hypervisor 0.8-004                                                   

TRW - in map_fdt: treephys = ff3000                                            

TRW - in map_fdt: mapaddr = c00000                                             

TRW - in map_fdt: mapsize = 400000                                             

ftd_totalsize(vaddr) = b000                                                    

TRW - Hypervisor command line: config-addr=0xe8900000                          

TRW - calling init_hv_mem. cfg_addr = e8900000                                 

TRW - Calling map_fdt. cfg_addr: e8900000                                      

TRW - in map_fdt: treephys = e8900000                                          

TRW - in map_fdt: mapaddr = e8800000                                           

TRW - in map_fdt: mapsize = 400000                                             

ftd_totalsize(vaddr) = fffffffe                                                

panic: fdt too large: 4294967294 bytes                                         

TRW - in map_fdt: treephys = ff3000                                            

TRW - in map_fdt: mapaddr = c00000                                             

TRW - in map_fdt: mapsize = 400000                                             

ftd_totalsize(vaddr) = b000                                                    

 

 

Outcomes