[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] [xen-unstable] arm: fix unaligned memcpy() and memmove()



# HG changeset patch
# User David Vrabel <david.vrabel@xxxxxxxxxx>
# Date 1330362318 0
# Node ID e4fc04c15cd71a4090f06cd1f0df66703824fcb8
# Parent  21c0c086119fea9514949ddbc4b1a17f994f2724
arm: fix unaligned memcpy() and memmove()

If memcpy() and memmove() were used with source and destination of
different alignment then the result would be all jumbled.

When their implementations were imported from Linux some macros for
big-endian platforms were taken instead of the correct little-endian
ones (specifically, the push and pull macros in assembler.h).

Fix this by taking Linux's arch/include/asm/assembler.h as-is and
making only the minimum changes necessary for Xen.

Signed-off-by: David Vrabel <david.vrabel@xxxxxxxxxx>
Acked-by: Ian Campbell <ian.campbell@xxxxxxxxxx>
Committed-by: Ian Campbell <Ian.Campbell@xxxxxxxxxx>
---


diff -r 21c0c086119f -r e4fc04c15cd7 xen/arch/arm/lib/assembler.h
--- a/xen/arch/arm/lib/assembler.h      Mon Feb 27 16:12:24 2012 +0000
+++ b/xen/arch/arm/lib/assembler.h      Mon Feb 27 17:05:18 2012 +0000
@@ -1,25 +1,24 @@
-#ifndef __ARCH_ARM_LIB_ASSEMBLER_H__
-#define __ARCH_ARM_LIB_ASSEMBLER_H__
-
 /* From Linux arch/arm/include/asm/assembler.h */
 /*
- * Data preload for architectures that support it
+ *  arch/arm/include/asm/assembler.h
+ *
+ *  Copyright (C) 1996-2000 Russell King
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ *  This file contains arm architecture specific defines
+ *  for the different processors.
+ *
+ *  Do not include any C declarations in this file - it is included by
+ *  assembler source.
  */
-#define PLD(code...)    code
+#ifndef __ASM_ASSEMBLER_H__
+#define __ASM_ASSEMBLER_H__
 
-/*
- * This can be used to enable code to cacheline align the destination
- * pointer when bulk writing to memory.  Experiments on StrongARM and
- * XScale didn't show this a worthwhile thing to do when the cache is not
- * set to write-allocate (this would need further testing on XScale when WA
- * is used).
- *
- * On Feroceon there is much to gain however, regardless of cache mode.
- */
-#ifdef CONFIG_CPU_FEROCEON /* Not in Xen... */
-#define CALGN(code...) code
-#else
-#define CALGN(code...)
+#ifndef __ASSEMBLY__
+#error "Only include this from assembly code"
 #endif
 
 // No Thumb, hence:
@@ -33,17 +32,294 @@
 #define UNWIND(code...)
 #endif
 
+/*
+ * Endian independent macros for shifting bytes within registers.
+ */
+#ifndef __ARMEB__
+#define pull            lsr
+#define push            lsl
+#define get_byte_0      lsl #0
+#define get_byte_1     lsr #8
+#define get_byte_2     lsr #16
+#define get_byte_3     lsr #24
+#define put_byte_0      lsl #0
+#define put_byte_1     lsl #8
+#define put_byte_2     lsl #16
+#define put_byte_3     lsl #24
+#else
 #define pull            lsl
 #define push            lsr
-#define get_byte_0      lsr #24
-#define get_byte_1      lsr #16
-#define get_byte_2      lsr #8
+#define get_byte_0     lsr #24
+#define get_byte_1     lsr #16
+#define get_byte_2     lsr #8
 #define get_byte_3      lsl #0
-#define put_byte_0      lsl #24
-#define put_byte_1      lsl #16
-#define put_byte_2      lsl #8
+#define put_byte_0     lsl #24
+#define put_byte_1     lsl #16
+#define put_byte_2     lsl #8
 #define put_byte_3      lsl #0
+#endif
 
-#define smp_dmb dmb
+/*
+ * Data preload for architectures that support it
+ */
+#if __LINUX_ARM_ARCH__ >= 5
+#define PLD(code...)   code
+#else
+#define PLD(code...)
+#endif
 
