Sometimes we want to be able to load values greater than 0xff into a
register, without placing said values in a literal pool. Arranging for
the value to be split up across a number of movz and movk instructions
is tedious and error-prone.
Following the example of {adr,str,ldr}_l, this patch adds a new mov_l
macro which can be used to load immediate values of up to 64 bits into a
register.
Signed-off-by: Mark Rutland <mark.rutland@arm.com>
Cc: Ard Biesheuvel <redacted>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Marc Zyngier <redacted>
Cc: Will Deacon <redacted>
---
arch/arm64/include/asm/assembler.h | 13 +++++++++++++
1 file changed, 13 insertions(+)
@@ -193,6 +193,19 @@ lr .req x30 // link registerstr\src,[\tmp,:lo12:\sym].endm+/*+*Movealargeimmediateupto64-bits.+*+*@dst:destinationregister(64bitwide)+*@val:value+*/+.macromov_l,dst,val+movz\dst,:abs_g0_nc:\val+movk\dst,:abs_g1_nc:\val+movk\dst,:abs_g2_nc:\val+movk\dst,:abs_g3:\val+.endm+/**Annotateafunctionaspositionindependent,i.e.,safetobecalledbefore*thekernelvirtualmappingisactivated.
Currently we use an open-coded memzero to clear the BSS. As it is a
trivial implementation, it is sub-optimal.
Our optimised memset doesn't use the stack, is position-independent, and
for the memzero case can use of DC ZVA to clear large blocks
efficiently. In __mmap_switched the MMU is on and there are no live
caller-saved registers, so we can safely call an uninstrumented memset.
This patch changes __mmap_switched to use memset when clearing the BSS.
We use the __pi_memset alias so as to avoid any instrumentation in all
kernel configurations. As with the head symbols, we must get the linker
to generate __bss_size, as there is no ELF relocation for the
subtraction of two symbols.
Signed-off-by: Mark Rutland <mark.rutland@arm.com>
Cc: Ard Biesheuvel <redacted>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Marc Zyngier <redacted>
Cc: Will Deacon <redacted>
---
arch/arm64/kernel/head.S | 14 ++++++--------
arch/arm64/kernel/image.h | 2 ++
2 files changed, 8 insertions(+), 8 deletions(-)
On 6 January 2016 at 12:05, Mark Rutland [off-list ref] wrote:
quoted hunk
Currently we use an open-coded memzero to clear the BSS. As it is a
trivial implementation, it is sub-optimal.
Our optimised memset doesn't use the stack, is position-independent, and
for the memzero case can use of DC ZVA to clear large blocks
efficiently. In __mmap_switched the MMU is on and there are no live
caller-saved registers, so we can safely call an uninstrumented memset.
This patch changes __mmap_switched to use memset when clearing the BSS.
We use the __pi_memset alias so as to avoid any instrumentation in all
kernel configurations. As with the head symbols, we must get the linker
to generate __bss_size, as there is no ELF relocation for the
subtraction of two symbols.
Signed-off-by: Mark Rutland <mark.rutland@arm.com>
Cc: Ard Biesheuvel <redacted>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Marc Zyngier <redacted>
Cc: Will Deacon <redacted>
---
arch/arm64/kernel/head.S | 14 ++++++--------
arch/arm64/kernel/image.h | 2 ++
2 files changed, 8 insertions(+), 8 deletions(-)
On 6 January 2016 at 12:05, Mark Rutland [off-list ref] wrote:
quoted hunk
Sometimes we want to be able to load values greater than 0xff into a
register, without placing said values in a literal pool. Arranging for
the value to be split up across a number of movz and movk instructions
is tedious and error-prone.
Following the example of {adr,str,ldr}_l, this patch adds a new mov_l
macro which can be used to load immediate values of up to 64 bits into a
register.
Signed-off-by: Mark Rutland <mark.rutland@arm.com>
Cc: Ard Biesheuvel <redacted>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Marc Zyngier <redacted>
Cc: Will Deacon <redacted>
---
arch/arm64/include/asm/assembler.h | 13 +++++++++++++
1 file changed, 13 insertions(+)
@@ -193,6 +193,19 @@ lr .req x30 // link registerstr\src,[\tmp,:lo12:\sym].endm+/*+*Movealargeimmediateupto64-bits.+*+*@dst:destinationregister(64bitwide)+*@val:value+*/+.macromov_l,dst,val+movz\dst,:abs_g0_nc:\val+movk\dst,:abs_g1_nc:\val+movk\dst,:abs_g2_nc:\val+movk\dst,:abs_g3:\val+.endm+
Ack for the general idea, but for correctness, you should pair the
movk instructions with the _nc relocations (i.e., keep movz first, but
invert the order of the relocs)
On Wed, Jan 06, 2016 at 12:12:45PM +0100, Ard Biesheuvel wrote:
On 6 January 2016 at 12:05, Mark Rutland [off-list ref] wrote:
quoted
Currently we use an open-coded memzero to clear the BSS. As it is a
trivial implementation, it is sub-optimal.
Our optimised memset doesn't use the stack, is position-independent, and
for the memzero case can use of DC ZVA to clear large blocks
efficiently. In __mmap_switched the MMU is on and there are no live
caller-saved registers, so we can safely call an uninstrumented memset.
This patch changes __mmap_switched to use memset when clearing the BSS.
We use the __pi_memset alias so as to avoid any instrumentation in all
kernel configurations. As with the head symbols, we must get the linker
to generate __bss_size, as there is no ELF relocation for the
subtraction of two symbols.
Signed-off-by: Mark Rutland <mark.rutland@arm.com>
Cc: Ard Biesheuvel <redacted>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Marc Zyngier <redacted>
Cc: Will Deacon <redacted>
---
arch/arm64/kernel/head.S | 14 ++++++--------
arch/arm64/kernel/image.h | 2 ++
2 files changed, 8 insertions(+), 8 deletions(-)
On Wed, Jan 06, 2016 at 12:15:14PM +0100, Ard Biesheuvel wrote:
On 6 January 2016 at 12:05, Mark Rutland [off-list ref] wrote:
quoted
Sometimes we want to be able to load values greater than 0xff into a
register, without placing said values in a literal pool. Arranging for
the value to be split up across a number of movz and movk instructions
is tedious and error-prone.
Following the example of {adr,str,ldr}_l, this patch adds a new mov_l
macro which can be used to load immediate values of up to 64 bits into a
register.
Signed-off-by: Mark Rutland <mark.rutland@arm.com>
Cc: Ard Biesheuvel <redacted>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Marc Zyngier <redacted>
Cc: Will Deacon <redacted>
---
arch/arm64/include/asm/assembler.h | 13 +++++++++++++
1 file changed, 13 insertions(+)
@@ -193,6 +193,19 @@ lr .req x30 // link registerstr\src,[\tmp,:lo12:\sym].endm+/*+*Movealargeimmediateupto64-bits.+*+*@dst:destinationregister(64bitwide)+*@val:value+*/+.macromov_l,dst,val+movz\dst,:abs_g0_nc:\val+movk\dst,:abs_g1_nc:\val+movk\dst,:abs_g2_nc:\val+movk\dst,:abs_g3:\val+.endm+
Ack for the general idea, but for correctness, you should pair the
movk instructions with the _nc relocations (i.e., keep movz first, but
invert the order of the relocs)
Ah, I hadn't spotted the restriction. I'll change that to:
movz \dst, :abs_g3:\val
movk \dst, :abs_g2:\val
movk \dst, :abs_g1:\val
movk \dst, :abs_g0:\val
That raises a related question. Is it the linker's responsibility to
fill in the shift encoding in the hw field as part of the g{3,2,1}
relocs?
Mine seems to, but I don't know if that's strictly required or correct
as the AArrch64 ELF spec only mentions the immediate field for *ABS_G*,
and the shift is encoded in hw rather than imm16.
Thanks,
Mark.
On 6 January 2016 at 13:21, Mark Rutland [off-list ref] wrote:
On Wed, Jan 06, 2016 at 12:15:14PM +0100, Ard Biesheuvel wrote:
quoted
On 6 January 2016 at 12:05, Mark Rutland [off-list ref] wrote:
quoted
Sometimes we want to be able to load values greater than 0xff into a
register, without placing said values in a literal pool. Arranging for
the value to be split up across a number of movz and movk instructions
is tedious and error-prone.
Following the example of {adr,str,ldr}_l, this patch adds a new mov_l
macro which can be used to load immediate values of up to 64 bits into a
register.
Signed-off-by: Mark Rutland <mark.rutland@arm.com>
Cc: Ard Biesheuvel <redacted>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Marc Zyngier <redacted>
Cc: Will Deacon <redacted>
---
arch/arm64/include/asm/assembler.h | 13 +++++++++++++
1 file changed, 13 insertions(+)
@@ -193,6 +193,19 @@ lr .req x30 // link registerstr\src,[\tmp,:lo12:\sym].endm+/*+*Movealargeimmediateupto64-bits.+*+*@dst:destinationregister(64bitwide)+*@val:value+*/+.macromov_l,dst,val+movz\dst,:abs_g0_nc:\val+movk\dst,:abs_g1_nc:\val+movk\dst,:abs_g2_nc:\val+movk\dst,:abs_g3:\val+.endm+
Ack for the general idea, but for correctness, you should pair the
movk instructions with the _nc relocations (i.e., keep movz first, but
invert the order of the relocs)
Ah, I hadn't spotted the restriction. I'll change that to:
movz \dst, :abs_g3:\val
movk \dst, :abs_g2:\val
movk \dst, :abs_g1:\val
movk \dst, :abs_g0:\val
Yes, but with the _nc suffix on the latter three.
That raises a related question. Is it the linker's responsibility to
fill in the shift encoding in the hw field as part of the g{3,2,1}
relocs?
This
movz x0, :abs_g3:val
movk x0, :abs_g2_nc:val
movk x0, :abs_g1_nc:val
movk x0, :abs_g0_nc:val
assembles to
0000000000000000 <.text>:
0: d2e00000 movz x0, #0x0, lsl #48
4: f2c00000 movk x0, #0x0, lsl #32
8: f2a00000 movk x0, #0x0, lsl #16
c: f2800000 movk x0, #0x0
so it is in fact the assembler that sets the hw field.
Mine seems to, but I don't know if that's strictly required or correct
as the AArrch64 ELF spec only mentions the immediate field for *ABS_G*,
and the shift is encoded in hw rather than imm16.
On Wed, Jan 06, 2016 at 11:40:39AM +0000, Mark Rutland wrote:
On Wed, Jan 06, 2016 at 12:12:45PM +0100, Ard Biesheuvel wrote:
quoted
On 6 January 2016 at 12:05, Mark Rutland [off-list ref] wrote:
quoted
Currently we use an open-coded memzero to clear the BSS. As it is a
trivial implementation, it is sub-optimal.
Our optimised memset doesn't use the stack, is position-independent, and
for the memzero case can use of DC ZVA to clear large blocks
efficiently. In __mmap_switched the MMU is on and there are no live
caller-saved registers, so we can safely call an uninstrumented memset.
This patch changes __mmap_switched to use memset when clearing the BSS.
We use the __pi_memset alias so as to avoid any instrumentation in all
kernel configurations. As with the head symbols, we must get the linker
to generate __bss_size, as there is no ELF relocation for the
subtraction of two symbols.
Signed-off-by: Mark Rutland <mark.rutland@arm.com>
Cc: Ard Biesheuvel <redacted>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Marc Zyngier <redacted>
Cc: Will Deacon <redacted>
---
arch/arm64/kernel/head.S | 14 ++++++--------
arch/arm64/kernel/image.h | 2 ++
2 files changed, 8 insertions(+), 8 deletions(-)
Ack for the general idea, but for correctness, you should pair the
movk instructions with the _nc relocations (i.e., keep movz first, but
invert the order of the relocs)
Ah, I hadn't spotted the restriction. I'll change that to:
movz \dst, :abs_g3:\val
movk \dst, :abs_g2:\val
movk \dst, :abs_g1:\val
movk \dst, :abs_g0:\val
Yes, but with the _nc suffix on the latter three.
Yup.
quoted
That raises a related question. Is it the linker's responsibility to
fill in the shift encoding in the hw field as part of the g{3,2,1}
relocs?
This
movz x0, :abs_g3:val
movk x0, :abs_g2_nc:val
movk x0, :abs_g1_nc:val
movk x0, :abs_g0_nc:val
assembles to
0000000000000000 <.text>:
0: d2e00000 movz x0, #0x0, lsl #48
4: f2c00000 movk x0, #0x0, lsl #32
8: f2a00000 movk x0, #0x0, lsl #16
c: f2800000 movk x0, #0x0
so it is in fact the assembler that sets the hw field.
Interesting!
As I mentioned in another reply, for the moment I'm going to drop mov_l
unless we have another need for it.
Thanks,
Mark.