* [PATCH v8 04/13] IIO: inkern: API for manipulating channel attributes
From: Arnaud Pouliquen @ 2017-12-11 10:18 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1512987524-2901-1-git-send-email-arnaud.pouliquen@st.com>
Extend the inkern API with functions for reading and writing
attribute of iio channels.
Signed-off-by: Arnaud Pouliquen <arnaud.pouliquen@st.com>
Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
---
V7 to V8
- Suppress extra line.
drivers/iio/inkern.c | 17 ++++++++++++-----
include/linux/iio/consumer.h | 26 ++++++++++++++++++++++++++
include/linux/iio/iio.h | 28 ----------------------------
include/linux/iio/types.h | 28 ++++++++++++++++++++++++++++
4 files changed, 66 insertions(+), 33 deletions(-)
diff --git a/drivers/iio/inkern.c b/drivers/iio/inkern.c
index 069defc..ec98790 100644
--- a/drivers/iio/inkern.c
+++ b/drivers/iio/inkern.c
@@ -664,9 +664,8 @@ int iio_convert_raw_to_processed(struct iio_channel *chan, int raw,
}
EXPORT_SYMBOL_GPL(iio_convert_raw_to_processed);
-static int iio_read_channel_attribute(struct iio_channel *chan,
- int *val, int *val2,
- enum iio_chan_info_enum attribute)
+int iio_read_channel_attribute(struct iio_channel *chan, int *val, int *val2,
+ enum iio_chan_info_enum attribute)
{
int ret;
@@ -682,6 +681,7 @@ static int iio_read_channel_attribute(struct iio_channel *chan,
return ret;
}
+EXPORT_SYMBOL_GPL(iio_read_channel_attribute);
int iio_read_channel_offset(struct iio_channel *chan, int *val, int *val2)
{
@@ -850,7 +850,8 @@ static int iio_channel_write(struct iio_channel *chan, int val, int val2,
chan->channel, val, val2, info);
}
-int iio_write_channel_raw(struct iio_channel *chan, int val)
+int iio_write_channel_attribute(struct iio_channel *chan, int val, int val2,
+ enum iio_chan_info_enum attribute)
{
int ret;
@@ -860,12 +861,18 @@ int iio_write_channel_raw(struct iio_channel *chan, int val)
goto err_unlock;
}
- ret = iio_channel_write(chan, val, 0, IIO_CHAN_INFO_RAW);
+ ret = iio_channel_write(chan, val, val2, attribute);
err_unlock:
mutex_unlock(&chan->indio_dev->info_exist_lock);
return ret;
}
+EXPORT_SYMBOL_GPL(iio_write_channel_attribute);
+
+int iio_write_channel_raw(struct iio_channel *chan, int val)
+{
+ return iio_write_channel_attribute(chan, val, 0, IIO_CHAN_INFO_RAW);
+}
EXPORT_SYMBOL_GPL(iio_write_channel_raw);
unsigned int iio_get_channel_ext_info_count(struct iio_channel *chan)
diff --git a/include/linux/iio/consumer.h b/include/linux/iio/consumer.h
index 5e347a9..2017f35 100644
--- a/include/linux/iio/consumer.h
+++ b/include/linux/iio/consumer.h
@@ -216,6 +216,32 @@ int iio_read_channel_average_raw(struct iio_channel *chan, int *val);
int iio_read_channel_processed(struct iio_channel *chan, int *val);
/**
+ * iio_write_channel_attribute() - Write values to the device attribute.
+ * @chan: The channel being queried.
+ * @val: Value being written.
+ * @val2: Value being written.val2 use depends on attribute type.
+ * @attribute: info attribute to be read.
+ *
+ * Returns an error code or 0.
+ */
+int iio_write_channel_attribute(struct iio_channel *chan, int val,
+ int val2, enum iio_chan_info_enum attribute);
+
+/**
+ * iio_read_channel_attribute() - Read values from the device attribute.
+ * @chan: The channel being queried.
+ * @val: Value being written.
+ * @val2: Value being written.Val2 use depends on attribute type.
+ * @attribute: info attribute to be written.
+ *
+ * Returns an error code if failed. Else returns a description of what is in val
+ * and val2, such as IIO_VAL_INT_PLUS_MICRO telling us we have a value of val
+ * + val2/1e6
+ */
+int iio_read_channel_attribute(struct iio_channel *chan, int *val,
+ int *val2, enum iio_chan_info_enum attribute);
+
+/**
* iio_write_channel_raw() - write to a given channel
* @chan: The channel being queried.
* @val: Value being written.
diff --git a/include/linux/iio/iio.h b/include/linux/iio/iio.h
index c380daa..007caf7 100644
--- a/include/linux/iio/iio.h
+++ b/include/linux/iio/iio.h
@@ -20,34 +20,6 @@
* Currently assumes nano seconds.
*/
-enum iio_chan_info_enum {
- IIO_CHAN_INFO_RAW = 0,
- IIO_CHAN_INFO_PROCESSED,
- IIO_CHAN_INFO_SCALE,
- IIO_CHAN_INFO_OFFSET,
- IIO_CHAN_INFO_CALIBSCALE,
- IIO_CHAN_INFO_CALIBBIAS,
- IIO_CHAN_INFO_PEAK,
- IIO_CHAN_INFO_PEAK_SCALE,
- IIO_CHAN_INFO_QUADRATURE_CORRECTION_RAW,
- IIO_CHAN_INFO_AVERAGE_RAW,
- IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY,
- IIO_CHAN_INFO_HIGH_PASS_FILTER_3DB_FREQUENCY,
- IIO_CHAN_INFO_SAMP_FREQ,
- IIO_CHAN_INFO_FREQUENCY,
- IIO_CHAN_INFO_PHASE,
- IIO_CHAN_INFO_HARDWAREGAIN,
- IIO_CHAN_INFO_HYSTERESIS,
- IIO_CHAN_INFO_INT_TIME,
- IIO_CHAN_INFO_ENABLE,
- IIO_CHAN_INFO_CALIBHEIGHT,
- IIO_CHAN_INFO_CALIBWEIGHT,
- IIO_CHAN_INFO_DEBOUNCE_COUNT,
- IIO_CHAN_INFO_DEBOUNCE_TIME,
- IIO_CHAN_INFO_CALIBEMISSIVITY,
- IIO_CHAN_INFO_OVERSAMPLING_RATIO,
-};
-
enum iio_shared_by {
IIO_SEPARATE,
IIO_SHARED_BY_TYPE,
diff --git a/include/linux/iio/types.h b/include/linux/iio/types.h
index 2aa7b63..6eb3d683 100644
--- a/include/linux/iio/types.h
+++ b/include/linux/iio/types.h
@@ -34,4 +34,32 @@ enum iio_available_type {
IIO_AVAIL_RANGE,
};
+enum iio_chan_info_enum {
+ IIO_CHAN_INFO_RAW = 0,
+ IIO_CHAN_INFO_PROCESSED,
+ IIO_CHAN_INFO_SCALE,
+ IIO_CHAN_INFO_OFFSET,
+ IIO_CHAN_INFO_CALIBSCALE,
+ IIO_CHAN_INFO_CALIBBIAS,
+ IIO_CHAN_INFO_PEAK,
+ IIO_CHAN_INFO_PEAK_SCALE,
+ IIO_CHAN_INFO_QUADRATURE_CORRECTION_RAW,
+ IIO_CHAN_INFO_AVERAGE_RAW,
+ IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY,
+ IIO_CHAN_INFO_HIGH_PASS_FILTER_3DB_FREQUENCY,
+ IIO_CHAN_INFO_SAMP_FREQ,
+ IIO_CHAN_INFO_FREQUENCY,
+ IIO_CHAN_INFO_PHASE,
+ IIO_CHAN_INFO_HARDWAREGAIN,
+ IIO_CHAN_INFO_HYSTERESIS,
+ IIO_CHAN_INFO_INT_TIME,
+ IIO_CHAN_INFO_ENABLE,
+ IIO_CHAN_INFO_CALIBHEIGHT,
+ IIO_CHAN_INFO_CALIBWEIGHT,
+ IIO_CHAN_INFO_DEBOUNCE_COUNT,
+ IIO_CHAN_INFO_DEBOUNCE_TIME,
+ IIO_CHAN_INFO_CALIBEMISSIVITY,
+ IIO_CHAN_INFO_OVERSAMPLING_RATIO,
+};
+
#endif /* _IIO_TYPES_H_ */
--
2.7.4
^ permalink raw reply related
* [PATCH v8 03/13] IIO: hw_consumer: add devm_iio_hw_consumer_alloc
From: Arnaud Pouliquen @ 2017-12-11 10:18 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1512987524-2901-1-git-send-email-arnaud.pouliquen@st.com>
Add devm_iio_hw_consumer_alloc function that calls iio_hw_consumer_free
when the device is unbound from the bus.
Signed-off-by: Arnaud Pouliquen <arnaud.pouliquen@st.com>
Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
---
drivers/iio/buffer/industrialio-hw-consumer.c | 66 +++++++++++++++++++++++++++
include/linux/iio/hw-consumer.h | 2 +
2 files changed, 68 insertions(+)
diff --git a/drivers/iio/buffer/industrialio-hw-consumer.c b/drivers/iio/buffer/industrialio-hw-consumer.c
index 993ecdc..9516569 100644
--- a/drivers/iio/buffer/industrialio-hw-consumer.c
+++ b/drivers/iio/buffer/industrialio-hw-consumer.c
@@ -137,6 +137,72 @@ void iio_hw_consumer_free(struct iio_hw_consumer *hwc)
}
EXPORT_SYMBOL_GPL(iio_hw_consumer_free);
+static void devm_iio_hw_consumer_release(struct device *dev, void *res)
+{
+ iio_hw_consumer_free(*(struct iio_hw_consumer **)res);
+}
+
+static int devm_iio_hw_consumer_match(struct device *dev, void *res, void *data)
+{
+ struct iio_hw_consumer **r = res;
+
+ if (!r || !*r) {
+ WARN_ON(!r || !*r);
+ return 0;
+ }
+ return *r == data;
+}
+
+/**
+ * devm_iio_hw_consumer_alloc - Resource-managed iio_hw_consumer_alloc()
+ * @dev: Pointer to consumer device.
+ *
+ * Managed iio_hw_consumer_alloc. iio_hw_consumer allocated with this function
+ * is automatically freed on driver detach.
+ *
+ * If an iio_hw_consumer allocated with this function needs to be freed
+ * separately, devm_iio_hw_consumer_free() must be used.
+ *
+ * returns pointer to allocated iio_hw_consumer on success, NULL on failure.
+ */
+struct iio_hw_consumer *devm_iio_hw_consumer_alloc(struct device *dev)
+{
+ struct iio_hw_consumer **ptr, *iio_hwc;
+
+ ptr = devres_alloc(devm_iio_hw_consumer_release, sizeof(*ptr),
+ GFP_KERNEL);
+ if (!ptr)
+ return NULL;
+
+ iio_hwc = iio_hw_consumer_alloc(dev);
+ if (IS_ERR(iio_hwc)) {
+ devres_free(ptr);
+ } else {
+ *ptr = iio_hwc;
+ devres_add(dev, ptr);
+ }
+
+ return iio_hwc;
+}
+EXPORT_SYMBOL_GPL(devm_iio_hw_consumer_alloc);
+
+/**
+ * devm_iio_hw_consumer_free - Resource-managed iio_hw_consumer_free()
+ * @dev: Pointer to consumer device.
+ * @hwc: iio_hw_consumer to free.
+ *
+ * Free iio_hw_consumer allocated with devm_iio_hw_consumer_alloc().
+ */
+void devm_iio_hw_consumer_free(struct device *dev, struct iio_hw_consumer *hwc)
+{
+ int rc;
+
+ rc = devres_release(dev, devm_iio_hw_consumer_release,
+ devm_iio_hw_consumer_match, hwc);
+ WARN_ON(rc);
+}
+EXPORT_SYMBOL_GPL(devm_iio_hw_consumer_free);
+
/**
* iio_hw_consumer_enable() - Enable IIO hardware consumer
* @hwc: iio_hw_consumer to enable.
diff --git a/include/linux/iio/hw-consumer.h b/include/linux/iio/hw-consumer.h
index db8c00b..44d48bb 100644
--- a/include/linux/iio/hw-consumer.h
+++ b/include/linux/iio/hw-consumer.h
@@ -13,6 +13,8 @@ struct iio_hw_consumer;
struct iio_hw_consumer *iio_hw_consumer_alloc(struct device *dev);
void iio_hw_consumer_free(struct iio_hw_consumer *hwc);
+struct iio_hw_consumer *devm_iio_hw_consumer_alloc(struct device *dev);
+void devm_iio_hw_consumer_free(struct device *dev, struct iio_hw_consumer *hwc);
int iio_hw_consumer_enable(struct iio_hw_consumer *hwc);
void iio_hw_consumer_disable(struct iio_hw_consumer *hwc);
--
2.7.4
^ permalink raw reply related
* [PATCH v8 02/13] docs: driver-api: add iio hw consumer section
From: Arnaud Pouliquen @ 2017-12-11 10:18 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1512987524-2901-1-git-send-email-arnaud.pouliquen@st.com>
This adds a section about the Hardware consumer
API of the IIO subsystem to the driver API
documentation.
Signed-off-by: Arnaud Pouliquen <arnaud.pouliquen@st.com>
Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
---
Documentation/driver-api/iio/hw-consumer.rst | 51 ++++++++++++++++++++++++++++
Documentation/driver-api/iio/index.rst | 1 +
2 files changed, 52 insertions(+)
create mode 100644 Documentation/driver-api/iio/hw-consumer.rst
diff --git a/Documentation/driver-api/iio/hw-consumer.rst b/Documentation/driver-api/iio/hw-consumer.rst
new file mode 100644
index 0000000..8facce6
--- /dev/null
+++ b/Documentation/driver-api/iio/hw-consumer.rst
@@ -0,0 +1,51 @@
+===========
+HW consumer
+===========
+An IIO device can be directly connected to another device in hardware. in this
+case the buffers between IIO provider and IIO consumer are handled by hardware.
+The Industrial I/O HW consumer offers a way to bond these IIO devices without
+software buffer for data. The implementation can be found under
+:file:`drivers/iio/buffer/hw-consumer.c`
+
+
+* struct :c:type:`iio_hw_consumer` ? Hardware consumer structure
+* :c:func:`iio_hw_consumer_alloc` ? Allocate IIO hardware consumer
+* :c:func:`iio_hw_consumer_free` ? Free IIO hardware consumer
+* :c:func:`iio_hw_consumer_enable` ? Enable IIO hardware consumer
+* :c:func:`iio_hw_consumer_disable` ? Disable IIO hardware consumer
+
+
+HW consumer setup
+=================
+
+As standard IIO device the implementation is based on IIO provider/consumer.
+A typical IIO HW consumer setup looks like this::
+
+ static struct iio_hw_consumer *hwc;
+
+ static const struct iio_info adc_info = {
+ .read_raw = adc_read_raw,
+ };
+
+ static int adc_read_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan, int *val,
+ int *val2, long mask)
+ {
+ ret = iio_hw_consumer_enable(hwc);
+
+ /* Acquire data */
+
+ ret = iio_hw_consumer_disable(hwc);
+ }
+
+ static int adc_probe(struct platform_device *pdev)
+ {
+ hwc = devm_iio_hw_consumer_alloc(&iio->dev);
+ }
+
+More details
+============
+.. kernel-doc:: include/linux/iio/hw-consumer.h
+.. kernel-doc:: drivers/iio/buffer/industrialio-hw-consumer.c
+ :export:
+
diff --git a/Documentation/driver-api/iio/index.rst b/Documentation/driver-api/iio/index.rst
index e5c3922..7fba341 100644
--- a/Documentation/driver-api/iio/index.rst
+++ b/Documentation/driver-api/iio/index.rst
@@ -15,3 +15,4 @@ Contents:
buffers
triggers
triggered-buffers
+ hw-consumer
--
2.7.4
^ permalink raw reply related
* [PATCH v8 01/13] iio: Add hardware consumer buffer support
From: Arnaud Pouliquen @ 2017-12-11 10:18 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1512987524-2901-1-git-send-email-arnaud.pouliquen@st.com>
From: Lars-Peter Clausen <lars@metafoo.de>
Hardware consumer interface can be used when one IIO device has
a direct connection to another device in hardware.
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
Signed-off-by: Arnaud Pouliquen <arnaud.pouliquen@st.com>
Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
---
drivers/iio/buffer/Kconfig | 10 ++
drivers/iio/buffer/Makefile | 1 +
drivers/iio/buffer/industrialio-hw-consumer.c | 181 ++++++++++++++++++++++++++
include/linux/iio/hw-consumer.h | 19 +++
4 files changed, 211 insertions(+)
create mode 100644 drivers/iio/buffer/industrialio-hw-consumer.c
create mode 100644 include/linux/iio/hw-consumer.h
diff --git a/drivers/iio/buffer/Kconfig b/drivers/iio/buffer/Kconfig
index 4ffd3db..338774c 100644
--- a/drivers/iio/buffer/Kconfig
+++ b/drivers/iio/buffer/Kconfig
@@ -29,6 +29,16 @@ config IIO_BUFFER_DMAENGINE
Should be selected by drivers that want to use this functionality.
+config IIO_BUFFER_HW_CONSUMER
+ tristate "Industrial I/O HW buffering"
+ help
+ Provides a way to bonding when an IIO device has a direct connection
+ to another device in hardware. In this case buffers for data transfers
+ are handled by hardware.
+
+ Should be selected by drivers that want to use the generic Hw consumer
+ interface.
+
config IIO_KFIFO_BUF
tristate "Industrial I/O buffering based on kfifo"
help
diff --git a/drivers/iio/buffer/Makefile b/drivers/iio/buffer/Makefile
index 85beaae..324a36b 100644
--- a/drivers/iio/buffer/Makefile
+++ b/drivers/iio/buffer/Makefile
@@ -6,5 +6,6 @@
obj-$(CONFIG_IIO_BUFFER_CB) += industrialio-buffer-cb.o
obj-$(CONFIG_IIO_BUFFER_DMA) += industrialio-buffer-dma.o
obj-$(CONFIG_IIO_BUFFER_DMAENGINE) += industrialio-buffer-dmaengine.o
+obj-$(CONFIG_IIO_BUFFER_HW_CONSUMER) += industrialio-hw-consumer.o
obj-$(CONFIG_IIO_TRIGGERED_BUFFER) += industrialio-triggered-buffer.o
obj-$(CONFIG_IIO_KFIFO_BUF) += kfifo_buf.o
diff --git a/drivers/iio/buffer/industrialio-hw-consumer.c b/drivers/iio/buffer/industrialio-hw-consumer.c
new file mode 100644
index 0000000..993ecdc
--- /dev/null
+++ b/drivers/iio/buffer/industrialio-hw-consumer.c
@@ -0,0 +1,181 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright 2017 Analog Devices Inc.
+ * Author: Lars-Peter Clausen <lars@metafoo.de>
+ */
+
+#include <linux/err.h>
+#include <linux/export.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+
+#include <linux/iio/iio.h>
+#include <linux/iio/consumer.h>
+#include <linux/iio/hw-consumer.h>
+#include <linux/iio/buffer_impl.h>
+
+/**
+ * struct iio_hw_consumer - IIO hw consumer block
+ * @buffers: hardware buffers list head.
+ * @channels: IIO provider channels.
+ */
+struct iio_hw_consumer {
+ struct list_head buffers;
+ struct iio_channel *channels;
+};
+
+struct hw_consumer_buffer {
+ struct list_head head;
+ struct iio_dev *indio_dev;
+ struct iio_buffer buffer;
+ long scan_mask[];
+};
+
+static struct hw_consumer_buffer *iio_buffer_to_hw_consumer_buffer(
+ struct iio_buffer *buffer)
+{
+ return container_of(buffer, struct hw_consumer_buffer, buffer);
+}
+
+static void iio_hw_buf_release(struct iio_buffer *buffer)
+{
+ struct hw_consumer_buffer *hw_buf =
+ iio_buffer_to_hw_consumer_buffer(buffer);
+ kfree(hw_buf);
+}
+
+static const struct iio_buffer_access_funcs iio_hw_buf_access = {
+ .release = &iio_hw_buf_release,
+ .modes = INDIO_BUFFER_HARDWARE,
+};
+
+static struct hw_consumer_buffer *iio_hw_consumer_get_buffer(
+ struct iio_hw_consumer *hwc, struct iio_dev *indio_dev)
+{
+ size_t mask_size = BITS_TO_LONGS(indio_dev->masklength) * sizeof(long);
+ struct hw_consumer_buffer *buf;
+
+ list_for_each_entry(buf, &hwc->buffers, head) {
+ if (buf->indio_dev == indio_dev)
+ return buf;
+ }
+
+ buf = kzalloc(sizeof(*buf) + mask_size, GFP_KERNEL);
+ if (!buf)
+ return NULL;
+
+ buf->buffer.access = &iio_hw_buf_access;
+ buf->indio_dev = indio_dev;
+ buf->buffer.scan_mask = buf->scan_mask;
+
+ iio_buffer_init(&buf->buffer);
+ list_add_tail(&buf->head, &hwc->buffers);
+
+ return buf;
+}
+
+/**
+ * iio_hw_consumer_alloc() - Allocate IIO hardware consumer
+ * @dev: Pointer to consumer device.
+ *
+ * Returns a valid iio_hw_consumer on success or a ERR_PTR() on failure.
+ */
+struct iio_hw_consumer *iio_hw_consumer_alloc(struct device *dev)
+{
+ struct hw_consumer_buffer *buf;
+ struct iio_hw_consumer *hwc;
+ struct iio_channel *chan;
+ int ret;
+
+ hwc = kzalloc(sizeof(*hwc), GFP_KERNEL);
+ if (!hwc)
+ return ERR_PTR(-ENOMEM);
+
+ INIT_LIST_HEAD(&hwc->buffers);
+
+ hwc->channels = iio_channel_get_all(dev);
+ if (IS_ERR(hwc->channels)) {
+ ret = PTR_ERR(hwc->channels);
+ goto err_free_hwc;
+ }
+
+ chan = &hwc->channels[0];
+ while (chan->indio_dev) {
+ buf = iio_hw_consumer_get_buffer(hwc, chan->indio_dev);
+ if (!buf) {
+ ret = -ENOMEM;
+ goto err_put_buffers;
+ }
+ set_bit(chan->channel->scan_index, buf->buffer.scan_mask);
+ chan++;
+ }
+
+ return hwc;
+
+err_put_buffers:
+ list_for_each_entry(buf, &hwc->buffers, head)
+ iio_buffer_put(&buf->buffer);
+ iio_channel_release_all(hwc->channels);
+err_free_hwc:
+ kfree(hwc);
+ return ERR_PTR(ret);
+}
+EXPORT_SYMBOL_GPL(iio_hw_consumer_alloc);
+
+/**
+ * iio_hw_consumer_free() - Free IIO hardware consumer
+ * @hwc: hw consumer to free.
+ */
+void iio_hw_consumer_free(struct iio_hw_consumer *hwc)
+{
+ struct hw_consumer_buffer *buf, *n;
+
+ iio_channel_release_all(hwc->channels);
+ list_for_each_entry_safe(buf, n, &hwc->buffers, head)
+ iio_buffer_put(&buf->buffer);
+ kfree(hwc);
+}
+EXPORT_SYMBOL_GPL(iio_hw_consumer_free);
+
+/**
+ * iio_hw_consumer_enable() - Enable IIO hardware consumer
+ * @hwc: iio_hw_consumer to enable.
+ *
+ * Returns 0 on success.
+ */
+int iio_hw_consumer_enable(struct iio_hw_consumer *hwc)
+{
+ struct hw_consumer_buffer *buf;
+ int ret;
+
+ list_for_each_entry(buf, &hwc->buffers, head) {
+ ret = iio_update_buffers(buf->indio_dev, &buf->buffer, NULL);
+ if (ret)
+ goto err_disable_buffers;
+ }
+
+ return 0;
+
+err_disable_buffers:
+ list_for_each_entry_continue_reverse(buf, &hwc->buffers, head)
+ iio_update_buffers(buf->indio_dev, NULL, &buf->buffer);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(iio_hw_consumer_enable);
+
+/**
+ * iio_hw_consumer_disable() - Disable IIO hardware consumer
+ * @hwc: iio_hw_consumer to disable.
+ */
+void iio_hw_consumer_disable(struct iio_hw_consumer *hwc)
+{
+ struct hw_consumer_buffer *buf;
+
+ list_for_each_entry(buf, &hwc->buffers, head)
+ iio_update_buffers(buf->indio_dev, NULL, &buf->buffer);
+}
+EXPORT_SYMBOL_GPL(iio_hw_consumer_disable);
+
+MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
+MODULE_DESCRIPTION("Hardware consumer buffer the IIO framework");
+MODULE_LICENSE("GPL v2");
diff --git a/include/linux/iio/hw-consumer.h b/include/linux/iio/hw-consumer.h
new file mode 100644
index 0000000..db8c00b
--- /dev/null
+++ b/include/linux/iio/hw-consumer.h
@@ -0,0 +1,19 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Industrial I/O in kernel hardware consumer interface
+ *
+ * Copyright 2017 Analog Devices Inc.
+ * Author: Lars-Peter Clausen <lars@metafoo.de>
+ */
+
+#ifndef LINUX_IIO_HW_CONSUMER_H
+#define LINUX_IIO_HW_CONSUMER_H
+
+struct iio_hw_consumer;
+
+struct iio_hw_consumer *iio_hw_consumer_alloc(struct device *dev);
+void iio_hw_consumer_free(struct iio_hw_consumer *hwc);
+int iio_hw_consumer_enable(struct iio_hw_consumer *hwc);
+void iio_hw_consumer_disable(struct iio_hw_consumer *hwc);
+
+#endif
--
2.7.4
^ permalink raw reply related
* [PATCH v8 00/13] Add STM32 DFSDM support
From: Arnaud Pouliquen @ 2017-12-11 10:18 UTC (permalink / raw)
To: linux-arm-kernel
Hello
New version based on minor comments from Jonathan.
Main deltas V8 vs V7:
- Few typos fixes.
- Function return optimizations in sound/soc/stm/stm32_adfsdm.c.
Main deltas V7 vs V6:
- Replaces the custom license information text with the appropriate
SPDX identifier.
- Few fixes in sound/soc/stm/stm32_adfsdm.c and stm32-dfsdm-core.c.
- Add missing #interrupt-cells in binding examples.
- Integrate last Jonathan's comments.
Main deltas V6 vs V5:
- Fix warning reported by kbuild test in :
include/linux/iio/consumer.h
sound/soc/stm/stm32_adfsdm.c
Main deltas V5 vs V4:
- Integrate ASOC DAI as a subnode of the DFSDM.
- Add in kernel consumer interface to allow to manipulate attribute.
Thanks,
Arnaud
Arnaud Pouliquen (12):
docs: driver-api: add iio hw consumer section
IIO: hw_consumer: add devm_iio_hw_consumer_alloc
IIO: inkern: API for manipulating channel attributes
IIO: Add DT bindings for sigma delta adc modulator
IIO: ADC: add sigma delta modulator support
IIO: add DT bindings for stm32 DFSDM filter
IIO: ADC: add stm32 DFSDM core support
IIO: ADC: add STM32 DFSDM sigma delta ADC support
IIO: ADC: add stm32 DFSDM support for PDM microphone
IIO: consumer: allow to set buffer sizes
ASoC: add bindings for stm32 DFSDM filter
ASoC: stm32: add DFSDM DAI support
Lars-Peter Clausen (1):
iio: Add hardware consumer buffer support
.../ABI/testing/sysfs-bus-iio-dfsdm-adc-stm32 | 16 +
.../bindings/iio/adc/sigma-delta-modulator.txt | 13 +
.../bindings/iio/adc/st,stm32-dfsdm-adc.txt | 128 ++
.../devicetree/bindings/sound/st,stm32-adfsdm.txt | 63 +
Documentation/driver-api/iio/hw-consumer.rst | 51 +
Documentation/driver-api/iio/index.rst | 1 +
drivers/iio/adc/Kconfig | 37 +
drivers/iio/adc/Makefile | 3 +
drivers/iio/adc/sd_adc_modulator.c | 68 ++
drivers/iio/adc/stm32-dfsdm-adc.c | 1220 ++++++++++++++++++++
drivers/iio/adc/stm32-dfsdm-core.c | 309 +++++
drivers/iio/adc/stm32-dfsdm.h | 310 +++++
drivers/iio/buffer/Kconfig | 10 +
drivers/iio/buffer/Makefile | 1 +
drivers/iio/buffer/industrialio-buffer-cb.c | 11 +
drivers/iio/buffer/industrialio-hw-consumer.c | 247 ++++
drivers/iio/inkern.c | 17 +-
include/linux/iio/adc/stm32-dfsdm-adc.h | 18 +
include/linux/iio/consumer.h | 37 +
include/linux/iio/hw-consumer.h | 21 +
include/linux/iio/iio.h | 28 -
include/linux/iio/types.h | 28 +
sound/soc/stm/Kconfig | 11 +
sound/soc/stm/Makefile | 3 +
sound/soc/stm/stm32_adfsdm.c | 347 ++++++
25 files changed, 2965 insertions(+), 33 deletions(-)
create mode 100644 Documentation/ABI/testing/sysfs-bus-iio-dfsdm-adc-stm32
create mode 100644 Documentation/devicetree/bindings/iio/adc/sigma-delta-modulator.txt
create mode 100644 Documentation/devicetree/bindings/iio/adc/st,stm32-dfsdm-adc.txt
create mode 100644 Documentation/devicetree/bindings/sound/st,stm32-adfsdm.txt
create mode 100644 Documentation/driver-api/iio/hw-consumer.rst
create mode 100644 drivers/iio/adc/sd_adc_modulator.c
create mode 100644 drivers/iio/adc/stm32-dfsdm-adc.c
create mode 100644 drivers/iio/adc/stm32-dfsdm-core.c
create mode 100644 drivers/iio/adc/stm32-dfsdm.h
create mode 100644 drivers/iio/buffer/industrialio-hw-consumer.c
create mode 100644 include/linux/iio/adc/stm32-dfsdm-adc.h
create mode 100644 include/linux/iio/hw-consumer.h
create mode 100644 sound/soc/stm/stm32_adfsdm.c
--
2.7.4
^ permalink raw reply
* [PATCH v6 3/6] clk: meson-axg: add clock controller drivers
From: Yixun Lan @ 2017-12-11 10:16 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1512985560.334.17.camel@baylibre.com>
HI Jerome:
On 12/11/17 17:46, Jerome Brunet wrote:
> On Mon, 2017-12-11 at 14:48 +0800, Yixun Lan wrote:
>> From: Qiufang Dai <qiufang.dai@amlogic.com>
>>
>> Add clock controller drivers for Amlogic Meson-AXG SoC.
>>
>> Acked-by: Neil Armstrong <narmstrong@baylibre.com>
>> Signed-off-by: Qiufang Dai <qiufang.dai@amlogic.com>
>> Signed-off-by: Yixun Lan <yixun.lan@amlogic.com>
>> ---
>> arch/arm64/Kconfig.platforms | 1 +
>> drivers/clk/meson/Kconfig | 8 +
>> drivers/clk/meson/Makefile | 1 +
>> drivers/clk/meson/axg.c | 944
>> +++++++++++++++++++++++++++++++++++++++++++
>> drivers/clk/meson/axg.h | 126 ++++++
>> 5 files changed, 1080 insertions(+)
>> create mode 100644 drivers/clk/meson/axg.c
>> create mode 100644 drivers/clk/meson/axg.h
>
> Overall, the changes looks good to me.
> I still have a few comments which I'd like to see addressed quickly after this
> series is merged
did you say that:
you will merge these patches now, then I could send fixes later?
or I can send another version (v7) to address this..
>
> [...]
>
>>
>> +static struct meson_clk_pll axg_fixed_pll = {
>> + .m = {
>> + .reg_off = HHI_MPLL_CNTL,
>> + .shift = 0,
>> + .width = 9,
>> + },
>> + .n = {
>> + .reg_off = HHI_MPLL_CNTL,
>> + .shift = 9,
>> + .width = 5,
>> + },
>> + .od = {
>> + .reg_off = HHI_MPLL_CNTL,
>> + .shift = 16,
>> + .width = 2,
>> + },
>> + .lock = &clk_lock,
>> + .hw.init = &(struct clk_init_data){
>> + .name = "fixed_pll",
>> + .ops = &meson_clk_pll_ro_ops,
>> + .parent_names = (const char *[]){ "xtal" },
>> + .num_parents = 1,
>> + .flags = CLK_GET_RATE_NOCACHE,
>
> Is the rate of this clock supposed to changed by something else than
> the CCF after boot ?
>
> If not, you should drop this flag.
> Same comment goes for axg_sys_pll and axg_gp0_pll
>
we need to keep the CLK_GET_RATE_NOCACHE flag for axg_sys_pll, since the
BL30 will change it for the frequency change.
for the other two, we can drop them safely
>> + },
>> +};
>
> [...]
>
>> +/*
>> + * FIXME The legacy composite clocks (e.g. clk81) are both PLL post-dividers
>> + * and should be modeled with their respective PLLs via the forthcoming
>> + * coordinated clock rates feature
>> + */
>> +static u32 mux_table_clk81[] = { 0, 2, 3, 4, 5, 6, 7 };
>> +static const char * const clk81_parent_names[] = {
>> + "xtal", "fclk_div7", "mpll1", "mpll2", "fclk_div4",
>> + "fclk_div3", "fclk_div5"
>> +};
>> +
>> +static struct clk_mux axg_mpeg_clk_sel = {
>> + .reg = (void *)HHI_MPEG_CLK_CNTL,
>> + .mask = 0x7,
>> + .shift = 12,
>> + .flags = CLK_MUX_READ_ONLY,
>> + .table = mux_table_clk81,
>> + .lock = &clk_lock,
>> + .hw.init = &(struct clk_init_data){
>> + .name = "mpeg_clk_sel",
>> + .ops = &clk_mux_ro_ops,
>> + /*
>> + * bits 14:12 selects from 8 possible parents:
>> + * xtal, 1'b0 (wtf), fclk_div7, mpll_clkout1, mpll_clkout2,
>> + * fclk_div4, fclk_div3, fclk_div5
>> + */
>
> This comment is not necessary with table above.
>
can drop
>> + .parent_names = clk81_parent_names,
>> + .num_parents = ARRAY_SIZE(clk81_parent_names),
>> + .flags = CLK_SET_RATE_NO_REPARENT,
>
> With ro_ops, this flag is not necessary, consider removing it.
>
can drop
>> + },
>> +};
>> +
>>
>
> .
>
^ permalink raw reply
* [PATCH v2 16/36] KVM: arm64: Rewrite sysreg alternatives to static keys
From: Marc Zyngier @ 2017-12-11 10:15 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20171207170630.592-17-christoffer.dall@linaro.org>
On 07/12/17 17:06, Christoffer Dall wrote:
> As we are about to move calls around in the sysreg save/restore logic,
> let's first rewrite the alternative function callers, because it is
> going to make the next patches much easier to read.
>
> Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
Acked-by: Marc Zyngier <marc.zyngier@arm.com>
M.
--
Jazz is not dead. It just smells funny...
^ permalink raw reply
* [PATCH v2 15/36] KVM: arm64: Move userspace system registers into separate function
From: Marc Zyngier @ 2017-12-11 10:14 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20171207170630.592-16-christoffer.dall@linaro.org>
On 07/12/17 17:06, Christoffer Dall wrote:
> There's a semantic difference between the EL1 registers that control
> operation of a kernel running in EL1 and EL1 registers that only control
> userspace execution in EL0. Since we can defer saving/restoring the
> latter, move them into their own function.
>
> We also take this chance to rename the function saving/restoring the
> remaining system register to make it clear this function deals with
> the EL1 system registers.
>
> No functional change.
>
> Reviewed-by: Andrew Jones <drjones@redhat.com>
> Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
> ---
>
> Notes:
> Changes since v1:
> - Added comment about sp_el0 to common save sysreg save/restore functions
>
> arch/arm64/kvm/hyp/sysreg-sr.c | 44 +++++++++++++++++++++++++++++++-----------
> 1 file changed, 33 insertions(+), 11 deletions(-)
>
> diff --git a/arch/arm64/kvm/hyp/sysreg-sr.c b/arch/arm64/kvm/hyp/sysreg-sr.c
> index 68a7d164e5e1..bbfb4d01af88 100644
> --- a/arch/arm64/kvm/hyp/sysreg-sr.c
> +++ b/arch/arm64/kvm/hyp/sysreg-sr.c
> @@ -33,15 +33,24 @@ static void __hyp_text __sysreg_do_nothing(struct kvm_cpu_context *ctxt) { }
> */
>
> static void __hyp_text __sysreg_save_common_state(struct kvm_cpu_context *ctxt)
> +{
> + ctxt->sys_regs[MDSCR_EL1] = read_sysreg(mdscr_el1);
> +
> + /*
> + * The host arm64 Linux uses sp_el0 to point to 'current' and it must
> + * therefore be saved/restored on every entry/exit to/from the guest.
> + */
> + ctxt->gp_regs.regs.sp = read_sysreg(sp_el0);
> +}
> +
> +static void __hyp_text __sysreg_save_user_state(struct kvm_cpu_context *ctxt)
> {
> ctxt->sys_regs[ACTLR_EL1] = read_sysreg(actlr_el1);
What is the rational for keeping ACTLR_EL1 as part of the user state?
> ctxt->sys_regs[TPIDR_EL0] = read_sysreg(tpidr_el0);
> ctxt->sys_regs[TPIDRRO_EL0] = read_sysreg(tpidrro_el0);
> - ctxt->sys_regs[MDSCR_EL1] = read_sysreg(mdscr_el1);
> - ctxt->gp_regs.regs.sp = read_sysreg(sp_el0);
> }
>
> -static void __hyp_text __sysreg_save_state(struct kvm_cpu_context *ctxt)
> +static void __hyp_text __sysreg_save_el1_state(struct kvm_cpu_context *ctxt)
> {
> ctxt->sys_regs[MPIDR_EL1] = read_sysreg(vmpidr_el2);
> ctxt->sys_regs[CSSELR_EL1] = read_sysreg(csselr_el1);
> @@ -70,31 +79,42 @@ static void __hyp_text __sysreg_save_state(struct kvm_cpu_context *ctxt)
> }
>
> static hyp_alternate_select(__sysreg_call_save_host_state,
> - __sysreg_save_state, __sysreg_do_nothing,
> + __sysreg_save_el1_state, __sysreg_do_nothing,
> ARM64_HAS_VIRT_HOST_EXTN);
>
> void __hyp_text __sysreg_save_host_state(struct kvm_cpu_context *ctxt)
> {
> __sysreg_call_save_host_state()(ctxt);
> __sysreg_save_common_state(ctxt);
> + __sysreg_save_user_state(ctxt);
> }
>
> void __hyp_text __sysreg_save_guest_state(struct kvm_cpu_context *ctxt)
> {
> - __sysreg_save_state(ctxt);
> + __sysreg_save_el1_state(ctxt);
> __sysreg_save_common_state(ctxt);
> + __sysreg_save_user_state(ctxt);
> }
>
> static void __hyp_text __sysreg_restore_common_state(struct kvm_cpu_context *ctxt)
> {
> - write_sysreg(ctxt->sys_regs[ACTLR_EL1], actlr_el1);
> - write_sysreg(ctxt->sys_regs[TPIDR_EL0], tpidr_el0);
> - write_sysreg(ctxt->sys_regs[TPIDRRO_EL0], tpidrro_el0);
> write_sysreg(ctxt->sys_regs[MDSCR_EL1], mdscr_el1);
> +
> + /*
> + * The host arm64 Linux uses sp_el0 to point to 'current' and it must
> + * therefore be saved/restored on every entry/exit to/from the guest.
> + */
> write_sysreg(ctxt->gp_regs.regs.sp, sp_el0);
> }
>
> -static void __hyp_text __sysreg_restore_state(struct kvm_cpu_context *ctxt)
> +static void __hyp_text __sysreg_restore_user_state(struct kvm_cpu_context *ctxt)
> +{
> + write_sysreg(ctxt->sys_regs[ACTLR_EL1], actlr_el1);
Same here.
> + write_sysreg(ctxt->sys_regs[TPIDR_EL0], tpidr_el0);
> + write_sysreg(ctxt->sys_regs[TPIDRRO_EL0], tpidrro_el0);
> +}
> +
> +static void __hyp_text __sysreg_restore_el1_state(struct kvm_cpu_context *ctxt)
> {
> write_sysreg(ctxt->sys_regs[MPIDR_EL1], vmpidr_el2);
> write_sysreg(ctxt->sys_regs[CSSELR_EL1], csselr_el1);
> @@ -123,19 +143,21 @@ static void __hyp_text __sysreg_restore_state(struct kvm_cpu_context *ctxt)
> }
>
> static hyp_alternate_select(__sysreg_call_restore_host_state,
> - __sysreg_restore_state, __sysreg_do_nothing,
> + __sysreg_restore_el1_state, __sysreg_do_nothing,
> ARM64_HAS_VIRT_HOST_EXTN);
>
> void __hyp_text __sysreg_restore_host_state(struct kvm_cpu_context *ctxt)
> {
> __sysreg_call_restore_host_state()(ctxt);
> __sysreg_restore_common_state(ctxt);
> + __sysreg_restore_user_state(ctxt);
> }
>
> void __hyp_text __sysreg_restore_guest_state(struct kvm_cpu_context *ctxt)
> {
> - __sysreg_restore_state(ctxt);
> + __sysreg_restore_el1_state(ctxt);
> __sysreg_restore_common_state(ctxt);
> + __sysreg_restore_user_state(ctxt);
> }
>
> static void __hyp_text __fpsimd32_save_state(struct kvm_cpu_context *ctxt)
>
I think we should move ACTLR_EL1 to the EL1 state, allowing it to be
lazily switched. See the note in D10.2.1 that recommends a VHE enabled
system to have ACTLR_EL1 as a guest-only register.
Thanks,
M.
--
Jazz is not dead. It just smells funny...
^ permalink raw reply
* [PATCH v2 14/36] KVM: arm64: Remove noop calls to timer save/restore from VHE switch
From: Marc Zyngier @ 2017-12-11 10:02 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20171207170630.592-15-christoffer.dall@linaro.org>
On 07/12/17 17:06, Christoffer Dall wrote:
> The VHE switch function calls __timer_enable_traps and
> __timer_disable_traps which don't do anything on VHE systems.
> Therefore, simply remove these calls from the VHE switch function and
> make the functions non-conditional as they are now only called from the
> non-VHE switch path.
>
> Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
> ---
> arch/arm64/kvm/hyp/switch.c | 2 --
> virt/kvm/arm/hyp/timer-sr.c | 36 ++++++++++++++----------------------
> 2 files changed, 14 insertions(+), 24 deletions(-)
>
> diff --git a/arch/arm64/kvm/hyp/switch.c b/arch/arm64/kvm/hyp/switch.c
> index e783e2371b7c..09aafa0470f7 100644
> --- a/arch/arm64/kvm/hyp/switch.c
> +++ b/arch/arm64/kvm/hyp/switch.c
> @@ -358,7 +358,6 @@ int kvm_vcpu_run_vhe(struct kvm_vcpu *vcpu)
> __activate_vm(vcpu->kvm);
>
> __vgic_restore_state(vcpu);
> - __timer_enable_traps(vcpu);
>
> /*
> * We must restore the 32-bit state before the sysregs, thanks
> @@ -377,7 +376,6 @@ int kvm_vcpu_run_vhe(struct kvm_vcpu *vcpu)
>
> __sysreg_save_guest_state(guest_ctxt);
> __sysreg32_save_state(vcpu);
> - __timer_disable_traps(vcpu);
> __vgic_save_state(vcpu);
>
> __deactivate_traps(vcpu);
> diff --git a/virt/kvm/arm/hyp/timer-sr.c b/virt/kvm/arm/hyp/timer-sr.c
> index f24404b3c8df..752b37f9133c 100644
> --- a/virt/kvm/arm/hyp/timer-sr.c
> +++ b/virt/kvm/arm/hyp/timer-sr.c
> @@ -29,32 +29,24 @@ void __hyp_text __kvm_timer_set_cntvoff(u32 cntvoff_low, u32 cntvoff_high)
>
> void __hyp_text __timer_disable_traps(struct kvm_vcpu *vcpu)
> {
> - /*
> - * We don't need to do this for VHE since the host kernel runs in EL2
> - * with HCR_EL2.TGE ==1, which makes those bits have no impact.
> - */
> - if (!has_vhe()) {
> - u64 val;
> + u64 val;
>
> - /* Allow physical timer/counter access for the host */
> - val = read_sysreg(cnthctl_el2);
> - val |= CNTHCTL_EL1PCTEN | CNTHCTL_EL1PCEN;
> - write_sysreg(val, cnthctl_el2);
> - }
> + /* Allow physical timer/counter access for the host */
> + val = read_sysreg(cnthctl_el2);
> + val |= CNTHCTL_EL1PCTEN | CNTHCTL_EL1PCEN;
> + write_sysreg(val, cnthctl_el2);
> }
>
> void __hyp_text __timer_enable_traps(struct kvm_vcpu *vcpu)
> {
> - if (!has_vhe()) {
> - u64 val;
> + u64 val;
>
> - /*
> - * Disallow physical timer access for the guest
> - * Physical counter access is allowed
> - */
> - val = read_sysreg(cnthctl_el2);
> - val &= ~CNTHCTL_EL1PCEN;
> - val |= CNTHCTL_EL1PCTEN;
> - write_sysreg(val, cnthctl_el2);
> - }
> + /*
> + * Disallow physical timer access for the guest
> + * Physical counter access is allowed
> + */
> + val = read_sysreg(cnthctl_el2);
> + val &= ~CNTHCTL_EL1PCEN;
> + val |= CNTHCTL_EL1PCTEN;
> + write_sysreg(val, cnthctl_el2);
> }
>
Since we're not testing for !VHE anymore, can you add a small comment
saying that these two function are for the benefit of !VHE only and
shouldn't be called on VHE?
Otherwise,
Acked-by: Marc Zyngier <marc.zyngier@arm.com>
M.
--
Jazz is not dead. It just smells funny...
^ permalink raw reply
* [PATCH v2 13/36] KVM: arm64: Don't deactivate VM on VHE systems
From: Marc Zyngier @ 2017-12-11 9:58 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20171207170630.592-14-christoffer.dall@linaro.org>
On 07/12/17 17:06, Christoffer Dall wrote:
> There is no need to reset the VTTBR to zero when exiting the guest on
> VHE systems. VHE systems don't use stage 2 translations for the EL2&0
> translation regime used by the host.
>
> Reviewed-by: Andrew Jones <drjones@redhat.com>
> Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
Acked-by: Marc Zyngier <marc.zyngier@arm.com>
M.
--
Jazz is not dead. It just smells funny...
^ permalink raw reply
* [PATCH v2 12/36] KVM: arm64: Remove kern_hyp_va() use in VHE switch function
From: Marc Zyngier @ 2017-12-11 9:54 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20171207170630.592-13-christoffer.dall@linaro.org>
On 07/12/17 17:06, Christoffer Dall wrote:
> VHE kernels run completely in EL2 and therefore don't have a notion of
> kernel and hyp addresses, they are all just kernel addresses. Therefore
> don't call kern_hyp_va() in the VHE switch function.
>
> Reviewed-by: Andrew Jones <drjones@redhat.com>
> Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
Reviewed-by: Marc Zyngier <marc.zyngier@arm.com>
M.
--
Jazz is not dead. It just smells funny...
^ permalink raw reply
* [PATCH v2 11/36] KVM: arm64: Introduce VHE-specific kvm_vcpu_run
From: Marc Zyngier @ 2017-12-11 9:53 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20171207170630.592-12-christoffer.dall@linaro.org>
On 07/12/17 17:06, Christoffer Dall wrote:
> So far this is just a copy of the legacy non-VHE switch function, where
> we only change the existing calls to has_vhe() in both the original and
> new functions.
I'm not sure I correctly parse the above. Do you want to say that you
use has_vhe() to select the right world switch back-end? Or did you mean
to drop some of the has_vhe() calls in the non-VHE case?
>
> Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
> ---
>
> Notes:
> Changes since v1:
> - Rename kvm_vcpu_run to kvm_vcpu_run_vhe and rename __kvm_vcpu_run to
> __kvm_vcpu_run_nvhe
> - Removed stray whitespace line
>
> arch/arm/include/asm/kvm_asm.h | 5 +++-
> arch/arm/kvm/hyp/switch.c | 2 +-
> arch/arm64/include/asm/kvm_asm.h | 4 ++-
> arch/arm64/kvm/hyp/switch.c | 58 +++++++++++++++++++++++++++++++++++++++-
> virt/kvm/arm/arm.c | 5 +++-
> 5 files changed, 69 insertions(+), 5 deletions(-)
>
> diff --git a/arch/arm/include/asm/kvm_asm.h b/arch/arm/include/asm/kvm_asm.h
> index 36dd2962a42d..4ac717276543 100644
> --- a/arch/arm/include/asm/kvm_asm.h
> +++ b/arch/arm/include/asm/kvm_asm.h
> @@ -70,7 +70,10 @@ extern void __kvm_tlb_flush_local_vmid(struct kvm_vcpu *vcpu);
>
> extern void __kvm_timer_set_cntvoff(u32 cntvoff_low, u32 cntvoff_high);
>
> -extern int __kvm_vcpu_run(struct kvm_vcpu *vcpu);
> +/* no VHE on 32-bit :( */
> +static inline int kvm_vcpu_run_vhe(struct kvm_vcpu *vcpu) { return 0; }
> +
> +extern int __kvm_vcpu_run_nvhe(struct kvm_vcpu *vcpu);
>
> extern void __init_stage2_translation(void);
>
> diff --git a/arch/arm/kvm/hyp/switch.c b/arch/arm/kvm/hyp/switch.c
> index c3b9799e2e13..7b2bd25e3b10 100644
> --- a/arch/arm/kvm/hyp/switch.c
> +++ b/arch/arm/kvm/hyp/switch.c
> @@ -153,7 +153,7 @@ static bool __hyp_text __populate_fault_info(struct kvm_vcpu *vcpu)
> return true;
> }
>
> -int __hyp_text __kvm_vcpu_run(struct kvm_vcpu *vcpu)
> +int __hyp_text __kvm_vcpu_run_nvhe(struct kvm_vcpu *vcpu)
> {
> struct kvm_cpu_context *host_ctxt;
> struct kvm_cpu_context *guest_ctxt;
> diff --git a/arch/arm64/include/asm/kvm_asm.h b/arch/arm64/include/asm/kvm_asm.h
> index 33e0edc6f8be..adaf1db12271 100644
> --- a/arch/arm64/include/asm/kvm_asm.h
> +++ b/arch/arm64/include/asm/kvm_asm.h
> @@ -58,7 +58,9 @@ extern void __kvm_tlb_flush_local_vmid(struct kvm_vcpu *vcpu);
>
> extern void __kvm_timer_set_cntvoff(u32 cntvoff_low, u32 cntvoff_high);
>
> -extern int __kvm_vcpu_run(struct kvm_vcpu *vcpu);
> +extern int kvm_vcpu_run_vhe(struct kvm_vcpu *vcpu);
> +
> +extern int __kvm_vcpu_run_nvhe(struct kvm_vcpu *vcpu);
>
> extern u64 __vgic_v3_get_ich_vtr_el2(void);
> extern u64 __vgic_v3_read_vmcr(void);
> diff --git a/arch/arm64/kvm/hyp/switch.c b/arch/arm64/kvm/hyp/switch.c
> index 845e3bece399..8f32f8dcab65 100644
> --- a/arch/arm64/kvm/hyp/switch.c
> +++ b/arch/arm64/kvm/hyp/switch.c
> @@ -342,7 +342,63 @@ static bool __hyp_text fixup_guest_exit(struct kvm_vcpu *vcpu, u64 *exit_code)
> return false;
> }
>
> -int __hyp_text __kvm_vcpu_run(struct kvm_vcpu *vcpu)
> +/* Switch to the guest for VHE systems running in EL2 */
> +int kvm_vcpu_run_vhe(struct kvm_vcpu *vcpu)
> +{
> + struct kvm_cpu_context *host_ctxt;
> + struct kvm_cpu_context *guest_ctxt;
> + u64 exit_code;
> +
> + vcpu = kern_hyp_va(vcpu);
> +
> + host_ctxt = kern_hyp_va(vcpu->arch.host_cpu_context);
> + host_ctxt->__hyp_running_vcpu = vcpu;
> + guest_ctxt = &vcpu->arch.ctxt;
> +
> + __sysreg_save_host_state(host_ctxt);
> +
> + __activate_traps(vcpu);
> + __activate_vm(vcpu);
> +
> + __vgic_restore_state(vcpu);
> + __timer_enable_traps(vcpu);
> +
> + /*
> + * We must restore the 32-bit state before the sysregs, thanks
> + * to erratum #852523 (Cortex-A57) or #853709 (Cortex-A72).
> + */
> + __sysreg32_restore_state(vcpu);
> + __sysreg_restore_guest_state(guest_ctxt);
> + __debug_switch_to_guest(vcpu);
> +
> + do {
> + /* Jump in the fire! */
> + exit_code = __guest_enter(vcpu, host_ctxt);
> +
> + /* And we're baaack! */
> + } while (fixup_guest_exit(vcpu, &exit_code));
> +
> + __sysreg_save_guest_state(guest_ctxt);
> + __sysreg32_save_state(vcpu);
> + __timer_disable_traps(vcpu);
> + __vgic_save_state(vcpu);
> +
> + __deactivate_traps(vcpu);
> + __deactivate_vm(vcpu);
> +
> + __sysreg_restore_host_state(host_ctxt);
> +
> + /*
> + * This must come after restoring the host sysregs, since a non-VHE
> + * system may enable SPE here and make use of the TTBRs.
> + */
> + __debug_switch_to_host(vcpu);
> +
> + return exit_code;
> +}
> +
> +/* Switch to the guest for legacy non-VHE systems */
> +int __hyp_text __kvm_vcpu_run_nvhe(struct kvm_vcpu *vcpu)
> {
> struct kvm_cpu_context *host_ctxt;
> struct kvm_cpu_context *guest_ctxt;
> diff --git a/virt/kvm/arm/arm.c b/virt/kvm/arm/arm.c
> index 3e10343374a1..104ee524c75a 100644
> --- a/virt/kvm/arm/arm.c
> +++ b/virt/kvm/arm/arm.c
> @@ -712,7 +712,10 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *run)
> trace_kvm_entry(*vcpu_pc(vcpu));
> guest_enter_irqoff();
>
> - ret = kvm_call_hyp(__kvm_vcpu_run, vcpu);
> + if (has_vhe())
> + ret = kvm_vcpu_run_vhe(vcpu);
> + else
> + ret = kvm_call_hyp(__kvm_vcpu_run_nvhe, vcpu);
>
> vcpu->mode = OUTSIDE_GUEST_MODE;
> vcpu->stat.exits++;
>
Otherwise looks good to me.
M.
--
Jazz is not dead. It just smells funny...
^ permalink raw reply
* [PATCH v6 3/6] clk: meson-axg: add clock controller drivers
From: Jerome Brunet @ 2017-12-11 9:46 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20171211064853.32111-4-yixun.lan@amlogic.com>
On Mon, 2017-12-11 at 14:48 +0800, Yixun Lan wrote:
> From: Qiufang Dai <qiufang.dai@amlogic.com>
>
> Add clock controller drivers for Amlogic Meson-AXG SoC.
>
> Acked-by: Neil Armstrong <narmstrong@baylibre.com>
> Signed-off-by: Qiufang Dai <qiufang.dai@amlogic.com>
> Signed-off-by: Yixun Lan <yixun.lan@amlogic.com>
> ---
> arch/arm64/Kconfig.platforms | 1 +
> drivers/clk/meson/Kconfig | 8 +
> drivers/clk/meson/Makefile | 1 +
> drivers/clk/meson/axg.c | 944
> +++++++++++++++++++++++++++++++++++++++++++
> drivers/clk/meson/axg.h | 126 ++++++
> 5 files changed, 1080 insertions(+)
> create mode 100644 drivers/clk/meson/axg.c
> create mode 100644 drivers/clk/meson/axg.h
Overall, the changes looks good to me.
I still have a few comments which I'd like to see addressed quickly after this
series is merged
[...]
>
> +static struct meson_clk_pll axg_fixed_pll = {
> + .m = {
> + .reg_off = HHI_MPLL_CNTL,
> + .shift = 0,
> + .width = 9,
> + },
> + .n = {
> + .reg_off = HHI_MPLL_CNTL,
> + .shift = 9,
> + .width = 5,
> + },
> + .od = {
> + .reg_off = HHI_MPLL_CNTL,
> + .shift = 16,
> + .width = 2,
> + },
> + .lock = &clk_lock,
> + .hw.init = &(struct clk_init_data){
> + .name = "fixed_pll",
> + .ops = &meson_clk_pll_ro_ops,
> + .parent_names = (const char *[]){ "xtal" },
> + .num_parents = 1,
> + .flags = CLK_GET_RATE_NOCACHE,
Is the rate of this clock supposed to changed by something else than
the CCF after boot ?
If not, you should drop this flag.
Same comment goes for axg_sys_pll and axg_gp0_pll
> + },
> +};
[...]
> +/*
> + * FIXME The legacy composite clocks (e.g. clk81) are both PLL post-dividers
> + * and should be modeled with their respective PLLs via the forthcoming
> + * coordinated clock rates feature
> + */
> +static u32 mux_table_clk81[] = { 0, 2, 3, 4, 5, 6, 7 };
> +static const char * const clk81_parent_names[] = {
> + "xtal", "fclk_div7", "mpll1", "mpll2", "fclk_div4",
> + "fclk_div3", "fclk_div5"
> +};
> +
> +static struct clk_mux axg_mpeg_clk_sel = {
> + .reg = (void *)HHI_MPEG_CLK_CNTL,
> + .mask = 0x7,
> + .shift = 12,
> + .flags = CLK_MUX_READ_ONLY,
> + .table = mux_table_clk81,
> + .lock = &clk_lock,
> + .hw.init = &(struct clk_init_data){
> + .name = "mpeg_clk_sel",
> + .ops = &clk_mux_ro_ops,
> + /*
> + * bits 14:12 selects from 8 possible parents:
> + * xtal, 1'b0 (wtf), fclk_div7, mpll_clkout1, mpll_clkout2,
> + * fclk_div4, fclk_div3, fclk_div5
> + */
This comment is not necessary with table above.
> + .parent_names = clk81_parent_names,
> + .num_parents = ARRAY_SIZE(clk81_parent_names),
> + .flags = CLK_SET_RATE_NO_REPARENT,
With ro_ops, this flag is not necessary, consider removing it.
> + },
> +};
> +
>
^ permalink raw reply
* [PATCH v2 10/36] KVM: arm64: Factor out fault info population and gic workarounds
From: Marc Zyngier @ 2017-12-11 9:45 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20171207170630.592-11-christoffer.dall@linaro.org>
On 07/12/17 17:06, Christoffer Dall wrote:
> The current world-switch function has functionality to detect a number
> of cases where we need to fixup some part of the exit condition and
> possibly run the guest again, before having restored the host state.
>
> This includes populating missing fault info, emulating GICv2 CPU
> interface accesses when mapped at unaligned addresses, and emulating
> the GICv3 CPU interface on systems that need it.
>
> As we are about to have an alternative switch function for VHE systems,
> but VHE systems still need the same early fixup logic, factor out this
> logic into a separate function that can be shared by both switch
> functions.
>
> No functional change.
>
> Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
Acked-by: Marc Zyngier <marc.zyngier@arm.com>
M.
--
Jazz is not dead. It just smells funny...
^ permalink raw reply
* Linux kernel configuration for MPS2 AN385
From: Vladimir Murzin @ 2017-12-11 9:43 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <e529f3cb-da35-269c-83e3-bc07816904b9@roeck-us.net>
On 09/12/17 18:33, Guenter Roeck wrote:
> Hi folks,
>
> I am playing with qemu's mps2-an385 emulation and try to get Linux to boot with it,
> so far with little (ie no) success.
>
> Is a working kernel configuration for this board available somewhere ?
make ARCH=arm mps2_defconfig
would give you an Image and mps2-an385.dtb suitable for AN385.
You also need a simple wrapper to pass control to kernel... I think
you can get some clue from [1] as well.
[1] https://community.arm.com/dev-platforms/b/documents/posts/instructions-for-running-uclinux-on-arm-s-mps2-platform
Cheers
Vladimir
>
> Thanks,
> Guenter
>
^ permalink raw reply
* [PATCH v2 09/36] KVM: arm64: Improve debug register save/restore flow
From: Marc Zyngier @ 2017-12-11 9:40 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20171207170630.592-10-christoffer.dall@linaro.org>
On 07/12/17 17:06, Christoffer Dall wrote:
> Instead of having multiple calls from the world switch path to the debug
> logic, each figuring out if the dirty bit is set and if we should
> save/restore the debug registers, let's just provide two hooks to the
> debug save/restore functionality, one for switching to the guest
> context, and one for switching to the host context, and we get the
> benefit of only having to evaluate the dirty flag once on each path,
> plus we give the compiler some more room to inline some of this
> functionality.
>
> Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
Reviewed-by: Marc Zyngier <marc.zyngier@arm.com>
M.
--
Jazz is not dead. It just smells funny...
^ permalink raw reply
* [PATCH 0/5] Add STM32F769 pinctrl support
From: Alexandre Torgue @ 2017-12-11 9:37 UTC (permalink / raw)
To: linux-arm-kernel
This series adds STM32F769 pinctrl and GPIO support, relies on the
generic STM32 pinctrl driver. It also changes stm32f7 device tree
structure to use dedicated files for stm32f746 pinctrl and stm32f769
pinctrl.
Regards
Alex
Alexandre Torgue (5):
dt-bindings: pinctrl: Add st,stm32f769-pinctrl compatible to
stm32-pinctrl
pinctrl: stm32: add STM32F769 MCU support
ARM: mach-stm32: Kconfig: introduce MACH_STM32F769 flag
ARM: mach-stm32: add new STM32F769 MCU
ARM: dts: stm32: use dedicated files for pinctrl on stm32f7 family
Documentation/arm/stm32/stm32f769-overview.txt | 36 +
.../bindings/pinctrl/st,stm32-pinctrl.txt | 1 +
arch/arm/boot/dts/stm32746g-eval.dts | 1 +
arch/arm/boot/dts/stm32f7-pinctrl.dtsi | 227 +++
arch/arm/boot/dts/stm32f746-disco.dts | 1 +
arch/arm/boot/dts/stm32f746-pinctrl.dtsi | 11 +
arch/arm/boot/dts/stm32f746.dtsi | 217 ---
arch/arm/boot/dts/stm32f769-disco.dts | 3 +-
arch/arm/boot/dts/stm32f769-pinctrl.dtsi | 11 +
arch/arm/mach-stm32/Kconfig | 5 +
arch/arm/mach-stm32/board-dt.c | 1 +
drivers/pinctrl/stm32/Kconfig | 6 +
drivers/pinctrl/stm32/Makefile | 1 +
drivers/pinctrl/stm32/pinctrl-stm32f769.c | 1827 ++++++++++++++++++++
14 files changed, 2130 insertions(+), 218 deletions(-)
create mode 100644 Documentation/arm/stm32/stm32f769-overview.txt
create mode 100644 arch/arm/boot/dts/stm32f7-pinctrl.dtsi
create mode 100644 arch/arm/boot/dts/stm32f746-pinctrl.dtsi
create mode 100644 arch/arm/boot/dts/stm32f769-pinctrl.dtsi
create mode 100644 drivers/pinctrl/stm32/pinctrl-stm32f769.c
--
2.7.4
^ permalink raw reply
* [PATCH v2 01/36] KVM: arm64: Avoid storing the vcpu pointer on the stack
From: Marc Zyngier @ 2017-12-11 9:35 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20171211093031.GF910@cbox>
On 11/12/17 09:30, Christoffer Dall wrote:
> On Sat, Dec 09, 2017 at 05:19:41PM +0000, Marc Zyngier wrote:
>> On Thu, 07 Dec 2017 17:05:55 +0000,
>> Christoffer Dall wrote:
>>>
>>> We already have the percpu area for the host cpu state, which points to
>>> the VCPU, so there's no need to store the VCPU pointer on the stack on
>>> every context switch. We can be a little more clever and just use
>>> tpidr_el2 for the percpu offset and load the VCPU pointer from the host
>>> context.
>>>
>>> This does require us to calculate the percpu offset without including
>>> the offset from the kernel mapping of the percpu array to the linaro
>>
>> "linaro"?
>>
>
> *linear* - spell check must have played a trick on me.
>
>>> mapping of the array (which is what we store in tpidr_el1), because a
>>> PC-relative generated address in EL2 is already giving us the hyp alias
>>> of the linear mapping of a kernel address. We do this in
>>> __cpu_init_hyp_mode() by using kvm_ksym_ref().
>>>
>>> This change also requires us to have a scratch register, so we take the
>>> chance to rearrange some of the el1_sync code to only look at the
>>> vttbr_el2 to determine if this is a trap from the guest or an HVC from
>>> the host. We do add an extra check to call the panic code if the kernel
>>> is configured with debugging enabled and we saw a trap from the host
>>> which wasn't an HVC, indicating that we left some EL2 trap configured by
>>> mistake.
>>>
>>> The code that accesses ESR_EL2 was previously using an alternative to
>>> use the _EL1 accessor on VHE systems, but this was actually unnecessary
>>> as the _EL1 accessor aliases the ESR_EL2 register on VHE, and the _EL2
>>> accessor does the same thing on both systems.
>>>
>>> Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
>>> Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
>>> ---
>>>
>>> Notes:
>>> Changes since v1:
>>> - Use PC-relative addressing to access per-cpu variables instead of
>>> using a load from the literal pool.
>>> - Remove stale comments as pointed out by Marc
>>> - Reworded the commit message as suggested by Drew
>>>
>>> arch/arm64/include/asm/kvm_asm.h | 15 ++++++++++++++
>>> arch/arm64/include/asm/kvm_host.h | 15 ++++++++++++++
>>> arch/arm64/kernel/asm-offsets.c | 1 +
>>> arch/arm64/kvm/hyp/entry.S | 6 +-----
>>> arch/arm64/kvm/hyp/hyp-entry.S | 41 ++++++++++++++++++---------------------
>>> arch/arm64/kvm/hyp/switch.c | 5 +----
>>> arch/arm64/kvm/hyp/sysreg-sr.c | 5 +++++
>>> 7 files changed, 57 insertions(+), 31 deletions(-)
>>>
>>> diff --git a/arch/arm64/include/asm/kvm_asm.h b/arch/arm64/include/asm/kvm_asm.h
>>> index ab4d0a926043..33e0edc6f8be 100644
>>> --- a/arch/arm64/include/asm/kvm_asm.h
>>> +++ b/arch/arm64/include/asm/kvm_asm.h
>>> @@ -33,6 +33,7 @@
>>> #define KVM_ARM64_DEBUG_DIRTY_SHIFT 0
>>> #define KVM_ARM64_DEBUG_DIRTY (1 << KVM_ARM64_DEBUG_DIRTY_SHIFT)
>>>
>>> +/* Translate a kernel address of @sym into its equivalent linear mapping */
>>> #define kvm_ksym_ref(sym) \
>>> ({ \
>>> void *val = &sym; \
>>> @@ -70,4 +71,18 @@ extern u32 __init_stage2_translation(void);
>>>
>>> #endif
>>>
>>> +#ifdef __ASSEMBLY__
>>
>> You could turn this and the previous #endif into a simple #else.
>>
>
> yup
>
>>> +.macro get_host_ctxt reg, tmp
>>> + adr_l \reg, kvm_host_cpu_state
>>> + mrs \tmp, tpidr_el2
>>> + add \reg, \reg, \tmp
>>> +.endm
>>> +
>>> +.macro get_vcpu vcpu, ctxt
>>> + ldr \vcpu, [\ctxt, #HOST_CONTEXT_VCPU]
>>> + kern_hyp_va \vcpu
>>> +.endm
>>> +
>>> +#endif
>>> +
>>> #endif /* __ARM_KVM_ASM_H__ */
>>> diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
>>> index 7ee72b402907..af58deb6ec3c 100644
>>> --- a/arch/arm64/include/asm/kvm_host.h
>>> +++ b/arch/arm64/include/asm/kvm_host.h
>>> @@ -348,10 +348,15 @@ int kvm_perf_teardown(void);
>>>
>>> struct kvm_vcpu *kvm_mpidr_to_vcpu(struct kvm *kvm, unsigned long mpidr);
>>>
>>> +extern void __kvm_set_tpidr_el2(u64 tpidr_el2);
>>
>> Is there any advantage in having this prototype in kvm_host.h, instead
>> of putting it in kvm_hyp.h (which feels more appropriate)?
>>
>
> asm-offsets.c pukes all over the place and I can't include asm/kvm_hyp.h
> from kvm_host.h, because it depends on kvm_host.h, and I can't include
> asm/kvm_hyp.h easily in asm-offsets.c because it pukes again from all
> sorts of other missing things.
>
> If you care strongly about this point, I can try to dig deeper in this
> or refactor this somehow more substantially. Ideas?
Yeah. I've fixed a couple of the asm-offsets crap (see my randomization
series), but it is really not worth adding a dependency on that. Forget
about it for now, we'll address it at a later time, if ever.
Thanks,
M./
--
Jazz is not dead. It just smells funny...
^ permalink raw reply
* [PATCH] ARM: debug: add stm32 low-level debug support
From: Philippe Ombredanne @ 2017-12-11 9:33 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <edcc6666-31eb-5404-0a3e-fa6051707408@st.com>
Ludovic,
On Mon, Dec 11, 2017 at 10:08 AM, Alexandre Torgue
<alexandre.torgue@st.com> wrote:
> Hi Ludovic
>
> On 12/04/2017 02:32 PM, Ludovic Barre wrote:
>>
>> From: Ludovic Barre <ludovic.barre@st.com>
>>
>> This adds low-level debug support on USART1 for STM32F4
>> and STM32F7. Compiled via 'CONFIG_DEBUG_LL' and 'CONFIG_EARLY_PRINTK'.
>> Enabled via 'earlyprintk' in bootargs.
>>
>> Signed-off-by: Gerald Baeza <gerald.baeza@st.com>
>
>
> Acked-by: Alexandre TORGUE <alexandre.torgue@st.com>
[...]
>> --- /dev/null
>> +++ b/arch/arm/include/debug/stm32.S
>> @@ -0,0 +1,41 @@
>> +/*
>> + * Copyright (C) 2017, STMicroelectronics - All Rights Reserved
>> + * Author: Gerald Baeza <gerald_baeza@st.com>
>> + * License terms: GNU General Public License (GPL), version 2
Have you considered using the new SPDX ids? See THomas doc patches for details.
--
Cordially
Philippe Ombredanne
^ permalink raw reply
* [PATCH v2 06/36] KVM: arm64: Defer restoring host VFP state to vcpu_put
From: Christoffer Dall @ 2017-12-11 9:31 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <864lozssy6.wl-marc.zyngier@arm.com>
On Sat, Dec 09, 2017 at 05:37:53PM +0000, Marc Zyngier wrote:
> On Thu, 07 Dec 2017 17:06:00 +0000,
> Christoffer Dall wrote:
> >
> > Avoid saving the guest VFP registers and restoring the host VFP
> > registers on every exit from the VM. Only when we're about to run
> > userspace or other threads in the kernel do we really have to switch the
> > state back to the host state.
> >
> > We still initially configure the VFP registers to trap when entering the
> > VM, but the difference is that we now leave the guest state in the
> > hardware registers as long as we're running this VCPU, even if we
> > occasionally trap to the host, and we only restore the host state when
> > we return to user space or when scheduling another thread.
> >
> > Reviewed-by: Andrew Jones <drjones@redhat.com>
> > Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
> > ---
> >
> > Notes:
> > Changes since v1:
> > - Cosmetic changes
> > - Change the flags variable to a u8
> > - Expanded the commit message
> >
> > arch/arm64/include/asm/kvm_emulate.h | 5 ++++
> > arch/arm64/include/asm/kvm_host.h | 3 +++
> > arch/arm64/kernel/asm-offsets.c | 1 +
> > arch/arm64/kvm/hyp/entry.S | 3 +++
> > arch/arm64/kvm/hyp/switch.c | 48 +++++++++++-------------------------
> > arch/arm64/kvm/hyp/sysreg-sr.c | 22 ++++++++++++++---
> > 6 files changed, 46 insertions(+), 36 deletions(-)
> >
> > diff --git a/arch/arm64/include/asm/kvm_emulate.h b/arch/arm64/include/asm/kvm_emulate.h
> > index b36aaa1fe332..635137e6ed1c 100644
> > --- a/arch/arm64/include/asm/kvm_emulate.h
> > +++ b/arch/arm64/include/asm/kvm_emulate.h
> > @@ -67,6 +67,11 @@ static inline unsigned long *vcpu_hcr(struct kvm_vcpu *vcpu)
> > return (unsigned long *)&vcpu->arch.hcr_el2;
> > }
> >
> > +static inline bool vcpu_el1_is_32bit(struct kvm_vcpu *vcpu)
> > +{
> > + return !(vcpu->arch.hcr_el2 & HCR_RW);
> > +}
>
> Since you now introduce this helper, could you use it to repaint
> inject_fault.c which could make use of it too? This could actually be
> a separate patch.
>
Yes, I'll do that first, and the have this patch follow.
> > +
> > static inline unsigned long *vcpu_pc(const struct kvm_vcpu *vcpu)
> > {
> > return (unsigned long *)&vcpu_gp_regs(vcpu)->regs.pc;
> > diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
> > index 20fab9194794..c841eeeeb5c5 100644
> > --- a/arch/arm64/include/asm/kvm_host.h
> > +++ b/arch/arm64/include/asm/kvm_host.h
> > @@ -211,6 +211,9 @@ struct kvm_vcpu_arch {
> > /* Guest debug state */
> > u64 debug_flags;
> >
> > + /* 1 if the guest VFP state is loaded into the hardware */
> > + u8 guest_vfp_loaded;
> > +
> > /*
> > * We maintain more than a single set of debug registers to support
> > * debugging the guest from the host and to maintain separate host and
> > diff --git a/arch/arm64/kernel/asm-offsets.c b/arch/arm64/kernel/asm-offsets.c
> > index 612021dce84f..99467327c043 100644
> > --- a/arch/arm64/kernel/asm-offsets.c
> > +++ b/arch/arm64/kernel/asm-offsets.c
> > @@ -133,6 +133,7 @@ int main(void)
> > DEFINE(CPU_GP_REGS, offsetof(struct kvm_cpu_context, gp_regs));
> > DEFINE(CPU_USER_PT_REGS, offsetof(struct kvm_regs, regs));
> > DEFINE(CPU_FP_REGS, offsetof(struct kvm_regs, fp_regs));
> > + DEFINE(VCPU_GUEST_VFP_LOADED, offsetof(struct kvm_vcpu, arch.guest_vfp_loaded));
> > DEFINE(VCPU_FPEXC32_EL2, offsetof(struct kvm_vcpu, arch.ctxt.sys_regs[FPEXC32_EL2]));
> > DEFINE(VCPU_HOST_CONTEXT, offsetof(struct kvm_vcpu, arch.host_cpu_context));
> > DEFINE(HOST_CONTEXT_VCPU, offsetof(struct kvm_cpu_context, __hyp_running_vcpu));
> > diff --git a/arch/arm64/kvm/hyp/entry.S b/arch/arm64/kvm/hyp/entry.S
> > index a360ac6e89e9..53652287a236 100644
> > --- a/arch/arm64/kvm/hyp/entry.S
> > +++ b/arch/arm64/kvm/hyp/entry.S
> > @@ -184,6 +184,9 @@ alternative_endif
> > add x0, x2, #CPU_GP_REG_OFFSET(CPU_FP_REGS)
> > bl __fpsimd_restore_state
> >
> > + mov x0, #1
> > + strb w0, [x3, #VCPU_GUEST_VFP_LOADED]
> > +
> > // Skip restoring fpexc32 for AArch64 guests
> > mrs x1, hcr_el2
> > tbnz x1, #HCR_RW_SHIFT, 1f
> > diff --git a/arch/arm64/kvm/hyp/switch.c b/arch/arm64/kvm/hyp/switch.c
> > index 11ec1c6f3b84..f5d53ef9ca79 100644
> > --- a/arch/arm64/kvm/hyp/switch.c
> > +++ b/arch/arm64/kvm/hyp/switch.c
> > @@ -24,43 +24,32 @@
> > #include <asm/fpsimd.h>
> > #include <asm/debug-monitors.h>
> >
> > -static bool __hyp_text __fpsimd_enabled_nvhe(void)
> > -{
> > - return !(read_sysreg(cptr_el2) & CPTR_EL2_TFP);
> > -}
> > -
> > -static bool __hyp_text __fpsimd_enabled_vhe(void)
> > -{
> > - return !!(read_sysreg(cpacr_el1) & CPACR_EL1_FPEN);
> > -}
> > -
> > -static hyp_alternate_select(__fpsimd_is_enabled,
> > - __fpsimd_enabled_nvhe, __fpsimd_enabled_vhe,
> > - ARM64_HAS_VIRT_HOST_EXTN);
> > -
> > -bool __hyp_text __fpsimd_enabled(void)
> > -{
> > - return __fpsimd_is_enabled()();
> > -}
> > -
> > -static void __hyp_text __activate_traps_vhe(void)
> > +static void __hyp_text __activate_traps_vhe(struct kvm_vcpu *vcpu)
> > {
> > u64 val;
> >
> > val = read_sysreg(cpacr_el1);
> > val |= CPACR_EL1_TTA;
> > - val &= ~(CPACR_EL1_FPEN | CPACR_EL1_ZEN);
> > + val &= ~CPACR_EL1_ZEN;
> > + if (vcpu->arch.guest_vfp_loaded)
> > + val |= CPACR_EL1_FPEN;
> > + else
> > + val &= ~CPACR_EL1_FPEN;
> > write_sysreg(val, cpacr_el1);
> >
> > write_sysreg(__kvm_hyp_vector, vbar_el1);
> > }
> >
> > -static void __hyp_text __activate_traps_nvhe(void)
> > +static void __hyp_text __activate_traps_nvhe(struct kvm_vcpu *vcpu)
> > {
> > u64 val;
> >
> > val = CPTR_EL2_DEFAULT;
> > - val |= CPTR_EL2_TTA | CPTR_EL2_TFP | CPTR_EL2_TZ;
> > + val |= CPTR_EL2_TTA | CPTR_EL2_TZ;
> > + if (vcpu->arch.guest_vfp_loaded)
> > + val &= ~CPTR_EL2_TFP;
> > + else
> > + val |= CPTR_EL2_TFP;
> > write_sysreg(val, cptr_el2);
> > }
> >
> > @@ -83,7 +72,8 @@ static void __hyp_text __activate_traps(struct kvm_vcpu *vcpu)
> > */
> > val = vcpu->arch.hcr_el2;
> >
> > - if (!(val & HCR_RW) && system_supports_fpsimd()) {
> > + if (vcpu_el1_is_32bit(vcpu) && system_supports_fpsimd() &&
> > + !vcpu->arch.guest_vfp_loaded) {
> > write_sysreg(1 << 30, fpexc32_el2);
> > isb();
> > }
> > @@ -100,7 +90,7 @@ static void __hyp_text __activate_traps(struct kvm_vcpu *vcpu)
> > write_sysreg(0, pmselr_el0);
> > write_sysreg(ARMV8_PMU_USERENR_MASK, pmuserenr_el0);
> > write_sysreg(vcpu->arch.mdcr_el2, mdcr_el2);
> > - __activate_traps_arch()();
> > + __activate_traps_arch()(vcpu);
> > }
> >
> > static void __hyp_text __deactivate_traps_vhe(void)
> > @@ -288,7 +278,6 @@ int __hyp_text __kvm_vcpu_run(struct kvm_vcpu *vcpu)
> > {
> > struct kvm_cpu_context *host_ctxt;
> > struct kvm_cpu_context *guest_ctxt;
> > - bool fp_enabled;
> > u64 exit_code;
> >
> > vcpu = kern_hyp_va(vcpu);
> > @@ -380,8 +369,6 @@ int __hyp_text __kvm_vcpu_run(struct kvm_vcpu *vcpu)
> > /* 0 falls through to be handled out of EL2 */
> > }
> >
> > - fp_enabled = __fpsimd_enabled();
> > -
> > __sysreg_save_guest_state(guest_ctxt);
> > __sysreg32_save_state(vcpu);
> > __timer_disable_traps(vcpu);
> > @@ -392,11 +379,6 @@ int __hyp_text __kvm_vcpu_run(struct kvm_vcpu *vcpu)
> >
> > __sysreg_restore_host_state(host_ctxt);
> >
> > - if (fp_enabled) {
> > - __fpsimd_save_state(&guest_ctxt->gp_regs.fp_regs);
> > - __fpsimd_restore_state(&host_ctxt->gp_regs.fp_regs);
> > - }
> > -
> > __debug_save_state(vcpu, kern_hyp_va(vcpu->arch.debug_ptr), guest_ctxt);
> > /*
> > * This must come after restoring the host sysregs, since a non-VHE
> > diff --git a/arch/arm64/kvm/hyp/sysreg-sr.c b/arch/arm64/kvm/hyp/sysreg-sr.c
> > index cbbcd6f410a8..68a7d164e5e1 100644
> > --- a/arch/arm64/kvm/hyp/sysreg-sr.c
> > +++ b/arch/arm64/kvm/hyp/sysreg-sr.c
> > @@ -19,6 +19,7 @@
> > #include <linux/kvm_host.h>
> >
> > #include <asm/kvm_asm.h>
> > +#include <asm/kvm_emulate.h>
> > #include <asm/kvm_hyp.h>
> >
> > /* Yes, this does nothing, on purpose */
> > @@ -137,6 +138,11 @@ void __hyp_text __sysreg_restore_guest_state(struct kvm_cpu_context *ctxt)
> > __sysreg_restore_common_state(ctxt);
> > }
> >
> > +static void __hyp_text __fpsimd32_save_state(struct kvm_cpu_context *ctxt)
> > +{
> > + ctxt->sys_regs[FPEXC32_EL2] = read_sysreg(fpexc32_el2);
> > +}
> > +
> > void __hyp_text __sysreg32_save_state(struct kvm_vcpu *vcpu)
> > {
> > u64 *spsr, *sysreg;
> > @@ -155,9 +161,6 @@ void __hyp_text __sysreg32_save_state(struct kvm_vcpu *vcpu)
> > sysreg[DACR32_EL2] = read_sysreg(dacr32_el2);
> > sysreg[IFSR32_EL2] = read_sysreg(ifsr32_el2);
> >
> > - if (__fpsimd_enabled())
> > - sysreg[FPEXC32_EL2] = read_sysreg(fpexc32_el2);
> > -
> > if (vcpu->arch.debug_flags & KVM_ARM64_DEBUG_DIRTY)
> > sysreg[DBGVCR32_EL2] = read_sysreg(dbgvcr32_el2);
> > }
> > @@ -212,6 +215,19 @@ void kvm_vcpu_load_sysregs(struct kvm_vcpu *vcpu)
> > */
> > void kvm_vcpu_put_sysregs(struct kvm_vcpu *vcpu)
> > {
> > + struct kvm_cpu_context *host_ctxt = vcpu->arch.host_cpu_context;
> > + struct kvm_cpu_context *guest_ctxt = &vcpu->arch.ctxt;
> > +
> > + /* Restore host FP/SIMD state */
> > + if (vcpu->arch.guest_vfp_loaded) {
> > + if (vcpu_el1_is_32bit(vcpu)) {
> > + kvm_call_hyp(__fpsimd32_save_state,
> > + kern_hyp_va(guest_ctxt));
> > + }
> > + __fpsimd_save_state(&guest_ctxt->gp_regs.fp_regs);
> > + __fpsimd_restore_state(&host_ctxt->gp_regs.fp_regs);
> > + vcpu->arch.guest_vfp_loaded = 0;
> > + }
> > }
> >
> > void __hyp_text __kvm_set_tpidr_el2(u64 tpidr_el2)
> > --
> > 2.14.2
> >
>
> Otherwise,
>
> Reviewed-by: Marc Zyngier <marc.zyngier@arm.com>
>
Thanks!
-Christoffer
^ permalink raw reply
* [PATCH v2 01/36] KVM: arm64: Avoid storing the vcpu pointer on the stack
From: Christoffer Dall @ 2017-12-11 9:30 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <868tebstsi.wl-marc.zyngier@arm.com>
On Sat, Dec 09, 2017 at 05:19:41PM +0000, Marc Zyngier wrote:
> On Thu, 07 Dec 2017 17:05:55 +0000,
> Christoffer Dall wrote:
> >
> > We already have the percpu area for the host cpu state, which points to
> > the VCPU, so there's no need to store the VCPU pointer on the stack on
> > every context switch. We can be a little more clever and just use
> > tpidr_el2 for the percpu offset and load the VCPU pointer from the host
> > context.
> >
> > This does require us to calculate the percpu offset without including
> > the offset from the kernel mapping of the percpu array to the linaro
>
> "linaro"?
>
*linear* - spell check must have played a trick on me.
> > mapping of the array (which is what we store in tpidr_el1), because a
> > PC-relative generated address in EL2 is already giving us the hyp alias
> > of the linear mapping of a kernel address. We do this in
> > __cpu_init_hyp_mode() by using kvm_ksym_ref().
> >
> > This change also requires us to have a scratch register, so we take the
> > chance to rearrange some of the el1_sync code to only look at the
> > vttbr_el2 to determine if this is a trap from the guest or an HVC from
> > the host. We do add an extra check to call the panic code if the kernel
> > is configured with debugging enabled and we saw a trap from the host
> > which wasn't an HVC, indicating that we left some EL2 trap configured by
> > mistake.
> >
> > The code that accesses ESR_EL2 was previously using an alternative to
> > use the _EL1 accessor on VHE systems, but this was actually unnecessary
> > as the _EL1 accessor aliases the ESR_EL2 register on VHE, and the _EL2
> > accessor does the same thing on both systems.
> >
> > Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> > Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
> > ---
> >
> > Notes:
> > Changes since v1:
> > - Use PC-relative addressing to access per-cpu variables instead of
> > using a load from the literal pool.
> > - Remove stale comments as pointed out by Marc
> > - Reworded the commit message as suggested by Drew
> >
> > arch/arm64/include/asm/kvm_asm.h | 15 ++++++++++++++
> > arch/arm64/include/asm/kvm_host.h | 15 ++++++++++++++
> > arch/arm64/kernel/asm-offsets.c | 1 +
> > arch/arm64/kvm/hyp/entry.S | 6 +-----
> > arch/arm64/kvm/hyp/hyp-entry.S | 41 ++++++++++++++++++---------------------
> > arch/arm64/kvm/hyp/switch.c | 5 +----
> > arch/arm64/kvm/hyp/sysreg-sr.c | 5 +++++
> > 7 files changed, 57 insertions(+), 31 deletions(-)
> >
> > diff --git a/arch/arm64/include/asm/kvm_asm.h b/arch/arm64/include/asm/kvm_asm.h
> > index ab4d0a926043..33e0edc6f8be 100644
> > --- a/arch/arm64/include/asm/kvm_asm.h
> > +++ b/arch/arm64/include/asm/kvm_asm.h
> > @@ -33,6 +33,7 @@
> > #define KVM_ARM64_DEBUG_DIRTY_SHIFT 0
> > #define KVM_ARM64_DEBUG_DIRTY (1 << KVM_ARM64_DEBUG_DIRTY_SHIFT)
> >
> > +/* Translate a kernel address of @sym into its equivalent linear mapping */
> > #define kvm_ksym_ref(sym) \
> > ({ \
> > void *val = &sym; \
> > @@ -70,4 +71,18 @@ extern u32 __init_stage2_translation(void);
> >
> > #endif
> >
> > +#ifdef __ASSEMBLY__
>
> You could turn this and the previous #endif into a simple #else.
>
yup
> > +.macro get_host_ctxt reg, tmp
> > + adr_l \reg, kvm_host_cpu_state
> > + mrs \tmp, tpidr_el2
> > + add \reg, \reg, \tmp
> > +.endm
> > +
> > +.macro get_vcpu vcpu, ctxt
> > + ldr \vcpu, [\ctxt, #HOST_CONTEXT_VCPU]
> > + kern_hyp_va \vcpu
> > +.endm
> > +
> > +#endif
> > +
> > #endif /* __ARM_KVM_ASM_H__ */
> > diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
> > index 7ee72b402907..af58deb6ec3c 100644
> > --- a/arch/arm64/include/asm/kvm_host.h
> > +++ b/arch/arm64/include/asm/kvm_host.h
> > @@ -348,10 +348,15 @@ int kvm_perf_teardown(void);
> >
> > struct kvm_vcpu *kvm_mpidr_to_vcpu(struct kvm *kvm, unsigned long mpidr);
> >
> > +extern void __kvm_set_tpidr_el2(u64 tpidr_el2);
>
> Is there any advantage in having this prototype in kvm_host.h, instead
> of putting it in kvm_hyp.h (which feels more appropriate)?
>
asm-offsets.c pukes all over the place and I can't include asm/kvm_hyp.h
from kvm_host.h, because it depends on kvm_host.h, and I can't include
asm/kvm_hyp.h easily in asm-offsets.c because it pukes again from all
sorts of other missing things.
If you care strongly about this point, I can try to dig deeper in this
or refactor this somehow more substantially. Ideas?
> > +DECLARE_PER_CPU(kvm_cpu_context_t, kvm_host_cpu_state);
> > +
> > static inline void __cpu_init_hyp_mode(phys_addr_t pgd_ptr,
> > unsigned long hyp_stack_ptr,
> > unsigned long vector_ptr)
> > {
> > + u64 tpidr_el2;
> > +
> > /*
> > * Call initialization code, and switch to the full blown HYP code.
> > * If the cpucaps haven't been finalized yet, something has gone very
> > @@ -360,6 +365,16 @@ static inline void __cpu_init_hyp_mode(phys_addr_t pgd_ptr,
> > */
> > BUG_ON(!static_branch_likely(&arm64_const_caps_ready));
> > __kvm_call_hyp((void *)pgd_ptr, hyp_stack_ptr, vector_ptr);
> > +
> > + /*
> > + * Calculate the raw per-cpu offset without a translation from the
> > + * kernel's mapping to the linear mapping, and store it in tpidr_el2
> > + * so that we can use adr_l to access per-cpu variables in EL2.
> > + */
> > + tpidr_el2 = (u64)this_cpu_ptr(&kvm_host_cpu_state)
> > + - (u64)kvm_ksym_ref(kvm_host_cpu_state);
> > +
> > + kvm_call_hyp(__kvm_set_tpidr_el2, tpidr_el2);
> > }
> >
> > static inline void kvm_arch_hardware_unsetup(void) {}
> > diff --git a/arch/arm64/kernel/asm-offsets.c b/arch/arm64/kernel/asm-offsets.c
> > index 71bf088f1e4b..612021dce84f 100644
> > --- a/arch/arm64/kernel/asm-offsets.c
> > +++ b/arch/arm64/kernel/asm-offsets.c
> > @@ -135,6 +135,7 @@ int main(void)
> > DEFINE(CPU_FP_REGS, offsetof(struct kvm_regs, fp_regs));
> > DEFINE(VCPU_FPEXC32_EL2, offsetof(struct kvm_vcpu, arch.ctxt.sys_regs[FPEXC32_EL2]));
> > DEFINE(VCPU_HOST_CONTEXT, offsetof(struct kvm_vcpu, arch.host_cpu_context));
> > + DEFINE(HOST_CONTEXT_VCPU, offsetof(struct kvm_cpu_context, __hyp_running_vcpu));
> > #endif
> > #ifdef CONFIG_CPU_PM
> > DEFINE(CPU_SUSPEND_SZ, sizeof(struct cpu_suspend_ctx));
> > diff --git a/arch/arm64/kvm/hyp/entry.S b/arch/arm64/kvm/hyp/entry.S
> > index 9a8ab5dddd9e..a360ac6e89e9 100644
> > --- a/arch/arm64/kvm/hyp/entry.S
> > +++ b/arch/arm64/kvm/hyp/entry.S
> > @@ -62,9 +62,6 @@ ENTRY(__guest_enter)
> > // Store the host regs
> > save_callee_saved_regs x1
> >
> > - // Store host_ctxt and vcpu for use at exit time
> > - stp x1, x0, [sp, #-16]!
> > -
> > add x18, x0, #VCPU_CONTEXT
> >
> > // Restore guest regs x0-x17
> > @@ -118,8 +115,7 @@ ENTRY(__guest_exit)
> > // Store the guest regs x19-x29, lr
> > save_callee_saved_regs x1
> >
> > - // Restore the host_ctxt from the stack
> > - ldr x2, [sp], #16
> > + get_host_ctxt x2, x3
> >
> > // Now restore the host regs
> > restore_callee_saved_regs x2
> > diff --git a/arch/arm64/kvm/hyp/hyp-entry.S b/arch/arm64/kvm/hyp/hyp-entry.S
> > index e4f37b9dd47c..71b4cc92895e 100644
> > --- a/arch/arm64/kvm/hyp/hyp-entry.S
> > +++ b/arch/arm64/kvm/hyp/hyp-entry.S
> > @@ -56,18 +56,15 @@ ENDPROC(__vhe_hyp_call)
> > el1_sync: // Guest trapped into EL2
> > stp x0, x1, [sp, #-16]!
> >
> > -alternative_if_not ARM64_HAS_VIRT_HOST_EXTN
> > - mrs x1, esr_el2
> > -alternative_else
> > - mrs x1, esr_el1
> > -alternative_endif
> > - lsr x0, x1, #ESR_ELx_EC_SHIFT
> > + mrs x1, vttbr_el2 // If vttbr is valid, this is a trap
> > + cbnz x1, el1_trap // from the guest
> >
> > - cmp x0, #ESR_ELx_EC_HVC64
> > - b.ne el1_trap
> > -
> > - mrs x1, vttbr_el2 // If vttbr is valid, the 64bit guest
> > - cbnz x1, el1_trap // called HVC
> > +#ifdef CONFIG_DEBUG
> > + mrs x0, esr_el2
> > + lsr x0, x0, #ESR_ELx_EC_SHIFT
> > + cmp x0, #ESR_ELx_EC_HVC64
> > + b.ne __hyp_panic
> > +#endif
> >
> > /* Here, we're pretty sure the host called HVC. */
> > ldp x0, x1, [sp], #16
> > @@ -101,10 +98,15 @@ alternative_endif
> > eret
> >
> > el1_trap:
> > + get_host_ctxt x0, x1
> > + get_vcpu x1, x0
> > +
> > + mrs x0, esr_el2
> > + lsr x0, x0, #ESR_ELx_EC_SHIFT
> > /*
> > * x0: ESR_EC
> > + * x1: vcpu pointer
> > */
> > - ldr x1, [sp, #16 + 8] // vcpu stored by __guest_enter
> >
> > /*
> > * We trap the first access to the FP/SIMD to save the host context
> > @@ -122,13 +124,15 @@ alternative_else_nop_endif
> >
> > el1_irq:
> > stp x0, x1, [sp, #-16]!
> > - ldr x1, [sp, #16 + 8]
> > + get_host_ctxt x0, x1
> > + get_vcpu x1, x0
> > mov x0, #ARM_EXCEPTION_IRQ
> > b __guest_exit
> >
> > el1_error:
> > stp x0, x1, [sp, #-16]!
> > - ldr x1, [sp, #16 + 8]
> > + get_host_ctxt x0, x1
> > + get_vcpu x1, x0
> > mov x0, #ARM_EXCEPTION_EL1_SERROR
> > b __guest_exit
> >
> > @@ -164,14 +168,7 @@ ENTRY(__hyp_do_panic)
> > ENDPROC(__hyp_do_panic)
> >
> > ENTRY(__hyp_panic)
> > - /*
> > - * '=kvm_host_cpu_state' is a host VA from the constant pool, it may
> > - * not be accessible by this address from EL2, hyp_panic() converts
> > - * it with kern_hyp_va() before use.
> > - */
> > - ldr x0, =kvm_host_cpu_state
> > - mrs x1, tpidr_el2
> > - add x0, x0, x1
> > + get_host_ctxt x0, x1
> > b hyp_panic
> > ENDPROC(__hyp_panic)
> >
> > diff --git a/arch/arm64/kvm/hyp/switch.c b/arch/arm64/kvm/hyp/switch.c
> > index f7307b6b42f0..6fcb37e220b5 100644
> > --- a/arch/arm64/kvm/hyp/switch.c
> > +++ b/arch/arm64/kvm/hyp/switch.c
> > @@ -449,7 +449,7 @@ static hyp_alternate_select(__hyp_call_panic,
> > __hyp_call_panic_nvhe, __hyp_call_panic_vhe,
> > ARM64_HAS_VIRT_HOST_EXTN);
> >
> > -void __hyp_text __noreturn hyp_panic(struct kvm_cpu_context *__host_ctxt)
> > +void __hyp_text __noreturn hyp_panic(struct kvm_cpu_context *host_ctxt)
> > {
> > struct kvm_vcpu *vcpu = NULL;
> >
> > @@ -458,9 +458,6 @@ void __hyp_text __noreturn hyp_panic(struct kvm_cpu_context *__host_ctxt)
> > u64 par = read_sysreg(par_el1);
> >
> > if (read_sysreg(vttbr_el2)) {
> > - struct kvm_cpu_context *host_ctxt;
> > -
> > - host_ctxt = kern_hyp_va(__host_ctxt);
> > vcpu = host_ctxt->__hyp_running_vcpu;
> > __timer_disable_traps(vcpu);
> > __deactivate_traps(vcpu);
> > diff --git a/arch/arm64/kvm/hyp/sysreg-sr.c b/arch/arm64/kvm/hyp/sysreg-sr.c
> > index c54cc2afb92b..e19d89cabf2a 100644
> > --- a/arch/arm64/kvm/hyp/sysreg-sr.c
> > +++ b/arch/arm64/kvm/hyp/sysreg-sr.c
> > @@ -183,3 +183,8 @@ void __hyp_text __sysreg32_restore_state(struct kvm_vcpu *vcpu)
> > if (vcpu->arch.debug_flags & KVM_ARM64_DEBUG_DIRTY)
> > write_sysreg(sysreg[DBGVCR32_EL2], dbgvcr32_el2);
> > }
> > +
> > +void __hyp_text __kvm_set_tpidr_el2(u64 tpidr_el2)
> > +{
> > + asm("msr tpidr_el2, %0": : "r" (tpidr_el2));
> > +}
> > --
> > 2.14.2
> >
>
> Other than the couple of nits above:
>
> Reviewed-by: Marc Zyngier <marc.zyngier@arm.com>
>
Thanks!
-Christoffer
^ permalink raw reply
* next/master boot: 270 boots: 35 failed, 213 passed with 20 offline, 2 untried/unknown (next-20171207)
From: Marek Szyprowski @ 2017-12-11 9:28 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20171208165943.GC4283@codeaurora.org>
Hi Stephen,
On 2017-12-08 17:59, Stephen Boyd wrote:
> On 12/08, Marek Szyprowski wrote:
>> On 2017-12-08 13:33, Krzysztof Kozlowski wrote:
>>> On Fri, Dec 8, 2017 at 1:27 PM, Mark Brown <broonie@kernel.org> wrote:
>>>> On Fri, Dec 08, 2017 at 12:20:07PM +0000, Mark Brown wrote:
>>>>> On Thu, Dec 07, 2017 at 03:54:47PM -0800, kernelci.org bot wrote:
>>>>>
>>>>> Today's -next failed to boot on peach-pi:
>>>>>
>>>>>> exynos_defconfig:
>>>>>> exynos5800-peach-pi:
>>>>>> lab-collabora: new failure (last pass: next-20171205)
>>>>> with details at https://kernelci.org/boot/id/5a2a2e7859b5141bc2afa17c/
>>>>> (including logs and comparisons with other boots, the last good boot was
>>>>> Wednesday). It looks like it hangs somewhere late on in boot, the last
>>>>> output on the console is:
>>>>>
>>>>> [ 4.827139] smsc95xx 3-1.1:1.0 eth0: register 'smsc95xx' at usb-xhci-hcd.3.auto-1.1, smsc95xx USB 2.0 Ethernet, 94:eb:2c:00:03:c0
>>>>> [ 5.781037] dma-pl330 3880000.adma: Loaded driver for PL330 DMAC-241330
>>>>> [ 5.786247] dma-pl330 3880000.adma: DBUFF-4x8bytes Num_Chans-6 Num_Peri-16 Num_Events-6
>>>>> [ 5.819200] dma-pl330 3880000.adma: PM domain MAU will not be powered off
>>>>> [ 64.529228] random: crng init done
>>>>>
>>>>> and there's failures earlier to instantiate the display.
>>>> I just noticed that further up the log there's a lockdep splat with a
>>>> conflict between the genpd and clock API locking - an ABBA issue with
>>>> genpd->mlock and the clock API prepare_lock.
>>> +Cc Marek Szyprowski,
>>>
>>> The lockdep issue and display failures (including regulator warning)
>>> were present for some time. They also appear in boot log for
>>> next-20171206 (https://storage.kernelci.org/next/master/next-20171206/arm/exynos_defconfig/lab-collabora/boot-exynos5800-peach-pi.html).
>>> The difference is that 20171208 hangs on "random: crng init done"
>>> which did not appear before at all.
> I haven't looked at the lockdep splat yet, but is that happening
> because of runtime PM usage by the clk framework?
This is a false positive. The deplock doesn't distinguish each domain
instance.
Only some instances of exynos power domains use clocks (as an old
workaround of
the lack possibility to integrate proper clock rate/topology restoration
after
power off/on cycle in the clock provider driver).
Those clock controllers, which implements runtime pm, are assigned to power
domain, which doesn't touch clocks at all.
I still have no idea how to fix the code to make deplock happy.
Best regards
--
Marek Szyprowski, PhD
Samsung R&D Institute Poland
^ permalink raw reply
* [PATCH] ARM: debug: add stm32 low-level debug support
From: Neil Armstrong @ 2017-12-11 9:28 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1512394376-25962-1-git-send-email-ludovic.Barre@st.com>
On 04/12/2017 14:32, Ludovic Barre wrote:
> From: Ludovic Barre <ludovic.barre@st.com>
>
> This adds low-level debug support on USART1 for STM32F4
> and STM32F7. Compiled via 'CONFIG_DEBUG_LL' and 'CONFIG_EARLY_PRINTK'.
> Enabled via 'earlyprintk' in bootargs.
>
> Signed-off-by: Gerald Baeza <gerald.baeza@st.com>
Hi Ludovic,
Please also add your sign-off here.
Neil
> ---
> arch/arm/Kconfig.debug | 25 +++++++++++++++++++++++++
> arch/arm/include/debug/stm32.S | 41 +++++++++++++++++++++++++++++++++++++++++
> 2 files changed, 66 insertions(+)
> create mode 100644 arch/arm/include/debug/stm32.S
>
> diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug
> index 17685e1..9469c58 100644
> --- a/arch/arm/Kconfig.debug
> +++ b/arch/arm/Kconfig.debug
> @@ -1140,6 +1140,26 @@ choice
>
> If unsure, say N.
>
> + config STM32F4_DEBUG_UART
> + bool "Use STM32F4 UART for low-level debug"
> + depends on ARCH_STM32
> + select DEBUG_STM32_UART
> + help
> + Say Y here if you want kernel low-level debugging support
> + on STM32 based platforms.
> +
> + If unsure, say N.
> +
> + config STM32F7_DEBUG_UART
> + bool "Use STM32F7 UART for low-level debug"
> + depends on ARCH_STM32
> + select DEBUG_STM32_UART
> + help
> + Say Y here if you want kernel low-level debugging support
> + on STM32 based platforms.
> +
> + If unsure, say N.
> +
> config TEGRA_DEBUG_UART_AUTO_ODMDATA
> bool "Kernel low-level debugging messages via Tegra UART via ODMDATA"
> depends on ARCH_TEGRA
> @@ -1424,6 +1444,10 @@ config DEBUG_STI_UART
> bool
> depends on ARCH_STI
>
> +config DEBUG_STM32_UART
> + bool
> + depends on ARCH_STM32
> +
> config DEBUG_SIRFSOC_UART
> bool
> depends on ARCH_SIRF
> @@ -1472,6 +1496,7 @@ config DEBUG_LL_INCLUDE
> default "debug/s5pv210.S" if DEBUG_S5PV210_UART
> default "debug/sirf.S" if DEBUG_SIRFSOC_UART
> default "debug/sti.S" if DEBUG_STI_UART
> + default "debug/stm32.S" if DEBUG_STM32_UART
> default "debug/tegra.S" if DEBUG_TEGRA_UART
> default "debug/ux500.S" if DEBUG_UX500_UART
> default "debug/vexpress.S" if DEBUG_VEXPRESS_UART0_DETECT
> diff --git a/arch/arm/include/debug/stm32.S b/arch/arm/include/debug/stm32.S
> new file mode 100644
> index 0000000..4015257
> --- /dev/null
> +++ b/arch/arm/include/debug/stm32.S
> @@ -0,0 +1,41 @@
> +/*
> + * Copyright (C) 2017, STMicroelectronics - All Rights Reserved
> + * Author: Gerald Baeza <gerald_baeza@st.com>
> + * License terms: GNU General Public License (GPL), version 2
> + */
> +
> +#define STM32_UART_BASE 0x40011000 /* USART1 */
> +
> +#ifdef CONFIG_STM32F4_DEBUG_UART
> +#define STM32_USART_SR_OFF 0x00
> +#define STM32_USART_TDR_OFF 0x04
> +#endif
> +
> +#ifdef CONFIG_STM32F7_DEBUG_UART
> +#define STM32_USART_SR_OFF 0x1C
> +#define STM32_USART_TDR_OFF 0x28
> +#endif
> +
> +#define STM32_USART_TC (1 << 6) /* Tx complete */
> +#define STM32_USART_TXE (1 << 7) /* Tx data reg empty */
> +
> + .macro addruart, rp, rv, tmp
> + ldr \rp, =STM32_UART_BASE @ physical base
> + ldr \rv, =STM32_UART_BASE @ virt base /* NoMMU */
> + .endm
> +
> + .macro senduart,rd,rx
> + strb \rd, [\rx, #STM32_USART_TDR_OFF]
> + .endm
> +
> + .macro waituart,rd,rx
> +1001: ldr \rd, [\rx, #(STM32_USART_SR_OFF)] @ Read Status Register
> + tst \rd, #STM32_USART_TXE @ TXE = 1 = tx empty
> + beq 1001b
> + .endm
> +
> + .macro busyuart,rd,rx
> +1001: ldr \rd, [\rx, #(STM32_USART_SR_OFF)] @ Read Status Register
> + tst \rd, #STM32_USART_TC @ TC = 1 = tx complete
> + beq 1001b
> + .endm
>
^ permalink raw reply
* [PATCH v6 4/6] clk: meson: make the spinlock naming more specific
From: Jerome Brunet @ 2017-12-11 9:26 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20171211064853.32111-5-yixun.lan@amlogic.com>
On Mon, 2017-12-11 at 14:48 +0800, Yixun Lan wrote:
> Make the spinlock more specific, so better for lockdep
> debugging and ctags/grep.
>
> Suggested-by: Stephen Boyd <sboyd@codeaurora.org>
> Signed-off-by: Yixun Lan <yixun.lan@amlogic.com>
Yixun,
This change is not related to the main task describe in the cover letter.
Next time, please send it after your series, or before as a dependency to avoid
mixing topics
Thanks
Jerome
^ permalink raw reply
* [PATCH 5/8] ASoC: uniphier: add support for UniPhier AIO driver
From: Katsuhiro Suzuki @ 2017-12-11 9:21 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20171206125817.GF1827@finisterre>
Hello,
> One example is how all the drivers that use the generic dmaengine code
> instantiate their DMA drivers, or how all the drivers for CODECs that
> have both I2C and SPIi control interfaces instantiate - given that the
> device specific code here seems to be mostly data tables that's probably
> the closest thing.
Thank you. I'm checking the ALSA drivers of other companies, I found Qualcomm's
QTi LPASS driver is similar with my wanted.
> > Thanks, I'll try it. Is there Documentation in
sound/designes/compress-offload.rst?
> > And best sample is... Intel's driver?
>
> Yes.
I read Intel's driver, I understand how to define the compress CPU DAI and
snd_compr_ops. The driver of Intel Atom (at sst-mfld-platform-pcm.c) defines
following DAI:
{
.name = "compress-cpu-dai",
.compress_new = snd_soc_new_compress,
.ops = &sst_compr_dai_ops,
.playback = {
.stream_name = "Compress Playback",
.channels_min = 1,
},
},
But I can't find how to use/map this DAI in machine driver or Device-Tree or
something. I think that it's same as PCM DAI, am I correct?
I read compress-offload.rst, but I can't find how do I test it. It seems aplay
of
alsa-util doesn't know compress audio formats. Should I use PulseAudio or
Android HAL to test compress audio APIs?
Regards,
--
Katsuhiro Suzuki
> -----Original Message-----
> From: Mark Brown [mailto:broonie at kernel.org]
> Sent: Wednesday, December 6, 2017 9:58 PM
> To: Suzuki, Katsuhiro/?? ?? <suzuki.katsuhiro@socionext.com>
> Cc: alsa-devel at alsa-project.org; Rob Herring <robh+dt@kernel.org>;
> devicetree at vger.kernel.org; Yamada, Masahiro/?? ??
> <yamada.masahiro@socionext.com>; Masami Hiramatsu
> <masami.hiramatsu@linaro.org>; Jassi Brar <jaswinder.singh@linaro.org>;
> linux-arm-kernel at lists.infradead.org; linux-kernel at vger.kernel.org
> Subject: Re: [PATCH 5/8] ASoC: uniphier: add support for UniPhier AIO driver
>
> On Wed, Dec 06, 2017 at 03:03:18PM +0900, Katsuhiro Suzuki wrote:
>
> > > I'd expect this code to be structured more like a library - have a
> > > driver that handles the specific IPs then have it call into a shared
> > > block of code that does the generic bits. Though in this case the
> > > device specific bit looks like a couple of tiny data tables so I'm not
> > > sure it's worth making it conditional or separate at all.
>
> > Sorry... I agree your opinion, but I can't imagine the detail.
>
> > I think my driver has structure as follows (ex. startup):
> > DAI: uniphier_aio_startup()@aio-core.c
> > Lib: uniphier_aio_init()@aio-regctrl.c
> > SoC specific: uniphier_aio_ld11_spec at aio-ld11.c
>
> > Am I wrong? Would you mean split the functions in aio-regctl.[ch] to other
> > kernel module? I wonder if you could tell me the example from existing
> > drivers. I'll try to fix my driver like as it.
>
> One example is how all the drivers that use the generic dmaengine code
> instantiate their DMA drivers, or how all the drivers for CODECs that
> have both I2C and SPIi control interfaces instantiate - given that the
> device specific code here seems to be mostly data tables that's probably
> the closest thing.
>
> > > At least. I do think we need to get to the bottom of how flexible the
> > > hardware is first though.
>
> > Yes, indeed. This hardware is more flexible and complex, but now I (and our
> > company) don't use it. Of course, I don't want to hide some features of this
> > hardware from ALSA people. I should try to upstream all features in the
future,
> > I think.
>
> My main concern here is to make sure that when you decide you need to
> use the more complex hardware that this can be done without too much
> pain to existing machines (and that they can benefit from as much of the
> enhanced functionality as is possible).
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox