4.14.108-stable review
Greg Kroah-Hartman
maintainerPATCH 164/183 perf auxtrace: Define auxtrace record alignment
In reply to Greg Kroah-Hartman4.14-stable review patch. If anyone has any objections, please let me know.
------------------
From: Adrian Hunter <[email protected]>
commit c3fcadf0bb765faf45d6d562246e1d08885466df upstream.
Define auxtrace record alignment so that it can be referenced elsewhere.
Note this is preparation for patch "perf intel-pt: Fix overlap calculation for padding"
--- tools/perf/util/auxtrace.c | 4 ++-- tools/perf/util/auxtrace.h | 3 +++ 2 files changed, 5 insertions(+), 2 deletions(-)
tools/perf/util/auxtrace.c +2 -2
@@ -1264,9 +1264,9 @@ static int __auxtrace_mmap__read(struct }/* padding must be written by fn() e.g. record__process_auxtrace() */ - padding = size &7 ; + padding = size & (PERF_AUXTRACE_RECORD_ALIGNMENT -1 );if (padding) - padding =8 - padding; + padding =PERF_AUXTRACE_RECORD_ALIGNMENT - padding;memset (&ev,0 ,sizeof (ev)); ev.auxtrace.header.type =PERF_RECORD_AUXTRACE ;
tools/perf/util/auxtrace.h +3 -0
@@ -38,6 +38,9 @@ struct record_opts;struct auxtrace_info_event ;struct events_stats ; +/* Auxtrace records must have the same alignment as perf event records */ +#define PERF_AUXTRACE_RECORD_ALIGNMENT 8 +enum auxtrace_type {PERF_AUXTRACE_UNKNOWN ,PERF_AUXTRACE_INTEL_PT ,
Greg Kroah-Hartman
maintainerPATCH 165/183 perf intel-pt: Fix overlap calculation for padding
In reply to Greg Kroah-Hartman4.14-stable review patch. If anyone has any objections, please let me know.
------------------
From: Adrian Hunter <[email protected]>
commit 5a99d99e3310a565b0cf63f785b347be9ee0da45 upstream.
Auxtrace records might have up to 7 bytes of padding appended. Adjust the overlap accordingly.
--- tools/perf/util/intel-pt-decoder/intel-pt-decoder.c | 36 ++++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-)
tools/perf/util/intel-pt-decoder/intel-pt-decoder.c +34 -2
@@ -26,6 +26,7 @@#include "../cache.h" #include "../util.h" +#include "../auxtrace.h" #include "intel-pt-insn-decoder.h" #include "intel-pt-pkt-decoder.h"
@@ -2558,6 +2559,34 @@ static int intel_pt_tsc_cmp(uint64_t tsc } } +#define MAX_PADDING (PERF_AUXTRACE_RECORD_ALIGNMENT - 1) + +/** +* adj_for_padding - adjust overlap to account for padding. +* @buf_b: second buffer +* @buf_a: first buffer +* @len_a: size of first buffer +* +* @buf_a might have up to 7 bytes of padding appended. Adjust the overlap +* accordingly. +* +* Return: A pointer into @buf_b from where non-overlapped data starts +*/ +static unsigned char *adj_for_padding (unsigned char *buf_b, +unsigned char *buf_a,size_t len_a) +{ +unsigned char *p = buf_b -MAX_PADDING ; +unsigned char *q = buf_a + len_a -MAX_PADDING ; +int i; + +for (i =MAX_PADDING ; i; i--, p++, q++) { +if (*p != *q) +break ; + } + +return p; +} +/** * intel_pt_find_overlap_tsc - determine start of non-overlapped trace data * using TSC.
@@ -2608,8 +2637,11 @@ static unsigned char *intel_pt_find_over/* Same TSC, so buffers are consecutive */ if (!cmp && rem_b >= rem_a) { +unsigned char *start; + *consecutive = true; -return buf_b + len_b - (rem_b - rem_a); + start = buf_b + len_b - (rem_b - rem_a); +return adj_for_padding (start, buf_a, len_a); }if (cmp <0 )return buf_b;/* tsc_a < tsc_b => no overlap */
@@ -2672,7 +2704,7 @@ unsigned char *intel_pt_find_overlap(uns found =memmem (buf_a, len_a, buf_b, len_a);if (found) { *consecutive = true; -return buf_b + len_a; +return adj_for_padding (buf_b + len_a, buf_a, len_a); }/* Try again at next PSB in buffer 'a' */
Greg Kroah-Hartman
maintainerPATCH 166/183 perf intel-pt: Fix divide by zero when TSC is not available
In reply to Greg Kroah-Hartman4.14-stable review patch. If anyone has any objections, please let me know.
------------------
From: Adrian Hunter <[email protected]>
commit 076333870c2f5bdd9b6d31e7ca1909cf0c84cbfa upstream.
When TSC is not available, "timeless" decoding is used but a divide by zero occurs if perf_time_to_tsc() is called.
Ensure the divisor is not zero.
--- tools/perf/util/intel-pt.c | 2 ++ 1 file changed, 2 insertions(+)
tools/perf/util/intel-pt.c +2 -0
@@ -2545,6 +2545,8 @@ int intel_pt_process_auxtrace_info(union } pt->timeless_decoding =intel_pt_timeless_decoding (pt); +if (pt->timeless_decoding && !pt->tc.time_mult) + pt->tc.time_mult =1 ; pt->have_tsc =intel_pt_have_tsc (pt); pt->sampling_mode = false; pt->est_tsc = !pt->timeless_decoding;
Greg Kroah-Hartman
maintainerPATCH 167/183 md: Fix failed allocation of md_register_thread
In reply to Greg Kroah-Hartman4.14-stable review patch. If anyone has any objections, please let me know.
------------------
From: Aditya Pakki <[email protected]>
commit e406f12dde1a8375d77ea02d91f313fb1a9c6aec upstream.
mddev->sync_thread can be set to NULL on kzalloc failure downstream. The patch checks for such a scenario and frees allocated resources.
Committer node:
Added similar fix to raid5.c, as suggested by Guoqing.
--- drivers/md/raid10.c | 2 ++ drivers/md/raid5.c | 2 ++ 2 files changed, 4 insertions(+)
drivers/md/raid10.c +2 -0
@@ -3821,6 +3821,8 @@ static int raid10_run(struct mddev *mddeset_bit (MD_RECOVERY_RUNNING , &mddev->recovery); mddev->sync_thread =md_register_thread (md_do_sync, mddev,"reshape" ); +if (!mddev->sync_thread) + goto out_free_conf; }return 0 ;
drivers/md/raid5.c +2 -0
@@ -7370,6 +7370,8 @@ static int raid5_run(struct mddev *mddevset_bit (MD_RECOVERY_RUNNING , &mddev->recovery); mddev->sync_thread =md_register_thread (md_do_sync, mddev,"reshape" ); +if (!mddev->sync_thread) + goto abort; }/* Ok, everything is just fine now */
Greg Kroah-Hartman
maintainerPATCH 168/183 tpm/tpm_crb: Avoid unaligned reads in crb_recv()
In reply to Greg Kroah-Hartman4.14-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jarkko Sakkinen <[email protected]>
commit 3d7a850fdc1a2e4d2adbc95cc0fc962974725e88 upstream.
The current approach to read first 6 bytes from the response and then tail of the response, can cause the 2nd memcpy_fromio() to do an unaligned read (e.g. read 32-bit word from address aligned to a 16-bits), depending on how memcpy_fromio() is implemented. If this happens, the read will fail and the memory controller will fill the read with 1's.
This was triggered by 170d13ca3a2f, which should be probably refined to check and react to the address alignment. Before that commit, on x86 memcpy_fromio() turned out to be memcpy(). By a luck GCC has done the right thing (from tpm_crb's perspective) for us so far, but we should not rely on that. Thus, it makes sense to fix this also in tpm_crb, not least because the fix can be then backported to stable kernels and make them more robust when compiled in differing environments.
--- drivers/char/tpm/tpm_crb.c | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-)
drivers/char/tpm/tpm_crb.c +16 -6
@@ -288,19 +288,29 @@ static int crb_recv(struct tpm_chip *chistruct crb_priv *priv =dev_get_drvdata (&chip->dev);unsigned int expected; -/* sanity check */ -if (count <6 ) +/* A sanity check that the upper layer wants to get at least the header +* as that is the minimum size for any TPM response. +*/ +if (count <TPM_HEADER_SIZE )return -EIO ; +/* If this bit is set, according to the spec, the TPM is in +* unrecoverable condition. +*/ if (ioread32 (&priv->regs_t->ctrl_sts) &CRB_CTRL_STS_ERROR )return -EIO ; -memcpy_fromio (buf, priv->rsp,6 ); - expected =be32_to_cpup ((__be32 *) &buf[2 ]); -if (expected > count || expected <6 ) +/* Read the first 8 bytes in order to get the length of the response. +* We read exactly a quad word in order to make sure that the remaining +* reads will be aligned. +*/ +memcpy_fromio (buf, priv->rsp,8 ); + + expected =be32_to_cpup ((__be32 *)&buf[2 ]); +if (expected > count || expected <TPM_HEADER_SIZE )return -EIO ; -memcpy_fromio (&buf[6 ], &priv->rsp[6 ], expected -6 ); +memcpy_fromio (&buf[8 ], &priv->rsp[8 ], expected -8 );return expected; }
Greg Kroah-Hartman
maintainerPATCH 169/183 tpm: Unify the send callback behaviour
In reply to Greg Kroah-Hartman4.14-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jarkko Sakkinen <[email protected]>
commit f5595f5baa30e009bf54d0d7653a9a0cc465be60 upstream.
The send() callback should never return length as it does not in every driver except tpm_crb in the success case. The reason is that the main transmit functionality only cares about whether the transmit was successful or not and ignores the count completely.
--- drivers/char/tpm/st33zp24/st33zp24.c | 2 +- drivers/char/tpm/tpm-interface.c | 11 ++++++++++- drivers/char/tpm/tpm_atmel.c | 2 +- drivers/char/tpm/tpm_i2c_atmel.c | 6 +++++- drivers/char/tpm/tpm_i2c_infineon.c | 2 +- drivers/char/tpm/tpm_i2c_nuvoton.c | 2 +- drivers/char/tpm/tpm_ibmvtpm.c | 8 ++++---- drivers/char/tpm/tpm_infineon.c | 2 +- drivers/char/tpm/tpm_nsc.c | 2 +- drivers/char/tpm/tpm_tis_core.c | 2 +- drivers/char/tpm/tpm_vtpm_proxy.c | 3 +-- drivers/char/tpm/xen-tpmfront.c | 2 +- 12 files changed, 28 insertions(+), 16 deletions(-)
drivers/char/tpm/st33zp24/st33zp24.c +1 -1
@@ -438,7 +438,7 @@ static int st33zp24_send(struct tpm_chip goto out_err; } -return len; +return 0 ; out_err:st33zp24_cancel (chip);release_locality (chip);
drivers/char/tpm/tpm-interface.c +10 -1
@@ -497,10 +497,19 @@ static ssize_t tpm_try_transmit(struct tif (rc <0 ) {if (rc != -EPIPE )dev_err (&chip->dev, -"%s: tpm_send: error %d\n" , __func__, rc); +"%s: send(): error %d\n" , __func__, rc); goto out; } +/* A sanity check. send() should just return zero on success e.g. +* not the command length. +*/ +if (rc >0 ) { +dev_warn (&chip->dev, +"%s: send(): invalid value %d\n" , __func__, rc); + rc =0 ; + } +if (chip->flags &TPM_CHIP_FLAG_IRQ ) goto out_recv;
drivers/char/tpm/tpm_atmel.c +1 -1
@@ -105,7 +105,7 @@ static int tpm_atml_send(struct tpm_chipiowrite8 (buf[i], priv->iobase); } -return count; +return 0 ; }static void tpm_atml_cancel (struct tpm_chip *chip)
drivers/char/tpm/tpm_i2c_atmel.c +5 -1
@@ -65,7 +65,11 @@ static int i2c_atmel_send(struct tpm_chidev_dbg (&chip->dev,"%s(buf=%*ph len=%0zx) -> sts=%d\n" , __func__, (int )min_t (size_t,64 , len), buf, len, status); -return status; + +if (status <0 ) +return status; + +return 0 ; }static int i2c_atmel_recv (struct tpm_chip *chip,u8 *buf,size_t count)
drivers/char/tpm/tpm_i2c_infineon.c +1 -1
@@ -587,7 +587,7 @@ static int tpm_tis_i2c_send(struct tpm_c/* go and do it */ iic_tpm_write (TPM_STS (tpm_dev.locality), &sts,1 ); -return len; +return 0 ; out_err:tpm_tis_i2c_ready (chip);/* The TPM needs some time to clean up here,
drivers/char/tpm/tpm_i2c_nuvoton.c +1 -1
@@ -469,7 +469,7 @@ static int i2c_nuvoton_send(struct tpm_c }dev_dbg (dev,"%s() -> %zd\n" , __func__, len); -return len; +return 0 ; }static bool i2c_nuvoton_req_canceled (struct tpm_chip *chip,u8 status)
drivers/char/tpm/tpm_ibmvtpm.c +4 -4
@@ -141,14 +141,14 @@ static int tpm_ibmvtpm_recv(struct tpm_c }/** -* tpm_ibmvtpm_send - Send tpm request -* +* tpm_ibmvtpm_send() - Send a TPM command * @chip: tpm chip struct * @buf: buffer contains data to send * @count: size of buffer * * Return: -* Number of bytes sent or < 0 on error. +* 0 on success, +* -errno on error */ static int tpm_ibmvtpm_send (struct tpm_chip *chip,u8 *buf,size_t count) {
@@ -194,7 +194,7 @@ static int tpm_ibmvtpm_send(struct tpm_c rc =0 ; ibmvtpm->tpm_processing_cmd = false; }else - rc = count; + rc =0 ;spin_unlock (&ibmvtpm->rtce_lock);return rc;
drivers/char/tpm/tpm_infineon.c +1 -1
@@ -354,7 +354,7 @@ static int tpm_inf_send(struct tpm_chipfor (i =0 ; i < count; i++) {wait_and_send (chip, buf[i]); } -return count; +return 0 ; }static void tpm_inf_cancel (struct tpm_chip *chip)
drivers/char/tpm/tpm_nsc.c +1 -1
@@ -226,7 +226,7 @@ static int tpm_nsc_send(struct tpm_chip }outb (NSC_COMMAND_EOC , priv->base +NSC_COMMAND ); -return count; +return 0 ; }static void tpm_nsc_cancel (struct tpm_chip *chip)
drivers/char/tpm/tpm_tis_core.c +1 -1
@@ -379,7 +379,7 @@ static int tpm_tis_send_main(struct tpm_ goto out_err; } } -return len; +return 0 ; out_err:tpm_tis_ready (chip);return rc;
drivers/char/tpm/tpm_vtpm_proxy.c +1 -2
@@ -335,7 +335,6 @@ static int vtpm_proxy_is_driver_command(static int vtpm_proxy_tpm_op_send (struct tpm_chip *chip,u8 *buf,size_t count) {struct proxy_dev *proxy_dev =dev_get_drvdata (&chip->dev); -int rc =0 ;if (count >sizeof (proxy_dev->buffer)) { dev_err(&chip->dev,
@@ -366,7 +365,7 @@ static int vtpm_proxy_tpm_op_send(structwake_up_interruptible (&proxy_dev->wq); -return rc; +return 0 ; }static void vtpm_proxy_tpm_op_cancel (struct tpm_chip *chip)
drivers/char/tpm/xen-tpmfront.c +1 -1
@@ -112,7 +112,7 @@ static int vtpm_send(struct tpm_chip *chreturn -ETIME ; } -return count; +return 0 ; }static int vtpm_recv (struct tpm_chip *chip,u8 *buf,size_t count)
Greg Kroah-Hartman
maintainerPATCH 170/183 rcu: Do RCU GP kthread self-wakeup from softirq and interrupt
In reply to Greg Kroah-Hartman4.14-stable review patch. If anyone has any objections, please let me know.
------------------
From: Zhang, Jun <[email protected]>
commit 1d1f898df6586c5ea9aeaf349f13089c6fa37903 upstream.
The rcu_gp_kthread_wake() function is invoked when it might be necessary to wake the RCU grace-period kthread. Because self-wakeups are normally a useless waste of CPU cycles, if rcu_gp_kthread_wake() is invoked from this kthread, it naturally refuses to do the wakeup.
Unfortunately, natural though it might be, this heuristic fails when rcu_gp_kthread_wake() is invoked from an interrupt or softirq handler that interrupted the grace-period kthread just after the final check of the wait-event condition but just before the schedule() call. In this case, a wakeup is required, even though the call to rcu_gp_kthread_wake() is within the RCU grace-period kthread's context. Failing to provide this wakeup can result in grace periods failing to start, which in turn results in out-of-memory conditions.
This race window is quite narrow, but it actually did happen during real testing. It would of course need to be fixed even if it was strictly theoretical in nature.
This patch does not Cc stable because it does not apply cleanly to earlier kernel versions.
Signed-off: "Zhang, Jun" <[email protected]>
Signed-off: "He, Bo" <[email protected]>
Signed-off: "xiao, jin" <[email protected]>
Signed-off: Bai, Jie A <[email protected]>
[ paulmck: Switch from !in_softirq() to "!in_interrupt() &&
!in_serving_softirq() to avoid redundant wakeups and to also handle the interrupt-handler scenario as well as the softirq-handler scenario that actually occurred in testing. ]
--- kernel/rcu/tree.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-)
kernel/rcu/tree.c +14 -6
@@ -1789,15 +1789,23 @@ static int rcu_future_gp_cleanup(struct }/* -* Awaken the grace-period kthread for the specified flavor of RCU. -* Don't do a self-awaken, and don't bother awakening when there is -* nothing for the grace-period kthread to do (as in several CPUs -* raced to awaken, and we lost), and finally don't try to awaken -* a kthread that has not yet been created. +* Awaken the grace-period kthread. Don't do a self-awaken (unless in +* an interrupt or softirq handler), and don't bother awakening when there +* is nothing for the grace-period kthread to do (as in several CPUs raced +* to awaken, and we lost), and finally don't try to awaken a kthread that +* has not yet been created. If all those checks are passed, track some +* debug information and awaken. +* +* So why do the self-wakeup when in an interrupt or softirq handler +* in the grace-period kthread's context? Because the kthread might have +* been interrupted just as it was going to sleep, and just after the final +* pre-sleep check of the awaken condition. In this case, a wakeup really +* is required, and is therefore supplied. */ static void rcu_gp_kthread_wake (struct rcu_state *rsp) { -if (current == rsp->gp_kthread || +if ((current == rsp->gp_kthread && + !in_interrupt () && !in_serving_softirq ()) || !READ_ONCE (rsp->gp_flags) || !rsp->gp_kthread)return ;
Greg Kroah-Hartman
maintainerPATCH 171/183 media: imx: prpencvf: Stop upstream before disabling IDMA channel
In reply to Greg Kroah-Hartman4.14-stable review patch. If anyone has any objections, please let me know.
------------------
From: Steve Longerbeam <[email protected]>
commit a19c22677377b87e4354f7306f46ad99bc982a9f upstream.
Upstream must be stopped immediately after receiving the last EOF and before disabling the IDMA channel. This can be accomplished by moving upstream stream off to just after receiving the last EOF completion in prp_stop(). For symmetry also move upstream stream on to end of prp_start().
This fixes a complete system hard lockup on the SabreAuto when streaming from the ADV7180, by repeatedly sending a stream off immediately followed by stream on:
while true; do v4l2-ctl -d1 --stream-mmap --stream-count=3; done
Eventually this either causes the system lockup or EOF timeouts at all subsequent stream on, until a system reset.
The lockup occurs when disabling the IDMA channel at stream off. Stopping the video data stream entering the IDMA channel before disabling the channel itself appears to be a reliable fix for the hard lockup.
--- drivers/staging/media/imx/imx-ic-prpencvf.c | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-)
drivers/staging/media/imx/imx-ic-prpencvf.c +17 -9
@@ -676,12 +676,23 @@ static int prp_start(struct prp_priv *pr goto out_free_nfb4eof_irq; } +/* start upstream */ + ret =v4l2_subdev_call (priv->src_sd, video, s_stream,1 ); + ret = (ret && ret != -ENOIOCTLCMD ) ? ret :0 ; +if (ret) { +v4l2_err (&ic_priv->sd, +"upstream stream on failed: %d\n" , ret); + goto out_free_eof_irq; + } +/* start the EOF timeout timer */ mod_timer (&priv->eof_timeout_timer, jiffies +msecs_to_jiffies (IMX_MEDIA_EOF_TIMEOUT ));return 0 ; +out_free_eof_irq: +devm_free_irq (ic_priv->dev, priv->eof_irq, priv); out_free_nfb4eof_irq:devm_free_irq (ic_priv->dev, priv->nfb4eof_irq, priv); out_unsetup:
@@ -713,6 +724,12 @@ static void prp_stop(struct prp_priv *prif (ret ==0 )v4l2_warn (&ic_priv->sd,"wait last EOF timeout\n" ); +/* stop upstream */ + ret =v4l2_subdev_call (priv->src_sd, video, s_stream,0 ); +if (ret && ret != -ENOIOCTLCMD ) +v4l2_warn (&ic_priv->sd, +"upstream stream off failed: %d\n" , ret); +devm_free_irq (ic_priv->dev, priv->eof_irq, priv);devm_free_irq (ic_priv->dev, priv->nfb4eof_irq, priv);
@@ -1144,15 +1161,6 @@ static int prp_s_stream(struct v4l2_subdif (ret) goto out; -/* start/stop upstream */ - ret =v4l2_subdev_call (priv->src_sd, video, s_stream, enable); - ret = (ret && ret != -ENOIOCTLCMD ) ? ret :0 ; -if (ret) { -if (enable) -prp_stop (priv); - goto out; - } - update_count: priv->stream_count += enable ?1 :-1 ;if (priv->stream_count <0 )
Greg Kroah-Hartman
maintainerPATCH 172/183 media: uvcvideo: Avoid NULL pointer dereference at the end of streaming
In reply to Greg Kroah-Hartman4.14-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sakari Ailus <[email protected]>
commit 9dd0627d8d62a7ddb001a75f63942d92b5336561 upstream.
The UVC video driver converts the timestamp from hardware specific unit to one known by the kernel at the time when the buffer is dequeued. This is fine in general, but the streamoff operation consists of the following steps (among other things):
1. uvc_video_clock_cleanup --- the hardware clock sample array is released and the pointer to the array is set to NULL,
2. buffers in active state are returned to the user and
3. buf_finish callback is called on buffers that are prepared. buf_finish includes calling uvc_video_clock_update that accesses the hardware clock sample array.
The above is serialised by a queue specific mutex. Address the problem by skipping the clock conversion if the hardware clock sample array is already released.
--- drivers/media/usb/uvc/uvc_video.c | 8 ++++++++ 1 file changed, 8 insertions(+)
drivers/media/usb/uvc/uvc_video.c +8 -0
@@ -638,6 +638,14 @@ void uvc_video_clock_update(struct uvc_sif (!uvc_hw_timestamps_param)return ; +/* +* We will get called from __vb2_queue_cancel() if there are buffers +* done but not dequeued by the user, but the sample array has already +* been released at that time. Just bail out in that case. +*/ +if (!clock->samples) +return ; +spin_lock_irqsave (&clock->lock, flags);if (clock->count < clock->size)
Greg Kroah-Hartman
maintainerPATCH 173/183 media: vimc: Add vimc-streamer for stream control
In reply to Greg Kroah-Hartman4.14-stable review patch. If anyone has any objections, please let me know.
------------------
From: Lucas A. M. Magalhães <[email protected]>
commit adc589d2a20808fb99d46a78175cd023f2040338 upstream.
Add a linear pipeline logic for the stream control. It's created by walking backwards on the entity graph. When the stream starts it will simply loop through the pipeline calling the respective process_frame function of each entity.
and sensor")
--- drivers/media/platform/vimc/Makefile | 3 drivers/media/platform/vimc/vimc-capture.c | 18 +- drivers/media/platform/vimc/vimc-common.c | 35 ----- drivers/media/platform/vimc/vimc-common.h | 15 -- drivers/media/platform/vimc/vimc-debayer.c | 26 --- drivers/media/platform/vimc/vimc-scaler.c | 28 ---- drivers/media/platform/vimc/vimc-sensor.c | 56 +------- drivers/media/platform/vimc/vimc-streamer.c | 188 ++++++++++++++++++++++++++++ drivers/media/platform/vimc/vimc-streamer.h | 38 +++++ 9 files changed, 260 insertions(+), 147 deletions(-)
drivers/media/platform/vimc/Makefile +2 -1
@@ -5,6 +5,7 @@ vimc_common-objs := vimc-common.o vimc_debayer-objs := vimc-debayer.o vimc_scaler-objs := vimc-scaler.o vimc_sensor-objs := vimc-sensor.o +vimc_streamer-objs := vimc-streamer.o obj-$(CONFIG_VIDEO_VIMC) += vimc.o vimc_capture.o vimc_common.o vimc-debayer.o \ - vimc_scaler.o vimc_sensor.o + vimc_scaler.o vimc_sensor.o vimc_streamer.o
drivers/media/platform/vimc/vimc-capture.c +9 -9
@@ -23,6 +23,7 @@#include <media/videobuf2-vmalloc.h> #include "vimc-common.h" +#include "vimc-streamer.h" #define VIMC_CAP_DRV_NAME "vimc-capture"
@@ -43,7 +44,7 @@ struct vimc_cap_device {spinlock_t qlock;struct mutex lock;u32 sequence; -struct media_pipeline pipe; +struct vimc_stream stream; };static const struct v4l2_pix_format fmt_default = {
@@ -247,14 +248,13 @@ static int vimc_cap_start_streaming(stru vcap->sequence =0 ;/* Start the media pipeline */ - ret =media_pipeline_start (entity, &vcap->pipe); + ret =media_pipeline_start (entity, &vcap->stream.pipe);if (ret) {vimc_cap_return_all_buffers (vcap,VB2_BUF_STATE_QUEUED );return ret; } -/* Enable streaming from the pipe */ - ret =vimc_pipeline_s_stream (&vcap->vdev.entity,1 ); + ret =vimc_streamer_s_stream (&vcap->stream, &vcap->ved,1 );if (ret) {media_pipeline_stop (entity);vimc_cap_return_all_buffers (vcap,VB2_BUF_STATE_QUEUED );
@@ -272,8 +272,7 @@ static void vimc_cap_stop_streaming(stru {struct vimc_cap_device *vcap =vb2_get_drv_priv (vq); -/* Disable streaming from the pipe */ -vimc_pipeline_s_stream (&vcap->vdev.entity,0 ); +vimc_streamer_s_stream (&vcap->stream, &vcap->ved,0 );/* Stop the media pipeline */ media_pipeline_stop (&vcap->vdev.entity);
@@ -354,8 +353,8 @@ static void vimc_cap_comp_unbind(structkfree (vcap); } -static void vimc_cap_process_frame (struct vimc_ent_device *ved, -struct media_pad *sink,const void *frame) +static void *vimc_cap_process_frame (struct vimc_ent_device *ved, +const void *frame) { struct vimc_cap_device *vcap = container_of(ved, struct vimc_cap_device, ved);
@@ -369,7 +368,7 @@ static void vimc_cap_process_frame(struc typeof(*vimc_buf), list);if (!vimc_buf) {spin_unlock (&vcap->qlock); -return ; +return ERR_PTR (-EAGAIN ); }/* Remove this entry from the list */
@@ -390,6 +389,7 @@ static void vimc_cap_process_frame(strucvb2_set_plane_payload (&vimc_buf->vb2.vb2_buf,0 , vcap->format.sizeimage);vb2_buffer_done (&vimc_buf->vb2.vb2_buf,VB2_BUF_STATE_DONE ); +return NULL ; } static int vimc_cap_comp_bind(struct device *comp, struct device *master,
drivers/media/platform/vimc/vimc-common.c +0 -35
@@ -207,41 +207,6 @@ const struct vimc_pix_map *vimc_pix_map_ }EXPORT_SYMBOL_GPL (vimc_pix_map_by_pixelformat); -int vimc_propagate_frame (struct media_pad *src,const void *frame) -{ -struct media_link *link; - -if (!(src->flags &MEDIA_PAD_FL_SOURCE )) -return -EINVAL ; - -/* Send this frame to all sink pads that are direct linked */ -list_for_each_entry (link, &src->entity->links, list) { -if (link->source == src && - (link->flags &MEDIA_LNK_FL_ENABLED )) { -struct vimc_ent_device *ved =NULL ; -struct media_entity *entity = link->sink->entity; - -if (is_media_entity_v4l2_subdev (entity)) { -struct v4l2_subdev *sd = - container_of(entity, struct v4l2_subdev, - entity); - ved =v4l2_get_subdevdata (sd); - }else if (is_media_entity_v4l2_video_device (entity)) { -struct video_device *vdev = -container_of (entity, - struct video_device, - entity); - ved =video_get_drvdata (vdev); - } -if (ved && ved->process_frame) - ved->process_frame (ved, link->sink, frame); - } - } - -return 0 ; -} -EXPORT_SYMBOL_GPL (vimc_propagate_frame); -/* Helper function to allocate and initialize pads */ struct media_pad *vimc_pads_init (u16 num_pads,const unsigned long *pads_flag) {
drivers/media/platform/vimc/vimc-common.h +2 -13
@@ -108,24 +108,13 @@ struct vimc_pix_map {struct vimc_ent_device {struct media_entity *ent;struct media_pad *pads; -void (*process_frame)(struct vimc_ent_device *ved, -struct media_pad *sink,const void *frame); +void * (*process_frame)(struct vimc_ent_device *ved, +const void *frame);void (*vdev_get_format)(struct vimc_ent_device *ved,struct v4l2_pix_format *fmt); };/** -* vimc_propagate_frame - propagate a frame through the topology -* -* @src: the source pad where the frame is being originated -* @frame: the frame to be propagated -* -* This function will call the process_frame callback from the vimc_ent_device -* struct of the nodes directly connected to the @src pad -*/ -int vimc_propagate_frame (struct media_pad *src,const void *frame); - -/** * vimc_pads_init - initialize pads * * @num_pads: number of pads to initialize
drivers/media/platform/vimc/vimc-debayer.c +4 -22
@@ -320,7 +320,6 @@ static void vimc_deb_set_rgb_mbus_fmt_rgstatic int vimc_deb_s_stream (struct v4l2_subdev *sd,int enable) {struct vimc_deb_device *vdeb =v4l2_get_subdevdata (sd); -int ret;if (enable) {const struct vimc_pix_map *vpix;
@@ -350,22 +349,10 @@ static int vimc_deb_s_stream(struct v4l2if (!vdeb->src_frame)return -ENOMEM ; -/* Turn the stream on in the subdevices directly connected */ - ret =vimc_pipeline_s_stream (&vdeb->sd.entity,1 ); -if (ret) { -vfree (vdeb->src_frame); - vdeb->src_frame =NULL ; -return ret; - } }else {if (!vdeb->src_frame)return 0 ; -/* Disable streaming from the pipe */ - ret =vimc_pipeline_s_stream (&vdeb->sd.entity,0 ); -if (ret) -return ret; -vfree (vdeb->src_frame); vdeb->src_frame =NULL ; }
@@ -479,9 +466,8 @@ static void vimc_deb_calc_rgb_sink(struc } } -static void vimc_deb_process_frame (struct vimc_ent_device *ved, -struct media_pad *sink, -const void *sink_frame) +static void *vimc_deb_process_frame (struct vimc_ent_device *ved, +const void *sink_frame) { struct vimc_deb_device *vdeb = container_of(ved, struct vimc_deb_device, ved);
@@ -490,7 +476,7 @@ static void vimc_deb_process_frame(struc/* If the stream in this node is not active, just return */ if (!vdeb->src_frame) -return ; +return ERR_PTR (-EINVAL );for (i =0 ; i < vdeb->sink_fmt.height; i++)for (j =0 ; j < vdeb->sink_fmt.width; j++) {
@@ -498,12 +484,8 @@ static void vimc_deb_process_frame(struc vdeb->set_rgb_src (vdeb, i, j, rgb); } -/* Propagate the frame through all source pads */ -for (i =1 ; i < vdeb->sd.entity.num_pads; i++) { -struct media_pad *pad = &vdeb->sd.entity.pads[i]; +return vdeb->src_frame; -vimc_propagate_frame (pad, vdeb->src_frame); - } } static void vimc_deb_comp_unbind(struct device *comp, struct device *master,
drivers/media/platform/vimc/vimc-scaler.c +4 -24
@@ -216,7 +216,6 @@ static const struct v4l2_subdev_pad_opsstatic int vimc_sca_s_stream (struct v4l2_subdev *sd,int enable) {struct vimc_sca_device *vsca =v4l2_get_subdevdata (sd); -int ret;if (enable) {const struct vimc_pix_map *vpix;
@@ -244,22 +243,10 @@ static int vimc_sca_s_stream(struct v4l2if (!vsca->src_frame)return -ENOMEM ; -/* Turn the stream on in the subdevices directly connected */ - ret =vimc_pipeline_s_stream (&vsca->sd.entity,1 ); -if (ret) { -vfree (vsca->src_frame); - vsca->src_frame =NULL ; -return ret; - } }else {if (!vsca->src_frame)return 0 ; -/* Disable streaming from the pipe */ - ret =vimc_pipeline_s_stream (&vsca->sd.entity,0 ); -if (ret) -return ret; -vfree (vsca->src_frame); vsca->src_frame =NULL ; }
@@ -345,26 +332,19 @@ static void vimc_sca_fill_src_frame(consvimc_sca_scale_pix (vsca, i, j, sink_frame); } -static void vimc_sca_process_frame (struct vimc_ent_device *ved, -struct media_pad *sink, -const void *sink_frame) +static void *vimc_sca_process_frame (struct vimc_ent_device *ved, +const void *sink_frame) { struct vimc_sca_device *vsca = container_of(ved, struct vimc_sca_device, ved); -unsigned int i;/* If the stream in this node is not active, just return */ if (!vsca->src_frame) -return ; +return ERR_PTR (-EINVAL );vimc_sca_fill_src_frame (vsca, sink_frame); -/* Propagate the frame through all source pads */ -for (i =1 ; i < vsca->sd.entity.num_pads; i++) { -struct media_pad *pad = &vsca->sd.entity.pads[i]; - -vimc_propagate_frame (pad, vsca->src_frame); - } +return vsca->src_frame; }; static void vimc_sca_comp_unbind(struct device *comp, struct device *master,
drivers/media/platform/vimc/vimc-sensor.c +13 -43
91 lines not on this page · raw message
drivers/media/platform/vimc/vimc-streamer.c new file +188 -0
188 lines not on this page · raw message
drivers/media/platform/vimc/vimc-streamer.h new file +38 -0
@@ -0,0 +1,38 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* +* vimc-streamer.h Virtual Media Controller Driver +* +* Copyright (C) 2018 Lucas A. M. Magalhães <[email protected]> +* +*/ + +#ifndef _VIMC_STREAMER_H_ +#define _VIMC_STREAMER_H_ + +#include <media/media-device.h> + +#include "vimc-common.h" + +#define VIMC_STREAMER_PIPELINE_MAX_SIZE 16 + +struct vimc_stream { +struct media_pipeline pipe; +struct vimc_ent_device *ved_pipeline[VIMC_STREAMER_PIPELINE_MAX_SIZE ]; +unsigned int pipe_size; +u8 *frame; +struct task_struct *kthread; +}; + +/** +* vimc_streamer_s_streamer - start/stop the stream +* +* @stream: the pointer to the stream to start or stop +* @ved: The last entity of the streamer pipeline +* @enable: any non-zero number start the stream, zero stop +* +*/ +int vimc_streamer_s_stream (struct vimc_stream *stream, +struct vimc_ent_device *ved, +int enable); + +#endif //_VIMC_STREAMER_H_
Greg Kroah-Hartman
maintainerPATCH 174/183 media: imx: csi: Disable CSI immediately after last EOF
In reply to Greg Kroah-Hartman4.14-stable review patch. If anyone has any objections, please let me know.
------------------
From: Steve Longerbeam <[email protected]>
commit 2e0fe66e0a136252f4d89dbbccdcb26deb867eb8 upstream.
Disable the CSI immediately after receiving the last EOF before stream off (and thus before disabling the IDMA channel). Do this by moving the wait for EOF completion into a new function csi_idmac_wait_last_eof().
This fixes a complete system hard lockup on the SabreAuto when streaming from the ADV7180, by repeatedly sending a stream off immediately followed by stream on:
while true; do v4l2-ctl -d4 --stream-mmap --stream-count=3; done
Eventually this either causes the system lockup or EOF timeouts at all subsequent stream on, until a system reset.
The lockup occurs when disabling the IDMA channel at stream off. Disabling the CSI before disabling the IDMA channel appears to be a reliable fix for the hard lockup.
--- drivers/staging/media/imx/imx-media-csi.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-)
drivers/staging/media/imx/imx-media-csi.c +14 -3
@@ -538,7 +538,7 @@ out_put_ipu:return ret; } -static void csi_idmac_stop (struct csi_priv *priv) +static void csi_idmac_wait_last_eof (struct csi_priv *priv) {unsigned long flags;int ret;
@@ -555,7 +555,10 @@ static void csi_idmac_stop(struct csi_pr &priv->last_eof_comp, msecs_to_jiffies(IMX_MEDIA_EOF_TIMEOUT));if (ret ==0 )v4l2_warn (&priv->sd,"wait last EOF timeout\n" ); +} +static void csi_idmac_stop (struct csi_priv *priv) +{devm_free_irq (priv->dev, priv->eof_irq, priv);devm_free_irq (priv->dev, priv->nfb4eof_irq, priv);
@@ -681,6 +684,16 @@ idmac_stop:static void csi_stop (struct csi_priv *priv) { +if (priv->dest ==IPU_CSI_DEST_IDMAC ) +csi_idmac_wait_last_eof (priv); + +/* +* Disable the CSI asap, after syncing with the last EOF. +* Doing so after the IDMA channel is disabled has shown to +* create hard system-wide hangs. +*/ +ipu_csi_disable (priv->csi); +if (priv->dest ==IPU_CSI_DEST_IDMAC ) {csi_idmac_stop (priv);
@@ -688,8 +701,6 @@ static void csi_stop(struct csi_priv *prif (priv->fim)imx_media_fim_set_stream (priv->fim,NULL , false); } - -ipu_csi_disable (priv->csi); }static const struct csi_skip_desc csi_skip[12 ] = {
Greg Kroah-Hartman
maintainerPATCH 175/183 media: imx: csi: Stop upstream before disabling IDMA channel
In reply to Greg Kroah-Hartman4.14-stable review patch. If anyone has any objections, please let me know.
------------------
From: Steve Longerbeam <[email protected]>
commit 4bc1ab41eee9d02ad2483bf8f51a7b72e3504eba upstream.
Move upstream stream off to just after receiving the last EOF completion and disabling the CSI (and thus before disabling the IDMA channel) in csi_stop(). For symmetry also move upstream stream on to beginning of csi_start().
Doing this makes csi_s_stream() more symmetric with prp_s_stream() which will require the same change to fix a hard lockup.
--- drivers/staging/media/imx/imx-media-csi.c | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-)
drivers/staging/media/imx/imx-media-csi.c +13 -12
@@ -648,10 +648,16 @@ static int csi_start(struct csi_priv *prusleep_range (delay_usec, delay_usec +1000 ); } +/* start upstream */ + ret =v4l2_subdev_call (priv->src_sd, video, s_stream,1 ); + ret = (ret && ret != -ENOIOCTLCMD ) ? ret :0 ; +if (ret) +return ret; +if (priv->dest ==IPU_CSI_DEST_IDMAC ) { ret =csi_idmac_start (priv);if (ret) -return ret; + goto stop_upstream; } ret =csi_setup (priv);
@@ -679,6 +685,8 @@ fim_off: idmac_stop:if (priv->dest ==IPU_CSI_DEST_IDMAC )csi_idmac_stop (priv); +stop_upstream: +v4l2_subdev_call (priv->src_sd, video, s_stream,0 );return ret; }
@@ -694,6 +702,9 @@ static void csi_stop(struct csi_priv *pr*/ ipu_csi_disable (priv->csi); +/* stop upstream */ +v4l2_subdev_call (priv->src_sd, video, s_stream,0 ); +if (priv->dest ==IPU_CSI_DEST_IDMAC ) {csi_idmac_stop (priv);
@@ -861,23 +872,13 @@ static int csi_s_stream(struct v4l2_subd goto update_count;if (enable) { -/* upstream must be started first, before starting CSI */ - ret =v4l2_subdev_call (priv->src_sd, video, s_stream,1 ); - ret = (ret && ret != -ENOIOCTLCMD ) ? ret :0 ; -if (ret) - goto out; -dev_dbg (priv->dev,"stream ON\n" ); ret =csi_start (priv); -if (ret) { -v4l2_subdev_call (priv->src_sd, video, s_stream,0 ); +if (ret) goto out; - } }else {dev_dbg (priv->dev,"stream OFF\n" ); -/* CSI must be stopped first, then stop upstream */ csi_stop (priv); -v4l2_subdev_call (priv->src_sd, video, s_stream,0 ); } update_count:
Greg Kroah-Hartman
maintainerPATCH 176/183 drm/radeon/evergreen_cs: fix missing break in switch statement
In reply to Greg Kroah-Hartman4.14-stable review patch. If anyone has any objections, please let me know.
------------------
From: Gustavo A. R. Silva <[email protected]>
commit cc5034a5d293dd620484d1d836aa16c6764a1c8c upstream.
Add missing break statement in order to prevent the code from falling through to case CB_TARGET_MASK.
This bug was found thanks to the ongoing efforts to enable -Wimplicit-fallthrough.
--- drivers/gpu/drm/radeon/evergreen_cs.c | 1 + 1 file changed, 1 insertion(+)
drivers/gpu/drm/radeon/evergreen_cs.c +1 -0
@@ -1299,6 +1299,7 @@ static int evergreen_cs_handle_reg(strucreturn -EINVAL ; } ib[idx] += (u32)((reloc->gpu_offset >>8 ) &0xffffffff ); +break ;case CB_TARGET_MASK : track->cb_target_mask =radeon_get_ib_value (p, idx); track->cb_dirty = true;
Greg Kroah-Hartman
maintainerPATCH 177/183 KVM: Call kvm_arch_memslots_updated() before updating memslots
In reply to Greg Kroah-Hartman4.14-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sean Christopherson <[email protected]>
commit 152482580a1b0accb60676063a1ac57b2d12daf6 upstream.
kvm_arch_memslots_updated() is at this point in time an x86-specific hook for handling MMIO generation wraparound. x86 stashes 19 bits of the memslots generation number in its MMIO sptes in order to avoid full page fault walks for repeat faults on emulated MMIO addresses. Because only 19 bits are used, wrapping the MMIO generation number is possible, if unlikely. kvm_arch_memslots_updated() alerts x86 that the generation has changed so that it can invalidate all MMIO sptes in case the effective MMIO generation has wrapped so as to avoid using a stale spte, e.g. a (very) old spte that was created with generation==0.
Given that the purpose of kvm_arch_memslots_updated() is to prevent consuming stale entries, it needs to be called before the new generation is propagated to memslots. Invalidating the MMIO sptes after updating memslots means that there is a window where a vCPU could dereference the new memslots generation, e.g. 0, and incorrectly reuse an old MMIO spte that was created with (pre-wrap) generation==0.
--- arch/mips/include/asm/kvm_host.h | 2 +- arch/powerpc/include/asm/kvm_host.h | 2 +- arch/s390/include/asm/kvm_host.h | 2 +- arch/x86/include/asm/kvm_host.h | 2 +- arch/x86/kvm/mmu.c | 4 ++-- arch/x86/kvm/x86.c | 4 ++-- include/linux/kvm_host.h | 2 +- virt/kvm/arm/mmu.c | 2 +- virt/kvm/kvm_main.c | 7 +++++-- 9 files changed, 15 insertions(+), 12 deletions(-)
arch/mips/include/asm/kvm_host.h +1 -1
@@ -1132,7 +1132,7 @@ static inline void kvm_arch_hardware_unsstatic inline void kvm_arch_sync_events (struct kvm *kvm) {}static inline void kvm_arch_free_memslot (struct kvm *kvm,struct kvm_memory_slot *free,struct kvm_memory_slot *dont) {} -static inline void kvm_arch_memslots_updated (struct kvm *kvm,struct kvm_memslots *slots) {} +static inline void kvm_arch_memslots_updated (struct kvm *kvm,u64 gen) {}static inline void kvm_arch_sched_in (struct kvm_vcpu *vcpu,int cpu) {}static inline void kvm_arch_vcpu_blocking (struct kvm_vcpu *vcpu) {}static inline void kvm_arch_vcpu_unblocking (struct kvm_vcpu *vcpu) {}
arch/powerpc/include/asm/kvm_host.h +1 -1
@@ -809,7 +809,7 @@ struct kvm_vcpu_arch {static inline void kvm_arch_hardware_disable (void ) {}static inline void kvm_arch_hardware_unsetup (void ) {}static inline void kvm_arch_sync_events (struct kvm *kvm) {} -static inline void kvm_arch_memslots_updated (struct kvm *kvm,struct kvm_memslots *slots) {} +static inline void kvm_arch_memslots_updated (struct kvm *kvm,u64 gen) {}static inline void kvm_arch_flush_shadow_all (struct kvm *kvm) {}static inline void kvm_arch_sched_in (struct kvm_vcpu *vcpu,int cpu) {}static inline void kvm_arch_exit (void ) {}
arch/s390/include/asm/kvm_host.h +1 -1
@@ -784,7 +784,7 @@ static inline void kvm_arch_vcpu_uninit(static inline void kvm_arch_sched_in (struct kvm_vcpu *vcpu,int cpu) {}static inline void kvm_arch_free_memslot (struct kvm *kvm,struct kvm_memory_slot *free,struct kvm_memory_slot *dont) {} -static inline void kvm_arch_memslots_updated (struct kvm *kvm,struct kvm_memslots *slots) {} +static inline void kvm_arch_memslots_updated (struct kvm *kvm,u64 gen) {}static inline void kvm_arch_flush_shadow_all (struct kvm *kvm) {}static inline void kvm_arch_flush_shadow_memslot (struct kvm *kvm,struct kvm_memory_slot *slot) {}
arch/x86/include/asm/kvm_host.h +1 -1
@@ -1121,7 +1121,7 @@ void kvm_mmu_clear_dirty_pt_masked(strucstruct kvm_memory_slot *slot, gfn_t gfn_offset, unsigned long mask);void kvm_mmu_zap_all (struct kvm *kvm); -void kvm_mmu_invalidate_mmio_sptes (struct kvm *kvm,struct kvm_memslots *slots); +void kvm_mmu_invalidate_mmio_sptes (struct kvm *kvm,u64 gen);unsigned int kvm_mmu_calculate_mmu_pages (struct kvm *kvm);void kvm_mmu_change_mmu_pages (struct kvm *kvm,unsigned int kvm_nr_mmu_pages);
arch/x86/kvm/mmu.c +2 -2
@@ -5418,13 +5418,13 @@ static bool kvm_has_zapped_obsolete_pagereturn unlikely (!list_empty_careful (&kvm->arch.zapped_obsolete_pages)); } -void kvm_mmu_invalidate_mmio_sptes (struct kvm *kvm,struct kvm_memslots *slots) +void kvm_mmu_invalidate_mmio_sptes (struct kvm *kvm,u64 gen) {/* * The very rare case: if the generation-number is round, * zap all shadow pages. */ -if (unlikely ((slots->generation &MMIO_GEN_MASK ) ==0 )) { +if (unlikely ((gen &MMIO_GEN_MASK ) ==0 )) {kvm_debug_ratelimited ("kvm: zapping shadow pages for mmio generation wraparound\n" );kvm_mmu_invalidate_zap_all_pages (kvm); }
arch/x86/kvm/x86.c +2 -2
@@ -8524,13 +8524,13 @@ out_free:return -ENOMEM ; } -void kvm_arch_memslots_updated (struct kvm *kvm,struct kvm_memslots *slots) +void kvm_arch_memslots_updated (struct kvm *kvm,u64 gen) {/* * memslots->generation has been incremented. * mmio generation may have reached its maximum value. */ -kvm_mmu_invalidate_mmio_sptes (kvm, slots); +kvm_mmu_invalidate_mmio_sptes (kvm, gen); } int kvm_arch_prepare_memory_region(struct kvm *kvm,
include/linux/kvm_host.h +1 -1
@@ -625,7 +625,7 @@ void kvm_arch_free_memslot(struct kvm *k struct kvm_memory_slot *dont);int kvm_arch_create_memslot (struct kvm *kvm,struct kvm_memory_slot *slot,unsigned long npages); -void kvm_arch_memslots_updated (struct kvm *kvm,struct kvm_memslots *slots); +void kvm_arch_memslots_updated (struct kvm *kvm,u64 gen); int kvm_arch_prepare_memory_region(struct kvm *kvm, struct kvm_memory_slot *memslot, const struct kvm_userspace_memory_region *mem,
virt/kvm/arm/mmu.c +1 -1
@@ -1955,7 +1955,7 @@ int kvm_arch_create_memslot(struct kvm *return 0 ; } -void kvm_arch_memslots_updated (struct kvm *kvm,struct kvm_memslots *slots) +void kvm_arch_memslots_updated (struct kvm *kvm,u64 gen) { }
virt/kvm/kvm_main.c +5 -2
@@ -856,6 +856,7 @@ static struct kvm_memslots *install_new_ int as_id, struct kvm_memslots *slots) { struct kvm_memslots *old_memslots = __kvm_memslots(kvm, as_id); +u64 gen;/* * Set the low bit in the generation, which disables SPTE caching
@@ -878,9 +879,11 @@ static struct kvm_memslots *install_new_* space 0 will use generations 0, 4, 8, ... while * address space 1 will * use generations 2, 6, 10, 14, ... */ - slots->generation +=KVM_ADDRESS_SPACE_NUM *2 -1 ; + gen = slots->generation +KVM_ADDRESS_SPACE_NUM *2 -1 ; -kvm_arch_memslots_updated (kvm, slots); +kvm_arch_memslots_updated (kvm, gen); + + slots->generation = gen;return old_memslots; }
Greg Kroah-Hartman
maintainerPATCH 178/183 KVM: x86/mmu: Detect MMIO generation wrap in any address space
In reply to Greg Kroah-Hartman4.14-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sean Christopherson <[email protected]>
commit e1359e2beb8b0a1188abc997273acbaedc8ee791 upstream.
The check to detect a wrap of the MMIO generation explicitly looks for a generation number of zero. Now that unique memslots generation numbers are assigned to each address space, only address space 0 will get a generation number of exactly zero when wrapping. E.g. when address space 1 goes from 0x7fffe to 0x80002, the MMIO generation number will wrap to 0x2. Adjust the MMIO generation to strip the address space modifier prior to checking for a wrap.
--- arch/x86/kvm/mmu.c | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-)
arch/x86/kvm/mmu.c +19 -2
@@ -5420,11 +5420,28 @@ static bool kvm_has_zapped_obsolete_pagevoid kvm_mmu_invalidate_mmio_sptes (struct kvm *kvm,u64 gen) { + gen &=MMIO_GEN_MASK ; + +/* +* Shift to eliminate the "update in-progress" flag, which isn't +* included in the spte's generation number. +*/ + gen >>=1 ; + +/* +* Generation numbers are incremented in multiples of the number of +* address spaces in order to provide unique generations across all +* address spaces. Strip what is effectively the address space +* modifier prior to checking for a wrap of the MMIO generation so +* that a wrap in any address space is detected. +*/ + gen &= ~((u64 )KVM_ADDRESS_SPACE_NUM -1 ); +/* -* The very rare case: if the generation-number is round, +* The very rare case: if the MMIO generation number has wrapped, * zap all shadow pages. */ -if (unlikely ((gen &MMIO_GEN_MASK ) ==0 )) { +if (unlikely (gen ==0 )) {kvm_debug_ratelimited ("kvm: zapping shadow pages for mmio generation wraparound\n" );kvm_mmu_invalidate_zap_all_pages (kvm); }
Greg Kroah-Hartman
maintainerPATCH 179/183 KVM: x86/mmu: Do not cache MMIO accesses while memslots are in flux
In reply to Greg Kroah-Hartman4.14-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sean Christopherson <[email protected]>
commit ddfd1730fd829743e41213e32ccc8b4aa6dc8325 upstream.
When installing new memslots, KVM sets bit 0 of the generation number to indicate that an update is in-progress. Until the update is complete, there are no guarantees as to whether a vCPU will see the old or the new memslots. Explicity prevent caching MMIO accesses so as to avoid using an access cached from the old memslots after the new memslots have been installed.
Note that it is unclear whether or not disabling caching during the update window is strictly necessary as there is no definitive documentation as to what ordering guarantees KVM provides with respect to updating memslots. That being said, the MMIO spte code does not allow reusing sptes created while an update is in-progress, and the associated documentation explicitly states:
We do not want to use an MMIO sptes created with an odd generation number, ... If KVM is unlucky and creates an MMIO spte while the low bit is 1, the next access to the spte will always be a cache miss.
At the very least, disabling the per-vCPU MMIO cache during updates will make its behavior consistent with the MMIO spte behavior and documentation.
--- arch/x86/kvm/x86.h | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-)
arch/x86/kvm/x86.h +6 -1
@@ -136,6 +136,11 @@ static inline bool emul_is_noncanonical_static inline void vcpu_cache_mmio_info (struct kvm_vcpu *vcpu,gva_t gva,gfn_t gfn,unsigned access) { +u64 gen =kvm_memslots (vcpu->kvm)->generation; + +if (unlikely (gen &1 )) +return ; +/* * If this is a shadow nested page table, the "GVA" is * actually a nGPA.
@@ -143,7 +148,7 @@ static inline void vcpu_cache_mmio_info( vcpu->arch.mmio_gva =mmu_is_nested (vcpu) ?0 : gva &PAGE_MASK ; vcpu->arch.access = access; vcpu->arch.mmio_gfn = gfn; - vcpu->arch.mmio_gen =kvm_memslots (vcpu->kvm)->generation; + vcpu->arch.mmio_gen = gen; }static inline bool vcpu_match_mmio_gen (struct kvm_vcpu *vcpu)
Greg Kroah-Hartman
maintainerPATCH 180/183 KVM: nVMX: Sign extend displacements of VMX instrs mem operands
In reply to Greg Kroah-Hartman4.14-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sean Christopherson <[email protected]>
commit 946c522b603f281195af1df91837a1d4d1eb3bc9 upstream.
The VMCS.EXIT_QUALIFCATION field reports the displacements of memory operands for various instructions, including VMX instructions, as a naturally sized unsigned value, but masks the value by the addr size, e.g. given a ModRM encoded as -0x28(%ebp), the -0x28 displacement is reported as 0xffffffd8 for a 32-bit address size. Despite some weird wording regarding sign extension, the SDM explicitly states that bits beyond the instructions address size are undefined:
In all cases, bits of this field beyond the instruction’s address size are undefined.
Failure to sign extend the displacement results in KVM incorrectly treating a negative displacement as a large positive displacement when the address size of the VMX instruction is smaller than KVM's native size, e.g. a 32-bit address size on a 64-bit KVM.
The very original decoding, added by commit 064aea774768 ("KVM: nVMX:
Decoding memory operands of VMX instructions"), sort of modeled sign extension by truncating the final virtual/linear address for a 32-bit address size. I.e. it messed up the effective address but made it work by adjusting the final address.
When segmentation checks were added, the truncation logic was kept as-is and no sign extension logic was introduced. In other words, it kept calculating the wrong effective address while mostly generating the correct virtual/linear address. As the effective address is what's used in the segment limit checks, this results in KVM incorreclty injecting #GP/#SS faults due to non-existent segment violations when a nested VMM uses negative displacements with an address size smaller than KVM's native address size.
Using the -0x28(%ebp) example, an EBP value of 0x1000 will result in KVM using 0x100000fd8 as the effective address when checking for a segment limit violation. This causes a 100% failure rate when running a 32-bit KVM build as L1 on top of a 64-bit KVM L0.
--- arch/x86/kvm/vmx.c | 4 ++++ 1 file changed, 4 insertions(+)
arch/x86/kvm/vmx.c +4 -0
@@ -7446,6 +7446,10 @@ static int get_vmx_mem_address(struct kv/* Addr = segment_base + offset */ /* offset = base + [index * scale] + displacement */ off = exit_qualification;/* holds the displacement */ +if (addr_size ==1 ) + off = (gva_t )sign_extend64 (off,31 ); +else if (addr_size ==0 ) + off = (gva_t )sign_extend64 (off,15 );if (base_is_valid) off +=kvm_register_read (vcpu, base_reg);if (index_is_valid)
Greg Kroah-Hartman
maintainerPATCH 181/183 KVM: nVMX: Apply addr size mask to effective address for VMX instructions
In reply to Greg Kroah-Hartman4.14-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sean Christopherson <[email protected]>
commit 8570f9e881e3fde98801bb3a47eef84dd934d405 upstream.
The address size of an instruction affects the effective address, not the virtual/linear address. The final address may still be truncated, e.g. to 32-bits outside of long mode, but that happens irrespective of the address size, e.g. a 32-bit address size can yield a 64-bit virtual address when using FS/GS with a non-zero base.
--- arch/x86/kvm/vmx.c | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-)
arch/x86/kvm/vmx.c +23 -2
@@ -7455,20 +7455,41 @@ static int get_vmx_mem_address(struct kvif (index_is_valid) off +=kvm_register_read (vcpu, index_reg)<<scaling;vmx_get_segment (vcpu, &s, seg_reg); - *ret = s.base + off; +/* +* The effective address, i.e. @off, of a memory operand is truncated +* based on the address size of the instruction. Note that this is +* the *effective address*, i.e. the address prior to accounting for +* the segment's base. +*/ if (addr_size ==1 )/* 32 bit */ - *ret &=0xffffffff ; + off &=0xffffffff ; +else if (addr_size ==0 )/* 16 bit */ + off &=0xffff ;/* Checks for #GP/#SS exceptions. */ exn = false;if (is_long_mode (vcpu)) { +/* +* The virtual/linear address is never truncated in 64-bit +* mode, e.g. a 32-bit address size can yield a 64-bit virtual +* address when using FS/GS with a non-zero base. +*/ + *ret = s.base + off; +/* Long mode: #GP(0)/#SS(0) if the memory address is in a * non-canonical form. This is the only check on the memory * destination for long mode! */ exn =is_noncanonical_address (*ret, vcpu); }else if (is_protmode (vcpu)) { +/* +* When not in long mode, the virtual/linear address is +* unconditionally truncated to 32 bits regardless of the +* address size. +*/ + *ret = (s.base + off) &0xffffffff ; +/* Protected mode: apply checks for segment validity in the * following order: * - segment type check (#GP(0) may be thrown)
Greg Kroah-Hartman
maintainerPATCH 182/183 KVM: nVMX: Ignore limit checks on VMX instructions using flat segments
In reply to Greg Kroah-Hartman4.14-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sean Christopherson <[email protected]>
commit 34333cc6c2cb021662fd32e24e618d1b86de95bf upstream.
Regarding segments with a limit==0xffffffff, the SDM officially states:
When the effective limit is FFFFFFFFH (4 GBytes), these accesses may or may not cause the indicated exceptions. Behavior is implementation-specific and may vary from one execution to another.
In practice, all CPUs that support VMX ignore limit checks for "flat segments", i.e. an expand-up data or code segment with base=0 and limit=0xffffffff. This is subtly different than wrapping the effective address calculation based on the address size, as the flat segment behavior also applies to accesses that would wrap the 4g boundary, e.g. a 4-byte access starting at 0xffffffff will access linear addresses 0xffffffff, 0x0, 0x1 and 0x2.
--- arch/x86/kvm/vmx.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-)
arch/x86/kvm/vmx.c +9 -3
@@ -7513,10 +7513,16 @@ static int get_vmx_mem_address(struct kv/* Protected mode: #GP(0)/#SS(0) if the segment is unusable. */ exn = (s.unusable !=0 ); -/* Protected mode: #GP(0)/#SS(0) if the memory -* operand is outside the segment limit. + +/* +* Protected mode: #GP(0)/#SS(0) if the memory operand is +* outside the segment limit. All CPUs that support VMX ignore +* limit checks for flat segments, i.e. segments with base==0, +* limit==0xffffffff and of type expand-up data or code. */ - exn = exn || (off +sizeof (u64) > s.limit); +if (!(s.base ==0 && s.limit ==0xffffffff && + ((s.type &8 ) || !(s.type &4 )))) + exn = exn || (off +sizeof (u64) > s.limit); }if (exn) { kvm_queue_exception_e(vcpu,
Greg Kroah-Hartman
maintainerPATCH 183/183 s390/setup: fix boot crash for machine without EDAT-1
In reply to Greg Kroah-Hartman4.14-stable review patch. If anyone has any objections, please let me know.
------------------
From: Martin Schwidefsky <[email protected]>
commit 86a86804e4f18fc3880541b3d5a07f4df0fe29cb upstream.
The fix to make WARN work in the early boot code created a problem on older machines without EDAT-1. The setup_lowcore_dat_on function uses the pointer from lowcore_ptr[0] to set the DAT bit in the new PSWs. That does not work if the kernel page table is set up with 4K pages as the prefix address maps to absolute zero.
To make this work the PSWs need to be changed with via address 0 in form of the S390_lowcore definition.
--- arch/s390/kernel/setup.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-)
arch/s390/kernel/setup.c +6 -7
@@ -390,13 +390,12 @@ static void __init setup_lowcore_dat_offstatic void __init setup_lowcore_dat_on (void ) { -struct lowcore *lc; - - lc = lowcore_ptr[0 ]; - lc->external_new_psw.mask |=PSW_MASK_DAT ; - lc->svc_new_psw.mask |=PSW_MASK_DAT ; - lc->program_new_psw.mask |=PSW_MASK_DAT ; - lc->io_new_psw.mask |=PSW_MASK_DAT ; +__ctl_clear_bit (0 ,28 ); + S390_lowcore.external_new_psw.mask |=PSW_MASK_DAT ; + S390_lowcore.svc_new_psw.mask |=PSW_MASK_DAT ; + S390_lowcore.program_new_psw.mask |=PSW_MASK_DAT ; + S390_lowcore.io_new_psw.mask |=PSW_MASK_DAT ; +__ctl_set_bit (0 ,28 ); }static struct resource code_resource = {
stable-rc/linux-4.14.y boot: 52 boots: 0 failed, 51 passed with 1 untried/unknown (v4.14.107-184-gf85b59a43475)
stable-rc/linux-4.14.y boot: 52 boots: 0 failed, 51 passed with 1 untried/unknown (v4.14.107-184-gf85b59a43475)
Full Boot Summary: https://kernelci.org/boot/all/job/stable-rc/branch/linux-4.14.y/kernel/v4.14.107-184-gf85b59a43475/
Full Build Summary: https://kernelci.org/build/stable-rc/branch/linux-4.14.y/kernel/v4.14.107-184-gf85b59a43475/
Tree: stable-rc
Branch: linux-4.14.y
Git Describe: v4.14.107-184-gf85b59a43475
Git Commit: f85b59a43475b5bcca299c897549d4aff496dda2
Git URL: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git
Tested: 29 unique boards, 15 SoC families, 9 builds out of 201
---
For more info write to <[email protected]>
Quoted 8 lines · Greg Kroah-Hartman
This is the start of the stable review cycle for the 4.14.108 release. There are 183 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Responses should be made by Sun Mar 24 11:11:06 UTC 2019. Anything received after that time might be too late.
Build results:
total: 172 pass: 172 fail: 0 Qemu test results: total: 329 pass: 329 fail: 0
Guenter
Quoted 10 lines · Greg Kroah-Hartman
This is the start of the stable review cycle for the 4.14.108 release. There are 183 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Responses should be made by Sun Mar 24 11:11:06 UTC 2019. Anything received after that time might be too late.
The whole patch series can be found in one patch at:
Quoted 8 lines
https://www.kernel.org/pub/linux/kernel/v4.x/stable-review/patch-4.14.108-rc1.gzor in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.gitlinux-4.14.y
and the diffstat can be found below.thanks,
greg k-h
Results from Linaro’s test farm.
No regressions on arm64, arm, x86_64, and i386.
Summary
------------------------------------------------------------------------
kernel: 4.14.108-rc1
git repo: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git
git branch: linux-4.14.y
git commit: f85b59a43475b5bcca299c897549d4aff496dda2
git describe: v4.14.107-184-gf85b59a43475
Test details: https://qa-reports.linaro.org/lkft/linux-stable-rc-4.14-oe/build/v4.14.107-184-gf85b59a43475
No regressions (compared to build v4.14.107)
No fixes (compared to build v4.14.107)
Ran 22886 total tests in the following environments and test suites.
Environments
--------------
- dragonboard-410c - arm64
- hi6220-hikey - arm64
- i386
- juno-r2 - arm64
- qemu_arm
- qemu_arm64
- qemu_i386
- qemu_x86_64
- x15 - arm
- x86_64
Test Suites
-----------
* boot
* install-android-platform-tools-r2600
* kselftest
* libhugetlbfs
* ltp-cap_bounds-tests
* ltp-commands-tests
* ltp-containers-tests
* ltp-cpuhotplug-tests
* ltp-cve-tests
* ltp-dio-tests
* ltp-fcntl-locktests-tests
* ltp-filecaps-tests
* ltp-fs-tests
* ltp-fs_bind-tests
* ltp-fs_perms_simple-tests
* ltp-fsx-tests
* ltp-hugetlb-tests
* ltp-io-tests
* ltp-ipc-tests
* ltp-math-tests
* ltp-mm-tests
* ltp-nptl-tests
* ltp-pty-tests
* ltp-sched-tests
* ltp-securebits-tests
* ltp-syscalls-tests
* ltp-timers-tests
* spectre-meltdown-checker-test
* ltp-open-posix-tests
* kselftest-vsyscall-mode-native
* kselftest-vsyscall-mode-none
Signature · 2 lines
Linaro LKFT https://lkft.linaro.org
Jon Hunter
maintainerQuoted 9 lines · Greg Kroah-Hartman
This is the start of the stable review cycle for the 4.14.108 release. There are 183 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Responses should be made by Sun Mar 24 11:11:06 UTC 2019. Anything received after that time might be too late.
The whole patch series can be found in one patch at:
Quoted 8 lines
https://www.kernel.org/pub/linux/kernel/v4.x/stable-review/patch-4.14.108-rc1.gzor in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.gitlinux-4.14.y
and the diffstat can be found below.thanks,
greg k-h
All tests are passing for Tegra ...
Test results for stable-v4.14:
8 builds: 8 pass, 0 fail
16 boots: 16 pass, 0 fail
20 tests: 20 pass, 0 failLinux version: 4.14.108-gdee55b0
Boards tested: tegra124-jetson-tk1, tegra20-ventana,
tegra210-p2371-2180, tegra30-cardhu-a04
Cheers
Jon
Signature · 1 line
nvpublic