FreeBSD/armv6z/clang on Raspberry Pi 512MB (with U-Boot + ubldr)
Daisuke Aoyama
aoyama at peach.ne.jp
Thu Dec 27 16:43:54 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.
>
> The thing I don't understand about all this is that I'm not seeing any
> of the problems you describe, and I can run this sequence you showed:
>
>> # rm -rf /var/db/portsnap /usr/ports
>> # mkdir /var/db/portsnap
>> # portsnap fetch
>> # portsnap extract
>> # cd /usr/ports/shells/bash
>> # make BATCH=y
>
> It works on an SSD drive connected via USB without any errors. I
> noticed your message said to try it with an sdcard, so I'm preparing an
> 8gb card now to try that with. But if it fails with sd after working
> fine with a USB drive, that would make me suspect the sd-related
> drivers.
Thank you for a comment.
Probably it may be clang issue. I didn't check with gcc.
> I don't have any of your patches, I'm just using plain -current @
> r244691. I'm using gcc, not clang. I probably do need your timer
> patch, because I have seen ssh sessions close unexpectedly when the
> system is idle.
Now I have uploaded the patch contains the systimer patch.
Please take the part of this patch if you are interested in.
http://www.peach.ne.jp/archives/rpi/patch/src-244663-20121228.patch.gz
For clang user, this pre-build version can be used:
http://www.peach.ne.jp/archives/rpi/test/kernel-20121228.gz
Thanks.
--
Daisuke Aoyama
More information about the freebsd-arm
mailing list