From 5bc1cf1466f635682c3e26eb4179541feeefb1be Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Mon, 18 May 2020 22:16:56 +0800 Subject: [PATCH 0001/2249] iommu/qcom: add optional 'tbu' clock for TLB invalidate On some SoCs like MSM8939 with A405 adreno, there is a gfx_tbu clock needs to be on while doing TLB invalidate. Otherwise, TLBSYNC status will not be correctly reflected, causing the system to go into a bad state. Add it as an optional clock, so that platforms that have this clock can pass it over DT. While adding the third clock, let's switch to bulk clk API to simplify the enable/disable calls. clk_bulk_get() cannot used because the existing two clocks are required while the new one is optional. Signed-off-by: Shawn Guo Reviewed-by: Bjorn Andersson Link: https://lore.kernel.org/r/20200518141656.26284-1-shawn.guo@linaro.org Signed-off-by: Joerg Roedel --- drivers/iommu/qcom_iommu.c | 62 ++++++++++++++++---------------------- 1 file changed, 26 insertions(+), 36 deletions(-) diff --git a/drivers/iommu/qcom_iommu.c b/drivers/iommu/qcom_iommu.c index 0e2a96467767b..116d8188f87f7 100644 --- a/drivers/iommu/qcom_iommu.c +++ b/drivers/iommu/qcom_iommu.c @@ -37,14 +37,20 @@ #define SMMU_INTR_SEL_NS 0x2000 +enum qcom_iommu_clk { + CLK_IFACE, + CLK_BUS, + CLK_TBU, + CLK_NUM, +}; + struct qcom_iommu_ctx; struct qcom_iommu_dev { /* IOMMU core code handle */ struct iommu_device iommu; struct device *dev; - struct clk *iface_clk; - struct clk *bus_clk; + struct clk_bulk_data clks[CLK_NUM]; void __iomem *local_base; u32 sec_id; u8 num_ctxs; @@ -626,32 +632,6 @@ static const struct iommu_ops qcom_iommu_ops = { .pgsize_bitmap = SZ_4K | SZ_64K | SZ_1M | SZ_16M, }; -static int qcom_iommu_enable_clocks(struct qcom_iommu_dev *qcom_iommu) -{ - int ret; - - ret = clk_prepare_enable(qcom_iommu->iface_clk); - if (ret) { - dev_err(qcom_iommu->dev, "Couldn't enable iface_clk\n"); - return ret; - } - - ret = clk_prepare_enable(qcom_iommu->bus_clk); - if (ret) { - dev_err(qcom_iommu->dev, "Couldn't enable bus_clk\n"); - clk_disable_unprepare(qcom_iommu->iface_clk); - return ret; - } - - return 0; -} - -static void qcom_iommu_disable_clocks(struct qcom_iommu_dev *qcom_iommu) -{ - clk_disable_unprepare(qcom_iommu->bus_clk); - clk_disable_unprepare(qcom_iommu->iface_clk); -} - static int qcom_iommu_sec_ptbl_init(struct device *dev) { size_t psize = 0; @@ -808,6 +788,7 @@ static int qcom_iommu_device_probe(struct platform_device *pdev) struct qcom_iommu_dev *qcom_iommu; struct device *dev = &pdev->dev; struct resource *res; + struct clk *clk; int ret, max_asid = 0; /* find the max asid (which is 1:1 to ctx bank idx), so we know how @@ -827,17 +808,26 @@ static int qcom_iommu_device_probe(struct platform_device *pdev) if (res) qcom_iommu->local_base = devm_ioremap_resource(dev, res); - qcom_iommu->iface_clk = devm_clk_get(dev, "iface"); - if (IS_ERR(qcom_iommu->iface_clk)) { + clk = devm_clk_get(dev, "iface"); + if (IS_ERR(clk)) { dev_err(dev, "failed to get iface clock\n"); - return PTR_ERR(qcom_iommu->iface_clk); + return PTR_ERR(clk); } + qcom_iommu->clks[CLK_IFACE].clk = clk; - qcom_iommu->bus_clk = devm_clk_get(dev, "bus"); - if (IS_ERR(qcom_iommu->bus_clk)) { + clk = devm_clk_get(dev, "bus"); + if (IS_ERR(clk)) { dev_err(dev, "failed to get bus clock\n"); - return PTR_ERR(qcom_iommu->bus_clk); + return PTR_ERR(clk); + } + qcom_iommu->clks[CLK_BUS].clk = clk; + + clk = devm_clk_get_optional(dev, "tbu"); + if (IS_ERR(clk)) { + dev_err(dev, "failed to get tbu clock\n"); + return PTR_ERR(clk); } + qcom_iommu->clks[CLK_TBU].clk = clk; if (of_property_read_u32(dev->of_node, "qcom,iommu-secure-id", &qcom_iommu->sec_id)) { @@ -909,14 +899,14 @@ static int __maybe_unused qcom_iommu_resume(struct device *dev) { struct qcom_iommu_dev *qcom_iommu = dev_get_drvdata(dev); - return qcom_iommu_enable_clocks(qcom_iommu); + return clk_bulk_prepare_enable(CLK_NUM, qcom_iommu->clks); } static int __maybe_unused qcom_iommu_suspend(struct device *dev) { struct qcom_iommu_dev *qcom_iommu = dev_get_drvdata(dev); - qcom_iommu_disable_clocks(qcom_iommu); + clk_bulk_disable_unprepare(CLK_NUM, qcom_iommu->clks); return 0; } -- GitLab From b35250c0816c7cf7d0a8de92f5fafb6a7508a708 Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Wed, 10 Jun 2020 17:36:03 +0200 Subject: [PATCH 0002/2249] writeback: Protect inode->i_io_list with inode->i_lock Currently, operations on inode->i_io_list are protected by wb->list_lock. In the following patches we'll need to maintain consistency between inode->i_state and inode->i_io_list so change the code so that inode->i_lock protects also all inode's i_io_list handling. Reviewed-by: Martijn Coenen Reviewed-by: Christoph Hellwig CC: stable@vger.kernel.org # Prerequisite for "writeback: Avoid skipping inode writeback" Signed-off-by: Jan Kara --- fs/fs-writeback.c | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c index a605c3dddabc7..ff0b18331590b 100644 --- a/fs/fs-writeback.c +++ b/fs/fs-writeback.c @@ -144,6 +144,7 @@ static void inode_io_list_del_locked(struct inode *inode, struct bdi_writeback *wb) { assert_spin_locked(&wb->list_lock); + assert_spin_locked(&inode->i_lock); list_del_init(&inode->i_io_list); wb_io_lists_depopulated(wb); @@ -1122,7 +1123,9 @@ void inode_io_list_del(struct inode *inode) struct bdi_writeback *wb; wb = inode_to_wb_and_lock_list(inode); + spin_lock(&inode->i_lock); inode_io_list_del_locked(inode, wb); + spin_unlock(&inode->i_lock); spin_unlock(&wb->list_lock); } EXPORT_SYMBOL(inode_io_list_del); @@ -1172,8 +1175,10 @@ void sb_clear_inode_writeback(struct inode *inode) * the case then the inode must have been redirtied while it was being written * out and we don't reset its dirtied_when. */ -static void redirty_tail(struct inode *inode, struct bdi_writeback *wb) +static void redirty_tail_locked(struct inode *inode, struct bdi_writeback *wb) { + assert_spin_locked(&inode->i_lock); + if (!list_empty(&wb->b_dirty)) { struct inode *tail; @@ -1184,6 +1189,13 @@ static void redirty_tail(struct inode *inode, struct bdi_writeback *wb) inode_io_list_move_locked(inode, wb, &wb->b_dirty); } +static void redirty_tail(struct inode *inode, struct bdi_writeback *wb) +{ + spin_lock(&inode->i_lock); + redirty_tail_locked(inode, wb); + spin_unlock(&inode->i_lock); +} + /* * requeue inode for re-scanning after bdi->b_io list is exhausted. */ @@ -1394,7 +1406,7 @@ static void requeue_inode(struct inode *inode, struct bdi_writeback *wb, * writeback is not making progress due to locked * buffers. Skip this inode for now. */ - redirty_tail(inode, wb); + redirty_tail_locked(inode, wb); return; } @@ -1414,7 +1426,7 @@ static void requeue_inode(struct inode *inode, struct bdi_writeback *wb, * retrying writeback of the dirty page/inode * that cannot be performed immediately. */ - redirty_tail(inode, wb); + redirty_tail_locked(inode, wb); } } else if (inode->i_state & I_DIRTY) { /* @@ -1422,7 +1434,7 @@ static void requeue_inode(struct inode *inode, struct bdi_writeback *wb, * such as delayed allocation during submission or metadata * updates after data IO completion. */ - redirty_tail(inode, wb); + redirty_tail_locked(inode, wb); } else if (inode->i_state & I_DIRTY_TIME) { inode->dirtied_when = jiffies; inode_io_list_move_locked(inode, wb, &wb->b_dirty_time); @@ -1669,8 +1681,8 @@ static long writeback_sb_inodes(struct super_block *sb, */ spin_lock(&inode->i_lock); if (inode->i_state & (I_NEW | I_FREEING | I_WILL_FREE)) { + redirty_tail_locked(inode, wb); spin_unlock(&inode->i_lock); - redirty_tail(inode, wb); continue; } if ((inode->i_state & I_SYNC) && wbc.sync_mode != WB_SYNC_ALL) { -- GitLab From 5afced3bf28100d81fb2fe7e98918632a08feaf5 Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Fri, 29 May 2020 15:05:22 +0200 Subject: [PATCH 0003/2249] writeback: Avoid skipping inode writeback Inode's i_io_list list head is used to attach inode to several different lists - wb->{b_dirty, b_dirty_time, b_io, b_more_io}. When flush worker prepares a list of inodes to writeback e.g. for sync(2), it moves inodes to b_io list. Thus it is critical for sync(2) data integrity guarantees that inode is not requeued to any other writeback list when inode is queued for processing by flush worker. That's the reason why writeback_single_inode() does not touch i_io_list (unless the inode is completely clean) and why __mark_inode_dirty() does not touch i_io_list if I_SYNC flag is set. However there are two flaws in the current logic: 1) When inode has only I_DIRTY_TIME set but it is already queued in b_io list due to sync(2), concurrent __mark_inode_dirty(inode, I_DIRTY_SYNC) can still move inode back to b_dirty list resulting in skipping writeback of inode time stamps during sync(2). 2) When inode is on b_dirty_time list and writeback_single_inode() races with __mark_inode_dirty() like: writeback_single_inode() __mark_inode_dirty(inode, I_DIRTY_PAGES) inode->i_state |= I_SYNC __writeback_single_inode() inode->i_state |= I_DIRTY_PAGES; if (inode->i_state & I_SYNC) bail if (!(inode->i_state & I_DIRTY_ALL)) - not true so nothing done We end up with I_DIRTY_PAGES inode on b_dirty_time list and thus standard background writeback will not writeback this inode leading to possible dirty throttling stalls etc. (thanks to Martijn Coenen for this analysis). Fix these problems by tracking whether inode is queued in b_io or b_more_io lists in a new I_SYNC_QUEUED flag. When this flag is set, we know flush worker has queued inode and we should not touch i_io_list. On the other hand we also know that once flush worker is done with the inode it will requeue the inode to appropriate dirty list. When I_SYNC_QUEUED is not set, __mark_inode_dirty() can (and must) move inode to appropriate dirty list. Reported-by: Martijn Coenen Reviewed-by: Martijn Coenen Tested-by: Martijn Coenen Reviewed-by: Christoph Hellwig Fixes: 0ae45f63d4ef ("vfs: add support for a lazytime mount option") CC: stable@vger.kernel.org Signed-off-by: Jan Kara --- fs/fs-writeback.c | 17 ++++++++++++----- include/linux/fs.h | 8 ++++++-- 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c index ff0b18331590b..f470c10641c5c 100644 --- a/fs/fs-writeback.c +++ b/fs/fs-writeback.c @@ -146,6 +146,7 @@ static void inode_io_list_del_locked(struct inode *inode, assert_spin_locked(&wb->list_lock); assert_spin_locked(&inode->i_lock); + inode->i_state &= ~I_SYNC_QUEUED; list_del_init(&inode->i_io_list); wb_io_lists_depopulated(wb); } @@ -1187,6 +1188,7 @@ static void redirty_tail_locked(struct inode *inode, struct bdi_writeback *wb) inode->dirtied_when = jiffies; } inode_io_list_move_locked(inode, wb, &wb->b_dirty); + inode->i_state &= ~I_SYNC_QUEUED; } static void redirty_tail(struct inode *inode, struct bdi_writeback *wb) @@ -1262,8 +1264,11 @@ static int move_expired_inodes(struct list_head *delaying_queue, break; list_move(&inode->i_io_list, &tmp); moved++; + spin_lock(&inode->i_lock); if (flags & EXPIRE_DIRTY_ATIME) - set_bit(__I_DIRTY_TIME_EXPIRED, &inode->i_state); + inode->i_state |= I_DIRTY_TIME_EXPIRED; + inode->i_state |= I_SYNC_QUEUED; + spin_unlock(&inode->i_lock); if (sb_is_blkdev_sb(inode->i_sb)) continue; if (sb && sb != inode->i_sb) @@ -1438,6 +1443,7 @@ static void requeue_inode(struct inode *inode, struct bdi_writeback *wb, } else if (inode->i_state & I_DIRTY_TIME) { inode->dirtied_when = jiffies; inode_io_list_move_locked(inode, wb, &wb->b_dirty_time); + inode->i_state &= ~I_SYNC_QUEUED; } else { /* The inode is clean. Remove from writeback lists. */ inode_io_list_del_locked(inode, wb); @@ -2301,11 +2307,12 @@ void __mark_inode_dirty(struct inode *inode, int flags) inode->i_state |= flags; /* - * If the inode is being synced, just update its dirty state. - * The unlocker will place the inode on the appropriate - * superblock list, based upon its state. + * If the inode is queued for writeback by flush worker, just + * update its dirty state. Once the flush worker is done with + * the inode it will place it on the appropriate superblock + * list, based upon its state. */ - if (inode->i_state & I_SYNC) + if (inode->i_state & I_SYNC_QUEUED) goto out_unlock_inode; /* diff --git a/include/linux/fs.h b/include/linux/fs.h index 19ef6c88c152e..48556efcdcf06 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -2157,6 +2157,10 @@ static inline void kiocb_clone(struct kiocb *kiocb, struct kiocb *kiocb_src, * * I_DONTCACHE Evict inode as soon as it is not used anymore. * + * I_SYNC_QUEUED Inode is queued in b_io or b_more_io writeback lists. + * Used to detect that mark_inode_dirty() should not move + * inode between dirty lists. + * * Q: What is the difference between I_WILL_FREE and I_FREEING? */ #define I_DIRTY_SYNC (1 << 0) @@ -2174,12 +2178,12 @@ static inline void kiocb_clone(struct kiocb *kiocb, struct kiocb *kiocb_src, #define I_DIO_WAKEUP (1 << __I_DIO_WAKEUP) #define I_LINKABLE (1 << 10) #define I_DIRTY_TIME (1 << 11) -#define __I_DIRTY_TIME_EXPIRED 12 -#define I_DIRTY_TIME_EXPIRED (1 << __I_DIRTY_TIME_EXPIRED) +#define I_DIRTY_TIME_EXPIRED (1 << 12) #define I_WB_SWITCH (1 << 13) #define I_OVL_INUSE (1 << 14) #define I_CREATING (1 << 15) #define I_DONTCACHE (1 << 16) +#define I_SYNC_QUEUED (1 << 17) #define I_DIRTY_INODE (I_DIRTY_SYNC | I_DIRTY_DATASYNC) #define I_DIRTY (I_DIRTY_INODE | I_DIRTY_PAGES) -- GitLab From f9cae926f35e8230330f28c7b743ad088611a8de Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Fri, 29 May 2020 16:08:58 +0200 Subject: [PATCH 0004/2249] writeback: Fix sync livelock due to b_dirty_time processing When we are processing writeback for sync(2), move_expired_inodes() didn't set any inode expiry value (older_than_this). This can result in writeback never completing if there's steady stream of inodes added to b_dirty_time list as writeback rechecks dirty lists after each writeback round whether there's more work to be done. Fix the problem by using sync(2) start time is inode expiry value when processing b_dirty_time list similarly as for ordinarily dirtied inodes. This requires some refactoring of older_than_this handling which simplifies the code noticeably as a bonus. Fixes: 0ae45f63d4ef ("vfs: add support for a lazytime mount option") CC: stable@vger.kernel.org Reviewed-by: Christoph Hellwig Signed-off-by: Jan Kara --- fs/fs-writeback.c | 44 ++++++++++++-------------------- include/trace/events/writeback.h | 13 +++++----- 2 files changed, 23 insertions(+), 34 deletions(-) diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c index f470c10641c5c..ae17d64a3e189 100644 --- a/fs/fs-writeback.c +++ b/fs/fs-writeback.c @@ -42,7 +42,6 @@ struct wb_writeback_work { long nr_pages; struct super_block *sb; - unsigned long *older_than_this; enum writeback_sync_modes sync_mode; unsigned int tagged_writepages:1; unsigned int for_kupdate:1; @@ -1234,16 +1233,13 @@ static bool inode_dirtied_after(struct inode *inode, unsigned long t) #define EXPIRE_DIRTY_ATIME 0x0001 /* - * Move expired (dirtied before work->older_than_this) dirty inodes from + * Move expired (dirtied before dirtied_before) dirty inodes from * @delaying_queue to @dispatch_queue. */ static int move_expired_inodes(struct list_head *delaying_queue, struct list_head *dispatch_queue, - int flags, - struct wb_writeback_work *work) + int flags, unsigned long dirtied_before) { - unsigned long *older_than_this = NULL; - unsigned long expire_time; LIST_HEAD(tmp); struct list_head *pos, *node; struct super_block *sb = NULL; @@ -1251,16 +1247,9 @@ static int move_expired_inodes(struct list_head *delaying_queue, int do_sb_sort = 0; int moved = 0; - if ((flags & EXPIRE_DIRTY_ATIME) == 0) - older_than_this = work->older_than_this; - else if (!work->for_sync) { - expire_time = jiffies - (dirtytime_expire_interval * HZ); - older_than_this = &expire_time; - } while (!list_empty(delaying_queue)) { inode = wb_inode(delaying_queue->prev); - if (older_than_this && - inode_dirtied_after(inode, *older_than_this)) + if (inode_dirtied_after(inode, dirtied_before)) break; list_move(&inode->i_io_list, &tmp); moved++; @@ -1306,18 +1295,22 @@ static int move_expired_inodes(struct list_head *delaying_queue, * | * +--> dequeue for IO */ -static void queue_io(struct bdi_writeback *wb, struct wb_writeback_work *work) +static void queue_io(struct bdi_writeback *wb, struct wb_writeback_work *work, + unsigned long dirtied_before) { int moved; + unsigned long time_expire_jif = dirtied_before; assert_spin_locked(&wb->list_lock); list_splice_init(&wb->b_more_io, &wb->b_io); - moved = move_expired_inodes(&wb->b_dirty, &wb->b_io, 0, work); + moved = move_expired_inodes(&wb->b_dirty, &wb->b_io, 0, dirtied_before); + if (!work->for_sync) + time_expire_jif = jiffies - dirtytime_expire_interval * HZ; moved += move_expired_inodes(&wb->b_dirty_time, &wb->b_io, - EXPIRE_DIRTY_ATIME, work); + EXPIRE_DIRTY_ATIME, time_expire_jif); if (moved) wb_io_lists_populated(wb); - trace_writeback_queue_io(wb, work, moved); + trace_writeback_queue_io(wb, work, dirtied_before, moved); } static int write_inode(struct inode *inode, struct writeback_control *wbc) @@ -1829,7 +1822,7 @@ static long writeback_inodes_wb(struct bdi_writeback *wb, long nr_pages, blk_start_plug(&plug); spin_lock(&wb->list_lock); if (list_empty(&wb->b_io)) - queue_io(wb, &work); + queue_io(wb, &work, jiffies); __writeback_inodes_wb(wb, &work); spin_unlock(&wb->list_lock); blk_finish_plug(&plug); @@ -1849,7 +1842,7 @@ static long writeback_inodes_wb(struct bdi_writeback *wb, long nr_pages, * takes longer than a dirty_writeback_interval interval, then leave a * one-second gap. * - * older_than_this takes precedence over nr_to_write. So we'll only write back + * dirtied_before takes precedence over nr_to_write. So we'll only write back * all dirty pages if they are all attached to "old" mappings. */ static long wb_writeback(struct bdi_writeback *wb, @@ -1857,14 +1850,11 @@ static long wb_writeback(struct bdi_writeback *wb, { unsigned long wb_start = jiffies; long nr_pages = work->nr_pages; - unsigned long oldest_jif; + unsigned long dirtied_before = jiffies; struct inode *inode; long progress; struct blk_plug plug; - oldest_jif = jiffies; - work->older_than_this = &oldest_jif; - blk_start_plug(&plug); spin_lock(&wb->list_lock); for (;;) { @@ -1898,14 +1888,14 @@ static long wb_writeback(struct bdi_writeback *wb, * safe. */ if (work->for_kupdate) { - oldest_jif = jiffies - + dirtied_before = jiffies - msecs_to_jiffies(dirty_expire_interval * 10); } else if (work->for_background) - oldest_jif = jiffies; + dirtied_before = jiffies; trace_writeback_start(wb, work); if (list_empty(&wb->b_io)) - queue_io(wb, work); + queue_io(wb, work, dirtied_before); if (work->sb) progress = writeback_sb_inodes(work->sb, wb, work); else diff --git a/include/trace/events/writeback.h b/include/trace/events/writeback.h index 10f5d1fa73476..7565dcd596973 100644 --- a/include/trace/events/writeback.h +++ b/include/trace/events/writeback.h @@ -498,8 +498,9 @@ DEFINE_WBC_EVENT(wbc_writepage); TRACE_EVENT(writeback_queue_io, TP_PROTO(struct bdi_writeback *wb, struct wb_writeback_work *work, + unsigned long dirtied_before, int moved), - TP_ARGS(wb, work, moved), + TP_ARGS(wb, work, dirtied_before, moved), TP_STRUCT__entry( __array(char, name, 32) __field(unsigned long, older) @@ -509,19 +510,17 @@ TRACE_EVENT(writeback_queue_io, __field(ino_t, cgroup_ino) ), TP_fast_assign( - unsigned long *older_than_this = work->older_than_this; strscpy_pad(__entry->name, bdi_dev_name(wb->bdi), 32); - __entry->older = older_than_this ? *older_than_this : 0; - __entry->age = older_than_this ? - (jiffies - *older_than_this) * 1000 / HZ : -1; + __entry->older = dirtied_before; + __entry->age = (jiffies - dirtied_before) * 1000 / HZ; __entry->moved = moved; __entry->reason = work->reason; __entry->cgroup_ino = __trace_wb_assign_cgroup(wb); ), TP_printk("bdi %s: older=%lu age=%ld enqueue=%d reason=%s cgroup_ino=%lu", __entry->name, - __entry->older, /* older_than_this in jiffies */ - __entry->age, /* older_than_this in relative milliseconds */ + __entry->older, /* dirtied_before in jiffies */ + __entry->age, /* dirtied_before in relative milliseconds */ __entry->moved, __print_symbolic(__entry->reason, WB_WORK_REASON), (unsigned long)__entry->cgroup_ino -- GitLab From 5fcd57505c002efc5823a7355e21f48dd02d5a51 Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Fri, 29 May 2020 16:24:43 +0200 Subject: [PATCH 0005/2249] writeback: Drop I_DIRTY_TIME_EXPIRE The only use of I_DIRTY_TIME_EXPIRE is to detect in __writeback_single_inode() that inode got there because flush worker decided it's time to writeback the dirty inode time stamps (either because we are syncing or because of age). However we can detect this directly in __writeback_single_inode() and there's no need for the strange propagation with I_DIRTY_TIME_EXPIRE flag. Reviewed-by: Christoph Hellwig Signed-off-by: Jan Kara --- fs/ext4/inode.c | 2 +- fs/fs-writeback.c | 28 +++++++++++----------------- fs/xfs/libxfs/xfs_trans_inode.c | 4 ++-- include/linux/fs.h | 1 - include/trace/events/writeback.h | 1 - 5 files changed, 14 insertions(+), 22 deletions(-) diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 40ec5c7ef0d35..4db497f02ffbb 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -4887,7 +4887,7 @@ static void __ext4_update_other_inode_time(struct super_block *sb, (inode->i_state & I_DIRTY_TIME)) { struct ext4_inode_info *ei = EXT4_I(inode); - inode->i_state &= ~(I_DIRTY_TIME | I_DIRTY_TIME_EXPIRED); + inode->i_state &= ~I_DIRTY_TIME; spin_unlock(&inode->i_lock); spin_lock(&ei->i_raw_lock); diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c index ae17d64a3e189..149227160ff0b 100644 --- a/fs/fs-writeback.c +++ b/fs/fs-writeback.c @@ -1238,7 +1238,7 @@ static bool inode_dirtied_after(struct inode *inode, unsigned long t) */ static int move_expired_inodes(struct list_head *delaying_queue, struct list_head *dispatch_queue, - int flags, unsigned long dirtied_before) + unsigned long dirtied_before) { LIST_HEAD(tmp); struct list_head *pos, *node; @@ -1254,8 +1254,6 @@ static int move_expired_inodes(struct list_head *delaying_queue, list_move(&inode->i_io_list, &tmp); moved++; spin_lock(&inode->i_lock); - if (flags & EXPIRE_DIRTY_ATIME) - inode->i_state |= I_DIRTY_TIME_EXPIRED; inode->i_state |= I_SYNC_QUEUED; spin_unlock(&inode->i_lock); if (sb_is_blkdev_sb(inode->i_sb)) @@ -1303,11 +1301,11 @@ static void queue_io(struct bdi_writeback *wb, struct wb_writeback_work *work, assert_spin_locked(&wb->list_lock); list_splice_init(&wb->b_more_io, &wb->b_io); - moved = move_expired_inodes(&wb->b_dirty, &wb->b_io, 0, dirtied_before); + moved = move_expired_inodes(&wb->b_dirty, &wb->b_io, dirtied_before); if (!work->for_sync) time_expire_jif = jiffies - dirtytime_expire_interval * HZ; moved += move_expired_inodes(&wb->b_dirty_time, &wb->b_io, - EXPIRE_DIRTY_ATIME, time_expire_jif); + time_expire_jif); if (moved) wb_io_lists_populated(wb); trace_writeback_queue_io(wb, work, dirtied_before, moved); @@ -1483,18 +1481,14 @@ __writeback_single_inode(struct inode *inode, struct writeback_control *wbc) spin_lock(&inode->i_lock); dirty = inode->i_state & I_DIRTY; - if (inode->i_state & I_DIRTY_TIME) { - if ((dirty & I_DIRTY_INODE) || - wbc->sync_mode == WB_SYNC_ALL || - unlikely(inode->i_state & I_DIRTY_TIME_EXPIRED) || - unlikely(time_after(jiffies, - (inode->dirtied_time_when + - dirtytime_expire_interval * HZ)))) { - dirty |= I_DIRTY_TIME | I_DIRTY_TIME_EXPIRED; - trace_writeback_lazytime(inode); - } - } else - inode->i_state &= ~I_DIRTY_TIME_EXPIRED; + if ((inode->i_state & I_DIRTY_TIME) && + ((dirty & I_DIRTY_INODE) || + wbc->sync_mode == WB_SYNC_ALL || wbc->for_sync || + time_after(jiffies, inode->dirtied_time_when + + dirtytime_expire_interval * HZ))) { + dirty |= I_DIRTY_TIME; + trace_writeback_lazytime(inode); + } inode->i_state &= ~dirty; /* diff --git a/fs/xfs/libxfs/xfs_trans_inode.c b/fs/xfs/libxfs/xfs_trans_inode.c index b5dfb66548422..1b4df6636944c 100644 --- a/fs/xfs/libxfs/xfs_trans_inode.c +++ b/fs/xfs/libxfs/xfs_trans_inode.c @@ -96,9 +96,9 @@ xfs_trans_log_inode( * to log the timestamps, or will clear already cleared fields in the * worst case. */ - if (inode->i_state & (I_DIRTY_TIME | I_DIRTY_TIME_EXPIRED)) { + if (inode->i_state & I_DIRTY_TIME) { spin_lock(&inode->i_lock); - inode->i_state &= ~(I_DIRTY_TIME | I_DIRTY_TIME_EXPIRED); + inode->i_state &= ~I_DIRTY_TIME; spin_unlock(&inode->i_lock); } diff --git a/include/linux/fs.h b/include/linux/fs.h index 48556efcdcf06..45eadf5bea5d7 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -2178,7 +2178,6 @@ static inline void kiocb_clone(struct kiocb *kiocb, struct kiocb *kiocb_src, #define I_DIO_WAKEUP (1 << __I_DIO_WAKEUP) #define I_LINKABLE (1 << 10) #define I_DIRTY_TIME (1 << 11) -#define I_DIRTY_TIME_EXPIRED (1 << 12) #define I_WB_SWITCH (1 << 13) #define I_OVL_INUSE (1 << 14) #define I_CREATING (1 << 15) diff --git a/include/trace/events/writeback.h b/include/trace/events/writeback.h index 7565dcd596973..e7cbccc7c14cc 100644 --- a/include/trace/events/writeback.h +++ b/include/trace/events/writeback.h @@ -20,7 +20,6 @@ {I_CLEAR, "I_CLEAR"}, \ {I_SYNC, "I_SYNC"}, \ {I_DIRTY_TIME, "I_DIRTY_TIME"}, \ - {I_DIRTY_TIME_EXPIRED, "I_DIRTY_TIME_EXPIRED"}, \ {I_REFERENCED, "I_REFERENCED"} \ ) -- GitLab From bf4237a188f872e535de8cbfc7903c1387b83b01 Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Wed, 29 Jan 2020 17:38:19 +0100 Subject: [PATCH 0006/2249] clk: rockchip: convert rk3399 pll type to use readl_relaxed_poll_timeout Instead of open coding the polling of the lock status, use the handy readl_relaxed_poll_timeout for this. As the pll locking is normally blazingly fast and we don't want to incur additional delays, we're not doing any sleeps similar to for example the imx clk-pllv4 and define a very safe but still short timeout of 1ms. Suggested-by: Stephen Boyd Signed-off-by: Heiko Stuebner Reviewed-by: Stephen Boyd Link: https://lore.kernel.org/r/20200129163821.1547295-1-heiko@sntech.de --- drivers/clk/rockchip/clk-pll.c | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/drivers/clk/rockchip/clk-pll.c b/drivers/clk/rockchip/clk-pll.c index 10560d963baf6..28b04aad31ad7 100644 --- a/drivers/clk/rockchip/clk-pll.c +++ b/drivers/clk/rockchip/clk-pll.c @@ -589,19 +589,20 @@ static const struct clk_ops rockchip_rk3066_pll_clk_ops = { static int rockchip_rk3399_pll_wait_lock(struct rockchip_clk_pll *pll) { u32 pllcon; - int delay = 24000000; + int ret; - /* poll check the lock status in rk3399 xPLLCON2 */ - while (delay > 0) { - pllcon = readl_relaxed(pll->reg_base + RK3399_PLLCON(2)); - if (pllcon & RK3399_PLLCON2_LOCK_STATUS) - return 0; + /* + * Lock time typical 250, max 500 input clock cycles @24MHz + * So define a very safe maximum of 1000us, meaning 24000 cycles. + */ + ret = readl_relaxed_poll_timeout(pll->reg_base + RK3399_PLLCON(2), + pllcon, + pllcon & RK3399_PLLCON2_LOCK_STATUS, + 0, 1000); + if (ret) + pr_err("%s: timeout waiting for pll to lock\n", __func__); - delay--; - } - - pr_err("%s: timeout waiting for pll to lock\n", __func__); - return -ETIMEDOUT; + return ret; } static void rockchip_rk3399_pll_get_params(struct rockchip_clk_pll *pll, -- GitLab From 3507df1a4615113ae6509e0f14f6546f0d1c84b4 Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Wed, 29 Jan 2020 17:38:20 +0100 Subject: [PATCH 0007/2249] clk: rockchip: convert basic pll lock_wait to use regmap_read_poll_timeout Instead of open coding the polling of the lock status, use the handy regmap_read_poll_timeout for this. As the pll locking is normally blazingly fast and we don't want to incur additional delays, we're not doing any sleeps similar to for example the imx clk-pllv4 and define a very safe but still short timeout of 1ms. Suggested-by: Stephen Boyd Signed-off-by: Heiko Stuebner Reviewed-by: Stephen Boyd Link: https://lore.kernel.org/r/20200129163821.1547295-2-heiko@sntech.de --- drivers/clk/rockchip/clk-pll.c | 21 ++++++--------------- 1 file changed, 6 insertions(+), 15 deletions(-) diff --git a/drivers/clk/rockchip/clk-pll.c b/drivers/clk/rockchip/clk-pll.c index 28b04aad31ad7..945f8b2cacc1d 100644 --- a/drivers/clk/rockchip/clk-pll.c +++ b/drivers/clk/rockchip/clk-pll.c @@ -86,23 +86,14 @@ static int rockchip_pll_wait_lock(struct rockchip_clk_pll *pll) { struct regmap *grf = pll->ctx->grf; unsigned int val; - int delay = 24000000, ret; - - while (delay > 0) { - ret = regmap_read(grf, pll->lock_offset, &val); - if (ret) { - pr_err("%s: failed to read pll lock status: %d\n", - __func__, ret); - return ret; - } + int ret; - if (val & BIT(pll->lock_shift)) - return 0; - delay--; - } + ret = regmap_read_poll_timeout(grf, pll->lock_offset, val, + val & BIT(pll->lock_shift), 0, 1000); + if (ret) + pr_err("%s: timeout waiting for pll to lock\n", __func__); - pr_err("%s: timeout waiting for pll to lock\n", __func__); - return -ETIMEDOUT; + return ret; } /** -- GitLab From 7f6ffbb885d147557bdca471c37b7b1204005798 Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Wed, 29 Jan 2020 17:38:21 +0100 Subject: [PATCH 0008/2249] clk: rockchip: convert rk3036 pll type to use internal lock status The rk3036 pll type exposes its lock status in both its pllcon registers as well as the General Register Files. To remove one dependency convert it to the "internal" lock status, similar to how rk3399 handles it. Signed-off-by: Heiko Stuebner Reviewed-by: Stephen Boyd Link: https://lore.kernel.org/r/20200129163821.1547295-3-heiko@sntech.de --- drivers/clk/rockchip/clk-pll.c | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/drivers/clk/rockchip/clk-pll.c b/drivers/clk/rockchip/clk-pll.c index 945f8b2cacc1d..4c6c9167ef509 100644 --- a/drivers/clk/rockchip/clk-pll.c +++ b/drivers/clk/rockchip/clk-pll.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include "clk.h" @@ -109,12 +110,31 @@ static int rockchip_pll_wait_lock(struct rockchip_clk_pll *pll) #define RK3036_PLLCON1_REFDIV_SHIFT 0 #define RK3036_PLLCON1_POSTDIV2_MASK 0x7 #define RK3036_PLLCON1_POSTDIV2_SHIFT 6 +#define RK3036_PLLCON1_LOCK_STATUS BIT(10) #define RK3036_PLLCON1_DSMPD_MASK 0x1 #define RK3036_PLLCON1_DSMPD_SHIFT 12 +#define RK3036_PLLCON1_PWRDOWN BIT(13) #define RK3036_PLLCON2_FRAC_MASK 0xffffff #define RK3036_PLLCON2_FRAC_SHIFT 0 -#define RK3036_PLLCON1_PWRDOWN (1 << 13) +static int rockchip_rk3036_pll_wait_lock(struct rockchip_clk_pll *pll) +{ + u32 pllcon; + int ret; + + /* + * Lock time typical 250, max 500 input clock cycles @24MHz + * So define a very safe maximum of 1000us, meaning 24000 cycles. + */ + ret = readl_relaxed_poll_timeout(pll->reg_base + RK3036_PLLCON(1), + pllcon, + pllcon & RK3036_PLLCON1_LOCK_STATUS, + 0, 1000); + if (ret) + pr_err("%s: timeout waiting for pll to lock\n", __func__); + + return ret; +} static void rockchip_rk3036_pll_get_params(struct rockchip_clk_pll *pll, struct rockchip_pll_rate_table *rate) @@ -212,7 +232,7 @@ static int rockchip_rk3036_pll_set_params(struct rockchip_clk_pll *pll, writel_relaxed(pllcon, pll->reg_base + RK3036_PLLCON(2)); /* wait for the pll to lock */ - ret = rockchip_pll_wait_lock(pll); + ret = rockchip_rk3036_pll_wait_lock(pll); if (ret) { pr_warn("%s: pll update unsuccessful, trying to restore old params\n", __func__); @@ -251,7 +271,7 @@ static int rockchip_rk3036_pll_enable(struct clk_hw *hw) writel(HIWORD_UPDATE(0, RK3036_PLLCON1_PWRDOWN, 0), pll->reg_base + RK3036_PLLCON(1)); - rockchip_pll_wait_lock(pll); + rockchip_rk3036_pll_wait_lock(pll); return 0; } -- GitLab From a9b9b2af40c717adbc4981acd29c53b92be3a99a Mon Sep 17 00:00:00 2001 From: Wang Qing Date: Mon, 15 Jun 2020 16:54:02 +0800 Subject: [PATCH 0009/2249] backlight: lm3533_bl: Use kobj_to_dev() instead Use kobj_to_dev() instead of container_of() Signed-off-by: Wang Qing Reviewed-by: Daniel Thompson Signed-off-by: Lee Jones --- drivers/video/backlight/lm3533_bl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/video/backlight/lm3533_bl.c b/drivers/video/backlight/lm3533_bl.c index ee09d1bd02b97..0c7830f793def 100644 --- a/drivers/video/backlight/lm3533_bl.c +++ b/drivers/video/backlight/lm3533_bl.c @@ -235,7 +235,7 @@ static struct attribute *lm3533_bl_attributes[] = { static umode_t lm3533_bl_attr_is_visible(struct kobject *kobj, struct attribute *attr, int n) { - struct device *dev = container_of(kobj, struct device, kobj); + struct device *dev = kobj_to_dev(kobj); struct lm3533_bl *bl = dev_get_drvdata(dev); umode_t mode = attr->mode; -- GitLab From 899c537c25f9547a0f591ed2013be0f9f68f2df3 Mon Sep 17 00:00:00 2001 From: Guru Das Srinagesh Date: Tue, 2 Jun 2020 15:31:05 -0700 Subject: [PATCH 0010/2249] drm/i915: Use 64-bit division macro Since the PWM framework is switching struct pwm_state.duty_cycle's datatype to u64, prepare for this transition by using DIV_ROUND_UP_ULL to handle a 64-bit dividend. Signed-off-by: Guru Das Srinagesh Reviewed-by: Jani Nikula Acked-by: Jani Nikula Signed-off-by: Thierry Reding --- drivers/gpu/drm/i915/display/intel_panel.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_panel.c b/drivers/gpu/drm/i915/display/intel_panel.c index 3c5056dbf6079..31cb285e8b38a 100644 --- a/drivers/gpu/drm/i915/display/intel_panel.c +++ b/drivers/gpu/drm/i915/display/intel_panel.c @@ -1929,7 +1929,7 @@ static int pwm_setup_backlight(struct intel_connector *connector, return retval; } - level = DIV_ROUND_UP(pwm_get_duty_cycle(panel->backlight.pwm) * 100, + level = DIV_ROUND_UP_ULL(pwm_get_duty_cycle(panel->backlight.pwm) * 100, CRC_PMIC_PWM_PERIOD_NS); panel->backlight.level = intel_panel_compute_brightness(connector, level); -- GitLab From f3e4b14144a928c097e2d526f6dcd6ba0f5eba8a Mon Sep 17 00:00:00 2001 From: Guru Das Srinagesh Date: Tue, 2 Jun 2020 15:31:06 -0700 Subject: [PATCH 0011/2249] hwmon: pwm-fan: Use 64-bit division macro Since the PWM framework is switching struct pwm_args.period's datatype to u64, prepare for this transition by using DIV_ROUND_UP_ULL to handle a 64-bit dividend. Signed-off-by: Guru Das Srinagesh Acked-by: Guenter Roeck Signed-off-by: Thierry Reding --- drivers/hwmon/pwm-fan.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/hwmon/pwm-fan.c b/drivers/hwmon/pwm-fan.c index 30b7b3ea8836f..17bb64299bfd8 100644 --- a/drivers/hwmon/pwm-fan.c +++ b/drivers/hwmon/pwm-fan.c @@ -447,7 +447,7 @@ static int pwm_fan_resume(struct device *dev) return 0; pwm_get_args(ctx->pwm, &pargs); - duty = DIV_ROUND_UP(ctx->pwm_value * (pargs.period - 1), MAX_PWM); + duty = DIV_ROUND_UP_ULL(ctx->pwm_value * (pargs.period - 1), MAX_PWM); ret = pwm_config(ctx->pwm, duty, pargs.period); if (ret) return ret; -- GitLab From 5bd0b9011da836dad1a00d92ebead7eaa87f5fe3 Mon Sep 17 00:00:00 2001 From: Guru Das Srinagesh Date: Tue, 2 Jun 2020 15:31:08 -0700 Subject: [PATCH 0012/2249] pwm: clps711x: Use 64-bit division macro Since the PWM framework is switching struct pwm_args.period's datatype to u64, prepare for this transition by using DIV64_U64_ROUND_CLOSEST to handle a 64-bit divisor. Cc: Daniel Thompson Signed-off-by: Guru Das Srinagesh Signed-off-by: Thierry Reding --- drivers/pwm/pwm-clps711x.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/pwm/pwm-clps711x.c b/drivers/pwm/pwm-clps711x.c index 924d39a797cf7..ba9500aca078a 100644 --- a/drivers/pwm/pwm-clps711x.c +++ b/drivers/pwm/pwm-clps711x.c @@ -43,7 +43,7 @@ static void clps711x_pwm_update_val(struct clps711x_chip *priv, u32 n, u32 v) static unsigned int clps711x_get_duty(struct pwm_device *pwm, unsigned int v) { /* Duty cycle 0..15 max */ - return DIV_ROUND_CLOSEST(v * 0xf, pwm->args.period); + return DIV64_U64_ROUND_CLOSEST(v * 0xf, pwm->args.period); } static int clps711x_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm) -- GitLab From fcdea6b2a3f6508618e39e061073a18c55993a1b Mon Sep 17 00:00:00 2001 From: Guru Das Srinagesh Date: Tue, 2 Jun 2020 15:31:09 -0700 Subject: [PATCH 0013/2249] pwm: imx-tpm: Use 64-bit division macro Since the PWM framework is switching struct pwm_state.period's datatype to u64, prepare for this transition by using DIV64_U64_ROUND_CLOSEST to handle a 64-bit divisor. Cc: Shawn Guo Cc: Sascha Hauer Cc: Pengutronix Kernel Team Cc: Fabio Estevam Cc: NXP Linux Team Signed-off-by: Guru Das Srinagesh Signed-off-by: Thierry Reding --- drivers/pwm/pwm-imx-tpm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/pwm/pwm-imx-tpm.c b/drivers/pwm/pwm-imx-tpm.c index 5f3d7f7e6aef0..fcdf6befb8389 100644 --- a/drivers/pwm/pwm-imx-tpm.c +++ b/drivers/pwm/pwm-imx-tpm.c @@ -124,7 +124,7 @@ static int pwm_imx_tpm_round_state(struct pwm_chip *chip, real_state->duty_cycle = state->duty_cycle; tmp = (u64)p->mod * real_state->duty_cycle; - p->val = DIV_ROUND_CLOSEST_ULL(tmp, real_state->period); + p->val = DIV64_U64_ROUND_CLOSEST(tmp, real_state->period); real_state->polarity = state->polarity; real_state->enabled = state->enabled; -- GitLab From 1689dcd433aaa0d32dec3fdb4bd166a0d38f4bbf Mon Sep 17 00:00:00 2001 From: Guru Das Srinagesh Date: Tue, 2 Jun 2020 15:31:11 -0700 Subject: [PATCH 0014/2249] pwm: imx27: Use 64-bit division macro Since the PWM framework is switching struct pwm_state.period's datatype to u64, prepare for this transition by using DIV_ROUND_UP_ULL to handle a 64-bit dividend. Signed-off-by: Guru Das Srinagesh Signed-off-by: Thierry Reding --- drivers/pwm/pwm-imx27.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/pwm/pwm-imx27.c b/drivers/pwm/pwm-imx27.c index 732a6f3701e8e..c50d453552bd4 100644 --- a/drivers/pwm/pwm-imx27.c +++ b/drivers/pwm/pwm-imx27.c @@ -202,7 +202,7 @@ static void pwm_imx27_wait_fifo_slot(struct pwm_chip *chip, sr = readl(imx->mmio_base + MX3_PWMSR); fifoav = FIELD_GET(MX3_PWMSR_FIFOAV, sr); if (fifoav == MX3_PWMSR_FIFOAV_4WORDS) { - period_ms = DIV_ROUND_UP(pwm_get_period(pwm), + period_ms = DIV_ROUND_UP_ULL(pwm_get_period(pwm), NSEC_PER_MSEC); msleep(period_ms); -- GitLab From 1627f683636df70fb25358b0a7b39a24e8fce5bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Myl=C3=A8ne=20Josserand?= Date: Tue, 2 Jun 2020 10:06:43 +0200 Subject: [PATCH 0015/2249] clk: rockchip: Handle clock tree for rk3288w variant MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The revision rk3288w has a different clock tree about "hclk_vio" clock, according to the BSP kernel code. This patch handles this difference by detecting which device-tree we are using. If it is a "rockchip,rk3288-cru", let's register the clock tree as it was before. If the device-tree node is "rockchip,rk3288w-cru", we will apply the difference with this version of this SoC. Noticed that this new device-tree compatible must be handled in bootloader such as u-boot. Signed-off-by: Mylène Josserand Link: https://lore.kernel.org/r/20200602080644.11333-2-mylene.josserand@collabora.com Signed-off-by: Heiko Stuebner --- drivers/clk/rockchip/clk-rk3288.c | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/drivers/clk/rockchip/clk-rk3288.c b/drivers/clk/rockchip/clk-rk3288.c index cc2a177bbdbf4..204976e2d0cb8 100644 --- a/drivers/clk/rockchip/clk-rk3288.c +++ b/drivers/clk/rockchip/clk-rk3288.c @@ -425,8 +425,6 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = { COMPOSITE(0, "aclk_vio0", mux_pll_src_cpll_gpll_usb480m_p, CLK_IGNORE_UNUSED, RK3288_CLKSEL_CON(31), 6, 2, MFLAGS, 0, 5, DFLAGS, RK3288_CLKGATE_CON(3), 0, GFLAGS), - DIV(0, "hclk_vio", "aclk_vio0", 0, - RK3288_CLKSEL_CON(28), 8, 5, DFLAGS), COMPOSITE(0, "aclk_vio1", mux_pll_src_cpll_gpll_usb480m_p, CLK_IGNORE_UNUSED, RK3288_CLKSEL_CON(31), 14, 2, MFLAGS, 8, 5, DFLAGS, RK3288_CLKGATE_CON(3), 2, GFLAGS), @@ -819,6 +817,16 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = { INVERTER(0, "pclk_isp", "pclk_isp_in", RK3288_CLKSEL_CON(29), 3, IFLAGS), }; +static struct rockchip_clk_branch rk3288w_hclkvio_branch[] __initdata = { + DIV(0, "hclk_vio", "aclk_vio1", 0, + RK3288_CLKSEL_CON(28), 8, 5, DFLAGS), +}; + +static struct rockchip_clk_branch rk3288_hclkvio_branch[] __initdata = { + DIV(0, "hclk_vio", "aclk_vio0", 0, + RK3288_CLKSEL_CON(28), 8, 5, DFLAGS), +}; + static const char *const rk3288_critical_clocks[] __initconst = { "aclk_cpu", "aclk_peri", @@ -936,6 +944,14 @@ static void __init rk3288_clk_init(struct device_node *np) RK3288_GRF_SOC_STATUS1); rockchip_clk_register_branches(ctx, rk3288_clk_branches, ARRAY_SIZE(rk3288_clk_branches)); + + if (of_device_is_compatible(np, "rockchip,rk3288w-cru")) + rockchip_clk_register_branches(ctx, rk3288w_hclkvio_branch, + ARRAY_SIZE(rk3288w_hclkvio_branch)); + else + rockchip_clk_register_branches(ctx, rk3288_hclkvio_branch, + ARRAY_SIZE(rk3288_hclkvio_branch)); + rockchip_clk_protect_critical(rk3288_critical_clocks, ARRAY_SIZE(rk3288_critical_clocks)); -- GitLab From 00bd404144241155653bb0d0c15be51e4e6983aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Myl=C3=A8ne=20Josserand?= Date: Tue, 2 Jun 2020 10:06:44 +0200 Subject: [PATCH 0016/2249] dt-bindings: clocks: add rk3288w variant compatible MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add the possible compatible "rockchip,rk3288w-cru" that handles the difference between the rk3288 and the new revision rk3288w. This compatible will be added by bootloaders. Signed-off-by: Mylène Josserand Acked-by: Rob Herring Link: https://lore.kernel.org/r/20200602080644.11333-3-mylene.josserand@collabora.com Signed-off-by: Heiko Stuebner --- .../devicetree/bindings/clock/rockchip,rk3288-cru.txt | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/clock/rockchip,rk3288-cru.txt b/Documentation/devicetree/bindings/clock/rockchip,rk3288-cru.txt index 8cb47c39ba539..bf3a9ec192416 100644 --- a/Documentation/devicetree/bindings/clock/rockchip,rk3288-cru.txt +++ b/Documentation/devicetree/bindings/clock/rockchip,rk3288-cru.txt @@ -4,9 +4,15 @@ The RK3288 clock controller generates and supplies clock to various controllers within the SoC and also implements a reset controller for SoC peripherals. +A revision of this SoC is available: rk3288w. The clock tree is a bit +different so another dt-compatible is available. Noticed that it is only +setting the difference but there is no automatic revision detection. This +should be performed by bootloaders. + Required Properties: -- compatible: should be "rockchip,rk3288-cru" +- compatible: should be "rockchip,rk3288-cru" or "rockchip,rk3288w-cru" in + case of this revision of Rockchip rk3288. - reg: physical base address of the controller and length of memory mapped region. - #clock-cells: should be 1. -- GitLab From 5bc5d99f1f836858820ad8e9a412bb103bb0d88b Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Mon, 15 Jun 2020 16:08:28 +0200 Subject: [PATCH 0017/2249] pwm: iqs620a: Use 64-bit division MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The PWM framework is going to change the PWM period and duty cycles to be 64-bit unsigned integers. To avoid build errors on platforms that do not natively support 64-bit division, use explicity 64-bit division. Acked-by: Uwe Kleine-König Acked-by: Lee Jones Signed-off-by: Thierry Reding --- drivers/pwm/pwm-iqs620a.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/pwm/pwm-iqs620a.c b/drivers/pwm/pwm-iqs620a.c index 674f0e238ba01..b2bb27eff6239 100644 --- a/drivers/pwm/pwm-iqs620a.c +++ b/drivers/pwm/pwm-iqs620a.c @@ -46,7 +46,8 @@ static int iqs620_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, { struct iqs620_pwm_private *iqs620_pwm; struct iqs62x_core *iqs62x; - int duty_scale, ret; + u64 duty_scale; + int ret; if (state->polarity != PWM_POLARITY_NORMAL) return -ENOTSUPP; @@ -69,7 +70,7 @@ static int iqs620_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, * For lower duty cycles (e.g. 0), the PWM output is simply disabled to * allow an external pull-down resistor to hold the GPIO3/LTX pin low. */ - duty_scale = state->duty_cycle * 256 / IQS620_PWM_PERIOD_NS; + duty_scale = div_u64(state->duty_cycle * 256, IQS620_PWM_PERIOD_NS); mutex_lock(&iqs620_pwm->lock); @@ -81,7 +82,7 @@ static int iqs620_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, } if (duty_scale) { - u8 duty_val = min(duty_scale - 1, 0xFF); + u8 duty_val = min_t(u64, duty_scale - 1, 0xff); ret = regmap_write(iqs62x->regmap, IQS620_PWM_DUTY_CYCLE, duty_val); -- GitLab From 4cc23430a5361f29999545de34fc05fa7d8e513b Mon Sep 17 00:00:00 2001 From: Guru Das Srinagesh Date: Tue, 2 Jun 2020 15:31:12 -0700 Subject: [PATCH 0018/2249] pwm: sifive: Use 64-bit division macro Since the PWM framework is switching struct pwm_args.period's datatype to u64, prepare for this transition by using DIV64_U64_ROUND_CLOSEST to handle a 64-bit divisor. Signed-off-by: Guru Das Srinagesh Acked-by: Palmer Dabbelt Signed-off-by: Thierry Reding --- drivers/pwm/pwm-sifive.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/pwm/pwm-sifive.c b/drivers/pwm/pwm-sifive.c index cc63f9baa4819..62de0bb859214 100644 --- a/drivers/pwm/pwm-sifive.c +++ b/drivers/pwm/pwm-sifive.c @@ -181,7 +181,7 @@ static int pwm_sifive_apply(struct pwm_chip *chip, struct pwm_device *pwm, * consecutively */ num = (u64)duty_cycle * (1U << PWM_SIFIVE_CMPWIDTH); - frac = DIV_ROUND_CLOSEST_ULL(num, state->period); + frac = DIV64_U64_ROUND_CLOSEST(num, state->period); /* The hardware cannot generate a 100% duty cycle */ frac = min(frac, (1U << PWM_SIFIVE_CMPWIDTH) - 1); -- GitLab From c7dcccaec2f7e99f95ad4b7c20f4f9086c6982be Mon Sep 17 00:00:00 2001 From: Guru Das Srinagesh Date: Tue, 2 Jun 2020 15:31:13 -0700 Subject: [PATCH 0019/2249] pwm: sun4i: Use nsecs_to_jiffies to avoid a division Since the PWM framework is switching struct pwm_state.period's datatype to u64, prepare for this transition by using nsecs_to_jiffies() which does away with the need for a division operation. Signed-off-by: Guru Das Srinagesh Acked-by: Chen-Yu Tsai Signed-off-by: Thierry Reding --- drivers/pwm/pwm-sun4i.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/pwm/pwm-sun4i.c b/drivers/pwm/pwm-sun4i.c index 18fbbe3277d0f..961c59c99bb3b 100644 --- a/drivers/pwm/pwm-sun4i.c +++ b/drivers/pwm/pwm-sun4i.c @@ -285,7 +285,7 @@ static int sun4i_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, val = (duty & PWM_DTY_MASK) | PWM_PRD(period); sun4i_pwm_writel(sun4i_pwm, val, PWM_CH_PRD(pwm->hwpwm)); sun4i_pwm->next_period[pwm->hwpwm] = jiffies + - usecs_to_jiffies(cstate.period / 1000 + 1); + nsecs_to_jiffies(cstate.period + 1000); if (state->polarity != PWM_POLARITY_NORMAL) ctrl &= ~BIT_CH(PWM_ACT_STATE, pwm->hwpwm); -- GitLab From 134ada17dbad272cdca57f2819a796c87e352274 Mon Sep 17 00:00:00 2001 From: Guru Das Srinagesh Date: Tue, 2 Jun 2020 15:31:14 -0700 Subject: [PATCH 0020/2249] backlight: pwm_bl: Use 64-bit division function Since the PWM framework is switching struct pwm_state.period's datatype to u64, prepare for this transition by using div_u64 to handle a 64-bit dividend instead of a straight division operation. Signed-off-by: Guru Das Srinagesh Reviewed-by: Daniel Thompson Acked-by: Lee Jones Signed-off-by: Thierry Reding --- drivers/video/backlight/pwm_bl.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/video/backlight/pwm_bl.c b/drivers/video/backlight/pwm_bl.c index 82b8d7594701d..464baade8f527 100644 --- a/drivers/video/backlight/pwm_bl.c +++ b/drivers/video/backlight/pwm_bl.c @@ -606,7 +606,8 @@ static int pwm_backlight_probe(struct platform_device *pdev) pb->scale = data->max_brightness; } - pb->lth_brightness = data->lth_brightness * (state.period / pb->scale); + pb->lth_brightness = data->lth_brightness * (div_u64(state.period, + pb->scale)); props.type = BACKLIGHT_RAW; props.max_brightness = data->max_brightness; -- GitLab From a6733474ba4bf3150120bacc1d2db446d89d3dbe Mon Sep 17 00:00:00 2001 From: Guru Das Srinagesh Date: Tue, 2 Jun 2020 15:31:15 -0700 Subject: [PATCH 0021/2249] clk: pwm: Use 64-bit division function Since the PWM framework is switching struct pwm_args.period's datatype to u64, prepare for this transition by using div64_u64() to handle a 64-bit divisor. Also ensure that divide-by-zero (with fixed_rate as denominator) does not happen with an explicit check with probe failure as a consequence. Signed-off-by: Guru Das Srinagesh Acked-by: Stephen Boyd Signed-off-by: Thierry Reding --- drivers/clk/clk-pwm.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/clk/clk-pwm.c b/drivers/clk/clk-pwm.c index 87fe0b0e01a3d..86f2e2d3fc022 100644 --- a/drivers/clk/clk-pwm.c +++ b/drivers/clk/clk-pwm.c @@ -89,7 +89,12 @@ static int clk_pwm_probe(struct platform_device *pdev) } if (of_property_read_u32(node, "clock-frequency", &clk_pwm->fixed_rate)) - clk_pwm->fixed_rate = NSEC_PER_SEC / pargs.period; + clk_pwm->fixed_rate = div64_u64(NSEC_PER_SEC, pargs.period); + + if (!clk_pwm->fixed_rate) { + dev_err(&pdev->dev, "fixed_rate cannot be zero\n"); + return -EINVAL; + } if (pargs.period != NSEC_PER_SEC / clk_pwm->fixed_rate && pargs.period != DIV_ROUND_UP(NSEC_PER_SEC, clk_pwm->fixed_rate)) { -- GitLab From a9d887dc1c60ed67f2271d66560cdcf864c4a578 Mon Sep 17 00:00:00 2001 From: Guru Das Srinagesh Date: Tue, 2 Jun 2020 15:31:16 -0700 Subject: [PATCH 0022/2249] pwm: Convert period and duty cycle to u64 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Because period and duty cycle are defined as ints with units of nanoseconds, the maximum time duration that can be set is limited to ~2.147 seconds. Change their definitions to u64 in the structs of the PWM framework so that higher durations may be set. Also use the right format specifiers in debug prints in both core.c, pwm-stm32-lp.c as well as video/fbdev/ssd1307fb.c. Reported-by: kbuild test robot Signed-off-by: Guru Das Srinagesh Acked-by: Uwe Kleine-König Signed-off-by: Thierry Reding --- drivers/pwm/core.c | 14 +++++++------- drivers/pwm/pwm-stm32-lp.c | 2 +- drivers/pwm/sysfs.c | 8 ++++---- drivers/video/fbdev/ssd1307fb.c | 2 +- include/linux/pwm.h | 12 ++++++------ 5 files changed, 19 insertions(+), 19 deletions(-) diff --git a/drivers/pwm/core.c b/drivers/pwm/core.c index 004b2ea9b5fde..276e939a56846 100644 --- a/drivers/pwm/core.c +++ b/drivers/pwm/core.c @@ -510,12 +510,12 @@ static void pwm_apply_state_debug(struct pwm_device *pwm, last->period > s2.period && last->period <= state->period) dev_warn(chip->dev, - ".apply didn't pick the best available period (requested: %u, applied: %u, possible: %u)\n", + ".apply didn't pick the best available period (requested: %llu, applied: %llu, possible: %llu)\n", state->period, s2.period, last->period); if (state->enabled && state->period < s2.period) dev_warn(chip->dev, - ".apply is supposed to round down period (requested: %u, applied: %u)\n", + ".apply is supposed to round down period (requested: %llu, applied: %llu)\n", state->period, s2.period); if (state->enabled && @@ -524,14 +524,14 @@ static void pwm_apply_state_debug(struct pwm_device *pwm, last->duty_cycle > s2.duty_cycle && last->duty_cycle <= state->duty_cycle) dev_warn(chip->dev, - ".apply didn't pick the best available duty cycle (requested: %u/%u, applied: %u/%u, possible: %u/%u)\n", + ".apply didn't pick the best available duty cycle (requested: %llu/%llu, applied: %llu/%llu, possible: %llu/%llu)\n", state->duty_cycle, state->period, s2.duty_cycle, s2.period, last->duty_cycle, last->period); if (state->enabled && state->duty_cycle < s2.duty_cycle) dev_warn(chip->dev, - ".apply is supposed to round down duty_cycle (requested: %u/%u, applied: %u/%u)\n", + ".apply is supposed to round down duty_cycle (requested: %llu/%llu, applied: %llu/%llu)\n", state->duty_cycle, state->period, s2.duty_cycle, s2.period); @@ -558,7 +558,7 @@ static void pwm_apply_state_debug(struct pwm_device *pwm, (s1.enabled && s1.period != last->period) || (s1.enabled && s1.duty_cycle != last->duty_cycle)) { dev_err(chip->dev, - ".apply is not idempotent (ena=%d pol=%d %u/%u) -> (ena=%d pol=%d %u/%u)\n", + ".apply is not idempotent (ena=%d pol=%d %llu/%llu) -> (ena=%d pol=%d %llu/%llu)\n", s1.enabled, s1.polarity, s1.duty_cycle, s1.period, last->enabled, last->polarity, last->duty_cycle, last->period); @@ -1284,8 +1284,8 @@ static void pwm_dbg_show(struct pwm_chip *chip, struct seq_file *s) if (state.enabled) seq_puts(s, " enabled"); - seq_printf(s, " period: %u ns", state.period); - seq_printf(s, " duty: %u ns", state.duty_cycle); + seq_printf(s, " period: %llu ns", state.period); + seq_printf(s, " duty: %llu ns", state.duty_cycle); seq_printf(s, " polarity: %s", state.polarity ? "inverse" : "normal"); diff --git a/drivers/pwm/pwm-stm32-lp.c b/drivers/pwm/pwm-stm32-lp.c index 67fca62524dc2..134c14621ee01 100644 --- a/drivers/pwm/pwm-stm32-lp.c +++ b/drivers/pwm/pwm-stm32-lp.c @@ -61,7 +61,7 @@ static int stm32_pwm_lp_apply(struct pwm_chip *chip, struct pwm_device *pwm, do_div(div, NSEC_PER_SEC); if (!div) { /* Clock is too slow to achieve requested period. */ - dev_dbg(priv->chip.dev, "Can't reach %u ns\n", state->period); + dev_dbg(priv->chip.dev, "Can't reach %llu ns\n", state->period); return -EINVAL; } diff --git a/drivers/pwm/sysfs.c b/drivers/pwm/sysfs.c index 2389b86698468..449dbc0f49ede 100644 --- a/drivers/pwm/sysfs.c +++ b/drivers/pwm/sysfs.c @@ -42,7 +42,7 @@ static ssize_t period_show(struct device *child, pwm_get_state(pwm, &state); - return sprintf(buf, "%u\n", state.period); + return sprintf(buf, "%llu\n", state.period); } static ssize_t period_store(struct device *child, @@ -52,10 +52,10 @@ static ssize_t period_store(struct device *child, struct pwm_export *export = child_to_pwm_export(child); struct pwm_device *pwm = export->pwm; struct pwm_state state; - unsigned int val; + u64 val; int ret; - ret = kstrtouint(buf, 0, &val); + ret = kstrtou64(buf, 0, &val); if (ret) return ret; @@ -77,7 +77,7 @@ static ssize_t duty_cycle_show(struct device *child, pwm_get_state(pwm, &state); - return sprintf(buf, "%u\n", state.duty_cycle); + return sprintf(buf, "%llu\n", state.duty_cycle); } static ssize_t duty_cycle_store(struct device *child, diff --git a/drivers/video/fbdev/ssd1307fb.c b/drivers/video/fbdev/ssd1307fb.c index 8e06ba912d60a..09425ec317ba2 100644 --- a/drivers/video/fbdev/ssd1307fb.c +++ b/drivers/video/fbdev/ssd1307fb.c @@ -312,7 +312,7 @@ static int ssd1307fb_init(struct ssd1307fb_par *par) /* Enable the PWM */ pwm_enable(par->pwm); - dev_dbg(&par->client->dev, "Using PWM%d with a %dns period.\n", + dev_dbg(&par->client->dev, "Using PWM%d with a %lluns period.\n", par->pwm->pwm, pwm_get_period(par->pwm)); } diff --git a/include/linux/pwm.h b/include/linux/pwm.h index 2635b2a55090d..a13ff383fa1d5 100644 --- a/include/linux/pwm.h +++ b/include/linux/pwm.h @@ -39,7 +39,7 @@ enum pwm_polarity { * current PWM hardware state. */ struct pwm_args { - unsigned int period; + u64 period; enum pwm_polarity polarity; }; @@ -56,8 +56,8 @@ enum { * @enabled: PWM enabled status */ struct pwm_state { - unsigned int period; - unsigned int duty_cycle; + u64 period; + u64 duty_cycle; enum pwm_polarity polarity; bool enabled; }; @@ -107,13 +107,13 @@ static inline bool pwm_is_enabled(const struct pwm_device *pwm) return state.enabled; } -static inline void pwm_set_period(struct pwm_device *pwm, unsigned int period) +static inline void pwm_set_period(struct pwm_device *pwm, u64 period) { if (pwm) pwm->state.period = period; } -static inline unsigned int pwm_get_period(const struct pwm_device *pwm) +static inline u64 pwm_get_period(const struct pwm_device *pwm) { struct pwm_state state; @@ -128,7 +128,7 @@ static inline void pwm_set_duty_cycle(struct pwm_device *pwm, unsigned int duty) pwm->state.duty_cycle = duty; } -static inline unsigned int pwm_get_duty_cycle(const struct pwm_device *pwm) +static inline u64 pwm_get_duty_cycle(const struct pwm_device *pwm) { struct pwm_state state; -- GitLab From b8fb642afa0277a0a9072fe119c1fce18437de0d Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Mon, 15 Jun 2020 16:10:16 +0200 Subject: [PATCH 0023/2249] pwm: iqs620a: Use lowercase hexadecimal literals for consistency Other drivers use lowercase hexadecimal literals, so convert the IQS620a driver to do the same for consistency. Signed-off-by: Thierry Reding --- drivers/pwm/pwm-iqs620a.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/pwm/pwm-iqs620a.c b/drivers/pwm/pwm-iqs620a.c index b2bb27eff6239..7d33e36464360 100644 --- a/drivers/pwm/pwm-iqs620a.c +++ b/drivers/pwm/pwm-iqs620a.c @@ -25,10 +25,10 @@ #include #include -#define IQS620_PWR_SETTINGS 0xD2 +#define IQS620_PWR_SETTINGS 0xd2 #define IQS620_PWR_SETTINGS_PWM_OUT BIT(7) -#define IQS620_PWM_DUTY_CYCLE 0xD8 +#define IQS620_PWM_DUTY_CYCLE 0xd8 #define IQS620_PWM_PERIOD_NS 1000000 @@ -94,7 +94,7 @@ static int iqs620_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, if (state->enabled && duty_scale) { ret = regmap_update_bits(iqs62x->regmap, IQS620_PWR_SETTINGS, - IQS620_PWR_SETTINGS_PWM_OUT, 0xFF); + IQS620_PWR_SETTINGS_PWM_OUT, 0xff); if (ret) goto err_mutex; } @@ -160,7 +160,7 @@ static int iqs620_pwm_notifier(struct notifier_block *notifier, ret = regmap_update_bits(iqs62x->regmap, IQS620_PWR_SETTINGS, IQS620_PWR_SETTINGS_PWM_OUT, - iqs620_pwm->out_en ? 0xFF : 0); + iqs620_pwm->out_en ? 0xff : 0); err_mutex: mutex_unlock(&iqs620_pwm->lock); -- GitLab From cb8ae6e188a2230a2515493918385dd054e14fa1 Mon Sep 17 00:00:00 2001 From: Benjamin Gaignard Date: Wed, 3 Jun 2020 14:54:34 +0200 Subject: [PATCH 0024/2249] dt-bindings: mfd: Document STM32 low power timer bindings Add a subnode to STM low power timer bindings to support timer driver Signed-off-by: Benjamin Gaignard Reviewed-by: Rob Herring Signed-off-by: Lee Jones --- Documentation/devicetree/bindings/mfd/st,stm32-lptimer.yaml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Documentation/devicetree/bindings/mfd/st,stm32-lptimer.yaml b/Documentation/devicetree/bindings/mfd/st,stm32-lptimer.yaml index e675611f80d03..8bcea8dd7d908 100644 --- a/Documentation/devicetree/bindings/mfd/st,stm32-lptimer.yaml +++ b/Documentation/devicetree/bindings/mfd/st,stm32-lptimer.yaml @@ -33,6 +33,9 @@ properties: items: - const: mux + interrupts: + maxItems: 1 + "#address-cells": const: 1 @@ -106,11 +109,13 @@ additionalProperties: false examples: - | #include + #include timer@40002400 { compatible = "st,stm32-lptimer"; reg = <0x40002400 0x400>; clocks = <&timer_clk>; clock-names = "mux"; + interrupts-extended = <&exti 47 IRQ_TYPE_LEVEL_HIGH>; #address-cells = <1>; #size-cells = <0>; -- GitLab From e0bcc58d876c6ece9720310509a908b7637e37cf Mon Sep 17 00:00:00 2001 From: Benjamin Gaignard Date: Wed, 3 Jun 2020 14:54:36 +0200 Subject: [PATCH 0025/2249] mfd: stm32: Add defines to be used for clkevent purpose Add defines to be able to enable/clear irq and configure one shot mode. Signed-off-by: Benjamin Gaignard Signed-off-by: Lee Jones --- include/linux/mfd/stm32-lptimer.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/include/linux/mfd/stm32-lptimer.h b/include/linux/mfd/stm32-lptimer.h index 605f622648258..90b20550c1c8b 100644 --- a/include/linux/mfd/stm32-lptimer.h +++ b/include/linux/mfd/stm32-lptimer.h @@ -27,10 +27,15 @@ #define STM32_LPTIM_CMPOK BIT(3) /* STM32_LPTIM_ICR - bit fields */ +#define STM32_LPTIM_ARRMCF BIT(1) #define STM32_LPTIM_CMPOKCF_ARROKCF GENMASK(4, 3) +/* STM32_LPTIM_IER - bit flieds */ +#define STM32_LPTIM_ARRMIE BIT(1) + /* STM32_LPTIM_CR - bit fields */ #define STM32_LPTIM_CNTSTRT BIT(2) +#define STM32_LPTIM_SNGSTRT BIT(1) #define STM32_LPTIM_ENABLE BIT(0) /* STM32_LPTIM_CFGR - bit fields */ -- GitLab From 45d93065c8ec4e671f4b1ff02b5b3a633658a92f Mon Sep 17 00:00:00 2001 From: Benjamin Gaignard Date: Wed, 3 Jun 2020 14:54:37 +0200 Subject: [PATCH 0026/2249] mfd: stm32: Enable regmap fast_io for stm32-lptimer Because stm32-lptimer need to write in registers in interrupt context enable regmap fast_io to use a spin_lock to protect registers access rather than a mutex. Signed-off-by: Benjamin Gaignard Signed-off-by: Lee Jones --- drivers/mfd/stm32-lptimer.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/mfd/stm32-lptimer.c b/drivers/mfd/stm32-lptimer.c index a00f99f365595..746e51a17cc8e 100644 --- a/drivers/mfd/stm32-lptimer.c +++ b/drivers/mfd/stm32-lptimer.c @@ -17,6 +17,7 @@ static const struct regmap_config stm32_lptimer_regmap_cfg = { .val_bits = 32, .reg_stride = sizeof(u32), .max_register = STM32_LPTIM_MAX_REGISTER, + .fast_io = true, }; static int stm32_lptimer_detect_encoder(struct stm32_lptimer *ddata) -- GitLab From 48b41c5e2de6c52c90efa99cfa122a5da7a7f0cd Mon Sep 17 00:00:00 2001 From: Benjamin Gaignard Date: Wed, 3 Jun 2020 14:54:38 +0200 Subject: [PATCH 0027/2249] clocksource: Add Low Power STM32 timers driver Implement clock event driver using low power STM32 timers. Low power timer counters running even when CPUs are stopped. It could be used as clock event broadcaster to wake up CPUs but not like a clocksource because each it rise an interrupt the counter restart from 0. Low power timers have a 16 bits counter and a prescaler which allow to divide the clock per power of 2 to up 128 to target a 32KHz rate. Signed-off-by: Benjamin Gaignard Signed-off-by: Pascal Paillet Acked-by: Daniel Lezcano Signed-off-by: Lee Jones --- drivers/clocksource/Kconfig | 4 + drivers/clocksource/Makefile | 1 + drivers/clocksource/timer-stm32-lp.c | 221 +++++++++++++++++++++++++++ 3 files changed, 226 insertions(+) create mode 100644 drivers/clocksource/timer-stm32-lp.c diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig index 91418381fcd41..be49123b088ab 100644 --- a/drivers/clocksource/Kconfig +++ b/drivers/clocksource/Kconfig @@ -291,6 +291,10 @@ config CLKSRC_STM32 select CLKSRC_MMIO select TIMER_OF +config CLKSRC_STM32_LP + bool "Low power clocksource for STM32 SoCs" + depends on MFD_STM32_LPTIMER || COMPILE_TEST + config CLKSRC_MPS2 bool "Clocksource for MPS2 SoCs" if COMPILE_TEST depends on GENERIC_SCHED_CLOCK diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile index bdda1a2e4097d..66501e64d0b64 100644 --- a/drivers/clocksource/Makefile +++ b/drivers/clocksource/Makefile @@ -45,6 +45,7 @@ obj-$(CONFIG_BCM_KONA_TIMER) += bcm_kona_timer.o obj-$(CONFIG_CADENCE_TTC_TIMER) += timer-cadence-ttc.o obj-$(CONFIG_CLKSRC_EFM32) += timer-efm32.o obj-$(CONFIG_CLKSRC_STM32) += timer-stm32.o +obj-$(CONFIG_CLKSRC_STM32_LP) += timer-stm32-lp.o obj-$(CONFIG_CLKSRC_EXYNOS_MCT) += exynos_mct.o obj-$(CONFIG_CLKSRC_LPC32XX) += timer-lpc32xx.o obj-$(CONFIG_CLKSRC_MPS2) += mps2-timer.o diff --git a/drivers/clocksource/timer-stm32-lp.c b/drivers/clocksource/timer-stm32-lp.c new file mode 100644 index 0000000000000..db2841d0beb81 --- /dev/null +++ b/drivers/clocksource/timer-stm32-lp.c @@ -0,0 +1,221 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) STMicroelectronics 2019 - All Rights Reserved + * Authors: Benjamin Gaignard for STMicroelectronics. + * Pascal Paillet for STMicroelectronics. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define CFGR_PSC_OFFSET 9 +#define STM32_LP_RATING 1000 +#define STM32_TARGET_CLKRATE (32000 * HZ) +#define STM32_LP_MAX_PSC 7 + +struct stm32_lp_private { + struct regmap *reg; + struct clock_event_device clkevt; + unsigned long period; + struct device *dev; +}; + +static struct stm32_lp_private* +to_priv(struct clock_event_device *clkevt) +{ + return container_of(clkevt, struct stm32_lp_private, clkevt); +} + +static int stm32_clkevent_lp_shutdown(struct clock_event_device *clkevt) +{ + struct stm32_lp_private *priv = to_priv(clkevt); + + regmap_write(priv->reg, STM32_LPTIM_CR, 0); + regmap_write(priv->reg, STM32_LPTIM_IER, 0); + /* clear pending flags */ + regmap_write(priv->reg, STM32_LPTIM_ICR, STM32_LPTIM_ARRMCF); + + return 0; +} + +static int stm32_clkevent_lp_set_timer(unsigned long evt, + struct clock_event_device *clkevt, + int is_periodic) +{ + struct stm32_lp_private *priv = to_priv(clkevt); + + /* disable LPTIMER to be able to write into IER register*/ + regmap_write(priv->reg, STM32_LPTIM_CR, 0); + /* enable ARR interrupt */ + regmap_write(priv->reg, STM32_LPTIM_IER, STM32_LPTIM_ARRMIE); + /* enable LPTIMER to be able to write into ARR register */ + regmap_write(priv->reg, STM32_LPTIM_CR, STM32_LPTIM_ENABLE); + /* set next event counter */ + regmap_write(priv->reg, STM32_LPTIM_ARR, evt); + + /* start counter */ + if (is_periodic) + regmap_write(priv->reg, STM32_LPTIM_CR, + STM32_LPTIM_CNTSTRT | STM32_LPTIM_ENABLE); + else + regmap_write(priv->reg, STM32_LPTIM_CR, + STM32_LPTIM_SNGSTRT | STM32_LPTIM_ENABLE); + + return 0; +} + +static int stm32_clkevent_lp_set_next_event(unsigned long evt, + struct clock_event_device *clkevt) +{ + return stm32_clkevent_lp_set_timer(evt, clkevt, + clockevent_state_periodic(clkevt)); +} + +static int stm32_clkevent_lp_set_periodic(struct clock_event_device *clkevt) +{ + struct stm32_lp_private *priv = to_priv(clkevt); + + return stm32_clkevent_lp_set_timer(priv->period, clkevt, true); +} + +static int stm32_clkevent_lp_set_oneshot(struct clock_event_device *clkevt) +{ + struct stm32_lp_private *priv = to_priv(clkevt); + + return stm32_clkevent_lp_set_timer(priv->period, clkevt, false); +} + +static irqreturn_t stm32_clkevent_lp_irq_handler(int irq, void *dev_id) +{ + struct clock_event_device *clkevt = (struct clock_event_device *)dev_id; + struct stm32_lp_private *priv = to_priv(clkevt); + + regmap_write(priv->reg, STM32_LPTIM_ICR, STM32_LPTIM_ARRMCF); + + if (clkevt->event_handler) + clkevt->event_handler(clkevt); + + return IRQ_HANDLED; +} + +static void stm32_clkevent_lp_set_prescaler(struct stm32_lp_private *priv, + unsigned long *rate) +{ + int i; + + for (i = 0; i <= STM32_LP_MAX_PSC; i++) { + if (DIV_ROUND_CLOSEST(*rate, 1 << i) < STM32_TARGET_CLKRATE) + break; + } + + regmap_write(priv->reg, STM32_LPTIM_CFGR, i << CFGR_PSC_OFFSET); + + /* Adjust rate and period given the prescaler value */ + *rate = DIV_ROUND_CLOSEST(*rate, (1 << i)); + priv->period = DIV_ROUND_UP(*rate, HZ); +} + +static void stm32_clkevent_lp_init(struct stm32_lp_private *priv, + struct device_node *np, unsigned long rate) +{ + priv->clkevt.name = np->full_name; + priv->clkevt.cpumask = cpu_possible_mask; + priv->clkevt.features = CLOCK_EVT_FEAT_PERIODIC | + CLOCK_EVT_FEAT_ONESHOT; + priv->clkevt.set_state_shutdown = stm32_clkevent_lp_shutdown; + priv->clkevt.set_state_periodic = stm32_clkevent_lp_set_periodic; + priv->clkevt.set_state_oneshot = stm32_clkevent_lp_set_oneshot; + priv->clkevt.set_next_event = stm32_clkevent_lp_set_next_event; + priv->clkevt.rating = STM32_LP_RATING; + + clockevents_config_and_register(&priv->clkevt, rate, 0x1, + STM32_LPTIM_MAX_ARR); +} + +static int stm32_clkevent_lp_probe(struct platform_device *pdev) +{ + struct stm32_lptimer *ddata = dev_get_drvdata(pdev->dev.parent); + struct stm32_lp_private *priv; + unsigned long rate; + int ret, irq; + + priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + priv->reg = ddata->regmap; + ret = clk_prepare_enable(ddata->clk); + if (ret) + return -EINVAL; + + rate = clk_get_rate(ddata->clk); + if (!rate) { + ret = -EINVAL; + goto out_clk_disable; + } + + irq = platform_get_irq(to_platform_device(pdev->dev.parent), 0); + if (irq <= 0) { + ret = irq; + goto out_clk_disable; + } + + if (of_property_read_bool(pdev->dev.parent->of_node, "wakeup-source")) { + ret = device_init_wakeup(&pdev->dev, true); + if (ret) + goto out_clk_disable; + + ret = dev_pm_set_wake_irq(&pdev->dev, irq); + if (ret) + goto out_clk_disable; + } + + ret = devm_request_irq(&pdev->dev, irq, stm32_clkevent_lp_irq_handler, + IRQF_TIMER, pdev->name, &priv->clkevt); + if (ret) + goto out_clk_disable; + + stm32_clkevent_lp_set_prescaler(priv, &rate); + + stm32_clkevent_lp_init(priv, pdev->dev.parent->of_node, rate); + + priv->dev = &pdev->dev; + + return 0; + +out_clk_disable: + clk_disable_unprepare(ddata->clk); + return ret; +} + +static int stm32_clkevent_lp_remove(struct platform_device *pdev) +{ + return -EBUSY; /* cannot unregister clockevent */ +} + +static const struct of_device_id stm32_clkevent_lp_of_match[] = { + { .compatible = "st,stm32-lptimer-timer", }, + {}, +}; +MODULE_DEVICE_TABLE(of, stm32_clkevent_lp_of_match); + +static struct platform_driver stm32_clkevent_lp_driver = { + .probe = stm32_clkevent_lp_probe, + .remove = stm32_clkevent_lp_remove, + .driver = { + .name = "stm32-lptimer-timer", + .of_match_table = of_match_ptr(stm32_clkevent_lp_of_match), + }, +}; +module_platform_driver(stm32_clkevent_lp_driver); + +MODULE_ALIAS("platform:stm32-lptimer-timer"); +MODULE_DESCRIPTION("STMicroelectronics STM32 clockevent low power driver"); +MODULE_LICENSE("GPL v2"); -- GitLab From 3ea2e4eab64cefa06055bb0541fcdedad4b48565 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 15 Jun 2020 19:10:32 +0300 Subject: [PATCH 0028/2249] mfd: intel-lpss: Add Intel Emmitsburg PCH PCI IDs Intel Emmitsburg PCH has the same LPSS than Intel Ice Lake. Add the new IDs to the list of supported devices. Signed-off-by: Andy Shevchenko Signed-off-by: Lee Jones --- drivers/mfd/intel-lpss-pci.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/mfd/intel-lpss-pci.c b/drivers/mfd/intel-lpss-pci.c index 046222684b8b2..17bcadc00a11c 100644 --- a/drivers/mfd/intel-lpss-pci.c +++ b/drivers/mfd/intel-lpss-pci.c @@ -201,6 +201,9 @@ static const struct pci_device_id intel_lpss_pci_ids[] = { { PCI_VDEVICE(INTEL, 0x1ac4), (kernel_ulong_t)&bxt_info }, { PCI_VDEVICE(INTEL, 0x1ac6), (kernel_ulong_t)&bxt_info }, { PCI_VDEVICE(INTEL, 0x1aee), (kernel_ulong_t)&bxt_uart_info }, + /* EBG */ + { PCI_VDEVICE(INTEL, 0x1bad), (kernel_ulong_t)&bxt_uart_info }, + { PCI_VDEVICE(INTEL, 0x1bae), (kernel_ulong_t)&bxt_uart_info }, /* GLK */ { PCI_VDEVICE(INTEL, 0x31ac), (kernel_ulong_t)&glk_i2c_info }, { PCI_VDEVICE(INTEL, 0x31ae), (kernel_ulong_t)&glk_i2c_info }, -- GitLab From 14024cc9fe9478b9948521c0d38fde03ac00cd3d Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Mon, 15 Jun 2020 14:53:20 +0100 Subject: [PATCH 0029/2249] mfd: arizona: Remove BUG_ON usage BUG_ON macros are generally frowned upon when the issue isn't super critical, the kernel can certainly carry on with the 32k clock on the CODEC in a bad state so change the BUG_ON to a WARN_ON. Signed-off-by: Charles Keepax Signed-off-by: Lee Jones --- drivers/mfd/arizona-core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mfd/arizona-core.c b/drivers/mfd/arizona-core.c index f73cf76d1373d..19e0bc3c0683e 100644 --- a/drivers/mfd/arizona-core.c +++ b/drivers/mfd/arizona-core.c @@ -80,7 +80,7 @@ int arizona_clk32k_disable(struct arizona *arizona) { mutex_lock(&arizona->clk_lock); - BUG_ON(arizona->clk32k_ref <= 0); + WARN_ON(arizona->clk32k_ref <= 0); arizona->clk32k_ref--; -- GitLab From ddff6c45b21d0437ce0c85f8ac35d7b5480513d7 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Mon, 15 Jun 2020 14:53:21 +0100 Subject: [PATCH 0030/2249] mfd: arizona: Ensure 32k clock is put on driver unbind and error Whilst it doesn't matter if the internal 32k clock register settings are cleaned up on exit, as the part will be turned off losing any settings, hence the driver hasn't historially bothered. The external clock should however be cleaned up, as it could cause clocks to be left on, and will at best generate a warning on unbind. Add clean up on both the probe error path and unbind for the 32k clock. Fixes: cdd8da8cc66b ("mfd: arizona: Add gating of external MCLKn clocks") Signed-off-by: Charles Keepax Signed-off-by: Lee Jones --- drivers/mfd/arizona-core.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/drivers/mfd/arizona-core.c b/drivers/mfd/arizona-core.c index 19e0bc3c0683e..000cb82023e35 100644 --- a/drivers/mfd/arizona-core.c +++ b/drivers/mfd/arizona-core.c @@ -1426,6 +1426,15 @@ int arizona_dev_init(struct arizona *arizona) arizona_irq_exit(arizona); err_pm: pm_runtime_disable(arizona->dev); + + switch (arizona->pdata.clk32k_src) { + case ARIZONA_32KZ_MCLK1: + case ARIZONA_32KZ_MCLK2: + arizona_clk32k_disable(arizona); + break; + default: + break; + } err_reset: arizona_enable_reset(arizona); regulator_disable(arizona->dcvdd); @@ -1448,6 +1457,15 @@ int arizona_dev_exit(struct arizona *arizona) regulator_disable(arizona->dcvdd); regulator_put(arizona->dcvdd); + switch (arizona->pdata.clk32k_src) { + case ARIZONA_32KZ_MCLK1: + case ARIZONA_32KZ_MCLK2: + arizona_clk32k_disable(arizona); + break; + default: + break; + } + mfd_remove_devices(arizona->dev); arizona_free_irq(arizona, ARIZONA_IRQ_UNDERCLOCKED, arizona); arizona_free_irq(arizona, ARIZONA_IRQ_OVERCLOCKED, arizona); -- GitLab From 7f8a137f736f7366820c485c5a0d34d65b9d0125 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Mon, 15 Jun 2020 14:53:22 +0100 Subject: [PATCH 0031/2249] mfd: madera: Remove unused forward declaration of madera_codec_pdata This forward declaration is redundant since the header including the full data structure is included. Signed-off-by: Charles Keepax Signed-off-by: Lee Jones --- include/linux/mfd/madera/pdata.h | 1 - 1 file changed, 1 deletion(-) diff --git a/include/linux/mfd/madera/pdata.h b/include/linux/mfd/madera/pdata.h index fa9595dd42ba5..601cbbc10370c 100644 --- a/include/linux/mfd/madera/pdata.h +++ b/include/linux/mfd/madera/pdata.h @@ -21,7 +21,6 @@ struct gpio_desc; struct pinctrl_map; -struct madera_codec_pdata; /** * struct madera_pdata - Configuration data for Madera devices -- GitLab From b92735f45f99c9bdcf93ce822fab56231e64a904 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Mon, 15 Jun 2020 14:53:23 +0100 Subject: [PATCH 0032/2249] mfd: madera: Fix minor formatting issues The mfd_cell structures inconsistently use commas on single entries in the table, make this consistent by always using a comma. Also remove an extra blank line. Signed-off-by: Charles Keepax Signed-off-by: Lee Jones --- drivers/mfd/madera-core.c | 12 ++++++------ drivers/mfd/madera-i2c.c | 1 - 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/drivers/mfd/madera-core.c b/drivers/mfd/madera-core.c index 7e0835cb062b1..4724c1a01a39f 100644 --- a/drivers/mfd/madera-core.c +++ b/drivers/mfd/madera-core.c @@ -44,7 +44,7 @@ static const char * const madera_core_supplies[] = { }; static const struct mfd_cell madera_ldo1_devs[] = { - { .name = "madera-ldo1" }, + { .name = "madera-ldo1", }, }; static const char * const cs47l15_supplies[] = { @@ -55,8 +55,8 @@ static const char * const cs47l15_supplies[] = { static const struct mfd_cell cs47l15_devs[] = { { .name = "madera-pinctrl", }, - { .name = "madera-irq" }, - { .name = "madera-gpio" }, + { .name = "madera-irq", }, + { .name = "madera-gpio", }, { .name = "madera-extcon", .parent_supplies = cs47l15_supplies, @@ -108,7 +108,7 @@ static const char * const cs47l85_supplies[] = { static const struct mfd_cell cs47l85_devs[] = { { .name = "madera-pinctrl", }, { .name = "madera-irq", }, - { .name = "madera-micsupp" }, + { .name = "madera-micsupp", }, { .name = "madera-gpio", }, { .name = "madera-extcon", @@ -155,10 +155,10 @@ static const char * const cs47l92_supplies[] = { }; static const struct mfd_cell cs47l92_devs[] = { - { .name = "madera-pinctrl" }, + { .name = "madera-pinctrl", }, { .name = "madera-irq", }, { .name = "madera-micsupp", }, - { .name = "madera-gpio" }, + { .name = "madera-gpio", }, { .name = "madera-extcon", .parent_supplies = cs47l92_supplies, diff --git a/drivers/mfd/madera-i2c.c b/drivers/mfd/madera-i2c.c index 6b965eb034b6c..7df5b9ba58554 100644 --- a/drivers/mfd/madera-i2c.c +++ b/drivers/mfd/madera-i2c.c @@ -88,7 +88,6 @@ static int madera_i2c_probe(struct i2c_client *i2c, if (!madera) return -ENOMEM; - madera->regmap = devm_regmap_init_i2c(i2c, regmap_16bit_config); if (IS_ERR(madera->regmap)) { ret = PTR_ERR(madera->regmap); -- GitLab From ad738ddd506b68679faf79277280b75522dd84e7 Mon Sep 17 00:00:00 2001 From: Tim Harvey Date: Tue, 9 Jun 2020 07:57:19 -0700 Subject: [PATCH 0033/2249] dt-bindings: mfd: gateworks-gsc: Add 16bit pre-scaled voltage mode Add a 16-bit pre-scaled voltage mode to ADC and clarify that existing pre-scaled mode is 24bit. Signed-off-by: Tim Harvey Acked-by: Rob Herring Signed-off-by: Lee Jones --- Documentation/devicetree/bindings/mfd/gateworks-gsc.yaml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/mfd/gateworks-gsc.yaml b/Documentation/devicetree/bindings/mfd/gateworks-gsc.yaml index 487a8445722e5..ceec33f6aba15 100644 --- a/Documentation/devicetree/bindings/mfd/gateworks-gsc.yaml +++ b/Documentation/devicetree/bindings/mfd/gateworks-gsc.yaml @@ -79,11 +79,12 @@ properties: description: | conversion mode: 0 - temperature, in C*10 - 1 - pre-scaled voltage value + 1 - pre-scaled 24-bit voltage value 2 - scaled voltage based on an optional resistor divider and optional offset + 3 - pre-scaled 16-bit voltage value $ref: /schemas/types.yaml#/definitions/uint32 - enum: [0, 1, 2] + enum: [0, 1, 2, 3] gw,voltage-divider-ohms: description: Values of resistors for divider on raw ADC input -- GitLab From 6bcb330c1f373f314118f772c6e22f1cc36d7683 Mon Sep 17 00:00:00 2001 From: Neil Armstrong Date: Mon, 8 Jun 2020 11:17:35 +0200 Subject: [PATCH 0034/2249] dt-bindings: mfd: Add Khadas Microcontroller bindings This Microcontroller is present on the Khadas VIM1, VIM2, VIM3 and Edge boards. It has multiple boot control features like password check, power-on options, power-off control and system FAN control on recent boards. Signed-off-by: Neil Armstrong Reviewed-by: Rob Herring Signed-off-by: Lee Jones --- .../devicetree/bindings/mfd/khadas,mcu.yaml | 44 +++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 Documentation/devicetree/bindings/mfd/khadas,mcu.yaml diff --git a/Documentation/devicetree/bindings/mfd/khadas,mcu.yaml b/Documentation/devicetree/bindings/mfd/khadas,mcu.yaml new file mode 100644 index 0000000000000..a3b976f101e8c --- /dev/null +++ b/Documentation/devicetree/bindings/mfd/khadas,mcu.yaml @@ -0,0 +1,44 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/mfd/khadas,mcu.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Khadas on-board Microcontroller Device Tree Bindings + +maintainers: + - Neil Armstrong + +description: | + Khadas embeds a microcontroller on their VIM and Edge boards adding some + system feature as PWM Fan control (for VIM2 rev14 or VIM3), User memory + storage, IR/Key resume control, system power LED control and more. + +properties: + compatible: + enum: + - khadas,mcu # MCU revision is discoverable + + "#cooling-cells": # Only needed for boards having FAN control feature + const: 2 + + reg: + maxItems: 1 + +required: + - compatible + - reg + +additionalProperties: false + +examples: + - | + i2c { + #address-cells = <1>; + #size-cells = <0>; + khadas_mcu: system-controller@18 { + compatible = "khadas,mcu"; + reg = <0x18>; + #cooling-cells = <2>; + }; + }; -- GitLab From 6c27219e34911601955b72c754adfc11c527ba7b Mon Sep 17 00:00:00 2001 From: Neil Armstrong Date: Mon, 8 Jun 2020 11:17:36 +0200 Subject: [PATCH 0035/2249] mfd: Add support for the Khadas System control Microcontroller This Microcontroller is present on the Khadas VIM1, VIM2, VIM3 and Edge boards. It has multiple boot control features like password check, power-on options, power-off control and system FAN control on recent boards. This implements a very basic MFD driver with the fan control and User NVMEM cells. Signed-off-by: Neil Armstrong Signed-off-by: Lee Jones --- drivers/mfd/Kconfig | 21 +++++ drivers/mfd/Makefile | 1 + drivers/mfd/khadas-mcu.c | 142 +++++++++++++++++++++++++++++++++ include/linux/mfd/khadas-mcu.h | 91 +++++++++++++++++++++ 4 files changed, 255 insertions(+) create mode 100644 drivers/mfd/khadas-mcu.c create mode 100644 include/linux/mfd/khadas-mcu.h diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index a37d7d1713820..d13bb0abfd6f9 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -2053,6 +2053,27 @@ config MFD_WCD934X This driver provides common support WCD934x audio codec and its associated Pin Controller, Soundwire Controller and Audio codec. +config MFD_KHADAS_MCU + tristate "Support for Khadas System control Microcontroller" + depends on I2C + depends on ARCH_MESON || ARCH_ROCKCHIP || COMPILE_TEST + select MFD_CORE + select REGMAP_I2C + help + Support for the Khadas System control Microcontroller interface + present on their VIM and Edge boards. + + This Microcontroller is present on the Khadas VIM1, VIM2, VIM3 and + Edge boards. + + It provides multiple boot control features like password check, + power-on options, power-off control and system FAN control on recent + boards. + + This driver provides common support for accessing the device, + additional drivers must be enabled in order to use the functionality + of the device. + menu "Multimedia Capabilities Port drivers" depends on ARCH_SA1100 diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile index 9367a92f795a6..1c8d6be3347d6 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile @@ -262,5 +262,6 @@ obj-$(CONFIG_MFD_ROHM_BD70528) += rohm-bd70528.o obj-$(CONFIG_MFD_ROHM_BD71828) += rohm-bd71828.o obj-$(CONFIG_MFD_ROHM_BD718XX) += rohm-bd718x7.o obj-$(CONFIG_MFD_STMFX) += stmfx.o +obj-$(CONFIG_MFD_KHADAS_MCU) += khadas-mcu.o obj-$(CONFIG_SGI_MFD_IOC3) += ioc3.o diff --git a/drivers/mfd/khadas-mcu.c b/drivers/mfd/khadas-mcu.c new file mode 100644 index 0000000000000..44d5bb462daba --- /dev/null +++ b/drivers/mfd/khadas-mcu.c @@ -0,0 +1,142 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Driver for Khadas System control Microcontroller + * + * Copyright (C) 2020 BayLibre SAS + * + * Author(s): Neil Armstrong + */ +#include +#include +#include +#include +#include +#include + +static bool khadas_mcu_reg_volatile(struct device *dev, unsigned int reg) +{ + if (reg >= KHADAS_MCU_USER_DATA_0_REG && + reg < KHADAS_MCU_PWR_OFF_CMD_REG) + return true; + + switch (reg) { + case KHADAS_MCU_PWR_OFF_CMD_REG: + case KHADAS_MCU_PASSWD_START_REG: + case KHADAS_MCU_CHECK_VEN_PASSWD_REG: + case KHADAS_MCU_CHECK_USER_PASSWD_REG: + case KHADAS_MCU_WOL_INIT_START_REG: + case KHADAS_MCU_CMD_FAN_STATUS_CTRL_REG: + return true; + default: + return false; + } +} + +static bool khadas_mcu_reg_writeable(struct device *dev, unsigned int reg) +{ + switch (reg) { + case KHADAS_MCU_PASSWD_VEN_0_REG: + case KHADAS_MCU_PASSWD_VEN_1_REG: + case KHADAS_MCU_PASSWD_VEN_2_REG: + case KHADAS_MCU_PASSWD_VEN_3_REG: + case KHADAS_MCU_PASSWD_VEN_4_REG: + case KHADAS_MCU_PASSWD_VEN_5_REG: + case KHADAS_MCU_MAC_0_REG: + case KHADAS_MCU_MAC_1_REG: + case KHADAS_MCU_MAC_2_REG: + case KHADAS_MCU_MAC_3_REG: + case KHADAS_MCU_MAC_4_REG: + case KHADAS_MCU_MAC_5_REG: + case KHADAS_MCU_USID_0_REG: + case KHADAS_MCU_USID_1_REG: + case KHADAS_MCU_USID_2_REG: + case KHADAS_MCU_USID_3_REG: + case KHADAS_MCU_USID_4_REG: + case KHADAS_MCU_USID_5_REG: + case KHADAS_MCU_VERSION_0_REG: + case KHADAS_MCU_VERSION_1_REG: + case KHADAS_MCU_DEVICE_NO_0_REG: + case KHADAS_MCU_DEVICE_NO_1_REG: + case KHADAS_MCU_FACTORY_TEST_REG: + case KHADAS_MCU_SHUTDOWN_NORMAL_STATUS_REG: + return false; + default: + return true; + } +} + +static const struct regmap_config khadas_mcu_regmap_config = { + .reg_bits = 8, + .reg_stride = 1, + .val_bits = 8, + .max_register = KHADAS_MCU_CMD_FAN_STATUS_CTRL_REG, + .volatile_reg = khadas_mcu_reg_volatile, + .writeable_reg = khadas_mcu_reg_writeable, + .cache_type = REGCACHE_RBTREE, +}; + +static struct mfd_cell khadas_mcu_fan_cells[] = { + /* VIM1/2 Rev13+ and VIM3 only */ + { .name = "khadas-mcu-fan-ctrl", }, +}; + +static struct mfd_cell khadas_mcu_cells[] = { + { .name = "khadas-mcu-user-mem", }, +}; + +static int khadas_mcu_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct device *dev = &client->dev; + struct khadas_mcu *ddata; + int ret; + + ddata = devm_kzalloc(dev, sizeof(*ddata), GFP_KERNEL); + if (!ddata) + return -ENOMEM; + + i2c_set_clientdata(client, ddata); + + ddata->dev = dev; + + ddata->regmap = devm_regmap_init_i2c(client, &khadas_mcu_regmap_config); + if (IS_ERR(ddata->regmap)) { + ret = PTR_ERR(ddata->regmap); + dev_err(dev, "Failed to allocate register map: %d\n", ret); + return ret; + } + + ret = devm_mfd_add_devices(dev, PLATFORM_DEVID_NONE, + khadas_mcu_cells, + ARRAY_SIZE(khadas_mcu_cells), + NULL, 0, NULL); + if (ret) + return ret; + + if (of_find_property(dev->of_node, "#cooling-cells", NULL)) + return devm_mfd_add_devices(dev, PLATFORM_DEVID_NONE, + khadas_mcu_fan_cells, + ARRAY_SIZE(khadas_mcu_fan_cells), + NULL, 0, NULL); + + return 0; +} + +static const struct of_device_id khadas_mcu_of_match[] = { + { .compatible = "khadas,mcu", }, + {}, +}; +MODULE_DEVICE_TABLE(of, khadas_mcu_of_match); + +static struct i2c_driver khadas_mcu_driver = { + .driver = { + .name = "khadas-mcu-core", + .of_match_table = of_match_ptr(khadas_mcu_of_match), + }, + .probe = khadas_mcu_probe, +}; +module_i2c_driver(khadas_mcu_driver); + +MODULE_DESCRIPTION("Khadas MCU core driver"); +MODULE_AUTHOR("Neil Armstrong "); +MODULE_LICENSE("GPL v2"); diff --git a/include/linux/mfd/khadas-mcu.h b/include/linux/mfd/khadas-mcu.h new file mode 100644 index 0000000000000..a99ba2ed0e4e0 --- /dev/null +++ b/include/linux/mfd/khadas-mcu.h @@ -0,0 +1,91 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Khadas System control Microcontroller Register map + * + * Copyright (C) 2020 BayLibre SAS + * + * Author(s): Neil Armstrong + */ + +#ifndef MFD_KHADAS_MCU_H +#define MFD_KHADAS_MCU_H + +#define KHADAS_MCU_PASSWD_VEN_0_REG 0x00 /* RO */ +#define KHADAS_MCU_PASSWD_VEN_1_REG 0x01 /* RO */ +#define KHADAS_MCU_PASSWD_VEN_2_REG 0x02 /* RO */ +#define KHADAS_MCU_PASSWD_VEN_3_REG 0x03 /* RO */ +#define KHADAS_MCU_PASSWD_VEN_4_REG 0x04 /* RO */ +#define KHADAS_MCU_PASSWD_VEN_5_REG 0x05 /* RO */ +#define KHADAS_MCU_MAC_0_REG 0x06 /* RO */ +#define KHADAS_MCU_MAC_1_REG 0x07 /* RO */ +#define KHADAS_MCU_MAC_2_REG 0x08 /* RO */ +#define KHADAS_MCU_MAC_3_REG 0x09 /* RO */ +#define KHADAS_MCU_MAC_4_REG 0x0a /* RO */ +#define KHADAS_MCU_MAC_5_REG 0x0b /* RO */ +#define KHADAS_MCU_USID_0_REG 0x0c /* RO */ +#define KHADAS_MCU_USID_1_REG 0x0d /* RO */ +#define KHADAS_MCU_USID_2_REG 0x0e /* RO */ +#define KHADAS_MCU_USID_3_REG 0x0f /* RO */ +#define KHADAS_MCU_USID_4_REG 0x10 /* RO */ +#define KHADAS_MCU_USID_5_REG 0x11 /* RO */ +#define KHADAS_MCU_VERSION_0_REG 0x12 /* RO */ +#define KHADAS_MCU_VERSION_1_REG 0x13 /* RO */ +#define KHADAS_MCU_DEVICE_NO_0_REG 0x14 /* RO */ +#define KHADAS_MCU_DEVICE_NO_1_REG 0x15 /* RO */ +#define KHADAS_MCU_FACTORY_TEST_REG 0x16 /* R */ +#define KHADAS_MCU_BOOT_MODE_REG 0x20 /* RW */ +#define KHADAS_MCU_BOOT_EN_WOL_REG 0x21 /* RW */ +#define KHADAS_MCU_BOOT_EN_RTC_REG 0x22 /* RW */ +#define KHADAS_MCU_BOOT_EN_EXP_REG 0x23 /* RW */ +#define KHADAS_MCU_BOOT_EN_IR_REG 0x24 /* RW */ +#define KHADAS_MCU_BOOT_EN_DCIN_REG 0x25 /* RW */ +#define KHADAS_MCU_BOOT_EN_KEY_REG 0x26 /* RW */ +#define KHADAS_MCU_KEY_MODE_REG 0x27 /* RW */ +#define KHADAS_MCU_LED_MODE_ON_REG 0x28 /* RW */ +#define KHADAS_MCU_LED_MODE_OFF_REG 0x29 /* RW */ +#define KHADAS_MCU_SHUTDOWN_NORMAL_REG 0x2c /* RW */ +#define KHADAS_MCU_MAC_SWITCH_REG 0x2d /* RW */ +#define KHADAS_MCU_MCU_SLEEP_MODE_REG 0x2e /* RW */ +#define KHADAS_MCU_IR_CODE1_0_REG 0x2f /* RW */ +#define KHADAS_MCU_IR_CODE1_1_REG 0x30 /* RW */ +#define KHADAS_MCU_IR_CODE1_2_REG 0x31 /* RW */ +#define KHADAS_MCU_IR_CODE1_3_REG 0x32 /* RW */ +#define KHADAS_MCU_USB_PCIE_SWITCH_REG 0x33 /* RW */ +#define KHADAS_MCU_IR_CODE2_0_REG 0x34 /* RW */ +#define KHADAS_MCU_IR_CODE2_1_REG 0x35 /* RW */ +#define KHADAS_MCU_IR_CODE2_2_REG 0x36 /* RW */ +#define KHADAS_MCU_IR_CODE2_3_REG 0x37 /* RW */ +#define KHADAS_MCU_PASSWD_USER_0_REG 0x40 /* RW */ +#define KHADAS_MCU_PASSWD_USER_1_REG 0x41 /* RW */ +#define KHADAS_MCU_PASSWD_USER_2_REG 0x42 /* RW */ +#define KHADAS_MCU_PASSWD_USER_3_REG 0x43 /* RW */ +#define KHADAS_MCU_PASSWD_USER_4_REG 0x44 /* RW */ +#define KHADAS_MCU_PASSWD_USER_5_REG 0x45 /* RW */ +#define KHADAS_MCU_USER_DATA_0_REG 0x46 /* RW 56 bytes */ +#define KHADAS_MCU_PWR_OFF_CMD_REG 0x80 /* WO */ +#define KHADAS_MCU_PASSWD_START_REG 0x81 /* WO */ +#define KHADAS_MCU_CHECK_VEN_PASSWD_REG 0x82 /* WO */ +#define KHADAS_MCU_CHECK_USER_PASSWD_REG 0x83 /* WO */ +#define KHADAS_MCU_SHUTDOWN_NORMAL_STATUS_REG 0x86 /* RO */ +#define KHADAS_MCU_WOL_INIT_START_REG 0x87 /* WO */ +#define KHADAS_MCU_CMD_FAN_STATUS_CTRL_REG 0x88 /* WO */ + +enum { + KHADAS_BOARD_VIM1 = 0x1, + KHADAS_BOARD_VIM2, + KHADAS_BOARD_VIM3, + KHADAS_BOARD_EDGE = 0x11, + KHADAS_BOARD_EDGE_V, +}; + +/** + * struct khadas_mcu - Khadas MCU structure + * @device: device reference used for logs + * @regmap: register map + */ +struct khadas_mcu { + struct device *dev; + struct regmap *regmap; +}; + +#endif /* MFD_KHADAS_MCU_H */ -- GitLab From 99bbe307013059951368d12f5454d34568de4850 Mon Sep 17 00:00:00 2001 From: Jaegeuk Kim Date: Tue, 16 Jun 2020 09:56:51 -0700 Subject: [PATCH 0036/2249] f2fs: avoid checkpatch error ERROR:INITIALISED_STATIC: do not initialise statics to NULL Reviewed-by: Chao Yu Signed-off-by: Jaegeuk Kim --- fs/f2fs/compress.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/f2fs/compress.c b/fs/f2fs/compress.c index 1e02a8c106b0a..4dca9e4567348 100644 --- a/fs/f2fs/compress.c +++ b/fs/f2fs/compress.c @@ -506,7 +506,7 @@ bool f2fs_is_compress_backend_ready(struct inode *inode) return f2fs_cops[F2FS_I(inode)->i_compress_algorithm]; } -static mempool_t *compress_page_pool = NULL; +static mempool_t *compress_page_pool; static int num_compress_pages = 512; module_param(num_compress_pages, uint, 0444); MODULE_PARM_DESC(num_compress_pages, -- GitLab From 742532d11d8328231d099f557e6287e75b2d247b Mon Sep 17 00:00:00 2001 From: Denis Efremov Date: Wed, 10 Jun 2020 01:14:46 +0300 Subject: [PATCH 0037/2249] f2fs: use kfree() instead of kvfree() to free superblock data Use kfree() instead of kvfree() to free super in read_raw_super_block() because the memory is allocated with kzalloc() in the function. Use kfree() instead of kvfree() to free sbi, raw_super in f2fs_fill_super() and f2fs_put_super() because the memory is allocated with kzalloc(). Signed-off-by: Denis Efremov Reviewed-by: Chao Yu Signed-off-by: Jaegeuk Kim --- fs/f2fs/super.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c index 20e56b0fa46a9..426cebdd84e5d 100644 --- a/fs/f2fs/super.c +++ b/fs/f2fs/super.c @@ -1243,7 +1243,7 @@ static void f2fs_put_super(struct super_block *sb) sb->s_fs_info = NULL; if (sbi->s_chksum_driver) crypto_free_shash(sbi->s_chksum_driver); - kvfree(sbi->raw_super); + kfree(sbi->raw_super); destroy_device_list(sbi); f2fs_destroy_xattr_caches(sbi); @@ -1259,7 +1259,7 @@ static void f2fs_put_super(struct super_block *sb) #ifdef CONFIG_UNICODE utf8_unload(sbi->s_encoding); #endif - kvfree(sbi); + kfree(sbi); } int f2fs_sync_fs(struct super_block *sb, int sync) @@ -3137,7 +3137,7 @@ static int read_raw_super_block(struct f2fs_sb_info *sbi, /* No valid superblock */ if (!*raw_super) - kvfree(super); + kfree(super); else err = 0; @@ -3816,11 +3816,11 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent) fscrypt_free_dummy_context(&F2FS_OPTION(sbi).dummy_enc_ctx); kvfree(options); free_sb_buf: - kvfree(raw_super); + kfree(raw_super); free_sbi: if (sbi->s_chksum_driver) crypto_free_shash(sbi->s_chksum_driver); - kvfree(sbi); + kfree(sbi); /* give only one another chance */ if (retry_cnt > 0 && skip_recovery) { -- GitLab From 6f6489288ed196a962ef8d33b1b9cf6369ff0807 Mon Sep 17 00:00:00 2001 From: Wei Fang Date: Mon, 15 Jun 2020 16:11:38 +0800 Subject: [PATCH 0038/2249] f2fs: remove useless truncate in f2fs_collapse_range() Since offset < new_size, no need to do truncate_pagecache() again with new_size. Signed-off-by: Wei Fang Reviewed-by: Chao Yu Signed-off-by: Jaegeuk Kim --- fs/f2fs/file.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c index 3268f8dd59bba..98721f9bef253 100644 --- a/fs/f2fs/file.c +++ b/fs/f2fs/file.c @@ -1373,8 +1373,6 @@ static int f2fs_collapse_range(struct inode *inode, loff_t offset, loff_t len) truncate_pagecache(inode, offset); new_size = i_size_read(inode) - len; - truncate_pagecache(inode, new_size); - ret = f2fs_truncate_blocks(inode, new_size, true); up_write(&F2FS_I(inode)->i_mmap_sem); if (!ret) -- GitLab From db5ae363292705d52c5b653d5079a07a6417ef4c Mon Sep 17 00:00:00 2001 From: Wuyun Zhao Date: Thu, 18 Jun 2020 10:58:37 +0800 Subject: [PATCH 0039/2249] f2fs: fix a race condition between f2fs_write_end_io and f2fs_del_fsync_node_entry Under some condition, the __write_node_page will submit a page which is not f2fs_in_warm_node_list and will not call f2fs_add_fsync_node_entry. f2fs_gc continue to run to invoke f2fs_iget -> do_read_inode to read the same node page and set code node, which make f2fs_in_warm_node_list become true, that will cause f2fs_bug_on in f2fs_del_fsync_node_entry when f2fs_write_end_io called. - f2fs_write_end_io - f2fs_iget - do_read_inode - set_cold_node recover cold node flag - f2fs_in_warm_node_list - is_cold_node if node is cold, assume we have added node to fsync_node_list during writepages() - f2fs_del_fsync_node_entry - f2fs_bug_on() due to node page is not in fsync_node_list [ 34.966133] Call trace: [ 34.969902] f2fs_del_fsync_node_entry+0x100/0x108 [ 34.976071] f2fs_write_end_io+0x1e0/0x288 [ 34.981539] bio_endio+0x248/0x270 [ 34.986289] blk_update_request+0x2b0/0x4d8 [ 34.991841] scsi_end_request+0x40/0x440 [ 34.997126] scsi_io_completion+0xa4/0x748 [ 35.002593] scsi_finish_command+0xdc/0x110 [ 35.008143] scsi_softirq_done+0x118/0x150 [ 35.013610] blk_done_softirq+0x8c/0xe8 [ 35.018811] __do_softirq+0x2e8/0x578 [ 35.023828] irq_exit+0xfc/0x120 [ 35.028398] handle_IPI+0x1d8/0x330 [ 35.033233] gic_handle_irq+0x110/0x1d4 [ 35.038433] el1_irq+0xb4/0x130 [ 35.042917] kmem_cache_alloc+0x3f0/0x418 [ 35.048288] radix_tree_node_alloc+0x50/0xf8 [ 35.053933] __radix_tree_create+0xf8/0x188 [ 35.059484] __radix_tree_insert+0x3c/0x128 [ 35.065035] add_gc_inode+0x90/0x118 [ 35.069967] f2fs_gc+0x1b80/0x2d70 [ 35.074718] f2fs_disable_checkpoint+0x94/0x1d0 [ 35.080621] f2fs_fill_super+0x10c4/0x1b88 [ 35.086088] mount_bdev+0x194/0x1e0 [ 35.090923] f2fs_mount+0x40/0x50 [ 35.095589] mount_fs+0xb4/0x190 [ 35.100159] vfs_kern_mount+0x80/0x1d8 [ 35.105260] do_mount+0x478/0xf18 [ 35.109926] ksys_mount+0x90/0xd0 [ 35.114592] __arm64_sys_mount+0x24/0x38 Signed-off-by: Wuyun Zhao Reviewed-by: Chao Yu Signed-off-by: Jaegeuk Kim --- fs/f2fs/inode.c | 1 + 1 file changed, 1 insertion(+) diff --git a/fs/f2fs/inode.c b/fs/f2fs/inode.c index 44582a4db513e..33affa788588f 100644 --- a/fs/f2fs/inode.c +++ b/fs/f2fs/inode.c @@ -402,6 +402,7 @@ static int do_read_inode(struct inode *inode) /* try to recover cold bit for non-dir inode */ if (!S_ISDIR(inode->i_mode) && !is_cold_node(node_page)) { + f2fs_wait_on_page_writeback(node_page, NODE, true, true); set_cold_node(node_page, false); set_page_dirty(node_page); } -- GitLab From da52f8ade40b032eb8111a0fd514c8ac5f8f0f1b Mon Sep 17 00:00:00 2001 From: Jack Qiu Date: Thu, 18 Jun 2020 12:37:10 +0800 Subject: [PATCH 0040/2249] f2fs: get the right gc victim section when section has several segments Assume each section has 4 segment: .___________________________. |_Segment0_|_..._|_Segment3_| . . . . .__________. |_section0_| Segment 0~2 has 0 valid block, segment 3 has 512 valid blocks. It will fail if we want to gc section0 in this scenes, because all 4 segments in section0 is not dirty. So we should use dirty section bitmap instead of dirty segment bitmap to get right victim section. Signed-off-by: Jack Qiu Reviewed-by: Chao Yu Signed-off-by: Jaegeuk Kim --- fs/f2fs/gc.c | 41 ++++++++++++++++++------------- fs/f2fs/segment.c | 61 +++++++++++++++++++++++++++++++++++++++++++++-- fs/f2fs/segment.h | 8 +++++-- 3 files changed, 89 insertions(+), 21 deletions(-) diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c index 5b95d5a146eb6..9b6fc61ce6493 100644 --- a/fs/f2fs/gc.c +++ b/fs/f2fs/gc.c @@ -21,6 +21,9 @@ #include "gc.h" #include +static unsigned int count_bits(const unsigned long *addr, + unsigned int offset, unsigned int len); + static int gc_thread_func(void *data) { struct f2fs_sb_info *sbi = data; @@ -187,14 +190,20 @@ static void select_policy(struct f2fs_sb_info *sbi, int gc_type, if (p->alloc_mode == SSR) { p->gc_mode = GC_GREEDY; - p->dirty_segmap = dirty_i->dirty_segmap[type]; + p->dirty_bitmap = dirty_i->dirty_segmap[type]; p->max_search = dirty_i->nr_dirty[type]; p->ofs_unit = 1; } else { p->gc_mode = select_gc_type(sbi, gc_type); - p->dirty_segmap = dirty_i->dirty_segmap[DIRTY]; - p->max_search = dirty_i->nr_dirty[DIRTY]; p->ofs_unit = sbi->segs_per_sec; + if (__is_large_section(sbi)) { + p->dirty_bitmap = dirty_i->dirty_secmap; + p->max_search = count_bits(p->dirty_bitmap, + 0, MAIN_SECS(sbi)); + } else { + p->dirty_bitmap = dirty_i->dirty_segmap[DIRTY]; + p->max_search = dirty_i->nr_dirty[DIRTY]; + } } /* @@ -365,10 +374,14 @@ static int get_victim_by_default(struct f2fs_sb_info *sbi, } while (1) { - unsigned long cost; - unsigned int segno; - - segno = find_next_bit(p.dirty_segmap, last_segment, p.offset); + unsigned long cost, *dirty_bitmap; + unsigned int unit_no, segno; + + dirty_bitmap = p.dirty_bitmap; + unit_no = find_next_bit(dirty_bitmap, + last_segment / p.ofs_unit, + p.offset / p.ofs_unit); + segno = unit_no * p.ofs_unit; if (segno >= last_segment) { if (sm->last_victim[p.gc_mode]) { last_segment = @@ -381,14 +394,7 @@ static int get_victim_by_default(struct f2fs_sb_info *sbi, } p.offset = segno + p.ofs_unit; - if (p.ofs_unit > 1) { - p.offset -= segno % p.ofs_unit; - nsearched += count_bits(p.dirty_segmap, - p.offset - p.ofs_unit, - p.ofs_unit); - } else { - nsearched++; - } + nsearched++; #ifdef CONFIG_F2FS_CHECK_FS /* @@ -421,9 +427,10 @@ static int get_victim_by_default(struct f2fs_sb_info *sbi, next: if (nsearched >= p.max_search) { if (!sm->last_victim[p.gc_mode] && segno <= last_victim) - sm->last_victim[p.gc_mode] = last_victim + 1; + sm->last_victim[p.gc_mode] = + last_victim + p.ofs_unit; else - sm->last_victim[p.gc_mode] = segno + 1; + sm->last_victim[p.gc_mode] = segno + p.ofs_unit; sm->last_victim[p.gc_mode] %= (MAIN_SECS(sbi) * sbi->segs_per_sec); break; diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c index 196f315035118..66eeaba30e918 100644 --- a/fs/f2fs/segment.c +++ b/fs/f2fs/segment.c @@ -796,6 +796,18 @@ static void __locate_dirty_segment(struct f2fs_sb_info *sbi, unsigned int segno, } if (!test_and_set_bit(segno, dirty_i->dirty_segmap[t])) dirty_i->nr_dirty[t]++; + + if (__is_large_section(sbi)) { + unsigned int secno = GET_SEC_FROM_SEG(sbi, segno); + unsigned short valid_blocks = + get_valid_blocks(sbi, segno, true); + + f2fs_bug_on(sbi, unlikely(!valid_blocks || + valid_blocks == BLKS_PER_SEC(sbi))); + + if (!IS_CURSEC(sbi, secno)) + set_bit(secno, dirty_i->dirty_secmap); + } } } @@ -803,6 +815,7 @@ static void __remove_dirty_segment(struct f2fs_sb_info *sbi, unsigned int segno, enum dirty_type dirty_type) { struct dirty_seglist_info *dirty_i = DIRTY_I(sbi); + unsigned short valid_blocks; if (test_and_clear_bit(segno, dirty_i->dirty_segmap[dirty_type])) dirty_i->nr_dirty[dirty_type]--; @@ -814,13 +827,26 @@ static void __remove_dirty_segment(struct f2fs_sb_info *sbi, unsigned int segno, if (test_and_clear_bit(segno, dirty_i->dirty_segmap[t])) dirty_i->nr_dirty[t]--; - if (get_valid_blocks(sbi, segno, true) == 0) { + valid_blocks = get_valid_blocks(sbi, segno, true); + if (valid_blocks == 0) { clear_bit(GET_SEC_FROM_SEG(sbi, segno), dirty_i->victim_secmap); #ifdef CONFIG_F2FS_CHECK_FS clear_bit(segno, SIT_I(sbi)->invalid_segmap); #endif } + if (__is_large_section(sbi)) { + unsigned int secno = GET_SEC_FROM_SEG(sbi, segno); + + if (!valid_blocks || + valid_blocks == BLKS_PER_SEC(sbi)) { + clear_bit(secno, dirty_i->dirty_secmap); + return; + } + + if (!IS_CURSEC(sbi, secno)) + set_bit(secno, dirty_i->dirty_secmap); + } } } @@ -4293,8 +4319,9 @@ static void init_dirty_segmap(struct f2fs_sb_info *sbi) { struct dirty_seglist_info *dirty_i = DIRTY_I(sbi); struct free_segmap_info *free_i = FREE_I(sbi); - unsigned int segno = 0, offset = 0; + unsigned int segno = 0, offset = 0, secno; unsigned short valid_blocks; + unsigned short blks_per_sec = BLKS_PER_SEC(sbi); while (1) { /* find dirty segment based on free segmap */ @@ -4313,6 +4340,22 @@ static void init_dirty_segmap(struct f2fs_sb_info *sbi) __locate_dirty_segment(sbi, segno, DIRTY); mutex_unlock(&dirty_i->seglist_lock); } + + if (!__is_large_section(sbi)) + return; + + mutex_lock(&dirty_i->seglist_lock); + for (segno = 0; segno < MAIN_SECS(sbi); segno += blks_per_sec) { + valid_blocks = get_valid_blocks(sbi, segno, true); + secno = GET_SEC_FROM_SEG(sbi, segno); + + if (!valid_blocks || valid_blocks == blks_per_sec) + continue; + if (IS_CURSEC(sbi, secno)) + continue; + set_bit(secno, dirty_i->dirty_secmap); + } + mutex_unlock(&dirty_i->seglist_lock); } static int init_victim_secmap(struct f2fs_sb_info *sbi) @@ -4349,6 +4392,14 @@ static int build_dirty_segmap(struct f2fs_sb_info *sbi) return -ENOMEM; } + if (__is_large_section(sbi)) { + bitmap_size = f2fs_bitmap_size(MAIN_SECS(sbi)); + dirty_i->dirty_secmap = f2fs_kvzalloc(sbi, + bitmap_size, GFP_KERNEL); + if (!dirty_i->dirty_secmap) + return -ENOMEM; + } + init_dirty_segmap(sbi); return init_victim_secmap(sbi); } @@ -4775,6 +4826,12 @@ static void destroy_dirty_segmap(struct f2fs_sb_info *sbi) for (i = 0; i < NR_DIRTY_TYPE; i++) discard_dirty_segmap(sbi, i); + if (__is_large_section(sbi)) { + mutex_lock(&dirty_i->seglist_lock); + kvfree(dirty_i->dirty_secmap); + mutex_unlock(&dirty_i->seglist_lock); + } + destroy_victim_secmap(sbi); SM_I(sbi)->dirty_info = NULL; kvfree(dirty_i); diff --git a/fs/f2fs/segment.h b/fs/f2fs/segment.h index cba16cca51895..f261e3e6a69bc 100644 --- a/fs/f2fs/segment.h +++ b/fs/f2fs/segment.h @@ -166,8 +166,11 @@ enum { struct victim_sel_policy { int alloc_mode; /* LFS or SSR */ int gc_mode; /* GC_CB or GC_GREEDY */ - unsigned long *dirty_segmap; /* dirty segment bitmap */ - unsigned int max_search; /* maximum # of segments to search */ + unsigned long *dirty_bitmap; /* dirty segment/section bitmap */ + unsigned int max_search; /* + * maximum # of segments/sections + * to search + */ unsigned int offset; /* last scanned bitmap offset */ unsigned int ofs_unit; /* bitmap search unit */ unsigned int min_cost; /* minimum cost */ @@ -266,6 +269,7 @@ enum dirty_type { struct dirty_seglist_info { const struct victim_selection *v_ops; /* victim selction operation */ unsigned long *dirty_segmap[NR_DIRTY_TYPE]; + unsigned long *dirty_secmap; struct mutex seglist_lock; /* lock for segment bitmaps */ int nr_dirty[NR_DIRTY_TYPE]; /* # of dirty segments */ unsigned long *victim_secmap; /* background GC victims */ -- GitLab From ba87a45c23d645b25e1265b477e83cc1b73086e4 Mon Sep 17 00:00:00 2001 From: Wang Xiaojun Date: Wed, 17 Jun 2020 20:30:12 +0800 Subject: [PATCH 0041/2249] f2fs: use kfree() to free variables allocated by match_strdup() Use kfree() instead of kvfree() to free variables allocated by match_strdup(). Because the memory is allocated with kmalloc inside match_strdup(). Signed-off-by: Wang Xiaojun Reviewed-by: Chao Yu Signed-off-by: Jaegeuk Kim --- fs/f2fs/super.c | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c index 426cebdd84e5d..7326522057378 100644 --- a/fs/f2fs/super.c +++ b/fs/f2fs/super.c @@ -348,7 +348,7 @@ static int f2fs_set_qf_name(struct super_block *sb, int qtype, set_opt(sbi, QUOTA); return 0; errout: - kvfree(qname); + kfree(qname); return ret; } @@ -360,7 +360,7 @@ static int f2fs_clear_qf_name(struct super_block *sb, int qtype) f2fs_err(sbi, "Cannot change journaled quota options when quota turned on"); return -EINVAL; } - kvfree(F2FS_OPTION(sbi).s_qf_names[qtype]); + kfree(F2FS_OPTION(sbi).s_qf_names[qtype]); F2FS_OPTION(sbi).s_qf_names[qtype] = NULL; return 0; } @@ -494,10 +494,10 @@ static int parse_options(struct super_block *sb, char *options, bool is_remount) } else if (!strcmp(name, "sync")) { F2FS_OPTION(sbi).bggc_mode = BGGC_MODE_SYNC; } else { - kvfree(name); + kfree(name); return -EINVAL; } - kvfree(name); + kfree(name); break; case Opt_disable_roll_forward: set_opt(sbi, DISABLE_ROLL_FORWARD); @@ -654,17 +654,17 @@ static int parse_options(struct super_block *sb, char *options, bool is_remount) if (!strcmp(name, "adaptive")) { if (f2fs_sb_has_blkzoned(sbi)) { f2fs_warn(sbi, "adaptive mode is not allowed with zoned block device feature"); - kvfree(name); + kfree(name); return -EINVAL; } F2FS_OPTION(sbi).fs_mode = FS_MODE_ADAPTIVE; } else if (!strcmp(name, "lfs")) { F2FS_OPTION(sbi).fs_mode = FS_MODE_LFS; } else { - kvfree(name); + kfree(name); return -EINVAL; } - kvfree(name); + kfree(name); break; case Opt_io_size_bits: if (args->from && match_int(args, &arg)) @@ -790,10 +790,10 @@ static int parse_options(struct super_block *sb, char *options, bool is_remount) } else if (!strcmp(name, "fs-based")) { F2FS_OPTION(sbi).whint_mode = WHINT_MODE_FS; } else { - kvfree(name); + kfree(name); return -EINVAL; } - kvfree(name); + kfree(name); break; case Opt_alloc: name = match_strdup(&args[0]); @@ -805,10 +805,10 @@ static int parse_options(struct super_block *sb, char *options, bool is_remount) } else if (!strcmp(name, "reuse")) { F2FS_OPTION(sbi).alloc_mode = ALLOC_MODE_REUSE; } else { - kvfree(name); + kfree(name); return -EINVAL; } - kvfree(name); + kfree(name); break; case Opt_fsync: name = match_strdup(&args[0]); @@ -822,10 +822,10 @@ static int parse_options(struct super_block *sb, char *options, bool is_remount) F2FS_OPTION(sbi).fsync_mode = FSYNC_MODE_NOBARRIER; } else { - kvfree(name); + kfree(name); return -EINVAL; } - kvfree(name); + kfree(name); break; case Opt_test_dummy_encryption: ret = f2fs_set_test_dummy_encryption(sb, p, &args[0], @@ -1250,7 +1250,7 @@ static void f2fs_put_super(struct super_block *sb) mempool_destroy(sbi->write_io_dummy); #ifdef CONFIG_QUOTA for (i = 0; i < MAXQUOTAS; i++) - kvfree(F2FS_OPTION(sbi).s_qf_names[i]); + kfree(F2FS_OPTION(sbi).s_qf_names[i]); #endif fscrypt_free_dummy_context(&F2FS_OPTION(sbi).dummy_enc_ctx); destroy_percpu_info(sbi); @@ -1754,7 +1754,7 @@ static int f2fs_remount(struct super_block *sb, int *flags, char *data) GFP_KERNEL); if (!org_mount_opt.s_qf_names[i]) { for (j = 0; j < i; j++) - kvfree(org_mount_opt.s_qf_names[j]); + kfree(org_mount_opt.s_qf_names[j]); return -ENOMEM; } } else { @@ -1879,7 +1879,7 @@ static int f2fs_remount(struct super_block *sb, int *flags, char *data) #ifdef CONFIG_QUOTA /* Release old quota file names */ for (i = 0; i < MAXQUOTAS; i++) - kvfree(org_mount_opt.s_qf_names[i]); + kfree(org_mount_opt.s_qf_names[i]); #endif /* Update the POSIXACL Flag */ sb->s_flags = (sb->s_flags & ~SB_POSIXACL) | @@ -1900,7 +1900,7 @@ static int f2fs_remount(struct super_block *sb, int *flags, char *data) #ifdef CONFIG_QUOTA F2FS_OPTION(sbi).s_jquota_fmt = org_mount_opt.s_jquota_fmt; for (i = 0; i < MAXQUOTAS; i++) { - kvfree(F2FS_OPTION(sbi).s_qf_names[i]); + kfree(F2FS_OPTION(sbi).s_qf_names[i]); F2FS_OPTION(sbi).s_qf_names[i] = org_mount_opt.s_qf_names[i]; } #endif @@ -3811,7 +3811,7 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent) free_options: #ifdef CONFIG_QUOTA for (i = 0; i < MAXQUOTAS; i++) - kvfree(F2FS_OPTION(sbi).s_qf_names[i]); + kfree(F2FS_OPTION(sbi).s_qf_names[i]); #endif fscrypt_free_dummy_context(&F2FS_OPTION(sbi).dummy_enc_ctx); kvfree(options); -- GitLab From d378cdd0113878e3860f954d16dd3e91defb1492 Mon Sep 17 00:00:00 2001 From: Gwendal Grignou Date: Tue, 26 May 2020 11:53:28 -0700 Subject: [PATCH 0042/2249] platform/chrome: cros_ec_debugfs: Control uptime information request When EC does not support uptime command (EC_CMD_GET_UPTIME_INFO), do not create the uptime sysfs entry point. User space application will not probe the file needlessly. The EC console log will not contain EC_CMD_GET_UPTIME_INFO anymore. Signed-off-by: Gwendal Grignou Signed-off-by: Enric Balletbo i Serra --- drivers/platform/chrome/cros_ec_debugfs.c | 24 +++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/drivers/platform/chrome/cros_ec_debugfs.c b/drivers/platform/chrome/cros_ec_debugfs.c index ecfada00e6c51..272c89837d745 100644 --- a/drivers/platform/chrome/cros_ec_debugfs.c +++ b/drivers/platform/chrome/cros_ec_debugfs.c @@ -242,6 +242,25 @@ static ssize_t cros_ec_pdinfo_read(struct file *file, read_buf, p - read_buf); } +static bool cros_ec_uptime_is_supported(struct cros_ec_device *ec_dev) +{ + struct { + struct cros_ec_command cmd; + struct ec_response_uptime_info resp; + } __packed msg = {}; + int ret; + + msg.cmd.command = EC_CMD_GET_UPTIME_INFO; + msg.cmd.insize = sizeof(msg.resp); + + ret = cros_ec_cmd_xfer_status(ec_dev, &msg.cmd); + if (ret == -EPROTO && msg.cmd.result == EC_RES_INVALID_COMMAND) + return false; + + /* Other errors maybe a transient error, do not rule about support. */ + return true; +} + static ssize_t cros_ec_uptime_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { @@ -444,8 +463,9 @@ static int cros_ec_debugfs_probe(struct platform_device *pd) debugfs_create_file("pdinfo", 0444, debug_info->dir, debug_info, &cros_ec_pdinfo_fops); - debugfs_create_file("uptime", 0444, debug_info->dir, debug_info, - &cros_ec_uptime_fops); + if (cros_ec_uptime_is_supported(ec->ec_dev)) + debugfs_create_file("uptime", 0444, debug_info->dir, debug_info, + &cros_ec_uptime_fops); debugfs_create_x32("last_resume_result", 0444, debug_info->dir, &ec->ec_dev->last_resume_result); -- GitLab From f28adb41dab4a2795fd959750df57adffd2bb0be Mon Sep 17 00:00:00 2001 From: Prashant Malani Date: Tue, 19 May 2020 14:46:04 -0700 Subject: [PATCH 0043/2249] platform/chrome: cros_ec_typec: Register Type C switches Register Type C mux and switch handles, when provided via firmware bindings. These will allow the cros-ec-typec driver, and also alternate mode drivers to configure connected Muxes correctly, according to PD information retrieved from the Chrome OS EC. Signed-off-by: Prashant Malani Reviewed-by: Heikki Krogerus Signed-off-by: Enric Balletbo i Serra --- drivers/platform/chrome/cros_ec_typec.c | 47 +++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/drivers/platform/chrome/cros_ec_typec.c b/drivers/platform/chrome/cros_ec_typec.c index 66b8d21092afb..6e79f917314bf 100644 --- a/drivers/platform/chrome/cros_ec_typec.c +++ b/drivers/platform/chrome/cros_ec_typec.c @@ -14,6 +14,8 @@ #include #include #include +#include +#include #define DRV_NAME "cros-ec-typec" @@ -25,6 +27,9 @@ struct cros_typec_port { struct typec_partner *partner; /* Port partner PD identity info. */ struct usb_pd_identity p_identity; + struct typec_switch *ori_sw; + struct typec_mux *mux; + struct usb_role_switch *role_sw; }; /* Platform-specific data for the Chrome OS EC Type C controller. */ @@ -84,6 +89,40 @@ static int cros_typec_parse_port_props(struct typec_capability *cap, return 0; } +static int cros_typec_get_switch_handles(struct cros_typec_port *port, + struct fwnode_handle *fwnode, + struct device *dev) +{ + port->mux = fwnode_typec_mux_get(fwnode, NULL); + if (IS_ERR(port->mux)) { + dev_dbg(dev, "Mux handle not found.\n"); + goto mux_err; + } + + port->ori_sw = fwnode_typec_switch_get(fwnode); + if (IS_ERR(port->ori_sw)) { + dev_dbg(dev, "Orientation switch handle not found.\n"); + goto ori_sw_err; + } + + port->role_sw = fwnode_usb_role_switch_get(fwnode); + if (IS_ERR(port->role_sw)) { + dev_dbg(dev, "USB role switch handle not found.\n"); + goto role_sw_err; + } + + return 0; + +role_sw_err: + usb_role_switch_put(port->role_sw); +ori_sw_err: + typec_switch_put(port->ori_sw); +mux_err: + typec_mux_put(port->mux); + + return -ENODEV; +} + static void cros_unregister_ports(struct cros_typec_data *typec) { int i; @@ -91,6 +130,9 @@ static void cros_unregister_ports(struct cros_typec_data *typec) for (i = 0; i < typec->num_ports; i++) { if (!typec->ports[i]) continue; + usb_role_switch_put(typec->ports[i]->role_sw); + typec_switch_put(typec->ports[i]->ori_sw); + typec_mux_put(typec->ports[i]->mux); typec_unregister_port(typec->ports[i]->port); } } @@ -153,6 +195,11 @@ static int cros_typec_init_ports(struct cros_typec_data *typec) ret = PTR_ERR(cros_port->port); goto unregister_ports; } + + ret = cros_typec_get_switch_handles(cros_port, fwnode, dev); + if (ret) + dev_dbg(dev, "No switch control for port %d\n", + port_num); } return 0; -- GitLab From e32b16c31339e37d3cdc814f2773b74c1dbf660c Mon Sep 17 00:00:00 2001 From: Prashant Malani Date: Thu, 28 May 2020 04:36:03 -0700 Subject: [PATCH 0044/2249] platform/chrome: cros_ec: Update mux state bits Sync the EC_CMD_USB_PD_MUX_INFO mux state bit fields with the Chrome EC code base. The newly added bit fields will be used for cros-ec-typec mux control. Signed-off-by: Prashant Malani Signed-off-by: Enric Balletbo i Serra --- include/linux/platform_data/cros_ec_commands.h | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/include/linux/platform_data/cros_ec_commands.h b/include/linux/platform_data/cros_ec_commands.h index 69210881ebac8..a7b0fc440c355 100644 --- a/include/linux/platform_data/cros_ec_commands.h +++ b/include/linux/platform_data/cros_ec_commands.h @@ -5207,11 +5207,15 @@ struct ec_params_usb_pd_mux_info { } __ec_align1; /* Flags representing mux state */ -#define USB_PD_MUX_USB_ENABLED BIT(0) /* USB connected */ -#define USB_PD_MUX_DP_ENABLED BIT(1) /* DP connected */ -#define USB_PD_MUX_POLARITY_INVERTED BIT(2) /* CC line Polarity inverted */ -#define USB_PD_MUX_HPD_IRQ BIT(3) /* HPD IRQ is asserted */ -#define USB_PD_MUX_HPD_LVL BIT(4) /* HPD level is asserted */ +#define USB_PD_MUX_NONE 0 /* Open switch */ +#define USB_PD_MUX_USB_ENABLED BIT(0) /* USB connected */ +#define USB_PD_MUX_DP_ENABLED BIT(1) /* DP connected */ +#define USB_PD_MUX_POLARITY_INVERTED BIT(2) /* CC line Polarity inverted */ +#define USB_PD_MUX_HPD_IRQ BIT(3) /* HPD IRQ is asserted */ +#define USB_PD_MUX_HPD_LVL BIT(4) /* HPD level is asserted */ +#define USB_PD_MUX_SAFE_MODE BIT(5) /* DP is in safe mode */ +#define USB_PD_MUX_TBT_COMPAT_ENABLED BIT(6) /* TBT compat enabled */ +#define USB_PD_MUX_USB4_ENABLED BIT(7) /* USB4 enabled */ struct ec_response_usb_pd_mux_info { uint8_t flags; /* USB_PD_MUX_*-encoded USB mux state */ -- GitLab From 2ee97377a0d459fb3c484e49fb471ac6add06441 Mon Sep 17 00:00:00 2001 From: Prashant Malani Date: Thu, 28 May 2020 04:36:05 -0700 Subject: [PATCH 0045/2249] platform/chrome: cros_ec_typec: Register PD CTRL cmd v2 Recognize EC_CMD_USB_PD_CONTROL command version 2. This is necessary in order to process Type C mux information (like DP alt mode pin configuration), which is needed by the Type C Connector class API to configure the Type C muxes correctly While we are here, rename the struct member storing this version number from cmd_ver to pd_ctrl_ver, which more accurately reflects what is being stored. Also, slightly change the logic for calling cros_typec_set_port_params_*(). Now, v0 is called when pd_ctrl_ver is 0, and v1 is called otherwise. Signed-off-by: Prashant Malani Reviewed-by: Heikki Krogerus Signed-off-by: Enric Balletbo i Serra --- drivers/platform/chrome/cros_ec_typec.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/drivers/platform/chrome/cros_ec_typec.c b/drivers/platform/chrome/cros_ec_typec.c index 6e79f917314bf..d69a88464cef0 100644 --- a/drivers/platform/chrome/cros_ec_typec.c +++ b/drivers/platform/chrome/cros_ec_typec.c @@ -37,7 +37,7 @@ struct cros_typec_data { struct device *dev; struct cros_ec_device *ec; int num_ports; - unsigned int cmd_ver; + unsigned int pd_ctrl_ver; /* Array of ports, indexed by port number. */ struct cros_typec_port *ports[EC_USB_PD_MAX_PORTS]; struct notifier_block nb; @@ -340,7 +340,7 @@ static int cros_typec_port_update(struct cros_typec_data *typec, int port_num) req.mux = USB_PD_CTRL_MUX_NO_CHANGE; req.swap = USB_PD_CTRL_SWAP_NONE; - ret = cros_typec_ec_command(typec, typec->cmd_ver, + ret = cros_typec_ec_command(typec, typec->pd_ctrl_ver, EC_CMD_USB_PD_CONTROL, &req, sizeof(req), &resp, sizeof(resp)); if (ret < 0) @@ -351,7 +351,7 @@ static int cros_typec_port_update(struct cros_typec_data *typec, int port_num) dev_dbg(typec->dev, "Polarity %d: 0x%hhx\n", port_num, resp.polarity); dev_dbg(typec->dev, "State %d: %s\n", port_num, resp.state); - if (typec->cmd_ver == 1) + if (typec->pd_ctrl_ver != 0) cros_typec_set_port_params_v1(typec, port_num, &resp); else cros_typec_set_port_params_v0(typec, port_num, @@ -374,13 +374,15 @@ static int cros_typec_get_cmd_version(struct cros_typec_data *typec) if (ret < 0) return ret; - if (resp.version_mask & EC_VER_MASK(1)) - typec->cmd_ver = 1; + if (resp.version_mask & EC_VER_MASK(2)) + typec->pd_ctrl_ver = 2; + else if (resp.version_mask & EC_VER_MASK(1)) + typec->pd_ctrl_ver = 1; else - typec->cmd_ver = 0; + typec->pd_ctrl_ver = 0; dev_dbg(typec->dev, "PD Control has version mask 0x%hhx\n", - typec->cmd_ver); + typec->pd_ctrl_ver); return 0; } -- GitLab From 7e7def15fa4bc9d6a2fa3d1d379286591c249381 Mon Sep 17 00:00:00 2001 From: Prashant Malani Date: Thu, 28 May 2020 04:36:07 -0700 Subject: [PATCH 0046/2249] platform/chrome: cros_ec_typec: Add USB mux control Add support to configure various Type C switches appropriately using the Type C connector class API, when the Chrome OS EC informs the AP that the USB operating mode has been entered. Signed-off-by: Prashant Malani Reviewed-by: Heikki Krogerus Signed-off-by: Enric Balletbo i Serra --- drivers/platform/chrome/cros_ec_typec.c | 100 +++++++++++++++++++++++- 1 file changed, 97 insertions(+), 3 deletions(-) diff --git a/drivers/platform/chrome/cros_ec_typec.c b/drivers/platform/chrome/cros_ec_typec.c index d69a88464cef0..9ebf9abed16ff 100644 --- a/drivers/platform/chrome/cros_ec_typec.c +++ b/drivers/platform/chrome/cros_ec_typec.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include @@ -30,6 +31,10 @@ struct cros_typec_port { struct typec_switch *ori_sw; struct typec_mux *mux; struct usb_role_switch *role_sw; + + /* Variables keeping track of switch state. */ + struct typec_mux_state state; + uint8_t mux_flags; }; /* Platform-specific data for the Chrome OS EC Type C controller. */ @@ -264,6 +269,23 @@ static int cros_typec_add_partner(struct cros_typec_data *typec, int port_num, return ret; } +static void cros_typec_remove_partner(struct cros_typec_data *typec, + int port_num) +{ + struct cros_typec_port *port = typec->ports[port_num]; + + port->state.alt = NULL; + port->state.mode = TYPEC_STATE_USB; + port->state.data = NULL; + + usb_role_switch_set_role(port->role_sw, USB_ROLE_NONE); + typec_switch_set(port->ori_sw, TYPEC_ORIENTATION_NONE); + typec_mux_set(port->mux, &port->state); + + typec_unregister_partner(port->partner); + port->partner = NULL; +} + static void cros_typec_set_port_params_v0(struct cros_typec_data *typec, int port_num, struct ec_response_usb_pd_control *resp) { @@ -317,16 +339,69 @@ static void cros_typec_set_port_params_v1(struct cros_typec_data *typec, } else { if (!typec->ports[port_num]->partner) return; + cros_typec_remove_partner(typec, port_num); + } +} + +static int cros_typec_get_mux_info(struct cros_typec_data *typec, int port_num, + struct ec_response_usb_pd_mux_info *resp) +{ + struct ec_params_usb_pd_mux_info req = { + .port = port_num, + }; + + return cros_typec_ec_command(typec, 0, EC_CMD_USB_PD_MUX_INFO, &req, + sizeof(req), resp, sizeof(*resp)); +} + +static int cros_typec_usb_safe_state(struct cros_typec_port *port) +{ + port->state.mode = TYPEC_STATE_SAFE; + + return typec_mux_set(port->mux, &port->state); +} - typec_unregister_partner(typec->ports[port_num]->partner); - typec->ports[port_num]->partner = NULL; +int cros_typec_configure_mux(struct cros_typec_data *typec, int port_num, + uint8_t mux_flags) +{ + struct cros_typec_port *port = typec->ports[port_num]; + enum typec_orientation orientation; + int ret; + + if (!port->partner) + return 0; + + if (mux_flags & USB_PD_MUX_POLARITY_INVERTED) + orientation = TYPEC_ORIENTATION_REVERSE; + else + orientation = TYPEC_ORIENTATION_NORMAL; + + ret = typec_switch_set(port->ori_sw, orientation); + if (ret) + return ret; + + port->state.alt = NULL; + port->state.mode = TYPEC_STATE_USB; + + if (mux_flags & USB_PD_MUX_SAFE_MODE) + ret = cros_typec_usb_safe_state(port); + else if (mux_flags & USB_PD_MUX_USB_ENABLED) + ret = typec_mux_set(port->mux, &port->state); + else { + dev_info(typec->dev, + "Unsupported mode requested, mux flags: %x\n", + mux_flags); + ret = -ENOTSUPP; } + + return ret; } static int cros_typec_port_update(struct cros_typec_data *typec, int port_num) { struct ec_params_usb_pd_control req; struct ec_response_usb_pd_control_v1 resp; + struct ec_response_usb_pd_mux_info mux_resp; int ret; if (port_num < 0 || port_num >= typec->num_ports) { @@ -357,7 +432,26 @@ static int cros_typec_port_update(struct cros_typec_data *typec, int port_num) cros_typec_set_port_params_v0(typec, port_num, (struct ec_response_usb_pd_control *) &resp); - return 0; + /* Update the switches if they exist, according to requested state */ + ret = cros_typec_get_mux_info(typec, port_num, &mux_resp); + if (ret < 0) { + dev_warn(typec->dev, + "Failed to get mux info for port: %d, err = %d\n", + port_num, ret); + return 0; + } + + /* No change needs to be made, let's exit early. */ + if (typec->ports[port_num]->mux_flags == mux_resp.flags) + return 0; + + typec->ports[port_num]->mux_flags = mux_resp.flags; + ret = cros_typec_configure_mux(typec, port_num, mux_resp.flags); + if (ret) + dev_warn(typec->dev, "Configure muxes failed, err = %d\n", ret); + + return usb_role_switch_set_role(typec->ports[port_num]->role_sw, + !!(resp.role & PD_CTRL_RESP_ROLE_DATA)); } static int cros_typec_get_cmd_version(struct cros_typec_data *typec) -- GitLab From 410457b99c7ea3e0cf8de1054e175ba3c2213d33 Mon Sep 17 00:00:00 2001 From: Prashant Malani Date: Thu, 28 May 2020 04:36:10 -0700 Subject: [PATCH 0047/2249] platform/chrome: cros_ec_typec: Support DP alt mode Handle Chrome EC mux events to configure on-board muxes correctly while entering DP alternate mode. Since we don't surface SVID and VDO information regarding the DP alternate mode, configure the Type C muxes directly from the port driver. Later, when mode discovery information is correctly surfaced to the driver, we can register the DP alternate mode driver and let it handle the mux configuration. Also, modify the struct_typec_state state management to account for the addition of DP alternate mode. Signed-off-by: Prashant Malani Reviewed-by: Heikki Krogerus Signed-off-by: Enric Balletbo i Serra --- drivers/platform/chrome/cros_ec_typec.c | 90 ++++++++++++++++++++++--- 1 file changed, 80 insertions(+), 10 deletions(-) diff --git a/drivers/platform/chrome/cros_ec_typec.c b/drivers/platform/chrome/cros_ec_typec.c index 9ebf9abed16ff..509fc761906bb 100644 --- a/drivers/platform/chrome/cros_ec_typec.c +++ b/drivers/platform/chrome/cros_ec_typec.c @@ -15,11 +15,18 @@ #include #include #include +#include #include #include #define DRV_NAME "cros-ec-typec" +/* Supported alt modes. */ +enum { + CROS_EC_ALTMODE_DP = 0, + CROS_EC_ALTMODE_MAX, +}; + /* Per port data. */ struct cros_typec_port { struct typec_port *port; @@ -35,6 +42,9 @@ struct cros_typec_port { /* Variables keeping track of switch state. */ struct typec_mux_state state; uint8_t mux_flags; + + /* Port alt modes. */ + struct typec_altmode p_altmode[CROS_EC_ALTMODE_MAX]; }; /* Platform-specific data for the Chrome OS EC Type C controller. */ @@ -142,6 +152,24 @@ static void cros_unregister_ports(struct cros_typec_data *typec) } } +/* + * Fake the alt mode structs until we actually start registering Type C port + * and partner alt modes. + */ +static void cros_typec_register_port_altmodes(struct cros_typec_data *typec, + int port_num) +{ + struct cros_typec_port *port = typec->ports[port_num]; + + /* All PD capable CrOS devices are assumed to support DP altmode. */ + port->p_altmode[CROS_EC_ALTMODE_DP].svid = USB_TYPEC_DP_SID; + port->p_altmode[CROS_EC_ALTMODE_DP].mode = USB_TYPEC_DP_MODE; + + port->state.alt = NULL; + port->state.mode = TYPEC_STATE_USB; + port->state.data = NULL; +} + static int cros_typec_init_ports(struct cros_typec_data *typec) { struct device *dev = typec->dev; @@ -205,6 +233,8 @@ static int cros_typec_init_ports(struct cros_typec_data *typec) if (ret) dev_dbg(dev, "No switch control for port %d\n", port_num); + + cros_typec_register_port_altmodes(typec, port_num); } return 0; @@ -361,8 +391,46 @@ static int cros_typec_usb_safe_state(struct cros_typec_port *port) return typec_mux_set(port->mux, &port->state); } +/* Spoof the VDOs that were likely communicated by the partner. */ +static int cros_typec_enable_dp(struct cros_typec_data *typec, + int port_num, + struct ec_response_usb_pd_control_v2 *pd_ctrl) +{ + struct cros_typec_port *port = typec->ports[port_num]; + struct typec_displayport_data dp_data; + int ret; + + if (typec->pd_ctrl_ver < 2) { + dev_err(typec->dev, + "PD_CTRL version too old: %d\n", typec->pd_ctrl_ver); + return -ENOTSUPP; + } + + /* Status VDO. */ + dp_data.status = DP_STATUS_ENABLED; + if (port->mux_flags & USB_PD_MUX_HPD_IRQ) + dp_data.status |= DP_STATUS_IRQ_HPD; + if (port->mux_flags & USB_PD_MUX_HPD_LVL) + dp_data.status |= DP_STATUS_HPD_STATE; + + /* Configuration VDO. */ + dp_data.conf = DP_CONF_SET_PIN_ASSIGN(pd_ctrl->dp_mode); + if (!port->state.alt) { + port->state.alt = &port->p_altmode[CROS_EC_ALTMODE_DP]; + ret = cros_typec_usb_safe_state(port); + if (ret) + return ret; + } + + port->state.data = &dp_data; + port->state.mode = TYPEC_MODAL_STATE(ffs(pd_ctrl->dp_mode)); + + return typec_mux_set(port->mux, &port->state); +} + int cros_typec_configure_mux(struct cros_typec_data *typec, int port_num, - uint8_t mux_flags) + uint8_t mux_flags, + struct ec_response_usb_pd_control_v2 *pd_ctrl) { struct cros_typec_port *port = typec->ports[port_num]; enum typec_orientation orientation; @@ -380,14 +448,15 @@ int cros_typec_configure_mux(struct cros_typec_data *typec, int port_num, if (ret) return ret; - port->state.alt = NULL; - port->state.mode = TYPEC_STATE_USB; - - if (mux_flags & USB_PD_MUX_SAFE_MODE) + if (mux_flags & USB_PD_MUX_DP_ENABLED) { + ret = cros_typec_enable_dp(typec, port_num, pd_ctrl); + } else if (mux_flags & USB_PD_MUX_SAFE_MODE) { ret = cros_typec_usb_safe_state(port); - else if (mux_flags & USB_PD_MUX_USB_ENABLED) + } else if (mux_flags & USB_PD_MUX_USB_ENABLED) { + port->state.alt = NULL; + port->state.mode = TYPEC_STATE_USB; ret = typec_mux_set(port->mux, &port->state); - else { + } else { dev_info(typec->dev, "Unsupported mode requested, mux flags: %x\n", mux_flags); @@ -400,7 +469,7 @@ int cros_typec_configure_mux(struct cros_typec_data *typec, int port_num, static int cros_typec_port_update(struct cros_typec_data *typec, int port_num) { struct ec_params_usb_pd_control req; - struct ec_response_usb_pd_control_v1 resp; + struct ec_response_usb_pd_control_v2 resp; struct ec_response_usb_pd_mux_info mux_resp; int ret; @@ -427,7 +496,8 @@ static int cros_typec_port_update(struct cros_typec_data *typec, int port_num) dev_dbg(typec->dev, "State %d: %s\n", port_num, resp.state); if (typec->pd_ctrl_ver != 0) - cros_typec_set_port_params_v1(typec, port_num, &resp); + cros_typec_set_port_params_v1(typec, port_num, + (struct ec_response_usb_pd_control_v1 *)&resp); else cros_typec_set_port_params_v0(typec, port_num, (struct ec_response_usb_pd_control *) &resp); @@ -446,7 +516,7 @@ static int cros_typec_port_update(struct cros_typec_data *typec, int port_num) return 0; typec->ports[port_num]->mux_flags = mux_resp.flags; - ret = cros_typec_configure_mux(typec, port_num, mux_resp.flags); + ret = cros_typec_configure_mux(typec, port_num, mux_resp.flags, &resp); if (ret) dev_warn(typec->dev, "Configure muxes failed, err = %d\n", ret); -- GitLab From 285e74ab4f94d921a56fcf66320b3cd65e35b6bc Mon Sep 17 00:00:00 2001 From: Ezequiel Garcia Date: Tue, 14 Apr 2020 19:09:43 -0300 Subject: [PATCH 0048/2249] hwspinlock: Simplify Kconfig Every hwspinlock driver is expected to depend on the hwspinlock core, so it's possible to simplify the Kconfig, factoring out the HWSPINLOCK dependency. Reviewed-by: Baolin Wang Signed-off-by: Ezequiel Garcia Link: https://lore.kernel.org/r/20200414220943.6203-1-ezequiel@collabora.com Signed-off-by: Bjorn Andersson --- drivers/hwspinlock/Kconfig | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/drivers/hwspinlock/Kconfig b/drivers/hwspinlock/Kconfig index 826a1054100d0..32cd26352f381 100644 --- a/drivers/hwspinlock/Kconfig +++ b/drivers/hwspinlock/Kconfig @@ -6,9 +6,10 @@ menuconfig HWSPINLOCK bool "Hardware Spinlock drivers" +if HWSPINLOCK + config HWSPINLOCK_OMAP tristate "OMAP Hardware Spinlock device" - depends on HWSPINLOCK depends on ARCH_OMAP4 || SOC_OMAP5 || SOC_DRA7XX || SOC_AM33XX || SOC_AM43XX || ARCH_K3 || COMPILE_TEST help Say y here to support the OMAP Hardware Spinlock device (firstly @@ -18,7 +19,6 @@ config HWSPINLOCK_OMAP config HWSPINLOCK_QCOM tristate "Qualcomm Hardware Spinlock device" - depends on HWSPINLOCK depends on ARCH_QCOM || COMPILE_TEST select MFD_SYSCON help @@ -30,7 +30,6 @@ config HWSPINLOCK_QCOM config HWSPINLOCK_SIRF tristate "SIRF Hardware Spinlock device" - depends on HWSPINLOCK depends on ARCH_SIRF || COMPILE_TEST help Say y here to support the SIRF Hardware Spinlock device, which @@ -43,7 +42,6 @@ config HWSPINLOCK_SIRF config HWSPINLOCK_SPRD tristate "SPRD Hardware Spinlock device" depends on ARCH_SPRD || COMPILE_TEST - depends on HWSPINLOCK help Say y here to support the SPRD Hardware Spinlock device. @@ -52,7 +50,6 @@ config HWSPINLOCK_SPRD config HWSPINLOCK_STM32 tristate "STM32 Hardware Spinlock device" depends on MACH_STM32MP157 || COMPILE_TEST - depends on HWSPINLOCK help Say y here to support the STM32 Hardware Spinlock device. @@ -60,7 +57,6 @@ config HWSPINLOCK_STM32 config HSEM_U8500 tristate "STE Hardware Semaphore functionality" - depends on HWSPINLOCK depends on ARCH_U8500 || COMPILE_TEST help Say y here to support the STE Hardware Semaphore functionality, which @@ -68,3 +64,5 @@ config HSEM_U8500 SoC. If unsure, say N. + +endif # HWSPINLOCK -- GitLab From 4a95a1b20da31db0c1ca5289a892fef21f691f27 Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Thu, 11 Jun 2020 11:54:01 +0100 Subject: [PATCH 0049/2249] KVM: arm64: Enable Address Authentication at EL2 if available While initializing EL2, enable Address Authentication if detected from EL1. We still use the EL1-provided keys though. Acked-by: Andrew Scull Acked-by: Mark Rutland Signed-off-by: Marc Zyngier --- arch/arm64/kvm/hyp-init.S | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/arch/arm64/kvm/hyp-init.S b/arch/arm64/kvm/hyp-init.S index 6e6ed5581eed1..1587d146726ab 100644 --- a/arch/arm64/kvm/hyp-init.S +++ b/arch/arm64/kvm/hyp-init.S @@ -104,6 +104,11 @@ alternative_else_nop_endif */ mov_q x4, (SCTLR_EL2_RES1 | (SCTLR_ELx_FLAGS & ~SCTLR_ELx_A)) CPU_BE( orr x4, x4, #SCTLR_ELx_EE) +alternative_if ARM64_HAS_ADDRESS_AUTH + mov_q x5, (SCTLR_ELx_ENIA | SCTLR_ELx_ENIB | \ + SCTLR_ELx_ENDA | SCTLR_ELx_ENDB) + orr x4, x4, x5 +alternative_else_nop_endif msr sctlr_el2, x4 isb -- GitLab From dfb0589c8fff9dde809b9013335a6b8019b299b8 Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Thu, 11 Jun 2020 12:18:58 +0100 Subject: [PATCH 0050/2249] KVM: arm64: Allow ARM64_PTR_AUTH when ARM64_VHE=n We currently prevent PtrAuth from even being built if KVM is selected, but VHE isn't. It is a bit of a pointless restriction, since we also check this at run time (rejecting the enabling of PtrAuth for the vcpu if we're not running with VHE). Just drop this apparently useless restriction. Acked-by: Andrew Scull Acked-by: Mark Rutland Signed-off-by: Marc Zyngier --- arch/arm64/Kconfig | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index 31380da536894..d719ea9c596d9 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@ -1516,7 +1516,6 @@ menu "ARMv8.3 architectural features" config ARM64_PTR_AUTH bool "Enable support for pointer authentication" default y - depends on !KVM || ARM64_VHE depends on (CC_HAS_SIGN_RETURN_ADDRESS || CC_HAS_BRANCH_PROT_PAC_RET) && AS_HAS_PAC # GCC 9.1 and later inserts a .note.gnu.property section note for PAC # which is only understood by binutils starting with version 2.33.1. @@ -1543,8 +1542,7 @@ config ARM64_PTR_AUTH The feature is detected at runtime. If the feature is not present in hardware it will not be advertised to userspace/KVM guest nor will it - be enabled. However, KVM guest also require VHE mode and hence - CONFIG_ARM64_VHE=y option to use this feature. + be enabled. If the feature is present on the boot CPU but not on a late CPU, then the late CPU will be parked. Also, if the boot CPU does not have -- GitLab From aff7cce0d337f5468470d614ef83a507dcf4c93f Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Thu, 11 Jun 2020 13:20:28 +0100 Subject: [PATCH 0051/2249] KVM: arm64: Allow PtrAuth to be enabled from userspace on non-VHE systems Now that the scene is set for enabling PtrAuth on non-VHE, drop the restrictions preventing userspace from enabling it. Acked-by: Andrew Scull Acked-by: Mark Rutland Signed-off-by: Marc Zyngier --- arch/arm64/kvm/reset.c | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/arch/arm64/kvm/reset.c b/arch/arm64/kvm/reset.c index d3b2090237274..2a929789fe2ed 100644 --- a/arch/arm64/kvm/reset.c +++ b/arch/arm64/kvm/reset.c @@ -42,6 +42,11 @@ static u32 kvm_ipa_limit; #define VCPU_RESET_PSTATE_SVC (PSR_AA32_MODE_SVC | PSR_AA32_A_BIT | \ PSR_AA32_I_BIT | PSR_AA32_F_BIT) +static bool system_has_full_ptr_auth(void) +{ + return system_supports_address_auth() && system_supports_generic_auth(); +} + /** * kvm_arch_vm_ioctl_check_extension * @@ -80,8 +85,7 @@ int kvm_arch_vm_ioctl_check_extension(struct kvm *kvm, long ext) break; case KVM_CAP_ARM_PTRAUTH_ADDRESS: case KVM_CAP_ARM_PTRAUTH_GENERIC: - r = has_vhe() && system_supports_address_auth() && - system_supports_generic_auth(); + r = system_has_full_ptr_auth(); break; default: r = 0; @@ -205,19 +209,14 @@ static void kvm_vcpu_reset_sve(struct kvm_vcpu *vcpu) static int kvm_vcpu_enable_ptrauth(struct kvm_vcpu *vcpu) { - /* Support ptrauth only if the system supports these capabilities. */ - if (!has_vhe()) - return -EINVAL; - - if (!system_supports_address_auth() || - !system_supports_generic_auth()) - return -EINVAL; /* * For now make sure that both address/generic pointer authentication - * features are requested by the userspace together. + * features are requested by the userspace together and the system + * supports these capabilities. */ if (!test_bit(KVM_ARM_VCPU_PTRAUTH_ADDRESS, vcpu->arch.features) || - !test_bit(KVM_ARM_VCPU_PTRAUTH_GENERIC, vcpu->arch.features)) + !test_bit(KVM_ARM_VCPU_PTRAUTH_GENERIC, vcpu->arch.features) || + !system_has_full_ptr_auth()) return -EINVAL; vcpu->arch.flags |= KVM_ARM64_GUEST_HAS_PTRAUTH; -- GitLab From 655169cec7bbf84f59faa9f824edb581eaecf78d Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Thu, 11 Jun 2020 11:26:09 +0100 Subject: [PATCH 0052/2249] KVM: arm64: Check HCR_EL2 instead of shadow copy to swap PtrAuth registers When save/restoring PtrAuth registers between host and guest, it is pretty useless to fetch the in-memory state, while we have the right state in the HCR_EL2 system register. Use that instead. Acked-by: Mark Rutland Signed-off-by: Marc Zyngier --- arch/arm64/include/asm/kvm_ptrauth.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm64/include/asm/kvm_ptrauth.h b/arch/arm64/include/asm/kvm_ptrauth.h index 6301813dcace0..f1830173fa9ec 100644 --- a/arch/arm64/include/asm/kvm_ptrauth.h +++ b/arch/arm64/include/asm/kvm_ptrauth.h @@ -74,7 +74,7 @@ alternative_if_not ARM64_HAS_ADDRESS_AUTH_IMP_DEF b 1001f alternative_else_nop_endif 1000: - ldr \reg1, [\g_ctxt, #(VCPU_HCR_EL2 - VCPU_CONTEXT)] + mrs \reg1, hcr_el2 and \reg1, \reg1, #(HCR_API | HCR_APK) cbz \reg1, 1001f add \reg1, \g_ctxt, #CPU_APIAKEYLO_EL1 @@ -90,7 +90,7 @@ alternative_if_not ARM64_HAS_ADDRESS_AUTH_IMP_DEF b 2001f alternative_else_nop_endif 2000: - ldr \reg1, [\g_ctxt, #(VCPU_HCR_EL2 - VCPU_CONTEXT)] + mrs \reg1, hcr_el2 and \reg1, \reg1, #(HCR_API | HCR_APK) cbz \reg1, 2001f add \reg1, \g_ctxt, #CPU_APIAKEYLO_EL1 -- GitLab From 11ac16a4290b72efa8328cb144b727f3cbbdfa6a Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Mon, 15 Jun 2020 21:03:30 +0100 Subject: [PATCH 0053/2249] KVM: arm64: Simplify PtrAuth alternative patching We currently decide to execute the PtrAuth save/restore code based on a set of branches that evaluate as (ARM64_HAS_ADDRESS_AUTH_ARCH || ARM64_HAS_ADDRESS_AUTH_IMP_DEF). This can be easily replaced by a much simpler test as the ARM64_HAS_ADDRESS_AUTH capability is exactly this expression. Suggested-by: Mark Rutland Acked-by: Mark Rutland Signed-off-by: Marc Zyngier --- arch/arm64/include/asm/kvm_ptrauth.h | 30 ++++++++++------------------ 1 file changed, 11 insertions(+), 19 deletions(-) diff --git a/arch/arm64/include/asm/kvm_ptrauth.h b/arch/arm64/include/asm/kvm_ptrauth.h index f1830173fa9ec..0ddf98c3ba9fa 100644 --- a/arch/arm64/include/asm/kvm_ptrauth.h +++ b/arch/arm64/include/asm/kvm_ptrauth.h @@ -61,44 +61,36 @@ /* * Both ptrauth_switch_to_guest and ptrauth_switch_to_host macros will - * check for the presence of one of the cpufeature flag - * ARM64_HAS_ADDRESS_AUTH_ARCH or ARM64_HAS_ADDRESS_AUTH_IMP_DEF and + * check for the presence ARM64_HAS_ADDRESS_AUTH, which is defined as + * (ARM64_HAS_ADDRESS_AUTH_ARCH || ARM64_HAS_ADDRESS_AUTH_IMP_DEF) and * then proceed ahead with the save/restore of Pointer Authentication - * key registers. + * key registers if enabled for the guest. */ .macro ptrauth_switch_to_guest g_ctxt, reg1, reg2, reg3 -alternative_if ARM64_HAS_ADDRESS_AUTH_ARCH - b 1000f +alternative_if_not ARM64_HAS_ADDRESS_AUTH + b .L__skip_switch\@ alternative_else_nop_endif -alternative_if_not ARM64_HAS_ADDRESS_AUTH_IMP_DEF - b 1001f -alternative_else_nop_endif -1000: mrs \reg1, hcr_el2 and \reg1, \reg1, #(HCR_API | HCR_APK) - cbz \reg1, 1001f + cbz \reg1, .L__skip_switch\@ add \reg1, \g_ctxt, #CPU_APIAKEYLO_EL1 ptrauth_restore_state \reg1, \reg2, \reg3 -1001: +.L__skip_switch\@: .endm .macro ptrauth_switch_to_host g_ctxt, h_ctxt, reg1, reg2, reg3 -alternative_if ARM64_HAS_ADDRESS_AUTH_ARCH - b 2000f -alternative_else_nop_endif -alternative_if_not ARM64_HAS_ADDRESS_AUTH_IMP_DEF - b 2001f +alternative_if_not ARM64_HAS_ADDRESS_AUTH + b .L__skip_switch\@ alternative_else_nop_endif -2000: mrs \reg1, hcr_el2 and \reg1, \reg1, #(HCR_API | HCR_APK) - cbz \reg1, 2001f + cbz \reg1, .L__skip_switch\@ add \reg1, \g_ctxt, #CPU_APIAKEYLO_EL1 ptrauth_save_state \reg1, \reg2, \reg3 add \reg1, \h_ctxt, #CPU_APIAKEYLO_EL1 ptrauth_restore_state \reg1, \reg2, \reg3 isb -2001: +.L__skip_switch\@: .endm #else /* !CONFIG_ARM64_PTR_AUTH */ -- GitLab From 447b4eb6ceeb2d0d83d7f5aa248f2798f167cfda Mon Sep 17 00:00:00 2001 From: Prashant Malani Date: Fri, 19 Jun 2020 19:00:37 -0700 Subject: [PATCH 0054/2249] platform/chrome: cros_ec_typec: Make configure_mux static Since cros_typec_configure_mux() is only used in cros-ec-typec, it should be marked static. Fixes: 7e7def15fa4b ("platform/chrome: cros_ec_typec: Add USB mux control") Reported-by: kernel test robot Signed-off-by: Prashant Malani Signed-off-by: Enric Balletbo i Serra --- drivers/platform/chrome/cros_ec_typec.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/platform/chrome/cros_ec_typec.c b/drivers/platform/chrome/cros_ec_typec.c index 509fc761906bb..1df1386f32e4f 100644 --- a/drivers/platform/chrome/cros_ec_typec.c +++ b/drivers/platform/chrome/cros_ec_typec.c @@ -428,9 +428,9 @@ static int cros_typec_enable_dp(struct cros_typec_data *typec, return typec_mux_set(port->mux, &port->state); } -int cros_typec_configure_mux(struct cros_typec_data *typec, int port_num, - uint8_t mux_flags, - struct ec_response_usb_pd_control_v2 *pd_ctrl) +static int cros_typec_configure_mux(struct cros_typec_data *typec, int port_num, + uint8_t mux_flags, + struct ec_response_usb_pd_control_v2 *pd_ctrl) { struct cros_typec_port *port = typec->ports[port_num]; enum typec_orientation orientation; -- GitLab From a1f8bc95c33e953e080f72be4b95176dacb423b0 Mon Sep 17 00:00:00 2001 From: Jason Yan Date: Mon, 20 Apr 2020 20:35:28 +0800 Subject: [PATCH 0055/2249] perf annotate: Remove unneeded conversion to bool The '>' expression itself is bool, no need to convert it to bool again. This fixes the following coccicheck warning: tools/perf/ui/browsers/annotate.c:212:30-35: WARNING: conversion to bool not needed here Signed-off-by: Jason Yan Cc: Alexander Shishkin Cc: Jiri Olsa Cc: Mark Rutland Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lore.kernel.org/lkml/20200420123528.11655-1-yanaijie@huawei.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/ui/browsers/annotate.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/perf/ui/browsers/annotate.c b/tools/perf/ui/browsers/annotate.c index 9023267e56433..bd77825fd5a15 100644 --- a/tools/perf/ui/browsers/annotate.c +++ b/tools/perf/ui/browsers/annotate.c @@ -209,7 +209,7 @@ static void annotate_browser__draw_current_jump(struct ui_browser *browser) ui_browser__mark_fused(browser, pcnt_width + 3 + notes->widths.addr + width, from - 1, - to > from ? true : false); + to > from); } } -- GitLab From 387ad33fe710758a8e1b860819a7452bceb4329a Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Tue, 2 Jun 2020 23:47:29 +0200 Subject: [PATCH 0056/2249] perf tools: Add fake pmu support Add a way to create a pmu event without the actual PMU being in place. This way we can test metrics defined for any processor. The interface is to define fake_pmu in struct parse_events_state data. It will be used only in tests via special interface function added in following changes. Signed-off-by: Jiri Olsa Acked-by: Ian Rogers Cc: Alexander Shishkin Cc: Andi Kleen Cc: Michael Petlan Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lore.kernel.org/lkml/20200602214741.1218986-2-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/parse-events.c | 6 ++--- tools/perf/util/parse-events.h | 3 ++- tools/perf/util/parse-events.l | 8 +++++-- tools/perf/util/parse-events.y | 41 ++++++++++++++++++++++++++++++++-- 4 files changed, 50 insertions(+), 8 deletions(-) diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index 3decbb203846a..4eb7bd53d0481 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c @@ -1450,7 +1450,7 @@ int parse_events_add_pmu(struct parse_events_state *parse_state, fprintf(stderr, "' that may result in non-fatal errors\n"); } - pmu = perf_pmu__find(name); + pmu = parse_state->fake_pmu ?: perf_pmu__find(name); if (!pmu) { char *err_str; @@ -1483,7 +1483,7 @@ int parse_events_add_pmu(struct parse_events_state *parse_state, } } - if (perf_pmu__check_alias(pmu, head_config, &info)) + if (!parse_state->fake_pmu && perf_pmu__check_alias(pmu, head_config, &info)) return -EINVAL; if (verbose > 1) { @@ -1516,7 +1516,7 @@ int parse_events_add_pmu(struct parse_events_state *parse_state, if (pmu->default_config && get_config_chgs(pmu, head_config, &config_terms)) return -ENOMEM; - if (perf_pmu__config(pmu, &attr, head_config, parse_state->error)) { + if (!parse_state->fake_pmu && perf_pmu__config(pmu, &attr, head_config, parse_state->error)) { struct evsel_config_term *pos, *tmp; list_for_each_entry_safe(pos, tmp, &config_terms, list) { diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h index 1fe23a2f9b36e..bf79e1eac7d95 100644 --- a/tools/perf/util/parse-events.h +++ b/tools/perf/util/parse-events.h @@ -127,9 +127,10 @@ struct parse_events_state { int idx; int nr_groups; struct parse_events_error *error; - struct evlist *evlist; + struct evlist *evlist; struct list_head *terms; int stoken; + struct perf_pmu *fake_pmu; }; void parse_events__handle_error(struct parse_events_error *err, int idx, diff --git a/tools/perf/util/parse-events.l b/tools/perf/util/parse-events.l index 002802e17059e..56912c9641f55 100644 --- a/tools/perf/util/parse-events.l +++ b/tools/perf/util/parse-events.l @@ -129,12 +129,16 @@ do { \ yyless(0); \ } while (0) -static int pmu_str_check(yyscan_t scanner) +static int pmu_str_check(yyscan_t scanner, struct parse_events_state *parse_state) { YYSTYPE *yylval = parse_events_get_lval(scanner); char *text = parse_events_get_text(scanner); yylval->str = strdup(text); + + if (parse_state->fake_pmu) + return PE_PMU_EVENT_FAKE; + switch (perf_pmu__parse_check(text)) { case PMU_EVENT_SYMBOL_PREFIX: return PE_PMU_EVENT_PRE; @@ -376,7 +380,7 @@ r{num_raw_hex} { return raw(yyscanner); } {modifier_event} { return str(yyscanner, PE_MODIFIER_EVENT); } {bpf_object} { if (!isbpf(yyscanner)) { USER_REJECT }; return str(yyscanner, PE_BPF_OBJECT); } {bpf_source} { if (!isbpf(yyscanner)) { USER_REJECT }; return str(yyscanner, PE_BPF_SOURCE); } -{name} { return pmu_str_check(yyscanner); } +{name} { return pmu_str_check(yyscanner, _parse_state); } {name_tag} { return str(yyscanner, PE_NAME); } "/" { BEGIN(config); return '/'; } - { return '-'; } diff --git a/tools/perf/util/parse-events.y b/tools/perf/util/parse-events.y index acef87d9af588..b9fb91fdc5de9 100644 --- a/tools/perf/util/parse-events.y +++ b/tools/perf/util/parse-events.y @@ -69,7 +69,7 @@ static void inc_group_count(struct list_head *list, %token PE_NAME_CACHE_TYPE PE_NAME_CACHE_OP_RESULT %token PE_PREFIX_MEM PE_PREFIX_RAW PE_PREFIX_GROUP %token PE_ERROR -%token PE_PMU_EVENT_PRE PE_PMU_EVENT_SUF PE_KERNEL_PMU_EVENT +%token PE_PMU_EVENT_PRE PE_PMU_EVENT_SUF PE_KERNEL_PMU_EVENT PE_PMU_EVENT_FAKE %token PE_ARRAY_ALL PE_ARRAY_RANGE %token PE_DRV_CFG_TERM %type PE_VALUE @@ -87,7 +87,7 @@ static void inc_group_count(struct list_head *list, %type PE_MODIFIER_EVENT %type PE_MODIFIER_BP %type PE_EVENT_NAME -%type PE_PMU_EVENT_PRE PE_PMU_EVENT_SUF PE_KERNEL_PMU_EVENT +%type PE_PMU_EVENT_PRE PE_PMU_EVENT_SUF PE_KERNEL_PMU_EVENT PE_PMU_EVENT_FAKE %type PE_DRV_CFG_TERM %destructor { free ($$); } %type event_term @@ -356,6 +356,43 @@ PE_PMU_EVENT_PRE '-' PE_PMU_EVENT_SUF sep_dc YYABORT; $$ = list; } +| +PE_PMU_EVENT_FAKE sep_dc +{ + struct list_head *list; + int err; + + list = alloc_list(); + if (!list) + YYABORT; + + err = parse_events_add_pmu(_parse_state, list, $1, NULL, false, false); + free($1); + if (err < 0) { + free(list); + YYABORT; + } + $$ = list; +} +| +PE_PMU_EVENT_FAKE opt_pmu_config +{ + struct list_head *list; + int err; + + list = alloc_list(); + if (!list) + YYABORT; + + err = parse_events_add_pmu(_parse_state, list, $1, $2, false, false); + free($1); + parse_events_terms__delete($2); + if (err < 0) { + free(list); + YYABORT; + } + $$ = list; +} value_sym: PE_VALUE_SYM_HW -- GitLab From 34bacc9578de2893ab6301cea89ea001d8e4cf5b Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Tue, 2 Jun 2020 23:47:31 +0200 Subject: [PATCH 0057/2249] perf tests: Factor check_parse_id function Separating the generic part of check_parse_id function, so it can be used in following changes for the new test. Committer notes: Fix this error: tests/pmu-events.c:413:40: error: missing field 'idx' initializer [-Werror,-Wmissing-field-initializers] struct parse_events_error error = { 0 }; Signed-off-by: Jiri Olsa Acked-by: Ian Rogers Cc: Alexander Shishkin Cc: Andi Kleen Cc: Michael Petlan Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lore.kernel.org/lkml/20200602214741.1218986-4-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/tests/pmu-events.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/tools/perf/tests/pmu-events.c b/tools/perf/tests/pmu-events.c index ab64b4a4e2848..82fa69a60ec8a 100644 --- a/tools/perf/tests/pmu-events.c +++ b/tools/perf/tests/pmu-events.c @@ -390,9 +390,8 @@ static bool is_number(const char *str) return errno == 0 && end_ptr != str; } -static int check_parse_id(const char *id, bool same_cpu, struct pmu_event *pe) +static int check_parse_id(const char *id, struct parse_events_error *error) { - struct parse_events_error error; struct evlist *evlist; int ret; @@ -401,8 +400,18 @@ static int check_parse_id(const char *id, bool same_cpu, struct pmu_event *pe) return 0; evlist = evlist__new(); - memset(&error, 0, sizeof(error)); - ret = parse_events(evlist, id, &error); + if (!evlist) + return -ENOMEM; + ret = parse_events(evlist, id, error); + evlist__delete(evlist); + return ret; +} + +static int check_parse_cpu(const char *id, bool same_cpu, struct pmu_event *pe) +{ + struct parse_events_error error = { .idx = 0, }; + + int ret = check_parse_id(id, &error); if (ret && same_cpu) { pr_warning("Parse event failed metric '%s' id '%s' expr '%s'\n", pe->metric_name, id, pe->metric_expr); @@ -413,7 +422,6 @@ static int check_parse_id(const char *id, bool same_cpu, struct pmu_event *pe) id, pe->metric_name, pe->metric_expr); ret = 0; } - evlist__delete(evlist); free(error.str); free(error.help); free(error.first_str); @@ -474,7 +482,7 @@ static int test_parsing(void) expr__add_id(&ctx, strdup(cur->key), k++); hashmap__for_each_entry((&ctx.ids), cur, bkt) { - if (check_parse_id(cur->key, map == cpus_map, + if (check_parse_cpu(cur->key, map == cpus_map, pe)) ret++; } -- GitLab From 3bf91aa5aa493b2ac24ffcfc93ffe861bf03685f Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Wed, 3 Jun 2020 12:32:55 -0300 Subject: [PATCH 0058/2249] perf parse: Provide a way to pass a fake_pmu to parse_events() This is an alternative patch to what Jiri sent that instead of changing all callers to parse_events() for allowing to pass a fake_pmu, provide another function specifically for that. From Jiri's patch: This way it's possible to parse events from PMUs which are not present in the system. It's available only for testing purposes coming in following changes, so all the current users set fake_pmu argument as false. Based-on-a-patch-by: Jiri Olsa Link: http://lore.kernel.org/lkml/20200602214741.1218986-3-jolsa@kernel.org Acked-by: Jiri Olsa Cc: Alexander Shishkin Cc: Andi Kleen Cc: Ian Rogers Cc: Ingo Molnar Cc: Michael Petlan Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Stephane Eranian Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/parse-events.c | 15 ++++++++------- tools/perf/util/parse-events.h | 11 +++++++++-- 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index 4eb7bd53d0481..c4906a6a9f1af 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c @@ -2088,15 +2088,16 @@ int parse_events_terms(struct list_head *terms, const char *str) return ret; } -int parse_events(struct evlist *evlist, const char *str, - struct parse_events_error *err) +int __parse_events(struct evlist *evlist, const char *str, + struct parse_events_error *err, struct perf_pmu *fake_pmu) { struct parse_events_state parse_state = { - .list = LIST_HEAD_INIT(parse_state.list), - .idx = evlist->core.nr_entries, - .error = err, - .evlist = evlist, - .stoken = PE_START_EVENTS, + .list = LIST_HEAD_INIT(parse_state.list), + .idx = evlist->core.nr_entries, + .error = err, + .evlist = evlist, + .stoken = PE_START_EVENTS, + .fake_pmu = fake_pmu, }; int ret; diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h index bf79e1eac7d95..f0010095fc8c2 100644 --- a/tools/perf/util/parse-events.h +++ b/tools/perf/util/parse-events.h @@ -33,8 +33,15 @@ const char *event_type(int type); int parse_events_option(const struct option *opt, const char *str, int unset); int parse_events_option_new_evlist(const struct option *opt, const char *str, int unset); -int parse_events(struct evlist *evlist, const char *str, - struct parse_events_error *error); +int __parse_events(struct evlist *evlist, const char *str, struct parse_events_error *error, + struct perf_pmu *fake_pmu); + +static inline int parse_events(struct evlist *evlist, const char *str, + struct parse_events_error *err) +{ + return __parse_events(evlist, str, err, NULL); +} + int parse_events_terms(struct list_head *terms, const char *str); int parse_filter(const struct option *opt, const char *str, int unset); int exclude_perf(const struct option *opt, const char *arg, int unset); -- GitLab From e46fc8d9dd352c88fec49b140008958d2dc1efe1 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Tue, 9 Jun 2020 13:23:24 -0300 Subject: [PATCH 0059/2249] perf pmu: Add a perf_pmu__fake object to use with __parse_events() When wanting to use the support in __parse_events() for fake pmus, just pass it. Cc: Alexander Shishkin Cc: Andi Kleen Cc: Ian Rogers Cc: Jiri Olsa Cc: Michael Petlan Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Stephane Eranian Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/pmu.c | 2 ++ tools/perf/util/pmu.h | 2 ++ 2 files changed, 4 insertions(+) diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c index 93fe72a9dc0b2..6d51042044fd1 100644 --- a/tools/perf/util/pmu.c +++ b/tools/perf/util/pmu.c @@ -26,6 +26,8 @@ #include "strbuf.h" #include "fncache.h" +struct perf_pmu perf_pmu__fake; + struct perf_pmu_format { char *name; int value; diff --git a/tools/perf/util/pmu.h b/tools/perf/util/pmu.h index f971d9aa4570a..44ccbdbb1c374 100644 --- a/tools/perf/util/pmu.h +++ b/tools/perf/util/pmu.h @@ -43,6 +43,8 @@ struct perf_pmu { struct list_head list; /* ELEM */ }; +extern struct perf_pmu perf_pmu__fake; + struct perf_pmu_info { const char *unit; const char *metric_expr; -- GitLab From e1c92a7fbbc5668510736624df3028accd6af0ea Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Wed, 3 Jun 2020 12:51:15 -0300 Subject: [PATCH 0060/2249] perf tests: Add another metric parsing test The test goes through all metrics compiled for arch within pmu events and try to parse them. This test is different from 'test_parsing' in that we go through all the events in the current arch, not just one defined for current CPU model. Using 'fake_pmu' to parse events which do not have PMUs defined in the system. Say there's bad change in ivybridge metrics file, like: - a/tools/perf/pmu-events/arch/x86/ivybridge/ivb-metrics.json + b/tools/perf/pmu-events/arch/x86/ivybridge/ivb-metrics.json @@ -8,7 +8,7 @@ - "MetricExpr": "IDQ_UOPS_NOT_DELIVERED.CORE / (4 * (( + "MetricExpr": "IDQ_UOPS_NOT_DELIVERED.CORE / / (4 * the test fails with (on my kabylake laptop): $ perf test 'Parsing of PMU event table metrics with fake PMUs' -v parsing 'idq_uops_not_delivered.core / / (4 * (( ( cpu_clk_unh... syntax error, line 1 expr__parse failed test child finished with -1 ... The test also defines its own list of metrics and tries to parse them. It's handy for developing. Committer notes: Testing it: $ perf test fake 10: PMU events : 10.4: Parsing of PMU event table metrics with fake PMUs : FAILED! $ perf test -v fake |& tail parsing '(unc_p_freq_trans_cycles / unc_p_clockticks) * 100.' parsing '(unc_m_power_channel_ppd / unc_m_clockticks) * 100.' parsing '(unc_m_power_critical_throttle_cycles / unc_m_clockticks) * 100.' parsing '(unc_m_power_self_refresh / unc_m_clockticks) * 100.' parsing 'idq_uops_not_delivered.core / * (4 * cycles)' syntax error expr__parse failed test child finished with -1 ---- end ---- PMU events subtest 4: FAILED! $ And fix this error: tests/pmu-events.c:437:40: error: missing field 'idx' initializer [-Werror,-Wmissing-field-initializers] struct parse_events_error error = { 0 }; Signed-off-by: Jiri Olsa Tested-by: Arnaldo Carvalho de Melo Cc: Alexander Shishkin Cc: Andi Kleen Cc: Ian Rogers Cc: Ingo Molnar Cc: Michael Petlan Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lore.kernel.org/lkml/20200602214741.1218986-5-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/tests/pmu-events.c | 117 +++++++++++++++++++++++++++++++++- 1 file changed, 114 insertions(+), 3 deletions(-) diff --git a/tools/perf/tests/pmu-events.c b/tools/perf/tests/pmu-events.c index 82fa69a60ec8a..b66b021476ec4 100644 --- a/tools/perf/tests/pmu-events.c +++ b/tools/perf/tests/pmu-events.c @@ -390,7 +390,8 @@ static bool is_number(const char *str) return errno == 0 && end_ptr != str; } -static int check_parse_id(const char *id, struct parse_events_error *error) +static int check_parse_id(const char *id, struct parse_events_error *error, + struct perf_pmu *fake_pmu) { struct evlist *evlist; int ret; @@ -402,7 +403,7 @@ static int check_parse_id(const char *id, struct parse_events_error *error) evlist = evlist__new(); if (!evlist) return -ENOMEM; - ret = parse_events(evlist, id, error); + ret = __parse_events(evlist, id, error, fake_pmu); evlist__delete(evlist); return ret; } @@ -411,7 +412,7 @@ static int check_parse_cpu(const char *id, bool same_cpu, struct pmu_event *pe) { struct parse_events_error error = { .idx = 0, }; - int ret = check_parse_id(id, &error); + int ret = check_parse_id(id, &error, NULL); if (ret && same_cpu) { pr_warning("Parse event failed metric '%s' id '%s' expr '%s'\n", pe->metric_name, id, pe->metric_expr); @@ -429,6 +430,18 @@ static int check_parse_cpu(const char *id, bool same_cpu, struct pmu_event *pe) return ret; } +static int check_parse_fake(const char *id) +{ + struct parse_events_error error = { .idx = 0, }; + int ret = check_parse_id(id, &error, &perf_pmu__fake); + + free(error.str); + free(error.help); + free(error.first_str); + free(error.first_help); + return ret; +} + static void expr_failure(const char *msg, const struct pmu_events_map *map, const struct pmu_event *pe) @@ -498,6 +511,100 @@ static int test_parsing(void) return ret == 0 ? TEST_OK : TEST_SKIP; } +struct test_metric { + const char *str; +}; + +static struct test_metric metrics[] = { + { "(unc_p_power_state_occupancy.cores_c0 / unc_p_clockticks) * 100." }, + { "imx8_ddr0@read\\-cycles@ * 4 * 4", }, + { "imx8_ddr0@axid\\-read\\,axi_mask\\=0xffff\\,axi_id\\=0x0000@ * 4", }, + { "(cstate_pkg@c2\\-residency@ / msr@tsc@) * 100", }, + { "(imx8_ddr0@read\\-cycles@ + imx8_ddr0@write\\-cycles@)", }, +}; + +static int metric_parse_fake(const char *str) +{ + struct expr_parse_ctx ctx; + struct hashmap_entry *cur; + double result; + int ret = -1; + size_t bkt; + int i; + + pr_debug("parsing '%s'\n", str); + + expr__ctx_init(&ctx); + if (expr__find_other(str, NULL, &ctx, 0) < 0) { + pr_err("expr__find_other failed\n"); + return -1; + } + + /* + * Add all ids with a made up value. The value may + * trigger divide by zero when subtracted and so try to + * make them unique. + */ + i = 1; + hashmap__for_each_entry((&ctx.ids), cur, bkt) + expr__add_id(&ctx, strdup(cur->key), i++); + + hashmap__for_each_entry((&ctx.ids), cur, bkt) { + if (check_parse_fake(cur->key)) { + pr_err("check_parse_fake failed\n"); + goto out; + } + } + + if (expr__parse(&result, &ctx, str, 1)) + pr_err("expr__parse failed\n"); + else + ret = 0; + +out: + expr__ctx_clear(&ctx); + return ret; +} + +/* + * Parse all the metrics for current architecture, + * or all defined cpus via the 'fake_pmu' + * in parse_events. + */ +static int test_parsing_fake(void) +{ + struct pmu_events_map *map; + struct pmu_event *pe; + unsigned int i, j; + int err = 0; + + for (i = 0; i < ARRAY_SIZE(metrics); i++) { + err = metric_parse_fake(metrics[i].str); + if (err) + return err; + } + + i = 0; + for (;;) { + map = &pmu_events_map[i++]; + if (!map->table) + break; + j = 0; + for (;;) { + pe = &map->table[j++]; + if (!pe->name && !pe->metric_group && !pe->metric_name) + break; + if (!pe->metric_expr) + continue; + err = metric_parse_fake(pe->metric_expr); + if (err) + return err; + } + } + + return 0; +} + static const struct { int (*func)(void); const char *desc; @@ -514,6 +621,10 @@ static const struct { .func = test_parsing, .desc = "Parsing of PMU event table metrics", }, + { + .func = test_parsing_fake, + .desc = "Parsing of PMU event table metrics with fake PMUs", + }, }; const char *test__pmu_events_subtest_get_desc(int subtest) -- GitLab From 8b4468a2107af32b796fa818e5fb76481c39ee5a Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Tue, 2 Jun 2020 23:47:33 +0200 Subject: [PATCH 0061/2249] perf parse: Factor out parse_groups() function Factor out the parse_groups function, it will be used for new test interface coming in following changes. Signed-off-by: Jiri Olsa Acked-by: Ian Rogers Cc: Alexander Shishkin Cc: Andi Kleen Cc: Michael Petlan Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lore.kernel.org/lkml/20200602214741.1218986-6-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/metricgroup.c | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/tools/perf/util/metricgroup.c b/tools/perf/util/metricgroup.c index 9e21aa767e417..d72a565ec4835 100644 --- a/tools/perf/util/metricgroup.c +++ b/tools/perf/util/metricgroup.c @@ -709,14 +709,12 @@ static void metricgroup__free_egroups(struct list_head *group_list) } } -int metricgroup__parse_groups(const struct option *opt, - const char *str, - bool metric_no_group, - bool metric_no_merge, - struct rblist *metric_events) +static int parse_groups(struct evlist *perf_evlist, const char *str, + bool metric_no_group, + bool metric_no_merge, + struct rblist *metric_events) { struct parse_events_error parse_error; - struct evlist *perf_evlist = *(struct evlist **)opt->value; struct strbuf extra_events; LIST_HEAD(group_list); int ret; @@ -742,6 +740,18 @@ int metricgroup__parse_groups(const struct option *opt, return ret; } +int metricgroup__parse_groups(const struct option *opt, + const char *str, + bool metric_no_group, + bool metric_no_merge, + struct rblist *metric_events) +{ + struct evlist *perf_evlist = *(struct evlist **)opt->value; + + return parse_groups(perf_evlist, str, metric_no_group, + metric_no_merge, metric_events); +} + bool metricgroup__has_metric(const char *metric) { struct pmu_events_map *map = perf_pmu__find_map(NULL); -- GitLab From 68173bda6ac9d498e450276323f1c10a1d0307ad Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Tue, 9 Jun 2020 12:50:42 -0300 Subject: [PATCH 0062/2249] perf tools: Add fake_pmu to parse_group() function Allow to pass fake_pmu in parse_groups function so it can be used in parse_events call. It's will be passed by the upcoming metricgroup__parse_groups_test function. Committer notes: Made it a 'struct perf_pmu' pointer, in line with the changes at the start of this patchkit to avoid statics deep down in library code. Acked-by: Ian Rogers Cc: Alexander Shishkin Cc: Andi Kleen Cc: Ingo Molnar Cc: Michael Petlan Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lore.kernel.org/lkml/20200602214741.1218986-6-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/metricgroup.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tools/perf/util/metricgroup.c b/tools/perf/util/metricgroup.c index d72a565ec4835..49e6f7c6fb703 100644 --- a/tools/perf/util/metricgroup.c +++ b/tools/perf/util/metricgroup.c @@ -712,6 +712,7 @@ static void metricgroup__free_egroups(struct list_head *group_list) static int parse_groups(struct evlist *perf_evlist, const char *str, bool metric_no_group, bool metric_no_merge, + struct perf_pmu *fake_pmu, struct rblist *metric_events) { struct parse_events_error parse_error; @@ -727,7 +728,7 @@ static int parse_groups(struct evlist *perf_evlist, const char *str, return ret; pr_debug("adding %s\n", extra_events.buf); bzero(&parse_error, sizeof(parse_error)); - ret = parse_events(perf_evlist, extra_events.buf, &parse_error); + ret = __parse_events(perf_evlist, extra_events.buf, &parse_error, fake_pmu); if (ret) { parse_events_print_error(&parse_error, extra_events.buf); goto out; @@ -749,7 +750,7 @@ int metricgroup__parse_groups(const struct option *opt, struct evlist *perf_evlist = *(struct evlist **)opt->value; return parse_groups(perf_evlist, str, metric_no_group, - metric_no_merge, metric_events); + metric_no_merge, NULL, metric_events); } bool metricgroup__has_metric(const char *metric) -- GitLab From 1381396b0b778c918bf191b1960f92fbd563476d Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Tue, 9 Jun 2020 12:57:47 -0300 Subject: [PATCH 0063/2249] perf tools: Add map to parse_groups() function For testing purposes we need to pass our own map of events from parse_groups() through metricgroup__add_metric. Acked-by: Ian Rogers Cc: Alexander Shishkin Cc: Andi Kleen Cc: Ingo Molnar Cc: Michael Petlan Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lore.kernel.org/lkml/20200602214741.1218986-8-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/metricgroup.c | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/tools/perf/util/metricgroup.c b/tools/perf/util/metricgroup.c index 49e6f7c6fb703..f89f656c77577 100644 --- a/tools/perf/util/metricgroup.c +++ b/tools/perf/util/metricgroup.c @@ -597,17 +597,14 @@ static int __metricgroup__add_metric(struct list_head *group_list, static int metricgroup__add_metric(const char *metric, bool metric_no_group, struct strbuf *events, - struct list_head *group_list) + struct list_head *group_list, + struct pmu_events_map *map) { - struct pmu_events_map *map = perf_pmu__find_map(NULL); struct pmu_event *pe; struct egroup *eg; int i, ret; bool has_match = false; - if (!map) - return 0; - for (i = 0; ; i++) { pe = &map->table[i]; @@ -668,7 +665,8 @@ static int metricgroup__add_metric(const char *metric, bool metric_no_group, static int metricgroup__add_metric_list(const char *list, bool metric_no_group, struct strbuf *events, - struct list_head *group_list) + struct list_head *group_list, + struct pmu_events_map *map) { char *llist, *nlist, *p; int ret = -EINVAL; @@ -683,7 +681,7 @@ static int metricgroup__add_metric_list(const char *list, bool metric_no_group, while ((p = strsep(&llist, ",")) != NULL) { ret = metricgroup__add_metric(p, metric_no_group, events, - group_list); + group_list, map); if (ret == -EINVAL) { fprintf(stderr, "Cannot find metric or group `%s'\n", p); @@ -713,7 +711,8 @@ static int parse_groups(struct evlist *perf_evlist, const char *str, bool metric_no_group, bool metric_no_merge, struct perf_pmu *fake_pmu, - struct rblist *metric_events) + struct rblist *metric_events, + struct pmu_events_map *map) { struct parse_events_error parse_error; struct strbuf extra_events; @@ -723,7 +722,7 @@ static int parse_groups(struct evlist *perf_evlist, const char *str, if (metric_events->nr_entries == 0) metricgroup__rblist_init(metric_events); ret = metricgroup__add_metric_list(str, metric_no_group, - &extra_events, &group_list); + &extra_events, &group_list, map); if (ret) return ret; pr_debug("adding %s\n", extra_events.buf); @@ -748,9 +747,13 @@ int metricgroup__parse_groups(const struct option *opt, struct rblist *metric_events) { struct evlist *perf_evlist = *(struct evlist **)opt->value; + struct pmu_events_map *map = perf_pmu__find_map(NULL); + + if (!map) + return 0; return parse_groups(perf_evlist, str, metric_no_group, - metric_no_merge, NULL, metric_events); + metric_no_merge, NULL, metric_events, map); } bool metricgroup__has_metric(const char *metric) -- GitLab From f78ac00a8c999f4418e69e606485784fc5ff1d09 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Tue, 2 Jun 2020 23:47:36 +0200 Subject: [PATCH 0064/2249] perf tools: Add metricgroup__parse_groups_test function Add the metricgroup__parse_groups_test function. It will be used as test's interface to metric parsing in following changes. Signed-off-by: Jiri Olsa Acked-by: Ian Rogers Cc: Alexander Shishkin Cc: Andi Kleen Cc: Michael Petlan Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lore.kernel.org/lkml/20200602214741.1218986-9-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/metricgroup.c | 11 +++++++++++ tools/perf/util/metricgroup.h | 9 +++++++++ 2 files changed, 20 insertions(+) diff --git a/tools/perf/util/metricgroup.c b/tools/perf/util/metricgroup.c index f89f656c77577..edb13b8b7a57f 100644 --- a/tools/perf/util/metricgroup.c +++ b/tools/perf/util/metricgroup.c @@ -756,6 +756,17 @@ int metricgroup__parse_groups(const struct option *opt, metric_no_merge, NULL, metric_events, map); } +int metricgroup__parse_groups_test(struct evlist *evlist, + struct pmu_events_map *map, + const char *str, + bool metric_no_group, + bool metric_no_merge, + struct rblist *metric_events) +{ + return parse_groups(evlist, str, metric_no_group, + metric_no_merge, &perf_pmu__fake, metric_events, map); +} + bool metricgroup__has_metric(const char *metric) { struct pmu_events_map *map = perf_pmu__find_map(NULL); diff --git a/tools/perf/util/metricgroup.h b/tools/perf/util/metricgroup.h index 287850bcdeca1..426c824e20bf4 100644 --- a/tools/perf/util/metricgroup.h +++ b/tools/perf/util/metricgroup.h @@ -7,8 +7,10 @@ #include struct evsel; +struct evlist; struct option; struct rblist; +struct pmu_events_map; struct metric_event { struct rb_node nd; @@ -34,6 +36,13 @@ int metricgroup__parse_groups(const struct option *opt, bool metric_no_merge, struct rblist *metric_events); +int metricgroup__parse_groups_test(struct evlist *evlist, + struct pmu_events_map *map, + const char *str, + bool metric_no_group, + bool metric_no_merge, + struct rblist *metric_events); + void metricgroup__print(bool metrics, bool groups, char *filter, bool raw, bool details); bool metricgroup__has_metric(const char *metric); -- GitLab From 2cfaa853d8ead2fe4cd82986163b5cea21e300bd Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Tue, 2 Jun 2020 23:47:37 +0200 Subject: [PATCH 0065/2249] perf tools: Factor out prepare_metric function Factoring out prepare_metric function so it can be used in test interface coming in following changes. Signed-off-by: Jiri Olsa Acked-by: Ian Rogers Cc: Alexander Shishkin Cc: Andi Kleen Cc: Michael Petlan Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lore.kernel.org/lkml/20200602214741.1218986-10-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/stat-shadow.c | 53 ++++++++++++++++++++++------------- 1 file changed, 34 insertions(+), 19 deletions(-) diff --git a/tools/perf/util/stat-shadow.c b/tools/perf/util/stat-shadow.c index a7c13a88ecb9f..27be7ce2fff4e 100644 --- a/tools/perf/util/stat-shadow.c +++ b/tools/perf/util/stat-shadow.c @@ -730,25 +730,16 @@ static void print_smi_cost(struct perf_stat_config *config, out->print_metric(config, out->ctx, NULL, "%4.0f", "SMI#", smi_num); } -static void generic_metric(struct perf_stat_config *config, - const char *metric_expr, - struct evsel **metric_events, - char *name, - const char *metric_name, - const char *metric_unit, - int runtime, - int cpu, - struct perf_stat_output_ctx *out, - struct runtime_stat *st) +static int prepare_metric(struct evsel **metric_events, + struct expr_parse_ctx *pctx, + int cpu, + struct runtime_stat *st) { - print_metric_t print_metric = out->print_metric; - struct expr_parse_ctx pctx; - double ratio, scale; - int i; - void *ctxp = out->ctx; + double scale; char *n, *pn; + int i; - expr__ctx_init(&pctx); + expr__ctx_init(pctx); for (i = 0; metric_events[i]; i++) { struct saved_value *v; struct stats *stats; @@ -771,7 +762,7 @@ static void generic_metric(struct perf_stat_config *config, n = strdup(metric_events[i]->name); if (!n) - return; + return -ENOMEM; /* * This display code with --no-merge adds [cpu] postfixes. * These are not supported by the parser. Remove everything @@ -782,11 +773,35 @@ static void generic_metric(struct perf_stat_config *config, *pn = 0; if (metric_total) - expr__add_id(&pctx, n, metric_total); + expr__add_id(pctx, n, metric_total); else - expr__add_id(&pctx, n, avg_stats(stats)*scale); + expr__add_id(pctx, n, avg_stats(stats)*scale); } + return i; +} + +static void generic_metric(struct perf_stat_config *config, + const char *metric_expr, + struct evsel **metric_events, + char *name, + const char *metric_name, + const char *metric_unit, + int runtime, + int cpu, + struct perf_stat_output_ctx *out, + struct runtime_stat *st) +{ + print_metric_t print_metric = out->print_metric; + struct expr_parse_ctx pctx; + double ratio, scale; + int i; + void *ctxp = out->ctx; + + i = prepare_metric(metric_events, &pctx, cpu, st); + if (i < 0) + return; + if (!metric_events[i]) { if (expr__parse(&ratio, &pctx, metric_expr, runtime) == 0) { char *unit; -- GitLab From 9afe5658a6fa89f59f01d2857d78203cc8665f1c Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Tue, 2 Jun 2020 23:47:38 +0200 Subject: [PATCH 0066/2249] perf tools: Release metric_events rblist We don't release metric_events rblist, add the missing delete hook and call the release before leaving cmd_stat. Signed-off-by: Jiri Olsa Acked-by: Ian Rogers Cc: Alexander Shishkin Cc: Andi Kleen Cc: Michael Petlan Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lore.kernel.org/lkml/20200602214741.1218986-11-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-stat.c | 1 + tools/perf/util/metricgroup.c | 19 +++++++++++++++++++ tools/perf/util/metricgroup.h | 1 + 3 files changed, 21 insertions(+) diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index 9be020e0098ad..911b9c3538a2d 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -2307,6 +2307,7 @@ int cmd_stat(int argc, const char **argv) evlist__delete(evsel_list); + metricgroup__rblist_exit(&stat_config.metric_events); runtime_stat_delete(&stat_config); return status; diff --git a/tools/perf/util/metricgroup.c b/tools/perf/util/metricgroup.c index edb13b8b7a57f..82fecb5a302df 100644 --- a/tools/perf/util/metricgroup.c +++ b/tools/perf/util/metricgroup.c @@ -76,11 +76,30 @@ static struct rb_node *metric_event_new(struct rblist *rblist __maybe_unused, return &me->nd; } +static void metric_event_delete(struct rblist *rblist __maybe_unused, + struct rb_node *rb_node) +{ + struct metric_event *me = container_of(rb_node, struct metric_event, nd); + struct metric_expr *expr, *tmp; + + list_for_each_entry_safe(expr, tmp, &me->head, nd) { + free(expr); + } + + free(me); +} + static void metricgroup__rblist_init(struct rblist *metric_events) { rblist__init(metric_events); metric_events->node_cmp = metric_event_cmp; metric_events->node_new = metric_event_new; + metric_events->node_delete = metric_event_delete; +} + +void metricgroup__rblist_exit(struct rblist *metric_events) +{ + rblist__exit(metric_events); } struct egroup { diff --git a/tools/perf/util/metricgroup.h b/tools/perf/util/metricgroup.h index 426c824e20bf4..8315bd1a7da47 100644 --- a/tools/perf/util/metricgroup.h +++ b/tools/perf/util/metricgroup.h @@ -47,4 +47,5 @@ void metricgroup__print(bool metrics, bool groups, char *filter, bool raw, bool details); bool metricgroup__has_metric(const char *metric); int arch_get_runtimeparam(void); +void metricgroup__rblist_exit(struct rblist *metric_events); #endif -- GitLab From 6d432c4c8aa5660d8f9f43326db8350b48dcb6f5 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Tue, 2 Jun 2020 23:47:39 +0200 Subject: [PATCH 0067/2249] perf tools: Add test_generic_metric function Adding test_generic_metric that prepares and runs given metric over the data from struct runtime_stat object. Signed-off-by: Jiri Olsa Acked-by: Ian Rogers Cc: Alexander Shishkin Cc: Andi Kleen Cc: Michael Petlan Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lore.kernel.org/lkml/20200602214741.1218986-12-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/stat-shadow.c | 14 ++++++++++++++ tools/perf/util/stat.h | 3 +++ 2 files changed, 17 insertions(+) diff --git a/tools/perf/util/stat-shadow.c b/tools/perf/util/stat-shadow.c index 27be7ce2fff4e..8fdef47005e60 100644 --- a/tools/perf/util/stat-shadow.c +++ b/tools/perf/util/stat-shadow.c @@ -842,6 +842,20 @@ static void generic_metric(struct perf_stat_config *config, expr__ctx_clear(&pctx); } +double test_generic_metric(struct metric_expr *mexp, int cpu, struct runtime_stat *st) +{ + struct expr_parse_ctx pctx; + double ratio; + + if (prepare_metric(mexp->metric_events, &pctx, cpu, st) < 0) + return 0.; + + if (expr__parse(&ratio, &pctx, mexp->metric_expr, 1)) + return 0.; + + return ratio; +} + void perf_stat__print_shadow_stats(struct perf_stat_config *config, struct evsel *evsel, double avg, int cpu, diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h index f75ae679eb281..6911c7249199a 100644 --- a/tools/perf/util/stat.h +++ b/tools/perf/util/stat.h @@ -230,4 +230,7 @@ perf_evlist__print_counters(struct evlist *evlist, struct target *_target, struct timespec *ts, int argc, const char **argv); + +struct metric_expr; +double test_generic_metric(struct metric_expr *mexp, int cpu, struct runtime_stat *st); #endif -- GitLab From 0a507af9c681ac2adedc5fe1b2d534e27be85446 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Tue, 2 Jun 2020 23:47:40 +0200 Subject: [PATCH 0068/2249] perf tests: Add parse metric test for ipc metric Adding new test that process metrics code and checks the expected results. Starting with easy ipc metric. Committer testing: # perf test "Parse and process metrics" 67: Parse and process metrics : Ok # # perf test -v "Parse and process metrics" 67: Parse and process metrics : --- start --- test child forked, pid 103402 metric expr inst_retired.any / cpu_clk_unhalted.thread for IPC found event inst_retired.any found event cpu_clk_unhalted.thread adding {inst_retired.any,cpu_clk_unhalted.thread}:W test child finished with 0 ---- end ---- Parse and process metrics: Ok # Had to fix it to initialize that 'struct value' array sentinel with a named initializer to fix the build with some versions of clang: tests/parse-metric.c:135:7: error: missing field 'val' initializer [-Werror,-Wmissing-field-initializers] { 0 }, Signed-off-by: Jiri Olsa Acked-by: Ian Rogers Tested-by: Arnaldo Carvalho de Melo Cc: Alexander Shishkin Cc: Andi Kleen Cc: Michael Petlan Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lore.kernel.org/lkml/20200602214741.1218986-13-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/tests/Build | 1 + tools/perf/tests/builtin-test.c | 4 + tools/perf/tests/parse-metric.c | 145 ++++++++++++++++++++++++++++++++ tools/perf/tests/tests.h | 1 + 4 files changed, 151 insertions(+) create mode 100644 tools/perf/tests/parse-metric.c diff --git a/tools/perf/tests/Build b/tools/perf/tests/Build index cd00498a5dce6..84352fc49a205 100644 --- a/tools/perf/tests/Build +++ b/tools/perf/tests/Build @@ -59,6 +59,7 @@ perf-y += genelf.o perf-y += api-io.o perf-y += demangle-java-test.o perf-y += pfm.o +perf-y += parse-metric.o $(OUTPUT)tests/llvm-src-base.c: tests/bpf-script-example.c tests/Build $(call rule_mkdir) diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c index da5b6cc23f25b..d328caaba45d4 100644 --- a/tools/perf/tests/builtin-test.c +++ b/tools/perf/tests/builtin-test.c @@ -337,6 +337,10 @@ static struct test generic_tests[] = { .desc = "Demangle Java", .func = test__demangle_java, }, + { + .desc = "Parse and process metrics", + .func = test__parse_metric, + }, { .func = NULL, }, diff --git a/tools/perf/tests/parse-metric.c b/tools/perf/tests/parse-metric.c new file mode 100644 index 0000000000000..79d956dc6a74a --- /dev/null +++ b/tools/perf/tests/parse-metric.c @@ -0,0 +1,145 @@ +// SPDX-License-Identifier: GPL-2.0 +#include +#include +#include +#include +#include "metricgroup.h" +#include "tests.h" +#include "pmu-events/pmu-events.h" +#include "evlist.h" +#include "rblist.h" +#include "debug.h" +#include "expr.h" +#include "stat.h" + +static struct pmu_event pme_test[] = { +{ + .metric_expr = "inst_retired.any / cpu_clk_unhalted.thread", + .metric_name = "IPC", +}, +}; + +static struct pmu_events_map map = { + .cpuid = "test", + .version = "1", + .type = "core", + .table = pme_test, +}; + +struct value { + const char *event; + u64 val; +}; + +static u64 find_value(const char *name, struct value *values) +{ + struct value *v = values; + + while (v->event) { + if (!strcmp(name, v->event)) + return v->val; + v++; + }; + return 0; +} + +static void load_runtime_stat(struct runtime_stat *st, struct evlist *evlist, + struct value *vals) +{ + struct evsel *evsel; + u64 count; + + evlist__for_each_entry(evlist, evsel) { + count = find_value(evsel->name, vals); + perf_stat__update_shadow_stats(evsel, count, 0, st); + } +} + +static double compute_single(struct rblist *metric_events, struct evlist *evlist, + struct runtime_stat *st) +{ + struct evsel *evsel = evlist__first(evlist); + struct metric_event *me; + + me = metricgroup__lookup(metric_events, evsel, false); + if (me != NULL) { + struct metric_expr *mexp; + + mexp = list_first_entry(&me->head, struct metric_expr, nd); + return test_generic_metric(mexp, 0, st); + } + return 0.; +} + +static int compute_metric(const char *name, struct value *vals, double *ratio) +{ + struct rblist metric_events = { + .nr_entries = 0, + }; + struct perf_cpu_map *cpus; + struct runtime_stat st; + struct evlist *evlist; + int err; + + /* + * We need to prepare evlist for stat mode running on CPU 0 + * because that's where all the stats are going to be created. + */ + evlist = evlist__new(); + if (!evlist) + return -ENOMEM; + + cpus = perf_cpu_map__new("0"); + if (!cpus) + return -ENOMEM; + + perf_evlist__set_maps(&evlist->core, cpus, NULL); + + /* Parse the metric into metric_events list. */ + err = metricgroup__parse_groups_test(evlist, &map, name, + false, false, + &metric_events); + + TEST_ASSERT_VAL("failed to parse metric", err == 0); + + if (perf_evlist__alloc_stats(evlist, false)) + return -1; + + /* Load the runtime stats with given numbers for events. */ + runtime_stat__init(&st); + load_runtime_stat(&st, evlist, vals); + + /* And execute the metric */ + *ratio = compute_single(&metric_events, evlist, &st); + + /* ... clenup. */ + metricgroup__rblist_exit(&metric_events); + runtime_stat__exit(&st); + perf_evlist__free_stats(evlist); + perf_cpu_map__put(cpus); + evlist__delete(evlist); + return 0; +} + +static int test_ipc(void) +{ + double ratio; + struct value vals[] = { + { .event = "inst_retired.any", .val = 300 }, + { .event = "cpu_clk_unhalted.thread", .val = 200 }, + { .event = NULL, }, + }; + + TEST_ASSERT_VAL("failed to compute metric", + compute_metric("IPC", vals, &ratio) == 0); + + TEST_ASSERT_VAL("IPC failed, wrong ratio", + ratio == 1.5); + return 0; +} + +int test__parse_metric(struct test *test __maybe_unused, int subtest __maybe_unused) +{ + TEST_ASSERT_VAL("IPC failed", test_ipc() == 0); + return 0; +} diff --git a/tools/perf/tests/tests.h b/tools/perf/tests/tests.h index 76a4e352eaaf7..4447a516c6897 100644 --- a/tools/perf/tests/tests.h +++ b/tools/perf/tests/tests.h @@ -121,6 +121,7 @@ int test__demangle_java(struct test *test, int subtest); int test__pfm(struct test *test, int subtest); const char *test__pfm_subtest_get_desc(int subtest); int test__pfm_subtest_get_nr(void); +int test__parse_metric(struct test *test, int subtest); bool test__bp_signal_is_supported(void); bool test__bp_account_is_supported(void); -- GitLab From 218ca91df47712a7b2b5a554e39c4a2c819a9e86 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Tue, 2 Jun 2020 23:47:41 +0200 Subject: [PATCH 0069/2249] perf tests: Add parse metric test for frontend metric Adding new metric test for frontend metric. It's stolen from x86 pmu events. Committer testing: # perf test "Parse and process metrics" 67: Parse and process metrics : Ok # perf test -v "Parse and process metrics" # 67: Parse and process metrics : --- start --- test child forked, pid 104881 metric expr inst_retired.any / cpu_clk_unhalted.thread for IPC found event inst_retired.any found event cpu_clk_unhalted.thread adding {inst_retired.any,cpu_clk_unhalted.thread}:W metric expr idq_uops_not_delivered.core / (4 * (( ( cpu_clk_unhalted.thread / 2 ) * ( 1 + cpu_clk_unhalted.one_thread_active / cpu_clk_unhalted.ref_xclk ) ))) for Frontend_Bound_SMT found event cpu_clk_unhalted.one_thread_active found event cpu_clk_unhalted.ref_xclk found event idq_uops_not_delivered.core found event cpu_clk_unhalted.thread adding {cpu_clk_unhalted.one_thread_active,cpu_clk_unhalted.ref_xclk,idq_uops_not_delivered.core,cpu_clk_unhalted.thread}:W test child finished with 0 ---- end ---- Parse and process metrics: Ok # Had to fix it to initialize that 'struct value' array sentinel with a named initializer to fix the build with some versions of clang: tests/parse-metric.c:154:7: error: missing field 'val' initializer [-Werror,-Wmissing-field-initializers] { 0 }, Signed-off-by: Jiri Olsa Acked-by: Ian Rogers Tested-by: Arnaldo Carvalho de Melo Cc: Alexander Shishkin Cc: Andi Kleen Cc: Michael Petlan Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lore.kernel.org/lkml/20200602214741.1218986-14-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/tests/parse-metric.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/tools/perf/tests/parse-metric.c b/tools/perf/tests/parse-metric.c index 79d956dc6a74a..8c48251425e1c 100644 --- a/tools/perf/tests/parse-metric.c +++ b/tools/perf/tests/parse-metric.c @@ -17,6 +17,11 @@ static struct pmu_event pme_test[] = { .metric_expr = "inst_retired.any / cpu_clk_unhalted.thread", .metric_name = "IPC", }, +{ + .metric_expr = "idq_uops_not_delivered.core / (4 * (( ( cpu_clk_unhalted.thread / 2 ) * " + "( 1 + cpu_clk_unhalted.one_thread_active / cpu_clk_unhalted.ref_xclk ) )))", + .metric_name = "Frontend_Bound_SMT", +}, }; static struct pmu_events_map map = { @@ -138,8 +143,28 @@ static int test_ipc(void) return 0; } +static int test_frontend(void) +{ + double ratio; + struct value vals[] = { + { .event = "idq_uops_not_delivered.core", .val = 300 }, + { .event = "cpu_clk_unhalted.thread", .val = 200 }, + { .event = "cpu_clk_unhalted.one_thread_active", .val = 400 }, + { .event = "cpu_clk_unhalted.ref_xclk", .val = 600 }, + { .event = NULL, }, + }; + + TEST_ASSERT_VAL("failed to compute metric", + compute_metric("Frontend_Bound_SMT", vals, &ratio) == 0); + + TEST_ASSERT_VAL("Frontend_Bound_SMT failed, wrong ratio", + ratio == 0.45); + return 0; +} + int test__parse_metric(struct test *test __maybe_unused, int subtest __maybe_unused) { TEST_ASSERT_VAL("IPC failed", test_ipc() == 0); + TEST_ASSERT_VAL("frontend failed", test_frontend() == 0); return 0; } -- GitLab From afdd63f5933b3c970438e8ab6bb0cd9f392f3bf6 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Wed, 10 Jun 2020 11:39:16 -0300 Subject: [PATCH 0070/2249] perf script: Fixup some evsel/evlist method names Fixups related to the introduction of libperf, where the perf_{evsel,evlist}__ prefix is reserved for functions operating on struct perf_{evsel,evlist}. Cc: Adrian Hunter Cc: Jiri Olsa Cc: Namhyung Kim Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-script.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c index 181d65e5a4505..1ff6a8a8dde51 100644 --- a/tools/perf/builtin-script.c +++ b/tools/perf/builtin-script.c @@ -388,7 +388,7 @@ static int evsel__check_stype(struct evsel *evsel, u64 sample_type, const char * return evsel__do_check_stype(evsel, sample_type, sample_msg, field, false); } -static int perf_evsel__check_attr(struct evsel *evsel, struct perf_session *session) +static int evsel__check_attr(struct evsel *evsel, struct perf_session *session) { struct perf_event_attr *attr = &evsel->core.attr; bool allow_user_set; @@ -522,7 +522,7 @@ static int perf_session__check_output_opt(struct perf_session *session) } if (evsel && output[j].fields && - perf_evsel__check_attr(evsel, session)) + evsel__check_attr(evsel, session)) return -1; if (evsel == NULL) @@ -1692,7 +1692,7 @@ struct perf_script { int range_num; }; -static int perf_evlist__max_name_len(struct evlist *evlist) +static int evlist__max_name_len(struct evlist *evlist) { struct evsel *evsel; int max = 0; @@ -1875,7 +1875,7 @@ static void process_event(struct perf_script *script, const char *evname = evsel__name(evsel); if (!script->name_width) - script->name_width = perf_evlist__max_name_len(script->session->evlist); + script->name_width = evlist__max_name_len(script->session->evlist); fprintf(fp, "%*s: ", script->name_width, evname ?: "[unknown]"); } @@ -2120,7 +2120,7 @@ static int process_attr(struct perf_tool *tool, union perf_event *event, } if (evsel->core.attr.sample_type) { - err = perf_evsel__check_attr(evsel, scr->session); + err = evsel__check_attr(evsel, scr->session); if (err) return err; } -- GitLab From 3e21a28a01e227726456a51933ed004c2df31850 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Wed, 10 Jun 2020 16:58:22 -0700 Subject: [PATCH 0071/2249] perf expr: Add d_ratio operation d_ratio avoids division by 0 yielding infinity, such as when a counter doesn't get scheduled. An example usage is: { "BriefDescription": "DCache L1 misses", "MetricExpr": "d_ratio(MEM_LOAD_RETIRED.L1_MISS, MEM_LOAD_RETIRED.L1_HIT + MEM_LOAD_RETIRED.L1_MISS + MEM_LOAD_RETIRED.FB_HIT)", "MetricGroup": "DCache;DCache_L1", "MetricName": "DCache_L1_Miss", "ScaleUnit": "100%", } Signed-off-by: Ian Rogers Acked-by: Jiri Olsa Cc: Alexander Shishkin Cc: Andi Kleen Cc: Jin Yao Cc: John Garry Cc: Kajol Jain Cc: Mark Rutland Cc: Namhyung Kim Cc: Paul Clarke Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lore.kernel.org/lkml/20200610235823.52557-1-irogers@google.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/tests/expr.c | 2 ++ tools/perf/util/expr.l | 1 + tools/perf/util/expr.y | 14 ++++++++++++-- 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/tools/perf/tests/expr.c b/tools/perf/tests/expr.c index 1cb02ca2b15fb..c4877b36ab58b 100644 --- a/tools/perf/tests/expr.c +++ b/tools/perf/tests/expr.c @@ -39,6 +39,8 @@ int test__expr(struct test *t __maybe_unused, int subtest __maybe_unused) ret |= test(&ctx, "1+1 if 3*4 else 0", 2); ret |= test(&ctx, "1.1 + 2.1", 3.2); ret |= test(&ctx, ".1 + 2.", 2.1); + ret |= test(&ctx, "d_ratio(1, 2)", 0.5); + ret |= test(&ctx, "d_ratio(2.5, 0)", 0); if (ret) return ret; diff --git a/tools/perf/util/expr.l b/tools/perf/util/expr.l index f397bf8b1a48e..298d86660a969 100644 --- a/tools/perf/util/expr.l +++ b/tools/perf/util/expr.l @@ -100,6 +100,7 @@ symbol ({spec}|{sym})+ } } +d_ratio { return D_RATIO; } max { return MAX; } min { return MIN; } if { return IF; } diff --git a/tools/perf/util/expr.y b/tools/perf/util/expr.y index bf3e898e30554..fe145344bb393 100644 --- a/tools/perf/util/expr.y +++ b/tools/perf/util/expr.y @@ -10,6 +10,14 @@ #include "smt.h" #include +static double d_ratio(double val0, double val1) +{ + if (val1 == 0) { + return 0; + } + return val0 / val1; +} + %} %define api.pure full @@ -28,7 +36,7 @@ %token NUMBER %token ID %destructor { free ($$); } -%token MIN MAX IF ELSE SMT_ON +%token MIN MAX IF ELSE SMT_ON D_RATIO %left MIN MAX IF %left '|' %left '^' @@ -64,7 +72,8 @@ other: ID } | MIN | MAX | IF | ELSE | SMT_ON | NUMBER | '|' | '^' | '&' | '-' | '+' | '*' | '/' | '%' | '(' | ')' | ',' - +| +D_RATIO all_expr: if_expr { *final_val = $1; } ; @@ -105,6 +114,7 @@ expr: NUMBER | MIN '(' expr ',' expr ')' { $$ = $3 < $5 ? $3 : $5; } | MAX '(' expr ',' expr ')' { $$ = $3 > $5 ? $3 : $5; } | SMT_ON { $$ = smt_on() > 0; } + | D_RATIO '(' expr ',' expr ')' { $$ = d_ratio($3,$5); } ; %% -- GitLab From ff1a12f962dff5b490c5ce1c2c4bcd0bf3bf517d Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Wed, 10 Jun 2020 16:58:23 -0700 Subject: [PATCH 0072/2249] perf expr: Add < and > operators These are broadly useful but required to handle TMA metrics. For example encoding Ports_Utilization from: https://download.01.org/perfmon/TMA_Metrics.csv requires '<'. { "BriefDescription": "This metric estimates fraction of cycles the CPU performance was potentially limited due to Core computation issues (non divider-related). Two distinct categories can be attributed into this metric: (1) heavy data-dependency among contiguous instructions would manifest in this metric - such cases are often referred to as low Instruction Level Parallelism (ILP). (2) Contention on some hardware execution unit other than Divider. For example; when there are too many multiply operations.", "MetricExpr": "( ( cpu@EXE_ACTIVITY.EXE_BOUND_0_PORTS@ + cpu@EXE_ACTIVITY.1_PORTS_UTIL@ + ( cpu@EXE_ACTIVITY.2_PORTS_UTIL@ * ( ( ( cpu@UOPS_RETIRED.RETIRE_SLOTS@ ) / ( cpu@CPU_CLK_UNHALTED.THREAD@ ) ) / ( ( 4.000000 ) + 1.000000 ) ) ) ) / ( cpu@CPU_CLK_UNHALTED.THREAD@ ) if ( cpu@ARITH.DIVIDER_ACTIVE\\,cmask\\=1@ < cpu@EXE_ACTIVITY.EXE_BOUND_0_PORTS@ ) else ( ( cpu@EXE_ACTIVITY.EXE_BOUND_0_PORTS@ + cpu@EXE_ACTIVITY.1_PORTS_UTIL@ + ( cpu@EXE_ACTIVITY.2_PORTS_UTIL@ * ( ( ( cpu@UOPS_RETIRED.RETIRE_SLOTS@ ) / ( cpu@CPU_CLK_UNHALTED.THREAD@ ) ) / ( ( 4.000000 ) + 1.000000 ) ) ) ) - cpu@EXE_ACTIVITY.EXE_BOUND_0_PORTS@ ) / ( cpu@CPU_CLK_UNHALTED.THREAD@ ) )", "MetricGroup": "Topdown_Group_Ports_Utilization", "MetricName": "Topdown_Metric_Ports_Utilization" }, Signed-off-by: Ian Rogers Acked-by: Jiri Olsa Cc: Alexander Shishkin Cc: Andi Kleen Cc: Jin Yao Cc: John Garry Cc: Kajol Jain Cc: Mark Rutland Cc: Namhyung Kim Cc: Paul Clarke Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lore.kernel.org/lkml/20200610235823.52557-2-irogers@google.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/tests/expr.c | 6 ++++++ tools/perf/util/expr.l | 2 ++ tools/perf/util/expr.y | 5 ++++- 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/tools/perf/tests/expr.c b/tools/perf/tests/expr.c index c4877b36ab58b..b7e5ef3007fc1 100644 --- a/tools/perf/tests/expr.c +++ b/tools/perf/tests/expr.c @@ -41,6 +41,12 @@ int test__expr(struct test *t __maybe_unused, int subtest __maybe_unused) ret |= test(&ctx, ".1 + 2.", 2.1); ret |= test(&ctx, "d_ratio(1, 2)", 0.5); ret |= test(&ctx, "d_ratio(2.5, 0)", 0); + ret |= test(&ctx, "1.1 < 2.2", 1); + ret |= test(&ctx, "2.2 > 1.1", 1); + ret |= test(&ctx, "1.1 < 1.1", 0); + ret |= test(&ctx, "2.2 > 2.2", 0); + ret |= test(&ctx, "2.2 < 1.1", 0); + ret |= test(&ctx, "1.1 > 2.2", 0); if (ret) return ret; diff --git a/tools/perf/util/expr.l b/tools/perf/util/expr.l index 298d86660a969..13e5e3c75f563 100644 --- a/tools/perf/util/expr.l +++ b/tools/perf/util/expr.l @@ -111,6 +111,8 @@ else { return ELSE; } "|" { return '|'; } "^" { return '^'; } "&" { return '&'; } +"<" { return '<'; } +">" { return '>'; } "-" { return '-'; } "+" { return '+'; } "*" { return '*'; } diff --git a/tools/perf/util/expr.y b/tools/perf/util/expr.y index fe145344bb393..5fcb98800f9c1 100644 --- a/tools/perf/util/expr.y +++ b/tools/perf/util/expr.y @@ -41,6 +41,7 @@ static double d_ratio(double val0, double val1) %left '|' %left '^' %left '&' +%left '<' '>' %left '-' '+' %left '*' '/' '%' %left NEG NOT @@ -73,7 +74,7 @@ other: ID | MIN | MAX | IF | ELSE | SMT_ON | NUMBER | '|' | '^' | '&' | '-' | '+' | '*' | '/' | '%' | '(' | ')' | ',' | -D_RATIO +'<' | '>' | D_RATIO all_expr: if_expr { *final_val = $1; } ; @@ -94,6 +95,8 @@ expr: NUMBER | expr '|' expr { $$ = (long)$1 | (long)$3; } | expr '&' expr { $$ = (long)$1 & (long)$3; } | expr '^' expr { $$ = (long)$1 ^ (long)$3; } + | expr '<' expr { $$ = $1 < $3; } + | expr '>' expr { $$ = $1 > $3; } | expr '+' expr { $$ = $1 + $3; } | expr '-' expr { $$ = $1 - $3; } | expr '*' expr { $$ = $1 * $3; } -- GitLab From 47446212832871e66f3b5fbf021c148eced2e24c Mon Sep 17 00:00:00 2001 From: Mike Leach Date: Tue, 16 Jun 2020 17:40:41 +0100 Subject: [PATCH 0073/2249] perf cs-etm: Allow no CoreSight sink to be specified on command line Adjust the handling of the session sink selection to allow no sink to be selected on the command line. This then forwards the sink selection to the CoreSight infrastructure which will attempt to select a sink based on the default sink select priorities. Signed-off-by: Mike Leach Tested-by: Leo Yan Cc: Mathieu Poirier Cc: Peter Zijlstra Cc: Suzuki Poulouse Cc: coresight@lists.linaro.org Cc: linux-arm-kernel@lists.infradead.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/arch/arm/util/cs-etm.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/perf/arch/arm/util/cs-etm.c b/tools/perf/arch/arm/util/cs-etm.c index cea5e33d61d2b..cad7bf7834138 100644 --- a/tools/perf/arch/arm/util/cs-etm.c +++ b/tools/perf/arch/arm/util/cs-etm.c @@ -243,10 +243,10 @@ static int cs_etm_set_sink_attr(struct perf_pmu *pmu, } /* - * No sink was provided on the command line - for _now_ treat - * this as an error. + * No sink was provided on the command line - allow the CoreSight + * system to look for a default */ - return ret; + return 0; } static int cs_etm_recording_options(struct auxtrace_record *itr, -- GitLab From c1b4745b48b3c5a29df6ef2b68384e7cccdc3691 Mon Sep 17 00:00:00 2001 From: John Garry Date: Wed, 17 Jun 2020 17:01:53 +0800 Subject: [PATCH 0074/2249] perf pmu: List kernel supplied event aliases for arm64 In commit dc098b35b56f ("perf list: List kernel supplied event aliases"), the aliases for events are supplied in addition to CPU event in perf list. This relies on the name of the core PMU being "cpu", which is not the case for arm64, so arm64 has always missed this. Use generic is_pmu_core() helper which takes account of arm64 to make this feature work for arm64 (and possibly other archs). Sample, before: armv8_pmuv3_0/br_mis_pred/ [Kernel PMU event] after: br_mis_pred OR armv8_pmuv3_0/br_mis_pred/ [Kernel PMU event] Signed-off-by: John Garry Acked-by: Jiri Olsa Acked-by: Namhyung Kim Cc: Alexander Shishkin Cc: Andi Kleen Cc: Ian Rogers Cc: Mark Rutland Cc: Peter Zijlstra Cc: Will Deacon Cc: linux-arm-kernel@lists.infradead.org Cc: linuxarm@huawei.com Link: http://lore.kernel.org/lkml/1592384514-119954-2-git-send-email-john.garry@huawei.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/pmu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c index 6d51042044fd1..d039879bd9141 100644 --- a/tools/perf/util/pmu.c +++ b/tools/perf/util/pmu.c @@ -1477,7 +1477,7 @@ void print_pmu_events(const char *event_glob, bool name_only, bool quiet_flag, list_for_each_entry(alias, &pmu->aliases, list) { char *name = alias->desc ? alias->name : format_alias(buf, sizeof(buf), pmu, alias); - bool is_cpu = !strcmp(pmu->name, "cpu"); + bool is_cpu = is_pmu_core(pmu->name); if (alias->deprecated && !deprecated) continue; -- GitLab From ce0dc7d22271fa7eac3875fc9b57772742b8245e Mon Sep 17 00:00:00 2001 From: John Garry Date: Wed, 17 Jun 2020 17:01:54 +0800 Subject: [PATCH 0075/2249] perf pmu: Improve CPU core PMU HW event list ordering For perf list, the CPU core PMU HW event ordering is such that not all events may will be listed adjacent - consider this example: $ tools/perf/perf list List of pre-defined events (to be used in -e): duration_time [Tool event] branch-instructions OR cpu/branch-instructions/ [Kernel PMU event] branch-misses OR cpu/branch-misses/ [Kernel PMU event] bus-cycles OR cpu/bus-cycles/ [Kernel PMU event] cache-misses OR cpu/cache-misses/ [Kernel PMU event] cache-references OR cpu/cache-references/ [Kernel PMU event] cpu-cycles OR cpu/cpu-cycles/ [Kernel PMU event] cstate_core/c3-residency/ [Kernel PMU event] cstate_core/c6-residency/ [Kernel PMU event] cstate_core/c7-residency/ [Kernel PMU event] cstate_pkg/c2-residency/ [Kernel PMU event] cstate_pkg/c3-residency/ [Kernel PMU event] cstate_pkg/c6-residency/ [Kernel PMU event] cstate_pkg/c7-residency/ [Kernel PMU event] cycles-ct OR cpu/cycles-ct/ [Kernel PMU event] cycles-t OR cpu/cycles-t/ [Kernel PMU event] el-abort OR cpu/el-abort/ [Kernel PMU event] el-capacity OR cpu/el-capacity/ [Kernel PMU event] Notice in the above example how the cstate_core PMU events are mixed in the middle of the CPU core events. For my arm64 platform, all the uncore events get mixed in, making the list very disorganised: page-faults OR faults [Software event] task-clock [Software event] duration_time [Tool event] L1-dcache-load-misses [Hardware cache event] L1-dcache-loads [Hardware cache event] L1-icache-load-misses [Hardware cache event] L1-icache-loads [Hardware cache event] branch-load-misses [Hardware cache event] branch-loads [Hardware cache event] dTLB-load-misses [Hardware cache event] dTLB-loads [Hardware cache event] iTLB-load-misses [Hardware cache event] iTLB-loads [Hardware cache event] br_mis_pred OR armv8_pmuv3_0/br_mis_pred/ [Kernel PMU event] br_mis_pred_retired OR armv8_pmuv3_0/br_mis_pred_retired/ [Kernel PMU event] br_pred OR armv8_pmuv3_0/br_pred/ [Kernel PMU event] br_retired OR armv8_pmuv3_0/br_retired/ [Kernel PMU event] br_return_retired OR armv8_pmuv3_0/br_return_retired/ [Kernel PMU event] bus_access OR armv8_pmuv3_0/bus_access/ [Kernel PMU event] bus_cycles OR armv8_pmuv3_0/bus_cycles/ [Kernel PMU event] cid_write_retired OR armv8_pmuv3_0/cid_write_retired/ [Kernel PMU event] cpu_cycles OR armv8_pmuv3_0/cpu_cycles/ [Kernel PMU event] dtlb_walk OR armv8_pmuv3_0/dtlb_walk/ [Kernel PMU event] exc_return OR armv8_pmuv3_0/exc_return/ [Kernel PMU event] exc_taken OR armv8_pmuv3_0/exc_taken/ [Kernel PMU event] hisi_sccl1_ddrc0/act_cmd/ [Kernel PMU event] hisi_sccl1_ddrc0/flux_rcmd/ [Kernel PMU event] hisi_sccl1_ddrc0/flux_rd/ [Kernel PMU event] hisi_sccl1_ddrc0/flux_wcmd/ [Kernel PMU event] hisi_sccl1_ddrc0/flux_wr/ [Kernel PMU event] hisi_sccl1_ddrc0/pre_cmd/ [Kernel PMU event] hisi_sccl1_ddrc0/rnk_chg/ [Kernel PMU event] ... hisi_sccl7_l3c21/wr_hit_cpipe/ [Kernel PMU event] hisi_sccl7_l3c21/wr_hit_spipe/ [Kernel PMU event] hisi_sccl7_l3c21/wr_spipe/ [Kernel PMU event] inst_retired OR armv8_pmuv3_0/inst_retired/ [Kernel PMU event] inst_spec OR armv8_pmuv3_0/inst_spec/ [Kernel PMU event] itlb_walk OR armv8_pmuv3_0/itlb_walk/ [Kernel PMU event] l1d_cache OR armv8_pmuv3_0/l1d_cache/ [Kernel PMU event] l1d_cache_refill OR armv8_pmuv3_0/l1d_cache_refill/ [Kernel PMU event] l1d_cache_wb OR armv8_pmuv3_0/l1d_cache_wb/ [Kernel PMU event] l1d_tlb OR armv8_pmuv3_0/l1d_tlb/ [Kernel PMU event] l1d_tlb_refill OR armv8_pmuv3_0/l1d_tlb_refill/ [Kernel PMU event] So the events are list alphabetically. However, CPU core event listing is special from commit dc098b35b56f ("perf list: List kernel supplied event aliases"), in that the alias and full event is shown (in that order). As such, the core events may become sparse. Improve this by grouping the CPU core events and ensure that they are listed first for kernel PMU events. For the first example, above, this now looks like: duration_time [Tool event] branch-instructions OR cpu/branch-instructions/ [Kernel PMU event] branch-misses OR cpu/branch-misses/ [Kernel PMU event] bus-cycles OR cpu/bus-cycles/ [Kernel PMU event] cache-misses OR cpu/cache-misses/ [Kernel PMU event] cache-references OR cpu/cache-references/ [Kernel PMU event] cpu-cycles OR cpu/cpu-cycles/ [Kernel PMU event] cycles-ct OR cpu/cycles-ct/ [Kernel PMU event] cycles-t OR cpu/cycles-t/ [Kernel PMU event] el-abort OR cpu/el-abort/ [Kernel PMU event] el-capacity OR cpu/el-capacity/ [Kernel PMU event] el-commit OR cpu/el-commit/ [Kernel PMU event] el-conflict OR cpu/el-conflict/ [Kernel PMU event] el-start OR cpu/el-start/ [Kernel PMU event] instructions OR cpu/instructions/ [Kernel PMU event] mem-loads OR cpu/mem-loads/ [Kernel PMU event] mem-stores OR cpu/mem-stores/ [Kernel PMU event] ref-cycles OR cpu/ref-cycles/ [Kernel PMU event] topdown-fetch-bubbles OR cpu/topdown-fetch-bubbles/ [Kernel PMU event] topdown-recovery-bubbles OR cpu/topdown-recovery-bubbles/ [Kernel PMU event] topdown-slots-issued OR cpu/topdown-slots-issued/ [Kernel PMU event] topdown-slots-retired OR cpu/topdown-slots-retired/ [Kernel PMU event] topdown-total-slots OR cpu/topdown-total-slots/ [Kernel PMU event] tx-abort OR cpu/tx-abort/ [Kernel PMU event] tx-capacity OR cpu/tx-capacity/ [Kernel PMU event] tx-commit OR cpu/tx-commit/ [Kernel PMU event] tx-conflict OR cpu/tx-conflict/ [Kernel PMU event] tx-start OR cpu/tx-start/ [Kernel PMU event] cstate_core/c3-residency/ [Kernel PMU event] cstate_core/c6-residency/ [Kernel PMU event] cstate_core/c7-residency/ [Kernel PMU event] cstate_pkg/c2-residency/ [Kernel PMU event] cstate_pkg/c3-residency/ [Kernel PMU event] cstate_pkg/c6-residency/ [Kernel PMU event] cstate_pkg/c7-residency/ [Kernel PMU event] Signed-off-by: John Garry Acked-by: Jiri Olsa Acked-by: Namhyung Kim Tested-by: Arnaldo Carvalho de Melo Cc: Alexander Shishkin Cc: Andi Kleen Cc: Ian Rogers Cc: Mark Rutland Cc: Peter Zijlstra Cc: Will Deacon Cc: linux-arm-kernel@lists.infradead.org Cc: linuxarm@huawei.com Link: http://lore.kernel.org/lkml/1592384514-119954-3-git-send-email-john.garry@huawei.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/pmu.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c index d039879bd9141..f1688e1f6ed78 100644 --- a/tools/perf/util/pmu.c +++ b/tools/perf/util/pmu.c @@ -1402,6 +1402,7 @@ struct sevent { char *pmu; char *metric_expr; char *metric_name; + int is_cpu; }; static int cmp_sevent(const void *a, const void *b) @@ -1418,6 +1419,11 @@ static int cmp_sevent(const void *a, const void *b) if (n) return n; } + + /* Order CPU core events to be first */ + if (as->is_cpu != bs->is_cpu) + return bs->is_cpu - as->is_cpu; + return strcmp(as->name, bs->name); } @@ -1509,6 +1515,7 @@ void print_pmu_events(const char *event_glob, bool name_only, bool quiet_flag, aliases[j].pmu = pmu->name; aliases[j].metric_expr = alias->metric_expr; aliases[j].metric_name = alias->metric_name; + aliases[j].is_cpu = is_cpu; j++; } if (pmu->selectable && -- GitLab From e251abee87cf9c49a2ec1b143bd71f92b71557c1 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Wed, 17 Jun 2020 09:16:20 -0300 Subject: [PATCH 0076/2249] perf evlist: Fix the class prefix for 'struct evlist' 'add' evsel methods To differentiate from libperf's 'struct perf_evlist' methods. Cc: Adrian Hunter Cc: Jiri Olsa Cc: Namhyung Kim Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-kvm.c | 2 +- tools/perf/builtin-record.c | 4 ++-- tools/perf/builtin-stat.c | 16 +++++++--------- tools/perf/builtin-top.c | 2 +- tools/perf/builtin-trace.c | 3 +-- tools/perf/util/evlist.c | 17 +++++++---------- tools/perf/util/evlist.h | 17 ++++++++--------- 7 files changed, 27 insertions(+), 34 deletions(-) diff --git a/tools/perf/builtin-kvm.c b/tools/perf/builtin-kvm.c index 95a77058023e6..460945ded6dd2 100644 --- a/tools/perf/builtin-kvm.c +++ b/tools/perf/builtin-kvm.c @@ -1319,7 +1319,7 @@ static struct evlist *kvm_live_event_list(void) *name = '\0'; name++; - if (perf_evlist__add_newtp(evlist, sys, name, NULL)) { + if (evlist__add_newtp(evlist, sys, name, NULL)) { pr_err("Failed to add %s tracepoint to the list\n", *events_tp); free(tp); goto out; diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index e108d90ae2edf..1eeb58eac5df3 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -852,7 +852,7 @@ static int record__open(struct record *rec) * event synthesis. */ if (opts->initial_delay || target__has_cpu(&opts->target)) { - if (perf_evlist__add_dummy(evlist)) + if (evlist__add_dummy(evlist)) return -ENOMEM; /* Disable tracking of mmaps on lead event. */ @@ -2722,7 +2722,7 @@ int cmd_record(int argc, const char **argv) record.opts.tail_synthesize = true; if (rec->evlist->core.nr_entries == 0 && - __perf_evlist__add_default(rec->evlist, !record.opts.no_samples) < 0) { + __evlist__add_default(rec->evlist, !record.opts.no_samples) < 0) { pr_err("Not enough memory for event selector list\n"); goto out; } diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index 911b9c3538a2d..922d9961ba98e 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -1679,19 +1679,17 @@ static int add_default_attributes(void) if (target__has_cpu(&target)) default_attrs0[0].config = PERF_COUNT_SW_CPU_CLOCK; - if (perf_evlist__add_default_attrs(evsel_list, default_attrs0) < 0) + if (evlist__add_default_attrs(evsel_list, default_attrs0) < 0) return -1; if (pmu_have_event("cpu", "stalled-cycles-frontend")) { - if (perf_evlist__add_default_attrs(evsel_list, - frontend_attrs) < 0) + if (evlist__add_default_attrs(evsel_list, frontend_attrs) < 0) return -1; } if (pmu_have_event("cpu", "stalled-cycles-backend")) { - if (perf_evlist__add_default_attrs(evsel_list, - backend_attrs) < 0) + if (evlist__add_default_attrs(evsel_list, backend_attrs) < 0) return -1; } - if (perf_evlist__add_default_attrs(evsel_list, default_attrs1) < 0) + if (evlist__add_default_attrs(evsel_list, default_attrs1) < 0) return -1; } @@ -1701,21 +1699,21 @@ static int add_default_attributes(void) return 0; /* Append detailed run extra attributes: */ - if (perf_evlist__add_default_attrs(evsel_list, detailed_attrs) < 0) + if (evlist__add_default_attrs(evsel_list, detailed_attrs) < 0) return -1; if (detailed_run < 2) return 0; /* Append very detailed run extra attributes: */ - if (perf_evlist__add_default_attrs(evsel_list, very_detailed_attrs) < 0) + if (evlist__add_default_attrs(evsel_list, very_detailed_attrs) < 0) return -1; if (detailed_run < 3) return 0; /* Append very, very detailed run extra attributes: */ - return perf_evlist__add_default_attrs(evsel_list, very_very_detailed_attrs); + return evlist__add_default_attrs(evsel_list, very_very_detailed_attrs); } static const char * const stat_record_usage[] = { diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index 13889d73f8dd5..994c230027bb2 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c @@ -1627,7 +1627,7 @@ int cmd_top(int argc, const char **argv) goto out_delete_evlist; if (!top.evlist->core.nr_entries && - perf_evlist__add_default(top.evlist) < 0) { + evlist__add_default(top.evlist) < 0) { pr_err("Not enough memory for event selector list\n"); goto out_delete_evlist; } diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index 4cbb64edc9983..b9c8b40c71359 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -3917,8 +3917,7 @@ static int trace__run(struct trace *trace, int argc, const char **argv) } if (trace->sched && - perf_evlist__add_newtp(evlist, "sched", "sched_stat_runtime", - trace__sched_stat_runtime)) + evlist__add_newtp(evlist, "sched", "sched_stat_runtime", trace__sched_stat_runtime)) goto out_error_sched_stat_runtime; /* * If a global cgroup was set, apply it to all the events without an diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index 173b4f0e0e6e6..d574e774073ca 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c @@ -79,7 +79,7 @@ struct evlist *perf_evlist__new_default(void) { struct evlist *evlist = evlist__new(); - if (evlist && perf_evlist__add_default(evlist)) { + if (evlist && evlist__add_default(evlist)) { evlist__delete(evlist); evlist = NULL; } @@ -91,7 +91,7 @@ struct evlist *perf_evlist__new_dummy(void) { struct evlist *evlist = evlist__new(); - if (evlist && perf_evlist__add_dummy(evlist)) { + if (evlist && evlist__add_dummy(evlist)) { evlist__delete(evlist); evlist = NULL; } @@ -231,7 +231,7 @@ void perf_evlist__set_leader(struct evlist *evlist) } } -int __perf_evlist__add_default(struct evlist *evlist, bool precise) +int __evlist__add_default(struct evlist *evlist, bool precise) { struct evsel *evsel = evsel__new_cycles(precise); @@ -242,7 +242,7 @@ int __perf_evlist__add_default(struct evlist *evlist, bool precise) return 0; } -int perf_evlist__add_dummy(struct evlist *evlist) +int evlist__add_dummy(struct evlist *evlist) { struct perf_event_attr attr = { .type = PERF_TYPE_SOFTWARE, @@ -258,8 +258,7 @@ int perf_evlist__add_dummy(struct evlist *evlist) return 0; } -static int evlist__add_attrs(struct evlist *evlist, - struct perf_event_attr *attrs, size_t nr_attrs) +static int evlist__add_attrs(struct evlist *evlist, struct perf_event_attr *attrs, size_t nr_attrs) { struct evsel *evsel, *n; LIST_HEAD(head); @@ -282,8 +281,7 @@ static int evlist__add_attrs(struct evlist *evlist, return -1; } -int __perf_evlist__add_default_attrs(struct evlist *evlist, - struct perf_event_attr *attrs, size_t nr_attrs) +int __evlist__add_default_attrs(struct evlist *evlist, struct perf_event_attr *attrs, size_t nr_attrs) { size_t i; @@ -322,8 +320,7 @@ perf_evlist__find_tracepoint_by_name(struct evlist *evlist, return NULL; } -int perf_evlist__add_newtp(struct evlist *evlist, - const char *sys, const char *name, void *handler) +int evlist__add_newtp(struct evlist *evlist, const char *sys, const char *name, void *handler) { struct evsel *evsel = evsel__newtp(sys, name); diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h index b6f325dfb4d24..94f210d2f313f 100644 --- a/tools/perf/util/evlist.h +++ b/tools/perf/util/evlist.h @@ -92,20 +92,20 @@ void evlist__delete(struct evlist *evlist); void evlist__add(struct evlist *evlist, struct evsel *entry); void evlist__remove(struct evlist *evlist, struct evsel *evsel); -int __perf_evlist__add_default(struct evlist *evlist, bool precise); +int __evlist__add_default(struct evlist *evlist, bool precise); -static inline int perf_evlist__add_default(struct evlist *evlist) +static inline int evlist__add_default(struct evlist *evlist) { - return __perf_evlist__add_default(evlist, true); + return __evlist__add_default(evlist, true); } -int __perf_evlist__add_default_attrs(struct evlist *evlist, +int __evlist__add_default_attrs(struct evlist *evlist, struct perf_event_attr *attrs, size_t nr_attrs); -#define perf_evlist__add_default_attrs(evlist, array) \ - __perf_evlist__add_default_attrs(evlist, array, ARRAY_SIZE(array)) +#define evlist__add_default_attrs(evlist, array) \ + __evlist__add_default_attrs(evlist, array, ARRAY_SIZE(array)) -int perf_evlist__add_dummy(struct evlist *evlist); +int evlist__add_dummy(struct evlist *evlist); int perf_evlist__add_sb_event(struct evlist *evlist, struct perf_event_attr *attr, @@ -116,8 +116,7 @@ int perf_evlist__start_sb_thread(struct evlist *evlist, struct target *target); void perf_evlist__stop_sb_thread(struct evlist *evlist); -int perf_evlist__add_newtp(struct evlist *evlist, - const char *sys, const char *name, void *handler); +int evlist__add_newtp(struct evlist *evlist, const char *sys, const char *name, void *handler); int __evlist__set_tracepoints_handlers(struct evlist *evlist, const struct evsel_str_handler *assocs, -- GitLab From d1f249ecbd8413cb15f3bbad403253a183aa1d81 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Wed, 17 Jun 2020 09:19:46 -0300 Subject: [PATCH 0077/2249] perf evlist: Fix the class prefix for 'struct evlist' strerror methods To differentiate from libperf's 'struct perf_evlist' methods. Cc: Adrian Hunter Cc: Jiri Olsa Cc: Namhyung Kim Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-trace.c | 4 ++-- tools/perf/tests/code-reading.c | 2 +- tools/perf/util/evlist.c | 5 ++--- tools/perf/util/evlist.h | 4 ++-- 4 files changed, 7 insertions(+), 8 deletions(-) diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index b9c8b40c71359..a333a9a64f276 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -4149,11 +4149,11 @@ static int trace__run(struct trace *trace, int argc, const char **argv) goto out_error; out_error_mmap: - perf_evlist__strerror_mmap(evlist, errno, errbuf, sizeof(errbuf)); + evlist__strerror_mmap(evlist, errno, errbuf, sizeof(errbuf)); goto out_error; out_error_open: - perf_evlist__strerror_open(evlist, errno, errbuf, sizeof(errbuf)); + evlist__strerror_open(evlist, errno, errbuf, sizeof(errbuf)); out_error: fprintf(trace->output, "%s\n", errbuf); diff --git a/tools/perf/tests/code-reading.c b/tools/perf/tests/code-reading.c index 6fe221d31f07e..035c9123549a9 100644 --- a/tools/perf/tests/code-reading.c +++ b/tools/perf/tests/code-reading.c @@ -678,7 +678,7 @@ static int do_test_code_reading(bool try_kcore) if (verbose > 0) { char errbuf[512]; - perf_evlist__strerror_open(evlist, errno, errbuf, sizeof(errbuf)); + evlist__strerror_open(evlist, errno, errbuf, sizeof(errbuf)); pr_debug("perf_evlist__open() failed!\n%s\n", errbuf); } diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index d574e774073ca..4b7f9f9b1588e 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c @@ -1461,8 +1461,7 @@ int perf_evlist__parse_sample_timestamp(struct evlist *evlist, return evsel__parse_sample_timestamp(evsel, event, timestamp); } -int perf_evlist__strerror_open(struct evlist *evlist, - int err, char *buf, size_t size) +int evlist__strerror_open(struct evlist *evlist, int err, char *buf, size_t size) { int printed, value; char sbuf[STRERR_BUFSIZE], *emsg = str_error_r(err, sbuf, sizeof(sbuf)); @@ -1515,7 +1514,7 @@ int perf_evlist__strerror_open(struct evlist *evlist, return 0; } -int perf_evlist__strerror_mmap(struct evlist *evlist, int err, char *buf, size_t size) +int evlist__strerror_mmap(struct evlist *evlist, int err, char *buf, size_t size) { char sbuf[STRERR_BUFSIZE], *emsg = str_error_r(err, sbuf, sizeof(sbuf)); int pages_attempted = evlist->core.mmap_len / 1024, pages_max_per_user, printed = 0; diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h index 94f210d2f313f..a832639a82218 100644 --- a/tools/perf/util/evlist.h +++ b/tools/perf/util/evlist.h @@ -257,8 +257,8 @@ static inline struct evsel *evlist__last(struct evlist *evlist) return container_of(evsel, struct evsel, core); } -int perf_evlist__strerror_open(struct evlist *evlist, int err, char *buf, size_t size); -int perf_evlist__strerror_mmap(struct evlist *evlist, int err, char *buf, size_t size); +int evlist__strerror_open(struct evlist *evlist, int err, char *buf, size_t size); +int evlist__strerror_mmap(struct evlist *evlist, int err, char *buf, size_t size); bool perf_evlist__can_select_event(struct evlist *evlist, const char *str); void perf_evlist__to_front(struct evlist *evlist, -- GitLab From b3c2cc2bd21d1d97b34fcd1a08ca7f8cc29202a0 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Wed, 17 Jun 2020 09:24:21 -0300 Subject: [PATCH 0078/2249] perf evlist: Fix the class prefix for 'struct evlist' sample_type methods To differentiate from libperf's 'struct perf_evlist' methods. Cc: Adrian Hunter Cc: Jiri Olsa Cc: Namhyung Kim Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-c2c.c | 2 +- tools/perf/builtin-report.c | 6 +++--- tools/perf/builtin-script.c | 4 ++-- tools/perf/util/evlist.c | 8 ++++---- tools/perf/util/evlist.h | 6 +++--- tools/perf/util/session.c | 4 ++-- 6 files changed, 15 insertions(+), 15 deletions(-) diff --git a/tools/perf/builtin-c2c.c b/tools/perf/builtin-c2c.c index d617d5682c688..5938b100eaf4c 100644 --- a/tools/perf/builtin-c2c.c +++ b/tools/perf/builtin-c2c.c @@ -2582,7 +2582,7 @@ parse_callchain_opt(const struct option *opt, const char *arg, int unset) static int setup_callchain(struct evlist *evlist) { - u64 sample_type = perf_evlist__combined_sample_type(evlist); + u64 sample_type = evlist__combined_sample_type(evlist); enum perf_call_graph_mode mode = CALLCHAIN_NONE; if ((sample_type & PERF_SAMPLE_REGS_USER) && diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index 5f1d2a878fade..67e0692489fad 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -338,7 +338,7 @@ static int process_read_event(struct perf_tool *tool, static int report__setup_sample_type(struct report *rep) { struct perf_session *session = rep->session; - u64 sample_type = perf_evlist__combined_sample_type(session->evlist); + u64 sample_type = evlist__combined_sample_type(session->evlist); bool is_pipe = perf_data__is_pipe(session->data); if (session->itrace_synth_opts->callchain || @@ -1093,7 +1093,7 @@ static int process_attr(struct perf_tool *tool __maybe_unused, * Check if we need to enable callchains based * on events sample_type. */ - sample_type = perf_evlist__combined_sample_type(*pevlist); + sample_type = evlist__combined_sample_type(*pevlist); callchain_param_setup(sample_type); return 0; } @@ -1389,7 +1389,7 @@ int cmd_report(int argc, const char **argv) has_br_stack = perf_header__has_feat(&session->header, HEADER_BRANCH_STACK); - if (perf_evlist__combined_sample_type(session->evlist) & PERF_SAMPLE_STACK_USER) + if (evlist__combined_sample_type(session->evlist) & PERF_SAMPLE_STACK_USER) has_br_stack = false; setup_forced_leader(&report, session->evlist); diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c index 1ff6a8a8dde51..a47d3386f4b4e 100644 --- a/tools/perf/builtin-script.c +++ b/tools/perf/builtin-script.c @@ -2129,7 +2129,7 @@ static int process_attr(struct perf_tool *tool, union perf_event *event, * Check if we need to enable callchains based * on events sample_type. */ - sample_type = perf_evlist__combined_sample_type(evlist); + sample_type = evlist__combined_sample_type(evlist); callchain_param_setup(sample_type); /* Enable fields for callchain entries */ @@ -3171,7 +3171,7 @@ static int have_cmd(int argc, const char **argv) static void script__setup_sample_type(struct perf_script *script) { struct perf_session *session = script->session; - u64 sample_type = perf_evlist__combined_sample_type(session->evlist); + u64 sample_type = evlist__combined_sample_type(session->evlist); if (symbol_conf.use_callchain || symbol_conf.cumulate_callchain) { if ((sample_type & PERF_SAMPLE_REGS_USER) && diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index 4b7f9f9b1588e..6415f97e22995 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c @@ -1085,7 +1085,7 @@ int perf_evlist__append_tp_filter_pid(struct evlist *evlist, pid_t pid) return perf_evlist__append_tp_filter_pids(evlist, 1, &pid); } -bool perf_evlist__valid_sample_type(struct evlist *evlist) +bool evlist__valid_sample_type(struct evlist *evlist) { struct evsel *pos; @@ -1104,7 +1104,7 @@ bool perf_evlist__valid_sample_type(struct evlist *evlist) return true; } -u64 __perf_evlist__combined_sample_type(struct evlist *evlist) +u64 __evlist__combined_sample_type(struct evlist *evlist) { struct evsel *evsel; @@ -1117,10 +1117,10 @@ u64 __perf_evlist__combined_sample_type(struct evlist *evlist) return evlist->combined_sample_type; } -u64 perf_evlist__combined_sample_type(struct evlist *evlist) +u64 evlist__combined_sample_type(struct evlist *evlist) { evlist->combined_sample_type = 0; - return __perf_evlist__combined_sample_type(evlist); + return __evlist__combined_sample_type(evlist); } u64 perf_evlist__combined_branch_type(struct evlist *evlist) diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h index a832639a82218..2edc1512c4438 100644 --- a/tools/perf/util/evlist.h +++ b/tools/perf/util/evlist.h @@ -218,8 +218,8 @@ int perf_evlist__apply_filters(struct evlist *evlist, struct evsel **err_evsel); void __perf_evlist__set_leader(struct list_head *list); void perf_evlist__set_leader(struct evlist *evlist); -u64 __perf_evlist__combined_sample_type(struct evlist *evlist); -u64 perf_evlist__combined_sample_type(struct evlist *evlist); +u64 __evlist__combined_sample_type(struct evlist *evlist); +u64 evlist__combined_sample_type(struct evlist *evlist); u64 perf_evlist__combined_branch_type(struct evlist *evlist); bool perf_evlist__sample_id_all(struct evlist *evlist); u16 perf_evlist__id_hdr_size(struct evlist *evlist); @@ -231,7 +231,7 @@ int perf_evlist__parse_sample_timestamp(struct evlist *evlist, union perf_event *event, u64 *timestamp); -bool perf_evlist__valid_sample_type(struct evlist *evlist); +bool evlist__valid_sample_type(struct evlist *evlist); bool perf_evlist__valid_sample_id_all(struct evlist *evlist); bool perf_evlist__valid_read_format(struct evlist *evlist); diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index 1a157e84a04a5..cbc8c476c8d33 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -115,7 +115,7 @@ static int perf_session__open(struct perf_session *session) if (perf_header__has_feat(&session->header, HEADER_STAT)) return 0; - if (!perf_evlist__valid_sample_type(session->evlist)) { + if (!evlist__valid_sample_type(session->evlist)) { pr_err("non matching sample_type\n"); return -1; } @@ -1160,7 +1160,7 @@ static void perf_evlist__print_tstamp(struct evlist *evlist, union perf_event *event, struct perf_sample *sample) { - u64 sample_type = __perf_evlist__combined_sample_type(evlist); + u64 sample_type = __evlist__combined_sample_type(evlist); if (event->header.type != PERF_RECORD_SAMPLE && !perf_evlist__sample_id_all(evlist)) { -- GitLab From 8cedf3a5c1f232fd8adf60affd040d32c5d9800f Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Wed, 17 Jun 2020 09:29:48 -0300 Subject: [PATCH 0079/2249] perf evlist: Fix the class prefix for 'struct evlist' sample_id_all methods To differentiate from libperf's 'struct perf_evlist' methods. Cc: Adrian Hunter Cc: Jiri Olsa Cc: Namhyung Kim Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-record.c | 2 +- tools/perf/util/evlist.c | 6 +++--- tools/perf/util/evlist.h | 4 ++-- tools/perf/util/session.c | 12 ++++++------ 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index 1eeb58eac5df3..19b1d5effb7a7 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -1646,7 +1646,7 @@ static int __cmd_record(struct record *rec, int argc, const char **argv) * Normally perf_session__new would do this, but it doesn't have the * evlist. */ - if (rec->tool.ordered_events && !perf_evlist__sample_id_all(rec->evlist)) { + if (rec->tool.ordered_events && !evlist__sample_id_all(rec->evlist)) { pr_warning("WARNING: No sample_id_all support, falling back to unordered processing\n"); rec->tool.ordered_events = false; } diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index 6415f97e22995..daae5c6723449 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c @@ -537,7 +537,7 @@ struct evsel *perf_evlist__id2evsel(struct evlist *evlist, u64 id) if (sid) return container_of(sid->evsel, struct evsel, core); - if (!perf_evlist__sample_id_all(evlist)) + if (!evlist__sample_id_all(evlist)) return evlist__first(evlist); return NULL; @@ -1188,7 +1188,7 @@ u16 perf_evlist__id_hdr_size(struct evlist *evlist) return size; } -bool perf_evlist__valid_sample_id_all(struct evlist *evlist) +bool evlist__valid_sample_id_all(struct evlist *evlist) { struct evsel *first = evlist__first(evlist), *pos = first; @@ -1200,7 +1200,7 @@ bool perf_evlist__valid_sample_id_all(struct evlist *evlist) return true; } -bool perf_evlist__sample_id_all(struct evlist *evlist) +bool evlist__sample_id_all(struct evlist *evlist) { struct evsel *first = evlist__first(evlist); return first->core.attr.sample_id_all; diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h index 2edc1512c4438..6c7b865e435bb 100644 --- a/tools/perf/util/evlist.h +++ b/tools/perf/util/evlist.h @@ -221,7 +221,7 @@ void perf_evlist__set_leader(struct evlist *evlist); u64 __evlist__combined_sample_type(struct evlist *evlist); u64 evlist__combined_sample_type(struct evlist *evlist); u64 perf_evlist__combined_branch_type(struct evlist *evlist); -bool perf_evlist__sample_id_all(struct evlist *evlist); +bool evlist__sample_id_all(struct evlist *evlist); u16 perf_evlist__id_hdr_size(struct evlist *evlist); int perf_evlist__parse_sample(struct evlist *evlist, union perf_event *event, @@ -232,7 +232,7 @@ int perf_evlist__parse_sample_timestamp(struct evlist *evlist, u64 *timestamp); bool evlist__valid_sample_type(struct evlist *evlist); -bool perf_evlist__valid_sample_id_all(struct evlist *evlist); +bool evlist__valid_sample_id_all(struct evlist *evlist); bool perf_evlist__valid_read_format(struct evlist *evlist); void perf_evlist__splice_list_tail(struct evlist *evlist, diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index cbc8c476c8d33..396424fcaadfe 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -120,7 +120,7 @@ static int perf_session__open(struct perf_session *session) return -1; } - if (!perf_evlist__valid_sample_id_all(session->evlist)) { + if (!evlist__valid_sample_id_all(session->evlist)) { pr_err("non matching sample_id_all\n"); return -1; } @@ -252,10 +252,10 @@ struct perf_session *perf_session__new(struct perf_data *data, /* * In pipe-mode, evlist is empty until PERF_RECORD_HEADER_ATTR is - * processed, so perf_evlist__sample_id_all is not meaningful here. + * processed, so evlist__sample_id_all is not meaningful here. */ if ((!data || !data->is_pipe) && tool && tool->ordering_requires_timestamps && - tool->ordered_events && !perf_evlist__sample_id_all(session->evlist)) { + tool->ordered_events && !evlist__sample_id_all(session->evlist)) { dump_printf("WARNING: No sample_id_all support, falling back to unordered processing\n"); tool->ordered_events = false; } @@ -1163,7 +1163,7 @@ static void perf_evlist__print_tstamp(struct evlist *evlist, u64 sample_type = __evlist__combined_sample_type(evlist); if (event->header.type != PERF_RECORD_SAMPLE && - !perf_evlist__sample_id_all(evlist)) { + !evlist__sample_id_all(evlist)) { fputs("-1 -1 ", stdout); return; } @@ -1655,7 +1655,7 @@ int perf_session__peek_event(struct perf_session *session, off_t file_offset, return -1; if (session->header.needs_swap) - event_swap(event, perf_evlist__sample_id_all(session->evlist)); + event_swap(event, evlist__sample_id_all(session->evlist)); out_parse_sample: @@ -1704,7 +1704,7 @@ static s64 perf_session__process_event(struct perf_session *session, int ret; if (session->header.needs_swap) - event_swap(event, perf_evlist__sample_id_all(evlist)); + event_swap(event, evlist__sample_id_all(evlist)); if (event->header.type >= PERF_RECORD_HEADER_MAX) return -EINVAL; -- GitLab From 92c7d7cdf490b1f906da04b6340ca8f56836f723 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Wed, 17 Jun 2020 09:31:25 -0300 Subject: [PATCH 0080/2249] perf evlist: Fix the class prefix for 'struct evlist' branch_type methods To differentiate from libperf's 'struct perf_evlist' methods. Cc: Adrian Hunter Cc: Jiri Olsa Cc: Namhyung Kim Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-report.c | 3 +-- tools/perf/builtin-script.c | 3 +-- tools/perf/util/evlist.c | 2 +- tools/perf/util/evlist.h | 2 +- 4 files changed, 4 insertions(+), 6 deletions(-) diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index 67e0692489fad..ece1cddfcd7c7 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -410,8 +410,7 @@ static int report__setup_sample_type(struct report *rep) } /* ??? handle more cases than just ANY? */ - if (!(perf_evlist__combined_branch_type(session->evlist) & - PERF_SAMPLE_BRANCH_ANY)) + if (!(evlist__combined_branch_type(session->evlist) & PERF_SAMPLE_BRANCH_ANY)) rep->nonany_branch_mode = true; #if !defined(HAVE_LIBUNWIND_SUPPORT) && !defined(HAVE_DWARF_SUPPORT) diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c index a47d3386f4b4e..6613e2bfef243 100644 --- a/tools/perf/builtin-script.c +++ b/tools/perf/builtin-script.c @@ -443,8 +443,7 @@ static int evsel__check_attr(struct evsel *evsel, struct perf_session *session) return -EINVAL; } if (PRINT_FIELD(BRSTACKINSN) && !allow_user_set && - !(perf_evlist__combined_branch_type(session->evlist) & - PERF_SAMPLE_BRANCH_ANY)) { + !(evlist__combined_branch_type(session->evlist) & PERF_SAMPLE_BRANCH_ANY)) { pr_err("Display of branch stack assembler requested, but non all-branch filter set\n" "Hint: run 'perf record -b ...'\n"); return -EINVAL; diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index daae5c6723449..1b884695b4d3f 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c @@ -1123,7 +1123,7 @@ u64 evlist__combined_sample_type(struct evlist *evlist) return __evlist__combined_sample_type(evlist); } -u64 perf_evlist__combined_branch_type(struct evlist *evlist) +u64 evlist__combined_branch_type(struct evlist *evlist) { struct evsel *evsel; u64 branch_type = 0; diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h index 6c7b865e435bb..38901c0d1599f 100644 --- a/tools/perf/util/evlist.h +++ b/tools/perf/util/evlist.h @@ -220,7 +220,7 @@ void perf_evlist__set_leader(struct evlist *evlist); u64 __evlist__combined_sample_type(struct evlist *evlist); u64 evlist__combined_sample_type(struct evlist *evlist); -u64 perf_evlist__combined_branch_type(struct evlist *evlist); +u64 evlist__combined_branch_type(struct evlist *evlist); bool evlist__sample_id_all(struct evlist *evlist); u16 perf_evlist__id_hdr_size(struct evlist *evlist); -- GitLab From 8d54c308c87f1b50ca088b12b89d7c0d96cf7dbf Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Thu, 18 Jun 2020 21:33:47 -0700 Subject: [PATCH 0081/2249] perf parse-events: Use automatic variable for flex input This reduces the command line size slightly. Signed-off-by: Ian Rogers Acked-by: Jiri Olsa Cc: Adrian Hunter Cc: Alexander Shishkin Cc: Andi Kleen Cc: Jin Yao Cc: John Garry Cc: Mark Rutland Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lore.kernel.org/lkml/20200619043356.90024-2-irogers@google.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/Build | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/perf/util/Build b/tools/perf/util/Build index 8d18380ecd10e..66cf009f78d87 100644 --- a/tools/perf/util/Build +++ b/tools/perf/util/Build @@ -193,7 +193,7 @@ CFLAGS_genelf_debug.o += -Wno-packed $(OUTPUT)util/parse-events-flex.c: util/parse-events.l $(OUTPUT)util/parse-events-bison.c $(call rule_mkdir) - $(Q)$(call echo-cmd,flex)$(FLEX) -o $@ --header-file=$(OUTPUT)util/parse-events-flex.h $(PARSER_DEBUG_FLEX) util/parse-events.l + $(Q)$(call echo-cmd,flex)$(FLEX) -o $@ --header-file=$(OUTPUT)util/parse-events-flex.h $(PARSER_DEBUG_FLEX) $< $(OUTPUT)util/parse-events-bison.c: util/parse-events.y $(call rule_mkdir) @@ -201,7 +201,7 @@ $(OUTPUT)util/parse-events-bison.c: util/parse-events.y $(OUTPUT)util/expr-flex.c: util/expr.l $(OUTPUT)util/expr-bison.c $(call rule_mkdir) - $(Q)$(call echo-cmd,flex)$(FLEX) -o $@ --header-file=$(OUTPUT)util/expr-flex.h $(PARSER_DEBUG_FLEX) util/expr.l + $(Q)$(call echo-cmd,flex)$(FLEX) -o $@ --header-file=$(OUTPUT)util/expr-flex.h $(PARSER_DEBUG_FLEX) $< $(OUTPUT)util/expr-bison.c: util/expr.y $(call rule_mkdir) @@ -209,7 +209,7 @@ $(OUTPUT)util/expr-bison.c: util/expr.y $(OUTPUT)util/pmu-flex.c: util/pmu.l $(OUTPUT)util/pmu-bison.c $(call rule_mkdir) - $(Q)$(call echo-cmd,flex)$(FLEX) -o $@ --header-file=$(OUTPUT)util/pmu-flex.h util/pmu.l + $(Q)$(call echo-cmd,flex)$(FLEX) -o $@ --header-file=$(OUTPUT)util/pmu-flex.h $< $(OUTPUT)util/pmu-bison.c: util/pmu.y $(call rule_mkdir) -- GitLab From da77a14db3a03562f70dbe4951042ff84f647d7b Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Thu, 18 Jun 2020 21:33:48 -0700 Subject: [PATCH 0082/2249] perf parse-events: Use automatic variable for yacc input This reduces the command line size slightly. Signed-off-by: Ian Rogers Acked-by: Jiri Olsa Cc: Adrian Hunter Cc: Alexander Shishkin Cc: Andi Kleen Cc: Jin Yao Cc: John Garry Cc: Mark Rutland Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lore.kernel.org/lkml/20200619043356.90024-3-irogers@google.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/Build | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/perf/util/Build b/tools/perf/util/Build index 66cf009f78d87..4e1aa52d75a83 100644 --- a/tools/perf/util/Build +++ b/tools/perf/util/Build @@ -197,7 +197,7 @@ $(OUTPUT)util/parse-events-flex.c: util/parse-events.l $(OUTPUT)util/parse-event $(OUTPUT)util/parse-events-bison.c: util/parse-events.y $(call rule_mkdir) - $(Q)$(call echo-cmd,bison)$(BISON) -v util/parse-events.y -d $(PARSER_DEBUG_BISON) -o $@ -p parse_events_ + $(Q)$(call echo-cmd,bison)$(BISON) -v $< -d $(PARSER_DEBUG_BISON) -o $@ -p parse_events_ $(OUTPUT)util/expr-flex.c: util/expr.l $(OUTPUT)util/expr-bison.c $(call rule_mkdir) @@ -205,7 +205,7 @@ $(OUTPUT)util/expr-flex.c: util/expr.l $(OUTPUT)util/expr-bison.c $(OUTPUT)util/expr-bison.c: util/expr.y $(call rule_mkdir) - $(Q)$(call echo-cmd,bison)$(BISON) -v util/expr.y -d $(PARSER_DEBUG_BISON) -o $@ -p expr_ + $(Q)$(call echo-cmd,bison)$(BISON) -v $< -d $(PARSER_DEBUG_BISON) -o $@ -p expr_ $(OUTPUT)util/pmu-flex.c: util/pmu.l $(OUTPUT)util/pmu-bison.c $(call rule_mkdir) @@ -213,7 +213,7 @@ $(OUTPUT)util/pmu-flex.c: util/pmu.l $(OUTPUT)util/pmu-bison.c $(OUTPUT)util/pmu-bison.c: util/pmu.y $(call rule_mkdir) - $(Q)$(call echo-cmd,bison)$(BISON) -v util/pmu.y -d -o $@ -p perf_pmu_ + $(Q)$(call echo-cmd,bison)$(BISON) -v $< -d -o $@ -p perf_pmu_ CFLAGS_parse-events-flex.o += -w CFLAGS_pmu-flex.o += -w -- GitLab From 5011a52fc53570b816f80b0543cb7260cffca1bd Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Thu, 18 Jun 2020 21:33:49 -0700 Subject: [PATCH 0083/2249] perf pmu: Add bison debug build flag Allow pmu parser to be debugged as the parse-events and expr currently are. Enabling this requires the C code to set perf_pmu_debug. Signed-off-by: Ian Rogers Acked-by: Jiri Olsa Cc: Adrian Hunter Cc: Alexander Shishkin Cc: Andi Kleen Cc: Jin Yao Cc: John Garry Cc: Mark Rutland Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lore.kernel.org/lkml/20200619043356.90024-4-irogers@google.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/Build | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/perf/util/Build b/tools/perf/util/Build index 4e1aa52d75a83..3ae4adc8e9666 100644 --- a/tools/perf/util/Build +++ b/tools/perf/util/Build @@ -213,7 +213,7 @@ $(OUTPUT)util/pmu-flex.c: util/pmu.l $(OUTPUT)util/pmu-bison.c $(OUTPUT)util/pmu-bison.c: util/pmu.y $(call rule_mkdir) - $(Q)$(call echo-cmd,bison)$(BISON) -v $< -d -o $@ -p perf_pmu_ + $(Q)$(call echo-cmd,bison)$(BISON) -v $< -d $(PARSER_DEBUG_BISON) -o $@ -p perf_pmu_ CFLAGS_parse-events-flex.o += -w CFLAGS_pmu-flex.o += -w -- GitLab From 970a4a3418e626d0d4220edd4e981ecbf9d87758 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Thu, 18 Jun 2020 21:33:50 -0700 Subject: [PATCH 0084/2249] perf pmu: Add flex debug build flag Allow pmu parser's flex to be debugged as the parse-events and expr currently are. Enabling this requires the C code to call perf_pmu__flex_debug. Signed-off-by: Ian Rogers Acked-by: Jiri Olsa Cc: Adrian Hunter Cc: Alexander Shishkin Cc: Andi Kleen Cc: Jin Yao Cc: John Garry Cc: Mark Rutland Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lore.kernel.org/lkml/20200619043356.90024-5-irogers@google.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/Build | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/perf/util/Build b/tools/perf/util/Build index 3ae4adc8e9666..e63bfc46d50f2 100644 --- a/tools/perf/util/Build +++ b/tools/perf/util/Build @@ -209,7 +209,7 @@ $(OUTPUT)util/expr-bison.c: util/expr.y $(OUTPUT)util/pmu-flex.c: util/pmu.l $(OUTPUT)util/pmu-bison.c $(call rule_mkdir) - $(Q)$(call echo-cmd,flex)$(FLEX) -o $@ --header-file=$(OUTPUT)util/pmu-flex.h $< + $(Q)$(call echo-cmd,flex)$(FLEX) -o $@ --header-file=$(OUTPUT)util/pmu-flex.h $(PARSER_DEBUG_FLEX) $< $(OUTPUT)util/pmu-bison.c: util/pmu.y $(call rule_mkdir) -- GitLab From 4b971df992fdf8e0d55ab3cbea9fca4ce62bcefc Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Thu, 18 Jun 2020 21:33:51 -0700 Subject: [PATCH 0085/2249] perf parse-events: Declare flex header file output Declare flex header file output so that bison C files can depend upon them. As there are multiple output targets $@ is replaced by the target name. Signed-off-by: Ian Rogers Acked-by: Jiri Olsa Cc: Adrian Hunter Cc: Alexander Shishkin Cc: Andi Kleen Cc: Jin Yao Cc: Jiri Olsa Cc: John Garry Cc: Mark Rutland Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lore.kernel.org/lkml/20200619043356.90024-6-irogers@google.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/Build | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/tools/perf/util/Build b/tools/perf/util/Build index e63bfc46d50f2..55c78ac53f048 100644 --- a/tools/perf/util/Build +++ b/tools/perf/util/Build @@ -191,25 +191,28 @@ CFLAGS_llvm-utils.o += -DPERF_INCLUDE_DIR="BUILD_STR($(perf_include_dir_SQ))" # avoid compiler warnings in 32-bit mode CFLAGS_genelf_debug.o += -Wno-packed -$(OUTPUT)util/parse-events-flex.c: util/parse-events.l $(OUTPUT)util/parse-events-bison.c +$(OUTPUT)util/parse-events-flex.c $(OUTPUT)util/parse-events-flex.h: util/parse-events.l $(OUTPUT)util/parse-events-bison.c $(call rule_mkdir) - $(Q)$(call echo-cmd,flex)$(FLEX) -o $@ --header-file=$(OUTPUT)util/parse-events-flex.h $(PARSER_DEBUG_FLEX) $< + $(Q)$(call echo-cmd,flex)$(FLEX) -o $(OUTPUT)util/parse-events-flex.c \ + --header-file=$(OUTPUT)util/parse-events-flex.h $(PARSER_DEBUG_FLEX) $< $(OUTPUT)util/parse-events-bison.c: util/parse-events.y $(call rule_mkdir) $(Q)$(call echo-cmd,bison)$(BISON) -v $< -d $(PARSER_DEBUG_BISON) -o $@ -p parse_events_ -$(OUTPUT)util/expr-flex.c: util/expr.l $(OUTPUT)util/expr-bison.c +$(OUTPUT)util/expr-flex.c $(OUTPUT)util/expr-flex.h: util/expr.l $(OUTPUT)util/expr-bison.c $(call rule_mkdir) - $(Q)$(call echo-cmd,flex)$(FLEX) -o $@ --header-file=$(OUTPUT)util/expr-flex.h $(PARSER_DEBUG_FLEX) $< + $(Q)$(call echo-cmd,flex)$(FLEX) -o $(OUTPUT)util/expr-flex.c \ + --header-file=$(OUTPUT)util/expr-flex.h $(PARSER_DEBUG_FLEX) $< $(OUTPUT)util/expr-bison.c: util/expr.y $(call rule_mkdir) $(Q)$(call echo-cmd,bison)$(BISON) -v $< -d $(PARSER_DEBUG_BISON) -o $@ -p expr_ -$(OUTPUT)util/pmu-flex.c: util/pmu.l $(OUTPUT)util/pmu-bison.c +$(OUTPUT)util/pmu-flex.c $(OUTPUT)util/pmu-flex.h: util/pmu.l $(OUTPUT)util/pmu-bison.c $(call rule_mkdir) - $(Q)$(call echo-cmd,flex)$(FLEX) -o $@ --header-file=$(OUTPUT)util/pmu-flex.h $(PARSER_DEBUG_FLEX) $< + $(Q)$(call echo-cmd,flex)$(FLEX) -o $(OUTPUT)util/pmu-flex.c \ + --header-file=$(OUTPUT)util/pmu-flex.h $(PARSER_DEBUG_FLEX) $< $(OUTPUT)util/pmu-bison.c: util/pmu.y $(call rule_mkdir) -- GitLab From 3744ca1e670e6155ead37d9123ff005b07108259 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Tue, 23 Jun 2020 10:09:03 -0300 Subject: [PATCH 0086/2249] perf expr: Add missing headers noticed when building with NO_LIBBPF=1 These will break the build as soon as we stop disabling all warnings when building flex and bison generated files, so add them before we do that to keep the tree bisectable. Noticed when building on centos:7 with NO_LIBBPF=1: util/expr.c: In function 'key_equal': util/expr.c:29:2: error: implicit declaration of function 'strcmp' [-Werror=implicit-function-declaration] return !strcmp((const char *)key1, (const char *)key2); ^ util/expr.c: In function 'expr__add_id': util/expr.c:40:3: error: implicit declaration of function 'malloc' [-Werror=implicit-function-declaration] val_ptr = malloc(sizeof(double)); ^ util/expr.c:40:13: error: incompatible implicit declaration of built-in function 'malloc' [-Werror] val_ptr = malloc(sizeof(double)); ^ util/expr.c:42:12: error: 'ENOMEM' undeclared (first use in this function) return -ENOMEM; ^ Signed-off-by: Ian Rogers Cc: Adrian Hunter Cc: Alexander Shishkin Cc: Andi Kleen Cc: Jin Yao Cc: John Garry Cc: Mark Rutland Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Stephane Eranian Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/expr.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tools/perf/util/expr.c b/tools/perf/util/expr.c index f64ab91c432ba..e8f777830a23f 100644 --- a/tools/perf/util/expr.c +++ b/tools/perf/util/expr.c @@ -1,6 +1,9 @@ // SPDX-License-Identifier: GPL-2.0 #include #include +#include +#include +#include #include "expr.h" #include "expr-bison.h" #include "expr-flex.h" -- GitLab From ef9894d9667786489f710199628e0bfffccf452a Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Thu, 18 Jun 2020 21:33:52 -0700 Subject: [PATCH 0087/2249] perf parse-events: Declare bison header file output Declare bison header file output so that C files can depend upon them. As there are multiple output targets $@ is replaced by the target name. Signed-off-by: Ian Rogers Acked-by: Jiri Olsa Cc: Adrian Hunter Cc: Alexander Shishkin Cc: Andi Kleen Cc: Jin Yao Cc: John Garry Cc: Mark Rutland Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lore.kernel.org/lkml/20200619043356.90024-7-irogers@google.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/Build | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/tools/perf/util/Build b/tools/perf/util/Build index 55c78ac53f048..504a6bb991ba3 100644 --- a/tools/perf/util/Build +++ b/tools/perf/util/Build @@ -196,27 +196,30 @@ $(OUTPUT)util/parse-events-flex.c $(OUTPUT)util/parse-events-flex.h: util/parse- $(Q)$(call echo-cmd,flex)$(FLEX) -o $(OUTPUT)util/parse-events-flex.c \ --header-file=$(OUTPUT)util/parse-events-flex.h $(PARSER_DEBUG_FLEX) $< -$(OUTPUT)util/parse-events-bison.c: util/parse-events.y +$(OUTPUT)util/parse-events-bison.c $(OUTPUT)util/parse-events-bison.h: util/parse-events.y $(call rule_mkdir) - $(Q)$(call echo-cmd,bison)$(BISON) -v $< -d $(PARSER_DEBUG_BISON) -o $@ -p parse_events_ + $(Q)$(call echo-cmd,bison)$(BISON) -v $< -d $(PARSER_DEBUG_BISON) \ + -o $(OUTPUT)util/parse-events-bison.c -p parse_events_ $(OUTPUT)util/expr-flex.c $(OUTPUT)util/expr-flex.h: util/expr.l $(OUTPUT)util/expr-bison.c $(call rule_mkdir) $(Q)$(call echo-cmd,flex)$(FLEX) -o $(OUTPUT)util/expr-flex.c \ --header-file=$(OUTPUT)util/expr-flex.h $(PARSER_DEBUG_FLEX) $< -$(OUTPUT)util/expr-bison.c: util/expr.y +$(OUTPUT)util/expr-bison.c $(OUTPUT)util/expr-bison.h: util/expr.y $(call rule_mkdir) - $(Q)$(call echo-cmd,bison)$(BISON) -v $< -d $(PARSER_DEBUG_BISON) -o $@ -p expr_ + $(Q)$(call echo-cmd,bison)$(BISON) -v $< -d $(PARSER_DEBUG_BISON) \ + -o $(OUTPUT)util/expr-bison.c -p expr_ $(OUTPUT)util/pmu-flex.c $(OUTPUT)util/pmu-flex.h: util/pmu.l $(OUTPUT)util/pmu-bison.c $(call rule_mkdir) $(Q)$(call echo-cmd,flex)$(FLEX) -o $(OUTPUT)util/pmu-flex.c \ --header-file=$(OUTPUT)util/pmu-flex.h $(PARSER_DEBUG_FLEX) $< -$(OUTPUT)util/pmu-bison.c: util/pmu.y +$(OUTPUT)util/pmu-bison.c $(OUTPUT)util/pmu-bison.h: util/pmu.y $(call rule_mkdir) - $(Q)$(call echo-cmd,bison)$(BISON) -v $< -d $(PARSER_DEBUG_BISON) -o $@ -p perf_pmu_ + $(Q)$(call echo-cmd,bison)$(BISON) -v $< -d $(PARSER_DEBUG_BISON) \ + -o $(OUTPUT)util/pmu-bison.c -p perf_pmu_ CFLAGS_parse-events-flex.o += -w CFLAGS_pmu-flex.o += -w -- GitLab From 5772717e59b9fbdc9e97da606dd69a75174f8101 Mon Sep 17 00:00:00 2001 From: Neil Armstrong Date: Wed, 24 Jun 2020 18:15:27 +0200 Subject: [PATCH 0088/2249] thermal: Add support for the MCU controlled FAN on Khadas boards The new Khadas VIM2 and VIM3 boards controls the cooling fan via the on-board microcontroller. This implements the FAN control as thermal devices and as cell of the Khadas MCU MFD driver. Signed-off-by: Neil Armstrong Reviewed-by: Amit Kucheria Acked-by: Daniel Lezcano Signed-off-by: Lee Jones --- drivers/thermal/Kconfig | 11 +++ drivers/thermal/Makefile | 1 + drivers/thermal/khadas_mcu_fan.c | 162 +++++++++++++++++++++++++++++++ 3 files changed, 174 insertions(+) create mode 100644 drivers/thermal/khadas_mcu_fan.c diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig index 3eb2348e52427..0125561488c9e 100644 --- a/drivers/thermal/Kconfig +++ b/drivers/thermal/Kconfig @@ -500,4 +500,15 @@ config SPRD_THERMAL help Support for the Spreadtrum thermal sensor driver in the Linux thermal framework. + +config KHADAS_MCU_FAN_THERMAL + tristate "Khadas MCU controller FAN cooling support" + depends on OF || COMPILE_TEST + depends on MFD_KHADAS_MCU + select MFD_CORE + select REGMAP + help + If you say yes here you get support for the FAN controlled + by the Microcontroller found on the Khadas VIM boards. + endif diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile index 0c8b84a09b9aa..4b6aabaa7e313 100644 --- a/drivers/thermal/Makefile +++ b/drivers/thermal/Makefile @@ -61,3 +61,4 @@ obj-$(CONFIG_ZX2967_THERMAL) += zx2967_thermal.o obj-$(CONFIG_UNIPHIER_THERMAL) += uniphier_thermal.o obj-$(CONFIG_AMLOGIC_THERMAL) += amlogic_thermal.o obj-$(CONFIG_SPRD_THERMAL) += sprd_thermal.o +obj-$(CONFIG_KHADAS_MCU_FAN_THERMAL) += khadas_mcu_fan.o diff --git a/drivers/thermal/khadas_mcu_fan.c b/drivers/thermal/khadas_mcu_fan.c new file mode 100644 index 0000000000000..9eadd2d6413e4 --- /dev/null +++ b/drivers/thermal/khadas_mcu_fan.c @@ -0,0 +1,162 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Khadas MCU Controlled FAN driver + * + * Copyright (C) 2020 BayLibre SAS + * Author(s): Neil Armstrong + */ + +#include +#include +#include +#include +#include +#include +#include + +#define MAX_LEVEL 3 + +struct khadas_mcu_fan_ctx { + struct khadas_mcu *mcu; + unsigned int level; + struct thermal_cooling_device *cdev; +}; + +static int khadas_mcu_fan_set_level(struct khadas_mcu_fan_ctx *ctx, + unsigned int level) +{ + int ret; + + ret = regmap_write(ctx->mcu->regmap, KHADAS_MCU_CMD_FAN_STATUS_CTRL_REG, + level); + if (ret) + return ret; + + ctx->level = level; + + return 0; +} + +static int khadas_mcu_fan_get_max_state(struct thermal_cooling_device *cdev, + unsigned long *state) +{ + *state = MAX_LEVEL; + + return 0; +} + +static int khadas_mcu_fan_get_cur_state(struct thermal_cooling_device *cdev, + unsigned long *state) +{ + struct khadas_mcu_fan_ctx *ctx = cdev->devdata; + + *state = ctx->level; + + return 0; +} + +static int +khadas_mcu_fan_set_cur_state(struct thermal_cooling_device *cdev, + unsigned long state) +{ + struct khadas_mcu_fan_ctx *ctx = cdev->devdata; + + if (state > MAX_LEVEL) + return -EINVAL; + + if (state == ctx->level) + return 0; + + return khadas_mcu_fan_set_level(ctx, state); +} + +static const struct thermal_cooling_device_ops khadas_mcu_fan_cooling_ops = { + .get_max_state = khadas_mcu_fan_get_max_state, + .get_cur_state = khadas_mcu_fan_get_cur_state, + .set_cur_state = khadas_mcu_fan_set_cur_state, +}; + +static int khadas_mcu_fan_probe(struct platform_device *pdev) +{ + struct khadas_mcu *mcu = dev_get_drvdata(pdev->dev.parent); + struct thermal_cooling_device *cdev; + struct device *dev = &pdev->dev; + struct khadas_mcu_fan_ctx *ctx; + int ret; + + ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL); + if (!ctx) + return -ENOMEM; + ctx->mcu = mcu; + platform_set_drvdata(pdev, ctx); + + cdev = devm_thermal_of_cooling_device_register(dev->parent, + dev->parent->of_node, "khadas-mcu-fan", ctx, + &khadas_mcu_fan_cooling_ops); + if (IS_ERR(cdev)) { + ret = PTR_ERR(cdev); + dev_err(dev, "Failed to register khadas-mcu-fan as cooling device: %d\n", + ret); + return ret; + } + ctx->cdev = cdev; + thermal_cdev_update(cdev); + + return 0; +} + +static void khadas_mcu_fan_shutdown(struct platform_device *pdev) +{ + struct khadas_mcu_fan_ctx *ctx = platform_get_drvdata(pdev); + + khadas_mcu_fan_set_level(ctx, 0); +} + +#ifdef CONFIG_PM_SLEEP +static int khadas_mcu_fan_suspend(struct device *dev) +{ + struct khadas_mcu_fan_ctx *ctx = dev_get_drvdata(dev); + unsigned int level_save = ctx->level; + int ret; + + ret = khadas_mcu_fan_set_level(ctx, 0); + if (ret) + return ret; + + ctx->level = level_save; + + return 0; +} + +static int khadas_mcu_fan_resume(struct device *dev) +{ + struct khadas_mcu_fan_ctx *ctx = dev_get_drvdata(dev); + + return khadas_mcu_fan_set_level(ctx, ctx->level); +} +#endif + +static SIMPLE_DEV_PM_OPS(khadas_mcu_fan_pm, khadas_mcu_fan_suspend, + khadas_mcu_fan_resume); + +static const struct platform_device_id khadas_mcu_fan_id_table[] = { + { .name = "khadas-mcu-fan-ctrl", }, + {}, +}; +MODULE_DEVICE_TABLE(platform, khadas_mcu_fan_id_table); + +static struct platform_driver khadas_mcu_fan_driver = { + .probe = khadas_mcu_fan_probe, + .shutdown = khadas_mcu_fan_shutdown, + .driver = { + .name = "khadas-mcu-fan-ctrl", + .pm = &khadas_mcu_fan_pm, + }, + .id_table = khadas_mcu_fan_id_table, +}; + +module_platform_driver(khadas_mcu_fan_driver); + +MODULE_AUTHOR("Neil Armstrong "); +MODULE_DESCRIPTION("Khadas MCU FAN driver"); +MODULE_LICENSE("GPL"); -- GitLab From bf9367a156fd868b312e8a575c00d57db2bc16bf Mon Sep 17 00:00:00 2001 From: Neil Armstrong Date: Mon, 8 Jun 2020 11:17:38 +0200 Subject: [PATCH 0089/2249] MAINTAINERS: Add myself as maintainer for Khadas MCU drivers Add the Thermal driver along the MFD drivers and header as Maintained by myself. Signed-off-by: Neil Armstrong Signed-off-by: Lee Jones --- MAINTAINERS | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 68f21d46614c4..02d9827a4f810 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -9574,6 +9574,15 @@ F: include/linux/kdb.h F: include/linux/kgdb.h F: kernel/debug/ +KHADAS MCU MFD DRIVER +M: Neil Armstrong +L: linux-amlogic@lists.infradead.org +S: Maintained +F: Documentation/devicetree/bindings/mfd/khadas,mcu.yaml +F: drivers/mfd/khadas-mcu.c +F: include/linux/mfd/khadas-mcu.h +F: drivers/thermal/khadas_mcu_fan.c + KMEMLEAK M: Catalin Marinas S: Maintained -- GitLab From c61e165822d57fd317868d14b46151d9c83662d2 Mon Sep 17 00:00:00 2001 From: Chunyan Zhang Date: Fri, 19 Jun 2020 17:09:14 +0800 Subject: [PATCH 0090/2249] mfd: sprd: Populate sub-devices defined in DT SC27XX-SPI added subdevices according to a pre-defined mfd_cell array, no matter these devices were really included on board. In this patch, switch to use devm_of_platform_populate() for adding sub-devices which are defined in devicetree. Signed-off-by: Chunyan Zhang Signed-off-by: Lee Jones --- drivers/mfd/sprd-sc27xx-spi.c | 75 ++--------------------------------- 1 file changed, 3 insertions(+), 72 deletions(-) diff --git a/drivers/mfd/sprd-sc27xx-spi.c b/drivers/mfd/sprd-sc27xx-spi.c index 33336cde47243..d030a5da55444 100644 --- a/drivers/mfd/sprd-sc27xx-spi.c +++ b/drivers/mfd/sprd-sc27xx-spi.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -93,73 +94,6 @@ enum usb_charger_type sprd_pmic_detect_charger_type(struct device *dev) } EXPORT_SYMBOL_GPL(sprd_pmic_detect_charger_type); -static const struct mfd_cell sprd_pmic_devs[] = { - { - .name = "sc27xx-wdt", - .of_compatible = "sprd,sc2731-wdt", - }, { - .name = "sc27xx-rtc", - .of_compatible = "sprd,sc2731-rtc", - }, { - .name = "sc27xx-charger", - .of_compatible = "sprd,sc2731-charger", - }, { - .name = "sc27xx-chg-timer", - .of_compatible = "sprd,sc2731-chg-timer", - }, { - .name = "sc27xx-fast-chg", - .of_compatible = "sprd,sc2731-fast-chg", - }, { - .name = "sc27xx-chg-wdt", - .of_compatible = "sprd,sc2731-chg-wdt", - }, { - .name = "sc27xx-typec", - .of_compatible = "sprd,sc2731-typec", - }, { - .name = "sc27xx-flash", - .of_compatible = "sprd,sc2731-flash", - }, { - .name = "sc27xx-eic", - .of_compatible = "sprd,sc2731-eic", - }, { - .name = "sc27xx-efuse", - .of_compatible = "sprd,sc2731-efuse", - }, { - .name = "sc27xx-thermal", - .of_compatible = "sprd,sc2731-thermal", - }, { - .name = "sc27xx-adc", - .of_compatible = "sprd,sc2731-adc", - }, { - .name = "sc27xx-audio-codec", - .of_compatible = "sprd,sc2731-audio-codec", - }, { - .name = "sc27xx-regulator", - .of_compatible = "sprd,sc2731-regulator", - }, { - .name = "sc27xx-vibrator", - .of_compatible = "sprd,sc2731-vibrator", - }, { - .name = "sc27xx-keypad-led", - .of_compatible = "sprd,sc2731-keypad-led", - }, { - .name = "sc27xx-bltc", - .of_compatible = "sprd,sc2731-bltc", - }, { - .name = "sc27xx-fgu", - .of_compatible = "sprd,sc2731-fgu", - }, { - .name = "sc27xx-7sreset", - .of_compatible = "sprd,sc2731-7sreset", - }, { - .name = "sc27xx-poweroff", - .of_compatible = "sprd,sc2731-poweroff", - }, { - .name = "sc27xx-syscon", - .of_compatible = "sprd,sc2731-syscon", - }, -}; - static int sprd_pmic_spi_write(void *context, const void *data, size_t count) { struct device *dev = context; @@ -263,12 +197,9 @@ static int sprd_pmic_probe(struct spi_device *spi) return ret; } - ret = devm_mfd_add_devices(&spi->dev, PLATFORM_DEVID_AUTO, - sprd_pmic_devs, ARRAY_SIZE(sprd_pmic_devs), - NULL, 0, - regmap_irq_get_domain(ddata->irq_data)); + ret = devm_of_platform_populate(&spi->dev); if (ret) { - dev_err(&spi->dev, "Failed to register device %d\n", ret); + dev_err(&spi->dev, "Failed to populate sub-devices %d\n", ret); return ret; } -- GitLab From e8da9ed039805a52c32c4ee2f462080aa2315929 Mon Sep 17 00:00:00 2001 From: Benjamin Gaignard Date: Thu, 20 Feb 2020 17:22:46 +0100 Subject: [PATCH 0091/2249] dt-bindings: mfd: Convert stmfx bindings to json-schema Convert stmfx bindings to json-schema. Signed-off-by: Benjamin Gaignard Reviewed-by: Rob Herring Reviewed-by: Linus Walleij Signed-off-by: Lee Jones --- .../devicetree/bindings/mfd/st,stmfx.yaml | 124 ++++++++++++++++++ .../devicetree/bindings/mfd/stmfx.txt | 28 ---- .../bindings/pinctrl/pinctrl-stmfx.txt | 116 ---------------- 3 files changed, 124 insertions(+), 144 deletions(-) create mode 100644 Documentation/devicetree/bindings/mfd/st,stmfx.yaml delete mode 100644 Documentation/devicetree/bindings/mfd/stmfx.txt delete mode 100644 Documentation/devicetree/bindings/pinctrl/pinctrl-stmfx.txt diff --git a/Documentation/devicetree/bindings/mfd/st,stmfx.yaml b/Documentation/devicetree/bindings/mfd/st,stmfx.yaml new file mode 100644 index 0000000000000..0ce56a0da5536 --- /dev/null +++ b/Documentation/devicetree/bindings/mfd/st,stmfx.yaml @@ -0,0 +1,124 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/mfd/st,stmfx.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: STMicroelectonics Multi-Function eXpander (STMFX) bindings + +description: ST Multi-Function eXpander (STMFX) is a slave controller using I2C for + communication with the main MCU. Its main features are GPIO expansion, + main MCU IDD measurement (IDD is the amount of current that flows + through VDD) and resistive touchscreen controller. + +maintainers: + - Amelie Delaunay + +properties: + compatible: + const: st,stmfx-0300 + + reg: + enum: [ 0x42, 0x43 ] + + interrupts: + maxItems: 1 + + drive-open-drain: true + + vdd-supply: + maxItems: 1 + + pinctrl: + type: object + + properties: + compatible: + const: st,stmfx-0300-pinctrl + + "#gpio-cells": + const: 2 + + "#interrupt-cells": + const: 2 + + gpio-controller: true + + interrupt-controller: true + + gpio-ranges: + description: if all STMFX pins[24:0] are available (no other STMFX function in use), + you should use gpio-ranges = <&stmfx_pinctrl 0 0 24>; + if agpio[3:0] are not available (STMFX Touchscreen function in use), + you should use gpio-ranges = <&stmfx_pinctrl 0 0 16>, <&stmfx_pinctrl 20 20 4>; + if agpio[7:4] are not available (STMFX IDD function in use), + you should use gpio-ranges = <&stmfx_pinctrl 0 0 20>; + maxItems: 1 + + patternProperties: + "^[a-zA-Z]*-pins$": + type: object + + allOf: + - $ref: ../pinctrl/pinmux-node.yaml + + properties: + pins: true + bias-disable: true + bias-pull-up: true + bias-pull-pin-default: true + bias-pull-down: true + drive-open-drain: true + drive-push-pull: true + output-high: true + output-low: true + + additionalProperties: false + + additionalProperties: false + + required: + - compatible + - "#gpio-cells" + - "#interrupt-cells" + - gpio-controller + - interrupt-controller + - gpio-ranges + +additionalProperties: false + +required: + - compatible + - reg + - interrupts + +examples: + - | + #include + i2c@0 { + #address-cells = <1>; + #size-cells = <0>; + stmfx@42 { + compatible = "st,stmfx-0300"; + reg = <0x42>; + interrupts = <8 IRQ_TYPE_EDGE_RISING>; + interrupt-parent = <&gpioi>; + vdd-supply = <&v3v3>; + + stmfx_pinctrl: pinctrl { + compatible = "st,stmfx-0300-pinctrl"; + #gpio-cells = <2>; + #interrupt-cells = <2>; + gpio-controller; + interrupt-controller; + gpio-ranges = <&stmfx_pinctrl 0 0 24>; + + joystick_pins: joystick-pins { + pins = "gpio0", "gpio1", "gpio2", "gpio3", "gpio4"; + drive-push-pull; + bias-pull-up; + }; + }; + }; + }; +... diff --git a/Documentation/devicetree/bindings/mfd/stmfx.txt b/Documentation/devicetree/bindings/mfd/stmfx.txt deleted file mode 100644 index f0c2f7fcf5c7f..0000000000000 --- a/Documentation/devicetree/bindings/mfd/stmfx.txt +++ /dev/null @@ -1,28 +0,0 @@ -STMicroelectonics Multi-Function eXpander (STMFX) Core bindings - -ST Multi-Function eXpander (STMFX) is a slave controller using I2C for -communication with the main MCU. Its main features are GPIO expansion, main -MCU IDD measurement (IDD is the amount of current that flows through VDD) and -resistive touchscreen controller. - -Required properties: -- compatible: should be "st,stmfx-0300". -- reg: I2C slave address of the device. -- interrupts: interrupt specifier triggered by MFX_IRQ_OUT signal. - Please refer to ../interrupt-controller/interrupt.txt - -Optional properties: -- drive-open-drain: configure MFX_IRQ_OUT as open drain. -- vdd-supply: phandle of the regulator supplying STMFX. - -Example: - - stmfx: stmfx@42 { - compatible = "st,stmfx-0300"; - reg = <0x42>; - interrupts = <8 IRQ_TYPE_EDGE_RISING>; - interrupt-parent = <&gpioi>; - vdd-supply = <&v3v3>; - }; - -Please refer to ../pinctrl/pinctrl-stmfx.txt for STMFX GPIO expander function bindings. diff --git a/Documentation/devicetree/bindings/pinctrl/pinctrl-stmfx.txt b/Documentation/devicetree/bindings/pinctrl/pinctrl-stmfx.txt deleted file mode 100644 index c1b4c1819b84c..0000000000000 --- a/Documentation/devicetree/bindings/pinctrl/pinctrl-stmfx.txt +++ /dev/null @@ -1,116 +0,0 @@ -STMicroelectronics Multi-Function eXpander (STMFX) GPIO expander bindings - -ST Multi-Function eXpander (STMFX) offers up to 24 GPIOs expansion. -Please refer to ../mfd/stmfx.txt for STMFX Core bindings. - -Required properties: -- compatible: should be "st,stmfx-0300-pinctrl". -- #gpio-cells: should be <2>, the first cell is the GPIO number and the second - cell is the gpio flags in accordance with . -- gpio-controller: marks the device as a GPIO controller. -- #interrupt-cells: should be <2>, the first cell is the GPIO number and the - second cell is the interrupt flags in accordance with - . -- interrupt-controller: marks the device as an interrupt controller. -- gpio-ranges: specifies the mapping between gpio controller and pin - controller pins. Check "Concerning gpio-ranges property" below. -Please refer to ../gpio/gpio.txt. - -Please refer to pinctrl-bindings.txt for pin configuration. - -Required properties for pin configuration sub-nodes: -- pins: list of pins to which the configuration applies. - -Optional properties for pin configuration sub-nodes (pinconf-generic ones): -- bias-disable: disable any bias on the pin. -- bias-pull-up: the pin will be pulled up. -- bias-pull-pin-default: use the pin-default pull state. -- bias-pull-down: the pin will be pulled down. -- drive-open-drain: the pin will be driven with open drain. -- drive-push-pull: the pin will be driven actively high and low. -- output-high: the pin will be configured as an output driving high level. -- output-low: the pin will be configured as an output driving low level. - -Note that STMFX pins[15:0] are called "gpio[15:0]", and STMFX pins[23:16] are -called "agpio[7:0]". Example, to refer to pin 18 of STMFX, use "agpio2". - -Concerning gpio-ranges property: -- if all STMFX pins[24:0] are available (no other STMFX function in use), you - should use gpio-ranges = <&stmfx_pinctrl 0 0 24>; -- if agpio[3:0] are not available (STMFX Touchscreen function in use), you - should use gpio-ranges = <&stmfx_pinctrl 0 0 16>, <&stmfx_pinctrl 20 20 4>; -- if agpio[7:4] are not available (STMFX IDD function in use), you - should use gpio-ranges = <&stmfx_pinctrl 0 0 20>; - - -Example: - - stmfx: stmfx@42 { - ... - - stmfx_pinctrl: stmfx-pin-controller { - compatible = "st,stmfx-0300-pinctrl"; - #gpio-cells = <2>; - #interrupt-cells = <2>; - gpio-controller; - interrupt-controller; - gpio-ranges = <&stmfx_pinctrl 0 0 24>; - - joystick_pins: joystick { - pins = "gpio0", "gpio1", "gpio2", "gpio3", "gpio4"; - drive-push-pull; - bias-pull-up; - }; - }; - }; - -Example of STMFX GPIO consumers: - - joystick { - compatible = "gpio-keys"; - #address-cells = <1>; - #size-cells = <0>; - pinctrl-0 = <&joystick_pins>; - pinctrl-names = "default"; - button-0 { - label = "JoySel"; - linux,code = ; - interrupt-parent = <&stmfx_pinctrl>; - interrupts = <0 IRQ_TYPE_EDGE_RISING>; - }; - button-1 { - label = "JoyDown"; - linux,code = ; - interrupt-parent = <&stmfx_pinctrl>; - interrupts = <1 IRQ_TYPE_EDGE_RISING>; - }; - button-2 { - label = "JoyLeft"; - linux,code = ; - interrupt-parent = <&stmfx_pinctrl>; - interrupts = <2 IRQ_TYPE_EDGE_RISING>; - }; - button-3 { - label = "JoyRight"; - linux,code = ; - interrupt-parent = <&stmfx_pinctrl>; - interrupts = <3 IRQ_TYPE_EDGE_RISING>; - }; - button-4 { - label = "JoyUp"; - linux,code = ; - interrupt-parent = <&stmfx_pinctrl>; - interrupts = <4 IRQ_TYPE_EDGE_RISING>; - }; - }; - - leds { - compatible = "gpio-leds"; - orange { - gpios = <&stmfx_pinctrl 17 1>; - }; - - blue { - gpios = <&stmfx_pinctrl 19 1>; - }; - } -- GitLab From 5e48a03bb9bff1728164040d71aa03cdb3cdfca2 Mon Sep 17 00:00:00 2001 From: Prashant Malani Date: Wed, 24 Jun 2020 01:09:23 -0700 Subject: [PATCH 0092/2249] platform/chrome: cros_ec: Add TBT pd_ctrl fields To support Thunderbolt compatibility mode, synchronize ec_response_usb_pd_control_v2 with the Chrome EC version, so that we get the Thunderbolt related control fields and macros. Signed-off-by: Prashant Malani Signed-off-by: Enric Balletbo i Serra --- .../linux/platform_data/cros_ec_commands.h | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/include/linux/platform_data/cros_ec_commands.h b/include/linux/platform_data/cros_ec_commands.h index a7b0fc440c355..b808570bdd046 100644 --- a/include/linux/platform_data/cros_ec_commands.h +++ b/include/linux/platform_data/cros_ec_commands.h @@ -4917,15 +4917,26 @@ struct ec_response_usb_pd_control_v1 { #define USBC_PD_CC_UFP_ATTACHED 4 /* UFP attached to usbc */ #define USBC_PD_CC_DFP_ATTACHED 5 /* DPF attached to usbc */ +/* Active/Passive Cable */ +#define USB_PD_CTRL_ACTIVE_CABLE BIT(0) +/* Optical/Non-optical cable */ +#define USB_PD_CTRL_OPTICAL_CABLE BIT(1) +/* 3rd Gen TBT device (or AMA)/2nd gen tbt Adapter */ +#define USB_PD_CTRL_TBT_LEGACY_ADAPTER BIT(2) +/* Active Link Uni-Direction */ +#define USB_PD_CTRL_ACTIVE_LINK_UNIDIR BIT(3) + struct ec_response_usb_pd_control_v2 { uint8_t enabled; uint8_t role; uint8_t polarity; char state[32]; - uint8_t cc_state; /* USBC_PD_CC_*Encoded cc state */ - uint8_t dp_mode; /* Current DP pin mode (MODE_DP_PIN_[A-E]) */ - /* CL:1500994 Current cable type */ - uint8_t reserved_cable_type; + uint8_t cc_state; /* enum pd_cc_states representing cc state */ + uint8_t dp_mode; /* Current DP pin mode (MODE_DP_PIN_[A-E]) */ + uint8_t reserved; /* Reserved for future use */ + uint8_t control_flags; /* USB_PD_CTRL_*flags */ + uint8_t cable_speed; /* TBT_SS_* cable speed */ + uint8_t cable_gen; /* TBT_GEN3_* cable rounded support */ } __ec_align1; #define EC_CMD_USB_PD_PORTS 0x0102 -- GitLab From 5b30bd35aab4bcea6a06627a1e943659d82a71cb Mon Sep 17 00:00:00 2001 From: Prashant Malani Date: Wed, 24 Jun 2020 01:09:24 -0700 Subject: [PATCH 0093/2249] platform/chrome: cros_ec_typec: Add TBT compat support Add mux control support for Thunderbolt compatibility mode. Suggested-by: Heikki Krogerus Co-developed-by: Azhar Shaikh Co-developed-by: Casey Bowman Signed-off-by: Prashant Malani Reviewed-by: Heikki Krogerus Signed-off-by: Enric Balletbo i Serra --- drivers/platform/chrome/cros_ec_typec.c | 70 ++++++++++++++++++++++++- 1 file changed, 69 insertions(+), 1 deletion(-) diff --git a/drivers/platform/chrome/cros_ec_typec.c b/drivers/platform/chrome/cros_ec_typec.c index 1df1386f32e4f..0c041b79cbbac 100644 --- a/drivers/platform/chrome/cros_ec_typec.c +++ b/drivers/platform/chrome/cros_ec_typec.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #define DRV_NAME "cros-ec-typec" @@ -24,6 +25,7 @@ /* Supported alt modes. */ enum { CROS_EC_ALTMODE_DP = 0, + CROS_EC_ALTMODE_TBT, CROS_EC_ALTMODE_MAX, }; @@ -165,6 +167,14 @@ static void cros_typec_register_port_altmodes(struct cros_typec_data *typec, port->p_altmode[CROS_EC_ALTMODE_DP].svid = USB_TYPEC_DP_SID; port->p_altmode[CROS_EC_ALTMODE_DP].mode = USB_TYPEC_DP_MODE; + /* + * Register TBT compatibility alt mode. The EC will not enter the mode + * if it doesn't support it, so it's safe to register it unconditionally + * here for now. + */ + port->p_altmode[CROS_EC_ALTMODE_TBT].svid = USB_TYPEC_TBT_SID; + port->p_altmode[CROS_EC_ALTMODE_TBT].mode = TYPEC_ANY_MODE; + port->state.alt = NULL; port->state.mode = TYPEC_STATE_USB; port->state.data = NULL; @@ -391,6 +401,62 @@ static int cros_typec_usb_safe_state(struct cros_typec_port *port) return typec_mux_set(port->mux, &port->state); } +/* + * Spoof the VDOs that were likely communicated by the partner for TBT alt + * mode. + */ +static int cros_typec_enable_tbt(struct cros_typec_data *typec, + int port_num, + struct ec_response_usb_pd_control_v2 *pd_ctrl) +{ + struct cros_typec_port *port = typec->ports[port_num]; + struct typec_thunderbolt_data data; + int ret; + + if (typec->pd_ctrl_ver < 2) { + dev_err(typec->dev, + "PD_CTRL version too old: %d\n", typec->pd_ctrl_ver); + return -ENOTSUPP; + } + + /* Device Discover Mode VDO */ + data.device_mode = TBT_MODE; + + if (pd_ctrl->control_flags & USB_PD_CTRL_TBT_LEGACY_ADAPTER) + data.device_mode = TBT_SET_ADAPTER(TBT_ADAPTER_TBT3); + + /* Cable Discover Mode VDO */ + data.cable_mode = TBT_MODE; + data.cable_mode |= TBT_SET_CABLE_SPEED(pd_ctrl->cable_speed); + + if (pd_ctrl->control_flags & USB_PD_CTRL_OPTICAL_CABLE) + data.cable_mode |= TBT_CABLE_OPTICAL; + + if (pd_ctrl->control_flags & USB_PD_CTRL_ACTIVE_LINK_UNIDIR) + data.cable_mode |= TBT_CABLE_LINK_TRAINING; + + if (pd_ctrl->cable_gen) + data.cable_mode |= TBT_CABLE_ROUNDED; + + /* Enter Mode VDO */ + data.enter_vdo = TBT_SET_CABLE_SPEED(pd_ctrl->cable_speed); + + if (pd_ctrl->control_flags & USB_PD_CTRL_ACTIVE_CABLE) + data.enter_vdo |= TBT_ENTER_MODE_ACTIVE_CABLE; + + if (!port->state.alt) { + port->state.alt = &port->p_altmode[CROS_EC_ALTMODE_TBT]; + ret = cros_typec_usb_safe_state(port); + if (ret) + return ret; + } + + port->state.data = &data; + port->state.mode = TYPEC_TBT_MODE; + + return typec_mux_set(port->mux, &port->state); +} + /* Spoof the VDOs that were likely communicated by the partner. */ static int cros_typec_enable_dp(struct cros_typec_data *typec, int port_num, @@ -448,7 +514,9 @@ static int cros_typec_configure_mux(struct cros_typec_data *typec, int port_num, if (ret) return ret; - if (mux_flags & USB_PD_MUX_DP_ENABLED) { + if (mux_flags & USB_PD_MUX_TBT_COMPAT_ENABLED) { + ret = cros_typec_enable_tbt(typec, port_num, pd_ctrl); + } else if (mux_flags & USB_PD_MUX_DP_ENABLED) { ret = cros_typec_enable_dp(typec, port_num, pd_ctrl); } else if (mux_flags & USB_PD_MUX_SAFE_MODE) { ret = cros_typec_usb_safe_state(port); -- GitLab From bb7fcad48d3804d814b97c785514e2d1657e157f Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Thu, 25 Jun 2020 16:10:36 +0300 Subject: [PATCH 0094/2249] mfd: intel-lpss: Add Intel Tiger Lake PCH-H PCI IDs Intel Tiger Lake PCH-H has the same LPSS than Intel Broxton. Add the new IDs to the list of supported devices. Signed-off-by: Andy Shevchenko Signed-off-by: Lee Jones --- drivers/mfd/intel-lpss-pci.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/drivers/mfd/intel-lpss-pci.c b/drivers/mfd/intel-lpss-pci.c index 17bcadc00a11c..9a58032f818ae 100644 --- a/drivers/mfd/intel-lpss-pci.c +++ b/drivers/mfd/intel-lpss-pci.c @@ -233,6 +233,22 @@ static const struct pci_device_id intel_lpss_pci_ids[] = { { PCI_VDEVICE(INTEL, 0x34ea), (kernel_ulong_t)&bxt_i2c_info }, { PCI_VDEVICE(INTEL, 0x34eb), (kernel_ulong_t)&bxt_i2c_info }, { PCI_VDEVICE(INTEL, 0x34fb), (kernel_ulong_t)&spt_info }, + /* TGL-H */ + { PCI_VDEVICE(INTEL, 0x43a7), (kernel_ulong_t)&bxt_uart_info }, + { PCI_VDEVICE(INTEL, 0x43a8), (kernel_ulong_t)&bxt_uart_info }, + { PCI_VDEVICE(INTEL, 0x43a9), (kernel_ulong_t)&bxt_uart_info }, + { PCI_VDEVICE(INTEL, 0x43aa), (kernel_ulong_t)&bxt_info }, + { PCI_VDEVICE(INTEL, 0x43ab), (kernel_ulong_t)&bxt_info }, + { PCI_VDEVICE(INTEL, 0x43ad), (kernel_ulong_t)&bxt_i2c_info }, + { PCI_VDEVICE(INTEL, 0x43ae), (kernel_ulong_t)&bxt_i2c_info }, + { PCI_VDEVICE(INTEL, 0x43d8), (kernel_ulong_t)&bxt_i2c_info }, + { PCI_VDEVICE(INTEL, 0x43da), (kernel_ulong_t)&bxt_uart_info }, + { PCI_VDEVICE(INTEL, 0x43e8), (kernel_ulong_t)&bxt_i2c_info }, + { PCI_VDEVICE(INTEL, 0x43e9), (kernel_ulong_t)&bxt_i2c_info }, + { PCI_VDEVICE(INTEL, 0x43ea), (kernel_ulong_t)&bxt_i2c_info }, + { PCI_VDEVICE(INTEL, 0x43eb), (kernel_ulong_t)&bxt_i2c_info }, + { PCI_VDEVICE(INTEL, 0x43fb), (kernel_ulong_t)&bxt_info }, + { PCI_VDEVICE(INTEL, 0x43fd), (kernel_ulong_t)&bxt_info }, /* EHL */ { PCI_VDEVICE(INTEL, 0x4b28), (kernel_ulong_t)&bxt_uart_info }, { PCI_VDEVICE(INTEL, 0x4b29), (kernel_ulong_t)&bxt_uart_info }, -- GitLab From f375a038daf655933dae0c54542a071388c02880 Mon Sep 17 00:00:00 2001 From: Matti Vaittinen Date: Thu, 18 Jun 2020 10:33:31 +0300 Subject: [PATCH 0095/2249] MAINTAINERS: Add entry for ROHM Power Management ICs Add entry for maintaining power management IC drivers for ROHM BD71837, BD71847, BD71850, BD71828, BD71878, BD70528 and BD99954. Signed-off-by: Matti Vaittinen Acked-by: Sebastian Reichel Acked-by: Guenter Roeck Acked-by: Stephen Boyd Reviewed-by: Linus Walleij Signed-off-by: Lee Jones --- MAINTAINERS | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 02d9827a4f810..423f7107ace40 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -14713,6 +14713,13 @@ L: linux-serial@vger.kernel.org S: Odd Fixes F: drivers/tty/serial/rp2.* +ROHM BD99954 CHARGER IC +R: Matti Vaittinen +L: linux-power@fi.rohmeurope.com +S: Supported +F: drivers/power/supply/bd99954-charger.c +F: drivers/power/supply/bd99954-charger.h + ROHM BH1750 AMBIENT LIGHT SENSOR DRIVER M: Tomasz Duszynski S: Maintained @@ -14730,6 +14737,31 @@ F: drivers/mfd/bd9571mwv.c F: drivers/regulator/bd9571mwv-regulator.c F: include/linux/mfd/bd9571mwv.h +ROHM POWER MANAGEMENT IC DEVICE DRIVERS +R: Matti Vaittinen +L: linux-power@fi.rohmeurope.com +S: Supported +F: Documentation/devicetree/bindings/mfd/rohm,bd70528-pmic.txt +F: Documentation/devicetree/bindings/regulator/rohm,bd70528-regulator.txt +F: drivers/clk/clk-bd718x7.c +F: drivers/gpio/gpio-bd70528.c +F: drivers/gpio/gpio-bd71828.c +F: drivers/mfd/rohm-bd70528.c +F: drivers/mfd/rohm-bd71828.c +F: drivers/mfd/rohm-bd718x7.c +F: drivers/power/supply/bd70528-charger.c +F: drivers/regulator/bd70528-regulator.c +F: drivers/regulator/bd71828-regulator.c +F: drivers/regulator/bd718x7-regulator.c +F: drivers/regulator/rohm-regulator.c +F: drivers/rtc/rtc-bd70528.c +F: drivers/watchdog/bd70528_wdt.c +F: include/linux/mfd/rohm-bd70528.h +F: include/linux/mfd/rohm-bd71828.h +F: include/linux/mfd/rohm-bd718x7.h +F: include/linux/mfd/rohm-generic.h +F: include/linux/mfd/rohm-shared.h + ROSE NETWORK LAYER M: Ralf Baechle L: linux-hams@vger.kernel.org -- GitLab From d3e3d2be688b4b5864538de61e750721a311e4fc Mon Sep 17 00:00:00 2001 From: Robin Murphy Date: Tue, 2 Jun 2020 14:08:18 +0100 Subject: [PATCH 0096/2249] iommu/iova: Don't BUG on invalid PFNs Unlike the other instances which represent a complete loss of consistency within the rcache mechanism itself, or a fundamental and obvious misconfiguration by an IOMMU driver, the BUG_ON() in iova_magazine_free_pfns() can be provoked at more or less any time in a "spooky action-at-a-distance" manner by any old device driver passing nonsense to dma_unmap_*() which then propagates through to queue_iova(). Not only is this well outside the IOVA layer's control, it's also nowhere near fatal enough to justify panicking anyway - all that really achieves is to make debugging the offending driver more difficult. Let's simply WARN and otherwise ignore bogus PFNs. Reported-by: Prakash Gupta Signed-off-by: Robin Murphy Reviewed-by: Prakash Gupta Link: https://lore.kernel.org/r/acbd2d092b42738a03a21b417ce64e27f8c91c86.1591103298.git.robin.murphy@arm.com Signed-off-by: Joerg Roedel --- drivers/iommu/iova.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/iommu/iova.c b/drivers/iommu/iova.c index 49fc01f2a28d4..45a251da54537 100644 --- a/drivers/iommu/iova.c +++ b/drivers/iommu/iova.c @@ -811,7 +811,9 @@ iova_magazine_free_pfns(struct iova_magazine *mag, struct iova_domain *iovad) for (i = 0 ; i < mag->size; ++i) { struct iova *iova = private_find_iova(iovad, mag->pfns[i]); - BUG_ON(!iova); + if (WARN_ON(!iova)) + continue; + private_free_iova(iovad, iova); } -- GitLab From f5e383ac8b58f421ac0a005f6df4f2e9eefeb93f Mon Sep 17 00:00:00 2001 From: Denis Efremov Date: Thu, 4 Jun 2020 15:37:09 +0300 Subject: [PATCH 0097/2249] iommu/pamu: Use kzfree() in fsl_pamu_probe() Use kzfree() instead of opencoded memset with 0 followed by kfree(). Null check is not required since kzfree() checks for NULL internally. Signed-off-by: Denis Efremov Link: https://lore.kernel.org/r/20200604123709.96561-1-efremov@linux.com Signed-off-by: Joerg Roedel --- drivers/iommu/fsl_pamu.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/iommu/fsl_pamu.c b/drivers/iommu/fsl_pamu.c index cde281b97afa8..099a11a35fb9c 100644 --- a/drivers/iommu/fsl_pamu.c +++ b/drivers/iommu/fsl_pamu.c @@ -1174,10 +1174,7 @@ static int fsl_pamu_probe(struct platform_device *pdev) if (irq != NO_IRQ) free_irq(irq, data); - if (data) { - memset(data, 0, sizeof(struct pamu_isr_data)); - kfree(data); - } + kzfree(data); if (pamu_regs) iounmap(pamu_regs); -- GitLab From e725a00a8f2e1ae866c29f956d637a889f561882 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Sat, 6 Jun 2020 12:16:17 -0700 Subject: [PATCH 0098/2249] iommu/qcom: Change CONFIG_BIG_ENDIAN to CONFIG_CPU_BIG_ENDIAN CONFIG_BIG_ENDIAN does not exist as a Kconfig symbol. Signed-off-by: Joe Perches Reviewed-by: Rob Clark Link: https://lore.kernel.org/r/5a663096b489b86472fe3bfbd5138c411d669bad.camel@perches.com Signed-off-by: Joerg Roedel --- drivers/iommu/qcom_iommu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/iommu/qcom_iommu.c b/drivers/iommu/qcom_iommu.c index 801768cf86c61..cca39b2091586 100644 --- a/drivers/iommu/qcom_iommu.c +++ b/drivers/iommu/qcom_iommu.c @@ -310,7 +310,7 @@ static int qcom_iommu_init_domain(struct iommu_domain *domain, ARM_SMMU_SCTLR_M | ARM_SMMU_SCTLR_S1_ASIDPNE | ARM_SMMU_SCTLR_CFCFG; - if (IS_ENABLED(CONFIG_BIG_ENDIAN)) + if (IS_ENABLED(CONFIG_CPU_BIG_ENDIAN)) reg |= ARM_SMMU_SCTLR_E; iommu_writel(ctx, ARM_SMMU_CB_SCTLR, reg); -- GitLab From 215c224f4dfa89f1d97500f419092c0110da3c2e Mon Sep 17 00:00:00 2001 From: Yoshihiro Shimoda Date: Thu, 11 Jun 2020 20:10:29 +0900 Subject: [PATCH 0099/2249] dt-bindings: iommu: renesas,ipmmu-vmsa: add r8a77961 support Add support for r8a77961 (R-Car M3-W+). Signed-off-by: Yoshihiro Shimoda Reviewed-by: Geert Uytterhoeven Acked-by: Rob Herring Link: https://lore.kernel.org/r/1591873830-10128-2-git-send-email-yoshihiro.shimoda.uh@renesas.com Signed-off-by: Joerg Roedel --- Documentation/devicetree/bindings/iommu/renesas,ipmmu-vmsa.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/iommu/renesas,ipmmu-vmsa.yaml b/Documentation/devicetree/bindings/iommu/renesas,ipmmu-vmsa.yaml index 39675cf4ed71c..e9d28a4060fa3 100644 --- a/Documentation/devicetree/bindings/iommu/renesas,ipmmu-vmsa.yaml +++ b/Documentation/devicetree/bindings/iommu/renesas,ipmmu-vmsa.yaml @@ -35,6 +35,7 @@ properties: - renesas,ipmmu-r8a774c0 # RZ/G2E - renesas,ipmmu-r8a7795 # R-Car H3 - renesas,ipmmu-r8a7796 # R-Car M3-W + - renesas,ipmmu-r8a77961 # R-Car M3-W+ - renesas,ipmmu-r8a77965 # R-Car M3-N - renesas,ipmmu-r8a77970 # R-Car V3M - renesas,ipmmu-r8a77980 # R-Car V3H -- GitLab From 17fe16181639801bfeba647a1e452a75efe651b4 Mon Sep 17 00:00:00 2001 From: Yoshihiro Shimoda Date: Thu, 11 Jun 2020 20:10:30 +0900 Subject: [PATCH 0100/2249] iommu/renesas: Add support for r8a77961 Add support for r8a77961 (R-Car M3-W+). Signed-off-by: Yoshihiro Shimoda Link: https://lore.kernel.org/r/1591873830-10128-3-git-send-email-yoshihiro.shimoda.uh@renesas.com Signed-off-by: Joerg Roedel --- drivers/iommu/ipmmu-vmsa.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/iommu/ipmmu-vmsa.c b/drivers/iommu/ipmmu-vmsa.c index 4c2972f3153b5..b57b1f213a486 100644 --- a/drivers/iommu/ipmmu-vmsa.c +++ b/drivers/iommu/ipmmu-vmsa.c @@ -3,7 +3,7 @@ * IOMMU API for Renesas VMSA-compatible IPMMU * Author: Laurent Pinchart * - * Copyright (C) 2014 Renesas Electronics Corporation + * Copyright (C) 2014-2020 Renesas Electronics Corporation */ #include @@ -753,6 +753,7 @@ static const struct soc_device_attribute soc_rcar_gen3_whitelist[] = { { .soc_id = "r8a774b1", }, { .soc_id = "r8a774c0", }, { .soc_id = "r8a7795", .revision = "ES3.*" }, + { .soc_id = "r8a77961", }, { .soc_id = "r8a77965", }, { .soc_id = "r8a77990", }, { .soc_id = "r8a77995", }, @@ -969,6 +970,9 @@ static const struct of_device_id ipmmu_of_ids[] = { }, { .compatible = "renesas,ipmmu-r8a7796", .data = &ipmmu_features_rcar_gen3, + }, { + .compatible = "renesas,ipmmu-r8a77961", + .data = &ipmmu_features_rcar_gen3, }, { .compatible = "renesas,ipmmu-r8a77965", .data = &ipmmu_features_rcar_gen3, -- GitLab From 3c5ca501b46b91e68b935b4bd752a0aba5232208 Mon Sep 17 00:00:00 2001 From: Enric Balletbo i Serra Date: Thu, 25 Jun 2020 19:02:41 +0200 Subject: [PATCH 0101/2249] platform/chrome: cros_ec_spi: Document missing function parameters Kerneldoc expects all kernel function members to be documented. Fixes the following W=1 level warnings: cros_ec_spi.c:153: warning: Function parameter or member 'ec_dev' not described in 'receive_n_bytes' cros_ec_spi.c:153: warning: Function parameter or member 'buf' not described in 'receive_n_bytes' cros_ec_spi.c:153: warning: Function parameter or member 'n' not described in 'receive_n_bytes' Signed-off-by: Enric Balletbo i Serra Reviewed-by: Gwendal Grignou --- drivers/platform/chrome/cros_ec_spi.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/platform/chrome/cros_ec_spi.c b/drivers/platform/chrome/cros_ec_spi.c index debea5c4c8293..a74e91df264be 100644 --- a/drivers/platform/chrome/cros_ec_spi.c +++ b/drivers/platform/chrome/cros_ec_spi.c @@ -148,6 +148,10 @@ static int terminate_request(struct cros_ec_device *ec_dev) * receive_n_bytes - receive n bytes from the EC. * * Assumes buf is a pointer into the ec_dev->din buffer + * + * @ec_dev: ChromeOS EC device. + * @buf: Pointer to the buffer receiving the data. + * @n: Number of bytes received. */ static int receive_n_bytes(struct cros_ec_device *ec_dev, u8 *buf, int n) { -- GitLab From 9a876ba58d1e660e7957dd7afd1129b615eb1e04 Mon Sep 17 00:00:00 2001 From: Enric Balletbo i Serra Date: Thu, 25 Jun 2020 19:03:00 +0200 Subject: [PATCH 0102/2249] platform/chrome: cros_ec_rpmsg: Document missing struct parameters Kerneldoc expects all kernel structure member to be documented. Fixes the following W=1 level warnings: cros_ec_rpmsg.c:49: warning: Function parameter or member 'ept' not described in 'cros_ec_rpmsg' cros_ec_rpmsg.c:49: warning: Function parameter or member 'has_pending_host_event' not described in 'cros_ec_rpmsg' cros_ec_rpmsg.c:49: warning: Function parameter or member 'probe_done' not described in 'cros_ec_rpmsg' Signed-off-by: Enric Balletbo i Serra Reviewed-by: Gwendal Grignou --- drivers/platform/chrome/cros_ec_rpmsg.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/platform/chrome/cros_ec_rpmsg.c b/drivers/platform/chrome/cros_ec_rpmsg.c index 7e8629e3db746..30d0ba3b8889c 100644 --- a/drivers/platform/chrome/cros_ec_rpmsg.c +++ b/drivers/platform/chrome/cros_ec_rpmsg.c @@ -38,6 +38,9 @@ struct cros_ec_rpmsg_response { * @rpdev: rpmsg device we are connected to * @xfer_ack: completion for host command transfer. * @host_event_work: Work struct for pending host event. + * @ept: The rpmsg endpoint of this channel. + * @has_pending_host_event: Boolean used to check if there is a pending event. + * @probe_done: Flag to indicate that probe is done. */ struct cros_ec_rpmsg { struct rpmsg_device *rpdev; -- GitLab From aaa3cbbac326c95308e315f1ab964a3369c4d07d Mon Sep 17 00:00:00 2001 From: Qiushi Wu Date: Fri, 22 May 2020 22:16:08 -0500 Subject: [PATCH 0103/2249] platform/chrome: cros_ec_ishtp: Fix a double-unlock issue MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In function cros_ec_ishtp_probe(), "up_write" is already called before function "cros_ec_dev_init". But "up_write" will be called again after the calling of the function "cros_ec_dev_init" failed. Thus add a call of the function “down_write” in this if branch for the completion of the exception handling. Fixes: 26a14267aff2 ("platform/chrome: Add ChromeOS EC ISHTP driver") Signed-off-by: Qiushi Wu Tested-by: Mathew King Signed-off-by: Enric Balletbo i Serra --- drivers/platform/chrome/cros_ec_ishtp.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/platform/chrome/cros_ec_ishtp.c b/drivers/platform/chrome/cros_ec_ishtp.c index ed794a7ddba9b..81364029af367 100644 --- a/drivers/platform/chrome/cros_ec_ishtp.c +++ b/drivers/platform/chrome/cros_ec_ishtp.c @@ -681,8 +681,10 @@ static int cros_ec_ishtp_probe(struct ishtp_cl_device *cl_device) /* Register croc_ec_dev mfd */ rv = cros_ec_dev_init(client_data); - if (rv) + if (rv) { + down_write(&init_lock); goto end_cros_ec_dev_init_error; + } return 0; -- GitLab From 970471914c67b70df24def6b2a30cc42acbebded Mon Sep 17 00:00:00 2001 From: Jean-Philippe Brucker Date: Tue, 16 Jun 2020 16:47:14 +0200 Subject: [PATCH 0104/2249] iommu: Allow page responses without PASID Some PCIe devices do not expect a PASID value in PRI Page Responses. If the "PRG Response PASID Required" bit in the PRI capability is zero, then the OS should not set the PASID field. Similarly on Arm SMMU, responses to stall events do not have a PASID. Currently iommu_page_response() systematically checks that the PASID in the page response corresponds to the one in the page request. This can't work with virtualization because a page response coming from a guest OS won't have a PASID if the passed-through device does not require one. Add a flag to page requests that declares whether the corresponding response needs to have a PASID. When this flag isn't set, allow page responses without PASID. Reported-by: Shameerali Kolothum Thodi Signed-off-by: Jean-Philippe Brucker Link: https://lore.kernel.org/r/20200616144712.748818-1-jean-philippe@linaro.org Signed-off-by: Joerg Roedel --- drivers/iommu/iommu.c | 23 +++++++++++++++++------ include/uapi/linux/iommu.h | 6 +++++- 2 files changed, 22 insertions(+), 7 deletions(-) diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c index d43120eb1dc56..1ed1e14a1f0cf 100644 --- a/drivers/iommu/iommu.c +++ b/drivers/iommu/iommu.c @@ -1185,11 +1185,12 @@ EXPORT_SYMBOL_GPL(iommu_report_device_fault); int iommu_page_response(struct device *dev, struct iommu_page_response *msg) { - bool pasid_valid; + bool needs_pasid; int ret = -EINVAL; struct iommu_fault_event *evt; struct iommu_fault_page_request *prm; struct dev_iommu *param = dev->iommu; + bool has_pasid = msg->flags & IOMMU_PAGE_RESP_PASID_VALID; struct iommu_domain *domain = iommu_get_domain_for_dev(dev); if (!domain || !domain->ops->page_response) @@ -1214,14 +1215,24 @@ int iommu_page_response(struct device *dev, */ list_for_each_entry(evt, ¶m->fault_param->faults, list) { prm = &evt->fault.prm; - pasid_valid = prm->flags & IOMMU_FAULT_PAGE_REQUEST_PASID_VALID; + if (prm->grpid != msg->grpid) + continue; - if ((pasid_valid && prm->pasid != msg->pasid) || - prm->grpid != msg->grpid) + /* + * If the PASID is required, the corresponding request is + * matched using the group ID, the PASID valid bit and the PASID + * value. Otherwise only the group ID matches request and + * response. + */ + needs_pasid = prm->flags & IOMMU_FAULT_PAGE_RESPONSE_NEEDS_PASID; + if (needs_pasid && (!has_pasid || msg->pasid != prm->pasid)) continue; - /* Sanitize the reply */ - msg->flags = pasid_valid ? IOMMU_PAGE_RESP_PASID_VALID : 0; + if (!needs_pasid && has_pasid) { + /* No big deal, just clear it. */ + msg->flags &= ~IOMMU_PAGE_RESP_PASID_VALID; + msg->pasid = 0; + } ret = domain->ops->page_response(dev, evt, msg); list_del(&evt->list); diff --git a/include/uapi/linux/iommu.h b/include/uapi/linux/iommu.h index e907b7091a463..c2b2caf9ed412 100644 --- a/include/uapi/linux/iommu.h +++ b/include/uapi/linux/iommu.h @@ -81,7 +81,10 @@ struct iommu_fault_unrecoverable { /** * struct iommu_fault_page_request - Page Request data * @flags: encodes whether the corresponding fields are valid and whether this - * is the last page in group (IOMMU_FAULT_PAGE_REQUEST_* values) + * is the last page in group (IOMMU_FAULT_PAGE_REQUEST_* values). + * When IOMMU_FAULT_PAGE_RESPONSE_NEEDS_PASID is set, the page response + * must have the same PASID value as the page request. When it is clear, + * the page response should not have a PASID. * @pasid: Process Address Space ID * @grpid: Page Request Group Index * @perm: requested page permissions (IOMMU_FAULT_PERM_* values) @@ -92,6 +95,7 @@ struct iommu_fault_page_request { #define IOMMU_FAULT_PAGE_REQUEST_PASID_VALID (1 << 0) #define IOMMU_FAULT_PAGE_REQUEST_LAST_PAGE (1 << 1) #define IOMMU_FAULT_PAGE_REQUEST_PRIV_DATA (1 << 2) +#define IOMMU_FAULT_PAGE_RESPONSE_NEEDS_PASID (1 << 3) __u32 flags; __u32 pasid; __u32 grpid; -- GitLab From 9a295ff0ffc94e1be60d604fee0cce4fbb3b8964 Mon Sep 17 00:00:00 2001 From: Paul Menzel Date: Wed, 17 Jun 2020 00:04:20 +0200 Subject: [PATCH 0105/2249] iommu/amd: Print extended features in one line to fix divergent log levels Currently, Linux logs the two messages below. [ 0.979142] pci 0000:00:00.2: AMD-Vi: Extended features (0xf77ef22294ada): [ 0.979546] PPR NX GT IA GA PC GA_vAPIC The log level of these lines differs though. The first one has level *info*, while the second has level *warn*, which is confusing. $ dmesg -T --level=info | grep "Extended features" [Tue Jun 16 21:46:58 2020] pci 0000:00:00.2: AMD-Vi: Extended features (0xf77ef22294ada): $ dmesg -T --level=warn | grep "PPR" [Tue Jun 16 21:46:58 2020] PPR NX GT IA GA PC GA_vAPIC The problem is, that commit 3928aa3f57 ("iommu/amd: Detect and enable guest vAPIC support") introduced a newline, causing `pr_cont()`, used to print the features, to default back to the default log level. /** * pr_cont - Continues a previous log message in the same line. * @fmt: format string * @...: arguments for the format string * * This macro expands to a printk with KERN_CONT loglevel. It should only be * used when continuing a log message with no newline ('\n') enclosed. Otherwise * it defaults back to KERN_DEFAULT loglevel. */ #define pr_cont(fmt, ...) \ printk(KERN_CONT fmt, ##__VA_ARGS__) So, remove the line break, so only one line is logged. Fixes: 3928aa3f57 ("iommu/amd: Detect and enable guest vAPIC support") Signed-off-by: Paul Menzel Reviewed-by: Suravee Suthikulpanit Cc: Suravee Suthikulpanit Cc: iommu@lists.linux-foundation.org Link: https://lore.kernel.org/r/20200616220420.19466-1-pmenzel@molgen.mpg.de Signed-off-by: Joerg Roedel --- drivers/iommu/amd/init.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/iommu/amd/init.c b/drivers/iommu/amd/init.c index 6ebd4825e3206..232683ea10e0b 100644 --- a/drivers/iommu/amd/init.c +++ b/drivers/iommu/amd/init.c @@ -1842,7 +1842,7 @@ static void print_iommu_info(void) pci_info(pdev, "Found IOMMU cap 0x%hx\n", iommu->cap_ptr); if (iommu->cap & (1 << IOMMU_CAP_EFR)) { - pci_info(pdev, "Extended features (%#llx):\n", + pci_info(pdev, "Extended features (%#llx):", iommu->features); for (i = 0; i < ARRAY_SIZE(feat_str); ++i) { if (iommu_feature(iommu, (1ULL << i))) -- GitLab From 70fcd3592b05fde4d95938cd5a20e996b4ef4e15 Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Fri, 26 Jun 2020 10:05:46 +0200 Subject: [PATCH 0106/2249] iommu/amd: Add helper functions to update domain->pt_root Do not call atomic64_set() directly to update the domain page-table root and use two new helper functions. This makes it easier to implement additional work necessary when the page-table is updated. Signed-off-by: Joerg Roedel Link: https://lore.kernel.org/r/20200626080547.24865-2-joro@8bytes.org --- drivers/iommu/amd/iommu.c | 31 ++++++++++++++++++++----------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/drivers/iommu/amd/iommu.c b/drivers/iommu/amd/iommu.c index 74cca17571725..5286ddcfc2f9f 100644 --- a/drivers/iommu/amd/iommu.c +++ b/drivers/iommu/amd/iommu.c @@ -162,7 +162,18 @@ static void amd_iommu_domain_get_pgtable(struct protection_domain *domain, pgtable->mode = pt_root & 7; /* lowest 3 bits encode pgtable mode */ } -static u64 amd_iommu_domain_encode_pgtable(u64 *root, int mode) +static void amd_iommu_domain_set_pt_root(struct protection_domain *domain, u64 root) +{ + atomic64_set(&domain->pt_root, root); +} + +static void amd_iommu_domain_clr_pt_root(struct protection_domain *domain) +{ + amd_iommu_domain_set_pt_root(domain, 0); +} + +static void amd_iommu_domain_set_pgtable(struct protection_domain *domain, + u64 *root, int mode) { u64 pt_root; @@ -170,7 +181,7 @@ static u64 amd_iommu_domain_encode_pgtable(u64 *root, int mode) pt_root = mode & 7; pt_root |= (u64)root; - return pt_root; + amd_iommu_domain_set_pt_root(domain, pt_root); } static struct iommu_dev_data *alloc_dev_data(u16 devid) @@ -1410,7 +1421,7 @@ static bool increase_address_space(struct protection_domain *domain, struct domain_pgtable pgtable; unsigned long flags; bool ret = true; - u64 *pte, root; + u64 *pte; spin_lock_irqsave(&domain->lock, flags); @@ -1438,8 +1449,7 @@ static bool increase_address_space(struct protection_domain *domain, * Device Table needs to be updated and flushed before the new root can * be published. */ - root = amd_iommu_domain_encode_pgtable(pte, pgtable.mode); - atomic64_set(&domain->pt_root, root); + amd_iommu_domain_set_pgtable(domain, pte, pgtable.mode); ret = true; @@ -2319,7 +2329,7 @@ static void protection_domain_free(struct protection_domain *domain) domain_id_free(domain->id); amd_iommu_domain_get_pgtable(domain, &pgtable); - atomic64_set(&domain->pt_root, 0); + amd_iommu_domain_clr_pt_root(domain); free_pagetable(&pgtable); kfree(domain); @@ -2327,7 +2337,7 @@ static void protection_domain_free(struct protection_domain *domain) static int protection_domain_init(struct protection_domain *domain, int mode) { - u64 *pt_root = NULL, root; + u64 *pt_root = NULL; BUG_ON(mode < PAGE_MODE_NONE || mode > PAGE_MODE_6_LEVEL); @@ -2343,8 +2353,7 @@ static int protection_domain_init(struct protection_domain *domain, int mode) return -ENOMEM; } - root = amd_iommu_domain_encode_pgtable(pt_root, mode); - atomic64_set(&domain->pt_root, root); + amd_iommu_domain_set_pgtable(domain, pt_root, mode); return 0; } @@ -2713,8 +2722,8 @@ void amd_iommu_domain_direct_map(struct iommu_domain *dom) /* First save pgtable configuration*/ amd_iommu_domain_get_pgtable(domain, &pgtable); - /* Update data structure */ - atomic64_set(&domain->pt_root, 0); + /* Remove page-table from domain */ + amd_iommu_domain_clr_pt_root(domain); /* Make changes visible to IOMMUs */ update_domain(domain); -- GitLab From 0f45b04da18305726c18d4b6169c4083f301d91c Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Thu, 25 Jun 2020 15:08:24 +0200 Subject: [PATCH 0107/2249] iommu/exynos: Use dev_iommu_priv_get/set() Remove the use of dev->archdata.iommu and use the private per-device pointer provided by IOMMU core code instead. Signed-off-by: Joerg Roedel Reviewed-by: Jerry Snitselaar Acked-by: Marek Szyprowski Link: https://lore.kernel.org/r/20200625130836.1916-2-joro@8bytes.org --- drivers/iommu/exynos-iommu.c | 20 +++++++++---------- .../media/platform/s5p-mfc/s5p_mfc_iommu.h | 4 +++- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c index 60c8a56e4a3f8..6a9b67302369d 100644 --- a/drivers/iommu/exynos-iommu.c +++ b/drivers/iommu/exynos-iommu.c @@ -173,7 +173,7 @@ static u32 lv2ent_offset(sysmmu_iova_t iova) #define REG_V5_FAULT_AR_VA 0x070 #define REG_V5_FAULT_AW_VA 0x080 -#define has_sysmmu(dev) (dev->archdata.iommu != NULL) +#define has_sysmmu(dev) (dev_iommu_priv_get(dev) != NULL) static struct device *dma_dev; static struct kmem_cache *lv2table_kmem_cache; @@ -226,7 +226,7 @@ static const struct sysmmu_fault_info sysmmu_v5_faults[] = { }; /* - * This structure is attached to dev.archdata.iommu of the master device + * This structure is attached to dev->iommu->priv of the master device * on device add, contains a list of SYSMMU controllers defined by device tree, * which are bound to given master device. It is usually referenced by 'owner' * pointer. @@ -670,7 +670,7 @@ static int __maybe_unused exynos_sysmmu_suspend(struct device *dev) struct device *master = data->master; if (master) { - struct exynos_iommu_owner *owner = master->archdata.iommu; + struct exynos_iommu_owner *owner = dev_iommu_priv_get(master); mutex_lock(&owner->rpm_lock); if (data->domain) { @@ -688,7 +688,7 @@ static int __maybe_unused exynos_sysmmu_resume(struct device *dev) struct device *master = data->master; if (master) { - struct exynos_iommu_owner *owner = master->archdata.iommu; + struct exynos_iommu_owner *owner = dev_iommu_priv_get(master); mutex_lock(&owner->rpm_lock); if (data->domain) { @@ -837,8 +837,8 @@ static void exynos_iommu_domain_free(struct iommu_domain *iommu_domain) static void exynos_iommu_detach_device(struct iommu_domain *iommu_domain, struct device *dev) { - struct exynos_iommu_owner *owner = dev->archdata.iommu; struct exynos_iommu_domain *domain = to_exynos_domain(iommu_domain); + struct exynos_iommu_owner *owner = dev_iommu_priv_get(dev); phys_addr_t pagetable = virt_to_phys(domain->pgtable); struct sysmmu_drvdata *data, *next; unsigned long flags; @@ -875,8 +875,8 @@ static void exynos_iommu_detach_device(struct iommu_domain *iommu_domain, static int exynos_iommu_attach_device(struct iommu_domain *iommu_domain, struct device *dev) { - struct exynos_iommu_owner *owner = dev->archdata.iommu; struct exynos_iommu_domain *domain = to_exynos_domain(iommu_domain); + struct exynos_iommu_owner *owner = dev_iommu_priv_get(dev); struct sysmmu_drvdata *data; phys_addr_t pagetable = virt_to_phys(domain->pgtable); unsigned long flags; @@ -1237,7 +1237,7 @@ static phys_addr_t exynos_iommu_iova_to_phys(struct iommu_domain *iommu_domain, static struct iommu_device *exynos_iommu_probe_device(struct device *dev) { - struct exynos_iommu_owner *owner = dev->archdata.iommu; + struct exynos_iommu_owner *owner = dev_iommu_priv_get(dev); struct sysmmu_drvdata *data; if (!has_sysmmu(dev)) @@ -1263,7 +1263,7 @@ static struct iommu_device *exynos_iommu_probe_device(struct device *dev) static void exynos_iommu_release_device(struct device *dev) { - struct exynos_iommu_owner *owner = dev->archdata.iommu; + struct exynos_iommu_owner *owner = dev_iommu_priv_get(dev); struct sysmmu_drvdata *data; if (!has_sysmmu(dev)) @@ -1287,8 +1287,8 @@ static void exynos_iommu_release_device(struct device *dev) static int exynos_iommu_of_xlate(struct device *dev, struct of_phandle_args *spec) { - struct exynos_iommu_owner *owner = dev->archdata.iommu; struct platform_device *sysmmu = of_find_device_by_node(spec->np); + struct exynos_iommu_owner *owner = dev_iommu_priv_get(dev); struct sysmmu_drvdata *data, *entry; if (!sysmmu) @@ -1305,7 +1305,7 @@ static int exynos_iommu_of_xlate(struct device *dev, INIT_LIST_HEAD(&owner->controllers); mutex_init(&owner->rpm_lock); - dev->archdata.iommu = owner; + dev_iommu_priv_set(dev, owner); } list_for_each_entry(entry, &owner->controllers, owner_node) diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_iommu.h b/drivers/media/platform/s5p-mfc/s5p_mfc_iommu.h index 152a713fff78c..1a32266b7ddc2 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_iommu.h +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_iommu.h @@ -9,9 +9,11 @@ #if defined(CONFIG_EXYNOS_IOMMU) +#include + static inline bool exynos_is_iommu_available(struct device *dev) { - return dev->archdata.iommu != NULL; + return dev_iommu_priv_get(dev) != NULL; } #else -- GitLab From 01b9d4e21148c89fdbab3d6b3705f9791314b631 Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Thu, 25 Jun 2020 15:08:25 +0200 Subject: [PATCH 0108/2249] iommu/vt-d: Use dev_iommu_priv_get/set() Remove the use of dev->archdata.iommu and use the private per-device pointer provided by IOMMU core code instead. Signed-off-by: Joerg Roedel Reviewed-by: Jerry Snitselaar Reviewed-by: Lu Baolu Link: https://lore.kernel.org/r/20200625130836.1916-3-joro@8bytes.org --- .../gpu/drm/i915/selftests/mock_gem_device.c | 10 ++++++++-- drivers/iommu/intel/iommu.c | 18 +++++++++--------- 2 files changed, 17 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/i915/selftests/mock_gem_device.c b/drivers/gpu/drm/i915/selftests/mock_gem_device.c index 9b105b811f1f4..e08601905a64a 100644 --- a/drivers/gpu/drm/i915/selftests/mock_gem_device.c +++ b/drivers/gpu/drm/i915/selftests/mock_gem_device.c @@ -24,6 +24,7 @@ #include #include +#include #include @@ -118,6 +119,9 @@ struct drm_i915_private *mock_gem_device(void) { struct drm_i915_private *i915; struct pci_dev *pdev; +#if IS_ENABLED(CONFIG_IOMMU_API) && defined(CONFIG_INTEL_IOMMU) + struct dev_iommu iommu; +#endif int err; pdev = kzalloc(sizeof(*pdev), GFP_KERNEL); @@ -136,8 +140,10 @@ struct drm_i915_private *mock_gem_device(void) dma_coerce_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64)); #if IS_ENABLED(CONFIG_IOMMU_API) && defined(CONFIG_INTEL_IOMMU) - /* hack to disable iommu for the fake device; force identity mapping */ - pdev->dev.archdata.iommu = (void *)-1; + /* HACK HACK HACK to disable iommu for the fake device; force identity mapping */ + memset(&iommu, 0, sizeof(iommu)); + iommu.priv = (void *)-1; + pdev->dev.iommu = &iommu; #endif pci_set_drvdata(pdev, i915); diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c index d759e7234e982..2ce490c2eab89 100644 --- a/drivers/iommu/intel/iommu.c +++ b/drivers/iommu/intel/iommu.c @@ -372,7 +372,7 @@ struct device_domain_info *get_domain_info(struct device *dev) if (!dev) return NULL; - info = dev->archdata.iommu; + info = dev_iommu_priv_get(dev); if (unlikely(info == DUMMY_DEVICE_DOMAIN_INFO || info == DEFER_DEVICE_DOMAIN_INFO)) return NULL; @@ -743,12 +743,12 @@ struct context_entry *iommu_context_addr(struct intel_iommu *iommu, u8 bus, static int iommu_dummy(struct device *dev) { - return dev->archdata.iommu == DUMMY_DEVICE_DOMAIN_INFO; + return dev_iommu_priv_get(dev) == DUMMY_DEVICE_DOMAIN_INFO; } static bool attach_deferred(struct device *dev) { - return dev->archdata.iommu == DEFER_DEVICE_DOMAIN_INFO; + return dev_iommu_priv_get(dev) == DEFER_DEVICE_DOMAIN_INFO; } /** @@ -2420,7 +2420,7 @@ static inline void unlink_domain_info(struct device_domain_info *info) list_del(&info->link); list_del(&info->global); if (info->dev) - info->dev->archdata.iommu = NULL; + dev_iommu_priv_set(info->dev, NULL); } static void domain_remove_dev_info(struct dmar_domain *domain) @@ -2453,7 +2453,7 @@ static void do_deferred_attach(struct device *dev) { struct iommu_domain *domain; - dev->archdata.iommu = NULL; + dev_iommu_priv_set(dev, NULL); domain = iommu_get_domain_for_dev(dev); if (domain) intel_iommu_attach_device(domain, dev); @@ -2599,7 +2599,7 @@ static struct dmar_domain *dmar_insert_one_dev_info(struct intel_iommu *iommu, list_add(&info->link, &domain->devices); list_add(&info->global, &device_domain_list); if (dev) - dev->archdata.iommu = info; + dev_iommu_priv_set(dev, info); spin_unlock_irqrestore(&device_domain_lock, flags); /* PASID table is mandatory for a PCI device in scalable mode. */ @@ -4004,7 +4004,7 @@ static void quirk_ioat_snb_local_iommu(struct pci_dev *pdev) if (!drhd || drhd->reg_base_addr - vtbar != 0xa000) { pr_warn_once(FW_BUG "BIOS assigned incorrect VT-d unit for Intel(R) QuickData Technology device\n"); add_taint(TAINT_FIRMWARE_WORKAROUND, LOCKDEP_STILL_OK); - pdev->dev.archdata.iommu = DUMMY_DEVICE_DOMAIN_INFO; + dev_iommu_priv_set(&pdev->dev, DUMMY_DEVICE_DOMAIN_INFO); } } DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IOAT_SNB, quirk_ioat_snb_local_iommu); @@ -4043,7 +4043,7 @@ static void __init init_no_remapping_devices(void) drhd->ignored = 1; for_each_active_dev_scope(drhd->devices, drhd->devices_cnt, i, dev) - dev->archdata.iommu = DUMMY_DEVICE_DOMAIN_INFO; + dev_iommu_priv_set(dev, DUMMY_DEVICE_DOMAIN_INFO); } } } @@ -5665,7 +5665,7 @@ static struct iommu_device *intel_iommu_probe_device(struct device *dev) return ERR_PTR(-ENODEV); if (translation_pre_enabled(iommu)) - dev->archdata.iommu = DEFER_DEVICE_DOMAIN_INFO; + dev_iommu_priv_set(dev, DEFER_DEVICE_DOMAIN_INFO); return &iommu->iommu; } -- GitLab From 4bbe0c7ccc431dcf06242860a7900f92800724c0 Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Thu, 25 Jun 2020 15:08:26 +0200 Subject: [PATCH 0109/2249] iommu/msm: Use dev_iommu_priv_get/set() Remove the use of dev->archdata.iommu and use the private per-device pointer provided by IOMMU core code instead. Signed-off-by: Joerg Roedel Reviewed-by: Jerry Snitselaar Link: https://lore.kernel.org/r/20200625130836.1916-4-joro@8bytes.org --- drivers/iommu/msm_iommu.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/iommu/msm_iommu.c b/drivers/iommu/msm_iommu.c index 3d8a63555c250..f773cc85f311f 100644 --- a/drivers/iommu/msm_iommu.c +++ b/drivers/iommu/msm_iommu.c @@ -593,14 +593,14 @@ static void insert_iommu_master(struct device *dev, struct msm_iommu_dev **iommu, struct of_phandle_args *spec) { - struct msm_iommu_ctx_dev *master = dev->archdata.iommu; + struct msm_iommu_ctx_dev *master = dev_iommu_priv_get(dev); int sid; if (list_empty(&(*iommu)->ctx_list)) { master = kzalloc(sizeof(*master), GFP_ATOMIC); master->of_node = dev->of_node; list_add(&master->list, &(*iommu)->ctx_list); - dev->archdata.iommu = master; + dev_iommu_priv_set(dev, master); } for (sid = 0; sid < master->num_mids; sid++) -- GitLab From 97ea1202601a7f936c9c9a86f900ec001cb589d3 Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Thu, 25 Jun 2020 15:08:27 +0200 Subject: [PATCH 0110/2249] iommu/omap: Use dev_iommu_priv_get/set() Remove the use of dev->archdata.iommu and use the private per-device pointer provided by IOMMU core code instead. Signed-off-by: Joerg Roedel Reviewed-by: Jerry Snitselaar Link: https://lore.kernel.org/r/20200625130836.1916-5-joro@8bytes.org --- drivers/iommu/omap-iommu.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/iommu/omap-iommu.c b/drivers/iommu/omap-iommu.c index c8282cc212cbd..e84ead6fb234a 100644 --- a/drivers/iommu/omap-iommu.c +++ b/drivers/iommu/omap-iommu.c @@ -71,7 +71,7 @@ static struct omap_iommu_domain *to_omap_domain(struct iommu_domain *dom) **/ void omap_iommu_save_ctx(struct device *dev) { - struct omap_iommu_arch_data *arch_data = dev->archdata.iommu; + struct omap_iommu_arch_data *arch_data = dev_iommu_priv_get(dev); struct omap_iommu *obj; u32 *p; int i; @@ -101,7 +101,7 @@ EXPORT_SYMBOL_GPL(omap_iommu_save_ctx); **/ void omap_iommu_restore_ctx(struct device *dev) { - struct omap_iommu_arch_data *arch_data = dev->archdata.iommu; + struct omap_iommu_arch_data *arch_data = dev_iommu_priv_get(dev); struct omap_iommu *obj; u32 *p; int i; @@ -1398,7 +1398,7 @@ static size_t omap_iommu_unmap(struct iommu_domain *domain, unsigned long da, static int omap_iommu_count(struct device *dev) { - struct omap_iommu_arch_data *arch_data = dev->archdata.iommu; + struct omap_iommu_arch_data *arch_data = dev_iommu_priv_get(dev); int count = 0; while (arch_data->iommu_dev) { @@ -1459,8 +1459,8 @@ static void omap_iommu_detach_fini(struct omap_iommu_domain *odomain) static int omap_iommu_attach_dev(struct iommu_domain *domain, struct device *dev) { + struct omap_iommu_arch_data *arch_data = dev_iommu_priv_get(dev); struct omap_iommu_domain *omap_domain = to_omap_domain(domain); - struct omap_iommu_arch_data *arch_data = dev->archdata.iommu; struct omap_iommu_device *iommu; struct omap_iommu *oiommu; int ret = 0; @@ -1524,7 +1524,7 @@ omap_iommu_attach_dev(struct iommu_domain *domain, struct device *dev) static void _omap_iommu_detach_dev(struct omap_iommu_domain *omap_domain, struct device *dev) { - struct omap_iommu_arch_data *arch_data = dev->archdata.iommu; + struct omap_iommu_arch_data *arch_data = dev_iommu_priv_get(dev); struct omap_iommu_device *iommu = omap_domain->iommus; struct omap_iommu *oiommu; int i; @@ -1650,7 +1650,7 @@ static struct iommu_device *omap_iommu_probe_device(struct device *dev) int num_iommus, i; /* - * Allocate the archdata iommu structure for DT-based devices. + * Allocate the per-device iommu structure for DT-based devices. * * TODO: Simplify this when removing non-DT support completely from the * IOMMU users. @@ -1698,7 +1698,7 @@ static struct iommu_device *omap_iommu_probe_device(struct device *dev) of_node_put(np); } - dev->archdata.iommu = arch_data; + dev_iommu_priv_set(dev, arch_data); /* * use the first IOMMU alone for the sysfs device linking. @@ -1712,19 +1712,19 @@ static struct iommu_device *omap_iommu_probe_device(struct device *dev) static void omap_iommu_release_device(struct device *dev) { - struct omap_iommu_arch_data *arch_data = dev->archdata.iommu; + struct omap_iommu_arch_data *arch_data = dev_iommu_priv_get(dev); if (!dev->of_node || !arch_data) return; - dev->archdata.iommu = NULL; + dev_iommu_priv_set(dev, NULL); kfree(arch_data); } static struct iommu_group *omap_iommu_device_group(struct device *dev) { - struct omap_iommu_arch_data *arch_data = dev->archdata.iommu; + struct omap_iommu_arch_data *arch_data = dev_iommu_priv_get(dev); struct iommu_group *group = ERR_PTR(-EINVAL); if (!arch_data) -- GitLab From 8b9cc3b71bfda8e7c273b8f0fd80a8860ed077ad Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Thu, 25 Jun 2020 15:08:28 +0200 Subject: [PATCH 0111/2249] iommu/rockchip: Use dev_iommu_priv_get/set() Remove the use of dev->archdata.iommu and use the private per-device pointer provided by IOMMU core code instead. Signed-off-by: Joerg Roedel Reviewed-by: Jerry Snitselaar Link: https://lore.kernel.org/r/20200625130836.1916-6-joro@8bytes.org --- drivers/iommu/rockchip-iommu.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/iommu/rockchip-iommu.c b/drivers/iommu/rockchip-iommu.c index d25c2486ca070..e5d86b7177dec 100644 --- a/drivers/iommu/rockchip-iommu.c +++ b/drivers/iommu/rockchip-iommu.c @@ -836,7 +836,7 @@ static size_t rk_iommu_unmap(struct iommu_domain *domain, unsigned long _iova, static struct rk_iommu *rk_iommu_from_dev(struct device *dev) { - struct rk_iommudata *data = dev->archdata.iommu; + struct rk_iommudata *data = dev_iommu_priv_get(dev); return data ? data->iommu : NULL; } @@ -1059,7 +1059,7 @@ static struct iommu_device *rk_iommu_probe_device(struct device *dev) struct rk_iommudata *data; struct rk_iommu *iommu; - data = dev->archdata.iommu; + data = dev_iommu_priv_get(dev); if (!data) return ERR_PTR(-ENODEV); @@ -1073,7 +1073,7 @@ static struct iommu_device *rk_iommu_probe_device(struct device *dev) static void rk_iommu_release_device(struct device *dev) { - struct rk_iommudata *data = dev->archdata.iommu; + struct rk_iommudata *data = dev_iommu_priv_get(dev); device_link_del(data->link); } @@ -1100,7 +1100,7 @@ static int rk_iommu_of_xlate(struct device *dev, iommu_dev = of_find_device_by_node(args->np); data->iommu = platform_get_drvdata(iommu_dev); - dev->archdata.iommu = data; + dev_iommu_priv_set(dev, data); platform_device_put(iommu_dev); -- GitLab From a5616e24609a2bb3dc6ea1ab360207fa1198c976 Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Thu, 25 Jun 2020 15:08:29 +0200 Subject: [PATCH 0112/2249] iommu/tegra: Use dev_iommu_priv_get/set() Remove the use of dev->archdata.iommu and use the private per-device pointer provided by IOMMU core code instead. Signed-off-by: Joerg Roedel Reviewed-by: Jerry Snitselaar Link: https://lore.kernel.org/r/20200625130836.1916-7-joro@8bytes.org --- drivers/iommu/tegra-gart.c | 8 ++++---- drivers/iommu/tegra-smmu.c | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/iommu/tegra-gart.c b/drivers/iommu/tegra-gart.c index 5fbdff6ff41a8..fac720273889c 100644 --- a/drivers/iommu/tegra-gart.c +++ b/drivers/iommu/tegra-gart.c @@ -113,8 +113,8 @@ static int gart_iommu_attach_dev(struct iommu_domain *domain, if (gart->active_domain && gart->active_domain != domain) { ret = -EBUSY; - } else if (dev->archdata.iommu != domain) { - dev->archdata.iommu = domain; + } else if (dev_iommu_priv_get(dev) != domain) { + dev_iommu_priv_set(dev, domain); gart->active_domain = domain; gart->active_devices++; } @@ -131,8 +131,8 @@ static void gart_iommu_detach_dev(struct iommu_domain *domain, spin_lock(&gart->dom_lock); - if (dev->archdata.iommu == domain) { - dev->archdata.iommu = NULL; + if (dev_iommu_priv_get(dev) == domain) { + dev_iommu_priv_set(dev, NULL); if (--gart->active_devices == 0) gart->active_domain = NULL; diff --git a/drivers/iommu/tegra-smmu.c b/drivers/iommu/tegra-smmu.c index 7426b7666e2bd..124c8848ab7ec 100644 --- a/drivers/iommu/tegra-smmu.c +++ b/drivers/iommu/tegra-smmu.c @@ -465,7 +465,7 @@ static void tegra_smmu_as_unprepare(struct tegra_smmu *smmu, static int tegra_smmu_attach_dev(struct iommu_domain *domain, struct device *dev) { - struct tegra_smmu *smmu = dev->archdata.iommu; + struct tegra_smmu *smmu = dev_iommu_priv_get(dev); struct tegra_smmu_as *as = to_smmu_as(domain); struct device_node *np = dev->of_node; struct of_phandle_args args; @@ -780,7 +780,7 @@ static struct iommu_device *tegra_smmu_probe_device(struct device *dev) * supported by the Linux kernel, so abort after the * first match. */ - dev->archdata.iommu = smmu; + dev_iommu_priv_set(dev, smmu); break; } @@ -797,7 +797,7 @@ static struct iommu_device *tegra_smmu_probe_device(struct device *dev) static void tegra_smmu_release_device(struct device *dev) { - dev->archdata.iommu = NULL; + dev_iommu_priv_set(dev, NULL); } static const struct tegra_smmu_group_soc * @@ -856,7 +856,7 @@ static struct iommu_group *tegra_smmu_group_get(struct tegra_smmu *smmu, static struct iommu_group *tegra_smmu_device_group(struct device *dev) { struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev); - struct tegra_smmu *smmu = dev->archdata.iommu; + struct tegra_smmu *smmu = dev_iommu_priv_get(dev); struct iommu_group *group; group = tegra_smmu_group_get(smmu, fwspec->ids[0]); -- GitLab From 2263d818bceff516254bfce4091632530720505a Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Thu, 25 Jun 2020 15:08:30 +0200 Subject: [PATCH 0113/2249] iommu/pamu: Use dev_iommu_priv_get/set() Remove the use of dev->archdata.iommu_domain and use the private per-device pointer provided by IOMMU core code instead. Signed-off-by: Joerg Roedel Reviewed-by: Jerry Snitselaar Link: https://lore.kernel.org/r/20200625130836.1916-8-joro@8bytes.org --- drivers/iommu/fsl_pamu_domain.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/iommu/fsl_pamu_domain.c b/drivers/iommu/fsl_pamu_domain.c index 928d37771ece0..b2110767caf49 100644 --- a/drivers/iommu/fsl_pamu_domain.c +++ b/drivers/iommu/fsl_pamu_domain.c @@ -323,7 +323,7 @@ static void remove_device_ref(struct device_domain_info *info, u32 win_cnt) pamu_disable_liodn(info->liodn); spin_unlock_irqrestore(&iommu_lock, flags); spin_lock_irqsave(&device_domain_lock, flags); - info->dev->archdata.iommu_domain = NULL; + dev_iommu_priv_set(info->dev, NULL); kmem_cache_free(iommu_devinfo_cache, info); spin_unlock_irqrestore(&device_domain_lock, flags); } @@ -352,7 +352,7 @@ static void attach_device(struct fsl_dma_domain *dma_domain, int liodn, struct d * Check here if the device is already attached to domain or not. * If the device is already attached to a domain detach it. */ - old_domain_info = dev->archdata.iommu_domain; + old_domain_info = dev_iommu_priv_get(dev); if (old_domain_info && old_domain_info->domain != dma_domain) { spin_unlock_irqrestore(&device_domain_lock, flags); detach_device(dev, old_domain_info->domain); @@ -371,8 +371,8 @@ static void attach_device(struct fsl_dma_domain *dma_domain, int liodn, struct d * the info for the first LIODN as all * LIODNs share the same domain */ - if (!dev->archdata.iommu_domain) - dev->archdata.iommu_domain = info; + if (!dev_iommu_priv_get(dev)) + dev_iommu_priv_set(dev, info); spin_unlock_irqrestore(&device_domain_lock, flags); } -- GitLab From 589601720d9d0366670eb415a4a62692d7af3713 Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Thu, 25 Jun 2020 15:08:31 +0200 Subject: [PATCH 0114/2249] iommu/mediatek: Do no use dev->archdata.iommu The iommu private pointer is already used in the Mediatek IOMMU v1 driver, so move the dma_iommu_mapping pointer into 'struct mtk_iommu_data' and do not use dev->archdata.iommu anymore. Signed-off-by: Joerg Roedel Reviewed-by: Jerry Snitselaar Link: https://lore.kernel.org/r/20200625130836.1916-9-joro@8bytes.org --- drivers/iommu/mtk_iommu.h | 2 ++ drivers/iommu/mtk_iommu_v1.c | 10 ++++------ 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/iommu/mtk_iommu.h b/drivers/iommu/mtk_iommu.h index ea949a324e338..1682406e98dc7 100644 --- a/drivers/iommu/mtk_iommu.h +++ b/drivers/iommu/mtk_iommu.h @@ -62,6 +62,8 @@ struct mtk_iommu_data { struct iommu_device iommu; const struct mtk_iommu_plat_data *plat_data; + struct dma_iommu_mapping *mapping; /* For mtk_iommu_v1.c */ + struct list_head list; struct mtk_smi_larb_iommu larb_imu[MTK_LARB_NR_MAX]; }; diff --git a/drivers/iommu/mtk_iommu_v1.c b/drivers/iommu/mtk_iommu_v1.c index c9d79cff4d178..82ddfe9170d4d 100644 --- a/drivers/iommu/mtk_iommu_v1.c +++ b/drivers/iommu/mtk_iommu_v1.c @@ -269,7 +269,7 @@ static int mtk_iommu_attach_device(struct iommu_domain *domain, int ret; /* Only allow the domain created internally. */ - mtk_mapping = data->dev->archdata.iommu; + mtk_mapping = data->mapping; if (mtk_mapping->domain != domain) return 0; @@ -369,7 +369,6 @@ static int mtk_iommu_create_mapping(struct device *dev, struct mtk_iommu_data *data; struct platform_device *m4updev; struct dma_iommu_mapping *mtk_mapping; - struct device *m4udev; int ret; if (args->args_count != 1) { @@ -401,8 +400,7 @@ static int mtk_iommu_create_mapping(struct device *dev, return ret; data = dev_iommu_priv_get(dev); - m4udev = data->dev; - mtk_mapping = m4udev->archdata.iommu; + mtk_mapping = data->mapping; if (!mtk_mapping) { /* MTK iommu support 4GB iova address space. */ mtk_mapping = arm_iommu_create_mapping(&platform_bus_type, @@ -410,7 +408,7 @@ static int mtk_iommu_create_mapping(struct device *dev, if (IS_ERR(mtk_mapping)) return PTR_ERR(mtk_mapping); - m4udev->archdata.iommu = mtk_mapping; + data->mapping = mtk_mapping; } return 0; @@ -459,7 +457,7 @@ static void mtk_iommu_probe_finalize(struct device *dev) int err; data = dev_iommu_priv_get(dev); - mtk_mapping = data->dev->archdata.iommu; + mtk_mapping = data->mapping; err = arm_iommu_attach_device(dev, mtk_mapping); if (err) -- GitLab From ad962d864c61a73757085847027a532cbe2c1353 Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Thu, 25 Jun 2020 15:08:32 +0200 Subject: [PATCH 0115/2249] x86: Remove dev->archdata.iommu pointer There are no users left, all drivers have been converted to use the per-device private pointer offered by IOMMU core. Signed-off-by: Joerg Roedel Reviewed-by: Jerry Snitselaar Acked-by: Borislav Petkov Link: https://lore.kernel.org/r/20200625130836.1916-10-joro@8bytes.org --- arch/x86/include/asm/device.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/arch/x86/include/asm/device.h b/arch/x86/include/asm/device.h index 49bd6cf3eec91..7c0a52ca2f4dd 100644 --- a/arch/x86/include/asm/device.h +++ b/arch/x86/include/asm/device.h @@ -3,9 +3,6 @@ #define _ASM_X86_DEVICE_H struct dev_archdata { -#ifdef CONFIG_IOMMU_API - void *iommu; /* hook for IOMMU specific extension */ -#endif }; struct pdev_archdata { -- GitLab From 0b660afe310855c6eef35f8082594f32e3b05511 Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Thu, 25 Jun 2020 15:08:33 +0200 Subject: [PATCH 0116/2249] ia64: Remove dev->archdata.iommu pointer There are no users left, all drivers have been converted to use the per-device private pointer offered by IOMMU core. Signed-off-by: Joerg Roedel Reviewed-by: Jerry Snitselaar Link: https://lore.kernel.org/r/20200625130836.1916-11-joro@8bytes.org --- arch/ia64/include/asm/device.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/arch/ia64/include/asm/device.h b/arch/ia64/include/asm/device.h index 3eb3974153810..918b198cd5bbe 100644 --- a/arch/ia64/include/asm/device.h +++ b/arch/ia64/include/asm/device.h @@ -6,9 +6,6 @@ #define _ASM_IA64_DEVICE_H struct dev_archdata { -#ifdef CONFIG_IOMMU_API - void *iommu; /* hook for IOMMU specific extension */ -#endif }; struct pdev_archdata { -- GitLab From fb0fd5f70c1bfc9cdf5406e82d5de0ecdbe1e80c Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Thu, 25 Jun 2020 15:08:34 +0200 Subject: [PATCH 0117/2249] arm: Remove dev->archdata.iommu pointer There are no users left, all drivers have been converted to use the per-device private pointer offered by IOMMU core. Signed-off-by: Joerg Roedel Reviewed-by: Jerry Snitselaar Link: https://lore.kernel.org/r/20200625130836.1916-12-joro@8bytes.org --- arch/arm/include/asm/device.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/arch/arm/include/asm/device.h b/arch/arm/include/asm/device.h index c675bc0d5aa88..be666f58bf7ae 100644 --- a/arch/arm/include/asm/device.h +++ b/arch/arm/include/asm/device.h @@ -9,9 +9,6 @@ struct dev_archdata { #ifdef CONFIG_DMABOUNCE struct dmabounce_device_info *dmabounce; #endif -#ifdef CONFIG_IOMMU_API - void *iommu; /* private IOMMU data */ -#endif #ifdef CONFIG_ARM_DMA_USE_IOMMU struct dma_iommu_mapping *mapping; #endif -- GitLab From 5866a75b50b381fa05028e7ff3f2272ed006e321 Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Thu, 25 Jun 2020 15:08:35 +0200 Subject: [PATCH 0118/2249] arm64: Remove dev->archdata.iommu pointer There are no users left, all drivers have been converted to use the per-device private pointer offered by IOMMU core. Signed-off-by: Joerg Roedel Reviewed-by: Jerry Snitselaar Acked-by: Will Deacon Link: https://lore.kernel.org/r/20200625130836.1916-13-joro@8bytes.org --- arch/arm64/include/asm/device.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/arch/arm64/include/asm/device.h b/arch/arm64/include/asm/device.h index 12b778d55342e..9964987513183 100644 --- a/arch/arm64/include/asm/device.h +++ b/arch/arm64/include/asm/device.h @@ -6,9 +6,6 @@ #define __ASM_DEVICE_H struct dev_archdata { -#ifdef CONFIG_IOMMU_API - void *iommu; /* private IOMMU data */ -#endif }; struct pdev_archdata { -- GitLab From 6255c8c8d256b38b550b35c6362750f64ce46b8d Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Thu, 25 Jun 2020 15:08:36 +0200 Subject: [PATCH 0119/2249] powerpc/dma: Remove dev->archdata.iommu_domain There are no users left, so remove the pointer and save some memory. Signed-off-by: Joerg Roedel Reviewed-by: Jerry Snitselaar Link: https://lore.kernel.org/r/20200625130836.1916-14-joro@8bytes.org --- arch/powerpc/include/asm/device.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/arch/powerpc/include/asm/device.h b/arch/powerpc/include/asm/device.h index 266542769e4bd..1bc5952133382 100644 --- a/arch/powerpc/include/asm/device.h +++ b/arch/powerpc/include/asm/device.h @@ -34,9 +34,6 @@ struct dev_archdata { struct iommu_table *iommu_table_base; #endif -#ifdef CONFIG_IOMMU_API - void *iommu_domain; -#endif #ifdef CONFIG_PPC64 struct pci_dn *pci_data; #endif -- GitLab From ca37faf3d7005b5588f045edfac1d82799c408a7 Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Tue, 30 Jun 2020 10:17:56 +0200 Subject: [PATCH 0120/2249] iommu: Move sg_table wrapper out of CONFIG_IOMMU_SUPPORT Move the recently added sg_table wrapper out of CONFIG_IOMMU_SUPPORT to let the client code copile also when IOMMU support is disabled. Fixes: 48530d9fab0d ("iommu: add generic helper for mapping sgtable objects") Signed-off-by: Marek Szyprowski Link: https://lore.kernel.org/r/20200630081756.18526-1-m.szyprowski@samsung.com Signed-off-by: Joerg Roedel --- include/linux/iommu.h | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/include/linux/iommu.h b/include/linux/iommu.h index 5f0b7859d2eb5..5657d4fef9f2b 100644 --- a/include/linux/iommu.h +++ b/include/linux/iommu.h @@ -457,22 +457,6 @@ extern phys_addr_t iommu_iova_to_phys(struct iommu_domain *domain, dma_addr_t io extern void iommu_set_fault_handler(struct iommu_domain *domain, iommu_fault_handler_t handler, void *token); -/** - * iommu_map_sgtable - Map the given buffer to the IOMMU domain - * @domain: The IOMMU domain to perform the mapping - * @iova: The start address to map the buffer - * @sgt: The sg_table object describing the buffer - * @prot: IOMMU protection bits - * - * Creates a mapping at @iova for the buffer described by a scatterlist - * stored in the given sg_table object in the provided IOMMU domain. - */ -static inline size_t iommu_map_sgtable(struct iommu_domain *domain, - unsigned long iova, struct sg_table *sgt, int prot) -{ - return iommu_map_sg(domain, iova, sgt->sgl, sgt->orig_nents, prot); -} - extern void iommu_get_resv_regions(struct device *dev, struct list_head *list); extern void iommu_put_resv_regions(struct device *dev, struct list_head *list); extern void generic_iommu_put_resv_regions(struct device *dev, @@ -1079,6 +1063,22 @@ static inline struct iommu_fwspec *dev_iommu_fwspec_get(struct device *dev) } #endif /* CONFIG_IOMMU_API */ +/** + * iommu_map_sgtable - Map the given buffer to the IOMMU domain + * @domain: The IOMMU domain to perform the mapping + * @iova: The start address to map the buffer + * @sgt: The sg_table object describing the buffer + * @prot: IOMMU protection bits + * + * Creates a mapping at @iova for the buffer described by a scatterlist + * stored in the given sg_table object in the provided IOMMU domain. + */ +static inline size_t iommu_map_sgtable(struct iommu_domain *domain, + unsigned long iova, struct sg_table *sgt, int prot) +{ + return iommu_map_sg(domain, iova, sgt->sgl, sgt->orig_nents, prot); +} + #ifdef CONFIG_IOMMU_DEBUGFS extern struct dentry *iommu_debugfs_dir; void iommu_debugfs_setup(void); -- GitLab From 557d4bec009330567ce99692918abbe9c77528e0 Mon Sep 17 00:00:00 2001 From: Jerry Snitselaar Date: Fri, 5 Jun 2020 00:00:25 -0700 Subject: [PATCH 0121/2249] iommu: Add include/uapi/linux/iommu.h to MAINTAINERS file When include/uapi/linux/iommu.h was created it was never added to the file list in MAINTAINERS. Signed-off-by: Jerry Snitselaar Cc: Joerg Roedel Link: https://lore.kernel.org/r/20200605070025.216124-1-jsnitsel@redhat.com Signed-off-by: Joerg Roedel --- MAINTAINERS | 1 + 1 file changed, 1 insertion(+) diff --git a/MAINTAINERS b/MAINTAINERS index 496fd4eafb68c..c23352059a6bc 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -9014,6 +9014,7 @@ F: drivers/iommu/ F: include/linux/iommu.h F: include/linux/iova.h F: include/linux/of_iommu.h +F: include/uapi/linux/iommu.h IO_URING M: Jens Axboe -- GitLab From bdc4094591c3809e53eb7792344248bb447768c3 Mon Sep 17 00:00:00 2001 From: Enric Balletbo i Serra Date: Mon, 29 Jun 2020 12:32:23 +0200 Subject: [PATCH 0122/2249] platform/chrome: cros_ec_typec: Add a dependency on USB_ROLE_SWITCH As reported by the kernel test robot the cros_ec_typec driver fails to build if the USB_ROLE_SWITCH is not selected, to fix that, add a dependency on that symbol. This fixes the following build error: drivers/platform/chrome/cros_ec_typec.c:133: undefined reference to `usb_role_switch_put' ld: drivers/platform/chrome/cros_ec_typec.o: in function `cros_typec_get_switch_handles': drivers/platform/chrome/cros_ec_typec.c:108: undefined reference to `fwnode_usb_role_switch_get' ld: drivers/platform/chrome/cros_ec_typec.c:117: undefined reference to `usb_role_switch_put' Fixes: 7e7def15fa4b ("platform/chrome: cros_ec_typec: Add USB mux control") Reported-by: kernel test robot Acked-by: Prashant Malani Signed-off-by: Enric Balletbo i Serra --- drivers/platform/chrome/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/platform/chrome/Kconfig b/drivers/platform/chrome/Kconfig index cf072153bdc5d..a056031dee811 100644 --- a/drivers/platform/chrome/Kconfig +++ b/drivers/platform/chrome/Kconfig @@ -218,6 +218,7 @@ config CROS_EC_TYPEC tristate "ChromeOS EC Type-C Connector Control" depends on MFD_CROS_EC_DEV && TYPEC depends on CROS_USBPD_NOTIFY + depends on USB_ROLE_SWITCH default MFD_CROS_EC_DEV help If you say Y here, you get support for accessing Type C connector -- GitLab From f1d8fe2e98d11788cabb2ad5c5becfcc95dd81a9 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Tue, 30 Jun 2020 08:44:43 -0300 Subject: [PATCH 0123/2249] dt-bindings: mfd: st,stmfx: Remove extra additionalProperties The following build error is seen with 'make dt_binding_check': CHKDT Documentation/devicetree/bindings/mfd/st,stmfx.yaml /home/fabio/linux-next/Documentation/devicetree/bindings/mfd/st,stmfx.yaml: properties:pinctrl:patternProperties: {'enum': ['$ref', 'additionalItems', 'additionalProperties', 'allOf', 'anyOf', 'const', 'contains', 'default', 'dependencies', 'deprecated', 'description', 'else', 'enum', 'if', 'items', 'maxItems', 'maximum', 'minItems', 'minimum', 'multipleOf', 'not', 'oneOf', 'pattern', 'patternProperties', 'properties', 'propertyNames', 'required', 'then', 'unevaluatedProperties']} is not allowed for 'additionalProperties' Remove the extra 'additionalProperties' to pass the build. Signed-off-by: Fabio Estevam Reviewed-by: Rob Herring Signed-off-by: Lee Jones --- Documentation/devicetree/bindings/mfd/st,stmfx.yaml | 2 -- 1 file changed, 2 deletions(-) diff --git a/Documentation/devicetree/bindings/mfd/st,stmfx.yaml b/Documentation/devicetree/bindings/mfd/st,stmfx.yaml index 0ce56a0da5536..bed22d4abffba 100644 --- a/Documentation/devicetree/bindings/mfd/st,stmfx.yaml +++ b/Documentation/devicetree/bindings/mfd/st,stmfx.yaml @@ -73,8 +73,6 @@ properties: output-high: true output-low: true - additionalProperties: false - additionalProperties: false required: -- GitLab From 83cbc69df8b8ec598ff8ca7629be34a50274e5b5 Mon Sep 17 00:00:00 2001 From: Prashant Malani Date: Mon, 29 Jun 2020 14:13:27 -0700 Subject: [PATCH 0124/2249] platform/chrome: cros_ec_typec: Use workqueue for port update Use a work queue to call the port update routines, instead of doing it directly in the PD notifier callback. This will prevent other drivers with PD notifier callbacks from being blocked on the port update routine completing. Signed-off-by: Prashant Malani Reviewed-by: Guenter Roeck Reviewed-by: Heikki Krogerus Signed-off-by: Enric Balletbo i Serra --- drivers/platform/chrome/cros_ec_typec.c | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/drivers/platform/chrome/cros_ec_typec.c b/drivers/platform/chrome/cros_ec_typec.c index 0c041b79cbbac..9901bf2a96c2f 100644 --- a/drivers/platform/chrome/cros_ec_typec.c +++ b/drivers/platform/chrome/cros_ec_typec.c @@ -58,6 +58,7 @@ struct cros_typec_data { /* Array of ports, indexed by port number. */ struct cros_typec_port *ports[EC_USB_PD_MAX_PORTS]; struct notifier_block nb; + struct work_struct port_work; }; static int cros_typec_parse_port_props(struct typec_capability *cap, @@ -619,11 +620,9 @@ static int cros_typec_get_cmd_version(struct cros_typec_data *typec) return 0; } -static int cros_ec_typec_event(struct notifier_block *nb, - unsigned long host_event, void *_notify) +static void cros_typec_port_work(struct work_struct *work) { - struct cros_typec_data *typec = container_of(nb, struct cros_typec_data, - nb); + struct cros_typec_data *typec = container_of(work, struct cros_typec_data, port_work); int ret, i; for (i = 0; i < typec->num_ports; i++) { @@ -631,6 +630,14 @@ static int cros_ec_typec_event(struct notifier_block *nb, if (ret < 0) dev_warn(typec->dev, "Update failed for port: %d\n", i); } +} + +static int cros_ec_typec_event(struct notifier_block *nb, + unsigned long host_event, void *_notify) +{ + struct cros_typec_data *typec = container_of(nb, struct cros_typec_data, nb); + + schedule_work(&typec->port_work); return NOTIFY_OK; } @@ -689,6 +696,12 @@ static int cros_typec_probe(struct platform_device *pdev) if (ret < 0) return ret; + INIT_WORK(&typec->port_work, cros_typec_port_work); + + /* + * Safe to call port update here, since we haven't registered the + * PD notifier yet. + */ for (i = 0; i < typec->num_ports; i++) { ret = cros_typec_port_update(typec, i); if (ret < 0) -- GitLab From 20b736872f7f324438649a277ec711a646ce8e8d Mon Sep 17 00:00:00 2001 From: Prashant Malani Date: Mon, 29 Jun 2020 14:13:29 -0700 Subject: [PATCH 0125/2249] platform/chrome: cros_ec_typec: Add PM support Define basic suspend resume functions for cros-ec-typec. On suspend, we simply ensure that any pending port update work is completed, and on resume, we re-poll the port state to account for any changes/disconnections that might have occurred during suspend. Signed-off-by: Prashant Malani Reviewed-by: Guenter Roeck Reviewed-by: Heikki Krogerus Signed-off-by: Enric Balletbo i Serra --- drivers/platform/chrome/cros_ec_typec.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/drivers/platform/chrome/cros_ec_typec.c b/drivers/platform/chrome/cros_ec_typec.c index 9901bf2a96c2f..3eae01f4c9f70 100644 --- a/drivers/platform/chrome/cros_ec_typec.c +++ b/drivers/platform/chrome/cros_ec_typec.c @@ -720,11 +720,35 @@ static int cros_typec_probe(struct platform_device *pdev) return ret; } +static int __maybe_unused cros_typec_suspend(struct device *dev) +{ + struct cros_typec_data *typec = dev_get_drvdata(dev); + + cancel_work_sync(&typec->port_work); + + return 0; +} + +static int __maybe_unused cros_typec_resume(struct device *dev) +{ + struct cros_typec_data *typec = dev_get_drvdata(dev); + + /* Refresh port state. */ + schedule_work(&typec->port_work); + + return 0; +} + +static const struct dev_pm_ops cros_typec_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(cros_typec_suspend, cros_typec_resume) +}; + static struct platform_driver cros_typec_driver = { .driver = { .name = DRV_NAME, .acpi_match_table = ACPI_PTR(cros_typec_acpi_id), .of_match_table = of_match_ptr(cros_typec_of_match), + .pm = &cros_typec_pm_ops, }, .probe = cros_typec_probe, }; -- GitLab From e48bc01ed5adec203676c735365373b31c3c7600 Mon Sep 17 00:00:00 2001 From: Gwendal Grignou Date: Tue, 30 Jun 2020 00:52:03 -0700 Subject: [PATCH 0126/2249] platform/chrome: cros_ec_sensorhub: Fix EC timestamp overflow EC is using 32 bit timestamps (us), and before converting it to 64bit they were not casted, so it would overflow every 4s. Regular overflow every ~70 minutes was not taken into account either. Signed-off-by: Gwendal Grignou Signed-off-by: Enric Balletbo i Serra --- drivers/platform/chrome/cros_ec_sensorhub_ring.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/platform/chrome/cros_ec_sensorhub_ring.c b/drivers/platform/chrome/cros_ec_sensorhub_ring.c index 24e48d96ed766..b1c641c72f515 100644 --- a/drivers/platform/chrome/cros_ec_sensorhub_ring.c +++ b/drivers/platform/chrome/cros_ec_sensorhub_ring.c @@ -419,9 +419,7 @@ cros_ec_sensor_ring_process_event(struct cros_ec_sensorhub *sensorhub, * Disable filtering since we might add more jitter * if b is in a random point in time. */ - new_timestamp = fifo_timestamp - - fifo_info->timestamp * 1000 + - in->timestamp * 1000; + new_timestamp = c - b * 1000 + a * 1000; /* * The timestamp can be stale if we had to use the fifo * info timestamp. -- GitLab From e1915eec54a6b4902664eaf6fb7a20de5624c4dd Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Fri, 26 Jun 2020 22:37:41 +0200 Subject: [PATCH 0127/2249] backlight: sky81452: Convert to GPIO descriptors The SKY81452 backlight driver just obtains a GPIO (named "gpios" in the device tree) drives it high and leaves it high until the driver is removed. Switch to use GPIO descriptors for this, simple and straight-forward. Cc: Gyungoh Yoo Signed-off-by: Linus Walleij Reviewed-by: Daniel Thompson Signed-off-by: Lee Jones --- drivers/video/backlight/sky81452-backlight.c | 18 ++++-------------- .../linux/platform_data/sky81452-backlight.h | 6 ++++-- 2 files changed, 8 insertions(+), 16 deletions(-) diff --git a/drivers/video/backlight/sky81452-backlight.c b/drivers/video/backlight/sky81452-backlight.c index 2355f00f57732..81d2c8f3ca50a 100644 --- a/drivers/video/backlight/sky81452-backlight.c +++ b/drivers/video/backlight/sky81452-backlight.c @@ -8,12 +8,11 @@ #include #include -#include +#include #include #include #include #include -#include #include #include #include @@ -182,7 +181,7 @@ static struct sky81452_bl_platform_data *sky81452_bl_parse_dt( pdata->ignore_pwm = of_property_read_bool(np, "skyworks,ignore-pwm"); pdata->dpwm_mode = of_property_read_bool(np, "skyworks,dpwm-mode"); pdata->phase_shift = of_property_read_bool(np, "skyworks,phase-shift"); - pdata->gpio_enable = of_get_gpio(np, 0); + pdata->gpiod_enable = devm_gpiod_get_optional(dev, NULL, GPIOD_OUT_HIGH); ret = of_property_count_u32_elems(np, "led-sources"); if (ret < 0) { @@ -264,15 +263,6 @@ static int sky81452_bl_probe(struct platform_device *pdev) return PTR_ERR(pdata); } - if (gpio_is_valid(pdata->gpio_enable)) { - ret = devm_gpio_request_one(dev, pdata->gpio_enable, - GPIOF_OUT_INIT_HIGH, "sky81452-en"); - if (ret < 0) { - dev_err(dev, "failed to request GPIO. err=%d\n", ret); - return ret; - } - } - ret = sky81452_bl_init_device(regmap, pdata); if (ret < 0) { dev_err(dev, "failed to initialize. err=%d\n", ret); @@ -312,8 +302,8 @@ static int sky81452_bl_remove(struct platform_device *pdev) bd->props.brightness = 0; backlight_update_status(bd); - if (gpio_is_valid(pdata->gpio_enable)) - gpio_set_value_cansleep(pdata->gpio_enable, 0); + if (pdata->gpiod_enable) + gpiod_set_value_cansleep(pdata->gpiod_enable, 0); return 0; } diff --git a/include/linux/platform_data/sky81452-backlight.h b/include/linux/platform_data/sky81452-backlight.h index 02653d92d84fc..d6f46670d9230 100644 --- a/include/linux/platform_data/sky81452-backlight.h +++ b/include/linux/platform_data/sky81452-backlight.h @@ -9,11 +9,13 @@ #ifndef _SKY81452_BACKLIGHT_H #define _SKY81452_BACKLIGHT_H +#include + /** * struct sky81452_platform_data * @name: backlight driver name. If it is not defined, default name is lcd-backlight. - * @gpio_enable:GPIO number which control EN pin + * @gpios_enable:GPIO descriptor which control EN pin * @enable: Enable mask for current sink channel 1, 2, 3, 4, 5 and 6. * @ignore_pwm: true if DPWMI should be ignored. * @dpwm_mode: true is DPWM dimming mode, otherwise Analog dimming mode. @@ -23,7 +25,7 @@ */ struct sky81452_bl_platform_data { const char *name; - int gpio_enable; + struct gpio_desc *gpiod_enable; unsigned int enable; bool ignore_pwm; bool dpwm_mode; -- GitLab From 08bf73a6f056d84fd52a58c5d165523dd84be535 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Fri, 26 Jun 2020 22:37:42 +0200 Subject: [PATCH 0128/2249] backlight: sky81452: Privatize platform data The only way the platform data for the SKY81452 ever gets populated is through the device tree. The MFD device is bothered with this for no reason at all. Just allocate the platform data in the driver and be happy. Cc: Gyungoh Yoo Signed-off-by: Linus Walleij Reviewed-by: Daniel Thompson Signed-off-by: Lee Jones --- drivers/mfd/sky81452.c | 2 - drivers/video/backlight/sky81452-backlight.c | 34 +++++++++++++---- include/linux/mfd/sky81452.h | 2 - .../linux/platform_data/sky81452-backlight.h | 37 ------------------- 4 files changed, 27 insertions(+), 48 deletions(-) delete mode 100644 include/linux/platform_data/sky81452-backlight.h diff --git a/drivers/mfd/sky81452.c b/drivers/mfd/sky81452.c index 76eedfae85536..3ad35bf0c0155 100644 --- a/drivers/mfd/sky81452.c +++ b/drivers/mfd/sky81452.c @@ -47,8 +47,6 @@ static int sky81452_probe(struct i2c_client *client, memset(cells, 0, sizeof(cells)); cells[0].name = "sky81452-backlight"; cells[0].of_compatible = "skyworks,sky81452-backlight"; - cells[0].platform_data = pdata->bl_pdata; - cells[0].pdata_size = sizeof(*pdata->bl_pdata); cells[1].name = "sky81452-regulator"; cells[1].platform_data = pdata->regulator_init_data; cells[1].pdata_size = sizeof(*pdata->regulator_init_data); diff --git a/drivers/video/backlight/sky81452-backlight.c b/drivers/video/backlight/sky81452-backlight.c index 81d2c8f3ca50a..83ccb3d940fae 100644 --- a/drivers/video/backlight/sky81452-backlight.c +++ b/drivers/video/backlight/sky81452-backlight.c @@ -15,7 +15,6 @@ #include #include #include -#include #include /* registers */ @@ -41,6 +40,29 @@ #define SKY81452_DEFAULT_NAME "lcd-backlight" #define SKY81452_MAX_BRIGHTNESS (SKY81452_CS + 1) +/** + * struct sky81452_platform_data + * @name: backlight driver name. + If it is not defined, default name is lcd-backlight. + * @gpios_enable:GPIO descriptor which control EN pin + * @enable: Enable mask for current sink channel 1, 2, 3, 4, 5 and 6. + * @ignore_pwm: true if DPWMI should be ignored. + * @dpwm_mode: true is DPWM dimming mode, otherwise Analog dimming mode. + * @phase_shift:true is phase shift mode. + * @short_detecion_threshold: It should be one of 4, 5, 6 and 7V. + * @boost_current_limit: It should be one of 2300, 2750mA. + */ +struct sky81452_bl_platform_data { + const char *name; + struct gpio_desc *gpiod_enable; + unsigned int enable; + bool ignore_pwm; + bool dpwm_mode; + bool phase_shift; + unsigned int short_detection_threshold; + unsigned int boost_current_limit; +}; + #define CTZ(b) __builtin_ctz(b) static int sky81452_bl_update_status(struct backlight_device *bd) @@ -251,17 +273,15 @@ static int sky81452_bl_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct regmap *regmap = dev_get_drvdata(dev->parent); - struct sky81452_bl_platform_data *pdata = dev_get_platdata(dev); + struct sky81452_bl_platform_data *pdata; struct backlight_device *bd; struct backlight_properties props; const char *name; int ret; - if (!pdata) { - pdata = sky81452_bl_parse_dt(dev); - if (IS_ERR(pdata)) - return PTR_ERR(pdata); - } + pdata = sky81452_bl_parse_dt(dev); + if (IS_ERR(pdata)) + return PTR_ERR(pdata); ret = sky81452_bl_init_device(regmap, pdata); if (ret < 0) { diff --git a/include/linux/mfd/sky81452.h b/include/linux/mfd/sky81452.h index d469aa4812434..b08570ff34df9 100644 --- a/include/linux/mfd/sky81452.h +++ b/include/linux/mfd/sky81452.h @@ -9,11 +9,9 @@ #ifndef _SKY81452_H #define _SKY81452_H -#include #include struct sky81452_platform_data { - struct sky81452_bl_platform_data *bl_pdata; struct regulator_init_data *regulator_init_data; }; diff --git a/include/linux/platform_data/sky81452-backlight.h b/include/linux/platform_data/sky81452-backlight.h deleted file mode 100644 index d6f46670d9230..0000000000000 --- a/include/linux/platform_data/sky81452-backlight.h +++ /dev/null @@ -1,37 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * sky81452.h SKY81452 backlight driver - * - * Copyright 2014 Skyworks Solutions Inc. - * Author : Gyungoh Yoo - */ - -#ifndef _SKY81452_BACKLIGHT_H -#define _SKY81452_BACKLIGHT_H - -#include - -/** - * struct sky81452_platform_data - * @name: backlight driver name. - If it is not defined, default name is lcd-backlight. - * @gpios_enable:GPIO descriptor which control EN pin - * @enable: Enable mask for current sink channel 1, 2, 3, 4, 5 and 6. - * @ignore_pwm: true if DPWMI should be ignored. - * @dpwm_mode: true is DPWM dimming mode, otherwise Analog dimming mode. - * @phase_shift:true is phase shift mode. - * @short_detecion_threshold: It should be one of 4, 5, 6 and 7V. - * @boost_current_limit: It should be one of 2300, 2750mA. - */ -struct sky81452_bl_platform_data { - const char *name; - struct gpio_desc *gpiod_enable; - unsigned int enable; - bool ignore_pwm; - bool dpwm_mode; - bool phase_shift; - unsigned int short_detection_threshold; - unsigned int boost_current_limit; -}; - -#endif -- GitLab From e994734fdca7309234a210169c7a7f2f446e430f Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Fri, 26 Jun 2020 12:25:00 +0200 Subject: [PATCH 0129/2249] backlight: Delete the OT200 backlight driver This driver has no in-kernel users. The device can only be populated by board files since it does not support device tree nor ACPI, and nothing in the kernel creates a device named "ot200-backlight". This driver has been in the kernel since 2012. If it is used by out-of-tree code that code should have been upstreamed by now, it's been 8 years. It uses the idiomatic forked GPIO of the CS5535 which combines pin control and GPIO into its private custom interface, which causes me a headache because that is not how we do things these days: we creates separate pin control and GPIO drivers. Delete this unused driver. Cc: Christian Gmeiner Signed-off-by: Linus Walleij Reviewed-by: Daniel Thompson Signed-off-by: Lee Jones --- drivers/video/backlight/Kconfig | 7 -- drivers/video/backlight/Makefile | 1 - drivers/video/backlight/ot200_bl.c | 162 ----------------------------- 3 files changed, 170 deletions(-) delete mode 100644 drivers/video/backlight/ot200_bl.c diff --git a/drivers/video/backlight/Kconfig b/drivers/video/backlight/Kconfig index 7d22d73776064..95c546cc87748 100644 --- a/drivers/video/backlight/Kconfig +++ b/drivers/video/backlight/Kconfig @@ -386,13 +386,6 @@ config BACKLIGHT_LP8788 help This supports TI LP8788 backlight driver. -config BACKLIGHT_OT200 - tristate "Backlight driver for ot200 visualisation device" - depends on CS5535_MFGPT && GPIO_CS5535 - help - To compile this driver as a module, choose M here: the module will be - called ot200_bl. - config BACKLIGHT_PANDORA tristate "Backlight driver for Pandora console" depends on TWL4030_CORE diff --git a/drivers/video/backlight/Makefile b/drivers/video/backlight/Makefile index 0c1a1524627ad..2072d21b60f70 100644 --- a/drivers/video/backlight/Makefile +++ b/drivers/video/backlight/Makefile @@ -45,7 +45,6 @@ obj-$(CONFIG_BACKLIGHT_LP8788) += lp8788_bl.o obj-$(CONFIG_BACKLIGHT_LV5207LP) += lv5207lp.o obj-$(CONFIG_BACKLIGHT_MAX8925) += max8925_bl.o obj-$(CONFIG_BACKLIGHT_OMAP1) += omap1_bl.o -obj-$(CONFIG_BACKLIGHT_OT200) += ot200_bl.o obj-$(CONFIG_BACKLIGHT_PANDORA) += pandora_bl.o obj-$(CONFIG_BACKLIGHT_PCF50633) += pcf50633-backlight.o obj-$(CONFIG_BACKLIGHT_PWM) += pwm_bl.o diff --git a/drivers/video/backlight/ot200_bl.c b/drivers/video/backlight/ot200_bl.c deleted file mode 100644 index 23ee7106c72a3..0000000000000 --- a/drivers/video/backlight/ot200_bl.c +++ /dev/null @@ -1,162 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Copyright (C) 2012 Bachmann electronic GmbH - * Christian Gmeiner - * - * Backlight driver for ot200 visualisation device from - * Bachmann electronic GmbH. - */ - -#include -#include -#include -#include -#include -#include - -static struct cs5535_mfgpt_timer *pwm_timer; - -/* this array defines the mapping of brightness in % to pwm frequency */ -static const u8 dim_table[101] = {0, 0, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, - 4, 5, 5, 5, 5, 6, 6, 6, 7, 7, 7, 8, 8, 9, 9, - 10, 10, 11, 11, 12, 12, 13, 14, 15, 15, 16, - 17, 18, 19, 20, 21, 22, 23, 24, 26, 27, 28, - 30, 31, 33, 35, 37, 39, 41, 43, 45, 47, 50, - 53, 55, 58, 61, 65, 68, 72, 75, 79, 84, 88, - 93, 97, 103, 108, 114, 120, 126, 133, 140, - 147, 155, 163}; - -struct ot200_backlight_data { - int current_brightness; -}; - -#define GPIO_DIMM 27 -#define SCALE 1 -#define CMP1MODE 0x2 /* compare on GE; output high on compare - * greater than or equal */ -#define PWM_SETUP (SCALE | CMP1MODE << 6 | MFGPT_SETUP_CNTEN) -#define MAX_COMP2 163 - -static int ot200_backlight_update_status(struct backlight_device *bl) -{ - struct ot200_backlight_data *data = bl_get_data(bl); - int brightness = bl->props.brightness; - - if (bl->props.state & BL_CORE_FBBLANK) - brightness = 0; - - /* enable or disable PWM timer */ - if (brightness == 0) - cs5535_mfgpt_write(pwm_timer, MFGPT_REG_SETUP, 0); - else if (data->current_brightness == 0) { - cs5535_mfgpt_write(pwm_timer, MFGPT_REG_COUNTER, 0); - cs5535_mfgpt_write(pwm_timer, MFGPT_REG_SETUP, - MFGPT_SETUP_CNTEN); - } - - /* apply new brightness value */ - cs5535_mfgpt_write(pwm_timer, MFGPT_REG_CMP1, - MAX_COMP2 - dim_table[brightness]); - data->current_brightness = brightness; - - return 0; -} - -static int ot200_backlight_get_brightness(struct backlight_device *bl) -{ - struct ot200_backlight_data *data = bl_get_data(bl); - return data->current_brightness; -} - -static const struct backlight_ops ot200_backlight_ops = { - .update_status = ot200_backlight_update_status, - .get_brightness = ot200_backlight_get_brightness, -}; - -static int ot200_backlight_probe(struct platform_device *pdev) -{ - struct backlight_device *bl; - struct ot200_backlight_data *data; - struct backlight_properties props; - int retval = 0; - - /* request gpio */ - if (devm_gpio_request(&pdev->dev, GPIO_DIMM, - "ot200 backlight dimmer") < 0) { - dev_err(&pdev->dev, "failed to request GPIO %d\n", GPIO_DIMM); - return -ENODEV; - } - - /* request timer */ - pwm_timer = cs5535_mfgpt_alloc_timer(7, MFGPT_DOMAIN_ANY); - if (!pwm_timer) { - dev_err(&pdev->dev, "MFGPT 7 not available\n"); - return -ENODEV; - } - - data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); - if (!data) { - retval = -ENOMEM; - goto error_devm_kzalloc; - } - - /* setup gpio */ - cs5535_gpio_set(GPIO_DIMM, GPIO_OUTPUT_ENABLE); - cs5535_gpio_set(GPIO_DIMM, GPIO_OUTPUT_AUX1); - - /* setup timer */ - cs5535_mfgpt_write(pwm_timer, MFGPT_REG_CMP1, 0); - cs5535_mfgpt_write(pwm_timer, MFGPT_REG_CMP2, MAX_COMP2); - cs5535_mfgpt_write(pwm_timer, MFGPT_REG_SETUP, PWM_SETUP); - - data->current_brightness = 100; - props.max_brightness = 100; - props.brightness = 100; - props.type = BACKLIGHT_RAW; - - bl = devm_backlight_device_register(&pdev->dev, dev_name(&pdev->dev), - &pdev->dev, data, &ot200_backlight_ops, - &props); - if (IS_ERR(bl)) { - dev_err(&pdev->dev, "failed to register backlight\n"); - retval = PTR_ERR(bl); - goto error_devm_kzalloc; - } - - platform_set_drvdata(pdev, bl); - - return 0; - -error_devm_kzalloc: - cs5535_mfgpt_free_timer(pwm_timer); - return retval; -} - -static int ot200_backlight_remove(struct platform_device *pdev) -{ - /* on module unload set brightness to 100% */ - cs5535_mfgpt_write(pwm_timer, MFGPT_REG_COUNTER, 0); - cs5535_mfgpt_write(pwm_timer, MFGPT_REG_SETUP, MFGPT_SETUP_CNTEN); - cs5535_mfgpt_write(pwm_timer, MFGPT_REG_CMP1, - MAX_COMP2 - dim_table[100]); - - cs5535_mfgpt_free_timer(pwm_timer); - - return 0; -} - -static struct platform_driver ot200_backlight_driver = { - .driver = { - .name = "ot200-backlight", - }, - .probe = ot200_backlight_probe, - .remove = ot200_backlight_remove, -}; - -module_platform_driver(ot200_backlight_driver); - -MODULE_DESCRIPTION("backlight driver for ot200 visualisation device"); -MODULE_AUTHOR("Christian Gmeiner "); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:ot200-backlight"); -- GitLab From f3528630e2e7b1556b0f150f1e205462c66efe8e Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Fri, 26 Jun 2020 01:25:12 +0200 Subject: [PATCH 0130/2249] backlight: lms501kf03: Drop unused include This driver includes but does not use any symbols from that file, drop the include. Signed-off-by: Linus Walleij Reviewed-by: Daniel Thompson Signed-off-by: Lee Jones --- drivers/video/backlight/lms501kf03.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/video/backlight/lms501kf03.c b/drivers/video/backlight/lms501kf03.c index 8ae32e3573c1a..52d3ee6c3f7f9 100644 --- a/drivers/video/backlight/lms501kf03.c +++ b/drivers/video/backlight/lms501kf03.c @@ -9,7 +9,6 @@ #include #include #include -#include #include #include #include -- GitLab From 9dce29e65b38591eac0ce6786bdb725aea1eadeb Mon Sep 17 00:00:00 2001 From: "Steven Rostedt (VMware)" Date: Wed, 1 Jul 2020 09:28:39 -0400 Subject: [PATCH 0131/2249] ktest.pl: Have config-bisect save each config used in the bisect When performing a automatic config bisect via ktest.pl, it is very useful to have a copy of each of the bisects used. This way, if a bisect were to go wrong, it is possible to retrace the steps and continue at the location before the error was made. The ktest.pl will make a copy of the good and bad configs, labeled as such, as well as a number attached to it that represents the iteration of the bisect. These files are saved in the ktest temp directory where it currently stores the good and bad config files. Signed-off-by: Steven Rostedt (VMware) --- tools/testing/ktest/ktest.pl | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/tools/testing/ktest/ktest.pl b/tools/testing/ktest/ktest.pl index 7570e36d636d8..5f6f88911f5cf 100755 --- a/tools/testing/ktest/ktest.pl +++ b/tools/testing/ktest/ktest.pl @@ -3188,6 +3188,8 @@ sub config_bisect_end { doprint "***************************************\n\n"; } +my $pass = 1; + sub run_config_bisect { my ($good, $bad, $last_result) = @_; my $reset = ""; @@ -3210,11 +3212,15 @@ sub run_config_bisect { $ret = run_config_bisect_test $config_bisect_type; if ($ret) { - doprint "NEW GOOD CONFIG\n"; + doprint "NEW GOOD CONFIG ($pass)\n"; + system("cp $output_config $tmpdir/good_config.tmp.$pass"); + $pass++; # Return 3 for good config return 3; } else { - doprint "NEW BAD CONFIG\n"; + doprint "NEW BAD CONFIG ($pass)\n"; + system("cp $output_config $tmpdir/bad_config.tmp.$pass"); + $pass++; # Return 4 for bad config return 4; } -- GitLab From 4d3ec936f80dbb2174c8c1f426eb86c032e9f14e Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 30 Jun 2020 10:39:48 +0200 Subject: [PATCH 0132/2249] mfd: lm3533: Expand control-bank accessors Expand the control-bank accessors that were implemented using macros. This allows the definitions of these exported functions to be found more easily and specifically avoids a W=1 compiler warning due to the redundant brightness sanity check: drivers/mfd/lm3533-ctrlbank.c: In function 'lm3533_ctrlbank_set_brightness': drivers/mfd/lm3533-ctrlbank.c:98:10: warning: comparison is always false due to limited range of data type [-Wtype-limits] 98 | if (val > LM3533_##_NAME##_MAX) \ | ^ drivers/mfd/lm3533-ctrlbank.c:125:1: note: in expansion of macro 'lm3533_ctrlbank_set' 125 | lm3533_ctrlbank_set(brightness, BRIGHTNESS); | ^~~~~~~~~~~~~~~~~~~ Signed-off-by: Johan Hovold Signed-off-by: Lee Jones --- drivers/mfd/lm3533-ctrlbank.c | 94 +++++++++++++++++++++-------------- 1 file changed, 56 insertions(+), 38 deletions(-) diff --git a/drivers/mfd/lm3533-ctrlbank.c b/drivers/mfd/lm3533-ctrlbank.c index 34fba06ec7057..2537dfade51cd 100644 --- a/drivers/mfd/lm3533-ctrlbank.c +++ b/drivers/mfd/lm3533-ctrlbank.c @@ -17,7 +17,6 @@ #define LM3533_MAX_CURRENT_MAX 29800 #define LM3533_MAX_CURRENT_STEP 800 -#define LM3533_BRIGHTNESS_MAX 255 #define LM3533_PWM_MAX 0x3f #define LM3533_REG_PWM_BASE 0x14 @@ -89,41 +88,33 @@ int lm3533_ctrlbank_set_max_current(struct lm3533_ctrlbank *cb, u16 imax) } EXPORT_SYMBOL_GPL(lm3533_ctrlbank_set_max_current); -#define lm3533_ctrlbank_set(_name, _NAME) \ -int lm3533_ctrlbank_set_##_name(struct lm3533_ctrlbank *cb, u8 val) \ -{ \ - u8 reg; \ - int ret; \ - \ - if (val > LM3533_##_NAME##_MAX) \ - return -EINVAL; \ - \ - reg = lm3533_ctrlbank_get_reg(cb, LM3533_REG_##_NAME##_BASE); \ - ret = lm3533_write(cb->lm3533, reg, val); \ - if (ret) \ - dev_err(cb->dev, "failed to set " #_name "\n"); \ - \ - return ret; \ -} \ -EXPORT_SYMBOL_GPL(lm3533_ctrlbank_set_##_name); - -#define lm3533_ctrlbank_get(_name, _NAME) \ -int lm3533_ctrlbank_get_##_name(struct lm3533_ctrlbank *cb, u8 *val) \ -{ \ - u8 reg; \ - int ret; \ - \ - reg = lm3533_ctrlbank_get_reg(cb, LM3533_REG_##_NAME##_BASE); \ - ret = lm3533_read(cb->lm3533, reg, val); \ - if (ret) \ - dev_err(cb->dev, "failed to get " #_name "\n"); \ - \ - return ret; \ -} \ -EXPORT_SYMBOL_GPL(lm3533_ctrlbank_get_##_name); - -lm3533_ctrlbank_set(brightness, BRIGHTNESS); -lm3533_ctrlbank_get(brightness, BRIGHTNESS); +int lm3533_ctrlbank_set_brightness(struct lm3533_ctrlbank *cb, u8 val) +{ + u8 reg; + int ret; + + reg = lm3533_ctrlbank_get_reg(cb, LM3533_REG_BRIGHTNESS_BASE); + ret = lm3533_write(cb->lm3533, reg, val); + if (ret) + dev_err(cb->dev, "failed to set brightness\n"); + + return ret; +} +EXPORT_SYMBOL_GPL(lm3533_ctrlbank_set_brightness); + +int lm3533_ctrlbank_get_brightness(struct lm3533_ctrlbank *cb, u8 *val) +{ + u8 reg; + int ret; + + reg = lm3533_ctrlbank_get_reg(cb, LM3533_REG_BRIGHTNESS_BASE); + ret = lm3533_read(cb->lm3533, reg, val); + if (ret) + dev_err(cb->dev, "failed to get brightness\n"); + + return ret; +} +EXPORT_SYMBOL_GPL(lm3533_ctrlbank_get_brightness); /* * PWM-input control mask: @@ -135,9 +126,36 @@ lm3533_ctrlbank_get(brightness, BRIGHTNESS); * bit 1 - PWM-input enabled in Zone 0 * bit 0 - PWM-input enabled */ -lm3533_ctrlbank_set(pwm, PWM); -lm3533_ctrlbank_get(pwm, PWM); +int lm3533_ctrlbank_set_pwm(struct lm3533_ctrlbank *cb, u8 val) +{ + u8 reg; + int ret; + + if (val > LM3533_PWM_MAX) + return -EINVAL; + + reg = lm3533_ctrlbank_get_reg(cb, LM3533_REG_PWM_BASE); + ret = lm3533_write(cb->lm3533, reg, val); + if (ret) + dev_err(cb->dev, "failed to set PWM mask\n"); + + return ret; +} +EXPORT_SYMBOL_GPL(lm3533_ctrlbank_set_pwm); + +int lm3533_ctrlbank_get_pwm(struct lm3533_ctrlbank *cb, u8 *val) +{ + u8 reg; + int ret; + reg = lm3533_ctrlbank_get_reg(cb, LM3533_REG_PWM_BASE); + ret = lm3533_read(cb->lm3533, reg, val); + if (ret) + dev_err(cb->dev, "failed to get PWM mask\n"); + + return ret; +} +EXPORT_SYMBOL_GPL(lm3533_ctrlbank_get_pwm); MODULE_AUTHOR("Johan Hovold "); MODULE_DESCRIPTION("LM3533 Control Bank interface"); -- GitLab From 2f059db0b8313f8964ac917394e7425d966a6884 Mon Sep 17 00:00:00 2001 From: "Steven Rostedt (VMware)" Date: Wed, 1 Jul 2020 10:28:23 -0400 Subject: [PATCH 0133/2249] ktest.pl: Always show log file location if defined even on success If a log file is defined and the test were to error, a print statement is made that shows the user where the log file is to examine it further. But this is not done if the test were to succeed. I find it annoying that it does not show where the log file is on success, as I run several different tests that place their log files in various locations, and even though the test pass, there's things I want to look at in the log file (like warnings). It is much easier to find where the log file is, if it is displayed at the end of a test. Signed-off-by: Steven Rostedt (VMware) --- tools/testing/ktest/ktest.pl | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tools/testing/ktest/ktest.pl b/tools/testing/ktest/ktest.pl index 5f6f88911f5cf..5d5cf3e1e81a9 100755 --- a/tools/testing/ktest/ktest.pl +++ b/tools/testing/ktest/ktest.pl @@ -4441,6 +4441,10 @@ if ($opt{"POWEROFF_ON_SUCCESS"}) { } +if (defined($opt{"LOG_FILE"})) { + print "\n See $opt{LOG_FILE} for the record of results.\n"; +} + doprint "\n $successes of $opt{NUM_TESTS} tests were successful\n\n"; if ($email_when_finished) { -- GitLab From d53cdda3fda6e737151e091c7d9388c31a73c828 Mon Sep 17 00:00:00 2001 From: "Steven Rostedt (VMware)" Date: Wed, 1 Jul 2020 10:32:28 -0400 Subject: [PATCH 0134/2249] ktest.pl: Define PRE_TEST_DIE to kill the test if the PRE_TEST fails Currently, if a PRE_TEST is defined and ran, but fails, there's nothing currently available to make the test fail too. Add a PRE_TEST_DIE option that when set, if a PRE_TEST is defined and fails, the test will die too. Signed-off-by: Steven Rostedt (VMware) --- tools/testing/ktest/ktest.pl | 8 +++++++- tools/testing/ktest/sample.conf | 5 +++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/tools/testing/ktest/ktest.pl b/tools/testing/ktest/ktest.pl index 5d5cf3e1e81a9..f99cf633ed84f 100755 --- a/tools/testing/ktest/ktest.pl +++ b/tools/testing/ktest/ktest.pl @@ -98,6 +98,7 @@ my $final_post_ktest; my $pre_ktest; my $post_ktest; my $pre_test; +my $pre_test_die; my $post_test; my $pre_build; my $post_build; @@ -273,6 +274,7 @@ my %option_map = ( "PRE_KTEST" => \$pre_ktest, "POST_KTEST" => \$post_ktest, "PRE_TEST" => \$pre_test, + "PRE_TEST_DIE" => \$pre_test_die, "POST_TEST" => \$post_test, "BUILD_TYPE" => \$build_type, "BUILD_OPTIONS" => \$build_options, @@ -4347,7 +4349,11 @@ for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) { doprint "RUNNING TEST $i of $opt{NUM_TESTS}$name with option $test_type $run_type$installme\n\n"; if (defined($pre_test)) { - run_command $pre_test; + my $ret = run_command $pre_test; + if (!$ret && defined($pre_test_die) && + $pre_test_die) { + dodie "failed to pre_test\n"; + } } unlink $dmesg; diff --git a/tools/testing/ktest/sample.conf b/tools/testing/ktest/sample.conf index 27666b8007edb..cb8227fbd01ed 100644 --- a/tools/testing/ktest/sample.conf +++ b/tools/testing/ktest/sample.conf @@ -557,6 +557,11 @@ # default (undefined) #PRE_TEST = ${SSH} reboot_to_special_kernel +# To kill the entire test if PRE_TEST is defined but fails set this +# to 1. +# (default 0) +#PRE_TEST_DIE = 1 + # If there is a command you want to run after the individual test case # completes, then you can set this option. # -- GitLab From 167234268cf6cb932ffb180586f3874ae3293a55 Mon Sep 17 00:00:00 2001 From: "Steven Rostedt (VMware)" Date: Wed, 1 Jul 2020 11:09:23 -0400 Subject: [PATCH 0135/2249] ktest.pl: Add a NOT operator There is a NOT DEFINED operator, but there is not an operator that can negate any other expression. For example: NOT (${FOO} == boot || ${BAR} == run) Add the keyword NOT to allow the ktest.pl config files to negate operators. Signed-off-by: Steven Rostedt (VMware) --- tools/testing/ktest/ktest.pl | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tools/testing/ktest/ktest.pl b/tools/testing/ktest/ktest.pl index f99cf633ed84f..0d04b8a2b5a2c 100755 --- a/tools/testing/ktest/ktest.pl +++ b/tools/testing/ktest/ktest.pl @@ -911,6 +911,12 @@ sub process_expression { } } + if ($val =~ s/^\s*NOT\s+(.*)//) { + my $express = $1; + my $ret = process_expression($name, $express); + return !$ret; + } + if ($val =~ /^\s*0\s*$/) { return 0; } elsif ($val =~ /^\s*\d+\s*$/) { -- GitLab From d6bc29d987336927ff97219d5f661389f33f8f11 Mon Sep 17 00:00:00 2001 From: "Steven Rostedt (VMware)" Date: Wed, 1 Jul 2020 15:21:15 -0400 Subject: [PATCH 0136/2249] ktest.pl: Just open up the log file once Currently, every write to the log file is done by opening the file, writing to it, then closing the file. This rather expensive. Just open it at the beginning and close it at the end. Signed-off-by: Steven Rostedt (VMware) --- tools/testing/ktest/ktest.pl | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/tools/testing/ktest/ktest.pl b/tools/testing/ktest/ktest.pl index 0d04b8a2b5a2c..f20a81bb3abe2 100755 --- a/tools/testing/ktest/ktest.pl +++ b/tools/testing/ktest/ktest.pl @@ -509,9 +509,7 @@ EOF sub _logit { if (defined($opt{"LOG_FILE"})) { - open(OUT, ">> $opt{LOG_FILE}") or die "Can't write to $opt{LOG_FILE}"; - print OUT @_; - close(OUT); + print LOG @_; } } @@ -1780,8 +1778,6 @@ sub run_command { (fail "unable to exec $command" and return 0); if (defined($opt{"LOG_FILE"})) { - open(LOG, ">>$opt{LOG_FILE}") or - dodie "failed to write to log"; $dolog = 1; } @@ -1829,7 +1825,6 @@ sub run_command { } close(CMD); - close(LOG) if ($dolog); close(RD) if ($dord); $end_time = time; @@ -4091,8 +4086,11 @@ if ($#new_configs >= 0) { } } -if ($opt{"CLEAR_LOG"} && defined($opt{"LOG_FILE"})) { - unlink $opt{"LOG_FILE"}; +if (defined($opt{"LOG_FILE"})) { + if ($opt{"CLEAR_LOG"}) { + unlink $opt{"LOG_FILE"}; + } + open(LOG, ">> $opt{LOG_FILE}") or die "Can't write to $opt{LOG_FILE}"; } doprint "\n\nSTARTING AUTOMATED TESTS\n\n"; @@ -4453,14 +4451,16 @@ if ($opt{"POWEROFF_ON_SUCCESS"}) { } -if (defined($opt{"LOG_FILE"})) { - print "\n See $opt{LOG_FILE} for the record of results.\n"; -} - doprint "\n $successes of $opt{NUM_TESTS} tests were successful\n\n"; if ($email_when_finished) { send_email("KTEST: Your test has finished!", "$successes of $opt{NUM_TESTS} tests started at $script_start_time were successful!"); } + +if (defined($opt{"LOG_FILE"})) { + print "\n See $opt{LOG_FILE} for the record of results.\n\n"; + close LOG; +} + exit 0; -- GitLab From eefb9d2b8c6a781dd1026b18e37b4bcb50cff440 Mon Sep 17 00:00:00 2001 From: "Steven Rostedt (VMware)" Date: Wed, 1 Jul 2020 15:29:06 -0400 Subject: [PATCH 0137/2249] ktest.pl: Turn off buffering to the log file The log file should be up to date to whatever is happening in ktest. Disable buffering to the LOG output file handle. Signed-off-by: Steven Rostedt (VMware) --- tools/testing/ktest/ktest.pl | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/testing/ktest/ktest.pl b/tools/testing/ktest/ktest.pl index f20a81bb3abe2..e90e2e7cb72cf 100755 --- a/tools/testing/ktest/ktest.pl +++ b/tools/testing/ktest/ktest.pl @@ -11,6 +11,7 @@ use File::Path qw(mkpath); use File::Copy qw(cp); use FileHandle; use FindBin; +use IO::Handle; my $VERSION = "0.2"; @@ -4091,6 +4092,7 @@ if (defined($opt{"LOG_FILE"})) { unlink $opt{"LOG_FILE"}; } open(LOG, ">> $opt{LOG_FILE}") or die "Can't write to $opt{LOG_FILE}"; + LOG->autoflush(1); } doprint "\n\nSTARTING AUTOMATED TESTS\n\n"; -- GitLab From 4605ad8f4581981787ed22b3a755209c8fe5aa24 Mon Sep 17 00:00:00 2001 From: Mathieu Poirier Date: Tue, 30 Jun 2020 10:31:17 -0600 Subject: [PATCH 0138/2249] remoteproc: ingenic: Move clock handling to prepare/unprepare callbacks This patch moves clock related operations to the remoteproc prepare() and unprepare() callbacks so that the PM runtime framework doesn't have to be involved needlessly. This provides a simpler approach and requires less code. Based on the work from Paul Cercueil published here: https://lore.kernel.org/linux-remoteproc/20191116170846.67220-4-paul@crapouillou.net/ Reviewed-by: Suman Anna Signed-off-by: Mathieu Poirier Link: https://lore.kernel.org/r/20200630163118.3830422-2-mathieu.poirier@linaro.org Signed-off-by: Bjorn Andersson --- drivers/remoteproc/ingenic_rproc.c | 84 +++++++++--------------------- 1 file changed, 26 insertions(+), 58 deletions(-) diff --git a/drivers/remoteproc/ingenic_rproc.c b/drivers/remoteproc/ingenic_rproc.c index 189020d77b25c..1c2b21a5d1782 100644 --- a/drivers/remoteproc/ingenic_rproc.c +++ b/drivers/remoteproc/ingenic_rproc.c @@ -11,7 +11,6 @@ #include #include #include -#include #include #include "remoteproc_internal.h" @@ -62,6 +61,28 @@ struct vpu { struct device *dev; }; +static int ingenic_rproc_prepare(struct rproc *rproc) +{ + struct vpu *vpu = rproc->priv; + int ret; + + /* The clocks must be enabled for the firmware to be loaded in TCSM */ + ret = clk_bulk_prepare_enable(ARRAY_SIZE(vpu->clks), vpu->clks); + if (ret) + dev_err(vpu->dev, "Unable to start clocks: %d\n", ret); + + return ret; +} + +static int ingenic_rproc_unprepare(struct rproc *rproc) +{ + struct vpu *vpu = rproc->priv; + + clk_bulk_disable_unprepare(ARRAY_SIZE(vpu->clks), vpu->clks); + + return 0; +} + static int ingenic_rproc_start(struct rproc *rproc) { struct vpu *vpu = rproc->priv; @@ -115,6 +136,8 @@ static void *ingenic_rproc_da_to_va(struct rproc *rproc, u64 da, size_t len) } static struct rproc_ops ingenic_rproc_ops = { + .prepare = ingenic_rproc_prepare, + .unprepare = ingenic_rproc_unprepare, .start = ingenic_rproc_start, .stop = ingenic_rproc_stop, .kick = ingenic_rproc_kick, @@ -135,16 +158,6 @@ static irqreturn_t vpu_interrupt(int irq, void *data) return rproc_vq_interrupt(rproc, vring); } -static void ingenic_rproc_disable_clks(void *data) -{ - struct vpu *vpu = data; - - pm_runtime_resume(vpu->dev); - pm_runtime_disable(vpu->dev); - - clk_bulk_disable_unprepare(ARRAY_SIZE(vpu->clks), vpu->clks); -} - static int ingenic_rproc_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -206,35 +219,13 @@ static int ingenic_rproc_probe(struct platform_device *pdev) disable_irq(vpu->irq); - /* The clocks must be enabled for the firmware to be loaded in TCSM */ - ret = clk_bulk_prepare_enable(ARRAY_SIZE(vpu->clks), vpu->clks); - if (ret) { - dev_err(dev, "Unable to start clocks\n"); - return ret; - } - - pm_runtime_irq_safe(dev); - pm_runtime_set_active(dev); - pm_runtime_enable(dev); - pm_runtime_get_sync(dev); - pm_runtime_use_autosuspend(dev); - - ret = devm_add_action_or_reset(dev, ingenic_rproc_disable_clks, vpu); - if (ret) { - dev_err(dev, "Unable to register action\n"); - goto out_pm_put; - } - ret = devm_rproc_add(dev, rproc); if (ret) { dev_err(dev, "Failed to register remote processor\n"); - goto out_pm_put; + return ret; } -out_pm_put: - pm_runtime_put_autosuspend(dev); - - return ret; + return 0; } static const struct of_device_id ingenic_rproc_of_matches[] = { @@ -243,33 +234,10 @@ static const struct of_device_id ingenic_rproc_of_matches[] = { }; MODULE_DEVICE_TABLE(of, ingenic_rproc_of_matches); -static int __maybe_unused ingenic_rproc_suspend(struct device *dev) -{ - struct vpu *vpu = dev_get_drvdata(dev); - - clk_bulk_disable(ARRAY_SIZE(vpu->clks), vpu->clks); - - return 0; -} - -static int __maybe_unused ingenic_rproc_resume(struct device *dev) -{ - struct vpu *vpu = dev_get_drvdata(dev); - - return clk_bulk_enable(ARRAY_SIZE(vpu->clks), vpu->clks); -} - -static const struct dev_pm_ops __maybe_unused ingenic_rproc_pm = { - SET_RUNTIME_PM_OPS(ingenic_rproc_suspend, ingenic_rproc_resume, NULL) -}; - static struct platform_driver ingenic_rproc_driver = { .probe = ingenic_rproc_probe, .driver = { .name = "ingenic-vpu", -#ifdef CONFIG_PM - .pm = &ingenic_rproc_pm, -#endif .of_match_table = ingenic_rproc_of_matches, }, }; -- GitLab From 49cff1256879d8622d253b6deac2438d6cd33445 Mon Sep 17 00:00:00 2001 From: Mathieu Poirier Date: Tue, 30 Jun 2020 10:31:18 -0600 Subject: [PATCH 0139/2249] Revert "remoteproc: Add support for runtime PM" This reverts commit a99a37f6cd5a74d5b22c08544aa6c5890813c8ba. Removing PM runtime operations from the remoteproc core in order to: 1) Keep all power management operations in platform drivers. That way we do not loose flexibility in an area that is very HW specific. 2) Avoid making the support for remote processor managed by external entities more complex that it already is. 3) Fix regression introduced for the Omap remoteproc driver. Acked-by: Suman Anna Tested-by: Suman Anna Signed-off-by: Mathieu Poirier Link: https://lore.kernel.org/r/20200630163118.3830422-3-mathieu.poirier@linaro.org Signed-off-by: Bjorn Andersson --- drivers/remoteproc/remoteproc_core.c | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c index 9f04c30c4aaf7..0f95e025ba030 100644 --- a/drivers/remoteproc/remoteproc_core.c +++ b/drivers/remoteproc/remoteproc_core.c @@ -29,7 +29,6 @@ #include #include #include -#include #include #include #include @@ -1383,12 +1382,6 @@ static int rproc_fw_boot(struct rproc *rproc, const struct firmware *fw) if (ret) return ret; - ret = pm_runtime_get_sync(dev); - if (ret < 0) { - dev_err(dev, "pm_runtime_get_sync failed: %d\n", ret); - return ret; - } - dev_info(dev, "Booting fw image %s, size %zd\n", name, fw->size); /* @@ -1398,7 +1391,7 @@ static int rproc_fw_boot(struct rproc *rproc, const struct firmware *fw) ret = rproc_enable_iommu(rproc); if (ret) { dev_err(dev, "can't enable iommu: %d\n", ret); - goto put_pm_runtime; + return ret; } /* Prepare rproc for firmware loading if needed */ @@ -1452,8 +1445,6 @@ static int rproc_fw_boot(struct rproc *rproc, const struct firmware *fw) rproc_unprepare_device(rproc); disable_iommu: rproc_disable_iommu(rproc); -put_pm_runtime: - pm_runtime_put(dev); return ret; } @@ -1891,8 +1882,6 @@ void rproc_shutdown(struct rproc *rproc) rproc_disable_iommu(rproc); - pm_runtime_put(dev); - /* Free the copy of the resource table */ kfree(rproc->cached_table); rproc->cached_table = NULL; @@ -2183,9 +2172,6 @@ struct rproc *rproc_alloc(struct device *dev, const char *name, rproc->state = RPROC_OFFLINE; - pm_runtime_no_callbacks(&rproc->dev); - pm_runtime_enable(&rproc->dev); - return rproc; put_device: @@ -2205,7 +2191,6 @@ EXPORT_SYMBOL(rproc_alloc); */ void rproc_free(struct rproc *rproc) { - pm_runtime_disable(&rproc->dev); put_device(&rproc->dev); } EXPORT_SYMBOL(rproc_free); -- GitLab From 87ad854dd76ca3534ef2e368265c3566a59e21e0 Mon Sep 17 00:00:00 2001 From: Bjorn Andersson Date: Mon, 22 Jun 2020 12:19:38 -0700 Subject: [PATCH 0140/2249] dt-bindings: remoteproc: Add Qualcomm PIL info binding Add a devicetree binding for the Qualcomm peripheral image loader relocation information region found in the IMEM. Reviewed-by: Mathieu Poirier Reviewed-by: Rob Herring Reviewed-by: Stephen Boyd Reviewed-by: Vinod Koul Signed-off-by: Bjorn Andersson Link: https://lore.kernel.org/r/20200622191942.255460-2-bjorn.andersson@linaro.org Signed-off-by: Bjorn Andersson --- .../bindings/remoteproc/qcom,pil-info.yaml | 44 +++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 Documentation/devicetree/bindings/remoteproc/qcom,pil-info.yaml diff --git a/Documentation/devicetree/bindings/remoteproc/qcom,pil-info.yaml b/Documentation/devicetree/bindings/remoteproc/qcom,pil-info.yaml new file mode 100644 index 0000000000000..87c52316ddbd6 --- /dev/null +++ b/Documentation/devicetree/bindings/remoteproc/qcom,pil-info.yaml @@ -0,0 +1,44 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/remoteproc/qcom,pil-info.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Qualcomm peripheral image loader relocation info binding + +maintainers: + - Bjorn Andersson + +description: + The Qualcomm peripheral image loader relocation memory region, in IMEM, is + used for communicating remoteproc relocation information to post mortem + debugging tools. + +properties: + compatible: + const: qcom,pil-reloc-info + + reg: + maxItems: 1 + +required: + - compatible + - reg + +examples: + - | + imem@146bf000 { + compatible = "syscon", "simple-mfd"; + reg = <0x146bf000 0x1000>; + + #address-cells = <1>; + #size-cells = <1>; + + ranges = <0 0x146bf000 0x1000>; + + pil-reloc@94c { + compatible = "qcom,pil-reloc-info"; + reg = <0x94c 0xc8>; + }; + }; +... -- GitLab From 549b67da660d634e3a4a50a325bd1f5609ddb84b Mon Sep 17 00:00:00 2001 From: Bjorn Andersson Date: Mon, 22 Jun 2020 12:19:39 -0700 Subject: [PATCH 0141/2249] remoteproc: qcom: Introduce helper to store pil info in IMEM A region in IMEM is used to communicate load addresses of remoteproc to post mortem debug tools. Implement a helper function that can be used to store this information in order to enable these tools to process collected ramdumps. Reviewed-by: Mathieu Poirier Reviewed-by: Vinod Koul Signed-off-by: Bjorn Andersson Link: https://lore.kernel.org/r/20200622191942.255460-3-bjorn.andersson@linaro.org Signed-off-by: Bjorn Andersson --- drivers/remoteproc/Kconfig | 3 + drivers/remoteproc/Makefile | 1 + drivers/remoteproc/qcom_pil_info.c | 129 +++++++++++++++++++++++++++++ drivers/remoteproc/qcom_pil_info.h | 9 ++ 4 files changed, 142 insertions(+) create mode 100644 drivers/remoteproc/qcom_pil_info.c create mode 100644 drivers/remoteproc/qcom_pil_info.h diff --git a/drivers/remoteproc/Kconfig b/drivers/remoteproc/Kconfig index c4d1731295ebc..f4bd96d1a1a34 100644 --- a/drivers/remoteproc/Kconfig +++ b/drivers/remoteproc/Kconfig @@ -116,6 +116,9 @@ config KEYSTONE_REMOTEPROC It's safe to say N here if you're not interested in the Keystone DSPs or just want to use a bare minimum kernel. +config QCOM_PIL_INFO + tristate + config QCOM_RPROC_COMMON tristate diff --git a/drivers/remoteproc/Makefile b/drivers/remoteproc/Makefile index e8b886e511f0b..fe398f82d5500 100644 --- a/drivers/remoteproc/Makefile +++ b/drivers/remoteproc/Makefile @@ -16,6 +16,7 @@ obj-$(CONFIG_OMAP_REMOTEPROC) += omap_remoteproc.o obj-$(CONFIG_WKUP_M3_RPROC) += wkup_m3_rproc.o obj-$(CONFIG_DA8XX_REMOTEPROC) += da8xx_remoteproc.o obj-$(CONFIG_KEYSTONE_REMOTEPROC) += keystone_remoteproc.o +obj-$(CONFIG_QCOM_PIL_INFO) += qcom_pil_info.o obj-$(CONFIG_QCOM_RPROC_COMMON) += qcom_common.o obj-$(CONFIG_QCOM_Q6V5_COMMON) += qcom_q6v5.o obj-$(CONFIG_QCOM_Q6V5_ADSP) += qcom_q6v5_adsp.o diff --git a/drivers/remoteproc/qcom_pil_info.c b/drivers/remoteproc/qcom_pil_info.c new file mode 100644 index 0000000000000..0536e39046691 --- /dev/null +++ b/drivers/remoteproc/qcom_pil_info.c @@ -0,0 +1,129 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2019-2020 Linaro Ltd. + */ +#include +#include +#include +#include +#include "qcom_pil_info.h" + +/* + * The PIL relocation information region is used to communicate memory regions + * occupied by co-processor firmware for post mortem crash analysis. + * + * It consists of an array of entries with an 8 byte textual identifier of the + * region followed by a 64 bit base address and 32 bit size, both little + * endian. + */ +#define PIL_RELOC_NAME_LEN 8 +#define PIL_RELOC_ENTRY_SIZE (PIL_RELOC_NAME_LEN + sizeof(__le64) + sizeof(__le32)) + +struct pil_reloc { + void __iomem *base; + size_t num_entries; +}; + +static struct pil_reloc _reloc __read_mostly; +static DEFINE_MUTEX(pil_reloc_lock); + +static int qcom_pil_info_init(void) +{ + struct device_node *np; + struct resource imem; + void __iomem *base; + int ret; + + /* Already initialized? */ + if (_reloc.base) + return 0; + + np = of_find_compatible_node(NULL, NULL, "qcom,pil-reloc-info"); + if (!np) + return -ENOENT; + + ret = of_address_to_resource(np, 0, &imem); + of_node_put(np); + if (ret < 0) + return ret; + + base = ioremap(imem.start, resource_size(&imem)); + if (!base) { + pr_err("failed to map PIL relocation info region\n"); + return -ENOMEM; + } + + memset_io(base, 0, resource_size(&imem)); + + _reloc.base = base; + _reloc.num_entries = resource_size(&imem) / PIL_RELOC_ENTRY_SIZE; + + return 0; +} + +/** + * qcom_pil_info_store() - store PIL information of image in IMEM + * @image: name of the image + * @base: base address of the loaded image + * @size: size of the loaded image + * + * Return: 0 on success, negative errno on failure + */ +int qcom_pil_info_store(const char *image, phys_addr_t base, size_t size) +{ + char buf[PIL_RELOC_NAME_LEN]; + void __iomem *entry; + int ret; + int i; + + mutex_lock(&pil_reloc_lock); + ret = qcom_pil_info_init(); + if (ret < 0) { + mutex_unlock(&pil_reloc_lock); + return ret; + } + + for (i = 0; i < _reloc.num_entries; i++) { + entry = _reloc.base + i * PIL_RELOC_ENTRY_SIZE; + + memcpy_fromio(buf, entry, PIL_RELOC_NAME_LEN); + + /* + * An empty record means we didn't find it, given that the + * records are packed. + */ + if (!buf[0]) + goto found_unused; + + if (!strncmp(buf, image, PIL_RELOC_NAME_LEN)) + goto found_existing; + } + + pr_warn("insufficient PIL info slots\n"); + mutex_unlock(&pil_reloc_lock); + return -ENOMEM; + +found_unused: + memcpy_toio(entry, image, PIL_RELOC_NAME_LEN); +found_existing: + /* Use two writel() as base is only aligned to 4 bytes on odd entries */ + writel(base, entry + PIL_RELOC_NAME_LEN); + writel(base >> 32, entry + PIL_RELOC_NAME_LEN + 4); + writel(size, entry + PIL_RELOC_NAME_LEN + sizeof(__le64)); + mutex_unlock(&pil_reloc_lock); + + return 0; +} +EXPORT_SYMBOL_GPL(qcom_pil_info_store); + +static void __exit pil_reloc_exit(void) +{ + mutex_lock(&pil_reloc_lock); + iounmap(_reloc.base); + _reloc.base = NULL; + mutex_unlock(&pil_reloc_lock); +} +module_exit(pil_reloc_exit); + +MODULE_DESCRIPTION("Qualcomm PIL relocation info"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/remoteproc/qcom_pil_info.h b/drivers/remoteproc/qcom_pil_info.h new file mode 100644 index 0000000000000..0dce6142935ee --- /dev/null +++ b/drivers/remoteproc/qcom_pil_info.h @@ -0,0 +1,9 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef __QCOM_PIL_INFO_H__ +#define __QCOM_PIL_INFO_H__ + +#include + +int qcom_pil_info_store(const char *image, phys_addr_t base, size_t size); + +#endif -- GitLab From d4c78d2167913b3f7af0d2189fd3d76f6614a1bf Mon Sep 17 00:00:00 2001 From: Bjorn Andersson Date: Mon, 22 Jun 2020 12:19:40 -0700 Subject: [PATCH 0142/2249] remoteproc: qcom: Update PIL relocation info on load Update the PIL relocation information in IMEM with information about where the firmware for various remoteprocs are loaded. Reviewed-by: Vinod Koul Reviewed-by: Stephen Boyd Signed-off-by: Bjorn Andersson Link: https://lore.kernel.org/r/20200622191942.255460-4-bjorn.andersson@linaro.org Signed-off-by: Bjorn Andersson --- drivers/remoteproc/Kconfig | 5 +++++ drivers/remoteproc/qcom_q6v5_adsp.c | 16 +++++++++++++--- drivers/remoteproc/qcom_q6v5_mss.c | 3 +++ drivers/remoteproc/qcom_q6v5_pas.c | 15 ++++++++++++--- drivers/remoteproc/qcom_q6v5_wcss.c | 14 +++++++++++--- drivers/remoteproc/qcom_wcnss.c | 14 +++++++++++--- 6 files changed, 55 insertions(+), 12 deletions(-) diff --git a/drivers/remoteproc/Kconfig b/drivers/remoteproc/Kconfig index f4bd96d1a1a34..3e8d5d1a2b9ee 100644 --- a/drivers/remoteproc/Kconfig +++ b/drivers/remoteproc/Kconfig @@ -135,6 +135,7 @@ config QCOM_Q6V5_ADSP depends on RPMSG_QCOM_GLINK_SMEM || RPMSG_QCOM_GLINK_SMEM=n depends on QCOM_SYSMON || QCOM_SYSMON=n select MFD_SYSCON + select QCOM_PIL_INFO select QCOM_MDT_LOADER select QCOM_Q6V5_COMMON select QCOM_RPROC_COMMON @@ -151,6 +152,7 @@ config QCOM_Q6V5_MSS depends on QCOM_SYSMON || QCOM_SYSMON=n select MFD_SYSCON select QCOM_MDT_LOADER + select QCOM_PIL_INFO select QCOM_Q6V5_COMMON select QCOM_Q6V5_IPA_NOTIFY select QCOM_RPROC_COMMON @@ -167,6 +169,7 @@ config QCOM_Q6V5_PAS depends on RPMSG_QCOM_GLINK_SMEM || RPMSG_QCOM_GLINK_SMEM=n depends on QCOM_SYSMON || QCOM_SYSMON=n select MFD_SYSCON + select QCOM_PIL_INFO select QCOM_MDT_LOADER select QCOM_Q6V5_COMMON select QCOM_RPROC_COMMON @@ -185,6 +188,7 @@ config QCOM_Q6V5_WCSS depends on QCOM_SYSMON || QCOM_SYSMON=n select MFD_SYSCON select QCOM_MDT_LOADER + select QCOM_PIL_INFO select QCOM_Q6V5_COMMON select QCOM_RPROC_COMMON select QCOM_SCM @@ -218,6 +222,7 @@ config QCOM_WCNSS_PIL depends on QCOM_SMEM depends on QCOM_SYSMON || QCOM_SYSMON=n select QCOM_MDT_LOADER + select QCOM_PIL_INFO select QCOM_RPROC_COMMON select QCOM_SCM help diff --git a/drivers/remoteproc/qcom_q6v5_adsp.c b/drivers/remoteproc/qcom_q6v5_adsp.c index d2a2574dcf354..efb2c1aa80a3c 100644 --- a/drivers/remoteproc/qcom_q6v5_adsp.c +++ b/drivers/remoteproc/qcom_q6v5_adsp.c @@ -26,6 +26,7 @@ #include #include "qcom_common.h" +#include "qcom_pil_info.h" #include "qcom_q6v5.h" #include "remoteproc_internal.h" @@ -82,6 +83,7 @@ struct qcom_adsp { unsigned int halt_lpass; int crash_reason_smem; + const char *info_name; struct completion start_done; struct completion stop_done; @@ -164,10 +166,17 @@ static int qcom_adsp_shutdown(struct qcom_adsp *adsp) static int adsp_load(struct rproc *rproc, const struct firmware *fw) { struct qcom_adsp *adsp = (struct qcom_adsp *)rproc->priv; + int ret; + + ret = qcom_mdt_load_no_init(adsp->dev, fw, rproc->firmware, 0, + adsp->mem_region, adsp->mem_phys, + adsp->mem_size, &adsp->mem_reloc); + if (ret) + return ret; + + qcom_pil_info_store(adsp->info_name, adsp->mem_phys, adsp->mem_size); - return qcom_mdt_load_no_init(adsp->dev, fw, rproc->firmware, 0, - adsp->mem_region, adsp->mem_phys, adsp->mem_size, - &adsp->mem_reloc); + return 0; } static int adsp_start(struct rproc *rproc) @@ -436,6 +445,7 @@ static int adsp_probe(struct platform_device *pdev) adsp = (struct qcom_adsp *)rproc->priv; adsp->dev = &pdev->dev; adsp->rproc = rproc; + adsp->info_name = desc->sysmon_name; platform_set_drvdata(pdev, adsp); ret = adsp_alloc_memory_region(adsp); diff --git a/drivers/remoteproc/qcom_q6v5_mss.c b/drivers/remoteproc/qcom_q6v5_mss.c index feb70283b6a21..dd37e462ed615 100644 --- a/drivers/remoteproc/qcom_q6v5_mss.c +++ b/drivers/remoteproc/qcom_q6v5_mss.c @@ -29,6 +29,7 @@ #include "remoteproc_internal.h" #include "qcom_common.h" +#include "qcom_pil_info.h" #include "qcom_q6v5.h" #include @@ -1189,6 +1190,8 @@ static int q6v5_mpss_load(struct q6v5 *qproc) else if (ret < 0) dev_err(qproc->dev, "MPSS authentication failed: %d\n", ret); + qcom_pil_info_store("modem", qproc->mpss_phys, qproc->mpss_size); + release_firmware: release_firmware(fw); out: diff --git a/drivers/remoteproc/qcom_q6v5_pas.c b/drivers/remoteproc/qcom_q6v5_pas.c index 61791a03f648c..3837f23995e05 100644 --- a/drivers/remoteproc/qcom_q6v5_pas.c +++ b/drivers/remoteproc/qcom_q6v5_pas.c @@ -25,6 +25,7 @@ #include #include "qcom_common.h" +#include "qcom_pil_info.h" #include "qcom_q6v5.h" #include "remoteproc_internal.h" @@ -64,6 +65,7 @@ struct qcom_adsp { int pas_id; int crash_reason_smem; bool has_aggre2_clk; + const char *info_name; struct completion start_done; struct completion stop_done; @@ -117,11 +119,17 @@ static void adsp_pds_disable(struct qcom_adsp *adsp, struct device **pds, static int adsp_load(struct rproc *rproc, const struct firmware *fw) { struct qcom_adsp *adsp = (struct qcom_adsp *)rproc->priv; + int ret; - return qcom_mdt_load(adsp->dev, fw, rproc->firmware, adsp->pas_id, - adsp->mem_region, adsp->mem_phys, adsp->mem_size, - &adsp->mem_reloc); + ret = qcom_mdt_load(adsp->dev, fw, rproc->firmware, adsp->pas_id, + adsp->mem_region, adsp->mem_phys, adsp->mem_size, + &adsp->mem_reloc); + if (ret) + return ret; + qcom_pil_info_store(adsp->info_name, adsp->mem_phys, adsp->mem_size); + + return 0; } static int adsp_start(struct rproc *rproc) @@ -405,6 +413,7 @@ static int adsp_probe(struct platform_device *pdev) adsp->rproc = rproc; adsp->pas_id = desc->pas_id; adsp->has_aggre2_clk = desc->has_aggre2_clk; + adsp->info_name = desc->sysmon_name; platform_set_drvdata(pdev, adsp); device_wakeup_enable(adsp->dev); diff --git a/drivers/remoteproc/qcom_q6v5_wcss.c b/drivers/remoteproc/qcom_q6v5_wcss.c index 88c76b9417fab..8846ef0b0f1a2 100644 --- a/drivers/remoteproc/qcom_q6v5_wcss.c +++ b/drivers/remoteproc/qcom_q6v5_wcss.c @@ -14,6 +14,7 @@ #include #include #include "qcom_common.h" +#include "qcom_pil_info.h" #include "qcom_q6v5.h" #define WCSS_CRASH_REASON 421 @@ -424,10 +425,17 @@ static void *q6v5_wcss_da_to_va(struct rproc *rproc, u64 da, size_t len) static int q6v5_wcss_load(struct rproc *rproc, const struct firmware *fw) { struct q6v5_wcss *wcss = rproc->priv; + int ret; + + ret = qcom_mdt_load_no_init(wcss->dev, fw, rproc->firmware, + 0, wcss->mem_region, wcss->mem_phys, + wcss->mem_size, &wcss->mem_reloc); + if (ret) + return ret; + + qcom_pil_info_store("wcnss", wcss->mem_phys, wcss->mem_size); - return qcom_mdt_load_no_init(wcss->dev, fw, rproc->firmware, - 0, wcss->mem_region, wcss->mem_phys, - wcss->mem_size, &wcss->mem_reloc); + return ret; } static const struct rproc_ops q6v5_wcss_ops = { diff --git a/drivers/remoteproc/qcom_wcnss.c b/drivers/remoteproc/qcom_wcnss.c index 5d65e1a9329a0..e2573f79a137d 100644 --- a/drivers/remoteproc/qcom_wcnss.c +++ b/drivers/remoteproc/qcom_wcnss.c @@ -27,6 +27,7 @@ #include "qcom_common.h" #include "remoteproc_internal.h" +#include "qcom_pil_info.h" #include "qcom_wcnss.h" #define WCNSS_CRASH_REASON_SMEM 422 @@ -145,10 +146,17 @@ void qcom_wcnss_assign_iris(struct qcom_wcnss *wcnss, static int wcnss_load(struct rproc *rproc, const struct firmware *fw) { struct qcom_wcnss *wcnss = (struct qcom_wcnss *)rproc->priv; + int ret; + + ret = qcom_mdt_load(wcnss->dev, fw, rproc->firmware, WCNSS_PAS_ID, + wcnss->mem_region, wcnss->mem_phys, + wcnss->mem_size, &wcnss->mem_reloc); + if (ret) + return ret; + + qcom_pil_info_store("wcnss", wcnss->mem_phys, wcnss->mem_size); - return qcom_mdt_load(wcnss->dev, fw, rproc->firmware, WCNSS_PAS_ID, - wcnss->mem_region, wcnss->mem_phys, - wcnss->mem_size, &wcnss->mem_reloc); + return 0; } static void wcnss_indicate_nv_download(struct qcom_wcnss *wcnss) -- GitLab From 304d7a90c43f7471fb481e6b1e2b47fef2a02b8c Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Thu, 18 Jun 2020 21:33:53 -0700 Subject: [PATCH 0143/2249] perf parse-events: Disable a subset of flex warnings Rather than disable all warnings with -w, disable specific warnings. Predicate enabling the warnings on more recent flex versions. Tested with GCC 9.3.0 and clang 9.0.1. Committer notes: The full set of compilers, gcc and clang that this will be tested on will be on the signed tag when this change goes upstream. Added -Wno-misleading-indentation to the flex_flags to overcome this on opensuse tumbleweed when building with clang: CC /tmp/build/perf/util/parse-events-flex.o CC /tmp/build/perf/util/pmu.o /tmp/build/perf/util/parse-events-flex.c:5038:13: error: misleading indentation; statement is not part of the previous 'if' [-Werror,-Wmisleading-indentation] if ( ! yyg->yy_state_buf ) ^ /tmp/build/perf/util/parse-events-flex.c:5036:9: note: previous statement is here if ( ! yyg->yy_state_buf ) ^ And we need to use this to redirect stderr to stdin and then grep in a way that is acceptable for BusyBox shell: 2>&1 | Previously I was using: |& Which seems to be bash specific. Added -Wno-sign-compare to overcome this on systems such as centos:7: CC /tmp/build/perf/util/parse-events-flex.o CC /tmp/build/perf/util/pmu.o CC /tmp/build/perf/util/pmu-flex.o util/parse-events.l: In function 'parse_events_lex': /tmp/build/perf/util/parse-events-flex.c:193:36: error: comparison between signed and unsigned integer expressions [-Werror=sign-compare] for ( yyl = n; yyl < yyleng; ++yyl )\ ^ /tmp/build/perf/util/parse-events-flex.c:204:9: note: in expansion of macro 'YY_LESS_LINENO' Added -Wno-unused-parameter to overcome this in systems such as centos:7: CC /tmp/build/perf/util/parse-events-flex.o CC /tmp/build/perf/util/pmu.o /tmp/build/perf/util/parse-events-flex.c: In function 'yy_fatal_error': /tmp/build/perf/util/parse-events-flex.c:6265:58: error: unused parameter 'yyscanner' [-Werror=unused-parameter] static void yy_fatal_error (yyconst char* msg , yyscan_t yyscanner) ^ Added -Wno-missing-declarations to build in systems such as centos:6: /tmp/build/perf/util/parse-events-flex.c:6313: error: no previous prototype for 'parse_events_get_column' /tmp/build/perf/util/parse-events-flex.c:6389: error: no previous prototype for 'parse_events_set_column' And -Wno-missing-prototypes to cover older compilers: -Wmissing-prototypes (C only) Warn if a global function is defined without a previous prototype declaration. This warning is issued even if the definition itself provides a prototype. The aim is to detect global functions that fail to be declared in header files. -Wmissing-declarations (C only) Warn if a global function is defined without a previous declaration. Do so even if the definition itself provides a prototype. Use this option to detect global functions that are not declared in header files. Older C compilers lack -Wno-misleading-indentation, check if it is available before using it. Also needed to check just the first two levels of the flex version, as the patch was assuming that all versions were of the form x.y.z, and there are several cases where it is just x.y, breaking the build. Signed-off-by: Ian Rogers Acked-by: Jiri Olsa Cc: Adrian Hunter Cc: Alexander Shishkin Cc: Andi Kleen Cc: Jin Yao Cc: John Garry Cc: Mark Rutland Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lore.kernel.org/lkml/20200619043356.90024-8-irogers@google.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/Build | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/tools/perf/util/Build b/tools/perf/util/Build index 504a6bb991ba3..cd86a3068eab4 100644 --- a/tools/perf/util/Build +++ b/tools/perf/util/Build @@ -221,9 +221,19 @@ $(OUTPUT)util/pmu-bison.c $(OUTPUT)util/pmu-bison.h: util/pmu.y $(Q)$(call echo-cmd,bison)$(BISON) -v $< -d $(PARSER_DEBUG_BISON) \ -o $(OUTPUT)util/pmu-bison.c -p perf_pmu_ -CFLAGS_parse-events-flex.o += -w -CFLAGS_pmu-flex.o += -w -CFLAGS_expr-flex.o += -w +FLEX_GE_26 := $(shell expr $(shell $(FLEX) --version | sed -e 's/flex \([0-9]\+\).\([0-9]\+\)/\1\2/g') \>\= 26) +ifeq ($(FLEX_GE_26),1) + flex_flags := -Wno-switch-enum -Wno-switch-default -Wno-unused-function -Wno-redundant-decls -Wno-sign-compare -Wno-unused-parameter -Wno-missing-prototypes -Wno-missing-declarations + CC_HASNT_MISLEADING_INDENTATION := $(shell echo "int main(void) { return 0 }" | $(CC) -Werror -Wno-misleading-indentation -o /dev/null -xc - 2>&1 | grep -q -- -Wno-misleading-indentation ; echo $$?) + ifeq ($(CC_HASNT_MISLEADING_INDENTATION), 1) + flex_flags += -Wno-misleading-indentation + endif +else + flex_flags := -w +endif +CFLAGS_parse-events-flex.o += $(flex_flags) +CFLAGS_pmu-flex.o += $(flex_flags) +CFLAGS_expr-flex.o += $(flex_flags) CFLAGS_parse-events-bison.o += -DYYENABLE_NLS=0 -w CFLAGS_pmu-bison.o += -DYYENABLE_NLS=0 -DYYLTYPE_IS_TRIVIAL=0 -w CFLAGS_expr-bison.o += -DYYENABLE_NLS=0 -DYYLTYPE_IS_TRIVIAL=0 -w -- GitLab From 1f16fcad688552d442ddf1c5d3d8d4152d9bf4af Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Thu, 18 Jun 2020 21:33:56 -0700 Subject: [PATCH 0144/2249] perf parse-events: Disable a subset of bison warnings Rather than disable all warnings with -w, disable specific warnings. Predicate enabling the warnings on a recent version of bison. Tested with GCC 9.3.0 and clang 9.0.1. Committer testing: The full set of compilers, gcc and clang that this will be tested on will be on the signed tag when this change goes upstream. Had to add -Wno-switch-enum to build on opensuse tumbleweed: /tmp/build/perf/util/parse-events-bison.c: In function 'yydestruct': /tmp/build/perf/util/parse-events-bison.c:1200:3: error: enumeration value 'YYSYMBOL_YYEMPTY' not handled in switch [-Werror=switch-enum] 1200 | switch (yykind) | ^~~~~~ /tmp/build/perf/util/parse-events-bison.c:1200:3: error: enumeration value 'YYSYMBOL_YYEOF' not handled in switch [-Werror=switch-enum] Also replace -Wno-error=implicit-function-declaration with -Wno-implicit-function-declaration. Also needed to check just the first two levels of the bison version, as the patch was assuming that all versions were of the form x.y.z, and there are several cases where it is just x.y, breaking the build. Signed-off-by: Ian Rogers Cc: Adrian Hunter Cc: Alexander Shishkin Cc: Andi Kleen Cc: Jin Yao Cc: John Garry Cc: Mark Rutland Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lore.kernel.org/lkml/20200619043356.90024-11-irogers@google.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/Build | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/tools/perf/util/Build b/tools/perf/util/Build index cd86a3068eab4..380e6a9f564dc 100644 --- a/tools/perf/util/Build +++ b/tools/perf/util/Build @@ -234,9 +234,17 @@ endif CFLAGS_parse-events-flex.o += $(flex_flags) CFLAGS_pmu-flex.o += $(flex_flags) CFLAGS_expr-flex.o += $(flex_flags) -CFLAGS_parse-events-bison.o += -DYYENABLE_NLS=0 -w -CFLAGS_pmu-bison.o += -DYYENABLE_NLS=0 -DYYLTYPE_IS_TRIVIAL=0 -w -CFLAGS_expr-bison.o += -DYYENABLE_NLS=0 -DYYLTYPE_IS_TRIVIAL=0 -w + +bison_flags := -DYYENABLE_NLS=0 +BISON_GE_35 := $(shell expr $(shell $(BISON) --version | grep bison | sed -e 's/.\+ \([0-9]\+\).\([0-9]\+\)/\1\2/g') \>\= 35) +ifeq ($(BISON_GE_35),1) + bison_flags += -Wno-unused-parameter -Wno-nested-externs -Wno-implicit-function-declaration -Wno-switch-enum +else + bison_flags += -w +endif +CFLAGS_parse-events-bison.o += $(bison_flags) +CFLAGS_pmu-bison.o += -DYYLTYPE_IS_TRIVIAL=0 $(bison_flags) +CFLAGS_expr-bison.o += -DYYLTYPE_IS_TRIVIAL=0 $(bison_flags) $(OUTPUT)util/parse-events.o: $(OUTPUT)util/parse-events-flex.c $(OUTPUT)util/parse-events-bison.c $(OUTPUT)util/pmu.o: $(OUTPUT)util/pmu-flex.c $(OUTPUT)util/pmu-bison.c -- GitLab From 34148b13eec9c738327f8c8f84f468f4694b17a3 Mon Sep 17 00:00:00 2001 From: "Steven Rostedt (VMware)" Date: Wed, 1 Jul 2020 18:15:07 -0400 Subject: [PATCH 0145/2249] ktest.pl: Add the log of last test in email on failure If a failure happens and an email is sent, show the contents of the log of the last test that failed in the email. Link: http://lore.kernel.org/r/20200701231756.619246244@goodmis.org Reviewed-by: Greg Kroah-Hartman Signed-off-by: Steven Rostedt (VMware) --- tools/testing/ktest/ktest.pl | 42 ++++++++++++++++++++++++++++++++---- 1 file changed, 38 insertions(+), 4 deletions(-) diff --git a/tools/testing/ktest/ktest.pl b/tools/testing/ktest/ktest.pl index e90e2e7cb72cf..8a4a33492952b 100755 --- a/tools/testing/ktest/ktest.pl +++ b/tools/testing/ktest/ktest.pl @@ -82,6 +82,8 @@ my %default = ( "IGNORE_UNUSED" => 0, ); +my $test_log_start = 0; + my $ktest_config = "ktest.conf"; my $version; my $have_version = 0; @@ -1492,8 +1494,21 @@ sub dodie { if ($email_on_error) { my $name = get_test_name; + my $log_file; + + if (defined($opt{"LOG_FILE"})) { + $log_file = "$tmpdir/log"; + open (L, "$opt{LOG_FILE}") or die "Can't open $opt{LOG_FILE} to read)"; + open (O, "> $tmpdir/log") or die "Can't open $tmpdir/log\n"; + seek(L, $test_log_start, 0); + while () { + print O; + } + close O; + close L; + } send_email("KTEST: critical failure for test $i [$name]", - "Your test started at $script_start_time has failed with:\n@_\n"); + "Your test started at $script_start_time has failed with:\n@_\n", $log_file); } if ($monitor_cnt) { @@ -4185,7 +4200,7 @@ sub find_mailer { } sub do_send_mail { - my ($subject, $message) = @_; + my ($subject, $message, $file) = @_; if (!defined($mail_path)) { # find the mailer @@ -4195,16 +4210,30 @@ sub do_send_mail { } } + my $header_file = "$tmpdir/header"; + open (HEAD, ">$header_file") or die "Can not create $header_file\n"; + print HEAD "To: $mailto\n"; + print HEAD "Subject: $subject\n\n"; + print HEAD "$message\n"; + close HEAD; + if (!defined($mail_command)) { if ($mailer eq "mail" || $mailer eq "mailx") { - $mail_command = "\$MAIL_PATH/\$MAILER -s \'\$SUBJECT\' \$MAILTO <<< \'\$MESSAGE\'"; + $mail_command = "cat \$HEADER_FILE \$BODY_FILE | \$MAIL_PATH/\$MAILER -s \'\$SUBJECT\' \$MAILTO"; } elsif ($mailer eq "sendmail" ) { - $mail_command = "echo \'Subject: \$SUBJECT\n\n\$MESSAGE\' | \$MAIL_PATH/\$MAILER -t \$MAILTO"; + $mail_command = "cat \$HEADER_FILE \$BODY_FILE | \$MAIL_PATH/\$MAILER -t \$MAILTO"; } else { die "\nYour mailer: $mailer is not supported.\n"; } } + if (defined($file)) { + $mail_command =~ s/\$BODY_FILE/$file/g; + } else { + $mail_command =~ s/\$BODY_FILE//g; + } + + $mail_command =~ s/\$HEADER_FILE/$header_file/g; $mail_command =~ s/\$MAILER/$mailer/g; $mail_command =~ s/\$MAIL_PATH/$mail_path/g; $mail_command =~ s/\$MAILTO/$mailto/g; @@ -4352,6 +4381,11 @@ for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) { } doprint "\n\n"; + + if (defined($opt{"LOG_FILE"})) { + $test_log_start = tell(LOG); + } + doprint "RUNNING TEST $i of $opt{NUM_TESTS}$name with option $test_type $run_type$installme\n\n"; if (defined($pre_test)) { -- GitLab From f986900209093f5de887d6c342139df6ebec04ac Mon Sep 17 00:00:00 2001 From: "Steven Rostedt (VMware)" Date: Wed, 1 Jul 2020 18:34:10 -0400 Subject: [PATCH 0146/2249] ktest.pl: Add MAIL_MAX_SIZE to limit the amount of log emailed Add the ktest config option MAIL_MAX_SIZE that will limit the size of the log file that is placed into the email on failure. Link: https://lore.kernel.org/r/20200701231756.790637968@goodmis.org Reviewed-by: Greg Kroah-Hartman Signed-off-by: Steven Rostedt (VMware) --- tools/testing/ktest/ktest.pl | 12 +++++++++++- tools/testing/ktest/sample.conf | 13 +++++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/tools/testing/ktest/ktest.pl b/tools/testing/ktest/ktest.pl index 8a4a33492952b..36db5b0b36475 100755 --- a/tools/testing/ktest/ktest.pl +++ b/tools/testing/ktest/ktest.pl @@ -227,6 +227,7 @@ my $dirname = $FindBin::Bin; my $mailto; my $mailer; my $mail_path; +my $mail_max_size; my $mail_command; my $email_on_error; my $email_when_finished; @@ -263,6 +264,7 @@ my %option_map = ( "MAILTO" => \$mailto, "MAILER" => \$mailer, "MAIL_PATH" => \$mail_path, + "MAIL_MAX_SIZE" => \$mail_max_size, "MAIL_COMMAND" => \$mail_command, "EMAIL_ON_ERROR" => \$email_on_error, "EMAIL_WHEN_FINISHED" => \$email_when_finished, @@ -1497,10 +1499,18 @@ sub dodie { my $log_file; if (defined($opt{"LOG_FILE"})) { + my $size = 0; + if (defined($mail_max_size)) { + my $log_size = tell LOG; + $log_size -= $test_log_start; + if ($log_size > $mail_max_size) { + $size = $log_size - $mail_max_size; + } + } $log_file = "$tmpdir/log"; open (L, "$opt{LOG_FILE}") or die "Can't open $opt{LOG_FILE} to read)"; open (O, "> $tmpdir/log") or die "Can't open $tmpdir/log\n"; - seek(L, $test_log_start, 0); + seek(L, $test_log_start + $size, 0); while () { print O; } diff --git a/tools/testing/ktest/sample.conf b/tools/testing/ktest/sample.conf index cb8227fbd01ed..5e7d1d7297529 100644 --- a/tools/testing/ktest/sample.conf +++ b/tools/testing/ktest/sample.conf @@ -442,6 +442,19 @@ # Users can cancel the test by Ctrl^C # (default 0) #EMAIL_WHEN_CANCELED = 1 +# +# If a test ends with an error and EMAIL_ON_ERROR is set as well +# as a LOG_FILE is defined, then the log of the failing test will +# be included in the email that is sent. +# It is possible that the log may be very large, in which case, +# only the last amount of the log should be sent. To limit how +# much of the log is sent, set MAIL_MAX_SIZE. This will be the +# size in bytes of the last portion of the log of the failed +# test file. That is, if this is set to 100000, then only the +# last 100 thousand bytes of the log file will be included in +# the email. +# (default undef) +#MAIL_MAX_SIZE = 1000000 # Start a test setup. If you leave this off, all options # will be default and the test will run once. -- GitLab From 3180cfabf6fbf982ca6d1a6eb56334647cc1416b Mon Sep 17 00:00:00 2001 From: Sebastian Reichel Date: Mon, 29 Jun 2020 13:41:23 +0200 Subject: [PATCH 0147/2249] rtc: cpcap: fix range Unbreak CPCAP driver, which has one more bit in the day counter increasing the max. range from 2014 to 2058. The original commit introducing the range limit was obviously wrong, since the driver has only been written in 2017 (3 years after 14 bits would have run out). Fixes: d2377f8cc5a7 ("rtc: cpcap: set range") Reported-by: Sicelo A. Mhlongo Reported-by: Dev Null Signed-off-by: Sebastian Reichel Signed-off-by: Alexandre Belloni Tested-by: Merlijn Wajer Acked-by: Tony Lindgren Acked-by: Merlijn Wajer Link: https://lore.kernel.org/r/20200629114123.27956-1-sebastian.reichel@collabora.com --- drivers/rtc/rtc-cpcap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/rtc/rtc-cpcap.c b/drivers/rtc/rtc-cpcap.c index a603f1f211250..800667d73a6fb 100644 --- a/drivers/rtc/rtc-cpcap.c +++ b/drivers/rtc/rtc-cpcap.c @@ -261,7 +261,7 @@ static int cpcap_rtc_probe(struct platform_device *pdev) return PTR_ERR(rtc->rtc_dev); rtc->rtc_dev->ops = &cpcap_rtc_ops; - rtc->rtc_dev->range_max = (1 << 14) * SECS_PER_DAY - 1; + rtc->rtc_dev->range_max = (timeu64_t) (DAY_MASK + 1) * SECS_PER_DAY - 1; err = cpcap_get_vendor(dev, rtc->regmap, &rtc->vendor); if (err) -- GitLab From 05513a706b4f8f978c0ecc97b6d99793fbaaaf17 Mon Sep 17 00:00:00 2001 From: "Tales L. da Aparecida" Date: Tue, 23 Jun 2020 22:21:19 -0300 Subject: [PATCH 0148/2249] rtc: imxdi: fix trivial typos Fix typos 'pionter' -> 'pointer' and 'softwere' -> 'software' Signed-off-by: Tales L. da Aparecida Signed-off-by: Alexandre Belloni Link: https://lore.kernel.org/r/20200624012119.54768-1-tales.aparecida@gmail.com --- drivers/rtc/rtc-imxdi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/rtc/rtc-imxdi.c b/drivers/rtc/rtc-imxdi.c index f21dc6b16d88a..8d141d8a5490b 100644 --- a/drivers/rtc/rtc-imxdi.c +++ b/drivers/rtc/rtc-imxdi.c @@ -95,7 +95,7 @@ /** * struct imxdi_dev - private imxdi rtc data - * @pdev: pionter to platform dev + * @pdev: pointer to platform dev * @rtc: pointer to rtc struct * @ioaddr: IO registers pointer * @clk: input reference clock @@ -350,7 +350,7 @@ static int di_handle_invalid_and_failure_state(struct imxdi_dev *imxdi, u32 dsr) * the tamper register is locked. We cannot disable the * tamper detection. The TDCHL can only be reset by a * DRYICE POR, but we cannot force a DRYICE POR in - * softwere because we are still in "FAILURE STATE". + * software because we are still in "FAILURE STATE". * We need a DRYICE POR via battery power cycling.... */ /* -- GitLab From f80531c8217c5b348058a0280f3be05835abd737 Mon Sep 17 00:00:00 2001 From: Jarkko Nikula Date: Thu, 11 Jun 2020 14:05:34 +0300 Subject: [PATCH 0149/2249] i2c: Use separate MODULE_AUTHOR() statements for multiple authors Modules with multiple authors should use multiple MODULE_AUTHOR() statements according to comment in include/linux/module.h. Split the i2c modules with multiple authors to use multiple MODULE_AUTHOR() statements. Signed-off-by: Jarkko Nikula Reviewed-by: Jean Delvare Signed-off-by: Wolfram Sang --- drivers/i2c/algos/i2c-algo-pca.c | 4 ++-- drivers/i2c/busses/i2c-ali1535.c | 8 ++++---- drivers/i2c/busses/i2c-ali15x3.c | 6 +++--- drivers/i2c/busses/i2c-emev2.c | 3 ++- drivers/i2c/busses/i2c-i801.c | 3 ++- drivers/i2c/busses/i2c-nomadik.c | 3 ++- drivers/i2c/busses/i2c-piix4.c | 4 ++-- drivers/i2c/busses/i2c-pnx.c | 3 ++- drivers/i2c/busses/i2c-sh_mobile.c | 3 ++- drivers/i2c/busses/i2c-sibyte.c | 3 ++- drivers/i2c/busses/i2c-sirf.c | 4 ++-- drivers/i2c/busses/i2c-viapro.c | 6 +++--- drivers/i2c/i2c-dev.c | 4 ++-- 13 files changed, 30 insertions(+), 24 deletions(-) diff --git a/drivers/i2c/algos/i2c-algo-pca.c b/drivers/i2c/algos/i2c-algo-pca.c index 7f10312d1b88f..8620963e442c2 100644 --- a/drivers/i2c/algos/i2c-algo-pca.c +++ b/drivers/i2c/algos/i2c-algo-pca.c @@ -541,8 +541,8 @@ int i2c_pca_add_numbered_bus(struct i2c_adapter *adap) } EXPORT_SYMBOL(i2c_pca_add_numbered_bus); -MODULE_AUTHOR("Ian Campbell , " - "Wolfram Sang "); +MODULE_AUTHOR("Ian Campbell "); +MODULE_AUTHOR("Wolfram Sang "); MODULE_DESCRIPTION("I2C-Bus PCA9564/PCA9665 algorithm"); MODULE_LICENSE("GPL"); diff --git a/drivers/i2c/busses/i2c-ali1535.c b/drivers/i2c/busses/i2c-ali1535.c index a43deea390f5a..fb93152845f43 100644 --- a/drivers/i2c/busses/i2c-ali1535.c +++ b/drivers/i2c/busses/i2c-ali1535.c @@ -519,9 +519,9 @@ static struct pci_driver ali1535_driver = { module_pci_driver(ali1535_driver); -MODULE_AUTHOR("Frodo Looijaard , " - "Philip Edelbrock , " - "Mark D. Studebaker " - "and Dan Eaton "); +MODULE_AUTHOR("Frodo Looijaard "); +MODULE_AUTHOR("Philip Edelbrock "); +MODULE_AUTHOR("Mark D. Studebaker "); +MODULE_AUTHOR("Dan Eaton "); MODULE_DESCRIPTION("ALI1535 SMBus driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/i2c/busses/i2c-ali15x3.c b/drivers/i2c/busses/i2c-ali15x3.c index 02185a1cfa775..cc58feacd0821 100644 --- a/drivers/i2c/busses/i2c-ali15x3.c +++ b/drivers/i2c/busses/i2c-ali15x3.c @@ -502,8 +502,8 @@ static struct pci_driver ali15x3_driver = { module_pci_driver(ali15x3_driver); -MODULE_AUTHOR ("Frodo Looijaard , " - "Philip Edelbrock , " - "and Mark D. Studebaker "); +MODULE_AUTHOR("Frodo Looijaard "); +MODULE_AUTHOR("Philip Edelbrock "); +MODULE_AUTHOR("Mark D. Studebaker "); MODULE_DESCRIPTION("ALI15X3 SMBus driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/i2c/busses/i2c-emev2.c b/drivers/i2c/busses/i2c-emev2.c index 1a319352e51b4..a08554c1a5704 100644 --- a/drivers/i2c/busses/i2c-emev2.c +++ b/drivers/i2c/busses/i2c-emev2.c @@ -442,6 +442,7 @@ static struct platform_driver em_i2c_driver = { module_platform_driver(em_i2c_driver); MODULE_DESCRIPTION("EMEV2 I2C bus driver"); -MODULE_AUTHOR("Ian Molton and Wolfram Sang "); +MODULE_AUTHOR("Ian Molton"); +MODULE_AUTHOR("Wolfram Sang "); MODULE_LICENSE("GPL v2"); MODULE_DEVICE_TABLE(of, em_i2c_ids); diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c index fea644921a768..1fc7ae77753d6 100644 --- a/drivers/i2c/busses/i2c-i801.c +++ b/drivers/i2c/busses/i2c-i801.c @@ -1986,7 +1986,8 @@ static void __exit i2c_i801_exit(void) pci_unregister_driver(&i801_driver); } -MODULE_AUTHOR("Mark D. Studebaker , Jean Delvare "); +MODULE_AUTHOR("Mark D. Studebaker "); +MODULE_AUTHOR("Jean Delvare "); MODULE_DESCRIPTION("I801 SMBus driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/i2c/busses/i2c-nomadik.c b/drivers/i2c/busses/i2c-nomadik.c index e1e8d4ef9aa72..d4b1b0865f676 100644 --- a/drivers/i2c/busses/i2c-nomadik.c +++ b/drivers/i2c/busses/i2c-nomadik.c @@ -1122,6 +1122,7 @@ static void __exit nmk_i2c_exit(void) subsys_initcall(nmk_i2c_init); module_exit(nmk_i2c_exit); -MODULE_AUTHOR("Sachin Verma, Srinidhi KASAGAR"); +MODULE_AUTHOR("Sachin Verma"); +MODULE_AUTHOR("Srinidhi KASAGAR"); MODULE_DESCRIPTION("Nomadik/Ux500 I2C driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/i2c/busses/i2c-piix4.c b/drivers/i2c/busses/i2c-piix4.c index 69740a4ff1db2..8c1b31ed0c429 100644 --- a/drivers/i2c/busses/i2c-piix4.c +++ b/drivers/i2c/busses/i2c-piix4.c @@ -1032,7 +1032,7 @@ static struct pci_driver piix4_driver = { module_pci_driver(piix4_driver); -MODULE_AUTHOR("Frodo Looijaard and " - "Philip Edelbrock "); +MODULE_AUTHOR("Frodo Looijaard "); +MODULE_AUTHOR("Philip Edelbrock "); MODULE_DESCRIPTION("PIIX4 SMBus driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/i2c/busses/i2c-pnx.c b/drivers/i2c/busses/i2c-pnx.c index 5d7207c10f1dc..8c4ec7f13f5ab 100644 --- a/drivers/i2c/busses/i2c-pnx.c +++ b/drivers/i2c/busses/i2c-pnx.c @@ -781,7 +781,8 @@ static void __exit i2c_adap_pnx_exit(void) platform_driver_unregister(&i2c_pnx_driver); } -MODULE_AUTHOR("Vitaly Wool, Dennis Kovalev "); +MODULE_AUTHOR("Vitaly Wool"); +MODULE_AUTHOR("Dennis Kovalev "); MODULE_DESCRIPTION("I2C driver for Philips IP3204-based I2C busses"); MODULE_LICENSE("GPL"); MODULE_ALIAS("platform:pnx-i2c"); diff --git a/drivers/i2c/busses/i2c-sh_mobile.c b/drivers/i2c/busses/i2c-sh_mobile.c index 2cca1b21e26e8..cab7255599991 100644 --- a/drivers/i2c/busses/i2c-sh_mobile.c +++ b/drivers/i2c/busses/i2c-sh_mobile.c @@ -932,6 +932,7 @@ static void __exit sh_mobile_i2c_adap_exit(void) module_exit(sh_mobile_i2c_adap_exit); MODULE_DESCRIPTION("SuperH Mobile I2C Bus Controller driver"); -MODULE_AUTHOR("Magnus Damm and Wolfram Sang"); +MODULE_AUTHOR("Magnus Damm"); +MODULE_AUTHOR("Wolfram Sang"); MODULE_LICENSE("GPL v2"); MODULE_ALIAS("platform:i2c-sh_mobile"); diff --git a/drivers/i2c/busses/i2c-sibyte.c b/drivers/i2c/busses/i2c-sibyte.c index 9dcea2ba71681..8f71f01cb169b 100644 --- a/drivers/i2c/busses/i2c-sibyte.c +++ b/drivers/i2c/busses/i2c-sibyte.c @@ -180,6 +180,7 @@ static void __exit i2c_sibyte_exit(void) module_init(i2c_sibyte_init); module_exit(i2c_sibyte_exit); -MODULE_AUTHOR("Kip Walker (Broadcom Corp.), Steven J. Hill "); +MODULE_AUTHOR("Kip Walker (Broadcom Corp.)"); +MODULE_AUTHOR("Steven J. Hill "); MODULE_DESCRIPTION("SMBus adapter routines for SiByte boards"); MODULE_LICENSE("GPL"); diff --git a/drivers/i2c/busses/i2c-sirf.c b/drivers/i2c/busses/i2c-sirf.c index d7f72ec331e80..30db8fafe078e 100644 --- a/drivers/i2c/busses/i2c-sirf.c +++ b/drivers/i2c/busses/i2c-sirf.c @@ -470,6 +470,6 @@ static struct platform_driver i2c_sirfsoc_driver = { module_platform_driver(i2c_sirfsoc_driver); MODULE_DESCRIPTION("SiRF SoC I2C master controller driver"); -MODULE_AUTHOR("Zhiwu Song , " - "Xiangzhen Ye "); +MODULE_AUTHOR("Zhiwu Song "); +MODULE_AUTHOR("Xiangzhen Ye "); MODULE_LICENSE("GPL v2"); diff --git a/drivers/i2c/busses/i2c-viapro.c b/drivers/i2c/busses/i2c-viapro.c index 4abc7771af069..05aa92a3fbe00 100644 --- a/drivers/i2c/busses/i2c-viapro.c +++ b/drivers/i2c/busses/i2c-viapro.c @@ -489,9 +489,9 @@ static void __exit i2c_vt596_exit(void) } } -MODULE_AUTHOR("Kyosti Malkki , " - "Mark D. Studebaker and " - "Jean Delvare "); +MODULE_AUTHOR("Kyosti Malkki "); +MODULE_AUTHOR("Mark D. Studebaker "); +MODULE_AUTHOR("Jean Delvare "); MODULE_DESCRIPTION("vt82c596 SMBus driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/i2c/i2c-dev.c b/drivers/i2c/i2c-dev.c index da020acc9bbd4..6ceb11cc4be18 100644 --- a/drivers/i2c/i2c-dev.c +++ b/drivers/i2c/i2c-dev.c @@ -761,8 +761,8 @@ static void __exit i2c_dev_exit(void) unregister_chrdev_region(MKDEV(I2C_MAJOR, 0), I2C_MINORS); } -MODULE_AUTHOR("Frodo Looijaard and " - "Simon G. Vogl "); +MODULE_AUTHOR("Frodo Looijaard "); +MODULE_AUTHOR("Simon G. Vogl "); MODULE_DESCRIPTION("I2C /dev entries driver"); MODULE_LICENSE("GPL"); -- GitLab From f3e2bd713730e6d69e8e021d3ff574f01c39e7e3 Mon Sep 17 00:00:00 2001 From: John Keeping Date: Tue, 23 Jun 2020 13:06:46 +0100 Subject: [PATCH 0150/2249] i2c: rk3x: support master_xfer_atomic Enable i2c transactions in irq disabled contexts like poweroff where the PMIC is connected via i2c. Signed-off-by: John Keeping Tested-by: Heiko Stuebner Reviewed-by: Heiko Stuebner Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-rk3x.c | 39 +++++++++++++++++++++++++++++++---- 1 file changed, 35 insertions(+), 4 deletions(-) diff --git a/drivers/i2c/busses/i2c-rk3x.c b/drivers/i2c/busses/i2c-rk3x.c index bc698240c4aaa..b67bb54caf272 100644 --- a/drivers/i2c/busses/i2c-rk3x.c +++ b/drivers/i2c/busses/i2c-rk3x.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -1040,8 +1041,21 @@ static int rk3x_i2c_setup(struct rk3x_i2c *i2c, struct i2c_msg *msgs, int num) return ret; } -static int rk3x_i2c_xfer(struct i2c_adapter *adap, - struct i2c_msg *msgs, int num) +static int rk3x_i2c_wait_xfer_poll(struct rk3x_i2c *i2c) +{ + ktime_t timeout = ktime_add_ms(ktime_get(), WAIT_TIMEOUT); + + while (READ_ONCE(i2c->busy) && + ktime_compare(ktime_get(), timeout) < 0) { + udelay(5); + rk3x_i2c_irq(0, i2c); + } + + return !i2c->busy; +} + +static int rk3x_i2c_xfer_common(struct i2c_adapter *adap, + struct i2c_msg *msgs, int num, bool polling) { struct rk3x_i2c *i2c = (struct rk3x_i2c *)adap->algo_data; unsigned long timeout, flags; @@ -1075,8 +1089,12 @@ static int rk3x_i2c_xfer(struct i2c_adapter *adap, rk3x_i2c_start(i2c); - timeout = wait_event_timeout(i2c->wait, !i2c->busy, - msecs_to_jiffies(WAIT_TIMEOUT)); + if (!polling) { + timeout = wait_event_timeout(i2c->wait, !i2c->busy, + msecs_to_jiffies(WAIT_TIMEOUT)); + } else { + timeout = rk3x_i2c_wait_xfer_poll(i2c); + } spin_lock_irqsave(&i2c->lock, flags); @@ -1110,6 +1128,18 @@ static int rk3x_i2c_xfer(struct i2c_adapter *adap, return ret < 0 ? ret : num; } +static int rk3x_i2c_xfer(struct i2c_adapter *adap, + struct i2c_msg *msgs, int num) +{ + return rk3x_i2c_xfer_common(adap, msgs, num, false); +} + +static int rk3x_i2c_xfer_polling(struct i2c_adapter *adap, + struct i2c_msg *msgs, int num) +{ + return rk3x_i2c_xfer_common(adap, msgs, num, true); +} + static __maybe_unused int rk3x_i2c_resume(struct device *dev) { struct rk3x_i2c *i2c = dev_get_drvdata(dev); @@ -1126,6 +1156,7 @@ static u32 rk3x_i2c_func(struct i2c_adapter *adap) static const struct i2c_algorithm rk3x_i2c_algorithm = { .master_xfer = rk3x_i2c_xfer, + .master_xfer_atomic = rk3x_i2c_xfer_polling, .functionality = rk3x_i2c_func, }; -- GitLab From 0a7f99aad259d223ce69c03e792c7e2bfcf8c2c6 Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Fri, 3 Jul 2020 17:49:48 +0200 Subject: [PATCH 0151/2249] clk: rockchip: use separate compatibles for rk3288w-cru Commit 1627f683636d ("clk: rockchip: Handle clock tree for rk3288w variant") added the check for rk3288w-specific clock-tree changes but in turn would require a double-compatible due to re-using the main rockchip,rk3288-cru compatible as entry point. The binding change actually describes the compatibles as one or the other so adapt the code accordingly and add a real second entry-point for the clock controller. Signed-off-by: Heiko Stuebner Reviewed-by: Ezequiel Garcia Reviewed-by: Jagan Teki Tested-by: Jagan Teki # rock-pi-n8 Link: https://lore.kernel.org/r/20200703154948.260369-1-heiko@sntech.de --- drivers/clk/rockchip/clk-rk3288.c | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/drivers/clk/rockchip/clk-rk3288.c b/drivers/clk/rockchip/clk-rk3288.c index 204976e2d0cb8..93c794695c469 100644 --- a/drivers/clk/rockchip/clk-rk3288.c +++ b/drivers/clk/rockchip/clk-rk3288.c @@ -15,6 +15,11 @@ #define RK3288_GRF_SOC_CON(x) (0x244 + x * 4) #define RK3288_GRF_SOC_STATUS1 0x284 +enum rk3288_variant { + RK3288_CRU, + RK3288W_CRU, +}; + enum rk3288_plls { apll, dpll, cpll, gpll, npll, }; @@ -922,7 +927,8 @@ static struct syscore_ops rk3288_clk_syscore_ops = { .resume = rk3288_clk_resume, }; -static void __init rk3288_clk_init(struct device_node *np) +static void __init rk3288_common_init(struct device_node *np, + enum rk3288_variant soc) { struct rockchip_clk_provider *ctx; @@ -945,7 +951,7 @@ static void __init rk3288_clk_init(struct device_node *np) rockchip_clk_register_branches(ctx, rk3288_clk_branches, ARRAY_SIZE(rk3288_clk_branches)); - if (of_device_is_compatible(np, "rockchip,rk3288w-cru")) + if (soc == RK3288W_CRU) rockchip_clk_register_branches(ctx, rk3288w_hclkvio_branch, ARRAY_SIZE(rk3288w_hclkvio_branch)); else @@ -970,4 +976,15 @@ static void __init rk3288_clk_init(struct device_node *np) rockchip_clk_of_add_provider(np, ctx); } + +static void __init rk3288_clk_init(struct device_node *np) +{ + rk3288_common_init(np, RK3288_CRU); +} CLK_OF_DECLARE(rk3288_cru, "rockchip,rk3288-cru", rk3288_clk_init); + +static void __init rk3288w_clk_init(struct device_node *np) +{ + rk3288_common_init(np, RK3288W_CRU); +} +CLK_OF_DECLARE(rk3288w_cru, "rockchip,rk3288w-cru", rk3288w_clk_init); -- GitLab From a47dee5513cd7b6d1e20dfecd458363f24a19cdc Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Mon, 25 May 2020 09:45:21 +0100 Subject: [PATCH 0152/2249] KVM: arm64: Allow in-atomic injection of SPIs On a system that uses SPIs to implement MSIs (as it would be the case on a GICv2 system exposing a GICv2m to its guests), we deny the possibility of injecting SPIs on the in-atomic fast-path. This results in a very large amount of context-switches (roughly equivalent to twice the interrupt rate) on the host, and suboptimal performance for the guest (as measured with a test workload involving a virtio interface backed by vhost-net). Given that GICv2 systems are usually on the low-end of the spectrum performance wise, they could do without the aggravation. We solved this for GICv3+ITS by having a translation cache. But SPIs do not need any extra infrastructure, and can be immediately injected in the virtual distributor as the locking is already heavy enough that we don't need to worry about anything. This halves the number of context switches for the same workload. Reviewed-by: Eric Auger Signed-off-by: Marc Zyngier --- arch/arm64/kvm/vgic/vgic-irqfd.c | 24 +++++++++++++++++++----- arch/arm64/kvm/vgic/vgic-its.c | 3 +-- 2 files changed, 20 insertions(+), 7 deletions(-) diff --git a/arch/arm64/kvm/vgic/vgic-irqfd.c b/arch/arm64/kvm/vgic/vgic-irqfd.c index d8cdfea5cc966..79f8899b234cf 100644 --- a/arch/arm64/kvm/vgic/vgic-irqfd.c +++ b/arch/arm64/kvm/vgic/vgic-irqfd.c @@ -100,19 +100,33 @@ int kvm_set_msi(struct kvm_kernel_irq_routing_entry *e, /** * kvm_arch_set_irq_inatomic: fast-path for irqfd injection - * - * Currently only direct MSI injection is supported. */ int kvm_arch_set_irq_inatomic(struct kvm_kernel_irq_routing_entry *e, struct kvm *kvm, int irq_source_id, int level, bool line_status) { - if (e->type == KVM_IRQ_ROUTING_MSI && vgic_has_its(kvm) && level) { + if (!level) + return -EWOULDBLOCK; + + switch (e->type) { + case KVM_IRQ_ROUTING_MSI: { struct kvm_msi msi; + if (!vgic_has_its(kvm)) + break; + kvm_populate_msi(e, &msi); - if (!vgic_its_inject_cached_translation(kvm, &msi)) - return 0; + return vgic_its_inject_cached_translation(kvm, &msi); + } + + case KVM_IRQ_ROUTING_IRQCHIP: + /* + * Injecting SPIs is always possible in atomic context + * as long as the damn vgic is initialized. + */ + if (unlikely(!vgic_initialized(kvm))) + break; + return vgic_irqfd_set_irq(e, kvm, irq_source_id, 1, line_status); } return -EWOULDBLOCK; diff --git a/arch/arm64/kvm/vgic/vgic-its.c b/arch/arm64/kvm/vgic/vgic-its.c index c012a52b19f57..40cbaca813334 100644 --- a/arch/arm64/kvm/vgic/vgic-its.c +++ b/arch/arm64/kvm/vgic/vgic-its.c @@ -757,9 +757,8 @@ int vgic_its_inject_cached_translation(struct kvm *kvm, struct kvm_msi *msi) db = (u64)msi->address_hi << 32 | msi->address_lo; irq = vgic_its_check_cache(kvm, db, msi->devid, msi->data); - if (!irq) - return -1; + return -EWOULDBLOCK; raw_spin_lock_irqsave(&irq->irq_lock, flags); irq->pending_latch = true; -- GitLab From 2da3ffa6e840b9f8fc65a71326c43b716992861d Mon Sep 17 00:00:00 2001 From: Andrew Scull Date: Thu, 18 Jun 2020 10:36:16 +0100 Subject: [PATCH 0153/2249] arm64: kvm: Remove kern_hyp_va from get_vcpu_ptr get_vcpu_ptr is an assembly accessor for the percpu value kvm_host_data->host_ctxt.__hyp_running_vcpu. kern_hyp_va only applies to nVHE however __hyp_running_vcpu is always assigned a pointer that has already had kern_hyp_va applied in __kvm_vcpu_run_nvhe. kern_hyp_va is currently idempotent as it just masks and inserts the tag, but this could change in future and the second application is unnecessary. Signed-off-by: Andrew Scull Signed-off-by: Marc Zyngier Reviewed-by: James Morse Link: https://lore.kernel.org/r/20200618093616.164413-1-ascull@google.com --- arch/arm64/include/asm/kvm_asm.h | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/arm64/include/asm/kvm_asm.h b/arch/arm64/include/asm/kvm_asm.h index 352aaebf41980..ac71d0939f2eb 100644 --- a/arch/arm64/include/asm/kvm_asm.h +++ b/arch/arm64/include/asm/kvm_asm.h @@ -143,7 +143,6 @@ extern char __smccc_workaround_1_smc[__SMCCC_WORKAROUND_1_SMC_SZ]; .macro get_vcpu_ptr vcpu, ctxt get_host_ctxt \ctxt, \vcpu ldr \vcpu, [\ctxt, #HOST_CONTEXT_VCPU] - kern_hyp_va \vcpu .endm #endif -- GitLab From 6b33e0d64f8501b51d32069e08d3ed68c58c25b4 Mon Sep 17 00:00:00 2001 From: James Morse Date: Mon, 22 Jun 2020 11:33:13 +0000 Subject: [PATCH 0154/2249] KVM: arm64: Drop the target_table[] indirection KVM for 32bit arm had a get/set target mechanism to allow for micro-architecture differences that are visible in system registers to be described. KVM's user-space can query the supported targets for a CPU, and create vCPUs for that target. The target can override the handling of system registers to provide different reset or RES0 behaviour. On 32bit arm this was used to provide different ACTLR reset values for A7 and A15. On 64bit arm, the first few CPUs out of the gate used this mechanism, before it was deemed redundant in commit bca556ac468a ("arm64/kvm: Add generic v8 KVM target"). All future CPUs use the KVM_ARM_TARGET_GENERIC_V8 target. The 64bit target_table[] stuff exists to preserve the ABI to user-space. As all targets registers genericv8_target_table, there is no reason to look the target up. Until we can merge genericv8_target_table with the main sys_regs array, kvm_register_target_sys_reg_table() becomes kvm_check_target_sys_reg_table(), which uses BUG_ON() in keeping with the other callers in this file. Signed-off-by: James Morse Signed-off-by: Marc Zyngier Link: https://lore.kernel.org/r/20200622113317.20477-2-james.morse@arm.com --- arch/arm64/include/asm/kvm_coproc.h | 3 +-- arch/arm64/kvm/sys_regs.c | 16 ++++------------ arch/arm64/kvm/sys_regs.h | 2 ++ arch/arm64/kvm/sys_regs_generic_v8.c | 15 ++------------- 4 files changed, 9 insertions(+), 27 deletions(-) diff --git a/arch/arm64/include/asm/kvm_coproc.h b/arch/arm64/include/asm/kvm_coproc.h index 0185ee8b8b5e0..4bf0d6d05e0f4 100644 --- a/arch/arm64/include/asm/kvm_coproc.h +++ b/arch/arm64/include/asm/kvm_coproc.h @@ -24,8 +24,7 @@ struct kvm_sys_reg_target_table { struct kvm_sys_reg_table table32; }; -void kvm_register_target_sys_reg_table(unsigned int target, - struct kvm_sys_reg_target_table *table); +void kvm_check_target_sys_reg_table(struct kvm_sys_reg_target_table *table); int kvm_handle_cp14_load_store(struct kvm_vcpu *vcpu, struct kvm_run *run); int kvm_handle_cp14_32(struct kvm_vcpu *vcpu, struct kvm_run *run); diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c index baf5ce9225cee..6333a7cd92d35 100644 --- a/arch/arm64/kvm/sys_regs.c +++ b/arch/arm64/kvm/sys_regs.c @@ -2109,17 +2109,10 @@ static int check_sysreg_table(const struct sys_reg_desc *table, unsigned int n, return 0; } -/* Target specific emulation tables */ -static struct kvm_sys_reg_target_table *target_tables[KVM_ARM_NUM_TARGETS]; - -void kvm_register_target_sys_reg_table(unsigned int target, - struct kvm_sys_reg_target_table *table) +void kvm_check_target_sys_reg_table(struct kvm_sys_reg_target_table *table) { - if (check_sysreg_table(table->table64.table, table->table64.num, false) || - check_sysreg_table(table->table32.table, table->table32.num, true)) - return; - - target_tables[target] = table; + BUG_ON(check_sysreg_table(table->table64.table, table->table64.num, false)); + BUG_ON(check_sysreg_table(table->table32.table, table->table32.num, true)); } /* Get specific register table for this target. */ @@ -2127,9 +2120,8 @@ static const struct sys_reg_desc *get_target_table(unsigned target, bool mode_is_64, size_t *num) { - struct kvm_sys_reg_target_table *table; + struct kvm_sys_reg_target_table *table = &genericv8_target_table; - table = target_tables[target]; if (mode_is_64) { *num = table->table64.num; return table->table64.table; diff --git a/arch/arm64/kvm/sys_regs.h b/arch/arm64/kvm/sys_regs.h index 5a6fc30f59894..933609e883bf1 100644 --- a/arch/arm64/kvm/sys_regs.h +++ b/arch/arm64/kvm/sys_regs.h @@ -165,4 +165,6 @@ const struct sys_reg_desc *find_reg_by_id(u64 id, CRn(sys_reg_CRn(reg)), CRm(sys_reg_CRm(reg)), \ Op2(sys_reg_Op2(reg)) +extern struct kvm_sys_reg_target_table genericv8_target_table; + #endif /* __ARM64_KVM_SYS_REGS_LOCAL_H__ */ diff --git a/arch/arm64/kvm/sys_regs_generic_v8.c b/arch/arm64/kvm/sys_regs_generic_v8.c index aa9d356451ebc..a82cc2ccfd440 100644 --- a/arch/arm64/kvm/sys_regs_generic_v8.c +++ b/arch/arm64/kvm/sys_regs_generic_v8.c @@ -59,7 +59,7 @@ static const struct sys_reg_desc genericv8_cp15_regs[] = { access_actlr }, }; -static struct kvm_sys_reg_target_table genericv8_target_table = { +struct kvm_sys_reg_target_table genericv8_target_table = { .table64 = { .table = genericv8_sys_regs, .num = ARRAY_SIZE(genericv8_sys_regs), @@ -78,18 +78,7 @@ static int __init sys_reg_genericv8_init(void) BUG_ON(cmp_sys_reg(&genericv8_sys_regs[i-1], &genericv8_sys_regs[i]) >= 0); - kvm_register_target_sys_reg_table(KVM_ARM_TARGET_AEM_V8, - &genericv8_target_table); - kvm_register_target_sys_reg_table(KVM_ARM_TARGET_FOUNDATION_V8, - &genericv8_target_table); - kvm_register_target_sys_reg_table(KVM_ARM_TARGET_CORTEX_A53, - &genericv8_target_table); - kvm_register_target_sys_reg_table(KVM_ARM_TARGET_CORTEX_A57, - &genericv8_target_table); - kvm_register_target_sys_reg_table(KVM_ARM_TARGET_XGENE_POTENZA, - &genericv8_target_table); - kvm_register_target_sys_reg_table(KVM_ARM_TARGET_GENERIC_V8, - &genericv8_target_table); + kvm_check_target_sys_reg_table(&genericv8_target_table); return 0; } -- GitLab From 04343ae312ef0d80d601ea1b784b6b039ae9c82a Mon Sep 17 00:00:00 2001 From: James Morse Date: Mon, 22 Jun 2020 11:33:14 +0000 Subject: [PATCH 0155/2249] KVM: arm64: Tolerate an empty target_table list Before emptying the target_table lists, and then removing their infrastructure, add some tolerance to an empty list. Instead of bugging-out on an empty list, pretend we already reached the end in the two-list-walk. Signed-off-by: James Morse Signed-off-by: Marc Zyngier Link: https://lore.kernel.org/r/20200622113317.20477-3-james.morse@arm.com --- arch/arm64/kvm/sys_regs.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c index 6333a7cd92d35..fb448bfc83ec7 100644 --- a/arch/arm64/kvm/sys_regs.c +++ b/arch/arm64/kvm/sys_regs.c @@ -2809,7 +2809,10 @@ static int walk_sys_regs(struct kvm_vcpu *vcpu, u64 __user *uind) i2 = sys_reg_descs; end2 = sys_reg_descs + ARRAY_SIZE(sys_reg_descs); - BUG_ON(i1 == end1 || i2 == end2); + if (i1 == end1) + i1 = NULL; + + BUG_ON(i2 == end2); /* Walk carefully, as both tables may refer to the same register. */ while (i1 || i2) { -- GitLab From af4738290d9dfe3787f60e40f709a4f78a115943 Mon Sep 17 00:00:00 2001 From: James Morse Date: Mon, 22 Jun 2020 11:33:15 +0000 Subject: [PATCH 0156/2249] KVM: arm64: Move ACTLR_EL1 emulation to the sys_reg_descs array The only entry in the genericv8_sys_regs arrays is for emulation of ACTLR_EL1. As all targets emulate this in the same way, move it to sys_reg_descs[]. Signed-off-by: James Morse Signed-off-by: Marc Zyngier Link: https://lore.kernel.org/r/20200622113317.20477-4-james.morse@arm.com --- arch/arm64/kvm/sys_regs.c | 28 ++++++++++++++++++++++++++ arch/arm64/kvm/sys_regs_generic_v8.c | 30 ---------------------------- 2 files changed, 28 insertions(+), 30 deletions(-) diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c index fb448bfc83ec7..f8407cfa9032c 100644 --- a/arch/arm64/kvm/sys_regs.c +++ b/arch/arm64/kvm/sys_regs.c @@ -242,6 +242,25 @@ static bool access_vm_reg(struct kvm_vcpu *vcpu, return true; } +static bool access_actlr(struct kvm_vcpu *vcpu, + struct sys_reg_params *p, + const struct sys_reg_desc *r) +{ + if (p->is_write) + return ignore_write(vcpu, p); + + p->regval = vcpu_read_sys_reg(vcpu, ACTLR_EL1); + + if (p->is_aarch32) { + if (r->Op2 & 2) + p->regval = upper_32_bits(p->regval); + else + p->regval = lower_32_bits(p->regval); + } + + return true; +} + /* * Trap handler for the GICv3 SGI generation system register. * Forward the request to the VGIC emulation. @@ -615,6 +634,12 @@ static void reset_amair_el1(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r) vcpu_write_sys_reg(vcpu, amair, AMAIR_EL1); } +static void reset_actlr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r) +{ + u64 actlr = read_sysreg(actlr_el1); + vcpu_write_sys_reg(vcpu, actlr, ACTLR_EL1); +} + static void reset_mpidr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r) { u64 mpidr; @@ -1518,6 +1543,7 @@ static const struct sys_reg_desc sys_reg_descs[] = { ID_UNALLOCATED(7,7), { SYS_DESC(SYS_SCTLR_EL1), access_vm_reg, reset_val, SCTLR_EL1, 0x00C50078 }, + { SYS_DESC(SYS_ACTLR_EL1), access_actlr, reset_actlr, ACTLR_EL1 }, { SYS_DESC(SYS_CPACR_EL1), NULL, reset_val, CPACR_EL1, 0 }, { SYS_DESC(SYS_ZCR_EL1), NULL, reset_val, ZCR_EL1, 0, .visibility = sve_visibility }, { SYS_DESC(SYS_TTBR0_EL1), access_vm_reg, reset_unknown, TTBR0_EL1 }, @@ -1957,6 +1983,8 @@ static const struct sys_reg_desc cp14_64_regs[] = { static const struct sys_reg_desc cp15_regs[] = { { Op1( 0), CRn( 0), CRm( 0), Op2( 1), access_ctr }, { Op1( 0), CRn( 1), CRm( 0), Op2( 0), access_vm_reg, NULL, c1_SCTLR }, + { Op1( 0), CRn( 1), CRm( 0), Op2( 1), access_actlr }, + { Op1( 0), CRn( 1), CRm( 0), Op2( 3), access_actlr }, { Op1( 0), CRn( 2), CRm( 0), Op2( 0), access_vm_reg, NULL, c2_TTBR0 }, { Op1( 0), CRn( 2), CRm( 0), Op2( 1), access_vm_reg, NULL, c2_TTBR1 }, { Op1( 0), CRn( 2), CRm( 0), Op2( 2), access_vm_reg, NULL, c2_TTBCR }, diff --git a/arch/arm64/kvm/sys_regs_generic_v8.c b/arch/arm64/kvm/sys_regs_generic_v8.c index a82cc2ccfd440..a7e21e61beea7 100644 --- a/arch/arm64/kvm/sys_regs_generic_v8.c +++ b/arch/arm64/kvm/sys_regs_generic_v8.c @@ -19,44 +19,14 @@ #include "sys_regs.h" -static bool access_actlr(struct kvm_vcpu *vcpu, - struct sys_reg_params *p, - const struct sys_reg_desc *r) -{ - if (p->is_write) - return ignore_write(vcpu, p); - - p->regval = vcpu_read_sys_reg(vcpu, ACTLR_EL1); - - if (p->is_aarch32) { - if (r->Op2 & 2) - p->regval = upper_32_bits(p->regval); - else - p->regval = lower_32_bits(p->regval); - } - - return true; -} - -static void reset_actlr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r) -{ - __vcpu_sys_reg(vcpu, ACTLR_EL1) = read_sysreg(actlr_el1); -} - /* * Implementation specific sys-reg registers. * Important: Must be sorted ascending by Op0, Op1, CRn, CRm, Op2 */ static const struct sys_reg_desc genericv8_sys_regs[] = { - { SYS_DESC(SYS_ACTLR_EL1), access_actlr, reset_actlr, ACTLR_EL1 }, }; static const struct sys_reg_desc genericv8_cp15_regs[] = { - /* ACTLR */ - { Op1(0b000), CRn(0b0001), CRm(0b0000), Op2(0b001), - access_actlr }, - { Op1(0b000), CRn(0b0001), CRm(0b0000), Op2(0b011), - access_actlr }, }; struct kvm_sys_reg_target_table genericv8_target_table = { -- GitLab From dcaffa7bf911578a6d69165d712501996c587fbe Mon Sep 17 00:00:00 2001 From: James Morse Date: Mon, 22 Jun 2020 11:33:16 +0000 Subject: [PATCH 0157/2249] KVM: arm64: Remove target_table from exit handlers Whenever KVM searches for a register (e.g. due to a guest exit), it works with two tables, as the target table overrides the sys_regs array. Now that everything is in the sys_regs array, and the target table is empty, stop doing that. Remove the second table and its size from all the functions that take it. Signed-off-by: James Morse Signed-off-by: Marc Zyngier Link: https://lore.kernel.org/r/20200622113317.20477-5-james.morse@arm.com --- arch/arm64/kvm/sys_regs.c | 87 +++++++-------------------------------- 1 file changed, 16 insertions(+), 71 deletions(-) diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c index f8407cfa9032c..14333005b4769 100644 --- a/arch/arm64/kvm/sys_regs.c +++ b/arch/arm64/kvm/sys_regs.c @@ -2269,9 +2269,7 @@ static void unhandled_cp_access(struct kvm_vcpu *vcpu, */ static int kvm_handle_cp_64(struct kvm_vcpu *vcpu, const struct sys_reg_desc *global, - size_t nr_global, - const struct sys_reg_desc *target_specific, - size_t nr_specific) + size_t nr_global) { struct sys_reg_params params; u32 hsr = kvm_vcpu_get_hsr(vcpu); @@ -2298,14 +2296,11 @@ static int kvm_handle_cp_64(struct kvm_vcpu *vcpu, } /* - * Try to emulate the coprocessor access using the target - * specific table first, and using the global table afterwards. - * If either of the tables contains a handler, handle the + * If the table contains a handler, handle the * potential register operation in the case of a read and return * with success. */ - if (!emulate_cp(vcpu, ¶ms, target_specific, nr_specific) || - !emulate_cp(vcpu, ¶ms, global, nr_global)) { + if (!emulate_cp(vcpu, ¶ms, global, nr_global)) { /* Split up the value between registers for the read side */ if (!params.is_write) { vcpu_set_reg(vcpu, Rt, lower_32_bits(params.regval)); @@ -2326,9 +2321,7 @@ static int kvm_handle_cp_64(struct kvm_vcpu *vcpu, */ static int kvm_handle_cp_32(struct kvm_vcpu *vcpu, const struct sys_reg_desc *global, - size_t nr_global, - const struct sys_reg_desc *target_specific, - size_t nr_specific) + size_t nr_global) { struct sys_reg_params params; u32 hsr = kvm_vcpu_get_hsr(vcpu); @@ -2344,8 +2337,7 @@ static int kvm_handle_cp_32(struct kvm_vcpu *vcpu, params.Op1 = (hsr >> 14) & 0x7; params.Op2 = (hsr >> 17) & 0x7; - if (!emulate_cp(vcpu, ¶ms, target_specific, nr_specific) || - !emulate_cp(vcpu, ¶ms, global, nr_global)) { + if (!emulate_cp(vcpu, ¶ms, global, nr_global)) { if (!params.is_write) vcpu_set_reg(vcpu, Rt, params.regval); return 1; @@ -2357,38 +2349,22 @@ static int kvm_handle_cp_32(struct kvm_vcpu *vcpu, int kvm_handle_cp15_64(struct kvm_vcpu *vcpu, struct kvm_run *run) { - const struct sys_reg_desc *target_specific; - size_t num; - - target_specific = get_target_table(vcpu->arch.target, false, &num); - return kvm_handle_cp_64(vcpu, - cp15_64_regs, ARRAY_SIZE(cp15_64_regs), - target_specific, num); + return kvm_handle_cp_64(vcpu, cp15_64_regs, ARRAY_SIZE(cp15_64_regs)); } int kvm_handle_cp15_32(struct kvm_vcpu *vcpu, struct kvm_run *run) { - const struct sys_reg_desc *target_specific; - size_t num; - - target_specific = get_target_table(vcpu->arch.target, false, &num); - return kvm_handle_cp_32(vcpu, - cp15_regs, ARRAY_SIZE(cp15_regs), - target_specific, num); + return kvm_handle_cp_32(vcpu, cp15_regs, ARRAY_SIZE(cp15_regs)); } int kvm_handle_cp14_64(struct kvm_vcpu *vcpu, struct kvm_run *run) { - return kvm_handle_cp_64(vcpu, - cp14_64_regs, ARRAY_SIZE(cp14_64_regs), - NULL, 0); + return kvm_handle_cp_64(vcpu, cp14_64_regs, ARRAY_SIZE(cp14_64_regs)); } int kvm_handle_cp14_32(struct kvm_vcpu *vcpu, struct kvm_run *run) { - return kvm_handle_cp_32(vcpu, - cp14_regs, ARRAY_SIZE(cp14_regs), - NULL, 0); + return kvm_handle_cp_32(vcpu, cp14_regs, ARRAY_SIZE(cp14_regs)); } static bool is_imp_def_sys_reg(struct sys_reg_params *params) @@ -2400,15 +2376,9 @@ static bool is_imp_def_sys_reg(struct sys_reg_params *params) static int emulate_sys_reg(struct kvm_vcpu *vcpu, struct sys_reg_params *params) { - size_t num; - const struct sys_reg_desc *table, *r; - - table = get_target_table(vcpu->arch.target, true, &num); + const struct sys_reg_desc *r; - /* Search target-specific then generic table. */ - r = find_reg(params, table, num); - if (!r) - r = find_reg(params, sys_reg_descs, ARRAY_SIZE(sys_reg_descs)); + r = find_reg(params, sys_reg_descs, ARRAY_SIZE(sys_reg_descs)); if (likely(r)) { perform_access(vcpu, params, r); @@ -2512,8 +2482,7 @@ const struct sys_reg_desc *find_reg_by_id(u64 id, static const struct sys_reg_desc *index_to_sys_reg_desc(struct kvm_vcpu *vcpu, u64 id) { - size_t num; - const struct sys_reg_desc *table, *r; + const struct sys_reg_desc *r; struct sys_reg_params params; /* We only do sys_reg for now. */ @@ -2523,10 +2492,7 @@ static const struct sys_reg_desc *index_to_sys_reg_desc(struct kvm_vcpu *vcpu, if (!index_to_params(id, ¶ms)) return NULL; - table = get_target_table(vcpu->arch.target, true, &num); - r = find_reg(¶ms, table, num); - if (!r) - r = find_reg(¶ms, sys_reg_descs, ARRAY_SIZE(sys_reg_descs)); + r = find_reg(¶ms, sys_reg_descs, ARRAY_SIZE(sys_reg_descs)); /* Not saved in the sys_reg array and not otherwise accessible? */ if (r && !(r->reg || r->get_user)) @@ -2826,38 +2792,17 @@ static int walk_one_sys_reg(const struct kvm_vcpu *vcpu, /* Assumed ordered tables, see kvm_sys_reg_table_init. */ static int walk_sys_regs(struct kvm_vcpu *vcpu, u64 __user *uind) { - const struct sys_reg_desc *i1, *i2, *end1, *end2; + const struct sys_reg_desc *i2, *end2; unsigned int total = 0; - size_t num; int err; - /* We check for duplicates here, to allow arch-specific overrides. */ - i1 = get_target_table(vcpu->arch.target, true, &num); - end1 = i1 + num; i2 = sys_reg_descs; end2 = sys_reg_descs + ARRAY_SIZE(sys_reg_descs); - if (i1 == end1) - i1 = NULL; - - BUG_ON(i2 == end2); - - /* Walk carefully, as both tables may refer to the same register. */ - while (i1 || i2) { - int cmp = cmp_sys_reg(i1, i2); - /* target-specific overrides generic entry. */ - if (cmp <= 0) - err = walk_one_sys_reg(vcpu, i1, &uind, &total); - else - err = walk_one_sys_reg(vcpu, i2, &uind, &total); - + while (i2 != end2) { + err = walk_one_sys_reg(vcpu, i2++, &uind, &total); if (err) return err; - - if (cmp <= 0 && ++i1 == end1) - i1 = NULL; - if (cmp >= 0 && ++i2 == end2) - i2 = NULL; } return total; } -- GitLab From 750ed56693803e992ed09ac9c46e07226dd4d350 Mon Sep 17 00:00:00 2001 From: James Morse Date: Mon, 22 Jun 2020 11:33:17 +0000 Subject: [PATCH 0158/2249] KVM: arm64: Remove the target table Finally, remove the target table. Merge the code that checks the tables into kvm_reset_sys_regs() as there is now only one table. Signed-off-by: James Morse Signed-off-by: Marc Zyngier Link: https://lore.kernel.org/r/20200622113317.20477-6-james.morse@arm.com --- arch/arm64/include/asm/kvm_coproc.h | 7 ---- arch/arm64/kvm/Makefile | 2 +- arch/arm64/kvm/sys_regs.c | 57 ++++++---------------------- arch/arm64/kvm/sys_regs.h | 2 - arch/arm64/kvm/sys_regs_generic_v8.c | 55 --------------------------- 5 files changed, 12 insertions(+), 111 deletions(-) delete mode 100644 arch/arm64/kvm/sys_regs_generic_v8.c diff --git a/arch/arm64/include/asm/kvm_coproc.h b/arch/arm64/include/asm/kvm_coproc.h index 4bf0d6d05e0f4..147f3a77e6a52 100644 --- a/arch/arm64/include/asm/kvm_coproc.h +++ b/arch/arm64/include/asm/kvm_coproc.h @@ -19,13 +19,6 @@ struct kvm_sys_reg_table { size_t num; }; -struct kvm_sys_reg_target_table { - struct kvm_sys_reg_table table64; - struct kvm_sys_reg_table table32; -}; - -void kvm_check_target_sys_reg_table(struct kvm_sys_reg_target_table *table); - int kvm_handle_cp14_load_store(struct kvm_vcpu *vcpu, struct kvm_run *run); int kvm_handle_cp14_32(struct kvm_vcpu *vcpu, struct kvm_run *run); int kvm_handle_cp14_64(struct kvm_vcpu *vcpu, struct kvm_run *run); diff --git a/arch/arm64/kvm/Makefile b/arch/arm64/kvm/Makefile index 8d3d9513cbfe4..48cda50aa2257 100644 --- a/arch/arm64/kvm/Makefile +++ b/arch/arm64/kvm/Makefile @@ -14,7 +14,7 @@ kvm-y := $(KVM)/kvm_main.o $(KVM)/coalesced_mmio.o $(KVM)/eventfd.o \ $(KVM)/vfio.o $(KVM)/irqchip.o \ arm.o mmu.o mmio.o psci.o perf.o hypercalls.o pvtime.o \ inject_fault.o regmap.o va_layout.o hyp.o hyp-init.o handle_exit.o \ - guest.o debug.o reset.o sys_regs.o sys_regs_generic_v8.o \ + guest.o debug.o reset.o sys_regs.o \ vgic-sys-reg-v3.o fpsimd.o pmu.o \ aarch32.o arch_timer.o \ vgic/vgic.o vgic/vgic-init.o \ diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c index 14333005b4769..41a4d3d2a312a 100644 --- a/arch/arm64/kvm/sys_regs.c +++ b/arch/arm64/kvm/sys_regs.c @@ -2137,28 +2137,6 @@ static int check_sysreg_table(const struct sys_reg_desc *table, unsigned int n, return 0; } -void kvm_check_target_sys_reg_table(struct kvm_sys_reg_target_table *table) -{ - BUG_ON(check_sysreg_table(table->table64.table, table->table64.num, false)); - BUG_ON(check_sysreg_table(table->table32.table, table->table32.num, true)); -} - -/* Get specific register table for this target. */ -static const struct sys_reg_desc *get_target_table(unsigned target, - bool mode_is_64, - size_t *num) -{ - struct kvm_sys_reg_target_table *table = &genericv8_target_table; - - if (mode_is_64) { - *num = table->table64.num; - return table->table64.table; - } else { - *num = table->table32.num; - return table->table32.table; - } -} - static int match_sys_reg(const void *key, const void *elt) { const unsigned long pval = (unsigned long)key; @@ -2393,14 +2371,20 @@ static int emulate_sys_reg(struct kvm_vcpu *vcpu, return 1; } -static void reset_sys_reg_descs(struct kvm_vcpu *vcpu, - const struct sys_reg_desc *table, size_t num) +/** + * kvm_reset_sys_regs - sets system registers to reset value + * @vcpu: The VCPU pointer + * + * This function finds the right table above and sets the registers on the + * virtual CPU struct to their architecturally defined reset values. + */ +void kvm_reset_sys_regs(struct kvm_vcpu *vcpu) { unsigned long i; - for (i = 0; i < num; i++) - if (table[i].reset) - table[i].reset(vcpu, &table[i]); + for (i = 0; i < ARRAY_SIZE(sys_reg_descs); i++) + if (sys_reg_descs[i].reset) + sys_reg_descs[i].reset(vcpu, &sys_reg_descs[i]); } /** @@ -2869,22 +2853,3 @@ void kvm_sys_reg_table_init(void) /* Clear all higher bits. */ cache_levels &= (1 << (i*3))-1; } - -/** - * kvm_reset_sys_regs - sets system registers to reset value - * @vcpu: The VCPU pointer - * - * This function finds the right table above and sets the registers on the - * virtual CPU struct to their architecturally defined reset values. - */ -void kvm_reset_sys_regs(struct kvm_vcpu *vcpu) -{ - size_t num; - const struct sys_reg_desc *table; - - /* Generic chip reset first (so target could override). */ - reset_sys_reg_descs(vcpu, sys_reg_descs, ARRAY_SIZE(sys_reg_descs)); - - table = get_target_table(vcpu->arch.target, true, &num); - reset_sys_reg_descs(vcpu, table, num); -} diff --git a/arch/arm64/kvm/sys_regs.h b/arch/arm64/kvm/sys_regs.h index 933609e883bf1..5a6fc30f59894 100644 --- a/arch/arm64/kvm/sys_regs.h +++ b/arch/arm64/kvm/sys_regs.h @@ -165,6 +165,4 @@ const struct sys_reg_desc *find_reg_by_id(u64 id, CRn(sys_reg_CRn(reg)), CRm(sys_reg_CRm(reg)), \ Op2(sys_reg_Op2(reg)) -extern struct kvm_sys_reg_target_table genericv8_target_table; - #endif /* __ARM64_KVM_SYS_REGS_LOCAL_H__ */ diff --git a/arch/arm64/kvm/sys_regs_generic_v8.c b/arch/arm64/kvm/sys_regs_generic_v8.c deleted file mode 100644 index a7e21e61beea7..0000000000000 --- a/arch/arm64/kvm/sys_regs_generic_v8.c +++ /dev/null @@ -1,55 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Copyright (C) 2012,2013 - ARM Ltd - * Author: Marc Zyngier - * - * Based on arch/arm/kvm/coproc_a15.c: - * Copyright (C) 2012 - Virtual Open Systems and Columbia University - * Authors: Rusty Russell - * Christoffer Dall - */ -#include -#include -#include -#include -#include -#include -#include -#include - -#include "sys_regs.h" - -/* - * Implementation specific sys-reg registers. - * Important: Must be sorted ascending by Op0, Op1, CRn, CRm, Op2 - */ -static const struct sys_reg_desc genericv8_sys_regs[] = { -}; - -static const struct sys_reg_desc genericv8_cp15_regs[] = { -}; - -struct kvm_sys_reg_target_table genericv8_target_table = { - .table64 = { - .table = genericv8_sys_regs, - .num = ARRAY_SIZE(genericv8_sys_regs), - }, - .table32 = { - .table = genericv8_cp15_regs, - .num = ARRAY_SIZE(genericv8_cp15_regs), - }, -}; - -static int __init sys_reg_genericv8_init(void) -{ - unsigned int i; - - for (i = 1; i < ARRAY_SIZE(genericv8_sys_regs); i++) - BUG_ON(cmp_sys_reg(&genericv8_sys_regs[i-1], - &genericv8_sys_regs[i]) >= 0); - - kvm_check_target_sys_reg_table(&genericv8_target_table); - - return 0; -} -late_initcall(sys_reg_genericv8_init); -- GitLab From b38b298aa4397e2dc74a89b4dd3eac9e59b64c96 Mon Sep 17 00:00:00 2001 From: David Brazdil Date: Thu, 25 Jun 2020 14:14:06 +0100 Subject: [PATCH 0159/2249] KVM: arm64: Fix symbol dependency in __hyp_call_panic_nvhe __hyp_call_panic_nvhe contains inline assembly which did not declare its dependency on the __hyp_panic_string symbol. The static-declared string has previously been kept alive because of a use in __hyp_call_panic_vhe. Fix this in preparation for separating the source files between VHE and nVHE when the two users land in two different compilation units. The static variable otherwise gets dropped when compiling the nVHE source file, causing an undefined symbol linker error later. Signed-off-by: David Brazdil Signed-off-by: Marc Zyngier Link: https://lore.kernel.org/r/20200625131420.71444-2-dbrazdil@google.com --- arch/arm64/kvm/hyp/switch.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/kvm/hyp/switch.c b/arch/arm64/kvm/hyp/switch.c index db1c4487d95d1..9270b14157b55 100644 --- a/arch/arm64/kvm/hyp/switch.c +++ b/arch/arm64/kvm/hyp/switch.c @@ -897,7 +897,7 @@ static void __hyp_text __hyp_call_panic_nvhe(u64 spsr, u64 elr, u64 par, * making sure it is a kernel address and not a PC-relative * reference. */ - asm volatile("ldr %0, =__hyp_panic_string" : "=r" (str_va)); + asm volatile("ldr %0, =%1" : "=r" (str_va) : "S" (__hyp_panic_string)); __hyp_do_panic(str_va, spsr, elr, -- GitLab From 7b2399ea5640b2e5f576af08b91091a26f240ea4 Mon Sep 17 00:00:00 2001 From: David Brazdil Date: Thu, 25 Jun 2020 14:14:07 +0100 Subject: [PATCH 0160/2249] KVM: arm64: Move __smccc_workaround_1_smc to .rodata This snippet of assembly is used by cpu_errata.c to overwrite parts of KVM hyp vector. Move it to its own source file and change its ELF section to .rodata. Signed-off-by: David Brazdil Signed-off-by: Marc Zyngier Link: https://lore.kernel.org/r/20200625131420.71444-3-dbrazdil@google.com --- arch/arm64/kvm/hyp/Makefile | 1 + arch/arm64/kvm/hyp/hyp-entry.S | 16 ---------------- arch/arm64/kvm/hyp/smccc_wa.S | 32 ++++++++++++++++++++++++++++++++ 3 files changed, 33 insertions(+), 16 deletions(-) create mode 100644 arch/arm64/kvm/hyp/smccc_wa.S diff --git a/arch/arm64/kvm/hyp/Makefile b/arch/arm64/kvm/hyp/Makefile index 8c98807838390..5d8357ddc2344 100644 --- a/arch/arm64/kvm/hyp/Makefile +++ b/arch/arm64/kvm/hyp/Makefile @@ -7,6 +7,7 @@ ccflags-y += -fno-stack-protector -DDISABLE_BRANCH_PROFILING \ $(DISABLE_STACKLEAK_PLUGIN) obj-$(CONFIG_KVM) += hyp.o +obj-$(CONFIG_KVM_INDIRECT_VECTORS) += smccc_wa.o hyp-y := vgic-v3-sr.o timer-sr.o aarch32.o vgic-v2-cpuif-proxy.o sysreg-sr.o \ debug-sr.o entry.o switch.o fpsimd.o tlb.o hyp-entry.o diff --git a/arch/arm64/kvm/hyp/hyp-entry.S b/arch/arm64/kvm/hyp/hyp-entry.S index 9c5cfb04170ee..d362fad97cc83 100644 --- a/arch/arm64/kvm/hyp/hyp-entry.S +++ b/arch/arm64/kvm/hyp/hyp-entry.S @@ -318,20 +318,4 @@ SYM_CODE_START(__bp_harden_hyp_vecs) 1: .org __bp_harden_hyp_vecs + __BP_HARDEN_HYP_VECS_SZ .org 1b SYM_CODE_END(__bp_harden_hyp_vecs) - - .popsection - -SYM_CODE_START(__smccc_workaround_1_smc) - esb - sub sp, sp, #(8 * 4) - stp x2, x3, [sp, #(8 * 0)] - stp x0, x1, [sp, #(8 * 2)] - mov w0, #ARM_SMCCC_ARCH_WORKAROUND_1 - smc #0 - ldp x2, x3, [sp, #(8 * 0)] - ldp x0, x1, [sp, #(8 * 2)] - add sp, sp, #(8 * 4) -1: .org __smccc_workaround_1_smc + __SMCCC_WORKAROUND_1_SMC_SZ - .org 1b -SYM_CODE_END(__smccc_workaround_1_smc) #endif diff --git a/arch/arm64/kvm/hyp/smccc_wa.S b/arch/arm64/kvm/hyp/smccc_wa.S new file mode 100644 index 0000000000000..b0441dbdf68bd --- /dev/null +++ b/arch/arm64/kvm/hyp/smccc_wa.S @@ -0,0 +1,32 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (C) 2015-2018 - ARM Ltd + * Author: Marc Zyngier + */ + +#include +#include + +#include +#include + + /* + * This is not executed directly and is instead copied into the vectors + * by install_bp_hardening_cb(). + */ + .data + .pushsection .rodata + .global __smccc_workaround_1_smc +SYM_DATA_START(__smccc_workaround_1_smc) + esb + sub sp, sp, #(8 * 4) + stp x2, x3, [sp, #(8 * 0)] + stp x0, x1, [sp, #(8 * 2)] + mov w0, #ARM_SMCCC_ARCH_WORKAROUND_1 + smc #0 + ldp x2, x3, [sp, #(8 * 0)] + ldp x0, x1, [sp, #(8 * 2)] + add sp, sp, #(8 * 4) +1: .org __smccc_workaround_1_smc + __SMCCC_WORKAROUND_1_SMC_SZ + .org 1b +SYM_DATA_END(__smccc_workaround_1_smc) -- GitLab From 7621712918ad4f5e6356193d9058debf657a6254 Mon Sep 17 00:00:00 2001 From: David Brazdil Date: Thu, 25 Jun 2020 14:14:08 +0100 Subject: [PATCH 0161/2249] KVM: arm64: Add build rules for separate VHE/nVHE object files Add new folders arch/arm64/kvm/hyp/{vhe,nvhe} and Makefiles for building code that runs in EL2 under VHE/nVHE KVM, repsectivelly. Add an include folder for hyp-specific header files which will include code common to VHE/nVHE. Build nVHE code with -D__KVM_NVHE_HYPERVISOR__, VHE code with -D__KVM_VHE_HYPERVISOR__. Under nVHE compile each source file into a `.hyp.tmp.o` object first, then prefix all its symbols with "__kvm_nvhe_" using `objcopy` and produce a `.hyp.o`. Suffixes were chosen so that it would be possible for VHE and nVHE to share some source files, but compiled with different CFLAGS. The nVHE ELF symbol prefix is added to kallsyms.c as ignored. EL2-only symbols will never appear in EL1 stack traces. Due to symbol prefixing, add a section in image-vars.h for aliases of symbols that are defined in nVHE EL2 and accessed by kernel in EL1 or vice versa. Signed-off-by: David Brazdil Signed-off-by: Marc Zyngier Link: https://lore.kernel.org/r/20200625131420.71444-4-dbrazdil@google.com --- arch/arm64/kernel/image-vars.h | 14 +++++++++++++ arch/arm64/kvm/hyp/Makefile | 10 +++++++--- arch/arm64/kvm/hyp/nvhe/Makefile | 34 ++++++++++++++++++++++++++++++++ arch/arm64/kvm/hyp/vhe/Makefile | 17 ++++++++++++++++ scripts/kallsyms.c | 1 + 5 files changed, 73 insertions(+), 3 deletions(-) create mode 100644 arch/arm64/kvm/hyp/nvhe/Makefile create mode 100644 arch/arm64/kvm/hyp/vhe/Makefile diff --git a/arch/arm64/kernel/image-vars.h b/arch/arm64/kernel/image-vars.h index be0a63ffed239..3dc27da47712c 100644 --- a/arch/arm64/kernel/image-vars.h +++ b/arch/arm64/kernel/image-vars.h @@ -51,4 +51,18 @@ __efistub__ctype = _ctype; #endif +#ifdef CONFIG_KVM + +/* + * KVM nVHE code has its own symbol namespace prefixed with __kvm_nvhe_, to + * separate it from the kernel proper. The following symbols are legally + * accessed by it, therefore provide aliases to make them linkable. + * Do not include symbols which may not be safely accessed under hypervisor + * memory mappings. + */ + +#define KVM_NVHE_ALIAS(sym) __kvm_nvhe_##sym = sym; + +#endif /* CONFIG_KVM */ + #endif /* __ARM64_KERNEL_IMAGE_VARS_H */ diff --git a/arch/arm64/kvm/hyp/Makefile b/arch/arm64/kvm/hyp/Makefile index 5d8357ddc2344..9c5dfe6ff80b7 100644 --- a/arch/arm64/kvm/hyp/Makefile +++ b/arch/arm64/kvm/hyp/Makefile @@ -3,10 +3,14 @@ # Makefile for Kernel-based Virtual Machine module, HYP part # -ccflags-y += -fno-stack-protector -DDISABLE_BRANCH_PROFILING \ - $(DISABLE_STACKLEAK_PLUGIN) +incdir := $(srctree)/$(src)/include +subdir-asflags-y := -I$(incdir) +subdir-ccflags-y := -I$(incdir) \ + -fno-stack-protector \ + -DDISABLE_BRANCH_PROFILING \ + $(DISABLE_STACKLEAK_PLUGIN) -obj-$(CONFIG_KVM) += hyp.o +obj-$(CONFIG_KVM) += hyp.o nvhe/ obj-$(CONFIG_KVM_INDIRECT_VECTORS) += smccc_wa.o hyp-y := vgic-v3-sr.o timer-sr.o aarch32.o vgic-v2-cpuif-proxy.o sysreg-sr.o \ diff --git a/arch/arm64/kvm/hyp/nvhe/Makefile b/arch/arm64/kvm/hyp/nvhe/Makefile new file mode 100644 index 0000000000000..955f4188e00ff --- /dev/null +++ b/arch/arm64/kvm/hyp/nvhe/Makefile @@ -0,0 +1,34 @@ +# SPDX-License-Identifier: GPL-2.0 +# +# Makefile for Kernel-based Virtual Machine module, HYP/nVHE part +# + +asflags-y := -D__KVM_NVHE_HYPERVISOR__ +ccflags-y := -D__KVM_NVHE_HYPERVISOR__ + +obj-y := + +obj-y := $(patsubst %.o,%.hyp.o,$(obj-y)) +extra-y := $(patsubst %.hyp.o,%.hyp.tmp.o,$(obj-y)) + +$(obj)/%.hyp.tmp.o: $(src)/%.c FORCE + $(call if_changed_rule,cc_o_c) +$(obj)/%.hyp.tmp.o: $(src)/%.S FORCE + $(call if_changed_rule,as_o_S) +$(obj)/%.hyp.o: $(obj)/%.hyp.tmp.o FORCE + $(call if_changed,hypcopy) + +quiet_cmd_hypcopy = HYPCOPY $@ + cmd_hypcopy = $(OBJCOPY) --prefix-symbols=__kvm_nvhe_ $< $@ + +# KVM nVHE code is run at a different exception code with a different map, so +# compiler instrumentation that inserts callbacks or checks into the code may +# cause crashes. Just disable it. +GCOV_PROFILE := n +KASAN_SANITIZE := n +UBSAN_SANITIZE := n +KCOV_INSTRUMENT := n + +# Skip objtool checking for this directory because nVHE code is compiled with +# non-standard build rules. +OBJECT_FILES_NON_STANDARD := y diff --git a/arch/arm64/kvm/hyp/vhe/Makefile b/arch/arm64/kvm/hyp/vhe/Makefile new file mode 100644 index 0000000000000..e043755460815 --- /dev/null +++ b/arch/arm64/kvm/hyp/vhe/Makefile @@ -0,0 +1,17 @@ +# SPDX-License-Identifier: GPL-2.0 +# +# Makefile for Kernel-based Virtual Machine module, HYP/nVHE part +# + +asflags-y := -D__KVM_VHE_HYPERVISOR__ +ccflags-y := -D__KVM_VHE_HYPERVISOR__ + +obj-y := + +# KVM code is run at a different exception code with a different map, so +# compiler instrumentation that inserts callbacks or checks into the code may +# cause crashes. Just disable it. +GCOV_PROFILE := n +KASAN_SANITIZE := n +UBSAN_SANITIZE := n +KCOV_INSTRUMENT := n diff --git a/scripts/kallsyms.c b/scripts/kallsyms.c index 6dc3078649fa0..0096cd9653327 100644 --- a/scripts/kallsyms.c +++ b/scripts/kallsyms.c @@ -109,6 +109,7 @@ static bool is_ignored_symbol(const char *name, char type) ".LASANPC", /* s390 kasan local symbols */ "__crc_", /* modversions */ "__efistub_", /* arm64 EFI stub namespace */ + "__kvm_nvhe_", /* arm64 non-VHE KVM namespace */ NULL }; -- GitLab From 53b671128bd7f9ea41ae1a06106d88eb4cf66623 Mon Sep 17 00:00:00 2001 From: David Brazdil Date: Thu, 25 Jun 2020 14:14:09 +0100 Subject: [PATCH 0162/2249] KVM: arm64: Use build-time defines in has_vhe() Build system compiles hyp code with macros specifying if the code belongs to VHE or nVHE. Use these macros to evaluate has_vhe() at compile time. Signed-off-by: David Brazdil Signed-off-by: Marc Zyngier Link: https://lore.kernel.org/r/20200625131420.71444-5-dbrazdil@google.com --- arch/arm64/include/asm/virt.h | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/arch/arm64/include/asm/virt.h b/arch/arm64/include/asm/virt.h index 5051b388c6548..09977acc007d1 100644 --- a/arch/arm64/include/asm/virt.h +++ b/arch/arm64/include/asm/virt.h @@ -85,10 +85,17 @@ static inline bool is_kernel_in_hyp_mode(void) static __always_inline bool has_vhe(void) { - if (cpus_have_final_cap(ARM64_HAS_VIRT_HOST_EXTN)) + /* + * The following macros are defined for code specic to VHE/nVHE. + * If has_vhe() is inlined into those compilation units, it can + * be determined statically. Otherwise fall back to caps. + */ + if (__is_defined(__KVM_VHE_HYPERVISOR__)) return true; - - return false; + else if (__is_defined(__KVM_NVHE_HYPERVISOR__)) + return false; + else + return cpus_have_final_cap(ARM64_HAS_VIRT_HOST_EXTN); } #endif /* __ASSEMBLY__ */ -- GitLab From f50b6f6ae131b6ee7d5dd738961eda0c00b7f027 Mon Sep 17 00:00:00 2001 From: Andrew Scull Date: Thu, 25 Jun 2020 14:14:10 +0100 Subject: [PATCH 0163/2249] KVM: arm64: Handle calls to prefixed hyp functions Once hyp functions are moved to a hyp object, they will have prefixed symbols. This change declares and gets the address of the prefixed version for calls to the hyp functions. To aid migration, the hyp functions that have not yet moved have their prefixed versions aliased to their non-prefixed version. This begins with all the hyp functions being listed and will reduce to none of them once the migration is complete. Signed-off-by: Andrew Scull [David: Extracted kvm_call_hyp nVHE branches into own helper macros, added comments around symbol aliases.] Signed-off-by: David Brazdil Signed-off-by: Marc Zyngier Link: https://lore.kernel.org/r/20200625131420.71444-6-dbrazdil@google.com --- arch/arm64/include/asm/kvm_asm.h | 19 +++++++++++++++++++ arch/arm64/include/asm/kvm_host.h | 17 ++++++++++++++--- arch/arm64/kernel/image-vars.h | 26 ++++++++++++++++++++++++++ 3 files changed, 59 insertions(+), 3 deletions(-) diff --git a/arch/arm64/include/asm/kvm_asm.h b/arch/arm64/include/asm/kvm_asm.h index 352aaebf41980..6a682d66a6404 100644 --- a/arch/arm64/include/asm/kvm_asm.h +++ b/arch/arm64/include/asm/kvm_asm.h @@ -42,6 +42,24 @@ #include +/* + * Translate name of a symbol defined in nVHE hyp to the name seen + * by kernel proper. All nVHE symbols are prefixed by the build system + * to avoid clashes with the VHE variants. + */ +#define kvm_nvhe_sym(sym) __kvm_nvhe_##sym + +#define DECLARE_KVM_VHE_SYM(sym) extern char sym[] +#define DECLARE_KVM_NVHE_SYM(sym) extern char kvm_nvhe_sym(sym)[] + +/* + * Define a pair of symbols sharing the same name but one defined in + * VHE and the other in nVHE hyp implementations. + */ +#define DECLARE_KVM_HYP_SYM(sym) \ + DECLARE_KVM_VHE_SYM(sym); \ + DECLARE_KVM_NVHE_SYM(sym) + /* Translate a kernel address of @sym into its equivalent linear mapping */ #define kvm_ksym_ref(sym) \ ({ \ @@ -50,6 +68,7 @@ val = lm_alias(&sym); \ val; \ }) +#define kvm_ksym_ref_nvhe(sym) kvm_ksym_ref(kvm_nvhe_sym(sym)) struct kvm; struct kvm_vcpu; diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h index c3e6fcc664b1b..49d1a5cd8f8f4 100644 --- a/arch/arm64/include/asm/kvm_host.h +++ b/arch/arm64/include/asm/kvm_host.h @@ -448,6 +448,18 @@ void kvm_arm_resume_guest(struct kvm *kvm); u64 __kvm_call_hyp(void *hypfn, ...); +#define kvm_call_hyp_nvhe(f, ...) \ + do { \ + DECLARE_KVM_NVHE_SYM(f); \ + __kvm_call_hyp(kvm_ksym_ref_nvhe(f), ##__VA_ARGS__); \ + } while(0) + +#define kvm_call_hyp_nvhe_ret(f, ...) \ + ({ \ + DECLARE_KVM_NVHE_SYM(f); \ + __kvm_call_hyp(kvm_ksym_ref_nvhe(f), ##__VA_ARGS__); \ + }) + /* * The couple of isb() below are there to guarantee the same behaviour * on VHE as on !VHE, where the eret to EL1 acts as a context @@ -459,7 +471,7 @@ u64 __kvm_call_hyp(void *hypfn, ...); f(__VA_ARGS__); \ isb(); \ } else { \ - __kvm_call_hyp(kvm_ksym_ref(f), ##__VA_ARGS__); \ + kvm_call_hyp_nvhe(f, ##__VA_ARGS__); \ } \ } while(0) @@ -471,8 +483,7 @@ u64 __kvm_call_hyp(void *hypfn, ...); ret = f(__VA_ARGS__); \ isb(); \ } else { \ - ret = __kvm_call_hyp(kvm_ksym_ref(f), \ - ##__VA_ARGS__); \ + ret = kvm_call_hyp_nvhe_ret(f, ##__VA_ARGS__); \ } \ \ ret; \ diff --git a/arch/arm64/kernel/image-vars.h b/arch/arm64/kernel/image-vars.h index 3dc27da47712c..36444bac6a053 100644 --- a/arch/arm64/kernel/image-vars.h +++ b/arch/arm64/kernel/image-vars.h @@ -63,6 +63,32 @@ __efistub__ctype = _ctype; #define KVM_NVHE_ALIAS(sym) __kvm_nvhe_##sym = sym; +/* Symbols defined in debug-sr.c (not yet compiled with nVHE build rules). */ +KVM_NVHE_ALIAS(__kvm_get_mdcr_el2); + +/* Symbols defined in switch.c (not yet compiled with nVHE build rules). */ +KVM_NVHE_ALIAS(__kvm_vcpu_run_nvhe); + +/* Symbols defined in sysreg-sr.c (not yet compiled with nVHE build rules). */ +KVM_NVHE_ALIAS(__kvm_enable_ssbs); + +/* Symbols defined in timer-sr.c (not yet compiled with nVHE build rules). */ +KVM_NVHE_ALIAS(__kvm_timer_set_cntvoff); + +/* Symbols defined in tlb.c (not yet compiled with nVHE build rules). */ +KVM_NVHE_ALIAS(__kvm_flush_vm_context); +KVM_NVHE_ALIAS(__kvm_tlb_flush_local_vmid); +KVM_NVHE_ALIAS(__kvm_tlb_flush_vmid); +KVM_NVHE_ALIAS(__kvm_tlb_flush_vmid_ipa); + +/* Symbols defined in vgic-v3-sr.c (not yet compiled with nVHE build rules). */ +KVM_NVHE_ALIAS(__vgic_v3_get_ich_vtr_el2); +KVM_NVHE_ALIAS(__vgic_v3_init_lrs); +KVM_NVHE_ALIAS(__vgic_v3_read_vmcr); +KVM_NVHE_ALIAS(__vgic_v3_restore_aprs); +KVM_NVHE_ALIAS(__vgic_v3_save_aprs); +KVM_NVHE_ALIAS(__vgic_v3_write_vmcr); + #endif /* CONFIG_KVM */ #endif /* __ARM64_KERNEL_IMAGE_VARS_H */ -- GitLab From b877e9849d41e7d2100d2933e0a3971d0ddec011 Mon Sep 17 00:00:00 2001 From: David Brazdil Date: Thu, 25 Jun 2020 14:14:11 +0100 Subject: [PATCH 0164/2249] KVM: arm64: Build hyp-entry.S separately for VHE/nVHE hyp-entry.S contains implementation of KVM hyp vectors. This code is mostly shared between VHE/nVHE, therefore compile it under both VHE and nVHE build rules. nVHE-specific host HVC handler is hidden behind __KVM_NVHE_HYPERVISOR__. Adjust code which selects which KVM hyp vecs to install to choose the correct VHE/nVHE symbol. Signed-off-by: David Brazdil Signed-off-by: Marc Zyngier Link: https://lore.kernel.org/r/20200625131420.71444-7-dbrazdil@google.com --- arch/arm64/include/asm/kvm_asm.h | 22 +++++++++++++++++----- arch/arm64/include/asm/mmu.h | 7 ------- arch/arm64/kernel/image-vars.h | 24 ++++++++++++++++++++++++ arch/arm64/kvm/arm.c | 2 +- arch/arm64/kvm/hyp/Makefile | 4 ++-- arch/arm64/kvm/hyp/hyp-entry.S | 2 ++ arch/arm64/kvm/hyp/nvhe/Makefile | 2 +- arch/arm64/kvm/hyp/vhe/Makefile | 2 +- 8 files changed, 48 insertions(+), 17 deletions(-) diff --git a/arch/arm64/include/asm/kvm_asm.h b/arch/arm64/include/asm/kvm_asm.h index 6a682d66a6404..6026cbd204ae9 100644 --- a/arch/arm64/include/asm/kvm_asm.h +++ b/arch/arm64/include/asm/kvm_asm.h @@ -60,12 +60,17 @@ DECLARE_KVM_VHE_SYM(sym); \ DECLARE_KVM_NVHE_SYM(sym) -/* Translate a kernel address of @sym into its equivalent linear mapping */ -#define kvm_ksym_ref(sym) \ +#define CHOOSE_VHE_SYM(sym) sym +#define CHOOSE_NVHE_SYM(sym) kvm_nvhe_sym(sym) +#define CHOOSE_HYP_SYM(sym) (has_vhe() ? CHOOSE_VHE_SYM(sym) \ + : CHOOSE_NVHE_SYM(sym)) + +/* Translate a kernel address @ptr into its equivalent linear mapping */ +#define kvm_ksym_ref(ptr) \ ({ \ - void *val = &sym; \ + void *val = (ptr); \ if (!is_kernel_in_hyp_mode()) \ - val = lm_alias(&sym); \ + val = lm_alias((ptr)); \ val; \ }) #define kvm_ksym_ref_nvhe(sym) kvm_ksym_ref(kvm_nvhe_sym(sym)) @@ -76,7 +81,14 @@ struct kvm_vcpu; extern char __kvm_hyp_init[]; extern char __kvm_hyp_init_end[]; -extern char __kvm_hyp_vector[]; +DECLARE_KVM_HYP_SYM(__kvm_hyp_vector); +#define __kvm_hyp_vector CHOOSE_HYP_SYM(__kvm_hyp_vector) + +#ifdef CONFIG_KVM_INDIRECT_VECTORS +extern atomic_t arm64_el2_vector_last_slot; +DECLARE_KVM_HYP_SYM(__bp_harden_hyp_vecs); +#define __bp_harden_hyp_vecs CHOOSE_HYP_SYM(__bp_harden_hyp_vecs) +#endif extern void __kvm_flush_vm_context(void); extern void __kvm_tlb_flush_vmid_ipa(struct kvm *kvm, phys_addr_t ipa); diff --git a/arch/arm64/include/asm/mmu.h b/arch/arm64/include/asm/mmu.h index 8444df0001813..a7a5ecaa2e836 100644 --- a/arch/arm64/include/asm/mmu.h +++ b/arch/arm64/include/asm/mmu.h @@ -45,13 +45,6 @@ struct bp_hardening_data { bp_hardening_cb_t fn; }; -#if (defined(CONFIG_HARDEN_BRANCH_PREDICTOR) || \ - defined(CONFIG_HARDEN_EL2_VECTORS)) - -extern char __bp_harden_hyp_vecs[]; -extern atomic_t arm64_el2_vector_last_slot; -#endif /* CONFIG_HARDEN_BRANCH_PREDICTOR || CONFIG_HARDEN_EL2_VECTORS */ - #ifdef CONFIG_HARDEN_BRANCH_PREDICTOR DECLARE_PER_CPU_READ_MOSTLY(struct bp_hardening_data, bp_hardening_data); diff --git a/arch/arm64/kernel/image-vars.h b/arch/arm64/kernel/image-vars.h index 36444bac6a053..f28da486b75af 100644 --- a/arch/arm64/kernel/image-vars.h +++ b/arch/arm64/kernel/image-vars.h @@ -66,8 +66,17 @@ __efistub__ctype = _ctype; /* Symbols defined in debug-sr.c (not yet compiled with nVHE build rules). */ KVM_NVHE_ALIAS(__kvm_get_mdcr_el2); +/* Symbols defined in entry.S (not yet compiled with nVHE build rules). */ +KVM_NVHE_ALIAS(__guest_exit); +KVM_NVHE_ALIAS(abort_guest_exit_end); +KVM_NVHE_ALIAS(abort_guest_exit_start); + +/* Symbols defined in hyp-init.S (not yet compiled with nVHE build rules). */ +KVM_NVHE_ALIAS(__kvm_handle_stub_hvc); + /* Symbols defined in switch.c (not yet compiled with nVHE build rules). */ KVM_NVHE_ALIAS(__kvm_vcpu_run_nvhe); +KVM_NVHE_ALIAS(hyp_panic); /* Symbols defined in sysreg-sr.c (not yet compiled with nVHE build rules). */ KVM_NVHE_ALIAS(__kvm_enable_ssbs); @@ -89,6 +98,21 @@ KVM_NVHE_ALIAS(__vgic_v3_restore_aprs); KVM_NVHE_ALIAS(__vgic_v3_save_aprs); KVM_NVHE_ALIAS(__vgic_v3_write_vmcr); +/* Alternative callbacks for init-time patching of nVHE hyp code. */ +KVM_NVHE_ALIAS(arm64_enable_wa2_handling); +KVM_NVHE_ALIAS(kvm_patch_vector_branch); +KVM_NVHE_ALIAS(kvm_update_va_mask); + +/* Global kernel state accessed by nVHE hyp code. */ +KVM_NVHE_ALIAS(arm64_ssbd_callback_required); +KVM_NVHE_ALIAS(kvm_host_data); + +/* Kernel constant needed to compute idmap addresses. */ +KVM_NVHE_ALIAS(kimage_voffset); + +/* Kernel symbols used to call panic() from nVHE hyp code (via ERET). */ +KVM_NVHE_ALIAS(panic); + #endif /* CONFIG_KVM */ #endif /* __ARM64_KERNEL_IMAGE_VARS_H */ diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c index 90cb905614468..34b5513851536 100644 --- a/arch/arm64/kvm/arm.c +++ b/arch/arm64/kvm/arm.c @@ -1285,7 +1285,7 @@ static void cpu_init_hyp_mode(void) * so that we can use adr_l to access per-cpu variables in EL2. */ tpidr_el2 = ((unsigned long)this_cpu_ptr(&kvm_host_data) - - (unsigned long)kvm_ksym_ref(kvm_host_data)); + (unsigned long)kvm_ksym_ref(&kvm_host_data)); pgd_ptr = kvm_mmu_get_httbr(); hyp_stack_ptr = __this_cpu_read(kvm_arm_hyp_stack_page) + PAGE_SIZE; diff --git a/arch/arm64/kvm/hyp/Makefile b/arch/arm64/kvm/hyp/Makefile index 9c5dfe6ff80b7..8b0cf85080b56 100644 --- a/arch/arm64/kvm/hyp/Makefile +++ b/arch/arm64/kvm/hyp/Makefile @@ -10,11 +10,11 @@ subdir-ccflags-y := -I$(incdir) \ -DDISABLE_BRANCH_PROFILING \ $(DISABLE_STACKLEAK_PLUGIN) -obj-$(CONFIG_KVM) += hyp.o nvhe/ +obj-$(CONFIG_KVM) += hyp.o vhe/ nvhe/ obj-$(CONFIG_KVM_INDIRECT_VECTORS) += smccc_wa.o hyp-y := vgic-v3-sr.o timer-sr.o aarch32.o vgic-v2-cpuif-proxy.o sysreg-sr.o \ - debug-sr.o entry.o switch.o fpsimd.o tlb.o hyp-entry.o + debug-sr.o entry.o switch.o fpsimd.o tlb.o # KVM code is run at a different exception code with a different map, so # compiler instrumentation that inserts callbacks or checks into the code may diff --git a/arch/arm64/kvm/hyp/hyp-entry.S b/arch/arm64/kvm/hyp/hyp-entry.S index d362fad97cc83..7e3c72fa634fb 100644 --- a/arch/arm64/kvm/hyp/hyp-entry.S +++ b/arch/arm64/kvm/hyp/hyp-entry.S @@ -40,6 +40,7 @@ el1_sync: // Guest trapped into EL2 ccmp x0, #ESR_ELx_EC_HVC32, #4, ne b.ne el1_trap +#ifdef __KVM_NVHE_HYPERVISOR__ mrs x1, vttbr_el2 // If vttbr is valid, the guest cbnz x1, el1_hvc_guest // called HVC @@ -74,6 +75,7 @@ el1_sync: // Guest trapped into EL2 eret sb +#endif /* __KVM_NVHE_HYPERVISOR__ */ el1_hvc_guest: /* diff --git a/arch/arm64/kvm/hyp/nvhe/Makefile b/arch/arm64/kvm/hyp/nvhe/Makefile index 955f4188e00ff..79eb8eed96a1c 100644 --- a/arch/arm64/kvm/hyp/nvhe/Makefile +++ b/arch/arm64/kvm/hyp/nvhe/Makefile @@ -6,7 +6,7 @@ asflags-y := -D__KVM_NVHE_HYPERVISOR__ ccflags-y := -D__KVM_NVHE_HYPERVISOR__ -obj-y := +obj-y := ../hyp-entry.o obj-y := $(patsubst %.o,%.hyp.o,$(obj-y)) extra-y := $(patsubst %.hyp.o,%.hyp.tmp.o,$(obj-y)) diff --git a/arch/arm64/kvm/hyp/vhe/Makefile b/arch/arm64/kvm/hyp/vhe/Makefile index e043755460815..323029e02b4e5 100644 --- a/arch/arm64/kvm/hyp/vhe/Makefile +++ b/arch/arm64/kvm/hyp/vhe/Makefile @@ -6,7 +6,7 @@ asflags-y := -D__KVM_VHE_HYPERVISOR__ ccflags-y := -D__KVM_VHE_HYPERVISOR__ -obj-y := +obj-y := ../hyp-entry.o # KVM code is run at a different exception code with a different map, so # compiler instrumentation that inserts callbacks or checks into the code may -- GitLab From 208243c752a7eeef4236f7b7d67e806ee356e3f8 Mon Sep 17 00:00:00 2001 From: Andrew Scull Date: Thu, 25 Jun 2020 14:14:12 +0100 Subject: [PATCH 0165/2249] KVM: arm64: Move hyp-init.S to nVHE hyp-init.S contains the identity mapped initialisation code for the non-VHE code that runs at EL2. It is only used for non-VHE. Adjust code that calls into this to use the prefixed symbol name. Signed-off-by: Andrew Scull Signed-off-by: David Brazdil Signed-off-by: Marc Zyngier Link: https://lore.kernel.org/r/20200625131420.71444-8-dbrazdil@google.com --- arch/arm64/include/asm/kvm_asm.h | 5 ++--- arch/arm64/kernel/image-vars.h | 9 ++++++--- arch/arm64/kvm/Makefile | 2 +- arch/arm64/kvm/hyp/nvhe/Makefile | 2 +- arch/arm64/kvm/{ => hyp/nvhe}/hyp-init.S | 0 5 files changed, 10 insertions(+), 8 deletions(-) rename arch/arm64/kvm/{ => hyp/nvhe}/hyp-init.S (100%) diff --git a/arch/arm64/include/asm/kvm_asm.h b/arch/arm64/include/asm/kvm_asm.h index 6026cbd204ae9..3476abb046e36 100644 --- a/arch/arm64/include/asm/kvm_asm.h +++ b/arch/arm64/include/asm/kvm_asm.h @@ -78,10 +78,9 @@ struct kvm; struct kvm_vcpu; -extern char __kvm_hyp_init[]; -extern char __kvm_hyp_init_end[]; - +DECLARE_KVM_NVHE_SYM(__kvm_hyp_init); DECLARE_KVM_HYP_SYM(__kvm_hyp_vector); +#define __kvm_hyp_init CHOOSE_NVHE_SYM(__kvm_hyp_init) #define __kvm_hyp_vector CHOOSE_HYP_SYM(__kvm_hyp_vector) #ifdef CONFIG_KVM_INDIRECT_VECTORS diff --git a/arch/arm64/kernel/image-vars.h b/arch/arm64/kernel/image-vars.h index f28da486b75af..63186c91b614f 100644 --- a/arch/arm64/kernel/image-vars.h +++ b/arch/arm64/kernel/image-vars.h @@ -71,9 +71,6 @@ KVM_NVHE_ALIAS(__guest_exit); KVM_NVHE_ALIAS(abort_guest_exit_end); KVM_NVHE_ALIAS(abort_guest_exit_start); -/* Symbols defined in hyp-init.S (not yet compiled with nVHE build rules). */ -KVM_NVHE_ALIAS(__kvm_handle_stub_hvc); - /* Symbols defined in switch.c (not yet compiled with nVHE build rules). */ KVM_NVHE_ALIAS(__kvm_vcpu_run_nvhe); KVM_NVHE_ALIAS(hyp_panic); @@ -113,6 +110,12 @@ KVM_NVHE_ALIAS(kimage_voffset); /* Kernel symbols used to call panic() from nVHE hyp code (via ERET). */ KVM_NVHE_ALIAS(panic); +/* Vectors installed by hyp-init on reset HVC. */ +KVM_NVHE_ALIAS(__hyp_stub_vectors); + +/* IDMAP TCR_EL1.T0SZ as computed by the EL1 init code */ +KVM_NVHE_ALIAS(idmap_t0sz); + #endif /* CONFIG_KVM */ #endif /* __ARM64_KERNEL_IMAGE_VARS_H */ diff --git a/arch/arm64/kvm/Makefile b/arch/arm64/kvm/Makefile index 8d3d9513cbfe4..152d8845a1a2a 100644 --- a/arch/arm64/kvm/Makefile +++ b/arch/arm64/kvm/Makefile @@ -13,7 +13,7 @@ obj-$(CONFIG_KVM) += hyp/ kvm-y := $(KVM)/kvm_main.o $(KVM)/coalesced_mmio.o $(KVM)/eventfd.o \ $(KVM)/vfio.o $(KVM)/irqchip.o \ arm.o mmu.o mmio.o psci.o perf.o hypercalls.o pvtime.o \ - inject_fault.o regmap.o va_layout.o hyp.o hyp-init.o handle_exit.o \ + inject_fault.o regmap.o va_layout.o hyp.o handle_exit.o \ guest.o debug.o reset.o sys_regs.o sys_regs_generic_v8.o \ vgic-sys-reg-v3.o fpsimd.o pmu.o \ aarch32.o arch_timer.o \ diff --git a/arch/arm64/kvm/hyp/nvhe/Makefile b/arch/arm64/kvm/hyp/nvhe/Makefile index 79eb8eed96a1c..bf2d8dea54003 100644 --- a/arch/arm64/kvm/hyp/nvhe/Makefile +++ b/arch/arm64/kvm/hyp/nvhe/Makefile @@ -6,7 +6,7 @@ asflags-y := -D__KVM_NVHE_HYPERVISOR__ ccflags-y := -D__KVM_NVHE_HYPERVISOR__ -obj-y := ../hyp-entry.o +obj-y := hyp-init.o ../hyp-entry.o obj-y := $(patsubst %.o,%.hyp.o,$(obj-y)) extra-y := $(patsubst %.hyp.o,%.hyp.tmp.o,$(obj-y)) diff --git a/arch/arm64/kvm/hyp-init.S b/arch/arm64/kvm/hyp/nvhe/hyp-init.S similarity index 100% rename from arch/arm64/kvm/hyp-init.S rename to arch/arm64/kvm/hyp/nvhe/hyp-init.S -- GitLab From e03fa29164ec1db1a81dc0168d0017a9e0366c7c Mon Sep 17 00:00:00 2001 From: David Brazdil Date: Thu, 25 Jun 2020 14:14:13 +0100 Subject: [PATCH 0166/2249] KVM: arm64: Duplicate hyp/tlb.c for VHE/nVHE tlb.c contains code for flushing the TLB, with code shared between VHE/nVHE. Because common code is small, duplicate tlb.c and specialize each copy for VHE/nVHE. Signed-off-by: David Brazdil Signed-off-by: Marc Zyngier Link: https://lore.kernel.org/r/20200625131420.71444-9-dbrazdil@google.com --- arch/arm64/kernel/image-vars.h | 14 +-- arch/arm64/kvm/hyp/Makefile | 2 +- arch/arm64/kvm/hyp/nvhe/Makefile | 2 +- arch/arm64/kvm/hyp/{ => nvhe}/tlb.c | 96 +---------------- arch/arm64/kvm/hyp/vhe/Makefile | 2 +- arch/arm64/kvm/hyp/vhe/tlb.c | 161 ++++++++++++++++++++++++++++ 6 files changed, 177 insertions(+), 100 deletions(-) rename arch/arm64/kvm/hyp/{ => nvhe}/tlb.c (61%) create mode 100644 arch/arm64/kvm/hyp/vhe/tlb.c diff --git a/arch/arm64/kernel/image-vars.h b/arch/arm64/kernel/image-vars.h index 63186c91b614f..f029f3ea7ffec 100644 --- a/arch/arm64/kernel/image-vars.h +++ b/arch/arm64/kernel/image-vars.h @@ -81,12 +81,6 @@ KVM_NVHE_ALIAS(__kvm_enable_ssbs); /* Symbols defined in timer-sr.c (not yet compiled with nVHE build rules). */ KVM_NVHE_ALIAS(__kvm_timer_set_cntvoff); -/* Symbols defined in tlb.c (not yet compiled with nVHE build rules). */ -KVM_NVHE_ALIAS(__kvm_flush_vm_context); -KVM_NVHE_ALIAS(__kvm_tlb_flush_local_vmid); -KVM_NVHE_ALIAS(__kvm_tlb_flush_vmid); -KVM_NVHE_ALIAS(__kvm_tlb_flush_vmid_ipa); - /* Symbols defined in vgic-v3-sr.c (not yet compiled with nVHE build rules). */ KVM_NVHE_ALIAS(__vgic_v3_get_ich_vtr_el2); KVM_NVHE_ALIAS(__vgic_v3_init_lrs); @@ -116,6 +110,14 @@ KVM_NVHE_ALIAS(__hyp_stub_vectors); /* IDMAP TCR_EL1.T0SZ as computed by the EL1 init code */ KVM_NVHE_ALIAS(idmap_t0sz); +/* Kernel symbol used by icache_is_vpipt(). */ +KVM_NVHE_ALIAS(__icache_flags); + +/* Kernel symbols needed for cpus_have_final/const_caps checks. */ +KVM_NVHE_ALIAS(arm64_const_caps_ready); +KVM_NVHE_ALIAS(cpu_hwcap_keys); +KVM_NVHE_ALIAS(cpu_hwcaps); + #endif /* CONFIG_KVM */ #endif /* __ARM64_KERNEL_IMAGE_VARS_H */ diff --git a/arch/arm64/kvm/hyp/Makefile b/arch/arm64/kvm/hyp/Makefile index 8b0cf85080b56..87d3cce2b26e6 100644 --- a/arch/arm64/kvm/hyp/Makefile +++ b/arch/arm64/kvm/hyp/Makefile @@ -14,7 +14,7 @@ obj-$(CONFIG_KVM) += hyp.o vhe/ nvhe/ obj-$(CONFIG_KVM_INDIRECT_VECTORS) += smccc_wa.o hyp-y := vgic-v3-sr.o timer-sr.o aarch32.o vgic-v2-cpuif-proxy.o sysreg-sr.o \ - debug-sr.o entry.o switch.o fpsimd.o tlb.o + debug-sr.o entry.o switch.o fpsimd.o # KVM code is run at a different exception code with a different map, so # compiler instrumentation that inserts callbacks or checks into the code may diff --git a/arch/arm64/kvm/hyp/nvhe/Makefile b/arch/arm64/kvm/hyp/nvhe/Makefile index bf2d8dea54003..a5316e97d3730 100644 --- a/arch/arm64/kvm/hyp/nvhe/Makefile +++ b/arch/arm64/kvm/hyp/nvhe/Makefile @@ -6,7 +6,7 @@ asflags-y := -D__KVM_NVHE_HYPERVISOR__ ccflags-y := -D__KVM_NVHE_HYPERVISOR__ -obj-y := hyp-init.o ../hyp-entry.o +obj-y := tlb.o hyp-init.o ../hyp-entry.o obj-y := $(patsubst %.o,%.hyp.o,$(obj-y)) extra-y := $(patsubst %.hyp.o,%.hyp.tmp.o,$(obj-y)) diff --git a/arch/arm64/kvm/hyp/tlb.c b/arch/arm64/kvm/hyp/nvhe/tlb.c similarity index 61% rename from arch/arm64/kvm/hyp/tlb.c rename to arch/arm64/kvm/hyp/nvhe/tlb.c index d063a576d511b..deb48c8c00eed 100644 --- a/arch/arm64/kvm/hyp/tlb.c +++ b/arch/arm64/kvm/hyp/nvhe/tlb.c @@ -4,64 +4,16 @@ * Author: Marc Zyngier */ -#include - #include #include #include struct tlb_inv_context { - unsigned long flags; u64 tcr; - u64 sctlr; }; -static void __hyp_text __tlb_switch_to_guest_vhe(struct kvm *kvm, - struct tlb_inv_context *cxt) -{ - u64 val; - - local_irq_save(cxt->flags); - - if (cpus_have_final_cap(ARM64_WORKAROUND_SPECULATIVE_AT)) { - /* - * For CPUs that are affected by ARM errata 1165522 or 1530923, - * we cannot trust stage-1 to be in a correct state at that - * point. Since we do not want to force a full load of the - * vcpu state, we prevent the EL1 page-table walker to - * allocate new TLBs. This is done by setting the EPD bits - * in the TCR_EL1 register. We also need to prevent it to - * allocate IPA->PA walks, so we enable the S1 MMU... - */ - val = cxt->tcr = read_sysreg_el1(SYS_TCR); - val |= TCR_EPD1_MASK | TCR_EPD0_MASK; - write_sysreg_el1(val, SYS_TCR); - val = cxt->sctlr = read_sysreg_el1(SYS_SCTLR); - val |= SCTLR_ELx_M; - write_sysreg_el1(val, SYS_SCTLR); - } - - /* - * With VHE enabled, we have HCR_EL2.{E2H,TGE} = {1,1}, and - * most TLB operations target EL2/EL0. In order to affect the - * guest TLBs (EL1/EL0), we need to change one of these two - * bits. Changing E2H is impossible (goodbye TTBR1_EL2), so - * let's flip TGE before executing the TLB operation. - * - * ARM erratum 1165522 requires some special handling (again), - * as we need to make sure both stages of translation are in - * place before clearing TGE. __load_guest_stage2() already - * has an ISB in order to deal with this. - */ - __load_guest_stage2(kvm); - val = read_sysreg(hcr_el2); - val &= ~HCR_TGE; - write_sysreg(val, hcr_el2); - isb(); -} - -static void __hyp_text __tlb_switch_to_guest_nvhe(struct kvm *kvm, - struct tlb_inv_context *cxt) +static void __hyp_text __tlb_switch_to_guest(struct kvm *kvm, + struct tlb_inv_context *cxt) { if (cpus_have_final_cap(ARM64_WORKAROUND_SPECULATIVE_AT)) { u64 val; @@ -84,37 +36,8 @@ static void __hyp_text __tlb_switch_to_guest_nvhe(struct kvm *kvm, asm(ALTERNATIVE("isb", "nop", ARM64_WORKAROUND_SPECULATIVE_AT)); } -static void __hyp_text __tlb_switch_to_guest(struct kvm *kvm, - struct tlb_inv_context *cxt) -{ - if (has_vhe()) - __tlb_switch_to_guest_vhe(kvm, cxt); - else - __tlb_switch_to_guest_nvhe(kvm, cxt); -} - -static void __hyp_text __tlb_switch_to_host_vhe(struct kvm *kvm, - struct tlb_inv_context *cxt) -{ - /* - * We're done with the TLB operation, let's restore the host's - * view of HCR_EL2. - */ - write_sysreg(0, vttbr_el2); - write_sysreg(HCR_HOST_VHE_FLAGS, hcr_el2); - isb(); - - if (cpus_have_final_cap(ARM64_WORKAROUND_SPECULATIVE_AT)) { - /* Restore the registers to what they were */ - write_sysreg_el1(cxt->tcr, SYS_TCR); - write_sysreg_el1(cxt->sctlr, SYS_SCTLR); - } - - local_irq_restore(cxt->flags); -} - -static void __hyp_text __tlb_switch_to_host_nvhe(struct kvm *kvm, - struct tlb_inv_context *cxt) +static void __hyp_text __tlb_switch_to_host(struct kvm *kvm, + struct tlb_inv_context *cxt) { write_sysreg(0, vttbr_el2); @@ -126,15 +49,6 @@ static void __hyp_text __tlb_switch_to_host_nvhe(struct kvm *kvm, } } -static void __hyp_text __tlb_switch_to_host(struct kvm *kvm, - struct tlb_inv_context *cxt) -{ - if (has_vhe()) - __tlb_switch_to_host_vhe(kvm, cxt); - else - __tlb_switch_to_host_nvhe(kvm, cxt); -} - void __hyp_text __kvm_tlb_flush_vmid_ipa(struct kvm *kvm, phys_addr_t ipa) { struct tlb_inv_context cxt; @@ -183,7 +97,7 @@ void __hyp_text __kvm_tlb_flush_vmid_ipa(struct kvm *kvm, phys_addr_t ipa) * The moral of this story is: if you have a VPIPT I-cache, then * you should be running with VHE enabled. */ - if (!has_vhe() && icache_is_vpipt()) + if (icache_is_vpipt()) __flush_icache_all(); __tlb_switch_to_host(kvm, &cxt); diff --git a/arch/arm64/kvm/hyp/vhe/Makefile b/arch/arm64/kvm/hyp/vhe/Makefile index 323029e02b4e5..704140fc5d66b 100644 --- a/arch/arm64/kvm/hyp/vhe/Makefile +++ b/arch/arm64/kvm/hyp/vhe/Makefile @@ -6,7 +6,7 @@ asflags-y := -D__KVM_VHE_HYPERVISOR__ ccflags-y := -D__KVM_VHE_HYPERVISOR__ -obj-y := ../hyp-entry.o +obj-y := tlb.o ../hyp-entry.o # KVM code is run at a different exception code with a different map, so # compiler instrumentation that inserts callbacks or checks into the code may diff --git a/arch/arm64/kvm/hyp/vhe/tlb.c b/arch/arm64/kvm/hyp/vhe/tlb.c new file mode 100644 index 0000000000000..b275101e9c9cf --- /dev/null +++ b/arch/arm64/kvm/hyp/vhe/tlb.c @@ -0,0 +1,161 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2015 - ARM Ltd + * Author: Marc Zyngier + */ + +#include + +#include +#include +#include + +struct tlb_inv_context { + unsigned long flags; + u64 tcr; + u64 sctlr; +}; + +static void __tlb_switch_to_guest(struct kvm *kvm, struct tlb_inv_context *cxt) +{ + u64 val; + + local_irq_save(cxt->flags); + + if (cpus_have_final_cap(ARM64_WORKAROUND_SPECULATIVE_AT)) { + /* + * For CPUs that are affected by ARM errata 1165522 or 1530923, + * we cannot trust stage-1 to be in a correct state at that + * point. Since we do not want to force a full load of the + * vcpu state, we prevent the EL1 page-table walker to + * allocate new TLBs. This is done by setting the EPD bits + * in the TCR_EL1 register. We also need to prevent it to + * allocate IPA->PA walks, so we enable the S1 MMU... + */ + val = cxt->tcr = read_sysreg_el1(SYS_TCR); + val |= TCR_EPD1_MASK | TCR_EPD0_MASK; + write_sysreg_el1(val, SYS_TCR); + val = cxt->sctlr = read_sysreg_el1(SYS_SCTLR); + val |= SCTLR_ELx_M; + write_sysreg_el1(val, SYS_SCTLR); + } + + /* + * With VHE enabled, we have HCR_EL2.{E2H,TGE} = {1,1}, and + * most TLB operations target EL2/EL0. In order to affect the + * guest TLBs (EL1/EL0), we need to change one of these two + * bits. Changing E2H is impossible (goodbye TTBR1_EL2), so + * let's flip TGE before executing the TLB operation. + * + * ARM erratum 1165522 requires some special handling (again), + * as we need to make sure both stages of translation are in + * place before clearing TGE. __load_guest_stage2() already + * has an ISB in order to deal with this. + */ + __load_guest_stage2(kvm); + val = read_sysreg(hcr_el2); + val &= ~HCR_TGE; + write_sysreg(val, hcr_el2); + isb(); +} + +static void __tlb_switch_to_host(struct kvm *kvm, struct tlb_inv_context *cxt) +{ + /* + * We're done with the TLB operation, let's restore the host's + * view of HCR_EL2. + */ + write_sysreg(0, vttbr_el2); + write_sysreg(HCR_HOST_VHE_FLAGS, hcr_el2); + isb(); + + if (cpus_have_final_cap(ARM64_WORKAROUND_SPECULATIVE_AT)) { + /* Restore the registers to what they were */ + write_sysreg_el1(cxt->tcr, SYS_TCR); + write_sysreg_el1(cxt->sctlr, SYS_SCTLR); + } + + local_irq_restore(cxt->flags); +} + +void __kvm_tlb_flush_vmid_ipa(struct kvm *kvm, phys_addr_t ipa) +{ + struct tlb_inv_context cxt; + + dsb(ishst); + + /* Switch to requested VMID */ + __tlb_switch_to_guest(kvm, &cxt); + + /* + * We could do so much better if we had the VA as well. + * Instead, we invalidate Stage-2 for this IPA, and the + * whole of Stage-1. Weep... + */ + ipa >>= 12; + __tlbi(ipas2e1is, ipa); + + /* + * We have to ensure completion of the invalidation at Stage-2, + * since a table walk on another CPU could refill a TLB with a + * complete (S1 + S2) walk based on the old Stage-2 mapping if + * the Stage-1 invalidation happened first. + */ + dsb(ish); + __tlbi(vmalle1is); + dsb(ish); + isb(); + + __tlb_switch_to_host(kvm, &cxt); +} + +void __kvm_tlb_flush_vmid(struct kvm *kvm) +{ + struct tlb_inv_context cxt; + + dsb(ishst); + + /* Switch to requested VMID */ + __tlb_switch_to_guest(kvm, &cxt); + + __tlbi(vmalls12e1is); + dsb(ish); + isb(); + + __tlb_switch_to_host(kvm, &cxt); +} + +void __kvm_tlb_flush_local_vmid(struct kvm_vcpu *vcpu) +{ + struct kvm *kvm = vcpu->kvm; + struct tlb_inv_context cxt; + + /* Switch to requested VMID */ + __tlb_switch_to_guest(kvm, &cxt); + + __tlbi(vmalle1); + dsb(nsh); + isb(); + + __tlb_switch_to_host(kvm, &cxt); +} + +void __kvm_flush_vm_context(void) +{ + dsb(ishst); + __tlbi(alle1is); + + /* + * VIPT and PIPT caches are not affected by VMID, so no maintenance + * is necessary across a VMID rollover. + * + * VPIPT caches constrain lookup and maintenance to the active VMID, + * so we need to invalidate lines with a stale VMID to avoid an ABA + * race after multiple rollovers. + * + */ + if (icache_is_vpipt()) + asm volatile("ic ialluis"); + + dsb(ish); +} -- GitLab From 09cf57eba304246141367b95c89801fd2047ac96 Mon Sep 17 00:00:00 2001 From: David Brazdil Date: Thu, 25 Jun 2020 14:14:14 +0100 Subject: [PATCH 0167/2249] KVM: arm64: Split hyp/switch.c to VHE/nVHE switch.c implements context-switching for KVM, with large parts shared between VHE/nVHE. These common routines are moved to a header file, VHE-specific code is moved to vhe/switch.c and nVHE-specific code is moved to nvhe/switch.c. Previously __kvm_vcpu_run needed a different symbol name for VHE/nVHE. This is cleaned up and the caller in arm.c simplified. Signed-off-by: David Brazdil Signed-off-by: Marc Zyngier Link: https://lore.kernel.org/r/20200625131420.71444-10-dbrazdil@google.com --- arch/arm64/include/asm/kvm_asm.h | 4 +- arch/arm64/include/asm/kvm_hyp.h | 6 + arch/arm64/kernel/image-vars.h | 37 +- arch/arm64/kvm/arm.c | 6 +- arch/arm64/kvm/hyp/Makefile | 2 +- arch/arm64/kvm/hyp/hyp-entry.S | 2 + arch/arm64/kvm/hyp/include/hyp/switch.h | 509 +++++++++++++ arch/arm64/kvm/hyp/nvhe/Makefile | 2 +- arch/arm64/kvm/hyp/nvhe/switch.c | 271 +++++++ arch/arm64/kvm/hyp/switch.c | 936 ------------------------ arch/arm64/kvm/hyp/sysreg-sr.c | 4 +- arch/arm64/kvm/hyp/vhe/Makefile | 2 +- arch/arm64/kvm/hyp/vhe/switch.c | 219 ++++++ 13 files changed, 1048 insertions(+), 952 deletions(-) create mode 100644 arch/arm64/kvm/hyp/include/hyp/switch.h create mode 100644 arch/arm64/kvm/hyp/nvhe/switch.c delete mode 100644 arch/arm64/kvm/hyp/switch.c create mode 100644 arch/arm64/kvm/hyp/vhe/switch.c diff --git a/arch/arm64/include/asm/kvm_asm.h b/arch/arm64/include/asm/kvm_asm.h index 3476abb046e36..5a91aaae78d2f 100644 --- a/arch/arm64/include/asm/kvm_asm.h +++ b/arch/arm64/include/asm/kvm_asm.h @@ -96,9 +96,7 @@ extern void __kvm_tlb_flush_local_vmid(struct kvm_vcpu *vcpu); extern void __kvm_timer_set_cntvoff(u64 cntvoff); -extern int kvm_vcpu_run_vhe(struct kvm_vcpu *vcpu); - -extern int __kvm_vcpu_run_nvhe(struct kvm_vcpu *vcpu); +extern int __kvm_vcpu_run(struct kvm_vcpu *vcpu); extern void __kvm_enable_ssbs(void); diff --git a/arch/arm64/include/asm/kvm_hyp.h b/arch/arm64/include/asm/kvm_hyp.h index ce3080834bfaa..82fa05d15b8bd 100644 --- a/arch/arm64/include/asm/kvm_hyp.h +++ b/arch/arm64/include/asm/kvm_hyp.h @@ -81,11 +81,17 @@ void __debug_switch_to_host(struct kvm_vcpu *vcpu); void __fpsimd_save_state(struct user_fpsimd_state *fp_regs); void __fpsimd_restore_state(struct user_fpsimd_state *fp_regs); +#ifndef __KVM_NVHE_HYPERVISOR__ void activate_traps_vhe_load(struct kvm_vcpu *vcpu); void deactivate_traps_vhe_put(void); +#endif u64 __guest_enter(struct kvm_vcpu *vcpu, struct kvm_cpu_context *host_ctxt); + +void __noreturn hyp_panic(struct kvm_cpu_context *host_ctxt); +#ifdef __KVM_NVHE_HYPERVISOR__ void __noreturn __hyp_do_panic(unsigned long, ...); +#endif #endif /* __ARM64_KVM_HYP_H__ */ diff --git a/arch/arm64/kernel/image-vars.h b/arch/arm64/kernel/image-vars.h index f029f3ea7ffec..06fe9833104ae 100644 --- a/arch/arm64/kernel/image-vars.h +++ b/arch/arm64/kernel/image-vars.h @@ -63,30 +63,50 @@ __efistub__ctype = _ctype; #define KVM_NVHE_ALIAS(sym) __kvm_nvhe_##sym = sym; +/* Symbols defined in aarch32.c (not yet compiled with nVHE build rules). */ +KVM_NVHE_ALIAS(kvm_skip_instr32); + /* Symbols defined in debug-sr.c (not yet compiled with nVHE build rules). */ +KVM_NVHE_ALIAS(__debug_switch_to_guest); +KVM_NVHE_ALIAS(__debug_switch_to_host); KVM_NVHE_ALIAS(__kvm_get_mdcr_el2); /* Symbols defined in entry.S (not yet compiled with nVHE build rules). */ +KVM_NVHE_ALIAS(__guest_enter); KVM_NVHE_ALIAS(__guest_exit); KVM_NVHE_ALIAS(abort_guest_exit_end); KVM_NVHE_ALIAS(abort_guest_exit_start); -/* Symbols defined in switch.c (not yet compiled with nVHE build rules). */ -KVM_NVHE_ALIAS(__kvm_vcpu_run_nvhe); -KVM_NVHE_ALIAS(hyp_panic); +/* Symbols defined in fpsimd.S (not yet compiled with nVHE build rules). */ +KVM_NVHE_ALIAS(__fpsimd_restore_state); +KVM_NVHE_ALIAS(__fpsimd_save_state); /* Symbols defined in sysreg-sr.c (not yet compiled with nVHE build rules). */ KVM_NVHE_ALIAS(__kvm_enable_ssbs); +KVM_NVHE_ALIAS(__sysreg32_restore_state); +KVM_NVHE_ALIAS(__sysreg32_save_state); +KVM_NVHE_ALIAS(__sysreg_restore_state_nvhe); +KVM_NVHE_ALIAS(__sysreg_save_state_nvhe); /* Symbols defined in timer-sr.c (not yet compiled with nVHE build rules). */ KVM_NVHE_ALIAS(__kvm_timer_set_cntvoff); +KVM_NVHE_ALIAS(__timer_disable_traps); +KVM_NVHE_ALIAS(__timer_enable_traps); + +/* Symbols defined in vgic-v2-cpuif-proxy.c (not yet compiled with nVHE build rules). */ +KVM_NVHE_ALIAS(__vgic_v2_perform_cpuif_access); /* Symbols defined in vgic-v3-sr.c (not yet compiled with nVHE build rules). */ +KVM_NVHE_ALIAS(__vgic_v3_activate_traps); +KVM_NVHE_ALIAS(__vgic_v3_deactivate_traps); KVM_NVHE_ALIAS(__vgic_v3_get_ich_vtr_el2); KVM_NVHE_ALIAS(__vgic_v3_init_lrs); +KVM_NVHE_ALIAS(__vgic_v3_perform_cpuif_access); KVM_NVHE_ALIAS(__vgic_v3_read_vmcr); KVM_NVHE_ALIAS(__vgic_v3_restore_aprs); +KVM_NVHE_ALIAS(__vgic_v3_restore_state); KVM_NVHE_ALIAS(__vgic_v3_save_aprs); +KVM_NVHE_ALIAS(__vgic_v3_save_state); KVM_NVHE_ALIAS(__vgic_v3_write_vmcr); /* Alternative callbacks for init-time patching of nVHE hyp code. */ @@ -97,11 +117,13 @@ KVM_NVHE_ALIAS(kvm_update_va_mask); /* Global kernel state accessed by nVHE hyp code. */ KVM_NVHE_ALIAS(arm64_ssbd_callback_required); KVM_NVHE_ALIAS(kvm_host_data); +KVM_NVHE_ALIAS(kvm_vgic_global_state); /* Kernel constant needed to compute idmap addresses. */ KVM_NVHE_ALIAS(kimage_voffset); /* Kernel symbols used to call panic() from nVHE hyp code (via ERET). */ +KVM_NVHE_ALIAS(__hyp_panic_string); KVM_NVHE_ALIAS(panic); /* Vectors installed by hyp-init on reset HVC. */ @@ -118,6 +140,15 @@ KVM_NVHE_ALIAS(arm64_const_caps_ready); KVM_NVHE_ALIAS(cpu_hwcap_keys); KVM_NVHE_ALIAS(cpu_hwcaps); +/* Static keys which are set if a vGIC trap should be handled in hyp. */ +KVM_NVHE_ALIAS(vgic_v2_cpuif_trap); +KVM_NVHE_ALIAS(vgic_v3_cpuif_trap); + +/* Static key checked in pmr_sync(). */ +#ifdef CONFIG_ARM64_PSEUDO_NMI +KVM_NVHE_ALIAS(gic_pmr_sync); +#endif + #endif /* CONFIG_KVM */ #endif /* __ARM64_KERNEL_IMAGE_VARS_H */ diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c index 34b5513851536..26780b78a523f 100644 --- a/arch/arm64/kvm/arm.c +++ b/arch/arm64/kvm/arm.c @@ -748,11 +748,7 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu) trace_kvm_entry(*vcpu_pc(vcpu)); guest_enter_irqoff(); - if (has_vhe()) { - ret = kvm_vcpu_run_vhe(vcpu); - } else { - ret = kvm_call_hyp_ret(__kvm_vcpu_run_nvhe, vcpu); - } + ret = kvm_call_hyp_ret(__kvm_vcpu_run, vcpu); vcpu->mode = OUTSIDE_GUEST_MODE; vcpu->stat.exits++; diff --git a/arch/arm64/kvm/hyp/Makefile b/arch/arm64/kvm/hyp/Makefile index 87d3cce2b26e6..7462d3a8a6f26 100644 --- a/arch/arm64/kvm/hyp/Makefile +++ b/arch/arm64/kvm/hyp/Makefile @@ -14,7 +14,7 @@ obj-$(CONFIG_KVM) += hyp.o vhe/ nvhe/ obj-$(CONFIG_KVM_INDIRECT_VECTORS) += smccc_wa.o hyp-y := vgic-v3-sr.o timer-sr.o aarch32.o vgic-v2-cpuif-proxy.o sysreg-sr.o \ - debug-sr.o entry.o switch.o fpsimd.o + debug-sr.o entry.o fpsimd.o # KVM code is run at a different exception code with a different map, so # compiler instrumentation that inserts callbacks or checks into the code may diff --git a/arch/arm64/kvm/hyp/hyp-entry.S b/arch/arm64/kvm/hyp/hyp-entry.S index 7e3c72fa634fb..8316ee67d6a0c 100644 --- a/arch/arm64/kvm/hyp/hyp-entry.S +++ b/arch/arm64/kvm/hyp/hyp-entry.S @@ -182,6 +182,7 @@ el2_error: eret sb +#ifdef __KVM_NVHE_HYPERVISOR__ SYM_FUNC_START(__hyp_do_panic) mov lr, #(PSR_F_BIT | PSR_I_BIT | PSR_A_BIT | PSR_D_BIT |\ PSR_MODE_EL1h) @@ -191,6 +192,7 @@ SYM_FUNC_START(__hyp_do_panic) eret sb SYM_FUNC_END(__hyp_do_panic) +#endif SYM_CODE_START(__hyp_panic) get_host_ctxt x0, x1 diff --git a/arch/arm64/kvm/hyp/include/hyp/switch.h b/arch/arm64/kvm/hyp/include/hyp/switch.h new file mode 100644 index 0000000000000..65d2a879b93b4 --- /dev/null +++ b/arch/arm64/kvm/hyp/include/hyp/switch.h @@ -0,0 +1,509 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2015 - ARM Ltd + * Author: Marc Zyngier + */ + +#ifndef __ARM64_KVM_HYP_SWITCH_H__ +#define __ARM64_KVM_HYP_SWITCH_H__ + +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern const char __hyp_panic_string[]; + +/* Check whether the FP regs were dirtied while in the host-side run loop: */ +static inline bool __hyp_text update_fp_enabled(struct kvm_vcpu *vcpu) +{ + /* + * When the system doesn't support FP/SIMD, we cannot rely on + * the _TIF_FOREIGN_FPSTATE flag. However, we always inject an + * abort on the very first access to FP and thus we should never + * see KVM_ARM64_FP_ENABLED. For added safety, make sure we always + * trap the accesses. + */ + if (!system_supports_fpsimd() || + vcpu->arch.host_thread_info->flags & _TIF_FOREIGN_FPSTATE) + vcpu->arch.flags &= ~(KVM_ARM64_FP_ENABLED | + KVM_ARM64_FP_HOST); + + return !!(vcpu->arch.flags & KVM_ARM64_FP_ENABLED); +} + +/* Save the 32-bit only FPSIMD system register state */ +static inline void __hyp_text __fpsimd_save_fpexc32(struct kvm_vcpu *vcpu) +{ + if (!vcpu_el1_is_32bit(vcpu)) + return; + + vcpu->arch.ctxt.sys_regs[FPEXC32_EL2] = read_sysreg(fpexc32_el2); +} + +static inline void __hyp_text __activate_traps_fpsimd32(struct kvm_vcpu *vcpu) +{ + /* + * We are about to set CPTR_EL2.TFP to trap all floating point + * register accesses to EL2, however, the ARM ARM clearly states that + * traps are only taken to EL2 if the operation would not otherwise + * trap to EL1. Therefore, always make sure that for 32-bit guests, + * we set FPEXC.EN to prevent traps to EL1, when setting the TFP bit. + * If FP/ASIMD is not implemented, FPEXC is UNDEFINED and any access to + * it will cause an exception. + */ + if (vcpu_el1_is_32bit(vcpu) && system_supports_fpsimd()) { + write_sysreg(1 << 30, fpexc32_el2); + isb(); + } +} + +static inline void __hyp_text __activate_traps_common(struct kvm_vcpu *vcpu) +{ + /* Trap on AArch32 cp15 c15 (impdef sysregs) accesses (EL1 or EL0) */ + write_sysreg(1 << 15, hstr_el2); + + /* + * Make sure we trap PMU access from EL0 to EL2. Also sanitize + * PMSELR_EL0 to make sure it never contains the cycle + * counter, which could make a PMXEVCNTR_EL0 access UNDEF at + * EL1 instead of being trapped to EL2. + */ + write_sysreg(0, pmselr_el0); + write_sysreg(ARMV8_PMU_USERENR_MASK, pmuserenr_el0); + write_sysreg(vcpu->arch.mdcr_el2, mdcr_el2); +} + +static inline void __hyp_text __deactivate_traps_common(void) +{ + write_sysreg(0, hstr_el2); + write_sysreg(0, pmuserenr_el0); +} + +static inline void __hyp_text ___activate_traps(struct kvm_vcpu *vcpu) +{ + u64 hcr = vcpu->arch.hcr_el2; + + if (cpus_have_final_cap(ARM64_WORKAROUND_CAVIUM_TX2_219_TVM)) + hcr |= HCR_TVM; + + write_sysreg(hcr, hcr_el2); + + if (cpus_have_final_cap(ARM64_HAS_RAS_EXTN) && (hcr & HCR_VSE)) + write_sysreg_s(vcpu->arch.vsesr_el2, SYS_VSESR_EL2); +} + +static inline void __hyp_text ___deactivate_traps(struct kvm_vcpu *vcpu) +{ + /* + * If we pended a virtual abort, preserve it until it gets + * cleared. See D1.14.3 (Virtual Interrupts) for details, but + * the crucial bit is "On taking a vSError interrupt, + * HCR_EL2.VSE is cleared to 0." + */ + if (vcpu->arch.hcr_el2 & HCR_VSE) { + vcpu->arch.hcr_el2 &= ~HCR_VSE; + vcpu->arch.hcr_el2 |= read_sysreg(hcr_el2) & HCR_VSE; + } +} + +static inline void __hyp_text __activate_vm(struct kvm *kvm) +{ + __load_guest_stage2(kvm); +} + +static inline bool __hyp_text __translate_far_to_hpfar(u64 far, u64 *hpfar) +{ + u64 par, tmp; + + /* + * Resolve the IPA the hard way using the guest VA. + * + * Stage-1 translation already validated the memory access + * rights. As such, we can use the EL1 translation regime, and + * don't have to distinguish between EL0 and EL1 access. + * + * We do need to save/restore PAR_EL1 though, as we haven't + * saved the guest context yet, and we may return early... + */ + par = read_sysreg(par_el1); + asm volatile("at s1e1r, %0" : : "r" (far)); + isb(); + + tmp = read_sysreg(par_el1); + write_sysreg(par, par_el1); + + if (unlikely(tmp & SYS_PAR_EL1_F)) + return false; /* Translation failed, back to guest */ + + /* Convert PAR to HPFAR format */ + *hpfar = PAR_TO_HPFAR(tmp); + return true; +} + +static inline bool __hyp_text __populate_fault_info(struct kvm_vcpu *vcpu) +{ + u8 ec; + u64 esr; + u64 hpfar, far; + + esr = vcpu->arch.fault.esr_el2; + ec = ESR_ELx_EC(esr); + + if (ec != ESR_ELx_EC_DABT_LOW && ec != ESR_ELx_EC_IABT_LOW) + return true; + + far = read_sysreg_el2(SYS_FAR); + + /* + * The HPFAR can be invalid if the stage 2 fault did not + * happen during a stage 1 page table walk (the ESR_EL2.S1PTW + * bit is clear) and one of the two following cases are true: + * 1. The fault was due to a permission fault + * 2. The processor carries errata 834220 + * + * Therefore, for all non S1PTW faults where we either have a + * permission fault or the errata workaround is enabled, we + * resolve the IPA using the AT instruction. + */ + if (!(esr & ESR_ELx_S1PTW) && + (cpus_have_final_cap(ARM64_WORKAROUND_834220) || + (esr & ESR_ELx_FSC_TYPE) == FSC_PERM)) { + if (!__translate_far_to_hpfar(far, &hpfar)) + return false; + } else { + hpfar = read_sysreg(hpfar_el2); + } + + vcpu->arch.fault.far_el2 = far; + vcpu->arch.fault.hpfar_el2 = hpfar; + return true; +} + +/* Check for an FPSIMD/SVE trap and handle as appropriate */ +static inline bool __hyp_text __hyp_handle_fpsimd(struct kvm_vcpu *vcpu) +{ + bool vhe, sve_guest, sve_host; + u8 hsr_ec; + + if (!system_supports_fpsimd()) + return false; + + /* + * Currently system_supports_sve() currently implies has_vhe(), + * so the check is redundant. However, has_vhe() can be determined + * statically and helps the compiler remove dead code. + */ + if (has_vhe() && system_supports_sve()) { + sve_guest = vcpu_has_sve(vcpu); + sve_host = vcpu->arch.flags & KVM_ARM64_HOST_SVE_IN_USE; + vhe = true; + } else { + sve_guest = false; + sve_host = false; + vhe = has_vhe(); + } + + hsr_ec = kvm_vcpu_trap_get_class(vcpu); + if (hsr_ec != ESR_ELx_EC_FP_ASIMD && + hsr_ec != ESR_ELx_EC_SVE) + return false; + + /* Don't handle SVE traps for non-SVE vcpus here: */ + if (!sve_guest) + if (hsr_ec != ESR_ELx_EC_FP_ASIMD) + return false; + + /* Valid trap. Switch the context: */ + + if (vhe) { + u64 reg = read_sysreg(cpacr_el1) | CPACR_EL1_FPEN; + + if (sve_guest) + reg |= CPACR_EL1_ZEN; + + write_sysreg(reg, cpacr_el1); + } else { + write_sysreg(read_sysreg(cptr_el2) & ~(u64)CPTR_EL2_TFP, + cptr_el2); + } + + isb(); + + if (vcpu->arch.flags & KVM_ARM64_FP_HOST) { + /* + * In the SVE case, VHE is assumed: it is enforced by + * Kconfig and kvm_arch_init(). + */ + if (sve_host) { + struct thread_struct *thread = container_of( + vcpu->arch.host_fpsimd_state, + struct thread_struct, uw.fpsimd_state); + + sve_save_state(sve_pffr(thread), + &vcpu->arch.host_fpsimd_state->fpsr); + } else { + __fpsimd_save_state(vcpu->arch.host_fpsimd_state); + } + + vcpu->arch.flags &= ~KVM_ARM64_FP_HOST; + } + + if (sve_guest) { + sve_load_state(vcpu_sve_pffr(vcpu), + &vcpu->arch.ctxt.gp_regs.fp_regs.fpsr, + sve_vq_from_vl(vcpu->arch.sve_max_vl) - 1); + write_sysreg_s(vcpu->arch.ctxt.sys_regs[ZCR_EL1], SYS_ZCR_EL12); + } else { + __fpsimd_restore_state(&vcpu->arch.ctxt.gp_regs.fp_regs); + } + + /* Skip restoring fpexc32 for AArch64 guests */ + if (!(read_sysreg(hcr_el2) & HCR_RW)) + write_sysreg(vcpu->arch.ctxt.sys_regs[FPEXC32_EL2], + fpexc32_el2); + + vcpu->arch.flags |= KVM_ARM64_FP_ENABLED; + + return true; +} + +static inline bool __hyp_text handle_tx2_tvm(struct kvm_vcpu *vcpu) +{ + u32 sysreg = esr_sys64_to_sysreg(kvm_vcpu_get_hsr(vcpu)); + int rt = kvm_vcpu_sys_get_rt(vcpu); + u64 val = vcpu_get_reg(vcpu, rt); + + /* + * The normal sysreg handling code expects to see the traps, + * let's not do anything here. + */ + if (vcpu->arch.hcr_el2 & HCR_TVM) + return false; + + switch (sysreg) { + case SYS_SCTLR_EL1: + write_sysreg_el1(val, SYS_SCTLR); + break; + case SYS_TTBR0_EL1: + write_sysreg_el1(val, SYS_TTBR0); + break; + case SYS_TTBR1_EL1: + write_sysreg_el1(val, SYS_TTBR1); + break; + case SYS_TCR_EL1: + write_sysreg_el1(val, SYS_TCR); + break; + case SYS_ESR_EL1: + write_sysreg_el1(val, SYS_ESR); + break; + case SYS_FAR_EL1: + write_sysreg_el1(val, SYS_FAR); + break; + case SYS_AFSR0_EL1: + write_sysreg_el1(val, SYS_AFSR0); + break; + case SYS_AFSR1_EL1: + write_sysreg_el1(val, SYS_AFSR1); + break; + case SYS_MAIR_EL1: + write_sysreg_el1(val, SYS_MAIR); + break; + case SYS_AMAIR_EL1: + write_sysreg_el1(val, SYS_AMAIR); + break; + case SYS_CONTEXTIDR_EL1: + write_sysreg_el1(val, SYS_CONTEXTIDR); + break; + default: + return false; + } + + __kvm_skip_instr(vcpu); + return true; +} + +static inline bool __hyp_text esr_is_ptrauth_trap(u32 esr) +{ + u32 ec = ESR_ELx_EC(esr); + + if (ec == ESR_ELx_EC_PAC) + return true; + + if (ec != ESR_ELx_EC_SYS64) + return false; + + switch (esr_sys64_to_sysreg(esr)) { + case SYS_APIAKEYLO_EL1: + case SYS_APIAKEYHI_EL1: + case SYS_APIBKEYLO_EL1: + case SYS_APIBKEYHI_EL1: + case SYS_APDAKEYLO_EL1: + case SYS_APDAKEYHI_EL1: + case SYS_APDBKEYLO_EL1: + case SYS_APDBKEYHI_EL1: + case SYS_APGAKEYLO_EL1: + case SYS_APGAKEYHI_EL1: + return true; + } + + return false; +} + +#define __ptrauth_save_key(regs, key) \ +({ \ + regs[key ## KEYLO_EL1] = read_sysreg_s(SYS_ ## key ## KEYLO_EL1); \ + regs[key ## KEYHI_EL1] = read_sysreg_s(SYS_ ## key ## KEYHI_EL1); \ +}) + +static inline bool __hyp_text __hyp_handle_ptrauth(struct kvm_vcpu *vcpu) +{ + struct kvm_cpu_context *ctxt; + u64 val; + + if (!vcpu_has_ptrauth(vcpu) || + !esr_is_ptrauth_trap(kvm_vcpu_get_hsr(vcpu))) + return false; + + ctxt = &__hyp_this_cpu_ptr(kvm_host_data)->host_ctxt; + __ptrauth_save_key(ctxt->sys_regs, APIA); + __ptrauth_save_key(ctxt->sys_regs, APIB); + __ptrauth_save_key(ctxt->sys_regs, APDA); + __ptrauth_save_key(ctxt->sys_regs, APDB); + __ptrauth_save_key(ctxt->sys_regs, APGA); + + vcpu_ptrauth_enable(vcpu); + + val = read_sysreg(hcr_el2); + val |= (HCR_API | HCR_APK); + write_sysreg(val, hcr_el2); + + return true; +} + +/* + * Return true when we were able to fixup the guest exit and should return to + * the guest, false when we should restore the host state and return to the + * main run loop. + */ +static inline bool __hyp_text fixup_guest_exit(struct kvm_vcpu *vcpu, u64 *exit_code) +{ + if (ARM_EXCEPTION_CODE(*exit_code) != ARM_EXCEPTION_IRQ) + vcpu->arch.fault.esr_el2 = read_sysreg_el2(SYS_ESR); + + /* + * We're using the raw exception code in order to only process + * the trap if no SError is pending. We will come back to the + * same PC once the SError has been injected, and replay the + * trapping instruction. + */ + if (*exit_code != ARM_EXCEPTION_TRAP) + goto exit; + + if (cpus_have_final_cap(ARM64_WORKAROUND_CAVIUM_TX2_219_TVM) && + kvm_vcpu_trap_get_class(vcpu) == ESR_ELx_EC_SYS64 && + handle_tx2_tvm(vcpu)) + return true; + + /* + * We trap the first access to the FP/SIMD to save the host context + * and restore the guest context lazily. + * If FP/SIMD is not implemented, handle the trap and inject an + * undefined instruction exception to the guest. + * Similarly for trapped SVE accesses. + */ + if (__hyp_handle_fpsimd(vcpu)) + return true; + + if (__hyp_handle_ptrauth(vcpu)) + return true; + + if (!__populate_fault_info(vcpu)) + return true; + + if (static_branch_unlikely(&vgic_v2_cpuif_trap)) { + bool valid; + + valid = kvm_vcpu_trap_get_class(vcpu) == ESR_ELx_EC_DABT_LOW && + kvm_vcpu_trap_get_fault_type(vcpu) == FSC_FAULT && + kvm_vcpu_dabt_isvalid(vcpu) && + !kvm_vcpu_dabt_isextabt(vcpu) && + !kvm_vcpu_dabt_iss1tw(vcpu); + + if (valid) { + int ret = __vgic_v2_perform_cpuif_access(vcpu); + + if (ret == 1) + return true; + + /* Promote an illegal access to an SError.*/ + if (ret == -1) + *exit_code = ARM_EXCEPTION_EL1_SERROR; + + goto exit; + } + } + + if (static_branch_unlikely(&vgic_v3_cpuif_trap) && + (kvm_vcpu_trap_get_class(vcpu) == ESR_ELx_EC_SYS64 || + kvm_vcpu_trap_get_class(vcpu) == ESR_ELx_EC_CP15_32)) { + int ret = __vgic_v3_perform_cpuif_access(vcpu); + + if (ret == 1) + return true; + } + +exit: + /* Return to the host kernel and handle the exit */ + return false; +} + +static inline bool __hyp_text __needs_ssbd_off(struct kvm_vcpu *vcpu) +{ + if (!cpus_have_final_cap(ARM64_SSBD)) + return false; + + return !(vcpu->arch.workaround_flags & VCPU_WORKAROUND_2_FLAG); +} + +static inline void __hyp_text __set_guest_arch_workaround_state(struct kvm_vcpu *vcpu) +{ +#ifdef CONFIG_ARM64_SSBD + /* + * The host runs with the workaround always present. If the + * guest wants it disabled, so be it... + */ + if (__needs_ssbd_off(vcpu) && + __hyp_this_cpu_read(arm64_ssbd_callback_required)) + arm_smccc_1_1_smc(ARM_SMCCC_ARCH_WORKAROUND_2, 0, NULL); +#endif +} + +static inline void __hyp_text __set_host_arch_workaround_state(struct kvm_vcpu *vcpu) +{ +#ifdef CONFIG_ARM64_SSBD + /* + * If the guest has disabled the workaround, bring it back on. + */ + if (__needs_ssbd_off(vcpu) && + __hyp_this_cpu_read(arm64_ssbd_callback_required)) + arm_smccc_1_1_smc(ARM_SMCCC_ARCH_WORKAROUND_2, 1, NULL); +#endif +} + +#endif /* __ARM64_KVM_HYP_SWITCH_H__ */ diff --git a/arch/arm64/kvm/hyp/nvhe/Makefile b/arch/arm64/kvm/hyp/nvhe/Makefile index a5316e97d3730..8b3ac38eaa448 100644 --- a/arch/arm64/kvm/hyp/nvhe/Makefile +++ b/arch/arm64/kvm/hyp/nvhe/Makefile @@ -6,7 +6,7 @@ asflags-y := -D__KVM_NVHE_HYPERVISOR__ ccflags-y := -D__KVM_NVHE_HYPERVISOR__ -obj-y := tlb.o hyp-init.o ../hyp-entry.o +obj-y := switch.o tlb.o hyp-init.o ../hyp-entry.o obj-y := $(patsubst %.o,%.hyp.o,$(obj-y)) extra-y := $(patsubst %.hyp.o,%.hyp.tmp.o,$(obj-y)) diff --git a/arch/arm64/kvm/hyp/nvhe/switch.c b/arch/arm64/kvm/hyp/nvhe/switch.c new file mode 100644 index 0000000000000..7f6b8d3dc637a --- /dev/null +++ b/arch/arm64/kvm/hyp/nvhe/switch.c @@ -0,0 +1,271 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2015 - ARM Ltd + * Author: Marc Zyngier + */ + +#include + +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static void __hyp_text __activate_traps(struct kvm_vcpu *vcpu) +{ + u64 val; + + ___activate_traps(vcpu); + __activate_traps_common(vcpu); + + val = CPTR_EL2_DEFAULT; + val |= CPTR_EL2_TTA | CPTR_EL2_TZ | CPTR_EL2_TAM; + if (!update_fp_enabled(vcpu)) { + val |= CPTR_EL2_TFP; + __activate_traps_fpsimd32(vcpu); + } + + write_sysreg(val, cptr_el2); + + if (cpus_have_final_cap(ARM64_WORKAROUND_SPECULATIVE_AT)) { + struct kvm_cpu_context *ctxt = &vcpu->arch.ctxt; + + isb(); + /* + * At this stage, and thanks to the above isb(), S2 is + * configured and enabled. We can now restore the guest's S1 + * configuration: SCTLR, and only then TCR. + */ + write_sysreg_el1(ctxt->sys_regs[SCTLR_EL1], SYS_SCTLR); + isb(); + write_sysreg_el1(ctxt->sys_regs[TCR_EL1], SYS_TCR); + } +} + +static void __hyp_text __deactivate_traps(struct kvm_vcpu *vcpu) +{ + u64 mdcr_el2; + + ___deactivate_traps(vcpu); + + mdcr_el2 = read_sysreg(mdcr_el2); + + if (cpus_have_final_cap(ARM64_WORKAROUND_SPECULATIVE_AT)) { + u64 val; + + /* + * Set the TCR and SCTLR registers in the exact opposite + * sequence as __activate_traps (first prevent walks, + * then force the MMU on). A generous sprinkling of isb() + * ensure that things happen in this exact order. + */ + val = read_sysreg_el1(SYS_TCR); + write_sysreg_el1(val | TCR_EPD1_MASK | TCR_EPD0_MASK, SYS_TCR); + isb(); + val = read_sysreg_el1(SYS_SCTLR); + write_sysreg_el1(val | SCTLR_ELx_M, SYS_SCTLR); + isb(); + } + + __deactivate_traps_common(); + + mdcr_el2 &= MDCR_EL2_HPMN_MASK; + mdcr_el2 |= MDCR_EL2_E2PB_MASK << MDCR_EL2_E2PB_SHIFT; + + write_sysreg(mdcr_el2, mdcr_el2); + write_sysreg(HCR_HOST_NVHE_FLAGS, hcr_el2); + write_sysreg(CPTR_EL2_DEFAULT, cptr_el2); +} + +static void __hyp_text __deactivate_vm(struct kvm_vcpu *vcpu) +{ + write_sysreg(0, vttbr_el2); +} + +/* Save VGICv3 state on non-VHE systems */ +static void __hyp_text __hyp_vgic_save_state(struct kvm_vcpu *vcpu) +{ + if (static_branch_unlikely(&kvm_vgic_global_state.gicv3_cpuif)) { + __vgic_v3_save_state(&vcpu->arch.vgic_cpu.vgic_v3); + __vgic_v3_deactivate_traps(&vcpu->arch.vgic_cpu.vgic_v3); + } +} + +/* Restore VGICv3 state on non_VEH systems */ +static void __hyp_text __hyp_vgic_restore_state(struct kvm_vcpu *vcpu) +{ + if (static_branch_unlikely(&kvm_vgic_global_state.gicv3_cpuif)) { + __vgic_v3_activate_traps(&vcpu->arch.vgic_cpu.vgic_v3); + __vgic_v3_restore_state(&vcpu->arch.vgic_cpu.vgic_v3); + } +} + +/** + * Disable host events, enable guest events + */ +static bool __hyp_text __pmu_switch_to_guest(struct kvm_cpu_context *host_ctxt) +{ + struct kvm_host_data *host; + struct kvm_pmu_events *pmu; + + host = container_of(host_ctxt, struct kvm_host_data, host_ctxt); + pmu = &host->pmu_events; + + if (pmu->events_host) + write_sysreg(pmu->events_host, pmcntenclr_el0); + + if (pmu->events_guest) + write_sysreg(pmu->events_guest, pmcntenset_el0); + + return (pmu->events_host || pmu->events_guest); +} + +/** + * Disable guest events, enable host events + */ +static void __hyp_text __pmu_switch_to_host(struct kvm_cpu_context *host_ctxt) +{ + struct kvm_host_data *host; + struct kvm_pmu_events *pmu; + + host = container_of(host_ctxt, struct kvm_host_data, host_ctxt); + pmu = &host->pmu_events; + + if (pmu->events_guest) + write_sysreg(pmu->events_guest, pmcntenclr_el0); + + if (pmu->events_host) + write_sysreg(pmu->events_host, pmcntenset_el0); +} + +/* Switch to the guest for legacy non-VHE systems */ +int __hyp_text __kvm_vcpu_run(struct kvm_vcpu *vcpu) +{ + struct kvm_cpu_context *host_ctxt; + struct kvm_cpu_context *guest_ctxt; + bool pmu_switch_needed; + u64 exit_code; + + /* + * Having IRQs masked via PMR when entering the guest means the GIC + * will not signal the CPU of interrupts of lower priority, and the + * only way to get out will be via guest exceptions. + * Naturally, we want to avoid this. + */ + if (system_uses_irq_prio_masking()) { + gic_write_pmr(GIC_PRIO_IRQON | GIC_PRIO_PSR_I_SET); + pmr_sync(); + } + + vcpu = kern_hyp_va(vcpu); + + host_ctxt = &__hyp_this_cpu_ptr(kvm_host_data)->host_ctxt; + host_ctxt->__hyp_running_vcpu = vcpu; + guest_ctxt = &vcpu->arch.ctxt; + + pmu_switch_needed = __pmu_switch_to_guest(host_ctxt); + + __sysreg_save_state_nvhe(host_ctxt); + + /* + * We must restore the 32-bit state before the sysregs, thanks + * to erratum #852523 (Cortex-A57) or #853709 (Cortex-A72). + * + * Also, and in order to be able to deal with erratum #1319537 (A57) + * and #1319367 (A72), we must ensure that all VM-related sysreg are + * restored before we enable S2 translation. + */ + __sysreg32_restore_state(vcpu); + __sysreg_restore_state_nvhe(guest_ctxt); + + __activate_vm(kern_hyp_va(vcpu->kvm)); + __activate_traps(vcpu); + + __hyp_vgic_restore_state(vcpu); + __timer_enable_traps(vcpu); + + __debug_switch_to_guest(vcpu); + + __set_guest_arch_workaround_state(vcpu); + + do { + /* Jump in the fire! */ + exit_code = __guest_enter(vcpu, host_ctxt); + + /* And we're baaack! */ + } while (fixup_guest_exit(vcpu, &exit_code)); + + __set_host_arch_workaround_state(vcpu); + + __sysreg_save_state_nvhe(guest_ctxt); + __sysreg32_save_state(vcpu); + __timer_disable_traps(vcpu); + __hyp_vgic_save_state(vcpu); + + __deactivate_traps(vcpu); + __deactivate_vm(vcpu); + + __sysreg_restore_state_nvhe(host_ctxt); + + if (vcpu->arch.flags & KVM_ARM64_FP_ENABLED) + __fpsimd_save_fpexc32(vcpu); + + /* + * 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); + + if (pmu_switch_needed) + __pmu_switch_to_host(host_ctxt); + + /* Returning to host will clear PSR.I, remask PMR if needed */ + if (system_uses_irq_prio_masking()) + gic_write_pmr(GIC_PRIO_IRQOFF); + + return exit_code; +} + +void __hyp_text __noreturn hyp_panic(struct kvm_cpu_context *host_ctxt) +{ + u64 spsr = read_sysreg_el2(SYS_SPSR); + u64 elr = read_sysreg_el2(SYS_ELR); + u64 par = read_sysreg(par_el1); + struct kvm_vcpu *vcpu = host_ctxt->__hyp_running_vcpu; + unsigned long str_va; + + if (read_sysreg(vttbr_el2)) { + __timer_disable_traps(vcpu); + __deactivate_traps(vcpu); + __deactivate_vm(vcpu); + __sysreg_restore_state_nvhe(host_ctxt); + } + + /* + * Force the panic string to be loaded from the literal pool, + * making sure it is a kernel address and not a PC-relative + * reference. + */ + asm volatile("ldr %0, =%1" : "=r" (str_va) : "S" (__hyp_panic_string)); + + __hyp_do_panic(str_va, + spsr, elr, + read_sysreg(esr_el2), read_sysreg_el2(SYS_FAR), + read_sysreg(hpfar_el2), par, vcpu); + unreachable(); +} diff --git a/arch/arm64/kvm/hyp/switch.c b/arch/arm64/kvm/hyp/switch.c deleted file mode 100644 index 9270b14157b55..0000000000000 --- a/arch/arm64/kvm/hyp/switch.c +++ /dev/null @@ -1,936 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Copyright (C) 2015 - ARM Ltd - * Author: Marc Zyngier - */ - -#include -#include -#include -#include -#include - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* Check whether the FP regs were dirtied while in the host-side run loop: */ -static bool __hyp_text update_fp_enabled(struct kvm_vcpu *vcpu) -{ - /* - * When the system doesn't support FP/SIMD, we cannot rely on - * the _TIF_FOREIGN_FPSTATE flag. However, we always inject an - * abort on the very first access to FP and thus we should never - * see KVM_ARM64_FP_ENABLED. For added safety, make sure we always - * trap the accesses. - */ - if (!system_supports_fpsimd() || - vcpu->arch.host_thread_info->flags & _TIF_FOREIGN_FPSTATE) - vcpu->arch.flags &= ~(KVM_ARM64_FP_ENABLED | - KVM_ARM64_FP_HOST); - - return !!(vcpu->arch.flags & KVM_ARM64_FP_ENABLED); -} - -/* Save the 32-bit only FPSIMD system register state */ -static void __hyp_text __fpsimd_save_fpexc32(struct kvm_vcpu *vcpu) -{ - if (!vcpu_el1_is_32bit(vcpu)) - return; - - vcpu->arch.ctxt.sys_regs[FPEXC32_EL2] = read_sysreg(fpexc32_el2); -} - -static void __hyp_text __activate_traps_fpsimd32(struct kvm_vcpu *vcpu) -{ - /* - * We are about to set CPTR_EL2.TFP to trap all floating point - * register accesses to EL2, however, the ARM ARM clearly states that - * traps are only taken to EL2 if the operation would not otherwise - * trap to EL1. Therefore, always make sure that for 32-bit guests, - * we set FPEXC.EN to prevent traps to EL1, when setting the TFP bit. - * If FP/ASIMD is not implemented, FPEXC is UNDEFINED and any access to - * it will cause an exception. - */ - if (vcpu_el1_is_32bit(vcpu) && system_supports_fpsimd()) { - write_sysreg(1 << 30, fpexc32_el2); - isb(); - } -} - -static void __hyp_text __activate_traps_common(struct kvm_vcpu *vcpu) -{ - /* Trap on AArch32 cp15 c15 (impdef sysregs) accesses (EL1 or EL0) */ - write_sysreg(1 << 15, hstr_el2); - - /* - * Make sure we trap PMU access from EL0 to EL2. Also sanitize - * PMSELR_EL0 to make sure it never contains the cycle - * counter, which could make a PMXEVCNTR_EL0 access UNDEF at - * EL1 instead of being trapped to EL2. - */ - write_sysreg(0, pmselr_el0); - write_sysreg(ARMV8_PMU_USERENR_MASK, pmuserenr_el0); - write_sysreg(vcpu->arch.mdcr_el2, mdcr_el2); -} - -static void __hyp_text __deactivate_traps_common(void) -{ - write_sysreg(0, hstr_el2); - write_sysreg(0, pmuserenr_el0); -} - -static void activate_traps_vhe(struct kvm_vcpu *vcpu) -{ - u64 val; - - val = read_sysreg(cpacr_el1); - val |= CPACR_EL1_TTA; - val &= ~CPACR_EL1_ZEN; - - /* - * With VHE (HCR.E2H == 1), accesses to CPACR_EL1 are routed to - * CPTR_EL2. In general, CPACR_EL1 has the same layout as CPTR_EL2, - * except for some missing controls, such as TAM. - * In this case, CPTR_EL2.TAM has the same position with or without - * VHE (HCR.E2H == 1) which allows us to use here the CPTR_EL2.TAM - * shift value for trapping the AMU accesses. - */ - - val |= CPTR_EL2_TAM; - - if (update_fp_enabled(vcpu)) { - if (vcpu_has_sve(vcpu)) - val |= CPACR_EL1_ZEN; - } else { - val &= ~CPACR_EL1_FPEN; - __activate_traps_fpsimd32(vcpu); - } - - write_sysreg(val, cpacr_el1); - - write_sysreg(kvm_get_hyp_vector(), vbar_el1); -} -NOKPROBE_SYMBOL(activate_traps_vhe); - -static void __hyp_text __activate_traps_nvhe(struct kvm_vcpu *vcpu) -{ - u64 val; - - __activate_traps_common(vcpu); - - val = CPTR_EL2_DEFAULT; - val |= CPTR_EL2_TTA | CPTR_EL2_TZ | CPTR_EL2_TAM; - if (!update_fp_enabled(vcpu)) { - val |= CPTR_EL2_TFP; - __activate_traps_fpsimd32(vcpu); - } - - write_sysreg(val, cptr_el2); - - if (cpus_have_final_cap(ARM64_WORKAROUND_SPECULATIVE_AT)) { - struct kvm_cpu_context *ctxt = &vcpu->arch.ctxt; - - isb(); - /* - * At this stage, and thanks to the above isb(), S2 is - * configured and enabled. We can now restore the guest's S1 - * configuration: SCTLR, and only then TCR. - */ - write_sysreg_el1(ctxt->sys_regs[SCTLR_EL1], SYS_SCTLR); - isb(); - write_sysreg_el1(ctxt->sys_regs[TCR_EL1], SYS_TCR); - } -} - -static void __hyp_text __activate_traps(struct kvm_vcpu *vcpu) -{ - u64 hcr = vcpu->arch.hcr_el2; - - if (cpus_have_final_cap(ARM64_WORKAROUND_CAVIUM_TX2_219_TVM)) - hcr |= HCR_TVM; - - write_sysreg(hcr, hcr_el2); - - if (cpus_have_final_cap(ARM64_HAS_RAS_EXTN) && (hcr & HCR_VSE)) - write_sysreg_s(vcpu->arch.vsesr_el2, SYS_VSESR_EL2); - - if (has_vhe()) - activate_traps_vhe(vcpu); - else - __activate_traps_nvhe(vcpu); -} - -static void deactivate_traps_vhe(void) -{ - extern char vectors[]; /* kernel exception vectors */ - write_sysreg(HCR_HOST_VHE_FLAGS, hcr_el2); - - /* - * ARM errata 1165522 and 1530923 require the actual execution of the - * above before we can switch to the EL2/EL0 translation regime used by - * the host. - */ - asm(ALTERNATIVE("nop", "isb", ARM64_WORKAROUND_SPECULATIVE_AT)); - - write_sysreg(CPACR_EL1_DEFAULT, cpacr_el1); - write_sysreg(vectors, vbar_el1); -} -NOKPROBE_SYMBOL(deactivate_traps_vhe); - -static void __hyp_text __deactivate_traps_nvhe(void) -{ - u64 mdcr_el2 = read_sysreg(mdcr_el2); - - if (cpus_have_final_cap(ARM64_WORKAROUND_SPECULATIVE_AT)) { - u64 val; - - /* - * Set the TCR and SCTLR registers in the exact opposite - * sequence as __activate_traps_nvhe (first prevent walks, - * then force the MMU on). A generous sprinkling of isb() - * ensure that things happen in this exact order. - */ - val = read_sysreg_el1(SYS_TCR); - write_sysreg_el1(val | TCR_EPD1_MASK | TCR_EPD0_MASK, SYS_TCR); - isb(); - val = read_sysreg_el1(SYS_SCTLR); - write_sysreg_el1(val | SCTLR_ELx_M, SYS_SCTLR); - isb(); - } - - __deactivate_traps_common(); - - mdcr_el2 &= MDCR_EL2_HPMN_MASK; - mdcr_el2 |= MDCR_EL2_E2PB_MASK << MDCR_EL2_E2PB_SHIFT; - - write_sysreg(mdcr_el2, mdcr_el2); - write_sysreg(HCR_HOST_NVHE_FLAGS, hcr_el2); - write_sysreg(CPTR_EL2_DEFAULT, cptr_el2); -} - -static void __hyp_text __deactivate_traps(struct kvm_vcpu *vcpu) -{ - /* - * If we pended a virtual abort, preserve it until it gets - * cleared. See D1.14.3 (Virtual Interrupts) for details, but - * the crucial bit is "On taking a vSError interrupt, - * HCR_EL2.VSE is cleared to 0." - */ - if (vcpu->arch.hcr_el2 & HCR_VSE) { - vcpu->arch.hcr_el2 &= ~HCR_VSE; - vcpu->arch.hcr_el2 |= read_sysreg(hcr_el2) & HCR_VSE; - } - - if (has_vhe()) - deactivate_traps_vhe(); - else - __deactivate_traps_nvhe(); -} - -void activate_traps_vhe_load(struct kvm_vcpu *vcpu) -{ - __activate_traps_common(vcpu); -} - -void deactivate_traps_vhe_put(void) -{ - u64 mdcr_el2 = read_sysreg(mdcr_el2); - - mdcr_el2 &= MDCR_EL2_HPMN_MASK | - MDCR_EL2_E2PB_MASK << MDCR_EL2_E2PB_SHIFT | - MDCR_EL2_TPMS; - - write_sysreg(mdcr_el2, mdcr_el2); - - __deactivate_traps_common(); -} - -static void __hyp_text __activate_vm(struct kvm *kvm) -{ - __load_guest_stage2(kvm); -} - -static void __hyp_text __deactivate_vm(struct kvm_vcpu *vcpu) -{ - write_sysreg(0, vttbr_el2); -} - -/* Save VGICv3 state on non-VHE systems */ -static void __hyp_text __hyp_vgic_save_state(struct kvm_vcpu *vcpu) -{ - if (static_branch_unlikely(&kvm_vgic_global_state.gicv3_cpuif)) { - __vgic_v3_save_state(&vcpu->arch.vgic_cpu.vgic_v3); - __vgic_v3_deactivate_traps(&vcpu->arch.vgic_cpu.vgic_v3); - } -} - -/* Restore VGICv3 state on non_VEH systems */ -static void __hyp_text __hyp_vgic_restore_state(struct kvm_vcpu *vcpu) -{ - if (static_branch_unlikely(&kvm_vgic_global_state.gicv3_cpuif)) { - __vgic_v3_activate_traps(&vcpu->arch.vgic_cpu.vgic_v3); - __vgic_v3_restore_state(&vcpu->arch.vgic_cpu.vgic_v3); - } -} - -static bool __hyp_text __translate_far_to_hpfar(u64 far, u64 *hpfar) -{ - u64 par, tmp; - - /* - * Resolve the IPA the hard way using the guest VA. - * - * Stage-1 translation already validated the memory access - * rights. As such, we can use the EL1 translation regime, and - * don't have to distinguish between EL0 and EL1 access. - * - * We do need to save/restore PAR_EL1 though, as we haven't - * saved the guest context yet, and we may return early... - */ - par = read_sysreg(par_el1); - asm volatile("at s1e1r, %0" : : "r" (far)); - isb(); - - tmp = read_sysreg(par_el1); - write_sysreg(par, par_el1); - - if (unlikely(tmp & SYS_PAR_EL1_F)) - return false; /* Translation failed, back to guest */ - - /* Convert PAR to HPFAR format */ - *hpfar = PAR_TO_HPFAR(tmp); - return true; -} - -static bool __hyp_text __populate_fault_info(struct kvm_vcpu *vcpu) -{ - u8 ec; - u64 esr; - u64 hpfar, far; - - esr = vcpu->arch.fault.esr_el2; - ec = ESR_ELx_EC(esr); - - if (ec != ESR_ELx_EC_DABT_LOW && ec != ESR_ELx_EC_IABT_LOW) - return true; - - far = read_sysreg_el2(SYS_FAR); - - /* - * The HPFAR can be invalid if the stage 2 fault did not - * happen during a stage 1 page table walk (the ESR_EL2.S1PTW - * bit is clear) and one of the two following cases are true: - * 1. The fault was due to a permission fault - * 2. The processor carries errata 834220 - * - * Therefore, for all non S1PTW faults where we either have a - * permission fault or the errata workaround is enabled, we - * resolve the IPA using the AT instruction. - */ - if (!(esr & ESR_ELx_S1PTW) && - (cpus_have_final_cap(ARM64_WORKAROUND_834220) || - (esr & ESR_ELx_FSC_TYPE) == FSC_PERM)) { - if (!__translate_far_to_hpfar(far, &hpfar)) - return false; - } else { - hpfar = read_sysreg(hpfar_el2); - } - - vcpu->arch.fault.far_el2 = far; - vcpu->arch.fault.hpfar_el2 = hpfar; - return true; -} - -/* Check for an FPSIMD/SVE trap and handle as appropriate */ -static bool __hyp_text __hyp_handle_fpsimd(struct kvm_vcpu *vcpu) -{ - bool vhe, sve_guest, sve_host; - u8 hsr_ec; - - if (!system_supports_fpsimd()) - return false; - - if (system_supports_sve()) { - sve_guest = vcpu_has_sve(vcpu); - sve_host = vcpu->arch.flags & KVM_ARM64_HOST_SVE_IN_USE; - vhe = true; - } else { - sve_guest = false; - sve_host = false; - vhe = has_vhe(); - } - - hsr_ec = kvm_vcpu_trap_get_class(vcpu); - if (hsr_ec != ESR_ELx_EC_FP_ASIMD && - hsr_ec != ESR_ELx_EC_SVE) - return false; - - /* Don't handle SVE traps for non-SVE vcpus here: */ - if (!sve_guest) - if (hsr_ec != ESR_ELx_EC_FP_ASIMD) - return false; - - /* Valid trap. Switch the context: */ - - if (vhe) { - u64 reg = read_sysreg(cpacr_el1) | CPACR_EL1_FPEN; - - if (sve_guest) - reg |= CPACR_EL1_ZEN; - - write_sysreg(reg, cpacr_el1); - } else { - write_sysreg(read_sysreg(cptr_el2) & ~(u64)CPTR_EL2_TFP, - cptr_el2); - } - - isb(); - - if (vcpu->arch.flags & KVM_ARM64_FP_HOST) { - /* - * In the SVE case, VHE is assumed: it is enforced by - * Kconfig and kvm_arch_init(). - */ - if (sve_host) { - struct thread_struct *thread = container_of( - vcpu->arch.host_fpsimd_state, - struct thread_struct, uw.fpsimd_state); - - sve_save_state(sve_pffr(thread), - &vcpu->arch.host_fpsimd_state->fpsr); - } else { - __fpsimd_save_state(vcpu->arch.host_fpsimd_state); - } - - vcpu->arch.flags &= ~KVM_ARM64_FP_HOST; - } - - if (sve_guest) { - sve_load_state(vcpu_sve_pffr(vcpu), - &vcpu->arch.ctxt.gp_regs.fp_regs.fpsr, - sve_vq_from_vl(vcpu->arch.sve_max_vl) - 1); - write_sysreg_s(vcpu->arch.ctxt.sys_regs[ZCR_EL1], SYS_ZCR_EL12); - } else { - __fpsimd_restore_state(&vcpu->arch.ctxt.gp_regs.fp_regs); - } - - /* Skip restoring fpexc32 for AArch64 guests */ - if (!(read_sysreg(hcr_el2) & HCR_RW)) - write_sysreg(vcpu->arch.ctxt.sys_regs[FPEXC32_EL2], - fpexc32_el2); - - vcpu->arch.flags |= KVM_ARM64_FP_ENABLED; - - return true; -} - -static bool __hyp_text handle_tx2_tvm(struct kvm_vcpu *vcpu) -{ - u32 sysreg = esr_sys64_to_sysreg(kvm_vcpu_get_hsr(vcpu)); - int rt = kvm_vcpu_sys_get_rt(vcpu); - u64 val = vcpu_get_reg(vcpu, rt); - - /* - * The normal sysreg handling code expects to see the traps, - * let's not do anything here. - */ - if (vcpu->arch.hcr_el2 & HCR_TVM) - return false; - - switch (sysreg) { - case SYS_SCTLR_EL1: - write_sysreg_el1(val, SYS_SCTLR); - break; - case SYS_TTBR0_EL1: - write_sysreg_el1(val, SYS_TTBR0); - break; - case SYS_TTBR1_EL1: - write_sysreg_el1(val, SYS_TTBR1); - break; - case SYS_TCR_EL1: - write_sysreg_el1(val, SYS_TCR); - break; - case SYS_ESR_EL1: - write_sysreg_el1(val, SYS_ESR); - break; - case SYS_FAR_EL1: - write_sysreg_el1(val, SYS_FAR); - break; - case SYS_AFSR0_EL1: - write_sysreg_el1(val, SYS_AFSR0); - break; - case SYS_AFSR1_EL1: - write_sysreg_el1(val, SYS_AFSR1); - break; - case SYS_MAIR_EL1: - write_sysreg_el1(val, SYS_MAIR); - break; - case SYS_AMAIR_EL1: - write_sysreg_el1(val, SYS_AMAIR); - break; - case SYS_CONTEXTIDR_EL1: - write_sysreg_el1(val, SYS_CONTEXTIDR); - break; - default: - return false; - } - - __kvm_skip_instr(vcpu); - return true; -} - -static bool __hyp_text esr_is_ptrauth_trap(u32 esr) -{ - u32 ec = ESR_ELx_EC(esr); - - if (ec == ESR_ELx_EC_PAC) - return true; - - if (ec != ESR_ELx_EC_SYS64) - return false; - - switch (esr_sys64_to_sysreg(esr)) { - case SYS_APIAKEYLO_EL1: - case SYS_APIAKEYHI_EL1: - case SYS_APIBKEYLO_EL1: - case SYS_APIBKEYHI_EL1: - case SYS_APDAKEYLO_EL1: - case SYS_APDAKEYHI_EL1: - case SYS_APDBKEYLO_EL1: - case SYS_APDBKEYHI_EL1: - case SYS_APGAKEYLO_EL1: - case SYS_APGAKEYHI_EL1: - return true; - } - - return false; -} - -#define __ptrauth_save_key(regs, key) \ -({ \ - regs[key ## KEYLO_EL1] = read_sysreg_s(SYS_ ## key ## KEYLO_EL1); \ - regs[key ## KEYHI_EL1] = read_sysreg_s(SYS_ ## key ## KEYHI_EL1); \ -}) - -static bool __hyp_text __hyp_handle_ptrauth(struct kvm_vcpu *vcpu) -{ - struct kvm_cpu_context *ctxt; - u64 val; - - if (!vcpu_has_ptrauth(vcpu) || - !esr_is_ptrauth_trap(kvm_vcpu_get_hsr(vcpu))) - return false; - - ctxt = &__hyp_this_cpu_ptr(kvm_host_data)->host_ctxt; - __ptrauth_save_key(ctxt->sys_regs, APIA); - __ptrauth_save_key(ctxt->sys_regs, APIB); - __ptrauth_save_key(ctxt->sys_regs, APDA); - __ptrauth_save_key(ctxt->sys_regs, APDB); - __ptrauth_save_key(ctxt->sys_regs, APGA); - - vcpu_ptrauth_enable(vcpu); - - val = read_sysreg(hcr_el2); - val |= (HCR_API | HCR_APK); - write_sysreg(val, hcr_el2); - - return true; -} - -/* - * Return true when we were able to fixup the guest exit and should return to - * the guest, false when we should restore the host state and return to the - * main run loop. - */ -static bool __hyp_text fixup_guest_exit(struct kvm_vcpu *vcpu, u64 *exit_code) -{ - if (ARM_EXCEPTION_CODE(*exit_code) != ARM_EXCEPTION_IRQ) - vcpu->arch.fault.esr_el2 = read_sysreg_el2(SYS_ESR); - - /* - * We're using the raw exception code in order to only process - * the trap if no SError is pending. We will come back to the - * same PC once the SError has been injected, and replay the - * trapping instruction. - */ - if (*exit_code != ARM_EXCEPTION_TRAP) - goto exit; - - if (cpus_have_final_cap(ARM64_WORKAROUND_CAVIUM_TX2_219_TVM) && - kvm_vcpu_trap_get_class(vcpu) == ESR_ELx_EC_SYS64 && - handle_tx2_tvm(vcpu)) - return true; - - /* - * We trap the first access to the FP/SIMD to save the host context - * and restore the guest context lazily. - * If FP/SIMD is not implemented, handle the trap and inject an - * undefined instruction exception to the guest. - * Similarly for trapped SVE accesses. - */ - if (__hyp_handle_fpsimd(vcpu)) - return true; - - if (__hyp_handle_ptrauth(vcpu)) - return true; - - if (!__populate_fault_info(vcpu)) - return true; - - if (static_branch_unlikely(&vgic_v2_cpuif_trap)) { - bool valid; - - valid = kvm_vcpu_trap_get_class(vcpu) == ESR_ELx_EC_DABT_LOW && - kvm_vcpu_trap_get_fault_type(vcpu) == FSC_FAULT && - kvm_vcpu_dabt_isvalid(vcpu) && - !kvm_vcpu_dabt_isextabt(vcpu) && - !kvm_vcpu_dabt_iss1tw(vcpu); - - if (valid) { - int ret = __vgic_v2_perform_cpuif_access(vcpu); - - if (ret == 1) - return true; - - /* Promote an illegal access to an SError.*/ - if (ret == -1) - *exit_code = ARM_EXCEPTION_EL1_SERROR; - - goto exit; - } - } - - if (static_branch_unlikely(&vgic_v3_cpuif_trap) && - (kvm_vcpu_trap_get_class(vcpu) == ESR_ELx_EC_SYS64 || - kvm_vcpu_trap_get_class(vcpu) == ESR_ELx_EC_CP15_32)) { - int ret = __vgic_v3_perform_cpuif_access(vcpu); - - if (ret == 1) - return true; - } - -exit: - /* Return to the host kernel and handle the exit */ - return false; -} - -static inline bool __hyp_text __needs_ssbd_off(struct kvm_vcpu *vcpu) -{ - if (!cpus_have_final_cap(ARM64_SSBD)) - return false; - - return !(vcpu->arch.workaround_flags & VCPU_WORKAROUND_2_FLAG); -} - -static void __hyp_text __set_guest_arch_workaround_state(struct kvm_vcpu *vcpu) -{ -#ifdef CONFIG_ARM64_SSBD - /* - * The host runs with the workaround always present. If the - * guest wants it disabled, so be it... - */ - if (__needs_ssbd_off(vcpu) && - __hyp_this_cpu_read(arm64_ssbd_callback_required)) - arm_smccc_1_1_smc(ARM_SMCCC_ARCH_WORKAROUND_2, 0, NULL); -#endif -} - -static void __hyp_text __set_host_arch_workaround_state(struct kvm_vcpu *vcpu) -{ -#ifdef CONFIG_ARM64_SSBD - /* - * If the guest has disabled the workaround, bring it back on. - */ - if (__needs_ssbd_off(vcpu) && - __hyp_this_cpu_read(arm64_ssbd_callback_required)) - arm_smccc_1_1_smc(ARM_SMCCC_ARCH_WORKAROUND_2, 1, NULL); -#endif -} - -/** - * Disable host events, enable guest events - */ -static bool __hyp_text __pmu_switch_to_guest(struct kvm_cpu_context *host_ctxt) -{ - struct kvm_host_data *host; - struct kvm_pmu_events *pmu; - - host = container_of(host_ctxt, struct kvm_host_data, host_ctxt); - pmu = &host->pmu_events; - - if (pmu->events_host) - write_sysreg(pmu->events_host, pmcntenclr_el0); - - if (pmu->events_guest) - write_sysreg(pmu->events_guest, pmcntenset_el0); - - return (pmu->events_host || pmu->events_guest); -} - -/** - * Disable guest events, enable host events - */ -static void __hyp_text __pmu_switch_to_host(struct kvm_cpu_context *host_ctxt) -{ - struct kvm_host_data *host; - struct kvm_pmu_events *pmu; - - host = container_of(host_ctxt, struct kvm_host_data, host_ctxt); - pmu = &host->pmu_events; - - if (pmu->events_guest) - write_sysreg(pmu->events_guest, pmcntenclr_el0); - - if (pmu->events_host) - write_sysreg(pmu->events_host, pmcntenset_el0); -} - -/* Switch to the guest for VHE systems running in EL2 */ -static int __kvm_vcpu_run_vhe(struct kvm_vcpu *vcpu) -{ - struct kvm_cpu_context *host_ctxt; - struct kvm_cpu_context *guest_ctxt; - u64 exit_code; - - host_ctxt = &__hyp_this_cpu_ptr(kvm_host_data)->host_ctxt; - host_ctxt->__hyp_running_vcpu = vcpu; - guest_ctxt = &vcpu->arch.ctxt; - - sysreg_save_host_state_vhe(host_ctxt); - - /* - * ARM erratum 1165522 requires us to configure both stage 1 and - * stage 2 translation for the guest context before we clear - * HCR_EL2.TGE. - * - * We have already configured the guest's stage 1 translation in - * kvm_vcpu_load_sysregs above. We must now call __activate_vm - * before __activate_traps, because __activate_vm configures - * stage 2 translation, and __activate_traps clear HCR_EL2.TGE - * (among other things). - */ - __activate_vm(vcpu->kvm); - __activate_traps(vcpu); - - sysreg_restore_guest_state_vhe(guest_ctxt); - __debug_switch_to_guest(vcpu); - - __set_guest_arch_workaround_state(vcpu); - - do { - /* Jump in the fire! */ - exit_code = __guest_enter(vcpu, host_ctxt); - - /* And we're baaack! */ - } while (fixup_guest_exit(vcpu, &exit_code)); - - __set_host_arch_workaround_state(vcpu); - - sysreg_save_guest_state_vhe(guest_ctxt); - - __deactivate_traps(vcpu); - - sysreg_restore_host_state_vhe(host_ctxt); - - if (vcpu->arch.flags & KVM_ARM64_FP_ENABLED) - __fpsimd_save_fpexc32(vcpu); - - __debug_switch_to_host(vcpu); - - return exit_code; -} -NOKPROBE_SYMBOL(__kvm_vcpu_run_vhe); - -int kvm_vcpu_run_vhe(struct kvm_vcpu *vcpu) -{ - int ret; - - local_daif_mask(); - - /* - * Having IRQs masked via PMR when entering the guest means the GIC - * will not signal the CPU of interrupts of lower priority, and the - * only way to get out will be via guest exceptions. - * Naturally, we want to avoid this. - * - * local_daif_mask() already sets GIC_PRIO_PSR_I_SET, we just need a - * dsb to ensure the redistributor is forwards EL2 IRQs to the CPU. - */ - pmr_sync(); - - ret = __kvm_vcpu_run_vhe(vcpu); - - /* - * local_daif_restore() takes care to properly restore PSTATE.DAIF - * and the GIC PMR if the host is using IRQ priorities. - */ - local_daif_restore(DAIF_PROCCTX_NOIRQ); - - /* - * When we exit from the guest we change a number of CPU configuration - * parameters, such as traps. Make sure these changes take effect - * before running the host or additional guests. - */ - isb(); - - return ret; -} - -/* 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; - bool pmu_switch_needed; - u64 exit_code; - - /* - * Having IRQs masked via PMR when entering the guest means the GIC - * will not signal the CPU of interrupts of lower priority, and the - * only way to get out will be via guest exceptions. - * Naturally, we want to avoid this. - */ - if (system_uses_irq_prio_masking()) { - gic_write_pmr(GIC_PRIO_IRQON | GIC_PRIO_PSR_I_SET); - pmr_sync(); - } - - vcpu = kern_hyp_va(vcpu); - - host_ctxt = &__hyp_this_cpu_ptr(kvm_host_data)->host_ctxt; - host_ctxt->__hyp_running_vcpu = vcpu; - guest_ctxt = &vcpu->arch.ctxt; - - pmu_switch_needed = __pmu_switch_to_guest(host_ctxt); - - __sysreg_save_state_nvhe(host_ctxt); - - /* - * We must restore the 32-bit state before the sysregs, thanks - * to erratum #852523 (Cortex-A57) or #853709 (Cortex-A72). - * - * Also, and in order to be able to deal with erratum #1319537 (A57) - * and #1319367 (A72), we must ensure that all VM-related sysreg are - * restored before we enable S2 translation. - */ - __sysreg32_restore_state(vcpu); - __sysreg_restore_state_nvhe(guest_ctxt); - - __activate_vm(kern_hyp_va(vcpu->kvm)); - __activate_traps(vcpu); - - __hyp_vgic_restore_state(vcpu); - __timer_enable_traps(vcpu); - - __debug_switch_to_guest(vcpu); - - __set_guest_arch_workaround_state(vcpu); - - do { - /* Jump in the fire! */ - exit_code = __guest_enter(vcpu, host_ctxt); - - /* And we're baaack! */ - } while (fixup_guest_exit(vcpu, &exit_code)); - - __set_host_arch_workaround_state(vcpu); - - __sysreg_save_state_nvhe(guest_ctxt); - __sysreg32_save_state(vcpu); - __timer_disable_traps(vcpu); - __hyp_vgic_save_state(vcpu); - - __deactivate_traps(vcpu); - __deactivate_vm(vcpu); - - __sysreg_restore_state_nvhe(host_ctxt); - - if (vcpu->arch.flags & KVM_ARM64_FP_ENABLED) - __fpsimd_save_fpexc32(vcpu); - - /* - * 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); - - if (pmu_switch_needed) - __pmu_switch_to_host(host_ctxt); - - /* Returning to host will clear PSR.I, remask PMR if needed */ - if (system_uses_irq_prio_masking()) - gic_write_pmr(GIC_PRIO_IRQOFF); - - return exit_code; -} - -static const char __hyp_panic_string[] = "HYP panic:\nPS:%08llx PC:%016llx ESR:%08llx\nFAR:%016llx HPFAR:%016llx PAR:%016llx\nVCPU:%p\n"; - -static void __hyp_text __hyp_call_panic_nvhe(u64 spsr, u64 elr, u64 par, - struct kvm_cpu_context *__host_ctxt) -{ - struct kvm_vcpu *vcpu; - unsigned long str_va; - - vcpu = __host_ctxt->__hyp_running_vcpu; - - if (read_sysreg(vttbr_el2)) { - __timer_disable_traps(vcpu); - __deactivate_traps(vcpu); - __deactivate_vm(vcpu); - __sysreg_restore_state_nvhe(__host_ctxt); - } - - /* - * Force the panic string to be loaded from the literal pool, - * making sure it is a kernel address and not a PC-relative - * reference. - */ - asm volatile("ldr %0, =%1" : "=r" (str_va) : "S" (__hyp_panic_string)); - - __hyp_do_panic(str_va, - spsr, elr, - read_sysreg(esr_el2), read_sysreg_el2(SYS_FAR), - read_sysreg(hpfar_el2), par, vcpu); -} - -static void __hyp_call_panic_vhe(u64 spsr, u64 elr, u64 par, - struct kvm_cpu_context *host_ctxt) -{ - struct kvm_vcpu *vcpu; - vcpu = host_ctxt->__hyp_running_vcpu; - - __deactivate_traps(vcpu); - sysreg_restore_host_state_vhe(host_ctxt); - - panic(__hyp_panic_string, - spsr, elr, - read_sysreg_el2(SYS_ESR), read_sysreg_el2(SYS_FAR), - read_sysreg(hpfar_el2), par, vcpu); -} -NOKPROBE_SYMBOL(__hyp_call_panic_vhe); - -void __hyp_text __noreturn hyp_panic(struct kvm_cpu_context *host_ctxt) -{ - u64 spsr = read_sysreg_el2(SYS_SPSR); - u64 elr = read_sysreg_el2(SYS_ELR); - u64 par = read_sysreg(par_el1); - - if (!has_vhe()) - __hyp_call_panic_nvhe(spsr, elr, par, host_ctxt); - else - __hyp_call_panic_vhe(spsr, elr, par, host_ctxt); - - unreachable(); -} diff --git a/arch/arm64/kvm/hyp/sysreg-sr.c b/arch/arm64/kvm/hyp/sysreg-sr.c index cc7e957f5b2c3..2493439a5c548 100644 --- a/arch/arm64/kvm/hyp/sysreg-sr.c +++ b/arch/arm64/kvm/hyp/sysreg-sr.c @@ -114,7 +114,7 @@ static void __hyp_text __sysreg_restore_el1_state(struct kvm_cpu_context *ctxt) /* * Must only be done for guest registers, hence the context * test. We're coming from the host, so SCTLR.M is already - * set. Pairs with __activate_traps_nvhe(). + * set. Pairs with nVHE's __activate_traps(). */ write_sysreg_el1((ctxt->sys_regs[TCR_EL1] | TCR_EPD1_MASK | TCR_EPD0_MASK), @@ -142,7 +142,7 @@ static void __hyp_text __sysreg_restore_el1_state(struct kvm_cpu_context *ctxt) ctxt->__hyp_running_vcpu) { /* * Must only be done for host registers, hence the context - * test. Pairs with __deactivate_traps_nvhe(). + * test. Pairs with nVHE's __deactivate_traps(). */ isb(); /* diff --git a/arch/arm64/kvm/hyp/vhe/Makefile b/arch/arm64/kvm/hyp/vhe/Makefile index 704140fc5d66b..9f71cd3ba50d1 100644 --- a/arch/arm64/kvm/hyp/vhe/Makefile +++ b/arch/arm64/kvm/hyp/vhe/Makefile @@ -6,7 +6,7 @@ asflags-y := -D__KVM_VHE_HYPERVISOR__ ccflags-y := -D__KVM_VHE_HYPERVISOR__ -obj-y := tlb.o ../hyp-entry.o +obj-y := switch.o tlb.o ../hyp-entry.o # KVM code is run at a different exception code with a different map, so # compiler instrumentation that inserts callbacks or checks into the code may diff --git a/arch/arm64/kvm/hyp/vhe/switch.c b/arch/arm64/kvm/hyp/vhe/switch.c new file mode 100644 index 0000000000000..e8d76cab44e43 --- /dev/null +++ b/arch/arm64/kvm/hyp/vhe/switch.c @@ -0,0 +1,219 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2015 - ARM Ltd + * Author: Marc Zyngier + */ + +#include + +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +const char __hyp_panic_string[] = "HYP panic:\nPS:%08llx PC:%016llx ESR:%08llx\nFAR:%016llx HPFAR:%016llx PAR:%016llx\nVCPU:%p\n"; + +static void __activate_traps(struct kvm_vcpu *vcpu) +{ + u64 val; + + ___activate_traps(vcpu); + + val = read_sysreg(cpacr_el1); + val |= CPACR_EL1_TTA; + val &= ~CPACR_EL1_ZEN; + + /* + * With VHE (HCR.E2H == 1), accesses to CPACR_EL1 are routed to + * CPTR_EL2. In general, CPACR_EL1 has the same layout as CPTR_EL2, + * except for some missing controls, such as TAM. + * In this case, CPTR_EL2.TAM has the same position with or without + * VHE (HCR.E2H == 1) which allows us to use here the CPTR_EL2.TAM + * shift value for trapping the AMU accesses. + */ + + val |= CPTR_EL2_TAM; + + if (update_fp_enabled(vcpu)) { + if (vcpu_has_sve(vcpu)) + val |= CPACR_EL1_ZEN; + } else { + val &= ~CPACR_EL1_FPEN; + __activate_traps_fpsimd32(vcpu); + } + + write_sysreg(val, cpacr_el1); + + write_sysreg(kvm_get_hyp_vector(), vbar_el1); +} +NOKPROBE_SYMBOL(__activate_traps); + +static void __deactivate_traps(struct kvm_vcpu *vcpu) +{ + extern char vectors[]; /* kernel exception vectors */ + + ___deactivate_traps(vcpu); + + write_sysreg(HCR_HOST_VHE_FLAGS, hcr_el2); + + /* + * ARM errata 1165522 and 1530923 require the actual execution of the + * above before we can switch to the EL2/EL0 translation regime used by + * the host. + */ + asm(ALTERNATIVE("nop", "isb", ARM64_WORKAROUND_SPECULATIVE_AT)); + + write_sysreg(CPACR_EL1_DEFAULT, cpacr_el1); + write_sysreg(vectors, vbar_el1); +} +NOKPROBE_SYMBOL(__deactivate_traps); + +void activate_traps_vhe_load(struct kvm_vcpu *vcpu) +{ + __activate_traps_common(vcpu); +} + +void deactivate_traps_vhe_put(void) +{ + u64 mdcr_el2 = read_sysreg(mdcr_el2); + + mdcr_el2 &= MDCR_EL2_HPMN_MASK | + MDCR_EL2_E2PB_MASK << MDCR_EL2_E2PB_SHIFT | + MDCR_EL2_TPMS; + + write_sysreg(mdcr_el2, mdcr_el2); + + __deactivate_traps_common(); +} + +/* Switch to the guest for VHE systems running in EL2 */ +static int __kvm_vcpu_run_vhe(struct kvm_vcpu *vcpu) +{ + struct kvm_cpu_context *host_ctxt; + struct kvm_cpu_context *guest_ctxt; + u64 exit_code; + + host_ctxt = &__hyp_this_cpu_ptr(kvm_host_data)->host_ctxt; + host_ctxt->__hyp_running_vcpu = vcpu; + guest_ctxt = &vcpu->arch.ctxt; + + sysreg_save_host_state_vhe(host_ctxt); + + /* + * ARM erratum 1165522 requires us to configure both stage 1 and + * stage 2 translation for the guest context before we clear + * HCR_EL2.TGE. + * + * We have already configured the guest's stage 1 translation in + * kvm_vcpu_load_sysregs above. We must now call __activate_vm + * before __activate_traps, because __activate_vm configures + * stage 2 translation, and __activate_traps clear HCR_EL2.TGE + * (among other things). + */ + __activate_vm(vcpu->kvm); + __activate_traps(vcpu); + + sysreg_restore_guest_state_vhe(guest_ctxt); + __debug_switch_to_guest(vcpu); + + __set_guest_arch_workaround_state(vcpu); + + do { + /* Jump in the fire! */ + exit_code = __guest_enter(vcpu, host_ctxt); + + /* And we're baaack! */ + } while (fixup_guest_exit(vcpu, &exit_code)); + + __set_host_arch_workaround_state(vcpu); + + sysreg_save_guest_state_vhe(guest_ctxt); + + __deactivate_traps(vcpu); + + sysreg_restore_host_state_vhe(host_ctxt); + + if (vcpu->arch.flags & KVM_ARM64_FP_ENABLED) + __fpsimd_save_fpexc32(vcpu); + + __debug_switch_to_host(vcpu); + + return exit_code; +} +NOKPROBE_SYMBOL(__kvm_vcpu_run_vhe); + +int __kvm_vcpu_run(struct kvm_vcpu *vcpu) +{ + int ret; + + local_daif_mask(); + + /* + * Having IRQs masked via PMR when entering the guest means the GIC + * will not signal the CPU of interrupts of lower priority, and the + * only way to get out will be via guest exceptions. + * Naturally, we want to avoid this. + * + * local_daif_mask() already sets GIC_PRIO_PSR_I_SET, we just need a + * dsb to ensure the redistributor is forwards EL2 IRQs to the CPU. + */ + pmr_sync(); + + ret = __kvm_vcpu_run_vhe(vcpu); + + /* + * local_daif_restore() takes care to properly restore PSTATE.DAIF + * and the GIC PMR if the host is using IRQ priorities. + */ + local_daif_restore(DAIF_PROCCTX_NOIRQ); + + /* + * When we exit from the guest we change a number of CPU configuration + * parameters, such as traps. Make sure these changes take effect + * before running the host or additional guests. + */ + isb(); + + return ret; +} + +static void __hyp_call_panic(u64 spsr, u64 elr, u64 par, + struct kvm_cpu_context *host_ctxt) +{ + struct kvm_vcpu *vcpu; + vcpu = host_ctxt->__hyp_running_vcpu; + + __deactivate_traps(vcpu); + sysreg_restore_host_state_vhe(host_ctxt); + + panic(__hyp_panic_string, + spsr, elr, + read_sysreg_el2(SYS_ESR), read_sysreg_el2(SYS_FAR), + read_sysreg(hpfar_el2), par, vcpu); +} +NOKPROBE_SYMBOL(__hyp_call_panic); + +void __noreturn hyp_panic(struct kvm_cpu_context *host_ctxt) +{ + u64 spsr = read_sysreg_el2(SYS_SPSR); + u64 elr = read_sysreg_el2(SYS_ELR); + u64 par = read_sysreg(par_el1); + + __hyp_call_panic(spsr, elr, par, host_ctxt); + unreachable(); +} -- GitLab From d400c5b2025c9aeca76213d6bd4138ec39da5cef Mon Sep 17 00:00:00 2001 From: David Brazdil Date: Thu, 25 Jun 2020 14:14:15 +0100 Subject: [PATCH 0168/2249] KVM: arm64: Split hyp/debug-sr.c to VHE/nVHE debug-sr.c contains KVM's code for context-switching debug registers, with some code shared between VHE/nVHE. These common routines are moved to a header file, VHE-specific code is moved to vhe/debug-sr.c and nVHE-specific code to nvhe/debug-sr.c. Functions are slightly refactored to move code hidden behind `has_vhe()` checks to the corresponding .c files. Signed-off-by: David Brazdil Signed-off-by: Marc Zyngier Link: https://lore.kernel.org/r/20200625131420.71444-11-dbrazdil@google.com --- arch/arm64/kernel/image-vars.h | 5 -- arch/arm64/kvm/hyp/Makefile | 2 +- .../{debug-sr.c => include/hyp/debug-sr.h} | 78 +++---------------- arch/arm64/kvm/hyp/nvhe/Makefile | 2 +- arch/arm64/kvm/hyp/nvhe/debug-sr.c | 77 ++++++++++++++++++ arch/arm64/kvm/hyp/vhe/Makefile | 2 +- arch/arm64/kvm/hyp/vhe/debug-sr.c | 26 +++++++ 7 files changed, 118 insertions(+), 74 deletions(-) rename arch/arm64/kvm/hyp/{debug-sr.c => include/hyp/debug-sr.h} (71%) create mode 100644 arch/arm64/kvm/hyp/nvhe/debug-sr.c create mode 100644 arch/arm64/kvm/hyp/vhe/debug-sr.c diff --git a/arch/arm64/kernel/image-vars.h b/arch/arm64/kernel/image-vars.h index 06fe9833104ae..c44ca4e7dd663 100644 --- a/arch/arm64/kernel/image-vars.h +++ b/arch/arm64/kernel/image-vars.h @@ -66,11 +66,6 @@ __efistub__ctype = _ctype; /* Symbols defined in aarch32.c (not yet compiled with nVHE build rules). */ KVM_NVHE_ALIAS(kvm_skip_instr32); -/* Symbols defined in debug-sr.c (not yet compiled with nVHE build rules). */ -KVM_NVHE_ALIAS(__debug_switch_to_guest); -KVM_NVHE_ALIAS(__debug_switch_to_host); -KVM_NVHE_ALIAS(__kvm_get_mdcr_el2); - /* Symbols defined in entry.S (not yet compiled with nVHE build rules). */ KVM_NVHE_ALIAS(__guest_enter); KVM_NVHE_ALIAS(__guest_exit); diff --git a/arch/arm64/kvm/hyp/Makefile b/arch/arm64/kvm/hyp/Makefile index 7462d3a8a6f26..fc09025d2e97d 100644 --- a/arch/arm64/kvm/hyp/Makefile +++ b/arch/arm64/kvm/hyp/Makefile @@ -14,7 +14,7 @@ obj-$(CONFIG_KVM) += hyp.o vhe/ nvhe/ obj-$(CONFIG_KVM_INDIRECT_VECTORS) += smccc_wa.o hyp-y := vgic-v3-sr.o timer-sr.o aarch32.o vgic-v2-cpuif-proxy.o sysreg-sr.o \ - debug-sr.o entry.o fpsimd.o + entry.o fpsimd.o # KVM code is run at a different exception code with a different map, so # compiler instrumentation that inserts callbacks or checks into the code may diff --git a/arch/arm64/kvm/hyp/debug-sr.c b/arch/arm64/kvm/hyp/include/hyp/debug-sr.h similarity index 71% rename from arch/arm64/kvm/hyp/debug-sr.c rename to arch/arm64/kvm/hyp/include/hyp/debug-sr.h index e95af204fec74..e041dbd23243f 100644 --- a/arch/arm64/kvm/hyp/debug-sr.c +++ b/arch/arm64/kvm/hyp/include/hyp/debug-sr.h @@ -4,6 +4,9 @@ * Author: Marc Zyngier */ +#ifndef __ARM64_KVM_HYP_DEBUG_SR_H__ +#define __ARM64_KVM_HYP_DEBUG_SR_H__ + #include #include @@ -85,53 +88,9 @@ default: write_debug(ptr[0], reg, 0); \ } -static void __hyp_text __debug_save_spe_nvhe(u64 *pmscr_el1) -{ - u64 reg; - - /* Clear pmscr in case of early return */ - *pmscr_el1 = 0; - - /* SPE present on this CPU? */ - if (!cpuid_feature_extract_unsigned_field(read_sysreg(id_aa64dfr0_el1), - ID_AA64DFR0_PMSVER_SHIFT)) - return; - - /* Yes; is it owned by EL3? */ - reg = read_sysreg_s(SYS_PMBIDR_EL1); - if (reg & BIT(SYS_PMBIDR_EL1_P_SHIFT)) - return; - - /* No; is the host actually using the thing? */ - reg = read_sysreg_s(SYS_PMBLIMITR_EL1); - if (!(reg & BIT(SYS_PMBLIMITR_EL1_E_SHIFT))) - return; - - /* Yes; save the control register and disable data generation */ - *pmscr_el1 = read_sysreg_s(SYS_PMSCR_EL1); - write_sysreg_s(0, SYS_PMSCR_EL1); - isb(); - - /* Now drain all buffered data to memory */ - psb_csync(); - dsb(nsh); -} - -static void __hyp_text __debug_restore_spe_nvhe(u64 pmscr_el1) -{ - if (!pmscr_el1) - return; - - /* The host page table is installed, but not yet synchronised */ - isb(); - - /* Re-enable data generation */ - write_sysreg_s(pmscr_el1, SYS_PMSCR_EL1); -} - -static void __hyp_text __debug_save_state(struct kvm_vcpu *vcpu, - struct kvm_guest_debug_arch *dbg, - struct kvm_cpu_context *ctxt) +static inline void __hyp_text __debug_save_state(struct kvm_vcpu *vcpu, + struct kvm_guest_debug_arch *dbg, + struct kvm_cpu_context *ctxt) { u64 aa64dfr0; int brps, wrps; @@ -148,9 +107,9 @@ static void __hyp_text __debug_save_state(struct kvm_vcpu *vcpu, ctxt->sys_regs[MDCCINT_EL1] = read_sysreg(mdccint_el1); } -static void __hyp_text __debug_restore_state(struct kvm_vcpu *vcpu, - struct kvm_guest_debug_arch *dbg, - struct kvm_cpu_context *ctxt) +static inline void __hyp_text __debug_restore_state(struct kvm_vcpu *vcpu, + struct kvm_guest_debug_arch *dbg, + struct kvm_cpu_context *ctxt) { u64 aa64dfr0; int brps, wrps; @@ -168,20 +127,13 @@ static void __hyp_text __debug_restore_state(struct kvm_vcpu *vcpu, write_sysreg(ctxt->sys_regs[MDCCINT_EL1], mdccint_el1); } -void __hyp_text __debug_switch_to_guest(struct kvm_vcpu *vcpu) +static inline void __hyp_text __debug_switch_to_guest_common(struct kvm_vcpu *vcpu) { struct kvm_cpu_context *host_ctxt; struct kvm_cpu_context *guest_ctxt; struct kvm_guest_debug_arch *host_dbg; struct kvm_guest_debug_arch *guest_dbg; - /* - * Non-VHE: Disable and flush SPE data generation - * VHE: The vcpu can run, but it can't hide. - */ - if (!has_vhe()) - __debug_save_spe_nvhe(&vcpu->arch.host_debug_state.pmscr_el1); - if (!(vcpu->arch.flags & KVM_ARM64_DEBUG_DIRTY)) return; @@ -194,16 +146,13 @@ void __hyp_text __debug_switch_to_guest(struct kvm_vcpu *vcpu) __debug_restore_state(vcpu, guest_dbg, guest_ctxt); } -void __hyp_text __debug_switch_to_host(struct kvm_vcpu *vcpu) +static inline void __hyp_text __debug_switch_to_host_common(struct kvm_vcpu *vcpu) { struct kvm_cpu_context *host_ctxt; struct kvm_cpu_context *guest_ctxt; struct kvm_guest_debug_arch *host_dbg; struct kvm_guest_debug_arch *guest_dbg; - if (!has_vhe()) - __debug_restore_spe_nvhe(vcpu->arch.host_debug_state.pmscr_el1); - if (!(vcpu->arch.flags & KVM_ARM64_DEBUG_DIRTY)) return; @@ -218,7 +167,4 @@ void __hyp_text __debug_switch_to_host(struct kvm_vcpu *vcpu) vcpu->arch.flags &= ~KVM_ARM64_DEBUG_DIRTY; } -u32 __hyp_text __kvm_get_mdcr_el2(void) -{ - return read_sysreg(mdcr_el2); -} +#endif /* __ARM64_KVM_HYP_DEBUG_SR_H__ */ diff --git a/arch/arm64/kvm/hyp/nvhe/Makefile b/arch/arm64/kvm/hyp/nvhe/Makefile index 8b3ac38eaa448..b3cb67b63d671 100644 --- a/arch/arm64/kvm/hyp/nvhe/Makefile +++ b/arch/arm64/kvm/hyp/nvhe/Makefile @@ -6,7 +6,7 @@ asflags-y := -D__KVM_NVHE_HYPERVISOR__ ccflags-y := -D__KVM_NVHE_HYPERVISOR__ -obj-y := switch.o tlb.o hyp-init.o ../hyp-entry.o +obj-y := debug-sr.o switch.o tlb.o hyp-init.o ../hyp-entry.o obj-y := $(patsubst %.o,%.hyp.o,$(obj-y)) extra-y := $(patsubst %.hyp.o,%.hyp.tmp.o,$(obj-y)) diff --git a/arch/arm64/kvm/hyp/nvhe/debug-sr.c b/arch/arm64/kvm/hyp/nvhe/debug-sr.c new file mode 100644 index 0000000000000..828c0d48e790d --- /dev/null +++ b/arch/arm64/kvm/hyp/nvhe/debug-sr.c @@ -0,0 +1,77 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2015 - ARM Ltd + * Author: Marc Zyngier + */ + +#include + +#include +#include + +#include +#include +#include +#include + +static void __hyp_text __debug_save_spe(u64 *pmscr_el1) +{ + u64 reg; + + /* Clear pmscr in case of early return */ + *pmscr_el1 = 0; + + /* SPE present on this CPU? */ + if (!cpuid_feature_extract_unsigned_field(read_sysreg(id_aa64dfr0_el1), + ID_AA64DFR0_PMSVER_SHIFT)) + return; + + /* Yes; is it owned by EL3? */ + reg = read_sysreg_s(SYS_PMBIDR_EL1); + if (reg & BIT(SYS_PMBIDR_EL1_P_SHIFT)) + return; + + /* No; is the host actually using the thing? */ + reg = read_sysreg_s(SYS_PMBLIMITR_EL1); + if (!(reg & BIT(SYS_PMBLIMITR_EL1_E_SHIFT))) + return; + + /* Yes; save the control register and disable data generation */ + *pmscr_el1 = read_sysreg_s(SYS_PMSCR_EL1); + write_sysreg_s(0, SYS_PMSCR_EL1); + isb(); + + /* Now drain all buffered data to memory */ + psb_csync(); + dsb(nsh); +} + +static void __hyp_text __debug_restore_spe(u64 pmscr_el1) +{ + if (!pmscr_el1) + return; + + /* The host page table is installed, but not yet synchronised */ + isb(); + + /* Re-enable data generation */ + write_sysreg_s(pmscr_el1, SYS_PMSCR_EL1); +} + +void __hyp_text __debug_switch_to_guest(struct kvm_vcpu *vcpu) +{ + /* Disable and flush SPE data generation */ + __debug_save_spe(&vcpu->arch.host_debug_state.pmscr_el1); + __debug_switch_to_guest_common(vcpu); +} + +void __hyp_text __debug_switch_to_host(struct kvm_vcpu *vcpu) +{ + __debug_restore_spe(vcpu->arch.host_debug_state.pmscr_el1); + __debug_switch_to_host_common(vcpu); +} + +u32 __hyp_text __kvm_get_mdcr_el2(void) +{ + return read_sysreg(mdcr_el2); +} diff --git a/arch/arm64/kvm/hyp/vhe/Makefile b/arch/arm64/kvm/hyp/vhe/Makefile index 9f71cd3ba50d1..62bdaf272b03a 100644 --- a/arch/arm64/kvm/hyp/vhe/Makefile +++ b/arch/arm64/kvm/hyp/vhe/Makefile @@ -6,7 +6,7 @@ asflags-y := -D__KVM_VHE_HYPERVISOR__ ccflags-y := -D__KVM_VHE_HYPERVISOR__ -obj-y := switch.o tlb.o ../hyp-entry.o +obj-y := debug-sr.o switch.o tlb.o ../hyp-entry.o # KVM code is run at a different exception code with a different map, so # compiler instrumentation that inserts callbacks or checks into the code may diff --git a/arch/arm64/kvm/hyp/vhe/debug-sr.c b/arch/arm64/kvm/hyp/vhe/debug-sr.c new file mode 100644 index 0000000000000..f1e2e5a00933d --- /dev/null +++ b/arch/arm64/kvm/hyp/vhe/debug-sr.c @@ -0,0 +1,26 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2015 - ARM Ltd + * Author: Marc Zyngier + */ + +#include + +#include + +#include + +void __debug_switch_to_guest(struct kvm_vcpu *vcpu) +{ + __debug_switch_to_guest_common(vcpu); +} + +void __debug_switch_to_host(struct kvm_vcpu *vcpu) +{ + __debug_switch_to_host_common(vcpu); +} + +u32 __kvm_get_mdcr_el2(void) +{ + return read_sysreg(mdcr_el2); +} -- GitLab From 13aeb9b400c5d7c5e979fdbbf994c787487f7889 Mon Sep 17 00:00:00 2001 From: David Brazdil Date: Thu, 25 Jun 2020 14:14:16 +0100 Subject: [PATCH 0169/2249] KVM: arm64: Split hyp/sysreg-sr.c to VHE/nVHE sysreg-sr.c contains KVM's code for saving/restoring system registers, with some code shared between VHE/nVHE. These common routines are moved to a header file, VHE-specific code is moved to vhe/sysreg-sr.c and nVHE-specific code to nvhe/sysreg-sr.c. Signed-off-by: David Brazdil Signed-off-by: Marc Zyngier Link: https://lore.kernel.org/r/20200625131420.71444-12-dbrazdil@google.com --- arch/arm64/include/asm/kvm_host.h | 6 +- arch/arm64/include/asm/kvm_hyp.h | 5 +- arch/arm64/kernel/image-vars.h | 7 - arch/arm64/kvm/arm.c | 8 +- arch/arm64/kvm/hyp/Makefile | 4 +- .../{sysreg-sr.c => include/hyp/sysreg-sr.h} | 158 ++---------------- arch/arm64/kvm/hyp/nvhe/Makefile | 2 +- arch/arm64/kvm/hyp/nvhe/switch.c | 1 + arch/arm64/kvm/hyp/nvhe/sysreg-sr.c | 46 +++++ arch/arm64/kvm/hyp/vhe/Makefile | 2 +- arch/arm64/kvm/hyp/vhe/switch.c | 2 +- arch/arm64/kvm/hyp/vhe/sysreg-sr.c | 114 +++++++++++++ 12 files changed, 191 insertions(+), 164 deletions(-) rename arch/arm64/kvm/hyp/{sysreg-sr.c => include/hyp/sysreg-sr.h} (56%) create mode 100644 arch/arm64/kvm/hyp/nvhe/sysreg-sr.c create mode 100644 arch/arm64/kvm/hyp/vhe/sysreg-sr.c diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h index 49d1a5cd8f8f4..e0920df1d0c14 100644 --- a/arch/arm64/include/asm/kvm_host.h +++ b/arch/arm64/include/asm/kvm_host.h @@ -338,7 +338,7 @@ struct kvm_vcpu_arch { struct vcpu_reset_state reset_state; /* True when deferrable sysregs are loaded on the physical CPU, - * see kvm_vcpu_load_sysregs and kvm_vcpu_put_sysregs. */ + * see kvm_vcpu_load_sysregs_vhe and kvm_vcpu_put_sysregs_vhe. */ bool sysregs_loaded_on_cpu; /* Guest PV state */ @@ -639,8 +639,8 @@ static inline int kvm_arm_have_ssbd(void) } } -void kvm_vcpu_load_sysregs(struct kvm_vcpu *vcpu); -void kvm_vcpu_put_sysregs(struct kvm_vcpu *vcpu); +void kvm_vcpu_load_sysregs_vhe(struct kvm_vcpu *vcpu); +void kvm_vcpu_put_sysregs_vhe(struct kvm_vcpu *vcpu); int kvm_set_ipa_limit(void); diff --git a/arch/arm64/include/asm/kvm_hyp.h b/arch/arm64/include/asm/kvm_hyp.h index 82fa05d15b8bd..997c5bda1ac79 100644 --- a/arch/arm64/include/asm/kvm_hyp.h +++ b/arch/arm64/include/asm/kvm_hyp.h @@ -66,14 +66,15 @@ int __vgic_v3_perform_cpuif_access(struct kvm_vcpu *vcpu); void __timer_enable_traps(struct kvm_vcpu *vcpu); void __timer_disable_traps(struct kvm_vcpu *vcpu); +#ifdef __KVM_NVHE_HYPERVISOR__ void __sysreg_save_state_nvhe(struct kvm_cpu_context *ctxt); void __sysreg_restore_state_nvhe(struct kvm_cpu_context *ctxt); +#else void sysreg_save_host_state_vhe(struct kvm_cpu_context *ctxt); void sysreg_restore_host_state_vhe(struct kvm_cpu_context *ctxt); void sysreg_save_guest_state_vhe(struct kvm_cpu_context *ctxt); void sysreg_restore_guest_state_vhe(struct kvm_cpu_context *ctxt); -void __sysreg32_save_state(struct kvm_vcpu *vcpu); -void __sysreg32_restore_state(struct kvm_vcpu *vcpu); +#endif void __debug_switch_to_guest(struct kvm_vcpu *vcpu); void __debug_switch_to_host(struct kvm_vcpu *vcpu); diff --git a/arch/arm64/kernel/image-vars.h b/arch/arm64/kernel/image-vars.h index c44ca4e7dd663..59eb55893eaf6 100644 --- a/arch/arm64/kernel/image-vars.h +++ b/arch/arm64/kernel/image-vars.h @@ -76,13 +76,6 @@ KVM_NVHE_ALIAS(abort_guest_exit_start); KVM_NVHE_ALIAS(__fpsimd_restore_state); KVM_NVHE_ALIAS(__fpsimd_save_state); -/* Symbols defined in sysreg-sr.c (not yet compiled with nVHE build rules). */ -KVM_NVHE_ALIAS(__kvm_enable_ssbs); -KVM_NVHE_ALIAS(__sysreg32_restore_state); -KVM_NVHE_ALIAS(__sysreg32_save_state); -KVM_NVHE_ALIAS(__sysreg_restore_state_nvhe); -KVM_NVHE_ALIAS(__sysreg_save_state_nvhe); - /* Symbols defined in timer-sr.c (not yet compiled with nVHE build rules). */ KVM_NVHE_ALIAS(__kvm_timer_set_cntvoff); KVM_NVHE_ALIAS(__timer_disable_traps); diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c index 26780b78a523f..0bf2cf5614c6b 100644 --- a/arch/arm64/kvm/arm.c +++ b/arch/arm64/kvm/arm.c @@ -351,7 +351,8 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu) kvm_vgic_load(vcpu); kvm_timer_vcpu_load(vcpu); - kvm_vcpu_load_sysregs(vcpu); + if (has_vhe()) + kvm_vcpu_load_sysregs_vhe(vcpu); kvm_arch_vcpu_load_fp(vcpu); kvm_vcpu_pmu_restore_guest(vcpu); if (kvm_arm_is_pvtime_enabled(&vcpu->arch)) @@ -369,7 +370,8 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu) void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu) { kvm_arch_vcpu_put_fp(vcpu); - kvm_vcpu_put_sysregs(vcpu); + if (has_vhe()) + kvm_vcpu_put_sysregs_vhe(vcpu); kvm_timer_vcpu_put(vcpu); kvm_vgic_put(vcpu); kvm_vcpu_pmu_restore_host(vcpu); @@ -1302,7 +1304,7 @@ static void cpu_init_hyp_mode(void) */ if (this_cpu_has_cap(ARM64_SSBS) && arm64_get_ssbd_state() == ARM64_SSBD_FORCE_DISABLE) { - kvm_call_hyp(__kvm_enable_ssbs); + kvm_call_hyp_nvhe(__kvm_enable_ssbs); } } diff --git a/arch/arm64/kvm/hyp/Makefile b/arch/arm64/kvm/hyp/Makefile index fc09025d2e97d..f497972378183 100644 --- a/arch/arm64/kvm/hyp/Makefile +++ b/arch/arm64/kvm/hyp/Makefile @@ -13,8 +13,8 @@ subdir-ccflags-y := -I$(incdir) \ obj-$(CONFIG_KVM) += hyp.o vhe/ nvhe/ obj-$(CONFIG_KVM_INDIRECT_VECTORS) += smccc_wa.o -hyp-y := vgic-v3-sr.o timer-sr.o aarch32.o vgic-v2-cpuif-proxy.o sysreg-sr.o \ - entry.o fpsimd.o +hyp-y := vgic-v3-sr.o timer-sr.o aarch32.o vgic-v2-cpuif-proxy.o entry.o \ + fpsimd.o # KVM code is run at a different exception code with a different map, so # compiler instrumentation that inserts callbacks or checks into the code may diff --git a/arch/arm64/kvm/hyp/sysreg-sr.c b/arch/arm64/kvm/hyp/include/hyp/sysreg-sr.h similarity index 56% rename from arch/arm64/kvm/hyp/sysreg-sr.c rename to arch/arm64/kvm/hyp/include/hyp/sysreg-sr.h index 2493439a5c548..3e0585fbd4032 100644 --- a/arch/arm64/kvm/hyp/sysreg-sr.c +++ b/arch/arm64/kvm/hyp/include/hyp/sysreg-sr.h @@ -4,6 +4,9 @@ * Author: Marc Zyngier */ +#ifndef __ARM64_KVM_HYP_SYSREG_SR_H__ +#define __ARM64_KVM_HYP_SYSREG_SR_H__ + #include #include @@ -12,30 +15,18 @@ #include #include -/* - * Non-VHE: Both host and guest must save everything. - * - * VHE: Host and guest must save mdscr_el1 and sp_el0 (and the PC and - * pstate, which are handled as part of the el2 return state) on every - * switch (sp_el0 is being dealt with in the assembly code). - * tpidr_el0 and tpidrro_el0 only need to be switched when going - * to host userspace or a different VCPU. EL1 registers only need to be - * switched when potentially going to run a different VCPU. The latter two - * classes are handled as part of kvm_arch_vcpu_load and kvm_arch_vcpu_put. - */ - -static void __hyp_text __sysreg_save_common_state(struct kvm_cpu_context *ctxt) +static inline void __hyp_text __sysreg_save_common_state(struct kvm_cpu_context *ctxt) { ctxt->sys_regs[MDSCR_EL1] = read_sysreg(mdscr_el1); } -static void __hyp_text __sysreg_save_user_state(struct kvm_cpu_context *ctxt) +static inline void __hyp_text __sysreg_save_user_state(struct kvm_cpu_context *ctxt) { ctxt->sys_regs[TPIDR_EL0] = read_sysreg(tpidr_el0); ctxt->sys_regs[TPIDRRO_EL0] = read_sysreg(tpidrro_el0); } -static void __hyp_text __sysreg_save_el1_state(struct kvm_cpu_context *ctxt) +static inline void __hyp_text __sysreg_save_el1_state(struct kvm_cpu_context *ctxt) { ctxt->sys_regs[CSSELR_EL1] = read_sysreg(csselr_el1); ctxt->sys_regs[SCTLR_EL1] = read_sysreg_el1(SYS_SCTLR); @@ -60,7 +51,7 @@ static void __hyp_text __sysreg_save_el1_state(struct kvm_cpu_context *ctxt) ctxt->gp_regs.spsr[KVM_SPSR_EL1]= read_sysreg_el1(SYS_SPSR); } -static void __hyp_text __sysreg_save_el2_return_state(struct kvm_cpu_context *ctxt) +static inline void __hyp_text __sysreg_save_el2_return_state(struct kvm_cpu_context *ctxt) { ctxt->gp_regs.regs.pc = read_sysreg_el2(SYS_ELR); ctxt->gp_regs.regs.pstate = read_sysreg_el2(SYS_SPSR); @@ -69,39 +60,18 @@ static void __hyp_text __sysreg_save_el2_return_state(struct kvm_cpu_context *ct ctxt->sys_regs[DISR_EL1] = read_sysreg_s(SYS_VDISR_EL2); } -void __hyp_text __sysreg_save_state_nvhe(struct kvm_cpu_context *ctxt) -{ - __sysreg_save_el1_state(ctxt); - __sysreg_save_common_state(ctxt); - __sysreg_save_user_state(ctxt); - __sysreg_save_el2_return_state(ctxt); -} - -void sysreg_save_host_state_vhe(struct kvm_cpu_context *ctxt) -{ - __sysreg_save_common_state(ctxt); -} -NOKPROBE_SYMBOL(sysreg_save_host_state_vhe); - -void sysreg_save_guest_state_vhe(struct kvm_cpu_context *ctxt) -{ - __sysreg_save_common_state(ctxt); - __sysreg_save_el2_return_state(ctxt); -} -NOKPROBE_SYMBOL(sysreg_save_guest_state_vhe); - -static void __hyp_text __sysreg_restore_common_state(struct kvm_cpu_context *ctxt) +static inline void __hyp_text __sysreg_restore_common_state(struct kvm_cpu_context *ctxt) { write_sysreg(ctxt->sys_regs[MDSCR_EL1], mdscr_el1); } -static void __hyp_text __sysreg_restore_user_state(struct kvm_cpu_context *ctxt) +static inline void __hyp_text __sysreg_restore_user_state(struct kvm_cpu_context *ctxt) { 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) +static inline 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); @@ -160,8 +130,7 @@ static void __hyp_text __sysreg_restore_el1_state(struct kvm_cpu_context *ctxt) write_sysreg_el1(ctxt->gp_regs.spsr[KVM_SPSR_EL1],SYS_SPSR); } -static void __hyp_text -__sysreg_restore_el2_return_state(struct kvm_cpu_context *ctxt) +static inline void __hyp_text __sysreg_restore_el2_return_state(struct kvm_cpu_context *ctxt) { u64 pstate = ctxt->gp_regs.regs.pstate; u64 mode = pstate & PSR_AA32_MODE_MASK; @@ -187,28 +156,7 @@ __sysreg_restore_el2_return_state(struct kvm_cpu_context *ctxt) write_sysreg_s(ctxt->sys_regs[DISR_EL1], SYS_VDISR_EL2); } -void __hyp_text __sysreg_restore_state_nvhe(struct kvm_cpu_context *ctxt) -{ - __sysreg_restore_el1_state(ctxt); - __sysreg_restore_common_state(ctxt); - __sysreg_restore_user_state(ctxt); - __sysreg_restore_el2_return_state(ctxt); -} - -void sysreg_restore_host_state_vhe(struct kvm_cpu_context *ctxt) -{ - __sysreg_restore_common_state(ctxt); -} -NOKPROBE_SYMBOL(sysreg_restore_host_state_vhe); - -void sysreg_restore_guest_state_vhe(struct kvm_cpu_context *ctxt) -{ - __sysreg_restore_common_state(ctxt); - __sysreg_restore_el2_return_state(ctxt); -} -NOKPROBE_SYMBOL(sysreg_restore_guest_state_vhe); - -void __hyp_text __sysreg32_save_state(struct kvm_vcpu *vcpu) +static inline void __hyp_text __sysreg32_save_state(struct kvm_vcpu *vcpu) { u64 *spsr, *sysreg; @@ -230,7 +178,7 @@ void __hyp_text __sysreg32_save_state(struct kvm_vcpu *vcpu) sysreg[DBGVCR32_EL2] = read_sysreg(dbgvcr32_el2); } -void __hyp_text __sysreg32_restore_state(struct kvm_vcpu *vcpu) +static inline void __hyp_text __sysreg32_restore_state(struct kvm_vcpu *vcpu) { u64 *spsr, *sysreg; @@ -252,82 +200,4 @@ void __hyp_text __sysreg32_restore_state(struct kvm_vcpu *vcpu) write_sysreg(sysreg[DBGVCR32_EL2], dbgvcr32_el2); } -/** - * kvm_vcpu_load_sysregs - Load guest system registers to the physical CPU - * - * @vcpu: The VCPU pointer - * - * Load system registers that do not affect the host's execution, for - * example EL1 system registers on a VHE system where the host kernel - * runs at EL2. This function is called from KVM's vcpu_load() function - * and loading system register state early avoids having to load them on - * every entry to the VM. - */ -void kvm_vcpu_load_sysregs(struct kvm_vcpu *vcpu) -{ - struct kvm_cpu_context *guest_ctxt = &vcpu->arch.ctxt; - struct kvm_cpu_context *host_ctxt; - - if (!has_vhe()) - return; - - host_ctxt = &__hyp_this_cpu_ptr(kvm_host_data)->host_ctxt; - __sysreg_save_user_state(host_ctxt); - - /* - * Load guest EL1 and user state - * - * 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_user_state(guest_ctxt); - __sysreg_restore_el1_state(guest_ctxt); - - vcpu->arch.sysregs_loaded_on_cpu = true; - - activate_traps_vhe_load(vcpu); -} - -/** - * kvm_vcpu_put_sysregs - Restore host system registers to the physical CPU - * - * @vcpu: The VCPU pointer - * - * Save guest system registers that do not affect the host's execution, for - * example EL1 system registers on a VHE system where the host kernel - * runs at EL2. This function is called from KVM's vcpu_put() function - * and deferring saving system register state until we're no longer running the - * VCPU avoids having to save them on every exit from the VM. - */ -void kvm_vcpu_put_sysregs(struct kvm_vcpu *vcpu) -{ - struct kvm_cpu_context *guest_ctxt = &vcpu->arch.ctxt; - struct kvm_cpu_context *host_ctxt; - - if (!has_vhe()) - return; - - host_ctxt = &__hyp_this_cpu_ptr(kvm_host_data)->host_ctxt; - deactivate_traps_vhe_put(); - - __sysreg_save_el1_state(guest_ctxt); - __sysreg_save_user_state(guest_ctxt); - __sysreg32_save_state(vcpu); - - /* Restore host user state */ - __sysreg_restore_user_state(host_ctxt); - - vcpu->arch.sysregs_loaded_on_cpu = false; -} - -void __hyp_text __kvm_enable_ssbs(void) -{ - u64 tmp; - - asm volatile( - "mrs %0, sctlr_el2\n" - "orr %0, %0, %1\n" - "msr sctlr_el2, %0" - : "=&r" (tmp) : "L" (SCTLR_ELx_DSSBS)); -} +#endif /* __ARM64_KVM_HYP_SYSREG_SR_H__ */ diff --git a/arch/arm64/kvm/hyp/nvhe/Makefile b/arch/arm64/kvm/hyp/nvhe/Makefile index b3cb67b63d671..61a8160f0dd94 100644 --- a/arch/arm64/kvm/hyp/nvhe/Makefile +++ b/arch/arm64/kvm/hyp/nvhe/Makefile @@ -6,7 +6,7 @@ asflags-y := -D__KVM_NVHE_HYPERVISOR__ ccflags-y := -D__KVM_NVHE_HYPERVISOR__ -obj-y := debug-sr.o switch.o tlb.o hyp-init.o ../hyp-entry.o +obj-y := sysreg-sr.o debug-sr.o switch.o tlb.o hyp-init.o ../hyp-entry.o obj-y := $(patsubst %.o,%.hyp.o,$(obj-y)) extra-y := $(patsubst %.hyp.o,%.hyp.tmp.o,$(obj-y)) diff --git a/arch/arm64/kvm/hyp/nvhe/switch.c b/arch/arm64/kvm/hyp/nvhe/switch.c index 7f6b8d3dc637a..f08bfb951df60 100644 --- a/arch/arm64/kvm/hyp/nvhe/switch.c +++ b/arch/arm64/kvm/hyp/nvhe/switch.c @@ -5,6 +5,7 @@ */ #include +#include #include #include diff --git a/arch/arm64/kvm/hyp/nvhe/sysreg-sr.c b/arch/arm64/kvm/hyp/nvhe/sysreg-sr.c new file mode 100644 index 0000000000000..710cf28ab1ec9 --- /dev/null +++ b/arch/arm64/kvm/hyp/nvhe/sysreg-sr.c @@ -0,0 +1,46 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2012-2015 - ARM Ltd + * Author: Marc Zyngier + */ + +#include + +#include +#include + +#include +#include +#include +#include + +/* + * Non-VHE: Both host and guest must save everything. + */ + +void __hyp_text __sysreg_save_state_nvhe(struct kvm_cpu_context *ctxt) +{ + __sysreg_save_el1_state(ctxt); + __sysreg_save_common_state(ctxt); + __sysreg_save_user_state(ctxt); + __sysreg_save_el2_return_state(ctxt); +} + +void __hyp_text __sysreg_restore_state_nvhe(struct kvm_cpu_context *ctxt) +{ + __sysreg_restore_el1_state(ctxt); + __sysreg_restore_common_state(ctxt); + __sysreg_restore_user_state(ctxt); + __sysreg_restore_el2_return_state(ctxt); +} + +void __hyp_text __kvm_enable_ssbs(void) +{ + u64 tmp; + + asm volatile( + "mrs %0, sctlr_el2\n" + "orr %0, %0, %1\n" + "msr sctlr_el2, %0" + : "=&r" (tmp) : "L" (SCTLR_ELx_DSSBS)); +} diff --git a/arch/arm64/kvm/hyp/vhe/Makefile b/arch/arm64/kvm/hyp/vhe/Makefile index 62bdaf272b03a..2801582a739a5 100644 --- a/arch/arm64/kvm/hyp/vhe/Makefile +++ b/arch/arm64/kvm/hyp/vhe/Makefile @@ -6,7 +6,7 @@ asflags-y := -D__KVM_VHE_HYPERVISOR__ ccflags-y := -D__KVM_VHE_HYPERVISOR__ -obj-y := debug-sr.o switch.o tlb.o ../hyp-entry.o +obj-y := sysreg-sr.o debug-sr.o switch.o tlb.o ../hyp-entry.o # KVM code is run at a different exception code with a different map, so # compiler instrumentation that inserts callbacks or checks into the code may diff --git a/arch/arm64/kvm/hyp/vhe/switch.c b/arch/arm64/kvm/hyp/vhe/switch.c index e8d76cab44e43..c0d33deba77e6 100644 --- a/arch/arm64/kvm/hyp/vhe/switch.c +++ b/arch/arm64/kvm/hyp/vhe/switch.c @@ -120,7 +120,7 @@ static int __kvm_vcpu_run_vhe(struct kvm_vcpu *vcpu) * HCR_EL2.TGE. * * We have already configured the guest's stage 1 translation in - * kvm_vcpu_load_sysregs above. We must now call __activate_vm + * kvm_vcpu_load_sysregs_vhe above. We must now call __activate_vm * before __activate_traps, because __activate_vm configures * stage 2 translation, and __activate_traps clear HCR_EL2.TGE * (among other things). diff --git a/arch/arm64/kvm/hyp/vhe/sysreg-sr.c b/arch/arm64/kvm/hyp/vhe/sysreg-sr.c new file mode 100644 index 0000000000000..996471e4c1380 --- /dev/null +++ b/arch/arm64/kvm/hyp/vhe/sysreg-sr.c @@ -0,0 +1,114 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2012-2015 - ARM Ltd + * Author: Marc Zyngier + */ + +#include + +#include +#include + +#include +#include +#include +#include + +/* + * VHE: Host and guest must save mdscr_el1 and sp_el0 (and the PC and + * pstate, which are handled as part of the el2 return state) on every + * switch (sp_el0 is being dealt with in the assembly code). + * tpidr_el0 and tpidrro_el0 only need to be switched when going + * to host userspace or a different VCPU. EL1 registers only need to be + * switched when potentially going to run a different VCPU. The latter two + * classes are handled as part of kvm_arch_vcpu_load and kvm_arch_vcpu_put. + */ + +void sysreg_save_host_state_vhe(struct kvm_cpu_context *ctxt) +{ + __sysreg_save_common_state(ctxt); +} +NOKPROBE_SYMBOL(sysreg_save_host_state_vhe); + +void sysreg_save_guest_state_vhe(struct kvm_cpu_context *ctxt) +{ + __sysreg_save_common_state(ctxt); + __sysreg_save_el2_return_state(ctxt); +} +NOKPROBE_SYMBOL(sysreg_save_guest_state_vhe); + +void sysreg_restore_host_state_vhe(struct kvm_cpu_context *ctxt) +{ + __sysreg_restore_common_state(ctxt); +} +NOKPROBE_SYMBOL(sysreg_restore_host_state_vhe); + +void sysreg_restore_guest_state_vhe(struct kvm_cpu_context *ctxt) +{ + __sysreg_restore_common_state(ctxt); + __sysreg_restore_el2_return_state(ctxt); +} +NOKPROBE_SYMBOL(sysreg_restore_guest_state_vhe); + +/** + * kvm_vcpu_load_sysregs_vhe - Load guest system registers to the physical CPU + * + * @vcpu: The VCPU pointer + * + * Load system registers that do not affect the host's execution, for + * example EL1 system registers on a VHE system where the host kernel + * runs at EL2. This function is called from KVM's vcpu_load() function + * and loading system register state early avoids having to load them on + * every entry to the VM. + */ +void kvm_vcpu_load_sysregs_vhe(struct kvm_vcpu *vcpu) +{ + struct kvm_cpu_context *guest_ctxt = &vcpu->arch.ctxt; + struct kvm_cpu_context *host_ctxt; + + host_ctxt = &__hyp_this_cpu_ptr(kvm_host_data)->host_ctxt; + __sysreg_save_user_state(host_ctxt); + + /* + * Load guest EL1 and user state + * + * 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_user_state(guest_ctxt); + __sysreg_restore_el1_state(guest_ctxt); + + vcpu->arch.sysregs_loaded_on_cpu = true; + + activate_traps_vhe_load(vcpu); +} + +/** + * kvm_vcpu_put_sysregs_vhe - Restore host system registers to the physical CPU + * + * @vcpu: The VCPU pointer + * + * Save guest system registers that do not affect the host's execution, for + * example EL1 system registers on a VHE system where the host kernel + * runs at EL2. This function is called from KVM's vcpu_put() function + * and deferring saving system register state until we're no longer running the + * VCPU avoids having to save them on every exit from the VM. + */ +void kvm_vcpu_put_sysregs_vhe(struct kvm_vcpu *vcpu) +{ + struct kvm_cpu_context *guest_ctxt = &vcpu->arch.ctxt; + struct kvm_cpu_context *host_ctxt; + + host_ctxt = &__hyp_this_cpu_ptr(kvm_host_data)->host_ctxt; + deactivate_traps_vhe_put(); + + __sysreg_save_el1_state(guest_ctxt); + __sysreg_save_user_state(guest_ctxt); + __sysreg32_save_state(vcpu); + + /* Restore host user state */ + __sysreg_restore_user_state(host_ctxt); + + vcpu->arch.sysregs_loaded_on_cpu = false; +} -- GitLab From 9aebdea494b5d2d5fe0ba54d71e9d6c5acfe76b4 Mon Sep 17 00:00:00 2001 From: David Brazdil Date: Thu, 25 Jun 2020 14:14:17 +0100 Subject: [PATCH 0170/2249] KVM: arm64: Duplicate hyp/timer-sr.c for VHE/nVHE timer-sr.c contains a HVC handler for setting CNTVOFF_EL2 and two helper functions for controlling access to physical counter. The former is used by both VHE/nVHE and is duplicated, the latter are used only by nVHE and moved to nvhe/timer-sr.c. Signed-off-by: David Brazdil Signed-off-by: Marc Zyngier Link: https://lore.kernel.org/r/20200625131420.71444-13-dbrazdil@google.com --- arch/arm64/include/asm/kvm_hyp.h | 2 ++ arch/arm64/kernel/image-vars.h | 5 ----- arch/arm64/kvm/hyp/Makefile | 2 +- arch/arm64/kvm/hyp/nvhe/Makefile | 3 ++- arch/arm64/kvm/hyp/{ => nvhe}/timer-sr.c | 2 +- arch/arm64/kvm/hyp/vhe/Makefile | 2 +- arch/arm64/kvm/hyp/vhe/timer-sr.c | 12 ++++++++++++ 7 files changed, 19 insertions(+), 9 deletions(-) rename arch/arm64/kvm/hyp/{ => nvhe}/timer-sr.c (95%) create mode 100644 arch/arm64/kvm/hyp/vhe/timer-sr.c diff --git a/arch/arm64/include/asm/kvm_hyp.h b/arch/arm64/include/asm/kvm_hyp.h index 997c5bda1ac79..19f8b40fe6cf1 100644 --- a/arch/arm64/include/asm/kvm_hyp.h +++ b/arch/arm64/include/asm/kvm_hyp.h @@ -63,8 +63,10 @@ void __vgic_v3_save_aprs(struct vgic_v3_cpu_if *cpu_if); void __vgic_v3_restore_aprs(struct vgic_v3_cpu_if *cpu_if); int __vgic_v3_perform_cpuif_access(struct kvm_vcpu *vcpu); +#ifdef __KVM_NVHE_HYPERVISOR__ void __timer_enable_traps(struct kvm_vcpu *vcpu); void __timer_disable_traps(struct kvm_vcpu *vcpu); +#endif #ifdef __KVM_NVHE_HYPERVISOR__ void __sysreg_save_state_nvhe(struct kvm_cpu_context *ctxt); diff --git a/arch/arm64/kernel/image-vars.h b/arch/arm64/kernel/image-vars.h index 59eb55893eaf6..2757d3512704f 100644 --- a/arch/arm64/kernel/image-vars.h +++ b/arch/arm64/kernel/image-vars.h @@ -76,11 +76,6 @@ KVM_NVHE_ALIAS(abort_guest_exit_start); KVM_NVHE_ALIAS(__fpsimd_restore_state); KVM_NVHE_ALIAS(__fpsimd_save_state); -/* Symbols defined in timer-sr.c (not yet compiled with nVHE build rules). */ -KVM_NVHE_ALIAS(__kvm_timer_set_cntvoff); -KVM_NVHE_ALIAS(__timer_disable_traps); -KVM_NVHE_ALIAS(__timer_enable_traps); - /* Symbols defined in vgic-v2-cpuif-proxy.c (not yet compiled with nVHE build rules). */ KVM_NVHE_ALIAS(__vgic_v2_perform_cpuif_access); diff --git a/arch/arm64/kvm/hyp/Makefile b/arch/arm64/kvm/hyp/Makefile index f497972378183..ef1aa7fe8f5ad 100644 --- a/arch/arm64/kvm/hyp/Makefile +++ b/arch/arm64/kvm/hyp/Makefile @@ -13,7 +13,7 @@ subdir-ccflags-y := -I$(incdir) \ obj-$(CONFIG_KVM) += hyp.o vhe/ nvhe/ obj-$(CONFIG_KVM_INDIRECT_VECTORS) += smccc_wa.o -hyp-y := vgic-v3-sr.o timer-sr.o aarch32.o vgic-v2-cpuif-proxy.o entry.o \ +hyp-y := vgic-v3-sr.o aarch32.o vgic-v2-cpuif-proxy.o entry.o \ fpsimd.o # KVM code is run at a different exception code with a different map, so diff --git a/arch/arm64/kvm/hyp/nvhe/Makefile b/arch/arm64/kvm/hyp/nvhe/Makefile index 61a8160f0dd94..0f4c544f07dbc 100644 --- a/arch/arm64/kvm/hyp/nvhe/Makefile +++ b/arch/arm64/kvm/hyp/nvhe/Makefile @@ -6,7 +6,8 @@ asflags-y := -D__KVM_NVHE_HYPERVISOR__ ccflags-y := -D__KVM_NVHE_HYPERVISOR__ -obj-y := sysreg-sr.o debug-sr.o switch.o tlb.o hyp-init.o ../hyp-entry.o +obj-y := timer-sr.o sysreg-sr.o debug-sr.o switch.o tlb.o hyp-init.o \ + ../hyp-entry.o obj-y := $(patsubst %.o,%.hyp.o,$(obj-y)) extra-y := $(patsubst %.hyp.o,%.hyp.tmp.o,$(obj-y)) diff --git a/arch/arm64/kvm/hyp/timer-sr.c b/arch/arm64/kvm/hyp/nvhe/timer-sr.c similarity index 95% rename from arch/arm64/kvm/hyp/timer-sr.c rename to arch/arm64/kvm/hyp/nvhe/timer-sr.c index fb5c0be332237..42c8ed71d06ee 100644 --- a/arch/arm64/kvm/hyp/timer-sr.c +++ b/arch/arm64/kvm/hyp/nvhe/timer-sr.c @@ -10,7 +10,7 @@ #include -void __hyp_text __kvm_timer_set_cntvoff(u64 cntvoff) +void __kvm_timer_set_cntvoff(u64 cntvoff) { write_sysreg(cntvoff, cntvoff_el2); } diff --git a/arch/arm64/kvm/hyp/vhe/Makefile b/arch/arm64/kvm/hyp/vhe/Makefile index 2801582a739a5..a1dbbc5409bd4 100644 --- a/arch/arm64/kvm/hyp/vhe/Makefile +++ b/arch/arm64/kvm/hyp/vhe/Makefile @@ -6,7 +6,7 @@ asflags-y := -D__KVM_VHE_HYPERVISOR__ ccflags-y := -D__KVM_VHE_HYPERVISOR__ -obj-y := sysreg-sr.o debug-sr.o switch.o tlb.o ../hyp-entry.o +obj-y := timer-sr.o sysreg-sr.o debug-sr.o switch.o tlb.o ../hyp-entry.o # KVM code is run at a different exception code with a different map, so # compiler instrumentation that inserts callbacks or checks into the code may diff --git a/arch/arm64/kvm/hyp/vhe/timer-sr.c b/arch/arm64/kvm/hyp/vhe/timer-sr.c new file mode 100644 index 0000000000000..4cda674a8be65 --- /dev/null +++ b/arch/arm64/kvm/hyp/vhe/timer-sr.c @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2012-2015 - ARM Ltd + * Author: Marc Zyngier + */ + +#include + +void __kvm_timer_set_cntvoff(u64 cntvoff) +{ + write_sysreg(cntvoff, cntvoff_el2); +} -- GitLab From c04dd455eb311d2d289c9d81d080eaf11a06cebf Mon Sep 17 00:00:00 2001 From: David Brazdil Date: Thu, 25 Jun 2020 14:14:18 +0100 Subject: [PATCH 0171/2249] KVM: arm64: Compile remaining hyp/ files for both VHE/nVHE The following files in hyp/ contain only code shared by VHE/nVHE: vgic-v3-sr.c, aarch32.c, vgic-v2-cpuif-proxy.c, entry.S, fpsimd.S Compile them under both configurations. Deletions in image-vars.h reflect eliminated dependencies of nVHE code on the rest of the kernel. Signed-off-by: David Brazdil Signed-off-by: Marc Zyngier Link: https://lore.kernel.org/r/20200625131420.71444-14-dbrazdil@google.com --- arch/arm64/kernel/image-vars.h | 29 ----------------------------- arch/arm64/kvm/hyp/Makefile | 13 +------------ arch/arm64/kvm/hyp/nvhe/Makefile | 5 +++-- arch/arm64/kvm/hyp/vhe/Makefile | 4 +++- 4 files changed, 7 insertions(+), 44 deletions(-) diff --git a/arch/arm64/kernel/image-vars.h b/arch/arm64/kernel/image-vars.h index 2757d3512704f..9e897c500237d 100644 --- a/arch/arm64/kernel/image-vars.h +++ b/arch/arm64/kernel/image-vars.h @@ -63,35 +63,6 @@ __efistub__ctype = _ctype; #define KVM_NVHE_ALIAS(sym) __kvm_nvhe_##sym = sym; -/* Symbols defined in aarch32.c (not yet compiled with nVHE build rules). */ -KVM_NVHE_ALIAS(kvm_skip_instr32); - -/* Symbols defined in entry.S (not yet compiled with nVHE build rules). */ -KVM_NVHE_ALIAS(__guest_enter); -KVM_NVHE_ALIAS(__guest_exit); -KVM_NVHE_ALIAS(abort_guest_exit_end); -KVM_NVHE_ALIAS(abort_guest_exit_start); - -/* Symbols defined in fpsimd.S (not yet compiled with nVHE build rules). */ -KVM_NVHE_ALIAS(__fpsimd_restore_state); -KVM_NVHE_ALIAS(__fpsimd_save_state); - -/* Symbols defined in vgic-v2-cpuif-proxy.c (not yet compiled with nVHE build rules). */ -KVM_NVHE_ALIAS(__vgic_v2_perform_cpuif_access); - -/* Symbols defined in vgic-v3-sr.c (not yet compiled with nVHE build rules). */ -KVM_NVHE_ALIAS(__vgic_v3_activate_traps); -KVM_NVHE_ALIAS(__vgic_v3_deactivate_traps); -KVM_NVHE_ALIAS(__vgic_v3_get_ich_vtr_el2); -KVM_NVHE_ALIAS(__vgic_v3_init_lrs); -KVM_NVHE_ALIAS(__vgic_v3_perform_cpuif_access); -KVM_NVHE_ALIAS(__vgic_v3_read_vmcr); -KVM_NVHE_ALIAS(__vgic_v3_restore_aprs); -KVM_NVHE_ALIAS(__vgic_v3_restore_state); -KVM_NVHE_ALIAS(__vgic_v3_save_aprs); -KVM_NVHE_ALIAS(__vgic_v3_save_state); -KVM_NVHE_ALIAS(__vgic_v3_write_vmcr); - /* Alternative callbacks for init-time patching of nVHE hyp code. */ KVM_NVHE_ALIAS(arm64_enable_wa2_handling); KVM_NVHE_ALIAS(kvm_patch_vector_branch); diff --git a/arch/arm64/kvm/hyp/Makefile b/arch/arm64/kvm/hyp/Makefile index ef1aa7fe8f5ad..f54f0e89a71cb 100644 --- a/arch/arm64/kvm/hyp/Makefile +++ b/arch/arm64/kvm/hyp/Makefile @@ -10,16 +10,5 @@ subdir-ccflags-y := -I$(incdir) \ -DDISABLE_BRANCH_PROFILING \ $(DISABLE_STACKLEAK_PLUGIN) -obj-$(CONFIG_KVM) += hyp.o vhe/ nvhe/ +obj-$(CONFIG_KVM) += vhe/ nvhe/ obj-$(CONFIG_KVM_INDIRECT_VECTORS) += smccc_wa.o - -hyp-y := vgic-v3-sr.o aarch32.o vgic-v2-cpuif-proxy.o entry.o \ - fpsimd.o - -# KVM code is run at a different exception code with a different map, so -# compiler instrumentation that inserts callbacks or checks into the code may -# cause crashes. Just disable it. -GCOV_PROFILE := n -KASAN_SANITIZE := n -UBSAN_SANITIZE := n -KCOV_INSTRUMENT := n diff --git a/arch/arm64/kvm/hyp/nvhe/Makefile b/arch/arm64/kvm/hyp/nvhe/Makefile index 0f4c544f07dbc..ad8729f5e8144 100644 --- a/arch/arm64/kvm/hyp/nvhe/Makefile +++ b/arch/arm64/kvm/hyp/nvhe/Makefile @@ -6,8 +6,9 @@ asflags-y := -D__KVM_NVHE_HYPERVISOR__ ccflags-y := -D__KVM_NVHE_HYPERVISOR__ -obj-y := timer-sr.o sysreg-sr.o debug-sr.o switch.o tlb.o hyp-init.o \ - ../hyp-entry.o +obj-y := timer-sr.o sysreg-sr.o debug-sr.o switch.o tlb.o hyp-init.o +obj-y += ../vgic-v3-sr.o ../aarch32.o ../vgic-v2-cpuif-proxy.o ../entry.o \ + ../fpsimd.o ../hyp-entry.o obj-y := $(patsubst %.o,%.hyp.o,$(obj-y)) extra-y := $(patsubst %.hyp.o,%.hyp.tmp.o,$(obj-y)) diff --git a/arch/arm64/kvm/hyp/vhe/Makefile b/arch/arm64/kvm/hyp/vhe/Makefile index a1dbbc5409bd4..090fd1e14be2b 100644 --- a/arch/arm64/kvm/hyp/vhe/Makefile +++ b/arch/arm64/kvm/hyp/vhe/Makefile @@ -6,7 +6,9 @@ asflags-y := -D__KVM_VHE_HYPERVISOR__ ccflags-y := -D__KVM_VHE_HYPERVISOR__ -obj-y := timer-sr.o sysreg-sr.o debug-sr.o switch.o tlb.o ../hyp-entry.o +obj-y := timer-sr.o sysreg-sr.o debug-sr.o switch.o tlb.o +obj-y += ../vgic-v3-sr.o ../aarch32.o ../vgic-v2-cpuif-proxy.o ../entry.o \ + ../fpsimd.o ../hyp-entry.o # KVM code is run at a different exception code with a different map, so # compiler instrumentation that inserts callbacks or checks into the code may -- GitLab From c50cb04303cb88c517715b078e3e010c024af1a5 Mon Sep 17 00:00:00 2001 From: David Brazdil Date: Thu, 25 Jun 2020 14:14:19 +0100 Subject: [PATCH 0172/2249] KVM: arm64: Remove __hyp_text macro, use build rules instead With nVHE code now fully separated from the rest of the kernel, the effects of the __hyp_text macro (which had to be applied on all nVHE code) can be achieved with build rules instead. The macro used to: (a) move code to .hyp.text ELF section, now done by renaming .text using `objcopy`, and (b) `notrace` and `__noscs` would negate effects of CC_FLAGS_FTRACE and CC_FLAGS_SCS, respectivelly, now those flags are erased from KBUILD_CFLAGS (same way as in EFI stub). Note that by removing __hyp_text from code shared with VHE, all VHE code is now compiled into .text and without `notrace` and `__noscs`. Use of '.pushsection .hyp.text' removed from assembly files as this is now also covered by the build rules. For MAINTAINERS: if needed to re-run, uses of macro were removed with the following command. Formatting was fixed up manually. find arch/arm64/kvm/hyp -type f -name '*.c' -o -name '*.h' \ -exec sed -i 's/ __hyp_text//g' {} + Signed-off-by: David Brazdil Signed-off-by: Marc Zyngier Link: https://lore.kernel.org/r/20200625131420.71444-15-dbrazdil@google.com --- arch/arm64/include/asm/kvm_emulate.h | 2 +- arch/arm64/include/asm/kvm_hyp.h | 2 - arch/arm64/kvm/hyp/aarch32.c | 6 +- arch/arm64/kvm/hyp/entry.S | 1 - arch/arm64/kvm/hyp/fpsimd.S | 1 - arch/arm64/kvm/hyp/hyp-entry.S | 1 - arch/arm64/kvm/hyp/include/hyp/debug-sr.h | 16 +-- arch/arm64/kvm/hyp/include/hyp/switch.h | 36 +++--- arch/arm64/kvm/hyp/include/hyp/sysreg-sr.h | 20 ++-- arch/arm64/kvm/hyp/nvhe/Makefile | 8 +- arch/arm64/kvm/hyp/nvhe/debug-sr.c | 10 +- arch/arm64/kvm/hyp/nvhe/switch.c | 18 +-- arch/arm64/kvm/hyp/nvhe/sysreg-sr.c | 6 +- arch/arm64/kvm/hyp/nvhe/timer-sr.c | 4 +- arch/arm64/kvm/hyp/nvhe/tlb.c | 14 +-- arch/arm64/kvm/hyp/vgic-v2-cpuif-proxy.c | 4 +- arch/arm64/kvm/hyp/vgic-v3-sr.c | 130 +++++++++------------ 17 files changed, 132 insertions(+), 147 deletions(-) diff --git a/arch/arm64/include/asm/kvm_emulate.h b/arch/arm64/include/asm/kvm_emulate.h index 4d0f8ea600ba4..269a76cd51fff 100644 --- a/arch/arm64/include/asm/kvm_emulate.h +++ b/arch/arm64/include/asm/kvm_emulate.h @@ -516,7 +516,7 @@ static __always_inline void kvm_skip_instr(struct kvm_vcpu *vcpu, bool is_wide_i * Skip an instruction which has been emulated at hyp while most guest sysregs * are live. */ -static __always_inline void __hyp_text __kvm_skip_instr(struct kvm_vcpu *vcpu) +static __always_inline void __kvm_skip_instr(struct kvm_vcpu *vcpu) { *vcpu_pc(vcpu) = read_sysreg_el2(SYS_ELR); vcpu->arch.ctxt.gp_regs.regs.pstate = read_sysreg_el2(SYS_SPSR); diff --git a/arch/arm64/include/asm/kvm_hyp.h b/arch/arm64/include/asm/kvm_hyp.h index 19f8b40fe6cf1..46689e7db46c2 100644 --- a/arch/arm64/include/asm/kvm_hyp.h +++ b/arch/arm64/include/asm/kvm_hyp.h @@ -12,8 +12,6 @@ #include #include -#define __hyp_text __section(.hyp.text) notrace __noscs - #define read_sysreg_elx(r,nvh,vh) \ ({ \ u64 reg; \ diff --git a/arch/arm64/kvm/hyp/aarch32.c b/arch/arm64/kvm/hyp/aarch32.c index 25c0e47d57cbe..f9ff67dfbf0b1 100644 --- a/arch/arm64/kvm/hyp/aarch32.c +++ b/arch/arm64/kvm/hyp/aarch32.c @@ -44,7 +44,7 @@ static const unsigned short cc_map[16] = { /* * Check if a trapped instruction should have been executed or not. */ -bool __hyp_text kvm_condition_valid32(const struct kvm_vcpu *vcpu) +bool kvm_condition_valid32(const struct kvm_vcpu *vcpu) { unsigned long cpsr; u32 cpsr_cond; @@ -93,7 +93,7 @@ bool __hyp_text kvm_condition_valid32(const struct kvm_vcpu *vcpu) * * IT[7:0] -> CPSR[26:25],CPSR[15:10] */ -static void __hyp_text kvm_adjust_itstate(struct kvm_vcpu *vcpu) +static void kvm_adjust_itstate(struct kvm_vcpu *vcpu) { unsigned long itbits, cond; unsigned long cpsr = *vcpu_cpsr(vcpu); @@ -123,7 +123,7 @@ static void __hyp_text kvm_adjust_itstate(struct kvm_vcpu *vcpu) * kvm_skip_instr - skip a trapped instruction and proceed to the next * @vcpu: The vcpu pointer */ -void __hyp_text kvm_skip_instr32(struct kvm_vcpu *vcpu, bool is_wide_instr) +void kvm_skip_instr32(struct kvm_vcpu *vcpu, bool is_wide_instr) { u32 pc = *vcpu_pc(vcpu); bool is_thumb; diff --git a/arch/arm64/kvm/hyp/entry.S b/arch/arm64/kvm/hyp/entry.S index 90186cf6473e0..dfb4e6d359ab1 100644 --- a/arch/arm64/kvm/hyp/entry.S +++ b/arch/arm64/kvm/hyp/entry.S @@ -21,7 +21,6 @@ #define CPU_SP_EL0_OFFSET (CPU_XREG_OFFSET(30) + 8) .text - .pushsection .hyp.text, "ax" /* * We treat x18 as callee-saved as the host may use it as a platform diff --git a/arch/arm64/kvm/hyp/fpsimd.S b/arch/arm64/kvm/hyp/fpsimd.S index 5b8ff517ff100..01f114aa47b09 100644 --- a/arch/arm64/kvm/hyp/fpsimd.S +++ b/arch/arm64/kvm/hyp/fpsimd.S @@ -9,7 +9,6 @@ #include .text - .pushsection .hyp.text, "ax" SYM_FUNC_START(__fpsimd_save_state) fpsimd_save x0, 1 diff --git a/arch/arm64/kvm/hyp/hyp-entry.S b/arch/arm64/kvm/hyp/hyp-entry.S index 8316ee67d6a0c..689fccbc9de72 100644 --- a/arch/arm64/kvm/hyp/hyp-entry.S +++ b/arch/arm64/kvm/hyp/hyp-entry.S @@ -16,7 +16,6 @@ #include .text - .pushsection .hyp.text, "ax" .macro do_el2_call /* diff --git a/arch/arm64/kvm/hyp/include/hyp/debug-sr.h b/arch/arm64/kvm/hyp/include/hyp/debug-sr.h index e041dbd23243f..24e8acf9ec106 100644 --- a/arch/arm64/kvm/hyp/include/hyp/debug-sr.h +++ b/arch/arm64/kvm/hyp/include/hyp/debug-sr.h @@ -88,9 +88,9 @@ default: write_debug(ptr[0], reg, 0); \ } -static inline void __hyp_text __debug_save_state(struct kvm_vcpu *vcpu, - struct kvm_guest_debug_arch *dbg, - struct kvm_cpu_context *ctxt) +static inline void __debug_save_state(struct kvm_vcpu *vcpu, + struct kvm_guest_debug_arch *dbg, + struct kvm_cpu_context *ctxt) { u64 aa64dfr0; int brps, wrps; @@ -107,9 +107,9 @@ static inline void __hyp_text __debug_save_state(struct kvm_vcpu *vcpu, ctxt->sys_regs[MDCCINT_EL1] = read_sysreg(mdccint_el1); } -static inline void __hyp_text __debug_restore_state(struct kvm_vcpu *vcpu, - struct kvm_guest_debug_arch *dbg, - struct kvm_cpu_context *ctxt) +static inline void __debug_restore_state(struct kvm_vcpu *vcpu, + struct kvm_guest_debug_arch *dbg, + struct kvm_cpu_context *ctxt) { u64 aa64dfr0; int brps, wrps; @@ -127,7 +127,7 @@ static inline void __hyp_text __debug_restore_state(struct kvm_vcpu *vcpu, write_sysreg(ctxt->sys_regs[MDCCINT_EL1], mdccint_el1); } -static inline void __hyp_text __debug_switch_to_guest_common(struct kvm_vcpu *vcpu) +static inline void __debug_switch_to_guest_common(struct kvm_vcpu *vcpu) { struct kvm_cpu_context *host_ctxt; struct kvm_cpu_context *guest_ctxt; @@ -146,7 +146,7 @@ static inline void __hyp_text __debug_switch_to_guest_common(struct kvm_vcpu *vc __debug_restore_state(vcpu, guest_dbg, guest_ctxt); } -static inline void __hyp_text __debug_switch_to_host_common(struct kvm_vcpu *vcpu) +static inline void __debug_switch_to_host_common(struct kvm_vcpu *vcpu) { struct kvm_cpu_context *host_ctxt; struct kvm_cpu_context *guest_ctxt; diff --git a/arch/arm64/kvm/hyp/include/hyp/switch.h b/arch/arm64/kvm/hyp/include/hyp/switch.h index 65d2a879b93b4..8f622688fa647 100644 --- a/arch/arm64/kvm/hyp/include/hyp/switch.h +++ b/arch/arm64/kvm/hyp/include/hyp/switch.h @@ -30,7 +30,7 @@ extern const char __hyp_panic_string[]; /* Check whether the FP regs were dirtied while in the host-side run loop: */ -static inline bool __hyp_text update_fp_enabled(struct kvm_vcpu *vcpu) +static inline bool update_fp_enabled(struct kvm_vcpu *vcpu) { /* * When the system doesn't support FP/SIMD, we cannot rely on @@ -48,7 +48,7 @@ static inline bool __hyp_text update_fp_enabled(struct kvm_vcpu *vcpu) } /* Save the 32-bit only FPSIMD system register state */ -static inline void __hyp_text __fpsimd_save_fpexc32(struct kvm_vcpu *vcpu) +static inline void __fpsimd_save_fpexc32(struct kvm_vcpu *vcpu) { if (!vcpu_el1_is_32bit(vcpu)) return; @@ -56,7 +56,7 @@ static inline void __hyp_text __fpsimd_save_fpexc32(struct kvm_vcpu *vcpu) vcpu->arch.ctxt.sys_regs[FPEXC32_EL2] = read_sysreg(fpexc32_el2); } -static inline void __hyp_text __activate_traps_fpsimd32(struct kvm_vcpu *vcpu) +static inline void __activate_traps_fpsimd32(struct kvm_vcpu *vcpu) { /* * We are about to set CPTR_EL2.TFP to trap all floating point @@ -73,7 +73,7 @@ static inline void __hyp_text __activate_traps_fpsimd32(struct kvm_vcpu *vcpu) } } -static inline void __hyp_text __activate_traps_common(struct kvm_vcpu *vcpu) +static inline void __activate_traps_common(struct kvm_vcpu *vcpu) { /* Trap on AArch32 cp15 c15 (impdef sysregs) accesses (EL1 or EL0) */ write_sysreg(1 << 15, hstr_el2); @@ -89,13 +89,13 @@ static inline void __hyp_text __activate_traps_common(struct kvm_vcpu *vcpu) write_sysreg(vcpu->arch.mdcr_el2, mdcr_el2); } -static inline void __hyp_text __deactivate_traps_common(void) +static inline void __deactivate_traps_common(void) { write_sysreg(0, hstr_el2); write_sysreg(0, pmuserenr_el0); } -static inline void __hyp_text ___activate_traps(struct kvm_vcpu *vcpu) +static inline void ___activate_traps(struct kvm_vcpu *vcpu) { u64 hcr = vcpu->arch.hcr_el2; @@ -108,7 +108,7 @@ static inline void __hyp_text ___activate_traps(struct kvm_vcpu *vcpu) write_sysreg_s(vcpu->arch.vsesr_el2, SYS_VSESR_EL2); } -static inline void __hyp_text ___deactivate_traps(struct kvm_vcpu *vcpu) +static inline void ___deactivate_traps(struct kvm_vcpu *vcpu) { /* * If we pended a virtual abort, preserve it until it gets @@ -122,12 +122,12 @@ static inline void __hyp_text ___deactivate_traps(struct kvm_vcpu *vcpu) } } -static inline void __hyp_text __activate_vm(struct kvm *kvm) +static inline void __activate_vm(struct kvm *kvm) { __load_guest_stage2(kvm); } -static inline bool __hyp_text __translate_far_to_hpfar(u64 far, u64 *hpfar) +static inline bool __translate_far_to_hpfar(u64 far, u64 *hpfar) { u64 par, tmp; @@ -156,7 +156,7 @@ static inline bool __hyp_text __translate_far_to_hpfar(u64 far, u64 *hpfar) return true; } -static inline bool __hyp_text __populate_fault_info(struct kvm_vcpu *vcpu) +static inline bool __populate_fault_info(struct kvm_vcpu *vcpu) { u8 ec; u64 esr; @@ -196,7 +196,7 @@ static inline bool __hyp_text __populate_fault_info(struct kvm_vcpu *vcpu) } /* Check for an FPSIMD/SVE trap and handle as appropriate */ -static inline bool __hyp_text __hyp_handle_fpsimd(struct kvm_vcpu *vcpu) +static inline bool __hyp_handle_fpsimd(struct kvm_vcpu *vcpu) { bool vhe, sve_guest, sve_host; u8 hsr_ec; @@ -283,7 +283,7 @@ static inline bool __hyp_text __hyp_handle_fpsimd(struct kvm_vcpu *vcpu) return true; } -static inline bool __hyp_text handle_tx2_tvm(struct kvm_vcpu *vcpu) +static inline bool handle_tx2_tvm(struct kvm_vcpu *vcpu) { u32 sysreg = esr_sys64_to_sysreg(kvm_vcpu_get_hsr(vcpu)); int rt = kvm_vcpu_sys_get_rt(vcpu); @@ -338,7 +338,7 @@ static inline bool __hyp_text handle_tx2_tvm(struct kvm_vcpu *vcpu) return true; } -static inline bool __hyp_text esr_is_ptrauth_trap(u32 esr) +static inline bool esr_is_ptrauth_trap(u32 esr) { u32 ec = ESR_ELx_EC(esr); @@ -371,7 +371,7 @@ static inline bool __hyp_text esr_is_ptrauth_trap(u32 esr) regs[key ## KEYHI_EL1] = read_sysreg_s(SYS_ ## key ## KEYHI_EL1); \ }) -static inline bool __hyp_text __hyp_handle_ptrauth(struct kvm_vcpu *vcpu) +static inline bool __hyp_handle_ptrauth(struct kvm_vcpu *vcpu) { struct kvm_cpu_context *ctxt; u64 val; @@ -401,7 +401,7 @@ static inline bool __hyp_text __hyp_handle_ptrauth(struct kvm_vcpu *vcpu) * the guest, false when we should restore the host state and return to the * main run loop. */ -static inline bool __hyp_text fixup_guest_exit(struct kvm_vcpu *vcpu, u64 *exit_code) +static inline bool fixup_guest_exit(struct kvm_vcpu *vcpu, u64 *exit_code) { if (ARM_EXCEPTION_CODE(*exit_code) != ARM_EXCEPTION_IRQ) vcpu->arch.fault.esr_el2 = read_sysreg_el2(SYS_ESR); @@ -473,7 +473,7 @@ static inline bool __hyp_text fixup_guest_exit(struct kvm_vcpu *vcpu, u64 *exit_ return false; } -static inline bool __hyp_text __needs_ssbd_off(struct kvm_vcpu *vcpu) +static inline bool __needs_ssbd_off(struct kvm_vcpu *vcpu) { if (!cpus_have_final_cap(ARM64_SSBD)) return false; @@ -481,7 +481,7 @@ static inline bool __hyp_text __needs_ssbd_off(struct kvm_vcpu *vcpu) return !(vcpu->arch.workaround_flags & VCPU_WORKAROUND_2_FLAG); } -static inline void __hyp_text __set_guest_arch_workaround_state(struct kvm_vcpu *vcpu) +static inline void __set_guest_arch_workaround_state(struct kvm_vcpu *vcpu) { #ifdef CONFIG_ARM64_SSBD /* @@ -494,7 +494,7 @@ static inline void __hyp_text __set_guest_arch_workaround_state(struct kvm_vcpu #endif } -static inline void __hyp_text __set_host_arch_workaround_state(struct kvm_vcpu *vcpu) +static inline void __set_host_arch_workaround_state(struct kvm_vcpu *vcpu) { #ifdef CONFIG_ARM64_SSBD /* diff --git a/arch/arm64/kvm/hyp/include/hyp/sysreg-sr.h b/arch/arm64/kvm/hyp/include/hyp/sysreg-sr.h index 3e0585fbd4032..6e04e061f762a 100644 --- a/arch/arm64/kvm/hyp/include/hyp/sysreg-sr.h +++ b/arch/arm64/kvm/hyp/include/hyp/sysreg-sr.h @@ -15,18 +15,18 @@ #include #include -static inline void __hyp_text __sysreg_save_common_state(struct kvm_cpu_context *ctxt) +static inline void __sysreg_save_common_state(struct kvm_cpu_context *ctxt) { ctxt->sys_regs[MDSCR_EL1] = read_sysreg(mdscr_el1); } -static inline void __hyp_text __sysreg_save_user_state(struct kvm_cpu_context *ctxt) +static inline void __sysreg_save_user_state(struct kvm_cpu_context *ctxt) { ctxt->sys_regs[TPIDR_EL0] = read_sysreg(tpidr_el0); ctxt->sys_regs[TPIDRRO_EL0] = read_sysreg(tpidrro_el0); } -static inline void __hyp_text __sysreg_save_el1_state(struct kvm_cpu_context *ctxt) +static inline void __sysreg_save_el1_state(struct kvm_cpu_context *ctxt) { ctxt->sys_regs[CSSELR_EL1] = read_sysreg(csselr_el1); ctxt->sys_regs[SCTLR_EL1] = read_sysreg_el1(SYS_SCTLR); @@ -51,7 +51,7 @@ static inline void __hyp_text __sysreg_save_el1_state(struct kvm_cpu_context *ct ctxt->gp_regs.spsr[KVM_SPSR_EL1]= read_sysreg_el1(SYS_SPSR); } -static inline void __hyp_text __sysreg_save_el2_return_state(struct kvm_cpu_context *ctxt) +static inline void __sysreg_save_el2_return_state(struct kvm_cpu_context *ctxt) { ctxt->gp_regs.regs.pc = read_sysreg_el2(SYS_ELR); ctxt->gp_regs.regs.pstate = read_sysreg_el2(SYS_SPSR); @@ -60,18 +60,18 @@ static inline void __hyp_text __sysreg_save_el2_return_state(struct kvm_cpu_cont ctxt->sys_regs[DISR_EL1] = read_sysreg_s(SYS_VDISR_EL2); } -static inline void __hyp_text __sysreg_restore_common_state(struct kvm_cpu_context *ctxt) +static inline void __sysreg_restore_common_state(struct kvm_cpu_context *ctxt) { write_sysreg(ctxt->sys_regs[MDSCR_EL1], mdscr_el1); } -static inline void __hyp_text __sysreg_restore_user_state(struct kvm_cpu_context *ctxt) +static inline void __sysreg_restore_user_state(struct kvm_cpu_context *ctxt) { write_sysreg(ctxt->sys_regs[TPIDR_EL0], tpidr_el0); write_sysreg(ctxt->sys_regs[TPIDRRO_EL0], tpidrro_el0); } -static inline void __hyp_text __sysreg_restore_el1_state(struct kvm_cpu_context *ctxt) +static inline void __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); @@ -130,7 +130,7 @@ static inline void __hyp_text __sysreg_restore_el1_state(struct kvm_cpu_context write_sysreg_el1(ctxt->gp_regs.spsr[KVM_SPSR_EL1],SYS_SPSR); } -static inline void __hyp_text __sysreg_restore_el2_return_state(struct kvm_cpu_context *ctxt) +static inline void __sysreg_restore_el2_return_state(struct kvm_cpu_context *ctxt) { u64 pstate = ctxt->gp_regs.regs.pstate; u64 mode = pstate & PSR_AA32_MODE_MASK; @@ -156,7 +156,7 @@ static inline void __hyp_text __sysreg_restore_el2_return_state(struct kvm_cpu_c write_sysreg_s(ctxt->sys_regs[DISR_EL1], SYS_VDISR_EL2); } -static inline void __hyp_text __sysreg32_save_state(struct kvm_vcpu *vcpu) +static inline void __sysreg32_save_state(struct kvm_vcpu *vcpu) { u64 *spsr, *sysreg; @@ -178,7 +178,7 @@ static inline void __hyp_text __sysreg32_save_state(struct kvm_vcpu *vcpu) sysreg[DBGVCR32_EL2] = read_sysreg(dbgvcr32_el2); } -static inline void __hyp_text __sysreg32_restore_state(struct kvm_vcpu *vcpu) +static inline void __sysreg32_restore_state(struct kvm_vcpu *vcpu) { u64 *spsr, *sysreg; diff --git a/arch/arm64/kvm/hyp/nvhe/Makefile b/arch/arm64/kvm/hyp/nvhe/Makefile index ad8729f5e8144..0b34414557d63 100644 --- a/arch/arm64/kvm/hyp/nvhe/Makefile +++ b/arch/arm64/kvm/hyp/nvhe/Makefile @@ -21,7 +21,13 @@ $(obj)/%.hyp.o: $(obj)/%.hyp.tmp.o FORCE $(call if_changed,hypcopy) quiet_cmd_hypcopy = HYPCOPY $@ - cmd_hypcopy = $(OBJCOPY) --prefix-symbols=__kvm_nvhe_ $< $@ + cmd_hypcopy = $(OBJCOPY) --prefix-symbols=__kvm_nvhe_ \ + --rename-section=.text=.hyp.text \ + $< $@ + +# Remove ftrace and Shadow Call Stack CFLAGS. +# This is equivalent to the 'notrace' and '__noscs' annotations. +KBUILD_CFLAGS := $(filter-out $(CC_FLAGS_FTRACE) $(CC_FLAGS_SCS), $(KBUILD_CFLAGS)) # KVM nVHE code is run at a different exception code with a different map, so # compiler instrumentation that inserts callbacks or checks into the code may diff --git a/arch/arm64/kvm/hyp/nvhe/debug-sr.c b/arch/arm64/kvm/hyp/nvhe/debug-sr.c index 828c0d48e790d..91a711aa8382e 100644 --- a/arch/arm64/kvm/hyp/nvhe/debug-sr.c +++ b/arch/arm64/kvm/hyp/nvhe/debug-sr.c @@ -14,7 +14,7 @@ #include #include -static void __hyp_text __debug_save_spe(u64 *pmscr_el1) +static void __debug_save_spe(u64 *pmscr_el1) { u64 reg; @@ -46,7 +46,7 @@ static void __hyp_text __debug_save_spe(u64 *pmscr_el1) dsb(nsh); } -static void __hyp_text __debug_restore_spe(u64 pmscr_el1) +static void __debug_restore_spe(u64 pmscr_el1) { if (!pmscr_el1) return; @@ -58,20 +58,20 @@ static void __hyp_text __debug_restore_spe(u64 pmscr_el1) write_sysreg_s(pmscr_el1, SYS_PMSCR_EL1); } -void __hyp_text __debug_switch_to_guest(struct kvm_vcpu *vcpu) +void __debug_switch_to_guest(struct kvm_vcpu *vcpu) { /* Disable and flush SPE data generation */ __debug_save_spe(&vcpu->arch.host_debug_state.pmscr_el1); __debug_switch_to_guest_common(vcpu); } -void __hyp_text __debug_switch_to_host(struct kvm_vcpu *vcpu) +void __debug_switch_to_host(struct kvm_vcpu *vcpu) { __debug_restore_spe(vcpu->arch.host_debug_state.pmscr_el1); __debug_switch_to_host_common(vcpu); } -u32 __hyp_text __kvm_get_mdcr_el2(void) +u32 __kvm_get_mdcr_el2(void) { return read_sysreg(mdcr_el2); } diff --git a/arch/arm64/kvm/hyp/nvhe/switch.c b/arch/arm64/kvm/hyp/nvhe/switch.c index f08bfb951df60..a1dcf59bd45ee 100644 --- a/arch/arm64/kvm/hyp/nvhe/switch.c +++ b/arch/arm64/kvm/hyp/nvhe/switch.c @@ -27,7 +27,7 @@ #include #include -static void __hyp_text __activate_traps(struct kvm_vcpu *vcpu) +static void __activate_traps(struct kvm_vcpu *vcpu) { u64 val; @@ -58,7 +58,7 @@ static void __hyp_text __activate_traps(struct kvm_vcpu *vcpu) } } -static void __hyp_text __deactivate_traps(struct kvm_vcpu *vcpu) +static void __deactivate_traps(struct kvm_vcpu *vcpu) { u64 mdcr_el2; @@ -93,13 +93,13 @@ static void __hyp_text __deactivate_traps(struct kvm_vcpu *vcpu) write_sysreg(CPTR_EL2_DEFAULT, cptr_el2); } -static void __hyp_text __deactivate_vm(struct kvm_vcpu *vcpu) +static void __deactivate_vm(struct kvm_vcpu *vcpu) { write_sysreg(0, vttbr_el2); } /* Save VGICv3 state on non-VHE systems */ -static void __hyp_text __hyp_vgic_save_state(struct kvm_vcpu *vcpu) +static void __hyp_vgic_save_state(struct kvm_vcpu *vcpu) { if (static_branch_unlikely(&kvm_vgic_global_state.gicv3_cpuif)) { __vgic_v3_save_state(&vcpu->arch.vgic_cpu.vgic_v3); @@ -108,7 +108,7 @@ static void __hyp_text __hyp_vgic_save_state(struct kvm_vcpu *vcpu) } /* Restore VGICv3 state on non_VEH systems */ -static void __hyp_text __hyp_vgic_restore_state(struct kvm_vcpu *vcpu) +static void __hyp_vgic_restore_state(struct kvm_vcpu *vcpu) { if (static_branch_unlikely(&kvm_vgic_global_state.gicv3_cpuif)) { __vgic_v3_activate_traps(&vcpu->arch.vgic_cpu.vgic_v3); @@ -119,7 +119,7 @@ static void __hyp_text __hyp_vgic_restore_state(struct kvm_vcpu *vcpu) /** * Disable host events, enable guest events */ -static bool __hyp_text __pmu_switch_to_guest(struct kvm_cpu_context *host_ctxt) +static bool __pmu_switch_to_guest(struct kvm_cpu_context *host_ctxt) { struct kvm_host_data *host; struct kvm_pmu_events *pmu; @@ -139,7 +139,7 @@ static bool __hyp_text __pmu_switch_to_guest(struct kvm_cpu_context *host_ctxt) /** * Disable guest events, enable host events */ -static void __hyp_text __pmu_switch_to_host(struct kvm_cpu_context *host_ctxt) +static void __pmu_switch_to_host(struct kvm_cpu_context *host_ctxt) { struct kvm_host_data *host; struct kvm_pmu_events *pmu; @@ -155,7 +155,7 @@ static void __hyp_text __pmu_switch_to_host(struct kvm_cpu_context *host_ctxt) } /* Switch to the guest for legacy non-VHE systems */ -int __hyp_text __kvm_vcpu_run(struct kvm_vcpu *vcpu) +int __kvm_vcpu_run(struct kvm_vcpu *vcpu) { struct kvm_cpu_context *host_ctxt; struct kvm_cpu_context *guest_ctxt; @@ -242,7 +242,7 @@ int __hyp_text __kvm_vcpu_run(struct kvm_vcpu *vcpu) return exit_code; } -void __hyp_text __noreturn hyp_panic(struct kvm_cpu_context *host_ctxt) +void __noreturn hyp_panic(struct kvm_cpu_context *host_ctxt) { u64 spsr = read_sysreg_el2(SYS_SPSR); u64 elr = read_sysreg_el2(SYS_ELR); diff --git a/arch/arm64/kvm/hyp/nvhe/sysreg-sr.c b/arch/arm64/kvm/hyp/nvhe/sysreg-sr.c index 710cf28ab1ec9..88a25fc8fcd36 100644 --- a/arch/arm64/kvm/hyp/nvhe/sysreg-sr.c +++ b/arch/arm64/kvm/hyp/nvhe/sysreg-sr.c @@ -18,7 +18,7 @@ * Non-VHE: Both host and guest must save everything. */ -void __hyp_text __sysreg_save_state_nvhe(struct kvm_cpu_context *ctxt) +void __sysreg_save_state_nvhe(struct kvm_cpu_context *ctxt) { __sysreg_save_el1_state(ctxt); __sysreg_save_common_state(ctxt); @@ -26,7 +26,7 @@ void __hyp_text __sysreg_save_state_nvhe(struct kvm_cpu_context *ctxt) __sysreg_save_el2_return_state(ctxt); } -void __hyp_text __sysreg_restore_state_nvhe(struct kvm_cpu_context *ctxt) +void __sysreg_restore_state_nvhe(struct kvm_cpu_context *ctxt) { __sysreg_restore_el1_state(ctxt); __sysreg_restore_common_state(ctxt); @@ -34,7 +34,7 @@ void __hyp_text __sysreg_restore_state_nvhe(struct kvm_cpu_context *ctxt) __sysreg_restore_el2_return_state(ctxt); } -void __hyp_text __kvm_enable_ssbs(void) +void __kvm_enable_ssbs(void) { u64 tmp; diff --git a/arch/arm64/kvm/hyp/nvhe/timer-sr.c b/arch/arm64/kvm/hyp/nvhe/timer-sr.c index 42c8ed71d06ee..9072e71693bab 100644 --- a/arch/arm64/kvm/hyp/nvhe/timer-sr.c +++ b/arch/arm64/kvm/hyp/nvhe/timer-sr.c @@ -19,7 +19,7 @@ void __kvm_timer_set_cntvoff(u64 cntvoff) * Should only be called on non-VHE systems. * VHE systems use EL2 timers and configure EL1 timers in kvm_timer_init_vhe(). */ -void __hyp_text __timer_disable_traps(struct kvm_vcpu *vcpu) +void __timer_disable_traps(struct kvm_vcpu *vcpu) { u64 val; @@ -33,7 +33,7 @@ void __hyp_text __timer_disable_traps(struct kvm_vcpu *vcpu) * Should only be called on non-VHE systems. * VHE systems use EL2 timers and configure EL1 timers in kvm_timer_init_vhe(). */ -void __hyp_text __timer_enable_traps(struct kvm_vcpu *vcpu) +void __timer_enable_traps(struct kvm_vcpu *vcpu) { u64 val; diff --git a/arch/arm64/kvm/hyp/nvhe/tlb.c b/arch/arm64/kvm/hyp/nvhe/tlb.c index deb48c8c00eed..d4475f8340c40 100644 --- a/arch/arm64/kvm/hyp/nvhe/tlb.c +++ b/arch/arm64/kvm/hyp/nvhe/tlb.c @@ -12,8 +12,7 @@ struct tlb_inv_context { u64 tcr; }; -static void __hyp_text __tlb_switch_to_guest(struct kvm *kvm, - struct tlb_inv_context *cxt) +static void __tlb_switch_to_guest(struct kvm *kvm, struct tlb_inv_context *cxt) { if (cpus_have_final_cap(ARM64_WORKAROUND_SPECULATIVE_AT)) { u64 val; @@ -36,8 +35,7 @@ static void __hyp_text __tlb_switch_to_guest(struct kvm *kvm, asm(ALTERNATIVE("isb", "nop", ARM64_WORKAROUND_SPECULATIVE_AT)); } -static void __hyp_text __tlb_switch_to_host(struct kvm *kvm, - struct tlb_inv_context *cxt) +static void __tlb_switch_to_host(struct kvm *kvm, struct tlb_inv_context *cxt) { write_sysreg(0, vttbr_el2); @@ -49,7 +47,7 @@ static void __hyp_text __tlb_switch_to_host(struct kvm *kvm, } } -void __hyp_text __kvm_tlb_flush_vmid_ipa(struct kvm *kvm, phys_addr_t ipa) +void __kvm_tlb_flush_vmid_ipa(struct kvm *kvm, phys_addr_t ipa) { struct tlb_inv_context cxt; @@ -103,7 +101,7 @@ void __hyp_text __kvm_tlb_flush_vmid_ipa(struct kvm *kvm, phys_addr_t ipa) __tlb_switch_to_host(kvm, &cxt); } -void __hyp_text __kvm_tlb_flush_vmid(struct kvm *kvm) +void __kvm_tlb_flush_vmid(struct kvm *kvm) { struct tlb_inv_context cxt; @@ -120,7 +118,7 @@ void __hyp_text __kvm_tlb_flush_vmid(struct kvm *kvm) __tlb_switch_to_host(kvm, &cxt); } -void __hyp_text __kvm_tlb_flush_local_vmid(struct kvm_vcpu *vcpu) +void __kvm_tlb_flush_local_vmid(struct kvm_vcpu *vcpu) { struct kvm *kvm = kern_hyp_va(kern_hyp_va(vcpu)->kvm); struct tlb_inv_context cxt; @@ -135,7 +133,7 @@ void __hyp_text __kvm_tlb_flush_local_vmid(struct kvm_vcpu *vcpu) __tlb_switch_to_host(kvm, &cxt); } -void __hyp_text __kvm_flush_vm_context(void) +void __kvm_flush_vm_context(void) { dsb(ishst); __tlbi(alle1is); diff --git a/arch/arm64/kvm/hyp/vgic-v2-cpuif-proxy.c b/arch/arm64/kvm/hyp/vgic-v2-cpuif-proxy.c index 4f3a087e36d51..bd1bab551d481 100644 --- a/arch/arm64/kvm/hyp/vgic-v2-cpuif-proxy.c +++ b/arch/arm64/kvm/hyp/vgic-v2-cpuif-proxy.c @@ -13,7 +13,7 @@ #include #include -static bool __hyp_text __is_be(struct kvm_vcpu *vcpu) +static bool __is_be(struct kvm_vcpu *vcpu) { if (vcpu_mode_is_32bit(vcpu)) return !!(read_sysreg_el2(SYS_SPSR) & PSR_AA32_E_BIT); @@ -32,7 +32,7 @@ static bool __hyp_text __is_be(struct kvm_vcpu *vcpu) * 0: Not a GICV access * -1: Illegal GICV access successfully performed */ -int __hyp_text __vgic_v2_perform_cpuif_access(struct kvm_vcpu *vcpu) +int __vgic_v2_perform_cpuif_access(struct kvm_vcpu *vcpu) { struct kvm *kvm = kern_hyp_va(vcpu->kvm); struct vgic_dist *vgic = &kvm->arch.vgic; diff --git a/arch/arm64/kvm/hyp/vgic-v3-sr.c b/arch/arm64/kvm/hyp/vgic-v3-sr.c index 10ed539835c14..d31eb6266f2e1 100644 --- a/arch/arm64/kvm/hyp/vgic-v3-sr.c +++ b/arch/arm64/kvm/hyp/vgic-v3-sr.c @@ -16,7 +16,7 @@ #define vtr_to_nr_pre_bits(v) ((((u32)(v) >> 26) & 7) + 1) #define vtr_to_nr_apr_regs(v) (1 << (vtr_to_nr_pre_bits(v) - 5)) -static u64 __hyp_text __gic_v3_get_lr(unsigned int lr) +static u64 __gic_v3_get_lr(unsigned int lr) { switch (lr & 0xf) { case 0: @@ -56,7 +56,7 @@ static u64 __hyp_text __gic_v3_get_lr(unsigned int lr) unreachable(); } -static void __hyp_text __gic_v3_set_lr(u64 val, int lr) +static void __gic_v3_set_lr(u64 val, int lr) { switch (lr & 0xf) { case 0: @@ -110,7 +110,7 @@ static void __hyp_text __gic_v3_set_lr(u64 val, int lr) } } -static void __hyp_text __vgic_v3_write_ap0rn(u32 val, int n) +static void __vgic_v3_write_ap0rn(u32 val, int n) { switch (n) { case 0: @@ -128,7 +128,7 @@ static void __hyp_text __vgic_v3_write_ap0rn(u32 val, int n) } } -static void __hyp_text __vgic_v3_write_ap1rn(u32 val, int n) +static void __vgic_v3_write_ap1rn(u32 val, int n) { switch (n) { case 0: @@ -146,7 +146,7 @@ static void __hyp_text __vgic_v3_write_ap1rn(u32 val, int n) } } -static u32 __hyp_text __vgic_v3_read_ap0rn(int n) +static u32 __vgic_v3_read_ap0rn(int n) { u32 val; @@ -170,7 +170,7 @@ static u32 __hyp_text __vgic_v3_read_ap0rn(int n) return val; } -static u32 __hyp_text __vgic_v3_read_ap1rn(int n) +static u32 __vgic_v3_read_ap1rn(int n) { u32 val; @@ -194,7 +194,7 @@ static u32 __hyp_text __vgic_v3_read_ap1rn(int n) return val; } -void __hyp_text __vgic_v3_save_state(struct vgic_v3_cpu_if *cpu_if) +void __vgic_v3_save_state(struct vgic_v3_cpu_if *cpu_if) { u64 used_lrs = cpu_if->used_lrs; @@ -229,7 +229,7 @@ void __hyp_text __vgic_v3_save_state(struct vgic_v3_cpu_if *cpu_if) } } -void __hyp_text __vgic_v3_restore_state(struct vgic_v3_cpu_if *cpu_if) +void __vgic_v3_restore_state(struct vgic_v3_cpu_if *cpu_if) { u64 used_lrs = cpu_if->used_lrs; int i; @@ -255,7 +255,7 @@ void __hyp_text __vgic_v3_restore_state(struct vgic_v3_cpu_if *cpu_if) } } -void __hyp_text __vgic_v3_activate_traps(struct vgic_v3_cpu_if *cpu_if) +void __vgic_v3_activate_traps(struct vgic_v3_cpu_if *cpu_if) { /* * VFIQEn is RES1 if ICC_SRE_EL1.SRE is 1. This causes a @@ -302,7 +302,7 @@ void __hyp_text __vgic_v3_activate_traps(struct vgic_v3_cpu_if *cpu_if) write_gicreg(cpu_if->vgic_hcr, ICH_HCR_EL2); } -void __hyp_text __vgic_v3_deactivate_traps(struct vgic_v3_cpu_if *cpu_if) +void __vgic_v3_deactivate_traps(struct vgic_v3_cpu_if *cpu_if) { u64 val; @@ -328,7 +328,7 @@ void __hyp_text __vgic_v3_deactivate_traps(struct vgic_v3_cpu_if *cpu_if) write_gicreg(0, ICH_HCR_EL2); } -void __hyp_text __vgic_v3_save_aprs(struct vgic_v3_cpu_if *cpu_if) +void __vgic_v3_save_aprs(struct vgic_v3_cpu_if *cpu_if) { u64 val; u32 nr_pre_bits; @@ -361,7 +361,7 @@ void __hyp_text __vgic_v3_save_aprs(struct vgic_v3_cpu_if *cpu_if) } } -void __hyp_text __vgic_v3_restore_aprs(struct vgic_v3_cpu_if *cpu_if) +void __vgic_v3_restore_aprs(struct vgic_v3_cpu_if *cpu_if) { u64 val; u32 nr_pre_bits; @@ -394,7 +394,7 @@ void __hyp_text __vgic_v3_restore_aprs(struct vgic_v3_cpu_if *cpu_if) } } -void __hyp_text __vgic_v3_init_lrs(void) +void __vgic_v3_init_lrs(void) { int max_lr_idx = vtr_to_max_lr_idx(read_gicreg(ICH_VTR_EL2)); int i; @@ -403,28 +403,28 @@ void __hyp_text __vgic_v3_init_lrs(void) __gic_v3_set_lr(0, i); } -u64 __hyp_text __vgic_v3_get_ich_vtr_el2(void) +u64 __vgic_v3_get_ich_vtr_el2(void) { return read_gicreg(ICH_VTR_EL2); } -u64 __hyp_text __vgic_v3_read_vmcr(void) +u64 __vgic_v3_read_vmcr(void) { return read_gicreg(ICH_VMCR_EL2); } -void __hyp_text __vgic_v3_write_vmcr(u32 vmcr) +void __vgic_v3_write_vmcr(u32 vmcr) { write_gicreg(vmcr, ICH_VMCR_EL2); } -static int __hyp_text __vgic_v3_bpr_min(void) +static int __vgic_v3_bpr_min(void) { /* See Pseudocode for VPriorityGroup */ return 8 - vtr_to_nr_pre_bits(read_gicreg(ICH_VTR_EL2)); } -static int __hyp_text __vgic_v3_get_group(struct kvm_vcpu *vcpu) +static int __vgic_v3_get_group(struct kvm_vcpu *vcpu) { u32 esr = kvm_vcpu_get_hsr(vcpu); u8 crm = (esr & ESR_ELx_SYS64_ISS_CRM_MASK) >> ESR_ELx_SYS64_ISS_CRM_SHIFT; @@ -434,9 +434,8 @@ static int __hyp_text __vgic_v3_get_group(struct kvm_vcpu *vcpu) #define GICv3_IDLE_PRIORITY 0xff -static int __hyp_text __vgic_v3_highest_priority_lr(struct kvm_vcpu *vcpu, - u32 vmcr, - u64 *lr_val) +static int __vgic_v3_highest_priority_lr(struct kvm_vcpu *vcpu, u32 vmcr, + u64 *lr_val) { unsigned int used_lrs = vcpu->arch.vgic_cpu.vgic_v3.used_lrs; u8 priority = GICv3_IDLE_PRIORITY; @@ -474,8 +473,8 @@ static int __hyp_text __vgic_v3_highest_priority_lr(struct kvm_vcpu *vcpu, return lr; } -static int __hyp_text __vgic_v3_find_active_lr(struct kvm_vcpu *vcpu, - int intid, u64 *lr_val) +static int __vgic_v3_find_active_lr(struct kvm_vcpu *vcpu, int intid, + u64 *lr_val) { unsigned int used_lrs = vcpu->arch.vgic_cpu.vgic_v3.used_lrs; int i; @@ -494,7 +493,7 @@ static int __hyp_text __vgic_v3_find_active_lr(struct kvm_vcpu *vcpu, return -1; } -static int __hyp_text __vgic_v3_get_highest_active_priority(void) +static int __vgic_v3_get_highest_active_priority(void) { u8 nr_apr_regs = vtr_to_nr_apr_regs(read_gicreg(ICH_VTR_EL2)); u32 hap = 0; @@ -526,12 +525,12 @@ static int __hyp_text __vgic_v3_get_highest_active_priority(void) return GICv3_IDLE_PRIORITY; } -static unsigned int __hyp_text __vgic_v3_get_bpr0(u32 vmcr) +static unsigned int __vgic_v3_get_bpr0(u32 vmcr) { return (vmcr & ICH_VMCR_BPR0_MASK) >> ICH_VMCR_BPR0_SHIFT; } -static unsigned int __hyp_text __vgic_v3_get_bpr1(u32 vmcr) +static unsigned int __vgic_v3_get_bpr1(u32 vmcr) { unsigned int bpr; @@ -550,7 +549,7 @@ static unsigned int __hyp_text __vgic_v3_get_bpr1(u32 vmcr) * Convert a priority to a preemption level, taking the relevant BPR * into account by zeroing the sub-priority bits. */ -static u8 __hyp_text __vgic_v3_pri_to_pre(u8 pri, u32 vmcr, int grp) +static u8 __vgic_v3_pri_to_pre(u8 pri, u32 vmcr, int grp) { unsigned int bpr; @@ -568,7 +567,7 @@ static u8 __hyp_text __vgic_v3_pri_to_pre(u8 pri, u32 vmcr, int grp) * matter what the guest does with its BPR, we can always set/get the * same value of a priority. */ -static void __hyp_text __vgic_v3_set_active_priority(u8 pri, u32 vmcr, int grp) +static void __vgic_v3_set_active_priority(u8 pri, u32 vmcr, int grp) { u8 pre, ap; u32 val; @@ -587,7 +586,7 @@ static void __hyp_text __vgic_v3_set_active_priority(u8 pri, u32 vmcr, int grp) } } -static int __hyp_text __vgic_v3_clear_highest_active_priority(void) +static int __vgic_v3_clear_highest_active_priority(void) { u8 nr_apr_regs = vtr_to_nr_apr_regs(read_gicreg(ICH_VTR_EL2)); u32 hap = 0; @@ -625,7 +624,7 @@ static int __hyp_text __vgic_v3_clear_highest_active_priority(void) return GICv3_IDLE_PRIORITY; } -static void __hyp_text __vgic_v3_read_iar(struct kvm_vcpu *vcpu, u32 vmcr, int rt) +static void __vgic_v3_read_iar(struct kvm_vcpu *vcpu, u32 vmcr, int rt) { u64 lr_val; u8 lr_prio, pmr; @@ -661,7 +660,7 @@ static void __hyp_text __vgic_v3_read_iar(struct kvm_vcpu *vcpu, u32 vmcr, int r vcpu_set_reg(vcpu, rt, ICC_IAR1_EL1_SPURIOUS); } -static void __hyp_text __vgic_v3_clear_active_lr(int lr, u64 lr_val) +static void __vgic_v3_clear_active_lr(int lr, u64 lr_val) { lr_val &= ~ICH_LR_ACTIVE_BIT; if (lr_val & ICH_LR_HW) { @@ -674,7 +673,7 @@ static void __hyp_text __vgic_v3_clear_active_lr(int lr, u64 lr_val) __gic_v3_set_lr(lr_val, lr); } -static void __hyp_text __vgic_v3_bump_eoicount(void) +static void __vgic_v3_bump_eoicount(void) { u32 hcr; @@ -683,8 +682,7 @@ static void __hyp_text __vgic_v3_bump_eoicount(void) write_gicreg(hcr, ICH_HCR_EL2); } -static void __hyp_text __vgic_v3_write_dir(struct kvm_vcpu *vcpu, - u32 vmcr, int rt) +static void __vgic_v3_write_dir(struct kvm_vcpu *vcpu, u32 vmcr, int rt) { u32 vid = vcpu_get_reg(vcpu, rt); u64 lr_val; @@ -707,7 +705,7 @@ static void __hyp_text __vgic_v3_write_dir(struct kvm_vcpu *vcpu, __vgic_v3_clear_active_lr(lr, lr_val); } -static void __hyp_text __vgic_v3_write_eoir(struct kvm_vcpu *vcpu, u32 vmcr, int rt) +static void __vgic_v3_write_eoir(struct kvm_vcpu *vcpu, u32 vmcr, int rt) { u32 vid = vcpu_get_reg(vcpu, rt); u64 lr_val; @@ -744,17 +742,17 @@ static void __hyp_text __vgic_v3_write_eoir(struct kvm_vcpu *vcpu, u32 vmcr, int __vgic_v3_clear_active_lr(lr, lr_val); } -static void __hyp_text __vgic_v3_read_igrpen0(struct kvm_vcpu *vcpu, u32 vmcr, int rt) +static void __vgic_v3_read_igrpen0(struct kvm_vcpu *vcpu, u32 vmcr, int rt) { vcpu_set_reg(vcpu, rt, !!(vmcr & ICH_VMCR_ENG0_MASK)); } -static void __hyp_text __vgic_v3_read_igrpen1(struct kvm_vcpu *vcpu, u32 vmcr, int rt) +static void __vgic_v3_read_igrpen1(struct kvm_vcpu *vcpu, u32 vmcr, int rt) { vcpu_set_reg(vcpu, rt, !!(vmcr & ICH_VMCR_ENG1_MASK)); } -static void __hyp_text __vgic_v3_write_igrpen0(struct kvm_vcpu *vcpu, u32 vmcr, int rt) +static void __vgic_v3_write_igrpen0(struct kvm_vcpu *vcpu, u32 vmcr, int rt) { u64 val = vcpu_get_reg(vcpu, rt); @@ -766,7 +764,7 @@ static void __hyp_text __vgic_v3_write_igrpen0(struct kvm_vcpu *vcpu, u32 vmcr, __vgic_v3_write_vmcr(vmcr); } -static void __hyp_text __vgic_v3_write_igrpen1(struct kvm_vcpu *vcpu, u32 vmcr, int rt) +static void __vgic_v3_write_igrpen1(struct kvm_vcpu *vcpu, u32 vmcr, int rt) { u64 val = vcpu_get_reg(vcpu, rt); @@ -778,17 +776,17 @@ static void __hyp_text __vgic_v3_write_igrpen1(struct kvm_vcpu *vcpu, u32 vmcr, __vgic_v3_write_vmcr(vmcr); } -static void __hyp_text __vgic_v3_read_bpr0(struct kvm_vcpu *vcpu, u32 vmcr, int rt) +static void __vgic_v3_read_bpr0(struct kvm_vcpu *vcpu, u32 vmcr, int rt) { vcpu_set_reg(vcpu, rt, __vgic_v3_get_bpr0(vmcr)); } -static void __hyp_text __vgic_v3_read_bpr1(struct kvm_vcpu *vcpu, u32 vmcr, int rt) +static void __vgic_v3_read_bpr1(struct kvm_vcpu *vcpu, u32 vmcr, int rt) { vcpu_set_reg(vcpu, rt, __vgic_v3_get_bpr1(vmcr)); } -static void __hyp_text __vgic_v3_write_bpr0(struct kvm_vcpu *vcpu, u32 vmcr, int rt) +static void __vgic_v3_write_bpr0(struct kvm_vcpu *vcpu, u32 vmcr, int rt) { u64 val = vcpu_get_reg(vcpu, rt); u8 bpr_min = __vgic_v3_bpr_min() - 1; @@ -805,7 +803,7 @@ static void __hyp_text __vgic_v3_write_bpr0(struct kvm_vcpu *vcpu, u32 vmcr, int __vgic_v3_write_vmcr(vmcr); } -static void __hyp_text __vgic_v3_write_bpr1(struct kvm_vcpu *vcpu, u32 vmcr, int rt) +static void __vgic_v3_write_bpr1(struct kvm_vcpu *vcpu, u32 vmcr, int rt) { u64 val = vcpu_get_reg(vcpu, rt); u8 bpr_min = __vgic_v3_bpr_min(); @@ -825,7 +823,7 @@ static void __hyp_text __vgic_v3_write_bpr1(struct kvm_vcpu *vcpu, u32 vmcr, int __vgic_v3_write_vmcr(vmcr); } -static void __hyp_text __vgic_v3_read_apxrn(struct kvm_vcpu *vcpu, int rt, int n) +static void __vgic_v3_read_apxrn(struct kvm_vcpu *vcpu, int rt, int n) { u32 val; @@ -837,7 +835,7 @@ static void __hyp_text __vgic_v3_read_apxrn(struct kvm_vcpu *vcpu, int rt, int n vcpu_set_reg(vcpu, rt, val); } -static void __hyp_text __vgic_v3_write_apxrn(struct kvm_vcpu *vcpu, int rt, int n) +static void __vgic_v3_write_apxrn(struct kvm_vcpu *vcpu, int rt, int n) { u32 val = vcpu_get_reg(vcpu, rt); @@ -847,56 +845,49 @@ static void __hyp_text __vgic_v3_write_apxrn(struct kvm_vcpu *vcpu, int rt, int __vgic_v3_write_ap1rn(val, n); } -static void __hyp_text __vgic_v3_read_apxr0(struct kvm_vcpu *vcpu, +static void __vgic_v3_read_apxr0(struct kvm_vcpu *vcpu, u32 vmcr, int rt) { __vgic_v3_read_apxrn(vcpu, rt, 0); } -static void __hyp_text __vgic_v3_read_apxr1(struct kvm_vcpu *vcpu, +static void __vgic_v3_read_apxr1(struct kvm_vcpu *vcpu, u32 vmcr, int rt) { __vgic_v3_read_apxrn(vcpu, rt, 1); } -static void __hyp_text __vgic_v3_read_apxr2(struct kvm_vcpu *vcpu, - u32 vmcr, int rt) +static void __vgic_v3_read_apxr2(struct kvm_vcpu *vcpu, u32 vmcr, int rt) { __vgic_v3_read_apxrn(vcpu, rt, 2); } -static void __hyp_text __vgic_v3_read_apxr3(struct kvm_vcpu *vcpu, - u32 vmcr, int rt) +static void __vgic_v3_read_apxr3(struct kvm_vcpu *vcpu, u32 vmcr, int rt) { __vgic_v3_read_apxrn(vcpu, rt, 3); } -static void __hyp_text __vgic_v3_write_apxr0(struct kvm_vcpu *vcpu, - u32 vmcr, int rt) +static void __vgic_v3_write_apxr0(struct kvm_vcpu *vcpu, u32 vmcr, int rt) { __vgic_v3_write_apxrn(vcpu, rt, 0); } -static void __hyp_text __vgic_v3_write_apxr1(struct kvm_vcpu *vcpu, - u32 vmcr, int rt) +static void __vgic_v3_write_apxr1(struct kvm_vcpu *vcpu, u32 vmcr, int rt) { __vgic_v3_write_apxrn(vcpu, rt, 1); } -static void __hyp_text __vgic_v3_write_apxr2(struct kvm_vcpu *vcpu, - u32 vmcr, int rt) +static void __vgic_v3_write_apxr2(struct kvm_vcpu *vcpu, u32 vmcr, int rt) { __vgic_v3_write_apxrn(vcpu, rt, 2); } -static void __hyp_text __vgic_v3_write_apxr3(struct kvm_vcpu *vcpu, - u32 vmcr, int rt) +static void __vgic_v3_write_apxr3(struct kvm_vcpu *vcpu, u32 vmcr, int rt) { __vgic_v3_write_apxrn(vcpu, rt, 3); } -static void __hyp_text __vgic_v3_read_hppir(struct kvm_vcpu *vcpu, - u32 vmcr, int rt) +static void __vgic_v3_read_hppir(struct kvm_vcpu *vcpu, u32 vmcr, int rt) { u64 lr_val; int lr, lr_grp, grp; @@ -915,16 +906,14 @@ static void __hyp_text __vgic_v3_read_hppir(struct kvm_vcpu *vcpu, vcpu_set_reg(vcpu, rt, lr_val & ICH_LR_VIRTUAL_ID_MASK); } -static void __hyp_text __vgic_v3_read_pmr(struct kvm_vcpu *vcpu, - u32 vmcr, int rt) +static void __vgic_v3_read_pmr(struct kvm_vcpu *vcpu, u32 vmcr, int rt) { vmcr &= ICH_VMCR_PMR_MASK; vmcr >>= ICH_VMCR_PMR_SHIFT; vcpu_set_reg(vcpu, rt, vmcr); } -static void __hyp_text __vgic_v3_write_pmr(struct kvm_vcpu *vcpu, - u32 vmcr, int rt) +static void __vgic_v3_write_pmr(struct kvm_vcpu *vcpu, u32 vmcr, int rt) { u32 val = vcpu_get_reg(vcpu, rt); @@ -936,15 +925,13 @@ static void __hyp_text __vgic_v3_write_pmr(struct kvm_vcpu *vcpu, write_gicreg(vmcr, ICH_VMCR_EL2); } -static void __hyp_text __vgic_v3_read_rpr(struct kvm_vcpu *vcpu, - u32 vmcr, int rt) +static void __vgic_v3_read_rpr(struct kvm_vcpu *vcpu, u32 vmcr, int rt) { u32 val = __vgic_v3_get_highest_active_priority(); vcpu_set_reg(vcpu, rt, val); } -static void __hyp_text __vgic_v3_read_ctlr(struct kvm_vcpu *vcpu, - u32 vmcr, int rt) +static void __vgic_v3_read_ctlr(struct kvm_vcpu *vcpu, u32 vmcr, int rt) { u32 vtr, val; @@ -965,8 +952,7 @@ static void __hyp_text __vgic_v3_read_ctlr(struct kvm_vcpu *vcpu, vcpu_set_reg(vcpu, rt, val); } -static void __hyp_text __vgic_v3_write_ctlr(struct kvm_vcpu *vcpu, - u32 vmcr, int rt) +static void __vgic_v3_write_ctlr(struct kvm_vcpu *vcpu, u32 vmcr, int rt) { u32 val = vcpu_get_reg(vcpu, rt); @@ -983,7 +969,7 @@ static void __hyp_text __vgic_v3_write_ctlr(struct kvm_vcpu *vcpu, write_gicreg(vmcr, ICH_VMCR_EL2); } -int __hyp_text __vgic_v3_perform_cpuif_access(struct kvm_vcpu *vcpu) +int __vgic_v3_perform_cpuif_access(struct kvm_vcpu *vcpu) { int rt; u32 esr; -- GitLab From f9a026e3d38ba81cd274725f1caaf64322a86aa5 Mon Sep 17 00:00:00 2001 From: David Brazdil Date: Thu, 25 Jun 2020 14:14:20 +0100 Subject: [PATCH 0173/2249] KVM: arm64: Lift instrumentation restrictions on VHE With VHE and nVHE executable code completely separated, remove build config that disabled GCOV/KASAN/UBSAN/KCOV instrumentation for VHE as these now execute under the same memory mappings as the rest of the kernel. No violations are currently being reported by either KASAN or UBSAN. Signed-off-by: David Brazdil Signed-off-by: Marc Zyngier Link: https://lore.kernel.org/r/20200625131420.71444-16-dbrazdil@google.com --- arch/arm64/kvm/hyp/vhe/Makefile | 8 -------- 1 file changed, 8 deletions(-) diff --git a/arch/arm64/kvm/hyp/vhe/Makefile b/arch/arm64/kvm/hyp/vhe/Makefile index 090fd1e14be2b..461e97c375cc7 100644 --- a/arch/arm64/kvm/hyp/vhe/Makefile +++ b/arch/arm64/kvm/hyp/vhe/Makefile @@ -9,11 +9,3 @@ ccflags-y := -D__KVM_VHE_HYPERVISOR__ obj-y := timer-sr.o sysreg-sr.o debug-sr.o switch.o tlb.o obj-y += ../vgic-v3-sr.o ../aarch32.o ../vgic-v2-cpuif-proxy.o ../entry.o \ ../fpsimd.o ../hyp-entry.o - -# KVM code is run at a different exception code with a different map, so -# compiler instrumentation that inserts callbacks or checks into the code may -# cause crashes. Just disable it. -GCOV_PROFILE := n -KASAN_SANITIZE := n -UBSAN_SANITIZE := n -KCOV_INSTRUMENT := n -- GitLab From 731532176716e2775a5d21115bb9c5c61e0cb704 Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Wed, 1 Jul 2020 16:02:06 +0200 Subject: [PATCH 0174/2249] KVM: arm64: vgic-its: Change default outer cacheability for {PEND, PROP}BASER PENDBASER and PROPBASER define the outer caching mode for LPI tables. The memory backing them may not be outer sharable, so we mark them as nC by default. This however, breaks Windows on ARM which only accepts SameAsInner or RaWaWb as values for outer cachability. We do today already allow the outer mode to be set to SameAsInner explicitly, so the easy fix is to default to that instead of nC for situations when an OS asks for a not fulfillable cachability request. This fixes booting Windows in KVM with vgicv3 and ITS enabled for me. Signed-off-by: Alexander Graf Signed-off-by: Marc Zyngier Link: https://lore.kernel.org/r/20200701140206.8664-1-graf@amazon.com --- arch/arm64/kvm/vgic/vgic-mmio-v3.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/kvm/vgic/vgic-mmio-v3.c b/arch/arm64/kvm/vgic/vgic-mmio-v3.c index d2339a2b9fb9c..5c786b915cd34 100644 --- a/arch/arm64/kvm/vgic/vgic-mmio-v3.c +++ b/arch/arm64/kvm/vgic/vgic-mmio-v3.c @@ -389,7 +389,7 @@ u64 vgic_sanitise_outer_cacheability(u64 field) case GIC_BASER_CACHE_nC: return field; default: - return GIC_BASER_CACHE_nC; + return GIC_BASER_CACHE_SameAsInner; } } -- GitLab From 95fa0ba83e66dea0d3af48ad69842ae8c1dd9af2 Mon Sep 17 00:00:00 2001 From: Peng Hao Date: Wed, 1 Jul 2020 08:07:09 -0400 Subject: [PATCH 0175/2249] KVM: arm64: Drop long gone function parameter documentation update_vmid() just has one parameter "vmid".The other parameter "kvm" is no longer used. Signed-off-by: Peng Hao Signed-off-by: Marc Zyngier Link: https://lore.kernel.org/r/20200701120709.388377-1-richard.peng@oppo.com --- arch/arm64/kvm/arm.c | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c index 90cb905614468..5bf9bf54b22c9 100644 --- a/arch/arm64/kvm/arm.c +++ b/arch/arm64/kvm/arm.c @@ -466,7 +466,6 @@ static bool need_new_vmid_gen(struct kvm_vmid *vmid) /** * update_vmid - Update the vmid with a valid VMID for the current generation - * @kvm: The guest that struct vmid belongs to * @vmid: The stage-2 VMID information struct */ static void update_vmid(struct kvm_vmid *vmid) -- GitLab From 3a949f4c93548751a377691b2a208063da05e369 Mon Sep 17 00:00:00 2001 From: Gavin Shan Date: Tue, 30 Jun 2020 11:57:05 +1000 Subject: [PATCH 0176/2249] KVM: arm64: Rename HSR to ESR kvm/arm32 isn't supported since commit 541ad0150ca4 ("arm: Remove 32bit KVM host support"). So HSR isn't meaningful since then. This renames HSR to ESR accordingly. This shouldn't cause any functional changes: * Rename kvm_vcpu_get_hsr() to kvm_vcpu_get_esr() to make the function names self-explanatory. * Rename variables from @hsr to @esr to make them self-explanatory. Note that the renaming on uapi and tracepoint will cause ABI changes, which we should avoid. Specificly, there are 4 related source files in this regard: * arch/arm64/include/uapi/asm/kvm.h (struct kvm_debug_exit_arch::hsr) * arch/arm64/kvm/handle_exit.c (struct kvm_debug_exit_arch::hsr) * arch/arm64/kvm/trace_arm.h (tracepoints) * arch/arm64/kvm/trace_handle_exit.h (tracepoints) Signed-off-by: Gavin Shan Signed-off-by: Marc Zyngier Acked-by: Andrew Scull Link: https://lore.kernel.org/r/20200630015705.103366-1-gshan@redhat.com --- arch/arm64/include/asm/kvm_emulate.h | 34 ++++++++++++++-------------- arch/arm64/kvm/handle_exit.c | 32 +++++++++++++------------- arch/arm64/kvm/hyp/aarch32.c | 2 +- arch/arm64/kvm/hyp/switch.c | 14 ++++++------ arch/arm64/kvm/hyp/vgic-v3-sr.c | 4 ++-- arch/arm64/kvm/mmu.c | 6 ++--- arch/arm64/kvm/sys_regs.c | 28 +++++++++++------------ 7 files changed, 60 insertions(+), 60 deletions(-) diff --git a/arch/arm64/include/asm/kvm_emulate.h b/arch/arm64/include/asm/kvm_emulate.h index 4d0f8ea600ba4..c9ba0df47f7d2 100644 --- a/arch/arm64/include/asm/kvm_emulate.h +++ b/arch/arm64/include/asm/kvm_emulate.h @@ -259,14 +259,14 @@ static inline bool vcpu_mode_priv(const struct kvm_vcpu *vcpu) return mode != PSR_MODE_EL0t; } -static __always_inline u32 kvm_vcpu_get_hsr(const struct kvm_vcpu *vcpu) +static __always_inline u32 kvm_vcpu_get_esr(const struct kvm_vcpu *vcpu) { return vcpu->arch.fault.esr_el2; } static __always_inline int kvm_vcpu_get_condition(const struct kvm_vcpu *vcpu) { - u32 esr = kvm_vcpu_get_hsr(vcpu); + u32 esr = kvm_vcpu_get_esr(vcpu); if (esr & ESR_ELx_CV) return (esr & ESR_ELx_COND_MASK) >> ESR_ELx_COND_SHIFT; @@ -291,64 +291,64 @@ static inline u64 kvm_vcpu_get_disr(const struct kvm_vcpu *vcpu) static inline u32 kvm_vcpu_hvc_get_imm(const struct kvm_vcpu *vcpu) { - return kvm_vcpu_get_hsr(vcpu) & ESR_ELx_xVC_IMM_MASK; + return kvm_vcpu_get_esr(vcpu) & ESR_ELx_xVC_IMM_MASK; } static __always_inline bool kvm_vcpu_dabt_isvalid(const struct kvm_vcpu *vcpu) { - return !!(kvm_vcpu_get_hsr(vcpu) & ESR_ELx_ISV); + return !!(kvm_vcpu_get_esr(vcpu) & ESR_ELx_ISV); } static inline unsigned long kvm_vcpu_dabt_iss_nisv_sanitized(const struct kvm_vcpu *vcpu) { - return kvm_vcpu_get_hsr(vcpu) & (ESR_ELx_CM | ESR_ELx_WNR | ESR_ELx_FSC); + return kvm_vcpu_get_esr(vcpu) & (ESR_ELx_CM | ESR_ELx_WNR | ESR_ELx_FSC); } static inline bool kvm_vcpu_dabt_issext(const struct kvm_vcpu *vcpu) { - return !!(kvm_vcpu_get_hsr(vcpu) & ESR_ELx_SSE); + return !!(kvm_vcpu_get_esr(vcpu) & ESR_ELx_SSE); } static inline bool kvm_vcpu_dabt_issf(const struct kvm_vcpu *vcpu) { - return !!(kvm_vcpu_get_hsr(vcpu) & ESR_ELx_SF); + return !!(kvm_vcpu_get_esr(vcpu) & ESR_ELx_SF); } static __always_inline int kvm_vcpu_dabt_get_rd(const struct kvm_vcpu *vcpu) { - return (kvm_vcpu_get_hsr(vcpu) & ESR_ELx_SRT_MASK) >> ESR_ELx_SRT_SHIFT; + return (kvm_vcpu_get_esr(vcpu) & ESR_ELx_SRT_MASK) >> ESR_ELx_SRT_SHIFT; } static __always_inline bool kvm_vcpu_dabt_iss1tw(const struct kvm_vcpu *vcpu) { - return !!(kvm_vcpu_get_hsr(vcpu) & ESR_ELx_S1PTW); + return !!(kvm_vcpu_get_esr(vcpu) & ESR_ELx_S1PTW); } static __always_inline bool kvm_vcpu_dabt_iswrite(const struct kvm_vcpu *vcpu) { - return !!(kvm_vcpu_get_hsr(vcpu) & ESR_ELx_WNR) || + return !!(kvm_vcpu_get_esr(vcpu) & ESR_ELx_WNR) || kvm_vcpu_dabt_iss1tw(vcpu); /* AF/DBM update */ } static inline bool kvm_vcpu_dabt_is_cm(const struct kvm_vcpu *vcpu) { - return !!(kvm_vcpu_get_hsr(vcpu) & ESR_ELx_CM); + return !!(kvm_vcpu_get_esr(vcpu) & ESR_ELx_CM); } static __always_inline unsigned int kvm_vcpu_dabt_get_as(const struct kvm_vcpu *vcpu) { - return 1 << ((kvm_vcpu_get_hsr(vcpu) & ESR_ELx_SAS) >> ESR_ELx_SAS_SHIFT); + return 1 << ((kvm_vcpu_get_esr(vcpu) & ESR_ELx_SAS) >> ESR_ELx_SAS_SHIFT); } /* This one is not specific to Data Abort */ static __always_inline bool kvm_vcpu_trap_il_is32bit(const struct kvm_vcpu *vcpu) { - return !!(kvm_vcpu_get_hsr(vcpu) & ESR_ELx_IL); + return !!(kvm_vcpu_get_esr(vcpu) & ESR_ELx_IL); } static __always_inline u8 kvm_vcpu_trap_get_class(const struct kvm_vcpu *vcpu) { - return ESR_ELx_EC(kvm_vcpu_get_hsr(vcpu)); + return ESR_ELx_EC(kvm_vcpu_get_esr(vcpu)); } static inline bool kvm_vcpu_trap_is_iabt(const struct kvm_vcpu *vcpu) @@ -358,12 +358,12 @@ static inline bool kvm_vcpu_trap_is_iabt(const struct kvm_vcpu *vcpu) static __always_inline u8 kvm_vcpu_trap_get_fault(const struct kvm_vcpu *vcpu) { - return kvm_vcpu_get_hsr(vcpu) & ESR_ELx_FSC; + return kvm_vcpu_get_esr(vcpu) & ESR_ELx_FSC; } static __always_inline u8 kvm_vcpu_trap_get_fault_type(const struct kvm_vcpu *vcpu) { - return kvm_vcpu_get_hsr(vcpu) & ESR_ELx_FSC_TYPE; + return kvm_vcpu_get_esr(vcpu) & ESR_ELx_FSC_TYPE; } static __always_inline bool kvm_vcpu_dabt_isextabt(const struct kvm_vcpu *vcpu) @@ -387,7 +387,7 @@ static __always_inline bool kvm_vcpu_dabt_isextabt(const struct kvm_vcpu *vcpu) static __always_inline int kvm_vcpu_sys_get_rt(struct kvm_vcpu *vcpu) { - u32 esr = kvm_vcpu_get_hsr(vcpu); + u32 esr = kvm_vcpu_get_esr(vcpu); return ESR_ELx_SYS64_ISS_RT(esr); } diff --git a/arch/arm64/kvm/handle_exit.c b/arch/arm64/kvm/handle_exit.c index 5a02d4c90559e..98ab331399826 100644 --- a/arch/arm64/kvm/handle_exit.c +++ b/arch/arm64/kvm/handle_exit.c @@ -89,7 +89,7 @@ static int handle_no_fpsimd(struct kvm_vcpu *vcpu, struct kvm_run *run) */ static int kvm_handle_wfx(struct kvm_vcpu *vcpu, struct kvm_run *run) { - if (kvm_vcpu_get_hsr(vcpu) & ESR_ELx_WFx_ISS_WFE) { + if (kvm_vcpu_get_esr(vcpu) & ESR_ELx_WFx_ISS_WFE) { trace_kvm_wfx_arm64(*vcpu_pc(vcpu), true); vcpu->stat.wfe_exit_stat++; kvm_vcpu_on_spin(vcpu, vcpu_mode_priv(vcpu)); @@ -119,13 +119,13 @@ static int kvm_handle_wfx(struct kvm_vcpu *vcpu, struct kvm_run *run) */ static int kvm_handle_guest_debug(struct kvm_vcpu *vcpu, struct kvm_run *run) { - u32 hsr = kvm_vcpu_get_hsr(vcpu); + u32 esr = kvm_vcpu_get_esr(vcpu); int ret = 0; run->exit_reason = KVM_EXIT_DEBUG; - run->debug.arch.hsr = hsr; + run->debug.arch.hsr = esr; - switch (ESR_ELx_EC(hsr)) { + switch (ESR_ELx_EC(esr)) { case ESR_ELx_EC_WATCHPT_LOW: run->debug.arch.far = vcpu->arch.fault.far_el2; /* fall through */ @@ -135,8 +135,8 @@ static int kvm_handle_guest_debug(struct kvm_vcpu *vcpu, struct kvm_run *run) case ESR_ELx_EC_BRK64: break; default: - kvm_err("%s: un-handled case hsr: %#08x\n", - __func__, (unsigned int) hsr); + kvm_err("%s: un-handled case esr: %#08x\n", + __func__, (unsigned int) esr); ret = -1; break; } @@ -146,10 +146,10 @@ static int kvm_handle_guest_debug(struct kvm_vcpu *vcpu, struct kvm_run *run) static int kvm_handle_unknown_ec(struct kvm_vcpu *vcpu, struct kvm_run *run) { - u32 hsr = kvm_vcpu_get_hsr(vcpu); + u32 esr = kvm_vcpu_get_esr(vcpu); - kvm_pr_unimpl("Unknown exception class: hsr: %#08x -- %s\n", - hsr, esr_get_class_string(hsr)); + kvm_pr_unimpl("Unknown exception class: esr: %#08x -- %s\n", + esr, esr_get_class_string(esr)); kvm_inject_undefined(vcpu); return 1; @@ -200,10 +200,10 @@ static exit_handle_fn arm_exit_handlers[] = { static exit_handle_fn kvm_get_exit_handler(struct kvm_vcpu *vcpu) { - u32 hsr = kvm_vcpu_get_hsr(vcpu); - u8 hsr_ec = ESR_ELx_EC(hsr); + u32 esr = kvm_vcpu_get_esr(vcpu); + u8 esr_ec = ESR_ELx_EC(esr); - return arm_exit_handlers[hsr_ec]; + return arm_exit_handlers[esr_ec]; } /* @@ -241,15 +241,15 @@ int handle_exit(struct kvm_vcpu *vcpu, struct kvm_run *run, int exception_index) { if (ARM_SERROR_PENDING(exception_index)) { - u8 hsr_ec = ESR_ELx_EC(kvm_vcpu_get_hsr(vcpu)); + u8 esr_ec = ESR_ELx_EC(kvm_vcpu_get_esr(vcpu)); /* * HVC/SMC already have an adjusted PC, which we need * to correct in order to return to after having * injected the SError. */ - if (hsr_ec == ESR_ELx_EC_HVC32 || hsr_ec == ESR_ELx_EC_HVC64 || - hsr_ec == ESR_ELx_EC_SMC32 || hsr_ec == ESR_ELx_EC_SMC64) { + if (esr_ec == ESR_ELx_EC_HVC32 || esr_ec == ESR_ELx_EC_HVC64 || + esr_ec == ESR_ELx_EC_SMC32 || esr_ec == ESR_ELx_EC_SMC64) { u32 adj = kvm_vcpu_trap_il_is32bit(vcpu) ? 4 : 2; *vcpu_pc(vcpu) -= adj; } @@ -307,5 +307,5 @@ void handle_exit_early(struct kvm_vcpu *vcpu, struct kvm_run *run, exception_index = ARM_EXCEPTION_CODE(exception_index); if (exception_index == ARM_EXCEPTION_EL1_SERROR) - kvm_handle_guest_serror(vcpu, kvm_vcpu_get_hsr(vcpu)); + kvm_handle_guest_serror(vcpu, kvm_vcpu_get_esr(vcpu)); } diff --git a/arch/arm64/kvm/hyp/aarch32.c b/arch/arm64/kvm/hyp/aarch32.c index 25c0e47d57cbe..1e948704d60ff 100644 --- a/arch/arm64/kvm/hyp/aarch32.c +++ b/arch/arm64/kvm/hyp/aarch32.c @@ -51,7 +51,7 @@ bool __hyp_text kvm_condition_valid32(const struct kvm_vcpu *vcpu) int cond; /* Top two bits non-zero? Unconditional. */ - if (kvm_vcpu_get_hsr(vcpu) >> 30) + if (kvm_vcpu_get_esr(vcpu) >> 30) return true; /* Is condition field valid? */ diff --git a/arch/arm64/kvm/hyp/switch.c b/arch/arm64/kvm/hyp/switch.c index db1c4487d95d1..5164074c1ae1b 100644 --- a/arch/arm64/kvm/hyp/switch.c +++ b/arch/arm64/kvm/hyp/switch.c @@ -356,7 +356,7 @@ static bool __hyp_text __populate_fault_info(struct kvm_vcpu *vcpu) static bool __hyp_text __hyp_handle_fpsimd(struct kvm_vcpu *vcpu) { bool vhe, sve_guest, sve_host; - u8 hsr_ec; + u8 esr_ec; if (!system_supports_fpsimd()) return false; @@ -371,14 +371,14 @@ static bool __hyp_text __hyp_handle_fpsimd(struct kvm_vcpu *vcpu) vhe = has_vhe(); } - hsr_ec = kvm_vcpu_trap_get_class(vcpu); - if (hsr_ec != ESR_ELx_EC_FP_ASIMD && - hsr_ec != ESR_ELx_EC_SVE) + esr_ec = kvm_vcpu_trap_get_class(vcpu); + if (esr_ec != ESR_ELx_EC_FP_ASIMD && + esr_ec != ESR_ELx_EC_SVE) return false; /* Don't handle SVE traps for non-SVE vcpus here: */ if (!sve_guest) - if (hsr_ec != ESR_ELx_EC_FP_ASIMD) + if (esr_ec != ESR_ELx_EC_FP_ASIMD) return false; /* Valid trap. Switch the context: */ @@ -437,7 +437,7 @@ static bool __hyp_text __hyp_handle_fpsimd(struct kvm_vcpu *vcpu) static bool __hyp_text handle_tx2_tvm(struct kvm_vcpu *vcpu) { - u32 sysreg = esr_sys64_to_sysreg(kvm_vcpu_get_hsr(vcpu)); + u32 sysreg = esr_sys64_to_sysreg(kvm_vcpu_get_esr(vcpu)); int rt = kvm_vcpu_sys_get_rt(vcpu); u64 val = vcpu_get_reg(vcpu, rt); @@ -529,7 +529,7 @@ static bool __hyp_text __hyp_handle_ptrauth(struct kvm_vcpu *vcpu) u64 val; if (!vcpu_has_ptrauth(vcpu) || - !esr_is_ptrauth_trap(kvm_vcpu_get_hsr(vcpu))) + !esr_is_ptrauth_trap(kvm_vcpu_get_esr(vcpu))) return false; ctxt = &__hyp_this_cpu_ptr(kvm_host_data)->host_ctxt; diff --git a/arch/arm64/kvm/hyp/vgic-v3-sr.c b/arch/arm64/kvm/hyp/vgic-v3-sr.c index 10ed539835c14..bee0a74671ca8 100644 --- a/arch/arm64/kvm/hyp/vgic-v3-sr.c +++ b/arch/arm64/kvm/hyp/vgic-v3-sr.c @@ -426,7 +426,7 @@ static int __hyp_text __vgic_v3_bpr_min(void) static int __hyp_text __vgic_v3_get_group(struct kvm_vcpu *vcpu) { - u32 esr = kvm_vcpu_get_hsr(vcpu); + u32 esr = kvm_vcpu_get_esr(vcpu); u8 crm = (esr & ESR_ELx_SYS64_ISS_CRM_MASK) >> ESR_ELx_SYS64_ISS_CRM_SHIFT; return crm != 8; @@ -992,7 +992,7 @@ int __hyp_text __vgic_v3_perform_cpuif_access(struct kvm_vcpu *vcpu) bool is_read; u32 sysreg; - esr = kvm_vcpu_get_hsr(vcpu); + esr = kvm_vcpu_get_esr(vcpu); if (vcpu_mode_is_32bit(vcpu)) { if (!kvm_condition_valid(vcpu)) { __kvm_skip_instr(vcpu); diff --git a/arch/arm64/kvm/mmu.c b/arch/arm64/kvm/mmu.c index 8c0035cab6b62..36506112480ea 100644 --- a/arch/arm64/kvm/mmu.c +++ b/arch/arm64/kvm/mmu.c @@ -2079,7 +2079,7 @@ int kvm_handle_guest_abort(struct kvm_vcpu *vcpu, struct kvm_run *run) * For RAS the host kernel may handle this abort. * There is no need to pass the error into the guest. */ - if (!kvm_handle_guest_sea(fault_ipa, kvm_vcpu_get_hsr(vcpu))) + if (!kvm_handle_guest_sea(fault_ipa, kvm_vcpu_get_esr(vcpu))) return 1; if (unlikely(!is_iabt)) { @@ -2088,7 +2088,7 @@ int kvm_handle_guest_abort(struct kvm_vcpu *vcpu, struct kvm_run *run) } } - trace_kvm_guest_fault(*vcpu_pc(vcpu), kvm_vcpu_get_hsr(vcpu), + trace_kvm_guest_fault(*vcpu_pc(vcpu), kvm_vcpu_get_esr(vcpu), kvm_vcpu_get_hfar(vcpu), fault_ipa); /* Check the stage-2 fault is trans. fault or write fault */ @@ -2097,7 +2097,7 @@ int kvm_handle_guest_abort(struct kvm_vcpu *vcpu, struct kvm_run *run) kvm_err("Unsupported FSC: EC=%#x xFSC=%#lx ESR_EL2=%#lx\n", kvm_vcpu_trap_get_class(vcpu), (unsigned long)kvm_vcpu_trap_get_fault(vcpu), - (unsigned long)kvm_vcpu_get_hsr(vcpu)); + (unsigned long)kvm_vcpu_get_esr(vcpu)); return -EFAULT; } diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c index baf5ce9225cee..a96dd62a90ce9 100644 --- a/arch/arm64/kvm/sys_regs.c +++ b/arch/arm64/kvm/sys_regs.c @@ -2220,10 +2220,10 @@ static int emulate_cp(struct kvm_vcpu *vcpu, static void unhandled_cp_access(struct kvm_vcpu *vcpu, struct sys_reg_params *params) { - u8 hsr_ec = kvm_vcpu_trap_get_class(vcpu); + u8 esr_ec = kvm_vcpu_trap_get_class(vcpu); int cp = -1; - switch(hsr_ec) { + switch (esr_ec) { case ESR_ELx_EC_CP15_32: case ESR_ELx_EC_CP15_64: cp = 15; @@ -2254,17 +2254,17 @@ static int kvm_handle_cp_64(struct kvm_vcpu *vcpu, size_t nr_specific) { struct sys_reg_params params; - u32 hsr = kvm_vcpu_get_hsr(vcpu); + u32 esr = kvm_vcpu_get_esr(vcpu); int Rt = kvm_vcpu_sys_get_rt(vcpu); - int Rt2 = (hsr >> 10) & 0x1f; + int Rt2 = (esr >> 10) & 0x1f; params.is_aarch32 = true; params.is_32bit = false; - params.CRm = (hsr >> 1) & 0xf; - params.is_write = ((hsr & 1) == 0); + params.CRm = (esr >> 1) & 0xf; + params.is_write = ((esr & 1) == 0); params.Op0 = 0; - params.Op1 = (hsr >> 16) & 0xf; + params.Op1 = (esr >> 16) & 0xf; params.Op2 = 0; params.CRn = 0; @@ -2311,18 +2311,18 @@ static int kvm_handle_cp_32(struct kvm_vcpu *vcpu, size_t nr_specific) { struct sys_reg_params params; - u32 hsr = kvm_vcpu_get_hsr(vcpu); + u32 esr = kvm_vcpu_get_esr(vcpu); int Rt = kvm_vcpu_sys_get_rt(vcpu); params.is_aarch32 = true; params.is_32bit = true; - params.CRm = (hsr >> 1) & 0xf; + params.CRm = (esr >> 1) & 0xf; params.regval = vcpu_get_reg(vcpu, Rt); - params.is_write = ((hsr & 1) == 0); - params.CRn = (hsr >> 10) & 0xf; + params.is_write = ((esr & 1) == 0); + params.CRn = (esr >> 10) & 0xf; params.Op0 = 0; - params.Op1 = (hsr >> 14) & 0x7; - params.Op2 = (hsr >> 17) & 0x7; + params.Op1 = (esr >> 14) & 0x7; + params.Op2 = (esr >> 17) & 0x7; if (!emulate_cp(vcpu, ¶ms, target_specific, nr_specific) || !emulate_cp(vcpu, ¶ms, global, nr_global)) { @@ -2421,7 +2421,7 @@ static void reset_sys_reg_descs(struct kvm_vcpu *vcpu, int kvm_handle_sys_reg(struct kvm_vcpu *vcpu, struct kvm_run *run) { struct sys_reg_params params; - unsigned long esr = kvm_vcpu_get_hsr(vcpu); + unsigned long esr = kvm_vcpu_get_esr(vcpu); int Rt = kvm_vcpu_sys_get_rt(vcpu); int ret; -- GitLab From 81357f818f3e21963aa7630874bfc941330ef4d4 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Tue, 23 Jun 2020 12:16:37 +0100 Subject: [PATCH 0177/2249] backlight: lms501kf03: Remove unused const variables MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit W=1 kernel build reports: drivers/video/backlight/lms501kf03.c:96:28: warning: ‘seq_sleep_in’ defined but not used [-Wunused-const-variable=] 96 | static const unsigned char seq_sleep_in[] = { | ^~~~~~~~~~~~ drivers/video/backlight/lms501kf03.c:92:28: warning: ‘seq_up_dn’ defined but not used [-Wunused-const-variable=] 92 | static const unsigned char seq_up_dn[] = { | ^~~~~~~~~ Either 'seq_sleep_in' nor 'seq_up_dn' have been used since the driver first landed in 2013. Cc: Bartlomiej Zolnierkiewicz Signed-off-by: Lee Jones Reviewed-by: Daniel Thompson Reviewed-by: Sam Ravnborg Signed-off-by: Lee Jones --- drivers/video/backlight/lms501kf03.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/drivers/video/backlight/lms501kf03.c b/drivers/video/backlight/lms501kf03.c index 52d3ee6c3f7f9..f949b66dce1be 100644 --- a/drivers/video/backlight/lms501kf03.c +++ b/drivers/video/backlight/lms501kf03.c @@ -88,14 +88,6 @@ static const unsigned char seq_rgb_gamma[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }; -static const unsigned char seq_up_dn[] = { - 0x36, 0x10, -}; - -static const unsigned char seq_sleep_in[] = { - 0x10, -}; - static const unsigned char seq_sleep_out[] = { 0x11, }; -- GitLab From 4160ebacd3579651c5fd9cb1d27dc2205adb13d7 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Tue, 23 Jun 2020 12:27:10 +0100 Subject: [PATCH 0178/2249] backlight: lcd: Add missing kerneldoc entry for 'struct device parent' This has been missing since the conversion to 'struct device' in 2007. Cc: Bartlomiej Zolnierkiewicz Cc: Jamey Hicks Cc: Andrew Zabolotny Signed-off-by: Lee Jones Reviewed-by: Daniel Thompson Reviewed-by: Sam Ravnborg Signed-off-by: Lee Jones --- drivers/video/backlight/lcd.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/video/backlight/lcd.c b/drivers/video/backlight/lcd.c index 78b0333586258..db56e465aaff3 100644 --- a/drivers/video/backlight/lcd.c +++ b/drivers/video/backlight/lcd.c @@ -179,6 +179,7 @@ ATTRIBUTE_GROUPS(lcd_device); * lcd_device_register - register a new object of lcd_device class. * @name: the name of the new object(must be the same as the name of the * respective framebuffer device). + * @parent: pointer to the parent's struct device . * @devdata: an optional pointer to be stored in the device. The * methods may retrieve it by using lcd_get_data(ld). * @ops: the lcd operations structure. -- GitLab From 0e0428be20fac07989bdccc4c2836cdfe2ff5ec4 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Tue, 23 Jun 2020 12:41:34 +0100 Subject: [PATCH 0179/2249] backlight: ili922x: Add missing kerneldoc descriptions for CHECK_FREQ_REG() args Kerneldoc syntax is used, but not complete. Descriptions required. Prevents warnings like: drivers/video/backlight/ili922x.c:116: warning: Function parameter or member 's' not described in 'CHECK_FREQ_REG' drivers/video/backlight/ili922x.c:116: warning: Function parameter or member 'x' not described in 'CHECK_FREQ_REG' Cc: Bartlomiej Zolnierkiewicz Cc: Software Engineering Signed-off-by: Lee Jones Reviewed-by: Daniel Thompson Reviewed-by: Sam Ravnborg Signed-off-by: Lee Jones --- drivers/video/backlight/ili922x.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/video/backlight/ili922x.c b/drivers/video/backlight/ili922x.c index 9c5aa3fbb2842..5914147b2c4b9 100644 --- a/drivers/video/backlight/ili922x.c +++ b/drivers/video/backlight/ili922x.c @@ -107,6 +107,8 @@ * lower frequency when the registers are read/written. * The macro sets the frequency in the spi_transfer structure if * the frequency exceeds the maximum value. + * @s: pointer to an SPI device + * @x: pointer to the read/write buffer pair */ #define CHECK_FREQ_REG(s, x) \ do { \ -- GitLab From ee555c1dbe69d7de80d11ebbe5c9589726e12ed9 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Tue, 23 Jun 2020 12:44:05 +0100 Subject: [PATCH 0180/2249] backlight: ili922x: Remove invalid use of kerneldoc syntax Kerneldoc is for documenting function arguments and return values. Prevents warnings like: drivers/video/backlight/ili922x.c:127: warning: cannot understand function prototype: 'int ili922x_id = 1; ' drivers/video/backlight/ili922x.c:136: warning: cannot understand function prototype: 'struct ili922x ' Cc: Bartlomiej Zolnierkiewicz Cc: Software Engineering Signed-off-by: Lee Jones Reviewed-by: Daniel Thompson Reviewed-by: Sam Ravnborg Signed-off-by: Lee Jones --- drivers/video/backlight/ili922x.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/video/backlight/ili922x.c b/drivers/video/backlight/ili922x.c index 5914147b2c4b9..fe03fb058ef06 100644 --- a/drivers/video/backlight/ili922x.c +++ b/drivers/video/backlight/ili922x.c @@ -123,7 +123,7 @@ #define set_tx_byte(b) (tx_invert ? ~(b) : b) -/** +/* * ili922x_id - id as set by manufacturer */ static int ili922x_id = 1; @@ -132,7 +132,7 @@ module_param(ili922x_id, int, 0); static int tx_invert; module_param(tx_invert, int, 0); -/** +/* * driver's private structure */ struct ili922x { -- GitLab From 7099c930fa71438f1b46350f693e3e6d7e627482 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Tue, 23 Jun 2020 12:48:41 +0100 Subject: [PATCH 0181/2249] backlight: ili922x: Add missing kerneldoc description for ili922x_reg_dump()'s arg Kerneldoc syntax is used, but not complete. Descriptions required. Prevents warnings like: drivers/video/backlight/ili922x.c:298: warning: Function parameter or member 'spi' not described in 'ili922x_reg_dump' Cc: Bartlomiej Zolnierkiewicz Cc: Software Engineering Signed-off-by: Lee Jones Reviewed-by: Daniel Thompson Reviewed-by: Sam Ravnborg Signed-off-by: Lee Jones --- drivers/video/backlight/ili922x.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/video/backlight/ili922x.c b/drivers/video/backlight/ili922x.c index fe03fb058ef06..328aba9cddad1 100644 --- a/drivers/video/backlight/ili922x.c +++ b/drivers/video/backlight/ili922x.c @@ -295,6 +295,8 @@ static int ili922x_write(struct spi_device *spi, u8 reg, u16 value) #ifdef DEBUG /** * ili922x_reg_dump - dump all registers + * + * @spi: pointer to an SPI device */ static void ili922x_reg_dump(struct spi_device *spi) { -- GitLab From 6c05632d6341ced4c2cb431ed0e5f617cc83f5bb Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Tue, 23 Jun 2020 15:04:36 +0100 Subject: [PATCH 0182/2249] backlight: backlight: Supply description for function args in existing Kerneldocs Kerneldoc syntax is used, but not complete. Descriptions required. Prevents warnings like: drivers/video/backlight/backlight.c:329: warning: Function parameter or member 'reason' not described in 'backlight_force_update' drivers/video/backlight/backlight.c:354: warning: Function parameter or member 'props' not described in 'backlight_device_register' Cc: Bartlomiej Zolnierkiewicz Cc: Jamey Hicks Cc: Andrew Zabolotny Signed-off-by: Lee Jones Reviewed-by: Daniel Thompson Reviewed-by: Sam Ravnborg Signed-off-by: Lee Jones --- drivers/video/backlight/backlight.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/video/backlight/backlight.c b/drivers/video/backlight/backlight.c index 92d80aa0c0ef1..744ba58488e01 100644 --- a/drivers/video/backlight/backlight.c +++ b/drivers/video/backlight/backlight.c @@ -320,6 +320,7 @@ ATTRIBUTE_GROUPS(bl_device); * backlight_force_update - tell the backlight subsystem that hardware state * has changed * @bd: the backlight device to update + * @reason: reason for update * * Updates the internal state of the backlight in response to a hardware event, * and generate a uevent to notify userspace @@ -344,6 +345,7 @@ EXPORT_SYMBOL(backlight_force_update); * @devdata: an optional pointer to be stored for private driver use. The * methods may retrieve it by using bl_get_data(bd). * @ops: the backlight operations structure. + * @props: pointer to backlight's properties structure. * * Creates and registers new backlight device. Returns either an * ERR_PTR() or a pointer to the newly allocated device. -- GitLab From 3e799ccda3651a43ef3b366f70101e16e5054865 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Tue, 23 Jun 2020 15:37:50 +0100 Subject: [PATCH 0183/2249] backlight: lm3630a_bl: Remove invalid checks for unsigned int < 0 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit unsigned ints 'sources' and 'bank' cannot be less than LM3630A_SINK_0 (0) and LM3630A_BANK_0 (0) respecitively, so change the logic to only check for thier two possible valid values. Fixes W=1 warnings: drivers/video/backlight/lm3630a_bl.c: In function ‘lm3630a_parse_led_sources’: drivers/video/backlight/lm3630a_bl.c:394:18: warning: comparison of unsigned expression < 0 is always false [-Wtype-limits] 394 | if (sources[i] < LM3630A_SINK_0 || sources[i] > LM3630A_SINK_1) | ^ drivers/video/backlight/lm3630a_bl.c: In function ‘lm3630a_parse_bank’: drivers/video/backlight/lm3630a_bl.c:415:11: warning: comparison of unsigned expression < 0 is always false [-Wtype-limits] 415 | if (bank < LM3630A_BANK_0 || bank > LM3630A_BANK_1) | ^ Cc: Bartlomiej Zolnierkiewicz Cc: Daniel Jeong Cc: LDD MLP Signed-off-by: Lee Jones Reviewed-by: Daniel Thompson Reviewed-by: Sam Ravnborg Signed-off-by: Lee Jones --- drivers/video/backlight/lm3630a_bl.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/video/backlight/lm3630a_bl.c b/drivers/video/backlight/lm3630a_bl.c index ee320883b7108..e88a2b0e59046 100644 --- a/drivers/video/backlight/lm3630a_bl.c +++ b/drivers/video/backlight/lm3630a_bl.c @@ -391,7 +391,7 @@ static int lm3630a_parse_led_sources(struct fwnode_handle *node, return ret; for (i = 0; i < num_sources; i++) { - if (sources[i] < LM3630A_SINK_0 || sources[i] > LM3630A_SINK_1) + if (sources[i] != LM3630A_SINK_0 && sources[i] != LM3630A_SINK_1) return -EINVAL; ret |= BIT(sources[i]); @@ -412,7 +412,7 @@ static int lm3630a_parse_bank(struct lm3630a_platform_data *pdata, if (ret) return ret; - if (bank < LM3630A_BANK_0 || bank > LM3630A_BANK_1) + if (bank != LM3630A_BANK_0 && bank != LM3630A_BANK_1) return -EINVAL; led_sources = lm3630a_parse_led_sources(node, BIT(bank)); -- GitLab From e17c7461a28ce7f0cc2c1aec307584dccd04a847 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Tue, 23 Jun 2020 15:47:02 +0100 Subject: [PATCH 0184/2249] backlight: qcom-wled: Remove unused configs for LED3 and LED4 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes W=1 warnings: drivers/video/backlight/qcom-wled.c:1294:34: warning: ‘wled4_string_cfg’ defined but not used [-Wunused-const-variable=] 1294 | static const struct wled_var_cfg wled4_string_cfg = { | ^~~~~~~~~~~~~~~~ drivers/video/backlight/qcom-wled.c:1290:34: warning: ‘wled3_string_cfg’ defined but not used [-Wunused-const-variable=] 1290 | static const struct wled_var_cfg wled3_string_cfg = { | ^~~~~~~~~~~~~~~~ Cc: Andy Gross Cc: Bjorn Andersson Cc: Bartlomiej Zolnierkiewicz Cc: linux-arm-msm@vger.kernel.org Signed-off-by: Lee Jones Reviewed-by: Daniel Thompson Reviewed-by: Sam Ravnborg Signed-off-by: Lee Jones --- drivers/video/backlight/qcom-wled.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/drivers/video/backlight/qcom-wled.c b/drivers/video/backlight/qcom-wled.c index 4c8c34b994414..c25c31199952c 100644 --- a/drivers/video/backlight/qcom-wled.c +++ b/drivers/video/backlight/qcom-wled.c @@ -1287,14 +1287,6 @@ static const struct wled_var_cfg wled4_string_i_limit_cfg = { .size = ARRAY_SIZE(wled4_string_i_limit_values), }; -static const struct wled_var_cfg wled3_string_cfg = { - .size = 8, -}; - -static const struct wled_var_cfg wled4_string_cfg = { - .size = 16, -}; - static const struct wled_var_cfg wled5_mod_sel_cfg = { .size = 2, }; -- GitLab From 6fef0d4ea575c0561b38fd9149a05f1acb505bc0 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Tue, 23 Jun 2020 08:55:47 +0100 Subject: [PATCH 0185/2249] mfd: twl4030-irq: Fix incorrect type in assignment warning Silences Sparse warning: drivers/mfd/twl4030-irq.c:485:26: warning: incorrect type in assignment (different base types) drivers/mfd/twl4030-irq.c:485:26: expected unsigned int [usertype] word drivers/mfd/twl4030-irq.c:485:26: got restricted __le32 [usertype] Cc: Tony Lindgren Cc: Kai Svahn Cc: Syed Khasim Cc: linux-omap@vger.kernel.org Signed-off-by: Lee Jones --- drivers/mfd/twl4030-irq.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mfd/twl4030-irq.c b/drivers/mfd/twl4030-irq.c index 910a304b397ce..d05bc74daba32 100644 --- a/drivers/mfd/twl4030-irq.c +++ b/drivers/mfd/twl4030-irq.c @@ -477,7 +477,7 @@ static void twl4030_sih_bus_sync_unlock(struct irq_data *data) if (agent->imr_change_pending) { union { - u32 word; + __le32 word; u8 bytes[4]; } imr; -- GitLab From b174015b1ddd0a7009acaf6aa7019e9883b0f75b Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Tue, 23 Jun 2020 09:01:07 +0100 Subject: [PATCH 0186/2249] mfd: twl4030-irq: Fix cast to restricted __le32 warning Silences Sparse warning(s): drivers/mfd/twl4030-irq.c:573:40: warning: cast to restricted __le32 drivers/mfd/twl4030-irq.c:573:40: warning: cast to restricted __le32 drivers/mfd/twl4030-irq.c:573:40: warning: cast to restricted __le32 drivers/mfd/twl4030-irq.c:573:40: warning: cast to restricted __le32 drivers/mfd/twl4030-irq.c:573:40: warning: cast to restricted __le32 drivers/mfd/twl4030-irq.c:573:40: warning: cast to restricted __le32 Cc: Tony Lindgren Cc: Kai Svahn Cc: Syed Khasim Cc: linux-omap@vger.kernel.org Signed-off-by: Lee Jones --- drivers/mfd/twl4030-irq.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mfd/twl4030-irq.c b/drivers/mfd/twl4030-irq.c index d05bc74daba32..ab417438d1faa 100644 --- a/drivers/mfd/twl4030-irq.c +++ b/drivers/mfd/twl4030-irq.c @@ -561,7 +561,7 @@ static inline int sih_read_isr(const struct sih *sih) int status; union { u8 bytes[4]; - u32 word; + __le32 word; } isr; /* FIXME need retry-on-error ... */ -- GitLab From c504a2486ab67cd9fc38940ad2841075d6a3e9a4 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Tue, 23 Jun 2020 09:15:56 +0100 Subject: [PATCH 0187/2249] mfd: tps6586x: Fix cast to restricted __le32 warning Silences Sparse warning(s): drivers/mfd/tps6586x.c:323:16: warning: cast to restricted __le32 drivers/mfd/tps6586x.c:323:16: warning: cast to restricted __le32 drivers/mfd/tps6586x.c:323:16: warning: cast to restricted __le32 drivers/mfd/tps6586x.c:323:16: warning: cast to restricted __le32 drivers/mfd/tps6586x.c:323:16: warning: cast to restricted __le32 drivers/mfd/tps6586x.c:323:16: warning: cast to restricted __le32 Cc: Mike Rapoport Cc: Eric Miao Signed-off-by: Lee Jones --- drivers/mfd/tps6586x.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/mfd/tps6586x.c b/drivers/mfd/tps6586x.c index c8aadd39324e3..c36597797ddd8 100644 --- a/drivers/mfd/tps6586x.c +++ b/drivers/mfd/tps6586x.c @@ -309,18 +309,19 @@ static const struct irq_domain_ops tps6586x_domain_ops = { static irqreturn_t tps6586x_irq(int irq, void *data) { struct tps6586x *tps6586x = data; - u32 acks; + uint32_t acks; + __le32 val; int ret = 0; ret = tps6586x_reads(tps6586x->dev, TPS6586X_INT_ACK1, - sizeof(acks), (uint8_t *)&acks); + sizeof(acks), (uint8_t *)&val); if (ret < 0) { dev_err(tps6586x->dev, "failed to read interrupt status\n"); return IRQ_NONE; } - acks = le32_to_cpu(acks); + acks = le32_to_cpu(val); while (acks) { int i = __ffs(acks); -- GitLab From d9ca7801b6e5ffdfd7a4ed3f287b277895e63e90 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Tue, 23 Jun 2020 09:55:05 +0100 Subject: [PATCH 0188/2249] mfd: altera-sysmgr: Fix physical address storing hacks Sparse reports: drivers/mfd/altera-sysmgr.c:150:30: warning: incorrect type in assignment (different address spaces) drivers/mfd/altera-sysmgr.c:150:30: expected unsigned int [usertype] *base drivers/mfd/altera-sysmgr.c:150:30: got void [noderef] * drivers/mfd/altera-sysmgr.c:156:26: warning: incorrect type in argument 3 (different address spaces) drivers/mfd/altera-sysmgr.c:156:26: expected void [noderef] *regs drivers/mfd/altera-sysmgr.c:156:26: got unsigned int [usertype] *base It appears as though the driver data property 'resource_size_t *base' was being used to store 2 different types of addresses (physical and IO-mapped) under a single declared type. Fortunately, no value is recalled from the driver data entry, so it can be easily omitted. Instead we can use the value obtained directly from the platform resource to pass through Regmap into the call-backs to be used for the SMCC call and use a local dedicated __iomem variable for IO-remapping. Cc: Thor Thayer Signed-off-by: Lee Jones --- drivers/mfd/altera-sysmgr.c | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/drivers/mfd/altera-sysmgr.c b/drivers/mfd/altera-sysmgr.c index d2a13a547a3ca..83f0765f819b0 100644 --- a/drivers/mfd/altera-sysmgr.c +++ b/drivers/mfd/altera-sysmgr.c @@ -22,11 +22,9 @@ /** * struct altr_sysmgr - Altera SOCFPGA System Manager * @regmap: the regmap used for System Manager accesses. - * @base : the base address for the System Manager */ struct altr_sysmgr { struct regmap *regmap; - resource_size_t *base; }; static struct platform_driver altr_sysmgr_driver; @@ -127,6 +125,7 @@ static int sysmgr_probe(struct platform_device *pdev) struct regmap_config sysmgr_config = altr_sysmgr_regmap_cfg; struct device *dev = &pdev->dev; struct device_node *np = dev->of_node; + void __iomem *base; sysmgr = devm_kzalloc(dev, sizeof(*sysmgr), GFP_KERNEL); if (!sysmgr) @@ -139,22 +138,19 @@ static int sysmgr_probe(struct platform_device *pdev) sysmgr_config.max_register = resource_size(res) - sysmgr_config.reg_stride; if (of_device_is_compatible(np, "altr,sys-mgr-s10")) { - /* Need physical address for SMCC call */ - sysmgr->base = (resource_size_t *)res->start; sysmgr_config.reg_read = s10_protected_reg_read; sysmgr_config.reg_write = s10_protected_reg_write; - regmap = devm_regmap_init(dev, NULL, sysmgr->base, + /* Need physical address for SMCC call */ + regmap = devm_regmap_init(dev, NULL, (void *)res->start, &sysmgr_config); } else { - sysmgr->base = devm_ioremap(dev, res->start, - resource_size(res)); - if (!sysmgr->base) + base = devm_ioremap(dev, res->start, resource_size(res)); + if (!base) return -ENOMEM; sysmgr_config.max_register = res->end - res->start - 3; - regmap = devm_regmap_init_mmio(dev, sysmgr->base, - &sysmgr_config); + regmap = devm_regmap_init_mmio(dev, base, &sysmgr_config); } if (IS_ERR(regmap)) { -- GitLab From 3d4a87576f3762c8c986950af157bc9025808b5c Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Tue, 23 Jun 2020 10:08:41 +0100 Subject: [PATCH 0189/2249] mfd: sprd-sc27xx-spi: Fix symbol 'sprd_pmic_detect_charger_type' was not declared warning Sparse reports: drivers/mfd/sprd-sc27xx-spi.c:59:23: warning: symbol 'sprd_pmic_detect_charger_type' was not declared. Should it be static? ... due to a missing header file. Cc: Orson Zhai Cc: Chunyan Zhang Signed-off-by: Lee Jones Reviewed-by: Baolin Wang Signed-off-by: Lee Jones --- drivers/mfd/sprd-sc27xx-spi.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/mfd/sprd-sc27xx-spi.c b/drivers/mfd/sprd-sc27xx-spi.c index d030a5da55444..d3486c2a1b339 100644 --- a/drivers/mfd/sprd-sc27xx-spi.c +++ b/drivers/mfd/sprd-sc27xx-spi.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include -- GitLab From 54daa5d47c47662067115a78dd317fba3de9e828 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Tue, 23 Jun 2020 10:26:11 +0100 Subject: [PATCH 0190/2249] mfd: ab3100-core: Fix incompatible types in comparison expression warning Smatch reports: drivers/mfd/ab3100-core.c:501:20: error: incompatible types in comparison expression (different type sizes): drivers/mfd/ab3100-core.c:501:20: unsigned int * drivers/mfd/ab3100-core.c:501:20: unsigned long * drivers/mfd/ab8500-debugfs.c:1804:20: error: incompatible types in comparison expression (different type sizes): drivers/mfd/ab8500-debugfs.c:1804:20: unsigned int * drivers/mfd/ab8500-debugfs.c:1804:20: unsigned long * Since the second min() argument can be less than 0 a signed variable is required for assignment. However, the non-sized type size_t is passed in from the userspace handlers. In order to firstly compare, then assign the smallest value, we firstly need to cast them both to the same as the receiving size_t typed variable. Cc: Linus Walleij Signed-off-by: Lee Jones --- drivers/mfd/ab3100-core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mfd/ab3100-core.c b/drivers/mfd/ab3100-core.c index 57723f116bb58..ee71ae04b5e63 100644 --- a/drivers/mfd/ab3100-core.c +++ b/drivers/mfd/ab3100-core.c @@ -498,7 +498,7 @@ static ssize_t ab3100_get_set_reg(struct file *file, int i = 0; /* Get userspace string and assure termination */ - buf_size = min(count, (sizeof(buf)-1)); + buf_size = min((ssize_t)count, (ssize_t)(sizeof(buf)-1)); if (copy_from_user(buf, user_buf, buf_size)) return -EFAULT; buf[buf_size] = 0; -- GitLab From ddb6b26c4102aab886277b2ca3c027b4976d819b Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Tue, 23 Jun 2020 11:05:23 +0100 Subject: [PATCH 0191/2249] mfd: ab8500-debugfs: Fix incompatible types in comparison expression issue Smatch reports: drivers/mfd/ab8500-debugfs.c:1804:20: error: incompatible types in comparison expression (different type sizes): drivers/mfd/ab8500-debugfs.c:1804:20: unsigned int * drivers/mfd/ab8500-debugfs.c:1804:20: unsigned long * This is due to mixed types being compared in a min() comparison. Fix this by treating values as signed and casting them to the same type as the receiving variable. Cc: Linus Walleij Signed-off-by: Lee Jones --- drivers/mfd/ab8500-debugfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mfd/ab8500-debugfs.c b/drivers/mfd/ab8500-debugfs.c index 1a9a3414d4fa8..6d1bf7c3ca3b1 100644 --- a/drivers/mfd/ab8500-debugfs.c +++ b/drivers/mfd/ab8500-debugfs.c @@ -1801,7 +1801,7 @@ static ssize_t ab8500_hwreg_write(struct file *file, int buf_size, ret; /* Get userspace string and assure termination */ - buf_size = min(count, (sizeof(buf)-1)); + buf_size = min((int)count, (int)(sizeof(buf)-1)); if (copy_from_user(buf, user_buf, buf_size)) return -EFAULT; buf[buf_size] = 0; -- GitLab From 0dfae4a3205cb73e8ab2aafd4cbd0ff1fb082b5f Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Tue, 23 Jun 2020 13:36:30 +0100 Subject: [PATCH 0192/2249] mfd: tc3589x: Remove invalid use of kerneldoc syntax Kerneldoc is for documenting function arguments and return values. Prevents warnings like: drivers/mfd/tc3589x.c:32: warning: Enum value 'TC3589X_TC35890' not described in enum 'tc3589x_version' drivers/mfd/tc3589x.c:32: warning: Enum value 'TC3589X_TC35892' not described in enum 'tc3589x_version' drivers/mfd/tc3589x.c:32: warning: Enum value 'TC3589X_TC35893' not described in enum 'tc3589x_version' drivers/mfd/tc3589x.c:32: warning: Enum value 'TC3589X_TC35894' not described in enum 'tc3589x_version' drivers/mfd/tc3589x.c:32: warning: Enum value 'TC3589X_TC35895' not described in enum 'tc3589x_version' drivers/mfd/tc3589x.c:32: warning: Enum value 'TC3589X_TC35896' not described in enum 'tc3589x_version' drivers/mfd/tc3589x.c:32: warning: Enum value 'TC3589X_UNKNOWN' not described in enum 'tc3589x_version' Signed-off-by: Lee Jones --- drivers/mfd/tc3589x.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mfd/tc3589x.c b/drivers/mfd/tc3589x.c index 67c9995bb1aa6..7882a37ffc352 100644 --- a/drivers/mfd/tc3589x.c +++ b/drivers/mfd/tc3589x.c @@ -18,7 +18,7 @@ #include #include -/** +/* * enum tc3589x_version - indicates the TC3589x version */ enum tc3589x_version { -- GitLab From f139ef70789a6e8ae1692e00cf0a3ef7d68bf6b1 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Tue, 23 Jun 2020 14:06:40 +0100 Subject: [PATCH 0193/2249] mfd: wm8400-core: Supply description for wm8400_reset_codec_reg_cache's arg Kerneldoc syntax is used, but not complete. Descriptions required. Prevents warnings like: drivers/mfd/wm8400-core.c:113: warning: Function parameter or member 'wm8400' not described in 'wm8400_reset_codec_reg_cache' Cc: Mark Brown Cc: patches@opensource.cirrus.com Signed-off-by: Lee Jones Acked-by: Charles Keepax Signed-off-by: Lee Jones --- drivers/mfd/wm8400-core.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/mfd/wm8400-core.c b/drivers/mfd/wm8400-core.c index 3055d6f47afcc..0fe32a05421be 100644 --- a/drivers/mfd/wm8400-core.c +++ b/drivers/mfd/wm8400-core.c @@ -108,6 +108,8 @@ static const struct regmap_config wm8400_regmap_config = { /** * wm8400_reset_codec_reg_cache - Reset cached codec registers to * their default values. + * + * @wm8400: pointer to local driver data structure */ void wm8400_reset_codec_reg_cache(struct wm8400 *wm8400) { -- GitLab From 38ea9f47317d8e8a74b15b719d5c794a79346be8 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Tue, 23 Jun 2020 15:33:33 +0100 Subject: [PATCH 0194/2249] mfd: wm831x-core: Supply description wm831x_reg_{un}lock args Kerneldoc syntax is used, but not complete. Descriptions required. Prevents warnings like: drivers/mfd/wm831x-core.c:119: warning: Function parameter or member 'wm831x' not described in 'wm831x_reg_lock' drivers/mfd/wm831x-core.c:145: warning: Function parameter or member 'wm831x' not described in 'wm831x_reg_unlock' Cc: Mark Brown Cc: patches@opensource.cirrus.com Signed-off-by: Lee Jones Acked-by: Charles Keepax Signed-off-by: Lee Jones --- drivers/mfd/wm831x-core.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/mfd/wm831x-core.c b/drivers/mfd/wm831x-core.c index 02f879b23d9f6..b0344e5353e4f 100644 --- a/drivers/mfd/wm831x-core.c +++ b/drivers/mfd/wm831x-core.c @@ -114,6 +114,8 @@ static int wm831x_reg_locked(struct wm831x *wm831x, unsigned short reg) * The WM831x has a user key preventing writes to particularly * critical registers. This function locks those registers, * allowing writes to them. + * + * @wm831x: pointer to local driver data structure */ void wm831x_reg_lock(struct wm831x *wm831x) { @@ -140,6 +142,8 @@ EXPORT_SYMBOL_GPL(wm831x_reg_lock); * The WM831x has a user key preventing writes to particularly * critical registers. This function locks those registers, * preventing spurious writes. + * + * @wm831x: pointer to local driver data structure */ int wm831x_reg_unlock(struct wm831x *wm831x) { -- GitLab From afb718a870ef20efcf18d6fbea45fa6576a54d27 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Tue, 23 Jun 2020 15:44:48 +0100 Subject: [PATCH 0195/2249] mfd: wm8350-core: Supply description wm8350_reg_{un}lock args Kerneldoc syntax is used, but not complete. Descriptions required. Prevents warnings like: drivers/mfd/wm8350-core.c:136: warning: Function parameter or member 'wm8350' not described in 'wm8350_reg_lock' drivers/mfd/wm8350-core.c:165: warning: Function parameter or member 'wm8350' not described in 'wm8350_reg_unlock' Cc: patches@opensource.cirrus.com Signed-off-by: Lee Jones --- drivers/mfd/wm8350-core.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/mfd/wm8350-core.c b/drivers/mfd/wm8350-core.c index 42b16503e6cd1..fbc77b218215c 100644 --- a/drivers/mfd/wm8350-core.c +++ b/drivers/mfd/wm8350-core.c @@ -131,6 +131,8 @@ EXPORT_SYMBOL_GPL(wm8350_block_write); * The WM8350 has a hardware lock which can be used to prevent writes to * some registers (generally those which can cause particularly serious * problems if misused). This function enables that lock. + * + * @wm8350: pointer to local driver data structure */ int wm8350_reg_lock(struct wm8350 *wm8350) { @@ -160,6 +162,8 @@ EXPORT_SYMBOL_GPL(wm8350_reg_lock); * problems if misused). This function disables that lock so updates * can be performed. For maximum safety this should be done only when * required. + * + * @wm8350: pointer to local driver data structure */ int wm8350_reg_unlock(struct wm8350 *wm8350) { -- GitLab From 5a0ffef8b74fda62114d7bfba92f318fcc4b9283 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Tue, 23 Jun 2020 15:51:28 +0100 Subject: [PATCH 0196/2249] mfd: mfd-core: Complete kerneldoc header for devm_mfd_add_devices() Each function parameter should be documented in kerneldoc format. Squashes the following W=1 warnings: drivers/mfd/mfd-core.c:326: warning: Function parameter or member 'dev' not described in 'devm_mfd_add_devices' drivers/mfd/mfd-core.c:326: warning: Function parameter or member 'id' not described in 'devm_mfd_add_devices' drivers/mfd/mfd-core.c:326: warning: Function parameter or member 'cells' not described in 'devm_mfd_add_devices' drivers/mfd/mfd-core.c:326: warning: Function parameter or member 'n_devs' not described in 'devm_mfd_add_devices' drivers/mfd/mfd-core.c:326: warning: Function parameter or member 'mem_base' not described in 'devm_mfd_add_devices' drivers/mfd/mfd-core.c:326: warning: Function parameter or member 'irq_base' not described in 'devm_mfd_add_devices' drivers/mfd/mfd-core.c:326: warning: Function parameter or member 'domain' not described in 'devm_mfd_add_devices' Signed-off-by: Lee Jones --- drivers/mfd/mfd-core.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/mfd/mfd-core.c b/drivers/mfd/mfd-core.c index f5a73af60dd40..720e5c8b1588c 100644 --- a/drivers/mfd/mfd-core.c +++ b/drivers/mfd/mfd-core.c @@ -318,6 +318,16 @@ static void devm_mfd_dev_release(struct device *dev, void *res) * Returns 0 on success or an appropriate negative error number on failure. * All child-devices of the MFD will automatically be removed when it gets * unbinded. + * + * @dev: Pointer to parent device. + * @id: Can be PLATFORM_DEVID_AUTO to let the Platform API take care + * of device numbering, or will be added to a device's cell_id. + * @cells: Array of (struct mfd_cell)s describing child devices. + * @n_devs: Number of child devices to register. + * @mem_base: Parent register range resource for child devices. + * @irq_base: Base of the range of virtual interrupt numbers allocated for + * this MFD device. Unused if @domain is specified. + * @domain: Interrupt domain to create mappings for hardware interrupts. */ int devm_mfd_add_devices(struct device *dev, int id, const struct mfd_cell *cells, int n_devs, -- GitLab From 3ecbcd20e06f2c1254a85fc208ccc6aa20594314 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Wed, 24 Jun 2020 09:34:00 +0100 Subject: [PATCH 0197/2249] mfd: db8500-prcmu: Add description for 'reset_reason' in kerneldoc Each function parameter should be documented in kerneldoc format. Squashes the following W=1 warnings: drivers/mfd/db8500-prcmu.c:2281: warning: Function parameter or member 'reset_code' not described in 'db8500_prcmu_system_reset' drivers/mfd/db8500-prcmu.c:3012: warning: Function parameter or member 'pdev' not described in 'db8500_prcmu_probe' Cc: Linus Walleij Signed-off-by: Lee Jones --- drivers/mfd/db8500-prcmu.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/mfd/db8500-prcmu.c b/drivers/mfd/db8500-prcmu.c index 0452b43b04232..9b58b02967638 100644 --- a/drivers/mfd/db8500-prcmu.c +++ b/drivers/mfd/db8500-prcmu.c @@ -2276,6 +2276,8 @@ bool db8500_prcmu_is_ac_wake_requested(void) * * Saves the reset reason code and then sets the APE_SOFTRST register which * fires interrupt to fw + * + * @reset_code: The reason for system reset */ void db8500_prcmu_system_reset(u16 reset_code) { -- GitLab From 07d88c97aef826f1ba8a5026ea30700f85433057 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Wed, 24 Jun 2020 09:35:24 +0100 Subject: [PATCH 0198/2249] mfd: db8500-prcmu: Remove incorrect function header from .probe() function Not only is the current header incorrect, the isn't actually a need to document the ubiquitous platform probe call. Cc: Linus Walleij Signed-off-by: Lee Jones --- drivers/mfd/db8500-prcmu.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/mfd/db8500-prcmu.c b/drivers/mfd/db8500-prcmu.c index 9b58b02967638..a9d9c1cdf546b 100644 --- a/drivers/mfd/db8500-prcmu.c +++ b/drivers/mfd/db8500-prcmu.c @@ -3006,10 +3006,6 @@ static int db8500_prcmu_register_ab8500(struct device *parent) return mfd_add_devices(parent, 0, ab850x_cell, 1, NULL, 0, NULL); } -/** - * prcmu_fw_init - arch init call for the Linux PRCMU fw init logic - * - */ static int db8500_prcmu_probe(struct platform_device *pdev) { struct device_node *np = pdev->dev.of_node; -- GitLab From 5d36df75839d2dc6216f13ed86a60f801c38937f Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Wed, 24 Jun 2020 09:42:33 +0100 Subject: [PATCH 0199/2249] mfd: omap-usb-host: Remove invalid use of kerneldoc syntax Kerneldoc is for documenting function arguments and return values. Prevents warnings like: drivers/mfd/omap-usb-host.c:128: warning: cannot understand function prototype: 'const char * const port_modes[] = ' Cc: Tony Lindgren Cc: Keshava Munegowda Cc: Roger Quadros Cc: linux-omap@vger.kernel.org Signed-off-by: Lee Jones --- drivers/mfd/omap-usb-host.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mfd/omap-usb-host.c b/drivers/mfd/omap-usb-host.c index 1f4f01b02d98c..f56cdf3149dc0 100644 --- a/drivers/mfd/omap-usb-host.c +++ b/drivers/mfd/omap-usb-host.c @@ -120,7 +120,7 @@ static inline u32 usbhs_read(void __iomem *base, u32 reg) /*-------------------------------------------------------------------------*/ -/** +/* * Map 'enum usbhs_omap_port_mode' found in * to the device tree binding portN-mode found in * 'Documentation/devicetree/bindings/mfd/omap-usb-host.txt' -- GitLab From 3fc65627c81c700c2b12eb3b8ca8a47f4cb4dd20 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Wed, 24 Jun 2020 09:45:56 +0100 Subject: [PATCH 0200/2249] mfd: omap-usb-host: Provide description for 'pdev' argument to .probe() Kerneldoc syntax is used, but not complete. Arg descriptions required. Prevents warnings like: drivers/mfd/omap-usb-host.c:531: warning: Function parameter or member 'pdev' not described in 'usbhs_omap_probe' Cc: Tony Lindgren Cc: Keshava Munegowda Cc: Roger Quadros Cc: linux-omap@vger.kernel.org Signed-off-by: Lee Jones --- drivers/mfd/omap-usb-host.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/mfd/omap-usb-host.c b/drivers/mfd/omap-usb-host.c index f56cdf3149dc0..aca5a160c1b24 100644 --- a/drivers/mfd/omap-usb-host.c +++ b/drivers/mfd/omap-usb-host.c @@ -526,6 +526,8 @@ static const struct of_device_id usbhs_child_match_table[] = { * usbhs_omap_probe - initialize TI-based HCDs * * Allocates basic resources for this USB host controller. + * + * @pdev: Pointer to this device's platform device structure */ static int usbhs_omap_probe(struct platform_device *pdev) { -- GitLab From 55bbf5d42ee6c609de56702ae7f766c4e88efbed Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Wed, 24 Jun 2020 09:48:17 +0100 Subject: [PATCH 0201/2249] mfd: omap-usb-tll: Provide description for 'pdev' argument to .probe() Kerneldoc syntax is used, but not complete. Arg descriptions required. Prevents warnings like: drivers/mfd/omap-usb-tll.c:204: warning: Function parameter or member 'pdev' not described in 'usbtll_omap_probe Cc: Tony Lindgren Cc: Keshava Munegowda Cc: Roger Quadros Cc: linux-omap@vger.kernel.org Signed-off-by: Lee Jones --- drivers/mfd/omap-usb-tll.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/mfd/omap-usb-tll.c b/drivers/mfd/omap-usb-tll.c index 4b7f73c317e87..04a444007cf4e 100644 --- a/drivers/mfd/omap-usb-tll.c +++ b/drivers/mfd/omap-usb-tll.c @@ -199,6 +199,8 @@ static unsigned ohci_omap3_fslsmode(enum usbhs_omap_port_mode mode) * usbtll_omap_probe - initialize TI-based HCDs * * Allocates basic resources for this USB host controller. + * + * @pdev: Pointer to this device's platform device structure */ static int usbtll_omap_probe(struct platform_device *pdev) { -- GitLab From 1574360a98cef9842d86e208944bb45243150440 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Wed, 24 Jun 2020 12:29:02 +0100 Subject: [PATCH 0202/2249] mfd: atmel-smc: Add missing colon(s) for 'conf' arguments Kerneldoc valication gets confused if syntax isn't "@.*: ". Adding the missing colons squashes the following W=1 warnings: drivers/mfd/atmel-smc.c:247: warning: Function parameter or member 'conf' not described in 'atmel_smc_cs_conf_apply' drivers/mfd/atmel-smc.c:268: warning: Function parameter or member 'conf' not described in 'atmel_hsmc_cs_conf_apply' Cc: Nicolas Ferre Cc: Alexandre Belloni Cc: Ludovic Desroches Cc: Boris Brezillon Signed-off-by: Lee Jones --- drivers/mfd/atmel-smc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/mfd/atmel-smc.c b/drivers/mfd/atmel-smc.c index 1fa2ec950e7df..d96f1d689e7fb 100644 --- a/drivers/mfd/atmel-smc.c +++ b/drivers/mfd/atmel-smc.c @@ -237,7 +237,7 @@ EXPORT_SYMBOL_GPL(atmel_smc_cs_conf_set_cycle); * atmel_smc_cs_conf_apply - apply an SMC CS conf * @regmap: the SMC regmap * @cs: the CS id - * @conf the SMC CS conf to apply + * @conf: the SMC CS conf to apply * * Applies an SMC CS configuration. * Only valid on at91sam9/avr32 SoCs. @@ -257,7 +257,7 @@ EXPORT_SYMBOL_GPL(atmel_smc_cs_conf_apply); * @regmap: the HSMC regmap * @cs: the CS id * @layout: the layout of registers - * @conf the SMC CS conf to apply + * @conf: the SMC CS conf to apply * * Applies an SMC CS configuration. * Only valid on post-sama5 SoCs. -- GitLab From 0824c889e1a4b1ec0edf890689c7852363c4b055 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Wed, 24 Jun 2020 12:56:11 +0100 Subject: [PATCH 0203/2249] mfd: altera-sysmgr: Supply descriptions for 'np' and 'property' function args Kerneldoc syntax is used, but not complete. Arg descriptions are required. Fixes the following W=1 build warnings: drivers/mfd/altera-sysmgr.c:95: warning: Function parameter or member 'np' not described in 'altr_sysmgr_regmap_lookup_by_phandle' drivers/mfd/altera-sysmgr.c:95: warning: Function parameter or member 'property' not described in 'altr_sysmgr_regmap_lookup_by_phandle' Cc: Thor Thayer Signed-off-by: Lee Jones --- drivers/mfd/altera-sysmgr.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/mfd/altera-sysmgr.c b/drivers/mfd/altera-sysmgr.c index 83f0765f819b0..41076d121dd54 100644 --- a/drivers/mfd/altera-sysmgr.c +++ b/drivers/mfd/altera-sysmgr.c @@ -89,6 +89,9 @@ static struct regmap_config altr_sysmgr_regmap_cfg = { * altr_sysmgr_regmap_lookup_by_phandle * Find the sysmgr previous configured in probe() and return regmap property. * Return: regmap if found or error if not found. + * + * @np: Pointer to device's Device Tree node + * @property: Device Tree property name which references the sysmgr */ struct regmap *altr_sysmgr_regmap_lookup_by_phandle(struct device_node *np, const char *property) -- GitLab From 5ae3d1bcea485e3f0056c508d2e12d1a95c453ee Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Wed, 24 Jun 2020 13:07:45 +0100 Subject: [PATCH 0204/2249] mfd: cros_ec_dev: Fix cros_feature_to_{name,cells} struct descriptions Kerneldoc expects kernel structures to be prefixed with 'struct'. Fixes the following W=1 level warnings: drivers/mfd/cros_ec_dev.c:32: warning: cannot understand function prototype: 'struct cros_feature_to_name ' drivers/mfd/cros_ec_dev.c:44: warning: cannot understand function prototype: 'struct cros_feature_to_cells ' Cc: Benson Leung Cc: Guenter Roeck Cc: Bill Richardson Signed-off-by: Lee Jones Acked-by: Enric Balletbo i Serra Signed-off-by: Lee Jones --- drivers/mfd/cros_ec_dev.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/mfd/cros_ec_dev.c b/drivers/mfd/cros_ec_dev.c index 32c2b912b58b2..d07b43d7c761a 100644 --- a/drivers/mfd/cros_ec_dev.c +++ b/drivers/mfd/cros_ec_dev.c @@ -24,7 +24,7 @@ static struct class cros_class = { }; /** - * cros_feature_to_name - CrOS feature id to name/short description. + * struct cros_feature_to_name - CrOS feature id to name/short description. * @id: The feature identifier. * @name: Device name associated with the feature id. * @desc: Short name that will be displayed. @@ -36,7 +36,7 @@ struct cros_feature_to_name { }; /** - * cros_feature_to_cells - CrOS feature id to mfd cells association. + * struct cros_feature_to_cells - CrOS feature id to mfd cells association. * @id: The feature identifier. * @mfd_cells: Pointer to the array of mfd cells that needs to be added. * @num_cells: Number of mfd cells into the array. -- GitLab From 9c3739ee293bc956739c9a90d357595f41f46d39 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Wed, 24 Jun 2020 13:10:54 +0100 Subject: [PATCH 0205/2249] mfd: tps65218: Repair incorrect function argument name 's/tps65218/tps/' The kerneldocs for both tps65218_reg_write() and tps65218_update_bits() describe their first arguments as 'tps65218', when in reality these are simply called 'tps'. Fixes the following W=1 warnings: drivers/mfd/tps65218.c:58: warning: Function parameter or member 'tps' not described in 'tps65218_reg_write' drivers/mfd/tps65218.c:58: warning: Excess function parameter 'tps65218' description in 'tps65218_reg_write' drivers/mfd/tps65218.c:90: warning: Function parameter or member 'tps' not described in 'tps65218_update_bits' drivers/mfd/tps65218.c:90: warning: Excess function parameter 'tps65218' description in 'tps65218_update_bits' Cc: Tony Lindgren Cc: J Keerthy Cc: linux-omap@vger.kernel.org Signed-off-by: Lee Jones --- drivers/mfd/tps65218.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/mfd/tps65218.c b/drivers/mfd/tps65218.c index a62ea4cb8be7e..d41dd864b472b 100644 --- a/drivers/mfd/tps65218.c +++ b/drivers/mfd/tps65218.c @@ -48,7 +48,7 @@ static const struct mfd_cell tps65218_cells[] = { /** * tps65218_reg_write: Write a single tps65218 register. * - * @tps65218: Device to write to. + * @tps: Device to write to. * @reg: Register to write to. * @val: Value to write. * @level: Password protected level @@ -79,7 +79,7 @@ EXPORT_SYMBOL_GPL(tps65218_reg_write); /** * tps65218_update_bits: Modify bits w.r.t mask, val and level. * - * @tps65218: Device to write to. + * @tps: Device to write to. * @reg: Register to read-write to. * @mask: Mask. * @val: Value to write. -- GitLab From 4976bfb8d853a246f83da7ccdfb49fa34093ac0d Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Wed, 24 Jun 2020 13:14:51 +0100 Subject: [PATCH 0206/2249] mfd: tps65217: Repair incorrect function argument name 's/tps65217/tps/' The kerneldocs for both tps65217_reg_write() and tps65217_update_bits() describe their first arguments as 'tps65217', when in reality these are simply called 'tps'. Fixes the following W=1 warnings: drivers/mfd/tps65217.c:215: warning: Function parameter or member 'tps' not described in 'tps65217_reg_write' drivers/mfd/tps65217.c:215: warning: Excess function parameter 'tps65217' description in 'tps65217_reg_write' drivers/mfd/tps65217.c:261: warning: Function parameter or member 'tps' not described in 'tps65217_update_bits' drivers/mfd/tps65217.c:261: warning: Excess function parameter 'tps65217' description in 'tps65217_update_bits' Cc: Tony Lindgren Cc: AnilKumar Ch Cc: linux-omap@vger.kernel.org Signed-off-by: Lee Jones --- drivers/mfd/tps65217.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/mfd/tps65217.c b/drivers/mfd/tps65217.c index 7566ce4457a01..923602599549b 100644 --- a/drivers/mfd/tps65217.c +++ b/drivers/mfd/tps65217.c @@ -205,7 +205,7 @@ EXPORT_SYMBOL_GPL(tps65217_reg_read); /** * tps65217_reg_write: Write a single tps65217 register. * - * @tps65217: Device to write to. + * @tps: Device to write to. * @reg: Register to write to. * @val: Value to write. * @level: Password protected level @@ -250,7 +250,7 @@ EXPORT_SYMBOL_GPL(tps65217_reg_write); /** * tps65217_update_bits: Modify bits w.r.t mask, val and level. * - * @tps65217: Device to write to. + * @tps: Device to write to. * @reg: Register to read-write to. * @mask: Mask. * @val: Value to write. -- GitLab From 20d60f850d2d8b6f9536c1a499fc6d6a5c724a55 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Wed, 24 Jun 2020 13:17:01 +0100 Subject: [PATCH 0207/2249] mfd: ab3100-otp: Add missing colon(s) for all documented kerneldoc arguments Kerneldoc validation gets confused if syntax isn't "@.*: ". Adding the missing colons squashes the following W=1 warnings: drivers/mfd/ab3100-otp.c:60: warning: Function parameter or member 'dev' not described in 'ab3100_otp' drivers/mfd/ab3100-otp.c:60: warning: Function parameter or member 'locked' not described in 'ab3100_otp' drivers/mfd/ab3100-otp.c:60: warning: Function parameter or member 'freq' not described in 'ab3100_otp' drivers/mfd/ab3100-otp.c:60: warning: Function parameter or member 'paf' not described in 'ab3100_otp' drivers/mfd/ab3100-otp.c:60: warning: Function parameter or member 'imeich' not described in 'ab3100_otp' drivers/mfd/ab3100-otp.c:60: warning: Function parameter or member 'cid' not described in 'ab3100_otp' drivers/mfd/ab3100-otp.c:60: warning: Function parameter or member 'tac' not described in 'ab3100_otp' drivers/mfd/ab3100-otp.c:60: warning: Function parameter or member 'fac' not described in 'ab3100_otp' drivers/mfd/ab3100-otp.c:60: warning: Function parameter or member 'svn' not described in 'ab3100_otp' drivers/mfd/ab3100-otp.c:60: warning: Function parameter or member 'debugfs' not described in 'ab3100_otp' Cc: Linus Walleij Signed-off-by: Lee Jones --- drivers/mfd/ab3100-otp.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/mfd/ab3100-otp.c b/drivers/mfd/ab3100-otp.c index c4751fb9bc224..c393102e3a394 100644 --- a/drivers/mfd/ab3100-otp.c +++ b/drivers/mfd/ab3100-otp.c @@ -29,22 +29,22 @@ /** * struct ab3100_otp - * @dev containing device - * @locked whether the OTP is locked, after locking, no more bits + * @dev: containing device + * @locked: whether the OTP is locked, after locking, no more bits * can be changed but before locking it is still possible * to change bits from 1->0. - * @freq clocking frequency for the OTP, this frequency is either + * @freq: clocking frequency for the OTP, this frequency is either * 32768Hz or 1MHz/30 - * @paf product activation flag, indicates whether this is a real + * @paf: product activation flag, indicates whether this is a real * product (paf true) or a lab board etc (paf false) - * @imeich if this is set it is possible to override the + * @imeich: if this is set it is possible to override the * IMEI number found in the tac, fac and svn fields with * (secured) software - * @cid customer ID - * @tac type allocation code of the IMEI - * @fac final assembly code of the IMEI - * @svn software version number of the IMEI - * @debugfs a debugfs file used when dumping to file + * @cid: customer ID + * @tac: type allocation code of the IMEI + * @fac: final assembly code of the IMEI + * @svn: software version number of the IMEI + * @debugfs: a debugfs file used when dumping to file */ struct ab3100_otp { struct device *dev; -- GitLab From 2fbd583443905d6f8c6d87aebdef2717ae039f0b Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Wed, 24 Jun 2020 13:31:31 +0100 Subject: [PATCH 0208/2249] mfd: tps65010: Remove delcared and set, but never used variable 'status' MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 'status' hasn't been checked since 2008. It's probably safe to remove it. Fixes W=1 warning: drivers/mfd/tps65010.c:407:7: warning: variable ‘status’ set but not used [-Wunused-but-set-variable] 407 | int status; | ^~~~~~ Signed-off-by: Lee Jones --- drivers/mfd/tps65010.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/mfd/tps65010.c b/drivers/mfd/tps65010.c index 65fcc58c02da8..7e7dbee58ca90 100644 --- a/drivers/mfd/tps65010.c +++ b/drivers/mfd/tps65010.c @@ -404,7 +404,6 @@ static void tps65010_work(struct work_struct *work) tps65010_interrupt(tps); if (test_and_clear_bit(FLAG_VBUS_CHANGED, &tps->flags)) { - int status; u8 chgconfig, tmp; chgconfig = i2c_smbus_read_byte_data(tps->client, @@ -415,8 +414,8 @@ static void tps65010_work(struct work_struct *work) else if (tps->vbus >= 100) chgconfig |= TPS_VBUS_CHARGING; - status = i2c_smbus_write_byte_data(tps->client, - TPS_CHGCONFIG, chgconfig); + i2c_smbus_write_byte_data(tps->client, + TPS_CHGCONFIG, chgconfig); /* vbus update fails unless VBUS is connected! */ tmp = i2c_smbus_read_byte_data(tps->client, TPS_CHGCONFIG); -- GitLab From 3c719388f6ff505239f8285a423571236abbd3c2 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Wed, 24 Jun 2020 13:36:23 +0100 Subject: [PATCH 0209/2249] mfd: si476x-cmd: Repair wrongly described function argument 's/response/resp' si476x_core_send_command()'s 5th argument has never been called response. This change must have occurred prior to the driver being Mainlined. We're also taking the opportunity to bring the first description back into line, making my OCD happy! This fixes the following W=1 warning(s): drivers/mfd/si476x-cmd.c:264: warning: Function parameter or member 'resp' not described in 'si476x_core_send_command drivers/mfd/si476x-cmd.c:264: warning: Excess function parameter 'response' description in 'si476x_core_send_command' Cc: Andrey Smirnov Signed-off-by: Lee Jones --- drivers/mfd/si476x-cmd.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/mfd/si476x-cmd.c b/drivers/mfd/si476x-cmd.c index 4a09ce9609c90..316d44c2edcd4 100644 --- a/drivers/mfd/si476x-cmd.c +++ b/drivers/mfd/si476x-cmd.c @@ -241,13 +241,13 @@ static int si476x_core_parse_and_nag_about_error(struct si476x_core *core) /** * si476x_core_send_command() - sends a command to si476x and waits its * response - * @core: si476x_device structure for the device we are + * @core: si476x_device structure for the device we are * communicating with * @command: command id * @args: command arguments we are sending * @argn: actual size of @args - * @response: buffer to place the expected response from the device - * @respn: actual size of @response + * @resp: buffer to place the expected response from the device + * @respn: actual size of @resp * @usecs: amount of time to wait before reading the response (in * usecs) * -- GitLab From 9745ef7dcf86bbad277c4a6575393a4eaabca1b4 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Wed, 24 Jun 2020 13:43:25 +0100 Subject: [PATCH 0210/2249] mfd: si476x-cmd: Add missing colon(s) for all documented kerneldoc arguments Kerneldoc validation gets confused if syntax isn't "@.*: ". Adding the missing colons squashes the following W=1 warnings: drivers/mfd/si476x-cmd.c:525: warning: Function parameter or member 'dout' not described in 'si476x_core_cmd_dig_audio_pin_c drivers/mfd/si476x-cmd.c:525: warning: Function parameter or member 'xout' not described in 'si476x_core_cmd_dig_audio_pin_c drivers/mfd/si476x-cmd.c:574: warning: Function parameter or member 'core' not described in 'si476x_core_cmd_zif_pin_cfg' drivers/mfd/si476x-cmd.c:574: warning: Function parameter or member 'iqclk' not described in 'si476x_core_cmd_zif_pin_cfg' drivers/mfd/si476x-cmd.c:574: warning: Function parameter or member 'iqfs' not described in 'si476x_core_cmd_zif_pin_cfg' drivers/mfd/si476x-cmd.c:574: warning: Function parameter or member 'iout' not described in 'si476x_core_cmd_zif_pin_cfg' drivers/mfd/si476x-cmd.c:574: warning: Function parameter or member 'qout' not described in 'si476x_core_cmd_zif_pin_cfg' drivers/mfd/si476x-i2c.c:550: warning: Function parameter or member 'func' not described in 'si476x_core_fwver_to_revision' drivers/mfd/si476x-cmd.c:631: warning: Function parameter or member 'core' not described in 'si476x_core_cmd_ic_link_gpo_ctl drivers/mfd/si476x-cmd.c:631: warning: Function parameter or member 'icin' not described in 'si476x_core_cmd_ic_link_gpo_ctl drivers/mfd/si476x-cmd.c:631: warning: Function parameter or member 'icip' not described in 'si476x_core_cmd_ic_link_gpo_ctl drivers/mfd/si476x-cmd.c:631: warning: Function parameter or member 'icon' not described in 'si476x_core_cmd_ic_link_gpo_ctl drivers/mfd/si476x-cmd.c:631: warning: Function parameter or member 'icop' not described in 'si476x_core_cmd_ic_link_gpo_ctl drivers/mfd/si476x-cmd.c:662: warning: Function parameter or member 'core' not described in 'si476x_core_cmd_ana_audio_pin_c drivers/mfd/si476x-cmd.c:662: warning: Function parameter or member 'lrout' not described in 'si476x_core_cmd_ana_audio_pin_ drivers/mfd/si476x-cmd.c:697: warning: Function parameter or member 'core' not described in 'si476x_core_cmd_intb_pin_cfg_a1 drivers/mfd/si476x-cmd.c:697: warning: Function parameter or member 'intb' not described in 'si476x_core_cmd_intb_pin_cfg_a1 drivers/mfd/si476x-cmd.c:697: warning: Function parameter or member 'a1' not described in 'si476x_core_cmd_intb_pin_cfg_a10' drivers/mfd/si476x-cmd.c:746: warning: Function parameter or member 'core' not described in 'si476x_core_cmd_am_rsq_status' drivers/mfd/si476x-cmd.c:746: warning: Function parameter or member 'rsqargs' not described in 'si476x_core_cmd_am_rsq_statu drivers/mfd/si476x-cmd.c:746: warning: Function parameter or member 'report' not described in 'si476x_core_cmd_am_rsq_status drivers/mfd/si476x-cmd.c:878: warning: Function parameter or member 'core' not described in 'si476x_core_cmd_fm_seek_start' drivers/mfd/si476x-cmd.c:878: warning: Function parameter or member 'seekup' not described in 'si476x_core_cmd_fm_seek_start drivers/mfd/si476x-cmd.c:878: warning: Function parameter or member 'wrap' not described in 'si476x_core_cmd_fm_seek_start' drivers/mfd/si476x-cmd.c:907: warning: Function parameter or member 'core' not described in 'si476x_core_cmd_fm_rds_status' drivers/mfd/si476x-cmd.c:907: warning: Function parameter or member 'status_only' not described in 'si476x_core_cmd_fm_rds_s drivers/mfd/si476x-cmd.c:907: warning: Function parameter or member 'mtfifo' not described in 'si476x_core_cmd_fm_rds_status drivers/mfd/si476x-cmd.c:907: warning: Function parameter or member 'intack' not described in 'si476x_core_cmd_fm_rds_status drivers/mfd/si476x-cmd.c:907: warning: Function parameter or member 'report' not described in 'si476x_core_cmd_fm_rds_status drivers/mfd/si476x-cmd.c:1052: warning: Function parameter or member 'core' not described in 'si476x_core_cmd_am_seek_start' drivers/mfd/si476x-cmd.c:1052: warning: Function parameter or member 'seekup' not described in 'si476x_core_cmd_am_seek_star drivers/mfd/si476x-cmd.c:1052: warning: Function parameter or member 'wrap' not described in 'si476x_core_cmd_am_seek_start' Cc: Andrey Smirnov Signed-off-by: Lee Jones --- drivers/mfd/si476x-cmd.c | 66 ++++++++++++++++++++-------------------- 1 file changed, 33 insertions(+), 33 deletions(-) diff --git a/drivers/mfd/si476x-cmd.c b/drivers/mfd/si476x-cmd.c index 316d44c2edcd4..5b42dfab431a3 100644 --- a/drivers/mfd/si476x-cmd.c +++ b/drivers/mfd/si476x-cmd.c @@ -496,7 +496,7 @@ EXPORT_SYMBOL_GPL(si476x_core_cmd_get_property); * enable 1MOhm pulldown * SI476X_DFS_DAUDIO - set the pin to be a part of digital * audio interface - * @dout - DOUT pin function configuration: + * @dout: - DOUT pin function configuration: * SI476X_DOUT_NOOP - do not modify the behaviour * SI476X_DOUT_TRISTATE - put the pin in tristate condition, * enable 1MOhm pulldown @@ -504,7 +504,7 @@ EXPORT_SYMBOL_GPL(si476x_core_cmd_get_property); * port 1 * SI476X_DOUT_I2S_INPUT - set this pin to be digital in on I2S * port 1 - * @xout - XOUT pin function configuration: + * @xout: - XOUT pin function configuration: * SI476X_XOUT_NOOP - do not modify the behaviour * SI476X_XOUT_TRISTATE - put the pin in tristate condition, * enable 1MOhm pulldown @@ -540,25 +540,25 @@ EXPORT_SYMBOL_GPL(si476x_core_cmd_dig_audio_pin_cfg); /** * si476x_cmd_zif_pin_cfg - send 'ZIF_PIN_CFG_COMMAND' - * @core - device to send the command to - * @iqclk - IQCL pin function configuration: + * @core: - device to send the command to + * @iqclk: - IQCL pin function configuration: * SI476X_IQCLK_NOOP - do not modify the behaviour * SI476X_IQCLK_TRISTATE - put the pin in tristate condition, * enable 1MOhm pulldown * SI476X_IQCLK_IQ - set pin to be a part of I/Q interace * in master mode - * @iqfs - IQFS pin function configuration: + * @iqfs: - IQFS pin function configuration: * SI476X_IQFS_NOOP - do not modify the behaviour * SI476X_IQFS_TRISTATE - put the pin in tristate condition, * enable 1MOhm pulldown * SI476X_IQFS_IQ - set pin to be a part of I/Q interace * in master mode - * @iout - IOUT pin function configuration: + * @iout: - IOUT pin function configuration: * SI476X_IOUT_NOOP - do not modify the behaviour * SI476X_IOUT_TRISTATE - put the pin in tristate condition, * enable 1MOhm pulldown * SI476X_IOUT_OUTPUT - set pin to be I out - * @qout - QOUT pin function configuration: + * @qout: - QOUT pin function configuration: * SI476X_QOUT_NOOP - do not modify the behaviour * SI476X_QOUT_TRISTATE - put the pin in tristate condition, * enable 1MOhm pulldown @@ -590,29 +590,29 @@ EXPORT_SYMBOL_GPL(si476x_core_cmd_zif_pin_cfg); /** * si476x_cmd_ic_link_gpo_ctl_pin_cfg - send * 'IC_LINK_GPIO_CTL_PIN_CFG' comand to the device - * @core - device to send the command to - * @icin - ICIN pin function configuration: + * @core: - device to send the command to + * @icin: - ICIN pin function configuration: * SI476X_ICIN_NOOP - do not modify the behaviour * SI476X_ICIN_TRISTATE - put the pin in tristate condition, * enable 1MOhm pulldown * SI476X_ICIN_GPO1_HIGH - set pin to be an output, drive it high * SI476X_ICIN_GPO1_LOW - set pin to be an output, drive it low * SI476X_ICIN_IC_LINK - set the pin to be a part of Inter-Chip link - * @icip - ICIP pin function configuration: + * @icip: - ICIP pin function configuration: * SI476X_ICIP_NOOP - do not modify the behaviour * SI476X_ICIP_TRISTATE - put the pin in tristate condition, * enable 1MOhm pulldown * SI476X_ICIP_GPO1_HIGH - set pin to be an output, drive it high * SI476X_ICIP_GPO1_LOW - set pin to be an output, drive it low * SI476X_ICIP_IC_LINK - set the pin to be a part of Inter-Chip link - * @icon - ICON pin function configuration: + * @icon: - ICON pin function configuration: * SI476X_ICON_NOOP - do not modify the behaviour * SI476X_ICON_TRISTATE - put the pin in tristate condition, * enable 1MOhm pulldown * SI476X_ICON_I2S - set the pin to be a part of audio * interface in slave mode (DCLK) * SI476X_ICON_IC_LINK - set the pin to be a part of Inter-Chip link - * @icop - ICOP pin function configuration: + * @icop: - ICOP pin function configuration: * SI476X_ICOP_NOOP - do not modify the behaviour * SI476X_ICOP_TRISTATE - put the pin in tristate condition, * enable 1MOhm pulldown @@ -647,8 +647,8 @@ EXPORT_SYMBOL_GPL(si476x_core_cmd_ic_link_gpo_ctl_pin_cfg); /** * si476x_cmd_ana_audio_pin_cfg - send 'ANA_AUDIO_PIN_CFG' to the * device - * @core - device to send the command to - * @lrout - LROUT pin function configuration: + * @core: - device to send the command to + * @lrout: - LROUT pin function configuration: * SI476X_LROUT_NOOP - do not modify the behaviour * SI476X_LROUT_TRISTATE - put the pin in tristate condition, * enable 1MOhm pulldown @@ -675,15 +675,15 @@ EXPORT_SYMBOL_GPL(si476x_core_cmd_ana_audio_pin_cfg); /** * si476x_cmd_intb_pin_cfg - send 'INTB_PIN_CFG' command to the device - * @core - device to send the command to - * @intb - INTB pin function configuration: + * @core: - device to send the command to + * @intb: - INTB pin function configuration: * SI476X_INTB_NOOP - do not modify the behaviour * SI476X_INTB_TRISTATE - put the pin in tristate condition, * enable 1MOhm pulldown * SI476X_INTB_DAUDIO - set pin to be a part of digital * audio interface in slave mode * SI476X_INTB_IRQ - set pin to be an interrupt request line - * @a1 - A1 pin function configuration: + * @a1: - A1 pin function configuration: * SI476X_A1_NOOP - do not modify the behaviour * SI476X_A1_TRISTATE - put the pin in tristate condition, * enable 1MOhm pulldown @@ -728,14 +728,14 @@ static int si476x_core_cmd_intb_pin_cfg_a20(struct si476x_core *core, /** * si476x_cmd_am_rsq_status - send 'AM_RSQ_STATUS' command to the * device - * @core - device to send the command to - * @rsqack - if set command clears RSQINT, SNRINT, SNRLINT, RSSIHINT, + * @core: - device to send the command to + * @rsqack: - if set command clears RSQINT, SNRINT, SNRLINT, RSSIHINT, * RSSSILINT, BLENDINT, MULTHINT and MULTLINT - * @attune - when set the values in the status report are the values + * @attune: - when set the values in the status report are the values * that were calculated at tune - * @cancel - abort ongoing seek/tune opertation - * @stcack - clear the STCINT bin in status register - * @report - all signal quality information retured by the command + * @cancel: - abort ongoing seek/tune opertation + * @stcack: - clear the STCINT bin in status register + * @report: - all signal quality information retured by the command * (if NULL then the output of the command is ignored) * * Function returns 0 on success and negative error code on failure @@ -862,9 +862,9 @@ EXPORT_SYMBOL_GPL(si476x_core_cmd_am_acf_status); /** * si476x_cmd_fm_seek_start - send 'FM_SEEK_START' command to the * device - * @core - device to send the command to - * @seekup - if set the direction of the search is 'up' - * @wrap - if set seek wraps when hitting band limit + * @core: - device to send the command to + * @seekup: - if set the direction of the search is 'up' + * @wrap: - if set seek wraps when hitting band limit * * This function begins search for a valid station. The station is * considered valid when 'FM_VALID_SNR_THRESHOLD' and @@ -890,12 +890,12 @@ EXPORT_SYMBOL_GPL(si476x_core_cmd_fm_seek_start); /** * si476x_cmd_fm_rds_status - send 'FM_RDS_STATUS' command to the * device - * @core - device to send the command to - * @status_only - if set the data is not removed from RDSFIFO, + * @core: - device to send the command to + * @status_only: - if set the data is not removed from RDSFIFO, * RDSFIFOUSED is not decremented and data in all the * rest RDS data contains the last valid info received - * @mtfifo if set the command clears RDS receive FIFO - * @intack if set the command clards the RDSINT bit. + * @mtfifo: if set the command clears RDS receive FIFO + * @intack: if set the command clards the RDSINT bit. * * Function returns 0 on success and negative error code on failure */ @@ -1036,9 +1036,9 @@ EXPORT_SYMBOL_GPL(si476x_core_cmd_fm_phase_div_status); /** * si476x_cmd_am_seek_start - send 'FM_SEEK_START' command to the * device - * @core - device to send the command to - * @seekup - if set the direction of the search is 'up' - * @wrap - if set seek wraps when hitting band limit + * @core: - device to send the command to + * @seekup: - if set the direction of the search is 'up' + * @wrap: - if set seek wraps when hitting band limit * * This function begins search for a valid station. The station is * considered valid when 'FM_VALID_SNR_THRESHOLD' and -- GitLab From c9b55f99fc679b3c7c9c1677b2fd2c86d6ac5e03 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Wed, 24 Jun 2020 14:32:06 +0100 Subject: [PATCH 0211/2249] mfd: si476x-i2c: Add description for si476x_core_fwver_to_revision()'s arg 'func' Kerneldoc syntax is used, but not complete. Descriptions are required for all arguments. Fixes the following W=1 build warning: drivers/mfd/si476x-i2c.c:550: warning: Function parameter or member 'func' not described in 'si476x_core_fwver_to_revision' Cc: Andrey Smirnov Signed-off-by: Lee Jones --- drivers/mfd/si476x-i2c.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/mfd/si476x-i2c.c b/drivers/mfd/si476x-i2c.c index c8d28b844def8..517d49bcd667b 100644 --- a/drivers/mfd/si476x-i2c.c +++ b/drivers/mfd/si476x-i2c.c @@ -534,6 +534,11 @@ static irqreturn_t si476x_core_interrupt(int irq, void *dev) /** * si476x_firmware_version_to_revision() * @core: Core device structure + * @func: Selects the boot function of the device: + * *_BOOTLOADER - Boot loader + * *_FM_RECEIVER - FM receiver + * *_AM_RECEIVER - AM receiver + * *_WB_RECEIVER - Weatherband receiver * @major: Firmware major number * @minor1: Firmware first minor number * @minor2: Firmware second minor number -- GitLab From b1ded80a61f3b7ee5337318f0dc1bada280f0605 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Wed, 24 Jun 2020 14:32:33 +0100 Subject: [PATCH 0212/2249] mfd: si476x-i2c: Fix spelling mistake in case() statement's FALLTHROUGH comment 's/FALLTHROUG/FALLTHROUGH' Cc: Andrey Smirnov Signed-off-by: Lee Jones --- drivers/mfd/si476x-i2c.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mfd/si476x-i2c.c b/drivers/mfd/si476x-i2c.c index 517d49bcd667b..c1d7b845244ed 100644 --- a/drivers/mfd/si476x-i2c.c +++ b/drivers/mfd/si476x-i2c.c @@ -588,7 +588,7 @@ static int si476x_core_fwver_to_revision(struct si476x_core *core, goto unknown_revision; } case SI476X_FUNC_BOOTLOADER: - default: /* FALLTHROUG */ + default: /* FALLTHROUGH */ BUG(); return -1; } -- GitLab From 748160e7718d1fb3c90c0df86c4b07e4b5e92621 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Wed, 24 Jun 2020 14:26:16 +0100 Subject: [PATCH 0213/2249] mfd: si476x-cmd: Update si476x_cmd_am_rsq_status()'s kerneldoc 4 of the old arguments were grouped and moved into a struct which is now passed as a pointer instead of the arguments themselves. However, whoever carried out this work forgot to update the function's kerneldoc header. Fixes the following W=1 warnings: drivers/mfd/si476x-cmd.c:746: warning: Function parameter or member 'rsqargs' not described in 'si476x_core_cmd_am_rsq_s drivers/mfd/si476x-cmd.c:746: warning: Excess function parameter 'rsqack' description in 'si476x_core_cmd_am_rsq_status' drivers/mfd/si476x-cmd.c:746: warning: Excess function parameter 'attune' description in 'si476x_core_cmd_am_rsq_status' drivers/mfd/si476x-cmd.c:746: warning: Excess function parameter 'cancel' description in 'si476x_core_cmd_am_rsq_status' drivers/mfd/si476x-cmd.c:746: warning: Excess function parameter 'stcack' description in 'si476x_core_cmd_am_rsq_status' Cc: Andrey Smirnov Signed-off-by: Lee Jones --- drivers/mfd/si476x-cmd.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/drivers/mfd/si476x-cmd.c b/drivers/mfd/si476x-cmd.c index 5b42dfab431a3..0a40c5cb751db 100644 --- a/drivers/mfd/si476x-cmd.c +++ b/drivers/mfd/si476x-cmd.c @@ -729,12 +729,8 @@ static int si476x_core_cmd_intb_pin_cfg_a20(struct si476x_core *core, * si476x_cmd_am_rsq_status - send 'AM_RSQ_STATUS' command to the * device * @core: - device to send the command to - * @rsqack: - if set command clears RSQINT, SNRINT, SNRLINT, RSSIHINT, - * RSSSILINT, BLENDINT, MULTHINT and MULTLINT - * @attune: - when set the values in the status report are the values - * that were calculated at tune - * @cancel: - abort ongoing seek/tune opertation - * @stcack: - clear the STCINT bin in status register + * @rsqargs: - pointer to a structure containing a group of sub-args + * relevant to sending the RSQ status command * @report: - all signal quality information retured by the command * (if NULL then the output of the command is ignored) * -- GitLab From 981b1261bfdf7cb3e3c2029ecc4a1510d46eff9e Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Wed, 24 Jun 2020 14:29:18 +0100 Subject: [PATCH 0214/2249] mfd: si476x-cmd: Add missing documentation for si476x_cmd_fm_rds_status()'s arg 'report' Kerneldoc syntax is used, but not complete. Descriptions are required for all arguments. Fixes the following W=1 build warning: drivers/mfd/si476x-cmd.c:907: warning: Function parameter or member 'report' not described in 'si476x_core_cmd_fm_rds_status' Cc: Andrey Smirnov Signed-off-by: Lee Jones --- drivers/mfd/si476x-cmd.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/mfd/si476x-cmd.c b/drivers/mfd/si476x-cmd.c index 0a40c5cb751db..d15b3e7833692 100644 --- a/drivers/mfd/si476x-cmd.c +++ b/drivers/mfd/si476x-cmd.c @@ -892,6 +892,8 @@ EXPORT_SYMBOL_GPL(si476x_core_cmd_fm_seek_start); * rest RDS data contains the last valid info received * @mtfifo: if set the command clears RDS receive FIFO * @intack: if set the command clards the RDSINT bit. + * @report: - all signal quality information retured by the command + * (if NULL then the output of the command is ignored) * * Function returns 0 on success and negative error code on failure */ -- GitLab From 768c1e38dc43b1fc43f73409f58c58344f243892 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Wed, 24 Jun 2020 14:52:27 +0100 Subject: [PATCH 0215/2249] mfd: rave-sp: Fix mistake in 'struct rave_sp_deframer's kerneldoc Argument 'received' was incorrectly named by its struct type 'completion' instead of its name. Fixes the following W=1 warning: drivers/mfd/rave-sp.c:107: warning: Function parameter or member 'received' not described in 'rave_sp_reply' Cc: Andrey Vostrikov Cc: Nikita Yushchenko Cc: Andrey Smirnov Signed-off-by: Lee Jones --- drivers/mfd/rave-sp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mfd/rave-sp.c b/drivers/mfd/rave-sp.c index 26c7b63e008a8..abaab541df19d 100644 --- a/drivers/mfd/rave-sp.c +++ b/drivers/mfd/rave-sp.c @@ -96,7 +96,7 @@ struct rave_sp_deframer { * @data: Buffer to store reply payload in * @code: Expected reply code * @ackid: Expected reply ACK ID - * @completion: Successful reply reception completion + * @received: Successful reply reception completion */ struct rave_sp_reply { size_t length; -- GitLab From ec46855df33973ac6ed646e26cc8977b97cc7cd0 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Thu, 25 Jun 2020 09:39:11 +0100 Subject: [PATCH 0216/2249] mfd: sprd-sc27xx-spi: Fix-up bogus IRQ register offset and mask setting 'i / pdata->num_irqs' always equates to 0 and 'BIT(i % pdata->num_irqs)' always ends up being BIT(i) here, so make that clearer in the code. If the code base needs to support more than 32 IRQs in the future, this will have to be reworked, but lets just keep it simple for as long as we can. This fixes the following W=1 warning: drivers/mfd/sprd-sc27xx-spi.c:255 sprd_pmic_probe() debug: sval_binop_unsigned: divide by zero Cc: Orson Zhai Cc: Chunyan Zhang Suggested-by: Baolin Wang Signed-off-by: Lee Jones Reviewed-by: Baolin Wang Signed-off-by: Lee Jones --- drivers/mfd/sprd-sc27xx-spi.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/mfd/sprd-sc27xx-spi.c b/drivers/mfd/sprd-sc27xx-spi.c index d3486c2a1b339..f8a8b918c60d9 100644 --- a/drivers/mfd/sprd-sc27xx-spi.c +++ b/drivers/mfd/sprd-sc27xx-spi.c @@ -185,10 +185,8 @@ static int sprd_pmic_probe(struct spi_device *spi) return -ENOMEM; ddata->irq_chip.irqs = ddata->irqs; - for (i = 0; i < pdata->num_irqs; i++) { - ddata->irqs[i].reg_offset = i / pdata->num_irqs; - ddata->irqs[i].mask = BIT(i % pdata->num_irqs); - } + for (i = 0; i < pdata->num_irqs; i++) + ddata->irqs[i].mask = BIT(i); ret = devm_regmap_add_irq_chip(&spi->dev, ddata->regmap, ddata->irq, IRQF_ONESHOT | IRQF_NO_SUSPEND, 0, -- GitLab From 662081acfa25edf0d8fabd8021ac26f0d1e2d3a1 Mon Sep 17 00:00:00 2001 From: "Tzvetomir Stoyanov (VMware)" Date: Thu, 2 Jul 2020 14:53:47 -0400 Subject: [PATCH 0217/2249] tools lib traceevent: Add tep_load_plugins_hook() API Add the API function tep_load_plugins_hook() to the traceevent API to allow tools a common method to load in the plugins that are part of the lib traceevent library. Link: http://lore.kernel.org/linux-trace-devel/20190802110101.14759-4-tz.stoyanov@gmail.com Link: http://lore.kernel.org/linux-trace-devel/20200625100516.365338-4-tz.stoyanov@gmail.com Signed-off-by: Tzvetomir Stoyanov (VMware) Cc: Andrew Morton Cc: Jiri Olsa Cc: Namhyung Kim Cc: linux-trace-devel@vger.kernel.org Link: http://lore.kernel.org/lkml/20200702185703.946652691@goodmis.org Signed-off-by: Steven Rostedt (VMware) Signed-off-by: Arnaldo Carvalho de Melo --- tools/lib/traceevent/event-parse.h | 6 ++++++ tools/lib/traceevent/event-plugin.c | 19 +++++++++---------- 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/tools/lib/traceevent/event-parse.h b/tools/lib/traceevent/event-parse.h index b77837f75a0d7..776c7c24ee792 100644 --- a/tools/lib/traceevent/event-parse.h +++ b/tools/lib/traceevent/event-parse.h @@ -396,6 +396,12 @@ struct tep_plugin_list; struct tep_plugin_list *tep_load_plugins(struct tep_handle *tep); void tep_unload_plugins(struct tep_plugin_list *plugin_list, struct tep_handle *tep); +void tep_load_plugins_hook(struct tep_handle *tep, const char *suffix, + void (*load_plugin)(struct tep_handle *tep, + const char *path, + const char *name, + void *data), + void *data); char **tep_plugin_list_options(void); void tep_plugin_free_options_list(char **list); int tep_plugin_add_options(const char *name, diff --git a/tools/lib/traceevent/event-plugin.c b/tools/lib/traceevent/event-plugin.c index e1f7ddd5a6cf0..b53d9a53bcf95 100644 --- a/tools/lib/traceevent/event-plugin.c +++ b/tools/lib/traceevent/event-plugin.c @@ -365,20 +365,19 @@ load_plugins_dir(struct tep_handle *tep, const char *suffix, closedir(dir); } -static void -load_plugins(struct tep_handle *tep, const char *suffix, - void (*load_plugin)(struct tep_handle *tep, - const char *path, - const char *name, - void *data), - void *data) +void tep_load_plugins_hook(struct tep_handle *tep, const char *suffix, + void (*load_plugin)(struct tep_handle *tep, + const char *path, + const char *name, + void *data), + void *data) { char *home; char *path; char *envdir; int ret; - if (tep->flags & TEP_DISABLE_PLUGINS) + if (tep && tep->flags & TEP_DISABLE_PLUGINS) return; /* @@ -386,7 +385,7 @@ load_plugins(struct tep_handle *tep, const char *suffix, * check that first. */ #ifdef PLUGIN_DIR - if (!(tep->flags & TEP_DISABLE_SYS_PLUGINS)) + if (!tep || !(tep->flags & TEP_DISABLE_SYS_PLUGINS)) load_plugins_dir(tep, suffix, PLUGIN_DIR, load_plugin, data); #endif @@ -423,7 +422,7 @@ tep_load_plugins(struct tep_handle *tep) { struct tep_plugin_list *list = NULL; - load_plugins(tep, ".so", load_plugin, &list); + tep_load_plugins_hook(tep, ".so", load_plugin, &list); return list; } -- GitLab From 74006289cfedbb2f922fcd6fef7efee232450550 Mon Sep 17 00:00:00 2001 From: "Tzvetomir Stoyanov (VMware)" Date: Thu, 2 Jul 2020 14:53:48 -0400 Subject: [PATCH 0218/2249] tools lib traceevent: Add interface for options to plugins Add tep_plugin_add_option() and tep_plugin_print_options() to lib traceevent library that allows plugins to have their own options. For example, the function plugin by default does not print the parent, as it uses the parent to do the indenting. The "parent" option is created by the function plugin that will print the parent of the function like it does in the trace file. The tep_plugin_print_options() will print out the list of options that a Cc: Tzvetomir Stoyanov (VMware) plugin has defined. Link: http://lore.kernel.org/linux-trace-devel/20190802110101.14759-3-tz.stoyanov@gmail.com Link: http://lore.kernel.org/linux-trace-devel/20200625100516.365338-5-tz.stoyanov@gmail.com Signed-off-by: Tzvetomir Stoyanov (VMware) Cc: Andrew Morton Cc: Jiri Olsa Cc: Namhyung Kim Cc: linux-trace-devel@vger.kernel.org Link: http://lore.kernel.org/lkml/20200702185704.092654084@goodmis.org Signed-off-by: Steven Rostedt (VMware) Signed-off-by: Arnaldo Carvalho de Melo --- tools/lib/traceevent/event-parse.h | 2 + tools/lib/traceevent/event-plugin.c | 172 ++++++++++++++++++++++++++++ 2 files changed, 174 insertions(+) diff --git a/tools/lib/traceevent/event-parse.h b/tools/lib/traceevent/event-parse.h index 776c7c24ee792..02c0438527de6 100644 --- a/tools/lib/traceevent/event-parse.h +++ b/tools/lib/traceevent/event-parse.h @@ -406,7 +406,9 @@ char **tep_plugin_list_options(void); void tep_plugin_free_options_list(char **list); int tep_plugin_add_options(const char *name, struct tep_plugin_option *options); +int tep_plugin_add_option(const char *name, const char *val); void tep_plugin_remove_options(struct tep_plugin_option *options); +void tep_plugin_print_options(struct trace_seq *s); void tep_print_plugins(struct trace_seq *s, const char *prefix, const char *suffix, const struct tep_plugin_list *list); diff --git a/tools/lib/traceevent/event-plugin.c b/tools/lib/traceevent/event-plugin.c index b53d9a53bcf95..e8f4329ba8e08 100644 --- a/tools/lib/traceevent/event-plugin.c +++ b/tools/lib/traceevent/event-plugin.c @@ -13,6 +13,7 @@ #include #include #include +#include #include "event-parse.h" #include "event-parse-local.h" #include "event-utils.h" @@ -247,6 +248,166 @@ void tep_plugin_remove_options(struct tep_plugin_option *options) } } +static void parse_option_name(char **option, char **plugin) +{ + char *p; + + *plugin = NULL; + + if ((p = strstr(*option, ":"))) { + *plugin = *option; + *p = '\0'; + *option = strdup(p + 1); + if (!*option) + return; + } +} + +static struct tep_plugin_option * +find_registered_option(const char *plugin, const char *option) +{ + struct registered_plugin_options *reg; + struct tep_plugin_option *op; + const char *op_plugin; + + for (reg = registered_options; reg; reg = reg->next) { + for (op = reg->options; op->name; op++) { + if (op->plugin_alias) + op_plugin = op->plugin_alias; + else + op_plugin = op->file; + + if (plugin && strcmp(plugin, op_plugin) != 0) + continue; + if (strcmp(option, op->name) != 0) + continue; + + return op; + } + } + + return NULL; +} + +static int process_option(const char *plugin, const char *option, const char *val) +{ + struct tep_plugin_option *op; + + op = find_registered_option(plugin, option); + if (!op) + return 0; + + return update_option_value(op, val); +} + +/** + * tep_plugin_add_option - add an option/val pair to set plugin options + * @name: The name of the option (format: :