loongarch queue

-----BEGIN PGP SIGNATURE-----
 
 iHUEABYKAB0WIQQNhkKjomWfgLCz0aQfewwSUazn0QUCZ7156AAKCRAfewwSUazn
 0T2AAQDW4zr8ECab5FH+udeCtGOv2I6gtTT8CwjwhCdHNzsAAgEAxi0JJOjTIMrK
 z657Q4MTeKbTyzi48niXBbI9hKvyhQM=
 =g4Wx
 -----END PGP SIGNATURE-----

Merge tag 'pull-loongarch-20250225' of https://gitlab.com/bibo-mao/qemu into staging

loongarch queue

# -----BEGIN PGP SIGNATURE-----
#
# iHUEABYKAB0WIQQNhkKjomWfgLCz0aQfewwSUazn0QUCZ7156AAKCRAfewwSUazn
# 0T2AAQDW4zr8ECab5FH+udeCtGOv2I6gtTT8CwjwhCdHNzsAAgEAxi0JJOjTIMrK
# z657Q4MTeKbTyzi48niXBbI9hKvyhQM=
# =g4Wx
# -----END PGP SIGNATURE-----
# gpg: Signature made Tue 25 Feb 2025 16:06:00 HKT
# gpg:                using EDDSA key 0D8642A3A2659F80B0B3D1A41F7B0C1251ACE7D1
# gpg: Good signature from "bibo mao <maobibo@loongson.cn>" [unknown]
# gpg: WARNING: This key is not certified with a trusted signature!
# gpg:          There is no indication that the signature belongs to the owner.
# Primary key fingerprint: 7044 3A00 19C0 E97A 31C7  13C4 8E86 8FB7 A176 9D4C
#      Subkey fingerprint: 0D86 42A3 A265 9F80 B0B3  D1A4 1F7B 0C12 51AC E7D1

* tag 'pull-loongarch-20250225' of https://gitlab.com/bibo-mao/qemu:
  target/loongarch: Enable virtual extioi feature
  target/loongarch: Add kvm steal time feature detection
  target/loongarch: Add vCPU property for kvm steal time feature
  target/loongarch: Enable paravirt ipi feature
  target/loongarch: Add paravirt ipi feature detection
  target/loongarch: Add vCPU property for paravirt ipi feature
  target/loongarch: Move kvm specified vCPU property to kvm directory
  target/loongarch: Add post init function for kvm mode
  target/loongarch: Correct maximum physical address in KVM mode
  target/loongarch/gdbstub: Fix gdbstub incorrectly handling some registers
  target/loongarch: fix vcpu reset command word issue

Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
This commit is contained in:
Stefan Hajnoczi 2025-02-26 07:35:55 +08:00
commit 50d38b8921
7 changed files with 224 additions and 57 deletions

View File

