[POWERPC] vdso: Fixes for cache block sizes
authorOlof Johansson <olof@lixom.net>
Tue, 20 Nov 2007 01:24:45 +0000 (12:24 +1100)
committerPaul Mackerras <paulus@samba.org>
Tue, 20 Nov 2007 02:56:31 +0000 (13:56 +1100)
The current VDSO implementation is hardcoded to 128 byte cache blocks,
which are only used on IBM's 64-bit processors.

Convert it to get the cache block sizes out of vdso_data instead,
similar to how the ppc64 in-kernel cache flush does it.

Signed-off-by: Olof Johansson <olof@lixom.net>
Signed-off-by: Paul Mackerras <paulus@samba.org>
arch/powerpc/kernel/asm-offsets.c
arch/powerpc/kernel/vdso.c
arch/powerpc/kernel/vdso32/cacheflush.S
arch/powerpc/kernel/vdso64/cacheflush.S
include/asm-powerpc/vdso_datapage.h

index 2c8e756d19a39846db6f9c986dcce7ebbd099c39..d67bcd84f32966b50e9745cb847d092dee415556 100644 (file)
@@ -284,6 +284,10 @@ int main(void)
        DEFINE(CFG_SYSCALL_MAP32, offsetof(struct vdso_data, syscall_map_32));
        DEFINE(WTOM_CLOCK_SEC, offsetof(struct vdso_data, wtom_clock_sec));
        DEFINE(WTOM_CLOCK_NSEC, offsetof(struct vdso_data, wtom_clock_nsec));
+       DEFINE(CFG_ICACHE_BLOCKSZ, offsetof(struct vdso_data, icache_block_size));
+       DEFINE(CFG_DCACHE_BLOCKSZ, offsetof(struct vdso_data, dcache_block_size));
+       DEFINE(CFG_ICACHE_LOGBLOCKSZ, offsetof(struct vdso_data, icache_log_block_size));
+       DEFINE(CFG_DCACHE_LOGBLOCKSZ, offsetof(struct vdso_data, dcache_log_block_size));
 #ifdef CONFIG_PPC64
        DEFINE(CFG_SYSCALL_MAP64, offsetof(struct vdso_data, syscall_map_64));
        DEFINE(TVAL64_TV_SEC, offsetof(struct timeval, tv_sec));
index 2322ba5cce4ce23c3eca48336686518671d05283..3702df7dc567e160f08cfe09b5b825b5298a0f94 100644 (file)
@@ -699,11 +699,22 @@ static int __init vdso_init(void)
        vdso_data->icache_size = ppc64_caches.isize;
        vdso_data->icache_line_size = ppc64_caches.iline_size;
 
+       /* XXXOJN: Blocks should be added to ppc64_caches and used instead */
+       vdso_data->dcache_block_size = ppc64_caches.dline_size;
+       vdso_data->icache_block_size = ppc64_caches.iline_size;
+       vdso_data->dcache_log_block_size = ppc64_caches.log_dline_size;
+       vdso_data->icache_log_block_size = ppc64_caches.log_iline_size;
+
        /*
         * Calculate the size of the 64 bits vDSO
         */
        vdso64_pages = (&vdso64_end - &vdso64_start) >> PAGE_SHIFT;
        DBG("vdso64_kbase: %p, 0x%x pages\n", vdso64_kbase, vdso64_pages);
+#else
+       vdso_data->dcache_block_size = L1_CACHE_BYTES;
+       vdso_data->dcache_log_block_size = L1_CACHE_SHIFT;
+       vdso_data->icache_block_size = L1_CACHE_BYTES;
+       vdso_data->icache_log_block_size = L1_CACHE_SHIFT;
 #endif /* CONFIG_PPC64 */
 
 
