Commit a0efbf16 authored by Markus Armbruster's avatar Markus Armbruster Committed by Michael S. Tsirkin
Browse files

range: Eliminate direct Range member access



Users of struct Range mess liberally with its members, which makes
refactoring hard.  Create a set of methods, and convert all users to
call them instead of accessing members.  The methods have carefully
worded contracts, and use assertions to check them.

Signed-off-by: default avatarMarkus Armbruster <armbru@redhat.com>
Reviewed-by: default avatarEric Blake <eblake@redhat.com>
Reviewed-by: default avatarMichael S. Tsirkin <mst@redhat.com>
Reviewed-by: default avatarMichael S. Tsirkin <mst@redhat.com>
Signed-off-by: default avatarMichael S. Tsirkin <mst@redhat.com>
parent 58e19e6e
Loading
Loading
Loading
Loading
+19 −16
Original line number Diff line number Diff line
@@ -236,18 +236,20 @@ static void acpi_get_pci_holes(Range *hole, Range *hole64)
    pci_host = acpi_get_i386_pci_host();
    g_assert(pci_host);

    hole->begin = object_property_get_int(pci_host,
    range_set_bounds1(hole,
                      object_property_get_int(pci_host,
                                              PCI_HOST_PROP_PCI_HOLE_START,
                                          NULL);
    hole->end = object_property_get_int(pci_host,
                                              NULL),
                      object_property_get_int(pci_host,
                                              PCI_HOST_PROP_PCI_HOLE_END,
                                        NULL);
    hole64->begin = object_property_get_int(pci_host,
                                              NULL));
    range_set_bounds1(hole64,
                      object_property_get_int(pci_host,
                                              PCI_HOST_PROP_PCI_HOLE64_START,
                                            NULL);
    hole64->end = object_property_get_int(pci_host,
                                              NULL),
                      object_property_get_int(pci_host,
                                              PCI_HOST_PROP_PCI_HOLE64_END,
                                          NULL);
                                              NULL));
}

