[OpenBIOS] [PATCH 3/3] ofmem: helper to find first virtual address map entry

Igor Kovalenko igor.v.kovalenko at gmail.com
Sun Dec 27 12:28:55 CET 2009


On Sun, Dec 27, 2009 at 1:14 PM, Blue Swirl <blauwirbel at gmail.com> wrote:
> On Sat, Dec 26, 2009 at 10:07 PM, Igor V. Kovalenko
> <igor.v.kovalenko at gmail.com> wrote:
>> From: Igor V. Kovalenko <igor.v.kovalenko at gmail.com>
>>
>> A few places in sparc64 code may need to know where
>> specific physical address range is mapped to access
>> memory locations. Create helper to find first suitable
>> mapping and return virtual address.
>>
>> - ofmem_find_virtual: new method; use it to find
>>  where physical memory address is mapped
>>
>> - arch_nvram_get call ofmem_find_virtual to access
>>  kernel command line parameters from qemu
>>
>> - vga_config_cb call ofmem_find_virtual to access
>>  framebuffer on sparc64
>
> It would be nice to split the patch to two pieces so that it would be
> OK to apply the ofmem_find_virtual part even without the 1/3 patch or
> VGA/cmdline part.

Will do the split, there to be 3 pieces.

>
>> --- a/arch/sparc64/openbios.c
>> +++ b/arch/sparc64/openbios.c
>> @@ -281,6 +281,7 @@ void arch_nvram_get(char *data)
>>     uint16_t machine_id;
>>     const char *stdin_path, *stdout_path;
>>     const char *kernel_cmdline;
>> +    ucell kernel_cmdline_addr;
>>
>>     fw_cfg_init();
>>
>> @@ -302,12 +303,18 @@ void arch_nvram_get(char *data)
>>     kernel_size = fw_cfg_read_i32(FW_CFG_KERNEL_SIZE);
>>     if (kernel_size)
>>         kernel_image = fw_cfg_read_i64(FW_CFG_KERNEL_ADDR);
>> -    kernel_cmdline = (const char *) fw_cfg_read_i64(FW_CFG_KERNEL_CMDLINE);
>> -    if (kernel_cmdline) {
>> -        size = strlen(kernel_cmdline);
>> -        if (size > OBIO_CMDLINE_MAX - 1)
>> -            size = OBIO_CMDLINE_MAX - 1;
>> -        memcpy(&obio_cmdline, kernel_cmdline, size);
>> +    /* first read physical address of command line parameters */
>> +    kernel_cmdline_addr = fw_cfg_read_i64(FW_CFG_KERNEL_CMDLINE);
>> +    if (kernel_cmdline_addr) {
>> +        /* find virtual address, expect it to be mapped by entry.S */
>> +        kernel_cmdline_addr = ofmem_find_virtual(kernel_cmdline_addr);
>> +        if (kernel_cmdline_addr != (ucell)-1) {
>> +            kernel_cmdline = (const char*) kernel_cmdline_addr;
>> +            size = strlen(kernel_cmdline);
>> +            if (size > OBIO_CMDLINE_MAX - 1)
>> +                size = OBIO_CMDLINE_MAX - 1;
>> +            memcpy(&obio_cmdline, kernel_cmdline, size);
>> +        }
>>     }
>>     obio_cmdline[size] = '\0';
>>     qemu_cmdline = (uint64_t)obio_cmdline;
>
> As a side note, QEMU should store the command line in fw_cfg like PC
> also for Sparc.

I'll split this out as well, so when qemu part is ready we can revert
this and install proper solution.

>
>> diff --git a/include/ofmem.h b/include/ofmem.h
>> index 37f9e3b..eaa5082 100644
>> --- a/include/ofmem.h
>> +++ b/include/ofmem.h
>> @@ -92,6 +92,7 @@ extern int   ofmem_unmap( ucell virt, ucell size );
>>  extern void  ofmem_release_phys( ucell phys, ucell size );
>>  extern void  ofmem_release_virt( ucell virt, ucell size );
>>  extern ucell ofmem_translate( ucell virt, ucell *ret_mode );
>> +extern ucell ofmem_find_virtual( ucell phys );
>>
>>  #ifdef CONFIG_PPC
>>  #define PAGE_SHIFT   12
>> diff --git a/modules/ofmem_common.c b/modules/ofmem_common.c
>> index 760823d..fedcaa1 100644
>> --- a/modules/ofmem_common.c
>> +++ b/modules/ofmem_common.c
>> @@ -694,6 +694,31 @@ ucell ofmem_translate( ucell virt, ucell *mode )
>>        return -1;
>>  }
>>
>> +/* physical -> virtual.
>> +   return first found translation
>> + */
>> +ucell ofmem_find_virtual( ucell phys )
>> +{
>> +    ofmem_t *ofmem = ofmem_arch_get_private();
>> +    translation_t *t;
>> +
>> +    OFMEM_TRACE("ofmem_find_virtual: searching virtual address of "
>> +            FMT_ucellx "\n", phys);
>> +
>> +    for( t=ofmem->trans; t ; t=t->next ) {
>> +        ucell offs;
>> +        if( t->phys <= phys && t->phys + t->size - 1 >= phys ) {
>> +            offs = phys - t->phys;
>> +            return t->virt + offs;
>> +        }
>> +    }
>> +
>> +    OFMEM_TRACE("ofmem_find_virtual: no translation defined (" FMT_ucellx ")\n",
>> +            phys);
>> +
>> +    return -1;
>> +}
>> +
>>  /* release memory allocated by ofmem_claim_phys */
>>  void ofmem_release_phys( ucell phys, ucell size )
>>  {
>> diff --git a/modules/video.c b/modules/video.c
>> index fe8f1a2..83a39b4 100644
>> --- a/modules/video.c
>> +++ b/modules/video.c
>> @@ -309,7 +309,6 @@ init_video( unsigned long fb,  int width, int height, int depth, int rb )
>>        int i, s, size;
>>        phandle_t ph=0;
>>
>> -       video.fb.mphys = fb;
>>        video.fb.w = width;
>>        video.fb.h = height;
>>        video.fb.depth = depth;
>> @@ -333,6 +332,14 @@ init_video( unsigned long fb,  int width, int height, int depth, int rb )
>>        ofmem_claim_virt( video.fb.mphys, size, 0 );
>>        ofmem_map( video.fb.mphys, video.fb.mphys, size, -1 );
>>  #endif
>> +#if defined(CONFIG_SPARC64)
>> +    // TODO: use full 64bit physical address of framebuffer
>> +       // The issue here is that fb is passed value of bar address
>> +       // which is an offset from pci memory space
>> +       fb = ofmem_find_virtual(fb);
>> +#endif
>> +
>> +       video.fb.mphys = fb;
>
> What would be the correct solution, should pci.c use physical (or
> virtual?) addresses for assigned addresses, or should the assigned
> address be translated to physical/virtual before passing to callbacks?

To my mind vga_config_cb should map the bar into virtual address space,
then pass virtual address to video init routine. Video module should work
with already mapped framebuffer.

I decided to postpone change to vga_config_cb to minimize churn.

-- 
Kind regards,
Igor V. Kovalenko



More information about the OpenBIOS mailing list