From: Fangyu Yu When mapping writable pages, the RISC-V format code currently pre-sets the PTE D bit unconditionally. If hardware dirty tracking is active (DC.tc.GADE set), the IOMMU sets D autonomously on the first write. Pre-setting D makes every new mapping appear dirty immediately and breaks dirty tracking. Introduce PT_FEAT_RISCV_DIRTY_TRACKING_ACTIVE and, when set, leave D cleared for new writable mappings so hardware can capture the first write. Keep pre-setting D when dirty tracking is inactive. Only meaningful for second-stage (iohgatp) page tables. Signed-off-by: Fangyu Yu --- drivers/iommu/generic_pt/fmt/riscv.h | 13 +++++++++++-- include/linux/generic_pt/common.h | 8 ++++++++ 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/drivers/iommu/generic_pt/fmt/riscv.h b/drivers/iommu/generic_pt/fmt/riscv.h index 4fe645e60375..0281356cfaf6 100644 --- a/drivers/iommu/generic_pt/fmt/riscv.h +++ b/drivers/iommu/generic_pt/fmt/riscv.h @@ -248,8 +248,17 @@ static inline int riscvpt_iommu_set_prot(struct pt_common *common, u64 pte; pte = RISCVPT_A | RISCVPT_U; - if (iommu_prot & IOMMU_WRITE) - pte |= RISCVPT_W | RISCVPT_R | RISCVPT_D; + if (iommu_prot & IOMMU_WRITE) { + pte |= RISCVPT_W | RISCVPT_R; + /* + * When hardware dirty tracking is active (GADE set), the IOMMU + * sets the D bit autonomously on the first write access. + * + */ + if (!(common->features & + BIT(PT_FEAT_RISCV_DIRTY_TRACKING_ACTIVE))) + pte |= RISCVPT_D; + } if (iommu_prot & IOMMU_READ) pte |= RISCVPT_R; if (!(iommu_prot & IOMMU_NOEXEC)) diff --git a/include/linux/generic_pt/common.h b/include/linux/generic_pt/common.h index e82dff33ece8..4606c7464c27 100644 --- a/include/linux/generic_pt/common.h +++ b/include/linux/generic_pt/common.h @@ -193,6 +193,14 @@ enum { * Support the 64k contiguous page size following the Svnapot extension. */ PT_FEAT_RISCV_SVNAPOT_64K = PT_FEAT_FMT_START, + /* + * Hardware dirty tracking is currently active: DC.tc.GADE is set and + * the IOMMU will set the D bit in PTEs autonomously on write access. + * When this flag is set, new mappings must not pre-set the D bit so + * that every write is correctly captured by hardware. + * Only meaningful for second-stage (iohgatp) page tables. + */ + PT_FEAT_RISCV_DIRTY_TRACKING_ACTIVE, }; -- 2.50.1