#define ACPI_PORT_SMI_CMD           0x00b2 /* TODO: this is APM_CNT_IOPORT */
@@ -2047,7 +2049,8 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,
                         0, 0x000A0000, 0x000BFFFF, 0, 0x00020000));

    crs_replace_with_free_ranges(mem_ranges,
                                 pci_hole->begin, pci_hole->end - 1);
                                 range_lob(pci_hole),
                                 range_upb(pci_hole));
    for (i = 0; i < mem_ranges->len; i++) {
        entry = g_ptr_array_index(mem_ranges, i);
        aml_append(crs,
@@ -2057,12 +2060,12 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,
                             0, entry->limit - entry->base + 1));
    }

    if (pci_hole64->begin) {
    if (!range_is_empty(pci_hole64)) {
        aml_append(crs,
            aml_qword_memory(AML_POS_DECODE, AML_MIN_FIXED, AML_MAX_FIXED,
                             AML_CACHEABLE, AML_READ_WRITE,
                             0, pci_hole64->begin, pci_hole64->end - 1, 0,
                             pci_hole64->end - pci_hole64->begin));
                             0, range_lob(pci_hole64), range_upb(pci_hole64), 0,
                             range_upb(pci_hole64) + 1 - range_lob(pci_hole64)));
    }

    if (misc->tpm_version != TPM_VERSION_UNSPEC) {
+18 −8
Original line number Diff line number Diff line
@@ -221,8 +221,12 @@ static void i440fx_pcihost_get_pci_hole_start(Object *obj, Visitor *v,
                                              Error **errp)
{
    I440FXState *s = I440FX_PCI_HOST_BRIDGE(obj);
    uint32_t value = s->pci_hole.begin;
    uint64_t val64;
    uint32_t value;

    val64 = range_is_empty(&s->pci_hole) ? 0 : range_lob(&s->pci_hole);
    value = val64;
    assert(value == val64);
    visit_type_uint32(v, name, &value, errp);
}

@@ -231,8 +235,12 @@ static void i440fx_pcihost_get_pci_hole_end(Object *obj, Visitor *v,
                                            Error **errp)
{
    I440FXState *s = I440FX_PCI_HOST_BRIDGE(obj);
    uint32_t value = s->pci_hole.end;
    uint64_t val64;
    uint32_t value;

    val64 = range_is_empty(&s->pci_hole) ? 0 : range_upb(&s->pci_hole) + 1;
    value = val64;
    assert(value == val64);
    visit_type_uint32(v, name, &value, errp);
}

@@ -242,10 +250,11 @@ static void i440fx_pcihost_get_pci_hole64_start(Object *obj, Visitor *v,
{
    PCIHostState *h = PCI_HOST_BRIDGE(obj);
    Range w64;
    uint64_t value;

    pci_bus_get_w64_range(h->bus, &w64);

    visit_type_uint64(v, name, &w64.begin, errp);
    value = range_is_empty(&w64) ? 0 : range_lob(&w64);
    visit_type_uint64(v, name, &value, errp);
}

static void i440fx_pcihost_get_pci_hole64_end(Object *obj, Visitor *v,
@@ -254,10 +263,11 @@ static void i440fx_pcihost_get_pci_hole64_end(Object *obj, Visitor *v,
{
    PCIHostState *h = PCI_HOST_BRIDGE(obj);
    Range w64;
    uint64_t value;

    pci_bus_get_w64_range(h->bus, &w64);

    visit_type_uint64(v, name, &w64.end, errp);
    value = range_is_empty(&w64) ? 0 : range_upb(&w64) + 1;
    visit_type_uint64(v, name, &value, errp);
}

static void i440fx_pcihost_initfn(Object *obj)
@@ -344,8 +354,8 @@ PCIBus *i440fx_init(const char *host_type, const char *pci_type,
    f->ram_memory = ram_memory;

    i440fx = I440FX_PCI_HOST_BRIDGE(dev);
    i440fx->pci_hole.begin = below_4g_mem_size;
    i440fx->pci_hole.end = IO_APIC_DEFAULT_ADDRESS;
    range_set_bounds(&i440fx->pci_hole, below_4g_mem_size,
                     IO_APIC_DEFAULT_ADDRESS - 1);

    /* setup pci memory mapping */
    pc_pci_as_mapping_init(OBJECT(f), f->system_memory,
+27 −14
Original line number Diff line number Diff line
@@ -74,8 +74,13 @@ static void q35_host_get_pci_hole_start(Object *obj, Visitor *v,
                                        Error **errp)
{
    Q35PCIHost *s = Q35_HOST_DEVICE(obj);
    uint32_t value = s->mch.pci_hole.begin;
    uint64_t val64;
    uint32_t value;

    val64 = range_is_empty(&s->mch.pci_hole)
        ? 0 : range_lob(&s->mch.pci_hole);
    value = val64;
    assert(value == val64);
    visit_type_uint32(v, name, &value, errp);
}

@@ -84,8 +89,13 @@ static void q35_host_get_pci_hole_end(Object *obj, Visitor *v,
                                      Error **errp)
{
    Q35PCIHost *s = Q35_HOST_DEVICE(obj);
    uint32_t value = s->mch.pci_hole.end;
    uint64_t val64;
    uint32_t value;

    val64 = range_is_empty(&s->mch.pci_hole)
        ? 0 : range_upb(&s->mch.pci_hole) + 1;
    value = val64;
    assert(value == val64);
    visit_type_uint32(v, name, &value, errp);
}

@@ -95,10 +105,11 @@ static void q35_host_get_pci_hole64_start(Object *obj, Visitor *v,
{
    PCIHostState *h = PCI_HOST_BRIDGE(obj);
    Range w64;
    uint64_t value;

    pci_bus_get_w64_range(h->bus, &w64);

    visit_type_uint64(v, name, &w64.begin, errp);
    value = range_is_empty(&w64) ? 0 : range_lob(&w64);
    visit_type_uint64(v, name, &value, errp);
}

static void q35_host_get_pci_hole64_end(Object *obj, Visitor *v,
@@ -107,10 +118,11 @@ static void q35_host_get_pci_hole64_end(Object *obj, Visitor *v,
{
    PCIHostState *h = PCI_HOST_BRIDGE(obj);
    Range w64;
    uint64_t value;

    pci_bus_get_w64_range(h->bus, &w64);

    visit_type_uint64(v, name, &w64.end, errp);
    value = range_is_empty(&w64) ? 0 : range_upb(&w64) + 1;
    visit_type_uint64(v, name, &value, errp);
}

static void q35_host_get_mmcfg_size(Object *obj, Visitor *v, const char *name,
@@ -205,9 +217,9 @@ static void q35_host_initfn(Object *obj)
     * it's not a power of two, which means an MTRR
     * can't cover it exactly.
     */
    s->mch.pci_hole.begin = MCH_HOST_BRIDGE_PCIEXBAR_DEFAULT +
        MCH_HOST_BRIDGE_PCIEXBAR_MAX;
    s->mch.pci_hole.end = IO_APIC_DEFAULT_ADDRESS;
    range_set_bounds(&s->mch.pci_hole,
            MCH_HOST_BRIDGE_PCIEXBAR_DEFAULT + MCH_HOST_BRIDGE_PCIEXBAR_MAX,
            IO_APIC_DEFAULT_ADDRESS - 1);
}

static const TypeInfo q35_host_info = {
@@ -275,10 +287,7 @@ static void mch_update_pciexbar(MCHPCIState *mch)
        break;
    case MCH_HOST_BRIDGE_PCIEXBAR_LENGTH_RVD:
    default:
        enable = 0;
        length = 0;
        abort();
        break;
    }
    addr = pciexbar & addr_mask;
    pcie_host_mmcfg_update(pehb, enable, addr, length);
@@ -288,9 +297,13 @@ static void mch_update_pciexbar(MCHPCIState *mch)
     * which means an MTRR can't cover it exactly.
     */
    if (enable) {
        mch->pci_hole.begin = addr + length;
        range_set_bounds(&mch->pci_hole,
                         addr + length,
                         IO_APIC_DEFAULT_ADDRESS - 1);
    } else {
        mch->pci_hole.begin = MCH_HOST_BRIDGE_PCIEXBAR_DEFAULT;
        range_set_bounds(&mch->pci_hole,
                         MCH_HOST_BRIDGE_PCIEXBAR_DEFAULT,
                         IO_APIC_DEFAULT_ADDRESS - 1);
    }
}

+9 −8
Original line number Diff line number Diff line
@@ -2533,13 +2533,13 @@ static void pci_dev_get_w64(PCIBus *b, PCIDevice *dev, void *opaque)

        if (limit >= base) {
            Range pref_range;
            pref_range.begin = base;
            pref_range.end = limit + 1;
            range_set_bounds(&pref_range, base, limit);
            range_extend(range, &pref_range);
        }
    }
    for (i = 0; i < PCI_NUM_REGIONS; ++i) {
        PCIIORegion *r = &dev->io_regions[i];
        pcibus_t lob, upb;
        Range region_range;

        if (!r->size ||
@@ -2547,16 +2547,17 @@ static void pci_dev_get_w64(PCIBus *b, PCIDevice *dev, void *opaque)
            !(r->type & PCI_BASE_ADDRESS_MEM_TYPE_64)) {
            continue;
        }
        region_range.begin = pci_bar_address(dev, i, r->type, r->size);
        region_range.end = region_range.begin + r->size;

        if (region_range.begin == PCI_BAR_UNMAPPED) {
        lob = pci_bar_address(dev, i, r->type, r->size);
        upb = lob + r->size - 1;
        if (lob == PCI_BAR_UNMAPPED) {
            continue;
        }

        region_range.begin = MAX(region_range.begin, 0x1ULL << 32);
        lob = MAX(lob, 0x1ULL << 32);

        if (region_range.end - 1 >= region_range.begin) {
        if (upb >= lob) {
            range_set_bounds(&region_range, lob, upb);
            range_extend(range, &region_range);
        }
    }
@@ -2564,7 +2565,7 @@ static void pci_dev_get_w64(PCIBus *b, PCIDevice *dev, void *opaque)

void pci_bus_get_w64_range(PCIBus *bus, Range *range)
{
    range->begin = range->end = 0;
    range_make_empty(range);
    pci_for_each_device_under_bus(bus, pci_dev_get_w64, range);
}

+83 −2
Original line number Diff line number Diff line
@@ -36,12 +36,91 @@ struct Range {
    uint64_t end;   /* 1 + the last byte. 0 if range empty or ends at ~0x0LL. */
};

static inline void range_invariant(Range *range)
{
    assert((!range->begin && !range->end) /* empty */
           || range->begin <= range->end - 1); /* non-empty */
}

/* Compound literal encoding the empty range */
#define range_empty ((Range){ .begin = 0, .end = 0 })

/* Is @range empty? */
static inline bool range_is_empty(Range *range)
{
    range_invariant(range);
    return !range->begin && !range->end;
}

/* Does @range contain @val? */
static inline bool range_contains(Range *range, uint64_t val)
{
    return !range_is_empty(range)
        && val >= range->begin && val <= range->end - 1;
}

/* Initialize @range to the empty range */
static inline void range_make_empty(Range *range)
{
    *range = range_empty;
    assert(range_is_empty(range));
}

/*
 * Initialize @range to span the interval [@lob,@upb].
 * Both bounds are inclusive.
 * The interval must not be empty, i.e. @lob must be less than or
 * equal @upb.
 * The interval must not be [0,UINT64_MAX], because Range can't
 * represent that.
 */
static inline void range_set_bounds(Range *range, uint64_t lob, uint64_t upb)
{
    assert(lob <= upb);
    range->begin = lob;
    range->end = upb + 1;       /* may wrap to zero, that's okay */
    assert(!range_is_empty(range));
}

/*
 * Initialize @range to span the interval [@lob,@upb_plus1).
 * The lower bound is inclusive, the upper bound is exclusive.
 * Zero @upb_plus1 is special: if @lob is also zero, set @range to the
 * empty range.  Else, set @range to [@lob,UINT64_MAX].
 */
static inline void range_set_bounds1(Range *range,
                                     uint64_t lob, uint64_t upb_plus1)
{
    range->begin = lob;
    range->end = upb_plus1;
    range_invariant(range);
}

/* Return @range's lower bound.  @range must not be empty. */
static inline uint64_t range_lob(Range *range)
{
    assert(!range_is_empty(range));
    return range->begin;
}

/* Return @range's upper bound.  @range must not be empty. */
static inline uint64_t range_upb(Range *range)
{
    assert(!range_is_empty(range));
    return range->end - 1;
}

/*
 * Extend @range to the smallest interval that includes @extend_by, too.
 * This must not extend @range to cover the interval [0,UINT64_MAX],
 * because Range can't represent that.
 */
static inline void range_extend(Range *range, Range *extend_by)
{
    if (!extend_by->begin && !extend_by->end) {
    if (range_is_empty(extend_by)) {
        return;
    }
    if (!range->begin && !range->end) {
    if (range_is_empty(range)) {
        *range = *extend_by;
        return;
    }
@@ -52,6 +131,8 @@ static inline void range_extend(Range *range, Range *extend_by)
    if (range->end - 1 < extend_by->end - 1) {
        range->end = extend_by->end;
    }
    /* Must not extend to { .begin = 0, .end = 0 }: */
    assert(!range_is_empty(range));
}

/* Get last byte of a range from offset + length.
Loading