[xtensa-cvscommit] linux/arch/xtensa/mm cache.c,1.7,1.8 fault.c,1.5,1.6 mmu.c,1.6,1.7
Brought to you by:
zankel
|
From: <jn...@us...> - 2003-03-05 17:57:53
|
Update of /cvsroot/xtensa/linux/arch/xtensa/mm
In directory sc8-pr-cvs1:/tmp/cvs-serv32016/arch/xtensa/mm
Modified Files:
cache.c fault.c mmu.c
Log Message:
Fixed two fundamental problems with writeback cache plus cache
aliasing.
1) set_pte -- When writing to a pte, that pte may be mapped into the
pagetable, and it may be aliased. It's important that the
pte when written be flushed back to memory so that when the
autorefill happens, it will read the fresh copy.
It would probably be more efficient to allocate these pages of
ptes as writethru instead of writing back the line everytime
set_pte happens.
2) copy_user_page -- There are facilities to make the to and address parameters
unaliased, but there isn't for the from address. So it seems that
there is the chance that any writes that happened to the from page,
may be in a different cache line. It seems necessart to force the
data cache to be written back at this point.
Index: cache.c
===================================================================
RCS file: /cvsroot/xtensa/linux/arch/xtensa/mm/cache.c,v
retrieving revision 1.7
retrieving revision 1.8
diff -C2 -d -r1.7 -r1.8
*** cache.c 28 Feb 2003 23:18:49 -0000 1.7
--- cache.c 5 Mar 2003 17:57:44 -0000 1.8
***************
*** 180,186 ****
-
-
-
/* 20feb2003 -- jn
* some subset of these functions need to be available when
--- 180,183 ----
***************
*** 194,199 ****
--- 191,198 ----
unsigned long addr = (unsigned long) page_address(page);
unsigned long flags;
+
save_and_cli(flags);
xthal_dcache_region_writeback_inv((void *)addr, PAGE_SIZE);
+ xthal_icache_region_invalidate((void*)addr, PAGE_SIZE);
restore_flags(flags);
}
***************
*** 204,207 ****
--- 203,207 ----
{
unsigned long flags;
+
save_and_cli(flags);
#if defined(XCHAL_DCACHE_IS_WRITEBACK)
***************
*** 252,257 ****
unsigned long addr = (unsigned long) page_address(page);
unsigned long flags;
save_and_cli(flags);
! #if 1
#if defined(XCHAL_DCACHE_IS_WRITEBACK)
xthal_dcache_region_writeback_inv((void *)addr, PAGE_SIZE);
--- 252,258 ----
unsigned long addr = (unsigned long) page_address(page);
unsigned long flags;
+
save_and_cli(flags);
! #if 0
#if defined(XCHAL_DCACHE_IS_WRITEBACK)
xthal_dcache_region_writeback_inv((void *)addr, PAGE_SIZE);
***************
*** 262,268 ****
/* XTFIXME -- this is just a test, going to flush the entire cache
* cache and see if that makes it start working.
! */
// printk("flush_dcache_page: addr=0x%08x\n", addr);
! xthal_dcache_all_writeback_inv();
#endif
--- 263,270 ----
/* XTFIXME -- this is just a test, going to flush the entire cache
* cache and see if that makes it start working.
! */
// printk("flush_dcache_page: addr=0x%08x\n", addr);
! flush_cache_all();
! // xthal_dcache_all_writeback_inv();
#endif
***************
*** 274,277 ****
--- 276,298 ----
void clear_user_page(void *to, unsigned long address)
{
+ #if XCHAL_DCACHE_IS_WRITEBACK
+ unsigned long flags;
+
+ /* 03mar2003 jn
+ * I had a dream last night.... And in that dream I saw
+ * a process being copied... But the the page "from" which
+ * that process was being copied was an alias to the physical
+ * page. And with cache aliasing, the data that was being
+ * read was not in sync...
+ * Therefore, at this point, we need to flush the writeback
+ * cache before we do the copy.
+ */
+
+ save_and_cli(flags);
+ xthal_dcache_all_writeback();
+ restore_flags(flags);
+
+ #endif
+
if ( (( (unsigned long)to ^ address) & XT_CACHE_ALIAS_BITS) == 0) {
clear_page(to);
***************
*** 282,285 ****
--- 303,309 ----
unsigned long vpnval;
pte_t pteval;
+ #if XCHAL_DCACHE_IS_WRITEBACK
+ unsigned long flags;
+ #endif
new_to = new_to + (address & XT_CACHE_ALIAS_BITS);
***************
*** 289,292 ****
--- 313,327 ----
write_dtlb_entry(pteval, vpnval);
clear_page((void *)new_to);
+
+ /* XTFIXME -- would it be better to allocate the
+ * new_to pte as writethru, instead of
+ * having to writeback the cache at this
+ * point?
+ */
+ #if XCHAL_DCACHE_IS_WRITEBACK
+ save_and_cli(flags);
+ xthal_dcache_all_writeback();
+ restore_flags(flags);
+ #endif
up(&dealias_page_sem);
}
***************
*** 301,305 ****
struct page *topage = virt_to_page(to);
!
set_bit(PG_mapped, &topage->flags);
--- 336,359 ----
struct page *topage = virt_to_page(to);
! #if XCHAL_DCACHE_IS_WRITEBACK
! unsigned long flags;
!
! /* 03mar2003 jn
! * I had a dream last night.... And in that dream I saw
! * a process being copied... But the the page "from" which
! * that process was being copied was an alias to the physical
! * page. And with cache aliasing, the data that was being
! * read was not in sync...
! * Therefore, at this point, we need to flush the writeback
! * cache before we do the copy.
! */
!
! save_and_cli(flags);
! xthal_dcache_all_writeback();
! restore_flags(flags);
!
! #endif
!
!
set_bit(PG_mapped, &topage->flags);
***************
*** 307,314 ****
copy_page(to, from);
} else {
- #if 0
- copy_page(to, from);
- flush_cache_all();
- #else
unsigned long new_to = (XTENSA_ALIAS_RESERVE_START);
unsigned long vpnval;
--- 361,364 ----
***************
*** 320,326 ****
down(&dealias_page_sem);
write_dtlb_entry(pteval, vpnval);
copy_page((void *)new_to, from);
! up(&dealias_page_sem);
#endif
}
}
--- 370,393 ----
down(&dealias_page_sem);
write_dtlb_entry(pteval, vpnval);
+ #if 0
+ printk("copy_user_page: to: %p\n", to);
+ printk(" from: %p\n", from);
+ printk(" new_to: %p\n", new_to);
+ printk(" address: %p\n", address);
+ #endif
+
copy_page((void *)new_to, from);
!
! /* XTFIXME -- would it be better to allocate the
! * new_to pte as writethru, instead of
! * having to writeback the cache at this
! * point?
! */
! #if XCHAL_DCACHE_IS_WRITEBACK
! save_and_cli(flags);
! xthal_dcache_all_writeback();
! restore_flags(flags);
#endif
+ up(&dealias_page_sem);
}
}
***************
*** 336,343 ****
#endif /* XTENSA_CACHE_ALIAS */
-
-
-
-
-
--- 403,405 ----
Index: fault.c
===================================================================
RCS file: /cvsroot/xtensa/linux/arch/xtensa/mm/fault.c,v
retrieving revision 1.5
retrieving revision 1.6
diff -C2 -d -r1.5 -r1.6
*** fault.c 28 Feb 2003 01:53:09 -0000 1.5
--- fault.c 5 Mar 2003 17:57:44 -0000 1.6
***************
*** 68,72 ****
save_and_cli(flags);
#if ( XCHAL_DCACHE_IS_WRITEBACK )
! xthal_dcache_region_writeback(ptep, 4);
#endif
xthal_dcache_line_invalidate(ptevaddr);
--- 68,72 ----
save_and_cli(flags);
#if ( XCHAL_DCACHE_IS_WRITEBACK )
! xthal_dcache_line_writeback(ptep);
#endif
xthal_dcache_line_invalidate(ptevaddr);
***************
*** 74,77 ****
--- 74,78 ----
#endif
save_and_cli(flags);
+ xthal_dcache_all_writeback();
xthal_dcache_all_invalidate();
restore_flags(flags);
Index: mmu.c
===================================================================
RCS file: /cvsroot/xtensa/linux/arch/xtensa/mm/mmu.c,v
retrieving revision 1.6
retrieving revision 1.7
diff -C2 -d -r1.6 -r1.7
*** mmu.c 28 Feb 2003 01:53:09 -0000 1.6
--- mmu.c 5 Mar 2003 17:57:45 -0000 1.7
***************
*** 24,27 ****
--- 24,28 ----
/* Called from arch-indep. files: */
+
void flush_tlb_all (void)
{
***************
*** 90,93 ****
--- 91,97 ----
unsigned long flags;
int oldpid;
+
+ // !!!!
+ flush_cache_all();
#ifdef DEBUG_TLB
|