allocating uncachable memory

18 messages, 6 authors, 2000-08-29 · open the first message on its own page

allocating uncachable memory

From: Ronald Wahl <hidden>
Date: 2000-08-23 13:50:26

Hi,

I'm writing a driver for a PCI controller in a PPC system. That driver
"exports" a bit of local ram into the PCI space. Now if some PCI device is
writing into this memory the local system won't notice it in all cases
since this memory is cached. How can i allocate uncached memory in linux?
Or if this does not work how can I remap it as non-cachable. I already
tried ioremap_nocache but this does not work for real memory. It would be
nice if someone could give me a short code fragment...

thanx,
ron


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

Re: allocating uncachable memory

From: Benjamin Herrenschmidt <hidden>
Date: 2000-08-23 14:03:27

I'm writing a driver for a PCI controller in a PPC system. That driver
"exports" a bit of local ram into the PCI space. Now if some PCI device is
writing into this memory the local system won't notice it in all cases
since this memory is cached. How can i allocate uncached memory in linux?
Or if this does not work how can I remap it as non-cachable. I already
tried ioremap_nocache but this does not work for real memory. It would be
nice if someone could give me a short code fragment...
Depending on the host PCI controller, the machine will or will not be
cache-coherent. Most PPC machines out there (all PCI PPC machines) are,
AFAIK, cache coherents. PPC NuBus powermacs are not. That means that any
access done to memory from the PCI is "snooped" by the CPU and the cache
is kept up-to-date.

There are routines in 2.4 for allocating PCI "consistent" memory (will be
uncached on archs that are not coherent and normal on others). See
pci_alloc_consistent() or something like that (I don't have my kernel
sources with me).


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

Re: allocating uncachable memory

From: Gabriel Paubert <hidden>
Date: 2000-08-23 14:11:11

On Wed, 23 Aug 2000, Ronald Wahl wrote:
Hi,

I'm writing a driver for a PCI controller in a PPC system. That driver
"exports" a bit of local ram into the PCI space. Now if some PCI device is
writing into this memory the local system won't notice it in all cases
Yes, it will notice, unless there is a _serious_ bug in the host bridge.
Accesses from the bridge to memory are snooped by the processor and the
relevant cache lines are invalidated if necessary.

The sequence is the following:

- the PCI device requests the bus,

- the PCI device becomes the master on the bus,

- it puts an address and then data onto the (multiplexed) PCI bus,

- the host bridge writes the data to system RAM at the specified address
(beware of the difference between kernel, physical and PCI bus addresses),
but before doing this the bridge signals the processor to invalidate or
push to memory the corresponding cache lines.

There is still a race with this kind of protocol: you need to read a
register of you device in order to flush the buffers which might hold
data on its way to memory in the host bridge.

Note that many devices (network and disk interfaces to start with) just do
this, they write directly to system RAM through the host bridge.
since this memory is cached. How can i allocate uncached memory in linux?
You don't need to, note that on some architectures you would have to flush
the cache to avoid stale data. It's not the case on PPC.
Or if this does not work how can I remap it as non-cachable. I already
tried ioremap_nocache but this does not work for real memory. It would be
nice if someone could give me a short code fragment...
Here is the code, guaranteed 100% bug-free ;-):

========================== CUT here ======================================

========================== CUT here ======================================


	Regards,
	Gabriel.


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

Re: allocating uncachable memory

From: Dan Malek <hidden>
Date: 2000-08-23 17:37:39

Benjamin Herrenschmidt wrote:
... Most PPC machines out there (all PCI PPC machines) are,
AFAIK, cache coherents. PPC NuBus powermacs are not.

The MPC8xx and IBM 4xx systems can have PCI options but are not
cache coherent.  PCI masters are still challenging (if you can actually
get them to work :-).


	-- Dan

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

Re: allocating uncachable memory

From: Ronald Wahl <hidden>
Date: 2000-08-24 07:42:53

