Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 26 Aug 2015 12:32:46 +0000 (UTC)
From:      Zbigniew Bodek <zbb@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r287164 - head/sys/arm64/arm64
Message-ID:  <201508261232.t7QCWkFL042333@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: zbb
Date: Wed Aug 26 12:32:46 2015
New Revision: 287164
URL: https://svnweb.freebsd.org/changeset/base/287164

Log:
  Fix race condition in its_cmd_send()
  
  its_cmd_send() can be called by multiple CPUs simultaneously.
  After the command is pushed to ITS command ring the completion
  status is polled using global pointer to the next free ring slot.
  Use copied pointer and provide correct locking to avoid spurious
  pointer value when concurrent access occurs.
  
  Obtained from: Semihalf
  Sponsored by:  The FreeBSD Foundation
  Differential Revision: https://reviews.freebsd.org/D3436

Modified:
  head/sys/arm64/arm64/gic_v3_its.c

Modified: head/sys/arm64/arm64/gic_v3_its.c
==============================================================================
--- head/sys/arm64/arm64/gic_v3_its.c	Wed Aug 26 11:54:40 2015	(r287163)
+++ head/sys/arm64/arm64/gic_v3_its.c	Wed Aug 26 12:32:46 2015	(r287164)
@@ -1311,16 +1311,16 @@ its_cmd_wait_completion(struct gic_v3_it
 static int
 its_cmd_send(struct gic_v3_its_softc *sc, struct its_cmd_desc *desc)
 {
-	struct its_cmd *cmd, *cmd_sync;
+	struct its_cmd *cmd, *cmd_sync, *cmd_write;
 	struct its_col col_sync;
 	struct its_cmd_desc desc_sync;
 	uint64_t target, cwriter;
 
 	mtx_lock_spin(&sc->its_spin_mtx);
 	cmd = its_cmd_alloc_locked(sc);
-	mtx_unlock_spin(&sc->its_spin_mtx);
 	if (cmd == NULL) {
 		device_printf(sc->dev, "could not allocate ITS command\n");
+		mtx_unlock_spin(&sc->its_spin_mtx);
 		return (EBUSY);
 	}
 
@@ -1328,9 +1328,7 @@ its_cmd_send(struct gic_v3_its_softc *sc
 	its_cmd_sync(sc, cmd);
 
 	if (target != ITS_TARGET_NONE) {
-		mtx_lock_spin(&sc->its_spin_mtx);
 		cmd_sync = its_cmd_alloc_locked(sc);
-		mtx_unlock_spin(&sc->its_spin_mtx);
 		if (cmd_sync == NULL)
 			goto end;
 		desc_sync.cmd_type = ITS_CMD_SYNC;
@@ -1341,12 +1339,12 @@ its_cmd_send(struct gic_v3_its_softc *sc
 	}
 end:
 	/* Update GITS_CWRITER */
-	mtx_lock_spin(&sc->its_spin_mtx);
 	cwriter = its_cmd_cwriter_offset(sc, sc->its_cmdq_write);
 	gic_its_write(sc, 8, GITS_CWRITER, cwriter);
+	cmd_write = sc->its_cmdq_write;
 	mtx_unlock_spin(&sc->its_spin_mtx);
 
-	its_cmd_wait_completion(sc, cmd, sc->its_cmdq_write);
+	its_cmd_wait_completion(sc, cmd, cmd_write);
 
 	return (0);
 }



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201508261232.t7QCWkFL042333>