uint64_t ptimer_get_count(ptimer_state *s) { uint64_t counter; if (s->enabled) { int64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); int64_t next = s->next_event; bool expired = (now - next >= 0); bool oneshot = (s->enabled == 2); /* Figure out the current counter value. */ if (expired) { /* Prevent timer underflowing if it should already have triggered. */ counter = 0; } else { uint64_t rem; uint64_t div; int clz1, clz2; int shift; uint32_t period_frac = s->period_frac; uint64_t period = s->period; if (!oneshot && (s->delta * period < 10000) && !use_icount) { period = 10000 / s->delta; period_frac = 0; } /* We need to divide time by period, where time is stored in rem (64-bit integer) and period is stored in period/period_frac (64.32 fixed point). Doing full precision division is hard, so scale values and do a 64-bit division. The result should be rounded down, so that the rounding error never causes the timer to go backwards. */ rem = next - now; div = period; clz1 = clz64(rem); clz2 = clz64(div); shift = clz1 < clz2 ? clz1 : clz2; rem <<= shift; div <<= shift; if (shift >= 32) { div |= ((uint64_t)period_frac << (shift - 32)); } else { if (shift != 0) div |= (period_frac >> (32 - shift)); /* Look at remaining bits of period_frac and round div up if necessary. */ if ((uint32_t)(period_frac << shift)) div += 1; } counter = rem / div; } } else {
unsigned StdpProcess::closestPostFire(uint64_t arrivals) const { uint64_t validArrivals = arrivals & m_postPreBits; int dt = clz64(validArrivals << uint64_t(64 - m_postPreWindow)); return validArrivals ? (unsigned) dt : STDP_NO_APPLICATION; }
/* calculate condition code for insert character under mask insn */ static uint32_t cc_calc_icm(uint64_t mask, uint64_t val) { if ((val & mask) == 0) { return 0; } else { int top = clz64(mask); if ((int64_t)(val << top) < 0) { return 1; } else { return 2; } } }
static uint32_t cc_calc_tm_64(uint64_t val, uint64_t mask) { uint64_t r = val & mask; if (r == 0) { return 0; } else if (r == mask) { return 3; } else { int top = clz64(mask); if ((int64_t)(val << top) < 0) { return 2; } else { return 1; } } }
/* count leading zeros, for find leftmost one */ uint64_t HELPER(clz)(uint64_t v) { return clz64(v); }
uint64_t HELPER(clz_i64)(uint64_t arg, uint64_t zero_val) { return arg ? clz64(arg) : zero_val; }
/* Metadata initial parser * * This loads all the metadata entry fields. This may cause additional * fields to be processed (e.g. parent locator, etc..). * * There are 5 Metadata items that are always required: * - File Parameters (block size, has a parent) * - Virtual Disk Size (size, in bytes, of the virtual drive) * - Page 83 Data (scsi page 83 guid) * - Logical Sector Size (logical sector size in bytes, either 512 or * 4096. We only support 512 currently) * - Physical Sector Size (512 or 4096) * * Also, if the File Parameters indicate this is a differencing file, * we must also look for the Parent Locator metadata item. */ static int vhdx_parse_metadata(BlockDriverState *bs, BDRVVHDXState *s) { int ret = 0; uint8_t *buffer; int offset = 0; uint32_t i = 0; VHDXMetadataTableEntry md_entry; buffer = qemu_blockalign(bs, VHDX_METADATA_TABLE_MAX_SIZE); ret = bdrv_pread(bs->file, s->metadata_rt.file_offset, buffer, VHDX_METADATA_TABLE_MAX_SIZE); if (ret < 0) { goto exit; } memcpy(&s->metadata_hdr, buffer, sizeof(s->metadata_hdr)); offset += sizeof(s->metadata_hdr); le64_to_cpus(&s->metadata_hdr.signature); le16_to_cpus(&s->metadata_hdr.reserved); le16_to_cpus(&s->metadata_hdr.entry_count); if (memcmp(&s->metadata_hdr.signature, "metadata", 8)) { ret = -EINVAL; goto exit; } s->metadata_entries.present = 0; if ((s->metadata_hdr.entry_count * sizeof(md_entry)) > (VHDX_METADATA_TABLE_MAX_SIZE - offset)) { ret = -EINVAL; goto exit; } for (i = 0; i < s->metadata_hdr.entry_count; i++) { memcpy(&md_entry, buffer + offset, sizeof(md_entry)); offset += sizeof(md_entry); leguid_to_cpus(&md_entry.item_id); le32_to_cpus(&md_entry.offset); le32_to_cpus(&md_entry.length); le32_to_cpus(&md_entry.data_bits); le32_to_cpus(&md_entry.reserved2); if (guid_eq(md_entry.item_id, file_param_guid)) { if (s->metadata_entries.present & META_FILE_PARAMETER_PRESENT) { ret = -EINVAL; goto exit; } s->metadata_entries.file_parameters_entry = md_entry; s->metadata_entries.present |= META_FILE_PARAMETER_PRESENT; continue; } if (guid_eq(md_entry.item_id, virtual_size_guid)) { if (s->metadata_entries.present & META_VIRTUAL_DISK_SIZE_PRESENT) { ret = -EINVAL; goto exit; } s->metadata_entries.virtual_disk_size_entry = md_entry; s->metadata_entries.present |= META_VIRTUAL_DISK_SIZE_PRESENT; continue; } if (guid_eq(md_entry.item_id, page83_guid)) { if (s->metadata_entries.present & META_PAGE_83_PRESENT) { ret = -EINVAL; goto exit; } s->metadata_entries.page83_data_entry = md_entry; s->metadata_entries.present |= META_PAGE_83_PRESENT; continue; } if (guid_eq(md_entry.item_id, logical_sector_guid)) { if (s->metadata_entries.present & META_LOGICAL_SECTOR_SIZE_PRESENT) { ret = -EINVAL; goto exit; } s->metadata_entries.logical_sector_size_entry = md_entry; s->metadata_entries.present |= META_LOGICAL_SECTOR_SIZE_PRESENT; continue; } if (guid_eq(md_entry.item_id, phys_sector_guid)) { if (s->metadata_entries.present & META_PHYS_SECTOR_SIZE_PRESENT) { ret = -EINVAL; goto exit; } s->metadata_entries.phys_sector_size_entry = md_entry; s->metadata_entries.present |= META_PHYS_SECTOR_SIZE_PRESENT; continue; } if (guid_eq(md_entry.item_id, parent_locator_guid)) { if (s->metadata_entries.present & META_PARENT_LOCATOR_PRESENT) { ret = -EINVAL; goto exit; } s->metadata_entries.parent_locator_entry = md_entry; s->metadata_entries.present |= META_PARENT_LOCATOR_PRESENT; continue; } if (md_entry.data_bits & VHDX_META_FLAGS_IS_REQUIRED) { /* cannot read vhdx file - required region table entry that * we do not understand. per spec, we must fail to open */ ret = -ENOTSUP; goto exit; } } if (s->metadata_entries.present != META_ALL_PRESENT) { ret = -ENOTSUP; goto exit; } ret = bdrv_pread(bs->file, s->metadata_entries.file_parameters_entry.offset + s->metadata_rt.file_offset, &s->params, sizeof(s->params)); if (ret < 0) { goto exit; } le32_to_cpus(&s->params.block_size); le32_to_cpus(&s->params.data_bits); /* We now have the file parameters, so we can tell if this is a * differencing file (i.e.. has_parent), is dynamic or fixed * sized (leave_blocks_allocated), and the block size */ /* The parent locator required iff the file parameters has_parent set */ if (s->params.data_bits & VHDX_PARAMS_HAS_PARENT) { if (s->metadata_entries.present & META_PARENT_LOCATOR_PRESENT) { /* TODO: parse parent locator fields */ ret = -ENOTSUP; /* temp, until differencing files are supported */ goto exit; } else { /* if has_parent is set, but there is not parent locator present, * then that is an invalid combination */ ret = -EINVAL; goto exit; } } /* determine virtual disk size, logical sector size, * and phys sector size */ ret = bdrv_pread(bs->file, s->metadata_entries.virtual_disk_size_entry.offset + s->metadata_rt.file_offset, &s->virtual_disk_size, sizeof(uint64_t)); if (ret < 0) { goto exit; } ret = bdrv_pread(bs->file, s->metadata_entries.logical_sector_size_entry.offset + s->metadata_rt.file_offset, &s->logical_sector_size, sizeof(uint32_t)); if (ret < 0) { goto exit; } ret = bdrv_pread(bs->file, s->metadata_entries.phys_sector_size_entry.offset + s->metadata_rt.file_offset, &s->physical_sector_size, sizeof(uint32_t)); if (ret < 0) { goto exit; } le64_to_cpus(&s->virtual_disk_size); le32_to_cpus(&s->logical_sector_size); le32_to_cpus(&s->physical_sector_size); if (s->logical_sector_size == 0 || s->params.block_size == 0) { ret = -EINVAL; goto exit; } /* both block_size and sector_size are guaranteed powers of 2 */ s->sectors_per_block = s->params.block_size / s->logical_sector_size; s->chunk_ratio = (VHDX_MAX_SECTORS_PER_BLOCK) * (uint64_t)s->logical_sector_size / (uint64_t)s->params.block_size; /* These values are ones we will want to use for division / multiplication * later on, and they are all guaranteed (per the spec) to be powers of 2, * so we can take advantage of that for shift operations during * reads/writes */ if (s->logical_sector_size & (s->logical_sector_size - 1)) { ret = -EINVAL; goto exit; } if (s->sectors_per_block & (s->sectors_per_block - 1)) { ret = -EINVAL; goto exit; } if (s->chunk_ratio & (s->chunk_ratio - 1)) { ret = -EINVAL; goto exit; } s->block_size = s->params.block_size; if (s->block_size & (s->block_size - 1)) { ret = -EINVAL; goto exit; } s->logical_sector_size_bits = 31 - clz32(s->logical_sector_size); s->sectors_per_block_bits = 31 - clz32(s->sectors_per_block); s->chunk_ratio_bits = 63 - clz64(s->chunk_ratio); s->block_size_bits = 31 - clz32(s->block_size); ret = 0; exit: qemu_vfree(buffer); return ret; }
/* round down to the nearest power of 2*/ int64_t pow2floor(int64_t value) { if (!is_power_of_2(value)) { value = 0x8000000000000000ULL >> clz64(value); }
uint64_t HELPER(clz64)(uint64_t x) { return clz64(x); }