* [PATCH v1 0/3] Add support for Variscite DART-MX93 and Sonata board
From: Stefano Radaelli @ 2026-03-26 15:47 UTC (permalink / raw)
To: linux-kernel, devicetree, imx, linux-arm-kernel
Cc: pierluigi.p, Stefano Radaelli, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Frank Li, Sascha Hauer, Pengutronix Kernel Team,
Fabio Estevam, Shawn Guo, Dario Binacchi, Alexander Stein,
Maud Spierings, Josua Mayer, Markus Niebel, Francesco Dolcini,
Primoz Fiser
This patch series adds support for the Variscite DART-MX93 system on
module and the Sonata carrier board.
The series includes:
- SOM device tree with on-module peripherals
- Sonata carrier board device tree with board-specific features
The implementation follows the standard SOM + carrier board pattern
where the SOM dtsi contains only peripherals mounted on the module,
while carrier-specific interfaces are enabled in the board dts.
Stefano Radaelli (3):
dt-bindings: arm: fsl: add Variscite DART-MX93 Boards
arm64: dts: freescale: Add support for Variscite DART-MX93
arm64: dts: imx93-var-dart: Add support for Variscite Sonata board
.../devicetree/bindings/arm/fsl.yaml | 6 +
arch/arm64/boot/dts/freescale/Makefile | 1 +
.../dts/freescale/imx93-var-dart-sonata.dts | 654 ++++++++++++++++++
.../boot/dts/freescale/imx93-var-dart.dtsi | 462 +++++++++++++
4 files changed, 1123 insertions(+)
create mode 100644 arch/arm64/boot/dts/freescale/imx93-var-dart-sonata.dts
create mode 100644 arch/arm64/boot/dts/freescale/imx93-var-dart.dtsi
base-commit: 6c4b48012d57f205c94f25da0c68a4027ea6daf6
--
2.47.3
^ permalink raw reply
* Re: [PATCH v10 00/12] barrier: Add smp_cond_load_{relaxed,acquire}_timeout()
From: Catalin Marinas @ 2026-03-26 15:39 UTC (permalink / raw)
To: David Laight
Cc: Ankur Arora, Andrew Morton, linux-kernel, linux-arch,
linux-arm-kernel, linux-pm, bpf, arnd, will, peterz, mark.rutland,
harisokn, cl, ast, rafael, daniel.lezcano, memxor, zhenglifeng1,
xueshuai, rdunlap, joao.m.martins, boris.ostrovsky, konrad.wilk
In-Reply-To: <20260325202357.3e203314@pumpkin>
On Wed, Mar 25, 2026 at 08:23:57PM +0000, David Laight wrote:
> On Wed, 25 Mar 2026 16:32:49 +0000
> Catalin Marinas <catalin.marinas@arm.com> wrote:
>
> > On Wed, Mar 25, 2026 at 03:42:10PM +0000, David Laight wrote:
> ...
> > > Looking at the code I think the "sevl; wfe" pair should be higher up.
> >
> > Yes, I replied to your other message. We could move it higher indeed,
> > before the condition check, but I can't get my head around the ordering.
> > Can need_resched() check be speculated before the WFE? I need to think
> > some more.
>
> I don't think speculation can matter.
> Both SEVL and WFE must be serialised against any other instructions
> that can change the event flag (as well as each other) otherwise
> everything is broken.
Welcome to the Arm memory model. We don't have any guarantee that an LDR
will only access memory after SEVL+WFE. They are not serialising.
> Apart from that it doesn't matter, what matters is the instruction
> boundary the interrupt happens at.
True. If an interrupt is taken before the LDR (that would be a
need_resched() check for example), then a prior WFE would not matter.
This won't work if we replace the IPI with a SEV though (suggested
somewhere in this thread).
> Actually both SEVL and WFE may be synchronising instructions and very slow.
Most likely not.
> So you may not want to put them in the fast path where the condition
> is true on entry (or even true after a retry).
> So the code might have to look like:
> for (;;) {
> VAL = mem;
If we only waited on the location passed to LDXR, things would have been
much simpler. But the osq_lock() also wants to wait on the TIF flags via
need_resched() (and vcpu_is_preempted()).
> if (cond(VAL)) return;
So the cond(VAL) here is actually a series of other memory loads
unrelated to 'mem'
> SEVL; WFE;
> if (cond(VAL)) return;
I think this will work in principle even if 'cond' accesses other memory
locations, though I wouldn't bother with an additional 'cond' call, I'd
expect SEVL+WFE to be mostly NOPs. However, 'cond' must not set a local
event, otherwise the power saving on waiting is gone.
> v1 = LDX(mem);
> if (v1 == VAL)
> WFE;
> }
I think it's cleaner to use Ankur's timeout API here for the very rare
case where an IPI hits at the wrong time. We then keep
smp_cond_load_relaxed() intact as it's really not meant to wait on
multiple memory locations to change. Any changes of
smp_cond_load_relaxed() with moving the WFE around are just hacks, not
the intended use of this API.
--
Catalin
^ permalink raw reply
* Re: [PATCH net 2/2] net: xilinx: axienet: Fix BQL accounting for multi-BD TX packets
From: Sean Anderson @ 2026-03-26 15:38 UTC (permalink / raw)
To: Gupta, Suraj, andrew+netdev@lunn.ch, davem@davemloft.net,
edumazet@google.com, kuba@kernel.org, pabeni@redhat.com,
Simek, Michal, Pandey, Radhey Shyam, horms@kernel.org
Cc: netdev@vger.kernel.org, linux-arm-kernel@lists.infradead.org,
linux-kernel@vger.kernel.org, Katakam, Harini
In-Reply-To: <SA1PR12MB6798E4EB242D58AEB86661B9C949A@SA1PR12MB6798.namprd12.prod.outlook.com>
On 3/25/26 01:30, Gupta, Suraj wrote:
> [Public]
>
>> -----Original Message-----
>> From: Sean Anderson <sean.anderson@linux.dev>
>> Sent: Tuesday, March 24, 2026 9:39 PM
>> To: Gupta, Suraj <Suraj.Gupta2@amd.com>; andrew+netdev@lunn.ch;
>> davem@davemloft.net; edumazet@google.com; kuba@kernel.org;
>> pabeni@redhat.com; Simek, Michal <michal.simek@amd.com>; Pandey,
>> Radhey Shyam <radhey.shyam.pandey@amd.com>; horms@kernel.org
>> Cc: netdev@vger.kernel.org; linux-arm-kernel@lists.infradead.org; linux-
>> kernel@vger.kernel.org; Katakam, Harini <harini.katakam@amd.com>
>> Subject: Re: [PATCH net 2/2] net: xilinx: axienet: Fix BQL accounting for multi-BD
>> TX packets
>>
>> Caution: This message originated from an External Source. Use proper caution
>> when opening attachments, clicking links, or responding.
>>
>>
>> On 3/24/26 10:53, Suraj Gupta wrote:
>> > When a TX packet spans multiple buffer descriptors (scatter-gather),
>> > the per-BD byte count is accumulated into a local variable that resets
>> > on each NAPI poll. If the BDs for a single packet complete across
>> > different polls, the earlier bytes are lost and never credited to BQL.
>> > This causes BQL to think bytes are permanently in-flight, eventually
>> > stalling the TX queue.
>> >
>> > Fix this by replacing the local accumulator with a persistent counter
>> > (tx_compl_bytes) that survives across polls and is reset only after
>> > updating BQL and stats.
>>
>> Do we need this? Can't we just do something like
>>
>
> Nope, the 'size' variable passed to axienet_free_tx_chain() is local
> to axienet_tx_poll() and goes out of scope between different polls.
> This means it can't track completion bytes across multiple NAPI polls.
Yes, but that's fine since we only update completed bytes when we retire at least one packet:
packets = axienet_free_tx_chain(lp, &size, budget);
if (packets) {
netdev_completed_queue(ndev, packets, size);
u64_stats_update_begin(&lp->tx_stat_sync);
u64_stats_add(&lp->tx_packets, packets);
u64_stats_add(&lp->tx_bytes, size);
u64_stats_update_end(&lp->tx_stat_sync);
/* Matches barrier in axienet_start_xmit */
smp_mb();
if (((tail - ci) & (lp->rx_bd_num - 1)) >= MAX_SKB_FRAGS + 1)
netif_wake_queue(ndev);
}
and this matches the value we use when enqueuing a packet
tail_p = lp->tx_bd_p + sizeof(*lp->tx_bd_v) * (last_p - lp->tx_bd_v);
smp_store_release(&lp->tx_bd_tail, new_tail_ptr);
netdev_sent_queue(ndev, skb->len);
> Regards,
> Suraj
>
>> diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
>> b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
>> index 415e9bc252527..1ea8a6592bce1 100644
>> --- a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
>> +++ b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
>> @@ -768,6 +768,7 @@ static int axienet_free_tx_chain(struct axienet_local
>> *lp, u32 *sizep, int budge
>> if (cur_p->skb) {
>> struct axienet_cb *cb = (void *)cur_p->skb->cb;
>>
>> + *sizep += skb->len;
>> dma_unmap_sgtable(lp->dev, &cb->sgt, DMA_TO_DEVICE, 0);
>> sg_free_table_chained(&cb->sgt, XAE_INLINE_SG_CNT);
>> napi_consume_skb(cur_p->skb, budget); @@ -783,8 +784,6 @@
>> static int axienet_free_tx_chain(struct axienet_local *lp, u32 *sizep, int budge
>> wmb();
>> cur_p->cntrl = 0;
>> cur_p->status = 0;
>> -
>> - *sizep += status & XAXIDMA_BD_STS_ACTUAL_LEN_MASK;
>> }
>>
>> smp_store_release(&lp->tx_bd_ci, (ci + i) & (lp->tx_bd_num - 1));
>>
>> > Fixes: c900e49d58eb ("net: xilinx: axienet: Implement BQL")
>> > Signed-off-by: Suraj Gupta <suraj.gupta2@amd.com>
>> > ---
>> > drivers/net/ethernet/xilinx/xilinx_axienet.h | 3 +++
>> > .../net/ethernet/xilinx/xilinx_axienet_main.c | 20 +++++++++----------
>> > 2 files changed, 13 insertions(+), 10 deletions(-)
>> >
>> > diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet.h
>> > b/drivers/net/ethernet/xilinx/xilinx_axienet.h
>> > index 602389843342..a4444c939451 100644
>> > --- a/drivers/net/ethernet/xilinx/xilinx_axienet.h
>> > +++ b/drivers/net/ethernet/xilinx/xilinx_axienet.h
>> > @@ -509,6 +509,8 @@ struct skbuf_dma_descriptor {
>> > * complete. Only updated at runtime by TX NAPI poll.
>> > * @tx_bd_tail: Stores the index of the next Tx buffer descriptor in the ring
>> > * to be populated.
>> > + * @tx_compl_bytes: Accumulates TX completion length until a full packet is
>> > + * reported to the stack.
>> > * @tx_packets: TX packet count for statistics
>> > * @tx_bytes: TX byte count for statistics
>> > * @tx_stat_sync: Synchronization object for TX stats @@ -592,6
>> > +594,7 @@ struct axienet_local {
>> > u32 tx_bd_num;
>> > u32 tx_bd_ci;
>> > u32 tx_bd_tail;
>> > + u32 tx_compl_bytes;
>> > u64_stats_t tx_packets;
>> > u64_stats_t tx_bytes;
>> > struct u64_stats_sync tx_stat_sync; diff --git
>> > a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
>> > b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
>> > index b06e4c37ff61..95bf61986cb7 100644
>> > --- a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
>> > +++ b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
>> > @@ -692,6 +692,8 @@ static void axienet_dma_stop(struct axienet_local
>> *lp)
>> > axienet_lock_mii(lp);
>> > __axienet_device_reset(lp);
>> > axienet_unlock_mii(lp);
>> > +
>> > + lp->tx_compl_bytes = 0;
>> > }
>> >
>> > /**
>> > @@ -770,8 +772,6 @@ static int axienet_device_reset(struct net_device
>> *ndev)
>> > * @first_bd: Index of first descriptor to clean up
>> > * @nr_bds: Max number of descriptors to clean up
>> > * @force: Whether to clean descriptors even if not complete
>> > - * @sizep: Pointer to a u32 filled with the total sum of all bytes
>> > - * in all cleaned-up descriptors. Ignored if NULL.
>> > * @budget: NAPI budget (use 0 when not called from NAPI poll)
>> > *
>> > * Would either be called after a successful transmit operation, or
>> > after @@ -780,7 +780,7 @@ static int axienet_device_reset(struct net_device
>> *ndev)
>> > * Return: The number of packets handled.
>> > */
>> > static int axienet_free_tx_chain(struct axienet_local *lp, u32 first_bd,
>> > - int nr_bds, bool force, u32 *sizep, int budget)
>> > + int nr_bds, bool force, int budget)
>> > {
>> > struct axidma_bd *cur_p;
>> > unsigned int status;
>> > @@ -819,8 +819,8 @@ static int axienet_free_tx_chain(struct axienet_local
>> *lp, u32 first_bd,
>> > cur_p->cntrl = 0;
>> > cur_p->status = 0;
>> >
>> > - if (sizep)
>> > - *sizep += status & XAXIDMA_BD_STS_ACTUAL_LEN_MASK;
>> > + if (!force)
>> > + lp->tx_compl_bytes += status &
>> > + XAXIDMA_BD_STS_ACTUAL_LEN_MASK;
>> > }
>> >
>> > if (!force) {
>> > @@ -999,18 +999,18 @@ static int axienet_tx_poll(struct napi_struct
>> > *napi, int budget) {
>> > struct axienet_local *lp = container_of(napi, struct axienet_local, napi_tx);
>> > struct net_device *ndev = lp->ndev;
>> > - u32 size = 0;
>> > int packets;
>> >
>> > packets = axienet_free_tx_chain(lp, lp->tx_bd_ci, lp->tx_bd_num, false,
>> > - &size, budget);
>> > + budget);
>> >
>> > if (packets) {
>> > - netdev_completed_queue(ndev, packets, size);
>> > + netdev_completed_queue(ndev, packets,
>> > + lp->tx_compl_bytes);
>> > u64_stats_update_begin(&lp->tx_stat_sync);
>> > u64_stats_add(&lp->tx_packets, packets);
>> > - u64_stats_add(&lp->tx_bytes, size);
>> > + u64_stats_add(&lp->tx_bytes, lp->tx_compl_bytes);
>> > u64_stats_update_end(&lp->tx_stat_sync);
>> > + lp->tx_compl_bytes = 0;
>> >
>> > /* Matches barrier in axienet_start_xmit */
>> > smp_mb();
>> > @@ -1115,7 +1115,7 @@ axienet_start_xmit(struct sk_buff *skb, struct
>> net_device *ndev)
>> > netdev_err(ndev, "TX DMA mapping error\n");
>> > ndev->stats.tx_dropped++;
>> > axienet_free_tx_chain(lp, orig_tail_ptr, ii + 1,
>> > - true, NULL, 0);
>> > + true, 0);
>> > dev_kfree_skb_any(skb);
>> > return NETDEV_TX_OK;
>> > }
^ permalink raw reply
* Re: [PATCH v2 07/17] firmware: arm_scmi: Use new Telemetry traces
From: Cristian Marussi @ 2026-03-26 15:35 UTC (permalink / raw)
To: Elif Topuz
Cc: Cristian Marussi, linux-kernel, linux-arm-kernel, arm-scmi,
linux-fsdevel, sudeep.holla, james.quinlan, f.fainelli,
vincent.guittot, etienne.carriere, peng.fan, michal.simek,
dan.carpenter, d-gole, jonathan.cameron, lukasz.luba,
philip.radford, souvik.chakravarty
In-Reply-To: <3c6bddfd-a674-486c-add4-35ef93ec88c4@arm.com>
On Fri, Jan 23, 2026 at 11:43:37AM +0000, Elif Topuz wrote:
>
> Hi Cristian,
Hi Elif,
>
> On 14/01/2026 11:46, Cristian Marussi wrote:
> > Track failed SHMTI accesses and received notifications.
> >
> > Signed-off-by: Cristian Marussi <cristian.marussi@arm.com>
> > ---
> > drivers/firmware/arm_scmi/telemetry.c | 57 ++++++++++++++++++++++-----
> > 1 file changed, 48 insertions(+), 9 deletions(-)
> >
> > diff --git a/drivers/firmware/arm_scmi/telemetry.c b/drivers/firmware/arm_scmi/telemetry.c
> > index 16bcdcdc1dc3..443e032a3553 100644
> > --- a/drivers/firmware/arm_scmi/telemetry.c
> > +++ b/drivers/firmware/arm_scmi/telemetry.c
> > @@ -25,6 +25,8 @@
> > #include "protocols.h"
> > #include "notify.h"
> >
> > +#include <trace/events/scmi.h>
> > +
> > /* Updated only after ALL the mandatory features for that version are merged */
> > #define SCMI_PROTOCOL_SUPPORTED_VERSION 0x10000
> >
> > @@ -1366,8 +1368,10 @@ static void scmi_telemetry_tdcf_blkts_parse(struct telemetry_info *ti,
> >
> > /* Check for spec compliance */
> > if (USE_LINE_TS(payld) || USE_BLK_TS(payld) ||
> > - DATA_INVALID(payld) || (PAYLD_ID(payld) != 0))
> > + DATA_INVALID(payld) || (PAYLD_ID(payld) != 0)) {
> > + trace_scmi_tlm_access(0, "BLK_TS_INVALID", 0, 0);
> > return;
> > + }
> >
> > /* A BLK_TS descriptor MUST be returned: it is found or it is crated */
> > bts = scmi_telemetry_blkts_lookup(ti->ph->dev, &ti->xa_bts, payld);
> > @@ -1376,6 +1380,9 @@ static void scmi_telemetry_tdcf_blkts_parse(struct telemetry_info *ti,
> >
> > /* Update the descriptor with the lastest TS*/
> > scmi_telemetry_blkts_update(shmti->last_magic, bts);
> > +
> > + trace_scmi_tlm_collect(bts->last_ts, (u64)payld,
> > + bts->last_magic, "SHMTI_BLK_TS");
> > }
> >
> > static void scmi_telemetry_tdcf_data_parse(struct telemetry_info *ti,
> > @@ -1393,8 +1400,10 @@ static void scmi_telemetry_tdcf_data_parse(struct telemetry_info *ti,
> > /* Is thi DE ID know ? */
> > tde = scmi_telemetry_tde_lookup(ti, de_id);
> > if (!tde) {
> > - if (mode != SCAN_DISCOVERY)
> > + if (mode != SCAN_DISCOVERY) {
> > + trace_scmi_tlm_access(de_id, "DE_INVALID", 0, 0);
> > return;
> > + }
> >
> > /* In SCAN_DISCOVERY mode we allocate new DEs for unknown IDs */
> > tde = scmi_telemetry_tde_get(ti, de_id);
> > @@ -1462,6 +1471,8 @@ static void scmi_telemetry_tdcf_data_parse(struct telemetry_info *ti,
> > tde->last_ts = tstamp;
> > else
> > tde->last_ts = 0;
> > +
> > + trace_scmi_tlm_collect(0, tde->de.info->id, tde->last_val, "SHMTI_DE_UPDT");
>
> tde->last_ts instead of 0?
>
Yes, but I have reworked a lot the code so the traces also are moved
around a lot with different tags...also I move the trace definitions
before the protocol series in V3 and scattered the trace calls all
across the protocol patches, which I split a lot.
I tried anyway to follow your advice...well..anyway I doubt V3 will be
the last one :P, so you're welcome to complain...
> > }
> >
> > static int scmi_telemetry_tdcf_line_parse(struct telemetry_info *ti,
> > @@ -1507,8 +1518,10 @@ static int scmi_telemetry_shmti_scan(struct telemetry_info *ti,
> > fsleep((SCMI_TLM_TDCF_MAX_RETRIES - retries) * 1000);
> >
> > startm = TDCF_START_SEQ_GET(tdcf);
> > - if (IS_BAD_START_SEQ(startm))
> > + if (IS_BAD_START_SEQ(startm)) {
> > + trace_scmi_tlm_access(0, "MSEQ_BADSTART", startm, 0);
> > continue;
> > + }
> >
> > /* On a BAD_SEQ this will be updated on the next attempt */
> > shmti->last_magic = startm;
> > @@ -1520,18 +1533,25 @@ static int scmi_telemetry_shmti_scan(struct telemetry_info *ti,
> >
> > used_qwords = scmi_telemetry_tdcf_line_parse(ti, next,
> > shmti, mode);
> > - if (qwords < used_qwords)
> > + if (qwords < used_qwords) {
> > + trace_scmi_tlm_access(PAYLD_ID(next),
> > + "BAD_QWORDS", startm, 0);
> > return -EINVAL;
> > + }
> >
> > next += used_qwords * 8;
> > qwords -= used_qwords;
> > }
> >
> > endm = TDCF_END_SEQ_GET(eplg);
> > + if (startm != endm)
> > + trace_scmi_tlm_access(0, "MSEQ_MISMATCH", startm, endm);
> > } while (startm != endm && --retries);
> >
> > - if (startm != endm)
> > + if (startm != endm) {
> > + trace_scmi_tlm_access(0, "TDCF_SCAN_FAIL", startm, endm);
> > return -EPROTO;
> > + }
> >
> > return 0;
> > }
> > @@ -1923,6 +1943,8 @@ static void scmi_telemetry_scan_update(struct telemetry_info *ti, u64 ts)
> > tde->last_ts = tstamp;
> > else
> > tde->last_ts = 0;
> > +
> > + trace_scmi_tlm_collect(ts, tde->de.info->id, tde->last_val, "FC_UPDATE");
>
> tde->last_ts instead of ts?
Yes...but a lot of rework as said above...
>
> > }
> > }
> >
> > @@ -2001,8 +2023,11 @@ static int scmi_telemetry_tdcf_de_parse(struct telemetry_de *tde,
> > fsleep((SCMI_TLM_TDCF_MAX_RETRIES - retries) * 1000);
> >
> > startm = TDCF_START_SEQ_GET(tdcf);
> > - if (IS_BAD_START_SEQ(startm))
> > + if (IS_BAD_START_SEQ(startm)) {
> > + trace_scmi_tlm_access(tde->de.info->id, "MSEQ_BADSTART",
> > + startm, 0);
> > continue;
> > + }
> >
> > /* Has anything changed at all at the SHMTI level ? */
> > scoped_guard(mutex, &tde->mtx) {
> > @@ -2018,11 +2043,16 @@ static int scmi_telemetry_tdcf_de_parse(struct telemetry_de *tde,
> > if (DATA_INVALID(payld))
> > return -EINVAL;
> >
> > - if (IS_BLK_TS(payld))
> > + if (IS_BLK_TS(payld)) {
> > + trace_scmi_tlm_access(tde->de.info->id,
> > + "BAD_DE_META", 0, 0);
> > return -EINVAL;
> > + }
> >
> > - if (PAYLD_ID(payld) != tde->de.info->id)
> > + if (PAYLD_ID(payld) != tde->de.info->id) {
> > + trace_scmi_tlm_access(tde->de.info->id, "DE_INVALID", 0, 0);
> > return -EINVAL;
> > + }
> >
> > /* Data is always valid since NOT handling BLK TS lines here */
> > *val = LINE_DATA_GET(&payld->l);
> > @@ -2046,10 +2076,16 @@ static int scmi_telemetry_tdcf_de_parse(struct telemetry_de *tde,
> > }
> >
> > endm = TDCF_END_SEQ_GET(tde->eplg);
> > + if (startm != endm)
> > + trace_scmi_tlm_access(tde->de.info->id, "MSEQ_MISMATCH",
> > + startm, endm);
> > } while (startm != endm && --retries);
> >
> > - if (startm != endm)
> > + if (startm != endm) {
> > + trace_scmi_tlm_access(tde->de.info->id, "TDCF_DE_FAIL",
> > + startm, endm);
> > return -EPROTO;
> > + }
> >
> > guard(mutex)(&tde->mtx);
> > tde->last_magic = startm;
> > @@ -2230,6 +2266,9 @@ scmi_telemetry_msg_payld_process(struct telemetry_info *ti,
> > tde->last_ts = LINE_TSTAMP_GET(&payld->tsl);
> > else
> > tde->last_ts = 0;
> > +
> > + trace_scmi_tlm_collect(timestamp, tde->de.info->id, tde->last_val,
> > + "MESSAGE");
>
> tde->last_ts instead of timestamp? If I understand correctly, tde->last_ts
> corresponds to the time coming from the platform. We have kernel time anyway
> coming from ftrace format.
Yes good point...timestamp is the time of arrival of the
notification...I can also drop that parameter at this point...
Thanks a lot for reviewing !
Cristian
^ permalink raw reply
* [PATCH 14/15] KVM: arm64: Correctly plumb ID_AA64PFR2_EL1 into pkvm idreg handling
From: Marc Zyngier @ 2026-03-26 15:35 UTC (permalink / raw)
To: kvmarm, kvm, linux-arm-kernel
Cc: Joey Gouly, Suzuki K Poulose, Oliver Upton, Zenghui Yu,
Sascha Bischoff, Mark Brown
In-Reply-To: <20260326153530.3981879-1-maz@kernel.org>
While we now compute ID_AA64PFR2_EL1 to a glorious 0, we never use
that data and instead return the 0 that corresponds to an allocated
idreg. Not a big deal, but we might as well be consistent.
Fixes: 5aefaf11f9af5 ("KVM: arm64: gic: Hide GICv5 for protected guests")
Link: https://sashiko.dev/#/patchset/20260319154937.3619520-1-sascha.bischoff%40arm.com
Signed-off-by: Marc Zyngier <maz@kernel.org>
---
arch/arm64/kvm/hyp/nvhe/sys_regs.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/arm64/kvm/hyp/nvhe/sys_regs.c b/arch/arm64/kvm/hyp/nvhe/sys_regs.c
index b40fd01ebf329..be6f420388a14 100644
--- a/arch/arm64/kvm/hyp/nvhe/sys_regs.c
+++ b/arch/arm64/kvm/hyp/nvhe/sys_regs.c
@@ -439,7 +439,7 @@ static const struct sys_reg_desc pvm_sys_reg_descs[] = {
/* CRm=4 */
AARCH64(SYS_ID_AA64PFR0_EL1),
AARCH64(SYS_ID_AA64PFR1_EL1),
- ID_UNALLOCATED(4,2),
+ AARCH64(SYS_ID_AA64PFR2_EL1),
ID_UNALLOCATED(4,3),
AARCH64(SYS_ID_AA64ZFR0_EL1),
ID_UNALLOCATED(4,5),
--
2.47.3
^ permalink raw reply related
* [PATCH 12/15] KVM: arm64: Remove evaluation of timer state in kvm_cpu_has_pending_timer()
From: Marc Zyngier @ 2026-03-26 15:35 UTC (permalink / raw)
To: kvmarm, kvm, linux-arm-kernel
Cc: Joey Gouly, Suzuki K Poulose, Oliver Upton, Zenghui Yu,
Sascha Bischoff, Mark Brown
In-Reply-To: <20260326153530.3981879-1-maz@kernel.org>
The vgic-v5 code added some evaluations of the timers in a helper funtion
(kvm_cpu_has_pending_timer()) that is called to determine whether
the vcpu can wake-up.
But looking at the timer there is wrong:
- we want to see timers that are signalling an interrupt to the
vcpu, and not just that have a pending interrupt
- we already have kvm_arch_vcpu_runnable() that evaluates the
state of interrupts
- kvm_cpu_has_pending_timer() really is about WFIT, as the timeout
does not generate an interrupt, and is therefore distinct from
the point above
As a consequence, revert these changes.
Fixes: 9491c63b6cd7b ("KVM: arm64: gic-v5: Enlighten arch timer for GICv5")
Link: https://sashiko.dev/#/patchset/20260319154937.3619520-1-sascha.bischoff%40arm.com
Signed-off-by: Marc Zyngier <maz@kernel.org>
---
arch/arm64/kvm/arch_timer.c | 6 +-----
1 file changed, 1 insertion(+), 5 deletions(-)
diff --git a/arch/arm64/kvm/arch_timer.c b/arch/arm64/kvm/arch_timer.c
index 37279f8748695..6608c47d1f628 100644
--- a/arch/arm64/kvm/arch_timer.c
+++ b/arch/arm64/kvm/arch_timer.c
@@ -402,11 +402,7 @@ static bool kvm_timer_should_fire(struct arch_timer_context *timer_ctx)
int kvm_cpu_has_pending_timer(struct kvm_vcpu *vcpu)
{
- struct arch_timer_context *vtimer = vcpu_vtimer(vcpu);
- struct arch_timer_context *ptimer = vcpu_ptimer(vcpu);
-
- return kvm_timer_should_fire(vtimer) || kvm_timer_should_fire(ptimer) ||
- (vcpu_has_wfit_active(vcpu) && wfit_delay_ns(vcpu) == 0);
+ return vcpu_has_wfit_active(vcpu) && wfit_delay_ns(vcpu) == 0;
}
/*
--
2.47.3
^ permalink raw reply related
* [PATCH 10/15] KVM: arm64: vgic-v5: Correctly set dist->ready once initialised
From: Marc Zyngier @ 2026-03-26 15:35 UTC (permalink / raw)
To: kvmarm, kvm, linux-arm-kernel
Cc: Joey Gouly, Suzuki K Poulose, Oliver Upton, Zenghui Yu,
Sascha Bischoff, Mark Brown
In-Reply-To: <20260326153530.3981879-1-maz@kernel.org>
kvm_vgic_map_resources() targetting a v5 model results in vgic->dist_ready
never being set. This doesn't result in anything really bad, only
some more heavy locking as we go and re-init something for no good reason.
Rejig the code to correctly set the ready flag in all non-failing
cases.
Fixes: f4d37c7c35769 ("KVM: arm64: gic-v5: Create and initialise vgic_v5")
Link: https://sashiko.dev/#/patchset/20260319154937.3619520-1-sascha.bischoff%40arm.com
Signed-off-by: Marc Zyngier <maz@kernel.org>
---
arch/arm64/kvm/vgic/vgic-init.c | 18 +++++++++++-------
1 file changed, 11 insertions(+), 7 deletions(-)
diff --git a/arch/arm64/kvm/vgic/vgic-init.c b/arch/arm64/kvm/vgic/vgic-init.c
index fd872079f2a24..ecb0aea180327 100644
--- a/arch/arm64/kvm/vgic/vgic-init.c
+++ b/arch/arm64/kvm/vgic/vgic-init.c
@@ -657,16 +657,20 @@ int kvm_vgic_map_resources(struct kvm *kvm)
needs_dist = false;
}
- if (ret || !needs_dist)
+ if (ret)
goto out;
- dist_base = dist->vgic_dist_base;
- mutex_unlock(&kvm->arch.config_lock);
+ if (needs_dist) {
+ dist_base = dist->vgic_dist_base;
+ mutex_unlock(&kvm->arch.config_lock);
- ret = vgic_register_dist_iodev(kvm, dist_base, type);
- if (ret) {
- kvm_err("Unable to register VGIC dist MMIO regions\n");
- goto out_slots;
+ ret = vgic_register_dist_iodev(kvm, dist_base, type);
+ if (ret) {
+ kvm_err("Unable to register VGIC dist MMIO regions\n");
+ goto out_slots;
+ }
+ } else {
+ mutex_unlock(&kvm->arch.config_lock);
}
smp_store_release(&dist->ready, true);
--
2.47.3
^ permalink raw reply related
* [PATCH 11/15] KVM: arm64: Kill arch_timer_context::direct field
From: Marc Zyngier @ 2026-03-26 15:35 UTC (permalink / raw)
To: kvmarm, kvm, linux-arm-kernel
Cc: Joey Gouly, Suzuki K Poulose, Oliver Upton, Zenghui Yu,
Sascha Bischoff, Mark Brown
In-Reply-To: <20260326153530.3981879-1-maz@kernel.org>
The newly introduced arch_timer_context::direct field is a bit pointless,
as it is always set on timers that are... err... direct, while
we already have a way to get to that by doing a get_map() operation.
Additionally, this field is:
- only set when get_map() is called
- never cleared
and the single point where it is actually checked doesn't call get_map()
at all.
At this stage, it is probably better to just kill it, and rely on
get_map() to give us the correct information.
Fixes: 9491c63b6cd7b ("KVM: arm64: gic-v5: Enlighten arch timer for GICv5")
Link: https://sashiko.dev/#/patchset/20260319154937.3619520-1-sascha.bischoff%40arm.com
Signed-off-by: Marc Zyngier <maz@kernel.org>
---
arch/arm64/kvm/arch_timer.c | 15 +++++++++------
include/kvm/arm_arch_timer.h | 3 ---
2 files changed, 9 insertions(+), 9 deletions(-)
diff --git a/arch/arm64/kvm/arch_timer.c b/arch/arm64/kvm/arch_timer.c
index 67b989671b410..37279f8748695 100644
--- a/arch/arm64/kvm/arch_timer.c
+++ b/arch/arm64/kvm/arch_timer.c
@@ -183,10 +183,6 @@ void get_timer_map(struct kvm_vcpu *vcpu, struct timer_map *map)
map->emul_ptimer = vcpu_ptimer(vcpu);
}
- map->direct_vtimer->direct = true;
- if (map->direct_ptimer)
- map->direct_ptimer->direct = true;
-
trace_kvm_get_timer_map(vcpu->vcpu_id, map);
}
@@ -462,8 +458,15 @@ static void kvm_timer_update_irq(struct kvm_vcpu *vcpu, bool new_level,
return;
/* Skip injecting on GICv5 for directly injected (DVI'd) timers */
- if (vgic_is_v5(vcpu->kvm) && timer_ctx->direct)
- return;
+ if (vgic_is_v5(vcpu->kvm)) {
+ struct timer_map map;
+
+ get_timer_map(vcpu, &map);
+
+ if (map.direct_ptimer == timer_ctx ||
+ map.direct_vtimer == timer_ctx)
+ return;
+ }
kvm_vgic_inject_irq(vcpu->kvm, vcpu,
timer_irq(timer_ctx),
diff --git a/include/kvm/arm_arch_timer.h b/include/kvm/arm_arch_timer.h
index a7754e0a2ef41..bf8cc9589bd09 100644
--- a/include/kvm/arm_arch_timer.h
+++ b/include/kvm/arm_arch_timer.h
@@ -76,9 +76,6 @@ struct arch_timer_context {
/* Duplicated state from arch_timer.c for convenience */
u32 host_timer_irq;
-
- /* Is this a direct timer? */
- bool direct;
};
struct timer_map {
--
2.47.3
^ permalink raw reply related
* [PATCH 13/15] KVM: arm64: Move GICv5 timer PPI validation into timer_irqs_are_valid()
From: Marc Zyngier @ 2026-03-26 15:35 UTC (permalink / raw)
To: kvmarm, kvm, linux-arm-kernel
Cc: Joey Gouly, Suzuki K Poulose, Oliver Upton, Zenghui Yu,
Sascha Bischoff, Mark Brown
In-Reply-To: <20260326153530.3981879-1-maz@kernel.org>
Userspace can set the timer PPI numbers way before a GIC has been
created, leading to odd behaviours on GICv5 as we'd accept non
architectural PPI numbers.
Move the v5 check into timer_irqs_are_valid(), which aligns the
behaviour with the pre-v5 GICs, and is also guaranteed to run
only once a GIC has been configured.
Fixes: 9491c63b6cd7b ("KVM: arm64: gic-v5: Enlighten arch timer for GICv5")
Link: https://sashiko.dev/#/patchset/20260319154937.3619520-1-sascha.bischoff%40arm.com
Signed-off-by: Marc Zyngier <maz@kernel.org>
---
arch/arm64/kvm/arch_timer.c | 11 ++++-------
1 file changed, 4 insertions(+), 7 deletions(-)
diff --git a/arch/arm64/kvm/arch_timer.c b/arch/arm64/kvm/arch_timer.c
index 6608c47d1f628..cbea4d9ee9552 100644
--- a/arch/arm64/kvm/arch_timer.c
+++ b/arch/arm64/kvm/arch_timer.c
@@ -1543,6 +1543,10 @@ static bool timer_irqs_are_valid(struct kvm_vcpu *vcpu)
if (kvm_vgic_set_owner(vcpu, irq, ctx))
break;
+ /* With GICv5, the default PPI is what you get -- nothing else */
+ if (vgic_is_v5(vcpu->kvm) && irq != get_vgic_ppi(vcpu->kvm, default_ppi[i]))
+ break;
+
/*
* We know by construction that we only have PPIs, so all values
* are less than 32 for non-GICv5 VGICs. On GICv5, they are
@@ -1678,13 +1682,6 @@ int kvm_arm_timer_set_attr(struct kvm_vcpu *vcpu, struct kvm_device_attr *attr)
return -ENXIO;
}
- /*
- * The PPIs for the Arch Timers are architecturally defined for
- * GICv5. Reject anything that changes them from the specified value.
- */
- if (vgic_is_v5(vcpu->kvm) && vcpu->kvm->arch.timer_data.ppi[idx] != irq)
- return -EINVAL;
-
/*
* We cannot validate the IRQ unicity before we run, so take it at
* face value. The verdict will be given on first vcpu run, for each
--
2.47.3
^ permalink raw reply related
* [PATCH 08/15] KVM: arm64: vgic-v5: Cast vgic_apr to u32 to avoid undefined behaviours
From: Marc Zyngier @ 2026-03-26 15:35 UTC (permalink / raw)
To: kvmarm, kvm, linux-arm-kernel
Cc: Joey Gouly, Suzuki K Poulose, Oliver Upton, Zenghui Yu,
Sascha Bischoff, Mark Brown
In-Reply-To: <20260326153530.3981879-1-maz@kernel.org>
Passing a u64 to __builtin_ctz() is odd, and requires some digging to
figure out why this construct is indeed safe as long as the HW is
correct.
But it is much easier to make it clear to the compiler by casting
the u64 into an intermediate u32, and be done with the UD.
Fixes: 933e5288fa971 ("KVM: arm64: gic-v5: Check for pending PPIs")
Link: https://sashiko.dev/#/patchset/20260319154937.3619520-1-sascha.bischoff%40arm.com
Signed-off-by: Marc Zyngier <maz@kernel.org>
---
arch/arm64/kvm/vgic/vgic-v5.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/arch/arm64/kvm/vgic/vgic-v5.c b/arch/arm64/kvm/vgic/vgic-v5.c
index 422741c86c6a8..0f269321ece4b 100644
--- a/arch/arm64/kvm/vgic/vgic-v5.c
+++ b/arch/arm64/kvm/vgic/vgic-v5.c
@@ -212,7 +212,7 @@ int vgic_v5_finalize_ppi_state(struct kvm *kvm)
static u32 vgic_v5_get_effective_priority_mask(struct kvm_vcpu *vcpu)
{
struct vgic_v5_cpu_if *cpu_if = &vcpu->arch.vgic_cpu.vgic_v5;
- u32 highest_ap, priority_mask;
+ u32 highest_ap, priority_mask, apr;
/*
* If the guest's CPU has not opted to receive interrupts, then the
@@ -227,7 +227,8 @@ static u32 vgic_v5_get_effective_priority_mask(struct kvm_vcpu *vcpu)
* priority. Explicitly use the 32-bit version here as we have 32
* priorities. 32 then means that there are no active priorities.
*/
- highest_ap = cpu_if->vgic_apr ? __builtin_ctz(cpu_if->vgic_apr) : 32;
+ apr = cpu_if->vgic_apr;
+ highest_ap = apr ? __builtin_ctz(apr) : 32;
/*
* An interrupt is of sufficient priority if it is equal to or
--
2.47.3
^ permalink raw reply related
* [PATCH 09/15] KVM: arm64: vgic-v5: align priority comparison with other GICs
From: Marc Zyngier @ 2026-03-26 15:35 UTC (permalink / raw)
To: kvmarm, kvm, linux-arm-kernel
Cc: Joey Gouly, Suzuki K Poulose, Oliver Upton, Zenghui Yu,
Sascha Bischoff, Mark Brown
In-Reply-To: <20260326153530.3981879-1-maz@kernel.org>
The way the effective priority mask is computed, and then compared
to the priority of an interrupt to decide whether to wake-up or not,
is slightly odd, and breaks at the limits.
This could result in spurious wake-ups that are undesirable.
Adopt the GICv[23] logic instead, which checks that the priority value
is strictly lower than the mask.
Fixes: 933e5288fa971 ("KVM: arm64: gic-v5: Check for pending PPIs")
Link: https://sashiko.dev/#/patchset/20260319154937.3619520-1-sascha.bischoff%40arm.com
Signed-off-by: Marc Zyngier <maz@kernel.org>
---
arch/arm64/kvm/vgic/vgic-v5.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/arch/arm64/kvm/vgic/vgic-v5.c b/arch/arm64/kvm/vgic/vgic-v5.c
index 0f269321ece4b..75372bbfb6a6a 100644
--- a/arch/arm64/kvm/vgic/vgic-v5.c
+++ b/arch/arm64/kvm/vgic/vgic-v5.c
@@ -238,7 +238,7 @@ static u32 vgic_v5_get_effective_priority_mask(struct kvm_vcpu *vcpu)
*/
priority_mask = FIELD_GET(FEAT_GCIE_ICH_VMCR_EL2_VPMR, cpu_if->vgic_vmcr);
- return min(highest_ap, priority_mask + 1);
+ return min(highest_ap, priority_mask);
}
/*
@@ -367,7 +367,7 @@ bool vgic_v5_has_pending_ppi(struct kvm_vcpu *vcpu)
scoped_guard(raw_spinlock_irqsave, &irq->irq_lock)
has_pending = (irq->enabled && irq_is_pending(irq) &&
- irq->priority <= priority_mask);
+ irq->priority < priority_mask);
vgic_put_irq(vcpu->kvm, irq);
--
2.47.3
^ permalink raw reply related
* [PATCH 06/15] KVM: arm64: vgic-v5: Hold config_lock while finalizing GICv5 PPIs
From: Marc Zyngier @ 2026-03-26 15:35 UTC (permalink / raw)
To: kvmarm, kvm, linux-arm-kernel
Cc: Joey Gouly, Suzuki K Poulose, Oliver Upton, Zenghui Yu,
Sascha Bischoff, Mark Brown
In-Reply-To: <20260326153530.3981879-1-maz@kernel.org>
Finalizing the PPI state is done without holding any lock, which
means that two vcpus can race against each other and have one zeroing
the state while another one is setting it, or even maybe using it.
Fixing this is done by:
- holding the config lock while performing the initialisation
- checking if SW_PPI has already been advertised, meaning that
we have already completed the initialisation once
Fixes: 8f1fbe2fd2792 ("KVM: arm64: gic-v5: Finalize GICv5 PPIs and generate mask")
Link: https://sashiko.dev/#/patchset/20260319154937.3619520-1-sascha.bischoff%40arm.com
Signed-off-by: Marc Zyngier <maz@kernel.org>
---
arch/arm64/kvm/vgic/vgic-v5.c | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/arch/arm64/kvm/vgic/vgic-v5.c b/arch/arm64/kvm/vgic/vgic-v5.c
index 2b6cd5c3f9c2f..119d7d01d0e77 100644
--- a/arch/arm64/kvm/vgic/vgic-v5.c
+++ b/arch/arm64/kvm/vgic/vgic-v5.c
@@ -172,6 +172,16 @@ int vgic_v5_finalize_ppi_state(struct kvm *kvm)
if (!vgic_is_v5(kvm))
return 0;
+ guard(mutex)(&kvm->arch.config_lock);
+
+ /*
+ * If SW_PPI has been advertised, then we know we already
+ * initialised the whole thing, and we can return early. Yes,
+ * this is pretty hackish as far as state tracking goes...
+ */
+ if (test_bit(GICV5_ARCH_PPI_SW_PPI, kvm->arch.vgic.gicv5_vm.vgic_ppi_mask))
+ return 0;
+
/* The PPI state for all VCPUs should be the same. Pick the first. */
vcpu0 = kvm_get_vcpu(kvm, 0);
--
2.47.3
^ permalink raw reply related
* [PATCH 07/15] KVM: arm64: vgic-v5: Transfer edge pending state to ICH_PPI_PENDRx_EL2
From: Marc Zyngier @ 2026-03-26 15:35 UTC (permalink / raw)
To: kvmarm, kvm, linux-arm-kernel
Cc: Joey Gouly, Suzuki K Poulose, Oliver Upton, Zenghui Yu,
Sascha Bischoff, Mark Brown
In-Reply-To: <20260326153530.3981879-1-maz@kernel.org>
While it is perfectly correct to leave the pending state of a level
interrupt as is when queuing it (it is, after all, only driven by
the line), edge pending state must be transfered, as nothing will
lower it.
Fixes: 4d591252bacb2 ("KVM: arm64: gic-v5: Implement PPI interrupt injection")
Link: https://sashiko.dev/#/patchset/20260319154937.3619520-1-sascha.bischoff%40arm.com
Signed-off-by: Marc Zyngier <maz@kernel.org>
---
arch/arm64/kvm/vgic/vgic-v5.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/arch/arm64/kvm/vgic/vgic-v5.c b/arch/arm64/kvm/vgic/vgic-v5.c
index 119d7d01d0e77..422741c86c6a8 100644
--- a/arch/arm64/kvm/vgic/vgic-v5.c
+++ b/arch/arm64/kvm/vgic/vgic-v5.c
@@ -445,8 +445,11 @@ void vgic_v5_flush_ppi_state(struct kvm_vcpu *vcpu)
irq = vgic_get_vcpu_irq(vcpu, intid);
- scoped_guard(raw_spinlock_irqsave, &irq->irq_lock)
+ scoped_guard(raw_spinlock_irqsave, &irq->irq_lock) {
__assign_bit(i, pendr, irq_is_pending(irq));
+ if (irq->config == VGIC_CONFIG_EDGE)
+ irq->pending_latch = false;
+ }
vgic_put_irq(vcpu->kvm, irq);
}
--
2.47.3
^ permalink raw reply related
* [PATCH 15/15] KVM: arm64: Don't advertises GICv3 in ID_PFR1_EL1 if AArch32 isn't supported
From: Marc Zyngier @ 2026-03-26 15:35 UTC (permalink / raw)
To: kvmarm, kvm, linux-arm-kernel
Cc: Joey Gouly, Suzuki K Poulose, Oliver Upton, Zenghui Yu,
Sascha Bischoff, Mark Brown
In-Reply-To: <20260326153530.3981879-1-maz@kernel.org>
Although the AArch32 ID regs are architecturally UNKNOWN when AArch32
isn't supported at any EL, KVM makes a point in making them RAZ.
Therefore, advertising GICv3 in ID_PFR1_EL1 must be gated on AArch32
being supported at least at EL0.
Fixes: a258a383b9177 ("KVM: arm64: gic-v5: Sanitize ID_AA64PFR2_EL1.GCIE")
Reported-by: Mark Brown <broonie@kernel.org>
Signed-off-by: Marc Zyngier <maz@kernel.org>
---
arch/arm64/kvm/vgic/vgic-init.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/arch/arm64/kvm/vgic/vgic-init.c b/arch/arm64/kvm/vgic/vgic-init.c
index ecb0aea180327..5c684ecf79e66 100644
--- a/arch/arm64/kvm/vgic/vgic-init.c
+++ b/arch/arm64/kvm/vgic/vgic-init.c
@@ -700,7 +700,8 @@ void kvm_vgic_finalize_idregs(struct kvm *kvm)
break;
case KVM_DEV_TYPE_ARM_VGIC_V3:
aa64pfr0 |= SYS_FIELD_PREP_ENUM(ID_AA64PFR0_EL1, GIC, IMP);
- pfr1 |= SYS_FIELD_PREP_ENUM(ID_PFR1_EL1, GIC, GICv3);
+ if (kvm_supports_32bit_el0())
+ pfr1 |= SYS_FIELD_PREP_ENUM(ID_PFR1_EL1, GIC, GICv3);
break;
case KVM_DEV_TYPE_ARM_VGIC_V5:
aa64pfr2 |= SYS_FIELD_PREP_ENUM(ID_AA64PFR2_EL1, GCIE, IMP);
--
2.47.3
^ permalink raw reply related
* [PATCH 01/15] KVM: arm64: vgic: Don't reset cpuif/redist addresses at finalize time
From: Marc Zyngier @ 2026-03-26 15:35 UTC (permalink / raw)
To: kvmarm, kvm, linux-arm-kernel
Cc: Joey Gouly, Suzuki K Poulose, Oliver Upton, Zenghui Yu,
Sascha Bischoff, Mark Brown
In-Reply-To: <20260326153530.3981879-1-maz@kernel.org>
Although we are OK with rewriting idregs at finalize time, resetting
the guest's cpuif (GICv3) or redistributor (GICv3) addresses once
we start running the guest is a pretty bad idea.
Move back this initialisation to vgic creation time.
Fixes: a258a383b9177 ("KVM: arm64: gic-v5: Sanitize ID_AA64PFR2_EL1.GCIE")
Link: https://patch.msgid.link/20260323174713.3183111-1-maz@kernel.org
Signed-off-by: Marc Zyngier <maz@kernel.org>
---
arch/arm64/kvm/vgic/vgic-init.c | 11 +++++++++--
1 file changed, 9 insertions(+), 2 deletions(-)
diff --git a/arch/arm64/kvm/vgic/vgic-init.c b/arch/arm64/kvm/vgic/vgic-init.c
index 47169604100f2..fd872079f2a24 100644
--- a/arch/arm64/kvm/vgic/vgic-init.c
+++ b/arch/arm64/kvm/vgic/vgic-init.c
@@ -147,6 +147,15 @@ int kvm_vgic_create(struct kvm *kvm, u32 type)
kvm->arch.vgic.implementation_rev = KVM_VGIC_IMP_REV_LATEST;
kvm->arch.vgic.vgic_dist_base = VGIC_ADDR_UNDEF;
+ switch (type) {
+ case KVM_DEV_TYPE_ARM_VGIC_V2:
+ kvm->arch.vgic.vgic_cpu_base = VGIC_ADDR_UNDEF;
+ break;
+ case KVM_DEV_TYPE_ARM_VGIC_V3:
+ INIT_LIST_HEAD(&kvm->arch.vgic.rd_regions);
+ break;
+ }
+
/*
* We've now created the GIC. Update the system register state
* to accurately reflect what we've created.
@@ -684,10 +693,8 @@ void kvm_vgic_finalize_idregs(struct kvm *kvm)
switch (type) {
case KVM_DEV_TYPE_ARM_VGIC_V2:
- kvm->arch.vgic.vgic_cpu_base = VGIC_ADDR_UNDEF;
break;
case KVM_DEV_TYPE_ARM_VGIC_V3:
- INIT_LIST_HEAD(&kvm->arch.vgic.rd_regions);
aa64pfr0 |= SYS_FIELD_PREP_ENUM(ID_AA64PFR0_EL1, GIC, IMP);
pfr1 |= SYS_FIELD_PREP_ENUM(ID_PFR1_EL1, GIC, GICv3);
break;
--
2.47.3
^ permalink raw reply related
* [PATCH 03/15] arm64: Fix field references for ICH_PPI_DVIR[01]_EL2
From: Marc Zyngier @ 2026-03-26 15:35 UTC (permalink / raw)
To: kvmarm, kvm, linux-arm-kernel
Cc: Joey Gouly, Suzuki K Poulose, Oliver Upton, Zenghui Yu,
Sascha Bischoff, Mark Brown
In-Reply-To: <20260326153530.3981879-1-maz@kernel.org>
The ICH_PPI_DVIR[01]_EL2 registers should refer to the ICH_PPI_DVIRx_EL2
fields, instead of ICH_PPI_DVIx_EL2.
Fixes: 2808a8337078f ("arm64/sysreg: Add remaining GICv5 ICC_ & ICH_ sysregs for KVM support")
Link: https://sashiko.dev/#/patchset/20260319154937.3619520-1-sascha.bischoff%40arm.com
Signed-off-by: Marc Zyngier <maz@kernel.org>
---
arch/arm64/tools/sysreg | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/arch/arm64/tools/sysreg b/arch/arm64/tools/sysreg
index 51dcca5b2fa6e..3b57cb692c5be 100644
--- a/arch/arm64/tools/sysreg
+++ b/arch/arm64/tools/sysreg
@@ -4888,11 +4888,11 @@ Field 0 DVI0
EndSysregFields
Sysreg ICH_PPI_DVIR0_EL2 3 4 12 10 0
-Fields ICH_PPI_DVIx_EL2
+Fields ICH_PPI_DVIRx_EL2
EndSysreg
Sysreg ICH_PPI_DVIR1_EL2 3 4 12 10 1
-Fields ICH_PPI_DVIx_EL2
+Fields ICH_PPI_DVIRx_EL2
EndSysreg
SysregFields ICH_PPI_ENABLERx_EL2
--
2.47.3
^ permalink raw reply related
* [PATCH 00/15] KVM: arm64: First batch of vgic-v5 related fixes
From: Marc Zyngier @ 2026-03-26 15:35 UTC (permalink / raw)
To: kvmarm, kvm, linux-arm-kernel
Cc: Joey Gouly, Suzuki K Poulose, Oliver Upton, Zenghui Yu,
Sascha Bischoff, Mark Brown
Well, merging the first batch of vgic-v5 patches didn't go smoothly at
all. We initially found a couple of regressions, but most of the crap
was actually uncovered by everyone's new best friend (enemy?), the AI
bot sitting behind sashiko.dev [1].
While not all of the remarks were valid, a bunch of them were actually
extremely pertinent, and resulted in me frantically hacking away at
the series. Hopefully the bot doesn't find even more issues in the
fixes. Note that the first patch has already been posted and merged,
and is only here for reference.
Note that given the amount of rework, I'm really in two minds between
adding these patches on top, or pulling the whole series for another
cycle. I guess time will tell.
[1] https://sashiko.dev/#/patchset/20260319154937.3619520-1-sascha.bischoff%40arm.com
Marc Zyngier (15):
KVM: arm64: vgic: Don't reset cpuif/redist addresses at finalize time
KVM: arm64: Don't skip per-vcpu NV initialisation
arm64: Fix field references for ICH_PPI_DVIR[01]_EL2
KVM: arm64: Fix writeable mask for ID_AA64PFR2_EL1
KVM: arm64: Account for RESx bits in __compute_fgt()
KVM: arm64: vgic-v5: Hold config_lock while finalizing GICv5 PPIs
KVM: arm64: vgic-v5: Transfer edge pending state to ICH_PPI_PENDRx_EL2
KVM: arm64: vgic-v5: Cast vgic_apr to u32 to avoid undefined
behaviours
KVM: arm64: vgic-v5: align priority comparison with other GICs
KVM: arm64: vgic-v5: Correctly set dist->ready once initialised
KVM: arm64: Kill arch_timer_context::direct field
KVM: arm64: Remove evaluation of timer state in
kvm_cpu_has_pending_timer()
KVM: arm64: Move GICv5 timer PPI validation into
timer_irqs_are_valid()
KVM: arm64: Correctly plumb ID_AA64PFR2_EL1 into pkvm idreg handling
KVM: arm64: Don't advertises GICv3 in ID_PFR1_EL1 if AArch32 isn't
supported
arch/arm64/kvm/arch_timer.c | 32 +++++++++++++-----------------
arch/arm64/kvm/config.c | 4 ++--
arch/arm64/kvm/hyp/nvhe/sys_regs.c | 2 +-
arch/arm64/kvm/sys_regs.c | 20 +++++++++----------
arch/arm64/kvm/vgic/vgic-init.c | 32 ++++++++++++++++++++----------
arch/arm64/kvm/vgic/vgic-v5.c | 24 +++++++++++++++++-----
arch/arm64/tools/sysreg | 4 ++--
include/kvm/arm_arch_timer.h | 3 ---
8 files changed, 70 insertions(+), 51 deletions(-)
--
2.47.3
^ permalink raw reply
* [PATCH 04/15] KVM: arm64: Fix writeable mask for ID_AA64PFR2_EL1
From: Marc Zyngier @ 2026-03-26 15:35 UTC (permalink / raw)
To: kvmarm, kvm, linux-arm-kernel
Cc: Joey Gouly, Suzuki K Poulose, Oliver Upton, Zenghui Yu,
Sascha Bischoff, Mark Brown
In-Reply-To: <20260326153530.3981879-1-maz@kernel.org>
The writeable mask for fields in ID_AA64PFR2_EL1 has been accidentally
inverted, which isn't a very good idea.
Restore the expected polarity.
Fixes: a258a383b9177 ("KVM: arm64: gic-v5: Sanitize ID_AA64PFR2_EL1.GCIE")
Link: https://sashiko.dev/#/patchset/20260319154937.3619520-1-sascha.bischoff%40arm.com
Signed-off-by: Marc Zyngier <maz@kernel.org>
---
arch/arm64/kvm/sys_regs.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
index 18e2d2fccedb8..6a96cb7ba9a3c 100644
--- a/arch/arm64/kvm/sys_regs.c
+++ b/arch/arm64/kvm/sys_regs.c
@@ -3304,10 +3304,10 @@ static const struct sys_reg_desc sys_reg_descs[] = {
ID_AA64PFR1_EL1_MPAM_frac |
ID_AA64PFR1_EL1_MTE)),
ID_FILTERED(ID_AA64PFR2_EL1, id_aa64pfr2_el1,
- ~(ID_AA64PFR2_EL1_FPMR |
- ID_AA64PFR2_EL1_MTEFAR |
- ID_AA64PFR2_EL1_MTESTOREONLY |
- ID_AA64PFR2_EL1_GCIE)),
+ (ID_AA64PFR2_EL1_FPMR |
+ ID_AA64PFR2_EL1_MTEFAR |
+ ID_AA64PFR2_EL1_MTESTOREONLY |
+ ID_AA64PFR2_EL1_GCIE)),
ID_UNALLOCATED(4,3),
ID_WRITABLE(ID_AA64ZFR0_EL1, ~ID_AA64ZFR0_EL1_RES0),
ID_HIDDEN(ID_AA64SMFR0_EL1),
--
2.47.3
^ permalink raw reply related
* [PATCH 02/15] KVM: arm64: Don't skip per-vcpu NV initialisation
From: Marc Zyngier @ 2026-03-26 15:35 UTC (permalink / raw)
To: kvmarm, kvm, linux-arm-kernel
Cc: Joey Gouly, Suzuki K Poulose, Oliver Upton, Zenghui Yu,
Sascha Bischoff, Mark Brown
In-Reply-To: <20260326153530.3981879-1-maz@kernel.org>
Some GICv5-related rework have resulted in the NV sanitisation of
registers being skipped for secondary vcpus, which is a pretty bad
idea.
Hoist the NV init early so that it is always executed.
Fixes: cbd8c958be54a ("KVM: arm64: Return early from kvm_finalize_sys_regs() if guest has run")
Link: https://sashiko.dev/#/patchset/20260319154937.3619520-1-sascha.bischoff%40arm.com
Signed-off-by: Marc Zyngier <maz@kernel.org>
---
arch/arm64/kvm/sys_regs.c | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
index e1001544d4f40..18e2d2fccedb8 100644
--- a/arch/arm64/kvm/sys_regs.c
+++ b/arch/arm64/kvm/sys_regs.c
@@ -5772,6 +5772,12 @@ int kvm_finalize_sys_regs(struct kvm_vcpu *vcpu)
guard(mutex)(&kvm->arch.config_lock);
+ if (vcpu_has_nv(vcpu)) {
+ int ret = kvm_init_nv_sysregs(vcpu);
+ if (ret)
+ return ret;
+ }
+
if (kvm_vm_has_ran_once(kvm))
return 0;
@@ -5820,12 +5826,6 @@ int kvm_finalize_sys_regs(struct kvm_vcpu *vcpu)
kvm_vgic_finalize_idregs(kvm);
}
- if (vcpu_has_nv(vcpu)) {
- int ret = kvm_init_nv_sysregs(vcpu);
- if (ret)
- return ret;
- }
-
return 0;
}
--
2.47.3
^ permalink raw reply related
* [PATCH 05/15] KVM: arm64: Account for RESx bits in __compute_fgt()
From: Marc Zyngier @ 2026-03-26 15:35 UTC (permalink / raw)
To: kvmarm, kvm, linux-arm-kernel
Cc: Joey Gouly, Suzuki K Poulose, Oliver Upton, Zenghui Yu,
Sascha Bischoff, Mark Brown, stable
In-Reply-To: <20260326153530.3981879-1-maz@kernel.org>
When computing Fine Grained Traps, it is preferable to account for
the reserved bits. The HW will most probably ignore them, unless the
bits have been repurposed to do something else.
Use caution, and fold our view of the reserved bits in,
Fixes: c259d763e6b09 ("KVM: arm64: Account for RES1 bits in DECLARE_FEAT_MAP() and co")
Link: https://sashiko.dev/#/patchset/20260319154937.3619520-1-sascha.bischoff%40arm.com
Signed-off-by: Marc Zyngier <maz@kernel.org>
Cc: stable@vger.kernel.org
---
arch/arm64/kvm/config.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/arch/arm64/kvm/config.c b/arch/arm64/kvm/config.c
index e14685343191b..f35b8dddd7c1f 100644
--- a/arch/arm64/kvm/config.c
+++ b/arch/arm64/kvm/config.c
@@ -1663,8 +1663,8 @@ static __always_inline void __compute_fgt(struct kvm_vcpu *vcpu, enum vcpu_sysre
clear |= ~nested & m->nmask;
}
- val |= set;
- val &= ~clear;
+ val |= set | m->res1;
+ val &= ~(clear | m->res0);
*vcpu_fgt(vcpu, reg) = val;
}
--
2.47.3
^ permalink raw reply related
* Re: [PATCH] perf/arm-cmn: Fix incorrect error check for devm_ioremap()
From: Will Deacon @ 2026-03-26 15:34 UTC (permalink / raw)
To: Chen Ni
Cc: catalin.marinas, kernel-team, Will Deacon, robin.murphy,
mark.rutland, ilkka, linux-arm-kernel, linux-perf-users
In-Reply-To: <20260326090856.644136-1-nichen@iscas.ac.cn>
On Thu, 26 Mar 2026 17:08:56 +0800, Chen Ni wrote:
> Check devm_ioremap() return value for NULL instead of ERR_PTR and return
> -ENOMEM on failure. devm_ioremap() never returns ERR_PTR, using IS_ERR()
> skips the error path and may cause a NULL pointer dereference.
>
>
Applied to will (for-next/perf), thanks!
[1/1] perf/arm-cmn: Fix incorrect error check for devm_ioremap()
https://git.kernel.org/will/c/d49802b6617b
Cheers,
--
Will
https://fixes.arm64.dev
https://next.arm64.dev
https://will.arm64.dev
^ permalink raw reply
* Re: [PATCH] perf/arm-cmn: Fix resource_size_t printk specifier in arm_cmn_init_dtc()
From: Will Deacon @ 2026-03-26 15:34 UTC (permalink / raw)
To: Robin Murphy, Mark Rutland, Ilkka Koskinen, Nathan Chancellor
Cc: catalin.marinas, kernel-team, Will Deacon, linux-arm-kernel,
linux-perf-users, linux-kernel
In-Reply-To: <20260325-perf-arm-cmn-fix-resource_size_t-format-v1-1-e84d52ee3e81@kernel.org>
On Wed, 25 Mar 2026 19:19:26 -0700, Nathan Chancellor wrote:
> When building for 32-bit ARM, there is a warning when using the %llx
> specifier to print a resource_size_t variable:
>
> drivers/perf/arm-cmn.c: In function 'arm_cmn_init_dtc':
> drivers/perf/arm-cmn.c:2149:73: error: format '%llx' expects argument of type 'long long unsigned int', but argument 4 has type 'resource_size_t' {aka 'unsigned int'} [-Werror=format=]
> 2149 | "Failed to request DTC region 0x%llx\n", base);
> | ~~~^ ~~~~
> | | |
> | | resource_size_t {aka unsigned int}
> | long long unsigned int
> | %x
>
> [...]
Applied to will (for-next/perf), thanks!
[1/1] perf/arm-cmn: Fix resource_size_t printk specifier in arm_cmn_init_dtc()
https://git.kernel.org/will/c/47f06ebbe8da
Cheers,
--
Will
https://fixes.arm64.dev
https://next.arm64.dev
https://will.arm64.dev
^ permalink raw reply
* Re: [PATCH net-next v2 4/4] net: phy: Introduce Airoha AN8801/R Gigabit Ethernet PHY driver
From: Russell King (Oracle) @ 2026-03-26 15:26 UTC (permalink / raw)
To: Andrew Lunn
Cc: Andrew Lunn, Louis-Alexis Eyraud, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, AngeloGioacchino Del Regno, Heiner Kallweit,
kevin-kw.huang, macpaul.lin, matthias.bgg, kernel, netdev,
devicetree, linux-arm-kernel, linux-mediatek, linux-kernel
In-Reply-To: <044110c5-da1e-48c0-93fd-35553e86b271@lunn.ch>
On Thu, Mar 26, 2026 at 04:24:23PM +0100, Andrew Lunn wrote:
> On Thu, Mar 26, 2026 at 03:13:19PM +0000, Russell King (Oracle) wrote:
> > On Thu, Mar 26, 2026 at 01:04:15PM +0100, Louis-Alexis Eyraud wrote:
> > > +static int an8801r_set_wol(struct phy_device *phydev,
> > > + struct ethtool_wolinfo *wol)
> > > +{
> > > + struct net_device *attach_dev = phydev->attached_dev;
> > > + const unsigned char *macaddr = attach_dev->dev_addr;
> >
> > This isn't a criticism for this patch, but a discussion point for
> > phylib itself.
> >
> > It occurs to me that there's a weakness in the phylib interface for WoL,
> > specifically when WoL is enabled at the PHY, but someone then changes
> > the interface's MAC address - there doesn't seem to be a way for the
> > address programmed into the PHY to be updated. Should there be?
> >
> > Do we instead expect users to disable WoL before changing the MAC for
> > a network interface?
>
> Program the MAC address during suspend? I assume userspace is no
> longer active at this point, so the address should be stable.
What is the timing requirements for a system going into suspend vs a WoL
packet being sent? Should a WoL packet abort entry into suspend? If yes,
then we need to program the MAC before the PHY is suspended, because
suspend could already be in progress.
--
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
FTTP is here! 80Mbps down 10Mbps up. Decent connectivity at last!
^ permalink raw reply
* Re: [PATCH v3 09/10] dt-bindings: firmware: add arm,ras-cper
From: Rob Herring @ 2026-03-26 15:24 UTC (permalink / raw)
To: Ahmed Tiba
Cc: linux-acpi, devicetree, linux-cxl, Michael.Zhao2,
linux-arm-kernel, Dmitry.Lamerov, rafael, conor, will, bp,
catalin.marinas, krzk+dt, linux-doc, mchehab+huawei, tony.luck
In-Reply-To: <20260318-topics-ahmtib01-ras_ffh_arm_internal_review-v3-9-48e6a1c249ef@arm.com>
On Wed, Mar 18, 2026 at 08:48:06PM +0000, Ahmed Tiba wrote:
> Describe the DeviceTree node that exposes the Arm firmware-first
> CPER provider and hook the file into MAINTAINERS so the
> binding has an owner.
>
> Signed-off-by: Ahmed Tiba <ahmed.tiba@arm.com>
> ---
> .../devicetree/bindings/firmware/arm,ras-cper.yaml | 71 ++++++++++++++++++++++
> MAINTAINERS | 5 ++
> 2 files changed, 76 insertions(+)
>
> diff --git a/Documentation/devicetree/bindings/firmware/arm,ras-cper.yaml b/Documentation/devicetree/bindings/firmware/arm,ras-cper.yaml
> new file mode 100644
> index 000000000000..bd93cfb8d222
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/firmware/arm,ras-cper.yaml
> @@ -0,0 +1,71 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/firmware/arm,ras-cper.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Arm RAS CPER provider
> +
> +maintainers:
> + - Ahmed Tiba <ahmed.tiba@arm.com>
> +
> +description: |
> + Arm Reliability, Availability and Serviceability (RAS) firmware can expose
> + a firmware-first CPER error source directly via DeviceTree. Firmware
> + provides the CPER Generic Error Status block and notifies the OS through
> + an interrupt.
> +
> +properties:
> + compatible:
> + const: arm,ras-cper
> +
> + reg:
> + minItems: 1
> + items:
> + - description:
> + CPER Generic Error Status block exposed by firmware
> + - description:
> + Optional 32- or 64-bit doorbell register used on platforms
> + where firmware needs an explicit "ack" handshake before overwriting
> + the CPER buffer. Firmware watches bit 0 and expects the OS to set it
> + once the current status block has been consumed.
> +
> + interrupts:
> + maxItems: 1
> + description:
> + Interrupt used to signal that a new status record is ready.
> +
> + memory-region:
> + $ref: /schemas/types.yaml#/definitions/phandle
memory-region already has a defined type. You just need to define how
many entries (maxItems: 1).
> + description:
> + Optional phandle to the reserved-memory entry that backs the status
> + buffer so firmware and the OS use the same carved-out region.
> +
> +required:
> + - compatible
> + - reg
> + - interrupts
> +
> +additionalProperties: false
> +
> +examples:
> + - |
> + #include <dt-bindings/interrupt-controller/arm-gic.h>
> +
> + reserved-memory {
> + #address-cells = <2>;
> + #size-cells = <2>;
> + ras_cper_buffer: cper@fe800000 {
> + reg = <0x0 0xfe800000 0x0 0x1000>;
> + no-map;
> + };
> + };
> +
> + error-handler@fe800000 {
> + compatible = "arm,ras-cper";
> + reg = <0xfe800000 0x1000>,
Wait! Why is the reserved address here? There's 2 problems with that.
There shouldn't be same address in 2 places in the DT. The 2nd is
reserved memory should only be regions within DRAM (or whatever is
system memory).
Rob
^ permalink raw reply
* Re: [PATCH net-next v2 4/4] net: phy: Introduce Airoha AN8801/R Gigabit Ethernet PHY driver
From: Andrew Lunn @ 2026-03-26 15:24 UTC (permalink / raw)
To: Russell King (Oracle)
Cc: Andrew Lunn, Louis-Alexis Eyraud, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, AngeloGioacchino Del Regno, Heiner Kallweit,
kevin-kw.huang, macpaul.lin, matthias.bgg, kernel, netdev,
devicetree, linux-arm-kernel, linux-mediatek, linux-kernel
In-Reply-To: <acVND6DdpM9czIwU@shell.armlinux.org.uk>
On Thu, Mar 26, 2026 at 03:13:19PM +0000, Russell King (Oracle) wrote:
> On Thu, Mar 26, 2026 at 01:04:15PM +0100, Louis-Alexis Eyraud wrote:
> > +static int an8801r_set_wol(struct phy_device *phydev,
> > + struct ethtool_wolinfo *wol)
> > +{
> > + struct net_device *attach_dev = phydev->attached_dev;
> > + const unsigned char *macaddr = attach_dev->dev_addr;
>
> This isn't a criticism for this patch, but a discussion point for
> phylib itself.
>
> It occurs to me that there's a weakness in the phylib interface for WoL,
> specifically when WoL is enabled at the PHY, but someone then changes
> the interface's MAC address - there doesn't seem to be a way for the
> address programmed into the PHY to be updated. Should there be?
>
> Do we instead expect users to disable WoL before changing the MAC for
> a network interface?
Program the MAC address during suspend? I assume userspace is no
longer active at this point, so the address should be stable.
Andrew
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox