# HG changeset patch # User tristan.gingold@xxxxxxxx # Node ID e3622337d7ebd4a8013a76992bf7e1b7a4b9f2ed # Parent 39086041a101cbfd7e2a097bcf37ecbffa177989 domain_cache_flush added. SAL_CACHE_FLUSH implemented. Signed-off-by: Tristan Gingold diff -r 39086041a101 -r e3622337d7eb xen/arch/ia64/linux-xen/setup.c --- a/xen/arch/ia64/linux-xen/setup.c Fri Mar 31 09:03:30 2006 +++ b/xen/arch/ia64/linux-xen/setup.c Fri Mar 31 10:44:31 2006 @@ -104,6 +104,11 @@ */ #define I_CACHE_STRIDE_SHIFT 5 /* Safest way to go: 32 bytes by 32 bytes */ unsigned long ia64_i_cache_stride_shift = ~0; + +#ifdef XEN +#define D_CACHE_STRIDE_SHIFT 5 /* Safest. */ +unsigned long ia64_d_cache_stride_shift = ~0; +#endif /* * The merge_mask variable needs to be set to (max(iommu_page_size(iommu)) - 1). This @@ -718,6 +723,9 @@ max = SMP_CACHE_BYTES; /* Safest setup for "flush_icache_range()" */ ia64_i_cache_stride_shift = I_CACHE_STRIDE_SHIFT; +#ifdef XEN + ia64_d_cache_stride_shift = D_CACHE_STRIDE_SHIFT; +#endif goto out; } @@ -733,6 +741,10 @@ cci.pcci_stride = I_CACHE_STRIDE_SHIFT; cci.pcci_unified = 1; } +#ifdef XEN + if (cci.pcci_stride < ia64_d_cache_stride_shift) + ia64_d_cache_stride_shift = cci.pcci_stride; +#endif line_size = 1 << cci.pcci_line_size; if (line_size > max) max = line_size; @@ -754,6 +766,11 @@ out: if (max > ia64_max_cacheline_size) ia64_max_cacheline_size = max; +#ifdef XEN + if (ia64_d_cache_stride_shift > ia64_i_cache_stride_shift) + ia64_d_cache_stride_shift = ia64_i_cache_stride_shift; +#endif + } /* diff -r 39086041a101 -r e3622337d7eb xen/arch/ia64/xen/Makefile --- a/xen/arch/ia64/xen/Makefile Fri Mar 31 09:03:30 2006 +++ b/xen/arch/ia64/xen/Makefile Fri Mar 31 10:44:31 2006 @@ -24,6 +24,7 @@ obj-y += xenmisc.o obj-y += xensetup.o obj-y += xentime.o +obj-y += flushd.o obj-$(crash_debug) += gdbstub.o diff -r 39086041a101 -r e3622337d7eb xen/arch/ia64/xen/dom_fw.c --- a/xen/arch/ia64/xen/dom_fw.c Fri Mar 31 09:03:30 2006 +++ b/xen/arch/ia64/xen/dom_fw.c Fri Mar 31 10:44:31 2006 @@ -176,7 +176,9 @@ printf("*** CALLED SAL_MC_SET_PARAMS. IGNORED...\n"); break; case SAL_CACHE_FLUSH: - printf("*** CALLED SAL_CACHE_FLUSH. IGNORED...\n"); + /* The best we can do is to flush with fc all the domain. */ + domain_cache_flush (current->domain, in1 == 4 ? 1 : 0); + status = 0; break; case SAL_CACHE_INIT: printf("*** CALLED SAL_CACHE_INIT. IGNORED...\n"); diff -r 39086041a101 -r e3622337d7eb xen/arch/ia64/xen/domain.c --- a/xen/arch/ia64/xen/domain.c Fri Mar 31 09:03:30 2006 +++ b/xen/arch/ia64/xen/domain.c Fri Mar 31 10:44:31 2006 @@ -674,6 +674,61 @@ return 0; } +/* Flush cache of domain d. */ +void domain_cache_flush (struct domain *d, int sync_only) +{ + struct mm_struct *mm = d->arch.mm; + pgd_t *pgd = mm->pgd; + unsigned long maddr; + int i,j,k, l; + int nbr_page = 0; + void (*flush_func)(unsigned long start, unsigned long end); + extern void flush_dcache_range (unsigned long, unsigned long); + + if (sync_only) + flush_func = &flush_icache_range; + else + flush_func = &flush_dcache_range; + +#ifdef CONFIG_DOMAIN0_CONTIGUOUS + if (d == dom0) { + /* This is not fully correct (because of hole), but it should + be enough for now. */ + (*flush_func)(__va_ul (dom0_start), + __va_ul (dom0_start + dom0_size)); + return; + } +#endif + for (i = 0; i < PTRS_PER_PGD; pgd++, i++) { + pud_t *pud; + if (!pgd_present(*pgd)) + continue; + pud = pud_offset(pgd, 0); + for (j = 0; j < PTRS_PER_PUD; pud++, j++) { + pmd_t *pmd; + if (!pud_present(*pud)) + continue; + pmd = pmd_offset(pud, 0); + for (k = 0; k < PTRS_PER_PMD; pmd++, k++) { + pte_t *pte; + if (!pmd_present(*pmd)) + continue; + pte = pte_offset_map(pmd, 0); + for (l = 0; l < PTRS_PER_PTE; pte++, l++) { + if (!pte_present(*pte)) + continue; + /* Convert PTE to maddr. */ + maddr = __va_ul (pte_val(*pte) + & _PAGE_PPN_MASK); + (*flush_func)(maddr, maddr+ PAGE_SIZE); + nbr_page++; + } + } + } + } + //printf ("domain_cache_flush: %d %d pages\n", d->domain_id, nbr_page); +} + // FIXME: ONLY USE FOR DOMAIN PAGE_SIZE == PAGE_SIZE #if 1 unsigned long domain_mpa_to_imva(struct domain *d, unsigned long mpaddr) diff -r 39086041a101 -r e3622337d7eb xen/include/asm-ia64/domain.h --- a/xen/include/asm-ia64/domain.h Fri Mar 31 09:03:30 2006 +++ b/xen/include/asm-ia64/domain.h Fri Mar 31 10:44:31 2006 @@ -12,6 +12,11 @@ #include extern void domain_relinquish_resources(struct domain *); + +/* Flush cache of domain d. + If sync_only is true, only synchronize I&D caches, + if false, flush and invalidate caches. */ +extern void domain_cache_flush (struct domain *d, int sync_only); struct arch_domain { struct mm_struct *mm; diff -r 39086041a101 -r e3622337d7eb xen/include/asm-ia64/vhpt.h --- a/xen/include/asm-ia64/vhpt.h Fri Mar 31 09:03:30 2006 +++ b/xen/include/asm-ia64/vhpt.h Fri Mar 31 10:44:31 2006 @@ -127,6 +127,7 @@ extern void vhpt_insert (unsigned long vadr, unsigned long ptr, unsigned logps); extern void vhpt_flush(void); +extern void smp_vhpt_flush_all(void); /* Currently the VHPT is allocated per CPU. */ DECLARE_PER_CPU (unsigned long, vhpt_paddr); diff -r 39086041a101 -r e3622337d7eb xen/include/asm-ia64/xenpage.h --- a/xen/include/asm-ia64/xenpage.h Fri Mar 31 09:03:30 2006 +++ b/xen/include/asm-ia64/xenpage.h Fri Mar 31 10:44:31 2006 @@ -55,6 +55,9 @@ #define __pa(x) ({xen_va _v; _v.l = (long) (x); _v.f.reg = 0; _v.l;}) #define __va(x) ({xen_va _v; _v.l = (long) (x); _v.f.reg = -1; _v.p;}) +/* It is sometimes very useful to have unsigned long as result. */ +#define __va_ul(x) ({xen_va _v; _v.l = (long) (x); _v.f.reg = -1; _v.l;}) + #undef PAGE_OFFSET #define PAGE_OFFSET __IA64_UL_CONST(0xf000000000000000) diff -r 39086041a101 -r e3622337d7eb xen/arch/ia64/xen/flushd.S --- /dev/null Fri Mar 31 09:03:30 2006 +++ b/xen/arch/ia64/xen/flushd.S Fri Mar 31 10:44:31 2006 @@ -0,0 +1,62 @@ +/* + * Cache flushing routines. + * + * Copyright (C) 1999-2001, 2005 Hewlett-Packard Co + * David Mosberger-Tang + * + * 05/28/05 Zoltan Menyhart Dynamic stride size + * 03/31/06 Tristan Gingold copied and modified for dcache. + */ + +#include + + + /* + * flush_dcache_range(start,end) + * + * Flush cache. + * + * Must deal with range from start to end-1 but nothing else (need to + * be careful not to touch addresses that may be unmapped). + * + * Note: "in0" and "in1" are preserved for debugging purposes. + */ +GLOBAL_ENTRY(flush_dcache_range) + + .prologue + alloc r2=ar.pfs,2,0,0,0 + movl r3=ia64_d_cache_stride_shift + mov r21=1 + ;; + ld8 r20=[r3] // r20: stride shift + sub r22=in1,r0,1 // last byte address + ;; + shr.u r23=in0,r20 // start / (stride size) + shr.u r22=r22,r20 // (last byte address) / (stride size) + shl r21=r21,r20 // r21: stride size of the i-cache(s) + ;; + sub r8=r22,r23 // number of strides - 1 + shl r24=r23,r20 // r24: addresses for "fc" = + // "start" rounded down to stride boundary + .save ar.lc,r3 + mov r3=ar.lc // save ar.lc + ;; + + .body + mov ar.lc=r8 + ;; + /* + * 32 byte aligned loop, even number of (actually 2) bundles + */ +.Loop: fc r24 // issuable on M0 only + add r24=r21,r24 // we flush "stride size" bytes per iteration + nop.i 0 + br.cloop.sptk.few .Loop + ;; + sync.i + ;; + srlz.i + ;; + mov ar.lc=r3 // restore ar.lc + br.ret.sptk.many rp +END(flush_dcache_range)