Revision 08942ac1

b/hw/spapr_vio.c
226 226
            (unsigned long long)taddr, size);
227 227
#endif
228 228

  
229
    /* Check for bypass */
230
    if (dev->flags & VIO_PAPR_FLAG_DMA_BYPASS) {
231
        cpu_physical_memory_write(taddr, buf, size);
232
        return 0;
233
    }
234

  
229 235
    while (size) {
230 236
        uint64_t tce;
231 237
        uint32_t lsize;
......
313 319
            (unsigned long long)taddr, size);
314 320
#endif
315 321

  
322
    /* Check for bypass */
323
    if (dev->flags & VIO_PAPR_FLAG_DMA_BYPASS) {
324
        cpu_physical_memory_read(taddr, buf, size);
325
        return 0;
326
    }
327

  
316 328
    while (size) {
317 329
        uint64_t tce;
318 330
        uint32_t lsize;
......
513 525
    return 0;
514 526
}
515 527

  
528
/* "quiesce" handling */
529

  
530
static void spapr_vio_quiesce_one(VIOsPAPRDevice *dev)
531
{
532
    dev->flags &= ~VIO_PAPR_FLAG_DMA_BYPASS;
533

  
534
    if (dev->rtce_table) {
535
        size_t size = (dev->rtce_window_size >> SPAPR_VIO_TCE_PAGE_SHIFT)
536
            * sizeof(VIOsPAPR_RTCE);
537
        memset(dev->rtce_table, 0, size);
538
    }
539

  
540
    dev->crq.qladdr = 0;
541
    dev->crq.qsize = 0;
542
    dev->crq.qnext = 0;
543
}
544

  
545
static void rtas_set_tce_bypass(sPAPREnvironment *spapr, uint32_t token,
546
                                uint32_t nargs, target_ulong args,
547
                                uint32_t nret, target_ulong rets)
548
{
549
    VIOsPAPRBus *bus = spapr->vio_bus;
550
    VIOsPAPRDevice *dev;
551
    uint32_t unit, enable;
552

  
553
    if (nargs != 2) {
554
        rtas_st(rets, 0, -3);
555
        return;
556
    }
557
    unit = rtas_ld(args, 0);
558
    enable = rtas_ld(args, 1);
559
    dev = spapr_vio_find_by_reg(bus, unit);
560
    if (!dev) {
561
        rtas_st(rets, 0, -3);
562
        return;
563
    }
564
    if (enable) {
565
        dev->flags |= VIO_PAPR_FLAG_DMA_BYPASS;
566
    } else {
567
        dev->flags &= ~VIO_PAPR_FLAG_DMA_BYPASS;
568
    }
569

  
570
    rtas_st(rets, 0, 0);
571
}
572

  
573
static void rtas_quiesce(sPAPREnvironment *spapr, uint32_t token,
574
                         uint32_t nargs, target_ulong args,
575
                         uint32_t nret, target_ulong rets)
576
{
577
    VIOsPAPRBus *bus = spapr->vio_bus;
578
    DeviceState *qdev;
579
    VIOsPAPRDevice *dev = NULL;
580

  
581
    if (nargs != 0) {
582
        rtas_st(rets, 0, -3);
583
        return;
584
    }
585

  
586
    QLIST_FOREACH(qdev, &bus->bus.children, sibling) {
587
        dev = (VIOsPAPRDevice *)qdev;
588
        spapr_vio_quiesce_one(dev);
589
    }
590

  
591
    rtas_st(rets, 0, 0);
592
}
593

  
516 594
static int spapr_vio_busdev_init(DeviceState *qdev, DeviceInfo *qinfo)
517 595
{
518 596
    VIOsPAPRDeviceInfo *info = (VIOsPAPRDeviceInfo *)qinfo;
......
591 669
    spapr_register_hypercall(H_SEND_CRQ, h_send_crq);
592 670
    spapr_register_hypercall(H_ENABLE_CRQ, h_enable_crq);
593 671

  
672
    /* RTAS calls */
673
    spapr_rtas_register("ibm,set-tce-bypass", rtas_set_tce_bypass);
674
    spapr_rtas_register("quiesce", rtas_quiesce);
675

  
594 676
    for (qinfo = device_info_list; qinfo; qinfo = qinfo->next) {
595 677
        VIOsPAPRDeviceInfo *info = (VIOsPAPRDeviceInfo *)qinfo;
596 678

  
b/hw/spapr_vio.h
48 48
typedef struct VIOsPAPRDevice {
49 49
    DeviceState qdev;
50 50
    uint32_t reg;
51
    uint32_t flags;
52
#define VIO_PAPR_FLAG_DMA_BYPASS        0x1
51 53
    qemu_irq qirq;
52 54
    uint32_t vio_irq_num;
53 55
    target_ulong signal_state;
......
104 106
void spapr_vscsi_create(VIOsPAPRBus *bus, uint32_t reg,
105 107
                        qemu_irq qirq, uint32_t vio_irq_num);
106 108

  
109
int spapr_tce_set_bypass(uint32_t unit, uint32_t enable);
110
void spapr_vio_quiesce(void);
111

  
107 112
#endif /* _HW_SPAPR_VIO_H */

Also available in: Unified diff