-#endif /*  __ARCH_ARM_LIB_ASSEMBLER_H__ */
+/*
+ * This can be used to enable code to cacheline align the destination
+ * pointer when bulk writing to memory.  Experiments on StrongARM and
+ * XScale didn't show this a worthwhile thing to do when the cache is not
+ * set to write-allocate (this would need further testing on XScale when WA
+ * is used).
+ *
+ * On Feroceon there is much to gain however, regardless of cache mode.
+ */
+#ifdef CONFIG_CPU_FEROCEON
+#define CALGN(code...) code
+#else
+#define CALGN(code...)
+#endif
+
+/*
+ * Enable and disable interrupts
+ */
+#if __LINUX_ARM_ARCH__ >= 6
+       .macro  disable_irq_notrace
+       cpsid   i
+       .endm
+
+       .macro  enable_irq_notrace
+       cpsie   i
+       .endm
+#else
+       .macro  disable_irq_notrace
+       msr     cpsr_c, #PSR_I_BIT | SVC_MODE
+       .endm
+
+       .macro  enable_irq_notrace
+       msr     cpsr_c, #SVC_MODE
+       .endm
+#endif
+
+       .macro asm_trace_hardirqs_off
+#if defined(CONFIG_TRACE_IRQFLAGS)
+       stmdb   sp!, {r0-r3, ip, lr}
+       bl      trace_hardirqs_off
+       ldmia   sp!, {r0-r3, ip, lr}
+#endif
+       .endm
+
+       .macro asm_trace_hardirqs_on_cond, cond
+#if defined(CONFIG_TRACE_IRQFLAGS)
+       /*
+        * actually the registers should be pushed and pop'd conditionally, but
+        * after bl the flags are certainly clobbered
+        */
+       stmdb   sp!, {r0-r3, ip, lr}
+       bl\cond trace_hardirqs_on
+       ldmia   sp!, {r0-r3, ip, lr}
+#endif
+       .endm
+
+       .macro asm_trace_hardirqs_on
+       asm_trace_hardirqs_on_cond al
+       .endm
+
+       .macro disable_irq
+       disable_irq_notrace
+       asm_trace_hardirqs_off
+       .endm
+
+       .macro enable_irq
+       asm_trace_hardirqs_on
+       enable_irq_notrace
+       .endm
+/*
+ * Save the current IRQ state and disable IRQs.  Note that this macro
+ * assumes FIQs are enabled, and that the processor is in SVC mode.
+ */
+       .macro  save_and_disable_irqs, oldcpsr
+       mrs     \oldcpsr, cpsr
+       disable_irq
+       .endm
+
+/*
+ * Restore interrupt state previously stored in a register.  We don't
+ * guarantee that this will preserve the flags.
+ */
+       .macro  restore_irqs_notrace, oldcpsr
+       msr     cpsr_c, \oldcpsr
+       .endm
+
+       .macro restore_irqs, oldcpsr
+       tst     \oldcpsr, #PSR_I_BIT
+       asm_trace_hardirqs_on_cond eq
+       restore_irqs_notrace \oldcpsr
+       .endm
+
+#define USER(x...)                             \
+9999:  x;                                      \
+       .pushsection __ex_table,"a";            \
+       .align  3;                              \
+       .long   9999b,9001f;                    \
+       .popsection
+
+#ifdef CONFIG_SMP
+#define ALT_SMP(instr...)                                      \
+9998:  instr
+/*
+ * Note: if you get assembler errors from ALT_UP() when building with
+ * CONFIG_THUMB2_KERNEL, you almost certainly need to use
+ * ALT_SMP( W(instr) ... )
+ */
+#define ALT_UP(instr...)                                       \
+       .pushsection ".alt.smp.init", "a"                       ;\
+       .long   9998b                                           ;\
+9997:  instr                                                   ;\
+       .if . - 9997b != 4                                      ;\
+               .error "ALT_UP() content must assemble to exactly 4 bytes";\
+       .endif                                                  ;\
+       .popsection
+#define ALT_UP_B(label)                                        \
+       .equ    up_b_offset, label - 9998b                      ;\
+       .pushsection ".alt.smp.init", "a"                       ;\
+       .long   9998b                                           ;\
+       W(b)    . + up_b_offset                                 ;\
+       .popsection
+#else
+#define ALT_SMP(instr...)
+#define ALT_UP(instr...) instr
+#define ALT_UP_B(label) b label
+#endif
+
+/*
+ * Instruction barrier
+ */
+       .macro  instr_sync
+#if __LINUX_ARM_ARCH__ >= 7
+       isb
+#elif __LINUX_ARM_ARCH__ == 6
+       mcr     p15, 0, r0, c7, c5, 4
+#endif
+       .endm
+
+/*
+ * SMP data memory barrier
+ */
+       .macro  smp_dmb mode
+#ifdef CONFIG_SMP
+#if __LINUX_ARM_ARCH__ >= 7
+       .ifeqs "\mode","arm"
+       ALT_SMP(dmb)
+       .else
+       ALT_SMP(W(dmb))
+       .endif
+#elif __LINUX_ARM_ARCH__ == 6
+       ALT_SMP(mcr     p15, 0, r0, c7, c10, 5) @ dmb
+#else
+#error Incompatible SMP platform
+#endif
+       .ifeqs "\mode","arm"
+       ALT_UP(nop)
+       .else
+       ALT_UP(W(nop))
+       .endif
+#endif
+       .endm
+
+#ifdef CONFIG_THUMB2_KERNEL
+       .macro  setmode, mode, reg
+       mov     \reg, #\mode
+       msr     cpsr_c, \reg
+       .endm
+#else
+       .macro  setmode, mode, reg
+       msr     cpsr_c, #\mode
+       .endm
+#endif
+
+/*
+ * STRT/LDRT access macros with ARM and Thumb-2 variants
+ */
+#ifdef CONFIG_THUMB2_KERNEL
+
+       .macro  usraccoff, instr, reg, ptr, inc, off, cond, abort, t=T()
+9999:
+       .if     \inc == 1
+       \instr\cond\()b\()\t\().w \reg, [\ptr, #\off]
+       .elseif \inc == 4
+       \instr\cond\()\t\().w \reg, [\ptr, #\off]
+       .else
+       .error  "Unsupported inc macro argument"
+       .endif
+
+       .pushsection __ex_table,"a"
+       .align  3
+       .long   9999b, \abort
+       .popsection
+       .endm
+
+       .macro  usracc, instr, reg, ptr, inc, cond, rept, abort
+       @ explicit IT instruction needed because of the label
+       @ introduced by the USER macro
+       .ifnc   \cond,al
+       .if     \rept == 1
+       itt     \cond
+       .elseif \rept == 2
+       ittt    \cond
+       .else
+       .error  "Unsupported rept macro argument"
+       .endif
+       .endif
+
+       @ Slightly optimised to avoid incrementing the pointer twice
+       usraccoff \instr, \reg, \ptr, \inc, 0, \cond, \abort
+       .if     \rept == 2
+       usraccoff \instr, \reg, \ptr, \inc, \inc, \cond, \abort
+       .endif
+
+       add\cond \ptr, #\rept * \inc
+       .endm
+
+#else  /* !CONFIG_THUMB2_KERNEL */
+
+       .macro  usracc, instr, reg, ptr, inc, cond, rept, abort, t=T()
+       .rept   \rept
+9999:
+       .if     \inc == 1
+       \instr\cond\()b\()\t \reg, [\ptr], #\inc
+       .elseif \inc == 4
+       \instr\cond\()\t \reg, [\ptr], #\inc
+       .else
+       .error  "Unsupported inc macro argument"
+       .endif
+
+       .pushsection __ex_table,"a"
+       .align  3
+       .long   9999b, \abort
+       .popsection
+       .endr
+       .endm
+
+#endif /* CONFIG_THUMB2_KERNEL */
+
+       .macro  strusr, reg, ptr, inc, cond=al, rept=1, abort=9001f
+       usracc  str, \reg, \ptr, \inc, \cond, \rept, \abort
+       .endm
+
+       .macro  ldrusr, reg, ptr, inc, cond=al, rept=1, abort=9001f
+       usracc  ldr, \reg, \ptr, \inc, \cond, \rept, \abort
+       .endm
+
+/* Utility macro for declaring string literals */
+       .macro  string name:req, string
+       .type \name , #object
+\name:
+       .asciz "\string"
+       .size \name , . - \name
+       .endm
+
+#endif /* __ASM_ASSEMBLER_H__ */

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.