[PATCH] mmci: call flush_dcache_page() outside of atomic kmap
From: Russell King - ARM Linux <hidden>
Date: 2011-01-01 22:13:09
On Sat, Jan 01, 2011 at 07:58:03PM +0530, Rabin Vincent wrote:
On Sat, Jan 1, 2011 at 5:35 PM, Russell King - ARM Linux [off-list ref] wrote:quoted
On Sat, Jan 01, 2011 at 04:06:08PM +0530, Rabin Vincent wrote:quoted
It's the WARN_ON(!irqs_disabled()) in sg_miter_stop(): ? ? ? ? ? ? ? ? if (miter->__flags & SG_MITER_ATOMIC) { ? ? ? ? ? ? ? ? ? ? ? ? WARN_ON(!irqs_disabled()); ? ? ? ? ? ? ? ? ? ? ? ? kunmap_atomic(miter->addr, KM_BIO_SRC_IRQ); ? ? ? ? ? ? ? ? } This is because if the cache is VIVT, flush_dcache_page() calls __flush_dcache_aliases() when a user space mapping exists. ?That function uses flush_dcache_mmap_unlock() which is spin_unlock_irq(), which enables interrupts. ? Fix this by calling flush_dcache_page() only after the sg_miter is stopped.I think there's some questions that need to be answered here first: 1. Why does this not trigger on real PB926 hardware?Normal read/write does not trigger this, it only happens when a file on the SD card is executed (in my case it first happens when a page in init's data segment is faulted in) . Has rootfs-on-SD been tried on real PB926 hardware after the conversion to the sg_miter API?quoted
2. Why the hell is a page being submitted which is mapped into userspace ? yet has not already been populated with data from the card? (2) is a serious error, what it means is that userspace can access the data which was _previously_ in the page before the page has been read with the required data.flush_dcache_page() checks mapping_mapped(page->mapping). This returns true if any pages from the file are mapped into userspace, not only if this particular page is mapped. When init starts, its text section is mapped in to user space, after which any mapping_mapped() check on any pages from init will return true. When init tries to access some data, the page is faulted in, and flush_dcache_page() on this page leads to __flush_dcache_aliases() being executed, because mapping_mapped() returned true. This page is not mapped into userspace until later (as expected).
Err, hang on. The sg iter API uses flush_kernel_dcache_page(), not flush_dcache_page(). flush_kernel_dcache_page() is not expected to touch userspace mappings. On ARM, we don't implement flush_kernel_dcache_page() because it's not required (see commit f8b63c1.) Essentially, because we now consider freshly created page cache pages dirty, we always flush them before we map them into userspace, so a call to flush_kernel_dcache_page() has nothing to do.