C-sparse
view release on metacpan or search on metacpan
src/sparse-0.4.4/perl/t/target-arm/helper.c view on Meta::CPAN
} else {
CPREG_FIELD32(env, ri) = value;
}
return 0;
}
static bool read_raw_cp_reg(CPUARMState *env, const ARMCPRegInfo *ri,
uint64_t *v)
{
/* Raw read of a coprocessor register (as needed for migration, etc)
* return true on success, false if the read is impossible for some reason.
*/
if (ri->type & ARM_CP_CONST) {
*v = ri->resetvalue;
} else if (ri->raw_readfn) {
return (ri->raw_readfn(env, ri, v) == 0);
} else if (ri->readfn) {
return (ri->readfn(env, ri, v) == 0);
} else {
if (ri->type & ARM_CP_64BIT) {
*v = CPREG_FIELD64(env, ri);
} else {
*v = CPREG_FIELD32(env, ri);
}
}
return true;
}
static bool write_raw_cp_reg(CPUARMState *env, const ARMCPRegInfo *ri,
int64_t v)
{
/* Raw write of a coprocessor register (as needed for migration, etc).
* Return true on success, false if the write is impossible for some reason.
* Note that constant registers are treated as write-ignored; the
* caller should check for success by whether a readback gives the
* value written.
*/
if (ri->type & ARM_CP_CONST) {
return true;
} else if (ri->raw_writefn) {
return (ri->raw_writefn(env, ri, v) == 0);
} else if (ri->writefn) {
return (ri->writefn(env, ri, v) == 0);
} else {
if (ri->type & ARM_CP_64BIT) {
CPREG_FIELD64(env, ri) = v;
} else {
CPREG_FIELD32(env, ri) = v;
}
}
return true;
}
bool write_cpustate_to_list(ARMCPU *cpu)
{
/* Write the coprocessor state from cpu->env to the (index,value) list. */
int i;
bool ok = true;
for (i = 0; i < cpu->cpreg_array_len; i++) {
uint32_t regidx = kvm_to_cpreg_id(cpu->cpreg_indexes[i]);
const ARMCPRegInfo *ri;
uint64_t v;
ri = get_arm_cp_reginfo(cpu, regidx);
if (!ri) {
ok = false;
continue;
}
if (ri->type & ARM_CP_NO_MIGRATE) {
continue;
}
if (!read_raw_cp_reg(&cpu->env, ri, &v)) {
ok = false;
continue;
}
cpu->cpreg_values[i] = v;
}
return ok;
}
bool write_list_to_cpustate(ARMCPU *cpu)
{
int i;
bool ok = true;
for (i = 0; i < cpu->cpreg_array_len; i++) {
uint32_t regidx = kvm_to_cpreg_id(cpu->cpreg_indexes[i]);
uint64_t v = cpu->cpreg_values[i];
uint64_t readback;
const ARMCPRegInfo *ri;
ri = get_arm_cp_reginfo(cpu, regidx);
if (!ri) {
ok = false;
continue;
}
if (ri->type & ARM_CP_NO_MIGRATE) {
continue;
}
/* Write value and confirm it reads back as written
* (to catch read-only registers and partially read-only
* registers where the incoming migration value doesn't match)
*/
if (!write_raw_cp_reg(&cpu->env, ri, v) ||
!read_raw_cp_reg(&cpu->env, ri, &readback) ||
readback != v) {
ok = false;
}
}
return ok;
}
static void add_cpreg_to_list(gpointer key, gpointer opaque)
{
ARMCPU *cpu = opaque;
uint64_t regidx;
const ARMCPRegInfo *ri;
regidx = *(uint32_t *)key;
ri = get_arm_cp_reginfo(cpu, regidx);
if (!(ri->type & ARM_CP_NO_MIGRATE)) {
cpu->cpreg_indexes[cpu->cpreg_array_len] = cpreg_to_kvm_id(regidx);
/* The value array need not be initialized at this point */
cpu->cpreg_array_len++;
}
}
static void count_cpreg(gpointer key, gpointer opaque)
{
ARMCPU *cpu = opaque;
uint64_t regidx;
const ARMCPRegInfo *ri;
regidx = *(uint32_t *)key;
ri = get_arm_cp_reginfo(cpu, regidx);
if (!(ri->type & ARM_CP_NO_MIGRATE)) {
cpu->cpreg_array_len++;
}
}
static gint cpreg_key_compare(gconstpointer a, gconstpointer b)
{
uint64_t aidx = cpreg_to_kvm_id(*(uint32_t *)a);
uint64_t bidx = cpreg_to_kvm_id(*(uint32_t *)b);
if (aidx > bidx) {
return 1;
}
if (aidx < bidx) {
return -1;
}
return 0;
}
static void cpreg_make_keylist(gpointer key, gpointer value, gpointer udata)
{
GList **plist = udata;
*plist = g_list_prepend(*plist, key);
}
void init_cpreg_list(ARMCPU *cpu)
{
/* Initialise the cpreg_tuples[] array based on the cp_regs hash.
* Note that we require cpreg_tuples[] to be sorted by key ID.
*/
GList *keys = NULL;
int arraylen;
g_hash_table_foreach(cpu->cp_regs, cpreg_make_keylist, &keys);
keys = g_list_sort(keys, cpreg_key_compare);
cpu->cpreg_array_len = 0;
g_list_foreach(keys, count_cpreg, cpu);
arraylen = cpu->cpreg_array_len;
cpu->cpreg_indexes = g_new(uint64_t, arraylen);
cpu->cpreg_values = g_new(uint64_t, arraylen);
cpu->cpreg_vmstate_indexes = g_new(uint64_t, arraylen);
cpu->cpreg_vmstate_values = g_new(uint64_t, arraylen);
cpu->cpreg_vmstate_array_len = cpu->cpreg_array_len;
cpu->cpreg_array_len = 0;
g_list_foreach(keys, add_cpreg_to_list, cpu);
assert(cpu->cpreg_array_len == arraylen);
g_list_free(keys);
}
static int dacr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
{
( run in 0.708 second using v1.01-cache-2.11-cpan-5735350b133 )