acpi_status
acpi_os_map_memory(acpi_physical_address phys, acpi_size size, void **virt)
{
#ifdef CONFIG_ACPI_EFI
	if (EFI_MEMORY_WB & efi_mem_attributes(phys)) {
		*virt = phys_to_virt(phys);
	} else {
		*virt = ioremap(phys, size);
	}
#else
	if (phys > ULONG_MAX) {
		printk(KERN_ERR PREFIX "Cannot map memory that high\n");
		return AE_BAD_PARAMETER;
	}
	/*
	 * ioremap checks to ensure this is in reserved space
	 */
	*virt = ioremap((unsigned long) phys, size);
#endif

	if (!*virt)
		return AE_NO_MEMORY;

	return AE_OK;
}
Exemple #2
0
/*
 * Architectures vary in how they handle caching for addresses
 * outside of main memory.
 *
 */
static inline int uncached_access(struct file *file, unsigned long addr)
{
#if defined(__i386__)
	/*
	 * On the PPro and successors, the MTRRs are used to set
	 * memory types for physical addresses outside main memory,
	 * so blindly setting PCD or PWT on those pages is wrong.
	 * For Pentiums and earlier, the surround logic should disable
	 * caching for the high addresses through the KEN pin, but
	 * we maintain the tradition of paranoia in this code.
	 */
	if (file->f_flags & O_SYNC)
		return 1;
 	return !( test_bit(X86_FEATURE_MTRR, boot_cpu_data.x86_capability) ||
		  test_bit(X86_FEATURE_K6_MTRR, boot_cpu_data.x86_capability) ||
		  test_bit(X86_FEATURE_CYRIX_ARR, boot_cpu_data.x86_capability) ||
		  test_bit(X86_FEATURE_CENTAUR_MCR, boot_cpu_data.x86_capability) )
	  && addr >= __pa(high_memory);
#elif defined(__x86_64__)
	/* 
	 * This is broken because it can generate memory type aliases,
	 * which can cause cache corruptions
	 * But it is only available for root and we have to be bug-to-bug
	 * compatible with i386.
	 */
	if (file->f_flags & O_SYNC)
		return 1;
	/* same behaviour as i386. PAT always set to cached and MTRRs control the
	   caching behaviour. 
	   Hopefully a full PAT implementation will fix that soon. */	   
	return 0;
#elif defined(CONFIG_IA64)
	/*
	 * On ia64, we ignore O_SYNC because we cannot tolerate memory attribute aliases.
	 */
	return !(efi_mem_attributes(addr) & EFI_MEMORY_WB);
#elif defined(CONFIG_PPC64)
	/* On PPC64, we always do non-cacheable access to the IO hole and
	 * cacheable elsewhere. Cache paradox can checkstop the CPU and
	 * the high_memory heuristic below is wrong on machines with memory
	 * above the IO hole... Ah, and of course, XFree86 doesn't pass
	 * O_SYNC when mapping us to tap IO space. Surprised ?
	 */
	return !page_is_ram(addr >> PAGE_SHIFT);
#else
	/*
	 * Accessing memory above the top the kernel knows about or through a file pointer
	 * that was marked O_SYNC will be done non-cached.
	 */
	if (file->f_flags & O_SYNC)
		return 1;
	return addr >= __pa(high_memory);
#endif
}
acpi_status
acpi_os_read_memory(
	acpi_physical_address	phys_addr,
	u32			*value,
	u32			width)
{
	u32			dummy;
	void			*virt_addr;

#ifdef CONFIG_ACPI_EFI
	int			iomem = 0;

	if (EFI_MEMORY_WB & efi_mem_attributes(phys_addr)) {
		virt_addr = phys_to_virt(phys_addr);
	} else {
		iomem = 1;
		virt_addr = ioremap(phys_addr, width);
	}
#else
	virt_addr = phys_to_virt(phys_addr);
#endif
	if (!value)
		value = &dummy;

	switch (width) {
	case 8:
		*(u8*) value = *(u8*) virt_addr;
		break;
	case 16:
		*(u16*) value = *(u16*) virt_addr;
		break;
	case 32:
		*(u32*) value = *(u32*) virt_addr;
		break;
	default:
		BUG();
	}

#ifdef CONFIG_ACPI_EFI
	if (iomem)
		iounmap(virt_addr);
#endif

	return AE_OK;
}
Exemple #4
0
acpi_status
acpi_os_read_memory(
	acpi_physical_address	phys_addr,
	u32			*value,
	u32			width)
{
	u32			dummy;
	void __iomem		*virt_addr;
	int			iomem = 0;

	if (efi_enabled) {
		if (EFI_MEMORY_WB & efi_mem_attributes(phys_addr)) {
			/* HACK ALERT! We can use readb/w/l on real memory too.. */
			virt_addr = (void __iomem *) phys_to_virt(phys_addr);
		} else {
			iomem = 1;
			virt_addr = ioremap(phys_addr, width);
		}
	} else
		virt_addr = (void __iomem *) phys_to_virt(phys_addr);
	if (!value)
		value = &dummy;

	switch (width) {
	case 8:
		*(u8*) value = readb(virt_addr);
		break;
	case 16:
		*(u16*) value = readw(virt_addr);
		break;
	case 32:
		*(u32*) value = readl(virt_addr);
		break;
	default:
		BUG();
	}

	if (efi_enabled) {
		if (iomem)
			iounmap(virt_addr);
	}

	return AE_OK;
}
Exemple #5
0
pgprot_t arch_apei_get_mem_attribute(phys_addr_t addr)
{
	/*
	 * According to "Table 8 Map: EFI memory types to AArch64 memory
	 * types" of UEFI 2.5 section 2.3.6.1, each EFI memory type is
	 * mapped to a corresponding MAIR attribute encoding.
	 * The EFI memory attribute advises all possible capabilities
	 * of a memory region. We use the most efficient capability.
	 */

	u64 attr;

	attr = efi_mem_attributes(addr);
	if (attr & EFI_MEMORY_WB)
		return PAGE_KERNEL;
	if (attr & EFI_MEMORY_WT)
		return __pgprot(PROT_NORMAL_WT);
	if (attr & EFI_MEMORY_WC)
		return __pgprot(PROT_NORMAL_NC);
	return __pgprot(PROT_DEVICE_nGnRnE);
}
Exemple #6
0
acpi_status
acpi_os_write_memory(
	acpi_physical_address	phys_addr,
	u32			value,
	u32			width)
{
	void __iomem		*virt_addr;
	int			iomem = 0;

	if (efi_enabled) {
		if (EFI_MEMORY_WB & efi_mem_attributes(phys_addr)) {
			/* HACK ALERT! We can use writeb/w/l on real memory too */
			virt_addr = (void __iomem *) phys_to_virt(phys_addr);
		} else {
			iomem = 1;
			virt_addr = ioremap(phys_addr, width);
		}
	} else
		virt_addr = (void __iomem *) phys_to_virt(phys_addr);

	switch (width) {
	case 8:
		writeb(value, virt_addr);
		break;
	case 16:
		writew(value, virt_addr);
		break;
	case 32:
		writel(value, virt_addr);
		break;
	default:
		BUG();
	}

	if (iomem)
		iounmap(virt_addr);

	return AE_OK;
}
Exemple #7
0
acpi_status
acpi_os_write_memory(
	acpi_physical_address	phys_addr,
	u32			value,
	u32			width)
{
	void			*virt_addr;
	int			iomem = 0;

	if (efi_enabled) {
		if (EFI_MEMORY_WB & efi_mem_attributes(phys_addr)) {
			virt_addr = phys_to_virt(phys_addr);
		} else {
			iomem = 1;
			virt_addr = ioremap(phys_addr, width);
		}
	} else
		virt_addr = phys_to_virt(phys_addr);

	switch (width) {
	case 8:
		*(u8*) virt_addr = value;
		break;
	case 16:
		*(u16*) virt_addr = value;
		break;
	case 32:
		*(u32*) virt_addr = value;
		break;
	default:
		BUG();
	}

	if (iomem)
		iounmap(virt_addr);

	return AE_OK;
}