/* * Copyright (c) 2006, Intel Corporation. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, * version 2, as published by the Free Software Foundation. * * This program is distributed in the hope 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, write to the Free Software Foundation, Inc., 59 Temple * Place - Suite 330, Boston, MA 02111-1307 USA. * * Copyright (C) Allen Kay * Copyright (C) Xiaohui Xin */ #include #include #include #include #include static void hvm_dirq_assist(unsigned long _d); static int pt_irq_need_timer(uint32_t flags) { return !(flags & (HVM_IRQ_DPCI_GUEST_MSI | HVM_IRQ_DPCI_TRANSLATE)); } static void pt_irq_time_out(void *data) { struct hvm_mirq_dpci_mapping *irq_map = data; unsigned int guest_gsi, machine_gsi = 0; struct hvm_irq_dpci *dpci = NULL; struct dev_intx_gsi_link *digl; struct hvm_girq_dpci_mapping *girq; uint32_t device, intx; unsigned int nr_pirqs = irq_map->dom->nr_pirqs; DECLARE_BITMAP(machine_gsi_map, nr_pirqs); bitmap_zero(machine_gsi_map, nr_pirqs); spin_lock(&irq_map->dom->event_lock); dpci = domain_get_irq_dpci(irq_map->dom); ASSERT(dpci); list_for_each_entry ( digl, &irq_map->digl_list, list ) { guest_gsi = digl->gsi; list_for_each_entry ( girq, &dpci->girq[guest_gsi], list ) { machine_gsi = girq->machine_gsi; set_bit(machine_gsi, machine_gsi_map); } device = digl->device; intx = digl->intx; hvm_pci_intx_deassert(irq_map->dom, device, intx); } for ( machine_gsi = find_first_bit(machine_gsi_map, nr_pirqs); machine_gsi < nr_pirqs; machine_gsi = find_next_bit(machine_gsi_map, nr_pirqs, machine_gsi + 1) ) { clear_bit(machine_gsi, dpci->dirq_mask); dpci->mirq[machine_gsi].pending = 0; } spin_unlock(&irq_map->dom->event_lock); for ( machine_gsi = find_first_bit(machine_gsi_map, nr_pirqs); machine_gsi < nr_pirqs; machine_gsi = find_next_bit(machine_gsi_map, nr_pirqs, machine_gsi + 1) ) { pirq_guest_eoi(irq_map->dom, machine_gsi); } } void free_hvm_irq_dpci(struct hvm_irq_dpci *dpci) { xfree(dpci->mirq); xfree(dpci->dirq_mask); xfree(dpci->mapping); xfree(dpci->hvm_timer); xfree(dpci); } int pt_irq_create_bind_vtd( struct domain *d, xen_domctl_bind_pt_irq_t *pt_irq_bind) { struct hvm_irq_dpci *hvm_irq_dpci = NULL; uint32_t machine_gsi, guest_gsi; uint32_t device, intx, link; struct dev_intx_gsi_link *digl; struct hvm_girq_dpci_mapping *girq; int rc, pirq = pt_irq_bind->machine_irq; if ( pirq < 0 || pirq >= d->nr_pirqs ) return -EINVAL; spin_lock(&d->event_lock); hvm_irq_dpci = domain_get_irq_dpci(d); if ( hvm_irq_dpci == NULL ) { hvm_irq_dpci = xmalloc(struct hvm_irq_dpci); if ( hvm_irq_dpci == NULL ) { spin_unlock(&d->event_lock); return -ENOMEM; } memset(hvm_irq_dpci, 0, sizeof(*hvm_irq_dpci)); tasklet_init(&hvm_irq_dpci->dirq_tasklet, hvm_dirq_assist, (unsigned long)d); hvm_irq_dpci->mirq = xmalloc_array(struct hvm_mirq_dpci_mapping, d->nr_pirqs); hvm_irq_dpci->dirq_mask = xmalloc_array(unsigned long, BITS_TO_LONGS(d->nr_pirqs)); hvm_irq_dpci->mapping = xmalloc_array(unsigned long, BITS_TO_LONGS(d->nr_pirqs)); hvm_irq_dpci->hvm_timer = xmalloc_array(struct timer, nr_irqs); if ( !hvm_irq_dpci->mirq || !hvm_irq_dpci->dirq_mask || !hvm_irq_dpci->mapping || !hvm_irq_dpci->hvm_timer) { spin_unlock(&d->event_lock); free_hvm_irq_dpci(hvm_irq_dpci); return -ENOMEM; } memset(hvm_irq_dpci->mirq, 0, d->nr_pirqs * sizeof(*hvm_irq_dpci->mirq)); bitmap_zero(hvm_irq_dpci->dirq_mask, d->nr_pirqs); bitmap_zero(hvm_irq_dpci->mapping, d->nr_pirqs); memset(hvm_irq_dpci->hvm_timer, 0, nr_irqs * sizeof(*hvm_irq_dpci->hvm_timer)); for ( int i = 0; i < d->nr_pirqs; i++ ) INIT_LIST_HEAD(&hvm_irq_dpci->mirq[i].digl_list); for ( int i = 0; i < NR_HVM_IRQS; i++ ) INIT_LIST_HEAD(&hvm_irq_dpci->girq[i]); if ( domain_set_irq_dpci(d, hvm_irq_dpci) == 0 ) { spin_unlock(&d->event_lock); free_hvm_irq_dpci(hvm_irq_dpci); return -EINVAL; } } if ( pt_irq_bind->irq_type == PT_IRQ_TYPE_MSI ) { if ( !test_and_set_bit(pirq, hvm_irq_dpci->mapping)) { hvm_irq_dpci->mirq[pirq].flags = HVM_IRQ_DPCI_MACH_MSI | HVM_IRQ_DPCI_GUEST_MSI; hvm_irq_dpci->mirq[pirq].gmsi.gvec = pt_irq_bind->u.msi.gvec; hvm_irq_dpci->mirq[pirq].gmsi.gflags = pt_irq_bind->u.msi.gflags; /* bind after
/**CFile****************************************************************

  FileName    [utilSignal.c]

  SystemName  [ABC: Logic synthesis and verification system.]

  PackageName []

  Synopsis    []

  Author      [Baruch Sterin]
  
  Affiliation [UC Berkeley]

  Date        [Ver. 1.0. Started - February 1, 2011.]

  Revision    [$Id: utilSignal.c,v 1.00 2011/02/01 00:00:00 alanmi Exp $]

***********************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "abc_global.h"
#include "utilSignal.h"

#ifdef _MSC_VER
#define unlink _unlink
#else
#include <unistd.h>
#endif

ABC_NAMESPACE_IMPL_START

////////////////////////////////////////////////////////////////////////
///                        DECLARATIONS                              ///
////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////
///                     FUNCTION DEFINITIONS                         ///
////////////////////////////////////////////////////////////////////////

int Util_SignalSystem(const char* cmd)
{
    return system(cmd);
}

int tmpFile(const char* prefix, const char* suffix, char** out_name);

int Util_SignalTmpFile(const char* prefix, const char* suffix, char** out_name)
{
    return tmpFile(prefix, suffix, out_name);
}

void Util_SignalTmpFileRemove(const char* fname, int fLeave)
{
    if (! fLeave)
    {
        unlink(fname);
    }
}

ABC_NAMESPACE_IMPL_END

////////////////////////////////////////////////////////////////////////
///                       END OF FILE                                ///
////////////////////////////////////////////////////////////////////////
translated MSI to INTx interrupt, eoi as early as possible */ __msi_pirq_eoi(d, pirq); } #endif } /* * Set a timer to see if the guest can finish the interrupt or not. For * example, the guest OS may unmask the PIC during boot, before the * guest driver is loaded. hvm_pci_intx_assert() may succeed, but the * guest will never deal with the irq, then the physical interrupt line * will never be deasserted. */ if ( pt_irq_need_timer(hvm_irq_dpci->mirq[pirq].flags) ) set_timer(&hvm_irq_dpci->hvm_timer[domain_pirq_to_irq(d, pirq)], NOW() + PT_IRQ_TIME_OUT); spin_unlock(&d->event_lock); } } static void __hvm_dpci_eoi(struct domain *d, struct hvm_irq_dpci *hvm_irq_dpci, struct hvm_girq_dpci_mapping *girq, union vioapic_redir_entry *ent) { uint32_t device, intx, machine_gsi; device = girq->device; intx = girq->intx; hvm_pci_intx_deassert(d, device, intx); machine_gsi = girq->machine_gsi; /* * No need to get vector lock for timer * since interrupt is still not EOIed */ if ( --hvm_irq_dpci->mirq[machine_gsi].pending || ( ent && ent->fields.mask ) || ! pt_irq_need_timer(hvm_irq_dpci->mirq[machine_gsi].flags) ) return; stop_timer(&hvm_irq_dpci->hvm_timer[domain_pirq_to_irq(d, machine_gsi)]); pirq_guest_eoi(d, machine_gsi); } void hvm_dpci_eoi(struct domain *d, unsigned int guest_gsi, union vioapic_redir_entry *ent) { struct hvm_irq_dpci *hvm_irq_dpci; struct hvm_girq_dpci_mapping *girq; if ( !iommu_enabled ) return; if ( guest_gsi < NR_ISAIRQS ) { hvm_dpci_isairq_eoi(d, guest_gsi); return; } spin_lock(&d->event_lock); hvm_irq_dpci = domain_get_irq_dpci(d); if ( !hvm_irq_dpci ) goto unlock; list_for_each_entry ( girq, &hvm_irq_dpci->girq[guest_gsi], list ) __hvm_dpci_eoi(d, hvm_irq_dpci, girq, ent); unlock: spin_unlock(&d->event_lock); }