Hi all:

Most tests in the or1ksim's test suite are written in C and do not initialise the BSS section properly. They still work because the simulator initialises all memories with zeroes. This is an excerpt from file default.cfg used by most test cases:

  section memory
    pattern = 0x00
    type = unknown /* Fastest */
    ...

I changed that configuration to "type = exitnops" and some of the tests stopped working. There is no guarantee that all RAM contents will be zeroed on reset, so decided to add code to clear the BSS section properly.

On a side note, I found this type of code at several places like the OpenRISC bootloaders:

        /* Clear the BSS section */
        l.movhi r3,     hi(_bstart)
        l.ori   r3, r3, lo(_bstart)
        l.movhi r4,     hi(_bend)
        l.ori   r4, r4, lo(_bend)
  bss_clear_loop:
        l.sw    0(r3),r0
        l.sfgtu r3, r4
        l.bnf   bss_clear_loop
        l.addi  r3, r3, 4

Note that this code writes at least 32 bits worth of zeroes, but the BSS section could be empty, so it could be writing out of bounds.

Going back to or1ksim's test suite, the first think I did was to add symbols _bstart and _bend to linker script file default.ld like this:

        .bss :
        {
        _bstart = .;
        *(.bss)
        _bend = .;
        } > ram

In the case of <or1ksim repository>/testsuite/test-code-or1k/basic , that produced the following results:

0000327c l    d  .bss   00000000 .bss
00002580 l       .text  00000000 bss_clear_loop
0000327c l     O .bss   00000004 period.1455
00003280 g     O .bss   00000100 int_handlers
0000327c g       .bss   00000000 _bstart
00003280 g       .bss   00000000 _bend

Note that int_handlers is 0x100 bytes long (it's an array), but it does not come up in the resulting length ( _bend - _bstart ).

I then changed the linker script file to this:

        .bss :
        {
        *(.bss)
        } > ram

        _bstart = ADDR(.bss);
        _bend   = _bstart + SIZEOF(.bss);

And got these results:

0000327c l    d  .bss   00000000 .bss
00002580 l       .text  00000000 bss_clear_loop
0000327c l     O .bss   00000004 period.1455
00003280 g     O .bss   00000100 int_handlers
0000327c g       .bss   00000000 _bstart
00003380 g       *ABS*  00000000 _bend

That worked. Then I did yet another test to confirm the problem, I added 2 new symbols to the first version like this:

        .bss :
        {
        _bstart = .;
        *(.bss)
        _bend = .;
        } > ram

        _BSS_BEGIN = ADDR(.bss);
        _BSS_END   = _BSS_BEGIN + SIZEOF(.bss);

And this is what I got:

0000328c l    d  .bss   00000000 .bss
0000328c l     O .bss   00000004 period.1455
00003290 g     O .bss   00000100 int_handlers
0000328c g       .bss   00000000 _bstart
0000328c g       .bss   00000000 _BSS_BEGIN
00003390 g       *ABS*  00000000 _BSS_END
00003290 g       .bss   00000000 _bend

Note that, while _bstart and _BSS_BEGIN have the same value, _BSS_END and _bend do not (!).

I certainly did not expect that behaviour. Does anybody here know why the results are different? I am using the svn head versions from OpenCore's gnusrc repository (gcc-4.5.1 and binutils-2.20.1).

The assembly code that clears BSS writes 32-bits at a time, therefore, if BSS's size is not aligned, it might clear up to 3 bytes beyond the end. This is not normally a problem, as the start of the next section is normally aligned and those (up to) 3 bytes should be padding anyway. In the past, I've made sure that the BSS section length is aligned with this trick:

  . = ALIGN(., 4);

However, that does not seem to work for the OpenRISC toolchain either. I added a couple of "char xxxx" variables and BSS's size was no longer aligned. It's not so important, but I'm worried that something may not be working properly in the OpenRISC port. Or maybe I don't quite understand what's going on with the linker script.

Thanks,
  R. Diez
_______________________________________________
OpenRISC mailing list
[email protected]
http://lists.openrisc.net/listinfo/openrisc

Reply via email to