config KERNEL_PL
        int "Processor protection level for kernel"
        range 1 2
-       default "1"
+       default 2 if TILEGX
+       default 1 if !TILEGX
        ---help---
-         This setting determines the processor protection level the
-         kernel will be built to run at.  Generally you should use
-         the default value here.
+         Since MDE 4.2, the Tilera hypervisor runs the kernel
+         at PL2 by default.  If running under an older hypervisor,
+         or as a KVM guest, you must run at PL1.  (The current
+         hypervisor may also be recompiled with "make HV_PL=2" to
+         allow it to run a kernel at PL1, but clients running at PL1
+         are not expected to be supported indefinitely.)
+
+         If you're not sure, don't change the default.
 
 source "arch/tile/gxio/Kconfig"
 
 
 #define HV_DISPATCH_ENTRY_SIZE 32
 
 /** Version of the hypervisor interface defined by this file */
-#define _HV_VERSION 11
+#define _HV_VERSION 13
+
+/** Last version of the hypervisor interface with old hv_init() ABI.
+ *
+ * The change from version 12 to version 13 corresponds to launching
+ * the client by default at PL2 instead of PL1 (corresponding to the
+ * hv itself running at PL3 instead of PL2).  To make this explicit,
+ * the hv_init() API was also extended so the client can report its
+ * desired PL, resulting in a more helpful failure diagnostic.  If you
+ * call hv_init() with _HV_VERSION_OLD_HV_INIT and omit the client_pl
+ * argument, the hypervisor will assume client_pl = 1.
+ *
+ * Note that this is a deprecated solution and we do not expect to
+ * support clients of the Tilera hypervisor running at PL1 indefinitely.
+ */
+#define _HV_VERSION_OLD_HV_INIT 12
 
 /* Index into hypervisor interface dispatch code blocks.
  *
 #ifndef __ASSEMBLER__
 
 /** Pass HV_VERSION to hv_init to request this version of the interface. */
-typedef enum { HV_VERSION = _HV_VERSION } HV_VersionNumber;
+typedef enum {
+  HV_VERSION = _HV_VERSION,
+  HV_VERSION_OLD_HV_INIT = _HV_VERSION_OLD_HV_INIT,
+
+} HV_VersionNumber;
 
 /** Initializes the hypervisor.
  *
  * that this program expects, typically HV_VERSION.
  * @param chip_num Architecture number of the chip the client was built for.
  * @param chip_rev_num Revision number of the chip the client was built for.
+ * @param client_pl Privilege level the client is built for
+ *   (not required if interface_version_number == HV_VERSION_OLD_HV_INIT).
  */
 void hv_init(HV_VersionNumber interface_version_number,
-             int chip_num, int chip_rev_num);
+             int chip_num, int chip_rev_num, int client_pl);
 
 
 /** Queries we can make for hv_sysconf().
 
 ENTRY(_start)
        /* Notify the hypervisor of what version of the API we want */
        {
+#if KERNEL_PL == 1 && _HV_VERSION == 13
+         /* Support older hypervisors by asking for API version 12. */
+         movei r0, _HV_VERSION_OLD_HV_INIT
+#else
+         movei r0, _HV_VERSION
+#endif
          movei r1, TILE_CHIP
-         movei r2, TILE_CHIP_REV
        }
        {
-         moveli r0, _HV_VERSION
-         jal hv_init
+         movei r2, TILE_CHIP_REV
+         movei r3, KERNEL_PL
        }
+       jal hv_init
        /* Get a reasonable default ASID in r0 */
        {
          move r0, zero