All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v6 00/17] KVM nVHE Hypervisor stack unwinder
@ 2022-07-26  7:37 ` Kalesh Singh
  0 siblings, 0 replies; 112+ messages in thread
From: Kalesh Singh @ 2022-07-26  7:37 UTC (permalink / raw)
  To: maz, mark.rutland, broonie, madvenka, tabba, oliver.upton
  Cc: wangkefeng.wang, catalin.marinas, ast, vincenzo.frascino, will,
	kvmarm, android-mm, kernel-team, elver, linux-arm-kernel,
	andreyknvl, linux-kernel, mhiramat

Hi all,

This is v6 of nVHE stacktrace support. The series is based on
arm64 for-next/stacktrace.

The previous versions were posted at:
v5: https://lore.kernel.org/r/20220721055728.718573-1-kaleshsingh@google.com/
v4: https://lore.kernel.org/r/20220715061027.1612149-1-kaleshsingh@google.com/
v3: https://lore.kernel.org/r/20220607165105.639716-1-kaleshsingh@google.com/
v2: https://lore.kernel.org/r/20220502191222.4192768-1-kaleshsingh@google.com/
v1: https://lore.kernel.org/r/20220427184716.1949239-1-kaleshsingh@google.com/

This version mainly reorganizes the order of to patches into more coherent
groups, along with addressing the other feedback in v5.

Patches 1 to 6 factor out the common unwinding logic into
into arch/arm64/include/asm/stacktrace/common.h, for reuse by the nVHE
unwinder. No functional change is introduced by these:

  [01/17] arm64: stacktrace: Add shared header for common stack unwinding code
  [02/17] arm64: stacktrace: Factor out on_accessible_stack_common()
  [03/17] arm64: stacktrace: Factor out unwind_next_common()
  [04/17] arm64: stacktrace: Handle frame pointer from different address spaces
  [05/17] arm64: stacktrace: Factor out common unwind()
  [06/17] arm64: stacktrace: Add description of stacktrace/common.h

Patches 7 to 11 implement stacktraces for conventional nVHE (non-protected
mode):

  [07/17] KVM: arm64: On stack overflow switch to hyp overflow_stack
  [08/17] KVM: arm64: Stub implementation of non-protected nVHE HYP stack
    unwinder
  [09/17] KVM: arm64: Prepare non-protected nVHE hypervisor stacktrace
  [10/17] KVM: arm64: Implement non-protected nVHE hyp stack unwinder
  [11/17] KVM: arm64: Introduce hyp_dump_backtrace()

Patches 12 to 17 implement stacktraces for protected-nVHE (pKVM):

  [12/17] KVM: arm64: Add PROTECTED_NVHE_STACKTRACE Kconfig
  [13/17] KVM: arm64: Allocate shared pKVM hyp stacktrace buffers
  [14/17] KVM: arm64: Stub implementation of pKVM HYP stack unwinder
  [15/17] KVM: arm64: Save protected-nVHE (pKVM) hyp stacktrace
  [16/17] KVM: arm64: Implement protected nVHE hyp stack unwinder
  [17/17] KVM: arm64: Introduce pkvm_dump_backtrace()

The updated cover letter is copied below for convenience.

Thanks,
Kalesh

============

KVM nVHE Stack unwinding.
===

nVHE has two modes of operation: protected (pKVM) and unprotected
(conventional nVHE). Depending on the mode, a slightly different approach
is used to dump the hypervisor stacktrace but the core unwinding logic
remains the same.

Protected nVHE (pKVM) stacktraces
====

In protected nVHE mode, the host cannot directly access hypervisor memory.

The hypervisor stack unwinding happens in EL2 and is made accessible to
the host via a shared buffer. Symbolizing and printing the stacktrace
addresses is delegated to the host and happens in EL1.

Non-protected (Conventional) nVHE stacktraces
====

In non-protected mode, the host is able to directly access the hypervisor
stack pages.

The hypervisor stack unwinding and dumping of the stacktrace is performed
by the host in EL1, as this avoids the memory overhead of setting up
shared buffers between the host and hypervisor.

Resuing the Core Unwinding Logic
====

Since the hypervisor cannot link against the kernel code in proteced mode.
The common stack unwinding code is moved to a shared header to allow reuse
in the nVHE hypervisor.

Reducing the memory footprint
====

In this version the below steps were taken to reduce the memory usage of
nVHE stack unwinding:

    1) The nVHE overflow stack is reduced from PAGE_SIZE to 4KB; benificial
       for configurations with non 4KB pages (16KB or 64KB pages).
    2) In protected nVHE mode (pKVM), the shared stacktrace buffers with the
       host are reduced from PAGE_SIZE to the minimum size required.
    3) In systems other than Android, conventional nVHE makes up the vast
       majority of use case. So the pKVM stack tracing is disabled by default
       (!CONFIG_PROTECTED_NVHE_STACKTRACE), which avoid the memory usage for
       setting up shared buffers.
    4) In non-protected nVHE mode (conventional nVHE), the stack unwinding
       is done directly in EL1 by the host and no shared buffers with the
       hypervisor are needed.

Sample Output
====

The below shows an example output from a simple stack overflow test:

[  111.623091] kvm [367]: nVHE call trace:
[  111.623215] kvm [367]:  [<ffff8000090a6570>] __kvm_nvhe_hyp_panic+0xac/0xf8
[  111.623448] kvm [367]:  [<ffff8000090a65cc>] __kvm_nvhe_hyp_panic_bad_stack+0x10/0x10
[  111.623642] kvm [367]:  [<ffff8000090a61e4>] __kvm_nvhe_recursive_death+0x24/0x34
. . .
[  111.640366] kvm [367]:  [<ffff8000090a61e4>] __kvm_nvhe_recursive_death+0x24/0x34
[  111.640467] kvm [367]:  [<ffff8000090a61e4>] __kvm_nvhe_recursive_death+0x24/0x34
[  111.640574] kvm [367]:  [<ffff8000090a5de4>] __kvm_nvhe___kvm_vcpu_run+0x30/0x40c
[  111.640676] kvm [367]:  [<ffff8000090a8b64>] __kvm_nvhe_handle___kvm_vcpu_run+0x30/0x48
[  111.640778] kvm [367]:  [<ffff8000090a88b8>] __kvm_nvhe_handle_trap+0xc4/0x128
[  111.640880] kvm [367]:  [<ffff8000090a7864>] __kvm_nvhe___host_exit+0x64/0x64
[  111.640996] kvm [367]: ---[ end nVHE call trace ]---

============

Kalesh Singh (17):
  arm64: stacktrace: Add shared header for common stack unwinding code
  arm64: stacktrace: Factor out on_accessible_stack_common()
  arm64: stacktrace: Factor out unwind_next_common()
  arm64: stacktrace: Handle frame pointer from different address spaces
  arm64: stacktrace: Factor out common unwind()
  arm64: stacktrace: Add description of stacktrace/common.h
  KVM: arm64: On stack overflow switch to hyp overflow_stack
  KVM: arm64: Stub implementation of non-protected nVHE HYP stack
    unwinder
  KVM: arm64: Prepare non-protected nVHE hypervisor stacktrace
  KVM: arm64: Implement non-protected nVHE hyp stack unwinder
  KVM: arm64: Introduce hyp_dump_backtrace()
  KVM: arm64: Add PROTECTED_NVHE_STACKTRACE Kconfig
  KVM: arm64: Allocate shared pKVM hyp stacktrace buffers
  KVM: arm64: Stub implementation of pKVM HYP stack unwinder
  KVM: arm64: Save protected-nVHE (pKVM) hyp stacktrace
  KVM: arm64: Implement protected nVHE hyp stack unwinder
  KVM: arm64: Introduce pkvm_dump_backtrace()

 arch/arm64/include/asm/kvm_asm.h           |  16 ++
 arch/arm64/include/asm/memory.h            |   8 +
 arch/arm64/include/asm/stacktrace.h        |  92 +++++----
 arch/arm64/include/asm/stacktrace/common.h | 230 +++++++++++++++++++++
 arch/arm64/include/asm/stacktrace/nvhe.h   | 176 ++++++++++++++++
 arch/arm64/kernel/stacktrace.c             | 157 --------------
 arch/arm64/kvm/Kconfig                     |  15 ++
 arch/arm64/kvm/arm.c                       |   2 +-
 arch/arm64/kvm/handle_exit.c               | 102 +++++++++
 arch/arm64/kvm/hyp/nvhe/Makefile           |   2 +-
 arch/arm64/kvm/hyp/nvhe/host.S             |   9 +-
 arch/arm64/kvm/hyp/nvhe/stacktrace.c       | 109 ++++++++++
 arch/arm64/kvm/hyp/nvhe/switch.c           |   6 +
 13 files changed, 720 insertions(+), 204 deletions(-)
 create mode 100644 arch/arm64/include/asm/stacktrace/common.h
 create mode 100644 arch/arm64/include/asm/stacktrace/nvhe.h
 create mode 100644 arch/arm64/kvm/hyp/nvhe/stacktrace.c


base-commit: 82a592c13b0aeff94d84d54183dae0b26384c95f
-- 
2.37.1.359.gd136c6c3e2-goog

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply	[flat|nested] 112+ messages in thread

* [PATCH v6 00/17] KVM nVHE Hypervisor stack unwinder
@ 2022-07-26  7:37 ` Kalesh Singh
  0 siblings, 0 replies; 112+ messages in thread
From: Kalesh Singh @ 2022-07-26  7:37 UTC (permalink / raw)
  To: maz, mark.rutland, broonie, madvenka, tabba, oliver.upton
  Cc: will, qperret, kaleshsingh, james.morse, alexandru.elisei,
	suzuki.poulose, catalin.marinas, andreyknvl, vincenzo.frascino,
	mhiramat, ast, wangkefeng.wang, elver, keirf, yuzenghui, ardb,
	oupton, linux-arm-kernel, kvmarm, linux-kernel, android-mm,
	kernel-team

Hi all,

This is v6 of nVHE stacktrace support. The series is based on
arm64 for-next/stacktrace.

The previous versions were posted at:
v5: https://lore.kernel.org/r/20220721055728.718573-1-kaleshsingh@google.com/
v4: https://lore.kernel.org/r/20220715061027.1612149-1-kaleshsingh@google.com/
v3: https://lore.kernel.org/r/20220607165105.639716-1-kaleshsingh@google.com/
v2: https://lore.kernel.org/r/20220502191222.4192768-1-kaleshsingh@google.com/
v1: https://lore.kernel.org/r/20220427184716.1949239-1-kaleshsingh@google.com/

This version mainly reorganizes the order of to patches into more coherent
groups, along with addressing the other feedback in v5.

Patches 1 to 6 factor out the common unwinding logic into
into arch/arm64/include/asm/stacktrace/common.h, for reuse by the nVHE
unwinder. No functional change is introduced by these:

  [01/17] arm64: stacktrace: Add shared header for common stack unwinding code
  [02/17] arm64: stacktrace: Factor out on_accessible_stack_common()
  [03/17] arm64: stacktrace: Factor out unwind_next_common()
  [04/17] arm64: stacktrace: Handle frame pointer from different address spaces
  [05/17] arm64: stacktrace: Factor out common unwind()
  [06/17] arm64: stacktrace: Add description of stacktrace/common.h

Patches 7 to 11 implement stacktraces for conventional nVHE (non-protected
mode):

  [07/17] KVM: arm64: On stack overflow switch to hyp overflow_stack
  [08/17] KVM: arm64: Stub implementation of non-protected nVHE HYP stack
    unwinder
  [09/17] KVM: arm64: Prepare non-protected nVHE hypervisor stacktrace
  [10/17] KVM: arm64: Implement non-protected nVHE hyp stack unwinder
  [11/17] KVM: arm64: Introduce hyp_dump_backtrace()

Patches 12 to 17 implement stacktraces for protected-nVHE (pKVM):

  [12/17] KVM: arm64: Add PROTECTED_NVHE_STACKTRACE Kconfig
  [13/17] KVM: arm64: Allocate shared pKVM hyp stacktrace buffers
  [14/17] KVM: arm64: Stub implementation of pKVM HYP stack unwinder
  [15/17] KVM: arm64: Save protected-nVHE (pKVM) hyp stacktrace
  [16/17] KVM: arm64: Implement protected nVHE hyp stack unwinder
  [17/17] KVM: arm64: Introduce pkvm_dump_backtrace()

The updated cover letter is copied below for convenience.

Thanks,
Kalesh

============

KVM nVHE Stack unwinding.
===

nVHE has two modes of operation: protected (pKVM) and unprotected
(conventional nVHE). Depending on the mode, a slightly different approach
is used to dump the hypervisor stacktrace but the core unwinding logic
remains the same.

Protected nVHE (pKVM) stacktraces
====

In protected nVHE mode, the host cannot directly access hypervisor memory.

The hypervisor stack unwinding happens in EL2 and is made accessible to
the host via a shared buffer. Symbolizing and printing the stacktrace
addresses is delegated to the host and happens in EL1.

Non-protected (Conventional) nVHE stacktraces
====

In non-protected mode, the host is able to directly access the hypervisor
stack pages.

The hypervisor stack unwinding and dumping of the stacktrace is performed
by the host in EL1, as this avoids the memory overhead of setting up
shared buffers between the host and hypervisor.

Resuing the Core Unwinding Logic
====

Since the hypervisor cannot link against the kernel code in proteced mode.
The common stack unwinding code is moved to a shared header to allow reuse
in the nVHE hypervisor.

Reducing the memory footprint
====

In this version the below steps were taken to reduce the memory usage of
nVHE stack unwinding:

    1) The nVHE overflow stack is reduced from PAGE_SIZE to 4KB; benificial
       for configurations with non 4KB pages (16KB or 64KB pages).
    2) In protected nVHE mode (pKVM), the shared stacktrace buffers with the
       host are reduced from PAGE_SIZE to the minimum size required.
    3) In systems other than Android, conventional nVHE makes up the vast
       majority of use case. So the pKVM stack tracing is disabled by default
       (!CONFIG_PROTECTED_NVHE_STACKTRACE), which avoid the memory usage for
       setting up shared buffers.
    4) In non-protected nVHE mode (conventional nVHE), the stack unwinding
       is done directly in EL1 by the host and no shared buffers with the
       hypervisor are needed.

Sample Output
====

The below shows an example output from a simple stack overflow test:

[  111.623091] kvm [367]: nVHE call trace:
[  111.623215] kvm [367]:  [<ffff8000090a6570>] __kvm_nvhe_hyp_panic+0xac/0xf8
[  111.623448] kvm [367]:  [<ffff8000090a65cc>] __kvm_nvhe_hyp_panic_bad_stack+0x10/0x10
[  111.623642] kvm [367]:  [<ffff8000090a61e4>] __kvm_nvhe_recursive_death+0x24/0x34
. . .
[  111.640366] kvm [367]:  [<ffff8000090a61e4>] __kvm_nvhe_recursive_death+0x24/0x34
[  111.640467] kvm [367]:  [<ffff8000090a61e4>] __kvm_nvhe_recursive_death+0x24/0x34
[  111.640574] kvm [367]:  [<ffff8000090a5de4>] __kvm_nvhe___kvm_vcpu_run+0x30/0x40c
[  111.640676] kvm [367]:  [<ffff8000090a8b64>] __kvm_nvhe_handle___kvm_vcpu_run+0x30/0x48
[  111.640778] kvm [367]:  [<ffff8000090a88b8>] __kvm_nvhe_handle_trap+0xc4/0x128
[  111.640880] kvm [367]:  [<ffff8000090a7864>] __kvm_nvhe___host_exit+0x64/0x64
[  111.640996] kvm [367]: ---[ end nVHE call trace ]---

============

Kalesh Singh (17):
  arm64: stacktrace: Add shared header for common stack unwinding code
  arm64: stacktrace: Factor out on_accessible_stack_common()
  arm64: stacktrace: Factor out unwind_next_common()
  arm64: stacktrace: Handle frame pointer from different address spaces
  arm64: stacktrace: Factor out common unwind()
  arm64: stacktrace: Add description of stacktrace/common.h
  KVM: arm64: On stack overflow switch to hyp overflow_stack
  KVM: arm64: Stub implementation of non-protected nVHE HYP stack
    unwinder
  KVM: arm64: Prepare non-protected nVHE hypervisor stacktrace
  KVM: arm64: Implement non-protected nVHE hyp stack unwinder
  KVM: arm64: Introduce hyp_dump_backtrace()
  KVM: arm64: Add PROTECTED_NVHE_STACKTRACE Kconfig
  KVM: arm64: Allocate shared pKVM hyp stacktrace buffers
  KVM: arm64: Stub implementation of pKVM HYP stack unwinder
  KVM: arm64: Save protected-nVHE (pKVM) hyp stacktrace
  KVM: arm64: Implement protected nVHE hyp stack unwinder
  KVM: arm64: Introduce pkvm_dump_backtrace()

 arch/arm64/include/asm/kvm_asm.h           |  16 ++
 arch/arm64/include/asm/memory.h            |   8 +
 arch/arm64/include/asm/stacktrace.h        |  92 +++++----
 arch/arm64/include/asm/stacktrace/common.h | 230 +++++++++++++++++++++
 arch/arm64/include/asm/stacktrace/nvhe.h   | 176 ++++++++++++++++
 arch/arm64/kernel/stacktrace.c             | 157 --------------
 arch/arm64/kvm/Kconfig                     |  15 ++
 arch/arm64/kvm/arm.c                       |   2 +-
 arch/arm64/kvm/handle_exit.c               | 102 +++++++++
 arch/arm64/kvm/hyp/nvhe/Makefile           |   2 +-
 arch/arm64/kvm/hyp/nvhe/host.S             |   9 +-
 arch/arm64/kvm/hyp/nvhe/stacktrace.c       | 109 ++++++++++
 arch/arm64/kvm/hyp/nvhe/switch.c           |   6 +
 13 files changed, 720 insertions(+), 204 deletions(-)
 create mode 100644 arch/arm64/include/asm/stacktrace/common.h
 create mode 100644 arch/arm64/include/asm/stacktrace/nvhe.h
 create mode 100644 arch/arm64/kvm/hyp/nvhe/stacktrace.c


base-commit: 82a592c13b0aeff94d84d54183dae0b26384c95f
-- 
2.37.1.359.gd136c6c3e2-goog


^ permalink raw reply	[flat|nested] 112+ messages in thread

* [PATCH v6 00/17] KVM nVHE Hypervisor stack unwinder
@ 2022-07-26  7:37 ` Kalesh Singh
  0 siblings, 0 replies; 112+ messages in thread
From: Kalesh Singh @ 2022-07-26  7:37 UTC (permalink / raw)
  To: maz, mark.rutland, broonie, madvenka, tabba, oliver.upton
  Cc: will, qperret, kaleshsingh, james.morse, alexandru.elisei,
	suzuki.poulose, catalin.marinas, andreyknvl, vincenzo.frascino,
	mhiramat, ast, wangkefeng.wang, elver, keirf, yuzenghui, ardb,
	oupton, linux-arm-kernel, kvmarm, linux-kernel, android-mm,
	kernel-team

Hi all,

This is v6 of nVHE stacktrace support. The series is based on
arm64 for-next/stacktrace.

The previous versions were posted at:
v5: https://lore.kernel.org/r/20220721055728.718573-1-kaleshsingh@google.com/
v4: https://lore.kernel.org/r/20220715061027.1612149-1-kaleshsingh@google.com/
v3: https://lore.kernel.org/r/20220607165105.639716-1-kaleshsingh@google.com/
v2: https://lore.kernel.org/r/20220502191222.4192768-1-kaleshsingh@google.com/
v1: https://lore.kernel.org/r/20220427184716.1949239-1-kaleshsingh@google.com/

This version mainly reorganizes the order of to patches into more coherent
groups, along with addressing the other feedback in v5.

Patches 1 to 6 factor out the common unwinding logic into
into arch/arm64/include/asm/stacktrace/common.h, for reuse by the nVHE
unwinder. No functional change is introduced by these:

  [01/17] arm64: stacktrace: Add shared header for common stack unwinding code
  [02/17] arm64: stacktrace: Factor out on_accessible_stack_common()
  [03/17] arm64: stacktrace: Factor out unwind_next_common()
  [04/17] arm64: stacktrace: Handle frame pointer from different address spaces
  [05/17] arm64: stacktrace: Factor out common unwind()
  [06/17] arm64: stacktrace: Add description of stacktrace/common.h

Patches 7 to 11 implement stacktraces for conventional nVHE (non-protected
mode):

  [07/17] KVM: arm64: On stack overflow switch to hyp overflow_stack
  [08/17] KVM: arm64: Stub implementation of non-protected nVHE HYP stack
    unwinder
  [09/17] KVM: arm64: Prepare non-protected nVHE hypervisor stacktrace
  [10/17] KVM: arm64: Implement non-protected nVHE hyp stack unwinder
  [11/17] KVM: arm64: Introduce hyp_dump_backtrace()

Patches 12 to 17 implement stacktraces for protected-nVHE (pKVM):

  [12/17] KVM: arm64: Add PROTECTED_NVHE_STACKTRACE Kconfig
  [13/17] KVM: arm64: Allocate shared pKVM hyp stacktrace buffers
  [14/17] KVM: arm64: Stub implementation of pKVM HYP stack unwinder
  [15/17] KVM: arm64: Save protected-nVHE (pKVM) hyp stacktrace
  [16/17] KVM: arm64: Implement protected nVHE hyp stack unwinder
  [17/17] KVM: arm64: Introduce pkvm_dump_backtrace()

The updated cover letter is copied below for convenience.

Thanks,
Kalesh

============

KVM nVHE Stack unwinding.
===

nVHE has two modes of operation: protected (pKVM) and unprotected
(conventional nVHE). Depending on the mode, a slightly different approach
is used to dump the hypervisor stacktrace but the core unwinding logic
remains the same.

Protected nVHE (pKVM) stacktraces
====

In protected nVHE mode, the host cannot directly access hypervisor memory.

The hypervisor stack unwinding happens in EL2 and is made accessible to
the host via a shared buffer. Symbolizing and printing the stacktrace
addresses is delegated to the host and happens in EL1.

Non-protected (Conventional) nVHE stacktraces
====

In non-protected mode, the host is able to directly access the hypervisor
stack pages.

The hypervisor stack unwinding and dumping of the stacktrace is performed
by the host in EL1, as this avoids the memory overhead of setting up
shared buffers between the host and hypervisor.

Resuing the Core Unwinding Logic
====

Since the hypervisor cannot link against the kernel code in proteced mode.
The common stack unwinding code is moved to a shared header to allow reuse
in the nVHE hypervisor.

Reducing the memory footprint
====

In this version the below steps were taken to reduce the memory usage of
nVHE stack unwinding:

    1) The nVHE overflow stack is reduced from PAGE_SIZE to 4KB; benificial
       for configurations with non 4KB pages (16KB or 64KB pages).
    2) In protected nVHE mode (pKVM), the shared stacktrace buffers with the
       host are reduced from PAGE_SIZE to the minimum size required.
    3) In systems other than Android, conventional nVHE makes up the vast
       majority of use case. So the pKVM stack tracing is disabled by default
       (!CONFIG_PROTECTED_NVHE_STACKTRACE), which avoid the memory usage for
       setting up shared buffers.
    4) In non-protected nVHE mode (conventional nVHE), the stack unwinding
       is done directly in EL1 by the host and no shared buffers with the
       hypervisor are needed.

Sample Output
====

The below shows an example output from a simple stack overflow test:

[  111.623091] kvm [367]: nVHE call trace:
[  111.623215] kvm [367]:  [<ffff8000090a6570>] __kvm_nvhe_hyp_panic+0xac/0xf8
[  111.623448] kvm [367]:  [<ffff8000090a65cc>] __kvm_nvhe_hyp_panic_bad_stack+0x10/0x10
[  111.623642] kvm [367]:  [<ffff8000090a61e4>] __kvm_nvhe_recursive_death+0x24/0x34
. . .
[  111.640366] kvm [367]:  [<ffff8000090a61e4>] __kvm_nvhe_recursive_death+0x24/0x34
[  111.640467] kvm [367]:  [<ffff8000090a61e4>] __kvm_nvhe_recursive_death+0x24/0x34
[  111.640574] kvm [367]:  [<ffff8000090a5de4>] __kvm_nvhe___kvm_vcpu_run+0x30/0x40c
[  111.640676] kvm [367]:  [<ffff8000090a8b64>] __kvm_nvhe_handle___kvm_vcpu_run+0x30/0x48
[  111.640778] kvm [367]:  [<ffff8000090a88b8>] __kvm_nvhe_handle_trap+0xc4/0x128
[  111.640880] kvm [367]:  [<ffff8000090a7864>] __kvm_nvhe___host_exit+0x64/0x64
[  111.640996] kvm [367]: ---[ end nVHE call trace ]---

============

Kalesh Singh (17):
  arm64: stacktrace: Add shared header for common stack unwinding code
  arm64: stacktrace: Factor out on_accessible_stack_common()
  arm64: stacktrace: Factor out unwind_next_common()
  arm64: stacktrace: Handle frame pointer from different address spaces
  arm64: stacktrace: Factor out common unwind()
  arm64: stacktrace: Add description of stacktrace/common.h
  KVM: arm64: On stack overflow switch to hyp overflow_stack
  KVM: arm64: Stub implementation of non-protected nVHE HYP stack
    unwinder
  KVM: arm64: Prepare non-protected nVHE hypervisor stacktrace
  KVM: arm64: Implement non-protected nVHE hyp stack unwinder
  KVM: arm64: Introduce hyp_dump_backtrace()
  KVM: arm64: Add PROTECTED_NVHE_STACKTRACE Kconfig
  KVM: arm64: Allocate shared pKVM hyp stacktrace buffers
  KVM: arm64: Stub implementation of pKVM HYP stack unwinder
  KVM: arm64: Save protected-nVHE (pKVM) hyp stacktrace
  KVM: arm64: Implement protected nVHE hyp stack unwinder
  KVM: arm64: Introduce pkvm_dump_backtrace()

 arch/arm64/include/asm/kvm_asm.h           |  16 ++
 arch/arm64/include/asm/memory.h            |   8 +
 arch/arm64/include/asm/stacktrace.h        |  92 +++++----
 arch/arm64/include/asm/stacktrace/common.h | 230 +++++++++++++++++++++
 arch/arm64/include/asm/stacktrace/nvhe.h   | 176 ++++++++++++++++
 arch/arm64/kernel/stacktrace.c             | 157 --------------
 arch/arm64/kvm/Kconfig                     |  15 ++
 arch/arm64/kvm/arm.c                       |   2 +-
 arch/arm64/kvm/handle_exit.c               | 102 +++++++++
 arch/arm64/kvm/hyp/nvhe/Makefile           |   2 +-
 arch/arm64/kvm/hyp/nvhe/host.S             |   9 +-
 arch/arm64/kvm/hyp/nvhe/stacktrace.c       | 109 ++++++++++
 arch/arm64/kvm/hyp/nvhe/switch.c           |   6 +
 13 files changed, 720 insertions(+), 204 deletions(-)
 create mode 100644 arch/arm64/include/asm/stacktrace/common.h
 create mode 100644 arch/arm64/include/asm/stacktrace/nvhe.h
 create mode 100644 arch/arm64/kvm/hyp/nvhe/stacktrace.c


base-commit: 82a592c13b0aeff94d84d54183dae0b26384c95f
-- 
2.37.1.359.gd136c6c3e2-goog


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 112+ messages in thread

* [PATCH v6 01/17] arm64: stacktrace: Add shared header for common stack unwinding code
  2022-07-26  7:37 ` Kalesh Singh
  (?)
@ 2022-07-26  7:37   ` Kalesh Singh
  -1 siblings, 0 replies; 112+ messages in thread
From: Kalesh Singh @ 2022-07-26  7:37 UTC (permalink / raw)
  To: maz, mark.rutland, broonie, madvenka, tabba, oliver.upton
  Cc: wangkefeng.wang, catalin.marinas, ast, vincenzo.frascino, will,
	kvmarm, android-mm, kernel-team, elver, linux-arm-kernel,
	andreyknvl, linux-kernel, mhiramat

In order to reuse the arm64 stack unwinding logic for the nVHE
hypervisor stack, move the common code to a shared header
(arch/arm64/include/asm/stacktrace/common.h).

The nVHE hypervisor cannot safely link against kernel code, so we
make use of the shared header to avoid duplicated logic later in
this series.

Signed-off-by: Kalesh Singh <kaleshsingh@google.com>
Reviewed-by: Mark Brown <broonie@kernel.org>
Reviewed-by: Fuad Tabba <tabba@google.com>
Tested-by: Fuad Tabba <tabba@google.com>
---

Changes in v6:
  - Add Fuad's Tested-by tag

Changes in v5:
  - Add Reviewed-by tags from Mark Brown and Fuad

 arch/arm64/include/asm/stacktrace.h        |  35 +------
 arch/arm64/include/asm/stacktrace/common.h | 105 +++++++++++++++++++++
 arch/arm64/kernel/stacktrace.c             |  57 -----------
 3 files changed, 106 insertions(+), 91 deletions(-)
 create mode 100644 arch/arm64/include/asm/stacktrace/common.h

diff --git a/arch/arm64/include/asm/stacktrace.h b/arch/arm64/include/asm/stacktrace.h
index aec9315bf156..79f455b37c84 100644
--- a/arch/arm64/include/asm/stacktrace.h
+++ b/arch/arm64/include/asm/stacktrace.h
@@ -8,52 +8,19 @@
 #include <linux/percpu.h>
 #include <linux/sched.h>
 #include <linux/sched/task_stack.h>
-#include <linux/types.h>
 #include <linux/llist.h>
 
 #include <asm/memory.h>
 #include <asm/ptrace.h>
 #include <asm/sdei.h>
 
-enum stack_type {
-	STACK_TYPE_UNKNOWN,
-	STACK_TYPE_TASK,
-	STACK_TYPE_IRQ,
-	STACK_TYPE_OVERFLOW,
-	STACK_TYPE_SDEI_NORMAL,
-	STACK_TYPE_SDEI_CRITICAL,
-	__NR_STACK_TYPES
-};
-
-struct stack_info {
-	unsigned long low;
-	unsigned long high;
-	enum stack_type type;
-};
+#include <asm/stacktrace/common.h>
 
 extern void dump_backtrace(struct pt_regs *regs, struct task_struct *tsk,
 			   const char *loglvl);
 
 DECLARE_PER_CPU(unsigned long *, irq_stack_ptr);
 
-static inline bool on_stack(unsigned long sp, unsigned long size,
-			    unsigned long low, unsigned long high,
-			    enum stack_type type, struct stack_info *info)
-{
-	if (!low)
-		return false;
-
-	if (sp < low || sp + size < sp || sp + size > high)
-		return false;
-
-	if (info) {
-		info->low = low;
-		info->high = high;
-		info->type = type;
-	}
-	return true;
-}
-
 static inline bool on_irq_stack(unsigned long sp, unsigned long size,
 				struct stack_info *info)
 {
diff --git a/arch/arm64/include/asm/stacktrace/common.h b/arch/arm64/include/asm/stacktrace/common.h
new file mode 100644
index 000000000000..64ae4f6b06fe
--- /dev/null
+++ b/arch/arm64/include/asm/stacktrace/common.h
@@ -0,0 +1,105 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Common arm64 stack unwinder code.
+ *
+ * Copyright (C) 2012 ARM Ltd.
+ */
+#ifndef __ASM_STACKTRACE_COMMON_H
+#define __ASM_STACKTRACE_COMMON_H
+
+#include <linux/bitmap.h>
+#include <linux/bitops.h>
+#include <linux/types.h>
+
+enum stack_type {
+	STACK_TYPE_UNKNOWN,
+	STACK_TYPE_TASK,
+	STACK_TYPE_IRQ,
+	STACK_TYPE_OVERFLOW,
+	STACK_TYPE_SDEI_NORMAL,
+	STACK_TYPE_SDEI_CRITICAL,
+	__NR_STACK_TYPES
+};
+
+struct stack_info {
+	unsigned long low;
+	unsigned long high;
+	enum stack_type type;
+};
+
+/*
+ * A snapshot of a frame record or fp/lr register values, along with some
+ * accounting information necessary for robust unwinding.
+ *
+ * @fp:          The fp value in the frame record (or the real fp)
+ * @pc:          The lr value in the frame record (or the real lr)
+ *
+ * @stacks_done: Stacks which have been entirely unwound, for which it is no
+ *               longer valid to unwind to.
+ *
+ * @prev_fp:     The fp that pointed to this frame record, or a synthetic value
+ *               of 0. This is used to ensure that within a stack, each
+ *               subsequent frame record is at an increasing address.
+ * @prev_type:   The type of stack this frame record was on, or a synthetic
+ *               value of STACK_TYPE_UNKNOWN. This is used to detect a
+ *               transition from one stack to another.
+ *
+ * @kr_cur:      When KRETPROBES is selected, holds the kretprobe instance
+ *               associated with the most recently encountered replacement lr
+ *               value.
+ *
+ * @task:        The task being unwound.
+ */
+struct unwind_state {
+	unsigned long fp;
+	unsigned long pc;
+	DECLARE_BITMAP(stacks_done, __NR_STACK_TYPES);
+	unsigned long prev_fp;
+	enum stack_type prev_type;
+#ifdef CONFIG_KRETPROBES
+	struct llist_node *kr_cur;
+#endif
+	struct task_struct *task;
+};
+
+static inline bool on_stack(unsigned long sp, unsigned long size,
+			    unsigned long low, unsigned long high,
+			    enum stack_type type, struct stack_info *info)
+{
+	if (!low)
+		return false;
+
+	if (sp < low || sp + size < sp || sp + size > high)
+		return false;
+
+	if (info) {
+		info->low = low;
+		info->high = high;
+		info->type = type;
+	}
+	return true;
+}
+
+static inline void unwind_init_common(struct unwind_state *state,
+				      struct task_struct *task)
+{
+	state->task = task;
+#ifdef CONFIG_KRETPROBES
+	state->kr_cur = NULL;
+#endif
+
+	/*
+	 * Prime the first unwind.
+	 *
+	 * In unwind_next() we'll check that the FP points to a valid stack,
+	 * which can't be STACK_TYPE_UNKNOWN, and the first unwind will be
+	 * treated as a transition to whichever stack that happens to be. The
+	 * prev_fp value won't be used, but we set it to 0 such that it is
+	 * definitely not an accessible stack address.
+	 */
+	bitmap_zero(state->stacks_done, __NR_STACK_TYPES);
+	state->prev_fp = 0;
+	state->prev_type = STACK_TYPE_UNKNOWN;
+}
+
+#endif	/* __ASM_STACKTRACE_COMMON_H */
diff --git a/arch/arm64/kernel/stacktrace.c b/arch/arm64/kernel/stacktrace.c
index fcaa151b81f1..94a5dd2ab8fd 100644
--- a/arch/arm64/kernel/stacktrace.c
+++ b/arch/arm64/kernel/stacktrace.c
@@ -18,63 +18,6 @@
 #include <asm/stack_pointer.h>
 #include <asm/stacktrace.h>
 
-/*
- * A snapshot of a frame record or fp/lr register values, along with some
- * accounting information necessary for robust unwinding.
- *
- * @fp:          The fp value in the frame record (or the real fp)
- * @pc:          The lr value in the frame record (or the real lr)
- *
- * @stacks_done: Stacks which have been entirely unwound, for which it is no
- *               longer valid to unwind to.
- *
- * @prev_fp:     The fp that pointed to this frame record, or a synthetic value
- *               of 0. This is used to ensure that within a stack, each
- *               subsequent frame record is at an increasing address.
- * @prev_type:   The type of stack this frame record was on, or a synthetic
- *               value of STACK_TYPE_UNKNOWN. This is used to detect a
- *               transition from one stack to another.
- *
- * @kr_cur:      When KRETPROBES is selected, holds the kretprobe instance
- *               associated with the most recently encountered replacement lr
- *               value.
- *
- * @task:        The task being unwound.
- */
-struct unwind_state {
-	unsigned long fp;
-	unsigned long pc;
-	DECLARE_BITMAP(stacks_done, __NR_STACK_TYPES);
-	unsigned long prev_fp;
-	enum stack_type prev_type;
-#ifdef CONFIG_KRETPROBES
-	struct llist_node *kr_cur;
-#endif
-	struct task_struct *task;
-};
-
-static void unwind_init_common(struct unwind_state *state,
-			       struct task_struct *task)
-{
-	state->task = task;
-#ifdef CONFIG_KRETPROBES
-	state->kr_cur = NULL;
-#endif
-
-	/*
-	 * Prime the first unwind.
-	 *
-	 * In unwind_next() we'll check that the FP points to a valid stack,
-	 * which can't be STACK_TYPE_UNKNOWN, and the first unwind will be
-	 * treated as a transition to whichever stack that happens to be. The
-	 * prev_fp value won't be used, but we set it to 0 such that it is
-	 * definitely not an accessible stack address.
-	 */
-	bitmap_zero(state->stacks_done, __NR_STACK_TYPES);
-	state->prev_fp = 0;
-	state->prev_type = STACK_TYPE_UNKNOWN;
-}
-
 /*
  * Start an unwind from a pt_regs.
  *
-- 
2.37.1.359.gd136c6c3e2-goog

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply related	[flat|nested] 112+ messages in thread

* [PATCH v6 01/17] arm64: stacktrace: Add shared header for common stack unwinding code
@ 2022-07-26  7:37   ` Kalesh Singh
  0 siblings, 0 replies; 112+ messages in thread
From: Kalesh Singh @ 2022-07-26  7:37 UTC (permalink / raw)
  To: maz, mark.rutland, broonie, madvenka, tabba, oliver.upton
  Cc: will, qperret, kaleshsingh, james.morse, alexandru.elisei,
	suzuki.poulose, catalin.marinas, andreyknvl, vincenzo.frascino,
	mhiramat, ast, wangkefeng.wang, elver, keirf, yuzenghui, ardb,
	oupton, linux-arm-kernel, kvmarm, linux-kernel, android-mm,
	kernel-team

In order to reuse the arm64 stack unwinding logic for the nVHE
hypervisor stack, move the common code to a shared header
(arch/arm64/include/asm/stacktrace/common.h).

The nVHE hypervisor cannot safely link against kernel code, so we
make use of the shared header to avoid duplicated logic later in
this series.

Signed-off-by: Kalesh Singh <kaleshsingh@google.com>
Reviewed-by: Mark Brown <broonie@kernel.org>
Reviewed-by: Fuad Tabba <tabba@google.com>
Tested-by: Fuad Tabba <tabba@google.com>
---

Changes in v6:
  - Add Fuad's Tested-by tag

Changes in v5:
  - Add Reviewed-by tags from Mark Brown and Fuad

 arch/arm64/include/asm/stacktrace.h        |  35 +------
 arch/arm64/include/asm/stacktrace/common.h | 105 +++++++++++++++++++++
 arch/arm64/kernel/stacktrace.c             |  57 -----------
 3 files changed, 106 insertions(+), 91 deletions(-)
 create mode 100644 arch/arm64/include/asm/stacktrace/common.h

diff --git a/arch/arm64/include/asm/stacktrace.h b/arch/arm64/include/asm/stacktrace.h
index aec9315bf156..79f455b37c84 100644
--- a/arch/arm64/include/asm/stacktrace.h
+++ b/arch/arm64/include/asm/stacktrace.h
@@ -8,52 +8,19 @@
 #include <linux/percpu.h>
 #include <linux/sched.h>
 #include <linux/sched/task_stack.h>
-#include <linux/types.h>
 #include <linux/llist.h>
 
 #include <asm/memory.h>
 #include <asm/ptrace.h>
 #include <asm/sdei.h>
 
-enum stack_type {
-	STACK_TYPE_UNKNOWN,
-	STACK_TYPE_TASK,
-	STACK_TYPE_IRQ,
-	STACK_TYPE_OVERFLOW,
-	STACK_TYPE_SDEI_NORMAL,
-	STACK_TYPE_SDEI_CRITICAL,
-	__NR_STACK_TYPES
-};
-
-struct stack_info {
-	unsigned long low;
-	unsigned long high;
-	enum stack_type type;
-};
+#include <asm/stacktrace/common.h>
 
 extern void dump_backtrace(struct pt_regs *regs, struct task_struct *tsk,
 			   const char *loglvl);
 
 DECLARE_PER_CPU(unsigned long *, irq_stack_ptr);
 
-static inline bool on_stack(unsigned long sp, unsigned long size,
-			    unsigned long low, unsigned long high,
-			    enum stack_type type, struct stack_info *info)
-{
-	if (!low)
-		return false;
-
-	if (sp < low || sp + size < sp || sp + size > high)
-		return false;
-
-	if (info) {
-		info->low = low;
-		info->high = high;
-		info->type = type;
-	}
-	return true;
-}
-
 static inline bool on_irq_stack(unsigned long sp, unsigned long size,
 				struct stack_info *info)
 {
diff --git a/arch/arm64/include/asm/stacktrace/common.h b/arch/arm64/include/asm/stacktrace/common.h
new file mode 100644
index 000000000000..64ae4f6b06fe
--- /dev/null
+++ b/arch/arm64/include/asm/stacktrace/common.h
@@ -0,0 +1,105 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Common arm64 stack unwinder code.
+ *
+ * Copyright (C) 2012 ARM Ltd.
+ */
+#ifndef __ASM_STACKTRACE_COMMON_H
+#define __ASM_STACKTRACE_COMMON_H
+
+#include <linux/bitmap.h>
+#include <linux/bitops.h>
+#include <linux/types.h>
+
+enum stack_type {
+	STACK_TYPE_UNKNOWN,
+	STACK_TYPE_TASK,
+	STACK_TYPE_IRQ,
+	STACK_TYPE_OVERFLOW,
+	STACK_TYPE_SDEI_NORMAL,
+	STACK_TYPE_SDEI_CRITICAL,
+	__NR_STACK_TYPES
+};
+
+struct stack_info {
+	unsigned long low;
+	unsigned long high;
+	enum stack_type type;
+};
+
+/*
+ * A snapshot of a frame record or fp/lr register values, along with some
+ * accounting information necessary for robust unwinding.
+ *
+ * @fp:          The fp value in the frame record (or the real fp)
+ * @pc:          The lr value in the frame record (or the real lr)
+ *
+ * @stacks_done: Stacks which have been entirely unwound, for which it is no
+ *               longer valid to unwind to.
+ *
+ * @prev_fp:     The fp that pointed to this frame record, or a synthetic value
+ *               of 0. This is used to ensure that within a stack, each
+ *               subsequent frame record is at an increasing address.
+ * @prev_type:   The type of stack this frame record was on, or a synthetic
+ *               value of STACK_TYPE_UNKNOWN. This is used to detect a
+ *               transition from one stack to another.
+ *
+ * @kr_cur:      When KRETPROBES is selected, holds the kretprobe instance
+ *               associated with the most recently encountered replacement lr
+ *               value.
+ *
+ * @task:        The task being unwound.
+ */
+struct unwind_state {
+	unsigned long fp;
+	unsigned long pc;
+	DECLARE_BITMAP(stacks_done, __NR_STACK_TYPES);
+	unsigned long prev_fp;
+	enum stack_type prev_type;
+#ifdef CONFIG_KRETPROBES
+	struct llist_node *kr_cur;
+#endif
+	struct task_struct *task;
+};
+
+static inline bool on_stack(unsigned long sp, unsigned long size,
+			    unsigned long low, unsigned long high,
+			    enum stack_type type, struct stack_info *info)
+{
+	if (!low)
+		return false;
+
+	if (sp < low || sp + size < sp || sp + size > high)
+		return false;
+
+	if (info) {
+		info->low = low;
+		info->high = high;
+		info->type = type;
+	}
+	return true;
+}
+
+static inline void unwind_init_common(struct unwind_state *state,
+				      struct task_struct *task)
+{
+	state->task = task;
+#ifdef CONFIG_KRETPROBES
+	state->kr_cur = NULL;
+#endif
+
+	/*
+	 * Prime the first unwind.
+	 *
+	 * In unwind_next() we'll check that the FP points to a valid stack,
+	 * which can't be STACK_TYPE_UNKNOWN, and the first unwind will be
+	 * treated as a transition to whichever stack that happens to be. The
+	 * prev_fp value won't be used, but we set it to 0 such that it is
+	 * definitely not an accessible stack address.
+	 */
+	bitmap_zero(state->stacks_done, __NR_STACK_TYPES);
+	state->prev_fp = 0;
+	state->prev_type = STACK_TYPE_UNKNOWN;
+}
+
+#endif	/* __ASM_STACKTRACE_COMMON_H */
diff --git a/arch/arm64/kernel/stacktrace.c b/arch/arm64/kernel/stacktrace.c
index fcaa151b81f1..94a5dd2ab8fd 100644
--- a/arch/arm64/kernel/stacktrace.c
+++ b/arch/arm64/kernel/stacktrace.c
@@ -18,63 +18,6 @@
 #include <asm/stack_pointer.h>
 #include <asm/stacktrace.h>
 
-/*
- * A snapshot of a frame record or fp/lr register values, along with some
- * accounting information necessary for robust unwinding.
- *
- * @fp:          The fp value in the frame record (or the real fp)
- * @pc:          The lr value in the frame record (or the real lr)
- *
- * @stacks_done: Stacks which have been entirely unwound, for which it is no
- *               longer valid to unwind to.
- *
- * @prev_fp:     The fp that pointed to this frame record, or a synthetic value
- *               of 0. This is used to ensure that within a stack, each
- *               subsequent frame record is at an increasing address.
- * @prev_type:   The type of stack this frame record was on, or a synthetic
- *               value of STACK_TYPE_UNKNOWN. This is used to detect a
- *               transition from one stack to another.
- *
- * @kr_cur:      When KRETPROBES is selected, holds the kretprobe instance
- *               associated with the most recently encountered replacement lr
- *               value.
- *
- * @task:        The task being unwound.
- */
-struct unwind_state {
-	unsigned long fp;
-	unsigned long pc;
-	DECLARE_BITMAP(stacks_done, __NR_STACK_TYPES);
-	unsigned long prev_fp;
-	enum stack_type prev_type;
-#ifdef CONFIG_KRETPROBES
-	struct llist_node *kr_cur;
-#endif
-	struct task_struct *task;
-};
-
-static void unwind_init_common(struct unwind_state *state,
-			       struct task_struct *task)
-{
-	state->task = task;
-#ifdef CONFIG_KRETPROBES
-	state->kr_cur = NULL;
-#endif
-
-	/*
-	 * Prime the first unwind.
-	 *
-	 * In unwind_next() we'll check that the FP points to a valid stack,
-	 * which can't be STACK_TYPE_UNKNOWN, and the first unwind will be
-	 * treated as a transition to whichever stack that happens to be. The
-	 * prev_fp value won't be used, but we set it to 0 such that it is
-	 * definitely not an accessible stack address.
-	 */
-	bitmap_zero(state->stacks_done, __NR_STACK_TYPES);
-	state->prev_fp = 0;
-	state->prev_type = STACK_TYPE_UNKNOWN;
-}
-
 /*
  * Start an unwind from a pt_regs.
  *
-- 
2.37.1.359.gd136c6c3e2-goog


^ permalink raw reply related	[flat|nested] 112+ messages in thread

* [PATCH v6 01/17] arm64: stacktrace: Add shared header for common stack unwinding code
@ 2022-07-26  7:37   ` Kalesh Singh
  0 siblings, 0 replies; 112+ messages in thread
From: Kalesh Singh @ 2022-07-26  7:37 UTC (permalink / raw)
  To: maz, mark.rutland, broonie, madvenka, tabba, oliver.upton
  Cc: will, qperret, kaleshsingh, james.morse, alexandru.elisei,
	suzuki.poulose, catalin.marinas, andreyknvl, vincenzo.frascino,
	mhiramat, ast, wangkefeng.wang, elver, keirf, yuzenghui, ardb,
	oupton, linux-arm-kernel, kvmarm, linux-kernel, android-mm,
	kernel-team

In order to reuse the arm64 stack unwinding logic for the nVHE
hypervisor stack, move the common code to a shared header
(arch/arm64/include/asm/stacktrace/common.h).

The nVHE hypervisor cannot safely link against kernel code, so we
make use of the shared header to avoid duplicated logic later in
this series.

Signed-off-by: Kalesh Singh <kaleshsingh@google.com>
Reviewed-by: Mark Brown <broonie@kernel.org>
Reviewed-by: Fuad Tabba <tabba@google.com>
Tested-by: Fuad Tabba <tabba@google.com>
---

Changes in v6:
  - Add Fuad's Tested-by tag

Changes in v5:
  - Add Reviewed-by tags from Mark Brown and Fuad

 arch/arm64/include/asm/stacktrace.h        |  35 +------
 arch/arm64/include/asm/stacktrace/common.h | 105 +++++++++++++++++++++
 arch/arm64/kernel/stacktrace.c             |  57 -----------
 3 files changed, 106 insertions(+), 91 deletions(-)
 create mode 100644 arch/arm64/include/asm/stacktrace/common.h

diff --git a/arch/arm64/include/asm/stacktrace.h b/arch/arm64/include/asm/stacktrace.h
index aec9315bf156..79f455b37c84 100644
--- a/arch/arm64/include/asm/stacktrace.h
+++ b/arch/arm64/include/asm/stacktrace.h
@@ -8,52 +8,19 @@
 #include <linux/percpu.h>
 #include <linux/sched.h>
 #include <linux/sched/task_stack.h>
-#include <linux/types.h>
 #include <linux/llist.h>
 
 #include <asm/memory.h>
 #include <asm/ptrace.h>
 #include <asm/sdei.h>
 
-enum stack_type {
-	STACK_TYPE_UNKNOWN,
-	STACK_TYPE_TASK,
-	STACK_TYPE_IRQ,
-	STACK_TYPE_OVERFLOW,
-	STACK_TYPE_SDEI_NORMAL,
-	STACK_TYPE_SDEI_CRITICAL,
-	__NR_STACK_TYPES
-};
-
-struct stack_info {
-	unsigned long low;
-	unsigned long high;
-	enum stack_type type;
-};
+#include <asm/stacktrace/common.h>
 
 extern void dump_backtrace(struct pt_regs *regs, struct task_struct *tsk,
 			   const char *loglvl);
 
 DECLARE_PER_CPU(unsigned long *, irq_stack_ptr);
 
-static inline bool on_stack(unsigned long sp, unsigned long size,
-			    unsigned long low, unsigned long high,
-			    enum stack_type type, struct stack_info *info)
-{
-	if (!low)
-		return false;
-
-	if (sp < low || sp + size < sp || sp + size > high)
-		return false;
-
-	if (info) {
-		info->low = low;
-		info->high = high;
-		info->type = type;
-	}
-	return true;
-}
-
 static inline bool on_irq_stack(unsigned long sp, unsigned long size,
 				struct stack_info *info)
 {
diff --git a/arch/arm64/include/asm/stacktrace/common.h b/arch/arm64/include/asm/stacktrace/common.h
new file mode 100644
index 000000000000..64ae4f6b06fe
--- /dev/null
+++ b/arch/arm64/include/asm/stacktrace/common.h
@@ -0,0 +1,105 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Common arm64 stack unwinder code.
+ *
+ * Copyright (C) 2012 ARM Ltd.
+ */
+#ifndef __ASM_STACKTRACE_COMMON_H
+#define __ASM_STACKTRACE_COMMON_H
+
+#include <linux/bitmap.h>
+#include <linux/bitops.h>
+#include <linux/types.h>
+
+enum stack_type {
+	STACK_TYPE_UNKNOWN,
+	STACK_TYPE_TASK,
+	STACK_TYPE_IRQ,
+	STACK_TYPE_OVERFLOW,
+	STACK_TYPE_SDEI_NORMAL,
+	STACK_TYPE_SDEI_CRITICAL,
+	__NR_STACK_TYPES
+};
+
+struct stack_info {
+	unsigned long low;
+	unsigned long high;
+	enum stack_type type;
+};
+
+/*
+ * A snapshot of a frame record or fp/lr register values, along with some
+ * accounting information necessary for robust unwinding.
+ *
+ * @fp:          The fp value in the frame record (or the real fp)
+ * @pc:          The lr value in the frame record (or the real lr)
+ *
+ * @stacks_done: Stacks which have been entirely unwound, for which it is no
+ *               longer valid to unwind to.
+ *
+ * @prev_fp:     The fp that pointed to this frame record, or a synthetic value
+ *               of 0. This is used to ensure that within a stack, each
+ *               subsequent frame record is at an increasing address.
+ * @prev_type:   The type of stack this frame record was on, or a synthetic
+ *               value of STACK_TYPE_UNKNOWN. This is used to detect a
+ *               transition from one stack to another.
+ *
+ * @kr_cur:      When KRETPROBES is selected, holds the kretprobe instance
+ *               associated with the most recently encountered replacement lr
+ *               value.
+ *
+ * @task:        The task being unwound.
+ */
+struct unwind_state {
+	unsigned long fp;
+	unsigned long pc;
+	DECLARE_BITMAP(stacks_done, __NR_STACK_TYPES);
+	unsigned long prev_fp;
+	enum stack_type prev_type;
+#ifdef CONFIG_KRETPROBES
+	struct llist_node *kr_cur;
+#endif
+	struct task_struct *task;
+};
+
+static inline bool on_stack(unsigned long sp, unsigned long size,
+			    unsigned long low, unsigned long high,
+			    enum stack_type type, struct stack_info *info)
+{
+	if (!low)
+		return false;
+
+	if (sp < low || sp + size < sp || sp + size > high)
+		return false;
+
+	if (info) {
+		info->low = low;
+		info->high = high;
+		info->type = type;
+	}
+	return true;
+}
+
+static inline void unwind_init_common(struct unwind_state *state,
+				      struct task_struct *task)
+{
+	state->task = task;
+#ifdef CONFIG_KRETPROBES
+	state->kr_cur = NULL;
+#endif
+
+	/*
+	 * Prime the first unwind.
+	 *
+	 * In unwind_next() we'll check that the FP points to a valid stack,
+	 * which can't be STACK_TYPE_UNKNOWN, and the first unwind will be
+	 * treated as a transition to whichever stack that happens to be. The
+	 * prev_fp value won't be used, but we set it to 0 such that it is
+	 * definitely not an accessible stack address.
+	 */
+	bitmap_zero(state->stacks_done, __NR_STACK_TYPES);
+	state->prev_fp = 0;
+	state->prev_type = STACK_TYPE_UNKNOWN;
+}
+
+#endif	/* __ASM_STACKTRACE_COMMON_H */
diff --git a/arch/arm64/kernel/stacktrace.c b/arch/arm64/kernel/stacktrace.c
index fcaa151b81f1..94a5dd2ab8fd 100644
--- a/arch/arm64/kernel/stacktrace.c
+++ b/arch/arm64/kernel/stacktrace.c
@@ -18,63 +18,6 @@
 #include <asm/stack_pointer.h>
 #include <asm/stacktrace.h>
 
-/*
- * A snapshot of a frame record or fp/lr register values, along with some
- * accounting information necessary for robust unwinding.
- *
- * @fp:          The fp value in the frame record (or the real fp)
- * @pc:          The lr value in the frame record (or the real lr)
- *
- * @stacks_done: Stacks which have been entirely unwound, for which it is no
- *               longer valid to unwind to.
- *
- * @prev_fp:     The fp that pointed to this frame record, or a synthetic value
- *               of 0. This is used to ensure that within a stack, each
- *               subsequent frame record is at an increasing address.
- * @prev_type:   The type of stack this frame record was on, or a synthetic
- *               value of STACK_TYPE_UNKNOWN. This is used to detect a
- *               transition from one stack to another.
- *
- * @kr_cur:      When KRETPROBES is selected, holds the kretprobe instance
- *               associated with the most recently encountered replacement lr
- *               value.
- *
- * @task:        The task being unwound.
- */
-struct unwind_state {
-	unsigned long fp;
-	unsigned long pc;
-	DECLARE_BITMAP(stacks_done, __NR_STACK_TYPES);
-	unsigned long prev_fp;
-	enum stack_type prev_type;
-#ifdef CONFIG_KRETPROBES
-	struct llist_node *kr_cur;
-#endif
-	struct task_struct *task;
-};
-
-static void unwind_init_common(struct unwind_state *state,
-			       struct task_struct *task)
-{
-	state->task = task;
-#ifdef CONFIG_KRETPROBES
-	state->kr_cur = NULL;
-#endif
-
-	/*
-	 * Prime the first unwind.
-	 *
-	 * In unwind_next() we'll check that the FP points to a valid stack,
-	 * which can't be STACK_TYPE_UNKNOWN, and the first unwind will be
-	 * treated as a transition to whichever stack that happens to be. The
-	 * prev_fp value won't be used, but we set it to 0 such that it is
-	 * definitely not an accessible stack address.
-	 */
-	bitmap_zero(state->stacks_done, __NR_STACK_TYPES);
-	state->prev_fp = 0;
-	state->prev_type = STACK_TYPE_UNKNOWN;
-}
-
 /*
  * Start an unwind from a pt_regs.
  *
-- 
2.37.1.359.gd136c6c3e2-goog


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 112+ messages in thread

* [PATCH v6 02/17] arm64: stacktrace: Factor out on_accessible_stack_common()
  2022-07-26  7:37 ` Kalesh Singh
  (?)
@ 2022-07-26  7:37   ` Kalesh Singh
  -1 siblings, 0 replies; 112+ messages in thread
From: Kalesh Singh @ 2022-07-26  7:37 UTC (permalink / raw)
  To: maz, mark.rutland, broonie, madvenka, tabba, oliver.upton
  Cc: wangkefeng.wang, catalin.marinas, ast, vincenzo.frascino, will,
	kvmarm, android-mm, kernel-team, elver, linux-arm-kernel,
	andreyknvl, linux-kernel, mhiramat

Move common on_accessible_stack checks to stacktrace/common.h. This is
used in the implementation of the nVHE hypervisor unwinder later in
this series.

Signed-off-by: Kalesh Singh <kaleshsingh@google.com>
Reviewed-by: Fuad Tabba <tabba@google.com>
Reviewed-by: Mark Brown <broonie@kernel.org>
Tested-by: Fuad Tabba <tabba@google.com>
---

Changes in v6:
  - Add Fuad's Tested-by tag

Changes in v5:
  - Add Reviewed-by tags from Mark Brown and Fuad
  - Remove random whitespace change, per Mark Brown

 arch/arm64/include/asm/stacktrace.h        |  6 ++----
 arch/arm64/include/asm/stacktrace/common.h | 18 ++++++++++++++++++
 2 files changed, 20 insertions(+), 4 deletions(-)

diff --git a/arch/arm64/include/asm/stacktrace.h b/arch/arm64/include/asm/stacktrace.h
index 79f455b37c84..43f4b4a6d383 100644
--- a/arch/arm64/include/asm/stacktrace.h
+++ b/arch/arm64/include/asm/stacktrace.h
@@ -65,8 +65,8 @@ static inline bool on_accessible_stack(const struct task_struct *tsk,
 				       unsigned long sp, unsigned long size,
 				       struct stack_info *info)
 {
-	if (info)
-		info->type = STACK_TYPE_UNKNOWN;
+	if (on_accessible_stack_common(tsk, sp, size, info))
+		return true;
 
 	if (on_task_stack(tsk, sp, size, info))
 		return true;
@@ -74,8 +74,6 @@ static inline bool on_accessible_stack(const struct task_struct *tsk,
 		return false;
 	if (on_irq_stack(sp, size, info))
 		return true;
-	if (on_overflow_stack(sp, size, info))
-		return true;
 	if (on_sdei_stack(sp, size, info))
 		return true;
 
diff --git a/arch/arm64/include/asm/stacktrace/common.h b/arch/arm64/include/asm/stacktrace/common.h
index 64ae4f6b06fe..f58b786460d3 100644
--- a/arch/arm64/include/asm/stacktrace/common.h
+++ b/arch/arm64/include/asm/stacktrace/common.h
@@ -62,6 +62,9 @@ struct unwind_state {
 	struct task_struct *task;
 };
 
+static inline bool on_overflow_stack(unsigned long sp, unsigned long size,
+				     struct stack_info *info);
+
 static inline bool on_stack(unsigned long sp, unsigned long size,
 			    unsigned long low, unsigned long high,
 			    enum stack_type type, struct stack_info *info)
@@ -80,6 +83,21 @@ static inline bool on_stack(unsigned long sp, unsigned long size,
 	return true;
 }
 
+static inline bool on_accessible_stack_common(const struct task_struct *tsk,
+					      unsigned long sp,
+					      unsigned long size,
+					      struct stack_info *info)
+{
+	if (info)
+		info->type = STACK_TYPE_UNKNOWN;
+
+	/*
+	 * Both the kernel and nvhe hypervisor make use of
+	 * an overflow_stack
+	 */
+	return on_overflow_stack(sp, size, info);
+}
+
 static inline void unwind_init_common(struct unwind_state *state,
 				      struct task_struct *task)
 {
-- 
2.37.1.359.gd136c6c3e2-goog

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply related	[flat|nested] 112+ messages in thread

* [PATCH v6 02/17] arm64: stacktrace: Factor out on_accessible_stack_common()
@ 2022-07-26  7:37   ` Kalesh Singh
  0 siblings, 0 replies; 112+ messages in thread
From: Kalesh Singh @ 2022-07-26  7:37 UTC (permalink / raw)
  To: maz, mark.rutland, broonie, madvenka, tabba, oliver.upton
  Cc: will, qperret, kaleshsingh, james.morse, alexandru.elisei,
	suzuki.poulose, catalin.marinas, andreyknvl, vincenzo.frascino,
	mhiramat, ast, wangkefeng.wang, elver, keirf, yuzenghui, ardb,
	oupton, linux-arm-kernel, kvmarm, linux-kernel, android-mm,
	kernel-team

Move common on_accessible_stack checks to stacktrace/common.h. This is
used in the implementation of the nVHE hypervisor unwinder later in
this series.

Signed-off-by: Kalesh Singh <kaleshsingh@google.com>
Reviewed-by: Fuad Tabba <tabba@google.com>
Reviewed-by: Mark Brown <broonie@kernel.org>
Tested-by: Fuad Tabba <tabba@google.com>
---

Changes in v6:
  - Add Fuad's Tested-by tag

Changes in v5:
  - Add Reviewed-by tags from Mark Brown and Fuad
  - Remove random whitespace change, per Mark Brown

 arch/arm64/include/asm/stacktrace.h        |  6 ++----
 arch/arm64/include/asm/stacktrace/common.h | 18 ++++++++++++++++++
 2 files changed, 20 insertions(+), 4 deletions(-)

diff --git a/arch/arm64/include/asm/stacktrace.h b/arch/arm64/include/asm/stacktrace.h
index 79f455b37c84..43f4b4a6d383 100644
--- a/arch/arm64/include/asm/stacktrace.h
+++ b/arch/arm64/include/asm/stacktrace.h
@@ -65,8 +65,8 @@ static inline bool on_accessible_stack(const struct task_struct *tsk,
 				       unsigned long sp, unsigned long size,
 				       struct stack_info *info)
 {
-	if (info)
-		info->type = STACK_TYPE_UNKNOWN;
+	if (on_accessible_stack_common(tsk, sp, size, info))
+		return true;
 
 	if (on_task_stack(tsk, sp, size, info))
 		return true;
@@ -74,8 +74,6 @@ static inline bool on_accessible_stack(const struct task_struct *tsk,
 		return false;
 	if (on_irq_stack(sp, size, info))
 		return true;
-	if (on_overflow_stack(sp, size, info))
-		return true;
 	if (on_sdei_stack(sp, size, info))
 		return true;
 
diff --git a/arch/arm64/include/asm/stacktrace/common.h b/arch/arm64/include/asm/stacktrace/common.h
index 64ae4f6b06fe..f58b786460d3 100644
--- a/arch/arm64/include/asm/stacktrace/common.h
+++ b/arch/arm64/include/asm/stacktrace/common.h
@@ -62,6 +62,9 @@ struct unwind_state {
 	struct task_struct *task;
 };
 
+static inline bool on_overflow_stack(unsigned long sp, unsigned long size,
+				     struct stack_info *info);
+
 static inline bool on_stack(unsigned long sp, unsigned long size,
 			    unsigned long low, unsigned long high,
 			    enum stack_type type, struct stack_info *info)
@@ -80,6 +83,21 @@ static inline bool on_stack(unsigned long sp, unsigned long size,
 	return true;
 }
 
+static inline bool on_accessible_stack_common(const struct task_struct *tsk,
+					      unsigned long sp,
+					      unsigned long size,
+					      struct stack_info *info)
+{
+	if (info)
+		info->type = STACK_TYPE_UNKNOWN;
+
+	/*
+	 * Both the kernel and nvhe hypervisor make use of
+	 * an overflow_stack
+	 */
+	return on_overflow_stack(sp, size, info);
+}
+
 static inline void unwind_init_common(struct unwind_state *state,
 				      struct task_struct *task)
 {
-- 
2.37.1.359.gd136c6c3e2-goog


^ permalink raw reply related	[flat|nested] 112+ messages in thread

* [PATCH v6 02/17] arm64: stacktrace: Factor out on_accessible_stack_common()
@ 2022-07-26  7:37   ` Kalesh Singh
  0 siblings, 0 replies; 112+ messages in thread
From: Kalesh Singh @ 2022-07-26  7:37 UTC (permalink / raw)
  To: maz, mark.rutland, broonie, madvenka, tabba, oliver.upton
  Cc: will, qperret, kaleshsingh, james.morse, alexandru.elisei,
	suzuki.poulose, catalin.marinas, andreyknvl, vincenzo.frascino,
	mhiramat, ast, wangkefeng.wang, elver, keirf, yuzenghui, ardb,
	oupton, linux-arm-kernel, kvmarm, linux-kernel, android-mm,
	kernel-team

Move common on_accessible_stack checks to stacktrace/common.h. This is
used in the implementation of the nVHE hypervisor unwinder later in
this series.

Signed-off-by: Kalesh Singh <kaleshsingh@google.com>
Reviewed-by: Fuad Tabba <tabba@google.com>
Reviewed-by: Mark Brown <broonie@kernel.org>
Tested-by: Fuad Tabba <tabba@google.com>
---

Changes in v6:
  - Add Fuad's Tested-by tag

Changes in v5:
  - Add Reviewed-by tags from Mark Brown and Fuad
  - Remove random whitespace change, per Mark Brown

 arch/arm64/include/asm/stacktrace.h        |  6 ++----
 arch/arm64/include/asm/stacktrace/common.h | 18 ++++++++++++++++++
 2 files changed, 20 insertions(+), 4 deletions(-)

diff --git a/arch/arm64/include/asm/stacktrace.h b/arch/arm64/include/asm/stacktrace.h
index 79f455b37c84..43f4b4a6d383 100644
--- a/arch/arm64/include/asm/stacktrace.h
+++ b/arch/arm64/include/asm/stacktrace.h
@@ -65,8 +65,8 @@ static inline bool on_accessible_stack(const struct task_struct *tsk,
 				       unsigned long sp, unsigned long size,
 				       struct stack_info *info)
 {
-	if (info)
-		info->type = STACK_TYPE_UNKNOWN;
+	if (on_accessible_stack_common(tsk, sp, size, info))
+		return true;
 
 	if (on_task_stack(tsk, sp, size, info))
 		return true;
@@ -74,8 +74,6 @@ static inline bool on_accessible_stack(const struct task_struct *tsk,
 		return false;
 	if (on_irq_stack(sp, size, info))
 		return true;
-	if (on_overflow_stack(sp, size, info))
-		return true;
 	if (on_sdei_stack(sp, size, info))
 		return true;
 
diff --git a/arch/arm64/include/asm/stacktrace/common.h b/arch/arm64/include/asm/stacktrace/common.h
index 64ae4f6b06fe..f58b786460d3 100644
--- a/arch/arm64/include/asm/stacktrace/common.h
+++ b/arch/arm64/include/asm/stacktrace/common.h
@@ -62,6 +62,9 @@ struct unwind_state {
 	struct task_struct *task;
 };
 
+static inline bool on_overflow_stack(unsigned long sp, unsigned long size,
+				     struct stack_info *info);
+
 static inline bool on_stack(unsigned long sp, unsigned long size,
 			    unsigned long low, unsigned long high,
 			    enum stack_type type, struct stack_info *info)
@@ -80,6 +83,21 @@ static inline bool on_stack(unsigned long sp, unsigned long size,
 	return true;
 }
 
+static inline bool on_accessible_stack_common(const struct task_struct *tsk,
+					      unsigned long sp,
+					      unsigned long size,
+					      struct stack_info *info)
+{
+	if (info)
+		info->type = STACK_TYPE_UNKNOWN;
+
+	/*
+	 * Both the kernel and nvhe hypervisor make use of
+	 * an overflow_stack
+	 */
+	return on_overflow_stack(sp, size, info);
+}
+
 static inline void unwind_init_common(struct unwind_state *state,
 				      struct task_struct *task)
 {
-- 
2.37.1.359.gd136c6c3e2-goog


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 112+ messages in thread

* [PATCH v6 03/17] arm64: stacktrace: Factor out unwind_next_common()
  2022-07-26  7:37 ` Kalesh Singh
  (?)
@ 2022-07-26  7:37   ` Kalesh Singh
  -1 siblings, 0 replies; 112+ messages in thread
From: Kalesh Singh @ 2022-07-26  7:37 UTC (permalink / raw)
  To: maz, mark.rutland, broonie, madvenka, tabba, oliver.upton
  Cc: wangkefeng.wang, catalin.marinas, ast, vincenzo.frascino, will,
	kvmarm, android-mm, kernel-team, elver, linux-arm-kernel,
	andreyknvl, linux-kernel, mhiramat

Move common unwind_next logic to stacktrace/common.h. This allows
reusing the code in the implementation the nVHE hypervisor stack
unwinder, later in this series.

Signed-off-by: Kalesh Singh <kaleshsingh@google.com>
Reviewed-by: Fuad Tabba <tabba@google.com>
Reviewed-by: Mark Brown <broonie@kernel.org>
Tested-by: Fuad Tabba <tabba@google.com>
---

Changes in v6:
  - Add Fuad's Tested-by tag

Changes in v5:
  - Add Reviewed-by tags from Mark Brown and Fuad

 arch/arm64/include/asm/stacktrace/common.h | 50 ++++++++++++++++++++++
 arch/arm64/kernel/stacktrace.c             | 41 ++----------------
 2 files changed, 54 insertions(+), 37 deletions(-)

diff --git a/arch/arm64/include/asm/stacktrace/common.h b/arch/arm64/include/asm/stacktrace/common.h
index f58b786460d3..0c5cbfdb56b5 100644
--- a/arch/arm64/include/asm/stacktrace/common.h
+++ b/arch/arm64/include/asm/stacktrace/common.h
@@ -65,6 +65,10 @@ struct unwind_state {
 static inline bool on_overflow_stack(unsigned long sp, unsigned long size,
 				     struct stack_info *info);
 
+static inline bool on_accessible_stack(const struct task_struct *tsk,
+				       unsigned long sp, unsigned long size,
+				       struct stack_info *info);
+
 static inline bool on_stack(unsigned long sp, unsigned long size,
 			    unsigned long low, unsigned long high,
 			    enum stack_type type, struct stack_info *info)
@@ -120,4 +124,50 @@ static inline void unwind_init_common(struct unwind_state *state,
 	state->prev_type = STACK_TYPE_UNKNOWN;
 }
 
+static inline int unwind_next_common(struct unwind_state *state,
+				     struct stack_info *info)
+{
+	struct task_struct *tsk = state->task;
+	unsigned long fp = state->fp;
+
+	if (fp & 0x7)
+		return -EINVAL;
+
+	if (!on_accessible_stack(tsk, fp, 16, info))
+		return -EINVAL;
+
+	if (test_bit(info->type, state->stacks_done))
+		return -EINVAL;
+
+	/*
+	 * As stacks grow downward, any valid record on the same stack must be
+	 * at a strictly higher address than the prior record.
+	 *
+	 * Stacks can nest in several valid orders, e.g.
+	 *
+	 * TASK -> IRQ -> OVERFLOW -> SDEI_NORMAL
+	 * TASK -> SDEI_NORMAL -> SDEI_CRITICAL -> OVERFLOW
+	 *
+	 * ... but the nesting itself is strict. Once we transition from one
+	 * stack to another, it's never valid to unwind back to that first
+	 * stack.
+	 */
+	if (info->type == state->prev_type) {
+		if (fp <= state->prev_fp)
+			return -EINVAL;
+	} else {
+		__set_bit(state->prev_type, state->stacks_done);
+	}
+
+	/*
+	 * Record this frame record's values and location. The prev_fp and
+	 * prev_type are only meaningful to the next unwind_next() invocation.
+	 */
+	state->fp = READ_ONCE(*(unsigned long *)(fp));
+	state->pc = READ_ONCE(*(unsigned long *)(fp + 8));
+	state->prev_fp = fp;
+	state->prev_type = info->type;
+
+	return 0;
+}
 #endif	/* __ASM_STACKTRACE_COMMON_H */
diff --git a/arch/arm64/kernel/stacktrace.c b/arch/arm64/kernel/stacktrace.c
index 94a5dd2ab8fd..834851939364 100644
--- a/arch/arm64/kernel/stacktrace.c
+++ b/arch/arm64/kernel/stacktrace.c
@@ -81,48 +81,15 @@ static int notrace unwind_next(struct unwind_state *state)
 	struct task_struct *tsk = state->task;
 	unsigned long fp = state->fp;
 	struct stack_info info;
+	int err;
 
 	/* Final frame; nothing to unwind */
 	if (fp == (unsigned long)task_pt_regs(tsk)->stackframe)
 		return -ENOENT;
 
-	if (fp & 0x7)
-		return -EINVAL;
-
-	if (!on_accessible_stack(tsk, fp, 16, &info))
-		return -EINVAL;
-
-	if (test_bit(info.type, state->stacks_done))
-		return -EINVAL;
-
-	/*
-	 * As stacks grow downward, any valid record on the same stack must be
-	 * at a strictly higher address than the prior record.
-	 *
-	 * Stacks can nest in several valid orders, e.g.
-	 *
-	 * TASK -> IRQ -> OVERFLOW -> SDEI_NORMAL
-	 * TASK -> SDEI_NORMAL -> SDEI_CRITICAL -> OVERFLOW
-	 *
-	 * ... but the nesting itself is strict. Once we transition from one
-	 * stack to another, it's never valid to unwind back to that first
-	 * stack.
-	 */
-	if (info.type == state->prev_type) {
-		if (fp <= state->prev_fp)
-			return -EINVAL;
-	} else {
-		__set_bit(state->prev_type, state->stacks_done);
-	}
-
-	/*
-	 * Record this frame record's values and location. The prev_fp and
-	 * prev_type are only meaningful to the next unwind_next() invocation.
-	 */
-	state->fp = READ_ONCE(*(unsigned long *)(fp));
-	state->pc = READ_ONCE(*(unsigned long *)(fp + 8));
-	state->prev_fp = fp;
-	state->prev_type = info.type;
+	err = unwind_next_common(state, &info);
+	if (err)
+		return err;
 
 	state->pc = ptrauth_strip_insn_pac(state->pc);
 
-- 
2.37.1.359.gd136c6c3e2-goog

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply related	[flat|nested] 112+ messages in thread

* [PATCH v6 03/17] arm64: stacktrace: Factor out unwind_next_common()
@ 2022-07-26  7:37   ` Kalesh Singh
  0 siblings, 0 replies; 112+ messages in thread
From: Kalesh Singh @ 2022-07-26  7:37 UTC (permalink / raw)
  To: maz, mark.rutland, broonie, madvenka, tabba, oliver.upton
  Cc: will, qperret, kaleshsingh, james.morse, alexandru.elisei,
	suzuki.poulose, catalin.marinas, andreyknvl, vincenzo.frascino,
	mhiramat, ast, wangkefeng.wang, elver, keirf, yuzenghui, ardb,
	oupton, linux-arm-kernel, kvmarm, linux-kernel, android-mm,
	kernel-team

Move common unwind_next logic to stacktrace/common.h. This allows
reusing the code in the implementation the nVHE hypervisor stack
unwinder, later in this series.

Signed-off-by: Kalesh Singh <kaleshsingh@google.com>
Reviewed-by: Fuad Tabba <tabba@google.com>
Reviewed-by: Mark Brown <broonie@kernel.org>
Tested-by: Fuad Tabba <tabba@google.com>
---

Changes in v6:
  - Add Fuad's Tested-by tag

Changes in v5:
  - Add Reviewed-by tags from Mark Brown and Fuad

 arch/arm64/include/asm/stacktrace/common.h | 50 ++++++++++++++++++++++
 arch/arm64/kernel/stacktrace.c             | 41 ++----------------
 2 files changed, 54 insertions(+), 37 deletions(-)

diff --git a/arch/arm64/include/asm/stacktrace/common.h b/arch/arm64/include/asm/stacktrace/common.h
index f58b786460d3..0c5cbfdb56b5 100644
--- a/arch/arm64/include/asm/stacktrace/common.h
+++ b/arch/arm64/include/asm/stacktrace/common.h
@@ -65,6 +65,10 @@ struct unwind_state {
 static inline bool on_overflow_stack(unsigned long sp, unsigned long size,
 				     struct stack_info *info);
 
+static inline bool on_accessible_stack(const struct task_struct *tsk,
+				       unsigned long sp, unsigned long size,
+				       struct stack_info *info);
+
 static inline bool on_stack(unsigned long sp, unsigned long size,
 			    unsigned long low, unsigned long high,
 			    enum stack_type type, struct stack_info *info)
@@ -120,4 +124,50 @@ static inline void unwind_init_common(struct unwind_state *state,
 	state->prev_type = STACK_TYPE_UNKNOWN;
 }
 
+static inline int unwind_next_common(struct unwind_state *state,
+				     struct stack_info *info)
+{
+	struct task_struct *tsk = state->task;
+	unsigned long fp = state->fp;
+
+	if (fp & 0x7)
+		return -EINVAL;
+
+	if (!on_accessible_stack(tsk, fp, 16, info))
+		return -EINVAL;
+
+	if (test_bit(info->type, state->stacks_done))
+		return -EINVAL;
+
+	/*
+	 * As stacks grow downward, any valid record on the same stack must be
+	 * at a strictly higher address than the prior record.
+	 *
+	 * Stacks can nest in several valid orders, e.g.
+	 *
+	 * TASK -> IRQ -> OVERFLOW -> SDEI_NORMAL
+	 * TASK -> SDEI_NORMAL -> SDEI_CRITICAL -> OVERFLOW
+	 *
+	 * ... but the nesting itself is strict. Once we transition from one
+	 * stack to another, it's never valid to unwind back to that first
+	 * stack.
+	 */
+	if (info->type == state->prev_type) {
+		if (fp <= state->prev_fp)
+			return -EINVAL;
+	} else {
+		__set_bit(state->prev_type, state->stacks_done);
+	}
+
+	/*
+	 * Record this frame record's values and location. The prev_fp and
+	 * prev_type are only meaningful to the next unwind_next() invocation.
+	 */
+	state->fp = READ_ONCE(*(unsigned long *)(fp));
+	state->pc = READ_ONCE(*(unsigned long *)(fp + 8));
+	state->prev_fp = fp;
+	state->prev_type = info->type;
+
+	return 0;
+}
 #endif	/* __ASM_STACKTRACE_COMMON_H */
diff --git a/arch/arm64/kernel/stacktrace.c b/arch/arm64/kernel/stacktrace.c
index 94a5dd2ab8fd..834851939364 100644
--- a/arch/arm64/kernel/stacktrace.c
+++ b/arch/arm64/kernel/stacktrace.c
@@ -81,48 +81,15 @@ static int notrace unwind_next(struct unwind_state *state)
 	struct task_struct *tsk = state->task;
 	unsigned long fp = state->fp;
 	struct stack_info info;
+	int err;
 
 	/* Final frame; nothing to unwind */
 	if (fp == (unsigned long)task_pt_regs(tsk)->stackframe)
 		return -ENOENT;
 
-	if (fp & 0x7)
-		return -EINVAL;
-
-	if (!on_accessible_stack(tsk, fp, 16, &info))
-		return -EINVAL;
-
-	if (test_bit(info.type, state->stacks_done))
-		return -EINVAL;
-
-	/*
-	 * As stacks grow downward, any valid record on the same stack must be
-	 * at a strictly higher address than the prior record.
-	 *
-	 * Stacks can nest in several valid orders, e.g.
-	 *
-	 * TASK -> IRQ -> OVERFLOW -> SDEI_NORMAL
-	 * TASK -> SDEI_NORMAL -> SDEI_CRITICAL -> OVERFLOW
-	 *
-	 * ... but the nesting itself is strict. Once we transition from one
-	 * stack to another, it's never valid to unwind back to that first
-	 * stack.
-	 */
-	if (info.type == state->prev_type) {
-		if (fp <= state->prev_fp)
-			return -EINVAL;
-	} else {
-		__set_bit(state->prev_type, state->stacks_done);
-	}
-
-	/*
-	 * Record this frame record's values and location. The prev_fp and
-	 * prev_type are only meaningful to the next unwind_next() invocation.
-	 */
-	state->fp = READ_ONCE(*(unsigned long *)(fp));
-	state->pc = READ_ONCE(*(unsigned long *)(fp + 8));
-	state->prev_fp = fp;
-	state->prev_type = info.type;
+	err = unwind_next_common(state, &info);
+	if (err)
+		return err;
 
 	state->pc = ptrauth_strip_insn_pac(state->pc);
 
-- 
2.37.1.359.gd136c6c3e2-goog


^ permalink raw reply related	[flat|nested] 112+ messages in thread

* [PATCH v6 03/17] arm64: stacktrace: Factor out unwind_next_common()
@ 2022-07-26  7:37   ` Kalesh Singh
  0 siblings, 0 replies; 112+ messages in thread
From: Kalesh Singh @ 2022-07-26  7:37 UTC (permalink / raw)
  To: maz, mark.rutland, broonie, madvenka, tabba, oliver.upton
  Cc: will, qperret, kaleshsingh, james.morse, alexandru.elisei,
	suzuki.poulose, catalin.marinas, andreyknvl, vincenzo.frascino,
	mhiramat, ast, wangkefeng.wang, elver, keirf, yuzenghui, ardb,
	oupton, linux-arm-kernel, kvmarm, linux-kernel, android-mm,
	kernel-team

Move common unwind_next logic to stacktrace/common.h. This allows
reusing the code in the implementation the nVHE hypervisor stack
unwinder, later in this series.

Signed-off-by: Kalesh Singh <kaleshsingh@google.com>
Reviewed-by: Fuad Tabba <tabba@google.com>
Reviewed-by: Mark Brown <broonie@kernel.org>
Tested-by: Fuad Tabba <tabba@google.com>
---

Changes in v6:
  - Add Fuad's Tested-by tag

Changes in v5:
  - Add Reviewed-by tags from Mark Brown and Fuad

 arch/arm64/include/asm/stacktrace/common.h | 50 ++++++++++++++++++++++
 arch/arm64/kernel/stacktrace.c             | 41 ++----------------
 2 files changed, 54 insertions(+), 37 deletions(-)

diff --git a/arch/arm64/include/asm/stacktrace/common.h b/arch/arm64/include/asm/stacktrace/common.h
index f58b786460d3..0c5cbfdb56b5 100644
--- a/arch/arm64/include/asm/stacktrace/common.h
+++ b/arch/arm64/include/asm/stacktrace/common.h
@@ -65,6 +65,10 @@ struct unwind_state {
 static inline bool on_overflow_stack(unsigned long sp, unsigned long size,
 				     struct stack_info *info);
 
+static inline bool on_accessible_stack(const struct task_struct *tsk,
+				       unsigned long sp, unsigned long size,
+				       struct stack_info *info);
+
 static inline bool on_stack(unsigned long sp, unsigned long size,
 			    unsigned long low, unsigned long high,
 			    enum stack_type type, struct stack_info *info)
@@ -120,4 +124,50 @@ static inline void unwind_init_common(struct unwind_state *state,
 	state->prev_type = STACK_TYPE_UNKNOWN;
 }
 
+static inline int unwind_next_common(struct unwind_state *state,
+				     struct stack_info *info)
+{
+	struct task_struct *tsk = state->task;
+	unsigned long fp = state->fp;
+
+	if (fp & 0x7)
+		return -EINVAL;
+
+	if (!on_accessible_stack(tsk, fp, 16, info))
+		return -EINVAL;
+
+	if (test_bit(info->type, state->stacks_done))
+		return -EINVAL;
+
+	/*
+	 * As stacks grow downward, any valid record on the same stack must be
+	 * at a strictly higher address than the prior record.
+	 *
+	 * Stacks can nest in several valid orders, e.g.
+	 *
+	 * TASK -> IRQ -> OVERFLOW -> SDEI_NORMAL
+	 * TASK -> SDEI_NORMAL -> SDEI_CRITICAL -> OVERFLOW
+	 *
+	 * ... but the nesting itself is strict. Once we transition from one
+	 * stack to another, it's never valid to unwind back to that first
+	 * stack.
+	 */
+	if (info->type == state->prev_type) {
+		if (fp <= state->prev_fp)
+			return -EINVAL;
+	} else {
+		__set_bit(state->prev_type, state->stacks_done);
+	}
+
+	/*
+	 * Record this frame record's values and location. The prev_fp and
+	 * prev_type are only meaningful to the next unwind_next() invocation.
+	 */
+	state->fp = READ_ONCE(*(unsigned long *)(fp));
+	state->pc = READ_ONCE(*(unsigned long *)(fp + 8));
+	state->prev_fp = fp;
+	state->prev_type = info->type;
+
+	return 0;
+}
 #endif	/* __ASM_STACKTRACE_COMMON_H */
diff --git a/arch/arm64/kernel/stacktrace.c b/arch/arm64/kernel/stacktrace.c
index 94a5dd2ab8fd..834851939364 100644
--- a/arch/arm64/kernel/stacktrace.c
+++ b/arch/arm64/kernel/stacktrace.c
@@ -81,48 +81,15 @@ static int notrace unwind_next(struct unwind_state *state)
 	struct task_struct *tsk = state->task;
 	unsigned long fp = state->fp;
 	struct stack_info info;
+	int err;
 
 	/* Final frame; nothing to unwind */
 	if (fp == (unsigned long)task_pt_regs(tsk)->stackframe)
 		return -ENOENT;
 
-	if (fp & 0x7)
-		return -EINVAL;
-
-	if (!on_accessible_stack(tsk, fp, 16, &info))
-		return -EINVAL;
-
-	if (test_bit(info.type, state->stacks_done))
-		return -EINVAL;
-
-	/*
-	 * As stacks grow downward, any valid record on the same stack must be
-	 * at a strictly higher address than the prior record.
-	 *
-	 * Stacks can nest in several valid orders, e.g.
-	 *
-	 * TASK -> IRQ -> OVERFLOW -> SDEI_NORMAL
-	 * TASK -> SDEI_NORMAL -> SDEI_CRITICAL -> OVERFLOW
-	 *
-	 * ... but the nesting itself is strict. Once we transition from one
-	 * stack to another, it's never valid to unwind back to that first
-	 * stack.
-	 */
-	if (info.type == state->prev_type) {
-		if (fp <= state->prev_fp)
-			return -EINVAL;
-	} else {
-		__set_bit(state->prev_type, state->stacks_done);
-	}
-
-	/*
-	 * Record this frame record's values and location. The prev_fp and
-	 * prev_type are only meaningful to the next unwind_next() invocation.
-	 */
-	state->fp = READ_ONCE(*(unsigned long *)(fp));
-	state->pc = READ_ONCE(*(unsigned long *)(fp + 8));
-	state->prev_fp = fp;
-	state->prev_type = info.type;
+	err = unwind_next_common(state, &info);
+	if (err)
+		return err;
 
 	state->pc = ptrauth_strip_insn_pac(state->pc);
 
-- 
2.37.1.359.gd136c6c3e2-goog


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 112+ messages in thread

* [PATCH v6 04/17] arm64: stacktrace: Handle frame pointer from different address spaces
  2022-07-26  7:37 ` Kalesh Singh
  (?)
@ 2022-07-26  7:37   ` Kalesh Singh
  -1 siblings, 0 replies; 112+ messages in thread
From: Kalesh Singh @ 2022-07-26  7:37 UTC (permalink / raw)
  To: maz, mark.rutland, broonie, madvenka, tabba, oliver.upton
  Cc: wangkefeng.wang, catalin.marinas, ast, vincenzo.frascino, will,
	kvmarm, android-mm, kernel-team, elver, linux-arm-kernel,
	andreyknvl, linux-kernel, mhiramat

The unwinder code is made reusable so that it can be used to
unwind various types of stacks. One usecase is unwinding the
nVHE hyp stack from the host (EL1) in non-protected mode. This
means that the unwinder must be able to translate HYP stack
addresses to kernel addresses.

Add a callback (stack_trace_translate_fp_fn) to allow specifying
the translation function.

Signed-off-by: Kalesh Singh <kaleshsingh@google.com>
Reviewed-by: Fuad Tabba <tabba@google.com>
Tested-by: Fuad Tabba <tabba@google.com>
---

Changes in v6:
  - Fix typo in comment, per Fuad
  - Add Fuad’s Reviewed-by tag and Tested-by tags

Changes in v5:
  - Fix typo in commit text, per Fuad
  - Update unwind_next_common() to not have side effects on failure, per Fuad
  - Use regular comment instead of doc comments, per Fuad

 arch/arm64/include/asm/stacktrace/common.h | 29 +++++++++++++++++++---
 arch/arm64/kernel/stacktrace.c             |  2 +-
 2 files changed, 26 insertions(+), 5 deletions(-)

diff --git a/arch/arm64/include/asm/stacktrace/common.h b/arch/arm64/include/asm/stacktrace/common.h
index 0c5cbfdb56b5..b241edba5c76 100644
--- a/arch/arm64/include/asm/stacktrace/common.h
+++ b/arch/arm64/include/asm/stacktrace/common.h
@@ -124,11 +124,25 @@ static inline void unwind_init_common(struct unwind_state *state,
 	state->prev_type = STACK_TYPE_UNKNOWN;
 }
 
+/*
+ * stack_trace_translate_fp_fn() - Translates a non-kernel frame pointer to
+ * a kernel address.
+ *
+ * @fp:   the frame pointer to be updated to its kernel address.
+ * @type: the stack type associated with frame pointer @fp
+ *
+ * Returns true and success and @fp is updated to the corresponding
+ * kernel virtual address; otherwise returns false.
+ */
+typedef bool (*stack_trace_translate_fp_fn)(unsigned long *fp,
+					    enum stack_type type);
+
 static inline int unwind_next_common(struct unwind_state *state,
-				     struct stack_info *info)
+				     struct stack_info *info,
+				     stack_trace_translate_fp_fn translate_fp)
 {
+	unsigned long fp = state->fp, kern_fp = fp;
 	struct task_struct *tsk = state->task;
-	unsigned long fp = state->fp;
 
 	if (fp & 0x7)
 		return -EINVAL;
@@ -139,6 +153,13 @@ static inline int unwind_next_common(struct unwind_state *state,
 	if (test_bit(info->type, state->stacks_done))
 		return -EINVAL;
 
+	/*
+	 * If fp is not from the current address space perform the necessary
+	 * translation before dereferencing it to get the next fp.
+	 */
+	if (translate_fp && !translate_fp(&kern_fp, info->type))
+		return -EINVAL;
+
 	/*
 	 * As stacks grow downward, any valid record on the same stack must be
 	 * at a strictly higher address than the prior record.
@@ -163,8 +184,8 @@ static inline int unwind_next_common(struct unwind_state *state,
 	 * Record this frame record's values and location. The prev_fp and
 	 * prev_type are only meaningful to the next unwind_next() invocation.
 	 */
-	state->fp = READ_ONCE(*(unsigned long *)(fp));
-	state->pc = READ_ONCE(*(unsigned long *)(fp + 8));
+	state->fp = READ_ONCE(*(unsigned long *)(kern_fp));
+	state->pc = READ_ONCE(*(unsigned long *)(kern_fp + 8));
 	state->prev_fp = fp;
 	state->prev_type = info->type;
 
diff --git a/arch/arm64/kernel/stacktrace.c b/arch/arm64/kernel/stacktrace.c
index 834851939364..eef3cf6bf2d7 100644
--- a/arch/arm64/kernel/stacktrace.c
+++ b/arch/arm64/kernel/stacktrace.c
@@ -87,7 +87,7 @@ static int notrace unwind_next(struct unwind_state *state)
 	if (fp == (unsigned long)task_pt_regs(tsk)->stackframe)
 		return -ENOENT;
 
-	err = unwind_next_common(state, &info);
+	err = unwind_next_common(state, &info, NULL);
 	if (err)
 		return err;
 
-- 
2.37.1.359.gd136c6c3e2-goog

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply related	[flat|nested] 112+ messages in thread

* [PATCH v6 04/17] arm64: stacktrace: Handle frame pointer from different address spaces
@ 2022-07-26  7:37   ` Kalesh Singh
  0 siblings, 0 replies; 112+ messages in thread
From: Kalesh Singh @ 2022-07-26  7:37 UTC (permalink / raw)
  To: maz, mark.rutland, broonie, madvenka, tabba, oliver.upton
  Cc: will, qperret, kaleshsingh, james.morse, alexandru.elisei,
	suzuki.poulose, catalin.marinas, andreyknvl, vincenzo.frascino,
	mhiramat, ast, wangkefeng.wang, elver, keirf, yuzenghui, ardb,
	oupton, linux-arm-kernel, kvmarm, linux-kernel, android-mm,
	kernel-team

The unwinder code is made reusable so that it can be used to
unwind various types of stacks. One usecase is unwinding the
nVHE hyp stack from the host (EL1) in non-protected mode. This
means that the unwinder must be able to translate HYP stack
addresses to kernel addresses.

Add a callback (stack_trace_translate_fp_fn) to allow specifying
the translation function.

Signed-off-by: Kalesh Singh <kaleshsingh@google.com>
Reviewed-by: Fuad Tabba <tabba@google.com>
Tested-by: Fuad Tabba <tabba@google.com>
---

Changes in v6:
  - Fix typo in comment, per Fuad
  - Add Fuad’s Reviewed-by tag and Tested-by tags

Changes in v5:
  - Fix typo in commit text, per Fuad
  - Update unwind_next_common() to not have side effects on failure, per Fuad
  - Use regular comment instead of doc comments, per Fuad

 arch/arm64/include/asm/stacktrace/common.h | 29 +++++++++++++++++++---
 arch/arm64/kernel/stacktrace.c             |  2 +-
 2 files changed, 26 insertions(+), 5 deletions(-)

diff --git a/arch/arm64/include/asm/stacktrace/common.h b/arch/arm64/include/asm/stacktrace/common.h
index 0c5cbfdb56b5..b241edba5c76 100644
--- a/arch/arm64/include/asm/stacktrace/common.h
+++ b/arch/arm64/include/asm/stacktrace/common.h
@@ -124,11 +124,25 @@ static inline void unwind_init_common(struct unwind_state *state,
 	state->prev_type = STACK_TYPE_UNKNOWN;
 }
 
+/*
+ * stack_trace_translate_fp_fn() - Translates a non-kernel frame pointer to
+ * a kernel address.
+ *
+ * @fp:   the frame pointer to be updated to its kernel address.
+ * @type: the stack type associated with frame pointer @fp
+ *
+ * Returns true and success and @fp is updated to the corresponding
+ * kernel virtual address; otherwise returns false.
+ */
+typedef bool (*stack_trace_translate_fp_fn)(unsigned long *fp,
+					    enum stack_type type);
+
 static inline int unwind_next_common(struct unwind_state *state,
-				     struct stack_info *info)
+				     struct stack_info *info,
+				     stack_trace_translate_fp_fn translate_fp)
 {
+	unsigned long fp = state->fp, kern_fp = fp;
 	struct task_struct *tsk = state->task;
-	unsigned long fp = state->fp;
 
 	if (fp & 0x7)
 		return -EINVAL;
@@ -139,6 +153,13 @@ static inline int unwind_next_common(struct unwind_state *state,
 	if (test_bit(info->type, state->stacks_done))
 		return -EINVAL;
 
+	/*
+	 * If fp is not from the current address space perform the necessary
+	 * translation before dereferencing it to get the next fp.
+	 */
+	if (translate_fp && !translate_fp(&kern_fp, info->type))
+		return -EINVAL;
+
 	/*
 	 * As stacks grow downward, any valid record on the same stack must be
 	 * at a strictly higher address than the prior record.
@@ -163,8 +184,8 @@ static inline int unwind_next_common(struct unwind_state *state,
 	 * Record this frame record's values and location. The prev_fp and
 	 * prev_type are only meaningful to the next unwind_next() invocation.
 	 */
-	state->fp = READ_ONCE(*(unsigned long *)(fp));
-	state->pc = READ_ONCE(*(unsigned long *)(fp + 8));
+	state->fp = READ_ONCE(*(unsigned long *)(kern_fp));
+	state->pc = READ_ONCE(*(unsigned long *)(kern_fp + 8));
 	state->prev_fp = fp;
 	state->prev_type = info->type;
 
diff --git a/arch/arm64/kernel/stacktrace.c b/arch/arm64/kernel/stacktrace.c
index 834851939364..eef3cf6bf2d7 100644
--- a/arch/arm64/kernel/stacktrace.c
+++ b/arch/arm64/kernel/stacktrace.c
@@ -87,7 +87,7 @@ static int notrace unwind_next(struct unwind_state *state)
 	if (fp == (unsigned long)task_pt_regs(tsk)->stackframe)
 		return -ENOENT;
 
-	err = unwind_next_common(state, &info);
+	err = unwind_next_common(state, &info, NULL);
 	if (err)
 		return err;
 
-- 
2.37.1.359.gd136c6c3e2-goog


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 112+ messages in thread

* [PATCH v6 04/17] arm64: stacktrace: Handle frame pointer from different address spaces
@ 2022-07-26  7:37   ` Kalesh Singh
  0 siblings, 0 replies; 112+ messages in thread
From: Kalesh Singh @ 2022-07-26  7:37 UTC (permalink / raw)
  To: maz, mark.rutland, broonie, madvenka, tabba, oliver.upton
  Cc: will, qperret, kaleshsingh, james.morse, alexandru.elisei,
	suzuki.poulose, catalin.marinas, andreyknvl, vincenzo.frascino,
	mhiramat, ast, wangkefeng.wang, elver, keirf, yuzenghui, ardb,
	oupton, linux-arm-kernel, kvmarm, linux-kernel, android-mm,
	kernel-team

The unwinder code is made reusable so that it can be used to
unwind various types of stacks. One usecase is unwinding the
nVHE hyp stack from the host (EL1) in non-protected mode. This
means that the unwinder must be able to translate HYP stack
addresses to kernel addresses.

Add a callback (stack_trace_translate_fp_fn) to allow specifying
the translation function.

Signed-off-by: Kalesh Singh <kaleshsingh@google.com>
Reviewed-by: Fuad Tabba <tabba@google.com>
Tested-by: Fuad Tabba <tabba@google.com>
---

Changes in v6:
  - Fix typo in comment, per Fuad
  - Add Fuad’s Reviewed-by tag and Tested-by tags

Changes in v5:
  - Fix typo in commit text, per Fuad
  - Update unwind_next_common() to not have side effects on failure, per Fuad
  - Use regular comment instead of doc comments, per Fuad

 arch/arm64/include/asm/stacktrace/common.h | 29 +++++++++++++++++++---
 arch/arm64/kernel/stacktrace.c             |  2 +-
 2 files changed, 26 insertions(+), 5 deletions(-)

diff --git a/arch/arm64/include/asm/stacktrace/common.h b/arch/arm64/include/asm/stacktrace/common.h
index 0c5cbfdb56b5..b241edba5c76 100644
--- a/arch/arm64/include/asm/stacktrace/common.h
+++ b/arch/arm64/include/asm/stacktrace/common.h
@@ -124,11 +124,25 @@ static inline void unwind_init_common(struct unwind_state *state,
 	state->prev_type = STACK_TYPE_UNKNOWN;
 }
 
+/*
+ * stack_trace_translate_fp_fn() - Translates a non-kernel frame pointer to
+ * a kernel address.
+ *
+ * @fp:   the frame pointer to be updated to its kernel address.
+ * @type: the stack type associated with frame pointer @fp
+ *
+ * Returns true and success and @fp is updated to the corresponding
+ * kernel virtual address; otherwise returns false.
+ */
+typedef bool (*stack_trace_translate_fp_fn)(unsigned long *fp,
+					    enum stack_type type);
+
 static inline int unwind_next_common(struct unwind_state *state,
-				     struct stack_info *info)
+				     struct stack_info *info,
+				     stack_trace_translate_fp_fn translate_fp)
 {
+	unsigned long fp = state->fp, kern_fp = fp;
 	struct task_struct *tsk = state->task;
-	unsigned long fp = state->fp;
 
 	if (fp & 0x7)
 		return -EINVAL;
@@ -139,6 +153,13 @@ static inline int unwind_next_common(struct unwind_state *state,
 	if (test_bit(info->type, state->stacks_done))
 		return -EINVAL;
 
+	/*
+	 * If fp is not from the current address space perform the necessary
+	 * translation before dereferencing it to get the next fp.
+	 */
+	if (translate_fp && !translate_fp(&kern_fp, info->type))
+		return -EINVAL;
+
 	/*
 	 * As stacks grow downward, any valid record on the same stack must be
 	 * at a strictly higher address than the prior record.
@@ -163,8 +184,8 @@ static inline int unwind_next_common(struct unwind_state *state,
 	 * Record this frame record's values and location. The prev_fp and
 	 * prev_type are only meaningful to the next unwind_next() invocation.
 	 */
-	state->fp = READ_ONCE(*(unsigned long *)(fp));
-	state->pc = READ_ONCE(*(unsigned long *)(fp + 8));
+	state->fp = READ_ONCE(*(unsigned long *)(kern_fp));
+	state->pc = READ_ONCE(*(unsigned long *)(kern_fp + 8));
 	state->prev_fp = fp;
 	state->prev_type = info->type;
 
diff --git a/arch/arm64/kernel/stacktrace.c b/arch/arm64/kernel/stacktrace.c
index 834851939364..eef3cf6bf2d7 100644
--- a/arch/arm64/kernel/stacktrace.c
+++ b/arch/arm64/kernel/stacktrace.c
@@ -87,7 +87,7 @@ static int notrace unwind_next(struct unwind_state *state)
 	if (fp == (unsigned long)task_pt_regs(tsk)->stackframe)
 		return -ENOENT;
 
-	err = unwind_next_common(state, &info);
+	err = unwind_next_common(state, &info, NULL);
 	if (err)
 		return err;
 
-- 
2.37.1.359.gd136c6c3e2-goog


^ permalink raw reply related	[flat|nested] 112+ messages in thread

* [PATCH v6 05/17] arm64: stacktrace: Factor out common unwind()
  2022-07-26  7:37 ` Kalesh Singh
  (?)
@ 2022-07-26  7:37   ` Kalesh Singh
  -1 siblings, 0 replies; 112+ messages in thread
From: Kalesh Singh @ 2022-07-26  7:37 UTC (permalink / raw)
  To: maz, mark.rutland, broonie, madvenka, tabba, oliver.upton
  Cc: wangkefeng.wang, catalin.marinas, ast, vincenzo.frascino, will,
	kvmarm, android-mm, kernel-team, elver, linux-arm-kernel,
	andreyknvl, linux-kernel, mhiramat

Move unwind() to stacktrace/common.h, and as a result
the kernel unwind_next() to asm/stacktrace.h. This allow
reusing unwind() in the implementation of the nVHE HYP
stack unwinder, later in the series.

Signed-off-by: Kalesh Singh <kaleshsingh@google.com>
Reviewed-by: Fuad Tabba <tabba@google.com>
Reviewed-by: Mark Brown <broonie@kernel.org>
Tested-by: Fuad Tabba <tabba@google.com>
---

Changes in v6:
  - Add Mark Brown’s Reviewed-by tag
  - Add Fuad's Tested-by tag

Changes in v5:
  - Add Reviewed-by tag from Fuad

 arch/arm64/include/asm/stacktrace.h        | 51 ++++++++++++++++
 arch/arm64/include/asm/stacktrace/common.h | 19 ++++++
 arch/arm64/kernel/stacktrace.c             | 67 ----------------------
 3 files changed, 70 insertions(+), 67 deletions(-)

diff --git a/arch/arm64/include/asm/stacktrace.h b/arch/arm64/include/asm/stacktrace.h
index 43f4b4a6d383..ea828579a98b 100644
--- a/arch/arm64/include/asm/stacktrace.h
+++ b/arch/arm64/include/asm/stacktrace.h
@@ -11,6 +11,7 @@
 #include <linux/llist.h>
 
 #include <asm/memory.h>
+#include <asm/pointer_auth.h>
 #include <asm/ptrace.h>
 #include <asm/sdei.h>
 
@@ -80,4 +81,54 @@ static inline bool on_accessible_stack(const struct task_struct *tsk,
 	return false;
 }
 
+/*
+ * Unwind from one frame record (A) to the next frame record (B).
+ *
+ * We terminate early if the location of B indicates a malformed chain of frame
+ * records (e.g. a cycle), determined based on the location and fp value of A
+ * and the location (but not the fp value) of B.
+ */
+static inline int notrace unwind_next(struct unwind_state *state)
+{
+	struct task_struct *tsk = state->task;
+	unsigned long fp = state->fp;
+	struct stack_info info;
+	int err;
+
+	/* Final frame; nothing to unwind */
+	if (fp == (unsigned long)task_pt_regs(tsk)->stackframe)
+		return -ENOENT;
+
+	err = unwind_next_common(state, &info, NULL);
+	if (err)
+		return err;
+
+	state->pc = ptrauth_strip_insn_pac(state->pc);
+
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+	if (tsk->ret_stack &&
+		(state->pc == (unsigned long)return_to_handler)) {
+		unsigned long orig_pc;
+		/*
+		 * This is a case where function graph tracer has
+		 * modified a return address (LR) in a stack frame
+		 * to hook a function return.
+		 * So replace it to an original value.
+		 */
+		orig_pc = ftrace_graph_ret_addr(tsk, NULL, state->pc,
+						(void *)state->fp);
+		if (WARN_ON_ONCE(state->pc == orig_pc))
+			return -EINVAL;
+		state->pc = orig_pc;
+	}
+#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
+#ifdef CONFIG_KRETPROBES
+	if (is_kretprobe_trampoline(state->pc))
+		state->pc = kretprobe_find_ret_addr(tsk, (void *)state->fp, &state->kr_cur);
+#endif
+
+	return 0;
+}
+NOKPROBE_SYMBOL(unwind_next);
+
 #endif	/* __ASM_STACKTRACE_H */
diff --git a/arch/arm64/include/asm/stacktrace/common.h b/arch/arm64/include/asm/stacktrace/common.h
index b241edba5c76..4b632141d91c 100644
--- a/arch/arm64/include/asm/stacktrace/common.h
+++ b/arch/arm64/include/asm/stacktrace/common.h
@@ -9,6 +9,7 @@
 
 #include <linux/bitmap.h>
 #include <linux/bitops.h>
+#include <linux/kprobes.h>
 #include <linux/types.h>
 
 enum stack_type {
@@ -69,6 +70,8 @@ static inline bool on_accessible_stack(const struct task_struct *tsk,
 				       unsigned long sp, unsigned long size,
 				       struct stack_info *info);
 
+static inline int unwind_next(struct unwind_state *state);
+
 static inline bool on_stack(unsigned long sp, unsigned long size,
 			    unsigned long low, unsigned long high,
 			    enum stack_type type, struct stack_info *info)
@@ -191,4 +194,20 @@ static inline int unwind_next_common(struct unwind_state *state,
 
 	return 0;
 }
+
+static inline void notrace unwind(struct unwind_state *state,
+				  stack_trace_consume_fn consume_entry,
+				  void *cookie)
+{
+	while (1) {
+		int ret;
+
+		if (!consume_entry(cookie, state->pc))
+			break;
+		ret = unwind_next(state);
+		if (ret < 0)
+			break;
+	}
+}
+NOKPROBE_SYMBOL(unwind);
 #endif	/* __ASM_STACKTRACE_COMMON_H */
diff --git a/arch/arm64/kernel/stacktrace.c b/arch/arm64/kernel/stacktrace.c
index eef3cf6bf2d7..9fa60ee48499 100644
--- a/arch/arm64/kernel/stacktrace.c
+++ b/arch/arm64/kernel/stacktrace.c
@@ -7,14 +7,12 @@
 #include <linux/kernel.h>
 #include <linux/export.h>
 #include <linux/ftrace.h>
-#include <linux/kprobes.h>
 #include <linux/sched.h>
 #include <linux/sched/debug.h>
 #include <linux/sched/task_stack.h>
 #include <linux/stacktrace.h>
 
 #include <asm/irq.h>
-#include <asm/pointer_auth.h>
 #include <asm/stack_pointer.h>
 #include <asm/stacktrace.h>
 
@@ -69,71 +67,6 @@ static inline void unwind_init_from_task(struct unwind_state *state,
 	state->pc = thread_saved_pc(task);
 }
 
-/*
- * Unwind from one frame record (A) to the next frame record (B).
- *
- * We terminate early if the location of B indicates a malformed chain of frame
- * records (e.g. a cycle), determined based on the location and fp value of A
- * and the location (but not the fp value) of B.
- */
-static int notrace unwind_next(struct unwind_state *state)
-{
-	struct task_struct *tsk = state->task;
-	unsigned long fp = state->fp;
-	struct stack_info info;
-	int err;
-
-	/* Final frame; nothing to unwind */
-	if (fp == (unsigned long)task_pt_regs(tsk)->stackframe)
-		return -ENOENT;
-
-	err = unwind_next_common(state, &info, NULL);
-	if (err)
-		return err;
-
-	state->pc = ptrauth_strip_insn_pac(state->pc);
-
-#ifdef CONFIG_FUNCTION_GRAPH_TRACER
-	if (tsk->ret_stack &&
-		(state->pc == (unsigned long)return_to_handler)) {
-		unsigned long orig_pc;
-		/*
-		 * This is a case where function graph tracer has
-		 * modified a return address (LR) in a stack frame
-		 * to hook a function return.
-		 * So replace it to an original value.
-		 */
-		orig_pc = ftrace_graph_ret_addr(tsk, NULL, state->pc,
-						(void *)state->fp);
-		if (WARN_ON_ONCE(state->pc == orig_pc))
-			return -EINVAL;
-		state->pc = orig_pc;
-	}
-#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
-#ifdef CONFIG_KRETPROBES
-	if (is_kretprobe_trampoline(state->pc))
-		state->pc = kretprobe_find_ret_addr(tsk, (void *)state->fp, &state->kr_cur);
-#endif
-
-	return 0;
-}
-NOKPROBE_SYMBOL(unwind_next);
-
-static void notrace unwind(struct unwind_state *state,
-			   stack_trace_consume_fn consume_entry, void *cookie)
-{
-	while (1) {
-		int ret;
-
-		if (!consume_entry(cookie, state->pc))
-			break;
-		ret = unwind_next(state);
-		if (ret < 0)
-			break;
-	}
-}
-NOKPROBE_SYMBOL(unwind);
-
 static bool dump_backtrace_entry(void *arg, unsigned long where)
 {
 	char *loglvl = arg;
-- 
2.37.1.359.gd136c6c3e2-goog

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply related	[flat|nested] 112+ messages in thread

* [PATCH v6 05/17] arm64: stacktrace: Factor out common unwind()
@ 2022-07-26  7:37   ` Kalesh Singh
  0 siblings, 0 replies; 112+ messages in thread
From: Kalesh Singh @ 2022-07-26  7:37 UTC (permalink / raw)
  To: maz, mark.rutland, broonie, madvenka, tabba, oliver.upton
  Cc: will, qperret, kaleshsingh, james.morse, alexandru.elisei,
	suzuki.poulose, catalin.marinas, andreyknvl, vincenzo.frascino,
	mhiramat, ast, wangkefeng.wang, elver, keirf, yuzenghui, ardb,
	oupton, linux-arm-kernel, kvmarm, linux-kernel, android-mm,
	kernel-team

Move unwind() to stacktrace/common.h, and as a result
the kernel unwind_next() to asm/stacktrace.h. This allow
reusing unwind() in the implementation of the nVHE HYP
stack unwinder, later in the series.

Signed-off-by: Kalesh Singh <kaleshsingh@google.com>
Reviewed-by: Fuad Tabba <tabba@google.com>
Reviewed-by: Mark Brown <broonie@kernel.org>
Tested-by: Fuad Tabba <tabba@google.com>
---

Changes in v6:
  - Add Mark Brown’s Reviewed-by tag
  - Add Fuad's Tested-by tag

Changes in v5:
  - Add Reviewed-by tag from Fuad

 arch/arm64/include/asm/stacktrace.h        | 51 ++++++++++++++++
 arch/arm64/include/asm/stacktrace/common.h | 19 ++++++
 arch/arm64/kernel/stacktrace.c             | 67 ----------------------
 3 files changed, 70 insertions(+), 67 deletions(-)

diff --git a/arch/arm64/include/asm/stacktrace.h b/arch/arm64/include/asm/stacktrace.h
index 43f4b4a6d383..ea828579a98b 100644
--- a/arch/arm64/include/asm/stacktrace.h
+++ b/arch/arm64/include/asm/stacktrace.h
@@ -11,6 +11,7 @@
 #include <linux/llist.h>
 
 #include <asm/memory.h>
+#include <asm/pointer_auth.h>
 #include <asm/ptrace.h>
 #include <asm/sdei.h>
 
@@ -80,4 +81,54 @@ static inline bool on_accessible_stack(const struct task_struct *tsk,
 	return false;
 }
 
+/*
+ * Unwind from one frame record (A) to the next frame record (B).
+ *
+ * We terminate early if the location of B indicates a malformed chain of frame
+ * records (e.g. a cycle), determined based on the location and fp value of A
+ * and the location (but not the fp value) of B.
+ */
+static inline int notrace unwind_next(struct unwind_state *state)
+{
+	struct task_struct *tsk = state->task;
+	unsigned long fp = state->fp;
+	struct stack_info info;
+	int err;
+
+	/* Final frame; nothing to unwind */
+	if (fp == (unsigned long)task_pt_regs(tsk)->stackframe)
+		return -ENOENT;
+
+	err = unwind_next_common(state, &info, NULL);
+	if (err)
+		return err;
+
+	state->pc = ptrauth_strip_insn_pac(state->pc);
+
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+	if (tsk->ret_stack &&
+		(state->pc == (unsigned long)return_to_handler)) {
+		unsigned long orig_pc;
+		/*
+		 * This is a case where function graph tracer has
+		 * modified a return address (LR) in a stack frame
+		 * to hook a function return.
+		 * So replace it to an original value.
+		 */
+		orig_pc = ftrace_graph_ret_addr(tsk, NULL, state->pc,
+						(void *)state->fp);
+		if (WARN_ON_ONCE(state->pc == orig_pc))
+			return -EINVAL;
+		state->pc = orig_pc;
+	}
+#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
+#ifdef CONFIG_KRETPROBES
+	if (is_kretprobe_trampoline(state->pc))
+		state->pc = kretprobe_find_ret_addr(tsk, (void *)state->fp, &state->kr_cur);
+#endif
+
+	return 0;
+}
+NOKPROBE_SYMBOL(unwind_next);
+
 #endif	/* __ASM_STACKTRACE_H */
diff --git a/arch/arm64/include/asm/stacktrace/common.h b/arch/arm64/include/asm/stacktrace/common.h
index b241edba5c76..4b632141d91c 100644
--- a/arch/arm64/include/asm/stacktrace/common.h
+++ b/arch/arm64/include/asm/stacktrace/common.h
@@ -9,6 +9,7 @@
 
 #include <linux/bitmap.h>
 #include <linux/bitops.h>
+#include <linux/kprobes.h>
 #include <linux/types.h>
 
 enum stack_type {
@@ -69,6 +70,8 @@ static inline bool on_accessible_stack(const struct task_struct *tsk,
 				       unsigned long sp, unsigned long size,
 				       struct stack_info *info);
 
+static inline int unwind_next(struct unwind_state *state);
+
 static inline bool on_stack(unsigned long sp, unsigned long size,
 			    unsigned long low, unsigned long high,
 			    enum stack_type type, struct stack_info *info)
@@ -191,4 +194,20 @@ static inline int unwind_next_common(struct unwind_state *state,
 
 	return 0;
 }
+
+static inline void notrace unwind(struct unwind_state *state,
+				  stack_trace_consume_fn consume_entry,
+				  void *cookie)
+{
+	while (1) {
+		int ret;
+
+		if (!consume_entry(cookie, state->pc))
+			break;
+		ret = unwind_next(state);
+		if (ret < 0)
+			break;
+	}
+}
+NOKPROBE_SYMBOL(unwind);
 #endif	/* __ASM_STACKTRACE_COMMON_H */
diff --git a/arch/arm64/kernel/stacktrace.c b/arch/arm64/kernel/stacktrace.c
index eef3cf6bf2d7..9fa60ee48499 100644
--- a/arch/arm64/kernel/stacktrace.c
+++ b/arch/arm64/kernel/stacktrace.c
@@ -7,14 +7,12 @@
 #include <linux/kernel.h>
 #include <linux/export.h>
 #include <linux/ftrace.h>
-#include <linux/kprobes.h>
 #include <linux/sched.h>
 #include <linux/sched/debug.h>
 #include <linux/sched/task_stack.h>
 #include <linux/stacktrace.h>
 
 #include <asm/irq.h>
-#include <asm/pointer_auth.h>
 #include <asm/stack_pointer.h>
 #include <asm/stacktrace.h>
 
@@ -69,71 +67,6 @@ static inline void unwind_init_from_task(struct unwind_state *state,
 	state->pc = thread_saved_pc(task);
 }
 
-/*
- * Unwind from one frame record (A) to the next frame record (B).
- *
- * We terminate early if the location of B indicates a malformed chain of frame
- * records (e.g. a cycle), determined based on the location and fp value of A
- * and the location (but not the fp value) of B.
- */
-static int notrace unwind_next(struct unwind_state *state)
-{
-	struct task_struct *tsk = state->task;
-	unsigned long fp = state->fp;
-	struct stack_info info;
-	int err;
-
-	/* Final frame; nothing to unwind */
-	if (fp == (unsigned long)task_pt_regs(tsk)->stackframe)
-		return -ENOENT;
-
-	err = unwind_next_common(state, &info, NULL);
-	if (err)
-		return err;
-
-	state->pc = ptrauth_strip_insn_pac(state->pc);
-
-#ifdef CONFIG_FUNCTION_GRAPH_TRACER
-	if (tsk->ret_stack &&
-		(state->pc == (unsigned long)return_to_handler)) {
-		unsigned long orig_pc;
-		/*
-		 * This is a case where function graph tracer has
-		 * modified a return address (LR) in a stack frame
-		 * to hook a function return.
-		 * So replace it to an original value.
-		 */
-		orig_pc = ftrace_graph_ret_addr(tsk, NULL, state->pc,
-						(void *)state->fp);
-		if (WARN_ON_ONCE(state->pc == orig_pc))
-			return -EINVAL;
-		state->pc = orig_pc;
-	}
-#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
-#ifdef CONFIG_KRETPROBES
-	if (is_kretprobe_trampoline(state->pc))
-		state->pc = kretprobe_find_ret_addr(tsk, (void *)state->fp, &state->kr_cur);
-#endif
-
-	return 0;
-}
-NOKPROBE_SYMBOL(unwind_next);
-
-static void notrace unwind(struct unwind_state *state,
-			   stack_trace_consume_fn consume_entry, void *cookie)
-{
-	while (1) {
-		int ret;
-
-		if (!consume_entry(cookie, state->pc))
-			break;
-		ret = unwind_next(state);
-		if (ret < 0)
-			break;
-	}
-}
-NOKPROBE_SYMBOL(unwind);
-
 static bool dump_backtrace_entry(void *arg, unsigned long where)
 {
 	char *loglvl = arg;
-- 
2.37.1.359.gd136c6c3e2-goog


^ permalink raw reply related	[flat|nested] 112+ messages in thread

* [PATCH v6 05/17] arm64: stacktrace: Factor out common unwind()
@ 2022-07-26  7:37   ` Kalesh Singh
  0 siblings, 0 replies; 112+ messages in thread
From: Kalesh Singh @ 2022-07-26  7:37 UTC (permalink / raw)
  To: maz, mark.rutland, broonie, madvenka, tabba, oliver.upton
  Cc: will, qperret, kaleshsingh, james.morse, alexandru.elisei,
	suzuki.poulose, catalin.marinas, andreyknvl, vincenzo.frascino,
	mhiramat, ast, wangkefeng.wang, elver, keirf, yuzenghui, ardb,
	oupton, linux-arm-kernel, kvmarm, linux-kernel, android-mm,
	kernel-team

Move unwind() to stacktrace/common.h, and as a result
the kernel unwind_next() to asm/stacktrace.h. This allow
reusing unwind() in the implementation of the nVHE HYP
stack unwinder, later in the series.

Signed-off-by: Kalesh Singh <kaleshsingh@google.com>
Reviewed-by: Fuad Tabba <tabba@google.com>
Reviewed-by: Mark Brown <broonie@kernel.org>
Tested-by: Fuad Tabba <tabba@google.com>
---

Changes in v6:
  - Add Mark Brown’s Reviewed-by tag
  - Add Fuad's Tested-by tag

Changes in v5:
  - Add Reviewed-by tag from Fuad

 arch/arm64/include/asm/stacktrace.h        | 51 ++++++++++++++++
 arch/arm64/include/asm/stacktrace/common.h | 19 ++++++
 arch/arm64/kernel/stacktrace.c             | 67 ----------------------
 3 files changed, 70 insertions(+), 67 deletions(-)

diff --git a/arch/arm64/include/asm/stacktrace.h b/arch/arm64/include/asm/stacktrace.h
index 43f4b4a6d383..ea828579a98b 100644
--- a/arch/arm64/include/asm/stacktrace.h
+++ b/arch/arm64/include/asm/stacktrace.h
@@ -11,6 +11,7 @@
 #include <linux/llist.h>
 
 #include <asm/memory.h>
+#include <asm/pointer_auth.h>
 #include <asm/ptrace.h>
 #include <asm/sdei.h>
 
@@ -80,4 +81,54 @@ static inline bool on_accessible_stack(const struct task_struct *tsk,
 	return false;
 }
 
+/*
+ * Unwind from one frame record (A) to the next frame record (B).
+ *
+ * We terminate early if the location of B indicates a malformed chain of frame
+ * records (e.g. a cycle), determined based on the location and fp value of A
+ * and the location (but not the fp value) of B.
+ */
+static inline int notrace unwind_next(struct unwind_state *state)
+{
+	struct task_struct *tsk = state->task;
+	unsigned long fp = state->fp;
+	struct stack_info info;
+	int err;
+
+	/* Final frame; nothing to unwind */
+	if (fp == (unsigned long)task_pt_regs(tsk)->stackframe)
+		return -ENOENT;
+
+	err = unwind_next_common(state, &info, NULL);
+	if (err)
+		return err;
+
+	state->pc = ptrauth_strip_insn_pac(state->pc);
+
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+	if (tsk->ret_stack &&
+		(state->pc == (unsigned long)return_to_handler)) {
+		unsigned long orig_pc;
+		/*
+		 * This is a case where function graph tracer has
+		 * modified a return address (LR) in a stack frame
+		 * to hook a function return.
+		 * So replace it to an original value.
+		 */
+		orig_pc = ftrace_graph_ret_addr(tsk, NULL, state->pc,
+						(void *)state->fp);
+		if (WARN_ON_ONCE(state->pc == orig_pc))
+			return -EINVAL;
+		state->pc = orig_pc;
+	}
+#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
+#ifdef CONFIG_KRETPROBES
+	if (is_kretprobe_trampoline(state->pc))
+		state->pc = kretprobe_find_ret_addr(tsk, (void *)state->fp, &state->kr_cur);
+#endif
+
+	return 0;
+}
+NOKPROBE_SYMBOL(unwind_next);
+
 #endif	/* __ASM_STACKTRACE_H */
diff --git a/arch/arm64/include/asm/stacktrace/common.h b/arch/arm64/include/asm/stacktrace/common.h
index b241edba5c76..4b632141d91c 100644
--- a/arch/arm64/include/asm/stacktrace/common.h
+++ b/arch/arm64/include/asm/stacktrace/common.h
@@ -9,6 +9,7 @@
 
 #include <linux/bitmap.h>
 #include <linux/bitops.h>
+#include <linux/kprobes.h>
 #include <linux/types.h>
 
 enum stack_type {
@@ -69,6 +70,8 @@ static inline bool on_accessible_stack(const struct task_struct *tsk,
 				       unsigned long sp, unsigned long size,
 				       struct stack_info *info);
 
+static inline int unwind_next(struct unwind_state *state);
+
 static inline bool on_stack(unsigned long sp, unsigned long size,
 			    unsigned long low, unsigned long high,
 			    enum stack_type type, struct stack_info *info)
@@ -191,4 +194,20 @@ static inline int unwind_next_common(struct unwind_state *state,
 
 	return 0;
 }
+
+static inline void notrace unwind(struct unwind_state *state,
+				  stack_trace_consume_fn consume_entry,
+				  void *cookie)
+{
+	while (1) {
+		int ret;
+
+		if (!consume_entry(cookie, state->pc))
+			break;
+		ret = unwind_next(state);
+		if (ret < 0)
+			break;
+	}
+}
+NOKPROBE_SYMBOL(unwind);
 #endif	/* __ASM_STACKTRACE_COMMON_H */
diff --git a/arch/arm64/kernel/stacktrace.c b/arch/arm64/kernel/stacktrace.c
index eef3cf6bf2d7..9fa60ee48499 100644
--- a/arch/arm64/kernel/stacktrace.c
+++ b/arch/arm64/kernel/stacktrace.c
@@ -7,14 +7,12 @@
 #include <linux/kernel.h>
 #include <linux/export.h>
 #include <linux/ftrace.h>
-#include <linux/kprobes.h>
 #include <linux/sched.h>
 #include <linux/sched/debug.h>
 #include <linux/sched/task_stack.h>
 #include <linux/stacktrace.h>
 
 #include <asm/irq.h>
-#include <asm/pointer_auth.h>
 #include <asm/stack_pointer.h>
 #include <asm/stacktrace.h>
 
@@ -69,71 +67,6 @@ static inline void unwind_init_from_task(struct unwind_state *state,
 	state->pc = thread_saved_pc(task);
 }
 
-/*
- * Unwind from one frame record (A) to the next frame record (B).
- *
- * We terminate early if the location of B indicates a malformed chain of frame
- * records (e.g. a cycle), determined based on the location and fp value of A
- * and the location (but not the fp value) of B.
- */
-static int notrace unwind_next(struct unwind_state *state)
-{
-	struct task_struct *tsk = state->task;
-	unsigned long fp = state->fp;
-	struct stack_info info;
-	int err;
-
-	/* Final frame; nothing to unwind */
-	if (fp == (unsigned long)task_pt_regs(tsk)->stackframe)
-		return -ENOENT;
-
-	err = unwind_next_common(state, &info, NULL);
-	if (err)
-		return err;
-
-	state->pc = ptrauth_strip_insn_pac(state->pc);
-
-#ifdef CONFIG_FUNCTION_GRAPH_TRACER
-	if (tsk->ret_stack &&
-		(state->pc == (unsigned long)return_to_handler)) {
-		unsigned long orig_pc;
-		/*
-		 * This is a case where function graph tracer has
-		 * modified a return address (LR) in a stack frame
-		 * to hook a function return.
-		 * So replace it to an original value.
-		 */
-		orig_pc = ftrace_graph_ret_addr(tsk, NULL, state->pc,
-						(void *)state->fp);
-		if (WARN_ON_ONCE(state->pc == orig_pc))
-			return -EINVAL;
-		state->pc = orig_pc;
-	}
-#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
-#ifdef CONFIG_KRETPROBES
-	if (is_kretprobe_trampoline(state->pc))
-		state->pc = kretprobe_find_ret_addr(tsk, (void *)state->fp, &state->kr_cur);
-#endif
-
-	return 0;
-}
-NOKPROBE_SYMBOL(unwind_next);
-
-static void notrace unwind(struct unwind_state *state,
-			   stack_trace_consume_fn consume_entry, void *cookie)
-{
-	while (1) {
-		int ret;
-
-		if (!consume_entry(cookie, state->pc))
-			break;
-		ret = unwind_next(state);
-		if (ret < 0)
-			break;
-	}
-}
-NOKPROBE_SYMBOL(unwind);
-
 static bool dump_backtrace_entry(void *arg, unsigned long where)
 {
 	char *loglvl = arg;
-- 
2.37.1.359.gd136c6c3e2-goog


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 112+ messages in thread

* [PATCH v6 06/17] arm64: stacktrace: Add description of stacktrace/common.h
  2022-07-26  7:37 ` Kalesh Singh
  (?)
@ 2022-07-26  7:37   ` Kalesh Singh
  -1 siblings, 0 replies; 112+ messages in thread
From: Kalesh Singh @ 2022-07-26  7:37 UTC (permalink / raw)
  To: maz, mark.rutland, broonie, madvenka, tabba, oliver.upton
  Cc: wangkefeng.wang, catalin.marinas, ast, vincenzo.frascino, will,
	kvmarm, android-mm, kernel-team, elver, linux-arm-kernel,
	andreyknvl, linux-kernel, mhiramat

Add brief description on how to use stacktrace/common.h to implement
a stack unwinder.

Signed-off-by: Kalesh Singh <kaleshsingh@google.com>
Reviewed-by: Fuad Tabba <tabba@google.com>
---

Changes in v6:
  - Add Fuad’s Reviewed-by tag

Changes in v5:
  - Add short description of each required function, per Fuad and Marc

 arch/arm64/include/asm/stacktrace/common.h | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/arch/arm64/include/asm/stacktrace/common.h b/arch/arm64/include/asm/stacktrace/common.h
index 4b632141d91c..45474b383630 100644
--- a/arch/arm64/include/asm/stacktrace/common.h
+++ b/arch/arm64/include/asm/stacktrace/common.h
@@ -2,6 +2,21 @@
 /*
  * Common arm64 stack unwinder code.
  *
+ * To implement a new arm64 stack unwinder:
+ *     1) Include this header
+ *
+ *     2) Provide implementations for the following functions:
+ *          on_overflow_stack():   Returns true if SP is on the overflow
+ *                                 stack.
+ *          on_accessible_stack(): Returns true is SP is on any accessible
+ *                                 stack.
+ *          unwind_next():         Performs validation checks on the frame
+ *                                 pointer, and transitions unwind_state
+ *                                 to the next frame.
+ *
+ *         See: arch/arm64/include/asm/stacktrace.h for reference
+ *              implementations.
+ *
  * Copyright (C) 2012 ARM Ltd.
  */
 #ifndef __ASM_STACKTRACE_COMMON_H
-- 
2.37.1.359.gd136c6c3e2-goog

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply related	[flat|nested] 112+ messages in thread

* [PATCH v6 06/17] arm64: stacktrace: Add description of stacktrace/common.h
@ 2022-07-26  7:37   ` Kalesh Singh
  0 siblings, 0 replies; 112+ messages in thread
From: Kalesh Singh @ 2022-07-26  7:37 UTC (permalink / raw)
  To: maz, mark.rutland, broonie, madvenka, tabba, oliver.upton
  Cc: will, qperret, kaleshsingh, james.morse, alexandru.elisei,
	suzuki.poulose, catalin.marinas, andreyknvl, vincenzo.frascino,
	mhiramat, ast, wangkefeng.wang, elver, keirf, yuzenghui, ardb,
	oupton, linux-arm-kernel, kvmarm, linux-kernel, android-mm,
	kernel-team

Add brief description on how to use stacktrace/common.h to implement
a stack unwinder.

Signed-off-by: Kalesh Singh <kaleshsingh@google.com>
Reviewed-by: Fuad Tabba <tabba@google.com>
---

Changes in v6:
  - Add Fuad’s Reviewed-by tag

Changes in v5:
  - Add short description of each required function, per Fuad and Marc

 arch/arm64/include/asm/stacktrace/common.h | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/arch/arm64/include/asm/stacktrace/common.h b/arch/arm64/include/asm/stacktrace/common.h
index 4b632141d91c..45474b383630 100644
--- a/arch/arm64/include/asm/stacktrace/common.h
+++ b/arch/arm64/include/asm/stacktrace/common.h
@@ -2,6 +2,21 @@
 /*
  * Common arm64 stack unwinder code.
  *
+ * To implement a new arm64 stack unwinder:
+ *     1) Include this header
+ *
+ *     2) Provide implementations for the following functions:
+ *          on_overflow_stack():   Returns true if SP is on the overflow
+ *                                 stack.
+ *          on_accessible_stack(): Returns true is SP is on any accessible
+ *                                 stack.
+ *          unwind_next():         Performs validation checks on the frame
+ *                                 pointer, and transitions unwind_state
+ *                                 to the next frame.
+ *
+ *         See: arch/arm64/include/asm/stacktrace.h for reference
+ *              implementations.
+ *
  * Copyright (C) 2012 ARM Ltd.
  */
 #ifndef __ASM_STACKTRACE_COMMON_H
-- 
2.37.1.359.gd136c6c3e2-goog


^ permalink raw reply related	[flat|nested] 112+ messages in thread

* [PATCH v6 06/17] arm64: stacktrace: Add description of stacktrace/common.h
@ 2022-07-26  7:37   ` Kalesh Singh
  0 siblings, 0 replies; 112+ messages in thread
From: Kalesh Singh @ 2022-07-26  7:37 UTC (permalink / raw)
  To: maz, mark.rutland, broonie, madvenka, tabba, oliver.upton
  Cc: will, qperret, kaleshsingh, james.morse, alexandru.elisei,
	suzuki.poulose, catalin.marinas, andreyknvl, vincenzo.frascino,
	mhiramat, ast, wangkefeng.wang, elver, keirf, yuzenghui, ardb,
	oupton, linux-arm-kernel, kvmarm, linux-kernel, android-mm,
	kernel-team

Add brief description on how to use stacktrace/common.h to implement
a stack unwinder.

Signed-off-by: Kalesh Singh <kaleshsingh@google.com>
Reviewed-by: Fuad Tabba <tabba@google.com>
---

Changes in v6:
  - Add Fuad’s Reviewed-by tag

Changes in v5:
  - Add short description of each required function, per Fuad and Marc

 arch/arm64/include/asm/stacktrace/common.h | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/arch/arm64/include/asm/stacktrace/common.h b/arch/arm64/include/asm/stacktrace/common.h
index 4b632141d91c..45474b383630 100644
--- a/arch/arm64/include/asm/stacktrace/common.h
+++ b/arch/arm64/include/asm/stacktrace/common.h
@@ -2,6 +2,21 @@
 /*
  * Common arm64 stack unwinder code.
  *
+ * To implement a new arm64 stack unwinder:
+ *     1) Include this header
+ *
+ *     2) Provide implementations for the following functions:
+ *          on_overflow_stack():   Returns true if SP is on the overflow
+ *                                 stack.
+ *          on_accessible_stack(): Returns true is SP is on any accessible
+ *                                 stack.
+ *          unwind_next():         Performs validation checks on the frame
+ *                                 pointer, and transitions unwind_state
+ *                                 to the next frame.
+ *
+ *         See: arch/arm64/include/asm/stacktrace.h for reference
+ *              implementations.
+ *
  * Copyright (C) 2012 ARM Ltd.
  */
 #ifndef __ASM_STACKTRACE_COMMON_H
-- 
2.37.1.359.gd136c6c3e2-goog


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 112+ messages in thread

* [PATCH v6 07/17] KVM: arm64: On stack overflow switch to hyp overflow_stack
  2022-07-26  7:37 ` Kalesh Singh
  (?)
@ 2022-07-26  7:37   ` Kalesh Singh
  -1 siblings, 0 replies; 112+ messages in thread
From: Kalesh Singh @ 2022-07-26  7:37 UTC (permalink / raw)
  To: maz, mark.rutland, broonie, madvenka, tabba, oliver.upton
  Cc: wangkefeng.wang, catalin.marinas, ast, vincenzo.frascino, will,
	kvmarm, android-mm, kernel-team, elver, linux-arm-kernel,
	andreyknvl, linux-kernel, mhiramat

On hyp stack overflow switch to 16-byte aligned secondary stack.
This provides us stack space to better handle overflows; and is
used in a subsequent patch to dump the hypervisor stacktrace.

Signed-off-by: Kalesh Singh <kaleshsingh@google.com>
Reviewed-by: Fuad Tabba <tabba@google.com>
Tested-by: Fuad Tabba <tabba@google.com>
---

Changes in v6:
  - Add Fuad's Tested-by tag

Changes in v5:
  - Add Reviewed-by tag from Fuad

 arch/arm64/kvm/hyp/nvhe/Makefile     |  2 +-
 arch/arm64/kvm/hyp/nvhe/host.S       |  9 ++-------
 arch/arm64/kvm/hyp/nvhe/stacktrace.c | 11 +++++++++++
 3 files changed, 14 insertions(+), 8 deletions(-)
 create mode 100644 arch/arm64/kvm/hyp/nvhe/stacktrace.c

diff --git a/arch/arm64/kvm/hyp/nvhe/Makefile b/arch/arm64/kvm/hyp/nvhe/Makefile
index f9fe4dc21b1f..524e7dad5739 100644
--- a/arch/arm64/kvm/hyp/nvhe/Makefile
+++ b/arch/arm64/kvm/hyp/nvhe/Makefile
@@ -14,7 +14,7 @@ lib-objs := $(addprefix ../../../lib/, $(lib-objs))
 
 obj-y := timer-sr.o sysreg-sr.o debug-sr.o switch.o tlb.o hyp-init.o host.o \
 	 hyp-main.o hyp-smp.o psci-relay.o early_alloc.o page_alloc.o \
-	 cache.o setup.o mm.o mem_protect.o sys_regs.o pkvm.o
+	 cache.o setup.o mm.o mem_protect.o sys_regs.o pkvm.o stacktrace.o
 obj-y += ../vgic-v3-sr.o ../aarch32.o ../vgic-v2-cpuif-proxy.o ../entry.o \
 	 ../fpsimd.o ../hyp-entry.o ../exception.o ../pgtable.o
 obj-$(CONFIG_DEBUG_LIST) += list_debug.o
diff --git a/arch/arm64/kvm/hyp/nvhe/host.S b/arch/arm64/kvm/hyp/nvhe/host.S
index ea6a397b64a6..b6c0188c4b35 100644
--- a/arch/arm64/kvm/hyp/nvhe/host.S
+++ b/arch/arm64/kvm/hyp/nvhe/host.S
@@ -177,13 +177,8 @@ SYM_FUNC_END(__host_hvc)
 	b	hyp_panic
 
 .L__hyp_sp_overflow\@:
-	/*
-	 * Reset SP to the top of the stack, to allow handling the hyp_panic.
-	 * This corrupts the stack but is ok, since we won't be attempting
-	 * any unwinding here.
-	 */
-	ldr_this_cpu	x0, kvm_init_params + NVHE_INIT_STACK_HYP_VA, x1
-	mov	sp, x0
+	/* Switch to the overflow stack */
+	adr_this_cpu sp, overflow_stack + OVERFLOW_STACK_SIZE, x0
 
 	b	hyp_panic_bad_stack
 	ASM_BUG()
diff --git a/arch/arm64/kvm/hyp/nvhe/stacktrace.c b/arch/arm64/kvm/hyp/nvhe/stacktrace.c
new file mode 100644
index 000000000000..a3d5b34e1249
--- /dev/null
+++ b/arch/arm64/kvm/hyp/nvhe/stacktrace.c
@@ -0,0 +1,11 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * KVM nVHE hypervisor stack tracing support.
+ *
+ * Copyright (C) 2022 Google LLC
+ */
+#include <asm/memory.h>
+#include <asm/percpu.h>
+
+DEFINE_PER_CPU(unsigned long [OVERFLOW_STACK_SIZE/sizeof(long)], overflow_stack)
+	__aligned(16);
-- 
2.37.1.359.gd136c6c3e2-goog

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply related	[flat|nested] 112+ messages in thread

* [PATCH v6 07/17] KVM: arm64: On stack overflow switch to hyp overflow_stack
@ 2022-07-26  7:37   ` Kalesh Singh
  0 siblings, 0 replies; 112+ messages in thread
From: Kalesh Singh @ 2022-07-26  7:37 UTC (permalink / raw)
  To: maz, mark.rutland, broonie, madvenka, tabba, oliver.upton
  Cc: will, qperret, kaleshsingh, james.morse, alexandru.elisei,
	suzuki.poulose, catalin.marinas, andreyknvl, vincenzo.frascino,
	mhiramat, ast, wangkefeng.wang, elver, keirf, yuzenghui, ardb,
	oupton, linux-arm-kernel, kvmarm, linux-kernel, android-mm,
	kernel-team

On hyp stack overflow switch to 16-byte aligned secondary stack.
This provides us stack space to better handle overflows; and is
used in a subsequent patch to dump the hypervisor stacktrace.

Signed-off-by: Kalesh Singh <kaleshsingh@google.com>
Reviewed-by: Fuad Tabba <tabba@google.com>
Tested-by: Fuad Tabba <tabba@google.com>
---

Changes in v6:
  - Add Fuad's Tested-by tag

Changes in v5:
  - Add Reviewed-by tag from Fuad

 arch/arm64/kvm/hyp/nvhe/Makefile     |  2 +-
 arch/arm64/kvm/hyp/nvhe/host.S       |  9 ++-------
 arch/arm64/kvm/hyp/nvhe/stacktrace.c | 11 +++++++++++
 3 files changed, 14 insertions(+), 8 deletions(-)
 create mode 100644 arch/arm64/kvm/hyp/nvhe/stacktrace.c

diff --git a/arch/arm64/kvm/hyp/nvhe/Makefile b/arch/arm64/kvm/hyp/nvhe/Makefile
index f9fe4dc21b1f..524e7dad5739 100644
--- a/arch/arm64/kvm/hyp/nvhe/Makefile
+++ b/arch/arm64/kvm/hyp/nvhe/Makefile
@@ -14,7 +14,7 @@ lib-objs := $(addprefix ../../../lib/, $(lib-objs))
 
 obj-y := timer-sr.o sysreg-sr.o debug-sr.o switch.o tlb.o hyp-init.o host.o \
 	 hyp-main.o hyp-smp.o psci-relay.o early_alloc.o page_alloc.o \
-	 cache.o setup.o mm.o mem_protect.o sys_regs.o pkvm.o
+	 cache.o setup.o mm.o mem_protect.o sys_regs.o pkvm.o stacktrace.o
 obj-y += ../vgic-v3-sr.o ../aarch32.o ../vgic-v2-cpuif-proxy.o ../entry.o \
 	 ../fpsimd.o ../hyp-entry.o ../exception.o ../pgtable.o
 obj-$(CONFIG_DEBUG_LIST) += list_debug.o
diff --git a/arch/arm64/kvm/hyp/nvhe/host.S b/arch/arm64/kvm/hyp/nvhe/host.S
index ea6a397b64a6..b6c0188c4b35 100644
--- a/arch/arm64/kvm/hyp/nvhe/host.S
+++ b/arch/arm64/kvm/hyp/nvhe/host.S
@@ -177,13 +177,8 @@ SYM_FUNC_END(__host_hvc)
 	b	hyp_panic
 
 .L__hyp_sp_overflow\@:
-	/*
-	 * Reset SP to the top of the stack, to allow handling the hyp_panic.
-	 * This corrupts the stack but is ok, since we won't be attempting
-	 * any unwinding here.
-	 */
-	ldr_this_cpu	x0, kvm_init_params + NVHE_INIT_STACK_HYP_VA, x1
-	mov	sp, x0
+	/* Switch to the overflow stack */
+	adr_this_cpu sp, overflow_stack + OVERFLOW_STACK_SIZE, x0
 
 	b	hyp_panic_bad_stack
 	ASM_BUG()
diff --git a/arch/arm64/kvm/hyp/nvhe/stacktrace.c b/arch/arm64/kvm/hyp/nvhe/stacktrace.c
new file mode 100644
index 000000000000..a3d5b34e1249
--- /dev/null
+++ b/arch/arm64/kvm/hyp/nvhe/stacktrace.c
@@ -0,0 +1,11 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * KVM nVHE hypervisor stack tracing support.
+ *
+ * Copyright (C) 2022 Google LLC
+ */
+#include <asm/memory.h>
+#include <asm/percpu.h>
+
+DEFINE_PER_CPU(unsigned long [OVERFLOW_STACK_SIZE/sizeof(long)], overflow_stack)
+	__aligned(16);
-- 
2.37.1.359.gd136c6c3e2-goog


^ permalink raw reply related	[flat|nested] 112+ messages in thread

* [PATCH v6 07/17] KVM: arm64: On stack overflow switch to hyp overflow_stack
@ 2022-07-26  7:37   ` Kalesh Singh
  0 siblings, 0 replies; 112+ messages in thread
From: Kalesh Singh @ 2022-07-26  7:37 UTC (permalink / raw)
  To: maz, mark.rutland, broonie, madvenka, tabba, oliver.upton
  Cc: will, qperret, kaleshsingh, james.morse, alexandru.elisei,
	suzuki.poulose, catalin.marinas, andreyknvl, vincenzo.frascino,
	mhiramat, ast, wangkefeng.wang, elver, keirf, yuzenghui, ardb,
	oupton, linux-arm-kernel, kvmarm, linux-kernel, android-mm,
	kernel-team

On hyp stack overflow switch to 16-byte aligned secondary stack.
This provides us stack space to better handle overflows; and is
used in a subsequent patch to dump the hypervisor stacktrace.

Signed-off-by: Kalesh Singh <kaleshsingh@google.com>
Reviewed-by: Fuad Tabba <tabba@google.com>
Tested-by: Fuad Tabba <tabba@google.com>
---

Changes in v6:
  - Add Fuad's Tested-by tag

Changes in v5:
  - Add Reviewed-by tag from Fuad

 arch/arm64/kvm/hyp/nvhe/Makefile     |  2 +-
 arch/arm64/kvm/hyp/nvhe/host.S       |  9 ++-------
 arch/arm64/kvm/hyp/nvhe/stacktrace.c | 11 +++++++++++
 3 files changed, 14 insertions(+), 8 deletions(-)
 create mode 100644 arch/arm64/kvm/hyp/nvhe/stacktrace.c

diff --git a/arch/arm64/kvm/hyp/nvhe/Makefile b/arch/arm64/kvm/hyp/nvhe/Makefile
index f9fe4dc21b1f..524e7dad5739 100644
--- a/arch/arm64/kvm/hyp/nvhe/Makefile
+++ b/arch/arm64/kvm/hyp/nvhe/Makefile
@@ -14,7 +14,7 @@ lib-objs := $(addprefix ../../../lib/, $(lib-objs))
 
 obj-y := timer-sr.o sysreg-sr.o debug-sr.o switch.o tlb.o hyp-init.o host.o \
 	 hyp-main.o hyp-smp.o psci-relay.o early_alloc.o page_alloc.o \
-	 cache.o setup.o mm.o mem_protect.o sys_regs.o pkvm.o
+	 cache.o setup.o mm.o mem_protect.o sys_regs.o pkvm.o stacktrace.o
 obj-y += ../vgic-v3-sr.o ../aarch32.o ../vgic-v2-cpuif-proxy.o ../entry.o \
 	 ../fpsimd.o ../hyp-entry.o ../exception.o ../pgtable.o
 obj-$(CONFIG_DEBUG_LIST) += list_debug.o
diff --git a/arch/arm64/kvm/hyp/nvhe/host.S b/arch/arm64/kvm/hyp/nvhe/host.S
index ea6a397b64a6..b6c0188c4b35 100644
--- a/arch/arm64/kvm/hyp/nvhe/host.S
+++ b/arch/arm64/kvm/hyp/nvhe/host.S
@@ -177,13 +177,8 @@ SYM_FUNC_END(__host_hvc)
 	b	hyp_panic
 
 .L__hyp_sp_overflow\@:
-	/*
-	 * Reset SP to the top of the stack, to allow handling the hyp_panic.
-	 * This corrupts the stack but is ok, since we won't be attempting
-	 * any unwinding here.
-	 */
-	ldr_this_cpu	x0, kvm_init_params + NVHE_INIT_STACK_HYP_VA, x1
-	mov	sp, x0
+	/* Switch to the overflow stack */
+	adr_this_cpu sp, overflow_stack + OVERFLOW_STACK_SIZE, x0
 
 	b	hyp_panic_bad_stack
 	ASM_BUG()
diff --git a/arch/arm64/kvm/hyp/nvhe/stacktrace.c b/arch/arm64/kvm/hyp/nvhe/stacktrace.c
new file mode 100644
index 000000000000..a3d5b34e1249
--- /dev/null
+++ b/arch/arm64/kvm/hyp/nvhe/stacktrace.c
@@ -0,0 +1,11 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * KVM nVHE hypervisor stack tracing support.
+ *
+ * Copyright (C) 2022 Google LLC
+ */
+#include <asm/memory.h>
+#include <asm/percpu.h>
+
+DEFINE_PER_CPU(unsigned long [OVERFLOW_STACK_SIZE/sizeof(long)], overflow_stack)
+	__aligned(16);
-- 
2.37.1.359.gd136c6c3e2-goog


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 112+ messages in thread

* [PATCH v6 08/17] KVM: arm64: Stub implementation of non-protected nVHE HYP stack unwinder
  2022-07-26  7:37 ` Kalesh Singh
  (?)
@ 2022-07-26  7:37   ` Kalesh Singh
  -1 siblings, 0 replies; 112+ messages in thread
From: Kalesh Singh @ 2022-07-26  7:37 UTC (permalink / raw)
  To: maz, mark.rutland, broonie, madvenka, tabba, oliver.upton
  Cc: wangkefeng.wang, catalin.marinas, ast, vincenzo.frascino, will,
	kvmarm, android-mm, kernel-team, elver, linux-arm-kernel,
	andreyknvl, linux-kernel, mhiramat

Add stub implementations of non-protected nVHE stack unwinder, for
building. These are implemented later in this series.

Signed-off-by: Kalesh Singh <kaleshsingh@google.com>
Reviewed-by: Fuad Tabba <tabba@google.com>
Tested-by: Fuad Tabba <tabba@google.com>
---

Changes in v6:
  - Add Fuad’s Reviewed-by and Tested-by tags

Changes in v5:
  - Mark unwind_next() as inline, per Marc
  - Comment !__KVM_NVHE_HYPERVISOR__ unwinder path, per Marc

 arch/arm64/include/asm/stacktrace/nvhe.h | 47 ++++++++++++++++++++++++
 1 file changed, 47 insertions(+)
 create mode 100644 arch/arm64/include/asm/stacktrace/nvhe.h

diff --git a/arch/arm64/include/asm/stacktrace/nvhe.h b/arch/arm64/include/asm/stacktrace/nvhe.h
new file mode 100644
index 000000000000..1192ae0f80c1
--- /dev/null
+++ b/arch/arm64/include/asm/stacktrace/nvhe.h
@@ -0,0 +1,47 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * KVM nVHE hypervisor stack tracing support.
+ *
+ * The unwinder implementation depends on the nVHE mode:
+ *
+ *   1) Non-protected nVHE mode - the host can directly access the
+ *      HYP stack pages and unwind the HYP stack in EL1. This saves having
+ *      to allocate shared buffers for the host to read the unwinded
+ *      stacktrace.
+ *
+ * Copyright (C) 2022 Google LLC
+ */
+#ifndef __ASM_STACKTRACE_NVHE_H
+#define __ASM_STACKTRACE_NVHE_H
+
+#include <asm/stacktrace/common.h>
+
+static inline bool on_accessible_stack(const struct task_struct *tsk,
+				       unsigned long sp, unsigned long size,
+				       struct stack_info *info)
+{
+	return false;
+}
+
+#ifndef __KVM_NVHE_HYPERVISOR__
+/*
+ * Conventional (non-protected) nVHE HYP stack unwinder
+ *
+ * In non-protected mode, the unwinding is done from kernel proper context
+ * (by the host in EL1).
+ */
+
+static inline bool on_overflow_stack(unsigned long sp, unsigned long size,
+				     struct stack_info *info)
+{
+	return false;
+}
+
+static inline int notrace unwind_next(struct unwind_state *state)
+{
+	return 0;
+}
+NOKPROBE_SYMBOL(unwind_next);
+
+#endif	/* !__KVM_NVHE_HYPERVISOR__ */
+#endif	/* __ASM_STACKTRACE_NVHE_H */
-- 
2.37.1.359.gd136c6c3e2-goog

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply related	[flat|nested] 112+ messages in thread

* [PATCH v6 08/17] KVM: arm64: Stub implementation of non-protected nVHE HYP stack unwinder
@ 2022-07-26  7:37   ` Kalesh Singh
  0 siblings, 0 replies; 112+ messages in thread
From: Kalesh Singh @ 2022-07-26  7:37 UTC (permalink / raw)
  To: maz, mark.rutland, broonie, madvenka, tabba, oliver.upton
  Cc: will, qperret, kaleshsingh, james.morse, alexandru.elisei,
	suzuki.poulose, catalin.marinas, andreyknvl, vincenzo.frascino,
	mhiramat, ast, wangkefeng.wang, elver, keirf, yuzenghui, ardb,
	oupton, linux-arm-kernel, kvmarm, linux-kernel, android-mm,
	kernel-team

Add stub implementations of non-protected nVHE stack unwinder, for
building. These are implemented later in this series.

Signed-off-by: Kalesh Singh <kaleshsingh@google.com>
Reviewed-by: Fuad Tabba <tabba@google.com>
Tested-by: Fuad Tabba <tabba@google.com>
---

Changes in v6:
  - Add Fuad’s Reviewed-by and Tested-by tags

Changes in v5:
  - Mark unwind_next() as inline, per Marc
  - Comment !__KVM_NVHE_HYPERVISOR__ unwinder path, per Marc

 arch/arm64/include/asm/stacktrace/nvhe.h | 47 ++++++++++++++++++++++++
 1 file changed, 47 insertions(+)
 create mode 100644 arch/arm64/include/asm/stacktrace/nvhe.h

diff --git a/arch/arm64/include/asm/stacktrace/nvhe.h b/arch/arm64/include/asm/stacktrace/nvhe.h
new file mode 100644
index 000000000000..1192ae0f80c1
--- /dev/null
+++ b/arch/arm64/include/asm/stacktrace/nvhe.h
@@ -0,0 +1,47 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * KVM nVHE hypervisor stack tracing support.
+ *
+ * The unwinder implementation depends on the nVHE mode:
+ *
+ *   1) Non-protected nVHE mode - the host can directly access the
+ *      HYP stack pages and unwind the HYP stack in EL1. This saves having
+ *      to allocate shared buffers for the host to read the unwinded
+ *      stacktrace.
+ *
+ * Copyright (C) 2022 Google LLC
+ */
+#ifndef __ASM_STACKTRACE_NVHE_H
+#define __ASM_STACKTRACE_NVHE_H
+
+#include <asm/stacktrace/common.h>
+
+static inline bool on_accessible_stack(const struct task_struct *tsk,
+				       unsigned long sp, unsigned long size,
+				       struct stack_info *info)
+{
+	return false;
+}
+
+#ifndef __KVM_NVHE_HYPERVISOR__
+/*
+ * Conventional (non-protected) nVHE HYP stack unwinder
+ *
+ * In non-protected mode, the unwinding is done from kernel proper context
+ * (by the host in EL1).
+ */
+
+static inline bool on_overflow_stack(unsigned long sp, unsigned long size,
+				     struct stack_info *info)
+{
+	return false;
+}
+
+static inline int notrace unwind_next(struct unwind_state *state)
+{
+	return 0;
+}
+NOKPROBE_SYMBOL(unwind_next);
+
+#endif	/* !__KVM_NVHE_HYPERVISOR__ */
+#endif	/* __ASM_STACKTRACE_NVHE_H */
-- 
2.37.1.359.gd136c6c3e2-goog


^ permalink raw reply related	[flat|nested] 112+ messages in thread

* [PATCH v6 08/17] KVM: arm64: Stub implementation of non-protected nVHE HYP stack unwinder
@ 2022-07-26  7:37   ` Kalesh Singh
  0 siblings, 0 replies; 112+ messages in thread
From: Kalesh Singh @ 2022-07-26  7:37 UTC (permalink / raw)
  To: maz, mark.rutland, broonie, madvenka, tabba, oliver.upton
  Cc: will, qperret, kaleshsingh, james.morse, alexandru.elisei,
	suzuki.poulose, catalin.marinas, andreyknvl, vincenzo.frascino,
	mhiramat, ast, wangkefeng.wang, elver, keirf, yuzenghui, ardb,
	oupton, linux-arm-kernel, kvmarm, linux-kernel, android-mm,
	kernel-team

Add stub implementations of non-protected nVHE stack unwinder, for
building. These are implemented later in this series.

Signed-off-by: Kalesh Singh <kaleshsingh@google.com>
Reviewed-by: Fuad Tabba <tabba@google.com>
Tested-by: Fuad Tabba <tabba@google.com>
---

Changes in v6:
  - Add Fuad’s Reviewed-by and Tested-by tags

Changes in v5:
  - Mark unwind_next() as inline, per Marc
  - Comment !__KVM_NVHE_HYPERVISOR__ unwinder path, per Marc

 arch/arm64/include/asm/stacktrace/nvhe.h | 47 ++++++++++++++++++++++++
 1 file changed, 47 insertions(+)
 create mode 100644 arch/arm64/include/asm/stacktrace/nvhe.h

diff --git a/arch/arm64/include/asm/stacktrace/nvhe.h b/arch/arm64/include/asm/stacktrace/nvhe.h
new file mode 100644
index 000000000000..1192ae0f80c1
--- /dev/null
+++ b/arch/arm64/include/asm/stacktrace/nvhe.h
@@ -0,0 +1,47 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * KVM nVHE hypervisor stack tracing support.
+ *
+ * The unwinder implementation depends on the nVHE mode:
+ *
+ *   1) Non-protected nVHE mode - the host can directly access the
+ *      HYP stack pages and unwind the HYP stack in EL1. This saves having
+ *      to allocate shared buffers for the host to read the unwinded
+ *      stacktrace.
+ *
+ * Copyright (C) 2022 Google LLC
+ */
+#ifndef __ASM_STACKTRACE_NVHE_H
+#define __ASM_STACKTRACE_NVHE_H
+
+#include <asm/stacktrace/common.h>
+
+static inline bool on_accessible_stack(const struct task_struct *tsk,
+				       unsigned long sp, unsigned long size,
+				       struct stack_info *info)
+{
+	return false;
+}
+
+#ifndef __KVM_NVHE_HYPERVISOR__
+/*
+ * Conventional (non-protected) nVHE HYP stack unwinder
+ *
+ * In non-protected mode, the unwinding is done from kernel proper context
+ * (by the host in EL1).
+ */
+
+static inline bool on_overflow_stack(unsigned long sp, unsigned long size,
+				     struct stack_info *info)
+{
+	return false;
+}
+
+static inline int notrace unwind_next(struct unwind_state *state)
+{
+	return 0;
+}
+NOKPROBE_SYMBOL(unwind_next);
+
+#endif	/* !__KVM_NVHE_HYPERVISOR__ */
+#endif	/* __ASM_STACKTRACE_NVHE_H */
-- 
2.37.1.359.gd136c6c3e2-goog


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 112+ messages in thread

* [PATCH v6 09/17] KVM: arm64: Prepare non-protected nVHE hypervisor stacktrace
  2022-07-26  7:37 ` Kalesh Singh
  (?)
@ 2022-07-26  7:37   ` Kalesh Singh
  -1 siblings, 0 replies; 112+ messages in thread
From: Kalesh Singh @ 2022-07-26  7:37 UTC (permalink / raw)
  To: maz, mark.rutland, broonie, madvenka, tabba, oliver.upton
  Cc: wangkefeng.wang, catalin.marinas, ast, vincenzo.frascino, will,
	kvmarm, android-mm, kernel-team, elver, linux-arm-kernel,
	andreyknvl, linux-kernel, mhiramat

In non-protected nVHE mode (non-pKVM) the host can directly access
hypervisor memory; and unwinding of the hypervisor stacktrace is
done from EL1 to save on memory for shared buffers.

To unwind the hypervisor stack from EL1 the host needs to know the
starting point for the unwind and information that will allow it to
translate hypervisor stack addresses to the corresponding kernel
addresses. This patch sets up this book keeping. It is made use of
later in the series.

Signed-off-by: Kalesh Singh <kaleshsingh@google.com>
Reviewed-by: Fuad Tabba <tabba@google.com>
Tested-by: Fuad Tabba <tabba@google.com>
---

Changes in v6:
  - Add Fuad’s Reviewed-by and Tested-by tags

Changes in v5:
  - Use regular comments instead of doc comments, per Fuad

 arch/arm64/include/asm/kvm_asm.h     | 16 +++++++++++
 arch/arm64/kvm/hyp/nvhe/stacktrace.c | 41 ++++++++++++++++++++++++++++
 arch/arm64/kvm/hyp/nvhe/switch.c     |  6 ++++
 3 files changed, 63 insertions(+)

diff --git a/arch/arm64/include/asm/kvm_asm.h b/arch/arm64/include/asm/kvm_asm.h
index 2e277f2ed671..53035763e48e 100644
--- a/arch/arm64/include/asm/kvm_asm.h
+++ b/arch/arm64/include/asm/kvm_asm.h
@@ -176,6 +176,22 @@ struct kvm_nvhe_init_params {
 	unsigned long vtcr;
 };
 
+/*
+ * Used by the host in EL1 to dump the nVHE hypervisor backtrace on
+ * hyp_panic() in non-protected mode.
+ *
+ * @stack_base:                 hyp VA of the hyp_stack base.
+ * @overflow_stack_base:        hyp VA of the hyp_overflow_stack base.
+ * @fp:                         hyp FP where the backtrace begins.
+ * @pc:                         hyp PC where the backtrace begins.
+ */
+struct kvm_nvhe_stacktrace_info {
+	unsigned long stack_base;
+	unsigned long overflow_stack_base;
+	unsigned long fp;
+	unsigned long pc;
+};
+
 /* Translate a kernel address @ptr into its equivalent linear mapping */
 #define kvm_ksym_ref(ptr)						\
 	({								\
diff --git a/arch/arm64/kvm/hyp/nvhe/stacktrace.c b/arch/arm64/kvm/hyp/nvhe/stacktrace.c
index a3d5b34e1249..b8a280aa026a 100644
--- a/arch/arm64/kvm/hyp/nvhe/stacktrace.c
+++ b/arch/arm64/kvm/hyp/nvhe/stacktrace.c
@@ -4,8 +4,49 @@
  *
  * Copyright (C) 2022 Google LLC
  */
+#include <asm/kvm_asm.h>
+#include <asm/kvm_hyp.h>
 #include <asm/memory.h>
 #include <asm/percpu.h>
 
 DEFINE_PER_CPU(unsigned long [OVERFLOW_STACK_SIZE/sizeof(long)], overflow_stack)
 	__aligned(16);
+
+DEFINE_PER_CPU(struct kvm_nvhe_stacktrace_info, kvm_stacktrace_info);
+
+/*
+ * hyp_prepare_backtrace - Prepare non-protected nVHE backtrace.
+ *
+ * @fp : frame pointer at which to start the unwinding.
+ * @pc : program counter at which to start the unwinding.
+ *
+ * Save the information needed by the host to unwind the non-protected
+ * nVHE hypervisor stack in EL1.
+ */
+static void hyp_prepare_backtrace(unsigned long fp, unsigned long pc)
+{
+	struct kvm_nvhe_stacktrace_info *stacktrace_info = this_cpu_ptr(&kvm_stacktrace_info);
+	struct kvm_nvhe_init_params *params = this_cpu_ptr(&kvm_init_params);
+
+	stacktrace_info->stack_base = (unsigned long)(params->stack_hyp_va - PAGE_SIZE);
+	stacktrace_info->overflow_stack_base = (unsigned long)this_cpu_ptr(overflow_stack);
+	stacktrace_info->fp = fp;
+	stacktrace_info->pc = pc;
+}
+
+/*
+ * kvm_nvhe_prepare_backtrace - prepare to dump the nVHE backtrace
+ *
+ * @fp : frame pointer at which to start the unwinding.
+ * @pc : program counter at which to start the unwinding.
+ *
+ * Saves the information needed by the host to dump the nVHE hypervisor
+ * backtrace.
+ */
+void kvm_nvhe_prepare_backtrace(unsigned long fp, unsigned long pc)
+{
+	if (is_protected_kvm_enabled())
+		return;
+	else
+		hyp_prepare_backtrace(fp, pc);
+}
diff --git a/arch/arm64/kvm/hyp/nvhe/switch.c b/arch/arm64/kvm/hyp/nvhe/switch.c
index 6db801db8f27..64e13445d0d9 100644
--- a/arch/arm64/kvm/hyp/nvhe/switch.c
+++ b/arch/arm64/kvm/hyp/nvhe/switch.c
@@ -34,6 +34,8 @@ DEFINE_PER_CPU(struct kvm_host_data, kvm_host_data);
 DEFINE_PER_CPU(struct kvm_cpu_context, kvm_hyp_ctxt);
 DEFINE_PER_CPU(unsigned long, kvm_hyp_vector);
 
+extern void kvm_nvhe_prepare_backtrace(unsigned long fp, unsigned long pc);
+
 static void __activate_traps(struct kvm_vcpu *vcpu)
 {
 	u64 val;
@@ -375,6 +377,10 @@ asmlinkage void __noreturn hyp_panic(void)
 		__sysreg_restore_state_nvhe(host_ctxt);
 	}
 
+	/* Prepare to dump kvm nvhe hyp stacktrace */
+	kvm_nvhe_prepare_backtrace((unsigned long)__builtin_frame_address(0),
+				   _THIS_IP_);
+
 	__hyp_do_panic(host_ctxt, spsr, elr, par);
 	unreachable();
 }
-- 
2.37.1.359.gd136c6c3e2-goog

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply related	[flat|nested] 112+ messages in thread

* [PATCH v6 09/17] KVM: arm64: Prepare non-protected nVHE hypervisor stacktrace
@ 2022-07-26  7:37   ` Kalesh Singh
  0 siblings, 0 replies; 112+ messages in thread
From: Kalesh Singh @ 2022-07-26  7:37 UTC (permalink / raw)
  To: maz, mark.rutland, broonie, madvenka, tabba, oliver.upton
  Cc: will, qperret, kaleshsingh, james.morse, alexandru.elisei,
	suzuki.poulose, catalin.marinas, andreyknvl, vincenzo.frascino,
	mhiramat, ast, wangkefeng.wang, elver, keirf, yuzenghui, ardb,
	oupton, linux-arm-kernel, kvmarm, linux-kernel, android-mm,
	kernel-team

In non-protected nVHE mode (non-pKVM) the host can directly access
hypervisor memory; and unwinding of the hypervisor stacktrace is
done from EL1 to save on memory for shared buffers.

To unwind the hypervisor stack from EL1 the host needs to know the
starting point for the unwind and information that will allow it to
translate hypervisor stack addresses to the corresponding kernel
addresses. This patch sets up this book keeping. It is made use of
later in the series.

Signed-off-by: Kalesh Singh <kaleshsingh@google.com>
Reviewed-by: Fuad Tabba <tabba@google.com>
Tested-by: Fuad Tabba <tabba@google.com>
---

Changes in v6:
  - Add Fuad’s Reviewed-by and Tested-by tags

Changes in v5:
  - Use regular comments instead of doc comments, per Fuad

 arch/arm64/include/asm/kvm_asm.h     | 16 +++++++++++
 arch/arm64/kvm/hyp/nvhe/stacktrace.c | 41 ++++++++++++++++++++++++++++
 arch/arm64/kvm/hyp/nvhe/switch.c     |  6 ++++
 3 files changed, 63 insertions(+)

diff --git a/arch/arm64/include/asm/kvm_asm.h b/arch/arm64/include/asm/kvm_asm.h
index 2e277f2ed671..53035763e48e 100644
--- a/arch/arm64/include/asm/kvm_asm.h
+++ b/arch/arm64/include/asm/kvm_asm.h
@@ -176,6 +176,22 @@ struct kvm_nvhe_init_params {
 	unsigned long vtcr;
 };
 
+/*
+ * Used by the host in EL1 to dump the nVHE hypervisor backtrace on
+ * hyp_panic() in non-protected mode.
+ *
+ * @stack_base:                 hyp VA of the hyp_stack base.
+ * @overflow_stack_base:        hyp VA of the hyp_overflow_stack base.
+ * @fp:                         hyp FP where the backtrace begins.
+ * @pc:                         hyp PC where the backtrace begins.
+ */
+struct kvm_nvhe_stacktrace_info {
+	unsigned long stack_base;
+	unsigned long overflow_stack_base;
+	unsigned long fp;
+	unsigned long pc;
+};
+
 /* Translate a kernel address @ptr into its equivalent linear mapping */
 #define kvm_ksym_ref(ptr)						\
 	({								\
diff --git a/arch/arm64/kvm/hyp/nvhe/stacktrace.c b/arch/arm64/kvm/hyp/nvhe/stacktrace.c
index a3d5b34e1249..b8a280aa026a 100644
--- a/arch/arm64/kvm/hyp/nvhe/stacktrace.c
+++ b/arch/arm64/kvm/hyp/nvhe/stacktrace.c
@@ -4,8 +4,49 @@
  *
  * Copyright (C) 2022 Google LLC
  */
+#include <asm/kvm_asm.h>
+#include <asm/kvm_hyp.h>
 #include <asm/memory.h>
 #include <asm/percpu.h>
 
 DEFINE_PER_CPU(unsigned long [OVERFLOW_STACK_SIZE/sizeof(long)], overflow_stack)
 	__aligned(16);
+
+DEFINE_PER_CPU(struct kvm_nvhe_stacktrace_info, kvm_stacktrace_info);
+
+/*
+ * hyp_prepare_backtrace - Prepare non-protected nVHE backtrace.
+ *
+ * @fp : frame pointer at which to start the unwinding.
+ * @pc : program counter at which to start the unwinding.
+ *
+ * Save the information needed by the host to unwind the non-protected
+ * nVHE hypervisor stack in EL1.
+ */
+static void hyp_prepare_backtrace(unsigned long fp, unsigned long pc)
+{
+	struct kvm_nvhe_stacktrace_info *stacktrace_info = this_cpu_ptr(&kvm_stacktrace_info);
+	struct kvm_nvhe_init_params *params = this_cpu_ptr(&kvm_init_params);
+
+	stacktrace_info->stack_base = (unsigned long)(params->stack_hyp_va - PAGE_SIZE);
+	stacktrace_info->overflow_stack_base = (unsigned long)this_cpu_ptr(overflow_stack);
+	stacktrace_info->fp = fp;
+	stacktrace_info->pc = pc;
+}
+
+/*
+ * kvm_nvhe_prepare_backtrace - prepare to dump the nVHE backtrace
+ *
+ * @fp : frame pointer at which to start the unwinding.
+ * @pc : program counter at which to start the unwinding.
+ *
+ * Saves the information needed by the host to dump the nVHE hypervisor
+ * backtrace.
+ */
+void kvm_nvhe_prepare_backtrace(unsigned long fp, unsigned long pc)
+{
+	if (is_protected_kvm_enabled())
+		return;
+	else
+		hyp_prepare_backtrace(fp, pc);
+}
diff --git a/arch/arm64/kvm/hyp/nvhe/switch.c b/arch/arm64/kvm/hyp/nvhe/switch.c
index 6db801db8f27..64e13445d0d9 100644
--- a/arch/arm64/kvm/hyp/nvhe/switch.c
+++ b/arch/arm64/kvm/hyp/nvhe/switch.c
@@ -34,6 +34,8 @@ DEFINE_PER_CPU(struct kvm_host_data, kvm_host_data);
 DEFINE_PER_CPU(struct kvm_cpu_context, kvm_hyp_ctxt);
 DEFINE_PER_CPU(unsigned long, kvm_hyp_vector);
 
+extern void kvm_nvhe_prepare_backtrace(unsigned long fp, unsigned long pc);
+
 static void __activate_traps(struct kvm_vcpu *vcpu)
 {
 	u64 val;
@@ -375,6 +377,10 @@ asmlinkage void __noreturn hyp_panic(void)
 		__sysreg_restore_state_nvhe(host_ctxt);
 	}
 
+	/* Prepare to dump kvm nvhe hyp stacktrace */
+	kvm_nvhe_prepare_backtrace((unsigned long)__builtin_frame_address(0),
+				   _THIS_IP_);
+
 	__hyp_do_panic(host_ctxt, spsr, elr, par);
 	unreachable();
 }
-- 
2.37.1.359.gd136c6c3e2-goog


^ permalink raw reply related	[flat|nested] 112+ messages in thread

* [PATCH v6 09/17] KVM: arm64: Prepare non-protected nVHE hypervisor stacktrace
@ 2022-07-26  7:37   ` Kalesh Singh
  0 siblings, 0 replies; 112+ messages in thread
From: Kalesh Singh @ 2022-07-26  7:37 UTC (permalink / raw)
  To: maz, mark.rutland, broonie, madvenka, tabba, oliver.upton
  Cc: will, qperret, kaleshsingh, james.morse, alexandru.elisei,
	suzuki.poulose, catalin.marinas, andreyknvl, vincenzo.frascino,
	mhiramat, ast, wangkefeng.wang, elver, keirf, yuzenghui, ardb,
	oupton, linux-arm-kernel, kvmarm, linux-kernel, android-mm,
	kernel-team

In non-protected nVHE mode (non-pKVM) the host can directly access
hypervisor memory; and unwinding of the hypervisor stacktrace is
done from EL1 to save on memory for shared buffers.

To unwind the hypervisor stack from EL1 the host needs to know the
starting point for the unwind and information that will allow it to
translate hypervisor stack addresses to the corresponding kernel
addresses. This patch sets up this book keeping. It is made use of
later in the series.

Signed-off-by: Kalesh Singh <kaleshsingh@google.com>
Reviewed-by: Fuad Tabba <tabba@google.com>
Tested-by: Fuad Tabba <tabba@google.com>
---

Changes in v6:
  - Add Fuad’s Reviewed-by and Tested-by tags

Changes in v5:
  - Use regular comments instead of doc comments, per Fuad

 arch/arm64/include/asm/kvm_asm.h     | 16 +++++++++++
 arch/arm64/kvm/hyp/nvhe/stacktrace.c | 41 ++++++++++++++++++++++++++++
 arch/arm64/kvm/hyp/nvhe/switch.c     |  6 ++++
 3 files changed, 63 insertions(+)

diff --git a/arch/arm64/include/asm/kvm_asm.h b/arch/arm64/include/asm/kvm_asm.h
index 2e277f2ed671..53035763e48e 100644
--- a/arch/arm64/include/asm/kvm_asm.h
+++ b/arch/arm64/include/asm/kvm_asm.h
@@ -176,6 +176,22 @@ struct kvm_nvhe_init_params {
 	unsigned long vtcr;
 };
 
+/*
+ * Used by the host in EL1 to dump the nVHE hypervisor backtrace on
+ * hyp_panic() in non-protected mode.
+ *
+ * @stack_base:                 hyp VA of the hyp_stack base.
+ * @overflow_stack_base:        hyp VA of the hyp_overflow_stack base.
+ * @fp:                         hyp FP where the backtrace begins.
+ * @pc:                         hyp PC where the backtrace begins.
+ */
+struct kvm_nvhe_stacktrace_info {
+	unsigned long stack_base;
+	unsigned long overflow_stack_base;
+	unsigned long fp;
+	unsigned long pc;
+};
+
 /* Translate a kernel address @ptr into its equivalent linear mapping */
 #define kvm_ksym_ref(ptr)						\
 	({								\
diff --git a/arch/arm64/kvm/hyp/nvhe/stacktrace.c b/arch/arm64/kvm/hyp/nvhe/stacktrace.c
index a3d5b34e1249..b8a280aa026a 100644
--- a/arch/arm64/kvm/hyp/nvhe/stacktrace.c
+++ b/arch/arm64/kvm/hyp/nvhe/stacktrace.c
@@ -4,8 +4,49 @@
  *
  * Copyright (C) 2022 Google LLC
  */
+#include <asm/kvm_asm.h>
+#include <asm/kvm_hyp.h>
 #include <asm/memory.h>
 #include <asm/percpu.h>
 
 DEFINE_PER_CPU(unsigned long [OVERFLOW_STACK_SIZE/sizeof(long)], overflow_stack)
 	__aligned(16);
+
+DEFINE_PER_CPU(struct kvm_nvhe_stacktrace_info, kvm_stacktrace_info);
+
+/*
+ * hyp_prepare_backtrace - Prepare non-protected nVHE backtrace.
+ *
+ * @fp : frame pointer at which to start the unwinding.
+ * @pc : program counter at which to start the unwinding.
+ *
+ * Save the information needed by the host to unwind the non-protected
+ * nVHE hypervisor stack in EL1.
+ */
+static void hyp_prepare_backtrace(unsigned long fp, unsigned long pc)
+{
+	struct kvm_nvhe_stacktrace_info *stacktrace_info = this_cpu_ptr(&kvm_stacktrace_info);
+	struct kvm_nvhe_init_params *params = this_cpu_ptr(&kvm_init_params);
+
+	stacktrace_info->stack_base = (unsigned long)(params->stack_hyp_va - PAGE_SIZE);
+	stacktrace_info->overflow_stack_base = (unsigned long)this_cpu_ptr(overflow_stack);
+	stacktrace_info->fp = fp;
+	stacktrace_info->pc = pc;
+}
+
+/*
+ * kvm_nvhe_prepare_backtrace - prepare to dump the nVHE backtrace
+ *
+ * @fp : frame pointer at which to start the unwinding.
+ * @pc : program counter at which to start the unwinding.
+ *
+ * Saves the information needed by the host to dump the nVHE hypervisor
+ * backtrace.
+ */
+void kvm_nvhe_prepare_backtrace(unsigned long fp, unsigned long pc)
+{
+	if (is_protected_kvm_enabled())
+		return;
+	else
+		hyp_prepare_backtrace(fp, pc);
+}
diff --git a/arch/arm64/kvm/hyp/nvhe/switch.c b/arch/arm64/kvm/hyp/nvhe/switch.c
index 6db801db8f27..64e13445d0d9 100644
--- a/arch/arm64/kvm/hyp/nvhe/switch.c
+++ b/arch/arm64/kvm/hyp/nvhe/switch.c
@@ -34,6 +34,8 @@ DEFINE_PER_CPU(struct kvm_host_data, kvm_host_data);
 DEFINE_PER_CPU(struct kvm_cpu_context, kvm_hyp_ctxt);
 DEFINE_PER_CPU(unsigned long, kvm_hyp_vector);
 
+extern void kvm_nvhe_prepare_backtrace(unsigned long fp, unsigned long pc);
+
 static void __activate_traps(struct kvm_vcpu *vcpu)
 {
 	u64 val;
@@ -375,6 +377,10 @@ asmlinkage void __noreturn hyp_panic(void)
 		__sysreg_restore_state_nvhe(host_ctxt);
 	}
 
+	/* Prepare to dump kvm nvhe hyp stacktrace */
+	kvm_nvhe_prepare_backtrace((unsigned long)__builtin_frame_address(0),
+				   _THIS_IP_);
+
 	__hyp_do_panic(host_ctxt, spsr, elr, par);
 	unreachable();
 }
-- 
2.37.1.359.gd136c6c3e2-goog


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 112+ messages in thread

* [PATCH v6 10/17] KVM: arm64: Implement non-protected nVHE hyp stack unwinder
  2022-07-26  7:37 ` Kalesh Singh
  (?)
@ 2022-07-26  7:37   ` Kalesh Singh
  -1 siblings, 0 replies; 112+ messages in thread
From: Kalesh Singh @ 2022-07-26  7:37 UTC (permalink / raw)
  To: maz, mark.rutland, broonie, madvenka, tabba, oliver.upton
  Cc: wangkefeng.wang, catalin.marinas, ast, vincenzo.frascino, will,
	kvmarm, android-mm, kernel-team, elver, linux-arm-kernel,
	andreyknvl, linux-kernel, mhiramat

Implements the common framework necessary for unwind() to work
for non-protected nVHE mode:
    - on_accessible_stack()
    - on_overflow_stack()
    - unwind_next()

Non-protected nVHE unwind() is used to unwind and dump the hypervisor
stacktrace by the host in EL1

Signed-off-by: Kalesh Singh <kaleshsingh@google.com>
Reviewed-by: Fuad Tabba <tabba@google.com>
Tested-by: Fuad Tabba <tabba@google.com>
---

Changes in v6:
  - Add Fuad’s Reviewed-by and Tested-by tags

Changes in v5:
  - Use regular comments instead of doc comments, per Fuad

 arch/arm64/include/asm/stacktrace/common.h |  2 +
 arch/arm64/include/asm/stacktrace/nvhe.h   | 76 +++++++++++++++++++++-
 arch/arm64/kvm/arm.c                       |  2 +-
 3 files changed, 77 insertions(+), 3 deletions(-)

diff --git a/arch/arm64/include/asm/stacktrace/common.h b/arch/arm64/include/asm/stacktrace/common.h
index 45474b383630..3ebb69ea374a 100644
--- a/arch/arm64/include/asm/stacktrace/common.h
+++ b/arch/arm64/include/asm/stacktrace/common.h
@@ -34,6 +34,7 @@ enum stack_type {
 	STACK_TYPE_OVERFLOW,
 	STACK_TYPE_SDEI_NORMAL,
 	STACK_TYPE_SDEI_CRITICAL,
+	STACK_TYPE_HYP,
 	__NR_STACK_TYPES
 };
 
@@ -186,6 +187,7 @@ static inline int unwind_next_common(struct unwind_state *state,
 	 *
 	 * TASK -> IRQ -> OVERFLOW -> SDEI_NORMAL
 	 * TASK -> SDEI_NORMAL -> SDEI_CRITICAL -> OVERFLOW
+	 * HYP -> OVERFLOW
 	 *
 	 * ... but the nesting itself is strict. Once we transition from one
 	 * stack to another, it's never valid to unwind back to that first
diff --git a/arch/arm64/include/asm/stacktrace/nvhe.h b/arch/arm64/include/asm/stacktrace/nvhe.h
index 1192ae0f80c1..21082fd4a0b7 100644
--- a/arch/arm64/include/asm/stacktrace/nvhe.h
+++ b/arch/arm64/include/asm/stacktrace/nvhe.h
@@ -16,10 +16,19 @@
 
 #include <asm/stacktrace/common.h>
 
+static inline bool on_hyp_stack(unsigned long sp, unsigned long size,
+				struct stack_info *info);
+
 static inline bool on_accessible_stack(const struct task_struct *tsk,
 				       unsigned long sp, unsigned long size,
 				       struct stack_info *info)
 {
+	if (on_accessible_stack_common(tsk, sp, size, info))
+		return true;
+
+	if (on_hyp_stack(sp, size, info))
+		return true;
+
 	return false;
 }
 
@@ -31,15 +40,78 @@ static inline bool on_accessible_stack(const struct task_struct *tsk,
  * (by the host in EL1).
  */
 
+DECLARE_KVM_NVHE_PER_CPU(unsigned long [OVERFLOW_STACK_SIZE/sizeof(long)], overflow_stack);
+DECLARE_KVM_NVHE_PER_CPU(struct kvm_nvhe_stacktrace_info, kvm_stacktrace_info);
+DECLARE_PER_CPU(unsigned long, kvm_arm_hyp_stack_page);
+
+/*
+ * kvm_nvhe_stack_kern_va - Convert KVM nVHE HYP stack addresses to a kernel VAs
+ *
+ * The nVHE hypervisor stack is mapped in the flexible 'private' VA range, to
+ * allow for guard pages below the stack. Consequently, the fixed offset address
+ * translation macros won't work here.
+ *
+ * The kernel VA is calculated as an offset from the kernel VA of the hypervisor
+ * stack base.
+ *
+ * Returns true on success and updates @addr to its corresponding kernel VA;
+ * otherwise returns false.
+ */
+static inline bool kvm_nvhe_stack_kern_va(unsigned long *addr,
+					  enum stack_type type)
+{
+	struct kvm_nvhe_stacktrace_info *stacktrace_info;
+	unsigned long hyp_base, kern_base, hyp_offset;
+
+	stacktrace_info = this_cpu_ptr_nvhe_sym(kvm_stacktrace_info);
+
+	switch (type) {
+	case STACK_TYPE_HYP:
+		kern_base = (unsigned long)*this_cpu_ptr(&kvm_arm_hyp_stack_page);
+		hyp_base = (unsigned long)stacktrace_info->stack_base;
+		break;
+	case STACK_TYPE_OVERFLOW:
+		kern_base = (unsigned long)this_cpu_ptr_nvhe_sym(overflow_stack);
+		hyp_base = (unsigned long)stacktrace_info->overflow_stack_base;
+		break;
+	default:
+		return false;
+	}
+
+	hyp_offset = *addr - hyp_base;
+
+	*addr = kern_base + hyp_offset;
+
+	return true;
+}
+
 static inline bool on_overflow_stack(unsigned long sp, unsigned long size,
 				     struct stack_info *info)
 {
-	return false;
+	struct kvm_nvhe_stacktrace_info *stacktrace_info
+				= this_cpu_ptr_nvhe_sym(kvm_stacktrace_info);
+	unsigned long low = (unsigned long)stacktrace_info->overflow_stack_base;
+	unsigned long high = low + OVERFLOW_STACK_SIZE;
+
+	return on_stack(sp, size, low, high, STACK_TYPE_OVERFLOW, info);
+}
+
+static inline bool on_hyp_stack(unsigned long sp, unsigned long size,
+				struct stack_info *info)
+{
+	struct kvm_nvhe_stacktrace_info *stacktrace_info
+				= this_cpu_ptr_nvhe_sym(kvm_stacktrace_info);
+	unsigned long low = (unsigned long)stacktrace_info->stack_base;
+	unsigned long high = low + PAGE_SIZE;
+
+	return on_stack(sp, size, low, high, STACK_TYPE_HYP, info);
 }
 
 static inline int notrace unwind_next(struct unwind_state *state)
 {
-	return 0;
+	struct stack_info info;
+
+	return unwind_next_common(state, &info, kvm_nvhe_stack_kern_va);
 }
 NOKPROBE_SYMBOL(unwind_next);
 
diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c
index a0188144a122..6a64293108c5 100644
--- a/arch/arm64/kvm/arm.c
+++ b/arch/arm64/kvm/arm.c
@@ -49,7 +49,7 @@ DEFINE_STATIC_KEY_FALSE(kvm_protected_mode_initialized);
 
 DECLARE_KVM_HYP_PER_CPU(unsigned long, kvm_hyp_vector);
 
-static DEFINE_PER_CPU(unsigned long, kvm_arm_hyp_stack_page);
+DEFINE_PER_CPU(unsigned long, kvm_arm_hyp_stack_page);
 unsigned long kvm_arm_hyp_percpu_base[NR_CPUS];
 DECLARE_KVM_NVHE_PER_CPU(struct kvm_nvhe_init_params, kvm_init_params);
 
-- 
2.37.1.359.gd136c6c3e2-goog

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply related	[flat|nested] 112+ messages in thread

* [PATCH v6 10/17] KVM: arm64: Implement non-protected nVHE hyp stack unwinder
@ 2022-07-26  7:37   ` Kalesh Singh
  0 siblings, 0 replies; 112+ messages in thread
From: Kalesh Singh @ 2022-07-26  7:37 UTC (permalink / raw)
  To: maz, mark.rutland, broonie, madvenka, tabba, oliver.upton
  Cc: will, qperret, kaleshsingh, james.morse, alexandru.elisei,
	suzuki.poulose, catalin.marinas, andreyknvl, vincenzo.frascino,
	mhiramat, ast, wangkefeng.wang, elver, keirf, yuzenghui, ardb,
	oupton, linux-arm-kernel, kvmarm, linux-kernel, android-mm,
	kernel-team

Implements the common framework necessary for unwind() to work
for non-protected nVHE mode:
    - on_accessible_stack()
    - on_overflow_stack()
    - unwind_next()

Non-protected nVHE unwind() is used to unwind and dump the hypervisor
stacktrace by the host in EL1

Signed-off-by: Kalesh Singh <kaleshsingh@google.com>
Reviewed-by: Fuad Tabba <tabba@google.com>
Tested-by: Fuad Tabba <tabba@google.com>
---

Changes in v6:
  - Add Fuad’s Reviewed-by and Tested-by tags

Changes in v5:
  - Use regular comments instead of doc comments, per Fuad

 arch/arm64/include/asm/stacktrace/common.h |  2 +
 arch/arm64/include/asm/stacktrace/nvhe.h   | 76 +++++++++++++++++++++-
 arch/arm64/kvm/arm.c                       |  2 +-
 3 files changed, 77 insertions(+), 3 deletions(-)

diff --git a/arch/arm64/include/asm/stacktrace/common.h b/arch/arm64/include/asm/stacktrace/common.h
index 45474b383630..3ebb69ea374a 100644
--- a/arch/arm64/include/asm/stacktrace/common.h
+++ b/arch/arm64/include/asm/stacktrace/common.h
@@ -34,6 +34,7 @@ enum stack_type {
 	STACK_TYPE_OVERFLOW,
 	STACK_TYPE_SDEI_NORMAL,
 	STACK_TYPE_SDEI_CRITICAL,
+	STACK_TYPE_HYP,
 	__NR_STACK_TYPES
 };
 
@@ -186,6 +187,7 @@ static inline int unwind_next_common(struct unwind_state *state,
 	 *
 	 * TASK -> IRQ -> OVERFLOW -> SDEI_NORMAL
 	 * TASK -> SDEI_NORMAL -> SDEI_CRITICAL -> OVERFLOW
+	 * HYP -> OVERFLOW
 	 *
 	 * ... but the nesting itself is strict. Once we transition from one
 	 * stack to another, it's never valid to unwind back to that first
diff --git a/arch/arm64/include/asm/stacktrace/nvhe.h b/arch/arm64/include/asm/stacktrace/nvhe.h
index 1192ae0f80c1..21082fd4a0b7 100644
--- a/arch/arm64/include/asm/stacktrace/nvhe.h
+++ b/arch/arm64/include/asm/stacktrace/nvhe.h
@@ -16,10 +16,19 @@
 
 #include <asm/stacktrace/common.h>
 
+static inline bool on_hyp_stack(unsigned long sp, unsigned long size,
+				struct stack_info *info);
+
 static inline bool on_accessible_stack(const struct task_struct *tsk,
 				       unsigned long sp, unsigned long size,
 				       struct stack_info *info)
 {
+	if (on_accessible_stack_common(tsk, sp, size, info))
+		return true;
+
+	if (on_hyp_stack(sp, size, info))
+		return true;
+
 	return false;
 }
 
@@ -31,15 +40,78 @@ static inline bool on_accessible_stack(const struct task_struct *tsk,
  * (by the host in EL1).
  */
 
+DECLARE_KVM_NVHE_PER_CPU(unsigned long [OVERFLOW_STACK_SIZE/sizeof(long)], overflow_stack);
+DECLARE_KVM_NVHE_PER_CPU(struct kvm_nvhe_stacktrace_info, kvm_stacktrace_info);
+DECLARE_PER_CPU(unsigned long, kvm_arm_hyp_stack_page);
+
+/*
+ * kvm_nvhe_stack_kern_va - Convert KVM nVHE HYP stack addresses to a kernel VAs
+ *
+ * The nVHE hypervisor stack is mapped in the flexible 'private' VA range, to
+ * allow for guard pages below the stack. Consequently, the fixed offset address
+ * translation macros won't work here.
+ *
+ * The kernel VA is calculated as an offset from the kernel VA of the hypervisor
+ * stack base.
+ *
+ * Returns true on success and updates @addr to its corresponding kernel VA;
+ * otherwise returns false.
+ */
+static inline bool kvm_nvhe_stack_kern_va(unsigned long *addr,
+					  enum stack_type type)
+{
+	struct kvm_nvhe_stacktrace_info *stacktrace_info;
+	unsigned long hyp_base, kern_base, hyp_offset;
+
+	stacktrace_info = this_cpu_ptr_nvhe_sym(kvm_stacktrace_info);
+
+	switch (type) {
+	case STACK_TYPE_HYP:
+		kern_base = (unsigned long)*this_cpu_ptr(&kvm_arm_hyp_stack_page);
+		hyp_base = (unsigned long)stacktrace_info->stack_base;
+		break;
+	case STACK_TYPE_OVERFLOW:
+		kern_base = (unsigned long)this_cpu_ptr_nvhe_sym(overflow_stack);
+		hyp_base = (unsigned long)stacktrace_info->overflow_stack_base;
+		break;
+	default:
+		return false;
+	}
+
+	hyp_offset = *addr - hyp_base;
+
+	*addr = kern_base + hyp_offset;
+
+	return true;
+}
+
 static inline bool on_overflow_stack(unsigned long sp, unsigned long size,
 				     struct stack_info *info)
 {
-	return false;
+	struct kvm_nvhe_stacktrace_info *stacktrace_info
+				= this_cpu_ptr_nvhe_sym(kvm_stacktrace_info);
+	unsigned long low = (unsigned long)stacktrace_info->overflow_stack_base;
+	unsigned long high = low + OVERFLOW_STACK_SIZE;
+
+	return on_stack(sp, size, low, high, STACK_TYPE_OVERFLOW, info);
+}
+
+static inline bool on_hyp_stack(unsigned long sp, unsigned long size,
+				struct stack_info *info)
+{
+	struct kvm_nvhe_stacktrace_info *stacktrace_info
+				= this_cpu_ptr_nvhe_sym(kvm_stacktrace_info);
+	unsigned long low = (unsigned long)stacktrace_info->stack_base;
+	unsigned long high = low + PAGE_SIZE;
+
+	return on_stack(sp, size, low, high, STACK_TYPE_HYP, info);
 }
 
 static inline int notrace unwind_next(struct unwind_state *state)
 {
-	return 0;
+	struct stack_info info;
+
+	return unwind_next_common(state, &info, kvm_nvhe_stack_kern_va);
 }
 NOKPROBE_SYMBOL(unwind_next);
 
diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c
index a0188144a122..6a64293108c5 100644
--- a/arch/arm64/kvm/arm.c
+++ b/arch/arm64/kvm/arm.c
@@ -49,7 +49,7 @@ DEFINE_STATIC_KEY_FALSE(kvm_protected_mode_initialized);
 
 DECLARE_KVM_HYP_PER_CPU(unsigned long, kvm_hyp_vector);
 
-static DEFINE_PER_CPU(unsigned long, kvm_arm_hyp_stack_page);
+DEFINE_PER_CPU(unsigned long, kvm_arm_hyp_stack_page);
 unsigned long kvm_arm_hyp_percpu_base[NR_CPUS];
 DECLARE_KVM_NVHE_PER_CPU(struct kvm_nvhe_init_params, kvm_init_params);
 
-- 
2.37.1.359.gd136c6c3e2-goog


^ permalink raw reply related	[flat|nested] 112+ messages in thread

* [PATCH v6 10/17] KVM: arm64: Implement non-protected nVHE hyp stack unwinder
@ 2022-07-26  7:37   ` Kalesh Singh
  0 siblings, 0 replies; 112+ messages in thread
From: Kalesh Singh @ 2022-07-26  7:37 UTC (permalink / raw)
  To: maz, mark.rutland, broonie, madvenka, tabba, oliver.upton
  Cc: will, qperret, kaleshsingh, james.morse, alexandru.elisei,
	suzuki.poulose, catalin.marinas, andreyknvl, vincenzo.frascino,
	mhiramat, ast, wangkefeng.wang, elver, keirf, yuzenghui, ardb,
	oupton, linux-arm-kernel, kvmarm, linux-kernel, android-mm,
	kernel-team

Implements the common framework necessary for unwind() to work
for non-protected nVHE mode:
    - on_accessible_stack()
    - on_overflow_stack()
    - unwind_next()

Non-protected nVHE unwind() is used to unwind and dump the hypervisor
stacktrace by the host in EL1

Signed-off-by: Kalesh Singh <kaleshsingh@google.com>
Reviewed-by: Fuad Tabba <tabba@google.com>
Tested-by: Fuad Tabba <tabba@google.com>
---

Changes in v6:
  - Add Fuad’s Reviewed-by and Tested-by tags

Changes in v5:
  - Use regular comments instead of doc comments, per Fuad

 arch/arm64/include/asm/stacktrace/common.h |  2 +
 arch/arm64/include/asm/stacktrace/nvhe.h   | 76 +++++++++++++++++++++-
 arch/arm64/kvm/arm.c                       |  2 +-
 3 files changed, 77 insertions(+), 3 deletions(-)

diff --git a/arch/arm64/include/asm/stacktrace/common.h b/arch/arm64/include/asm/stacktrace/common.h
index 45474b383630..3ebb69ea374a 100644
--- a/arch/arm64/include/asm/stacktrace/common.h
+++ b/arch/arm64/include/asm/stacktrace/common.h
@@ -34,6 +34,7 @@ enum stack_type {
 	STACK_TYPE_OVERFLOW,
 	STACK_TYPE_SDEI_NORMAL,
 	STACK_TYPE_SDEI_CRITICAL,
+	STACK_TYPE_HYP,
 	__NR_STACK_TYPES
 };
 
@@ -186,6 +187,7 @@ static inline int unwind_next_common(struct unwind_state *state,
 	 *
 	 * TASK -> IRQ -> OVERFLOW -> SDEI_NORMAL
 	 * TASK -> SDEI_NORMAL -> SDEI_CRITICAL -> OVERFLOW
+	 * HYP -> OVERFLOW
 	 *
 	 * ... but the nesting itself is strict. Once we transition from one
 	 * stack to another, it's never valid to unwind back to that first
diff --git a/arch/arm64/include/asm/stacktrace/nvhe.h b/arch/arm64/include/asm/stacktrace/nvhe.h
index 1192ae0f80c1..21082fd4a0b7 100644
--- a/arch/arm64/include/asm/stacktrace/nvhe.h
+++ b/arch/arm64/include/asm/stacktrace/nvhe.h
@@ -16,10 +16,19 @@
 
 #include <asm/stacktrace/common.h>
 
+static inline bool on_hyp_stack(unsigned long sp, unsigned long size,
+				struct stack_info *info);
+
 static inline bool on_accessible_stack(const struct task_struct *tsk,
 				       unsigned long sp, unsigned long size,
 				       struct stack_info *info)
 {
+	if (on_accessible_stack_common(tsk, sp, size, info))
+		return true;
+
+	if (on_hyp_stack(sp, size, info))
+		return true;
+
 	return false;
 }
 
@@ -31,15 +40,78 @@ static inline bool on_accessible_stack(const struct task_struct *tsk,
  * (by the host in EL1).
  */
 
+DECLARE_KVM_NVHE_PER_CPU(unsigned long [OVERFLOW_STACK_SIZE/sizeof(long)], overflow_stack);
+DECLARE_KVM_NVHE_PER_CPU(struct kvm_nvhe_stacktrace_info, kvm_stacktrace_info);
+DECLARE_PER_CPU(unsigned long, kvm_arm_hyp_stack_page);
+
+/*
+ * kvm_nvhe_stack_kern_va - Convert KVM nVHE HYP stack addresses to a kernel VAs
+ *
+ * The nVHE hypervisor stack is mapped in the flexible 'private' VA range, to
+ * allow for guard pages below the stack. Consequently, the fixed offset address
+ * translation macros won't work here.
+ *
+ * The kernel VA is calculated as an offset from the kernel VA of the hypervisor
+ * stack base.
+ *
+ * Returns true on success and updates @addr to its corresponding kernel VA;
+ * otherwise returns false.
+ */
+static inline bool kvm_nvhe_stack_kern_va(unsigned long *addr,
+					  enum stack_type type)
+{
+	struct kvm_nvhe_stacktrace_info *stacktrace_info;
+	unsigned long hyp_base, kern_base, hyp_offset;
+
+	stacktrace_info = this_cpu_ptr_nvhe_sym(kvm_stacktrace_info);
+
+	switch (type) {
+	case STACK_TYPE_HYP:
+		kern_base = (unsigned long)*this_cpu_ptr(&kvm_arm_hyp_stack_page);
+		hyp_base = (unsigned long)stacktrace_info->stack_base;
+		break;
+	case STACK_TYPE_OVERFLOW:
+		kern_base = (unsigned long)this_cpu_ptr_nvhe_sym(overflow_stack);
+		hyp_base = (unsigned long)stacktrace_info->overflow_stack_base;
+		break;
+	default:
+		return false;
+	}
+
+	hyp_offset = *addr - hyp_base;
+
+	*addr = kern_base + hyp_offset;
+
+	return true;
+}
+
 static inline bool on_overflow_stack(unsigned long sp, unsigned long size,
 				     struct stack_info *info)
 {
-	return false;
+	struct kvm_nvhe_stacktrace_info *stacktrace_info
+				= this_cpu_ptr_nvhe_sym(kvm_stacktrace_info);
+	unsigned long low = (unsigned long)stacktrace_info->overflow_stack_base;
+	unsigned long high = low + OVERFLOW_STACK_SIZE;
+
+	return on_stack(sp, size, low, high, STACK_TYPE_OVERFLOW, info);
+}
+
+static inline bool on_hyp_stack(unsigned long sp, unsigned long size,
+				struct stack_info *info)
+{
+	struct kvm_nvhe_stacktrace_info *stacktrace_info
+				= this_cpu_ptr_nvhe_sym(kvm_stacktrace_info);
+	unsigned long low = (unsigned long)stacktrace_info->stack_base;
+	unsigned long high = low + PAGE_SIZE;
+
+	return on_stack(sp, size, low, high, STACK_TYPE_HYP, info);
 }
 
 static inline int notrace unwind_next(struct unwind_state *state)
 {
-	return 0;
+	struct stack_info info;
+
+	return unwind_next_common(state, &info, kvm_nvhe_stack_kern_va);
 }
 NOKPROBE_SYMBOL(unwind_next);
 
diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c
index a0188144a122..6a64293108c5 100644
--- a/arch/arm64/kvm/arm.c
+++ b/arch/arm64/kvm/arm.c
@@ -49,7 +49,7 @@ DEFINE_STATIC_KEY_FALSE(kvm_protected_mode_initialized);
 
 DECLARE_KVM_HYP_PER_CPU(unsigned long, kvm_hyp_vector);
 
-static DEFINE_PER_CPU(unsigned long, kvm_arm_hyp_stack_page);
+DEFINE_PER_CPU(unsigned long, kvm_arm_hyp_stack_page);
 unsigned long kvm_arm_hyp_percpu_base[NR_CPUS];
 DECLARE_KVM_NVHE_PER_CPU(struct kvm_nvhe_init_params, kvm_init_params);
 
-- 
2.37.1.359.gd136c6c3e2-goog


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 112+ messages in thread

* [PATCH v6 11/17] KVM: arm64: Introduce hyp_dump_backtrace()
  2022-07-26  7:37 ` Kalesh Singh
  (?)
@ 2022-07-26  7:37   ` Kalesh Singh
  -1 siblings, 0 replies; 112+ messages in thread
From: Kalesh Singh @ 2022-07-26  7:37 UTC (permalink / raw)
  To: maz, mark.rutland, broonie, madvenka, tabba, oliver.upton
  Cc: wangkefeng.wang, catalin.marinas, ast, vincenzo.frascino, will,
	kvmarm, android-mm, kernel-team, elver, linux-arm-kernel,
	andreyknvl, linux-kernel, mhiramat

In non-protected nVHE mode, unwinds and dumps the hypervisor backtrace
from EL1. This is possible beacause the host can directly access the
hypervisor stack pages in non-protected mode.

The nVHE backtrace is dumped on hyp_panic(), before panicking the host.

[  101.498183] kvm [377]: nVHE call trace:
[  101.498363] kvm [377]:  [<ffff8000090a6570>] __kvm_nvhe_hyp_panic+0xac/0xf8
[  101.499045] kvm [377]:  [<ffff8000090a65cc>] __kvm_nvhe_hyp_panic_bad_stack+0x10/0x10
[  101.499498] kvm [377]:  [<ffff8000090a61e4>] __kvm_nvhe_recursive_death+0x24/0x34
. . .
[  101.524929] kvm [377]:  [<ffff8000090a61e4>] __kvm_nvhe_recursive_death+0x24/0x34
[  101.525062] kvm [377]:  [<ffff8000090a61e4>] __kvm_nvhe_recursive_death+0x24/0x34
[  101.525195] kvm [377]:  [<ffff8000090a5de4>] __kvm_nvhe___kvm_vcpu_run+0x30/0x40c
[  101.525333] kvm [377]:  [<ffff8000090a8b64>] __kvm_nvhe_handle___kvm_vcpu_run+0x30/0x48
[  101.525468] kvm [377]:  [<ffff8000090a88b8>] __kvm_nvhe_handle_trap+0xc4/0x128
[  101.525602] kvm [377]:  [<ffff8000090a7864>] __kvm_nvhe___host_exit+0x64/0x64
[  101.525745] kvm [377]: ---[ end nVHE call trace ]---

Signed-off-by: Kalesh Singh <kaleshsingh@google.com>
---

Changes in v6:
  - Fix some typos in commit text and comments, per Fuad
  - Remove kvm_nvhe_print_backtrace_entry(), per Oliver
  - To make nVHE call trace delimiters consistent between protected and
    non-protected mode, factor it out into helpers, per Oliver
  - Change end delimiter to more match that of arm64 stacktrace
    (---[ end nVHE call trace ]---), per Oliver

Changes in v5:
  - Move code out from nvhe.h header to handle_exit.c, per Marc
  - Fix stacktrace symbolization when CONFIG_RAMDOMIZE_BASE is enabled,
    per Fuad
  - Use regular comments instead of doc comments, per Fuad

 arch/arm64/include/asm/stacktrace/nvhe.h | 17 ++++++
 arch/arm64/kvm/handle_exit.c             | 69 ++++++++++++++++++++++++
 2 files changed, 86 insertions(+)

diff --git a/arch/arm64/include/asm/stacktrace/nvhe.h b/arch/arm64/include/asm/stacktrace/nvhe.h
index 21082fd4a0b7..170fe7459f7c 100644
--- a/arch/arm64/include/asm/stacktrace/nvhe.h
+++ b/arch/arm64/include/asm/stacktrace/nvhe.h
@@ -16,6 +16,23 @@
 
 #include <asm/stacktrace/common.h>
 
+/*
+ * kvm_nvhe_unwind_init - Start an unwind from the given nVHE HYP fp and pc
+ *
+ * @state : unwind_state to initialize
+ * @fp    : frame pointer at which to start the unwinding.
+ * @pc    : program counter at which to start the unwinding.
+ */
+static inline void kvm_nvhe_unwind_init(struct unwind_state *state,
+					unsigned long fp,
+					unsigned long pc)
+{
+	unwind_init_common(state, NULL);
+
+	state->fp = fp;
+	state->pc = pc;
+}
+
 static inline bool on_hyp_stack(unsigned long sp, unsigned long size,
 				struct stack_info *info);
 
diff --git a/arch/arm64/kvm/handle_exit.c b/arch/arm64/kvm/handle_exit.c
index f66c0142b335..e83e6f735100 100644
--- a/arch/arm64/kvm/handle_exit.c
+++ b/arch/arm64/kvm/handle_exit.c
@@ -17,6 +17,7 @@
 #include <asm/kvm_emulate.h>
 #include <asm/kvm_mmu.h>
 #include <asm/debug-monitors.h>
+#include <asm/stacktrace/nvhe.h>
 #include <asm/traps.h>
 
 #include <kvm/arm_hypercalls.h>
@@ -318,6 +319,71 @@ void handle_exit_early(struct kvm_vcpu *vcpu, int exception_index)
 		kvm_handle_guest_serror(vcpu, kvm_vcpu_get_esr(vcpu));
 }
 
+/*
+ * kvm_nvhe_dump_backtrace_entry - Symbolize and print an nVHE backtrace entry
+ *
+ * @arg    : the hypervisor offset, used for address translation
+ * @where  : the program counter corresponding to the stack frame
+ */
+static bool kvm_nvhe_dump_backtrace_entry(void *arg, unsigned long where)
+{
+	unsigned long va_mask = GENMASK_ULL(vabits_actual - 1, 0);
+	unsigned long hyp_offset = (unsigned long)arg;
+
+	/* Mask tags and convert to kern addr */
+	where = (where & va_mask) + hyp_offset;
+	kvm_err(" [<%016lx>] %pB\n", where, (void *)(where + kaslr_offset()));
+
+	return true;
+}
+
+static inline void kvm_nvhe_dump_backtrace_start(void)
+{
+	kvm_err("nVHE call trace:\n");
+}
+
+static inline void kvm_nvhe_dump_backtrace_end(void)
+{
+	kvm_err("---[ end nVHE call trace ]---\n");
+}
+
+/*
+ * hyp_dump_backtrace - Dump the non-protected nVHE backtrace.
+ *
+ * @hyp_offset: hypervisor offset, used for address translation.
+ *
+ * The host can directly access HYP stack pages in non-protected
+ * mode, so the unwinding is done directly from EL1. This removes
+ * the need for shared buffers between host and hypervisor for
+ * the stacktrace.
+ */
+static void hyp_dump_backtrace(unsigned long hyp_offset)
+{
+	struct kvm_nvhe_stacktrace_info *stacktrace_info;
+	struct unwind_state state;
+
+	stacktrace_info = this_cpu_ptr_nvhe_sym(kvm_stacktrace_info);
+
+	kvm_nvhe_unwind_init(&state, stacktrace_info->fp, stacktrace_info->pc);
+
+	kvm_nvhe_dump_backtrace_start();
+	unwind(&state, kvm_nvhe_dump_backtrace_entry, (void *)hyp_offset);
+	kvm_nvhe_dump_backtrace_end();
+}
+
+/*
+ * kvm_nvhe_dump_backtrace - Dump KVM nVHE hypervisor backtrace.
+ *
+ * @hyp_offset: hypervisor offset, used for address translation.
+ */
+static void kvm_nvhe_dump_backtrace(unsigned long hyp_offset)
+{
+	if (is_protected_kvm_enabled())
+		return;
+	else
+		hyp_dump_backtrace(hyp_offset);
+}
+
 void __noreturn __cold nvhe_hyp_panic_handler(u64 esr, u64 spsr,
 					      u64 elr_virt, u64 elr_phys,
 					      u64 par, uintptr_t vcpu,
@@ -353,6 +419,9 @@ void __noreturn __cold nvhe_hyp_panic_handler(u64 esr, u64 spsr,
 				(void *)panic_addr);
 	}
 
+	/* Dump the nVHE hypervisor backtrace */
+	kvm_nvhe_dump_backtrace(hyp_offset);
+
 	/*
 	 * Hyp has panicked and we're going to handle that by panicking the
 	 * kernel. The kernel offset will be revealed in the panic so we're
-- 
2.37.1.359.gd136c6c3e2-goog

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply related	[flat|nested] 112+ messages in thread

* [PATCH v6 11/17] KVM: arm64: Introduce hyp_dump_backtrace()
@ 2022-07-26  7:37   ` Kalesh Singh
  0 siblings, 0 replies; 112+ messages in thread
From: Kalesh Singh @ 2022-07-26  7:37 UTC (permalink / raw)
  To: maz, mark.rutland, broonie, madvenka, tabba, oliver.upton
  Cc: will, qperret, kaleshsingh, james.morse, alexandru.elisei,
	suzuki.poulose, catalin.marinas, andreyknvl, vincenzo.frascino,
	mhiramat, ast, wangkefeng.wang, elver, keirf, yuzenghui, ardb,
	oupton, linux-arm-kernel, kvmarm, linux-kernel, android-mm,
	kernel-team

In non-protected nVHE mode, unwinds and dumps the hypervisor backtrace
from EL1. This is possible beacause the host can directly access the
hypervisor stack pages in non-protected mode.

The nVHE backtrace is dumped on hyp_panic(), before panicking the host.

[  101.498183] kvm [377]: nVHE call trace:
[  101.498363] kvm [377]:  [<ffff8000090a6570>] __kvm_nvhe_hyp_panic+0xac/0xf8
[  101.499045] kvm [377]:  [<ffff8000090a65cc>] __kvm_nvhe_hyp_panic_bad_stack+0x10/0x10
[  101.499498] kvm [377]:  [<ffff8000090a61e4>] __kvm_nvhe_recursive_death+0x24/0x34
. . .
[  101.524929] kvm [377]:  [<ffff8000090a61e4>] __kvm_nvhe_recursive_death+0x24/0x34
[  101.525062] kvm [377]:  [<ffff8000090a61e4>] __kvm_nvhe_recursive_death+0x24/0x34
[  101.525195] kvm [377]:  [<ffff8000090a5de4>] __kvm_nvhe___kvm_vcpu_run+0x30/0x40c
[  101.525333] kvm [377]:  [<ffff8000090a8b64>] __kvm_nvhe_handle___kvm_vcpu_run+0x30/0x48
[  101.525468] kvm [377]:  [<ffff8000090a88b8>] __kvm_nvhe_handle_trap+0xc4/0x128
[  101.525602] kvm [377]:  [<ffff8000090a7864>] __kvm_nvhe___host_exit+0x64/0x64
[  101.525745] kvm [377]: ---[ end nVHE call trace ]---

Signed-off-by: Kalesh Singh <kaleshsingh@google.com>
---

Changes in v6:
  - Fix some typos in commit text and comments, per Fuad
  - Remove kvm_nvhe_print_backtrace_entry(), per Oliver
  - To make nVHE call trace delimiters consistent between protected and
    non-protected mode, factor it out into helpers, per Oliver
  - Change end delimiter to more match that of arm64 stacktrace
    (---[ end nVHE call trace ]---), per Oliver

Changes in v5:
  - Move code out from nvhe.h header to handle_exit.c, per Marc
  - Fix stacktrace symbolization when CONFIG_RAMDOMIZE_BASE is enabled,
    per Fuad
  - Use regular comments instead of doc comments, per Fuad

 arch/arm64/include/asm/stacktrace/nvhe.h | 17 ++++++
 arch/arm64/kvm/handle_exit.c             | 69 ++++++++++++++++++++++++
 2 files changed, 86 insertions(+)

diff --git a/arch/arm64/include/asm/stacktrace/nvhe.h b/arch/arm64/include/asm/stacktrace/nvhe.h
index 21082fd4a0b7..170fe7459f7c 100644
--- a/arch/arm64/include/asm/stacktrace/nvhe.h
+++ b/arch/arm64/include/asm/stacktrace/nvhe.h
@@ -16,6 +16,23 @@
 
 #include <asm/stacktrace/common.h>
 
+/*
+ * kvm_nvhe_unwind_init - Start an unwind from the given nVHE HYP fp and pc
+ *
+ * @state : unwind_state to initialize
+ * @fp    : frame pointer at which to start the unwinding.
+ * @pc    : program counter at which to start the unwinding.
+ */
+static inline void kvm_nvhe_unwind_init(struct unwind_state *state,
+					unsigned long fp,
+					unsigned long pc)
+{
+	unwind_init_common(state, NULL);
+
+	state->fp = fp;
+	state->pc = pc;
+}
+
 static inline bool on_hyp_stack(unsigned long sp, unsigned long size,
 				struct stack_info *info);
 
diff --git a/arch/arm64/kvm/handle_exit.c b/arch/arm64/kvm/handle_exit.c
index f66c0142b335..e83e6f735100 100644
--- a/arch/arm64/kvm/handle_exit.c
+++ b/arch/arm64/kvm/handle_exit.c
@@ -17,6 +17,7 @@
 #include <asm/kvm_emulate.h>
 #include <asm/kvm_mmu.h>
 #include <asm/debug-monitors.h>
+#include <asm/stacktrace/nvhe.h>
 #include <asm/traps.h>
 
 #include <kvm/arm_hypercalls.h>
@@ -318,6 +319,71 @@ void handle_exit_early(struct kvm_vcpu *vcpu, int exception_index)
 		kvm_handle_guest_serror(vcpu, kvm_vcpu_get_esr(vcpu));
 }
 
+/*
+ * kvm_nvhe_dump_backtrace_entry - Symbolize and print an nVHE backtrace entry
+ *
+ * @arg    : the hypervisor offset, used for address translation
+ * @where  : the program counter corresponding to the stack frame
+ */
+static bool kvm_nvhe_dump_backtrace_entry(void *arg, unsigned long where)
+{
+	unsigned long va_mask = GENMASK_ULL(vabits_actual - 1, 0);
+	unsigned long hyp_offset = (unsigned long)arg;
+
+	/* Mask tags and convert to kern addr */
+	where = (where & va_mask) + hyp_offset;
+	kvm_err(" [<%016lx>] %pB\n", where, (void *)(where + kaslr_offset()));
+
+	return true;
+}
+
+static inline void kvm_nvhe_dump_backtrace_start(void)
+{
+	kvm_err("nVHE call trace:\n");
+}
+
+static inline void kvm_nvhe_dump_backtrace_end(void)
+{
+	kvm_err("---[ end nVHE call trace ]---\n");
+}
+
+/*
+ * hyp_dump_backtrace - Dump the non-protected nVHE backtrace.
+ *
+ * @hyp_offset: hypervisor offset, used for address translation.
+ *
+ * The host can directly access HYP stack pages in non-protected
+ * mode, so the unwinding is done directly from EL1. This removes
+ * the need for shared buffers between host and hypervisor for
+ * the stacktrace.
+ */
+static void hyp_dump_backtrace(unsigned long hyp_offset)
+{
+	struct kvm_nvhe_stacktrace_info *stacktrace_info;
+	struct unwind_state state;
+
+	stacktrace_info = this_cpu_ptr_nvhe_sym(kvm_stacktrace_info);
+
+	kvm_nvhe_unwind_init(&state, stacktrace_info->fp, stacktrace_info->pc);
+
+	kvm_nvhe_dump_backtrace_start();
+	unwind(&state, kvm_nvhe_dump_backtrace_entry, (void *)hyp_offset);
+	kvm_nvhe_dump_backtrace_end();
+}
+
+/*
+ * kvm_nvhe_dump_backtrace - Dump KVM nVHE hypervisor backtrace.
+ *
+ * @hyp_offset: hypervisor offset, used for address translation.
+ */
+static void kvm_nvhe_dump_backtrace(unsigned long hyp_offset)
+{
+	if (is_protected_kvm_enabled())
+		return;
+	else
+		hyp_dump_backtrace(hyp_offset);
+}
+
 void __noreturn __cold nvhe_hyp_panic_handler(u64 esr, u64 spsr,
 					      u64 elr_virt, u64 elr_phys,
 					      u64 par, uintptr_t vcpu,
@@ -353,6 +419,9 @@ void __noreturn __cold nvhe_hyp_panic_handler(u64 esr, u64 spsr,
 				(void *)panic_addr);
 	}
 
+	/* Dump the nVHE hypervisor backtrace */
+	kvm_nvhe_dump_backtrace(hyp_offset);
+
 	/*
 	 * Hyp has panicked and we're going to handle that by panicking the
 	 * kernel. The kernel offset will be revealed in the panic so we're
-- 
2.37.1.359.gd136c6c3e2-goog


^ permalink raw reply related	[flat|nested] 112+ messages in thread

* [PATCH v6 11/17] KVM: arm64: Introduce hyp_dump_backtrace()
@ 2022-07-26  7:37   ` Kalesh Singh
  0 siblings, 0 replies; 112+ messages in thread
From: Kalesh Singh @ 2022-07-26  7:37 UTC (permalink / raw)
  To: maz, mark.rutland, broonie, madvenka, tabba, oliver.upton
  Cc: will, qperret, kaleshsingh, james.morse, alexandru.elisei,
	suzuki.poulose, catalin.marinas, andreyknvl, vincenzo.frascino,
	mhiramat, ast, wangkefeng.wang, elver, keirf, yuzenghui, ardb,
	oupton, linux-arm-kernel, kvmarm, linux-kernel, android-mm,
	kernel-team

In non-protected nVHE mode, unwinds and dumps the hypervisor backtrace
from EL1. This is possible beacause the host can directly access the
hypervisor stack pages in non-protected mode.

The nVHE backtrace is dumped on hyp_panic(), before panicking the host.

[  101.498183] kvm [377]: nVHE call trace:
[  101.498363] kvm [377]:  [<ffff8000090a6570>] __kvm_nvhe_hyp_panic+0xac/0xf8
[  101.499045] kvm [377]:  [<ffff8000090a65cc>] __kvm_nvhe_hyp_panic_bad_stack+0x10/0x10
[  101.499498] kvm [377]:  [<ffff8000090a61e4>] __kvm_nvhe_recursive_death+0x24/0x34
. . .
[  101.524929] kvm [377]:  [<ffff8000090a61e4>] __kvm_nvhe_recursive_death+0x24/0x34
[  101.525062] kvm [377]:  [<ffff8000090a61e4>] __kvm_nvhe_recursive_death+0x24/0x34
[  101.525195] kvm [377]:  [<ffff8000090a5de4>] __kvm_nvhe___kvm_vcpu_run+0x30/0x40c
[  101.525333] kvm [377]:  [<ffff8000090a8b64>] __kvm_nvhe_handle___kvm_vcpu_run+0x30/0x48
[  101.525468] kvm [377]:  [<ffff8000090a88b8>] __kvm_nvhe_handle_trap+0xc4/0x128
[  101.525602] kvm [377]:  [<ffff8000090a7864>] __kvm_nvhe___host_exit+0x64/0x64
[  101.525745] kvm [377]: ---[ end nVHE call trace ]---

Signed-off-by: Kalesh Singh <kaleshsingh@google.com>
---

Changes in v6:
  - Fix some typos in commit text and comments, per Fuad
  - Remove kvm_nvhe_print_backtrace_entry(), per Oliver
  - To make nVHE call trace delimiters consistent between protected and
    non-protected mode, factor it out into helpers, per Oliver
  - Change end delimiter to more match that of arm64 stacktrace
    (---[ end nVHE call trace ]---), per Oliver

Changes in v5:
  - Move code out from nvhe.h header to handle_exit.c, per Marc
  - Fix stacktrace symbolization when CONFIG_RAMDOMIZE_BASE is enabled,
    per Fuad
  - Use regular comments instead of doc comments, per Fuad

 arch/arm64/include/asm/stacktrace/nvhe.h | 17 ++++++
 arch/arm64/kvm/handle_exit.c             | 69 ++++++++++++++++++++++++
 2 files changed, 86 insertions(+)

diff --git a/arch/arm64/include/asm/stacktrace/nvhe.h b/arch/arm64/include/asm/stacktrace/nvhe.h
index 21082fd4a0b7..170fe7459f7c 100644
--- a/arch/arm64/include/asm/stacktrace/nvhe.h
+++ b/arch/arm64/include/asm/stacktrace/nvhe.h
@@ -16,6 +16,23 @@
 
 #include <asm/stacktrace/common.h>
 
+/*
+ * kvm_nvhe_unwind_init - Start an unwind from the given nVHE HYP fp and pc
+ *
+ * @state : unwind_state to initialize
+ * @fp    : frame pointer at which to start the unwinding.
+ * @pc    : program counter at which to start the unwinding.
+ */
+static inline void kvm_nvhe_unwind_init(struct unwind_state *state,
+					unsigned long fp,
+					unsigned long pc)
+{
+	unwind_init_common(state, NULL);
+
+	state->fp = fp;
+	state->pc = pc;
+}
+
 static inline bool on_hyp_stack(unsigned long sp, unsigned long size,
 				struct stack_info *info);
 
diff --git a/arch/arm64/kvm/handle_exit.c b/arch/arm64/kvm/handle_exit.c
index f66c0142b335..e83e6f735100 100644
--- a/arch/arm64/kvm/handle_exit.c
+++ b/arch/arm64/kvm/handle_exit.c
@@ -17,6 +17,7 @@
 #include <asm/kvm_emulate.h>
 #include <asm/kvm_mmu.h>
 #include <asm/debug-monitors.h>
+#include <asm/stacktrace/nvhe.h>
 #include <asm/traps.h>
 
 #include <kvm/arm_hypercalls.h>
@@ -318,6 +319,71 @@ void handle_exit_early(struct kvm_vcpu *vcpu, int exception_index)
 		kvm_handle_guest_serror(vcpu, kvm_vcpu_get_esr(vcpu));
 }
 
+/*
+ * kvm_nvhe_dump_backtrace_entry - Symbolize and print an nVHE backtrace entry
+ *
+ * @arg    : the hypervisor offset, used for address translation
+ * @where  : the program counter corresponding to the stack frame
+ */
+static bool kvm_nvhe_dump_backtrace_entry(void *arg, unsigned long where)
+{
+	unsigned long va_mask = GENMASK_ULL(vabits_actual - 1, 0);
+	unsigned long hyp_offset = (unsigned long)arg;
+
+	/* Mask tags and convert to kern addr */
+	where = (where & va_mask) + hyp_offset;
+	kvm_err(" [<%016lx>] %pB\n", where, (void *)(where + kaslr_offset()));
+
+	return true;
+}
+
+static inline void kvm_nvhe_dump_backtrace_start(void)
+{
+	kvm_err("nVHE call trace:\n");
+}
+
+static inline void kvm_nvhe_dump_backtrace_end(void)
+{
+	kvm_err("---[ end nVHE call trace ]---\n");
+}
+
+/*
+ * hyp_dump_backtrace - Dump the non-protected nVHE backtrace.
+ *
+ * @hyp_offset: hypervisor offset, used for address translation.
+ *
+ * The host can directly access HYP stack pages in non-protected
+ * mode, so the unwinding is done directly from EL1. This removes
+ * the need for shared buffers between host and hypervisor for
+ * the stacktrace.
+ */
+static void hyp_dump_backtrace(unsigned long hyp_offset)
+{
+	struct kvm_nvhe_stacktrace_info *stacktrace_info;
+	struct unwind_state state;
+
+	stacktrace_info = this_cpu_ptr_nvhe_sym(kvm_stacktrace_info);
+
+	kvm_nvhe_unwind_init(&state, stacktrace_info->fp, stacktrace_info->pc);
+
+	kvm_nvhe_dump_backtrace_start();
+	unwind(&state, kvm_nvhe_dump_backtrace_entry, (void *)hyp_offset);
+	kvm_nvhe_dump_backtrace_end();
+}
+
+/*
+ * kvm_nvhe_dump_backtrace - Dump KVM nVHE hypervisor backtrace.
+ *
+ * @hyp_offset: hypervisor offset, used for address translation.
+ */
+static void kvm_nvhe_dump_backtrace(unsigned long hyp_offset)
+{
+	if (is_protected_kvm_enabled())
+		return;
+	else
+		hyp_dump_backtrace(hyp_offset);
+}
+
 void __noreturn __cold nvhe_hyp_panic_handler(u64 esr, u64 spsr,
 					      u64 elr_virt, u64 elr_phys,
 					      u64 par, uintptr_t vcpu,
@@ -353,6 +419,9 @@ void __noreturn __cold nvhe_hyp_panic_handler(u64 esr, u64 spsr,
 				(void *)panic_addr);
 	}
 
+	/* Dump the nVHE hypervisor backtrace */
+	kvm_nvhe_dump_backtrace(hyp_offset);
+
 	/*
 	 * Hyp has panicked and we're going to handle that by panicking the
 	 * kernel. The kernel offset will be revealed in the panic so we're
-- 
2.37.1.359.gd136c6c3e2-goog


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 112+ messages in thread

* [PATCH v6 12/17] KVM: arm64: Add PROTECTED_NVHE_STACKTRACE Kconfig
  2022-07-26  7:37 ` Kalesh Singh
  (?)
@ 2022-07-26  7:37   ` Kalesh Singh
  -1 siblings, 0 replies; 112+ messages in thread
From: Kalesh Singh @ 2022-07-26  7:37 UTC (permalink / raw)
  To: maz, mark.rutland, broonie, madvenka, tabba, oliver.upton
  Cc: wangkefeng.wang, catalin.marinas, ast, vincenzo.frascino, will,
	kvmarm, android-mm, kernel-team, elver, linux-arm-kernel,
	andreyknvl, linux-kernel, mhiramat

This can be used to disable stacktrace for the protected KVM
nVHE hypervisor, in order to save on the associated memory usage.

This option is disabled by default, since protected KVM is not widely
used on platforms other than Android currently.

Signed-off-by: Kalesh Singh <kaleshsingh@google.com>
Reviewed-by: Fuad Tabba <tabba@google.com>
Tested-by: Fuad Tabba <tabba@google.com>
---

Changes in v6:
  - Add Fuad’s Reviewed-by and Tested-by tags

Changes in v5:
  - Make PROTECTED_NVHE_STACKTRACE depend on NVHE_EL2_DEBUG, per Marc

 arch/arm64/kvm/Kconfig | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/arch/arm64/kvm/Kconfig b/arch/arm64/kvm/Kconfig
index 8a5fbbf084df..09c995869916 100644
--- a/arch/arm64/kvm/Kconfig
+++ b/arch/arm64/kvm/Kconfig
@@ -46,6 +46,21 @@ menuconfig KVM
 
 	  If unsure, say N.
 
+config PROTECTED_NVHE_STACKTRACE
+	bool "Protected KVM hypervisor stacktraces"
+	depends on NVHE_EL2_DEBUG
+	default n
+	help
+	  Say Y here to enable pKVM hypervisor stacktraces on hyp_panic()
+
+	  If you are not using protected nVHE (pKVM), say N.
+
+	  If using protected nVHE mode, but cannot afford the associated
+	  memory cost (less than 0.75 page per CPU) of pKVM stacktraces,
+	  say N.
+
+	  If unsure, say N.
+
 config NVHE_EL2_DEBUG
 	bool "Debug mode for non-VHE EL2 object"
 	depends on KVM
-- 
2.37.1.359.gd136c6c3e2-goog

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply related	[flat|nested] 112+ messages in thread

* [PATCH v6 12/17] KVM: arm64: Add PROTECTED_NVHE_STACKTRACE Kconfig
@ 2022-07-26  7:37   ` Kalesh Singh
  0 siblings, 0 replies; 112+ messages in thread
From: Kalesh Singh @ 2022-07-26  7:37 UTC (permalink / raw)
  To: maz, mark.rutland, broonie, madvenka, tabba, oliver.upton
  Cc: will, qperret, kaleshsingh, james.morse, alexandru.elisei,
	suzuki.poulose, catalin.marinas, andreyknvl, vincenzo.frascino,
	mhiramat, ast, wangkefeng.wang, elver, keirf, yuzenghui, ardb,
	oupton, linux-arm-kernel, kvmarm, linux-kernel, android-mm,
	kernel-team

This can be used to disable stacktrace for the protected KVM
nVHE hypervisor, in order to save on the associated memory usage.

This option is disabled by default, since protected KVM is not widely
used on platforms other than Android currently.

Signed-off-by: Kalesh Singh <kaleshsingh@google.com>
Reviewed-by: Fuad Tabba <tabba@google.com>
Tested-by: Fuad Tabba <tabba@google.com>
---

Changes in v6:
  - Add Fuad’s Reviewed-by and Tested-by tags

Changes in v5:
  - Make PROTECTED_NVHE_STACKTRACE depend on NVHE_EL2_DEBUG, per Marc

 arch/arm64/kvm/Kconfig | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/arch/arm64/kvm/Kconfig b/arch/arm64/kvm/Kconfig
index 8a5fbbf084df..09c995869916 100644
--- a/arch/arm64/kvm/Kconfig
+++ b/arch/arm64/kvm/Kconfig
@@ -46,6 +46,21 @@ menuconfig KVM
 
 	  If unsure, say N.
 
+config PROTECTED_NVHE_STACKTRACE
+	bool "Protected KVM hypervisor stacktraces"
+	depends on NVHE_EL2_DEBUG
+	default n
+	help
+	  Say Y here to enable pKVM hypervisor stacktraces on hyp_panic()
+
+	  If you are not using protected nVHE (pKVM), say N.
+
+	  If using protected nVHE mode, but cannot afford the associated
+	  memory cost (less than 0.75 page per CPU) of pKVM stacktraces,
+	  say N.
+
+	  If unsure, say N.
+
 config NVHE_EL2_DEBUG
 	bool "Debug mode for non-VHE EL2 object"
 	depends on KVM
-- 
2.37.1.359.gd136c6c3e2-goog


^ permalink raw reply related	[flat|nested] 112+ messages in thread

* [PATCH v6 12/17] KVM: arm64: Add PROTECTED_NVHE_STACKTRACE Kconfig
@ 2022-07-26  7:37   ` Kalesh Singh
  0 siblings, 0 replies; 112+ messages in thread
From: Kalesh Singh @ 2022-07-26  7:37 UTC (permalink / raw)
  To: maz, mark.rutland, broonie, madvenka, tabba, oliver.upton
  Cc: will, qperret, kaleshsingh, james.morse, alexandru.elisei,
	suzuki.poulose, catalin.marinas, andreyknvl, vincenzo.frascino,
	mhiramat, ast, wangkefeng.wang, elver, keirf, yuzenghui, ardb,
	oupton, linux-arm-kernel, kvmarm, linux-kernel, android-mm,
	kernel-team

This can be used to disable stacktrace for the protected KVM
nVHE hypervisor, in order to save on the associated memory usage.

This option is disabled by default, since protected KVM is not widely
used on platforms other than Android currently.

Signed-off-by: Kalesh Singh <kaleshsingh@google.com>
Reviewed-by: Fuad Tabba <tabba@google.com>
Tested-by: Fuad Tabba <tabba@google.com>
---

Changes in v6:
  - Add Fuad’s Reviewed-by and Tested-by tags

Changes in v5:
  - Make PROTECTED_NVHE_STACKTRACE depend on NVHE_EL2_DEBUG, per Marc

 arch/arm64/kvm/Kconfig | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/arch/arm64/kvm/Kconfig b/arch/arm64/kvm/Kconfig
index 8a5fbbf084df..09c995869916 100644
--- a/arch/arm64/kvm/Kconfig
+++ b/arch/arm64/kvm/Kconfig
@@ -46,6 +46,21 @@ menuconfig KVM
 
 	  If unsure, say N.
 
+config PROTECTED_NVHE_STACKTRACE
+	bool "Protected KVM hypervisor stacktraces"
+	depends on NVHE_EL2_DEBUG
+	default n
+	help
+	  Say Y here to enable pKVM hypervisor stacktraces on hyp_panic()
+
+	  If you are not using protected nVHE (pKVM), say N.
+
+	  If using protected nVHE mode, but cannot afford the associated
+	  memory cost (less than 0.75 page per CPU) of pKVM stacktraces,
+	  say N.
+
+	  If unsure, say N.
+
 config NVHE_EL2_DEBUG
 	bool "Debug mode for non-VHE EL2 object"
 	depends on KVM
-- 
2.37.1.359.gd136c6c3e2-goog


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 112+ messages in thread

* [PATCH v6 13/17] KVM: arm64: Allocate shared pKVM hyp stacktrace buffers
  2022-07-26  7:37 ` Kalesh Singh
  (?)
@ 2022-07-26  7:37   ` Kalesh Singh
  -1 siblings, 0 replies; 112+ messages in thread
From: Kalesh Singh @ 2022-07-26  7:37 UTC (permalink / raw)
  To: maz, mark.rutland, broonie, madvenka, tabba, oliver.upton
  Cc: wangkefeng.wang, catalin.marinas, ast, vincenzo.frascino, will,
	kvmarm, android-mm, kernel-team, elver, linux-arm-kernel,
	andreyknvl, linux-kernel, mhiramat

In protected nVHE mode the host cannot directly access
hypervisor memory, so we will dump the hypervisor stacktrace
to a shared buffer with the host.

The minimum size for the buffer required, assuming the min frame
size of [x29, x30] (2 * sizeof(long)), is half the combined size of
the hypervisor and overflow stacks plus an additional entry to
delimit the end of the stacktrace.

The stacktrace buffers are used later in the series to dump the
nVHE hypervisor stacktrace when using protected-mode.

Signed-off-by: Kalesh Singh <kaleshsingh@google.com>
Reviewed-by: Fuad Tabba <tabba@google.com>
Tested-by: Fuad Tabba <tabba@google.com>
---

Changes in v6:
  - Fix typo in commit text, per Fuad
  - Add Fuad’s Reviewed-by and Tested-by tags

Changes in v5:
  - Fix typo in commit text, per Marc

 arch/arm64/include/asm/memory.h      | 8 ++++++++
 arch/arm64/kvm/hyp/nvhe/stacktrace.c | 4 ++++
 2 files changed, 12 insertions(+)

diff --git a/arch/arm64/include/asm/memory.h b/arch/arm64/include/asm/memory.h
index 0af70d9abede..cab80a9a4086 100644
--- a/arch/arm64/include/asm/memory.h
+++ b/arch/arm64/include/asm/memory.h
@@ -113,6 +113,14 @@
 
 #define OVERFLOW_STACK_SIZE	SZ_4K
 
+/*
+ * With the minimum frame size of [x29, x30], exactly half the combined
+ * sizes of the hyp and overflow stacks is the maximum size needed to
+ * save the unwinded stacktrace; plus an additional entry to delimit the
+ * end.
+ */
+#define NVHE_STACKTRACE_SIZE	((OVERFLOW_STACK_SIZE + PAGE_SIZE) / 2 + sizeof(long))
+
 /*
  * Alignment of kernel segments (e.g. .text, .data).
  *
diff --git a/arch/arm64/kvm/hyp/nvhe/stacktrace.c b/arch/arm64/kvm/hyp/nvhe/stacktrace.c
index b8a280aa026a..e2edda92a108 100644
--- a/arch/arm64/kvm/hyp/nvhe/stacktrace.c
+++ b/arch/arm64/kvm/hyp/nvhe/stacktrace.c
@@ -34,6 +34,10 @@ static void hyp_prepare_backtrace(unsigned long fp, unsigned long pc)
 	stacktrace_info->pc = pc;
 }
 
+#ifdef CONFIG_PROTECTED_NVHE_STACKTRACE
+DEFINE_PER_CPU(unsigned long [NVHE_STACKTRACE_SIZE/sizeof(long)], pkvm_stacktrace);
+#endif /* CONFIG_PROTECTED_NVHE_STACKTRACE */
+
 /*
  * kvm_nvhe_prepare_backtrace - prepare to dump the nVHE backtrace
  *
-- 
2.37.1.359.gd136c6c3e2-goog

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply related	[flat|nested] 112+ messages in thread

* [PATCH v6 13/17] KVM: arm64: Allocate shared pKVM hyp stacktrace buffers
@ 2022-07-26  7:37   ` Kalesh Singh
  0 siblings, 0 replies; 112+ messages in thread
From: Kalesh Singh @ 2022-07-26  7:37 UTC (permalink / raw)
  To: maz, mark.rutland, broonie, madvenka, tabba, oliver.upton
  Cc: will, qperret, kaleshsingh, james.morse, alexandru.elisei,
	suzuki.poulose, catalin.marinas, andreyknvl, vincenzo.frascino,
	mhiramat, ast, wangkefeng.wang, elver, keirf, yuzenghui, ardb,
	oupton, linux-arm-kernel, kvmarm, linux-kernel, android-mm,
	kernel-team

In protected nVHE mode the host cannot directly access
hypervisor memory, so we will dump the hypervisor stacktrace
to a shared buffer with the host.

The minimum size for the buffer required, assuming the min frame
size of [x29, x30] (2 * sizeof(long)), is half the combined size of
the hypervisor and overflow stacks plus an additional entry to
delimit the end of the stacktrace.

The stacktrace buffers are used later in the series to dump the
nVHE hypervisor stacktrace when using protected-mode.

Signed-off-by: Kalesh Singh <kaleshsingh@google.com>
Reviewed-by: Fuad Tabba <tabba@google.com>
Tested-by: Fuad Tabba <tabba@google.com>
---

Changes in v6:
  - Fix typo in commit text, per Fuad
  - Add Fuad’s Reviewed-by and Tested-by tags

Changes in v5:
  - Fix typo in commit text, per Marc

 arch/arm64/include/asm/memory.h      | 8 ++++++++
 arch/arm64/kvm/hyp/nvhe/stacktrace.c | 4 ++++
 2 files changed, 12 insertions(+)

diff --git a/arch/arm64/include/asm/memory.h b/arch/arm64/include/asm/memory.h
index 0af70d9abede..cab80a9a4086 100644
--- a/arch/arm64/include/asm/memory.h
+++ b/arch/arm64/include/asm/memory.h
@@ -113,6 +113,14 @@
 
 #define OVERFLOW_STACK_SIZE	SZ_4K
 
+/*
+ * With the minimum frame size of [x29, x30], exactly half the combined
+ * sizes of the hyp and overflow stacks is the maximum size needed to
+ * save the unwinded stacktrace; plus an additional entry to delimit the
+ * end.
+ */
+#define NVHE_STACKTRACE_SIZE	((OVERFLOW_STACK_SIZE + PAGE_SIZE) / 2 + sizeof(long))
+
 /*
  * Alignment of kernel segments (e.g. .text, .data).
  *
diff --git a/arch/arm64/kvm/hyp/nvhe/stacktrace.c b/arch/arm64/kvm/hyp/nvhe/stacktrace.c
index b8a280aa026a..e2edda92a108 100644
--- a/arch/arm64/kvm/hyp/nvhe/stacktrace.c
+++ b/arch/arm64/kvm/hyp/nvhe/stacktrace.c
@@ -34,6 +34,10 @@ static void hyp_prepare_backtrace(unsigned long fp, unsigned long pc)
 	stacktrace_info->pc = pc;
 }
 
+#ifdef CONFIG_PROTECTED_NVHE_STACKTRACE
+DEFINE_PER_CPU(unsigned long [NVHE_STACKTRACE_SIZE/sizeof(long)], pkvm_stacktrace);
+#endif /* CONFIG_PROTECTED_NVHE_STACKTRACE */
+
 /*
  * kvm_nvhe_prepare_backtrace - prepare to dump the nVHE backtrace
  *
-- 
2.37.1.359.gd136c6c3e2-goog


^ permalink raw reply related	[flat|nested] 112+ messages in thread

* [PATCH v6 13/17] KVM: arm64: Allocate shared pKVM hyp stacktrace buffers
@ 2022-07-26  7:37   ` Kalesh Singh
  0 siblings, 0 replies; 112+ messages in thread
From: Kalesh Singh @ 2022-07-26  7:37 UTC (permalink / raw)
  To: maz, mark.rutland, broonie, madvenka, tabba, oliver.upton
  Cc: will, qperret, kaleshsingh, james.morse, alexandru.elisei,
	suzuki.poulose, catalin.marinas, andreyknvl, vincenzo.frascino,
	mhiramat, ast, wangkefeng.wang, elver, keirf, yuzenghui, ardb,
	oupton, linux-arm-kernel, kvmarm, linux-kernel, android-mm,
	kernel-team

In protected nVHE mode the host cannot directly access
hypervisor memory, so we will dump the hypervisor stacktrace
to a shared buffer with the host.

The minimum size for the buffer required, assuming the min frame
size of [x29, x30] (2 * sizeof(long)), is half the combined size of
the hypervisor and overflow stacks plus an additional entry to
delimit the end of the stacktrace.

The stacktrace buffers are used later in the series to dump the
nVHE hypervisor stacktrace when using protected-mode.

Signed-off-by: Kalesh Singh <kaleshsingh@google.com>
Reviewed-by: Fuad Tabba <tabba@google.com>
Tested-by: Fuad Tabba <tabba@google.com>
---

Changes in v6:
  - Fix typo in commit text, per Fuad
  - Add Fuad’s Reviewed-by and Tested-by tags

Changes in v5:
  - Fix typo in commit text, per Marc

 arch/arm64/include/asm/memory.h      | 8 ++++++++
 arch/arm64/kvm/hyp/nvhe/stacktrace.c | 4 ++++
 2 files changed, 12 insertions(+)

diff --git a/arch/arm64/include/asm/memory.h b/arch/arm64/include/asm/memory.h
index 0af70d9abede..cab80a9a4086 100644
--- a/arch/arm64/include/asm/memory.h
+++ b/arch/arm64/include/asm/memory.h
@@ -113,6 +113,14 @@
 
 #define OVERFLOW_STACK_SIZE	SZ_4K
 
+/*
+ * With the minimum frame size of [x29, x30], exactly half the combined
+ * sizes of the hyp and overflow stacks is the maximum size needed to
+ * save the unwinded stacktrace; plus an additional entry to delimit the
+ * end.
+ */
+#define NVHE_STACKTRACE_SIZE	((OVERFLOW_STACK_SIZE + PAGE_SIZE) / 2 + sizeof(long))
+
 /*
  * Alignment of kernel segments (e.g. .text, .data).
  *
diff --git a/arch/arm64/kvm/hyp/nvhe/stacktrace.c b/arch/arm64/kvm/hyp/nvhe/stacktrace.c
index b8a280aa026a..e2edda92a108 100644
--- a/arch/arm64/kvm/hyp/nvhe/stacktrace.c
+++ b/arch/arm64/kvm/hyp/nvhe/stacktrace.c
@@ -34,6 +34,10 @@ static void hyp_prepare_backtrace(unsigned long fp, unsigned long pc)
 	stacktrace_info->pc = pc;
 }
 
+#ifdef CONFIG_PROTECTED_NVHE_STACKTRACE
+DEFINE_PER_CPU(unsigned long [NVHE_STACKTRACE_SIZE/sizeof(long)], pkvm_stacktrace);
+#endif /* CONFIG_PROTECTED_NVHE_STACKTRACE */
+
 /*
  * kvm_nvhe_prepare_backtrace - prepare to dump the nVHE backtrace
  *
-- 
2.37.1.359.gd136c6c3e2-goog


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 112+ messages in thread

* [PATCH v6 14/17] KVM: arm64: Stub implementation of pKVM HYP stack unwinder
  2022-07-26  7:37 ` Kalesh Singh
  (?)
@ 2022-07-26  7:37   ` Kalesh Singh
  -1 siblings, 0 replies; 112+ messages in thread
From: Kalesh Singh @ 2022-07-26  7:37 UTC (permalink / raw)
  To: maz, mark.rutland, broonie, madvenka, tabba, oliver.upton
  Cc: wangkefeng.wang, catalin.marinas, ast, vincenzo.frascino, will,
	kvmarm, android-mm, kernel-team, elver, linux-arm-kernel,
	andreyknvl, linux-kernel, mhiramat

Add some stub implementations of protected nVHE stack unwinder, for
building. These are implemented later in this series.

Signed-off-by: Kalesh Singh <kaleshsingh@google.com>
Reviewed-by: Fuad Tabba <tabba@google.com>
Tested-by: Fuad Tabba <tabba@google.com>
---

Changes in v6:
  - Add Fuad’s Reviewed-by and Tested-by tags

Changes in v5:
  - Mark unwind_next() as inline, per Marc

 arch/arm64/include/asm/stacktrace/nvhe.h | 35 ++++++++++++++++++++++--
 1 file changed, 33 insertions(+), 2 deletions(-)

diff --git a/arch/arm64/include/asm/stacktrace/nvhe.h b/arch/arm64/include/asm/stacktrace/nvhe.h
index 170fe7459f7c..2ce59c058806 100644
--- a/arch/arm64/include/asm/stacktrace/nvhe.h
+++ b/arch/arm64/include/asm/stacktrace/nvhe.h
@@ -9,6 +9,10 @@
  *      to allocate shared buffers for the host to read the unwinded
  *      stacktrace.
  *
+ *   2) pKVM (protected nVHE) mode - the host cannot directly access
+ *      the HYP memory. The stack is unwinded in EL2 and dumped to a shared
+ *      buffer where the host can read and print the stacktrace.
+ *
  * Copyright (C) 2022 Google LLC
  */
 #ifndef __ASM_STACKTRACE_NVHE_H
@@ -49,7 +53,34 @@ static inline bool on_accessible_stack(const struct task_struct *tsk,
 	return false;
 }
 
-#ifndef __KVM_NVHE_HYPERVISOR__
+#ifdef __KVM_NVHE_HYPERVISOR__
+/*
+ * Protected nVHE HYP stack unwinder
+ *
+ * In protected mode, the unwinding is done by the hypervisor in EL2.
+ */
+
+#ifdef CONFIG_PROTECTED_NVHE_STACKTRACE
+static inline bool on_overflow_stack(unsigned long sp, unsigned long size,
+				     struct stack_info *info)
+{
+	return false;
+}
+
+static inline bool on_hyp_stack(unsigned long sp, unsigned long size,
+				struct stack_info *info)
+{
+	return false;
+}
+
+static inline int notrace unwind_next(struct unwind_state *state)
+{
+	return 0;
+}
+NOKPROBE_SYMBOL(unwind_next);
+#endif	/* CONFIG_PROTECTED_NVHE_STACKTRACE */
+
+#else	/* !__KVM_NVHE_HYPERVISOR__ */
 /*
  * Conventional (non-protected) nVHE HYP stack unwinder
  *
@@ -132,5 +163,5 @@ static inline int notrace unwind_next(struct unwind_state *state)
 }
 NOKPROBE_SYMBOL(unwind_next);
 
-#endif	/* !__KVM_NVHE_HYPERVISOR__ */
+#endif	/* __KVM_NVHE_HYPERVISOR__ */
 #endif	/* __ASM_STACKTRACE_NVHE_H */
-- 
2.37.1.359.gd136c6c3e2-goog

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply related	[flat|nested] 112+ messages in thread

* [PATCH v6 14/17] KVM: arm64: Stub implementation of pKVM HYP stack unwinder
@ 2022-07-26  7:37   ` Kalesh Singh
  0 siblings, 0 replies; 112+ messages in thread
From: Kalesh Singh @ 2022-07-26  7:37 UTC (permalink / raw)
  To: maz, mark.rutland, broonie, madvenka, tabba, oliver.upton
  Cc: will, qperret, kaleshsingh, james.morse, alexandru.elisei,
	suzuki.poulose, catalin.marinas, andreyknvl, vincenzo.frascino,
	mhiramat, ast, wangkefeng.wang, elver, keirf, yuzenghui, ardb,
	oupton, linux-arm-kernel, kvmarm, linux-kernel, android-mm,
	kernel-team

Add some stub implementations of protected nVHE stack unwinder, for
building. These are implemented later in this series.

Signed-off-by: Kalesh Singh <kaleshsingh@google.com>
Reviewed-by: Fuad Tabba <tabba@google.com>
Tested-by: Fuad Tabba <tabba@google.com>
---

Changes in v6:
  - Add Fuad’s Reviewed-by and Tested-by tags

Changes in v5:
  - Mark unwind_next() as inline, per Marc

 arch/arm64/include/asm/stacktrace/nvhe.h | 35 ++++++++++++++++++++++--
 1 file changed, 33 insertions(+), 2 deletions(-)

diff --git a/arch/arm64/include/asm/stacktrace/nvhe.h b/arch/arm64/include/asm/stacktrace/nvhe.h
index 170fe7459f7c..2ce59c058806 100644
--- a/arch/arm64/include/asm/stacktrace/nvhe.h
+++ b/arch/arm64/include/asm/stacktrace/nvhe.h
@@ -9,6 +9,10 @@
  *      to allocate shared buffers for the host to read the unwinded
  *      stacktrace.
  *
+ *   2) pKVM (protected nVHE) mode - the host cannot directly access
+ *      the HYP memory. The stack is unwinded in EL2 and dumped to a shared
+ *      buffer where the host can read and print the stacktrace.
+ *
  * Copyright (C) 2022 Google LLC
  */
 #ifndef __ASM_STACKTRACE_NVHE_H
@@ -49,7 +53,34 @@ static inline bool on_accessible_stack(const struct task_struct *tsk,
 	return false;
 }
 
-#ifndef __KVM_NVHE_HYPERVISOR__
+#ifdef __KVM_NVHE_HYPERVISOR__
+/*
+ * Protected nVHE HYP stack unwinder
+ *
+ * In protected mode, the unwinding is done by the hypervisor in EL2.
+ */
+
+#ifdef CONFIG_PROTECTED_NVHE_STACKTRACE
+static inline bool on_overflow_stack(unsigned long sp, unsigned long size,
+				     struct stack_info *info)
+{
+	return false;
+}
+
+static inline bool on_hyp_stack(unsigned long sp, unsigned long size,
+				struct stack_info *info)
+{
+	return false;
+}
+
+static inline int notrace unwind_next(struct unwind_state *state)
+{
+	return 0;
+}
+NOKPROBE_SYMBOL(unwind_next);
+#endif	/* CONFIG_PROTECTED_NVHE_STACKTRACE */
+
+#else	/* !__KVM_NVHE_HYPERVISOR__ */
 /*
  * Conventional (non-protected) nVHE HYP stack unwinder
  *
@@ -132,5 +163,5 @@ static inline int notrace unwind_next(struct unwind_state *state)
 }
 NOKPROBE_SYMBOL(unwind_next);
 
-#endif	/* !__KVM_NVHE_HYPERVISOR__ */
+#endif	/* __KVM_NVHE_HYPERVISOR__ */
 #endif	/* __ASM_STACKTRACE_NVHE_H */
-- 
2.37.1.359.gd136c6c3e2-goog


^ permalink raw reply related	[flat|nested] 112+ messages in thread

* [PATCH v6 14/17] KVM: arm64: Stub implementation of pKVM HYP stack unwinder
@ 2022-07-26  7:37   ` Kalesh Singh
  0 siblings, 0 replies; 112+ messages in thread
From: Kalesh Singh @ 2022-07-26  7:37 UTC (permalink / raw)
  To: maz, mark.rutland, broonie, madvenka, tabba, oliver.upton
  Cc: will, qperret, kaleshsingh, james.morse, alexandru.elisei,
	suzuki.poulose, catalin.marinas, andreyknvl, vincenzo.frascino,
	mhiramat, ast, wangkefeng.wang, elver, keirf, yuzenghui, ardb,
	oupton, linux-arm-kernel, kvmarm, linux-kernel, android-mm,
	kernel-team

Add some stub implementations of protected nVHE stack unwinder, for
building. These are implemented later in this series.

Signed-off-by: Kalesh Singh <kaleshsingh@google.com>
Reviewed-by: Fuad Tabba <tabba@google.com>
Tested-by: Fuad Tabba <tabba@google.com>
---

Changes in v6:
  - Add Fuad’s Reviewed-by and Tested-by tags

Changes in v5:
  - Mark unwind_next() as inline, per Marc

 arch/arm64/include/asm/stacktrace/nvhe.h | 35 ++++++++++++++++++++++--
 1 file changed, 33 insertions(+), 2 deletions(-)

diff --git a/arch/arm64/include/asm/stacktrace/nvhe.h b/arch/arm64/include/asm/stacktrace/nvhe.h
index 170fe7459f7c..2ce59c058806 100644
--- a/arch/arm64/include/asm/stacktrace/nvhe.h
+++ b/arch/arm64/include/asm/stacktrace/nvhe.h
@@ -9,6 +9,10 @@
  *      to allocate shared buffers for the host to read the unwinded
  *      stacktrace.
  *
+ *   2) pKVM (protected nVHE) mode - the host cannot directly access
+ *      the HYP memory. The stack is unwinded in EL2 and dumped to a shared
+ *      buffer where the host can read and print the stacktrace.
+ *
  * Copyright (C) 2022 Google LLC
  */
 #ifndef __ASM_STACKTRACE_NVHE_H
@@ -49,7 +53,34 @@ static inline bool on_accessible_stack(const struct task_struct *tsk,
 	return false;
 }
 
-#ifndef __KVM_NVHE_HYPERVISOR__
+#ifdef __KVM_NVHE_HYPERVISOR__
+/*
+ * Protected nVHE HYP stack unwinder
+ *
+ * In protected mode, the unwinding is done by the hypervisor in EL2.
+ */
+
+#ifdef CONFIG_PROTECTED_NVHE_STACKTRACE
+static inline bool on_overflow_stack(unsigned long sp, unsigned long size,
+				     struct stack_info *info)
+{
+	return false;
+}
+
+static inline bool on_hyp_stack(unsigned long sp, unsigned long size,
+				struct stack_info *info)
+{
+	return false;
+}
+
+static inline int notrace unwind_next(struct unwind_state *state)
+{
+	return 0;
+}
+NOKPROBE_SYMBOL(unwind_next);
+#endif	/* CONFIG_PROTECTED_NVHE_STACKTRACE */
+
+#else	/* !__KVM_NVHE_HYPERVISOR__ */
 /*
  * Conventional (non-protected) nVHE HYP stack unwinder
  *
@@ -132,5 +163,5 @@ static inline int notrace unwind_next(struct unwind_state *state)
 }
 NOKPROBE_SYMBOL(unwind_next);
 
-#endif	/* !__KVM_NVHE_HYPERVISOR__ */
+#endif	/* __KVM_NVHE_HYPERVISOR__ */
 #endif	/* __ASM_STACKTRACE_NVHE_H */
-- 
2.37.1.359.gd136c6c3e2-goog


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 112+ messages in thread

* [PATCH v6 15/17] KVM: arm64: Save protected-nVHE (pKVM) hyp stacktrace
  2022-07-26  7:37 ` Kalesh Singh
  (?)
@ 2022-07-26  7:37   ` Kalesh Singh
  -1 siblings, 0 replies; 112+ messages in thread
From: Kalesh Singh @ 2022-07-26  7:37 UTC (permalink / raw)
  To: maz, mark.rutland, broonie, madvenka, tabba, oliver.upton
  Cc: wangkefeng.wang, catalin.marinas, ast, vincenzo.frascino, will,
	kvmarm, android-mm, kernel-team, elver, linux-arm-kernel,
	andreyknvl, linux-kernel, mhiramat

In protected nVHE mode, the host cannot access private owned hypervisor
memory. Also the hypervisor aims to remains simple to reduce the attack
surface and does not provide any printk support.

For the above reasons, the approach taken to provide hypervisor stacktraces
in protected mode is:
   1) Unwind and save the hyp stack addresses in EL2 to a shared buffer
      with the host (done in this patch).
   2) Delegate the dumping and symbolization of the addresses to the
      host in EL1 (later patch in the series).

On hyp_panic(), the hypervisor prepares the stacktrace before returning to
the host.

Signed-off-by: Kalesh Singh <kaleshsingh@google.com>
---

Changes in v6:
  - Simplify pkvm_save_backtrace_entry() using array semantics instead
    of the pointer arithmetic, per Oliver.

Changes in v5:
  - Comment/clarify pkvm_save_backtrace_entry(), per Fuad
  - kvm_nvhe_unwind_init(), doesn't need to be always inline, make it
    inline instead to avoid linking issues, per Marc
  - Use regular comments instead of doc comments, per Fuad

 arch/arm64/kvm/hyp/nvhe/stacktrace.c | 55 +++++++++++++++++++++++++++-
 1 file changed, 54 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/kvm/hyp/nvhe/stacktrace.c b/arch/arm64/kvm/hyp/nvhe/stacktrace.c
index e2edda92a108..900324b7a08f 100644
--- a/arch/arm64/kvm/hyp/nvhe/stacktrace.c
+++ b/arch/arm64/kvm/hyp/nvhe/stacktrace.c
@@ -35,7 +35,60 @@ static void hyp_prepare_backtrace(unsigned long fp, unsigned long pc)
 }
 
 #ifdef CONFIG_PROTECTED_NVHE_STACKTRACE
+#include <asm/stacktrace/nvhe.h>
+
 DEFINE_PER_CPU(unsigned long [NVHE_STACKTRACE_SIZE/sizeof(long)], pkvm_stacktrace);
+
+/*
+ * pkvm_save_backtrace_entry - Saves a protected nVHE HYP stacktrace entry
+ *
+ * @arg    : index of the entry in the stacktrace buffer
+ * @where  : the program counter corresponding to the stack frame
+ *
+ * Save the return address of a stack frame to the shared stacktrace buffer.
+ * The host can access this shared buffer from EL1 to dump the backtrace.
+ */
+static bool pkvm_save_backtrace_entry(void *arg, unsigned long where)
+{
+	unsigned long *stacktrace = this_cpu_ptr(pkvm_stacktrace);
+	int size = NVHE_STACKTRACE_SIZE / sizeof(long);
+	int *idx = (int *)arg;
+
+	/*
+	 * Need 2 free slots: 1 for current entry and 1 for the
+	 * delimiter.
+	 */
+	if (*idx > size - 2)
+		return false;
+
+	stacktrace[*idx] = where;
+	stacktrace[++*idx] = 0UL;
+
+	return true;
+}
+
+/*
+ * pkvm_save_backtrace - Saves the protected nVHE HYP stacktrace
+ *
+ * @fp : frame pointer at which to start the unwinding.
+ * @pc : program counter at which to start the unwinding.
+ *
+ * Save the unwinded stack addresses to the shared stacktrace buffer.
+ * The host can access this shared buffer from EL1 to dump the backtrace.
+ */
+static void pkvm_save_backtrace(unsigned long fp, unsigned long pc)
+{
+	struct unwind_state state;
+	int idx = 0;
+
+	kvm_nvhe_unwind_init(&state, fp, pc);
+
+	unwind(&state, pkvm_save_backtrace_entry, &idx);
+}
+#else /* !CONFIG_PROTECTED_NVHE_STACKTRACE */
+static void pkvm_save_backtrace(unsigned long fp, unsigned long pc)
+{
+}
 #endif /* CONFIG_PROTECTED_NVHE_STACKTRACE */
 
 /*
@@ -50,7 +103,7 @@ DEFINE_PER_CPU(unsigned long [NVHE_STACKTRACE_SIZE/sizeof(long)], pkvm_stacktrac
 void kvm_nvhe_prepare_backtrace(unsigned long fp, unsigned long pc)
 {
 	if (is_protected_kvm_enabled())
-		return;
+		pkvm_save_backtrace(fp, pc);
 	else
 		hyp_prepare_backtrace(fp, pc);
 }
-- 
2.37.1.359.gd136c6c3e2-goog

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply related	[flat|nested] 112+ messages in thread

* [PATCH v6 15/17] KVM: arm64: Save protected-nVHE (pKVM) hyp stacktrace
@ 2022-07-26  7:37   ` Kalesh Singh
  0 siblings, 0 replies; 112+ messages in thread
From: Kalesh Singh @ 2022-07-26  7:37 UTC (permalink / raw)
  To: maz, mark.rutland, broonie, madvenka, tabba, oliver.upton
  Cc: will, qperret, kaleshsingh, james.morse, alexandru.elisei,
	suzuki.poulose, catalin.marinas, andreyknvl, vincenzo.frascino,
	mhiramat, ast, wangkefeng.wang, elver, keirf, yuzenghui, ardb,
	oupton, linux-arm-kernel, kvmarm, linux-kernel, android-mm,
	kernel-team

In protected nVHE mode, the host cannot access private owned hypervisor
memory. Also the hypervisor aims to remains simple to reduce the attack
surface and does not provide any printk support.

For the above reasons, the approach taken to provide hypervisor stacktraces
in protected mode is:
   1) Unwind and save the hyp stack addresses in EL2 to a shared buffer
      with the host (done in this patch).
   2) Delegate the dumping and symbolization of the addresses to the
      host in EL1 (later patch in the series).

On hyp_panic(), the hypervisor prepares the stacktrace before returning to
the host.

Signed-off-by: Kalesh Singh <kaleshsingh@google.com>
---

Changes in v6:
  - Simplify pkvm_save_backtrace_entry() using array semantics instead
    of the pointer arithmetic, per Oliver.

Changes in v5:
  - Comment/clarify pkvm_save_backtrace_entry(), per Fuad
  - kvm_nvhe_unwind_init(), doesn't need to be always inline, make it
    inline instead to avoid linking issues, per Marc
  - Use regular comments instead of doc comments, per Fuad

 arch/arm64/kvm/hyp/nvhe/stacktrace.c | 55 +++++++++++++++++++++++++++-
 1 file changed, 54 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/kvm/hyp/nvhe/stacktrace.c b/arch/arm64/kvm/hyp/nvhe/stacktrace.c
index e2edda92a108..900324b7a08f 100644
--- a/arch/arm64/kvm/hyp/nvhe/stacktrace.c
+++ b/arch/arm64/kvm/hyp/nvhe/stacktrace.c
@@ -35,7 +35,60 @@ static void hyp_prepare_backtrace(unsigned long fp, unsigned long pc)
 }
 
 #ifdef CONFIG_PROTECTED_NVHE_STACKTRACE
+#include <asm/stacktrace/nvhe.h>
+
 DEFINE_PER_CPU(unsigned long [NVHE_STACKTRACE_SIZE/sizeof(long)], pkvm_stacktrace);
+
+/*
+ * pkvm_save_backtrace_entry - Saves a protected nVHE HYP stacktrace entry
+ *
+ * @arg    : index of the entry in the stacktrace buffer
+ * @where  : the program counter corresponding to the stack frame
+ *
+ * Save the return address of a stack frame to the shared stacktrace buffer.
+ * The host can access this shared buffer from EL1 to dump the backtrace.
+ */
+static bool pkvm_save_backtrace_entry(void *arg, unsigned long where)
+{
+	unsigned long *stacktrace = this_cpu_ptr(pkvm_stacktrace);
+	int size = NVHE_STACKTRACE_SIZE / sizeof(long);
+	int *idx = (int *)arg;
+
+	/*
+	 * Need 2 free slots: 1 for current entry and 1 for the
+	 * delimiter.
+	 */
+	if (*idx > size - 2)
+		return false;
+
+	stacktrace[*idx] = where;
+	stacktrace[++*idx] = 0UL;
+
+	return true;
+}
+
+/*
+ * pkvm_save_backtrace - Saves the protected nVHE HYP stacktrace
+ *
+ * @fp : frame pointer at which to start the unwinding.
+ * @pc : program counter at which to start the unwinding.
+ *
+ * Save the unwinded stack addresses to the shared stacktrace buffer.
+ * The host can access this shared buffer from EL1 to dump the backtrace.
+ */
+static void pkvm_save_backtrace(unsigned long fp, unsigned long pc)
+{
+	struct unwind_state state;
+	int idx = 0;
+
+	kvm_nvhe_unwind_init(&state, fp, pc);
+
+	unwind(&state, pkvm_save_backtrace_entry, &idx);
+}
+#else /* !CONFIG_PROTECTED_NVHE_STACKTRACE */
+static void pkvm_save_backtrace(unsigned long fp, unsigned long pc)
+{
+}
 #endif /* CONFIG_PROTECTED_NVHE_STACKTRACE */
 
 /*
@@ -50,7 +103,7 @@ DEFINE_PER_CPU(unsigned long [NVHE_STACKTRACE_SIZE/sizeof(long)], pkvm_stacktrac
 void kvm_nvhe_prepare_backtrace(unsigned long fp, unsigned long pc)
 {
 	if (is_protected_kvm_enabled())
-		return;
+		pkvm_save_backtrace(fp, pc);
 	else
 		hyp_prepare_backtrace(fp, pc);
 }
-- 
2.37.1.359.gd136c6c3e2-goog


^ permalink raw reply related	[flat|nested] 112+ messages in thread

* [PATCH v6 15/17] KVM: arm64: Save protected-nVHE (pKVM) hyp stacktrace
@ 2022-07-26  7:37   ` Kalesh Singh
  0 siblings, 0 replies; 112+ messages in thread
From: Kalesh Singh @ 2022-07-26  7:37 UTC (permalink / raw)
  To: maz, mark.rutland, broonie, madvenka, tabba, oliver.upton
  Cc: will, qperret, kaleshsingh, james.morse, alexandru.elisei,
	suzuki.poulose, catalin.marinas, andreyknvl, vincenzo.frascino,
	mhiramat, ast, wangkefeng.wang, elver, keirf, yuzenghui, ardb,
	oupton, linux-arm-kernel, kvmarm, linux-kernel, android-mm,
	kernel-team

In protected nVHE mode, the host cannot access private owned hypervisor
memory. Also the hypervisor aims to remains simple to reduce the attack
surface and does not provide any printk support.

For the above reasons, the approach taken to provide hypervisor stacktraces
in protected mode is:
   1) Unwind and save the hyp stack addresses in EL2 to a shared buffer
      with the host (done in this patch).
   2) Delegate the dumping and symbolization of the addresses to the
      host in EL1 (later patch in the series).

On hyp_panic(), the hypervisor prepares the stacktrace before returning to
the host.

Signed-off-by: Kalesh Singh <kaleshsingh@google.com>
---

Changes in v6:
  - Simplify pkvm_save_backtrace_entry() using array semantics instead
    of the pointer arithmetic, per Oliver.

Changes in v5:
  - Comment/clarify pkvm_save_backtrace_entry(), per Fuad
  - kvm_nvhe_unwind_init(), doesn't need to be always inline, make it
    inline instead to avoid linking issues, per Marc
  - Use regular comments instead of doc comments, per Fuad

 arch/arm64/kvm/hyp/nvhe/stacktrace.c | 55 +++++++++++++++++++++++++++-
 1 file changed, 54 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/kvm/hyp/nvhe/stacktrace.c b/arch/arm64/kvm/hyp/nvhe/stacktrace.c
index e2edda92a108..900324b7a08f 100644
--- a/arch/arm64/kvm/hyp/nvhe/stacktrace.c
+++ b/arch/arm64/kvm/hyp/nvhe/stacktrace.c
@@ -35,7 +35,60 @@ static void hyp_prepare_backtrace(unsigned long fp, unsigned long pc)
 }
 
 #ifdef CONFIG_PROTECTED_NVHE_STACKTRACE
+#include <asm/stacktrace/nvhe.h>
+
 DEFINE_PER_CPU(unsigned long [NVHE_STACKTRACE_SIZE/sizeof(long)], pkvm_stacktrace);
+
+/*
+ * pkvm_save_backtrace_entry - Saves a protected nVHE HYP stacktrace entry
+ *
+ * @arg    : index of the entry in the stacktrace buffer
+ * @where  : the program counter corresponding to the stack frame
+ *
+ * Save the return address of a stack frame to the shared stacktrace buffer.
+ * The host can access this shared buffer from EL1 to dump the backtrace.
+ */
+static bool pkvm_save_backtrace_entry(void *arg, unsigned long where)
+{
+	unsigned long *stacktrace = this_cpu_ptr(pkvm_stacktrace);
+	int size = NVHE_STACKTRACE_SIZE / sizeof(long);
+	int *idx = (int *)arg;
+
+	/*
+	 * Need 2 free slots: 1 for current entry and 1 for the
+	 * delimiter.
+	 */
+	if (*idx > size - 2)
+		return false;
+
+	stacktrace[*idx] = where;
+	stacktrace[++*idx] = 0UL;
+
+	return true;
+}
+
+/*
+ * pkvm_save_backtrace - Saves the protected nVHE HYP stacktrace
+ *
+ * @fp : frame pointer at which to start the unwinding.
+ * @pc : program counter at which to start the unwinding.
+ *
+ * Save the unwinded stack addresses to the shared stacktrace buffer.
+ * The host can access this shared buffer from EL1 to dump the backtrace.
+ */
+static void pkvm_save_backtrace(unsigned long fp, unsigned long pc)
+{
+	struct unwind_state state;
+	int idx = 0;
+
+	kvm_nvhe_unwind_init(&state, fp, pc);
+
+	unwind(&state, pkvm_save_backtrace_entry, &idx);
+}
+#else /* !CONFIG_PROTECTED_NVHE_STACKTRACE */
+static void pkvm_save_backtrace(unsigned long fp, unsigned long pc)
+{
+}
 #endif /* CONFIG_PROTECTED_NVHE_STACKTRACE */
 
 /*
@@ -50,7 +103,7 @@ DEFINE_PER_CPU(unsigned long [NVHE_STACKTRACE_SIZE/sizeof(long)], pkvm_stacktrac
 void kvm_nvhe_prepare_backtrace(unsigned long fp, unsigned long pc)
 {
 	if (is_protected_kvm_enabled())
-		return;
+		pkvm_save_backtrace(fp, pc);
 	else
 		hyp_prepare_backtrace(fp, pc);
 }
-- 
2.37.1.359.gd136c6c3e2-goog


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 112+ messages in thread

* [PATCH v6 16/17] KVM: arm64: Implement protected nVHE hyp stack unwinder
  2022-07-26  7:37 ` Kalesh Singh
  (?)
@ 2022-07-26  7:37   ` Kalesh Singh
  -1 siblings, 0 replies; 112+ messages in thread
From: Kalesh Singh @ 2022-07-26  7:37 UTC (permalink / raw)
  To: maz, mark.rutland, broonie, madvenka, tabba, oliver.upton
  Cc: wangkefeng.wang, catalin.marinas, ast, vincenzo.frascino, will,
	kvmarm, android-mm, kernel-team, elver, linux-arm-kernel,
	andreyknvl, linux-kernel, mhiramat

Implements the common framework necessary for unwind() to work in
the protected nVHE context:
   - on_accessible_stack()
   - on_overflow_stack()
   - unwind_next()

Protected nVHE unwind() is used to unwind and save the hyp stack
addresses to the shared stacktrace buffer. The host reads the
entries in this buffer, symbolizes and dumps the stacktrace (later
patch in the series).

Signed-off-by: Kalesh Singh <kaleshsingh@google.com>
Reviewed-by: Fuad Tabba <tabba@google.com>
Tested-by: Fuad Tabba <tabba@google.com>
---

Changes in v6:
  - Add Fuad’s Reviewed-by and Tested-by tags

 arch/arm64/include/asm/stacktrace/nvhe.h | 15 ++++++++++++---
 1 file changed, 12 insertions(+), 3 deletions(-)

diff --git a/arch/arm64/include/asm/stacktrace/nvhe.h b/arch/arm64/include/asm/stacktrace/nvhe.h
index 2ce59c058806..600dbc2220b6 100644
--- a/arch/arm64/include/asm/stacktrace/nvhe.h
+++ b/arch/arm64/include/asm/stacktrace/nvhe.h
@@ -64,18 +64,27 @@ static inline bool on_accessible_stack(const struct task_struct *tsk,
 static inline bool on_overflow_stack(unsigned long sp, unsigned long size,
 				     struct stack_info *info)
 {
-	return false;
+	unsigned long low = (unsigned long)this_cpu_ptr(overflow_stack);
+	unsigned long high = low + OVERFLOW_STACK_SIZE;
+
+	return on_stack(sp, size, low, high, STACK_TYPE_OVERFLOW, info);
 }
 
 static inline bool on_hyp_stack(unsigned long sp, unsigned long size,
 				struct stack_info *info)
 {
-	return false;
+	struct kvm_nvhe_init_params *params = this_cpu_ptr(&kvm_init_params);
+	unsigned long high = params->stack_hyp_va;
+	unsigned long low = high - PAGE_SIZE;
+
+	return on_stack(sp, size, low, high, STACK_TYPE_HYP, info);
 }
 
 static inline int notrace unwind_next(struct unwind_state *state)
 {
-	return 0;
+	struct stack_info info;
+
+	return unwind_next_common(state, &info, NULL);
 }
 NOKPROBE_SYMBOL(unwind_next);
 #endif	/* CONFIG_PROTECTED_NVHE_STACKTRACE */
-- 
2.37.1.359.gd136c6c3e2-goog

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply related	[flat|nested] 112+ messages in thread

* [PATCH v6 16/17] KVM: arm64: Implement protected nVHE hyp stack unwinder
@ 2022-07-26  7:37   ` Kalesh Singh
  0 siblings, 0 replies; 112+ messages in thread
From: Kalesh Singh @ 2022-07-26  7:37 UTC (permalink / raw)
  To: maz, mark.rutland, broonie, madvenka, tabba, oliver.upton
  Cc: will, qperret, kaleshsingh, james.morse, alexandru.elisei,
	suzuki.poulose, catalin.marinas, andreyknvl, vincenzo.frascino,
	mhiramat, ast, wangkefeng.wang, elver, keirf, yuzenghui, ardb,
	oupton, linux-arm-kernel, kvmarm, linux-kernel, android-mm,
	kernel-team

Implements the common framework necessary for unwind() to work in
the protected nVHE context:
   - on_accessible_stack()
   - on_overflow_stack()
   - unwind_next()

Protected nVHE unwind() is used to unwind and save the hyp stack
addresses to the shared stacktrace buffer. The host reads the
entries in this buffer, symbolizes and dumps the stacktrace (later
patch in the series).

Signed-off-by: Kalesh Singh <kaleshsingh@google.com>
Reviewed-by: Fuad Tabba <tabba@google.com>
Tested-by: Fuad Tabba <tabba@google.com>
---

Changes in v6:
  - Add Fuad’s Reviewed-by and Tested-by tags

 arch/arm64/include/asm/stacktrace/nvhe.h | 15 ++++++++++++---
 1 file changed, 12 insertions(+), 3 deletions(-)

diff --git a/arch/arm64/include/asm/stacktrace/nvhe.h b/arch/arm64/include/asm/stacktrace/nvhe.h
index 2ce59c058806..600dbc2220b6 100644
--- a/arch/arm64/include/asm/stacktrace/nvhe.h
+++ b/arch/arm64/include/asm/stacktrace/nvhe.h
@@ -64,18 +64,27 @@ static inline bool on_accessible_stack(const struct task_struct *tsk,
 static inline bool on_overflow_stack(unsigned long sp, unsigned long size,
 				     struct stack_info *info)
 {
-	return false;
+	unsigned long low = (unsigned long)this_cpu_ptr(overflow_stack);
+	unsigned long high = low + OVERFLOW_STACK_SIZE;
+
+	return on_stack(sp, size, low, high, STACK_TYPE_OVERFLOW, info);
 }
 
 static inline bool on_hyp_stack(unsigned long sp, unsigned long size,
 				struct stack_info *info)
 {
-	return false;
+	struct kvm_nvhe_init_params *params = this_cpu_ptr(&kvm_init_params);
+	unsigned long high = params->stack_hyp_va;
+	unsigned long low = high - PAGE_SIZE;
+
+	return on_stack(sp, size, low, high, STACK_TYPE_HYP, info);
 }
 
 static inline int notrace unwind_next(struct unwind_state *state)
 {
-	return 0;
+	struct stack_info info;
+
+	return unwind_next_common(state, &info, NULL);
 }
 NOKPROBE_SYMBOL(unwind_next);
 #endif	/* CONFIG_PROTECTED_NVHE_STACKTRACE */
-- 
2.37.1.359.gd136c6c3e2-goog


^ permalink raw reply related	[flat|nested] 112+ messages in thread

* [PATCH v6 16/17] KVM: arm64: Implement protected nVHE hyp stack unwinder
@ 2022-07-26  7:37   ` Kalesh Singh
  0 siblings, 0 replies; 112+ messages in thread
From: Kalesh Singh @ 2022-07-26  7:37 UTC (permalink / raw)
  To: maz, mark.rutland, broonie, madvenka, tabba, oliver.upton
  Cc: will, qperret, kaleshsingh, james.morse, alexandru.elisei,
	suzuki.poulose, catalin.marinas, andreyknvl, vincenzo.frascino,
	mhiramat, ast, wangkefeng.wang, elver, keirf, yuzenghui, ardb,
	oupton, linux-arm-kernel, kvmarm, linux-kernel, android-mm,
	kernel-team

Implements the common framework necessary for unwind() to work in
the protected nVHE context:
   - on_accessible_stack()
   - on_overflow_stack()
   - unwind_next()

Protected nVHE unwind() is used to unwind and save the hyp stack
addresses to the shared stacktrace buffer. The host reads the
entries in this buffer, symbolizes and dumps the stacktrace (later
patch in the series).

Signed-off-by: Kalesh Singh <kaleshsingh@google.com>
Reviewed-by: Fuad Tabba <tabba@google.com>
Tested-by: Fuad Tabba <tabba@google.com>
---

Changes in v6:
  - Add Fuad’s Reviewed-by and Tested-by tags

 arch/arm64/include/asm/stacktrace/nvhe.h | 15 ++++++++++++---
 1 file changed, 12 insertions(+), 3 deletions(-)

diff --git a/arch/arm64/include/asm/stacktrace/nvhe.h b/arch/arm64/include/asm/stacktrace/nvhe.h
index 2ce59c058806..600dbc2220b6 100644
--- a/arch/arm64/include/asm/stacktrace/nvhe.h
+++ b/arch/arm64/include/asm/stacktrace/nvhe.h
@@ -64,18 +64,27 @@ static inline bool on_accessible_stack(const struct task_struct *tsk,
 static inline bool on_overflow_stack(unsigned long sp, unsigned long size,
 				     struct stack_info *info)
 {
-	return false;
+	unsigned long low = (unsigned long)this_cpu_ptr(overflow_stack);
+	unsigned long high = low + OVERFLOW_STACK_SIZE;
+
+	return on_stack(sp, size, low, high, STACK_TYPE_OVERFLOW, info);
 }
 
 static inline bool on_hyp_stack(unsigned long sp, unsigned long size,
 				struct stack_info *info)
 {
-	return false;
+	struct kvm_nvhe_init_params *params = this_cpu_ptr(&kvm_init_params);
+	unsigned long high = params->stack_hyp_va;
+	unsigned long low = high - PAGE_SIZE;
+
+	return on_stack(sp, size, low, high, STACK_TYPE_HYP, info);
 }
 
 static inline int notrace unwind_next(struct unwind_state *state)
 {
-	return 0;
+	struct stack_info info;
+
+	return unwind_next_common(state, &info, NULL);
 }
 NOKPROBE_SYMBOL(unwind_next);
 #endif	/* CONFIG_PROTECTED_NVHE_STACKTRACE */
-- 
2.37.1.359.gd136c6c3e2-goog


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 112+ messages in thread

* [PATCH v6 17/17] KVM: arm64: Introduce pkvm_dump_backtrace()
  2022-07-26  7:37 ` Kalesh Singh
  (?)
@ 2022-07-26  7:37   ` Kalesh Singh
  -1 siblings, 0 replies; 112+ messages in thread
From: Kalesh Singh @ 2022-07-26  7:37 UTC (permalink / raw)
  To: maz, mark.rutland, broonie, madvenka, tabba, oliver.upton
  Cc: wangkefeng.wang, catalin.marinas, ast, vincenzo.frascino, will,
	kvmarm, android-mm, kernel-team, elver, linux-arm-kernel,
	andreyknvl, linux-kernel, mhiramat

Dumps the pKVM hypervisor backtrace from EL1 by reading the unwinded
addresses from the shared stacktrace buffer.

The nVHE hyp backtrace is dumped on hyp_panic(), before panicking the
host.

[  111.623091] kvm [367]: nVHE call trace:
[  111.623215] kvm [367]:  [<ffff8000090a6570>] __kvm_nvhe_hyp_panic+0xac/0xf8
[  111.623448] kvm [367]:  [<ffff8000090a65cc>] __kvm_nvhe_hyp_panic_bad_stack+0x10/0x10
[  111.623642] kvm [367]:  [<ffff8000090a61e4>] __kvm_nvhe_recursive_death+0x24/0x34
. . .
[  111.640366] kvm [367]:  [<ffff8000090a61e4>] __kvm_nvhe_recursive_death+0x24/0x34
[  111.640467] kvm [367]:  [<ffff8000090a61e4>] __kvm_nvhe_recursive_death+0x24/0x34
[  111.640574] kvm [367]:  [<ffff8000090a5de4>] __kvm_nvhe___kvm_vcpu_run+0x30/0x40c
[  111.640676] kvm [367]:  [<ffff8000090a8b64>] __kvm_nvhe_handle___kvm_vcpu_run+0x30/0x48
[  111.640778] kvm [367]:  [<ffff8000090a88b8>] __kvm_nvhe_handle_trap+0xc4/0x128
[  111.640880] kvm [367]:  [<ffff8000090a7864>] __kvm_nvhe___host_exit+0x64/0x64
[  111.640996] kvm [367]: ---[ end nVHE call trace ]---

Signed-off-by: Kalesh Singh <kaleshsingh@google.com>
---

Changes in v6:
  - And range check when dumping pkvm stacktrace, per Oliver
  - Use consistent nVHE call trace delimiters between protected and
    non-protected mode, per Oliver
  - Fix typo in comment, per Fuad

Changes in v5:
  - Move code out from nvhe.h header to handle_exit.c, per Marc
  - Fix stacktrace symbolization when CONFIG_RAMDOMIZE_BASE is enabled,
    per Fuad
  - Use regular comments instead of doc comments, per Fuad

 arch/arm64/kvm/handle_exit.c | 35 ++++++++++++++++++++++++++++++++++-
 1 file changed, 34 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/kvm/handle_exit.c b/arch/arm64/kvm/handle_exit.c
index e83e6f735100..c14fc4ba4422 100644
--- a/arch/arm64/kvm/handle_exit.c
+++ b/arch/arm64/kvm/handle_exit.c
@@ -371,6 +371,39 @@ static void hyp_dump_backtrace(unsigned long hyp_offset)
 	kvm_nvhe_dump_backtrace_end();
 }
 
+#ifdef CONFIG_PROTECTED_NVHE_STACKTRACE
+DECLARE_KVM_NVHE_PER_CPU(unsigned long [NVHE_STACKTRACE_SIZE/sizeof(long)],
+			 pkvm_stacktrace);
+
+/*
+ * pkvm_dump_backtrace - Dump the protected nVHE HYP backtrace.
+ *
+ * @hyp_offset: hypervisor offset, used for address translation.
+ *
+ * Dumping of the pKVM HYP backtrace is done by reading the
+ * stack addresses from the shared stacktrace buffer, since the
+ * host cannot directly access hypervisor memory in protected
+ * mode.
+ */
+static void pkvm_dump_backtrace(unsigned long hyp_offset)
+{
+	unsigned long *stacktrace
+		= (unsigned long *) this_cpu_ptr_nvhe_sym(pkvm_stacktrace);
+	int i, size = NVHE_STACKTRACE_SIZE / sizeof(long);
+
+	kvm_nvhe_dump_backtrace_start();
+	/* The saved stacktrace is terminated by a null entry */
+	for (i = 0; i < size && stacktrace[i]; i++)
+		kvm_nvhe_dump_backtrace_entry((void *)hyp_offset, stacktrace[i]);
+	kvm_nvhe_dump_backtrace_end();
+}
+#else	/* !CONFIG_PROTECTED_NVHE_STACKTRACE */
+static void pkvm_dump_backtrace(unsigned long hyp_offset)
+{
+	kvm_err("Cannot dump pKVM nVHE stacktrace: !CONFIG_PROTECTED_NVHE_STACKTRACE\n");
+}
+#endif /* CONFIG_PROTECTED_NVHE_STACKTRACE */
+
 /*
  * kvm_nvhe_dump_backtrace - Dump KVM nVHE hypervisor backtrace.
  *
@@ -379,7 +412,7 @@ static void hyp_dump_backtrace(unsigned long hyp_offset)
 static void kvm_nvhe_dump_backtrace(unsigned long hyp_offset)
 {
 	if (is_protected_kvm_enabled())
-		return;
+		pkvm_dump_backtrace(hyp_offset);
 	else
 		hyp_dump_backtrace(hyp_offset);
 }
-- 
2.37.1.359.gd136c6c3e2-goog

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply related	[flat|nested] 112+ messages in thread

* [PATCH v6 17/17] KVM: arm64: Introduce pkvm_dump_backtrace()
@ 2022-07-26  7:37   ` Kalesh Singh
  0 siblings, 0 replies; 112+ messages in thread
From: Kalesh Singh @ 2022-07-26  7:37 UTC (permalink / raw)
  To: maz, mark.rutland, broonie, madvenka, tabba, oliver.upton
  Cc: will, qperret, kaleshsingh, james.morse, alexandru.elisei,
	suzuki.poulose, catalin.marinas, andreyknvl, vincenzo.frascino,
	mhiramat, ast, wangkefeng.wang, elver, keirf, yuzenghui, ardb,
	oupton, linux-arm-kernel, kvmarm, linux-kernel, android-mm,
	kernel-team

Dumps the pKVM hypervisor backtrace from EL1 by reading the unwinded
addresses from the shared stacktrace buffer.

The nVHE hyp backtrace is dumped on hyp_panic(), before panicking the
host.

[  111.623091] kvm [367]: nVHE call trace:
[  111.623215] kvm [367]:  [<ffff8000090a6570>] __kvm_nvhe_hyp_panic+0xac/0xf8
[  111.623448] kvm [367]:  [<ffff8000090a65cc>] __kvm_nvhe_hyp_panic_bad_stack+0x10/0x10
[  111.623642] kvm [367]:  [<ffff8000090a61e4>] __kvm_nvhe_recursive_death+0x24/0x34
. . .
[  111.640366] kvm [367]:  [<ffff8000090a61e4>] __kvm_nvhe_recursive_death+0x24/0x34
[  111.640467] kvm [367]:  [<ffff8000090a61e4>] __kvm_nvhe_recursive_death+0x24/0x34
[  111.640574] kvm [367]:  [<ffff8000090a5de4>] __kvm_nvhe___kvm_vcpu_run+0x30/0x40c
[  111.640676] kvm [367]:  [<ffff8000090a8b64>] __kvm_nvhe_handle___kvm_vcpu_run+0x30/0x48
[  111.640778] kvm [367]:  [<ffff8000090a88b8>] __kvm_nvhe_handle_trap+0xc4/0x128
[  111.640880] kvm [367]:  [<ffff8000090a7864>] __kvm_nvhe___host_exit+0x64/0x64
[  111.640996] kvm [367]: ---[ end nVHE call trace ]---

Signed-off-by: Kalesh Singh <kaleshsingh@google.com>
---

Changes in v6:
  - And range check when dumping pkvm stacktrace, per Oliver
  - Use consistent nVHE call trace delimiters between protected and
    non-protected mode, per Oliver
  - Fix typo in comment, per Fuad

Changes in v5:
  - Move code out from nvhe.h header to handle_exit.c, per Marc
  - Fix stacktrace symbolization when CONFIG_RAMDOMIZE_BASE is enabled,
    per Fuad
  - Use regular comments instead of doc comments, per Fuad

 arch/arm64/kvm/handle_exit.c | 35 ++++++++++++++++++++++++++++++++++-
 1 file changed, 34 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/kvm/handle_exit.c b/arch/arm64/kvm/handle_exit.c
index e83e6f735100..c14fc4ba4422 100644
--- a/arch/arm64/kvm/handle_exit.c
+++ b/arch/arm64/kvm/handle_exit.c
@@ -371,6 +371,39 @@ static void hyp_dump_backtrace(unsigned long hyp_offset)
 	kvm_nvhe_dump_backtrace_end();
 }
 
+#ifdef CONFIG_PROTECTED_NVHE_STACKTRACE
+DECLARE_KVM_NVHE_PER_CPU(unsigned long [NVHE_STACKTRACE_SIZE/sizeof(long)],
+			 pkvm_stacktrace);
+
+/*
+ * pkvm_dump_backtrace - Dump the protected nVHE HYP backtrace.
+ *
+ * @hyp_offset: hypervisor offset, used for address translation.
+ *
+ * Dumping of the pKVM HYP backtrace is done by reading the
+ * stack addresses from the shared stacktrace buffer, since the
+ * host cannot directly access hypervisor memory in protected
+ * mode.
+ */
+static void pkvm_dump_backtrace(unsigned long hyp_offset)
+{
+	unsigned long *stacktrace
+		= (unsigned long *) this_cpu_ptr_nvhe_sym(pkvm_stacktrace);
+	int i, size = NVHE_STACKTRACE_SIZE / sizeof(long);
+
+	kvm_nvhe_dump_backtrace_start();
+	/* The saved stacktrace is terminated by a null entry */
+	for (i = 0; i < size && stacktrace[i]; i++)
+		kvm_nvhe_dump_backtrace_entry((void *)hyp_offset, stacktrace[i]);
+	kvm_nvhe_dump_backtrace_end();
+}
+#else	/* !CONFIG_PROTECTED_NVHE_STACKTRACE */
+static void pkvm_dump_backtrace(unsigned long hyp_offset)
+{
+	kvm_err("Cannot dump pKVM nVHE stacktrace: !CONFIG_PROTECTED_NVHE_STACKTRACE\n");
+}
+#endif /* CONFIG_PROTECTED_NVHE_STACKTRACE */
+
 /*
  * kvm_nvhe_dump_backtrace - Dump KVM nVHE hypervisor backtrace.
  *
@@ -379,7 +412,7 @@ static void hyp_dump_backtrace(unsigned long hyp_offset)
 static void kvm_nvhe_dump_backtrace(unsigned long hyp_offset)
 {
 	if (is_protected_kvm_enabled())
-		return;
+		pkvm_dump_backtrace(hyp_offset);
 	else
 		hyp_dump_backtrace(hyp_offset);
 }
-- 
2.37.1.359.gd136c6c3e2-goog


^ permalink raw reply related	[flat|nested] 112+ messages in thread

* [PATCH v6 17/17] KVM: arm64: Introduce pkvm_dump_backtrace()
@ 2022-07-26  7:37   ` Kalesh Singh
  0 siblings, 0 replies; 112+ messages in thread
From: Kalesh Singh @ 2022-07-26  7:37 UTC (permalink / raw)
  To: maz, mark.rutland, broonie, madvenka, tabba, oliver.upton
  Cc: will, qperret, kaleshsingh, james.morse, alexandru.elisei,
	suzuki.poulose, catalin.marinas, andreyknvl, vincenzo.frascino,
	mhiramat, ast, wangkefeng.wang, elver, keirf, yuzenghui, ardb,
	oupton, linux-arm-kernel, kvmarm, linux-kernel, android-mm,
	kernel-team

Dumps the pKVM hypervisor backtrace from EL1 by reading the unwinded
addresses from the shared stacktrace buffer.

The nVHE hyp backtrace is dumped on hyp_panic(), before panicking the
host.

[  111.623091] kvm [367]: nVHE call trace:
[  111.623215] kvm [367]:  [<ffff8000090a6570>] __kvm_nvhe_hyp_panic+0xac/0xf8
[  111.623448] kvm [367]:  [<ffff8000090a65cc>] __kvm_nvhe_hyp_panic_bad_stack+0x10/0x10
[  111.623642] kvm [367]:  [<ffff8000090a61e4>] __kvm_nvhe_recursive_death+0x24/0x34
. . .
[  111.640366] kvm [367]:  [<ffff8000090a61e4>] __kvm_nvhe_recursive_death+0x24/0x34
[  111.640467] kvm [367]:  [<ffff8000090a61e4>] __kvm_nvhe_recursive_death+0x24/0x34
[  111.640574] kvm [367]:  [<ffff8000090a5de4>] __kvm_nvhe___kvm_vcpu_run+0x30/0x40c
[  111.640676] kvm [367]:  [<ffff8000090a8b64>] __kvm_nvhe_handle___kvm_vcpu_run+0x30/0x48
[  111.640778] kvm [367]:  [<ffff8000090a88b8>] __kvm_nvhe_handle_trap+0xc4/0x128
[  111.640880] kvm [367]:  [<ffff8000090a7864>] __kvm_nvhe___host_exit+0x64/0x64
[  111.640996] kvm [367]: ---[ end nVHE call trace ]---

Signed-off-by: Kalesh Singh <kaleshsingh@google.com>
---

Changes in v6:
  - And range check when dumping pkvm stacktrace, per Oliver
  - Use consistent nVHE call trace delimiters between protected and
    non-protected mode, per Oliver
  - Fix typo in comment, per Fuad

Changes in v5:
  - Move code out from nvhe.h header to handle_exit.c, per Marc
  - Fix stacktrace symbolization when CONFIG_RAMDOMIZE_BASE is enabled,
    per Fuad
  - Use regular comments instead of doc comments, per Fuad

 arch/arm64/kvm/handle_exit.c | 35 ++++++++++++++++++++++++++++++++++-
 1 file changed, 34 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/kvm/handle_exit.c b/arch/arm64/kvm/handle_exit.c
index e83e6f735100..c14fc4ba4422 100644
--- a/arch/arm64/kvm/handle_exit.c
+++ b/arch/arm64/kvm/handle_exit.c
@@ -371,6 +371,39 @@ static void hyp_dump_backtrace(unsigned long hyp_offset)
 	kvm_nvhe_dump_backtrace_end();
 }
 
+#ifdef CONFIG_PROTECTED_NVHE_STACKTRACE
+DECLARE_KVM_NVHE_PER_CPU(unsigned long [NVHE_STACKTRACE_SIZE/sizeof(long)],
+			 pkvm_stacktrace);
+
+/*
+ * pkvm_dump_backtrace - Dump the protected nVHE HYP backtrace.
+ *
+ * @hyp_offset: hypervisor offset, used for address translation.
+ *
+ * Dumping of the pKVM HYP backtrace is done by reading the
+ * stack addresses from the shared stacktrace buffer, since the
+ * host cannot directly access hypervisor memory in protected
+ * mode.
+ */
+static void pkvm_dump_backtrace(unsigned long hyp_offset)
+{
+	unsigned long *stacktrace
+		= (unsigned long *) this_cpu_ptr_nvhe_sym(pkvm_stacktrace);
+	int i, size = NVHE_STACKTRACE_SIZE / sizeof(long);
+
+	kvm_nvhe_dump_backtrace_start();
+	/* The saved stacktrace is terminated by a null entry */
+	for (i = 0; i < size && stacktrace[i]; i++)
+		kvm_nvhe_dump_backtrace_entry((void *)hyp_offset, stacktrace[i]);
+	kvm_nvhe_dump_backtrace_end();
+}
+#else	/* !CONFIG_PROTECTED_NVHE_STACKTRACE */
+static void pkvm_dump_backtrace(unsigned long hyp_offset)
+{
+	kvm_err("Cannot dump pKVM nVHE stacktrace: !CONFIG_PROTECTED_NVHE_STACKTRACE\n");
+}
+#endif /* CONFIG_PROTECTED_NVHE_STACKTRACE */
+
 /*
  * kvm_nvhe_dump_backtrace - Dump KVM nVHE hypervisor backtrace.
  *
@@ -379,7 +412,7 @@ static void hyp_dump_backtrace(unsigned long hyp_offset)
 static void kvm_nvhe_dump_backtrace(unsigned long hyp_offset)
 {
 	if (is_protected_kvm_enabled())
-		return;
+		pkvm_dump_backtrace(hyp_offset);
 	else
 		hyp_dump_backtrace(hyp_offset);
 }
-- 
2.37.1.359.gd136c6c3e2-goog


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 112+ messages in thread

* Re: [PATCH v6 12/17] KVM: arm64: Add PROTECTED_NVHE_STACKTRACE Kconfig
  2022-07-26  7:37   ` Kalesh Singh
  (?)
@ 2022-07-26 10:00     ` Marc Zyngier
  -1 siblings, 0 replies; 112+ messages in thread
From: Marc Zyngier @ 2022-07-26 10:00 UTC (permalink / raw)
  To: Kalesh Singh
  Cc: mark.rutland, broonie, madvenka, tabba, oliver.upton, will,
	qperret, james.morse, alexandru.elisei, suzuki.poulose,
	catalin.marinas, andreyknvl, vincenzo.frascino, mhiramat, ast,
	wangkefeng.wang, elver, keirf, yuzenghui, ardb, oupton,
	linux-arm-kernel, kvmarm, linux-kernel, android-mm, kernel-team

On Tue, 26 Jul 2022 08:37:45 +0100,
Kalesh Singh <kaleshsingh@google.com> wrote:
> 
> This can be used to disable stacktrace for the protected KVM
> nVHE hypervisor, in order to save on the associated memory usage.
> 
> This option is disabled by default, since protected KVM is not widely
> used on platforms other than Android currently.
> 
> Signed-off-by: Kalesh Singh <kaleshsingh@google.com>
> Reviewed-by: Fuad Tabba <tabba@google.com>
> Tested-by: Fuad Tabba <tabba@google.com>
> ---
> 
> Changes in v6:
>   - Add Fuad’s Reviewed-by and Tested-by tags
> 
> Changes in v5:
>   - Make PROTECTED_NVHE_STACKTRACE depend on NVHE_EL2_DEBUG, per Marc
> 
>  arch/arm64/kvm/Kconfig | 15 +++++++++++++++
>  1 file changed, 15 insertions(+)
> 
> diff --git a/arch/arm64/kvm/Kconfig b/arch/arm64/kvm/Kconfig
> index 8a5fbbf084df..09c995869916 100644
> --- a/arch/arm64/kvm/Kconfig
> +++ b/arch/arm64/kvm/Kconfig
> @@ -46,6 +46,21 @@ menuconfig KVM
>  
>  	  If unsure, say N.
>  
> +config PROTECTED_NVHE_STACKTRACE
> +	bool "Protected KVM hypervisor stacktraces"
> +	depends on NVHE_EL2_DEBUG
> +	default n
> +	help
> +	  Say Y here to enable pKVM hypervisor stacktraces on hyp_panic()
> +
> +	  If you are not using protected nVHE (pKVM), say N.
> +
> +	  If using protected nVHE mode, but cannot afford the associated
> +	  memory cost (less than 0.75 page per CPU) of pKVM stacktraces,
> +	  say N.
> +
> +	  If unsure, say N.
> +
>  config NVHE_EL2_DEBUG
>  	bool "Debug mode for non-VHE EL2 object"
>  	depends on KVM

Having NVHE_EL2_DEBUG after PROTECTED_NVHE_STACKTRACE is pretty odd
when you use 'make menuconfig', as the new option appears out of
sequence.

I'll move it around, no need to respin for this.

Thanks,

	M.

-- 
Without deviation from the norm, progress is not possible.

^ permalink raw reply	[flat|nested] 112+ messages in thread

* Re: [PATCH v6 12/17] KVM: arm64: Add PROTECTED_NVHE_STACKTRACE Kconfig
@ 2022-07-26 10:00     ` Marc Zyngier
  0 siblings, 0 replies; 112+ messages in thread
From: Marc Zyngier @ 2022-07-26 10:00 UTC (permalink / raw)
  To: Kalesh Singh
  Cc: wangkefeng.wang, catalin.marinas, ast, vincenzo.frascino, will,
	android-mm, kvmarm, madvenka, kernel-team, elver, broonie,
	linux-arm-kernel, andreyknvl, linux-kernel, mhiramat

On Tue, 26 Jul 2022 08:37:45 +0100,
Kalesh Singh <kaleshsingh@google.com> wrote:
> 
> This can be used to disable stacktrace for the protected KVM
> nVHE hypervisor, in order to save on the associated memory usage.
> 
> This option is disabled by default, since protected KVM is not widely
> used on platforms other than Android currently.
> 
> Signed-off-by: Kalesh Singh <kaleshsingh@google.com>
> Reviewed-by: Fuad Tabba <tabba@google.com>
> Tested-by: Fuad Tabba <tabba@google.com>
> ---
> 
> Changes in v6:
>   - Add Fuad’s Reviewed-by and Tested-by tags
> 
> Changes in v5:
>   - Make PROTECTED_NVHE_STACKTRACE depend on NVHE_EL2_DEBUG, per Marc
> 
>  arch/arm64/kvm/Kconfig | 15 +++++++++++++++
>  1 file changed, 15 insertions(+)
> 
> diff --git a/arch/arm64/kvm/Kconfig b/arch/arm64/kvm/Kconfig
> index 8a5fbbf084df..09c995869916 100644
> --- a/arch/arm64/kvm/Kconfig
> +++ b/arch/arm64/kvm/Kconfig
> @@ -46,6 +46,21 @@ menuconfig KVM
>  
>  	  If unsure, say N.
>  
> +config PROTECTED_NVHE_STACKTRACE
> +	bool "Protected KVM hypervisor stacktraces"
> +	depends on NVHE_EL2_DEBUG
> +	default n
> +	help
> +	  Say Y here to enable pKVM hypervisor stacktraces on hyp_panic()
> +
> +	  If you are not using protected nVHE (pKVM), say N.
> +
> +	  If using protected nVHE mode, but cannot afford the associated
> +	  memory cost (less than 0.75 page per CPU) of pKVM stacktraces,
> +	  say N.
> +
> +	  If unsure, say N.
> +
>  config NVHE_EL2_DEBUG
>  	bool "Debug mode for non-VHE EL2 object"
>  	depends on KVM

Having NVHE_EL2_DEBUG after PROTECTED_NVHE_STACKTRACE is pretty odd
when you use 'make menuconfig', as the new option appears out of
sequence.

I'll move it around, no need to respin for this.

Thanks,

	M.

-- 
Without deviation from the norm, progress is not possible.
_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply	[flat|nested] 112+ messages in thread

* Re: [PATCH v6 12/17] KVM: arm64: Add PROTECTED_NVHE_STACKTRACE Kconfig
@ 2022-07-26 10:00     ` Marc Zyngier
  0 siblings, 0 replies; 112+ messages in thread
From: Marc Zyngier @ 2022-07-26 10:00 UTC (permalink / raw)
  To: Kalesh Singh
  Cc: mark.rutland, broonie, madvenka, tabba, oliver.upton, will,
	qperret, james.morse, alexandru.elisei, suzuki.poulose,
	catalin.marinas, andreyknvl, vincenzo.frascino, mhiramat, ast,
	wangkefeng.wang, elver, keirf, yuzenghui, ardb, oupton,
	linux-arm-kernel, kvmarm, linux-kernel, android-mm, kernel-team

On Tue, 26 Jul 2022 08:37:45 +0100,
Kalesh Singh <kaleshsingh@google.com> wrote:
> 
> This can be used to disable stacktrace for the protected KVM
> nVHE hypervisor, in order to save on the associated memory usage.
> 
> This option is disabled by default, since protected KVM is not widely
> used on platforms other than Android currently.
> 
> Signed-off-by: Kalesh Singh <kaleshsingh@google.com>
> Reviewed-by: Fuad Tabba <tabba@google.com>
> Tested-by: Fuad Tabba <tabba@google.com>
> ---
> 
> Changes in v6:
>   - Add Fuad’s Reviewed-by and Tested-by tags
> 
> Changes in v5:
>   - Make PROTECTED_NVHE_STACKTRACE depend on NVHE_EL2_DEBUG, per Marc
> 
>  arch/arm64/kvm/Kconfig | 15 +++++++++++++++
>  1 file changed, 15 insertions(+)
> 
> diff --git a/arch/arm64/kvm/Kconfig b/arch/arm64/kvm/Kconfig
> index 8a5fbbf084df..09c995869916 100644
> --- a/arch/arm64/kvm/Kconfig
> +++ b/arch/arm64/kvm/Kconfig
> @@ -46,6 +46,21 @@ menuconfig KVM
>  
>  	  If unsure, say N.
>  
> +config PROTECTED_NVHE_STACKTRACE
> +	bool "Protected KVM hypervisor stacktraces"
> +	depends on NVHE_EL2_DEBUG
> +	default n
> +	help
> +	  Say Y here to enable pKVM hypervisor stacktraces on hyp_panic()
> +
> +	  If you are not using protected nVHE (pKVM), say N.
> +
> +	  If using protected nVHE mode, but cannot afford the associated
> +	  memory cost (less than 0.75 page per CPU) of pKVM stacktraces,
> +	  say N.
> +
> +	  If unsure, say N.
> +
>  config NVHE_EL2_DEBUG
>  	bool "Debug mode for non-VHE EL2 object"
>  	depends on KVM

Having NVHE_EL2_DEBUG after PROTECTED_NVHE_STACKTRACE is pretty odd
when you use 'make menuconfig', as the new option appears out of
sequence.

I'll move it around, no need to respin for this.

Thanks,

	M.

-- 
Without deviation from the norm, progress is not possible.

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 112+ messages in thread

* Re: [PATCH v6 04/17] arm64: stacktrace: Handle frame pointer from different address spaces
  2022-07-26  7:37   ` Kalesh Singh
  (?)
@ 2022-07-26 14:34     ` Mark Brown
  -1 siblings, 0 replies; 112+ messages in thread
From: Mark Brown @ 2022-07-26 14:34 UTC (permalink / raw)
  To: Kalesh Singh
  Cc: maz, mark.rutland, madvenka, tabba, oliver.upton, will, qperret,
	james.morse, alexandru.elisei, suzuki.poulose, catalin.marinas,
	andreyknvl, vincenzo.frascino, mhiramat, ast, wangkefeng.wang,
	elver, keirf, yuzenghui, ardb, oupton, linux-arm-kernel, kvmarm,
	linux-kernel, android-mm, kernel-team

[-- Attachment #1: Type: text/plain, Size: 921 bytes --]

On Tue, Jul 26, 2022 at 12:37:37AM -0700, Kalesh Singh wrote:
> The unwinder code is made reusable so that it can be used to
> unwind various types of stacks. One usecase is unwinding the
> nVHE hyp stack from the host (EL1) in non-protected mode. This
> means that the unwinder must be able to translate HYP stack
> addresses to kernel addresses.
> 
> Add a callback (stack_trace_translate_fp_fn) to allow specifying
> the translation function.

Reviewed-by: Mark Brown <broonie@kernel.org>

with or without one very minor thing:

>  static inline int unwind_next_common(struct unwind_state *state,
> -				     struct stack_info *info)
> +				     struct stack_info *info,
> +				     stack_trace_translate_fp_fn translate_fp)
>  {
> +	unsigned long fp = state->fp, kern_fp = fp;

As a coding style nit I don't love having multiple assignments on a
single line especially as part of declarations.

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 112+ messages in thread

* Re: [PATCH v6 04/17] arm64: stacktrace: Handle frame pointer from different address spaces
@ 2022-07-26 14:34     ` Mark Brown
  0 siblings, 0 replies; 112+ messages in thread
From: Mark Brown @ 2022-07-26 14:34 UTC (permalink / raw)
  To: Kalesh Singh
  Cc: wangkefeng.wang, catalin.marinas, ast, vincenzo.frascino, will,
	android-mm, maz, kvmarm, madvenka, kernel-team, elver,
	linux-arm-kernel, andreyknvl, linux-kernel, mhiramat


[-- Attachment #1.1: Type: text/plain, Size: 921 bytes --]

On Tue, Jul 26, 2022 at 12:37:37AM -0700, Kalesh Singh wrote:
> The unwinder code is made reusable so that it can be used to
> unwind various types of stacks. One usecase is unwinding the
> nVHE hyp stack from the host (EL1) in non-protected mode. This
> means that the unwinder must be able to translate HYP stack
> addresses to kernel addresses.
> 
> Add a callback (stack_trace_translate_fp_fn) to allow specifying
> the translation function.

Reviewed-by: Mark Brown <broonie@kernel.org>

with or without one very minor thing:

>  static inline int unwind_next_common(struct unwind_state *state,
> -				     struct stack_info *info)
> +				     struct stack_info *info,
> +				     stack_trace_translate_fp_fn translate_fp)
>  {
> +	unsigned long fp = state->fp, kern_fp = fp;

As a coding style nit I don't love having multiple assignments on a
single line especially as part of declarations.

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

[-- Attachment #2: Type: text/plain, Size: 151 bytes --]

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply	[flat|nested] 112+ messages in thread

* Re: [PATCH v6 04/17] arm64: stacktrace: Handle frame pointer from different address spaces
@ 2022-07-26 14:34     ` Mark Brown
  0 siblings, 0 replies; 112+ messages in thread
From: Mark Brown @ 2022-07-26 14:34 UTC (permalink / raw)
  To: Kalesh Singh
  Cc: maz, mark.rutland, madvenka, tabba, oliver.upton, will, qperret,
	james.morse, alexandru.elisei, suzuki.poulose, catalin.marinas,
	andreyknvl, vincenzo.frascino, mhiramat, ast, wangkefeng.wang,
	elver, keirf, yuzenghui, ardb, oupton, linux-arm-kernel, kvmarm,
	linux-kernel, android-mm, kernel-team


[-- Attachment #1.1: Type: text/plain, Size: 921 bytes --]

On Tue, Jul 26, 2022 at 12:37:37AM -0700, Kalesh Singh wrote:
> The unwinder code is made reusable so that it can be used to
> unwind various types of stacks. One usecase is unwinding the
> nVHE hyp stack from the host (EL1) in non-protected mode. This
> means that the unwinder must be able to translate HYP stack
> addresses to kernel addresses.
> 
> Add a callback (stack_trace_translate_fp_fn) to allow specifying
> the translation function.

Reviewed-by: Mark Brown <broonie@kernel.org>

with or without one very minor thing:

>  static inline int unwind_next_common(struct unwind_state *state,
> -				     struct stack_info *info)
> +				     struct stack_info *info,
> +				     stack_trace_translate_fp_fn translate_fp)
>  {
> +	unsigned long fp = state->fp, kern_fp = fp;

As a coding style nit I don't love having multiple assignments on a
single line especially as part of declarations.

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

[-- Attachment #2: Type: text/plain, Size: 176 bytes --]

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 112+ messages in thread

* Re: [PATCH v6 06/17] arm64: stacktrace: Add description of stacktrace/common.h
  2022-07-26  7:37   ` Kalesh Singh
  (?)
@ 2022-07-26 14:49     ` Mark Brown
  -1 siblings, 0 replies; 112+ messages in thread
From: Mark Brown @ 2022-07-26 14:49 UTC (permalink / raw)
  To: Kalesh Singh
  Cc: maz, mark.rutland, madvenka, tabba, oliver.upton, will, qperret,
	james.morse, alexandru.elisei, suzuki.poulose, catalin.marinas,
	andreyknvl, vincenzo.frascino, mhiramat, ast, wangkefeng.wang,
	elver, keirf, yuzenghui, ardb, oupton, linux-arm-kernel, kvmarm,
	linux-kernel, android-mm, kernel-team

[-- Attachment #1: Type: text/plain, Size: 200 bytes --]

On Tue, Jul 26, 2022 at 12:37:39AM -0700, Kalesh Singh wrote:

> Add brief description on how to use stacktrace/common.h to implement
> a stack unwinder.

Reviewed-by: Mark Brown <broonie@kernel.org>

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 112+ messages in thread

* Re: [PATCH v6 06/17] arm64: stacktrace: Add description of stacktrace/common.h
@ 2022-07-26 14:49     ` Mark Brown
  0 siblings, 0 replies; 112+ messages in thread
From: Mark Brown @ 2022-07-26 14:49 UTC (permalink / raw)
  To: Kalesh Singh
  Cc: wangkefeng.wang, catalin.marinas, ast, vincenzo.frascino, will,
	android-mm, maz, kvmarm, madvenka, kernel-team, elver,
	linux-arm-kernel, andreyknvl, linux-kernel, mhiramat


[-- Attachment #1.1: Type: text/plain, Size: 200 bytes --]

On Tue, Jul 26, 2022 at 12:37:39AM -0700, Kalesh Singh wrote:

> Add brief description on how to use stacktrace/common.h to implement
> a stack unwinder.

Reviewed-by: Mark Brown <broonie@kernel.org>

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

[-- Attachment #2: Type: text/plain, Size: 151 bytes --]

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply	[flat|nested] 112+ messages in thread

* Re: [PATCH v6 06/17] arm64: stacktrace: Add description of stacktrace/common.h
@ 2022-07-26 14:49     ` Mark Brown
  0 siblings, 0 replies; 112+ messages in thread
From: Mark Brown @ 2022-07-26 14:49 UTC (permalink / raw)
  To: Kalesh Singh
  Cc: maz, mark.rutland, madvenka, tabba, oliver.upton, will, qperret,
	james.morse, alexandru.elisei, suzuki.poulose, catalin.marinas,
	andreyknvl, vincenzo.frascino, mhiramat, ast, wangkefeng.wang,
	elver, keirf, yuzenghui, ardb, oupton, linux-arm-kernel, kvmarm,
	linux-kernel, android-mm, kernel-team


[-- Attachment #1.1: Type: text/plain, Size: 200 bytes --]

On Tue, Jul 26, 2022 at 12:37:39AM -0700, Kalesh Singh wrote:

> Add brief description on how to use stacktrace/common.h to implement
> a stack unwinder.

Reviewed-by: Mark Brown <broonie@kernel.org>

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

[-- Attachment #2: Type: text/plain, Size: 176 bytes --]

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 112+ messages in thread

* Re: [PATCH v6 04/17] arm64: stacktrace: Handle frame pointer from different address spaces
  2022-07-26 14:34     ` Mark Brown
  (?)
@ 2022-07-26 15:30       ` Kalesh Singh
  -1 siblings, 0 replies; 112+ messages in thread
From: Kalesh Singh @ 2022-07-26 15:30 UTC (permalink / raw)
  To: Mark Brown
  Cc: Marc Zyngier, Mark Rutland, Madhavan T. Venkataraman, Fuad Tabba,
	Oliver Upton, Will Deacon, Quentin Perret, James Morse,
	Alexandru Elisei, Suzuki K Poulose, Catalin Marinas, andreyknvl,
	vincenzo.frascino, Masami Hiramatsu, Alexei Starovoitov,
	Kefeng Wang, Marco Elver, Keir Fraser, Zenghui Yu,
	Ard Biesheuvel, Oliver Upton,
	moderated list:ARM64 PORT (AARCH64 ARCHITECTURE),
	kvmarm, LKML, android-mm, Cc: Android Kernel

On Tue, Jul 26, 2022 at 7:34 AM Mark Brown <broonie@kernel.org> wrote:
>
> On Tue, Jul 26, 2022 at 12:37:37AM -0700, Kalesh Singh wrote:
> > The unwinder code is made reusable so that it can be used to
> > unwind various types of stacks. One usecase is unwinding the
> > nVHE hyp stack from the host (EL1) in non-protected mode. This
> > means that the unwinder must be able to translate HYP stack
> > addresses to kernel addresses.
> >
> > Add a callback (stack_trace_translate_fp_fn) to allow specifying
> > the translation function.
>
> Reviewed-by: Mark Brown <broonie@kernel.org>
>
> with or without one very minor thing:
>
> >  static inline int unwind_next_common(struct unwind_state *state,
> > -                                  struct stack_info *info)
> > +                                  struct stack_info *info,
> > +                                  stack_trace_translate_fp_fn translate_fp)
> >  {
> > +     unsigned long fp = state->fp, kern_fp = fp;
>
> As a coding style nit I don't love having multiple assignments on a
> single line especially as part of declarations.

Hi Mark,

Thanks for the reviews. I'll update this if a respin is needed.

--Kalesh

^ permalink raw reply	[flat|nested] 112+ messages in thread

* Re: [PATCH v6 04/17] arm64: stacktrace: Handle frame pointer from different address spaces
@ 2022-07-26 15:30       ` Kalesh Singh
  0 siblings, 0 replies; 112+ messages in thread
From: Kalesh Singh @ 2022-07-26 15:30 UTC (permalink / raw)
  To: Mark Brown
  Cc: Kefeng Wang, Catalin Marinas, Alexei Starovoitov,
	vincenzo.frascino, Will Deacon, android-mm, Marc Zyngier, kvmarm,
	Madhavan T. Venkataraman, Cc: Android Kernel, Marco Elver,
	moderated list:ARM64 PORT (AARCH64 ARCHITECTURE),
	andreyknvl, LKML, Masami Hiramatsu

On Tue, Jul 26, 2022 at 7:34 AM Mark Brown <broonie@kernel.org> wrote:
>
> On Tue, Jul 26, 2022 at 12:37:37AM -0700, Kalesh Singh wrote:
> > The unwinder code is made reusable so that it can be used to
> > unwind various types of stacks. One usecase is unwinding the
> > nVHE hyp stack from the host (EL1) in non-protected mode. This
> > means that the unwinder must be able to translate HYP stack
> > addresses to kernel addresses.
> >
> > Add a callback (stack_trace_translate_fp_fn) to allow specifying
> > the translation function.
>
> Reviewed-by: Mark Brown <broonie@kernel.org>
>
> with or without one very minor thing:
>
> >  static inline int unwind_next_common(struct unwind_state *state,
> > -                                  struct stack_info *info)
> > +                                  struct stack_info *info,
> > +                                  stack_trace_translate_fp_fn translate_fp)
> >  {
> > +     unsigned long fp = state->fp, kern_fp = fp;
>
> As a coding style nit I don't love having multiple assignments on a
> single line especially as part of declarations.

Hi Mark,

Thanks for the reviews. I'll update this if a respin is needed.

--Kalesh
_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply	[flat|nested] 112+ messages in thread

* Re: [PATCH v6 04/17] arm64: stacktrace: Handle frame pointer from different address spaces
@ 2022-07-26 15:30       ` Kalesh Singh
  0 siblings, 0 replies; 112+ messages in thread
From: Kalesh Singh @ 2022-07-26 15:30 UTC (permalink / raw)
  To: Mark Brown
  Cc: Marc Zyngier, Mark Rutland, Madhavan T. Venkataraman, Fuad Tabba,
	Oliver Upton, Will Deacon, Quentin Perret, James Morse,
	Alexandru Elisei, Suzuki K Poulose, Catalin Marinas, andreyknvl,
	vincenzo.frascino, Masami Hiramatsu, Alexei Starovoitov,
	Kefeng Wang, Marco Elver, Keir Fraser, Zenghui Yu,
	Ard Biesheuvel, Oliver Upton,
	moderated list:ARM64 PORT (AARCH64 ARCHITECTURE),
	kvmarm, LKML, android-mm, Cc: Android Kernel

On Tue, Jul 26, 2022 at 7:34 AM Mark Brown <broonie@kernel.org> wrote:
>
> On Tue, Jul 26, 2022 at 12:37:37AM -0700, Kalesh Singh wrote:
> > The unwinder code is made reusable so that it can be used to
> > unwind various types of stacks. One usecase is unwinding the
> > nVHE hyp stack from the host (EL1) in non-protected mode. This
> > means that the unwinder must be able to translate HYP stack
> > addresses to kernel addresses.
> >
> > Add a callback (stack_trace_translate_fp_fn) to allow specifying
> > the translation function.
>
> Reviewed-by: Mark Brown <broonie@kernel.org>
>
> with or without one very minor thing:
>
> >  static inline int unwind_next_common(struct unwind_state *state,
> > -                                  struct stack_info *info)
> > +                                  struct stack_info *info,
> > +                                  stack_trace_translate_fp_fn translate_fp)
> >  {
> > +     unsigned long fp = state->fp, kern_fp = fp;
>
> As a coding style nit I don't love having multiple assignments on a
> single line especially as part of declarations.

Hi Mark,

Thanks for the reviews. I'll update this if a respin is needed.

--Kalesh

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 112+ messages in thread

* Re: [PATCH v6 12/17] KVM: arm64: Add PROTECTED_NVHE_STACKTRACE Kconfig
  2022-07-26 10:00     ` Marc Zyngier
  (?)
@ 2022-07-26 15:33       ` Kalesh Singh
  -1 siblings, 0 replies; 112+ messages in thread
From: Kalesh Singh @ 2022-07-26 15:33 UTC (permalink / raw)
  To: Marc Zyngier
  Cc: Mark Rutland, Mark Brown, Madhavan T. Venkataraman, Fuad Tabba,
	Oliver Upton, Will Deacon, Quentin Perret, James Morse,
	Alexandru Elisei, Suzuki K Poulose, Catalin Marinas, andreyknvl,
	vincenzo.frascino, Masami Hiramatsu, Alexei Starovoitov,
	Kefeng Wang, Marco Elver, Keir Fraser, Zenghui Yu,
	Ard Biesheuvel, Oliver Upton,
	moderated list:ARM64 PORT (AARCH64 ARCHITECTURE),
	kvmarm, LKML, android-mm, Cc: Android Kernel

On Tue, Jul 26, 2022 at 3:00 AM Marc Zyngier <maz@kernel.org> wrote:
>
> On Tue, 26 Jul 2022 08:37:45 +0100,
> Kalesh Singh <kaleshsingh@google.com> wrote:
> >
> > This can be used to disable stacktrace for the protected KVM
> > nVHE hypervisor, in order to save on the associated memory usage.
> >
> > This option is disabled by default, since protected KVM is not widely
> > used on platforms other than Android currently.
> >
> > Signed-off-by: Kalesh Singh <kaleshsingh@google.com>
> > Reviewed-by: Fuad Tabba <tabba@google.com>
> > Tested-by: Fuad Tabba <tabba@google.com>
> > ---
> >
> > Changes in v6:
> >   - Add Fuad’s Reviewed-by and Tested-by tags
> >

> > Changes in v5:
> >   - Make PROTECTED_NVHE_STACKTRACE depend on NVHE_EL2_DEBUG, per Marc
> >
> >  arch/arm64/kvm/Kconfig | 15 +++++++++++++++
> >  1 file changed, 15 insertions(+)
> >
> > diff --git a/arch/arm64/kvm/Kconfig b/arch/arm64/kvm/Kconfig
> > index 8a5fbbf084df..09c995869916 100644
> > --- a/arch/arm64/kvm/Kconfig
> > +++ b/arch/arm64/kvm/Kconfig
> > @@ -46,6 +46,21 @@ menuconfig KVM
> >
> >         If unsure, say N.
> >
> > +config PROTECTED_NVHE_STACKTRACE
> > +     bool "Protected KVM hypervisor stacktraces"
> > +     depends on NVHE_EL2_DEBUG
> > +     default n
> > +     help
> > +       Say Y here to enable pKVM hypervisor stacktraces on hyp_panic()
> > +
> > +       If you are not using protected nVHE (pKVM), say N.
> > +
> > +       If using protected nVHE mode, but cannot afford the associated
> > +       memory cost (less than 0.75 page per CPU) of pKVM stacktraces,
> > +       say N.
> > +
> > +       If unsure, say N.
> > +
> >  config NVHE_EL2_DEBUG
> >       bool "Debug mode for non-VHE EL2 object"
> >       depends on KVM
>
> Having NVHE_EL2_DEBUG after PROTECTED_NVHE_STACKTRACE is pretty odd
> when you use 'make menuconfig', as the new option appears out of
> sequence.

Ahh good catch. Should have moved it when the dependency got changed.

>
> I'll move it around, no need to respin for this.
>

Thanks Marc.


> Thanks,
>
>         M.
>
> --
> Without deviation from the norm, progress is not possible.

^ permalink raw reply	[flat|nested] 112+ messages in thread

* Re: [PATCH v6 12/17] KVM: arm64: Add PROTECTED_NVHE_STACKTRACE Kconfig
@ 2022-07-26 15:33       ` Kalesh Singh
  0 siblings, 0 replies; 112+ messages in thread
From: Kalesh Singh @ 2022-07-26 15:33 UTC (permalink / raw)
  To: Marc Zyngier
  Cc: Kefeng Wang, Catalin Marinas, Alexei Starovoitov,
	vincenzo.frascino, Will Deacon, android-mm, kvmarm,
	Madhavan T. Venkataraman, Cc: Android Kernel, Marco Elver,
	Mark Brown, moderated list:ARM64 PORT (AARCH64 ARCHITECTURE),
	andreyknvl, LKML, Masami Hiramatsu

On Tue, Jul 26, 2022 at 3:00 AM Marc Zyngier <maz@kernel.org> wrote:
>
> On Tue, 26 Jul 2022 08:37:45 +0100,
> Kalesh Singh <kaleshsingh@google.com> wrote:
> >
> > This can be used to disable stacktrace for the protected KVM
> > nVHE hypervisor, in order to save on the associated memory usage.
> >
> > This option is disabled by default, since protected KVM is not widely
> > used on platforms other than Android currently.
> >
> > Signed-off-by: Kalesh Singh <kaleshsingh@google.com>
> > Reviewed-by: Fuad Tabba <tabba@google.com>
> > Tested-by: Fuad Tabba <tabba@google.com>
> > ---
> >
> > Changes in v6:
> >   - Add Fuad’s Reviewed-by and Tested-by tags
> >

> > Changes in v5:
> >   - Make PROTECTED_NVHE_STACKTRACE depend on NVHE_EL2_DEBUG, per Marc
> >
> >  arch/arm64/kvm/Kconfig | 15 +++++++++++++++
> >  1 file changed, 15 insertions(+)
> >
> > diff --git a/arch/arm64/kvm/Kconfig b/arch/arm64/kvm/Kconfig
> > index 8a5fbbf084df..09c995869916 100644
> > --- a/arch/arm64/kvm/Kconfig
> > +++ b/arch/arm64/kvm/Kconfig
> > @@ -46,6 +46,21 @@ menuconfig KVM
> >
> >         If unsure, say N.
> >
> > +config PROTECTED_NVHE_STACKTRACE
> > +     bool "Protected KVM hypervisor stacktraces"
> > +     depends on NVHE_EL2_DEBUG
> > +     default n
> > +     help
> > +       Say Y here to enable pKVM hypervisor stacktraces on hyp_panic()
> > +
> > +       If you are not using protected nVHE (pKVM), say N.
> > +
> > +       If using protected nVHE mode, but cannot afford the associated
> > +       memory cost (less than 0.75 page per CPU) of pKVM stacktraces,
> > +       say N.
> > +
> > +       If unsure, say N.
> > +
> >  config NVHE_EL2_DEBUG
> >       bool "Debug mode for non-VHE EL2 object"
> >       depends on KVM
>
> Having NVHE_EL2_DEBUG after PROTECTED_NVHE_STACKTRACE is pretty odd
> when you use 'make menuconfig', as the new option appears out of
> sequence.

Ahh good catch. Should have moved it when the dependency got changed.

>
> I'll move it around, no need to respin for this.
>

Thanks Marc.


> Thanks,
>
>         M.
>
> --
> Without deviation from the norm, progress is not possible.
_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply	[flat|nested] 112+ messages in thread

* Re: [PATCH v6 12/17] KVM: arm64: Add PROTECTED_NVHE_STACKTRACE Kconfig
@ 2022-07-26 15:33       ` Kalesh Singh
  0 siblings, 0 replies; 112+ messages in thread
From: Kalesh Singh @ 2022-07-26 15:33 UTC (permalink / raw)
  To: Marc Zyngier
  Cc: Mark Rutland, Mark Brown, Madhavan T. Venkataraman, Fuad Tabba,
	Oliver Upton, Will Deacon, Quentin Perret, James Morse,
	Alexandru Elisei, Suzuki K Poulose, Catalin Marinas, andreyknvl,
	vincenzo.frascino, Masami Hiramatsu, Alexei Starovoitov,
	Kefeng Wang, Marco Elver, Keir Fraser, Zenghui Yu,
	Ard Biesheuvel, Oliver Upton,
	moderated list:ARM64 PORT (AARCH64 ARCHITECTURE),
	kvmarm, LKML, android-mm, Cc: Android Kernel

On Tue, Jul 26, 2022 at 3:00 AM Marc Zyngier <maz@kernel.org> wrote:
>
> On Tue, 26 Jul 2022 08:37:45 +0100,
> Kalesh Singh <kaleshsingh@google.com> wrote:
> >
> > This can be used to disable stacktrace for the protected KVM
> > nVHE hypervisor, in order to save on the associated memory usage.
> >
> > This option is disabled by default, since protected KVM is not widely
> > used on platforms other than Android currently.
> >
> > Signed-off-by: Kalesh Singh <kaleshsingh@google.com>
> > Reviewed-by: Fuad Tabba <tabba@google.com>
> > Tested-by: Fuad Tabba <tabba@google.com>
> > ---
> >
> > Changes in v6:
> >   - Add Fuad’s Reviewed-by and Tested-by tags
> >

> > Changes in v5:
> >   - Make PROTECTED_NVHE_STACKTRACE depend on NVHE_EL2_DEBUG, per Marc
> >
> >  arch/arm64/kvm/Kconfig | 15 +++++++++++++++
> >  1 file changed, 15 insertions(+)
> >
> > diff --git a/arch/arm64/kvm/Kconfig b/arch/arm64/kvm/Kconfig
> > index 8a5fbbf084df..09c995869916 100644
> > --- a/arch/arm64/kvm/Kconfig
> > +++ b/arch/arm64/kvm/Kconfig
> > @@ -46,6 +46,21 @@ menuconfig KVM
> >
> >         If unsure, say N.
> >
> > +config PROTECTED_NVHE_STACKTRACE
> > +     bool "Protected KVM hypervisor stacktraces"
> > +     depends on NVHE_EL2_DEBUG
> > +     default n
> > +     help
> > +       Say Y here to enable pKVM hypervisor stacktraces on hyp_panic()
> > +
> > +       If you are not using protected nVHE (pKVM), say N.
> > +
> > +       If using protected nVHE mode, but cannot afford the associated
> > +       memory cost (less than 0.75 page per CPU) of pKVM stacktraces,
> > +       say N.
> > +
> > +       If unsure, say N.
> > +
> >  config NVHE_EL2_DEBUG
> >       bool "Debug mode for non-VHE EL2 object"
> >       depends on KVM
>
> Having NVHE_EL2_DEBUG after PROTECTED_NVHE_STACKTRACE is pretty odd
> when you use 'make menuconfig', as the new option appears out of
> sequence.

Ahh good catch. Should have moved it when the dependency got changed.

>
> I'll move it around, no need to respin for this.
>

Thanks Marc.


> Thanks,
>
>         M.
>
> --
> Without deviation from the norm, progress is not possible.

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 112+ messages in thread

* Re: [PATCH v6 02/17] arm64: stacktrace: Factor out on_accessible_stack_common()
  2022-07-26  7:37   ` Kalesh Singh
  (?)
@ 2022-07-26 16:01     ` Marc Zyngier
  -1 siblings, 0 replies; 112+ messages in thread
From: Marc Zyngier @ 2022-07-26 16:01 UTC (permalink / raw)
  To: Kalesh Singh
  Cc: mark.rutland, broonie, madvenka, tabba, oliver.upton, will,
	qperret, james.morse, alexandru.elisei, suzuki.poulose,
	catalin.marinas, andreyknvl, vincenzo.frascino, mhiramat, ast,
	wangkefeng.wang, elver, keirf, yuzenghui, ardb, oupton,
	linux-arm-kernel, kvmarm, linux-kernel, android-mm, kernel-team

On Tue, 26 Jul 2022 08:37:35 +0100,
Kalesh Singh <kaleshsingh@google.com> wrote:
> 
> Move common on_accessible_stack checks to stacktrace/common.h. This is
> used in the implementation of the nVHE hypervisor unwinder later in
> this series.
> 
> Signed-off-by: Kalesh Singh <kaleshsingh@google.com>
> Reviewed-by: Fuad Tabba <tabba@google.com>
> Reviewed-by: Mark Brown <broonie@kernel.org>
> Tested-by: Fuad Tabba <tabba@google.com>
> ---
> 
> Changes in v6:
>   - Add Fuad's Tested-by tag
> 
> Changes in v5:
>   - Add Reviewed-by tags from Mark Brown and Fuad
>   - Remove random whitespace change, per Mark Brown
> 
>  arch/arm64/include/asm/stacktrace.h        |  6 ++----
>  arch/arm64/include/asm/stacktrace/common.h | 18 ++++++++++++++++++
>  2 files changed, 20 insertions(+), 4 deletions(-)
> 
> diff --git a/arch/arm64/include/asm/stacktrace.h b/arch/arm64/include/asm/stacktrace.h
> index 79f455b37c84..43f4b4a6d383 100644
> --- a/arch/arm64/include/asm/stacktrace.h
> +++ b/arch/arm64/include/asm/stacktrace.h
> @@ -65,8 +65,8 @@ static inline bool on_accessible_stack(const struct task_struct *tsk,
>  				       unsigned long sp, unsigned long size,
>  				       struct stack_info *info)
>  {
> -	if (info)
> -		info->type = STACK_TYPE_UNKNOWN;
> +	if (on_accessible_stack_common(tsk, sp, size, info))
> +		return true;
>  
>  	if (on_task_stack(tsk, sp, size, info))
>  		return true;
> @@ -74,8 +74,6 @@ static inline bool on_accessible_stack(const struct task_struct *tsk,
>  		return false;
>  	if (on_irq_stack(sp, size, info))
>  		return true;
> -	if (on_overflow_stack(sp, size, info))
> -		return true;
>  	if (on_sdei_stack(sp, size, info))
>  		return true;
>  
> diff --git a/arch/arm64/include/asm/stacktrace/common.h b/arch/arm64/include/asm/stacktrace/common.h
> index 64ae4f6b06fe..f58b786460d3 100644
> --- a/arch/arm64/include/asm/stacktrace/common.h
> +++ b/arch/arm64/include/asm/stacktrace/common.h
> @@ -62,6 +62,9 @@ struct unwind_state {
>  	struct task_struct *task;
>  };
>  
> +static inline bool on_overflow_stack(unsigned long sp, unsigned long size,
> +				     struct stack_info *info);
> +
>  static inline bool on_stack(unsigned long sp, unsigned long size,
>  			    unsigned long low, unsigned long high,
>  			    enum stack_type type, struct stack_info *info)
> @@ -80,6 +83,21 @@ static inline bool on_stack(unsigned long sp, unsigned long size,
>  	return true;
>  }
>  
> +static inline bool on_accessible_stack_common(const struct task_struct *tsk,
> +					      unsigned long sp,
> +					      unsigned long size,
> +					      struct stack_info *info)
> +{
> +	if (info)
> +		info->type = STACK_TYPE_UNKNOWN;
> +
> +	/*
> +	 * Both the kernel and nvhe hypervisor make use of
> +	 * an overflow_stack
> +	 */
> +	return on_overflow_stack(sp, size, info);
> +}

on_accessible_stack has the following comment:

/*
 * We can only safely access per-cpu stacks from current in a non-preemptible
 * context.
 */

With this change, I don't think we satisfy this requirement anymore,
as we're checking the overflow stack *before* the preemptible check,
which is a big change in behaviour.

The hypervisor doesn't have this requirement: the unwinding is either
done out of context (nVHE, where EL1 unwinds EL2) or in a
non-preemptible section (pKVM, where the whole thing is
non-preemptible). But the kernel is usually preemptible, so this patch
needs fixing.

I'll see if I can address it locally (I'm currently moving things
around, stay tuned).

Thanks,

	M.

-- 
Without deviation from the norm, progress is not possible.

^ permalink raw reply	[flat|nested] 112+ messages in thread

* Re: [PATCH v6 02/17] arm64: stacktrace: Factor out on_accessible_stack_common()
@ 2022-07-26 16:01     ` Marc Zyngier
  0 siblings, 0 replies; 112+ messages in thread
From: Marc Zyngier @ 2022-07-26 16:01 UTC (permalink / raw)
  To: Kalesh Singh
  Cc: wangkefeng.wang, catalin.marinas, ast, vincenzo.frascino, will,
	android-mm, kvmarm, madvenka, kernel-team, elver, broonie,
	linux-arm-kernel, andreyknvl, linux-kernel, mhiramat

On Tue, 26 Jul 2022 08:37:35 +0100,
Kalesh Singh <kaleshsingh@google.com> wrote:
> 
> Move common on_accessible_stack checks to stacktrace/common.h. This is
> used in the implementation of the nVHE hypervisor unwinder later in
> this series.
> 
> Signed-off-by: Kalesh Singh <kaleshsingh@google.com>
> Reviewed-by: Fuad Tabba <tabba@google.com>
> Reviewed-by: Mark Brown <broonie@kernel.org>
> Tested-by: Fuad Tabba <tabba@google.com>
> ---
> 
> Changes in v6:
>   - Add Fuad's Tested-by tag
> 
> Changes in v5:
>   - Add Reviewed-by tags from Mark Brown and Fuad
>   - Remove random whitespace change, per Mark Brown
> 
>  arch/arm64/include/asm/stacktrace.h        |  6 ++----
>  arch/arm64/include/asm/stacktrace/common.h | 18 ++++++++++++++++++
>  2 files changed, 20 insertions(+), 4 deletions(-)
> 
> diff --git a/arch/arm64/include/asm/stacktrace.h b/arch/arm64/include/asm/stacktrace.h
> index 79f455b37c84..43f4b4a6d383 100644
> --- a/arch/arm64/include/asm/stacktrace.h
> +++ b/arch/arm64/include/asm/stacktrace.h
> @@ -65,8 +65,8 @@ static inline bool on_accessible_stack(const struct task_struct *tsk,
>  				       unsigned long sp, unsigned long size,
>  				       struct stack_info *info)
>  {
> -	if (info)
> -		info->type = STACK_TYPE_UNKNOWN;
> +	if (on_accessible_stack_common(tsk, sp, size, info))
> +		return true;
>  
>  	if (on_task_stack(tsk, sp, size, info))
>  		return true;
> @@ -74,8 +74,6 @@ static inline bool on_accessible_stack(const struct task_struct *tsk,
>  		return false;
>  	if (on_irq_stack(sp, size, info))
>  		return true;
> -	if (on_overflow_stack(sp, size, info))
> -		return true;
>  	if (on_sdei_stack(sp, size, info))
>  		return true;
>  
> diff --git a/arch/arm64/include/asm/stacktrace/common.h b/arch/arm64/include/asm/stacktrace/common.h
> index 64ae4f6b06fe..f58b786460d3 100644
> --- a/arch/arm64/include/asm/stacktrace/common.h
> +++ b/arch/arm64/include/asm/stacktrace/common.h
> @@ -62,6 +62,9 @@ struct unwind_state {
>  	struct task_struct *task;
>  };
>  
> +static inline bool on_overflow_stack(unsigned long sp, unsigned long size,
> +				     struct stack_info *info);
> +
>  static inline bool on_stack(unsigned long sp, unsigned long size,
>  			    unsigned long low, unsigned long high,
>  			    enum stack_type type, struct stack_info *info)
> @@ -80,6 +83,21 @@ static inline bool on_stack(unsigned long sp, unsigned long size,
>  	return true;
>  }
>  
> +static inline bool on_accessible_stack_common(const struct task_struct *tsk,
> +					      unsigned long sp,
> +					      unsigned long size,
> +					      struct stack_info *info)
> +{
> +	if (info)
> +		info->type = STACK_TYPE_UNKNOWN;
> +
> +	/*
> +	 * Both the kernel and nvhe hypervisor make use of
> +	 * an overflow_stack
> +	 */
> +	return on_overflow_stack(sp, size, info);
> +}

on_accessible_stack has the following comment:

/*
 * We can only safely access per-cpu stacks from current in a non-preemptible
 * context.
 */

With this change, I don't think we satisfy this requirement anymore,
as we're checking the overflow stack *before* the preemptible check,
which is a big change in behaviour.

The hypervisor doesn't have this requirement: the unwinding is either
done out of context (nVHE, where EL1 unwinds EL2) or in a
non-preemptible section (pKVM, where the whole thing is
non-preemptible). But the kernel is usually preemptible, so this patch
needs fixing.

I'll see if I can address it locally (I'm currently moving things
around, stay tuned).

Thanks,

	M.

-- 
Without deviation from the norm, progress is not possible.
_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply	[flat|nested] 112+ messages in thread

* Re: [PATCH v6 02/17] arm64: stacktrace: Factor out on_accessible_stack_common()
@ 2022-07-26 16:01     ` Marc Zyngier
  0 siblings, 0 replies; 112+ messages in thread
From: Marc Zyngier @ 2022-07-26 16:01 UTC (permalink / raw)
  To: Kalesh Singh
  Cc: mark.rutland, broonie, madvenka, tabba, oliver.upton, will,
	qperret, james.morse, alexandru.elisei, suzuki.poulose,
	catalin.marinas, andreyknvl, vincenzo.frascino, mhiramat, ast,
	wangkefeng.wang, elver, keirf, yuzenghui, ardb, oupton,
	linux-arm-kernel, kvmarm, linux-kernel, android-mm, kernel-team

On Tue, 26 Jul 2022 08:37:35 +0100,
Kalesh Singh <kaleshsingh@google.com> wrote:
> 
> Move common on_accessible_stack checks to stacktrace/common.h. This is
> used in the implementation of the nVHE hypervisor unwinder later in
> this series.
> 
> Signed-off-by: Kalesh Singh <kaleshsingh@google.com>
> Reviewed-by: Fuad Tabba <tabba@google.com>
> Reviewed-by: Mark Brown <broonie@kernel.org>
> Tested-by: Fuad Tabba <tabba@google.com>
> ---
> 
> Changes in v6:
>   - Add Fuad's Tested-by tag
> 
> Changes in v5:
>   - Add Reviewed-by tags from Mark Brown and Fuad
>   - Remove random whitespace change, per Mark Brown
> 
>  arch/arm64/include/asm/stacktrace.h        |  6 ++----
>  arch/arm64/include/asm/stacktrace/common.h | 18 ++++++++++++++++++
>  2 files changed, 20 insertions(+), 4 deletions(-)
> 
> diff --git a/arch/arm64/include/asm/stacktrace.h b/arch/arm64/include/asm/stacktrace.h
> index 79f455b37c84..43f4b4a6d383 100644
> --- a/arch/arm64/include/asm/stacktrace.h
> +++ b/arch/arm64/include/asm/stacktrace.h
> @@ -65,8 +65,8 @@ static inline bool on_accessible_stack(const struct task_struct *tsk,
>  				       unsigned long sp, unsigned long size,
>  				       struct stack_info *info)
>  {
> -	if (info)
> -		info->type = STACK_TYPE_UNKNOWN;
> +	if (on_accessible_stack_common(tsk, sp, size, info))
> +		return true;
>  
>  	if (on_task_stack(tsk, sp, size, info))
>  		return true;
> @@ -74,8 +74,6 @@ static inline bool on_accessible_stack(const struct task_struct *tsk,
>  		return false;
>  	if (on_irq_stack(sp, size, info))
>  		return true;
> -	if (on_overflow_stack(sp, size, info))
> -		return true;
>  	if (on_sdei_stack(sp, size, info))
>  		return true;
>  
> diff --git a/arch/arm64/include/asm/stacktrace/common.h b/arch/arm64/include/asm/stacktrace/common.h
> index 64ae4f6b06fe..f58b786460d3 100644
> --- a/arch/arm64/include/asm/stacktrace/common.h
> +++ b/arch/arm64/include/asm/stacktrace/common.h
> @@ -62,6 +62,9 @@ struct unwind_state {
>  	struct task_struct *task;
>  };
>  
> +static inline bool on_overflow_stack(unsigned long sp, unsigned long size,
> +				     struct stack_info *info);
> +
>  static inline bool on_stack(unsigned long sp, unsigned long size,
>  			    unsigned long low, unsigned long high,
>  			    enum stack_type type, struct stack_info *info)
> @@ -80,6 +83,21 @@ static inline bool on_stack(unsigned long sp, unsigned long size,
>  	return true;
>  }
>  
> +static inline bool on_accessible_stack_common(const struct task_struct *tsk,
> +					      unsigned long sp,
> +					      unsigned long size,
> +					      struct stack_info *info)
> +{
> +	if (info)
> +		info->type = STACK_TYPE_UNKNOWN;
> +
> +	/*
> +	 * Both the kernel and nvhe hypervisor make use of
> +	 * an overflow_stack
> +	 */
> +	return on_overflow_stack(sp, size, info);
> +}

on_accessible_stack has the following comment:

/*
 * We can only safely access per-cpu stacks from current in a non-preemptible
 * context.
 */

With this change, I don't think we satisfy this requirement anymore,
as we're checking the overflow stack *before* the preemptible check,
which is a big change in behaviour.

The hypervisor doesn't have this requirement: the unwinding is either
done out of context (nVHE, where EL1 unwinds EL2) or in a
non-preemptible section (pKVM, where the whole thing is
non-preemptible). But the kernel is usually preemptible, so this patch
needs fixing.

I'll see if I can address it locally (I'm currently moving things
around, stay tuned).

Thanks,

	M.

-- 
Without deviation from the norm, progress is not possible.

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 112+ messages in thread

* Re: [PATCH v6 09/17] KVM: arm64: Prepare non-protected nVHE hypervisor stacktrace
  2022-07-26  7:37   ` Kalesh Singh
  (?)
  (?)
@ 2022-07-26 16:26   ` kernel test robot
  -1 siblings, 0 replies; 112+ messages in thread
From: kernel test robot @ 2022-07-26 16:26 UTC (permalink / raw)
  To: Kalesh Singh; +Cc: llvm, kbuild-all

Hi Kalesh,

Thank you for the patch! Perhaps something to improve:

[auto build test WARNING on 82a592c13b0aeff94d84d54183dae0b26384c95f]

url:    https://github.com/intel-lab-lkp/linux/commits/Kalesh-Singh/KVM-nVHE-Hypervisor-stack-unwinder/20220726-154355
base:   82a592c13b0aeff94d84d54183dae0b26384c95f
config: arm64-buildonly-randconfig-r006-20220724 (https://download.01.org/0day-ci/archive/20220727/202207270011.GnBElFk7-lkp@intel.com/config)
compiler: clang version 15.0.0 (https://github.com/llvm/llvm-project 83882606dbd7ffb0bdd3460356202d97705809c8)
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # install arm64 cross compiling tool for clang build
        # apt-get install binutils-aarch64-linux-gnu
        # https://github.com/intel-lab-lkp/linux/commit/adb3292a8f22d642d40a5f2f649592a1961fa7da
        git remote add linux-review https://github.com/intel-lab-lkp/linux
        git fetch --no-tags linux-review Kalesh-Singh/KVM-nVHE-Hypervisor-stack-unwinder/20220726-154355
        git checkout adb3292a8f22d642d40a5f2f649592a1961fa7da
        # save the config file
        mkdir build_dir && cp config build_dir/.config
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross W=1 O=build_dir ARCH=arm64 SHELL=/bin/bash arch/arm64/

If you fix the issue, kindly add following tag where applicable
Reported-by: kernel test robot <lkp@intel.com>

All warnings (new ones prefixed by >>):

>> arch/arm64/kvm/hyp/nvhe/stacktrace.c:46:6: warning: no previous prototype for function 'kvm_nvhe_prepare_backtrace' [-Wmissing-prototypes]
   void kvm_nvhe_prepare_backtrace(unsigned long fp, unsigned long pc)
        ^
   arch/arm64/kvm/hyp/nvhe/stacktrace.c:46:1: note: declare 'static' if the function is not intended to be used outside of this translation unit
   void kvm_nvhe_prepare_backtrace(unsigned long fp, unsigned long pc)
   ^
   static 
   1 warning generated.


vim +/kvm_nvhe_prepare_backtrace +46 arch/arm64/kvm/hyp/nvhe/stacktrace.c

    36	
    37	/*
    38	 * kvm_nvhe_prepare_backtrace - prepare to dump the nVHE backtrace
    39	 *
    40	 * @fp : frame pointer at which to start the unwinding.
    41	 * @pc : program counter at which to start the unwinding.
    42	 *
    43	 * Saves the information needed by the host to dump the nVHE hypervisor
    44	 * backtrace.
    45	 */
  > 46	void kvm_nvhe_prepare_backtrace(unsigned long fp, unsigned long pc)

-- 
0-DAY CI Kernel Test Service
https://01.org/lkp

^ permalink raw reply	[flat|nested] 112+ messages in thread

* Re: [PATCH v6 02/17] arm64: stacktrace: Factor out on_accessible_stack_common()
  2022-07-26 16:01     ` Marc Zyngier
  (?)
@ 2022-07-26 16:33       ` Kalesh Singh
  -1 siblings, 0 replies; 112+ messages in thread
From: Kalesh Singh @ 2022-07-26 16:33 UTC (permalink / raw)
  To: Marc Zyngier
  Cc: Mark Rutland, Mark Brown, Madhavan T. Venkataraman, Fuad Tabba,
	Oliver Upton, Will Deacon, Quentin Perret, James Morse,
	Alexandru Elisei, Suzuki K Poulose, Catalin Marinas, andreyknvl,
	vincenzo.frascino, Masami Hiramatsu, Alexei Starovoitov,
	Kefeng Wang, Marco Elver, Keir Fraser, Zenghui Yu,
	Ard Biesheuvel, Oliver Upton,
	moderated list:ARM64 PORT (AARCH64 ARCHITECTURE),
	kvmarm, LKML, android-mm, Cc: Android Kernel

On Tue, Jul 26, 2022 at 9:01 AM Marc Zyngier <maz@kernel.org> wrote:
>
> On Tue, 26 Jul 2022 08:37:35 +0100,
> Kalesh Singh <kaleshsingh@google.com> wrote:
> >
> > Move common on_accessible_stack checks to stacktrace/common.h. This is
> > used in the implementation of the nVHE hypervisor unwinder later in
> > this series.
> >
> > Signed-off-by: Kalesh Singh <kaleshsingh@google.com>
> > Reviewed-by: Fuad Tabba <tabba@google.com>
> > Reviewed-by: Mark Brown <broonie@kernel.org>
> > Tested-by: Fuad Tabba <tabba@google.com>
> > ---
> >
> > Changes in v6:
> >   - Add Fuad's Tested-by tag
> >
> > Changes in v5:
> >   - Add Reviewed-by tags from Mark Brown and Fuad
> >   - Remove random whitespace change, per Mark Brown
> >
> >  arch/arm64/include/asm/stacktrace.h        |  6 ++----
> >  arch/arm64/include/asm/stacktrace/common.h | 18 ++++++++++++++++++
> >  2 files changed, 20 insertions(+), 4 deletions(-)
> >
> > diff --git a/arch/arm64/include/asm/stacktrace.h b/arch/arm64/include/asm/stacktrace.h
> > index 79f455b37c84..43f4b4a6d383 100644
> > --- a/arch/arm64/include/asm/stacktrace.h
> > +++ b/arch/arm64/include/asm/stacktrace.h
> > @@ -65,8 +65,8 @@ static inline bool on_accessible_stack(const struct task_struct *tsk,
> >                                      unsigned long sp, unsigned long size,
> >                                      struct stack_info *info)
> >  {
> > -     if (info)
> > -             info->type = STACK_TYPE_UNKNOWN;
> > +     if (on_accessible_stack_common(tsk, sp, size, info))
> > +             return true;
> >
> >       if (on_task_stack(tsk, sp, size, info))
> >               return true;
> > @@ -74,8 +74,6 @@ static inline bool on_accessible_stack(const struct task_struct *tsk,
> >               return false;
> >       if (on_irq_stack(sp, size, info))
> >               return true;
> > -     if (on_overflow_stack(sp, size, info))
> > -             return true;
> >       if (on_sdei_stack(sp, size, info))
> >               return true;
> >
> > diff --git a/arch/arm64/include/asm/stacktrace/common.h b/arch/arm64/include/asm/stacktrace/common.h
> > index 64ae4f6b06fe..f58b786460d3 100644
> > --- a/arch/arm64/include/asm/stacktrace/common.h
> > +++ b/arch/arm64/include/asm/stacktrace/common.h
> > @@ -62,6 +62,9 @@ struct unwind_state {
> >       struct task_struct *task;
> >  };
> >
> > +static inline bool on_overflow_stack(unsigned long sp, unsigned long size,
> > +                                  struct stack_info *info);
> > +
> >  static inline bool on_stack(unsigned long sp, unsigned long size,
> >                           unsigned long low, unsigned long high,
> >                           enum stack_type type, struct stack_info *info)
> > @@ -80,6 +83,21 @@ static inline bool on_stack(unsigned long sp, unsigned long size,
> >       return true;
> >  }
> >
> > +static inline bool on_accessible_stack_common(const struct task_struct *tsk,
> > +                                           unsigned long sp,
> > +                                           unsigned long size,
> > +                                           struct stack_info *info)
> > +{
> > +     if (info)
> > +             info->type = STACK_TYPE_UNKNOWN;
> > +
> > +     /*
> > +      * Both the kernel and nvhe hypervisor make use of
> > +      * an overflow_stack
> > +      */
> > +     return on_overflow_stack(sp, size, info);
> > +}
>
> on_accessible_stack has the following comment:
>
> /*
>  * We can only safely access per-cpu stacks from current in a non-preemptible
>  * context.
>  */
>
> With this change, I don't think we satisfy this requirement anymore,
> as we're checking the overflow stack *before* the preemptible check,
> which is a big change in behaviour.
>
> The hypervisor doesn't have this requirement: the unwinding is either
> done out of context (nVHE, where EL1 unwinds EL2) or in a
> non-preemptible section (pKVM, where the whole thing is
> non-preemptible). But the kernel is usually preemptible, so this patch
> needs fixing.
>
> I'll see if I can address it locally (I'm currently moving things
> around, stay tuned).

Hi Marc,

You are right it changes the order of the checks. I think the simplest
way then is to drop this patch, and replace uses of on_accessible
_stack_common().

Thanks,
Kalesh

>
> Thanks,
>
>         M.
>
> --
> Without deviation from the norm, progress is not possible.

^ permalink raw reply	[flat|nested] 112+ messages in thread

* Re: [PATCH v6 02/17] arm64: stacktrace: Factor out on_accessible_stack_common()
@ 2022-07-26 16:33       ` Kalesh Singh
  0 siblings, 0 replies; 112+ messages in thread
From: Kalesh Singh @ 2022-07-26 16:33 UTC (permalink / raw)
  To: Marc Zyngier
  Cc: Kefeng Wang, Catalin Marinas, Alexei Starovoitov,
	vincenzo.frascino, Will Deacon, android-mm, kvmarm,
	Madhavan T. Venkataraman, Cc: Android Kernel, Marco Elver,
	Mark Brown, moderated list:ARM64 PORT (AARCH64 ARCHITECTURE),
	andreyknvl, LKML, Masami Hiramatsu

On Tue, Jul 26, 2022 at 9:01 AM Marc Zyngier <maz@kernel.org> wrote:
>
> On Tue, 26 Jul 2022 08:37:35 +0100,
> Kalesh Singh <kaleshsingh@google.com> wrote:
> >
> > Move common on_accessible_stack checks to stacktrace/common.h. This is
> > used in the implementation of the nVHE hypervisor unwinder later in
> > this series.
> >
> > Signed-off-by: Kalesh Singh <kaleshsingh@google.com>
> > Reviewed-by: Fuad Tabba <tabba@google.com>
> > Reviewed-by: Mark Brown <broonie@kernel.org>
> > Tested-by: Fuad Tabba <tabba@google.com>
> > ---
> >
> > Changes in v6:
> >   - Add Fuad's Tested-by tag
> >
> > Changes in v5:
> >   - Add Reviewed-by tags from Mark Brown and Fuad
> >   - Remove random whitespace change, per Mark Brown
> >
> >  arch/arm64/include/asm/stacktrace.h        |  6 ++----
> >  arch/arm64/include/asm/stacktrace/common.h | 18 ++++++++++++++++++
> >  2 files changed, 20 insertions(+), 4 deletions(-)
> >
> > diff --git a/arch/arm64/include/asm/stacktrace.h b/arch/arm64/include/asm/stacktrace.h
> > index 79f455b37c84..43f4b4a6d383 100644
> > --- a/arch/arm64/include/asm/stacktrace.h
> > +++ b/arch/arm64/include/asm/stacktrace.h
> > @@ -65,8 +65,8 @@ static inline bool on_accessible_stack(const struct task_struct *tsk,
> >                                      unsigned long sp, unsigned long size,
> >                                      struct stack_info *info)
> >  {
> > -     if (info)
> > -             info->type = STACK_TYPE_UNKNOWN;
> > +     if (on_accessible_stack_common(tsk, sp, size, info))
> > +             return true;
> >
> >       if (on_task_stack(tsk, sp, size, info))
> >               return true;
> > @@ -74,8 +74,6 @@ static inline bool on_accessible_stack(const struct task_struct *tsk,
> >               return false;
> >       if (on_irq_stack(sp, size, info))
> >               return true;
> > -     if (on_overflow_stack(sp, size, info))
> > -             return true;
> >       if (on_sdei_stack(sp, size, info))
> >               return true;
> >
> > diff --git a/arch/arm64/include/asm/stacktrace/common.h b/arch/arm64/include/asm/stacktrace/common.h
> > index 64ae4f6b06fe..f58b786460d3 100644
> > --- a/arch/arm64/include/asm/stacktrace/common.h
> > +++ b/arch/arm64/include/asm/stacktrace/common.h
> > @@ -62,6 +62,9 @@ struct unwind_state {
> >       struct task_struct *task;
> >  };
> >
> > +static inline bool on_overflow_stack(unsigned long sp, unsigned long size,
> > +                                  struct stack_info *info);
> > +
> >  static inline bool on_stack(unsigned long sp, unsigned long size,
> >                           unsigned long low, unsigned long high,
> >                           enum stack_type type, struct stack_info *info)
> > @@ -80,6 +83,21 @@ static inline bool on_stack(unsigned long sp, unsigned long size,
> >       return true;
> >  }
> >
> > +static inline bool on_accessible_stack_common(const struct task_struct *tsk,
> > +                                           unsigned long sp,
> > +                                           unsigned long size,
> > +                                           struct stack_info *info)
> > +{
> > +     if (info)
> > +             info->type = STACK_TYPE_UNKNOWN;
> > +
> > +     /*
> > +      * Both the kernel and nvhe hypervisor make use of
> > +      * an overflow_stack
> > +      */
> > +     return on_overflow_stack(sp, size, info);
> > +}
>
> on_accessible_stack has the following comment:
>
> /*
>  * We can only safely access per-cpu stacks from current in a non-preemptible
>  * context.
>  */
>
> With this change, I don't think we satisfy this requirement anymore,
> as we're checking the overflow stack *before* the preemptible check,
> which is a big change in behaviour.
>
> The hypervisor doesn't have this requirement: the unwinding is either
> done out of context (nVHE, where EL1 unwinds EL2) or in a
> non-preemptible section (pKVM, where the whole thing is
> non-preemptible). But the kernel is usually preemptible, so this patch
> needs fixing.
>
> I'll see if I can address it locally (I'm currently moving things
> around, stay tuned).

Hi Marc,

You are right it changes the order of the checks. I think the simplest
way then is to drop this patch, and replace uses of on_accessible
_stack_common().

Thanks,
Kalesh

>
> Thanks,
>
>         M.
>
> --
> Without deviation from the norm, progress is not possible.
_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply	[flat|nested] 112+ messages in thread

* Re: [PATCH v6 02/17] arm64: stacktrace: Factor out on_accessible_stack_common()
@ 2022-07-26 16:33       ` Kalesh Singh
  0 siblings, 0 replies; 112+ messages in thread
From: Kalesh Singh @ 2022-07-26 16:33 UTC (permalink / raw)
  To: Marc Zyngier
  Cc: Mark Rutland, Mark Brown, Madhavan T. Venkataraman, Fuad Tabba,
	Oliver Upton, Will Deacon, Quentin Perret, James Morse,
	Alexandru Elisei, Suzuki K Poulose, Catalin Marinas, andreyknvl,
	vincenzo.frascino, Masami Hiramatsu, Alexei Starovoitov,
	Kefeng Wang, Marco Elver, Keir Fraser, Zenghui Yu,
	Ard Biesheuvel, Oliver Upton,
	moderated list:ARM64 PORT (AARCH64 ARCHITECTURE),
	kvmarm, LKML, android-mm, Cc: Android Kernel

On Tue, Jul 26, 2022 at 9:01 AM Marc Zyngier <maz@kernel.org> wrote:
>
> On Tue, 26 Jul 2022 08:37:35 +0100,
> Kalesh Singh <kaleshsingh@google.com> wrote:
> >
> > Move common on_accessible_stack checks to stacktrace/common.h. This is
> > used in the implementation of the nVHE hypervisor unwinder later in
> > this series.
> >
> > Signed-off-by: Kalesh Singh <kaleshsingh@google.com>
> > Reviewed-by: Fuad Tabba <tabba@google.com>
> > Reviewed-by: Mark Brown <broonie@kernel.org>
> > Tested-by: Fuad Tabba <tabba@google.com>
> > ---
> >
> > Changes in v6:
> >   - Add Fuad's Tested-by tag
> >
> > Changes in v5:
> >   - Add Reviewed-by tags from Mark Brown and Fuad
> >   - Remove random whitespace change, per Mark Brown
> >
> >  arch/arm64/include/asm/stacktrace.h        |  6 ++----
> >  arch/arm64/include/asm/stacktrace/common.h | 18 ++++++++++++++++++
> >  2 files changed, 20 insertions(+), 4 deletions(-)
> >
> > diff --git a/arch/arm64/include/asm/stacktrace.h b/arch/arm64/include/asm/stacktrace.h
> > index 79f455b37c84..43f4b4a6d383 100644
> > --- a/arch/arm64/include/asm/stacktrace.h
> > +++ b/arch/arm64/include/asm/stacktrace.h
> > @@ -65,8 +65,8 @@ static inline bool on_accessible_stack(const struct task_struct *tsk,
> >                                      unsigned long sp, unsigned long size,
> >                                      struct stack_info *info)
> >  {
> > -     if (info)
> > -             info->type = STACK_TYPE_UNKNOWN;
> > +     if (on_accessible_stack_common(tsk, sp, size, info))
> > +             return true;
> >
> >       if (on_task_stack(tsk, sp, size, info))
> >               return true;
> > @@ -74,8 +74,6 @@ static inline bool on_accessible_stack(const struct task_struct *tsk,
> >               return false;
> >       if (on_irq_stack(sp, size, info))
> >               return true;
> > -     if (on_overflow_stack(sp, size, info))
> > -             return true;
> >       if (on_sdei_stack(sp, size, info))
> >               return true;
> >
> > diff --git a/arch/arm64/include/asm/stacktrace/common.h b/arch/arm64/include/asm/stacktrace/common.h
> > index 64ae4f6b06fe..f58b786460d3 100644
> > --- a/arch/arm64/include/asm/stacktrace/common.h
> > +++ b/arch/arm64/include/asm/stacktrace/common.h
> > @@ -62,6 +62,9 @@ struct unwind_state {
> >       struct task_struct *task;
> >  };
> >
> > +static inline bool on_overflow_stack(unsigned long sp, unsigned long size,
> > +                                  struct stack_info *info);
> > +
> >  static inline bool on_stack(unsigned long sp, unsigned long size,
> >                           unsigned long low, unsigned long high,
> >                           enum stack_type type, struct stack_info *info)
> > @@ -80,6 +83,21 @@ static inline bool on_stack(unsigned long sp, unsigned long size,
> >       return true;
> >  }
> >
> > +static inline bool on_accessible_stack_common(const struct task_struct *tsk,
> > +                                           unsigned long sp,
> > +                                           unsigned long size,
> > +                                           struct stack_info *info)
> > +{
> > +     if (info)
> > +             info->type = STACK_TYPE_UNKNOWN;
> > +
> > +     /*
> > +      * Both the kernel and nvhe hypervisor make use of
> > +      * an overflow_stack
> > +      */
> > +     return on_overflow_stack(sp, size, info);
> > +}
>
> on_accessible_stack has the following comment:
>
> /*
>  * We can only safely access per-cpu stacks from current in a non-preemptible
>  * context.
>  */
>
> With this change, I don't think we satisfy this requirement anymore,
> as we're checking the overflow stack *before* the preemptible check,
> which is a big change in behaviour.
>
> The hypervisor doesn't have this requirement: the unwinding is either
> done out of context (nVHE, where EL1 unwinds EL2) or in a
> non-preemptible section (pKVM, where the whole thing is
> non-preemptible). But the kernel is usually preemptible, so this patch
> needs fixing.
>
> I'll see if I can address it locally (I'm currently moving things
> around, stay tuned).

Hi Marc,

You are right it changes the order of the checks. I think the simplest
way then is to drop this patch, and replace uses of on_accessible
_stack_common().

Thanks,
Kalesh

>
> Thanks,
>
>         M.
>
> --
> Without deviation from the norm, progress is not possible.

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 112+ messages in thread

* [PATCH 0/6] KVM: arm64: nVHE stack unwinder rework
  2022-07-26  7:37   ` Kalesh Singh
  (?)
@ 2022-07-27 14:29     ` Marc Zyngier
  -1 siblings, 0 replies; 112+ messages in thread
From: Marc Zyngier @ 2022-07-27 14:29 UTC (permalink / raw)
  To: linux-arm-kernel, kvmarm, kvm
  Cc: mark.rutland, broonie, madvenka, tabba, oliver.upton, qperret,
	kaleshsingh, james.morse, alexandru.elisei, suzuki.poulose,
	catalin.marinas, andreyknvl, vincenzo.frascino, mhiramat, ast,
	wangkefeng.wang, elver, keirf, yuzenghui, ardb, oupton,
	kernel-team

Hi all,

As Kalesh's series[1] already went through quite a few rounds and that
it has proved to be an extremely useful debugging help, I'd like to
queue it for 5.20.

However, there is a couple of nits that I'd like to address:

- the code is extremely hard to follow, due to the include maze and
  the various levels of inline functions that have forward
  declarations...

- there is a subtle bug in the way the kernel on_accessible_stack()
  helper has been rewritten

- the config symbol for the protected unwinder is oddly placed

Instead of going for another round and missing the merge window, I
propose to stash the following patches on top, which IMHO result in
something much more readable.

This series directly applies on top of Kalesh's.

[1] https://lore.kernel.org/r/20220726073750.3219117-1-kaleshsingh@google.com

Marc Zyngier (5):
  KVM: arm64: Move PROTECTED_NVHE_STACKTRACE around
  KVM: arm64: Move nVHE stacktrace unwinding into its own compilation
    unit
  KVM: arm64: Make unwind()/on_accessible_stack() per-unwinder functions
  KVM: arm64: Move nVHE-only helpers into kvm/stacktrace.c
  arm64: Update 'unwinder howto'

Oliver Upton (1):
  KVM: arm64: Don't open code ARRAY_SIZE()

 arch/arm64/include/asm/stacktrace.h        |  74 -------
 arch/arm64/include/asm/stacktrace/common.h |  69 ++-----
 arch/arm64/include/asm/stacktrace/nvhe.h   | 125 +-----------
 arch/arm64/kernel/stacktrace.c             |  90 +++++++++
 arch/arm64/kvm/Kconfig                     |  24 ++-
 arch/arm64/kvm/Makefile                    |   2 +-
 arch/arm64/kvm/handle_exit.c               |  98 ---------
 arch/arm64/kvm/hyp/nvhe/stacktrace.c       |  55 +++++-
 arch/arm64/kvm/stacktrace.c                | 218 +++++++++++++++++++++
 9 files changed, 394 insertions(+), 361 deletions(-)
 create mode 100644 arch/arm64/kvm/stacktrace.c

-- 
2.34.1


^ permalink raw reply	[flat|nested] 112+ messages in thread

* [PATCH 0/6] KVM: arm64: nVHE stack unwinder rework
@ 2022-07-27 14:29     ` Marc Zyngier
  0 siblings, 0 replies; 112+ messages in thread
From: Marc Zyngier @ 2022-07-27 14:29 UTC (permalink / raw)
  To: linux-arm-kernel, kvmarm, kvm
  Cc: wangkefeng.wang, catalin.marinas, ast, vincenzo.frascino,
	madvenka, kernel-team, elver, broonie, andreyknvl, mhiramat

Hi all,

As Kalesh's series[1] already went through quite a few rounds and that
it has proved to be an extremely useful debugging help, I'd like to
queue it for 5.20.

However, there is a couple of nits that I'd like to address:

- the code is extremely hard to follow, due to the include maze and
  the various levels of inline functions that have forward
  declarations...

- there is a subtle bug in the way the kernel on_accessible_stack()
  helper has been rewritten

- the config symbol for the protected unwinder is oddly placed

Instead of going for another round and missing the merge window, I
propose to stash the following patches on top, which IMHO result in
something much more readable.

This series directly applies on top of Kalesh's.

[1] https://lore.kernel.org/r/20220726073750.3219117-1-kaleshsingh@google.com

Marc Zyngier (5):
  KVM: arm64: Move PROTECTED_NVHE_STACKTRACE around
  KVM: arm64: Move nVHE stacktrace unwinding into its own compilation
    unit
  KVM: arm64: Make unwind()/on_accessible_stack() per-unwinder functions
  KVM: arm64: Move nVHE-only helpers into kvm/stacktrace.c
  arm64: Update 'unwinder howto'

Oliver Upton (1):
  KVM: arm64: Don't open code ARRAY_SIZE()

 arch/arm64/include/asm/stacktrace.h        |  74 -------
 arch/arm64/include/asm/stacktrace/common.h |  69 ++-----
 arch/arm64/include/asm/stacktrace/nvhe.h   | 125 +-----------
 arch/arm64/kernel/stacktrace.c             |  90 +++++++++
 arch/arm64/kvm/Kconfig                     |  24 ++-
 arch/arm64/kvm/Makefile                    |   2 +-
 arch/arm64/kvm/handle_exit.c               |  98 ---------
 arch/arm64/kvm/hyp/nvhe/stacktrace.c       |  55 +++++-
 arch/arm64/kvm/stacktrace.c                | 218 +++++++++++++++++++++
 9 files changed, 394 insertions(+), 361 deletions(-)
 create mode 100644 arch/arm64/kvm/stacktrace.c

-- 
2.34.1

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply	[flat|nested] 112+ messages in thread

* [PATCH 0/6] KVM: arm64: nVHE stack unwinder rework
@ 2022-07-27 14:29     ` Marc Zyngier
  0 siblings, 0 replies; 112+ messages in thread
From: Marc Zyngier @ 2022-07-27 14:29 UTC (permalink / raw)
  To: linux-arm-kernel, kvmarm, kvm
  Cc: mark.rutland, broonie, madvenka, tabba, oliver.upton, qperret,
	kaleshsingh, james.morse, alexandru.elisei, suzuki.poulose,
	catalin.marinas, andreyknvl, vincenzo.frascino, mhiramat, ast,
	wangkefeng.wang, elver, keirf, yuzenghui, ardb, oupton,
	kernel-team

Hi all,

As Kalesh's series[1] already went through quite a few rounds and that
it has proved to be an extremely useful debugging help, I'd like to
queue it for 5.20.

However, there is a couple of nits that I'd like to address:

- the code is extremely hard to follow, due to the include maze and
  the various levels of inline functions that have forward
  declarations...

- there is a subtle bug in the way the kernel on_accessible_stack()
  helper has been rewritten

- the config symbol for the protected unwinder is oddly placed

Instead of going for another round and missing the merge window, I
propose to stash the following patches on top, which IMHO result in
something much more readable.

This series directly applies on top of Kalesh's.

[1] https://lore.kernel.org/r/20220726073750.3219117-1-kaleshsingh@google.com

Marc Zyngier (5):
  KVM: arm64: Move PROTECTED_NVHE_STACKTRACE around
  KVM: arm64: Move nVHE stacktrace unwinding into its own compilation
    unit
  KVM: arm64: Make unwind()/on_accessible_stack() per-unwinder functions
  KVM: arm64: Move nVHE-only helpers into kvm/stacktrace.c
  arm64: Update 'unwinder howto'

Oliver Upton (1):
  KVM: arm64: Don't open code ARRAY_SIZE()

 arch/arm64/include/asm/stacktrace.h        |  74 -------
 arch/arm64/include/asm/stacktrace/common.h |  69 ++-----
 arch/arm64/include/asm/stacktrace/nvhe.h   | 125 +-----------
 arch/arm64/kernel/stacktrace.c             |  90 +++++++++
 arch/arm64/kvm/Kconfig                     |  24 ++-
 arch/arm64/kvm/Makefile                    |   2 +-
 arch/arm64/kvm/handle_exit.c               |  98 ---------
 arch/arm64/kvm/hyp/nvhe/stacktrace.c       |  55 +++++-
 arch/arm64/kvm/stacktrace.c                | 218 +++++++++++++++++++++
 9 files changed, 394 insertions(+), 361 deletions(-)
 create mode 100644 arch/arm64/kvm/stacktrace.c

-- 
2.34.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 112+ messages in thread

* [PATCH 1/6] KVM: arm64: Move PROTECTED_NVHE_STACKTRACE around
  2022-07-27 14:29     ` Marc Zyngier
  (?)
@ 2022-07-27 14:29       ` Marc Zyngier
  -1 siblings, 0 replies; 112+ messages in thread
From: Marc Zyngier @ 2022-07-27 14:29 UTC (permalink / raw)
  To: linux-arm-kernel, kvmarm, kvm
  Cc: mark.rutland, broonie, madvenka, tabba, oliver.upton, qperret,
	kaleshsingh, james.morse, alexandru.elisei, suzuki.poulose,
	catalin.marinas, andreyknvl, vincenzo.frascino, mhiramat, ast,
	wangkefeng.wang, elver, keirf, yuzenghui, ardb, oupton,
	kernel-team

Make the dependency with EL2_DEBUG more obvious by moving the
stacktrace configurtion *after* it.

Signed-off-by: Marc Zyngier <maz@kernel.org>
---
 arch/arm64/kvm/Kconfig | 24 +++++++++++-------------
 1 file changed, 11 insertions(+), 13 deletions(-)

diff --git a/arch/arm64/kvm/Kconfig b/arch/arm64/kvm/Kconfig
index 09c995869916..815cc118c675 100644
--- a/arch/arm64/kvm/Kconfig
+++ b/arch/arm64/kvm/Kconfig
@@ -46,6 +46,16 @@ menuconfig KVM
 
 	  If unsure, say N.
 
+config NVHE_EL2_DEBUG
+	bool "Debug mode for non-VHE EL2 object"
+	depends on KVM
+	help
+	  Say Y here to enable the debug mode for the non-VHE KVM EL2 object.
+	  Failure reports will BUG() in the hypervisor. This is intended for
+	  local EL2 hypervisor development.
+
+	  If unsure, say N.
+
 config PROTECTED_NVHE_STACKTRACE
 	bool "Protected KVM hypervisor stacktraces"
 	depends on NVHE_EL2_DEBUG
@@ -53,22 +63,10 @@ config PROTECTED_NVHE_STACKTRACE
 	help
 	  Say Y here to enable pKVM hypervisor stacktraces on hyp_panic()
 
-	  If you are not using protected nVHE (pKVM), say N.
-
 	  If using protected nVHE mode, but cannot afford the associated
 	  memory cost (less than 0.75 page per CPU) of pKVM stacktraces,
 	  say N.
 
-	  If unsure, say N.
-
-config NVHE_EL2_DEBUG
-	bool "Debug mode for non-VHE EL2 object"
-	depends on KVM
-	help
-	  Say Y here to enable the debug mode for the non-VHE KVM EL2 object.
-	  Failure reports will BUG() in the hypervisor. This is intended for
-	  local EL2 hypervisor development.
-
-	  If unsure, say N.
+	  If unsure, or not using protected nVHE (pKVM), say N.
 
 endif # VIRTUALIZATION
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 112+ messages in thread

* [PATCH 1/6] KVM: arm64: Move PROTECTED_NVHE_STACKTRACE around
@ 2022-07-27 14:29       ` Marc Zyngier
  0 siblings, 0 replies; 112+ messages in thread
From: Marc Zyngier @ 2022-07-27 14:29 UTC (permalink / raw)
  To: linux-arm-kernel, kvmarm, kvm
  Cc: wangkefeng.wang, catalin.marinas, ast, vincenzo.frascino,
	madvenka, kernel-team, elver, broonie, andreyknvl, mhiramat

Make the dependency with EL2_DEBUG more obvious by moving the
stacktrace configurtion *after* it.

Signed-off-by: Marc Zyngier <maz@kernel.org>
---
 arch/arm64/kvm/Kconfig | 24 +++++++++++-------------
 1 file changed, 11 insertions(+), 13 deletions(-)

diff --git a/arch/arm64/kvm/Kconfig b/arch/arm64/kvm/Kconfig
index 09c995869916..815cc118c675 100644
--- a/arch/arm64/kvm/Kconfig
+++ b/arch/arm64/kvm/Kconfig
@@ -46,6 +46,16 @@ menuconfig KVM
 
 	  If unsure, say N.
 
+config NVHE_EL2_DEBUG
+	bool "Debug mode for non-VHE EL2 object"
+	depends on KVM
+	help
+	  Say Y here to enable the debug mode for the non-VHE KVM EL2 object.
+	  Failure reports will BUG() in the hypervisor. This is intended for
+	  local EL2 hypervisor development.
+
+	  If unsure, say N.
+
 config PROTECTED_NVHE_STACKTRACE
 	bool "Protected KVM hypervisor stacktraces"
 	depends on NVHE_EL2_DEBUG
@@ -53,22 +63,10 @@ config PROTECTED_NVHE_STACKTRACE
 	help
 	  Say Y here to enable pKVM hypervisor stacktraces on hyp_panic()
 
-	  If you are not using protected nVHE (pKVM), say N.
-
 	  If using protected nVHE mode, but cannot afford the associated
 	  memory cost (less than 0.75 page per CPU) of pKVM stacktraces,
 	  say N.
 
-	  If unsure, say N.
-
-config NVHE_EL2_DEBUG
-	bool "Debug mode for non-VHE EL2 object"
-	depends on KVM
-	help
-	  Say Y here to enable the debug mode for the non-VHE KVM EL2 object.
-	  Failure reports will BUG() in the hypervisor. This is intended for
-	  local EL2 hypervisor development.
-
-	  If unsure, say N.
+	  If unsure, or not using protected nVHE (pKVM), say N.
 
 endif # VIRTUALIZATION
-- 
2.34.1

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply related	[flat|nested] 112+ messages in thread

* [PATCH 1/6] KVM: arm64: Move PROTECTED_NVHE_STACKTRACE around
@ 2022-07-27 14:29       ` Marc Zyngier
  0 siblings, 0 replies; 112+ messages in thread
From: Marc Zyngier @ 2022-07-27 14:29 UTC (permalink / raw)
  To: linux-arm-kernel, kvmarm, kvm
  Cc: mark.rutland, broonie, madvenka, tabba, oliver.upton, qperret,
	kaleshsingh, james.morse, alexandru.elisei, suzuki.poulose,
	catalin.marinas, andreyknvl, vincenzo.frascino, mhiramat, ast,
	wangkefeng.wang, elver, keirf, yuzenghui, ardb, oupton,
	kernel-team

Make the dependency with EL2_DEBUG more obvious by moving the
stacktrace configurtion *after* it.

Signed-off-by: Marc Zyngier <maz@kernel.org>
---
 arch/arm64/kvm/Kconfig | 24 +++++++++++-------------
 1 file changed, 11 insertions(+), 13 deletions(-)

diff --git a/arch/arm64/kvm/Kconfig b/arch/arm64/kvm/Kconfig
index 09c995869916..815cc118c675 100644
--- a/arch/arm64/kvm/Kconfig
+++ b/arch/arm64/kvm/Kconfig
@@ -46,6 +46,16 @@ menuconfig KVM
 
 	  If unsure, say N.
 
+config NVHE_EL2_DEBUG
+	bool "Debug mode for non-VHE EL2 object"
+	depends on KVM
+	help
+	  Say Y here to enable the debug mode for the non-VHE KVM EL2 object.
+	  Failure reports will BUG() in the hypervisor. This is intended for
+	  local EL2 hypervisor development.
+
+	  If unsure, say N.
+
 config PROTECTED_NVHE_STACKTRACE
 	bool "Protected KVM hypervisor stacktraces"
 	depends on NVHE_EL2_DEBUG
@@ -53,22 +63,10 @@ config PROTECTED_NVHE_STACKTRACE
 	help
 	  Say Y here to enable pKVM hypervisor stacktraces on hyp_panic()
 
-	  If you are not using protected nVHE (pKVM), say N.
-
 	  If using protected nVHE mode, but cannot afford the associated
 	  memory cost (less than 0.75 page per CPU) of pKVM stacktraces,
 	  say N.
 
-	  If unsure, say N.
-
-config NVHE_EL2_DEBUG
-	bool "Debug mode for non-VHE EL2 object"
-	depends on KVM
-	help
-	  Say Y here to enable the debug mode for the non-VHE KVM EL2 object.
-	  Failure reports will BUG() in the hypervisor. This is intended for
-	  local EL2 hypervisor development.
-
-	  If unsure, say N.
+	  If unsure, or not using protected nVHE (pKVM), say N.
 
 endif # VIRTUALIZATION
-- 
2.34.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 112+ messages in thread

* [PATCH 2/6] KVM: arm64: Move nVHE stacktrace unwinding into its own compilation unit
  2022-07-27 14:29     ` Marc Zyngier
  (?)
@ 2022-07-27 14:29       ` Marc Zyngier
  -1 siblings, 0 replies; 112+ messages in thread
From: Marc Zyngier @ 2022-07-27 14:29 UTC (permalink / raw)
  To: linux-arm-kernel, kvmarm, kvm
  Cc: mark.rutland, broonie, madvenka, tabba, oliver.upton, qperret,
	kaleshsingh, james.morse, alexandru.elisei, suzuki.poulose,
	catalin.marinas, andreyknvl, vincenzo.frascino, mhiramat, ast,
	wangkefeng.wang, elver, keirf, yuzenghui, ardb, oupton,
	kernel-team

The unwinding code doesn't really belong to the exit handling
code. Instead, move it to a file (conveniently named stacktrace.c
to confuse the reviewer), and move all the stacktrace-related
stuff there.

It will be joined by more code very soon.

Signed-off-by: Marc Zyngier <maz@kernel.org>
---
 arch/arm64/include/asm/stacktrace/nvhe.h |   2 +
 arch/arm64/kvm/Makefile                  |   2 +-
 arch/arm64/kvm/handle_exit.c             |  98 ------------------
 arch/arm64/kvm/stacktrace.c              | 120 +++++++++++++++++++++++
 4 files changed, 123 insertions(+), 99 deletions(-)
 create mode 100644 arch/arm64/kvm/stacktrace.c

diff --git a/arch/arm64/include/asm/stacktrace/nvhe.h b/arch/arm64/include/asm/stacktrace/nvhe.h
index 600dbc2220b6..8a5cb96d7143 100644
--- a/arch/arm64/include/asm/stacktrace/nvhe.h
+++ b/arch/arm64/include/asm/stacktrace/nvhe.h
@@ -172,5 +172,7 @@ static inline int notrace unwind_next(struct unwind_state *state)
 }
 NOKPROBE_SYMBOL(unwind_next);
 
+void kvm_nvhe_dump_backtrace(unsigned long hyp_offset);
+
 #endif	/* __KVM_NVHE_HYPERVISOR__ */
 #endif	/* __ASM_STACKTRACE_NVHE_H */
diff --git a/arch/arm64/kvm/Makefile b/arch/arm64/kvm/Makefile
index aa127ae9f675..5e33c2d4645a 100644
--- a/arch/arm64/kvm/Makefile
+++ b/arch/arm64/kvm/Makefile
@@ -12,7 +12,7 @@ obj-$(CONFIG_KVM) += hyp/
 
 kvm-y += arm.o mmu.o mmio.o psci.o hypercalls.o pvtime.o \
 	 inject_fault.o va_layout.o handle_exit.o \
-	 guest.o debug.o reset.o sys_regs.o \
+	 guest.o debug.o reset.o sys_regs.o stacktrace.o \
 	 vgic-sys-reg-v3.o fpsimd.o pkvm.o \
 	 arch_timer.o trng.o vmid.o \
 	 vgic/vgic.o vgic/vgic-init.o \
diff --git a/arch/arm64/kvm/handle_exit.c b/arch/arm64/kvm/handle_exit.c
index c14fc4ba4422..ef8b57953aa2 100644
--- a/arch/arm64/kvm/handle_exit.c
+++ b/arch/arm64/kvm/handle_exit.c
@@ -319,104 +319,6 @@ void handle_exit_early(struct kvm_vcpu *vcpu, int exception_index)
 		kvm_handle_guest_serror(vcpu, kvm_vcpu_get_esr(vcpu));
 }
 
-/*
- * kvm_nvhe_dump_backtrace_entry - Symbolize and print an nVHE backtrace entry
- *
- * @arg    : the hypervisor offset, used for address translation
- * @where  : the program counter corresponding to the stack frame
- */
-static bool kvm_nvhe_dump_backtrace_entry(void *arg, unsigned long where)
-{
-	unsigned long va_mask = GENMASK_ULL(vabits_actual - 1, 0);
-	unsigned long hyp_offset = (unsigned long)arg;
-
-	/* Mask tags and convert to kern addr */
-	where = (where & va_mask) + hyp_offset;
-	kvm_err(" [<%016lx>] %pB\n", where, (void *)(where + kaslr_offset()));
-
-	return true;
-}
-
-static inline void kvm_nvhe_dump_backtrace_start(void)
-{
-	kvm_err("nVHE call trace:\n");
-}
-
-static inline void kvm_nvhe_dump_backtrace_end(void)
-{
-	kvm_err("---[ end nVHE call trace ]---\n");
-}
-
-/*
- * hyp_dump_backtrace - Dump the non-protected nVHE backtrace.
- *
- * @hyp_offset: hypervisor offset, used for address translation.
- *
- * The host can directly access HYP stack pages in non-protected
- * mode, so the unwinding is done directly from EL1. This removes
- * the need for shared buffers between host and hypervisor for
- * the stacktrace.
- */
-static void hyp_dump_backtrace(unsigned long hyp_offset)
-{
-	struct kvm_nvhe_stacktrace_info *stacktrace_info;
-	struct unwind_state state;
-
-	stacktrace_info = this_cpu_ptr_nvhe_sym(kvm_stacktrace_info);
-
-	kvm_nvhe_unwind_init(&state, stacktrace_info->fp, stacktrace_info->pc);
-
-	kvm_nvhe_dump_backtrace_start();
-	unwind(&state, kvm_nvhe_dump_backtrace_entry, (void *)hyp_offset);
-	kvm_nvhe_dump_backtrace_end();
-}
-
-#ifdef CONFIG_PROTECTED_NVHE_STACKTRACE
-DECLARE_KVM_NVHE_PER_CPU(unsigned long [NVHE_STACKTRACE_SIZE/sizeof(long)],
-			 pkvm_stacktrace);
-
-/*
- * pkvm_dump_backtrace - Dump the protected nVHE HYP backtrace.
- *
- * @hyp_offset: hypervisor offset, used for address translation.
- *
- * Dumping of the pKVM HYP backtrace is done by reading the
- * stack addresses from the shared stacktrace buffer, since the
- * host cannot directly access hypervisor memory in protected
- * mode.
- */
-static void pkvm_dump_backtrace(unsigned long hyp_offset)
-{
-	unsigned long *stacktrace
-		= (unsigned long *) this_cpu_ptr_nvhe_sym(pkvm_stacktrace);
-	int i, size = NVHE_STACKTRACE_SIZE / sizeof(long);
-
-	kvm_nvhe_dump_backtrace_start();
-	/* The saved stacktrace is terminated by a null entry */
-	for (i = 0; i < size && stacktrace[i]; i++)
-		kvm_nvhe_dump_backtrace_entry((void *)hyp_offset, stacktrace[i]);
-	kvm_nvhe_dump_backtrace_end();
-}
-#else	/* !CONFIG_PROTECTED_NVHE_STACKTRACE */
-static void pkvm_dump_backtrace(unsigned long hyp_offset)
-{
-	kvm_err("Cannot dump pKVM nVHE stacktrace: !CONFIG_PROTECTED_NVHE_STACKTRACE\n");
-}
-#endif /* CONFIG_PROTECTED_NVHE_STACKTRACE */
-
-/*
- * kvm_nvhe_dump_backtrace - Dump KVM nVHE hypervisor backtrace.
- *
- * @hyp_offset: hypervisor offset, used for address translation.
- */
-static void kvm_nvhe_dump_backtrace(unsigned long hyp_offset)
-{
-	if (is_protected_kvm_enabled())
-		pkvm_dump_backtrace(hyp_offset);
-	else
-		hyp_dump_backtrace(hyp_offset);
-}
-
 void __noreturn __cold nvhe_hyp_panic_handler(u64 esr, u64 spsr,
 					      u64 elr_virt, u64 elr_phys,
 					      u64 par, uintptr_t vcpu,
diff --git a/arch/arm64/kvm/stacktrace.c b/arch/arm64/kvm/stacktrace.c
new file mode 100644
index 000000000000..9812aefdcfb4
--- /dev/null
+++ b/arch/arm64/kvm/stacktrace.c
@@ -0,0 +1,120 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * KVM nVHE hypervisor stack tracing support.
+ *
+ * The unwinder implementation depends on the nVHE mode:
+ *
+ *   1) Non-protected nVHE mode - the host can directly access the
+ *      HYP stack pages and unwind the HYP stack in EL1. This saves having
+ *      to allocate shared buffers for the host to read the unwinded
+ *      stacktrace.
+ *
+ *   2) pKVM (protected nVHE) mode - the host cannot directly access
+ *      the HYP memory. The stack is unwinded in EL2 and dumped to a shared
+ *      buffer where the host can read and print the stacktrace.
+ *
+ * Copyright (C) 2022 Google LLC
+ */
+
+#include <linux/kvm.h>
+#include <linux/kvm_host.h>
+
+#include <asm/stacktrace/nvhe.h>
+
+/*
+ * kvm_nvhe_dump_backtrace_entry - Symbolize and print an nVHE backtrace entry
+ *
+ * @arg    : the hypervisor offset, used for address translation
+ * @where  : the program counter corresponding to the stack frame
+ */
+static bool kvm_nvhe_dump_backtrace_entry(void *arg, unsigned long where)
+{
+	unsigned long va_mask = GENMASK_ULL(vabits_actual - 1, 0);
+	unsigned long hyp_offset = (unsigned long)arg;
+
+	/* Mask tags and convert to kern addr */
+	where = (where & va_mask) + hyp_offset;
+	kvm_err(" [<%016lx>] %pB\n", where, (void *)(where + kaslr_offset()));
+
+	return true;
+}
+
+static void kvm_nvhe_dump_backtrace_start(void)
+{
+	kvm_err("nVHE call trace:\n");
+}
+
+static void kvm_nvhe_dump_backtrace_end(void)
+{
+	kvm_err("---[ end nVHE call trace ]---\n");
+}
+
+/*
+ * hyp_dump_backtrace - Dump the non-protected nVHE backtrace.
+ *
+ * @hyp_offset: hypervisor offset, used for address translation.
+ *
+ * The host can directly access HYP stack pages in non-protected
+ * mode, so the unwinding is done directly from EL1. This removes
+ * the need for shared buffers between host and hypervisor for
+ * the stacktrace.
+ */
+static void hyp_dump_backtrace(unsigned long hyp_offset)
+{
+	struct kvm_nvhe_stacktrace_info *stacktrace_info;
+	struct unwind_state state;
+
+	stacktrace_info = this_cpu_ptr_nvhe_sym(kvm_stacktrace_info);
+
+	kvm_nvhe_unwind_init(&state, stacktrace_info->fp, stacktrace_info->pc);
+
+	kvm_nvhe_dump_backtrace_start();
+	unwind(&state, kvm_nvhe_dump_backtrace_entry, (void *)hyp_offset);
+	kvm_nvhe_dump_backtrace_end();
+}
+
+#ifdef CONFIG_PROTECTED_NVHE_STACKTRACE
+DECLARE_KVM_NVHE_PER_CPU(unsigned long [NVHE_STACKTRACE_SIZE/sizeof(long)],
+			 pkvm_stacktrace);
+
+/*
+ * pkvm_dump_backtrace - Dump the protected nVHE HYP backtrace.
+ *
+ * @hyp_offset: hypervisor offset, used for address translation.
+ *
+ * Dumping of the pKVM HYP backtrace is done by reading the
+ * stack addresses from the shared stacktrace buffer, since the
+ * host cannot directly access hypervisor memory in protected
+ * mode.
+ */
+static void pkvm_dump_backtrace(unsigned long hyp_offset)
+{
+	unsigned long *stacktrace
+		= (unsigned long *) this_cpu_ptr_nvhe_sym(pkvm_stacktrace);
+	int i, size = NVHE_STACKTRACE_SIZE / sizeof(long);
+
+	kvm_nvhe_dump_backtrace_start();
+	/* The saved stacktrace is terminated by a null entry */
+	for (i = 0; i < size && stacktrace[i]; i++)
+		kvm_nvhe_dump_backtrace_entry((void *)hyp_offset, stacktrace[i]);
+	kvm_nvhe_dump_backtrace_end();
+}
+#else	/* !CONFIG_PROTECTED_NVHE_STACKTRACE */
+static void pkvm_dump_backtrace(unsigned long hyp_offset)
+{
+	kvm_err("Cannot dump pKVM nVHE stacktrace: !CONFIG_PROTECTED_NVHE_STACKTRACE\n");
+}
+#endif /* CONFIG_PROTECTED_NVHE_STACKTRACE */
+
+/*
+ * kvm_nvhe_dump_backtrace - Dump KVM nVHE hypervisor backtrace.
+ *
+ * @hyp_offset: hypervisor offset, used for address translation.
+ */
+void kvm_nvhe_dump_backtrace(unsigned long hyp_offset)
+{
+	if (is_protected_kvm_enabled())
+		pkvm_dump_backtrace(hyp_offset);
+	else
+		hyp_dump_backtrace(hyp_offset);
+}
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 112+ messages in thread

* [PATCH 2/6] KVM: arm64: Move nVHE stacktrace unwinding into its own compilation unit
@ 2022-07-27 14:29       ` Marc Zyngier
  0 siblings, 0 replies; 112+ messages in thread
From: Marc Zyngier @ 2022-07-27 14:29 UTC (permalink / raw)
  To: linux-arm-kernel, kvmarm, kvm
  Cc: wangkefeng.wang, catalin.marinas, ast, vincenzo.frascino,
	madvenka, kernel-team, elver, broonie, andreyknvl, mhiramat

The unwinding code doesn't really belong to the exit handling
code. Instead, move it to a file (conveniently named stacktrace.c
to confuse the reviewer), and move all the stacktrace-related
stuff there.

It will be joined by more code very soon.

Signed-off-by: Marc Zyngier <maz@kernel.org>
---
 arch/arm64/include/asm/stacktrace/nvhe.h |   2 +
 arch/arm64/kvm/Makefile                  |   2 +-
 arch/arm64/kvm/handle_exit.c             |  98 ------------------
 arch/arm64/kvm/stacktrace.c              | 120 +++++++++++++++++++++++
 4 files changed, 123 insertions(+), 99 deletions(-)
 create mode 100644 arch/arm64/kvm/stacktrace.c

diff --git a/arch/arm64/include/asm/stacktrace/nvhe.h b/arch/arm64/include/asm/stacktrace/nvhe.h
index 600dbc2220b6..8a5cb96d7143 100644
--- a/arch/arm64/include/asm/stacktrace/nvhe.h
+++ b/arch/arm64/include/asm/stacktrace/nvhe.h
@@ -172,5 +172,7 @@ static inline int notrace unwind_next(struct unwind_state *state)
 }
 NOKPROBE_SYMBOL(unwind_next);
 
+void kvm_nvhe_dump_backtrace(unsigned long hyp_offset);
+
 #endif	/* __KVM_NVHE_HYPERVISOR__ */
 #endif	/* __ASM_STACKTRACE_NVHE_H */
diff --git a/arch/arm64/kvm/Makefile b/arch/arm64/kvm/Makefile
index aa127ae9f675..5e33c2d4645a 100644
--- a/arch/arm64/kvm/Makefile
+++ b/arch/arm64/kvm/Makefile
@@ -12,7 +12,7 @@ obj-$(CONFIG_KVM) += hyp/
 
 kvm-y += arm.o mmu.o mmio.o psci.o hypercalls.o pvtime.o \
 	 inject_fault.o va_layout.o handle_exit.o \
-	 guest.o debug.o reset.o sys_regs.o \
+	 guest.o debug.o reset.o sys_regs.o stacktrace.o \
 	 vgic-sys-reg-v3.o fpsimd.o pkvm.o \
 	 arch_timer.o trng.o vmid.o \
 	 vgic/vgic.o vgic/vgic-init.o \
diff --git a/arch/arm64/kvm/handle_exit.c b/arch/arm64/kvm/handle_exit.c
index c14fc4ba4422..ef8b57953aa2 100644
--- a/arch/arm64/kvm/handle_exit.c
+++ b/arch/arm64/kvm/handle_exit.c
@@ -319,104 +319,6 @@ void handle_exit_early(struct kvm_vcpu *vcpu, int exception_index)
 		kvm_handle_guest_serror(vcpu, kvm_vcpu_get_esr(vcpu));
 }
 
-/*
- * kvm_nvhe_dump_backtrace_entry - Symbolize and print an nVHE backtrace entry
- *
- * @arg    : the hypervisor offset, used for address translation
- * @where  : the program counter corresponding to the stack frame
- */
-static bool kvm_nvhe_dump_backtrace_entry(void *arg, unsigned long where)
-{
-	unsigned long va_mask = GENMASK_ULL(vabits_actual - 1, 0);
-	unsigned long hyp_offset = (unsigned long)arg;
-
-	/* Mask tags and convert to kern addr */
-	where = (where & va_mask) + hyp_offset;
-	kvm_err(" [<%016lx>] %pB\n", where, (void *)(where + kaslr_offset()));
-
-	return true;
-}
-
-static inline void kvm_nvhe_dump_backtrace_start(void)
-{
-	kvm_err("nVHE call trace:\n");
-}
-
-static inline void kvm_nvhe_dump_backtrace_end(void)
-{
-	kvm_err("---[ end nVHE call trace ]---\n");
-}
-
-/*
- * hyp_dump_backtrace - Dump the non-protected nVHE backtrace.
- *
- * @hyp_offset: hypervisor offset, used for address translation.
- *
- * The host can directly access HYP stack pages in non-protected
- * mode, so the unwinding is done directly from EL1. This removes
- * the need for shared buffers between host and hypervisor for
- * the stacktrace.
- */
-static void hyp_dump_backtrace(unsigned long hyp_offset)
-{
-	struct kvm_nvhe_stacktrace_info *stacktrace_info;
-	struct unwind_state state;
-
-	stacktrace_info = this_cpu_ptr_nvhe_sym(kvm_stacktrace_info);
-
-	kvm_nvhe_unwind_init(&state, stacktrace_info->fp, stacktrace_info->pc);
-
-	kvm_nvhe_dump_backtrace_start();
-	unwind(&state, kvm_nvhe_dump_backtrace_entry, (void *)hyp_offset);
-	kvm_nvhe_dump_backtrace_end();
-}
-
-#ifdef CONFIG_PROTECTED_NVHE_STACKTRACE
-DECLARE_KVM_NVHE_PER_CPU(unsigned long [NVHE_STACKTRACE_SIZE/sizeof(long)],
-			 pkvm_stacktrace);
-
-/*
- * pkvm_dump_backtrace - Dump the protected nVHE HYP backtrace.
- *
- * @hyp_offset: hypervisor offset, used for address translation.
- *
- * Dumping of the pKVM HYP backtrace is done by reading the
- * stack addresses from the shared stacktrace buffer, since the
- * host cannot directly access hypervisor memory in protected
- * mode.
- */
-static void pkvm_dump_backtrace(unsigned long hyp_offset)
-{
-	unsigned long *stacktrace
-		= (unsigned long *) this_cpu_ptr_nvhe_sym(pkvm_stacktrace);
-	int i, size = NVHE_STACKTRACE_SIZE / sizeof(long);
-
-	kvm_nvhe_dump_backtrace_start();
-	/* The saved stacktrace is terminated by a null entry */
-	for (i = 0; i < size && stacktrace[i]; i++)
-		kvm_nvhe_dump_backtrace_entry((void *)hyp_offset, stacktrace[i]);
-	kvm_nvhe_dump_backtrace_end();
-}
-#else	/* !CONFIG_PROTECTED_NVHE_STACKTRACE */
-static void pkvm_dump_backtrace(unsigned long hyp_offset)
-{
-	kvm_err("Cannot dump pKVM nVHE stacktrace: !CONFIG_PROTECTED_NVHE_STACKTRACE\n");
-}
-#endif /* CONFIG_PROTECTED_NVHE_STACKTRACE */
-
-/*
- * kvm_nvhe_dump_backtrace - Dump KVM nVHE hypervisor backtrace.
- *
- * @hyp_offset: hypervisor offset, used for address translation.
- */
-static void kvm_nvhe_dump_backtrace(unsigned long hyp_offset)
-{
-	if (is_protected_kvm_enabled())
-		pkvm_dump_backtrace(hyp_offset);
-	else
-		hyp_dump_backtrace(hyp_offset);
-}
-
 void __noreturn __cold nvhe_hyp_panic_handler(u64 esr, u64 spsr,
 					      u64 elr_virt, u64 elr_phys,
 					      u64 par, uintptr_t vcpu,
diff --git a/arch/arm64/kvm/stacktrace.c b/arch/arm64/kvm/stacktrace.c
new file mode 100644
index 000000000000..9812aefdcfb4
--- /dev/null
+++ b/arch/arm64/kvm/stacktrace.c
@@ -0,0 +1,120 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * KVM nVHE hypervisor stack tracing support.
+ *
+ * The unwinder implementation depends on the nVHE mode:
+ *
+ *   1) Non-protected nVHE mode - the host can directly access the
+ *      HYP stack pages and unwind the HYP stack in EL1. This saves having
+ *      to allocate shared buffers for the host to read the unwinded
+ *      stacktrace.
+ *
+ *   2) pKVM (protected nVHE) mode - the host cannot directly access
+ *      the HYP memory. The stack is unwinded in EL2 and dumped to a shared
+ *      buffer where the host can read and print the stacktrace.
+ *
+ * Copyright (C) 2022 Google LLC
+ */
+
+#include <linux/kvm.h>
+#include <linux/kvm_host.h>
+
+#include <asm/stacktrace/nvhe.h>
+
+/*
+ * kvm_nvhe_dump_backtrace_entry - Symbolize and print an nVHE backtrace entry
+ *
+ * @arg    : the hypervisor offset, used for address translation
+ * @where  : the program counter corresponding to the stack frame
+ */
+static bool kvm_nvhe_dump_backtrace_entry(void *arg, unsigned long where)
+{
+	unsigned long va_mask = GENMASK_ULL(vabits_actual - 1, 0);
+	unsigned long hyp_offset = (unsigned long)arg;
+
+	/* Mask tags and convert to kern addr */
+	where = (where & va_mask) + hyp_offset;
+	kvm_err(" [<%016lx>] %pB\n", where, (void *)(where + kaslr_offset()));
+
+	return true;
+}
+
+static void kvm_nvhe_dump_backtrace_start(void)
+{
+	kvm_err("nVHE call trace:\n");
+}
+
+static void kvm_nvhe_dump_backtrace_end(void)
+{
+	kvm_err("---[ end nVHE call trace ]---\n");
+}
+
+/*
+ * hyp_dump_backtrace - Dump the non-protected nVHE backtrace.
+ *
+ * @hyp_offset: hypervisor offset, used for address translation.
+ *
+ * The host can directly access HYP stack pages in non-protected
+ * mode, so the unwinding is done directly from EL1. This removes
+ * the need for shared buffers between host and hypervisor for
+ * the stacktrace.
+ */
+static void hyp_dump_backtrace(unsigned long hyp_offset)
+{
+	struct kvm_nvhe_stacktrace_info *stacktrace_info;
+	struct unwind_state state;
+
+	stacktrace_info = this_cpu_ptr_nvhe_sym(kvm_stacktrace_info);
+
+	kvm_nvhe_unwind_init(&state, stacktrace_info->fp, stacktrace_info->pc);
+
+	kvm_nvhe_dump_backtrace_start();
+	unwind(&state, kvm_nvhe_dump_backtrace_entry, (void *)hyp_offset);
+	kvm_nvhe_dump_backtrace_end();
+}
+
+#ifdef CONFIG_PROTECTED_NVHE_STACKTRACE
+DECLARE_KVM_NVHE_PER_CPU(unsigned long [NVHE_STACKTRACE_SIZE/sizeof(long)],
+			 pkvm_stacktrace);
+
+/*
+ * pkvm_dump_backtrace - Dump the protected nVHE HYP backtrace.
+ *
+ * @hyp_offset: hypervisor offset, used for address translation.
+ *
+ * Dumping of the pKVM HYP backtrace is done by reading the
+ * stack addresses from the shared stacktrace buffer, since the
+ * host cannot directly access hypervisor memory in protected
+ * mode.
+ */
+static void pkvm_dump_backtrace(unsigned long hyp_offset)
+{
+	unsigned long *stacktrace
+		= (unsigned long *) this_cpu_ptr_nvhe_sym(pkvm_stacktrace);
+	int i, size = NVHE_STACKTRACE_SIZE / sizeof(long);
+
+	kvm_nvhe_dump_backtrace_start();
+	/* The saved stacktrace is terminated by a null entry */
+	for (i = 0; i < size && stacktrace[i]; i++)
+		kvm_nvhe_dump_backtrace_entry((void *)hyp_offset, stacktrace[i]);
+	kvm_nvhe_dump_backtrace_end();
+}
+#else	/* !CONFIG_PROTECTED_NVHE_STACKTRACE */
+static void pkvm_dump_backtrace(unsigned long hyp_offset)
+{
+	kvm_err("Cannot dump pKVM nVHE stacktrace: !CONFIG_PROTECTED_NVHE_STACKTRACE\n");
+}
+#endif /* CONFIG_PROTECTED_NVHE_STACKTRACE */
+
+/*
+ * kvm_nvhe_dump_backtrace - Dump KVM nVHE hypervisor backtrace.
+ *
+ * @hyp_offset: hypervisor offset, used for address translation.
+ */
+void kvm_nvhe_dump_backtrace(unsigned long hyp_offset)
+{
+	if (is_protected_kvm_enabled())
+		pkvm_dump_backtrace(hyp_offset);
+	else
+		hyp_dump_backtrace(hyp_offset);
+}
-- 
2.34.1

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply related	[flat|nested] 112+ messages in thread

* [PATCH 2/6] KVM: arm64: Move nVHE stacktrace unwinding into its own compilation unit
@ 2022-07-27 14:29       ` Marc Zyngier
  0 siblings, 0 replies; 112+ messages in thread
From: Marc Zyngier @ 2022-07-27 14:29 UTC (permalink / raw)
  To: linux-arm-kernel, kvmarm, kvm
  Cc: mark.rutland, broonie, madvenka, tabba, oliver.upton, qperret,
	kaleshsingh, james.morse, alexandru.elisei, suzuki.poulose,
	catalin.marinas, andreyknvl, vincenzo.frascino, mhiramat, ast,
	wangkefeng.wang, elver, keirf, yuzenghui, ardb, oupton,
	kernel-team

The unwinding code doesn't really belong to the exit handling
code. Instead, move it to a file (conveniently named stacktrace.c
to confuse the reviewer), and move all the stacktrace-related
stuff there.

It will be joined by more code very soon.

Signed-off-by: Marc Zyngier <maz@kernel.org>
---
 arch/arm64/include/asm/stacktrace/nvhe.h |   2 +
 arch/arm64/kvm/Makefile                  |   2 +-
 arch/arm64/kvm/handle_exit.c             |  98 ------------------
 arch/arm64/kvm/stacktrace.c              | 120 +++++++++++++++++++++++
 4 files changed, 123 insertions(+), 99 deletions(-)
 create mode 100644 arch/arm64/kvm/stacktrace.c

diff --git a/arch/arm64/include/asm/stacktrace/nvhe.h b/arch/arm64/include/asm/stacktrace/nvhe.h
index 600dbc2220b6..8a5cb96d7143 100644
--- a/arch/arm64/include/asm/stacktrace/nvhe.h
+++ b/arch/arm64/include/asm/stacktrace/nvhe.h
@@ -172,5 +172,7 @@ static inline int notrace unwind_next(struct unwind_state *state)
 }
 NOKPROBE_SYMBOL(unwind_next);
 
+void kvm_nvhe_dump_backtrace(unsigned long hyp_offset);
+
 #endif	/* __KVM_NVHE_HYPERVISOR__ */
 #endif	/* __ASM_STACKTRACE_NVHE_H */
diff --git a/arch/arm64/kvm/Makefile b/arch/arm64/kvm/Makefile
index aa127ae9f675..5e33c2d4645a 100644
--- a/arch/arm64/kvm/Makefile
+++ b/arch/arm64/kvm/Makefile
@@ -12,7 +12,7 @@ obj-$(CONFIG_KVM) += hyp/
 
 kvm-y += arm.o mmu.o mmio.o psci.o hypercalls.o pvtime.o \
 	 inject_fault.o va_layout.o handle_exit.o \
-	 guest.o debug.o reset.o sys_regs.o \
+	 guest.o debug.o reset.o sys_regs.o stacktrace.o \
 	 vgic-sys-reg-v3.o fpsimd.o pkvm.o \
 	 arch_timer.o trng.o vmid.o \
 	 vgic/vgic.o vgic/vgic-init.o \
diff --git a/arch/arm64/kvm/handle_exit.c b/arch/arm64/kvm/handle_exit.c
index c14fc4ba4422..ef8b57953aa2 100644
--- a/arch/arm64/kvm/handle_exit.c
+++ b/arch/arm64/kvm/handle_exit.c
@@ -319,104 +319,6 @@ void handle_exit_early(struct kvm_vcpu *vcpu, int exception_index)
 		kvm_handle_guest_serror(vcpu, kvm_vcpu_get_esr(vcpu));
 }
 
-/*
- * kvm_nvhe_dump_backtrace_entry - Symbolize and print an nVHE backtrace entry
- *
- * @arg    : the hypervisor offset, used for address translation
- * @where  : the program counter corresponding to the stack frame
- */
-static bool kvm_nvhe_dump_backtrace_entry(void *arg, unsigned long where)
-{
-	unsigned long va_mask = GENMASK_ULL(vabits_actual - 1, 0);
-	unsigned long hyp_offset = (unsigned long)arg;
-
-	/* Mask tags and convert to kern addr */
-	where = (where & va_mask) + hyp_offset;
-	kvm_err(" [<%016lx>] %pB\n", where, (void *)(where + kaslr_offset()));
-
-	return true;
-}
-
-static inline void kvm_nvhe_dump_backtrace_start(void)
-{
-	kvm_err("nVHE call trace:\n");
-}
-
-static inline void kvm_nvhe_dump_backtrace_end(void)
-{
-	kvm_err("---[ end nVHE call trace ]---\n");
-}
-
-/*
- * hyp_dump_backtrace - Dump the non-protected nVHE backtrace.
- *
- * @hyp_offset: hypervisor offset, used for address translation.
- *
- * The host can directly access HYP stack pages in non-protected
- * mode, so the unwinding is done directly from EL1. This removes
- * the need for shared buffers between host and hypervisor for
- * the stacktrace.
- */
-static void hyp_dump_backtrace(unsigned long hyp_offset)
-{
-	struct kvm_nvhe_stacktrace_info *stacktrace_info;
-	struct unwind_state state;
-
-	stacktrace_info = this_cpu_ptr_nvhe_sym(kvm_stacktrace_info);
-
-	kvm_nvhe_unwind_init(&state, stacktrace_info->fp, stacktrace_info->pc);
-
-	kvm_nvhe_dump_backtrace_start();
-	unwind(&state, kvm_nvhe_dump_backtrace_entry, (void *)hyp_offset);
-	kvm_nvhe_dump_backtrace_end();
-}
-
-#ifdef CONFIG_PROTECTED_NVHE_STACKTRACE
-DECLARE_KVM_NVHE_PER_CPU(unsigned long [NVHE_STACKTRACE_SIZE/sizeof(long)],
-			 pkvm_stacktrace);
-
-/*
- * pkvm_dump_backtrace - Dump the protected nVHE HYP backtrace.
- *
- * @hyp_offset: hypervisor offset, used for address translation.
- *
- * Dumping of the pKVM HYP backtrace is done by reading the
- * stack addresses from the shared stacktrace buffer, since the
- * host cannot directly access hypervisor memory in protected
- * mode.
- */
-static void pkvm_dump_backtrace(unsigned long hyp_offset)
-{
-	unsigned long *stacktrace
-		= (unsigned long *) this_cpu_ptr_nvhe_sym(pkvm_stacktrace);
-	int i, size = NVHE_STACKTRACE_SIZE / sizeof(long);
-
-	kvm_nvhe_dump_backtrace_start();
-	/* The saved stacktrace is terminated by a null entry */
-	for (i = 0; i < size && stacktrace[i]; i++)
-		kvm_nvhe_dump_backtrace_entry((void *)hyp_offset, stacktrace[i]);
-	kvm_nvhe_dump_backtrace_end();
-}
-#else	/* !CONFIG_PROTECTED_NVHE_STACKTRACE */
-static void pkvm_dump_backtrace(unsigned long hyp_offset)
-{
-	kvm_err("Cannot dump pKVM nVHE stacktrace: !CONFIG_PROTECTED_NVHE_STACKTRACE\n");
-}
-#endif /* CONFIG_PROTECTED_NVHE_STACKTRACE */
-
-/*
- * kvm_nvhe_dump_backtrace - Dump KVM nVHE hypervisor backtrace.
- *
- * @hyp_offset: hypervisor offset, used for address translation.
- */
-static void kvm_nvhe_dump_backtrace(unsigned long hyp_offset)
-{
-	if (is_protected_kvm_enabled())
-		pkvm_dump_backtrace(hyp_offset);
-	else
-		hyp_dump_backtrace(hyp_offset);
-}
-
 void __noreturn __cold nvhe_hyp_panic_handler(u64 esr, u64 spsr,
 					      u64 elr_virt, u64 elr_phys,
 					      u64 par, uintptr_t vcpu,
diff --git a/arch/arm64/kvm/stacktrace.c b/arch/arm64/kvm/stacktrace.c
new file mode 100644
index 000000000000..9812aefdcfb4
--- /dev/null
+++ b/arch/arm64/kvm/stacktrace.c
@@ -0,0 +1,120 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * KVM nVHE hypervisor stack tracing support.
+ *
+ * The unwinder implementation depends on the nVHE mode:
+ *
+ *   1) Non-protected nVHE mode - the host can directly access the
+ *      HYP stack pages and unwind the HYP stack in EL1. This saves having
+ *      to allocate shared buffers for the host to read the unwinded
+ *      stacktrace.
+ *
+ *   2) pKVM (protected nVHE) mode - the host cannot directly access
+ *      the HYP memory. The stack is unwinded in EL2 and dumped to a shared
+ *      buffer where the host can read and print the stacktrace.
+ *
+ * Copyright (C) 2022 Google LLC
+ */
+
+#include <linux/kvm.h>
+#include <linux/kvm_host.h>
+
+#include <asm/stacktrace/nvhe.h>
+
+/*
+ * kvm_nvhe_dump_backtrace_entry - Symbolize and print an nVHE backtrace entry
+ *
+ * @arg    : the hypervisor offset, used for address translation
+ * @where  : the program counter corresponding to the stack frame
+ */
+static bool kvm_nvhe_dump_backtrace_entry(void *arg, unsigned long where)
+{
+	unsigned long va_mask = GENMASK_ULL(vabits_actual - 1, 0);
+	unsigned long hyp_offset = (unsigned long)arg;
+
+	/* Mask tags and convert to kern addr */
+	where = (where & va_mask) + hyp_offset;
+	kvm_err(" [<%016lx>] %pB\n", where, (void *)(where + kaslr_offset()));
+
+	return true;
+}
+
+static void kvm_nvhe_dump_backtrace_start(void)
+{
+	kvm_err("nVHE call trace:\n");
+}
+
+static void kvm_nvhe_dump_backtrace_end(void)
+{
+	kvm_err("---[ end nVHE call trace ]---\n");
+}
+
+/*
+ * hyp_dump_backtrace - Dump the non-protected nVHE backtrace.
+ *
+ * @hyp_offset: hypervisor offset, used for address translation.
+ *
+ * The host can directly access HYP stack pages in non-protected
+ * mode, so the unwinding is done directly from EL1. This removes
+ * the need for shared buffers between host and hypervisor for
+ * the stacktrace.
+ */
+static void hyp_dump_backtrace(unsigned long hyp_offset)
+{
+	struct kvm_nvhe_stacktrace_info *stacktrace_info;
+	struct unwind_state state;
+
+	stacktrace_info = this_cpu_ptr_nvhe_sym(kvm_stacktrace_info);
+
+	kvm_nvhe_unwind_init(&state, stacktrace_info->fp, stacktrace_info->pc);
+
+	kvm_nvhe_dump_backtrace_start();
+	unwind(&state, kvm_nvhe_dump_backtrace_entry, (void *)hyp_offset);
+	kvm_nvhe_dump_backtrace_end();
+}
+
+#ifdef CONFIG_PROTECTED_NVHE_STACKTRACE
+DECLARE_KVM_NVHE_PER_CPU(unsigned long [NVHE_STACKTRACE_SIZE/sizeof(long)],
+			 pkvm_stacktrace);
+
+/*
+ * pkvm_dump_backtrace - Dump the protected nVHE HYP backtrace.
+ *
+ * @hyp_offset: hypervisor offset, used for address translation.
+ *
+ * Dumping of the pKVM HYP backtrace is done by reading the
+ * stack addresses from the shared stacktrace buffer, since the
+ * host cannot directly access hypervisor memory in protected
+ * mode.
+ */
+static void pkvm_dump_backtrace(unsigned long hyp_offset)
+{
+	unsigned long *stacktrace
+		= (unsigned long *) this_cpu_ptr_nvhe_sym(pkvm_stacktrace);
+	int i, size = NVHE_STACKTRACE_SIZE / sizeof(long);
+
+	kvm_nvhe_dump_backtrace_start();
+	/* The saved stacktrace is terminated by a null entry */
+	for (i = 0; i < size && stacktrace[i]; i++)
+		kvm_nvhe_dump_backtrace_entry((void *)hyp_offset, stacktrace[i]);
+	kvm_nvhe_dump_backtrace_end();
+}
+#else	/* !CONFIG_PROTECTED_NVHE_STACKTRACE */
+static void pkvm_dump_backtrace(unsigned long hyp_offset)
+{
+	kvm_err("Cannot dump pKVM nVHE stacktrace: !CONFIG_PROTECTED_NVHE_STACKTRACE\n");
+}
+#endif /* CONFIG_PROTECTED_NVHE_STACKTRACE */
+
+/*
+ * kvm_nvhe_dump_backtrace - Dump KVM nVHE hypervisor backtrace.
+ *
+ * @hyp_offset: hypervisor offset, used for address translation.
+ */
+void kvm_nvhe_dump_backtrace(unsigned long hyp_offset)
+{
+	if (is_protected_kvm_enabled())
+		pkvm_dump_backtrace(hyp_offset);
+	else
+		hyp_dump_backtrace(hyp_offset);
+}
-- 
2.34.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 112+ messages in thread

* [PATCH 3/6] KVM: arm64: Make unwind()/on_accessible_stack() per-unwinder functions
  2022-07-27 14:29     ` Marc Zyngier
  (?)
@ 2022-07-27 14:29       ` Marc Zyngier
  -1 siblings, 0 replies; 112+ messages in thread
From: Marc Zyngier @ 2022-07-27 14:29 UTC (permalink / raw)
  To: linux-arm-kernel, kvmarm, kvm
  Cc: mark.rutland, broonie, madvenka, tabba, oliver.upton, qperret,
	kaleshsingh, james.morse, alexandru.elisei, suzuki.poulose,
	catalin.marinas, andreyknvl, vincenzo.frascino, mhiramat, ast,
	wangkefeng.wang, elver, keirf, yuzenghui, ardb, oupton,
	kernel-team

Having multiple versions of on_accessible_stack() (one per unwinder)
makes it very hard to reason about what is used where due to the
complexity of the various includes, the forward declarations, and
the reliance on everything being 'inline'.

Instead, move the code back where it should be. Each unwinder
implements:

- on_accessible_stack() as well as the helpers it depends on,

- unwind()/unwind_next(), as they pass on_accessible_stack as
  a parameter to unwind_next_common() (which is the only common
  code here)

This hardly results in any duplication, and makes it much
easier to reason about the code.

Signed-off-by: Marc Zyngier <maz@kernel.org>
---
 arch/arm64/include/asm/stacktrace.h        | 74 ------------------
 arch/arm64/include/asm/stacktrace/common.h | 55 ++++---------
 arch/arm64/include/asm/stacktrace/nvhe.h   | 84 +-------------------
 arch/arm64/kernel/stacktrace.c             | 90 ++++++++++++++++++++++
 arch/arm64/kvm/hyp/nvhe/stacktrace.c       | 52 +++++++++++++
 arch/arm64/kvm/stacktrace.c                | 55 +++++++++++++
 6 files changed, 213 insertions(+), 197 deletions(-)

diff --git a/arch/arm64/include/asm/stacktrace.h b/arch/arm64/include/asm/stacktrace.h
index ea828579a98b..6ebdcdff77f5 100644
--- a/arch/arm64/include/asm/stacktrace.h
+++ b/arch/arm64/include/asm/stacktrace.h
@@ -57,78 +57,4 @@ static inline bool on_overflow_stack(unsigned long sp, unsigned long size,
 			struct stack_info *info) { return false; }
 #endif
 
-
-/*
- * We can only safely access per-cpu stacks from current in a non-preemptible
- * context.
- */
-static inline bool on_accessible_stack(const struct task_struct *tsk,
-				       unsigned long sp, unsigned long size,
-				       struct stack_info *info)
-{
-	if (on_accessible_stack_common(tsk, sp, size, info))
-		return true;
-
-	if (on_task_stack(tsk, sp, size, info))
-		return true;
-	if (tsk != current || preemptible())
-		return false;
-	if (on_irq_stack(sp, size, info))
-		return true;
-	if (on_sdei_stack(sp, size, info))
-		return true;
-
-	return false;
-}
-
-/*
- * Unwind from one frame record (A) to the next frame record (B).
- *
- * We terminate early if the location of B indicates a malformed chain of frame
- * records (e.g. a cycle), determined based on the location and fp value of A
- * and the location (but not the fp value) of B.
- */
-static inline int notrace unwind_next(struct unwind_state *state)
-{
-	struct task_struct *tsk = state->task;
-	unsigned long fp = state->fp;
-	struct stack_info info;
-	int err;
-
-	/* Final frame; nothing to unwind */
-	if (fp == (unsigned long)task_pt_regs(tsk)->stackframe)
-		return -ENOENT;
-
-	err = unwind_next_common(state, &info, NULL);
-	if (err)
-		return err;
-
-	state->pc = ptrauth_strip_insn_pac(state->pc);
-
-#ifdef CONFIG_FUNCTION_GRAPH_TRACER
-	if (tsk->ret_stack &&
-		(state->pc == (unsigned long)return_to_handler)) {
-		unsigned long orig_pc;
-		/*
-		 * This is a case where function graph tracer has
-		 * modified a return address (LR) in a stack frame
-		 * to hook a function return.
-		 * So replace it to an original value.
-		 */
-		orig_pc = ftrace_graph_ret_addr(tsk, NULL, state->pc,
-						(void *)state->fp);
-		if (WARN_ON_ONCE(state->pc == orig_pc))
-			return -EINVAL;
-		state->pc = orig_pc;
-	}
-#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
-#ifdef CONFIG_KRETPROBES
-	if (is_kretprobe_trampoline(state->pc))
-		state->pc = kretprobe_find_ret_addr(tsk, (void *)state->fp, &state->kr_cur);
-#endif
-
-	return 0;
-}
-NOKPROBE_SYMBOL(unwind_next);
-
 #endif	/* __ASM_STACKTRACE_H */
diff --git a/arch/arm64/include/asm/stacktrace/common.h b/arch/arm64/include/asm/stacktrace/common.h
index 3ebb69ea374a..18046a7248a2 100644
--- a/arch/arm64/include/asm/stacktrace/common.h
+++ b/arch/arm64/include/asm/stacktrace/common.h
@@ -79,15 +79,6 @@ struct unwind_state {
 	struct task_struct *task;
 };
 
-static inline bool on_overflow_stack(unsigned long sp, unsigned long size,
-				     struct stack_info *info);
-
-static inline bool on_accessible_stack(const struct task_struct *tsk,
-				       unsigned long sp, unsigned long size,
-				       struct stack_info *info);
-
-static inline int unwind_next(struct unwind_state *state);
-
 static inline bool on_stack(unsigned long sp, unsigned long size,
 			    unsigned long low, unsigned long high,
 			    enum stack_type type, struct stack_info *info)
@@ -106,21 +97,6 @@ static inline bool on_stack(unsigned long sp, unsigned long size,
 	return true;
 }
 
-static inline bool on_accessible_stack_common(const struct task_struct *tsk,
-					      unsigned long sp,
-					      unsigned long size,
-					      struct stack_info *info)
-{
-	if (info)
-		info->type = STACK_TYPE_UNKNOWN;
-
-	/*
-	 * Both the kernel and nvhe hypervisor make use of
-	 * an overflow_stack
-	 */
-	return on_overflow_stack(sp, size, info);
-}
-
 static inline void unwind_init_common(struct unwind_state *state,
 				      struct task_struct *task)
 {
@@ -156,8 +132,22 @@ static inline void unwind_init_common(struct unwind_state *state,
 typedef bool (*stack_trace_translate_fp_fn)(unsigned long *fp,
 					    enum stack_type type);
 
+/*
+ * on_accessible_stack_fn() - Check whether a stack range is on any
+ * of the possible stacks.
+ *
+ * @tsk:  task whose stack is being unwound
+ * @sp:   stack address being checked
+ * @size: size of the stack range being checked
+ * @info: stack unwinding context
+ */
+typedef bool (*on_accessible_stack_fn)(const struct task_struct *tsk,
+				       unsigned long sp, unsigned long size,
+				       struct stack_info *info);
+
 static inline int unwind_next_common(struct unwind_state *state,
 				     struct stack_info *info,
+				     on_accessible_stack_fn accessible,
 				     stack_trace_translate_fp_fn translate_fp)
 {
 	unsigned long fp = state->fp, kern_fp = fp;
@@ -166,7 +156,7 @@ static inline int unwind_next_common(struct unwind_state *state,
 	if (fp & 0x7)
 		return -EINVAL;
 
-	if (!on_accessible_stack(tsk, fp, 16, info))
+	if (!accessible(tsk, fp, 16, info))
 		return -EINVAL;
 
 	if (test_bit(info->type, state->stacks_done))
@@ -212,19 +202,4 @@ static inline int unwind_next_common(struct unwind_state *state,
 	return 0;
 }
 
-static inline void notrace unwind(struct unwind_state *state,
-				  stack_trace_consume_fn consume_entry,
-				  void *cookie)
-{
-	while (1) {
-		int ret;
-
-		if (!consume_entry(cookie, state->pc))
-			break;
-		ret = unwind_next(state);
-		if (ret < 0)
-			break;
-	}
-}
-NOKPROBE_SYMBOL(unwind);
 #endif	/* __ASM_STACKTRACE_COMMON_H */
diff --git a/arch/arm64/include/asm/stacktrace/nvhe.h b/arch/arm64/include/asm/stacktrace/nvhe.h
index 8a5cb96d7143..a096216d8970 100644
--- a/arch/arm64/include/asm/stacktrace/nvhe.h
+++ b/arch/arm64/include/asm/stacktrace/nvhe.h
@@ -37,59 +37,7 @@ static inline void kvm_nvhe_unwind_init(struct unwind_state *state,
 	state->pc = pc;
 }
 
-static inline bool on_hyp_stack(unsigned long sp, unsigned long size,
-				struct stack_info *info);
-
-static inline bool on_accessible_stack(const struct task_struct *tsk,
-				       unsigned long sp, unsigned long size,
-				       struct stack_info *info)
-{
-	if (on_accessible_stack_common(tsk, sp, size, info))
-		return true;
-
-	if (on_hyp_stack(sp, size, info))
-		return true;
-
-	return false;
-}
-
-#ifdef __KVM_NVHE_HYPERVISOR__
-/*
- * Protected nVHE HYP stack unwinder
- *
- * In protected mode, the unwinding is done by the hypervisor in EL2.
- */
-
-#ifdef CONFIG_PROTECTED_NVHE_STACKTRACE
-static inline bool on_overflow_stack(unsigned long sp, unsigned long size,
-				     struct stack_info *info)
-{
-	unsigned long low = (unsigned long)this_cpu_ptr(overflow_stack);
-	unsigned long high = low + OVERFLOW_STACK_SIZE;
-
-	return on_stack(sp, size, low, high, STACK_TYPE_OVERFLOW, info);
-}
-
-static inline bool on_hyp_stack(unsigned long sp, unsigned long size,
-				struct stack_info *info)
-{
-	struct kvm_nvhe_init_params *params = this_cpu_ptr(&kvm_init_params);
-	unsigned long high = params->stack_hyp_va;
-	unsigned long low = high - PAGE_SIZE;
-
-	return on_stack(sp, size, low, high, STACK_TYPE_HYP, info);
-}
-
-static inline int notrace unwind_next(struct unwind_state *state)
-{
-	struct stack_info info;
-
-	return unwind_next_common(state, &info, NULL);
-}
-NOKPROBE_SYMBOL(unwind_next);
-#endif	/* CONFIG_PROTECTED_NVHE_STACKTRACE */
-
-#else	/* !__KVM_NVHE_HYPERVISOR__ */
+#ifndef __KVM_NVHE_HYPERVISOR__
 /*
  * Conventional (non-protected) nVHE HYP stack unwinder
  *
@@ -142,36 +90,6 @@ static inline bool kvm_nvhe_stack_kern_va(unsigned long *addr,
 	return true;
 }
 
-static inline bool on_overflow_stack(unsigned long sp, unsigned long size,
-				     struct stack_info *info)
-{
-	struct kvm_nvhe_stacktrace_info *stacktrace_info
-				= this_cpu_ptr_nvhe_sym(kvm_stacktrace_info);
-	unsigned long low = (unsigned long)stacktrace_info->overflow_stack_base;
-	unsigned long high = low + OVERFLOW_STACK_SIZE;
-
-	return on_stack(sp, size, low, high, STACK_TYPE_OVERFLOW, info);
-}
-
-static inline bool on_hyp_stack(unsigned long sp, unsigned long size,
-				struct stack_info *info)
-{
-	struct kvm_nvhe_stacktrace_info *stacktrace_info
-				= this_cpu_ptr_nvhe_sym(kvm_stacktrace_info);
-	unsigned long low = (unsigned long)stacktrace_info->stack_base;
-	unsigned long high = low + PAGE_SIZE;
-
-	return on_stack(sp, size, low, high, STACK_TYPE_HYP, info);
-}
-
-static inline int notrace unwind_next(struct unwind_state *state)
-{
-	struct stack_info info;
-
-	return unwind_next_common(state, &info, kvm_nvhe_stack_kern_va);
-}
-NOKPROBE_SYMBOL(unwind_next);
-
 void kvm_nvhe_dump_backtrace(unsigned long hyp_offset);
 
 #endif	/* __KVM_NVHE_HYPERVISOR__ */
diff --git a/arch/arm64/kernel/stacktrace.c b/arch/arm64/kernel/stacktrace.c
index 9fa60ee48499..ce190ee18a20 100644
--- a/arch/arm64/kernel/stacktrace.c
+++ b/arch/arm64/kernel/stacktrace.c
@@ -67,6 +67,96 @@ static inline void unwind_init_from_task(struct unwind_state *state,
 	state->pc = thread_saved_pc(task);
 }
 
+/*
+ * We can only safely access per-cpu stacks from current in a non-preemptible
+ * context.
+ */
+static bool on_accessible_stack(const struct task_struct *tsk,
+				unsigned long sp, unsigned long size,
+				struct stack_info *info)
+{
+	if (info)
+		info->type = STACK_TYPE_UNKNOWN;
+
+	if (on_task_stack(tsk, sp, size, info))
+		return true;
+	if (tsk != current || preemptible())
+		return false;
+	if (on_irq_stack(sp, size, info))
+		return true;
+	if (on_overflow_stack(sp, size, info))
+		return true;
+	if (on_sdei_stack(sp, size, info))
+		return true;
+
+	return false;
+}
+
+/*
+ * Unwind from one frame record (A) to the next frame record (B).
+ *
+ * We terminate early if the location of B indicates a malformed chain of frame
+ * records (e.g. a cycle), determined based on the location and fp value of A
+ * and the location (but not the fp value) of B.
+ */
+static int notrace unwind_next(struct unwind_state *state)
+{
+	struct task_struct *tsk = state->task;
+	unsigned long fp = state->fp;
+	struct stack_info info;
+	int err;
+
+	/* Final frame; nothing to unwind */
+	if (fp == (unsigned long)task_pt_regs(tsk)->stackframe)
+		return -ENOENT;
+
+	err = unwind_next_common(state, &info, on_accessible_stack, NULL);
+	if (err)
+		return err;
+
+	state->pc = ptrauth_strip_insn_pac(state->pc);
+
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+	if (tsk->ret_stack &&
+		(state->pc == (unsigned long)return_to_handler)) {
+		unsigned long orig_pc;
+		/*
+		 * This is a case where function graph tracer has
+		 * modified a return address (LR) in a stack frame
+		 * to hook a function return.
+		 * So replace it to an original value.
+		 */
+		orig_pc = ftrace_graph_ret_addr(tsk, NULL, state->pc,
+						(void *)state->fp);
+		if (WARN_ON_ONCE(state->pc == orig_pc))
+			return -EINVAL;
+		state->pc = orig_pc;
+	}
+#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
+#ifdef CONFIG_KRETPROBES
+	if (is_kretprobe_trampoline(state->pc))
+		state->pc = kretprobe_find_ret_addr(tsk, (void *)state->fp, &state->kr_cur);
+#endif
+
+	return 0;
+}
+NOKPROBE_SYMBOL(unwind_next);
+
+static void notrace unwind(struct unwind_state *state,
+			   stack_trace_consume_fn consume_entry, void *cookie)
+{
+	while (1) {
+		int ret;
+
+		if (!consume_entry(cookie, state->pc))
+			break;
+		ret = unwind_next(state);
+		if (ret < 0)
+			break;
+	}
+}
+NOKPROBE_SYMBOL(unwind);
+
 static bool dump_backtrace_entry(void *arg, unsigned long where)
 {
 	char *loglvl = arg;
diff --git a/arch/arm64/kvm/hyp/nvhe/stacktrace.c b/arch/arm64/kvm/hyp/nvhe/stacktrace.c
index 900324b7a08f..acbe272ecb32 100644
--- a/arch/arm64/kvm/hyp/nvhe/stacktrace.c
+++ b/arch/arm64/kvm/hyp/nvhe/stacktrace.c
@@ -39,6 +39,58 @@ static void hyp_prepare_backtrace(unsigned long fp, unsigned long pc)
 
 DEFINE_PER_CPU(unsigned long [NVHE_STACKTRACE_SIZE/sizeof(long)], pkvm_stacktrace);
 
+static bool on_overflow_stack(unsigned long sp, unsigned long size,
+			      struct stack_info *info)
+{
+	unsigned long low = (unsigned long)this_cpu_ptr(overflow_stack);
+	unsigned long high = low + OVERFLOW_STACK_SIZE;
+
+	return on_stack(sp, size, low, high, STACK_TYPE_OVERFLOW, info);
+}
+
+static bool on_hyp_stack(unsigned long sp, unsigned long size,
+			      struct stack_info *info)
+{
+	struct kvm_nvhe_init_params *params = this_cpu_ptr(&kvm_init_params);
+	unsigned long high = params->stack_hyp_va;
+	unsigned long low = high - PAGE_SIZE;
+
+	return on_stack(sp, size, low, high, STACK_TYPE_HYP, info);
+}
+
+static bool on_accessible_stack(const struct task_struct *tsk,
+				unsigned long sp, unsigned long size,
+				struct stack_info *info)
+{
+	if (info)
+		info->type = STACK_TYPE_UNKNOWN;
+
+	return (on_overflow_stack(sp, size, info) ||
+		on_hyp_stack(sp, size, info));
+}
+
+static int unwind_next(struct unwind_state *state)
+{
+	struct stack_info info;
+
+	return unwind_next_common(state, &info, on_accessible_stack, NULL);
+}
+
+static void notrace unwind(struct unwind_state *state,
+			   stack_trace_consume_fn consume_entry,
+			   void *cookie)
+{
+	while (1) {
+		int ret;
+
+		if (!consume_entry(cookie, state->pc))
+			break;
+		ret = unwind_next(state);
+		if (ret < 0)
+			break;
+	}
+}
+
 /*
  * pkvm_save_backtrace_entry - Saves a protected nVHE HYP stacktrace entry
  *
diff --git a/arch/arm64/kvm/stacktrace.c b/arch/arm64/kvm/stacktrace.c
index 9812aefdcfb4..4d5fec3175ff 100644
--- a/arch/arm64/kvm/stacktrace.c
+++ b/arch/arm64/kvm/stacktrace.c
@@ -21,6 +21,61 @@
 
 #include <asm/stacktrace/nvhe.h>
 
+static bool on_overflow_stack(unsigned long sp, unsigned long size,
+			      struct stack_info *info)
+{
+	struct kvm_nvhe_stacktrace_info *stacktrace_info
+				= this_cpu_ptr_nvhe_sym(kvm_stacktrace_info);
+	unsigned long low = (unsigned long)stacktrace_info->overflow_stack_base;
+	unsigned long high = low + OVERFLOW_STACK_SIZE;
+
+	return on_stack(sp, size, low, high, STACK_TYPE_OVERFLOW, info);
+}
+
+static bool on_hyp_stack(unsigned long sp, unsigned long size,
+			 struct stack_info *info)
+{
+	struct kvm_nvhe_stacktrace_info *stacktrace_info
+				= this_cpu_ptr_nvhe_sym(kvm_stacktrace_info);
+	unsigned long low = (unsigned long)stacktrace_info->stack_base;
+	unsigned long high = low + PAGE_SIZE;
+
+	return on_stack(sp, size, low, high, STACK_TYPE_HYP, info);
+}
+
+static bool on_accessible_stack(const struct task_struct *tsk,
+				unsigned long sp, unsigned long size,
+				struct stack_info *info)
+{
+	if (info)
+		info->type = STACK_TYPE_UNKNOWN;
+
+	return (on_overflow_stack(sp, size, info) ||
+		on_hyp_stack(sp, size, info));
+}
+
+static int unwind_next(struct unwind_state *state)
+{
+	struct stack_info info;
+
+	return unwind_next_common(state, &info, on_accessible_stack,
+				  kvm_nvhe_stack_kern_va);
+}
+
+static void unwind(struct unwind_state *state,
+		   stack_trace_consume_fn consume_entry, void *cookie)
+{
+	while (1) {
+		int ret;
+
+		if (!consume_entry(cookie, state->pc))
+			break;
+		ret = unwind_next(state);
+		if (ret < 0)
+			break;
+	}
+}
+
 /*
  * kvm_nvhe_dump_backtrace_entry - Symbolize and print an nVHE backtrace entry
  *
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 112+ messages in thread

* [PATCH 3/6] KVM: arm64: Make unwind()/on_accessible_stack() per-unwinder functions
@ 2022-07-27 14:29       ` Marc Zyngier
  0 siblings, 0 replies; 112+ messages in thread
From: Marc Zyngier @ 2022-07-27 14:29 UTC (permalink / raw)
  To: linux-arm-kernel, kvmarm, kvm
  Cc: wangkefeng.wang, catalin.marinas, ast, vincenzo.frascino,
	madvenka, kernel-team, elver, broonie, andreyknvl, mhiramat

Having multiple versions of on_accessible_stack() (one per unwinder)
makes it very hard to reason about what is used where due to the
complexity of the various includes, the forward declarations, and
the reliance on everything being 'inline'.

Instead, move the code back where it should be. Each unwinder
implements:

- on_accessible_stack() as well as the helpers it depends on,

- unwind()/unwind_next(), as they pass on_accessible_stack as
  a parameter to unwind_next_common() (which is the only common
  code here)

This hardly results in any duplication, and makes it much
easier to reason about the code.

Signed-off-by: Marc Zyngier <maz@kernel.org>
---
 arch/arm64/include/asm/stacktrace.h        | 74 ------------------
 arch/arm64/include/asm/stacktrace/common.h | 55 ++++---------
 arch/arm64/include/asm/stacktrace/nvhe.h   | 84 +-------------------
 arch/arm64/kernel/stacktrace.c             | 90 ++++++++++++++++++++++
 arch/arm64/kvm/hyp/nvhe/stacktrace.c       | 52 +++++++++++++
 arch/arm64/kvm/stacktrace.c                | 55 +++++++++++++
 6 files changed, 213 insertions(+), 197 deletions(-)

diff --git a/arch/arm64/include/asm/stacktrace.h b/arch/arm64/include/asm/stacktrace.h
index ea828579a98b..6ebdcdff77f5 100644
--- a/arch/arm64/include/asm/stacktrace.h
+++ b/arch/arm64/include/asm/stacktrace.h
@@ -57,78 +57,4 @@ static inline bool on_overflow_stack(unsigned long sp, unsigned long size,
 			struct stack_info *info) { return false; }
 #endif
 
-
-/*
- * We can only safely access per-cpu stacks from current in a non-preemptible
- * context.
- */
-static inline bool on_accessible_stack(const struct task_struct *tsk,
-				       unsigned long sp, unsigned long size,
-				       struct stack_info *info)
-{
-	if (on_accessible_stack_common(tsk, sp, size, info))
-		return true;
-
-	if (on_task_stack(tsk, sp, size, info))
-		return true;
-	if (tsk != current || preemptible())
-		return false;
-	if (on_irq_stack(sp, size, info))
-		return true;
-	if (on_sdei_stack(sp, size, info))
-		return true;
-
-	return false;
-}
-
-/*
- * Unwind from one frame record (A) to the next frame record (B).
- *
- * We terminate early if the location of B indicates a malformed chain of frame
- * records (e.g. a cycle), determined based on the location and fp value of A
- * and the location (but not the fp value) of B.
- */
-static inline int notrace unwind_next(struct unwind_state *state)
-{
-	struct task_struct *tsk = state->task;
-	unsigned long fp = state->fp;
-	struct stack_info info;
-	int err;
-
-	/* Final frame; nothing to unwind */
-	if (fp == (unsigned long)task_pt_regs(tsk)->stackframe)
-		return -ENOENT;
-
-	err = unwind_next_common(state, &info, NULL);
-	if (err)
-		return err;
-
-	state->pc = ptrauth_strip_insn_pac(state->pc);
-
-#ifdef CONFIG_FUNCTION_GRAPH_TRACER
-	if (tsk->ret_stack &&
-		(state->pc == (unsigned long)return_to_handler)) {
-		unsigned long orig_pc;
-		/*
-		 * This is a case where function graph tracer has
-		 * modified a return address (LR) in a stack frame
-		 * to hook a function return.
-		 * So replace it to an original value.
-		 */
-		orig_pc = ftrace_graph_ret_addr(tsk, NULL, state->pc,
-						(void *)state->fp);
-		if (WARN_ON_ONCE(state->pc == orig_pc))
-			return -EINVAL;
-		state->pc = orig_pc;
-	}
-#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
-#ifdef CONFIG_KRETPROBES
-	if (is_kretprobe_trampoline(state->pc))
-		state->pc = kretprobe_find_ret_addr(tsk, (void *)state->fp, &state->kr_cur);
-#endif
-
-	return 0;
-}
-NOKPROBE_SYMBOL(unwind_next);
-
 #endif	/* __ASM_STACKTRACE_H */
diff --git a/arch/arm64/include/asm/stacktrace/common.h b/arch/arm64/include/asm/stacktrace/common.h
index 3ebb69ea374a..18046a7248a2 100644
--- a/arch/arm64/include/asm/stacktrace/common.h
+++ b/arch/arm64/include/asm/stacktrace/common.h
@@ -79,15 +79,6 @@ struct unwind_state {
 	struct task_struct *task;
 };
 
-static inline bool on_overflow_stack(unsigned long sp, unsigned long size,
-				     struct stack_info *info);
-
-static inline bool on_accessible_stack(const struct task_struct *tsk,
-				       unsigned long sp, unsigned long size,
-				       struct stack_info *info);
-
-static inline int unwind_next(struct unwind_state *state);
-
 static inline bool on_stack(unsigned long sp, unsigned long size,
 			    unsigned long low, unsigned long high,
 			    enum stack_type type, struct stack_info *info)
@@ -106,21 +97,6 @@ static inline bool on_stack(unsigned long sp, unsigned long size,
 	return true;
 }
 
-static inline bool on_accessible_stack_common(const struct task_struct *tsk,
-					      unsigned long sp,
-					      unsigned long size,
-					      struct stack_info *info)
-{
-	if (info)
-		info->type = STACK_TYPE_UNKNOWN;
-
-	/*
-	 * Both the kernel and nvhe hypervisor make use of
-	 * an overflow_stack
-	 */
-	return on_overflow_stack(sp, size, info);
-}
-
 static inline void unwind_init_common(struct unwind_state *state,
 				      struct task_struct *task)
 {
@@ -156,8 +132,22 @@ static inline void unwind_init_common(struct unwind_state *state,
 typedef bool (*stack_trace_translate_fp_fn)(unsigned long *fp,
 					    enum stack_type type);
 
+/*
+ * on_accessible_stack_fn() - Check whether a stack range is on any
+ * of the possible stacks.
+ *
+ * @tsk:  task whose stack is being unwound
+ * @sp:   stack address being checked
+ * @size: size of the stack range being checked
+ * @info: stack unwinding context
+ */
+typedef bool (*on_accessible_stack_fn)(const struct task_struct *tsk,
+				       unsigned long sp, unsigned long size,
+				       struct stack_info *info);
+
 static inline int unwind_next_common(struct unwind_state *state,
 				     struct stack_info *info,
+				     on_accessible_stack_fn accessible,
 				     stack_trace_translate_fp_fn translate_fp)
 {
 	unsigned long fp = state->fp, kern_fp = fp;
@@ -166,7 +156,7 @@ static inline int unwind_next_common(struct unwind_state *state,
 	if (fp & 0x7)
 		return -EINVAL;
 
-	if (!on_accessible_stack(tsk, fp, 16, info))
+	if (!accessible(tsk, fp, 16, info))
 		return -EINVAL;
 
 	if (test_bit(info->type, state->stacks_done))
@@ -212,19 +202,4 @@ static inline int unwind_next_common(struct unwind_state *state,
 	return 0;
 }
 
-static inline void notrace unwind(struct unwind_state *state,
-				  stack_trace_consume_fn consume_entry,
-				  void *cookie)
-{
-	while (1) {
-		int ret;
-
-		if (!consume_entry(cookie, state->pc))
-			break;
-		ret = unwind_next(state);
-		if (ret < 0)
-			break;
-	}
-}
-NOKPROBE_SYMBOL(unwind);
 #endif	/* __ASM_STACKTRACE_COMMON_H */
diff --git a/arch/arm64/include/asm/stacktrace/nvhe.h b/arch/arm64/include/asm/stacktrace/nvhe.h
index 8a5cb96d7143..a096216d8970 100644
--- a/arch/arm64/include/asm/stacktrace/nvhe.h
+++ b/arch/arm64/include/asm/stacktrace/nvhe.h
@@ -37,59 +37,7 @@ static inline void kvm_nvhe_unwind_init(struct unwind_state *state,
 	state->pc = pc;
 }
 
-static inline bool on_hyp_stack(unsigned long sp, unsigned long size,
-				struct stack_info *info);
-
-static inline bool on_accessible_stack(const struct task_struct *tsk,
-				       unsigned long sp, unsigned long size,
-				       struct stack_info *info)
-{
-	if (on_accessible_stack_common(tsk, sp, size, info))
-		return true;
-
-	if (on_hyp_stack(sp, size, info))
-		return true;
-
-	return false;
-}
-
-#ifdef __KVM_NVHE_HYPERVISOR__
-/*
- * Protected nVHE HYP stack unwinder
- *
- * In protected mode, the unwinding is done by the hypervisor in EL2.
- */
-
-#ifdef CONFIG_PROTECTED_NVHE_STACKTRACE
-static inline bool on_overflow_stack(unsigned long sp, unsigned long size,
-				     struct stack_info *info)
-{
-	unsigned long low = (unsigned long)this_cpu_ptr(overflow_stack);
-	unsigned long high = low + OVERFLOW_STACK_SIZE;
-
-	return on_stack(sp, size, low, high, STACK_TYPE_OVERFLOW, info);
-}
-
-static inline bool on_hyp_stack(unsigned long sp, unsigned long size,
-				struct stack_info *info)
-{
-	struct kvm_nvhe_init_params *params = this_cpu_ptr(&kvm_init_params);
-	unsigned long high = params->stack_hyp_va;
-	unsigned long low = high - PAGE_SIZE;
-
-	return on_stack(sp, size, low, high, STACK_TYPE_HYP, info);
-}
-
-static inline int notrace unwind_next(struct unwind_state *state)
-{
-	struct stack_info info;
-
-	return unwind_next_common(state, &info, NULL);
-}
-NOKPROBE_SYMBOL(unwind_next);
-#endif	/* CONFIG_PROTECTED_NVHE_STACKTRACE */
-
-#else	/* !__KVM_NVHE_HYPERVISOR__ */
+#ifndef __KVM_NVHE_HYPERVISOR__
 /*
  * Conventional (non-protected) nVHE HYP stack unwinder
  *
@@ -142,36 +90,6 @@ static inline bool kvm_nvhe_stack_kern_va(unsigned long *addr,
 	return true;
 }
 
-static inline bool on_overflow_stack(unsigned long sp, unsigned long size,
-				     struct stack_info *info)
-{
-	struct kvm_nvhe_stacktrace_info *stacktrace_info
-				= this_cpu_ptr_nvhe_sym(kvm_stacktrace_info);
-	unsigned long low = (unsigned long)stacktrace_info->overflow_stack_base;
-	unsigned long high = low + OVERFLOW_STACK_SIZE;
-
-	return on_stack(sp, size, low, high, STACK_TYPE_OVERFLOW, info);
-}
-
-static inline bool on_hyp_stack(unsigned long sp, unsigned long size,
-				struct stack_info *info)
-{
-	struct kvm_nvhe_stacktrace_info *stacktrace_info
-				= this_cpu_ptr_nvhe_sym(kvm_stacktrace_info);
-	unsigned long low = (unsigned long)stacktrace_info->stack_base;
-	unsigned long high = low + PAGE_SIZE;
-
-	return on_stack(sp, size, low, high, STACK_TYPE_HYP, info);
-}
-
-static inline int notrace unwind_next(struct unwind_state *state)
-{
-	struct stack_info info;
-
-	return unwind_next_common(state, &info, kvm_nvhe_stack_kern_va);
-}
-NOKPROBE_SYMBOL(unwind_next);
-
 void kvm_nvhe_dump_backtrace(unsigned long hyp_offset);
 
 #endif	/* __KVM_NVHE_HYPERVISOR__ */
diff --git a/arch/arm64/kernel/stacktrace.c b/arch/arm64/kernel/stacktrace.c
index 9fa60ee48499..ce190ee18a20 100644
--- a/arch/arm64/kernel/stacktrace.c
+++ b/arch/arm64/kernel/stacktrace.c
@@ -67,6 +67,96 @@ static inline void unwind_init_from_task(struct unwind_state *state,
 	state->pc = thread_saved_pc(task);
 }
 
+/*
+ * We can only safely access per-cpu stacks from current in a non-preemptible
+ * context.
+ */
+static bool on_accessible_stack(const struct task_struct *tsk,
+				unsigned long sp, unsigned long size,
+				struct stack_info *info)
+{
+	if (info)
+		info->type = STACK_TYPE_UNKNOWN;
+
+	if (on_task_stack(tsk, sp, size, info))
+		return true;
+	if (tsk != current || preemptible())
+		return false;
+	if (on_irq_stack(sp, size, info))
+		return true;
+	if (on_overflow_stack(sp, size, info))
+		return true;
+	if (on_sdei_stack(sp, size, info))
+		return true;
+
+	return false;
+}
+
+/*
+ * Unwind from one frame record (A) to the next frame record (B).
+ *
+ * We terminate early if the location of B indicates a malformed chain of frame
+ * records (e.g. a cycle), determined based on the location and fp value of A
+ * and the location (but not the fp value) of B.
+ */
+static int notrace unwind_next(struct unwind_state *state)
+{
+	struct task_struct *tsk = state->task;
+	unsigned long fp = state->fp;
+	struct stack_info info;
+	int err;
+
+	/* Final frame; nothing to unwind */
+	if (fp == (unsigned long)task_pt_regs(tsk)->stackframe)
+		return -ENOENT;
+
+	err = unwind_next_common(state, &info, on_accessible_stack, NULL);
+	if (err)
+		return err;
+
+	state->pc = ptrauth_strip_insn_pac(state->pc);
+
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+	if (tsk->ret_stack &&
+		(state->pc == (unsigned long)return_to_handler)) {
+		unsigned long orig_pc;
+		/*
+		 * This is a case where function graph tracer has
+		 * modified a return address (LR) in a stack frame
+		 * to hook a function return.
+		 * So replace it to an original value.
+		 */
+		orig_pc = ftrace_graph_ret_addr(tsk, NULL, state->pc,
+						(void *)state->fp);
+		if (WARN_ON_ONCE(state->pc == orig_pc))
+			return -EINVAL;
+		state->pc = orig_pc;
+	}
+#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
+#ifdef CONFIG_KRETPROBES
+	if (is_kretprobe_trampoline(state->pc))
+		state->pc = kretprobe_find_ret_addr(tsk, (void *)state->fp, &state->kr_cur);
+#endif
+
+	return 0;
+}
+NOKPROBE_SYMBOL(unwind_next);
+
+static void notrace unwind(struct unwind_state *state,
+			   stack_trace_consume_fn consume_entry, void *cookie)
+{
+	while (1) {
+		int ret;
+
+		if (!consume_entry(cookie, state->pc))
+			break;
+		ret = unwind_next(state);
+		if (ret < 0)
+			break;
+	}
+}
+NOKPROBE_SYMBOL(unwind);
+
 static bool dump_backtrace_entry(void *arg, unsigned long where)
 {
 	char *loglvl = arg;
diff --git a/arch/arm64/kvm/hyp/nvhe/stacktrace.c b/arch/arm64/kvm/hyp/nvhe/stacktrace.c
index 900324b7a08f..acbe272ecb32 100644
--- a/arch/arm64/kvm/hyp/nvhe/stacktrace.c
+++ b/arch/arm64/kvm/hyp/nvhe/stacktrace.c
@@ -39,6 +39,58 @@ static void hyp_prepare_backtrace(unsigned long fp, unsigned long pc)
 
 DEFINE_PER_CPU(unsigned long [NVHE_STACKTRACE_SIZE/sizeof(long)], pkvm_stacktrace);
 
+static bool on_overflow_stack(unsigned long sp, unsigned long size,
+			      struct stack_info *info)
+{
+	unsigned long low = (unsigned long)this_cpu_ptr(overflow_stack);
+	unsigned long high = low + OVERFLOW_STACK_SIZE;
+
+	return on_stack(sp, size, low, high, STACK_TYPE_OVERFLOW, info);
+}
+
+static bool on_hyp_stack(unsigned long sp, unsigned long size,
+			      struct stack_info *info)
+{
+	struct kvm_nvhe_init_params *params = this_cpu_ptr(&kvm_init_params);
+	unsigned long high = params->stack_hyp_va;
+	unsigned long low = high - PAGE_SIZE;
+
+	return on_stack(sp, size, low, high, STACK_TYPE_HYP, info);
+}
+
+static bool on_accessible_stack(const struct task_struct *tsk,
+				unsigned long sp, unsigned long size,
+				struct stack_info *info)
+{
+	if (info)
+		info->type = STACK_TYPE_UNKNOWN;
+
+	return (on_overflow_stack(sp, size, info) ||
+		on_hyp_stack(sp, size, info));
+}
+
+static int unwind_next(struct unwind_state *state)
+{
+	struct stack_info info;
+
+	return unwind_next_common(state, &info, on_accessible_stack, NULL);
+}
+
+static void notrace unwind(struct unwind_state *state,
+			   stack_trace_consume_fn consume_entry,
+			   void *cookie)
+{
+	while (1) {
+		int ret;
+
+		if (!consume_entry(cookie, state->pc))
+			break;
+		ret = unwind_next(state);
+		if (ret < 0)
+			break;
+	}
+}
+
 /*
  * pkvm_save_backtrace_entry - Saves a protected nVHE HYP stacktrace entry
  *
diff --git a/arch/arm64/kvm/stacktrace.c b/arch/arm64/kvm/stacktrace.c
index 9812aefdcfb4..4d5fec3175ff 100644
--- a/arch/arm64/kvm/stacktrace.c
+++ b/arch/arm64/kvm/stacktrace.c
@@ -21,6 +21,61 @@
 
 #include <asm/stacktrace/nvhe.h>
 
+static bool on_overflow_stack(unsigned long sp, unsigned long size,
+			      struct stack_info *info)
+{
+	struct kvm_nvhe_stacktrace_info *stacktrace_info
+				= this_cpu_ptr_nvhe_sym(kvm_stacktrace_info);
+	unsigned long low = (unsigned long)stacktrace_info->overflow_stack_base;
+	unsigned long high = low + OVERFLOW_STACK_SIZE;
+
+	return on_stack(sp, size, low, high, STACK_TYPE_OVERFLOW, info);
+}
+
+static bool on_hyp_stack(unsigned long sp, unsigned long size,
+			 struct stack_info *info)
+{
+	struct kvm_nvhe_stacktrace_info *stacktrace_info
+				= this_cpu_ptr_nvhe_sym(kvm_stacktrace_info);
+	unsigned long low = (unsigned long)stacktrace_info->stack_base;
+	unsigned long high = low + PAGE_SIZE;
+
+	return on_stack(sp, size, low, high, STACK_TYPE_HYP, info);
+}
+
+static bool on_accessible_stack(const struct task_struct *tsk,
+				unsigned long sp, unsigned long size,
+				struct stack_info *info)
+{
+	if (info)
+		info->type = STACK_TYPE_UNKNOWN;
+
+	return (on_overflow_stack(sp, size, info) ||
+		on_hyp_stack(sp, size, info));
+}
+
+static int unwind_next(struct unwind_state *state)
+{
+	struct stack_info info;
+
+	return unwind_next_common(state, &info, on_accessible_stack,
+				  kvm_nvhe_stack_kern_va);
+}
+
+static void unwind(struct unwind_state *state,
+		   stack_trace_consume_fn consume_entry, void *cookie)
+{
+	while (1) {
+		int ret;
+
+		if (!consume_entry(cookie, state->pc))
+			break;
+		ret = unwind_next(state);
+		if (ret < 0)
+			break;
+	}
+}
+
 /*
  * kvm_nvhe_dump_backtrace_entry - Symbolize and print an nVHE backtrace entry
  *
-- 
2.34.1

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply related	[flat|nested] 112+ messages in thread

* [PATCH 3/6] KVM: arm64: Make unwind()/on_accessible_stack() per-unwinder functions
@ 2022-07-27 14:29       ` Marc Zyngier
  0 siblings, 0 replies; 112+ messages in thread
From: Marc Zyngier @ 2022-07-27 14:29 UTC (permalink / raw)
  To: linux-arm-kernel, kvmarm, kvm
  Cc: mark.rutland, broonie, madvenka, tabba, oliver.upton, qperret,
	kaleshsingh, james.morse, alexandru.elisei, suzuki.poulose,
	catalin.marinas, andreyknvl, vincenzo.frascino, mhiramat, ast,
	wangkefeng.wang, elver, keirf, yuzenghui, ardb, oupton,
	kernel-team

Having multiple versions of on_accessible_stack() (one per unwinder)
makes it very hard to reason about what is used where due to the
complexity of the various includes, the forward declarations, and
the reliance on everything being 'inline'.

Instead, move the code back where it should be. Each unwinder
implements:

- on_accessible_stack() as well as the helpers it depends on,

- unwind()/unwind_next(), as they pass on_accessible_stack as
  a parameter to unwind_next_common() (which is the only common
  code here)

This hardly results in any duplication, and makes it much
easier to reason about the code.

Signed-off-by: Marc Zyngier <maz@kernel.org>
---
 arch/arm64/include/asm/stacktrace.h        | 74 ------------------
 arch/arm64/include/asm/stacktrace/common.h | 55 ++++---------
 arch/arm64/include/asm/stacktrace/nvhe.h   | 84 +-------------------
 arch/arm64/kernel/stacktrace.c             | 90 ++++++++++++++++++++++
 arch/arm64/kvm/hyp/nvhe/stacktrace.c       | 52 +++++++++++++
 arch/arm64/kvm/stacktrace.c                | 55 +++++++++++++
 6 files changed, 213 insertions(+), 197 deletions(-)

diff --git a/arch/arm64/include/asm/stacktrace.h b/arch/arm64/include/asm/stacktrace.h
index ea828579a98b..6ebdcdff77f5 100644
--- a/arch/arm64/include/asm/stacktrace.h
+++ b/arch/arm64/include/asm/stacktrace.h
@@ -57,78 +57,4 @@ static inline bool on_overflow_stack(unsigned long sp, unsigned long size,
 			struct stack_info *info) { return false; }
 #endif
 
-
-/*
- * We can only safely access per-cpu stacks from current in a non-preemptible
- * context.
- */
-static inline bool on_accessible_stack(const struct task_struct *tsk,
-				       unsigned long sp, unsigned long size,
-				       struct stack_info *info)
-{
-	if (on_accessible_stack_common(tsk, sp, size, info))
-		return true;
-
-	if (on_task_stack(tsk, sp, size, info))
-		return true;
-	if (tsk != current || preemptible())
-		return false;
-	if (on_irq_stack(sp, size, info))
-		return true;
-	if (on_sdei_stack(sp, size, info))
-		return true;
-
-	return false;
-}
-
-/*
- * Unwind from one frame record (A) to the next frame record (B).
- *
- * We terminate early if the location of B indicates a malformed chain of frame
- * records (e.g. a cycle), determined based on the location and fp value of A
- * and the location (but not the fp value) of B.
- */
-static inline int notrace unwind_next(struct unwind_state *state)
-{
-	struct task_struct *tsk = state->task;
-	unsigned long fp = state->fp;
-	struct stack_info info;
-	int err;
-
-	/* Final frame; nothing to unwind */
-	if (fp == (unsigned long)task_pt_regs(tsk)->stackframe)
-		return -ENOENT;
-
-	err = unwind_next_common(state, &info, NULL);
-	if (err)
-		return err;
-
-	state->pc = ptrauth_strip_insn_pac(state->pc);
-
-#ifdef CONFIG_FUNCTION_GRAPH_TRACER
-	if (tsk->ret_stack &&
-		(state->pc == (unsigned long)return_to_handler)) {
-		unsigned long orig_pc;
-		/*
-		 * This is a case where function graph tracer has
-		 * modified a return address (LR) in a stack frame
-		 * to hook a function return.
-		 * So replace it to an original value.
-		 */
-		orig_pc = ftrace_graph_ret_addr(tsk, NULL, state->pc,
-						(void *)state->fp);
-		if (WARN_ON_ONCE(state->pc == orig_pc))
-			return -EINVAL;
-		state->pc = orig_pc;
-	}
-#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
-#ifdef CONFIG_KRETPROBES
-	if (is_kretprobe_trampoline(state->pc))
-		state->pc = kretprobe_find_ret_addr(tsk, (void *)state->fp, &state->kr_cur);
-#endif
-
-	return 0;
-}
-NOKPROBE_SYMBOL(unwind_next);
-
 #endif	/* __ASM_STACKTRACE_H */
diff --git a/arch/arm64/include/asm/stacktrace/common.h b/arch/arm64/include/asm/stacktrace/common.h
index 3ebb69ea374a..18046a7248a2 100644
--- a/arch/arm64/include/asm/stacktrace/common.h
+++ b/arch/arm64/include/asm/stacktrace/common.h
@@ -79,15 +79,6 @@ struct unwind_state {
 	struct task_struct *task;
 };
 
-static inline bool on_overflow_stack(unsigned long sp, unsigned long size,
-				     struct stack_info *info);
-
-static inline bool on_accessible_stack(const struct task_struct *tsk,
-				       unsigned long sp, unsigned long size,
-				       struct stack_info *info);
-
-static inline int unwind_next(struct unwind_state *state);
-
 static inline bool on_stack(unsigned long sp, unsigned long size,
 			    unsigned long low, unsigned long high,
 			    enum stack_type type, struct stack_info *info)
@@ -106,21 +97,6 @@ static inline bool on_stack(unsigned long sp, unsigned long size,
 	return true;
 }
 
-static inline bool on_accessible_stack_common(const struct task_struct *tsk,
-					      unsigned long sp,
-					      unsigned long size,
-					      struct stack_info *info)
-{
-	if (info)
-		info->type = STACK_TYPE_UNKNOWN;
-
-	/*
-	 * Both the kernel and nvhe hypervisor make use of
-	 * an overflow_stack
-	 */
-	return on_overflow_stack(sp, size, info);
-}
-
 static inline void unwind_init_common(struct unwind_state *state,
 				      struct task_struct *task)
 {
@@ -156,8 +132,22 @@ static inline void unwind_init_common(struct unwind_state *state,
 typedef bool (*stack_trace_translate_fp_fn)(unsigned long *fp,
 					    enum stack_type type);
 
+/*
+ * on_accessible_stack_fn() - Check whether a stack range is on any
+ * of the possible stacks.
+ *
+ * @tsk:  task whose stack is being unwound
+ * @sp:   stack address being checked
+ * @size: size of the stack range being checked
+ * @info: stack unwinding context
+ */
+typedef bool (*on_accessible_stack_fn)(const struct task_struct *tsk,
+				       unsigned long sp, unsigned long size,
+				       struct stack_info *info);
+
 static inline int unwind_next_common(struct unwind_state *state,
 				     struct stack_info *info,
+				     on_accessible_stack_fn accessible,
 				     stack_trace_translate_fp_fn translate_fp)
 {
 	unsigned long fp = state->fp, kern_fp = fp;
@@ -166,7 +156,7 @@ static inline int unwind_next_common(struct unwind_state *state,
 	if (fp & 0x7)
 		return -EINVAL;
 
-	if (!on_accessible_stack(tsk, fp, 16, info))
+	if (!accessible(tsk, fp, 16, info))
 		return -EINVAL;
 
 	if (test_bit(info->type, state->stacks_done))
@@ -212,19 +202,4 @@ static inline int unwind_next_common(struct unwind_state *state,
 	return 0;
 }
 
-static inline void notrace unwind(struct unwind_state *state,
-				  stack_trace_consume_fn consume_entry,
-				  void *cookie)
-{
-	while (1) {
-		int ret;
-
-		if (!consume_entry(cookie, state->pc))
-			break;
-		ret = unwind_next(state);
-		if (ret < 0)
-			break;
-	}
-}
-NOKPROBE_SYMBOL(unwind);
 #endif	/* __ASM_STACKTRACE_COMMON_H */
diff --git a/arch/arm64/include/asm/stacktrace/nvhe.h b/arch/arm64/include/asm/stacktrace/nvhe.h
index 8a5cb96d7143..a096216d8970 100644
--- a/arch/arm64/include/asm/stacktrace/nvhe.h
+++ b/arch/arm64/include/asm/stacktrace/nvhe.h
@@ -37,59 +37,7 @@ static inline void kvm_nvhe_unwind_init(struct unwind_state *state,
 	state->pc = pc;
 }
 
-static inline bool on_hyp_stack(unsigned long sp, unsigned long size,
-				struct stack_info *info);
-
-static inline bool on_accessible_stack(const struct task_struct *tsk,
-				       unsigned long sp, unsigned long size,
-				       struct stack_info *info)
-{
-	if (on_accessible_stack_common(tsk, sp, size, info))
-		return true;
-
-	if (on_hyp_stack(sp, size, info))
-		return true;
-
-	return false;
-}
-
-#ifdef __KVM_NVHE_HYPERVISOR__
-/*
- * Protected nVHE HYP stack unwinder
- *
- * In protected mode, the unwinding is done by the hypervisor in EL2.
- */
-
-#ifdef CONFIG_PROTECTED_NVHE_STACKTRACE
-static inline bool on_overflow_stack(unsigned long sp, unsigned long size,
-				     struct stack_info *info)
-{
-	unsigned long low = (unsigned long)this_cpu_ptr(overflow_stack);
-	unsigned long high = low + OVERFLOW_STACK_SIZE;
-
-	return on_stack(sp, size, low, high, STACK_TYPE_OVERFLOW, info);
-}
-
-static inline bool on_hyp_stack(unsigned long sp, unsigned long size,
-				struct stack_info *info)
-{
-	struct kvm_nvhe_init_params *params = this_cpu_ptr(&kvm_init_params);
-	unsigned long high = params->stack_hyp_va;
-	unsigned long low = high - PAGE_SIZE;
-
-	return on_stack(sp, size, low, high, STACK_TYPE_HYP, info);
-}
-
-static inline int notrace unwind_next(struct unwind_state *state)
-{
-	struct stack_info info;
-
-	return unwind_next_common(state, &info, NULL);
-}
-NOKPROBE_SYMBOL(unwind_next);
-#endif	/* CONFIG_PROTECTED_NVHE_STACKTRACE */
-
-#else	/* !__KVM_NVHE_HYPERVISOR__ */
+#ifndef __KVM_NVHE_HYPERVISOR__
 /*
  * Conventional (non-protected) nVHE HYP stack unwinder
  *
@@ -142,36 +90,6 @@ static inline bool kvm_nvhe_stack_kern_va(unsigned long *addr,
 	return true;
 }
 
-static inline bool on_overflow_stack(unsigned long sp, unsigned long size,
-				     struct stack_info *info)
-{
-	struct kvm_nvhe_stacktrace_info *stacktrace_info
-				= this_cpu_ptr_nvhe_sym(kvm_stacktrace_info);
-	unsigned long low = (unsigned long)stacktrace_info->overflow_stack_base;
-	unsigned long high = low + OVERFLOW_STACK_SIZE;
-
-	return on_stack(sp, size, low, high, STACK_TYPE_OVERFLOW, info);
-}
-
-static inline bool on_hyp_stack(unsigned long sp, unsigned long size,
-				struct stack_info *info)
-{
-	struct kvm_nvhe_stacktrace_info *stacktrace_info
-				= this_cpu_ptr_nvhe_sym(kvm_stacktrace_info);
-	unsigned long low = (unsigned long)stacktrace_info->stack_base;
-	unsigned long high = low + PAGE_SIZE;
-
-	return on_stack(sp, size, low, high, STACK_TYPE_HYP, info);
-}
-
-static inline int notrace unwind_next(struct unwind_state *state)
-{
-	struct stack_info info;
-
-	return unwind_next_common(state, &info, kvm_nvhe_stack_kern_va);
-}
-NOKPROBE_SYMBOL(unwind_next);
-
 void kvm_nvhe_dump_backtrace(unsigned long hyp_offset);
 
 #endif	/* __KVM_NVHE_HYPERVISOR__ */
diff --git a/arch/arm64/kernel/stacktrace.c b/arch/arm64/kernel/stacktrace.c
index 9fa60ee48499..ce190ee18a20 100644
--- a/arch/arm64/kernel/stacktrace.c
+++ b/arch/arm64/kernel/stacktrace.c
@@ -67,6 +67,96 @@ static inline void unwind_init_from_task(struct unwind_state *state,
 	state->pc = thread_saved_pc(task);
 }
 
+/*
+ * We can only safely access per-cpu stacks from current in a non-preemptible
+ * context.
+ */
+static bool on_accessible_stack(const struct task_struct *tsk,
+				unsigned long sp, unsigned long size,
+				struct stack_info *info)
+{
+	if (info)
+		info->type = STACK_TYPE_UNKNOWN;
+
+	if (on_task_stack(tsk, sp, size, info))
+		return true;
+	if (tsk != current || preemptible())
+		return false;
+	if (on_irq_stack(sp, size, info))
+		return true;
+	if (on_overflow_stack(sp, size, info))
+		return true;
+	if (on_sdei_stack(sp, size, info))
+		return true;
+
+	return false;
+}
+
+/*
+ * Unwind from one frame record (A) to the next frame record (B).
+ *
+ * We terminate early if the location of B indicates a malformed chain of frame
+ * records (e.g. a cycle), determined based on the location and fp value of A
+ * and the location (but not the fp value) of B.
+ */
+static int notrace unwind_next(struct unwind_state *state)
+{
+	struct task_struct *tsk = state->task;
+	unsigned long fp = state->fp;
+	struct stack_info info;
+	int err;
+
+	/* Final frame; nothing to unwind */
+	if (fp == (unsigned long)task_pt_regs(tsk)->stackframe)
+		return -ENOENT;
+
+	err = unwind_next_common(state, &info, on_accessible_stack, NULL);
+	if (err)
+		return err;
+
+	state->pc = ptrauth_strip_insn_pac(state->pc);
+
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+	if (tsk->ret_stack &&
+		(state->pc == (unsigned long)return_to_handler)) {
+		unsigned long orig_pc;
+		/*
+		 * This is a case where function graph tracer has
+		 * modified a return address (LR) in a stack frame
+		 * to hook a function return.
+		 * So replace it to an original value.
+		 */
+		orig_pc = ftrace_graph_ret_addr(tsk, NULL, state->pc,
+						(void *)state->fp);
+		if (WARN_ON_ONCE(state->pc == orig_pc))
+			return -EINVAL;
+		state->pc = orig_pc;
+	}
+#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
+#ifdef CONFIG_KRETPROBES
+	if (is_kretprobe_trampoline(state->pc))
+		state->pc = kretprobe_find_ret_addr(tsk, (void *)state->fp, &state->kr_cur);
+#endif
+
+	return 0;
+}
+NOKPROBE_SYMBOL(unwind_next);
+
+static void notrace unwind(struct unwind_state *state,
+			   stack_trace_consume_fn consume_entry, void *cookie)
+{
+	while (1) {
+		int ret;
+
+		if (!consume_entry(cookie, state->pc))
+			break;
+		ret = unwind_next(state);
+		if (ret < 0)
+			break;
+	}
+}
+NOKPROBE_SYMBOL(unwind);
+
 static bool dump_backtrace_entry(void *arg, unsigned long where)
 {
 	char *loglvl = arg;
diff --git a/arch/arm64/kvm/hyp/nvhe/stacktrace.c b/arch/arm64/kvm/hyp/nvhe/stacktrace.c
index 900324b7a08f..acbe272ecb32 100644
--- a/arch/arm64/kvm/hyp/nvhe/stacktrace.c
+++ b/arch/arm64/kvm/hyp/nvhe/stacktrace.c
@@ -39,6 +39,58 @@ static void hyp_prepare_backtrace(unsigned long fp, unsigned long pc)
 
 DEFINE_PER_CPU(unsigned long [NVHE_STACKTRACE_SIZE/sizeof(long)], pkvm_stacktrace);
 
+static bool on_overflow_stack(unsigned long sp, unsigned long size,
+			      struct stack_info *info)
+{
+	unsigned long low = (unsigned long)this_cpu_ptr(overflow_stack);
+	unsigned long high = low + OVERFLOW_STACK_SIZE;
+
+	return on_stack(sp, size, low, high, STACK_TYPE_OVERFLOW, info);
+}
+
+static bool on_hyp_stack(unsigned long sp, unsigned long size,
+			      struct stack_info *info)
+{
+	struct kvm_nvhe_init_params *params = this_cpu_ptr(&kvm_init_params);
+	unsigned long high = params->stack_hyp_va;
+	unsigned long low = high - PAGE_SIZE;
+
+	return on_stack(sp, size, low, high, STACK_TYPE_HYP, info);
+}
+
+static bool on_accessible_stack(const struct task_struct *tsk,
+				unsigned long sp, unsigned long size,
+				struct stack_info *info)
+{
+	if (info)
+		info->type = STACK_TYPE_UNKNOWN;
+
+	return (on_overflow_stack(sp, size, info) ||
+		on_hyp_stack(sp, size, info));
+}
+
+static int unwind_next(struct unwind_state *state)
+{
+	struct stack_info info;
+
+	return unwind_next_common(state, &info, on_accessible_stack, NULL);
+}
+
+static void notrace unwind(struct unwind_state *state,
+			   stack_trace_consume_fn consume_entry,
+			   void *cookie)
+{
+	while (1) {
+		int ret;
+
+		if (!consume_entry(cookie, state->pc))
+			break;
+		ret = unwind_next(state);
+		if (ret < 0)
+			break;
+	}
+}
+
 /*
  * pkvm_save_backtrace_entry - Saves a protected nVHE HYP stacktrace entry
  *
diff --git a/arch/arm64/kvm/stacktrace.c b/arch/arm64/kvm/stacktrace.c
index 9812aefdcfb4..4d5fec3175ff 100644
--- a/arch/arm64/kvm/stacktrace.c
+++ b/arch/arm64/kvm/stacktrace.c
@@ -21,6 +21,61 @@
 
 #include <asm/stacktrace/nvhe.h>
 
+static bool on_overflow_stack(unsigned long sp, unsigned long size,
+			      struct stack_info *info)
+{
+	struct kvm_nvhe_stacktrace_info *stacktrace_info
+				= this_cpu_ptr_nvhe_sym(kvm_stacktrace_info);
+	unsigned long low = (unsigned long)stacktrace_info->overflow_stack_base;
+	unsigned long high = low + OVERFLOW_STACK_SIZE;
+
+	return on_stack(sp, size, low, high, STACK_TYPE_OVERFLOW, info);
+}
+
+static bool on_hyp_stack(unsigned long sp, unsigned long size,
+			 struct stack_info *info)
+{
+	struct kvm_nvhe_stacktrace_info *stacktrace_info
+				= this_cpu_ptr_nvhe_sym(kvm_stacktrace_info);
+	unsigned long low = (unsigned long)stacktrace_info->stack_base;
+	unsigned long high = low + PAGE_SIZE;
+
+	return on_stack(sp, size, low, high, STACK_TYPE_HYP, info);
+}
+
+static bool on_accessible_stack(const struct task_struct *tsk,
+				unsigned long sp, unsigned long size,
+				struct stack_info *info)
+{
+	if (info)
+		info->type = STACK_TYPE_UNKNOWN;
+
+	return (on_overflow_stack(sp, size, info) ||
+		on_hyp_stack(sp, size, info));
+}
+
+static int unwind_next(struct unwind_state *state)
+{
+	struct stack_info info;
+
+	return unwind_next_common(state, &info, on_accessible_stack,
+				  kvm_nvhe_stack_kern_va);
+}
+
+static void unwind(struct unwind_state *state,
+		   stack_trace_consume_fn consume_entry, void *cookie)
+{
+	while (1) {
+		int ret;
+
+		if (!consume_entry(cookie, state->pc))
+			break;
+		ret = unwind_next(state);
+		if (ret < 0)
+			break;
+	}
+}
+
 /*
  * kvm_nvhe_dump_backtrace_entry - Symbolize and print an nVHE backtrace entry
  *
-- 
2.34.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 112+ messages in thread

* [PATCH 4/6] KVM: arm64: Move nVHE-only helpers into kvm/stacktrace.c
  2022-07-27 14:29     ` Marc Zyngier
  (?)
@ 2022-07-27 14:29       ` Marc Zyngier
  -1 siblings, 0 replies; 112+ messages in thread
From: Marc Zyngier @ 2022-07-27 14:29 UTC (permalink / raw)
  To: linux-arm-kernel, kvmarm, kvm
  Cc: mark.rutland, broonie, madvenka, tabba, oliver.upton, qperret,
	kaleshsingh, james.morse, alexandru.elisei, suzuki.poulose,
	catalin.marinas, andreyknvl, vincenzo.frascino, mhiramat, ast,
	wangkefeng.wang, elver, keirf, yuzenghui, ardb, oupton,
	kernel-team

kvm_nvhe_stack_kern_va() only makes sense as part of the nVHE
unwinder, so simply move it there.

Signed-off-by: Marc Zyngier <maz@kernel.org>
---
 arch/arm64/include/asm/stacktrace/nvhe.h | 41 ------------------------
 arch/arm64/kvm/stacktrace.c              | 41 ++++++++++++++++++++++++
 2 files changed, 41 insertions(+), 41 deletions(-)

diff --git a/arch/arm64/include/asm/stacktrace/nvhe.h b/arch/arm64/include/asm/stacktrace/nvhe.h
index a096216d8970..d5527b600390 100644
--- a/arch/arm64/include/asm/stacktrace/nvhe.h
+++ b/arch/arm64/include/asm/stacktrace/nvhe.h
@@ -49,47 +49,6 @@ DECLARE_KVM_NVHE_PER_CPU(unsigned long [OVERFLOW_STACK_SIZE/sizeof(long)], overf
 DECLARE_KVM_NVHE_PER_CPU(struct kvm_nvhe_stacktrace_info, kvm_stacktrace_info);
 DECLARE_PER_CPU(unsigned long, kvm_arm_hyp_stack_page);
 
-/*
- * kvm_nvhe_stack_kern_va - Convert KVM nVHE HYP stack addresses to a kernel VAs
- *
- * The nVHE hypervisor stack is mapped in the flexible 'private' VA range, to
- * allow for guard pages below the stack. Consequently, the fixed offset address
- * translation macros won't work here.
- *
- * The kernel VA is calculated as an offset from the kernel VA of the hypervisor
- * stack base.
- *
- * Returns true on success and updates @addr to its corresponding kernel VA;
- * otherwise returns false.
- */
-static inline bool kvm_nvhe_stack_kern_va(unsigned long *addr,
-					  enum stack_type type)
-{
-	struct kvm_nvhe_stacktrace_info *stacktrace_info;
-	unsigned long hyp_base, kern_base, hyp_offset;
-
-	stacktrace_info = this_cpu_ptr_nvhe_sym(kvm_stacktrace_info);
-
-	switch (type) {
-	case STACK_TYPE_HYP:
-		kern_base = (unsigned long)*this_cpu_ptr(&kvm_arm_hyp_stack_page);
-		hyp_base = (unsigned long)stacktrace_info->stack_base;
-		break;
-	case STACK_TYPE_OVERFLOW:
-		kern_base = (unsigned long)this_cpu_ptr_nvhe_sym(overflow_stack);
-		hyp_base = (unsigned long)stacktrace_info->overflow_stack_base;
-		break;
-	default:
-		return false;
-	}
-
-	hyp_offset = *addr - hyp_base;
-
-	*addr = kern_base + hyp_offset;
-
-	return true;
-}
-
 void kvm_nvhe_dump_backtrace(unsigned long hyp_offset);
 
 #endif	/* __KVM_NVHE_HYPERVISOR__ */
diff --git a/arch/arm64/kvm/stacktrace.c b/arch/arm64/kvm/stacktrace.c
index 4d5fec3175ff..417665854f86 100644
--- a/arch/arm64/kvm/stacktrace.c
+++ b/arch/arm64/kvm/stacktrace.c
@@ -21,6 +21,47 @@
 
 #include <asm/stacktrace/nvhe.h>
 
+/*
+ * kvm_nvhe_stack_kern_va - Convert KVM nVHE HYP stack addresses to a kernel VAs
+ *
+ * The nVHE hypervisor stack is mapped in the flexible 'private' VA range, to
+ * allow for guard pages below the stack. Consequently, the fixed offset address
+ * translation macros won't work here.
+ *
+ * The kernel VA is calculated as an offset from the kernel VA of the hypervisor
+ * stack base.
+ *
+ * Returns true on success and updates @addr to its corresponding kernel VA;
+ * otherwise returns false.
+ */
+static bool kvm_nvhe_stack_kern_va(unsigned long *addr,
+				   enum stack_type type)
+{
+	struct kvm_nvhe_stacktrace_info *stacktrace_info;
+	unsigned long hyp_base, kern_base, hyp_offset;
+
+	stacktrace_info = this_cpu_ptr_nvhe_sym(kvm_stacktrace_info);
+
+	switch (type) {
+	case STACK_TYPE_HYP:
+		kern_base = (unsigned long)*this_cpu_ptr(&kvm_arm_hyp_stack_page);
+		hyp_base = (unsigned long)stacktrace_info->stack_base;
+		break;
+	case STACK_TYPE_OVERFLOW:
+		kern_base = (unsigned long)this_cpu_ptr_nvhe_sym(overflow_stack);
+		hyp_base = (unsigned long)stacktrace_info->overflow_stack_base;
+		break;
+	default:
+		return false;
+	}
+
+	hyp_offset = *addr - hyp_base;
+
+	*addr = kern_base + hyp_offset;
+
+	return true;
+}
+
 static bool on_overflow_stack(unsigned long sp, unsigned long size,
 			      struct stack_info *info)
 {
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 112+ messages in thread

* [PATCH 4/6] KVM: arm64: Move nVHE-only helpers into kvm/stacktrace.c
@ 2022-07-27 14:29       ` Marc Zyngier
  0 siblings, 0 replies; 112+ messages in thread
From: Marc Zyngier @ 2022-07-27 14:29 UTC (permalink / raw)
  To: linux-arm-kernel, kvmarm, kvm
  Cc: wangkefeng.wang, catalin.marinas, ast, vincenzo.frascino,
	madvenka, kernel-team, elver, broonie, andreyknvl, mhiramat

kvm_nvhe_stack_kern_va() only makes sense as part of the nVHE
unwinder, so simply move it there.

Signed-off-by: Marc Zyngier <maz@kernel.org>
---
 arch/arm64/include/asm/stacktrace/nvhe.h | 41 ------------------------
 arch/arm64/kvm/stacktrace.c              | 41 ++++++++++++++++++++++++
 2 files changed, 41 insertions(+), 41 deletions(-)

diff --git a/arch/arm64/include/asm/stacktrace/nvhe.h b/arch/arm64/include/asm/stacktrace/nvhe.h
index a096216d8970..d5527b600390 100644
--- a/arch/arm64/include/asm/stacktrace/nvhe.h
+++ b/arch/arm64/include/asm/stacktrace/nvhe.h
@@ -49,47 +49,6 @@ DECLARE_KVM_NVHE_PER_CPU(unsigned long [OVERFLOW_STACK_SIZE/sizeof(long)], overf
 DECLARE_KVM_NVHE_PER_CPU(struct kvm_nvhe_stacktrace_info, kvm_stacktrace_info);
 DECLARE_PER_CPU(unsigned long, kvm_arm_hyp_stack_page);
 
-/*
- * kvm_nvhe_stack_kern_va - Convert KVM nVHE HYP stack addresses to a kernel VAs
- *
- * The nVHE hypervisor stack is mapped in the flexible 'private' VA range, to
- * allow for guard pages below the stack. Consequently, the fixed offset address
- * translation macros won't work here.
- *
- * The kernel VA is calculated as an offset from the kernel VA of the hypervisor
- * stack base.
- *
- * Returns true on success and updates @addr to its corresponding kernel VA;
- * otherwise returns false.
- */
-static inline bool kvm_nvhe_stack_kern_va(unsigned long *addr,
-					  enum stack_type type)
-{
-	struct kvm_nvhe_stacktrace_info *stacktrace_info;
-	unsigned long hyp_base, kern_base, hyp_offset;
-
-	stacktrace_info = this_cpu_ptr_nvhe_sym(kvm_stacktrace_info);
-
-	switch (type) {
-	case STACK_TYPE_HYP:
-		kern_base = (unsigned long)*this_cpu_ptr(&kvm_arm_hyp_stack_page);
-		hyp_base = (unsigned long)stacktrace_info->stack_base;
-		break;
-	case STACK_TYPE_OVERFLOW:
-		kern_base = (unsigned long)this_cpu_ptr_nvhe_sym(overflow_stack);
-		hyp_base = (unsigned long)stacktrace_info->overflow_stack_base;
-		break;
-	default:
-		return false;
-	}
-
-	hyp_offset = *addr - hyp_base;
-
-	*addr = kern_base + hyp_offset;
-
-	return true;
-}
-
 void kvm_nvhe_dump_backtrace(unsigned long hyp_offset);
 
 #endif	/* __KVM_NVHE_HYPERVISOR__ */
diff --git a/arch/arm64/kvm/stacktrace.c b/arch/arm64/kvm/stacktrace.c
index 4d5fec3175ff..417665854f86 100644
--- a/arch/arm64/kvm/stacktrace.c
+++ b/arch/arm64/kvm/stacktrace.c
@@ -21,6 +21,47 @@
 
 #include <asm/stacktrace/nvhe.h>
 
+/*
+ * kvm_nvhe_stack_kern_va - Convert KVM nVHE HYP stack addresses to a kernel VAs
+ *
+ * The nVHE hypervisor stack is mapped in the flexible 'private' VA range, to
+ * allow for guard pages below the stack. Consequently, the fixed offset address
+ * translation macros won't work here.
+ *
+ * The kernel VA is calculated as an offset from the kernel VA of the hypervisor
+ * stack base.
+ *
+ * Returns true on success and updates @addr to its corresponding kernel VA;
+ * otherwise returns false.
+ */
+static bool kvm_nvhe_stack_kern_va(unsigned long *addr,
+				   enum stack_type type)
+{
+	struct kvm_nvhe_stacktrace_info *stacktrace_info;
+	unsigned long hyp_base, kern_base, hyp_offset;
+
+	stacktrace_info = this_cpu_ptr_nvhe_sym(kvm_stacktrace_info);
+
+	switch (type) {
+	case STACK_TYPE_HYP:
+		kern_base = (unsigned long)*this_cpu_ptr(&kvm_arm_hyp_stack_page);
+		hyp_base = (unsigned long)stacktrace_info->stack_base;
+		break;
+	case STACK_TYPE_OVERFLOW:
+		kern_base = (unsigned long)this_cpu_ptr_nvhe_sym(overflow_stack);
+		hyp_base = (unsigned long)stacktrace_info->overflow_stack_base;
+		break;
+	default:
+		return false;
+	}
+
+	hyp_offset = *addr - hyp_base;
+
+	*addr = kern_base + hyp_offset;
+
+	return true;
+}
+
 static bool on_overflow_stack(unsigned long sp, unsigned long size,
 			      struct stack_info *info)
 {
-- 
2.34.1

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply related	[flat|nested] 112+ messages in thread

* [PATCH 4/6] KVM: arm64: Move nVHE-only helpers into kvm/stacktrace.c
@ 2022-07-27 14:29       ` Marc Zyngier
  0 siblings, 0 replies; 112+ messages in thread
From: Marc Zyngier @ 2022-07-27 14:29 UTC (permalink / raw)
  To: linux-arm-kernel, kvmarm, kvm
  Cc: mark.rutland, broonie, madvenka, tabba, oliver.upton, qperret,
	kaleshsingh, james.morse, alexandru.elisei, suzuki.poulose,
	catalin.marinas, andreyknvl, vincenzo.frascino, mhiramat, ast,
	wangkefeng.wang, elver, keirf, yuzenghui, ardb, oupton,
	kernel-team

kvm_nvhe_stack_kern_va() only makes sense as part of the nVHE
unwinder, so simply move it there.

Signed-off-by: Marc Zyngier <maz@kernel.org>
---
 arch/arm64/include/asm/stacktrace/nvhe.h | 41 ------------------------
 arch/arm64/kvm/stacktrace.c              | 41 ++++++++++++++++++++++++
 2 files changed, 41 insertions(+), 41 deletions(-)

diff --git a/arch/arm64/include/asm/stacktrace/nvhe.h b/arch/arm64/include/asm/stacktrace/nvhe.h
index a096216d8970..d5527b600390 100644
--- a/arch/arm64/include/asm/stacktrace/nvhe.h
+++ b/arch/arm64/include/asm/stacktrace/nvhe.h
@@ -49,47 +49,6 @@ DECLARE_KVM_NVHE_PER_CPU(unsigned long [OVERFLOW_STACK_SIZE/sizeof(long)], overf
 DECLARE_KVM_NVHE_PER_CPU(struct kvm_nvhe_stacktrace_info, kvm_stacktrace_info);
 DECLARE_PER_CPU(unsigned long, kvm_arm_hyp_stack_page);
 
-/*
- * kvm_nvhe_stack_kern_va - Convert KVM nVHE HYP stack addresses to a kernel VAs
- *
- * The nVHE hypervisor stack is mapped in the flexible 'private' VA range, to
- * allow for guard pages below the stack. Consequently, the fixed offset address
- * translation macros won't work here.
- *
- * The kernel VA is calculated as an offset from the kernel VA of the hypervisor
- * stack base.
- *
- * Returns true on success and updates @addr to its corresponding kernel VA;
- * otherwise returns false.
- */
-static inline bool kvm_nvhe_stack_kern_va(unsigned long *addr,
-					  enum stack_type type)
-{
-	struct kvm_nvhe_stacktrace_info *stacktrace_info;
-	unsigned long hyp_base, kern_base, hyp_offset;
-
-	stacktrace_info = this_cpu_ptr_nvhe_sym(kvm_stacktrace_info);
-
-	switch (type) {
-	case STACK_TYPE_HYP:
-		kern_base = (unsigned long)*this_cpu_ptr(&kvm_arm_hyp_stack_page);
-		hyp_base = (unsigned long)stacktrace_info->stack_base;
-		break;
-	case STACK_TYPE_OVERFLOW:
-		kern_base = (unsigned long)this_cpu_ptr_nvhe_sym(overflow_stack);
-		hyp_base = (unsigned long)stacktrace_info->overflow_stack_base;
-		break;
-	default:
-		return false;
-	}
-
-	hyp_offset = *addr - hyp_base;
-
-	*addr = kern_base + hyp_offset;
-
-	return true;
-}
-
 void kvm_nvhe_dump_backtrace(unsigned long hyp_offset);
 
 #endif	/* __KVM_NVHE_HYPERVISOR__ */
diff --git a/arch/arm64/kvm/stacktrace.c b/arch/arm64/kvm/stacktrace.c
index 4d5fec3175ff..417665854f86 100644
--- a/arch/arm64/kvm/stacktrace.c
+++ b/arch/arm64/kvm/stacktrace.c
@@ -21,6 +21,47 @@
 
 #include <asm/stacktrace/nvhe.h>
 
+/*
+ * kvm_nvhe_stack_kern_va - Convert KVM nVHE HYP stack addresses to a kernel VAs
+ *
+ * The nVHE hypervisor stack is mapped in the flexible 'private' VA range, to
+ * allow for guard pages below the stack. Consequently, the fixed offset address
+ * translation macros won't work here.
+ *
+ * The kernel VA is calculated as an offset from the kernel VA of the hypervisor
+ * stack base.
+ *
+ * Returns true on success and updates @addr to its corresponding kernel VA;
+ * otherwise returns false.
+ */
+static bool kvm_nvhe_stack_kern_va(unsigned long *addr,
+				   enum stack_type type)
+{
+	struct kvm_nvhe_stacktrace_info *stacktrace_info;
+	unsigned long hyp_base, kern_base, hyp_offset;
+
+	stacktrace_info = this_cpu_ptr_nvhe_sym(kvm_stacktrace_info);
+
+	switch (type) {
+	case STACK_TYPE_HYP:
+		kern_base = (unsigned long)*this_cpu_ptr(&kvm_arm_hyp_stack_page);
+		hyp_base = (unsigned long)stacktrace_info->stack_base;
+		break;
+	case STACK_TYPE_OVERFLOW:
+		kern_base = (unsigned long)this_cpu_ptr_nvhe_sym(overflow_stack);
+		hyp_base = (unsigned long)stacktrace_info->overflow_stack_base;
+		break;
+	default:
+		return false;
+	}
+
+	hyp_offset = *addr - hyp_base;
+
+	*addr = kern_base + hyp_offset;
+
+	return true;
+}
+
 static bool on_overflow_stack(unsigned long sp, unsigned long size,
 			      struct stack_info *info)
 {
-- 
2.34.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 112+ messages in thread

* [PATCH 5/6] KVM: arm64: Don't open code ARRAY_SIZE()
  2022-07-27 14:29     ` Marc Zyngier
  (?)
@ 2022-07-27 14:29       ` Marc Zyngier
  -1 siblings, 0 replies; 112+ messages in thread
From: Marc Zyngier @ 2022-07-27 14:29 UTC (permalink / raw)
  To: linux-arm-kernel, kvmarm, kvm
  Cc: mark.rutland, broonie, madvenka, tabba, oliver.upton, qperret,
	kaleshsingh, james.morse, alexandru.elisei, suzuki.poulose,
	catalin.marinas, andreyknvl, vincenzo.frascino, mhiramat, ast,
	wangkefeng.wang, elver, keirf, yuzenghui, ardb, oupton,
	kernel-team

From: Oliver Upton <oliver.upton@linux.dev>

Use ARRAY_SIZE() instead of an open-coded version.

Signed-off-by: Oliver Upton <oliver.upton@linux.dev>
Signed-off-by: Marc Zyngier <maz@kernel.org>
---
 arch/arm64/kvm/hyp/nvhe/stacktrace.c | 3 +--
 arch/arm64/kvm/stacktrace.c          | 6 ++++--
 2 files changed, 5 insertions(+), 4 deletions(-)

diff --git a/arch/arm64/kvm/hyp/nvhe/stacktrace.c b/arch/arm64/kvm/hyp/nvhe/stacktrace.c
index acbe272ecb32..58f645ad66bc 100644
--- a/arch/arm64/kvm/hyp/nvhe/stacktrace.c
+++ b/arch/arm64/kvm/hyp/nvhe/stacktrace.c
@@ -103,14 +103,13 @@ static void notrace unwind(struct unwind_state *state,
 static bool pkvm_save_backtrace_entry(void *arg, unsigned long where)
 {
 	unsigned long *stacktrace = this_cpu_ptr(pkvm_stacktrace);
-	int size = NVHE_STACKTRACE_SIZE / sizeof(long);
 	int *idx = (int *)arg;
 
 	/*
 	 * Need 2 free slots: 1 for current entry and 1 for the
 	 * delimiter.
 	 */
-	if (*idx > size - 2)
+	if (*idx > ARRAY_SIZE(pkvm_stacktrace) - 2)
 		return false;
 
 	stacktrace[*idx] = where;
diff --git a/arch/arm64/kvm/stacktrace.c b/arch/arm64/kvm/stacktrace.c
index 417665854f86..949d19d603fb 100644
--- a/arch/arm64/kvm/stacktrace.c
+++ b/arch/arm64/kvm/stacktrace.c
@@ -187,11 +187,13 @@ static void pkvm_dump_backtrace(unsigned long hyp_offset)
 {
 	unsigned long *stacktrace
 		= (unsigned long *) this_cpu_ptr_nvhe_sym(pkvm_stacktrace);
-	int i, size = NVHE_STACKTRACE_SIZE / sizeof(long);
+	int i;
 
 	kvm_nvhe_dump_backtrace_start();
 	/* The saved stacktrace is terminated by a null entry */
-	for (i = 0; i < size && stacktrace[i]; i++)
+	for (i = 0;
+	     i < ARRAY_SIZE(kvm_nvhe_sym(pkvm_stacktrace)) && stacktrace[i];
+	     i++)
 		kvm_nvhe_dump_backtrace_entry((void *)hyp_offset, stacktrace[i]);
 	kvm_nvhe_dump_backtrace_end();
 }
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 112+ messages in thread

* [PATCH 5/6] KVM: arm64: Don't open code ARRAY_SIZE()
@ 2022-07-27 14:29       ` Marc Zyngier
  0 siblings, 0 replies; 112+ messages in thread
From: Marc Zyngier @ 2022-07-27 14:29 UTC (permalink / raw)
  To: linux-arm-kernel, kvmarm, kvm
  Cc: wangkefeng.wang, catalin.marinas, ast, vincenzo.frascino,
	madvenka, kernel-team, elver, broonie, andreyknvl, mhiramat

From: Oliver Upton <oliver.upton@linux.dev>

Use ARRAY_SIZE() instead of an open-coded version.

Signed-off-by: Oliver Upton <oliver.upton@linux.dev>
Signed-off-by: Marc Zyngier <maz@kernel.org>
---
 arch/arm64/kvm/hyp/nvhe/stacktrace.c | 3 +--
 arch/arm64/kvm/stacktrace.c          | 6 ++++--
 2 files changed, 5 insertions(+), 4 deletions(-)

diff --git a/arch/arm64/kvm/hyp/nvhe/stacktrace.c b/arch/arm64/kvm/hyp/nvhe/stacktrace.c
index acbe272ecb32..58f645ad66bc 100644
--- a/arch/arm64/kvm/hyp/nvhe/stacktrace.c
+++ b/arch/arm64/kvm/hyp/nvhe/stacktrace.c
@@ -103,14 +103,13 @@ static void notrace unwind(struct unwind_state *state,
 static bool pkvm_save_backtrace_entry(void *arg, unsigned long where)
 {
 	unsigned long *stacktrace = this_cpu_ptr(pkvm_stacktrace);
-	int size = NVHE_STACKTRACE_SIZE / sizeof(long);
 	int *idx = (int *)arg;
 
 	/*
 	 * Need 2 free slots: 1 for current entry and 1 for the
 	 * delimiter.
 	 */
-	if (*idx > size - 2)
+	if (*idx > ARRAY_SIZE(pkvm_stacktrace) - 2)
 		return false;
 
 	stacktrace[*idx] = where;
diff --git a/arch/arm64/kvm/stacktrace.c b/arch/arm64/kvm/stacktrace.c
index 417665854f86..949d19d603fb 100644
--- a/arch/arm64/kvm/stacktrace.c
+++ b/arch/arm64/kvm/stacktrace.c
@@ -187,11 +187,13 @@ static void pkvm_dump_backtrace(unsigned long hyp_offset)
 {
 	unsigned long *stacktrace
 		= (unsigned long *) this_cpu_ptr_nvhe_sym(pkvm_stacktrace);
-	int i, size = NVHE_STACKTRACE_SIZE / sizeof(long);
+	int i;
 
 	kvm_nvhe_dump_backtrace_start();
 	/* The saved stacktrace is terminated by a null entry */
-	for (i = 0; i < size && stacktrace[i]; i++)
+	for (i = 0;
+	     i < ARRAY_SIZE(kvm_nvhe_sym(pkvm_stacktrace)) && stacktrace[i];
+	     i++)
 		kvm_nvhe_dump_backtrace_entry((void *)hyp_offset, stacktrace[i]);
 	kvm_nvhe_dump_backtrace_end();
 }
-- 
2.34.1

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply related	[flat|nested] 112+ messages in thread

* [PATCH 5/6] KVM: arm64: Don't open code ARRAY_SIZE()
@ 2022-07-27 14:29       ` Marc Zyngier
  0 siblings, 0 replies; 112+ messages in thread
From: Marc Zyngier @ 2022-07-27 14:29 UTC (permalink / raw)
  To: linux-arm-kernel, kvmarm, kvm
  Cc: mark.rutland, broonie, madvenka, tabba, oliver.upton, qperret,
	kaleshsingh, james.morse, alexandru.elisei, suzuki.poulose,
	catalin.marinas, andreyknvl, vincenzo.frascino, mhiramat, ast,
	wangkefeng.wang, elver, keirf, yuzenghui, ardb, oupton,
	kernel-team

From: Oliver Upton <oliver.upton@linux.dev>

Use ARRAY_SIZE() instead of an open-coded version.

Signed-off-by: Oliver Upton <oliver.upton@linux.dev>
Signed-off-by: Marc Zyngier <maz@kernel.org>
---
 arch/arm64/kvm/hyp/nvhe/stacktrace.c | 3 +--
 arch/arm64/kvm/stacktrace.c          | 6 ++++--
 2 files changed, 5 insertions(+), 4 deletions(-)

diff --git a/arch/arm64/kvm/hyp/nvhe/stacktrace.c b/arch/arm64/kvm/hyp/nvhe/stacktrace.c
index acbe272ecb32..58f645ad66bc 100644
--- a/arch/arm64/kvm/hyp/nvhe/stacktrace.c
+++ b/arch/arm64/kvm/hyp/nvhe/stacktrace.c
@@ -103,14 +103,13 @@ static void notrace unwind(struct unwind_state *state,
 static bool pkvm_save_backtrace_entry(void *arg, unsigned long where)
 {
 	unsigned long *stacktrace = this_cpu_ptr(pkvm_stacktrace);
-	int size = NVHE_STACKTRACE_SIZE / sizeof(long);
 	int *idx = (int *)arg;
 
 	/*
 	 * Need 2 free slots: 1 for current entry and 1 for the
 	 * delimiter.
 	 */
-	if (*idx > size - 2)
+	if (*idx > ARRAY_SIZE(pkvm_stacktrace) - 2)
 		return false;
 
 	stacktrace[*idx] = where;
diff --git a/arch/arm64/kvm/stacktrace.c b/arch/arm64/kvm/stacktrace.c
index 417665854f86..949d19d603fb 100644
--- a/arch/arm64/kvm/stacktrace.c
+++ b/arch/arm64/kvm/stacktrace.c
@@ -187,11 +187,13 @@ static void pkvm_dump_backtrace(unsigned long hyp_offset)
 {
 	unsigned long *stacktrace
 		= (unsigned long *) this_cpu_ptr_nvhe_sym(pkvm_stacktrace);
-	int i, size = NVHE_STACKTRACE_SIZE / sizeof(long);
+	int i;
 
 	kvm_nvhe_dump_backtrace_start();
 	/* The saved stacktrace is terminated by a null entry */
-	for (i = 0; i < size && stacktrace[i]; i++)
+	for (i = 0;
+	     i < ARRAY_SIZE(kvm_nvhe_sym(pkvm_stacktrace)) && stacktrace[i];
+	     i++)
 		kvm_nvhe_dump_backtrace_entry((void *)hyp_offset, stacktrace[i]);
 	kvm_nvhe_dump_backtrace_end();
 }
-- 
2.34.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 112+ messages in thread

* [PATCH 6/6] arm64: Update 'unwinder howto'
  2022-07-27 14:29     ` Marc Zyngier
  (?)
@ 2022-07-27 14:29       ` Marc Zyngier
  -1 siblings, 0 replies; 112+ messages in thread
From: Marc Zyngier @ 2022-07-27 14:29 UTC (permalink / raw)
  To: linux-arm-kernel, kvmarm, kvm
  Cc: mark.rutland, broonie, madvenka, tabba, oliver.upton, qperret,
	kaleshsingh, james.morse, alexandru.elisei, suzuki.poulose,
	catalin.marinas, andreyknvl, vincenzo.frascino, mhiramat, ast,
	wangkefeng.wang, elver, keirf, yuzenghui, ardb, oupton,
	kernel-team

Implementing a new unwinder is a bit more involved than writing
a couple of helpers, so let's not lure the reader into a false
sense of comfort. Instead, let's point out what they should
call into, and what sort of parameter they need to provide.

Signed-off-by: Marc Zyngier <maz@kernel.org>
---
 arch/arm64/include/asm/stacktrace/common.h | 14 ++++----------
 1 file changed, 4 insertions(+), 10 deletions(-)

diff --git a/arch/arm64/include/asm/stacktrace/common.h b/arch/arm64/include/asm/stacktrace/common.h
index 18046a7248a2..f58eb944c46f 100644
--- a/arch/arm64/include/asm/stacktrace/common.h
+++ b/arch/arm64/include/asm/stacktrace/common.h
@@ -5,17 +5,11 @@
  * To implement a new arm64 stack unwinder:
  *     1) Include this header
  *
- *     2) Provide implementations for the following functions:
- *          on_overflow_stack():   Returns true if SP is on the overflow
- *                                 stack.
- *          on_accessible_stack(): Returns true is SP is on any accessible
- *                                 stack.
- *          unwind_next():         Performs validation checks on the frame
- *                                 pointer, and transitions unwind_state
- *                                 to the next frame.
+ *     2) Call into unwind_next_common() from your top level unwind
+ *        function, passing it the validation and translation callbacks
+ *        (though the later can be NULL if no translation is required).
  *
- *         See: arch/arm64/include/asm/stacktrace.h for reference
- *              implementations.
+ * See: arch/arm64/kernel/stacktrace.c for the reference implementation.
  *
  * Copyright (C) 2012 ARM Ltd.
  */
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 112+ messages in thread

* [PATCH 6/6] arm64: Update 'unwinder howto'
@ 2022-07-27 14:29       ` Marc Zyngier
  0 siblings, 0 replies; 112+ messages in thread
From: Marc Zyngier @ 2022-07-27 14:29 UTC (permalink / raw)
  To: linux-arm-kernel, kvmarm, kvm
  Cc: wangkefeng.wang, catalin.marinas, ast, vincenzo.frascino,
	madvenka, kernel-team, elver, broonie, andreyknvl, mhiramat

Implementing a new unwinder is a bit more involved than writing
a couple of helpers, so let's not lure the reader into a false
sense of comfort. Instead, let's point out what they should
call into, and what sort of parameter they need to provide.

Signed-off-by: Marc Zyngier <maz@kernel.org>
---
 arch/arm64/include/asm/stacktrace/common.h | 14 ++++----------
 1 file changed, 4 insertions(+), 10 deletions(-)

diff --git a/arch/arm64/include/asm/stacktrace/common.h b/arch/arm64/include/asm/stacktrace/common.h
index 18046a7248a2..f58eb944c46f 100644
--- a/arch/arm64/include/asm/stacktrace/common.h
+++ b/arch/arm64/include/asm/stacktrace/common.h
@@ -5,17 +5,11 @@
  * To implement a new arm64 stack unwinder:
  *     1) Include this header
  *
- *     2) Provide implementations for the following functions:
- *          on_overflow_stack():   Returns true if SP is on the overflow
- *                                 stack.
- *          on_accessible_stack(): Returns true is SP is on any accessible
- *                                 stack.
- *          unwind_next():         Performs validation checks on the frame
- *                                 pointer, and transitions unwind_state
- *                                 to the next frame.
+ *     2) Call into unwind_next_common() from your top level unwind
+ *        function, passing it the validation and translation callbacks
+ *        (though the later can be NULL if no translation is required).
  *
- *         See: arch/arm64/include/asm/stacktrace.h for reference
- *              implementations.
+ * See: arch/arm64/kernel/stacktrace.c for the reference implementation.
  *
  * Copyright (C) 2012 ARM Ltd.
  */
-- 
2.34.1

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply related	[flat|nested] 112+ messages in thread

* [PATCH 6/6] arm64: Update 'unwinder howto'
@ 2022-07-27 14:29       ` Marc Zyngier
  0 siblings, 0 replies; 112+ messages in thread
From: Marc Zyngier @ 2022-07-27 14:29 UTC (permalink / raw)
  To: linux-arm-kernel, kvmarm, kvm
  Cc: mark.rutland, broonie, madvenka, tabba, oliver.upton, qperret,
	kaleshsingh, james.morse, alexandru.elisei, suzuki.poulose,
	catalin.marinas, andreyknvl, vincenzo.frascino, mhiramat, ast,
	wangkefeng.wang, elver, keirf, yuzenghui, ardb, oupton,
	kernel-team

Implementing a new unwinder is a bit more involved than writing
a couple of helpers, so let's not lure the reader into a false
sense of comfort. Instead, let's point out what they should
call into, and what sort of parameter they need to provide.

Signed-off-by: Marc Zyngier <maz@kernel.org>
---
 arch/arm64/include/asm/stacktrace/common.h | 14 ++++----------
 1 file changed, 4 insertions(+), 10 deletions(-)

diff --git a/arch/arm64/include/asm/stacktrace/common.h b/arch/arm64/include/asm/stacktrace/common.h
index 18046a7248a2..f58eb944c46f 100644
--- a/arch/arm64/include/asm/stacktrace/common.h
+++ b/arch/arm64/include/asm/stacktrace/common.h
@@ -5,17 +5,11 @@
  * To implement a new arm64 stack unwinder:
  *     1) Include this header
  *
- *     2) Provide implementations for the following functions:
- *          on_overflow_stack():   Returns true if SP is on the overflow
- *                                 stack.
- *          on_accessible_stack(): Returns true is SP is on any accessible
- *                                 stack.
- *          unwind_next():         Performs validation checks on the frame
- *                                 pointer, and transitions unwind_state
- *                                 to the next frame.
+ *     2) Call into unwind_next_common() from your top level unwind
+ *        function, passing it the validation and translation callbacks
+ *        (though the later can be NULL if no translation is required).
  *
- *         See: arch/arm64/include/asm/stacktrace.h for reference
- *              implementations.
+ * See: arch/arm64/kernel/stacktrace.c for the reference implementation.
  *
  * Copyright (C) 2012 ARM Ltd.
  */
-- 
2.34.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 112+ messages in thread

* Re: [PATCH 0/6] KVM: arm64: nVHE stack unwinder rework
  2022-07-27 14:29     ` Marc Zyngier
  (?)
@ 2022-07-27 15:56       ` Kalesh Singh
  -1 siblings, 0 replies; 112+ messages in thread
From: Kalesh Singh @ 2022-07-27 15:56 UTC (permalink / raw)
  To: Marc Zyngier
  Cc: moderated list:ARM64 PORT (AARCH64 ARCHITECTURE),
	kvmarm, kvm, Mark Rutland, Mark Brown, Madhavan T. Venkataraman,
	Fuad Tabba, Oliver Upton, Quentin Perret, James Morse,
	Alexandru Elisei, Suzuki K Poulose, Catalin Marinas, andreyknvl,
	vincenzo.frascino, Masami Hiramatsu, Alexei Starovoitov,
	Kefeng Wang, Marco Elver, Keir Fraser, Zenghui Yu,
	Ard Biesheuvel, Oliver Upton, Cc: Android Kernel

On Wed, Jul 27, 2022 at 7:29 AM Marc Zyngier <maz@kernel.org> wrote:
>
> Hi all,
>
> As Kalesh's series[1] already went through quite a few rounds and that
> it has proved to be an extremely useful debugging help, I'd like to
> queue it for 5.20.
>
> However, there is a couple of nits that I'd like to address:
>
> - the code is extremely hard to follow, due to the include maze and
>   the various levels of inline functions that have forward
>   declarations...
>
> - there is a subtle bug in the way the kernel on_accessible_stack()
>   helper has been rewritten
>
> - the config symbol for the protected unwinder is oddly placed

Hi Marc,

Thanks for doing this rework.

For the series:
Reviewed-by: Kalesh Singh <kaleshsingh@google.com>
Tested-by: Kalesh Singh <kaleshsingh@google.com>

Thanks,
Kalesh

>
> Instead of going for another round and missing the merge window, I
> propose to stash the following patches on top, which IMHO result in
> something much more readable.
>
> This series directly applies on top of Kalesh's.
>
> [1] https://lore.kernel.org/r/20220726073750.3219117-1-kaleshsingh@google.com
>
> Marc Zyngier (5):
>   KVM: arm64: Move PROTECTED_NVHE_STACKTRACE around
>   KVM: arm64: Move nVHE stacktrace unwinding into its own compilation
>     unit
>   KVM: arm64: Make unwind()/on_accessible_stack() per-unwinder functions
>   KVM: arm64: Move nVHE-only helpers into kvm/stacktrace.c
>   arm64: Update 'unwinder howto'
>
> Oliver Upton (1):
>   KVM: arm64: Don't open code ARRAY_SIZE()
>
>  arch/arm64/include/asm/stacktrace.h        |  74 -------
>  arch/arm64/include/asm/stacktrace/common.h |  69 ++-----
>  arch/arm64/include/asm/stacktrace/nvhe.h   | 125 +-----------
>  arch/arm64/kernel/stacktrace.c             |  90 +++++++++
>  arch/arm64/kvm/Kconfig                     |  24 ++-
>  arch/arm64/kvm/Makefile                    |   2 +-
>  arch/arm64/kvm/handle_exit.c               |  98 ---------
>  arch/arm64/kvm/hyp/nvhe/stacktrace.c       |  55 +++++-
>  arch/arm64/kvm/stacktrace.c                | 218 +++++++++++++++++++++
>  9 files changed, 394 insertions(+), 361 deletions(-)
>  create mode 100644 arch/arm64/kvm/stacktrace.c
>
> --
> 2.34.1
>

^ permalink raw reply	[flat|nested] 112+ messages in thread

* Re: [PATCH 0/6] KVM: arm64: nVHE stack unwinder rework
@ 2022-07-27 15:56       ` Kalesh Singh
  0 siblings, 0 replies; 112+ messages in thread
From: Kalesh Singh @ 2022-07-27 15:56 UTC (permalink / raw)
  To: Marc Zyngier
  Cc: Kefeng Wang, kvm, Catalin Marinas, Alexei Starovoitov,
	vincenzo.frascino, kvmarm, Madhavan T. Venkataraman,
	moderated list:ARM64 PORT (AARCH64 ARCHITECTURE),
	Cc: Android Kernel, Marco Elver, Mark Brown, andreyknvl,
	Masami Hiramatsu

On Wed, Jul 27, 2022 at 7:29 AM Marc Zyngier <maz@kernel.org> wrote:
>
> Hi all,
>
> As Kalesh's series[1] already went through quite a few rounds and that
> it has proved to be an extremely useful debugging help, I'd like to
> queue it for 5.20.
>
> However, there is a couple of nits that I'd like to address:
>
> - the code is extremely hard to follow, due to the include maze and
>   the various levels of inline functions that have forward
>   declarations...
>
> - there is a subtle bug in the way the kernel on_accessible_stack()
>   helper has been rewritten
>
> - the config symbol for the protected unwinder is oddly placed

Hi Marc,

Thanks for doing this rework.

For the series:
Reviewed-by: Kalesh Singh <kaleshsingh@google.com>
Tested-by: Kalesh Singh <kaleshsingh@google.com>

Thanks,
Kalesh

>
> Instead of going for another round and missing the merge window, I
> propose to stash the following patches on top, which IMHO result in
> something much more readable.
>
> This series directly applies on top of Kalesh's.
>
> [1] https://lore.kernel.org/r/20220726073750.3219117-1-kaleshsingh@google.com
>
> Marc Zyngier (5):
>   KVM: arm64: Move PROTECTED_NVHE_STACKTRACE around
>   KVM: arm64: Move nVHE stacktrace unwinding into its own compilation
>     unit
>   KVM: arm64: Make unwind()/on_accessible_stack() per-unwinder functions
>   KVM: arm64: Move nVHE-only helpers into kvm/stacktrace.c
>   arm64: Update 'unwinder howto'
>
> Oliver Upton (1):
>   KVM: arm64: Don't open code ARRAY_SIZE()
>
>  arch/arm64/include/asm/stacktrace.h        |  74 -------
>  arch/arm64/include/asm/stacktrace/common.h |  69 ++-----
>  arch/arm64/include/asm/stacktrace/nvhe.h   | 125 +-----------
>  arch/arm64/kernel/stacktrace.c             |  90 +++++++++
>  arch/arm64/kvm/Kconfig                     |  24 ++-
>  arch/arm64/kvm/Makefile                    |   2 +-
>  arch/arm64/kvm/handle_exit.c               |  98 ---------
>  arch/arm64/kvm/hyp/nvhe/stacktrace.c       |  55 +++++-
>  arch/arm64/kvm/stacktrace.c                | 218 +++++++++++++++++++++
>  9 files changed, 394 insertions(+), 361 deletions(-)
>  create mode 100644 arch/arm64/kvm/stacktrace.c
>
> --
> 2.34.1
>
_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply	[flat|nested] 112+ messages in thread

* Re: [PATCH 0/6] KVM: arm64: nVHE stack unwinder rework
@ 2022-07-27 15:56       ` Kalesh Singh
  0 siblings, 0 replies; 112+ messages in thread
From: Kalesh Singh @ 2022-07-27 15:56 UTC (permalink / raw)
  To: Marc Zyngier
  Cc: moderated list:ARM64 PORT (AARCH64 ARCHITECTURE),
	kvmarm, kvm, Mark Rutland, Mark Brown, Madhavan T. Venkataraman,
	Fuad Tabba, Oliver Upton, Quentin Perret, James Morse,
	Alexandru Elisei, Suzuki K Poulose, Catalin Marinas, andreyknvl,
	vincenzo.frascino, Masami Hiramatsu, Alexei Starovoitov,
	Kefeng Wang, Marco Elver, Keir Fraser, Zenghui Yu,
	Ard Biesheuvel, Oliver Upton, Cc: Android Kernel

On Wed, Jul 27, 2022 at 7:29 AM Marc Zyngier <maz@kernel.org> wrote:
>
> Hi all,
>
> As Kalesh's series[1] already went through quite a few rounds and that
> it has proved to be an extremely useful debugging help, I'd like to
> queue it for 5.20.
>
> However, there is a couple of nits that I'd like to address:
>
> - the code is extremely hard to follow, due to the include maze and
>   the various levels of inline functions that have forward
>   declarations...
>
> - there is a subtle bug in the way the kernel on_accessible_stack()
>   helper has been rewritten
>
> - the config symbol for the protected unwinder is oddly placed

Hi Marc,

Thanks for doing this rework.

For the series:
Reviewed-by: Kalesh Singh <kaleshsingh@google.com>
Tested-by: Kalesh Singh <kaleshsingh@google.com>

Thanks,
Kalesh

>
> Instead of going for another round and missing the merge window, I
> propose to stash the following patches on top, which IMHO result in
> something much more readable.
>
> This series directly applies on top of Kalesh's.
>
> [1] https://lore.kernel.org/r/20220726073750.3219117-1-kaleshsingh@google.com
>
> Marc Zyngier (5):
>   KVM: arm64: Move PROTECTED_NVHE_STACKTRACE around
>   KVM: arm64: Move nVHE stacktrace unwinding into its own compilation
>     unit
>   KVM: arm64: Make unwind()/on_accessible_stack() per-unwinder functions
>   KVM: arm64: Move nVHE-only helpers into kvm/stacktrace.c
>   arm64: Update 'unwinder howto'
>
> Oliver Upton (1):
>   KVM: arm64: Don't open code ARRAY_SIZE()
>
>  arch/arm64/include/asm/stacktrace.h        |  74 -------
>  arch/arm64/include/asm/stacktrace/common.h |  69 ++-----
>  arch/arm64/include/asm/stacktrace/nvhe.h   | 125 +-----------
>  arch/arm64/kernel/stacktrace.c             |  90 +++++++++
>  arch/arm64/kvm/Kconfig                     |  24 ++-
>  arch/arm64/kvm/Makefile                    |   2 +-
>  arch/arm64/kvm/handle_exit.c               |  98 ---------
>  arch/arm64/kvm/hyp/nvhe/stacktrace.c       |  55 +++++-
>  arch/arm64/kvm/stacktrace.c                | 218 +++++++++++++++++++++
>  9 files changed, 394 insertions(+), 361 deletions(-)
>  create mode 100644 arch/arm64/kvm/stacktrace.c
>
> --
> 2.34.1
>

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 112+ messages in thread

* Re: [PATCH 0/6] KVM: arm64: nVHE stack unwinder rework
  2022-07-27 14:29     ` Marc Zyngier
  (?)
@ 2022-07-27 16:01       ` Oliver Upton
  -1 siblings, 0 replies; 112+ messages in thread
From: Oliver Upton @ 2022-07-27 16:01 UTC (permalink / raw)
  To: Marc Zyngier
  Cc: linux-arm-kernel, kvmarm, kvm, mark.rutland, broonie, madvenka,
	tabba, qperret, kaleshsingh, james.morse, alexandru.elisei,
	suzuki.poulose, catalin.marinas, andreyknvl, vincenzo.frascino,
	mhiramat, ast, wangkefeng.wang, elver, keirf, yuzenghui, ardb,
	kernel-team

On Wed, Jul 27, 2022 at 03:29:00PM +0100, Marc Zyngier wrote:
> Hi all,
> 
> As Kalesh's series[1] already went through quite a few rounds and that
> it has proved to be an extremely useful debugging help, I'd like to
> queue it for 5.20.
> 
> However, there is a couple of nits that I'd like to address:
> 
> - the code is extremely hard to follow, due to the include maze and
>   the various levels of inline functions that have forward
>   declarations...
> 
> - there is a subtle bug in the way the kernel on_accessible_stack()
>   helper has been rewritten
> 
> - the config symbol for the protected unwinder is oddly placed
> 
> Instead of going for another round and missing the merge window, I
> propose to stash the following patches on top, which IMHO result in
> something much more readable.
> 
> This series directly applies on top of Kalesh's.
> 
> [1] https://lore.kernel.org/r/20220726073750.3219117-1-kaleshsingh@google.com

For the series (besides my own patch of course):

Reviewed-by: Oliver Upton <oliver.upton@linux.dev>

--
Thanks,
Oliver

^ permalink raw reply	[flat|nested] 112+ messages in thread

* Re: [PATCH 0/6] KVM: arm64: nVHE stack unwinder rework
@ 2022-07-27 16:01       ` Oliver Upton
  0 siblings, 0 replies; 112+ messages in thread
From: Oliver Upton @ 2022-07-27 16:01 UTC (permalink / raw)
  To: Marc Zyngier
  Cc: wangkefeng.wang, kvm, catalin.marinas, ast, vincenzo.frascino,
	kvmarm, madvenka, linux-arm-kernel, kernel-team, elver, broonie,
	andreyknvl, mhiramat

On Wed, Jul 27, 2022 at 03:29:00PM +0100, Marc Zyngier wrote:
> Hi all,
> 
> As Kalesh's series[1] already went through quite a few rounds and that
> it has proved to be an extremely useful debugging help, I'd like to
> queue it for 5.20.
> 
> However, there is a couple of nits that I'd like to address:
> 
> - the code is extremely hard to follow, due to the include maze and
>   the various levels of inline functions that have forward
>   declarations...
> 
> - there is a subtle bug in the way the kernel on_accessible_stack()
>   helper has been rewritten
> 
> - the config symbol for the protected unwinder is oddly placed
> 
> Instead of going for another round and missing the merge window, I
> propose to stash the following patches on top, which IMHO result in
> something much more readable.
> 
> This series directly applies on top of Kalesh's.
> 
> [1] https://lore.kernel.org/r/20220726073750.3219117-1-kaleshsingh@google.com

For the series (besides my own patch of course):

Reviewed-by: Oliver Upton <oliver.upton@linux.dev>

--
Thanks,
Oliver
_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply	[flat|nested] 112+ messages in thread

* Re: [PATCH 0/6] KVM: arm64: nVHE stack unwinder rework
@ 2022-07-27 16:01       ` Oliver Upton
  0 siblings, 0 replies; 112+ messages in thread
From: Oliver Upton @ 2022-07-27 16:01 UTC (permalink / raw)
  To: Marc Zyngier
  Cc: linux-arm-kernel, kvmarm, kvm, mark.rutland, broonie, madvenka,
	tabba, qperret, kaleshsingh, james.morse, alexandru.elisei,
	suzuki.poulose, catalin.marinas, andreyknvl, vincenzo.frascino,
	mhiramat, ast, wangkefeng.wang, elver, keirf, yuzenghui, ardb,
	kernel-team

On Wed, Jul 27, 2022 at 03:29:00PM +0100, Marc Zyngier wrote:
> Hi all,
> 
> As Kalesh's series[1] already went through quite a few rounds and that
> it has proved to be an extremely useful debugging help, I'd like to
> queue it for 5.20.
> 
> However, there is a couple of nits that I'd like to address:
> 
> - the code is extremely hard to follow, due to the include maze and
>   the various levels of inline functions that have forward
>   declarations...
> 
> - there is a subtle bug in the way the kernel on_accessible_stack()
>   helper has been rewritten
> 
> - the config symbol for the protected unwinder is oddly placed
> 
> Instead of going for another round and missing the merge window, I
> propose to stash the following patches on top, which IMHO result in
> something much more readable.
> 
> This series directly applies on top of Kalesh's.
> 
> [1] https://lore.kernel.org/r/20220726073750.3219117-1-kaleshsingh@google.com

For the series (besides my own patch of course):

Reviewed-by: Oliver Upton <oliver.upton@linux.dev>

--
Thanks,
Oliver

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 112+ messages in thread

* Re: [PATCH 3/6] KVM: arm64: Make unwind()/on_accessible_stack() per-unwinder functions
  2022-07-27 14:29       ` Marc Zyngier
  (?)
@ 2022-07-27 17:32         ` Mark Brown
  -1 siblings, 0 replies; 112+ messages in thread
From: Mark Brown @ 2022-07-27 17:32 UTC (permalink / raw)
  To: Marc Zyngier
  Cc: wangkefeng.wang, kvm, catalin.marinas, ast, vincenzo.frascino,
	kvmarm, madvenka, kernel-team, elver, linux-arm-kernel,
	andreyknvl, mhiramat


[-- Attachment #1.1: Type: text/plain, Size: 753 bytes --]

On Wed, Jul 27, 2022 at 03:29:03PM +0100, Marc Zyngier wrote:
> Having multiple versions of on_accessible_stack() (one per unwinder)
> makes it very hard to reason about what is used where due to the
> complexity of the various includes, the forward declarations, and
> the reliance on everything being 'inline'.
> 
> Instead, move the code back where it should be. Each unwinder
> implements:
> 
> - on_accessible_stack() as well as the helpers it depends on,
> 
> - unwind()/unwind_next(), as they pass on_accessible_stack as
>   a parameter to unwind_next_common() (which is the only common
>   code here)

Reviewed-by: Mark Brown <broonie@kernel.org>

It feels like more of the accessibility stuff *should* be sharable, but
yeah.

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

[-- Attachment #2: Type: text/plain, Size: 151 bytes --]

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply	[flat|nested] 112+ messages in thread

* Re: [PATCH 3/6] KVM: arm64: Make unwind()/on_accessible_stack() per-unwinder functions
@ 2022-07-27 17:32         ` Mark Brown
  0 siblings, 0 replies; 112+ messages in thread
From: Mark Brown @ 2022-07-27 17:32 UTC (permalink / raw)
  To: Marc Zyngier
  Cc: linux-arm-kernel, kvmarm, kvm, mark.rutland, madvenka, tabba,
	oliver.upton, qperret, kaleshsingh, james.morse,
	alexandru.elisei, suzuki.poulose, catalin.marinas, andreyknvl,
	vincenzo.frascino, mhiramat, ast, wangkefeng.wang, elver, keirf,
	yuzenghui, ardb, oupton, kernel-team


[-- Attachment #1.1: Type: text/plain, Size: 753 bytes --]

On Wed, Jul 27, 2022 at 03:29:03PM +0100, Marc Zyngier wrote:
> Having multiple versions of on_accessible_stack() (one per unwinder)
> makes it very hard to reason about what is used where due to the
> complexity of the various includes, the forward declarations, and
> the reliance on everything being 'inline'.
> 
> Instead, move the code back where it should be. Each unwinder
> implements:
> 
> - on_accessible_stack() as well as the helpers it depends on,
> 
> - unwind()/unwind_next(), as they pass on_accessible_stack as
>   a parameter to unwind_next_common() (which is the only common
>   code here)

Reviewed-by: Mark Brown <broonie@kernel.org>

It feels like more of the accessibility stuff *should* be sharable, but
yeah.

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

[-- Attachment #2: Type: text/plain, Size: 176 bytes --]

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 112+ messages in thread

* Re: [PATCH 3/6] KVM: arm64: Make unwind()/on_accessible_stack() per-unwinder functions
@ 2022-07-27 17:32         ` Mark Brown
  0 siblings, 0 replies; 112+ messages in thread
From: Mark Brown @ 2022-07-27 17:32 UTC (permalink / raw)
  To: Marc Zyngier
  Cc: linux-arm-kernel, kvmarm, kvm, mark.rutland, madvenka, tabba,
	oliver.upton, qperret, kaleshsingh, james.morse,
	alexandru.elisei, suzuki.poulose, catalin.marinas, andreyknvl,
	vincenzo.frascino, mhiramat, ast, wangkefeng.wang, elver, keirf,
	yuzenghui, ardb, oupton, kernel-team

[-- Attachment #1: Type: text/plain, Size: 753 bytes --]

On Wed, Jul 27, 2022 at 03:29:03PM +0100, Marc Zyngier wrote:
> Having multiple versions of on_accessible_stack() (one per unwinder)
> makes it very hard to reason about what is used where due to the
> complexity of the various includes, the forward declarations, and
> the reliance on everything being 'inline'.
> 
> Instead, move the code back where it should be. Each unwinder
> implements:
> 
> - on_accessible_stack() as well as the helpers it depends on,
> 
> - unwind()/unwind_next(), as they pass on_accessible_stack as
>   a parameter to unwind_next_common() (which is the only common
>   code here)

Reviewed-by: Mark Brown <broonie@kernel.org>

It feels like more of the accessibility stuff *should* be sharable, but
yeah.

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 112+ messages in thread

* Re: [PATCH v6 00/17] KVM nVHE Hypervisor stack unwinder
  2022-07-26  7:37 ` Kalesh Singh
  (?)
@ 2022-07-27 17:44   ` Marc Zyngier
  -1 siblings, 0 replies; 112+ messages in thread
From: Marc Zyngier @ 2022-07-27 17:44 UTC (permalink / raw)
  To: tabba, oliver.upton, broonie, Kalesh Singh, mark.rutland, madvenka
  Cc: android-mm, wangkefeng.wang, kernel-team, catalin.marinas, elver,
	ast, linux-kernel, mhiramat, vincenzo.frascino, will, kvmarm,
	linux-arm-kernel, andreyknvl

On Tue, 26 Jul 2022 00:37:33 -0700, Kalesh Singh wrote:
> This is v6 of nVHE stacktrace support. The series is based on
> arm64 for-next/stacktrace.
> 
> The previous versions were posted at:
> v5: https://lore.kernel.org/r/20220721055728.718573-1-kaleshsingh@google.com/
> v4: https://lore.kernel.org/r/20220715061027.1612149-1-kaleshsingh@google.com/
> v3: https://lore.kernel.org/r/20220607165105.639716-1-kaleshsingh@google.com/
> v2: https://lore.kernel.org/r/20220502191222.4192768-1-kaleshsingh@google.com/
> v1: https://lore.kernel.org/r/20220427184716.1949239-1-kaleshsingh@google.com/
> 
> [...]

Applied to next, thanks!

[01/17] arm64: stacktrace: Add shared header for common stack unwinding code
        commit: 6bf212c89c48458d8deef1c973678c62528dab04
[02/17] arm64: stacktrace: Factor out on_accessible_stack_common()
        commit: 15a59f19a015185bff90a68f601caec151dea4b4
[03/17] arm64: stacktrace: Factor out unwind_next_common()
        commit: be63c647fd28d25484257f5f36a008db7d99991d
[04/17] arm64: stacktrace: Handle frame pointer from different address spaces
        commit: 5b1b08619f50422c3e43d1fd7af257595a9e4a67
[05/17] arm64: stacktrace: Factor out common unwind()
        commit: f51e7146740514347d6c5526a2c393e224a19c0d
[06/17] arm64: stacktrace: Add description of stacktrace/common.h
        commit: 051ece6758cc10c2a6f1700ffe86d23fbb0b2553
[07/17] KVM: arm64: On stack overflow switch to hyp overflow_stack
        commit: 548ec3336f323db56260b312c232ab37285f0284
[08/17] KVM: arm64: Stub implementation of non-protected nVHE HYP stack unwinder
        commit: 573e1e8275f7167ddd533c6e4e0f500f8be4d974
[09/17] KVM: arm64: Prepare non-protected nVHE hypervisor stacktrace
        commit: 879e5ac7b2e4db05799a905b5a07fc9e5dedf651
[10/17] KVM: arm64: Implement non-protected nVHE hyp stack unwinder
        commit: db129d486ebdf4e3168282236f9d9008b42cac7e
[11/17] KVM: arm64: Introduce hyp_dump_backtrace()
        commit: 314a61dc31845c233e47c53db3fe6f34284034f4
[12/17] KVM: arm64: Add PROTECTED_NVHE_STACKTRACE Kconfig
        commit: 72adac1bd234002a65cef738e0eebfd6c2ce2e30
[13/17] KVM: arm64: Allocate shared pKVM hyp stacktrace buffers
        commit: 6928bcc84bc4bd9a24a1cb1986418c3de76e1d99
[14/17] KVM: arm64: Stub implementation of pKVM HYP stack unwinder
        commit: 25aa73b6db1831527cd4f14bf0ddf8dceadec802
[15/17] KVM: arm64: Save protected-nVHE (pKVM) hyp stacktrace
        commit: 871c5d931417d3c0e1aa32c9e04da1dc74703843
[16/17] KVM: arm64: Implement protected nVHE hyp stack unwinder
        commit: 75e9459e48d4867caf549e388bd4faabe1dbcbd3
[17/17] KVM: arm64: Introduce pkvm_dump_backtrace()
        commit: 3a7e1b55aad45c0cf86bd4e2f212bb9a61905142

Cheers,

	M.
-- 
Marc Zyngier <maz@kernel.org>

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply	[flat|nested] 112+ messages in thread

* Re: [PATCH v6 00/17] KVM nVHE Hypervisor stack unwinder
@ 2022-07-27 17:44   ` Marc Zyngier
  0 siblings, 0 replies; 112+ messages in thread
From: Marc Zyngier @ 2022-07-27 17:44 UTC (permalink / raw)
  To: tabba, oliver.upton, broonie, Kalesh Singh, mark.rutland, madvenka
  Cc: andreyknvl, kvmarm, will, wangkefeng.wang, catalin.marinas,
	vincenzo.frascino, ast, kernel-team, elver, mhiramat,
	linux-kernel, linux-arm-kernel, android-mm

On Tue, 26 Jul 2022 00:37:33 -0700, Kalesh Singh wrote:
> This is v6 of nVHE stacktrace support. The series is based on
> arm64 for-next/stacktrace.
> 
> The previous versions were posted at:
> v5: https://lore.kernel.org/r/20220721055728.718573-1-kaleshsingh@google.com/
> v4: https://lore.kernel.org/r/20220715061027.1612149-1-kaleshsingh@google.com/
> v3: https://lore.kernel.org/r/20220607165105.639716-1-kaleshsingh@google.com/
> v2: https://lore.kernel.org/r/20220502191222.4192768-1-kaleshsingh@google.com/
> v1: https://lore.kernel.org/r/20220427184716.1949239-1-kaleshsingh@google.com/
> 
> [...]

Applied to next, thanks!

[01/17] arm64: stacktrace: Add shared header for common stack unwinding code
        commit: 6bf212c89c48458d8deef1c973678c62528dab04
[02/17] arm64: stacktrace: Factor out on_accessible_stack_common()
        commit: 15a59f19a015185bff90a68f601caec151dea4b4
[03/17] arm64: stacktrace: Factor out unwind_next_common()
        commit: be63c647fd28d25484257f5f36a008db7d99991d
[04/17] arm64: stacktrace: Handle frame pointer from different address spaces
        commit: 5b1b08619f50422c3e43d1fd7af257595a9e4a67
[05/17] arm64: stacktrace: Factor out common unwind()
        commit: f51e7146740514347d6c5526a2c393e224a19c0d
[06/17] arm64: stacktrace: Add description of stacktrace/common.h
        commit: 051ece6758cc10c2a6f1700ffe86d23fbb0b2553
[07/17] KVM: arm64: On stack overflow switch to hyp overflow_stack
        commit: 548ec3336f323db56260b312c232ab37285f0284
[08/17] KVM: arm64: Stub implementation of non-protected nVHE HYP stack unwinder
        commit: 573e1e8275f7167ddd533c6e4e0f500f8be4d974
[09/17] KVM: arm64: Prepare non-protected nVHE hypervisor stacktrace
        commit: 879e5ac7b2e4db05799a905b5a07fc9e5dedf651
[10/17] KVM: arm64: Implement non-protected nVHE hyp stack unwinder
        commit: db129d486ebdf4e3168282236f9d9008b42cac7e
[11/17] KVM: arm64: Introduce hyp_dump_backtrace()
        commit: 314a61dc31845c233e47c53db3fe6f34284034f4
[12/17] KVM: arm64: Add PROTECTED_NVHE_STACKTRACE Kconfig
        commit: 72adac1bd234002a65cef738e0eebfd6c2ce2e30
[13/17] KVM: arm64: Allocate shared pKVM hyp stacktrace buffers
        commit: 6928bcc84bc4bd9a24a1cb1986418c3de76e1d99
[14/17] KVM: arm64: Stub implementation of pKVM HYP stack unwinder
        commit: 25aa73b6db1831527cd4f14bf0ddf8dceadec802
[15/17] KVM: arm64: Save protected-nVHE (pKVM) hyp stacktrace
        commit: 871c5d931417d3c0e1aa32c9e04da1dc74703843
[16/17] KVM: arm64: Implement protected nVHE hyp stack unwinder
        commit: 75e9459e48d4867caf549e388bd4faabe1dbcbd3
[17/17] KVM: arm64: Introduce pkvm_dump_backtrace()
        commit: 3a7e1b55aad45c0cf86bd4e2f212bb9a61905142

Cheers,

	M.
-- 
Marc Zyngier <maz@kernel.org>


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 112+ messages in thread

* Re: [PATCH v6 00/17] KVM nVHE Hypervisor stack unwinder
@ 2022-07-27 17:44   ` Marc Zyngier
  0 siblings, 0 replies; 112+ messages in thread
From: Marc Zyngier @ 2022-07-27 17:44 UTC (permalink / raw)
  To: tabba, oliver.upton, broonie, Kalesh Singh, mark.rutland, madvenka
  Cc: andreyknvl, kvmarm, will, wangkefeng.wang, catalin.marinas,
	vincenzo.frascino, ast, kernel-team, elver, mhiramat,
	linux-kernel, linux-arm-kernel, android-mm

On Tue, 26 Jul 2022 00:37:33 -0700, Kalesh Singh wrote:
> This is v6 of nVHE stacktrace support. The series is based on
> arm64 for-next/stacktrace.
> 
> The previous versions were posted at:
> v5: https://lore.kernel.org/r/20220721055728.718573-1-kaleshsingh@google.com/
> v4: https://lore.kernel.org/r/20220715061027.1612149-1-kaleshsingh@google.com/
> v3: https://lore.kernel.org/r/20220607165105.639716-1-kaleshsingh@google.com/
> v2: https://lore.kernel.org/r/20220502191222.4192768-1-kaleshsingh@google.com/
> v1: https://lore.kernel.org/r/20220427184716.1949239-1-kaleshsingh@google.com/
> 
> [...]

Applied to next, thanks!

[01/17] arm64: stacktrace: Add shared header for common stack unwinding code
        commit: 6bf212c89c48458d8deef1c973678c62528dab04
[02/17] arm64: stacktrace: Factor out on_accessible_stack_common()
        commit: 15a59f19a015185bff90a68f601caec151dea4b4
[03/17] arm64: stacktrace: Factor out unwind_next_common()
        commit: be63c647fd28d25484257f5f36a008db7d99991d
[04/17] arm64: stacktrace: Handle frame pointer from different address spaces
        commit: 5b1b08619f50422c3e43d1fd7af257595a9e4a67
[05/17] arm64: stacktrace: Factor out common unwind()
        commit: f51e7146740514347d6c5526a2c393e224a19c0d
[06/17] arm64: stacktrace: Add description of stacktrace/common.h
        commit: 051ece6758cc10c2a6f1700ffe86d23fbb0b2553
[07/17] KVM: arm64: On stack overflow switch to hyp overflow_stack
        commit: 548ec3336f323db56260b312c232ab37285f0284
[08/17] KVM: arm64: Stub implementation of non-protected nVHE HYP stack unwinder
        commit: 573e1e8275f7167ddd533c6e4e0f500f8be4d974
[09/17] KVM: arm64: Prepare non-protected nVHE hypervisor stacktrace
        commit: 879e5ac7b2e4db05799a905b5a07fc9e5dedf651
[10/17] KVM: arm64: Implement non-protected nVHE hyp stack unwinder
        commit: db129d486ebdf4e3168282236f9d9008b42cac7e
[11/17] KVM: arm64: Introduce hyp_dump_backtrace()
        commit: 314a61dc31845c233e47c53db3fe6f34284034f4
[12/17] KVM: arm64: Add PROTECTED_NVHE_STACKTRACE Kconfig
        commit: 72adac1bd234002a65cef738e0eebfd6c2ce2e30
[13/17] KVM: arm64: Allocate shared pKVM hyp stacktrace buffers
        commit: 6928bcc84bc4bd9a24a1cb1986418c3de76e1d99
[14/17] KVM: arm64: Stub implementation of pKVM HYP stack unwinder
        commit: 25aa73b6db1831527cd4f14bf0ddf8dceadec802
[15/17] KVM: arm64: Save protected-nVHE (pKVM) hyp stacktrace
        commit: 871c5d931417d3c0e1aa32c9e04da1dc74703843
[16/17] KVM: arm64: Implement protected nVHE hyp stack unwinder
        commit: 75e9459e48d4867caf549e388bd4faabe1dbcbd3
[17/17] KVM: arm64: Introduce pkvm_dump_backtrace()
        commit: 3a7e1b55aad45c0cf86bd4e2f212bb9a61905142

Cheers,

	M.
-- 
Marc Zyngier <maz@kernel.org>


^ permalink raw reply	[flat|nested] 112+ messages in thread

* Re: [PATCH 0/6] KVM: arm64: nVHE stack unwinder rework
  2022-07-27 14:29     ` Marc Zyngier
  (?)
@ 2022-07-27 17:45       ` Marc Zyngier
  -1 siblings, 0 replies; 112+ messages in thread
From: Marc Zyngier @ 2022-07-27 17:45 UTC (permalink / raw)
  To: Marc Zyngier, kvm, kvmarm, linux-arm-kernel
  Cc: wangkefeng.wang, catalin.marinas, ast, vincenzo.frascino,
	madvenka, kernel-team, elver, broonie, andreyknvl, mhiramat

On Wed, 27 Jul 2022 15:29:00 +0100, Marc Zyngier wrote:
> As Kalesh's series[1] already went through quite a few rounds and that
> it has proved to be an extremely useful debugging help, I'd like to
> queue it for 5.20.
> 
> However, there is a couple of nits that I'd like to address:
> 
> - the code is extremely hard to follow, due to the include maze and
>   the various levels of inline functions that have forward
>   declarations...
> 
> [...]

Applied to next, thanks!

[1/6] KVM: arm64: Move PROTECTED_NVHE_STACKTRACE around
      commit: 03fe9cd05b9f38353208c23bd791dac47c912054
[2/6] KVM: arm64: Move nVHE stacktrace unwinding into its own compilation unit
      commit: 9f5fee05f6897d0fe0e3a44ade71bb85cd97b2ef
[3/6] KVM: arm64: Make unwind()/on_accessible_stack() per-unwinder functions
      commit: 4e00532f37365967e9896966b1fe61888e659259
[4/6] KVM: arm64: Move nVHE-only helpers into kvm/stacktrace.c
      commit: 0e773da1e688a1425ef7deae58fa11c5c7e09533
[5/6] KVM: arm64: Don't open code ARRAY_SIZE()
      commit: 62ae21627aa96f6ef361981dd181c74dc7aa314c
[6/6] arm64: Update 'unwinder howto'
      commit: a4c750e2328a117dc9b19a2a61db0d4347902029

Cheers,

	M.
-- 
Marc Zyngier <maz@kernel.org>

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply	[flat|nested] 112+ messages in thread

* Re: [PATCH 0/6] KVM: arm64: nVHE stack unwinder rework
@ 2022-07-27 17:45       ` Marc Zyngier
  0 siblings, 0 replies; 112+ messages in thread
From: Marc Zyngier @ 2022-07-27 17:45 UTC (permalink / raw)
  To: Marc Zyngier, kvm, kvmarm, linux-arm-kernel
  Cc: keirf, kaleshsingh, catalin.marinas, broonie, madvenka, qperret,
	wangkefeng.wang, tabba, ast, vincenzo.frascino, elver,
	mark.rutland, mhiramat, oupton, james.morse, oliver.upton,
	suzuki.poulose, kernel-team, alexandru.elisei, ardb, andreyknvl,
	yuzenghui

On Wed, 27 Jul 2022 15:29:00 +0100, Marc Zyngier wrote:
> As Kalesh's series[1] already went through quite a few rounds and that
> it has proved to be an extremely useful debugging help, I'd like to
> queue it for 5.20.
> 
> However, there is a couple of nits that I'd like to address:
> 
> - the code is extremely hard to follow, due to the include maze and
>   the various levels of inline functions that have forward
>   declarations...
> 
> [...]

Applied to next, thanks!

[1/6] KVM: arm64: Move PROTECTED_NVHE_STACKTRACE around
      commit: 03fe9cd05b9f38353208c23bd791dac47c912054
[2/6] KVM: arm64: Move nVHE stacktrace unwinding into its own compilation unit
      commit: 9f5fee05f6897d0fe0e3a44ade71bb85cd97b2ef
[3/6] KVM: arm64: Make unwind()/on_accessible_stack() per-unwinder functions
      commit: 4e00532f37365967e9896966b1fe61888e659259
[4/6] KVM: arm64: Move nVHE-only helpers into kvm/stacktrace.c
      commit: 0e773da1e688a1425ef7deae58fa11c5c7e09533
[5/6] KVM: arm64: Don't open code ARRAY_SIZE()
      commit: 62ae21627aa96f6ef361981dd181c74dc7aa314c
[6/6] arm64: Update 'unwinder howto'
      commit: a4c750e2328a117dc9b19a2a61db0d4347902029

Cheers,

	M.
-- 
Marc Zyngier <maz@kernel.org>


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 112+ messages in thread

* Re: [PATCH 0/6] KVM: arm64: nVHE stack unwinder rework
@ 2022-07-27 17:45       ` Marc Zyngier
  0 siblings, 0 replies; 112+ messages in thread
From: Marc Zyngier @ 2022-07-27 17:45 UTC (permalink / raw)
  To: Marc Zyngier, kvm, kvmarm, linux-arm-kernel
  Cc: keirf, kaleshsingh, catalin.marinas, broonie, madvenka, qperret,
	wangkefeng.wang, tabba, ast, vincenzo.frascino, elver,
	mark.rutland, mhiramat, oupton, james.morse, oliver.upton,
	suzuki.poulose, kernel-team, alexandru.elisei, ardb, andreyknvl,
	yuzenghui

On Wed, 27 Jul 2022 15:29:00 +0100, Marc Zyngier wrote:
> As Kalesh's series[1] already went through quite a few rounds and that
> it has proved to be an extremely useful debugging help, I'd like to
> queue it for 5.20.
> 
> However, there is a couple of nits that I'd like to address:
> 
> - the code is extremely hard to follow, due to the include maze and
>   the various levels of inline functions that have forward
>   declarations...
> 
> [...]

Applied to next, thanks!

[1/6] KVM: arm64: Move PROTECTED_NVHE_STACKTRACE around
      commit: 03fe9cd05b9f38353208c23bd791dac47c912054
[2/6] KVM: arm64: Move nVHE stacktrace unwinding into its own compilation unit
      commit: 9f5fee05f6897d0fe0e3a44ade71bb85cd97b2ef
[3/6] KVM: arm64: Make unwind()/on_accessible_stack() per-unwinder functions
      commit: 4e00532f37365967e9896966b1fe61888e659259
[4/6] KVM: arm64: Move nVHE-only helpers into kvm/stacktrace.c
      commit: 0e773da1e688a1425ef7deae58fa11c5c7e09533
[5/6] KVM: arm64: Don't open code ARRAY_SIZE()
      commit: 62ae21627aa96f6ef361981dd181c74dc7aa314c
[6/6] arm64: Update 'unwinder howto'
      commit: a4c750e2328a117dc9b19a2a61db0d4347902029

Cheers,

	M.
-- 
Marc Zyngier <maz@kernel.org>


^ permalink raw reply	[flat|nested] 112+ messages in thread

end of thread, other threads:[~2022-07-27 18:48 UTC | newest]

Thread overview: 112+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-07-26  7:37 [PATCH v6 00/17] KVM nVHE Hypervisor stack unwinder Kalesh Singh
2022-07-26  7:37 ` Kalesh Singh
2022-07-26  7:37 ` Kalesh Singh
2022-07-26  7:37 ` [PATCH v6 01/17] arm64: stacktrace: Add shared header for common stack unwinding code Kalesh Singh
2022-07-26  7:37   ` Kalesh Singh
2022-07-26  7:37   ` Kalesh Singh
2022-07-26  7:37 ` [PATCH v6 02/17] arm64: stacktrace: Factor out on_accessible_stack_common() Kalesh Singh
2022-07-26  7:37   ` Kalesh Singh
2022-07-26  7:37   ` Kalesh Singh
2022-07-26 16:01   ` Marc Zyngier
2022-07-26 16:01     ` Marc Zyngier
2022-07-26 16:01     ` Marc Zyngier
2022-07-26 16:33     ` Kalesh Singh
2022-07-26 16:33       ` Kalesh Singh
2022-07-26 16:33       ` Kalesh Singh
2022-07-26  7:37 ` [PATCH v6 03/17] arm64: stacktrace: Factor out unwind_next_common() Kalesh Singh
2022-07-26  7:37   ` Kalesh Singh
2022-07-26  7:37   ` Kalesh Singh
2022-07-26  7:37 ` [PATCH v6 04/17] arm64: stacktrace: Handle frame pointer from different address spaces Kalesh Singh
2022-07-26  7:37   ` Kalesh Singh
2022-07-26  7:37   ` Kalesh Singh
2022-07-26 14:34   ` Mark Brown
2022-07-26 14:34     ` Mark Brown
2022-07-26 14:34     ` Mark Brown
2022-07-26 15:30     ` Kalesh Singh
2022-07-26 15:30       ` Kalesh Singh
2022-07-26 15:30       ` Kalesh Singh
2022-07-26  7:37 ` [PATCH v6 05/17] arm64: stacktrace: Factor out common unwind() Kalesh Singh
2022-07-26  7:37   ` Kalesh Singh
2022-07-26  7:37   ` Kalesh Singh
2022-07-26  7:37 ` [PATCH v6 06/17] arm64: stacktrace: Add description of stacktrace/common.h Kalesh Singh
2022-07-26  7:37   ` Kalesh Singh
2022-07-26  7:37   ` Kalesh Singh
2022-07-26 14:49   ` Mark Brown
2022-07-26 14:49     ` Mark Brown
2022-07-26 14:49     ` Mark Brown
2022-07-26  7:37 ` [PATCH v6 07/17] KVM: arm64: On stack overflow switch to hyp overflow_stack Kalesh Singh
2022-07-26  7:37   ` Kalesh Singh
2022-07-26  7:37   ` Kalesh Singh
2022-07-26  7:37 ` [PATCH v6 08/17] KVM: arm64: Stub implementation of non-protected nVHE HYP stack unwinder Kalesh Singh
2022-07-26  7:37   ` Kalesh Singh
2022-07-26  7:37   ` Kalesh Singh
2022-07-26  7:37 ` [PATCH v6 09/17] KVM: arm64: Prepare non-protected nVHE hypervisor stacktrace Kalesh Singh
2022-07-26  7:37   ` Kalesh Singh
2022-07-26  7:37   ` Kalesh Singh
2022-07-26 16:26   ` kernel test robot
2022-07-26  7:37 ` [PATCH v6 10/17] KVM: arm64: Implement non-protected nVHE hyp stack unwinder Kalesh Singh
2022-07-26  7:37   ` Kalesh Singh
2022-07-26  7:37   ` Kalesh Singh
2022-07-26  7:37 ` [PATCH v6 11/17] KVM: arm64: Introduce hyp_dump_backtrace() Kalesh Singh
2022-07-26  7:37   ` Kalesh Singh
2022-07-26  7:37   ` Kalesh Singh
2022-07-26  7:37 ` [PATCH v6 12/17] KVM: arm64: Add PROTECTED_NVHE_STACKTRACE Kconfig Kalesh Singh
2022-07-26  7:37   ` Kalesh Singh
2022-07-26  7:37   ` Kalesh Singh
2022-07-26 10:00   ` Marc Zyngier
2022-07-26 10:00     ` Marc Zyngier
2022-07-26 10:00     ` Marc Zyngier
2022-07-26 15:33     ` Kalesh Singh
2022-07-26 15:33       ` Kalesh Singh
2022-07-26 15:33       ` Kalesh Singh
2022-07-26  7:37 ` [PATCH v6 13/17] KVM: arm64: Allocate shared pKVM hyp stacktrace buffers Kalesh Singh
2022-07-26  7:37   ` Kalesh Singh
2022-07-26  7:37   ` Kalesh Singh
2022-07-26  7:37 ` [PATCH v6 14/17] KVM: arm64: Stub implementation of pKVM HYP stack unwinder Kalesh Singh
2022-07-26  7:37   ` Kalesh Singh
2022-07-26  7:37   ` Kalesh Singh
2022-07-26  7:37 ` [PATCH v6 15/17] KVM: arm64: Save protected-nVHE (pKVM) hyp stacktrace Kalesh Singh
2022-07-26  7:37   ` Kalesh Singh
2022-07-26  7:37   ` Kalesh Singh
2022-07-26  7:37 ` [PATCH v6 16/17] KVM: arm64: Implement protected nVHE hyp stack unwinder Kalesh Singh
2022-07-26  7:37   ` Kalesh Singh
2022-07-26  7:37   ` Kalesh Singh
2022-07-26  7:37 ` [PATCH v6 17/17] KVM: arm64: Introduce pkvm_dump_backtrace() Kalesh Singh
2022-07-26  7:37   ` Kalesh Singh
2022-07-26  7:37   ` Kalesh Singh
2022-07-27 14:29   ` [PATCH 0/6] KVM: arm64: nVHE stack unwinder rework Marc Zyngier
2022-07-27 14:29     ` Marc Zyngier
2022-07-27 14:29     ` Marc Zyngier
2022-07-27 14:29     ` [PATCH 1/6] KVM: arm64: Move PROTECTED_NVHE_STACKTRACE around Marc Zyngier
2022-07-27 14:29       ` Marc Zyngier
2022-07-27 14:29       ` Marc Zyngier
2022-07-27 14:29     ` [PATCH 2/6] KVM: arm64: Move nVHE stacktrace unwinding into its own compilation unit Marc Zyngier
2022-07-27 14:29       ` Marc Zyngier
2022-07-27 14:29       ` Marc Zyngier
2022-07-27 14:29     ` [PATCH 3/6] KVM: arm64: Make unwind()/on_accessible_stack() per-unwinder functions Marc Zyngier
2022-07-27 14:29       ` Marc Zyngier
2022-07-27 14:29       ` Marc Zyngier
2022-07-27 17:32       ` Mark Brown
2022-07-27 17:32         ` Mark Brown
2022-07-27 17:32         ` Mark Brown
2022-07-27 14:29     ` [PATCH 4/6] KVM: arm64: Move nVHE-only helpers into kvm/stacktrace.c Marc Zyngier
2022-07-27 14:29       ` Marc Zyngier
2022-07-27 14:29       ` Marc Zyngier
2022-07-27 14:29     ` [PATCH 5/6] KVM: arm64: Don't open code ARRAY_SIZE() Marc Zyngier
2022-07-27 14:29       ` Marc Zyngier
2022-07-27 14:29       ` Marc Zyngier
2022-07-27 14:29     ` [PATCH 6/6] arm64: Update 'unwinder howto' Marc Zyngier
2022-07-27 14:29       ` Marc Zyngier
2022-07-27 14:29       ` Marc Zyngier
2022-07-27 15:56     ` [PATCH 0/6] KVM: arm64: nVHE stack unwinder rework Kalesh Singh
2022-07-27 15:56       ` Kalesh Singh
2022-07-27 15:56       ` Kalesh Singh
2022-07-27 16:01     ` Oliver Upton
2022-07-27 16:01       ` Oliver Upton
2022-07-27 16:01       ` Oliver Upton
2022-07-27 17:45     ` Marc Zyngier
2022-07-27 17:45       ` Marc Zyngier
2022-07-27 17:45       ` Marc Zyngier
2022-07-27 17:44 ` [PATCH v6 00/17] KVM nVHE Hypervisor stack unwinder Marc Zyngier
2022-07-27 17:44   ` Marc Zyngier
2022-07-27 17:44   ` Marc Zyngier

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.