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 |
|