On Fri, 3 Aug 2018, Ard Biesheuvel wrote: > (- libc-alpha) > > On 3 August 2018 at 19:09, Mikulas Patocka <mpatocka@xxxxxxxxxx> wrote: > > > > > > On Fri, 3 Aug 2018, Will Deacon wrote: > > > >> On Fri, Aug 03, 2018 at 09:16:39AM +0200, Ard Biesheuvel wrote: > >> > On 3 August 2018 at 08:35, Mikulas Patocka <mpatocka@xxxxxxxxxx> wrote: > >> > > > >> > > > >> > > On Thu, 2 Aug 2018, Matt Sealey wrote: > >> > > > >> > >> The easiest explanation for this would be that the memory isn?t mapped > >> > >> correctly. You can?t use PCIe memory spaces with anything other than > >> > >> Device-nGnRE or stricter mappings. That?s just differences between the > >> > >> AMBA and PCIe (posted/unposted) memory models. > >> > > >> > Whoa hold on there. > >> > > >> > Are you saying we cannot have PCIe BAR windows with memory semantics on ARM? > >> > > >> > Most accelerated graphics drivers rely heavily on the ability to map > >> > the VRAM normal-non-cacheable (ioremap_wc, basically), and treat it as > >> > ordinary memory. > >> > >> Yeah, I'd expect framebuffers to be mapped as normal NC. That should be > >> fine for prefetchable BARs, no? > >> > >> Will > > > > So - why does it corrupt data then? I've created this program that > > reproduces the data corruption quicky. If I run it on /dev/fb0, I get an > > instant failure. Sometimes a few bytes are not written, sometimes a few > > bytes are written with a value that should be 16 bytes apart. > > > > Are we still talking about overlapping unaligned accesses here? Or do > you see other failures as well? Yes - it is caused by overlapping unaligned accesses inside memcpy. When I put "dmb sy" between the overlapping accesses in glibc/sysdeps/aarch64/memcpy.S, this program doesn't detect any memory corruption. > > I tried to run it on system RAM mapped with the NC attribute and I didn't > > get any corruption - that suggests the the bug may be in the PCIE > > subsystem. > > > > Jingoo Han and Joao Pinto are maintainers for the designware PCIE > > controllers. Could you suggest why does the controller corrupt data when > > writing to videoram? Are there any tricks that could be tried to work > > around the corruption? > > > > Mikulas > > > > > > > > #include <stdio.h> > > #include <stdlib.h> > > #include <string.h> > > #include <fcntl.h> > > #include <unistd.h> > > #include <sys/mman.h> > > > > #define LEN 256 > > #define PRINT_STRIDE 0x20 > > > > static unsigned char data[LEN]; > > static unsigned char val = 0; > > > > static unsigned char prev_data[LEN]; > > > > static unsigned char map_copy[LEN]; > > > > int main(int argc, char *argv[]) > > { > > unsigned long n = 0; > > int h; > > unsigned char *map; > > unsigned start, end, i; > > > > if (argc < 2) fprintf(stderr, "argc\n"), exit(1); > > if (argc >= 4) srandom(atoll(argv[3])); > > h = open(argv[1], O_RDWR | O_DSYNC); > > if (h == -1) perror("open"), exit(1); > > map = mmap(NULL, LEN, PROT_READ | PROT_WRITE, MAP_SHARED, h, argc >= 3 ? strtoull(argv[2], NULL, 16) : 0); > > if (map == MAP_FAILED) perror("mmap"), exit(1); > > > > memset(data, 0, LEN); > > memset(prev_data, 0, LEN); > > memset(map, 0, LEN); > > > > sleep(1); > > > > while (1) { > > start = (unsigned)random() % (LEN + 1); > > end = (unsigned)random() % (LEN + 1); > > if (start > end) > > continue; > > for (i = start; i < end; i++) > > data[i] = val++; > > memcpy(map + start, data + start, end - start); > > if (memcmp(map, data, LEN)) { > > unsigned j; > > memcpy(map_copy, map, LEN); > > fprintf(stderr, "mismatch after %lu loops!\n", n); > > fprintf(stderr, "last copied range: 0x%x - 0x%x (0x%x)\n", start, end, (unsigned)(end - start)); > > for (j = 0; j < LEN; j += PRINT_STRIDE) { > > fprintf(stderr, "p[%03x]", j); > > for (i = j; i < j + PRINT_STRIDE && i < LEN; i++) > > fprintf(stderr, " %s%s%02x\e[0m", !(i % 4) ? " " : "", data[i] != map_copy[i] ? "\e[31m" : "", prev_data[i]); > > fprintf(stderr, "\n"); > > fprintf(stderr, "d[%03x]", j); > > for (i = j; i < j + PRINT_STRIDE && i < LEN; i++) > > fprintf(stderr, " %s%s%02x\e[0m", !(i % 4) ? " " : "", data[i] != map_copy[i] ? "\e[31m" : "", data[i]); > > fprintf(stderr, "\n"); > > fprintf(stderr, "m[%03x]", j); > > for (i = j; i < j + PRINT_STRIDE && i < LEN; i++) > > fprintf(stderr, " %s%s%02x\e[0m", !(i % 4) ? " " : "", data[i] != map_copy[i] ? "\e[31m" : "", map_copy[i]); > > fprintf(stderr, "\n\n"); > > } > > exit(1); > > } > > memcpy(prev_data, data, LEN); > > n++; > > } > > } >