On Wed, 23 Aug 2000, Dan Malek wrote:
Benjamin Herrenschmidt wrote:
quoted
... Most PPC machines out there (all PCI PPC machines) are,
AFAIK, cache coherents. PPC NuBus powermacs are not.

The MPC8xx and IBM 4xx systems can have PCI options but are not
cache coherent.  PCI masters are still challenging (if you can actually
get them to work :-).
It's an MPC860 together with an PLX 9054 PCI Controller. The effect is
that most of the data is correct but sometimes the MPC860 seems to get
wrong data. Looks like more than a race condition than a cache side
effect, but I'm not sure.

ron


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

Re: allocating uncachable memory

From: Ronald Wahl <hidden>
Date: 2000-08-24 09:14:58

On Wed, 23 Aug 2000, Gabriel Paubert wrote:
On Wed, 23 Aug 2000, Ronald Wahl wrote:
quoted
I'm writing a driver for a PCI controller in a PPC system. That driver
"exports" a bit of local ram into the PCI space. Now if some PCI device is
writing into this memory the local system won't notice it in all cases
Yes, it will notice, unless there is a _serious_ bug in the host bridge.
Accesses from the bridge to memory are snooped by the processor and the
relevant cache lines are invalidated if necessary.

The sequence is the following:

- the PCI device requests the bus,

- the PCI device becomes the master on the bus,

- it puts an address and then data onto the (multiplexed) PCI bus,

- the host bridge writes the data to system RAM at the specified address
(beware of the difference between kernel, physical and PCI bus addresses),
but before doing this the bridge signals the processor to invalidate or
push to memory the corresponding cache lines.

There is still a race with this kind of protocol: you need to read a
register of you device in order to flush the buffers which might hold
data on its way to memory in the host bridge.
What register? How do i flush the FIFOs of the PLX 9054? I played around
with the MARBR register but with no success so far. Maybe this register is
only used together with DMA but I need a flush mechanism that works w/o
DMA.
Here is the code, guaranteed 100% bug-free ;-):

========================== CUT here ======================================

========================== CUT here ======================================
Haha. :-)

ron


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

Re: allocating uncachable memory

From: Ronald Wahl <hidden>
Date: 2000-08-25 07:12:06

On Thu, 24 Aug 2000, Ronald Wahl wrote:
On Wed, 23 Aug 2000, Dan Malek wrote:
quoted
Benjamin Herrenschmidt wrote:
quoted
... Most PPC machines out there (all PCI PPC machines) are,
AFAIK, cache coherents. PPC NuBus powermacs are not.

The MPC8xx and IBM 4xx systems can have PCI options but are not
cache coherent.  PCI masters are still challenging (if you can actually
get them to work :-).
It's an MPC860 together with an PLX 9054 PCI Controller. The effect is
that most of the data is correct but sometimes the MPC860 seems to get
wrong data. Looks like more than a race condition than a cache side
effect, but I'm not sure.
After some further tests I found out that it is the data cache of the
MPC860. If I switch the data cache off in head.S all goes well. So my
question again: How can I get an alias mapping (with _PAGE_NO_CACHE |
_PAGE_GUARDED) of some already mapped pages.
...or can I mark pages as non-cacheable w/o alias mapping?

thx,
ron


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

Re: allocating uncachable memory

From: Dan Malek <hidden>
Date: 2000-08-25 17:39:14

Ronald Wahl wrote:

After some further tests I found out that it is the data cache of the
MPC860.
Yep.
..... So my
question again: How can I get an alias mapping (with _PAGE_NO_CACHE |
_PAGE_GUARDED) of some already mapped pages.
There isn't anything generic right now.  A few of us are working on
a solution, as there are other processors affected (IBM 4xx) as well.
If you look at the uart or Ethernet drivers, you will notice they
allocate pages of memory, track down the PTEs and set the attributes
directly.  You can use that as an example.

