diff --git a/.gitignore b/.gitignore index d50ff905df..67ed7cb7b2 100644 --- a/.gitignore +++ b/.gitignore @@ -253,6 +253,10 @@ xen/arch/x86/efi.lds xen/arch/x86/efi/check.efi xen/arch/x86/efi/disabled xen/arch/x86/efi/mkreloc +xen/arch/*/efi/boot.c +xen/arch/*/efi/compat.c +xen/arch/*/efi/efi.h +xen/arch/*/efi/runtime.c xen/ddb/* xen/include/headers.chk xen/include/asm diff --git a/xen/Makefile b/xen/Makefile index 0e58bce91a..04f72e6c93 100644 --- a/xen/Makefile +++ b/xen/Makefile @@ -100,6 +100,9 @@ $(TARGET): delete-unfresh-files $(MAKE) -C tools $(MAKE) -f $(BASEDIR)/Rules.mk include/xen/compile.h [ -e include/asm ] || ln -sf asm-$(TARGET_ARCH) include/asm + [ -e arch/$(TARGET_ARCH)/efi ] && for f in boot.c runtime.c compat.c efi.h;\ + do ln -nsf ../../../common/efi/$$f arch/$(TARGET_ARCH)/efi/; done;\ + /bin/true $(MAKE) -f $(BASEDIR)/Rules.mk -C include $(MAKE) -f $(BASEDIR)/Rules.mk -C arch/$(TARGET_ARCH) asm-offsets.s $(MAKE) -f $(BASEDIR)/Rules.mk include/asm-$(TARGET_ARCH)/asm-offsets.h diff --git a/xen/arch/x86/efi/efi-boot.h b/xen/arch/x86/efi/efi-boot.h new file mode 100644 index 0000000000..2f032e0059 --- /dev/null +++ b/xen/arch/x86/efi/efi-boot.h @@ -0,0 +1,566 @@ +/* + * Architecture specific implementation for EFI boot code. This file + * is intended to be included by common/efi/boot.c _only_, and + * therefore can define arch specific global variables. + */ +#include +#include +#include +#include + +static struct file __initdata ucode; +static multiboot_info_t __initdata mbi = { + .flags = MBI_MODULES | MBI_LOADERNAME +}; +static module_t __initdata mb_modules[3]; + +static void __init edd_put_string(u8 *dst, size_t n, const char *src) +{ + while ( n-- && *src ) + *dst++ = *src++; + if ( *src ) + PrintErrMesg(L"Internal error populating EDD info", + EFI_BUFFER_TOO_SMALL); + while ( n-- ) + *dst++ = ' '; +} +#define edd_put_string(d, s) edd_put_string(d, ARRAY_SIZE(d), s) + +extern const intpte_t __page_tables_start[], __page_tables_end[]; +#define in_page_tables(v) ((intpte_t *)(v) >= __page_tables_start && \ + (intpte_t *)(v) < __page_tables_end) + +#define PE_BASE_RELOC_ABS 0 +#define PE_BASE_RELOC_HIGHLOW 3 +#define PE_BASE_RELOC_DIR64 10 + +extern const struct pe_base_relocs { + u32 rva; + u32 size; + u16 entries[]; +} __base_relocs_start[], __base_relocs_end[]; + +static void __init efi_arch_relocate_image(unsigned long delta) +{ + const struct pe_base_relocs *base_relocs; + + for ( base_relocs = __base_relocs_start; base_relocs < __base_relocs_end; ) + { + unsigned int i, n; + + n = (base_relocs->size - sizeof(*base_relocs)) / + sizeof(*base_relocs->entries); + for ( i = 0; i < n; ++i ) + { + unsigned long addr = xen_phys_start + base_relocs->rva + + (base_relocs->entries[i] & 0xfff); + + switch ( base_relocs->entries[i] >> 12 ) + { + case PE_BASE_RELOC_ABS: + break; + case PE_BASE_RELOC_HIGHLOW: + if ( delta ) + { + *(u32 *)addr += delta; + if ( in_page_tables(addr) ) + *(u32 *)addr += xen_phys_start; + } + break; + case PE_BASE_RELOC_DIR64: + if ( delta ) + { + *(u64 *)addr += delta; + if ( in_page_tables(addr) ) + *(intpte_t *)addr += xen_phys_start; + } + break; + default: + blexit(L"Unsupported relocation type"); + } + } + base_relocs = (const void *)(base_relocs->entries + i + (i & 1)); + } +} + +extern const s32 __trampoline_rel_start[], __trampoline_rel_stop[]; +extern const s32 __trampoline_seg_start[], __trampoline_seg_stop[]; + +static void __init relocate_trampoline(unsigned long phys) +{ + const s32 *trampoline_ptr; + + trampoline_phys = phys; + /* Apply relocations to trampoline. */ + for ( trampoline_ptr = __trampoline_rel_start; + trampoline_ptr < __trampoline_rel_stop; + ++trampoline_ptr ) + *(u32 *)(*trampoline_ptr + (long)trampoline_ptr) += phys; + for ( trampoline_ptr = __trampoline_seg_start; + trampoline_ptr < __trampoline_seg_stop; + ++trampoline_ptr ) + *(u16 *)(*trampoline_ptr + (long)trampoline_ptr) = phys >> 4; +} + +static void __init place_string(u32 *addr, const char *s) +{ + static char *__initdata alloc = start; + + if ( s && *s ) + { + size_t len1 = strlen(s) + 1; + const char *old = (char *)(long)*addr; + size_t len2 = *addr ? strlen(old) + 1 : 0; + + alloc -= len1 + len2; + /* + * Insert new string before already existing one. This is needed + * for options passed on the command line to override options from + * the configuration file. + */ + memcpy(alloc, s, len1); + if ( *addr ) + { + alloc[len1 - 1] = ' '; + memcpy(alloc + len1, old, len2); + } + } + *addr = (long)alloc; +} + +static void __init efi_arch_process_memory_map(EFI_SYSTEM_TABLE *SystemTable, + void *map, + UINTN map_size, + UINTN desc_size, + UINT32 desc_ver) +{ + struct e820entry *e; + unsigned int i; + + /* Populate E820 table and check trampoline area availability. */ + e = e820map - 1; + for ( i = 0; i < map_size; i += desc_size ) + { + EFI_MEMORY_DESCRIPTOR *desc = map + i; + u64 len = desc->NumberOfPages << EFI_PAGE_SHIFT; + u32 type; + + switch ( desc->Type ) + { + default: + type = E820_RESERVED; + break; + case EfiConventionalMemory: + case EfiBootServicesCode: + case EfiBootServicesData: + if ( !trampoline_phys && desc->PhysicalStart + len <= 0x100000 && + len >= cfg.size && desc->PhysicalStart + len > cfg.addr ) + cfg.addr = (desc->PhysicalStart + len - cfg.size) & PAGE_MASK; + /* fall through */ + case EfiLoaderCode: + case EfiLoaderData: + if ( desc->Attribute & EFI_MEMORY_WB ) + type = E820_RAM; + else + case EfiUnusableMemory: + type = E820_UNUSABLE; + break; + case EfiACPIReclaimMemory: + type = E820_ACPI; + break; + case EfiACPIMemoryNVS: + type = E820_NVS; + break; + } + if ( e820nr && type == e->type && + desc->PhysicalStart == e->addr + e->size ) + e->size += len; + else if ( !len || e820nr >= E820MAX ) + continue; + else + { + ++e; + e->addr = desc->PhysicalStart; + e->size = len; + e->type = type; + ++e820nr; + } + } + +} + +static void *__init efi_arch_allocate_mmap_buffer(UINTN map_size) +{ + place_string(&mbi.mem_upper, NULL); + mbi.mem_upper -= map_size; + mbi.mem_upper &= -__alignof__(EFI_MEMORY_DESCRIPTOR); + if ( mbi.mem_upper < xen_phys_start ) + return NULL; + return (void *)(long)mbi.mem_upper; +} + +static void __init efi_arch_pre_exit_boot(void) +{ + if ( !trampoline_phys ) + { + if ( !cfg.addr ) + blexit(L"No memory for trampoline"); + relocate_trampoline(cfg.addr); + } +} + +static void __init noreturn efi_arch_post_exit_boot(void) +{ + u64 efer; + + efi_arch_relocate_image(__XEN_VIRT_START - xen_phys_start); + memcpy((void *)trampoline_phys, trampoline_start, cfg.size); + + /* Set system registers and transfer control. */ + asm volatile("pushq $0\n\tpopfq"); + rdmsrl(MSR_EFER, efer); + efer |= EFER_SCE; + if ( cpuid_ext_features & (1 << (X86_FEATURE_NX & 0x1f)) ) + efer |= EFER_NX; + wrmsrl(MSR_EFER, efer); + write_cr0(X86_CR0_PE | X86_CR0_MP | X86_CR0_ET | X86_CR0_NE | X86_CR0_WP | + X86_CR0_AM | X86_CR0_PG); + asm volatile ( "mov %[cr4], %%cr4\n\t" + "mov %[cr3], %%cr3\n\t" + "movabs $__start_xen, %[rip]\n\t" + "lgdt gdt_descr(%%rip)\n\t" + "mov stack_start(%%rip), %%rsp\n\t" + "mov %[ds], %%ss\n\t" + "mov %[ds], %%ds\n\t" + "mov %[ds], %%es\n\t" + "mov %[ds], %%fs\n\t" + "mov %[ds], %%gs\n\t" + "movl %[cs], 8(%%rsp)\n\t" + "mov %[rip], (%%rsp)\n\t" + "lretq %[stkoff]-16" + : [rip] "=&r" (efer/* any dead 64-bit variable */) + : [cr3] "r" (idle_pg_table), + [cr4] "r" (mmu_cr4_features), + [cs] "ir" (__HYPERVISOR_CS), + [ds] "r" (__HYPERVISOR_DS), + [stkoff] "i" (STACK_SIZE - sizeof(struct cpu_info)), + "D" (&mbi) + : "memory" ); + for( ; ; ); /* not reached */ +} + +static void __init efi_arch_cfg_file_early(EFI_FILE_HANDLE dir_handle, char *section) +{ +} + +static void __init efi_arch_cfg_file_late(EFI_FILE_HANDLE dir_handle, char *section) +{ + union string name; + + name.s = get_value(&cfg, section, "ucode"); + if ( !name.s ) + name.s = get_value(&cfg, "global", "ucode"); + if ( name.s ) + { + microcode_set_module(mbi.mods_count); + split_value(name.s); + read_file(dir_handle, s2w(&name), &ucode); + efi_bs->FreePool(name.w); + } +} + +static void __init efi_arch_handle_cmdline(CHAR16 *image_name, + CHAR16 *cmdline_options, + char *cfgfile_options) +{ + union string name; + + if ( cmdline_options ) + { + name.w = cmdline_options; + w2s(&name); + place_string(&mbi.cmdline, name.s); + } + if ( cfgfile_options ) + place_string(&mbi.cmdline, cfgfile_options); + /* Insert image name last, as it gets prefixed to the other options. */ + if ( image_name ) + { + name.w = image_name; + w2s(&name); + } + else + name.s = "xen"; + place_string(&mbi.cmdline, name.s); + + if ( mbi.cmdline ) + mbi.flags |= MBI_CMDLINE; + /* + * These must not be initialized statically, since the value must + * not get relocated when processing base relocations later. + */ + mbi.boot_loader_name = (long)"EFI"; + mbi.mods_addr = (long)mb_modules; +} + +static void __init efi_arch_edd(void) +{ + static EFI_GUID __initdata bio_guid = BLOCK_IO_PROTOCOL; + static EFI_GUID __initdata devp_guid = DEVICE_PATH_PROTOCOL; + EFI_HANDLE *handles = NULL; + unsigned int i; + UINTN size; + EFI_STATUS status; + + /* Collect EDD info. */ + BUILD_BUG_ON(offsetof(struct edd_info, edd_device_params) != EDDEXTSIZE); + BUILD_BUG_ON(sizeof(struct edd_device_params) != EDDPARMSIZE); + size = 0; + status = efi_bs->LocateHandle(ByProtocol, &bio_guid, NULL, &size, NULL); + if ( status == EFI_BUFFER_TOO_SMALL ) + status = efi_bs->AllocatePool(EfiLoaderData, size, (void **)&handles); + if ( !EFI_ERROR(status) ) + status = efi_bs->LocateHandle(ByProtocol, &bio_guid, NULL, &size, + handles); + if ( EFI_ERROR(status) ) + size = 0; + for ( i = 0; i < size / sizeof(*handles); ++i ) + { + EFI_BLOCK_IO *bio; + EFI_DEV_PATH_PTR devp; + struct edd_info *info = boot_edd_info + boot_edd_info_nr; + struct edd_device_params *params = &info->edd_device_params; + enum { root, acpi, pci, ctrlr } state = root; + + status = efi_bs->HandleProtocol(handles[i], &bio_guid, (void **)&bio); + if ( EFI_ERROR(status) || + bio->Media->RemovableMedia || + bio->Media->LogicalPartition ) + continue; + if ( boot_edd_info_nr < EDD_INFO_MAX ) + { + info->device = 0x80 + boot_edd_info_nr; /* fake */ + info->version = 0x11; + params->length = offsetof(struct edd_device_params, dpte_ptr); + params->number_of_sectors = bio->Media->LastBlock + 1; + params->bytes_per_sector = bio->Media->BlockSize; + params->dpte_ptr = ~0; + } + ++boot_edd_info_nr; + status = efi_bs->HandleProtocol(handles[i], &devp_guid, + (void **)&devp); + if ( EFI_ERROR(status) ) + continue; + for ( ; !IsDevicePathEnd(devp.DevPath); + devp.DevPath = NextDevicePathNode(devp.DevPath) ) + { + switch ( DevicePathType(devp.DevPath) ) + { + const u8 *p; + + case ACPI_DEVICE_PATH: + if ( state != root || boot_edd_info_nr > EDD_INFO_MAX ) + break; + switch ( DevicePathSubType(devp.DevPath) ) + { + case ACPI_DP: + if ( devp.Acpi->HID != EISA_PNP_ID(0xA03) && + devp.Acpi->HID != EISA_PNP_ID(0xA08) ) + break; + params->interface_path.pci.bus = devp.Acpi->UID; + state = acpi; + break; + case EXPANDED_ACPI_DP: + /* XXX */ + break; + } + break; + case HARDWARE_DEVICE_PATH: + if ( state != acpi || + DevicePathSubType(devp.DevPath) != HW_PCI_DP || + boot_edd_info_nr > EDD_INFO_MAX ) + break; + state = pci; + edd_put_string(params->host_bus_type, "PCI"); + params->interface_path.pci.slot = devp.Pci->Device; + params->interface_path.pci.function = devp.Pci->Function; + break; + case MESSAGING_DEVICE_PATH: + if ( state != pci || boot_edd_info_nr > EDD_INFO_MAX ) + break; + state = ctrlr; + switch ( DevicePathSubType(devp.DevPath) ) + { + case MSG_ATAPI_DP: + edd_put_string(params->interface_type, "ATAPI"); + params->interface_path.pci.channel = + devp.Atapi->PrimarySecondary; + params->device_path.atapi.device = devp.Atapi->SlaveMaster; + params->device_path.atapi.lun = devp.Atapi->Lun; + break; + case MSG_SCSI_DP: + edd_put_string(params->interface_type, "SCSI"); + params->device_path.scsi.id = devp.Scsi->Pun; + params->device_path.scsi.lun = devp.Scsi->Lun; + break; + case MSG_FIBRECHANNEL_DP: + edd_put_string(params->interface_type, "FIBRE"); + params->device_path.fibre.wwid = devp.FibreChannel->WWN; + params->device_path.fibre.lun = devp.FibreChannel->Lun; + break; + case MSG_1394_DP: + edd_put_string(params->interface_type, "1394"); + params->device_path.i1394.eui = devp.F1394->Guid; + break; + case MSG_USB_DP: + case MSG_USB_CLASS_DP: + edd_put_string(params->interface_type, "USB"); + break; + case MSG_I2O_DP: + edd_put_string(params->interface_type, "I2O"); + params->device_path.i2o.identity_tag = devp.I2O->Tid; + break; + default: + continue; + } + info->version = 0x30; + params->length = sizeof(struct edd_device_params); + params->key = 0xbedd; + params->device_path_info_length = + sizeof(struct edd_device_params) - + offsetof(struct edd_device_params, key); + for ( p = (const u8 *)¶ms->key; p < ¶ms->checksum; ++p ) + params->checksum -= *p; + break; + case MEDIA_DEVICE_PATH: + if ( DevicePathSubType(devp.DevPath) == MEDIA_HARDDRIVE_DP && + devp.HardDrive->MBRType == MBR_TYPE_PCAT && + boot_mbr_signature_nr < EDD_MBR_SIG_MAX ) + { + struct mbr_signature *sig = boot_mbr_signature + + boot_mbr_signature_nr; + + sig->device = 0x80 + boot_edd_info_nr; /* fake */ + memcpy(&sig->signature, devp.HardDrive->Signature, + sizeof(sig->signature)); + ++boot_mbr_signature_nr; + } + break; + } + } + } + if ( handles ) + efi_bs->FreePool(handles); + if ( boot_edd_info_nr > EDD_INFO_MAX ) + boot_edd_info_nr = EDD_INFO_MAX; +} + +static void __init efi_arch_console_init(UINTN cols, UINTN rows) +{ + vga_console_info.video_type = XEN_VGATYPE_TEXT_MODE_3; + vga_console_info.u.text_mode_3.columns = cols; + vga_console_info.u.text_mode_3.rows = rows; + vga_console_info.u.text_mode_3.font_height = 16; +} + +static void __init efi_arch_video_init(EFI_GRAPHICS_OUTPUT_PROTOCOL *gop, + UINTN info_size, + EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *mode_info) +{ + int bpp = 0; + + switch ( mode_info->PixelFormat ) + { + case PixelRedGreenBlueReserved8BitPerColor: + vga_console_info.u.vesa_lfb.red_pos = 0; + vga_console_info.u.vesa_lfb.red_size = 8; + vga_console_info.u.vesa_lfb.green_pos = 8; + vga_console_info.u.vesa_lfb.green_size = 8; + vga_console_info.u.vesa_lfb.blue_pos = 16; + vga_console_info.u.vesa_lfb.blue_size = 8; + vga_console_info.u.vesa_lfb.rsvd_pos = 24; + vga_console_info.u.vesa_lfb.rsvd_size = 8; + bpp = 32; + break; + case PixelBlueGreenRedReserved8BitPerColor: + vga_console_info.u.vesa_lfb.red_pos = 16; + vga_console_info.u.vesa_lfb.red_size = 8; + vga_console_info.u.vesa_lfb.green_pos = 8; + vga_console_info.u.vesa_lfb.green_size = 8; + vga_console_info.u.vesa_lfb.blue_pos = 0; + vga_console_info.u.vesa_lfb.blue_size = 8; + vga_console_info.u.vesa_lfb.rsvd_pos = 24; + vga_console_info.u.vesa_lfb.rsvd_size = 8; + bpp = 32; + break; + case PixelBitMask: + bpp = set_color(mode_info->PixelInformation.RedMask, bpp, + &vga_console_info.u.vesa_lfb.red_pos, + &vga_console_info.u.vesa_lfb.red_size); + bpp = set_color(mode_info->PixelInformation.GreenMask, bpp, + &vga_console_info.u.vesa_lfb.green_pos, + &vga_console_info.u.vesa_lfb.green_size); + bpp = set_color(mode_info->PixelInformation.BlueMask, bpp, + &vga_console_info.u.vesa_lfb.blue_pos, + &vga_console_info.u.vesa_lfb.blue_size); + bpp = set_color(mode_info->PixelInformation.ReservedMask, bpp, + &vga_console_info.u.vesa_lfb.rsvd_pos, + &vga_console_info.u.vesa_lfb.rsvd_size); + if ( bpp > 0 ) + break; + /* fall through */ + default: + PrintErr(L"Current graphics mode is unsupported!\r\n"); + bpp = 0; + break; + } + if ( bpp > 0 ) + { + vga_console_info.video_type = XEN_VGATYPE_EFI_LFB; + vga_console_info.u.vesa_lfb.gbl_caps = 2; /* possibly non-VGA */ + vga_console_info.u.vesa_lfb.width = + mode_info->HorizontalResolution; + vga_console_info.u.vesa_lfb.height = mode_info->VerticalResolution; + vga_console_info.u.vesa_lfb.bits_per_pixel = bpp; + vga_console_info.u.vesa_lfb.bytes_per_line = + (mode_info->PixelsPerScanLine * bpp + 7) >> 3; + vga_console_info.u.vesa_lfb.lfb_base = gop->Mode->FrameBufferBase; + vga_console_info.u.vesa_lfb.lfb_size = + (gop->Mode->FrameBufferSize + 0xffff) >> 16; + } +} + +static void __init efi_arch_memory_setup(void) +{ + unsigned int i; + EFI_STATUS status; + + /* Allocate space for trampoline (in first Mb). */ + cfg.addr = 0x100000; + cfg.size = trampoline_end - trampoline_start; + status = efi_bs->AllocatePages(AllocateMaxAddress, EfiLoaderData, + PFN_UP(cfg.size), &cfg.addr); + if ( status == EFI_SUCCESS ) + relocate_trampoline(cfg.addr); + else + { + cfg.addr = 0; + PrintStr(L"Trampoline space cannot be allocated; will try fallback.\r\n"); + } + + /* Initialise L2 identity-map and boot-map page table entries (16MB). */ + for ( i = 0; i < 8; ++i ) + { + unsigned int slot = (xen_phys_start >> L2_PAGETABLE_SHIFT) + i; + paddr_t addr = slot << L2_PAGETABLE_SHIFT; + + l2_identmap[slot] = l2e_from_paddr(addr, PAGE_HYPERVISOR|_PAGE_PSE); + slot &= L2_PAGETABLE_ENTRIES - 1; + l2_bootmap[slot] = l2e_from_paddr(addr, __PAGE_HYPERVISOR|_PAGE_PSE); + } + /* Initialise L3 boot-map page directory entries. */ + l3_bootmap[l3_table_offset(xen_phys_start)] = + l3e_from_paddr((UINTN)l2_bootmap, __PAGE_HYPERVISOR); + l3_bootmap[l3_table_offset(xen_phys_start + (8 << L2_PAGETABLE_SHIFT) - 1)] = + l3e_from_paddr((UINTN)l2_bootmap, __PAGE_HYPERVISOR); +} diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c index 34f28d0fcd..9504ffc4b6 100644 --- a/xen/arch/x86/hvm/hvm.c +++ b/xen/arch/x86/hvm/hvm.c @@ -4504,7 +4504,8 @@ int hvm_msr_write_intercept(unsigned int msr, uint64_t msr_content) break; case MSR_IA32_APICBASE: - vlapic_msr_set(vcpu_vlapic(v), msr_content); + if ( !vlapic_msr_set(vcpu_vlapic(v), msr_content) ) + goto gp_fault; break; case MSR_IA32_TSC_DEADLINE: diff --git a/xen/arch/x86/hvm/vlapic.c b/xen/arch/x86/hvm/vlapic.c index 47c4eaa1a1..388e656baf 100644 --- a/xen/arch/x86/hvm/vlapic.c +++ b/xen/arch/x86/hvm/vlapic.c @@ -45,11 +45,11 @@ #define VLAPIC_LVT_NUM 6 #define LVT_MASK \ - APIC_LVT_MASKED | APIC_SEND_PENDING | APIC_VECTOR_MASK + (APIC_LVT_MASKED | APIC_SEND_PENDING | APIC_VECTOR_MASK) #define LINT_MASK \ - LVT_MASK | APIC_MODE_MASK | APIC_INPUT_POLARITY |\ - APIC_LVT_REMOTE_IRR | APIC_LVT_LEVEL_TRIGGER + (LVT_MASK | APIC_MODE_MASK | APIC_INPUT_POLARITY |\ + APIC_LVT_REMOTE_IRR | APIC_LVT_LEVEL_TRIGGER) static const unsigned int vlapic_lvt_mask[VLAPIC_LVT_NUM] = { @@ -123,10 +123,34 @@ static int vlapic_find_highest_irr(struct vlapic *vlapic) return vlapic_find_highest_vector(&vlapic->regs->data[APIC_IRR]); } +static void vlapic_error(struct vlapic *vlapic, unsigned int errmask) +{ + unsigned long flags; + uint32_t esr; + + spin_lock_irqsave(&vlapic->esr_lock, flags); + esr = vlapic_get_reg(vlapic, APIC_ESR); + if ( (esr & errmask) != errmask ) + { + uint32_t lvterr = vlapic_get_reg(vlapic, APIC_LVTERR); + + vlapic_set_reg(vlapic, APIC_ESR, esr | errmask); + if ( !(lvterr & APIC_LVT_MASKED) ) + vlapic_set_irq(vlapic, lvterr & APIC_VECTOR_MASK, 0); + } + spin_unlock_irqrestore(&vlapic->esr_lock, flags); +} + void vlapic_set_irq(struct vlapic *vlapic, uint8_t vec, uint8_t trig) { struct vcpu *target = vlapic_vcpu(vlapic); + if ( unlikely(vec < 16) ) + { + vlapic_error(vlapic, APIC_ESR_RECVILL); + return; + } + if ( trig ) vlapic_set_vector(vec, &vlapic->regs->data[APIC_TMR]); @@ -173,18 +197,18 @@ uint32_t vlapic_set_ppr(struct vlapic *vlapic) return ppr; } -static int vlapic_match_logical_addr(struct vlapic *vlapic, uint8_t mda) +static bool_t vlapic_match_logical_addr(const struct vlapic *vlapic, + uint32_t mda) { - int result = 0; - uint32_t logical_id; + bool_t result = 0; + uint32_t logical_id = vlapic_get_reg(vlapic, APIC_LDR); if ( vlapic_x2apic_mode(vlapic) ) - { - logical_id = vlapic_get_reg(vlapic, APIC_LDR); - return !!(logical_id & mda); - } + return ((logical_id >> 16) == (mda >> 16)) && + (uint16_t)(logical_id & mda); - logical_id = GET_xAPIC_LOGICAL_ID(vlapic_get_reg(vlapic, APIC_LDR)); + logical_id = GET_xAPIC_LOGICAL_ID(logical_id); + mda = (uint8_t)mda; switch ( vlapic_get_reg(vlapic, APIC_DFR) ) { @@ -197,9 +221,9 @@ static int vlapic_match_logical_addr(struct vlapic *vlapic, uint8_t mda) result = 1; break; default: - gdprintk(XENLOG_WARNING, "Bad DFR value for lapic of vcpu %d: %08x\n", - vlapic_vcpu(vlapic)->vcpu_id, - vlapic_get_reg(vlapic, APIC_DFR)); + printk(XENLOG_G_WARNING "%pv: bad LAPIC DFR value %08x\n", + const_vlapic_vcpu(vlapic), + vlapic_get_reg(vlapic, APIC_DFR)); break; } @@ -207,8 +231,8 @@ static int vlapic_match_logical_addr(struct vlapic *vlapic, uint8_t mda) } bool_t vlapic_match_dest( - struct vlapic *target, struct vlapic *source, - int short_hand, uint8_t dest, uint8_t dest_mode) + const struct vlapic *target, const struct vlapic *source, + int short_hand, uint32_t dest, bool_t dest_mode) { HVM_DBG_LOG(DBG_LEVEL_VLAPIC, "target %p, source %p, dest %#x, " "dest_mode %#x, short_hand %#x", @@ -219,7 +243,8 @@ bool_t vlapic_match_dest( case APIC_DEST_NOSHORT: if ( dest_mode ) return vlapic_match_logical_addr(target, dest); - return ((dest == 0xFF) || (dest == VLAPIC_ID(target))); + return (dest == _VLAPIC_ID(target, 0xffffffff)) || + (dest == VLAPIC_ID(target)); case APIC_DEST_SELF: return (target == source); @@ -286,7 +311,7 @@ static void vlapic_init_sipi_action(unsigned long _vcpu) uint32_t icr = vcpu_vlapic(origin)->init_sipi.icr; uint32_t dest = vcpu_vlapic(origin)->init_sipi.dest; uint32_t short_hand = icr & APIC_SHORT_MASK; - uint32_t dest_mode = !!(icr & APIC_DEST_MASK); + bool_t dest_mode = !!(icr & APIC_DEST_MASK); struct vcpu *v; if ( icr == 0 ) @@ -352,8 +377,8 @@ static void vlapic_accept_irq(struct vcpu *v, uint32_t icr_low) } struct vlapic *vlapic_lowest_prio( - struct domain *d, struct vlapic *source, - int short_hand, uint8_t dest, uint8_t dest_mode) + struct domain *d, const struct vlapic *source, + int short_hand, uint32_t dest, bool_t dest_mode) { int old = d->arch.hvm_domain.irq.round_robin_prev_vcpu; uint32_t ppr, target_ppr = UINT_MAX; @@ -434,13 +459,11 @@ void vlapic_ipi( { unsigned int dest; unsigned int short_hand = icr_low & APIC_SHORT_MASK; - unsigned int dest_mode = !!(icr_low & APIC_DEST_MASK); + bool_t dest_mode = !!(icr_low & APIC_DEST_MASK); HVM_DBG_LOG(DBG_LEVEL_VLAPIC, "icr = 0x%08x:%08x", icr_high, icr_low); - dest = (vlapic_x2apic_mode(vlapic) - ? icr_high - : GET_xAPIC_DEST_FIELD(icr_high)); + dest = _VLAPIC_ID(vlapic, icr_high); switch ( icr_low & APIC_MODE_MASK ) { @@ -461,7 +484,12 @@ void vlapic_ipi( struct vlapic *target = vlapic_lowest_prio( vlapic_domain(vlapic), vlapic, short_hand, dest, dest_mode); if ( target != NULL ) - vlapic_accept_irq(vlapic_vcpu(target), icr_low); + { + if ( likely((icr_low & APIC_VECTOR_MASK) >= 16) ) + vlapic_accept_irq(vlapic_vcpu(target), icr_low); + else + vlapic_error(vlapic, APIC_ESR_SENDILL); + } break; } @@ -469,6 +497,11 @@ void vlapic_ipi( struct vcpu *v; bool_t batch = is_multicast_dest(vlapic, short_hand, dest, dest_mode); + if ( unlikely((icr_low & APIC_VECTOR_MASK) < 16) ) + { + vlapic_error(vlapic, APIC_ESR_SENDILL); + break; + } if ( batch ) cpu_raise_softirq_batch_begin(); for_each_vcpu ( vlapic_domain(vlapic), v ) @@ -614,25 +647,24 @@ int hvm_x2apic_msr_read(struct vcpu *v, unsigned int msr, uint64_t *msr_content) uint32_t low, high = 0, offset = (msr - MSR_IA32_APICBASE_MSR) << 4; if ( !vlapic_x2apic_mode(vlapic) ) - return 1; + return X86EMUL_UNHANDLEABLE; vlapic_read_aligned(vlapic, offset, &low); switch ( offset ) { - case APIC_ID: - low = GET_xAPIC_ID(low); - break; - case APIC_ICR: vlapic_read_aligned(vlapic, APIC_ICR2, &high); break; + case APIC_EOI: case APIC_ICR2: - return 1; + case APIC_SELF_IPI: + return X86EMUL_UNHANDLEABLE; } *msr_content = (((uint64_t)high) << 32) | low; - return 0; + + return X86EMUL_OKAY; } static void vlapic_pt_cb(struct vcpu *v, void *data) @@ -653,13 +685,12 @@ static int vlapic_reg_write(struct vcpu *v, struct vlapic *vlapic = vcpu_vlapic(v); int rc = X86EMUL_OKAY; + memset(&vlapic->loaded, 0, sizeof(vlapic->loaded)); + switch ( offset ) { case APIC_ID: - if ( !vlapic_x2apic_mode(vlapic) ) - vlapic_set_reg(vlapic, APIC_ID, val); - else - rc = X86EMUL_UNHANDLEABLE; + vlapic_set_reg(vlapic, APIC_ID, val); break; case APIC_TASKPRI: @@ -671,17 +702,11 @@ static int vlapic_reg_write(struct vcpu *v, break; case APIC_LDR: - if ( !vlapic_x2apic_mode(vlapic) ) - vlapic_set_reg(vlapic, APIC_LDR, val & APIC_LDR_MASK); - else - rc = X86EMUL_UNHANDLEABLE; + vlapic_set_reg(vlapic, APIC_LDR, val & APIC_LDR_MASK); break; case APIC_DFR: - if ( !vlapic_x2apic_mode(vlapic) ) - vlapic_set_reg(vlapic, APIC_DFR, val | 0x0FFFFFFF); - else - rc = X86EMUL_UNHANDLEABLE; + vlapic_set_reg(vlapic, APIC_DFR, val | 0x0FFFFFFF); break; case APIC_SPIV: @@ -708,21 +733,6 @@ static int vlapic_reg_write(struct vcpu *v, } break; - case APIC_ESR: - if ( vlapic_x2apic_mode(vlapic) && (val != 0) ) - { - gdprintk(XENLOG_ERR, "Local APIC write ESR with non-zero %lx\n", - val); - rc = X86EMUL_UNHANDLEABLE; - } - break; - - case APIC_SELF_IPI: - rc = vlapic_x2apic_mode(vlapic) - ? vlapic_reg_write(v, APIC_ICR, 0x40000 | (val & 0xff)) - : X86EMUL_UNHANDLEABLE; - break; - case APIC_ICR: val &= ~(1 << 12); /* always clear the pending bit */ vlapic_ipi(vlapic, val, vlapic_get_reg(vlapic, APIC_ICR2)); @@ -730,9 +740,7 @@ static int vlapic_reg_write(struct vcpu *v, break; case APIC_ICR2: - if ( !vlapic_x2apic_mode(vlapic) ) - val &= 0xff000000; - vlapic_set_reg(vlapic, APIC_ICR2, val); + vlapic_set_reg(vlapic, APIC_ICR2, val & 0xff000000); break; case APIC_LVTT: /* LVT Timer Reg */ @@ -877,8 +885,17 @@ static int vlapic_write(struct vcpu *v, unsigned long address, int vlapic_apicv_write(struct vcpu *v, unsigned int offset) { - uint32_t val = vlapic_get_reg(vcpu_vlapic(v), offset); - return vlapic_reg_write(v, offset, val); + struct vlapic *vlapic = vcpu_vlapic(v); + uint32_t val = vlapic_get_reg(vlapic, offset); + + if ( !vlapic_x2apic_mode(vlapic) ) + return vlapic_reg_write(v, offset, val); + + if ( offset != APIC_SELF_IPI ) + return X86EMUL_UNHANDLEABLE; + + return vlapic_reg_write(v, APIC_ICR, + APIC_DEST_SELF | (val & APIC_VECTOR_MASK)); } int hvm_x2apic_msr_write(struct vcpu *v, unsigned int msr, uint64_t msr_content) @@ -891,16 +908,69 @@ int hvm_x2apic_msr_write(struct vcpu *v, unsigned int msr, uint64_t msr_content) switch ( offset ) { - int rc; - - case APIC_ICR: - rc = vlapic_reg_write(v, APIC_ICR2, (uint32_t)(msr_content >> 32)); - if ( rc ) - return rc; + case APIC_TASKPRI: + if ( msr_content & ~APIC_TPRI_MASK ) + return X86EMUL_UNHANDLEABLE; break; - case APIC_ICR2: - return X86EMUL_UNHANDLEABLE; + case APIC_SPIV: + if ( msr_content & ~(APIC_VECTOR_MASK | APIC_SPIV_APIC_ENABLED | + (VLAPIC_VERSION & APIC_LVR_DIRECTED_EOI + ? APIC_SPIV_DIRECTED_EOI : 0)) ) + return X86EMUL_UNHANDLEABLE; + break; + + case APIC_LVTT: + if ( msr_content & ~(LVT_MASK | APIC_TIMER_MODE_MASK) ) + return X86EMUL_UNHANDLEABLE; + break; + + case APIC_LVTTHMR: + case APIC_LVTPC: + case APIC_CMCI: + if ( msr_content & ~(LVT_MASK | APIC_MODE_MASK) ) + return X86EMUL_UNHANDLEABLE; + break; + + case APIC_LVT0: + case APIC_LVT1: + if ( msr_content & ~LINT_MASK ) + return X86EMUL_UNHANDLEABLE; + break; + + case APIC_LVTERR: + if ( msr_content & ~LVT_MASK ) + return X86EMUL_UNHANDLEABLE; + break; + + case APIC_TMICT: + break; + + case APIC_TDCR: + if ( msr_content & ~APIC_TDR_DIV_1 ) + return X86EMUL_UNHANDLEABLE; + break; + + case APIC_ICR: + if ( (uint32_t)msr_content & ~(APIC_VECTOR_MASK | APIC_MODE_MASK | + APIC_DEST_MASK | APIC_INT_ASSERT | + APIC_INT_LEVELTRIG | APIC_SHORT_MASK) ) + return X86EMUL_UNHANDLEABLE; + vlapic_set_reg(vlapic, APIC_ICR2, msr_content >> 32); + break; + + case APIC_SELF_IPI: + if ( msr_content & ~APIC_VECTOR_MASK ) + return X86EMUL_UNHANDLEABLE; + offset = APIC_ICR; + msr_content = APIC_DEST_SELF | (msr_content & APIC_VECTOR_MASK); + break; + + case APIC_EOI: + case APIC_ESR: + if ( msr_content ) + default: + return X86EMUL_UNHANDLEABLE; } return vlapic_reg_write(v, offset, (uint32_t)msr_content); @@ -910,7 +980,10 @@ static int vlapic_range(struct vcpu *v, unsigned long addr) { struct vlapic *vlapic = vcpu_vlapic(v); unsigned long offset = addr - vlapic_base_address(vlapic); - return (!vlapic_hw_disabled(vlapic) && (offset < PAGE_SIZE)); + + return !vlapic_hw_disabled(vlapic) && + !vlapic_x2apic_mode(vlapic) && + (offset < PAGE_SIZE); } const struct hvm_mmio_handler vlapic_mmio_handler = { @@ -919,10 +992,21 @@ const struct hvm_mmio_handler vlapic_mmio_handler = { .write_handler = vlapic_write }; -void vlapic_msr_set(struct vlapic *vlapic, uint64_t value) +static void set_x2apic_id(struct vlapic *vlapic) +{ + u32 id = vlapic_vcpu(vlapic)->vcpu_id; + u32 ldr = ((id & ~0xf) << 12) | (1 << (id & 0xf)); + + vlapic_set_reg(vlapic, APIC_ID, id * 2); + vlapic_set_reg(vlapic, APIC_LDR, ldr); +} + +bool_t vlapic_msr_set(struct vlapic *vlapic, uint64_t value) { if ( (vlapic->hw.apic_base_msr ^ value) & MSR_IA32_APICBASE_ENABLE ) { + if ( unlikely(value & MSR_IA32_APICBASE_EXTD) ) + return 0; if ( value & MSR_IA32_APICBASE_ENABLE ) { vlapic_reset(vlapic); @@ -931,24 +1015,28 @@ void vlapic_msr_set(struct vlapic *vlapic, uint64_t value) } else { + if ( unlikely(vlapic_x2apic_mode(vlapic)) ) + return 0; vlapic->hw.disabled |= VLAPIC_HW_DISABLED; pt_may_unmask_irq(vlapic_domain(vlapic), NULL); } } + else if ( !(value & MSR_IA32_APICBASE_ENABLE) && + unlikely(value & MSR_IA32_APICBASE_EXTD) ) + return 0; vlapic->hw.apic_base_msr = value; + memset(&vlapic->loaded, 0, sizeof(vlapic->loaded)); if ( vlapic_x2apic_mode(vlapic) ) - { - u32 id = vlapic_get_reg(vlapic, APIC_ID); - u32 ldr = ((id & ~0xf) << 16) | (1 << (id & 0xf)); - vlapic_set_reg(vlapic, APIC_LDR, ldr); - } + set_x2apic_id(vlapic); vmx_vlapic_msr_changed(vlapic_vcpu(vlapic)); HVM_DBG_LOG(DBG_LEVEL_VLAPIC, "apic base msr is 0x%016"PRIx64, vlapic->hw.apic_base_msr); + + return 1; } uint64_t vlapic_tdt_msr_get(struct vlapic *vlapic) @@ -1213,6 +1301,35 @@ static int lapic_save_regs(struct domain *d, hvm_domain_context_t *h) return rc; } +/* + * Following lapic_load_hidden()/lapic_load_regs() we may need to + * correct ID and LDR when they come from an old, broken hypervisor. + */ +static void lapic_load_fixup(struct vlapic *vlapic) +{ + uint32_t id = vlapic->loaded.id; + + if ( vlapic_x2apic_mode(vlapic) && id && vlapic->loaded.ldr == 1 ) + { + /* + * This is optional: ID != 0 contradicts LDR == 1. It's being added + * to aid in eventual debugging of issues arising from the fixup done + * here, but can be dropped as soon as it is found to conflict with + * other (future) changes. + */ + if ( GET_xAPIC_ID(id) != vlapic_vcpu(vlapic)->vcpu_id * 2 || + id != SET_xAPIC_ID(GET_xAPIC_ID(id)) ) + printk(XENLOG_G_WARNING "%pv: bogus APIC ID %#x loaded\n", + vlapic_vcpu(vlapic), id); + set_x2apic_id(vlapic); + } + else /* Undo an eventual earlier fixup. */ + { + vlapic_set_reg(vlapic, APIC_ID, id); + vlapic_set_reg(vlapic, APIC_LDR, vlapic->loaded.ldr); + } +} + static int lapic_load_hidden(struct domain *d, hvm_domain_context_t *h) { uint16_t vcpuid; @@ -1232,6 +1349,14 @@ static int lapic_load_hidden(struct domain *d, hvm_domain_context_t *h) if ( hvm_load_entry_zeroextend(LAPIC, h, &s->hw) != 0 ) return -EINVAL; + s->loaded.hw = 1; + if ( s->loaded.regs ) + lapic_load_fixup(s); + + if ( !(s->hw.apic_base_msr & MSR_IA32_APICBASE_ENABLE) && + unlikely(vlapic_x2apic_mode(s)) ) + return -EINVAL; + vmx_vlapic_msr_changed(v); return 0; @@ -1256,6 +1381,12 @@ static int lapic_load_regs(struct domain *d, hvm_domain_context_t *h) if ( hvm_load_entry(LAPIC_REGS, h, s->regs) != 0 ) return -EINVAL; + s->loaded.id = vlapic_get_reg(s, APIC_ID); + s->loaded.ldr = vlapic_get_reg(s, APIC_LDR); + s->loaded.regs = 1; + if ( s->loaded.hw ) + lapic_load_fixup(s); + if ( hvm_funcs.process_isr ) hvm_funcs.process_isr(vlapic_find_highest_isr(s), v); @@ -1307,6 +1438,8 @@ int vlapic_init(struct vcpu *v) if ( v->vcpu_id == 0 ) vlapic->hw.apic_base_msr |= MSR_IA32_APICBASE_BSP; + spin_lock_init(&vlapic->esr_lock); + tasklet_init(&vlapic->init_sipi.tasklet, vlapic_init_sipi_action, (unsigned long)v); diff --git a/xen/arch/x86/hvm/vmx/vmx.c b/xen/arch/x86/hvm/vmx/vmx.c index 923f0082ec..fd0ad59c04 100644 --- a/xen/arch/x86/hvm/vmx/vmx.c +++ b/xen/arch/x86/hvm/vmx/vmx.c @@ -3123,8 +3123,7 @@ void vmx_vmexit_handler(struct cpu_user_regs *regs) break; case EXIT_REASON_APIC_WRITE: - if ( vmx_handle_apic_write() ) - hvm_inject_hw_exception(TRAP_gp_fault, 0); + vmx_handle_apic_write(); break; case EXIT_REASON_ACCESS_GDTR_OR_IDTR: diff --git a/xen/arch/x86/efi/boot.c b/xen/common/efi/boot.c similarity index 65% rename from xen/arch/x86/efi/boot.c rename to xen/common/efi/boot.c index 6f345929f1..c9b5fdca83 100644 --- a/xen/arch/x86/efi/boot.c +++ b/xen/common/efi/boot.c @@ -18,13 +18,9 @@ #include #include #include -#include -#include #define __ASSEMBLY__ /* avoid pulling in ACPI stuff (conflicts with EFI) */ #include #undef __ASSEMBLY__ -#include -#include /* Using SetVirtualAddressMap() is incompatible with kexec: */ #undef USE_SET_VIRTUAL_ADDRESS_MAP @@ -41,9 +37,6 @@ typedef struct { EFI_SHIM_LOCK_VERIFY Verify; } EFI_SHIM_LOCK_PROTOCOL; -extern char start[]; -extern u32 cpuid_ext_features; - union string { CHAR16 *w; char *s; @@ -58,6 +51,21 @@ struct file { }; }; +static CHAR16 *FormatDec(UINT64 Val, CHAR16 *Buffer); +static CHAR16 *FormatHex(UINT64 Val, UINTN Width, CHAR16 *Buffer); +static void DisplayUint(UINT64 Val, INTN Width); +static CHAR16 *wstrcpy(CHAR16 *d, const CHAR16 *s); +static void noreturn blexit(const CHAR16 *str); +static void PrintErrMesg(const CHAR16 *mesg, EFI_STATUS ErrCode); +static char *get_value(const struct file *cfg, const char *section, + const char *item); +static void split_value(char *s); +static CHAR16 *s2w(union string *str); +static char *w2s(const union string *str); +static bool_t read_file(EFI_FILE_HANDLE dir_handle, CHAR16 *name, + struct file *file); +static int set_color(u32 mask, int bpp, u8 *pos, u8 *sz); + static EFI_BOOT_SERVICES *__initdata efi_bs; static EFI_HANDLE __initdata efi_ih; @@ -69,19 +77,18 @@ static UINT32 __initdata mdesc_ver; static struct file __initdata cfg; static struct file __initdata kernel; static struct file __initdata ramdisk; -static struct file __initdata ucode; static struct file __initdata xsm; - -static multiboot_info_t __initdata mbi = { - .flags = MBI_MODULES | MBI_LOADERNAME -}; -static module_t __initdata mb_modules[3]; - static CHAR16 __initdata newline[] = L"\r\n"; #define PrintStr(s) StdOut->OutputString(StdOut, s) #define PrintErr(s) StdErr->OutputString(StdErr, s) +/* + * Include architecture specific implementation here, which references the + * static globals defined above. + */ +#include "efi-boot.h" + static CHAR16 *__init FormatDec(UINT64 Val, CHAR16 *Buffer) { if ( Val >= 10 ) @@ -255,34 +262,9 @@ static void __init PrintErrMesg(const CHAR16 *mesg, EFI_STATUS ErrCode) blexit(mesg); } -static void __init place_string(u32 *addr, const char *s) -{ - static char *__initdata alloc = start; - - if ( s && *s ) - { - size_t len1 = strlen(s) + 1; - const char *old = (char *)(long)*addr; - size_t len2 = *addr ? strlen(old) + 1 : 0; - - alloc -= len1 + len2; - /* - * Insert new string before already existing one. This is needed - * for options passed on the command line to override options from - * the configuration file. - */ - memcpy(alloc, s, len1); - if ( *addr ) - { - alloc[len1 - 1] = ' '; - memcpy(alloc + len1, old, len2); - } - } - *addr = (long)alloc; -} - static unsigned int __init get_argv(unsigned int argc, CHAR16 **argv, - CHAR16 *cmdline, UINTN cmdsize) + CHAR16 *cmdline, UINTN cmdsize, + CHAR16 **options) { CHAR16 *ptr = (CHAR16 *)(argv + argc + 1), *prev = NULL; bool_t prev_sep = TRUE; @@ -308,10 +290,8 @@ static unsigned int __init get_argv(unsigned int argc, CHAR16 **argv, ++argc; else if ( prev && wstrcmp(prev, L"--") == 0 ) { - union string rest = { .w = cmdline }; - - --argv; - place_string(&mbi.cmdline, w2s(&rest)); + if ( options ) + *options = cmdline; break; } else @@ -574,18 +554,6 @@ static void __init split_value(char *s) *s = 0; } -static void __init edd_put_string(u8 *dst, size_t n, const char *src) -{ - while ( n-- && *src ) - *dst++ = *src++; - if ( *src ) - PrintErrMesg(L"Internal error populating EDD info", - EFI_BUFFER_TOO_SMALL); - while ( n-- ) - *dst++ = ' '; -} -#define edd_put_string(d, s) edd_put_string(d, ARRAY_SIZE(d), s) - static void __init setup_efi_pci(void) { EFI_STATUS status; @@ -688,94 +656,16 @@ static int __init set_color(u32 mask, int bpp, u8 *pos, u8 *sz) return max(*pos + *sz, bpp); } -extern const intpte_t __page_tables_start[], __page_tables_end[]; -#define in_page_tables(v) ((intpte_t *)(v) >= __page_tables_start && \ - (intpte_t *)(v) < __page_tables_end) - -#define PE_BASE_RELOC_ABS 0 -#define PE_BASE_RELOC_HIGHLOW 3 -#define PE_BASE_RELOC_DIR64 10 - -extern const struct pe_base_relocs { - u32 rva; - u32 size; - u16 entries[]; -} __base_relocs_start[], __base_relocs_end[]; - -static void __init relocate_image(unsigned long delta) -{ - const struct pe_base_relocs *base_relocs; - - for ( base_relocs = __base_relocs_start; base_relocs < __base_relocs_end; ) - { - unsigned int i, n; - - n = (base_relocs->size - sizeof(*base_relocs)) / - sizeof(*base_relocs->entries); - for ( i = 0; i < n; ++i ) - { - unsigned long addr = xen_phys_start + base_relocs->rva + - (base_relocs->entries[i] & 0xfff); - - switch ( base_relocs->entries[i] >> 12 ) - { - case PE_BASE_RELOC_ABS: - break; - case PE_BASE_RELOC_HIGHLOW: - if ( delta ) - { - *(u32 *)addr += delta; - if ( in_page_tables(addr) ) - *(u32 *)addr += xen_phys_start; - } - break; - case PE_BASE_RELOC_DIR64: - if ( delta ) - { - *(u64 *)addr += delta; - if ( in_page_tables(addr) ) - *(intpte_t *)addr += xen_phys_start; - } - break; - default: - blexit(L"Unsupported relocation type"); - } - } - base_relocs = (const void *)(base_relocs->entries + i + (i & 1)); - } -} - -extern const s32 __trampoline_rel_start[], __trampoline_rel_stop[]; -extern const s32 __trampoline_seg_start[], __trampoline_seg_stop[]; - -static void __init relocate_trampoline(unsigned long phys) -{ - const s32 *trampoline_ptr; - - trampoline_phys = phys; - /* Apply relocations to trampoline. */ - for ( trampoline_ptr = __trampoline_rel_start; - trampoline_ptr < __trampoline_rel_stop; - ++trampoline_ptr ) - *(u32 *)(*trampoline_ptr + (long)trampoline_ptr) += phys; - for ( trampoline_ptr = __trampoline_seg_start; - trampoline_ptr < __trampoline_seg_stop; - ++trampoline_ptr ) - *(u16 *)(*trampoline_ptr + (long)trampoline_ptr) = phys >> 4; -} - void EFIAPI __init noreturn efi_start(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable) { static EFI_GUID __initdata loaded_image_guid = LOADED_IMAGE_PROTOCOL; static EFI_GUID __initdata gop_guid = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID; - static EFI_GUID __initdata bio_guid = BLOCK_IO_PROTOCOL; - static EFI_GUID __initdata devp_guid = DEVICE_PATH_PROTOCOL; static EFI_GUID __initdata shim_lock_guid = SHIM_LOCK_PROTOCOL_GUID; EFI_LOADED_IMAGE *loaded_image; EFI_STATUS status; unsigned int i, argc; - CHAR16 **argv, *file_name, *cfg_file_name = NULL; + CHAR16 **argv, *file_name, *cfg_file_name = NULL, *options = NULL; UINTN cols, rows, depth, size, map_key, info_size, gop_mode = ~0; EFI_HANDLE *handles = NULL; EFI_SHIM_LOCK_PROTOCOL *shim_lock; @@ -783,8 +673,6 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable) EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *mode_info; EFI_FILE_HANDLE dir_handle; union string section = { NULL }, name; - struct e820entry *e; - u64 efer; bool_t base_video = 0; efi_ih = ImageHandle; @@ -815,14 +703,14 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable) dir_handle = get_parent_handle(loaded_image, &file_name); argc = get_argv(0, NULL, loaded_image->LoadOptions, - loaded_image->LoadOptionsSize); + loaded_image->LoadOptionsSize, NULL); if ( argc > 0 && efi_bs->AllocatePool(EfiLoaderData, (argc + 1) * sizeof(*argv) + loaded_image->LoadOptionsSize, (void **)&argv) == EFI_SUCCESS ) get_argv(argc, argv, loaded_image->LoadOptions, - loaded_image->LoadOptionsSize); + loaded_image->LoadOptionsSize, &options); else argc = 0; for ( i = 1; i < argc; ++i ) @@ -880,16 +768,11 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable) PrintStr(L"Xen " __stringify(XEN_VERSION) "." __stringify(XEN_SUBVERSION) XEN_EXTRAVERSION " (c/s " XEN_CHANGESET ") EFI loader\r\n"); - relocate_image(0); + efi_arch_relocate_image(0); if ( StdOut->QueryMode(StdOut, StdOut->Mode->Mode, &cols, &rows) == EFI_SUCCESS ) - { - vga_console_info.video_type = XEN_VGATYPE_TEXT_MODE_3; - vga_console_info.u.text_mode_3.columns = cols; - vga_console_info.u.text_mode_3.rows = rows; - vga_console_info.u.text_mode_3.font_height = 16; - } + efi_arch_console_init(cols, rows); size = 0; status = efi_bs->LocateHandle(ByProtocol, &gop_guid, NULL, &size, NULL); @@ -963,6 +846,9 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable) } if ( !name.s ) blexit(L"No Dom0 kernel image specified."); + + efi_arch_cfg_file_early(dir_handle, section.s); + split_value(name.s); read_file(dir_handle, s2w(&name), &kernel); efi_bs->FreePool(name.w); @@ -980,17 +866,6 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable) efi_bs->FreePool(name.w); } - name.s = get_value(&cfg, section.s, "ucode"); - if ( !name.s ) - name.s = get_value(&cfg, "global", "ucode"); - if ( name.s ) - { - microcode_set_module(mbi.mods_count); - split_value(name.s); - read_file(dir_handle, s2w(&name), &ucode); - efi_bs->FreePool(name.w); - } - name.s = get_value(&cfg, section.s, "xsm"); if ( name.s ) { @@ -1000,17 +875,7 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable) } name.s = get_value(&cfg, section.s, "options"); - if ( name.s ) - place_string(&mbi.cmdline, name.s); - /* Insert image name last, as it gets prefixed to the other options. */ - if ( argc ) - { - name.w = *argv; - w2s(&name); - } - else - name.s = "xen"; - place_string(&mbi.cmdline, name.s); + efi_arch_handle_cmdline(argc ? *argv : NULL, options, name.s); cols = rows = depth = 0; if ( !base_video ) @@ -1029,6 +894,7 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable) cols = rows = depth = 0; } } + efi_arch_cfg_file_late(dir_handle, section.s); efi_bs->FreePages(cfg.addr, PFN_UP(cfg.size)); cfg.addr = 0; @@ -1076,158 +942,7 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable) } } - if ( mbi.cmdline ) - mbi.flags |= MBI_CMDLINE; - /* - * These must not be initialized statically, since the value must - * not get relocated when processing base relocations below. - */ - mbi.boot_loader_name = (long)"EFI"; - mbi.mods_addr = (long)mb_modules; - - place_string(&mbi.mem_upper, NULL); - - /* Collect EDD info. */ - BUILD_BUG_ON(offsetof(struct edd_info, edd_device_params) != EDDEXTSIZE); - BUILD_BUG_ON(sizeof(struct edd_device_params) != EDDPARMSIZE); - size = 0; - status = efi_bs->LocateHandle(ByProtocol, &bio_guid, NULL, &size, NULL); - if ( status == EFI_BUFFER_TOO_SMALL ) - status = efi_bs->AllocatePool(EfiLoaderData, size, (void **)&handles); - if ( !EFI_ERROR(status) ) - status = efi_bs->LocateHandle(ByProtocol, &bio_guid, NULL, &size, - handles); - if ( EFI_ERROR(status) ) - size = 0; - for ( i = 0; i < size / sizeof(*handles); ++i ) - { - EFI_BLOCK_IO *bio; - EFI_DEV_PATH_PTR devp; - struct edd_info *info = boot_edd_info + boot_edd_info_nr; - struct edd_device_params *params = &info->edd_device_params; - enum { root, acpi, pci, ctrlr } state = root; - - status = efi_bs->HandleProtocol(handles[i], &bio_guid, (void **)&bio); - if ( EFI_ERROR(status) || - bio->Media->RemovableMedia || - bio->Media->LogicalPartition ) - continue; - if ( boot_edd_info_nr < EDD_INFO_MAX ) - { - info->device = 0x80 + boot_edd_info_nr; /* fake */ - info->version = 0x11; - params->length = offsetof(struct edd_device_params, dpte_ptr); - params->number_of_sectors = bio->Media->LastBlock + 1; - params->bytes_per_sector = bio->Media->BlockSize; - params->dpte_ptr = ~0; - } - ++boot_edd_info_nr; - status = efi_bs->HandleProtocol(handles[i], &devp_guid, - (void **)&devp); - if ( EFI_ERROR(status) ) - continue; - for ( ; !IsDevicePathEnd(devp.DevPath); - devp.DevPath = NextDevicePathNode(devp.DevPath) ) - { - switch ( DevicePathType(devp.DevPath) ) - { - const u8 *p; - - case ACPI_DEVICE_PATH: - if ( state != root || boot_edd_info_nr > EDD_INFO_MAX ) - break; - switch ( DevicePathSubType(devp.DevPath) ) - { - case ACPI_DP: - if ( devp.Acpi->HID != EISA_PNP_ID(0xA03) && - devp.Acpi->HID != EISA_PNP_ID(0xA08) ) - break; - params->interface_path.pci.bus = devp.Acpi->UID; - state = acpi; - break; - case EXPANDED_ACPI_DP: - /* XXX */ - break; - } - break; - case HARDWARE_DEVICE_PATH: - if ( state != acpi || - DevicePathSubType(devp.DevPath) != HW_PCI_DP || - boot_edd_info_nr > EDD_INFO_MAX ) - break; - state = pci; - edd_put_string(params->host_bus_type, "PCI"); - params->interface_path.pci.slot = devp.Pci->Device; - params->interface_path.pci.function = devp.Pci->Function; - break; - case MESSAGING_DEVICE_PATH: - if ( state != pci || boot_edd_info_nr > EDD_INFO_MAX ) - break; - state = ctrlr; - switch ( DevicePathSubType(devp.DevPath) ) - { - case MSG_ATAPI_DP: - edd_put_string(params->interface_type, "ATAPI"); - params->interface_path.pci.channel = - devp.Atapi->PrimarySecondary; - params->device_path.atapi.device = devp.Atapi->SlaveMaster; - params->device_path.atapi.lun = devp.Atapi->Lun; - break; - case MSG_SCSI_DP: - edd_put_string(params->interface_type, "SCSI"); - params->device_path.scsi.id = devp.Scsi->Pun; - params->device_path.scsi.lun = devp.Scsi->Lun; - break; - case MSG_FIBRECHANNEL_DP: - edd_put_string(params->interface_type, "FIBRE"); - params->device_path.fibre.wwid = devp.FibreChannel->WWN; - params->device_path.fibre.lun = devp.FibreChannel->Lun; - break; - case MSG_1394_DP: - edd_put_string(params->interface_type, "1394"); - params->device_path.i1394.eui = devp.F1394->Guid; - break; - case MSG_USB_DP: - case MSG_USB_CLASS_DP: - edd_put_string(params->interface_type, "USB"); - break; - case MSG_I2O_DP: - edd_put_string(params->interface_type, "I2O"); - params->device_path.i2o.identity_tag = devp.I2O->Tid; - break; - default: - continue; - } - info->version = 0x30; - params->length = sizeof(struct edd_device_params); - params->key = 0xbedd; - params->device_path_info_length = - sizeof(struct edd_device_params) - - offsetof(struct edd_device_params, key); - for ( p = (const u8 *)¶ms->key; p < ¶ms->checksum; ++p ) - params->checksum -= *p; - break; - case MEDIA_DEVICE_PATH: - if ( DevicePathSubType(devp.DevPath) == MEDIA_HARDDRIVE_DP && - devp.HardDrive->MBRType == MBR_TYPE_PCAT && - boot_mbr_signature_nr < EDD_MBR_SIG_MAX ) - { - struct mbr_signature *sig = boot_mbr_signature + - boot_mbr_signature_nr; - - sig->device = 0x80 + boot_edd_info_nr; /* fake */ - memcpy(&sig->signature, devp.HardDrive->Signature, - sizeof(sig->signature)); - ++boot_mbr_signature_nr; - } - break; - } - } - } - if ( handles ) - efi_bs->FreePool(handles); - if ( boot_edd_info_nr > EDD_INFO_MAX ) - boot_edd_info_nr = EDD_INFO_MAX; + efi_arch_edd(); /* XXX Collect EDID info. */ @@ -1280,38 +995,10 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable) PrintStr(newline); } - /* Allocate space for trampoline (in first Mb). */ - cfg.addr = 0x100000; - cfg.size = trampoline_end - trampoline_start; - status = efi_bs->AllocatePages(AllocateMaxAddress, EfiLoaderData, - PFN_UP(cfg.size), &cfg.addr); - if ( status == EFI_SUCCESS ) - relocate_trampoline(cfg.addr); - else - { - cfg.addr = 0; - PrintStr(L"Trampoline space cannot be allocated; will try fallback.\r\n"); - } - - /* Initialise L2 identity-map and boot-map page table entries (16MB). */ - for ( i = 0; i < 8; ++i ) - { - unsigned int slot = (xen_phys_start >> L2_PAGETABLE_SHIFT) + i; - paddr_t addr = slot << L2_PAGETABLE_SHIFT; - - l2_identmap[slot] = l2e_from_paddr(addr, PAGE_HYPERVISOR|_PAGE_PSE); - slot &= L2_PAGETABLE_ENTRIES - 1; - l2_bootmap[slot] = l2e_from_paddr(addr, __PAGE_HYPERVISOR|_PAGE_PSE); - } - /* Initialise L3 boot-map page directory entries. */ - l3_bootmap[l3_table_offset(xen_phys_start)] = - l3e_from_paddr((UINTN)l2_bootmap, __PAGE_HYPERVISOR); - l3_bootmap[l3_table_offset(xen_phys_start + (8 << L2_PAGETABLE_SHIFT) - 1)] = - l3e_from_paddr((UINTN)l2_bootmap, __PAGE_HYPERVISOR); + efi_arch_memory_setup(); if ( gop ) { - int bpp = 0; /* Set graphics mode. */ if ( gop_mode < gop->Mode->MaxMode && gop_mode != gop->Mode->Mode ) @@ -1320,134 +1007,24 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable) /* Get graphics and frame buffer info. */ status = gop->QueryMode(gop, gop->Mode->Mode, &info_size, &mode_info); if ( !EFI_ERROR(status) ) - switch ( mode_info->PixelFormat ) - { - case PixelRedGreenBlueReserved8BitPerColor: - vga_console_info.u.vesa_lfb.red_pos = 0; - vga_console_info.u.vesa_lfb.red_size = 8; - vga_console_info.u.vesa_lfb.green_pos = 8; - vga_console_info.u.vesa_lfb.green_size = 8; - vga_console_info.u.vesa_lfb.blue_pos = 16; - vga_console_info.u.vesa_lfb.blue_size = 8; - vga_console_info.u.vesa_lfb.rsvd_pos = 24; - vga_console_info.u.vesa_lfb.rsvd_size = 8; - bpp = 32; - break; - case PixelBlueGreenRedReserved8BitPerColor: - vga_console_info.u.vesa_lfb.red_pos = 16; - vga_console_info.u.vesa_lfb.red_size = 8; - vga_console_info.u.vesa_lfb.green_pos = 8; - vga_console_info.u.vesa_lfb.green_size = 8; - vga_console_info.u.vesa_lfb.blue_pos = 0; - vga_console_info.u.vesa_lfb.blue_size = 8; - vga_console_info.u.vesa_lfb.rsvd_pos = 24; - vga_console_info.u.vesa_lfb.rsvd_size = 8; - bpp = 32; - break; - case PixelBitMask: - bpp = set_color(mode_info->PixelInformation.RedMask, bpp, - &vga_console_info.u.vesa_lfb.red_pos, - &vga_console_info.u.vesa_lfb.red_size); - bpp = set_color(mode_info->PixelInformation.GreenMask, bpp, - &vga_console_info.u.vesa_lfb.green_pos, - &vga_console_info.u.vesa_lfb.green_size); - bpp = set_color(mode_info->PixelInformation.BlueMask, bpp, - &vga_console_info.u.vesa_lfb.blue_pos, - &vga_console_info.u.vesa_lfb.blue_size); - bpp = set_color(mode_info->PixelInformation.ReservedMask, bpp, - &vga_console_info.u.vesa_lfb.rsvd_pos, - &vga_console_info.u.vesa_lfb.rsvd_size); - if ( bpp > 0 ) - break; - /* fall through */ - default: - PrintErr(L"Current graphics mode is unsupported!\r\n"); - status = EFI_UNSUPPORTED; - break; - } - if ( !EFI_ERROR(status) ) - { - vga_console_info.video_type = XEN_VGATYPE_EFI_LFB; - vga_console_info.u.vesa_lfb.gbl_caps = 2; /* possibly non-VGA */ - vga_console_info.u.vesa_lfb.width = - mode_info->HorizontalResolution; - vga_console_info.u.vesa_lfb.height = mode_info->VerticalResolution; - vga_console_info.u.vesa_lfb.bits_per_pixel = bpp; - vga_console_info.u.vesa_lfb.bytes_per_line = - (mode_info->PixelsPerScanLine * bpp + 7) >> 3; - vga_console_info.u.vesa_lfb.lfb_base = gop->Mode->FrameBufferBase; - vga_console_info.u.vesa_lfb.lfb_size = - (gop->Mode->FrameBufferSize + 0xffff) >> 16; - } + efi_arch_video_init(gop, info_size, mode_info); } efi_bs->GetMemoryMap(&efi_memmap_size, NULL, &map_key, &efi_mdesc_size, &mdesc_ver); - mbi.mem_upper -= efi_memmap_size; - mbi.mem_upper &= -__alignof__(EFI_MEMORY_DESCRIPTOR); - if ( mbi.mem_upper < xen_phys_start ) - blexit(L"Out of static memory"); - efi_memmap = (void *)(long)mbi.mem_upper; + efi_memmap = efi_arch_allocate_mmap_buffer(efi_memmap_size); + if ( !efi_memmap ) + blexit(L"Unable to allocate memory for EFI memory map"); + status = efi_bs->GetMemoryMap(&efi_memmap_size, efi_memmap, &map_key, &efi_mdesc_size, &mdesc_ver); if ( EFI_ERROR(status) ) PrintErrMesg(L"Cannot obtain memory map", status); - /* Populate E820 table and check trampoline area availability. */ - e = e820map - 1; - for ( i = 0; i < efi_memmap_size; i += efi_mdesc_size ) - { - EFI_MEMORY_DESCRIPTOR *desc = efi_memmap + i; - u64 len = desc->NumberOfPages << EFI_PAGE_SHIFT; - u32 type; + efi_arch_process_memory_map(SystemTable, efi_memmap, efi_memmap_size, + efi_mdesc_size, mdesc_ver); - switch ( desc->Type ) - { - default: - type = E820_RESERVED; - break; - case EfiConventionalMemory: - case EfiBootServicesCode: - case EfiBootServicesData: - if ( !trampoline_phys && desc->PhysicalStart + len <= 0x100000 && - len >= cfg.size && desc->PhysicalStart + len > cfg.addr ) - cfg.addr = (desc->PhysicalStart + len - cfg.size) & PAGE_MASK; - /* fall through */ - case EfiLoaderCode: - case EfiLoaderData: - if ( desc->Attribute & EFI_MEMORY_WB ) - type = E820_RAM; - else - case EfiUnusableMemory: - type = E820_UNUSABLE; - break; - case EfiACPIReclaimMemory: - type = E820_ACPI; - break; - case EfiACPIMemoryNVS: - type = E820_NVS; - break; - } - if ( e820nr && type == e->type && - desc->PhysicalStart == e->addr + e->size ) - e->size += len; - else if ( !len || e820nr >= E820MAX ) - continue; - else - { - ++e; - e->addr = desc->PhysicalStart; - e->size = len; - e->type = type; - ++e820nr; - } - } - if ( !trampoline_phys ) - { - if ( !cfg.addr ) - blexit(L"No memory for trampoline"); - relocate_trampoline(cfg.addr); - } + efi_arch_pre_exit_boot(); status = efi_bs->ExitBootServices(ImageHandle, map_key); if ( EFI_ERROR(status) ) @@ -1461,39 +1038,7 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable) efi_memmap = (void *)efi_memmap + DIRECTMAP_VIRT_START; efi_fw_vendor = (void *)efi_fw_vendor + DIRECTMAP_VIRT_START; - relocate_image(__XEN_VIRT_START - xen_phys_start); - memcpy((void *)trampoline_phys, trampoline_start, cfg.size); - - /* Set system registers and transfer control. */ - asm volatile("pushq $0\n\tpopfq"); - rdmsrl(MSR_EFER, efer); - efer |= EFER_SCE; - if ( cpuid_ext_features & (1 << (X86_FEATURE_NX & 0x1f)) ) - efer |= EFER_NX; - wrmsrl(MSR_EFER, efer); - write_cr0(X86_CR0_PE | X86_CR0_MP | X86_CR0_ET | X86_CR0_NE | X86_CR0_WP | - X86_CR0_AM | X86_CR0_PG); - asm volatile ( "mov %[cr4], %%cr4\n\t" - "mov %[cr3], %%cr3\n\t" - "movabs $__start_xen, %[rip]\n\t" - "lgdt gdt_descr(%%rip)\n\t" - "mov stack_start(%%rip), %%rsp\n\t" - "mov %[ds], %%ss\n\t" - "mov %[ds], %%ds\n\t" - "mov %[ds], %%es\n\t" - "mov %[ds], %%fs\n\t" - "mov %[ds], %%gs\n\t" - "movl %[cs], 8(%%rsp)\n\t" - "mov %[rip], (%%rsp)\n\t" - "lretq %[stkoff]-16" - : [rip] "=&r" (efer/* any dead 64-bit variable */) - : [cr3] "r" (idle_pg_table), - [cr4] "r" (mmu_cr4_features), - [cs] "ir" (__HYPERVISOR_CS), - [ds] "r" (__HYPERVISOR_DS), - [stkoff] "i" (STACK_SIZE - sizeof(struct cpu_info)), - "D" (&mbi) - : "memory" ); + efi_arch_post_exit_boot(); for( ; ; ); /* not reached */ } diff --git a/xen/arch/x86/efi/compat.c b/xen/common/efi/compat.c similarity index 100% rename from xen/arch/x86/efi/compat.c rename to xen/common/efi/compat.c diff --git a/xen/arch/x86/efi/efi.h b/xen/common/efi/efi.h similarity index 100% rename from xen/arch/x86/efi/efi.h rename to xen/common/efi/efi.h diff --git a/xen/arch/x86/efi/runtime.c b/xen/common/efi/runtime.c similarity index 100% rename from xen/arch/x86/efi/runtime.c rename to xen/common/efi/runtime.c diff --git a/xen/include/asm-x86/hvm/vlapic.h b/xen/include/asm-x86/hvm/vlapic.h index 66f0aff4fc..16752b5195 100644 --- a/xen/include/asm-x86/hvm/vlapic.h +++ b/xen/include/asm-x86/hvm/vlapic.h @@ -28,10 +28,13 @@ #define vcpu_vlapic(x) (&(x)->arch.hvm_vcpu.vlapic) #define vlapic_vcpu(x) (container_of((x), struct vcpu, arch.hvm_vcpu.vlapic)) +#define const_vlapic_vcpu(x) (container_of((x), const struct vcpu, \ + arch.hvm_vcpu.vlapic)) #define vlapic_domain(x) (vlapic_vcpu(x)->domain) -#define VLAPIC_ID(vlapic) \ - (GET_xAPIC_ID(vlapic_get_reg((vlapic), APIC_ID))) +#define _VLAPIC_ID(vlapic, id) (vlapic_x2apic_mode(vlapic) \ + ? (id) : GET_xAPIC_ID(id)) +#define VLAPIC_ID(vlapic) _VLAPIC_ID(vlapic, vlapic_get_reg(vlapic, APIC_ID)) /* * APIC can be disabled in two ways: @@ -70,6 +73,11 @@ struct vlapic { struct hvm_hw_lapic hw; struct hvm_hw_lapic_regs *regs; + struct { + bool_t hw, regs; + uint32_t id, ldr; + } loaded; + spinlock_t esr_lock; struct periodic_time pt; s_time_t timer_last_update; struct page_info *regs_page; @@ -83,7 +91,8 @@ struct vlapic { /* vlapic's frequence is 100 MHz */ #define APIC_BUS_CYCLE_NS 10 -static inline uint32_t vlapic_get_reg(struct vlapic *vlapic, uint32_t reg) +static inline uint32_t vlapic_get_reg(const struct vlapic *vlapic, + uint32_t reg) { return *((uint32_t *)(&vlapic->regs->data[reg])); } @@ -106,7 +115,7 @@ void vlapic_destroy(struct vcpu *v); void vlapic_reset(struct vlapic *vlapic); -void vlapic_msr_set(struct vlapic *vlapic, uint64_t value); +bool_t vlapic_msr_set(struct vlapic *vlapic, uint64_t value); void vlapic_tdt_msr_set(struct vlapic *vlapic, uint64_t value); uint64_t vlapic_tdt_msr_get(struct vlapic *vlapic); @@ -123,11 +132,11 @@ void vlapic_ipi(struct vlapic *vlapic, uint32_t icr_low, uint32_t icr_high); int vlapic_apicv_write(struct vcpu *v, unsigned int offset); struct vlapic *vlapic_lowest_prio( - struct domain *d, struct vlapic *source, - int short_hand, uint8_t dest, uint8_t dest_mode); + struct domain *d, const struct vlapic *source, + int short_hand, uint32_t dest, bool_t dest_mode); bool_t vlapic_match_dest( - struct vlapic *target, struct vlapic *source, - int short_hand, uint8_t dest, uint8_t dest_mode); + const struct vlapic *target, const struct vlapic *source, + int short_hand, uint32_t dest, bool_t dest_mode); #endif /* __ASM_X86_HVM_VLAPIC_H__ */ diff --git a/xen/include/asm-x86/processor.h b/xen/include/asm-x86/processor.h index 9e1f210e6e..f98eaf5217 100644 --- a/xen/include/asm-x86/processor.h +++ b/xen/include/asm-x86/processor.h @@ -199,6 +199,7 @@ extern void set_cpuid_faulting(bool_t enable); extern u64 host_pat; extern bool_t opt_cpu_info; +extern u32 cpuid_ext_features; /* Maximum width of physical addresses supported by the hardware */ extern unsigned int paddr_bits; diff --git a/xen/include/xen/kernel.h b/xen/include/xen/kernel.h index 2c6d448369..548b64da9f 100644 --- a/xen/include/xen/kernel.h +++ b/xen/include/xen/kernel.h @@ -65,7 +65,7 @@ 1; \ }) -extern char _start[], _end[]; +extern char _start[], _end[], start[]; #define is_kernel(p) ({ \ char *__p = (char *)(unsigned long)(p); \ (__p >= _start) && (__p < _end); \