~ubuntu-branches/ubuntu/trusty/qemu/trusty

« back to all changes in this revision

Viewing changes to ioport.c

  • Committer: Package Import Robot
  • Author(s): Serge Hallyn
  • Date: 2013-10-22 22:47:07 UTC
  • mfrom: (1.8.3) (10.1.42 sid)
  • Revision ID: package-import@ubuntu.com-20131022224707-1lya34fw3k3f24tv
Tags: 1.6.0+dfsg-2ubuntu1
* Merge 1.6.0~rc0+dfsg-2exp from debian experimental.  Remaining changes:
  - debian/control
    * update maintainer
    * remove libiscsi, usb-redir, vde, vnc-jpeg, and libssh2-1-dev
      from build-deps
    * enable rbd
    * add qemu-system and qemu-common B/R to qemu-keymaps
    * add D:udev, R:qemu, R:qemu-common and B:qemu-common to
      qemu-system-common
    * qemu-system-arm, qemu-system-ppc, qemu-system-sparc:
      - add qemu-kvm to Provides
      - add qemu-common, qemu-kvm, kvm to B/R
      - remove openbios-sparc from qemu-system-sparc D
      - drop openbios-ppc and openhackware Depends to Suggests (for now)
    * qemu-system-x86:
      - add qemu-common to Breaks/Replaces.
      - add cpu-checker to Recommends.
    * qemu-user: add B/R:qemu-kvm
    * qemu-kvm:
      - add armhf armel powerpc sparc to Architecture
      - C/R/P: qemu-kvm-spice
    * add qemu-common package
    * drop qemu-slof which is not packaged in ubuntu
  - add qemu-system-common.links for tap ifup/down scripts and OVMF link.
  - qemu-system-x86.links:
    * remove pxe rom links which are in kvm-ipxe
    * add symlink for kvm.1 manpage
  - debian/rules
    * add kvm-spice symlink to qemu-kvm
    * call dh_installmodules for qemu-system-x86
    * update dh_installinit to install upstart script
    * run dh_installman (Closes: #709241) (cherrypicked from 1.5.0+dfsg-2)
  - Add qemu-utils.links for kvm-* symlinks.
  - Add qemu-system-x86.qemu-kvm.upstart and .default
  - Add qemu-system-x86.modprobe to set nesting=1
  - Add qemu-system-common.preinst to add kvm group
  - qemu-system-common.postinst: remove bad group acl if there, then have
    udev relabel /dev/kvm.
  - New linaro patches from qemu-linaro rebasing branch
  - Dropped patches:
    * xen-simplify-xen_enabled.patch
    * sparc-linux-user-fix-missing-symbols-in-.rel-.rela.plt-sections.patch
    * main_loop-do-not-set-nonblocking-if-xen_enabled.patch
    * xen_machine_pv-do-not-create-a-dummy-CPU-in-machine-.patch
    * virtio-rng-fix-crash
  - Kept patches:
    * expose_vms_qemu64cpu.patch - updated
    * linaro arm patches from qemu-linaro rebasing branch
  - New patches:
    * fix-pci-add: change CONFIG variable in ifdef to make sure that
      pci_add is defined.
* Add linaro patches
* Add experimental mach-virt patches for arm virtualization.
* qemu-system-common.install: add debian/tmp/usr/lib to install the
  qemu-bridge-helper

Show diffs side-by-side

added added

removed removed

Lines of Context:
28
28
#include "exec/ioport.h"
29
29
#include "trace.h"
30
30
#include "exec/memory.h"
31
 
 
32
 
/***********************************************************/
33
 
/* IO Port */
34
 
 
35
 
//#define DEBUG_UNUSED_IOPORT
 
31
#include "exec/address-spaces.h"
 
32
 
36
33
//#define DEBUG_IOPORT
37
34
 
38
 
#ifdef DEBUG_UNUSED_IOPORT
39
 
#  define LOG_UNUSED_IOPORT(fmt, ...) fprintf(stderr, fmt, ## __VA_ARGS__)
40
 
#else
41
 
#  define LOG_UNUSED_IOPORT(fmt, ...) do{ } while (0)
42
 
#endif
43
 
 
44
35
#ifdef DEBUG_IOPORT
45
36
#  define LOG_IOPORT(...) qemu_log_mask(CPU_LOG_IOPORT, ## __VA_ARGS__)
46
37
#else
47
38
#  define LOG_IOPORT(...) do { } while (0)
48
39
#endif
49
40
 
50
 
/* XXX: use a two level table to limit memory usage */
51
 
 
52
 
static void *ioport_opaque[MAX_IOPORTS];
53
 
static IOPortReadFunc *ioport_read_table[3][MAX_IOPORTS];
54
 
static IOPortWriteFunc *ioport_write_table[3][MAX_IOPORTS];
55
 
static IOPortDestructor *ioport_destructor_table[MAX_IOPORTS];
56
 
 
57
 
static IOPortReadFunc default_ioport_readb, default_ioport_readw, default_ioport_readl;
58
 
static IOPortWriteFunc default_ioport_writeb, default_ioport_writew, default_ioport_writel;
59
 
 
60
 
static uint32_t ioport_read(int index, uint32_t address)
61
 
{
62
 
    static IOPortReadFunc * const default_func[3] = {
63
 
        default_ioport_readb,
64
 
        default_ioport_readw,
65
 
        default_ioport_readl
66
 
    };
67
 
    IOPortReadFunc *func = ioport_read_table[index][address];
68
 
    if (!func)
69
 
        func = default_func[index];
70
 
    return func(ioport_opaque[address], address);
71
 
}
72
 
 
73
 
static void ioport_write(int index, uint32_t address, uint32_t data)
74
 
{
75
 
    static IOPortWriteFunc * const default_func[3] = {
76
 
        default_ioport_writeb,
77
 
        default_ioport_writew,
78
 
        default_ioport_writel
79
 
    };
80
 
    IOPortWriteFunc *func = ioport_write_table[index][address];
81
 
    if (!func)
82
 
        func = default_func[index];
83
 
    func(ioport_opaque[address], address, data);
84
 
}
85
 
 
86
 
static uint32_t default_ioport_readb(void *opaque, uint32_t address)
87
 
{
88
 
    LOG_UNUSED_IOPORT("unused inb: port=0x%04"PRIx32"\n", address);
89
 
    return 0xff;
90
 
}
91
 
 
92
 
static void default_ioport_writeb(void *opaque, uint32_t address, uint32_t data)
93
 
{
94
 
    LOG_UNUSED_IOPORT("unused outb: port=0x%04"PRIx32" data=0x%02"PRIx32"\n",
95
 
                      address, data);
96
 
}
97
 
 
98
 
/* default is to make two byte accesses */
99
 
static uint32_t default_ioport_readw(void *opaque, uint32_t address)
100
 
{
101
 
    uint32_t data;
102
 
    data = ioport_read(0, address);
103
 
    address = (address + 1) & IOPORTS_MASK;
104
 
    data |= ioport_read(0, address) << 8;
105
 
    return data;
106
 
}
107
 
 
108
 
static void default_ioport_writew(void *opaque, uint32_t address, uint32_t data)
109
 
{
110
 
    ioport_write(0, address, data & 0xff);
111
 
    address = (address + 1) & IOPORTS_MASK;
112
 
    ioport_write(0, address, (data >> 8) & 0xff);
113
 
}
114
 
 
115
 
static uint32_t default_ioport_readl(void *opaque, uint32_t address)
116
 
{
117
 
    LOG_UNUSED_IOPORT("unused inl: port=0x%04"PRIx32"\n", address);
118
 
    return 0xffffffff;
119
 
}
120
 
 
121
 
static void default_ioport_writel(void *opaque, uint32_t address, uint32_t data)
122
 
{
123
 
    LOG_UNUSED_IOPORT("unused outl: port=0x%04"PRIx32" data=0x%02"PRIx32"\n",
124
 
                      address, data);
125
 
}
126
 
 
127
 
static int ioport_bsize(int size, int *bsize)
128
 
{
129
 
    if (size == 1) {
130
 
        *bsize = 0;
131
 
    } else if (size == 2) {
132
 
        *bsize = 1;
133
 
    } else if (size == 4) {
134
 
        *bsize = 2;
135
 
    } else {
136
 
        return -1;
137
 
    }
138
 
    return 0;
139
 
}
140
 
 
141
 
/* size is the word size in byte */
142
 
int register_ioport_read(pio_addr_t start, int length, int size,
143
 
                         IOPortReadFunc *func, void *opaque)
144
 
{
145
 
    int i, bsize;
146
 
 
147
 
    if (ioport_bsize(size, &bsize)) {
148
 
        hw_error("register_ioport_read: invalid size");
149
 
        return -1;
150
 
    }
151
 
    for(i = start; i < start + length; ++i) {
152
 
        ioport_read_table[bsize][i] = func;
153
 
        if (ioport_opaque[i] != NULL && ioport_opaque[i] != opaque)
154
 
            hw_error("register_ioport_read: invalid opaque for address 0x%x",
155
 
                     i);
156
 
        ioport_opaque[i] = opaque;
157
 
    }
158
 
    return 0;
159
 
}
160
 
 
161
 
/* size is the word size in byte */
162
 
int register_ioport_write(pio_addr_t start, int length, int size,
163
 
                          IOPortWriteFunc *func, void *opaque)
164
 
{
165
 
    int i, bsize;
166
 
 
167
 
    if (ioport_bsize(size, &bsize)) {
168
 
        hw_error("register_ioport_write: invalid size");
169
 
        return -1;
170
 
    }
171
 
    for(i = start; i < start + length; ++i) {
172
 
        ioport_write_table[bsize][i] = func;
173
 
        if (ioport_opaque[i] != NULL && ioport_opaque[i] != opaque)
174
 
            hw_error("register_ioport_write: invalid opaque for address 0x%x",
175
 
                     i);
176
 
        ioport_opaque[i] = opaque;
177
 
    }
178
 
    return 0;
179
 
}
180
 
 
181
 
static uint32_t ioport_readb_thunk(void *opaque, uint32_t addr)
182
 
{
183
 
    IORange *ioport = opaque;
184
 
    uint64_t data;
185
 
 
186
 
    ioport->ops->read(ioport, addr - ioport->base, 1, &data);
187
 
    return data;
188
 
}
189
 
 
190
 
static uint32_t ioport_readw_thunk(void *opaque, uint32_t addr)
191
 
{
192
 
    IORange *ioport = opaque;
193
 
    uint64_t data;
194
 
 
195
 
    ioport->ops->read(ioport, addr - ioport->base, 2, &data);
196
 
    return data;
197
 
}
198
 
 
199
 
static uint32_t ioport_readl_thunk(void *opaque, uint32_t addr)
200
 
{
201
 
    IORange *ioport = opaque;
202
 
    uint64_t data;
203
 
 
204
 
    ioport->ops->read(ioport, addr - ioport->base, 4, &data);
205
 
    return data;
206
 
}
207
 
 
208
 
static void ioport_writeb_thunk(void *opaque, uint32_t addr, uint32_t data)
209
 
{
210
 
    IORange *ioport = opaque;
211
 
 
212
 
    ioport->ops->write(ioport, addr - ioport->base, 1, data);
213
 
}
214
 
 
215
 
static void ioport_writew_thunk(void *opaque, uint32_t addr, uint32_t data)
216
 
{
217
 
    IORange *ioport = opaque;
218
 
 
219
 
    ioport->ops->write(ioport, addr - ioport->base, 2, data);
220
 
}
221
 
 
222
 
static void ioport_writel_thunk(void *opaque, uint32_t addr, uint32_t data)
223
 
{
224
 
    IORange *ioport = opaque;
225
 
 
226
 
    ioport->ops->write(ioport, addr - ioport->base, 4, data);
227
 
}
228
 
 
229
 
static void iorange_destructor_thunk(void *opaque)
230
 
{
231
 
    IORange *iorange = opaque;
232
 
 
233
 
    if (iorange->ops->destructor) {
234
 
        iorange->ops->destructor(iorange);
235
 
    }
236
 
}
237
 
 
238
 
void ioport_register(IORange *ioport)
239
 
{
240
 
    register_ioport_read(ioport->base, ioport->len, 1,
241
 
                         ioport_readb_thunk, ioport);
242
 
    register_ioport_read(ioport->base, ioport->len, 2,
243
 
                         ioport_readw_thunk, ioport);
244
 
    register_ioport_read(ioport->base, ioport->len, 4,
245
 
                         ioport_readl_thunk, ioport);
246
 
    register_ioport_write(ioport->base, ioport->len, 1,
247
 
                          ioport_writeb_thunk, ioport);
248
 
    register_ioport_write(ioport->base, ioport->len, 2,
249
 
                          ioport_writew_thunk, ioport);
250
 
    register_ioport_write(ioport->base, ioport->len, 4,
251
 
                          ioport_writel_thunk, ioport);
252
 
    ioport_destructor_table[ioport->base] = iorange_destructor_thunk;
253
 
}
254
 
 
255
 
void isa_unassign_ioport(pio_addr_t start, int length)
256
 
{
257
 
    int i;
258
 
 
259
 
    if (ioport_destructor_table[start]) {
260
 
        ioport_destructor_table[start](ioport_opaque[start]);
261
 
        ioport_destructor_table[start] = NULL;
262
 
    }
263
 
    for(i = start; i < start + length; i++) {
264
 
        ioport_read_table[0][i] = NULL;
265
 
        ioport_read_table[1][i] = NULL;
266
 
        ioport_read_table[2][i] = NULL;
267
 
 
268
 
        ioport_write_table[0][i] = NULL;
269
 
        ioport_write_table[1][i] = NULL;
270
 
        ioport_write_table[2][i] = NULL;
271
 
 
272
 
        ioport_opaque[i] = NULL;
273
 
    }
274
 
}
275
 
 
276
 
bool isa_is_ioport_assigned(pio_addr_t start)
277
 
{
278
 
    return (ioport_read_table[0][start] || ioport_write_table[0][start] ||
279
 
            ioport_read_table[1][start] || ioport_write_table[1][start] ||
280
 
            ioport_read_table[2][start] || ioport_write_table[2][start]);
281
 
}
282
 
 
283
 
/***********************************************************/
 
41
typedef struct MemoryRegionPortioList {
 
42
    MemoryRegion mr;
 
43
    void *portio_opaque;
 
44
    MemoryRegionPortio ports[];
 
45
} MemoryRegionPortioList;
 
46
 
 
47
static uint64_t unassigned_io_read(void *opaque, hwaddr addr, unsigned size)
 
48
{
 
49
    return -1ULL;
 
50
}
 
51
 
 
52
static void unassigned_io_write(void *opaque, hwaddr addr, uint64_t val,
 
53
                                unsigned size)
 
54
{
 
55
}
 
56
 
 
57
const MemoryRegionOps unassigned_io_ops = {
 
58
    .read = unassigned_io_read,
 
59
    .write = unassigned_io_write,
 
60
    .endianness = DEVICE_NATIVE_ENDIAN,
 
61
};
284
62
 
285
63
void cpu_outb(pio_addr_t addr, uint8_t val)
286
64
{
287
65
    LOG_IOPORT("outb: %04"FMT_pioaddr" %02"PRIx8"\n", addr, val);
288
66
    trace_cpu_out(addr, val);
289
 
    ioport_write(0, addr, val);
 
67
    address_space_write(&address_space_io, addr, &val, 1);
290
68
}
291
69
 
292
70
void cpu_outw(pio_addr_t addr, uint16_t val)
293
71
{
 
72
    uint8_t buf[2];
 
73
 
294
74
    LOG_IOPORT("outw: %04"FMT_pioaddr" %04"PRIx16"\n", addr, val);
295
75
    trace_cpu_out(addr, val);
296
 
    ioport_write(1, addr, val);
 
76
    stw_p(buf, val);
 
77
    address_space_write(&address_space_io, addr, buf, 2);
297
78
}
298
79
 
299
80
void cpu_outl(pio_addr_t addr, uint32_t val)
300
81
{
 
82
    uint8_t buf[4];
 
83
 
301
84
    LOG_IOPORT("outl: %04"FMT_pioaddr" %08"PRIx32"\n", addr, val);
302
85
    trace_cpu_out(addr, val);
303
 
    ioport_write(2, addr, val);
 
86
    stl_p(buf, val);
 
87
    address_space_write(&address_space_io, addr, buf, 4);
304
88
}
305
89
 
306
90
uint8_t cpu_inb(pio_addr_t addr)
307
91
{
308
92
    uint8_t val;
309
 
    val = ioport_read(0, addr);
 
93
 
 
94
    address_space_read(&address_space_io, addr, &val, 1);
310
95
    trace_cpu_in(addr, val);
311
96
    LOG_IOPORT("inb : %04"FMT_pioaddr" %02"PRIx8"\n", addr, val);
312
97
    return val;
314
99
 
315
100
uint16_t cpu_inw(pio_addr_t addr)
316
101
{
 
102
    uint8_t buf[2];
317
103
    uint16_t val;
318
 
    val = ioport_read(1, addr);
 
104
 
 
105
    address_space_read(&address_space_io, addr, buf, 2);
 
106
    val = lduw_p(buf);
319
107
    trace_cpu_in(addr, val);
320
108
    LOG_IOPORT("inw : %04"FMT_pioaddr" %04"PRIx16"\n", addr, val);
321
109
    return val;
323
111
 
324
112
uint32_t cpu_inl(pio_addr_t addr)
325
113
{
 
114
    uint8_t buf[4];
326
115
    uint32_t val;
327
 
    val = ioport_read(2, addr);
 
116
 
 
117
    address_space_read(&address_space_io, addr, buf, 4);
 
118
    val = ldl_p(buf);
328
119
    trace_cpu_in(addr, val);
329
120
    LOG_IOPORT("inl : %04"FMT_pioaddr" %08"PRIx32"\n", addr, val);
330
121
    return val;
331
122
}
332
123
 
333
124
void portio_list_init(PortioList *piolist,
 
125
                      Object *owner,
334
126
                      const MemoryRegionPortio *callbacks,
335
127
                      void *opaque, const char *name)
336
128
{
343
135
    piolist->ports = callbacks;
344
136
    piolist->nr = 0;
345
137
    piolist->regions = g_new0(MemoryRegion *, n);
346
 
    piolist->aliases = g_new0(MemoryRegion *, n);
347
138
    piolist->address_space = NULL;
348
139
    piolist->opaque = opaque;
 
140
    piolist->owner = owner;
349
141
    piolist->name = name;
350
142
}
351
143
 
352
144
void portio_list_destroy(PortioList *piolist)
353
145
{
354
146
    g_free(piolist->regions);
355
 
    g_free(piolist->aliases);
356
 
}
 
147
}
 
148
 
 
149
static const MemoryRegionPortio *find_portio(MemoryRegionPortioList *mrpio,
 
150
                                             uint64_t offset, unsigned size,
 
151
                                             bool write)
 
152
{
 
153
    const MemoryRegionPortio *mrp;
 
154
 
 
155
    for (mrp = mrpio->ports; mrp->size; ++mrp) {
 
156
        if (offset >= mrp->offset && offset < mrp->offset + mrp->len &&
 
157
            size == mrp->size &&
 
158
            (write ? (bool)mrp->write : (bool)mrp->read)) {
 
159
            return mrp;
 
160
        }
 
161
    }
 
162
    return NULL;
 
163
}
 
164
 
 
165
static uint64_t portio_read(void *opaque, hwaddr addr, unsigned size)
 
166
{
 
167
    MemoryRegionPortioList *mrpio = opaque;
 
168
    const MemoryRegionPortio *mrp = find_portio(mrpio, addr, size, false);
 
169
    uint64_t data;
 
170
 
 
171
    data = ((uint64_t)1 << (size * 8)) - 1;
 
172
    if (mrp) {
 
173
        data = mrp->read(mrpio->portio_opaque, mrp->base + addr);
 
174
    } else if (size == 2) {
 
175
        mrp = find_portio(mrpio, addr, 1, false);
 
176
        assert(mrp);
 
177
        data = mrp->read(mrpio->portio_opaque, mrp->base + addr) |
 
178
                (mrp->read(mrpio->portio_opaque, mrp->base + addr + 1) << 8);
 
179
    }
 
180
    return data;
 
181
}
 
182
 
 
183
static void portio_write(void *opaque, hwaddr addr, uint64_t data,
 
184
                         unsigned size)
 
185
{
 
186
    MemoryRegionPortioList *mrpio = opaque;
 
187
    const MemoryRegionPortio *mrp = find_portio(mrpio, addr, size, true);
 
188
 
 
189
    if (mrp) {
 
190
        mrp->write(mrpio->portio_opaque, mrp->base + addr, data);
 
191
    } else if (size == 2) {
 
192
        mrp = find_portio(mrpio, addr, 1, true);
 
193
        assert(mrp);
 
194
        mrp->write(mrpio->portio_opaque, mrp->base + addr, data & 0xff);
 
195
        mrp->write(mrpio->portio_opaque, mrp->base + addr + 1, data >> 8);
 
196
    }
 
197
}
 
198
 
 
199
static const MemoryRegionOps portio_ops = {
 
200
    .read = portio_read,
 
201
    .write = portio_write,
 
202
    .endianness = DEVICE_LITTLE_ENDIAN,
 
203
    .valid.unaligned = true,
 
204
    .impl.unaligned = true,
 
205
};
357
206
 
358
207
static void portio_list_add_1(PortioList *piolist,
359
208
                              const MemoryRegionPortio *pio_init,
360
209
                              unsigned count, unsigned start,
361
210
                              unsigned off_low, unsigned off_high)
362
211
{
363
 
    MemoryRegionPortio *pio;
364
 
    MemoryRegionOps *ops;
365
 
    MemoryRegion *region, *alias;
 
212
    MemoryRegionPortioList *mrpio;
366
213
    unsigned i;
367
214
 
368
215
    /* Copy the sub-list and null-terminate it.  */
369
 
    pio = g_new(MemoryRegionPortio, count + 1);
370
 
    memcpy(pio, pio_init, sizeof(MemoryRegionPortio) * count);
371
 
    memset(pio + count, 0, sizeof(MemoryRegionPortio));
 
216
    mrpio = g_malloc0(sizeof(MemoryRegionPortioList) +
 
217
                      sizeof(MemoryRegionPortio) * (count + 1));
 
218
    mrpio->portio_opaque = piolist->opaque;
 
219
    memcpy(mrpio->ports, pio_init, sizeof(MemoryRegionPortio) * count);
 
220
    memset(mrpio->ports + count, 0, sizeof(MemoryRegionPortio));
372
221
 
373
222
    /* Adjust the offsets to all be zero-based for the region.  */
374
223
    for (i = 0; i < count; ++i) {
375
 
        pio[i].offset -= off_low;
 
224
        mrpio->ports[i].offset -= off_low;
 
225
        mrpio->ports[i].base = start + off_low;
376
226
    }
377
227
 
378
 
    ops = g_new0(MemoryRegionOps, 1);
379
 
    ops->old_portio = pio;
380
 
 
381
 
    region = g_new(MemoryRegion, 1);
382
 
    alias = g_new(MemoryRegion, 1);
383
228
    /*
384
229
     * Use an alias so that the callback is called with an absolute address,
385
230
     * rather than an offset relative to to start + off_low.
386
231
     */
387
 
    memory_region_init_io(region, ops, piolist->opaque, piolist->name,
388
 
                          INT64_MAX);
389
 
    memory_region_init_alias(alias, piolist->name,
390
 
                             region, start + off_low, off_high - off_low);
 
232
    memory_region_init_io(&mrpio->mr, piolist->owner, &portio_ops, mrpio,
 
233
                          piolist->name, off_high - off_low);
391
234
    memory_region_add_subregion(piolist->address_space,
392
 
                                start + off_low, alias);
393
 
    piolist->regions[piolist->nr] = region;
394
 
    piolist->aliases[piolist->nr] = alias;
 
235
                                start + off_low, &mrpio->mr);
 
236
    piolist->regions[piolist->nr] = &mrpio->mr;
395
237
    ++piolist->nr;
396
238
}
397
239
 
434
276
 
435
277
void portio_list_del(PortioList *piolist)
436
278
{
437
 
    MemoryRegion *mr, *alias;
 
279
    MemoryRegionPortioList *mrpio;
438
280
    unsigned i;
439
281
 
440
282
    for (i = 0; i < piolist->nr; ++i) {
441
 
        mr = piolist->regions[i];
442
 
        alias = piolist->aliases[i];
443
 
        memory_region_del_subregion(piolist->address_space, alias);
444
 
        memory_region_destroy(alias);
445
 
        memory_region_destroy(mr);
446
 
        g_free((MemoryRegionOps *)mr->ops);
447
 
        g_free(mr);
448
 
        g_free(alias);
 
283
        mrpio = container_of(piolist->regions[i], MemoryRegionPortioList, mr);
 
284
        memory_region_del_subregion(piolist->address_space, &mrpio->mr);
 
285
        memory_region_destroy(&mrpio->mr);
 
286
        g_free(mrpio);
449
287
        piolist->regions[i] = NULL;
450
 
        piolist->aliases[i] = NULL;
451
288
    }
452
289
}