Re: [PATCH v5 00/19] Reconstruct loongson ipi driver
在2024年7月18日七月 下午9:32,Philippe Mathieu-Daudé写道: > Since v4: > - Fix build failure due to rebase (Song) > - Loongarch -> LoongArch (Song) > - Added Song's tags > > Since v3: > - Use DEFINE_TYPES() macro (unreviewed patch #1) > - Update MAINTAINERS > - Added Bibo's tags For the whole series: Reviewed-by: Jiaxun Yang Tested-by: Jiaxun Yang Thanks! Tested on MIPS loongson3-virt with 2, 4 CPUs, all working fine. I'll get this covered by CI later. - Jiaxun > > Thanks, > > Phil. > > Bibo Mao (16): > hw/intc/loongson_ipi: Access memory in little endian > hw/intc/loongson_ipi: Rename LoongsonIPI -> LoongsonIPIState > hw/intc/loongson_ipi: Extract loongson_ipi_common_finalize() > hw/intc/loongson_ipi: Extract loongson_ipi_common_realize() > hw/intc/loongson_ipi: Add TYPE_LOONGSON_IPI_COMMON stub > hw/intc/loongson_ipi: Move common definitions to loongson_ipi_common.h > hw/intc/loongson_ipi: Move IPICore::mmio_mem to LoongsonIPIState > hw/intc/loongson_ipi: Move IPICore structure to loongson_ipi_common.h > hw/intc/loongson_ipi: Pass LoongsonIPICommonState to send_ipi_data() > hw/intc/loongson_ipi: Add LoongsonIPICommonClass::get_iocsr_as handler > hw/intc/loongson_ipi: Add LoongsonIPICommonClass::cpu_by_arch_id > handler > hw/intc/loongson_ipi: Expose loongson_ipi_core_read/write helpers > hw/intc/loongson_ipi: Move common code to loongson_ipi_common.c > hw/intc/loongarch_ipi: Add loongarch IPI support > hw/loongarch/virt: Replace Loongson IPI with LoongArch IPI > hw/intc/loongson_ipi: Restrict to MIPS > > Philippe Mathieu-Daudé (3): > hw/intc/loongson_ipi: Declare QOM types using DEFINE_TYPES() macro > hw/intc/loongson_ipi: Remove unused headers > docs: Correct Loongarch -> LoongArch > > MAINTAINERS | 6 +- > docs/about/emulation.rst | 2 +- > include/hw/intc/loongarch_ipi.h | 25 ++ > include/hw/intc/loongson_ipi.h| 50 +--- > include/hw/intc/loongson_ipi_common.h | 72 ++ > include/hw/loongarch/virt.h | 1 - > hw/intc/loongarch_ipi.c | 68 + > hw/intc/loongson_ipi.c| 355 +++--- > hw/intc/loongson_ipi_common.c | 344 + > hw/loongarch/virt.c | 4 +- > hw/rtc/ls7a_rtc.c | 2 +- > hw/intc/Kconfig | 8 + > hw/intc/meson.build | 2 + > hw/loongarch/Kconfig | 2 +- > 14 files changed, 570 insertions(+), 371 deletions(-) > create mode 100644 include/hw/intc/loongarch_ipi.h > create mode 100644 include/hw/intc/loongson_ipi_common.h > create mode 100644 hw/intc/loongarch_ipi.c > create mode 100644 hw/intc/loongson_ipi_common.c > > -- > 2.41.0 -- - Jiaxun
Re: [PATCH v2 0/4] Reconstruct loongson ipi driver
在2024年7月17日七月 下午5:22,maobibo写道: > On 2024/7/16 下午2:40, Philippe Mathieu-Daudé wrote: >> On 16/7/24 03:29, maobibo wrote: >>> >>> >>> On 2024/7/16 上午9:04, maobibo wrote: On 2024/7/15 下午11:17, Philippe Mathieu-Daudé wrote: > On 4/7/24 05:37, Bibo Mao wrote: >> Now loongson ipi and loongarch ipi share the same code with different >> macro, loongson ipi has its separate function such mmio region, >> loongarch ipi has other requirement such as irqchip in kernel. >> >> Interrupt irqchip has strong relationship with architecture, since >> it sends irq to vcpu and interfaces to get irqchip register is also >> architecture specific. >> >> Here like other architectures, base class TYPE_LOONGSON_IPI_COMMON >> is added, it comes from loongson ipi mostly. And it defined four >> abstract >> interfaces which can be used for MIPS 3A4000 and Loongarch 3A5000 >> machine, >> also can be used for 3A5000 irqchip in kernel mode soon. >> >> Also Loongarch ipi and loongson ipi device are added here, it inherits >> from base class TYPE_LOONGSON_IPI_COMMON. Loongarch ipi is tested, >> loongson ipi device only passes to compile and make check, it is not >> tested. >> >> Bibo Mao (4): >> hw/intc/loongson_ipi_common: Add loongson ipi common class >> hw/intc/loongarch_ipi: Add loongarch ipi support >> hw/loongarch/virt: Replace loongson ipi with loongarch ipi >> hw/intc/loongson_ipi: reconstruct driver inherit from common class > > I'll try to respin a clearer v3. I am ok with it since it solve the problem, and it is suitable for 9.1 release. Only that in the long time we hope that intc emulation driver has common base class + tcg/kvm driver, similar with other architecture. >>> Sorry for the confusion, I had thought it was another topic. >>> >>> Thanks for pointing out the problem and welcome the v3 version. >> >> Please do not post v3, let me post it. > Hi Philippe, > > QEMU 9.1 is coming to soft frozen stage, do you have enough time working > on it? Is it ok to use bugfix patch for 9.1 release version? Bug fix is always qualified between soft freeze and release. I tested the series for MIPS yesterday and can confirm it do work. Will give my tags on v3. Thanks > https://lore.kernel.org/all/20240627125819.62779-2-phi...@linaro.org/ > > After 9.1 is released, there will be enough time for patch v3. > > Regards > Bibo, Mao -- - Jiaxun
Re: [PATCH v2 0/4] Reconstruct loongson ipi driver
在2024年7月9日七月 下午8:04,maobibo写道: > Hi Philippe/Jiaxun, > > Could you do me a favor giving a review about this patch? Hi Bibo, I’m currently traveling, will test and review next week. I’m not really convinced to give a R-b but I’m fine with a T-b. Thanks > > Regards > Bibo Mao > > On 2024/7/4 上午11:37, Bibo Mao wrote: >> Now loongson ipi and loongarch ipi share the same code with different >> macro, loongson ipi has its separate function such mmio region, >> loongarch ipi has other requirement such as irqchip in kernel. >> >> Interrupt irqchip has strong relationship with architecture, since >> it sends irq to vcpu and interfaces to get irqchip register is also >> architecture specific. >> >> Here like other architectures, base class TYPE_LOONGSON_IPI_COMMON >> is added, it comes from loongson ipi mostly. And it defined four abstract >> interfaces which can be used for MIPS 3A4000 and Loongarch 3A5000 machine, >> also can be used for 3A5000 irqchip in kernel mode soon. >> >> Also Loongarch ipi and loongson ipi device are added here, it inherits >> from base class TYPE_LOONGSON_IPI_COMMON. Loongarch ipi is tested, >> loongson ipi device only passes to compile and make check, it is not >> tested. >> >> Bibo Mao (4): >>hw/intc/loongson_ipi_common: Add loongson ipi common class >>hw/intc/loongarch_ipi: Add loongarch ipi support >>hw/loongarch/virt: Replace loongson ipi with loongarch ipi >>hw/intc/loongson_ipi: reconstruct driver inherit from common class >> >> hw/intc/Kconfig | 3 + >> hw/intc/loongarch_ipi.c | 80 ++ >> hw/intc/loongson_ipi.c| 330 ++--- >> hw/intc/loongson_ipi_common.c | 394 ++ >> hw/intc/meson.build | 3 +- >> hw/loongarch/Kconfig | 2 +- >> hw/loongarch/virt.c | 4 +- >> include/hw/intc/loongarch_ipi.h | 33 +++ >> include/hw/intc/loongson_ipi.h| 54 ++-- >> include/hw/intc/loongson_ipi_common.h | 77 + >> include/hw/loongarch/virt.h | 1 - >> 11 files changed, 632 insertions(+), 349 deletions(-) >> create mode 100644 hw/intc/loongarch_ipi.c >> create mode 100644 hw/intc/loongson_ipi_common.c >> create mode 100644 include/hw/intc/loongarch_ipi.h >> create mode 100644 include/hw/intc/loongson_ipi_common.h >> >> >> base-commit: 6746482d12da3b6e4d3cdf06481a0027a797f719 >> -- - Jiaxun
Re: [RFC v3 1/2] target/loongarch: Add loongson binary translation feature
在2024年7月3日七月 下午6:10,maobibo写道: [...] >>> >>> Huacai, would you agree with me? >> For me the important thing is consistency, all vm-features or all >> vcpu-features are both accepted. > To understand features immediately is difficult job for me. There is > supported features/used features usages etc, overall feature detection > should be VM relative by my knowledge. > > Maybe after host machine type and migration feature detection and > checking is finished, there will be further upstanding -:( Do you agree with the scratch_vcpu approach? This seems to be the only straight forward way to make some progress here. Thanks -- - Jiaxun
Re: [RFC v3 1/2] target/loongarch: Add loongson binary translation feature
在2024年7月1日七月 下午2:57,Jiaxun Yang写道: > 在2024年5月30日五月 上午7:49,Bibo Mao写道: >> Loongson Binary Translation (LBT) is used to accelerate binary >> translation, which contains 4 scratch registers (scr0 to scr3), x86/ARM >> eflags (eflags) and x87 fpu stack pointer (ftop). >> >> Now LBT feature is added in kvm mode, not supported in TCG mode since >> it is not emulated. Feature variable lbt is added with OnOffAuto type, >> If lbt feature is not supported with KVM host, it reports error if there >> is lbt=on command line. >> >> If there is no any command line about lbt parameter, it checks whether >> KVM host supports lbt feature and set the corresponding value in cpucfg. >> >> Signed-off-by: Bibo Mao > Hi Bibo, > > I was going across recent LoongArch changes and this comes into my attention: > >> --- >> target/loongarch/cpu.c| 53 +++ >> target/loongarch/cpu.h| 6 +++ >> target/loongarch/kvm/kvm.c| 26 + >> target/loongarch/kvm/kvm_loongarch.h | 16 >> target/loongarch/loongarch-qmp-cmds.c | 2 +- >> 5 files changed, 102 insertions(+), 1 deletion(-) >> >> diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c >> index b5c1ec94af..14265b6667 100644 >> --- a/target/loongarch/cpu.c >> +++ b/target/loongarch/cpu.c >> @@ -571,6 +571,30 @@ static void loongarch_cpu_disas_set_info(CPUState >> *s, disassemble_info *info) >> info->print_insn = print_insn_loongarch; >> } >> >> +static void loongarch_cpu_check_lbt(CPUState *cs, Error **errp) >> +{ >> +CPULoongArchState *env = cpu_env(cs); >> +LoongArchCPU *cpu = LOONGARCH_CPU(cs); >> +bool kvm_supported; >> + >> +kvm_supported = kvm_feature_supported(cs, LOONGARCH_FEATURE_LBT); > > IMHO if there is no global states that should be saved/restored VM wise, > this should be handled at per CPU level, preferably with CPUCFG flags hint. > > We should minimize non-privilege KVM feature bits to prevent hindering > asymmetry ISA system. + Huacai for further discussion Hi Bibo, Huacai, I investigated the topic further and went through the thread on kernel side. I think Huacai and me are all on the same page that we should unify the interface for per-CPU level feature probing and setting interface. Huacai purposed converting all features to VM feature but I still believe CPUCFG is the best interface. To probe LBT before actual vcpu creation, we can borrow the approach used by other architectures (kvm_arm_create_scratch_host_vcpu() & kvm_riscv_create_scratch_vcpu()). Kernel will reject setting unknown CPUCFG bits with -EINVAL, so to probe LBT we just need to perform KVM_SET_REGS to scratch vcpu with LBT set to see if it's valid for kernel. There is no need for any other probing interface. I do think scratch CPU interface is also necessary if we are going to implement cpu = host. Huacai, would you agree with me? Thanks - Jiaxun > > Thanks > - Jiaxun > > -- > - Jiaxun -- - Jiaxun
Re: [PATCH 1/3] hw/intc/loongson_ipi_common: Add loongson ipi common class
在2024年7月3日七月 下午2:40,maobibo写道: [...] Hi Bobo, > > MMIO is loongson ipi specific, it is not necessary to put into common > function. Functions loongson_ipi_core_readl/loongson_ipi_core_writel can > be exported in header file include/hw/intc/loongson_ipi_common.h, or get > MemoryRegionOps of first memoryregion of loongson_ipi instance. > > There is pseudo code: Thanks for your demonstration. I'm still not quite convinced it's worthy to split but I'm not going to block you if we don't have other oppositions. Do you mind to finish conversion of loongson_ipi as well? Since you are drafting the design. > > static void loongson_ipi_realize(DeviceState *dev, Error **errp) > { > LoongarchIPIState *s = LOONGARCH_IPI(dev); > LoongarchIPIClass *lic = LOONGARCH_IPI_GET_CLASS(s); > Error *local_err = NULL; > > lic->parent_realize(dev, _err); > if (local_err) { > error_propagate(errp, local_err); > return; > } > > > *do mmio specific implematation in loongson ipi itself* > } > > static void loongson_ipi_class_init(ObjectClass *klass, void *data) > { > DeviceClass *dc = DEVICE_CLASS(klass); > LoongsonIPICommonClass *licc = LOONGSON_IPI_COMMON_CLASS(klass); > LoongarchIPIClass *lic = LOONGARCH_IPI_CLASS(klass); > > device_class_set_parent_realize(dc, loongson_ipi_realize, > >parent_realize); > licc->get_iocsr_as = get_iocsr_as; > } > >> >> If current implementation is hindering your future plan can you elaborate so >> we >> can work on a resolution. >> >> I'm happy to help with devlopment and testing. >> >>> 3. Interace cpu_by_arch_id is added, by default generic function >>> cpu_by_arch_id() is used to search vcpu from physical cpuid, it is >>> generic searching method. Different machine may define another search >>> method such binary searching method. >> >> If you are going to implement some faster searching algorithm why don't we >> make it generic for all architectures? > It depends on the detailed physical id layout, is physical id is growing > up with logic cpu id or irrelative with logic cpu id? Different > architecture has different logic definition about physical id. For x86' APIC id and RISC-V's hardid they are all somehow linear. I'd suggest you to post a RFC patch regarding better algorithm. Thanks - Jiaxun > > Regards > Bibo Mao > >> >> Thanks >> - Jiaxun >> >>> >>> Signed-off-by: Bibo Mao >>> --- >>> hw/intc/loongson_ipi_common.c | 394 ++ >>> include/hw/intc/loongson_ipi_common.h | 71 + >>> 2 files changed, 465 insertions(+) >>> create mode 100644 hw/intc/loongson_ipi_common.c >>> create mode 100644 include/hw/intc/loongson_ipi_common.h >>> >>> diff --git a/hw/intc/loongson_ipi_common.c >>> b/hw/intc/loongson_ipi_common.c >>> new file mode 100644 >>> index 00..f462f24f32 >>> --- /dev/null >>> +++ b/hw/intc/loongson_ipi_common.c >>> @@ -0,0 +1,394 @@ >>> +/* SPDX-License-Identifier: GPL-2.0-or-later */ >>> +/* >>> + * Loongson ipi interrupt support >>> + * >>> + * Copyright (C) 2021 Loongson Technology Corporation Limited >>> + */ >>> + >>> +#include "qemu/osdep.h" >>> +#include "hw/boards.h" >>> +#include "hw/sysbus.h" >>> +#include "hw/intc/loongson_ipi_common.h" >>> +#include "hw/irq.h" >>> +#include "hw/qdev-properties.h" >>> +#include "qapi/error.h" >>> +#include "qemu/log.h" >>> +#include "exec/address-spaces.h" >>> +#include "exec/memory.h" >>> +#include "migration/vmstate.h" >>> +#include "trace.h" >>> + >>> +static MemTxResult loongson_ipi_core_readl(void *opaque, hwaddr addr, >>> + uint64_t *data, >>> + unsigned size, MemTxAttrs >>> attrs) >>> +{ >>> +IPICore *s = opaque; >>> +uint64_t ret = 0; >>> +int index = 0; >>> + >>> +addr &= 0xff; >>> +switch (addr) { >>> +case CORE_STATUS_OFF: >>> +ret = s->status; >>> +break; >>> +case CORE_EN_OFF: >>> +ret = s->en; >>> +break; >>> +case CORE_SET_OFF: >>> +ret = 0; >>> +break; >>> +case CORE_CLEAR_OFF: >>> +ret = 0; >>> +break; >>> +case CORE_BUF_20 ... CORE_BUF_38 + 4: >>> +index = (addr - CORE_BUF_20) >> 2; >>> +ret = s->buf[index]; >>> +break; >>> +default: >>> +qemu_log_mask(LOG_UNIMP, "invalid read: %x", (uint32_t)addr); >>> +break; >>> +} >>> + >>> +trace_loongson_ipi_read(size, (uint64_t)addr, ret); >>> +*data = ret; >>> +return MEMTX_OK; >>> +} >>> + >>> +static MemTxResult loongson_ipi_iocsr_readl(void *opaque, hwaddr addr, >>> +uint64_t *data, >>> +unsigned size, MemTxAttrs >>> attrs) >>> +{ >>> +LoongsonIPICommonState *ipi = opaque; >>> +IPICore *s; >>> + >>> +if (attrs.requester_id >= ipi->num_cpu) { >>> +return
Re: [PATCH 1/3] hw/intc/loongson_ipi_common: Add loongson ipi common class
在2024年7月3日七月 上午10:12,Bibo Mao写道: > Loongson ipi common class and instance is created here, it comes > from file loongson_ipi mostly. For the new added loongson ipi > common class, there is four interfaces defined here: > 1. Interfaces pre_save/post_load are used for future kvm child class > 2. Interface get_iocsr_as can be used for different architectures, > now MIPS 3A4000 and LoongArch 3A5000 machine use this ip, can inherit > this common class. Please consider MMIO implementation here as well. Can you demonstrate how would you share implementation with MMIO based IPI? In current implementation we share memory R/W callbacks but in your implementation that's nolonger possible. If current implementation is hindering your future plan can you elaborate so we can work on a resolution. I'm happy to help with devlopment and testing. > 3. Interace cpu_by_arch_id is added, by default generic function > cpu_by_arch_id() is used to search vcpu from physical cpuid, it is > generic searching method. Different machine may define another search > method such binary searching method. If you are going to implement some faster searching algorithm why don't we make it generic for all architectures? Thanks - Jiaxun > > Signed-off-by: Bibo Mao > --- > hw/intc/loongson_ipi_common.c | 394 ++ > include/hw/intc/loongson_ipi_common.h | 71 + > 2 files changed, 465 insertions(+) > create mode 100644 hw/intc/loongson_ipi_common.c > create mode 100644 include/hw/intc/loongson_ipi_common.h > > diff --git a/hw/intc/loongson_ipi_common.c > b/hw/intc/loongson_ipi_common.c > new file mode 100644 > index 00..f462f24f32 > --- /dev/null > +++ b/hw/intc/loongson_ipi_common.c > @@ -0,0 +1,394 @@ > +/* SPDX-License-Identifier: GPL-2.0-or-later */ > +/* > + * Loongson ipi interrupt support > + * > + * Copyright (C) 2021 Loongson Technology Corporation Limited > + */ > + > +#include "qemu/osdep.h" > +#include "hw/boards.h" > +#include "hw/sysbus.h" > +#include "hw/intc/loongson_ipi_common.h" > +#include "hw/irq.h" > +#include "hw/qdev-properties.h" > +#include "qapi/error.h" > +#include "qemu/log.h" > +#include "exec/address-spaces.h" > +#include "exec/memory.h" > +#include "migration/vmstate.h" > +#include "trace.h" > + > +static MemTxResult loongson_ipi_core_readl(void *opaque, hwaddr addr, > + uint64_t *data, > + unsigned size, MemTxAttrs > attrs) > +{ > +IPICore *s = opaque; > +uint64_t ret = 0; > +int index = 0; > + > +addr &= 0xff; > +switch (addr) { > +case CORE_STATUS_OFF: > +ret = s->status; > +break; > +case CORE_EN_OFF: > +ret = s->en; > +break; > +case CORE_SET_OFF: > +ret = 0; > +break; > +case CORE_CLEAR_OFF: > +ret = 0; > +break; > +case CORE_BUF_20 ... CORE_BUF_38 + 4: > +index = (addr - CORE_BUF_20) >> 2; > +ret = s->buf[index]; > +break; > +default: > +qemu_log_mask(LOG_UNIMP, "invalid read: %x", (uint32_t)addr); > +break; > +} > + > +trace_loongson_ipi_read(size, (uint64_t)addr, ret); > +*data = ret; > +return MEMTX_OK; > +} > + > +static MemTxResult loongson_ipi_iocsr_readl(void *opaque, hwaddr addr, > +uint64_t *data, > +unsigned size, MemTxAttrs > attrs) > +{ > +LoongsonIPICommonState *ipi = opaque; > +IPICore *s; > + > +if (attrs.requester_id >= ipi->num_cpu) { > +return MEMTX_DECODE_ERROR; > +} > + > +s = >cpu[attrs.requester_id]; > +return loongson_ipi_core_readl(s, addr, data, size, attrs); > +} > + > +static MemTxResult send_ipi_data(LoongsonIPICommonState *ipi, CPUState > *cpu, > + uint64_t val, > + hwaddr addr, MemTxAttrs attrs) > +{ > +int i, mask = 0, data = 0; > +AddressSpace *iocsr_as; > +LoongsonIPICommonClass *licc = LOONGSON_IPI_COMMON_GET_CLASS(ipi); > + > +iocsr_as = NULL; > +if (licc->get_iocsr_as) { > +iocsr_as = licc->get_iocsr_as(cpu); > +} > + > +if (!iocsr_as) { > +return MEMTX_DECODE_ERROR; > +} > + > +/* > + * bit 27-30 is mask for byte writing, > + * if the mask is 0, we need not to do anything. > + */ > +if ((val >> 27) & 0xf) { > +data = address_space_ldl_le(iocsr_as, addr, attrs, NULL); > +for (i = 0; i < 4; i++) { > +/* get mask for byte writing */ > +if (val & (0x1 << (27 + i))) { > +mask |= 0xff << (i * 8); > +} > +} > +} > + > +data &= mask; > +data |= (val >> 32) & ~mask; > +address_space_stl_le(iocsr_as, addr, data, attrs, NULL); > + > +return MEMTX_OK; > +} > + > +static CPUState *get_cpu_by_arch_id(LoongsonIPICommonState *ipi, >
Re: [RFC v3 1/2] target/loongarch: Add loongson binary translation feature
在2024年7月1日七月 上午8:32,maobibo写道: [...] >>> >>> +static void loongarch_cpu_check_lbt(CPUState *cs, Error **errp) >>> +{ >>> +CPULoongArchState *env = cpu_env(cs); >>> +LoongArchCPU *cpu = LOONGARCH_CPU(cs); >>> +bool kvm_supported; >>> + >>> +kvm_supported = kvm_feature_supported(cs, LOONGARCH_FEATURE_LBT); >> >> IMHO if there is no global states that should be saved/restored VM wise, >> this should be handled at per CPU level, preferably with CPUCFG flags hint. >> >> We should minimize non-privilege KVM feature bits to prevent hindering >> asymmetry ISA system. > For "asymmetry ISA system", do you meaning some vcpus have LBT feature, > however some vcpus does have LBT features? That does not exists at all. Yes, we should always prepare for the future :-) >From Weiwu's presentations, I believe LASX asymmetry product is already on the roadmap. So for LBT it's also a possibility. Even if such product won't land in near future, we should still try our best to bound to vCPU creation, not to the system. > > It will be big disaster for such products, how does application use this? Affinity placement etc, there are many possibilities. On Arm side, there are already systems with Big.Little asymmetry CPU that some of the processor equipped 32 bit EL0 mode while others doesn't. They managed that well with affinity. See: arm64: Allow mismatched 32-bit EL0 support Thanks > > Regards > Bibo >> >> Thanks >> - Jiaxun >> -- - Jiaxun
Re: [PATCH v3 1/4] hw/intc: Remove loongarch_ipi.c
在2024年7月1日七月 上午8:22,maobibo写道: > On 2024/7/1 下午3:01, Jiaxun Yang wrote: >> >> >> 在2024年7月1日七月 上午7:44,maobibo写道: >>> Also this patch is problematic on LoongArch. >>> >>> The original patch is to search physical cpuid rather than logic cpuid. >>> >>> We want to make ipi module better and better, however now it comes back >>> to initial state at the beginning :( >> >> Isn't arch_id the "physical id" you want? "cs->cpu_index" is the logical ID >> for QEMU. >> >> arch_id is setup by arch code, like APIC ID for x86. >> >> I had come across the old ipi_getcpu implementation, and I'm sure we were >> looking at arch_id as well. > So, where is implementation code for function get_arch_id() looking for > vcpu with physical index? Hi Bibo, cpu_by_arch_id will be redirected to: ``` CPUState *cpu_by_arch_id(int64_t id) { CPUState *cpu; CPU_FOREACH(cpu) { CPUClass *cc = CPU_GET_CLASS(cpu); if (cc->get_arch_id(cpu) == id) { return cpu; } } return NULL; } ``` It iterates over all vcpus and return CPUStates with corresponding arch_id. Whereas, for LoongArch's get_arch_id implementation: ``` static int64_t loongarch_cpu_get_arch_id(CPUState *cs) { LoongArchCPU *cpu = LOONGARCH_CPU(cs); return cpu->phy_id; } ``` I believe it matches our intension here. Thanks > > Regards > Bibo Mao > >> >> Thanks >> - Jiaxun >>> >>> commit 03ca348b6b9038ce284916b36c19f700ac0ce7a6 >>> Author: Jiaxun Yang >>> Date: Wed Jun 5 10:04:27 2024 >>> >>> hw/intc/loongson_ipi: Replace ipi_getcpu with cpu_by_arch_id >>> >>> cpu_by_arch_id is doing the same thing as our ipi_getcpu logic. >>> >>> Signed-off-by: Jiaxun Yang >>> Reviewed-by: Song Gao >>> Message-ID: <20240605-loongson3-ipi-v3-4-ddd2c0e03...@flygoat.com> >>> Signed-off-by: Philippe Mathieu-Daudé >>> >>> >>> Regards >>> Bibo Mao >>> -- - Jiaxun
Re: [PATCH v3 1/4] hw/intc: Remove loongarch_ipi.c
在2024年7月1日七月 上午2:35,maobibo写道: [...] > > How about split loongson_ipi.c into > loongson_ipi_base.c/loongson_ipi_loongson.c/loongson_ipi_loongarch.c, > > File loongson_ipi_base.c contains the common code, loongson_ipi_xxx.c > contains arch specific. Soon we will submit irqchip in kernel function, > it will be much different for architectures, since ioctl command is > different for two architectures to save/restore ipi registers. MIPS's in kernel IPI IOCTL interface is non-existent so far, so if you are going to design something, I think it will be adopted by MIPS if necessary. There is still no need to create divergence in between. That being said, You are more than welcomed to draft a patch so we can discuss based on that. Thanks > > Regards > Bibo Mao -- - Jiaxun
Re: [PATCH v3 1/4] hw/intc: Remove loongarch_ipi.c
在2024年7月1日七月 上午7:44,maobibo写道: > Also this patch is problematic on LoongArch. > > The original patch is to search physical cpuid rather than logic cpuid. > > We want to make ipi module better and better, however now it comes back > to initial state at the beginning :( Isn't arch_id the "physical id" you want? "cs->cpu_index" is the logical ID for QEMU. arch_id is setup by arch code, like APIC ID for x86. I had come across the old ipi_getcpu implementation, and I'm sure we were looking at arch_id as well. Thanks - Jiaxun > > commit 03ca348b6b9038ce284916b36c19f700ac0ce7a6 > Author: Jiaxun Yang > Date: Wed Jun 5 10:04:27 2024 > > hw/intc/loongson_ipi: Replace ipi_getcpu with cpu_by_arch_id > > cpu_by_arch_id is doing the same thing as our ipi_getcpu logic. > > Signed-off-by: Jiaxun Yang > Reviewed-by: Song Gao > Message-ID: <20240605-loongson3-ipi-v3-4-ddd2c0e03...@flygoat.com> > Signed-off-by: Philippe Mathieu-Daudé > > > Regards > Bibo Mao > -- - Jiaxun
Re: [RFC v3 1/2] target/loongarch: Add loongson binary translation feature
在2024年5月30日五月 上午7:49,Bibo Mao写道: > Loongson Binary Translation (LBT) is used to accelerate binary > translation, which contains 4 scratch registers (scr0 to scr3), x86/ARM > eflags (eflags) and x87 fpu stack pointer (ftop). > > Now LBT feature is added in kvm mode, not supported in TCG mode since > it is not emulated. Feature variable lbt is added with OnOffAuto type, > If lbt feature is not supported with KVM host, it reports error if there > is lbt=on command line. > > If there is no any command line about lbt parameter, it checks whether > KVM host supports lbt feature and set the corresponding value in cpucfg. > > Signed-off-by: Bibo Mao Hi Bibo, I was going across recent LoongArch changes and this comes into my attention: > --- > target/loongarch/cpu.c| 53 +++ > target/loongarch/cpu.h| 6 +++ > target/loongarch/kvm/kvm.c| 26 + > target/loongarch/kvm/kvm_loongarch.h | 16 > target/loongarch/loongarch-qmp-cmds.c | 2 +- > 5 files changed, 102 insertions(+), 1 deletion(-) > > diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c > index b5c1ec94af..14265b6667 100644 > --- a/target/loongarch/cpu.c > +++ b/target/loongarch/cpu.c > @@ -571,6 +571,30 @@ static void loongarch_cpu_disas_set_info(CPUState > *s, disassemble_info *info) > info->print_insn = print_insn_loongarch; > } > > +static void loongarch_cpu_check_lbt(CPUState *cs, Error **errp) > +{ > +CPULoongArchState *env = cpu_env(cs); > +LoongArchCPU *cpu = LOONGARCH_CPU(cs); > +bool kvm_supported; > + > +kvm_supported = kvm_feature_supported(cs, LOONGARCH_FEATURE_LBT); IMHO if there is no global states that should be saved/restored VM wise, this should be handled at per CPU level, preferably with CPUCFG flags hint. We should minimize non-privilege KVM feature bits to prevent hindering asymmetry ISA system. Thanks - Jiaxun -- - Jiaxun
Re: [PATCH 0/2] hw/intc/loongson_ipi: Fix for LoongArch
在2024年6月27日六月 下午4:13,gaosong写道: > 在 2024/6/27 下午2:38, Philippe Mathieu-Daudé 写道: >> On 27/6/24 06:13, Jiaxun Yang wrote: >>> Signed-off-by: Jiaxun Yang >>> --- >>> Jiaxun Yang (2): >>> hw/intc/loongson_ipi: Gate MMIO regions creation with property >>> MAINTAINERS: Add myself as a reviewer of LoongArch virt machine >> >> Maybe s/has-mmio/use-mmio/? Otherwise series: >> Reviewed-by: Philippe Mathieu-Daudé >> > Hi, > > If we had done a simple test, we should have found the following > problem, but obviously we didn't . My bad, I’m currently traveling and sent that in rush. I do boot tested with CI and I trust CI can catch those issues. > > root@loongson-KVM:~/work/code/clean/github/qemu# . /kernel.sh > Unexpected error in object_property_find_err() at . /qom/object.c:1357. > qemu-system-loongarch64: Property 'loongson_ipi.unnamed-gpio-out[0]' not > found > . /kernel.sh: line 16: 117708 Aborted (core dumped) . > /build/qemu-system-loongarch64 -machine virt -m 8G -cpu la464 -smp 8 > -kernel ~/vmlinux -initrd ramdisk -serial stdio -monitor > telnet:localhost. 4418,server,nowait -net nic -net user -device > virtio-gpu-pci -device nec-usb-xhci,id=xhci,addr=0x1b -device > usb-tablet,id=tablet,bus=xhci.0, port=1 -device > usb-tablet,id=tablet,bus=xhci.0, -device usb-tablet,id=tablet,bus=xhci. > port=1 -device usb-kbd,id=keyboard,bus=xhci.0,port=2 -append > "root=/dev/ram rdinit=/sbin/init console=ttyS0,115200 > earlycon=uart,mmio. 0x1fe001e0" --nographic > > > So to minimize interactions with the MIPS architecture, I'll submit a > patch to restore loongarch_ipi for LoongArch. > > Thanks. > Song Gao -- - Jiaxun
[PATCH 0/2] hw/intc/loongson_ipi: Fix for LoongArch
Signed-off-by: Jiaxun Yang --- Jiaxun Yang (2): hw/intc/loongson_ipi: Gate MMIO regions creation with property MAINTAINERS: Add myself as a reviewer of LoongArch virt machine MAINTAINERS| 1 + hw/intc/loongson_ipi.c | 23 ++- hw/mips/loongson3_virt.c | 1 + include/hw/intc/loongson_ipi.h | 1 + 4 files changed, 17 insertions(+), 9 deletions(-) --- base-commit: 3f044554b94fc0756d5b3cdbf84501e0eea0e629 change-id: 20240627-ipi-fixes-13eaf1b8815a Best regards, -- Jiaxun Yang
[PATCH 1/2] hw/intc/loongson_ipi: Gate MMIO regions creation with property
Commit 49eba52a52fe ("hw/intc/loongson_ipi: Provide per core MMIO address spaces") implemented per core MMIO spaces for IPI registers. However on LoongArch system emulation with high core count it may exhaust QDEV_MAX_MMIO and trigger assertion. Given that MMIO region is unused for LoongArch system emulation (we do have it on hardware but kernel is in favor of IOCSR), gate MMIO regions creation with "has-mmio" property and only set if for loongson3-virt machine to avoid such limitation on LoongArch. Reported-by: maobibo Signed-off-by: Jiaxun Yang --- hw/intc/loongson_ipi.c | 23 ++- hw/mips/loongson3_virt.c | 1 + include/hw/intc/loongson_ipi.h | 1 + 3 files changed, 16 insertions(+), 9 deletions(-) diff --git a/hw/intc/loongson_ipi.c b/hw/intc/loongson_ipi.c index e6a7142480c6..6e92a503499a 100644 --- a/hw/intc/loongson_ipi.c +++ b/hw/intc/loongson_ipi.c @@ -305,15 +305,19 @@ static void loongson_ipi_realize(DeviceState *dev, Error **errp) return; } -for (i = 0; i < s->num_cpu; i++) { -s->cpu[i].ipi = s; -s->cpu[i].ipi_mmio_mem = g_new0(MemoryRegion, 1); -g_autofree char *name = g_strdup_printf("loongson_ipi_cpu%d_mmio", i); -memory_region_init_io(s->cpu[i].ipi_mmio_mem, OBJECT(dev), - _ipi_core_ops, >cpu[i], name, 0x48); -sysbus_init_mmio(sbd, s->cpu[i].ipi_mmio_mem); - -qdev_init_gpio_out(dev, >cpu[i].irq, 1); +if (s->has_mmio) { +for (i = 0; i < s->num_cpu; i++) { +s->cpu[i].ipi = s; +s->cpu[i].ipi_mmio_mem = g_new0(MemoryRegion, 1); +g_autofree char *name = +g_strdup_printf("loongson_ipi_cpu%d_mmio", i); +memory_region_init_io(s->cpu[i].ipi_mmio_mem, OBJECT(dev), + _ipi_core_ops, >cpu[i], + name, 0x48); +sysbus_init_mmio(sbd, s->cpu[i].ipi_mmio_mem); + +qdev_init_gpio_out(dev, >cpu[i].irq, 1); +} } } @@ -344,6 +348,7 @@ static const VMStateDescription vmstate_loongson_ipi = { static Property ipi_properties[] = { DEFINE_PROP_UINT32("num-cpu", LoongsonIPI, num_cpu, 1), +DEFINE_PROP_BOOL("has-mmio", LoongsonIPI, has_mmio, false), DEFINE_PROP_END_OF_LIST(), }; diff --git a/hw/mips/loongson3_virt.c b/hw/mips/loongson3_virt.c index 4ad36f0c5b64..a27b30ab318c 100644 --- a/hw/mips/loongson3_virt.c +++ b/hw/mips/loongson3_virt.c @@ -537,6 +537,7 @@ static void mips_loongson3_virt_init(MachineState *machine) if (!kvm_enabled()) { ipi = qdev_new(TYPE_LOONGSON_IPI); qdev_prop_set_uint32(ipi, "num-cpu", machine->smp.cpus); +qdev_prop_set_bit(ipi, "has-mmio", true); sysbus_realize_and_unref(SYS_BUS_DEVICE(ipi), _fatal); memory_region_add_subregion(iocsr, SMP_IPI_MAILBOX, sysbus_mmio_get_region(SYS_BUS_DEVICE(ipi), 0)); diff --git a/include/hw/intc/loongson_ipi.h b/include/hw/intc/loongson_ipi.h index 3f795edbf3cd..0e35674e7aaf 100644 --- a/include/hw/intc/loongson_ipi.h +++ b/include/hw/intc/loongson_ipi.h @@ -50,6 +50,7 @@ struct LoongsonIPI { MemoryRegion ipi_iocsr_mem; MemoryRegion ipi64_iocsr_mem; uint32_t num_cpu; +bool has_mmio; IPICore *cpu; }; -- 2.43.0
[PATCH 2/2] MAINTAINERS: Add myself as a reviewer of LoongArch virt machine
I would like to be informed on changes made to the LoongArch virt machine. I'm fairly familiar with Loongson-3 series platform hardware and doing firmwre (U-Boot) development as hobbyist on LoongArch virt platform, so I believe I can give positive review input to changes on that machine. Signed-off-by: Jiaxun Yang --- MAINTAINERS | 1 + 1 file changed, 1 insertion(+) diff --git a/MAINTAINERS b/MAINTAINERS index 19f67dc5d215..9a646ea58483 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1239,6 +1239,7 @@ LoongArch Machines -- Virt M: Song Gao +R: Jiaxun Yang S: Maintained F: docs/system/loongarch/virt.rst F: configs/targets/loongarch64-softmmu.mak -- 2.43.0
Re: [PATCH v3 1/4] hw/intc: Remove loongarch_ipi.c
在2024年6月26日六月 上午8:51,maobibo写道: > On 2024/6/26 下午3:40, Jiaxun Yang wrote: >> >> >> 在2024年6月26日六月 上午5:11,maobibo写道: >> [...] >>> It is different with existing implementation. >> What do you mean? Isn't this the actual hardware behaviour? >> >>> >>> With hw/intc/loongson_ipi.c, every vcpu has one ipi_mmio_mem, however on >>> loongarch ipi machine, there is no ipi_mmio_mem memory region. >>> So if machine has 256 vcpus, there will be 256 ipi_mmio_mem memory >>> regions. In function sysbus_init_mmio(), memory region can not exceed >>> QDEV_MAX_MMIO (32). With so many memory regions, it slows down memory >>> region search speed also. >> Ouch, never thought about that before, but I think we can control the >> registration of sysbus_mmio with a device property or even ifdef so LoongArch >> machine won't be affected. >> >> For MIPS loongson3-virt machine, our CPU number is capped, so that won't >> be a problem. >> >> I'm currently travelling without access to my PC, I'll prepare a patch >> as soon as I gain access again. Feel free to send a patch before me with >> this approach if you desperately want to fix it. >> >>> >>> void sysbus_init_mmio(SysBusDevice *dev, MemoryRegion *memory) >>> { >>> int n; >>> >>> assert(dev->num_mmio < QDEV_MAX_MMIO); >>> n = dev->num_mmio++; >>> dev->mmio[n].addr = -1; >>> dev->mmio[n].memory = memory; >>> } >>> >>> Can we revert this patch? We want to do production usable by real users >>> rather than show pure technology. >> >> I don't really get your point, we have at leat 4 real users requesting SMP >> support for loongson3-virt on gitlab issues, plus I need this to test >> MIPS/Loongson64 SMP kernel. >> >> If there is a problem with your use case, we can fix it. Why we do want to >> remove the functionality when there is an easy fix? > I do not think we have the ability to abstract hw and continuous > maintenance for two different architecture, including you and me. After all it’s the same IP block, I fail to see any reason to implement it separately. I perfectly understand that piece of hardware IP and I fix broken stuff in this driver time by time. I understand how does it work on LoongArch systems so I make my best effort to cover LoongArch part. There might be some edge cases that I missed, and I’ll be thankful for reports or assistance. The approach of shared drivers for LoongArch/MIPS works so well in kernel development, for QEMU I believe it’s also desirable. I’m not asking you or Loongson to maintain any MIPS/Loongson related features, I’ll take care of them if things go wrong. >lp > So I suggest that different files will be better for the present. After > one year or later, if we have further understanding about system, it is > ok to merge them into one file. If there is anything not clear to you on both MIPS and LoongArch side please let me know, I’m happy to help. We promote code reuse in QEMU to minimize maintenance burden. Thanks > > Regards > Bibo Mao >> >> It’s not only the features necessary for you that made QEMU an outstanding >> project; it’s everything coming together that completes it. >> >> Thanks >> - Jiaxun >>> >>> Regards >>> Bibo Mao >>> >>>> - >>>> -s->cpu = g_new0(IPICore, s->num_cpu); >>>> -if (s->cpu == NULL) { >>>> -error_setg(errp, "Memory allocation for ExtIOICore faile"); >>>> -return; >>>> -} >>>> - >>>> -for (i = 0; i < s->num_cpu; i++) { >>>> -qdev_init_gpio_out(dev, >cpu[i].irq, 1); >>>> -} >>>> -} >>>> - >>>> -static const VMStateDescription vmstate_ipi_core = { >>>> -.name = "ipi-single", >>>> -.version_id = 2, >>>> -.minimum_version_id = 2, >>>> -.fields = (const VMStateField[]) { >>>> -VMSTATE_UINT32(status, IPICore), >>>> -VMSTATE_UINT32(en, IPICore), >>>> -VMSTATE_UINT32(set, IPICore), >>>> -VMSTATE_UINT32(clear, IPICore), >>>> -VMSTATE_UINT32_ARRAY(buf, IPICore, IPI_MBX_NUM * 2), >>>> -VMSTATE_END_OF_LIST() >>>> -} >>>> -}; >>>> - >>>> -static const VMStateDescription vmstate_loongarch_ipi = { >>>> -.name = TYPE_LOONGAR
Re: [PATCH v3 1/4] hw/intc: Remove loongarch_ipi.c
在2024年6月26日六月 上午5:11,maobibo写道: [...] > It is different with existing implementation. What do you mean? Isn't this the actual hardware behaviour? > > With hw/intc/loongson_ipi.c, every vcpu has one ipi_mmio_mem, however on > loongarch ipi machine, there is no ipi_mmio_mem memory region. > So if machine has 256 vcpus, there will be 256 ipi_mmio_mem memory > regions. In function sysbus_init_mmio(), memory region can not exceed > QDEV_MAX_MMIO (32). With so many memory regions, it slows down memory > region search speed also. Ouch, never thought about that before, but I think we can control the registration of sysbus_mmio with a device property or even ifdef so LoongArch machine won't be affected. For MIPS loongson3-virt machine, our CPU number is capped, so that won't be a problem. I'm currently travelling without access to my PC, I'll prepare a patch as soon as I gain access again. Feel free to send a patch before me with this approach if you desperately want to fix it. > > void sysbus_init_mmio(SysBusDevice *dev, MemoryRegion *memory) > { > int n; > > assert(dev->num_mmio < QDEV_MAX_MMIO); > n = dev->num_mmio++; > dev->mmio[n].addr = -1; > dev->mmio[n].memory = memory; > } > > Can we revert this patch? We want to do production usable by real users > rather than show pure technology. I don't really get your point, we have at leat 4 real users requesting SMP support for loongson3-virt on gitlab issues, plus I need this to test MIPS/Loongson64 SMP kernel. If there is a problem with your use case, we can fix it. Why we do want to remove the functionality when there is an easy fix? It’s not only the features necessary for you that made QEMU an outstanding project; it’s everything coming together that completes it. Thanks - Jiaxun > > Regards > Bibo Mao > >> - >> -s->cpu = g_new0(IPICore, s->num_cpu); >> -if (s->cpu == NULL) { >> -error_setg(errp, "Memory allocation for ExtIOICore faile"); >> -return; >> -} >> - >> -for (i = 0; i < s->num_cpu; i++) { >> -qdev_init_gpio_out(dev, >cpu[i].irq, 1); >> -} >> -} >> - >> -static const VMStateDescription vmstate_ipi_core = { >> -.name = "ipi-single", >> -.version_id = 2, >> -.minimum_version_id = 2, >> -.fields = (const VMStateField[]) { >> -VMSTATE_UINT32(status, IPICore), >> -VMSTATE_UINT32(en, IPICore), >> -VMSTATE_UINT32(set, IPICore), >> -VMSTATE_UINT32(clear, IPICore), >> -VMSTATE_UINT32_ARRAY(buf, IPICore, IPI_MBX_NUM * 2), >> -VMSTATE_END_OF_LIST() >> -} >> -}; >> - >> -static const VMStateDescription vmstate_loongarch_ipi = { >> -.name = TYPE_LOONGARCH_IPI, >> -.version_id = 2, >> -.minimum_version_id = 2, >> -.fields = (const VMStateField[]) { >> -VMSTATE_STRUCT_VARRAY_POINTER_UINT32(cpu, LoongArchIPI, num_cpu, >> - vmstate_ipi_core, IPICore), >> -VMSTATE_END_OF_LIST() >> -} >> -}; >> - >> -static Property ipi_properties[] = { >> -DEFINE_PROP_UINT32("num-cpu", LoongArchIPI, num_cpu, 1), >> -DEFINE_PROP_END_OF_LIST(), >> -}; >> - >> -static void loongarch_ipi_class_init(ObjectClass *klass, void *data) >> -{ >> -DeviceClass *dc = DEVICE_CLASS(klass); >> - >> -dc->realize = loongarch_ipi_realize; >> -device_class_set_props(dc, ipi_properties); >> -dc->vmsd = _loongarch_ipi; >> -} >> - >> -static void loongarch_ipi_finalize(Object *obj) >> -{ >> -LoongArchIPI *s = LOONGARCH_IPI(obj); >> - >> -g_free(s->cpu); >> -} >> - >> -static const TypeInfo loongarch_ipi_info = { >> -.name = TYPE_LOONGARCH_IPI, >> -.parent= TYPE_SYS_BUS_DEVICE, >> -.instance_size = sizeof(LoongArchIPI), >> -.class_init= loongarch_ipi_class_init, >> -.instance_finalize = loongarch_ipi_finalize, >> -}; >> - >> -static void loongarch_ipi_register_types(void) >> -{ >> -type_register_static(_ipi_info); >> -} >> - >> -type_init(loongarch_ipi_register_types) >> -- - Jiaxun
[PATCH v2 2/3] hw/mips/loongson3_virt: Fix condition of IPI IOCSR connection
This fixes Coverity CID-1547264. Link: https://lore.kernel.org/qemu-devel/752417ad-ab72-4fed-8d1f-af41f15bc...@app.fastmail.com/ Signed-off-by: Jiaxun Yang --- hw/mips/loongson3_virt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/mips/loongson3_virt.c b/hw/mips/loongson3_virt.c index 69c1f2275838..24aa4dd04b18 100644 --- a/hw/mips/loongson3_virt.c +++ b/hw/mips/loongson3_virt.c @@ -574,7 +574,7 @@ static void mips_loongson3_virt_init(MachineState *machine) cpu_mips_clock_init(cpu); qemu_register_reset(main_cpu_reset, cpu); -if (ipi) { +if (!kvm_enabled()) { hwaddr base = ((hwaddr)node << 44) + virt_memmap[VIRT_IPI].base; base += core * 0x100; qdev_connect_gpio_out(ipi, i, cpu->env.irq[6]); -- 2.43.0
[PATCH v2 1/3] hw/mips/loongson3_virt: Store core_iocsr into LoongsonMachineState
Link: https://lore.kernel.org/qemu-devel/972034d6-23b3-415a-b401-b8bc1cc51...@linaro.org/ Suggested-by: Philippe Mathieu-Daudé Signed-off-by: Jiaxun Yang --- hw/mips/loongson3_virt.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/hw/mips/loongson3_virt.c b/hw/mips/loongson3_virt.c index 4ad36f0c5b64..69c1f2275838 100644 --- a/hw/mips/loongson3_virt.c +++ b/hw/mips/loongson3_virt.c @@ -97,6 +97,7 @@ struct LoongsonMachineState { MemoryRegion *pio_alias; MemoryRegion *mmio_alias; MemoryRegion *ecam_alias; +MemoryRegion *core_iocsr[LOONGSON_MAX_VCPUS]; }; typedef struct LoongsonMachineState LoongsonMachineState; @@ -493,6 +494,7 @@ static void mips_loongson3_virt_init(MachineState *machine) const char *kernel_filename = machine->kernel_filename; const char *initrd_filename = machine->initrd_filename; ram_addr_t ram_size = machine->ram_size; +LoongsonMachineState *s = LOONGSON_MACHINE(machine); MemoryRegion *address_space_mem = get_system_memory(); MemoryRegion *ram = g_new(MemoryRegion, 1); MemoryRegion *bios = g_new(MemoryRegion, 1); @@ -586,6 +588,7 @@ static void mips_loongson3_virt_init(MachineState *machine) iocsr, 0, UINT32_MAX); memory_region_add_subregion(_CPU(cpu)->env.iocsr.mr, 0, core_iocsr); +s->core_iocsr[i] = core_iocsr; } if (node > 0) { -- 2.43.0
[PATCH v2 3/3] linux-user/mips64: Use MIPS64R2-generic as default CPU type
5KEf is some what not standard compliant by having non-functional FCSR condition fields. This is causing glibc test failure in qemu-user. Use MIPS64R2-generic as our default type, which have maximum CPU features. Cc: sta...@vger.kernel.org Signed-off-by: Jiaxun Yang --- linux-user/mips64/target_elf.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linux-user/mips64/target_elf.h b/linux-user/mips64/target_elf.h index 5f2f2df29f7f..82bb7e8b1cbf 100644 --- a/linux-user/mips64/target_elf.h +++ b/linux-user/mips64/target_elf.h @@ -15,6 +15,6 @@ static inline const char *cpu_get_model(uint32_t eflags) if ((eflags & EF_MIPS_MACH) == EF_MIPS_MACH_5900) { return "R5900"; } -return "5KEf"; +return "MIPS64R2-generic"; } #endif -- 2.43.0
[PATCH v2 0/3] MIPS misc patches
Signed-off-by: Jiaxun Yang --- Changes in v2: - v1 was sent in mistake, b4 messed up with QEMU again - Link to v1: https://lore.kernel.org/r/20240621-loongson3-ipi-follow-v1-0-c6e73f2b2...@flygoat.com --- Jiaxun Yang (3): hw/mips/loongson3_virt: Store core_iocsr into LoongsonMachineState hw/mips/loongson3_virt: Fix condition of IPI IOCSR connection linux-user/mips64: Use MIPS64R2-generic as default CPU type hw/mips/loongson3_virt.c | 5 - linux-user/mips64/target_elf.h | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) --- base-commit: 02d9c38236cf8c9826e5c5be61780ccb4ae0 change-id: 20240621-loongson3-ipi-follow-1f4919621882 Best regards, -- Jiaxun Yang
[PATCH 2/3] hw/mips/loongson3_virt: Fix condition of IPI IOCSR connection
This fixes Coverity CID-1547264. Link: https://lore.kernel.org/qemu-devel/752417ad-ab72-4fed-8d1f-af41f15bc...@app.fastmail.com/ Signed-off-by: Jiaxun Yang --- hw/mips/loongson3_virt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/mips/loongson3_virt.c b/hw/mips/loongson3_virt.c index 528be84bf970..80e953512a85 100644 --- a/hw/mips/loongson3_virt.c +++ b/hw/mips/loongson3_virt.c @@ -575,7 +575,7 @@ static void mips_loongson3_virt_init(MachineState *machine) cpu_mips_clock_init(cpu); qemu_register_reset(main_cpu_reset, cpu); -if (ipi) { +if (!kvm_enabled()) { hwaddr base = ((hwaddr)node << 44) + virt_memmap[VIRT_IPI].base; base += core * 0x100; qdev_connect_gpio_out(ipi, i, cpu->env.irq[6]); -- 2.43.0
[PATCH 1/3] hw/mips/loongson3_virt: Store core_iocsr into LoongsonMachineState
Link: https://lore.kernel.org/qemu-devel/972034d6-23b3-415a-b401-b8bc1cc51...@linaro.org/ Suggested-by: Philippe Mathieu-Daudé Signed-off-by: Jiaxun Yang --- hw/mips/loongson3_virt.c | 4 1 file changed, 4 insertions(+) diff --git a/hw/mips/loongson3_virt.c b/hw/mips/loongson3_virt.c index 4ad36f0c5b64..528be84bf970 100644 --- a/hw/mips/loongson3_virt.c +++ b/hw/mips/loongson3_virt.c @@ -97,6 +97,7 @@ struct LoongsonMachineState { MemoryRegion *pio_alias; MemoryRegion *mmio_alias; MemoryRegion *ecam_alias; +MemoryRegion *core_iocsr[LOONGSON_MAX_VCPUS]; }; typedef struct LoongsonMachineState LoongsonMachineState; @@ -493,6 +494,8 @@ static void mips_loongson3_virt_init(MachineState *machine) const char *kernel_filename = machine->kernel_filename; const char *initrd_filename = machine->initrd_filename; ram_addr_t ram_size = machine->ram_size; +MachineClass *mc = MACHINE_GET_CLASS(machine); +LoongsonMachineState *s = LOONGSON_MACHINE(machine); MemoryRegion *address_space_mem = get_system_memory(); MemoryRegion *ram = g_new(MemoryRegion, 1); MemoryRegion *bios = g_new(MemoryRegion, 1); @@ -586,6 +589,7 @@ static void mips_loongson3_virt_init(MachineState *machine) iocsr, 0, UINT32_MAX); memory_region_add_subregion(_CPU(cpu)->env.iocsr.mr, 0, core_iocsr); +s->core_iocsr[i] = core_iocsr; } if (node > 0) { -- 2.43.0
[PATCH 3/3] linux-user/mips64: Use MIPS64R2-generic as default CPU type
5KEf is some what not standard compliant by having non-functional FCSR condition fields. This is causing glibc test failure in qemu-user. Use MIPS64R2-generic as our default type, which have maximum CPU features. Cc: sta...@vger.kernel.org Signed-off-by: Jiaxun Yang --- linux-user/mips64/target_elf.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linux-user/mips64/target_elf.h b/linux-user/mips64/target_elf.h index 5f2f2df29f7f..82bb7e8b1cbf 100644 --- a/linux-user/mips64/target_elf.h +++ b/linux-user/mips64/target_elf.h @@ -15,6 +15,6 @@ static inline const char *cpu_get_model(uint32_t eflags) if ((eflags & EF_MIPS_MACH) == EF_MIPS_MACH_5900) { return "R5900"; } -return "5KEf"; +return "MIPS64R2-generic"; } #endif -- 2.43.0
[PATCH 0/3] MIPS misc patches
Signed-off-by: Jiaxun Yang --- Jiaxun Yang (3): hw/mips/loongson3_virt: Store core_iocsr into LoongsonMachineState hw/mips/loongson3_virt: Fix condition of IPI IOCSR connection linux-user/mips64: Use MIPS64R2-generic as default CPU type hw/mips/loongson3_virt.c | 6 +- linux-user/mips64/target_elf.h | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) --- base-commit: 02d9c38236cf8c9826e5c5be61780ccb4ae0 change-id: 20240621-loongson3-ipi-follow-1f4919621882 Best regards, -- Jiaxun Yang
Re: [PULL 65/76] hw/mips/loongson3_virt: Wire up loongson_ipi device
在2024年6月20日六月 下午8:50,Philippe Mathieu-Daudé写道: [...] > Do you mind posting a patch fixing it? I'll prepare a series tomorrow with your comments on this patch before. Thanks - Jiaxun > >> +hwaddr base = ((hwaddr)node << 44) + virt_memmap[VIRT_IPI].base; >> +base += core * 0x100; >> +qdev_connect_gpio_out(ipi, i, cpu->env.irq[6]); >> +sysbus_mmio_map(SYS_BUS_DEVICE(ipi), i + 2, base); >> +} >> + >> +if (ase_lcsr_available(_CPU(cpu)->env)) { >> +MemoryRegion *core_iocsr = g_new(MemoryRegion, 1); >> +g_autofree char *name = g_strdup_printf("core%d_iocsr", i); >> +memory_region_init_alias(core_iocsr, OBJECT(cpu), name, >> + iocsr, 0, UINT32_MAX); >> +memory_region_add_subregion(_CPU(cpu)->env.iocsr.mr, >> +0, core_iocsr); >> +} >> + >> +if (node > 0) { >> continue; /* Only node-0 can be connected to LIOINTC */ >> } >> >> for (ip = 0; ip < 4 ; ip++) { >> -int pin = i * 4 + ip; >> +int pin = core * LOONGSON3_CORE_PER_NODE + ip; >> sysbus_connect_irq(SYS_BUS_DEVICE(liointc), >> pin, cpu->env.irq[ip + 2]); >> } -- - Jiaxun
Re: [PATCH 3/4] hw/m68k/virt: Add a pflash controller for BIOS firmware
在2024年6月18日六月 下午12:47,Philippe Mathieu-Daudé写道: > Hi Jiaxun, > > On 27/5/24 19:15, Jiaxun Yang wrote: >> Add a 8 MiB pflash controller for BIOS firmware, and boot >> from it if possible. >> >> Signed-off-by: Jiaxun Yang >> --- >> hw/m68k/Kconfig | 1 + >> hw/m68k/virt.c| 44 >> +++ >> include/standard-headers/asm-m68k/bootinfo-virt.h | 1 + >> 3 files changed, 46 insertions(+) >> >> diff --git a/hw/m68k/Kconfig b/hw/m68k/Kconfig >> index 4501da56ff6d..f233a5948f19 100644 >> --- a/hw/m68k/Kconfig >> +++ b/hw/m68k/Kconfig >> @@ -42,6 +42,7 @@ config M68K_VIRT >> select M68K_IRQC >> select FW_CFG_DMA >> select VIRT_CTRL >> +select PFLASH_CFI01 >> select GOLDFISH_PIC >> select GOLDFISH_TTY >> select GOLDFISH_RTC >> diff --git a/hw/m68k/virt.c b/hw/m68k/virt.c >> index 7590e6515ac3..a2eebc0f2243 100644 >> --- a/hw/m68k/virt.c >> +++ b/hw/m68k/virt.c >> @@ -8,6 +8,7 @@ >>*/ >> >> #include "qemu/osdep.h" >> +#include "qemu/datadir.h" >> #include "qemu/units.h" >> #include "qemu/guest-random.h" >> #include "sysemu/sysemu.h" >> @@ -28,6 +29,7 @@ >> #include "sysemu/runstate.h" >> #include "sysemu/reset.h" >> >> +#include "hw/block/flash.h" >> #include "hw/intc/m68k_irqc.h" >> #include "hw/misc/virt_ctrl.h" >> #include "hw/char/goldfish_tty.h" >> @@ -97,6 +99,10 @@ >> #define VIRT_XHCI_MMIO_BASE 0xff02/* MMIO: 0xff02 - 0xff023fff >> */ >> #define VIRT_XHCI_IRQ_BASE PIC_IRQ(1, 2) /* PIC: #1, IRQ: #2 */ >> >> +#define VIRT_PFLASH_MMIO_BASE 0xff80 /* MMIO: 0xff80 - >> 0x */ >> +#define VIRT_PFLASH_SIZE 0x80/* 8 MiB */ > > Do you need a real RW pflash or a ROM would be enough? U-Boot needs somewhere to store env vars :-( Probably a NVRAM would fit the purpose? Thanks > -- - Jiaxun
Re: [PATCH 0/3] S3 and S4 sleep for loongarch/virt & microvm
在2024年6月14日六月 上午6:17,maobibo写道: > On 2024/6/14 下午12:27, Jiaxun Yang wrote: >> >> >> 在2024年6月14日六月 上午4:32,maobibo写道: >>> It is interesting. >>> >>> How to wakeup VM if it sleeps in S3/S4, from emulated keyboard or >>> ethernet magic packet or qemu monitor command in background? >> >> Hi Bibo, >> >> The best way to wake the guest is system_wakeup command in monitor. > Ok, I see. > > It is useful and it can be used to test S3/S4 in TCG mode at least. > > Can we add feature capability, enabled in TCG mode, disabled in KVM mode > by default? If vm deploys in cloud, users in general help it is power-on > always. Well, I think we should align both machines as much as possible. It's also enabled for KVM on x86 piix4 and q35 machines. Thanks > > Regards > Bibo Mao -- - Jiaxun
Re: [PATCH 0/3] S3 and S4 sleep for loongarch/virt & microvm
在2024年6月14日六月 上午4:32,maobibo写道: > It is interesting. > > How to wakeup VM if it sleeps in S3/S4, from emulated keyboard or > ethernet magic packet or qemu monitor command in background? Hi Bibo, The best way to wake the guest is system_wakeup command in monitor. Thanks - Jiaxun > > Regards > Bibo Mao > > > On 2024/6/14 上午1:30, Jiaxun Yang wrote: >> Hi all, >> >> This series implemented S3 and S4 sleep for loongarch virt machine >> and microvm. >> >> For loongarch/virt a kernel patch is requried [1]. >> >> [1]: >> https://lore.kernel.org/loongarch/20240613-loongarch64-sleep-v1-0-a245232af...@flygoat.com/ >> >> Please review. >> Thanks >> >> Signed-off-by: Jiaxun Yang >> --- >> Jiaxun Yang (3): >>acpi/ged: Implement S3 and S4 sleep >>hw/loongarch/virt: Wire up S3 and S4 sleep >>hw/i386/microvm: Wire up S3 and S4 sleep >> >> hw/acpi/generic_event_device.c | 70 >> ++ >> hw/i386/acpi-microvm.c | 18 + >> hw/i386/microvm.c | 3 ++ >> hw/loongarch/acpi-build.c | 18 + >> hw/loongarch/virt.c| 3 ++ >> include/hw/acpi/generic_event_device.h | 12 +- >> 6 files changed, 115 insertions(+), 9 deletions(-) >> --- >> base-commit: f3e8cc47de2bc537d4991e883a85208e4e1c0f98 >> change-id: 20240613-loongarch64-sleep-37b2466b8d76 >> >> Best regards, >> -- - Jiaxun
[PATCH 1/3] acpi/ged: Implement S3 and S4 sleep
Implement S3 and S4 sleep with ACPI_GED_REG_SLEEP_CTL.SLP_TYP writes. Implement wakeup callback and WAK_STS register to inform guest about current states. All new functions are gated by "slp-typs" property, it is defaulted to S5 only and machines can opt-in for S3 and S4. Signed-off-by: Jiaxun Yang --- hw/acpi/generic_event_device.c | 70 ++ include/hw/acpi/generic_event_device.h | 12 +- 2 files changed, 73 insertions(+), 9 deletions(-) diff --git a/hw/acpi/generic_event_device.c b/hw/acpi/generic_event_device.c index 2d6e91b124e5..f1fc99c04011 100644 --- a/hw/acpi/generic_event_device.c +++ b/hw/acpi/generic_event_device.c @@ -11,6 +11,7 @@ #include "qemu/osdep.h" #include "qapi/error.h" +#include "qapi/qapi-events-run-state.h" #include "hw/acpi/acpi.h" #include "hw/acpi/generic_event_device.h" #include "hw/irq.h" @@ -186,24 +187,53 @@ static const MemoryRegionOps ged_evt_ops = { static uint64_t ged_regs_read(void *opaque, hwaddr addr, unsigned size) { +GEDState *ged_st = opaque; + +switch (addr) { +case ACPI_GED_REG_SLEEP_STS: +return ged_st->sleep_sts; +default: +break; +} + return 0; } static void ged_regs_write(void *opaque, hwaddr addr, uint64_t data, unsigned int size) { -bool slp_en; -int slp_typ; +GEDState *ged_st = opaque; +AcpiGedState *s = container_of(ged_st, AcpiGedState, ged_state); switch (addr) { case ACPI_GED_REG_SLEEP_CTL: -slp_typ = (data >> 2) & 0x07; -slp_en = (data >> 5) & 0x01; -if (slp_en && slp_typ == 5) { -qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN); +if (data & ACPI_GED_SLP_EN) { +switch (extract8(data, 2, 3)) { +case ACPI_GED_SLP_TYP_S3: +if (s->slp_typs_bitmap & (1 << ACPI_GED_SLP_TYP_S3)) { +qemu_system_suspend_request(); +} +break; +case ACPI_GED_SLP_TYP_S4: +if (s->slp_typs_bitmap & (1 << ACPI_GED_SLP_TYP_S4)) { +qapi_event_send_suspend_disk(); + qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN); +} +break; +case ACPI_GED_SLP_TYP_S5: +if (s->slp_typs_bitmap & (1 << ACPI_GED_SLP_TYP_S5)) { + qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN); +} +break; +default: +break; +} } return; case ACPI_GED_REG_SLEEP_STS: +if (data & ACPI_GED_WAK_STS) { +ged_st->sleep_sts &= ~ACPI_GED_WAK_STS; +} return; case ACPI_GED_REG_RESET: if (data == ACPI_GED_RESET_VALUE) { @@ -223,6 +253,14 @@ static const MemoryRegionOps ged_regs_ops = { }, }; +static void acpi_ged_notify_wakeup(Notifier *notifier, void *data) +{ +GEDState *ged_st = container_of(notifier, GEDState, wakeup); + +ged_st->sleep_sts |= ACPI_GED_WAK_STS; +} + + static void acpi_ged_device_plug_cb(HotplugHandler *hotplug_dev, DeviceState *dev, Error **errp) { @@ -305,6 +343,8 @@ static void acpi_ged_send_event(AcpiDeviceIf *adev, AcpiEventStatusBits ev) static Property acpi_ged_properties[] = { DEFINE_PROP_UINT32("ged-event", AcpiGedState, ged_event_bitmap, 0), +DEFINE_PROP_UINT32("slp-typs", AcpiGedState, slp_typs_bitmap, +(1 << ACPI_GED_SLP_TYP_S5)), DEFINE_PROP_END_OF_LIST(), }; @@ -320,10 +360,11 @@ static const VMStateDescription vmstate_memhp_state = { static const VMStateDescription vmstate_ged_state = { .name = "acpi-ged-state", -.version_id = 1, -.minimum_version_id = 1, +.version_id = 2, +.minimum_version_id = 2, .fields = (const VMStateField[]) { VMSTATE_UINT32(sel, GEDState), +VMSTATE_UINT8(sleep_sts, GEDState), VMSTATE_END_OF_LIST() } }; @@ -371,6 +412,18 @@ static const VMStateDescription vmstate_acpi_ged = { } }; +static void acpi_ged_realize(DeviceState *dev, Error **errp) +{ +AcpiGedState *s = ACPI_GED(dev); +GEDState *ged_st = >ged_state; + +if (s->slp_typs_bitmap & (1 << ACPI_GED_SLP_TYP_S3)) { +ged_st->wakeup.notify = acpi_ged_notify_wakeup; +qemu_register_wakeup_notifier(_st->wakeup); +qemu_register_wakeup_support(); +} +} + static void acpi_ged_initfn(Object *obj) { DeviceState *dev = DEVICE(obj); @@ -409,6 +462,7 @@ static void acpi_ged_class_init(ObjectClass *class, void *data) AcpiDeviceIfClass *adevc = ACPI_DEVICE_IF_CLASS(class); dc->desc =
[PATCH 2/3] hw/loongarch/virt: Wire up S3 and S4 sleep
Wire up S3 and S4 sleep by setting relevant slp-typs bits for GED and generate _S3 and _S4 methods in acpi table. Signed-off-by: Jiaxun Yang --- hw/loongarch/acpi-build.c | 18 ++ hw/loongarch/virt.c | 3 +++ 2 files changed, 21 insertions(+) diff --git a/hw/loongarch/acpi-build.c b/hw/loongarch/acpi-build.c index af45ce526d6e..2cb1696b579b 100644 --- a/hw/loongarch/acpi-build.c +++ b/hw/loongarch/acpi-build.c @@ -416,6 +416,24 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, MachineState *machine) acpi_dsdt_add_tpm(dsdt, lvms); #endif /* System State Package */ +scope = aml_scope("\\"); +pkg = aml_package(4); +aml_append(pkg, aml_int(ACPI_GED_SLP_TYP_S3)); +aml_append(pkg, aml_int(0)); /* ignored */ +aml_append(pkg, aml_int(0)); /* reserved */ +aml_append(pkg, aml_int(0)); /* reserved */ +aml_append(scope, aml_name_decl("_S3", pkg)); +aml_append(dsdt, scope); + +scope = aml_scope("\\"); +pkg = aml_package(4); +aml_append(pkg, aml_int(ACPI_GED_SLP_TYP_S4)); +aml_append(pkg, aml_int(0)); /* ignored */ +aml_append(pkg, aml_int(0)); /* reserved */ +aml_append(pkg, aml_int(0)); /* reserved */ +aml_append(scope, aml_name_decl("_S4", pkg)); +aml_append(dsdt, scope); + scope = aml_scope("\\"); pkg = aml_package(4); aml_append(pkg, aml_int(ACPI_GED_SLP_TYP_S5)); diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c index 66cef201abe0..a4b55f00a32b 100644 --- a/hw/loongarch/virt.c +++ b/hw/loongarch/virt.c @@ -615,6 +615,9 @@ static DeviceState *create_acpi_ged(DeviceState *pch_pic, } dev = qdev_new(TYPE_ACPI_GED); qdev_prop_set_uint32(dev, "ged-event", event); +qdev_prop_set_uint32(dev, "slp-typs", (1 << ACPI_GED_SLP_TYP_S3) | + (1 << ACPI_GED_SLP_TYP_S4) | + (1 << ACPI_GED_SLP_TYP_S5)); sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), _fatal); /* ged event */ -- 2.43.0
[PATCH 0/3] S3 and S4 sleep for loongarch/virt & microvm
Hi all, This series implemented S3 and S4 sleep for loongarch virt machine and microvm. For loongarch/virt a kernel patch is requried [1]. [1]: https://lore.kernel.org/loongarch/20240613-loongarch64-sleep-v1-0-a245232af...@flygoat.com/ Please review. Thanks Signed-off-by: Jiaxun Yang --- Jiaxun Yang (3): acpi/ged: Implement S3 and S4 sleep hw/loongarch/virt: Wire up S3 and S4 sleep hw/i386/microvm: Wire up S3 and S4 sleep hw/acpi/generic_event_device.c | 70 ++ hw/i386/acpi-microvm.c | 18 + hw/i386/microvm.c | 3 ++ hw/loongarch/acpi-build.c | 18 + hw/loongarch/virt.c| 3 ++ include/hw/acpi/generic_event_device.h | 12 +- 6 files changed, 115 insertions(+), 9 deletions(-) --- base-commit: f3e8cc47de2bc537d4991e883a85208e4e1c0f98 change-id: 20240613-loongarch64-sleep-37b2466b8d76 Best regards, -- Jiaxun Yang
[PATCH 3/3] hw/i386/microvm: Wire up S3 and S4 sleep
Wire up S3 and S4 sleep by setting relevant slp-typs bits for GED and generate _S3 and _S4 methods in acpi table. Signed-off-by: Jiaxun Yang --- hw/i386/acpi-microvm.c | 18 ++ hw/i386/microvm.c | 3 +++ 2 files changed, 21 insertions(+) diff --git a/hw/i386/acpi-microvm.c b/hw/i386/acpi-microvm.c index 279da6b4aa2f..7564de2b343b 100644 --- a/hw/i386/acpi-microvm.c +++ b/hw/i386/acpi-microvm.c @@ -129,6 +129,24 @@ build_dsdt_microvm(GArray *table_data, BIOSLinker *linker, aml_append(dsdt, sb_scope); /* ACPI 5.0: Table 7-209 System State Package */ +scope = aml_scope("\\"); +pkg = aml_package(4); +aml_append(pkg, aml_int(ACPI_GED_SLP_TYP_S3)); +aml_append(pkg, aml_int(0)); /* ignored */ +aml_append(pkg, aml_int(0)); /* reserved */ +aml_append(pkg, aml_int(0)); /* reserved */ +aml_append(scope, aml_name_decl("_S3", pkg)); +aml_append(dsdt, scope); + +scope = aml_scope("\\"); +pkg = aml_package(4); +aml_append(pkg, aml_int(ACPI_GED_SLP_TYP_S4)); +aml_append(pkg, aml_int(0)); /* ignored */ +aml_append(pkg, aml_int(0)); /* reserved */ +aml_append(pkg, aml_int(0)); /* reserved */ +aml_append(scope, aml_name_decl("_S4", pkg)); +aml_append(dsdt, scope); + scope = aml_scope("\\"); pkg = aml_package(4); aml_append(pkg, aml_int(ACPI_GED_SLP_TYP_S5)); diff --git a/hw/i386/microvm.c b/hw/i386/microvm.c index fec63cacfa88..b9fb2d28e570 100644 --- a/hw/i386/microvm.c +++ b/hw/i386/microvm.c @@ -206,6 +206,9 @@ static void microvm_devices_init(MicrovmMachineState *mms) if (x86_machine_is_acpi_enabled(x86ms)) { DeviceState *dev = qdev_new(TYPE_ACPI_GED); qdev_prop_set_uint32(dev, "ged-event", ACPI_GED_PWR_DOWN_EVT); +qdev_prop_set_uint32(dev, "slp-typs", (1 << ACPI_GED_SLP_TYP_S3) | + (1 << ACPI_GED_SLP_TYP_S4) | + (1 << ACPI_GED_SLP_TYP_S5)); sysbus_realize(SYS_BUS_DEVICE(dev), _fatal); sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, GED_MMIO_BASE); /* sysbus_mmio_map(SYS_BUS_DEVICE(dev), 1, GED_MMIO_BASE_MEMHP); */ -- 2.43.0
Re: [PATCH v3 0/4] hw/mips/loongson3_virt: Implement IPI support
在2024年6月5日六月 上午3:15,Jiaxun Yang写道: > Hi all, > > This series enabled IPI support for loongson3 virt board, loosely > based on my previous work[1]. > It generalized loongarch_ipi device to share among both loongarch > and MIPS machines. > > Thanks A genttle ping :-) Thanks - Jiaxun > > [1]: > https://lore.kernel.org/all/20230521102307.87081-1-jiaxun.y...@flygoat.com/ > > To: qemu-devel@nongnu.org > Cc: Song Gao > > Signed-off-by: Jiaxun Yang > --- > Changes in v3: > - Fix up sign off lines. > - Link to v2: > https://lore.kernel.org/r/20240605-loongson3-ipi-v2-0-da26282e0...@flygoat.com > > Changes in v2: > - Add a patch to remove loongarch_ipi.c (Gao) > - Change iocsr alias owner to CPU (philmd) > - New patch to remove ipi_getcpu > - Link to v1: > https://lore.kernel.org/r/20240508-loongson3-ipi-v1-0-1a7b67704...@flygoat.com > > --- > Jiaxun Yang (4): > hw/intc: Remove loongarch_ipi.c > hw/intc/loongson_ipi: Provide per core MMIO address spaces > hw/mips/loongson3_virt: Wire up loongson_ipi device > hw/intc/loongson_ipi: Replace ipi_getcpu with cpu_by_arch_id > > hw/intc/loongarch_ipi.c| 347 > - > hw/intc/loongson_ipi.c | 120 +++--- > hw/mips/Kconfig| 1 + > hw/mips/loongson3_bootp.c | 2 - > hw/mips/loongson3_bootp.h | 3 + > hw/mips/loongson3_virt.c | 39 - > include/hw/intc/loongson_ipi.h | 2 + > 7 files changed, 108 insertions(+), 406 deletions(-) > --- > base-commit: d67a6e054b92e5e1cbb7b0bd5782a670cc7f0df7 > change-id: 20240508-loongson3-ipi-65e99b47c400 > > Best regards, > -- > Jiaxun Yang -- - Jiaxun
Re: [PATCH] mips64el-softmmu: Enable MTTCG
在2024年6月5日六月 下午1:47,Jiaxun Yang写道: [...] > I'll try to upgrade kernel used in this test. Unfortunately, we don't have kernel build from reliable source for that test. I requested Debian project to build kernel for us[1]. [1]: https://salsa.debian.org/kernel-team/linux/-/merge_requests/1074 Thanks > > Thanks > - Jiaxun >> [...] > > -- > - Jiaxun -- - Jiaxun
Re: [PATCH] mips64el-softmmu: Enable MTTCG
在2024年6月4日六月 下午1:43,Alex Bennée写道: [...] > > I'm a little uncomfortable about making the success of MTTCG depend on > the user options passed to the kernel. Yes, I agree, it sounds awkward. > > How come a non-icount run depends on how many instructions are being run > on each core? Why is time not based on the wallclock time and by > definition synced between all cores? That's the problem of Guest Kernel, the synchronisation mechanism is poorly written that relies on instruction latency too much. I have patch pending to improve it at guest side, but we can't fix it in existing binary. This clock, CP0_Counter, as per ISA spec, is independent between cores and needs to be synchronized by software. We can emulate it as a monotonic clock source and Linux should be happy with it, but that is violating ISA spec. > >> In non-MTTCG build, the execution is slow enough so kernel won't >> observe back drifts. >> >> Test results: >> >> With clocksource=MIPS >> ``` >> ~/tmp/retry/retry.py -n 100 -c -- ./qemu-system-mips64el \ >> -display none -vga none -serial mon:stdio \ >> -machine malta -kernel ./vmlinux-4.7.0-rc1.I6400 \ >> -cpu I6400 -smp 8 -vga std \ >> -append "printk.time=0 clocksource=MIPS console=tty0 console=ttyS0 >> panic=-1" \ >> --no-reboot >> >> 100, 0, PASS, 5.258126, 100, 100, - >> Results summary: >> 0: 100 times (100.00%), avg time 6.508 (55.53 varience/7.45 deviation) >> Ran command 100 times, 100 passes >> ``` >> >> With linux-next: >> ``` >> ~/tmp/retry/retry.py -n 100 -c -- ./qemu-system-mips64el \ >> -display none -vga none -serial mon:stdio \ >> -machine malta -kernel ~/linux-next/vmlinux \ >> -cpu I6400 -smp 8 -vga std \ >> -append "printk.time=0 console=tty0 console=ttyS0 panic=-1" \ >> --no-reboot >> >> 100, 0, PASS, 4.507921, 100, 100, - >> Results summary: >> 0: 100 times (100.00%), avg time 4.233 (0.04 varience/0.21 deviation) >> Ran command 100 times, 100 passes >> ``` >> >> Signed-off-by: Jiaxun Yang >> --- >> I'll leave the test case alone as it's already marked as >> QEMU_TEST_FLAKY_TESTS > > We should ensure we have some testing enabled if we switch this on. Was > the FLAKY test marked for MTTCG issues or something else? Tracking history, I think it was because this issue is still popping up after disabling MTTCG. I'll try to upgrade kernel used in this test. Thanks - Jiaxun > >> --- >> configs/targets/mips64el-softmmu.mak | 1 + >> 1 file changed, 1 insertion(+) >> >> diff --git a/configs/targets/mips64el-softmmu.mak >> b/configs/targets/mips64el-softmmu.mak >> index 8d9ab3ddc4b1..199b1d909a7d 100644 >> --- a/configs/targets/mips64el-softmmu.mak >> +++ b/configs/targets/mips64el-softmmu.mak >> @@ -1,3 +1,4 @@ >> TARGET_ARCH=mips64 >> TARGET_BASE_ARCH=mips >> +TARGET_SUPPORTS_MTTCG=y >> TARGET_NEED_FDT=y >> >> --- >> base-commit: 248f6f62df073a3b4158fd0093863ab885feabb5 >> change-id: 20240511-mips_mttcg-47a6b19074b3 >> >> Best regards, > > -- > Alex Bennée > Virtualisation Tech Lead @ Linaro -- - Jiaxun
[PATCH v3 1/4] hw/intc: Remove loongarch_ipi.c
It was missed out in previous commit. Fixes: b4a12dfc2132 ("hw/intc/loongarch_ipi: Rename as loongson_ipi") Signed-off-by: Jiaxun Yang --- hw/intc/loongarch_ipi.c | 347 1 file changed, 347 deletions(-) diff --git a/hw/intc/loongarch_ipi.c b/hw/intc/loongarch_ipi.c deleted file mode 100644 index 44b3b9c138d6.. --- a/hw/intc/loongarch_ipi.c +++ /dev/null @@ -1,347 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* - * LoongArch ipi interrupt support - * - * Copyright (C) 2021 Loongson Technology Corporation Limited - */ - -#include "qemu/osdep.h" -#include "hw/boards.h" -#include "hw/sysbus.h" -#include "hw/intc/loongarch_ipi.h" -#include "hw/irq.h" -#include "hw/qdev-properties.h" -#include "qapi/error.h" -#include "qemu/log.h" -#include "exec/address-spaces.h" -#include "migration/vmstate.h" -#include "target/loongarch/cpu.h" -#include "trace.h" - -static MemTxResult loongarch_ipi_readl(void *opaque, hwaddr addr, - uint64_t *data, - unsigned size, MemTxAttrs attrs) -{ -IPICore *s; -LoongArchIPI *ipi = opaque; -uint64_t ret = 0; -int index = 0; - -s = >cpu[attrs.requester_id]; -addr &= 0xff; -switch (addr) { -case CORE_STATUS_OFF: -ret = s->status; -break; -case CORE_EN_OFF: -ret = s->en; -break; -case CORE_SET_OFF: -ret = 0; -break; -case CORE_CLEAR_OFF: -ret = 0; -break; -case CORE_BUF_20 ... CORE_BUF_38 + 4: -index = (addr - CORE_BUF_20) >> 2; -ret = s->buf[index]; -break; -default: -qemu_log_mask(LOG_UNIMP, "invalid read: %x", (uint32_t)addr); -break; -} - -trace_loongarch_ipi_read(size, (uint64_t)addr, ret); -*data = ret; -return MEMTX_OK; -} - -static void send_ipi_data(CPULoongArchState *env, uint64_t val, hwaddr addr, - MemTxAttrs attrs) -{ -int i, mask = 0, data = 0; - -/* - * bit 27-30 is mask for byte writing, - * if the mask is 0, we need not to do anything. - */ -if ((val >> 27) & 0xf) { -data = address_space_ldl(env->address_space_iocsr, addr, - attrs, NULL); -for (i = 0; i < 4; i++) { -/* get mask for byte writing */ -if (val & (0x1 << (27 + i))) { -mask |= 0xff << (i * 8); -} -} -} - -data &= mask; -data |= (val >> 32) & ~mask; -address_space_stl(env->address_space_iocsr, addr, - data, attrs, NULL); -} - -static int archid_cmp(const void *a, const void *b) -{ - CPUArchId *archid_a = (CPUArchId *)a; - CPUArchId *archid_b = (CPUArchId *)b; - - return archid_a->arch_id - archid_b->arch_id; -} - -static CPUArchId *find_cpu_by_archid(MachineState *ms, uint32_t id) -{ -CPUArchId apic_id, *found_cpu; - -apic_id.arch_id = id; -found_cpu = bsearch(_id, ms->possible_cpus->cpus, -ms->possible_cpus->len, sizeof(*ms->possible_cpus->cpus), -archid_cmp); - -return found_cpu; -} - -static CPUState *ipi_getcpu(int arch_id) -{ -MachineState *machine = MACHINE(qdev_get_machine()); -CPUArchId *archid; - -archid = find_cpu_by_archid(machine, arch_id); -if (archid) { -return CPU(archid->cpu); -} - -return NULL; -} - -static MemTxResult mail_send(uint64_t val, MemTxAttrs attrs) -{ -uint32_t cpuid; -hwaddr addr; -CPUState *cs; - -cpuid = extract32(val, 16, 10); -cs = ipi_getcpu(cpuid); -if (cs == NULL) { -return MEMTX_DECODE_ERROR; -} - -/* override requester_id */ -addr = SMP_IPI_MAILBOX + CORE_BUF_20 + (val & 0x1c); -attrs.requester_id = cs->cpu_index; -send_ipi_data(_CPU(cs)->env, val, addr, attrs); -return MEMTX_OK; -} - -static MemTxResult any_send(uint64_t val, MemTxAttrs attrs) -{ -uint32_t cpuid; -hwaddr addr; -CPUState *cs; - -cpuid = extract32(val, 16, 10); -cs = ipi_getcpu(cpuid); -if (cs == NULL) { -return MEMTX_DECODE_ERROR; -} - -/* override requester_id */ -addr = val & 0x; -attrs.requester_id = cs->cpu_index; -send_ipi_data(_CPU(cs)->env, val, addr, attrs); -return MEMTX_OK; -} - -static MemTxResult loongarch_ipi_writel(void *opaque, hwaddr addr, uint64_t val, -unsigned size, MemTxAttrs attrs) -{ -LoongArchIPI *ipi = opaque; -IPICore *s; -int index = 0; -uint32_t cpuid; -uint8_t vector; -CPUState *cs; - -s = >cpu[attrs.requester_id]; -addr &= 0xff; -trace_loongarch_ipi
[PATCH v3 4/4] hw/intc/loongson_ipi: Replace ipi_getcpu with cpu_by_arch_id
cpu_by_arch_id is doing the same thing as our ipi_getcpu logic. Signed-off-by: Jiaxun Yang --- hw/intc/loongson_ipi.c | 39 +++ 1 file changed, 3 insertions(+), 36 deletions(-) diff --git a/hw/intc/loongson_ipi.c b/hw/intc/loongson_ipi.c index c8a25b4eb8e2..b3cda5972793 100644 --- a/hw/intc/loongson_ipi.c +++ b/hw/intc/loongson_ipi.c @@ -118,39 +118,6 @@ static MemTxResult send_ipi_data(CPUState *cpu, uint64_t val, hwaddr addr, return MEMTX_OK; } -static int archid_cmp(const void *a, const void *b) -{ - CPUArchId *archid_a = (CPUArchId *)a; - CPUArchId *archid_b = (CPUArchId *)b; - - return archid_a->arch_id - archid_b->arch_id; -} - -static CPUArchId *find_cpu_by_archid(MachineState *ms, uint32_t id) -{ -CPUArchId apic_id, *found_cpu; - -apic_id.arch_id = id; -found_cpu = bsearch(_id, ms->possible_cpus->cpus, -ms->possible_cpus->len, sizeof(*ms->possible_cpus->cpus), -archid_cmp); - -return found_cpu; -} - -static CPUState *ipi_getcpu(int arch_id) -{ -MachineState *machine = MACHINE(qdev_get_machine()); -CPUArchId *archid; - -archid = find_cpu_by_archid(machine, arch_id); -if (archid) { -return CPU(archid->cpu); -} - -return NULL; -} - static MemTxResult mail_send(uint64_t val, MemTxAttrs attrs) { uint32_t cpuid; @@ -158,7 +125,7 @@ static MemTxResult mail_send(uint64_t val, MemTxAttrs attrs) CPUState *cs; cpuid = extract32(val, 16, 10); -cs = ipi_getcpu(cpuid); +cs = cpu_by_arch_id(cpuid); if (cs == NULL) { return MEMTX_DECODE_ERROR; } @@ -176,7 +143,7 @@ static MemTxResult any_send(uint64_t val, MemTxAttrs attrs) CPUState *cs; cpuid = extract32(val, 16, 10); -cs = ipi_getcpu(cpuid); +cs = cpu_by_arch_id(cpuid); if (cs == NULL) { return MEMTX_DECODE_ERROR; } @@ -227,7 +194,7 @@ static MemTxResult loongson_ipi_core_writel(void *opaque, hwaddr addr, cpuid = extract32(val, 16, 10); /* IPI status vector */ vector = extract8(val, 0, 5); -cs = ipi_getcpu(cpuid); +cs = cpu_by_arch_id(cpuid); if (cs == NULL || cs->cpu_index >= ipi->num_cpu) { return MEMTX_DECODE_ERROR; } -- 2.43.0
[PATCH v3 3/4] hw/mips/loongson3_virt: Wire up loongson_ipi device
Wire up loongson_ipi device for loongson3_virt machine, so we can have SMP support for TCG backend as well. Signed-off-by: Jiaxun Yang --- hw/mips/Kconfig | 1 + hw/mips/loongson3_bootp.c | 2 -- hw/mips/loongson3_bootp.h | 3 +++ hw/mips/loongson3_virt.c | 39 +-- 4 files changed, 41 insertions(+), 4 deletions(-) diff --git a/hw/mips/Kconfig b/hw/mips/Kconfig index a7f26edebe84..692bede538ee 100644 --- a/hw/mips/Kconfig +++ b/hw/mips/Kconfig @@ -67,6 +67,7 @@ config LOONGSON3V imply USB_OHCI_PCI select SERIAL select GOLDFISH_RTC +select LOONGSON_IPI select LOONGSON_LIOINTC select PCI_EXPRESS_GENERIC_BRIDGE select MSI_NONBROKEN diff --git a/hw/mips/loongson3_bootp.c b/hw/mips/loongson3_bootp.c index 03a10b63c1b4..b97b81903b74 100644 --- a/hw/mips/loongson3_bootp.c +++ b/hw/mips/loongson3_bootp.c @@ -25,8 +25,6 @@ #include "hw/boards.h" #include "hw/mips/loongson3_bootp.h" -#define LOONGSON3_CORE_PER_NODE 4 - static void init_cpu_info(void *g_cpuinfo, uint64_t cpu_freq) { struct efi_cpuinfo_loongson *c = g_cpuinfo; diff --git a/hw/mips/loongson3_bootp.h b/hw/mips/loongson3_bootp.h index 1b0dd3b59171..9091265df7fc 100644 --- a/hw/mips/loongson3_bootp.h +++ b/hw/mips/loongson3_bootp.h @@ -200,6 +200,8 @@ struct boot_params { struct efi_reset_system_t reset_system; }; +#define LOONGSON3_CORE_PER_NODE 4 + /* Overall MMIO & Memory layout */ enum { VIRT_LOWMEM, @@ -211,6 +213,7 @@ enum { VIRT_BIOS_ROM, VIRT_UART, VIRT_LIOINTC, +VIRT_IPI, VIRT_PCIE_MMIO, VIRT_HIGHMEM }; diff --git a/hw/mips/loongson3_virt.c b/hw/mips/loongson3_virt.c index 440268a07430..3a4105228c1d 100644 --- a/hw/mips/loongson3_virt.c +++ b/hw/mips/loongson3_virt.c @@ -36,6 +36,7 @@ #include "hw/mips/loongson3_bootp.h" #include "hw/misc/unimp.h" #include "hw/intc/i8259.h" +#include "hw/intc/loongson_ipi.h" #include "hw/loader.h" #include "hw/isa/superio.h" #include "hw/pci/msi.h" @@ -74,6 +75,7 @@ const MemMapEntry virt_memmap[] = { [VIRT_PCIE_ECAM] = { 0x1a00, 0x200 }, [VIRT_BIOS_ROM] ={ 0x1fc0, 0x20 }, [VIRT_UART] ={ 0x1fe001e0, 0x8 }, +[VIRT_IPI] = { 0x3ff01000, 0x400 }, [VIRT_LIOINTC] = { 0x3ff01400, 0x64 }, [VIRT_PCIE_MMIO] = { 0x4000,0x4000 }, [VIRT_HIGHMEM] = { 0x8000, 0x0 }, /* Variable */ @@ -485,6 +487,7 @@ static void mips_loongson3_virt_init(MachineState *machine) Clock *cpuclk; CPUMIPSState *env; DeviceState *liointc; +DeviceState *ipi = NULL; char *filename; const char *kernel_cmdline = machine->kernel_cmdline; const char *kernel_filename = machine->kernel_filename; @@ -494,6 +497,7 @@ static void mips_loongson3_virt_init(MachineState *machine) MemoryRegion *ram = g_new(MemoryRegion, 1); MemoryRegion *bios = g_new(MemoryRegion, 1); MemoryRegion *iomem = g_new(MemoryRegion, 1); +MemoryRegion *iocsr = g_new(MemoryRegion, 1); /* TODO: TCG will support all CPU types */ if (!kvm_enabled()) { @@ -527,6 +531,19 @@ static void mips_loongson3_virt_init(MachineState *machine) create_unimplemented_device("mmio fallback 0", 0x1000, 256 * MiB); create_unimplemented_device("mmio fallback 1", 0x3000, 256 * MiB); +memory_region_init(iocsr, OBJECT(machine), "loongson3.iocsr", UINT32_MAX); + +/* IPI controller is in kernel for KVM */ +if (!kvm_enabled()) { +ipi = qdev_new(TYPE_LOONGSON_IPI); +qdev_prop_set_uint32(ipi, "num-cpu", machine->smp.cpus); +sysbus_realize_and_unref(SYS_BUS_DEVICE(ipi), _fatal); +memory_region_add_subregion(iocsr, SMP_IPI_MAILBOX, +sysbus_mmio_get_region(SYS_BUS_DEVICE(ipi), 0)); +memory_region_add_subregion(iocsr, MAIL_SEND_ADDR, +sysbus_mmio_get_region(SYS_BUS_DEVICE(ipi), 1)); +} + liointc = qdev_new("loongson.liointc"); sysbus_realize_and_unref(SYS_BUS_DEVICE(liointc), _fatal); @@ -543,6 +560,8 @@ static void mips_loongson3_virt_init(MachineState *machine) clock_set_hz(cpuclk, DEF_LOONGSON3_FREQ); for (i = 0; i < machine->smp.cpus; i++) { +int node = i / LOONGSON3_CORE_PER_NODE; +int core = i % LOONGSON3_CORE_PER_NODE; int ip; /* init CPUs */ @@ -553,12 +572,28 @@ static void mips_loongson3_virt_init(MachineState *machine) cpu_mips_clock_init(cpu); qemu_register_reset(main_cpu_reset, cpu); -if (i >= 4) { +if (ipi) { +hwaddr base = ((hwaddr)node << 44) + virt_memmap[VIRT_IPI].base; +base += core * 0x100; +qdev_connect_gpio_out(ipi, i, cpu->env.irq[6]); +sysbu
[PATCH v3 2/4] hw/intc/loongson_ipi: Provide per core MMIO address spaces
The real IPI hardware have dedicated MMIO registers mapped into memory address space for every core. This is not used by LoongArch guest software but it is essential for CPU without IOCSR such as Loongson-3A1000. Implement it with existing infrastructure. Acked-by: Song Gao Signed-off-by: Jiaxun Yang --- hw/intc/loongson_ipi.c | 81 -- include/hw/intc/loongson_ipi.h | 2 ++ 2 files changed, 64 insertions(+), 19 deletions(-) diff --git a/hw/intc/loongson_ipi.c b/hw/intc/loongson_ipi.c index 93cc50a37a11..c8a25b4eb8e2 100644 --- a/hw/intc/loongson_ipi.c +++ b/hw/intc/loongson_ipi.c @@ -23,16 +23,14 @@ #endif #include "trace.h" -static MemTxResult loongson_ipi_readl(void *opaque, hwaddr addr, +static MemTxResult loongson_ipi_core_readl(void *opaque, hwaddr addr, uint64_t *data, unsigned size, MemTxAttrs attrs) { -IPICore *s; -LoongsonIPI *ipi = opaque; +IPICore *s = opaque; uint64_t ret = 0; int index = 0; -s = >cpu[attrs.requester_id]; addr &= 0xff; switch (addr) { case CORE_STATUS_OFF: @@ -61,6 +59,21 @@ static MemTxResult loongson_ipi_readl(void *opaque, hwaddr addr, return MEMTX_OK; } +static MemTxResult loongson_ipi_iocsr_readl(void *opaque, hwaddr addr, + uint64_t *data, + unsigned size, MemTxAttrs attrs) +{ +LoongsonIPI *ipi = opaque; +IPICore *s; + +if (attrs.requester_id >= ipi->num_cpu) { +return MEMTX_DECODE_ERROR; +} + +s = >cpu[attrs.requester_id]; +return loongson_ipi_core_readl(s, addr, data, size, attrs); +} + static AddressSpace *get_cpu_iocsr_as(CPUState *cpu) { #ifdef TARGET_LOONGARCH64 @@ -174,17 +187,17 @@ static MemTxResult any_send(uint64_t val, MemTxAttrs attrs) return send_ipi_data(cs, val, addr, attrs); } -static MemTxResult loongson_ipi_writel(void *opaque, hwaddr addr, uint64_t val, -unsigned size, MemTxAttrs attrs) +static MemTxResult loongson_ipi_core_writel(void *opaque, hwaddr addr, +uint64_t val, unsigned size, +MemTxAttrs attrs) { -LoongsonIPI *ipi = opaque; -IPICore *s; +IPICore *s = opaque; +LoongsonIPI *ipi = s->ipi; int index = 0; uint32_t cpuid; uint8_t vector; CPUState *cs; -s = >cpu[attrs.requester_id]; addr &= 0xff; trace_loongson_ipi_write(size, (uint64_t)addr, val); switch (addr) { @@ -215,13 +228,11 @@ static MemTxResult loongson_ipi_writel(void *opaque, hwaddr addr, uint64_t val, /* IPI status vector */ vector = extract8(val, 0, 5); cs = ipi_getcpu(cpuid); -if (cs == NULL) { +if (cs == NULL || cs->cpu_index >= ipi->num_cpu) { return MEMTX_DECODE_ERROR; } - -/* override requester_id */ -attrs.requester_id = cs->cpu_index; -loongson_ipi_writel(ipi, CORE_SET_OFF, BIT(vector), 4, attrs); +loongson_ipi_core_writel(>cpu[cs->cpu_index], CORE_SET_OFF, + BIT(vector), 4, attrs); break; default: qemu_log_mask(LOG_UNIMP, "invalid write: %x", (uint32_t)addr); @@ -231,9 +242,34 @@ static MemTxResult loongson_ipi_writel(void *opaque, hwaddr addr, uint64_t val, return MEMTX_OK; } -static const MemoryRegionOps loongson_ipi_ops = { -.read_with_attrs = loongson_ipi_readl, -.write_with_attrs = loongson_ipi_writel, +static MemTxResult loongson_ipi_iocsr_writel(void *opaque, hwaddr addr, +uint64_t val, unsigned size, +MemTxAttrs attrs) +{ +LoongsonIPI *ipi = opaque; +IPICore *s; + +if (attrs.requester_id >= ipi->num_cpu) { +return MEMTX_DECODE_ERROR; +} + +s = >cpu[attrs.requester_id]; +return loongson_ipi_core_writel(s, addr, val, size, attrs); +} + +static const MemoryRegionOps loongson_ipi_core_ops = { +.read_with_attrs = loongson_ipi_core_readl, +.write_with_attrs = loongson_ipi_core_writel, +.impl.min_access_size = 4, +.impl.max_access_size = 4, +.valid.min_access_size = 4, +.valid.max_access_size = 8, +.endianness = DEVICE_LITTLE_ENDIAN, +}; + +static const MemoryRegionOps loongson_ipi_iocsr_ops = { +.read_with_attrs = loongson_ipi_iocsr_readl, +.write_with_attrs = loongson_ipi_iocsr_writel, .impl.min_access_size = 4, .impl.max_access_size = 4, .valid.min_access_size = 4, @@ -282,7 +318,7 @@ static void loongson_ipi_realize(DeviceState *dev, Error **errp) return; } -memory_region_init_io(>ipi_iocsr_mem, OBJECT(dev), _ipi_ops, +memory_region_init_i
[PATCH v3 0/4] hw/mips/loongson3_virt: Implement IPI support
Hi all, This series enabled IPI support for loongson3 virt board, loosely based on my previous work[1]. It generalized loongarch_ipi device to share among both loongarch and MIPS machines. Thanks [1]: https://lore.kernel.org/all/20230521102307.87081-1-jiaxun.y...@flygoat.com/ To: qemu-devel@nongnu.org Cc: Song Gao Signed-off-by: Jiaxun Yang --- Changes in v3: - Fix up sign off lines. - Link to v2: https://lore.kernel.org/r/20240605-loongson3-ipi-v2-0-da26282e0...@flygoat.com Changes in v2: - Add a patch to remove loongarch_ipi.c (Gao) - Change iocsr alias owner to CPU (philmd) - New patch to remove ipi_getcpu - Link to v1: https://lore.kernel.org/r/20240508-loongson3-ipi-v1-0-1a7b67704...@flygoat.com --- Jiaxun Yang (4): hw/intc: Remove loongarch_ipi.c hw/intc/loongson_ipi: Provide per core MMIO address spaces hw/mips/loongson3_virt: Wire up loongson_ipi device hw/intc/loongson_ipi: Replace ipi_getcpu with cpu_by_arch_id hw/intc/loongarch_ipi.c| 347 - hw/intc/loongson_ipi.c | 120 +++--- hw/mips/Kconfig| 1 + hw/mips/loongson3_bootp.c | 2 - hw/mips/loongson3_bootp.h | 3 + hw/mips/loongson3_virt.c | 39 - include/hw/intc/loongson_ipi.h | 2 + 7 files changed, 108 insertions(+), 406 deletions(-) --- base-commit: d67a6e054b92e5e1cbb7b0bd5782a670cc7f0df7 change-id: 20240508-loongson3-ipi-65e99b47c400 Best regards, -- Jiaxun Yang
[PATCH v2 4/4] hw/intc/loongson_ipi: Replace ipi_getcpu with cpu_by_arch_id
cpu_by_arch_id is doing the same thing as our ipi_getcpu logic. Signed-off-by: jiaxun.y...@flygoat.com --- hw/intc/loongson_ipi.c | 39 +++ 1 file changed, 3 insertions(+), 36 deletions(-) diff --git a/hw/intc/loongson_ipi.c b/hw/intc/loongson_ipi.c index c8a25b4eb8e2..b3cda5972793 100644 --- a/hw/intc/loongson_ipi.c +++ b/hw/intc/loongson_ipi.c @@ -118,39 +118,6 @@ static MemTxResult send_ipi_data(CPUState *cpu, uint64_t val, hwaddr addr, return MEMTX_OK; } -static int archid_cmp(const void *a, const void *b) -{ - CPUArchId *archid_a = (CPUArchId *)a; - CPUArchId *archid_b = (CPUArchId *)b; - - return archid_a->arch_id - archid_b->arch_id; -} - -static CPUArchId *find_cpu_by_archid(MachineState *ms, uint32_t id) -{ -CPUArchId apic_id, *found_cpu; - -apic_id.arch_id = id; -found_cpu = bsearch(_id, ms->possible_cpus->cpus, -ms->possible_cpus->len, sizeof(*ms->possible_cpus->cpus), -archid_cmp); - -return found_cpu; -} - -static CPUState *ipi_getcpu(int arch_id) -{ -MachineState *machine = MACHINE(qdev_get_machine()); -CPUArchId *archid; - -archid = find_cpu_by_archid(machine, arch_id); -if (archid) { -return CPU(archid->cpu); -} - -return NULL; -} - static MemTxResult mail_send(uint64_t val, MemTxAttrs attrs) { uint32_t cpuid; @@ -158,7 +125,7 @@ static MemTxResult mail_send(uint64_t val, MemTxAttrs attrs) CPUState *cs; cpuid = extract32(val, 16, 10); -cs = ipi_getcpu(cpuid); +cs = cpu_by_arch_id(cpuid); if (cs == NULL) { return MEMTX_DECODE_ERROR; } @@ -176,7 +143,7 @@ static MemTxResult any_send(uint64_t val, MemTxAttrs attrs) CPUState *cs; cpuid = extract32(val, 16, 10); -cs = ipi_getcpu(cpuid); +cs = cpu_by_arch_id(cpuid); if (cs == NULL) { return MEMTX_DECODE_ERROR; } @@ -227,7 +194,7 @@ static MemTxResult loongson_ipi_core_writel(void *opaque, hwaddr addr, cpuid = extract32(val, 16, 10); /* IPI status vector */ vector = extract8(val, 0, 5); -cs = ipi_getcpu(cpuid); +cs = cpu_by_arch_id(cpuid); if (cs == NULL || cs->cpu_index >= ipi->num_cpu) { return MEMTX_DECODE_ERROR; } -- 2.43.0
[PATCH v2 3/4] hw/mips/loongson3_virt: Wire up loongson_ipi device
Wire up loongson_ipi device for loongson3_virt machine, so we can have SMP support for TCG backend as well. Signed-off-by: Jiaxun Yang --- hw/mips/Kconfig | 1 + hw/mips/loongson3_bootp.c | 2 -- hw/mips/loongson3_bootp.h | 3 +++ hw/mips/loongson3_virt.c | 39 +-- 4 files changed, 41 insertions(+), 4 deletions(-) diff --git a/hw/mips/Kconfig b/hw/mips/Kconfig index a7f26edebe84..692bede538ee 100644 --- a/hw/mips/Kconfig +++ b/hw/mips/Kconfig @@ -67,6 +67,7 @@ config LOONGSON3V imply USB_OHCI_PCI select SERIAL select GOLDFISH_RTC +select LOONGSON_IPI select LOONGSON_LIOINTC select PCI_EXPRESS_GENERIC_BRIDGE select MSI_NONBROKEN diff --git a/hw/mips/loongson3_bootp.c b/hw/mips/loongson3_bootp.c index 03a10b63c1b4..b97b81903b74 100644 --- a/hw/mips/loongson3_bootp.c +++ b/hw/mips/loongson3_bootp.c @@ -25,8 +25,6 @@ #include "hw/boards.h" #include "hw/mips/loongson3_bootp.h" -#define LOONGSON3_CORE_PER_NODE 4 - static void init_cpu_info(void *g_cpuinfo, uint64_t cpu_freq) { struct efi_cpuinfo_loongson *c = g_cpuinfo; diff --git a/hw/mips/loongson3_bootp.h b/hw/mips/loongson3_bootp.h index 1b0dd3b59171..9091265df7fc 100644 --- a/hw/mips/loongson3_bootp.h +++ b/hw/mips/loongson3_bootp.h @@ -200,6 +200,8 @@ struct boot_params { struct efi_reset_system_t reset_system; }; +#define LOONGSON3_CORE_PER_NODE 4 + /* Overall MMIO & Memory layout */ enum { VIRT_LOWMEM, @@ -211,6 +213,7 @@ enum { VIRT_BIOS_ROM, VIRT_UART, VIRT_LIOINTC, +VIRT_IPI, VIRT_PCIE_MMIO, VIRT_HIGHMEM }; diff --git a/hw/mips/loongson3_virt.c b/hw/mips/loongson3_virt.c index 440268a07430..3a4105228c1d 100644 --- a/hw/mips/loongson3_virt.c +++ b/hw/mips/loongson3_virt.c @@ -36,6 +36,7 @@ #include "hw/mips/loongson3_bootp.h" #include "hw/misc/unimp.h" #include "hw/intc/i8259.h" +#include "hw/intc/loongson_ipi.h" #include "hw/loader.h" #include "hw/isa/superio.h" #include "hw/pci/msi.h" @@ -74,6 +75,7 @@ const MemMapEntry virt_memmap[] = { [VIRT_PCIE_ECAM] = { 0x1a00, 0x200 }, [VIRT_BIOS_ROM] ={ 0x1fc0, 0x20 }, [VIRT_UART] ={ 0x1fe001e0, 0x8 }, +[VIRT_IPI] = { 0x3ff01000, 0x400 }, [VIRT_LIOINTC] = { 0x3ff01400, 0x64 }, [VIRT_PCIE_MMIO] = { 0x4000,0x4000 }, [VIRT_HIGHMEM] = { 0x8000, 0x0 }, /* Variable */ @@ -485,6 +487,7 @@ static void mips_loongson3_virt_init(MachineState *machine) Clock *cpuclk; CPUMIPSState *env; DeviceState *liointc; +DeviceState *ipi = NULL; char *filename; const char *kernel_cmdline = machine->kernel_cmdline; const char *kernel_filename = machine->kernel_filename; @@ -494,6 +497,7 @@ static void mips_loongson3_virt_init(MachineState *machine) MemoryRegion *ram = g_new(MemoryRegion, 1); MemoryRegion *bios = g_new(MemoryRegion, 1); MemoryRegion *iomem = g_new(MemoryRegion, 1); +MemoryRegion *iocsr = g_new(MemoryRegion, 1); /* TODO: TCG will support all CPU types */ if (!kvm_enabled()) { @@ -527,6 +531,19 @@ static void mips_loongson3_virt_init(MachineState *machine) create_unimplemented_device("mmio fallback 0", 0x1000, 256 * MiB); create_unimplemented_device("mmio fallback 1", 0x3000, 256 * MiB); +memory_region_init(iocsr, OBJECT(machine), "loongson3.iocsr", UINT32_MAX); + +/* IPI controller is in kernel for KVM */ +if (!kvm_enabled()) { +ipi = qdev_new(TYPE_LOONGSON_IPI); +qdev_prop_set_uint32(ipi, "num-cpu", machine->smp.cpus); +sysbus_realize_and_unref(SYS_BUS_DEVICE(ipi), _fatal); +memory_region_add_subregion(iocsr, SMP_IPI_MAILBOX, +sysbus_mmio_get_region(SYS_BUS_DEVICE(ipi), 0)); +memory_region_add_subregion(iocsr, MAIL_SEND_ADDR, +sysbus_mmio_get_region(SYS_BUS_DEVICE(ipi), 1)); +} + liointc = qdev_new("loongson.liointc"); sysbus_realize_and_unref(SYS_BUS_DEVICE(liointc), _fatal); @@ -543,6 +560,8 @@ static void mips_loongson3_virt_init(MachineState *machine) clock_set_hz(cpuclk, DEF_LOONGSON3_FREQ); for (i = 0; i < machine->smp.cpus; i++) { +int node = i / LOONGSON3_CORE_PER_NODE; +int core = i % LOONGSON3_CORE_PER_NODE; int ip; /* init CPUs */ @@ -553,12 +572,28 @@ static void mips_loongson3_virt_init(MachineState *machine) cpu_mips_clock_init(cpu); qemu_register_reset(main_cpu_reset, cpu); -if (i >= 4) { +if (ipi) { +hwaddr base = ((hwaddr)node << 44) + virt_memmap[VIRT_IPI].base; +base += core * 0x100; +qdev_connect_gpio_out(ipi, i, cpu->env.irq[6]); +sysbu
[PATCH v2 2/4] hw/intc/loongson_ipi: Provide per core MMIO address spaces
The real IPI hardware have dedicated MMIO registers mapped into memory address space for every core. This is not used by LoongArch guest software but it is essential for CPU without IOCSR such as Loongson-3A1000. Implement it with existing infrastructure. Acked-by: Song Gao Signed-off-by: Jiaxun Yang --- hw/intc/loongson_ipi.c | 81 -- include/hw/intc/loongson_ipi.h | 2 ++ 2 files changed, 64 insertions(+), 19 deletions(-) diff --git a/hw/intc/loongson_ipi.c b/hw/intc/loongson_ipi.c index 93cc50a37a11..c8a25b4eb8e2 100644 --- a/hw/intc/loongson_ipi.c +++ b/hw/intc/loongson_ipi.c @@ -23,16 +23,14 @@ #endif #include "trace.h" -static MemTxResult loongson_ipi_readl(void *opaque, hwaddr addr, +static MemTxResult loongson_ipi_core_readl(void *opaque, hwaddr addr, uint64_t *data, unsigned size, MemTxAttrs attrs) { -IPICore *s; -LoongsonIPI *ipi = opaque; +IPICore *s = opaque; uint64_t ret = 0; int index = 0; -s = >cpu[attrs.requester_id]; addr &= 0xff; switch (addr) { case CORE_STATUS_OFF: @@ -61,6 +59,21 @@ static MemTxResult loongson_ipi_readl(void *opaque, hwaddr addr, return MEMTX_OK; } +static MemTxResult loongson_ipi_iocsr_readl(void *opaque, hwaddr addr, + uint64_t *data, + unsigned size, MemTxAttrs attrs) +{ +LoongsonIPI *ipi = opaque; +IPICore *s; + +if (attrs.requester_id >= ipi->num_cpu) { +return MEMTX_DECODE_ERROR; +} + +s = >cpu[attrs.requester_id]; +return loongson_ipi_core_readl(s, addr, data, size, attrs); +} + static AddressSpace *get_cpu_iocsr_as(CPUState *cpu) { #ifdef TARGET_LOONGARCH64 @@ -174,17 +187,17 @@ static MemTxResult any_send(uint64_t val, MemTxAttrs attrs) return send_ipi_data(cs, val, addr, attrs); } -static MemTxResult loongson_ipi_writel(void *opaque, hwaddr addr, uint64_t val, -unsigned size, MemTxAttrs attrs) +static MemTxResult loongson_ipi_core_writel(void *opaque, hwaddr addr, +uint64_t val, unsigned size, +MemTxAttrs attrs) { -LoongsonIPI *ipi = opaque; -IPICore *s; +IPICore *s = opaque; +LoongsonIPI *ipi = s->ipi; int index = 0; uint32_t cpuid; uint8_t vector; CPUState *cs; -s = >cpu[attrs.requester_id]; addr &= 0xff; trace_loongson_ipi_write(size, (uint64_t)addr, val); switch (addr) { @@ -215,13 +228,11 @@ static MemTxResult loongson_ipi_writel(void *opaque, hwaddr addr, uint64_t val, /* IPI status vector */ vector = extract8(val, 0, 5); cs = ipi_getcpu(cpuid); -if (cs == NULL) { +if (cs == NULL || cs->cpu_index >= ipi->num_cpu) { return MEMTX_DECODE_ERROR; } - -/* override requester_id */ -attrs.requester_id = cs->cpu_index; -loongson_ipi_writel(ipi, CORE_SET_OFF, BIT(vector), 4, attrs); +loongson_ipi_core_writel(>cpu[cs->cpu_index], CORE_SET_OFF, + BIT(vector), 4, attrs); break; default: qemu_log_mask(LOG_UNIMP, "invalid write: %x", (uint32_t)addr); @@ -231,9 +242,34 @@ static MemTxResult loongson_ipi_writel(void *opaque, hwaddr addr, uint64_t val, return MEMTX_OK; } -static const MemoryRegionOps loongson_ipi_ops = { -.read_with_attrs = loongson_ipi_readl, -.write_with_attrs = loongson_ipi_writel, +static MemTxResult loongson_ipi_iocsr_writel(void *opaque, hwaddr addr, +uint64_t val, unsigned size, +MemTxAttrs attrs) +{ +LoongsonIPI *ipi = opaque; +IPICore *s; + +if (attrs.requester_id >= ipi->num_cpu) { +return MEMTX_DECODE_ERROR; +} + +s = >cpu[attrs.requester_id]; +return loongson_ipi_core_writel(s, addr, val, size, attrs); +} + +static const MemoryRegionOps loongson_ipi_core_ops = { +.read_with_attrs = loongson_ipi_core_readl, +.write_with_attrs = loongson_ipi_core_writel, +.impl.min_access_size = 4, +.impl.max_access_size = 4, +.valid.min_access_size = 4, +.valid.max_access_size = 8, +.endianness = DEVICE_LITTLE_ENDIAN, +}; + +static const MemoryRegionOps loongson_ipi_iocsr_ops = { +.read_with_attrs = loongson_ipi_iocsr_readl, +.write_with_attrs = loongson_ipi_iocsr_writel, .impl.min_access_size = 4, .impl.max_access_size = 4, .valid.min_access_size = 4, @@ -282,7 +318,7 @@ static void loongson_ipi_realize(DeviceState *dev, Error **errp) return; } -memory_region_init_io(>ipi_iocsr_mem, OBJECT(dev), _ipi_ops, +memory_region_init_i
[PATCH v2 1/4] hw/intc: Remove loongarch_ipi.c
It was missed out in previous commit. Fixes: b4a12dfc2132 ("hw/intc/loongarch_ipi: Rename as loongson_ipi") Signed-off-by: jiaxun.y...@flygoat.com --- hw/intc/loongarch_ipi.c | 347 1 file changed, 347 deletions(-) diff --git a/hw/intc/loongarch_ipi.c b/hw/intc/loongarch_ipi.c deleted file mode 100644 index 44b3b9c138d6.. --- a/hw/intc/loongarch_ipi.c +++ /dev/null @@ -1,347 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* - * LoongArch ipi interrupt support - * - * Copyright (C) 2021 Loongson Technology Corporation Limited - */ - -#include "qemu/osdep.h" -#include "hw/boards.h" -#include "hw/sysbus.h" -#include "hw/intc/loongarch_ipi.h" -#include "hw/irq.h" -#include "hw/qdev-properties.h" -#include "qapi/error.h" -#include "qemu/log.h" -#include "exec/address-spaces.h" -#include "migration/vmstate.h" -#include "target/loongarch/cpu.h" -#include "trace.h" - -static MemTxResult loongarch_ipi_readl(void *opaque, hwaddr addr, - uint64_t *data, - unsigned size, MemTxAttrs attrs) -{ -IPICore *s; -LoongArchIPI *ipi = opaque; -uint64_t ret = 0; -int index = 0; - -s = >cpu[attrs.requester_id]; -addr &= 0xff; -switch (addr) { -case CORE_STATUS_OFF: -ret = s->status; -break; -case CORE_EN_OFF: -ret = s->en; -break; -case CORE_SET_OFF: -ret = 0; -break; -case CORE_CLEAR_OFF: -ret = 0; -break; -case CORE_BUF_20 ... CORE_BUF_38 + 4: -index = (addr - CORE_BUF_20) >> 2; -ret = s->buf[index]; -break; -default: -qemu_log_mask(LOG_UNIMP, "invalid read: %x", (uint32_t)addr); -break; -} - -trace_loongarch_ipi_read(size, (uint64_t)addr, ret); -*data = ret; -return MEMTX_OK; -} - -static void send_ipi_data(CPULoongArchState *env, uint64_t val, hwaddr addr, - MemTxAttrs attrs) -{ -int i, mask = 0, data = 0; - -/* - * bit 27-30 is mask for byte writing, - * if the mask is 0, we need not to do anything. - */ -if ((val >> 27) & 0xf) { -data = address_space_ldl(env->address_space_iocsr, addr, - attrs, NULL); -for (i = 0; i < 4; i++) { -/* get mask for byte writing */ -if (val & (0x1 << (27 + i))) { -mask |= 0xff << (i * 8); -} -} -} - -data &= mask; -data |= (val >> 32) & ~mask; -address_space_stl(env->address_space_iocsr, addr, - data, attrs, NULL); -} - -static int archid_cmp(const void *a, const void *b) -{ - CPUArchId *archid_a = (CPUArchId *)a; - CPUArchId *archid_b = (CPUArchId *)b; - - return archid_a->arch_id - archid_b->arch_id; -} - -static CPUArchId *find_cpu_by_archid(MachineState *ms, uint32_t id) -{ -CPUArchId apic_id, *found_cpu; - -apic_id.arch_id = id; -found_cpu = bsearch(_id, ms->possible_cpus->cpus, -ms->possible_cpus->len, sizeof(*ms->possible_cpus->cpus), -archid_cmp); - -return found_cpu; -} - -static CPUState *ipi_getcpu(int arch_id) -{ -MachineState *machine = MACHINE(qdev_get_machine()); -CPUArchId *archid; - -archid = find_cpu_by_archid(machine, arch_id); -if (archid) { -return CPU(archid->cpu); -} - -return NULL; -} - -static MemTxResult mail_send(uint64_t val, MemTxAttrs attrs) -{ -uint32_t cpuid; -hwaddr addr; -CPUState *cs; - -cpuid = extract32(val, 16, 10); -cs = ipi_getcpu(cpuid); -if (cs == NULL) { -return MEMTX_DECODE_ERROR; -} - -/* override requester_id */ -addr = SMP_IPI_MAILBOX + CORE_BUF_20 + (val & 0x1c); -attrs.requester_id = cs->cpu_index; -send_ipi_data(_CPU(cs)->env, val, addr, attrs); -return MEMTX_OK; -} - -static MemTxResult any_send(uint64_t val, MemTxAttrs attrs) -{ -uint32_t cpuid; -hwaddr addr; -CPUState *cs; - -cpuid = extract32(val, 16, 10); -cs = ipi_getcpu(cpuid); -if (cs == NULL) { -return MEMTX_DECODE_ERROR; -} - -/* override requester_id */ -addr = val & 0x; -attrs.requester_id = cs->cpu_index; -send_ipi_data(_CPU(cs)->env, val, addr, attrs); -return MEMTX_OK; -} - -static MemTxResult loongarch_ipi_writel(void *opaque, hwaddr addr, uint64_t val, -unsigned size, MemTxAttrs attrs) -{ -LoongArchIPI *ipi = opaque; -IPICore *s; -int index = 0; -uint32_t cpuid; -uint8_t vector; -CPUState *cs; - -s = >cpu[attrs.requester_id]; -addr &= 0xff; -trace_loongarch_ipi_write(size, (uint64_t)addr, val); -switch (addr) { -case CORE_STATUS_OFF: -qemu_log_mask(LOG_GUEST_ERROR, "can not be written"); -break; -case CORE_EN_OFF: -s->en = val; -break; -case CORE_SET_OFF: -
[PATCH v2 0/4] hw/mips/loongson3_virt: Implement IPI support
Hi all, This series enabled IPI support for loongson3 virt board, loosely based on my previous work[1]. It generalized loongarch_ipi device to share among both loongarch and MIPS machines. Thanks [1]: https://lore.kernel.org/all/20230521102307.87081-1-jiaxun.y...@flygoat.com/ To: qemu-devel@nongnu.org Cc: Song Gao Signed-off-by: Jiaxun Yang --- Changes in v2: - Add a patch to remove loongarch_ipi.c (Gao) - Change iocsr alias owner to CPU (philmd) - New patch to remove ipi_getcpu - Link to v1: https://lore.kernel.org/r/20240508-loongson3-ipi-v1-0-1a7b67704...@flygoat.com --- Jiaxun Yang (4): hw/intc: Remove loongarch_ipi.c hw/intc/loongson_ipi: Provide per core MMIO address spaces hw/mips/loongson3_virt: Wire up loongson_ipi device hw/intc/loongson_ipi: Replace ipi_getcpu with cpu_by_arch_id hw/intc/loongarch_ipi.c| 347 - hw/intc/loongson_ipi.c | 120 +++--- hw/mips/Kconfig| 1 + hw/mips/loongson3_bootp.c | 2 - hw/mips/loongson3_bootp.h | 3 + hw/mips/loongson3_virt.c | 39 - include/hw/intc/loongson_ipi.h | 2 + 7 files changed, 108 insertions(+), 406 deletions(-) --- base-commit: d67a6e054b92e5e1cbb7b0bd5782a670cc7f0df7 change-id: 20240508-loongson3-ipi-65e99b47c400 Best regards, -- Jiaxun Yang
Re: [PATCH 3/5] hw/intc/loongson_ipi: Implement IOCSR address space for MIPS
在2024年6月3日六月 下午4:45,Philippe Mathieu-Daudé写道: [...] > > LoongsonIPI should have an array of CPUState[] and MemoryRegion[]. > (Or maybe add them to IPICore.) > Expose them as QOM link properties. > > Caller wire them while creating the LoongsonIPI. > Then loongson_ipi_realize() resolves them once. > No need to call get_cpu_iocsr_as() and ipi_getcpu() for each MMIO > access IMO. I was tempted to do so but realized that arch_id might be discontinuous for LoongArch. @Song, can you confirm if it's viable? Thanks - Jiaxun > >> + >> +if (!iocsr_as) { >> +return MEMTX_DECODE_ERROR; >> +} -- - Jiaxun
Re: [PATCH] mips64el-softmmu: Enable MTTCG
在2024年6月3日六月 下午7:15,Pierrick Bouvier写道: > On 5/11/24 13:26, Jiaxun Yang wrote: >> MTTCG was disabled in a092a9554771 ("configure: disable MTTCG >> for MIPS guests") due to test case instability. >> >> I was able to reproduce this issue with in latest QEMU and look >> into reason behind that. >> >> What actually happend is kernel's CP0 timer synchronisation >> mechanism assumed a consistent latency in memory access between >> cores, which TCG can't guarantee. Thus there is a huge drift in >> count value between cores, and in early kernel versions CP0 timer >> is always used as sched_clock. >> >> sched_clock drift back on some cores triggered RCU watchdog in >> some extreme cases. >> >> This can be resolved by setting clocksource to MIPS, which allows >> clocksource to drift together with sched_clock. However this will >> leed to other problems after boot. >> >> Another option would beupdating kernel to later version, which >> will use GIC as sched_clock. >> >> In non-MTTCG build, the execution is slow enough so kernel won't >> observe back drifts. >> >> Test results: >> >> With clocksource=MIPS >> ``` >> ~/tmp/retry/retry.py -n 100 -c -- ./qemu-system-mips64el \ >> -display none -vga none -serial mon:stdio \ >> -machine malta -kernel ./vmlinux-4.7.0-rc1.I6400 \ >> -cpu I6400 -smp 8 -vga std \ >> -append "printk.time=0 clocksource=MIPS console=tty0 console=ttyS0 >> panic=-1" \ >> --no-reboot >> >> 100, 0, PASS, 5.258126, 100, 100, - >> Results summary: >> 0: 100 times (100.00%), avg time 6.508 (55.53 varience/7.45 deviation) >> Ran command 100 times, 100 passes >> ``` >> >> With linux-next: >> ``` >> ~/tmp/retry/retry.py -n 100 -c -- ./qemu-system-mips64el \ >> -display none -vga none -serial mon:stdio \ >> -machine malta -kernel ~/linux-next/vmlinux \ >> -cpu I6400 -smp 8 -vga std \ >> -append "printk.time=0 console=tty0 console=ttyS0 panic=-1" \ >> --no-reboot >> >> 100, 0, PASS, 4.507921, 100, 100, - >> Results summary: >> 0: 100 times (100.00%), avg time 4.233 (0.04 varience/0.21 deviation) >> Ran command 100 times, 100 passes >> ``` >> >> Signed-off-by: Jiaxun Yang >> --- >> I'll leave the test case alone as it's already marked as >> QEMU_TEST_FLAKY_TESTS >> --- >> configs/targets/mips64el-softmmu.mak | 1 + >> 1 file changed, 1 insertion(+) >> >> diff --git a/configs/targets/mips64el-softmmu.mak >> b/configs/targets/mips64el-softmmu.mak >> index 8d9ab3ddc4b1..199b1d909a7d 100644 >> --- a/configs/targets/mips64el-softmmu.mak >> +++ b/configs/targets/mips64el-softmmu.mak >> @@ -1,3 +1,4 @@ >> TARGET_ARCH=mips64 >> TARGET_BASE_ARCH=mips >> +TARGET_SUPPORTS_MTTCG=y >> TARGET_NEED_FDT=y >> >> --- >> base-commit: 248f6f62df073a3b4158fd0093863ab885feabb5 >> change-id: 20240511-mips_mttcg-47a6b19074b3 >> >> Best regards, > > Hi Jiaxun, > Thanks for your analysis! > > We should see to update concerned test in another series. > I'm not sure which way is preferred between updating kernel used or > changing current command line. > > Reviewed-by: Pierrick Bouvier I think updating kernel can prevent further problems. Will test with latest Debian kernel. Thanks! -- - Jiaxun
Re: tests/avocado: Add LoongArch machine start test
在2024年5月31日五月 上午2:52,gaosong写道: > 在 2024/5/30 下午9:16, Jiaxun Yang 写道: >> >> 在2024年5月30日五月 下午2:00,gaosong写道: >> [...] >>>> FYI, the test does not seem to work anymore - apparently the binaries >>>> have changed and now the hashes do not match anymore. Could you please >>>> update it? (preferably with some versioned binaries that do not change >>>> in the course of time?) >>>> >>> Thank you, I had send a patch to fix it. >> Hi Song, >> >> As LoongArch EDK2 support has been merged long ago, do you to make a clean >> build and add it to pc-bios directory? > EDK2 LoongArchVirt under OvmfPkg is being committed to upstream. > > PR: > https://github.com/tianocore/edk2/pull/5208 I meant here: https://gitlab.com/qemu-project/qemu/-/tree/master/pc-bios?ref_type=heads Thanks > > Thanks > Song Gao >> >> Thanks >> - Jiaxun -- - Jiaxun
Re: tests/avocado: Add LoongArch machine start test
在2024年5月30日五月 下午2:00,gaosong写道: [...] >> FYI, the test does not seem to work anymore - apparently the binaries >> have changed and now the hashes do not match anymore. Could you please >> update it? (preferably with some versioned binaries that do not change >> in the course of time?) >> > Thank you, I had send a patch to fix it. Hi Song, As LoongArch EDK2 support has been merged long ago, do you to make a clean build and add it to pc-bios directory? Thanks - Jiaxun > > Thanks. > Song Gao -- - Jiaxun
Re: [PATCH] target/mips: Remove unused 'hw/misc/mips_itu.h' header
在2024年5月29日五月 下午4:52,Philippe Mathieu-Daudé写道: > Since commit e1152f8166 ("target/mips: Remove helpers accessing > SAAR registers") this header is not needed. > > Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Jiaxun Yang > --- > target/mips/tcg/sysemu/cp0_helper.c | 1 - > 1 file changed, 1 deletion(-) > > diff --git a/target/mips/tcg/sysemu/cp0_helper.c > b/target/mips/tcg/sysemu/cp0_helper.c > index ded6c78e9a..79a5c833ce 100644 > --- a/target/mips/tcg/sysemu/cp0_helper.c > +++ b/target/mips/tcg/sysemu/cp0_helper.c > @@ -28,7 +28,6 @@ > #include "qemu/host-utils.h" > #include "exec/helper-proto.h" > #include "exec/exec-all.h" > -#include "hw/misc/mips_itu.h" > > > /* SMP helpers. */ > -- > 2.41.0 -- - Jiaxun
[PATCH 2/4] hw/m68k/virt: Add fw_cfg controller
Add a fw_cfg controller to pass essential information to firmware. Signed-off-by: Jiaxun Yang --- hw/m68k/Kconfig | 1 + hw/m68k/virt.c| 25 ++- include/standard-headers/asm-m68k/bootinfo-virt.h | 1 + 3 files changed, 26 insertions(+), 1 deletion(-) diff --git a/hw/m68k/Kconfig b/hw/m68k/Kconfig index 66e63cd60b57..4501da56ff6d 100644 --- a/hw/m68k/Kconfig +++ b/hw/m68k/Kconfig @@ -40,6 +40,7 @@ config M68K_VIRT default y depends on M68K select M68K_IRQC +select FW_CFG_DMA select VIRT_CTRL select GOLDFISH_PIC select GOLDFISH_TTY diff --git a/hw/m68k/virt.c b/hw/m68k/virt.c index 7b3917dcbd2b..7590e6515ac3 100644 --- a/hw/m68k/virt.c +++ b/hw/m68k/virt.c @@ -42,7 +42,8 @@ * CPU IRQ #1 -> PIC #1 * IRQ #1 -> virt-ctrl * IRQ #2 -> xhci - * IRQ #3 to IRQ #31 -> unused + * IRQ #3 -> fw_cfg + * IRQ #4 to IRQ #31 -> unused * IRQ #32 -> goldfish-tty * CPU IRQ #2 -> PIC #2 * IRQ #1 to IRQ #32 -> virtio-mmio from 1 to 32 @@ -80,6 +81,10 @@ #define VIRT_CTRL_MMIO_BASE 0xff009000/* MMIO: 0xff009000 - 0xff009fff */ #define VIRT_CTRL_IRQ_BASE PIC_IRQ(1, 1) /* PIC: #1, IRQ: #1 */ +/* 1 fw_cfg */ +#define VIRT_FW_CFG_MMIO_BASE 0xff00a000/* MMIO: 0xff00a000 - 0xff00afff */ +#define VIRT_FW_CFG_IRQ_BASE PIC_IRQ(1, 3) /* PIC: #1, IRQ: #3 */ + /* * virtio-mmio size is 0x200 bytes * we use 4 goldfish-pic to attach them, @@ -116,6 +121,12 @@ static void rerandomize_rng_seed(void *opaque) be16_to_cpu(*(uint16_t *)rng_seed->data)); } +static void fw_cfg_boot_set(void *opaque, const char *boot_device, +Error **errp) +{ +fw_cfg_modify_i16(opaque, FW_CFG_BOOT_DEVICE, boot_device[0]); +} + static void virt_init(MachineState *machine) { M68kCPU *cpu = NULL; @@ -134,6 +145,7 @@ static void virt_init(MachineState *machine) SysBusDevice *sysbus; hwaddr io_base; int i; +FWCfgState *fw_cfg; ResetInfo *reset_info; uint8_t rng_seed[32]; @@ -210,6 +222,15 @@ static void virt_init(MachineState *machine) dev = sysbus_create_simple(TYPE_VIRT_CTRL, VIRT_CTRL_MMIO_BASE, PIC_GPIO(VIRT_CTRL_IRQ_BASE)); +/* fw_cfg */ +fw_cfg = fw_cfg_init_mem_wide(VIRT_FW_CFG_MMIO_BASE + 8, + VIRT_FW_CFG_MMIO_BASE, 8, + VIRT_FW_CFG_MMIO_BASE + 16, + _space_memory); +fw_cfg_add_i64(fw_cfg, FW_CFG_RAM_SIZE, (uint64_t)ram_size); +qemu_register_boot_set(fw_cfg_boot_set, fw_cfg); +rom_set_fw(fw_cfg); + /* virtio-mmio */ io_base = VIRT_VIRTIO_MMIO_BASE; for (i = 0; i < 128; i++) { @@ -288,6 +309,8 @@ static void virt_init(MachineState *machine) BOOTINFO2(param_ptr, BI_VIRT_XHCI_BASE, VIRT_XHCI_MMIO_BASE, VIRT_XHCI_IRQ_BASE); } +BOOTINFO2(param_ptr, BI_VIRT_FW_CFG_BASE, + VIRT_FW_CFG_MMIO_BASE, VIRT_FW_CFG_IRQ_BASE); if (kernel_cmdline) { BOOTINFOSTR(param_ptr, BI_COMMAND_LINE, diff --git a/include/standard-headers/asm-m68k/bootinfo-virt.h b/include/standard-headers/asm-m68k/bootinfo-virt.h index 1700c3ada765..7f90be1aa7bd 100644 --- a/include/standard-headers/asm-m68k/bootinfo-virt.h +++ b/include/standard-headers/asm-m68k/bootinfo-virt.h @@ -17,6 +17,7 @@ * #define BI_VIRT_RNG_SEED0x8006 */ #define BI_VIRT_XHCI_BASE 0x8007 +#define BI_VIRT_FW_CFG_BASE0x8008 #define VIRT_BOOTI_VERSION MK_BI_VERSION(2, 0) -- 2.43.0
[PATCH 3/4] hw/m68k/virt: Add a pflash controller for BIOS firmware
Add a 8 MiB pflash controller for BIOS firmware, and boot from it if possible. Signed-off-by: Jiaxun Yang --- hw/m68k/Kconfig | 1 + hw/m68k/virt.c| 44 +++ include/standard-headers/asm-m68k/bootinfo-virt.h | 1 + 3 files changed, 46 insertions(+) diff --git a/hw/m68k/Kconfig b/hw/m68k/Kconfig index 4501da56ff6d..f233a5948f19 100644 --- a/hw/m68k/Kconfig +++ b/hw/m68k/Kconfig @@ -42,6 +42,7 @@ config M68K_VIRT select M68K_IRQC select FW_CFG_DMA select VIRT_CTRL +select PFLASH_CFI01 select GOLDFISH_PIC select GOLDFISH_TTY select GOLDFISH_RTC diff --git a/hw/m68k/virt.c b/hw/m68k/virt.c index 7590e6515ac3..a2eebc0f2243 100644 --- a/hw/m68k/virt.c +++ b/hw/m68k/virt.c @@ -8,6 +8,7 @@ */ #include "qemu/osdep.h" +#include "qemu/datadir.h" #include "qemu/units.h" #include "qemu/guest-random.h" #include "sysemu/sysemu.h" @@ -28,6 +29,7 @@ #include "sysemu/runstate.h" #include "sysemu/reset.h" +#include "hw/block/flash.h" #include "hw/intc/m68k_irqc.h" #include "hw/misc/virt_ctrl.h" #include "hw/char/goldfish_tty.h" @@ -97,6 +99,10 @@ #define VIRT_XHCI_MMIO_BASE 0xff02/* MMIO: 0xff02 - 0xff023fff */ #define VIRT_XHCI_IRQ_BASE PIC_IRQ(1, 2) /* PIC: #1, IRQ: #2 */ +#define VIRT_PFLASH_MMIO_BASE 0xff80 /* MMIO: 0xff80 - 0x */ +#define VIRT_PFLASH_SIZE 0x80/* 8 MiB */ +#define VIRT_PFLASH_SECTOR_SIZE (128 * KiB) /* 64 KiB */ + typedef struct { M68kCPU *cpu; hwaddr initial_pc; @@ -139,6 +145,7 @@ static void virt_init(MachineState *machine) const char *initrd_filename = machine->initrd_filename; const char *kernel_cmdline = machine->kernel_cmdline; hwaddr parameters_base; +DriveInfo *dinfo; DeviceState *dev; DeviceState *irqc_dev; DeviceState *pic_dev[VIRT_GF_PIC_NB]; @@ -165,6 +172,8 @@ static void virt_init(MachineState *machine) cpu = M68K_CPU(cpu_create(machine->cpu_type)); reset_info->cpu = cpu; +reset_info->initial_pc = VIRT_PFLASH_MMIO_BASE; +reset_info->initial_stack = ram_size; qemu_register_reset(main_cpu_reset, reset_info); /* RAM */ @@ -253,6 +262,39 @@ static void virt_init(MachineState *machine) PIC_GPIO(VIRT_XHCI_IRQ_BASE)); } +/* pflash */ +dinfo = drive_get(IF_PFLASH, 0, 0); +pflash_cfi01_register(VIRT_PFLASH_MMIO_BASE, + "virt.pflash0", + VIRT_PFLASH_SIZE, + dinfo ? blk_by_legacy_dinfo(dinfo) : NULL, + VIRT_PFLASH_SECTOR_SIZE, 4, + 0x89, 0x18, 0, 0, 1); + +if (machine->firmware) { +char *fn; +int image_size; + +if (drive_get(IF_PFLASH, 0, 0)) { +error_report("The contents of the first flash device may be " + "specified with -bios or with -drive if=pflash... " + "but you cannot use both options at once"); +exit(1); +} +fn = qemu_find_file(QEMU_FILE_TYPE_BIOS, machine->firmware); +if (!fn) { +error_report("Could not find ROM image '%s'", machine->firmware); +exit(1); +} +image_size = load_image_targphys(fn, VIRT_PFLASH_MMIO_BASE, + VIRT_PFLASH_SIZE); +g_free(fn); +if (image_size < 0) { +error_report("Could not load ROM image '%s'", machine->firmware); +exit(1); +} +} + if (kernel_filename) { CPUState *cs = CPU(cpu); uint64_t high; @@ -311,6 +353,8 @@ static void virt_init(MachineState *machine) } BOOTINFO2(param_ptr, BI_VIRT_FW_CFG_BASE, VIRT_FW_CFG_MMIO_BASE, VIRT_FW_CFG_IRQ_BASE); +BOOTINFO2(param_ptr, BI_VIRT_PFLASH_BASE, +VIRT_PFLASH_MMIO_BASE, 0); if (kernel_cmdline) { BOOTINFOSTR(param_ptr, BI_COMMAND_LINE, diff --git a/include/standard-headers/asm-m68k/bootinfo-virt.h b/include/standard-headers/asm-m68k/bootinfo-virt.h index 7f90be1aa7bd..21c9a98d2912 100644 --- a/include/standard-headers/asm-m68k/bootinfo-virt.h +++ b/include/standard-headers/asm-m68k/bootinfo-virt.h @@ -18,6 +18,7 @@ #define BI_VIRT_XHCI_BASE 0x8007 #define BI_VIRT_FW_CFG_BASE0x8008 +#define BI_VIRT_PFLASH_BASE0x8009 #define VIRT_BOOTI_VERSION MK_BI_VERSION(2, 0) -- 2.43.0
[PATCH 1/4] hw/m68k/virt: Add a XHCI controller
VirtIO is somewhat limited on the diversity of devices. We lack proper audio, webcam and so on support on m68k virt machine. This can be improved by providing a XHCI controller, which enables provision of many different discoverable devices. Signed-off-by: Jiaxun Yang --- hw/m68k/Kconfig | 1 + hw/m68k/virt.c| 22 +- include/standard-headers/asm-m68k/bootinfo-virt.h | 2 ++ 3 files changed, 24 insertions(+), 1 deletion(-) diff --git a/hw/m68k/Kconfig b/hw/m68k/Kconfig index 0092cda4e9c8..66e63cd60b57 100644 --- a/hw/m68k/Kconfig +++ b/hw/m68k/Kconfig @@ -44,4 +44,5 @@ config M68K_VIRT select GOLDFISH_PIC select GOLDFISH_TTY select GOLDFISH_RTC +select USB_XHCI_SYSBUS select VIRTIO_MMIO diff --git a/hw/m68k/virt.c b/hw/m68k/virt.c index 09bc9bdfefb2..7b3917dcbd2b 100644 --- a/hw/m68k/virt.c +++ b/hw/m68k/virt.c @@ -33,13 +33,16 @@ #include "hw/char/goldfish_tty.h" #include "hw/rtc/goldfish_rtc.h" #include "hw/intc/goldfish_pic.h" +#include "hw/usb/hcd-xhci-sysbus.h" #include "hw/virtio/virtio-mmio.h" #include "hw/virtio/virtio-blk.h" /* * 6 goldfish-pic for CPU IRQ #1 to IRQ #6 * CPU IRQ #1 -> PIC #1 - * IRQ #1 to IRQ #31 -> unused + * IRQ #1 -> virt-ctrl + * IRQ #2 -> xhci + * IRQ #3 to IRQ #31 -> unused * IRQ #32 -> goldfish-tty * CPU IRQ #2 -> PIC #2 * IRQ #1 to IRQ #32 -> virtio-mmio from 1 to 32 @@ -86,6 +89,9 @@ #define VIRT_VIRTIO_MMIO_BASE 0xff01 /* MMIO: 0xff01 - 0xff01 */ #define VIRT_VIRTIO_IRQ_BASE PIC_IRQ(2, 1) /* PIC: 2, 3, 4, 5, IRQ: ALL */ +#define VIRT_XHCI_MMIO_BASE 0xff02/* MMIO: 0xff02 - 0xff023fff */ +#define VIRT_XHCI_IRQ_BASE PIC_IRQ(1, 2) /* PIC: #1, IRQ: #2 */ + typedef struct { M68kCPU *cpu; hwaddr initial_pc; @@ -216,6 +222,16 @@ static void virt_init(MachineState *machine) io_base += 0x200; } +/* xhci */ +if (machine_usb(machine)) { +dev = qdev_new(TYPE_XHCI_SYSBUS); +qdev_prop_set_uint32(dev, "intrs", 1); +sysbus_realize(SYS_BUS_DEVICE(dev), _fatal); +sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, VIRT_XHCI_MMIO_BASE); +sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, +PIC_GPIO(VIRT_XHCI_IRQ_BASE)); +} + if (kernel_filename) { CPUState *cs = CPU(cpu); uint64_t high; @@ -268,6 +284,10 @@ static void virt_init(MachineState *machine) VIRT_CTRL_MMIO_BASE, VIRT_CTRL_IRQ_BASE); BOOTINFO2(param_ptr, BI_VIRT_VIRTIO_BASE, VIRT_VIRTIO_MMIO_BASE, VIRT_VIRTIO_IRQ_BASE); +if (machine_usb(machine)) { +BOOTINFO2(param_ptr, BI_VIRT_XHCI_BASE, +VIRT_XHCI_MMIO_BASE, VIRT_XHCI_IRQ_BASE); +} if (kernel_cmdline) { BOOTINFOSTR(param_ptr, BI_COMMAND_LINE, diff --git a/include/standard-headers/asm-m68k/bootinfo-virt.h b/include/standard-headers/asm-m68k/bootinfo-virt.h index 75ac6bbd7d73..1700c3ada765 100644 --- a/include/standard-headers/asm-m68k/bootinfo-virt.h +++ b/include/standard-headers/asm-m68k/bootinfo-virt.h @@ -16,6 +16,8 @@ /* No longer used -- replaced with BI_RNG_SEED -- but don't reuse this index: * #define BI_VIRT_RNG_SEED0x8006 */ +#define BI_VIRT_XHCI_BASE 0x8007 + #define VIRT_BOOTI_VERSION MK_BI_VERSION(2, 0) #endif /* _UAPI_ASM_M68K_BOOTINFO_MAC_H */ -- 2.43.0
[PATCH 0/4] hw/m68k/virt: Add some devices
Hi all, This series added some devices that I found lacking when I was trying to port U-Boot to m68k virt machine. Please review. Thanks Signed-off-by: Jiaxun Yang --- Jiaxun Yang (4): hw/m68k/virt: Add a XHCI controller hw/m68k/virt: Add fw_cfg controller hw/m68k/virt: Add a pflash controller for BIOS firmware hw/m68k/virt: Supply bootinfo for BIOS hw/m68k/Kconfig | 3 + hw/m68k/virt.c| 231 -- include/standard-headers/asm-m68k/bootinfo-virt.h | 4 + 3 files changed, 176 insertions(+), 62 deletions(-) --- base-commit: 60b54b67c63d8f076152e0f7dccf39854dfc6a77 change-id: 20240527-m68k-bios-a0a2370181f5 Best regards, -- Jiaxun Yang
[PATCH 4/4] hw/m68k/virt: Supply bootinfo for BIOS
We follow common function split between BIOS and QEMU loader, When BIOS firmware is available QEMU does not load kernel/initrd binary to memory, instead BIOS retrieve those binaries from fw_cfg. A stripped version of bootinfo is placed at 1 KiB position of memory. This allows BIOS to probe board level information. It does not contain any booting related information (kernel, initrd, cmdline, random). Signed-off-by: Jiaxun Yang --- hw/m68k/virt.c | 160 - 1 file changed, 90 insertions(+), 70 deletions(-) diff --git a/hw/m68k/virt.c b/hw/m68k/virt.c index a2eebc0f2243..ea7a1bb430fc 100644 --- a/hw/m68k/virt.c +++ b/hw/m68k/virt.c @@ -138,13 +138,16 @@ static void virt_init(MachineState *machine) M68kCPU *cpu = NULL; int32_t kernel_size; uint64_t elf_entry; -ram_addr_t initrd_base; -int32_t initrd_size; +ram_addr_t initrd_base = 0; +int32_t initrd_size = 0; +int32_t bootinfo_size; +bool bios_loaded = false; ram_addr_t ram_size = machine->ram_size; const char *kernel_filename = machine->kernel_filename; const char *initrd_filename = machine->initrd_filename; const char *kernel_cmdline = machine->kernel_cmdline; -hwaddr parameters_base; +void *param_blob, *param_ptr, *param_rng_seed = NULL; +hwaddr parameters_base = 1 * KiB; DriveInfo *dinfo; DeviceState *dev; DeviceState *irqc_dev; @@ -264,6 +267,9 @@ static void virt_init(MachineState *machine) /* pflash */ dinfo = drive_get(IF_PFLASH, 0, 0); +if (dinfo) { +bios_loaded = true; +} pflash_cfi01_register(VIRT_PFLASH_MMIO_BASE, "virt.pflash0", VIRT_PFLASH_SIZE, @@ -293,18 +299,12 @@ static void virt_init(MachineState *machine) error_report("Could not load ROM image '%s'", machine->firmware); exit(1); } + +bios_loaded = true; } -if (kernel_filename) { -CPUState *cs = CPU(cpu); +if (kernel_filename && !bios_loaded) { uint64_t high; -void *param_blob, *param_ptr, *param_rng_seed; - -if (kernel_cmdline) { -param_blob = g_malloc(strlen(kernel_cmdline) + 1024); -} else { -param_blob = g_malloc(1024); -} kernel_size = load_elf(kernel_filename, NULL, NULL, NULL, _entry, NULL, , NULL, 1, @@ -315,57 +315,6 @@ static void virt_init(MachineState *machine) } reset_info->initial_pc = elf_entry; parameters_base = (high + 1) & ~1; -param_ptr = param_blob; - -BOOTINFO1(param_ptr, BI_MACHTYPE, MACH_VIRT); -if (m68k_feature(>env, M68K_FEATURE_M68020)) { -BOOTINFO1(param_ptr, BI_CPUTYPE, CPU_68020); -} else if (m68k_feature(>env, M68K_FEATURE_M68030)) { -BOOTINFO1(param_ptr, BI_MMUTYPE, MMU_68030); -BOOTINFO1(param_ptr, BI_CPUTYPE, CPU_68030); -} else if (m68k_feature(>env, M68K_FEATURE_M68040)) { -BOOTINFO1(param_ptr, BI_FPUTYPE, FPU_68040); -BOOTINFO1(param_ptr, BI_MMUTYPE, MMU_68040); -BOOTINFO1(param_ptr, BI_CPUTYPE, CPU_68040); -} else if (m68k_feature(>env, M68K_FEATURE_M68060)) { -BOOTINFO1(param_ptr, BI_FPUTYPE, FPU_68060); -BOOTINFO1(param_ptr, BI_MMUTYPE, MMU_68060); -BOOTINFO1(param_ptr, BI_CPUTYPE, CPU_68060); -} -BOOTINFO2(param_ptr, BI_MEMCHUNK, 0, ram_size); - -BOOTINFO1(param_ptr, BI_VIRT_QEMU_VERSION, - ((QEMU_VERSION_MAJOR << 24) | (QEMU_VERSION_MINOR << 16) | - (QEMU_VERSION_MICRO << 8))); -BOOTINFO2(param_ptr, BI_VIRT_GF_PIC_BASE, - VIRT_GF_PIC_MMIO_BASE, VIRT_GF_PIC_IRQ_BASE); -BOOTINFO2(param_ptr, BI_VIRT_GF_RTC_BASE, - VIRT_GF_RTC_MMIO_BASE, VIRT_GF_RTC_IRQ_BASE); -BOOTINFO2(param_ptr, BI_VIRT_GF_TTY_BASE, - VIRT_GF_TTY_MMIO_BASE, VIRT_GF_TTY_IRQ_BASE); -BOOTINFO2(param_ptr, BI_VIRT_CTRL_BASE, - VIRT_CTRL_MMIO_BASE, VIRT_CTRL_IRQ_BASE); -BOOTINFO2(param_ptr, BI_VIRT_VIRTIO_BASE, - VIRT_VIRTIO_MMIO_BASE, VIRT_VIRTIO_IRQ_BASE); -if (machine_usb(machine)) { -BOOTINFO2(param_ptr, BI_VIRT_XHCI_BASE, -VIRT_XHCI_MMIO_BASE, VIRT_XHCI_IRQ_BASE); -} -BOOTINFO2(param_ptr, BI_VIRT_FW_CFG_BASE, - VIRT_FW_CFG_MMIO_BASE, VIRT_FW_CFG_IRQ_BASE); -BOOTINFO2(param_ptr, BI_VIRT_PFLASH_BASE, -VIRT_PFLASH_MMIO_BASE, 0); - -if (kernel_cmdline) { -BOOTINFOSTR(param_ptr, BI_COMMAND_LINE, -kernel_cmdline); -} - -/* Pass seed to RNG. */ -param_rng_seed = param_ptr; -
Re: [PULL 10/10] hw/loongarch/virt: Fix FDT memory node address width
在2024年5月24日五月 上午11:10,Michael Tokarev写道: > 23.05.2024 04:46, Song Gao wrote: >> From: Jiaxun Yang >> >> Higher bits for memory nodes were omitted at qemu_fdt_setprop_cells. >> >> Cc: qemu-sta...@nongnu.org >> Signed-off-by: Jiaxun Yang >> Reviewed-by: Song Gao >> Message-Id: <20240520-loongarch-fdt-memnode-v1-1-5ea9be939...@flygoat.com> >> Signed-off-by: Song Gao >> --- >> hw/loongarch/virt.c | 3 ++- >> 1 file changed, 2 insertions(+), 1 deletion(-) >> >> diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c >> index e3bdf085b5..3e6e93edf3 100644 >> --- a/hw/loongarch/virt.c >> +++ b/hw/loongarch/virt.c >> @@ -464,7 +464,8 @@ static void fdt_add_memory_node(MachineState *ms, >> char *nodename = g_strdup_printf("/memory@%" PRIx64, base); >> >> qemu_fdt_add_subnode(ms->fdt, nodename); >> -qemu_fdt_setprop_cells(ms->fdt, nodename, "reg", 0, base, 0, size); >> +qemu_fdt_setprop_cells(ms->fdt, nodename, "reg", base >> 32, base, >> + size >> 32, size); >> qemu_fdt_setprop_string(ms->fdt, nodename, "device_type", "memory"); >> >> if (ms->numa_state && ms->numa_state->num_nodes) { > > This commit changes exactly the same place as the previous commit, > v9.0.0-274-gb11f981452, "hw/loongarch: Fix fdt memory node wrong 'reg'". > > Was it the wrong fix? Yes, I believe previous commit is the wrong fix on the same problem. > > Note the previous commit isn't in any released version of qemu. So > when picking up for any stable release, both needs to be picked up :) Please go ahead! Thanks - Jiaxun > > Thanks, > > /mjt > -- > GPG Key transition (from rsa2048 to rsa4096) since 2024-04-24. > New key: rsa4096/61AD3D98ECDF2C8E 9D8B E14E 3F2A 9DD7 9199 28F1 61AD > 3D98 ECDF 2C8E > Old key: rsa2048/457CE0A0804465C5 6EE1 95D1 886E 8FFB 810D 4324 457C > E0A0 8044 65C5 > Transition statement: http://www.corpit.ru/mjt/gpg-transition-2024.txt -- - Jiaxun
Re: [PATCH v3 0/3] Add extioi virt extension support
在2024年5月21日五月 下午1:32,Song Gao写道: > On LoongArch, IRQs can be routed to four vcpus with hardware extioi. > This patch adds the extioi virt extension support so that the IRQ can > route to 256 vcpus. Hi Song, Sorry for chime in here, I'm a little bit confused by this series, can you give me a little bit of context behind? I don't see this functionality on 3A5000/3A6000's user manual, so is this some sort of undocumented hardware feature? I checked openEuler kernel patch you referred, it seems like this applies to hypervisor mode only. I suppose it should be handled by KVM subsystem in kernel, why do we need this in user mode device emulation? Currently, LoongArch's in-kernel irqchip functionality does not include such feature, can we see KVM side support for this, or at least a draft specification? Thanks - Jiaxun > > v3: > - Split patch2 to two small patch. > - remove unused code. > - loongarch_extioi_reset() clear status without checking virt extioi > features. > - Link to v2: > https://patchew.org/QEMU/20240514090756.988096-1-gaos...@loongson.cn/ > > v2: > - Split the patch to two small patch. > - Drop 'RFC' title. extioi virt extension suport only enable on kvm > mode and the extioi driver need patch[1]. > but this series do not affect the old codes in any way. > - Link to v1: > https://lore.kernel.org/all/20240116022526.498613-1-gaos...@loongson.cn/#r > > [1]: > https://gitee.com/openeuler/kernel/commit/5d97cff72f91f4f20a536efd60eca75bfcb78a64 > > Thanks. > Song Gao > > Song Gao (3): > hw/intc/loongarch_extioi: Add extioi virt extension definition > hw/loongarch/virt: Enable extioi virt extension > hw/loongarch/virt: Use MemTxAttrs interface for misc ops > > include/hw/intc/loongarch_extioi.h | 21 ++ > include/hw/loongarch/virt.h| 2 + > target/loongarch/cpu.h | 1 + > hw/intc/loongarch_extioi.c | 88 +- > hw/loongarch/virt.c| 116 + > 5 files changed, 210 insertions(+), 18 deletions(-) > > -- > 2.34.1 -- - Jiaxun
[PATCH] hw/loongarch/virt: Fix FDT memory node address width
Higher bits for memory nodes were omitted at qemu_fdt_setprop_cells. Signed-off-by: Jiaxun Yang --- This should be stable backported, otherwise DT boot is totally broken. --- hw/loongarch/virt.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c index f0640d2d8035..f97626bacf65 100644 --- a/hw/loongarch/virt.c +++ b/hw/loongarch/virt.c @@ -463,7 +463,8 @@ static void fdt_add_memory_node(MachineState *ms, char *nodename = g_strdup_printf("/memory@%" PRIx64, base); qemu_fdt_add_subnode(ms->fdt, nodename); -qemu_fdt_setprop_cells(ms->fdt, nodename, "reg", 0, base, 0, size); +qemu_fdt_setprop_cells(ms->fdt, nodename, "reg", base >> 32, base, + size >> 32, size); qemu_fdt_setprop_string(ms->fdt, nodename, "device_type", "memory"); if (ms->numa_state && ms->numa_state->num_nodes) { --- base-commit: 85ef20f1673feaa083f4acab8cf054df77b0dbed change-id: 20240520-loongarch-fdt-memnode-e36c01ae9b6e Best regards, -- Jiaxun Yang
Re: [PATCH 0/5] hw/mips/loongson3_virt: Implement IPI support
在2024年5月8日五月 下午10:41,Philippe Mathieu-Daudé写道: > On 8/5/24 15:06, Jiaxun Yang wrote: >> Hi all, >> >> This series enabled IPI support for loongson3 virt board, loosely >> based on my previous work[1]. >> It generalized loongarch_ipi device to share among both loongarch >> and MIPS machines. > > >> Signed-off-by: Jiaxun Yang >> --- >> Jiaxun Yang (5): >>hw/intc/loongarch_ipi: Remove pointless MAX_CPU check >>hw/intc/loongarch_ipi: Rename as loongson_ipi >>hw/intc/loongson_ipi: Implement IOCSR address space for MIPS > > So far patches 1-3 queued to hw-misc tree, thanks. Hi Philippe, Thanks! What's your plan with the rest of the series and earlier MIPS CPS SMP series? Let me know if you need help on testing etc. Thanks -- - Jiaxun
[PATCH] hw/mips/loongson3_virt: Implement node counter timer
Node counter is a timer presents on Loongson-3 chips, which runs as fast as CPU clock. It's being mapped into a MMIO location. Emulate this for loongson3_virt machine, in hope that kernel can use it as a better clock source. Hardware's behavior on 32-bit read/write is also emulated in case legacy kernel is trying to use it with hi/lo splitted read. Signed-off-by: Jiaxun Yang --- hw/mips/loongson3_bootp.h | 1 + hw/mips/loongson3_virt.c | 38 ++ 2 files changed, 35 insertions(+), 4 deletions(-) diff --git a/hw/mips/loongson3_bootp.h b/hw/mips/loongson3_bootp.h index 1b0dd3b59171..c6a435397d2c 100644 --- a/hw/mips/loongson3_bootp.h +++ b/hw/mips/loongson3_bootp.h @@ -210,6 +210,7 @@ enum { VIRT_PCIE_ECAM, VIRT_BIOS_ROM, VIRT_UART, +VIRT_NODECNT, VIRT_LIOINTC, VIRT_PCIE_MMIO, VIRT_HIGHMEM diff --git a/hw/mips/loongson3_virt.c b/hw/mips/loongson3_virt.c index b10a611a98f4..b78ac8032096 100644 --- a/hw/mips/loongson3_virt.c +++ b/hw/mips/loongson3_virt.c @@ -74,6 +74,7 @@ const MemMapEntry virt_memmap[] = { [VIRT_PCIE_ECAM] = { 0x1a00, 0x200 }, [VIRT_BIOS_ROM] ={ 0x1fc0, 0x20 }, [VIRT_UART] ={ 0x1fe001e0, 0x8 }, +[VIRT_NODECNT] = { 0x3ff00408, 0x8 }, [VIRT_LIOINTC] = { 0x3ff01400, 0x64 }, [VIRT_PCIE_MMIO] = { 0x4000,0x4000 }, [VIRT_HIGHMEM] = { 0x8000, 0x0 }, /* Variable */ @@ -92,6 +93,7 @@ static const MemMapEntry loader_rommap[] = { struct LoongsonMachineState { MachineState parent_obj; +Clock *cpuclk; MemoryRegion *pio_alias; MemoryRegion *mmio_alias; MemoryRegion *ecam_alias; @@ -145,6 +147,29 @@ static const MemoryRegionOps loongson3_pm_ops = { } }; +static uint64_t loongson3_nodecnt_read(void *opaque, +hwaddr addr, unsigned size) +{ +LoongsonMachineState *s = opaque; +int64_t now_ns = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); +uint64_t ticks = clock_ns_to_ticks(s->cpuclk, now_ns); + +if (addr == 0x4) { +return ticks >> 32; +} + +return ticks; +} + +static const MemoryRegionOps loongson3_nodecnt_ops = { +.read = loongson3_nodecnt_read, +.endianness = DEVICE_NATIVE_ENDIAN, +.valid.min_access_size = 4, +.valid.max_access_size = 8, +.impl.min_access_size = 4, +.impl.max_access_size = 8, +}; + #define DEF_LOONGSON3_FREQ (800 * 1000 * 1000) static uint64_t get_cpu_freq_hz(void) @@ -463,7 +488,6 @@ static void mips_loongson3_virt_init(MachineState *machine) int i; long bios_size; MIPSCPU *cpu; -Clock *cpuclk; CPUMIPSState *env; DeviceState *liointc; char *filename; @@ -471,10 +495,12 @@ static void mips_loongson3_virt_init(MachineState *machine) const char *kernel_filename = machine->kernel_filename; const char *initrd_filename = machine->initrd_filename; ram_addr_t ram_size = machine->ram_size; +LoongsonMachineState *ms = LOONGSON_MACHINE(machine); MemoryRegion *address_space_mem = get_system_memory(); MemoryRegion *ram = g_new(MemoryRegion, 1); MemoryRegion *bios = g_new(MemoryRegion, 1); MemoryRegion *iomem = g_new(MemoryRegion, 1); +MemoryRegion *nodecnt = g_new(MemoryRegion, 1); /* TODO: TCG will support all CPU types */ if (!kvm_enabled()) { @@ -520,14 +546,14 @@ static void mips_loongson3_virt_init(MachineState *machine) sysbus_create_simple("goldfish_rtc", virt_memmap[VIRT_RTC].base, qdev_get_gpio_in(liointc, RTC_IRQ)); -cpuclk = clock_new(OBJECT(machine), "cpu-refclk"); -clock_set_hz(cpuclk, DEF_LOONGSON3_FREQ); +ms->cpuclk = clock_new(OBJECT(machine), "cpu-refclk"); +clock_set_hz(ms->cpuclk, DEF_LOONGSON3_FREQ); for (i = 0; i < machine->smp.cpus; i++) { int ip; /* init CPUs */ -cpu = mips_cpu_create_with_clock(machine->cpu_type, cpuclk); +cpu = mips_cpu_create_with_clock(machine->cpu_type, ms->cpuclk); /* Init internal devices */ cpu_mips_irq_init_cpu(cpu); @@ -553,6 +579,8 @@ static void mips_loongson3_virt_init(MachineState *machine) machine->ram, 0, virt_memmap[VIRT_LOWMEM].size); memory_region_init_io(iomem, NULL, _pm_ops, NULL, "loongson3_pm", virt_memmap[VIRT_PM].size); +memory_region_init_io(nodecnt, NULL, _nodecnt_ops, ms, + "loongson3_nodecnt", virt_memmap[VIRT_NODECNT].size); memory_region_add_subregion(address_space_mem, virt_memmap[VIRT_LOWMEM].base, ram); @@ -562,6 +590,8 @@ static void mips_loongson3_virt_init(MachineState *machine) virt_memmap[VIRT_HIGHMEM].base, machine->ram); memory_
[PATCH] mips64el-softmmu: Enable MTTCG
MTTCG was disabled in a092a9554771 ("configure: disable MTTCG for MIPS guests") due to test case instability. I was able to reproduce this issue with in latest QEMU and look into reason behind that. What actually happend is kernel's CP0 timer synchronisation mechanism assumed a consistent latency in memory access between cores, which TCG can't guarantee. Thus there is a huge drift in count value between cores, and in early kernel versions CP0 timer is always used as sched_clock. sched_clock drift back on some cores triggered RCU watchdog in some extreme cases. This can be resolved by setting clocksource to MIPS, which allows clocksource to drift together with sched_clock. However this will leed to other problems after boot. Another option would beupdating kernel to later version, which will use GIC as sched_clock. In non-MTTCG build, the execution is slow enough so kernel won't observe back drifts. Test results: With clocksource=MIPS ``` ~/tmp/retry/retry.py -n 100 -c -- ./qemu-system-mips64el \ -display none -vga none -serial mon:stdio \ -machine malta -kernel ./vmlinux-4.7.0-rc1.I6400 \ -cpu I6400 -smp 8 -vga std \ -append "printk.time=0 clocksource=MIPS console=tty0 console=ttyS0 panic=-1" \ --no-reboot 100, 0, PASS, 5.258126, 100, 100, - Results summary: 0: 100 times (100.00%), avg time 6.508 (55.53 varience/7.45 deviation) Ran command 100 times, 100 passes ``` With linux-next: ``` ~/tmp/retry/retry.py -n 100 -c -- ./qemu-system-mips64el \ -display none -vga none -serial mon:stdio \ -machine malta -kernel ~/linux-next/vmlinux \ -cpu I6400 -smp 8 -vga std \ -append "printk.time=0 console=tty0 console=ttyS0 panic=-1" \ --no-reboot 100, 0, PASS, 4.507921, 100, 100, - Results summary: 0: 100 times (100.00%), avg time 4.233 (0.04 varience/0.21 deviation) Ran command 100 times, 100 passes ``` Signed-off-by: Jiaxun Yang --- I'll leave the test case alone as it's already marked as QEMU_TEST_FLAKY_TESTS --- configs/targets/mips64el-softmmu.mak | 1 + 1 file changed, 1 insertion(+) diff --git a/configs/targets/mips64el-softmmu.mak b/configs/targets/mips64el-softmmu.mak index 8d9ab3ddc4b1..199b1d909a7d 100644 --- a/configs/targets/mips64el-softmmu.mak +++ b/configs/targets/mips64el-softmmu.mak @@ -1,3 +1,4 @@ TARGET_ARCH=mips64 TARGET_BASE_ARCH=mips +TARGET_SUPPORTS_MTTCG=y TARGET_NEED_FDT=y --- base-commit: 248f6f62df073a3b4158fd0093863ab885feabb5 change-id: 20240511-mips_mttcg-47a6b19074b3 Best regards, -- Jiaxun Yang
Re: [PATCH] hw/mips/loongson3_virt: Emulate suspend function
在2024年5月8日五月 下午5:48,Philippe Mathieu-Daudé写道: > On 8/5/24 17:35, Philippe Mathieu-Daudé wrote: >> On 8/5/24 11:31, Jiaxun Yang wrote: >>> Suspend function is emulated as what hardware actually do. >>> Doorbell register fields are updates to include suspend value, >>> suspend vector is encoded in firmware blob and fw_cfg is updated >>> to include S3 bits as what x86 did. >>> >>> Signed-off-by: Jiaxun Yang >>> --- >>> hw/mips/loongson3_bootp.c | 1 + >>> hw/mips/loongson3_virt.c | 19 +++ >>> 2 files changed, 20 insertions(+) >> >> Thanks, patch queued. > > Fixed: > > ERROR: use g_memdup2() instead of unsafe g_memdup() > #76: FILE: hw/mips/loongson3_virt.c:293: > +fw_cfg_add_file(fw_cfg, "etc/system-states", g_memdup(suspend, 6), 6); Thanks, I omitted this one as it is copied from hw/acpi/core.c Should we fix that one as well? -- - Jiaxun
[PATCH 0/5] hw/mips/loongson3_virt: Implement IPI support
Hi all, This series enabled IPI support for loongson3 virt board, loosely based on my previous work[1]. It generalized loongarch_ipi device to share among both loongarch and MIPS machines. Thanks [1]: https://lore.kernel.org/all/20230521102307.87081-1-jiaxun.y...@flygoat.com/ To: qemu-devel@nongnu.org Cc: Song Gao Signed-off-by: Jiaxun Yang --- Jiaxun Yang (5): hw/intc/loongarch_ipi: Remove pointless MAX_CPU check hw/intc/loongarch_ipi: Rename as loongson_ipi hw/intc/loongson_ipi: Implement IOCSR address space for MIPS hw/intc/loongson_ipi: Provide per core MMIO address spaces hw/mips/loongson3_virt: Wire up loongson_ipi device MAINTAINERS| 4 + hw/intc/Kconfig| 2 +- hw/intc/loongarch_ipi.c| 19 +- hw/intc/loongson_ipi.c | 411 + hw/intc/meson.build| 2 +- hw/intc/trace-events | 8 +- hw/loongarch/Kconfig | 2 +- hw/loongarch/virt.c| 4 +- hw/mips/Kconfig| 1 + hw/mips/loongson3_bootp.c | 2 - hw/mips/loongson3_bootp.h | 3 + hw/mips/loongson3_virt.c | 39 +- .../hw/intc/{loongarch_ipi.h => loongson_ipi.h}| 14 +- include/hw/loongarch/virt.h| 2 +- 14 files changed, 475 insertions(+), 38 deletions(-) --- base-commit: 248f6f62df073a3b4158fd0093863ab885feabb5 change-id: 20240508-loongson3-ipi-65e99b47c400 Best regards, -- Jiaxun Yang
[PATCH 5/5] hw/mips/loongson3_virt: Wire up loongson_ipi device
Wire up loongson_ipi device for loongson3_virt machine, so we can have SMP support for TCG backend as well. Signed-off-by: Jiaxun Yang --- hw/mips/Kconfig | 1 + hw/mips/loongson3_bootp.c | 2 -- hw/mips/loongson3_bootp.h | 3 +++ hw/mips/loongson3_virt.c | 39 +-- 4 files changed, 41 insertions(+), 4 deletions(-) diff --git a/hw/mips/Kconfig b/hw/mips/Kconfig index 5c83ef49cf6f..6f09fedc946e 100644 --- a/hw/mips/Kconfig +++ b/hw/mips/Kconfig @@ -57,6 +57,7 @@ config LOONGSON3V imply USB_OHCI_PCI select SERIAL select GOLDFISH_RTC +select LOONGSON_IPI select LOONGSON_LIOINTC select PCI_EXPRESS_GENERIC_BRIDGE select MSI_NONBROKEN diff --git a/hw/mips/loongson3_bootp.c b/hw/mips/loongson3_bootp.c index f99af229327a..474d3556b2e5 100644 --- a/hw/mips/loongson3_bootp.c +++ b/hw/mips/loongson3_bootp.c @@ -25,8 +25,6 @@ #include "hw/boards.h" #include "hw/mips/loongson3_bootp.h" -#define LOONGSON3_CORE_PER_NODE 4 - static void init_cpu_info(void *g_cpuinfo, uint64_t cpu_freq) { struct efi_cpuinfo_loongson *c = g_cpuinfo; diff --git a/hw/mips/loongson3_bootp.h b/hw/mips/loongson3_bootp.h index 1b0dd3b59171..9091265df7fc 100644 --- a/hw/mips/loongson3_bootp.h +++ b/hw/mips/loongson3_bootp.h @@ -200,6 +200,8 @@ struct boot_params { struct efi_reset_system_t reset_system; }; +#define LOONGSON3_CORE_PER_NODE 4 + /* Overall MMIO & Memory layout */ enum { VIRT_LOWMEM, @@ -211,6 +213,7 @@ enum { VIRT_BIOS_ROM, VIRT_UART, VIRT_LIOINTC, +VIRT_IPI, VIRT_PCIE_MMIO, VIRT_HIGHMEM }; diff --git a/hw/mips/loongson3_virt.c b/hw/mips/loongson3_virt.c index b10a611a98f4..1052fb7d6747 100644 --- a/hw/mips/loongson3_virt.c +++ b/hw/mips/loongson3_virt.c @@ -36,6 +36,7 @@ #include "hw/mips/loongson3_bootp.h" #include "hw/misc/unimp.h" #include "hw/intc/i8259.h" +#include "hw/intc/loongson_ipi.h" #include "hw/loader.h" #include "hw/isa/superio.h" #include "hw/pci/msi.h" @@ -74,6 +75,7 @@ const MemMapEntry virt_memmap[] = { [VIRT_PCIE_ECAM] = { 0x1a00, 0x200 }, [VIRT_BIOS_ROM] ={ 0x1fc0, 0x20 }, [VIRT_UART] ={ 0x1fe001e0, 0x8 }, +[VIRT_IPI] = { 0x3ff01000, 0x400 }, [VIRT_LIOINTC] = { 0x3ff01400, 0x64 }, [VIRT_PCIE_MMIO] = { 0x4000,0x4000 }, [VIRT_HIGHMEM] = { 0x8000, 0x0 }, /* Variable */ @@ -466,6 +468,7 @@ static void mips_loongson3_virt_init(MachineState *machine) Clock *cpuclk; CPUMIPSState *env; DeviceState *liointc; +DeviceState *ipi = NULL; char *filename; const char *kernel_cmdline = machine->kernel_cmdline; const char *kernel_filename = machine->kernel_filename; @@ -475,6 +478,7 @@ static void mips_loongson3_virt_init(MachineState *machine) MemoryRegion *ram = g_new(MemoryRegion, 1); MemoryRegion *bios = g_new(MemoryRegion, 1); MemoryRegion *iomem = g_new(MemoryRegion, 1); +MemoryRegion *iocsr = g_new(MemoryRegion, 1); /* TODO: TCG will support all CPU types */ if (!kvm_enabled()) { @@ -508,6 +512,19 @@ static void mips_loongson3_virt_init(MachineState *machine) create_unimplemented_device("mmio fallback 0", 0x1000, 256 * MiB); create_unimplemented_device("mmio fallback 1", 0x3000, 256 * MiB); +memory_region_init(iocsr, OBJECT(machine), "loongson3.iocsr", UINT32_MAX); + +/* IPI controller is in kernel for KVM */ +if (!kvm_enabled()) { +ipi = qdev_new(TYPE_LOONGSON_IPI); +qdev_prop_set_uint32(ipi, "num-cpu", machine->smp.cpus); +sysbus_realize_and_unref(SYS_BUS_DEVICE(ipi), _fatal); +memory_region_add_subregion(iocsr, SMP_IPI_MAILBOX, +sysbus_mmio_get_region(SYS_BUS_DEVICE(ipi), 0)); +memory_region_add_subregion(iocsr, MAIL_SEND_ADDR, +sysbus_mmio_get_region(SYS_BUS_DEVICE(ipi), 1)); +} + liointc = qdev_new("loongson.liointc"); sysbus_realize_and_unref(SYS_BUS_DEVICE(liointc), _fatal); @@ -524,6 +541,8 @@ static void mips_loongson3_virt_init(MachineState *machine) clock_set_hz(cpuclk, DEF_LOONGSON3_FREQ); for (i = 0; i < machine->smp.cpus; i++) { +int node = i / LOONGSON3_CORE_PER_NODE; +int core = i % LOONGSON3_CORE_PER_NODE; int ip; /* init CPUs */ @@ -534,12 +553,28 @@ static void mips_loongson3_virt_init(MachineState *machine) cpu_mips_clock_init(cpu); qemu_register_reset(main_cpu_reset, cpu); -if (i >= 4) { +if (ipi) { +hwaddr base = ((hwaddr)node << 44) + virt_memmap[VIRT_IPI].base; +base += core * 0x100; +qdev_connect_gpio_out(ipi, i, cpu->env.irq[6]); +sysbu
[PATCH 4/5] hw/intc/loongson_ipi: Provide per core MMIO address spaces
The real IPI hardware have dedicated MMIO registers mapped into memory address space for every core. This is not used by LoongArch guest software but it is essential for CPU without IOCSR such as Loongson-3A1000. Implement it with existing infrastructure. Signed-off-by: Jiaxun Yang --- hw/intc/loongson_ipi.c | 81 -- include/hw/intc/loongson_ipi.h | 2 ++ 2 files changed, 64 insertions(+), 19 deletions(-) diff --git a/hw/intc/loongson_ipi.c b/hw/intc/loongson_ipi.c index 93cc50a37a11..c8a25b4eb8e2 100644 --- a/hw/intc/loongson_ipi.c +++ b/hw/intc/loongson_ipi.c @@ -23,16 +23,14 @@ #endif #include "trace.h" -static MemTxResult loongson_ipi_readl(void *opaque, hwaddr addr, +static MemTxResult loongson_ipi_core_readl(void *opaque, hwaddr addr, uint64_t *data, unsigned size, MemTxAttrs attrs) { -IPICore *s; -LoongsonIPI *ipi = opaque; +IPICore *s = opaque; uint64_t ret = 0; int index = 0; -s = >cpu[attrs.requester_id]; addr &= 0xff; switch (addr) { case CORE_STATUS_OFF: @@ -61,6 +59,21 @@ static MemTxResult loongson_ipi_readl(void *opaque, hwaddr addr, return MEMTX_OK; } +static MemTxResult loongson_ipi_iocsr_readl(void *opaque, hwaddr addr, + uint64_t *data, + unsigned size, MemTxAttrs attrs) +{ +LoongsonIPI *ipi = opaque; +IPICore *s; + +if (attrs.requester_id >= ipi->num_cpu) { +return MEMTX_DECODE_ERROR; +} + +s = >cpu[attrs.requester_id]; +return loongson_ipi_core_readl(s, addr, data, size, attrs); +} + static AddressSpace *get_cpu_iocsr_as(CPUState *cpu) { #ifdef TARGET_LOONGARCH64 @@ -174,17 +187,17 @@ static MemTxResult any_send(uint64_t val, MemTxAttrs attrs) return send_ipi_data(cs, val, addr, attrs); } -static MemTxResult loongson_ipi_writel(void *opaque, hwaddr addr, uint64_t val, -unsigned size, MemTxAttrs attrs) +static MemTxResult loongson_ipi_core_writel(void *opaque, hwaddr addr, +uint64_t val, unsigned size, +MemTxAttrs attrs) { -LoongsonIPI *ipi = opaque; -IPICore *s; +IPICore *s = opaque; +LoongsonIPI *ipi = s->ipi; int index = 0; uint32_t cpuid; uint8_t vector; CPUState *cs; -s = >cpu[attrs.requester_id]; addr &= 0xff; trace_loongson_ipi_write(size, (uint64_t)addr, val); switch (addr) { @@ -215,13 +228,11 @@ static MemTxResult loongson_ipi_writel(void *opaque, hwaddr addr, uint64_t val, /* IPI status vector */ vector = extract8(val, 0, 5); cs = ipi_getcpu(cpuid); -if (cs == NULL) { +if (cs == NULL || cs->cpu_index >= ipi->num_cpu) { return MEMTX_DECODE_ERROR; } - -/* override requester_id */ -attrs.requester_id = cs->cpu_index; -loongson_ipi_writel(ipi, CORE_SET_OFF, BIT(vector), 4, attrs); +loongson_ipi_core_writel(>cpu[cs->cpu_index], CORE_SET_OFF, + BIT(vector), 4, attrs); break; default: qemu_log_mask(LOG_UNIMP, "invalid write: %x", (uint32_t)addr); @@ -231,9 +242,34 @@ static MemTxResult loongson_ipi_writel(void *opaque, hwaddr addr, uint64_t val, return MEMTX_OK; } -static const MemoryRegionOps loongson_ipi_ops = { -.read_with_attrs = loongson_ipi_readl, -.write_with_attrs = loongson_ipi_writel, +static MemTxResult loongson_ipi_iocsr_writel(void *opaque, hwaddr addr, +uint64_t val, unsigned size, +MemTxAttrs attrs) +{ +LoongsonIPI *ipi = opaque; +IPICore *s; + +if (attrs.requester_id >= ipi->num_cpu) { +return MEMTX_DECODE_ERROR; +} + +s = >cpu[attrs.requester_id]; +return loongson_ipi_core_writel(s, addr, val, size, attrs); +} + +static const MemoryRegionOps loongson_ipi_core_ops = { +.read_with_attrs = loongson_ipi_core_readl, +.write_with_attrs = loongson_ipi_core_writel, +.impl.min_access_size = 4, +.impl.max_access_size = 4, +.valid.min_access_size = 4, +.valid.max_access_size = 8, +.endianness = DEVICE_LITTLE_ENDIAN, +}; + +static const MemoryRegionOps loongson_ipi_iocsr_ops = { +.read_with_attrs = loongson_ipi_iocsr_readl, +.write_with_attrs = loongson_ipi_iocsr_writel, .impl.min_access_size = 4, .impl.max_access_size = 4, .valid.min_access_size = 4, @@ -282,7 +318,7 @@ static void loongson_ipi_realize(DeviceState *dev, Error **errp) return; } -memory_region_init_io(>ipi_iocsr_mem, OBJECT(dev), _ipi_ops, +memory_region_init_io(>ipi_iocsr_mem, OBJECT(
[PATCH 1/5] hw/intc/loongarch_ipi: Remove pointless MAX_CPU check
Since cpuid will be checked by ipi_getcpu anyway, there is no point to enforce MAX_CPU here. This also saved us from including loongarch board header. Signed-off-by: Jiaxun Yang --- hw/intc/loongarch_ipi.c | 19 ++- hw/intc/trace-events| 2 -- 2 files changed, 2 insertions(+), 19 deletions(-) diff --git a/hw/intc/loongarch_ipi.c b/hw/intc/loongarch_ipi.c index a184112b0923..44b3b9c138d6 100644 --- a/hw/intc/loongarch_ipi.c +++ b/hw/intc/loongarch_ipi.c @@ -6,6 +6,7 @@ */ #include "qemu/osdep.h" +#include "hw/boards.h" #include "hw/sysbus.h" #include "hw/intc/loongarch_ipi.h" #include "hw/irq.h" @@ -13,9 +14,8 @@ #include "qapi/error.h" #include "qemu/log.h" #include "exec/address-spaces.h" -#include "hw/loongarch/virt.h" #include "migration/vmstate.h" -#include "target/loongarch/internals.h" +#include "target/loongarch/cpu.h" #include "trace.h" static MemTxResult loongarch_ipi_readl(void *opaque, hwaddr addr, @@ -122,11 +122,6 @@ static MemTxResult mail_send(uint64_t val, MemTxAttrs attrs) CPUState *cs; cpuid = extract32(val, 16, 10); -if (cpuid >= LOONGARCH_MAX_CPUS) { -trace_loongarch_ipi_unsupported_cpuid("IOCSR_MAIL_SEND", cpuid); -return MEMTX_DECODE_ERROR; -} - cs = ipi_getcpu(cpuid); if (cs == NULL) { return MEMTX_DECODE_ERROR; @@ -146,11 +141,6 @@ static MemTxResult any_send(uint64_t val, MemTxAttrs attrs) CPUState *cs; cpuid = extract32(val, 16, 10); -if (cpuid >= LOONGARCH_MAX_CPUS) { -trace_loongarch_ipi_unsupported_cpuid("IOCSR_ANY_SEND", cpuid); -return MEMTX_DECODE_ERROR; -} - cs = ipi_getcpu(cpuid); if (cs == NULL) { return MEMTX_DECODE_ERROR; @@ -201,11 +191,6 @@ static MemTxResult loongarch_ipi_writel(void *opaque, hwaddr addr, uint64_t val, break; case IOCSR_IPI_SEND: cpuid = extract32(val, 16, 10); -if (cpuid >= LOONGARCH_MAX_CPUS) { -trace_loongarch_ipi_unsupported_cpuid("IOCSR_IPI_SEND", cpuid); -return MEMTX_DECODE_ERROR; -} - /* IPI status vector */ vector = extract8(val, 0, 5); cs = ipi_getcpu(cpuid); diff --git a/hw/intc/trace-events b/hw/intc/trace-events index 47340b5bc138..a979784f9bee 100644 --- a/hw/intc/trace-events +++ b/hw/intc/trace-events @@ -294,8 +294,6 @@ sh_intc_set(int id, int enable) "setting interrupt group %d to %d" # loongarch_ipi.c loongarch_ipi_read(unsigned size, uint64_t addr, uint64_t val) "size: %u addr: 0x%"PRIx64 "val: 0x%"PRIx64 loongarch_ipi_write(unsigned size, uint64_t addr, uint64_t val) "size: %u addr: 0x%"PRIx64 "val: 0x%"PRIx64 -loongarch_ipi_unsupported_cpuid(const char *s, uint32_t cpuid) "%s unsupported cpuid 0x%" PRIx32 - # loongarch_pch_pic.c loongarch_pch_pic_irq_handler(int irq, int level) "irq %d level %d" loongarch_pch_pic_low_readw(unsigned size, uint64_t addr, uint64_t val) "size: %u addr: 0x%"PRIx64 "val: 0x%" PRIx64 -- 2.34.1
[PATCH 2/5] hw/intc/loongarch_ipi: Rename as loongson_ipi
This device will be shared among LoongArch and MIPS based Loongson machine, rename it as loongson_ipi to reflect this nature. Signed-off-by: Jiaxun Yang --- MAINTAINERS| 4 + hw/intc/Kconfig| 2 +- hw/intc/loongson_ipi.c | 347 + hw/intc/meson.build| 2 +- hw/intc/trace-events | 6 +- hw/loongarch/Kconfig | 2 +- hw/loongarch/virt.c| 4 +- .../hw/intc/{loongarch_ipi.h => loongson_ipi.h}| 12 +- include/hw/loongarch/virt.h| 2 +- 9 files changed, 366 insertions(+), 15 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index 2f08cc528eb6..290dc3227baf 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1241,7 +1241,9 @@ F: configs/devices/loongarch64-softmmu/default.mak F: hw/loongarch/ F: include/hw/loongarch/virt.h F: include/hw/intc/loongarch_*.h +F: include/hw/intc/loongson_ipi.h F: hw/intc/loongarch_*.c +F: hw/intc/loongson_ipi.c F: include/hw/pci-host/ls7a.h F: hw/rtc/ls7a_rtc.c F: gdb-xml/loongarch*.xml @@ -1375,10 +1377,12 @@ Loongson-3 virtual platforms M: Huacai Chen R: Jiaxun Yang S: Maintained +F: hw/intc/loongson_ipi.c F: hw/intc/loongson_liointc.c F: hw/mips/loongson3_bootp.c F: hw/mips/loongson3_bootp.h F: hw/mips/loongson3_virt.c +F: include/hw/intc/loongson_ipi.h F: include/hw/intc/loongson_liointc.h F: tests/avocado/machine_mips_loongson3v.py diff --git a/hw/intc/Kconfig b/hw/intc/Kconfig index ad59abebaa1d..58b6d3a71003 100644 --- a/hw/intc/Kconfig +++ b/hw/intc/Kconfig @@ -87,7 +87,7 @@ config GOLDFISH_PIC config M68K_IRQC bool -config LOONGARCH_IPI +config LOONGSON_IPI bool config LOONGARCH_PCH_PIC diff --git a/hw/intc/loongson_ipi.c b/hw/intc/loongson_ipi.c new file mode 100644 index ..8c888da3b27c --- /dev/null +++ b/hw/intc/loongson_ipi.c @@ -0,0 +1,347 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Loongson ipi interrupt support + * + * Copyright (C) 2021 Loongson Technology Corporation Limited + */ + +#include "qemu/osdep.h" +#include "hw/boards.h" +#include "hw/sysbus.h" +#include "hw/intc/loongson_ipi.h" +#include "hw/irq.h" +#include "hw/qdev-properties.h" +#include "qapi/error.h" +#include "qemu/log.h" +#include "exec/address-spaces.h" +#include "migration/vmstate.h" +#include "target/loongarch/cpu.h" +#include "trace.h" + +static MemTxResult loongson_ipi_readl(void *opaque, hwaddr addr, + uint64_t *data, + unsigned size, MemTxAttrs attrs) +{ +IPICore *s; +LoongsonIPI *ipi = opaque; +uint64_t ret = 0; +int index = 0; + +s = >cpu[attrs.requester_id]; +addr &= 0xff; +switch (addr) { +case CORE_STATUS_OFF: +ret = s->status; +break; +case CORE_EN_OFF: +ret = s->en; +break; +case CORE_SET_OFF: +ret = 0; +break; +case CORE_CLEAR_OFF: +ret = 0; +break; +case CORE_BUF_20 ... CORE_BUF_38 + 4: +index = (addr - CORE_BUF_20) >> 2; +ret = s->buf[index]; +break; +default: +qemu_log_mask(LOG_UNIMP, "invalid read: %x", (uint32_t)addr); +break; +} + +trace_loongson_ipi_read(size, (uint64_t)addr, ret); +*data = ret; +return MEMTX_OK; +} + +static void send_ipi_data(CPULoongArchState *env, uint64_t val, hwaddr addr, + MemTxAttrs attrs) +{ +int i, mask = 0, data = 0; + +/* + * bit 27-30 is mask for byte writing, + * if the mask is 0, we need not to do anything. + */ +if ((val >> 27) & 0xf) { +data = address_space_ldl(env->address_space_iocsr, addr, + attrs, NULL); +for (i = 0; i < 4; i++) { +/* get mask for byte writing */ +if (val & (0x1 << (27 + i))) { +mask |= 0xff << (i * 8); +} +} +} + +data &= mask; +data |= (val >> 32) & ~mask; +address_space_stl(env->address_space_iocsr, addr, + data, attrs, NULL); +} + +static int archid_cmp(const void *a, const void *b) +{ + CPUArchId *archid_a = (CPUArchId *)a; + CPUArchId *archid_b = (CPUArchId *)b; + + return archid_a->arch_id - archid_b->arch_id; +} + +static CPUArchId *find_cpu_by_archid(MachineState *ms, uint32_t id) +{ +CPUArchId apic_id, *found_cpu; + +apic_id.arch_id = id; +found_cpu = bsearch(_id, ms->possible_cpus->cpus, +ms->possible_cpus->len, sizeof(*ms->possible_cpus->cpus), +archid_cmp)
[PATCH 3/5] hw/intc/loongson_ipi: Implement IOCSR address space for MIPS
Implement IOCSR address space get functions for MIPS/Loongson CPUs. For MIPS/Loongson without IOCSR (i.e. Loongson-3A1000), get_cpu_iocsr_as will return as null, and send_ipi_data will fail with MEMTX_DECODE_ERROR, which matches expected behavior on hardware. Signed-off-by: Jiaxun Yang --- I understand that there was a review comment stating that I shouldn't use TARGET_* macros in device drivers. But I still think this is the best way to handle architectural difference. There are many TARGET_* usages in hw/virtio for similiar purpose. --- hw/intc/loongson_ipi.c | 39 ++- 1 file changed, 30 insertions(+), 9 deletions(-) diff --git a/hw/intc/loongson_ipi.c b/hw/intc/loongson_ipi.c index 8c888da3b27c..93cc50a37a11 100644 --- a/hw/intc/loongson_ipi.c +++ b/hw/intc/loongson_ipi.c @@ -15,7 +15,12 @@ #include "qemu/log.h" #include "exec/address-spaces.h" #include "migration/vmstate.h" +#ifdef TARGET_LOONGARCH64 #include "target/loongarch/cpu.h" +#endif +#ifdef TARGET_MIPS +#include "target/mips/cpu.h" +#endif #include "trace.h" static MemTxResult loongson_ipi_readl(void *opaque, hwaddr addr, @@ -56,18 +61,35 @@ static MemTxResult loongson_ipi_readl(void *opaque, hwaddr addr, return MEMTX_OK; } -static void send_ipi_data(CPULoongArchState *env, uint64_t val, hwaddr addr, +static AddressSpace *get_cpu_iocsr_as(CPUState *cpu) +{ +#ifdef TARGET_LOONGARCH64 +return LOONGARCH_CPU(cpu)->env.address_space_iocsr; +#endif +#ifdef TARGET_MIPS +if (ase_lcsr_available(_CPU(cpu)->env)) { +return _CPU(cpu)->env.iocsr.as; +} +#endif +return NULL; +} + +static MemTxResult send_ipi_data(CPUState *cpu, uint64_t val, hwaddr addr, MemTxAttrs attrs) { int i, mask = 0, data = 0; +AddressSpace *iocsr_as = get_cpu_iocsr_as(cpu); + +if (!iocsr_as) { +return MEMTX_DECODE_ERROR; +} /* * bit 27-30 is mask for byte writing, * if the mask is 0, we need not to do anything. */ if ((val >> 27) & 0xf) { -data = address_space_ldl(env->address_space_iocsr, addr, - attrs, NULL); +data = address_space_ldl(iocsr_as, addr, attrs, NULL); for (i = 0; i < 4; i++) { /* get mask for byte writing */ if (val & (0x1 << (27 + i))) { @@ -78,8 +100,9 @@ static void send_ipi_data(CPULoongArchState *env, uint64_t val, hwaddr addr, data &= mask; data |= (val >> 32) & ~mask; -address_space_stl(env->address_space_iocsr, addr, - data, attrs, NULL); +address_space_stl(iocsr_as, addr, data, attrs, NULL); + +return MEMTX_OK; } static int archid_cmp(const void *a, const void *b) @@ -130,8 +153,7 @@ static MemTxResult mail_send(uint64_t val, MemTxAttrs attrs) /* override requester_id */ addr = SMP_IPI_MAILBOX + CORE_BUF_20 + (val & 0x1c); attrs.requester_id = cs->cpu_index; -send_ipi_data(_CPU(cs)->env, val, addr, attrs); -return MEMTX_OK; +return send_ipi_data(cs, val, addr, attrs); } static MemTxResult any_send(uint64_t val, MemTxAttrs attrs) @@ -149,8 +171,7 @@ static MemTxResult any_send(uint64_t val, MemTxAttrs attrs) /* override requester_id */ addr = val & 0x; attrs.requester_id = cs->cpu_index; -send_ipi_data(_CPU(cs)->env, val, addr, attrs); -return MEMTX_OK; +return send_ipi_data(cs, val, addr, attrs); } static MemTxResult loongson_ipi_writel(void *opaque, hwaddr addr, uint64_t val, -- 2.34.1
[PATCH] hw/mips/loongson3_virt: Emulate suspend function
Suspend function is emulated as what hardware actually do. Doorbell register fields are updates to include suspend value, suspend vector is encoded in firmware blob and fw_cfg is updated to include S3 bits as what x86 did. Signed-off-by: Jiaxun Yang --- hw/mips/loongson3_bootp.c | 1 + hw/mips/loongson3_virt.c | 19 +++ 2 files changed, 20 insertions(+) diff --git a/hw/mips/loongson3_bootp.c b/hw/mips/loongson3_bootp.c index f99af229327a..03a10b63c1b4 100644 --- a/hw/mips/loongson3_bootp.c +++ b/hw/mips/loongson3_bootp.c @@ -148,4 +148,5 @@ void init_reset_system(struct efi_reset_system_t *reset) reset->Shutdown = cpu_to_le64(0xbfc000a8); reset->ResetCold = cpu_to_le64(0xbfc00080); reset->ResetWarm = cpu_to_le64(0xbfc00080); +reset->DoSuspend = cpu_to_le64(0xbfc000d0); } diff --git a/hw/mips/loongson3_virt.c b/hw/mips/loongson3_virt.c index 33eae01eca2b..f06518ad8f54 100644 --- a/hw/mips/loongson3_virt.c +++ b/hw/mips/loongson3_virt.c @@ -127,6 +127,9 @@ static void loongson3_pm_write(void *opaque, hwaddr addr, case 0x00: qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET); return; +case 0x01: +qemu_system_suspend_request(); +return; case 0xff: qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN); return; @@ -250,6 +253,17 @@ static void init_boot_rom(void) 0x240D00FF, /* li t1, 0xff */ 0xA18D, /* sb t1, (t0) */ 0x1000, /* 1: b 1b */ +0x, /* nop */ + /* Suspend */ +0x3C0C9000, /* dli t0, 0x900010080010 */ +0x358C, +0x000C6438, +0x358C1008, +0x000C6438, +0x358C0010, +0x240D0001, /* li t1, 0x01 */ +0xA18D, /* sb t1, (t0) */ +0x03e8, /* jr ra */ 0x/* nop */ }; @@ -274,6 +288,10 @@ static void fw_conf_init(unsigned long ram_size) fw_cfg_add_i64(fw_cfg, FW_CFG_RAM_SIZE, (uint64_t)ram_size); fw_cfg_add_i32(fw_cfg, FW_CFG_MACHINE_VERSION, 1); fw_cfg_add_i64(fw_cfg, FW_CFG_CPU_FREQ, get_cpu_freq_hz()); + +uint8_t suspend[6] = {128, 0, 0, 129, 128, 128}; +fw_cfg_add_file(fw_cfg, "etc/system-states", g_memdup(suspend, 6), 6); + qemu_register_boot_set(fw_cfg_boot_set, fw_cfg); } @@ -551,6 +569,7 @@ static void mips_loongson3_virt_init(MachineState *machine) machine->ram, 0, virt_memmap[VIRT_LOWMEM].size); memory_region_init_io(iomem, NULL, _pm_ops, NULL, "loongson3_pm", virt_memmap[VIRT_PM].size); +qemu_register_wakeup_support(); memory_region_add_subregion(address_space_mem, virt_memmap[VIRT_LOWMEM].base, ram); --- base-commit: d762bf97931b58839316b68a570eecc6143c9e3e change-id: 20240508-loongson3v-suspend-cdd33a169eab Best regards, -- Jiaxun Yang
[PATCH 5/5] hw/mips/boston: Implement multi core support
Implement multiple physical core support by passing topology to CPS subsystem and generate cpu-map fdt node to decribe new topology. Signed-off-by: Jiaxun Yang --- hw/mips/boston.c | 37 - 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/hw/mips/boston.c b/hw/mips/boston.c index 1b44fb354c..4ed7d366fe 100644 --- a/hw/mips/boston.c +++ b/hw/mips/boston.c @@ -542,7 +542,10 @@ static const void *create_fdt(BostonState *s, qemu_fdt_setprop_cell(fdt, "/cpus", "#size-cells", 0x0); qemu_fdt_setprop_cell(fdt, "/cpus", "#address-cells", 0x1); +qemu_fdt_add_subnode(fdt, "/cpus/cpu-map"); for (cpu = 0; cpu < ms->smp.cpus; cpu++) { +char *map_path; + name = g_strdup_printf("/cpus/cpu@%d", cpu); qemu_fdt_add_subnode(fdt, name); qemu_fdt_setprop_string(fdt, name, "compatible", "img,mips"); @@ -550,6 +553,27 @@ static const void *create_fdt(BostonState *s, qemu_fdt_setprop_cell(fdt, name, "reg", cpu); qemu_fdt_setprop_string(fdt, name, "device_type", "cpu"); qemu_fdt_setprop_cells(fdt, name, "clocks", clk_ph, FDT_BOSTON_CLK_CPU); +qemu_fdt_setprop_cell(fdt, name, "phandle", qemu_fdt_alloc_phandle(fdt)); + +if (ms->smp.threads > 1) { +map_path = g_strdup_printf( +"/cpus/cpu-map/socket%d/cluster%d/core%d/thread%d", +cpu / (ms->smp.clusters * ms->smp.cores * ms->smp.threads), +(cpu / (ms->smp.cores * ms->smp.threads)) % ms->smp.clusters, +(cpu / ms->smp.threads) % ms->smp.cores, +cpu % ms->smp.threads); +} else { +map_path = g_strdup_printf( +"/cpus/cpu-map/socket%d/cluster%d/core%d", +cpu / (ms->smp.clusters * ms->smp.cores), +(cpu / ms->smp.cores) % ms->smp.clusters, +cpu % ms->smp.cores); +} + +qemu_fdt_add_path(fdt, map_path); +qemu_fdt_setprop_phandle(fdt, map_path, "cpu", name); + +g_free(map_path); g_free(name); } @@ -591,6 +615,15 @@ static const void *create_fdt(BostonState *s, g_free(name); g_free(gic_name); +/* CM node */ +name = g_strdup_printf("/soc/cm@%" HWADDR_PRIx, memmap[BOSTON_CM].base); +qemu_fdt_add_subnode(fdt, name); +qemu_fdt_setprop_string(fdt, name, "compatible", "mti,mips-cm"); +qemu_fdt_setprop_cells(fdt, name, "reg", memmap[BOSTON_CM].base, +memmap[BOSTON_CM].size); +g_free(name); + + /* CDMM node */ name = g_strdup_printf("/soc/cdmm@%" HWADDR_PRIx, memmap[BOSTON_CDMM].base); qemu_fdt_add_subnode(fdt, name); @@ -703,7 +736,9 @@ static void boston_mach_init(MachineState *machine) object_initialize_child(OBJECT(machine), "cps", >cps, TYPE_MIPS_CPS); object_property_set_str(OBJECT(>cps), "cpu-type", machine->cpu_type, _fatal); -object_property_set_uint(OBJECT(>cps), "num-vp", machine->smp.cpus, +object_property_set_uint(OBJECT(>cps), "num-pcore", machine->smp.cores, +_fatal); +object_property_set_uint(OBJECT(>cps), "num-vp", machine->smp.threads, _fatal); qdev_connect_clock_in(DEVICE(>cps), "clk-in", qdev_get_clock_out(dev, "cpu-refclk")); -- 2.34.1
[PATCH 2/5] hw/msic/mips_cmgcr: Implement multicore functions
We implemented following functions to allow software to probe and control VPs on secondary core - Reading out pcore count and coherence state - Two scratch GCRs for firmware - Semaphore GCR for register locking - Redirect block to other cores Signed-off-by: Jiaxun Yang --- hw/misc/mips_cmgcr.c | 168 +++ include/hw/misc/mips_cmgcr.h | 87 +++--- 2 files changed, 215 insertions(+), 40 deletions(-) diff --git a/hw/misc/mips_cmgcr.c b/hw/misc/mips_cmgcr.c index 2703040f45..8c2d184f2c 100644 --- a/hw/misc/mips_cmgcr.c +++ b/hw/misc/mips_cmgcr.c @@ -73,14 +73,19 @@ static inline void update_gic_base(MIPSGCRState *gcr, uint64_t val) static uint64_t gcr_read(void *opaque, hwaddr addr, unsigned size) { MIPSGCRState *gcr = (MIPSGCRState *) opaque; -MIPSGCRVPState *current_vps = >vps[current_cpu->cpu_index]; -MIPSGCRVPState *other_vps = >vps[current_vps->other]; +int redirect_corenum = mips_gcr_get_redirect_corenum(gcr); +int redirect_vpid = mips_gcr_get_redirect_vpid(gcr); +int current_corenum = mips_gcr_get_current_corenum(gcr); +int current_vpid = mips_gcr_get_current_vpid(gcr); +MIPSGCRPCoreState *current_pcore = >pcs[current_corenum]; +MIPSGCRVPState *current_vps = _pcore->vps[current_vpid]; +MIPSGCRPCoreState *other_pcore = >pcs[redirect_corenum]; +MIPSGCRVPState *other_vps = _pcore->vps[redirect_vpid]; switch (addr) { /* Global Control Block Register */ case GCR_CONFIG_OFS: -/* Set PCORES to 0 */ -return 0; +return gcr->num_pcores - 1; case GCR_BASE_OFS: return gcr->gcr_base; case GCR_REV_OFS: @@ -96,7 +101,19 @@ static uint64_t gcr_read(void *opaque, hwaddr addr, unsigned size) case GCR_L2_CONFIG_OFS: /* L2 BYPASS */ return GCR_L2_CONFIG_BYPASS_MSK; +case GCR_SYS_CONFIG2_OFS: +return gcr->num_vps << GCR_SYS_CONFIG2_MAXVP_SHF; +case GCR_SCRATCH0_OFS: +return gcr->scratch[0]; +case GCR_SCRATCH1_OFS: +return gcr->scratch[1]; +case GCR_SEM_OFS: +return gcr->sem; /* Core-Local and Core-Other Control Blocks */ +case MIPS_CLCB_OFS + GCR_CL_COH_EN_OFS: +return current_pcore->coh_en; +case MIPS_COCB_OFS + GCR_CL_COH_EN_OFS: +return other_pcore->coh_en; case MIPS_CLCB_OFS + GCR_CL_CONFIG_OFS: case MIPS_COCB_OFS + GCR_CL_CONFIG_OFS: /* Set PVP to # of VPs - 1 */ @@ -105,10 +122,18 @@ static uint64_t gcr_read(void *opaque, hwaddr addr, unsigned size) return current_vps->reset_base; case MIPS_COCB_OFS + GCR_CL_RESETBASE_OFS: return other_vps->reset_base; -case MIPS_CLCB_OFS + GCR_CL_OTHER_OFS: -return current_vps->other; -case MIPS_COCB_OFS + GCR_CL_OTHER_OFS: -return other_vps->other; +case MIPS_CLCB_OFS + GCR_CL_REDIRECT_OFS: +return current_vps->redirect; +case MIPS_COCB_OFS + GCR_CL_REDIRECT_OFS: +return other_vps->redirect; +case MIPS_CLCB_OFS + GCR_CL_ID_OFS: +return current_corenum; +case MIPS_COCB_OFS + GCR_CL_ID_OFS: +return redirect_corenum; +case MIPS_CLCB_OFS + GCR_CL_SCRATCH_OFS: +return current_vps->scratch; +case MIPS_COCB_OFS + GCR_CL_SCRATCH_OFS: +return other_vps->scratch; default: qemu_log_mask(LOG_UNIMP, "Read %d bytes at GCR offset 0x%" HWADDR_PRIx "\n", size, addr); @@ -123,12 +148,36 @@ static inline target_ulong get_exception_base(MIPSGCRVPState *vps) return (int32_t)(vps->reset_base & GCR_CL_RESET_BASE_RESETBASE_MSK); } +static inline void set_redirect(MIPSGCRState *gcr, +MIPSGCRVPState *vps, target_ulong data) +{ +int new_vpid = data & GCR_CL_REDIRECT_VP_MSK; +int new_coreid = (data & GCR_CL_REDIRECT_CORE_MSK) >> GCR_CL_REDIRECT_CORE_SHF; + +if (new_vpid >= gcr->num_vps) { +return; +} + +if (new_coreid >= gcr->num_pcores) { +return; +} + +vps->redirect = data & (GCR_CL_REDIRECT_VP_MSK | GCR_CL_REDIRECT_CORE_MSK); +} + /* Write GCR registers */ static void gcr_write(void *opaque, hwaddr addr, uint64_t data, unsigned size) { -MIPSGCRState *gcr = (MIPSGCRState *)opaque; -MIPSGCRVPState *current_vps = >vps[current_cpu->cpu_index]; -MIPSGCRVPState *other_vps = >vps[current_vps->other]; +MIPSGCRState *gcr = (MIPSGCRState *) opaque; +int redirect_corenum = mips_gcr_get_redirect_corenum(gcr); +int redirect_vpid = mips_gcr_get_redirect_vpid(gcr); +int redirect_vpnum = mips_gcr_get_redirect_vpnum(gcr); +int current_corenum = mips_gcr_get_current_corenum(gcr); +int current_vpid = mips_gcr_get_current_vpid(gcr); +MIPSGCRPCoreState *current_pcore = >pcs[current_corenum]; +
[PATCH 1/5] target/mips: Make globalnumber a CPU property
GlobalNumber marks topology information of a CPU instance. Make it a CPU property to allow CPS to override topology information. Signed-off-by: Jiaxun Yang --- target/mips/cpu.c| 16 +++- target/mips/cpu.h| 10 +- target/mips/sysemu/machine.c | 5 ++--- 3 files changed, 26 insertions(+), 5 deletions(-) diff --git a/target/mips/cpu.c b/target/mips/cpu.c index bbe01d07dd..762000d09b 100644 --- a/target/mips/cpu.c +++ b/target/mips/cpu.c @@ -296,7 +296,6 @@ static void mips_cpu_reset_hold(Object *obj, ResetType type) env->CP0_Random = env->tlb->nb_tlb - 1; env->tlb->tlb_in_use = env->tlb->nb_tlb; env->CP0_Wired = 0; -env->CP0_GlobalNumber = (cs->cpu_index & 0xFF) << CP0GN_VPId; env->CP0_EBase = KSEG0_BASE | (cs->cpu_index & 0x3FF); if (env->CP0_Config3 & (1 << CP0C3_CMGCR)) { env->CP0_CMGCRBase = 0x1fbf8000 >> 4; @@ -484,6 +483,12 @@ static void mips_cpu_realizefn(DeviceState *dev, Error **errp) env->exception_base = (int32_t)0xBFC0; +#if !defined(CONFIG_USER_ONLY) +if (env->CP0_GlobalNumber == -1) { +env->CP0_GlobalNumber = (cs->cpu_index & 0xFF) << CP0GN_VPId; +} +#endif + #if defined(CONFIG_TCG) && !defined(CONFIG_USER_ONLY) mmu_init(env, env->cpu_model); #endif @@ -563,6 +568,13 @@ static const TCGCPUOps mips_tcg_ops = { }; #endif /* CONFIG_TCG */ +static Property mips_cpu_properties[] = { +#if !defined(CONFIG_USER_ONLY) +DEFINE_PROP_INT32("globalnumber", MIPSCPU, env.CP0_GlobalNumber, -1), +#endif +DEFINE_PROP_END_OF_LIST(), +}; + static void mips_cpu_class_init(ObjectClass *c, void *data) { MIPSCPUClass *mcc = MIPS_CPU_CLASS(c); @@ -592,6 +604,8 @@ static void mips_cpu_class_init(ObjectClass *c, void *data) #ifdef CONFIG_TCG cc->tcg_ops = _tcg_ops; #endif /* CONFIG_TCG */ + +device_class_set_props(dc, mips_cpu_properties); } static const TypeInfo mips_cpu_type_info = { diff --git a/target/mips/cpu.h b/target/mips/cpu.h index 3e906a175a..7499608678 100644 --- a/target/mips/cpu.h +++ b/target/mips/cpu.h @@ -612,8 +612,13 @@ typedef struct CPUArchState { # define CP0EnLo_RI 31 # define CP0EnLo_XI 30 #endif -int32_t CP0_GlobalNumber; +/* CP0_GlobalNumber is preserved across CPU reset. */ #define CP0GN_VPId 0 +#define CP0GN_VPId_MASK (0xFFUL << CP0GN_VPId) +#define CP0GN_CoreNum 8 +#define CP0GN_CoreNum_MASK (0xFUL << CP0GN_CoreNum) +#define CP0GN_ClusterNum 16 +#define CP0GN_ClusterNum_MASK (0xFUL << CP0GN_ClusterNum) /* * CP0 Register 4 */ @@ -1175,6 +1180,9 @@ typedef struct CPUArchState { struct {} end_reset_fields; /* Fields from here on are preserved across CPU reset. */ +#if !defined(CONFIG_USER_ONLY) +int32_t CP0_GlobalNumber; +#endif CPUMIPSMVPContext *mvp; #if !defined(CONFIG_USER_ONLY) CPUMIPSTLBContext *tlb; diff --git a/target/mips/sysemu/machine.c b/target/mips/sysemu/machine.c index 213fd637fc..235d640862 100644 --- a/target/mips/sysemu/machine.c +++ b/target/mips/sysemu/machine.c @@ -218,8 +218,8 @@ static const VMStateDescription vmstate_tlb = { const VMStateDescription vmstate_mips_cpu = { .name = "cpu", -.version_id = 21, -.minimum_version_id = 21, +.version_id = 22, +.minimum_version_id = 22, .post_load = cpu_post_load, .fields = (const VMStateField[]) { /* Active TC */ @@ -257,7 +257,6 @@ const VMStateDescription vmstate_mips_cpu = { VMSTATE_INT32(env.CP0_VPEOpt, MIPSCPU), VMSTATE_UINT64(env.CP0_EntryLo0, MIPSCPU), VMSTATE_UINT64(env.CP0_EntryLo1, MIPSCPU), -VMSTATE_INT32(env.CP0_GlobalNumber, MIPSCPU), VMSTATE_UINTTL(env.CP0_Context, MIPSCPU), VMSTATE_INT32(env.CP0_MemoryMapID, MIPSCPU), VMSTATE_INT32(env.CP0_PageMask, MIPSCPU), -- 2.34.1
[PATCH 0/5] hw/mips: Proper multi core support
Hi all, This series implemented propper multiple core support for MIPS CPS systsm. Previously all CPUs are being implemented as a smt thread in a single core. Now it respects topology supplied in QEMU args. To test: Build a latest kernel with 64r6el_defconfig (tested on 6.6, next-20240506). Then run: ``` qemu-system-mips64el -M boston -cpu I6500 -kernel ~/linux-next/vmlinux -smp 4,cores=2,threads=2 -append "console=ttyS0,115200" -nographic ``` In dmesg of guest kernel: ``` [0.00] VP topology {2,2} total 4 ... [0.085190] smp: Bringing up secondary CPUs ... [0.090219] Primary instruction cache 64kB, VIPT, 4-way, linesize 64 bytes. [0.095461] Primary data cache 64kB, 4-way, PIPT, no aliases, linesize 64 bytes [0.096658] CPU1 revision is: 0001b000 (MIPS I6500) [0.096718] FPU revision is: 20f30300 [0.124711] Synchronize counters for CPU 1: done. [0.940979] Primary instruction cache 64kB, VIPT, 4-way, linesize 64 bytes. [0.941041] Primary data cache 64kB, 4-way, PIPT, no aliases, linesize 64 bytes [0.941256] CPU2 revision is: 0001b000 (MIPS I6500) [0.941289] FPU revision is: 20f30300 [0.965322] Synchronize counters for CPU 2: done. [1.260937] Primary instruction cache 64kB, VIPT, 4-way, linesize 64 bytes. [1.261001] Primary data cache 64kB, 4-way, PIPT, no aliases, linesize 64 bytes [1.261172] CPU3 revision is: 0001b000 (MIPS I6500) [1.261209] FPU revision is: 20f30300 [1.285390] Synchronize counters for CPU 3: done. [1.346985] smp: Brought up 1 node, 4 CPUs ``` Please review. Thanks To: qemu-devel@nongnu.org Cc: Philippe Mathieu-Daudé Signed-off-by: Jiaxun Yang --- Jiaxun Yang (5): target/mips: Make globalnumber a CPU property hw/msic/mips_cmgcr: Implement multicore functions hw/msic/mips_cpc: Implement multi core support hw/mips/cps: Implement multi core support hw/mips/boston: Implement multi core support hw/mips/boston.c | 37 +- hw/mips/cps.c| 66 ++--- hw/misc/mips_cmgcr.c | 168 +++ hw/misc/mips_cpc.c | 97 ++--- include/hw/mips/cps.h| 1 + include/hw/misc/mips_cmgcr.h | 87 +++--- include/hw/misc/mips_cpc.h | 15 +++- target/mips/cpu.c| 16 - target/mips/cpu.h| 10 ++- target/mips/sysemu/machine.c | 5 +- 10 files changed, 403 insertions(+), 99 deletions(-) --- base-commit: 248f6f62df073a3b4158fd0093863ab885feabb5 change-id: 20240506-mips-smp-9af9e71ad8c2 Best regards, -- Jiaxun Yang
[PATCH 4/5] hw/mips/cps: Implement multi core support
Implement multiple physical core support by creating CPU devices accorading to the new topology and passing pcore/vp information to CPC and CMGCR sub-devices. Signed-off-by: Jiaxun Yang --- hw/mips/cps.c | 66 +++ include/hw/mips/cps.h | 1 + 2 files changed, 41 insertions(+), 26 deletions(-) diff --git a/hw/mips/cps.c b/hw/mips/cps.c index 07b73b0a1f..6cf02379a9 100644 --- a/hw/mips/cps.c +++ b/hw/mips/cps.c @@ -73,31 +73,43 @@ static void mips_cps_realize(DeviceState *dev, Error **errp) return; } -for (int i = 0; i < s->num_vp; i++) { -MIPSCPU *cpu = MIPS_CPU(object_new(s->cpu_type)); -CPUMIPSState *env = >env; +object_initialize_child(OBJECT(dev), "gcr", >gcr, TYPE_MIPS_GCR); -/* All VPs are halted on reset. Leave powering up to CPC. */ -object_property_set_bool(OBJECT(cpu), "start-powered-off", true, - _abort); +for (int corenum = 0; corenum < s->num_pcore; corenum++) { +for (int vpid = 0; vpid < s->num_vp; vpid++) { +int vpnum = corenum * s->num_vp + vpid; +int32_t globalnumber = (corenum << CP0GN_CoreNum) | vpid; -/* All cores use the same clock tree */ -qdev_connect_clock_in(DEVICE(cpu), "clk-in", s->clock); +MIPSCPU *cpu = MIPS_CPU(object_new(s->cpu_type)); +CPUMIPSState *env = >env; -if (!qdev_realize_and_unref(DEVICE(cpu), NULL, errp)) { -return; -} +/* All VPs are halted on reset. Leave powering up to CPC. */ +object_property_set_bool(OBJECT(cpu), "start-powered-off", true, +_abort); + +object_property_set_int(OBJECT(cpu), "globalnumber", globalnumber, +_abort); + +/* All cores use the same clock tree */ +qdev_connect_clock_in(DEVICE(cpu), "clk-in", s->clock); + +if (!qdev_realize_and_unref(DEVICE(cpu), NULL, errp)) { +return; +} + +g_assert(vpnum == CPU(cpu)->cpu_index); -/* Init internal devices */ -cpu_mips_irq_init_cpu(cpu); -cpu_mips_clock_init(cpu); +/* Init internal devices */ +cpu_mips_irq_init_cpu(cpu); +cpu_mips_clock_init(cpu); -if (cpu_mips_itu_supported(env)) { -itu_present = true; -/* Attach ITC Tag to the VP */ -env->itc_tag = mips_itu_get_tag_region(>itu); +if (cpu_mips_itu_supported(env)) { +itu_present = true; +/* Attach ITC Tag to the VP */ +env->itc_tag = mips_itu_get_tag_region(>itu); +} +qemu_register_reset(main_cpu_reset, cpu); } -qemu_register_reset(main_cpu_reset, cpu); } /* Inter-Thread Communication Unit */ @@ -119,8 +131,12 @@ static void mips_cps_realize(DeviceState *dev, Error **errp) object_initialize_child(OBJECT(dev), "cpc", >cpc, TYPE_MIPS_CPC); object_property_set_uint(OBJECT(>cpc), "num-vp", s->num_vp, _abort); +object_property_set_uint(OBJECT(>cpc), "num-pcore", s->num_pcore, +_abort); object_property_set_int(OBJECT(>cpc), "vp-start-running", 1, _abort); +object_property_set_link(OBJECT(>cpc), "gcr", OBJECT(>gcr), +_abort); if (!sysbus_realize(SYS_BUS_DEVICE(>cpc), errp)) { return; } @@ -130,7 +146,7 @@ static void mips_cps_realize(DeviceState *dev, Error **errp) /* Global Interrupt Controller */ object_initialize_child(OBJECT(dev), "gic", >gic, TYPE_MIPS_GIC); -object_property_set_uint(OBJECT(>gic), "num-vp", s->num_vp, +object_property_set_uint(OBJECT(>gic), "num-vp", s->num_vp * s->num_pcore, _abort); object_property_set_uint(OBJECT(>gic), "num-irq", 128, _abort); @@ -141,16 +157,13 @@ static void mips_cps_realize(DeviceState *dev, Error **errp) memory_region_add_subregion(>container, 0, sysbus_mmio_get_region(SYS_BUS_DEVICE(>gic), 0)); -/* Global Configuration Registers */ -gcr_base = MIPS_CPU(first_cpu)->env.CP0_CMGCRBase << 4; - -object_initialize_child(OBJECT(dev), "gcr", >gcr, TYPE_MIPS_GCR); +gcr_base = GCR_BASE_ADDR; +object_property_set_uint(OBJECT(>gcr), "num-pcores", s->num_pcore, +_abort); object_property_set_uint(OBJECT(>gcr), "num-vp"
[PATCH 3/5] hw/msic/mips_cpc: Implement multi core support
Implement multiple physical core support for MIPS CPC controller. Including some R/O configuration registers and VP bring up support on multiple cores. Signed-off-by: Jiaxun Yang --- hw/misc/mips_cpc.c | 97 ++ include/hw/misc/mips_cpc.h | 15 ++- 2 files changed, 85 insertions(+), 27 deletions(-) diff --git a/hw/misc/mips_cpc.c b/hw/misc/mips_cpc.c index 1e8fd2e699..f6a2f29088 100644 --- a/hw/misc/mips_cpc.c +++ b/hw/misc/mips_cpc.c @@ -25,9 +25,25 @@ #include "hw/sysbus.h" #include "migration/vmstate.h" +#include "hw/misc/mips_cmgcr.h" #include "hw/misc/mips_cpc.h" #include "hw/qdev-properties.h" +static inline int cpc_vpnum_to_corenum(MIPSCPCState *cpc, int vpnum) +{ +return vpnum / cpc->num_vp; +} + +static inline int cpc_vpnum_to_vpid(MIPSCPCState *cpc, int vpnum) +{ +return vpnum % cpc->num_vp; +} + +static inline MIPSCPCPCoreState *cpc_vpnum_to_pcs(MIPSCPCState *cpc, int vpnum) +{ +return >pcs[cpc_vpnum_to_corenum(cpc, vpnum)]; +} + static inline uint64_t cpc_vp_run_mask(MIPSCPCState *cpc) { return (1ULL << cpc->num_vp) - 1; @@ -39,36 +55,41 @@ static void mips_cpu_reset_async_work(CPUState *cs, run_on_cpu_data data) cpu_reset(cs); cs->halted = 0; -cpc->vp_running |= 1ULL << cs->cpu_index; +cpc_vpnum_to_pcs(cpc, cs->cpu_index)->vp_running |= +1 << cpc_vpnum_to_vpid(cpc, cs->cpu_index); } -static void cpc_run_vp(MIPSCPCState *cpc, uint64_t vp_run) +static void cpc_run_vp(MIPSCPCState *cpc, int pcore, uint64_t vp_run) { -CPUState *cs = first_cpu; +MIPSCPCPCoreState *pcs = >pcs[pcore]; -CPU_FOREACH(cs) { -uint64_t i = 1ULL << cs->cpu_index; -if (i & vp_run & ~cpc->vp_running) { +for (int vpid = 0; vpid < cpc->num_vp; vpid++) { +if ((1 << vpid) & vp_run & ~pcs->vp_running) { +int vpnum = pcore * cpc->num_vp + vpid; /* * To avoid racing with a CPU we are just kicking off. * We do the final bit of preparation for the work in * the target CPUs context. */ -async_safe_run_on_cpu(cs, mips_cpu_reset_async_work, - RUN_ON_CPU_HOST_PTR(cpc)); +async_safe_run_on_cpu(qemu_get_cpu(vpnum), +mips_cpu_reset_async_work, +RUN_ON_CPU_HOST_PTR(cpc)); +pcs->vp_running |= 1 << vpid; } } } -static void cpc_stop_vp(MIPSCPCState *cpc, uint64_t vp_stop) +static void cpc_stop_vp(MIPSCPCState *cpc, int pcore, uint64_t vp_stop) { -CPUState *cs = first_cpu; +MIPSCPCPCoreState *pcs = >pcs[pcore]; + +for (int vpid = 0; vpid < cpc->num_vp; vpid++) { +if ((1 << vpid) & vp_stop & pcs->vp_running) { +int vpnum = pcore * cpc->num_vp + vpid; +CPUState *cs = qemu_get_cpu(vpnum); -CPU_FOREACH(cs) { -uint64_t i = 1ULL << cs->cpu_index; -if (i & vp_stop & cpc->vp_running) { cpu_interrupt(cs, CPU_INTERRUPT_HALT); -cpc->vp_running &= ~i; +pcs->vp_running &= ~(1 << vpid); } } } @@ -77,15 +98,20 @@ static void cpc_write(void *opaque, hwaddr offset, uint64_t data, unsigned size) { MIPSCPCState *s = opaque; +int current_corenum = cpc_vpnum_to_corenum(s, current_cpu->cpu_index); switch (offset) { case CPC_CL_BASE_OFS + CPC_VP_RUN_OFS: +cpc_run_vp(s, current_corenum, data); +break; case CPC_CO_BASE_OFS + CPC_VP_RUN_OFS: -cpc_run_vp(s, data & cpc_vp_run_mask(s)); +cpc_run_vp(s, mips_gcr_get_redirect_corenum(s->gcr), data); break; case CPC_CL_BASE_OFS + CPC_VP_STOP_OFS: +cpc_stop_vp(s, current_corenum, data); +break; case CPC_CO_BASE_OFS + CPC_VP_STOP_OFS: -cpc_stop_vp(s, data & cpc_vp_run_mask(s)); +cpc_stop_vp(s, mips_gcr_get_redirect_corenum(s->gcr), data); break; default: qemu_log_mask(LOG_UNIMP, @@ -101,9 +127,13 @@ static uint64_t cpc_read(void *opaque, hwaddr offset, unsigned size) MIPSCPCState *s = opaque; switch (offset) { +case CPC_CL_BASE_OFS + CPC_CL_STAT_CONF_OFS: +case CPC_CO_BASE_OFS + CPC_CL_STAT_CONF_OFS: +return CPC_CL_STAT_CONF_SEQ_STATE_U6 << CPC_CL_STAT_CONF_SEQ_STATE_SHF; case CPC_CL_BASE_OFS + CPC_VP_RUNNING_OFS: +return cpc_vpnum_to_pcs(s, current_cpu->cpu_index)->vp_running; case CPC_CO_BASE_OFS + CPC_VP_RUNNING_OFS: -return s->vp_running; +return s->pcs[mips_gcr_get_redirect_corenum(s->gcr)].vp_running; default:
Re: [RFC PATCH 00/11] target/mips: Remove I6500 CPU definition
在 2024/2/9 09:05, Philippe Mathieu-Daudé 写道: Alternative to: https://lore.kernel.org/qemu-devel/20240209085347.8446-1-phi...@linaro.org/ If the I6500 can not be tested or its support is incomplete, there is no point in wasting energy maintaining it. Actually all SAAR and ITU stuff are optional for I6500 in real world so it's fine to just leave I6500 defined without SAAR support. The main difference between I6400 and I6500 is multi-cluster support, I do have some patch for bringing proper multi-cluster support to QEMU, but it can't work with boston due to address space limitations. Should I give mips-virt stuff another go? Thanks - Jiaxun Philippe Mathieu-Daudé (11): target/mips: Remove helpers accessing SAAR registers hw/misc/mips: Reduce itc_reconfigure() scope target/mips: Remove MIPSITUState::itu field target/mips: Remove CPUMIPSState::saarp field hw/misc/mips_itu: Remove MIPSITUState::cpu0 field hw/misc/mips_itu: Remove MIPSITUState::saar field target/mips: Remove CPUMIPSState::CP0_SAAR[2] field target/mips: Remove helpers accessing SAARI register target/mips: Remove CPUMIPSState::CP0_SAARI field target/mips: Remove the unused DisasContext::saar field target/mips: Remove I6500 CPU definition docs/about/removed-features.rst | 5 +++ include/hw/misc/mips_itu.h | 6 --- target/mips/cpu.h | 4 -- target/mips/tcg/translate.h | 1 - target/mips/tcg/sysemu_helper.h.inc | 6 --- hw/mips/cps.c | 3 -- hw/misc/mips_itu.c | 35 ++-- target/mips/sysemu/machine.c| 4 +- target/mips/tcg/sysemu/cp0_helper.c | 63 - target/mips/tcg/translate.c | 62 tests/qtest/machine-none-test.c | 2 +- target/mips/cpu-defs.c.inc | 40 -- 12 files changed, 12 insertions(+), 219 deletions(-) -- --- Jiaxun Yang
Re: why various devices are loading x86 roms on non-x86 architectures?
在 2024/1/31 10:28, Michael Tokarev 写道: Hi! qemu-system-aarch64 -device virtio-vga this one loads vgabios-virtio.bin. Why? Does this bios work on aarch64 (or any other non-x86 arch)? Should there may be some conditional in this and similar places? The same is true for x86 pxe roms and other x86-only roms. FYI on some systems they use x86emu (or biosemu) to run x86 only OpROMs, this is at least true for u-boot (u-boot/drivers/bios_emulator), PMON (MIPS/Loongson) and coreboot. Thanks - Jiaxun Thanks, /mjt -- --- Jiaxun Yang
Re: [PATCH] target/mips: enable GINVx support for I6400 and I6500
在 2023/6/30 15:28, Marcin Nowakowski 写道: GINVI and GINVT operations are supported on MIPS I6400 and I6500 cores, so indicate that properly in CP0.Config5 register bits [16:15]. Signed-off-by: Marcin Nowakowski VZ is unimplemented in TCG so perhaps we should leave them as not supported? Thanks - Jiaxun --- target/mips/cpu-defs.c.inc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/target/mips/cpu-defs.c.inc b/target/mips/cpu-defs.c.inc index d45f245a67..da122e72d7 100644 --- a/target/mips/cpu-defs.c.inc +++ b/target/mips/cpu-defs.c.inc @@ -709,7 +709,7 @@ const mips_def_t mips_defs[] = .CP0_Config4 = MIPS_CONFIG4 | (1U << CP0C4_M) | (3 << CP0C4_IE) | (1 << CP0C4_AE) | (0xfc << CP0C4_KScrExist), .CP0_Config5 = MIPS_CONFIG5 | (1 << CP0C5_XNP) | (1 << CP0C5_VP) | - (1 << CP0C5_LLB) | (1 << CP0C5_MRP), + (1 << CP0C5_LLB) | (1 << CP0C5_MRP) | (3 << CP0C5_GI), .CP0_Config5_rw_bitmask = (1 << CP0C5_MSAEn) | (1 << CP0C5_SBRI) | (1 << CP0C5_FRE) | (1 << CP0C5_UFE), .CP0_LLAddr_rw_bitmask = 0, @@ -749,7 +749,7 @@ const mips_def_t mips_defs[] = .CP0_Config4 = MIPS_CONFIG4 | (1U << CP0C4_M) | (3 << CP0C4_IE) | (1 << CP0C4_AE) | (0xfc << CP0C4_KScrExist), .CP0_Config5 = MIPS_CONFIG5 | (1 << CP0C5_XNP) | (1 << CP0C5_VP) | - (1 << CP0C5_LLB) | (1 << CP0C5_MRP), + (1 << CP0C5_LLB) | (1 << CP0C5_MRP) | (3 << CP0C5_GI), .CP0_Config5_rw_bitmask = (1 << CP0C5_MSAEn) | (1 << CP0C5_SBRI) | (1 << CP0C5_FRE) | (1 << CP0C5_UFE), .CP0_LLAddr_rw_bitmask = 0,
Re: [PATCH 1/4] hw/intc/loongarch_ipi: Bring back all 4 IPI mailboxes
> 2023年6月3日 01:28,Peter Maydell 写道: > > On Sun, 21 May 2023 at 11:24, Jiaxun Yang wrote: >> >> As per "Loongson 3A5000/3B5000 Processor Reference Manual", >> Loongson 3A5000's IPI implementation have 4 mailboxes per >> core. >> >> However, in 78464f023b54 ("hw/loongarch/virt: Modify ipi as >> percpu device"), the number of IPI mailboxes was reduced to >> one, which mismatches actual hardware. >> >> It won't affect LoongArch based system as LoongArch boot code >> only uses the first mailbox, however MIPS based Loongson boot >> code uses all 4 mailboxes. >> >> Fixes: 78464f023b54 ("hw/loongarch/virt: Modify ipi as percpu device") >> Signed-off-by: Jiaxun Yang >> --- >> hw/intc/loongarch_ipi.c | 6 +++--- >> include/hw/intc/loongarch_ipi.h | 4 +++- >> 2 files changed, 6 insertions(+), 4 deletions(-) >> >> diff --git a/hw/intc/loongarch_ipi.c b/hw/intc/loongarch_ipi.c >> index d6ab91721ea1..3e453816524e 100644 >> --- a/hw/intc/loongarch_ipi.c >> +++ b/hw/intc/loongarch_ipi.c >> @@ -238,14 +238,14 @@ static void loongarch_ipi_init(Object *obj) >> >> static const VMStateDescription vmstate_ipi_core = { >> .name = "ipi-single", >> -.version_id = 1, >> -.minimum_version_id = 1, >> +.version_id = 2, >> +.minimum_version_id = 2, >> .fields = (VMStateField[]) { >> VMSTATE_UINT32(status, IPICore), >> VMSTATE_UINT32(en, IPICore), >> VMSTATE_UINT32(set, IPICore), >> VMSTATE_UINT32(clear, IPICore), >> -VMSTATE_UINT32_ARRAY(buf, IPICore, 2), >> +VMSTATE_UINT32_ARRAY(buf, IPICore, IPI_MBX_NUM * 2), >> VMSTATE_END_OF_LIST() >> } >> }; >> diff --git a/include/hw/intc/loongarch_ipi.h >> b/include/hw/intc/loongarch_ipi.h >> index 664e050b926e..6c6194786e80 100644 >> --- a/include/hw/intc/loongarch_ipi.h >> +++ b/include/hw/intc/loongarch_ipi.h >> @@ -28,6 +28,8 @@ >> #define MAIL_SEND_OFFSET 0 >> #define ANY_SEND_OFFSET (IOCSR_ANY_SEND - IOCSR_MAIL_SEND) >> >> +#define IPI_MBX_NUM 4 >> + >> #define TYPE_LOONGARCH_IPI "loongarch_ipi" >> OBJECT_DECLARE_SIMPLE_TYPE(LoongArchIPI, LOONGARCH_IPI) >> >> @@ -37,7 +39,7 @@ typedef struct IPICore { >> uint32_t set; >> uint32_t clear; >> /* 64bit buf divide into 2 32bit buf */ >> -uint32_t buf[2]; >> +uint32_t buf[IPI_MBX_NUM * 2]; >> qemu_irq irq; >> } IPICore; > > In particular, this fixes Coverity issues CID 1512452 and 1512453, > where Coverity notices that the code in loongarch_ipi_writel() and > loongarch_ipi_readl() reads off the end of the too-short buf[]. LoongArch maintainers, do you mind to take this patch while I’m refactoring rest of the series? Thanks Jiaxun > > thanks > -- PMM
Re: [PATCH 1/4] hw/intc/loongarch_ipi: Bring back all 4 IPI mailboxes
> 2023年5月23日 11:01,Song Gao 写道: > > > > 在 2023/5/23 上午11:22, Jiaxun Yang 写道: [...] >> >>> >> Is totally the same on MIPS and LoongArch. I’m guarding them out because >> We have different way to get IOCSR address space on MIPS, which is due >> to be implemented. >> >> I can further abstract out a function to get IOCSR address space. But still, >> I think the best way to differ those two architecture is using TARGET_* >> macros, >> as it doesn’t make much sense to have unused code for another architecture >> compiled. > Most of the code in hw/intc or hw/ uses property to distinguish between > different devices, not TARGE_* macro. They are the *same* device, with different way to handle IOCSR address space. Another problem is casting CPUState with LOONGARCH_CPU() is something invalid on MIPS, vice-versa. We are potentially introducing a security issue here. I know nobody have done something like this before, but not necessarily to be a bad idea. I’ll introduce something like: +#ifdef TARGET_LOONGARCH64 +static inline void *AddressSpace get_iocsr_as(int cpuid) +{ +CPUState *cs = qemu_get_cpu(cpuid); +LoongArchCPU *cpu = LOONGARCH_CPU(cs); + +return >env.address_space_iocsr; +} +#endif + +#ifdef TARGET_MIPS64 +static inline void *AddressSpace get_iocsr_as(int cpuid) +{ +CPUState *cs = qemu_get_cpu(cpuid); +MIPSCPU *cpu = MIPS_CPU(cs); + +return >env.iocsr.as; +} +#endif Thanks - Jiaxun > > I still think it is better to use property. > > Thanks. > Song Gao >>> All references to loongarch_ipi should also be changed. >> Sure. >> >> Thanks >> - Jiaxun >
Re: [PATCH 1/4] hw/intc/loongarch_ipi: Bring back all 4 IPI mailboxes
> 2023年5月23日 02:25,Song Gao 写道: > > > > 在 2023/5/22 下午9:44, Philippe Mathieu-Daudé 写道: >> On 22/5/23 13:47, Jiaxun Yang wrote: >>> >>> >>>> 2023年5月22日 04:52,Huacai Chen 写道: >>>> >>>> Hi, Jiaxun, >>>> >>>> Rename loongarch_ipi to loongson_ipi? It will be shared by both MIPS >>>> and LoongArch in your series. >>> >>> Hi Huacai, >>> >>> Thanks for the point, what’s the opinion from LoongArch mainatiners? >>> >>> Or perhaps rename it as loong_ipi to reflect the nature that it’s shared >>> by MIPS based Loongson and LoongArch based Loongson? >> >> I'm not a LoongArch maintainer, but a model named "loong_ipi" makes >> sense to me. >> >> Please add it to the two Virt machine sections in MAINTAINERS. Hi Song, >> > 'loonggson_ipi' is better, qemu doesn't have naming with 'loong' as prefix. Thanks, I’ll take looongson_ipi then. > > And patch2 should not use macros. Some attributes should be added to > distinguish between MIPS and LongArch. By attribute do you mean property? If so I don’t see any necessity, the IP block Is totally the same on MIPS and LoongArch. I’m guarding them out because We have different way to get IOCSR address space on MIPS, which is due to be implemented. I can further abstract out a function to get IOCSR address space. But still, I think the best way to differ those two architecture is using TARGET_* macros, as it doesn’t make much sense to have unused code for another architecture compiled. > > All references to loongarch_ipi should also be changed. Sure. Thanks - Jiaxun > > Thanks. > Song Gao
Re: [PATCH 2/2] hw/mips/loongson3_virt: Remove CPU restrictions for TCG
> 2023年5月22日 13:08,Philippe Mathieu-Daudé 写道: > > On 21/5/23 23:48, Jiaxun Yang wrote: >> After implemented CPUCFG and CSR, we are now able to boot Linux >> kernel with Loongson-3A4000 CPU, so there is no point to restrict >> CPU type for TCG. > > Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1639 > ? Potentially yes, although I think the issue itself is just a question on usage of the board. Thanks - Jiaxun > >> Signed-off-by: Jiaxun Yang >> --- >> hw/mips/loongson3_virt.c | 4 >> 1 file changed, 4 deletions(-) > >
Re: [PATCH 1/4] hw/intc/loongarch_ipi: Bring back all 4 IPI mailboxes
> 2023年5月22日 04:52,Huacai Chen 写道: > > Hi, Jiaxun, > > Rename loongarch_ipi to loongson_ipi? It will be shared by both MIPS > and LoongArch in your series. Hi Huacai, Thanks for the point, what’s the opinion from LoongArch mainatiners? Or perhaps rename it as loong_ipi to reflect the nature that it’s shared by MIPS based Loongson and LoongArch based Loongson? Thanks - Jiaxun > > > Huacai > > On Sun, May 21, 2023 at 6:24 PM Jiaxun Yang wrote: >> >> As per "Loongson 3A5000/3B5000 Processor Reference Manual", >> Loongson 3A5000's IPI implementation have 4 mailboxes per >> core. >> >> However, in 78464f023b54 ("hw/loongarch/virt: Modify ipi as >> percpu device"), the number of IPI mailboxes was reduced to >> one, which mismatches actual hardware. >> >> It won't affect LoongArch based system as LoongArch boot code >> only uses the first mailbox, however MIPS based Loongson boot >> code uses all 4 mailboxes. >> >> Fixes: 78464f023b54 ("hw/loongarch/virt: Modify ipi as percpu device") >> Signed-off-by: Jiaxun Yang >> --- >> hw/intc/loongarch_ipi.c | 6 +++--- >> include/hw/intc/loongarch_ipi.h | 4 +++- >> 2 files changed, 6 insertions(+), 4 deletions(-) >> >> diff --git a/hw/intc/loongarch_ipi.c b/hw/intc/loongarch_ipi.c >> index d6ab91721ea1..3e453816524e 100644 >> --- a/hw/intc/loongarch_ipi.c >> +++ b/hw/intc/loongarch_ipi.c >> @@ -238,14 +238,14 @@ static void loongarch_ipi_init(Object *obj) >> >> static const VMStateDescription vmstate_ipi_core = { >> .name = "ipi-single", >> -.version_id = 1, >> -.minimum_version_id = 1, >> +.version_id = 2, >> +.minimum_version_id = 2, >> .fields = (VMStateField[]) { >> VMSTATE_UINT32(status, IPICore), >> VMSTATE_UINT32(en, IPICore), >> VMSTATE_UINT32(set, IPICore), >> VMSTATE_UINT32(clear, IPICore), >> -VMSTATE_UINT32_ARRAY(buf, IPICore, 2), >> +VMSTATE_UINT32_ARRAY(buf, IPICore, IPI_MBX_NUM * 2), >> VMSTATE_END_OF_LIST() >> } >> }; >> diff --git a/include/hw/intc/loongarch_ipi.h >> b/include/hw/intc/loongarch_ipi.h >> index 664e050b926e..6c6194786e80 100644 >> --- a/include/hw/intc/loongarch_ipi.h >> +++ b/include/hw/intc/loongarch_ipi.h >> @@ -28,6 +28,8 @@ >> #define MAIL_SEND_OFFSET 0 >> #define ANY_SEND_OFFSET (IOCSR_ANY_SEND - IOCSR_MAIL_SEND) >> >> +#define IPI_MBX_NUM 4 >> + >> #define TYPE_LOONGARCH_IPI "loongarch_ipi" >> OBJECT_DECLARE_SIMPLE_TYPE(LoongArchIPI, LOONGARCH_IPI) >> >> @@ -37,7 +39,7 @@ typedef struct IPICore { >> uint32_t set; >> uint32_t clear; >> /* 64bit buf divide into 2 32bit buf */ >> -uint32_t buf[2]; >> +uint32_t buf[IPI_MBX_NUM * 2]; >> qemu_irq irq; >> } IPICore; >> >> -- >> 2.39.2 (Apple Git-143) >>
[PATCH 0/2] MIPS: Enable Loongson-3A4000 TCG for system emulation
Hi there, This series enables Loongson-3A4000 TCG for system emulation. It Implemented Loongson CSR insertions which is required for Linux Kernel to probe CPU features and removed CPU type restrictions for loongson3_virt board. This series is based on two of my previous series[1] [2]. However it's just a soft dependency for me to do boot test, feel free to apply this series without them. Note that loongarch_ipi is still not hooked up in IOCSR. I've sucessfully done it locally but I just want to confirm some details on hardware. Thanks - Jiaxun [1]: https://lore.kernel.org/qemu-devel/20230521102307.87081-1-jiaxun.y...@flygoat.com/T/#t [2]: https://lore.kernel.org/qemu-devel/0bb0cded-8450-536e-b90f-1a9d33311...@linaro.org/T/#t Jiaxun Yang (2): target/mips: Implement Loongson CSR instructions hw/mips/loongson3_virt: Remove CPU restrictions for TCG hw/mips/loongson3_virt.c | 4 -- target/mips/cpu-defs.c.inc | 9 target/mips/cpu.c| 8 target/mips/cpu.h| 40 target/mips/helper.h | 4 ++ target/mips/internal.h | 2 + target/mips/tcg/lcsr.decode | 17 +++ target/mips/tcg/lcsr_translate.c | 69 target/mips/tcg/meson.build | 2 + target/mips/tcg/op_helper.c | 16 +++ target/mips/tcg/sysemu/lcsr_helper.c | 45 ++ target/mips/tcg/sysemu/meson.build | 4 ++ target/mips/tcg/sysemu_helper.h.inc | 8 target/mips/tcg/translate.c | 3 ++ target/mips/tcg/translate.h | 7 +++ 15 files changed, 234 insertions(+), 4 deletions(-) create mode 100644 target/mips/tcg/lcsr.decode create mode 100644 target/mips/tcg/lcsr_translate.c create mode 100644 target/mips/tcg/sysemu/lcsr_helper.c -- 2.39.2 (Apple Git-143)
[PATCH 2/2] hw/mips/loongson3_virt: Remove CPU restrictions for TCG
After implemented CPUCFG and CSR, we are now able to boot Linux kernel with Loongson-3A4000 CPU, so there is no point to restrict CPU type for TCG. Signed-off-by: Jiaxun Yang --- hw/mips/loongson3_virt.c | 4 1 file changed, 4 deletions(-) diff --git a/hw/mips/loongson3_virt.c b/hw/mips/loongson3_virt.c index a57245012598..47289fb6bf85 100644 --- a/hw/mips/loongson3_virt.c +++ b/hw/mips/loongson3_virt.c @@ -488,10 +488,6 @@ static void mips_loongson3_virt_init(MachineState *machine) if (!machine->cpu_type) { machine->cpu_type = MIPS_CPU_TYPE_NAME("Loongson-3A1000"); } -if (!strstr(machine->cpu_type, "Loongson-3A1000")) { -error_report("Loongson-3/TCG needs cpu type Loongson-3A1000"); -exit(1); -} } else { if (!machine->cpu_type) { machine->cpu_type = MIPS_CPU_TYPE_NAME("Loongson-3A4000"); -- 2.39.2 (Apple Git-143)
[PATCH 1/2] target/mips: Implement Loongson CSR instructions
Loongson introduced CSR instructions since 3A4000, which looks similar to IOCSR and CPUCFG instructions we seen in LoongArch. Unfortunately we don't have much document about those instructions, bit fields of CPUCFG instructions and IOCSR registers can be found at 3A4000's user manual, while instruction encodings can be found at arch/mips/include/asm/mach-loongson64/loongson_regs.h from Linux Kernel. Our predefined CPUCFG bits are differ from actual 3A4000, since we can't emulate all CPUCFG features present in 3A4000 for now, we just enable bits for what we have in TCG. Signed-off-by: Jiaxun Yang --- target/mips/cpu-defs.c.inc | 9 target/mips/cpu.c| 8 target/mips/cpu.h| 40 target/mips/helper.h | 4 ++ target/mips/internal.h | 2 + target/mips/tcg/lcsr.decode | 17 +++ target/mips/tcg/lcsr_translate.c | 69 target/mips/tcg/meson.build | 2 + target/mips/tcg/op_helper.c | 16 +++ target/mips/tcg/sysemu/lcsr_helper.c | 45 ++ target/mips/tcg/sysemu/meson.build | 4 ++ target/mips/tcg/sysemu_helper.h.inc | 8 target/mips/tcg/translate.c | 3 ++ target/mips/tcg/translate.h | 7 +++ 14 files changed, 234 insertions(+) create mode 100644 target/mips/tcg/lcsr.decode create mode 100644 target/mips/tcg/lcsr_translate.c create mode 100644 target/mips/tcg/sysemu/lcsr_helper.c diff --git a/target/mips/cpu-defs.c.inc b/target/mips/cpu-defs.c.inc index d45f245a6718..167c96cb2748 100644 --- a/target/mips/cpu-defs.c.inc +++ b/target/mips/cpu-defs.c.inc @@ -895,6 +895,15 @@ const mips_def_t mips_defs[] = .CP1_fcr31 = 0, .CP1_fcr31_rw_bitmask = 0xFF83, .MSAIR = (0x01 << MSAIR_ProcID) | (0x40 << MSAIR_Rev), +.lcsr_cpucfg1 = (1 << CPUCFG1_FP) | (2 << CPUCFG1_FPREV) | +(1 << CPUCFG1_MSA1) | (1 << CPUCFG1_LSLDR0) | +(1 << CPUCFG1_LSPERF) | (1 << CPUCFG1_LSPERFX) | +(1 << CPUCFG1_LSSYNCI) | (1 << CPUCFG1_LLEXC) | +(1 << CPUCFG1_SCRAND) | (1 << CPUCFG1_MUALP) | +(1 << CPUCFG1_KMUALEN) | (1 << CPUCFG1_ITLBT) | +(1 << CPUCFG1_SFBP) | (1 << CPUCFG1_CDMAP), +.lcsr_cpucfg2 = (1 << CPUCFG2_LEXT1) | (1 << CPUCFG2_LCSRP) | +(1 << CPUCFG2_LDISBLIKELY), .SEGBITS = 48, .PABITS = 48, .insn_flags = CPU_MIPS64R2 | INSN_LOONGSON3A | diff --git a/target/mips/cpu.c b/target/mips/cpu.c index b7119cbbb459..e675b9178192 100644 --- a/target/mips/cpu.c +++ b/target/mips/cpu.c @@ -244,6 +244,8 @@ static void mips_cpu_reset_hold(Object *obj) env->CP0_PageGrain_rw_bitmask = env->cpu_model->CP0_PageGrain_rw_bitmask; env->CP0_PageGrain = env->cpu_model->CP0_PageGrain; env->CP0_EBaseWG_rw_bitmask = env->cpu_model->CP0_EBaseWG_rw_bitmask; +env->lcsr_cpucfg1 = env->cpu_model->lcsr_cpucfg1; +env->lcsr_cpucfg2 = env->cpu_model->lcsr_cpucfg2; env->active_fpu.fcr0 = env->cpu_model->CP1_fcr0; env->active_fpu.fcr31_rw_bitmask = env->cpu_model->CP1_fcr31_rw_bitmask; env->active_fpu.fcr31 = env->cpu_model->CP1_fcr31; @@ -507,6 +509,12 @@ static void mips_cpu_initfn(Object *obj) cpu->count_div = clock_new(OBJECT(obj), "clk-div-count"); env->count_clock = clock_new(OBJECT(obj), "clk-count"); env->cpu_model = mcc->cpu_def; +if (mcc->cpu_def->lcsr_cpucfg2 & (1 << CPUCFG2_LCSRP)) { +memory_region_init_io(>system_iocsr, OBJECT(cpu), NULL, +env, "iocsr", UINT64_MAX); +address_space_init(>address_space_iocsr, +>system_iocsr, "IOCSR"); +} } static char *mips_cpu_type_name(const char *cpu_model) diff --git a/target/mips/cpu.h b/target/mips/cpu.h index 1b8107b0af86..f63b128ff3d3 100644 --- a/target/mips/cpu.h +++ b/target/mips/cpu.h @@ -3,6 +3,9 @@ #include "cpu-qom.h" #include "exec/cpu-defs.h" +#ifndef CONFIG_USER_ONLY +#include "exec/memory.h" +#endif #include "fpu/softfloat-types.h" #include "hw/clock.h" #include "mips-defs.h" @@ -1068,6 +1071,33 @@ typedef struct CPUArchState { */ int32_t CP0_DESAVE; target_ulong CP0_KScratch[MIPS_KSCRATCH_NUM]; +/* + * Loongson CSR CPUCFG registers + */ +uint32_t lcsr_cpucfg1; +#define CPUCFG1_FP 0 +#define CPUCFG1_FPREV 1 +#define CPUCFG1_MMI4 +#define CPUCFG1_MSA1 5 +#define CPUCFG1_MSA2 6 +#define CPUCFG1_LSLDR0 16 +#define CPUCFG1_LSPERF 17 +#define CPUCFG1_LSPERFX 18 +#define CPUCFG1_LSSYNCI 19 +#d
[PATCH] target/mips: Rework cp0_timer with clock API
Previous implementation of MIPS cp0_timer computes a cp0_count_ns based on input clock. However rounding error of cp0_count_ns can affect precision of cp0_timer. Using clock API and a divider for cp0_timer, so we can use clock_ns_to_ticks/clock_ns_to_ticks to avoid rounding issue. Also workaround the situation that in such handler flow: count = read_c0_count() write_c0_compare(count) If timer had not progressed when compare was written, the interrupt would trigger again. Signed-off-by: Jiaxun Yang --- This seems fixed MTTCG booting issue on malta 5kEc with SMP. I'm going to do more test and see if we can enable MTTCG for mips64el. --- target/mips/cpu.c | 8 +--- target/mips/cpu.h | 3 ++- target/mips/sysemu/cp0_timer.c | 35 ++ 3 files changed, 26 insertions(+), 20 deletions(-) diff --git a/target/mips/cpu.c b/target/mips/cpu.c index 01e0fbe10db2..b7119cbbb459 100644 --- a/target/mips/cpu.c +++ b/target/mips/cpu.c @@ -449,9 +449,9 @@ static void mips_cp0_period_set(MIPSCPU *cpu) { CPUMIPSState *env = >env; -env->cp0_count_ns = clock_ticks_to_ns(MIPS_CPU(cpu)->clock, - env->cpu_model->CCRes); -assert(env->cp0_count_ns); +clock_set_mul_div(cpu->count_div, env->cpu_model->CCRes, 1); +clock_set_source(cpu->count_div, cpu->clock); +clock_set_source(env->count_clock, cpu->count_div); } static void mips_cpu_realizefn(DeviceState *dev, Error **errp) @@ -504,6 +504,8 @@ static void mips_cpu_initfn(Object *obj) cpu_set_cpustate_pointers(cpu); cpu->clock = qdev_init_clock_in(DEVICE(obj), "clk-in", NULL, cpu, 0); +cpu->count_div = clock_new(OBJECT(obj), "clk-div-count"); +env->count_clock = clock_new(OBJECT(obj), "clk-count"); env->cpu_model = mcc->cpu_def; } diff --git a/target/mips/cpu.h b/target/mips/cpu.h index 142c55af478b..1b8107b0af86 100644 --- a/target/mips/cpu.h +++ b/target/mips/cpu.h @@ -1160,8 +1160,8 @@ typedef struct CPUArchState { const mips_def_t *cpu_model; QEMUTimer *timer; /* Internal timer */ +Clock *count_clock; /* CP0_Count clock */ target_ulong exception_base; /* ExceptionBase input to the core */ -uint64_t cp0_count_ns; /* CP0_Count clock period (in nanoseconds) */ } CPUMIPSState; /** @@ -1178,6 +1178,7 @@ struct ArchCPU { /*< public >*/ Clock *clock; +Clock *count_div; /* Divider for CP0_Count clock */ CPUNegativeOffsetState neg; CPUMIPSState env; }; diff --git a/target/mips/sysemu/cp0_timer.c b/target/mips/sysemu/cp0_timer.c index 70de95d338f8..9d2bcb0dea21 100644 --- a/target/mips/sysemu/cp0_timer.c +++ b/target/mips/sysemu/cp0_timer.c @@ -28,15 +28,26 @@ #include "internal.h" /* MIPS R4K timer */ +static uint32_t cpu_mips_get_count_val(CPUMIPSState *env) +{ +int64_t now_ns; +now_ns = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); +return env->CP0_Count + +(uint32_t)clock_ns_to_ticks(env->count_clock, now_ns); +} + static void cpu_mips_timer_update(CPUMIPSState *env) { uint64_t now_ns, next_ns; uint32_t wait; now_ns = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); -wait = env->CP0_Compare - env->CP0_Count - - (uint32_t)(now_ns / env->cp0_count_ns); -next_ns = now_ns + (uint64_t)wait * env->cp0_count_ns; +wait = env->CP0_Compare - cpu_mips_get_count_val(env); +/* Clamp interval to overflow if virtual time had not progressed */ +if (!wait) { +wait = UINT32_MAX; +} +next_ns = now_ns + clock_ticks_to_ns(env->count_clock, wait); timer_mod(env->timer, next_ns); } @@ -64,7 +75,7 @@ uint32_t cpu_mips_get_count(CPUMIPSState *env) cpu_mips_timer_expire(env); } -return env->CP0_Count + (uint32_t)(now_ns / env->cp0_count_ns); +return cpu_mips_get_count_val(env); } } @@ -79,9 +90,8 @@ void cpu_mips_store_count(CPUMIPSState *env, uint32_t count) env->CP0_Count = count; } else { /* Store new count register */ -env->CP0_Count = count - - (uint32_t)(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) / - env->cp0_count_ns); +env->CP0_Count = count - (uint32_t)clock_ns_to_ticks(env->count_clock, +qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL)); /* Update timer timer */ cpu_mips_timer_update(env); } @@ -107,8 +117,8 @@ void cpu_mips_start_count(CPUMIPSState *env) void cpu_mips_stop_count(CPUMIPSState *env) { /* Store the current value */ -env->CP0_Count += (uint32_t)(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) / - env->cp0_count_ns); +env->CP0_Count += (uint32_t)clock_ns_to_ticks(env->count_clock, +qe
[PATCH 4/4] tests/avocado: Add boot_linux_console test for loongson3-virt
Test loongson3-virt machine againt debian kernel and cpio rootfs. Signed-off-by: Jiaxun Yang --- tests/avocado/boot_linux_console.py | 46 + 1 file changed, 46 insertions(+) diff --git a/tests/avocado/boot_linux_console.py b/tests/avocado/boot_linux_console.py index c0675809e641..fdb479448e47 100644 --- a/tests/avocado/boot_linux_console.py +++ b/tests/avocado/boot_linux_console.py @@ -191,6 +191,52 @@ def test_mips64el_fuloong2e(self): console_pattern = 'Kernel command line: %s' % kernel_command_line self.wait_for_console_pattern(console_pattern) +def test_mips64el_loongson3_virt_cpio(self): +""" +:avocado: tags=arch:mips64el +:avocado: tags=endian:little +:avocado: tags=machine:loongson3-virt +:avocado: tags=cpu:Loongson-3A1000 +:avocado: tags=device:liointc +:avocado: tags=device:loongarch_ipi +:avocado: tags=device:goldfish_rtc +""" +deb_url = ('http://snapshot.debian.org/archive/debian/' + '20230501T024743Z/pool/main/l/linux/' + 'linux-image-5.10.0-22-loongson-3_5.10.178-3_mips64el.deb') +deb_hash = 'af4fcc721b727df0bef31057325e4cc02725ae0c' +deb_path = self.fetch_asset(deb_url, asset_hash=deb_hash) +kernel_path = self.extract_from_deb(deb_path, +'/boot/vmlinuz-5.10.0-22-loongson-3') +initrd_url = ('https://github.com/groeck/linux-build-test/' + 'raw/8584a59e/rootfs/' + 'mipsel64/rootfs.mipsel64r1.cpio.gz') +initrd_hash = '1dbb8a396e916847325284dbe2151167' +initrd_path_gz = self.fetch_asset(initrd_url, algorithm='md5', + asset_hash=initrd_hash) +initrd_path = self.workdir + "rootfs.cpio" +archive.gzip_uncompress(initrd_path_gz, initrd_path) + +self.vm.set_console() +kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + + 'console=ttyS0,115200 ' + + 'rdinit=/sbin/init noreboot') +self.vm.add_args('-kernel', kernel_path, + '-initrd', initrd_path, + '-append', kernel_command_line, + '-no-reboot') +self.vm.launch() +wait_for_console_pattern(self, 'Boot successful.') + +exec_command_and_wait_for_pattern(self, 'cat /proc/cpuinfo', +'ICT Loongson-3') +exec_command_and_wait_for_pattern(self, 'uname -a', +'5.10.0-22-loongson-3') +exec_command_and_wait_for_pattern(self, 'reboot', +'reboot: Restarting system') +# Wait for VM to shut down gracefully +self.vm.wait() + def test_mips_malta_cpio(self): """ :avocado: tags=arch:mips -- 2.39.2 (Apple Git-143)
[PATCH 2/4] hw/intc/loongarch_ipi: Guard LoongArch only features with ifdef
IOCSR based send features are tied to LoongArch's CPU implmentation, ifdef them for LoongArch only so we can build loongarch_ipi on MIPS. Note that Loongson-3A4000 have IOCSR as well, so we may implement those features for MIPS in future. Signed-off-by: Jiaxun Yang --- hw/intc/loongarch_ipi.c | 20 1 file changed, 20 insertions(+) diff --git a/hw/intc/loongarch_ipi.c b/hw/intc/loongarch_ipi.c index 3e453816524e..895a2ee96e1e 100644 --- a/hw/intc/loongarch_ipi.c +++ b/hw/intc/loongarch_ipi.c @@ -50,6 +50,7 @@ static uint64_t loongarch_ipi_readl(void *opaque, hwaddr addr, unsigned size) return ret; } +#ifdef TARGET_LOONGARCH64 static void send_ipi_data(CPULoongArchState *env, uint64_t val, hwaddr addr) { int i, mask = 0, data = 0; @@ -140,6 +141,25 @@ static void any_send(uint64_t val) env = >env; send_ipi_data(env, val, addr); } +#else +static void ipi_send(uint64_t val) +{ +qemu_log_mask(LOG_UNIMP, "%s: Unimplemented send 0x%" PRIx64 "\n", +__func__, val); +} + +static void mail_send(uint64_t val) +{ +qemu_log_mask(LOG_UNIMP, "%s: Unimplemented send 0x%" PRIx64 "\n", +__func__, val); +} + +static void any_send(uint64_t val) +{ +qemu_log_mask(LOG_UNIMP, "%s: Unimplemented send 0x%" PRIx64 "\n", +__func__, val); +} +#endif static void loongarch_ipi_writel(void *opaque, hwaddr addr, uint64_t val, unsigned size) -- 2.39.2 (Apple Git-143)
[PATCH 0/4] hw/mips/loongson3_virt: Wire up loongarch_ipi device
Hi all, This series wires up loongarch_ipi device for loongson3-virt, which is required for SMP support. We also add a new test for loongson3-virt for acceptance harness. Thanks - Jiaxun Jiaxun Yang (4): hw/intc/loongarch_ipi: Bring back all 4 IPI mailboxes hw/intc/loongarch_ipi: Guard LoongArch only features with ifdef hw/mips/loongson3_virt: Wire up loongarch_ipi device tests/avocado: Add boot_linux_console test for loongson3-virt hw/intc/loongarch_ipi.c | 26 ++-- hw/mips/Kconfig | 1 + hw/mips/loongson3_bootp.c | 2 -- hw/mips/loongson3_bootp.h | 3 ++ hw/mips/loongson3_virt.c| 20 +++-- include/hw/intc/loongarch_ipi.h | 4 ++- tests/avocado/boot_linux_console.py | 46 + 7 files changed, 94 insertions(+), 8 deletions(-) -- 2.39.2 (Apple Git-143)
[PATCH 3/4] hw/mips/loongson3_virt: Wire up loongarch_ipi device
Wire up loongarch_ipi device for loongson3_virt machine, so we can have SMP support for TCG backend as well. Signed-off-by: Jiaxun Yang --- hw/mips/Kconfig | 1 + hw/mips/loongson3_bootp.c | 2 -- hw/mips/loongson3_bootp.h | 3 +++ hw/mips/loongson3_virt.c | 20 ++-- 4 files changed, 22 insertions(+), 4 deletions(-) diff --git a/hw/mips/Kconfig b/hw/mips/Kconfig index da3a37e215ec..7cb6c1def16c 100644 --- a/hw/mips/Kconfig +++ b/hw/mips/Kconfig @@ -40,6 +40,7 @@ config LOONGSON3V imply QXL if SPICE select SERIAL select GOLDFISH_RTC +select LOONGARCH_IPI select LOONGSON_LIOINTC select PCI_DEVICES select PCI_EXPRESS_GENERIC_BRIDGE diff --git a/hw/mips/loongson3_bootp.c b/hw/mips/loongson3_bootp.c index f99af229327a..474d3556b2e5 100644 --- a/hw/mips/loongson3_bootp.c +++ b/hw/mips/loongson3_bootp.c @@ -25,8 +25,6 @@ #include "hw/boards.h" #include "hw/mips/loongson3_bootp.h" -#define LOONGSON3_CORE_PER_NODE 4 - static void init_cpu_info(void *g_cpuinfo, uint64_t cpu_freq) { struct efi_cpuinfo_loongson *c = g_cpuinfo; diff --git a/hw/mips/loongson3_bootp.h b/hw/mips/loongson3_bootp.h index d525ab745a69..55f98858a5f4 100644 --- a/hw/mips/loongson3_bootp.h +++ b/hw/mips/loongson3_bootp.h @@ -200,6 +200,8 @@ struct boot_params { struct efi_reset_system_t reset_system; }; +#define LOONGSON3_CORE_PER_NODE 4 + /* Overall MMIO & Memory layout */ enum { VIRT_LOWMEM, @@ -211,6 +213,7 @@ enum { VIRT_BIOS_ROM, VIRT_UART, VIRT_LIOINTC, +VIRT_IPI, VIRT_PCIE_MMIO, VIRT_HIGHMEM }; diff --git a/hw/mips/loongson3_virt.c b/hw/mips/loongson3_virt.c index 25534288dd81..a57245012598 100644 --- a/hw/mips/loongson3_virt.c +++ b/hw/mips/loongson3_virt.c @@ -38,6 +38,7 @@ #include "hw/mips/loongson3_bootp.h" #include "hw/misc/unimp.h" #include "hw/intc/i8259.h" +#include "hw/intc/loongarch_ipi.h" #include "hw/loader.h" #include "hw/isa/superio.h" #include "hw/pci/msi.h" @@ -76,6 +77,7 @@ const MemMapEntry virt_memmap[] = { [VIRT_PCIE_ECAM] = { 0x1a00, 0x200 }, [VIRT_BIOS_ROM] ={ 0x1fc0, 0x20 }, [VIRT_UART] ={ 0x1fe001e0, 0x8 }, +[VIRT_IPI] = { 0x3ff01000, 0x400 }, [VIRT_LIOINTC] = { 0x3ff01400, 0x64 }, [VIRT_PCIE_MMIO] = { 0x4000,0x4000 }, [VIRT_HIGHMEM] = { 0x8000, 0x0 }, /* Variable */ @@ -529,6 +531,8 @@ static void mips_loongson3_virt_init(MachineState *machine) clock_set_hz(cpuclk, DEF_LOONGSON3_FREQ); for (i = 0; i < machine->smp.cpus; i++) { +int node = i / LOONGSON3_CORE_PER_NODE; +int core = i % LOONGSON3_CORE_PER_NODE; int ip; /* init CPUs */ @@ -539,12 +543,24 @@ static void mips_loongson3_virt_init(MachineState *machine) cpu_mips_clock_init(cpu); qemu_register_reset(main_cpu_reset, cpu); -if (i >= 4) { +/* IPI controller is in kernel for KVM */ +if (!kvm_enabled()) { +DeviceState *ipi; + +hwaddr base = ((hwaddr)node << 44) + virt_memmap[VIRT_IPI].base; +base += core * 0x100; +ipi = qdev_new(TYPE_LOONGARCH_IPI); +sysbus_realize_and_unref(SYS_BUS_DEVICE(ipi), _fatal); +qdev_connect_gpio_out(ipi, 0, cpu->env.irq[6]); +sysbus_mmio_map(SYS_BUS_DEVICE(ipi), 0, base); +} + +if (node > 0) { continue; /* Only node-0 can be connected to LIOINTC */ } for (ip = 0; ip < 4 ; ip++) { -int pin = i * 4 + ip; +int pin = core * LOONGSON3_CORE_PER_NODE + ip; sysbus_connect_irq(SYS_BUS_DEVICE(liointc), pin, cpu->env.irq[ip + 2]); } -- 2.39.2 (Apple Git-143)
[PATCH 1/4] hw/intc/loongarch_ipi: Bring back all 4 IPI mailboxes
As per "Loongson 3A5000/3B5000 Processor Reference Manual", Loongson 3A5000's IPI implementation have 4 mailboxes per core. However, in 78464f023b54 ("hw/loongarch/virt: Modify ipi as percpu device"), the number of IPI mailboxes was reduced to one, which mismatches actual hardware. It won't affect LoongArch based system as LoongArch boot code only uses the first mailbox, however MIPS based Loongson boot code uses all 4 mailboxes. Fixes: 78464f023b54 ("hw/loongarch/virt: Modify ipi as percpu device") Signed-off-by: Jiaxun Yang --- hw/intc/loongarch_ipi.c | 6 +++--- include/hw/intc/loongarch_ipi.h | 4 +++- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/hw/intc/loongarch_ipi.c b/hw/intc/loongarch_ipi.c index d6ab91721ea1..3e453816524e 100644 --- a/hw/intc/loongarch_ipi.c +++ b/hw/intc/loongarch_ipi.c @@ -238,14 +238,14 @@ static void loongarch_ipi_init(Object *obj) static const VMStateDescription vmstate_ipi_core = { .name = "ipi-single", -.version_id = 1, -.minimum_version_id = 1, +.version_id = 2, +.minimum_version_id = 2, .fields = (VMStateField[]) { VMSTATE_UINT32(status, IPICore), VMSTATE_UINT32(en, IPICore), VMSTATE_UINT32(set, IPICore), VMSTATE_UINT32(clear, IPICore), -VMSTATE_UINT32_ARRAY(buf, IPICore, 2), +VMSTATE_UINT32_ARRAY(buf, IPICore, IPI_MBX_NUM * 2), VMSTATE_END_OF_LIST() } }; diff --git a/include/hw/intc/loongarch_ipi.h b/include/hw/intc/loongarch_ipi.h index 664e050b926e..6c6194786e80 100644 --- a/include/hw/intc/loongarch_ipi.h +++ b/include/hw/intc/loongarch_ipi.h @@ -28,6 +28,8 @@ #define MAIL_SEND_OFFSET 0 #define ANY_SEND_OFFSET (IOCSR_ANY_SEND - IOCSR_MAIL_SEND) +#define IPI_MBX_NUM 4 + #define TYPE_LOONGARCH_IPI "loongarch_ipi" OBJECT_DECLARE_SIMPLE_TYPE(LoongArchIPI, LOONGARCH_IPI) @@ -37,7 +39,7 @@ typedef struct IPICore { uint32_t set; uint32_t clear; /* 64bit buf divide into 2 32bit buf */ -uint32_t buf[2]; +uint32_t buf[IPI_MBX_NUM * 2]; qemu_irq irq; } IPICore; -- 2.39.2 (Apple Git-143)
Re: [PATCH 21/22] tests/avocado: use http for mipsdistros.mips.com
> 2023年5月3日 10:12,Alex Bennée 写道: > > As the cached assets have fallen out of our cache new attempts to > fetch these binaries fail hard due to certificate expirty. It's hard > to find a contact email for the domain as the root page of mipsdistros > throws up some random XML. I suspect Amazon are merely the hosts. > > Signed-off-by: Alex Bennée > Cc: Philippe Mathieu-Daudé Hi all, Just reached MIPS to get certification fixed. Thanks - Jiaxun
Re: [PATCH] linux-user: Fix mips fp64 executables loading
> 2023年4月4日 06:21,Daniil Kovalev 写道: > > If a program requires fr1, we should set the FR bit of CP0 control status > register and add F64 hardware flag. The corresponding `else if` branch > statement is copied from the linux kernel sources (see `arch_check_elf` > function > in linux/arch/mips/kernel/elf.c). > > Signed-off-by: Daniil Kovalev Reviewed-by: Jiaxun Yang Thanks! > --- > linux-user/mips/cpu_loop.c | 5 - > 1 file changed, 4 insertions(+), 1 deletion(-) > > diff --git a/linux-user/mips/cpu_loop.c b/linux-user/mips/cpu_loop.c > index d5c1c7941d..8735e58bad 100644 > --- a/linux-user/mips/cpu_loop.c > +++ b/linux-user/mips/cpu_loop.c > @@ -290,7 +290,10 @@ void target_cpu_copy_regs(CPUArchState *env, struct > target_pt_regs *regs) > env->CP0_Status |= (1 << CP0St_FR); > env->hflags |= MIPS_HFLAG_F64; > } > -} else if (!prog_req.fre && !prog_req.frdefault && > +} else if (prog_req.fr1) { > +env->CP0_Status |= (1 << CP0St_FR); > +env->hflags |= MIPS_HFLAG_F64; > +} else if (!prog_req.fre && !prog_req.frdefault && > !prog_req.fr1 && !prog_req.single && !prog_req.soft) { > fprintf(stderr, "qemu: Can't find a matching FPU mode\n"); > exit(1); > -- > 2.40.0 >
Re: [PATCH] linux-user/mips: Low down switchable NaN2008 requirement
> 2023年3月15日 08:18,Philippe Mathieu-Daudé 写道: > > On 11/3/23 13:39, Jiaxun Yang wrote: >>> 2023年3月9日 12:32,Philippe Mathieu-Daudé 写道: >>> >>> Hi Jiaxun, >>> >>> On 11/2/23 18:34, Jiaxun Yang wrote: >>>> Previously switchable NaN2008 requires fcsr31.nan2008 to be writable >>>> for guest. However as per MIPS arch spec this bit can never be writable. >>>> This cause NaN2008 ELF to be rejected by QEMU. >>>> NaN2008 can be enabled on R2~R5 processors, just make it available >>>> unconditionally. >>>> Signed-off-by: Jiaxun Yang >>>> --- >>>> linux-user/mips/cpu_loop.c | 3 +-- >>>> 1 file changed, 1 insertion(+), 2 deletions(-) >>>> diff --git a/linux-user/mips/cpu_loop.c b/linux-user/mips/cpu_loop.c >>>> index d5c1c7941d..b5c2ca4a3e 100644 >>>> --- a/linux-user/mips/cpu_loop.c >>>> +++ b/linux-user/mips/cpu_loop.c >>>> @@ -301,8 +301,7 @@ void target_cpu_copy_regs(CPUArchState *env, struct >>>> target_pt_regs *regs) >>>> } >>>> if (((info->elf_flags & EF_MIPS_NAN2008) != 0) != >>>> ((env->active_fpu.fcr31 & (1 << FCR31_NAN2008)) != 0)) { >>>> -if ((env->active_fpu.fcr31_rw_bitmask & >>>> - (1 << FCR31_NAN2008)) == 0) { >>>> +if (!(env->insn_flags & ISA_MIPS_R2)) { >>>> fprintf(stderr, "ELF binary's NaN mode not supported by >>>> CPU\n"); >>>> exit(1); >>>> } >>> >>> Looking at R6.06 revision history: >>> >>> 5.03 August 21, 2013 >>> >>> • ABS2008 and NAN2008 fields of Table 5.7 “FCSR RegisterField >>>Descriptions” were optional in release 3 and could be R/W, >>>but as of release 5 are required, read-only, and preset by >>>hardware. >>> So I tried with this change: >>> >>> -- >8 -- >>> diff --git a/target/mips/cpu.c b/target/mips/cpu.c >>> index 05caf54999..5f1364ffaf 100644 >>> --- a/target/mips/cpu.c >>> +++ b/target/mips/cpu.c >>> @@ -243,6 +243,13 @@ static void mips_cpu_reset_hold(Object *obj) >>> env->CP0_EBaseWG_rw_bitmask = env->cpu_model->CP0_EBaseWG_rw_bitmask; >>> env->active_fpu.fcr0 = env->cpu_model->CP1_fcr0; >>> env->active_fpu.fcr31_rw_bitmask = env->cpu_model->CP1_fcr31_rw_bitmask; >>> +if (env->insn_flags & ISA_MIPS_R5) { >>> +assert(!(env->cpu_model->CP1_fcr31_rw_bitmask & (1 << >>> FCR31_ABS2008))); >>> +assert(!(env->cpu_model->CP1_fcr31_rw_bitmask & (1 << >>> FCR31_NAN2008))); >>> +} else if (env->insn_flags & ISA_MIPS_R3) { >>> +assert(env->cpu_model->CP1_fcr31_rw_bitmask & (1 << >>> FCR31_ABS2008)); >>> +assert(env->cpu_model->CP1_fcr31_rw_bitmask & (1 << >>> FCR31_NAN2008)); >>> +} >>> env->active_fpu.fcr31 = env->cpu_model->CP1_fcr31; >>> env->msair = env->cpu_model->MSAIR; >>> env->insn_flags = env->cpu_model->insn_flags; >>> --- >>> >>> and got: >>> >>> $ for cpu in $(./qemu-system-mips64el -cpu help | cut -d\' -f2); do \ >>> echo -n ${cpu}...;echo q \ >>> | ./qemu-system-mips64el -accel tcg -cpu ${cpu} \ >>> -S -monitor stdio 1> /dev/null || break; \ >>> echo OK; done >>> 4Kc...OK >>> 4Km...OK >>> 4KEcR1...OK >>> 4KEmR1...OK >>> 4KEc...OK >>> 4KEm...OK >>> 24Kc...OK >>> 24KEc...OK >>> 24Kf...OK >>> 34Kf...OK >>> 74Kf...OK >>> M14K...OK >>> M14Kc...OK >>> P5600...OK >>> mips32r6-generic...OK >>> I7200...OK >>> R4000...OK >>> VR5432...OK >>> 5Kc...OK >>> 5Kf...OK >>> 20Kc...OK >>> MIPS64R2-generic...OK >>> 5KEc...OK >>> 5KEf...OK >>> I6400...OK >>> I6500...OK >>> Loongson-2E...OK >>> Loongson-2F...OK >>> Loongson-3A1000...OK >>> Loongson-3A4000...OK >>> mips64dspr2...OK >>> Octeon68XX...OK >>> $ >> Well that’s because there is no CPU being marked as MIPS Release 3 in QEMU, >> and only >> P5600 is marked as MIPS Release 5. >> In reality R3 implementations are all advertising themself as R2, and later >> RCs of microAptiv >> and interaptiv can all be configured as NaN2008 only. So for those CPUs we >> have binary compiled >> with -march=mips32r2 -mnan=2008. >> Given that default CPU of mips32r2 in QEMU is 24Kf, I think the best >> approach to deal with such >> situation is to allow NaN2008 to be enabled for early processors for >> linux-user. >> There is a NAN2008 Debian port for test: >> http://repo.oss.cipunited.com/mipsel-nan2008/tarball/sid-mipsel-nan2008-20230309-1.tar.xz > > $ qemu-mipsel -L sid-mipsel-nan2008-20230313-1/usr -cpu P5600 usr/bin/uname > -ms > Linux mips > > What about something like: That would lost capability of testing NaN2008 binaries again other CPU models. Thanks - Jiaxun > > -- >8 -- > --- a/linux-user/mips/target_elf.h > +++ b/linux-user/mips/target_elf.h > @@ -15,6 +15,9 @@ static inline const char *cpu_get_model(uint32_t eflags) > if ((eflags & EF_MIPS_MACH) == EF_MIPS_MACH_5900) { > return "R5900"; > } > +if (eflags & EF_MIPS_NAN2008) { > +return "P5600"; > +} > return "24Kf"; > } > #endif > ---
Re: [PATCH] linux-user/mips: Low down switchable NaN2008 requirement
> 2023年3月9日 12:32,Philippe Mathieu-Daudé 写道: > > Hi Jiaxun, > > On 11/2/23 18:34, Jiaxun Yang wrote: >> Previously switchable NaN2008 requires fcsr31.nan2008 to be writable >> for guest. However as per MIPS arch spec this bit can never be writable. >> This cause NaN2008 ELF to be rejected by QEMU. >> NaN2008 can be enabled on R2~R5 processors, just make it available >> unconditionally. >> Signed-off-by: Jiaxun Yang >> --- >> linux-user/mips/cpu_loop.c | 3 +-- >> 1 file changed, 1 insertion(+), 2 deletions(-) >> diff --git a/linux-user/mips/cpu_loop.c b/linux-user/mips/cpu_loop.c >> index d5c1c7941d..b5c2ca4a3e 100644 >> --- a/linux-user/mips/cpu_loop.c >> +++ b/linux-user/mips/cpu_loop.c >> @@ -301,8 +301,7 @@ void target_cpu_copy_regs(CPUArchState *env, struct >> target_pt_regs *regs) >> } >> if (((info->elf_flags & EF_MIPS_NAN2008) != 0) != >> ((env->active_fpu.fcr31 & (1 << FCR31_NAN2008)) != 0)) { >> -if ((env->active_fpu.fcr31_rw_bitmask & >> - (1 << FCR31_NAN2008)) == 0) { >> +if (!(env->insn_flags & ISA_MIPS_R2)) { >> fprintf(stderr, "ELF binary's NaN mode not supported by CPU\n"); >> exit(1); >> } > > Looking at R6.06 revision history: > > 5.03 August 21, 2013 > > • ABS2008 and NAN2008 fields of Table 5.7 “FCSR RegisterField >Descriptions” were optional in release 3 and could be R/W, >but as of release 5 are required, read-only, and preset by >hardware. > So I tried with this change: > > -- >8 -- > diff --git a/target/mips/cpu.c b/target/mips/cpu.c > index 05caf54999..5f1364ffaf 100644 > --- a/target/mips/cpu.c > +++ b/target/mips/cpu.c > @@ -243,6 +243,13 @@ static void mips_cpu_reset_hold(Object *obj) > env->CP0_EBaseWG_rw_bitmask = env->cpu_model->CP0_EBaseWG_rw_bitmask; > env->active_fpu.fcr0 = env->cpu_model->CP1_fcr0; > env->active_fpu.fcr31_rw_bitmask = env->cpu_model->CP1_fcr31_rw_bitmask; > +if (env->insn_flags & ISA_MIPS_R5) { > +assert(!(env->cpu_model->CP1_fcr31_rw_bitmask & (1 << > FCR31_ABS2008))); > +assert(!(env->cpu_model->CP1_fcr31_rw_bitmask & (1 << > FCR31_NAN2008))); > +} else if (env->insn_flags & ISA_MIPS_R3) { > +assert(env->cpu_model->CP1_fcr31_rw_bitmask & (1 << FCR31_ABS2008)); > +assert(env->cpu_model->CP1_fcr31_rw_bitmask & (1 << FCR31_NAN2008)); > +} > env->active_fpu.fcr31 = env->cpu_model->CP1_fcr31; > env->msair = env->cpu_model->MSAIR; > env->insn_flags = env->cpu_model->insn_flags; > --- > > and got: > > $ for cpu in $(./qemu-system-mips64el -cpu help | cut -d\' -f2); do \ > echo -n ${cpu}...;echo q \ > | ./qemu-system-mips64el -accel tcg -cpu ${cpu} \ > -S -monitor stdio 1> /dev/null || break; \ > echo OK; done > 4Kc...OK > 4Km...OK > 4KEcR1...OK > 4KEmR1...OK > 4KEc...OK > 4KEm...OK > 24Kc...OK > 24KEc...OK > 24Kf...OK > 34Kf...OK > 74Kf...OK > M14K...OK > M14Kc...OK > P5600...OK > mips32r6-generic...OK > I7200...OK > R4000...OK > VR5432...OK > 5Kc...OK > 5Kf...OK > 20Kc...OK > MIPS64R2-generic...OK > 5KEc...OK > 5KEf...OK > I6400...OK > I6500...OK > Loongson-2E...OK > Loongson-2F...OK > Loongson-3A1000...OK > Loongson-3A4000...OK > mips64dspr2...OK > Octeon68XX...OK > $ Well that’s because there is no CPU being marked as MIPS Release 3 in QEMU, and only P5600 is marked as MIPS Release 5. In reality R3 implementations are all advertising themself as R2, and later RCs of microAptiv and interaptiv can all be configured as NaN2008 only. So for those CPUs we have binary compiled with -march=mips32r2 -mnan=2008. Given that default CPU of mips32r2 in QEMU is 24Kf, I think the best approach to deal with such situation is to allow NaN2008 to be enabled for early processors for linux-user. There is a NAN2008 Debian port for test: http://repo.oss.cipunited.com/mipsel-nan2008/tarball/sid-mipsel-nan2008-20230309-1.tar.xz Thanks > > Which CPU are you testing? Where can I get such ELF binary for testing? > > Thanks, > > Phil.
Re: [PATCH v2 0/2] MIPS Virt machine
> 2023年3月7日 21:07,Philippe Mathieu-Daudé 写道: > > On 7/3/23 21:14, Philippe Mathieu-Daudé wrote: >> On 7/3/23 21:07, Jiaxun Yang wrote: >>> >>> >>>> 2023年3月7日 15:01,Philippe Mathieu-Daudé 写道: >>>> >>>> On 4/3/23 23:38, Jiaxun Yang wrote: >>>>> Hi there, >>>>> This patchset is to add a new machine type for MIPS architecture, which >>>>> is purely a VirtIO machine. >>>> >>>>> Jiaxun Yang (2): >>>>> hw/misc: Add MIPS Trickbox device >>>>> hw/mips: Add MIPS virt board >>>> Thanks, applied with following changes: >>> >>> Thanks for those clean-ups! > > Unfortunately I have to drop this due to the libfdt > dependency, which fails the --disable-fdt job: > https://gitlab.com/philmd/qemu/-/jobs/3890587748 Perhaps we should just select TARGET_NEED_FDT for all MIPS variants? Thanks - Jiaxun
Re: [PATCH v2 2/2] hw/mips: Add MIPS virt board
> 2023年3月7日 20:10,Philippe Mathieu-Daudé 写道: > > On 4/3/23 23:38, Jiaxun Yang wrote: >> MIPS virt board is design to utilize existing VirtIO infrastures >> but also comptitable with MIPS's existing internal simulation tools. >> It includes virtio-pci, virtio-mmio, pcie gpex, flash rom, fw_cfg, >> goldfish-rtc and MIPS CPS system. >> It should be able to cooperate with any MIPS CPU cores. >> Signed-off-by: Jiaxun Yang >> --- >> v1: >> - Rename to virt board >> - Convert BIOS flash to ROM >> - Cleanups >> v2: >> - Fix fdt flash >> - Remove UP variant >> --- >> MAINTAINERS | 7 + >> configs/devices/mips-softmmu/common.mak | 1 + >> docs/system/target-mips.rst | 22 + >> hw/mips/Kconfig | 17 + >> hw/mips/meson.build | 1 + >> hw/mips/virt.c | 916 >> 6 files changed, 964 insertions(+) >> create mode 100644 hw/mips/virt.c > > >> +static void virt_machine_init(MachineState *machine) >> +{ >> +MIPSVirtState *s = MIPS_VIRT_MACHINE(machine); >> +MemoryRegion *system_memory = get_system_memory(); >> +const MemMapEntry *memmap = virt_memmap; >> +int i; >> + >> +s->cpuclk = clock_new(OBJECT(machine), "cpu-refclk"); >> +clock_set_hz(s->cpuclk, VIRT_CPU_REF_CLK_FREQ); >> + >> +s->cps = MIPS_CPS(qdev_new(TYPE_MIPS_CPS)); >> +object_property_set_str(OBJECT(s->cps), "cpu-type", machine->cpu_type, >> +_fatal); >> +object_property_set_int(OBJECT(s->cps), "num-core", machine->smp.cpus, >> +_fatal); >> +qdev_connect_clock_in(DEVICE(s->cps), "clk-in", s->cpuclk); >> +sysbus_realize(SYS_BUS_DEVICE(s->cps), _fatal); > > qemu-system-mips64el: Property 'mips-cps.num-core' not found > > I'm worried. I suppose you want this property: > > DEFINE_PROP_UINT32("num-vp", MIPSCPSState, num_vp, 1), Yes > > Is your series based on mainstream QEMU? Whoops, rebasing issue not caught by CI… Accidentally leaked part of following patch into this one, was trying to fix SMP support for earlier CPUs. Apologise for this. Thanks - Jiaxun