aboutsummaryrefslogtreecommitdiffstats
path: root/package/lua
Commit message (Expand)AuthorAgeFilesLines
* lua: switch to double precision for floatsJo-Philipp Wich2010-10-073-1/+23
* lua: drop refcounting patch in preparation for 10.03, it has unresolved issue...Jo-Philipp Wich2010-03-302-1129/+1
* package/lua: refresh patchesGabor Juhos2010-03-268-364/+256
* lua: add the 100-no_readline.patch to host buildJo-Philipp Wich2009-10-281-0/+49
* lua: the variable expansion to detect the host os does not work with GNU Make...Jo-Philipp Wich2009-10-281-4/+9
* lua: fix a typoFelix Fietkau2009-10-271-1/+1
* lua: re-enable host builds with some more fixesFelix Fietkau2009-10-277-722/+27
* lua: fix regressions in operator overloading caused by the refcounting patch,...Felix Fietkau2009-10-261-71/+3
* lua: use float instead of double, reduces the gc data structure size by 4 byt...Felix Fietkau2009-10-262-2/+2
* lua: fix various bugs in the refcounting implementation. seems to fix luci an...Felix Fietkau2009-10-261-72/+176
* lua: get rid of bitlib and md5lib from the core, they are no longer necessaryFelix Fietkau2009-10-242-670/+0
* lua: add reference counting for strings - this will need A LOT of testing, bu...Felix Fietkau2009-10-243-305/+1112
* lua: introduce soft memory limits that trigger a gc run but do not result in ...Jo-Philipp Wich2009-07-262-11/+23
* package/lua: implement memory limits, scripts can use get_memory_limit() and ...Jo-Philipp Wich2009-07-093-17/+294
* lua: install lua.pc pkgconfig file as well (closes: #5132)Nicolas Thill2009-05-141-2/+4
* lua: embed md5libJo-Philipp Wich2009-04-271-0/+484
* change occurences of LUA to Lua (from http://www.lua.org/about.html: Please d...Nicolas Thill2009-04-251-7/+7
* lua: revert r15108 & r15109Jo-Philipp Wich2009-04-193-160/+5
* get rid of $Id$ - it has never helped us and it has broken too many patches ;)Felix Fietkau2009-04-171-1/+0
* lua: add zlib build dependency, fix inaccuracy in gzip loaderJo-Philipp Wich2009-04-053-9/+13
* lua: add support for loading gzip compressed source files, bump package revisionJo-Philipp Wich2009-04-044-4/+272
* move host build in packages into a separate namespace: package/<name>/host/<t...Felix Fietkau2009-03-171-0/+2
* add back the old host patches for lua to improve portabilityFelix Fietkau2009-02-228-0/+4520
* merge host build of lua from tools/ into package/lua/MakefileFelix Fietkau2009-02-221-1/+17
* fix lua compile with eglibc selected and utmp support disabledFelix Fietkau2009-01-312-0/+32
* lua changes: - fix shared lib generation - don't ship liblua.so dev lib in li...Nicolas Thill2008-11-112-10/+6
* Embed luaposix and bitlib into Lua core librarySteven Barth2008-09-253-1/+1645
* Updated Lua to 5.1.4Steven Barth2008-08-244-201/+203
* lua: remove an unnecessary check and replace switch (GET_OPCODE(i)) as well (...Felix Fietkau2008-08-241-20/+20
* improve lua opcode dispatch performance by using computed goto instead of swi...Felix Fietkau2008-08-241-0/+363
* use $(FPIC) in a few places where it mattersFelix Fietkau2008-08-061-10/+2
* x86_64 also needs -fPIC to create lua shared librariesFlorian Fainelli2008-07-301-0/+3
* lua: Remove -fPIC for non-powerpc platformsSteven Barth2008-07-291-1/+6
* lua: Fixed some cross-platform issues for PPC (and probably other architectures)Steven Barth2008-06-292-2/+15
* fix liblua symlink installationFelix Fietkau2008-05-232-18/+25
* Added missing header reference to InstallDev targetSteven Barth2008-05-221-0/+1
* fix lua compile issues on ixp4xx (EABI) by linking libgcc into libluaFelix Fietkau2008-05-221-23/+30
* add updated lua patchset from Steven Barth (cyrus) as explained in http://lis...Felix Fietkau2008-05-225-100/+4026
* fix lua compile configuration errorFelix Fietkau2008-05-041-0/+2
* fix lua cflagsFelix Fietkau2008-04-281-1/+1
* remove lua's dependency on libreadline and libncursesFelix Fietkau2008-04-132-1/+54
* move lua from packages/ to trunk in anticipation of upcoming stuff ;)Felix Fietkau2008-04-132-0/+289
e */ .highlight .sh { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Heredoc */ .highlight .si { color: #3333bb; background-color: #fff0f0 } /* Literal.String.Interpol */ .highlight .sx { color: #22bb22; background-color: #f0fff0 } /* Literal.String.Other */ .highlight .sr { color: #008800; background-color: #fff0ff } /* Literal.String.Regex */ .highlight .s1 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Single */ .highlight .ss { color: #aa6600; background-color: #fff0f0 } /* Literal.String.Symbol */ .highlight .bp { color: #003388 } /* Name.Builtin.Pseudo */ .highlight .fm { color: #0066bb; font-weight: bold } /* Name.Function.Magic */ .highlight .vc { color: #336699 } /* Name.Variable.Class */ .highlight .vg { color: #dd7700 } /* Name.Variable.Global */ .highlight .vi { color: #3333bb } /* Name.Variable.Instance */ .highlight .vm { color: #336699 } /* Name.Variable.Magic */ .highlight .il { color: #0000DD; font-weight: bold } /* Literal.Number.Integer.Long */
#include <xen/config.h>
#include <xen/init.h>
#include <xen/lib.h>
#include <xen/types.h>
#include <xen/sched.h>
#include <xen/irq.h>
#include <xen/event.h>
#include <xen/guest_access.h>
#include <xen/iocap.h>
#include <asm/current.h>
#include <asm/msi.h>
#include <asm/hypercall.h>
#include <public/xen.h>
#include <public/physdev.h>
#include <xsm/xsm.h>

#ifndef COMPAT
typedef long ret_t;
#endif

int
ioapic_guest_read(
    unsigned long physbase, unsigned int reg, u32 *pval);
int
ioapic_guest_write(
    unsigned long physbase, unsigned int reg, u32 pval);

static int physdev_map_pirq(struct physdev_map_pirq *map)
{
    struct domain *d;
    int vector, pirq, ret = 0;
    struct msi_info _msi;
    void *map_data = NULL;

    if ( !IS_PRIV(current->domain) )
        return -EPERM;

    if ( !map )
        return -EINVAL;

    if ( map->domid == DOMID_SELF )
        d = rcu_lock_domain(current->domain);
    else
        d = rcu_lock_domain_by_id(map->domid);

    if ( d == NULL )
    {
        ret = -ESRCH;
        goto free_domain;
    }

    /* Verify or get vector. */
    switch ( map->type )
    {
        case MAP_PIRQ_TYPE_GSI:
            if ( map->index < 0 || map->index >= NR_IRQS )
            {
                dprintk(XENLOG_G_ERR, "dom%d: map invalid irq %d\n",
                        d->domain_id, map->index);
                ret = -EINVAL;
                goto free_domain;
            }
            vector = IO_APIC_VECTOR(map->index);
            if ( !vector )
            {
                dprintk(XENLOG_G_ERR, "dom%d: map irq with no vector %d\n",
                        d->domain_id, vector);
                ret = -EINVAL;
                goto free_domain;
            }
            break;

        case MAP_PIRQ_TYPE_MSI:
            vector = map->index;
            if ( vector == -1 )
                vector = assign_irq_vector(AUTO_ASSIGN);

            if ( vector < 0 || vector >= NR_VECTORS )
            {
                dprintk(XENLOG_G_ERR, "dom%d: map irq with wrong vector %d\n",
                        d->domain_id, vector);
                ret = -EINVAL;
                goto free_domain;
            }

            _msi.bus = map->bus;
            _msi.devfn = map->devfn;
            _msi.entry_nr = map->entry_nr;
            _msi.table_base = map->table_base;
            _msi.vector = vector;
            map_data = &_msi;
            break;

        default:
            dprintk(XENLOG_G_ERR, "dom%d: wrong map_pirq type %x\n",
                    d->domain_id, map->type);
            ret = -EINVAL;
            goto free_domain;
    }

    /* Verify or get pirq. */
    spin_lock(&d->event_lock);
    if ( map->pirq < 0 )
    {
        if ( d->arch.vector_pirq[vector] )
        {
            dprintk(XENLOG_G_ERR, "dom%d: %d:%d already mapped to %d\n",
                    d->domain_id, map->index, map->pirq,
                    d->arch.vector_pirq[vector]);
            pirq = d->arch.vector_pirq[vector];
            if ( pirq < 0 )
            {
                ret = -EBUSY;
                goto done;
            }
        }
        else
        {
            pirq = get_free_pirq(d, map->type, map->index);
            if ( pirq < 0 )
            {
                dprintk(XENLOG_G_ERR, "dom%d: no free pirq\n", d->domain_id);
                ret = pirq;
                goto done;
            }
        }
    }
    else
    {
        if ( d->arch.vector_pirq[vector] &&
             d->arch.vector_pirq[vector] != map->pirq )
        {
            dprintk(XENLOG_G_ERR, "dom%d: vector %d conflicts with irq %d\n",
                    d->domain_id, map->index, map->pirq);
            ret = -EEXIST;
            goto done;
        }
        else
            pirq = map->pirq;
    }

    ret = map_domain_pirq(d, pirq, vector, map->type, map_data);
    if ( ret == 0 )
        map->pirq = pirq;

done:
    spin_unlock(&d->event_lock);
    if ( (ret != 0) && (map->type == MAP_PIRQ_TYPE_MSI) && (map->index == -1) )
        free_irq_vector(vector);
free_domain:
    rcu_unlock_domain(d);
    return ret;
}

static int physdev_unmap_pirq(struct physdev_unmap_pirq *unmap)
{
    struct domain *d;
    int ret;

    if ( !IS_PRIV(current->domain) )
        return -EPERM;

    if ( unmap->domid == DOMID_SELF )
        d = rcu_lock_domain(current->domain);
    else
        d = rcu_lock_domain_by_id(unmap->domid);

    if ( d == NULL )
        return -ESRCH;

    spin_lock(&d->event_lock);
    ret = unmap_domain_pirq(d, unmap->pirq);
    spin_unlock(&d->event_lock);

    rcu_unlock_domain(d);

    return ret;
}

ret_t do_physdev_op(int cmd, XEN_GUEST_HANDLE(void) arg)
{
    int irq;
    ret_t ret;
    struct vcpu *v = current;

    switch ( cmd )
    {
    case PHYSDEVOP_eoi: {
        struct physdev_eoi eoi;
        ret = -EFAULT;
        if ( copy_from_guest(&eoi, arg, 1) != 0 )
            break;
        ret = pirq_guest_eoi(v->domain, eoi.irq);
        break;
    }

    /* Legacy since 0x00030202. */
    case PHYSDEVOP_IRQ_UNMASK_NOTIFY: {
        ret = pirq_guest_unmask(v->domain);
        break;
    }

    case PHYSDEVOP_irq_status_query: {
        struct physdev_irq_status_query irq_status_query;
        ret = -EFAULT;
        if ( copy_from_guest(&irq_status_query, arg, 1) != 0 )
            break;
        irq = irq_status_query.irq;
        ret = -EINVAL;
        if ( (irq < 0) || (irq >= NR_IRQS) )
            break;
        irq_status_query.flags = 0;
        if ( pirq_acktype(v->domain, irq) != 0 )
            irq_status_query.flags |= XENIRQSTAT_needs_eoi;
        if ( pirq_shared(v->domain, irq) )
            irq_status_query.flags |= XENIRQSTAT_shared;
        ret = copy_to_guest(arg, &irq_status_query, 1) ? -EFAULT : 0;
        break;
    }

    case PHYSDEVOP_map_pirq: {
        struct physdev_map_pirq map;

        ret = -EFAULT;
        if ( copy_from_guest(&map, arg, 1) != 0 )
            break;

        ret = physdev_map_pirq(&map);

        if ( copy_to_guest(arg, &map, 1) != 0 )
            ret = -EFAULT;
        break;
    }

    case PHYSDEVOP_unmap_pirq: {
        struct physdev_unmap_pirq unmap;

        ret = -EFAULT;
        if ( copy_from_guest(&unmap, arg, 1) != 0 )
            break;

        ret = physdev_unmap_pirq(&unmap);
        break;
    }

    case PHYSDEVOP_apic_read: {
        struct physdev_apic apic;
        ret = -EFAULT;
        if ( copy_from_guest(&apic, arg, 1) != 0 )
            break;
        ret = -EPERM;
        if ( !IS_PRIV(v->domain) )
            break;
        ret = xsm_apic(v->domain, cmd);
        if ( ret )
            break;
        ret = ioapic_guest_read(apic.apic_physbase, apic.reg, &apic.value);
        if ( copy_to_guest(arg, &apic, 1) != 0 )
            ret = -EFAULT;
        break;
    }

    case PHYSDEVOP_apic_write: {
        struct physdev_apic apic;
        ret = -EFAULT;
        if ( copy_from_guest(&apic, arg, 1) != 0 )
            break;
        ret = -EPERM;
        if ( !IS_PRIV(v->domain) )
            break;
        ret = xsm_apic(v->domain, cmd);
        if ( ret )
            break;
        ret = ioapic_guest_write(apic.apic_physbase, apic.reg, apic.value);
        break;
    }

    case PHYSDEVOP_alloc_irq_vector: {
        struct physdev_irq irq_op;

        ret = -EFAULT;
        if ( copy_from_guest(&irq_op, arg, 1) != 0 )
            break;

        ret = -EPERM;
        if ( !IS_PRIV(v->domain) )
            break;

        ret = xsm_assign_vector(v->domain, irq_op.irq);
        if ( ret )
            break;

        irq = irq_op.irq;
        ret = -EINVAL;
        if ( (irq < 0) || (irq >= NR_IRQS) )
            break;

        irq_op.vector = assign_irq_vector(irq);

        spin_lock(&dom0->event_lock);
        ret = map_domain_pirq(dom0, irq_op.irq, irq_op.vector,
                              MAP_PIRQ_TYPE_GSI, NULL);
        spin_unlock(&dom0->event_lock);

        if ( copy_to_guest(arg, &irq_op, 1) != 0 )
            ret = -EFAULT;
        break;
    }

    case PHYSDEVOP_set_iopl: {
        struct physdev_set_iopl set_iopl;
        ret = -EFAULT;
        if ( copy_from_guest(&set_iopl, arg, 1) != 0 )
            break;
        ret = -EINVAL;
        if ( set_iopl.iopl > 3 )
            break;
        ret = 0;
        v->arch.iopl = set_iopl.iopl;
        break;
    }

    case PHYSDEVOP_set_iobitmap: {
        struct physdev_set_iobitmap set_iobitmap;
        ret = -EFAULT;
        if ( copy_from_guest(&set_iobitmap, arg, 1) != 0 )
            break;
        ret = -EINVAL;
        if ( !guest_handle_okay(set_iobitmap.bitmap, IOBMP_BYTES) ||
             (set_iobitmap.nr_ports > 65536) )
            break;
        ret = 0;
#ifndef COMPAT
        v->arch.iobmp       = set_iobitmap.bitmap;
#else
        guest_from_compat_handle(v->arch.iobmp, set_iobitmap.bitmap);
#endif
        v->arch.iobmp_limit = set_iobitmap.nr_ports;
        break;
    }

    case PHYSDEVOP_manage_pci_add: {
        struct physdev_manage_pci manage_pci;
        ret = -EPERM;
        if ( !IS_PRIV(v->domain) )
            break;
        ret = -EFAULT;
        if ( copy_from_guest(&manage_pci, arg, 1) != 0 )
            break;

        ret = pci_add_device(manage_pci.bus, manage_pci.devfn);
        break;
    }

    case PHYSDEVOP_manage_pci_remove: {
        struct physdev_manage_pci manage_pci;
        ret = -EPERM;
        if ( !IS_PRIV(v->domain) )
            break;
        ret = -EFAULT;
        if ( copy_from_guest(&manage_pci, arg, 1) != 0 )
            break;

        ret = pci_remove_device(manage_pci.bus, manage_pci.devfn);
        break;
    }

    default:
        ret = -ENOSYS;
        break;
    }

    return ret;
}

/*
 * Local variables:
 * mode: C
 * c-set-style: "BSD"
 * c-basic-offset: 4
 * tab-width: 4
 * indent-tabs-mode: nil
 * End:
 */