2

EDIT: Is there a better stackexchange site I should put this on?

I am trying use the DDR4 connected to the FPGA side of a zynq ultrascale chip, specifically on Xilinx's devboard zcu102. I am using Vivado's MIG to generate the controller and connect to the HPM0 AXI port of the main processor. The memory is 0x2000_0000 long and mapped to physical address 0x4_0000_0000.

The problem I am having is when accessing memory unaligned. I believe it to be some misconfiguration in the MMU due to a missing detail in the device tree.

One thing I know is that this arm (A53) is supposed to be able to turn unaligned accesses into multiple access to the memory where necessary. My getting a bus error is telling me that the MMU is misconfigured in some way but I'm not sure how.

The device tree is too long to put here, so I will put what I think are the most important parts directly in here and the rest as a pastebin.

    amba_pl@0 {
            #address-cells = <0x2>;
            #size-cells = <0x2>;
            compatible = "simple-bus";
            ranges;

            ddr4@400000000 {
                    compatible = "xlnx,ddr4-2.2";
                    reg = <0x4 0x0 0x0 0x20000000>;
                    alignment = <0x10>;
            };

            PERIPHERAL@ff380000 {
                    compatible = "xlnx,PERIPHERAL-1.0";
                    reg = <0x0 0xff380000 0x0 0x80000>;
            };

            PERIPHERAL@ff990000 {
                    compatible = "xlnx,PERIPHERAL-1.0";
                    reg = <0x0 0xff990000 0x0 0x10000>;
            };
    };

    aliases {
            ethernet0 = "/amba/ethernet@ff0e0000";
            i2c0 = "/amba/i2c@ff020000";
            i2c1 = "/amba/i2c@ff030000";
            serial0 = "/amba/serial@ff000000";
            serial1 = "/amba/serial@ff010000";
            spi0 = "/amba/spi@ff0f0000";
    };

    memory {
            #address-cells = <0x2>;
            #size-cells = <0x2>;
            device_type = "memory";
            alignment = <0x10>;
            reg = <0x4 0x0 0x0 0x20000000>;
    };

I tried setting the alignment on both /memory and the ddr controller on the /amba_pl, but it doesn't seem to make a difference. In fact, it seems to be ignoring the /memory section, as it still boots off of main system memory and not the memory on the fpga.

I am able to access memory using mmap and devmem as such:

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <unistd.h>
#include <stdint.h>
#include <math.h>

#define ARRAY_TYPE uint16_t

int main(int argc, char *argv[]) {
    if (argc != 2){
        printf("Wrong arg count\n");
        return -1;
    }
    volatile ARRAY_TYPE * ps = malloc(sizeof(ARRAY_TYPE)*10);
    if (NULL==ps){
        printf("Failed to malloc for ps\n");
        return -1;
    }


    int fd = open("/dev/mem", O_RDWR | O_SYNC );
    volatile ARRAY_TYPE *pl = mmap((void*)0x400000000, 0x20000000, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0x400000000);
    if (pl == MAP_FAILED) {
        perror("Can't map memory for pl");
        printf("FAIL\n");
        return -1;
    }


    //force them out of alignment by argv[1] bytes.
    volatile ARRAY_TYPE *ps_unaligned = (volatile ARRAY_TYPE *)(((uint8_t *)ps) + atoi(argv[1]));
    volatile ARRAY_TYPE *pl_unaligned = (volatile ARRAY_TYPE *)(((uint8_t *)pl) + atoi(argv[1]));

    printf("trying ps with offset %d\n", atoi(argv[1]));
    ps_unaligned[0] = 1;
    printf("trying pl with offset %d\n", atoi(argv[1]));
    pl_unaligned[0] = 1;

    munmap(pl, 0x20000000);
    free(ps);
    close(fd);

    return 0;
}

Whenever I try to access memory out of alignment on the main system memory it works fine. However when I access the memory hanging off the FPGA unaligned I get a bus error.

root@zynq: ~
17:22:08 $ ./memtest 0
trying ps with offset 0
trying pl with offset 0
root@zynq: ~
17:22:12 $ ./memtest 1 
trying ps with offset 1
trying pl with offset 1
Bus error
root@zynq: ~
17:22:13 $ ./memtest 2
trying ps with offset 2
trying pl with offset 2
root@zynq: ~
17:22:14 $ ./memtest 3
trying ps with offset 3
trying pl with offset 3
Bus error

I've also looked at the virtual memory mappings of the memory region by looking at /proc/$pid/smaps during a gdb session: Here's the section containing the system memory allocated with devmem/mmap:

400000000-420000000 rw-s 400000000 00:06 1054                            /dev/mem
Size:             524288 kB
KernelPageSize:        4 kB
MMUPageSize:           4 kB
Rss:                   0 kB
Pss:                   0 kB
Shared_Clean:          0 kB
Shared_Dirty:          0 kB
Private_Clean:         0 kB
Private_Dirty:         0 kB
Referenced:            0 kB
Anonymous:             0 kB
LazyFree:              0 kB
AnonHugePages:         0 kB
ShmemPmdMapped:        0 kB
Shared_Hugetlb:        0 kB
Private_Hugetlb:       0 kB
Swap:                  0 kB
SwapPss:               0 kB
Locked:                0 kB
VmFlags: rd wr sh mr mw me ms pf io de dd 

Here's the section for the memory mapped from the FPGA:

5555567000-5555588000 rw-p 00000000 00:00 0                              [heap]
Size:                132 kB
KernelPageSize:        4 kB
MMUPageSize:           4 kB
Rss:                   4 kB
Pss:                   4 kB
Shared_Clean:          0 kB
Shared_Dirty:          0 kB
Private_Clean:         0 kB
Private_Dirty:         4 kB
Referenced:            4 kB
Anonymous:             4 kB
LazyFree:              0 kB
AnonHugePages:         0 kB
ShmemPmdMapped:        0 kB
Shared_Hugetlb:        0 kB
Private_Hugetlb:       0 kB
Swap:                  0 kB
SwapPss:               0 kB
Locked:                0 kB
VmFlags: rd wr mr mw me ac 

I'm not sure if any of the differences in flags explains what is going on but I'm including them in case someone more proficient in memory mapping knows something.

rocky
  • 144
  • 8

0 Answers0