vserver 1.9.5.x5
[linux-2.6.git] / arch / parisc / kernel / cache.c
index 0703ab0..f46a07a 100644 (file)
@@ -33,6 +33,17 @@ int dcache_stride;
 int icache_stride;
 EXPORT_SYMBOL(dcache_stride);
 
+
+#if defined(CONFIG_SMP)
+/* On some machines (e.g. ones with the Merced bus), there can be
+ * only a single PxTLB broadcast at a time; this must be guaranteed
+ * by software.  We put a spinlock around all TLB flushes  to
+ * ensure this.
+ */
+DEFINE_SPINLOCK(pa_tlb_lock);
+EXPORT_SYMBOL(pa_tlb_lock);
+#endif
+
 struct pdc_cache_info cache_info;
 #ifndef CONFIG_PA20
 static struct pdc_btlb_info btlb_info;
@@ -44,6 +55,11 @@ flush_data_cache(void)
 {
        on_each_cpu((void (*)(void *))flush_data_cache_local, NULL, 1, 1);
 }
+void 
+flush_instruction_cache(void)
+{
+       on_each_cpu((void (*)(void *))flush_instruction_cache_local, NULL, 1, 1);
+}
 #endif
 
 void
@@ -306,3 +322,45 @@ EXPORT_SYMBOL(flush_kernel_dcache_range_asm);
 EXPORT_SYMBOL(flush_kernel_dcache_page);
 EXPORT_SYMBOL(flush_data_cache_local);
 EXPORT_SYMBOL(flush_kernel_icache_range_asm);
+
+void clear_user_page_asm(void *page, unsigned long vaddr)
+{
+       /* This function is implemented in assembly in pacache.S */
+       extern void __clear_user_page_asm(void *page, unsigned long vaddr);
+
+       purge_tlb_start();
+       __clear_user_page_asm(page, vaddr);
+       purge_tlb_end();
+}
+
+#define FLUSH_THRESHOLD 0x80000 /* 0.5MB */
+int parisc_cache_flush_threshold = FLUSH_THRESHOLD;
+
+void parisc_setup_cache_timing(void)
+{
+       unsigned long rangetime, alltime;
+       extern char _text;      /* start of kernel code, defined by linker */
+       extern char _end;       /* end of BSS, defined by linker */
+       unsigned long size;
+
+       alltime = mfctl(16);
+       flush_data_cache();
+       alltime = mfctl(16) - alltime;
+
+       size = (unsigned long)(&_end - _text);
+       rangetime = mfctl(16);
+       flush_kernel_dcache_range((unsigned long)&_text, size);
+       rangetime = mfctl(16) - rangetime;
+
+       printk(KERN_DEBUG "Whole cache flush %lu cycles, flushing %lu bytes %lu cycles\n",
+               alltime, size, rangetime);
+
+       /* Racy, but if we see an intermediate value, it's ok too... */
+       parisc_cache_flush_threshold = size * alltime / rangetime;
+
+       parisc_cache_flush_threshold = (parisc_cache_flush_threshold + L1_CACHE_BYTES - 1) &~ (L1_CACHE_BYTES - 1); 
+       if (!parisc_cache_flush_threshold)
+               parisc_cache_flush_threshold = FLUSH_THRESHOLD;
+
+       printk("Setting cache flush threshold to %x (%d CPUs online)\n", parisc_cache_flush_threshold, num_online_cpus());
+}