[PATCH] hw/loongarch: Modify flash block size to 256K

2024-06-23 Thread Xianglai Li
loongarch added a common library for edk2 to
parse flash base addresses through fdt.
For compatibility with other architectures,
the flash block size in qemu is now changed to 256k.

Signed-off-by: Xianglai Li 
---
Cc: Bibo Mao 
Cc: Song Gao 

 include/hw/loongarch/virt.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/include/hw/loongarch/virt.h b/include/hw/loongarch/virt.h
index 8fdfacf268..603c1cebdb 100644
--- a/include/hw/loongarch/virt.h
+++ b/include/hw/loongarch/virt.h
@@ -20,7 +20,7 @@
 #define VIRT_FWCFG_BASE 0x1e02UL
 #define VIRT_BIOS_BASE  0x1c00UL
 #define VIRT_BIOS_SIZE  (16 * MiB)
-#define VIRT_FLASH_SECTOR_SIZE  (128 * KiB)
+#define VIRT_FLASH_SECTOR_SIZE  (256 * KiB)
 #define VIRT_FLASH0_BASEVIRT_BIOS_BASE
 #define VIRT_FLASH0_SIZEVIRT_BIOS_SIZE
 #define VIRT_FLASH1_BASE0x1d00UL
-- 
2.39.1




[PATCH] hw/loongarch: Change the tpm support by default

2024-06-23 Thread Xianglai Li
Add devices that support tpm by default,
Fixed incomplete tpm acpi table information.

Signed-off-by: Xianglai Li 
---
Cc: Bibo Mao 
Cc: Paolo Bonzini 
Cc: Song Gao 

 hw/loongarch/Kconfig  | 1 +
 hw/loongarch/acpi-build.c | 3 +++
 2 files changed, 4 insertions(+)

diff --git a/hw/loongarch/Kconfig b/hw/loongarch/Kconfig
index 90a0dba9d5..89be737726 100644
--- a/hw/loongarch/Kconfig
+++ b/hw/loongarch/Kconfig
@@ -8,6 +8,7 @@ config LOONGARCH_VIRT
 imply VIRTIO_VGA
 imply PCI_DEVICES
 imply NVDIMM
+imply TPM_TIS_SYSBUS
 select SERIAL
 select VIRTIO_PCI
 select PLATFORM_BUS
diff --git a/hw/loongarch/acpi-build.c b/hw/loongarch/acpi-build.c
index af45ce526d..72bfc35ae6 100644
--- a/hw/loongarch/acpi-build.c
+++ b/hw/loongarch/acpi-build.c
@@ -646,6 +646,9 @@ void loongarch_acpi_setup(LoongArchVirtMachineState *lvms)
  build_state, tables.rsdp,
  ACPI_BUILD_RSDP_FILE);
 
+fw_cfg_add_file(lvms->fw_cfg, ACPI_BUILD_TPMLOG_FILE, tables.tcpalog->data,
+acpi_data_len(tables.tcpalog));
+
 qemu_register_reset(acpi_build_reset, build_state);
 acpi_build_reset(build_state);
 vmstate_register(NULL, 0, _acpi_build, build_state);
-- 
2.39.1




[PATCH V6] target/loongarch: Fix tlb huge page loading issue

2024-03-18 Thread Xianglai Li
When we use qemu tcg simulation, the page size of bios is 4KB.
When using the level 2 super huge page (page size is 1G) to create the page 
table,
it is found that the content of the corresponding address space is abnormal,
resulting in the bios can not start the operating system and graphical 
interface normally.

The lddir and ldpte instruction emulation has
a problem with the use of super huge page processing above level 2.
The page size is not correctly calculated,
resulting in the wrong page size of the table entry found by tlb.

Signed-off-by: Xianglai Li 
---
 target/loongarch/cpu-csr.h|   3 +
 target/loongarch/internals.h  |   5 --
 target/loongarch/tcg/tlb_helper.c | 113 +-
 3 files changed, 82 insertions(+), 39 deletions(-)

Changes log:
V5->V6:
Add some necessary log printing to patch.

V4->V5:
Modifying the patch Title.
Fix incorrect usage of FIELD macro and code logic errors in patch.

V3->V4:
Optimize the huge page calculation method,
use the FIELD macro for bit calculation.

V2->V3:
Delete the intermediate variable LDDIR_PS, and implement lddir and ldpte
huge pages by referring to the latest architecture reference manual.

V1->V2:
Modified the patch title format and Enrich the commit mesg description

diff --git a/target/loongarch/cpu-csr.h b/target/loongarch/cpu-csr.h
index c59d7a9fcb..0834e91f30 100644
--- a/target/loongarch/cpu-csr.h
+++ b/target/loongarch/cpu-csr.h
@@ -67,6 +67,9 @@ FIELD(TLBENTRY, D, 1, 1)
 FIELD(TLBENTRY, PLV, 2, 2)
 FIELD(TLBENTRY, MAT, 4, 2)
 FIELD(TLBENTRY, G, 6, 1)
+FIELD(TLBENTRY, HUGE, 6, 1)
+FIELD(TLBENTRY, HGLOBAL, 12, 1)
+FIELD(TLBENTRY, LEVEL, 13, 2)
 FIELD(TLBENTRY_32, PPN, 8, 24)
 FIELD(TLBENTRY_64, PPN, 12, 36)
 FIELD(TLBENTRY_64, NR, 61, 1)
diff --git a/target/loongarch/internals.h b/target/loongarch/internals.h
index a2fc54c8a7..944153b180 100644
--- a/target/loongarch/internals.h
+++ b/target/loongarch/internals.h
@@ -16,11 +16,6 @@
 #define TARGET_PHYS_MASK MAKE_64BIT_MASK(0, TARGET_PHYS_ADDR_SPACE_BITS)
 #define TARGET_VIRT_MASK MAKE_64BIT_MASK(0, TARGET_VIRT_ADDR_SPACE_BITS)
 
-/* Global bit used for lddir/ldpte */
-#define LOONGARCH_PAGE_HUGE_SHIFT   6
-/* Global bit for huge page */
-#define LOONGARCH_HGLOBAL_SHIFT 12
-
 void loongarch_translate_init(void);
 
 void loongarch_cpu_dump_state(CPUState *cpu, FILE *f, int flags);
diff --git a/target/loongarch/tcg/tlb_helper.c 
b/target/loongarch/tcg/tlb_helper.c
index 22be031ac7..57f5308632 100644
--- a/target/loongarch/tcg/tlb_helper.c
+++ b/target/loongarch/tcg/tlb_helper.c
@@ -17,6 +17,34 @@
 #include "exec/log.h"
 #include "cpu-csr.h"
 
+static void get_dir_base_width(CPULoongArchState *env, uint64_t *dir_base,
+   uint64_t *dir_width, target_ulong level)
+{
+switch (level) {
+case 1:
+*dir_base = FIELD_EX64(env->CSR_PWCL, CSR_PWCL, DIR1_BASE);
+*dir_width = FIELD_EX64(env->CSR_PWCL, CSR_PWCL, DIR1_WIDTH);
+break;
+case 2:
+*dir_base = FIELD_EX64(env->CSR_PWCL, CSR_PWCL, DIR2_BASE);
+*dir_width = FIELD_EX64(env->CSR_PWCL, CSR_PWCL, DIR2_WIDTH);
+break;
+case 3:
+*dir_base = FIELD_EX64(env->CSR_PWCH, CSR_PWCH, DIR3_BASE);
+*dir_width = FIELD_EX64(env->CSR_PWCH, CSR_PWCH, DIR3_WIDTH);
+break;
+case 4:
+*dir_base = FIELD_EX64(env->CSR_PWCH, CSR_PWCH, DIR4_BASE);
+*dir_width = FIELD_EX64(env->CSR_PWCH, CSR_PWCH, DIR4_WIDTH);
+break;
+default:
+/* level may be zero for ldpte */
+*dir_base = FIELD_EX64(env->CSR_PWCL, CSR_PWCL, PTBASE);
+*dir_width = FIELD_EX64(env->CSR_PWCL, CSR_PWCL, PTWIDTH);
+break;
+}
+}
+
 static void raise_mmu_exception(CPULoongArchState *env, target_ulong address,
 MMUAccessType access_type, int tlb_error)
 {
@@ -485,7 +513,25 @@ target_ulong helper_lddir(CPULoongArchState *env, 
target_ulong base,
 target_ulong badvaddr, index, phys, ret;
 int shift;
 uint64_t dir_base, dir_width;
-bool huge = (base >> LOONGARCH_PAGE_HUGE_SHIFT) & 0x1;
+
+if (unlikely((level == 0) || (level > 4))) {
+qemu_log_mask(LOG_GUEST_ERROR,
+  "Attepted LDDIR with level %"PRId64"\n", level);
+return base;
+}
+
+if (FIELD_EX64(base, TLBENTRY, HUGE)) {
+if (unlikely(level == 4)) {
+qemu_log_mask(LOG_GUEST_ERROR,
+  "Attempted use of level 4 huge page\n");
+}
+
+if (FIELD_EX64(base, TLBENTRY, LEVEL)) {
+return base;
+} else {
+return FIELD_DP64(base, TLBENTRY, LEVEL, level);
+}
+}
 
 badvaddr = env->CSR_TLBRBADV;
 base = base & TARGET_PHYS_MASK;
@@ -494,30 +540,7 @@ target_ulong helper_lddir(CPULoongArchState *env, 
target_ulong base,
 shift = FIELD_EX64(env->CS

[PATCH V5] target/loongarch: Fix tlb huge page loading issue

2024-03-15 Thread Xianglai Li
When we use qemu tcg simulation, the page size of bios is 4KB.
When using the level 2 super huge page (page size is 1G) to create the page 
table,
it is found that the content of the corresponding address space is abnormal,
resulting in the bios can not start the operating system and graphical 
interface normally.

The lddir and ldpte instruction emulation has
a problem with the use of super huge page processing above level 2.
The page size is not correctly calculated,
resulting in the wrong page size of the table entry found by tlb.

Signed-off-by: Xianglai Li 
---
 target/loongarch/cpu-csr.h|   3 +
 target/loongarch/internals.h  |   5 --
 target/loongarch/tcg/tlb_helper.c | 111 +-
 3 files changed, 80 insertions(+), 39 deletions(-)

Changes log:
V4->V5:
Modifying the patch Title.
Fix incorrect usage of FIELD macro and code logic errors in patch.

V3->V4:
Optimize the huge page calculation method,
use the FIELD macro for bit calculation.

V2->V3:
Delete the intermediate variable LDDIR_PS, and implement lddir and ldpte
huge pages by referring to the latest architecture reference manual.

V1->V2:
Modified the patch title format and Enrich the commit mesg description

diff --git a/target/loongarch/cpu-csr.h b/target/loongarch/cpu-csr.h
index c59d7a9fcb..0834e91f30 100644
--- a/target/loongarch/cpu-csr.h
+++ b/target/loongarch/cpu-csr.h
@@ -67,6 +67,9 @@ FIELD(TLBENTRY, D, 1, 1)
 FIELD(TLBENTRY, PLV, 2, 2)
 FIELD(TLBENTRY, MAT, 4, 2)
 FIELD(TLBENTRY, G, 6, 1)
+FIELD(TLBENTRY, HUGE, 6, 1)
+FIELD(TLBENTRY, HGLOBAL, 12, 1)
+FIELD(TLBENTRY, LEVEL, 13, 2)
 FIELD(TLBENTRY_32, PPN, 8, 24)
 FIELD(TLBENTRY_64, PPN, 12, 36)
 FIELD(TLBENTRY_64, NR, 61, 1)
diff --git a/target/loongarch/internals.h b/target/loongarch/internals.h
index a2fc54c8a7..944153b180 100644
--- a/target/loongarch/internals.h
+++ b/target/loongarch/internals.h
@@ -16,11 +16,6 @@
 #define TARGET_PHYS_MASK MAKE_64BIT_MASK(0, TARGET_PHYS_ADDR_SPACE_BITS)
 #define TARGET_VIRT_MASK MAKE_64BIT_MASK(0, TARGET_VIRT_ADDR_SPACE_BITS)
 
-/* Global bit used for lddir/ldpte */
-#define LOONGARCH_PAGE_HUGE_SHIFT   6
-/* Global bit for huge page */
-#define LOONGARCH_HGLOBAL_SHIFT 12
-
 void loongarch_translate_init(void);
 
 void loongarch_cpu_dump_state(CPUState *cpu, FILE *f, int flags);
diff --git a/target/loongarch/tcg/tlb_helper.c 
b/target/loongarch/tcg/tlb_helper.c
index 22be031ac7..1d22afddd3 100644
--- a/target/loongarch/tcg/tlb_helper.c
+++ b/target/loongarch/tcg/tlb_helper.c
@@ -17,6 +17,34 @@
 #include "exec/log.h"
 #include "cpu-csr.h"
 
+static void get_dir_base_width(CPULoongArchState *env, uint64_t *dir_base,
+   uint64_t *dir_width, target_ulong level)
+{
+switch (level) {
+case 1:
+*dir_base = FIELD_EX64(env->CSR_PWCL, CSR_PWCL, DIR1_BASE);
+*dir_width = FIELD_EX64(env->CSR_PWCL, CSR_PWCL, DIR1_WIDTH);
+break;
+case 2:
+*dir_base = FIELD_EX64(env->CSR_PWCL, CSR_PWCL, DIR2_BASE);
+*dir_width = FIELD_EX64(env->CSR_PWCL, CSR_PWCL, DIR2_WIDTH);
+break;
+case 3:
+*dir_base = FIELD_EX64(env->CSR_PWCH, CSR_PWCH, DIR3_BASE);
+*dir_width = FIELD_EX64(env->CSR_PWCH, CSR_PWCH, DIR3_WIDTH);
+break;
+case 4:
+*dir_base = FIELD_EX64(env->CSR_PWCH, CSR_PWCH, DIR4_BASE);
+*dir_width = FIELD_EX64(env->CSR_PWCH, CSR_PWCH, DIR4_WIDTH);
+break;
+default:
+/* level may be zero for ldpte */
+*dir_base = FIELD_EX64(env->CSR_PWCL, CSR_PWCL, PTBASE);
+*dir_width = FIELD_EX64(env->CSR_PWCL, CSR_PWCL, PTWIDTH);
+break;
+}
+}
+
 static void raise_mmu_exception(CPULoongArchState *env, target_ulong address,
 MMUAccessType access_type, int tlb_error)
 {
@@ -485,7 +513,23 @@ target_ulong helper_lddir(CPULoongArchState *env, 
target_ulong base,
 target_ulong badvaddr, index, phys, ret;
 int shift;
 uint64_t dir_base, dir_width;
-bool huge = (base >> LOONGARCH_PAGE_HUGE_SHIFT) & 0x1;
+
+if (unlikely((level == 0) || (level > 4))) {
+return base;
+}
+
+if (FIELD_EX64(base, TLBENTRY, HUGE)) {
+if (unlikely(level == 4)) {
+qemu_log_mask(LOG_GUEST_ERROR,
+  "Attempted use of level %lu huge page\n", level);
+}
+
+if (FIELD_EX64(base, TLBENTRY, LEVEL)) {
+return base;
+} else {
+return FIELD_DP64(base, TLBENTRY, LEVEL, level);
+}
+}
 
 badvaddr = env->CSR_TLBRBADV;
 base = base & TARGET_PHYS_MASK;
@@ -494,30 +538,7 @@ target_ulong helper_lddir(CPULoongArchState *env, 
target_ulong base,
 shift = FIELD_EX64(env->CSR_PWCL, CSR_PWCL, PTEWIDTH);
 shift = (shift + 1) * 3;
 
-if (huge) {
-return base;
-}
-switch (level) {
-case 1:
-dir_base = FIELD_EX

[PATCH V4] target/loongarch: Fixed tlb huge page loading issue

2024-03-13 Thread Xianglai Li
When we use qemu tcg simulation, the page size of bios is 4KB.
When using the level 2 super large page (page size is 1G) to create the page 
table,
it is found that the content of the corresponding address space is abnormal,
resulting in the bios can not start the operating system and graphical 
interface normally.

The lddir and ldpte instruction emulation has
a problem with the use of super large page processing above level 2.
The page size is not correctly calculated,
resulting in the wrong page size of the table entry found by tlb.

Signed-off-by: Xianglai Li 
---
 target/loongarch/cpu-csr.h|   3 +
 target/loongarch/internals.h  |   5 --
 target/loongarch/tcg/tlb_helper.c | 105 --
 3 files changed, 74 insertions(+), 39 deletions(-)

Changes log:
V3->V4:
Optimize the huge page calculation method,
use the FIELD macro for bit calculation.

V2->V3:
Delete the intermediate variable LDDIR_PS, and implement lddir and ldpte
huge pages by referring to the latest architecture reference manual.

V1->V2:
Modified the patch title format and Enrich the commit mesg description

diff --git a/target/loongarch/cpu-csr.h b/target/loongarch/cpu-csr.h
index c59d7a9fcb..b0775cf6bf 100644
--- a/target/loongarch/cpu-csr.h
+++ b/target/loongarch/cpu-csr.h
@@ -67,6 +67,9 @@ FIELD(TLBENTRY, D, 1, 1)
 FIELD(TLBENTRY, PLV, 2, 2)
 FIELD(TLBENTRY, MAT, 4, 2)
 FIELD(TLBENTRY, G, 6, 1)
+FIELD(TLBENTRY, HUGE, 6, 1)
+FIELD(TLBENTRY, HG, 12, 1)
+FIELD(TLBENTRY, LEVEL, 13, 2)
 FIELD(TLBENTRY_32, PPN, 8, 24)
 FIELD(TLBENTRY_64, PPN, 12, 36)
 FIELD(TLBENTRY_64, NR, 61, 1)
diff --git a/target/loongarch/internals.h b/target/loongarch/internals.h
index a2fc54c8a7..944153b180 100644
--- a/target/loongarch/internals.h
+++ b/target/loongarch/internals.h
@@ -16,11 +16,6 @@
 #define TARGET_PHYS_MASK MAKE_64BIT_MASK(0, TARGET_PHYS_ADDR_SPACE_BITS)
 #define TARGET_VIRT_MASK MAKE_64BIT_MASK(0, TARGET_VIRT_ADDR_SPACE_BITS)
 
-/* Global bit used for lddir/ldpte */
-#define LOONGARCH_PAGE_HUGE_SHIFT   6
-/* Global bit for huge page */
-#define LOONGARCH_HGLOBAL_SHIFT 12
-
 void loongarch_translate_init(void);
 
 void loongarch_cpu_dump_state(CPUState *cpu, FILE *f, int flags);
diff --git a/target/loongarch/tcg/tlb_helper.c 
b/target/loongarch/tcg/tlb_helper.c
index 22be031ac7..b9a8633791 100644
--- a/target/loongarch/tcg/tlb_helper.c
+++ b/target/loongarch/tcg/tlb_helper.c
@@ -17,6 +17,34 @@
 #include "exec/log.h"
 #include "cpu-csr.h"
 
+static void get_dir_base_width(CPULoongArchState *env, uint64_t *dir_base,
+   uint64_t *dir_width, target_ulong level)
+{
+switch (level) {
+case 1:
+*dir_base = FIELD_EX64(env->CSR_PWCL, CSR_PWCL, DIR1_BASE);
+*dir_width = FIELD_EX64(env->CSR_PWCL, CSR_PWCL, DIR1_WIDTH);
+break;
+case 2:
+*dir_base = FIELD_EX64(env->CSR_PWCL, CSR_PWCL, DIR2_BASE);
+*dir_width = FIELD_EX64(env->CSR_PWCL, CSR_PWCL, DIR2_WIDTH);
+break;
+case 3:
+*dir_base = FIELD_EX64(env->CSR_PWCH, CSR_PWCH, DIR3_BASE);
+*dir_width = FIELD_EX64(env->CSR_PWCH, CSR_PWCH, DIR3_WIDTH);
+break;
+case 4:
+*dir_base = FIELD_EX64(env->CSR_PWCH, CSR_PWCH, DIR4_BASE);
+*dir_width = FIELD_EX64(env->CSR_PWCH, CSR_PWCH, DIR4_WIDTH);
+break;
+default:
+/* level may be zero for ldpte */
+*dir_base = FIELD_EX64(env->CSR_PWCL, CSR_PWCL, PTBASE);
+*dir_width = FIELD_EX64(env->CSR_PWCL, CSR_PWCL, PTWIDTH);
+break;
+}
+}
+
 static void raise_mmu_exception(CPULoongArchState *env, target_ulong address,
 MMUAccessType access_type, int tlb_error)
 {
@@ -485,7 +513,23 @@ target_ulong helper_lddir(CPULoongArchState *env, 
target_ulong base,
 target_ulong badvaddr, index, phys, ret;
 int shift;
 uint64_t dir_base, dir_width;
-bool huge = (base >> LOONGARCH_PAGE_HUGE_SHIFT) & 0x1;
+
+if (unlikely((level == 0) || (level > 4))) {
+return base;
+}
+
+if (FIELD_EX64(base, TLBENTRY, HUGE)) {
+if (FIELD_EX64(base, TLBENTRY, LEVEL)) {
+return base;
+} else {
+return  FIELD_DP64(base, TLBENTRY, LEVEL, level);
+}
+
+if (unlikely(level == 4)) {
+qemu_log_mask(LOG_GUEST_ERROR,
+  "Attempted use of level %lu huge page\n", level);
+}
+}
 
 badvaddr = env->CSR_TLBRBADV;
 base = base & TARGET_PHYS_MASK;
@@ -494,33 +538,12 @@ target_ulong helper_lddir(CPULoongArchState *env, 
target_ulong base,
 shift = FIELD_EX64(env->CSR_PWCL, CSR_PWCL, PTEWIDTH);
 shift = (shift + 1) * 3;
 
-if (huge) {
-return base;
-}
-switch (level) {
-case 1:
-dir_base = FIELD_EX64(env->CSR_PWCL, CSR_PWCL, DIR1_BASE);
-dir_width = FIELD_EX64(env->CSR_PWCL, CSR_PWCL, DIR1_WIDT

[PATCH V4 1/1] target/loongarch: Fixed tlb huge page loading issue

2024-03-13 Thread Xianglai Li
When we use qemu tcg simulation, the page size of bios is 4KB.
When using the level 2 super large page (page size is 1G) to create the page 
table,
it is found that the content of the corresponding address space is abnormal,
resulting in the bios can not start the operating system and graphical 
interface normally.

The lddir and ldpte instruction emulation has
a problem with the use of super large page processing above level 2.
The page size is not correctly calculated,
resulting in the wrong page size of the table entry found by tlb.

Cc: maob...@loongson.cn
Cc: Song Gao 
Cc: Xiaojuan Yang 
Cc: zhaotian...@loongson.cn
Cc: yi...@loongson.cn
Cc: wuruiy...@loongson.cn

Signed-off-by: Xianglai Li 
---
 target/loongarch/cpu-csr.h|   3 +
 target/loongarch/internals.h  |   5 --
 target/loongarch/tcg/tlb_helper.c | 105 --
 3 files changed, 74 insertions(+), 39 deletions(-)

Changes log:
V3->V4:
Optimize the huge page calculation method,
use the FIELD macro for bit calculation.

V2->V3:
Delete the intermediate variable LDDIR_PS, and implement lddir and ldpte
huge pages by referring to the latest architecture reference manual.

V1->V2:
Modified the patch title format and Enrich the commit mesg description

diff --git a/target/loongarch/cpu-csr.h b/target/loongarch/cpu-csr.h
index c59d7a9fcb..b0775cf6bf 100644
--- a/target/loongarch/cpu-csr.h
+++ b/target/loongarch/cpu-csr.h
@@ -67,6 +67,9 @@ FIELD(TLBENTRY, D, 1, 1)
 FIELD(TLBENTRY, PLV, 2, 2)
 FIELD(TLBENTRY, MAT, 4, 2)
 FIELD(TLBENTRY, G, 6, 1)
+FIELD(TLBENTRY, HUGE, 6, 1)
+FIELD(TLBENTRY, HG, 12, 1)
+FIELD(TLBENTRY, LEVEL, 13, 2)
 FIELD(TLBENTRY_32, PPN, 8, 24)
 FIELD(TLBENTRY_64, PPN, 12, 36)
 FIELD(TLBENTRY_64, NR, 61, 1)
diff --git a/target/loongarch/internals.h b/target/loongarch/internals.h
index a2fc54c8a7..944153b180 100644
--- a/target/loongarch/internals.h
+++ b/target/loongarch/internals.h
@@ -16,11 +16,6 @@
 #define TARGET_PHYS_MASK MAKE_64BIT_MASK(0, TARGET_PHYS_ADDR_SPACE_BITS)
 #define TARGET_VIRT_MASK MAKE_64BIT_MASK(0, TARGET_VIRT_ADDR_SPACE_BITS)
 
-/* Global bit used for lddir/ldpte */
-#define LOONGARCH_PAGE_HUGE_SHIFT   6
-/* Global bit for huge page */
-#define LOONGARCH_HGLOBAL_SHIFT 12
-
 void loongarch_translate_init(void);
 
 void loongarch_cpu_dump_state(CPUState *cpu, FILE *f, int flags);
diff --git a/target/loongarch/tcg/tlb_helper.c 
b/target/loongarch/tcg/tlb_helper.c
index 22be031ac7..b9a8633791 100644
--- a/target/loongarch/tcg/tlb_helper.c
+++ b/target/loongarch/tcg/tlb_helper.c
@@ -17,6 +17,34 @@
 #include "exec/log.h"
 #include "cpu-csr.h"
 
+static void get_dir_base_width(CPULoongArchState *env, uint64_t *dir_base,
+   uint64_t *dir_width, target_ulong level)
+{
+switch (level) {
+case 1:
+*dir_base = FIELD_EX64(env->CSR_PWCL, CSR_PWCL, DIR1_BASE);
+*dir_width = FIELD_EX64(env->CSR_PWCL, CSR_PWCL, DIR1_WIDTH);
+break;
+case 2:
+*dir_base = FIELD_EX64(env->CSR_PWCL, CSR_PWCL, DIR2_BASE);
+*dir_width = FIELD_EX64(env->CSR_PWCL, CSR_PWCL, DIR2_WIDTH);
+break;
+case 3:
+*dir_base = FIELD_EX64(env->CSR_PWCH, CSR_PWCH, DIR3_BASE);
+*dir_width = FIELD_EX64(env->CSR_PWCH, CSR_PWCH, DIR3_WIDTH);
+break;
+case 4:
+*dir_base = FIELD_EX64(env->CSR_PWCH, CSR_PWCH, DIR4_BASE);
+*dir_width = FIELD_EX64(env->CSR_PWCH, CSR_PWCH, DIR4_WIDTH);
+break;
+default:
+/* level may be zero for ldpte */
+*dir_base = FIELD_EX64(env->CSR_PWCL, CSR_PWCL, PTBASE);
+*dir_width = FIELD_EX64(env->CSR_PWCL, CSR_PWCL, PTWIDTH);
+break;
+}
+}
+
 static void raise_mmu_exception(CPULoongArchState *env, target_ulong address,
 MMUAccessType access_type, int tlb_error)
 {
@@ -485,7 +513,23 @@ target_ulong helper_lddir(CPULoongArchState *env, 
target_ulong base,
 target_ulong badvaddr, index, phys, ret;
 int shift;
 uint64_t dir_base, dir_width;
-bool huge = (base >> LOONGARCH_PAGE_HUGE_SHIFT) & 0x1;
+
+if (unlikely((level == 0) || (level > 4))) {
+return base;
+}
+
+if (FIELD_EX64(base, TLBENTRY, HUGE)) {
+if (FIELD_EX64(base, TLBENTRY, LEVEL)) {
+return base;
+} else {
+return  FIELD_DP64(base, TLBENTRY, LEVEL, level);
+}
+
+if (unlikely(level == 4)) {
+qemu_log_mask(LOG_GUEST_ERROR,
+  "Attempted use of level %lu huge page\n", level);
+}
+}
 
 badvaddr = env->CSR_TLBRBADV;
 base = base & TARGET_PHYS_MASK;
@@ -494,33 +538,12 @@ target_ulong helper_lddir(CPULoongArchState *env, 
target_ulong base,
 shift = FIELD_EX64(env->CSR_PWCL, CSR_PWCL, PTEWIDTH);
 shift = (shift + 1) * 3;
 
-if (huge) {
-return base;
-}
-switch (level) {
-case 1:
-  

[PATCH V3 1/1] target/loongarch: Fixed tlb huge page loading issue

2024-03-06 Thread Xianglai Li
When we use qemu tcg simulation, the page size of bios is 4KB.
When using the level 2 super large page (page size is 1G) to create the page 
table,
it is found that the content of the corresponding address space is abnormal,
resulting in the bios can not start the operating system and graphical 
interface normally.

The lddir and ldpte instruction emulation has
a problem with the use of super large page processing above level 2.
The page size is not correctly calculated,
resulting in the wrong page size of the table entry found by tlb.

Signed-off-by: Xianglai Li 
Cc: maob...@loongson.cn
Cc: Song Gao 
Cc: Xiaojuan Yang 
Cc: zhaotian...@loongson.cn
---
 target/loongarch/internals.h  |  8 +++
 target/loongarch/tcg/tlb_helper.c | 92 +++
 2 files changed, 76 insertions(+), 24 deletions(-)

diff --git a/target/loongarch/internals.h b/target/loongarch/internals.h
index a2fc54c8a7..55ceb4c079 100644
--- a/target/loongarch/internals.h
+++ b/target/loongarch/internals.h
@@ -16,6 +16,14 @@
 #define TARGET_PHYS_MASK MAKE_64BIT_MASK(0, TARGET_PHYS_ADDR_SPACE_BITS)
 #define TARGET_VIRT_MASK MAKE_64BIT_MASK(0, TARGET_VIRT_ADDR_SPACE_BITS)
 
+/*
+ * The [13..14]bits of the entry base address of the lddir/ldpte
+ * directive are used to represent the level of the large page
+ * when processing the huge page entry
+ */
+#define HUGE_PAGE_LEVEL_SHIFT   13
+#define HUGE_PAGE_LEVEL_MASK MAKE_64BIT_MASK(HUGE_PAGE_LEVEL_SHIFT, 2)
+
 /* Global bit used for lddir/ldpte */
 #define LOONGARCH_PAGE_HUGE_SHIFT   6
 /* Global bit for huge page */
diff --git a/target/loongarch/tcg/tlb_helper.c 
b/target/loongarch/tcg/tlb_helper.c
index a08c08b05a..2db77b48c5 100644
--- a/target/loongarch/tcg/tlb_helper.c
+++ b/target/loongarch/tcg/tlb_helper.c
@@ -17,6 +17,9 @@
 #include "exec/log.h"
 #include "cpu-csr.h"
 
+static int get_dir_base_width(CPULoongArchState *env, uint64_t *dir_base,
+  uint64_t *dir_width, target_ulong level);
+
 static void raise_mmu_exception(CPULoongArchState *env, target_ulong address,
 MMUAccessType access_type, int tlb_error)
 {
@@ -487,6 +490,16 @@ target_ulong helper_lddir(CPULoongArchState *env, 
target_ulong base,
 int shift;
 uint64_t dir_base, dir_width;
 bool huge = (base >> LOONGARCH_PAGE_HUGE_SHIFT) & 0x1;
+uint64_t huge_page_level = base & HUGE_PAGE_LEVEL_MASK;
+
+if (huge) {
+if (huge_page_level) {
+return base;
+} else {
+huge_page_level = (level & 0x3) << HUGE_PAGE_LEVEL_SHIFT;
+return base | huge_page_level;
+}
+}
 
 badvaddr = env->CSR_TLBRBADV;
 base = base & TARGET_PHYS_MASK;
@@ -495,30 +508,10 @@ target_ulong helper_lddir(CPULoongArchState *env, 
target_ulong base,
 shift = FIELD_EX64(env->CSR_PWCL, CSR_PWCL, PTEWIDTH);
 shift = (shift + 1) * 3;
 
-if (huge) {
-return base;
-}
-switch (level) {
-case 1:
-dir_base = FIELD_EX64(env->CSR_PWCL, CSR_PWCL, DIR1_BASE);
-dir_width = FIELD_EX64(env->CSR_PWCL, CSR_PWCL, DIR1_WIDTH);
-break;
-case 2:
-dir_base = FIELD_EX64(env->CSR_PWCL, CSR_PWCL, DIR2_BASE);
-dir_width = FIELD_EX64(env->CSR_PWCL, CSR_PWCL, DIR2_WIDTH);
-break;
-case 3:
-dir_base = FIELD_EX64(env->CSR_PWCH, CSR_PWCH, DIR3_BASE);
-dir_width = FIELD_EX64(env->CSR_PWCH, CSR_PWCH, DIR3_WIDTH);
-break;
-case 4:
-dir_base = FIELD_EX64(env->CSR_PWCH, CSR_PWCH, DIR4_BASE);
-dir_width = FIELD_EX64(env->CSR_PWCH, CSR_PWCH, DIR4_WIDTH);
-break;
-default:
-do_raise_exception(env, EXCCODE_INE, GETPC());
+if (get_dir_base_width(env, _base, _width, level) != 0) {
 return 0;
 }
+
 index = (badvaddr >> dir_base) & ((1 << dir_width) - 1);
 phys = base | index << shift;
 ret = ldq_phys(cs->as, phys) & TARGET_PHYS_MASK;
@@ -534,17 +527,38 @@ void helper_ldpte(CPULoongArchState *env, target_ulong 
base, target_ulong odd,
 bool huge = (base >> LOONGARCH_PAGE_HUGE_SHIFT) & 0x1;
 uint64_t ptbase = FIELD_EX64(env->CSR_PWCL, CSR_PWCL, PTBASE);
 uint64_t ptwidth = FIELD_EX64(env->CSR_PWCL, CSR_PWCL, PTWIDTH);
+uint64_t dir_base, dir_width;
+uint64_t huge_page_level;
 
 base = base & TARGET_PHYS_MASK;
 
 if (huge) {
-/* Huge Page. base is paddr */
+/*
+ * Gets the huge page level
+ * Clears the huge page level information in the address
+ * Clears huge page bit
+ * Gets huge page size
+ */
+huge_page_level = (base & HUGE_PAGE_LEVEL_MASK) >>
+  HUGE_PAGE_LEVEL_SHIFT;
+
+base &= ~HUGE_PAGE_LEVEL_MASK;
+
 tmp0 = base ^ (1 << LOONGARCH_PAGE_HUGE_SHIFT);
 /* Move Global bit */
  

[PATCH V3 0/1] target/loongarch: Fixed tlb huge page loading issue

2024-03-06 Thread Xianglai Li
When we use qemu tcg simulation, the page size of bios is 4KB.
When using the level 2 super large page (page size is 1G) to create the page 
table,
it is found that the content of the corresponding address space is abnormal,
resulting in the bios can not start the operating system and graphical 
interface normally.

The lddir and ldpte instruction emulation has
a problem with the use of super large page processing above level 2.
The page size is not correctly calculated,
resulting in the wrong page size of the table entry found by tlb.

Changes log:
V2->V3:
Delete the intermediate variable LDDIR_PS, and implement lddir and ldpte
huge pages by referring to the latest architecture reference manual.

V1->V2:
Modified the patch title format and Enrich the commit mesg description

Cc: maob...@loongson.cn
Cc: Song Gao 
Cc: Xiaojuan Yang 
Cc: zhaotian...@loongson.cn

Xianglai Li (1):
  target/loongarch: Fixed tlb huge page loading issue

 target/loongarch/internals.h  |  8 +++
 target/loongarch/tcg/tlb_helper.c | 92 +++
 2 files changed, 76 insertions(+), 24 deletions(-)

-- 
2.39.1




[PATCH V2 0/1] target/loongarch: Fixed tlb huge page loading issue

2024-03-04 Thread Xianglai Li
When we use qemu tcg simulation, the page size of bios is 4KB.
When using the level 2 super large page (page size is 1G) to create the page 
table,
it is found that the content of the corresponding address space is abnormal,
resulting in the bios can not start the operating system and graphical 
interface normally.

The lddir and ldpte instruction emulation has
a problem with the use of super large page processing above level 2.
The page size is not correctly calculated,
resulting in the wrong page size of the table entry found by tlb.

Changes log:
V1->V2:
Modified the patch title format and Enrich the commit mesg description

Cc: maob...@loongson.cn
Cc: Song Gao 
Cc: Xiaojuan Yang 
Cc: zhaotian...@loongson.cn

Xianglai Li (1):
  target/loongarch: Fixed tlb huge page loading issue

 target/loongarch/cpu.h|  1 +
 target/loongarch/tcg/tlb_helper.c | 21 -
 2 files changed, 13 insertions(+), 9 deletions(-)

-- 
2.39.1




[PATCH V2 1/1] target/loongarch: Fixed tlb huge page loading issue

2024-03-04 Thread Xianglai Li
When we use qemu tcg simulation, the page size of bios is 4KB.
When using the level 2 super large page (page size is 1G) to create the page 
table,
it is found that the content of the corresponding address space is abnormal,
resulting in the bios can not start the operating system and graphical 
interface normally.

The lddir and ldpte instruction emulation has
a problem with the use of super large page processing above level 2.
The page size is not correctly calculated,
resulting in the wrong page size of the table entry found by tlb.

Signed-off-by: Xianglai Li 
Cc: maob...@loongson.cn
Cc: Song Gao 
Cc: Xiaojuan Yang 
Cc: zhaotian...@loongson.cn
---
 target/loongarch/cpu.h|  1 +
 target/loongarch/tcg/tlb_helper.c | 21 -
 2 files changed, 13 insertions(+), 9 deletions(-)

diff --git a/target/loongarch/cpu.h b/target/loongarch/cpu.h
index ec37579fd6..eab3e41c71 100644
--- a/target/loongarch/cpu.h
+++ b/target/loongarch/cpu.h
@@ -292,6 +292,7 @@ typedef struct CPUArchState {
 uint32_t fcsr0_mask;
 
 uint32_t cpucfg[21];
+uint32_t lddir_ps;
 
 uint64_t lladdr; /* LL virtual address compared against SC */
 uint64_t llval;
diff --git a/target/loongarch/tcg/tlb_helper.c 
b/target/loongarch/tcg/tlb_helper.c
index a08c08b05a..3594c800b3 100644
--- a/target/loongarch/tcg/tlb_helper.c
+++ b/target/loongarch/tcg/tlb_helper.c
@@ -38,6 +38,7 @@ static void raise_mmu_exception(CPULoongArchState *env, 
target_ulong address,
 cs->exception_index = EXCCODE_PIF;
 }
 env->CSR_TLBRERA = FIELD_DP64(env->CSR_TLBRERA, CSR_TLBRERA, ISTLBR, 
1);
+env->lddir_ps = 0;
 break;
 case TLBRET_INVALID:
 /* TLB match with no valid bit */
@@ -488,13 +489,6 @@ target_ulong helper_lddir(CPULoongArchState *env, 
target_ulong base,
 uint64_t dir_base, dir_width;
 bool huge = (base >> LOONGARCH_PAGE_HUGE_SHIFT) & 0x1;
 
-badvaddr = env->CSR_TLBRBADV;
-base = base & TARGET_PHYS_MASK;
-
-/* 0:64bit, 1:128bit, 2:192bit, 3:256bit */
-shift = FIELD_EX64(env->CSR_PWCL, CSR_PWCL, PTEWIDTH);
-shift = (shift + 1) * 3;
-
 if (huge) {
 return base;
 }
@@ -519,9 +513,18 @@ target_ulong helper_lddir(CPULoongArchState *env, 
target_ulong base,
 do_raise_exception(env, EXCCODE_INE, GETPC());
 return 0;
 }
+
+/* 0:64bit, 1:128bit, 2:192bit, 3:256bit */
+shift = FIELD_EX64(env->CSR_PWCL, CSR_PWCL, PTEWIDTH);
+shift = (shift + 1) * 3;
+badvaddr = env->CSR_TLBRBADV;
+base = base & TARGET_PHYS_MASK;
 index = (badvaddr >> dir_base) & ((1 << dir_width) - 1);
 phys = base | index << shift;
 ret = ldq_phys(cs->as, phys) & TARGET_PHYS_MASK;
+if (ret & BIT_ULL(LOONGARCH_PAGE_HUGE_SHIFT)) {
+env->lddir_ps = dir_base;
+}
 return ret;
 }
 
@@ -538,13 +541,13 @@ void helper_ldpte(CPULoongArchState *env, target_ulong 
base, target_ulong odd,
 base = base & TARGET_PHYS_MASK;
 
 if (huge) {
-/* Huge Page. base is paddr */
 tmp0 = base ^ (1 << LOONGARCH_PAGE_HUGE_SHIFT);
 /* Move Global bit */
 tmp0 = ((tmp0 & (1 << LOONGARCH_HGLOBAL_SHIFT))  >>
 LOONGARCH_HGLOBAL_SHIFT) << R_TLBENTRY_G_SHIFT |
 (tmp0 & (~(1 << LOONGARCH_HGLOBAL_SHIFT)));
-ps = ptbase + ptwidth - 1;
+
+ps = env->lddir_ps - 1;
 if (odd) {
 tmp0 += MAKE_64BIT_MASK(ps, 1);
 }
-- 
2.39.1




[PATCH] Fixed tlb huge page loading issue

2024-02-27 Thread Xianglai Li
The lddir and ldpte instruction emulation has
a problem with the use of large page processing above level 2.
The page size is not correctly calculated,
resulting in the wrong page size of the table entry found by tlb.

Signed-off-by: Xianglai Li 
---
 target/loongarch/cpu.h|  1 +
 target/loongarch/tcg/tlb_helper.c | 21 -
 2 files changed, 13 insertions(+), 9 deletions(-)

diff --git a/target/loongarch/cpu.h b/target/loongarch/cpu.h
index ec37579fd6..eab3e41c71 100644
--- a/target/loongarch/cpu.h
+++ b/target/loongarch/cpu.h
@@ -292,6 +292,7 @@ typedef struct CPUArchState {
 uint32_t fcsr0_mask;
 
 uint32_t cpucfg[21];
+uint32_t lddir_ps;
 
 uint64_t lladdr; /* LL virtual address compared against SC */
 uint64_t llval;
diff --git a/target/loongarch/tcg/tlb_helper.c 
b/target/loongarch/tcg/tlb_helper.c
index a08c08b05a..3594c800b3 100644
--- a/target/loongarch/tcg/tlb_helper.c
+++ b/target/loongarch/tcg/tlb_helper.c
@@ -38,6 +38,7 @@ static void raise_mmu_exception(CPULoongArchState *env, 
target_ulong address,
 cs->exception_index = EXCCODE_PIF;
 }
 env->CSR_TLBRERA = FIELD_DP64(env->CSR_TLBRERA, CSR_TLBRERA, ISTLBR, 
1);
+env->lddir_ps = 0;
 break;
 case TLBRET_INVALID:
 /* TLB match with no valid bit */
@@ -488,13 +489,6 @@ target_ulong helper_lddir(CPULoongArchState *env, 
target_ulong base,
 uint64_t dir_base, dir_width;
 bool huge = (base >> LOONGARCH_PAGE_HUGE_SHIFT) & 0x1;
 
-badvaddr = env->CSR_TLBRBADV;
-base = base & TARGET_PHYS_MASK;
-
-/* 0:64bit, 1:128bit, 2:192bit, 3:256bit */
-shift = FIELD_EX64(env->CSR_PWCL, CSR_PWCL, PTEWIDTH);
-shift = (shift + 1) * 3;
-
 if (huge) {
 return base;
 }
@@ -519,9 +513,18 @@ target_ulong helper_lddir(CPULoongArchState *env, 
target_ulong base,
 do_raise_exception(env, EXCCODE_INE, GETPC());
 return 0;
 }
+
+/* 0:64bit, 1:128bit, 2:192bit, 3:256bit */
+shift = FIELD_EX64(env->CSR_PWCL, CSR_PWCL, PTEWIDTH);
+shift = (shift + 1) * 3;
+badvaddr = env->CSR_TLBRBADV;
+base = base & TARGET_PHYS_MASK;
 index = (badvaddr >> dir_base) & ((1 << dir_width) - 1);
 phys = base | index << shift;
 ret = ldq_phys(cs->as, phys) & TARGET_PHYS_MASK;
+if (ret & BIT_ULL(LOONGARCH_PAGE_HUGE_SHIFT)) {
+env->lddir_ps = dir_base;
+}
 return ret;
 }
 
@@ -538,13 +541,13 @@ void helper_ldpte(CPULoongArchState *env, target_ulong 
base, target_ulong odd,
 base = base & TARGET_PHYS_MASK;
 
 if (huge) {
-/* Huge Page. base is paddr */
 tmp0 = base ^ (1 << LOONGARCH_PAGE_HUGE_SHIFT);
 /* Move Global bit */
 tmp0 = ((tmp0 & (1 << LOONGARCH_HGLOBAL_SHIFT))  >>
 LOONGARCH_HGLOBAL_SHIFT) << R_TLBENTRY_G_SHIFT |
 (tmp0 & (~(1 << LOONGARCH_HGLOBAL_SHIFT)));
-ps = ptbase + ptwidth - 1;
+
+ps = env->lddir_ps - 1;
 if (odd) {
 tmp0 += MAKE_64BIT_MASK(ps, 1);
 }
-- 
2.39.1




[PATCH V2 1/1] loongarch: Change the UEFI loading mode to loongarch

2024-02-19 Thread Xianglai Li
The UEFI loading mode in loongarch is very different
from that in other architectures:loongarch's UEFI code
is in rom, while other architectures' UEFI code is in flash.

loongarch UEFI can be loaded as follows:
-machine virt,pflash=pflash0-format
-bios ./QEMU_EFI.fd

Other architectures load UEFI using the following methods:
-machine virt,pflash0=pflash0-format,pflash1=pflash1-format

loongarch's UEFI loading method makes qemu and libvirt incompatible
when using NVRAM, and the cost of loongarch's current loading method
far outweighs the benefits, so we decided to use the same UEFI loading
scheme as other architectures.

Cc: Andrea Bolognani 
Cc: maob...@loongson.cn
Cc: Philippe Mathieu-Daudé 
Cc: Song Gao 
Cc: zhaotian...@loongson.cn
Signed-off-by: Xianglai Li 
Tested-by: Andrea Bolognani 
---
 hw/loongarch/acpi-build.c   |  29 +--
 hw/loongarch/virt.c | 101 ++--
 include/hw/loongarch/virt.h |  10 ++--
 3 files changed, 107 insertions(+), 33 deletions(-)

diff --git a/hw/loongarch/acpi-build.c b/hw/loongarch/acpi-build.c
index a1c4198741..6c75f216ea 100644
--- a/hw/loongarch/acpi-build.c
+++ b/hw/loongarch/acpi-build.c
@@ -314,16 +314,39 @@ static void build_pci_device_aml(Aml *scope, 
LoongArchMachineState *lams)
 static void build_flash_aml(Aml *scope, LoongArchMachineState *lams)
 {
 Aml *dev, *crs;
+MemoryRegion *flash_mem;
 
-hwaddr flash_base = VIRT_FLASH_BASE;
-hwaddr flash_size = VIRT_FLASH_SIZE;
+hwaddr flash0_base;
+hwaddr flash0_size;
+
+hwaddr flash1_base;
+hwaddr flash1_size;
+
+flash_mem = pflash_cfi01_get_memory(lams->flash[0]);
+flash0_base = flash_mem->addr;
+flash0_size = flash_mem->size;
+
+flash_mem = pflash_cfi01_get_memory(lams->flash[1]);
+flash1_base = flash_mem->addr;
+flash1_size = flash_mem->size;
 
 dev = aml_device("FLS0");
 aml_append(dev, aml_name_decl("_HID", aml_string("LNRO0015")));
 aml_append(dev, aml_name_decl("_UID", aml_int(0)));
 
 crs = aml_resource_template();
-aml_append(crs, aml_memory32_fixed(flash_base, flash_size, 
AML_READ_WRITE));
+aml_append(crs, aml_memory32_fixed(flash0_base, flash0_size,
+   AML_READ_WRITE));
+aml_append(dev, aml_name_decl("_CRS", crs));
+aml_append(scope, dev);
+
+dev = aml_device("FLS1");
+aml_append(dev, aml_name_decl("_HID", aml_string("LNRO0015")));
+aml_append(dev, aml_name_decl("_UID", aml_int(1)));
+
+crs = aml_resource_template();
+aml_append(crs, aml_memory32_fixed(flash1_base, flash1_size,
+   AML_READ_WRITE));
 aml_append(dev, aml_name_decl("_CRS", crs));
 aml_append(scope, dev);
 }
diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c
index 0ad7d8c887..a7b9199e70 100644
--- a/hw/loongarch/virt.c
+++ b/hw/loongarch/virt.c
@@ -54,7 +54,9 @@ struct loaderparams {
 const char *initrd_filename;
 };
 
-static void virt_flash_create(LoongArchMachineState *lams)
+static PFlashCFI01 *virt_flash_create1(LoongArchMachineState *lams,
+   const char *name,
+   const char *alias_prop_name)
 {
 DeviceState *dev = qdev_new(TYPE_PFLASH_CFI01);
 
@@ -66,45 +68,78 @@ static void virt_flash_create(LoongArchMachineState *lams)
 qdev_prop_set_uint16(dev, "id1", 0x18);
 qdev_prop_set_uint16(dev, "id2", 0x00);
 qdev_prop_set_uint16(dev, "id3", 0x00);
-qdev_prop_set_string(dev, "name", "virt.flash");
-object_property_add_child(OBJECT(lams), "virt.flash", OBJECT(dev));
-object_property_add_alias(OBJECT(lams), "pflash",
+qdev_prop_set_string(dev, "name", name);
+object_property_add_child(OBJECT(lams), name, OBJECT(dev));
+object_property_add_alias(OBJECT(lams), alias_prop_name,
   OBJECT(dev), "drive");
+return PFLASH_CFI01(dev);
+}
 
-lams->flash = PFLASH_CFI01(dev);
+static void virt_flash_create(LoongArchMachineState *lams)
+{
+lams->flash[0] = virt_flash_create1(lams, "virt.flash0", "pflash0");
+lams->flash[1] = virt_flash_create1(lams, "virt.flash1", "pflash1");
 }
 
-static void virt_flash_map(LoongArchMachineState *lams,
-   MemoryRegion *sysmem)
+static void virt_flash_map1(PFlashCFI01 *flash,
+hwaddr base, hwaddr size,
+MemoryRegion *sysmem)
 {
-PFlashCFI01 *flash = lams->flash;
 DeviceState *dev = DEVICE(flash);
-hwaddr base = VIRT_FLASH_BASE;
-hwaddr size = VIRT_FLASH_SIZE;
+BlockBackend *blk;
+hwaddr real_size = size;
+
+blk = pflash_cfi01_get_blk(flash);
+if (b

[PATCH V2 0/1] Change the UEFI loading mode to loongarch

2024-02-19 Thread Xianglai Li
The UEFI loading mode in loongarch is very different
from that in other architectures:loongarch's UEFI code
is in rom, while other architectures' UEFI code is in flash.

loongarch UEFI can be loaded as follows:
-machine virt,pflash=pflash0-format
-bios ./QEMU_EFI.fd

Other architectures load UEFI using the following methods:
-machine virt,pflash0=pflash0-format,pflash1=pflash1-format

loongarch's UEFI loading method makes qemu and libvirt incompatible
when using NVRAM, and the cost of loongarch's current loading method
far outweighs the benefits, so we decided to use the same UEFI loading
scheme as other architectures.

V2:
Change the size of flash0 from 4M to 16M
Add test-by

Cc: Andrea Bolognani 
Cc: maob...@loongson.cn
Cc: Philippe Mathieu-Daudé 
Cc: Song Gao 
Cc: zhaotian...@loongson.cn

Xianglai Li (1):
  loongarch: Change the UEFI loading mode to loongarch

 hw/loongarch/acpi-build.c   |  29 +--
 hw/loongarch/virt.c | 101 ++--
 include/hw/loongarch/virt.h |  10 ++--
 3 files changed, 107 insertions(+), 33 deletions(-)

-- 
2.39.1




[PATCH V2] loongarch: Change the UEFI loading mode to loongarch

2024-02-05 Thread Xianglai Li
The UEFI loading mode in loongarch is very different
from that in other architectures:loongarch's UEFI code
is in rom, while other architectures' UEFI code is in flash.

loongarch UEFI can be loaded as follows:
-machine virt,pflash=pflash0-format
-bios ./QEMU_EFI.fd

Other architectures load UEFI using the following methods:
-machine virt,pflash0=pflash0-format,pflash1=pflash1-format

loongarch's UEFI loading method makes qemu and libvirt incompatible
when using NVRAM, and the cost of loongarch's current loading method
far outweighs the benefits, so we decided to use the same UEFI loading
scheme as other architectures.

Cc: Andrea Bolognani 
Cc: maob...@loongson.cn
Cc: Philippe Mathieu-Daudé 
Cc: Song Gao 
Cc: zhaotian...@loongson.cn
Signed-off-by: Xianglai Li 
---
 hw/loongarch/acpi-build.c   |  29 +--
 hw/loongarch/virt.c | 101 ++--
 include/hw/loongarch/virt.h |  10 ++--
 3 files changed, 107 insertions(+), 33 deletions(-)

diff --git a/hw/loongarch/acpi-build.c b/hw/loongarch/acpi-build.c
index a1c4198741..6c75f216ea 100644
--- a/hw/loongarch/acpi-build.c
+++ b/hw/loongarch/acpi-build.c
@@ -314,16 +314,39 @@ static void build_pci_device_aml(Aml *scope, 
LoongArchMachineState *lams)
 static void build_flash_aml(Aml *scope, LoongArchMachineState *lams)
 {
 Aml *dev, *crs;
+MemoryRegion *flash_mem;
 
-hwaddr flash_base = VIRT_FLASH_BASE;
-hwaddr flash_size = VIRT_FLASH_SIZE;
+hwaddr flash0_base;
+hwaddr flash0_size;
+
+hwaddr flash1_base;
+hwaddr flash1_size;
+
+flash_mem = pflash_cfi01_get_memory(lams->flash[0]);
+flash0_base = flash_mem->addr;
+flash0_size = flash_mem->size;
+
+flash_mem = pflash_cfi01_get_memory(lams->flash[1]);
+flash1_base = flash_mem->addr;
+flash1_size = flash_mem->size;
 
 dev = aml_device("FLS0");
 aml_append(dev, aml_name_decl("_HID", aml_string("LNRO0015")));
 aml_append(dev, aml_name_decl("_UID", aml_int(0)));
 
 crs = aml_resource_template();
-aml_append(crs, aml_memory32_fixed(flash_base, flash_size, 
AML_READ_WRITE));
+aml_append(crs, aml_memory32_fixed(flash0_base, flash0_size,
+   AML_READ_WRITE));
+aml_append(dev, aml_name_decl("_CRS", crs));
+aml_append(scope, dev);
+
+dev = aml_device("FLS1");
+aml_append(dev, aml_name_decl("_HID", aml_string("LNRO0015")));
+aml_append(dev, aml_name_decl("_UID", aml_int(1)));
+
+crs = aml_resource_template();
+aml_append(crs, aml_memory32_fixed(flash1_base, flash1_size,
+   AML_READ_WRITE));
 aml_append(dev, aml_name_decl("_CRS", crs));
 aml_append(scope, dev);
 }
diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c
index 0ad7d8c887..a7b9199e70 100644
--- a/hw/loongarch/virt.c
+++ b/hw/loongarch/virt.c
@@ -54,7 +54,9 @@ struct loaderparams {
 const char *initrd_filename;
 };
 
-static void virt_flash_create(LoongArchMachineState *lams)
+static PFlashCFI01 *virt_flash_create1(LoongArchMachineState *lams,
+   const char *name,
+   const char *alias_prop_name)
 {
 DeviceState *dev = qdev_new(TYPE_PFLASH_CFI01);
 
@@ -66,45 +68,78 @@ static void virt_flash_create(LoongArchMachineState *lams)
 qdev_prop_set_uint16(dev, "id1", 0x18);
 qdev_prop_set_uint16(dev, "id2", 0x00);
 qdev_prop_set_uint16(dev, "id3", 0x00);
-qdev_prop_set_string(dev, "name", "virt.flash");
-object_property_add_child(OBJECT(lams), "virt.flash", OBJECT(dev));
-object_property_add_alias(OBJECT(lams), "pflash",
+qdev_prop_set_string(dev, "name", name);
+object_property_add_child(OBJECT(lams), name, OBJECT(dev));
+object_property_add_alias(OBJECT(lams), alias_prop_name,
   OBJECT(dev), "drive");
+return PFLASH_CFI01(dev);
+}
 
-lams->flash = PFLASH_CFI01(dev);
+static void virt_flash_create(LoongArchMachineState *lams)
+{
+lams->flash[0] = virt_flash_create1(lams, "virt.flash0", "pflash0");
+lams->flash[1] = virt_flash_create1(lams, "virt.flash1", "pflash1");
 }
 
-static void virt_flash_map(LoongArchMachineState *lams,
-   MemoryRegion *sysmem)
+static void virt_flash_map1(PFlashCFI01 *flash,
+hwaddr base, hwaddr size,
+MemoryRegion *sysmem)
 {
-PFlashCFI01 *flash = lams->flash;
 DeviceState *dev = DEVICE(flash);
-hwaddr base = VIRT_FLASH_BASE;
-hwaddr size = VIRT_FLASH_SIZE;
+BlockBackend *blk;
+hwaddr real_size = size;
+
+blk = pflash_cfi01_get_blk(flash);
+if (blk) {
+real_size = blk_getlength(blk);
+ 

[PATCH] loongarch: Change the UEFI loading mode to loongarch

2024-02-03 Thread Xianglai Li
The UEFI loading mode in loongarch is very different
from that in other architectures:loongarch's UEFI code
is in rom, while other architectures' UEFI code is in flash.

loongarch UEFI can be loaded as follows:
-machine virt,pflash=pflash0-format
-bios ./QEMU_EFI.fd

Other architectures load UEFI using the following methods:
-machine virt,pflash0=pflash0-format,pflash1=pflash1-format

loongarch's UEFI loading method makes qemu and libvirt incompatible
when using NVRAM, and the cost of loongarch's current loading method
far outweighs the benefits, so we decided to use the same UEFI loading
scheme as other architectures.

Cc: Andrea Bolognani 
Cc: maob...@loongson.cn
Cc: Philippe Mathieu-Daudé 
Cc: Song Gao 
Cc: zhaotian...@loongson.cn
Signed-off-by: Xianglai Li 
---
 hw/loongarch/acpi-build.c   |  29 +--
 hw/loongarch/virt.c | 101 ++--
 include/hw/loongarch/virt.h |   8 +--
 3 files changed, 106 insertions(+), 32 deletions(-)

diff --git a/hw/loongarch/acpi-build.c b/hw/loongarch/acpi-build.c
index 730bc4a748..308a233e47 100644
--- a/hw/loongarch/acpi-build.c
+++ b/hw/loongarch/acpi-build.c
@@ -314,16 +314,39 @@ static void build_pci_device_aml(Aml *scope, 
LoongArchMachineState *lams)
 static void build_flash_aml(Aml *scope, LoongArchMachineState *lams)
 {
 Aml *dev, *crs;
+MemoryRegion *flash_mem;
 
-hwaddr flash_base = VIRT_FLASH_BASE;
-hwaddr flash_size = VIRT_FLASH_SIZE;
+hwaddr flash0_base;
+hwaddr flash0_size;
+
+hwaddr flash1_base;
+hwaddr flash1_size;
+
+flash_mem = pflash_cfi01_get_memory(lams->flash[0]);
+flash0_base = flash_mem->addr;
+flash0_size = flash_mem->size;
+
+flash_mem = pflash_cfi01_get_memory(lams->flash[1]);
+flash1_base = flash_mem->addr;
+flash1_size = flash_mem->size;
 
 dev = aml_device("FLS0");
 aml_append(dev, aml_name_decl("_HID", aml_string("LNRO0015")));
 aml_append(dev, aml_name_decl("_UID", aml_int(0)));
 
 crs = aml_resource_template();
-aml_append(crs, aml_memory32_fixed(flash_base, flash_size, 
AML_READ_WRITE));
+aml_append(crs, aml_memory32_fixed(flash0_base, flash0_size,
+   AML_READ_WRITE));
+aml_append(dev, aml_name_decl("_CRS", crs));
+aml_append(scope, dev);
+
+dev = aml_device("FLS1");
+aml_append(dev, aml_name_decl("_HID", aml_string("LNRO0015")));
+aml_append(dev, aml_name_decl("_UID", aml_int(1)));
+
+crs = aml_resource_template();
+aml_append(crs, aml_memory32_fixed(flash1_base, flash1_size,
+   AML_READ_WRITE));
 aml_append(dev, aml_name_decl("_CRS", crs));
 aml_append(scope, dev);
 }
diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c
index c9a680e61a..79dff497da 100644
--- a/hw/loongarch/virt.c
+++ b/hw/loongarch/virt.c
@@ -54,7 +54,9 @@ struct loaderparams {
 const char *initrd_filename;
 };
 
-static void virt_flash_create(LoongArchMachineState *lams)
+static PFlashCFI01 *virt_flash_create1(LoongArchMachineState *lams,
+   const char *name,
+   const char *alias_prop_name)
 {
 DeviceState *dev = qdev_new(TYPE_PFLASH_CFI01);
 
@@ -66,45 +68,78 @@ static void virt_flash_create(LoongArchMachineState *lams)
 qdev_prop_set_uint16(dev, "id1", 0x18);
 qdev_prop_set_uint16(dev, "id2", 0x00);
 qdev_prop_set_uint16(dev, "id3", 0x00);
-qdev_prop_set_string(dev, "name", "virt.flash");
-object_property_add_child(OBJECT(lams), "virt.flash", OBJECT(dev));
-object_property_add_alias(OBJECT(lams), "pflash",
+qdev_prop_set_string(dev, "name", name);
+object_property_add_child(OBJECT(lams), name, OBJECT(dev));
+object_property_add_alias(OBJECT(lams), alias_prop_name,
   OBJECT(dev), "drive");
+return PFLASH_CFI01(dev);
+}
 
-lams->flash = PFLASH_CFI01(dev);
+static void virt_flash_create(LoongArchMachineState *lams)
+{
+lams->flash[0] = virt_flash_create1(lams, "virt.flash0", "pflash0");
+lams->flash[1] = virt_flash_create1(lams, "virt.flash1", "pflash1");
 }
 
-static void virt_flash_map(LoongArchMachineState *lams,
-   MemoryRegion *sysmem)
+static void virt_flash_map1(PFlashCFI01 *flash,
+hwaddr base, hwaddr size,
+MemoryRegion *sysmem)
 {
-PFlashCFI01 *flash = lams->flash;
 DeviceState *dev = DEVICE(flash);
-hwaddr base = VIRT_FLASH_BASE;
-hwaddr size = VIRT_FLASH_SIZE;
+BlockBackend *blk;
+hwaddr real_size = size;
+
+blk = pflash_cfi01_get_blk(flash);
+if (blk) {
+real_size = blk_getlength(blk);
+ 

[PATCH v1 8/9] target/loongarch: Implement set vcpu intr for kvm

2023-11-07 Thread xianglai li
From: Tianrui Zhao 

Implement loongarch kvm set vcpu interrupt interface,
when a irq is set in vcpu, we use the KVM_INTERRUPT
ioctl to set intr into kvm.

Signed-off-by: Tianrui Zhao 
Signed-off-by: xianglai li 
---
 target/loongarch/cpu.c   | 18 +-
 target/loongarch/kvm-stub.c  | 13 +
 target/loongarch/kvm.c   | 15 +++
 target/loongarch/kvm_loongarch.h | 13 +
 target/loongarch/trace-events|  1 +
 5 files changed, 55 insertions(+), 5 deletions(-)
 create mode 100644 target/loongarch/kvm-stub.c
 create mode 100644 target/loongarch/kvm_loongarch.h

diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c
index 0a4d1a9778..3073f1548d 100644
--- a/target/loongarch/cpu.c
+++ b/target/loongarch/cpu.c
@@ -20,6 +20,11 @@
 #include "sysemu/reset.h"
 #include "tcg/tcg.h"
 #include "vec.h"
+#include "sysemu/kvm.h"
+#include "kvm_loongarch.h"
+#ifdef CONFIG_KVM
+#include 
+#endif
 
 const char * const regnames[32] = {
 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
@@ -108,12 +113,15 @@ void loongarch_cpu_set_irq(void *opaque, int irq, int 
level)
 return;
 }
 
-env->CSR_ESTAT = deposit64(env->CSR_ESTAT, irq, 1, level != 0);
-
-if (FIELD_EX64(env->CSR_ESTAT, CSR_ESTAT, IS)) {
-cpu_interrupt(cs, CPU_INTERRUPT_HARD);
+if (kvm_enabled()) {
+kvm_loongarch_set_interrupt(cpu, irq, level);
 } else {
-cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
+env->CSR_ESTAT = deposit64(env->CSR_ESTAT, irq, 1, level != 0);
+if (FIELD_EX64(env->CSR_ESTAT, CSR_ESTAT, IS)) {
+cpu_interrupt(cs, CPU_INTERRUPT_HARD);
+} else {
+cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
+}
 }
 }
 
diff --git a/target/loongarch/kvm-stub.c b/target/loongarch/kvm-stub.c
new file mode 100644
index 00..d38c30ec78
--- /dev/null
+++ b/target/loongarch/kvm-stub.c
@@ -0,0 +1,13 @@
+/*
+ * QEMU KVM LoongArch specific function stubs
+ *
+ * Copyright (c) 2023 Loongson Technology Corporation Limited
+ */
+#include "qemu/osdep.h"
+#include "cpu.h"
+#include "kvm_loongarch.h"
+
+int kvm_loongarch_set_interrupt(LoongArchCPU *cpu, int irq, int level)
+{
+   g_assert_not_reached();
+}
diff --git a/target/loongarch/kvm.c b/target/loongarch/kvm.c
index d2dab3fef4..bd33ec2114 100644
--- a/target/loongarch/kvm.c
+++ b/target/loongarch/kvm.c
@@ -748,6 +748,21 @@ int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run)
 return ret;
 }
 
+int kvm_loongarch_set_interrupt(LoongArchCPU *cpu, int irq, int level)
+{
+struct kvm_interrupt intr;
+CPUState *cs = CPU(cpu);
+
+if (level) {
+intr.irq = irq;
+} else {
+intr.irq = -irq;
+}
+
+trace_kvm_set_intr(irq, level);
+return kvm_vcpu_ioctl(cs, KVM_INTERRUPT, );
+}
+
 void kvm_arch_accel_class_init(ObjectClass *oc)
 {
 }
diff --git a/target/loongarch/kvm_loongarch.h b/target/loongarch/kvm_loongarch.h
new file mode 100644
index 00..cdef980eec
--- /dev/null
+++ b/target/loongarch/kvm_loongarch.h
@@ -0,0 +1,13 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * QEMU LoongArch kvm interface
+ *
+ * Copyright (c) 2023 Loongson Technology Corporation Limited
+ */
+
+#ifndef QEMU_KVM_LOONGARCH_H
+#define QEMU_KVM_LOONGARCH_H
+
+int  kvm_loongarch_set_interrupt(LoongArchCPU *cpu, int irq, int level);
+
+#endif
diff --git a/target/loongarch/trace-events b/target/loongarch/trace-events
index 021839880e..dea11edc0f 100644
--- a/target/loongarch/trace-events
+++ b/target/loongarch/trace-events
@@ -12,3 +12,4 @@ kvm_failed_put_counter(const char *msg) "Failed to put 
counter into KVM: %s"
 kvm_failed_get_cpucfg(const char *msg) "Failed to get cpucfg from KVM: %s"
 kvm_failed_put_cpucfg(const char *msg) "Failed to put cpucfg into KVM: %s"
 kvm_arch_handle_exit(int num) "kvm arch handle exit, the reason number: %d"
+kvm_set_intr(int irq, int level) "kvm set interrupt, irq num: %d, level: %d"
-- 
2.39.1




[PATCH v1 5/9] target/loongarch: Implement kvm_arch_init function

2023-11-07 Thread xianglai li
From: Tianrui Zhao 

Implement the kvm_arch_init of loongarch, in the function, the
KVM_CAP_MP_STATE cap is checked by kvm ioctl.

Signed-off-by: Tianrui Zhao 
Reviewed-by: Richard Henderson 
Signed-off-by: xianglai li 
---
 target/loongarch/kvm.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/target/loongarch/kvm.c b/target/loongarch/kvm.c
index e7c9ef830c..29944b9ef8 100644
--- a/target/loongarch/kvm.c
+++ b/target/loongarch/kvm.c
@@ -665,6 +665,7 @@ int kvm_arch_get_default_type(MachineState *ms)
 
 int kvm_arch_init(MachineState *ms, KVMState *s)
 {
+cap_has_mp_state = kvm_check_extension(s, KVM_CAP_MP_STATE);
 return 0;
 }
 
-- 
2.39.1




[PATCH v1 7/9] target/loongarch: Implement kvm_arch_handle_exit

2023-11-07 Thread xianglai li
From: Tianrui Zhao 

Implement kvm_arch_handle_exit for loongarch. In this
function, the KVM_EXIT_LOONGARCH_IOCSR is handled,
we read or write the iocsr address space by the addr,
length and is_write argument in kvm_run.

Signed-off-by: Tianrui Zhao 
Reviewed-by: Richard Henderson 
Signed-off-by: xianglai li 
---
 target/loongarch/kvm.c| 24 +++-
 target/loongarch/trace-events |  1 +
 2 files changed, 24 insertions(+), 1 deletion(-)

diff --git a/target/loongarch/kvm.c b/target/loongarch/kvm.c
index 85e7aeb083..d2dab3fef4 100644
--- a/target/loongarch/kvm.c
+++ b/target/loongarch/kvm.c
@@ -723,7 +723,29 @@ bool kvm_arch_cpu_check_are_resettable(void)
 
 int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run)
 {
-return 0;
+int ret = 0;
+LoongArchCPU *cpu = LOONGARCH_CPU(cs);
+CPULoongArchState *env = >env;
+MemTxAttrs attrs = {};
+
+attrs.requester_id = env_cpu(env)->cpu_index;
+
+trace_kvm_arch_handle_exit(run->exit_reason);
+switch (run->exit_reason) {
+case KVM_EXIT_LOONGARCH_IOCSR:
+address_space_rw(>address_space_iocsr,
+ run->iocsr_io.phys_addr,
+ attrs,
+ run->iocsr_io.data,
+ run->iocsr_io.len,
+ run->iocsr_io.is_write);
+break;
+default:
+ret = -1;
+warn_report("KVM: unknown exit reason %d", run->exit_reason);
+break;
+}
+return ret;
 }
 
 void kvm_arch_accel_class_init(ObjectClass *oc)
diff --git a/target/loongarch/trace-events b/target/loongarch/trace-events
index 937c3c7c0c..021839880e 100644
--- a/target/loongarch/trace-events
+++ b/target/loongarch/trace-events
@@ -11,3 +11,4 @@ kvm_failed_get_counter(const char *msg) "Failed to get 
counter from KVM: %s"
 kvm_failed_put_counter(const char *msg) "Failed to put counter into KVM: %s"
 kvm_failed_get_cpucfg(const char *msg) "Failed to get cpucfg from KVM: %s"
 kvm_failed_put_cpucfg(const char *msg) "Failed to put cpucfg into KVM: %s"
+kvm_arch_handle_exit(int num) "kvm arch handle exit, the reason number: %d"
-- 
2.39.1




[PATCH v1 9/9] target/loongarch: Add loongarch kvm into meson build

2023-11-07 Thread xianglai li
From: Tianrui Zhao 

Add kvm.c and kvm-stub.c into meson.build to compile
it when kvm is configed. Meanwhile in meson.build,
we set the kvm_targets to loongarch64-softmmu when
the cpu is loongarch.

Signed-off-by: Tianrui Zhao 
Signed-off-by: xianglai li 
---
 meson.build  | 2 ++
 target/loongarch/meson.build | 1 +
 2 files changed, 3 insertions(+)

diff --git a/meson.build b/meson.build
index a98e48b8e9..2a3b011fa4 100644
--- a/meson.build
+++ b/meson.build
@@ -114,6 +114,8 @@ elif cpu in ['riscv32']
   kvm_targets = ['riscv32-softmmu']
 elif cpu in ['riscv64']
   kvm_targets = ['riscv64-softmmu']
+elif cpu in ['loongarch64']
+  kvm_targets = ['loongarch64-softmmu']
 else
   kvm_targets = []
 endif
diff --git a/target/loongarch/meson.build b/target/loongarch/meson.build
index 18e8191e2b..e00cabcefc 100644
--- a/target/loongarch/meson.build
+++ b/target/loongarch/meson.build
@@ -27,6 +27,7 @@ loongarch_system_ss.add(files(
 
 common_ss.add(when: 'CONFIG_LOONGARCH_DIS', if_true: [files('disas.c'), gen])
 
+loongarch_ss.add(when: 'CONFIG_KVM', if_true: files('kvm.c'), if_false: 
files('kvm-stub.c'))
 loongarch_ss.add_all(when: 'CONFIG_TCG', if_true: [loongarch_tcg_ss])
 
 target_arch += {'loongarch': loongarch_ss}
-- 
2.39.1




[PATCH v1 2/9] target/loongarch: Define some kvm_arch interfaces

2023-11-07 Thread xianglai li
From: Tianrui Zhao 

Define some functions in target/loongarch/kvm.c, such as
kvm_arch_put_registers, kvm_arch_get_registers and
kvm_arch_handle_exit, etc. which are needed by kvm/kvm-all.c.
Now the most functions has no content and they will be
implemented in the next patches.

Signed-off-by: Tianrui Zhao 
Reviewed-by: Richard Henderson 
Signed-off-by: xianglai li 
---
 target/loongarch/kvm.c | 131 +
 1 file changed, 131 insertions(+)
 create mode 100644 target/loongarch/kvm.c

diff --git a/target/loongarch/kvm.c b/target/loongarch/kvm.c
new file mode 100644
index 00..0d67322fd9
--- /dev/null
+++ b/target/loongarch/kvm.c
@@ -0,0 +1,131 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * QEMU LoongArch KVM
+ *
+ * Copyright (c) 2023 Loongson Technology Corporation Limited
+ */
+
+#include "qemu/osdep.h"
+#include 
+#include 
+
+#include "qemu/timer.h"
+#include "qemu/error-report.h"
+#include "qemu/main-loop.h"
+#include "sysemu/sysemu.h"
+#include "sysemu/kvm.h"
+#include "sysemu/kvm_int.h"
+#include "hw/pci/pci.h"
+#include "exec/memattrs.h"
+#include "exec/address-spaces.h"
+#include "hw/boards.h"
+#include "hw/irq.h"
+#include "qemu/log.h"
+#include "hw/loader.h"
+#include "migration/migration.h"
+#include "sysemu/runstate.h"
+#include "cpu-csr.h"
+#include "kvm_loongarch.h"
+
+static bool cap_has_mp_state;
+const KVMCapabilityInfo kvm_arch_required_capabilities[] = {
+KVM_CAP_LAST_INFO
+};
+
+int kvm_arch_get_registers(CPUState *cs)
+{
+return 0;
+}
+int kvm_arch_put_registers(CPUState *cs, int level)
+{
+return 0;
+}
+
+int kvm_arch_init_vcpu(CPUState *cs)
+{
+return 0;
+}
+
+int kvm_arch_destroy_vcpu(CPUState *cs)
+{
+return 0;
+}
+
+unsigned long kvm_arch_vcpu_id(CPUState *cs)
+{
+return cs->cpu_index;
+}
+
+int kvm_arch_release_virq_post(int virq)
+{
+return 0;
+}
+
+int kvm_arch_msi_data_to_gsi(uint32_t data)
+{
+abort();
+}
+
+int kvm_arch_fixup_msi_route(struct kvm_irq_routing_entry *route,
+ uint64_t address, uint32_t data, PCIDevice *dev)
+{
+return 0;
+}
+
+int kvm_arch_add_msi_route_post(struct kvm_irq_routing_entry *route,
+int vector, PCIDevice *dev)
+{
+return 0;
+}
+
+void kvm_arch_init_irq_routing(KVMState *s)
+{
+}
+
+int kvm_arch_get_default_type(MachineState *ms)
+{
+return 0;
+}
+
+int kvm_arch_init(MachineState *ms, KVMState *s)
+{
+return 0;
+}
+
+int kvm_arch_irqchip_create(KVMState *s)
+{
+return 0;
+}
+
+void kvm_arch_pre_run(CPUState *cs, struct kvm_run *run)
+{
+}
+
+MemTxAttrs kvm_arch_post_run(CPUState *cs, struct kvm_run *run)
+{
+return MEMTXATTRS_UNSPECIFIED;
+}
+
+int kvm_arch_process_async_events(CPUState *cs)
+{
+return cs->halted;
+}
+
+bool kvm_arch_stop_on_emulation_error(CPUState *cs)
+{
+return true;
+}
+
+bool kvm_arch_cpu_check_are_resettable(void)
+{
+return true;
+}
+
+int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run)
+{
+return 0;
+}
+
+void kvm_arch_accel_class_init(ObjectClass *oc)
+{
+}
-- 
2.39.1




[PATCH v1 6/9] target/loongarch: Implement kvm_arch_init_vcpu

2023-11-07 Thread xianglai li
From: Tianrui Zhao 

Implement kvm_arch_init_vcpu interface for loongarch,
in this function, we register VM change state handler.
And when VM state changes to running, the counter value
should be put into kvm to keep consistent with kvm,
and when state change to stop, counter value should be
refreshed from kvm.

Signed-off-by: Tianrui Zhao 
Signed-off-by: xianglai li 
---
 target/loongarch/cpu.h|  2 ++
 target/loongarch/kvm.c| 23 +++
 target/loongarch/trace-events |  2 ++
 3 files changed, 27 insertions(+)

diff --git a/target/loongarch/cpu.h b/target/loongarch/cpu.h
index 2580dc26e1..49edf6b016 100644
--- a/target/loongarch/cpu.h
+++ b/target/loongarch/cpu.h
@@ -382,6 +382,8 @@ struct ArchCPU {
 
 /* 'compatible' string for this CPU for Linux device trees */
 const char *dtb_compatible;
+/* used by KVM_REG_LOONGARCH_COUNTER ioctl to access guest time counters */
+uint64_t kvm_state_counter;
 };
 
 #define TYPE_LOONGARCH_CPU "loongarch-cpu"
diff --git a/target/loongarch/kvm.c b/target/loongarch/kvm.c
index 29944b9ef8..85e7aeb083 100644
--- a/target/loongarch/kvm.c
+++ b/target/loongarch/kvm.c
@@ -617,8 +617,31 @@ int kvm_arch_put_registers(CPUState *cs, int level)
 return ret;
 }
 
+static void kvm_loongarch_vm_stage_change(void *opaque, bool running,
+  RunState state)
+{
+int ret;
+CPUState *cs = opaque;
+LoongArchCPU *cpu = LOONGARCH_CPU(cs);
+
+if (running) {
+ret = kvm_set_one_reg(cs, KVM_REG_LOONGARCH_COUNTER,
+  >kvm_state_counter);
+if (ret < 0) {
+trace_kvm_failed_put_counter(strerror(errno));
+}
+} else {
+ret = kvm_get_one_reg(cs, KVM_REG_LOONGARCH_COUNTER,
+  >kvm_state_counter);
+if (ret < 0) {
+trace_kvm_failed_get_counter(strerror(errno));
+}
+}
+}
+
 int kvm_arch_init_vcpu(CPUState *cs)
 {
+qemu_add_vm_change_state_handler(kvm_loongarch_vm_stage_change, cs);
 return 0;
 }
 
diff --git a/target/loongarch/trace-events b/target/loongarch/trace-events
index 6827ab566a..937c3c7c0c 100644
--- a/target/loongarch/trace-events
+++ b/target/loongarch/trace-events
@@ -7,5 +7,7 @@ kvm_failed_get_fpu(const char *msg) "Failed to get fpu from 
KVM: %s"
 kvm_failed_put_fpu(const char *msg) "Failed to put fpu into KVM: %s"
 kvm_failed_get_mpstate(const char *msg) "Failed to get mp_state from KVM: %s"
 kvm_failed_put_mpstate(const char *msg) "Failed to put mp_state into KVM: %s"
+kvm_failed_get_counter(const char *msg) "Failed to get counter from KVM: %s"
+kvm_failed_put_counter(const char *msg) "Failed to put counter into KVM: %s"
 kvm_failed_get_cpucfg(const char *msg) "Failed to get cpucfg from KVM: %s"
 kvm_failed_put_cpucfg(const char *msg) "Failed to put cpucfg into KVM: %s"
-- 
2.39.1




[PATCH v1 4/9] target/loongarch: Implement kvm get/set registers

2023-11-07 Thread xianglai li
From: Tianrui Zhao 

Implement kvm_arch_get/set_registers interfaces, many regs
can be get/set in the function, such as core regs, csr regs,
fpu regs, mp state, etc.

Signed-off-by: Tianrui Zhao 
Signed-off-by: xianglai li 
---
 meson.build   |   1 +
 target/loongarch/cpu.c|   3 +
 target/loongarch/cpu.h|   2 +
 target/loongarch/kvm.c| 580 +-
 target/loongarch/trace-events |  11 +
 target/loongarch/trace.h  |   1 +
 6 files changed, 596 insertions(+), 2 deletions(-)
 create mode 100644 target/loongarch/trace-events
 create mode 100644 target/loongarch/trace.h

diff --git a/meson.build b/meson.build
index bd65a111aa..a98e48b8e9 100644
--- a/meson.build
+++ b/meson.build
@@ -3305,6 +3305,7 @@ if have_system or have_user
 'target/hppa',
 'target/i386',
 'target/i386/kvm',
+'target/loongarch',
 'target/mips/tcg',
 'target/nios2',
 'target/ppc',
diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c
index 1eed1b3eb0..0a4d1a9778 100644
--- a/target/loongarch/cpu.c
+++ b/target/loongarch/cpu.c
@@ -546,6 +546,9 @@ static void loongarch_cpu_reset_hold(Object *obj)
 #ifndef CONFIG_USER_ONLY
 env->pc = 0x1c00;
 memset(env->tlb, 0, sizeof(env->tlb));
+if (kvm_enabled()) {
+kvm_arch_reset_vcpu(env);
+}
 #endif
 
 restore_fp_status(env);
diff --git a/target/loongarch/cpu.h b/target/loongarch/cpu.h
index e6a99c83ab..2580dc26e1 100644
--- a/target/loongarch/cpu.h
+++ b/target/loongarch/cpu.h
@@ -359,6 +359,7 @@ typedef struct CPUArchState {
 MemoryRegion iocsr_mem;
 bool load_elf;
 uint64_t elf_address;
+uint32_t mp_state;
 /* Store ipistate to access from this struct */
 DeviceState *ipistate;
 #endif
@@ -477,6 +478,7 @@ static inline void cpu_get_tb_cpu_state(CPULoongArchState 
*env, vaddr *pc,
 }
 
 void loongarch_cpu_list(void);
+void kvm_arch_reset_vcpu(CPULoongArchState *env);
 
 #define cpu_list loongarch_cpu_list
 
diff --git a/target/loongarch/kvm.c b/target/loongarch/kvm.c
index 0d67322fd9..e7c9ef830c 100644
--- a/target/loongarch/kvm.c
+++ b/target/loongarch/kvm.c
@@ -26,19 +26,595 @@
 #include "sysemu/runstate.h"
 #include "cpu-csr.h"
 #include "kvm_loongarch.h"
+#include "trace.h"
 
 static bool cap_has_mp_state;
 const KVMCapabilityInfo kvm_arch_required_capabilities[] = {
 KVM_CAP_LAST_INFO
 };
 
+static int kvm_loongarch_get_regs_core(CPUState *cs)
+{
+int ret = 0;
+int i;
+struct kvm_regs regs;
+LoongArchCPU *cpu = LOONGARCH_CPU(cs);
+CPULoongArchState *env = >env;
+
+/* Get the current register set as KVM seems it */
+ret = kvm_vcpu_ioctl(cs, KVM_GET_REGS, );
+if (ret < 0) {
+trace_kvm_failed_get_regs_core(strerror(errno));
+return ret;
+}
+/* gpr[0] value is always 0 */
+env->gpr[0] = 0;
+for (i = 1; i < 32; i++) {
+env->gpr[i] = regs.gpr[i];
+}
+
+env->pc = regs.pc;
+return ret;
+}
+
+static int kvm_loongarch_put_regs_core(CPUState *cs)
+{
+int ret = 0;
+int i;
+struct kvm_regs regs;
+LoongArchCPU *cpu = LOONGARCH_CPU(cs);
+CPULoongArchState *env = >env;
+
+/* Set the registers based on QEMU's view of things */
+for (i = 0; i < 32; i++) {
+regs.gpr[i] = env->gpr[i];
+}
+
+regs.pc = env->pc;
+ret = kvm_vcpu_ioctl(cs, KVM_SET_REGS, );
+if (ret < 0) {
+trace_kvm_failed_put_regs_core(strerror(errno));
+}
+
+return ret;
+}
+
+static int kvm_loongarch_get_csr(CPUState *cs)
+{
+int ret = 0;
+LoongArchCPU *cpu = LOONGARCH_CPU(cs);
+CPULoongArchState *env = >env;
+
+ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_CRMD),
+   >CSR_CRMD);
+
+ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_PRMD),
+   >CSR_PRMD);
+
+ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_EUEN),
+   >CSR_EUEN);
+
+ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_MISC),
+   >CSR_MISC);
+
+ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_ECFG),
+   >CSR_ECFG);
+
+ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_ESTAT),
+   >CSR_ESTAT);
+
+ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_ERA),
+   >CSR_ERA);
+
+ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_BADV),
+   >CSR_BADV);
+
+ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_BADI),
+   >CSR_BADI);
+
+ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_EENTRY),
+   >CSR_EENTRY);
+
+ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TLBIDX),
+   >CSR_TLBIDX);
+
+  

[PATCH v1 1/9] linux-headers: Add KVM headers for loongarch

2023-11-07 Thread xianglai li
From: zhaotianrui 

Update linux KVM headers about LoongArch KVM form linux
kernel. Mainly contains some KVM structures and macro
defines such as LoongArch KVM registers number, LoongArch
fpu structure, exit reason of LoongArch IOCSR, etc.

Signed-off-by: zhaotianrui 
Signed-off-by: xianglai li 
---
 linux-headers/asm-loongarch/kvm.h | 108 ++
 linux-headers/linux/kvm.h |   9 +++
 2 files changed, 117 insertions(+)
 create mode 100644 linux-headers/asm-loongarch/kvm.h

diff --git a/linux-headers/asm-loongarch/kvm.h 
b/linux-headers/asm-loongarch/kvm.h
new file mode 100644
index 00..c6ad2ee610
--- /dev/null
+++ b/linux-headers/asm-loongarch/kvm.h
@@ -0,0 +1,108 @@
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+/*
+ * Copyright (C) 2020-2023 Loongson Technology Corporation Limited
+ */
+
+#ifndef __UAPI_ASM_LOONGARCH_KVM_H
+#define __UAPI_ASM_LOONGARCH_KVM_H
+
+#include 
+
+/*
+ * KVM LoongArch specific structures and definitions.
+ *
+ * Some parts derived from the x86 version of this file.
+ */
+
+#define __KVM_HAVE_READONLY_MEM
+
+#define KVM_COALESCED_MMIO_PAGE_OFFSET 1
+#define KVM_DIRTY_LOG_PAGE_OFFSET  64
+
+/*
+ * for KVM_GET_REGS and KVM_SET_REGS
+ */
+struct kvm_regs {
+   /* out (KVM_GET_REGS) / in (KVM_SET_REGS) */
+   __u64 gpr[32];
+   __u64 pc;
+};
+
+/*
+ * for KVM_GET_FPU and KVM_SET_FPU
+ */
+struct kvm_fpu {
+   __u32 fcsr;
+   __u64 fcc;/* 8x8 */
+   struct kvm_fpureg {
+   __u64 val64[4];
+   } fpr[32];
+};
+
+/*
+ * For LoongArch, we use KVM_SET_ONE_REG and KVM_GET_ONE_REG to access various
+ * registers.  The id field is broken down as follows:
+ *
+ *  bits[63..52] - As per linux/kvm.h
+ *  bits[51..32] - Must be zero.
+ *  bits[31..16] - Register set.
+ *
+ * Register set = 0: GP registers from kvm_regs (see definitions below).
+ *
+ * Register set = 1: CSR registers.
+ *
+ * Register set = 2: KVM specific registers (see definitions below).
+ *
+ * Register set = 3: FPU / SIMD registers (see definitions below).
+ *
+ * Other sets registers may be added in the future.  Each set would
+ * have its own identifier in bits[31..16].
+ */
+
+#define KVM_REG_LOONGARCH_GPR  (KVM_REG_LOONGARCH | 0x0ULL)
+#define KVM_REG_LOONGARCH_CSR  (KVM_REG_LOONGARCH | 0x1ULL)
+#define KVM_REG_LOONGARCH_KVM  (KVM_REG_LOONGARCH | 0x2ULL)
+#define KVM_REG_LOONGARCH_FPSIMD   (KVM_REG_LOONGARCH | 0x3ULL)
+#define KVM_REG_LOONGARCH_CPUCFG   (KVM_REG_LOONGARCH | 0x4ULL)
+#define KVM_REG_LOONGARCH_MASK (KVM_REG_LOONGARCH | 0x7ULL)
+#define KVM_CSR_IDX_MASK   0x7fff
+#define KVM_CPUCFG_IDX_MASK0x7fff
+
+/*
+ * KVM_REG_LOONGARCH_KVM - KVM specific control registers.
+ */
+
+#define KVM_REG_LOONGARCH_COUNTER  (KVM_REG_LOONGARCH_KVM | 
KVM_REG_SIZE_U64 | 1)
+#define KVM_REG_LOONGARCH_VCPU_RESET   (KVM_REG_LOONGARCH_KVM | 
KVM_REG_SIZE_U64 | 2)
+
+#define LOONGARCH_REG_SHIFT3
+#define LOONGARCH_REG_64(TYPE, REG)(TYPE | KVM_REG_SIZE_U64 | (REG << 
LOONGARCH_REG_SHIFT))
+#define KVM_IOC_CSRID(REG) LOONGARCH_REG_64(KVM_REG_LOONGARCH_CSR, 
REG)
+#define KVM_IOC_CPUCFG(REG)
LOONGARCH_REG_64(KVM_REG_LOONGARCH_CPUCFG, REG)
+
+struct kvm_debug_exit_arch {
+};
+
+/* for KVM_SET_GUEST_DEBUG */
+struct kvm_guest_debug_arch {
+};
+
+/* definition of registers in kvm_run */
+struct kvm_sync_regs {
+};
+
+/* dummy definition */
+struct kvm_sregs {
+};
+
+struct kvm_iocsr_entry {
+   __u32 addr;
+   __u32 pad;
+   __u64 data;
+};
+
+#define KVM_NR_IRQCHIPS1
+#define KVM_IRQCHIP_NUM_PINS   64
+#define KVM_MAX_CORES  256
+
+#endif /* __UAPI_ASM_LOONGARCH_KVM_H */
diff --git a/linux-headers/linux/kvm.h b/linux-headers/linux/kvm.h
index 0d74ee999a..0e378bbcbf 100644
--- a/linux-headers/linux/kvm.h
+++ b/linux-headers/linux/kvm.h
@@ -264,6 +264,7 @@ struct kvm_xen_exit {
 #define KVM_EXIT_RISCV_SBI35
 #define KVM_EXIT_RISCV_CSR36
 #define KVM_EXIT_NOTIFY   37
+#define KVM_EXIT_LOONGARCH_IOCSR  38
 
 /* For KVM_EXIT_INTERNAL_ERROR */
 /* Emulate instruction failed. */
@@ -336,6 +337,13 @@ struct kvm_run {
__u32 len;
__u8  is_write;
} mmio;
+   /* KVM_EXIT_LOONGARCH_IOCSR */
+   struct {
+   __u64 phys_addr;
+   __u8  data[8];
+   __u32 len;
+   __u8  is_write;
+   } iocsr_io;
/* KVM_EXIT_HYPERCALL */
struct {
__u64 nr;
@@ -1358,6 +1366,7 @@ struct kvm_dirty_tlb {
 #define KVM_REG_ARM64  0x6000ULL
 #define KVM_REG_MIPS   0x7000ULL
 #define KVM_REG_RISCV  0x8000ULL
+#define KVM_REG_LOONGARCH  0x9000ULL
 
 #define KVM_REG_SIZE_SHIFT 

[PATCH v1 3/9] target/loongarch: Supplement vcpu env initial when vcpu reset

2023-11-07 Thread xianglai li
From: Tianrui Zhao 

Supplement vcpu env initial when vcpu reset, including
init vcpu CSR_CPUID,CSR_TID to cpu->cpu_index. The two
regs will be used in kvm_get/set_csr_ioctl.

Signed-off-by: Tianrui Zhao 
Signed-off-by: xianglai li 
---
 target/loongarch/cpu.c | 2 ++
 target/loongarch/cpu.h | 2 +-
 2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c
index ef1bf89dac..1eed1b3eb0 100644
--- a/target/loongarch/cpu.c
+++ b/target/loongarch/cpu.c
@@ -524,10 +524,12 @@ static void loongarch_cpu_reset_hold(Object *obj)
 
 env->CSR_ESTAT = env->CSR_ESTAT & (~MAKE_64BIT_MASK(0, 2));
 env->CSR_RVACFG = FIELD_DP64(env->CSR_RVACFG, CSR_RVACFG, RBITS, 0);
+env->CSR_CPUID = cs->cpu_index;
 env->CSR_TCFG = FIELD_DP64(env->CSR_TCFG, CSR_TCFG, EN, 0);
 env->CSR_LLBCTL = FIELD_DP64(env->CSR_LLBCTL, CSR_LLBCTL, KLO, 0);
 env->CSR_TLBRERA = FIELD_DP64(env->CSR_TLBRERA, CSR_TLBRERA, ISTLBR, 0);
 env->CSR_MERRCTL = FIELD_DP64(env->CSR_MERRCTL, CSR_MERRCTL, ISMERR, 0);
+env->CSR_TID = cs->cpu_index;
 
 env->CSR_PRCFG3 = FIELD_DP64(env->CSR_PRCFG3, CSR_PRCFG3, TLB_TYPE, 2);
 env->CSR_PRCFG3 = FIELD_DP64(env->CSR_PRCFG3, CSR_PRCFG3, MTLB_ENTRY, 63);
diff --git a/target/loongarch/cpu.h b/target/loongarch/cpu.h
index 40e70a8119..e6a99c83ab 100644
--- a/target/loongarch/cpu.h
+++ b/target/loongarch/cpu.h
@@ -318,6 +318,7 @@ typedef struct CPUArchState {
 uint64_t CSR_PWCH;
 uint64_t CSR_STLBPS;
 uint64_t CSR_RVACFG;
+uint64_t CSR_CPUID;
 uint64_t CSR_PRCFG1;
 uint64_t CSR_PRCFG2;
 uint64_t CSR_PRCFG3;
@@ -349,7 +350,6 @@ typedef struct CPUArchState {
 uint64_t CSR_DBG;
 uint64_t CSR_DERA;
 uint64_t CSR_DSAVE;
-uint64_t CSR_CPUID;
 
 #ifndef CONFIG_USER_ONLY
 LoongArchTLB  tlb[LOONGARCH_TLB_MAX];
-- 
2.39.1




[PATCH v1 0/9] Add loongarch kvm accel support

2023-11-07 Thread xianglai li
The LoongArch KVM patch series have been merged in Linux kernel,
so we remove the RFC flag in this patch series.

This series add loongarch kvm support, mainly implement
some interfaces used by kvm such as kvm_arch_get/set_regs,
kvm_arch_handle_exit, kvm_loongarch_set_interrupt, etc.

Currently, we are able to boot LoongArch KVM Linux Guests.
In loongarch VM, mmio devices and iocsr devices are emulated
in user space such as APIC, IPI, pci devices, etc, other
hardwares such as MMU, timer and csr are emulated in kernel.

The running environment of LoongArch virt machine:
1. Get the Linux KVM environment of LoongArch in Liunx mainline.
   make ARCH=loongarch CROSS_COMPILE=loongarch64-unknown-linux-gnu- 
loongson3_defconfig
   make ARCH=loongarch CROSS_COMPILE=loongarch64-unknown-linux-gnu-
2. Get the qemu source: https://github.com/loongson/qemu
   git checkout kvm-loongarch
   ./configure --target-list="loongarch64-softmmu"  --enable-kvm
   make
3. Get uefi bios of LoongArch virt machine:
   Link: 
https://github.com/tianocore/edk2-platforms/tree/master/Platform/Loongson/LoongArchQemuPkg#readme
4. Also you can access the binary files we have already built:
   https://github.com/yangxiaojuan-loongson/qemu-binary

The command to boot loongarch virt machine:
   $ qemu-system-loongarch64 -machine virt -m 4G -cpu la464 \
   -smp 1 -bios QEMU_EFI.fd -kernel vmlinuz.efi -initrd ramdisk \
   -serial stdio   -monitor telnet:localhost:4495,server,nowait \
   -append "root=/dev/ram rdinit=/sbin/init console=ttyS0,115200" \
   --nographic

Changes for v1:
1. Synchronous KVM headers about LoongArch KVM form linux kernel,
as the LoongArch KVM patch series have been accepted by linux kernel. 
2. Remove the KVM_GET/SET_ONE_UREG64 macro in target/loongarch, and
use the common interface kvm_get/set_one_reg to replace it.
3. Resolve the compiling errors when LoongArch is built by other archs.

The previous RFC change log:
Changes for RFC v3:
1. Move the init mp_state to KVM_MP_STATE_RUNNABLE function into kvm.c.
2. Fix some unstandard code problems in kvm_get/set_regs_ioctl, such as
sort loongarch to keep alphabetic ordering in meson.build, gpr[0] should
be always 0, remove unnecessary inline statement, etc.
3. Rename the counter_value variable to kvm_state_counter in cpu_env,
and add comments for it to explain the meaning.

Changes for RFC v2:
1. Mark the "Add KVM headers for loongarch" patch as a placeholder,
as we will use the update-linux-headers.sh to generate the kvm headers
when the linux loongarch KVM patch series are accepted.
2. Remove the DPRINTF macro in kvm.c and use trace events to replace
it, we add some trace functions such as trace_kvm_handle_exit,
trace_kvm_set_intr, trace_kvm_failed_get_csr, etc.
3. Remove the unused functions in kvm_stub.c and move stub function into
the suitable patch.

Tianrui Zhao (8):
  target/loongarch: Define some kvm_arch interfaces
  target/loongarch: Supplement vcpu env initial when vcpu reset
  target/loongarch: Implement kvm get/set registers
  target/loongarch: Implement kvm_arch_init function
  target/loongarch: Implement kvm_arch_init_vcpu
  target/loongarch: Implement kvm_arch_handle_exit
  target/loongarch: Implement set vcpu intr for kvm
  target/loongarch: Add loongarch kvm into meson build

zhaotianrui (1):
  linux-headers: Add KVM headers for loongarch

 linux-headers/asm-loongarch/kvm.h | 108 +
 linux-headers/linux/kvm.h |   9 +
 meson.build   |   3 +
 target/loongarch/cpu.c|  23 +-
 target/loongarch/cpu.h|   6 +-
 target/loongarch/kvm-stub.c   |  13 +
 target/loongarch/kvm.c| 768 ++
 target/loongarch/kvm_loongarch.h  |  13 +
 target/loongarch/meson.build  |   1 +
 target/loongarch/trace-events |  15 +
 target/loongarch/trace.h  |   1 +
 11 files changed, 954 insertions(+), 6 deletions(-)
 create mode 100644 linux-headers/asm-loongarch/kvm.h
 create mode 100644 target/loongarch/kvm-stub.c
 create mode 100644 target/loongarch/kvm.c
 create mode 100644 target/loongarch/kvm_loongarch.h
 create mode 100644 target/loongarch/trace-events
 create mode 100644 target/loongarch/trace.h

-- 
2.39.1




[PATCH RFC v4 0/9] Add loongarch kvm accel support

2023-10-09 Thread xianglai li
This series add loongarch kvm support, mainly implement
some interfaces used by kvm such as kvm_arch_get/set_regs,
kvm_arch_handle_exit, kvm_loongarch_set_interrupt, etc.

Currently, we are able to boot LoongArch KVM Linux Guests.
In loongarch VM, mmio devices and iocsr devices are emulated
in user space such as APIC, IPI, pci devices, etc, other
hardwares such as MMU, timer and csr are emulated in kernel.

It is based on temporarily unaccepted linux kvm:
https://github.com/loongson/linux-loongarch-kvm
And We will remove the RFC flag until the linux kvm patches
are merged.

The running environment of LoongArch virt machine:
1. Get the linux source by the above mentioned link.
   git checkout kvm-loongarch
   make ARCH=loongarch CROSS_COMPILE=loongarch64-unknown-linux-gnu- 
loongson3_defconfig
   make ARCH=loongarch CROSS_COMPILE=loongarch64-unknown-linux-gnu-
2. Get the qemu source: https://github.com/loongson/qemu
   git checkout kvm-loongarch
   ./configure --target-list="loongarch64-softmmu"  --enable-kvm
   make
3. Get uefi bios of LoongArch virt machine:
   Link: 
https://github.com/tianocore/edk2-platforms/tree/master/Platform/Loongson/LoongArchQemuPkg#readme
4. Also you can access the binary files we have already build:
   https://github.com/yangxiaojuan-loongson/qemu-binary

The command to boot loongarch virt machine:
   $ qemu-system-loongarch64 -machine virt -m 4G -cpu la464 \
   -smp 1 -bios QEMU_EFI.fd -kernel vmlinuz.efi -initrd ramdisk \
   -serial stdio   -monitor telnet:localhost:4495,server,nowait \
   -append "root=/dev/ram rdinit=/sbin/init console=ttyS0,115200" \
   --nographic

Changes for RFC v4:
1. Added function interfaces kvm_loongarch_get_cpucfg and
kvm_loongarch_put_cpucfg for passing the value of vcpu cfg to kvm.
Move the macro definition KVM_IOC_CSRID from kvm.c to kvm.h.
2.Delete the duplicate CSR_CPUID field in CPUArchState.
3.Add kvm_arch_get_default_type function in kvm.c.
4.Disable LSX,LASX in cpucfg2 in KVM. And disable LBT in cpucfg2 in KVM.

Changes for RFC v3:
1. Move the init mp_state to KVM_MP_STATE_RUNNABLE function into kvm.c.
2. Fix some unstandard code problems in kvm_get/set_regs_ioctl, such as
sort loongarch to keep alphabetic ordering in meson.build, gpr[0] should
be always 0, remove unnecessary inline statement, etc.
3. Rename the counter_value variable to kvm_state_counter in cpu_env,
and add comments for it to explain the meaning.

Changes for RFC v2:
1. Mark the "Add KVM headers for loongarch" patch as a placeholder,
as we will use the update-linux-headers.sh to generate the kvm headers
when the linux loongarch KVM patch series are accepted.
2. Remove the DPRINTF macro in kvm.c and use trace events to replace
it, we add some trace functions such as trace_kvm_handle_exit,
trace_kvm_set_intr, trace_kvm_failed_get_csr, etc.
3. Remove the unused functions in kvm_stub.c and move stub function into
the suitable patch.

Cc: "Michael S. Tsirkin" 
Cc: Cornelia Huck 
Cc: Paolo Bonzini 
Cc: "Marc-André Lureau" 
Cc: "Daniel P. Berrangé" 
Cc: Thomas Huth 
Cc: "Philippe Mathieu-Daudé" 
Cc: Richard Henderson 
Cc: Peter Maydell 
Cc: Bibo Mao 
Cc: Song Gao 
Cc: Xiaojuan Yang 
Cc: Tianrui Zhao 

Tianrui Zhao (9):
  linux-headers: Add KVM headers for loongarch
  target/loongarch: Define some kvm_arch interfaces
  target/loongarch: Supplement vcpu env initial when vcpu reset
  target/loongarch: Implement kvm get/set registers
  target/loongarch: Implement kvm_arch_init function
  target/loongarch: Implement kvm_arch_init_vcpu
  target/loongarch: Implement kvm_arch_handle_exit
  target/loongarch: Implement set vcpu intr for kvm
  target/loongarch: Add loongarch kvm into meson build

 linux-headers/asm-loongarch/kvm.h | 100 +
 linux-headers/linux/kvm.h |   9 +
 meson.build   |   3 +
 target/loongarch/cpu.c|  23 +-
 target/loongarch/cpu.h|   6 +-
 target/loongarch/kvm-stub.c   |  11 +
 target/loongarch/kvm.c| 594 ++
 target/loongarch/kvm_loongarch.h  |  13 +
 target/loongarch/meson.build  |   1 +
 target/loongarch/trace-events |  17 +
 target/loongarch/trace.h  |   1 +
 11 files changed, 772 insertions(+), 6 deletions(-)
 create mode 100644 linux-headers/asm-loongarch/kvm.h
 create mode 100644 target/loongarch/kvm-stub.c
 create mode 100644 target/loongarch/kvm.c
 create mode 100644 target/loongarch/kvm_loongarch.h
 create mode 100644 target/loongarch/trace-events
 create mode 100644 target/loongarch/trace.h

-- 
2.39.1




[PATCH RFC v4 7/9] target/loongarch: Implement kvm_arch_handle_exit

2023-10-09 Thread xianglai li
From: Tianrui Zhao 

Implement kvm_arch_handle_exit for loongarch. In this
function, the KVM_EXIT_LOONGARCH_IOCSR is handled,
we read or write the iocsr address space by the addr,
length and is_write argument in kvm_run.

Cc: "Michael S. Tsirkin" 
Cc: Cornelia Huck 
Cc: Paolo Bonzini 
Cc: "Marc-André Lureau" 
Cc: "Daniel P. Berrangé" 
Cc: Thomas Huth 
Cc: "Philippe Mathieu-Daudé" 
Cc: Richard Henderson 
Cc: Peter Maydell 
Cc: Bibo Mao 
Cc: Song Gao 
Cc: Xiaojuan Yang 
Cc: Tianrui Zhao 

Signed-off-by: Tianrui Zhao 
Reviewed-by: Richard Henderson 
Signed-off-by: xianglai li 
---
 target/loongarch/kvm.c| 24 +++-
 target/loongarch/trace-events |  1 +
 2 files changed, 24 insertions(+), 1 deletion(-)

diff --git a/target/loongarch/kvm.c b/target/loongarch/kvm.c
index 9754478e34..0fe52434ed 100644
--- a/target/loongarch/kvm.c
+++ b/target/loongarch/kvm.c
@@ -549,7 +549,29 @@ bool kvm_arch_cpu_check_are_resettable(void)
 
 int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run)
 {
-return 0;
+int ret = 0;
+LoongArchCPU *cpu = LOONGARCH_CPU(cs);
+CPULoongArchState *env = >env;
+MemTxAttrs attrs = {};
+
+attrs.requester_id = env_cpu(env)->cpu_index;
+
+trace_kvm_arch_handle_exit(run->exit_reason);
+switch (run->exit_reason) {
+case KVM_EXIT_LOONGARCH_IOCSR:
+address_space_rw(>address_space_iocsr,
+ run->iocsr_io.phys_addr,
+ attrs,
+ run->iocsr_io.data,
+ run->iocsr_io.len,
+ run->iocsr_io.is_write);
+break;
+default:
+ret = -1;
+warn_report("KVM: unknown exit reason %d", run->exit_reason);
+break;
+}
+return ret;
 }
 
 void kvm_arch_accel_class_init(ObjectClass *oc)
diff --git a/target/loongarch/trace-events b/target/loongarch/trace-events
index f801ad7c76..6cce653b20 100644
--- a/target/loongarch/trace-events
+++ b/target/loongarch/trace-events
@@ -13,3 +13,4 @@ kvm_failed_get_counter(const char *msg) "Failed to get 
counter from KVM: %s"
 kvm_failed_put_counter(const char *msg) "Failed to put counter into KVM: %s"
 kvm_failed_get_cpucfg(const char *msg) "Failed to get cpucfg from KVM: %s"
 kvm_failed_put_cpucfg(const char *msg) "Failed to put cpucfg into KVM: %s"
+kvm_arch_handle_exit(int num) "kvm arch handle exit, the reason number: %d"
-- 
2.39.1




[PATCH RFC v4 1/9] linux-headers: Add KVM headers for loongarch

2023-10-09 Thread xianglai li
From: Tianrui Zhao 

This patch is only a placeholder now, which is used to
show some kvm structures and macros for reviewers.
And it will be replaced by using update-linux-headers.sh
when the linux loongarch kvm patches are accepted.

Cc: "Michael S. Tsirkin" 
Cc: Cornelia Huck 
Cc: Paolo Bonzini 
Cc: "Marc-André Lureau" 
Cc: "Daniel P. Berrangé" 
Cc: Thomas Huth 
Cc: "Philippe Mathieu-Daudé" 
Cc: Richard Henderson 
Cc: Peter Maydell 
Cc: Bibo Mao 
Cc: Song Gao 
Cc: Xiaojuan Yang 
Cc: Tianrui Zhao 

Signed-off-by: Tianrui Zhao 
Signed-off-by: xianglai li 
---
 linux-headers/asm-loongarch/kvm.h | 100 ++
 linux-headers/linux/kvm.h |   9 +++
 2 files changed, 109 insertions(+)
 create mode 100644 linux-headers/asm-loongarch/kvm.h

diff --git a/linux-headers/asm-loongarch/kvm.h 
b/linux-headers/asm-loongarch/kvm.h
new file mode 100644
index 00..5e72b83372
--- /dev/null
+++ b/linux-headers/asm-loongarch/kvm.h
@@ -0,0 +1,100 @@
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+/*
+ * Copyright (C) 2023 Loongson Technology Corporation Limited
+ */
+
+#ifndef __UAPI_ASM_LOONGARCH_KVM_H
+#define __UAPI_ASM_LOONGARCH_KVM_H
+
+#include 
+
+/*
+ * KVM Loongarch specific structures and definitions.
+ */
+
+#define __KVM_HAVE_READONLY_MEM
+
+#define KVM_COALESCED_MMIO_PAGE_OFFSET 1
+
+/*
+ * for KVM_GET_REGS and KVM_SET_REGS
+ */
+struct kvm_regs {
+   /* out (KVM_GET_REGS) / in (KVM_SET_REGS) */
+   __u64 gpr[32];
+   __u64 pc;
+};
+
+/*
+ * for KVM_GET_FPU and KVM_SET_FPU
+ */
+struct kvm_fpu {
+   __u32 fcsr;
+   __u32 none;
+   __u64 fcc;/* 8x8 */
+   struct kvm_fpureg {
+   __u64 val64[4];
+   } fpr[32];
+};
+
+/*
+ * For LoongArch, we use KVM_SET_ONE_REG and KVM_GET_ONE_REG to access various
+ * registers.  The id field is broken down as follows:
+ *
+ *  bits[63..52] - As per linux/kvm.h
+ *  bits[51..32] - Must be zero.
+ *  bits[31..16] - Register set.
+ *
+ * Register set = 0: GP registers from kvm_regs (see definitions below).
+ *
+ * Register set = 1: CSR registers.
+ *
+ * Register set = 2: KVM specific registers (see definitions below).
+ *
+ * Register set = 3: FPU / SIMD registers (see definitions below).
+ *
+ * Other sets registers may be added in the future.  Each set would
+ * have its own identifier in bits[31..16].
+ */
+
+#define KVM_REG_LOONGARCH_GP   (KVM_REG_LOONGARCH | 0x0ULL)
+#define KVM_REG_LOONGARCH_CSR  (KVM_REG_LOONGARCH | 0x1ULL)
+#define KVM_REG_LOONGARCH_KVM  (KVM_REG_LOONGARCH | 0x2ULL)
+#define KVM_REG_LOONGARCH_FPU  (KVM_REG_LOONGARCH | 0x3ULL)
+#define KVM_REG_LOONGARCH_CPUCFG   (KVM_REG_LOONGARCH | 0x4ULL)
+#define KVM_REG_LOONGARCH_MASK (KVM_REG_LOONGARCH | 0x7ULL)
+#define KVM_CSR_IDX_MASK   0x7fff
+#define KVM_CPUCFG_IDX_MASK0x7fff
+
+/*
+ * KVM_REG_LOONGARCH_KVM - KVM specific control registers.
+ */
+
+#define KVM_REG_LOONGARCH_COUNTER  (KVM_REG_LOONGARCH_KVM | 
KVM_REG_SIZE_U64 | 3)
+#define KVM_REG_LOONGARCH_VCPU_RESET   (KVM_REG_LOONGARCH_KVM | 
KVM_REG_SIZE_U64 | 4)
+
+#define LOONGARCH_REG_SHIFT3
+#define LOONGARCH_REG_64(TYPE, REG)(TYPE | KVM_REG_SIZE_U64 | (REG << 
LOONGARCH_REG_SHIFT))
+#define KVM_IOC_CSRID(REG) LOONGARCH_REG_64(KVM_REG_LOONGARCH_CSR, 
REG)
+#define KVM_IOC_CPUCFG(REG)
LOONGARCH_REG_64(KVM_REG_LOONGARCH_CPUCFG, REG)
+
+struct kvm_debug_exit_arch {
+};
+
+/* for KVM_SET_GUEST_DEBUG */
+struct kvm_guest_debug_arch {
+};
+
+/* definition of registers in kvm_run */
+struct kvm_sync_regs {
+};
+
+/* dummy definition */
+struct kvm_sregs {
+};
+
+#define KVM_NR_IRQCHIPS1
+#define KVM_IRQCHIP_NUM_PINS   64
+#define KVM_MAX_CORES  256
+
+#endif /* __UAPI_ASM_LOONGARCH_KVM_H */
diff --git a/linux-headers/linux/kvm.h b/linux-headers/linux/kvm.h
index 0d74ee999a..0e378bbcbf 100644
--- a/linux-headers/linux/kvm.h
+++ b/linux-headers/linux/kvm.h
@@ -264,6 +264,7 @@ struct kvm_xen_exit {
 #define KVM_EXIT_RISCV_SBI35
 #define KVM_EXIT_RISCV_CSR36
 #define KVM_EXIT_NOTIFY   37
+#define KVM_EXIT_LOONGARCH_IOCSR  38
 
 /* For KVM_EXIT_INTERNAL_ERROR */
 /* Emulate instruction failed. */
@@ -336,6 +337,13 @@ struct kvm_run {
__u32 len;
__u8  is_write;
} mmio;
+   /* KVM_EXIT_LOONGARCH_IOCSR */
+   struct {
+   __u64 phys_addr;
+   __u8  data[8];
+   __u32 len;
+   __u8  is_write;
+   } iocsr_io;
/* KVM_EXIT_HYPERCALL */
struct {
__u64 nr;
@@ -1358,6 +1366,7 @@ struct kvm_dirty_tlb {
 #define KVM_REG_ARM64  0x6000ULL
 #define KVM_REG_MIPS   0x7000ULL
 #defin

[PATCH RFC v4 3/9] target/loongarch: Supplement vcpu env initial when vcpu reset

2023-10-09 Thread xianglai li
From: Tianrui Zhao 

Supplement vcpu env initial when vcpu reset, including
init vcpu CSR_CPUID,CSR_TID to cpu->cpu_index. The two
regs will be used in kvm_get/set_csr_ioctl.

Cc: "Michael S. Tsirkin" 
Cc: Cornelia Huck 
Cc: Paolo Bonzini 
Cc: "Marc-André Lureau" 
Cc: "Daniel P. Berrangé" 
Cc: Thomas Huth 
Cc: "Philippe Mathieu-Daudé" 
Cc: Richard Henderson 
Cc: Peter Maydell 
Cc: Bibo Mao 
Cc: Song Gao 
Cc: Xiaojuan Yang 
Cc: Tianrui Zhao 

Signed-off-by: Tianrui Zhao 
Signed-off-by: xianglai li 
---
 target/loongarch/cpu.c | 2 ++
 target/loongarch/cpu.h | 2 +-
 2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c
index 2bea7ca5d5..0d763d8a65 100644
--- a/target/loongarch/cpu.c
+++ b/target/loongarch/cpu.c
@@ -524,10 +524,12 @@ static void loongarch_cpu_reset_hold(Object *obj)
 
 env->CSR_ESTAT = env->CSR_ESTAT & (~MAKE_64BIT_MASK(0, 2));
 env->CSR_RVACFG = FIELD_DP64(env->CSR_RVACFG, CSR_RVACFG, RBITS, 0);
+env->CSR_CPUID = cs->cpu_index;
 env->CSR_TCFG = FIELD_DP64(env->CSR_TCFG, CSR_TCFG, EN, 0);
 env->CSR_LLBCTL = FIELD_DP64(env->CSR_LLBCTL, CSR_LLBCTL, KLO, 0);
 env->CSR_TLBRERA = FIELD_DP64(env->CSR_TLBRERA, CSR_TLBRERA, ISTLBR, 0);
 env->CSR_MERRCTL = FIELD_DP64(env->CSR_MERRCTL, CSR_MERRCTL, ISMERR, 0);
+env->CSR_TID = cs->cpu_index;
 
 env->CSR_PRCFG3 = FIELD_DP64(env->CSR_PRCFG3, CSR_PRCFG3, TLB_TYPE, 2);
 env->CSR_PRCFG3 = FIELD_DP64(env->CSR_PRCFG3, CSR_PRCFG3, MTLB_ENTRY, 63);
diff --git a/target/loongarch/cpu.h b/target/loongarch/cpu.h
index 40e70a8119..e6a99c83ab 100644
--- a/target/loongarch/cpu.h
+++ b/target/loongarch/cpu.h
@@ -318,6 +318,7 @@ typedef struct CPUArchState {
 uint64_t CSR_PWCH;
 uint64_t CSR_STLBPS;
 uint64_t CSR_RVACFG;
+uint64_t CSR_CPUID;
 uint64_t CSR_PRCFG1;
 uint64_t CSR_PRCFG2;
 uint64_t CSR_PRCFG3;
@@ -349,7 +350,6 @@ typedef struct CPUArchState {
 uint64_t CSR_DBG;
 uint64_t CSR_DERA;
 uint64_t CSR_DSAVE;
-uint64_t CSR_CPUID;
 
 #ifndef CONFIG_USER_ONLY
 LoongArchTLB  tlb[LOONGARCH_TLB_MAX];
-- 
2.39.1




[PATCH RFC v4 4/9] target/loongarch: Implement kvm get/set registers

2023-10-09 Thread xianglai li
From: Tianrui Zhao 

Implement kvm_arch_get/set_registers interfaces, many regs
can be get/set in the function, such as core regs, csr regs,
fpu regs, mp state, etc.

Cc: "Michael S. Tsirkin" 
Cc: Cornelia Huck 
Cc: Paolo Bonzini 
Cc: "Marc-André Lureau" 
Cc: "Daniel P. Berrangé" 
Cc: Thomas Huth 
Cc: "Philippe Mathieu-Daudé" 
Cc: Richard Henderson 
Cc: Peter Maydell 
Cc: Bibo Mao 
Cc: Song Gao 
Cc: Xiaojuan Yang 
Cc: Tianrui Zhao 

Signed-off-by: Tianrui Zhao 
Signed-off-by: xianglai li 
---
 meson.build   |   1 +
 target/loongarch/cpu.c|   3 +
 target/loongarch/cpu.h|   2 +
 target/loongarch/kvm.c| 406 +-
 target/loongarch/trace-events |  13 ++
 target/loongarch/trace.h  |   1 +
 6 files changed, 424 insertions(+), 2 deletions(-)
 create mode 100644 target/loongarch/trace-events
 create mode 100644 target/loongarch/trace.h

diff --git a/meson.build b/meson.build
index 3bb64b536c..1c71ead833 100644
--- a/meson.build
+++ b/meson.build
@@ -3305,6 +3305,7 @@ if have_system or have_user
 'target/hppa',
 'target/i386',
 'target/i386/kvm',
+'target/loongarch',
 'target/mips/tcg',
 'target/nios2',
 'target/ppc',
diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c
index 0d763d8a65..61344c7ad2 100644
--- a/target/loongarch/cpu.c
+++ b/target/loongarch/cpu.c
@@ -546,6 +546,9 @@ static void loongarch_cpu_reset_hold(Object *obj)
 #ifndef CONFIG_USER_ONLY
 env->pc = 0x1c00;
 memset(env->tlb, 0, sizeof(env->tlb));
+if (kvm_enabled()) {
+kvm_arch_reset_vcpu(env);
+}
 #endif
 
 restore_fp_status(env);
diff --git a/target/loongarch/cpu.h b/target/loongarch/cpu.h
index e6a99c83ab..2580dc26e1 100644
--- a/target/loongarch/cpu.h
+++ b/target/loongarch/cpu.h
@@ -359,6 +359,7 @@ typedef struct CPUArchState {
 MemoryRegion iocsr_mem;
 bool load_elf;
 uint64_t elf_address;
+uint32_t mp_state;
 /* Store ipistate to access from this struct */
 DeviceState *ipistate;
 #endif
@@ -477,6 +478,7 @@ static inline void cpu_get_tb_cpu_state(CPULoongArchState 
*env, vaddr *pc,
 }
 
 void loongarch_cpu_list(void);
+void kvm_arch_reset_vcpu(CPULoongArchState *env);
 
 #define cpu_list loongarch_cpu_list
 
diff --git a/target/loongarch/kvm.c b/target/loongarch/kvm.c
index 0d67322fd9..8fda80b107 100644
--- a/target/loongarch/kvm.c
+++ b/target/loongarch/kvm.c
@@ -26,19 +26,421 @@
 #include "sysemu/runstate.h"
 #include "cpu-csr.h"
 #include "kvm_loongarch.h"
+#include "trace.h"
 
 static bool cap_has_mp_state;
 const KVMCapabilityInfo kvm_arch_required_capabilities[] = {
 KVM_CAP_LAST_INFO
 };
 
+static int kvm_loongarch_get_regs_core(CPUState *cs)
+{
+int ret = 0;
+int i;
+struct kvm_regs regs;
+LoongArchCPU *cpu = LOONGARCH_CPU(cs);
+CPULoongArchState *env = >env;
+
+/* Get the current register set as KVM seems it */
+ret = kvm_vcpu_ioctl(cs, KVM_GET_REGS, );
+if (ret < 0) {
+trace_kvm_failed_get_regs_core(strerror(errno));
+return ret;
+}
+/* gpr[0] value is always 0 */
+env->gpr[0] = 0;
+for (i = 1; i < 32; i++) {
+env->gpr[i] = regs.gpr[i];
+}
+
+env->pc = regs.pc;
+return ret;
+}
+
+static int kvm_loongarch_put_regs_core(CPUState *cs)
+{
+int ret = 0;
+int i;
+struct kvm_regs regs;
+LoongArchCPU *cpu = LOONGARCH_CPU(cs);
+CPULoongArchState *env = >env;
+
+/* Set the registers based on QEMU's view of things */
+for (i = 0; i < 32; i++) {
+regs.gpr[i] = env->gpr[i];
+}
+
+regs.pc = env->pc;
+ret = kvm_vcpu_ioctl(cs, KVM_SET_REGS, );
+if (ret < 0) {
+trace_kvm_failed_put_regs_core(strerror(errno));
+}
+
+return ret;
+}
+
+static int kvm_larch_getq(CPUState *cs, uint64_t reg_id,
+ uint64_t *addr)
+{
+struct kvm_one_reg csrreg = {
+.id = reg_id,
+.addr = (uintptr_t)addr
+};
+
+return kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, );
+}
+
+static int kvm_larch_putq(CPUState *cs, uint64_t reg_id,
+ uint64_t *addr)
+{
+struct kvm_one_reg csrreg = {
+.id = reg_id,
+.addr = (uintptr_t)addr
+};
+
+return kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, );
+}
+
+#define KVM_GET_ONE_UREG64(cs, ret, regidx, addr) \
+({\
+err = kvm_larch_getq(cs, KVM_IOC_CSRID(regidx), addr);\
+if (err < 0) {\
+ret = err;\
+trace_kvm_failed_get_csr(regidx, strerror(errno));\
+} \
+})
+
+#define KVM_PUT_ONE_UREG64(cs, ret, regidx, addr) 

[PATCH RFC v4 9/9] target/loongarch: Add loongarch kvm into meson build

2023-10-09 Thread xianglai li
From: Tianrui Zhao 

Add kvm.c and kvm-stub.c into meson.build to compile
it when kvm is configed. Meanwhile in meson.build,
we set the kvm_targets to loongarch64-softmmu when
the cpu is loongarch.

Cc: "Michael S. Tsirkin" 
Cc: Cornelia Huck 
Cc: Paolo Bonzini 
Cc: "Marc-André Lureau" 
Cc: "Daniel P. Berrangé" 
Cc: Thomas Huth 
Cc: "Philippe Mathieu-Daudé" 
Cc: Richard Henderson 
Cc: Peter Maydell 
Cc: Bibo Mao 
Cc: Song Gao 
Cc: Xiaojuan Yang 
Cc: Tianrui Zhao 

Signed-off-by: Tianrui Zhao 
Signed-off-by: xianglai li 
---
 meson.build  | 2 ++
 target/loongarch/meson.build | 1 +
 2 files changed, 3 insertions(+)

diff --git a/meson.build b/meson.build
index 1c71ead833..1f8f3ea136 100644
--- a/meson.build
+++ b/meson.build
@@ -114,6 +114,8 @@ elif cpu in ['riscv32']
   kvm_targets = ['riscv32-softmmu']
 elif cpu in ['riscv64']
   kvm_targets = ['riscv64-softmmu']
+elif cpu in ['loongarch64']
+  kvm_targets = ['loongarch64-softmmu']
 else
   kvm_targets = []
 endif
diff --git a/target/loongarch/meson.build b/target/loongarch/meson.build
index 7fbf045a5d..dc2e452b1c 100644
--- a/target/loongarch/meson.build
+++ b/target/loongarch/meson.build
@@ -27,6 +27,7 @@ loongarch_system_ss.add(files(
 
 common_ss.add(when: 'CONFIG_LOONGARCH_DIS', if_true: [files('disas.c'), gen])
 
+loongarch_ss.add(when: 'CONFIG_KVM', if_true: files('kvm.c'), if_false: 
files('kvm-stub.c'))
 loongarch_ss.add_all(when: 'CONFIG_TCG', if_true: [loongarch_tcg_ss])
 
 target_arch += {'loongarch': loongarch_ss}
-- 
2.39.1




[PATCH RFC v4 8/9] target/loongarch: Implement set vcpu intr for kvm

2023-10-09 Thread xianglai li
From: Tianrui Zhao 

Implement loongarch kvm set vcpu interrupt interface,
when a irq is set in vcpu, we use the KVM_INTERRUPT
ioctl to set intr into kvm.

Cc: "Michael S. Tsirkin" 
Cc: Cornelia Huck 
Cc: Paolo Bonzini 
Cc: "Marc-André Lureau" 
Cc: "Daniel P. Berrangé" 
Cc: Thomas Huth 
Cc: "Philippe Mathieu-Daudé" 
Cc: Richard Henderson 
Cc: Peter Maydell 
Cc: Bibo Mao 
Cc: Song Gao 
Cc: Xiaojuan Yang 
Cc: Tianrui Zhao 

Signed-off-by: Tianrui Zhao 
Signed-off-by: xianglai li 
---
 target/loongarch/cpu.c   | 18 +-
 target/loongarch/kvm-stub.c  | 11 +++
 target/loongarch/kvm.c   | 15 +++
 target/loongarch/kvm_loongarch.h | 13 +
 target/loongarch/trace-events|  1 +
 5 files changed, 53 insertions(+), 5 deletions(-)
 create mode 100644 target/loongarch/kvm-stub.c
 create mode 100644 target/loongarch/kvm_loongarch.h

diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c
index 61344c7ad2..670612dd0b 100644
--- a/target/loongarch/cpu.c
+++ b/target/loongarch/cpu.c
@@ -20,6 +20,11 @@
 #include "sysemu/reset.h"
 #include "tcg/tcg.h"
 #include "vec.h"
+#include "sysemu/kvm.h"
+#include "kvm_loongarch.h"
+#ifdef CONFIG_KVM
+#include 
+#endif
 
 const char * const regnames[32] = {
 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
@@ -108,12 +113,15 @@ void loongarch_cpu_set_irq(void *opaque, int irq, int 
level)
 return;
 }
 
-env->CSR_ESTAT = deposit64(env->CSR_ESTAT, irq, 1, level != 0);
-
-if (FIELD_EX64(env->CSR_ESTAT, CSR_ESTAT, IS)) {
-cpu_interrupt(cs, CPU_INTERRUPT_HARD);
+if (kvm_enabled()) {
+kvm_loongarch_set_interrupt(cpu, irq, level);
 } else {
-cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
+env->CSR_ESTAT = deposit64(env->CSR_ESTAT, irq, 1, level != 0);
+if (FIELD_EX64(env->CSR_ESTAT, CSR_ESTAT, IS)) {
+cpu_interrupt(cs, CPU_INTERRUPT_HARD);
+} else {
+cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
+}
 }
 }
 
diff --git a/target/loongarch/kvm-stub.c b/target/loongarch/kvm-stub.c
new file mode 100644
index 00..9965c1f119
--- /dev/null
+++ b/target/loongarch/kvm-stub.c
@@ -0,0 +1,11 @@
+/*
+ * QEMU KVM LoongArch specific function stubs
+ *
+ * Copyright (c) 2023 Loongson Technology Corporation Limited
+ */
+#include "cpu.h"
+
+void kvm_loongarch_set_interrupt(LoongArchCPU *cpu, int irq, int level)
+{
+   g_assert_not_reached();
+}
diff --git a/target/loongarch/kvm.c b/target/loongarch/kvm.c
index 0fe52434ed..df8d5f 100644
--- a/target/loongarch/kvm.c
+++ b/target/loongarch/kvm.c
@@ -574,6 +574,21 @@ int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run)
 return ret;
 }
 
+int kvm_loongarch_set_interrupt(LoongArchCPU *cpu, int irq, int level)
+{
+struct kvm_interrupt intr;
+CPUState *cs = CPU(cpu);
+
+if (level) {
+intr.irq = irq;
+} else {
+intr.irq = -irq;
+}
+
+trace_kvm_set_intr(irq, level);
+return kvm_vcpu_ioctl(cs, KVM_INTERRUPT, );
+}
+
 void kvm_arch_accel_class_init(ObjectClass *oc)
 {
 }
diff --git a/target/loongarch/kvm_loongarch.h b/target/loongarch/kvm_loongarch.h
new file mode 100644
index 00..cdef980eec
--- /dev/null
+++ b/target/loongarch/kvm_loongarch.h
@@ -0,0 +1,13 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * QEMU LoongArch kvm interface
+ *
+ * Copyright (c) 2023 Loongson Technology Corporation Limited
+ */
+
+#ifndef QEMU_KVM_LOONGARCH_H
+#define QEMU_KVM_LOONGARCH_H
+
+int  kvm_loongarch_set_interrupt(LoongArchCPU *cpu, int irq, int level);
+
+#endif
diff --git a/target/loongarch/trace-events b/target/loongarch/trace-events
index 6cce653b20..3263406ebe 100644
--- a/target/loongarch/trace-events
+++ b/target/loongarch/trace-events
@@ -14,3 +14,4 @@ kvm_failed_put_counter(const char *msg) "Failed to put 
counter into KVM: %s"
 kvm_failed_get_cpucfg(const char *msg) "Failed to get cpucfg from KVM: %s"
 kvm_failed_put_cpucfg(const char *msg) "Failed to put cpucfg into KVM: %s"
 kvm_arch_handle_exit(int num) "kvm arch handle exit, the reason number: %d"
+kvm_set_intr(int irq, int level) "kvm set interrupt, irq num: %d, level: %d"
-- 
2.39.1




[PATCH RFC v4 5/9] target/loongarch: Implement kvm_arch_init function

2023-10-09 Thread xianglai li
From: Tianrui Zhao 

Implement the kvm_arch_init of loongarch, in the function, the
KVM_CAP_MP_STATE cap is checked by kvm ioctl.

Cc: "Michael S. Tsirkin" 
Cc: Cornelia Huck 
Cc: Paolo Bonzini 
Cc: "Marc-André Lureau" 
Cc: "Daniel P. Berrangé" 
Cc: Thomas Huth 
Cc: "Philippe Mathieu-Daudé" 
Cc: Richard Henderson 
Cc: Peter Maydell 
Cc: Bibo Mao 
Cc: Song Gao 
Cc: Xiaojuan Yang 
Cc: Tianrui Zhao 

Signed-off-by: Tianrui Zhao 
Reviewed-by: Richard Henderson 
Signed-off-by: xianglai li 
---
 target/loongarch/kvm.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/target/loongarch/kvm.c b/target/loongarch/kvm.c
index 8fda80b107..5e3bda444e 100644
--- a/target/loongarch/kvm.c
+++ b/target/loongarch/kvm.c
@@ -491,6 +491,7 @@ int kvm_arch_get_default_type(MachineState *ms)
 
 int kvm_arch_init(MachineState *ms, KVMState *s)
 {
+cap_has_mp_state = kvm_check_extension(s, KVM_CAP_MP_STATE);
 return 0;
 }
 
-- 
2.39.1




[PATCH RFC v4 6/9] target/loongarch: Implement kvm_arch_init_vcpu

2023-10-09 Thread xianglai li
From: Tianrui Zhao 

Implement kvm_arch_init_vcpu interface for loongarch,
in this function, we register VM change state handler.
And when VM state changes to running, the counter value
should be put into kvm to keep consistent with kvm,
and when state change to stop, counter value should be
refreshed from kvm.

Cc: "Michael S. Tsirkin" 
Cc: Cornelia Huck 
Cc: Paolo Bonzini 
Cc: "Marc-André Lureau" 
Cc: "Daniel P. Berrangé" 
Cc: Thomas Huth 
Cc: "Philippe Mathieu-Daudé" 
Cc: Richard Henderson 
Cc: Peter Maydell 
Cc: Bibo Mao 
Cc: Song Gao 
Cc: Xiaojuan Yang 
Cc: Tianrui Zhao 

Signed-off-by: Tianrui Zhao 
Signed-off-by: xianglai li 
---
 target/loongarch/cpu.h|  2 ++
 target/loongarch/kvm.c| 23 +++
 target/loongarch/trace-events |  2 ++
 3 files changed, 27 insertions(+)

diff --git a/target/loongarch/cpu.h b/target/loongarch/cpu.h
index 2580dc26e1..49edf6b016 100644
--- a/target/loongarch/cpu.h
+++ b/target/loongarch/cpu.h
@@ -382,6 +382,8 @@ struct ArchCPU {
 
 /* 'compatible' string for this CPU for Linux device trees */
 const char *dtb_compatible;
+/* used by KVM_REG_LOONGARCH_COUNTER ioctl to access guest time counters */
+uint64_t kvm_state_counter;
 };
 
 #define TYPE_LOONGARCH_CPU "loongarch-cpu"
diff --git a/target/loongarch/kvm.c b/target/loongarch/kvm.c
index 5e3bda444e..9754478e34 100644
--- a/target/loongarch/kvm.c
+++ b/target/loongarch/kvm.c
@@ -443,8 +443,31 @@ int kvm_arch_put_registers(CPUState *cs, int level)
 return ret;
 }
 
+static void kvm_loongarch_vm_stage_change(void *opaque, bool running,
+  RunState state)
+{
+int ret;
+CPUState *cs = opaque;
+LoongArchCPU *cpu = LOONGARCH_CPU(cs);
+
+if (running) {
+ret = kvm_larch_putq(cs, KVM_REG_LOONGARCH_COUNTER,
+ >kvm_state_counter);
+if (ret < 0) {
+trace_kvm_failed_put_counter(strerror(errno));
+}
+} else {
+ret = kvm_larch_getq(cs, KVM_REG_LOONGARCH_COUNTER,
+ >kvm_state_counter);
+if (ret < 0) {
+trace_kvm_failed_get_counter(strerror(errno));
+}
+}
+}
+
 int kvm_arch_init_vcpu(CPUState *cs)
 {
+qemu_add_vm_change_state_handler(kvm_loongarch_vm_stage_change, cs);
 return 0;
 }
 
diff --git a/target/loongarch/trace-events b/target/loongarch/trace-events
index ceba80121b..f801ad7c76 100644
--- a/target/loongarch/trace-events
+++ b/target/loongarch/trace-events
@@ -9,5 +9,7 @@ kvm_failed_get_fpu(const char *msg) "Failed to get fpu from 
KVM: %s"
 kvm_failed_put_fpu(const char *msg) "Failed to put fpu into KVM: %s"
 kvm_failed_get_mpstate(const char *msg) "Failed to get mp_state from KVM: %s"
 kvm_failed_put_mpstate(const char *msg) "Failed to put mp_state into KVM: %s"
+kvm_failed_get_counter(const char *msg) "Failed to get counter from KVM: %s"
+kvm_failed_put_counter(const char *msg) "Failed to put counter into KVM: %s"
 kvm_failed_get_cpucfg(const char *msg) "Failed to get cpucfg from KVM: %s"
 kvm_failed_put_cpucfg(const char *msg) "Failed to put cpucfg into KVM: %s"
-- 
2.39.1




[PATCH RFC v4 2/9] target/loongarch: Define some kvm_arch interfaces

2023-10-09 Thread xianglai li
From: Tianrui Zhao 

Define some functions in target/loongarch/kvm.c, such as
kvm_arch_put_registers, kvm_arch_get_registers and
kvm_arch_handle_exit, etc. which are needed by kvm/kvm-all.c.
Now the most functions has no content and they will be
implemented in the next patches.

Cc: "Michael S. Tsirkin" 
Cc: Cornelia Huck 
Cc: Paolo Bonzini 
Cc: "Marc-André Lureau" 
Cc: "Daniel P. Berrangé" 
Cc: Thomas Huth 
Cc: "Philippe Mathieu-Daudé" 
Cc: Richard Henderson 
Cc: Peter Maydell 
Cc: Bibo Mao 
Cc: Song Gao 
Cc: Xiaojuan Yang 
Cc: Tianrui Zhao 

Signed-off-by: Tianrui Zhao 
Reviewed-by: Richard Henderson 
Signed-off-by: xianglai li 
---
 target/loongarch/kvm.c | 131 +
 1 file changed, 131 insertions(+)
 create mode 100644 target/loongarch/kvm.c

diff --git a/target/loongarch/kvm.c b/target/loongarch/kvm.c
new file mode 100644
index 00..0d67322fd9
--- /dev/null
+++ b/target/loongarch/kvm.c
@@ -0,0 +1,131 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * QEMU LoongArch KVM
+ *
+ * Copyright (c) 2023 Loongson Technology Corporation Limited
+ */
+
+#include "qemu/osdep.h"
+#include 
+#include 
+
+#include "qemu/timer.h"
+#include "qemu/error-report.h"
+#include "qemu/main-loop.h"
+#include "sysemu/sysemu.h"
+#include "sysemu/kvm.h"
+#include "sysemu/kvm_int.h"
+#include "hw/pci/pci.h"
+#include "exec/memattrs.h"
+#include "exec/address-spaces.h"
+#include "hw/boards.h"
+#include "hw/irq.h"
+#include "qemu/log.h"
+#include "hw/loader.h"
+#include "migration/migration.h"
+#include "sysemu/runstate.h"
+#include "cpu-csr.h"
+#include "kvm_loongarch.h"
+
+static bool cap_has_mp_state;
+const KVMCapabilityInfo kvm_arch_required_capabilities[] = {
+KVM_CAP_LAST_INFO
+};
+
+int kvm_arch_get_registers(CPUState *cs)
+{
+return 0;
+}
+int kvm_arch_put_registers(CPUState *cs, int level)
+{
+return 0;
+}
+
+int kvm_arch_init_vcpu(CPUState *cs)
+{
+return 0;
+}
+
+int kvm_arch_destroy_vcpu(CPUState *cs)
+{
+return 0;
+}
+
+unsigned long kvm_arch_vcpu_id(CPUState *cs)
+{
+return cs->cpu_index;
+}
+
+int kvm_arch_release_virq_post(int virq)
+{
+return 0;
+}
+
+int kvm_arch_msi_data_to_gsi(uint32_t data)
+{
+abort();
+}
+
+int kvm_arch_fixup_msi_route(struct kvm_irq_routing_entry *route,
+ uint64_t address, uint32_t data, PCIDevice *dev)
+{
+return 0;
+}
+
+int kvm_arch_add_msi_route_post(struct kvm_irq_routing_entry *route,
+int vector, PCIDevice *dev)
+{
+return 0;
+}
+
+void kvm_arch_init_irq_routing(KVMState *s)
+{
+}
+
+int kvm_arch_get_default_type(MachineState *ms)
+{
+return 0;
+}
+
+int kvm_arch_init(MachineState *ms, KVMState *s)
+{
+return 0;
+}
+
+int kvm_arch_irqchip_create(KVMState *s)
+{
+return 0;
+}
+
+void kvm_arch_pre_run(CPUState *cs, struct kvm_run *run)
+{
+}
+
+MemTxAttrs kvm_arch_post_run(CPUState *cs, struct kvm_run *run)
+{
+return MEMTXATTRS_UNSPECIFIED;
+}
+
+int kvm_arch_process_async_events(CPUState *cs)
+{
+return cs->halted;
+}
+
+bool kvm_arch_stop_on_emulation_error(CPUState *cs)
+{
+return true;
+}
+
+bool kvm_arch_cpu_check_are_resettable(void)
+{
+return true;
+}
+
+int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run)
+{
+return 0;
+}
+
+void kvm_arch_accel_class_init(ObjectClass *oc)
+{
+}
-- 
2.39.1




[PATCH v3 2/7] Update CPUs AML with cpu-(ctrl)dev change

2023-09-26 Thread xianglai li
CPUs Control device(\\_SB.PCI0) register interface for the x86 arch
is based on PCI and is IO port based and hence existing cpus AML code
assumes _CRS objects would evaluate to a system resource which describes
IO Port address.
But on Loongarch arch CPUs control device(\\_SB.PRES) register interface
is memory-mapped hence _CRS object should evaluate to system resource
which describes memory-mapped base address.

This cpus AML code change updates the existing interface of the build cpus AML
function to accept both IO/MEMORY type regions and update the _CRS object
correspondingly.

Co-authored-by: "Bernhard Beschow" 
Co-authored-by: "Salil Mehta" 
Co-authored-by: "Salil Mehta" 
Cc: "Bernhard Beschow" 
Cc: "Salil Mehta" 
Cc: "Salil Mehta" 
Cc: Xiaojuan Yang 
Cc: Song Gao 
Cc: "Michael S. Tsirkin" 
Cc: Igor Mammedov 
Cc: Ani Sinha 
Cc: Paolo Bonzini 
Cc: Richard Henderson 
Cc: Eduardo Habkost 
Cc: Marcel Apfelbaum 
Cc: "Philippe Mathieu-Daudé" 
Cc: Yanan Wang 
Cc: "Daniel P. Berrangé" 
Cc: Peter Xu 
Cc: David Hildenbrand 
Cc: Bibo Mao 
Signed-off-by: xianglai li 
---
 hw/acpi/cpu.c | 20 +++-
 hw/i386/acpi-build.c  |  3 ++-
 include/hw/acpi/cpu.h |  5 +++--
 3 files changed, 20 insertions(+), 8 deletions(-)

diff --git a/hw/acpi/cpu.c b/hw/acpi/cpu.c
index 5bad983928..0afa04832e 100644
--- a/hw/acpi/cpu.c
+++ b/hw/acpi/cpu.c
@@ -6,6 +6,7 @@
 #include "qapi/qapi-events-acpi.h"
 #include "trace.h"
 #include "sysemu/numa.h"
+#include "hw/acpi/cpu_hotplug.h"
 
 #define OVMF_CPUHP_SMI_CMD 4
 
@@ -332,9 +333,10 @@ const VMStateDescription vmstate_cpu_hotplug = {
 #define CPU_FW_EJECT_EVENT "CEJF"
 
 void build_cpus_aml(Aml *table, MachineState *machine, CPUHotplugFeatures opts,
-build_madt_cpu_fn build_madt_cpu, hwaddr io_base,
+build_madt_cpu_fn build_madt_cpu, hwaddr mmap_io_base,
 const char *res_root,
-const char *event_handler_method)
+const char *event_handler_method,
+AmlRegionSpace rs)
 {
 Aml *ifctx;
 Aml *field;
@@ -359,14 +361,22 @@ void build_cpus_aml(Aml *table, MachineState *machine, 
CPUHotplugFeatures opts,
 aml_append(cpu_ctrl_dev, aml_mutex(CPU_LOCK, 0));
 
 crs = aml_resource_template();
-aml_append(crs, aml_io(AML_DECODE16, io_base, io_base, 1,
+if (rs == AML_SYSTEM_IO) {
+aml_append(crs, aml_io(AML_DECODE16, mmap_io_base, mmap_io_base, 1,
ACPI_CPU_HOTPLUG_REG_LEN));
+} else {
+aml_append(crs, aml_memory32_fixed(mmap_io_base,
+   ACPI_CPU_HOTPLUG_REG_LEN, AML_READ_WRITE));
+}
+
 aml_append(cpu_ctrl_dev, aml_name_decl("_CRS", crs));
 
+g_assert(rs == AML_SYSTEM_IO || rs == AML_SYSTEM_MEMORY);
 /* declare CPU hotplug MMIO region with related access fields */
 aml_append(cpu_ctrl_dev,
-aml_operation_region("PRST", AML_SYSTEM_IO, aml_int(io_base),
- ACPI_CPU_HOTPLUG_REG_LEN));
+aml_operation_region("PRST", rs,
+ aml_int(mmap_io_base),
+ ACPI_CPU_HOTPLUG_REG_LEN));
 
 field = aml_field("PRST", AML_BYTE_ACC, AML_NOLOCK,
   AML_WRITE_AS_ZEROS);
diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
index 863a939210..7016205d15 100644
--- a/hw/i386/acpi-build.c
+++ b/hw/i386/acpi-build.c
@@ -1550,7 +1550,8 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,
 .fw_unplugs_cpu = pm->smi_on_cpu_unplug,
 };
 build_cpus_aml(dsdt, machine, opts, pc_madt_cpu_entry,
-   pm->cpu_hp_io_base, "\\_SB.PCI0", "\\_GPE._E02");
+   pm->cpu_hp_io_base, "\\_SB.PCI0", "\\_GPE._E02",
+   AML_SYSTEM_IO);
 }
 
 if (pcms->memhp_io_base && nr_mem) {
diff --git a/include/hw/acpi/cpu.h b/include/hw/acpi/cpu.h
index bc901660fb..601f644e57 100644
--- a/include/hw/acpi/cpu.h
+++ b/include/hw/acpi/cpu.h
@@ -60,9 +60,10 @@ typedef void (*build_madt_cpu_fn)(int uid, const 
CPUArchIdList *apic_ids,
   GArray *entry, bool force_enabled);
 
 void build_cpus_aml(Aml *table, MachineState *machine, CPUHotplugFeatures opts,
-build_madt_cpu_fn build_madt_cpu, hwaddr io_base,
+build_madt_cpu_fn build_madt_cpu, hwaddr mmap_io_base,
 const char *res_root,
-const char *event_handler_method);
+const char *event_handler_method,
+AmlRegionSpace rs);
 
 void acpi_cpu_ospm_status(CPUHotplugState *cpu_st, ACPIOSTInfoList ***list);
 
-- 
2.39.1




[PATCH v3 6/7] Add support of *unrealize* for Loongarch cpu

2023-09-26 Thread xianglai li
Add the unrealize function to the Loongarch CPU for cpu hot-(un)plug

Cc: "Bernhard Beschow" 
Cc: "Salil Mehta" 
Cc: "Salil Mehta" 
Cc: Xiaojuan Yang 
Cc: Song Gao 
Cc: "Michael S. Tsirkin" 
Cc: Igor Mammedov 
Cc: Ani Sinha 
Cc: Paolo Bonzini 
Cc: Richard Henderson 
Cc: Eduardo Habkost 
Cc: Marcel Apfelbaum 
Cc: "Philippe Mathieu-Daudé" 
Cc: Yanan Wang 
Cc: "Daniel P. Berrangé" 
Cc: Peter Xu 
Cc: David Hildenbrand 
Cc: Bibo Mao 
Signed-off-by: xianglai li 
---
 target/loongarch/cpu.c | 20 
 target/loongarch/cpu.h |  1 +
 2 files changed, 21 insertions(+)

diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c
index 40b856554f..92fb23704f 100644
--- a/target/loongarch/cpu.c
+++ b/target/loongarch/cpu.c
@@ -576,6 +576,22 @@ static void loongarch_cpu_realizefn(DeviceState *dev, 
Error **errp)
 lacc->parent_realize(dev, errp);
 }
 
+static void loongarch_cpu_unrealizefn(DeviceState *dev)
+{
+LoongArchCPUClass *mcc = LOONGARCH_CPU_GET_CLASS(dev);
+
+#ifndef CONFIG_USER_ONLY
+LoongArchCPU *cpu = LOONGARCH_CPU(dev);
+CPULoongArchState *env = >env;
+
+cpu_remove_sync(CPU(dev));
+address_space_destroy(>address_space_iocsr);
+memory_region_del_subregion(>system_iocsr, >iocsr_mem);
+#endif
+
+mcc->parent_unrealize(dev);
+}
+
 #ifndef CONFIG_USER_ONLY
 static void loongarch_qemu_write(void *opaque, hwaddr addr,
  uint64_t val, unsigned size)
@@ -756,6 +772,9 @@ static void loongarch_cpu_class_init(ObjectClass *c, void 
*data)
 device_class_set_props(dc, loongarch_cpu_properties);
 device_class_set_parent_realize(dc, loongarch_cpu_realizefn,
 >parent_realize);
+device_class_set_parent_unrealize(dc, loongarch_cpu_unrealizefn,
+  >parent_unrealize);
+
 resettable_class_set_parent_phases(rc, NULL, loongarch_cpu_reset_hold, 
NULL,
>parent_phases);
 
@@ -777,6 +796,7 @@ static void loongarch_cpu_class_init(ObjectClass *c, void 
*data)
 #ifdef CONFIG_TCG
 cc->tcg_ops = _tcg_ops;
 #endif
+dc->user_creatable = true;
 }
 
 static gchar *loongarch32_gdb_arch_name(CPUState *cs)
diff --git a/target/loongarch/cpu.h b/target/loongarch/cpu.h
index 838492f014..ec4a9ff166 100644
--- a/target/loongarch/cpu.h
+++ b/target/loongarch/cpu.h
@@ -414,6 +414,7 @@ struct LoongArchCPUClass {
 /*< public >*/
 
 DeviceRealize parent_realize;
+DeviceUnrealize parent_unrealize;
 ResettablePhases parent_phases;
 };
 
-- 
2.39.1




[PATCH v3 4/7] Optimize loongarch_irq_init function implementation

2023-09-26 Thread xianglai li
Optimize loongarch_irq_init function implementation
and abstract the function loongarch_cpu_irq_init from it.

Cc: "Bernhard Beschow" 
Cc: "Salil Mehta" 
Cc: "Salil Mehta" 
Cc: Xiaojuan Yang 
Cc: Song Gao 
Cc: "Michael S. Tsirkin" 
Cc: Igor Mammedov 
Cc: Ani Sinha 
Cc: Paolo Bonzini 
Cc: Richard Henderson 
Cc: Eduardo Habkost 
Cc: Marcel Apfelbaum 
Cc: "Philippe Mathieu-Daudé" 
Cc: Yanan Wang 
Cc: "Daniel P. Berrangé" 
Cc: Peter Xu 
Cc: David Hildenbrand 
Cc: Bibo Mao 
Signed-off-by: xianglai li 
---
 hw/loongarch/virt.c | 105 
 include/hw/loongarch/virt.h |   5 +-
 2 files changed, 62 insertions(+), 48 deletions(-)

diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c
index b8474e7b94..fb06b4ab4e 100644
--- a/hw/loongarch/virt.c
+++ b/hw/loongarch/virt.c
@@ -46,6 +46,8 @@
 #include "hw/block/flash.h"
 #include "qemu/error-report.h"
 
+static LoongArchCPU *loongarch_cpu_irq_init(MachineState *machine,
+LoongArchCPU *cpu, Error **errp);
 
 static void virt_flash_create(LoongArchMachineState *lams)
 {
@@ -573,16 +575,16 @@ static void loongarch_devices_init(DeviceState *pch_pic, 
LoongArchMachineState *
 static void loongarch_irq_init(LoongArchMachineState *lams)
 {
 MachineState *ms = MACHINE(lams);
-DeviceState *pch_pic, *pch_msi, *cpudev;
-DeviceState *ipi, *extioi;
+DeviceState *pch_pic, *pch_msi;
+DeviceState *extioi;
 SysBusDevice *d;
 LoongArchCPU *lacpu;
-CPULoongArchState *env;
 CPUState *cpu_state;
-int cpu, pin, i, start, num;
+int cpu, i, start, num;
 
 extioi = qdev_new(TYPE_LOONGARCH_EXTIOI);
 sysbus_realize_and_unref(SYS_BUS_DEVICE(extioi), _fatal);
+lams->extioi = extioi;
 
 /*
  * The connection of interrupts:
@@ -607,44 +609,8 @@ static void loongarch_irq_init(LoongArchMachineState *lams)
  */
 for (cpu = 0; cpu < ms->smp.cpus; cpu++) {
 cpu_state = qemu_get_cpu(cpu);
-cpudev = DEVICE(cpu_state);
 lacpu = LOONGARCH_CPU(cpu_state);
-env = &(lacpu->env);
-
-ipi = qdev_new(TYPE_LOONGARCH_IPI);
-sysbus_realize_and_unref(SYS_BUS_DEVICE(ipi), _fatal);
-
-/* connect ipi irq to cpu irq */
-qdev_connect_gpio_out(ipi, 0, qdev_get_gpio_in(cpudev, IRQ_IPI));
-/* IPI iocsr memory region */
-memory_region_add_subregion(>system_iocsr, SMP_IPI_MAILBOX,
-sysbus_mmio_get_region(SYS_BUS_DEVICE(ipi),
-0));
-memory_region_add_subregion(>system_iocsr, MAIL_SEND_ADDR,
-sysbus_mmio_get_region(SYS_BUS_DEVICE(ipi),
-1));
-/*
- * extioi iocsr memory region
- * only one extioi is added on loongarch virt machine
- * external device interrupt can only be routed to cpu 0-3
- */
-if (cpu < EXTIOI_CPUS)
-memory_region_add_subregion(>system_iocsr, APIC_BASE,
-sysbus_mmio_get_region(SYS_BUS_DEVICE(extioi),
-cpu));
-env->ipistate = ipi;
-}
-
-/*
- * connect ext irq to the cpu irq
- * cpu_pin[9:2] <= intc_pin[7:0]
- */
-for (cpu = 0; cpu < MIN(ms->smp.cpus, EXTIOI_CPUS); cpu++) {
-cpudev = DEVICE(qemu_get_cpu(cpu));
-for (pin = 0; pin < LS3A_INTC_IP; pin++) {
-qdev_connect_gpio_out(extioi, (cpu * 8 + pin),
-  qdev_get_gpio_in(cpudev, pin + 2));
-}
+loongarch_cpu_irq_init(ms, lacpu, _fatal);
 }
 
 pch_pic = qdev_new(TYPE_LOONGARCH_PCH_PIC);
@@ -927,11 +893,7 @@ static void loongarch_init(MachineState *machine)
 }
 }
 fdt_add_flash_node(lams);
-/* register reset function */
-for (i = 0; i < machine->smp.cpus; i++) {
-lacpu = LOONGARCH_CPU(qemu_get_cpu(i));
-qemu_register_reset(reset_load_elf, lacpu);
-}
+
 /* Initialize the IO interrupt subsystem */
 loongarch_irq_init(lams);
 fdt_add_irqchip_node(lams);
@@ -1091,6 +1053,57 @@ static void virt_mem_plug(HotplugHandler *hotplug_dev,
  dev, _abort);
 }
 
+static LoongArchCPU *loongarch_cpu_irq_init(MachineState *machine,
+LoongArchCPU *cpu, Error **errp)
+{
+LoongArchMachineState *lsms = LOONGARCH_MACHINE(machine);
+CPUState *cs = CPU(cpu);
+unsigned int cpu_index = cs->cpu_index;
+DeviceState *cpudev = DEVICE(cpu);
+DeviceState *extioi = lsms->extioi;
+CPULoongArchState *env = >env;
+DeviceState *ipi;
+int pin;
+
+qemu_register_reset(reset_load_elf, cpu);
+
+ipi = qdev_new(TYPE_LOONGARCH_IPI);
+sysbus_realize_and_unref(SYS_BUS_DEVICE(ipi), errp);
+
+ 

[PATCH v3 7/7] Update the ACPI table for the Loongarch CPU

2023-09-26 Thread xianglai li
Add new types of GED devices for Loongarch machines,
add CPU hot-(un)plug event response and address spaces,
and update the ACPI table.

Cc: "Bernhard Beschow" 
Cc: "Salil Mehta" 
Cc: "Salil Mehta" 
Cc: Xiaojuan Yang 
Cc: Song Gao 
Cc: "Michael S. Tsirkin" 
Cc: Igor Mammedov 
Cc: Ani Sinha 
Cc: Paolo Bonzini 
Cc: Richard Henderson 
Cc: Eduardo Habkost 
Cc: Marcel Apfelbaum 
Cc: "Philippe Mathieu-Daudé" 
Cc: Yanan Wang 
Cc: "Daniel P. Berrangé" 
Cc: Peter Xu 
Cc: David Hildenbrand 
Cc: Bibo Mao 
Signed-off-by: xianglai li 
---
 hw/acpi/acpi-cpu-hotplug-stub.c |  9 +
 hw/loongarch/acpi-build.c   | 34 -
 hw/loongarch/virt.c |  3 ++-
 include/hw/loongarch/virt.h |  1 +
 4 files changed, 45 insertions(+), 2 deletions(-)

diff --git a/hw/acpi/acpi-cpu-hotplug-stub.c b/hw/acpi/acpi-cpu-hotplug-stub.c
index 2aec90d968..b3ac7a1e31 100644
--- a/hw/acpi/acpi-cpu-hotplug-stub.c
+++ b/hw/acpi/acpi-cpu-hotplug-stub.c
@@ -19,6 +19,15 @@ void legacy_acpi_cpu_hotplug_init(MemoryRegion *parent, 
Object *owner,
 return;
 }
 
+void build_cpus_aml(Aml *table, MachineState *machine, CPUHotplugFeatures opts,
+build_madt_cpu_fn build_madt_cpu, hwaddr mmap_io_base,
+const char *res_root,
+const char *event_handler_method,
+AmlRegionSpace rs)
+{
+return;
+}
+
 void acpi_cpu_ospm_status(CPUHotplugState *cpu_st, ACPIOSTInfoList ***list)
 {
 return;
diff --git a/hw/loongarch/acpi-build.c b/hw/loongarch/acpi-build.c
index ae292fc543..cf89e5c1cb 100644
--- a/hw/loongarch/acpi-build.c
+++ b/hw/loongarch/acpi-build.c
@@ -46,6 +46,23 @@
 #define ACPI_BUILD_DPRINTF(fmt, ...)
 #endif
 
+static void virt_madt_cpu_entry(int uid,
+const CPUArchIdList *apic_ids,
+GArray *entry, bool force_enabled)
+{
+uint32_t apic_id = apic_ids->cpus[uid].arch_id;
+/* Flags – Local APIC Flags */
+uint32_t flags = apic_ids->cpus[uid].cpu != NULL || force_enabled ?
+ 1 /* Enabled */ : 0;
+
+/* Rev 1.0b, Table 5-13 Processor Local APIC Structure */
+build_append_int_noprefix(entry, 0, 1);   /* Type */
+build_append_int_noprefix(entry, 8, 1);   /* Length */
+build_append_int_noprefix(entry, uid, 1); /* ACPI Processor ID */
+build_append_int_noprefix(entry, apic_id, 1); /* APIC ID */
+build_append_int_noprefix(entry, flags, 4); /* Flags */
+}
+
 /* build FADT */
 static void init_common_fadt_data(AcpiFadtData *data)
 {
@@ -121,15 +138,18 @@ build_madt(GArray *table_data, BIOSLinker *linker, 
LoongArchMachineState *lams)
 build_append_int_noprefix(table_data, 1 /* PCAT_COMPAT */, 4); /* Flags */
 
 for (i = 0; i < arch_ids->len; i++) {
+uint32_t flags;
+
 /* Processor Core Interrupt Controller Structure */
 arch_id = arch_ids->cpus[i].arch_id;
+flags = arch_ids->cpus[i].cpu ? 1 : 0;
 
 build_append_int_noprefix(table_data, 17, 1);/* Type */
 build_append_int_noprefix(table_data, 15, 1);/* Length */
 build_append_int_noprefix(table_data, 1, 1); /* Version */
 build_append_int_noprefix(table_data, i, 4); /* ACPI Processor ID 
*/
 build_append_int_noprefix(table_data, arch_id, 4); /* Core ID */
-build_append_int_noprefix(table_data, 1, 4); /* Flags */
+build_append_int_noprefix(table_data, flags, 4);   /* Flags */
 }
 
 /* Extend I/O Interrupt Controller Structure */
@@ -292,6 +312,18 @@ build_la_ged_aml(Aml *dsdt, MachineState *machine)
  AML_SYSTEM_MEMORY,
  VIRT_GED_MEM_ADDR);
 }
+
+if (event & ACPI_GED_CPU_HOTPLUG_EVT) {
+CPUHotplugFeatures opts = {
+.acpi_1_compatible = false,
+.has_legacy_cphp = false
+};
+
+build_cpus_aml(dsdt, machine, opts, virt_madt_cpu_entry,
+   VIRT_GED_CPUHP_ADDR, "\\_SB", "\\_GPE._E01",
+   AML_SYSTEM_MEMORY);
+
+}
 acpi_dsdt_add_power_button(dsdt);
 }
 
diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c
index c704f3117f..22b287eb39 100644
--- a/hw/loongarch/virt.c
+++ b/hw/loongarch/virt.c
@@ -449,7 +449,7 @@ static DeviceState *create_acpi_ged(DeviceState *pch_pic, 
LoongArchMachineState
 {
 DeviceState *dev;
 MachineState *ms = MACHINE(lams);
-uint32_t event = ACPI_GED_PWR_DOWN_EVT;
+uint32_t event = ACPI_GED_PWR_DOWN_EVT | ACPI_GED_CPU_HOTPLUG_EVT;
 
 if (ms->ram_slots) {
 event |= ACPI_GED_MEM_HOTPLUG_EVT;
@@ -463,6 +463,7 @@ static DeviceState *create_acpi_ged(DeviceState *pch_pic, 
LoongArchMachineState
 sysbus_mmio_map(SYS_BUS_DEVICE(dev), 1, VIRT_GED_MEM_ADDR);
 /* ged regs used for reset and power down */
   

[PATCH v3 3/7] Added CPU topology support for Loongarch

2023-09-26 Thread xianglai li
1.Add topological relationships for Loongarch VCPU
and initialize topology member variables.
2.Add a description of the calculation method of
the arch_id and the topological relationship of the CPU.

Cc: "Bernhard Beschow" 
Cc: "Salil Mehta" 
Cc: "Salil Mehta" 
Cc: Xiaojuan Yang 
Cc: Song Gao 
Cc: "Michael S. Tsirkin" 
Cc: Igor Mammedov 
Cc: Ani Sinha 
Cc: Paolo Bonzini 
Cc: Richard Henderson 
Cc: Eduardo Habkost 
Cc: Marcel Apfelbaum 
Cc: "Philippe Mathieu-Daudé" 
Cc: Yanan Wang 
Cc: "Daniel P. Berrangé" 
Cc: Peter Xu 
Cc: David Hildenbrand 
Cc: Bibo Mao 
Signed-off-by: xianglai li 
---
 docs/system/loongarch/virt.rst |  31 ++
 hw/loongarch/virt.c| 101 ++---
 target/loongarch/cpu.c |  13 -
 target/loongarch/cpu.h |  12 +++-
 4 files changed, 134 insertions(+), 23 deletions(-)

diff --git a/docs/system/loongarch/virt.rst b/docs/system/loongarch/virt.rst
index c37268b404..eaba9e2fd7 100644
--- a/docs/system/loongarch/virt.rst
+++ b/docs/system/loongarch/virt.rst
@@ -28,6 +28,37 @@ The ``qemu-system-loongarch64`` provides emulation for virt
 machine. You can specify the machine type ``virt`` and
 cpu type ``la464``.
 
+CPU Topology
+
+
+The ``LA464`` type CPUs have the concept of Socket Core and Thread.
+
+For example:
+
+``-smp 1,maxcpus=M,sockets=S,cores=C,threads=T``
+
+The above parameters indicate that the machine has a maximum of ``M`` vCPUs and
+``S`` sockets, each socket has ``C`` cores, each core has ``T`` threads,
+and each thread corresponds to a vCPU.
+
+Then ``M`` ``S`` ``C`` ``T`` has the following relationship:
+
+``M = S * C * T``
+
+In the CPU topology relationship, When we know the ``socket_id`` ``core_id``
+and ``thread_id`` of the CPU, we can calculate its ``arch_id``:
+
+``arch_id = (socket_id * S) + (core_id * C) + (thread_id * T)``
+
+Similarly, when we know the ``arch_id`` of the CPU,
+we can also get its ``socket_id`` ``core_id`` and ``thread_id``:
+
+``socket_id = arch_id / (C * T)``
+
+``core_id = (arch_id / T) % C``
+
+``thread_id = arch_id % T``
+
 Boot options
 
 
diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c
index 2629128aed..b8474e7b94 100644
--- a/hw/loongarch/virt.c
+++ b/hw/loongarch/virt.c
@@ -624,11 +624,11 @@ static void loongarch_irq_init(LoongArchMachineState 
*lams)
 sysbus_mmio_get_region(SYS_BUS_DEVICE(ipi),
 1));
 /*
-* extioi iocsr memory region
-* only one extioi is added on loongarch virt machine
-* external device interrupt can only be routed to cpu 0-3
-*/
-   if (cpu < EXTIOI_CPUS)
+ * extioi iocsr memory region
+ * only one extioi is added on loongarch virt machine
+ * external device interrupt can only be routed to cpu 0-3
+ */
+if (cpu < EXTIOI_CPUS)
 memory_region_add_subregion(>system_iocsr, APIC_BASE,
 sysbus_mmio_get_region(SYS_BUS_DEVICE(extioi),
 cpu));
@@ -789,9 +789,7 @@ static void loongarch_init(MachineState *machine)
 NodeInfo *numa_info = machine->numa_state->nodes;
 int i;
 hwaddr fdt_base;
-const CPUArchIdList *possible_cpus;
 MachineClass *mc = MACHINE_GET_CLASS(machine);
-CPUState *cpu;
 char *ramName = NULL;
 
 if (!cpu_model) {
@@ -803,16 +801,41 @@ static void loongarch_init(MachineState *machine)
 exit(1);
 }
 create_fdt(lams);
-/* Init CPUs */
 
-possible_cpus = mc->possible_cpu_arch_ids(machine);
-for (i = 0; i < possible_cpus->len; i++) {
-cpu = cpu_create(machine->cpu_type);
-cpu->cpu_index = i;
-machine->possible_cpus->cpus[i].cpu = OBJECT(cpu);
-lacpu = LOONGARCH_CPU(cpu);
-lacpu->phy_id = machine->possible_cpus->cpus[i].arch_id;
+/* Init CPUs */
+mc->possible_cpu_arch_ids(machine);
+for (i = 0; i < machine->smp.cpus; i++) {
+Object *cpuobj;
+cpuobj = object_new(machine->cpu_type);
+lacpu = LOONGARCH_CPU(cpuobj);
+
+lacpu->arch_id = machine->possible_cpus->cpus[i].arch_id;
+object_property_set_int(cpuobj, "socket-id",
+
machine->possible_cpus->cpus[i].props.socket_id,
+NULL);
+object_property_set_int(cpuobj, "core-id",
+machine->possible_cpus->cpus[i].props.core_id,
+NULL);
+object_property_set_int(cpuobj, "thread-id",
+
machine->possible_cpus->cpus[i].props.thread_id,
+NULL);
+/*
+ * The CPU in place at the time of machine startup will also enter
+  

[PATCH v3 0/7] *** Adds CPU hot-plug support to Loongarch ***

2023-09-26 Thread xianglai li
Hello everyone, We refer to the implementation of ARM CPU
Hot-Plug to add GED-based CPU Hot-Plug support to Loongarch.

The first 2 patches are changes to the QEMU common code,
including adding GED support for CPU Hot-Plug, updating
the ACPI table creation process.

For the modification of the public part of the code, we refer to the
arm-related patch, and the link address of the corresponding patch is
as follows:
https://lore.kernel.org/all/20200613213629.21984-1-salil.me...@huawei.com/

We also refer to shentey's patch link as follows:
https://patchew.org/QEMU/20230908084234.17642-1-shen...@gmail.com/

In order to respect the work of "Salil Mehta" and shentey, we will rebase
the first 2 patches in the final patch, which are referenced here to ensure
that the loongarch cpu hotplug can work properly.

The last 5 patches are Loongarch architecture-related,
and the modifications include the definition of the hook
function related to the CPU Hot-(UN)Plug, the allocation
and release of CPU resources when CPU Hot-(UN)Plug,
the creation process of updating the ACPI table,
and finally the custom switch for the CPU Hot-Plug.

V3:
- The call to the function qdev_disconnect_gpio_out_named was removed
- The use of the function cpu_address_space_destroy is necessary,
  most architectures also need to be called, we want to call
  in the common path, rather than each cpu architecture itself,
  because the scheme is not sure we want to solve this problem
  in a separate patch, here we do the function rollback processing.
- Referring to shentey's patch, loongarch no longer creates the
  TYPE_ACPI_GED_LOONGARCH device class, but instead passes build_madt_cpu_fn
  directly as an argument to the build_cpus_aml function

V2:
- Fix formatting and spelling errors
- Split large patches into smaller patches
  - Split the original patch
<> into
<>
<>
<>.
  - Split the original patch
<> into
<>
<>
- Added loongarch cpu topology calculation method.
- Change the position of the cpu topology patch.
- Change unreasonable variable and function names.

xianglai li (7):
  Update ACPI GED framework to support vcpu hot-(un)plug
  Update CPUs AML with cpu-(ctrl)dev change
  Added CPU topology support for Loongarch
  Optimize loongarch_irq_init function implementation
  Add basic CPU hot-(un)plug support for Loongarch
  Add support of *unrealize* for Loongarch cpu
  Update the ACPI table for the Loongarch CPU

 .../devices/loongarch64-softmmu/default.mak   |   1 +
 docs/system/loongarch/virt.rst|  31 ++
 hw/acpi/acpi-cpu-hotplug-stub.c   |  15 +
 hw/acpi/cpu.c |  27 +-
 hw/acpi/generic_event_device.c|  33 ++
 hw/i386/acpi-build.c  |   3 +-
 hw/loongarch/acpi-build.c |  34 +-
 hw/loongarch/virt.c   | 409 +++---
 include/hw/acpi/cpu.h |   5 +-
 include/hw/acpi/cpu_hotplug.h |  10 +
 include/hw/acpi/generic_event_device.h|   5 +
 include/hw/loongarch/virt.h   |   6 +-
 target/loongarch/cpu.c|  33 +-
 target/loongarch/cpu.h|  13 +-
 14 files changed, 542 insertions(+), 83 deletions(-)

-- 
2.39.1




[PATCH v3 5/7] Add basic CPU hot-(un)plug support for Loongarch

2023-09-26 Thread xianglai li
Add CPU hot-(un)plug related hook functions and
turn on the CPU hot-(un)plug custom switch.

Cc: "Bernhard Beschow" 
Cc: "Salil Mehta" 
Cc: "Salil Mehta" 
Cc: Xiaojuan Yang 
Cc: Song Gao 
Cc: "Michael S. Tsirkin" 
Cc: Igor Mammedov 
Cc: Ani Sinha 
Cc: Paolo Bonzini 
Cc: Richard Henderson 
Cc: Eduardo Habkost 
Cc: Marcel Apfelbaum 
Cc: "Philippe Mathieu-Daudé" 
Cc: Yanan Wang 
Cc: "Daniel P. Berrangé" 
Cc: Peter Xu 
Cc: David Hildenbrand 
Cc: Bibo Mao 
Signed-off-by: xianglai li 
---
 .../devices/loongarch64-softmmu/default.mak   |   1 +
 hw/loongarch/virt.c   | 210 ++
 2 files changed, 211 insertions(+)

diff --git a/configs/devices/loongarch64-softmmu/default.mak 
b/configs/devices/loongarch64-softmmu/default.mak
index 928bc117ef..e596706fab 100644
--- a/configs/devices/loongarch64-softmmu/default.mak
+++ b/configs/devices/loongarch64-softmmu/default.mak
@@ -1,3 +1,4 @@
 # Default configuration for loongarch64-softmmu
 
 CONFIG_LOONGARCH_VIRT=y
+CONFIG_ACPI_CPU_HOTPLUG=y
diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c
index fb06b4ab4e..c704f3117f 100644
--- a/hw/loongarch/virt.c
+++ b/hw/loongarch/virt.c
@@ -999,11 +999,93 @@ static void virt_get_cpu_topo_by_cpu_index(const 
MachineState *ms,
 cpu_topo->thread_id = cpu_index % ms->smp.threads;
 }
 
+/* find cpu slot in machine->possible_cpus by arch_id */
+static CPUArchId *loongarch_find_cpu_slot(MachineState *ms, int arch_id)
+{
+int n;
+for (n = 0; n < ms->possible_cpus->len; n++) {
+if (ms->possible_cpus->cpus[n].arch_id == arch_id) {
+return >possible_cpus->cpus[n];
+}
+}
+
+return NULL;
+}
+
+static void loongarch_cpu_pre_plug(HotplugHandler *hotplug_dev,
+DeviceState *dev, Error **errp)
+{
+MachineState *ms = MACHINE(OBJECT(hotplug_dev));
+MachineClass *mc = MACHINE_GET_CLASS(hotplug_dev);
+LoongArchCPU *cpu = LOONGARCH_CPU(dev);
+CPUState *cs = CPU(dev);
+CPUArchId *cpu_slot;
+Error *local_err = NULL;
+LoongArchCPUTopo cpu_topo;
+int arch_id;
+
+if (dev->hotplugged && !mc->has_hotpluggable_cpus) {
+error_setg(_err, "CPU hotplug not supported for this machine");
+goto out;
+}
+
+/* sanity check the cpu */
+if (!object_dynamic_cast(OBJECT(cpu), ms->cpu_type)) {
+error_setg(_err, "Invalid CPU type, expected cpu type: '%s'",
+   ms->cpu_type);
+goto out;
+}
+
+if ((cpu->thread_id < 0) || (cpu->thread_id >= ms->smp.threads)) {
+error_setg(_err,
+   "Invalid thread-id %u specified, must be in range 1:%u",
+   cpu->thread_id, ms->smp.threads - 1);
+goto out;
+}
+
+if ((cpu->core_id < 0) || (cpu->core_id >= ms->smp.cores)) {
+error_setg(_err,
+   "Invalid core-id %u specified, must be in range 1:%u",
+   cpu->core_id, ms->smp.cores);
+goto out;
+}
+
+if ((cpu->socket_id < 0) || (cpu->socket_id >= ms->smp.sockets)) {
+error_setg(_err,
+   "Invalid socket-id %u specified, must be in range 1:%u",
+   cpu->socket_id, ms->smp.sockets - 1);
+goto out;
+}
+
+cpu_topo.socket_id = cpu->socket_id;
+cpu_topo.core_id = cpu->core_id;
+cpu_topo.thread_id = cpu->thread_id;
+arch_id = virt_get_arch_id_from_cpu_topo(ms, _topo);
+
+cpu_slot = loongarch_find_cpu_slot(ms, arch_id);
+if (CPU(cpu_slot->cpu)) {
+error_setg(_err,
+   "cpu(id%d=%d:%d:%d) with arch-id %" PRIu64 " exists",
+   cs->cpu_index, cpu->socket_id, cpu->core_id,
+   cpu->thread_id, cpu_slot->arch_id);
+goto out;
+}
+cpu->arch_id = arch_id;
+
+numa_cpu_pre_plug(cpu_slot, dev, _err);
+
+return ;
+out:
+error_propagate(errp, local_err);
+}
+
 static void virt_machine_device_pre_plug(HotplugHandler *hotplug_dev,
 DeviceState *dev, Error **errp)
 {
 if (memhp_type_supported(dev)) {
 virt_mem_pre_plug(hotplug_dev, dev, errp);
+} else if (object_dynamic_cast(OBJECT(dev), TYPE_LOONGARCH_CPU)) {
+loongarch_cpu_pre_plug(hotplug_dev, dev, errp);
 }
 }
 
@@ -1017,11 +1099,45 @@ static void virt_mem_unplug_request(HotplugHandler 
*hotplug_dev,
errp);
 }
 
+static void loongarch_cpu_unplug_request(HotplugHandler *hotplug_dev,
+DeviceState *dev, Error **errp)
+{
+MachineState *machine = MACHINE(OBJECT(hotplug_dev));
+LoongArchMachineState *lsms = LOONGARCH_MACHINE(machine);
+Error *local_er

[PATCH v3 1/7] Update ACPI GED framework to support vcpu hot-(un)plug

2023-09-26 Thread xianglai li
ACPI GED shall be used to convey to the guest kernel about any cpu hot-(un)plug
events. Therefore, existing ACPI GED framework inside QEMU needs to be enhanced
to support CPU hot-(un)plug state and events.

Co-authored-by: "Salil Mehta" 
Co-authored-by: "Salil Mehta" 
Cc: "Bernhard Beschow" 
Cc: "Salil Mehta" 
Cc: "Salil Mehta" 
Cc: Xiaojuan Yang 
Cc: Song Gao 
Cc: "Michael S. Tsirkin" 
Cc: Igor Mammedov 
Cc: Ani Sinha 
Cc: Paolo Bonzini 
Cc: Richard Henderson 
Cc: Eduardo Habkost 
Cc: Marcel Apfelbaum 
Cc: "Philippe Mathieu-Daudé" 
Cc: Yanan Wang 
Cc: "Daniel P. Berrangé" 
Cc: Peter Xu 
Cc: David Hildenbrand 
Cc: Bibo Mao 
Signed-off-by: xianglai li 
---
 hw/acpi/acpi-cpu-hotplug-stub.c|  6 +
 hw/acpi/cpu.c  |  7 --
 hw/acpi/generic_event_device.c | 33 ++
 include/hw/acpi/cpu_hotplug.h  | 10 
 include/hw/acpi/generic_event_device.h |  5 
 5 files changed, 54 insertions(+), 7 deletions(-)

diff --git a/hw/acpi/acpi-cpu-hotplug-stub.c b/hw/acpi/acpi-cpu-hotplug-stub.c
index 3fc4b14c26..2aec90d968 100644
--- a/hw/acpi/acpi-cpu-hotplug-stub.c
+++ b/hw/acpi/acpi-cpu-hotplug-stub.c
@@ -24,6 +24,12 @@ void acpi_cpu_ospm_status(CPUHotplugState *cpu_st, 
ACPIOSTInfoList ***list)
 return;
 }
 
+void cpu_hotplug_hw_init(MemoryRegion *as, Object *owner,
+ CPUHotplugState *state, hwaddr base_addr)
+{
+return;
+}
+
 void acpi_cpu_plug_cb(HotplugHandler *hotplug_dev,
   CPUHotplugState *cpu_st, DeviceState *dev, Error **errp)
 {
diff --git a/hw/acpi/cpu.c b/hw/acpi/cpu.c
index 011d2c6c2d..5bad983928 100644
--- a/hw/acpi/cpu.c
+++ b/hw/acpi/cpu.c
@@ -7,13 +7,6 @@
 #include "trace.h"
 #include "sysemu/numa.h"
 
-#define ACPI_CPU_HOTPLUG_REG_LEN 12
-#define ACPI_CPU_SELECTOR_OFFSET_WR 0
-#define ACPI_CPU_FLAGS_OFFSET_RW 4
-#define ACPI_CPU_CMD_OFFSET_WR 5
-#define ACPI_CPU_CMD_DATA_OFFSET_RW 8
-#define ACPI_CPU_CMD_DATA2_OFFSET_R 0
-
 #define OVMF_CPUHP_SMI_CMD 4
 
 enum {
diff --git a/hw/acpi/generic_event_device.c b/hw/acpi/generic_event_device.c
index a3d31631fe..c5a70957b4 100644
--- a/hw/acpi/generic_event_device.c
+++ b/hw/acpi/generic_event_device.c
@@ -12,6 +12,7 @@
 #include "qemu/osdep.h"
 #include "qapi/error.h"
 #include "hw/acpi/acpi.h"
+#include "hw/acpi/cpu.h"
 #include "hw/acpi/generic_event_device.h"
 #include "hw/irq.h"
 #include "hw/mem/pc-dimm.h"
@@ -25,6 +26,7 @@ static const uint32_t ged_supported_events[] = {
 ACPI_GED_MEM_HOTPLUG_EVT,
 ACPI_GED_PWR_DOWN_EVT,
 ACPI_GED_NVDIMM_HOTPLUG_EVT,
+ACPI_GED_CPU_HOTPLUG_EVT,
 };
 
 /*
@@ -117,6 +119,10 @@ void build_ged_aml(Aml *table, const char *name, 
HotplugHandler *hotplug_dev,
aml_notify(aml_name("\\_SB.NVDR"),
   aml_int(0x80)));
 break;
+case ACPI_GED_CPU_HOTPLUG_EVT:
+aml_append(if_ctx, aml_call0(ACPI_CPU_CONTAINER "."
+ ACPI_CPU_SCAN_METHOD));
+break;
 default:
 /*
  * Please make sure all the events in ged_supported_events[]
@@ -234,6 +240,8 @@ static void acpi_ged_device_plug_cb(HotplugHandler 
*hotplug_dev,
 } else {
 acpi_memory_plug_cb(hotplug_dev, >memhp_state, dev, errp);
 }
+} else if (object_dynamic_cast(OBJECT(dev), TYPE_CPU)) {
+acpi_cpu_plug_cb(hotplug_dev, >cpuhp_state, dev, errp);
 } else {
 error_setg(errp, "virt: device plug request for unsupported device"
" type: %s", object_get_typename(OBJECT(dev)));
@@ -248,6 +256,8 @@ static void acpi_ged_unplug_request_cb(HotplugHandler 
*hotplug_dev,
 if ((object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM) &&
!(object_dynamic_cast(OBJECT(dev), TYPE_NVDIMM {
 acpi_memory_unplug_request_cb(hotplug_dev, >memhp_state, dev, errp);
+} else if (object_dynamic_cast(OBJECT(dev), TYPE_CPU)) {
+acpi_cpu_unplug_request_cb(hotplug_dev, >cpuhp_state, dev, errp);
 } else {
 error_setg(errp, "acpi: device unplug request for unsupported device"
" type: %s", object_get_typename(OBJECT(dev)));
@@ -261,6 +271,8 @@ static void acpi_ged_unplug_cb(HotplugHandler *hotplug_dev,
 
 if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) {
 acpi_memory_unplug_cb(>memhp_state, dev, errp);
+} else if (object_dynamic_cast(OBJECT(dev), TYPE_CPU)) {
+acpi_cpu_unplug_cb(>cpuhp_state, dev, errp);
 } else {
 error_setg(errp, "acpi: device unplug for unsupported device"
" type: %s", object_g

[PATCH v2 06/10] Optimize loongarch_irq_init function implementation

2023-09-11 Thread xianglai li
Optimize loongarch_irq_init function implementation
and abstract the function loongarch_cpu_irq_init from it.

Cc: "Salil Mehta" 
Cc: Xiaojuan Yang 
Cc: Song Gao 
Cc: "Michael S. Tsirkin" 
Cc: Igor Mammedov 
Cc: Ani Sinha 
Cc: Paolo Bonzini 
Cc: Richard Henderson 
Cc: Eduardo Habkost 
Cc: Marcel Apfelbaum 
Cc: "Philippe Mathieu-Daudé" 
Cc: Yanan Wang 
Cc: "Daniel P. Berrangé" 
Cc: Peter Xu 
Cc: David Hildenbrand 
Cc: Bibo Mao 
Signed-off-by: xianglai li 
---
 hw/loongarch/virt.c | 105 
 include/hw/loongarch/virt.h |   5 +-
 2 files changed, 62 insertions(+), 48 deletions(-)

diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c
index b8474e7b94..fb06b4ab4e 100644
--- a/hw/loongarch/virt.c
+++ b/hw/loongarch/virt.c
@@ -46,6 +46,8 @@
 #include "hw/block/flash.h"
 #include "qemu/error-report.h"
 
+static LoongArchCPU *loongarch_cpu_irq_init(MachineState *machine,
+LoongArchCPU *cpu, Error **errp);
 
 static void virt_flash_create(LoongArchMachineState *lams)
 {
@@ -573,16 +575,16 @@ static void loongarch_devices_init(DeviceState *pch_pic, 
LoongArchMachineState *
 static void loongarch_irq_init(LoongArchMachineState *lams)
 {
 MachineState *ms = MACHINE(lams);
-DeviceState *pch_pic, *pch_msi, *cpudev;
-DeviceState *ipi, *extioi;
+DeviceState *pch_pic, *pch_msi;
+DeviceState *extioi;
 SysBusDevice *d;
 LoongArchCPU *lacpu;
-CPULoongArchState *env;
 CPUState *cpu_state;
-int cpu, pin, i, start, num;
+int cpu, i, start, num;
 
 extioi = qdev_new(TYPE_LOONGARCH_EXTIOI);
 sysbus_realize_and_unref(SYS_BUS_DEVICE(extioi), _fatal);
+lams->extioi = extioi;
 
 /*
  * The connection of interrupts:
@@ -607,44 +609,8 @@ static void loongarch_irq_init(LoongArchMachineState *lams)
  */
 for (cpu = 0; cpu < ms->smp.cpus; cpu++) {
 cpu_state = qemu_get_cpu(cpu);
-cpudev = DEVICE(cpu_state);
 lacpu = LOONGARCH_CPU(cpu_state);
-env = &(lacpu->env);
-
-ipi = qdev_new(TYPE_LOONGARCH_IPI);
-sysbus_realize_and_unref(SYS_BUS_DEVICE(ipi), _fatal);
-
-/* connect ipi irq to cpu irq */
-qdev_connect_gpio_out(ipi, 0, qdev_get_gpio_in(cpudev, IRQ_IPI));
-/* IPI iocsr memory region */
-memory_region_add_subregion(>system_iocsr, SMP_IPI_MAILBOX,
-sysbus_mmio_get_region(SYS_BUS_DEVICE(ipi),
-0));
-memory_region_add_subregion(>system_iocsr, MAIL_SEND_ADDR,
-sysbus_mmio_get_region(SYS_BUS_DEVICE(ipi),
-1));
-/*
- * extioi iocsr memory region
- * only one extioi is added on loongarch virt machine
- * external device interrupt can only be routed to cpu 0-3
- */
-if (cpu < EXTIOI_CPUS)
-memory_region_add_subregion(>system_iocsr, APIC_BASE,
-sysbus_mmio_get_region(SYS_BUS_DEVICE(extioi),
-cpu));
-env->ipistate = ipi;
-}
-
-/*
- * connect ext irq to the cpu irq
- * cpu_pin[9:2] <= intc_pin[7:0]
- */
-for (cpu = 0; cpu < MIN(ms->smp.cpus, EXTIOI_CPUS); cpu++) {
-cpudev = DEVICE(qemu_get_cpu(cpu));
-for (pin = 0; pin < LS3A_INTC_IP; pin++) {
-qdev_connect_gpio_out(extioi, (cpu * 8 + pin),
-  qdev_get_gpio_in(cpudev, pin + 2));
-}
+loongarch_cpu_irq_init(ms, lacpu, _fatal);
 }
 
 pch_pic = qdev_new(TYPE_LOONGARCH_PCH_PIC);
@@ -927,11 +893,7 @@ static void loongarch_init(MachineState *machine)
 }
 }
 fdt_add_flash_node(lams);
-/* register reset function */
-for (i = 0; i < machine->smp.cpus; i++) {
-lacpu = LOONGARCH_CPU(qemu_get_cpu(i));
-qemu_register_reset(reset_load_elf, lacpu);
-}
+
 /* Initialize the IO interrupt subsystem */
 loongarch_irq_init(lams);
 fdt_add_irqchip_node(lams);
@@ -1091,6 +1053,57 @@ static void virt_mem_plug(HotplugHandler *hotplug_dev,
  dev, _abort);
 }
 
+static LoongArchCPU *loongarch_cpu_irq_init(MachineState *machine,
+LoongArchCPU *cpu, Error **errp)
+{
+LoongArchMachineState *lsms = LOONGARCH_MACHINE(machine);
+CPUState *cs = CPU(cpu);
+unsigned int cpu_index = cs->cpu_index;
+DeviceState *cpudev = DEVICE(cpu);
+DeviceState *extioi = lsms->extioi;
+CPULoongArchState *env = >env;
+DeviceState *ipi;
+int pin;
+
+qemu_register_reset(reset_load_elf, cpu);
+
+ipi = qdev_new(TYPE_LOONGARCH_IPI);
+sysbus_realize_and_unref(SYS_BUS_DEVICE(ipi), errp);
+
+/* connect ipi irq to cpu irq */
+qdev_connect_gpio_out(ipi, 0, qdev_get_gpio_in

[PATCH v2 09/10] Add generic event device for Loongarch

2023-09-11 Thread xianglai li
Create a new GED device type for Loongarch,
mount cpu_madt function to update the ACPI table.

Cc: "Salil Mehta" 
Cc: Xiaojuan Yang 
Cc: Song Gao 
Cc: "Michael S. Tsirkin" 
Cc: Igor Mammedov 
Cc: Ani Sinha 
Cc: Paolo Bonzini 
Cc: Richard Henderson 
Cc: Eduardo Habkost 
Cc: Marcel Apfelbaum 
Cc: "Philippe Mathieu-Daudé" 
Cc: Yanan Wang 
Cc: "Daniel P. Berrangé" 
Cc: Peter Xu 
Cc: David Hildenbrand 
Cc: Bibo Mao 
Signed-off-by: xianglai li 
---
 hw/loongarch/acpi-build.c | 17 +
 hw/loongarch/generic_event_device_loongarch.c | 36 +++
 hw/loongarch/meson.build  |  2 +-
 include/hw/acpi/generic_event_device.h|  1 +
 include/hw/loongarch/virt.h   |  4 +++
 5 files changed, 59 insertions(+), 1 deletion(-)
 create mode 100644 hw/loongarch/generic_event_device_loongarch.c

diff --git a/hw/loongarch/acpi-build.c b/hw/loongarch/acpi-build.c
index ae292fc543..66fad295cc 100644
--- a/hw/loongarch/acpi-build.c
+++ b/hw/loongarch/acpi-build.c
@@ -46,6 +46,23 @@
 #define ACPI_BUILD_DPRINTF(fmt, ...)
 #endif
 
+void virt_madt_cpu_entry(int uid,
+ const CPUArchIdList *apic_ids,
+ GArray *entry, bool force_enabled)
+{
+uint32_t apic_id = apic_ids->cpus[uid].arch_id;
+/* Flags – Local APIC Flags */
+uint32_t flags = apic_ids->cpus[uid].cpu != NULL || force_enabled ?
+ 1 /* Enabled */ : 0;
+
+/* Rev 1.0b, Table 5-13 Processor Local APIC Structure */
+build_append_int_noprefix(entry, 0, 1);   /* Type */
+build_append_int_noprefix(entry, 8, 1);   /* Length */
+build_append_int_noprefix(entry, uid, 1); /* ACPI Processor ID */
+build_append_int_noprefix(entry, apic_id, 1); /* APIC ID */
+build_append_int_noprefix(entry, flags, 4); /* Flags */
+}
+
 /* build FADT */
 static void init_common_fadt_data(AcpiFadtData *data)
 {
diff --git a/hw/loongarch/generic_event_device_loongarch.c 
b/hw/loongarch/generic_event_device_loongarch.c
new file mode 100644
index 00..1fe550239b
--- /dev/null
+++ b/hw/loongarch/generic_event_device_loongarch.c
@@ -0,0 +1,36 @@
+/*
+ * loongarch variant of the generic event device for hw reduced acpi
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2 or later, as published by the Free Software Foundation.
+ */
+
+#include "qemu/osdep.h"
+#include "hw/acpi/generic_event_device.h"
+#include "hw/loongarch/virt.h"
+
+static void acpi_ged_loongarch_class_init(ObjectClass *class, void *data)
+{
+AcpiDeviceIfClass *adevc = ACPI_DEVICE_IF_CLASS(class);
+
+adevc->madt_cpu = virt_madt_cpu_entry;
+}
+
+static const TypeInfo acpi_ged_loongarch_info = {
+.name  = TYPE_ACPI_GED_LOONGARCH,
+.parent= TYPE_ACPI_GED,
+.class_init= acpi_ged_loongarch_class_init,
+.interfaces = (InterfaceInfo[]) {
+{ TYPE_HOTPLUG_HANDLER },
+{ TYPE_ACPI_DEVICE_IF },
+{ }
+}
+};
+
+static void acpi_ged_loongarch_register_types(void)
+{
+type_register_static(_ged_loongarch_info);
+}
+
+type_init(acpi_ged_loongarch_register_types)
diff --git a/hw/loongarch/meson.build b/hw/loongarch/meson.build
index c0421502ab..8d21addee3 100644
--- a/hw/loongarch/meson.build
+++ b/hw/loongarch/meson.build
@@ -3,6 +3,6 @@ loongarch_ss.add(files(
 'fw_cfg.c',
 ))
 loongarch_ss.add(when: 'CONFIG_LOONGARCH_VIRT', if_true: [files('virt.c'), 
fdt])
-loongarch_ss.add(when: 'CONFIG_ACPI', if_true: files('acpi-build.c'))
+loongarch_ss.add(when: 'CONFIG_ACPI', if_true: files('acpi-build.c', 
'generic_event_device_loongarch.c'))
 
 hw_arch += {'loongarch': loongarch_ss}
diff --git a/include/hw/acpi/generic_event_device.h 
b/include/hw/acpi/generic_event_device.h
index d0a5a43abf..2923bd9d82 100644
--- a/include/hw/acpi/generic_event_device.h
+++ b/include/hw/acpi/generic_event_device.h
@@ -71,6 +71,7 @@
 OBJECT_DECLARE_SIMPLE_TYPE(AcpiGedState, ACPI_GED)
 
 #define TYPE_ACPI_GED_X86 "acpi-ged-x86"
+#define TYPE_ACPI_GED_LOONGARCH "acpi-ged-loongarch"
 
 #define ACPI_GED_EVT_SEL_OFFSET0x0
 #define ACPI_GED_EVT_SEL_LEN   0x4
diff --git a/include/hw/loongarch/virt.h b/include/hw/loongarch/virt.h
index 176dc43a93..f6c9495af2 100644
--- a/include/hw/loongarch/virt.h
+++ b/include/hw/loongarch/virt.h
@@ -60,4 +60,8 @@ struct LoongArchMachineState {
 OBJECT_DECLARE_SIMPLE_TYPE(LoongArchMachineState, LOONGARCH_MACHINE)
 bool loongarch_is_acpi_enabled(LoongArchMachineState *lams);
 void loongarch_acpi_setup(LoongArchMachineState *lams);
+void virt_madt_cpu_entry(int uid,
+ const CPUArchIdList *apic_ids, GArray *entry,
+ bool force_enabled);
+
 #endif
-- 
2.39.1




[PATCH v2 08/10] Add support of *unrealize* for Loongarch cpu

2023-09-11 Thread xianglai li
Add the unrealize function to the Loongarch CPU for cpu hot-(un)plug

Cc: "Salil Mehta" 
Cc: Xiaojuan Yang 
Cc: Song Gao 
Cc: "Michael S. Tsirkin" 
Cc: Igor Mammedov 
Cc: Ani Sinha 
Cc: Paolo Bonzini 
Cc: Richard Henderson 
Cc: Eduardo Habkost 
Cc: Marcel Apfelbaum 
Cc: "Philippe Mathieu-Daudé" 
Cc: Yanan Wang 
Cc: "Daniel P. Berrangé" 
Cc: Peter Xu 
Cc: David Hildenbrand 
Cc: Bibo Mao 
Signed-off-by: xianglai li 
---
 target/loongarch/cpu.c | 22 ++
 target/loongarch/cpu.h |  1 +
 2 files changed, 23 insertions(+)

diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c
index a5153cb3bc..03134d7bac 100644
--- a/target/loongarch/cpu.c
+++ b/target/loongarch/cpu.c
@@ -572,6 +572,24 @@ static void loongarch_cpu_realizefn(DeviceState *dev, 
Error **errp)
 lacc->parent_realize(dev, errp);
 }
 
+static void loongarch_cpu_unrealizefn(DeviceState *dev)
+{
+LoongArchCPUClass *mcc = LOONGARCH_CPU_GET_CLASS(dev);
+
+#ifndef CONFIG_USER_ONLY
+CPUState *cs = CPU(dev);
+LoongArchCPU *cpu = LOONGARCH_CPU(dev);
+CPULoongArchState *env = >env;
+
+cpu_remove_sync(CPU(dev));
+cpu_address_space_destroy(cs, 0);
+address_space_destroy(>address_space_iocsr);
+memory_region_del_subregion(>system_iocsr, >iocsr_mem);
+#endif
+
+mcc->parent_unrealize(dev);
+}
+
 #ifndef CONFIG_USER_ONLY
 static void loongarch_qemu_write(void *opaque, hwaddr addr,
  uint64_t val, unsigned size)
@@ -752,6 +770,9 @@ static void loongarch_cpu_class_init(ObjectClass *c, void 
*data)
 device_class_set_props(dc, loongarch_cpu_properties);
 device_class_set_parent_realize(dc, loongarch_cpu_realizefn,
 >parent_realize);
+device_class_set_parent_unrealize(dc, loongarch_cpu_unrealizefn,
+  >parent_unrealize);
+
 resettable_class_set_parent_phases(rc, NULL, loongarch_cpu_reset_hold, 
NULL,
>parent_phases);
 
@@ -773,6 +794,7 @@ static void loongarch_cpu_class_init(ObjectClass *c, void 
*data)
 #ifdef CONFIG_TCG
 cc->tcg_ops = _tcg_ops;
 #endif
+dc->user_creatable = true;
 }
 
 static gchar *loongarch32_gdb_arch_name(CPUState *cs)
diff --git a/target/loongarch/cpu.h b/target/loongarch/cpu.h
index 058bc53bde..4143138b12 100644
--- a/target/loongarch/cpu.h
+++ b/target/loongarch/cpu.h
@@ -412,6 +412,7 @@ struct LoongArchCPUClass {
 /*< public >*/
 
 DeviceRealize parent_realize;
+DeviceUnrealize parent_unrealize;
 ResettablePhases parent_phases;
 };
 
-- 
2.39.1




[PATCH v2 02/10] Update CPUs AML with cpu-(ctrl)dev change

2023-09-11 Thread xianglai li
CPUs Control device(\\_SB.PCI0) register interface for the x86 arch
is based on PCI and is IO port based and hence existing cpus AML code
assumes _CRS objects would evaluate to a system resource which describes
IO Port address.
But on Loongarch arch CPUs control device(\\_SB.PRES) register interface
is memory-mapped hence _CRS object should evaluate to system resource
which describes memory-mapped base address.

This cpus AML code change updates the existing interface of the build cpus AML
function to accept both IO/MEMORY type regions and update the _CRS object
correspondingly.

Co-authored-by: "Salil Mehta" 
Cc: "Salil Mehta" 
Cc: Xiaojuan Yang 
Cc: Song Gao 
Cc: "Michael S. Tsirkin" 
Cc: Igor Mammedov 
Cc: Ani Sinha 
Cc: Paolo Bonzini 
Cc: Richard Henderson 
Cc: Eduardo Habkost 
Cc: Marcel Apfelbaum 
Cc: "Philippe Mathieu-Daudé" 
Cc: Yanan Wang 
Cc: "Daniel P. Berrangé" 
Cc: Peter Xu 
Cc: David Hildenbrand 
Cc: Bibo Mao 
Signed-off-by: xianglai li 
---
 hw/acpi/cpu.c | 20 +++-
 hw/i386/acpi-build.c  |  2 +-
 include/hw/acpi/cpu.h |  5 +++--
 3 files changed, 19 insertions(+), 8 deletions(-)

diff --git a/hw/acpi/cpu.c b/hw/acpi/cpu.c
index 6897c8789a..41fc157ac9 100644
--- a/hw/acpi/cpu.c
+++ b/hw/acpi/cpu.c
@@ -5,6 +5,7 @@
 #include "qapi/qapi-events-acpi.h"
 #include "trace.h"
 #include "sysemu/numa.h"
+#include "hw/acpi/cpu_hotplug.h"
 
 #define OVMF_CPUHP_SMI_CMD 4
 
@@ -331,9 +332,10 @@ const VMStateDescription vmstate_cpu_hotplug = {
 #define CPU_FW_EJECT_EVENT "CEJF"
 
 void build_cpus_aml(Aml *table, MachineState *machine, CPUHotplugFeatures opts,
-hwaddr io_base,
+hwaddr mmap_io_base,
 const char *res_root,
-const char *event_handler_method)
+const char *event_handler_method,
+AmlRegionSpace rs)
 {
 Aml *ifctx;
 Aml *field;
@@ -360,14 +362,22 @@ void build_cpus_aml(Aml *table, MachineState *machine, 
CPUHotplugFeatures opts,
 aml_append(cpu_ctrl_dev, aml_mutex(CPU_LOCK, 0));
 
 crs = aml_resource_template();
-aml_append(crs, aml_io(AML_DECODE16, io_base, io_base, 1,
+if (rs == AML_SYSTEM_IO) {
+aml_append(crs, aml_io(AML_DECODE16, mmap_io_base, mmap_io_base, 1,
ACPI_CPU_HOTPLUG_REG_LEN));
+} else {
+aml_append(crs, aml_memory32_fixed(mmap_io_base,
+   ACPI_CPU_HOTPLUG_REG_LEN, AML_READ_WRITE));
+}
+
 aml_append(cpu_ctrl_dev, aml_name_decl("_CRS", crs));
 
+g_assert(rs == AML_SYSTEM_IO || rs == AML_SYSTEM_MEMORY);
 /* declare CPU hotplug MMIO region with related access fields */
 aml_append(cpu_ctrl_dev,
-aml_operation_region("PRST", AML_SYSTEM_IO, aml_int(io_base),
- ACPI_CPU_HOTPLUG_REG_LEN));
+aml_operation_region("PRST", rs,
+ aml_int(mmap_io_base),
+ ACPI_CPU_HOTPLUG_REG_LEN));
 
 field = aml_field("PRST", AML_BYTE_ACC, AML_NOLOCK,
   AML_WRITE_AS_ZEROS);
diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
index bb12b0ad43..560f108d38 100644
--- a/hw/i386/acpi-build.c
+++ b/hw/i386/acpi-build.c
@@ -1550,7 +1550,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,
 .fw_unplugs_cpu = pm->smi_on_cpu_unplug,
 };
 build_cpus_aml(dsdt, machine, opts, pm->cpu_hp_io_base,
-   "\\_SB.PCI0", "\\_GPE._E02");
+   "\\_SB.PCI0", "\\_GPE._E02", AML_SYSTEM_IO);
 }
 
 if (pcms->memhp_io_base && nr_mem) {
diff --git a/include/hw/acpi/cpu.h b/include/hw/acpi/cpu.h
index 999caaf510..cddea78333 100644
--- a/include/hw/acpi/cpu.h
+++ b/include/hw/acpi/cpu.h
@@ -56,9 +56,10 @@ typedef struct CPUHotplugFeatures {
 } CPUHotplugFeatures;
 
 void build_cpus_aml(Aml *table, MachineState *machine, CPUHotplugFeatures opts,
-hwaddr io_base,
+hwaddr mmap_io_base,
 const char *res_root,
-const char *event_handler_method);
+const char *event_handler_method,
+AmlRegionSpace rs);
 
 void acpi_cpu_ospm_status(CPUHotplugState *cpu_st, ACPIOSTInfoList ***list);
 
-- 
2.39.1




[PATCH v2 05/10] Added CPU topology support for Loongarch

2023-09-11 Thread xianglai li
1.Add topological relationships for Loongarch VCPU
and initialize topology member variables.
2.Add a description of the calculation method of
the arch_id and the topological relationship of the CPU.

Cc: "Salil Mehta" 
Cc: Xiaojuan Yang 
Cc: Song Gao 
Cc: "Michael S. Tsirkin" 
Cc: Igor Mammedov 
Cc: Ani Sinha 
Cc: Paolo Bonzini 
Cc: Richard Henderson 
Cc: Eduardo Habkost 
Cc: Marcel Apfelbaum 
Cc: "Philippe Mathieu-Daudé" 
Cc: Yanan Wang 
Cc: "Daniel P. Berrangé" 
Cc: Peter Xu 
Cc: David Hildenbrand 
Cc: Bibo Mao 
Signed-off-by: xianglai li 
---
 docs/system/loongarch/virt.rst |  31 ++
 hw/loongarch/virt.c| 101 ++---
 target/loongarch/cpu.c |  13 -
 target/loongarch/cpu.h |  12 +++-
 4 files changed, 134 insertions(+), 23 deletions(-)

diff --git a/docs/system/loongarch/virt.rst b/docs/system/loongarch/virt.rst
index c37268b404..eaba9e2fd7 100644
--- a/docs/system/loongarch/virt.rst
+++ b/docs/system/loongarch/virt.rst
@@ -28,6 +28,37 @@ The ``qemu-system-loongarch64`` provides emulation for virt
 machine. You can specify the machine type ``virt`` and
 cpu type ``la464``.
 
+CPU Topology
+
+
+The ``LA464`` type CPUs have the concept of Socket Core and Thread.
+
+For example:
+
+``-smp 1,maxcpus=M,sockets=S,cores=C,threads=T``
+
+The above parameters indicate that the machine has a maximum of ``M`` vCPUs and
+``S`` sockets, each socket has ``C`` cores, each core has ``T`` threads,
+and each thread corresponds to a vCPU.
+
+Then ``M`` ``S`` ``C`` ``T`` has the following relationship:
+
+``M = S * C * T``
+
+In the CPU topology relationship, When we know the ``socket_id`` ``core_id``
+and ``thread_id`` of the CPU, we can calculate its ``arch_id``:
+
+``arch_id = (socket_id * S) + (core_id * C) + (thread_id * T)``
+
+Similarly, when we know the ``arch_id`` of the CPU,
+we can also get its ``socket_id`` ``core_id`` and ``thread_id``:
+
+``socket_id = arch_id / (C * T)``
+
+``core_id = (arch_id / T) % C``
+
+``thread_id = arch_id % T``
+
 Boot options
 
 
diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c
index 2629128aed..b8474e7b94 100644
--- a/hw/loongarch/virt.c
+++ b/hw/loongarch/virt.c
@@ -624,11 +624,11 @@ static void loongarch_irq_init(LoongArchMachineState 
*lams)
 sysbus_mmio_get_region(SYS_BUS_DEVICE(ipi),
 1));
 /*
-* extioi iocsr memory region
-* only one extioi is added on loongarch virt machine
-* external device interrupt can only be routed to cpu 0-3
-*/
-   if (cpu < EXTIOI_CPUS)
+ * extioi iocsr memory region
+ * only one extioi is added on loongarch virt machine
+ * external device interrupt can only be routed to cpu 0-3
+ */
+if (cpu < EXTIOI_CPUS)
 memory_region_add_subregion(>system_iocsr, APIC_BASE,
 sysbus_mmio_get_region(SYS_BUS_DEVICE(extioi),
 cpu));
@@ -789,9 +789,7 @@ static void loongarch_init(MachineState *machine)
 NodeInfo *numa_info = machine->numa_state->nodes;
 int i;
 hwaddr fdt_base;
-const CPUArchIdList *possible_cpus;
 MachineClass *mc = MACHINE_GET_CLASS(machine);
-CPUState *cpu;
 char *ramName = NULL;
 
 if (!cpu_model) {
@@ -803,16 +801,41 @@ static void loongarch_init(MachineState *machine)
 exit(1);
 }
 create_fdt(lams);
-/* Init CPUs */
 
-possible_cpus = mc->possible_cpu_arch_ids(machine);
-for (i = 0; i < possible_cpus->len; i++) {
-cpu = cpu_create(machine->cpu_type);
-cpu->cpu_index = i;
-machine->possible_cpus->cpus[i].cpu = OBJECT(cpu);
-lacpu = LOONGARCH_CPU(cpu);
-lacpu->phy_id = machine->possible_cpus->cpus[i].arch_id;
+/* Init CPUs */
+mc->possible_cpu_arch_ids(machine);
+for (i = 0; i < machine->smp.cpus; i++) {
+Object *cpuobj;
+cpuobj = object_new(machine->cpu_type);
+lacpu = LOONGARCH_CPU(cpuobj);
+
+lacpu->arch_id = machine->possible_cpus->cpus[i].arch_id;
+object_property_set_int(cpuobj, "socket-id",
+
machine->possible_cpus->cpus[i].props.socket_id,
+NULL);
+object_property_set_int(cpuobj, "core-id",
+machine->possible_cpus->cpus[i].props.core_id,
+NULL);
+object_property_set_int(cpuobj, "thread-id",
+
machine->possible_cpus->cpus[i].props.thread_id,
+NULL);
+/*
+ * The CPU in place at the time of machine startup will also enter
+ * the CPU hot-plug process when it is created, but a

[PATCH v2 04/10] Introduce the CPU address space destruction function

2023-09-11 Thread xianglai li
Introduce new function to destroy CPU address space resources
for cpu hot-(un)plug.

Co-authored-by: "Salil Mehta" 
Cc: "Salil Mehta" 
Cc: Xiaojuan Yang 
Cc: Song Gao 
Cc: "Michael S. Tsirkin" 
Cc: Igor Mammedov 
Cc: Ani Sinha 
Cc: Paolo Bonzini 
Cc: Richard Henderson 
Cc: Eduardo Habkost 
Cc: Marcel Apfelbaum 
Cc: "Philippe Mathieu-Daudé" 
Cc: Yanan Wang 
Cc: "Daniel P. Berrangé" 
Cc: Peter Xu 
Cc: David Hildenbrand 
Cc: Bibo Mao 
Signed-off-by: xianglai li 
---
 include/exec/cpu-common.h |  8 
 include/hw/core/cpu.h |  1 +
 softmmu/physmem.c | 24 
 3 files changed, 33 insertions(+)

diff --git a/include/exec/cpu-common.h b/include/exec/cpu-common.h
index 41788c0bdd..eb56a228a2 100644
--- a/include/exec/cpu-common.h
+++ b/include/exec/cpu-common.h
@@ -120,6 +120,14 @@ size_t qemu_ram_pagesize_largest(void);
  */
 void cpu_address_space_init(CPUState *cpu, int asidx,
 const char *prefix, MemoryRegion *mr);
+/**
+ * cpu_address_space_destroy:
+ * @cpu: CPU for which address space needs to be destroyed
+ * @asidx: integer index of this address space
+ *
+ * Note that with KVM only one address space is supported.
+ */
+void cpu_address_space_destroy(CPUState *cpu, int asidx);
 
 void cpu_physical_memory_rw(hwaddr addr, void *buf,
 hwaddr len, bool is_write);
diff --git a/include/hw/core/cpu.h b/include/hw/core/cpu.h
index 92a4234439..c90cf3a162 100644
--- a/include/hw/core/cpu.h
+++ b/include/hw/core/cpu.h
@@ -366,6 +366,7 @@ struct CPUState {
 QSIMPLEQ_HEAD(, qemu_work_item) work_list;
 
 CPUAddressSpace *cpu_ases;
+int cpu_ases_ref_count;
 int num_ases;
 AddressSpace *as;
 MemoryRegion *memory;
diff --git a/softmmu/physmem.c b/softmmu/physmem.c
index 18277ddd67..c75e3e8042 100644
--- a/softmmu/physmem.c
+++ b/softmmu/physmem.c
@@ -761,6 +761,7 @@ void cpu_address_space_init(CPUState *cpu, int asidx,
 
 if (!cpu->cpu_ases) {
 cpu->cpu_ases = g_new0(CPUAddressSpace, cpu->num_ases);
+cpu->cpu_ases_ref_count = cpu->num_ases;
 }
 
 newas = >cpu_ases[asidx];
@@ -774,6 +775,29 @@ void cpu_address_space_init(CPUState *cpu, int asidx,
 }
 }
 
+void cpu_address_space_destroy(CPUState *cpu, int asidx)
+{
+CPUAddressSpace *cpuas;
+
+assert(asidx < cpu->num_ases);
+assert(asidx == 0 || !kvm_enabled());
+assert(cpu->cpu_ases);
+
+cpuas = >cpu_ases[asidx];
+if (tcg_enabled()) {
+memory_listener_unregister(>tcg_as_listener);
+}
+
+address_space_destroy(cpuas->as);
+
+cpu->cpu_ases_ref_count--;
+if (cpu->cpu_ases_ref_count == 0) {
+g_free(cpu->cpu_ases);
+cpu->cpu_ases = NULL;
+}
+
+}
+
 AddressSpace *cpu_get_address_space(CPUState *cpu, int asidx)
 {
 /* Return the AddressSpace corresponding to the specified index */
-- 
2.39.1




[PATCH v2 10/10] Update the ACPI table for the Loongarch CPU

2023-09-11 Thread xianglai li
Add new types of GED devices for Loongarch machines,
add CPU hot-(un)plug event response and address spaces,
and update the ACPI table.

Cc: "Salil Mehta" 
Cc: Xiaojuan Yang 
Cc: Song Gao 
Cc: "Michael S. Tsirkin" 
Cc: Igor Mammedov 
Cc: Ani Sinha 
Cc: Paolo Bonzini 
Cc: Richard Henderson 
Cc: Eduardo Habkost 
Cc: Marcel Apfelbaum 
Cc: "Philippe Mathieu-Daudé" 
Cc: Yanan Wang 
Cc: "Daniel P. Berrangé" 
Cc: Peter Xu 
Cc: David Hildenbrand 
Cc: Bibo Mao 
Signed-off-by: xianglai li 
---
 hw/acpi/acpi-cpu-hotplug-stub.c |  9 +
 hw/loongarch/acpi-build.c   | 16 +++-
 hw/loongarch/virt.c |  5 +++--
 include/hw/loongarch/virt.h |  1 +
 4 files changed, 28 insertions(+), 3 deletions(-)

diff --git a/hw/acpi/acpi-cpu-hotplug-stub.c b/hw/acpi/acpi-cpu-hotplug-stub.c
index 2aec90d968..af9fda2cf4 100644
--- a/hw/acpi/acpi-cpu-hotplug-stub.c
+++ b/hw/acpi/acpi-cpu-hotplug-stub.c
@@ -19,6 +19,15 @@ void legacy_acpi_cpu_hotplug_init(MemoryRegion *parent, 
Object *owner,
 return;
 }
 
+void build_cpus_aml(Aml *table, MachineState *machine, CPUHotplugFeatures opts,
+hwaddr mmap_io_base,
+const char *res_root,
+const char *event_handler_method,
+AmlRegionSpace rs)
+{
+return;
+}
+
 void acpi_cpu_ospm_status(CPUHotplugState *cpu_st, ACPIOSTInfoList ***list)
 {
 return;
diff --git a/hw/loongarch/acpi-build.c b/hw/loongarch/acpi-build.c
index 66fad295cc..312908fb2f 100644
--- a/hw/loongarch/acpi-build.c
+++ b/hw/loongarch/acpi-build.c
@@ -138,15 +138,18 @@ build_madt(GArray *table_data, BIOSLinker *linker, 
LoongArchMachineState *lams)
 build_append_int_noprefix(table_data, 1 /* PCAT_COMPAT */, 4); /* Flags */
 
 for (i = 0; i < arch_ids->len; i++) {
+uint32_t flags;
+
 /* Processor Core Interrupt Controller Structure */
 arch_id = arch_ids->cpus[i].arch_id;
+flags = arch_ids->cpus[i].cpu ? 1 : 0;
 
 build_append_int_noprefix(table_data, 17, 1);/* Type */
 build_append_int_noprefix(table_data, 15, 1);/* Length */
 build_append_int_noprefix(table_data, 1, 1); /* Version */
 build_append_int_noprefix(table_data, i, 4); /* ACPI Processor ID 
*/
 build_append_int_noprefix(table_data, arch_id, 4); /* Core ID */
-build_append_int_noprefix(table_data, 1, 4); /* Flags */
+build_append_int_noprefix(table_data, flags, 4);   /* Flags */
 }
 
 /* Extend I/O Interrupt Controller Structure */
@@ -309,6 +312,17 @@ build_la_ged_aml(Aml *dsdt, MachineState *machine)
  AML_SYSTEM_MEMORY,
  VIRT_GED_MEM_ADDR);
 }
+
+if (event & ACPI_GED_CPU_HOTPLUG_EVT) {
+CPUHotplugFeatures opts = {
+.acpi_1_compatible = false,
+.has_legacy_cphp = false
+};
+
+build_cpus_aml(dsdt, machine, opts, VIRT_GED_CPUHP_ADDR,
+   "\\_SB", "\\_GPE._E01", AML_SYSTEM_MEMORY);
+
+}
 acpi_dsdt_add_power_button(dsdt);
 }
 
diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c
index aabe8aa814..c4ec9dd6a7 100644
--- a/hw/loongarch/virt.c
+++ b/hw/loongarch/virt.c
@@ -449,12 +449,12 @@ static DeviceState *create_acpi_ged(DeviceState *pch_pic, 
LoongArchMachineState
 {
 DeviceState *dev;
 MachineState *ms = MACHINE(lams);
-uint32_t event = ACPI_GED_PWR_DOWN_EVT;
+uint32_t event = ACPI_GED_PWR_DOWN_EVT | ACPI_GED_CPU_HOTPLUG_EVT;
 
 if (ms->ram_slots) {
 event |= ACPI_GED_MEM_HOTPLUG_EVT;
 }
-dev = qdev_new(TYPE_ACPI_GED);
+dev = qdev_new(TYPE_ACPI_GED_LOONGARCH);
 qdev_prop_set_uint32(dev, "ged-event", event);
 
 /* ged event */
@@ -463,6 +463,7 @@ static DeviceState *create_acpi_ged(DeviceState *pch_pic, 
LoongArchMachineState
 sysbus_mmio_map(SYS_BUS_DEVICE(dev), 1, VIRT_GED_MEM_ADDR);
 /* ged regs used for reset and power down */
 sysbus_mmio_map(SYS_BUS_DEVICE(dev), 2, VIRT_GED_REG_ADDR);
+sysbus_mmio_map(SYS_BUS_DEVICE(dev), 3, VIRT_GED_CPUHP_ADDR);
 
 sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0,
qdev_get_gpio_in(pch_pic, VIRT_SCI_IRQ - 
VIRT_GSI_BASE));
diff --git a/include/hw/loongarch/virt.h b/include/hw/loongarch/virt.h
index f6c9495af2..82ac238f4f 100644
--- a/include/hw/loongarch/virt.h
+++ b/include/hw/loongarch/virt.h
@@ -31,6 +31,7 @@
 #define VIRT_GED_EVT_ADDR   0x100e
 #define VIRT_GED_MEM_ADDR   (VIRT_GED_EVT_ADDR + ACPI_GED_EVT_SEL_LEN)
 #define VIRT_GED_REG_ADDR   (VIRT_GED_MEM_ADDR + MEMORY_HOTPLUG_IO_LEN)
+#define VIRT_GED_CPUHP_ADDR (VIRT_GED_REG_ADDR + ACPI_CPU_HOTPLUG_REG_LEN)
 
 struct LoongArchMachineState {
 /*< private >*/
-- 
2.39.1




[PATCH v2 00/10] Adds CPU hot-plug support to Loongarch

2023-09-11 Thread xianglai li
Hello everyone, We refer to the implementation of ARM CPU
Hot-Plug to add GED-based CPU Hot-Plug support to Loongarch.

The first 4 patches are changes to the QEMU common code,
including adding GED support for CPU Hot-Plug, updating
the ACPI table creation process, and adding qdev_disconnect_gpio_out_named
and cpu_address_space_destroy interfaces to release resources
when CPU un-plug.

For the modification of the public part of the code, we refer to the
arm-related patch, and the link address of the corresponding patch is
as follows:
https://lore.kernel.org/all/20200613213629.21984-1-salil.me...@huawei.com/

In order to respect the work of "Salil Mehta", we will rebase the first
4 patches in the final patch, which are referenced here to ensure that
the loongarch cpu hotplug can work properly.

The last 6 patches are Loongarch architecture-related,
and the modifications include the definition of the hook
function related to the CPU Hot-(UN)Plug, the allocation
and release of CPU resources when CPU Hot-(UN)Plug,
the creation process of updating the ACPI table,
and finally the custom switch for the CPU Hot-Plug.

V2:
- Fix formatting and spelling errors
- Split large patches into smaller patches
  - Split the original patch
<> into
<>
<>
<>.
  - Split the original patch
<> into
<>
<>
- Added loongarch cpu topology calculation method.
- Change the position of the cpu topology patch.
- Change unreasonable variable and function names.



xianglai li (10):
  Update ACPI GED framework to support vcpu hot-(un)plug
  Update CPUs AML with cpu-(ctrl)dev change
  make qdev_disconnect_gpio_out_named() public
  Introduce the CPU address space destruction function
  Added CPU topology support for Loongarch
  Optimize loongarch_irq_init function implementation
  Add basic CPU hot-(un)plug support for Loongarch
  Add support of *unrealize* for Loongarch cpu
  Add generic event device for Loongarch
  Update the ACPI table for the Loongarch CPU

 .../devices/loongarch64-softmmu/default.mak   |   1 +
 docs/system/loongarch/virt.rst|  31 ++
 hw/acpi/acpi-cpu-hotplug-stub.c   |  15 +
 hw/acpi/cpu.c |  27 +-
 hw/acpi/generic_event_device.c|  33 ++
 hw/core/gpio.c|   4 +-
 hw/i386/acpi-build.c  |   2 +-
 hw/loongarch/acpi-build.c |  33 +-
 hw/loongarch/generic_event_device_loongarch.c |  36 ++
 hw/loongarch/meson.build  |   2 +-
 hw/loongarch/virt.c   | 424 +++---
 include/exec/cpu-common.h |   8 +
 include/hw/acpi/cpu.h |   5 +-
 include/hw/acpi/cpu_hotplug.h |  10 +
 include/hw/acpi/generic_event_device.h|   6 +
 include/hw/core/cpu.h |   1 +
 include/hw/loongarch/virt.h   |  10 +-
 include/hw/qdev-core.h|   2 +
 softmmu/physmem.c |  24 +
 target/loongarch/cpu.c|  35 +-
 target/loongarch/cpu.h|  13 +-
 21 files changed, 635 insertions(+), 87 deletions(-)
 create mode 100644 hw/loongarch/generic_event_device_loongarch.c

Cc: "Salil Mehta" 
Cc: Xiaojuan Yang 
Cc: Song Gao 
Cc: "Michael S. Tsirkin" 
Cc: Igor Mammedov 
Cc: Ani Sinha 
Cc: Paolo Bonzini 
Cc: Richard Henderson 
Cc: Eduardo Habkost 
Cc: Marcel Apfelbaum 
Cc: "Philippe Mathieu-Daudé" 
Cc: Yanan Wang 
Cc: "Daniel P. Berrangé" 
Cc: Peter Xu 
Cc: David Hildenbrand 
Cc: Bibo Mao 
Cc: Xianglai li 
--
2.39.1




[PATCH v2 03/10] make qdev_disconnect_gpio_out_named() public

2023-09-11 Thread xianglai li
It will be reused in loongarch/virt.c for unwiring
the vcpu<->exioi interrupts for the vcpu hot-(un)plug
cases.

Co-authored-by: "Salil Mehta" 
Cc: "Salil Mehta" 
Cc: Xiaojuan Yang 
Cc: Song Gao 
Cc: "Michael S. Tsirkin" 
Cc: Igor Mammedov 
Cc: Ani Sinha 
Cc: Paolo Bonzini 
Cc: Richard Henderson 
Cc: Eduardo Habkost 
Cc: Marcel Apfelbaum 
Cc: "Philippe Mathieu-Daudé" 
Cc: Yanan Wang 
Cc: "Daniel P. Berrangé" 
Cc: Peter Xu 
Cc: David Hildenbrand 
Cc: Bibo Mao 
Signed-off-by: xianglai li 
---
 hw/core/gpio.c | 4 ++--
 include/hw/qdev-core.h | 2 ++
 2 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/hw/core/gpio.c b/hw/core/gpio.c
index 80d07a6ec9..4fc6409545 100644
--- a/hw/core/gpio.c
+++ b/hw/core/gpio.c
@@ -143,8 +143,8 @@ qemu_irq qdev_get_gpio_out_connector(DeviceState *dev, 
const char *name, int n)
 
 /* disconnect a GPIO output, returning the disconnected input (if any) */
 
-static qemu_irq qdev_disconnect_gpio_out_named(DeviceState *dev,
-   const char *name, int n)
+qemu_irq qdev_disconnect_gpio_out_named(DeviceState *dev,
+const char *name, int n)
 {
 char *propname = g_strdup_printf("%s[%d]",
  name ? name : "unnamed-gpio-out", n);
diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h
index 151d968238..32bb54163e 100644
--- a/include/hw/qdev-core.h
+++ b/include/hw/qdev-core.h
@@ -739,6 +739,8 @@ qemu_irq qdev_get_gpio_out_connector(DeviceState *dev, 
const char *name, int n);
  */
 qemu_irq qdev_intercept_gpio_out(DeviceState *dev, qemu_irq icpt,
  const char *name, int n);
+qemu_irq qdev_disconnect_gpio_out_named(DeviceState *dev,
+const char *name, int n);
 
 BusState *qdev_get_child_bus(DeviceState *dev, const char *name);
 
-- 
2.39.1




[PATCH v2 07/10] Add basic CPU hot-(un)plug support for Loongarch

2023-09-11 Thread xianglai li
Add CPU hot-(un)plug related hook functions and
turn on the CPU hot-(un)plug custom switch.

Cc: "Salil Mehta" 
Cc: Xiaojuan Yang 
Cc: Song Gao 
Cc: "Michael S. Tsirkin" 
Cc: Igor Mammedov 
Cc: Ani Sinha 
Cc: Paolo Bonzini 
Cc: Richard Henderson 
Cc: Eduardo Habkost 
Cc: Marcel Apfelbaum 
Cc: "Philippe Mathieu-Daudé" 
Cc: Yanan Wang 
Cc: "Daniel P. Berrangé" 
Cc: Peter Xu 
Cc: David Hildenbrand 
Cc: Bibo Mao 
Signed-off-by: xianglai li 
---
 .../devices/loongarch64-softmmu/default.mak   |   1 +
 hw/loongarch/virt.c   | 223 ++
 2 files changed, 224 insertions(+)

diff --git a/configs/devices/loongarch64-softmmu/default.mak 
b/configs/devices/loongarch64-softmmu/default.mak
index 928bc117ef..e596706fab 100644
--- a/configs/devices/loongarch64-softmmu/default.mak
+++ b/configs/devices/loongarch64-softmmu/default.mak
@@ -1,3 +1,4 @@
 # Default configuration for loongarch64-softmmu
 
 CONFIG_LOONGARCH_VIRT=y
+CONFIG_ACPI_CPU_HOTPLUG=y
diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c
index fb06b4ab4e..aabe8aa814 100644
--- a/hw/loongarch/virt.c
+++ b/hw/loongarch/virt.c
@@ -999,11 +999,93 @@ static void virt_get_cpu_topo_by_cpu_index(const 
MachineState *ms,
 cpu_topo->thread_id = cpu_index % ms->smp.threads;
 }
 
+/* find cpu slot in machine->possible_cpus by arch_id */
+static CPUArchId *loongarch_find_cpu_slot(MachineState *ms, int arch_id)
+{
+int n;
+for (n = 0; n < ms->possible_cpus->len; n++) {
+if (ms->possible_cpus->cpus[n].arch_id == arch_id) {
+return >possible_cpus->cpus[n];
+}
+}
+
+return NULL;
+}
+
+static void loongarch_cpu_pre_plug(HotplugHandler *hotplug_dev,
+DeviceState *dev, Error **errp)
+{
+MachineState *ms = MACHINE(OBJECT(hotplug_dev));
+MachineClass *mc = MACHINE_GET_CLASS(hotplug_dev);
+LoongArchCPU *cpu = LOONGARCH_CPU(dev);
+CPUState *cs = CPU(dev);
+CPUArchId *cpu_slot;
+Error *local_err = NULL;
+LoongArchCPUTopo cpu_topo;
+int arch_id;
+
+if (dev->hotplugged && !mc->has_hotpluggable_cpus) {
+error_setg(_err, "CPU hotplug not supported for this machine");
+goto out;
+}
+
+/* sanity check the cpu */
+if (!object_dynamic_cast(OBJECT(cpu), ms->cpu_type)) {
+error_setg(_err, "Invalid CPU type, expected cpu type: '%s'",
+   ms->cpu_type);
+goto out;
+}
+
+if ((cpu->thread_id < 0) || (cpu->thread_id >= ms->smp.threads)) {
+error_setg(_err,
+   "Invalid thread-id %u specified, must be in range 1:%u",
+   cpu->thread_id, ms->smp.threads - 1);
+goto out;
+}
+
+if ((cpu->core_id < 0) || (cpu->core_id >= ms->smp.cores)) {
+error_setg(_err,
+   "Invalid core-id %u specified, must be in range 1:%u",
+   cpu->core_id, ms->smp.cores);
+goto out;
+}
+
+if ((cpu->socket_id < 0) || (cpu->socket_id >= ms->smp.sockets)) {
+error_setg(_err,
+   "Invalid socket-id %u specified, must be in range 1:%u",
+   cpu->socket_id, ms->smp.sockets - 1);
+goto out;
+}
+
+cpu_topo.socket_id = cpu->socket_id;
+cpu_topo.core_id = cpu->core_id;
+cpu_topo.thread_id = cpu->thread_id;
+arch_id = virt_get_arch_id_from_cpu_topo(ms, _topo);
+
+cpu_slot = loongarch_find_cpu_slot(ms, arch_id);
+if (CPU(cpu_slot->cpu)) {
+error_setg(_err,
+   "cpu(id%d=%d:%d:%d) with arch-id %" PRIu64 " exists",
+   cs->cpu_index, cpu->socket_id, cpu->core_id,
+   cpu->thread_id, cpu_slot->arch_id);
+goto out;
+}
+cpu->arch_id = arch_id;
+
+numa_cpu_pre_plug(cpu_slot, dev, _err);
+
+return ;
+out:
+error_propagate(errp, local_err);
+}
+
 static void virt_machine_device_pre_plug(HotplugHandler *hotplug_dev,
 DeviceState *dev, Error **errp)
 {
 if (memhp_type_supported(dev)) {
 virt_mem_pre_plug(hotplug_dev, dev, errp);
+} else if (object_dynamic_cast(OBJECT(dev), TYPE_LOONGARCH_CPU)) {
+loongarch_cpu_pre_plug(hotplug_dev, dev, errp);
 }
 }
 
@@ -1017,11 +1099,45 @@ static void virt_mem_unplug_request(HotplugHandler 
*hotplug_dev,
errp);
 }
 
+static void loongarch_cpu_unplug_request(HotplugHandler *hotplug_dev,
+DeviceState *dev, Error **errp)
+{
+MachineState *machine = MACHINE(OBJECT(hotplug_dev));
+LoongArchMachineState *lsms = LOONGARCH_MACHINE(machine);
+Error *local_err = NULL;
+HotplugHandlerClass *hhc;
+LoongArchCPU *cpu = LOONGARC

[PATCH v2 01/10] Update ACPI GED framework to support vcpu hot-(un)plug

2023-09-11 Thread xianglai li
ACPI GED shall be used to convey to the guest kernel about any cpu hot-(un)plug
events. Therefore, existing ACPI GED framework inside QEMU needs to be enhanced
to support CPU hot-(un)plug state and events.

Co-authored-by: "Salil Mehta" 
Cc: "Salil Mehta" 
Cc: Xiaojuan Yang 
Cc: Song Gao 
Cc: "Michael S. Tsirkin" 
Cc: Igor Mammedov 
Cc: Ani Sinha 
Cc: Paolo Bonzini 
Cc: Richard Henderson 
Cc: Eduardo Habkost 
Cc: Marcel Apfelbaum 
Cc: "Philippe Mathieu-Daudé" 
Cc: Yanan Wang 
Cc: "Daniel P. Berrangé" 
Cc: Peter Xu 
Cc: David Hildenbrand 
Cc: Bibo Mao 
Signed-off-by: xianglai li 
---
 hw/acpi/acpi-cpu-hotplug-stub.c|  6 +
 hw/acpi/cpu.c  |  7 --
 hw/acpi/generic_event_device.c | 33 ++
 include/hw/acpi/cpu_hotplug.h  | 10 
 include/hw/acpi/generic_event_device.h |  5 
 5 files changed, 54 insertions(+), 7 deletions(-)

diff --git a/hw/acpi/acpi-cpu-hotplug-stub.c b/hw/acpi/acpi-cpu-hotplug-stub.c
index 3fc4b14c26..2aec90d968 100644
--- a/hw/acpi/acpi-cpu-hotplug-stub.c
+++ b/hw/acpi/acpi-cpu-hotplug-stub.c
@@ -24,6 +24,12 @@ void acpi_cpu_ospm_status(CPUHotplugState *cpu_st, 
ACPIOSTInfoList ***list)
 return;
 }
 
+void cpu_hotplug_hw_init(MemoryRegion *as, Object *owner,
+ CPUHotplugState *state, hwaddr base_addr)
+{
+return;
+}
+
 void acpi_cpu_plug_cb(HotplugHandler *hotplug_dev,
   CPUHotplugState *cpu_st, DeviceState *dev, Error **errp)
 {
diff --git a/hw/acpi/cpu.c b/hw/acpi/cpu.c
index 19c154d78f..6897c8789a 100644
--- a/hw/acpi/cpu.c
+++ b/hw/acpi/cpu.c
@@ -6,13 +6,6 @@
 #include "trace.h"
 #include "sysemu/numa.h"
 
-#define ACPI_CPU_HOTPLUG_REG_LEN 12
-#define ACPI_CPU_SELECTOR_OFFSET_WR 0
-#define ACPI_CPU_FLAGS_OFFSET_RW 4
-#define ACPI_CPU_CMD_OFFSET_WR 5
-#define ACPI_CPU_CMD_DATA_OFFSET_RW 8
-#define ACPI_CPU_CMD_DATA2_OFFSET_R 0
-
 #define OVMF_CPUHP_SMI_CMD 4
 
 enum {
diff --git a/hw/acpi/generic_event_device.c b/hw/acpi/generic_event_device.c
index a3d31631fe..c5a70957b4 100644
--- a/hw/acpi/generic_event_device.c
+++ b/hw/acpi/generic_event_device.c
@@ -12,6 +12,7 @@
 #include "qemu/osdep.h"
 #include "qapi/error.h"
 #include "hw/acpi/acpi.h"
+#include "hw/acpi/cpu.h"
 #include "hw/acpi/generic_event_device.h"
 #include "hw/irq.h"
 #include "hw/mem/pc-dimm.h"
@@ -25,6 +26,7 @@ static const uint32_t ged_supported_events[] = {
 ACPI_GED_MEM_HOTPLUG_EVT,
 ACPI_GED_PWR_DOWN_EVT,
 ACPI_GED_NVDIMM_HOTPLUG_EVT,
+ACPI_GED_CPU_HOTPLUG_EVT,
 };
 
 /*
@@ -117,6 +119,10 @@ void build_ged_aml(Aml *table, const char *name, 
HotplugHandler *hotplug_dev,
aml_notify(aml_name("\\_SB.NVDR"),
   aml_int(0x80)));
 break;
+case ACPI_GED_CPU_HOTPLUG_EVT:
+aml_append(if_ctx, aml_call0(ACPI_CPU_CONTAINER "."
+ ACPI_CPU_SCAN_METHOD));
+break;
 default:
 /*
  * Please make sure all the events in ged_supported_events[]
@@ -234,6 +240,8 @@ static void acpi_ged_device_plug_cb(HotplugHandler 
*hotplug_dev,
 } else {
 acpi_memory_plug_cb(hotplug_dev, >memhp_state, dev, errp);
 }
+} else if (object_dynamic_cast(OBJECT(dev), TYPE_CPU)) {
+acpi_cpu_plug_cb(hotplug_dev, >cpuhp_state, dev, errp);
 } else {
 error_setg(errp, "virt: device plug request for unsupported device"
" type: %s", object_get_typename(OBJECT(dev)));
@@ -248,6 +256,8 @@ static void acpi_ged_unplug_request_cb(HotplugHandler 
*hotplug_dev,
 if ((object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM) &&
!(object_dynamic_cast(OBJECT(dev), TYPE_NVDIMM {
 acpi_memory_unplug_request_cb(hotplug_dev, >memhp_state, dev, errp);
+} else if (object_dynamic_cast(OBJECT(dev), TYPE_CPU)) {
+acpi_cpu_unplug_request_cb(hotplug_dev, >cpuhp_state, dev, errp);
 } else {
 error_setg(errp, "acpi: device unplug request for unsupported device"
" type: %s", object_get_typename(OBJECT(dev)));
@@ -261,6 +271,8 @@ static void acpi_ged_unplug_cb(HotplugHandler *hotplug_dev,
 
 if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) {
 acpi_memory_unplug_cb(>memhp_state, dev, errp);
+} else if (object_dynamic_cast(OBJECT(dev), TYPE_CPU)) {
+acpi_cpu_unplug_cb(>cpuhp_state, dev, errp);
 } else {
 error_setg(errp, "acpi: device unplug for unsupported device"
" type: %s", object_get_typename(OBJECT(dev)));
@@ -272,6 +284,7 @@ static void acpi_ged_ospm_status(AcpiDeviceIf *adev

[PATCH] roms: Support compile the efi bios for loongarch

2023-08-10 Thread xianglai li
1.Add edk2-platform submodule
2.Added loongarch UEFI BIOS support to compiled scripts.
3.The cross-compilation toolchain on x86 can be obtained from the link below:
https://github.com/loongson/build-tools/tree/2022.09.06

Cc: Paolo Bonzini 
Cc: "Marc-André Lureau" 
Cc: "Daniel P. Berrangé" 
Cc: Thomas Huth 
Cc: "Philippe Mathieu-Daudé" 
Cc: Gerd Hoffmann 
Cc: Xiaojuan Yang 
Cc: Song Gao 
Cc: Bibo Mao 
Signed-off-by: xianglai li 
---
 .gitmodules|  3 +++
 meson.build|  2 +-
 pc-bios/meson.build|  2 ++
 roms/edk2-build.config | 14 ++
 roms/edk2-build.py |  4 ++--
 roms/edk2-platforms|  1 +
 6 files changed, 23 insertions(+), 3 deletions(-)
 create mode 16 roms/edk2-platforms

diff --git a/.gitmodules b/.gitmodules
index 73cae4cd4d..0cb57123fa 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -43,3 +43,6 @@
 [submodule "tests/lcitool/libvirt-ci"]
path = tests/lcitool/libvirt-ci
url = https://gitlab.com/libvirt/libvirt-ci.git
+[submodule "roms/edk2-platforms"]
+   path = roms/edk2-platforms
+   url = https://github.com/tianocore/edk2-platforms.git
diff --git a/meson.build b/meson.build
index 98e68ef0b1..b398caf2ce 100644
--- a/meson.build
+++ b/meson.build
@@ -153,7 +153,7 @@ if targetos != 'darwin'
   modular_tcg = ['i386-softmmu', 'x86_64-softmmu']
 endif
 
-edk2_targets = [ 'arm-softmmu', 'aarch64-softmmu', 'i386-softmmu', 
'x86_64-softmmu' ]
+edk2_targets = [ 'arm-softmmu', 'aarch64-softmmu', 'i386-softmmu', 
'x86_64-softmmu', 'loongarch64-softmmu' ]
 unpack_edk2_blobs = false
 foreach target : edk2_targets
   if target in target_dirs
diff --git a/pc-bios/meson.build b/pc-bios/meson.build
index a7224ef469..fc73222b6c 100644
--- a/pc-bios/meson.build
+++ b/pc-bios/meson.build
@@ -9,6 +9,8 @@ if unpack_edk2_blobs
 'edk2-i386-vars.fd',
 'edk2-x86_64-code.fd',
 'edk2-x86_64-secure-code.fd',
+'edk2-loongarch64-code.fd',
+'edk2-loongarch64-vars.fd',
   ]
 
   foreach f : fds
diff --git a/roms/edk2-build.config b/roms/edk2-build.config
index 66ef9ffcb9..7960c4c2c5 100644
--- a/roms/edk2-build.config
+++ b/roms/edk2-build.config
@@ -1,5 +1,6 @@
 [global]
 core = edk2
+pkgs = edk2-platforms
 
 

 # options
@@ -122,3 +123,16 @@ plat = RiscVVirtQemu
 dest = ../pc-bios
 cpy1 = FV/RISCV_VIRT.fd  edk2-riscv.fd
 pad1 = edk2-riscv.fd 32m
+
+
+# LoongArch64
+
+[build.loongach64.qemu]
+conf = Platform/Loongson/LoongArchQemuPkg/Loongson.dsc
+arch = LOONGARCH64
+plat = LoongArchQemu
+dest = ../pc-bios
+cpy1 = FV/QEMU_EFI.fd  edk2-loongarch64-code.fd
+pad1 = edk2-loongarch64-code.fd 4m
+cpy2 = FV/QEMU_VARS.fd  edk2-loongarch64-vars.fd
+pad2 = edk2-loongarch64-vars.fd 16m
diff --git a/roms/edk2-build.py b/roms/edk2-build.py
index 870893f7c8..dbd641e51e 100755
--- a/roms/edk2-build.py
+++ b/roms/edk2-build.py
@@ -269,8 +269,8 @@ def prepare_env(cfg):
 # for cross builds
 if binary_exists('arm-linux-gnu-gcc'):
 os.environ['GCC5_ARM_PREFIX'] = 'arm-linux-gnu-'
-if binary_exists('loongarch64-linux-gnu-gcc'):
-os.environ['GCC5_LOONGARCH64_PREFIX'] = 'loongarch64-linux-gnu-'
+if binary_exists('loongarch64-unknown-linux-gnu-gcc'):
+os.environ['GCC5_LOONGARCH64_PREFIX'] = 
'loongarch64-unknown-linux-gnu-'
 
 hostarch = os.uname().machine
 if binary_exists('aarch64-linux-gnu-gcc') and hostarch != 'aarch64':
diff --git a/roms/edk2-platforms b/roms/edk2-platforms
new file mode 16
index 00..84ccada592
--- /dev/null
+++ b/roms/edk2-platforms
@@ -0,0 +1 @@
+Subproject commit 84ccada59257a8151a592a416017fbb03b8ed3cf
-- 
2.39.1




[PATCH 6/8] Add support of *unrealize* for loongarch cpu

2023-07-20 Thread xianglai li
1.Add the Unrealize function to the Loongarch CPU for cpu hot-(un)plug
2.Add CPU topology-related properties to the Loongarch CPU for cpu hot-(un)plug

Cc: Xiaojuan Yang 
Cc: Song Gao 
Cc: "Michael S. Tsirkin" 
Cc: Igor Mammedov 
Cc: Ani Sinha 
Cc: Paolo Bonzini 
Cc: Richard Henderson 
Cc: Eduardo Habkost 
Cc: Marcel Apfelbaum 
Cc: "Philippe Mathieu-Daudé" 
Cc: Yanan Wang 
Cc: "Daniel P. Berrangé" 
Cc: Peter Xu 
Cc: David Hildenbrand 
Signed-off-by: xianglai li 
---
 target/loongarch/cpu.c | 33 +
 target/loongarch/cpu.h |  1 +
 2 files changed, 34 insertions(+)

diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c
index ad93ecac92..97c577820f 100644
--- a/target/loongarch/cpu.c
+++ b/target/loongarch/cpu.c
@@ -18,6 +18,7 @@
 #include "cpu-csr.h"
 #include "sysemu/reset.h"
 #include "tcg/tcg.h"
+#include "hw/qdev-properties.h"
 
 const char * const regnames[32] = {
 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
@@ -540,6 +541,24 @@ static void loongarch_cpu_realizefn(DeviceState *dev, 
Error **errp)
 lacc->parent_realize(dev, errp);
 }
 
+static void loongarch_cpu_unrealizefn(DeviceState *dev)
+{
+LoongArchCPUClass *mcc = LOONGARCH_CPU_GET_CLASS(dev);
+
+#ifndef CONFIG_USER_ONLY
+CPUState *cs = CPU(dev);
+LoongArchCPU *cpu = LOONGARCH_CPU(dev);
+CPULoongArchState *env = >env;
+
+cpu_remove_sync(CPU(dev));
+cpu_address_space_destroy(cs, 0);
+address_space_destroy(>address_space_iocsr);
+memory_region_del_subregion(>system_iocsr, >iocsr_mem);
+#endif
+
+mcc->parent_unrealize(dev);
+}
+
 #ifndef CONFIG_USER_ONLY
 static void loongarch_qemu_write(void *opaque, hwaddr addr,
  uint64_t val, unsigned size)
@@ -697,6 +716,15 @@ static gchar *loongarch_gdb_arch_name(CPUState *cs)
 return g_strdup("loongarch64");
 }
 
+static Property loongarch_cpu_properties[] = {
+DEFINE_PROP_INT32("socket-id", LoongArchCPU, socket_id, 0),
+DEFINE_PROP_INT32("core-id", LoongArchCPU, core_id, 0),
+DEFINE_PROP_INT32("thread-id", LoongArchCPU, thread_id, 0),
+DEFINE_PROP_INT32("node-id", LoongArchCPU, node_id, 
CPU_UNSET_NUMA_NODE_ID),
+
+DEFINE_PROP_END_OF_LIST()
+};
+
 static void loongarch_cpu_class_init(ObjectClass *c, void *data)
 {
 LoongArchCPUClass *lacc = LOONGARCH_CPU_CLASS(c);
@@ -704,8 +732,12 @@ static void loongarch_cpu_class_init(ObjectClass *c, void 
*data)
 DeviceClass *dc = DEVICE_CLASS(c);
 ResettableClass *rc = RESETTABLE_CLASS(c);
 
+device_class_set_props(dc, loongarch_cpu_properties);
 device_class_set_parent_realize(dc, loongarch_cpu_realizefn,
 >parent_realize);
+device_class_set_parent_unrealize(dc, loongarch_cpu_unrealizefn,
+  >parent_unrealize);
+
 resettable_class_set_parent_phases(rc, NULL, loongarch_cpu_reset_hold, 
NULL,
>parent_phases);
 
@@ -730,6 +762,7 @@ static void loongarch_cpu_class_init(ObjectClass *c, void 
*data)
 #ifdef CONFIG_TCG
 cc->tcg_ops = _tcg_ops;
 #endif
+dc->user_creatable = true;
 }
 
 #define DEFINE_LOONGARCH_CPU_TYPE(model, initfn) \
diff --git a/target/loongarch/cpu.h b/target/loongarch/cpu.h
index f4439c245f..32feee4fe6 100644
--- a/target/loongarch/cpu.h
+++ b/target/loongarch/cpu.h
@@ -397,6 +397,7 @@ struct LoongArchCPUClass {
 /*< public >*/
 
 DeviceRealize parent_realize;
+DeviceUnrealize parent_unrealize;
 ResettablePhases parent_phases;
 };
 
-- 
2.39.1




[PATCH 0/8] Adds CPU hot-plug support to Loongarch

2023-07-20 Thread xianglai li
Hello everyone, We refer to the implementation of ARM CPU
Hot-Plug to add GED-based CPU Hot-Plug support to Loongarch.

The first 4 patches are changes to the QEMU common code,
including adding GED support for CPU Hot-Plug, updating
the ACPI table creation process, and adding qdev_disconnect_gpio_out_named
and cpu_address_space_destroy interfaces to release resources
when CPU un-plug.

The last four patches are Loongarch architecture-related,
and the modifications include the definition of the hook
function related to the CPU Hot-(UN)Plug, the allocation
and release of CPU resources when CPU Hot-(UN)Plug,
the creation process of updating the ACPI table,
and finally the custom switch for the CPU Hot-Plug.

xianglai li (8):
  Update ACPI GED framework to support vcpu hot-(un)plug
  Update CPUs AML with cpu-(ctrl)dev change
  Introduced a new function to disconnect GPIO connections
  Introduce the CPU address space destruction function
  Adds basic CPU hot-(un)plug support for Loongarch
  Add support of *unrealize* for loongarch cpu
  Update the ACPI table for the Loongarch CPU
  Turn on CPU hot-(un)plug customization for loongarch

 .../devices/loongarch64-softmmu/default.mak   |   1 +
 hw/acpi/acpi-cpu-hotplug-stub.c   |  15 +
 hw/acpi/cpu.c |  37 +-
 hw/acpi/generic_event_device.c|  33 ++
 hw/core/gpio.c|   4 +-
 hw/i386/acpi-build.c  |   2 +-
 hw/loongarch/acpi-build.c |  35 +-
 hw/loongarch/generic_event_device_loongarch.c |  36 ++
 hw/loongarch/meson.build  |   2 +-
 hw/loongarch/virt.c   | 381 +-
 include/exec/cpu-common.h |   8 +
 include/hw/acpi/cpu.h |   5 +-
 include/hw/acpi/cpu_hotplug.h |  10 +
 include/hw/acpi/generic_event_device.h|   6 +
 include/hw/core/cpu.h |   1 +
 include/hw/loongarch/virt.h   |  11 +-
 include/hw/qdev-core.h|   2 +
 softmmu/physmem.c |  24 ++
 target/loongarch/cpu.c|  33 ++
 target/loongarch/cpu.h|   5 +
 20 files changed, 615 insertions(+), 36 deletions(-)
 create mode 100644 hw/loongarch/generic_event_device_loongarch.c

-- 
2.39.1




[PATCH 4/8] Introduce the CPU address space destruction function

2023-07-20 Thread xianglai li
Introduce new functions to destroy CPU address space resources
for cpu hot-(un)plug.

Cc: Xiaojuan Yang 
Cc: Song Gao 
Cc: "Michael S. Tsirkin" 
Cc: Igor Mammedov 
Cc: Ani Sinha 
Cc: Paolo Bonzini 
Cc: Richard Henderson 
Cc: Eduardo Habkost 
Cc: Marcel Apfelbaum 
Cc: "Philippe Mathieu-Daudé" 
Cc: Yanan Wang 
Cc: "Daniel P. Berrangé" 
Cc: Peter Xu 
Cc: David Hildenbrand 
Signed-off-by: xianglai li 
---
 include/exec/cpu-common.h |  8 
 include/hw/core/cpu.h |  1 +
 softmmu/physmem.c | 24 
 3 files changed, 33 insertions(+)

diff --git a/include/exec/cpu-common.h b/include/exec/cpu-common.h
index 87dc9a752c..27cd4d32b1 100644
--- a/include/exec/cpu-common.h
+++ b/include/exec/cpu-common.h
@@ -120,6 +120,14 @@ size_t qemu_ram_pagesize_largest(void);
  */
 void cpu_address_space_init(CPUState *cpu, int asidx,
 const char *prefix, MemoryRegion *mr);
+/**
+ * cpu_address_space_destroy:
+ * @cpu: CPU for which address space needs to be destroyed
+ * @asidx: integer index of this address space
+ *
+ * Note that with KVM only one address space is supported.
+ */
+void cpu_address_space_destroy(CPUState *cpu, int asidx);
 
 void cpu_physical_memory_rw(hwaddr addr, void *buf,
 hwaddr len, bool is_write);
diff --git a/include/hw/core/cpu.h b/include/hw/core/cpu.h
index fdcbe87352..d6d68dac12 100644
--- a/include/hw/core/cpu.h
+++ b/include/hw/core/cpu.h
@@ -366,6 +366,7 @@ struct CPUState {
 QSIMPLEQ_HEAD(, qemu_work_item) work_list;
 
 CPUAddressSpace *cpu_ases;
+int cpu_ases_ref_count;
 int num_ases;
 AddressSpace *as;
 MemoryRegion *memory;
diff --git a/softmmu/physmem.c b/softmmu/physmem.c
index 3df73542e1..f4545b4508 100644
--- a/softmmu/physmem.c
+++ b/softmmu/physmem.c
@@ -762,6 +762,7 @@ void cpu_address_space_init(CPUState *cpu, int asidx,
 
 if (!cpu->cpu_ases) {
 cpu->cpu_ases = g_new0(CPUAddressSpace, cpu->num_ases);
+cpu->cpu_ases_ref_count = cpu->num_ases;
 }
 
 newas = >cpu_ases[asidx];
@@ -775,6 +776,29 @@ void cpu_address_space_init(CPUState *cpu, int asidx,
 }
 }
 
+void cpu_address_space_destroy(CPUState *cpu, int asidx)
+{
+CPUAddressSpace *cpuas;
+
+assert(asidx < cpu->num_ases);
+assert(asidx == 0 || !kvm_enabled());
+assert(cpu->cpu_ases);
+
+cpuas = >cpu_ases[asidx];
+if (tcg_enabled()) {
+memory_listener_unregister(>tcg_as_listener);
+}
+
+address_space_destroy(cpuas->as);
+
+cpu->cpu_ases_ref_count--;
+if (cpu->cpu_ases_ref_count == 0) {
+g_free(cpu->cpu_ases);
+cpu->cpu_ases = NULL;
+}
+
+}
+
 AddressSpace *cpu_get_address_space(CPUState *cpu, int asidx)
 {
 /* Return the AddressSpace corresponding to the specified index */
-- 
2.39.1




[PATCH 7/8] Update the ACPI table for the Loongarch CPU

2023-07-20 Thread xianglai li
1.Create a new GED device type for Loongarch,
mount cpu_madt function to update the ACPI table
2.Update the APIC table for loongarch based on
CPU information to support CPU hot-(un)plug

Cc: Xiaojuan Yang 
Cc: Song Gao 
Cc: "Michael S. Tsirkin" 
Cc: Igor Mammedov 
Cc: Ani Sinha 
Cc: Paolo Bonzini 
Cc: Richard Henderson 
Cc: Eduardo Habkost 
Cc: Marcel Apfelbaum 
Cc: "Philippe Mathieu-Daudé" 
Cc: Yanan Wang 
Cc: "Daniel P. Berrangé" 
Cc: Peter Xu 
Cc: David Hildenbrand 
Signed-off-by: xianglai li 
---
 hw/acpi/acpi-cpu-hotplug-stub.c   |  9 +
 hw/loongarch/acpi-build.c | 35 --
 hw/loongarch/generic_event_device_loongarch.c | 36 +++
 hw/loongarch/meson.build  |  2 +-
 4 files changed, 79 insertions(+), 3 deletions(-)
 create mode 100644 hw/loongarch/generic_event_device_loongarch.c

diff --git a/hw/acpi/acpi-cpu-hotplug-stub.c b/hw/acpi/acpi-cpu-hotplug-stub.c
index 2aec90d968..af9fda2cf4 100644
--- a/hw/acpi/acpi-cpu-hotplug-stub.c
+++ b/hw/acpi/acpi-cpu-hotplug-stub.c
@@ -19,6 +19,15 @@ void legacy_acpi_cpu_hotplug_init(MemoryRegion *parent, 
Object *owner,
 return;
 }
 
+void build_cpus_aml(Aml *table, MachineState *machine, CPUHotplugFeatures opts,
+hwaddr mmap_io_base,
+const char *res_root,
+const char *event_handler_method,
+AmlRegionSpace rs)
+{
+return;
+}
+
 void acpi_cpu_ospm_status(CPUHotplugState *cpu_st, ACPIOSTInfoList ***list)
 {
 return;
diff --git a/hw/loongarch/acpi-build.c b/hw/loongarch/acpi-build.c
index 0b62c3a2f7..312908fb2f 100644
--- a/hw/loongarch/acpi-build.c
+++ b/hw/loongarch/acpi-build.c
@@ -46,6 +46,23 @@
 #define ACPI_BUILD_DPRINTF(fmt, ...)
 #endif
 
+void virt_madt_cpu_entry(int uid,
+ const CPUArchIdList *apic_ids,
+ GArray *entry, bool force_enabled)
+{
+uint32_t apic_id = apic_ids->cpus[uid].arch_id;
+/* Flags – Local APIC Flags */
+uint32_t flags = apic_ids->cpus[uid].cpu != NULL || force_enabled ?
+ 1 /* Enabled */ : 0;
+
+/* Rev 1.0b, Table 5-13 Processor Local APIC Structure */
+build_append_int_noprefix(entry, 0, 1);   /* Type */
+build_append_int_noprefix(entry, 8, 1);   /* Length */
+build_append_int_noprefix(entry, uid, 1); /* ACPI Processor ID */
+build_append_int_noprefix(entry, apic_id, 1); /* APIC ID */
+build_append_int_noprefix(entry, flags, 4); /* Flags */
+}
+
 /* build FADT */
 static void init_common_fadt_data(AcpiFadtData *data)
 {
@@ -121,15 +138,18 @@ build_madt(GArray *table_data, BIOSLinker *linker, 
LoongArchMachineState *lams)
 build_append_int_noprefix(table_data, 1 /* PCAT_COMPAT */, 4); /* Flags */
 
 for (i = 0; i < arch_ids->len; i++) {
+uint32_t flags;
+
 /* Processor Core Interrupt Controller Structure */
 arch_id = arch_ids->cpus[i].arch_id;
+flags = arch_ids->cpus[i].cpu ? 1 : 0;
 
 build_append_int_noprefix(table_data, 17, 1);/* Type */
 build_append_int_noprefix(table_data, 15, 1);/* Length */
 build_append_int_noprefix(table_data, 1, 1); /* Version */
-build_append_int_noprefix(table_data, i + 1, 4); /* ACPI Processor ID 
*/
+build_append_int_noprefix(table_data, i, 4); /* ACPI Processor ID 
*/
 build_append_int_noprefix(table_data, arch_id, 4); /* Core ID */
-build_append_int_noprefix(table_data, 1, 4); /* Flags */
+build_append_int_noprefix(table_data, flags, 4);   /* Flags */
 }
 
 /* Extend I/O Interrupt Controller Structure */
@@ -292,6 +312,17 @@ build_la_ged_aml(Aml *dsdt, MachineState *machine)
  AML_SYSTEM_MEMORY,
  VIRT_GED_MEM_ADDR);
 }
+
+if (event & ACPI_GED_CPU_HOTPLUG_EVT) {
+CPUHotplugFeatures opts = {
+.acpi_1_compatible = false,
+.has_legacy_cphp = false
+};
+
+build_cpus_aml(dsdt, machine, opts, VIRT_GED_CPUHP_ADDR,
+   "\\_SB", "\\_GPE._E01", AML_SYSTEM_MEMORY);
+
+}
 acpi_dsdt_add_power_button(dsdt);
 }
 
diff --git a/hw/loongarch/generic_event_device_loongarch.c 
b/hw/loongarch/generic_event_device_loongarch.c
new file mode 100644
index 00..1fe550239b
--- /dev/null
+++ b/hw/loongarch/generic_event_device_loongarch.c
@@ -0,0 +1,36 @@
+/*
+ * loongarch variant of the generic event device for hw reduced acpi
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2 or later, as published by the Free Software Foundation.
+ */
+
+#include "qemu/osdep.h"
+#include "hw/acpi/generic_event_device.h"
+#include "hw/loongarch/virt.h"
+
+stat

[PATCH 2/8] Update CPUs AML with cpu-(ctrl)dev change

2023-07-20 Thread xianglai li
CPUs Control device(\\_SB.PCI0) register interface for the x86 arch is based on
PCI and is IO port based and hence existing cpus AML code assumes _CRS objects
would evaluate to a system resource which describes IO Port address. But on 
LOONGARCH
arch CPUs control device(\\_SB.PRES) register interface is memory-mapped hence
_CRS object should evaluate to system resource which describes memory-mapped
base address.

This cpus AML code change updates the existing inerface of the build cpus AML
function to accept both IO/MEMORY type regions and update the _CRS object
correspondingly.

Cc: Xiaojuan Yang 
Cc: Song Gao 
Cc: "Michael S. Tsirkin" 
Cc: Igor Mammedov 
Cc: Ani Sinha 
Cc: Paolo Bonzini 
Cc: Richard Henderson 
Cc: Eduardo Habkost 
Cc: Marcel Apfelbaum 
Cc: "Philippe Mathieu-Daudé" 
Cc: Yanan Wang 
Cc: "Daniel P. Berrangé" 
Cc: Peter Xu 
Cc: David Hildenbrand 
Signed-off-by: xianglai li 
---
 hw/acpi/cpu.c | 30 +++---
 hw/i386/acpi-build.c  |  2 +-
 include/hw/acpi/cpu.h |  5 +++--
 3 files changed, 27 insertions(+), 10 deletions(-)

diff --git a/hw/acpi/cpu.c b/hw/acpi/cpu.c
index 6897c8789a..3b945a1a40 100644
--- a/hw/acpi/cpu.c
+++ b/hw/acpi/cpu.c
@@ -5,6 +5,7 @@
 #include "qapi/qapi-events-acpi.h"
 #include "trace.h"
 #include "sysemu/numa.h"
+#include "hw/acpi/cpu_hotplug.h"
 
 #define OVMF_CPUHP_SMI_CMD 4
 
@@ -331,9 +332,10 @@ const VMStateDescription vmstate_cpu_hotplug = {
 #define CPU_FW_EJECT_EVENT "CEJF"
 
 void build_cpus_aml(Aml *table, MachineState *machine, CPUHotplugFeatures opts,
-hwaddr io_base,
+hwaddr mmap_io_base,
 const char *res_root,
-const char *event_handler_method)
+const char *event_handler_method,
+AmlRegionSpace rs)
 {
 Aml *ifctx;
 Aml *field;
@@ -360,14 +362,28 @@ void build_cpus_aml(Aml *table, MachineState *machine, 
CPUHotplugFeatures opts,
 aml_append(cpu_ctrl_dev, aml_mutex(CPU_LOCK, 0));
 
 crs = aml_resource_template();
-aml_append(crs, aml_io(AML_DECODE16, io_base, io_base, 1,
+if (rs == AML_SYSTEM_IO) {
+aml_append(crs, aml_io(AML_DECODE16, mmap_io_base, mmap_io_base, 1,
ACPI_CPU_HOTPLUG_REG_LEN));
+} else {
+aml_append(crs, aml_memory32_fixed(mmap_io_base,
+   ACPI_CPU_HOTPLUG_REG_LEN, AML_READ_WRITE));
+}
+
 aml_append(cpu_ctrl_dev, aml_name_decl("_CRS", crs));
 
-/* declare CPU hotplug MMIO region with related access fields */
-aml_append(cpu_ctrl_dev,
-aml_operation_region("PRST", AML_SYSTEM_IO, aml_int(io_base),
- ACPI_CPU_HOTPLUG_REG_LEN));
+if (rs == AML_SYSTEM_IO) {
+/* declare CPU hotplug MMIO region with related access fields */
+aml_append(cpu_ctrl_dev,
+aml_operation_region("PRST", AML_SYSTEM_IO,
+ aml_int(mmap_io_base),
+ ACPI_CPU_HOTPLUG_REG_LEN));
+} else {
+aml_append(cpu_ctrl_dev,
+aml_operation_region("PRST", AML_SYSTEM_MEMORY,
+ aml_int(mmap_io_base),
+ ACPI_CPU_HOTPLUG_REG_LEN));
+}
 
 field = aml_field("PRST", AML_BYTE_ACC, AML_NOLOCK,
   AML_WRITE_AS_ZEROS);
diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
index 9c74fa17ad..5d02690593 100644
--- a/hw/i386/acpi-build.c
+++ b/hw/i386/acpi-build.c
@@ -1548,7 +1548,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,
 .fw_unplugs_cpu = pm->smi_on_cpu_unplug,
 };
 build_cpus_aml(dsdt, machine, opts, pm->cpu_hp_io_base,
-   "\\_SB.PCI0", "\\_GPE._E02");
+   "\\_SB.PCI0", "\\_GPE._E02", AML_SYSTEM_IO);
 }
 
 if (pcms->memhp_io_base && nr_mem) {
diff --git a/include/hw/acpi/cpu.h b/include/hw/acpi/cpu.h
index 999caaf510..cddea78333 100644
--- a/include/hw/acpi/cpu.h
+++ b/include/hw/acpi/cpu.h
@@ -56,9 +56,10 @@ typedef struct CPUHotplugFeatures {
 } CPUHotplugFeatures;
 
 void build_cpus_aml(Aml *table, MachineState *machine, CPUHotplugFeatures opts,
-hwaddr io_base,
+hwaddr mmap_io_base,
 const char *res_root,
-const char *event_handler_method);
+const char *event_handler_method,
+AmlRegionSpace rs);
 
 void acpi_cpu_ospm_status(CPUHotplugState *cpu_st, ACPIOSTInfoList ***list);
 
-- 
2.39.1




[PATCH 1/8] Update ACPI GED framework to support vcpu hot-(un)plug

2023-07-20 Thread xianglai li
ACPI GED shall be used to convey to the guest kernel about any cpu hot-(un)plug
events. Therefore, existing ACPI GED framework inside QEMU needs to be enhanced
to support CPU hot-(un)plug state and events.

Cc: Xiaojuan Yang 
Cc: Song Gao 
Cc: "Michael S. Tsirkin" 
Cc: Igor Mammedov 
Cc: Ani Sinha 
Cc: Paolo Bonzini 
Cc: Richard Henderson 
Cc: Eduardo Habkost 
Cc: Marcel Apfelbaum 
Cc: "Philippe Mathieu-Daudé" 
Cc: Yanan Wang 
Cc: "Daniel P. Berrangé" 
Cc: Peter Xu 
Cc: David Hildenbrand 
Signed-off-by: xianglai li 
---
 hw/acpi/acpi-cpu-hotplug-stub.c|  6 +
 hw/acpi/cpu.c  |  7 --
 hw/acpi/generic_event_device.c | 33 ++
 include/hw/acpi/cpu_hotplug.h  | 10 
 include/hw/acpi/generic_event_device.h |  6 +
 5 files changed, 55 insertions(+), 7 deletions(-)

diff --git a/hw/acpi/acpi-cpu-hotplug-stub.c b/hw/acpi/acpi-cpu-hotplug-stub.c
index 3fc4b14c26..2aec90d968 100644
--- a/hw/acpi/acpi-cpu-hotplug-stub.c
+++ b/hw/acpi/acpi-cpu-hotplug-stub.c
@@ -24,6 +24,12 @@ void acpi_cpu_ospm_status(CPUHotplugState *cpu_st, 
ACPIOSTInfoList ***list)
 return;
 }
 
+void cpu_hotplug_hw_init(MemoryRegion *as, Object *owner,
+ CPUHotplugState *state, hwaddr base_addr)
+{
+return;
+}
+
 void acpi_cpu_plug_cb(HotplugHandler *hotplug_dev,
   CPUHotplugState *cpu_st, DeviceState *dev, Error **errp)
 {
diff --git a/hw/acpi/cpu.c b/hw/acpi/cpu.c
index 19c154d78f..6897c8789a 100644
--- a/hw/acpi/cpu.c
+++ b/hw/acpi/cpu.c
@@ -6,13 +6,6 @@
 #include "trace.h"
 #include "sysemu/numa.h"
 
-#define ACPI_CPU_HOTPLUG_REG_LEN 12
-#define ACPI_CPU_SELECTOR_OFFSET_WR 0
-#define ACPI_CPU_FLAGS_OFFSET_RW 4
-#define ACPI_CPU_CMD_OFFSET_WR 5
-#define ACPI_CPU_CMD_DATA_OFFSET_RW 8
-#define ACPI_CPU_CMD_DATA2_OFFSET_R 0
-
 #define OVMF_CPUHP_SMI_CMD 4
 
 enum {
diff --git a/hw/acpi/generic_event_device.c b/hw/acpi/generic_event_device.c
index a3d31631fe..c5a70957b4 100644
--- a/hw/acpi/generic_event_device.c
+++ b/hw/acpi/generic_event_device.c
@@ -12,6 +12,7 @@
 #include "qemu/osdep.h"
 #include "qapi/error.h"
 #include "hw/acpi/acpi.h"
+#include "hw/acpi/cpu.h"
 #include "hw/acpi/generic_event_device.h"
 #include "hw/irq.h"
 #include "hw/mem/pc-dimm.h"
@@ -25,6 +26,7 @@ static const uint32_t ged_supported_events[] = {
 ACPI_GED_MEM_HOTPLUG_EVT,
 ACPI_GED_PWR_DOWN_EVT,
 ACPI_GED_NVDIMM_HOTPLUG_EVT,
+ACPI_GED_CPU_HOTPLUG_EVT,
 };
 
 /*
@@ -117,6 +119,10 @@ void build_ged_aml(Aml *table, const char *name, 
HotplugHandler *hotplug_dev,
aml_notify(aml_name("\\_SB.NVDR"),
   aml_int(0x80)));
 break;
+case ACPI_GED_CPU_HOTPLUG_EVT:
+aml_append(if_ctx, aml_call0(ACPI_CPU_CONTAINER "."
+ ACPI_CPU_SCAN_METHOD));
+break;
 default:
 /*
  * Please make sure all the events in ged_supported_events[]
@@ -234,6 +240,8 @@ static void acpi_ged_device_plug_cb(HotplugHandler 
*hotplug_dev,
 } else {
 acpi_memory_plug_cb(hotplug_dev, >memhp_state, dev, errp);
 }
+} else if (object_dynamic_cast(OBJECT(dev), TYPE_CPU)) {
+acpi_cpu_plug_cb(hotplug_dev, >cpuhp_state, dev, errp);
 } else {
 error_setg(errp, "virt: device plug request for unsupported device"
" type: %s", object_get_typename(OBJECT(dev)));
@@ -248,6 +256,8 @@ static void acpi_ged_unplug_request_cb(HotplugHandler 
*hotplug_dev,
 if ((object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM) &&
!(object_dynamic_cast(OBJECT(dev), TYPE_NVDIMM {
 acpi_memory_unplug_request_cb(hotplug_dev, >memhp_state, dev, errp);
+} else if (object_dynamic_cast(OBJECT(dev), TYPE_CPU)) {
+acpi_cpu_unplug_request_cb(hotplug_dev, >cpuhp_state, dev, errp);
 } else {
 error_setg(errp, "acpi: device unplug request for unsupported device"
" type: %s", object_get_typename(OBJECT(dev)));
@@ -261,6 +271,8 @@ static void acpi_ged_unplug_cb(HotplugHandler *hotplug_dev,
 
 if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) {
 acpi_memory_unplug_cb(>memhp_state, dev, errp);
+} else if (object_dynamic_cast(OBJECT(dev), TYPE_CPU)) {
+acpi_cpu_unplug_cb(>cpuhp_state, dev, errp);
 } else {
 error_setg(errp, "acpi: device unplug for unsupported device"
" type: %s", object_get_typename(OBJECT(dev)));
@@ -272,6 +284,7 @@ static void acpi_ged_ospm_status(AcpiDeviceIf *adev, 
ACPIOSTInfoList ***list)
 AcpiGedState *s = ACPI_GED(adev);
 
 acpi_memory_

[PATCH 5/8] Adds basic CPU hot-(un)plug support for Loongarch

2023-07-20 Thread xianglai li
1.Add CPU topology related functions
2.Add CPU hot-plug related hook functions
3.Update the in-place CPU creation process at machine initialization

Cc: Xiaojuan Yang 
Cc: Song Gao 
Cc: "Michael S. Tsirkin" 
Cc: Igor Mammedov 
Cc: Ani Sinha 
Cc: Paolo Bonzini 
Cc: Richard Henderson 
Cc: Eduardo Habkost 
Cc: Marcel Apfelbaum 
Cc: "Philippe Mathieu-Daudé" 
Cc: Yanan Wang 
Cc: "Daniel P. Berrangé" 
Cc: Peter Xu 
Cc: David Hildenbrand 
Signed-off-by: xianglai li 
---
 hw/loongarch/virt.c | 381 ++--
 include/hw/loongarch/virt.h |  11 +-
 target/loongarch/cpu.h  |   4 +
 3 files changed, 382 insertions(+), 14 deletions(-)

diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c
index e19b042ce8..5919389f42 100644
--- a/hw/loongarch/virt.c
+++ b/hw/loongarch/virt.c
@@ -46,6 +46,9 @@
 #include "hw/block/flash.h"
 #include "qemu/error-report.h"
 
+static int virt_get_socket_id(const MachineState *ms, int cpu_index);
+static int virt_get_core_id(const MachineState *ms, int cpu_index);
+static int virt_get_thread_id(const MachineState *ms, int cpu_index);
 
 static void virt_flash_create(LoongArchMachineState *lams)
 {
@@ -447,12 +450,12 @@ static DeviceState *create_acpi_ged(DeviceState *pch_pic, 
LoongArchMachineState
 {
 DeviceState *dev;
 MachineState *ms = MACHINE(lams);
-uint32_t event = ACPI_GED_PWR_DOWN_EVT;
+uint32_t event = ACPI_GED_PWR_DOWN_EVT | ACPI_GED_CPU_HOTPLUG_EVT;
 
 if (ms->ram_slots) {
 event |= ACPI_GED_MEM_HOTPLUG_EVT;
 }
-dev = qdev_new(TYPE_ACPI_GED);
+dev = qdev_new(TYPE_ACPI_GED_LOONGARCH);
 qdev_prop_set_uint32(dev, "ged-event", event);
 
 /* ged event */
@@ -461,6 +464,7 @@ static DeviceState *create_acpi_ged(DeviceState *pch_pic, 
LoongArchMachineState
 sysbus_mmio_map(SYS_BUS_DEVICE(dev), 1, VIRT_GED_MEM_ADDR);
 /* ged regs used for reset and power down */
 sysbus_mmio_map(SYS_BUS_DEVICE(dev), 2, VIRT_GED_REG_ADDR);
+sysbus_mmio_map(SYS_BUS_DEVICE(dev), 3, VIRT_GED_CPUHP_ADDR);
 
 sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0,
qdev_get_gpio_in(pch_pic, VIRT_SCI_IRQ - 
VIRT_GSI_BASE));
@@ -583,6 +587,7 @@ static void loongarch_irq_init(LoongArchMachineState *lams)
 
 extioi = qdev_new(TYPE_LOONGARCH_EXTIOI);
 sysbus_realize_and_unref(SYS_BUS_DEVICE(extioi), _fatal);
+lams->extioi = extioi;
 
 /*
  * The connection of interrupts:
@@ -624,11 +629,11 @@ static void loongarch_irq_init(LoongArchMachineState 
*lams)
 sysbus_mmio_get_region(SYS_BUS_DEVICE(ipi),
 1));
 /*
-* extioi iocsr memory region
-* only one extioi is added on loongarch virt machine
-* external device interrupt can only be routed to cpu 0-3
-*/
-   if (cpu < EXTIOI_CPUS)
+ * extioi iocsr memory region
+ * only one extioi is added on loongarch virt machine
+ * external device interrupt can only be routed to cpu 0-3
+ */
+if (cpu < EXTIOI_CPUS)
 memory_region_add_subregion(>system_iocsr, APIC_BASE,
 sysbus_mmio_get_region(SYS_BUS_DEVICE(extioi),
 cpu));
@@ -789,7 +794,6 @@ static void loongarch_init(MachineState *machine)
 NodeInfo *numa_info = machine->numa_state->nodes;
 int i;
 hwaddr fdt_base;
-const CPUArchIdList *possible_cpus;
 MachineClass *mc = MACHINE_GET_CLASS(machine);
 CPUState *cpu;
 char *ramName = NULL;
@@ -810,12 +814,40 @@ static void loongarch_init(MachineState *machine)
 create_fdt(lams);
 /* Init CPUs */
 
-possible_cpus = mc->possible_cpu_arch_ids(machine);
-for (i = 0; i < possible_cpus->len; i++) {
-cpu = cpu_create(machine->cpu_type);
+mc->possible_cpu_arch_ids(machine);
+
+for (i = 0; i < machine->smp.cpus; i++) {
+Object *cpuobj;
+cpuobj = object_new(machine->cpu_type);
+
+cpu = CPU(cpuobj);
 cpu->cpu_index = i;
-machine->possible_cpus->cpus[i].cpu = OBJECT(cpu);
+
+object_property_set_int(cpuobj, "socket-id",
+virt_get_socket_id(machine, i), NULL);
+object_property_set_int(cpuobj, "core-id",
+virt_get_core_id(machine, i), NULL);
+object_property_set_int(cpuobj, "thread-id",
+virt_get_thread_id(machine, i), NULL);
+/*
+ * The CPU in place at the time of machine startup will also enter
+ * the CPU hot-plug process when it is created, but at this time,
+ * the GED device has not been created, resulting in exit in the CPU
+ * hot-plug process, which can avoid the incumbent CPU repeatedly
+ * applying for resources.

[PATCH 8/8] Turn on CPU hot-(un)plug customization for loongarch

2023-07-20 Thread xianglai li
Turn on CPU hot-(un)plug custom for loongarch in the configuration file

Cc: Xiaojuan Yang 
Cc: Song Gao 
Cc: "Michael S. Tsirkin" 
Cc: Igor Mammedov 
Cc: Ani Sinha 
Cc: Paolo Bonzini 
Cc: Richard Henderson 
Cc: Eduardo Habkost 
Cc: Marcel Apfelbaum 
Cc: "Philippe Mathieu-Daudé" 
Cc: Yanan Wang 
Cc: "Daniel P. Berrangé" 
Cc: Peter Xu 
Cc: David Hildenbrand 
Signed-off-by: xianglai li 
---
 configs/devices/loongarch64-softmmu/default.mak | 1 +
 1 file changed, 1 insertion(+)

diff --git a/configs/devices/loongarch64-softmmu/default.mak 
b/configs/devices/loongarch64-softmmu/default.mak
index 928bc117ef..e596706fab 100644
--- a/configs/devices/loongarch64-softmmu/default.mak
+++ b/configs/devices/loongarch64-softmmu/default.mak
@@ -1,3 +1,4 @@
 # Default configuration for loongarch64-softmmu
 
 CONFIG_LOONGARCH_VIRT=y
+CONFIG_ACPI_CPU_HOTPLUG=y
-- 
2.39.1




[PATCH 3/8] Introduced a new function to disconnect GPIO connections

2023-07-20 Thread xianglai li
It introduces a new function to unwire the
vcpu<->exioi interrupts for the vcpu hot-(un)plug cases.

Cc: Xiaojuan Yang 
Cc: Song Gao 
Cc: "Michael S. Tsirkin" 
Cc: Igor Mammedov 
Cc: Ani Sinha 
Cc: Paolo Bonzini 
Cc: Richard Henderson 
Cc: Eduardo Habkost 
Cc: Marcel Apfelbaum 
Cc: "Philippe Mathieu-Daudé" 
Cc: Yanan Wang 
Cc: "Daniel P. Berrangé" 
Cc: Peter Xu 
Cc: David Hildenbrand 
Signed-off-by: xianglai li 
---
 hw/core/gpio.c | 4 ++--
 include/hw/qdev-core.h | 2 ++
 2 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/hw/core/gpio.c b/hw/core/gpio.c
index 80d07a6ec9..4fc6409545 100644
--- a/hw/core/gpio.c
+++ b/hw/core/gpio.c
@@ -143,8 +143,8 @@ qemu_irq qdev_get_gpio_out_connector(DeviceState *dev, 
const char *name, int n)
 
 /* disconnect a GPIO output, returning the disconnected input (if any) */
 
-static qemu_irq qdev_disconnect_gpio_out_named(DeviceState *dev,
-   const char *name, int n)
+qemu_irq qdev_disconnect_gpio_out_named(DeviceState *dev,
+const char *name, int n)
 {
 char *propname = g_strdup_printf("%s[%d]",
  name ? name : "unnamed-gpio-out", n);
diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h
index 884c726a87..992f5419fa 100644
--- a/include/hw/qdev-core.h
+++ b/include/hw/qdev-core.h
@@ -739,6 +739,8 @@ qemu_irq qdev_get_gpio_out_connector(DeviceState *dev, 
const char *name, int n);
  */
 qemu_irq qdev_intercept_gpio_out(DeviceState *dev, qemu_irq icpt,
  const char *name, int n);
+qemu_irq qdev_disconnect_gpio_out_named(DeviceState *dev,
+   const char *name, int n);
 
 BusState *qdev_get_child_bus(DeviceState *dev, const char *name);
 
-- 
2.39.1