qemu-ppc
[Top][All Lists]
Advanced

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

[RFC PATCH 00/13] PowerPC interrupt rework


From: Matheus Ferst
Subject: [RFC PATCH 00/13] PowerPC interrupt rework
Date: Mon, 15 Aug 2022 13:20:06 -0300

Currently, PowerPC interrupts are handled as follows:

1) The CPU_INTERRUPT_HARD bit of cs->interrupt_request gates all
   interrupts;
2) The bits of env->pending_interrupts identify which particular
   interrupt is raised;
3) ppc_set_irq can be used to set/clear env->pending_interrupt bit and
   CPU_INTERRUPT_HARD, but some places access env->pending_interrupt
   directly;
4) ppc_cpu_exec_interrupt is called by cpu_handle_interrupt when
   cs->interrupt_request indicates that there is some interrupt pending.
   This method checks CPU_INTERRUPT_HARD and calls ppc_hw_interrupt. If
   env->pending_interrupt is zero after this call, CPU_INTERRUPT_HARD
   will be cleared.
5) ppc_hw_interrupt checks if there is any unmasked interrupt and calls
   powerpc_excp with the appropriate POWERPC_EXCP_* value. The method
   will also reset the corresponding bit in env->pending_interrupt for
   interrupts that clear on delivery.

If all pending interrupts are masked, CPU_INTERRUPT_HARD will be set,
but ppc_hw_interrupt will not deliver or clear the interrupt, so
CPU_INTERRUPT_HARD will not be reset by ppc_cpu_exec_interrupt. With
that, cs->has_work keeps returning true, creating a loop that acquires
and release qemu_mutex_lock_iothread, causing the poor performance
reported in [1].

This patch series attempts to rework the PowerPC interrupt code to set
CPU_INTERRUPT_HARD only when there are unmasked interrupts. Then
cs->has_work can be simplified to a check of CPU_INTERRUPT_HARD, so it
also only returns true when at least one interrupt can be delivered.

To achieve that, we are basically following Alex Bannée's suggestion[2]
in the original thread: the interrupt masking logic will be factored
out of ppc_hw_interrupt in a new method, ppc_pending_interrupts. This
method is then used to decide if CPU_INTERRUPT_HARD should be set or
cleared after changes to MSR, LPCR, env->pending_interrupts, and
power-management instructions.

We used [3] to check for regressions at each patch in this series. After
patch 12, booting a powernv machine with a newer skiboot with "-smp 4"
goes from 1m09s to 20.79s.

[1] https://lists.gnu.org/archive/html/qemu-ppc/2022-06/msg00336.html
[2] https://lists.gnu.org/archive/html/qemu-ppc/2022-06/msg00372.html
[3] https://github.com/legoater/qemu-ppc-boot

Matheus Ferst (13):
  target/ppc: define PPC_INTERRUPT_* values directly
  target/ppc: always use ppc_set_irq to set env->pending_interrupts
  target/ppc: move interrupt masking out of ppc_hw_interrupt
  target/ppc: prepare to split ppc_interrupt_pending by excp_model
  target/ppc: create a interrupt masking method for POWER9/POWER10
  target/ppc: remove embedded interrupts from ppc_pending_interrupt_p9
  target/ppc: create a interrupt masking method for POWER8
  target/ppc: remove unused interrupts from ppc_pending_interrupt_p8
  target/ppc: create a interrupt masking method for POWER7
  target/ppc: remove unused interrupts from ppc_pending_interrupt_p7
  target/ppc: remove ppc_store_lpcr from CONFIG_USER_ONLY builds
  target/ppc: introduce ppc_maybe_interrupt
  target/ppc: unify cpu->has_work based on cs->interrupt_request

 hw/ppc/ppc.c             |  17 +-
 hw/ppc/trace-events      |   2 +-
 target/ppc/cpu.c         |   2 +
 target/ppc/cpu.h         |  43 +--
 target/ppc/cpu_init.c    | 212 +------------
 target/ppc/excp_helper.c | 651 ++++++++++++++++++++++++++++++++-------
 target/ppc/helper_regs.c |   2 +
 target/ppc/misc_helper.c |  11 +-
 target/ppc/translate.c   |   8 +-
 9 files changed, 580 insertions(+), 368 deletions(-)

-- 
2.25.1




reply via email to

[Prev in Thread] Current Thread [Next in Thread]