Reset debug registers MDCR-EL3/SDCR and MDCR_EL2/HDCR

In order to avoid unexpected traps into EL3/MON mode, this patch
resets the debug registers, MDCR_EL3 and MDCR_EL2 for AArch64,
and SDCR and HDCR for AArch32.

MDCR_EL3/SDCR is zero'ed when EL3/MON mode is entered, at the
start of BL1 and BL31/SMP_MIN.

For MDCR_EL2/HDCR, this patch zero's the bits that are
architecturally UNKNOWN values on reset. This is done when
exiting from EL3/MON mode but only on platforms that support
EL2/HYP mode but choose to exit to EL1/SVC mode.

Fixes ARM-software/tf-issues#430

Change-Id: Idb992232163c072faa08892251b5626ae4c3a5b6
Signed-off-by: David Cunado <david.cunado@arm.com>
diff --git a/lib/el3_runtime/aarch32/context_mgmt.c b/lib/el3_runtime/aarch32/context_mgmt.c
index 02ae2a7..29532e8 100644
--- a/lib/el3_runtime/aarch32/context_mgmt.c
+++ b/lib/el3_runtime/aarch32/context_mgmt.c
@@ -200,7 +200,10 @@
 			isb();
 		} else if (read_id_pfr1() &
 			(ID_PFR1_VIRTEXT_MASK << ID_PFR1_VIRTEXT_SHIFT)) {
-			/* Set the NS bit to access HCR, HCPTR, CNTHCTL, VPIDR, VMPIDR */
+			/*
+			 * Set the NS bit to access NS copies of certain banked
+			 * registers
+			 */
 			write_scr(read_scr() | SCR_NS_BIT);
 			isb();
 
@@ -231,6 +234,15 @@
 			 * translation are disabled.
 			 */
 			write64_vttbr(0);
+
+			/*
+			 * Avoid unexpected debug traps in case where HDCR
+			 * is not completely reset by the hardware - set
+			 * HDCR.HPMN to PMCR.N and zero the remaining bits.
+			 * The HDCR.HPMN and PMCR.N fields are the same size
+			 * (5 bits) and HPMN is at offset zero within HDCR.
+			 */
+			write_hdcr((read_pmcr() & PMCR_N_BITS) >> PMCR_N_SHIFT);
 			isb();
 
 			write_scr(read_scr() & ~SCR_NS_BIT);
diff --git a/lib/el3_runtime/aarch64/context_mgmt.c b/lib/el3_runtime/aarch64/context_mgmt.c
index 4b5d0ee..fadc1db 100644
--- a/lib/el3_runtime/aarch64/context_mgmt.c
+++ b/lib/el3_runtime/aarch64/context_mgmt.c
@@ -259,6 +259,16 @@
 			 * translation are disabled.
 			 */
 			write_vttbr_el2(0);
+			/*
+			 * Avoid unexpected debug traps in case where MDCR_EL2
+			 * is not completely reset by the hardware - set
+			 * MDCR_EL2.HPMN to PMCR_EL0.N and zero the remaining
+			 * bits.
+			 * MDCR_EL2.HPMN and PMCR_EL0.N fields are the same size
+			 * (5 bits) and HPMN is at offset zero within MDCR_EL2.
+			 */
+			write_mdcr_el2((read_pmcr_el0() & PMCR_EL0_N_BITS)
+					>> PMCR_EL0_N_SHIFT);
 		}
 	}