index 9cb319992c3888dab15552977dab9dd4e0c4ec6e..1ba6feb71b313fd1b1208cc827f617a8f2692390 100644 (file)
  *
  * Flushes the data cache & invalidate the instruction cache for the
  * provided range [start, end[
- *
- * Note: all CPUs supported by this kernel have a 128 bytes cache
- * line size so we don't have to peek that info from the datapage
  */
 V_FUNCTION_BEGIN(__kernel_sync_dicache)
   .cfi_startproc
-       li      r5,127
-       andc    r6,r3,r5                /* round low to line bdy */
+       mflr    r12
+  .cfi_register lr,r12
+       mr      r11,r3
+       bl      __get_datapage@local
+       mtlr    r12
+       mr      r10,r3
+
+       lwz     r7,CFG_DCACHE_BLOCKSZ(r10)
+       addi    r5,r7,-1
+       andc    r6,r11,r5               /* round low to line bdy */
        subf    r8,r6,r4                /* compute length */
        add     r8,r8,r5                /* ensure we get enough */
-       srwi.   r8,r8,7                 /* compute line count */
+       lwz     r9,CFG_DCACHE_LOGBLOCKSZ(r10)
+       srw.    r8,r8,r9                /* compute line count */
        crclr   cr0*4+so
        beqlr                           /* nothing to do? */
        mtctr   r8
-       mr      r3,r6
-1:     dcbst   0,r3
-       addi    r3,r3,128
+1:     dcbst   0,r6
+       add     r6,r6,r7
        bdnz    1b
        sync
+
+/* Now invalidate the instruction cache */
+
+       lwz     r7,CFG_ICACHE_BLOCKSZ(r10)
+       addi    r5,r7,-1
+       andc    r6,r11,r5               /* round low to line bdy */
+       subf    r8,r6,r4                /* compute length */
+       add     r8,r8,r5
+       lwz     r9,CFG_ICACHE_LOGBLOCKSZ(r10)
+       srw.    r8,r8,r9                /* compute line count */
+       crclr   cr0*4+so
+       beqlr                           /* nothing to do? */
        mtctr   r8
-1:     icbi    0,r6
-       addi    r6,r6,128
-       bdnz    1b
+2:     icbi    0,r6
+       add     r6,r6,r7
+       bdnz    2b
        isync
        li      r3,0
        blr
index 66a36d3cc6ad13ae02173f6b41a52fba3e043086..69c5af2b3c96cfd46a85a2c250a9727e585fcabf 100644 (file)
  *
  * Flushes the data cache & invalidate the instruction cache for the
  * provided range [start, end[
- *
- * Note: all CPUs supported by this kernel have a 128 bytes cache
- * line size so we don't have to peek that info from the datapage
  */
 V_FUNCTION_BEGIN(__kernel_sync_dicache)
   .cfi_startproc
-       li      r5,127
-       andc    r6,r3,r5                /* round low to line bdy */
+       mflr    r12
+  .cfi_register lr,r12
+       mr      r11,r3
+       bl      V_LOCAL_FUNC(__get_datapage)
+       mtlr    r12
+       mr      r10,r3
+
+       lwz     r7,CFG_DCACHE_BLOCKSZ(r10)
+       addi    r5,r7,-1
+       andc    r6,r11,r5               /* round low to line bdy */
        subf    r8,r6,r4                /* compute length */
        add     r8,r8,r5                /* ensure we get enough */
-       srwi.   r8,r8,7                 /* compute line count */
+       lwz     r9,CFG_DCACHE_LOGBLOCKSZ(r10)
+       srw.    r8,r8,r9                /* compute line count */
        crclr   cr0*4+so
        beqlr                           /* nothing to do? */
        mtctr   r8
-       mr      r3,r6
-1:     dcbst   0,r3
-       addi    r3,r3,128
+1:     dcbst   0,r6
+       add     r6,r6,r7
        bdnz    1b
        sync
+
+/* Now invalidate the instruction cache */
+
+       lwz     r7,CFG_ICACHE_BLOCKSZ(r10)
+       addi    r5,r7,-1
+       andc    r6,r11,r5               /* round low to line bdy */
+       subf    r8,r6,r4                /* compute length */
+       add     r8,r8,r5
+       lwz     r9,CFG_ICACHE_LOGBLOCKSZ(r10)
+       srw.    r8,r8,r9                /* compute line count */
+       crclr   cr0*4+so
+       beqlr                           /* nothing to do? */
        mtctr   r8
-1:     icbi    0,r6
-       addi    r6,r6,128
-       bdnz    1b
+2:     icbi    0,r6
+       add     r6,r6,r7
+       bdnz    2b
        isync
        li      r3,0
        blr
index 8a94f0eba5e98afd1621e6ec9ec17015ceaae64b..f01393224b52dfe66ad88ef3bedad00f49a7fca4 100644 (file)
@@ -77,6 +77,10 @@ struct vdso_data {
        /* those additional ones don't have to be located anywhere
         * special as they were not part of the original systemcfg
         */
+       __u32 dcache_block_size;                /* L1 d-cache block size     */
+       __u32 icache_block_size;                /* L1 i-cache block size     */
+       __u32 dcache_log_block_size;            /* L1 d-cache log block size */
+       __u32 icache_log_block_size;            /* L1 i-cache log block size */
        __s32 wtom_clock_sec;                   /* Wall to monotonic clock */
        __s32 wtom_clock_nsec;
        __u32 syscall_map_64[SYSCALL_MAP_SIZE]; /* map of syscalls  */
@@ -99,6 +103,10 @@ struct vdso_data {
        __s32 wtom_clock_sec;                   /* Wall to monotonic clock */
        __s32 wtom_clock_nsec;
        __u32 syscall_map_32[SYSCALL_MAP_SIZE]; /* map of syscalls */
+       __u32 dcache_block_size;        /* L1 d-cache block size     */
+       __u32 icache_block_size;        /* L1 i-cache block size     */
+       __u32 dcache_log_block_size;    /* L1 d-cache log block size */
+       __u32 icache_log_block_size;    /* L1 i-cache log block size */
 };
 
 #endif /* CONFIG_PPC64 */