[coreboot] Resource Allocation discussion

Myles Watson mylesgw at gmail.com
Wed Dec 3 19:43:47 CET 2008


On Wed, Dec 3, 2008 at 7:46 AM, Myles Watson <mylesgw at gmail.com> wrote:

>
>
> > -----Original Message-----
> > From: Marc Jones [mailto:marcj303 at gmail.com]
> > Sent: Tuesday, December 02, 2008 7:52 PM
> > To: Myles Watson
> > Cc: ron minnich; Rudolf Marek; Coreboot
> > Subject: Re: [coreboot] Resource Allocation discussion
> >
> > On Tue, Dec 2, 2008 at 3:23 PM, Myles Watson <mylesgw at gmail.com> wrote:
> > >
> > >
> > >> -----Original Message-----
> > >> From: ron minnich [mailto:rminnich at gmail.com]
> > >> Sent: Tuesday, December 02, 2008 2:51 PM
> > >> To: Myles Watson
> > >> Cc: Marc Jones; Rudolf Marek; Coreboot
> > >> Subject: Re: [coreboot] Resource Allocation discussion
> > >>
> > >> On Tue, Dec 2, 2008 at 11:33 AM, Myles Watson <mylesgw at gmail.com>
> > wrote:
> > >>
> > >> > Do we want to take fixed resources into account in the allocator?
> > >>
> > >> I would think so.
> > >
> > > I would too, but v2 didn't and did pretty well.  I'm interested to see
> > an
> > > idea for the resource allocation algorithm that allocates from largest
> > to
> > > smallest resource, except when it's skipping fixed resources.
> > >
> > > I think it's doable, but nothing like what we have.
> >
> > That surprises me. I thought it does, which is how/why you can get rid
> > of DEVICE_MEM_HIGH. Otherwise you would clobber the ROM and the APIC.
>
> You're right.  I think it's broken.  That's why right now I'm setting the
> base to 0xfc000000 manually.  Thanks for pointing it out.
>
> I'd assumed that resource_max took fixed resources into account, but it
> doesn't.  All resource_max does is align the resource based on its limit.
>
> So maybe we need to traverse the tree looking for fixed spaces, and
> constrain the domain's resource limit and base.  That wouldn't be too hard.
> What I was saying would be hard is interleaving fixed resources with
> movable
> resources.  In other words, if we put the VGA ROM between the two APIC
> allocations to save space.  I think that's too ugly.
>
> I'll add a traversal to the tree that doesn't ignore fixed resources.
>

A question before the code:
1. Can anyone enumerate all the fixed resources that should be included in
QEMU?
Currently I have:
- DRAM (first 640K and 0xc0000-TOP-768K) Is this necessary?
- I/O first 0x400 in southbridge
- VGA 0xa0000-0xc0000
- APIC at 0xfec00000 and 0xfee00000
- ROM at 0xfff80000

Side note: Only the lowest and highest fixed addresses matter in my code.
The others get ignored.  I think it's too much pain to try to interleave
them to use the space between 0xfee00000 and 0xfff80000, for example.

All right.  I've added code that traverses each domain looking for fixed
resources.  Here's the pseudo code:

For each domain:
    call avoid_fixed_resources(domain_dev)

avoid_fixed_resources(dev)
     initialize limits to maximum size
     initialize the limits to dev's resources limits
     call constrain_resources(dev, limits)
     update dev's resources

constrain_resources(dev, limits)
     for each child
         call constrain_resources(child, limits)
         for each fixed resource
            if limits contain resource
               update limits to exclude resource (largest space possible)

And here's the code.  It's not a diff because it's all new.
struct constraints {
    struct resource pref, io, mem;
};

static void constrain_resources(struct device *dev, struct constraints*
limits)
{
    struct device *child;
    struct resource *res;
    struct resource *lim;
    int i;

#ifdef CONFIG_PCI_64BIT_PREF_MEM
    #define MEM_MASK (IORESOURCE_PREFETCH | IORESOURCE_MEM)
#else
    #define MEM_MASK (IORESOURCE_MEM)
#endif
#define IO_MASK (IORESOURCE_IO)
#define PREF_TYPE (IORESOURCE_PREFETCH | IORESOURCE_MEM)
#define MEM_TYPE (IORESOURCE_MEM)
#define IO_TYPE (IORESOURCE_IO)

    /* Descend into every child and look for fixed resources. */
    for (child=dev->link[0].children; child; child = child->sibling) {
        constrain_resources(child, limits);
        for (i = 0; i<child->resources; i++) {
            res = &child->resource[i];
            if (!(res->flags & IORESOURCE_FIXED))
                continue;
            /* Choose larger space: above or below fixed resources. */

            /* PREFETCH */
            if ((res->flags & MEM_MASK) == PREF_TYPE) {
                lim = &limits->pref;
                /* Is it already outside the limits? */
                if ((res->base + res->size -1) < lim->base ||
                    res->base > lim->limit)
                    continue;
                /* Is the space above larger? */
                if ((lim->limit - (res->base + res->size -1)) >
                    (res->base - lim->base))
                    lim->base = res->base + res->size;
                else
                    lim->limit = res->base -1;
            }

            /* MEM */
            if ((res->flags & MEM_MASK) == MEM_TYPE) {
                lim = &limits->mem;
                /* Is it already outside the limits? */
                if ((res->base + res->size -1) < lim->base ||
                    res->base > lim->limit)
                    continue;
                /* Is the space above larger? */
                if ((lim->limit - (res->base + res->size -1)) >
                    (res->base - lim->base))
                    lim->base = res->base + res->size;
                else
                    lim->limit = res->base -1;
            }

            /* I/O */
            if ((res->flags & IO_MASK) == IO_TYPE) {
                lim = &limits->io;
                /* Is it already outside the limits? */
                if ((res->base + res->size -1) < lim->base ||
                    res->base > lim->limit)
                    continue;
                /* Is the space above larger? */
                if ((lim->limit - (res->base + res->size -1)) >
                    (res->base - lim->base))
                    lim->base = res->base + res->size;
                else
                    lim->limit = res->base -1;
            }
        }
    }
}

static void avoid_fixed_resources(struct device *dev)
{
    struct constraints limits;
    struct resource *res;
    int i;

    /* Initialize constraints to maximum size. */

    limits.pref.base = 0;
    limits.pref.limit = 0xfffffffffffffffULL;
    limits.io.base = 0;
    limits.io.limit = 0xfffffffffffffffULL;
    limits.mem.base = 0;
    limits.mem.limit = 0xfffffffffffffffULL;

    /* Initialize the limits from the device's resources. */
    for (i = 0; i<dev->resources; i++) {
        res = &dev->resource[i];

        /* PREFETCH */
        if ((res->flags & MEM_MASK) == PREF_TYPE &&
            res->limit < limits.pref.limit )
            limits.pref.limit = res->limit;
        /* MEM */
        if ((res->flags & MEM_MASK) == MEM_TYPE &&
            res->limit < limits.mem.limit )
            limits.mem.limit = res->limit;
        /* I/O */
        if ((res->flags & IO_MASK) == IO_TYPE &&
            res->limit < limits.io.limit )
            limits.io.limit = res->limit;
    }

    constrain_resources(dev, &limits);

    for (i = 0; i<dev->resources; i++) {
        res = &dev->resource[i];
        /* Update the device's resources with new limits. */

        /* PREFETCH */
        if ((res->flags & MEM_MASK) == PREF_TYPE) {
            /* Is the resource outside the limits? */
            if ( limits.pref.base > res->base )
                res->base = limits.pref.base;
            if ( res->limit > limits.pref.limit )
                res->limit = limits.pref.limit;
        }

        /* MEM */
        if ((res->flags & MEM_MASK) == MEM_TYPE) {
            /* Is the resource outside the limits? */
            if ( limits.mem.base > res->base )
                res->base = limits.mem.base;
            if ( res->limit > limits.mem.limit )
                res->limit = limits.mem.limit;
        }

        /* I/O */
        if ((res->flags & IO_MASK) == IO_TYPE) {
            /* Is the resource outside the limits? */
            if ( limits.io.base > res->base )
                res->base = limits.io.base;
            if ( res->limit > limits.io.limit )
                res->limit = limits.io.limit;
        }
    }
}

Thanks,
Myles
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://www.coreboot.org/pipermail/coreboot/attachments/20081203/689bee61/attachment.html>


More information about the coreboot mailing list