Don't forget that managing the caches in software (via flushes and
invalidates) could actually provide better performance for data
transfers due to the cache bursting available when caches are enabled.


	-- Dan

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

Re: allocating uncachable memory

From: Roman Zippel <hidden>
Date: 2000-08-26 16:34:41

Hi,
There isn't anything generic right now.  A few of us are working on
a solution, as there are other processors affected (IBM 4xx) as well.
IMO the only portable solution would be a memremap (similiar to ioremap).
Don't forget that managing the caches in software (via flushes and
invalidates) could actually provide better performance for data
transfers due to the cache bursting available when caches are enabled.
Sure? Often you don't want io data in the cache at all. io is mostly slow
and you have to wait anyway. On the other hand such stuff is also a horror
to debug.

bye, Roman.


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

Re: allocating uncachable memory

From: Dan Malek <hidden>
Date: 2000-08-27 19:46:02

Roman Zippel wrote:
IMO the only portable solution would be a memremap (similiar to ioremap).
Coming up with a function name and actually implementing it are two
very different things......ioremap() should do the right thing.
There are also many other issues associated with the macros
bus_to_virt() and virt_to_bus() that are challenging.
Sure?
Yes I am sure.  Bursting data over the bus is hell of a lot faster,
especially in this case where the PCI bridge can combine these into
a PCI burst transfer as well.


	-- Dan

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

Re: allocating uncachable memory

From: Roman Zippel <hidden>
Date: 2000-08-27 21:26:53

Hi,
Coming up with a function name and actually implementing it are two
very different things......ioremap() should do the right thing.
If you mark the page(s) as reserved it should already do the right thing
on most architectures. The only problem is ioremap doesn't take an array
of pages.
Another possibility is __vmalloc(), that already has a protection
argument and you only need a virt_to_xxx() to get the address of the
allocated pages.
quoted
Sure?
Yes I am sure.  Bursting data over the bus is hell of a lot faster,
especially in this case where the PCI bridge can combine these into
a PCI burst transfer as well.
This mostly useful for stuff like framebuffers, where you have only one or
two copy functions, where the required complexity is concentrated.


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

Re: allocating uncachable memory

From: Dan Malek <hidden>
Date: 2000-08-27 22:52:05

Roman Zippel wrote:
If you mark the page(s) as reserved it should already do the right thing
on most architectures. The only problem is ioremap doesn't take an array
of pages.
Hmmm...I thought reserved didn't imply that much information.  The 8xx
allocates some memory early to get is reserved, but you still have to
perform the PTE updates to get the cache attributes.
Another possibility is __vmalloc(), that already has a protection
argument and you only need a virt_to_xxx() to get the address of the
allocated pages.
That's the current plan.  If all you need is virt_to_xxx() it's easy.
The xxx_to_virt() is nearly impossible.  I have a VM implementation that
uses (or tries to) mixed large pages, but all of the existing assumptions
about memory mapping fail.  Everything will have to vmalloc() and then
use virt_to_xxx/xxx_to_virt() (which are much more than simple addition
macros).  I'm waiting for some of the PCI mapping discussions to make
sufficient changes to the I/O subsystem so I can just use those.


	-- Dan

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

Re: allocating uncachable memory

From: Ronald Wahl <hidden>
Date: 2000-08-28 12:05:44

On Fri, 25 Aug 2000, Dan Malek wrote:
quoted
question again: How can I get an alias mapping (with _PAGE_NO_CACHE |
_PAGE_GUARDED) of some already mapped pages.
There isn't anything generic right now.  A few of us are working on
a solution, as there are other processors affected (IBM 4xx) as well.
If you look at the uart or Ethernet drivers, you will notice they
allocate pages of memory, track down the PTEs and set the attributes
directly.  You can use that as an example.

Don't forget that managing the caches in software (via flushes and
invalidates) could actually provide better performance for data
transfers due to the cache bursting available when caches are enabled.
Yeah, that's what i do currently. But I had to write an
invalidate_dcache_range() first. I used the code of
flush_dcache_range() and replaced dcbst by dcbi. Now it
seems to work. Thanks for this hint, Dan.

ron


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

Re: allocating uncachable memory

From: Dan Malek <hidden>
Date: 2000-08-28 15:25:42

Ronald Wahl wrote:
... But I had to write an
invalidate_dcache_range() first.
What kernel are you using?  This should have been there, the
Ethernet driver does this......


	-- Dan

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

Re: allocating uncachable memory

From: Roman Zippel <hidden>
Date: 2000-08-28 20:04:46

Hi,
quoted
If you mark the page(s) as reserved it should already do the right thing
on most architectures. The only problem is ioremap doesn't take an array
of pages.
Hmmm...I thought reserved didn't imply that much information.  The 8xx
allocates some memory early to get is reserved, but you still have to
perform the PTE updates to get the cache attributes.
It's only needed because iounmap would otherwise also automatically free
the pages (since it simply calls vfree()).
quoted
Another possibility is __vmalloc(), that already has a protection
argument and you only need a virt_to_xxx() to get the address of the
allocated pages.
That's the current plan.  If all you need is virt_to_xxx() it's easy.
The xxx_to_virt() is nearly impossible.
xxx_to_virt() is completly impossible (with a decent performance) and IMO
shouldn't be needed. It's similiar to ioremap() - the driver has to
remember both, what of course is more complex with more pages.
If there is room in the page (e.g. at the end), it should also be possible
to do:

	kerneladdr = phys_to_virt(physaddr);
	virtaddr = kerneladdr->virtaddr;
	invalidate_cache(kerneladdr);

after that the driver can continue using the uncached virtual address.
I'm waiting for some of the PCI mapping discussions to make
sufficient changes to the I/O subsystem so I can just use those.
Usually one simply posts a patch and gets flamed to death, but then you
mostly get the best answers :-), where discussions without patches (that
could endanger the source) often lead nowhere...

bye, Roman


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

Re: allocating uncachable memory

From: Dan Malek <hidden>
Date: 2000-08-28 20:34:42

Roman Zippel wrote:
xxx_to_virt() is completly impossible (with a decent performance) and IMO
shouldn't be needed.
Well......there are many devices that perform DMA and must know the
physical address that is often stored in some kind of device descriptor.
I have written drivers that convert back and forth to get this
information.  You would have to keep the address mappings in the
driver somehow.
Usually one simply posts a patch and gets flamed to death,....
Yeah, and I am usually the one doing the flaming, because I won't
check anything into a kernel tree that doesn't work.



	-- Dan

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

Re: allocating uncachable memory

From: Roman Zippel <hidden>
Date: 2000-08-28 21:33:45

Hi,
Well......there are many devices that perform DMA and must know the
physical address that is often stored in some kind of device descriptor.
I have written drivers that convert back and forth to get this
information.  You would have to keep the address mappings in the
driver somehow.
Hmm, I only know one driver, where such stuff is needed, but due to lack
of such hardware I never had to deal with this myself.
Anyway, actually in the new page structure there are two fields that are
AFAIK only used by the page cache - mapping and index. With that you can
do a very fast physical to virtual (uncached) translation. (Ok, I take
back that it's impossible :) )

bye, Roman


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

Re: allocating uncachable memory

From: Ronald Wahl <hidden>
Date: 2000-08-29 07:29:56

On Mon, 28 Aug 2000, Dan Malek wrote:
Ronald Wahl wrote:
quoted
... But I had to write an
invalidate_dcache_range() first.
What kernel are you using?  This should have been there, the
Ethernet driver does this......
Hmm, it's an 2.2.13. I've seen flush_dcache_range() there but not
invalidate_dcache_range().

ron


** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help