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)); }
/* 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(); }
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); } }
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); }
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 */ }
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; } }