@ -45,14 +45,6 @@
#include "hw/virtio/virtio-iommu.h"
#include "qemu/error-report.h"
static bool virt_is_veiointc_enabled(LoongArchVirtMachineState *lvms)
{
if (lvms->veiointc == ON_OFF_AUTO_OFF) {
return false;
}
return true;
}
static void virt_get_veiointc(Object *obj, Visitor *v, const char *name,
void *opaque, Error **errp)
{

View File

@ -68,4 +68,13 @@ struct LoongArchVirtMachineState {
OBJECT_DECLARE_SIMPLE_TYPE(LoongArchVirtMachineState, LOONGARCH_VIRT_MACHINE)
void virt_acpi_setup(LoongArchVirtMachineState *lvms);
void virt_fdt_setup(LoongArchVirtMachineState *lvms);
static inline bool virt_is_veiointc_enabled(LoongArchVirtMachineState *lvms)
{
if (lvms->veiointc == ON_OFF_AUTO_OFF) {
return false;
}
return true;
}
#endif

View File

@ -406,7 +406,7 @@ static void loongarch_la464_initfn(Object *obj)
{
LoongArchCPU *cpu = LOONGARCH_CPU(obj);
CPULoongArchState *env = &cpu->env;
uint32_t data = 0;
uint32_t data = 0, field;
int i;
for (i = 0; i < 21; i++) {
@ -419,7 +419,13 @@ static void loongarch_la464_initfn(Object *obj)
data = FIELD_DP32(data, CPUCFG1, ARCH, 2);
data = FIELD_DP32(data, CPUCFG1, PGMMU, 1);
data = FIELD_DP32(data, CPUCFG1, IOCSR, 1);
data = FIELD_DP32(data, CPUCFG1, PALEN, 0x2f);
if (kvm_enabled()) {
/* GPA address width of VM is 47, field value is 47 - 1 */
field = 0x2e;
} else {
field = 0x2f; /* 48 bit - 1 */
}
data = FIELD_DP32(data, CPUCFG1, PALEN, field);
data = FIELD_DP32(data, CPUCFG1, VALEN, 0x2f);
data = FIELD_DP32(data, CPUCFG1, UAL, 1);
data = FIELD_DP32(data, CPUCFG1, RI, 1);
@ -712,34 +718,12 @@ static void loongarch_set_lasx(Object *obj, bool value, Error **errp)
cpu->env.cpucfg[2] = FIELD_DP32(val, CPUCFG2, LASX, value);
}
static bool loongarch_get_lbt(Object *obj, Error **errp)
{
return LOONGARCH_CPU(obj)->lbt != ON_OFF_AUTO_OFF;
}
static void loongarch_set_lbt(Object *obj, bool value, Error **errp)
{
LoongArchCPU *cpu = LOONGARCH_CPU(obj);
cpu->lbt = value ? ON_OFF_AUTO_ON : ON_OFF_AUTO_OFF;
}
static bool loongarch_get_pmu(Object *obj, Error **errp)
{
return LOONGARCH_CPU(obj)->pmu != ON_OFF_AUTO_OFF;
}
static void loongarch_set_pmu(Object *obj, bool value, Error **errp)
{
LoongArchCPU *cpu = LOONGARCH_CPU(obj);
cpu->pmu = value ? ON_OFF_AUTO_ON : ON_OFF_AUTO_OFF;
}
void loongarch_cpu_post_init(Object *obj)
{
LoongArchCPU *cpu = LOONGARCH_CPU(obj);
cpu->lbt = ON_OFF_AUTO_OFF;
cpu->pmu = ON_OFF_AUTO_OFF;
cpu->lsx = ON_OFF_AUTO_AUTO;
cpu->lasx = ON_OFF_AUTO_AUTO;
object_property_add_bool(obj, "lsx", loongarch_get_lsx,
@ -748,21 +732,7 @@ void loongarch_cpu_post_init(Object *obj)
loongarch_set_lasx);
/* lbt is enabled only in kvm mode, not supported in tcg mode */
if (kvm_enabled()) {
cpu->lbt = ON_OFF_AUTO_AUTO;
object_property_add_bool(obj, "lbt", loongarch_get_lbt,
loongarch_set_lbt);
object_property_set_description(obj, "lbt",
"Set off to disable Binary Tranlation.");
cpu->pmu = ON_OFF_AUTO_AUTO;
object_property_add_bool(obj, "pmu", loongarch_get_pmu,
loongarch_set_pmu);
object_property_set_description(obj, "pmu",
"Set off to performance monitor unit.");
} else {
cpu->lbt = ON_OFF_AUTO_OFF;
cpu->pmu = ON_OFF_AUTO_OFF;
kvm_loongarch_cpu_post_init(cpu);
}
}

View File

@ -287,6 +287,8 @@ enum loongarch_features {
LOONGARCH_FEATURE_LASX,
LOONGARCH_FEATURE_LBT, /* loongson binary translation extension */
LOONGARCH_FEATURE_PMU,
LOONGARCH_FEATURE_PV_IPI,
LOONGARCH_FEATURE_STEALTIME,
};
typedef struct LoongArchBT {
@ -310,6 +312,7 @@ typedef struct CPUArchState {
lbt_t lbt;
uint32_t cpucfg[21];
uint32_t pv_features;
/* LoongArch CSRs */
uint64_t CSR_CRMD;
@ -406,6 +409,8 @@ struct ArchCPU {
OnOffAuto pmu;
OnOffAuto lsx;
OnOffAuto lasx;
OnOffAuto kvm_pv_ipi;
OnOffAuto kvm_steal_time;
/* 'compatible' string for this CPU for Linux device trees */
const char *dtb_compatible;
@ -491,4 +496,12 @@ static inline void cpu_get_tb_cpu_state(CPULoongArchState *env, vaddr *pc,
void loongarch_cpu_post_init(Object *obj);
#ifdef CONFIG_KVM
void kvm_loongarch_cpu_post_init(LoongArchCPU *cpu);
#else
static inline void kvm_loongarch_cpu_post_init(LoongArchCPU *cpu)
{
}
#endif
#endif /* LOONGARCH_CPU_H */

View File

@ -63,23 +63,24 @@ int loongarch_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
{
CPULoongArchState *env = cpu_env(cs);
target_ulong tmp;
int read_length;
int length = 0;
if (n < 0 || n > 34) {
return 0;
}
if (is_la64(env)) {
tmp = ldq_le_p(mem_buf);
read_length = 8;
length = 8;
} else {
tmp = ldl_le_p(mem_buf);
read_length = 4;
length = 4;
}
if (0 <= n && n < 32) {
env->gpr[n] = tmp;
length = read_length;
} else if (n == 33) {
set_pc(env, tmp);
length = read_length;
}
return length;
}

View File

@ -8,7 +8,7 @@
#include "qemu/osdep.h"
#include <sys/ioctl.h>
#include <linux/kvm.h>
#include "asm-loongarch/kvm_para.h"
#include "qapi/error.h"
#include "qemu/timer.h"
#include "qemu/error-report.h"
@ -21,6 +21,7 @@
#include "exec/address-spaces.h"
#include "hw/boards.h"
#include "hw/irq.h"
#include "hw/loongarch/virt.h"
#include "qemu/log.h"
#include "hw/loader.h"
#include "system/runstate.h"
@ -83,6 +84,33 @@ static int kvm_set_stealtime(CPUState *cs)
return 0;
}
static int kvm_set_pv_features(CPUState *cs)
{
CPULoongArchState *env = cpu_env(cs);
int err;
uint64_t val;
struct kvm_device_attr attr = {
.group = KVM_LOONGARCH_VCPU_CPUCFG,
.attr = CPUCFG_KVM_FEATURE,
.addr = (uint64_t)&val,
};
err = kvm_vcpu_ioctl(cs, KVM_HAS_DEVICE_ATTR, attr);
if (err) {
return 0;
}
val = env->pv_features;
err = kvm_vcpu_ioctl(cs, KVM_SET_DEVICE_ATTR, attr);
if (err) {
error_report("Fail to set pv feature "TARGET_FMT_lx " with error %s",
val, strerror(errno));
return err;
}
return 0;
}
static int kvm_loongarch_get_regs_core(CPUState *cs)
{
int ret = 0;
@ -581,9 +609,16 @@ static int kvm_loongarch_get_lbt(CPUState *cs)
void kvm_arch_reset_vcpu(CPUState *cs)
{
CPULoongArchState *env = cpu_env(cs);
int ret = 0;
uint64_t unused = 0;
env->mp_state = KVM_MP_STATE_RUNNABLE;
kvm_set_one_reg(cs, KVM_REG_LOONGARCH_VCPU_RESET, 0);
ret = kvm_set_one_reg(cs, KVM_REG_LOONGARCH_VCPU_RESET, &unused);
if (ret) {
error_report("Failed to set KVM_REG_LOONGARCH_VCPU_RESET: %s",
strerror(errno));
exit(EXIT_FAILURE);
}
}
static int kvm_loongarch_get_mpstate(CPUState *cs)
@ -731,6 +766,7 @@ int kvm_arch_get_registers(CPUState *cs, Error **errp)
int kvm_arch_put_registers(CPUState *cs, int level, Error **errp)
{
int ret;
static int once;
ret = kvm_loongarch_put_regs_core(cs);
if (ret) {
@ -757,6 +793,14 @@ int kvm_arch_put_registers(CPUState *cs, int level, Error **errp)
return ret;
}
if (!once) {
ret = kvm_set_pv_features(cs);
if (ret) {
return ret;
}
once = 1;
}
if (level >= KVM_PUT_FULL_STATE) {
/*
* only KVM_PUT_FULL_STATE is required, kvm kernel will clear
@ -875,6 +919,18 @@ static bool kvm_feature_supported(CPUState *cs, enum loongarch_features feature)
ret = kvm_vm_ioctl(kvm_state, KVM_HAS_DEVICE_ATTR, &attr);
return (ret == 0);
case LOONGARCH_FEATURE_PV_IPI:
attr.group = KVM_LOONGARCH_VM_FEAT_CTRL;
attr.attr = KVM_LOONGARCH_VM_FEAT_PV_IPI;
ret = kvm_vm_ioctl(kvm_state, KVM_HAS_DEVICE_ATTR, &attr);
return (ret == 0);
case LOONGARCH_FEATURE_STEALTIME:
attr.group = KVM_LOONGARCH_VM_FEAT_CTRL;
attr.attr = KVM_LOONGARCH_VM_FEAT_PV_STEALTIME;
ret = kvm_vm_ioctl(kvm_state, KVM_HAS_DEVICE_ATTR, &attr);
return (ret == 0);
default:
return false;
}
@ -973,6 +1029,52 @@ static int kvm_cpu_check_pmu(CPUState *cs, Error **errp)
return 0;
}
static int kvm_cpu_check_pv_features(CPUState *cs, Error **errp)
{
MachineState *ms = MACHINE(qdev_get_machine());
LoongArchCPU *cpu = LOONGARCH_CPU(cs);
CPULoongArchState *env = cpu_env(cs);
bool kvm_supported;
kvm_supported = kvm_feature_supported(cs, LOONGARCH_FEATURE_PV_IPI);
if (cpu->kvm_pv_ipi == ON_OFF_AUTO_ON) {
if (!kvm_supported) {
error_setg(errp, "'pv_ipi' feature not supported by KVM host");
return -ENOTSUP;
}
} else if (cpu->kvm_pv_ipi != ON_OFF_AUTO_AUTO) {
kvm_supported = false;
}
if (kvm_supported) {
env->pv_features |= BIT(KVM_FEATURE_IPI);
}
kvm_supported = kvm_feature_supported(cs, LOONGARCH_FEATURE_STEALTIME);
if (cpu->kvm_steal_time == ON_OFF_AUTO_ON) {
if (!kvm_supported) {
error_setg(errp, "'kvm stealtime' feature not supported by KVM host");
return -ENOTSUP;
}
} else if (cpu->kvm_steal_time != ON_OFF_AUTO_AUTO) {
kvm_supported = false;
}
if (kvm_supported) {
env->pv_features |= BIT(KVM_FEATURE_STEAL_TIME);
}
if (object_dynamic_cast(OBJECT(ms), TYPE_LOONGARCH_VIRT_MACHINE)) {
LoongArchVirtMachineState *lvms = LOONGARCH_VIRT_MACHINE(ms);
if (virt_is_veiointc_enabled(lvms)) {
env->pv_features |= BIT(KVM_FEATURE_VIRT_EXTIOI);
}
}
return 0;
}
int kvm_arch_init_vcpu(CPUState *cs)
{
uint64_t val;
@ -1006,9 +1108,89 @@ int kvm_arch_init_vcpu(CPUState *cs)
error_report_err(local_err);
}
ret = kvm_cpu_check_pv_features(cs, &local_err);
if (ret < 0) {
error_report_err(local_err);
}
return ret;
}
static bool loongarch_get_lbt(Object *obj, Error **errp)
{
return LOONGARCH_CPU(obj)->lbt != ON_OFF_AUTO_OFF;
}
static void loongarch_set_lbt(Object *obj, bool value, Error **errp)
{
LoongArchCPU *cpu = LOONGARCH_CPU(obj);
cpu->lbt = value ? ON_OFF_AUTO_ON : ON_OFF_AUTO_OFF;
}
static bool loongarch_get_pmu(Object *obj, Error **errp)
{
return LOONGARCH_CPU(obj)->pmu != ON_OFF_AUTO_OFF;
}
static void loongarch_set_pmu(Object *obj, bool value, Error **errp)
{
LoongArchCPU *cpu = LOONGARCH_CPU(obj);
cpu->pmu = value ? ON_OFF_AUTO_ON : ON_OFF_AUTO_OFF;
}
static bool kvm_pv_ipi_get(Object *obj, Error **errp)
{
return LOONGARCH_CPU(obj)->kvm_pv_ipi != ON_OFF_AUTO_OFF;
}
static void kvm_pv_ipi_set(Object *obj, bool value, Error **errp)
{
LoongArchCPU *cpu = LOONGARCH_CPU(obj);
cpu->kvm_pv_ipi = value ? ON_OFF_AUTO_ON : ON_OFF_AUTO_OFF;
}
static bool kvm_steal_time_get(Object *obj, Error **errp)
{
return LOONGARCH_CPU(obj)->kvm_steal_time != ON_OFF_AUTO_OFF;
}
static void kvm_steal_time_set(Object *obj, bool value, Error **errp)
{
LoongArchCPU *cpu = LOONGARCH_CPU(obj);
cpu->kvm_steal_time = value ? ON_OFF_AUTO_ON : ON_OFF_AUTO_OFF;
}
void kvm_loongarch_cpu_post_init(LoongArchCPU *cpu)
{
cpu->lbt = ON_OFF_AUTO_AUTO;
object_property_add_bool(OBJECT(cpu), "lbt", loongarch_get_lbt,
loongarch_set_lbt);
object_property_set_description(OBJECT(cpu), "lbt",
"Set off to disable Binary Tranlation.");
cpu->pmu = ON_OFF_AUTO_AUTO;
object_property_add_bool(OBJECT(cpu), "pmu", loongarch_get_pmu,
loongarch_set_pmu);
object_property_set_description(OBJECT(cpu), "pmu",
"Set off to disable performance monitor unit.");
cpu->kvm_pv_ipi = ON_OFF_AUTO_AUTO;
object_property_add_bool(OBJECT(cpu), "kvm-pv-ipi", kvm_pv_ipi_get,
kvm_pv_ipi_set);
object_property_set_description(OBJECT(cpu), "kvm-pv-ipi",
"Set off to disable KVM paravirt IPI.");
cpu->kvm_steal_time = ON_OFF_AUTO_AUTO;
object_property_add_bool(OBJECT(cpu), "kvm-steal-time", kvm_steal_time_get,
kvm_steal_time_set);
object_property_set_description(OBJECT(cpu), "kvm-steal-time",
"Set off to disable KVM steal time.");
}
int kvm_arch_destroy_vcpu(CPUState *cs)
{
return 0;

View File

@ -40,7 +40,7 @@ CpuDefinitionInfoList *qmp_query_cpu_definitions(Error **errp)
}
static const char *cpu_model_advertised_features[] = {
"lsx", "lasx", "lbt", "pmu", NULL
"lsx", "lasx", "lbt", "pmu", "kvm-pv-ipi", "kvm-steal-time", NULL
};
CpuModelExpansionInfo *qmp_query_cpu_model_expansion(CpuModelExpansionType type,