Subject: Curious limitation in copy_from_user()

From: Tom Roberts <[email-masked]>
Date: Fri, 26 May 2000 15:30:13 -0500

While porting Linux PPC to my hardware, I discovered a curious
limitation in copy_from_user() -- it cannot handle uncached memory.
I had mapped some main memory as uncached (using a BAT) because it
is a communication buffer to the host (this is an ISA peripheral
board with a PPC604 on it, and I'm trying to get Linux up on the 604;
this was inside my console driver).

Note that copy_to_user() does not have this limitation -- basically
copy_tofrom_user() is using dcbz-s to improve performance, so if the
destination is uncached you get an exception in the kernel. My first
workaround was simply to do a two-stage copy via a tmp[] buffer on
the stack. Then I did it right by writing a cache_flush() routine
and referencing the buffer via the usual (cached) kernel virtual
address. Of course I called cache_flush() before copy_to_user from
the host->board buffer, and called cache_flush() after copy_from_user
to the board->host buffer (because the host can only reference
physical memory, not the 604's cache).

	Note that in an SMP configuration you need to lock the buffer
	from other CPUs. In my case there is only one 604, and each
	buffer is dedicated to one-way traffic, so no locking is needed.

I still need the uncached address to reference the queue pointers,
but that is done using simple pointer dereferencing and is OK.

Tom Roberts	[email-masked]

** Sent via the linuxppc-embedded mail list. See http://lists.linuxppc.org/