[PATCH v11 06/10] iommu/vt-d: datatypes and functions used for kdump
Baoquan He
bhe at redhat.com
Wed May 13 01:56:09 PDT 2015
On 05/11/15 at 05:52pm, Li, Zhen-Hua wrote:
> Populate it with support functions to copy iommu translation tables from
> from the panicked kernel into the kdump kernel in the event of a crash.
>
> Functions:
> Use old root entry table, and load the old data to root_entry as cache.
> Malloc new context table and copy old context table to the new one.
>
> Bill Sumner:
> Original version, the creation of the data types and functions.
>
> Li, Zhenhua:
> Create new function iommu_check_pre_te_status() to check status.
> Update the caller of context_get_* and context_put*, use context_*
> and context_set_* for replacement.
> Update the name of the function that loads root entry table.
> Use new function to copy old context entry tables and page tables.
> Use "unsigned long" for physical address.
> Remove the functions to copy page table in Bill's version.
> Remove usage of dve and ppap in Bill's version.
>
> Signed-off-by: Bill Sumner <billsumnerlinux at gmail.com>
> Signed-off-by: Li, Zhen-Hua <zhen-hual at hp.com>
> ---
> drivers/iommu/intel-iommu.c | 121 ++++++++++++++++++++++++++++++++++++++++++++
> include/linux/intel-iommu.h | 3 ++
> 2 files changed, 124 insertions(+)
>
> diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c
> index 3a5d446..28c3c64 100644
> --- a/drivers/iommu/intel-iommu.c
> +++ b/drivers/iommu/intel-iommu.c
> @@ -386,6 +386,18 @@ struct iommu_remapped_entry {
> static LIST_HEAD(__iommu_remapped_mem);
> static DEFINE_MUTEX(__iommu_mem_list_lock);
>
> +/* ========================================================================
> + * Copy iommu translation tables from old kernel into new kernel.
> + * Entry to this set of functions is: intel_iommu_load_translation_tables()
> + * ------------------------------------------------------------------------
> + */
> +
> +static int copy_root_entry_table(struct intel_iommu *iommu);
> +
> +static int intel_iommu_load_translation_tables(struct intel_iommu *iommu);
> +
> +static void iommu_check_pre_te_status(struct intel_iommu *iommu);
> +
> /*
> * This domain is a statically identity mapping domain.
> * 1. This domain creats a static 1:1 mapping to all usable memory.
> @@ -4987,3 +4999,112 @@ static void __iommu_update_old_root_entry(struct intel_iommu *iommu, int index)
> __iommu_flush_cache(iommu, to + start, size);
> }
>
> +/*
> + * Load root entry tables from old kernel.
> + */
> +static int copy_root_entry_table(struct intel_iommu *iommu)
> +{
> + u32 bus; /* Index: root-entry-table */
> + struct root_entry *re; /* Virt(iterator: new table) */
> + unsigned long context_old_phys; /* Phys(context table entry) */
> + struct context_entry *context_new_virt; /* Virt(new context_entry) */
> +
> + /*
> + * A new root entry table has been allocated ,
> + * we need copy re from old kernel to the new allocated one.
> + */
> +
> + if (!iommu->root_entry_old_phys)
> + return -ENOMEM;
> +
> + for (bus = 0, re = iommu->root_entry; bus < 256; bus += 1, re += 1) {
> + if (!root_present(re))
> + continue;
> +
> + context_old_phys = get_context_phys_from_root(re);
> +
> + if (!context_old_phys)
> + continue;
> +
> + context_new_virt =
> + (struct context_entry *)alloc_pgtable_page(iommu->node);
> +
> + if (!context_new_virt)
> + return -ENOMEM;
> +
> + __iommu_load_from_oldmem(context_new_virt,
> + context_old_phys,
> + VTD_PAGE_SIZE);
> +
> + __iommu_flush_cache(iommu, context_new_virt, VTD_PAGE_SIZE);
> +
> + set_root_value(re, virt_to_phys(context_new_virt));
> + }
> +
> + return 0;
> +}
> +
> +/*
> + * Interface to the "load translation tables" set of functions
> + * from mainline code.
> + */
> +static int intel_iommu_load_translation_tables(struct intel_iommu *iommu)
> +{
> + unsigned long long q; /* quadword scratch */
> + int ret = 0; /* Integer return code */
> + unsigned long flags;
> +
> + q = dmar_readq(iommu->reg + DMAR_RTADDR_REG);
> + if (!q)
> + return -1;
> +
> + spin_lock_irqsave(&iommu->lock, flags);
> +
> + /* Load the root-entry table from the old kernel
> + * foreach context_entry_table in root_entry
> + * Copy each entry table from old kernel
> + */
> + if (!iommu->root_entry) {
> + iommu->root_entry =
> + (struct root_entry *)alloc_pgtable_page(iommu->node);
> + if (!iommu->root_entry) {
> + spin_unlock_irqrestore(&iommu->lock, flags);
> + return -ENOMEM;
> + }
> + }
> +
> + iommu->root_entry_old_phys = q & VTD_PAGE_MASK;
> + if (!iommu->root_entry_old_phys) {
> + pr_err("Could not read old root entry address.");
> + return -1;
> + }
> +
I didn't find where you call iounmap to free mapping of
iommu->root_entry_old_phys. Am I missing anything?
> + iommu->root_entry_old_virt = ioremap_cache(iommu->root_entry_old_phys,
> + VTD_PAGE_SIZE);
> + if (!iommu->root_entry_old_virt) {
> + pr_err("Could not map the old root entry.");
> + return -ENOMEM;
> + }
More information about the kexec
mailing list