[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