Re: framebuffer corruption due to overlapping stp instructions on arm64

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 




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++;
> >         }
> > }
> 



[Index of Archives]     [DMA Engine]     [Linux Coverity]     [Linux USB]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Greybus]

  Powered by Linux