Beispiel #1
0
static void *
map_table(vm_paddr_t pa, int offset, const char *sig)
{
	ACPI_TABLE_HEADER *header;
	vm_offset_t length;
	void *table;

	header = pmap_mapbios(pa, sizeof(ACPI_TABLE_HEADER));
	if (strncmp(header->Signature, sig, ACPI_NAME_SIZE) != 0) {
		pmap_unmapbios((vm_offset_t)header, sizeof(ACPI_TABLE_HEADER));
		return (NULL);
	}
	length = header->Length;
	pmap_unmapbios((vm_offset_t)header, sizeof(ACPI_TABLE_HEADER));

	table = pmap_mapbios(pa, length);
	if (ACPI_FAILURE(AcpiTbChecksum(table, length))) {
		if (bootverbose)
			printf("ACPI: Failed checksum for table %s\n", sig);
#if (ACPI_CHECKSUM_ABORT)
		pmap_unmapbios(table, length);
		return (NULL);
#endif
	}
	return (table);
}
Beispiel #2
0
void *
vga_pci_map_bios(device_t dev, size_t *size)
{
	int rid;
	struct resource *res;

#if defined(__amd64__) || defined(__i386__) || defined(__ia64__)
	if (vga_pci_is_boot_display(dev)) {
		/*
		 * On x86, the System BIOS copy the default display
		 * device's Video BIOS at a fixed location in system
		 * memory (0xC0000, 128 kBytes long) at boot time.
		 *
		 * We use this copy for the default boot device, because
		 * the original ROM may not be valid after boot.
		 */

		*size = VGA_PCI_BIOS_SHADOW_SIZE;
		return (pmap_mapbios(VGA_PCI_BIOS_SHADOW_ADDR, *size));
	}
#endif

	rid = PCIR_BIOS;
	res = vga_pci_alloc_resource(dev, NULL, SYS_RES_MEMORY, &rid, 0ul,
	    ~0ul, 1, RF_ACTIVE);
	if (res == NULL) {
		return (NULL);
	}

	*size = rman_get_size(res);
	return (rman_get_virtual(res));
}
Beispiel #3
0
/*
 * Initialize the local APIC on the BSP.
 */
static int
madt_setup_local(void)
{

    madt = pmap_mapbios(madt_physaddr, madt_length);
    lapic_init(madt->Address);
    printf("ACPI APIC Table: <%.*s %.*s>\n",
           (int)sizeof(madt->Header.OemId), madt->Header.OemId,
           (int)sizeof(madt->Header.OemTableId), madt->Header.OemTableId);

    /*
     * We ignore 64-bit local APIC override entries.  Should we
     * perhaps emit a warning here if we find one?
     */
    return (0);
}
Beispiel #4
0
/*
 * Look for an ACPI System Resource Affinity Table ("SRAT"),
 * allocate space for cpu information, and initialize globals.
 */
int
acpi_pxm_init(int ncpus, vm_paddr_t maxphys)
{
	unsigned int idx, size;
	vm_paddr_t addr;

	if (resource_disabled("srat", 0))
		return (-1);

	max_cpus = ncpus;
	last_cpu = -1;
	maxphyaddr = maxphys;
	srat_physaddr = acpi_find_table(ACPI_SIG_SRAT);
	if (srat_physaddr == 0)
		return (-1);

	/*
	 * Allocate data structure:
	 *
	 * Find the last physical memory region and steal some memory from
	 * it. This is done because at this point in the boot process
	 * malloc is still not usable.
	 */
	for (idx = 0; phys_avail[idx + 1] != 0; idx += 2);
	KASSERT(idx != 0, ("phys_avail is empty!"));
	idx -= 2;

	size =  sizeof(*cpus) * max_cpus;
	addr = trunc_page(phys_avail[idx + 1] - size);
	KASSERT(addr >= phys_avail[idx],
	    ("Not enough memory for SRAT table items"));
	phys_avail[idx + 1] = addr - 1;

	/*
	 * We cannot rely on PHYS_TO_DMAP because this code is also used in
	 * i386, so use pmap_mapbios to map the memory, this will end up using
	 * the default memory attribute (WB), and the DMAP when available.
	 */
	cpus = (struct cpu_info *)pmap_mapbios(addr, size);
	bzero(cpus, size);
	return (0);
}
Beispiel #5
0
/* Check BIOS date.  If 1998 or older, disable ACPI. */
int
acpi_machdep_quirks(int *quirks)
{
	char *va;
	int year;

	/* BIOS address 0xffff5 contains the date in the format mm/dd/yy. */
	va = pmap_mapbios(0xffff0, 16);
	sscanf(va + 11, "%2d", &year);
	pmap_unmapbios((vm_offset_t)va, 16);

	/* 
	 * Date must be >= 1/1/1999 or we don't trust ACPI.  Note that this
	 * check must be changed by my 114th birthday.
	 */
	if (year > 90 && year < 99)
		*quirks = ACPI_Q_BROKEN;

	return (0);
}
Beispiel #6
0
/*
 * See if a given ACPI table is the requested table.  Returns the
 * length of the able if it matches or zero on failure.
 */
