Revision b45d63b6

b/hw/spapr.c
67 67
    uint32_t end_prop = cpu_to_be32(initrd_base + initrd_size);
68 68
    uint32_t pft_size_prop[] = {0, cpu_to_be32(hash_shift)};
69 69
    char hypertas_prop[] = "hcall-pft\0hcall-term\0hcall-dabr\0hcall-interrupt"
70
        "\0hcall-tce";
70
        "\0hcall-tce\0hcall-vio";
71 71
    uint32_t interrupt_server_ranges_prop[] = {0, cpu_to_be32(smp_cpus)};
72 72
    int i;
73 73
    char *modelname;
b/hw/spapr_vio.c
28 28
#include "hw/sysbus.h"
29 29
#include "kvm.h"
30 30
#include "device_tree.h"
31
#include "kvm_ppc.h"
31 32

  
32 33
#include "hw/spapr.h"
33 34
#include "hw/spapr_vio.h"
......
359 360
    return tswap64(val);
360 361
}
361 362

  
363
/*
364
 * CRQ handling
365
 */
366
static target_ulong h_reg_crq(CPUState *env, sPAPREnvironment *spapr,
367
                              target_ulong opcode, target_ulong *args)
368
{
369
    target_ulong reg = args[0];
370
    target_ulong queue_addr = args[1];
371
    target_ulong queue_len = args[2];
372
    VIOsPAPRDevice *dev = spapr_vio_find_by_reg(spapr->vio_bus, reg);
373

  
374
    if (!dev) {
375
        hcall_dprintf("h_reg_crq on non-existent unit 0x"
376
                      TARGET_FMT_lx "\n", reg);
377
        return H_PARAMETER;
378
    }
379

  
380
    /* We can't grok a queue size bigger than 256M for now */
381
    if (queue_len < 0x1000 || queue_len > 0x10000000) {
382
        hcall_dprintf("h_reg_crq, queue size too small or too big (0x%llx)\n",
383
                      (unsigned long long)queue_len);
384
        return H_PARAMETER;
385
    }
386

  
387
    /* Check queue alignment */
388
    if (queue_addr & 0xfff) {
389
        hcall_dprintf("h_reg_crq, queue not aligned (0x%llx)\n",
390
                      (unsigned long long)queue_addr);
391
        return H_PARAMETER;
392
    }
393

  
394
    /* Check if device supports CRQs */
395
    if (!dev->crq.SendFunc) {
396
        return H_NOT_FOUND;
397
    }
398

  
399

  
400
    /* Already a queue ? */
401
    if (dev->crq.qsize) {
402
        return H_RESOURCE;
403
    }
404
    dev->crq.qladdr = queue_addr;
405
    dev->crq.qsize = queue_len;
406
    dev->crq.qnext = 0;
407

  
408
    dprintf("CRQ for dev 0x" TARGET_FMT_lx " registered at 0x"
409
            TARGET_FMT_lx "/0x" TARGET_FMT_lx "\n",
410
            reg, queue_addr, queue_len);
411
    return H_SUCCESS;
412
}
413

  
414
static target_ulong h_free_crq(CPUState *env, sPAPREnvironment *spapr,
415
                               target_ulong opcode, target_ulong *args)
416
{
417
    target_ulong reg = args[0];
418
    VIOsPAPRDevice *dev = spapr_vio_find_by_reg(spapr->vio_bus, reg);
419

  
420
    if (!dev) {
421
        hcall_dprintf("h_free_crq on non-existent unit 0x"
422
                      TARGET_FMT_lx "\n", reg);
423
        return H_PARAMETER;
424
    }
425

  
426
    dev->crq.qladdr = 0;
427
    dev->crq.qsize = 0;
428
    dev->crq.qnext = 0;
429

  
430
    dprintf("CRQ for dev 0x" TARGET_FMT_lx " freed\n", reg);
431

  
432
    return H_SUCCESS;
433
}
434

  
435
static target_ulong h_send_crq(CPUState *env, sPAPREnvironment *spapr,
436
                               target_ulong opcode, target_ulong *args)
437
{
438
    target_ulong reg = args[0];
439
    target_ulong msg_hi = args[1];
440
    target_ulong msg_lo = args[2];
441
    VIOsPAPRDevice *dev = spapr_vio_find_by_reg(spapr->vio_bus, reg);
442
    uint64_t crq_mangle[2];
443

  
444
    if (!dev) {
445
        hcall_dprintf("h_send_crq on non-existent unit 0x"
446
                      TARGET_FMT_lx "\n", reg);
447
        return H_PARAMETER;
448
    }
449
    crq_mangle[0] = cpu_to_be64(msg_hi);
450
    crq_mangle[1] = cpu_to_be64(msg_lo);
451

  
452
    if (dev->crq.SendFunc) {
453
        return dev->crq.SendFunc(dev, (uint8_t *)crq_mangle);
454
    }
455

  
456
    return H_HARDWARE;
457
}
458

  
459
static target_ulong h_enable_crq(CPUState *env, sPAPREnvironment *spapr,
460
                                 target_ulong opcode, target_ulong *args)
