[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Qemu-devel] [PATCH v2 2/5] register: Add Register API
From: |
Peter Maydell |
Subject: |
Re: [Qemu-devel] [PATCH v2 2/5] register: Add Register API |
Date: |
Fri, 5 Apr 2013 10:26:33 +0100 |
On 5 April 2013 09:43, Peter Crosthwaite <address@hidden> wrote:
> This API provides some encapsulation of registers and factors our some
> common functionality to common code. Bits of device state (usually MMIO
> registers), often have all sorts of access restrictions and semantics
> associated with them. This API allow you to define what those
> restrictions are on a bit-by-bit basis.
> +void register_write(RegisterInfo *reg, uint64_t val, uint64_t we)
> +{
> + uint64_t old_val, new_val, test;
> + const RegisterAccessInfo *ac;
> + const RegisterAccessError *rae;
> +
> + assert(reg);
> +
> + ac = reg->access;
> + if (!ac || !ac->name) {
> + qemu_log_mask(LOG_GUEST_ERROR, "%s: write to undefined device state "
> + "(written value: %#" PRIx64 ")\n", reg->prefix, val);
> + return;
> + }
> +
> + uint32_t no_w0_mask = ac->ro | ac->w1c | ac->nw0 | ~we;
> + uint32_t no_w1_mask = ac->ro | ac->w1c | ac->nw1 | ~we;
> +
> + if (reg->debug) {
> + fprintf(stderr, "%s:%s: write of value %#" PRIx64 "\n", reg->prefix,
> + ac->name, val);
> + }
> +
> + if (qemu_loglevel_mask(LOG_GUEST_ERROR)) {
> + for (rae = ac->ge1; rae && rae->mask; rae++) {
> + test = val & rae->mask;
> + if (test) {
> + register_write_log(reg, 1, test, LOG_GUEST_ERROR,
> + "invalid", rae->reason);
> + }
> + }
> + for (rae = ac->ge0; rae && rae->mask; rae++) {
> + test = val & rae->mask;
> + if (test) {
> + register_write_log(reg, 0, test, LOG_GUEST_ERROR,
> + "invalid", rae->reason);
> + }
> + }
> + }
> +
> + if (qemu_loglevel_mask(LOG_UNIMP)) {
> + for (rae = ac->ui1; rae && rae->mask; rae++) {
> + test = val & rae->mask;
> + if (test) {
> + register_write_log(reg, 1, test, LOG_GUEST_ERROR,
> + "unimplmented", rae->reason);
> + }
> + }
> + for (rae = ac->ui0; rae && rae->mask; rae++) {
> + test = val & rae->mask;
> + if (test) {
> + register_write_log(reg, 0, test, LOG_GUEST_ERROR,
> + "unimplemented", rae->reason);
> + }
> + }
> + }
> +
> + assert(reg->data);
> + old_val = register_read_val(reg);
> +
> + new_val = val & ~(no_w1_mask & val);
> + new_val |= no_w1_mask & old_val & val;
> + new_val |= no_w0_mask & old_val & ~val;
> + new_val &= ~(val & ac->w1c);
> +
> + if (ac->pre_write) {
> + new_val = ac->pre_write(reg, new_val);
> + }
> + register_write_val(reg, new_val);
> + if (ac->post_write) {
> + ac->post_write(reg, new_val);
> + }
> +}
Wow, this feels pretty heavyweight for "write a register"...
-- PMM