static int
probe_table(vm_paddr_t address, const char *sig)
{
	ACPI_TABLE_HEADER *table;

	table = pmap_mapbios(address, sizeof(ACPI_TABLE_HEADER));
	if (table == NULL) {
		if (bootverbose)
			printf("ACPI: Failed to map table at 0x%jx\n",
			    (uintmax_t)address);
		return (0);
	}
	if (bootverbose)
		printf("Table '%.4s' at 0x%jx\n", table->Signature,
		    (uintmax_t)address);

	if (strncmp(table->Signature, sig, ACPI_NAME_SIZE) != 0) {
		pmap_unmapbios((vm_offset_t)table, sizeof(ACPI_TABLE_HEADER));
		return (0);
	}
	pmap_unmapbios((vm_offset_t)table, sizeof(ACPI_TABLE_HEADER));
	return (1);
}
void *
AcpiOsMapMemory(ACPI_PHYSICAL_ADDRESS PhysicalAddress, ACPI_SIZE Length)
{
    return (pmap_mapbios((vm_offset_t)PhysicalAddress, Length));
}
Beispiel #8
0
/*
 * Initialize the local APIC on the BSP.
 */
static int
madt_setup_local(void)
{
	ACPI_TABLE_DMAR *dmartbl;
	vm_paddr_t dmartbl_physaddr;
	const char *reason;
	char *hw_vendor;
	u_int p[4];
	int user_x2apic;
	bool bios_x2apic;

	madt = pmap_mapbios(madt_physaddr, madt_length);
	if ((cpu_feature2 & CPUID2_X2APIC) != 0) {
		reason = NULL;

		/*
		 * Automatically detect several configurations where
		 * x2APIC mode is known to cause troubles.  User can
		 * override the setting with hw.x2apic_enable tunable.
		 */
		dmartbl_physaddr = acpi_find_table(ACPI_SIG_DMAR);
		if (dmartbl_physaddr != 0) {
			dmartbl = acpi_map_table(dmartbl_physaddr,
			    ACPI_SIG_DMAR);
			if ((dmartbl->Flags & ACPI_DMAR_X2APIC_OPT_OUT) != 0)
				reason = "by DMAR table";
			acpi_unmap_table(dmartbl);
		}
		if (vm_guest == VM_GUEST_VMWARE) {
			vmware_hvcall(VMW_HVCMD_GETVCPU_INFO, p);
			if ((p[0] & VMW_VCPUINFO_VCPU_RESERVED) != 0 ||
			    (p[0] & VMW_VCPUINFO_LEGACY_X2APIC) == 0)
				reason =
				    "inside VMWare without intr redirection";
		} else if (vm_guest == VM_GUEST_XEN) {
			reason = "due to running under XEN";
		} else if (vm_guest == VM_GUEST_NO &&
		    CPUID_TO_FAMILY(cpu_id) == 0x6 &&
		    CPUID_TO_MODEL(cpu_id) == 0x2a) {
			hw_vendor = kern_getenv("smbios.planar.maker");
			/*
			 * It seems that some Lenovo and ASUS
			 * SandyBridge-based notebook BIOSes have a
			 * bug which prevents booting AP in x2APIC
			 * mode.  Since the only way to detect mobile
			 * CPU is to check northbridge pci id, which
			 * cannot be done that early, disable x2APIC
			 * for all Lenovo and ASUS SandyBridge
			 * machines.
			 */
			if (hw_vendor != NULL) {
				if (!strcmp(hw_vendor, "LENOVO") ||
				    !strcmp(hw_vendor,
				    "ASUSTeK Computer Inc.")) {
					reason =
				    "for a suspected SandyBridge BIOS bug";
				}
				freeenv(hw_vendor);
			}
		}
		bios_x2apic = lapic_is_x2apic();
		if (reason != NULL && bios_x2apic) {
			if (bootverbose)
				printf("x2APIC should be disabled %s but "
				    "already enabled by BIOS; enabling.\n",
				     reason);
			reason = NULL;
		}
		if (reason == NULL)
			x2apic_mode = 1;
		else if (bootverbose)
			printf("x2APIC available but disabled %s\n", reason);
		user_x2apic = x2apic_mode;
		TUNABLE_INT_FETCH("hw.x2apic_enable", &user_x2apic);
		if (user_x2apic != x2apic_mode) {
			if (bios_x2apic && !user_x2apic)
				printf("x2APIC disabled by tunable and "
				    "enabled by BIOS; ignoring tunable.");
			else
				x2apic_mode = user_x2apic;
		}
	}

	lapic_init(madt->Address);
	printf("ACPI APIC Table: <%.*s %.*s>\n",
	    (int)sizeof(madt->Header.OemId), madt->Header.OemId,
	    (int)sizeof(madt->Header.OemTableId), madt->Header.OemTableId);

	/*
	 * We ignore 64-bit local APIC override entries.  Should we
	 * perhaps emit a warning here if we find one?
	 */
	return (0);
}
Beispiel #9
0
/*
 * Return the physical address of the requested table or zero if one
 * is not found.
 */
