static int vioapic_range(struct vcpu *v, unsigned long addr) { struct hvm_hw_vioapic *vioapic = domain_vioapic(v->domain); return ((addr >= vioapic->base_address && (addr < vioapic->base_address + VIOAPIC_MEM_LENGTH))); }
static unsigned long vioapic_read(struct vcpu *v, unsigned long addr, unsigned long length) { struct hvm_hw_vioapic *vioapic = domain_vioapic(v->domain); uint32_t result; HVM_DBG_LOG(DBG_LEVEL_IOAPIC, "addr %lx", addr); addr &= 0xff; switch ( addr ) { case VIOAPIC_REG_SELECT: result = vioapic->ioregsel; break; case VIOAPIC_REG_WINDOW: result = vioapic_read_indirect(vioapic, addr, length); break; default: result = 0; break; } return result; }
static void vioapic_write(struct vcpu *v, unsigned long addr, unsigned long length, unsigned long val) { struct hvm_hw_vioapic *vioapic = domain_vioapic(v->domain); addr &= 0xff; switch ( addr ) { case VIOAPIC_REG_SELECT: vioapic->ioregsel = val; break; case VIOAPIC_REG_WINDOW: vioapic_write_indirect(vioapic, addr, length, val); break; #if VIOAPIC_IS_IOSAPIC case VIOAPIC_REG_EOI: vioapic_update_EOI(v->domain, val); break; #endif default: break; } }
static int __init pvh_setup_acpi_madt(struct domain *d, paddr_t *addr) { struct acpi_table_madt *madt; struct acpi_table_header *table; struct acpi_madt_io_apic *io_apic; struct acpi_madt_local_x2apic *x2apic; acpi_status status; unsigned long size; unsigned int i, max_vcpus; int rc; /* Count number of interrupt overrides in the MADT. */ acpi_table_parse_madt(ACPI_MADT_TYPE_INTERRUPT_OVERRIDE, acpi_count_intr_ovr, UINT_MAX); /* Count number of NMI sources in the MADT. */ acpi_table_parse_madt(ACPI_MADT_TYPE_NMI_SOURCE, acpi_count_nmi_src, UINT_MAX); max_vcpus = dom0_max_vcpus(); /* Calculate the size of the crafted MADT. */ size = sizeof(*madt); size += sizeof(*io_apic) * nr_ioapics; size += sizeof(*intsrcovr) * acpi_intr_overrides; size += sizeof(*nmisrc) * acpi_nmi_sources; size += sizeof(*x2apic) * max_vcpus; madt = xzalloc_bytes(size); if ( !madt ) { printk("Unable to allocate memory for MADT table\n"); rc = -ENOMEM; goto out; } /* Copy the native MADT table header. */ status = acpi_get_table(ACPI_SIG_MADT, 0, &table); if ( !ACPI_SUCCESS(status) ) { printk("Failed to get MADT ACPI table, aborting.\n"); rc = -EINVAL; goto out; } madt->header = *table; madt->address = APIC_DEFAULT_PHYS_BASE; /* * NB: this is currently set to 4, which is the revision in the ACPI * spec 6.1. Sadly ACPICA doesn't provide revision numbers for the * tables described in the headers. */ madt->header.revision = min_t(unsigned char, table->revision, 4); /* Setup the IO APIC entries. */ io_apic = (void *)(madt + 1); for ( i = 0; i < nr_ioapics; i++ ) { io_apic->header.type = ACPI_MADT_TYPE_IO_APIC; io_apic->header.length = sizeof(*io_apic); io_apic->id = domain_vioapic(d, i)->id; io_apic->address = domain_vioapic(d, i)->base_address; io_apic->global_irq_base = domain_vioapic(d, i)->base_gsi; io_apic++; } x2apic = (void *)io_apic; for ( i = 0; i < max_vcpus; i++ ) { x2apic->header.type = ACPI_MADT_TYPE_LOCAL_X2APIC; x2apic->header.length = sizeof(*x2apic); x2apic->uid = i; x2apic->local_apic_id = i * 2; x2apic->lapic_flags = ACPI_MADT_ENABLED; x2apic++; } /* Setup interrupt overrides. */ intsrcovr = (void *)x2apic; acpi_table_parse_madt(ACPI_MADT_TYPE_INTERRUPT_OVERRIDE, acpi_set_intr_ovr, acpi_intr_overrides); /* Setup NMI sources. */ nmisrc = (void *)intsrcovr; acpi_table_parse_madt(ACPI_MADT_TYPE_NMI_SOURCE, acpi_set_nmi_src, acpi_nmi_sources); ASSERT(((void *)nmisrc - (void *)madt) == size); madt->header.length = size; /* * Calling acpi_tb_checksum here is a layering violation, but * introducing a wrapper for such simple usage seems overkill. */ madt->header.checksum -= acpi_tb_checksum(ACPI_CAST_PTR(u8, madt), size); /* Place the new MADT in guest memory space. */ if ( pvh_steal_ram(d, size, 0, GB(4), addr) ) { printk("Unable to find allocate guest RAM for MADT\n"); rc = -ENOMEM; goto out; } /* Mark this region as E820_ACPI. */ if ( pvh_add_mem_range(d, *addr, *addr + size, E820_ACPI) ) printk("Unable to add MADT region to memory map\n"); rc = hvm_copy_to_guest_phys(*addr, madt, size, d->vcpu[0]); if ( rc ) { printk("Unable to copy MADT into guest memory\n"); goto out; } rc = 0; out: xfree(madt); return rc; }