struct ivrs_mappings *map,
uint16_t bdf));
-/* iommu tables in guest space */
-struct mmio_reg {
- uint32_t lo;
- uint32_t hi;
-};
-
-struct guest_dev_table {
- struct mmio_reg reg_base;
- uint32_t size;
-};
-
-struct guest_buffer {
- struct mmio_reg reg_base;
- struct mmio_reg reg_tail;
- struct mmio_reg reg_head;
- uint32_t size;
-};
-
-struct guest_iommu_msi {
- uint8_t vector;
- uint8_t dest;
- uint8_t dest_mode;
- uint8_t delivery_mode;
- uint8_t trig_mode;
-};
-
-/* virtual IOMMU structure */
-struct guest_iommu {
-
- struct domain *domain;
- spinlock_t lock;
- bool enabled;
-
- struct guest_dev_table dev_table;
- struct guest_buffer cmd_buffer;
- struct guest_buffer event_log;
- struct guest_buffer ppr_log;
-
- struct tasklet cmd_buffer_tasklet;
-
- uint64_t mmio_base; /* MMIO base address */
-
- /* MMIO regs */
- union amd_iommu_control reg_ctrl; /* MMIO offset 0018h */
- struct mmio_reg reg_status; /* MMIO offset 2020h */
- union amd_iommu_ext_features reg_ext_feature; /* MMIO offset 0030h */
-
- /* guest interrupt settings */
- struct guest_iommu_msi msi;
-};
-
extern bool iommuv2_enabled;
struct acpi_ivrs_hardware;
int __must_check cf_check amd_iommu_suspend(void);
void cf_check amd_iommu_crash_shutdown(void);
-/* guest iommu support */
-#ifdef CONFIG_HVM
-void guest_iommu_add_ppr_log(struct domain *d, uint32_t entry[]);
-#else
-static inline void guest_iommu_add_ppr_log(struct domain *d, uint32_t entry[]) {}
-#endif
-
static inline u32 get_field_from_reg_u32(u32 reg_value, u32 mask, u32 shift)
{
u32 field;
+++ /dev/null
-/*
- * Copyright (C) 2011 Advanced Micro Devices, Inc.
- * Author: Wei Wang <wei.wang2@amd.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <asm/p2m.h>
-
-#include "iommu.h"
-
-#define reg_to_u64(reg) (((uint64_t)reg.hi << 32) | reg.lo )
-
-static uint16_t get_guest_bdf(struct domain *d, uint16_t machine_bdf)
-{
- return machine_bdf;
-}
-
-static inline struct guest_iommu *domain_iommu(struct domain *d)
-{
- return dom_iommu(d)->arch.amd.g_iommu;
-}
-
-static unsigned long get_gfn_from_base_reg(uint64_t base_raw)
-{
- base_raw &= PADDR_MASK;
- ASSERT ( base_raw != 0 );
- return base_raw >> PAGE_SHIFT;
-}
-
-static void guest_iommu_deliver_msi(struct domain *d)
-{
- uint8_t vector, dest, dest_mode, delivery_mode, trig_mode;
- struct guest_iommu *iommu = domain_iommu(d);
-
- vector = iommu->msi.vector;
- dest = iommu->msi.dest;
- dest_mode = iommu->msi.dest_mode;
- delivery_mode = iommu->msi.delivery_mode;
- trig_mode = iommu->msi.trig_mode;
-
- vmsi_deliver(d, vector, dest, dest_mode, delivery_mode, trig_mode);
-}
-
-static unsigned long guest_iommu_get_table_mfn(struct domain *d,
- uint64_t base_raw,
- unsigned int pos)
-{
- unsigned long idx, gfn, mfn;
- p2m_type_t p2mt;
-
- gfn = get_gfn_from_base_reg(base_raw);
- idx = pos >> PAGE_SHIFT;
-
- mfn = mfn_x(get_gfn(d, gfn + idx, &p2mt));
- put_gfn(d, gfn);
-
- return mfn;
-}
-
-void guest_iommu_add_ppr_log(struct domain *d, u32 entry[])
-{
- uint16_t gdev_id;
- unsigned long mfn, tail, head;
- ppr_entry_t *log;
- struct guest_iommu *iommu;
-
- if ( !is_hvm_domain(d) )
- return;
-
- iommu = domain_iommu(d);
- if ( !iommu )
- return;
-
- tail = iommu->ppr_log.reg_tail.lo;
- head = iommu->ppr_log.reg_head.lo;
-
- if ( tail >= iommu->ppr_log.size || head >= iommu->ppr_log.size )
- {
- AMD_IOMMU_DEBUG("Error: guest iommu ppr log overflows\n");
- iommu->enabled = 0;
- return;
- }
-
- mfn = guest_iommu_get_table_mfn(d, reg_to_u64(iommu->ppr_log.reg_base),
- tail);
- ASSERT(mfn_valid(_mfn(mfn)));
-
- log = map_domain_page(_mfn(mfn)) + (tail & ~PAGE_MASK);
-
- /* Convert physical device id back into virtual device id */
- gdev_id = get_guest_bdf(d, iommu_get_devid_from_cmd(entry[0]));
- iommu_set_devid_to_cmd(&entry[0], gdev_id);
-
- memcpy(log, entry, sizeof(ppr_entry_t));
-
- /* Now shift ppr log tail pointer */
- tail += sizeof(ppr_entry_t);
- if ( tail >= iommu->ppr_log.size )
- {
- tail = 0;
- iommu->reg_status.lo |= IOMMU_STATUS_PPR_LOG_OVERFLOW;
- }
-
- iommu->ppr_log.reg_tail.lo = tail;
- unmap_domain_page(log);
-
- guest_iommu_deliver_msi(d);
-}