461
{
462
    target_ulong reg = args[0];
463
    VIOsPAPRDevice *dev = spapr_vio_find_by_reg(spapr->vio_bus, reg);
464

  
465
    if (!dev) {
466
        hcall_dprintf("h_enable_crq on non-existent unit 0x"
467
                      TARGET_FMT_lx "\n", reg);
468
        return H_PARAMETER;
469
    }
470

  
471
    return 0;
472
}
473

  
474
/* Returns negative error, 0 success, or positive: queue full */
475
int spapr_vio_send_crq(VIOsPAPRDevice *dev, uint8_t *crq)
476
{
477
    int rc;
478
    uint8_t byte;
479

  
480
    if (!dev->crq.qsize) {
481
        fprintf(stderr, "spapr_vio_send_creq on uninitialized queue\n");
482
        return -1;
483
    }
484

  
485
    /* Maybe do a fast path for KVM just writing to the pages */
486
    rc = spapr_tce_dma_read(dev, dev->crq.qladdr + dev->crq.qnext, &byte, 1);
487
    if (rc) {
488
        return rc;
489
    }
490
    if (byte != 0) {
491
        return 1;
492
    }
493

  
494
    rc = spapr_tce_dma_write(dev, dev->crq.qladdr + dev->crq.qnext + 8,
495
                             &crq[8], 8);
496
    if (rc) {
497
        return rc;
498
    }
499

  
500
    kvmppc_eieio();
501

  
502
    rc = spapr_tce_dma_write(dev, dev->crq.qladdr + dev->crq.qnext, crq, 8);
503
    if (rc) {
504
        return rc;
505
    }
506

  
507
    dev->crq.qnext = (dev->crq.qnext + 16) % dev->crq.qsize;
508

  
509
    if (dev->signal_state & 1) {
510
        qemu_irq_pulse(dev->qirq);
511
    }
512

  
513
    return 0;
514
}
515

  
362 516
static int spapr_vio_busdev_init(DeviceState *qdev, DeviceInfo *qinfo)
363 517
{
364 518
    VIOsPAPRDeviceInfo *info = (VIOsPAPRDeviceInfo *)qinfo;
......
431 585
    /* hcall-tce */
432 586
    spapr_register_hypercall(H_PUT_TCE, h_put_tce);
433 587

  
588
    /* hcall-crq */
589
    spapr_register_hypercall(H_REG_CRQ, h_reg_crq);
590
    spapr_register_hypercall(H_FREE_CRQ, h_free_crq);
591
    spapr_register_hypercall(H_SEND_CRQ, h_send_crq);
592
    spapr_register_hypercall(H_ENABLE_CRQ, h_enable_crq);
593

  
434 594
    for (qinfo = device_info_list; qinfo; qinfo = qinfo->next) {
435 595
        VIOsPAPRDeviceInfo *info = (VIOsPAPRDeviceInfo *)qinfo;
436 596

  
b/hw/spapr_vio.h
32 32
    SPAPR_TCE_RW = 3,
33 33
};
34 34

  
35
struct VIOsPAPRDevice;
36

  
35 37
typedef struct VIOsPAPR_RTCE {
36 38
    uint64_t tce;
37 39
} VIOsPAPR_RTCE;
38 40

  
41
typedef struct VIOsPAPR_CRQ {
42
    uint64_t qladdr;
43
    uint32_t qsize;
44
    uint32_t qnext;
45
    int(*SendFunc)(struct VIOsPAPRDevice *vdev, uint8_t *crq);
46
} VIOsPAPR_CRQ;
47

  
39 48
typedef struct VIOsPAPRDevice {
40 49
    DeviceState qdev;
41 50
    uint32_t reg;
......
44 53
    target_ulong signal_state;
45 54
    uint32_t rtce_window_size;
46 55
    VIOsPAPR_RTCE *rtce_table;
56
    VIOsPAPR_CRQ crq;
47 57
} VIOsPAPRDevice;
48 58

  
49 59
typedef struct VIOsPAPRBus {
......
81 91
void stq_tce(VIOsPAPRDevice *dev, uint64_t taddr, uint64_t val);
82 92
uint64_t ldq_tce(VIOsPAPRDevice *dev, uint64_t taddr);
83 93

  
94
int spapr_vio_send_crq(VIOsPAPRDevice *dev, uint8_t *crq);
95

  
84 96
void vty_putchars(VIOsPAPRDevice *sdev, uint8_t *buf, int len);
85 97
void spapr_vty_create(VIOsPAPRBus *bus,
86 98
                      uint32_t reg, CharDriverState *chardev,
b/target-ppc/kvm_ppc.h
18 18
int kvmppc_get_hypercall(CPUState *env, uint8_t *buf, int buf_len);
19 19
int kvmppc_set_interrupt(CPUState *env, int irq, int level);
20 20

  
21
#ifndef CONFIG_KVM
22
#define kvmppc_eieio() do { } while (0)
23
#else
24
#define kvmppc_eieio() \
25
    do {                                          \
26
        if (kvm_enabled()) {                          \
27
            asm volatile("eieio" : : : "memory"); \
28
        } \
29
    } while (0)
30
#endif
31

  
21 32
#ifndef KVM_INTERRUPT_SET
22 33
#define KVM_INTERRUPT_SET -1
23 34
#endif

Also available in: Unified diff