Hi all,
This series fixed S3 sleep on U-Boot + QEMU virt machine.
The first patch is a further DMW window setting fix, the second fixed support of ACPI standard S3 sleep procdure.
Please review. Thanks
Signed-off-by: Jiaxun Yang jiaxun.yang@flygoat.com --- Jiaxun Yang (2): LoongArch: Initialise unused Direct Map Windows LoongArch: Fix ACPI standard register based S3 support
arch/loongarch/include/asm/loongarch.h | 4 ++++ arch/loongarch/include/asm/stackframe.h | 11 +++++++++++ arch/loongarch/kernel/head.S | 12 ++---------- arch/loongarch/power/platform.c | 24 ++++++++++++++++++------ arch/loongarch/power/suspend_asm.S | 8 ++------ drivers/firmware/efi/libstub/loongarch.c | 2 ++ 6 files changed, 39 insertions(+), 22 deletions(-) --- base-commit: 6906a84c482f098d31486df8dc98cead21cce2d0 change-id: 20240613-loongarch64-sleep-035ffcdff9eb
Best regards,
DMW 2 & 3 are unused by kernel, however firmware may leave garbage in them and interfere kernel's address mapping.
Clear them as necessary.
Cc: stable@vger.kernel.org Signed-off-by: Jiaxun Yang jiaxun.yang@flygoat.com --- arch/loongarch/include/asm/loongarch.h | 4 ++++ arch/loongarch/include/asm/stackframe.h | 11 +++++++++++ arch/loongarch/kernel/head.S | 12 ++---------- arch/loongarch/power/suspend_asm.S | 6 +----- drivers/firmware/efi/libstub/loongarch.c | 2 ++ 5 files changed, 20 insertions(+), 15 deletions(-)
diff --git a/arch/loongarch/include/asm/loongarch.h b/arch/loongarch/include/asm/loongarch.h index eb09adda54b7..3720096efcf9 100644 --- a/arch/loongarch/include/asm/loongarch.h +++ b/arch/loongarch/include/asm/loongarch.h @@ -889,6 +889,10 @@ #define CSR_DMW1_BASE (CSR_DMW1_VSEG << DMW_PABITS) #define CSR_DMW1_INIT (CSR_DMW1_BASE | CSR_DMW1_MAT | CSR_DMW1_PLV0)
+/* Direct Map window 2/3 - unused */ +#define CSR_DMW2_INIT 0 +#define CSR_DMW3_INIT 0 + /* Performance Counter registers */ #define LOONGARCH_CSR_PERFCTRL0 0x200 /* 32 perf event 0 config */ #define LOONGARCH_CSR_PERFCNTR0 0x201 /* 64 perf event 0 count value */ diff --git a/arch/loongarch/include/asm/stackframe.h b/arch/loongarch/include/asm/stackframe.h index d9eafd3ee3d1..10c5dcf56bc7 100644 --- a/arch/loongarch/include/asm/stackframe.h +++ b/arch/loongarch/include/asm/stackframe.h @@ -38,6 +38,17 @@ cfi_restore \reg \offset \docfi .endm
+ .macro SETUP_DMWS temp1 + li.d \temp1, CSR_DMW0_INIT + csrwr \temp1, LOONGARCH_CSR_DMWIN0 + li.d \temp1, CSR_DMW1_INIT + csrwr \temp1, LOONGARCH_CSR_DMWIN1 + li.d \temp1, CSR_DMW2_INIT + csrwr \temp1, LOONGARCH_CSR_DMWIN2 + li.d \temp1, CSR_DMW3_INIT + csrwr \temp1, LOONGARCH_CSR_DMWIN3 + .endm + /* Jump to the runtime virtual address. */ .macro JUMP_VIRT_ADDR temp1 temp2 li.d \temp1, CACHE_BASE diff --git a/arch/loongarch/kernel/head.S b/arch/loongarch/kernel/head.S index 4677ea8fa8e9..1a71fc09bfd6 100644 --- a/arch/loongarch/kernel/head.S +++ b/arch/loongarch/kernel/head.S @@ -44,11 +44,7 @@ SYM_DATA(kernel_fsize, .long _kernel_fsize); SYM_CODE_START(kernel_entry) # kernel entry point
/* Config direct window and set PG */ - li.d t0, CSR_DMW0_INIT # UC, PLV0, 0x8000 xxxx xxxx xxxx - csrwr t0, LOONGARCH_CSR_DMWIN0 - li.d t0, CSR_DMW1_INIT # CA, PLV0, 0x9000 xxxx xxxx xxxx - csrwr t0, LOONGARCH_CSR_DMWIN1 - + SETUP_DMWS t0 JUMP_VIRT_ADDR t0, t1
/* Enable PG */ @@ -124,11 +120,7 @@ SYM_CODE_END(kernel_entry) * function after setting up the stack and tp registers. */ SYM_CODE_START(smpboot_entry) - li.d t0, CSR_DMW0_INIT # UC, PLV0 - csrwr t0, LOONGARCH_CSR_DMWIN0 - li.d t0, CSR_DMW1_INIT # CA, PLV0 - csrwr t0, LOONGARCH_CSR_DMWIN1 - + SETUP_DMWS t0 JUMP_VIRT_ADDR t0, t1
#ifdef CONFIG_PAGE_SIZE_4KB diff --git a/arch/loongarch/power/suspend_asm.S b/arch/loongarch/power/suspend_asm.S index e2fc3b4e31f0..6fdd74eb219b 100644 --- a/arch/loongarch/power/suspend_asm.S +++ b/arch/loongarch/power/suspend_asm.S @@ -73,11 +73,7 @@ SYM_FUNC_START(loongarch_suspend_enter) * Reload all of the registers and return. */ SYM_INNER_LABEL(loongarch_wakeup_start, SYM_L_GLOBAL) - li.d t0, CSR_DMW0_INIT # UC, PLV0 - csrwr t0, LOONGARCH_CSR_DMWIN0 - li.d t0, CSR_DMW1_INIT # CA, PLV0 - csrwr t0, LOONGARCH_CSR_DMWIN1 - + SETUP_DMWS t0 JUMP_VIRT_ADDR t0, t1
/* Enable PG */ diff --git a/drivers/firmware/efi/libstub/loongarch.c b/drivers/firmware/efi/libstub/loongarch.c index d0ef93551c44..3782d0a187d1 100644 --- a/drivers/firmware/efi/libstub/loongarch.c +++ b/drivers/firmware/efi/libstub/loongarch.c @@ -74,6 +74,8 @@ efi_status_t efi_boot_kernel(void *handle, efi_loaded_image_t *image, /* Config Direct Mapping */ csr_write64(CSR_DMW0_INIT, LOONGARCH_CSR_DMWIN0); csr_write64(CSR_DMW1_INIT, LOONGARCH_CSR_DMWIN1); + csr_write64(CSR_DMW2_INIT, LOONGARCH_CSR_DMWIN2); + csr_write64(CSR_DMW3_INIT, LOONGARCH_CSR_DMWIN3);
real_kernel_entry = (void *)kernel_entry_address(kernel_addr, image);
Hi, Jiaxun,
On Fri, Jun 14, 2024 at 12:41 AM Jiaxun Yang jiaxun.yang@flygoat.com wrote:
DMW 2 & 3 are unused by kernel, however firmware may leave garbage in them and interfere kernel's address mapping.
Clear them as necessary.
I think the current status is as expected, we don't want kernel access to non-8000 and non-9000 addresses. And low-end chips may have only two DMWs.
Huacai
Huacai
Cc: stable@vger.kernel.org Signed-off-by: Jiaxun Yang jiaxun.yang@flygoat.com
arch/loongarch/include/asm/loongarch.h | 4 ++++ arch/loongarch/include/asm/stackframe.h | 11 +++++++++++ arch/loongarch/kernel/head.S | 12 ++---------- arch/loongarch/power/suspend_asm.S | 6 +----- drivers/firmware/efi/libstub/loongarch.c | 2 ++ 5 files changed, 20 insertions(+), 15 deletions(-)
diff --git a/arch/loongarch/include/asm/loongarch.h b/arch/loongarch/include/asm/loongarch.h index eb09adda54b7..3720096efcf9 100644 --- a/arch/loongarch/include/asm/loongarch.h +++ b/arch/loongarch/include/asm/loongarch.h @@ -889,6 +889,10 @@ #define CSR_DMW1_BASE (CSR_DMW1_VSEG << DMW_PABITS) #define CSR_DMW1_INIT (CSR_DMW1_BASE | CSR_DMW1_MAT | CSR_DMW1_PLV0)
+/* Direct Map window 2/3 - unused */ +#define CSR_DMW2_INIT 0 +#define CSR_DMW3_INIT 0
/* Performance Counter registers */ #define LOONGARCH_CSR_PERFCTRL0 0x200 /* 32 perf event 0 config */ #define LOONGARCH_CSR_PERFCNTR0 0x201 /* 64 perf event 0 count value */ diff --git a/arch/loongarch/include/asm/stackframe.h b/arch/loongarch/include/asm/stackframe.h index d9eafd3ee3d1..10c5dcf56bc7 100644 --- a/arch/loongarch/include/asm/stackframe.h +++ b/arch/loongarch/include/asm/stackframe.h @@ -38,6 +38,17 @@ cfi_restore \reg \offset \docfi .endm
.macro SETUP_DMWS temp1
li.d \temp1, CSR_DMW0_INIT
csrwr \temp1, LOONGARCH_CSR_DMWIN0
li.d \temp1, CSR_DMW1_INIT
csrwr \temp1, LOONGARCH_CSR_DMWIN1
li.d \temp1, CSR_DMW2_INIT
csrwr \temp1, LOONGARCH_CSR_DMWIN2
li.d \temp1, CSR_DMW3_INIT
csrwr \temp1, LOONGARCH_CSR_DMWIN3
.endm
/* Jump to the runtime virtual address. */ .macro JUMP_VIRT_ADDR temp1 temp2 li.d \temp1, CACHE_BASE diff --git a/arch/loongarch/kernel/head.S b/arch/loongarch/kernel/head.S index 4677ea8fa8e9..1a71fc09bfd6 100644 --- a/arch/loongarch/kernel/head.S +++ b/arch/loongarch/kernel/head.S @@ -44,11 +44,7 @@ SYM_DATA(kernel_fsize, .long _kernel_fsize); SYM_CODE_START(kernel_entry) # kernel entry point
/* Config direct window and set PG */
li.d t0, CSR_DMW0_INIT # UC, PLV0, 0x8000 xxxx xxxx xxxx
csrwr t0, LOONGARCH_CSR_DMWIN0
li.d t0, CSR_DMW1_INIT # CA, PLV0, 0x9000 xxxx xxxx xxxx
csrwr t0, LOONGARCH_CSR_DMWIN1
SETUP_DMWS t0 JUMP_VIRT_ADDR t0, t1 /* Enable PG */
@@ -124,11 +120,7 @@ SYM_CODE_END(kernel_entry)
- function after setting up the stack and tp registers.
*/ SYM_CODE_START(smpboot_entry)
li.d t0, CSR_DMW0_INIT # UC, PLV0
csrwr t0, LOONGARCH_CSR_DMWIN0
li.d t0, CSR_DMW1_INIT # CA, PLV0
csrwr t0, LOONGARCH_CSR_DMWIN1
SETUP_DMWS t0 JUMP_VIRT_ADDR t0, t1
#ifdef CONFIG_PAGE_SIZE_4KB diff --git a/arch/loongarch/power/suspend_asm.S b/arch/loongarch/power/suspend_asm.S index e2fc3b4e31f0..6fdd74eb219b 100644 --- a/arch/loongarch/power/suspend_asm.S +++ b/arch/loongarch/power/suspend_asm.S @@ -73,11 +73,7 @@ SYM_FUNC_START(loongarch_suspend_enter) * Reload all of the registers and return. */ SYM_INNER_LABEL(loongarch_wakeup_start, SYM_L_GLOBAL)
li.d t0, CSR_DMW0_INIT # UC, PLV0
csrwr t0, LOONGARCH_CSR_DMWIN0
li.d t0, CSR_DMW1_INIT # CA, PLV0
csrwr t0, LOONGARCH_CSR_DMWIN1
SETUP_DMWS t0 JUMP_VIRT_ADDR t0, t1 /* Enable PG */
diff --git a/drivers/firmware/efi/libstub/loongarch.c b/drivers/firmware/efi/libstub/loongarch.c index d0ef93551c44..3782d0a187d1 100644 --- a/drivers/firmware/efi/libstub/loongarch.c +++ b/drivers/firmware/efi/libstub/loongarch.c @@ -74,6 +74,8 @@ efi_status_t efi_boot_kernel(void *handle, efi_loaded_image_t *image, /* Config Direct Mapping */ csr_write64(CSR_DMW0_INIT, LOONGARCH_CSR_DMWIN0); csr_write64(CSR_DMW1_INIT, LOONGARCH_CSR_DMWIN1);
csr_write64(CSR_DMW2_INIT, LOONGARCH_CSR_DMWIN2);
csr_write64(CSR_DMW3_INIT, LOONGARCH_CSR_DMWIN3); real_kernel_entry = (void *)kernel_entry_address(kernel_addr, image);
-- 2.43.0
在2024年6月14日六月 上午3:13,Huacai Chen写道:
Hi, Jiaxun,
On Fri, Jun 14, 2024 at 12:41 AM Jiaxun Yang jiaxun.yang@flygoat.com wrote:
DMW 2 & 3 are unused by kernel, however firmware may leave garbage in them and interfere kernel's address mapping.
Clear them as necessary.
I think the current status is as expected, we don't want kernel access to non-8000 and non-9000 addresses. And low-end chips may have only two DMWs.
I see, I'll remove U-Boot's dependency to DMW 2 and 3 then.
Thanks - Jiaxun
Huacai
Huacai
Cc: stable@vger.kernel.org Signed-off-by: Jiaxun Yang jiaxun.yang@flygoat.com
arch/loongarch/include/asm/loongarch.h | 4 ++++ arch/loongarch/include/asm/stackframe.h | 11 +++++++++++ arch/loongarch/kernel/head.S | 12 ++---------- arch/loongarch/power/suspend_asm.S | 6 +----- drivers/firmware/efi/libstub/loongarch.c | 2 ++ 5 files changed, 20 insertions(+), 15 deletions(-)
diff --git a/arch/loongarch/include/asm/loongarch.h b/arch/loongarch/include/asm/loongarch.h index eb09adda54b7..3720096efcf9 100644 --- a/arch/loongarch/include/asm/loongarch.h +++ b/arch/loongarch/include/asm/loongarch.h @@ -889,6 +889,10 @@ #define CSR_DMW1_BASE (CSR_DMW1_VSEG << DMW_PABITS) #define CSR_DMW1_INIT (CSR_DMW1_BASE | CSR_DMW1_MAT | CSR_DMW1_PLV0)
+/* Direct Map window 2/3 - unused */ +#define CSR_DMW2_INIT 0 +#define CSR_DMW3_INIT 0
/* Performance Counter registers */ #define LOONGARCH_CSR_PERFCTRL0 0x200 /* 32 perf event 0 config */ #define LOONGARCH_CSR_PERFCNTR0 0x201 /* 64 perf event 0 count value */ diff --git a/arch/loongarch/include/asm/stackframe.h b/arch/loongarch/include/asm/stackframe.h index d9eafd3ee3d1..10c5dcf56bc7 100644 --- a/arch/loongarch/include/asm/stackframe.h +++ b/arch/loongarch/include/asm/stackframe.h @@ -38,6 +38,17 @@ cfi_restore \reg \offset \docfi .endm
.macro SETUP_DMWS temp1
li.d \temp1, CSR_DMW0_INIT
csrwr \temp1, LOONGARCH_CSR_DMWIN0
li.d \temp1, CSR_DMW1_INIT
csrwr \temp1, LOONGARCH_CSR_DMWIN1
li.d \temp1, CSR_DMW2_INIT
csrwr \temp1, LOONGARCH_CSR_DMWIN2
li.d \temp1, CSR_DMW3_INIT
csrwr \temp1, LOONGARCH_CSR_DMWIN3
.endm
/* Jump to the runtime virtual address. */ .macro JUMP_VIRT_ADDR temp1 temp2 li.d \temp1, CACHE_BASE diff --git a/arch/loongarch/kernel/head.S b/arch/loongarch/kernel/head.S index 4677ea8fa8e9..1a71fc09bfd6 100644 --- a/arch/loongarch/kernel/head.S +++ b/arch/loongarch/kernel/head.S @@ -44,11 +44,7 @@ SYM_DATA(kernel_fsize, .long _kernel_fsize); SYM_CODE_START(kernel_entry) # kernel entry point
/* Config direct window and set PG */
li.d t0, CSR_DMW0_INIT # UC, PLV0, 0x8000 xxxx xxxx xxxx
csrwr t0, LOONGARCH_CSR_DMWIN0
li.d t0, CSR_DMW1_INIT # CA, PLV0, 0x9000 xxxx xxxx xxxx
csrwr t0, LOONGARCH_CSR_DMWIN1
SETUP_DMWS t0 JUMP_VIRT_ADDR t0, t1 /* Enable PG */
@@ -124,11 +120,7 @@ SYM_CODE_END(kernel_entry)
- function after setting up the stack and tp registers.
*/ SYM_CODE_START(smpboot_entry)
li.d t0, CSR_DMW0_INIT # UC, PLV0
csrwr t0, LOONGARCH_CSR_DMWIN0
li.d t0, CSR_DMW1_INIT # CA, PLV0
csrwr t0, LOONGARCH_CSR_DMWIN1
SETUP_DMWS t0 JUMP_VIRT_ADDR t0, t1
#ifdef CONFIG_PAGE_SIZE_4KB diff --git a/arch/loongarch/power/suspend_asm.S b/arch/loongarch/power/suspend_asm.S index e2fc3b4e31f0..6fdd74eb219b 100644 --- a/arch/loongarch/power/suspend_asm.S +++ b/arch/loongarch/power/suspend_asm.S @@ -73,11 +73,7 @@ SYM_FUNC_START(loongarch_suspend_enter) * Reload all of the registers and return. */ SYM_INNER_LABEL(loongarch_wakeup_start, SYM_L_GLOBAL)
li.d t0, CSR_DMW0_INIT # UC, PLV0
csrwr t0, LOONGARCH_CSR_DMWIN0
li.d t0, CSR_DMW1_INIT # CA, PLV0
csrwr t0, LOONGARCH_CSR_DMWIN1
SETUP_DMWS t0 JUMP_VIRT_ADDR t0, t1 /* Enable PG */
diff --git a/drivers/firmware/efi/libstub/loongarch.c b/drivers/firmware/efi/libstub/loongarch.c index d0ef93551c44..3782d0a187d1 100644 --- a/drivers/firmware/efi/libstub/loongarch.c +++ b/drivers/firmware/efi/libstub/loongarch.c @@ -74,6 +74,8 @@ efi_status_t efi_boot_kernel(void *handle, efi_loaded_image_t *image, /* Config Direct Mapping */ csr_write64(CSR_DMW0_INIT, LOONGARCH_CSR_DMWIN0); csr_write64(CSR_DMW1_INIT, LOONGARCH_CSR_DMWIN1);
csr_write64(CSR_DMW2_INIT, LOONGARCH_CSR_DMWIN2);
csr_write64(CSR_DMW3_INIT, LOONGARCH_CSR_DMWIN3); real_kernel_entry = (void *)kernel_entry_address(kernel_addr, image);
-- 2.43.0
On Fri, Jun 14, 2024 at 10:18 AM Jiaxun Yang jiaxun.yang@flygoat.com wrote:
在2024年6月14日六月 上午3:13,Huacai Chen写道:
Hi, Jiaxun,
On Fri, Jun 14, 2024 at 12:41 AM Jiaxun Yang jiaxun.yang@flygoat.com wrote:
DMW 2 & 3 are unused by kernel, however firmware may leave garbage in them and interfere kernel's address mapping.
Clear them as necessary.
I think the current status is as expected, we don't want kernel access to non-8000 and non-9000 addresses. And low-end chips may have only two DMWs.
I see, I'll remove U-Boot's dependency to DMW 2 and 3 then.
I was told that DMW2&3 are probably exist (but cannot used for instruction fetch), so I applied this patch and implement DMW-based ioremap_wc().
https://github.com/chenhuacai/linux/commit/fa9f4109bf19a19736877d01e3e352975...
Huacai
Thanks
- Jiaxun
Huacai
Huacai
Cc: stable@vger.kernel.org Signed-off-by: Jiaxun Yang jiaxun.yang@flygoat.com
arch/loongarch/include/asm/loongarch.h | 4 ++++ arch/loongarch/include/asm/stackframe.h | 11 +++++++++++ arch/loongarch/kernel/head.S | 12 ++---------- arch/loongarch/power/suspend_asm.S | 6 +----- drivers/firmware/efi/libstub/loongarch.c | 2 ++ 5 files changed, 20 insertions(+), 15 deletions(-)
diff --git a/arch/loongarch/include/asm/loongarch.h b/arch/loongarch/include/asm/loongarch.h index eb09adda54b7..3720096efcf9 100644 --- a/arch/loongarch/include/asm/loongarch.h +++ b/arch/loongarch/include/asm/loongarch.h @@ -889,6 +889,10 @@ #define CSR_DMW1_BASE (CSR_DMW1_VSEG << DMW_PABITS) #define CSR_DMW1_INIT (CSR_DMW1_BASE | CSR_DMW1_MAT | CSR_DMW1_PLV0)
+/* Direct Map window 2/3 - unused */ +#define CSR_DMW2_INIT 0 +#define CSR_DMW3_INIT 0
/* Performance Counter registers */ #define LOONGARCH_CSR_PERFCTRL0 0x200 /* 32 perf event 0 config */ #define LOONGARCH_CSR_PERFCNTR0 0x201 /* 64 perf event 0 count value */ diff --git a/arch/loongarch/include/asm/stackframe.h b/arch/loongarch/include/asm/stackframe.h index d9eafd3ee3d1..10c5dcf56bc7 100644 --- a/arch/loongarch/include/asm/stackframe.h +++ b/arch/loongarch/include/asm/stackframe.h @@ -38,6 +38,17 @@ cfi_restore \reg \offset \docfi .endm
.macro SETUP_DMWS temp1
li.d \temp1, CSR_DMW0_INIT
csrwr \temp1, LOONGARCH_CSR_DMWIN0
li.d \temp1, CSR_DMW1_INIT
csrwr \temp1, LOONGARCH_CSR_DMWIN1
li.d \temp1, CSR_DMW2_INIT
csrwr \temp1, LOONGARCH_CSR_DMWIN2
li.d \temp1, CSR_DMW3_INIT
csrwr \temp1, LOONGARCH_CSR_DMWIN3
.endm
/* Jump to the runtime virtual address. */ .macro JUMP_VIRT_ADDR temp1 temp2 li.d \temp1, CACHE_BASE diff --git a/arch/loongarch/kernel/head.S b/arch/loongarch/kernel/head.S index 4677ea8fa8e9..1a71fc09bfd6 100644 --- a/arch/loongarch/kernel/head.S +++ b/arch/loongarch/kernel/head.S @@ -44,11 +44,7 @@ SYM_DATA(kernel_fsize, .long _kernel_fsize); SYM_CODE_START(kernel_entry) # kernel entry point
/* Config direct window and set PG */
li.d t0, CSR_DMW0_INIT # UC, PLV0, 0x8000 xxxx xxxx xxxx
csrwr t0, LOONGARCH_CSR_DMWIN0
li.d t0, CSR_DMW1_INIT # CA, PLV0, 0x9000 xxxx xxxx xxxx
csrwr t0, LOONGARCH_CSR_DMWIN1
SETUP_DMWS t0 JUMP_VIRT_ADDR t0, t1 /* Enable PG */
@@ -124,11 +120,7 @@ SYM_CODE_END(kernel_entry)
- function after setting up the stack and tp registers.
*/ SYM_CODE_START(smpboot_entry)
li.d t0, CSR_DMW0_INIT # UC, PLV0
csrwr t0, LOONGARCH_CSR_DMWIN0
li.d t0, CSR_DMW1_INIT # CA, PLV0
csrwr t0, LOONGARCH_CSR_DMWIN1
SETUP_DMWS t0 JUMP_VIRT_ADDR t0, t1
#ifdef CONFIG_PAGE_SIZE_4KB diff --git a/arch/loongarch/power/suspend_asm.S b/arch/loongarch/power/suspend_asm.S index e2fc3b4e31f0..6fdd74eb219b 100644 --- a/arch/loongarch/power/suspend_asm.S +++ b/arch/loongarch/power/suspend_asm.S @@ -73,11 +73,7 @@ SYM_FUNC_START(loongarch_suspend_enter) * Reload all of the registers and return. */ SYM_INNER_LABEL(loongarch_wakeup_start, SYM_L_GLOBAL)
li.d t0, CSR_DMW0_INIT # UC, PLV0
csrwr t0, LOONGARCH_CSR_DMWIN0
li.d t0, CSR_DMW1_INIT # CA, PLV0
csrwr t0, LOONGARCH_CSR_DMWIN1
SETUP_DMWS t0 JUMP_VIRT_ADDR t0, t1 /* Enable PG */
diff --git a/drivers/firmware/efi/libstub/loongarch.c b/drivers/firmware/efi/libstub/loongarch.c index d0ef93551c44..3782d0a187d1 100644 --- a/drivers/firmware/efi/libstub/loongarch.c +++ b/drivers/firmware/efi/libstub/loongarch.c @@ -74,6 +74,8 @@ efi_status_t efi_boot_kernel(void *handle, efi_loaded_image_t *image, /* Config Direct Mapping */ csr_write64(CSR_DMW0_INIT, LOONGARCH_CSR_DMWIN0); csr_write64(CSR_DMW1_INIT, LOONGARCH_CSR_DMWIN1);
csr_write64(CSR_DMW2_INIT, LOONGARCH_CSR_DMWIN2);
csr_write64(CSR_DMW3_INIT, LOONGARCH_CSR_DMWIN3); real_kernel_entry = (void *)kernel_entry_address(kernel_addr, image);
-- 2.43.0
--
- Jiaxun
Most LoongArch 64 machines are using custom "SADR" ACPI extension to perform ACPI S3 sleep. However the standard ACPI way to perform sleep is to write a value to ACPI PM1/SLEEP_CTL register, and this is never supported properly in kernel.
Fix standard S3 sleep by providing a fallback DoSuspend function which calls ACPI's acpi_enter_sleep_state routine when SADR is not provided by the firmware.
Also fix suspend assembly code so that ra is set properly before go into sleep routine. (Previously linked address of jirl was set to a0, some firmware do require return address in a0 but it's already set with la.pcrel before).
Cc: stable@vger.kernel.org Signed-off-by: Jiaxun Yang jiaxun.yang@flygoat.com --- arch/loongarch/power/platform.c | 24 ++++++++++++++++++------ arch/loongarch/power/suspend_asm.S | 2 +- 2 files changed, 19 insertions(+), 7 deletions(-)
diff --git a/arch/loongarch/power/platform.c b/arch/loongarch/power/platform.c index 3ea8e07aa225..2aea41f8e3ff 100644 --- a/arch/loongarch/power/platform.c +++ b/arch/loongarch/power/platform.c @@ -34,22 +34,34 @@ void enable_pci_wakeup(void) acpi_write_bit_register(ACPI_BITREG_PCIEXP_WAKE_DISABLE, 0); }
+static void acpi_suspend_register_fallback(void) +{ + acpi_enter_sleep_state(ACPI_STATE_S3); +} + static int __init loongson3_acpi_suspend_init(void) { #ifdef CONFIG_ACPI acpi_status status; uint64_t suspend_addr = 0;
- if (acpi_disabled || acpi_gbl_reduced_hardware) + if (acpi_disabled) return 0;
- acpi_write_bit_register(ACPI_BITREG_SCI_ENABLE, 1); + if (!acpi_sleep_state_supported(ACPI_STATE_S3)) + return 0; + + if (!acpi_gbl_reduced_hardware) + acpi_write_bit_register(ACPI_BITREG_SCI_ENABLE, 1); + status = acpi_evaluate_integer(NULL, "\SADR", NULL, &suspend_addr); - if (ACPI_FAILURE(status) || !suspend_addr) { - pr_err("ACPI S3 is not support!\n"); - return -1; + if (!ACPI_FAILURE(status) && suspend_addr) { + loongson_sysconf.suspend_addr = (u64)phys_to_virt(PHYSADDR(suspend_addr)); + return 0; } - loongson_sysconf.suspend_addr = (u64)phys_to_virt(PHYSADDR(suspend_addr)); + + pr_info("ACPI S3 supported with hw register fallback\n"); + loongson_sysconf.suspend_addr = (u64)acpi_suspend_register_fallback; #endif return 0; } diff --git a/arch/loongarch/power/suspend_asm.S b/arch/loongarch/power/suspend_asm.S index 6fdd74eb219b..fe08dbb73c87 100644 --- a/arch/loongarch/power/suspend_asm.S +++ b/arch/loongarch/power/suspend_asm.S @@ -66,7 +66,7 @@ SYM_FUNC_START(loongarch_suspend_enter) la.pcrel a0, loongarch_wakeup_start la.pcrel t0, loongarch_suspend_addr ld.d t0, t0, 0 - jirl a0, t0, 0 /* Call BIOS's STR sleep routine */ + jirl ra, t0, 0 /* Call BIOS's STR sleep routine */
/* * This is where we return upon wakeup.
Hi, Jiaxun,
On Fri, Jun 14, 2024 at 12:41 AM Jiaxun Yang jiaxun.yang@flygoat.com wrote:
Most LoongArch 64 machines are using custom "SADR" ACPI extension to perform ACPI S3 sleep. However the standard ACPI way to perform sleep is to write a value to ACPI PM1/SLEEP_CTL register, and this is never supported properly in kernel.
Maybe our hardware is insane so we need "SADR", if so, this patch may break real hardware. What's your opinion, Jianmin?
Huacai
Fix standard S3 sleep by providing a fallback DoSuspend function which calls ACPI's acpi_enter_sleep_state routine when SADR is not provided by the firmware.
Also fix suspend assembly code so that ra is set properly before go into sleep routine. (Previously linked address of jirl was set to a0, some firmware do require return address in a0 but it's already set with la.pcrel before).
Cc: stable@vger.kernel.org Signed-off-by: Jiaxun Yang jiaxun.yang@flygoat.com
arch/loongarch/power/platform.c | 24 ++++++++++++++++++------ arch/loongarch/power/suspend_asm.S | 2 +- 2 files changed, 19 insertions(+), 7 deletions(-)
diff --git a/arch/loongarch/power/platform.c b/arch/loongarch/power/platform.c index 3ea8e07aa225..2aea41f8e3ff 100644 --- a/arch/loongarch/power/platform.c +++ b/arch/loongarch/power/platform.c @@ -34,22 +34,34 @@ void enable_pci_wakeup(void) acpi_write_bit_register(ACPI_BITREG_PCIEXP_WAKE_DISABLE, 0); }
+static void acpi_suspend_register_fallback(void) +{
acpi_enter_sleep_state(ACPI_STATE_S3);
+}
static int __init loongson3_acpi_suspend_init(void) { #ifdef CONFIG_ACPI acpi_status status; uint64_t suspend_addr = 0;
if (acpi_disabled || acpi_gbl_reduced_hardware)
if (acpi_disabled) return 0;
acpi_write_bit_register(ACPI_BITREG_SCI_ENABLE, 1);
if (!acpi_sleep_state_supported(ACPI_STATE_S3))
return 0;
if (!acpi_gbl_reduced_hardware)
acpi_write_bit_register(ACPI_BITREG_SCI_ENABLE, 1);
status = acpi_evaluate_integer(NULL, "\\SADR", NULL, &suspend_addr);
if (ACPI_FAILURE(status) || !suspend_addr) {
pr_err("ACPI S3 is not support!\n");
return -1;
if (!ACPI_FAILURE(status) && suspend_addr) {
loongson_sysconf.suspend_addr = (u64)phys_to_virt(PHYSADDR(suspend_addr));
return 0; }
loongson_sysconf.suspend_addr = (u64)phys_to_virt(PHYSADDR(suspend_addr));
pr_info("ACPI S3 supported with hw register fallback\n");
loongson_sysconf.suspend_addr = (u64)acpi_suspend_register_fallback;
#endif return 0; } diff --git a/arch/loongarch/power/suspend_asm.S b/arch/loongarch/power/suspend_asm.S index 6fdd74eb219b..fe08dbb73c87 100644 --- a/arch/loongarch/power/suspend_asm.S +++ b/arch/loongarch/power/suspend_asm.S @@ -66,7 +66,7 @@ SYM_FUNC_START(loongarch_suspend_enter) la.pcrel a0, loongarch_wakeup_start la.pcrel t0, loongarch_suspend_addr ld.d t0, t0, 0
jirl a0, t0, 0 /* Call BIOS's STR sleep routine */
jirl ra, t0, 0 /* Call BIOS's STR sleep routine */ /* * This is where we return upon wakeup.
-- 2.43.0
在2024年6月14日六月 上午3:11,Huacai Chen写道:
Hi, Jiaxun,
On Fri, Jun 14, 2024 at 12:41 AM Jiaxun Yang jiaxun.yang@flygoat.com wrote:
Most LoongArch 64 machines are using custom "SADR" ACPI extension to perform ACPI S3 sleep. However the standard ACPI way to perform sleep is to write a value to ACPI PM1/SLEEP_CTL register, and this is never supported properly in kernel.
Maybe our hardware is insane so we need "SADR", if so, this patch may break real hardware. What's your opinion, Jianmin?
I understand why your hardware need SADR. Most systems DDR self-refresh mode needs to be setup by firmware.
There is no chance that it may break real hardware. When firmware supplied SADR it will always use SADR. The fallback only happens when _S3 method exist but no SADR supplied, which won't happen on real hardware.
For QEMU we don't have stub firmware but standard compliant SEEP_CTL is sufficient for entering sleep mode, thus we need this fallback path.
Thanks
Huacai
On Fri, Jun 14, 2024 at 10:25 AM Jiaxun Yang jiaxun.yang@flygoat.com wrote:
在2024年6月14日六月 上午3:11,Huacai Chen写道:
Hi, Jiaxun,
On Fri, Jun 14, 2024 at 12:41 AM Jiaxun Yang jiaxun.yang@flygoat.com wrote:
Most LoongArch 64 machines are using custom "SADR" ACPI extension to perform ACPI S3 sleep. However the standard ACPI way to perform sleep is to write a value to ACPI PM1/SLEEP_CTL register, and this is never supported properly in kernel.
Maybe our hardware is insane so we need "SADR", if so, this patch may break real hardware. What's your opinion, Jianmin?
I understand why your hardware need SADR. Most systems DDR self-refresh mode needs to be setup by firmware.
_S3 is also a firmware method, why we can't use it to setup self-refresh?
Huacai
There is no chance that it may break real hardware. When firmware supplied SADR it will always use SADR. The fallback only happens when _S3 method exist but no SADR supplied, which won't happen on real hardware.
For QEMU we don't have stub firmware but standard compliant SEEP_CTL is sufficient for entering sleep mode, thus we need this fallback path.
Thanks
Huacai
--
- Jiaxun
在2024年6月14日六月 上午3:32,Huacai Chen写道:
On Fri, Jun 14, 2024 at 10:25 AM Jiaxun Yang jiaxun.yang@flygoat.com wrote:
在2024年6月14日六月 上午3:11,Huacai Chen写道:
Hi, Jiaxun,
On Fri, Jun 14, 2024 at 12:41 AM Jiaxun Yang jiaxun.yang@flygoat.com wrote:
Most LoongArch 64 machines are using custom "SADR" ACPI extension to perform ACPI S3 sleep. However the standard ACPI way to perform sleep is to write a value to ACPI PM1/SLEEP_CTL register, and this is never supported properly in kernel.
Maybe our hardware is insane so we need "SADR", if so, this patch may break real hardware. What's your opinion, Jianmin?
I understand why your hardware need SADR. Most systems DDR self-refresh mode needs to be setup by firmware.
_S3 is also a firmware method, why we can't use it to setup self-refresh?
That's the problem from ACPI spec. As per ACPI spec _S3 method only tells you what should you write into PM1 or SLEEP_CTL register, it will NOT perform actual task to enter sleeping. (See 16.1.3.1 [1])
On existing LoongArch hardware _S3 method is only used to mark presence of S3 state. This is violating ACPI spec, but I guess we must live with it.
Furthermore, on Loongson hardware you have to disable access to DDR memory to access DDR controller's configuration registers. Which means self-refresh code must run from BIOS ROM.
[1]: https://uefi.org/htmlspecs/ACPI_Spec_6_4_html/16_Waking_and_Sleeping/sleepin...
Thanks - Jiaxun
Huacai
There is no chance that it may break real hardware. When firmware supplied SADR it will always use SADR. The fallback only happens when _S3 method exist but no SADR supplied, which won't happen on real hardware.
For QEMU we don't have stub firmware but standard compliant SEEP_CTL is sufficient for entering sleep mode, thus we need this fallback path.
Thanks
Huacai
--
- Jiaxun
On Fri, Jun 14, 2024 at 10:44 AM Jiaxun Yang jiaxun.yang@flygoat.com wrote:
在2024年6月14日六月 上午3:32,Huacai Chen写道:
On Fri, Jun 14, 2024 at 10:25 AM Jiaxun Yang jiaxun.yang@flygoat.com wrote:
在2024年6月14日六月 上午3:11,Huacai Chen写道:
Hi, Jiaxun,
On Fri, Jun 14, 2024 at 12:41 AM Jiaxun Yang jiaxun.yang@flygoat.com wrote:
Most LoongArch 64 machines are using custom "SADR" ACPI extension to perform ACPI S3 sleep. However the standard ACPI way to perform sleep is to write a value to ACPI PM1/SLEEP_CTL register, and this is never supported properly in kernel.
Maybe our hardware is insane so we need "SADR", if so, this patch may break real hardware. What's your opinion, Jianmin?
I understand why your hardware need SADR. Most systems DDR self-refresh mode needs to be setup by firmware.
_S3 is also a firmware method, why we can't use it to setup self-refresh?
That's the problem from ACPI spec. As per ACPI spec _S3 method only tells you what should you write into PM1 or SLEEP_CTL register, it will NOT perform actual task to enter sleeping. (See 16.1.3.1 [1])
On existing LoongArch hardware _S3 method is only used to mark presence of S3 state. This is violating ACPI spec, but I guess we must live with it.
Furthermore, on Loongson hardware you have to disable access to DDR memory to access DDR controller's configuration registers. Which means self-refresh code must run from BIOS ROM.
I think "if (!acpi_gbl_reduced_hardware)" should be before "if (!acpi_sleep_state_supported(ACPI_STATE_S3))", I applied this patch with adjustment.
https://github.com/chenhuacai/linux/commit/4bb9e051a4e9430c89ce83ca68a2f5998...
Huacai
Thanks
- Jiaxun
Huacai
There is no chance that it may break real hardware. When firmware supplied SADR it will always use SADR. The fallback only happens when _S3 method exist but no SADR supplied, which won't happen on real hardware.
For QEMU we don't have stub firmware but standard compliant SEEP_CTL is sufficient for entering sleep mode, thus we need this fallback path.
Thanks
Huacai
--
- Jiaxun
--
- Jiaxun
linux-stable-mirror@lists.linaro.org