vm_paddr_t
acpi_find_table(const char *sig)
{
	ACPI_PHYSICAL_ADDRESS rsdp_ptr;
	ACPI_TABLE_RSDP *rsdp;
	ACPI_TABLE_XSDT *xsdt;
	ACPI_TABLE_HEADER *table;
	vm_paddr_t addr;
	int i, count;

	if (resource_disabled("acpi", 0))
		return (0);

	/*
	 * Map in the RSDP.  Since ACPI uses AcpiOsMapMemory() which in turn
	 * calls pmap_mapbios() to find the RSDP, we assume that we can use
	 * pmap_mapbios() to map the RSDP.
	 */
	if ((rsdp_ptr = AcpiOsGetRootPointer()) == 0)
		return (0);
	rsdp = pmap_mapbios(rsdp_ptr, sizeof(ACPI_TABLE_RSDP));
	if (rsdp == NULL) {
		if (bootverbose)
			printf("ACPI: Failed to map RSDP\n");
		return (0);
	}

	addr = 0;
	if (rsdp->Revision >= 2 && rsdp->XsdtPhysicalAddress != 0) {
		/*
		 * AcpiOsGetRootPointer only verifies the checksum for
		 * the version 1.0 portion of the RSDP.  Version 2.0 has
		 * an additional checksum that we verify first.
		 */
		if (AcpiTbChecksum((UINT8 *)rsdp, ACPI_RSDP_XCHECKSUM_LENGTH)) {
			if (bootverbose)
				printf("ACPI: RSDP failed extended checksum\n");
			return (0);
		}
		xsdt = map_table(rsdp->XsdtPhysicalAddress, 2, ACPI_SIG_XSDT);
		if (xsdt == NULL) {
			if (bootverbose)
				printf("ACPI: Failed to map XSDT\n");
			pmap_unmapbios((vm_offset_t)rsdp,
			    sizeof(ACPI_TABLE_RSDP));
			return (0);
		}
		count = (xsdt->Header.Length - sizeof(ACPI_TABLE_HEADER)) /
		    sizeof(UINT64);
		for (i = 0; i < count; i++)
			if (probe_table(xsdt->TableOffsetEntry[i], sig)) {
				addr = xsdt->TableOffsetEntry[i];
				break;
			}
		acpi_unmap_table(xsdt);
	}
	pmap_unmapbios((vm_offset_t)rsdp, sizeof(ACPI_TABLE_RSDP));

	if (addr == 0) {
		if (bootverbose)
			printf("ACPI: No %s table found\n", sig);
		return (0);
	}
	if (bootverbose)
		printf("%s: Found table at 0x%jx\n", sig, (uintmax_t)addr);

	/*
	 * Verify that we can map the full table and that its checksum is
	 * correct, etc.
	 */
	table = map_table(addr, 0, sig);
	if (table == NULL)
		return (0);
	acpi_unmap_table(table);

	return (addr);
}