2019-06-04 10:11:33 +02:00
|
|
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
2005-04-16 15:20:36 -07:00
|
|
|
/*
|
2010-02-20 09:41:30 +01:00
|
|
|
* linux/include/amba/bus.h
|
|
|
|
|
*
|
|
|
|
|
* This device type deals with ARM PrimeCells and anything else that
|
|
|
|
|
* presents a proper CID (0xB105F00D) at the end of the I/O register
|
|
|
|
|
* region or that is derived from a PrimeCell.
|
2005-04-16 15:20:36 -07:00
|
|
|
*
|
|
|
|
|
* Copyright (C) 2003 Deep Blue Solutions Ltd, All Rights Reserved.
|
|
|
|
|
*/
|
|
|
|
|
#ifndef ASMARM_AMBA_H
|
|
|
|
|
#define ASMARM_AMBA_H
|
|
|
|
|
|
2010-07-15 10:47:14 +01:00
|
|
|
#include <linux/clk.h>
|
2010-03-29 05:28:32 +01:00
|
|
|
#include <linux/device.h>
|
2011-10-05 14:40:59 +01:00
|
|
|
#include <linux/mod_devicetable.h>
|
2010-07-15 10:47:14 +01:00
|
|
|
#include <linux/err.h>
|
2010-03-29 05:28:32 +01:00
|
|
|
#include <linux/resource.h>
|
2010-11-04 13:06:59 +01:00
|
|
|
#include <linux/regulator/consumer.h>
|
2010-03-29 05:28:32 +01:00
|
|
|
|
2013-10-29 16:02:00 +01:00
|
|
|
#define AMBA_NR_IRQS 9
|
2010-09-07 22:43:19 +01:00
|
|
|
#define AMBA_CID 0xb105f00d
|
2014-11-03 11:07:35 -07:00
|
|
|
#define CORESIGHT_CID 0xb105900d
|
2005-04-16 15:20:36 -07:00
|
|
|
|
ARM: 8838/1: drivers: amba: Updates to component identification for driver matching.
The CoreSight specification (ARM IHI 0029E), updates the ID register
requirements for components on an AMBA bus, to cover both traditional
ARM Primecell type devices, and newer CoreSight and other components.
The Peripheral ID (PID) / Component ID (CID) pair is extended in certain
cases to uniquely identify components. CoreSight components related to
a single function can share Peripheral ID values, and must be further
identified using a Unique Component Identifier (UCI). e.g. the ETM, CTI,
PMU and Debug hardware of the A35 all share the same PID.
Bits 15:12 of the CID are defined to be the device class.
Class 0xF remains for PrimeCell and legacy components.
Class 0x9 defines the component as CoreSight (CORESIGHT_CID above)
Class 0x0, 0x1, 0xB, 0xE define components that do not have driver support
at present.
Class 0x2-0x8,0xA and 0xD-0xD are presently reserved.
The specification futher defines which classes of device use the standard
CID/PID pair, and when additional ID registers are required.
This patch introduces the amba_cs_uci_id structure which will be used in
all coresight drivers for indentification via the private data pointer in
the amba_id structure.
Existing drivers that currently use the amba_id->data pointer for private
data are updated to use the amba_cs_uci_id->data pointer. Macros and
inline functions are added to simplify this code.
Signed-off-by: Mike Leach <mike.leach@linaro.org>
Reviewed-by: Mathieu Poirier <mathieu.poirier@linaro.org>
Reviewed-by: Suzuki K Poulose <suzuki.poulose@arm.com>
Tested-by: Sai Prakash Ranjan <saiprakash.ranjan@codeaurora.org>
Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
2019-02-13 14:41:49 +01:00
|
|
|
/*
|
|
|
|
|
* CoreSight Architecture specification updates the ID specification
|
|
|
|
|
* for components on the AMBA bus. (ARM IHI 0029E)
|
|
|
|
|
*
|
|
|
|
|
* Bits 15:12 of the CID are the device class.
|
|
|
|
|
*
|
|
|
|
|
* Class 0xF remains for PrimeCell and legacy components. (AMBA_CID above)
|
|
|
|
|
* Class 0x9 defines the component as CoreSight (CORESIGHT_CID above)
|
|
|
|
|
* Class 0x0, 0x1, 0xB, 0xE define components that do not have driver support
|
|
|
|
|
* at present.
|
|
|
|
|
* Class 0x2-0x8,0xA and 0xD-0xD are presently reserved.
|
|
|
|
|
*
|
|
|
|
|
* Remaining CID bits stay as 0xb105-00d
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Class 0x9 components use additional values to form a Unique Component
|
|
|
|
|
* Identifier (UCI), where peripheral ID values are identical for different
|
|
|
|
|
* components. Passed to the amba bus code from the component driver via
|
|
|
|
|
* the amba_id->data pointer.
|
|
|
|
|
* @devarch : coresight devarch register value
|
|
|
|
|
* @devarch_mask: mask bits used for matching. 0 indicates UCI not used.
|
|
|
|
|
* @devtype : coresight device type value
|
|
|
|
|
* @data : additional driver data. As we have usurped the original
|
|
|
|
|
* pointer some devices may still need additional data
|
|
|
|
|
*/
|
|
|
|
|
struct amba_cs_uci_id {
|
|
|
|
|
unsigned int devarch;
|
|
|
|
|
unsigned int devarch_mask;
|
|
|
|
|
unsigned int devtype;
|
|
|
|
|
void *data;
|
|
|
|
|
};
|
|
|
|
|
|
2019-02-13 14:41:50 +01:00
|
|
|
/* define offsets for registers used by UCI */
|
|
|
|
|
#define UCI_REG_DEVTYPE_OFFSET 0xFCC
|
|
|
|
|
#define UCI_REG_DEVARCH_OFFSET 0xFBC
|
|
|
|
|
|
2010-07-15 10:47:14 +01:00
|
|
|
struct clk;
|
|
|
|
|
|
2005-04-16 15:20:36 -07:00
|
|
|
struct amba_device {
|
|
|
|
|
struct device dev;
|
|
|
|
|
struct resource res;
|
2010-07-15 10:47:14 +01:00
|
|
|
struct clk *pclk;
|
2020-04-22 12:10:13 +02:00
|
|
|
struct device_dma_parameters dma_parms;
|
2005-04-16 15:20:36 -07:00
|
|
|
unsigned int periphid;
|
ARM: 9229/1: amba: Fix use-after-free in amba_read_periphid()
After commit f2d3b9a46e0e ("ARM: 9220/1: amba: Remove deferred device
addition"), it became possible for amba_read_periphid() to be invoked
concurrently from two threads for a particular AMBA device.
Consider the case where a thread (T0) is registering an AMBA driver, and
searching for all of the devices it can match with on the AMBA bus.
Suppose that another thread (T1) is executing the deferred probe work,
and is searching through all of the AMBA drivers on the bus for a driver
that matches a particular AMBA device. Assume that both threads begin
operating on the same AMBA device and the device's peripheral ID is
still unknown.
In this scenario, the amba_match() function will be invoked for the
same AMBA device by both threads, which means amba_read_periphid()
can also be invoked by both threads, and both threads will be able
to manipulate the AMBA device's pclk pointer without any synchronization.
It's possible that one thread will initialize the pclk pointer, then the
other thread will re-initialize it, overwriting the previous value, and
both will race to free the same pclk, resulting in a use-after-free for
whichever thread frees the pclk last.
Add a lock per AMBA device to synchronize the handling with detecting the
peripheral ID to avoid the use-after-free scenario.
The following KFENCE bug report helped detect this problem:
==================================================================
BUG: KFENCE: use-after-free read in clk_disable+0x14/0x34
Use-after-free read at 0x(ptrval) (in kfence-#19):
clk_disable+0x14/0x34
amba_read_periphid+0xdc/0x134
amba_match+0x3c/0x84
__driver_attach+0x20/0x158
bus_for_each_dev+0x74/0xc0
bus_add_driver+0x154/0x1e8
driver_register+0x88/0x11c
do_one_initcall+0x8c/0x2fc
kernel_init_freeable+0x190/0x220
kernel_init+0x10/0x108
ret_from_fork+0x14/0x3c
0x0
kfence-#19: 0x(ptrval)-0x(ptrval), size=36, cache=kmalloc-64
allocated by task 8 on cpu 0 at 11.629931s:
clk_hw_create_clk+0x38/0x134
amba_get_enable_pclk+0x10/0x68
amba_read_periphid+0x28/0x134
amba_match+0x3c/0x84
__device_attach_driver+0x2c/0xc4
bus_for_each_drv+0x80/0xd0
__device_attach+0xb0/0x1f0
bus_probe_device+0x88/0x90
deferred_probe_work_func+0x8c/0xc0
process_one_work+0x23c/0x690
worker_thread+0x34/0x488
kthread+0xd4/0xfc
ret_from_fork+0x14/0x3c
0x0
freed by task 8 on cpu 0 at 11.630095s:
amba_read_periphid+0xec/0x134
amba_match+0x3c/0x84
__device_attach_driver+0x2c/0xc4
bus_for_each_drv+0x80/0xd0
__device_attach+0xb0/0x1f0
bus_probe_device+0x88/0x90
deferred_probe_work_func+0x8c/0xc0
process_one_work+0x23c/0x690
worker_thread+0x34/0x488
kthread+0xd4/0xfc
ret_from_fork+0x14/0x3c
0x0
Cc: Saravana Kannan <saravanak@google.com>
Cc: patches@armlinux.org.uk
Fixes: f2d3b9a46e0e ("ARM: 9220/1: amba: Remove deferred device addition")
Reported-by: Guenter Roeck <linux@roeck-us.net>
Tested-by: Guenter Roeck <linux@roeck-us.net>
Signed-off-by: Isaac J. Manjarres <isaacmanjarres@google.com>
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
2022-08-18 18:28:51 +01:00
|
|
|
struct mutex periphid_lock;
|
2019-02-13 14:41:50 +01:00
|
|
|
unsigned int cid;
|
|
|
|
|
struct amba_cs_uci_id uci;
|
2005-04-16 15:20:36 -07:00
|
|
|
unsigned int irq[AMBA_NR_IRQS];
|
2022-04-19 13:34:25 +02:00
|
|
|
/*
|
|
|
|
|
* Driver name to force a match. Do not set directly, because core
|
|
|
|
|
* frees it. Use driver_set_override() to set or clear it.
|
|
|
|
|
*/
|
|
|
|
|
const char *driver_override;
|
2005-04-16 15:20:36 -07:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct amba_driver {
|
|
|
|
|
struct device_driver drv;
|
2011-02-19 15:55:00 +00:00
|
|
|
int (*probe)(struct amba_device *, const struct amba_id *);
|
2021-01-26 17:58:34 +01:00
|
|
|
void (*remove)(struct amba_device *);
|
2005-04-16 15:20:36 -07:00
|
|
|
void (*shutdown)(struct amba_device *);
|
2011-02-19 15:55:48 +00:00
|
|
|
const struct amba_id *id_table;
|
bus: platform,amba,fsl-mc,PCI: Add device DMA ownership management
The devices on platform/amba/fsl-mc/PCI buses could be bound to drivers
with the device DMA managed by kernel drivers or user-space applications.
Unfortunately, multiple devices may be placed in the same IOMMU group
because they cannot be isolated from each other. The DMA on these devices
must either be entirely under kernel control or userspace control, never
a mixture. Otherwise the driver integrity is not guaranteed because they
could access each other through the peer-to-peer accesses which by-pass
the IOMMU protection.
This checks and sets the default DMA mode during driver binding, and
cleanups during driver unbinding. In the default mode, the device DMA is
managed by the device driver which handles DMA operations through the
kernel DMA APIs (see Documentation/core-api/dma-api.rst).
For cases where the devices are assigned for userspace control through the
userspace driver framework(i.e. VFIO), the drivers(for example, vfio_pci/
vfio_platfrom etc.) may set a new flag (driver_managed_dma) to skip this
default setting in the assumption that the drivers know what they are
doing with the device DMA.
Calling iommu_device_use_default_domain() before {of,acpi}_dma_configure
is currently a problem. As things stand, the IOMMU driver ignored the
initial iommu_probe_device() call when the device was added, since at
that point it had no fwspec yet. In this situation,
{of,acpi}_iommu_configure() are retriggering iommu_probe_device() after
the IOMMU driver has seen the firmware data via .of_xlate to learn that
it actually responsible for the given device. As the result, before
that gets fixed, iommu_use_default_domain() goes at the end, and calls
arch_teardown_dma_ops() if it fails.
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Bjorn Helgaas <bhelgaas@google.com>
Cc: Stuart Yoder <stuyoder@gmail.com>
Cc: Laurentiu Tudor <laurentiu.tudor@nxp.com>
Signed-off-by: Lu Baolu <baolu.lu@linux.intel.com>
Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Reviewed-by: Jason Gunthorpe <jgg@nvidia.com>
Reviewed-by: Robin Murphy <robin.murphy@arm.com>
Tested-by: Eric Auger <eric.auger@redhat.com>
Link: https://lore.kernel.org/r/20220418005000.897664-5-baolu.lu@linux.intel.com
Signed-off-by: Joerg Roedel <jroedel@suse.de>
2022-04-18 08:49:53 +08:00
|
|
|
/*
|
|
|
|
|
* For most device drivers, no need to care about this flag as long as
|
|
|
|
|
* all DMAs are handled through the kernel DMA API. For some special
|
|
|
|
|
* ones, for example VFIO drivers, they know how to manage the DMA
|
|
|
|
|
* themselves and set this flag so that the IOMMU layer will allow them
|
|
|
|
|
* to setup and manage their own I/O address space.
|
|
|
|
|
*/
|
|
|
|
|
bool driver_managed_dma;
|
2005-04-16 15:20:36 -07:00
|
|
|
};
|
|
|
|
|
|
2014-09-17 08:46:58 +02:00
|
|
|
/*
|
|
|
|
|
* Constants for the designer field of the Peripheral ID register. When bit 7
|
|
|
|
|
* is set to '1', bits [6:0] should be the JEP106 manufacturer identity code.
|
|
|
|
|
*/
|
2009-08-04 01:01:02 +01:00
|
|
|
enum amba_vendor {
|
|
|
|
|
AMBA_VENDOR_ARM = 0x41,
|
|
|
|
|
AMBA_VENDOR_ST = 0x80,
|
2014-05-15 11:28:44 +01:00
|
|
|
AMBA_VENDOR_QCOM = 0x51,
|
2014-09-17 08:46:58 +02:00
|
|
|
AMBA_VENDOR_LSI = 0xb6,
|
2009-08-04 01:01:02 +01:00
|
|
|
};
|
|
|
|
|
|
2011-02-12 15:58:25 +01:00
|
|
|
extern struct bus_type amba_bustype;
|
|
|
|
|
|
2011-02-23 04:33:17 +01:00
|
|
|
#define to_amba_device(d) container_of(d, struct amba_device, dev)
|
|
|
|
|
|
2005-04-16 15:20:36 -07:00
|
|
|
#define amba_get_drvdata(d) dev_get_drvdata(&d->dev)
|
|
|
|
|
#define amba_set_drvdata(d,p) dev_set_drvdata(&d->dev, p)
|
|
|
|
|
|
2021-02-23 15:17:48 -04:00
|
|
|
#ifdef CONFIG_ARM_AMBA
|
2005-04-16 15:20:36 -07:00
|
|
|
int amba_driver_register(struct amba_driver *);
|
|
|
|
|
void amba_driver_unregister(struct amba_driver *);
|
2021-02-23 15:17:48 -04:00
|
|
|
#else
|
|
|
|
|
static inline int amba_driver_register(struct amba_driver *drv)
|
|
|
|
|
{
|
|
|
|
|
return -EINVAL;
|
|
|
|
|
}
|
|
|
|
|
static inline void amba_driver_unregister(struct amba_driver *drv)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
2011-12-18 11:07:47 +00:00
|
|
|
struct amba_device *amba_device_alloc(const char *, resource_size_t, size_t);
|
|
|
|
|
void amba_device_put(struct amba_device *);
|
|
|
|
|
int amba_device_add(struct amba_device *, struct resource *);
|
2005-04-16 15:20:36 -07:00
|
|
|
int amba_device_register(struct amba_device *, struct resource *);
|
|
|
|
|
void amba_device_unregister(struct amba_device *);
|
|
|
|
|
int amba_request_regions(struct amba_device *, const char *);
|
|
|
|
|
void amba_release_regions(struct amba_device *);
|
|
|
|
|
|
2010-09-07 22:43:19 +01:00
|
|
|
/* Some drivers don't use the struct amba_device */
|
|
|
|
|
#define AMBA_CONFIG_BITS(a) (((a) >> 24) & 0xff)
|
|
|
|
|
#define AMBA_REV_BITS(a) (((a) >> 20) & 0x0f)
|
|
|
|
|
#define AMBA_MANF_BITS(a) (((a) >> 12) & 0xff)
|
|
|
|
|
#define AMBA_PART_BITS(a) ((a) & 0xfff)
|
|
|
|
|
|
|
|
|
|
#define amba_config(d) AMBA_CONFIG_BITS((d)->periphid)
|
|
|
|
|
#define amba_rev(d) AMBA_REV_BITS((d)->periphid)
|
|
|
|
|
#define amba_manf(d) AMBA_MANF_BITS((d)->periphid)
|
|
|
|
|
#define amba_part(d) AMBA_PART_BITS((d)->periphid)
|
2005-04-16 15:20:36 -07:00
|
|
|
|
2011-12-18 12:06:25 +00:00
|
|
|
#define __AMBA_DEV(busid, data, mask) \
|
|
|
|
|
{ \
|
|
|
|
|
.coherent_dma_mask = mask, \
|
|
|
|
|
.init_name = busid, \
|
|
|
|
|
.platform_data = data, \
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* APB devices do not themselves have the ability to address memory,
|
|
|
|
|
* so DMA masks should be zero (much like USB peripheral devices.)
|
|
|
|
|
* The DMA controller DMA masks should be used instead (much like
|
|
|
|
|
* USB host controllers in conventional PCs.)
|
|
|
|
|
*/
|
|
|
|
|
#define AMBA_APB_DEVICE(name, busid, id, base, irqs, data) \
|
|
|
|
|
struct amba_device name##_device = { \
|
|
|
|
|
.dev = __AMBA_DEV(busid, data, 0), \
|
|
|
|
|
.res = DEFINE_RES_MEM(base, SZ_4K), \
|
|
|
|
|
.irq = irqs, \
|
|
|
|
|
.periphid = id, \
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* AHB devices are DMA capable, so set their DMA masks
|
|
|
|
|
*/
|
|
|
|
|
#define AMBA_AHB_DEVICE(name, busid, id, base, irqs, data) \
|
|
|
|
|
struct amba_device name##_device = { \
|
|
|
|
|
.dev = __AMBA_DEV(busid, data, ~0ULL), \
|
|
|
|
|
.res = DEFINE_RES_MEM(base, SZ_4K), \
|
|
|
|
|
.irq = irqs, \
|
|
|
|
|
.periphid = id, \
|
|
|
|
|
}
|
|
|
|
|
|
2012-03-15 10:40:38 +01:00
|
|
|
/*
|
|
|
|
|
* module_amba_driver() - Helper macro for drivers that don't do anything
|
|
|
|
|
* special in module init/exit. This eliminates a lot of boilerplate. Each
|
|
|
|
|
* module may only use this macro once, and calling it replaces module_init()
|
|
|
|
|
* and module_exit()
|
|
|
|
|
*/
|
|
|
|
|
#define module_amba_driver(__amba_drv) \
|
|
|
|
|
module_driver(__amba_drv, amba_driver_register, amba_driver_unregister)
|
|
|
|
|
|
2016-02-17 17:52:03 -07:00
|
|
|
/*
|
|
|
|
|
* builtin_amba_driver() - Helper macro for drivers that don't do anything
|
|
|
|
|
* special in driver initcall. This eliminates a lot of boilerplate. Each
|
|
|
|
|
* driver may only use this macro once, and calling it replaces the instance
|
|
|
|
|
* device_initcall().
|
|
|
|
|
*/
|
|
|
|
|
#define builtin_amba_driver(__amba_drv) \
|
|
|
|
|
builtin_driver(__amba_drv, amba_driver_register)
|
|
|
|
|
|
2005-04-16 15:20:36 -07:00
|
|
|
#endif
|