public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: David Woodhouse <dwmw2@infradead.org>
To: Christoph Rohland <cr@sap.com>
Cc: Alan Cox <alan@lxorguk.ukuu.org.uk>,
	maze@druid.if.uj.edu.pl (Maciej Zenczykowski),
	linux-kernel@vger.kernel.org
Subject: Re: [OT] Wrapping memory.
Date: Mon, 03 Dec 2001 09:11:18 +0000	[thread overview]
Message-ID: <25163.1007370678@redhat.com> (raw)
In-Reply-To: <m3r8qcagt7.fsf@linux.local>
In-Reply-To: <m3r8qcagt7.fsf@linux.local>  <E16AIZ8-0008Re-00@the-village.bc.nu> <12969.1007315617@redhat.com>

[-- Attachment #1: Type: text/plain, Size: 2186 bytes --]


cr@sap.com said:
> On Sun, 02 Dec 2001, David Woodhouse wrote:
> > You said 'assume i386', but just to make it clear - this is likely
> > to break horribly on some non-i386 platforms, due to dcache
> > aliasing. 
> Which platforms are affected by this? 

Anything with a virtually-indexed cache and a data capacity per way that's 
more than your page size - basically anything where it's possible for two 
different _virtual_ addresses for the same physical address to end up on 
different cache lines.

On SH3 you'll get away with it because the range of address space covered by
the cache is only 2KiB anyway - it's a 8KiB cache but 4-way associative, so
only the bottom 11 bits of the address affect the cache line used - and in
fact it doesn't matter that it's virtually indexed because unless you start
using 1KiB pages, those bits aren't changed by the MMU - only the offset
within the page defined the cache line you look in, and it doesn't matter
about the translation.

On SH4, the data capacity per way of the cache is 8KiB, and because we use 
4KiB pages we have two colours. See arch_get_unmapped_area() in 
arch/sh/kernel/sys_sh.c, and its usage in sys_mmap() and sys_mremap(). 
Basically we refuse to allow a mmap of a page to the 'wrong' colour, to 
avoid getting aliases.

ARM used to just break, but I pointed it out to Russell a while ago and I 
believe he fixed it. I don't remember what his fix was - it may have been 
just to map the offending page uncached, which is also a fairly effective 
was of avoiding cache aliasing :)

The MIPS kernel doesn't deal with this at all. Ralf tells me that the RM7000
and R[236]000 processors should be fine for the same reason as the SH3, but 
R[45]000 are likely to break.

I don't know about other architectures. 

A third possible approach other than just refusing the wrong-colour mapping
or disabling the cache entirely is to use the MMU to make sure only one
colour is accessible at a time - when you get a fault on the virtual address
of another colour, you flush the caches and swap over. You're not going to
do that without a physical->virtual lookup though, so it's basically not an
option for Linux atm.

--
dwmw2


[-- Attachment #2: aliastest.c --]
[-- Type: text/plain , Size: 1714 bytes --]

#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>

#define PAGE_SIZE 4096

int main(int argc, char **argv)
{
	int fd, err;
	int towrite = PAGE_SIZE;
	char *p;
	volatile char *map1, *map2;
	unsigned char b[4];

	fd = open (argc>2?argv[1]:"/tmp/testfile", O_CREAT|O_TRUNC|O_RDWR, 0644);
	if (!fd<0) {
		perror("open");
		close(fd);
		return 1;
	}
	
	p = malloc(PAGE_SIZE);
	if (!p) {
		fprintf(stderr, "malloc failed\n");
		return 2;
	}
	memset(p, 0, PAGE_SIZE);

	while(towrite) {
		err = write(fd, p, PAGE_SIZE);

		if (err < 0) {
			perror("write");
			close(fd);
			return 3;
		}
		towrite -= err;
	}

	map1 = mmap(0, PAGE_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
	if (!map1) {
		perror("mmap 1");
		close(fd);
		return 4;
	}
	/* Make sure the second mapping is _immediately_ after the first */
	map2 = mmap((void *)map1+PAGE_SIZE, PAGE_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_FIXED, fd, 0);
	if (!map2) {
		perror("mmap 2");
		munmap((void *)map1, PAGE_SIZE);
		close(fd);
		return 5;
	}
	
	printf("Mapped page twice, at 0x%08lx and 0x%08lx\n", 
	       (unsigned long)map1, (unsigned long) map2);

	/* Some arches (ARM) allocate cache lines only on read */
	(void)map1[0];
	(void)map2[0];

	map1[0] = 0x55;
	map2[1] = 0xaa;
	map1[2] = 0xa5;
	map2[3] = 0x5a;

	b[0] = map2[0];
	b[1] = map1[1];
	b[2] = map2[2];
	b[3] = map1[3];

	if (b[0] != 0x55 || b[1] != 0xaa || b[2] != 0xa5 || b[3] != 0x5a) {
		printf("Your cache is broken\n");
		return 6;
	} else {
		printf("Your cache appears to be OK\n");
	}

	munmap((void *)map1, PAGE_SIZE);
	munmap((void *)map2, PAGE_SIZE);
	close(fd);	
}

  parent reply	other threads:[~2001-12-03 23:46 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2001-12-01 22:03 [OT] Wrapping memory Maciej Zenczykowski
2001-12-01 22:24 ` Alan Cox
2001-12-02  1:52   ` Benjamin LaHaise
2001-12-02 10:24     ` Christoph Rohland
2001-12-02 17:53   ` David Woodhouse
2001-12-03  7:44     ` Christoph Rohland
2001-12-03  9:11     ` David Woodhouse [this message]
2001-12-04 10:40       ` Russell King
2001-12-04 16:39         ` Jamie Lokier
2001-12-04 21:03           ` Russell King
2001-12-04 10:45       ` David Woodhouse
2001-12-04 10:59         ` Russell King

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=25163.1007370678@redhat.com \
    --to=dwmw2@infradead.org \
    --cc=alan@lxorguk.ukuu.org.uk \
    --cc=cr@sap.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=maze@druid.if.uj.edu.pl \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox