Skip to content

Commit 437330d

Browse files
committed
Merge branch 'for-next/mops' into for-next/core
* for-next/mops: : More FEAT_MOPS (memcpy instructions) uses - in-kernel routines arm64: mops: Document requirements for hypervisors arm64: lib: Use MOPS for copy_page() and clear_page() arm64: lib: Use MOPS for memcpy() routines arm64: mops: Document booting requirement for HCR_EL2.MCE2 arm64: mops: Handle MOPS exceptions from EL1 arm64: probes: Disable kprobes/uprobes on MOPS instructions # Conflicts: # arch/arm64/kernel/entry-common.c
2 parents 5a43320 + 2cfdb79 commit 437330d

File tree

15 files changed

+146
-4
lines changed

15 files changed

+146
-4
lines changed

Documentation/arch/arm64/booting.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -388,6 +388,9 @@ Before jumping into the kernel, the following conditions must be met:
388388

389389
- HCRX_EL2.MSCEn (bit 11) must be initialised to 0b1.
390390

391+
- HCRX_EL2.MCE2 (bit 10) must be initialised to 0b1 and the hypervisor
392+
must handle MOPS exceptions as described in :ref:`arm64_mops_hyp`.
393+
391394
For CPUs with the Extended Translation Control Register feature (FEAT_TCR2):
392395

393396
- If EL3 is present:

Documentation/arch/arm64/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ ARM64 Architecture
2222
legacy_instructions
2323
memory
2424
memory-tagging-extension
25+
mops
2526
perf
2627
pointer-authentication
2728
ptdump

Documentation/arch/arm64/mops.rst

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
.. SPDX-License-Identifier: GPL-2.0
2+
3+
===================================
4+
Memory copy/set instructions (MOPS)
5+
===================================
6+
7+
A MOPS memory copy/set operation consists of three consecutive CPY* or SET*
8+
instructions: a prologue, main and epilogue (for example: CPYP, CPYM, CPYE).
9+
10+
A main or epilogue instruction can take a MOPS exception for various reasons,
11+
for example when a task is migrated to a CPU with a different MOPS
12+
implementation, or when the instruction's alignment and size requirements are
13+
not met. The software exception handler is then expected to reset the registers
14+
and restart execution from the prologue instruction. Normally this is handled
15+
by the kernel.
16+
17+
For more details refer to "D1.3.5.7 Memory Copy and Memory Set exceptions" in
18+
the Arm Architecture Reference Manual DDI 0487K.a (Arm ARM).
19+
20+
.. _arm64_mops_hyp:
21+
22+
Hypervisor requirements
23+
-----------------------
24+
25+
A hypervisor running a Linux guest must handle all MOPS exceptions from the
26+
guest kernel, as Linux may not be able to handle the exception at all times.
27+
For example, a MOPS exception can be taken when the hypervisor migrates a vCPU
28+
to another physical CPU with a different MOPS implementation.
29+
30+
To do this, the hypervisor must:
31+
32+
- Set HCRX_EL2.MCE2 to 1 so that the exception is taken to the hypervisor.
33+
34+
- Have an exception handler that implements the algorithm from the Arm ARM
35+
rules CNTMJ and MWFQH.
36+
37+
- Set the guest's PSTATE.SS to 0 in the exception handler, to handle a
38+
potential step of the current instruction.
39+
40+
Note: Clearing PSTATE.SS is needed so that a single step exception is taken
41+
on the next instruction (the prologue instruction). Otherwise prologue
42+
would get silently stepped over and the single step exception taken on the
43+
main instruction. Note that if the guest instruction is not being stepped
44+
then clearing PSTATE.SS has no effect.

arch/arm64/Kconfig

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2160,6 +2160,9 @@ config ARM64_EPAN
21602160
if the cpu does not implement the feature.
21612161
endmenu # "ARMv8.7 architectural features"
21622162

2163+
config AS_HAS_MOPS
2164+
def_bool $(as-instr,.arch_extension mops)
2165+
21632166
menu "ARMv8.9 architectural features"
21642167

21652168
config ARM64_POE

arch/arm64/include/asm/debug-monitors.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ void kernel_enable_single_step(struct pt_regs *regs);
105105
void kernel_disable_single_step(void);
106106
int kernel_active_single_step(void);
107107
void kernel_rewind_single_step(struct pt_regs *regs);
108+
void kernel_fastforward_single_step(struct pt_regs *regs);
108109

