Statistics
| Branch: | Revision:

root / hw / spapr_vio.c @ c48c6522

History | View | Annotate | Download (22.8 kB)

1
/*
2
 * QEMU sPAPR VIO code
3
 *
4
 * Copyright (c) 2010 David Gibson, IBM Corporation <dwg@au1.ibm.com>
5
 * Based on the s390 virtio bus code:
6
 * Copyright (c) 2009 Alexander Graf <agraf@suse.de>
7
 *
8
 * This library is free software; you can redistribute it and/or
9
 * modify it under the terms of the GNU Lesser General Public
10
 * License as published by the Free Software Foundation; either
11
 * version 2 of the License, or (at your option) any later version.
12
 *
13
 * This library is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16
 * Lesser General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU Lesser General Public
19
 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
20
 */
21

    
22
#include "hw.h"
23
#include "sysemu.h"
24
#include "boards.h"
25
#include "monitor.h"
26
#include "loader.h"
27
#include "elf.h"
28
#include "hw/sysbus.h"
29
#include "kvm.h"
30
#include "device_tree.h"
31
#include "kvm_ppc.h"
32

    
33
#include "hw/spapr.h"
34
#include "hw/spapr_vio.h"
35
#include "hw/xics.h"
36

    
37
#ifdef CONFIG_FDT
38
#include <libfdt.h>
39
#endif /* CONFIG_FDT */
40

    
41
/* #define DEBUG_SPAPR */
42
/* #define DEBUG_TCE */
43

    
44
#ifdef DEBUG_SPAPR
45
#define dprintf(fmt, ...) \
46
    do { fprintf(stderr, fmt, ## __VA_ARGS__); } while (0)
47
#else
48
#define dprintf(fmt, ...) \
49
    do { } while (0)
50
#endif
51

    
52
static Property spapr_vio_props[] = {
53
    DEFINE_PROP_UINT32("irq", VIOsPAPRDevice, vio_irq_num, 0), \
54
    DEFINE_PROP_END_OF_LIST(),
55
};
56

    
57
static const TypeInfo spapr_vio_bus_info = {
58
    .name = TYPE_SPAPR_VIO_BUS,
59
    .parent = TYPE_BUS,
60
    .instance_size = sizeof(VIOsPAPRBus),
61
};
62

    
63
VIOsPAPRDevice *spapr_vio_find_by_reg(VIOsPAPRBus *bus, uint32_t reg)
64
{
65
    BusChild *kid;
66
    VIOsPAPRDevice *dev = NULL;
67

    
68
    QTAILQ_FOREACH(kid, &bus->bus.children, sibling) {
69
        dev = (VIOsPAPRDevice *)kid->child;
70
        if (dev->reg == reg) {
71
            return dev;
72
        }
73
    }
74

    
75
    return NULL;
76
}
77

    
78
static char *vio_format_dev_name(VIOsPAPRDevice *dev)
79
{
80
    VIOsPAPRDeviceClass *pc = VIO_SPAPR_DEVICE_GET_CLASS(dev);
81
    char *name;
82

    
83
    /* Device tree style name device@reg */
84
    if (asprintf(&name, "%s@%x", pc->dt_name, dev->reg) < 0) {
85
        return NULL;
86
    }
87

    
88
    return name;
89
}
90

    
91
#ifdef CONFIG_FDT
92
static int vio_make_devnode(VIOsPAPRDevice *dev,
93
                            void *fdt)
94
{
95
    VIOsPAPRDeviceClass *pc = VIO_SPAPR_DEVICE_GET_CLASS(dev);
96
    int vdevice_off, node_off, ret;
97
    char *dt_name;
98

    
99
    vdevice_off = fdt_path_offset(fdt, "/vdevice");
100
    if (vdevice_off < 0) {
101
        return vdevice_off;
102
    }
103

    
104
    dt_name = vio_format_dev_name(dev);
105
    if (!dt_name) {
106
        return -ENOMEM;
107
    }
108

    
109
    node_off = fdt_add_subnode(fdt, vdevice_off, dt_name);
110
    free(dt_name);
111
    if (node_off < 0) {
112
        return node_off;
113
    }
114

    
115
    ret = fdt_setprop_cell(fdt, node_off, "reg", dev->reg);
116
    if (ret < 0) {
117
        return ret;
118
    }
119

    
120
    if (pc->dt_type) {
121
        ret = fdt_setprop_string(fdt, node_off, "device_type",
122
                                 pc->dt_type);
123
        if (ret < 0) {
124
            return ret;
125
        }
126
    }
127

    
128
    if (pc->dt_compatible) {
129
        ret = fdt_setprop_string(fdt, node_off, "compatible",
130
                                 pc->dt_compatible);
131
        if (ret < 0) {
132
            return ret;
133
        }
134
    }
135

    
136
    if (dev->qirq) {
137
        uint32_t ints_prop[] = {cpu_to_be32(dev->vio_irq_num), 0};
138

    
139
        ret = fdt_setprop(fdt, node_off, "interrupts", ints_prop,
140
                          sizeof(ints_prop));
141
        if (ret < 0) {
142
            return ret;
143
        }
144
    }
145

    
146
    if (dev->rtce_window_size) {
147
        uint32_t dma_prop[] = {cpu_to_be32(dev->reg),
148
                               0, 0,
149
                               0, cpu_to_be32(dev->rtce_window_size)};
150

    
151
        ret = fdt_setprop_cell(fdt, node_off, "ibm,#dma-address-cells", 2);
152
        if (ret < 0) {
153
            return ret;
154
        }
155

    
156
        ret = fdt_setprop_cell(fdt, node_off, "ibm,#dma-size-cells", 2);
157
        if (ret < 0) {
158
            return ret;
159
        }
160

    
161
        ret = fdt_setprop(fdt, node_off, "ibm,my-dma-window", dma_prop,
162
                          sizeof(dma_prop));
163
        if (ret < 0) {
164
            return ret;
165
        }
166
    }
167

    
168
    if (pc->devnode) {
169
        ret = (pc->devnode)(dev, fdt, node_off);
170
        if (ret < 0) {
171
            return ret;
172
        }
173
    }
174

    
175
    return node_off;
176
}
177
#endif /* CONFIG_FDT */
178

    
179
/*
180
 * RTCE handling
181
 */
182

    
183
static void rtce_init(VIOsPAPRDevice *dev)
184
{
185
    size_t size = (dev->rtce_window_size >> SPAPR_VIO_TCE_PAGE_SHIFT)
186
        * sizeof(VIOsPAPR_RTCE);
187

    
188
    if (size) {
189
        dev->rtce_table = kvmppc_create_spapr_tce(dev->reg,
190
                                                  dev->rtce_window_size,
191
                                                  &dev->kvmtce_fd);
192

    
193
        if (!dev->rtce_table) {
194
            dev->rtce_table = g_malloc0(size);
195
        }
196
    }
197
}
198

    
199
static target_ulong h_put_tce(CPUPPCState *env, sPAPREnvironment *spapr,
200
                              target_ulong opcode, target_ulong *args)
201
{
202
    target_ulong liobn = args[0];
203
    target_ulong ioba = args[1];
204
    target_ulong tce = args[2];
205
    VIOsPAPRDevice *dev = spapr_vio_find_by_reg(spapr->vio_bus, liobn);
206
    VIOsPAPR_RTCE *rtce;
207

    
208
    if (!dev) {
209
        hcall_dprintf("LIOBN 0x" TARGET_FMT_lx " does not exist\n", liobn);
210
        return H_PARAMETER;
211
    }
212

    
213
    ioba &= ~(SPAPR_VIO_TCE_PAGE_SIZE - 1);
214

    
215
#ifdef DEBUG_TCE
216
    fprintf(stderr, "spapr_vio_put_tce on %s  ioba 0x" TARGET_FMT_lx
217
            "  TCE 0x" TARGET_FMT_lx "\n", dev->qdev.id, ioba, tce);
218
#endif
219

    
220
    if (ioba >= dev->rtce_window_size) {
221
        hcall_dprintf("Out-of-bounds IOBA 0x" TARGET_FMT_lx "\n", ioba);
222
        return H_PARAMETER;
223
    }
224

    
225
    rtce = dev->rtce_table + (ioba >> SPAPR_VIO_TCE_PAGE_SHIFT);
226
    rtce->tce = tce;
227

    
228
    return H_SUCCESS;
229
}
230

    
231
int spapr_vio_check_tces(VIOsPAPRDevice *dev, target_ulong ioba,
232
                         target_ulong len, enum VIOsPAPR_TCEAccess access)
233
{
234
    int start, end, i;
235

    
236
    start = ioba >> SPAPR_VIO_TCE_PAGE_SHIFT;
237
    end = (ioba + len - 1) >> SPAPR_VIO_TCE_PAGE_SHIFT;
238

    
239
    for (i = start; i <= end; i++) {
240
        if ((dev->rtce_table[i].tce & access) != access) {
241
#ifdef DEBUG_TCE
242
            fprintf(stderr, "FAIL on %d\n", i);
243
#endif
244
            return -1;
245
        }
246
    }
247

    
248
    return 0;
249
}
250

    
251
int spapr_tce_dma_write(VIOsPAPRDevice *dev, uint64_t taddr, const void *buf,
252
                        uint32_t size)
253
{
254
#ifdef DEBUG_TCE
255
    fprintf(stderr, "spapr_tce_dma_write taddr=0x%llx size=0x%x\n",
256
            (unsigned long long)taddr, size);
257
#endif
258

    
259
    /* Check for bypass */
260
    if (dev->flags & VIO_PAPR_FLAG_DMA_BYPASS) {
261
        cpu_physical_memory_write(taddr, buf, size);
262
        return 0;
263
    }
264

    
265
    while (size) {
266
        uint64_t tce;
267
        uint32_t lsize;
268
        uint64_t txaddr;
269

    
270
        /* Check if we are in bound */
271
        if (taddr >= dev->rtce_window_size) {
272
#ifdef DEBUG_TCE
273
            fprintf(stderr, "spapr_tce_dma_write out of bounds\n");
274
#endif
275
            return H_DEST_PARM;
276
        }
277
        tce = dev->rtce_table[taddr >> SPAPR_VIO_TCE_PAGE_SHIFT].tce;
278

    
279
        /* How much til end of page ? */
280
        lsize = MIN(size, ((~taddr) & SPAPR_VIO_TCE_PAGE_MASK) + 1);
281

    
282
        /* Check TCE */
283
        if (!(tce & 2)) {
284
            return H_DEST_PARM;
285
        }
286

    
287
        /* Translate */
288
        txaddr = (tce & ~SPAPR_VIO_TCE_PAGE_MASK) |
289
            (taddr & SPAPR_VIO_TCE_PAGE_MASK);
290

    
291
#ifdef DEBUG_TCE
292
        fprintf(stderr, " -> write to txaddr=0x%llx, size=0x%x\n",
293
                (unsigned long long)txaddr, lsize);
294
#endif
295

    
296
        /* Do it */
297
        cpu_physical_memory_write(txaddr, buf, lsize);
298
        buf += lsize;
299
        taddr += lsize;
300
        size -= lsize;
301
    }
302
    return 0;
303
}
304

    
305
int spapr_tce_dma_zero(VIOsPAPRDevice *dev, uint64_t taddr, uint32_t size)
306
{
307
    /* FIXME: allocating a temp buffer is nasty, but just stepping
308
     * through writing zeroes is awkward.  This will do for now. */
309
    uint8_t zeroes[size];
310

    
311
#ifdef DEBUG_TCE
312
    fprintf(stderr, "spapr_tce_dma_zero taddr=0x%llx size=0x%x\n",
313
            (unsigned long long)taddr, size);
314
#endif
315

    
316
    memset(zeroes, 0, size);
317
    return spapr_tce_dma_write(dev, taddr, zeroes, size);
318
}
319

    
320
void stb_tce(VIOsPAPRDevice *dev, uint64_t taddr, uint8_t val)
321
{
322
    spapr_tce_dma_write(dev, taddr, &val, sizeof(val));
323
}
324

    
325
void sth_tce(VIOsPAPRDevice *dev, uint64_t taddr, uint16_t val)
326
{
327
    val = tswap16(val);
328
    spapr_tce_dma_write(dev, taddr, &val, sizeof(val));
329
}
330

    
331

    
332
void stw_tce(VIOsPAPRDevice *dev, uint64_t taddr, uint32_t val)
333
{
334
    val = tswap32(val);
335
    spapr_tce_dma_write(dev, taddr, &val, sizeof(val));
336
}
337

    
338
void stq_tce(VIOsPAPRDevice *dev, uint64_t taddr, uint64_t val)
339
{
340
    val = tswap64(val);
341
    spapr_tce_dma_write(dev, taddr, &val, sizeof(val));
342
}
343

    
344
int spapr_tce_dma_read(VIOsPAPRDevice *dev, uint64_t taddr, void *buf,
345
                       uint32_t size)
346
{
347
#ifdef DEBUG_TCE
348
    fprintf(stderr, "spapr_tce_dma_write taddr=0x%llx size=0x%x\n",
349
            (unsigned long long)taddr, size);
350
#endif
351

    
352
    /* Check for bypass */
353
    if (dev->flags & VIO_PAPR_FLAG_DMA_BYPASS) {
354
        cpu_physical_memory_read(taddr, buf, size);
355
        return 0;
356
    }
357

    
358
    while (size) {
359
        uint64_t tce;
360
        uint32_t lsize;
361
        uint64_t txaddr;
362

    
363
        /* Check if we are in bound */
364
        if (taddr >= dev->rtce_window_size) {
365
#ifdef DEBUG_TCE
366
            fprintf(stderr, "spapr_tce_dma_read out of bounds\n");
367
#endif
368
            return H_DEST_PARM;
369
        }
370
        tce = dev->rtce_table[taddr >> SPAPR_VIO_TCE_PAGE_SHIFT].tce;
371

    
372
        /* How much til end of page ? */
373
        lsize = MIN(size, ((~taddr) & SPAPR_VIO_TCE_PAGE_MASK) + 1);
374

    
375
        /* Check TCE */
376
        if (!(tce & 1)) {
377
            return H_DEST_PARM;
378
        }
379

    
380
        /* Translate */
381
        txaddr = (tce & ~SPAPR_VIO_TCE_PAGE_MASK) |
382
            (taddr & SPAPR_VIO_TCE_PAGE_MASK);
383

    
384
#ifdef DEBUG_TCE
385
        fprintf(stderr, " -> write to txaddr=0x%llx, size=0x%x\n",
386
                (unsigned long long)txaddr, lsize);
387
#endif
388
        /* Do it */
389
        cpu_physical_memory_read(txaddr, buf, lsize);
390
        buf += lsize;
391
        taddr += lsize;
392
        size -= lsize;
393
    }
394
    return H_SUCCESS;
395
}
396

    
397
uint64_t ldq_tce(VIOsPAPRDevice *dev, uint64_t taddr)
398
{
399
    uint64_t val;
400

    
401
    spapr_tce_dma_read(dev, taddr, &val, sizeof(val));
402
    return tswap64(val);
403
}
404

    
405
/*
406
 * CRQ handling
407
 */
408
static target_ulong h_reg_crq(CPUPPCState *env, sPAPREnvironment *spapr,
409
                              target_ulong opcode, target_ulong *args)
410
{
411
    target_ulong reg = args[0];
412
    target_ulong queue_addr = args[1];
413
    target_ulong queue_len = args[2];
414
    VIOsPAPRDevice *dev = spapr_vio_find_by_reg(spapr->vio_bus, reg);
415

    
416
    if (!dev) {
417
        hcall_dprintf("Unit 0x" TARGET_FMT_lx " does not exist\n", reg);
418
        return H_PARAMETER;
419
    }
420

    
421
    /* We can't grok a queue size bigger than 256M for now */
422
    if (queue_len < 0x1000 || queue_len > 0x10000000) {
423
        hcall_dprintf("Queue size too small or too big (0x" TARGET_FMT_lx
424
                      ")\n", queue_len);
425
        return H_PARAMETER;
426
    }
427

    
428
    /* Check queue alignment */
429
    if (queue_addr & 0xfff) {
430
        hcall_dprintf("Queue not aligned (0x" TARGET_FMT_lx ")\n", queue_addr);
431
        return H_PARAMETER;
432
    }
433

    
434
    /* Check if device supports CRQs */
435
    if (!dev->crq.SendFunc) {
436
        hcall_dprintf("Device does not support CRQ\n");
437
        return H_NOT_FOUND;
438
    }
439

    
440
    /* Already a queue ? */
441
    if (dev->crq.qsize) {
442
        hcall_dprintf("CRQ already registered\n");
443
        return H_RESOURCE;
444
    }
445
    dev->crq.qladdr = queue_addr;
446
    dev->crq.qsize = queue_len;
447
    dev->crq.qnext = 0;
448

    
449
    dprintf("CRQ for dev 0x" TARGET_FMT_lx " registered at 0x"
450
            TARGET_FMT_lx "/0x" TARGET_FMT_lx "\n",
451
            reg, queue_addr, queue_len);
452
    return H_SUCCESS;
453
}
454

    
455
static target_ulong free_crq(VIOsPAPRDevice *dev)
456
{
457
    dev->crq.qladdr = 0;
458
    dev->crq.qsize = 0;
459
    dev->crq.qnext = 0;
460

    
461
    dprintf("CRQ for dev 0x%" PRIx32 " freed\n", dev->reg);
462

    
463
    return H_SUCCESS;
464
}
465

    
466
static target_ulong h_free_crq(CPUPPCState *env, sPAPREnvironment *spapr,
467
                               target_ulong opcode, target_ulong *args)
468
{
469
    target_ulong reg = args[0];
470
    VIOsPAPRDevice *dev = spapr_vio_find_by_reg(spapr->vio_bus, reg);
471

    
472
    if (!dev) {
473
        hcall_dprintf("Unit 0x" TARGET_FMT_lx " does not exist\n", reg);
474
        return H_PARAMETER;
475
    }
476

    
477
    return free_crq(dev);
478
}
479

    
480
static target_ulong h_send_crq(CPUPPCState *env, sPAPREnvironment *spapr,
481
                               target_ulong opcode, target_ulong *args)
482
{
483
    target_ulong reg = args[0];
484
    target_ulong msg_hi = args[1];
485
    target_ulong msg_lo = args[2];
486
    VIOsPAPRDevice *dev = spapr_vio_find_by_reg(spapr->vio_bus, reg);
487
    uint64_t crq_mangle[2];
488

    
489
    if (!dev) {
490
        hcall_dprintf("Unit 0x" TARGET_FMT_lx " does not exist\n", reg);
491
        return H_PARAMETER;
492
    }
493
    crq_mangle[0] = cpu_to_be64(msg_hi);
494
    crq_mangle[1] = cpu_to_be64(msg_lo);
495

    
496
    if (dev->crq.SendFunc) {
497
        return dev->crq.SendFunc(dev, (uint8_t *)crq_mangle);
498
    }
499

    
500
    return H_HARDWARE;
501
}
502

    
503
static target_ulong h_enable_crq(CPUPPCState *env, sPAPREnvironment *spapr,
504
                                 target_ulong opcode, target_ulong *args)
505
{
506
    target_ulong reg = args[0];
507
    VIOsPAPRDevice *dev = spapr_vio_find_by_reg(spapr->vio_bus, reg);
508

    
509
    if (!dev) {
510
        hcall_dprintf("Unit 0x" TARGET_FMT_lx " does not exist\n", reg);
511
        return H_PARAMETER;
512
    }
513

    
514
    return 0;
515
}
516

    
517
/* Returns negative error, 0 success, or positive: queue full */
518
int spapr_vio_send_crq(VIOsPAPRDevice *dev, uint8_t *crq)
519
{
520
    int rc;
521
    uint8_t byte;
522

    
523
    if (!dev->crq.qsize) {
524
        fprintf(stderr, "spapr_vio_send_creq on uninitialized queue\n");
525
        return -1;
526
    }
527

    
528
    /* Maybe do a fast path for KVM just writing to the pages */
529
    rc = spapr_tce_dma_read(dev, dev->crq.qladdr + dev->crq.qnext, &byte, 1);
530
    if (rc) {
531
        return rc;
532
    }
533
    if (byte != 0) {
534
        return 1;
535
    }
536

    
537
    rc = spapr_tce_dma_write(dev, dev->crq.qladdr + dev->crq.qnext + 8,
538
                             &crq[8], 8);
539
    if (rc) {
540
        return rc;
541
    }
542

    
543
    kvmppc_eieio();
544

    
545
    rc = spapr_tce_dma_write(dev, dev->crq.qladdr + dev->crq.qnext, crq, 8);
546
    if (rc) {
547
        return rc;
548
    }
549

    
550
    dev->crq.qnext = (dev->crq.qnext + 16) % dev->crq.qsize;
551

    
552
    if (dev->signal_state & 1) {
553
        qemu_irq_pulse(dev->qirq);
554
    }
555

    
556
    return 0;
557
}
558

    
559
/* "quiesce" handling */
560

    
561
static void spapr_vio_quiesce_one(VIOsPAPRDevice *dev)
562
{
563
    dev->flags &= ~VIO_PAPR_FLAG_DMA_BYPASS;
564

    
565
    if (dev->rtce_table) {
566
        size_t size = (dev->rtce_window_size >> SPAPR_VIO_TCE_PAGE_SHIFT)
567
            * sizeof(VIOsPAPR_RTCE);
568
        memset(dev->rtce_table, 0, size);
569
    }
570

    
571
    dev->crq.qladdr = 0;
572
    dev->crq.qsize = 0;
573
    dev->crq.qnext = 0;
574
}
575

    
576
static void rtas_set_tce_bypass(sPAPREnvironment *spapr, uint32_t token,
577
                                uint32_t nargs, target_ulong args,
578
                                uint32_t nret, target_ulong rets)
579
{
580
    VIOsPAPRBus *bus = spapr->vio_bus;
581
    VIOsPAPRDevice *dev;
582
    uint32_t unit, enable;
583

    
584
    if (nargs != 2) {
585
        rtas_st(rets, 0, -3);
586
        return;
587
    }
588
    unit = rtas_ld(args, 0);
589
    enable = rtas_ld(args, 1);
590
    dev = spapr_vio_find_by_reg(bus, unit);
591
    if (!dev) {
592
        rtas_st(rets, 0, -3);
593
        return;
594
    }
595
    if (enable) {
596
        dev->flags |= VIO_PAPR_FLAG_DMA_BYPASS;
597
    } else {
598
        dev->flags &= ~VIO_PAPR_FLAG_DMA_BYPASS;
599
    }
600

    
601
    rtas_st(rets, 0, 0);
602
}
603

    
604
static void rtas_quiesce(sPAPREnvironment *spapr, uint32_t token,
605
                         uint32_t nargs, target_ulong args,
606
                         uint32_t nret, target_ulong rets)
607
{
608
    VIOsPAPRBus *bus = spapr->vio_bus;
609
    BusChild *kid;
610
    VIOsPAPRDevice *dev = NULL;
611

    
612
    if (nargs != 0) {
613
        rtas_st(rets, 0, -3);
614
        return;
615
    }
616

    
617
    QTAILQ_FOREACH(kid, &bus->bus.children, sibling) {
618
        dev = (VIOsPAPRDevice *)kid->child;
619
        spapr_vio_quiesce_one(dev);
620
    }
621

    
622
    rtas_st(rets, 0, 0);
623
}
624

    
625
static VIOsPAPRDevice *reg_conflict(VIOsPAPRDevice *dev)
626
{
627
    VIOsPAPRBus *bus = DO_UPCAST(VIOsPAPRBus, bus, dev->qdev.parent_bus);
628
    BusChild *kid;
629
    VIOsPAPRDevice *other;
630

    
631
    /*
632
     * Check for a device other than the given one which is already
633
     * using the requested address. We have to open code this because
634
     * the given dev might already be in the list.
635
     */
636
    QTAILQ_FOREACH(kid, &bus->bus.children, sibling) {
637
        other = DO_UPCAST(VIOsPAPRDevice, qdev, kid->child);
638

    
639
        if (other != dev && other->reg == dev->reg) {
640
            return other;
641
        }
642
    }
643

    
644
    return 0;
645
}
646

    
647
static void spapr_vio_busdev_reset(DeviceState *qdev)
648
{
649
    VIOsPAPRDevice *dev = DO_UPCAST(VIOsPAPRDevice, qdev, qdev);
650
    VIOsPAPRDeviceClass *pc = VIO_SPAPR_DEVICE_GET_CLASS(dev);
651

    
652
    if (dev->crq.qsize) {
653
        free_crq(dev);
654
    }
655

    
656
    if (pc->reset) {
657
        pc->reset(dev);
658
    }
659
}
660

    
661
static int spapr_vio_busdev_init(DeviceState *qdev)
662
{
663
    VIOsPAPRDevice *dev = (VIOsPAPRDevice *)qdev;
664
    VIOsPAPRDeviceClass *pc = VIO_SPAPR_DEVICE_GET_CLASS(dev);
665
    char *id;
666

    
667
    if (dev->reg != -1) {
668
        /*
669
         * Explicitly assigned address, just verify that no-one else
670
         * is using it.  other mechanism). We have to open code this
671
         * rather than using spapr_vio_find_by_reg() because sdev
672
         * itself is already in the list.
673
         */
674
        VIOsPAPRDevice *other = reg_conflict(dev);
675

    
676
        if (other) {
677
            fprintf(stderr, "vio: %s and %s devices conflict at address %#x\n",
678
                    object_get_typename(OBJECT(qdev)),
679
                    object_get_typename(OBJECT(&other->qdev)),
680
                    dev->reg);
681
            return -1;
682
        }
683
    } else {
684
        /* Need to assign an address */
685
        VIOsPAPRBus *bus = DO_UPCAST(VIOsPAPRBus, bus, dev->qdev.parent_bus);
686

    
687
        do {
688
            dev->reg = bus->next_reg++;
689
        } while (reg_conflict(dev));
690
    }
691

    
692
    /* Don't overwrite ids assigned on the command line */
693
    if (!dev->qdev.id) {
694
        id = vio_format_dev_name(dev);
695
        if (!id) {
696
            return -1;
697
        }
698
        dev->qdev.id = id;
699
    }
700

    
701
    dev->qirq = spapr_allocate_msi(dev->vio_irq_num, &dev->vio_irq_num);
702
    if (!dev->qirq) {
703
        return -1;
704
    }
705

    
706
    rtce_init(dev);
707

    
708
    return pc->init(dev);
709
}
710

    
711
static target_ulong h_vio_signal(CPUPPCState *env, sPAPREnvironment *spapr,
712
                                 target_ulong opcode,
713
                                 target_ulong *args)
714
{
715
    target_ulong reg = args[0];
716
    target_ulong mode = args[1];
717
    VIOsPAPRDevice *dev = spapr_vio_find_by_reg(spapr->vio_bus, reg);
718
    VIOsPAPRDeviceClass *pc;
719

    
720
    if (!dev) {
721
        return H_PARAMETER;
722
    }
723

    
724
    pc = VIO_SPAPR_DEVICE_GET_CLASS(dev);
725

    
726
    if (mode & ~pc->signal_mask) {
727
        return H_PARAMETER;
728
    }
729

    
730
    dev->signal_state = mode;
731

    
732
    return H_SUCCESS;
733
}
734

    
735
VIOsPAPRBus *spapr_vio_bus_init(void)
736
{
737
    VIOsPAPRBus *bus;
738
    BusState *qbus;
739
    DeviceState *dev;
740

    
741
    /* Create bridge device */
742
    dev = qdev_create(NULL, "spapr-vio-bridge");
743
    qdev_init_nofail(dev);
744

    
745
    /* Create bus on bridge device */
746

    
747
    qbus = qbus_create(TYPE_SPAPR_VIO_BUS, dev, "spapr-vio");
748
    bus = DO_UPCAST(VIOsPAPRBus, bus, qbus);
749
    bus->next_reg = 0x1000;
750

    
751
    /* hcall-vio */
752
    spapr_register_hypercall(H_VIO_SIGNAL, h_vio_signal);
753

    
754
    /* hcall-tce */
755
    spapr_register_hypercall(H_PUT_TCE, h_put_tce);
756

    
757
    /* hcall-crq */
758
    spapr_register_hypercall(H_REG_CRQ, h_reg_crq);
759
    spapr_register_hypercall(H_FREE_CRQ, h_free_crq);
760
    spapr_register_hypercall(H_SEND_CRQ, h_send_crq);
761
    spapr_register_hypercall(H_ENABLE_CRQ, h_enable_crq);
762

    
763
    /* RTAS calls */
764
    spapr_rtas_register("ibm,set-tce-bypass", rtas_set_tce_bypass);
765
    spapr_rtas_register("quiesce", rtas_quiesce);
766

    
767
    return bus;
768
}
769

    
770
/* Represents sPAPR hcall VIO devices */
771

    
772
static int spapr_vio_bridge_init(SysBusDevice *dev)
773
{
774
    /* nothing */
775
    return 0;
776
}
777

    
778
static void spapr_vio_bridge_class_init(ObjectClass *klass, void *data)
779
{
780
    DeviceClass *dc = DEVICE_CLASS(klass);
781
    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
782

    
783
    k->init = spapr_vio_bridge_init;
784
    dc->no_user = 1;
785
}
786

    
787
static TypeInfo spapr_vio_bridge_info = {
788
    .name          = "spapr-vio-bridge",
789
    .parent        = TYPE_SYS_BUS_DEVICE,
790
    .instance_size = sizeof(SysBusDevice),
791
    .class_init    = spapr_vio_bridge_class_init,
792
};
793

    
794
static void vio_spapr_device_class_init(ObjectClass *klass, void *data)
795
{
796
    DeviceClass *k = DEVICE_CLASS(klass);
797
    k->init = spapr_vio_busdev_init;
798
    k->reset = spapr_vio_busdev_reset;
799
    k->bus_type = TYPE_SPAPR_VIO_BUS;
800
    k->props = spapr_vio_props;
801
}
802

    
803
static TypeInfo spapr_vio_type_info = {
804
    .name = TYPE_VIO_SPAPR_DEVICE,
805
    .parent = TYPE_DEVICE,
806
    .instance_size = sizeof(VIOsPAPRDevice),
807
    .abstract = true,
808
    .class_size = sizeof(VIOsPAPRDeviceClass),
809
    .class_init = vio_spapr_device_class_init,
810
};
811

    
812
static void spapr_vio_register_types(void)
813
{
814
    type_register_static(&spapr_vio_bus_info);
815
    type_register_static(&spapr_vio_bridge_info);
816
    type_register_static(&spapr_vio_type_info);
817
}
818

    
819
type_init(spapr_vio_register_types)
820

    
821
#ifdef CONFIG_FDT
822
static int compare_reg(const void *p1, const void *p2)
823
{
824
    VIOsPAPRDevice const *dev1, *dev2;
825

    
826
    dev1 = (VIOsPAPRDevice *)*(DeviceState **)p1;
827
    dev2 = (VIOsPAPRDevice *)*(DeviceState **)p2;
828

    
829
    if (dev1->reg < dev2->reg) {
830
        return -1;
831
    }
832
    if (dev1->reg == dev2->reg) {
833
        return 0;
834
    }
835

    
836
    /* dev1->reg > dev2->reg */
837
    return 1;
838
}
839

    
840
int spapr_populate_vdevice(VIOsPAPRBus *bus, void *fdt)
841
{
842
    DeviceState *qdev, **qdevs;
843
    BusChild *kid;
844
    int i, num, ret = 0;
845

    
846
    /* Count qdevs on the bus list */
847
    num = 0;
848
    QTAILQ_FOREACH(kid, &bus->bus.children, sibling) {
849
        num++;
850
    }
851

    
852
    /* Copy out into an array of pointers */
853
    qdevs = g_malloc(sizeof(qdev) * num);
854
    num = 0;
855
    QTAILQ_FOREACH(kid, &bus->bus.children, sibling) {
856
        qdevs[num++] = kid->child;
857
    }
858

    
859
    /* Sort the array */
860
    qsort(qdevs, num, sizeof(qdev), compare_reg);
861

    
862
    /* Hack alert. Give the devices to libfdt in reverse order, we happen
863
     * to know that will mean they are in forward order in the tree. */
864
    for (i = num - 1; i >= 0; i--) {
865
        VIOsPAPRDevice *dev = (VIOsPAPRDevice *)(qdevs[i]);
866

    
867
        ret = vio_make_devnode(dev, fdt);
868

    
869
        if (ret < 0) {
870
            goto out;
871
        }
872
    }
873

    
874
    ret = 0;
875
out:
876
    free(qdevs);
877

    
878
    return ret;
879
}
880

    
881
int spapr_populate_chosen_stdout(void *fdt, VIOsPAPRBus *bus)
882
{
883
    VIOsPAPRDevice *dev;
884
    char *name, *path;
885
    int ret, offset;
886

    
887
    dev = spapr_vty_get_default(bus);
888
    if (!dev)
889
        return 0;
890

    
891
    offset = fdt_path_offset(fdt, "/chosen");
892
    if (offset < 0) {
893
        return offset;
894
    }
895

    
896
    name = vio_format_dev_name(dev);
897
    if (!name) {
898
        return -ENOMEM;
899
    }
900

    
901
    if (asprintf(&path, "/vdevice/%s", name) < 0) {
902
        path = NULL;
903
        ret = -ENOMEM;
904
        goto out;
905
    }
906

    
907
    ret = fdt_setprop_string(fdt, offset, "linux,stdout-path", path);
908
out:
909
    free(name);
910
    free(path);
911

    
912
    return ret;
913
}
914
#endif /* CONFIG_FDT */