mirror of
https://github.com/izzy2lost/xemu.git
synced 2026-07-06 00:20:22 -07:00
Merge tag 'pull-ppc-20250721' of https://github.com/legoater/qemu into staging
ppc/xive queue: * Various bug fixes around lost interrupts particularly. * Major group interrupt work, in particular around redistributing interrupts. Upstream group support is not in a complete or usable state as it is. * Significant context push/pull improvements, particularly pool and phys context handling was quite incomplete beyond trivial OPAL case that pushes at boot. * Improved tracing and checking for unimp and guest error situations. * Various other missing feature support. # -----BEGIN PGP SIGNATURE----- # # iQIzBAABCAAdFiEEoPZlSPBIlev+awtgUaNDx8/77KEFAmh951cACgkQUaNDx8/7 # 7KFK6w//SAmZpNmE380UN4OxMBcjsT5m5Cf2hy+Wq9pSEcwWckBFT03HyR86JAv3 # QLR1d6yx7dY0aVWAHtFC24vlU2jpv0Io97wfX9VbgG7e4TY/i1vRMSXYYehXuU/Y # gLrwuJGxAMKWrd+4ymvHOyXHRAq3LMGQQYfqLCB77b8UJ18JyCL8FwAl/D6EsZ1y # nUW8WlDy6qQ/SJQHZZ664kyJEv7Qw4xd81ZnmoPsy3xVd7c4ASNBWvDTjRoUn2EN # sfJW76UqqFn3EqASaKsqoNPHu3kklQ/AX3KlE1wFCBjYoXwl/051wIX4RIb+b2S4 # SLtc/YSAie1n2Pp1sghfLRFiRpjrmnqaLlw04Buw1TXY2OaQbFc9zTkc9rvFSez1 # cNjdJcvm3myAWy2Pg//Nt3FgCqfMlrrdTlyGsdqmrEaplBy6pHnas+82o5tPGC3t # SBMgTDqNMq0v/V/gOIsmHc5/9f+FS5s+v/nvm0xJDfLkY39qP73W+YZllYyyuTHY # HiLVjD7x5BSGZAsP9EN6EnL7DPXKPIIQSfNwo2564tAhe3/IyJo8hpGhMeiZ83Hf # G9oPiLa4YljsHzP0UPRNhID5IYyngEDoh2j3AXnew1tkikHd5LIpNCdbtW5x52RR # kik4hBmqJU6sYpO0O9yCd6YWv/Bpm4bDs6tQOSWMc6uWqP0qN8M= # =65BL # -----END PGP SIGNATURE----- # gpg: Signature made Mon 21 Jul 2025 03:08:07 EDT # gpg: using RSA key A0F66548F04895EBFE6B0B6051A343C7CFFBECA1 # gpg: Good signature from "Cédric Le Goater <clg@redhat.com>" [full] # gpg: aka "Cédric Le Goater <clg@kaod.org>" [full] # Primary key fingerprint: A0F6 6548 F048 95EB FE6B 0B60 51A3 43C7 CFFB ECA1 * tag 'pull-ppc-20250721' of https://github.com/legoater/qemu: (50 commits) ppc/xive2: Enable lower level contexts on VP push ppc/xive: Split need_resend into restore_nvp ppc/xive2: Implement PHYS ring VP push TIMA op ppc/xive2: Implement POOL LGS push TIMA op ppc/xive2: Implement set_os_pending TIMA op ppc/xive2: redistribute group interrupts on context push ppc/xive2: Implement pool context push TIMA op ppc/xive: Check TIMA operations validity ppc/xive: Redistribute phys after pulling of pool context ppc/xive2: Prevent pulling of pool context losing phys interrupt ppc/xive2: implement NVP context save restore for POOL ring ppc/xive: Assert group interrupts were redistributed ppc/xive2: Avoid needless interrupt re-check on CPPR set ppc/xive2: Consolidate presentation processing in context push ppc/xive2: split tctx presentation processing from set CPPR ppc/xive: Add xive_tctx_pipr_set() helper function ppc/xive: tctx_accept only lower irq line if an interrupt was presented ppc/xive: tctx signaling registers rework ppc/xive: Split xive recompute from IPB function ppc/xive: Fix high prio group interrupt being preempted by low prio VP ... Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
This commit is contained in:
+50
-16
@@ -365,6 +365,11 @@ static inline uint32_t xive_tctx_word2(uint8_t *ring)
|
||||
return *((uint32_t *) &ring[TM_WORD2]);
|
||||
}
|
||||
|
||||
bool xive_ring_valid(XiveTCTX *tctx, uint8_t ring);
|
||||
bool xive_nsr_indicates_exception(uint8_t ring, uint8_t nsr);
|
||||
bool xive_nsr_indicates_group_exception(uint8_t ring, uint8_t nsr);
|
||||
uint8_t xive_nsr_exception_ring(uint8_t ring, uint8_t nsr);
|
||||
|
||||
/*
|
||||
* XIVE Router
|
||||
*/
|
||||
@@ -421,6 +426,7 @@ void xive_router_end_notify(XiveRouter *xrtr, XiveEAS *eas);
|
||||
|
||||
typedef struct XiveTCTXMatch {
|
||||
XiveTCTX *tctx;
|
||||
int count;
|
||||
uint8_t ring;
|
||||
bool precluded;
|
||||
} XiveTCTXMatch;
|
||||
@@ -436,10 +442,10 @@ DECLARE_CLASS_CHECKERS(XivePresenterClass, XIVE_PRESENTER,
|
||||
|
||||
struct XivePresenterClass {
|
||||
InterfaceClass parent;
|
||||
int (*match_nvt)(XivePresenter *xptr, uint8_t format,
|
||||
uint8_t nvt_blk, uint32_t nvt_idx,
|
||||
bool crowd, bool cam_ignore, uint8_t priority,
|
||||
uint32_t logic_serv, XiveTCTXMatch *match);
|
||||
bool (*match_nvt)(XivePresenter *xptr, uint8_t format,
|
||||
uint8_t nvt_blk, uint32_t nvt_idx,
|
||||
bool crowd, bool cam_ignore, uint8_t priority,
|
||||
uint32_t logic_serv, XiveTCTXMatch *match);
|
||||
bool (*in_kernel)(const XivePresenter *xptr);
|
||||
uint32_t (*get_config)(XivePresenter *xptr);
|
||||
int (*broadcast)(XivePresenter *xptr,
|
||||
@@ -451,12 +457,14 @@ int xive_presenter_tctx_match(XivePresenter *xptr, XiveTCTX *tctx,
|
||||
uint8_t format,
|
||||
uint8_t nvt_blk, uint32_t nvt_idx,
|
||||
bool cam_ignore, uint32_t logic_serv);
|
||||
bool xive_presenter_notify(XiveFabric *xfb, uint8_t format,
|
||||
uint8_t nvt_blk, uint32_t nvt_idx,
|
||||
bool crowd, bool cam_ignore, uint8_t priority,
|
||||
uint32_t logic_serv, bool *precluded);
|
||||
bool xive_presenter_match(XiveFabric *xfb, uint8_t format,
|
||||
uint8_t nvt_blk, uint32_t nvt_idx,
|
||||
bool crowd, bool cam_ignore, uint8_t priority,
|
||||
uint32_t logic_serv, XiveTCTXMatch *match);
|
||||
|
||||
uint32_t xive_get_vpgroup_size(uint32_t nvp_index);
|
||||
uint8_t xive_get_group_level(bool crowd, bool ignore,
|
||||
uint32_t nvp_blk, uint32_t nvp_index);
|
||||
|
||||
/*
|
||||
* XIVE Fabric (Interface between Interrupt Controller and Machine)
|
||||
@@ -471,10 +479,10 @@ DECLARE_CLASS_CHECKERS(XiveFabricClass, XIVE_FABRIC,
|
||||
|
||||
struct XiveFabricClass {
|
||||
InterfaceClass parent;
|
||||
int (*match_nvt)(XiveFabric *xfb, uint8_t format,
|
||||
uint8_t nvt_blk, uint32_t nvt_idx,
|
||||
bool crowd, bool cam_ignore, uint8_t priority,
|
||||
uint32_t logic_serv, XiveTCTXMatch *match);
|
||||
bool (*match_nvt)(XiveFabric *xfb, uint8_t format,
|
||||
uint8_t nvt_blk, uint32_t nvt_idx,
|
||||
bool crowd, bool cam_ignore, uint8_t priority,
|
||||
uint32_t logic_serv, XiveTCTXMatch *match);
|
||||
int (*broadcast)(XiveFabric *xfb, uint8_t nvt_blk, uint32_t nvt_idx,
|
||||
bool crowd, bool cam_ignore, uint8_t priority);
|
||||
};
|
||||
@@ -532,7 +540,7 @@ static inline uint8_t xive_ipb_to_pipr(uint8_t ibp)
|
||||
}
|
||||
|
||||
/*
|
||||
* XIVE Thread Interrupt Management Aera (TIMA)
|
||||
* XIVE Thread Interrupt Management Area (TIMA)
|
||||
*
|
||||
* This region gives access to the registers of the thread interrupt
|
||||
* management context. It is four page wide, each page providing a
|
||||
@@ -544,6 +552,30 @@ static inline uint8_t xive_ipb_to_pipr(uint8_t ibp)
|
||||
#define XIVE_TM_OS_PAGE 0x2
|
||||
#define XIVE_TM_USER_PAGE 0x3
|
||||
|
||||
/*
|
||||
* The TCTX (TIMA) has 4 rings (phys, pool, os, user), but only signals
|
||||
* (raises an interrupt on) the CPU from 3 of them. Phys and pool both
|
||||
* cause a hypervisor privileged interrupt so interrupts presented on
|
||||
* those rings signal using the phys ring. This helper returns the signal
|
||||
* regs from the given ring.
|
||||
*/
|
||||
static inline uint8_t *xive_tctx_signal_regs(XiveTCTX *tctx, uint8_t ring)
|
||||
{
|
||||
/*
|
||||
* This is a good point to add invariants to ensure nothing has tried to
|
||||
* signal using the POOL ring.
|
||||
*/
|
||||
g_assert(tctx->regs[TM_QW2_HV_POOL + TM_NSR] == 0);
|
||||
g_assert(tctx->regs[TM_QW2_HV_POOL + TM_PIPR] == 0);
|
||||
g_assert(tctx->regs[TM_QW2_HV_POOL + TM_CPPR] == 0);
|
||||
|
||||
if (ring == TM_QW2_HV_POOL) {
|
||||
/* POOL and PHYS rings share the signal regs (PIPR, NSR, CPPR) */
|
||||
ring = TM_QW3_HV_PHYS;
|
||||
}
|
||||
return &tctx->regs[ring];
|
||||
}
|
||||
|
||||
void xive_tctx_tm_write(XivePresenter *xptr, XiveTCTX *tctx, hwaddr offset,
|
||||
uint64_t value, unsigned size);
|
||||
uint64_t xive_tctx_tm_read(XivePresenter *xptr, XiveTCTX *tctx, hwaddr offset,
|
||||
@@ -553,10 +585,12 @@ void xive_tctx_pic_print_info(XiveTCTX *tctx, GString *buf);
|
||||
Object *xive_tctx_create(Object *cpu, XivePresenter *xptr, Error **errp);
|
||||
void xive_tctx_reset(XiveTCTX *tctx);
|
||||
void xive_tctx_destroy(XiveTCTX *tctx);
|
||||
void xive_tctx_pipr_update(XiveTCTX *tctx, uint8_t ring, uint8_t priority,
|
||||
uint8_t group_level);
|
||||
void xive_tctx_pipr_set(XiveTCTX *tctx, uint8_t ring, uint8_t priority,
|
||||
uint8_t group_level);
|
||||
void xive_tctx_pipr_present(XiveTCTX *tctx, uint8_t ring, uint8_t priority,
|
||||
uint8_t group_level);
|
||||
void xive_tctx_reset_signal(XiveTCTX *tctx, uint8_t ring);
|
||||
void xive_tctx_notify(XiveTCTX *tctx, uint8_t ring, uint8_t group_level);
|
||||
uint64_t xive_tctx_accept(XiveTCTX *tctx, uint8_t ring);
|
||||
|
||||
/*
|
||||
* KVM XIVE device helpers
|
||||
|
||||
+18
-4
@@ -29,9 +29,11 @@ OBJECT_DECLARE_TYPE(Xive2Router, Xive2RouterClass, XIVE2_ROUTER);
|
||||
* Configuration flags
|
||||
*/
|
||||
|
||||
#define XIVE2_GEN1_TIMA_OS 0x00000001
|
||||
#define XIVE2_VP_SAVE_RESTORE 0x00000002
|
||||
#define XIVE2_THREADID_8BITS 0x00000004
|
||||
#define XIVE2_GEN1_TIMA_OS 0x00000001
|
||||
#define XIVE2_VP_SAVE_RESTORE 0x00000002
|
||||
#define XIVE2_THREADID_8BITS 0x00000004
|
||||
#define XIVE2_EN_VP_GRP_PRIORITY 0x00000008
|
||||
#define XIVE2_VP_INT_PRIO 0x00000030
|
||||
|
||||
typedef struct Xive2RouterClass {
|
||||
SysBusDeviceClass parent;
|
||||
@@ -80,6 +82,7 @@ int xive2_router_write_nvgc(Xive2Router *xrtr, bool crowd,
|
||||
uint32_t xive2_router_get_config(Xive2Router *xrtr);
|
||||
|
||||
void xive2_router_notify(XiveNotifier *xn, uint32_t lisn, bool pq_checked);
|
||||
void xive2_notify(Xive2Router *xrtr, uint32_t lisn, bool pq_checked);
|
||||
|
||||
/*
|
||||
* XIVE2 Presenter (POWER10)
|
||||
@@ -127,6 +130,8 @@ void xive2_tm_set_hv_cppr(XivePresenter *xptr, XiveTCTX *tctx,
|
||||
hwaddr offset, uint64_t value, unsigned size);
|
||||
void xive2_tm_set_os_cppr(XivePresenter *xptr, XiveTCTX *tctx,
|
||||
hwaddr offset, uint64_t value, unsigned size);
|
||||
void xive2_tm_set_os_pending(XivePresenter *xptr, XiveTCTX *tctx,
|
||||
hwaddr offset, uint64_t value, unsigned size);
|
||||
void xive2_tm_push_os_ctx(XivePresenter *xptr, XiveTCTX *tctx, hwaddr offset,
|
||||
uint64_t value, unsigned size);
|
||||
uint64_t xive2_tm_pull_os_ctx(XivePresenter *xptr, XiveTCTX *tctx,
|
||||
@@ -137,7 +142,16 @@ bool xive2_tm_irq_precluded(XiveTCTX *tctx, int ring, uint8_t priority);
|
||||
void xive2_tm_set_lsmfb(XiveTCTX *tctx, int ring, uint8_t priority);
|
||||
void xive2_tm_set_hv_target(XivePresenter *xptr, XiveTCTX *tctx,
|
||||
hwaddr offset, uint64_t value, unsigned size);
|
||||
void xive2_tm_push_pool_ctx(XivePresenter *xptr, XiveTCTX *tctx,
|
||||
hwaddr offset, uint64_t value, unsigned size);
|
||||
uint64_t xive2_tm_pull_pool_ctx(XivePresenter *xptr, XiveTCTX *tctx,
|
||||
hwaddr offset, unsigned size);
|
||||
void xive2_tm_push_phys_ctx(XivePresenter *xptr, XiveTCTX *tctx,
|
||||
hwaddr offset, uint64_t value, unsigned size);
|
||||
uint64_t xive2_tm_pull_phys_ctx(XivePresenter *xptr, XiveTCTX *tctx,
|
||||
hwaddr offset, unsigned size);
|
||||
void xive2_tm_pull_phys_ctx_ol(XivePresenter *xptr, XiveTCTX *tctx,
|
||||
hwaddr offset, uint64_t value, unsigned size);
|
||||
|
||||
void xive2_tm_ack_os_el(XivePresenter *xptr, XiveTCTX *tctx,
|
||||
hwaddr offset, uint64_t value, unsigned size);
|
||||
#endif /* PPC_XIVE2_H */
|
||||
|
||||
@@ -39,15 +39,18 @@
|
||||
|
||||
typedef struct Xive2Eas {
|
||||
uint64_t w;
|
||||
#define EAS2_VALID PPC_BIT(0)
|
||||
#define EAS2_END_BLOCK PPC_BITMASK(4, 7) /* Destination EQ block# */
|
||||
#define EAS2_END_INDEX PPC_BITMASK(8, 31) /* Destination EQ index */
|
||||
#define EAS2_MASKED PPC_BIT(32) /* Masked */
|
||||
#define EAS2_END_DATA PPC_BITMASK(33, 63) /* written to the EQ */
|
||||
#define EAS2_VALID PPC_BIT(0)
|
||||
#define EAS2_QOS PPC_BIT(1, 2) /* Quality of Service(unimp) */
|
||||
#define EAS2_RESUME PPC_BIT(3) /* END Resume(unimp) */
|
||||
#define EAS2_END_BLOCK PPC_BITMASK(4, 7) /* Destination EQ block# */
|
||||
#define EAS2_END_INDEX PPC_BITMASK(8, 31) /* Destination EQ index */
|
||||
#define EAS2_MASKED PPC_BIT(32) /* Masked */
|
||||
#define EAS2_END_DATA PPC_BITMASK(33, 63) /* written to the EQ */
|
||||
} Xive2Eas;
|
||||
|
||||
#define xive2_eas_is_valid(eas) (be64_to_cpu((eas)->w) & EAS2_VALID)
|
||||
#define xive2_eas_is_masked(eas) (be64_to_cpu((eas)->w) & EAS2_MASKED)
|
||||
#define xive2_eas_is_resume(eas) (be64_to_cpu((eas)->w) & EAS2_RESUME)
|
||||
|
||||
void xive2_eas_pic_print_info(Xive2Eas *eas, uint32_t lisn, GString *buf);
|
||||
|
||||
@@ -87,6 +90,7 @@ typedef struct Xive2End {
|
||||
#define END2_W2_EQ_ADDR_HI PPC_BITMASK32(8, 31)
|
||||
uint32_t w3;
|
||||
#define END2_W3_EQ_ADDR_LO PPC_BITMASK32(0, 24)
|
||||
#define END2_W3_CL PPC_BIT32(27)
|
||||
#define END2_W3_QSIZE PPC_BITMASK32(28, 31)
|
||||
uint32_t w4;
|
||||
#define END2_W4_END_BLOCK PPC_BITMASK32(4, 7)
|
||||
@@ -154,6 +158,7 @@ typedef struct Xive2Nvp {
|
||||
#define NVP2_W0_L PPC_BIT32(8)
|
||||
#define NVP2_W0_G PPC_BIT32(9)
|
||||
#define NVP2_W0_T PPC_BIT32(10)
|
||||
#define NVP2_W0_P PPC_BIT32(11)
|
||||
#define NVP2_W0_ESC_END PPC_BIT32(25) /* 'N' bit 0:ESB 1:END */
|
||||
#define NVP2_W0_PGOFIRST PPC_BITMASK32(26, 31)
|
||||
uint32_t w1;
|
||||
@@ -205,9 +210,9 @@ static inline uint32_t xive2_nvp_idx(uint32_t cam_line)
|
||||
return cam_line & ((1 << XIVE2_NVP_SHIFT) - 1);
|
||||
}
|
||||
|
||||
static inline uint32_t xive2_nvp_blk(uint32_t cam_line)
|
||||
static inline uint8_t xive2_nvp_blk(uint32_t cam_line)
|
||||
{
|
||||
return (cam_line >> XIVE2_NVP_SHIFT) & 0xf;
|
||||
return (uint8_t)((cam_line >> XIVE2_NVP_SHIFT) & 0xf);
|
||||
}
|
||||
|
||||
void xive2_nvp_pic_print_info(Xive2Nvp *nvp, uint32_t nvp_idx, GString *buf);
|
||||
@@ -220,6 +225,9 @@ typedef struct Xive2Nvgc {
|
||||
#define NVGC2_W0_VALID PPC_BIT32(0)
|
||||
#define NVGC2_W0_PGONEXT PPC_BITMASK32(26, 31)
|
||||
uint32_t w1;
|
||||
#define NVGC2_W1_PSIZE PPC_BITMASK32(0, 1)
|
||||
#define NVGC2_W1_END_BLK PPC_BITMASK32(4, 7)
|
||||
#define NVGC2_W1_END_IDX PPC_BITMASK32(8, 31)
|
||||
uint32_t w2;
|
||||
uint32_t w3;
|
||||
uint32_t w4;
|
||||
|
||||
Reference in New Issue
Block a user