Exemple #1
0
static void amdvi_writel(AMDVIState *s, hwaddr addr, uint32_t val)
{
    uint32_t romask = ldl_le_p(&s->romask[addr]);
    uint32_t w1cmask = ldl_le_p(&s->w1cmask[addr]);
    uint32_t oldval = ldl_le_p(&s->mmior[addr]);
    stl_le_p(&s->mmior[addr],
            ((oldval & romask) | (val & ~romask)) & ~(val & w1cmask));
}
Exemple #2
0
/* warning: addr must be aligned */
static inline void glue(address_space_stl_internal, SUFFIX)(ARG1_DECL,
    hwaddr addr, uint32_t val, MemTxAttrs attrs,
    MemTxResult *result, enum device_endian endian)
{
    uint8_t *ptr;
    MemoryRegion *mr;
    hwaddr l = 4;
    hwaddr addr1;
    MemTxResult r;
    bool release_lock = false;

    RCU_READ_LOCK();
    mr = TRANSLATE(addr, &addr1, &l, true);
    if (l < 4 || !IS_DIRECT(mr, true)) {
        release_lock |= prepare_mmio_access(mr);

#if defined(TARGET_WORDS_BIGENDIAN)
        if (endian == DEVICE_LITTLE_ENDIAN) {
            val = bswap32(val);
        }
#else
        if (endian == DEVICE_BIG_ENDIAN) {
            val = bswap32(val);
        }
#endif
        r = memory_region_dispatch_write(mr, addr1, val, 4, attrs);
    } else {
        /* RAM case */
        ptr = MAP_RAM(mr, addr1);
        switch (endian) {
        case DEVICE_LITTLE_ENDIAN:
            stl_le_p(ptr, val);
            break;
        case DEVICE_BIG_ENDIAN:
            stl_be_p(ptr, val);
            break;
        default:
            stl_p(ptr, val);
            break;
        }
        INVALIDATE(mr, addr1, 4);
        r = MEMTX_OK;
    }
    if (result) {
        *result = r;
    }
    if (release_lock) {
        qemu_mutex_unlock_iothread();
    }
    RCU_READ_UNLOCK();
}
Exemple #3
0
static void flash_write(void *opaque, hwaddr offset, uint64_t value,
        unsigned int size)
{
    NRF51NVMState *s = NRF51_NVM(opaque);

    if (s->config & NRF51_NVMC_CONFIG_WEN) {
        uint32_t oldval;

        assert(offset + size <= s->flash_size);

        /* NOR Flash only allows bits to be flipped from 1's to 0's on write */
        oldval = ldl_le_p(s->storage + offset);
        oldval &= value;
        stl_le_p(s->storage + offset, oldval);

        memory_region_flush_rom_device(&s->flash, offset, size);
    } else {
        qemu_log_mask(LOG_GUEST_ERROR,
                "%s: Flash write 0x%" HWADDR_PRIx" while flash not writable.\n",
                __func__, offset);
    }
}
Exemple #4
0
static void virtio_crypto_get_config(VirtIODevice *vdev, uint8_t *config)
{
    VirtIOCrypto *c = VIRTIO_CRYPTO(vdev);
    struct virtio_crypto_config crypto_cfg = {};

    /*
     * Virtio-crypto device conforms to VIRTIO 1.0 which is always LE,
     * so we can use LE accessors directly.
     */
    stl_le_p(&crypto_cfg.status, c->status);
    stl_le_p(&crypto_cfg.max_dataqueues, c->max_queues);
    stl_le_p(&crypto_cfg.crypto_services, c->conf.crypto_services);
    stl_le_p(&crypto_cfg.cipher_algo_l, c->conf.cipher_algo_l);
    stl_le_p(&crypto_cfg.cipher_algo_h, c->conf.cipher_algo_h);
    stl_le_p(&crypto_cfg.hash_algo, c->conf.hash_algo);
    stl_le_p(&crypto_cfg.mac_algo_l, c->conf.mac_algo_l);
    stl_le_p(&crypto_cfg.mac_algo_h, c->conf.mac_algo_h);
    stl_le_p(&crypto_cfg.aead_algo, c->conf.aead_algo);
    stl_le_p(&crypto_cfg.max_cipher_key_len, c->conf.max_cipher_key_len);
    stl_le_p(&crypto_cfg.max_auth_key_len, c->conf.max_auth_key_len);
    stq_le_p(&crypto_cfg.max_size, c->conf.max_size);

    memcpy(config, &crypto_cfg, c->config_size);
}
Exemple #5
0
static void virtio_crypto_handle_ctrl(VirtIODevice *vdev, VirtQueue *vq)
{
    VirtIOCrypto *vcrypto = VIRTIO_CRYPTO(vdev);
    struct virtio_crypto_op_ctrl_req ctrl;
    VirtQueueElement *elem;
    struct iovec *in_iov;
    struct iovec *out_iov;
    unsigned in_num;
    unsigned out_num;
    uint32_t queue_id;
    uint32_t opcode;
    struct virtio_crypto_session_input input;
    int64_t session_id;
    uint8_t status;
    size_t s;

    for (;;) {
        elem = virtqueue_pop(vq, sizeof(VirtQueueElement));
        if (!elem) {
            break;
        }
        if (elem->out_num < 1 || elem->in_num < 1) {
            virtio_error(vdev, "virtio-crypto ctrl missing headers");
            virtqueue_detach_element(vq, elem, 0);
            g_free(elem);
            break;
        }

        out_num = elem->out_num;
        out_iov = elem->out_sg;
        in_num = elem->in_num;
        in_iov = elem->in_sg;
        if (unlikely(iov_to_buf(out_iov, out_num, 0, &ctrl, sizeof(ctrl))
                    != sizeof(ctrl))) {
            virtio_error(vdev, "virtio-crypto request ctrl_hdr too short");
            virtqueue_detach_element(vq, elem, 0);
            g_free(elem);
            break;
        }
        iov_discard_front(&out_iov, &out_num, sizeof(ctrl));

        opcode = ldl_le_p(&ctrl.header.opcode);
        queue_id = ldl_le_p(&ctrl.header.queue_id);

        switch (opcode) {
        case VIRTIO_CRYPTO_CIPHER_CREATE_SESSION:
            memset(&input, 0, sizeof(input));
            session_id = virtio_crypto_create_sym_session(vcrypto,
                             &ctrl.u.sym_create_session,
                             queue_id, opcode,
                             out_iov, out_num);
            /* Serious errors, need to reset virtio crypto device */
            if (session_id == -EFAULT) {
                virtqueue_detach_element(vq, elem, 0);
                break;
            } else if (session_id == -VIRTIO_CRYPTO_NOTSUPP) {
                stl_le_p(&input.status, VIRTIO_CRYPTO_NOTSUPP);
            } else if (session_id == -VIRTIO_CRYPTO_ERR) {
                stl_le_p(&input.status, VIRTIO_CRYPTO_ERR);
            } else {
                /* Set the session id */
                stq_le_p(&input.session_id, session_id);
                stl_le_p(&input.status, VIRTIO_CRYPTO_OK);
            }

            s = iov_from_buf(in_iov, in_num, 0, &input, sizeof(input));
            if (unlikely(s != sizeof(input))) {
                virtio_error(vdev, "virtio-crypto input incorrect");
                virtqueue_detach_element(vq, elem, 0);
                break;
            }
            virtqueue_push(vq, elem, sizeof(input));
            virtio_notify(vdev, vq);
            break;
        case VIRTIO_CRYPTO_CIPHER_DESTROY_SESSION:
        case VIRTIO_CRYPTO_HASH_DESTROY_SESSION:
        case VIRTIO_CRYPTO_MAC_DESTROY_SESSION:
        case VIRTIO_CRYPTO_AEAD_DESTROY_SESSION:
            status = virtio_crypto_handle_close_session(vcrypto,
                   &ctrl.u.destroy_session, queue_id);
            /* The status only occupy one byte, we can directly use it */
            s = iov_from_buf(in_iov, in_num, 0, &status, sizeof(status));
            if (unlikely(s != sizeof(status))) {
                virtio_error(vdev, "virtio-crypto status incorrect");
                virtqueue_detach_element(vq, elem, 0);
                break;
            }
            virtqueue_push(vq, elem, sizeof(status));
            virtio_notify(vdev, vq);
            break;
        case VIRTIO_CRYPTO_HASH_CREATE_SESSION:
        case VIRTIO_CRYPTO_MAC_CREATE_SESSION:
        case VIRTIO_CRYPTO_AEAD_CREATE_SESSION:
        default:
            error_report("virtio-crypto unsupported ctrl opcode: %d", opcode);
            memset(&input, 0, sizeof(input));
            stl_le_p(&input.status, VIRTIO_CRYPTO_NOTSUPP);
            s = iov_from_buf(in_iov, in_num, 0, &input, sizeof(input));
            if (unlikely(s != sizeof(input))) {
                virtio_error(vdev, "virtio-crypto input incorrect");
                virtqueue_detach_element(vq, elem, 0);
                break;
            }
            virtqueue_push(vq, elem, sizeof(input));
            virtio_notify(vdev, vq);

            break;
        } /* end switch case */

        g_free(elem);
    } /* end for loop */
}
Exemple #6
0
static void ppc440_pcix_reg_write4(void *opaque, hwaddr addr,
                                   uint64_t val, unsigned size)
{
    struct PPC440PCIXState *s = opaque;

    trace_ppc440_pcix_reg_read(addr, val);
    switch (addr) {
    case PCI_VENDOR_ID ... PCI_MAX_LAT:
        stl_le_p(s->dev->config + addr, val);
        break;

    case PCIX0_POM0LAL:
        s->pom[0].la &= 0xffffffff00000000ULL;
        s->pom[0].la |= val;
        ppc440_pcix_update_pom(s, 0);
        break;
    case PCIX0_POM0LAH:
        s->pom[0].la &= 0xffffffffULL;
        s->pom[0].la |= val << 32;
        ppc440_pcix_update_pom(s, 0);
        break;
    case PCIX0_POM0SA:
        s->pom[0].sa = val;
        ppc440_pcix_update_pom(s, 0);
        break;
    case PCIX0_POM0PCIAL:
        s->pom[0].pcia &= 0xffffffff00000000ULL;
        s->pom[0].pcia |= val;
        ppc440_pcix_update_pom(s, 0);
        break;
    case PCIX0_POM0PCIAH:
        s->pom[0].pcia &= 0xffffffffULL;
        s->pom[0].pcia |= val << 32;
        ppc440_pcix_update_pom(s, 0);
        break;
    case PCIX0_POM1LAL:
        s->pom[1].la &= 0xffffffff00000000ULL;
        s->pom[1].la |= val;
        ppc440_pcix_update_pom(s, 1);
        break;
    case PCIX0_POM1LAH:
        s->pom[1].la &= 0xffffffffULL;
        s->pom[1].la |= val << 32;
        ppc440_pcix_update_pom(s, 1);
        break;
    case PCIX0_POM1SA:
        s->pom[1].sa = val;
        ppc440_pcix_update_pom(s, 1);
        break;
    case PCIX0_POM1PCIAL:
        s->pom[1].pcia &= 0xffffffff00000000ULL;
        s->pom[1].pcia |= val;
        ppc440_pcix_update_pom(s, 1);
        break;
    case PCIX0_POM1PCIAH:
        s->pom[1].pcia &= 0xffffffffULL;
        s->pom[1].pcia |= val << 32;
        ppc440_pcix_update_pom(s, 1);
        break;
    case PCIX0_POM2SA:
        s->pom[2].sa = val;
        break;

    case PCIX0_PIM0SAL:
        s->pim[0].sa &= 0xffffffff00000000ULL;
        s->pim[0].sa |= val;
        ppc440_pcix_update_pim(s, 0);
        break;
    case PCIX0_PIM0LAL:
        s->pim[0].la &= 0xffffffff00000000ULL;
        s->pim[0].la |= val;
        ppc440_pcix_update_pim(s, 0);
        break;
    case PCIX0_PIM0LAH:
        s->pim[0].la &= 0xffffffffULL;
        s->pim[0].la |= val << 32;
        ppc440_pcix_update_pim(s, 0);
        break;
    case PCIX0_PIM1SA:
        s->pim[1].sa = val;
        ppc440_pcix_update_pim(s, 1);
        break;
    case PCIX0_PIM1LAL:
        s->pim[1].la &= 0xffffffff00000000ULL;
        s->pim[1].la |= val;
        ppc440_pcix_update_pim(s, 1);
        break;
    case PCIX0_PIM1LAH:
        s->pim[1].la &= 0xffffffffULL;
        s->pim[1].la |= val << 32;
        ppc440_pcix_update_pim(s, 1);
        break;
    case PCIX0_PIM2SAL:
        s->pim[2].sa &= 0xffffffff00000000ULL;
        s->pim[2].sa |= val;
        ppc440_pcix_update_pim(s, 2);
        break;
    case PCIX0_PIM2LAL:
        s->pim[2].la &= 0xffffffff00000000ULL;
        s->pim[2].la |= val;
        ppc440_pcix_update_pim(s, 2);
        break;
    case PCIX0_PIM2LAH:
        s->pim[2].la &= 0xffffffffULL;
        s->pim[2].la |= val << 32;
        ppc440_pcix_update_pim(s, 2);
        break;

    case PCIX0_STS:
        s->sts = val;
        break;

    case PCIX0_PIM0SAH:
        s->pim[0].sa &= 0xffffffffULL;
        s->pim[0].sa |= val << 32;
        ppc440_pcix_update_pim(s, 0);
        break;
    case PCIX0_PIM2SAH:
        s->pim[2].sa &= 0xffffffffULL;
        s->pim[2].sa |= val << 32;
        ppc440_pcix_update_pim(s, 2);
        break;

    default:
        qemu_log_mask(LOG_UNIMP,
                      "%s: unhandled PCI internal register 0x%"HWADDR_PRIx"\n",
                      __func__, addr);
        break;
    }
}