FreeBSD/armv6z/clang on Raspberry Pi 512MB (with U-Boot + ubldr)

Daisuke Aoyama aoyama at peach.ne.jp
Thu Dec 27 15:34:36 UTC 2012


>>> PTE sync - related part, Im not sure it's strictly required. We use WT 
>>> caches for page tables
>>> so we should be OK without implicit sync operations for them. I hope 
>>> somebody
>>> more clueful can confirm/disprove this.
>>
>> Some digging, I notice "Invalidate Entire Instruction Cache" works 
>> without segfault.
>> So, Invalidate D-cache is no effect :)
>>
>> It seems following should work for this issue:
>>
>>       mov     r0, #0
>>       mcr     p15, 0, r0, c7, c5, 0           /* Invalidate Entire 
>> Instruction Cache */
>>       mcr     p15, 0, r0, c7, c10, 4          /* Data Synchronization 
>> Barrier */
(snip)
>
> Hmm, I saw problems with i-caches with kernel with WB cache enabled 
> instead of WT.
> This patch fixed it for me:
>
> http://people.freebsd.org/~gonzo/arm/patches/pmapv6-icache.diff
> It invalidates i-caches only when new mapping is created, not on every 
> switch so
> it should be less taxing on performance.
>
> Could you test it on your setup? =

It does not help. Also both your patch +PTE SYNC and call always WBINV in 
pmap +PTE SYNC don't help.
The kernel applied your patch was failed at first "portsnap fetch" step.
Probably change in pmap is no effect for this segfault.

Currently, adding invalidate I-cache to swtch.S is only solution.
My test is:

1) ping from other freebsd to RPI.
2) login to RPI, then run "top -PHs1" under pi user.
3) use simple test (portsnap fetch/extract/build bash) from console.

Side effect of digging, I found a reason why timer is never fired.

According to the source, et_min_period.frac set to 2.
This means the start will be called with 1 (frac - 1).
So the routine have only 1us(1MHz) to be finished for the request.
Probably it's impossible even if modern CPU such as 3GHz CPU.

If failed to setup, it will be fired after 0xffffffff(wrapped about 
4294.9sec).
So, "the interrupt is not fired" is wrong understanding.
The timer will be fired later. Until this, the world seems to have stopped 
:)

This is complete version of systimer patch.
It should fix stopping interrupt and related things such as USB LAN is 
unstable,
SSH is closed suddenly.
(I've not yet finished all test at this time, but at least portsnap fetch is 
success.
Now extracting the ports without any problems.)

----------------------------------------------------------------------
--- bcm2835_systimer.c  (revision 244663)
+++ bcm2835_systimer.c  (working copy)
@@ -55,6 +55,7 @@

 #define        DEFAULT_TIMER           3
 #define        DEFAULT_FREQUENCY       1000000
+#define        MIN_PERIOD                 1000LLU

 #define        SYSTIMER_CS     0x00
 #define        SYSTIMER_CLO    0x04
@@ -123,17 +124,20 @@
        struct systimer *st = et->et_priv;
        uint32_t clo;
        uint32_t count;
+       register_t s;

        if (first != NULL) {
-               st->enabled = 1;
-
                count = (st->et.et_frequency * (first->frac >> 32)) >> 32;
                if (first->sec != 0)
                        count += st->et.et_frequency * first->sec;

+               s = intr_disable();
                clo = bcm_systimer_tc_read_4(SYSTIMER_CLO);
                clo += count;
                bcm_systimer_tc_write_4(SYSTIMER_C0 + st->index*4, clo);
+               st->enabled = 1;
+               bcm_systimer_tc_write_4(SYSTIMER_CS, (1 << st->index));
+               intr_restore(s);

                return (0);
        }
@@ -154,13 +158,18 @@
 bcm_systimer_intr(void *arg)
 {
        struct systimer *st = (struct systimer *)arg;
+       uint32_t cs;

+       cs = bcm_systimer_tc_read_4(SYSTIMER_CS);
+       if ((cs & (1 << st->index)) == 0)
+         return (FILTER_STRAY);
+
        bcm_systimer_tc_write_4(SYSTIMER_CS, (1 << st->index));
-       if (st->enabled) {
+       //if (st->enabled) {
                if (st->et.et_active) {
                        st->et.et_event_cb(&st->et, st->et.et_arg);
                }
-       }
+       //}

        return (FILTER_HANDLED);
 }
@@ -226,7 +235,7 @@
        sc->st[DEFAULT_TIMER].et.et_frequency = sc->sysclk_freq;
        sc->st[DEFAULT_TIMER].et.et_min_period.sec = 0;
        sc->st[DEFAULT_TIMER].et.et_min_period.frac =
-           ((0x00000002LLU << 32) / sc->st[DEFAULT_TIMER].et.et_frequency) 
<< 32;
+           ((MIN_PERIOD << 32) / sc->st[DEFAULT_TIMER].et.et_frequency) << 
32;
        sc->st[DEFAULT_TIMER].et.et_max_period.sec = 0xfffffff0U / 
sc->st[DEFAULT_TIMER].et.et_frequency;
        sc->st[DEFAULT_TIMER].et.et_max_period.frac =
            ((0xfffffffeLLU << 32) / sc->st[DEFAULT_TIMER].et.et_frequency) 
<< 32;
----------------------------------------------------------------------
Thanks.
-- 
Daisuke Aoyama
 



More information about the freebsd-arm mailing list