Linux kernel -- 32bit - 64bit mmu 在Arm 与 X64上的差异

博客聚焦于Linux内核,探讨32位和64位MMU在Arm与X64架构上的差异,涉及信息技术中操作系统内核及硬件架构相关知识,有助于了解不同架构下MMU的特性与表现。

在这里插入图片描述
在这里插入图片描述

// SPDX-License-Identifier: GPL-2.0-only // Miscellaneous Arm SMMU implementation and integration quirks // Copyright (C) 2019 Arm Limited #define pr_fmt(fmt) "arm-smmu: " fmt #include <linux/bitfield.h> #include <linux/of.h> #include "arm-smmu.h" static int arm_smmu_gr0_ns(int offset) { switch (offset) { case ARM_SMMU_GR0_sCR0: case ARM_SMMU_GR0_sACR: case ARM_SMMU_GR0_sGFSR: case ARM_SMMU_GR0_sGFSYNR0: case ARM_SMMU_GR0_sGFSYNR1: case ARM_SMMU_GR0_sGFSYNR2: return offset + 0x400; default: return offset; } } static u32 arm_smmu_read_ns(struct arm_smmu_device *smmu, int page, int offset) { if (page == ARM_SMMU_GR0) offset = arm_smmu_gr0_ns(offset); return readl_relaxed(arm_smmu_page(smmu, page) + offset); } static void arm_smmu_write_ns(struct arm_smmu_device *smmu, int page, int offset, u32 val) { if (page == ARM_SMMU_GR0) offset = arm_smmu_gr0_ns(offset); writel_relaxed(val, arm_smmu_page(smmu, page) + offset); } /* Since we don't care for sGFAR, we can do without 64-bit accessors */ static const struct arm_smmu_impl calxeda_impl = { .read_reg = arm_smmu_read_ns, .write_reg = arm_smmu_write_ns, }; struct cavium_smmu { struct arm_smmu_device smmu; u32 id_base; }; static int cavium_cfg_probe(struct arm_smmu_device *smmu) { static atomic_t context_count = ATOMIC_INIT(0); struct cavium_smmu *cs = container_of(smmu, struct cavium_smmu, smmu); /* * Cavium CN88xx erratum #27704. * Ensure ASID and VMID allocation is unique across all SMMUs in * the system. */ cs->id_base = atomic_fetch_add(smmu->num_context_banks, &context_count); dev_notice(smmu->dev, "\tenabling workaround for Cavium erratum 27704\n"); return 0; } static int cavium_init_context(struct arm_smmu_domain *smmu_domain, struct io_pgtable_cfg *pgtbl_cfg, struct device *dev) { struct cavium_smmu *cs = container_of(smmu_domain->smmu, struct cavium_smmu, smmu); if (smmu_domain->stage == ARM_SMMU_DOMAIN_S2) smmu_domain->cfg.vmid += cs->id_base; else smmu_domain->cfg.asid += cs->id_base; return 0; } static const struct arm_smmu_impl cavium_impl = { .cfg_probe = cavium_cfg_probe, .init_context = cavium_init_context, }; static struct arm_smmu_device *cavium_smmu_impl_init(struct arm_smmu_device *smmu) { struct cavium_smmu *cs; cs = devm_krealloc(smmu->dev, smmu, sizeof(*cs), GFP_KERNEL); if (!cs) return ERR_PTR(-ENOMEM); cs->smmu.impl = &cavium_impl; return &cs->smmu; } #define ARM_MMU500_ACTLR_CPRE (1 << 1) #define ARM_MMU500_ACR_CACHE_LOCK (1 << 26) #define ARM_MMU500_ACR_S2CRB_TLBEN (1 << 10) #define ARM_MMU500_ACR_SMTNMB_TLBEN (1 << 8) int arm_mmu500_reset(struct arm_smmu_device *smmu) { u32 reg, major; int i; /* * On MMU-500 r2p0 onwards we need to clear ACR.CACHE_LOCK before * writes to the context bank ACTLRs will stick. And we just hope that * Secure has also cleared SACR.CACHE_LOCK for this to take effect... */ reg = arm_smmu_gr0_read(smmu, ARM_SMMU_GR0_ID7); major = FIELD_GET(ARM_SMMU_ID7_MAJOR, reg); reg = arm_smmu_gr0_read(smmu, ARM_SMMU_GR0_sACR); if (major >= 2) reg &= ~ARM_MMU500_ACR_CACHE_LOCK; /* * Allow unmatched Stream IDs to allocate bypass * TLB entries for reduced latency. */ reg |= ARM_MMU500_ACR_SMTNMB_TLBEN | ARM_MMU500_ACR_S2CRB_TLBEN; arm_smmu_gr0_write(smmu, ARM_SMMU_GR0_sACR, reg); /* * Disable MMU-500's not-particularly-beneficial next-page * prefetcher for the sake of at least 5 known errata. */ for (i = 0; i < smmu->num_context_banks; ++i) { reg = arm_smmu_cb_read(smmu, i, ARM_SMMU_CB_ACTLR); reg &= ~ARM_MMU500_ACTLR_CPRE; arm_smmu_cb_write(smmu, i, ARM_SMMU_CB_ACTLR, reg); reg = arm_smmu_cb_read(smmu, i, ARM_SMMU_CB_ACTLR); if (reg & ARM_MMU500_ACTLR_CPRE) dev_warn_once(smmu->dev, "Failed to disable prefetcher for errata workarounds, check SACR.CACHE_LOCK\n"); } return 0; } static const struct arm_smmu_impl arm_mmu500_impl = { .reset = arm_mmu500_reset, }; static u64 mrvl_mmu500_readq(struct arm_smmu_device *smmu, int page, int off) { /* * Marvell Armada-AP806 erratum #582743. * Split all the readq to double readl */ return hi_lo_readq_relaxed(arm_smmu_page(smmu, page) + off); } static void mrvl_mmu500_writeq(struct arm_smmu_device *smmu, int page, int off, u64 val) { /* * Marvell Armada-AP806 erratum #582743. * Split all the writeq to double writel */ hi_lo_writeq_relaxed(val, arm_smmu_page(smmu, page) + off); } static int mrvl_mmu500_cfg_probe(struct arm_smmu_device *smmu) { /* * Armada-AP806 erratum #582743. * Hide the SMMU_IDR2.PTFSv8 fields to sidestep the AArch64 * formats altogether and allow using 32 bits access on the * interconnect. */ smmu->features &= ~(ARM_SMMU_FEAT_FMT_AARCH64_4K | ARM_SMMU_FEAT_FMT_AARCH64_16K | ARM_SMMU_FEAT_FMT_AARCH64_64K); return 0; } static const struct arm_smmu_impl mrvl_mmu500_impl = { .read_reg64 = mrvl_mmu500_readq, .write_reg64 = mrvl_mmu500_writeq, .cfg_probe = mrvl_mmu500_cfg_probe, .reset = arm_mmu500_reset, }; struct arm_smmu_device *arm_smmu_impl_init(struct arm_smmu_device *smmu) { const struct device_node *np = smmu->dev->of_node; /* * Set the impl for model-specific implementation quirks first, * such that platform integration quirks can pick it up and * inherit from it if necessary. */ switch (smmu->model) { case ARM_MMU500: smmu->impl = &arm_mmu500_impl; break; case CAVIUM_SMMUV2: return cavium_smmu_impl_init(smmu); default: break; } /* This is implicitly MMU-400 */ if (of_property_read_bool(np, "calxeda,smmu-secure-config-access")) smmu->impl = &calxeda_impl; if (of_device_is_compatible(np, "nvidia,tegra234-smmu") || of_device_is_compatible(np, "nvidia,tegra194-smmu") || of_device_is_compatible(np, "nvidia,tegra186-smmu")) return nvidia_smmu_impl_init(smmu); if (IS_ENABLED(CONFIG_ARM_SMMU_QCOM)) smmu = qcom_smmu_impl_init(smmu); if (of_device_is_compatible(np, "marvell,ap806-smmu-500")) smmu->impl = &mrvl_mmu500_impl; return smmu; } 上边的是一个内核版本的代码, 其作用是什么, 该内核在CPU:飞腾S2500(双路64核)机器上运行后日志中报错: Sep 12 10:32:57 localhost kernel: [ 7.418320] arm-smmu arm-smmu.0.auto: probing hardware configuration... Sep 12 10:32:57 localhost kernel: [ 7.418338] arm-smmu arm-smmu.0.auto: SMMUv2 with: Sep 12 10:32:57 localhost kernel: [ 7.418343] arm-smmu arm-smmu.0.auto: #011stage 1 translation Sep 12 10:32:57 localhost kernel: [ 7.418346] arm-smmu arm-smmu.0.auto: #011stage 2 translation Sep 12 10:32:57 localhost kernel: [ 7.418350] arm-smmu arm-smmu.0.auto: #011nested translation Sep 12 10:32:57 localhost kernel: [ 7.418352] arm-smmu arm-smmu.0.auto: #011coherent table walk Sep 12 10:32:57 localhost kernel: [ 7.418356] arm-smmu arm-smmu.0.auto: #011stream matching with 64 register groups Sep 12 10:32:57 localhost kernel: [ 7.418362] arm-smmu arm-smmu.0.auto: #01132 context banks (0 stage-2 only) Sep 12 10:32:57 localhost kernel: [ 7.418368] arm-smmu arm-smmu.0.auto: #011Supported page sizes: 0x61311000 Sep 12 10:32:57 localhost kernel: [ 7.418372] arm-smmu arm-smmu.0.auto: #011Stage-1: 48-bit VA -> 48-bit IPA Sep 12 10:32:57 localhost kernel: [ 7.418375] arm-smmu arm-smmu.0.auto: #011Stage-2: 48-bit IPA -> 48-bit PA Sep 12 10:32:57 localhost kernel: [ 7.418463] arm-smmu arm-smmu.0.auto: #011preserved 0 boot mappings Sep 12 10:32:57 localhost kernel: [ 7.418486] arm-smmu arm-smmu.0.auto: Failed to disable prefetcher for errata workarounds, check SACR.CACHE_LOCK Sep 12 10:32:57 localhost kernel: [ 7.418547] arm-smmu arm-smmu.1.auto: probing hardware configuration... Sep 12 10:32:57 localhost kernel: [ 7.418551] arm-smmu arm-smmu.1.auto: SMMUv2 with: Sep 12 10:32:57 localhost kernel: [ 7.418554] arm-smmu arm-smmu.1.auto: #011stage 1 translation Sep 12 10:32:57 localhost kernel: [ 7.418557] arm-smmu arm-smmu.1.auto: #011stage 2 translation Sep 12 10:32:57 localhost kernel: [ 7.418560] arm-smmu arm-smmu.1.auto: #011nested translation Sep 12 10:32:57 localhost kernel: [ 7.418562] arm-smmu arm-smmu.1.auto: #011coherent table walk Sep 12 10:32:57 localhost kernel: [ 7.418566] arm-smmu arm-smmu.1.auto: #011stream matching with 64 register groups Sep 12 10:32:57 localhost kernel: [ 7.418570] arm-smmu arm-smmu.1.auto: #01132 context banks (0 stage-2 only) Sep 12 10:32:57 localhost kernel: [ 7.418575] arm-smmu arm-smmu.1.auto: #011Supported page sizes: 0x61311000 Sep 12 10:32:57 localhost kernel: [ 7.418578] arm-smmu arm-smmu.1.auto: #011Stage-1: 48-bit VA -> 48-bit IPA Sep 12 10:32:57 localhost kernel: [ 7.418581] arm-smmu arm-smmu.1.auto: #011Stage-2: 48-bit IPA -> 48-bit PA Sep 12 10:32:57 localhost kernel: [ 7.418644] arm-smmu arm-smmu.1.auto: #011preserved 0 boot mappings怎么回事,该怎么排查
最新发布
09-25
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值