svn commit: r364534 - in head/sys: amd64/acpica amd64/amd64 x86/acpica

Konstantin Belousov kib at FreeBSD.org
Sun Aug 23 20:43:24 UTC 2020


Author: kib
Date: Sun Aug 23 20:43:23 2020
New Revision: 364534
URL: https://svnweb.freebsd.org/changeset/base/364534

Log:
  amd64: Handle 5-level paging on wakeup.
  
  We can switch into long mode directly with LA57 enabled.
  
  Sponsored by:	The FreeBSD Foundation
  Differential revision:	https://reviews.freebsd.org/D25273

Modified:
  head/sys/amd64/acpica/acpi_wakecode.S
  head/sys/amd64/amd64/cpu_switch.S
  head/sys/x86/acpica/acpi_wakeup.c

Modified: head/sys/amd64/acpica/acpi_wakecode.S
==============================================================================
--- head/sys/amd64/acpica/acpi_wakecode.S	Sun Aug 23 20:40:35 2020	(r364533)
+++ head/sys/amd64/acpica/acpi_wakecode.S	Sun Aug 23 20:43:23 2020	(r364534)
@@ -148,10 +148,18 @@ wakeup_32:
 	mov	$bootdata32 - bootgdt, %eax
 	mov	%ax, %ds
 
-	/* Turn on the PAE bit for when paging is enabled */
+	/*
+	 * Turn on the PAE bit and optionally the LA57 bit for when paging
+	 * is later enabled.
+	 */
 	mov	%cr4, %eax
 	orl	$CR4_PAE, %eax
-	mov	%eax, %cr4
+	leal	wakeup_pagetables - wakeup_start(%ebx), %ecx
+	movl	(%ecx), %ecx
+	testl	$0x1, %ecx
+	je	1f
+	orl	$CR4_LA57, %eax
+1:	mov	%eax, %cr4
 
 	/*
 	 * Enable EFER.LME so that we get long mode when all the prereqs are
@@ -174,6 +182,7 @@ wakeup_32:
 	 */
 	leal	wakeup_pagetables - wakeup_start(%ebx), %eax
 	movl	(%eax), %eax
+	andl	$~0x1, %eax
 	mov	%eax, %cr3
 
 	/*

Modified: head/sys/amd64/amd64/cpu_switch.S
==============================================================================
--- head/sys/amd64/amd64/cpu_switch.S	Sun Aug 23 20:40:35 2020	(r364533)
+++ head/sys/amd64/amd64/cpu_switch.S	Sun Aug 23 20:43:23 2020	(r364534)
@@ -382,8 +382,11 @@ END(savectx)
  * Resuming processor state from pcb.
  */     
 ENTRY(resumectx)
-	/* Switch to KPML4phys. */
+	/* Switch to KPML5/4phys. */
 	movq	KPML4phys,%rax
+	movq	KPML5phys,%rcx
+	cmpl	$0, la57
+	cmovne	%rcx, %rax
 	movq	%rax,%cr3
 
 	/* Force kernel segment registers. */

Modified: head/sys/x86/acpica/acpi_wakeup.c
==============================================================================
--- head/sys/x86/acpica/acpi_wakeup.c	Sun Aug 23 20:40:35 2020	(r364533)
+++ head/sys/x86/acpica/acpi_wakeup.c	Sun Aug 23 20:43:23 2020	(r364534)
@@ -99,7 +99,7 @@ static void		acpi_wakeup_cpus(struct acpi_softc *);
 #endif
 
 #ifdef __amd64__
-#define	ACPI_WAKEPAGES	4
+#define	ACPI_WAKEPAGES	5
 #else
 #define	ACPI_WAKEPAGES	1
 #endif
@@ -414,8 +414,8 @@ acpi_install_wakeup_handler(struct acpi_softc *sc)
 	static void	*wakeaddr;
 	void		*wakepages[ACPI_WAKEPAGES];
 #ifdef __amd64__
-	uint64_t	*pt4, *pt3, *pt2;
-	vm_paddr_t	pt4pa, pt3pa, pt2pa;
+	uint64_t	*pt5, *pt4, *pt3, *pt2;
+	vm_paddr_t	pt5pa, pt4pa, pt3pa, pt2pa;
 	int		i;
 #endif
 
@@ -430,6 +430,10 @@ acpi_install_wakeup_handler(struct acpi_softc *sc)
 	sc->acpi_wakephys = vtophys(wakeaddr);
 
 #ifdef __amd64__
+	if (la57) {
+		pt5 = wakepages[4];
+		pt5pa = vtophys(pt5);
+	}
 	pt4 = wakepages[1];
 	pt3 = wakepages[2];
 	pt2 = wakepages[3];
@@ -448,7 +452,8 @@ acpi_install_wakeup_handler(struct acpi_softc *sc)
 #ifdef __amd64__
 	WAKECODE_FIXUP((wakeup_sw64 + 1), uint32_t,
 	    sc->acpi_wakephys + wakeup_64);
-	WAKECODE_FIXUP(wakeup_pagetables, uint32_t, pt4pa);
+	WAKECODE_FIXUP(wakeup_pagetables, uint32_t, la57 ? (pt5pa | 0x1) :
+	    pt4pa);
 #endif
 
 	/* Save pointers to some global data. */
@@ -457,7 +462,12 @@ acpi_install_wakeup_handler(struct acpi_softc *sc)
 	WAKECODE_FIXUP(wakeup_cr3, register_t, pmap_get_kcr3());
 #else /* __amd64__ */
 	/* Create the initial 1GB replicated page tables */
-	for (i = 0; i < 512; i++) {
+	for (i = 0; i < NPTEPG; i++) {
+		if (la57) {
+			pt5[i] = (uint64_t)pt4pa;
+			pt5[i] |= PG_V | PG_RW | PG_U;
+		}
+
 		/*
 		 * Each slot of the level 4 pages points
 		 * to the same level 3 page
@@ -473,7 +483,7 @@ acpi_install_wakeup_handler(struct acpi_softc *sc)
 		pt3[i] |= PG_V | PG_RW | PG_U;
 
 		/* The level 2 page slots are mapped with 2MB pages for 1GB. */
-		pt2[i] = i * (2 * 1024 * 1024);
+		pt2[i] = i * NBPDR;
 		pt2[i] |= PG_V | PG_RW | PG_PS | PG_U;
 	}
 #endif /* !__amd64__ */


More information about the svn-src-all mailing list