109110
#ifdef CONFIG_HAVE_HW_BREAKPOINT
110111
int reinstall_suspended_bps(struct pt_regs *regs);

arch/arm64/include/asm/exception.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ void do_el0_svc_compat(struct pt_regs *regs);
7575
void do_el0_fpac(struct pt_regs *regs, unsigned long esr);
7676
void do_el1_fpac(struct pt_regs *regs, unsigned long esr);
7777
void do_el0_mops(struct pt_regs *regs, unsigned long esr);
78+
void do_el1_mops(struct pt_regs *regs, unsigned long esr);
7879
void do_serror(struct pt_regs *regs, unsigned long esr);
7980
void do_signal(struct pt_regs *regs);
8081

arch/arm64/include/asm/insn.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -353,6 +353,7 @@ __AARCH64_INSN_FUNCS(ldrsw_lit, 0xFF000000, 0x98000000)
353353
__AARCH64_INSN_FUNCS(exclusive, 0x3F800000, 0x08000000)
354354
__AARCH64_INSN_FUNCS(load_ex, 0x3F400000, 0x08400000)
355355
__AARCH64_INSN_FUNCS(store_ex, 0x3F400000, 0x08000000)
356+
__AARCH64_INSN_FUNCS(mops, 0x3B200C00, 0x19000400)
356357
__AARCH64_INSN_FUNCS(stp, 0x7FC00000, 0x29000000)
357358
__AARCH64_INSN_FUNCS(ldp, 0x7FC00000, 0x29400000)
358359
__AARCH64_INSN_FUNCS(stp_post, 0x7FC00000, 0x28800000)

arch/arm64/kernel/debug-monitors.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -440,6 +440,11 @@ void kernel_rewind_single_step(struct pt_regs *regs)
440440
set_regs_spsr_ss(regs);
441441
}
442442

443+
void kernel_fastforward_single_step(struct pt_regs *regs)
444+
{
445+
clear_regs_spsr_ss(regs);
446+
}
447+
443448
/* ptrace API */
444449
void user_enable_single_step(struct task_struct *task)
445450
{

arch/arm64/kernel/entry-common.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -472,6 +472,15 @@ static void noinstr el1_gcs(struct pt_regs *regs, unsigned long esr)
472472
exit_to_kernel_mode(regs);
473473
}
474474

475+
static void noinstr el1_mops(struct pt_regs *regs, unsigned long esr)
476+
{
477+
enter_from_kernel_mode(regs);
478+
local_daif_inherit(regs);
479+
do_el1_mops(regs, esr);
480+
local_daif_mask();
481+
exit_to_kernel_mode(regs);
482+
}
483+
475484
static void noinstr el1_dbg(struct pt_regs *regs, unsigned long esr)
476485
{
477486
unsigned long far = read_sysreg(far_el1);
@@ -517,6 +526,9 @@ asmlinkage void noinstr el1h_64_sync_handler(struct pt_regs *regs)
517526
case ESR_ELx_EC_GCS:
518527
el1_gcs(regs, esr);
519528
break;
529+
case ESR_ELx_EC_MOPS:
530+
el1_mops(regs, esr);
531+
break;
520532
case ESR_ELx_EC_BREAKPT_CUR:
521533
case ESR_ELx_EC_SOFTSTP_CUR:
522534
case ESR_ELx_EC_WATCHPT_CUR:

arch/arm64/kernel/probes/decode-insn.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,10 +58,13 @@ static bool __kprobes aarch64_insn_is_steppable(u32 insn)
5858
* Instructions which load PC relative literals are not going to work
5959
* when executed from an XOL slot. Instructions doing an exclusive
6060
* load/store are not going to complete successfully when single-step
61-
* exception handling happens in the middle of the sequence.
61+
* exception handling happens in the middle of the sequence. Memory
62+
* copy/set instructions require that all three instructions be placed
63+
* consecutively in memory.
6264
*/
6365
if (aarch64_insn_uses_literal(insn) ||
64-
aarch64_insn_is_exclusive(insn))
66+
aarch64_insn_is_exclusive(insn) ||
67+
aarch64_insn_is_mops(insn))
6568
return false;
6669

6770
return true;

0 commit comments

Comments
 (0)