Hi all,

I'm currently working on a set of patches for OpenBIOS (the OF implementation for QEMU) in order to get the various *BSD kernels to boot under QEMU SPARC64 with some success, but I'm struggling with a privilege violation trap which occurs on the first window fill trap after OpenBSD takes over the trap table. This is with the latest OpenBSD 5.5 and with my current patchset the console output looks like this:


Loading FCode image...
Loaded 4829 bytes
entry point is 0x4000
OpenBSD IEEE 1275 Bootblock 1.3
..
Jumping to entry point 0000000000100000 for type 0000000000000001...
switching to new context: entry point 0x100000 stack 0x00000000ffe8aa09
>> OpenBSD BOOT 1.6
Trying bsd...
open /pci@1fe,0/pci-ata@5/ide1@600/cdrom@0:f/etc/random.seed: No such file or directory
Booting /pci@1fe,0/pci-ata@5/ide1@600/cdrom@0:f/bsd
3901336@0x1000000+6248@0x13b8798+3261984@0x1800000+932320@0x1b1c620
symbols @ 0xffc5a300 119 start=0x1000000

Unexpected client interface exception: -1
panic: trap type 0x101 (breakpoint): pc=1010254 npc=1010258 pstate=99110414<MG,PEF,PRIV>
halted

EXIT


I asked around on IRC and it was suggested that I post the information here in order to get some further input on this. My feeling is that QEMU SPARC64 may be doing something different to real hardware but I don't have any to play with and this is my first dig into OpenBSD, so I'd really appreciate some pointers from interested parties.

The privilege violation trap I experience occurs just after OpenBSD invokes the OF "SUNW,set-trap-table" call and occurs in the epilogue of openfirmware() in locore.S at the final restore:

        ...
        rdpr    %pstate, %l0
        jmpl    %i4, %o7
         wrpr   %g0, PSTATE_PROM|PSTATE_IE, %pstate
        wrpr    %l0, %g0, %pstate
        mov     %l1, %g1
        mov     %l2, %g2
        mov     %l3, %g3
        mov     %l4, %g4
        mov     %l5, %g5
        mov     %l6, %g6
        mov     %l7, %g7
        wrpr    %i2, 0, %pil
        ret
         restore        %o0, %g0, %o0

What happens here is that when the final restore is executed in the delay slot, a fill_0_normal trap is generated which vectors into 0x1001800 here:

(gdb) disas 0x1001800, 0x100185c
Dump of assembler code from 0x1001800 to 0x100185c:
=> 0x0000000001001800:  wr  %g0, 0x11, %asi
   0x0000000001001804:  ldxa  [ %sp + 0x7ff ] %asi, %l0
   0x0000000001001808:  ldxa  [ %sp + 0x807 ] %asi, %l1
   0x000000000100180c:  ldxa  [ %sp + 0x80f ] %asi, %l2
   0x0000000001001810:  ldxa  [ %sp + 0x817 ] %asi, %l3
   0x0000000001001814:  ldxa  [ %sp + 0x81f ] %asi, %l4
   0x0000000001001818:  ldxa  [ %sp + 0x827 ] %asi, %l5
   0x000000000100181c:  ldxa  [ %sp + 0x82f ] %asi, %l6
   0x0000000001001820:  ldxa  [ %sp + 0x837 ] %asi, %l7
   0x0000000001001824:  ldxa  [ %sp + 0x83f ] %asi, %i0
   0x0000000001001828:  ldxa  [ %sp + 0x847 ] %asi, %i1
   0x000000000100182c:  ldxa  [ %sp + 0x84f ] %asi, %i2
   0x0000000001001830:  ldxa  [ %sp + 0x857 ] %asi, %i3
   0x0000000001001834:  ldxa  [ %sp + 0x85f ] %asi, %i4
   0x0000000001001838:  ldxa  [ %sp + 0x867 ] %asi, %i5
   0x000000000100183c:  ldxa  [ %sp + 0x86f ] %asi, %fp
   0x0000000001001840:  ldxa  [ %sp + 0x877 ] %asi, %i7
   0x0000000001001844:  nop
   0x0000000001001848:  sethi  %hi(0xe0018000), %g5
   0x000000000100184c:  ldx  [ %g5 + 0x10 ], %g5        ! 0xe0018010
   0x0000000001001850:  ldx  [ %g5 + 0x28 ], %g5
   0x0000000001001854:  xor  %g5, %i7, %i7
   0x0000000001001858:  restored
End of assembler dump.
(gdb) info regi sp
sp             0x1800671        0x1800671

As soon as I step into address 0x1001804 then this is where things start to go wrong; the TLB (TTE) entry for 0x1800000 which is accessed by %sp is marked as privileged, but ASI 0x11 is user access only. QEMU's current behaviour for this is to generate a datafault for the page at 0x1800000 which seems to get all the way through to the retry at the end of winfixsave, but then hits the breakpoint trap above when executing the retry.

Based on this I have a couple of questions about what is happening here:

1) Is the fill_0_normal (user-level) trap the correct one? Or does OpenBIOS need to do something with %otherwin to invoke a supervisor-level trap?

2) Is the QEMU SPARC64 behaviour of invoking a data_access_exception when accessing supervisor memory with a user ASI correct?

FWIW I also tried some older OpenBSD ISOs and found that this behaviour was introduced between the 4.3 and 4.4 releases, and older releases don't exhibit this problem. Repeating the same test in 4.3, which is the last release that doesn't trap with the breakpoint error above, shows that the fill_0_normal trap is still invoked in the openfirmware() epilogue, however the stack pointer is now different:

(gdb) info regi sp
sp             0x1c09621        0x1c09621

And I can confirm that page 0x1c08000 exists in the TLB but compared to the current release above *isn't* marked as privileged, so no fault occurs and execution continues correctly until we reach device-tree related bugs (which are definitely in QEMU/OpenBIOS I should point out).


Kind regards,

Mark.

Reply via email to