On Tue, Sep 05, 2023 at 11:40:42PM +0200, Peter J. Philipp wrote:
> Hi,
>
> I'm porting OpenBSD to the Mango Pi D1. Most of the work is done but now
> is the time to try to get a RAMDISK kernel to boot.
>
> I'm having an issue with atomic_store_64() as shown here (line 1192):
>
> 1184 for (; va < DMAP_MAX_ADDRESS && pa < max_pa;
> 1185 pa += L1_SIZE, va += L1_SIZE, l1_slot++) {
> 1186 KASSERT(l1_slot < Ln_ENTRIES);
> 1187
> 1188 /* gigapages */
> 1189 pn = (pa / PAGE_SIZE);
> 1190 entry = PTE_KERN;
> 1191 entry |= (pn << PTE_PPN0_S);
> 1192 atomic_store_64(&l1[l1_slot], entry);
> 1193 }
>
> The D1 seems to hang on this call. To me that seems like the store hangs that
> I did on powerpc64 when memory was not aligned. When I replaced the
> AMO instruction with a simple C replacement it worked. So I wonder if the
> following is correct or not:
>
> entry = _ALIGN(PTE_KERN);
>
> I looked at riscv-privileged-202111203.pdf (page 79) which is for Sv32 and
> a few pages down is the Sv39 (page 84). But I can't make sense of it. And
> my Mona Lisa book that I have from Waterman mentions on page 101:
>
> ''Misaligned address exceptions occur when the effective address isn't
> divisible
> by the access size - for example, amoadd.w with an address of 0x12.''
>
> I don't think in the bootstrapping of pmap that traps are turned on yet,
> but I could be mistaken, hence the hang.
There is something weird which I can't figure out, this document is golden
to find the truth:
https://github.com/riscv/riscv-isa-manual/releases/download/Priv-v1.12/riscv-privileged-20211203.pdf
OK on page 79 is the Sv32 (32-bit specification), it is kinda irrelevant
for us but there is something bothering me, and we must see into this so that
we can talk about Sv39 (64-bit) which is on page 84, and Sv48 which is on
page 86.
Sv32:
on page 80, figure 4.17 is the 32-bit physical address translation (based on
satp register's MODE) and PPN0 is 10 bits here. PPN1 is 12 bits. PPN is
the physical page number. And the 0 and 1 is the levels of what sort of
pages these are. 4096 byte size is level 0, and level 1 is 4MB (megapages)
size. PTESIZE=4
Sv39:
on page 85, figure 4.20, is the 64-bit (Sv39) physical address translation
based on the satp register which is 64 bits. PPN0 is 9 bits here, PPN1 is
9 bits and PPN2 is 26 bits. These three levels represent 4096 byte physical
page numbers (level 0), 2 MB megapages PPN's (level 1) and 1 GB gigapages
PPN's. "each of which must be virtually and physically aligned to a
boundary equal to its size. A page-fault exception is raised if the physical
address is insufficently aligned". PTESIZE=8
Sv48:
on page 86, figure 4.23, is a 64-bit (Sv48) physical address translation
based on the satp register again which is 64 bits. They have 4 levels of
PPN numbers; level 0 pages (9 bits), level 1 megapages (9 bits),
level 2 gigapages (9 bits) and also introduce 512 GB terapages on level 3
(17 bits). PTESIZE=8
OK now that I have repeated the document I have 3 questions:
1. AFAIK, we ONLY support Sv39 right now, is this true?
2. From /usr/src/sys/arch/riscv64/include/pte.h:
#define PTE_PPN0_S 10
This is the PPN shift value...why is it 10 and not 9? We're using Sv39.
If this is wrong then PTE_PPN[123] also have to be adjusted.
3. Why are we talking about 4 levels of PPN's when there is only 3 levels in
the Sv39 definition?
I put some debugging into my kernel this morning and added a printf in
pmap's pmap_bootstrap_dmap() and had it just before the atomic function:
>> OpenBSD/riscv64 BOOTRISCV64 1.5
boot> boot
cannot open sd0a:/etc/random.seed: No such file or directory
booting sd0a:/bsd: 2152904+693716+8907000+538152
[181604+122+283464+186377]=0xfa1420
bootargs:
aligned_entry=10001000,pn=40000,ae%pn=1000,&l1[l1s]=ffffffc00100ba00
This is what it showed me. In my tests instead of _ALIGN()'ing PTE_KERN I
round_page() the entry value to make it 4096 page aligned (10001000),
I also show the physmem in page numbers 0x40000 which is 262144 pages for
1 GB RAM. aligned_entry % pn == 0x1000, which didn't fit exactly into this.
and finally &l1[l1_slot] which gave this odd looking number:
0xffffffc00100ba00
This is not a page aligned offset, on any physical page number. L1_slot I
think was 320 from earlier debugs and I left it alone in my tests. Let's see,
here it is:
before atomic store l1=ffffffc00100a000 l1_slot=320,[ffffffc00100aa00], entry =
100000c7
So I'm wondering about these misalignments and the questions above.
> If you have another idea why I get these let me know, I'm going to bed now
> and won't be up until 6AM or later tomorrow. I'm letting my kernel compile
> on the slow QEMU host overnight.
Sorry about this, tb@, I'll try to refrain from mentioning my bed times.
Best Regards,
-peter
--
Over thirty years experience on Unix-like Operating Systems starting with QNX.