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:
commit
50d38b8921
@ -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)
|
||||
{
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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 */
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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,
|
||||
|
Loading…
x
Reference in New Issue
Block a user