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

Blue Swirl blauwirbel at gmail.com
Sun Dec 27 11:14:53 CET 2009


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.

> --- 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.

> 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?



More information about the OpenBIOS mailing list