[OpenBIOS] Help with libopenbios/ofmem_common.c line 175 "insert in the freelist"
Kenneth Salerno
kennethsalerno at yahoo.com
Thu Aug 11 00:23:12 CEST 2011
--- On Tue, 8/9/11, Mark Cave-Ayland <mark.cave-ayland at siriusit.co.uk> wrote:
> From: Mark Cave-Ayland <mark.cave-ayland at siriusit.co.uk>
> Subject: Re: [OpenBIOS] Help with libopenbios/ofmem_common.c line 175 "insert in the freelist"
> To: openbios at openbios.org
> Date: Tuesday, August 9, 2011, 9:43 AM
> On 08/08/11 22:40, Kenneth Salerno
> wrote:
>
> > Hi,
> >
> > I finally got around to running QEMU in gdb to debug
> the AIX V6.1 boot hang and was able to get past where I got
> stuck previously:
> >
> >
> -------------------------------------------------------------------------------
> >
>
> Welcome to AIX.
> >
> boot image timestamp:
> 00:39 35/2D
> > NULL ihandle
> The current time and date: 00:00:00
> 228784/00/0008
> > processor count:
> 1; memory size: 1024MB; kernel size: 2293829
> >
> boot device: cd:\ppc\chrp\bootfile.exe
> > Validation failed: the "/rtas" device node does not
> exist.
> > EXIT
> >
> >
> > It used to hang after "boot device:
> cd:\ppc\chrp\bootfile.exe" with OpenBIOS stuck at line 175
> of libopenbios/ofmem_common.c:
> >
> > for( pp=&ofmem->mfree;
> *pp&& (**pp).size< d->size ; pp
> =&(**pp).next ) {
> > }
> >
> >
> > I made the following hack to get it to progress to the
> RTAS validation:
> >
> > --- ofmem_common.c.ORIG 2011-08-08 17:04:25.375000000
> -0400
> > +++ ofmem_common.c 2011-08-08
> 17:04:45.875000000 -0400
> > @@ -172,8 +172,9 @@
> > d->next =
> ofmem->mfree;
> >
> > /* insert in the
> (sorted) freelist */
> > - for(
> pp=&ofmem->mfree; *pp&&
> (**pp).size< d->size ; pp =&(**pp).next
> > ) {
> > - }
> > +/* for(
> pp=&ofmem->mfree; *pp&&
> (**pp).size< d->size ; pp =&(**pp).next
> > ) {
> > + } */
> > +
> pp=&ofmem->mfree;
> >
> > d->next = *pp;
> > *pp = d;
> >
> >
> > Before I made the above change, the following is what
> I saw in gdb and qemu console:
> >
> > (qemu) info cpus
> > * CPU #0: nip=0x00000000fff91a84
> thread_id=6828
> >
> > (gdb)
> > 0x00000000fff91a84 in ofmem_free
> (ptr=0x3fca1774)
> > at
> ../libopenbios/ofmem_common.c:175
> > 175 for(
> pp=&ofmem->mfree; *pp&&
> (**pp).size< d->size ; pp =&(**pp).next ) {
> >
> > (gdb) print /x pp
> > $1 = 0x3fc9e0ac
> >
> > The value 0x3fc9e0ac can be found in register GPR08:
> >
> > (qemu) info registers
> > NIP 00000000fff91a84 LR
> 00000000fff91a58 CTR 00000000fff93784 XER 000000002000
> > 0000
> > MSR 0000000000003032 HID0
> 0000000060000000 HF 0000000000002000 idx 1
> > TB 00000001 7638146663 DECR 951787926
> > GPR00 000000003fca1764 000000003fdf69e0
> 00000000fffc68e8 000000003fc9e0ac
> > GPR04 00000000fffc0088 000000003fc5bc68
> 00000000fffc0860 0000000000044200
> > GPR08 0000000000000002 000000003fc9e0ac
> 0000000000000024 0000000000000810
> > GPR12 00000000000088ac 0000000000000000
> 00000000fffb6703 00000000fffb7b65
> > GPR16 00000000fffb8331 00000000fffb6706
> 0000000004000000 00000000fffbf6b8
> > GPR20 00000000fffbf634 00000000fffc68e8
> 00000000fffbf634 00000000fffb650a
> > GPR24 00000000fffb64f8 00000000fffb6478
> 00000000fffb6500 00000000fffb6505
> > GPR28 00000000fffb707e 0000000000000027
> 0000000000000027 000000003fca1774
> > CR 48000084 [ G L
> - - - - L G ]
> RES
> ffffffffffffffff
> > FPR00 0000000000000000 0000000000000000
> 0000000000000000 0000000000000000
> > FPR04 0000000000000000 0000000000000000
> 0000000000000000 0000000000000000
> > FPR08 0000000000000000 0000000000000000
> 0000000000000000 0000000000000000
> > FPR12 0000000000000000 0000000000000000
> 0000000000000000 0000000000000000
> > FPR16 0000000000000000 0000000000000000
> 0000000000000000 0000000000000000
> > FPR20 0000000000000000 0000000000000000
> 0000000000000000 0000000000000000
> > FPR24 0000000000000000 0000000000000000
> 0000000000000000 0000000000000000
> > FPR28 0000000000000000 0000000000000000
> 0000000000000000 0000000000000000
> > FPSCR 00000000
> > SRR0 00000000fffaa590 SRR1
> 0000000000003032 PVR 00000000003c0301 VRSAVE
> 000
> > 0000000000000
> > SPRG0 000000003fe00000 SPRG1
> 000000003fdf6630 SPRG2 0000000000000000 SPRG3
> 000
> > 0000000000000
> > SPRG4 0000000000000000 SPRG5
> 0000000000000000 SPRG6 0000000000000000 SPRG7
> 000
> > 0000000000000
> > SDR1 000000003fe00000
> >
> >
> > Here is my QEMU command:
> >
> >
> ./testing/qemu/ppc64-softmmu/qemu-system-ppc64
> \
> > -L
> ./testing/qemu/pc-bios \
> > -m
> 1024 \
> >
> -bios
> ./testing/openbios-devel/obj-ppc64/openbios-qemu.elf
> >
> -drive
> file=images/aix.img,index=0,media=disk,cache=writeback
> >
> -cdrom images/ibmaix.iso \
> >
> -boot d \
> >
> -nographic \
> >
> -rtc base=localtime,clock=host \
> >
> -uuid 17202d0a-45f8-4159-a8e1-78b866f50aa7
> \
> >
> -serial tcp::9979,server,nowait \
> >
> -monitor tcp::9980,server,nowait \
> >
> -gdb tcp::1234
> >
> > powerpc64-unknown-linux-gnu-gdb
> testing/openbios-devel/obj-ppc64/openbios-qemu.elf-nostrip
> >
> > I don't really know what I'm doing so any help
> explaining this function in ofmem_common.c would be
> appreciated.
>
> Hi Ken,
>
> I didn't write the original version of this code, however I
> have played around with it enough to get an idea of what it
> does, so hopefully the explanation below will make sense ;)
>
> ofmem_malloc() and ofmem_free() are mapped to malloc() and
> free() calls used within OpenBIOS. They are not used by any
> client program. If an area of memory is requested via CIF
> then the allocation is handled separate using the arch/*/
> OFMEM code which will handle memory allocations/mapping
> across the entire address range.
>
> As per the code in libopenbios/ofmem_common.c,
> ofmem_malloc() allocates memory within the OpenBIOS binary
> image between ofmem_arch_get_malloc_base() and
> ofmem_arch_get_heap_top(). These limits are also specified
> per architecture within the arch/*/ OFMEM handler.
>
> In order to facilitate memory re-use, if a chunk of memory
> is ofmem_free()d then it is added to a free memory
> linked-list starting at ofmem->mfree ordered by size. The
> ofmem_malloc() code at line 105 consults this list first
> when trying to allocate memory in order to try and ensure
> that repeated ofmem_malloc() and ofmem_free() calls on the
> same size area of memory don't deplete the available memory
> store.
>
> Finally, ofmem_malloc() must ensure that the returned
> pointer is aligned both physically and virtually, and the so
> the memory descriptor for an entry is stored just before it
> in memory like this:
>
>
>
> | <- aligned ptr
> ----------------------------------------
> | alloc_desc_t | region (<size>
> bytes) |
> ----------------------------------------
>
>
> The code you are having trouble with is the code that tries
> to add the ofmem_free() location back into the freelist
> starting at ofmem->mfree.
>
> Now if ofmem->mfree is getting clobbered somehow then
> that would cause the linked list to jump to random locations
> in memory and hence cause a crash. In these cases the tactic
> is to add a watchpoint in gdb at ofmem->mfree so that gdb
> breaks whenever that memory location is written to. Assuming
> you compile OpenBIOS with -O0 -g then you can obtain a
> backtrace in order to find out where the error is occurring
> and post it back to the list if you need further help.
>
>
> HTH,
>
> Mark.
>
> -- Mark Cave-Ayland - Senior Technical Architect
> PostgreSQL - PostGIS
> Sirius Corporation plc - control through freedom
> http://www.siriusit.co.uk
> t: +44 870 608 0063
>
> Sirius Labs: http://www.siriusit.co.uk/labs
>
Thanks for the information, Mark.
I'm having issues getting OpenBIOS to work properly when I disable optimization, and I'm sure it's something I'm doing wrong or my compiler has a bug (GCC 4.6.1).
If I change -O2 to -O0 in Makefile.target, execution in QEMU will hang with a next instruction pointer of 0x0000000000000004 while reading the IDE device inside the Forth code... If I compile with -02, as you already know, I am told by GDB that ofmem->mfree was optimized out and cannot set a watchpoint:
#0 0x00000000fff91a84 in ofmem_free (ptr=0x3fca1774)
at ../libopenbios/ofmem_common.c:175
#1 0x00000000fff8862c in free (ptr=<optimized out>)
at ../arch/ppc/qemu/ofmem.c:258
#2 0x00000000fff93798 in deblk_close (di=<optimized out>)
at ../packages/deblocker.c:66
#3 0x00000000fff8d950 in call1_func () at ../libopenbios/bindings.c:431
#4 0x00000000fff8b62c in call () at ../kernel/forth.c:244
#5 0x00000000fff8b4e8 in processxt (xt=<optimized out>)
at ../kernel/forth.c:106
#6 next () at ../kernel/forth.c:127
#7 0x00000000fff8d288 in enterforth (xt=<optimized out>)
at ../kernel/forth.c:156
#8 0x00000000fff8de7c in _selfword (method=0xfffb7d26 "close-deblocker",
cache_xt=0xfffc0088) at ../libopenbios/bindings.c:83
#9 0x00000000fff98478 in ob_ide_close (drive=<optimized out>)
at ../drivers/ide.c:1289
#10 0x00000000fff8d950 in call1_func () at ../libopenbios/bindings.c:431
#11 0x00000000fff8b62c in call () at ../kernel/forth.c:244
#12 0x00000000fff8b4e8 in processxt (xt=<optimized out>)
at ../kernel/forth.c:106
#13 next () at ../kernel/forth.c:127
#14 0x00000000fff8d288 in enterforth (xt=<optimized out>)
at ../kernel/forth.c:156
#15 0x00000000fff8daec in _fword (word=<optimized out>, cache_xt=0xfffbfec0)
at ../libopenbios/bindings.c:71
#16 0x00000000fff8f20c in of_client_interface (params=0x44200)
at ../libopenbios/client.c:318
#17 0x00000000fff019fc in of_client_callback ()
at ../arch/ppc/qemu/start.S:614
Backtrace stopped: frame did not save the PC
Sorry to bug you but why can't I get a working OpenBIOS ELF with compiler optimization disabled?
Thank you,
Ken
More information about the OpenBIOS
mailing list