static void boot_cpu(unsigned int cpu) { unsigned int icr2 = SET_APIC_DEST_FIELD(LAPIC_ID(cpu)); /* Initialise shared variables. */ ap_cpuid = cpu; ap_callin = 0; wmb(); /* Wake up the secondary processor: INIT-SIPI-SIPI... */ lapic_wait_ready(); lapic_write(APIC_ICR2, icr2); lapic_write(APIC_ICR, APIC_DM_INIT); lapic_wait_ready(); lapic_write(APIC_ICR2, icr2); lapic_write(APIC_ICR, APIC_DM_STARTUP | (AP_BOOT_EIP >> 12)); lapic_wait_ready(); lapic_write(APIC_ICR2, icr2); lapic_write(APIC_ICR, APIC_DM_STARTUP | (AP_BOOT_EIP >> 12)); lapic_wait_ready(); /* * Wait for the secondary processor to complete initialisation. * Do not touch shared resources meanwhile. */ while ( !ap_callin ) cpu_relax(); /* Take the secondary processor offline. */ lapic_write(APIC_ICR2, icr2); lapic_write(APIC_ICR, APIC_DM_INIT); lapic_wait_ready(); }
static struct acpi_20_srat *construct_srat(void) { struct acpi_20_srat *srat; struct acpi_20_srat_processor *processor; struct acpi_20_srat_memory *memory; unsigned int size; void *p; unsigned int i; size = sizeof(*srat) + sizeof(*processor) * hvm_info->nr_vcpus + sizeof(*memory) * nr_vmemranges; p = mem_alloc(size, 16); if ( !p ) return NULL; srat = memset(p, 0, size); srat->header.signature = ACPI_2_0_SRAT_SIGNATURE; srat->header.revision = ACPI_2_0_SRAT_REVISION; fixed_strcpy(srat->header.oem_id, ACPI_OEM_ID); fixed_strcpy(srat->header.oem_table_id, ACPI_OEM_TABLE_ID); srat->header.oem_revision = ACPI_OEM_REVISION; srat->header.creator_id = ACPI_CREATOR_ID; srat->header.creator_revision = ACPI_CREATOR_REVISION; srat->table_revision = ACPI_SRAT_TABLE_REVISION; processor = (struct acpi_20_srat_processor *)(srat + 1); for ( i = 0; i < hvm_info->nr_vcpus; i++ ) { processor->type = ACPI_PROCESSOR_AFFINITY; processor->length = sizeof(*processor); processor->domain = vcpu_to_vnode[i]; processor->apic_id = LAPIC_ID(i); processor->flags = ACPI_LOCAL_APIC_AFFIN_ENABLED; processor++; } memory = (struct acpi_20_srat_memory *)processor; for ( i = 0; i < nr_vmemranges; i++ ) { memory->type = ACPI_MEMORY_AFFINITY; memory->length = sizeof(*memory); memory->domain = vmemrange[i].nid; memory->flags = ACPI_MEM_AFFIN_ENABLED; memory->base_address = vmemrange[i].start; memory->mem_length = vmemrange[i].end - vmemrange[i].start; memory++; } ASSERT(((unsigned long)memory) - ((unsigned long)p) == size); srat->header.length = size; set_checksum(srat, offsetof(struct acpi_header, checksum), size); return srat; }
/* fills in an MP processor entry for VCPU 'vcpu_id' */ static void fill_mp_proc_entry(struct mp_proc_entry *mppe, int vcpu_id) { mppe->type = ENTRY_TYPE_PROCESSOR; mppe->lapic_id = LAPIC_ID(vcpu_id); mppe->lapic_version = 0x11; mppe->cpu_flags = CPU_FLAG_ENABLED; if ( vcpu_id == 0 ) mppe->cpu_flags |= CPU_FLAG_BSP; mppe->cpu_signature = CPU_SIGNATURE; mppe->feature_flags = CPU_FEATURES; }
static void apic_setup(void) { /* Set the IOAPIC ID to the static value used in the MP/ACPI tables. */ ioapic_write(0x00, IOAPIC_ID); /* NMIs are delivered direct to the BSP. */ lapic_write(APIC_SPIV, APIC_SPIV_APIC_ENABLED | 0xFF); lapic_write(APIC_LVT0, (APIC_MODE_EXTINT << 8) | APIC_LVT_MASKED); lapic_write(APIC_LVT1, APIC_MODE_NMI << 8); /* 8259A ExtInts are delivered through IOAPIC pin 0 (Virtual Wire Mode). */ ioapic_write(0x10, APIC_DM_EXTINT); ioapic_write(0x11, SET_APIC_ID(LAPIC_ID(0))); }
static void apic_setup(void) { /* * This would the The Right Thing To Do (tm), if only qemu negotiated * with Xen where the IO-APIC actually sits (which is currently hard * coded in Xen and can't be controlled externally). Uncomment this code * once that changed. ioapic_base_address |= (pci_readb(PCI_ISA_DEVFN, 0x80) & 0x3f) << 10; */ ioapic_version = ioapic_read(0x01) & 0xff; /* Set the IOAPIC ID to the static value used in the MP/ACPI tables. */ ioapic_write(0x00, IOAPIC_ID); /* NMIs are delivered direct to the BSP. */ lapic_write(APIC_SPIV, APIC_SPIV_APIC_ENABLED | 0xFF); lapic_write(APIC_LVT0, (APIC_MODE_EXTINT << 8) | APIC_LVT_MASKED); lapic_write(APIC_LVT1, APIC_MODE_NMI << 8); /* 8259A ExtInts are delivered through IOAPIC pin 0 (Virtual Wire Mode). */ ioapic_write(0x10, APIC_DM_EXTINT); ioapic_write(0x11, SET_APIC_ID(LAPIC_ID(0))); }
static struct acpi_20_madt *construct_madt(struct acpi_info *info) { struct acpi_20_madt *madt; struct acpi_20_madt_intsrcovr *intsrcovr; struct acpi_20_madt_ioapic *io_apic; struct acpi_20_madt_lapic *lapic; int i, sz; sz = sizeof(struct acpi_20_madt); sz += sizeof(struct acpi_20_madt_intsrcovr) * 16; sz += sizeof(struct acpi_20_madt_ioapic); sz += sizeof(struct acpi_20_madt_lapic) * hvm_info->nr_vcpus; madt = mem_alloc(sz, 16); if (!madt) return NULL; memset(madt, 0, sizeof(*madt)); madt->header.signature = ACPI_2_0_MADT_SIGNATURE; madt->header.revision = ACPI_2_0_MADT_REVISION; fixed_strcpy(madt->header.oem_id, ACPI_OEM_ID); fixed_strcpy(madt->header.oem_table_id, ACPI_OEM_TABLE_ID); madt->header.oem_revision = ACPI_OEM_REVISION; madt->header.creator_id = ACPI_CREATOR_ID; madt->header.creator_revision = ACPI_CREATOR_REVISION; madt->lapic_addr = LAPIC_BASE_ADDRESS; madt->flags = ACPI_PCAT_COMPAT; intsrcovr = (struct acpi_20_madt_intsrcovr *)(madt + 1); for ( i = 0; i < 16; i++ ) { memset(intsrcovr, 0, sizeof(*intsrcovr)); intsrcovr->type = ACPI_INTERRUPT_SOURCE_OVERRIDE; intsrcovr->length = sizeof(*intsrcovr); intsrcovr->source = i; if ( i == 0 ) { /* ISA IRQ0 routed to IOAPIC GSI 2. */ intsrcovr->gsi = 2; intsrcovr->flags = 0x0; } else if ( PCI_ISA_IRQ_MASK & (1U << i) ) { /* PCI: active-low level-triggered. */ intsrcovr->gsi = i; intsrcovr->flags = 0xf; } else { /* No need for a INT source override structure. */ continue; } intsrcovr++; } io_apic = (struct acpi_20_madt_ioapic *)intsrcovr; memset(io_apic, 0, sizeof(*io_apic)); io_apic->type = ACPI_IO_APIC; io_apic->length = sizeof(*io_apic); io_apic->ioapic_id = IOAPIC_ID; io_apic->ioapic_addr = ioapic_base_address; lapic = (struct acpi_20_madt_lapic *)(io_apic + 1); info->nr_cpus = hvm_info->nr_vcpus; info->madt_lapic0_addr = (uint32_t)lapic; for ( i = 0; i < hvm_info->nr_vcpus; i++ ) { memset(lapic, 0, sizeof(*lapic)); lapic->type = ACPI_PROCESSOR_LOCAL_APIC; lapic->length = sizeof(*lapic); /* Processor ID must match processor-object IDs in the DSDT. */ lapic->acpi_processor_id = i; lapic->apic_id = LAPIC_ID(i); lapic->flags = (test_bit(i, hvm_info->vcpu_online) ? ACPI_LOCAL_APIC_ENABLED : 0); lapic++; } madt->header.length = (unsigned char *)lapic - (unsigned char *)madt; set_checksum(madt, offsetof(struct acpi_header, checksum), madt->header.length); info->madt_csum_addr = (uint32_t)&madt->header.checksum; return madt; }