2024-06-13 16:41:54

by Jiaxun Yang

[permalink] [raw]
Subject: [PATCH 0/2] LoongArch: Fix S3 sleep on U-Boot + QEMU virt machine

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 <[email protected]>
---
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,
--
Jiaxun Yang <[email protected]>



2024-06-13 16:41:59

by Jiaxun Yang

[permalink] [raw]
Subject: [PATCH 1/2] LoongArch: Initialise unused Direct Map Windows

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: [email protected]
Signed-off-by: Jiaxun Yang <[email protected]>
---
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-06-13 16:42:09

by Jiaxun Yang

[permalink] [raw]
Subject: [PATCH 2/2] LoongArch: Fix ACPI standard register based S3 support

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: [email protected]
Signed-off-by: Jiaxun Yang <[email protected]>
---
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-06-14 02:12:40

by Huacai Chen

[permalink] [raw]
Subject: Re: [PATCH 2/2] LoongArch: Fix ACPI standard register based S3 support

Hi, Jiaxun,

On Fri, Jun 14, 2024 at 12:41 AM Jiaxun Yang <[email protected]> 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: [email protected]
> Signed-off-by: Jiaxun Yang <[email protected]>
> ---
> 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-06-14 02:14:04

by Huacai Chen

[permalink] [raw]
Subject: Re: [PATCH 1/2] LoongArch: Initialise unused Direct Map Windows

Hi, Jiaxun,

On Fri, Jun 14, 2024 at 12:41 AM Jiaxun Yang <[email protected]> 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: [email protected]
> Signed-off-by: Jiaxun Yang <[email protected]>
> ---
> 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-06-14 02:18:11

by Jiaxun Yang

[permalink] [raw]
Subject: Re: [PATCH 1/2] LoongArch: Initialise unused Direct Map Windows



在2024年6月14日六月 上午3:13,Huacai Chen写道:
> Hi, Jiaxun,
>
> On Fri, Jun 14, 2024 at 12:41 AM Jiaxun Yang <[email protected]> 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: [email protected]
>> Signed-off-by: Jiaxun Yang <[email protected]>
>> ---
>> 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

2024-06-14 02:26:14

by Jiaxun Yang

[permalink] [raw]
Subject: Re: [PATCH 2/2] LoongArch: Fix ACPI standard register based S3 support



在2024年6月14日六月 上午3:11,Huacai Chen写道:
> Hi, Jiaxun,
>
> On Fri, Jun 14, 2024 at 12:41 AM Jiaxun Yang <[email protected]> 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
>
>>

--
- Jiaxun

2024-06-14 02:33:22

by Huacai Chen

[permalink] [raw]
Subject: Re: [PATCH 2/2] LoongArch: Fix ACPI standard register based S3 support

On Fri, Jun 14, 2024 at 10:25 AM Jiaxun Yang <[email protected]> wrote:
>
>
>
> 在2024年6月14日六月 上午3:11,Huacai Chen写道:
> > Hi, Jiaxun,
> >
> > On Fri, Jun 14, 2024 at 12:41 AM Jiaxun Yang <[email protected]> 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-06-14 02:45:08

by Jiaxun Yang

[permalink] [raw]
Subject: Re: [PATCH 2/2] LoongArch: Fix ACPI standard register based S3 support



在2024年6月14日六月 上午3:32,Huacai Chen写道:
> On Fri, Jun 14, 2024 at 10:25 AM Jiaxun Yang <[email protected]> wrote:
>>
>>
>>
>> 在2024年6月14日六月 上午3:11,Huacai Chen写道:
>> > Hi, Jiaxun,
>> >
>> > On Fri, Jun 14, 2024 at 12:41 AM Jiaxun Yang <[email protected]> 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/sleeping-states.html

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