From 75b208c28316095c4685e8596ceb9e3f656592e2 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 23 Nov 2020 07:17:47 -0500 Subject: [PATCH 001/113] target/i386: fix operand order for PDEP and PEXT For PDEP and PEXT, the mask is provided in the memory (mod+r/m) operand, and therefore is loaded in s->T0 by gen_ldst_modrm. The source is provided in the second source operand (VEX.vvvv) and therefore is loaded in s->T1. Fix the order in which they are passed to the helpers. Reported-by: Lenard Szolnoki Analyzed-by: Lenard Szolnoki Fixes: https://bugs.launchpad.net/qemu/+bug/1605123 Reviewed-by: Richard Henderson Signed-off-by: Paolo Bonzini --- target/i386/translate.c | 8 +++---- tests/tcg/i386/Makefile.target | 3 +++ tests/tcg/i386/test-i386-bmi2.c | 42 +++++++++++++++++++++++++++++++++ 3 files changed, 49 insertions(+), 4 deletions(-) create mode 100644 tests/tcg/i386/test-i386-bmi2.c diff --git a/target/i386/translate.c b/target/i386/translate.c index 4c57307e42..e8f5f5803a 100644 --- a/target/i386/translate.c +++ b/target/i386/translate.c @@ -3936,14 +3936,14 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, } ot = mo_64_32(s->dflag); gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0); - /* Note that by zero-extending the mask operand, we + /* Note that by zero-extending the source operand, we automatically handle zero-extending the result. */ if (ot == MO_64) { tcg_gen_mov_tl(s->T1, cpu_regs[s->vex_v]); } else { tcg_gen_ext32u_tl(s->T1, cpu_regs[s->vex_v]); } - gen_helper_pdep(cpu_regs[reg], s->T0, s->T1); + gen_helper_pdep(cpu_regs[reg], s->T1, s->T0); break; case 0x2f5: /* pext Gy, By, Ey */ @@ -3954,14 +3954,14 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, } ot = mo_64_32(s->dflag); gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0); - /* Note that by zero-extending the mask operand, we + /* Note that by zero-extending the source operand, we automatically handle zero-extending the result. */ if (ot == MO_64) { tcg_gen_mov_tl(s->T1, cpu_regs[s->vex_v]); } else { tcg_gen_ext32u_tl(s->T1, cpu_regs[s->vex_v]); } - gen_helper_pext(cpu_regs[reg], s->T0, s->T1); + gen_helper_pext(cpu_regs[reg], s->T1, s->T0); break; case 0x1f6: /* adcx Gy, Ey */ diff --git a/tests/tcg/i386/Makefile.target b/tests/tcg/i386/Makefile.target index a66232a67d..ad187cb2c9 100644 --- a/tests/tcg/i386/Makefile.target +++ b/tests/tcg/i386/Makefile.target @@ -18,6 +18,9 @@ test-i386-pcmpistri: CFLAGS += -msse4.2 run-test-i386-pcmpistri: QEMU_OPTS += -cpu max run-plugin-test-i386-pcmpistri-%: QEMU_OPTS += -cpu max +run-test-i386-bmi2: QEMU_OPTS += -cpu max +run-plugin-test-i386-bmi2-%: QEMU_OPTS += -cpu max + # # hello-i386 is a barebones app # diff --git a/tests/tcg/i386/test-i386-bmi2.c b/tests/tcg/i386/test-i386-bmi2.c new file mode 100644 index 0000000000..935a4d2a73 --- /dev/null +++ b/tests/tcg/i386/test-i386-bmi2.c @@ -0,0 +1,42 @@ +/* See if various BMI2 instructions give expected results */ +#include +#include + +int main(int argc, char *argv[]) { + uint64_t ehlo = 0x202020204f4c4845ull; + uint64_t mask = 0xa080800302020001ull; + uint32_t result32; + +#ifdef __x86_64 + uint64_t result64; + + /* 64 bits */ + asm volatile ("pextq %2, %1, %0" : "=r"(result64) : "r"(ehlo), "m"(mask)); + assert(result64 == 133); + + asm volatile ("pdepq %2, %1, %0" : "=r"(result64) : "r"(result64), "m"(mask)); + assert(result64 == (ehlo & mask)); + + asm volatile ("pextq %2, %1, %0" : "=r"(result64) : "r"(-1ull), "m"(mask)); + assert(result64 == 511); /* mask has 9 bits set */ + + asm volatile ("pdepq %2, %1, %0" : "=r"(result64) : "r"(-1ull), "m"(mask)); + assert(result64 == mask); +#endif + + /* 32 bits */ + asm volatile ("pextl %2, %k1, %k0" : "=r"(result32) : "r"((uint32_t) ehlo), "m"(mask)); + assert(result32 == 5); + + asm volatile ("pdepl %2, %k1, %k0" : "=r"(result32) : "r"(result32), "m"(mask)); + assert(result32 == (uint32_t)(ehlo & mask)); + + asm volatile ("pextl %2, %k1, %k0" : "=r"(result32) : "r"(-1ull), "m"(mask)); + assert(result32 == 7); /* mask has 3 bits set */ + + asm volatile ("pdepl %2, %k1, %k0" : "=r"(result32) : "r"(-1ull), "m"(mask)); + assert(result32 == (uint32_t)mask); + + return 0; +} + From c1bb5418e32ec70c72af332354b5963eab7a5579 Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Mon, 5 Oct 2020 15:18:19 +0100 Subject: [PATCH 002/113] target/i386: Support up to 32768 CPUs without IRQ remapping The IOAPIC has an 'Extended Destination ID' field in its RTE, which maps to bits 11-4 of the MSI address. Since those address bits fall within a given 4KiB page they were historically non-trivial to use on real hardware. The Intel IOMMU uses the lowest bit to indicate a remappable format MSI, and then the remaining 7 bits are part of the index. Where the remappable format bit isn't set, we can actually use the other seven to allow external (IOAPIC and MSI) interrupts to reach up to 32768 CPUs instead of just the 255 permitted on bare metal. Signed-off-by: David Woodhouse Message-Id: <78097f9218300e63e751e077a0a5ca029b56ba46.camel@infradead.org> [Fix UBSAN warning. - Paolo] Signed-off-by: Paolo Bonzini Signed-off-by: David Woodhouse --- hw/i386/kvm/apic.c | 7 ++ hw/i386/pc.c | 16 ++--- include/standard-headers/asm-x86/kvm_para.h | 1 + target/i386/cpu.c | 5 +- target/i386/kvm.c | 79 +++++++++++++++------ target/i386/kvm_i386.h | 2 + 6 files changed, 79 insertions(+), 31 deletions(-) diff --git a/hw/i386/kvm/apic.c b/hw/i386/kvm/apic.c index dd29906061..b226b674e8 100644 --- a/hw/i386/kvm/apic.c +++ b/hw/i386/kvm/apic.c @@ -183,6 +183,13 @@ static void kvm_send_msi(MSIMessage *msg) { int ret; + /* + * The message has already passed through interrupt remapping if enabled, + * but the legacy extended destination ID in low bits still needs to be + * handled. + */ + msg->address = kvm_swizzle_msi_ext_dest_id(msg->address); + ret = kvm_irqchip_send_msi(kvm_state, *msg); if (ret < 0) { fprintf(stderr, "KVM: injection failed, MSI lost (%s)\n", diff --git a/hw/i386/pc.c b/hw/i386/pc.c index 9e29f3792b..640fb5b0b7 100644 --- a/hw/i386/pc.c +++ b/hw/i386/pc.c @@ -104,6 +104,7 @@ const size_t pc_compat_5_2_len = G_N_ELEMENTS(pc_compat_5_2); GlobalProperty pc_compat_5_1[] = { { "ICH9-LPC", "x-smi-cpu-hotplug", "off" }, + { TYPE_X86_CPU, "kvm-msi-ext-dest-id", "off" }, }; const size_t pc_compat_5_1_len = G_N_ELEMENTS(pc_compat_5_1); @@ -796,17 +797,12 @@ void pc_machine_done(Notifier *notifier, void *data) fw_cfg_modify_i16(x86ms->fw_cfg, FW_CFG_NB_CPUS, x86ms->boot_cpus); } - if (x86ms->apic_id_limit > 255 && !xen_enabled()) { - IntelIOMMUState *iommu = INTEL_IOMMU_DEVICE(x86_iommu_get_default()); - if (!iommu || !x86_iommu_ir_supported(X86_IOMMU_DEVICE(iommu)) || - iommu->intr_eim != ON_OFF_AUTO_ON) { - error_report("current -smp configuration requires " - "Extended Interrupt Mode enabled. " - "You can add an IOMMU using: " - "-device intel-iommu,intremap=on,eim=on"); - exit(EXIT_FAILURE); - } + if (x86ms->apic_id_limit > 255 && !xen_enabled() && + !kvm_irqchip_in_kernel()) { + error_report("current -smp configuration requires kernel " + "irqchip support."); + exit(EXIT_FAILURE); } } diff --git a/include/standard-headers/asm-x86/kvm_para.h b/include/standard-headers/asm-x86/kvm_para.h index 07877d3295..215d01b4ec 100644 --- a/include/standard-headers/asm-x86/kvm_para.h +++ b/include/standard-headers/asm-x86/kvm_para.h @@ -32,6 +32,7 @@ #define KVM_FEATURE_POLL_CONTROL 12 #define KVM_FEATURE_PV_SCHED_YIELD 13 #define KVM_FEATURE_ASYNC_PF_INT 14 +#define KVM_FEATURE_MSI_EXT_DEST_ID 15 #define KVM_HINTS_REALTIME 0 diff --git a/target/i386/cpu.c b/target/i386/cpu.c index 5a8c96072e..b90ed05897 100644 --- a/target/i386/cpu.c +++ b/target/i386/cpu.c @@ -799,7 +799,7 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = { "kvmclock", "kvm-nopiodelay", "kvm-mmu", "kvmclock", "kvm-asyncpf", "kvm-steal-time", "kvm-pv-eoi", "kvm-pv-unhalt", NULL, "kvm-pv-tlb-flush", NULL, "kvm-pv-ipi", - "kvm-poll-control", "kvm-pv-sched-yield", "kvm-asyncpf-int", NULL, + "kvm-poll-control", "kvm-pv-sched-yield", "kvm-asyncpf-int", "kvm-msi-ext-dest-id", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, "kvmclock-stable-bit", NULL, NULL, NULL, @@ -4114,6 +4114,7 @@ static PropValue kvm_default_props[] = { { "kvm-pv-eoi", "on" }, { "kvmclock-stable-bit", "on" }, { "x2apic", "on" }, + { "kvm-msi-ext-dest-id", "off" }, { "acpi", "off" }, { "monitor", "off" }, { "svm", "off" }, @@ -5140,6 +5141,8 @@ static void x86_cpu_load_model(X86CPU *cpu, X86CPUModel *model) if (kvm_enabled()) { if (!kvm_irqchip_in_kernel()) { x86_cpu_change_kvm_default("x2apic", "off"); + } else if (kvm_irqchip_is_split() && kvm_enable_x2apic()) { + x86_cpu_change_kvm_default("kvm-msi-ext-dest-id", "on"); } x86_cpu_apply_props(cpu, kvm_default_props); diff --git a/target/i386/kvm.c b/target/i386/kvm.c index a2934dda02..bcfa4b03e0 100644 --- a/target/i386/kvm.c +++ b/target/i386/kvm.c @@ -416,6 +416,9 @@ uint32_t kvm_arch_get_supported_cpuid(KVMState *s, uint32_t function, if (!kvm_irqchip_in_kernel()) { ret &= ~(1U << KVM_FEATURE_PV_UNHALT); } + if (kvm_irqchip_is_split()) { + ret |= 1U << KVM_FEATURE_MSI_EXT_DEST_ID; + } } else if (function == KVM_CPUID_FEATURES && reg == R_EDX) { ret |= 1U << KVM_HINTS_REALTIME; } @@ -4589,38 +4592,74 @@ int kvm_arch_irqchip_create(KVMState *s) } } +uint64_t kvm_swizzle_msi_ext_dest_id(uint64_t address) +{ + CPUX86State *env; + uint64_t ext_id; + + if (!first_cpu) { + return address; + } + env = &X86_CPU(first_cpu)->env; + if (!(env->features[FEAT_KVM] & (1 << KVM_FEATURE_MSI_EXT_DEST_ID))) { + return address; + } + + /* + * If the remappable format bit is set, or the upper bits are + * already set in address_hi, or the low extended bits aren't + * there anyway, do nothing. + */ + ext_id = address & (0xff << MSI_ADDR_DEST_IDX_SHIFT); + if (!ext_id || (ext_id & (1 << MSI_ADDR_DEST_IDX_SHIFT)) || (address >> 32)) { + return address; + } + + address &= ~ext_id; + address |= ext_id << 35; + return address; +} + int kvm_arch_fixup_msi_route(struct kvm_irq_routing_entry *route, uint64_t address, uint32_t data, PCIDevice *dev) { X86IOMMUState *iommu = x86_iommu_get_default(); if (iommu) { - int ret; - MSIMessage src, dst; X86IOMMUClass *class = X86_IOMMU_DEVICE_GET_CLASS(iommu); - if (!class->int_remap) { + if (class->int_remap) { + int ret; + MSIMessage src, dst; + + src.address = route->u.msi.address_hi; + src.address <<= VTD_MSI_ADDR_HI_SHIFT; + src.address |= route->u.msi.address_lo; + src.data = route->u.msi.data; + + ret = class->int_remap(iommu, &src, &dst, dev ? \ + pci_requester_id(dev) : \ + X86_IOMMU_SID_INVALID); + if (ret) { + trace_kvm_x86_fixup_msi_error(route->gsi); + return 1; + } + + /* + * Handled untranslated compatibilty format interrupt with + * extended destination ID in the low bits 11-5. */ + dst.address = kvm_swizzle_msi_ext_dest_id(dst.address); + + route->u.msi.address_hi = dst.address >> VTD_MSI_ADDR_HI_SHIFT; + route->u.msi.address_lo = dst.address & VTD_MSI_ADDR_LO_MASK; + route->u.msi.data = dst.data; return 0; } - - src.address = route->u.msi.address_hi; - src.address <<= VTD_MSI_ADDR_HI_SHIFT; - src.address |= route->u.msi.address_lo; - src.data = route->u.msi.data; - - ret = class->int_remap(iommu, &src, &dst, dev ? \ - pci_requester_id(dev) : \ - X86_IOMMU_SID_INVALID); - if (ret) { - trace_kvm_x86_fixup_msi_error(route->gsi); - return 1; - } - - route->u.msi.address_hi = dst.address >> VTD_MSI_ADDR_HI_SHIFT; - route->u.msi.address_lo = dst.address & VTD_MSI_ADDR_LO_MASK; - route->u.msi.data = dst.data; } + address = kvm_swizzle_msi_ext_dest_id(address); + route->u.msi.address_hi = address >> VTD_MSI_ADDR_HI_SHIFT; + route->u.msi.address_lo = address & VTD_MSI_ADDR_LO_MASK; return 0; } diff --git a/target/i386/kvm_i386.h b/target/i386/kvm_i386.h index a4a619cebb..dc72508389 100644 --- a/target/i386/kvm_i386.h +++ b/target/i386/kvm_i386.h @@ -48,4 +48,6 @@ bool kvm_has_waitpkg(void); bool kvm_hv_vpindex_settable(void); +uint64_t kvm_swizzle_msi_ext_dest_id(uint64_t address); + #endif From c2ba0515f2df58a661fcb5d6485139877d92ab1b Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Fri, 13 Nov 2020 17:56:18 +0800 Subject: [PATCH 003/113] target/i386: seg_helper: Correct segment selector nullification in the RET/IRET helper Per the SDM, when returning to outer privilege level, for segment registers (ES, FS, GS, and DS) if the check fails, the segment selector becomes null, but QEMU clears the base/limit/flags as well as nullifying the segment selector, which should be a spec violation. Real hardware seems to be compliant with the spec, at least on one Coffee Lake board I tested. Signed-off-by: Bin Meng Message-Id: <1605261378-77971-1-git-send-email-bmeng.cn@gmail.com> Signed-off-by: Paolo Bonzini --- target/i386/seg_helper.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/target/i386/seg_helper.c b/target/i386/seg_helper.c index 09b6554660..e6ffa1f018 100644 --- a/target/i386/seg_helper.c +++ b/target/i386/seg_helper.c @@ -2108,7 +2108,10 @@ static inline void validate_seg(CPUX86State *env, int seg_reg, int cpl) if (!(e2 & DESC_CS_MASK) || !(e2 & DESC_C_MASK)) { /* data or non conforming code segment */ if (dpl < cpl) { - cpu_x86_load_seg_cache(env, seg_reg, 0, 0, 0, 0); + cpu_x86_load_seg_cache(env, seg_reg, 0, + env->segs[seg_reg].base, + env->segs[seg_reg].limit, + env->segs[seg_reg].flags & ~DESC_P_MASK); } } } From faf20793b5af15ed4bea9c40dd8e6ae46d51be23 Mon Sep 17 00:00:00 2001 From: Sunil Muthuswamy Date: Wed, 28 Oct 2020 02:23:19 +0000 Subject: [PATCH 004/113] WHPX: support for the kernel-irqchip on/off This patch adds support the kernel-irqchip option for WHPX with on or off value. 'split' value is not supported for the option. The option only works for the latest version of Windows (ones that are coming out on Insiders). The change maintains backward compatibility on older version of Windows where this option is not supported. Signed-off-by: Sunil Muthuswamy Message-Id: Signed-off-by: Paolo Bonzini --- MAINTAINERS | 1 + hw/i386/x86.c | 6 +- include/sysemu/whpx.h | 22 +++ softmmu/cpus.c | 3 +- softmmu/vl.c | 8 +- target/i386/cpu.c | 3 + target/i386/meson.build | 1 + target/i386/whp-dispatch.h | 9 +- target/i386/whpx-all.c | 291 ++++++++++++++++++++++++++++++++----- target/i386/whpx-apic.c | 274 ++++++++++++++++++++++++++++++++++ 10 files changed, 578 insertions(+), 40 deletions(-) create mode 100644 target/i386/whpx-apic.c diff --git a/MAINTAINERS b/MAINTAINERS index a83416d54c..aa39490a24 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -452,6 +452,7 @@ WHPX CPUs M: Sunil Muthuswamy S: Supported F: target/i386/whpx-all.c +F: target/i386/whpx-apic.c F: target/i386/whpx-cpus.c F: target/i386/whp-dispatch.h F: accel/stubs/whpx-stub.c diff --git a/hw/i386/x86.c b/hw/i386/x86.c index d68a9eaefc..7c1f64a1fc 100644 --- a/hw/i386/x86.c +++ b/hw/i386/x86.c @@ -31,6 +31,7 @@ #include "qapi/qapi-visit-common.h" #include "qapi/visitor.h" #include "sysemu/qtest.h" +#include "sysemu/whpx.h" #include "sysemu/numa.h" #include "sysemu/replay.h" #include "sysemu/sysemu.h" @@ -532,7 +533,8 @@ static void pic_irq_request(void *opaque, int irq, int level) X86CPU *cpu = X86_CPU(cs); trace_x86_pic_interrupt(irq, level); - if (cpu->apic_state && !kvm_irqchip_in_kernel()) { + if (cpu->apic_state && !kvm_irqchip_in_kernel() && + !whpx_apic_in_platform()) { CPU_FOREACH(cs) { cpu = X86_CPU(cs); if (apic_accept_pic_intr(cpu->apic_state)) { @@ -558,7 +560,7 @@ int cpu_get_pic_interrupt(CPUX86State *env) X86CPU *cpu = env_archcpu(env); int intno; - if (!kvm_irqchip_in_kernel()) { + if (!kvm_irqchip_in_kernel() && !whpx_apic_in_platform()) { intno = apic_get_interrupt(cpu->apic_state); if (intno >= 0) { return intno; diff --git a/include/sysemu/whpx.h b/include/sysemu/whpx.h index 59edf13742..9346fd92e9 100644 --- a/include/sysemu/whpx.h +++ b/include/sysemu/whpx.h @@ -15,11 +15,33 @@ #ifdef CONFIG_WHPX +#include "whp-dispatch.h" + +struct whpx_state { + uint64_t mem_quota; + WHV_PARTITION_HANDLE partition; + bool kernel_irqchip_allowed; + bool kernel_irqchip_required; + bool apic_in_platform; +}; + +struct whpx_lapic_state { + struct { + uint32_t data; + uint32_t padding[3]; + } fields[256]; +}; + +extern struct whpx_state whpx_global; int whpx_enabled(void); +void whpx_apic_get(DeviceState *s); +#define whpx_apic_in_platform() (whpx_global.apic_in_platform) + #else /* CONFIG_WHPX */ #define whpx_enabled() (0) +#define whpx_apic_in_platform() (0) #endif /* CONFIG_WHPX */ diff --git a/softmmu/cpus.c b/softmmu/cpus.c index e46ac68ad0..1dc20b9dc3 100644 --- a/softmmu/cpus.c +++ b/softmmu/cpus.c @@ -41,6 +41,7 @@ #include "sysemu/replay.h" #include "sysemu/runstate.h" #include "sysemu/cpu-timers.h" +#include "sysemu/whpx.h" #include "hw/boards.h" #include "hw/hw.h" @@ -88,7 +89,7 @@ bool cpu_thread_is_idle(CPUState *cpu) return true; } if (!cpu->halted || cpu_has_work(cpu) || - kvm_halt_in_kernel()) { + kvm_halt_in_kernel() || whpx_apic_in_platform()) { return false; } return true; diff --git a/softmmu/vl.c b/softmmu/vl.c index e6e0ad5a92..bbe65d3742 100644 --- a/softmmu/vl.c +++ b/softmmu/vl.c @@ -2501,11 +2501,15 @@ static int machine_set_property(void *opaque, object_register_sugar_prop(ACCEL_CLASS_NAME("xen"), qom_name, value); return 0; } - if (g_str_equal(qom_name, "kvm-shadow-mem") || - g_str_equal(qom_name, "kernel-irqchip")) { + if (g_str_equal(qom_name, "kvm-shadow-mem")) { object_register_sugar_prop(ACCEL_CLASS_NAME("kvm"), qom_name, value); return 0; } + if (g_str_equal(qom_name, "kernel-irqchip")) { + object_register_sugar_prop(ACCEL_CLASS_NAME("kvm"), qom_name, value); + object_register_sugar_prop(ACCEL_CLASS_NAME("whpx"), qom_name, value); + return 0; + } return object_parse_property_opt(opaque, name, value, "type", errp); } diff --git a/target/i386/cpu.c b/target/i386/cpu.c index b90ed05897..af48e3f79e 100644 --- a/target/i386/cpu.c +++ b/target/i386/cpu.c @@ -30,6 +30,7 @@ #include "sysemu/hvf.h" #include "sysemu/cpus.h" #include "sysemu/xen.h" +#include "sysemu/whpx.h" #include "kvm_i386.h" #include "sev_i386.h" @@ -6148,6 +6149,8 @@ APICCommonClass *apic_get_class(void) apic_type = "kvm-apic"; } else if (xen_enabled()) { apic_type = "xen-apic"; + } else if (whpx_apic_in_platform()) { + apic_type = "whpx-apic"; } return APIC_COMMON_CLASS(object_class_by_name(apic_type)); diff --git a/target/i386/meson.build b/target/i386/meson.build index a1a02f3e99..fc3ee80386 100644 --- a/target/i386/meson.build +++ b/target/i386/meson.build @@ -33,6 +33,7 @@ i386_softmmu_ss.add(when: 'CONFIG_KVM', if_true: files('kvm.c')) i386_softmmu_ss.add(when: 'CONFIG_WHPX', if_true: files( 'whpx-all.c', 'whpx-cpus.c', + 'whpx-apic.c', )) i386_softmmu_ss.add(when: 'CONFIG_HAX', if_true: files( 'hax-all.c', diff --git a/target/i386/whp-dispatch.h b/target/i386/whp-dispatch.h index b18aba20ed..cef5d848bd 100644 --- a/target/i386/whp-dispatch.h +++ b/target/i386/whp-dispatch.h @@ -30,6 +30,14 @@ */ #define LIST_WINHVPLATFORM_FUNCTIONS_SUPPLEMENTAL(X) \ X(HRESULT, WHvSuspendPartitionTime, (WHV_PARTITION_HANDLE Partition)) \ + X(HRESULT, WHvRequestInterrupt, (WHV_PARTITION_HANDLE Partition, \ + WHV_INTERRUPT_CONTROL* Interrupt, UINT32 InterruptControlSize)) \ + X(HRESULT, WHvGetVirtualProcessorInterruptControllerState2, \ + (WHV_PARTITION_HANDLE Partition, UINT32 VpIndex, PVOID State, \ + UINT32 StateSize, UINT32* WrittenSize)) \ + X(HRESULT, WHvSetVirtualProcessorInterruptControllerState2, \ + (WHV_PARTITION_HANDLE Partition, UINT32 VpIndex, PVOID State, \ + UINT32 StateSize)) \ #define LIST_WINHVEMULATION_FUNCTIONS(X) \ X(HRESULT, WHvEmulatorCreateEmulator, (const WHV_EMULATOR_CALLBACKS* Callbacks, WHV_EMULATOR_HANDLE* Emulator)) \ @@ -37,7 +45,6 @@ X(HRESULT, WHvEmulatorTryIoEmulation, (WHV_EMULATOR_HANDLE Emulator, VOID* Context, const WHV_VP_EXIT_CONTEXT* VpContext, const WHV_X64_IO_PORT_ACCESS_CONTEXT* IoInstructionContext, WHV_EMULATOR_STATUS* EmulatorReturnStatus)) \ X(HRESULT, WHvEmulatorTryMmioEmulation, (WHV_EMULATOR_HANDLE Emulator, VOID* Context, const WHV_VP_EXIT_CONTEXT* VpContext, const WHV_MEMORY_ACCESS_CONTEXT* MmioInstructionContext, WHV_EMULATOR_STATUS* EmulatorReturnStatus)) \ - #define WHP_DEFINE_TYPE(return_type, function_name, signature) \ typedef return_type (WINAPI *function_name ## _t) signature; diff --git a/target/i386/whpx-all.c b/target/i386/whpx-all.c index f4f3e33eac..3b824fc9d7 100644 --- a/target/i386/whpx-all.c +++ b/target/i386/whpx-all.c @@ -19,10 +19,15 @@ #include "sysemu/runstate.h" #include "qemu/main-loop.h" #include "hw/boards.h" +#include "hw/i386/ioapic.h" +#include "hw/i386/apic_internal.h" #include "qemu/error-report.h" #include "qapi/error.h" +#include "qapi/qapi-types-common.h" +#include "qapi/qapi-visit-common.h" #include "migration/blocker.h" #include "whp-dispatch.h" +#include #include "whpx-cpus.h" @@ -31,11 +36,6 @@ #define HYPERV_APIC_BUS_FREQUENCY (200000000ULL) -struct whpx_state { - uint64_t mem_quota; - WHV_PARTITION_HANDLE partition; -}; - static const WHV_REGISTER_NAME whpx_register_names[] = { /* X64 General purpose registers */ @@ -152,6 +152,7 @@ struct whpx_vcpu { WHV_EMULATOR_HANDLE emulator; bool window_registered; bool interruptable; + bool ready_for_pic_interrupt; uint64_t tpr; uint64_t apic_base; bool interruption_pending; @@ -163,7 +164,7 @@ struct whpx_vcpu { static bool whpx_allowed; static bool whp_dispatch_initialized; static HMODULE hWinHvPlatform, hWinHvEmulation; - +static uint32_t max_vcpu_index; struct whpx_state whpx_global; struct WHPDispatch whp_dispatch; @@ -599,6 +600,10 @@ static void whpx_get_registers(CPUState *cpu) assert(idx == RTL_NUMBER_OF(whpx_register_names)); + if (whpx_apic_in_platform()) { + whpx_apic_get(x86_cpu->apic_state); + } + return; } @@ -820,26 +825,42 @@ static void whpx_vcpu_pre_run(CPUState *cpu) } /* Get pending hard interruption or replay one that was overwritten */ - if (!vcpu->interruption_pending && - vcpu->interruptable && (env->eflags & IF_MASK)) { - assert(!new_int.InterruptionPending); - if (cpu->interrupt_request & CPU_INTERRUPT_HARD) { - cpu->interrupt_request &= ~CPU_INTERRUPT_HARD; - irq = cpu_get_pic_interrupt(env); - if (irq >= 0) { - new_int.InterruptionType = WHvX64PendingInterrupt; - new_int.InterruptionPending = 1; - new_int.InterruptionVector = irq; + if (!whpx_apic_in_platform()) { + if (!vcpu->interruption_pending && + vcpu->interruptable && (env->eflags & IF_MASK)) { + assert(!new_int.InterruptionPending); + if (cpu->interrupt_request & CPU_INTERRUPT_HARD) { + cpu->interrupt_request &= ~CPU_INTERRUPT_HARD; + irq = cpu_get_pic_interrupt(env); + if (irq >= 0) { + new_int.InterruptionType = WHvX64PendingInterrupt; + new_int.InterruptionPending = 1; + new_int.InterruptionVector = irq; + } } } - } - /* Setup interrupt state if new one was prepared */ - if (new_int.InterruptionPending) { - reg_values[reg_count].PendingInterruption = new_int; - reg_names[reg_count] = WHvRegisterPendingInterruption; - reg_count += 1; - } + /* Setup interrupt state if new one was prepared */ + if (new_int.InterruptionPending) { + reg_values[reg_count].PendingInterruption = new_int; + reg_names[reg_count] = WHvRegisterPendingInterruption; + reg_count += 1; + } + } else if (vcpu->ready_for_pic_interrupt && + (cpu->interrupt_request & CPU_INTERRUPT_HARD)) { + cpu->interrupt_request &= ~CPU_INTERRUPT_HARD; + irq = cpu_get_pic_interrupt(env); + if (irq >= 0) { + reg_names[reg_count] = WHvRegisterPendingEvent; + reg_values[reg_count].ExtIntEvent = (WHV_X64_PENDING_EXT_INT_EVENT) + { + .EventPending = 1, + .EventType = WHvX64PendingEventExtInt, + .Vector = irq, + }; + reg_count += 1; + } + } /* Sync the TPR to the CR8 if was modified during the intercept */ tpr = cpu_get_apic_tpr(x86_cpu->apic_state); @@ -854,14 +875,17 @@ static void whpx_vcpu_pre_run(CPUState *cpu) /* Update the state of the interrupt delivery notification */ if (!vcpu->window_registered && cpu->interrupt_request & CPU_INTERRUPT_HARD) { - reg_values[reg_count].DeliverabilityNotifications.InterruptNotification - = 1; + reg_values[reg_count].DeliverabilityNotifications = + (WHV_X64_DELIVERABILITY_NOTIFICATIONS_REGISTER) { + .InterruptNotification = 1 + }; vcpu->window_registered = 1; reg_names[reg_count] = WHvX64RegisterDeliverabilityNotifications; reg_count += 1; } qemu_mutex_unlock_iothread(); + vcpu->ready_for_pic_interrupt = false; if (reg_count) { hr = whp_dispatch.WHvSetVirtualProcessorRegisters( @@ -948,7 +972,7 @@ static int whpx_vcpu_run(CPUState *cpu) int ret; whpx_vcpu_process_async_events(cpu); - if (cpu->halted) { + if (cpu->halted && !whpx_apic_in_platform()) { cpu->exception_index = EXCP_HLT; qatomic_set(&cpu->exit_request, false); return 0; @@ -992,14 +1016,114 @@ static int whpx_vcpu_run(CPUState *cpu) break; case WHvRunVpExitReasonX64InterruptWindow: + vcpu->ready_for_pic_interrupt = 1; vcpu->window_registered = 0; ret = 0; break; + case WHvRunVpExitReasonX64ApicEoi: + assert(whpx_apic_in_platform()); + ioapic_eoi_broadcast(vcpu->exit_ctx.ApicEoi.InterruptVector); + break; + case WHvRunVpExitReasonX64Halt: ret = whpx_handle_halt(cpu); break; + case WHvRunVpExitReasonX64ApicInitSipiTrap: { + WHV_INTERRUPT_CONTROL ipi = {0}; + uint64_t icr = vcpu->exit_ctx.ApicInitSipi.ApicIcr; + uint32_t delivery_mode = + (icr & APIC_ICR_DELIV_MOD) >> APIC_ICR_DELIV_MOD_SHIFT; + int dest_shorthand = + (icr & APIC_ICR_DEST_SHORT) >> APIC_ICR_DEST_SHORT_SHIFT; + bool broadcast = false; + bool include_self = false; + uint32_t i; + + /* We only registered for INIT and SIPI exits. */ + if ((delivery_mode != APIC_DM_INIT) && + (delivery_mode != APIC_DM_SIPI)) { + error_report( + "WHPX: Unexpected APIC exit that is not a INIT or SIPI"); + break; + } + + if (delivery_mode == APIC_DM_INIT) { + ipi.Type = WHvX64InterruptTypeInit; + } else { + ipi.Type = WHvX64InterruptTypeSipi; + } + + ipi.DestinationMode = + ((icr & APIC_ICR_DEST_MOD) >> APIC_ICR_DEST_MOD_SHIFT) ? + WHvX64InterruptDestinationModeLogical : + WHvX64InterruptDestinationModePhysical; + + ipi.TriggerMode = + ((icr & APIC_ICR_TRIGGER_MOD) >> APIC_ICR_TRIGGER_MOD_SHIFT) ? + WHvX64InterruptTriggerModeLevel : + WHvX64InterruptTriggerModeEdge; + + ipi.Vector = icr & APIC_VECTOR_MASK; + switch (dest_shorthand) { + /* no shorthand. Bits 56-63 contain the destination. */ + case 0: + ipi.Destination = (icr >> 56) & APIC_VECTOR_MASK; + hr = whp_dispatch.WHvRequestInterrupt(whpx->partition, + &ipi, sizeof(ipi)); + if (FAILED(hr)) { + error_report("WHPX: Failed to request interrupt hr=%08lx", + hr); + } + + break; + + /* self */ + case 1: + include_self = true; + break; + + /* broadcast, including self */ + case 2: + broadcast = true; + include_self = true; + break; + + /* broadcast, excluding self */ + case 3: + broadcast = true; + break; + } + + if (!broadcast && !include_self) { + break; + } + + for (i = 0; i <= max_vcpu_index; i++) { + if (i == cpu->cpu_index && !include_self) { + continue; + } + + /* + * Assuming that APIC Ids are identity mapped since + * WHvX64RegisterApicId & WHvX64RegisterInitialApicId registers + * are not handled yet and the hypervisor doesn't allow the + * guest to modify the APIC ID. + */ + ipi.Destination = i; + hr = whp_dispatch.WHvRequestInterrupt(whpx->partition, + &ipi, sizeof(ipi)); + if (FAILED(hr)) { + error_report( + "WHPX: Failed to request SIPI for %d, hr=%08lx", + i, hr); + } + } + + break; + } + case WHvRunVpExitReasonCanceled: cpu->exception_index = EXCP_INTERRUPT; ret = 1; @@ -1314,6 +1438,7 @@ int whpx_init_vcpu(CPUState *cpu) vcpu->interruptable = true; cpu->vcpu_dirty = true; cpu->hax_vcpu = (struct hax_vcpu_state *)vcpu; + max_vcpu_index = max(max_vcpu_index, cpu->cpu_index); qemu_add_vm_change_state_handler(whpx_cpu_update_state, cpu->env_ptr); return 0; @@ -1549,6 +1674,43 @@ error: return false; } +static void whpx_set_kernel_irqchip(Object *obj, Visitor *v, + const char *name, void *opaque, + Error **errp) +{ + struct whpx_state *whpx = &whpx_global; + OnOffSplit mode; + + if (!visit_type_OnOffSplit(v, name, &mode, errp)) { + return; + } + + switch (mode) { + case ON_OFF_SPLIT_ON: + whpx->kernel_irqchip_allowed = true; + whpx->kernel_irqchip_required = true; + break; + + case ON_OFF_SPLIT_OFF: + whpx->kernel_irqchip_allowed = false; + whpx->kernel_irqchip_required = false; + break; + + case ON_OFF_SPLIT_SPLIT: + error_setg(errp, "WHPX: split irqchip currently not supported"); + error_append_hint(errp, + "Try without kernel-irqchip or with kernel-irqchip=on|off"); + break; + + default: + /* + * The value was checked in visit_type_OnOffSplit() above. If + * we get here, then something is wrong in QEMU. + */ + abort(); + } +} + /* * Partition support */ @@ -1562,6 +1724,7 @@ static int whpx_accel_init(MachineState *ms) UINT32 whpx_cap_size; WHV_PARTITION_PROPERTY prop; UINT32 cpuidExitList[] = {1, 0x80000001}; + WHV_CAPABILITY_FEATURES features = {0}; whpx = &whpx_global; @@ -1570,7 +1733,6 @@ static int whpx_accel_init(MachineState *ms) goto error; } - memset(whpx, 0, sizeof(struct whpx_state)); whpx->mem_quota = ms->ram_size; hr = whp_dispatch.WHvGetCapability( @@ -1582,6 +1744,14 @@ static int whpx_accel_init(MachineState *ms) goto error; } + hr = whp_dispatch.WHvGetCapability( + WHvCapabilityCodeFeatures, &features, sizeof(features), NULL); + if (FAILED(hr)) { + error_report("WHPX: Failed to query capabilities, hr=%08lx", hr); + ret = -EINVAL; + goto error; + } + hr = whp_dispatch.WHvCreatePartition(&whpx->partition); if (FAILED(hr)) { error_report("WHPX: Failed to create partition, hr=%08lx", hr); @@ -1604,18 +1774,55 @@ static int whpx_accel_init(MachineState *ms) goto error; } + /* + * Error out if WHP doesn't support apic emulation and user is requiring + * it. + */ + if (whpx->kernel_irqchip_required && (!features.LocalApicEmulation || + !whp_dispatch.WHvSetVirtualProcessorInterruptControllerState2)) { + error_report("WHPX: kernel irqchip requested, but unavailable. " + "Try without kernel-irqchip or with kernel-irqchip=off"); + ret = -EINVAL; + goto error; + } + + if (whpx->kernel_irqchip_allowed && features.LocalApicEmulation && + whp_dispatch.WHvSetVirtualProcessorInterruptControllerState2) { + WHV_X64_LOCAL_APIC_EMULATION_MODE mode = + WHvX64LocalApicEmulationModeXApic; + printf("WHPX: setting APIC emulation mode in the hypervisor\n"); + hr = whp_dispatch.WHvSetPartitionProperty( + whpx->partition, + WHvPartitionPropertyCodeLocalApicEmulationMode, + &mode, + sizeof(mode)); + if (FAILED(hr)) { + error_report("WHPX: Failed to enable kernel irqchip hr=%08lx", hr); + if (whpx->kernel_irqchip_required) { + error_report("WHPX: kernel irqchip requested, but unavailable"); + ret = -EINVAL; + goto error; + } + } else { + whpx->apic_in_platform = true; + } + } + + /* Register for MSR and CPUID exits */ memset(&prop, 0, sizeof(WHV_PARTITION_PROPERTY)); prop.ExtendedVmExits.X64MsrExit = 1; prop.ExtendedVmExits.X64CpuidExit = 1; - hr = whp_dispatch.WHvSetPartitionProperty( - whpx->partition, - WHvPartitionPropertyCodeExtendedVmExits, - &prop, - sizeof(WHV_PARTITION_PROPERTY)); + if (whpx_apic_in_platform()) { + prop.ExtendedVmExits.X64ApicInitSipiExitTrap = 1; + } + hr = whp_dispatch.WHvSetPartitionProperty( + whpx->partition, + WHvPartitionPropertyCodeExtendedVmExits, + &prop, + sizeof(WHV_PARTITION_PROPERTY)); if (FAILED(hr)) { - error_report("WHPX: Failed to enable partition extended X64MsrExit and" - " X64CpuidExit hr=%08lx", hr); + error_report("WHPX: Failed to enable MSR & CPUIDexit, hr=%08lx", hr); ret = -EINVAL; goto error; } @@ -1668,11 +1875,27 @@ static void whpx_accel_class_init(ObjectClass *oc, void *data) ac->name = "WHPX"; ac->init_machine = whpx_accel_init; ac->allowed = &whpx_allowed; + + object_class_property_add(oc, "kernel-irqchip", "on|off|split", + NULL, whpx_set_kernel_irqchip, + NULL, NULL); + object_class_property_set_description(oc, "kernel-irqchip", + "Configure WHPX in-kernel irqchip"); +} + +static void whpx_accel_instance_init(Object *obj) +{ + struct whpx_state *whpx = &whpx_global; + + memset(whpx, 0, sizeof(struct whpx_state)); + /* Turn on kernel-irqchip, by default */ + whpx->kernel_irqchip_allowed = true; } static const TypeInfo whpx_accel_type = { .name = ACCEL_CLASS_NAME("whpx"), .parent = TYPE_ACCEL, + .instance_init = whpx_accel_instance_init, .class_init = whpx_accel_class_init, }; diff --git a/target/i386/whpx-apic.c b/target/i386/whpx-apic.c new file mode 100644 index 0000000000..b127a3cb8a --- /dev/null +++ b/target/i386/whpx-apic.c @@ -0,0 +1,274 @@ +/* + * WHPX platform APIC support + * + * Copyright (c) 2011 Siemens AG + * + * Authors: + * Jan Kiszka + * John Starks + * + * This work is licensed under the terms of the GNU GPL version 2. + * See the COPYING file in the top-level directory. + */ +#include "qemu/osdep.h" +#include "qemu-common.h" +#include "cpu.h" +#include "hw/i386/apic_internal.h" +#include "hw/i386/apic-msidef.h" +#include "hw/pci/msi.h" +#include "sysemu/hw_accel.h" +#include "sysemu/whpx.h" +#include "whp-dispatch.h" + +static void whpx_put_apic_state(APICCommonState *s, + struct whpx_lapic_state *kapic) +{ + int i; + + memset(kapic, 0, sizeof(*kapic)); + kapic->fields[0x2].data = s->id << 24; + kapic->fields[0x3].data = s->version | ((APIC_LVT_NB - 1) << 16); + kapic->fields[0x8].data = s->tpr; + kapic->fields[0xd].data = s->log_dest << 24; + kapic->fields[0xe].data = s->dest_mode << 28 | 0x0fffffff; + kapic->fields[0xf].data = s->spurious_vec; + for (i = 0; i < 8; i++) { + kapic->fields[0x10 + i].data = s->isr[i]; + kapic->fields[0x18 + i].data = s->tmr[i]; + kapic->fields[0x20 + i].data = s->irr[i]; + } + + kapic->fields[0x28].data = s->esr; + kapic->fields[0x30].data = s->icr[0]; + kapic->fields[0x31].data = s->icr[1]; + for (i = 0; i < APIC_LVT_NB; i++) { + kapic->fields[0x32 + i].data = s->lvt[i]; + } + + kapic->fields[0x38].data = s->initial_count; + kapic->fields[0x3e].data = s->divide_conf; +} + +static void whpx_get_apic_state(APICCommonState *s, + struct whpx_lapic_state *kapic) +{ + int i, v; + + s->id = kapic->fields[0x2].data >> 24; + s->tpr = kapic->fields[0x8].data; + s->arb_id = kapic->fields[0x9].data; + s->log_dest = kapic->fields[0xd].data >> 24; + s->dest_mode = kapic->fields[0xe].data >> 28; + s->spurious_vec = kapic->fields[0xf].data; + for (i = 0; i < 8; i++) { + s->isr[i] = kapic->fields[0x10 + i].data; + s->tmr[i] = kapic->fields[0x18 + i].data; + s->irr[i] = kapic->fields[0x20 + i].data; + } + + s->esr = kapic->fields[0x28].data; + s->icr[0] = kapic->fields[0x30].data; + s->icr[1] = kapic->fields[0x31].data; + for (i = 0; i < APIC_LVT_NB; i++) { + s->lvt[i] = kapic->fields[0x32 + i].data; + } + + s->initial_count = kapic->fields[0x38].data; + s->divide_conf = kapic->fields[0x3e].data; + + v = (s->divide_conf & 3) | ((s->divide_conf >> 1) & 4); + s->count_shift = (v + 1) & 7; + + s->initial_count_load_time = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); + apic_next_timer(s, s->initial_count_load_time); +} + +static void whpx_apic_set_base(APICCommonState *s, uint64_t val) +{ + s->apicbase = val; +} + +static void whpx_put_apic_base(CPUState *cpu, uint64_t val) +{ + HRESULT hr; + WHV_REGISTER_VALUE reg_value = {.Reg64 = val}; + WHV_REGISTER_NAME reg_name = WHvX64RegisterApicBase; + + hr = whp_dispatch.WHvSetVirtualProcessorRegisters( + whpx_global.partition, + cpu->cpu_index, + ®_name, 1, + ®_value); + + if (FAILED(hr)) { + error_report("WHPX: Failed to set MSR APIC base, hr=%08lx", hr); + } +} + +static void whpx_apic_set_tpr(APICCommonState *s, uint8_t val) +{ + s->tpr = val; +} + +static uint8_t whpx_apic_get_tpr(APICCommonState *s) +{ + return s->tpr; +} + +static void whpx_apic_vapic_base_update(APICCommonState *s) +{ + /* not implemented yet */ +} + +static void whpx_apic_put(CPUState *cs, run_on_cpu_data data) +{ + APICCommonState *s = data.host_ptr; + struct whpx_lapic_state kapic; + HRESULT hr; + + whpx_put_apic_base(CPU(s->cpu), s->apicbase); + whpx_put_apic_state(s, &kapic); + + hr = whp_dispatch.WHvSetVirtualProcessorInterruptControllerState2( + whpx_global.partition, + cs->cpu_index, + &kapic, + sizeof(kapic)); + if (FAILED(hr)) { + fprintf(stderr, + "WHvSetVirtualProcessorInterruptControllerState failed: %08lx\n", + hr); + + abort(); + } +} + +void whpx_apic_get(DeviceState *dev) +{ + APICCommonState *s = APIC_COMMON(dev); + CPUState *cpu = CPU(s->cpu); + struct whpx_lapic_state kapic; + + HRESULT hr = whp_dispatch.WHvGetVirtualProcessorInterruptControllerState2( + whpx_global.partition, + cpu->cpu_index, + &kapic, + sizeof(kapic), + NULL); + if (FAILED(hr)) { + fprintf(stderr, + "WHvSetVirtualProcessorInterruptControllerState failed: %08lx\n", + hr); + + abort(); + } + + whpx_get_apic_state(s, &kapic); +} + +static void whpx_apic_post_load(APICCommonState *s) +{ + run_on_cpu(CPU(s->cpu), whpx_apic_put, RUN_ON_CPU_HOST_PTR(s)); +} + +static void whpx_apic_external_nmi(APICCommonState *s) +{ +} + +static void whpx_send_msi(MSIMessage *msg) +{ + uint64_t addr = msg->address; + uint32_t data = msg->data; + uint8_t dest = (addr & MSI_ADDR_DEST_ID_MASK) >> MSI_ADDR_DEST_ID_SHIFT; + uint8_t vector = (data & MSI_DATA_VECTOR_MASK) >> MSI_DATA_VECTOR_SHIFT; + uint8_t dest_mode = (addr >> MSI_ADDR_DEST_MODE_SHIFT) & 0x1; + uint8_t trigger_mode = (data >> MSI_DATA_TRIGGER_SHIFT) & 0x1; + uint8_t delivery = (data >> MSI_DATA_DELIVERY_MODE_SHIFT) & 0x7; + + WHV_INTERRUPT_CONTROL interrupt = { + /* Values correspond to delivery modes */ + .Type = delivery, + .DestinationMode = dest_mode ? + WHvX64InterruptDestinationModeLogical : + WHvX64InterruptDestinationModePhysical, + + .TriggerMode = trigger_mode ? + WHvX64InterruptTriggerModeLevel : WHvX64InterruptTriggerModeEdge, + .Reserved = 0, + .Vector = vector, + .Destination = dest, + }; + HRESULT hr = whp_dispatch.WHvRequestInterrupt(whpx_global.partition, + &interrupt, sizeof(interrupt)); + if (FAILED(hr)) { + fprintf(stderr, "whpx: injection failed, MSI (%llx, %x) delivery: %d, " + "dest_mode: %d, trigger mode: %d, vector: %d, lost (%08lx)\n", + addr, data, delivery, dest_mode, trigger_mode, vector, hr); + } +} + +static uint64_t whpx_apic_mem_read(void *opaque, hwaddr addr, + unsigned size) +{ + return ~(uint64_t)0; +} + +static void whpx_apic_mem_write(void *opaque, hwaddr addr, + uint64_t data, unsigned size) +{ + MSIMessage msg = { .address = addr, .data = data }; + whpx_send_msi(&msg); +} + +static const MemoryRegionOps whpx_apic_io_ops = { + .read = whpx_apic_mem_read, + .write = whpx_apic_mem_write, + .endianness = DEVICE_NATIVE_ENDIAN, +}; + +static void whpx_apic_reset(APICCommonState *s) +{ + /* Not used by WHPX. */ + s->wait_for_sipi = 0; + + run_on_cpu(CPU(s->cpu), whpx_apic_put, RUN_ON_CPU_HOST_PTR(s)); +} + +static void whpx_apic_realize(DeviceState *dev, Error **errp) +{ + APICCommonState *s = APIC_COMMON(dev); + + memory_region_init_io(&s->io_memory, OBJECT(s), &whpx_apic_io_ops, s, + "whpx-apic-msi", APIC_SPACE_SIZE); + + msi_nonbroken = true; +} + +static void whpx_apic_class_init(ObjectClass *klass, void *data) +{ + APICCommonClass *k = APIC_COMMON_CLASS(klass); + + k->realize = whpx_apic_realize; + k->reset = whpx_apic_reset; + k->set_base = whpx_apic_set_base; + k->set_tpr = whpx_apic_set_tpr; + k->get_tpr = whpx_apic_get_tpr; + k->post_load = whpx_apic_post_load; + k->vapic_base_update = whpx_apic_vapic_base_update; + k->external_nmi = whpx_apic_external_nmi; + k->send_msi = whpx_send_msi; +} + +static const TypeInfo whpx_apic_info = { + .name = "whpx-apic", + .parent = TYPE_APIC_COMMON, + .instance_size = sizeof(APICCommonState), + .class_init = whpx_apic_class_init, +}; + +static void whpx_apic_register_types(void) +{ + type_register_static(&whpx_apic_info); +} + +type_init(whpx_apic_register_types) From a6195b5b368865cab9200807763a9ad84d4eba64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Fri, 23 Oct 2020 17:19:15 +0200 Subject: [PATCH 005/113] docs/devel/loads-stores: Add regexp for DMA functions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Richard Henderson Reviewed-by: Edgar E. Iglesias Signed-off-by: Philippe Mathieu-Daudé Message-Id: <20201023151923.3243652-3-philmd@redhat.com> Signed-off-by: Paolo Bonzini --- docs/devel/loads-stores.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/devel/loads-stores.rst b/docs/devel/loads-stores.rst index 59c1225391..ee43f5dfee 100644 --- a/docs/devel/loads-stores.rst +++ b/docs/devel/loads-stores.rst @@ -483,6 +483,8 @@ make sure our existing code is doing things correctly. Regexes for git grep - ``\`` + - ``\`` + - ``\`` ``pci_dma_*`` and ``{ld,st}*_pci_dma`` ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ From 169cbac12d4fad5922619a0b64ad0aa66e9365a7 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Tue, 27 Oct 2020 12:12:57 -0400 Subject: [PATCH 006/113] qom: eliminate identical functions Most property release functions in qom/object.c only free the opaque value. Combine all of them into a single function. Signed-off-by: Paolo Bonzini --- qom/object.c | 36 +++++++----------------------------- 1 file changed, 7 insertions(+), 29 deletions(-) diff --git a/qom/object.c b/qom/object.c index 1065355233..75a78c9343 100644 --- a/qom/object.c +++ b/qom/object.c @@ -2174,11 +2174,10 @@ static void property_set_str(Object *obj, Visitor *v, const char *name, g_free(value); } -static void property_release_str(Object *obj, const char *name, - void *opaque) +static void property_release_data(Object *obj, const char *name, + void *opaque) { - StringProperty *prop = opaque; - g_free(prop); + g_free(opaque); } ObjectProperty * @@ -2194,7 +2193,7 @@ object_property_add_str(Object *obj, const char *name, return object_property_add(obj, name, "string", get ? property_get_str : NULL, set ? property_set_str : NULL, - property_release_str, + property_release_data, prop); } @@ -2251,13 +2250,6 @@ static void property_set_bool(Object *obj, Visitor *v, const char *name, prop->set(obj, value, errp); } -static void property_release_bool(Object *obj, const char *name, - void *opaque) -{ - BoolProperty *prop = opaque; - g_free(prop); -} - ObjectProperty * object_property_add_bool(Object *obj, const char *name, bool (*get)(Object *, Error **), @@ -2271,7 +2263,7 @@ object_property_add_bool(Object *obj, const char *name, return object_property_add(obj, name, "bool", get ? property_get_bool : NULL, set ? property_set_bool : NULL, - property_release_bool, + property_release_data, prop); } @@ -2320,13 +2312,6 @@ static void property_set_enum(Object *obj, Visitor *v, const char *name, prop->set(obj, value, errp); } -static void property_release_enum(Object *obj, const char *name, - void *opaque) -{ - EnumProperty *prop = opaque; - g_free(prop); -} - ObjectProperty * object_property_add_enum(Object *obj, const char *name, const char *typename, @@ -2343,7 +2328,7 @@ object_property_add_enum(Object *obj, const char *name, return object_property_add(obj, name, typename, get ? property_get_enum : NULL, set ? property_set_enum : NULL, - property_release_enum, + property_release_data, prop); } @@ -2410,13 +2395,6 @@ out_end: visit_end_struct(v, NULL); } -static void property_release_tm(Object *obj, const char *name, - void *opaque) -{ - TMProperty *prop = opaque; - g_free(prop); -} - ObjectProperty * object_property_add_tm(Object *obj, const char *name, void (*get)(Object *, struct tm *, Error **)) @@ -2427,7 +2405,7 @@ object_property_add_tm(Object *obj, const char *name, return object_property_add(obj, name, "struct tm", get ? property_get_tm : NULL, NULL, - property_release_tm, + property_release_data, prop); } From 9c211ad2ca09f47dc5563107a66c84141c966b7a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Fri, 23 Oct 2020 17:19:16 +0200 Subject: [PATCH 007/113] dma: Document address_space_map/address_space_unmap() prototypes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add documentation based on address_space_map / address_space_unmap. Reviewed-by: Richard Henderson Reviewed-by: Edgar E. Iglesias Signed-off-by: Philippe Mathieu-Daudé Message-Id: <20201023151923.3243652-4-philmd@redhat.com> Signed-off-by: Paolo Bonzini --- include/sysemu/dma.h | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/include/sysemu/dma.h b/include/sysemu/dma.h index 80c5bc3e02..c6e12b4c24 100644 --- a/include/sysemu/dma.h +++ b/include/sysemu/dma.h @@ -1,7 +1,7 @@ /* * DMA helper functions * - * Copyright (c) 2009 Red Hat + * Copyright (c) 2009, 2020 Red Hat * * This work is licensed under the terms of the GNU General Public License * (GNU GPL), version 2 or later. @@ -125,6 +125,19 @@ static inline int dma_memory_write(AddressSpace *as, dma_addr_t addr, int dma_memory_set(AddressSpace *as, dma_addr_t addr, uint8_t c, dma_addr_t len); +/** + * address_space_map: Map a physical memory region into a host virtual address. + * + * May map a subset of the requested range, given by and returned in @plen. + * May return %NULL and set *@plen to zero(0), if resources needed to perform + * the mapping are exhausted. + * Use only for reads OR writes - not for read-modify-write operations. + * + * @as: #AddressSpace to be accessed + * @addr: address within that address space + * @len: pointer to length of buffer; updated on return + * @dir: indicates the transfer direction + */ static inline void *dma_memory_map(AddressSpace *as, dma_addr_t addr, dma_addr_t *len, DMADirection dir) @@ -138,6 +151,20 @@ static inline void *dma_memory_map(AddressSpace *as, return p; } +/** + * address_space_unmap: Unmaps a memory region previously mapped + * by dma_memory_map() + * + * Will also mark the memory as dirty if @dir == %DMA_DIRECTION_FROM_DEVICE. + * @access_len gives the amount of memory that was actually read or written + * by the caller. + * + * @as: #AddressSpace used + * @buffer: host pointer as returned by address_space_map() + * @len: buffer length as returned by address_space_map() + * @dir: indicates the transfer direction + * @access_len: amount of data actually transferred + */ static inline void dma_memory_unmap(AddressSpace *as, void *buffer, dma_addr_t len, DMADirection dir, dma_addr_t access_len) From bb755f52863ed4b7e841b3d610589eb77592611e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Fri, 23 Oct 2020 17:19:17 +0200 Subject: [PATCH 008/113] dma: Let dma_memory_set() propagate MemTxResult MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit address_space_write() returns a MemTxResult type. Do not discard it, return it to the caller. Reviewed-by: Richard Henderson Reviewed-by: Li Qiang Reviewed-by: Edgar E. Iglesias Signed-off-by: Philippe Mathieu-Daudé Message-Id: <20201023151923.3243652-5-philmd@redhat.com> Signed-off-by: Paolo Bonzini --- include/sysemu/dma.h | 15 ++++++++++++++- softmmu/dma-helpers.c | 7 ++++--- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/include/sysemu/dma.h b/include/sysemu/dma.h index c6e12b4c24..37cd9f1121 100644 --- a/include/sysemu/dma.h +++ b/include/sysemu/dma.h @@ -123,7 +123,20 @@ static inline int dma_memory_write(AddressSpace *as, dma_addr_t addr, DMA_DIRECTION_FROM_DEVICE); } -int dma_memory_set(AddressSpace *as, dma_addr_t addr, uint8_t c, dma_addr_t len); +/** + * dma_memory_set: Fill memory with a constant byte from DMA controller. + * + * Return a MemTxResult indicating whether the operation succeeded + * or failed (eg unassigned memory, device rejected the transaction, + * IOMMU fault). + * + * @as: #AddressSpace to be accessed + * @addr: address within that address space + * @c: constant byte to fill the memory + * @len: the number of bytes to fill with the constant byte + */ +MemTxResult dma_memory_set(AddressSpace *as, dma_addr_t addr, + uint8_t c, dma_addr_t len); /** * address_space_map: Map a physical memory region into a host virtual address. diff --git a/softmmu/dma-helpers.c b/softmmu/dma-helpers.c index 03c92e0cc6..29001b5459 100644 --- a/softmmu/dma-helpers.c +++ b/softmmu/dma-helpers.c @@ -1,7 +1,7 @@ /* * DMA helper functions * - * Copyright (c) 2009 Red Hat + * Copyright (c) 2009,2020 Red Hat * * This work is licensed under the terms of the GNU General Public License * (GNU GPL), version 2 or later. @@ -18,14 +18,15 @@ /* #define DEBUG_IOMMU */ -int dma_memory_set(AddressSpace *as, dma_addr_t addr, uint8_t c, dma_addr_t len) +MemTxResult dma_memory_set(AddressSpace *as, dma_addr_t addr, + uint8_t c, dma_addr_t len) { dma_barrier(as, DMA_DIRECTION_FROM_DEVICE); #define FILLBUF_SIZE 512 uint8_t fillbuf[FILLBUF_SIZE]; int l; - bool error = false; + MemTxResult error = MEMTX_OK; memset(fillbuf, c, FILLBUF_SIZE); while (len > 0) { From 9989bcd337c4405b43295170bc93e29fa7523e75 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Fri, 23 Oct 2020 17:19:18 +0200 Subject: [PATCH 009/113] dma: Let dma_memory_rw() propagate MemTxResult MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit address_space_rw() returns a MemTxResult type. Do not discard it, return it to the caller. Reviewed-by: Richard Henderson Reviewed-by: Li Qiang Reviewed-by: Edgar E. Iglesias Signed-off-by: Philippe Mathieu-Daudé Message-Id: <20201023151923.3243652-6-philmd@redhat.com> Signed-off-by: Paolo Bonzini --- include/sysemu/dma.h | 30 ++++++++++++++++++++++-------- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/include/sysemu/dma.h b/include/sysemu/dma.h index 37cd9f1121..04687d8825 100644 --- a/include/sysemu/dma.h +++ b/include/sysemu/dma.h @@ -80,12 +80,13 @@ static inline bool dma_memory_valid(AddressSpace *as, MEMTXATTRS_UNSPECIFIED); } -static inline int dma_memory_rw_relaxed(AddressSpace *as, dma_addr_t addr, - void *buf, dma_addr_t len, - DMADirection dir) +static inline MemTxResult dma_memory_rw_relaxed(AddressSpace *as, + dma_addr_t addr, + void *buf, dma_addr_t len, + DMADirection dir) { - return (bool)address_space_rw(as, addr, MEMTXATTRS_UNSPECIFIED, - buf, len, dir == DMA_DIRECTION_FROM_DEVICE); + return address_space_rw(as, addr, MEMTXATTRS_UNSPECIFIED, + buf, len, dir == DMA_DIRECTION_FROM_DEVICE); } static inline int dma_memory_read_relaxed(AddressSpace *as, dma_addr_t addr, @@ -101,9 +102,22 @@ static inline int dma_memory_write_relaxed(AddressSpace *as, dma_addr_t addr, DMA_DIRECTION_FROM_DEVICE); } -static inline int dma_memory_rw(AddressSpace *as, dma_addr_t addr, - void *buf, dma_addr_t len, - DMADirection dir) +/** + * dma_memory_rw: Read from or write to an address space from DMA controller. + * + * Return a MemTxResult indicating whether the operation succeeded + * or failed (eg unassigned memory, device rejected the transaction, + * IOMMU fault). + * + * @as: #AddressSpace to be accessed + * @addr: address within that address space + * @buf: buffer with the data transferred + * @len: the number of bytes to read or write + * @dir: indicates the transfer direction + */ +static inline MemTxResult dma_memory_rw(AddressSpace *as, dma_addr_t addr, + void *buf, dma_addr_t len, + DMADirection dir) { dma_barrier(as, dir); From b1f51303af2840e5b9042f6fbe811331759cb557 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Fri, 23 Oct 2020 17:19:19 +0200 Subject: [PATCH 010/113] dma: Let dma_memory_read() propagate MemTxResult MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit dma_memory_rw_relaxed() returns a MemTxResult type. Do not discard it, return it to the caller. Reviewed-by: Richard Henderson Reviewed-by: Li Qiang Reviewed-by: Edgar E. Iglesias Signed-off-by: Philippe Mathieu-Daudé Message-Id: <20201023151923.3243652-7-philmd@redhat.com> Signed-off-by: Paolo Bonzini --- include/sysemu/dma.h | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/include/sysemu/dma.h b/include/sysemu/dma.h index 04687d8825..df170047eb 100644 --- a/include/sysemu/dma.h +++ b/include/sysemu/dma.h @@ -89,8 +89,9 @@ static inline MemTxResult dma_memory_rw_relaxed(AddressSpace *as, buf, len, dir == DMA_DIRECTION_FROM_DEVICE); } -static inline int dma_memory_read_relaxed(AddressSpace *as, dma_addr_t addr, - void *buf, dma_addr_t len) +static inline MemTxResult dma_memory_read_relaxed(AddressSpace *as, + dma_addr_t addr, + void *buf, dma_addr_t len) { return dma_memory_rw_relaxed(as, addr, buf, len, DMA_DIRECTION_TO_DEVICE); } @@ -124,8 +125,20 @@ static inline MemTxResult dma_memory_rw(AddressSpace *as, dma_addr_t addr, return dma_memory_rw_relaxed(as, addr, buf, len, dir); } -static inline int dma_memory_read(AddressSpace *as, dma_addr_t addr, - void *buf, dma_addr_t len) +/** + * dma_memory_read: Read from an address space from DMA controller. + * + * Return a MemTxResult indicating whether the operation succeeded + * or failed (eg unassigned memory, device rejected the transaction, + * IOMMU fault). Called within RCU critical section. + * + * @as: #AddressSpace to be accessed + * @addr: address within that address space + * @buf: buffer with the data transferred + * @len: length of the data transferred + */ +static inline MemTxResult dma_memory_read(AddressSpace *as, dma_addr_t addr, + void *buf, dma_addr_t len) { return dma_memory_rw(as, addr, buf, len, DMA_DIRECTION_TO_DEVICE); } From 77c71d1d7436a6b5418e5fa9703733188cb9e60b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Fri, 23 Oct 2020 17:19:20 +0200 Subject: [PATCH 011/113] dma: Let dma_memory_write() propagate MemTxResult MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit dma_memory_rw_relaxed() returns a MemTxResult type. Do not discard it, return it to the caller. Reviewed-by: Richard Henderson Reviewed-by: Li Qiang Reviewed-by: Edgar E. Iglesias Signed-off-by: Philippe Mathieu-Daudé Message-Id: <20201023151923.3243652-8-philmd@redhat.com> Signed-off-by: Paolo Bonzini --- include/sysemu/dma.h | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/include/sysemu/dma.h b/include/sysemu/dma.h index df170047eb..a052f7bca3 100644 --- a/include/sysemu/dma.h +++ b/include/sysemu/dma.h @@ -96,8 +96,10 @@ static inline MemTxResult dma_memory_read_relaxed(AddressSpace *as, return dma_memory_rw_relaxed(as, addr, buf, len, DMA_DIRECTION_TO_DEVICE); } -static inline int dma_memory_write_relaxed(AddressSpace *as, dma_addr_t addr, - const void *buf, dma_addr_t len) +static inline MemTxResult dma_memory_write_relaxed(AddressSpace *as, + dma_addr_t addr, + const void *buf, + dma_addr_t len) { return dma_memory_rw_relaxed(as, addr, (void *)buf, len, DMA_DIRECTION_FROM_DEVICE); @@ -143,8 +145,20 @@ static inline MemTxResult dma_memory_read(AddressSpace *as, dma_addr_t addr, return dma_memory_rw(as, addr, buf, len, DMA_DIRECTION_TO_DEVICE); } -static inline int dma_memory_write(AddressSpace *as, dma_addr_t addr, - const void *buf, dma_addr_t len) +/** + * address_space_write: Write to address space from DMA controller. + * + * Return a MemTxResult indicating whether the operation succeeded + * or failed (eg unassigned memory, device rejected the transaction, + * IOMMU fault). + * + * @as: #AddressSpace to be accessed + * @addr: address within that address space + * @buf: buffer with the data transferred + * @len: the number of bytes to write + */ +static inline MemTxResult dma_memory_write(AddressSpace *as, dma_addr_t addr, + const void *buf, dma_addr_t len) { return dma_memory_rw(as, addr, (void *)buf, len, DMA_DIRECTION_FROM_DEVICE); From b73299d04dc2d2196f86be129ddca0242831d413 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Fri, 23 Oct 2020 17:19:21 +0200 Subject: [PATCH 012/113] pci: Let pci_dma_rw() propagate MemTxResult MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit dma_memory_rw() returns a MemTxResult type. Do not discard it, return it to the caller. Reviewed-by: Li Qiang Reviewed-by: Richard Henderson Signed-off-by: Philippe Mathieu-Daudé Message-Id: <20201023151923.3243652-9-philmd@redhat.com> Signed-off-by: Paolo Bonzini --- include/hw/pci/pci.h | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/include/hw/pci/pci.h b/include/hw/pci/pci.h index 72ce649eee..37ffd73708 100644 --- a/include/hw/pci/pci.h +++ b/include/hw/pci/pci.h @@ -781,8 +781,22 @@ static inline AddressSpace *pci_get_address_space(PCIDevice *dev) return &dev->bus_master_as; } -static inline int pci_dma_rw(PCIDevice *dev, dma_addr_t addr, - void *buf, dma_addr_t len, DMADirection dir) +/** + * pci_dma_rw: Read from or write to an address space from PCI device. + * + * Return a MemTxResult indicating whether the operation succeeded + * or failed (eg unassigned memory, device rejected the transaction, + * IOMMU fault). + * + * @dev: #PCIDevice doing the memory access + * @addr: address within the #PCIDevice address space + * @buf: buffer with the data transferred + * @len: the number of bytes to read or write + * @dir: indicates the transfer direction + */ +static inline MemTxResult pci_dma_rw(PCIDevice *dev, dma_addr_t addr, + void *buf, dma_addr_t len, + DMADirection dir) { return dma_memory_rw(pci_get_address_space(dev), addr, buf, len, dir); } From c27f498237bdbdf956e815de77bf63b003355f7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Fri, 23 Oct 2020 17:19:22 +0200 Subject: [PATCH 013/113] pci: Let pci_dma_read() propagate MemTxResult MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit pci_dma_rw() returns a MemTxResult type. Do not discard it, return it to the caller. Reviewed-by: Li Qiang Reviewed-by: Richard Henderson Signed-off-by: Philippe Mathieu-Daudé Message-Id: <20201023151923.3243652-10-philmd@redhat.com> Signed-off-by: Paolo Bonzini --- include/hw/pci/pci.h | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/include/hw/pci/pci.h b/include/hw/pci/pci.h index 37ffd73708..a2de236eeb 100644 --- a/include/hw/pci/pci.h +++ b/include/hw/pci/pci.h @@ -801,8 +801,20 @@ static inline MemTxResult pci_dma_rw(PCIDevice *dev, dma_addr_t addr, return dma_memory_rw(pci_get_address_space(dev), addr, buf, len, dir); } -static inline int pci_dma_read(PCIDevice *dev, dma_addr_t addr, - void *buf, dma_addr_t len) +/** + * pci_dma_read: Read from an address space from PCI device. + * + * Return a MemTxResult indicating whether the operation succeeded + * or failed (eg unassigned memory, device rejected the transaction, + * IOMMU fault). Called within RCU critical section. + * + * @dev: #PCIDevice doing the memory access + * @addr: address within the #PCIDevice address space + * @buf: buffer with the data transferred + * @len: length of the data transferred + */ +static inline MemTxResult pci_dma_read(PCIDevice *dev, dma_addr_t addr, + void *buf, dma_addr_t len) { return pci_dma_rw(dev, addr, buf, len, DMA_DIRECTION_TO_DEVICE); } From 00b46eccffd3e74f24906e8d251861625fa3222c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Fri, 23 Oct 2020 17:19:23 +0200 Subject: [PATCH 014/113] pci: Let pci_dma_write() propagate MemTxResult MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit pci_dma_rw() returns a MemTxResult type. Do not discard it, return it to the caller. Reviewed-by: Li Qiang Reviewed-by: Richard Henderson Signed-off-by: Philippe Mathieu-Daudé Message-Id: <20201023151923.3243652-11-philmd@redhat.com> Signed-off-by: Paolo Bonzini --- include/hw/pci/pci.h | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/include/hw/pci/pci.h b/include/hw/pci/pci.h index a2de236eeb..259f9c992d 100644 --- a/include/hw/pci/pci.h +++ b/include/hw/pci/pci.h @@ -819,8 +819,20 @@ static inline MemTxResult pci_dma_read(PCIDevice *dev, dma_addr_t addr, return pci_dma_rw(dev, addr, buf, len, DMA_DIRECTION_TO_DEVICE); } -static inline int pci_dma_write(PCIDevice *dev, dma_addr_t addr, - const void *buf, dma_addr_t len) +/** + * pci_dma_write: Write to address space from PCI device. + * + * Return a MemTxResult indicating whether the operation succeeded + * or failed (eg unassigned memory, device rejected the transaction, + * IOMMU fault). + * + * @dev: #PCIDevice doing the memory access + * @addr: address within the #PCIDevice address space + * @buf: buffer with the data transferred + * @len: the number of bytes to write + */ +static inline MemTxResult pci_dma_write(PCIDevice *dev, dma_addr_t addr, + const void *buf, dma_addr_t len) { return pci_dma_rw(dev, addr, (void *) buf, len, DMA_DIRECTION_FROM_DEVICE); } From 5ade579ba9ae81adcb36b0ff185ce13cc560ed01 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Mon, 12 Oct 2020 14:49:53 +0200 Subject: [PATCH 015/113] hw/ssi/aspeed_smc: Rename 'max_slaves' variable as 'max_peripherals' MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In order to use inclusive terminology, rename max_slaves as max_peripherals. Patch generated using: $ sed -i s/slave/peripheral/ \ hw/ssi/aspeed_smc.c include/hw/ssi/aspeed_smc.h One line in aspeed_smc_read() has been manually tweaked to pass checkpatch. Reviewed-by: Thomas Huth Reviewed-by: Cédric Le Goater Signed-off-by: Philippe Mathieu-Daudé Message-Id: <20201012124955.3409127-2-f4bug@amsat.org> Signed-off-by: Paolo Bonzini --- hw/ssi/aspeed_smc.c | 53 +++++++++++++++++++------------------ include/hw/ssi/aspeed_smc.h | 2 +- 2 files changed, 28 insertions(+), 27 deletions(-) diff --git a/hw/ssi/aspeed_smc.c b/hw/ssi/aspeed_smc.c index e3d5e26058..16addee4dc 100644 --- a/hw/ssi/aspeed_smc.c +++ b/hw/ssi/aspeed_smc.c @@ -191,7 +191,7 @@ #define SNOOP_START 0x0 /* - * Default segments mapping addresses and size for each slave per + * Default segments mapping addresses and size for each peripheral per * controller. These can be changed when board is initialized with the * Segment Address Registers. */ @@ -269,7 +269,7 @@ static const AspeedSMCController controllers[] = { .r_timings = R_TIMINGS, .nregs_timings = 1, .conf_enable_w0 = CONF_ENABLE_W0, - .max_slaves = 1, + .max_peripherals = 1, .segments = aspeed_segments_legacy, .flash_window_base = ASPEED_SOC_SMC_FLASH_BASE, .flash_window_size = 0x6000000, @@ -285,7 +285,7 @@ static const AspeedSMCController controllers[] = { .r_timings = R_TIMINGS, .nregs_timings = 1, .conf_enable_w0 = CONF_ENABLE_W0, - .max_slaves = 5, + .max_peripherals = 5, .segments = aspeed_segments_fmc, .flash_window_base = ASPEED_SOC_FMC_FLASH_BASE, .flash_window_size = 0x10000000, @@ -303,7 +303,7 @@ static const AspeedSMCController controllers[] = { .r_timings = R_SPI_TIMINGS, .nregs_timings = 1, .conf_enable_w0 = SPI_CONF_ENABLE_W0, - .max_slaves = 1, + .max_peripherals = 1, .segments = aspeed_segments_spi, .flash_window_base = ASPEED_SOC_SPI_FLASH_BASE, .flash_window_size = 0x10000000, @@ -319,7 +319,7 @@ static const AspeedSMCController controllers[] = { .r_timings = R_TIMINGS, .nregs_timings = 1, .conf_enable_w0 = CONF_ENABLE_W0, - .max_slaves = 3, + .max_peripherals = 3, .segments = aspeed_segments_ast2500_fmc, .flash_window_base = ASPEED_SOC_FMC_FLASH_BASE, .flash_window_size = 0x10000000, @@ -337,7 +337,7 @@ static const AspeedSMCController controllers[] = { .r_timings = R_TIMINGS, .nregs_timings = 1, .conf_enable_w0 = CONF_ENABLE_W0, - .max_slaves = 2, + .max_peripherals = 2, .segments = aspeed_segments_ast2500_spi1, .flash_window_base = ASPEED_SOC_SPI_FLASH_BASE, .flash_window_size = 0x8000000, @@ -353,7 +353,7 @@ static const AspeedSMCController controllers[] = { .r_timings = R_TIMINGS, .nregs_timings = 1, .conf_enable_w0 = CONF_ENABLE_W0, - .max_slaves = 2, + .max_peripherals = 2, .segments = aspeed_segments_ast2500_spi2, .flash_window_base = ASPEED_SOC_SPI2_FLASH_BASE, .flash_window_size = 0x8000000, @@ -369,7 +369,7 @@ static const AspeedSMCController controllers[] = { .r_timings = R_TIMINGS, .nregs_timings = 1, .conf_enable_w0 = CONF_ENABLE_W0, - .max_slaves = 3, + .max_peripherals = 3, .segments = aspeed_segments_ast2600_fmc, .flash_window_base = ASPEED26_SOC_FMC_FLASH_BASE, .flash_window_size = 0x10000000, @@ -387,7 +387,7 @@ static const AspeedSMCController controllers[] = { .r_timings = R_TIMINGS, .nregs_timings = 2, .conf_enable_w0 = CONF_ENABLE_W0, - .max_slaves = 2, + .max_peripherals = 2, .segments = aspeed_segments_ast2600_spi1, .flash_window_base = ASPEED26_SOC_SPI_FLASH_BASE, .flash_window_size = 0x10000000, @@ -405,7 +405,7 @@ static const AspeedSMCController controllers[] = { .r_timings = R_TIMINGS, .nregs_timings = 3, .conf_enable_w0 = CONF_ENABLE_W0, - .max_slaves = 3, + .max_peripherals = 3, .segments = aspeed_segments_ast2600_spi2, .flash_window_base = ASPEED26_SOC_SPI2_FLASH_BASE, .flash_window_size = 0x10000000, @@ -420,7 +420,7 @@ static const AspeedSMCController controllers[] = { /* * The Segment Registers of the AST2400 and AST2500 have a 8MB - * unit. The address range of a flash SPI slave is encoded with + * unit. The address range of a flash SPI peripheral is encoded with * absolute addresses which should be part of the overall controller * window. */ @@ -442,7 +442,7 @@ static void aspeed_smc_reg_to_segment(const AspeedSMCState *s, /* * The Segment Registers of the AST2600 have a 1MB unit. The address - * range of a flash SPI slave is encoded with offsets in the overall + * range of a flash SPI peripheral is encoded with offsets in the overall * controller window. The previous SoC AST2400 and AST2500 used * absolute addresses. Only bits [27:20] are relevant and the end * address is an upper bound limit. @@ -486,7 +486,7 @@ static bool aspeed_smc_flash_overlap(const AspeedSMCState *s, AspeedSegments seg; int i; - for (i = 0; i < s->ctrl->max_slaves; i++) { + for (i = 0; i < s->ctrl->max_peripherals; i++) { if (i == cs) { continue; } @@ -547,7 +547,7 @@ static void aspeed_smc_flash_set_segment(AspeedSMCState *s, int cs, */ if ((s->ctrl->segments == aspeed_segments_ast2500_spi1 || s->ctrl->segments == aspeed_segments_ast2500_spi2) && - cs == s->ctrl->max_slaves && + cs == s->ctrl->max_peripherals && seg.addr + seg.size != s->ctrl->segments[cs].addr + s->ctrl->segments[cs].size) { qemu_log_mask(LOG_GUEST_ERROR, @@ -949,14 +949,14 @@ static void aspeed_smc_reset(DeviceState *d) memset(s->regs, 0, sizeof s->regs); - /* Unselect all slaves */ + /* Unselect all peripherals */ for (i = 0; i < s->num_cs; ++i) { s->regs[s->r_ctrl0 + i] |= CTRL_CE_STOP_ACTIVE; qemu_set_irq(s->cs_lines[i], true); } /* setup the default segment register values and regions for all */ - for (i = 0; i < s->ctrl->max_slaves; ++i) { + for (i = 0; i < s->ctrl->max_peripherals; ++i) { aspeed_smc_flash_set_segment_region(s, i, s->ctrl->segment_to_reg(s, &s->ctrl->segments[i])); } @@ -1004,8 +1004,9 @@ static uint64_t aspeed_smc_read(void *opaque, hwaddr addr, unsigned int size) (s->ctrl->has_dma && addr == R_DMA_DRAM_ADDR) || (s->ctrl->has_dma && addr == R_DMA_LEN) || (s->ctrl->has_dma && addr == R_DMA_CHECKSUM) || - (addr >= R_SEG_ADDR0 && addr < R_SEG_ADDR0 + s->ctrl->max_slaves) || - (addr >= s->r_ctrl0 && addr < s->r_ctrl0 + s->ctrl->max_slaves)) { + (addr >= R_SEG_ADDR0 && + addr < R_SEG_ADDR0 + s->ctrl->max_peripherals) || + (addr >= s->r_ctrl0 && addr < s->r_ctrl0 + s->ctrl->max_peripherals)) { trace_aspeed_smc_read(addr, size, s->regs[addr]); @@ -1279,7 +1280,7 @@ static void aspeed_smc_write(void *opaque, hwaddr addr, uint64_t data, int cs = addr - s->r_ctrl0; aspeed_smc_flash_update_ctrl(&s->flashes[cs], value); } else if (addr >= R_SEG_ADDR0 && - addr < R_SEG_ADDR0 + s->ctrl->max_slaves) { + addr < R_SEG_ADDR0 + s->ctrl->max_peripherals) { int cs = addr - R_SEG_ADDR0; if (value != s->regs[R_SEG_ADDR0 + cs]) { @@ -1352,10 +1353,10 @@ static void aspeed_smc_realize(DeviceState *dev, Error **errp) s->conf_enable_w0 = s->ctrl->conf_enable_w0; /* Enforce some real HW limits */ - if (s->num_cs > s->ctrl->max_slaves) { + if (s->num_cs > s->ctrl->max_peripherals) { qemu_log_mask(LOG_GUEST_ERROR, "%s: num_cs cannot exceed: %d\n", - __func__, s->ctrl->max_slaves); - s->num_cs = s->ctrl->max_slaves; + __func__, s->ctrl->max_peripherals); + s->num_cs = s->ctrl->max_peripherals; } /* DMA irq. Keep it first for the initialization in the SoC */ @@ -1363,7 +1364,7 @@ static void aspeed_smc_realize(DeviceState *dev, Error **errp) s->spi = ssi_create_bus(dev, "spi"); - /* Setup cs_lines for slaves */ + /* Setup cs_lines for peripherals */ s->cs_lines = g_new0(qemu_irq, s->num_cs); for (i = 0; i < s->num_cs; ++i) { @@ -1387,16 +1388,16 @@ static void aspeed_smc_realize(DeviceState *dev, Error **errp) s->ctrl->flash_window_size); sysbus_init_mmio(sbd, &s->mmio_flash); - s->flashes = g_new0(AspeedSMCFlash, s->ctrl->max_slaves); + s->flashes = g_new0(AspeedSMCFlash, s->ctrl->max_peripherals); /* - * Let's create a sub memory region for each possible slave. All + * Let's create a sub memory region for each possible peripheral. All * have a configurable memory segment in the overall flash mapping * window of the controller but, there is not necessarily a flash * module behind to handle the memory accesses. This depends on * the board configuration. */ - for (i = 0; i < s->ctrl->max_slaves; ++i) { + for (i = 0; i < s->ctrl->max_peripherals; ++i) { AspeedSMCFlash *fl = &s->flashes[i]; snprintf(name, sizeof(name), "%s.%d", s->ctrl->name, i); diff --git a/include/hw/ssi/aspeed_smc.h b/include/hw/ssi/aspeed_smc.h index 3dd354b52e..16c03fe64f 100644 --- a/include/hw/ssi/aspeed_smc.h +++ b/include/hw/ssi/aspeed_smc.h @@ -43,7 +43,7 @@ typedef struct AspeedSMCController { uint8_t r_timings; uint8_t nregs_timings; uint8_t conf_enable_w0; - uint8_t max_slaves; + uint8_t max_peripherals; const AspeedSegments *segments; hwaddr flash_window_base; uint32_t flash_window_size; From 9ce89a22aed41e8486dddb27fbeea9f182b90516 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Mon, 12 Oct 2020 14:49:54 +0200 Subject: [PATCH 016/113] hw/ssi: Update coding style to make checkpatch.pl happy MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit To make the next commit easier to review, clean this code first. Signed-off-by: Philippe Mathieu-Daudé Message-Id: <20201012124955.3409127-3-f4bug@amsat.org> Signed-off-by: Paolo Bonzini --- include/hw/ssi/ssi.h | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/include/hw/ssi/ssi.h b/include/hw/ssi/ssi.h index fe3028c39d..c15548425a 100644 --- a/include/hw/ssi/ssi.h +++ b/include/hw/ssi/ssi.h @@ -1,12 +1,14 @@ /* QEMU Synchronous Serial Interface support. */ -/* In principle SSI is a point-point interface. As such the qemu - implementation has a single slave device on a "bus". - However it is fairly common for boards to have multiple slaves - connected to a single master, and select devices with an external - chip select. This is implemented in qemu by having an explicit mux device. - It is assumed that master and slave are both using the same transfer width. - */ +/* + * In principle SSI is a point-point interface. As such the qemu + * implementation has a single slave device on a "bus". + * However it is fairly common for boards to have multiple slaves + * connected to a single master, and select devices with an external + * chip select. This is implemented in qemu by having an explicit mux device. + * It is assumed that master and slave are both using the same transfer + * width. + */ #ifndef QEMU_SSI_H #define QEMU_SSI_H From ec7e429bd250ecfb6528e27eec58ea9ee47cd95d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Mon, 12 Oct 2020 14:49:55 +0200 Subject: [PATCH 017/113] hw/ssi: Rename SSI 'slave' as 'peripheral' MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In order to use inclusive terminology, rename SSI 'slave' as 'peripheral', following the specification resolution: https://www.oshwa.org/a-resolution-to-redefine-spi-signal-names/ Patch created mechanically using: $ sed -i s/SSISlave/SSIPeripheral/ $(git grep -l SSISlave) $ sed -i s/SSI_SLAVE/SSI_PERIPHERAL/ $(git grep -l SSI_SLAVE) $ sed -i s/ssi-slave/ssi-peripheral/ $(git grep -l ssi-slave) $ sed -i s/ssi_slave/ssi_peripheral/ $(git grep -l ssi_slave) $ sed -i s/ssi_create_slave/ssi_create_peripheral/ \ $(git grep -l ssi_create_slave) Then in VMStateDescription vmstate_ssi_peripheral we restored the "SSISlave" migration stream name (to avoid breaking migration). Finally the following files have been manually tweaked: - hw/ssi/pl022.c - hw/ssi/xilinx_spips.c Suggested-by: Paolo Bonzini Signed-off-by: Philippe Mathieu-Daudé Message-Id: <20201012124955.3409127-4-f4bug@amsat.org> Signed-off-by: Paolo Bonzini --- hw/arm/spitz.c | 32 +++++++++++++------------- hw/arm/stellaris.c | 4 ++-- hw/arm/tosa.c | 12 +++++----- hw/arm/z2.c | 14 ++++++------ hw/block/m25p80.c | 14 ++++++------ hw/display/ads7846.c | 12 +++++----- hw/display/ssd0323.c | 12 +++++----- hw/misc/max111x.c | 18 +++++++-------- hw/sd/ssi-sd.c | 12 +++++----- hw/ssi/pl022.c | 2 +- hw/ssi/ssi.c | 48 +++++++++++++++++++-------------------- hw/ssi/xilinx_spips.c | 7 +++--- include/hw/misc/max111x.h | 2 +- include/hw/ssi/ssi.h | 46 ++++++++++++++++++------------------- 14 files changed, 118 insertions(+), 117 deletions(-) diff --git a/hw/arm/spitz.c b/hw/arm/spitz.c index 772662f149..6b3bf9828b 100644 --- a/hw/arm/spitz.c +++ b/hw/arm/spitz.c @@ -578,7 +578,7 @@ static void spitz_keyboard_realize(DeviceState *dev, Error **errp) OBJECT_DECLARE_SIMPLE_TYPE(SpitzLCDTG, SPITZ_LCDTG) struct SpitzLCDTG { - SSISlave ssidev; + SSIPeripheral ssidev; uint32_t bl_intensity; uint32_t bl_power; }; @@ -612,7 +612,7 @@ static inline void spitz_bl_power(void *opaque, int line, int level) spitz_bl_update(s); } -static uint32_t spitz_lcdtg_transfer(SSISlave *dev, uint32_t value) +static uint32_t spitz_lcdtg_transfer(SSIPeripheral *dev, uint32_t value) { SpitzLCDTG *s = SPITZ_LCDTG(dev); int addr; @@ -641,7 +641,7 @@ static uint32_t spitz_lcdtg_transfer(SSISlave *dev, uint32_t value) return 0; } -static void spitz_lcdtg_realize(SSISlave *ssi, Error **errp) +static void spitz_lcdtg_realize(SSIPeripheral *ssi, Error **errp) { SpitzLCDTG *s = SPITZ_LCDTG(ssi); DeviceState *dev = DEVICE(s); @@ -667,12 +667,12 @@ OBJECT_DECLARE_SIMPLE_TYPE(CorgiSSPState, CORGI_SSP) /* "Demux" the signal based on current chipselect */ struct CorgiSSPState { - SSISlave ssidev; + SSIPeripheral ssidev; SSIBus *bus[3]; uint32_t enable[3]; }; -static uint32_t corgi_ssp_transfer(SSISlave *dev, uint32_t value) +static uint32_t corgi_ssp_transfer(SSIPeripheral *dev, uint32_t value) { CorgiSSPState *s = CORGI_SSP(dev); int i; @@ -700,7 +700,7 @@ static void corgi_ssp_gpio_cs(void *opaque, int line, int level) #define SPITZ_BATTERY_VOLT 0xd0 /* About 4.0V */ #define SPITZ_CHARGEON_ACIN 0x80 /* About 5.0V */ -static void corgi_ssp_realize(SSISlave *d, Error **errp) +static void corgi_ssp_realize(SSIPeripheral *d, Error **errp) { DeviceState *dev = DEVICE(d); CorgiSSPState *s = CORGI_SSP(d); @@ -715,14 +715,14 @@ static void spitz_ssp_attach(SpitzMachineState *sms) { void *bus; - sms->mux = ssi_create_slave(sms->mpu->ssp[CORGI_SSP_PORT - 1], - TYPE_CORGI_SSP); + sms->mux = ssi_create_peripheral(sms->mpu->ssp[CORGI_SSP_PORT - 1], + TYPE_CORGI_SSP); bus = qdev_get_child_bus(sms->mux, "ssi0"); - sms->lcdtg = ssi_create_slave(bus, TYPE_SPITZ_LCDTG); + sms->lcdtg = ssi_create_peripheral(bus, TYPE_SPITZ_LCDTG); bus = qdev_get_child_bus(sms->mux, "ssi1"); - sms->ads7846 = ssi_create_slave(bus, "ads7846"); + sms->ads7846 = ssi_create_peripheral(bus, "ads7846"); qdev_connect_gpio_out(sms->ads7846, 0, qdev_get_gpio_in(sms->mpu->gpio, SPITZ_GPIO_TP_INT)); @@ -1204,7 +1204,7 @@ static const VMStateDescription vmstate_corgi_ssp_regs = { .version_id = 2, .minimum_version_id = 2, .fields = (VMStateField[]) { - VMSTATE_SSI_SLAVE(ssidev, CorgiSSPState), + VMSTATE_SSI_PERIPHERAL(ssidev, CorgiSSPState), VMSTATE_UINT32_ARRAY(enable, CorgiSSPState, 3), VMSTATE_END_OF_LIST(), } @@ -1213,7 +1213,7 @@ static const VMStateDescription vmstate_corgi_ssp_regs = { static void corgi_ssp_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); - SSISlaveClass *k = SSI_SLAVE_CLASS(klass); + SSIPeripheralClass *k = SSI_PERIPHERAL_CLASS(klass); k->realize = corgi_ssp_realize; k->transfer = corgi_ssp_transfer; @@ -1222,7 +1222,7 @@ static void corgi_ssp_class_init(ObjectClass *klass, void *data) static const TypeInfo corgi_ssp_info = { .name = TYPE_CORGI_SSP, - .parent = TYPE_SSI_SLAVE, + .parent = TYPE_SSI_PERIPHERAL, .instance_size = sizeof(CorgiSSPState), .class_init = corgi_ssp_class_init, }; @@ -1232,7 +1232,7 @@ static const VMStateDescription vmstate_spitz_lcdtg_regs = { .version_id = 1, .minimum_version_id = 1, .fields = (VMStateField[]) { - VMSTATE_SSI_SLAVE(ssidev, SpitzLCDTG), + VMSTATE_SSI_PERIPHERAL(ssidev, SpitzLCDTG), VMSTATE_UINT32(bl_intensity, SpitzLCDTG), VMSTATE_UINT32(bl_power, SpitzLCDTG), VMSTATE_END_OF_LIST(), @@ -1242,7 +1242,7 @@ static const VMStateDescription vmstate_spitz_lcdtg_regs = { static void spitz_lcdtg_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); - SSISlaveClass *k = SSI_SLAVE_CLASS(klass); + SSIPeripheralClass *k = SSI_PERIPHERAL_CLASS(klass); k->realize = spitz_lcdtg_realize; k->transfer = spitz_lcdtg_transfer; @@ -1251,7 +1251,7 @@ static void spitz_lcdtg_class_init(ObjectClass *klass, void *data) static const TypeInfo spitz_lcdtg_info = { .name = TYPE_SPITZ_LCDTG, - .parent = TYPE_SSI_SLAVE, + .parent = TYPE_SSI_PERIPHERAL, .instance_size = sizeof(SpitzLCDTG), .class_init = spitz_lcdtg_class_init, }; diff --git a/hw/arm/stellaris.c b/hw/arm/stellaris.c index 1237f5af02..652823195b 100644 --- a/hw/arm/stellaris.c +++ b/hw/arm/stellaris.c @@ -1397,8 +1397,8 @@ static void stellaris_init(MachineState *ms, stellaris_board_info *board) */ bus = qdev_get_child_bus(dev, "ssi"); - sddev = ssi_create_slave(bus, "ssi-sd"); - ssddev = ssi_create_slave(bus, "ssd0323"); + sddev = ssi_create_peripheral(bus, "ssi-sd"); + ssddev = ssi_create_peripheral(bus, "ssd0323"); gpio_out[GPIO_D][0] = qemu_irq_split( qdev_get_gpio_in_named(sddev, SSI_GPIO_CS, 0), qdev_get_gpio_in_named(ssddev, SSI_GPIO_CS, 0)); diff --git a/hw/arm/tosa.c b/hw/arm/tosa.c index 66b244aeff..d5a6763cf9 100644 --- a/hw/arm/tosa.c +++ b/hw/arm/tosa.c @@ -148,13 +148,13 @@ static void tosa_gpio_setup(PXA2xxState *cpu, qemu_irq_raise(qdev_get_gpio_in(cpu->gpio, TOSA_GPIO_USB_IN)); } -static uint32_t tosa_ssp_tansfer(SSISlave *dev, uint32_t value) +static uint32_t tosa_ssp_tansfer(SSIPeripheral *dev, uint32_t value) { fprintf(stderr, "TG: %u %02x\n", value >> 5, value & 0x1f); return 0; } -static void tosa_ssp_realize(SSISlave *dev, Error **errp) +static void tosa_ssp_realize(SSIPeripheral *dev, Error **errp) { /* Nothing to do. */ } @@ -225,7 +225,7 @@ static void tosa_tg_init(PXA2xxState *cpu) { I2CBus *bus = pxa2xx_i2c_bus(cpu->i2c[0]); i2c_slave_create_simple(bus, TYPE_TOSA_DAC, DAC_BASE); - ssi_create_slave(cpu->ssp[1], "tosa-ssp"); + ssi_create_peripheral(cpu->ssp[1], "tosa-ssp"); } @@ -292,7 +292,7 @@ static const TypeInfo tosa_dac_info = { static void tosa_ssp_class_init(ObjectClass *klass, void *data) { - SSISlaveClass *k = SSI_SLAVE_CLASS(klass); + SSIPeripheralClass *k = SSI_PERIPHERAL_CLASS(klass); k->realize = tosa_ssp_realize; k->transfer = tosa_ssp_tansfer; @@ -300,8 +300,8 @@ static void tosa_ssp_class_init(ObjectClass *klass, void *data) static const TypeInfo tosa_ssp_info = { .name = "tosa-ssp", - .parent = TYPE_SSI_SLAVE, - .instance_size = sizeof(SSISlave), + .parent = TYPE_SSI_PERIPHERAL, + .instance_size = sizeof(SSIPeripheral), .class_init = tosa_ssp_class_init, }; diff --git a/hw/arm/z2.c b/hw/arm/z2.c index 4fc5699dae..308c4da956 100644 --- a/hw/arm/z2.c +++ b/hw/arm/z2.c @@ -104,7 +104,7 @@ static struct arm_boot_info z2_binfo = { #define Z2_GPIO_LCD_CS 88 struct ZipitLCD { - SSISlave ssidev; + SSIPeripheral ssidev; int32_t selected; int32_t enabled; uint8_t buf[3]; @@ -115,7 +115,7 @@ struct ZipitLCD { #define TYPE_ZIPIT_LCD "zipit-lcd" OBJECT_DECLARE_SIMPLE_TYPE(ZipitLCD, ZIPIT_LCD) -static uint32_t zipit_lcd_transfer(SSISlave *dev, uint32_t value) +static uint32_t zipit_lcd_transfer(SSIPeripheral *dev, uint32_t value) { ZipitLCD *z = ZIPIT_LCD(dev); uint16_t val; @@ -155,7 +155,7 @@ static void z2_lcd_cs(void *opaque, int line, int level) z2_lcd->selected = !level; } -static void zipit_lcd_realize(SSISlave *dev, Error **errp) +static void zipit_lcd_realize(SSIPeripheral *dev, Error **errp) { ZipitLCD *z = ZIPIT_LCD(dev); z->selected = 0; @@ -168,7 +168,7 @@ static VMStateDescription vmstate_zipit_lcd_state = { .version_id = 2, .minimum_version_id = 2, .fields = (VMStateField[]) { - VMSTATE_SSI_SLAVE(ssidev, ZipitLCD), + VMSTATE_SSI_PERIPHERAL(ssidev, ZipitLCD), VMSTATE_INT32(selected, ZipitLCD), VMSTATE_INT32(enabled, ZipitLCD), VMSTATE_BUFFER(buf, ZipitLCD), @@ -181,7 +181,7 @@ static VMStateDescription vmstate_zipit_lcd_state = { static void zipit_lcd_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); - SSISlaveClass *k = SSI_SLAVE_CLASS(klass); + SSIPeripheralClass *k = SSI_PERIPHERAL_CLASS(klass); k->realize = zipit_lcd_realize; k->transfer = zipit_lcd_transfer; @@ -190,7 +190,7 @@ static void zipit_lcd_class_init(ObjectClass *klass, void *data) static const TypeInfo zipit_lcd_info = { .name = TYPE_ZIPIT_LCD, - .parent = TYPE_SSI_SLAVE, + .parent = TYPE_SSI_PERIPHERAL, .instance_size = sizeof(ZipitLCD), .class_init = zipit_lcd_class_init, }; @@ -329,7 +329,7 @@ static void z2_init(MachineState *machine) type_register_static(&zipit_lcd_info); type_register_static(&aer915_info); - z2_lcd = ssi_create_slave(mpu->ssp[1], TYPE_ZIPIT_LCD); + z2_lcd = ssi_create_peripheral(mpu->ssp[1], TYPE_ZIPIT_LCD); bus = pxa2xx_i2c_bus(mpu->i2c[0]); i2c_slave_create_simple(bus, TYPE_AER915, 0x55); wm = DEVICE(i2c_slave_create_simple(bus, TYPE_WM8750, 0x1b)); diff --git a/hw/block/m25p80.c b/hw/block/m25p80.c index 483925f57a..d09a811767 100644 --- a/hw/block/m25p80.c +++ b/hw/block/m25p80.c @@ -416,7 +416,7 @@ typedef enum { #define M25P80_INTERNAL_DATA_BUFFER_SZ 16 struct Flash { - SSISlave parent_obj; + SSIPeripheral parent_obj; BlockBackend *blk; @@ -458,7 +458,7 @@ struct Flash { }; struct M25P80Class { - SSISlaveClass parent_class; + SSIPeripheralClass parent_class; FlashPartInfo *pi; }; @@ -1170,7 +1170,7 @@ static void decode_new_cmd(Flash *s, uint32_t value) } } -static int m25p80_cs(SSISlave *ss, bool select) +static int m25p80_cs(SSIPeripheral *ss, bool select) { Flash *s = M25P80(ss); @@ -1190,7 +1190,7 @@ static int m25p80_cs(SSISlave *ss, bool select) return 0; } -static uint32_t m25p80_transfer8(SSISlave *ss, uint32_t tx) +static uint32_t m25p80_transfer8(SSIPeripheral *ss, uint32_t tx) { Flash *s = M25P80(ss); uint32_t r = 0; @@ -1265,7 +1265,7 @@ static uint32_t m25p80_transfer8(SSISlave *ss, uint32_t tx) return r; } -static void m25p80_realize(SSISlave *ss, Error **errp) +static void m25p80_realize(SSIPeripheral *ss, Error **errp) { Flash *s = M25P80(ss); M25P80Class *mc = M25P80_GET_CLASS(s); @@ -1386,7 +1386,7 @@ static const VMStateDescription vmstate_m25p80 = { static void m25p80_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); - SSISlaveClass *k = SSI_SLAVE_CLASS(klass); + SSIPeripheralClass *k = SSI_PERIPHERAL_CLASS(klass); M25P80Class *mc = M25P80_CLASS(klass); k->realize = m25p80_realize; @@ -1401,7 +1401,7 @@ static void m25p80_class_init(ObjectClass *klass, void *data) static const TypeInfo m25p80_info = { .name = TYPE_M25P80, - .parent = TYPE_SSI_SLAVE, + .parent = TYPE_SSI_PERIPHERAL, .instance_size = sizeof(Flash), .class_size = sizeof(M25P80Class), .abstract = true, diff --git a/hw/display/ads7846.c b/hw/display/ads7846.c index cb3a431cfd..1d4e04a2dc 100644 --- a/hw/display/ads7846.c +++ b/hw/display/ads7846.c @@ -19,7 +19,7 @@ #include "qom/object.h" struct ADS7846State { - SSISlave ssidev; + SSIPeripheral ssidev; qemu_irq interrupt; int input[8]; @@ -63,7 +63,7 @@ static void ads7846_int_update(ADS7846State *s) qemu_set_irq(s->interrupt, s->pressure == 0); } -static uint32_t ads7846_transfer(SSISlave *dev, uint32_t value) +static uint32_t ads7846_transfer(SSIPeripheral *dev, uint32_t value) { ADS7846State *s = ADS7846(dev); @@ -131,7 +131,7 @@ static const VMStateDescription vmstate_ads7846 = { .minimum_version_id = 1, .post_load = ads7856_post_load, .fields = (VMStateField[]) { - VMSTATE_SSI_SLAVE(ssidev, ADS7846State), + VMSTATE_SSI_PERIPHERAL(ssidev, ADS7846State), VMSTATE_INT32_ARRAY(input, ADS7846State, 8), VMSTATE_INT32(noise, ADS7846State), VMSTATE_INT32(cycle, ADS7846State), @@ -140,7 +140,7 @@ static const VMStateDescription vmstate_ads7846 = { } }; -static void ads7846_realize(SSISlave *d, Error **errp) +static void ads7846_realize(SSIPeripheral *d, Error **errp) { DeviceState *dev = DEVICE(d); ADS7846State *s = ADS7846(d); @@ -164,7 +164,7 @@ static void ads7846_realize(SSISlave *d, Error **errp) static void ads7846_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); - SSISlaveClass *k = SSI_SLAVE_CLASS(klass); + SSIPeripheralClass *k = SSI_PERIPHERAL_CLASS(klass); k->realize = ads7846_realize; k->transfer = ads7846_transfer; @@ -173,7 +173,7 @@ static void ads7846_class_init(ObjectClass *klass, void *data) static const TypeInfo ads7846_info = { .name = TYPE_ADS7846, - .parent = TYPE_SSI_SLAVE, + .parent = TYPE_SSI_PERIPHERAL, .instance_size = sizeof(ADS7846State), .class_init = ads7846_class_init, }; diff --git a/hw/display/ssd0323.c b/hw/display/ssd0323.c index cbfd21dfd5..ab229d32b7 100644 --- a/hw/display/ssd0323.c +++ b/hw/display/ssd0323.c @@ -49,7 +49,7 @@ enum ssd0323_mode }; struct ssd0323_state { - SSISlave ssidev; + SSIPeripheral ssidev; QemuConsole *con; uint32_t cmd_len; @@ -71,7 +71,7 @@ struct ssd0323_state { OBJECT_DECLARE_SIMPLE_TYPE(ssd0323_state, SSD0323) -static uint32_t ssd0323_transfer(SSISlave *dev, uint32_t data) +static uint32_t ssd0323_transfer(SSIPeripheral *dev, uint32_t data) { ssd0323_state *s = SSD0323(dev); @@ -338,7 +338,7 @@ static const VMStateDescription vmstate_ssd0323 = { VMSTATE_INT32(remap, ssd0323_state), VMSTATE_UINT32(mode, ssd0323_state), VMSTATE_BUFFER(framebuffer, ssd0323_state), - VMSTATE_SSI_SLAVE(ssidev, ssd0323_state), + VMSTATE_SSI_PERIPHERAL(ssidev, ssd0323_state), VMSTATE_END_OF_LIST() } }; @@ -348,7 +348,7 @@ static const GraphicHwOps ssd0323_ops = { .gfx_update = ssd0323_update_display, }; -static void ssd0323_realize(SSISlave *d, Error **errp) +static void ssd0323_realize(SSIPeripheral *d, Error **errp) { DeviceState *dev = DEVICE(d); ssd0323_state *s = SSD0323(d); @@ -364,7 +364,7 @@ static void ssd0323_realize(SSISlave *d, Error **errp) static void ssd0323_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); - SSISlaveClass *k = SSI_SLAVE_CLASS(klass); + SSIPeripheralClass *k = SSI_PERIPHERAL_CLASS(klass); k->realize = ssd0323_realize; k->transfer = ssd0323_transfer; @@ -375,7 +375,7 @@ static void ssd0323_class_init(ObjectClass *klass, void *data) static const TypeInfo ssd0323_info = { .name = TYPE_SSD0323, - .parent = TYPE_SSI_SLAVE, + .parent = TYPE_SSI_PERIPHERAL, .instance_size = sizeof(ssd0323_state), .class_init = ssd0323_class_init, }; diff --git a/hw/misc/max111x.c b/hw/misc/max111x.c index eae0f9b598..1b3234a519 100644 --- a/hw/misc/max111x.c +++ b/hw/misc/max111x.c @@ -85,7 +85,7 @@ static void max111x_write(MAX111xState *s, uint32_t value) qemu_irq_raise(s->interrupt); } -static uint32_t max111x_transfer(SSISlave *dev, uint32_t value) +static uint32_t max111x_transfer(SSIPeripheral *dev, uint32_t value) { MAX111xState *s = MAX_111X(dev); max111x_write(s, value); @@ -97,7 +97,7 @@ static const VMStateDescription vmstate_max111x = { .version_id = 1, .minimum_version_id = 1, .fields = (VMStateField[]) { - VMSTATE_SSI_SLAVE(parent_obj, MAX111xState), + VMSTATE_SSI_PERIPHERAL(parent_obj, MAX111xState), VMSTATE_UINT8(tb1, MAX111xState), VMSTATE_UINT8(rb2, MAX111xState), VMSTATE_UINT8(rb3, MAX111xState), @@ -117,7 +117,7 @@ static void max111x_input_set(void *opaque, int line, int value) s->input[line] = value; } -static int max111x_init(SSISlave *d, int inputs) +static int max111x_init(SSIPeripheral *d, int inputs) { DeviceState *dev = DEVICE(d); MAX111xState *s = MAX_111X(dev); @@ -130,12 +130,12 @@ static int max111x_init(SSISlave *d, int inputs) return 0; } -static void max1110_realize(SSISlave *dev, Error **errp) +static void max1110_realize(SSIPeripheral *dev, Error **errp) { max111x_init(dev, 8); } -static void max1111_realize(SSISlave *dev, Error **errp) +static void max1111_realize(SSIPeripheral *dev, Error **errp) { max111x_init(dev, 4); } @@ -179,7 +179,7 @@ static Property max1111_properties[] = { static void max111x_class_init(ObjectClass *klass, void *data) { - SSISlaveClass *k = SSI_SLAVE_CLASS(klass); + SSIPeripheralClass *k = SSI_PERIPHERAL_CLASS(klass); DeviceClass *dc = DEVICE_CLASS(klass); k->transfer = max111x_transfer; @@ -190,7 +190,7 @@ static void max111x_class_init(ObjectClass *klass, void *data) static const TypeInfo max111x_info = { .name = TYPE_MAX_111X, - .parent = TYPE_SSI_SLAVE, + .parent = TYPE_SSI_PERIPHERAL, .instance_size = sizeof(MAX111xState), .class_init = max111x_class_init, .abstract = true, @@ -198,7 +198,7 @@ static const TypeInfo max111x_info = { static void max1110_class_init(ObjectClass *klass, void *data) { - SSISlaveClass *k = SSI_SLAVE_CLASS(klass); + SSIPeripheralClass *k = SSI_PERIPHERAL_CLASS(klass); DeviceClass *dc = DEVICE_CLASS(klass); k->realize = max1110_realize; @@ -213,7 +213,7 @@ static const TypeInfo max1110_info = { static void max1111_class_init(ObjectClass *klass, void *data) { - SSISlaveClass *k = SSI_SLAVE_CLASS(klass); + SSIPeripheralClass *k = SSI_PERIPHERAL_CLASS(klass); DeviceClass *dc = DEVICE_CLASS(klass); k->realize = max1111_realize; diff --git a/hw/sd/ssi-sd.c b/hw/sd/ssi-sd.c index 14c8e04a89..9a75e0095c 100644 --- a/hw/sd/ssi-sd.c +++ b/hw/sd/ssi-sd.c @@ -42,7 +42,7 @@ typedef enum { } ssi_sd_mode; struct ssi_sd_state { - SSISlave ssidev; + SSIPeripheral ssidev; uint32_t mode; int cmd; uint8_t cmdarg[4]; @@ -73,7 +73,7 @@ OBJECT_DECLARE_SIMPLE_TYPE(ssi_sd_state, SSI_SD) #define SSI_SDR_ADDRESS_ERROR 0x2000 #define SSI_SDR_PARAMETER_ERROR 0x4000 -static uint32_t ssi_sd_transfer(SSISlave *dev, uint32_t val) +static uint32_t ssi_sd_transfer(SSIPeripheral *dev, uint32_t val) { ssi_sd_state *s = SSI_SD(dev); @@ -235,12 +235,12 @@ static const VMStateDescription vmstate_ssi_sd = { VMSTATE_INT32(arglen, ssi_sd_state), VMSTATE_INT32(response_pos, ssi_sd_state), VMSTATE_INT32(stopping, ssi_sd_state), - VMSTATE_SSI_SLAVE(ssidev, ssi_sd_state), + VMSTATE_SSI_PERIPHERAL(ssidev, ssi_sd_state), VMSTATE_END_OF_LIST() } }; -static void ssi_sd_realize(SSISlave *d, Error **errp) +static void ssi_sd_realize(SSIPeripheral *d, Error **errp) { ERRP_GUARD(); ssi_sd_state *s = SSI_SD(d); @@ -291,7 +291,7 @@ static void ssi_sd_reset(DeviceState *dev) static void ssi_sd_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); - SSISlaveClass *k = SSI_SLAVE_CLASS(klass); + SSIPeripheralClass *k = SSI_PERIPHERAL_CLASS(klass); k->realize = ssi_sd_realize; k->transfer = ssi_sd_transfer; @@ -304,7 +304,7 @@ static void ssi_sd_class_init(ObjectClass *klass, void *data) static const TypeInfo ssi_sd_info = { .name = TYPE_SSI_SD, - .parent = TYPE_SSI_SLAVE, + .parent = TYPE_SSI_PERIPHERAL, .instance_size = sizeof(ssi_sd_state), .class_init = ssi_sd_class_init, }; diff --git a/hw/ssi/pl022.c b/hw/ssi/pl022.c index cade2e92a8..8954ffebb1 100644 --- a/hw/ssi/pl022.c +++ b/hw/ssi/pl022.c @@ -174,7 +174,7 @@ static void pl022_write(void *opaque, hwaddr offset, s->cr1 = value; if ((s->cr1 & (PL022_CR1_MS | PL022_CR1_SSE)) == (PL022_CR1_MS | PL022_CR1_SSE)) { - BADF("SPI slave mode not implemented\n"); + BADF("SPI peripheral mode not implemented\n"); } pl022_xfer(s); break; diff --git a/hw/ssi/ssi.c b/hw/ssi/ssi.c index 4278d0e444..e5d7ce9523 100644 --- a/hw/ssi/ssi.c +++ b/hw/ssi/ssi.c @@ -34,11 +34,11 @@ static const TypeInfo ssi_bus_info = { static void ssi_cs_default(void *opaque, int n, int level) { - SSISlave *s = SSI_SLAVE(opaque); + SSIPeripheral *s = SSI_PERIPHERAL(opaque); bool cs = !!level; assert(n == 0); if (s->cs != cs) { - SSISlaveClass *ssc = SSI_SLAVE_GET_CLASS(s); + SSIPeripheralClass *ssc = SSI_PERIPHERAL_GET_CLASS(s); if (ssc->set_cs) { ssc->set_cs(s, cs); } @@ -46,9 +46,9 @@ static void ssi_cs_default(void *opaque, int n, int level) s->cs = cs; } -static uint32_t ssi_transfer_raw_default(SSISlave *dev, uint32_t val) +static uint32_t ssi_transfer_raw_default(SSIPeripheral *dev, uint32_t val) { - SSISlaveClass *ssc = SSI_SLAVE_GET_CLASS(dev); + SSIPeripheralClass *ssc = SSI_PERIPHERAL_GET_CLASS(dev); if ((dev->cs && ssc->cs_polarity == SSI_CS_HIGH) || (!dev->cs && ssc->cs_polarity == SSI_CS_LOW) || @@ -58,10 +58,10 @@ static uint32_t ssi_transfer_raw_default(SSISlave *dev, uint32_t val) return 0; } -static void ssi_slave_realize(DeviceState *dev, Error **errp) +static void ssi_peripheral_realize(DeviceState *dev, Error **errp) { - SSISlave *s = SSI_SLAVE(dev); - SSISlaveClass *ssc = SSI_SLAVE_GET_CLASS(s); + SSIPeripheral *s = SSI_PERIPHERAL(dev); + SSIPeripheralClass *ssc = SSI_PERIPHERAL_GET_CLASS(s); if (ssc->transfer_raw == ssi_transfer_raw_default && ssc->cs_polarity != SSI_CS_NONE) { @@ -71,23 +71,23 @@ static void ssi_slave_realize(DeviceState *dev, Error **errp) ssc->realize(s, errp); } -static void ssi_slave_class_init(ObjectClass *klass, void *data) +static void ssi_peripheral_class_init(ObjectClass *klass, void *data) { - SSISlaveClass *ssc = SSI_SLAVE_CLASS(klass); + SSIPeripheralClass *ssc = SSI_PERIPHERAL_CLASS(klass); DeviceClass *dc = DEVICE_CLASS(klass); - dc->realize = ssi_slave_realize; + dc->realize = ssi_peripheral_realize; dc->bus_type = TYPE_SSI_BUS; if (!ssc->transfer_raw) { ssc->transfer_raw = ssi_transfer_raw_default; } } -static const TypeInfo ssi_slave_info = { - .name = TYPE_SSI_SLAVE, +static const TypeInfo ssi_peripheral_info = { + .name = TYPE_SSI_PERIPHERAL, .parent = TYPE_DEVICE, - .class_init = ssi_slave_class_init, - .class_size = sizeof(SSISlaveClass), + .class_init = ssi_peripheral_class_init, + .class_size = sizeof(SSIPeripheralClass), .abstract = true, }; @@ -96,7 +96,7 @@ bool ssi_realize_and_unref(DeviceState *dev, SSIBus *bus, Error **errp) return qdev_realize_and_unref(dev, &bus->parent_obj, errp); } -DeviceState *ssi_create_slave(SSIBus *bus, const char *name) +DeviceState *ssi_create_peripheral(SSIBus *bus, const char *name) { DeviceState *dev = qdev_new(name); @@ -115,32 +115,32 @@ uint32_t ssi_transfer(SSIBus *bus, uint32_t val) { BusState *b = BUS(bus); BusChild *kid; - SSISlaveClass *ssc; + SSIPeripheralClass *ssc; uint32_t r = 0; QTAILQ_FOREACH(kid, &b->children, sibling) { - SSISlave *slave = SSI_SLAVE(kid->child); - ssc = SSI_SLAVE_GET_CLASS(slave); - r |= ssc->transfer_raw(slave, val); + SSIPeripheral *peripheral = SSI_PERIPHERAL(kid->child); + ssc = SSI_PERIPHERAL_GET_CLASS(peripheral); + r |= ssc->transfer_raw(peripheral, val); } return r; } -const VMStateDescription vmstate_ssi_slave = { +const VMStateDescription vmstate_ssi_peripheral = { .name = "SSISlave", .version_id = 1, .minimum_version_id = 1, .fields = (VMStateField[]) { - VMSTATE_BOOL(cs, SSISlave), + VMSTATE_BOOL(cs, SSIPeripheral), VMSTATE_END_OF_LIST() } }; -static void ssi_slave_register_types(void) +static void ssi_peripheral_register_types(void) { type_register_static(&ssi_bus_info); - type_register_static(&ssi_slave_info); + type_register_static(&ssi_peripheral_info); } -type_init(ssi_slave_register_types) +type_init(ssi_peripheral_register_types) diff --git a/hw/ssi/xilinx_spips.c b/hw/ssi/xilinx_spips.c index b9371dbf8d..dd8df9daf4 100644 --- a/hw/ssi/xilinx_spips.c +++ b/hw/ssi/xilinx_spips.c @@ -236,7 +236,8 @@ static void xilinx_spips_update_cs(XilinxSPIPS *s, int field) if (old_state != new_state) { s->cs_lines_state[i] = new_state; s->rx_discard = ARRAY_FIELD_EX32(s->regs, CMND, RX_DISCARD); - DB_PRINT_L(1, "%sselecting slave %d\n", new_state ? "" : "de", i); + DB_PRINT_L(1, "%sselecting peripheral %d\n", + new_state ? "" : "de", i); } qemu_set_irq(s->cs_lines[i], !new_state); } @@ -1154,7 +1155,7 @@ static void lqspi_load_cache(void *opaque, hwaddr addr) int i; int flash_addr = ((addr & ~(LQSPI_CACHE_SIZE - 1)) / num_effective_busses(s)); - int slave = flash_addr >> LQSPI_ADDRESS_BITS; + int peripheral = flash_addr >> LQSPI_ADDRESS_BITS; int cache_entry = 0; uint32_t u_page_save = s->regs[R_LQSPI_STS] & ~LQSPI_CFG_U_PAGE; @@ -1162,7 +1163,7 @@ static void lqspi_load_cache(void *opaque, hwaddr addr) addr > q->lqspi_cached_addr + LQSPI_CACHE_SIZE - 4) { xilinx_qspips_invalidate_mmio_ptr(q); s->regs[R_LQSPI_STS] &= ~LQSPI_CFG_U_PAGE; - s->regs[R_LQSPI_STS] |= slave ? LQSPI_CFG_U_PAGE : 0; + s->regs[R_LQSPI_STS] |= peripheral ? LQSPI_CFG_U_PAGE : 0; DB_PRINT_L(0, "config reg status: %08x\n", s->regs[R_LQSPI_CFG]); diff --git a/include/hw/misc/max111x.h b/include/hw/misc/max111x.h index 606cf1e0a2..beff59c815 100644 --- a/include/hw/misc/max111x.h +++ b/include/hw/misc/max111x.h @@ -33,7 +33,7 @@ * be lowered once it has been asserted. */ struct MAX111xState { - SSISlave parent_obj; + SSIPeripheral parent_obj; qemu_irq interrupt; /* Values of inputs at system reset (settable by QOM property) */ diff --git a/include/hw/ssi/ssi.h b/include/hw/ssi/ssi.h index c15548425a..f411858ab0 100644 --- a/include/hw/ssi/ssi.h +++ b/include/hw/ssi/ssi.h @@ -2,11 +2,11 @@ /* * In principle SSI is a point-point interface. As such the qemu - * implementation has a single slave device on a "bus". - * However it is fairly common for boards to have multiple slaves + * implementation has a single peripheral on a "bus". + * However it is fairly common for boards to have multiple peripherals * connected to a single master, and select devices with an external * chip select. This is implemented in qemu by having an explicit mux device. - * It is assumed that master and slave are both using the same transfer + * It is assumed that master and peripheral are both using the same transfer * width. */ @@ -18,9 +18,9 @@ typedef enum SSICSMode SSICSMode; -#define TYPE_SSI_SLAVE "ssi-slave" -OBJECT_DECLARE_TYPE(SSISlave, SSISlaveClass, - SSI_SLAVE) +#define TYPE_SSI_PERIPHERAL "ssi-peripheral" +OBJECT_DECLARE_TYPE(SSIPeripheral, SSIPeripheralClass, + SSI_PERIPHERAL) #define SSI_GPIO_CS "ssi-gpio-cs" @@ -30,21 +30,21 @@ enum SSICSMode { SSI_CS_HIGH, }; -/* Slave devices. */ -struct SSISlaveClass { +/* Peripherals. */ +struct SSIPeripheralClass { DeviceClass parent_class; - void (*realize)(SSISlave *dev, Error **errp); + void (*realize)(SSIPeripheral *dev, Error **errp); /* if you have standard or no CS behaviour, just override transfer. * This is called when the device cs is active (true by default). */ - uint32_t (*transfer)(SSISlave *dev, uint32_t val); + uint32_t (*transfer)(SSIPeripheral *dev, uint32_t val); /* called when the CS line changes. Optional, devices only need to implement * this if they have side effects associated with the cs line (beyond * tristating the txrx lines). */ - int (*set_cs)(SSISlave *dev, bool select); + int (*set_cs)(SSIPeripheral *dev, bool select); /* define whether or not CS exists and is active low/high */ SSICSMode cs_polarity; @@ -53,30 +53,30 @@ struct SSISlaveClass { * cs_polarity are unused if this is overwritten. Transfer_raw will * always be called for the device for every txrx access to the parent bus */ - uint32_t (*transfer_raw)(SSISlave *dev, uint32_t val); + uint32_t (*transfer_raw)(SSIPeripheral *dev, uint32_t val); }; -struct SSISlave { +struct SSIPeripheral { DeviceState parent_obj; /* Chip select state */ bool cs; }; -extern const VMStateDescription vmstate_ssi_slave; +extern const VMStateDescription vmstate_ssi_peripheral; -#define VMSTATE_SSI_SLAVE(_field, _state) { \ +#define VMSTATE_SSI_PERIPHERAL(_field, _state) { \ .name = (stringify(_field)), \ - .size = sizeof(SSISlave), \ - .vmsd = &vmstate_ssi_slave, \ + .size = sizeof(SSIPeripheral), \ + .vmsd = &vmstate_ssi_peripheral, \ .flags = VMS_STRUCT, \ - .offset = vmstate_offset_value(_state, _field, SSISlave), \ + .offset = vmstate_offset_value(_state, _field, SSIPeripheral), \ } -DeviceState *ssi_create_slave(SSIBus *bus, const char *name); +DeviceState *ssi_create_peripheral(SSIBus *bus, const char *name); /** - * ssi_realize_and_unref: realize and unref an SSI slave device - * @dev: SSI slave device to realize + * ssi_realize_and_unref: realize and unref an SSI peripheral + * @dev: SSI peripheral to realize * @bus: SSI bus to put it on * @errp: error pointer * @@ -87,10 +87,10 @@ DeviceState *ssi_create_slave(SSIBus *bus, const char *name); * This function is useful if you have created @dev via qdev_new() * (which takes a reference to the device it returns to you), so that * you can set properties on it before realizing it. If you don't need - * to set properties then ssi_create_slave() is probably better (as it + * to set properties then ssi_create_peripheral() is probably better (as it * does the create, init and realize in one step). * - * If you are embedding the SSI slave into another QOM device and + * If you are embedding the SSI peripheral into another QOM device and * initialized it via some variant on object_initialize_child() then * do not use this function, because that family of functions arrange * for the only reference to the child device to be held by the parent From cfbef3f4eb3816099bf573bdb238e4aad8803c4c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Thu, 10 Sep 2020 09:01:27 +0200 Subject: [PATCH 018/113] hw/core/stream: Rename StreamSlave as StreamSink MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In order to use inclusive terminology, rename 'slave stream' as 'sink stream'. Signed-off-by: Philippe Mathieu-Daudé Acked-by: Paolo Bonzini Reviewed-by: Edgar E. Iglesias Message-Id: <20200910070131.435543-3-philmd@redhat.com> Signed-off-by: Paolo Bonzini --- hw/core/stream.c | 20 ++++++++--------- hw/dma/xilinx_axidma.c | 32 +++++++++++++-------------- hw/net/xilinx_axienet.c | 20 ++++++++--------- hw/ssi/xilinx_spips.c | 2 +- include/hw/ssi/xilinx_spips.h | 2 +- include/hw/stream.h | 41 +++++++++++++++++------------------ 6 files changed, 58 insertions(+), 59 deletions(-) diff --git a/hw/core/stream.c b/hw/core/stream.c index a65ad1208d..19477d0f2d 100644 --- a/hw/core/stream.c +++ b/hw/core/stream.c @@ -3,32 +3,32 @@ #include "qemu/module.h" size_t -stream_push(StreamSlave *sink, uint8_t *buf, size_t len, bool eop) +stream_push(StreamSink *sink, uint8_t *buf, size_t len, bool eop) { - StreamSlaveClass *k = STREAM_SLAVE_GET_CLASS(sink); + StreamSinkClass *k = STREAM_SINK_GET_CLASS(sink); return k->push(sink, buf, len, eop); } bool -stream_can_push(StreamSlave *sink, StreamCanPushNotifyFn notify, +stream_can_push(StreamSink *sink, StreamCanPushNotifyFn notify, void *notify_opaque) { - StreamSlaveClass *k = STREAM_SLAVE_GET_CLASS(sink); + StreamSinkClass *k = STREAM_SINK_GET_CLASS(sink); return k->can_push ? k->can_push(sink, notify, notify_opaque) : true; } -static const TypeInfo stream_slave_info = { - .name = TYPE_STREAM_SLAVE, +static const TypeInfo stream_sink_info = { + .name = TYPE_STREAM_SINK, .parent = TYPE_INTERFACE, - .class_size = sizeof(StreamSlaveClass), + .class_size = sizeof(StreamSinkClass), }; -static void stream_slave_register_types(void) +static void stream_sink_register_types(void) { - type_register_static(&stream_slave_info); + type_register_static(&stream_sink_info); } -type_init(stream_slave_register_types) +type_init(stream_sink_register_types) diff --git a/hw/dma/xilinx_axidma.c b/hw/dma/xilinx_axidma.c index 0a7f5acb4b..306da46699 100644 --- a/hw/dma/xilinx_axidma.c +++ b/hw/dma/xilinx_axidma.c @@ -128,8 +128,8 @@ struct XilinxAXIDMA { AddressSpace as; uint32_t freqhz; - StreamSlave *tx_data_dev; - StreamSlave *tx_control_dev; + StreamSink *tx_data_dev; + StreamSink *tx_control_dev; XilinxAXIDMAStreamSlave rx_data_dev; XilinxAXIDMAStreamSlave rx_control_dev; @@ -261,8 +261,8 @@ static void stream_complete(struct Stream *s) ptimer_transaction_commit(s->ptimer); } -static void stream_process_mem2s(struct Stream *s, StreamSlave *tx_data_dev, - StreamSlave *tx_control_dev) +static void stream_process_mem2s(struct Stream *s, StreamSink *tx_data_dev, + StreamSink *tx_control_dev) { uint32_t prev_d; uint32_t txlen; @@ -384,7 +384,7 @@ static void xilinx_axidma_reset(DeviceState *dev) } static size_t -xilinx_axidma_control_stream_push(StreamSlave *obj, unsigned char *buf, +xilinx_axidma_control_stream_push(StreamSink *obj, unsigned char *buf, size_t len, bool eop) { XilinxAXIDMAStreamSlave *cs = XILINX_AXI_DMA_CONTROL_STREAM(obj); @@ -400,7 +400,7 @@ xilinx_axidma_control_stream_push(StreamSlave *obj, unsigned char *buf, } static bool -xilinx_axidma_data_stream_can_push(StreamSlave *obj, +xilinx_axidma_data_stream_can_push(StreamSink *obj, StreamCanPushNotifyFn notify, void *notify_opaque) { @@ -417,7 +417,7 @@ xilinx_axidma_data_stream_can_push(StreamSlave *obj, } static size_t -xilinx_axidma_data_stream_push(StreamSlave *obj, unsigned char *buf, size_t len, +xilinx_axidma_data_stream_push(StreamSink *obj, unsigned char *buf, size_t len, bool eop) { XilinxAXIDMAStreamSlave *ds = XILINX_AXI_DMA_DATA_STREAM(obj); @@ -588,9 +588,9 @@ static void xilinx_axidma_init(Object *obj) static Property axidma_properties[] = { DEFINE_PROP_UINT32("freqhz", XilinxAXIDMA, freqhz, 50000000), DEFINE_PROP_LINK("axistream-connected", XilinxAXIDMA, - tx_data_dev, TYPE_STREAM_SLAVE, StreamSlave *), + tx_data_dev, TYPE_STREAM_SINK, StreamSink *), DEFINE_PROP_LINK("axistream-control-connected", XilinxAXIDMA, - tx_control_dev, TYPE_STREAM_SLAVE, StreamSlave *), + tx_control_dev, TYPE_STREAM_SINK, StreamSink *), DEFINE_PROP_END_OF_LIST(), }; @@ -603,21 +603,21 @@ static void axidma_class_init(ObjectClass *klass, void *data) device_class_set_props(dc, axidma_properties); } -static StreamSlaveClass xilinx_axidma_data_stream_class = { +static StreamSinkClass xilinx_axidma_data_stream_class = { .push = xilinx_axidma_data_stream_push, .can_push = xilinx_axidma_data_stream_can_push, }; -static StreamSlaveClass xilinx_axidma_control_stream_class = { +static StreamSinkClass xilinx_axidma_control_stream_class = { .push = xilinx_axidma_control_stream_push, }; static void xilinx_axidma_stream_class_init(ObjectClass *klass, void *data) { - StreamSlaveClass *ssc = STREAM_SLAVE_CLASS(klass); + StreamSinkClass *ssc = STREAM_SINK_CLASS(klass); - ssc->push = ((StreamSlaveClass *)data)->push; - ssc->can_push = ((StreamSlaveClass *)data)->can_push; + ssc->push = ((StreamSinkClass *)data)->push; + ssc->can_push = ((StreamSinkClass *)data)->can_push; } static const TypeInfo axidma_info = { @@ -635,7 +635,7 @@ static const TypeInfo xilinx_axidma_data_stream_info = { .class_init = xilinx_axidma_stream_class_init, .class_data = &xilinx_axidma_data_stream_class, .interfaces = (InterfaceInfo[]) { - { TYPE_STREAM_SLAVE }, + { TYPE_STREAM_SINK }, { } } }; @@ -647,7 +647,7 @@ static const TypeInfo xilinx_axidma_control_stream_info = { .class_init = xilinx_axidma_stream_class_init, .class_data = &xilinx_axidma_control_stream_class, .interfaces = (InterfaceInfo[]) { - { TYPE_STREAM_SLAVE }, + { TYPE_STREAM_SINK }, { } } }; diff --git a/hw/net/xilinx_axienet.c b/hw/net/xilinx_axienet.c index f8cf5290e1..9bccbe9be3 100644 --- a/hw/net/xilinx_axienet.c +++ b/hw/net/xilinx_axienet.c @@ -320,8 +320,8 @@ struct XilinxAXIEnet { SysBusDevice busdev; MemoryRegion iomem; qemu_irq irq; - StreamSlave *tx_data_dev; - StreamSlave *tx_control_dev; + StreamSink *tx_data_dev; + StreamSink *tx_control_dev; XilinxAXIEnetStreamSlave rx_data_dev; XilinxAXIEnetStreamSlave rx_control_dev; NICState *nic; @@ -852,7 +852,7 @@ static ssize_t eth_rx(NetClientState *nc, const uint8_t *buf, size_t size) } static size_t -xilinx_axienet_control_stream_push(StreamSlave *obj, uint8_t *buf, size_t len, +xilinx_axienet_control_stream_push(StreamSink *obj, uint8_t *buf, size_t len, bool eop) { int i; @@ -874,7 +874,7 @@ xilinx_axienet_control_stream_push(StreamSlave *obj, uint8_t *buf, size_t len, } static size_t -xilinx_axienet_data_stream_push(StreamSlave *obj, uint8_t *buf, size_t size, +xilinx_axienet_data_stream_push(StreamSink *obj, uint8_t *buf, size_t size, bool eop) { XilinxAXIEnetStreamSlave *ds = XILINX_AXI_ENET_DATA_STREAM(obj); @@ -1002,9 +1002,9 @@ static Property xilinx_enet_properties[] = { DEFINE_PROP_UINT32("txmem", XilinxAXIEnet, c_txmem, 0x1000), DEFINE_NIC_PROPERTIES(XilinxAXIEnet, conf), DEFINE_PROP_LINK("axistream-connected", XilinxAXIEnet, - tx_data_dev, TYPE_STREAM_SLAVE, StreamSlave *), + tx_data_dev, TYPE_STREAM_SINK, StreamSink *), DEFINE_PROP_LINK("axistream-control-connected", XilinxAXIEnet, - tx_control_dev, TYPE_STREAM_SLAVE, StreamSlave *), + tx_control_dev, TYPE_STREAM_SINK, StreamSink *), DEFINE_PROP_END_OF_LIST(), }; @@ -1020,14 +1020,14 @@ static void xilinx_enet_class_init(ObjectClass *klass, void *data) static void xilinx_enet_control_stream_class_init(ObjectClass *klass, void *data) { - StreamSlaveClass *ssc = STREAM_SLAVE_CLASS(klass); + StreamSinkClass *ssc = STREAM_SINK_CLASS(klass); ssc->push = xilinx_axienet_control_stream_push; } static void xilinx_enet_data_stream_class_init(ObjectClass *klass, void *data) { - StreamSlaveClass *ssc = STREAM_SLAVE_CLASS(klass); + StreamSinkClass *ssc = STREAM_SINK_CLASS(klass); ssc->push = xilinx_axienet_data_stream_push; } @@ -1046,7 +1046,7 @@ static const TypeInfo xilinx_enet_data_stream_info = { .instance_size = sizeof(XilinxAXIEnetStreamSlave), .class_init = xilinx_enet_data_stream_class_init, .interfaces = (InterfaceInfo[]) { - { TYPE_STREAM_SLAVE }, + { TYPE_STREAM_SINK }, { } } }; @@ -1057,7 +1057,7 @@ static const TypeInfo xilinx_enet_control_stream_info = { .instance_size = sizeof(XilinxAXIEnetStreamSlave), .class_init = xilinx_enet_control_stream_class_init, .interfaces = (InterfaceInfo[]) { - { TYPE_STREAM_SLAVE }, + { TYPE_STREAM_SINK }, { } } }; diff --git a/hw/ssi/xilinx_spips.c b/hw/ssi/xilinx_spips.c index dd8df9daf4..a897034601 100644 --- a/hw/ssi/xilinx_spips.c +++ b/hw/ssi/xilinx_spips.c @@ -1354,7 +1354,7 @@ static void xlnx_zynqmp_qspips_init(Object *obj) { XlnxZynqMPQSPIPS *rq = XLNX_ZYNQMP_QSPIPS(obj); - object_property_add_link(obj, "stream-connected-dma", TYPE_STREAM_SLAVE, + object_property_add_link(obj, "stream-connected-dma", TYPE_STREAM_SINK, (Object **)&rq->dma, object_property_allow_set_link, OBJ_PROP_LINK_STRONG); diff --git a/include/hw/ssi/xilinx_spips.h b/include/hw/ssi/xilinx_spips.h index b96de21b34..3eae73480e 100644 --- a/include/hw/ssi/xilinx_spips.h +++ b/include/hw/ssi/xilinx_spips.h @@ -99,7 +99,7 @@ typedef struct XilinxQSPIPS XilinxQSPIPS; struct XlnxZynqMPQSPIPS { XilinxQSPIPS parent_obj; - StreamSlave *dma; + StreamSink *dma; int gqspi_irqline; uint32_t regs[XLNX_ZYNQMP_SPIPS_R_MAX]; diff --git a/include/hw/stream.h b/include/hw/stream.h index e39d5a5b55..f166facb09 100644 --- a/include/hw/stream.h +++ b/include/hw/stream.h @@ -3,51 +3,50 @@ #include "qom/object.h" -/* stream slave. Used until qdev provides a generic way. */ -#define TYPE_STREAM_SLAVE "stream-slave" +#define TYPE_STREAM_SINK "stream-sink" -typedef struct StreamSlaveClass StreamSlaveClass; -DECLARE_CLASS_CHECKERS(StreamSlaveClass, STREAM_SLAVE, - TYPE_STREAM_SLAVE) -#define STREAM_SLAVE(obj) \ - INTERFACE_CHECK(StreamSlave, (obj), TYPE_STREAM_SLAVE) +typedef struct StreamSinkClass StreamSinkClass; +DECLARE_CLASS_CHECKERS(StreamSinkClass, STREAM_SINK, + TYPE_STREAM_SINK) +#define STREAM_SINK(obj) \ + INTERFACE_CHECK(StreamSink, (obj), TYPE_STREAM_SINK) -typedef struct StreamSlave StreamSlave; +typedef struct StreamSink StreamSink; typedef void (*StreamCanPushNotifyFn)(void *opaque); -struct StreamSlaveClass { +struct StreamSinkClass { InterfaceClass parent; /** - * can push - determine if a stream slave is capable of accepting at least + * can push - determine if a stream sink is capable of accepting at least * one byte of data. Returns false if cannot accept. If not implemented, the - * slave is assumed to always be capable of receiving. - * @notify: Optional callback that the slave will call when the slave is + * sink is assumed to always be capable of receiving. + * @notify: Optional callback that the sink will call when the sink is * capable of receiving again. Only called if false is returned. * @notify_opaque: opaque data to pass to notify call. */ - bool (*can_push)(StreamSlave *obj, StreamCanPushNotifyFn notify, + bool (*can_push)(StreamSink *obj, StreamCanPushNotifyFn notify, void *notify_opaque); /** - * push - push data to a Stream slave. The number of bytes pushed is - * returned. If the slave short returns, the master must wait before trying - * again, the slave may continue to just return 0 waiting for the vm time to + * push - push data to a Stream sink. The number of bytes pushed is + * returned. If the sink short returns, the master must wait before trying + * again, the sink may continue to just return 0 waiting for the vm time to * advance. The can_push() function can be used to trap the point in time - * where the slave is ready to receive again, otherwise polling on a QEMU + * where the sink is ready to receive again, otherwise polling on a QEMU * timer will work. - * @obj: Stream slave to push to + * @obj: Stream sink to push to * @buf: Data to write * @len: Maximum number of bytes to write * @eop: End of packet flag */ - size_t (*push)(StreamSlave *obj, unsigned char *buf, size_t len, bool eop); + size_t (*push)(StreamSink *obj, unsigned char *buf, size_t len, bool eop); }; size_t -stream_push(StreamSlave *sink, uint8_t *buf, size_t len, bool eop); +stream_push(StreamSink *sink, uint8_t *buf, size_t len, bool eop); bool -stream_can_push(StreamSlave *sink, StreamCanPushNotifyFn notify, +stream_can_push(StreamSink *sink, StreamCanPushNotifyFn notify, void *notify_opaque); From 484f86de7e00ec2096d2d12388caf8009aaae3eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Thu, 10 Sep 2020 09:01:28 +0200 Subject: [PATCH 019/113] hw/dma/xilinx_axidma: Rename StreamSlave as StreamSink MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In order to use inclusive terminology, rename 'slave stream' as 'sink stream'. Signed-off-by: Philippe Mathieu-Daudé Acked-by: Paolo Bonzini Reviewed-by: Edgar E. Iglesias Message-Id: <20200910070131.435543-4-philmd@redhat.com> Signed-off-by: Paolo Bonzini --- hw/dma/xilinx_axidma.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/hw/dma/xilinx_axidma.c b/hw/dma/xilinx_axidma.c index 306da46699..bc383f53cc 100644 --- a/hw/dma/xilinx_axidma.c +++ b/hw/dma/xilinx_axidma.c @@ -45,11 +45,11 @@ OBJECT_DECLARE_SIMPLE_TYPE(XilinxAXIDMA, XILINX_AXI_DMA) -typedef struct XilinxAXIDMAStreamSlave XilinxAXIDMAStreamSlave; -DECLARE_INSTANCE_CHECKER(XilinxAXIDMAStreamSlave, XILINX_AXI_DMA_DATA_STREAM, +typedef struct XilinxAXIDMAStreamSink XilinxAXIDMAStreamSink; +DECLARE_INSTANCE_CHECKER(XilinxAXIDMAStreamSink, XILINX_AXI_DMA_DATA_STREAM, TYPE_XILINX_AXI_DMA_DATA_STREAM) -DECLARE_INSTANCE_CHECKER(XilinxAXIDMAStreamSlave, XILINX_AXI_DMA_CONTROL_STREAM, +DECLARE_INSTANCE_CHECKER(XilinxAXIDMAStreamSink, XILINX_AXI_DMA_CONTROL_STREAM, TYPE_XILINX_AXI_DMA_CONTROL_STREAM) #define R_DMACR (0x00 / 4) @@ -115,7 +115,7 @@ struct Stream { unsigned char txbuf[16 * 1024]; }; -struct XilinxAXIDMAStreamSlave { +struct XilinxAXIDMAStreamSink { Object parent; struct XilinxAXIDMA *dma; @@ -130,8 +130,8 @@ struct XilinxAXIDMA { uint32_t freqhz; StreamSink *tx_data_dev; StreamSink *tx_control_dev; - XilinxAXIDMAStreamSlave rx_data_dev; - XilinxAXIDMAStreamSlave rx_control_dev; + XilinxAXIDMAStreamSink rx_data_dev; + XilinxAXIDMAStreamSink rx_control_dev; struct Stream streams[2]; @@ -387,7 +387,7 @@ static size_t xilinx_axidma_control_stream_push(StreamSink *obj, unsigned char *buf, size_t len, bool eop) { - XilinxAXIDMAStreamSlave *cs = XILINX_AXI_DMA_CONTROL_STREAM(obj); + XilinxAXIDMAStreamSink *cs = XILINX_AXI_DMA_CONTROL_STREAM(obj); struct Stream *s = &cs->dma->streams[1]; if (len != CONTROL_PAYLOAD_SIZE) { @@ -404,7 +404,7 @@ xilinx_axidma_data_stream_can_push(StreamSink *obj, StreamCanPushNotifyFn notify, void *notify_opaque) { - XilinxAXIDMAStreamSlave *ds = XILINX_AXI_DMA_DATA_STREAM(obj); + XilinxAXIDMAStreamSink *ds = XILINX_AXI_DMA_DATA_STREAM(obj); struct Stream *s = &ds->dma->streams[1]; if (!stream_running(s) || stream_idle(s)) { @@ -420,7 +420,7 @@ static size_t xilinx_axidma_data_stream_push(StreamSink *obj, unsigned char *buf, size_t len, bool eop) { - XilinxAXIDMAStreamSlave *ds = XILINX_AXI_DMA_DATA_STREAM(obj); + XilinxAXIDMAStreamSink *ds = XILINX_AXI_DMA_DATA_STREAM(obj); struct Stream *s = &ds->dma->streams[1]; size_t ret; @@ -531,8 +531,8 @@ static const MemoryRegionOps axidma_ops = { static void xilinx_axidma_realize(DeviceState *dev, Error **errp) { XilinxAXIDMA *s = XILINX_AXI_DMA(dev); - XilinxAXIDMAStreamSlave *ds = XILINX_AXI_DMA_DATA_STREAM(&s->rx_data_dev); - XilinxAXIDMAStreamSlave *cs = XILINX_AXI_DMA_CONTROL_STREAM( + XilinxAXIDMAStreamSink *ds = XILINX_AXI_DMA_DATA_STREAM(&s->rx_data_dev); + XilinxAXIDMAStreamSink *cs = XILINX_AXI_DMA_CONTROL_STREAM( &s->rx_control_dev); int i; @@ -631,7 +631,7 @@ static const TypeInfo axidma_info = { static const TypeInfo xilinx_axidma_data_stream_info = { .name = TYPE_XILINX_AXI_DMA_DATA_STREAM, .parent = TYPE_OBJECT, - .instance_size = sizeof(XilinxAXIDMAStreamSlave), + .instance_size = sizeof(XilinxAXIDMAStreamSink), .class_init = xilinx_axidma_stream_class_init, .class_data = &xilinx_axidma_data_stream_class, .interfaces = (InterfaceInfo[]) { @@ -643,7 +643,7 @@ static const TypeInfo xilinx_axidma_data_stream_info = { static const TypeInfo xilinx_axidma_control_stream_info = { .name = TYPE_XILINX_AXI_DMA_CONTROL_STREAM, .parent = TYPE_OBJECT, - .instance_size = sizeof(XilinxAXIDMAStreamSlave), + .instance_size = sizeof(XilinxAXIDMAStreamSink), .class_init = xilinx_axidma_stream_class_init, .class_data = &xilinx_axidma_control_stream_class, .interfaces = (InterfaceInfo[]) { From 357088b1ed241566551631a89f55b7c30c4403d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Thu, 10 Sep 2020 09:01:29 +0200 Subject: [PATCH 020/113] hw/net/xilinx_axienet: Rename StreamSlave as StreamSink MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In order to use inclusive terminology, rename 'slave stream' as 'sink stream'. Signed-off-by: Philippe Mathieu-Daudé Acked-by: Paolo Bonzini Reviewed-by: Edgar E. Iglesias Message-Id: <20200910070131.435543-5-philmd@redhat.com> Signed-off-by: Paolo Bonzini --- hw/net/xilinx_axienet.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/hw/net/xilinx_axienet.c b/hw/net/xilinx_axienet.c index 9bccbe9be3..990ff3a1c2 100644 --- a/hw/net/xilinx_axienet.c +++ b/hw/net/xilinx_axienet.c @@ -45,11 +45,11 @@ OBJECT_DECLARE_SIMPLE_TYPE(XilinxAXIEnet, XILINX_AXI_ENET) -typedef struct XilinxAXIEnetStreamSlave XilinxAXIEnetStreamSlave; -DECLARE_INSTANCE_CHECKER(XilinxAXIEnetStreamSlave, XILINX_AXI_ENET_DATA_STREAM, +typedef struct XilinxAXIEnetStreamSink XilinxAXIEnetStreamSink; +DECLARE_INSTANCE_CHECKER(XilinxAXIEnetStreamSink, XILINX_AXI_ENET_DATA_STREAM, TYPE_XILINX_AXI_ENET_DATA_STREAM) -DECLARE_INSTANCE_CHECKER(XilinxAXIEnetStreamSlave, XILINX_AXI_ENET_CONTROL_STREAM, +DECLARE_INSTANCE_CHECKER(XilinxAXIEnetStreamSink, XILINX_AXI_ENET_CONTROL_STREAM, TYPE_XILINX_AXI_ENET_CONTROL_STREAM) /* Advertisement control register. */ @@ -310,7 +310,7 @@ struct TEMAC { }; -struct XilinxAXIEnetStreamSlave { +struct XilinxAXIEnetStreamSink { Object parent; struct XilinxAXIEnet *enet; @@ -322,8 +322,8 @@ struct XilinxAXIEnet { qemu_irq irq; StreamSink *tx_data_dev; StreamSink *tx_control_dev; - XilinxAXIEnetStreamSlave rx_data_dev; - XilinxAXIEnetStreamSlave rx_control_dev; + XilinxAXIEnetStreamSink rx_data_dev; + XilinxAXIEnetStreamSink rx_control_dev; NICState *nic; NICConf conf; @@ -856,7 +856,7 @@ xilinx_axienet_control_stream_push(StreamSink *obj, uint8_t *buf, size_t len, bool eop) { int i; - XilinxAXIEnetStreamSlave *cs = XILINX_AXI_ENET_CONTROL_STREAM(obj); + XilinxAXIEnetStreamSink *cs = XILINX_AXI_ENET_CONTROL_STREAM(obj); XilinxAXIEnet *s = cs->enet; assert(eop); @@ -877,7 +877,7 @@ static size_t xilinx_axienet_data_stream_push(StreamSink *obj, uint8_t *buf, size_t size, bool eop) { - XilinxAXIEnetStreamSlave *ds = XILINX_AXI_ENET_DATA_STREAM(obj); + XilinxAXIEnetStreamSink *ds = XILINX_AXI_ENET_DATA_STREAM(obj); XilinxAXIEnet *s = ds->enet; /* TX enable ? */ @@ -951,8 +951,8 @@ static NetClientInfo net_xilinx_enet_info = { static void xilinx_enet_realize(DeviceState *dev, Error **errp) { XilinxAXIEnet *s = XILINX_AXI_ENET(dev); - XilinxAXIEnetStreamSlave *ds = XILINX_AXI_ENET_DATA_STREAM(&s->rx_data_dev); - XilinxAXIEnetStreamSlave *cs = XILINX_AXI_ENET_CONTROL_STREAM( + XilinxAXIEnetStreamSink *ds = XILINX_AXI_ENET_DATA_STREAM(&s->rx_data_dev); + XilinxAXIEnetStreamSink *cs = XILINX_AXI_ENET_CONTROL_STREAM( &s->rx_control_dev); object_property_add_link(OBJECT(ds), "enet", "xlnx.axi-ethernet", @@ -1043,7 +1043,7 @@ static const TypeInfo xilinx_enet_info = { static const TypeInfo xilinx_enet_data_stream_info = { .name = TYPE_XILINX_AXI_ENET_DATA_STREAM, .parent = TYPE_OBJECT, - .instance_size = sizeof(XilinxAXIEnetStreamSlave), + .instance_size = sizeof(XilinxAXIEnetStreamSink), .class_init = xilinx_enet_data_stream_class_init, .interfaces = (InterfaceInfo[]) { { TYPE_STREAM_SINK }, @@ -1054,7 +1054,7 @@ static const TypeInfo xilinx_enet_data_stream_info = { static const TypeInfo xilinx_enet_control_stream_info = { .name = TYPE_XILINX_AXI_ENET_CONTROL_STREAM, .parent = TYPE_OBJECT, - .instance_size = sizeof(XilinxAXIEnetStreamSlave), + .instance_size = sizeof(XilinxAXIEnetStreamSink), .class_init = xilinx_enet_control_stream_class_init, .interfaces = (InterfaceInfo[]) { { TYPE_STREAM_SINK }, From 2c4a83eb82eabca549ae5b55342976e6fb200a0b Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 26 Oct 2020 10:30:14 -0400 Subject: [PATCH 021/113] alpha: remove bios_name MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Richard Henderson Signed-off-by: Paolo Bonzini Reviewed-by: Alex Bennée Reviewed-by: Philippe Mathieu-Daudé Message-Id: <20201026143028.3034018-2-pbonzini@redhat.com> Signed-off-by: Paolo Bonzini --- hw/alpha/dp264.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/alpha/dp264.c b/hw/alpha/dp264.c index 4d24518d1d..c4d407a9f1 100644 --- a/hw/alpha/dp264.c +++ b/hw/alpha/dp264.c @@ -107,7 +107,7 @@ static void clipper_init(MachineState *machine) but one explicitly written for the emulation, we might as well load it directly from and ELF image. */ palcode_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, - bios_name ? bios_name : "palcode-clipper"); + machine->firmware ?: "palcode-clipper"); if (palcode_filename == NULL) { error_report("no palcode provided"); exit(1); From 0ad3b5d3ee312e893d92be2de4b7123e03e6119d Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 26 Oct 2020 10:30:16 -0400 Subject: [PATCH 022/113] arm: remove bios_name MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Get the firmware name from the MachineState object. Cc: Peter Maydell Signed-off-by: Paolo Bonzini Reviewed-by: Alex Bennée Message-Id: <20201026143028.3034018-4-pbonzini@redhat.com> Signed-off-by: Paolo Bonzini --- hw/arm/cubieboard.c | 2 +- hw/arm/highbank.c | 8 ++++---- hw/arm/npcm7xx_boards.c | 5 +---- hw/arm/orangepi.c | 2 +- hw/arm/sbsa-ref.c | 2 ++ hw/arm/vexpress.c | 8 ++++---- hw/arm/virt.c | 2 ++ 7 files changed, 15 insertions(+), 14 deletions(-) diff --git a/hw/arm/cubieboard.c b/hw/arm/cubieboard.c index 1c6c792eb6..9d0d728180 100644 --- a/hw/arm/cubieboard.c +++ b/hw/arm/cubieboard.c @@ -40,7 +40,7 @@ static void cubieboard_init(MachineState *machine) DeviceState *carddev; /* BIOS is not supported by this board */ - if (bios_name) { + if (machine->firmware) { error_report("BIOS not supported for this machine"); exit(1); } diff --git a/hw/arm/highbank.c b/hw/arm/highbank.c index f71087860d..fd3429720e 100644 --- a/hw/arm/highbank.c +++ b/hw/arm/highbank.c @@ -297,16 +297,16 @@ static void calxeda_init(MachineState *machine, enum cxmachines machine_id) memory_region_init_ram(sysram, NULL, "highbank.sysram", 0x8000, &error_fatal); memory_region_add_subregion(sysmem, 0xfff88000, sysram); - if (bios_name != NULL) { - sysboot_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name); + if (machine->firmware != NULL) { + sysboot_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, machine->firmware); if (sysboot_filename != NULL) { if (load_image_targphys(sysboot_filename, 0xfff88000, 0x8000) < 0) { - error_report("Unable to load %s", bios_name); + error_report("Unable to load %s", machine->firmware); exit(1); } g_free(sysboot_filename); } else { - error_report("Unable to find %s", bios_name); + error_report("Unable to find %s", machine->firmware); exit(1); } } diff --git a/hw/arm/npcm7xx_boards.c b/hw/arm/npcm7xx_boards.c index 79e2e2744c..9821013bc6 100644 --- a/hw/arm/npcm7xx_boards.c +++ b/hw/arm/npcm7xx_boards.c @@ -33,13 +33,10 @@ static const char npcm7xx_default_bootrom[] = "npcm7xx_bootrom.bin"; static void npcm7xx_load_bootrom(MachineState *machine, NPCM7xxState *soc) { + const char *bios_name = machine->firmware ?: npcm7xx_default_bootrom; g_autofree char *filename = NULL; int ret; - if (!bios_name) { - bios_name = npcm7xx_default_bootrom; - } - filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name); if (!filename) { error_report("Could not find ROM image '%s'", bios_name); diff --git a/hw/arm/orangepi.c b/hw/arm/orangepi.c index 17a568a2b4..d6306dfdda 100644 --- a/hw/arm/orangepi.c +++ b/hw/arm/orangepi.c @@ -41,7 +41,7 @@ static void orangepi_init(MachineState *machine) DeviceState *carddev; /* BIOS is not supported by this board */ - if (bios_name) { + if (machine->firmware) { error_report("BIOS not supported for this machine"); exit(1); } diff --git a/hw/arm/sbsa-ref.c b/hw/arm/sbsa-ref.c index 4a5ea42938..8272983664 100644 --- a/hw/arm/sbsa-ref.c +++ b/hw/arm/sbsa-ref.c @@ -319,6 +319,7 @@ static bool sbsa_firmware_init(SBSAMachineState *sms, MemoryRegion *sysmem, MemoryRegion *secure_sysmem) { + const char *bios_name; int i; BlockBackend *pflash_blk0; @@ -332,6 +333,7 @@ static bool sbsa_firmware_init(SBSAMachineState *sms, pflash_blk0 = pflash_cfi01_get_blk(sms->flash[0]); + bios_name = MACHINE(sms)->firmware; if (bios_name) { char *fname; MemoryRegion *mr; diff --git a/hw/arm/vexpress.c b/hw/arm/vexpress.c index 531f3a122a..1adb663d77 100644 --- a/hw/arm/vexpress.c +++ b/hw/arm/vexpress.c @@ -560,7 +560,7 @@ static void vexpress_common_init(MachineState *machine) /* * If a bios file was provided, attempt to map it into memory */ - if (bios_name) { + if (machine->firmware) { char *fn; int image_size; @@ -570,16 +570,16 @@ static void vexpress_common_init(MachineState *machine) "but you cannot use both options at once"); exit(1); } - fn = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name); + fn = qemu_find_file(QEMU_FILE_TYPE_BIOS, machine->firmware); if (!fn) { - error_report("Could not find ROM image '%s'", bios_name); + error_report("Could not find ROM image '%s'", machine->firmware); exit(1); } image_size = load_image_targphys(fn, map[VE_NORFLASH0], VEXPRESS_FLASH_SIZE); g_free(fn); if (image_size < 0) { - error_report("Could not load ROM image '%s'", bios_name); + error_report("Could not load ROM image '%s'", machine->firmware); exit(1); } } diff --git a/hw/arm/virt.c b/hw/arm/virt.c index 22572c32b7..d09124832d 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c @@ -1047,6 +1047,7 @@ static bool virt_firmware_init(VirtMachineState *vms, MemoryRegion *secure_sysmem) { int i; + const char *bios_name; BlockBackend *pflash_blk0; /* Map legacy -drive if=pflash to machine properties */ @@ -1059,6 +1060,7 @@ static bool virt_firmware_init(VirtMachineState *vms, pflash_blk0 = pflash_cfi01_get_blk(vms->flash[0]); + bios_name = MACHINE(vms)->firmware; if (bios_name) { char *fname; MemoryRegion *mr; From b57e3e9785271a20b00f43d469b3011d0127e565 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 26 Oct 2020 10:30:17 -0400 Subject: [PATCH 023/113] hppa: remove bios_name MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Richard Henderson Signed-off-by: Paolo Bonzini Reviewed-by: Alex Bennée Reviewed-by: Philippe Mathieu-Daudé Message-Id: <20201026143028.3034018-5-pbonzini@redhat.com> Signed-off-by: Paolo Bonzini --- hw/hppa/machine.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/hw/hppa/machine.c b/hw/hppa/machine.c index d5164457ee..5e745d5ea9 100644 --- a/hw/hppa/machine.c +++ b/hw/hppa/machine.c @@ -213,8 +213,7 @@ static void machine_hppa_init(MachineState *machine) but one explicitly written for the emulation, we might as well load it directly from an ELF image. */ firmware_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, - bios_name ? bios_name : - "hppa-firmware.img"); + machine->firmware ?: "hppa-firmware.img"); if (firmware_filename == NULL) { error_report("no firmware provided"); exit(1); From 7d435078afa08eb136bdcdc4f199fd26ddbc353b Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 26 Oct 2020 10:30:18 -0400 Subject: [PATCH 024/113] i386: remove bios_name MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Paolo Bonzini Reviewed-by: Alex Bennée Message-Id: <20201026143028.3034018-6-pbonzini@redhat.com> Signed-off-by: Paolo Bonzini --- hw/i386/microvm.c | 7 +++---- hw/i386/pc_sysfw.c | 4 ++-- hw/i386/x86.c | 10 ++++------ include/hw/i386/x86.h | 3 ++- 4 files changed, 11 insertions(+), 13 deletions(-) diff --git a/hw/i386/microvm.c b/hw/i386/microvm.c index 5688608613..f111ef87d8 100644 --- a/hw/i386/microvm.c +++ b/hw/i386/microvm.c @@ -158,6 +158,7 @@ static int microvm_ioapics(MicrovmMachineState *mms) static void microvm_devices_init(MicrovmMachineState *mms) { + const char *default_firmware; X86MachineState *x86ms = X86_MACHINE(mms); ISABus *isa_bus; ISADevice *rtc_state; @@ -274,12 +275,10 @@ static void microvm_devices_init(MicrovmMachineState *mms) serial_hds_isa_init(isa_bus, 0, 1); } - if (bios_name == NULL) { - bios_name = x86_machine_is_acpi_enabled(x86ms) + default_firmware = x86_machine_is_acpi_enabled(x86ms) ? MICROVM_BIOS_FILENAME : MICROVM_QBOOT_FILENAME; - } - x86_bios_rom_init(get_system_memory(), true); + x86_bios_rom_init(MACHINE(mms), default_firmware, get_system_memory(), true); } static void microvm_memory_init(MicrovmMachineState *mms) diff --git a/hw/i386/pc_sysfw.c b/hw/i386/pc_sysfw.c index f8bd3a8b85..92e90ff013 100644 --- a/hw/i386/pc_sysfw.c +++ b/hw/i386/pc_sysfw.c @@ -213,7 +213,7 @@ void pc_system_firmware_init(PCMachineState *pcms, BlockBackend *pflash_blk[ARRAY_SIZE(pcms->flash)]; if (!pcmc->pci_enabled) { - x86_bios_rom_init(rom_memory, true); + x86_bios_rom_init(MACHINE(pcms), "bios.bin", rom_memory, true); return; } @@ -234,7 +234,7 @@ void pc_system_firmware_init(PCMachineState *pcms, if (!pflash_blk[0]) { /* Machine property pflash0 not set, use ROM mode */ - x86_bios_rom_init(rom_memory, false); + x86_bios_rom_init(MACHINE(pcms), "bios.bin", rom_memory, false); } else { if (kvm_enabled() && !kvm_readonly_mem_enabled()) { /* diff --git a/hw/i386/x86.c b/hw/i386/x86.c index 7c1f64a1fc..f86f6dbbec 100644 --- a/hw/i386/x86.c +++ b/hw/i386/x86.c @@ -55,8 +55,6 @@ #include CONFIG_DEVICES #include "kvm_i386.h" -#define BIOS_FILENAME "bios.bin" - /* Physical Address of PVH entry point read from kernel ELF NOTE */ static size_t pvh_start_addr; @@ -1080,17 +1078,17 @@ void x86_load_linux(X86MachineState *x86ms, nb_option_roms++; } -void x86_bios_rom_init(MemoryRegion *rom_memory, bool isapc_ram_fw) +void x86_bios_rom_init(MachineState *ms, const char *default_firmware, + MemoryRegion *rom_memory, bool isapc_ram_fw) { + const char *bios_name; char *filename; MemoryRegion *bios, *isa_bios; int bios_size, isa_bios_size; int ret; /* BIOS load */ - if (bios_name == NULL) { - bios_name = BIOS_FILENAME; - } + bios_name = ms->firmware ?: default_firmware; filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name); if (filename) { bios_size = get_image_size(filename); diff --git a/include/hw/i386/x86.h b/include/hw/i386/x86.h index 3f9b052cfc..56080bd1fb 100644 --- a/include/hw/i386/x86.h +++ b/include/hw/i386/x86.h @@ -102,7 +102,8 @@ void x86_cpu_unplug_request_cb(HotplugHandler *hotplug_dev, void x86_cpu_unplug_cb(HotplugHandler *hotplug_dev, DeviceState *dev, Error **errp); -void x86_bios_rom_init(MemoryRegion *rom_memory, bool isapc_ram_fw); +void x86_bios_rom_init(MachineState *ms, const char *default_firmware, + MemoryRegion *rom_memory, bool isapc_ram_fw); void x86_load_linux(X86MachineState *x86ms, FWCfgState *fw_cfg, From a408b81b2c6de437db7d6bd4aa8189185608b705 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 26 Oct 2020 10:30:19 -0400 Subject: [PATCH 025/113] lm32: remove bios_name MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Michael Walle Signed-off-by: Paolo Bonzini Reviewed-by: Alex Bennée Message-Id: <20201026143028.3034018-7-pbonzini@redhat.com> Signed-off-by: Paolo Bonzini --- hw/lm32/milkymist.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/hw/lm32/milkymist.c b/hw/lm32/milkymist.c index 9ef94883d5..93ca8bc2ac 100644 --- a/hw/lm32/milkymist.c +++ b/hw/lm32/milkymist.c @@ -108,6 +108,7 @@ static void milkymist_init(MachineState *machine) { MachineClass *mc = MACHINE_GET_CLASS(machine); + const char *bios_name = machine->firmware ?: BIOS_FILENAME; const char *kernel_filename = machine->kernel_filename; const char *kernel_cmdline = machine->kernel_cmdline; const char *initrd_filename = machine->initrd_filename; @@ -162,9 +163,6 @@ milkymist_init(MachineState *machine) } /* load bios rom */ - if (bios_name == NULL) { - bios_name = BIOS_FILENAME; - } bios_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name); if (bios_filename) { From 1684273ca8144d8f7dc9c8e9fea17753a9c09fd8 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 26 Oct 2020 10:30:20 -0400 Subject: [PATCH 026/113] m68k: remove bios_name MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Laurent Vivier Signed-off-by: Paolo Bonzini Acked-by: Laurent Vivier Reviewed-by: Alex Bennée Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Thomas Huth Message-Id: <20201026143028.3034018-8-pbonzini@redhat.com> Signed-off-by: Paolo Bonzini --- hw/m68k/mcf5208.c | 10 +++++----- hw/m68k/next-cube.c | 4 +--- hw/m68k/q800.c | 4 +--- 3 files changed, 7 insertions(+), 11 deletions(-) diff --git a/hw/m68k/mcf5208.c b/hw/m68k/mcf5208.c index d310a98e7b..7c8ca5ddf6 100644 --- a/hw/m68k/mcf5208.c +++ b/hw/m68k/mcf5208.c @@ -301,17 +301,17 @@ static void mcf5208evb_init(MachineState *machine) /* 0xfc0a8000 SDRAM controller. */ /* Load firmware */ - if (bios_name) { + if (machine->firmware) { char *fn; uint8_t *ptr; - fn = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name); + fn = qemu_find_file(QEMU_FILE_TYPE_BIOS, machine->firmware); if (!fn) { - error_report("Could not find ROM image '%s'", bios_name); + error_report("Could not find ROM image '%s'", machine->firmware); exit(1); } if (load_image_targphys(fn, 0x0, ROM_SIZE) < 8) { - error_report("Could not load ROM image '%s'", bios_name); + error_report("Could not load ROM image '%s'", machine->firmware); exit(1); } g_free(fn); @@ -323,7 +323,7 @@ static void mcf5208evb_init(MachineState *machine) /* Load kernel. */ if (!kernel_filename) { - if (qtest_enabled() || bios_name) { + if (qtest_enabled() || machine->firmware) { return; } error_report("Kernel image must be specified"); diff --git a/hw/m68k/next-cube.c b/hw/m68k/next-cube.c index e7045980b7..37bc35dfa4 100644 --- a/hw/m68k/next-cube.c +++ b/hw/m68k/next-cube.c @@ -868,6 +868,7 @@ static void next_cube_init(MachineState *machine) MemoryRegion *bmapm1 = g_new(MemoryRegion, 1); MemoryRegion *bmapm2 = g_new(MemoryRegion, 1); MemoryRegion *sysmem = get_system_memory(); + const char *bios_name = machine->firmware ?: ROM_FILE; NeXTState *ns = NEXT_MACHINE(machine); DeviceState *dev; @@ -924,9 +925,6 @@ static void next_cube_init(MachineState *machine) sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, 0x0200e000); /* Load ROM here */ - if (bios_name == NULL) { - bios_name = ROM_FILE; - } /* still not sure if the rom should also be mapped at 0x0*/ memory_region_init_rom(rom, NULL, "next.rom", 0x20000, &error_fatal); memory_region_add_subregion(sysmem, 0x01000000, rom); diff --git a/hw/m68k/q800.c b/hw/m68k/q800.c index ce4b47c3e3..6ebcddcfb2 100644 --- a/hw/m68k/q800.c +++ b/hw/m68k/q800.c @@ -167,6 +167,7 @@ static void q800_init(MachineState *machine) const char *kernel_filename = machine->kernel_filename; const char *initrd_filename = machine->initrd_filename; const char *kernel_cmdline = machine->kernel_cmdline; + const char *bios_name = machine->firmware ?: MACROM_FILENAME; hwaddr parameters_base; CPUState *cs; DeviceState *dev; @@ -400,9 +401,6 @@ static void q800_init(MachineState *machine) rom = g_malloc(sizeof(*rom)); memory_region_init_rom(rom, NULL, "m68k_mac.rom", MACROM_SIZE, &error_abort); - if (bios_name == NULL) { - bios_name = MACROM_FILENAME; - } filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name); memory_region_add_subregion(get_system_memory(), MACROM_ADDR, rom); From 59588bea5efa3f497a39a05ec94aed289afd3d2a Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 26 Oct 2020 10:30:21 -0400 Subject: [PATCH 027/113] mips: remove bios_name MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Philippe Mathieu-Daudé Signed-off-by: Paolo Bonzini Reviewed-by: Alex Bennée Message-Id: <20201026143028.3034018-9-pbonzini@redhat.com> Signed-off-by: Paolo Bonzini --- hw/mips/fuloong2e.c | 6 +++--- hw/mips/jazz.c | 6 +++--- hw/mips/malta.c | 6 +++--- hw/mips/mipssim.c | 6 +++--- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/hw/mips/fuloong2e.c b/hw/mips/fuloong2e.c index a9e0c2f8d3..25b679011f 100644 --- a/hw/mips/fuloong2e.c +++ b/hw/mips/fuloong2e.c @@ -338,7 +338,7 @@ static void mips_fuloong2e_init(MachineState *machine) write_bootloader(env, memory_region_get_ram_ptr(bios), kernel_entry); } else { filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, - bios_name ?: FULOONG_BIOSNAME); + machine->firmware ?: FULOONG_BIOSNAME); if (filename) { bios_size = load_image_targphys(filename, 0x1fc00000LL, BIOS_SIZE); @@ -348,8 +348,8 @@ static void mips_fuloong2e_init(MachineState *machine) } if ((bios_size < 0 || bios_size > BIOS_SIZE) && - bios_name && !qtest_enabled()) { - error_report("Could not load MIPS bios '%s'", bios_name); + machine->firmware && !qtest_enabled()) { + error_report("Could not load MIPS bios '%s'", machine->firmware); exit(1); } } diff --git a/hw/mips/jazz.c b/hw/mips/jazz.c index 71448f72ac..aa95c6a3d3 100644 --- a/hw/mips/jazz.c +++ b/hw/mips/jazz.c @@ -218,7 +218,7 @@ static void mips_jazz_init(MachineState *machine, memory_region_add_subregion(address_space, 0xfff00000LL, bios2); /* load the BIOS image. */ - filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name ?: BIOS_FILENAME); + filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, machine->firmware ?: BIOS_FILENAME); if (filename) { bios_size = load_image_targphys(filename, 0xfff00000LL, MAGNUM_BIOS_SIZE); @@ -227,8 +227,8 @@ static void mips_jazz_init(MachineState *machine, bios_size = -1; } if ((bios_size < 0 || bios_size > MAGNUM_BIOS_SIZE) - && bios_name && !qtest_enabled()) { - error_report("Could not load MIPS bios '%s'", bios_name); + && machine->firmware && !qtest_enabled()) { + error_report("Could not load MIPS bios '%s'", machine->firmware); exit(1); } diff --git a/hw/mips/malta.c b/hw/mips/malta.c index 9d1a3b50b7..ef369945d1 100644 --- a/hw/mips/malta.c +++ b/hw/mips/malta.c @@ -1333,7 +1333,7 @@ void mips_malta_init(MachineState *machine) if (!dinfo) { /* Load a BIOS image. */ filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, - bios_name ?: BIOS_FILENAME); + machine->firmware ?: BIOS_FILENAME); if (filename) { bios_size = load_image_targphys(filename, FLASH_ADDRESS, BIOS_SIZE); @@ -1342,8 +1342,8 @@ void mips_malta_init(MachineState *machine) bios_size = -1; } if ((bios_size < 0 || bios_size > BIOS_SIZE) && - bios_name && !qtest_enabled()) { - error_report("Could not load MIPS bios '%s'", bios_name); + machine->firmware && !qtest_enabled()) { + error_report("Could not load MIPS bios '%s'", machine->firmware); exit(1); } } diff --git a/hw/mips/mipssim.c b/hw/mips/mipssim.c index aaa62a0f4b..cc9b0934b3 100644 --- a/hw/mips/mipssim.c +++ b/hw/mips/mipssim.c @@ -177,7 +177,7 @@ mips_mipssim_init(MachineState *machine) /* Map the BIOS / boot exception handler. */ memory_region_add_subregion(address_space_mem, 0x1fc00000LL, bios); /* Load a BIOS / boot exception handler image. */ - filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name ?: BIOS_FILENAME); + filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, machine->firmware ?: BIOS_FILENAME); if (filename) { bios_size = load_image_targphys(filename, 0x1fc00000LL, BIOS_SIZE); g_free(filename); @@ -185,9 +185,9 @@ mips_mipssim_init(MachineState *machine) bios_size = -1; } if ((bios_size < 0 || bios_size > BIOS_SIZE) && - bios_name && !qtest_enabled()) { + machine->firmware && !qtest_enabled()) { /* Bail out if we have neither a kernel image nor boot vector code. */ - error_report("Could not load MIPS bios '%s'", bios_name); + error_report("Could not load MIPS bios '%s'", machine->firmware); exit(1); } else { /* We have a boot vector start address. */ From b029702bac28533bf8085f7c63c8b870d01acd47 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 26 Oct 2020 10:30:22 -0400 Subject: [PATCH 028/113] moxie: remove bios_name MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Paolo Bonzini Reviewed-by: Alex Bennée Message-Id: <20201026143028.3034018-10-pbonzini@redhat.com> Signed-off-by: Paolo Bonzini --- hw/moxie/moxiesim.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/hw/moxie/moxiesim.c b/hw/moxie/moxiesim.c index a765e9f6be..d07d504c0d 100644 --- a/hw/moxie/moxiesim.c +++ b/hw/moxie/moxiesim.c @@ -133,9 +133,9 @@ static void moxiesim_init(MachineState *machine) loader_params.initrd_filename = initrd_filename; load_kernel(cpu, &loader_params); } - if (bios_name) { - if (load_image_targphys(bios_name, FIRMWARE_BASE, FIRMWARE_SIZE) < 0) { - error_report("Failed to load firmware '%s'", bios_name); + if (machine->firmware) { + if (load_image_targphys(machine->firmware, FIRMWARE_BASE, FIRMWARE_SIZE) < 0) { + error_report("Failed to load firmware '%s'", machine->firmware); } } From cd7b94989a468bbdca40f663f35ce954c44a8c3f Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 26 Oct 2020 10:30:23 -0400 Subject: [PATCH 029/113] ppc: remove bios_name MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: David Gibson Signed-off-by: Paolo Bonzini Acked-by: David Gibson Reviewed-by: Alex Bennée Message-Id: <20201026143028.3034018-11-pbonzini@redhat.com> Signed-off-by: Paolo Bonzini --- hw/ppc/e500.c | 4 ++-- hw/ppc/mac_newworld.c | 4 +--- hw/ppc/mac_oldworld.c | 4 +--- hw/ppc/pnv.c | 5 +---- hw/ppc/ppc405_boards.c | 6 ++---- hw/ppc/prep.c | 4 +--- hw/ppc/spapr.c | 4 +--- 7 files changed, 9 insertions(+), 22 deletions(-) diff --git a/hw/ppc/e500.c b/hw/ppc/e500.c index ae39b9358e..153a74c98c 100644 --- a/hw/ppc/e500.c +++ b/hw/ppc/e500.c @@ -1035,7 +1035,7 @@ void ppce500_init(MachineState *machine) * -kernel to users but allows them to run through u-boot as well. */ kernel_as_payload = false; - if (bios_name == NULL) { + if (machine->firmware == NULL) { if (machine->kernel_filename) { payload_name = machine->kernel_filename; kernel_as_payload = true; @@ -1043,7 +1043,7 @@ void ppce500_init(MachineState *machine) payload_name = "u-boot.e500"; } } else { - payload_name = bios_name; + payload_name = machine->firmware; } filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, payload_name); diff --git a/hw/ppc/mac_newworld.c b/hw/ppc/mac_newworld.c index f9a1cc8944..61c63819df 100644 --- a/hw/ppc/mac_newworld.c +++ b/hw/ppc/mac_newworld.c @@ -109,6 +109,7 @@ static void ppc_core99_reset(void *opaque) static void ppc_core99_init(MachineState *machine) { ram_addr_t ram_size = machine->ram_size; + const char *bios_name = machine->firmware ?: PROM_FILENAME; const char *kernel_filename = machine->kernel_filename; const char *kernel_cmdline = machine->kernel_cmdline; const char *initrd_filename = machine->initrd_filename; @@ -161,9 +162,6 @@ static void ppc_core99_init(MachineState *machine) &error_fatal); memory_region_add_subregion(get_system_memory(), PROM_BASE, bios); - if (!bios_name) { - bios_name = PROM_FILENAME; - } filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name); if (filename) { /* Load OpenBIOS (ELF) */ diff --git a/hw/ppc/mac_oldworld.c b/hw/ppc/mac_oldworld.c index 6c59aa5601..11623e8e67 100644 --- a/hw/ppc/mac_oldworld.c +++ b/hw/ppc/mac_oldworld.c @@ -83,6 +83,7 @@ static void ppc_heathrow_reset(void *opaque) static void ppc_heathrow_init(MachineState *machine) { ram_addr_t ram_size = machine->ram_size; + const char *bios_name = machine->firmware ?: PROM_FILENAME; const char *boot_device = machine->boot_order; PowerPCCPU *cpu = NULL; CPUPPCState *env = NULL; @@ -130,9 +131,6 @@ static void ppc_heathrow_init(MachineState *machine) &error_fatal); memory_region_add_subregion(get_system_memory(), PROM_BASE, bios); - if (!bios_name) { - bios_name = PROM_FILENAME; - } filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name); if (filename) { /* Load OpenBIOS (ELF) */ diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c index 50ebd4a484..53a5121cab 100644 --- a/hw/ppc/pnv.c +++ b/hw/ppc/pnv.c @@ -713,6 +713,7 @@ static void pnv_chip_power10_pic_print_info(PnvChip *chip, Monitor *mon) static void pnv_init(MachineState *machine) { + const char *bios_name = machine->firmware ?: FW_FILE_NAME; PnvMachineState *pnv = PNV_MACHINE(machine); MachineClass *mc = MACHINE_GET_CLASS(machine); char *fw_filename; @@ -739,10 +740,6 @@ static void pnv_init(MachineState *machine) pnv->pnor = PNV_PNOR(dev); /* load skiboot firmware */ - if (bios_name == NULL) { - bios_name = FW_FILE_NAME; - } - fw_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name); if (!fw_filename) { error_report("Could not find OPAL firmware '%s'", bios_name); diff --git a/hw/ppc/ppc405_boards.c b/hw/ppc/ppc405_boards.c index 4687715b15..c867e46330 100644 --- a/hw/ppc/ppc405_boards.c +++ b/hw/ppc/ppc405_boards.c @@ -141,6 +141,7 @@ static void ref405ep_fpga_init(MemoryRegion *sysmem, uint32_t base) static void ref405ep_init(MachineState *machine) { MachineClass *mc = MACHINE_GET_CLASS(machine); + const char *bios_name = machine->firmware ?: BIOS_FILENAME; const char *kernel_filename = machine->kernel_filename; const char *kernel_cmdline = machine->kernel_cmdline; const char *initrd_filename = machine->initrd_filename; @@ -206,8 +207,6 @@ static void ref405ep_init(MachineState *machine) memory_region_init_rom(bios, NULL, "ef405ep.bios", BIOS_SIZE, &error_fatal); - if (bios_name == NULL) - bios_name = BIOS_FILENAME; filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name); if (filename) { bios_size = load_image_size(filename, @@ -425,6 +424,7 @@ static void taihu_cpld_init(MemoryRegion *sysmem, uint32_t base) static void taihu_405ep_init(MachineState *machine) { MachineClass *mc = MACHINE_GET_CLASS(machine); + const char *bios_name = machine->firmware ?: BIOS_FILENAME; const char *kernel_filename = machine->kernel_filename; const char *initrd_filename = machine->initrd_filename; char *filename; @@ -475,8 +475,6 @@ static void taihu_405ep_init(MachineState *machine) } else #endif { - if (bios_name == NULL) - bios_name = BIOS_FILENAME; bios = g_new(MemoryRegion, 1); memory_region_init_rom(bios, NULL, "taihu_405ep.bios", BIOS_SIZE, &error_fatal); diff --git a/hw/ppc/prep.c b/hw/ppc/prep.c index 4a0cb434a6..c6b9d1ddcb 100644 --- a/hw/ppc/prep.c +++ b/hw/ppc/prep.c @@ -237,6 +237,7 @@ static int prep_set_cmos_checksum(DeviceState *dev, void *opaque) static void ibm_40p_init(MachineState *machine) { + const char *bios_name = machine->firmware ?: "openbios-ppc"; CPUPPCState *env = NULL; uint16_t cmos_checksum; PowerPCCPU *cpu; @@ -271,9 +272,6 @@ static void ibm_40p_init(MachineState *machine) /* PCI host */ dev = qdev_new("raven-pcihost"); - if (!bios_name) { - bios_name = "openbios-ppc"; - } qdev_prop_set_string(dev, "bios-name", bios_name); qdev_prop_set_uint32(dev, "elf-machine", PPC_ELF_MACHINE); pcihost = SYS_BUS_DEVICE(dev); diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index c060702013..e87a3b8557 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -2657,6 +2657,7 @@ static void spapr_machine_init(MachineState *machine) SpaprMachineState *spapr = SPAPR_MACHINE(machine); SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(machine); MachineClass *mc = MACHINE_GET_CLASS(machine); + const char *bios_name = machine->firmware ?: FW_FILE_NAME; const char *kernel_filename = machine->kernel_filename; const char *initrd_filename = machine->initrd_filename; PCIHostState *phb; @@ -2980,9 +2981,6 @@ static void spapr_machine_init(MachineState *machine) } } - if (bios_name == NULL) { - bios_name = FW_FILE_NAME; - } filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name); if (!filename) { error_report("Could not find LPAR firmware '%s'", bios_name); From ac6dd9b9f3dd6f0914a9c822fdeb43149bc9c9ff Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 22 Oct 2020 11:12:46 -0400 Subject: [PATCH 030/113] rx: move BIOS load from MCU to board MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The ROM loader state is global and not part of the MCU, and the BIOS is in machine->firmware. So just like the kernel case, load it in the board. Due to the ordering between CPU reset and ROM reset, the ROM has to be registered before the CPU is realized, otherwise the reset vector is loaded before the ROM is there. Reviewed-by: Philippe Mathieu-Daudé Tested-by: Philippe Mathieu-Daudé Signed-off-by: Paolo Bonzini --- hw/rx/rx-gdbsim.c | 10 ++++++++++ hw/rx/rx62n.c | 9 --------- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/hw/rx/rx-gdbsim.c b/hw/rx/rx-gdbsim.c index 285549c79b..b1d7c2488f 100644 --- a/hw/rx/rx-gdbsim.c +++ b/hw/rx/rx-gdbsim.c @@ -106,6 +106,16 @@ static void rx_gdbsim_init(MachineState *machine) rxc->xtal_freq_hz, &error_abort); object_property_set_bool(OBJECT(&s->mcu), "load-kernel", kernel_filename != NULL, &error_abort); + + if (!kernel_filename) { + if (machine->firmware) { + rom_add_file_fixed(machine->firmware, RX62N_CFLASH_BASE, 0); + } else if (!qtest_enabled()) { + error_report("No bios or kernel specified"); + exit(1); + } + } + qdev_realize(DEVICE(&s->mcu), NULL, &error_abort); /* Load kernel and dtb */ diff --git a/hw/rx/rx62n.c b/hw/rx/rx62n.c index 6eb4eea700..17ec73fc7b 100644 --- a/hw/rx/rx62n.c +++ b/hw/rx/rx62n.c @@ -245,15 +245,6 @@ static void rx62n_realize(DeviceState *dev, Error **errp) rxc->rom_flash_size, &error_abort); memory_region_add_subregion(s->sysmem, RX62N_CFLASH_BASE, &s->c_flash); - if (!s->kernel) { - if (bios_name) { - rom_add_file_fixed(bios_name, RX62N_CFLASH_BASE, 0); - } else if (!qtest_enabled()) { - error_report("No bios or kernel specified"); - exit(1); - } - } - /* Initialize CPU */ object_initialize_child(OBJECT(s), "cpu", &s->cpu, TYPE_RX62N_CPU); qdev_realize(DEVICE(&s->cpu), NULL, &error_abort); From f03443954b5bab576880e373de8bd221a0818b02 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 26 Oct 2020 10:30:25 -0400 Subject: [PATCH 031/113] s390: remove bios_name MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Thomas Huth Signed-off-by: Paolo Bonzini Reviewed-by: Alex Bennée Reviewed-by: Thomas Huth Message-Id: <20201026143028.3034018-13-pbonzini@redhat.com> Signed-off-by: Paolo Bonzini --- hw/s390x/ipl.c | 8 ++------ hw/s390x/s390-virtio-ccw.c | 3 ++- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/hw/s390x/ipl.c b/hw/s390x/ipl.c index 3d2652d75a..61e8c967d3 100644 --- a/hw/s390x/ipl.c +++ b/hw/s390x/ipl.c @@ -128,11 +128,7 @@ static void s390_ipl_realize(DeviceState *dev, Error **errp) if (!ipl->kernel || ipl->enforce_bios) { uint64_t fwbase = (MIN(ram_size, 0x80000000U) - 0x200000) & ~0xffffUL; - if (bios_name == NULL) { - bios_name = ipl->firmware; - } - - bios_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name); + bios_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, ipl->firmware); if (bios_filename == NULL) { error_setg(errp, "could not find stage1 bootloader"); return; @@ -154,7 +150,7 @@ static void s390_ipl_realize(DeviceState *dev, Error **errp) g_free(bios_filename); if (bios_size == -1) { - error_setg(errp, "could not load bootloader '%s'", bios_name); + error_setg(errp, "could not load bootloader '%s'", ipl->firmware); return; } diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c index f0ee8dae68..a6324d94f1 100644 --- a/hw/s390x/s390-virtio-ccw.c +++ b/hw/s390x/s390-virtio-ccw.c @@ -259,7 +259,8 @@ static void ccw_init(MachineState *machine) /* get a BUS */ css_bus = virtual_css_bus_init(); s390_init_ipl_dev(machine->kernel_filename, machine->kernel_cmdline, - machine->initrd_filename, "s390-ccw.img", + machine->initrd_filename, + machine->firmware ?: "s390-ccw.img", "s390-netboot.img", true); dev = qdev_new(TYPE_S390_PCI_HOST_BRIDGE); From 2893cad6b987fd4564b5793fee31c907c3638fa6 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 26 Oct 2020 10:30:26 -0400 Subject: [PATCH 032/113] sh4: remove bios_name MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Yoshinori Sato Signed-off-by: Paolo Bonzini Reviewed-by: Alex Bennée Reviewed-by: Philippe Mathieu-Daudé Message-Id: <20201026143028.3034018-14-pbonzini@redhat.com> Signed-off-by: Paolo Bonzini --- hw/sh4/shix.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/hw/sh4/shix.c b/hw/sh4/shix.c index f410c08883..d9a9fcbc59 100644 --- a/hw/sh4/shix.c +++ b/hw/sh4/shix.c @@ -49,6 +49,7 @@ static void shix_init(MachineState *machine) MemoryRegion *sysmem = get_system_memory(); MemoryRegion *rom = g_new(MemoryRegion, 1); MemoryRegion *sdram = g_new(MemoryRegion, 2); + const char *bios_name = machine->firmware ?: BIOS_FILENAME; cpu = SUPERH_CPU(cpu_create(machine->cpu_type)); @@ -63,8 +64,6 @@ static void shix_init(MachineState *machine) memory_region_add_subregion(sysmem, 0x0c000000, &sdram[1]); /* Load BIOS in 0 (and access it through P2, 0xA0000000) */ - if (bios_name == NULL) - bios_name = BIOS_FILENAME; ret = load_image_targphys(bios_name, 0, 0x4000); if (ret < 0 && !qtest_enabled()) { error_report("Could not load SHIX bios '%s'", bios_name); From 377ce9cb0f728270d8acbe2c04b68596a5b3be71 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 26 Oct 2020 10:30:27 -0400 Subject: [PATCH 033/113] sparc: remove bios_name MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Mark Cave-Ayland Signed-off-by: Paolo Bonzini Reviewed-by: Alex Bennée Reviewed-by: Philippe Mathieu-Daudé Message-Id: <20201026143028.3034018-15-pbonzini@redhat.com> Signed-off-by: Paolo Bonzini --- hw/sparc/leon3.c | 4 +--- hw/sparc/sun4m.c | 2 +- hw/sparc64/sun4u.c | 2 +- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/hw/sparc/leon3.c b/hw/sparc/leon3.c index d40b7891f6..1c50b02f81 100644 --- a/hw/sparc/leon3.c +++ b/hw/sparc/leon3.c @@ -185,6 +185,7 @@ static void leon3_set_pil_in(void *opaque, int n, int level) static void leon3_generic_hw_init(MachineState *machine) { ram_addr_t ram_size = machine->ram_size; + const char *bios_name = machine->firmware ?: LEON3_PROM_FILENAME; const char *kernel_filename = machine->kernel_filename; SPARCCPU *cpu; CPUSPARCState *env; @@ -259,9 +260,6 @@ static void leon3_generic_hw_init(MachineState *machine) memory_region_add_subregion(address_space_mem, LEON3_PROM_OFFSET, prom); /* Load boot prom */ - if (bios_name == NULL) { - bios_name = LEON3_PROM_FILENAME; - } filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name); if (filename) { diff --git a/hw/sparc/sun4m.c b/hw/sparc/sun4m.c index 66fecb152a..0f9cd2bf52 100644 --- a/hw/sparc/sun4m.c +++ b/hw/sparc/sun4m.c @@ -882,7 +882,7 @@ static void sun4m_hw_init(const struct sun4m_hwdef *hwdef, hwdef->max_mem - machine->ram_size); } - prom_init(hwdef->slavio_base, bios_name); + prom_init(hwdef->slavio_base, machine->firmware); slavio_intctl = slavio_intctl_init(hwdef->intctl_base, hwdef->intctl_base + 0x10000ULL, diff --git a/hw/sparc64/sun4u.c b/hw/sparc64/sun4u.c index 2f8fc670cf..22896b4c62 100644 --- a/hw/sparc64/sun4u.c +++ b/hw/sparc64/sun4u.c @@ -578,7 +578,7 @@ static void sun4uv_init(MemoryRegion *address_space_mem, /* set up devices */ ram_init(0, machine->ram_size); - prom_init(hwdef->prom_addr, bios_name); + prom_init(hwdef->prom_addr, machine->firmware); /* Init sabre (PCI host bridge) */ sabre = SABRE(qdev_new(TYPE_SABRE)); From 43e61243cd0e89aa4e9492d8592f28c40a7c73ba Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 22 Oct 2020 10:50:02 -0400 Subject: [PATCH 034/113] digic: remove bios_name Pull defaults to digic4_board_init so that a MachineState is available. Cc: Peter Maydell Signed-off-by: Paolo Bonzini --- hw/arm/digic_boards.c | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/hw/arm/digic_boards.c b/hw/arm/digic_boards.c index d5524d3e72..fd228fa96f 100644 --- a/hw/arm/digic_boards.c +++ b/hw/arm/digic_boards.c @@ -70,19 +70,20 @@ static void digic4_board_init(MachineState *machine, DigicBoard *board) memory_region_add_subregion(get_system_memory(), 0, machine->ram); if (board->add_rom0) { - board->add_rom0(s, DIGIC4_ROM0_BASE, board->rom0_def_filename); + board->add_rom0(s, DIGIC4_ROM0_BASE, + machine->firmware ?: board->rom0_def_filename); } if (board->add_rom1) { - board->add_rom1(s, DIGIC4_ROM1_BASE, board->rom1_def_filename); + board->add_rom1(s, DIGIC4_ROM1_BASE, + machine->firmware ?: board->rom1_def_filename); } } static void digic_load_rom(DigicState *s, hwaddr addr, - hwaddr max_size, const char *def_filename) + hwaddr max_size, const char *filename) { target_long rom_size; - const char *filename; if (qtest_enabled()) { /* qtest runs no code so don't attempt a ROM load which @@ -91,12 +92,6 @@ static void digic_load_rom(DigicState *s, hwaddr addr, return; } - if (bios_name) { - filename = bios_name; - } else { - filename = def_filename; - } - if (filename) { char *fn = qemu_find_file(QEMU_FILE_TYPE_BIOS, filename); @@ -119,7 +114,7 @@ static void digic_load_rom(DigicState *s, hwaddr addr, * 64M Bit (4Mx16) Page Mode / Multi-Bank NOR Flash Memory */ static void digic4_add_k8p3215uqb_rom(DigicState *s, hwaddr addr, - const char *def_filename) + const char *filename) { #define FLASH_K8P3215UQB_SIZE (4 * 1024 * 1024) #define FLASH_K8P3215UQB_SECTOR_SIZE (64 * 1024) @@ -131,7 +126,7 @@ static void digic4_add_k8p3215uqb_rom(DigicState *s, hwaddr addr, 0x00EC, 0x007E, 0x0003, 0x0001, 0x0555, 0x2aa, 0); - digic_load_rom(s, addr, FLASH_K8P3215UQB_SIZE, def_filename); + digic_load_rom(s, addr, FLASH_K8P3215UQB_SIZE, filename); } static DigicBoard digic4_board_canon_a1100 = { From d619f157a50f0c98baee2dce0b6a5ca66fa89ac9 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 26 Oct 2020 10:30:28 -0400 Subject: [PATCH 035/113] vl: remove bios_name MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit bios_name was a legacy variable used by machine code, but it is no more. Signed-off-by: Paolo Bonzini Reviewed-by: Alex Bennée Message-Id: <20201026143028.3034018-16-pbonzini@redhat.com> Signed-off-by: Paolo Bonzini --- include/sysemu/sysemu.h | 1 - softmmu/vl.c | 2 -- 2 files changed, 3 deletions(-) diff --git a/include/sysemu/sysemu.h b/include/sysemu/sysemu.h index 817ff4cf75..1336b4264a 100644 --- a/include/sysemu/sysemu.h +++ b/include/sysemu/sysemu.h @@ -8,7 +8,6 @@ /* vl.c */ -extern const char *bios_name; extern int only_migratable; extern const char *qemu_name; extern QemuUUID qemu_uuid; diff --git a/softmmu/vl.c b/softmmu/vl.c index bbe65d3742..2b82e6f5cd 100644 --- a/softmmu/vl.c +++ b/softmmu/vl.c @@ -119,7 +119,6 @@ static const char *data_dir[16]; static int data_dir_idx; -const char *bios_name = NULL; enum vga_retrace_method vga_retrace_method = VGA_RETRACE_DUMB; int display_opengl; const char* keyboard_layout = NULL; @@ -4212,7 +4211,6 @@ void qemu_init(int argc, char **argv, char **envp) kernel_filename = qemu_opt_get(machine_opts, "kernel"); initrd_filename = qemu_opt_get(machine_opts, "initrd"); kernel_cmdline = qemu_opt_get(machine_opts, "append"); - bios_name = qemu_opt_get(machine_opts, "firmware"); opts = qemu_opts_find(qemu_find_opts("boot-opts"), NULL); if (opts) { From 6e504a989dece8136d58f9f7c42f6e22b1ce49ae Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 28 Oct 2020 06:18:20 -0400 Subject: [PATCH 036/113] arm: do not use ram_size global Use the machine properties instead. Cc: qemu-ppc@nongnu.org Signed-off-by: Paolo Bonzini --- hw/arm/aspeed.c | 8 ++++---- hw/display/pxa2xx_lcd.c | 5 +++-- target/arm/arm-semi.c | 3 ++- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c index bfe2051cfe..a17b75f494 100644 --- a/hw/arm/aspeed.c +++ b/hw/arm/aspeed.c @@ -309,7 +309,7 @@ static void aspeed_machine_init(MachineState *machine) /* * This will error out if isize is not supported by memory controller. */ - object_property_set_uint(OBJECT(&bmc->soc), "ram-size", ram_size, + object_property_set_uint(OBJECT(&bmc->soc), "ram-size", machine->ram_size, &error_fatal); for (i = 0; i < sc->macs_num; i++) { @@ -346,8 +346,8 @@ static void aspeed_machine_init(MachineState *machine) max_ram_size = object_property_get_uint(OBJECT(&bmc->soc), "max-ram-size", &error_abort); memory_region_init_io(&bmc->max_ram, NULL, &max_ram_ops, NULL, - "max_ram", max_ram_size - ram_size); - memory_region_add_subregion(&bmc->ram_container, ram_size, &bmc->max_ram); + "max_ram", max_ram_size - machine->ram_size); + memory_region_add_subregion(&bmc->ram_container, machine->ram_size, &bmc->max_ram); aspeed_board_init_flashes(&bmc->soc.fmc, bmc->fmc_model ? bmc->fmc_model : amc->fmc_model); @@ -392,7 +392,7 @@ static void aspeed_machine_init(MachineState *machine) aspeed_board_binfo.smp_loader_start = AST_SMP_MBOX_CODE; } - aspeed_board_binfo.ram_size = ram_size; + aspeed_board_binfo.ram_size = machine->ram_size; aspeed_board_binfo.loader_start = sc->memmap[ASPEED_DEV_SDRAM]; aspeed_board_binfo.nb_cpus = sc->num_cpus; diff --git a/hw/display/pxa2xx_lcd.c b/hw/display/pxa2xx_lcd.c index ff90104b80..dfff994962 100644 --- a/hw/display/pxa2xx_lcd.c +++ b/hw/display/pxa2xx_lcd.c @@ -17,6 +17,7 @@ #include "ui/console.h" #include "hw/arm/pxa.h" #include "ui/pixel_ops.h" +#include "hw/boards.h" /* FIXME: For graphic_rotate. Should probably be done in common code. */ #include "sysemu/sysemu.h" #include "framebuffer.h" @@ -305,7 +306,7 @@ static void pxa2xx_descriptor_load(PXA2xxLCDState *s) descptr = s->dma_ch[i].descriptor; if (!((descptr >= PXA2XX_SDRAM_BASE && descptr + - sizeof(desc) <= PXA2XX_SDRAM_BASE + ram_size) || + sizeof(desc) <= PXA2XX_SDRAM_BASE + current_machine->ram_size) || (descptr >= PXA2XX_INTERNAL_BASE && descptr + sizeof(desc) <= PXA2XX_INTERNAL_BASE + PXA2XX_INTERNAL_SIZE))) { continue; @@ -850,7 +851,7 @@ static void pxa2xx_update_display(void *opaque) } fbptr = s->dma_ch[ch].source; if (!((fbptr >= PXA2XX_SDRAM_BASE && - fbptr <= PXA2XX_SDRAM_BASE + ram_size) || + fbptr <= PXA2XX_SDRAM_BASE + current_machine->ram_size) || (fbptr >= PXA2XX_INTERNAL_BASE && fbptr <= PXA2XX_INTERNAL_BASE + PXA2XX_INTERNAL_SIZE))) { pxa2xx_dma_ber_set(s, ch); diff --git a/target/arm/arm-semi.c b/target/arm/arm-semi.c index c892e0e674..f7b7bff522 100644 --- a/target/arm/arm-semi.c +++ b/target/arm/arm-semi.c @@ -37,6 +37,7 @@ #include "exec/gdbstub.h" #include "qemu/cutils.h" #include "hw/arm/boot.h" +#include "hw/boards.h" #endif #define TARGET_SYS_OPEN 0x01 @@ -1048,7 +1049,7 @@ target_ulong do_arm_semihosting(CPUARMState *env) retvals[2] = ts->stack_base; retvals[3] = 0; /* Stack limit. */ #else - limit = ram_size; + limit = current_machine->ram_size; /* TODO: Make this use the limit of the loaded application. */ retvals[0] = rambase + limit / 2; retvals[1] = rambase + limit; From 58a70f169e33446a1a666145faaa1602b8a2ad3d Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 28 Oct 2020 06:19:42 -0400 Subject: [PATCH 037/113] cris: do not use ram_size global Use the machine properties instead. Signed-off-by: Paolo Bonzini --- hw/cris/axis_dev88.c | 1 + hw/cris/boot.c | 2 +- hw/cris/boot.h | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/hw/cris/axis_dev88.c b/hw/cris/axis_dev88.c index dab7423c73..b0cb6d84af 100644 --- a/hw/cris/axis_dev88.c +++ b/hw/cris/axis_dev88.c @@ -333,6 +333,7 @@ void axisdev88_init(MachineState *machine) if (kernel_filename) { li.image_filename = kernel_filename; li.cmdline = kernel_cmdline; + li.ram_size = machine->ram_size; cris_load_image(cpu, &li); } else if (!qtest_enabled()) { fprintf(stderr, "Kernel image must be specified\n"); diff --git a/hw/cris/boot.c b/hw/cris/boot.c index aa8d2756d6..9fa09cfd83 100644 --- a/hw/cris/boot.c +++ b/hw/cris/boot.c @@ -81,7 +81,7 @@ void cris_load_image(CRISCPU *cpu, struct cris_load_info *li) if (image_size < 0) { /* Takes a kimage from the axis devboard SDK. */ image_size = load_image_targphys(li->image_filename, 0x40004000, - ram_size); + li->ram_size); li->entry = 0x40004000; } diff --git a/hw/cris/boot.h b/hw/cris/boot.h index 218854e5d1..9f1e0e340c 100644 --- a/hw/cris/boot.h +++ b/hw/cris/boot.h @@ -6,6 +6,7 @@ struct cris_load_info const char *image_filename; const char *cmdline; int image_size; + ram_addr_t ram_size; hwaddr entry; }; From bfdf22bc769a56d8e1fe7c72a28ef05c0a6d8596 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 28 Oct 2020 06:19:23 -0400 Subject: [PATCH 038/113] hppa: do not use ram_size global Use the machine properties instead. Cc: Richard Henderson Signed-off-by: Paolo Bonzini --- hw/hppa/machine.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/hw/hppa/machine.c b/hw/hppa/machine.c index 5e745d5ea9..7e41cb2462 100644 --- a/hw/hppa/machine.c +++ b/hw/hppa/machine.c @@ -97,7 +97,7 @@ static FWCfgState *create_fw_cfg(MachineState *ms) fw_cfg = fw_cfg_init_mem(FW_CFG_IO_BASE, FW_CFG_IO_BASE + 4); fw_cfg_add_i16(fw_cfg, FW_CFG_NB_CPUS, ms->smp.cpus); fw_cfg_add_i16(fw_cfg, FW_CFG_MAX_CPUS, HPPA_MAX_CPUS); - fw_cfg_add_i64(fw_cfg, FW_CFG_RAM_SIZE, ram_size); + fw_cfg_add_i64(fw_cfg, FW_CFG_RAM_SIZE, ms->ram_size); val = cpu_to_le64(MIN_SEABIOS_HPPA_VERSION); fw_cfg_add_file(fw_cfg, "/etc/firmware-min-version", @@ -288,7 +288,7 @@ static void machine_hppa_init(MachineState *machine) (1) Due to sign-extension problems and PDC, put the initrd no higher than 1G. (2) Reserve 64k for stack. */ - initrd_base = MIN(ram_size, 1 * GiB); + initrd_base = MIN(machine->ram_size, 1 * GiB); initrd_base = initrd_base - 64 * KiB; initrd_base = (initrd_base - initrd_size) & TARGET_PAGE_MASK; @@ -316,7 +316,7 @@ static void machine_hppa_init(MachineState *machine) * various parameters in registers. After firmware initialization, * firmware will start the Linux kernel with ramdisk and cmdline. */ - cpu[0]->env.gr[26] = ram_size; + cpu[0]->env.gr[26] = machine->ram_size; cpu[0]->env.gr[25] = kernel_entry; /* tell firmware how many SMP CPUs to present in inventory table */ @@ -342,11 +342,11 @@ static void hppa_machine_reset(MachineState *ms) } /* already initialized by machine_hppa_init()? */ - if (cpu[0]->env.gr[26] == ram_size) { + if (cpu[0]->env.gr[26] == ms->ram_size) { return; } - cpu[0]->env.gr[26] = ram_size; + cpu[0]->env.gr[26] = ms->ram_size; cpu[0]->env.gr[25] = 0; /* no firmware boot menu */ cpu[0]->env.gr[24] = 'c'; /* gr22/gr23 unused, no initrd while reboot. */ From 86378b29fa22a9854a084241bf51515e149133e4 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 28 Oct 2020 06:22:23 -0400 Subject: [PATCH 039/113] i386: do not use ram_size global Use the loader parameters instead. Signed-off-by: Paolo Bonzini --- hw/i386/fw_cfg.c | 2 +- hw/i386/vmport.c | 3 ++- hw/i386/xen/xen-hvm.c | 2 +- hw/intc/apic_common.c | 3 ++- hw/smbios/smbios.c | 8 ++++---- 5 files changed, 10 insertions(+), 8 deletions(-) diff --git a/hw/i386/fw_cfg.c b/hw/i386/fw_cfg.c index e06579490c..b87f0e5070 100644 --- a/hw/i386/fw_cfg.c +++ b/hw/i386/fw_cfg.c @@ -118,7 +118,7 @@ FWCfgState *fw_cfg_arch_create(MachineState *ms, * "etc/max-cpus" actually being apic_id_limit */ fw_cfg_add_i16(fw_cfg, FW_CFG_MAX_CPUS, apic_id_limit); - fw_cfg_add_i64(fw_cfg, FW_CFG_RAM_SIZE, (uint64_t)ram_size); + fw_cfg_add_i64(fw_cfg, FW_CFG_RAM_SIZE, ms->ram_size); #ifdef CONFIG_ACPI fw_cfg_add_bytes(fw_cfg, FW_CFG_ACPI_TABLES, acpi_tables, acpi_tables_len); diff --git a/hw/i386/vmport.c b/hw/i386/vmport.c index 20d605506b..490a57f52c 100644 --- a/hw/i386/vmport.c +++ b/hw/i386/vmport.c @@ -32,6 +32,7 @@ #include "hw/isa/isa.h" #include "hw/i386/vmport.h" #include "hw/qdev-properties.h" +#include "hw/boards.h" #include "sysemu/sysemu.h" #include "sysemu/hw_accel.h" #include "sysemu/qtest.h" @@ -188,7 +189,7 @@ static uint32_t vmport_cmd_ram_size(void *opaque, uint32_t addr) return -1; } cpu->env.regs[R_EBX] = 0x1177; - return ram_size; + return current_machine->ram_size; } static uint32_t vmport_cmd_get_hz(void *opaque, uint32_t addr) diff --git a/hw/i386/xen/xen-hvm.c b/hw/i386/xen/xen-hvm.c index 9519c33c09..096c46fef1 100644 --- a/hw/i386/xen/xen-hvm.c +++ b/hw/i386/xen/xen-hvm.c @@ -1493,7 +1493,7 @@ void xen_hvm_init_pc(PCMachineState *pcms, MemoryRegion **ram_memory) #else xen_map_cache_init(NULL, state); #endif - xen_ram_init(pcms, ram_size, ram_memory); + xen_ram_init(pcms, ms->ram_size, ram_memory); qemu_add_vm_change_state_handler(xen_hvm_change_state_handler, state); diff --git a/hw/intc/apic_common.c b/hw/intc/apic_common.c index 502e94effc..97dd96dffa 100644 --- a/hw/intc/apic_common.c +++ b/hw/intc/apic_common.c @@ -27,6 +27,7 @@ #include "hw/i386/apic.h" #include "hw/i386/apic_internal.h" #include "trace.h" +#include "hw/boards.h" #include "sysemu/hax.h" #include "sysemu/kvm.h" #include "hw/qdev-properties.h" @@ -297,7 +298,7 @@ static void apic_common_realize(DeviceState *dev, Error **errp) /* Note: We need at least 1M to map the VAPIC option ROM */ if (!vapic && s->vapic_control & VAPIC_ENABLE_MASK && - !hax_enabled() && ram_size >= 1024 * 1024) { + !hax_enabled() && current_machine->ram_size >= 1024 * 1024) { vapic = sysbus_create_simple("kvmvapic", -1, NULL); } s->vapic = vapic; diff --git a/hw/smbios/smbios.c b/hw/smbios/smbios.c index 6a3d39793b..f22c4f5b73 100644 --- a/hw/smbios/smbios.c +++ b/hw/smbios/smbios.c @@ -678,13 +678,13 @@ static void smbios_build_type_16_table(unsigned dimm_cnt) t->location = 0x01; /* Other */ t->use = 0x03; /* System memory */ t->error_correction = 0x06; /* Multi-bit ECC (for Microsoft, per SeaBIOS) */ - size_kb = QEMU_ALIGN_UP(ram_size, KiB) / KiB; + size_kb = QEMU_ALIGN_UP(current_machine->ram_size, KiB) / KiB; if (size_kb < MAX_T16_STD_SZ) { t->maximum_capacity = cpu_to_le32(size_kb); t->extended_maximum_capacity = cpu_to_le64(0); } else { t->maximum_capacity = cpu_to_le32(MAX_T16_STD_SZ); - t->extended_maximum_capacity = cpu_to_le64(ram_size); + t->extended_maximum_capacity = cpu_to_le64(current_machine->ram_size); } t->memory_error_information_handle = cpu_to_le16(0xFFFE); /* Not provided */ t->number_of_memory_devices = cpu_to_le16(dimm_cnt); @@ -911,9 +911,9 @@ void smbios_get_tables(MachineState *ms, #define MAX_DIMM_SZ (16 * GiB) #define GET_DIMM_SZ ((i < dimm_cnt - 1) ? MAX_DIMM_SZ \ - : ((ram_size - 1) % MAX_DIMM_SZ) + 1) + : ((current_machine->ram_size - 1) % MAX_DIMM_SZ) + 1) - dimm_cnt = QEMU_ALIGN_UP(ram_size, MAX_DIMM_SZ) / MAX_DIMM_SZ; + dimm_cnt = QEMU_ALIGN_UP(current_machine->ram_size, MAX_DIMM_SZ) / MAX_DIMM_SZ; smbios_build_type_16_table(dimm_cnt); From 5601d24164551b3473588837c4f92ef1bbde0415 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 28 Oct 2020 06:15:40 -0400 Subject: [PATCH 040/113] m68k: do not use ram_size global Use the machine properties instead. Cc: Laurent Vivier Reviewed-by: Thomas Huth Signed-off-by: Paolo Bonzini --- hw/m68k/mcf5206.c | 4 +++- hw/m68k/mcf5208.c | 3 ++- target/m68k/m68k-semi.c | 5 +++-- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/hw/m68k/mcf5206.c b/hw/m68k/mcf5206.c index 92a194dbc4..6d93d761a5 100644 --- a/hw/m68k/mcf5206.c +++ b/hw/m68k/mcf5206.c @@ -10,6 +10,7 @@ #include "qemu/error-report.h" #include "qemu/log.h" #include "cpu.h" +#include "hw/boards.h" #include "hw/irq.h" #include "hw/m68k/mcf.h" #include "qemu/timer.h" @@ -312,8 +313,9 @@ static uint64_t m5206_mbar_read(m5206_mbar_state *s, /* FIXME: currently hardcoded to 128Mb. */ { uint32_t mask = ~0; - while (mask > ram_size) + while (mask > current_machine->ram_size) { mask >>= 1; + } return mask & 0x0ffe0000; } case 0x5c: return 1; /* DRAM bank 1 empty. */ diff --git a/hw/m68k/mcf5208.c b/hw/m68k/mcf5208.c index 7c8ca5ddf6..2205145ecc 100644 --- a/hw/m68k/mcf5208.c +++ b/hw/m68k/mcf5208.c @@ -157,8 +157,9 @@ static uint64_t m5208_sys_read(void *opaque, hwaddr addr, { int n; for (n = 0; n < 32; n++) { - if (ram_size < (2u << n)) + if (current_machine->ram_size < (2u << n)) { break; + } } return (n - 1) | 0x40000000; } diff --git a/target/m68k/m68k-semi.c b/target/m68k/m68k-semi.c index 8e5fbfc8fa..27600e0cc0 100644 --- a/target/m68k/m68k-semi.c +++ b/target/m68k/m68k-semi.c @@ -26,6 +26,7 @@ #else #include "exec/gdbstub.h" #include "exec/softmmu-semi.h" +#include "hw/boards.h" #endif #include "qemu/log.h" @@ -455,8 +456,8 @@ void do_m68k_semihosting(CPUM68KState *env, int nr) * FIXME: This is wrong for boards where RAM does not start at * address zero. */ - env->dregs[1] = ram_size; - env->aregs[7] = ram_size; + env->dregs[1] = current_machine->ram_size; + env->aregs[7] = current_machine->ram_size; #endif return; default: From 89ee4a098c130cea0aca50090388cdca41f89dd9 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 28 Oct 2020 06:20:01 -0400 Subject: [PATCH 041/113] microblaze: do not use ram_size global Use the equivalent argument to the function instead. Signed-off-by: Paolo Bonzini --- hw/microblaze/boot.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/hw/microblaze/boot.c b/hw/microblaze/boot.c index 8ad3c27f2c..e1f56f83f9 100644 --- a/hw/microblaze/boot.c +++ b/hw/microblaze/boot.c @@ -170,7 +170,7 @@ void microblaze_load_kernel(MicroBlazeCPU *cpu, hwaddr ddr_base, /* Not an ELF image nor an u-boot image, try a RAW image. */ if (kernel_size < 0) { kernel_size = load_image_targphys(kernel_filename, ddr_base, - ram_size); + ramsize); boot_info.bootstrap_pc = ddr_base; high = (ddr_base + kernel_size + 3) & ~3; } @@ -185,11 +185,11 @@ void microblaze_load_kernel(MicroBlazeCPU *cpu, hwaddr ddr_base, initrd_size = load_ramdisk(initrd_filename, boot_info.initrd_start, - ram_size - initrd_offset); + ramsize - initrd_offset); if (initrd_size < 0) { initrd_size = load_image_targphys(initrd_filename, boot_info.initrd_start, - ram_size - initrd_offset); + ramsize - initrd_offset); } if (initrd_size < 0) { error_report("could not load initrd '%s'", @@ -206,7 +206,7 @@ void microblaze_load_kernel(MicroBlazeCPU *cpu, hwaddr ddr_base, } /* Provide a device-tree. */ boot_info.fdt = boot_info.cmdline + 4096; - microblaze_load_dtb(boot_info.fdt, ram_size, + microblaze_load_dtb(boot_info.fdt, ramsize, boot_info.initrd_start, boot_info.initrd_end, kernel_cmdline, From 74d6bf85257ee0344696e35de54fa24757a50b0f Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 28 Oct 2020 06:20:52 -0400 Subject: [PATCH 042/113] mips: do not use ram_size global MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use the machine properties or loader parameters instead. Cc: Philippe Mathieu-Daudé Signed-off-by: Paolo Bonzini --- hw/mips/fuloong2e.c | 4 ++-- hw/mips/malta.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/hw/mips/fuloong2e.c b/hw/mips/fuloong2e.c index 25b679011f..84a2132f85 100644 --- a/hw/mips/fuloong2e.c +++ b/hw/mips/fuloong2e.c @@ -134,14 +134,14 @@ static int64_t load_kernel(CPUMIPSState *env) initrd_size = get_image_size(loaderparams.initrd_filename); if (initrd_size > 0) { initrd_offset = ROUND_UP(kernel_high, INITRD_PAGE_SIZE); - if (initrd_offset + initrd_size > ram_size) { + if (initrd_offset + initrd_size > loaderparams.ram_size) { error_report("memory too small for initial ram disk '%s'", loaderparams.initrd_filename); exit(1); } initrd_size = load_image_targphys(loaderparams.initrd_filename, initrd_offset, - ram_size - initrd_offset); + loaderparams.ram_size - initrd_offset); } if (initrd_size == (target_ulong) -1) { error_report("could not load initial ram disk '%s'", diff --git a/hw/mips/malta.c b/hw/mips/malta.c index ef369945d1..467b21849e 100644 --- a/hw/mips/malta.c +++ b/hw/mips/malta.c @@ -1087,7 +1087,7 @@ static int64_t load_kernel(void) } initrd_size = load_image_targphys(loaderparams.initrd_filename, initrd_offset, - ram_size - initrd_offset); + loaderparams.ram_size - initrd_offset); } if (initrd_size == (target_ulong) -1) { error_report("could not load initial ram disk '%s'", From eb09df927274c7a873557588a1a23398af47fbb6 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 28 Oct 2020 06:21:08 -0400 Subject: [PATCH 043/113] moxie: do not use ram_size global MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use the loader parameters instead. Cc: Philippe Mathieu-Daudé Signed-off-by: Paolo Bonzini --- hw/moxie/moxiesim.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/moxie/moxiesim.c b/hw/moxie/moxiesim.c index d07d504c0d..f7b57fcae1 100644 --- a/hw/moxie/moxiesim.c +++ b/hw/moxie/moxiesim.c @@ -82,7 +82,7 @@ static void load_kernel(MoxieCPU *cpu, LoaderParams *loader_params) } initrd_size = load_image_targphys(loader_params->initrd_filename, initrd_offset, - ram_size); + loader_params->ram_size); } if (initrd_size == (target_ulong)-1) { error_report("could not load initial ram disk '%s'", From 541693a4195508a077fc10e5803d0a5b4f76838a Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 28 Oct 2020 06:25:06 -0400 Subject: [PATCH 044/113] nios2: do not use ram_size global Use the equivalent argument to the function instead. Signed-off-by: Paolo Bonzini --- hw/nios2/boot.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/hw/nios2/boot.c b/hw/nios2/boot.c index 1df3b66c29..3cb864914b 100644 --- a/hw/nios2/boot.c +++ b/hw/nios2/boot.c @@ -181,7 +181,7 @@ void nios2_load_kernel(Nios2CPU *cpu, hwaddr ddr_base, /* Not an ELF image nor an u-boot image, try a RAW image. */ if (kernel_size < 0) { kernel_size = load_image_targphys(kernel_filename, ddr_base, - ram_size); + ramsize); boot_info.bootstrap_pc = ddr_base; high = ddr_base + kernel_size; } @@ -198,11 +198,11 @@ void nios2_load_kernel(Nios2CPU *cpu, hwaddr ddr_base, initrd_size = load_ramdisk(initrd_filename, boot_info.initrd_start, - ram_size - initrd_offset); + ramsize - initrd_offset); if (initrd_size < 0) { initrd_size = load_image_targphys(initrd_filename, boot_info.initrd_start, - ram_size - initrd_offset); + ramsize - initrd_offset); } if (initrd_size < 0) { error_report("could not load initrd '%s'", @@ -216,7 +216,7 @@ void nios2_load_kernel(Nios2CPU *cpu, hwaddr ddr_base, /* Device tree must be placed right after initrd (if available) */ boot_info.fdt = high; - fdt_size = nios2_load_dtb(boot_info, ram_size, kernel_cmdline, + fdt_size = nios2_load_dtb(boot_info, ramsize, kernel_cmdline, /* Preference a -dtb argument */ dtb_arg ? dtb_arg : filename); high += fdt_size; From ead2b283ad7b828252011c35a9407204010138af Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 28 Oct 2020 06:17:31 -0400 Subject: [PATCH 045/113] ppc: do not use ram_size global Use the machine properties instead. Cc: qemu-ppc@nongnu.org Signed-off-by: Paolo Bonzini --- hw/ppc/prep.c | 2 +- hw/ppc/spapr_vio.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/hw/ppc/prep.c b/hw/ppc/prep.c index c6b9d1ddcb..7e72f6e4a9 100644 --- a/hw/ppc/prep.c +++ b/hw/ppc/prep.c @@ -420,7 +420,7 @@ static void ibm_40p_init(MachineState *machine) /* Prepare firmware configuration for Open Hack'Ware */ if (m48t59) { - PPC_NVRAM_set_params(m48t59, NVRAM_SIZE, "PREP", ram_size, + PPC_NVRAM_set_params(m48t59, NVRAM_SIZE, "PREP", machine->ram_size, boot_device, kernel_base, kernel_size, machine->kernel_cmdline, diff --git a/hw/ppc/spapr_vio.c b/hw/ppc/spapr_vio.c index 5d6c56473f..3cc9421526 100644 --- a/hw/ppc/spapr_vio.c +++ b/hw/ppc/spapr_vio.c @@ -525,10 +525,10 @@ static void spapr_vio_busdev_realize(DeviceState *qdev, Error **errp) uint32_t liobn = SPAPR_VIO_LIOBN(dev->reg); memory_region_init(&dev->mrroot, OBJECT(dev), "iommu-spapr-root", - ram_size); + MACHINE(spapr)->ram_size); memory_region_init_alias(&dev->mrbypass, OBJECT(dev), "iommu-spapr-bypass", get_system_memory(), - 0, ram_size); + 0, MACHINE(spapr)->ram_size); memory_region_add_subregion_overlap(&dev->mrroot, 0, &dev->mrbypass, 1); address_space_init(&dev->as, &dev->mrroot, qdev->id); From 82e69054656f86d00b263437ad04395a5f834248 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 28 Oct 2020 06:16:22 -0400 Subject: [PATCH 046/113] riscv: do not use ram_size global Use the machine properties instead. Cc: Alistair Francis Signed-off-by: Paolo Bonzini --- hw/riscv/boot.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/hw/riscv/boot.c b/hw/riscv/boot.c index 9b3fe3fb1e..70a9bf8f5d 100644 --- a/hw/riscv/boot.c +++ b/hw/riscv/boot.c @@ -120,7 +120,8 @@ target_ulong riscv_load_firmware(const char *firmware_filename, } firmware_size = load_image_targphys_as(firmware_filename, - firmware_load_addr, ram_size, NULL); + firmware_load_addr, + current_machine->ram_size, NULL); if (firmware_size > 0) { return firmware_load_addr + firmware_size; @@ -148,7 +149,7 @@ target_ulong riscv_load_kernel(const char *kernel_filename, } if (load_image_targphys_as(kernel_filename, kernel_start_addr, - ram_size, NULL) > 0) { + current_machine->ram_size, NULL) > 0) { return kernel_start_addr; } From 382a04afa075927d843f11e9fb8c450a084bbfa8 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 28 Oct 2020 06:17:07 -0400 Subject: [PATCH 047/113] s390x: do not use ram_size global Use the machine properties instead. Cc: Cornelia Huck Signed-off-by: Paolo Bonzini --- hw/s390x/ipl.c | 10 ++++++---- hw/s390x/s390-skeys.c | 6 ++++-- hw/s390x/s390-virtio-ccw.c | 4 +++- target/s390x/excp_helper.c | 3 ++- target/s390x/mem_helper.c | 10 +++++++--- target/s390x/mmu_helper.c | 4 +++- 6 files changed, 25 insertions(+), 12 deletions(-) diff --git a/hw/s390x/ipl.c b/hw/s390x/ipl.c index 61e8c967d3..bddbaffac6 100644 --- a/hw/s390x/ipl.c +++ b/hw/s390x/ipl.c @@ -112,6 +112,7 @@ static uint64_t bios_translate_addr(void *opaque, uint64_t srcaddr) static void s390_ipl_realize(DeviceState *dev, Error **errp) { + MachineState *ms = MACHINE(qdev_get_machine()); S390IPLState *ipl = S390_IPL(dev); uint32_t *ipl_psw; uint64_t pentry; @@ -126,7 +127,7 @@ static void s390_ipl_realize(DeviceState *dev, Error **errp) * even if an external kernel has been defined. */ if (!ipl->kernel || ipl->enforce_bios) { - uint64_t fwbase = (MIN(ram_size, 0x80000000U) - 0x200000) & ~0xffffUL; + uint64_t fwbase = (MIN(ms->ram_size, 0x80000000U) - 0x200000) & ~0xffffUL; bios_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, ipl->firmware); if (bios_filename == NULL) { @@ -163,7 +164,7 @@ static void s390_ipl_realize(DeviceState *dev, Error **errp) &pentry, NULL, NULL, NULL, 1, EM_S390, 0, 0); if (kernel_size < 0) { - kernel_size = load_image_targphys(ipl->kernel, 0, ram_size); + kernel_size = load_image_targphys(ipl->kernel, 0, ms->ram_size); if (kernel_size < 0) { error_setg(errp, "could not load kernel '%s'", ipl->kernel); return; @@ -210,7 +211,7 @@ static void s390_ipl_realize(DeviceState *dev, Error **errp) initrd_offset += 0x100000; } initrd_size = load_image_targphys(ipl->initrd, initrd_offset, - ram_size - initrd_offset); + ms->ram_size - initrd_offset); if (initrd_size == -1) { error_setg(errp, "could not load initrd '%s'", ipl->initrd); return; @@ -448,6 +449,7 @@ int s390_ipl_set_loadparm(uint8_t *loadparm) static int load_netboot_image(Error **errp) { + MachineState *ms = MACHINE(qdev_get_machine()); S390IPLState *ipl = get_ipl_device(); char *netboot_filename; MemoryRegion *sysmem = get_system_memory(); @@ -480,7 +482,7 @@ static int load_netboot_image(Error **errp) false); if (img_size < 0) { - img_size = load_image_size(netboot_filename, ram_ptr, ram_size); + img_size = load_image_size(netboot_filename, ram_ptr, ms->ram_size); ipl->start_addr = KERN_IMAGE_START; } diff --git a/hw/s390x/s390-skeys.c b/hw/s390x/s390-skeys.c index 5cc559fe4c..9a8d60d1d9 100644 --- a/hw/s390x/s390-skeys.c +++ b/hw/s390x/s390-skeys.c @@ -109,7 +109,8 @@ void qmp_dump_skeys(const char *filename, Error **errp) { S390SKeysState *ss = s390_get_skeys_device(); S390SKeysClass *skeyclass = S390_SKEYS_GET_CLASS(ss); - const uint64_t total_count = ram_size / TARGET_PAGE_SIZE; + MachineState *ms = MACHINE(qdev_get_machine()); + const uint64_t total_count = ms->ram_size / TARGET_PAGE_SIZE; uint64_t handled_count = 0, cur_count; Error *lerr = NULL; vaddr cur_gfn = 0; @@ -256,7 +257,8 @@ static void s390_storage_keys_save(QEMUFile *f, void *opaque) { S390SKeysState *ss = S390_SKEYS(opaque); S390SKeysClass *skeyclass = S390_SKEYS_GET_CLASS(ss); - uint64_t pages_left = ram_size / TARGET_PAGE_SIZE; + MachineState *ms = MACHINE(qdev_get_machine()); + uint64_t pages_left = ms->ram_size / TARGET_PAGE_SIZE; uint64_t read_count, eos = S390_SKEYS_SAVE_FLAG_EOS; vaddr cur_gfn = 0; int error = 0; diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c index a6324d94f1..a2d9a79c84 100644 --- a/hw/s390x/s390-virtio-ccw.c +++ b/hw/s390x/s390-virtio-ccw.c @@ -17,6 +17,7 @@ #include "hw/boards.h" #include "exec/address-spaces.h" #include "exec/ram_addr.h" +#include "hw/boards.h" #include "hw/s390x/s390-virtio-hcall.h" #include "hw/s390x/sclp.h" #include "hw/s390x/s390_flic.h" @@ -142,8 +143,9 @@ static int virtio_ccw_hcall_notify(const uint64_t *args) static int virtio_ccw_hcall_early_printk(const uint64_t *args) { uint64_t mem = args[0]; + MachineState *ms = MACHINE(qdev_get_machine()); - if (mem < ram_size) { + if (mem < ms->ram_size) { /* Early printk */ return 0; } diff --git a/target/s390x/excp_helper.c b/target/s390x/excp_helper.c index 0adfbbda27..9cf66d3690 100644 --- a/target/s390x/excp_helper.c +++ b/target/s390x/excp_helper.c @@ -156,9 +156,10 @@ bool s390_cpu_tlb_fill(CPUState *cs, vaddr address, int size, !address_space_access_valid(&address_space_memory, raddr, TARGET_PAGE_SIZE, access_type, MEMTXATTRS_UNSPECIFIED)) { + MachineState *ms = MACHINE(qdev_get_machine()); qemu_log_mask(CPU_LOG_MMU, "%s: raddr %" PRIx64 " > ram_size %" PRIx64 "\n", - __func__, (uint64_t)raddr, (uint64_t)ram_size); + __func__, (uint64_t)raddr, (uint64_t)ms->ram_size); excp = PGM_ADDRESSING; tec = 0; /* unused */ } diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c index bd25eed3e8..0108611cc9 100644 --- a/target/s390x/mem_helper.c +++ b/target/s390x/mem_helper.c @@ -31,6 +31,7 @@ #if !defined(CONFIG_USER_ONLY) #include "hw/s390x/storage-keys.h" +#include "hw/boards.h" #endif /*****************************************************************************/ @@ -2075,12 +2076,13 @@ uint32_t HELPER(tprot)(CPUS390XState *env, uint64_t a1, uint64_t a2) /* insert storage key extended */ uint64_t HELPER(iske)(CPUS390XState *env, uint64_t r2) { + MachineState *ms = MACHINE(qdev_get_machine()); static S390SKeysState *ss; static S390SKeysClass *skeyclass; uint64_t addr = wrap_address(env, r2); uint8_t key; - if (addr > ram_size) { + if (addr > ms->ram_size) { return 0; } @@ -2098,12 +2100,13 @@ uint64_t HELPER(iske)(CPUS390XState *env, uint64_t r2) /* set storage key extended */ void HELPER(sske)(CPUS390XState *env, uint64_t r1, uint64_t r2) { + MachineState *ms = MACHINE(qdev_get_machine()); static S390SKeysState *ss; static S390SKeysClass *skeyclass; uint64_t addr = wrap_address(env, r2); uint8_t key; - if (addr > ram_size) { + if (addr > ms->ram_size) { return; } @@ -2124,11 +2127,12 @@ void HELPER(sske)(CPUS390XState *env, uint64_t r1, uint64_t r2) /* reset reference bit extended */ uint32_t HELPER(rrbe)(CPUS390XState *env, uint64_t r2) { + MachineState *ms = MACHINE(qdev_get_machine()); static S390SKeysState *ss; static S390SKeysClass *skeyclass; uint8_t re, key; - if (r2 > ram_size) { + if (r2 > ms->ram_size) { return 0; } diff --git a/target/s390x/mmu_helper.c b/target/s390x/mmu_helper.c index 7d9f3059cd..d492b23a17 100644 --- a/target/s390x/mmu_helper.c +++ b/target/s390x/mmu_helper.c @@ -27,6 +27,7 @@ #include "trace.h" #include "hw/hw.h" #include "hw/s390x/storage-keys.h" +#include "hw/boards.h" /* Fetch/store bits in the translation exception code: */ #define FS_READ 0x800 @@ -292,10 +293,11 @@ static void mmu_handle_skey(target_ulong addr, int rw, int *flags) { static S390SKeysClass *skeyclass; static S390SKeysState *ss; + MachineState *ms = MACHINE(qdev_get_machine()); uint8_t key; int rc; - if (unlikely(addr >= ram_size)) { + if (unlikely(addr >= ms->ram_size)) { return; } From 48c0b1e45f364e75a450ddd0ebbbf84b28197d6e Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 28 Oct 2020 06:14:33 -0400 Subject: [PATCH 048/113] sparc64: do not use ram_size global Use the machine properties instead. Cc: Mark Cave-Ayland Signed-off-by: Paolo Bonzini --- hw/sparc64/sparc64.c | 3 ++- hw/sparc64/sun4u.c | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/hw/sparc64/sparc64.c b/hw/sparc64/sparc64.c index 100b2fab17..e3f9219a10 100644 --- a/hw/sparc64/sparc64.c +++ b/hw/sparc64/sparc64.c @@ -25,6 +25,7 @@ #include "qemu/osdep.h" #include "cpu.h" +#include "hw/boards.h" #include "hw/char/serial.h" #include "hw/sparc/sparc64.h" #include "qemu/timer.h" @@ -180,7 +181,7 @@ static void main_cpu_reset(void *opaque) cpu_timer_reset(env->hstick); env->gregs[1] = 0; /* Memory start */ - env->gregs[2] = ram_size; /* Memory size */ + env->gregs[2] = current_machine->ram_size; /* Memory size */ env->gregs[3] = 0; /* Machine description XXX */ if (nr_resets++ == 0) { /* Power on reset */ diff --git a/hw/sparc64/sun4u.c b/hw/sparc64/sun4u.c index 22896b4c62..8bee7dd2f4 100644 --- a/hw/sparc64/sun4u.c +++ b/hw/sparc64/sun4u.c @@ -690,7 +690,7 @@ static void sun4uv_init(MemoryRegion *address_space_mem, initrd_addr = 0; kernel_size = sun4u_load_kernel(machine->kernel_filename, machine->initrd_filename, - ram_size, &initrd_size, &initrd_addr, + machine->ram_size, &initrd_size, &initrd_addr, &kernel_addr, &kernel_entry); sun4u_NVRAM_set_params(nvram, NVRAM_SIZE, "Sun4u", machine->ram_size, @@ -713,7 +713,7 @@ static void sun4uv_init(MemoryRegion *address_space_mem, fw_cfg = FW_CFG(dev); fw_cfg_add_i16(fw_cfg, FW_CFG_NB_CPUS, (uint16_t)machine->smp.cpus); fw_cfg_add_i16(fw_cfg, FW_CFG_MAX_CPUS, (uint16_t)machine->smp.max_cpus); - fw_cfg_add_i64(fw_cfg, FW_CFG_RAM_SIZE, (uint64_t)ram_size); + fw_cfg_add_i64(fw_cfg, FW_CFG_RAM_SIZE, (uint64_t)machine->ram_size); fw_cfg_add_i16(fw_cfg, FW_CFG_MACHINE_ID, hwdef->machine_id); fw_cfg_add_i64(fw_cfg, FW_CFG_KERNEL_ADDR, kernel_entry); fw_cfg_add_i64(fw_cfg, FW_CFG_KERNEL_SIZE, kernel_size); From b326b6ea7998912d0bb0565ffef34efdfe9016dc Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 28 Oct 2020 06:24:22 -0400 Subject: [PATCH 049/113] make ram_size local to vl.c Use the machine properties for the leftovers too. Signed-off-by: Paolo Bonzini --- hw/core/generic-loader.c | 3 ++- hw/core/numa.c | 10 +++++----- hw/virtio/virtio-balloon.c | 3 ++- include/exec/cpu-common.h | 2 -- monitor/qmp-cmds.c | 3 ++- softmmu/vl.c | 2 +- 6 files changed, 12 insertions(+), 11 deletions(-) diff --git a/hw/core/generic-loader.c b/hw/core/generic-loader.c index a242c076f6..2b2a7b5e9a 100644 --- a/hw/core/generic-loader.c +++ b/hw/core/generic-loader.c @@ -35,6 +35,7 @@ #include "hw/sysbus.h" #include "sysemu/dma.h" #include "sysemu/reset.h" +#include "hw/boards.h" #include "hw/loader.h" #include "hw/qdev-properties.h" #include "qapi/error.h" @@ -154,7 +155,7 @@ static void generic_loader_realize(DeviceState *dev, Error **errp) if (size < 0 || s->force_raw) { /* Default to the maximum size being the machine's ram size */ - size = load_image_targphys_as(s->file, s->addr, ram_size, as); + size = load_image_targphys_as(s->file, s->addr, current_machine->ram_size, as); } else { s->addr = entry; } diff --git a/hw/core/numa.c b/hw/core/numa.c index 7c4dd4e68e..68cee65f61 100644 --- a/hw/core/numa.c +++ b/hw/core/numa.c @@ -642,7 +642,7 @@ void numa_complete_configuration(MachineState *ms) /* * If memory hotplug is enabled (slot > 0) or memory devices are enabled - * (ms->maxram_size > ram_size) but without '-numa' options explicitly on + * (ms->maxram_size > ms->ram_size) but without '-numa' options explicitly on * CLI, guests will break. * * Windows: won't enable memory hotplug without SRAT table at all @@ -663,7 +663,7 @@ void numa_complete_configuration(MachineState *ms) mc->auto_enable_numa)) { NumaNodeOptions node = { }; parse_numa_node(ms, &node, &error_abort); - numa_info[0].node_mem = ram_size; + numa_info[0].node_mem = ms->ram_size; } assert(max_numa_nodeid <= MAX_NODES); @@ -687,10 +687,10 @@ void numa_complete_configuration(MachineState *ms) for (i = 0; i < ms->numa_state->num_nodes; i++) { numa_total += numa_info[i].node_mem; } - if (numa_total != ram_size) { + if (numa_total != ms->ram_size) { error_report("total memory for NUMA nodes (0x%" PRIx64 ")" " should equal RAM size (0x" RAM_ADDR_FMT ")", - numa_total, ram_size); + numa_total, ms->ram_size); exit(1); } @@ -702,7 +702,7 @@ void numa_complete_configuration(MachineState *ms) } ms->ram = g_new(MemoryRegion, 1); memory_region_init(ms->ram, OBJECT(ms), mc->default_ram_id, - ram_size); + ms->ram_size); numa_init_memdev_container(ms, ms->ram); } /* QEMU needs at least all unique node pair distances to build diff --git a/hw/virtio/virtio-balloon.c b/hw/virtio/virtio-balloon.c index b22b5beda3..e83017c02d 100644 --- a/hw/virtio/virtio-balloon.c +++ b/hw/virtio/virtio-balloon.c @@ -20,6 +20,7 @@ #include "hw/virtio/virtio.h" #include "hw/mem/pc-dimm.h" #include "hw/qdev-properties.h" +#include "hw/boards.h" #include "sysemu/balloon.h" #include "hw/virtio/virtio-balloon.h" #include "exec/address-spaces.h" @@ -748,7 +749,7 @@ static int build_dimm_list(Object *obj, void *opaque) static ram_addr_t get_current_ram_size(void) { GSList *list = NULL, *item; - ram_addr_t size = ram_size; + ram_addr_t size = current_machine->ram_size; build_dimm_list(qdev_get_machine(), &list); for (item = list; item; item = g_slist_next(item)) { diff --git a/include/exec/cpu-common.h b/include/exec/cpu-common.h index 19805ed6db..bd5e15dd7d 100644 --- a/include/exec/cpu-common.h +++ b/include/exec/cpu-common.h @@ -42,8 +42,6 @@ typedef uintptr_t ram_addr_t; # define RAM_ADDR_FMT "%" PRIxPTR #endif -extern ram_addr_t ram_size; - /* memory API */ void qemu_ram_remap(ram_addr_t addr, ram_addr_t length); diff --git a/monitor/qmp-cmds.c b/monitor/qmp-cmds.c index a08143b323..6299c0c8c7 100644 --- a/monitor/qmp-cmds.c +++ b/monitor/qmp-cmds.c @@ -392,8 +392,9 @@ ACPIOSTInfoList *qmp_query_acpi_ospm_status(Error **errp) MemoryInfo *qmp_query_memory_size_summary(Error **errp) { MemoryInfo *mem_info = g_malloc0(sizeof(MemoryInfo)); + MachineState *ms = MACHINE(qdev_get_machine()); - mem_info->base_memory = ram_size; + mem_info->base_memory = ms->ram_size; mem_info->plugged_memory = get_plugged_memory_size(); mem_info->has_plugged_memory = diff --git a/softmmu/vl.c b/softmmu/vl.c index 2b82e6f5cd..3819a4abf2 100644 --- a/softmmu/vl.c +++ b/softmmu/vl.c @@ -122,7 +122,7 @@ static int data_dir_idx; enum vga_retrace_method vga_retrace_method = VGA_RETRACE_DUMB; int display_opengl; const char* keyboard_layout = NULL; -ram_addr_t ram_size; +static ram_addr_t ram_size; bool enable_mlock = false; bool enable_cpu_pm = false; int nb_nics; From 29daa894b6c31eae074dcb59a98ff3a309688754 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Fri, 20 Nov 2020 17:19:33 +0100 Subject: [PATCH 050/113] hw/char/serial: Clean up unnecessary code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since commit 5ec3a23e6c8 ("serial: convert PIO to new memory api read/write") we don't need to worry about accesses bigger than 8-bit. Use the extract()/deposit() functions to access the correct part of the 16-bit 'divider' register. Reported-by: Jonathan D. Belanger Buglink: https://bugs.launchpad.net/qemu/+bug/1904331 Signed-off-by: Philippe Mathieu-Daudé Message-Id: <20201120161933.2514089-1-f4bug@amsat.org> Signed-off-by: Paolo Bonzini --- hw/char/serial.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/hw/char/serial.c b/hw/char/serial.c index 97f71879ff..62c627f486 100644 --- a/hw/char/serial.c +++ b/hw/char/serial.c @@ -24,6 +24,7 @@ */ #include "qemu/osdep.h" +#include "qemu/bitops.h" #include "hw/char/serial.h" #include "hw/irq.h" #include "migration/vmstate.h" @@ -338,11 +339,7 @@ static void serial_ioport_write(void *opaque, hwaddr addr, uint64_t val, default: case 0: if (s->lcr & UART_LCR_DLAB) { - if (size == 1) { - s->divider = (s->divider & 0xff00) | val; - } else { - s->divider = val; - } + s->divider = deposit32(s->divider, 8 * addr, 8, val); serial_update_parameters(s); } else { s->thr = (uint8_t) val; @@ -364,7 +361,7 @@ static void serial_ioport_write(void *opaque, hwaddr addr, uint64_t val, break; case 1: if (s->lcr & UART_LCR_DLAB) { - s->divider = (s->divider & 0x00ff) | (val << 8); + s->divider = deposit32(s->divider, 8 * addr, 8, val); serial_update_parameters(s); } else { uint8_t changed = (s->ier ^ val) & 0x0f; @@ -478,7 +475,7 @@ static uint64_t serial_ioport_read(void *opaque, hwaddr addr, unsigned size) default: case 0: if (s->lcr & UART_LCR_DLAB) { - ret = s->divider & 0xff; + ret = extract16(s->divider, 8 * addr, 8); } else { if(s->fcr & UART_FCR_FE) { ret = fifo8_is_empty(&s->recv_fifo) ? @@ -502,7 +499,7 @@ static uint64_t serial_ioport_read(void *opaque, hwaddr addr, unsigned size) break; case 1: if (s->lcr & UART_LCR_DLAB) { - ret = (s->divider >> 8) & 0xff; + ret = extract16(s->divider, 8 * addr, 8); } else { ret = s->ier; } From 991c180d740c04c2f8c08c8783ad868fc832589f Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Fri, 13 Nov 2020 03:10:52 -0500 Subject: [PATCH 051/113] treewide: do not use short-form boolean options They are going to be deprecated, avoid warnings on stdout while the tests run. Signed-off-by: Paolo Bonzini --- docs/specs/tpm.rst | 2 +- python/qemu/machine.py | 2 +- qemu-options.hx | 32 ++++++++++++++-------------- tests/qtest/bios-tables-test.c | 4 ++-- tests/qtest/pflash-cfi02-test.c | 4 ++-- tests/qtest/test-filter-redirector.c | 8 +++---- tests/qtest/vhost-user-test.c | 8 +++---- tests/test-char.c | 8 +++---- 8 files changed, 34 insertions(+), 34 deletions(-) diff --git a/docs/specs/tpm.rst b/docs/specs/tpm.rst index 5e9aef4db3..3be190343a 100644 --- a/docs/specs/tpm.rst +++ b/docs/specs/tpm.rst @@ -343,7 +343,7 @@ In case an Arm virt machine is emulated, use the following command line: -device tpm-tis-device,tpmdev=tpm0 \ -device virtio-blk-pci,drive=drv0 \ -drive format=qcow2,file=hda.qcow2,if=none,id=drv0 \ - -drive if=pflash,format=raw,file=flash0.img,readonly \ + -drive if=pflash,format=raw,file=flash0.img,readonly=on \ -drive if=pflash,format=raw,file=flash1.img In case SeaBIOS is used as firmware, it should show the TPM menu item diff --git a/python/qemu/machine.py b/python/qemu/machine.py index 64d966aeeb..7a40f4604b 100644 --- a/python/qemu/machine.py +++ b/python/qemu/machine.py @@ -292,7 +292,7 @@ def _base_args(self) -> List[str]: for _ in range(self._console_index): args.extend(['-serial', 'null']) if self._console_set: - chardev = ('socket,id=console,path=%s,server,nowait' % + chardev = ('socket,id=console,path=%s,server=on,wait=off' % self._console_address) args.extend(['-chardev', chardev]) if self._console_device_type is None: diff --git a/qemu-options.hx b/qemu-options.hx index 104632ea34..e60ad42976 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -1406,25 +1406,25 @@ ERST DEF("fsdev", HAS_ARG, QEMU_OPTION_fsdev, "-fsdev local,id=id,path=path,security_model=mapped-xattr|mapped-file|passthrough|none\n" - " [,writeout=immediate][,readonly][,fmode=fmode][,dmode=dmode]\n" + " [,writeout=immediate][,readonly=on][,fmode=fmode][,dmode=dmode]\n" " [[,throttling.bps-total=b]|[[,throttling.bps-read=r][,throttling.bps-write=w]]]\n" " [[,throttling.iops-total=i]|[[,throttling.iops-read=r][,throttling.iops-write=w]]]\n" " [[,throttling.bps-total-max=bm]|[[,throttling.bps-read-max=rm][,throttling.bps-write-max=wm]]]\n" " [[,throttling.iops-total-max=im]|[[,throttling.iops-read-max=irm][,throttling.iops-write-max=iwm]]]\n" " [[,throttling.iops-size=is]]\n" - "-fsdev proxy,id=id,socket=socket[,writeout=immediate][,readonly]\n" - "-fsdev proxy,id=id,sock_fd=sock_fd[,writeout=immediate][,readonly]\n" + "-fsdev proxy,id=id,socket=socket[,writeout=immediate][,readonly=on]\n" + "-fsdev proxy,id=id,sock_fd=sock_fd[,writeout=immediate][,readonly=on]\n" "-fsdev synth,id=id\n", QEMU_ARCH_ALL) SRST -``-fsdev local,id=id,path=path,security_model=security_model [,writeout=writeout][,readonly][,fmode=fmode][,dmode=dmode] [,throttling.option=value[,throttling.option=value[,...]]]`` +``-fsdev local,id=id,path=path,security_model=security_model [,writeout=writeout][,readonly=on][,fmode=fmode][,dmode=dmode] [,throttling.option=value[,throttling.option=value[,...]]]`` \ -``-fsdev proxy,id=id,socket=socket[,writeout=writeout][,readonly]`` +``-fsdev proxy,id=id,socket=socket[,writeout=writeout][,readonly=on]`` \ -``-fsdev proxy,id=id,sock_fd=sock_fd[,writeout=writeout][,readonly]`` +``-fsdev proxy,id=id,sock_fd=sock_fd[,writeout=writeout][,readonly=on]`` \ -``-fsdev synth,id=id[,readonly]`` +``-fsdev synth,id=id[,readonly=on]`` Define a new file system device. Valid options are: ``local`` @@ -1467,7 +1467,7 @@ SRST guest only when the data has been reported as written by the storage subsystem. - ``readonly`` + ``readonly=on`` Enables exporting 9p share as a readonly mount for guests. By default read-write access is given. @@ -1532,18 +1532,18 @@ ERST DEF("virtfs", HAS_ARG, QEMU_OPTION_virtfs, "-virtfs local,path=path,mount_tag=tag,security_model=mapped-xattr|mapped-file|passthrough|none\n" - " [,id=id][,writeout=immediate][,readonly][,fmode=fmode][,dmode=dmode][,multidevs=remap|forbid|warn]\n" - "-virtfs proxy,mount_tag=tag,socket=socket[,id=id][,writeout=immediate][,readonly]\n" - "-virtfs proxy,mount_tag=tag,sock_fd=sock_fd[,id=id][,writeout=immediate][,readonly]\n" - "-virtfs synth,mount_tag=tag[,id=id][,readonly]\n", + " [,id=id][,writeout=immediate][,readonly=on][,fmode=fmode][,dmode=dmode][,multidevs=remap|forbid|warn]\n" + "-virtfs proxy,mount_tag=tag,socket=socket[,id=id][,writeout=immediate][,readonly=on]\n" + "-virtfs proxy,mount_tag=tag,sock_fd=sock_fd[,id=id][,writeout=immediate][,readonly=on]\n" + "-virtfs synth,mount_tag=tag[,id=id][,readonly=on]\n", QEMU_ARCH_ALL) SRST -``-virtfs local,path=path,mount_tag=mount_tag ,security_model=security_model[,writeout=writeout][,readonly] [,fmode=fmode][,dmode=dmode][,multidevs=multidevs]`` +``-virtfs local,path=path,mount_tag=mount_tag ,security_model=security_model[,writeout=writeout][,readonly=on] [,fmode=fmode][,dmode=dmode][,multidevs=multidevs]`` \ -``-virtfs proxy,socket=socket,mount_tag=mount_tag [,writeout=writeout][,readonly]`` +``-virtfs proxy,socket=socket,mount_tag=mount_tag [,writeout=writeout][,readonly=on]`` \ -``-virtfs proxy,sock_fd=sock_fd,mount_tag=mount_tag [,writeout=writeout][,readonly]`` +``-virtfs proxy,sock_fd=sock_fd,mount_tag=mount_tag [,writeout=writeout][,readonly=on]`` \ ``-virtfs synth,mount_tag=mount_tag`` Define a new virtual filesystem device and expose it to the guest using @@ -1598,7 +1598,7 @@ SRST guest only when the data has been reported as written by the storage subsystem. - ``readonly`` + ``readonly=on`` Enables exporting 9p share as a readonly mount for guests. By default read-write access is given. diff --git a/tests/qtest/bios-tables-test.c b/tests/qtest/bios-tables-test.c index f2f79dd6a4..4e026f90d0 100644 --- a/tests/qtest/bios-tables-test.c +++ b/tests/qtest/bios-tables-test.c @@ -674,14 +674,14 @@ static void test_acpi_one(const char *params, test_data *data) if (data->cd) { args = g_strdup_printf("-machine %s %s -accel tcg " "-nodefaults -nographic " - "-drive if=pflash,format=raw,file=%s,readonly " + "-drive if=pflash,format=raw,file=%s,readonly=on " "-drive if=pflash,format=raw,file=%s,snapshot=on -cdrom %s %s", data->machine, data->tcg_only ? "" : "-accel kvm", data->uefi_fl1, data->uefi_fl2, data->cd, params ? params : ""); } else { args = g_strdup_printf("-machine %s %s -accel tcg " "-nodefaults -nographic " - "-drive if=pflash,format=raw,file=%s,readonly " + "-drive if=pflash,format=raw,file=%s,readonly=on " "-drive if=pflash,format=raw,file=%s,snapshot=on %s", data->machine, data->tcg_only ? "" : "-accel kvm", data->uefi_fl1, data->uefi_fl2, params ? params : ""); diff --git a/tests/qtest/pflash-cfi02-test.c b/tests/qtest/pflash-cfi02-test.c index afb702b565..60db81a3a2 100644 --- a/tests/qtest/pflash-cfi02-test.c +++ b/tests/qtest/pflash-cfi02-test.c @@ -261,7 +261,7 @@ static void test_geometry(const void *opaque) const FlashConfig *config = opaque; QTestState *qtest; qtest = qtest_initf("-M musicpal" - " -drive if=pflash,file=%s,format=raw,copy-on-read" + " -drive if=pflash,file=%s,format=raw,copy-on-read=on" /* Device geometry properties. */ " -global driver=cfi.pflash02," "property=num-blocks0,value=%d" @@ -581,7 +581,7 @@ static void test_cfi_in_autoselect(const void *opaque) const FlashConfig *config = opaque; QTestState *qtest; qtest = qtest_initf("-M musicpal" - " -drive if=pflash,file=%s,format=raw,copy-on-read", + " -drive if=pflash,file=%s,format=raw,copy-on-read=on", image_path); FlashConfig explicit_config = expand_config_defaults(config); explicit_config.qtest = qtest; diff --git a/tests/qtest/test-filter-redirector.c b/tests/qtest/test-filter-redirector.c index 829db8c2ea..4269b2cdd9 100644 --- a/tests/qtest/test-filter-redirector.c +++ b/tests/qtest/test-filter-redirector.c @@ -95,8 +95,8 @@ static void test_redirector_tx(void) qts = qtest_initf( "-netdev socket,id=qtest-bn0,fd=%d " "-device %s,netdev=qtest-bn0,id=qtest-e0 " - "-chardev socket,id=redirector0,path=%s,server,nowait " - "-chardev socket,id=redirector1,path=%s,server,nowait " + "-chardev socket,id=redirector0,path=%s,server=on,wait=off " + "-chardev socket,id=redirector1,path=%s,server=on,wait=off " "-chardev socket,id=redirector2,path=%s " "-object filter-redirector,id=qtest-f0,netdev=qtest-bn0," "queue=tx,outdev=redirector0 " @@ -165,8 +165,8 @@ static void test_redirector_rx(void) qts = qtest_initf( "-netdev socket,id=qtest-bn0,fd=%d " "-device %s,netdev=qtest-bn0,id=qtest-e0 " - "-chardev socket,id=redirector0,path=%s,server,nowait " - "-chardev socket,id=redirector1,path=%s,server,nowait " + "-chardev socket,id=redirector0,path=%s,server=on,wait=off " + "-chardev socket,id=redirector1,path=%s,server=on,wait=off " "-chardev socket,id=redirector2,path=%s " "-object filter-redirector,id=qtest-f0,netdev=qtest-bn0," "queue=rx,indev=redirector0 " diff --git a/tests/qtest/vhost-user-test.c b/tests/qtest/vhost-user-test.c index 3df5322614..1a5f5313ff 100644 --- a/tests/qtest/vhost-user-test.c +++ b/tests/qtest/vhost-user-test.c @@ -537,7 +537,7 @@ static void test_server_create_chr(TestServer *server, const gchar *opt) static void test_server_listen(TestServer *server) { - test_server_create_chr(server, ",server,nowait"); + test_server_create_chr(server, ",server=on,wait=off"); } static void test_server_free(TestServer *server) @@ -846,7 +846,7 @@ static void *vhost_user_test_setup_reconnect(GString *cmd_line, void *arg) g_thread_new("connect", connect_thread, s); append_mem_opts(s, cmd_line, 256, TEST_MEMFD_AUTO); - s->vu_ops->append_opts(s, cmd_line, ",server"); + s->vu_ops->append_opts(s, cmd_line, ",server=on"); g_test_queue_destroy(vhost_user_test_cleanup, s); @@ -883,7 +883,7 @@ static void *vhost_user_test_setup_connect_fail(GString *cmd_line, void *arg) g_thread_new("connect", connect_thread, s); append_mem_opts(s, cmd_line, 256, TEST_MEMFD_AUTO); - s->vu_ops->append_opts(s, cmd_line, ",server"); + s->vu_ops->append_opts(s, cmd_line, ",server=on"); g_test_queue_destroy(vhost_user_test_cleanup, s); @@ -898,7 +898,7 @@ static void *vhost_user_test_setup_flags_mismatch(GString *cmd_line, void *arg) g_thread_new("connect", connect_thread, s); append_mem_opts(s, cmd_line, 256, TEST_MEMFD_AUTO); - s->vu_ops->append_opts(s, cmd_line, ",server"); + s->vu_ops->append_opts(s, cmd_line, ",server=on"); g_test_queue_destroy(vhost_user_test_cleanup, s); diff --git a/tests/test-char.c b/tests/test-char.c index 9196e566e9..953e0d1c1f 100644 --- a/tests/test-char.c +++ b/tests/test-char.c @@ -413,7 +413,7 @@ static void char_websock_test(void) CharBackend client_be; Chardev *chr_client; Chardev *chr = qemu_chr_new("server", - "websocket:127.0.0.1:0,server,nowait", NULL); + "websocket:127.0.0.1:0,server=on,wait=off", NULL); const char handshake[] = "GET / HTTP/1.1\r\n" "Upgrade: websocket\r\n" "Connection: Upgrade\r\n" @@ -696,7 +696,7 @@ char_socket_addr_to_opt_str(SocketAddress *addr, bool fd_pass, fd = ioc->fd; ioc->fd = -1; optstr = g_strdup_printf("socket,id=cdev0,fd=%d%s", - fd, is_listen ? ",server,nowait" : ""); + fd, is_listen ? ",server=on,wait=off" : ""); object_unref(OBJECT(ioc)); return optstr; } else { @@ -706,13 +706,13 @@ char_socket_addr_to_opt_str(SocketAddress *addr, bool fd_pass, addr->u.inet.host, addr->u.inet.port, reconnect ? reconnect : "", - is_listen ? ",server,nowait" : ""); + is_listen ? ",server=on,wait=off" : ""); case SOCKET_ADDRESS_TYPE_UNIX: return g_strdup_printf("socket,id=cdev0,path=%s%s%s", addr->u.q_unix.path, reconnect ? reconnect : "", - is_listen ? ",server,nowait" : ""); + is_listen ? ",server=on,wait=off" : ""); default: g_assert_not_reached(); From 3df8c4f31a60101c61d7f49ce0a3635690bed579 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 21 Oct 2020 06:49:31 -0400 Subject: [PATCH 052/113] vl: extract validation of -smp to machine.c Once smp_parse is done, the validation operates on the MachineState. There is no reason for that code to be in vl.c. Reviewed-by: Igor Mammedov Tested-by: Igor Mammedov Signed-off-by: Paolo Bonzini --- hw/core/machine.c | 23 +++++++++++++++++++++++ include/hw/boards.h | 1 + softmmu/vl.c | 20 ++------------------ 3 files changed, 26 insertions(+), 18 deletions(-) diff --git a/hw/core/machine.c b/hw/core/machine.c index 9c41b94e0d..bd97fc2f1a 100644 --- a/hw/core/machine.c +++ b/hw/core/machine.c @@ -1077,6 +1077,29 @@ MemoryRegion *machine_consume_memdev(MachineState *machine, return ret; } +bool machine_smp_parse(MachineState *ms, QemuOpts *opts, Error **errp) +{ + MachineClass *mc = MACHINE_GET_CLASS(ms); + + mc->smp_parse(ms, opts); + + /* sanity-check smp_cpus and max_cpus against mc */ + if (ms->smp.cpus < mc->min_cpus) { + error_setg(errp, "Invalid SMP CPUs %d. The min CPUs " + "supported by machine '%s' is %d", + ms->smp.cpus, + mc->name, mc->min_cpus); + return false; + } else if (ms->smp.max_cpus > mc->max_cpus) { + error_setg(errp, "Invalid SMP CPUs %d. The max CPUs " + "supported by machine '%s' is %d", + current_machine->smp.max_cpus, + mc->name, mc->max_cpus); + return false; + } + return true; +} + void machine_run_board_init(MachineState *machine) { MachineClass *machine_class = MACHINE_GET_CLASS(machine); diff --git a/include/hw/boards.h b/include/hw/boards.h index f94f4ad5d8..3a1968d035 100644 --- a/include/hw/boards.h +++ b/include/hw/boards.h @@ -26,6 +26,7 @@ OBJECT_DECLARE_TYPE(MachineState, MachineClass, MACHINE) extern MachineState *current_machine; void machine_run_board_init(MachineState *machine); +bool machine_smp_parse(MachineState *ms, QemuOpts *opts, Error **errp); bool machine_usb(MachineState *machine); int machine_phandle_start(MachineState *machine); bool machine_dump_guest_core(MachineState *machine); diff --git a/softmmu/vl.c b/softmmu/vl.c index 3819a4abf2..69d54b27b9 100644 --- a/softmmu/vl.c +++ b/softmmu/vl.c @@ -3976,24 +3976,8 @@ void qemu_init(int argc, char **argv, char **envp) exit(0); } - machine_class->smp_parse(current_machine, - qemu_opts_find(qemu_find_opts("smp-opts"), NULL)); - - /* sanity-check smp_cpus and max_cpus against machine_class */ - if (current_machine->smp.cpus < machine_class->min_cpus) { - error_report("Invalid SMP CPUs %d. The min CPUs " - "supported by machine '%s' is %d", - current_machine->smp.cpus, - machine_class->name, machine_class->min_cpus); - exit(1); - } - if (current_machine->smp.max_cpus > machine_class->max_cpus) { - error_report("Invalid SMP CPUs %d. The max CPUs " - "supported by machine '%s' is %d", - current_machine->smp.max_cpus, - machine_class->name, machine_class->max_cpus); - exit(1); - } + machine_smp_parse(current_machine, + qemu_opts_find(qemu_find_opts("smp-opts"), NULL), &error_fatal); if (mem_prealloc) { char *val; From db372edc06889445106796430567c07fce146490 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 21 Oct 2020 06:07:55 -0400 Subject: [PATCH 053/113] vl: remove bogus check There is no reason to prevent -preconfig -daemonize. Of course if no monitor is defined there will be no way to start the VM, but that is a user error. Signed-off-by: Paolo Bonzini --- softmmu/vl.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/softmmu/vl.c b/softmmu/vl.c index 69d54b27b9..2f2372bac7 100644 --- a/softmmu/vl.c +++ b/softmmu/vl.c @@ -4032,12 +4032,6 @@ void qemu_init(int argc, char **argv, char **envp) } if (is_daemonized()) { - if (!preconfig_exit_requested) { - error_report("'preconfig' and 'daemonize' options are " - "mutually exclusive"); - exit(EXIT_FAILURE); - } - /* According to documentation and historically, -nographic redirects * serial port, parallel port and monitor to stdio, which does not work * with -daemonize. We can redirect these to null instead, but since From 0546c0609cb5a8d90c1cbac8e0d64b5a048bbb19 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 21 Oct 2020 05:17:39 -0400 Subject: [PATCH 054/113] vl: split various early command line options to a separate function Various options affect the global state of QEMU including the rest of qemu_init, and they need to be called very early. Group them together in a function that is called at the beginning. Reviewed-by: Igor Mammedov Signed-off-by: Paolo Bonzini --- softmmu/vl.c | 200 ++++++++++++++++++++++++++++----------------------- 1 file changed, 112 insertions(+), 88 deletions(-) diff --git a/softmmu/vl.c b/softmmu/vl.c index 2f2372bac7..9caff9fe8e 100644 --- a/softmmu/vl.c +++ b/softmmu/vl.c @@ -117,6 +117,7 @@ #define MAX_VIRTIO_CONSOLES 1 +static const char *cpu_option; static const char *data_dir[16]; static int data_dir_idx; enum vga_retrace_method vga_retrace_method = VGA_RETRACE_DUMB; @@ -142,6 +143,9 @@ int vga_interface_type = VGA_NONE; static DisplayOptions dpy; static int num_serial_hds; static Chardev **serial_hds; +static const char *log_mask; +static const char *log_file; +static bool list_data_dirs; Chardev *parallel_hds[MAX_PARALLEL_PORTS]; int win2k_install_hack = 0; int singlestep = 0; @@ -2866,6 +2870,105 @@ static char *find_datadir(void) return get_relocated_path(CONFIG_QEMU_DATADIR); } +static void qemu_process_early_options(void) +{ + char **dirs; + int i; + +#ifdef CONFIG_SECCOMP + QemuOptsList *olist = qemu_find_opts_err("sandbox", NULL); + if (olist) { + qemu_opts_foreach(olist, parse_sandbox, NULL, &error_fatal); + } +#endif + + qemu_opts_foreach(qemu_find_opts("name"), + parse_name, NULL, &error_fatal); + +#ifndef _WIN32 + qemu_opts_foreach(qemu_find_opts("add-fd"), + parse_add_fd, NULL, &error_fatal); + + qemu_opts_foreach(qemu_find_opts("add-fd"), + cleanup_add_fd, NULL, &error_fatal); +#endif + + if (!trace_init_backends()) { + exit(1); + } + trace_init_file(); + + /* Open the logfile at this point and set the log mask if necessary. */ + qemu_set_log_filename(log_file, &error_fatal); + if (log_mask) { + int mask; + mask = qemu_str_to_log_mask(log_mask); + if (!mask) { + qemu_print_log_usage(stdout); + exit(1); + } + qemu_set_log(mask); + } else { + qemu_set_log(0); + } + + /* add configured firmware directories */ + dirs = g_strsplit(CONFIG_QEMU_FIRMWAREPATH, G_SEARCHPATH_SEPARATOR_S, 0); + for (i = 0; dirs[i] != NULL; i++) { + qemu_add_data_dir(get_relocated_path(dirs[i])); + } + g_strfreev(dirs); + + /* try to find datadir relative to the executable path */ + qemu_add_data_dir(find_datadir()); +} + +static void qemu_process_help_options(void) +{ + int i; + + /* + * Check for -cpu help and -device help before we call select_machine(), + * which will return an error if the architecture has no default machine + * type and the user did not specify one, so that the user doesn't need + * to say '-cpu help -machine something'. + */ + if (cpu_option && is_help_option(cpu_option)) { + list_cpus(cpu_option); + exit(0); + } + + if (qemu_opts_foreach(qemu_find_opts("device"), + device_help_func, NULL, NULL)) { + exit(0); + } + + /* -L help lists the data directories and exits. */ + if (list_data_dirs) { + for (i = 0; i < data_dir_idx; i++) { + printf("%s\n", data_dir[i]); + } + exit(0); + } +} + +static void qemu_maybe_daemonize(const char *pid_file) +{ + Error *err; + + os_daemonize(); + rcu_disable_atfork(); + + if (pid_file && !qemu_write_pidfile(pid_file, &err)) { + error_reportf_err(err, "cannot create PID file: "); + exit(1); + } + + qemu_unlink_pidfile_notifier.notify = qemu_unlink_pidfile; + qemu_add_exit_notifier(&qemu_unlink_pidfile_notifier); +} + + void qemu_init(int argc, char **argv, char **envp) { int i; @@ -2882,21 +2985,16 @@ void qemu_init(int argc, char **argv, char **envp) const char *optarg; const char *loadvm = NULL; MachineClass *machine_class; - const char *cpu_option; const char *vga_model = NULL; const char *incoming = NULL; bool userconfig = true; bool nographic = false; int display_remote = 0; - const char *log_mask = NULL; - const char *log_file = NULL; ram_addr_t maxram_size; uint64_t ram_slots = 0; FILE *vmstate_dump_file = NULL; Error *main_loop_err = NULL; Error *err = NULL; - bool list_data_dirs = false; - char **dirs; const char *mem_path = NULL; bool have_custom_ram_size; BlockdevOptionsQueue bdo_queue = QSIMPLEQ_HEAD_INITIALIZER(bdo_queue); @@ -3846,19 +3944,17 @@ void qemu_init(int argc, char **argv, char **envp) loc_set_none(); /* - * Check for -cpu help and -device help before we call select_machine(), - * which will return an error if the architecture has no default machine - * type and the user did not specify one, so that the user doesn't need - * to say '-cpu help -machine something'. + * These options affect everything else and should be processed + * before daemonizing. */ - if (cpu_option && is_help_option(cpu_option)) { - list_cpus(cpu_option); - exit(0); - } + qemu_process_early_options(); - if (qemu_opts_foreach(qemu_find_opts("device"), - device_help_func, NULL, NULL)) { - exit(0); + qemu_process_help_options(); + qemu_maybe_daemonize(pid_file); + + if (qemu_init_main_loop(&main_loop_err)) { + error_report_err(main_loop_err); + exit(1); } user_register_global_props(); @@ -3879,40 +3975,6 @@ void qemu_init(int argc, char **argv, char **envp) have_custom_ram_size = set_memory_options(&ram_slots, &maxram_size, machine_class); - os_daemonize(); - rcu_disable_atfork(); - - if (pid_file && !qemu_write_pidfile(pid_file, &err)) { - error_reportf_err(err, "cannot create PID file: "); - exit(1); - } - - qemu_unlink_pidfile_notifier.notify = qemu_unlink_pidfile; - qemu_add_exit_notifier(&qemu_unlink_pidfile_notifier); - - if (qemu_init_main_loop(&main_loop_err)) { - error_report_err(main_loop_err); - exit(1); - } - -#ifdef CONFIG_SECCOMP - olist = qemu_find_opts_err("sandbox", NULL); - if (olist) { - qemu_opts_foreach(olist, parse_sandbox, NULL, &error_fatal); - } -#endif - - qemu_opts_foreach(qemu_find_opts("name"), - parse_name, NULL, &error_fatal); - -#ifndef _WIN32 - qemu_opts_foreach(qemu_find_opts("add-fd"), - parse_add_fd, NULL, &error_fatal); - - qemu_opts_foreach(qemu_find_opts("add-fd"), - cleanup_add_fd, NULL, &error_fatal); -#endif - current_machine = MACHINE(object_new_with_class(OBJECT_CLASS(machine_class))); if (machine_help_func(qemu_get_machine_opts(), current_machine)) { exit(0); @@ -3938,44 +4000,6 @@ void qemu_init(int argc, char **argv, char **envp) qemu_set_hw_version(machine_class->hw_version); } - if (!trace_init_backends()) { - exit(1); - } - trace_init_file(); - - /* Open the logfile at this point and set the log mask if necessary. - */ - qemu_set_log_filename(log_file, &error_fatal); - if (log_mask) { - int mask; - mask = qemu_str_to_log_mask(log_mask); - if (!mask) { - qemu_print_log_usage(stdout); - exit(1); - } - qemu_set_log(mask); - } else { - qemu_set_log(0); - } - - /* add configured firmware directories */ - dirs = g_strsplit(CONFIG_QEMU_FIRMWAREPATH, G_SEARCHPATH_SEPARATOR_S, 0); - for (i = 0; dirs[i] != NULL; i++) { - qemu_add_data_dir(get_relocated_path(dirs[i])); - } - g_strfreev(dirs); - - /* try to find datadir relative to the executable path */ - qemu_add_data_dir(find_datadir()); - - /* -L help lists the data directories and exits. */ - if (list_data_dirs) { - for (i = 0; i < data_dir_idx; i++) { - printf("%s\n", data_dir[i]); - } - exit(0); - } - machine_smp_parse(current_machine, qemu_opts_find(qemu_find_opts("smp-opts"), NULL), &error_fatal); From e0d17dfd22348eab63c5e19b7ee9c9212c2b8af8 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 21 Oct 2020 05:25:58 -0400 Subject: [PATCH 055/113] vl: move various initialization routines out of qemu_init Some very simple initialization routines can be nested in existing subsystem-level functions, do that to simplify qemu_init. Reviewed-by: Igor Mammedov Signed-off-by: Paolo Bonzini --- hw/core/machine.c | 3 +++ include/hw/qdev-core.h | 8 -------- migration/migration.c | 4 ++++ softmmu/qdev-monitor.c | 6 ------ softmmu/vl.c | 5 ----- 5 files changed, 7 insertions(+), 19 deletions(-) diff --git a/hw/core/machine.c b/hw/core/machine.c index bd97fc2f1a..83f45a9351 100644 --- a/hw/core/machine.c +++ b/hw/core/machine.c @@ -877,6 +877,9 @@ static void machine_initfn(Object *obj) MachineState *ms = MACHINE(obj); MachineClass *mc = MACHINE_GET_CLASS(obj); + container_get(obj, "/peripheral"); + container_get(obj, "/peripheral-anon"); + ms->dump_guest_core = true; ms->mem_merge = true; ms->enable_graphics = true; diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h index 6ac86db44e..9fbb22a48d 100644 --- a/include/hw/qdev-core.h +++ b/include/hw/qdev-core.h @@ -787,14 +787,6 @@ BusState *sysbus_get_default(void); char *qdev_get_fw_dev_path(DeviceState *dev); char *qdev_get_own_fw_dev_path_from_handler(BusState *bus, DeviceState *dev); -/** - * @qdev_machine_init - * - * Initialize platform devices before machine init. This is a hack until full - * support for composition is added. - */ -void qdev_machine_init(void); - /** * device_legacy_reset: * diff --git a/migration/migration.c b/migration/migration.c index 87a9b59f83..d9e94f4080 100644 --- a/migration/migration.c +++ b/migration/migration.c @@ -182,6 +182,10 @@ void migration_object_init(void) error_report_err(err); exit(1); } + + blk_mig_init(); + ram_mig_init(); + dirty_bitmap_mig_init(); } void migration_shutdown(void) diff --git a/softmmu/qdev-monitor.c b/softmmu/qdev-monitor.c index 301089eaea..c2816c5a29 100644 --- a/softmmu/qdev-monitor.c +++ b/softmmu/qdev-monitor.c @@ -928,12 +928,6 @@ BlockBackend *blk_by_qdev_id(const char *id, Error **errp) return blk; } -void qdev_machine_init(void) -{ - qdev_get_peripheral_anon(); - qdev_get_peripheral(); -} - QemuOptsList qemu_device_opts = { .name = "device", .implied_opt_name = "driver", diff --git a/softmmu/vl.c b/softmmu/vl.c index 9caff9fe8e..8640ddd3ec 100644 --- a/softmmu/vl.c +++ b/softmmu/vl.c @@ -4280,10 +4280,6 @@ void qemu_init(int argc, char **argv, char **envp) exit(1); } - blk_mig_init(); - ram_mig_init(); - dirty_bitmap_mig_init(); - qemu_opts_foreach(qemu_find_opts("mon"), mon_init_func, NULL, &error_fatal); @@ -4316,7 +4312,6 @@ void qemu_init(int argc, char **argv, char **envp) reading from the other reads, because timer polling functions query clock values from the log. */ replay_checkpoint(CHECKPOINT_INIT); - qdev_machine_init(); current_machine->boot_order = boot_order; From efd7ab22fbc9e58c0aaa0fbc0a723e95972a626f Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 21 Oct 2020 05:33:40 -0400 Subject: [PATCH 056/113] vl: extract qemu_init_subsystems Group a bunch of subsystem initializations that can be done right after command line parsing. Remove initializations that can be done simply as global variable initializers. Reviewed-by: Igor Mammedov Signed-off-by: Paolo Bonzini --- softmmu/vl.c | 94 ++++++++++++++++++++++++---------------------------- 1 file changed, 43 insertions(+), 51 deletions(-) diff --git a/softmmu/vl.c b/softmmu/vl.c index 8640ddd3ec..41a685bb5d 100644 --- a/softmmu/vl.c +++ b/softmmu/vl.c @@ -128,7 +128,7 @@ bool enable_mlock = false; bool enable_cpu_pm = false; int nb_nics; NICInfo nd_table[MAX_NICS]; -int autostart; +int autostart = 1; static enum { RTC_BASE_UTC, RTC_BASE_LOCALTIME, @@ -1228,7 +1228,8 @@ struct VMChangeStateEntry { int priority; }; -static QTAILQ_HEAD(, VMChangeStateEntry) vm_change_state_head; +static QTAILQ_HEAD(, VMChangeStateEntry) vm_change_state_head = + QTAILQ_HEAD_INITIALIZER(vm_change_state_head); /** * qemu_add_vm_change_state_handler_prio: @@ -2968,11 +2969,44 @@ static void qemu_maybe_daemonize(const char *pid_file) qemu_add_exit_notifier(&qemu_unlink_pidfile_notifier); } +static void qemu_init_subsystems(void) +{ + Error *err; + + os_set_line_buffering(); + + module_call_init(MODULE_INIT_TRACE); + + qemu_init_cpu_list(); + qemu_init_cpu_loop(); + qemu_mutex_lock_iothread(); + + atexit(qemu_run_exit_notifiers); + + module_call_init(MODULE_INIT_QOM); + module_call_init(MODULE_INIT_MIGRATION); + + runstate_init(); + precopy_infrastructure_init(); + postcopy_infrastructure_init(); + monitor_init_globals(); + + if (qcrypto_init(&err) < 0) { + error_reportf_err(err, "cannot initialize crypto: "); + exit(1); + } + + os_setup_early_signal_handling(); + + bdrv_init_with_whitelist(); + socket_init(); +} void qemu_init(int argc, char **argv, char **envp) { int i; - int snapshot, linux_boot; + int snapshot = 0; + int linux_boot; const char *initrd_filename; const char *kernel_filename, *kernel_cmdline; const char *boot_order = NULL; @@ -2993,7 +3027,6 @@ void qemu_init(int argc, char **argv, char **envp) ram_addr_t maxram_size; uint64_t ram_slots = 0; FILE *vmstate_dump_file = NULL; - Error *main_loop_err = NULL; Error *err = NULL; const char *mem_path = NULL; bool have_custom_ram_size; @@ -3001,22 +3034,6 @@ void qemu_init(int argc, char **argv, char **envp) QemuPluginList plugin_list = QTAILQ_HEAD_INITIALIZER(plugin_list); int mem_prealloc = 0; /* force preallocation of physical target memory */ - os_set_line_buffering(); - - error_init(argv[0]); - module_call_init(MODULE_INIT_TRACE); - - qemu_init_cpu_list(); - qemu_init_cpu_loop(); - - qemu_mutex_lock_iothread(); - - atexit(qemu_run_exit_notifiers); - qemu_init_exec_dir(argv[0]); - - module_call_init(MODULE_INIT_QOM); - module_call_init(MODULE_INIT_MIGRATION); - qemu_add_opts(&qemu_drive_opts); qemu_add_drive_opts(&qemu_legacy_drive_opts); qemu_add_drive_opts(&qemu_common_drive_opts); @@ -3051,27 +3068,10 @@ void qemu_init(int argc, char **argv, char **envp) qemu_add_opts(&qemu_fw_cfg_opts); module_call_init(MODULE_INIT_OPTS); - runstate_init(); - precopy_infrastructure_init(); - postcopy_infrastructure_init(); - monitor_init_globals(); + error_init(argv[0]); + qemu_init_exec_dir(argv[0]); - if (qcrypto_init(&err) < 0) { - error_reportf_err(err, "cannot initialize crypto: "); - exit(1); - } - - QTAILQ_INIT(&vm_change_state_head); - os_setup_early_signal_handling(); - - cpu_option = NULL; - snapshot = 0; - - nb_nics = 0; - - bdrv_init_with_whitelist(); - - autostart = 1; + qemu_init_subsystems(); /* first pass of option parsing */ optind = 1; @@ -3952,13 +3952,10 @@ void qemu_init(int argc, char **argv, char **envp) qemu_process_help_options(); qemu_maybe_daemonize(pid_file); - if (qemu_init_main_loop(&main_loop_err)) { - error_report_err(main_loop_err); - exit(1); - } + qemu_init_main_loop(&error_fatal); + cpu_timers_init(); user_register_global_props(); - replay_configure(icount_opts); if (incoming && !preconfig_exit_requested) { @@ -3995,6 +3992,7 @@ void qemu_init(int argc, char **argv, char **envp) } cpu_exec_init_all(); + page_size_init(); if (machine_class->hw_version) { qemu_set_hw_version(machine_class->hw_version); @@ -4137,9 +4135,6 @@ void qemu_init(int argc, char **argv, char **envp) exit(1); } - page_size_init(); - socket_init(); - qemu_opts_foreach(qemu_find_opts("object"), user_creatable_add_opts_foreach, object_create_initial, &error_fatal); @@ -4256,9 +4251,6 @@ void qemu_init(int argc, char **argv, char **envp) semihosting_arg_fallback(kernel_filename, kernel_cmdline); } - /* initialize cpu timers and VCPU throttle modules */ - cpu_timers_init(); - if (default_net) { QemuOptsList *net = qemu_find_opts("net"); qemu_opts_set(net, NULL, "type", "nic", &error_abort); From d8e4de41c95f701f79869080b23362f1325c8897 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Fri, 23 Oct 2020 08:04:29 -0400 Subject: [PATCH 057/113] vl: move prelaunch part of qemu_init to new functions The final part of qemu_init, starting with the completion of board init, is already relatively clean. Split it out of qemu_init so that qemu_init keeps only the messy parts. Reviewed-by: Igor Mammedov Signed-off-by: Paolo Bonzini --- softmmu/vl.c | 249 +++++++++++++++++++++++++++------------------------ 1 file changed, 134 insertions(+), 115 deletions(-) diff --git a/softmmu/vl.c b/softmmu/vl.c index 41a685bb5d..90f9782107 100644 --- a/softmmu/vl.c +++ b/softmmu/vl.c @@ -120,6 +120,9 @@ static const char *cpu_option; static const char *data_dir[16]; static int data_dir_idx; +static const char *mem_path; +static const char *boot_order; +static const char *boot_once; enum vga_retrace_method vga_retrace_method = VGA_RETRACE_DUMB; int display_opengl; const char* keyboard_layout = NULL; @@ -3002,6 +3005,134 @@ static void qemu_init_subsystems(void) socket_init(); } +/* + * Called after leaving preconfig state. From here on runstate is + * RUN_STATE_PRELAUNCH or RUN_STATE_INMIGRATE. + */ +static void qemu_init_board(void) +{ + MachineClass *machine_class = MACHINE_GET_CLASS(current_machine); + + if (machine_class->default_ram_id && current_machine->ram_size && + numa_uses_legacy_mem() && !current_machine->ram_memdev_id) { + create_default_memdev(current_machine, mem_path); + } + + machine_run_board_init(current_machine); + + /* + * TODO To drop support for deprecated bogus if=..., move + * drive_check_orphaned() here, replacing this call. Also drop + * its deprecation warning, along with DriveInfo member + * @claimed_by_board. + */ + drive_mark_claimed_by_board(); + + realtime_init(); + + if (hax_enabled()) { + /* FIXME: why isn't cpu_synchronize_all_post_init enough? */ + hax_sync_vcpus(); + } +} + +static void qemu_create_cli_devices(void) +{ + soundhw_init(); + + qemu_opts_foreach(qemu_find_opts("fw_cfg"), + parse_fw_cfg, fw_cfg_find(), &error_fatal); + + /* init USB devices */ + if (machine_usb(current_machine)) { + if (foreach_device_config(DEV_USB, usb_parse) < 0) + exit(1); + } + + /* init generic devices */ + rom_set_order_override(FW_CFG_ORDER_OVERRIDE_DEVICE); + qemu_opts_foreach(qemu_find_opts("device"), + device_init_func, NULL, &error_fatal); + rom_reset_order_override(); +} + +static void qemu_machine_creation_done(void) +{ + DisplayState *ds; + + cpu_synchronize_all_post_init(); + + /* Did we create any drives that we failed to create a device for? */ + drive_check_orphaned(); + + /* Don't warn about the default network setup that you get if + * no command line -net or -netdev options are specified. There + * are two cases that we would otherwise complain about: + * (1) board doesn't support a NIC but the implicit "-net nic" + * requested one + * (2) CONFIG_SLIRP not set, in which case the implicit "-net nic" + * sets up a nic that isn't connected to anything. + */ + if (!default_net && (!qtest_enabled() || has_defaults)) { + net_check_clients(); + } + + if (boot_once) { + qemu_boot_set(boot_once, &error_fatal); + qemu_register_reset(restore_boot_order, g_strdup(boot_order)); + } + + /* init local displays */ + ds = init_displaystate(); + qemu_display_init(ds, &dpy); + + /* must be after terminal init, SDL library changes signal handlers */ + os_setup_signal_handling(); + + /* init remote displays */ +#ifdef CONFIG_VNC + qemu_opts_foreach(qemu_find_opts("vnc"), + vnc_init_func, NULL, &error_fatal); +#endif + + if (using_spice) { + qemu_spice.display_init(); + } + + if (foreach_device_config(DEV_GDB, gdbserver_start) < 0) { + exit(1); + } + + qdev_machine_creation_done(); + + /* TODO: once all bus devices are qdevified, this should be done + * when bus is created by qdev.c */ + /* + * TODO: If we had a main 'reset container' that the whole system + * lived in, we could reset that using the multi-phase reset + * APIs. For the moment, we just reset the sysbus, which will cause + * all devices hanging off it (and all their child buses, recursively) + * to be reset. Note that this will *not* reset any Device objects + * which are not attached to some part of the qbus tree! + */ + qemu_register_reset(resettable_cold_reset_fn, sysbus_get_default()); + qemu_run_machine_init_done_notifiers(); + + if (rom_check_and_register_reset() != 0) { + error_report("rom check and register reset failed"); + exit(1); + } + + replay_start(); + + /* This checkpoint is required by replay to separate prior clock + reading from the other reads, because timer polling functions query + clock values from the log. */ + replay_checkpoint(CHECKPOINT_RESET); + qemu_system_reset(SHUTDOWN_CAUSE_NONE); + register_global_state(); +} + void qemu_init(int argc, char **argv, char **envp) { int i; @@ -3009,9 +3140,6 @@ void qemu_init(int argc, char **argv, char **envp) int linux_boot; const char *initrd_filename; const char *kernel_filename, *kernel_cmdline; - const char *boot_order = NULL; - const char *boot_once = NULL; - DisplayState *ds; QemuOpts *opts, *machine_opts; QemuOpts *icount_opts = NULL, *accel_opts = NULL; QemuOptsList *olist; @@ -3028,7 +3156,6 @@ void qemu_init(int argc, char **argv, char **envp) uint64_t ram_slots = 0; FILE *vmstate_dump_file = NULL; Error *err = NULL; - const char *mem_path = NULL; bool have_custom_ram_size; BlockdevOptionsQueue bdo_queue = QSIMPLEQ_HEAD_INITIALIZER(bdo_queue); QemuPluginList plugin_list = QTAILQ_HEAD_INITIALIZER(plugin_list); @@ -4351,117 +4478,10 @@ void qemu_init(int argc, char **argv, char **envp) /* do monitor/qmp handling at preconfig state if requested */ qemu_main_loop(); - if (machine_class->default_ram_id && current_machine->ram_size && - numa_uses_legacy_mem() && !current_machine->ram_memdev_id) { - create_default_memdev(current_machine, mem_path); - } + qemu_init_board(); + qemu_create_cli_devices(); + qemu_machine_creation_done(); - /* from here on runstate is RUN_STATE_PRELAUNCH */ - machine_run_board_init(current_machine); - - /* - * TODO To drop support for deprecated bogus if=..., move - * drive_check_orphaned() here, replacing this call. Also drop - * its deprecation warning, along with DriveInfo member - * @claimed_by_board. - */ - drive_mark_claimed_by_board(); - - realtime_init(); - - soundhw_init(); - - if (hax_enabled()) { - hax_sync_vcpus(); - } - - qemu_opts_foreach(qemu_find_opts("fw_cfg"), - parse_fw_cfg, fw_cfg_find(), &error_fatal); - - /* init USB devices */ - if (machine_usb(current_machine)) { - if (foreach_device_config(DEV_USB, usb_parse) < 0) - exit(1); - } - - /* init generic devices */ - rom_set_order_override(FW_CFG_ORDER_OVERRIDE_DEVICE); - qemu_opts_foreach(qemu_find_opts("device"), - device_init_func, NULL, &error_fatal); - - cpu_synchronize_all_post_init(); - - rom_reset_order_override(); - - /* Did we create any drives that we failed to create a device for? */ - drive_check_orphaned(); - - /* Don't warn about the default network setup that you get if - * no command line -net or -netdev options are specified. There - * are two cases that we would otherwise complain about: - * (1) board doesn't support a NIC but the implicit "-net nic" - * requested one - * (2) CONFIG_SLIRP not set, in which case the implicit "-net nic" - * sets up a nic that isn't connected to anything. - */ - if (!default_net && (!qtest_enabled() || has_defaults)) { - net_check_clients(); - } - - if (boot_once) { - qemu_boot_set(boot_once, &error_fatal); - qemu_register_reset(restore_boot_order, g_strdup(boot_order)); - } - - /* init local displays */ - ds = init_displaystate(); - qemu_display_init(ds, &dpy); - - /* must be after terminal init, SDL library changes signal handlers */ - os_setup_signal_handling(); - - /* init remote displays */ -#ifdef CONFIG_VNC - qemu_opts_foreach(qemu_find_opts("vnc"), - vnc_init_func, NULL, &error_fatal); -#endif - - if (using_spice) { - qemu_spice.display_init(); - } - - if (foreach_device_config(DEV_GDB, gdbserver_start) < 0) { - exit(1); - } - - qdev_machine_creation_done(); - - /* TODO: once all bus devices are qdevified, this should be done - * when bus is created by qdev.c */ - /* - * TODO: If we had a main 'reset container' that the whole system - * lived in, we could reset that using the multi-phase reset - * APIs. For the moment, we just reset the sysbus, which will cause - * all devices hanging off it (and all their child buses, recursively) - * to be reset. Note that this will *not* reset any Device objects - * which are not attached to some part of the qbus tree! - */ - qemu_register_reset(resettable_cold_reset_fn, sysbus_get_default()); - qemu_run_machine_init_done_notifiers(); - - if (rom_check_and_register_reset() != 0) { - error_report("rom check and register reset failed"); - exit(1); - } - - replay_start(); - - /* This checkpoint is required by replay to separate prior clock - reading from the other reads, because timer polling functions query - clock values from the log. */ - replay_checkpoint(CHECKPOINT_RESET); - qemu_system_reset(SHUTDOWN_CAUSE_NONE); - register_global_state(); if (loadvm) { Error *local_err = NULL; if (load_snapshot(loadvm, &local_err) < 0) { @@ -4480,7 +4500,6 @@ void qemu_init(int argc, char **argv, char **envp) dump_vmstate_json_to_file(vmstate_dump_file); exit(0); } - if (incoming) { Error *local_err = NULL; qemu_start_incoming_migration(incoming, &local_err); From 58c91595a793b9f54b58a449121a2cf4b9f86cf0 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Tue, 3 Nov 2020 03:45:26 -0500 Subject: [PATCH 058/113] vl: extract various command line validation snippets to a new function Reviewed-by: Igor Mammedov Signed-off-by: Paolo Bonzini --- hw/core/machine.c | 1 + softmmu/vl.c | 78 +++++++++++++++++++++++------------------------ 2 files changed, 40 insertions(+), 39 deletions(-) diff --git a/hw/core/machine.c b/hw/core/machine.c index 83f45a9351..5a65b9d88e 100644 --- a/hw/core/machine.c +++ b/hw/core/machine.c @@ -883,6 +883,7 @@ static void machine_initfn(Object *obj) ms->dump_guest_core = true; ms->mem_merge = true; ms->enable_graphics = true; + ms->kernel_cmdline = g_strdup(""); if (mc->nvdimm_supported) { Object *obj = OBJECT(ms); diff --git a/softmmu/vl.c b/softmmu/vl.c index 90f9782107..71b5263d05 100644 --- a/softmmu/vl.c +++ b/softmmu/vl.c @@ -123,6 +123,7 @@ static int data_dir_idx; static const char *mem_path; static const char *boot_order; static const char *boot_once; +static const char *incoming; enum vga_retrace_method vga_retrace_method = VGA_RETRACE_DUMB; int display_opengl; const char* keyboard_layout = NULL; @@ -2874,6 +2875,39 @@ static char *find_datadir(void) return get_relocated_path(CONFIG_QEMU_DATADIR); } +static void qemu_validate_options(void) +{ + QemuOpts *machine_opts = qemu_get_machine_opts(); + const char *kernel_filename = qemu_opt_get(machine_opts, "kernel"); + const char *initrd_filename = qemu_opt_get(machine_opts, "initrd"); + const char *kernel_cmdline = qemu_opt_get(machine_opts, "append"); + + if (kernel_filename == NULL) { + if (kernel_cmdline != NULL) { + error_report("-append only allowed with -kernel option"); + exit(1); + } + + if (initrd_filename != NULL) { + error_report("-initrd only allowed with -kernel option"); + exit(1); + } + } + + if (incoming && !preconfig_exit_requested) { + error_report("'preconfig' and 'incoming' options are " + "mutually exclusive"); + exit(EXIT_FAILURE); + } + +#ifdef CONFIG_CURSES + if (is_daemonized() && dpy.type == DISPLAY_TYPE_CURSES) { + error_report("curses display cannot be used with -daemonize"); + exit(1); + } +#endif +} + static void qemu_process_early_options(void) { char **dirs; @@ -3137,9 +3171,6 @@ void qemu_init(int argc, char **argv, char **envp) { int i; int snapshot = 0; - int linux_boot; - const char *initrd_filename; - const char *kernel_filename, *kernel_cmdline; QemuOpts *opts, *machine_opts; QemuOpts *icount_opts = NULL, *accel_opts = NULL; QemuOptsList *olist; @@ -3148,7 +3179,6 @@ void qemu_init(int argc, char **argv, char **envp) const char *loadvm = NULL; MachineClass *machine_class; const char *vga_model = NULL; - const char *incoming = NULL; bool userconfig = true; bool nographic = false; int display_remote = 0; @@ -4070,6 +4100,8 @@ void qemu_init(int argc, char **argv, char **envp) */ loc_set_none(); + qemu_validate_options(); + /* * These options affect everything else and should be processed * before daemonizing. @@ -4085,12 +4117,6 @@ void qemu_init(int argc, char **argv, char **envp) user_register_global_props(); replay_configure(icount_opts); - if (incoming && !preconfig_exit_requested) { - error_report("'preconfig' and 'incoming' options are " - "mutually exclusive"); - exit(EXIT_FAILURE); - } - configure_rtc(qemu_find_opts_singleton("rtc")); machine_class = select_machine(); @@ -4195,12 +4221,6 @@ void qemu_init(int argc, char **argv, char **envp) error_report("-nographic cannot be used with -daemonize"); exit(1); } -#ifdef CONFIG_CURSES - if (dpy.type == DISPLAY_TYPE_CURSES) { - error_report("curses display cannot be used with -daemonize"); - exit(1); - } -#endif } if (nographic) { @@ -4331,11 +4351,6 @@ void qemu_init(int argc, char **argv, char **envp) qtest_server_init(qtest_chrdev, qtest_log, &error_fatal); } - machine_opts = qemu_get_machine_opts(); - kernel_filename = qemu_opt_get(machine_opts, "kernel"); - initrd_filename = qemu_opt_get(machine_opts, "initrd"); - kernel_cmdline = qemu_opt_get(machine_opts, "append"); - opts = qemu_opts_find(qemu_find_opts("boot-opts"), NULL); if (opts) { boot_order = qemu_opt_get(opts, "order"); @@ -4356,24 +4371,9 @@ void qemu_init(int argc, char **argv, char **envp) boot_order = machine_class->default_boot_order; } - if (!kernel_cmdline) { - kernel_cmdline = ""; - current_machine->kernel_cmdline = (char *)kernel_cmdline; - } - - linux_boot = (kernel_filename != NULL); - - if (!linux_boot && *kernel_cmdline != '\0') { - error_report("-append only allowed with -kernel option"); - exit(1); - } - - if (!linux_boot && initrd_filename != NULL) { - error_report("-initrd only allowed with -kernel option"); - exit(1); - } - - if (semihosting_enabled() && !semihosting_get_argc() && kernel_filename) { + if (semihosting_enabled() && !semihosting_get_argc()) { + const char *kernel_filename = qemu_opt_get(machine_opts, "kernel"); + const char *kernel_cmdline = qemu_opt_get(machine_opts, "append"); /* fall back to the -kernel/-append */ semihosting_arg_fallback(kernel_filename, kernel_cmdline); } From 90285ec8bb1c47d4ef8349a765ba7c9a672212c8 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 21 Oct 2020 10:19:08 -0400 Subject: [PATCH 059/113] vl: preconfig and loadvm are mutually exclusive Just like -incoming. Later we will add support for "-incoming defer -preconfig", because there are cases (Xen, block layer) that want to look at RUNSTATE_INMIGRATE. -loadvm will remain mutually exclusive with preconfig; the plan is to just do loadvm in the monitor, since the user is already going to interact with it for preconfiguration. Reviewed-by: Igor Mammedov Signed-off-by: Paolo Bonzini --- softmmu/vl.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/softmmu/vl.c b/softmmu/vl.c index 71b5263d05..98994e10fa 100644 --- a/softmmu/vl.c +++ b/softmmu/vl.c @@ -124,6 +124,7 @@ static const char *mem_path; static const char *boot_order; static const char *boot_once; static const char *incoming; +static const char *loadvm; enum vga_retrace_method vga_retrace_method = VGA_RETRACE_DUMB; int display_opengl; const char* keyboard_layout = NULL; @@ -2894,6 +2895,11 @@ static void qemu_validate_options(void) } } + if (loadvm && !preconfig_exit_requested) { + error_report("'preconfig' and 'loadvm' options are " + "mutually exclusive"); + exit(EXIT_FAILURE); + } if (incoming && !preconfig_exit_requested) { error_report("'preconfig' and 'incoming' options are " "mutually exclusive"); @@ -3176,7 +3182,6 @@ void qemu_init(int argc, char **argv, char **envp) QemuOptsList *olist; int optind; const char *optarg; - const char *loadvm = NULL; MachineClass *machine_class; const char *vga_model = NULL; bool userconfig = true; From 4d2c17b0ef760881485a3d31f941117d9fc71bd8 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 21 Oct 2020 10:21:22 -0400 Subject: [PATCH 060/113] vl: extract various command line desugaring snippets to a new function Keep the machine initialization sequence free of miscellaneous command line parsing actions. The only difference is that preallocation will always be done with one thread if -smp is not provided; previously it was using mc->default_cpus, which is almost always 1 anyway. Reviewed-by: Igor Mammedov Signed-off-by: Paolo Bonzini --- softmmu/vl.c | 40 ++++++++++++++++++++++------------------ 1 file changed, 22 insertions(+), 18 deletions(-) diff --git a/softmmu/vl.c b/softmmu/vl.c index 98994e10fa..85b23d51be 100644 --- a/softmmu/vl.c +++ b/softmmu/vl.c @@ -126,6 +126,7 @@ static const char *boot_once; static const char *incoming; static const char *loadvm; enum vga_retrace_method vga_retrace_method = VGA_RETRACE_DUMB; +static int mem_prealloc; /* force preallocation of physical target memory */ int display_opengl; const char* keyboard_layout = NULL; static ram_addr_t ram_size; @@ -158,7 +159,7 @@ int fd_bootchk = 1; static int no_reboot; int no_shutdown = 0; int graphic_rotate = 0; -const char *watchdog; +static const char *watchdog; QEMUOptionRom option_rom[MAX_OPTION_ROMS]; int nb_option_roms; int old_param = 0; @@ -2914,6 +2915,25 @@ static void qemu_validate_options(void) #endif } +static void qemu_process_sugar_options(void) +{ + if (mem_prealloc) { + char *val; + + val = g_strdup_printf("%d", + (uint32_t) qemu_opt_get_number(qemu_find_opts_singleton("smp-opts"), "cpus", 1)); + object_register_sugar_prop("memory-backend", "prealloc-threads", val); + g_free(val); + object_register_sugar_prop("memory-backend", "prealloc", "on"); + } + + if (watchdog) { + int i = select_watchdog(watchdog); + if (i > 0) + exit (i == 1 ? 1 : 0); + } +} + static void qemu_process_early_options(void) { char **dirs; @@ -3175,7 +3195,6 @@ static void qemu_machine_creation_done(void) void qemu_init(int argc, char **argv, char **envp) { - int i; int snapshot = 0; QemuOpts *opts, *machine_opts; QemuOpts *icount_opts = NULL, *accel_opts = NULL; @@ -3194,7 +3213,6 @@ void qemu_init(int argc, char **argv, char **envp) bool have_custom_ram_size; BlockdevOptionsQueue bdo_queue = QSIMPLEQ_HEAD_INITIALIZER(bdo_queue); QemuPluginList plugin_list = QTAILQ_HEAD_INITIALIZER(plugin_list); - int mem_prealloc = 0; /* force preallocation of physical target memory */ qemu_add_opts(&qemu_drive_opts); qemu_add_drive_opts(&qemu_legacy_drive_opts); @@ -4106,6 +4124,7 @@ void qemu_init(int argc, char **argv, char **envp) loc_set_none(); qemu_validate_options(); + qemu_process_sugar_options(); /* * These options affect everything else and should be processed @@ -4159,15 +4178,6 @@ void qemu_init(int argc, char **argv, char **envp) machine_smp_parse(current_machine, qemu_opts_find(qemu_find_opts("smp-opts"), NULL), &error_fatal); - if (mem_prealloc) { - char *val; - - val = g_strdup_printf("%d", current_machine->smp.cpus); - object_register_sugar_prop("memory-backend", "prealloc-threads", val); - g_free(val); - object_register_sugar_prop("memory-backend", "prealloc", "on"); - } - /* * Get the default machine options from the machine if it is not already * specified either by the configuration file or by the command line. @@ -4426,12 +4436,6 @@ void qemu_init(int argc, char **argv, char **envp) select_vgahw(machine_class, vga_model); } - if (watchdog) { - i = select_watchdog(watchdog); - if (i > 0) - exit (i == 1 ? 1 : 0); - } - /* This checkpoint is required by replay to separate prior clock reading from the other reads, because timer polling functions query clock values from the log. */ From 32c02fdda49b8ace1517f1b95bfc215e0b92a154 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 9 Nov 2020 04:46:30 -0500 Subject: [PATCH 061/113] qemu-option: restrict qemu_opts_set to merge-lists QemuOpts qemu_opts_set is used to create default network backends and to parse sugar options -kernel, -initrd, -append, -bios and -dtb. These are very different uses: I would *expect* a function named qemu_opts_set to set an option in a merge-lists QemuOptsList, such as -kernel, and possibly to set an option in a non-merge-lists QemuOptsList with non-NULL id, similar to -set. However, it wouldn't *work* to use qemu_opts_set for the latter because qemu_opts_set uses fail_if_exists==1. So, for non-merge-lists QemuOptsList and non-NULL id, the semantics of qemu_opts_set (fail if the (QemuOptsList, id) pair already exists) are debatable. On the other hand, I would not expect qemu_opts_set to create a non-merge-lists QemuOpts with a single option; which it does, though. For this case of non-merge-lists QemuOptsList and NULL id, qemu_opts_set hardly adds value over qemu_opts_parse. It does skip some parsing and unescaping, but that's not needed when creating default network backends. So qemu_opts_set has warty behavior for non-merge-lists QemuOptsList if id is non-NULL, and it's mostly pointless if id is NULL. My solution to keeping the API as simple as possible is to limit qemu_opts_set to merge-lists QemuOptsList. For them, it's useful (we don't want comma-unescaping for -kernel) *and* has sane semantics. Network backend creation is switched to qemu_opts_parse. qemu_opts_set is now only used on merge-lists QemuOptsList... except in the testcase, which is changed to use a merge-list QemuOptsList. With this change we can also remove the id parameter. With the parameter always NULL, we know that qemu_opts_create cannot fail and can pass &error_abort to it. Signed-off-by: Paolo Bonzini --- include/qemu/option.h | 3 +-- softmmu/vl.c | 19 +++++++------------ tests/test-qemu-opts.c | 20 +++++++++++++++++--- util/qemu-option.c | 9 +++------ 4 files changed, 28 insertions(+), 23 deletions(-) diff --git a/include/qemu/option.h b/include/qemu/option.h index ac69352e0e..f73e0dc7d9 100644 --- a/include/qemu/option.h +++ b/include/qemu/option.h @@ -119,8 +119,7 @@ QemuOpts *qemu_opts_create(QemuOptsList *list, const char *id, int fail_if_exists, Error **errp); void qemu_opts_reset(QemuOptsList *list); void qemu_opts_loc_restore(QemuOpts *opts); -bool qemu_opts_set(QemuOptsList *list, const char *id, - const char *name, const char *value, Error **errp); +bool qemu_opts_set(QemuOptsList *list, const char *name, const char *value, Error **errp); const char *qemu_opts_id(QemuOpts *opts); void qemu_opts_set_id(QemuOpts *opts, char *id); void qemu_opts_del(QemuOpts *opts); diff --git a/softmmu/vl.c b/softmmu/vl.c index 85b23d51be..5571f9ff75 100644 --- a/softmmu/vl.c +++ b/softmmu/vl.c @@ -3388,20 +3388,16 @@ void qemu_init(int argc, char **argv, char **envp) } break; case QEMU_OPTION_kernel: - qemu_opts_set(qemu_find_opts("machine"), NULL, "kernel", optarg, - &error_abort); + qemu_opts_set(qemu_find_opts("machine"), "kernel", optarg, &error_abort); break; case QEMU_OPTION_initrd: - qemu_opts_set(qemu_find_opts("machine"), NULL, "initrd", optarg, - &error_abort); + qemu_opts_set(qemu_find_opts("machine"), "initrd", optarg, &error_abort); break; case QEMU_OPTION_append: - qemu_opts_set(qemu_find_opts("machine"), NULL, "append", optarg, - &error_abort); + qemu_opts_set(qemu_find_opts("machine"), "append", optarg, &error_abort); break; case QEMU_OPTION_dtb: - qemu_opts_set(qemu_find_opts("machine"), NULL, "dtb", optarg, - &error_abort); + qemu_opts_set(qemu_find_opts("machine"), "dtb", optarg, &error_abort); break; case QEMU_OPTION_cdrom: drive_add(IF_DEFAULT, 2, optarg, CDROM_OPTS); @@ -3511,8 +3507,7 @@ void qemu_init(int argc, char **argv, char **envp) } break; case QEMU_OPTION_bios: - qemu_opts_set(qemu_find_opts("machine"), NULL, "firmware", optarg, - &error_abort); + qemu_opts_set(qemu_find_opts("machine"), "firmware", optarg, &error_abort); break; case QEMU_OPTION_singlestep: singlestep = 1; @@ -4395,9 +4390,9 @@ void qemu_init(int argc, char **argv, char **envp) if (default_net) { QemuOptsList *net = qemu_find_opts("net"); - qemu_opts_set(net, NULL, "type", "nic", &error_abort); + qemu_opts_parse(net, "nic", true, &error_abort); #ifdef CONFIG_SLIRP - qemu_opts_set(net, NULL, "type", "user", &error_abort); + qemu_opts_parse(net, "user", true, &error_abort); #endif } diff --git a/tests/test-qemu-opts.c b/tests/test-qemu-opts.c index 297ffe79dd..2aab831d10 100644 --- a/tests/test-qemu-opts.c +++ b/tests/test-qemu-opts.c @@ -84,11 +84,25 @@ static QemuOptsList opts_list_03 = { }, }; +static QemuOptsList opts_list_04 = { + .name = "opts_list_04", + .head = QTAILQ_HEAD_INITIALIZER(opts_list_04.head), + .merge_lists = true, + .desc = { + { + .name = "str3", + .type = QEMU_OPT_STRING, + }, + { /* end of list */ } + }, +}; + static void register_opts(void) { qemu_add_opts(&opts_list_01); qemu_add_opts(&opts_list_02); qemu_add_opts(&opts_list_03); + qemu_add_opts(&opts_list_04); } static void test_find_unknown_opts(void) @@ -402,17 +416,17 @@ static void test_qemu_opts_set(void) QemuOpts *opts; const char *opt; - list = qemu_find_opts("opts_list_01"); + list = qemu_find_opts("opts_list_04"); g_assert(list != NULL); g_assert(QTAILQ_EMPTY(&list->head)); - g_assert_cmpstr(list->name, ==, "opts_list_01"); + g_assert_cmpstr(list->name, ==, "opts_list_04"); /* should not find anything at this point */ opts = qemu_opts_find(list, NULL); g_assert(opts == NULL); /* implicitly create opts and set str3 value */ - qemu_opts_set(list, NULL, "str3", "value", &error_abort); + qemu_opts_set(list, "str3", "value", &error_abort); g_assert(!QTAILQ_EMPTY(&list->head)); /* get the just created opts */ diff --git a/util/qemu-option.c b/util/qemu-option.c index acefbc23fa..25792159ba 100644 --- a/util/qemu-option.c +++ b/util/qemu-option.c @@ -670,15 +670,12 @@ void qemu_opts_loc_restore(QemuOpts *opts) loc_restore(&opts->loc); } -bool qemu_opts_set(QemuOptsList *list, const char *id, - const char *name, const char *value, Error **errp) +bool qemu_opts_set(QemuOptsList *list, const char *name, const char *value, Error **errp) { QemuOpts *opts; - opts = qemu_opts_create(list, id, 1, errp); - if (!opts) { - return false; - } + assert(list->merge_lists); + opts = qemu_opts_create(list, NULL, 0, &error_abort); return qemu_opt_set(opts, name, value, errp); } From d8a798f62e0c0bc5f7bf4968f52ed5e9a6357465 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 21 Oct 2020 06:01:30 -0400 Subject: [PATCH 062/113] vl: create "-net nic -net user" default earlier Create it together with other default backends, even though the processing is done later. Reviewed-by: Igor Mammedov Signed-off-by: Paolo Bonzini --- softmmu/vl.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/softmmu/vl.c b/softmmu/vl.c index 5571f9ff75..a4b87ae742 100644 --- a/softmmu/vl.c +++ b/softmmu/vl.c @@ -4253,6 +4253,14 @@ void qemu_init(int argc, char **argv, char **envp) monitor_parse("vc:80Cx24C", "readline", false); } + if (default_net) { + QemuOptsList *net = qemu_find_opts("net"); + qemu_opts_parse(net, "nic", true, &error_abort); +#ifdef CONFIG_SLIRP + qemu_opts_parse(net, "user", true, &error_abort); +#endif + } + #if defined(CONFIG_VNC) if (!QTAILQ_EMPTY(&(qemu_find_opts("vnc")->head))) { display_remote++; @@ -4388,14 +4396,6 @@ void qemu_init(int argc, char **argv, char **envp) semihosting_arg_fallback(kernel_filename, kernel_cmdline); } - if (default_net) { - QemuOptsList *net = qemu_find_opts("net"); - qemu_opts_parse(net, "nic", true, &error_abort); -#ifdef CONFIG_SLIRP - qemu_opts_parse(net, "user", true, &error_abort); -#endif - } - if (net_init_clients(&err) < 0) { error_report_err(err); exit(1); From 8a7459744c7ab29b92dfcc7784dd76befc9b0b43 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 21 Oct 2020 10:25:06 -0400 Subject: [PATCH 063/113] vl: load plugins as late as possible MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There is no need to load plugins in the middle of default device processing, move -plugin handling just before preconfig is entered. Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Igor Mammedov Signed-off-by: Paolo Bonzini --- softmmu/vl.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/softmmu/vl.c b/softmmu/vl.c index a4b87ae742..cb4b870f09 100644 --- a/softmmu/vl.c +++ b/softmmu/vl.c @@ -125,6 +125,7 @@ static const char *boot_order; static const char *boot_once; static const char *incoming; static const char *loadvm; +static QemuPluginList plugin_list = QTAILQ_HEAD_INITIALIZER(plugin_list); enum vga_retrace_method vga_retrace_method = VGA_RETRACE_DUMB; static int mem_prealloc; /* force preallocation of physical target memory */ int display_opengl; @@ -3078,6 +3079,11 @@ static void qemu_init_board(void) create_default_memdev(current_machine, mem_path); } + /* process plugin before CPUs are created, but once -smp has been parsed */ + if (qemu_plugin_load_list(&plugin_list)) { + exit(1); + } + machine_run_board_init(current_machine); /* @@ -3212,7 +3218,6 @@ void qemu_init(int argc, char **argv, char **envp) Error *err = NULL; bool have_custom_ram_size; BlockdevOptionsQueue bdo_queue = QSIMPLEQ_HEAD_INITIALIZER(bdo_queue); - QemuPluginList plugin_list = QTAILQ_HEAD_INITIALIZER(plugin_list); qemu_add_opts(&qemu_drive_opts); qemu_add_drive_opts(&qemu_legacy_drive_opts); @@ -4182,11 +4187,6 @@ void qemu_init(int argc, char **argv, char **envp) machine_class->default_machine_opts, 0); } - /* process plugin before CPUs are created, but once -smp has been parsed */ - if (qemu_plugin_load_list(&plugin_list)) { - exit(1); - } - qemu_opts_foreach(qemu_find_opts("device"), default_driver_check, NULL, NULL); qemu_opts_foreach(qemu_find_opts("global"), From f650266bc53a0195fc227e4ba8e816ac6f2d19e8 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 21 Oct 2020 06:22:39 -0400 Subject: [PATCH 064/113] vl: extract default devices to separate functions Reviewed-by: Igor Mammedov Signed-off-by: Paolo Bonzini --- softmmu/vl.c | 216 +++++++++++++++++++++++++++------------------------ 1 file changed, 114 insertions(+), 102 deletions(-) diff --git a/softmmu/vl.c b/softmmu/vl.c index cb4b870f09..1a80a9a68d 100644 --- a/softmmu/vl.c +++ b/softmmu/vl.c @@ -125,7 +125,9 @@ static const char *boot_order; static const char *boot_once; static const char *incoming; static const char *loadvm; +static int display_remote; static QemuPluginList plugin_list = QTAILQ_HEAD_INITIALIZER(plugin_list); +static bool nographic = false; enum vga_retrace_method vga_retrace_method = VGA_RETRACE_DUMB; static int mem_prealloc; /* force preallocation of physical target memory */ int display_opengl; @@ -147,6 +149,7 @@ static int rtc_host_datetime_offset = -1; /* valid & used only with RTC_BASE_DATETIME */ QEMUClockType rtc_clock; int vga_interface_type = VGA_NONE; +static const char *vga_model = NULL; static DisplayOptions dpy; static int num_serial_hds; static Chardev **serial_hds; @@ -2224,6 +2227,115 @@ static int foreach_device_config(int type, int (*func)(const char *cmdline)) return 0; } +static void qemu_disable_default_devices(void) +{ + MachineClass *machine_class = MACHINE_GET_CLASS(current_machine); + + qemu_opts_foreach(qemu_find_opts("device"), + default_driver_check, NULL, NULL); + qemu_opts_foreach(qemu_find_opts("global"), + default_driver_check, NULL, NULL); + + if (!vga_model && !default_vga) { + vga_interface_type = VGA_DEVICE; + } + if (!has_defaults || machine_class->no_serial) { + default_serial = 0; + } + if (!has_defaults || machine_class->no_parallel) { + default_parallel = 0; + } + if (!has_defaults || machine_class->no_floppy) { + default_floppy = 0; + } + if (!has_defaults || machine_class->no_cdrom) { + default_cdrom = 0; + } + if (!has_defaults || machine_class->no_sdcard) { + default_sdcard = 0; + } + if (!has_defaults) { + default_monitor = 0; + default_net = 0; + default_vga = 0; + } +} + +static void qemu_create_default_devices(void) +{ + MachineClass *machine_class = MACHINE_GET_CLASS(current_machine); + + if (is_daemonized()) { + /* According to documentation and historically, -nographic redirects + * serial port, parallel port and monitor to stdio, which does not work + * with -daemonize. We can redirect these to null instead, but since + * -nographic is legacy, let's just error out. + * We disallow -nographic only if all other ports are not redirected + * explicitly, to not break existing legacy setups which uses + * -nographic _and_ redirects all ports explicitly - this is valid + * usage, -nographic is just a no-op in this case. + */ + if (nographic + && (default_parallel || default_serial || default_monitor)) { + error_report("-nographic cannot be used with -daemonize"); + exit(1); + } + } + + if (nographic) { + if (default_parallel) + add_device_config(DEV_PARALLEL, "null"); + if (default_serial && default_monitor) { + add_device_config(DEV_SERIAL, "mon:stdio"); + } else { + if (default_serial) + add_device_config(DEV_SERIAL, "stdio"); + if (default_monitor) + monitor_parse("stdio", "readline", false); + } + } else { + if (default_serial) + add_device_config(DEV_SERIAL, "vc:80Cx24C"); + if (default_parallel) + add_device_config(DEV_PARALLEL, "vc:80Cx24C"); + if (default_monitor) + monitor_parse("vc:80Cx24C", "readline", false); + } + + if (default_net) { + QemuOptsList *net = qemu_find_opts("net"); + qemu_opts_parse(net, "nic", true, &error_abort); +#ifdef CONFIG_SLIRP + qemu_opts_parse(net, "user", true, &error_abort); +#endif + } + +#if defined(CONFIG_VNC) + if (!QTAILQ_EMPTY(&(qemu_find_opts("vnc")->head))) { + display_remote++; + } +#endif + if (dpy.type == DISPLAY_TYPE_DEFAULT && !display_remote) { + if (!qemu_display_find_default(&dpy)) { + dpy.type = DISPLAY_TYPE_NONE; +#if defined(CONFIG_VNC) + vnc_parse("localhost:0,to=99,id=default", &error_abort); +#endif + } + } + if (dpy.type == DISPLAY_TYPE_DEFAULT) { + dpy.type = DISPLAY_TYPE_NONE; + } + + /* If no default VGA is requested, the default is "none". */ + if (default_vga) { + vga_model = get_default_vga_model(machine_class); + } + if (vga_model) { + select_vgahw(machine_class, vga_model); + } +} + static int serial_parse(const char *devname) { int index = num_serial_hds; @@ -3208,10 +3320,7 @@ void qemu_init(int argc, char **argv, char **envp) int optind; const char *optarg; MachineClass *machine_class; - const char *vga_model = NULL; bool userconfig = true; - bool nographic = false; - int display_remote = 0; ram_addr_t maxram_size; uint64_t ram_slots = 0; FILE *vmstate_dump_file = NULL; @@ -4187,97 +4296,8 @@ void qemu_init(int argc, char **argv, char **envp) machine_class->default_machine_opts, 0); } - qemu_opts_foreach(qemu_find_opts("device"), - default_driver_check, NULL, NULL); - qemu_opts_foreach(qemu_find_opts("global"), - default_driver_check, NULL, NULL); - - if (!vga_model && !default_vga) { - vga_interface_type = VGA_DEVICE; - } - if (!has_defaults || machine_class->no_serial) { - default_serial = 0; - } - if (!has_defaults || machine_class->no_parallel) { - default_parallel = 0; - } - if (!has_defaults || machine_class->no_floppy) { - default_floppy = 0; - } - if (!has_defaults || machine_class->no_cdrom) { - default_cdrom = 0; - } - if (!has_defaults || machine_class->no_sdcard) { - default_sdcard = 0; - } - if (!has_defaults) { - default_monitor = 0; - default_net = 0; - default_vga = 0; - } - - if (is_daemonized()) { - /* According to documentation and historically, -nographic redirects - * serial port, parallel port and monitor to stdio, which does not work - * with -daemonize. We can redirect these to null instead, but since - * -nographic is legacy, let's just error out. - * We disallow -nographic only if all other ports are not redirected - * explicitly, to not break existing legacy setups which uses - * -nographic _and_ redirects all ports explicitly - this is valid - * usage, -nographic is just a no-op in this case. - */ - if (nographic - && (default_parallel || default_serial || default_monitor)) { - error_report("-nographic cannot be used with -daemonize"); - exit(1); - } - } - - if (nographic) { - if (default_parallel) - add_device_config(DEV_PARALLEL, "null"); - if (default_serial && default_monitor) { - add_device_config(DEV_SERIAL, "mon:stdio"); - } else { - if (default_serial) - add_device_config(DEV_SERIAL, "stdio"); - if (default_monitor) - monitor_parse("stdio", "readline", false); - } - } else { - if (default_serial) - add_device_config(DEV_SERIAL, "vc:80Cx24C"); - if (default_parallel) - add_device_config(DEV_PARALLEL, "vc:80Cx24C"); - if (default_monitor) - monitor_parse("vc:80Cx24C", "readline", false); - } - - if (default_net) { - QemuOptsList *net = qemu_find_opts("net"); - qemu_opts_parse(net, "nic", true, &error_abort); -#ifdef CONFIG_SLIRP - qemu_opts_parse(net, "user", true, &error_abort); -#endif - } - -#if defined(CONFIG_VNC) - if (!QTAILQ_EMPTY(&(qemu_find_opts("vnc")->head))) { - display_remote++; - } -#endif - if (dpy.type == DISPLAY_TYPE_DEFAULT && !display_remote) { - if (!qemu_display_find_default(&dpy)) { - dpy.type = DISPLAY_TYPE_NONE; -#if defined(CONFIG_VNC) - vnc_parse("localhost:0,to=99,id=default", &error_abort); -#endif - } - } - if (dpy.type == DISPLAY_TYPE_DEFAULT) { - dpy.type = DISPLAY_TYPE_NONE; - } - + qemu_disable_default_devices(); + qemu_create_default_devices(); if ((alt_grab || ctrl_grab) && dpy.type != DISPLAY_TYPE_SDL) { error_report("-alt-grab and -ctrl-grab are only valid " "for SDL, ignoring option"); @@ -4423,14 +4443,6 @@ void qemu_init(int argc, char **argv, char **envp) qemu_semihosting_connect_chardevs(); qemu_semihosting_console_init(); - /* If no default VGA is requested, the default is "none". */ - if (default_vga) { - vga_model = get_default_vga_model(machine_class); - } - if (vga_model) { - select_vgahw(machine_class, vga_model); - } - /* This checkpoint is required by replay to separate prior clock reading from the other reads, because timer polling functions query clock values from the log. */ From a3ef9bfb8808f615bd77dcc2ec5332e4cf670f92 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 21 Oct 2020 07:19:34 -0400 Subject: [PATCH 065/113] vl: move CHECKPOINT_INIT after preconfig MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move CHECKPOINT_INIT right before the machine initialization is completed. Everything before is essentially an extension of command line parsing. Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Igor Mammedov Signed-off-by: Paolo Bonzini --- hw/core/machine.c | 5 +++++ softmmu/vl.c | 5 ----- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/hw/core/machine.c b/hw/core/machine.c index 5a65b9d88e..71a0e375ab 100644 --- a/hw/core/machine.c +++ b/hw/core/machine.c @@ -1110,6 +1110,11 @@ void machine_run_board_init(MachineState *machine) ObjectClass *oc = object_class_by_name(machine->cpu_type); CPUClass *cc; + /* This checkpoint is required by replay to separate prior clock + reading from the other reads, because timer polling functions query + clock values from the log. */ + replay_checkpoint(CHECKPOINT_INIT); + if (machine->ram_memdev_id) { Object *o; o = object_resolve_path_type(machine->ram_memdev_id, diff --git a/softmmu/vl.c b/softmmu/vl.c index 1a80a9a68d..91ef21833b 100644 --- a/softmmu/vl.c +++ b/softmmu/vl.c @@ -4443,11 +4443,6 @@ void qemu_init(int argc, char **argv, char **envp) qemu_semihosting_connect_chardevs(); qemu_semihosting_console_init(); - /* This checkpoint is required by replay to separate prior clock - reading from the other reads, because timer polling functions query - clock values from the log. */ - replay_checkpoint(CHECKPOINT_INIT); - current_machine->boot_order = boot_order; /* parse features once if machine provides default cpu_type */ From 644186572dd3cb4603ef1a6cf83a81fd8c0b7904 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 21 Oct 2020 10:41:18 -0400 Subject: [PATCH 066/113] vl: separate qemu_create_early_backends "Early" backends are created before the machine and can be used as machine options. Reviewed-by: Igor Mammedov Signed-off-by: Paolo Bonzini --- softmmu/vl.c | 123 +++++++++++++++++++++++++++------------------------ 1 file changed, 65 insertions(+), 58 deletions(-) diff --git a/softmmu/vl.c b/softmmu/vl.c index 91ef21833b..aafcbec356 100644 --- a/softmmu/vl.c +++ b/softmmu/vl.c @@ -117,6 +117,14 @@ #define MAX_VIRTIO_CONSOLES 1 +typedef struct BlockdevOptionsQueueEntry { + BlockdevOptions *bdo; + Location loc; + QSIMPLEQ_ENTRY(BlockdevOptionsQueueEntry) entry; +} BlockdevOptionsQueueEntry; + +typedef QSIMPLEQ_HEAD(, BlockdevOptionsQueueEntry) BlockdevOptionsQueue; + static const char *cpu_option; static const char *data_dir[16]; static int data_dir_idx; @@ -126,7 +134,9 @@ static const char *boot_once; static const char *incoming; static const char *loadvm; static int display_remote; +static int snapshot; static QemuPluginList plugin_list = QTAILQ_HEAD_INITIALIZER(plugin_list); +static BlockdevOptionsQueue bdo_queue = QSIMPLEQ_HEAD_INITIALIZER(bdo_queue); static bool nographic = false; enum vga_retrace_method vga_retrace_method = VGA_RETRACE_DUMB; static int mem_prealloc; /* force preallocation of physical target memory */ @@ -1043,14 +1053,6 @@ static void default_drive(int enable, int snapshot, BlockInterfaceType type, } -typedef struct BlockdevOptionsQueueEntry { - BlockdevOptions *bdo; - Location loc; - QSIMPLEQ_ENTRY(BlockdevOptionsQueueEntry) entry; -} BlockdevOptionsQueueEntry; - -typedef QSIMPLEQ_HEAD(, BlockdevOptionsQueueEntry) BlockdevOptionsQueue; - static void configure_blockdev(BlockdevOptionsQueue *bdo_queue, MachineClass *machine_class, int snapshot) { @@ -2644,7 +2646,7 @@ static int machine_set_property(void *opaque, * cannot be created here, as it depends on the chardev * already existing. */ -static bool object_create_initial(const char *type, QemuOpts *opts) +static bool object_create_early(const char *type, QemuOpts *opts) { if (user_creatable_print_help(type, opts)) { exit(0); @@ -2700,6 +2702,58 @@ static bool object_create_initial(const char *type, QemuOpts *opts) return true; } +static void qemu_create_early_backends(void) +{ + MachineClass *machine_class = MACHINE_GET_CLASS(current_machine); + + if ((alt_grab || ctrl_grab) && dpy.type != DISPLAY_TYPE_SDL) { + error_report("-alt-grab and -ctrl-grab are only valid " + "for SDL, ignoring option"); + } + if (dpy.has_window_close && + (dpy.type != DISPLAY_TYPE_GTK && dpy.type != DISPLAY_TYPE_SDL)) { + error_report("-no-quit is only valid for GTK and SDL, " + "ignoring option"); + } + + qemu_display_early_init(&dpy); + qemu_console_early_init(); + + if (dpy.has_gl && dpy.gl != DISPLAYGL_MODE_OFF && display_opengl == 0) { +#if defined(CONFIG_OPENGL) + error_report("OpenGL is not supported by the display"); +#else + error_report("OpenGL support is disabled"); +#endif + exit(1); + } + + qemu_opts_foreach(qemu_find_opts("object"), + user_creatable_add_opts_foreach, + object_create_early, &error_fatal); + + /* spice needs the timers to be initialized by this point */ + /* spice must initialize before audio as it changes the default auiodev */ + /* spice must initialize before chardevs (for spicevmc and spiceport) */ + qemu_spice.init(); + + qemu_opts_foreach(qemu_find_opts("chardev"), + chardev_init_func, NULL, &error_fatal); + +#ifdef CONFIG_VIRTFS + qemu_opts_foreach(qemu_find_opts("fsdev"), + fsdev_init_func, NULL, &error_fatal); +#endif + + /* + * Note: we need to create audio and block backends before + * machine_set_property(), so machine properties can refer to + * them. + */ + configure_blockdev(&bdo_queue, machine_class, snapshot); + audio_init_audiodevs(); +} + /* * The remainder of object creation happens after the @@ -2707,7 +2761,7 @@ static bool object_create_initial(const char *type, QemuOpts *opts) */ static bool object_create_delayed(const char *type, QemuOpts *opts) { - return !object_create_initial(type, opts); + return !object_create_early(type, opts); } @@ -3313,7 +3367,6 @@ static void qemu_machine_creation_done(void) void qemu_init(int argc, char **argv, char **envp) { - int snapshot = 0; QemuOpts *opts, *machine_opts; QemuOpts *icount_opts = NULL, *accel_opts = NULL; QemuOptsList *olist; @@ -3326,7 +3379,6 @@ void qemu_init(int argc, char **argv, char **envp) FILE *vmstate_dump_file = NULL; Error *err = NULL; bool have_custom_ram_size; - BlockdevOptionsQueue bdo_queue = QSIMPLEQ_HEAD_INITIALIZER(bdo_queue); qemu_add_opts(&qemu_drive_opts); qemu_add_drive_opts(&qemu_legacy_drive_opts); @@ -4298,52 +4350,7 @@ void qemu_init(int argc, char **argv, char **envp) qemu_disable_default_devices(); qemu_create_default_devices(); - if ((alt_grab || ctrl_grab) && dpy.type != DISPLAY_TYPE_SDL) { - error_report("-alt-grab and -ctrl-grab are only valid " - "for SDL, ignoring option"); - } - if (dpy.has_window_close && - (dpy.type != DISPLAY_TYPE_GTK && dpy.type != DISPLAY_TYPE_SDL)) { - error_report("-no-quit is only valid for GTK and SDL, " - "ignoring option"); - } - - qemu_display_early_init(&dpy); - qemu_console_early_init(); - - if (dpy.has_gl && dpy.gl != DISPLAYGL_MODE_OFF && display_opengl == 0) { -#if defined(CONFIG_OPENGL) - error_report("OpenGL is not supported by the display"); -#else - error_report("OpenGL support is disabled"); -#endif - exit(1); - } - - qemu_opts_foreach(qemu_find_opts("object"), - user_creatable_add_opts_foreach, - object_create_initial, &error_fatal); - - /* spice needs the timers to be initialized by this point */ - /* spice must initialize before audio as it changes the default auiodev */ - /* spice must initialize before chardevs (for spicevmc and spiceport) */ - qemu_spice.init(); - - qemu_opts_foreach(qemu_find_opts("chardev"), - chardev_init_func, NULL, &error_fatal); - -#ifdef CONFIG_VIRTFS - qemu_opts_foreach(qemu_find_opts("fsdev"), - fsdev_init_func, NULL, &error_fatal); -#endif - - /* - * Note: we need to create audio and block backends before - * machine_set_property(), so machine properties can refer to - * them. - */ - configure_blockdev(&bdo_queue, machine_class, snapshot); - audio_init_audiodevs(); + qemu_create_early_backends(); machine_opts = qemu_get_machine_opts(); qemu_opt_foreach(machine_opts, machine_set_property, current_machine, From 07a91b1ac6c7edc0009de1abcd55ff4f6bdb9a14 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Tue, 27 Oct 2020 09:36:52 -0400 Subject: [PATCH 067/113] vl: separate qemu_create_late_backends "Late" backends are created after the machine. Reviewed-by: Igor Mammedov Signed-off-by: Paolo Bonzini --- softmmu/vl.c | 64 ++++++++++++++++++++++++++-------------------------- 1 file changed, 32 insertions(+), 32 deletions(-) diff --git a/softmmu/vl.c b/softmmu/vl.c index aafcbec356..d9fe9f63c0 100644 --- a/softmmu/vl.c +++ b/softmmu/vl.c @@ -2759,11 +2759,41 @@ static void qemu_create_early_backends(void) * The remainder of object creation happens after the * creation of chardev, fsdev, net clients and device data types. */ -static bool object_create_delayed(const char *type, QemuOpts *opts) +static bool object_create_late(const char *type, QemuOpts *opts) { return !object_create_early(type, opts); } +static void qemu_create_late_backends(void) +{ + if (qtest_chrdev) { + qtest_server_init(qtest_chrdev, qtest_log, &error_fatal); + } + + net_init_clients(&error_fatal); + + qemu_opts_foreach(qemu_find_opts("object"), + user_creatable_add_opts_foreach, + object_create_late, &error_fatal); + + if (tpm_init() < 0) { + exit(1); + } + + qemu_opts_foreach(qemu_find_opts("mon"), + mon_init_func, NULL, &error_fatal); + + if (foreach_device_config(DEV_SERIAL, serial_parse) < 0) + exit(1); + if (foreach_device_config(DEV_PARALLEL, parallel_parse) < 0) + exit(1); + if (foreach_device_config(DEV_DEBUGCON, debugcon_parse) < 0) + exit(1); + + /* now chardevs have been created we may have semihosting to connect */ + qemu_semihosting_connect_chardevs(); + qemu_semihosting_console_init(); +} static bool set_memory_options(uint64_t *ram_slots, ram_addr_t *maxram_size, MachineClass *mc) @@ -3377,7 +3407,6 @@ void qemu_init(int argc, char **argv, char **envp) ram_addr_t maxram_size; uint64_t ram_slots = 0; FILE *vmstate_dump_file = NULL; - Error *err = NULL; bool have_custom_ram_size; qemu_add_opts(&qemu_drive_opts); @@ -4392,10 +4421,6 @@ void qemu_init(int argc, char **argv, char **envp) */ migration_object_init(); - if (qtest_chrdev) { - qtest_server_init(qtest_chrdev, qtest_log, &error_fatal); - } - opts = qemu_opts_find(qemu_find_opts("boot-opts"), NULL); if (opts) { boot_order = qemu_opt_get(opts, "order"); @@ -4423,32 +4448,7 @@ void qemu_init(int argc, char **argv, char **envp) semihosting_arg_fallback(kernel_filename, kernel_cmdline); } - if (net_init_clients(&err) < 0) { - error_report_err(err); - exit(1); - } - - qemu_opts_foreach(qemu_find_opts("object"), - user_creatable_add_opts_foreach, - object_create_delayed, &error_fatal); - - if (tpm_init() < 0) { - exit(1); - } - - qemu_opts_foreach(qemu_find_opts("mon"), - mon_init_func, NULL, &error_fatal); - - if (foreach_device_config(DEV_SERIAL, serial_parse) < 0) - exit(1); - if (foreach_device_config(DEV_PARALLEL, parallel_parse) < 0) - exit(1); - if (foreach_device_config(DEV_DEBUGCON, debugcon_parse) < 0) - exit(1); - - /* now chardevs have been created we may have semihosting to connect */ - qemu_semihosting_connect_chardevs(); - qemu_semihosting_console_init(); + qemu_create_late_backends(); current_machine->boot_order = boot_order; From f5c9fcb82d37fe26aca1b8f68e1439ca3fd37587 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Tue, 27 Oct 2020 11:04:37 -0400 Subject: [PATCH 068/113] vl: separate qemu_create_machine Reviewed-by: Igor Mammedov Signed-off-by: Paolo Bonzini --- softmmu/vl.c | 113 +++++++++++++++++++++++++++------------------------ 1 file changed, 60 insertions(+), 53 deletions(-) diff --git a/softmmu/vl.c b/softmmu/vl.c index d9fe9f63c0..5af52454ee 100644 --- a/softmmu/vl.c +++ b/softmmu/vl.c @@ -133,6 +133,8 @@ static const char *boot_order; static const char *boot_once; static const char *incoming; static const char *loadvm; +static ram_addr_t maxram_size; +static uint64_t ram_slots; static int display_remote; static int snapshot; static QemuPluginList plugin_list = QTAILQ_HEAD_INITIALIZER(plugin_list); @@ -2795,8 +2797,13 @@ static void qemu_create_late_backends(void) qemu_semihosting_console_init(); } -static bool set_memory_options(uint64_t *ram_slots, ram_addr_t *maxram_size, - MachineClass *mc) +static bool have_custom_ram_size(void) +{ + QemuOpts *opts = qemu_find_opts_singleton("memory"); + return !!qemu_opt_get_size(opts, "size", 0); +} + +static void set_memory_options(MachineClass *mc) { uint64_t sz; const char *mem_str; @@ -2846,7 +2853,7 @@ static bool set_memory_options(uint64_t *ram_slots, ram_addr_t *maxram_size, /* store value for the future use */ qemu_opt_set_number(opts, "size", ram_size, &error_abort); - *maxram_size = ram_size; + maxram_size = ram_size; if (qemu_opt_get(opts, "maxmem")) { uint64_t slots; @@ -2867,15 +2874,59 @@ static bool set_memory_options(uint64_t *ram_slots, ram_addr_t *maxram_size, exit(EXIT_FAILURE); } - *maxram_size = sz; - *ram_slots = slots; + maxram_size = sz; + ram_slots = slots; } else if (qemu_opt_get(opts, "slots")) { error_report("invalid -m option value: missing 'maxmem' option"); exit(EXIT_FAILURE); } loc_pop(&loc); - return !!mem_str; +} + +static void qemu_create_machine(MachineClass *machine_class) +{ + object_set_machine_compat_props(machine_class->compat_props); + + set_memory_options(machine_class); + + current_machine = MACHINE(object_new_with_class(OBJECT_CLASS(machine_class))); + if (machine_help_func(qemu_get_machine_opts(), current_machine)) { + exit(0); + } + object_property_add_child(object_get_root(), "machine", + OBJECT(current_machine)); + object_property_add_child(container_get(OBJECT(current_machine), + "/unattached"), + "sysbus", OBJECT(sysbus_get_default())); + + if (machine_class->minimum_page_bits) { + if (!set_preferred_target_page_bits(machine_class->minimum_page_bits)) { + /* This would be a board error: specifying a minimum smaller than + * a target's compile-time fixed setting. + */ + g_assert_not_reached(); + } + } + + cpu_exec_init_all(); + page_size_init(); + + if (machine_class->hw_version) { + qemu_set_hw_version(machine_class->hw_version); + } + + machine_smp_parse(current_machine, + qemu_opts_find(qemu_find_opts("smp-opts"), NULL), &error_fatal); + + /* + * Get the default machine options from the machine if it is not already + * specified either by the configuration file or by the command line. + */ + if (machine_class->default_machine_opts) { + qemu_opts_set_defaults(qemu_find_opts("machine"), + machine_class->default_machine_opts, 0); + } } static int global_init_func(void *opaque, QemuOpts *opts, Error **errp) @@ -3404,10 +3455,7 @@ void qemu_init(int argc, char **argv, char **envp) const char *optarg; MachineClass *machine_class; bool userconfig = true; - ram_addr_t maxram_size; - uint64_t ram_slots = 0; FILE *vmstate_dump_file = NULL; - bool have_custom_ram_size; qemu_add_opts(&qemu_drive_opts); qemu_add_drive_opts(&qemu_legacy_drive_opts); @@ -4333,49 +4381,7 @@ void qemu_init(int argc, char **argv, char **envp) configure_rtc(qemu_find_opts_singleton("rtc")); - machine_class = select_machine(); - object_set_machine_compat_props(machine_class->compat_props); - - have_custom_ram_size = set_memory_options(&ram_slots, &maxram_size, - machine_class); - - current_machine = MACHINE(object_new_with_class(OBJECT_CLASS(machine_class))); - if (machine_help_func(qemu_get_machine_opts(), current_machine)) { - exit(0); - } - object_property_add_child(object_get_root(), "machine", - OBJECT(current_machine)); - object_property_add_child(container_get(OBJECT(current_machine), - "/unattached"), - "sysbus", OBJECT(sysbus_get_default())); - - if (machine_class->minimum_page_bits) { - if (!set_preferred_target_page_bits(machine_class->minimum_page_bits)) { - /* This would be a board error: specifying a minimum smaller than - * a target's compile-time fixed setting. - */ - g_assert_not_reached(); - } - } - - cpu_exec_init_all(); - page_size_init(); - - if (machine_class->hw_version) { - qemu_set_hw_version(machine_class->hw_version); - } - - machine_smp_parse(current_machine, - qemu_opts_find(qemu_find_opts("smp-opts"), NULL), &error_fatal); - - /* - * Get the default machine options from the machine if it is not already - * specified either by the configuration file or by the command line. - */ - if (machine_class->default_machine_opts) { - qemu_opts_set_defaults(qemu_find_opts("machine"), - machine_class->default_machine_opts, 0); - } + qemu_create_machine(select_machine()); qemu_disable_default_devices(); qemu_create_default_devices(); @@ -4410,6 +4416,7 @@ void qemu_init(int argc, char **argv, char **envp) * called from configure_accelerator(). */ + machine_class = MACHINE_GET_CLASS(current_machine); if (!qtest_enabled() && machine_class->deprecation_reason) { error_report("Machine type '%s' is deprecated: %s", machine_class->name, machine_class->deprecation_reason); @@ -4470,7 +4477,7 @@ void qemu_init(int argc, char **argv, char **envp) exit(EXIT_FAILURE); } backend_size = object_property_get_uint(backend, "size", &error_abort); - if (have_custom_ram_size && backend_size != ram_size) { + if (have_custom_ram_size() && backend_size != ram_size) { error_report("Size specified by -m option must match size of " "explicitly specified 'memory-backend' property"); exit(EXIT_FAILURE); From 7a84268dc9be3456e8d7d2fcc5ad0e3dec50899d Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Tue, 27 Oct 2020 11:08:04 -0400 Subject: [PATCH 069/113] vl: separate qemu_apply_machine_options Signed-off-by: Paolo Bonzini --- softmmu/vl.c | 81 +++++++++++++++++++++++++++++----------------------- 1 file changed, 45 insertions(+), 36 deletions(-) diff --git a/softmmu/vl.c b/softmmu/vl.c index 5af52454ee..acf09b2040 100644 --- a/softmmu/vl.c +++ b/softmmu/vl.c @@ -2704,6 +2704,49 @@ static bool object_create_early(const char *type, QemuOpts *opts) return true; } +static void qemu_apply_machine_options(void) +{ + MachineClass *machine_class = MACHINE_GET_CLASS(current_machine); + QemuOpts *machine_opts = qemu_get_machine_opts(); + QemuOpts *opts; + + qemu_opt_foreach(machine_opts, machine_set_property, current_machine, + &error_fatal); + current_machine->ram_size = ram_size; + current_machine->maxram_size = maxram_size; + current_machine->ram_slots = ram_slots; + + opts = qemu_opts_find(qemu_find_opts("boot-opts"), NULL); + if (opts) { + boot_order = qemu_opt_get(opts, "order"); + if (boot_order) { + validate_bootdevices(boot_order, &error_fatal); + } + + boot_once = qemu_opt_get(opts, "once"); + if (boot_once) { + validate_bootdevices(boot_once, &error_fatal); + } + + boot_menu = qemu_opt_get_bool(opts, "menu", boot_menu); + boot_strict = qemu_opt_get_bool(opts, "strict", false); + } + + if (!boot_order) { + boot_order = machine_class->default_boot_order; + } + + current_machine->boot_order = boot_order; + + if (semihosting_enabled() && !semihosting_get_argc()) { + const char *kernel_filename = qemu_opt_get(machine_opts, "kernel"); + const char *kernel_cmdline = qemu_opt_get(machine_opts, "append") ?: ""; + /* fall back to the -kernel/-append */ + semihosting_arg_fallback(kernel_filename, kernel_cmdline); + } + +} + static void qemu_create_early_backends(void) { MachineClass *machine_class = MACHINE_GET_CLASS(current_machine); @@ -3448,7 +3491,7 @@ static void qemu_machine_creation_done(void) void qemu_init(int argc, char **argv, char **envp) { - QemuOpts *opts, *machine_opts; + QemuOpts *opts; QemuOpts *icount_opts = NULL, *accel_opts = NULL; QemuOptsList *olist; int optind; @@ -4387,12 +4430,7 @@ void qemu_init(int argc, char **argv, char **envp) qemu_create_default_devices(); qemu_create_early_backends(); - machine_opts = qemu_get_machine_opts(); - qemu_opt_foreach(machine_opts, machine_set_property, current_machine, - &error_fatal); - current_machine->ram_size = ram_size; - current_machine->maxram_size = maxram_size; - current_machine->ram_slots = ram_slots; + qemu_apply_machine_options(); /* * Note: uses machine properties such as kernel-irqchip, must run @@ -4428,37 +4466,8 @@ void qemu_init(int argc, char **argv, char **envp) */ migration_object_init(); - opts = qemu_opts_find(qemu_find_opts("boot-opts"), NULL); - if (opts) { - boot_order = qemu_opt_get(opts, "order"); - if (boot_order) { - validate_bootdevices(boot_order, &error_fatal); - } - - boot_once = qemu_opt_get(opts, "once"); - if (boot_once) { - validate_bootdevices(boot_once, &error_fatal); - } - - boot_menu = qemu_opt_get_bool(opts, "menu", boot_menu); - boot_strict = qemu_opt_get_bool(opts, "strict", false); - } - - if (!boot_order) { - boot_order = machine_class->default_boot_order; - } - - if (semihosting_enabled() && !semihosting_get_argc()) { - const char *kernel_filename = qemu_opt_get(machine_opts, "kernel"); - const char *kernel_cmdline = qemu_opt_get(machine_opts, "append"); - /* fall back to the -kernel/-append */ - semihosting_arg_fallback(kernel_filename, kernel_cmdline); - } - qemu_create_late_backends(); - current_machine->boot_order = boot_order; - /* parse features once if machine provides default cpu_type */ current_machine->cpu_type = machine_class->default_cpu_type; if (cpu_option) { From b24986e7845594f4ce394403d2b5c15e89ce04f8 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Tue, 27 Oct 2020 11:16:18 -0400 Subject: [PATCH 070/113] vl: separate qemu_resolve_machine_memdev This is a bit nasty: the machine is storing a string and later resolving it. We probably want to remove the memdev property and instead make this a memory-set command. "-M memdev" can be handled a legacy option that is special cased by machine_set_property. Reviewed-by: Igor Mammedov Signed-off-by: Paolo Bonzini --- softmmu/vl.c | 70 +++++++++++++++++++++++++++------------------------- 1 file changed, 37 insertions(+), 33 deletions(-) diff --git a/softmmu/vl.c b/softmmu/vl.c index acf09b2040..891f959572 100644 --- a/softmmu/vl.c +++ b/softmmu/vl.c @@ -2846,6 +2846,42 @@ static bool have_custom_ram_size(void) return !!qemu_opt_get_size(opts, "size", 0); } +static void qemu_resolve_machine_memdev(void) +{ + if (current_machine->ram_memdev_id) { + Object *backend; + ram_addr_t backend_size; + + backend = object_resolve_path_type(current_machine->ram_memdev_id, + TYPE_MEMORY_BACKEND, NULL); + if (!backend) { + error_report("Memory backend '%s' not found", + current_machine->ram_memdev_id); + exit(EXIT_FAILURE); + } + backend_size = object_property_get_uint(backend, "size", &error_abort); + if (have_custom_ram_size() && backend_size != ram_size) { + error_report("Size specified by -m option must match size of " + "explicitly specified 'memory-backend' property"); + exit(EXIT_FAILURE); + } + if (mem_path) { + error_report("'-mem-path' can't be used together with" + "'-machine memory-backend'"); + exit(EXIT_FAILURE); + } + ram_size = backend_size; + } + + if (!xen_enabled()) { + /* On 32-bit hosts, QEMU is limited by virtual address space */ + if (ram_size > (2047 << 20) && HOST_LONG_BITS == 32) { + error_report("at most 2047 MB RAM can be simulated"); + exit(1); + } + } +} + static void set_memory_options(MachineClass *mc) { uint64_t sz; @@ -4474,39 +4510,7 @@ void qemu_init(int argc, char **argv, char **envp) current_machine->cpu_type = parse_cpu_option(cpu_option); } - if (current_machine->ram_memdev_id) { - Object *backend; - ram_addr_t backend_size; - - backend = object_resolve_path_type(current_machine->ram_memdev_id, - TYPE_MEMORY_BACKEND, NULL); - if (!backend) { - error_report("Memory backend '%s' not found", - current_machine->ram_memdev_id); - exit(EXIT_FAILURE); - } - backend_size = object_property_get_uint(backend, "size", &error_abort); - if (have_custom_ram_size() && backend_size != ram_size) { - error_report("Size specified by -m option must match size of " - "explicitly specified 'memory-backend' property"); - exit(EXIT_FAILURE); - } - if (mem_path) { - error_report("'-mem-path' can't be used together with" - "'-machine memory-backend'"); - exit(EXIT_FAILURE); - } - ram_size = backend_size; - } - - if (!xen_enabled()) { - /* On 32-bit hosts, QEMU is limited by virtual address space */ - if (ram_size > (2047 << 20) && HOST_LONG_BITS == 32) { - error_report("at most 2047 MB RAM can be simulated"); - exit(1); - } - } - + qemu_resolve_machine_memdev(); parse_numa_opts(current_machine); /* do monitor/qmp handling at preconfig state if requested */ From 7691bdef693c04e2a0c40846cda089c28016e043 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Tue, 27 Oct 2020 04:07:30 -0400 Subject: [PATCH 071/113] vl: initialize displays before preconfig loop Displays should be available before the monitor starts, so that it is possible to use the graphical console to interact with the monitor itself. This patch is quite ugly, but all this is temporary. The double call to qemu_init_displays will go away as soon we can unify machine initialization between the preconfig and "normal" flows, and so will the preconfig_exit_requested variable (that is only preconfig_requested remains). Reviewed-by: Igor Mammedov Signed-off-by: Paolo Bonzini --- softmmu/vl.c | 57 +++++++++++++++++++++++++++++++++------------------- 1 file changed, 36 insertions(+), 21 deletions(-) diff --git a/softmmu/vl.c b/softmmu/vl.c index 891f959572..6a2972938d 100644 --- a/softmmu/vl.c +++ b/softmmu/vl.c @@ -137,6 +137,7 @@ static ram_addr_t maxram_size; static uint64_t ram_slots; static int display_remote; static int snapshot; +static bool preconfig_requested; static QemuPluginList plugin_list = QTAILQ_HEAD_INITIALIZER(plugin_list); static BlockdevOptionsQueue bdo_queue = QSIMPLEQ_HEAD_INITIALIZER(bdo_queue); static bool nographic = false; @@ -3223,12 +3224,12 @@ static void qemu_validate_options(void) } } - if (loadvm && !preconfig_exit_requested) { + if (loadvm && preconfig_requested) { error_report("'preconfig' and 'loadvm' options are " "mutually exclusive"); exit(EXIT_FAILURE); } - if (incoming && !preconfig_exit_requested) { + if (incoming && preconfig_requested) { error_report("'preconfig' and 'incoming' options are " "mutually exclusive"); exit(EXIT_FAILURE); @@ -3392,6 +3393,28 @@ static void qemu_init_subsystems(void) socket_init(); } +static void qemu_init_displays(void) +{ + DisplayState *ds; + + /* init local displays */ + ds = init_displaystate(); + qemu_display_init(ds, &dpy); + + /* must be after terminal init, SDL library changes signal handlers */ + os_setup_signal_handling(); + + /* init remote displays */ +#ifdef CONFIG_VNC + qemu_opts_foreach(qemu_find_opts("vnc"), + vnc_init_func, NULL, &error_fatal); +#endif + + if (using_spice) { + qemu_spice.display_init(); + } +} + /* * Called after leaving preconfig state. From here on runstate is * RUN_STATE_PRELAUNCH or RUN_STATE_INMIGRATE. @@ -3450,8 +3473,6 @@ static void qemu_create_cli_devices(void) static void qemu_machine_creation_done(void) { - DisplayState *ds; - cpu_synchronize_all_post_init(); /* Did we create any drives that we failed to create a device for? */ @@ -3474,23 +3495,6 @@ static void qemu_machine_creation_done(void) qemu_register_reset(restore_boot_order, g_strdup(boot_order)); } - /* init local displays */ - ds = init_displaystate(); - qemu_display_init(ds, &dpy); - - /* must be after terminal init, SDL library changes signal handlers */ - os_setup_signal_handling(); - - /* init remote displays */ -#ifdef CONFIG_VNC - qemu_opts_foreach(qemu_find_opts("vnc"), - vnc_init_func, NULL, &error_fatal); -#endif - - if (using_spice) { - qemu_spice.display_init(); - } - if (foreach_device_config(DEV_GDB, gdbserver_start) < 0) { exit(1); } @@ -4090,6 +4094,7 @@ void qemu_init(int argc, char **argv, char **envp) break; case QEMU_OPTION_preconfig: preconfig_exit_requested = false; + preconfig_requested = true; break; case QEMU_OPTION_enable_kvm: olist = qemu_find_opts("machine"); @@ -4513,11 +4518,21 @@ void qemu_init(int argc, char **argv, char **envp) qemu_resolve_machine_memdev(); parse_numa_opts(current_machine); + if (preconfig_requested) { + qemu_init_displays(); + } + /* do monitor/qmp handling at preconfig state if requested */ qemu_main_loop(); qemu_init_board(); + qemu_create_cli_devices(); + + /* initialize displays after all errors have been reported */ + if (!preconfig_requested) { + qemu_init_displays(); + } qemu_machine_creation_done(); if (loadvm) { From cca686b44aa1315df4cda4dee56ca601050fab71 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Tue, 27 Oct 2020 04:26:14 -0400 Subject: [PATCH 072/113] vl: move -global check earlier The check has the same effect here, it only matters that it is performed once all devices, both builtin and user-specified, have been created. Reviewed-by: Igor Mammedov Signed-off-by: Paolo Bonzini --- softmmu/vl.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/softmmu/vl.c b/softmmu/vl.c index 6a2972938d..e65eb0c9f2 100644 --- a/softmmu/vl.c +++ b/softmmu/vl.c @@ -3490,6 +3490,8 @@ static void qemu_machine_creation_done(void) net_check_clients(); } + qdev_prop_check_globals(); + if (boot_once) { qemu_boot_set(boot_once, &error_fatal); qemu_register_reset(restore_boot_order, g_strdup(boot_order)); @@ -4547,7 +4549,6 @@ void qemu_init(int argc, char **argv, char **envp) replay_vmstate_init(); } - qdev_prop_check_globals(); if (vmstate_dump_file) { /* dump and exit */ dump_vmstate_json_to_file(vmstate_dump_file); From e69d50d621ccc1ab8b1048a3075ad944afebfed5 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Tue, 27 Oct 2020 04:22:57 -0400 Subject: [PATCH 073/113] migration, vl: start migration via qmp_migrate_incoming Make qemu_start_incoming_migration local to migration/migration.c. By using the runstate instead of a separate flag, vl need not do anything to setup deferred incoming migration. qmp_migrate_incoming also does not need the deferred_incoming flag anymore, because "-incoming PROTOCOL" will clear the "once" flag before the main loop starts. Therefore, later invocations of the migrate-incoming command will fail with the existing "The incoming migration has already been started" error message. Reviewed-by: Igor Mammedov Signed-off-by: Paolo Bonzini --- include/migration/misc.h | 1 - migration/migration.c | 33 ++++++++------------------------- softmmu/vl.c | 11 +++++++---- 3 files changed, 15 insertions(+), 30 deletions(-) diff --git a/include/migration/misc.h b/include/migration/misc.h index 34e7d75713..bccc1b6b44 100644 --- a/include/migration/misc.h +++ b/include/migration/misc.h @@ -58,7 +58,6 @@ void dump_vmstate_json_to_file(FILE *out_fp); /* migration/migration.c */ void migration_object_init(void); void migration_shutdown(void); -void qemu_start_incoming_migration(const char *uri, Error **errp); bool migration_is_idle(void); bool migration_is_active(MigrationState *); void add_migration_state_change_notifier(Notifier *notify); diff --git a/migration/migration.c b/migration/migration.c index d9e94f4080..e0dbde4091 100644 --- a/migration/migration.c +++ b/migration/migration.c @@ -118,8 +118,6 @@ static NotifierList migration_state_notifiers = NOTIFIER_LIST_INITIALIZER(migration_state_notifiers); -static bool deferred_incoming; - /* Messages sent on the return path from destination to source */ enum mig_rp_message_type { MIG_RP_MSG_INVALID = 0, /* Must be 0 */ @@ -275,19 +273,6 @@ static bool migrate_late_block_activate(void) MIGRATION_CAPABILITY_LATE_BLOCK_ACTIVATE]; } -/* - * Called on -incoming with a defer: uri. - * The migration can be started later after any parameters have been - * changed. - */ -static void deferred_incoming_migration(Error **errp) -{ - if (deferred_incoming) { - error_setg(errp, "Incoming migration already deferred"); - } - deferred_incoming = true; -} - /* * Send a message on the return channel back to the source * of the migration. @@ -429,16 +414,14 @@ void migrate_add_address(SocketAddress *address) addrs->value = QAPI_CLONE(SocketAddress, address); } -void qemu_start_incoming_migration(const char *uri, Error **errp) +static void qemu_start_incoming_migration(const char *uri, Error **errp) { const char *p = NULL; qapi_event_send_migration(MIGRATION_STATUS_SETUP); - if (!strcmp(uri, "defer")) { - deferred_incoming_migration(errp); - } else if (strstart(uri, "tcp:", &p) || - strstart(uri, "unix:", NULL) || - strstart(uri, "vsock:", NULL)) { + if (strstart(uri, "tcp:", &p) || + strstart(uri, "unix:", NULL) || + strstart(uri, "vsock:", NULL)) { socket_start_incoming_migration(p ? p : uri, errp); #ifdef CONFIG_RDMA } else if (strstart(uri, "rdma:", &p)) { @@ -1988,14 +1971,14 @@ void qmp_migrate_incoming(const char *uri, Error **errp) Error *local_err = NULL; static bool once = true; - if (!deferred_incoming) { - error_setg(errp, "For use with '-incoming defer'"); - return; - } if (!once) { error_setg(errp, "The incoming migration has already been started"); return; } + if (!runstate_check(RUN_STATE_INMIGRATE)) { + error_setg(errp, "'-incoming' was not specified on the command line"); + return; + } qemu_start_incoming_migration(uri, &local_err); diff --git a/softmmu/vl.c b/softmmu/vl.c index e65eb0c9f2..20dd0cd517 100644 --- a/softmmu/vl.c +++ b/softmmu/vl.c @@ -109,6 +109,7 @@ #include "qapi/qapi-visit-block-core.h" #include "qapi/qapi-visit-ui.h" #include "qapi/qapi-commands-block-core.h" +#include "qapi/qapi-commands-migration.h" #include "qapi/qapi-commands-run-state.h" #include "qapi/qapi-commands-ui.h" #include "qapi/qmp/qerror.h" @@ -4556,10 +4557,12 @@ void qemu_init(int argc, char **argv, char **envp) } if (incoming) { Error *local_err = NULL; - qemu_start_incoming_migration(incoming, &local_err); - if (local_err) { - error_reportf_err(local_err, "-incoming %s: ", incoming); - exit(1); + if (strcmp(incoming, "defer") != 0) { + qmp_migrate_incoming(incoming, &local_err); + if (local_err) { + error_reportf_err(local_err, "-incoming %s: ", incoming); + exit(1); + } } } else if (autostart) { vm_start(); From ee55686efbd7de8dce8c1437c6e38fb4f5398c24 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Tue, 27 Oct 2020 08:42:04 -0400 Subject: [PATCH 074/113] vl: start VM via qmp_cont Complement the previous patch by starting the VM with a QMP command. The plan is that the user will be able to do the same, invoking two commands "finish-machine-init" and "cont" instead of "x-exit-preconfig". Reviewed-by: Igor Mammedov Signed-off-by: Paolo Bonzini --- softmmu/vl.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/softmmu/vl.c b/softmmu/vl.c index 20dd0cd517..dc8a47efcb 100644 --- a/softmmu/vl.c +++ b/softmmu/vl.c @@ -110,6 +110,7 @@ #include "qapi/qapi-visit-ui.h" #include "qapi/qapi-commands-block-core.h" #include "qapi/qapi-commands-migration.h" +#include "qapi/qapi-commands-misc.h" #include "qapi/qapi-commands-run-state.h" #include "qapi/qapi-commands-ui.h" #include "qapi/qmp/qerror.h" @@ -4565,7 +4566,7 @@ void qemu_init(int argc, char **argv, char **envp) } } } else if (autostart) { - vm_start(); + qmp_cont(NULL); } accel_setup_post(current_machine); From 4cd29274729f6bfbb0202563929225bbbb861c1b Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Tue, 27 Oct 2020 04:40:02 -0400 Subject: [PATCH 075/113] hmp: introduce cmd_available Combine the RUN_STATE_PRECONFIG and cmd_can_preconfig checks into a single function, to avoid repeating the same expression (or its negation after applying DeMorgan's rule) over and over again. Reviewed-by: Igor Mammedov Signed-off-by: Paolo Bonzini --- monitor/hmp.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/monitor/hmp.c b/monitor/hmp.c index 1204233999..d40f4f4391 100644 --- a/monitor/hmp.c +++ b/monitor/hmp.c @@ -213,6 +213,11 @@ static bool cmd_can_preconfig(const HMPCommand *cmd) return strchr(cmd->flags, 'p'); } +static bool cmd_available(const HMPCommand *cmd) +{ + return !runstate_check(RUN_STATE_PRECONFIG) || cmd_can_preconfig(cmd); +} + static void help_cmd_dump_one(Monitor *mon, const HMPCommand *cmd, char **prefix_args, @@ -220,7 +225,7 @@ static void help_cmd_dump_one(Monitor *mon, { int i; - if (runstate_check(RUN_STATE_PRECONFIG) && !cmd_can_preconfig(cmd)) { + if (!cmd_available(cmd)) { return; } @@ -248,8 +253,7 @@ static void help_cmd_dump(Monitor *mon, const HMPCommand *cmds, /* Find one entry to dump */ for (cmd = cmds; cmd->name != NULL; cmd++) { if (hmp_compare_cmd(args[arg_index], cmd->name) && - ((!runstate_check(RUN_STATE_PRECONFIG) || - cmd_can_preconfig(cmd)))) { + cmd_available(cmd)) { if (cmd->sub_table) { /* continue with next arg */ help_cmd_dump(mon, cmd->sub_table, @@ -653,7 +657,7 @@ static const HMPCommand *monitor_parse_command(MonitorHMP *hmp_mon, (int)(p - cmdp_start), cmdp_start); return NULL; } - if (runstate_check(RUN_STATE_PRECONFIG) && !cmd_can_preconfig(cmd)) { + if (!cmd_available(cmd)) { monitor_printf(mon, "Command '%.*s' not available with -preconfig " "until after exit_preconfig.\n", (int)(p - cmdp_start), cmdp_start); @@ -1225,8 +1229,7 @@ static void monitor_find_completion_by_table(MonitorHMP *mon, } readline_set_completion_index(mon->rs, strlen(cmdname)); for (cmd = cmd_table; cmd->name != NULL; cmd++) { - if (!runstate_check(RUN_STATE_PRECONFIG) || - cmd_can_preconfig(cmd)) { + if (cmd_available(cmd)) { cmd_completion(mon, cmdname, cmd->name); } } @@ -1234,8 +1237,7 @@ static void monitor_find_completion_by_table(MonitorHMP *mon, /* find the command */ for (cmd = cmd_table; cmd->name != NULL; cmd++) { if (hmp_compare_cmd(args[0], cmd->name) && - (!runstate_check(RUN_STATE_PRECONFIG) || - cmd_can_preconfig(cmd))) { + cmd_available(cmd)) { break; } } From 2c65db5e58d2c74921077f6c064ba4c91ebde16a Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 28 Oct 2020 07:36:57 -0400 Subject: [PATCH 076/113] vl: extract softmmu/datadir.c Reviewed-by: Igor Mammedov Signed-off-by: Paolo Bonzini --- hw/alpha/dp264.c | 1 + hw/arm/boot.c | 1 + hw/arm/digic_boards.c | 1 + hw/arm/highbank.c | 1 + hw/arm/npcm7xx_boards.c | 1 + hw/arm/sbsa-ref.c | 1 + hw/arm/vexpress.c | 1 + hw/arm/virt.c | 1 + hw/avr/boot.c | 1 + hw/core/loader.c | 1 + hw/display/cg3.c | 1 + hw/display/tcx.c | 1 + hw/hppa/machine.c | 1 + hw/i386/x86.c | 1 + hw/lm32/milkymist.c | 1 + hw/m68k/mcf5208.c | 1 + hw/m68k/q800.c | 1 + hw/microblaze/boot.c | 1 + hw/mips/fuloong2e.c | 1 + hw/mips/jazz.c | 1 + hw/mips/malta.c | 1 + hw/mips/mipssim.c | 1 + hw/nios2/boot.c | 1 + hw/nvram/fw_cfg.c | 1 + hw/pci-host/prep.c | 1 + hw/pci/pci.c | 1 + hw/ppc/e500.c | 1 + hw/ppc/mac_newworld.c | 1 + hw/ppc/mac_oldworld.c | 1 + hw/ppc/pnv.c | 1 + hw/ppc/ppc405_boards.c | 1 + hw/ppc/ppc440_bamboo.c | 1 + hw/ppc/sam460ex.c | 1 + hw/ppc/spapr.c | 1 + hw/ppc/virtex_ml507.c | 1 + hw/riscv/boot.c | 1 + hw/s390x/ipl.c | 1 + hw/sparc/leon3.c | 1 + hw/sparc/sun4m.c | 1 + hw/sparc64/sun4u.c | 1 + include/qemu-common.h | 21 ------- include/qemu/datadir.h | 28 +++++++++ include/sysemu/sysemu.h | 2 - softmmu/datadir.c | 129 ++++++++++++++++++++++++++++++++++++++++ softmmu/meson.build | 1 + softmmu/vl.c | 95 +---------------------------- tests/qtest/fuzz/fuzz.c | 1 + ui/keymaps.c | 1 + 48 files changed, 203 insertions(+), 115 deletions(-) create mode 100644 include/qemu/datadir.h create mode 100644 softmmu/datadir.c diff --git a/hw/alpha/dp264.c b/hw/alpha/dp264.c index c4d407a9f1..c8e300d93f 100644 --- a/hw/alpha/dp264.c +++ b/hw/alpha/dp264.c @@ -21,6 +21,7 @@ #include "hw/dma/i8257.h" #include "net/net.h" #include "qemu/cutils.h" +#include "qemu/datadir.h" #include "net/net.h" #define MAX_IDE_BUS 2 diff --git a/hw/arm/boot.c b/hw/arm/boot.c index cf97600a91..4d9d47ba1c 100644 --- a/hw/arm/boot.c +++ b/hw/arm/boot.c @@ -9,6 +9,7 @@ #include "qemu/osdep.h" #include "qemu-common.h" +#include "qemu/datadir.h" #include "qemu/error-report.h" #include "qapi/error.h" #include diff --git a/hw/arm/digic_boards.c b/hw/arm/digic_boards.c index fd228fa96f..be12873673 100644 --- a/hw/arm/digic_boards.c +++ b/hw/arm/digic_boards.c @@ -26,6 +26,7 @@ #include "qemu/osdep.h" #include "qapi/error.h" #include "qemu-common.h" +#include "qemu/datadir.h" #include "cpu.h" #include "hw/boards.h" #include "exec/address-spaces.h" diff --git a/hw/arm/highbank.c b/hw/arm/highbank.c index fd3429720e..bf7b8f4c64 100644 --- a/hw/arm/highbank.c +++ b/hw/arm/highbank.c @@ -19,6 +19,7 @@ #include "qemu/osdep.h" #include "qemu-common.h" +#include "qemu/datadir.h" #include "qapi/error.h" #include "hw/sysbus.h" #include "migration/vmstate.h" diff --git a/hw/arm/npcm7xx_boards.c b/hw/arm/npcm7xx_boards.c index 9821013bc6..306260fa67 100644 --- a/hw/arm/npcm7xx_boards.c +++ b/hw/arm/npcm7xx_boards.c @@ -23,6 +23,7 @@ #include "hw/qdev-properties.h" #include "qapi/error.h" #include "qemu-common.h" +#include "qemu/datadir.h" #include "qemu/units.h" #include "sysemu/sysemu.h" diff --git a/hw/arm/sbsa-ref.c b/hw/arm/sbsa-ref.c index 8272983664..9f70735153 100644 --- a/hw/arm/sbsa-ref.c +++ b/hw/arm/sbsa-ref.c @@ -19,6 +19,7 @@ #include "qemu/osdep.h" #include "qemu-common.h" +#include "qemu/datadir.h" #include "qapi/error.h" #include "qemu/error-report.h" #include "qemu/units.h" diff --git a/hw/arm/vexpress.c b/hw/arm/vexpress.c index 1adb663d77..ac098375c1 100644 --- a/hw/arm/vexpress.c +++ b/hw/arm/vexpress.c @@ -24,6 +24,7 @@ #include "qemu/osdep.h" #include "qapi/error.h" #include "qemu-common.h" +#include "qemu/datadir.h" #include "cpu.h" #include "hw/sysbus.h" #include "hw/arm/boot.h" diff --git a/hw/arm/virt.c b/hw/arm/virt.c index d09124832d..556592012e 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c @@ -30,6 +30,7 @@ #include "qemu/osdep.h" #include "qemu-common.h" +#include "qemu/datadir.h" #include "qemu/units.h" #include "qemu/option.h" #include "monitor/qdev.h" diff --git a/hw/avr/boot.c b/hw/avr/boot.c index d16bb3dbe1..cbede775ce 100644 --- a/hw/avr/boot.c +++ b/hw/avr/boot.c @@ -10,6 +10,7 @@ #include "qemu/osdep.h" #include "qemu-common.h" +#include "qemu/datadir.h" #include "hw/loader.h" #include "elf.h" #include "boot.h" diff --git a/hw/core/loader.c b/hw/core/loader.c index 8bbb1797a4..fea22d265c 100644 --- a/hw/core/loader.c +++ b/hw/core/loader.c @@ -44,6 +44,7 @@ #include "qemu/osdep.h" #include "qemu-common.h" +#include "qemu/datadir.h" #include "qapi/error.h" #include "trace.h" #include "hw/hw.h" diff --git a/hw/display/cg3.c b/hw/display/cg3.c index 42fcf40010..4b7e78d919 100644 --- a/hw/display/cg3.c +++ b/hw/display/cg3.c @@ -25,6 +25,7 @@ #include "qemu/osdep.h" #include "qemu-common.h" +#include "qemu/datadir.h" #include "qapi/error.h" #include "qemu/error-report.h" #include "ui/console.h" diff --git a/hw/display/tcx.c b/hw/display/tcx.c index 3799d29b75..965f92ff6b 100644 --- a/hw/display/tcx.c +++ b/hw/display/tcx.c @@ -24,6 +24,7 @@ #include "qemu/osdep.h" #include "qemu-common.h" +#include "qemu/datadir.h" #include "qapi/error.h" #include "ui/console.h" #include "ui/pixel_ops.h" diff --git a/hw/hppa/machine.c b/hw/hppa/machine.c index 7e41cb2462..f2b71db9bd 100644 --- a/hw/hppa/machine.c +++ b/hw/hppa/machine.c @@ -5,6 +5,7 @@ #include "qemu/osdep.h" #include "qemu-common.h" +#include "qemu/datadir.h" #include "cpu.h" #include "elf.h" #include "hw/loader.h" diff --git a/hw/i386/x86.c b/hw/i386/x86.c index f86f6dbbec..49e1d419b2 100644 --- a/hw/i386/x86.c +++ b/hw/i386/x86.c @@ -26,6 +26,7 @@ #include "qemu/cutils.h" #include "qemu/units.h" #include "qemu-common.h" +#include "qemu/datadir.h" #include "qapi/error.h" #include "qapi/qmp/qerror.h" #include "qapi/qapi-visit-common.h" diff --git a/hw/lm32/milkymist.c b/hw/lm32/milkymist.c index 93ca8bc2ac..72d1326531 100644 --- a/hw/lm32/milkymist.c +++ b/hw/lm32/milkymist.c @@ -21,6 +21,7 @@ #include "qemu/units.h" #include "qemu/error-report.h" #include "qemu-common.h" +#include "qemu/datadir.h" #include "cpu.h" #include "hw/sysbus.h" #include "hw/irq.h" diff --git a/hw/m68k/mcf5208.c b/hw/m68k/mcf5208.c index 2205145ecc..7a03c71059 100644 --- a/hw/m68k/mcf5208.c +++ b/hw/m68k/mcf5208.c @@ -12,6 +12,7 @@ #include "qemu/log.h" #include "qapi/error.h" #include "qemu-common.h" +#include "qemu/datadir.h" #include "cpu.h" #include "hw/irq.h" #include "hw/m68k/mcf.h" diff --git a/hw/m68k/q800.c b/hw/m68k/q800.c index 6ebcddcfb2..4db2b9bbc7 100644 --- a/hw/m68k/q800.c +++ b/hw/m68k/q800.c @@ -23,6 +23,7 @@ #include "qemu/osdep.h" #include "qemu/units.h" #include "qemu-common.h" +#include "qemu/datadir.h" #include "sysemu/sysemu.h" #include "cpu.h" #include "hw/hw.h" diff --git a/hw/microblaze/boot.c b/hw/microblaze/boot.c index e1f56f83f9..6715ba2ff9 100644 --- a/hw/microblaze/boot.c +++ b/hw/microblaze/boot.c @@ -26,6 +26,7 @@ #include "qemu/osdep.h" #include "qemu-common.h" +#include "qemu/datadir.h" #include "cpu.h" #include "qemu/option.h" #include "qemu/config-file.h" diff --git a/hw/mips/fuloong2e.c b/hw/mips/fuloong2e.c index 84a2132f85..45c596f4fe 100644 --- a/hw/mips/fuloong2e.c +++ b/hw/mips/fuloong2e.c @@ -20,6 +20,7 @@ #include "qemu/osdep.h" #include "qemu-common.h" +#include "qemu/datadir.h" #include "qemu/units.h" #include "qapi/error.h" #include "cpu.h" diff --git a/hw/mips/jazz.c b/hw/mips/jazz.c index aa95c6a3d3..f9442731dd 100644 --- a/hw/mips/jazz.c +++ b/hw/mips/jazz.c @@ -24,6 +24,7 @@ #include "qemu/osdep.h" #include "qemu-common.h" +#include "qemu/datadir.h" #include "hw/clock.h" #include "hw/mips/mips.h" #include "hw/mips/cpudevs.h" diff --git a/hw/mips/malta.c b/hw/mips/malta.c index 467b21849e..5c11eecec1 100644 --- a/hw/mips/malta.c +++ b/hw/mips/malta.c @@ -25,6 +25,7 @@ #include "qemu/osdep.h" #include "qemu/units.h" #include "qemu-common.h" +#include "qemu/datadir.h" #include "cpu.h" #include "hw/clock.h" #include "hw/southbridge/piix.h" diff --git a/hw/mips/mipssim.c b/hw/mips/mipssim.c index cc9b0934b3..f2e6273525 100644 --- a/hw/mips/mipssim.c +++ b/hw/mips/mipssim.c @@ -28,6 +28,7 @@ #include "qemu/osdep.h" #include "qapi/error.h" #include "qemu-common.h" +#include "qemu/datadir.h" #include "cpu.h" #include "hw/clock.h" #include "hw/mips/mips.h" diff --git a/hw/nios2/boot.c b/hw/nios2/boot.c index 3cb864914b..95a8697906 100644 --- a/hw/nios2/boot.c +++ b/hw/nios2/boot.c @@ -31,6 +31,7 @@ #include "qemu/osdep.h" #include "qemu/units.h" #include "qemu-common.h" +#include "qemu/datadir.h" #include "cpu.h" #include "qemu/option.h" #include "qemu/config-file.h" diff --git a/hw/nvram/fw_cfg.c b/hw/nvram/fw_cfg.c index 282ba93e2e..44cb274a32 100644 --- a/hw/nvram/fw_cfg.c +++ b/hw/nvram/fw_cfg.c @@ -24,6 +24,7 @@ #include "qemu/osdep.h" #include "qemu-common.h" +#include "qemu/datadir.h" #include "sysemu/sysemu.h" #include "sysemu/dma.h" #include "sysemu/reset.h" diff --git a/hw/pci-host/prep.c b/hw/pci-host/prep.c index d0323fefb1..0469db8c1d 100644 --- a/hw/pci-host/prep.c +++ b/hw/pci-host/prep.c @@ -25,6 +25,7 @@ #include "qemu/osdep.h" #include "qemu-common.h" +#include "qemu/datadir.h" #include "qemu/units.h" #include "qapi/error.h" #include "hw/pci/pci.h" diff --git a/hw/pci/pci.c b/hw/pci/pci.c index 0131d9d02c..9424231542 100644 --- a/hw/pci/pci.c +++ b/hw/pci/pci.c @@ -24,6 +24,7 @@ #include "qemu/osdep.h" #include "qemu-common.h" +#include "qemu/datadir.h" #include "hw/irq.h" #include "hw/pci/pci.h" #include "hw/pci/pci_bridge.h" diff --git a/hw/ppc/e500.c b/hw/ppc/e500.c index 153a74c98c..6a64eb31ab 100644 --- a/hw/ppc/e500.c +++ b/hw/ppc/e500.c @@ -16,6 +16,7 @@ #include "qemu/osdep.h" #include "qemu-common.h" +#include "qemu/datadir.h" #include "qemu/units.h" #include "qapi/error.h" #include "e500.h" diff --git a/hw/ppc/mac_newworld.c b/hw/ppc/mac_newworld.c index 61c63819df..c0accda592 100644 --- a/hw/ppc/mac_newworld.c +++ b/hw/ppc/mac_newworld.c @@ -48,6 +48,7 @@ #include "qemu/osdep.h" #include "qemu-common.h" +#include "qemu/datadir.h" #include "qapi/error.h" #include "hw/ppc/ppc.h" #include "hw/qdev-properties.h" diff --git a/hw/ppc/mac_oldworld.c b/hw/ppc/mac_oldworld.c index 11623e8e67..04f98a4d81 100644 --- a/hw/ppc/mac_oldworld.c +++ b/hw/ppc/mac_oldworld.c @@ -26,6 +26,7 @@ #include "qemu/osdep.h" #include "qemu-common.h" +#include "qemu/datadir.h" #include "qemu/units.h" #include "qapi/error.h" #include "hw/ppc/ppc.h" diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c index 53a5121cab..14fc9758a9 100644 --- a/hw/ppc/pnv.c +++ b/hw/ppc/pnv.c @@ -19,6 +19,7 @@ #include "qemu/osdep.h" #include "qemu-common.h" +#include "qemu/datadir.h" #include "qemu/units.h" #include "qapi/error.h" #include "sysemu/qtest.h" diff --git a/hw/ppc/ppc405_boards.c b/hw/ppc/ppc405_boards.c index c867e46330..b7249f21cf 100644 --- a/hw/ppc/ppc405_boards.c +++ b/hw/ppc/ppc405_boards.c @@ -26,6 +26,7 @@ #include "qemu/units.h" #include "qapi/error.h" #include "qemu-common.h" +#include "qemu/datadir.h" #include "cpu.h" #include "hw/ppc/ppc.h" #include "hw/qdev-properties.h" diff --git a/hw/ppc/ppc440_bamboo.c b/hw/ppc/ppc440_bamboo.c index 74028dc986..665bc1784e 100644 --- a/hw/ppc/ppc440_bamboo.c +++ b/hw/ppc/ppc440_bamboo.c @@ -15,6 +15,7 @@ #include "qemu/units.h" #include "qemu/error-report.h" #include "qemu-common.h" +#include "qemu/datadir.h" #include "qemu/error-report.h" #include "net/net.h" #include "hw/pci/pci.h" diff --git a/hw/ppc/sam460ex.c b/hw/ppc/sam460ex.c index 7e59a91981..14e6583eb0 100644 --- a/hw/ppc/sam460ex.c +++ b/hw/ppc/sam460ex.c @@ -14,6 +14,7 @@ #include "qemu/osdep.h" #include "qemu/units.h" #include "qemu-common.h" +#include "qemu/datadir.h" #include "qemu/error-report.h" #include "qapi/error.h" #include "hw/boards.h" diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index e87a3b8557..3f5b0d0159 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -26,6 +26,7 @@ #include "qemu/osdep.h" #include "qemu-common.h" +#include "qemu/datadir.h" #include "qapi/error.h" #include "qapi/visitor.h" #include "sysemu/sysemu.h" diff --git a/hw/ppc/virtex_ml507.c b/hw/ppc/virtex_ml507.c index c790c1113f..7f1bca928c 100644 --- a/hw/ppc/virtex_ml507.c +++ b/hw/ppc/virtex_ml507.c @@ -24,6 +24,7 @@ #include "qemu/osdep.h" #include "qemu-common.h" +#include "qemu/datadir.h" #include "qemu/units.h" #include "cpu.h" #include "hw/sysbus.h" diff --git a/hw/riscv/boot.c b/hw/riscv/boot.c index 70a9bf8f5d..d62f3dc758 100644 --- a/hw/riscv/boot.c +++ b/hw/riscv/boot.c @@ -19,6 +19,7 @@ #include "qemu/osdep.h" #include "qemu-common.h" +#include "qemu/datadir.h" #include "qemu/units.h" #include "qemu/error-report.h" #include "exec/cpu-defs.h" diff --git a/hw/s390x/ipl.c b/hw/s390x/ipl.c index bddbaffac6..ff6b55e816 100644 --- a/hw/s390x/ipl.c +++ b/hw/s390x/ipl.c @@ -14,6 +14,7 @@ #include "qemu/osdep.h" #include "qemu-common.h" +#include "qemu/datadir.h" #include "qapi/error.h" #include "sysemu/reset.h" #include "sysemu/runstate.h" diff --git a/hw/sparc/leon3.c b/hw/sparc/leon3.c index 1c50b02f81..4bc4ebea84 100644 --- a/hw/sparc/leon3.c +++ b/hw/sparc/leon3.c @@ -27,6 +27,7 @@ #include "qemu/error-report.h" #include "qapi/error.h" #include "qemu-common.h" +#include "qemu/datadir.h" #include "cpu.h" #include "hw/irq.h" #include "qemu/timer.h" diff --git a/hw/sparc/sun4m.c b/hw/sparc/sun4m.c index 0f9cd2bf52..8686371318 100644 --- a/hw/sparc/sun4m.c +++ b/hw/sparc/sun4m.c @@ -25,6 +25,7 @@ #include "qemu/osdep.h" #include "qemu/units.h" #include "qapi/error.h" +#include "qemu/datadir.h" #include "qemu-common.h" #include "cpu.h" #include "hw/sysbus.h" diff --git a/hw/sparc64/sun4u.c b/hw/sparc64/sun4u.c index 8bee7dd2f4..0fa13a7330 100644 --- a/hw/sparc64/sun4u.c +++ b/hw/sparc64/sun4u.c @@ -27,6 +27,7 @@ #include "qemu/error-report.h" #include "qapi/error.h" #include "qemu-common.h" +#include "qemu/datadir.h" #include "cpu.h" #include "hw/pci/pci.h" #include "hw/pci/pci_bridge.h" diff --git a/include/qemu-common.h b/include/qemu-common.h index fda7dc6ca7..654621444e 100644 --- a/include/qemu-common.h +++ b/include/qemu-common.h @@ -108,27 +108,6 @@ void qemu_progress_end(void); void qemu_progress_print(float delta, int max); const char *qemu_get_vm_name(void); -#define QEMU_FILE_TYPE_BIOS 0 -#define QEMU_FILE_TYPE_KEYMAP 1 -/** - * qemu_find_file: - * @type: QEMU_FILE_TYPE_BIOS (for BIOS, VGA BIOS) - * or QEMU_FILE_TYPE_KEYMAP (for keymaps). - * @name: Relative or absolute file name - * - * If @name exists on disk as an absolute path, or a path relative - * to the current directory, then returns @name unchanged. - * Otherwise searches for @name file in the data directories, either - * configured at build time (DATADIR) or registered with the -L command - * line option. - * - * The caller must use g_free() to free the returned data when it is - * no longer required. - * - * Returns: a path that can access @name, or NULL if no matching file exists. - */ -char *qemu_find_file(int type, const char *name); - /* OS specific functions */ void os_setup_early_signal_handling(void); int os_parse_cmd_args(int index, const char *optarg); diff --git a/include/qemu/datadir.h b/include/qemu/datadir.h new file mode 100644 index 0000000000..21f9097f58 --- /dev/null +++ b/include/qemu/datadir.h @@ -0,0 +1,28 @@ +#ifndef QEMU_DATADIR_H +#define QEMU_DATADIR_H + +#define QEMU_FILE_TYPE_BIOS 0 +#define QEMU_FILE_TYPE_KEYMAP 1 +/** + * qemu_find_file: + * @type: QEMU_FILE_TYPE_BIOS (for BIOS, VGA BIOS) + * or QEMU_FILE_TYPE_KEYMAP (for keymaps). + * @name: Relative or absolute file name + * + * If @name exists on disk as an absolute path, or a path relative + * to the current directory, then returns @name unchanged. + * Otherwise searches for @name file in the data directories, either + * configured at build time (DATADIR) or registered with the -L command + * line option. + * + * The caller must use g_free() to free the returned data when it is + * no longer required. + * + * Returns: a path that can access @name, or NULL if no matching file exists. + */ +char *qemu_find_file(int type, const char *name); +void qemu_add_default_firmwarepath(void); +void qemu_add_data_dir(char *path); +void qemu_list_data_dirs(void); + +#endif diff --git a/include/sysemu/sysemu.h b/include/sysemu/sysemu.h index 1336b4264a..c94b2e7159 100644 --- a/include/sysemu/sysemu.h +++ b/include/sysemu/sysemu.h @@ -13,8 +13,6 @@ extern const char *qemu_name; extern QemuUUID qemu_uuid; extern bool qemu_uuid_set; -void qemu_add_data_dir(char *path); - void qemu_add_exit_notifier(Notifier *notify); void qemu_remove_exit_notifier(Notifier *notify); diff --git a/softmmu/datadir.c b/softmmu/datadir.c new file mode 100644 index 0000000000..504c4665be --- /dev/null +++ b/softmmu/datadir.c @@ -0,0 +1,129 @@ +/* + * QEMU firmware and keymap file search + * + * Copyright (c) 2003-2020 QEMU contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "qemu/osdep.h" +#include "qemu-common.h" +#include "qemu/datadir.h" +#include "qemu/cutils.h" +#include "trace.h" + +static const char *data_dir[16]; +static int data_dir_idx; + +char *qemu_find_file(int type, const char *name) +{ + int i; + const char *subdir; + char *buf; + + /* Try the name as a straight path first */ + if (access(name, R_OK) == 0) { + trace_load_file(name, name); + return g_strdup(name); + } + + switch (type) { + case QEMU_FILE_TYPE_BIOS: + subdir = ""; + break; + case QEMU_FILE_TYPE_KEYMAP: + subdir = "keymaps/"; + break; + default: + abort(); + } + + for (i = 0; i < data_dir_idx; i++) { + buf = g_strdup_printf("%s/%s%s", data_dir[i], subdir, name); + if (access(buf, R_OK) == 0) { + trace_load_file(name, buf); + return buf; + } + g_free(buf); + } + return NULL; +} + +void qemu_add_data_dir(char *path) +{ + int i; + + if (path == NULL) { + return; + } + if (data_dir_idx == ARRAY_SIZE(data_dir)) { + return; + } + for (i = 0; i < data_dir_idx; i++) { + if (strcmp(data_dir[i], path) == 0) { + g_free(path); /* duplicate */ + return; + } + } + data_dir[data_dir_idx++] = path; +} + +/* + * Find a likely location for support files using the location of the binary. + * When running from the build tree this will be "$bindir/pc-bios". + * Otherwise, this is CONFIG_QEMU_DATADIR (possibly relocated). + * + * The caller must use g_free() to free the returned data when it is + * no longer required. + */ +static char *find_datadir(void) +{ + g_autofree char *dir = NULL; + + dir = g_build_filename(qemu_get_exec_dir(), "pc-bios", NULL); + if (g_file_test(dir, G_FILE_TEST_IS_DIR)) { + return g_steal_pointer(&dir); + } + + return get_relocated_path(CONFIG_QEMU_DATADIR); +} + +void qemu_add_default_firmwarepath(void) +{ + char **dirs; + size_t i; + + /* add configured firmware directories */ + dirs = g_strsplit(CONFIG_QEMU_FIRMWAREPATH, G_SEARCHPATH_SEPARATOR_S, 0); + for (i = 0; dirs[i] != NULL; i++) { + qemu_add_data_dir(get_relocated_path(dirs[i])); + } + g_strfreev(dirs); + + /* try to find datadir relative to the executable path */ + qemu_add_data_dir(find_datadir()); +} + +void qemu_list_data_dirs(void) +{ + int i; + for (i = 0; i < data_dir_idx; i++) { + printf("%s\n", data_dir[i]); + } +} diff --git a/softmmu/meson.build b/softmmu/meson.build index 8f7210b4f0..7b52339e7a 100644 --- a/softmmu/meson.build +++ b/softmmu/meson.build @@ -3,6 +3,7 @@ specific_ss.add(when: 'CONFIG_SOFTMMU', if_true: [files( 'balloon.c', 'cpus.c', 'cpu-throttle.c', + 'datadir.c', 'physmem.c', 'ioport.c', 'memory.c', diff --git a/softmmu/vl.c b/softmmu/vl.c index dc8a47efcb..28aafc1101 100644 --- a/softmmu/vl.c +++ b/softmmu/vl.c @@ -24,6 +24,7 @@ #include "qemu/osdep.h" #include "qemu-common.h" +#include "qemu/datadir.h" #include "qemu/units.h" #include "hw/boards.h" #include "hw/qdev-properties.h" @@ -128,8 +129,6 @@ typedef struct BlockdevOptionsQueueEntry { typedef QSIMPLEQ_HEAD(, BlockdevOptionsQueueEntry) BlockdevOptionsQueue; static const char *cpu_option; -static const char *data_dir[16]; -static int data_dir_idx; static const char *mem_path; static const char *boot_order; static const char *boot_once; @@ -1994,59 +1993,6 @@ static void parse_display(const char *p) } } -char *qemu_find_file(int type, const char *name) -{ - int i; - const char *subdir; - char *buf; - - /* Try the name as a straight path first */ - if (access(name, R_OK) == 0) { - trace_load_file(name, name); - return g_strdup(name); - } - - switch (type) { - case QEMU_FILE_TYPE_BIOS: - subdir = ""; - break; - case QEMU_FILE_TYPE_KEYMAP: - subdir = "keymaps/"; - break; - default: - abort(); - } - - for (i = 0; i < data_dir_idx; i++) { - buf = g_strdup_printf("%s/%s%s", data_dir[i], subdir, name); - if (access(buf, R_OK) == 0) { - trace_load_file(name, buf); - return buf; - } - g_free(buf); - } - return NULL; -} - -void qemu_add_data_dir(char *path) -{ - int i; - - if (path == NULL) { - return; - } - if (data_dir_idx == ARRAY_SIZE(data_dir)) { - return; - } - for (i = 0; i < data_dir_idx; i++) { - if (strcmp(data_dir[i], path) == 0) { - g_free(path); /* duplicate */ - return; - } - } - data_dir[data_dir_idx++] = path; -} - static inline bool nonempty_str(const char *str) { return str && *str; @@ -3187,26 +3133,6 @@ static void create_default_memdev(MachineState *ms, const char *path) &error_fatal); } -/* - * Find a likely location for support files using the location of the binary. - * When running from the build tree this will be "$bindir/pc-bios". - * Otherwise, this is CONFIG_QEMU_DATADIR (possibly relocated). - * - * The caller must use g_free() to free the returned data when it is - * no longer required. - */ -static char *find_datadir(void) -{ - g_autofree char *dir = NULL; - - dir = g_build_filename(qemu_get_exec_dir(), "pc-bios", NULL); - if (g_file_test(dir, G_FILE_TEST_IS_DIR)) { - return g_steal_pointer(&dir); - } - - return get_relocated_path(CONFIG_QEMU_DATADIR); -} - static void qemu_validate_options(void) { QemuOpts *machine_opts = qemu_get_machine_opts(); @@ -3266,9 +3192,6 @@ static void qemu_process_sugar_options(void) static void qemu_process_early_options(void) { - char **dirs; - int i; - #ifdef CONFIG_SECCOMP QemuOptsList *olist = qemu_find_opts_err("sandbox", NULL); if (olist) { @@ -3306,21 +3229,11 @@ static void qemu_process_early_options(void) qemu_set_log(0); } - /* add configured firmware directories */ - dirs = g_strsplit(CONFIG_QEMU_FIRMWAREPATH, G_SEARCHPATH_SEPARATOR_S, 0); - for (i = 0; dirs[i] != NULL; i++) { - qemu_add_data_dir(get_relocated_path(dirs[i])); - } - g_strfreev(dirs); - - /* try to find datadir relative to the executable path */ - qemu_add_data_dir(find_datadir()); + qemu_add_default_firmwarepath(); } static void qemu_process_help_options(void) { - int i; - /* * Check for -cpu help and -device help before we call select_machine(), * which will return an error if the architecture has no default machine @@ -3339,9 +3252,7 @@ static void qemu_process_help_options(void) /* -L help lists the data directories and exits. */ if (list_data_dirs) { - for (i = 0; i < data_dir_idx; i++) { - printf("%s\n", data_dir[i]); - } + qemu_list_data_dirs(); exit(0); } } diff --git a/tests/qtest/fuzz/fuzz.c b/tests/qtest/fuzz/fuzz.c index 7be7226bc0..238866a037 100644 --- a/tests/qtest/fuzz/fuzz.c +++ b/tests/qtest/fuzz/fuzz.c @@ -15,6 +15,7 @@ #include +#include "qemu/datadir.h" #include "sysemu/qtest.h" #include "sysemu/runstate.h" #include "sysemu/sysemu.h" diff --git a/ui/keymaps.c b/ui/keymaps.c index 4e5fca57a8..d4a647464b 100644 --- a/ui/keymaps.c +++ b/ui/keymaps.c @@ -24,6 +24,7 @@ #include "qemu/osdep.h" #include "qemu-common.h" +#include "qemu/datadir.h" #include "keymaps.h" #include "trace.h" #include "qemu/ctype.h" From 6b21670cfda76e47a827810eea5eb3b518cb6521 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 28 Oct 2020 07:36:57 -0400 Subject: [PATCH 077/113] vl: extract machine done notifiers Reviewed-by: Igor Mammedov Signed-off-by: Paolo Bonzini --- hw/core/machine.c | 24 ++++++++++++++++++++++++ include/sysemu/sysemu.h | 1 + softmmu/vl.c | 24 ------------------------ 3 files changed, 25 insertions(+), 24 deletions(-) diff --git a/hw/core/machine.c b/hw/core/machine.c index 71a0e375ab..d7f8fdee45 100644 --- a/hw/core/machine.c +++ b/hw/core/machine.c @@ -1169,6 +1169,30 @@ void machine_run_board_init(MachineState *machine) machine_class->init(machine); } +static NotifierList machine_init_done_notifiers = + NOTIFIER_LIST_INITIALIZER(machine_init_done_notifiers); + +bool machine_init_done; + +void qemu_add_machine_init_done_notifier(Notifier *notify) +{ + notifier_list_add(&machine_init_done_notifiers, notify); + if (machine_init_done) { + notify->notify(notify, NULL); + } +} + +void qemu_remove_machine_init_done_notifier(Notifier *notify) +{ + notifier_remove(notify); +} + +void qemu_run_machine_init_done_notifiers(void) +{ + machine_init_done = true; + notifier_list_notify(&machine_init_done_notifiers, NULL); +} + static const TypeInfo machine_info = { .name = TYPE_MACHINE, .parent = TYPE_OBJECT, diff --git a/include/sysemu/sysemu.h b/include/sysemu/sysemu.h index c94b2e7159..1b62deaf2b 100644 --- a/include/sysemu/sysemu.h +++ b/include/sysemu/sysemu.h @@ -18,6 +18,7 @@ void qemu_remove_exit_notifier(Notifier *notify); extern bool machine_init_done; +void qemu_run_machine_init_done_notifiers(void); void qemu_add_machine_init_done_notifier(Notifier *notify); void qemu_remove_machine_init_done_notifier(Notifier *notify); diff --git a/softmmu/vl.c b/softmmu/vl.c index 28aafc1101..852ecf08e1 100644 --- a/softmmu/vl.c +++ b/softmmu/vl.c @@ -204,9 +204,6 @@ bool qemu_uuid_set; static NotifierList exit_notifiers = NOTIFIER_LIST_INITIALIZER(exit_notifiers); -static NotifierList machine_init_done_notifiers = - NOTIFIER_LIST_INITIALIZER(machine_init_done_notifiers); - uint32_t xen_domid; enum xen_mode xen_mode = XEN_EMULATE; bool xen_domid_restrict; @@ -2451,27 +2448,6 @@ static void qemu_unlink_pidfile(Notifier *n, void *data) } } -bool machine_init_done; - -void qemu_add_machine_init_done_notifier(Notifier *notify) -{ - notifier_list_add(&machine_init_done_notifiers, notify); - if (machine_init_done) { - notify->notify(notify, NULL); - } -} - -void qemu_remove_machine_init_done_notifier(Notifier *notify) -{ - notifier_remove(notify); -} - -static void qemu_run_machine_init_done_notifiers(void) -{ - machine_init_done = true; - notifier_list_notify(&machine_init_done_notifiers, NULL); -} - static const QEMUOption *lookup_opt(int argc, char **argv, const char **poptarg, int *poptind) { From bf4d4056fb7ef7d629d003a338445db9801aa743 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 28 Oct 2020 07:36:57 -0400 Subject: [PATCH 078/113] vl: extract softmmu/rtc.c Reviewed-by: Igor Mammedov Signed-off-by: Paolo Bonzini --- include/sysemu/sysemu.h | 2 + softmmu/meson.build | 1 + softmmu/rtc.c | 190 ++++++++++++++++++++++++++++++++++++++++ softmmu/vl.c | 156 --------------------------------- 4 files changed, 193 insertions(+), 156 deletions(-) create mode 100644 softmmu/rtc.c diff --git a/include/sysemu/sysemu.h b/include/sysemu/sysemu.h index 1b62deaf2b..18cf586cd0 100644 --- a/include/sysemu/sysemu.h +++ b/include/sysemu/sysemu.h @@ -22,6 +22,8 @@ void qemu_run_machine_init_done_notifiers(void); void qemu_add_machine_init_done_notifier(Notifier *notify); void qemu_remove_machine_init_done_notifier(Notifier *notify); +void configure_rtc(QemuOpts *opts); + extern int autostart; typedef enum { diff --git a/softmmu/meson.build b/softmmu/meson.build index 7b52339e7a..d098d89653 100644 --- a/softmmu/meson.build +++ b/softmmu/meson.build @@ -6,6 +6,7 @@ specific_ss.add(when: 'CONFIG_SOFTMMU', if_true: [files( 'datadir.c', 'physmem.c', 'ioport.c', + 'rtc.c', 'memory.c', 'memory_mapping.c', 'qtest.c', diff --git a/softmmu/rtc.c b/softmmu/rtc.c new file mode 100644 index 0000000000..e1e15ef613 --- /dev/null +++ b/softmmu/rtc.c @@ -0,0 +1,190 @@ +/* + * RTC configuration and clock read + * + * Copyright (c) 2003-2020 QEMU contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "qemu/osdep.h" +#include "qemu-common.h" +#include "qemu/cutils.h" +#include "qapi/error.h" +#include "qapi/qmp/qerror.h" +#include "qemu/error-report.h" +#include "qemu/option.h" +#include "qemu/timer.h" +#include "qom/object.h" +#include "sysemu/replay.h" +#include "sysemu/sysemu.h" + +static enum { + RTC_BASE_UTC, + RTC_BASE_LOCALTIME, + RTC_BASE_DATETIME, +} rtc_base_type = RTC_BASE_UTC; +static time_t rtc_ref_start_datetime; +static int rtc_realtime_clock_offset; /* used only with QEMU_CLOCK_REALTIME */ +static int rtc_host_datetime_offset = -1; /* valid & used only with + RTC_BASE_DATETIME */ +QEMUClockType rtc_clock; +/***********************************************************/ +/* RTC reference time/date access */ +static time_t qemu_ref_timedate(QEMUClockType clock) +{ + time_t value = qemu_clock_get_ms(clock) / 1000; + switch (clock) { + case QEMU_CLOCK_REALTIME: + value -= rtc_realtime_clock_offset; + /* fall through */ + case QEMU_CLOCK_VIRTUAL: + value += rtc_ref_start_datetime; + break; + case QEMU_CLOCK_HOST: + if (rtc_base_type == RTC_BASE_DATETIME) { + value -= rtc_host_datetime_offset; + } + break; + default: + assert(0); + } + return value; +} + +void qemu_get_timedate(struct tm *tm, int offset) +{ + time_t ti = qemu_ref_timedate(rtc_clock); + + ti += offset; + + switch (rtc_base_type) { + case RTC_BASE_DATETIME: + case RTC_BASE_UTC: + gmtime_r(&ti, tm); + break; + case RTC_BASE_LOCALTIME: + localtime_r(&ti, tm); + break; + } +} + +int qemu_timedate_diff(struct tm *tm) +{ + time_t seconds; + + switch (rtc_base_type) { + case RTC_BASE_DATETIME: + case RTC_BASE_UTC: + seconds = mktimegm(tm); + break; + case RTC_BASE_LOCALTIME: + { + struct tm tmp = *tm; + tmp.tm_isdst = -1; /* use timezone to figure it out */ + seconds = mktime(&tmp); + break; + } + default: + abort(); + } + + return seconds - qemu_ref_timedate(QEMU_CLOCK_HOST); +} + +static void configure_rtc_base_datetime(const char *startdate) +{ + time_t rtc_start_datetime; + struct tm tm; + + if (sscanf(startdate, "%d-%d-%dT%d:%d:%d", &tm.tm_year, &tm.tm_mon, + &tm.tm_mday, &tm.tm_hour, &tm.tm_min, &tm.tm_sec) == 6) { + /* OK */ + } else if (sscanf(startdate, "%d-%d-%d", + &tm.tm_year, &tm.tm_mon, &tm.tm_mday) == 3) { + tm.tm_hour = 0; + tm.tm_min = 0; + tm.tm_sec = 0; + } else { + goto date_fail; + } + tm.tm_year -= 1900; + tm.tm_mon--; + rtc_start_datetime = mktimegm(&tm); + if (rtc_start_datetime == -1) { + date_fail: + error_report("invalid datetime format"); + error_printf("valid formats: " + "'2006-06-17T16:01:21' or '2006-06-17'\n"); + exit(1); + } + rtc_host_datetime_offset = rtc_ref_start_datetime - rtc_start_datetime; + rtc_ref_start_datetime = rtc_start_datetime; +} + +void configure_rtc(QemuOpts *opts) +{ + const char *value; + + /* Set defaults */ + rtc_clock = QEMU_CLOCK_HOST; + rtc_ref_start_datetime = qemu_clock_get_ms(QEMU_CLOCK_HOST) / 1000; + rtc_realtime_clock_offset = qemu_clock_get_ms(QEMU_CLOCK_REALTIME) / 1000; + + value = qemu_opt_get(opts, "base"); + if (value) { + if (!strcmp(value, "utc")) { + rtc_base_type = RTC_BASE_UTC; + } else if (!strcmp(value, "localtime")) { + Error *blocker = NULL; + rtc_base_type = RTC_BASE_LOCALTIME; + error_setg(&blocker, QERR_REPLAY_NOT_SUPPORTED, + "-rtc base=localtime"); + replay_add_blocker(blocker); + } else { + rtc_base_type = RTC_BASE_DATETIME; + configure_rtc_base_datetime(value); + } + } + value = qemu_opt_get(opts, "clock"); + if (value) { + if (!strcmp(value, "host")) { + rtc_clock = QEMU_CLOCK_HOST; + } else if (!strcmp(value, "rt")) { + rtc_clock = QEMU_CLOCK_REALTIME; + } else if (!strcmp(value, "vm")) { + rtc_clock = QEMU_CLOCK_VIRTUAL; + } else { + error_report("invalid option value '%s'", value); + exit(1); + } + } + value = qemu_opt_get(opts, "driftfix"); + if (value) { + if (!strcmp(value, "slew")) { + object_register_sugar_prop("mc146818rtc", + "lost_tick_policy", + "slew"); + } else if (!strcmp(value, "none")) { + /* discard is default */ + } else { + error_report("invalid option value '%s'", value); + exit(1); + } + } +} diff --git a/softmmu/vl.c b/softmmu/vl.c index 852ecf08e1..4c95537af3 100644 --- a/softmmu/vl.c +++ b/softmmu/vl.c @@ -152,16 +152,6 @@ bool enable_cpu_pm = false; int nb_nics; NICInfo nd_table[MAX_NICS]; int autostart = 1; -static enum { - RTC_BASE_UTC, - RTC_BASE_LOCALTIME, - RTC_BASE_DATETIME, -} rtc_base_type = RTC_BASE_UTC; -static time_t rtc_ref_start_datetime; -static int rtc_realtime_clock_offset; /* used only with QEMU_CLOCK_REALTIME */ -static int rtc_host_datetime_offset = -1; /* valid & used only with - RTC_BASE_DATETIME */ -QEMUClockType rtc_clock; int vga_interface_type = VGA_NONE; static const char *vga_model = NULL; static DisplayOptions dpy; @@ -772,152 +762,6 @@ void qemu_system_vmstop_request(RunState state) qemu_mutex_unlock(&vmstop_lock); qemu_notify_event(); } - -/***********************************************************/ -/* RTC reference time/date access */ -static time_t qemu_ref_timedate(QEMUClockType clock) -{ - time_t value = qemu_clock_get_ms(clock) / 1000; - switch (clock) { - case QEMU_CLOCK_REALTIME: - value -= rtc_realtime_clock_offset; - /* fall through */ - case QEMU_CLOCK_VIRTUAL: - value += rtc_ref_start_datetime; - break; - case QEMU_CLOCK_HOST: - if (rtc_base_type == RTC_BASE_DATETIME) { - value -= rtc_host_datetime_offset; - } - break; - default: - assert(0); - } - return value; -} - -void qemu_get_timedate(struct tm *tm, int offset) -{ - time_t ti = qemu_ref_timedate(rtc_clock); - - ti += offset; - - switch (rtc_base_type) { - case RTC_BASE_DATETIME: - case RTC_BASE_UTC: - gmtime_r(&ti, tm); - break; - case RTC_BASE_LOCALTIME: - localtime_r(&ti, tm); - break; - } -} - -int qemu_timedate_diff(struct tm *tm) -{ - time_t seconds; - - switch (rtc_base_type) { - case RTC_BASE_DATETIME: - case RTC_BASE_UTC: - seconds = mktimegm(tm); - break; - case RTC_BASE_LOCALTIME: - { - struct tm tmp = *tm; - tmp.tm_isdst = -1; /* use timezone to figure it out */ - seconds = mktime(&tmp); - break; - } - default: - abort(); - } - - return seconds - qemu_ref_timedate(QEMU_CLOCK_HOST); -} - -static void configure_rtc_base_datetime(const char *startdate) -{ - time_t rtc_start_datetime; - struct tm tm; - - if (sscanf(startdate, "%d-%d-%dT%d:%d:%d", &tm.tm_year, &tm.tm_mon, - &tm.tm_mday, &tm.tm_hour, &tm.tm_min, &tm.tm_sec) == 6) { - /* OK */ - } else if (sscanf(startdate, "%d-%d-%d", - &tm.tm_year, &tm.tm_mon, &tm.tm_mday) == 3) { - tm.tm_hour = 0; - tm.tm_min = 0; - tm.tm_sec = 0; - } else { - goto date_fail; - } - tm.tm_year -= 1900; - tm.tm_mon--; - rtc_start_datetime = mktimegm(&tm); - if (rtc_start_datetime == -1) { - date_fail: - error_report("invalid datetime format"); - error_printf("valid formats: " - "'2006-06-17T16:01:21' or '2006-06-17'\n"); - exit(1); - } - rtc_host_datetime_offset = rtc_ref_start_datetime - rtc_start_datetime; - rtc_ref_start_datetime = rtc_start_datetime; -} - -static void configure_rtc(QemuOpts *opts) -{ - const char *value; - - /* Set defaults */ - rtc_clock = QEMU_CLOCK_HOST; - rtc_ref_start_datetime = qemu_clock_get_ms(QEMU_CLOCK_HOST) / 1000; - rtc_realtime_clock_offset = qemu_clock_get_ms(QEMU_CLOCK_REALTIME) / 1000; - - value = qemu_opt_get(opts, "base"); - if (value) { - if (!strcmp(value, "utc")) { - rtc_base_type = RTC_BASE_UTC; - } else if (!strcmp(value, "localtime")) { - Error *blocker = NULL; - rtc_base_type = RTC_BASE_LOCALTIME; - error_setg(&blocker, QERR_REPLAY_NOT_SUPPORTED, - "-rtc base=localtime"); - replay_add_blocker(blocker); - } else { - rtc_base_type = RTC_BASE_DATETIME; - configure_rtc_base_datetime(value); - } - } - value = qemu_opt_get(opts, "clock"); - if (value) { - if (!strcmp(value, "host")) { - rtc_clock = QEMU_CLOCK_HOST; - } else if (!strcmp(value, "rt")) { - rtc_clock = QEMU_CLOCK_REALTIME; - } else if (!strcmp(value, "vm")) { - rtc_clock = QEMU_CLOCK_VIRTUAL; - } else { - error_report("invalid option value '%s'", value); - exit(1); - } - } - value = qemu_opt_get(opts, "driftfix"); - if (value) { - if (!strcmp(value, "slew")) { - object_register_sugar_prop("mc146818rtc", - "lost_tick_policy", - "slew"); - } else if (!strcmp(value, "none")) { - /* discard is default */ - } else { - error_report("invalid option value '%s'", value); - exit(1); - } - } -} - static int parse_name(void *opaque, QemuOpts *opts, Error **errp) { const char *proc_name; From 46ee119fb64570c6efdff3342fbec3e86267bda3 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Tue, 3 Nov 2020 03:26:05 -0500 Subject: [PATCH 079/113] vl: remove serial_max_hds serial_hd(i) is NULL if and only if i >= serial_max_hds(). Test serial_hd(i) instead of bounding the loop at serial_max_hds(), thus removing one more function that vl.c is expected to export. Reviewed-by: Igor Mammedov Signed-off-by: Paolo Bonzini --- hw/ppc/spapr.c | 6 ++---- include/sysemu/sysemu.h | 4 ---- softmmu/vl.c | 5 ----- 3 files changed, 2 insertions(+), 13 deletions(-) diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index 3f5b0d0159..6abb45d0ed 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -2878,10 +2878,8 @@ static void spapr_machine_init(MachineState *machine) /* Set up VIO bus */ spapr->vio_bus = spapr_vio_bus_init(); - for (i = 0; i < serial_max_hds(); i++) { - if (serial_hd(i)) { - spapr_vty_create(spapr->vio_bus, serial_hd(i)); - } + for (i = 0; serial_hd(i); i++) { + spapr_vty_create(spapr->vio_bus, serial_hd(i)); } /* We always have at least the nvram device on VIO */ diff --git a/include/sysemu/sysemu.h b/include/sysemu/sysemu.h index 18cf586cd0..29c32f9851 100644 --- a/include/sysemu/sysemu.h +++ b/include/sysemu/sysemu.h @@ -71,10 +71,6 @@ void hmp_pcie_aer_inject_error(Monitor *mon, const QDict *qdict); /* Return the Chardev for serial port i, or NULL if none */ Chardev *serial_hd(int i); -/* return the number of serial ports defined by the user. serial_hd(i) - * will always return NULL for any i which is greater than or equal to this. - */ -int serial_max_hds(void); /* parallel ports */ diff --git a/softmmu/vl.c b/softmmu/vl.c index 4c95537af3..43a0a45b68 100644 --- a/softmmu/vl.c +++ b/softmmu/vl.c @@ -2159,11 +2159,6 @@ Chardev *serial_hd(int i) return NULL; } -int serial_max_hds(void) -{ - return num_serial_hds; -} - static int parallel_parse(const char *devname) { static int index = 0; From 4b7acd2ac82159fe193c0babf95aa9962d68a700 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Fri, 13 Nov 2020 02:41:38 -0500 Subject: [PATCH 080/113] vl: clean up -boot variables Move more of them into MachineState, in preparation for moving initialization of the machine out of vl.c. Reviewed-by: Igor Mammedov Signed-off-by: Paolo Bonzini --- include/hw/boards.h | 1 + softmmu/vl.c | 12 ++++++------ 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/include/hw/boards.h b/include/hw/boards.h index 3a1968d035..17b1f3f0b9 100644 --- a/include/hw/boards.h +++ b/include/hw/boards.h @@ -283,6 +283,7 @@ struct MachineState { ram_addr_t maxram_size; uint64_t ram_slots; const char *boot_order; + const char *boot_once; char *kernel_filename; char *kernel_cmdline; char *initrd_filename; diff --git a/softmmu/vl.c b/softmmu/vl.c index 43a0a45b68..77ee044c42 100644 --- a/softmmu/vl.c +++ b/softmmu/vl.c @@ -130,8 +130,6 @@ typedef QSIMPLEQ_HEAD(, BlockdevOptionsQueueEntry) BlockdevOptionsQueue; static const char *cpu_option; static const char *mem_path; -static const char *boot_order; -static const char *boot_once; static const char *incoming; static const char *loadvm; static ram_addr_t maxram_size; @@ -2472,6 +2470,8 @@ static void qemu_apply_machine_options(void) { MachineClass *machine_class = MACHINE_GET_CLASS(current_machine); QemuOpts *machine_opts = qemu_get_machine_opts(); + const char *boot_order = NULL; + const char *boot_once = NULL; QemuOpts *opts; qemu_opt_foreach(machine_opts, machine_set_property, current_machine, @@ -2501,6 +2501,7 @@ static void qemu_apply_machine_options(void) } current_machine->boot_order = boot_order; + current_machine->boot_once = boot_once; if (semihosting_enabled() && !semihosting_get_argc()) { const char *kernel_filename = qemu_opt_get(machine_opts, "kernel"); @@ -2508,7 +2509,6 @@ static void qemu_apply_machine_options(void) /* fall back to the -kernel/-append */ semihosting_arg_fallback(kernel_filename, kernel_cmdline); } - } static void qemu_create_early_backends(void) @@ -3220,9 +3220,9 @@ static void qemu_machine_creation_done(void) qdev_prop_check_globals(); - if (boot_once) { - qemu_boot_set(boot_once, &error_fatal); - qemu_register_reset(restore_boot_order, g_strdup(boot_order)); + if (current_machine->boot_once) { + qemu_boot_set(current_machine->boot_once, &error_fatal); + qemu_register_reset(restore_boot_order, g_strdup(current_machine->boot_order)); } if (foreach_device_config(DEV_GDB, gdbserver_start) < 0) { From ed7fa564cb104070213eb6184573a0074827bdb8 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 12 Nov 2020 08:16:22 -0500 Subject: [PATCH 081/113] config-file: move -set implementation to vl.c We want to make it independent of QemuOpts. Signed-off-by: Paolo Bonzini Signed-off-by: Paolo Bonzini --- include/qemu/config-file.h | 1 - softmmu/vl.c | 33 +++++++++++++++++++++++++++++++++ util/qemu-config.c | 33 --------------------------------- 3 files changed, 33 insertions(+), 34 deletions(-) diff --git a/include/qemu/config-file.h b/include/qemu/config-file.h index d74f920152..29226107bd 100644 --- a/include/qemu/config-file.h +++ b/include/qemu/config-file.h @@ -8,7 +8,6 @@ QemuOpts *qemu_find_opts_singleton(const char *group); void qemu_add_opts(QemuOptsList *list); void qemu_add_drive_opts(QemuOptsList *list); -int qemu_set_option(const char *str); int qemu_global_option(const char *str); void qemu_config_write(FILE *fp); diff --git a/softmmu/vl.c b/softmmu/vl.c index 77ee044c42..7146fbe219 100644 --- a/softmmu/vl.c +++ b/softmmu/vl.c @@ -2797,6 +2797,39 @@ static int qemu_read_default_config_file(void) return 0; } +static int qemu_set_option(const char *str) +{ + Error *local_err = NULL; + char group[64], id[64], arg[64]; + QemuOptsList *list; + QemuOpts *opts; + int rc, offset; + + rc = sscanf(str, "%63[^.].%63[^.].%63[^=]%n", group, id, arg, &offset); + if (rc < 3 || str[offset] != '=') { + error_report("can't parse: \"%s\"", str); + return -1; + } + + list = qemu_find_opts(group); + if (list == NULL) { + return -1; + } + + opts = qemu_opts_find(list, id); + if (!opts) { + error_report("there is no %s \"%s\" defined", + list->name, id); + return -1; + } + + if (!qemu_opt_set(opts, arg, str + offset + 1, &local_err)) { + error_report_err(local_err); + return -1; + } + return 0; +} + static void user_register_global_props(void) { qemu_opts_foreach(qemu_find_opts("global"), diff --git a/util/qemu-config.c b/util/qemu-config.c index 660f47b005..725e3d7e4b 100644 --- a/util/qemu-config.c +++ b/util/qemu-config.c @@ -313,39 +313,6 @@ void qemu_add_opts(QemuOptsList *list) abort(); } -int qemu_set_option(const char *str) -{ - Error *local_err = NULL; - char group[64], id[64], arg[64]; - QemuOptsList *list; - QemuOpts *opts; - int rc, offset; - - rc = sscanf(str, "%63[^.].%63[^.].%63[^=]%n", group, id, arg, &offset); - if (rc < 3 || str[offset] != '=') { - error_report("can't parse: \"%s\"", str); - return -1; - } - - list = qemu_find_opts(group); - if (list == NULL) { - return -1; - } - - opts = qemu_opts_find(list, id); - if (!opts) { - error_report("there is no %s \"%s\" defined", - list->name, id); - return -1; - } - - if (!qemu_opt_set(opts, arg, str + offset + 1, &local_err)) { - error_report_err(local_err); - return -1; - } - return 0; -} - struct ConfigWriteData { QemuOptsList *list; FILE *fp; From f79248b53bee83bb8e69c8b2e9d70d6d28039987 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 30 Nov 2020 07:16:11 -0500 Subject: [PATCH 082/113] docs: temporarily disable the kernel-doc extension Preserve bisectability while we update scripts/kernel-doc from Linux. Without this patch, building with Sphinx 3 would break while we revert our own Sphinx 3 support and replace it with Linux's. Suggested-by: Peter Maydell Signed-off-by: Paolo Bonzini --- docs/sphinx/kerneldoc.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/sphinx/kerneldoc.py b/docs/sphinx/kerneldoc.py index 3ac277d162..9124fcbff1 100644 --- a/docs/sphinx/kerneldoc.py +++ b/docs/sphinx/kerneldoc.py @@ -75,6 +75,9 @@ def run(self): # Tell sphinx of the dependency env.note_dependency(os.path.abspath(filename)) + # Disabled temporarily while scripts/kernel-doc is updated + return [] + tab_width = self.options.get('tab-width', self.state.document.settings.tab_width) # FIXME: make this nicer and more robust against errors From 872e6c47a083be5afb82b40aae849c7108ae5584 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Almeida?= Date: Tue, 17 Nov 2020 17:52:44 +0100 Subject: [PATCH 083/113] kernel-doc: fix processing nested structs with attributes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The current regular expression for strip attributes of structs (and for nested ones as well) also removes all whitespaces that may surround the attribute. After that, the code will split structs and iterate for each symbol separated by comma at the end of struct definition (e.g. "} alias1, alias2;"). However, if the nested struct does not have any alias and has an attribute, it will result in a empty string at the closing bracket (e.g "};"). This will make the split return nothing and $newmember will keep uninitialized. Fix that, by ensuring that the attribute substitution will leave at least one whitespace. Signed-off-by: André Almeida Signed-off-by: Jonathan Corbet Signed-off-by: Paolo Bonzini Message-Id: <20201117165312.118257-2-pbonzini@redhat.com> Signed-off-by: Paolo Bonzini --- scripts/kernel-doc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/scripts/kernel-doc b/scripts/kernel-doc index 4fbaaa05e3..d6bdb77ceb 100755 --- a/scripts/kernel-doc +++ b/scripts/kernel-doc @@ -1103,10 +1103,10 @@ sub dump_struct($$) { # strip comments: $members =~ s/\/\*.*?\*\///gos; # strip attributes - $members =~ s/\s*__attribute__\s*\(\([a-z0-9,_\*\s\(\)]*\)\)//gi; - $members =~ s/\s*__aligned\s*\([^;]*\)//gos; - $members =~ s/\s*__packed\s*//gos; - $members =~ s/\s*CRYPTO_MINALIGN_ATTR//gos; + $members =~ s/\s*__attribute__\s*\(\([a-z0-9,_\*\s\(\)]*\)\)/ /gi; + $members =~ s/\s*__aligned\s*\([^;]*\)/ /gos; + $members =~ s/\s*__packed\s*/ /gos; + $members =~ s/\s*CRYPTO_MINALIGN_ATTR/ /gos; # replace DECLARE_BITMAP $members =~ s/DECLARE_BITMAP\s*\(([^,)]+),\s*([^,)]+)\)/unsigned long $1\[BITS_TO_LONGS($2)\]/gos; # replace DECLARE_HASHTABLE From b5a8dfb5328a5546d52522b4b3504a79464aa3cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Almeida?= Date: Tue, 17 Nov 2020 17:52:45 +0100 Subject: [PATCH 084/113] kernel-doc: add support for ____cacheline_aligned_in_smp attribute MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Subroutine dump_struct uses type attributes to check if the struct syntax is valid. Then, it removes all attributes before using it for output. `____cacheline_aligned_in_smp` is an attribute that is not included in both steps. Add it, since it is used by kernel structs. Signed-off-by: André Almeida Signed-off-by: Jonathan Corbet Signed-off-by: Paolo Bonzini Message-Id: <20201117165312.118257-3-pbonzini@redhat.com> Signed-off-by: Paolo Bonzini --- scripts/kernel-doc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scripts/kernel-doc b/scripts/kernel-doc index d6bdb77ceb..2f421b7313 100755 --- a/scripts/kernel-doc +++ b/scripts/kernel-doc @@ -1092,7 +1092,7 @@ sub dump_struct($$) { my $x = shift; my $file = shift; - if ($x =~ /(struct|union)\s+(\w+)\s*\{(.*)\}(\s*(__packed|__aligned|__attribute__\s*\(\([a-z0-9,_\s\(\)]*\)\)))*/) { + if ($x =~ /(struct|union)\s+(\w+)\s*\{(.*)\}(\s*(__packed|__aligned|____cacheline_aligned_in_smp|__attribute__\s*\(\([a-z0-9,_\s\(\)]*\)\)))*/) { my $decl_type = $1; $declaration_name = $2; my $members = $3; @@ -1107,6 +1107,7 @@ sub dump_struct($$) { $members =~ s/\s*__aligned\s*\([^;]*\)/ /gos; $members =~ s/\s*__packed\s*/ /gos; $members =~ s/\s*CRYPTO_MINALIGN_ATTR/ /gos; + $members =~ s/\s*____cacheline_aligned_in_smp/ /gos; # replace DECLARE_BITMAP $members =~ s/DECLARE_BITMAP\s*\(([^,)]+),\s*([^,)]+)\)/unsigned long $1\[BITS_TO_LONGS($2)\]/gos; # replace DECLARE_HASHTABLE From 65fb67bf73603a218aa1d39286a452058364f253 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonathan=20Neusch=C3=A4fer?= Date: Tue, 17 Nov 2020 17:52:46 +0100 Subject: [PATCH 085/113] scripts/kernel-doc: Add support for named variable macro arguments MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently, when kernel-doc encounters a macro with a named variable argument[1], such as this: #define hlist_for_each_entry_rcu(pos, head, member, cond...) ... it expects the variable argument to be documented as `cond...`, rather than `cond`. This is semantically wrong, because the name (as used in the macro body) is actually `cond`. With this patch, kernel-doc will accept the name without dots (`cond` in the example above) in doc comments, and warn if the name with dots (`cond...`) is used and verbose mode[2] is enabled. The support for the `cond...` syntax can be removed later, when the documentation of all such macros has been switched to the new syntax. Testing this patch on top of v5.4-rc6, `make htmldocs` shows a few changes in log output and HTML output: 1) The following warnings[3] are eliminated: ./include/linux/rculist.h:374: warning: Excess function parameter 'cond' description in 'list_for_each_entry_rcu' ./include/linux/rculist.h:651: warning: Excess function parameter 'cond' description in 'hlist_for_each_entry_rcu' 2) For list_for_each_entry_rcu and hlist_for_each_entry_rcu, the correct description is shown 3) Named variable arguments are shown without dots [1]: https://gcc.gnu.org/onlinedocs/cpp/Variadic-Macros.html [2]: scripts/kernel-doc -v [3]: See also https://git.kernel.org/pub/scm/linux/kernel/git/paulmck/linux-rcu.git/commit/?h=dev&id=5bc4bc0d6153617eabde275285b7b5a8137fdf3c Signed-off-by: Jonathan Neuschäfer Tested-by: Paul E. McKenney Signed-off-by: Jonathan Corbet Signed-off-by: Paolo Bonzini Message-Id: <20201117165312.118257-4-pbonzini@redhat.com> Signed-off-by: Paolo Bonzini --- scripts/kernel-doc | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/scripts/kernel-doc b/scripts/kernel-doc index 2f421b7313..0f67664165 100755 --- a/scripts/kernel-doc +++ b/scripts/kernel-doc @@ -1480,6 +1480,10 @@ sub push_parameter($$$$) { # handles unnamed variable parameters $param = "..."; } + elsif ($param =~ /\w\.\.\.$/) { + # for named variable parameters of the form `x...`, remove the dots + $param =~ s/\.\.\.$//; + } if (!defined $parameterdescs{$param} || $parameterdescs{$param} eq "") { $parameterdescs{$param} = "variable arguments"; } @@ -1967,6 +1971,18 @@ sub process_name($$) { sub process_body($$) { my $file = shift; + # Until all named variable macro parameters are + # documented using the bare name (`x`) rather than with + # dots (`x...`), strip the dots: + if ($section =~ /\w\.\.\.$/) { + $section =~ s/\.\.\.$//; + + if ($verbose) { + print STDERR "${file}:$.: warning: Variable macro arguments should be documented without dots\n"; + ++$warnings; + } + } + if (/$doc_sect/i) { # case insensitive for supported section names $newsection = $1; $newcontents = $2; From 76083982a561fb9e24931b0e25cffb5865269eba Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 17 Nov 2020 17:52:47 +0100 Subject: [PATCH 086/113] scripts: kernel-doc: proper handle @foo->bar() The pattern @foo->bar() is valid, as it can be used by a function pointer inside a struct passed as a parameter. Right now, it causes a warning: ./drivers/firewire/core-transaction.c:606: WARNING: Inline strong start-string without end-string. In this specific case, the kernel-doc markup is: /** * fw_core_remove_address_handler() - unregister an address handler * @handler: callback * * To be called in process context. * * When fw_core_remove_address_handler() returns, @handler->callback() is * guaranteed to not run on any CPU anymore. */ With seems valid on my eyes. So, instead of trying to hack the kernel-doc markup, let's teach it about how to handle such things. This should likely remove lots of other similar warnings as well. Signed-off-by: Mauro Carvalho Chehab Link: https://lore.kernel.org/r/48b46426d7bf6ff7529f20e5718fbf4e9758e62c.1586881715.git.mchehab+huawei@kernel.org Signed-off-by: Jonathan Corbet Signed-off-by: Paolo Bonzini Message-Id: <20201117165312.118257-5-pbonzini@redhat.com> Signed-off-by: Paolo Bonzini --- scripts/kernel-doc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/scripts/kernel-doc b/scripts/kernel-doc index 0f67664165..99530fb08b 100755 --- a/scripts/kernel-doc +++ b/scripts/kernel-doc @@ -216,6 +216,7 @@ my $type_constant2 = '\%([-_\w]+)'; my $type_func = '(\w+)\(\)'; my $type_param = '\@(\w*((\.\w+)|(->\w+))*(\.\.\.)?)'; my $type_fp_param = '\@(\w+)\(\)'; # Special RST handling for func ptr params +my $type_fp_param2 = '\@(\w+->\S+)\(\)'; # Special RST handling for structs with func ptr params my $type_env = '(\$\w+)'; my $type_enum = '#(enum\s*([_\w]+))'; my $type_struct = '#(struct\s*([_\w]+))'; @@ -251,6 +252,7 @@ my @highlights_rst = ( [$type_member_func, "\\:c\\:type\\:`\$1\$2\$3\\\\(\\\\) <\$1>`"], [$type_member, "\\:c\\:type\\:`\$1\$2\$3 <\$1>`"], [$type_fp_param, "**\$1\\\\(\\\\)**"], + [$type_fp_param2, "**\$1\\\\(\\\\)**"], [$type_func, "\$1()"], [$type_enum, "\\:c\\:type\\:`\$1 <\$2>`"], [$type_struct, "\\:c\\:type\\:`\$1 <\$2>`"], From b1e8e720b649ad1b7275d7eeef841c2528a63fe1 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 17 Nov 2020 17:52:48 +0100 Subject: [PATCH 087/113] scripts: kernel-doc: accept negation like !@var On a few places, it sometimes need to indicate a negation of a parameter, like: !@fshared This pattern happens, for example, at: kernel/futex.c and it is perfectly valid. However, kernel-doc currently transforms it into: !**fshared** This won't do what it would be expected. Fortunately, fixing the script is a simple matter of storing the "!" before "@" and adding it after the bold markup, like: **!fshared** Signed-off-by: Mauro Carvalho Chehab Link: https://lore.kernel.org/r/0314b47f8c3e1f9db00d5375a73dc3cddd8a21f2.1586881715.git.mchehab+huawei@kernel.org Signed-off-by: Jonathan Corbet Signed-off-by: Paolo Bonzini Message-Id: <20201117165312.118257-6-pbonzini@redhat.com> Signed-off-by: Paolo Bonzini --- scripts/kernel-doc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/scripts/kernel-doc b/scripts/kernel-doc index 99530fb08b..e4b3cd486f 100755 --- a/scripts/kernel-doc +++ b/scripts/kernel-doc @@ -215,6 +215,7 @@ my $type_constant = '\b``([^\`]+)``\b'; my $type_constant2 = '\%([-_\w]+)'; my $type_func = '(\w+)\(\)'; my $type_param = '\@(\w*((\.\w+)|(->\w+))*(\.\.\.)?)'; +my $type_param_ref = '([\!]?)\@(\w*((\.\w+)|(->\w+))*(\.\.\.)?)'; my $type_fp_param = '\@(\w+)\(\)'; # Special RST handling for func ptr params my $type_fp_param2 = '\@(\w+->\S+)\(\)'; # Special RST handling for structs with func ptr params my $type_env = '(\$\w+)'; @@ -239,6 +240,7 @@ my @highlights_man = ( [$type_typedef, "\\\\fI\$1\\\\fP"], [$type_union, "\\\\fI\$1\\\\fP"], [$type_param, "\\\\fI\$1\\\\fP"], + [$type_param_ref, "\\\\fI\$1\$2\\\\fP"], [$type_member, "\\\\fI\$1\$2\$3\\\\fP"], [$type_fallback, "\\\\fI\$1\\\\fP"] ); @@ -260,7 +262,7 @@ my @highlights_rst = ( [$type_union, "\\:c\\:type\\:`\$1 <\$2>`"], # in rst this can refer to any type [$type_fallback, "\\:c\\:type\\:`\$1`"], - [$type_param, "**\$1**"] + [$type_param_ref, "**\$1\$2**"] ); my $blankline_rst = "\n"; From 9f2b463ad8beb76acaf3f5d1654b660592760e68 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 17 Nov 2020 17:52:49 +0100 Subject: [PATCH 088/113] scripts: kernel-doc: accept blank lines on parameter description Sphinx is very pedantic with respect to blank lines. Sometimes, in order to make it to properly handle something, we need to add a blank line. However, currently, any blank line inside a kernel-doc comment like: /* * @foo: bar * * foobar * * some description will be considered as if "foobar" was part of the description. This patch changes kernel-doc behavior. After it, foobar will be considered as part of the parameter text. The description will only be considered as such if it starts with: zero spaces after asterisk: *foo one space after asterisk: * foo or have a explicit Description section: * Description: Signed-off-by: Mauro Carvalho Chehab Link: https://lore.kernel.org/r/c07d2862792d75a2691d69c9eceb7b89a0164cc0.1586881715.git.mchehab+huawei@kernel.org Signed-off-by: Jonathan Corbet Signed-off-by: Paolo Bonzini Message-Id: <20201117165312.118257-7-pbonzini@redhat.com> Signed-off-by: Paolo Bonzini --- scripts/kernel-doc | 35 +++++++++++++++++++++++------------ 1 file changed, 23 insertions(+), 12 deletions(-) diff --git a/scripts/kernel-doc b/scripts/kernel-doc index e4b3cd486f..95f2d7adcf 100755 --- a/scripts/kernel-doc +++ b/scripts/kernel-doc @@ -334,13 +334,14 @@ my $lineprefix=""; # Parser states use constant { - STATE_NORMAL => 0, # normal code - STATE_NAME => 1, # looking for function name - STATE_BODY_MAYBE => 2, # body - or maybe more description - STATE_BODY => 3, # the body of the comment - STATE_PROTO => 4, # scanning prototype - STATE_DOCBLOCK => 5, # documentation block - STATE_INLINE => 6, # gathering documentation outside main block + STATE_NORMAL => 0, # normal code + STATE_NAME => 1, # looking for function name + STATE_BODY_MAYBE => 2, # body - or maybe more description + STATE_BODY => 3, # the body of the comment + STATE_BODY_WITH_BLANK_LINE => 4, # the body, which has a blank line + STATE_PROTO => 5, # scanning prototype + STATE_DOCBLOCK => 6, # documentation block + STATE_INLINE => 7, # gathering doc outside main block }; my $state; my $in_doc_sect; @@ -1987,6 +1988,12 @@ sub process_body($$) { } } + if ($state == STATE_BODY_WITH_BLANK_LINE && /^\s*\*\s?\S/) { + dump_section($file, $section, $contents); + $section = $section_default; + $contents = ""; + } + if (/$doc_sect/i) { # case insensitive for supported section names $newsection = $1; $newcontents = $2; @@ -2040,18 +2047,21 @@ sub process_body($$) { $state = STATE_PROTO; $brcount = 0; } elsif (/$doc_content/) { - # miguel-style comment kludge, look for blank lines after - # @parameter line to signify start of description if ($1 eq "") { - if ($section =~ m/^@/ || $section eq $section_context) { + if ($section eq $section_context) { dump_section($file, $section, $contents); $section = $section_default; $contents = ""; $new_start_line = $.; + $state = STATE_BODY; } else { + if ($section ne $section_default) { + $state = STATE_BODY_WITH_BLANK_LINE; + } else { + $state = STATE_BODY; + } $contents .= "\n"; } - $state = STATE_BODY; } elsif ($state == STATE_BODY_MAYBE) { # Continued declaration purpose chomp($declaration_purpose); @@ -2203,7 +2213,8 @@ sub process_file($) { process_normal(); } elsif ($state == STATE_NAME) { process_name($file, $_); - } elsif ($state == STATE_BODY || $state == STATE_BODY_MAYBE) { + } elsif ($state == STATE_BODY || $state == STATE_BODY_MAYBE || + $state == STATE_BODY_WITH_BLANK_LINE) { process_body($file, $_); } elsif ($state == STATE_INLINE) { # scanning for inline parameters process_inline($file, $_); From cd08b80952657ab9f9ca5b8f374982d9c3159f4a Mon Sep 17 00:00:00 2001 From: "Alexander A. Klimov" Date: Tue, 17 Nov 2020 17:52:50 +0100 Subject: [PATCH 089/113] Replace HTTP links with HTTPS ones: documentation Rationale: Reduces attack surface on kernel devs opening the links for MITM as HTTPS traffic is much harder to manipulate. Deterministic algorithm: For each file: For each line: If doesn't contain `\bxmlns\b`: For each link, `\bhttp://[^# \t\r\n]*(?:\w|/)`: If both the HTTP and HTTPS versions return 200 OK and serve the same content: Replace HTTP with HTTPS. Signed-off-by: Alexander A. Klimov Link: https://lore.kernel.org/r/20200526060544.25127-1-grandmaster@al2klimov.de Signed-off-by: Jonathan Corbet Signed-off-by: Paolo Bonzini Message-Id: <20201117165312.118257-8-pbonzini@redhat.com> Signed-off-by: Paolo Bonzini --- scripts/kernel-doc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/kernel-doc b/scripts/kernel-doc index 95f2d7adcf..fadc2f5b86 100755 --- a/scripts/kernel-doc +++ b/scripts/kernel-doc @@ -324,7 +324,7 @@ if (defined($ENV{'KBUILD_VERBOSE'})) { # Generated docbook code is inserted in a template at a point where # docbook v3.1 requires a non-zero sequence of RefEntry's; see: -# http://www.oasis-open.org/docbook/documentation/reference/html/refentry.html +# https://www.oasis-open.org/docbook/documentation/reference/html/refentry.html # We keep track of number of generated entries and generate a dummy # if needs be to ensure the expanded template can be postprocessed # into html. From f0fd307d255c007547a467bf522512f45456dab5 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 17 Nov 2020 17:52:51 +0100 Subject: [PATCH 090/113] scripts/kernel-doc: parse __ETHTOOL_DECLARE_LINK_MODE_MASK The __ETHTOOL_DECLARE_LINK_MODE_MASK macro is a variant of DECLARE_BITMAP(), used by phylink.h. As we have already a parser for DECLARE_BITMAP(), let's add one for this macro, in order to avoid such warnings: ./include/linux/phylink.h:54: warning: Function parameter or member '__ETHTOOL_DECLARE_LINK_MODE_MASK(advertising' not described in 'phylink_link_state' ./include/linux/phylink.h:54: warning: Function parameter or member '__ETHTOOL_DECLARE_LINK_MODE_MASK(lp_advertising' not described in 'phylink_link_state' Signed-off-by: Mauro Carvalho Chehab Link: https://lore.kernel.org/r/d1d1dea67a28117c0b0c33271b139c4455fef287.1592895969.git.mchehab+huawei@kernel.org Signed-off-by: Jonathan Corbet Signed-off-by: Paolo Bonzini Message-Id: <20201117165312.118257-9-pbonzini@redhat.com> Signed-off-by: Paolo Bonzini --- scripts/kernel-doc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/scripts/kernel-doc b/scripts/kernel-doc index fadc2f5b86..e8fff6a525 100755 --- a/scripts/kernel-doc +++ b/scripts/kernel-doc @@ -1113,7 +1113,9 @@ sub dump_struct($$) { $members =~ s/\s*__packed\s*/ /gos; $members =~ s/\s*CRYPTO_MINALIGN_ATTR/ /gos; $members =~ s/\s*____cacheline_aligned_in_smp/ /gos; + # replace DECLARE_BITMAP + $members =~ s/__ETHTOOL_DECLARE_LINK_MODE_MASK\s*\(([^\)]+)\)/DECLARE_BITMAP($1, __ETHTOOL_LINK_MODE_MASK_NBITS)/gos; $members =~ s/DECLARE_BITMAP\s*\(([^,)]+),\s*([^,)]+)\)/unsigned long $1\[BITS_TO_LONGS($2)\]/gos; # replace DECLARE_HASHTABLE $members =~ s/DECLARE_HASHTABLE\s*\(([^,)]+),\s*([^,)]+)\)/unsigned long $1\[1 << (($2) - 1)\]/gos; From 2552f59a348f5fc9df7af8175c20a195a1d93c4b Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 17 Nov 2020 17:52:52 +0100 Subject: [PATCH 091/113] scripts/kernel-doc: handle function pointer prototypes There are some function pointer prototypes inside the net includes, like this one: int (*pcs_config)(struct phylink_config *config, unsigned int mode, phy_interface_t interface, const unsigned long *advertising); There's nothing wrong using it with kernel-doc, but we need to add a rule for it to parse such kind of prototype. Signed-off-by: Mauro Carvalho Chehab Link: https://lore.kernel.org/r/fec520dd731a273013ae06b7653a19c7d15b9562.1592895969.git.mchehab+huawei@kernel.org Signed-off-by: Jonathan Corbet Signed-off-by: Paolo Bonzini Message-Id: <20201117165312.118257-10-pbonzini@redhat.com> Signed-off-by: Paolo Bonzini --- scripts/kernel-doc | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/scripts/kernel-doc b/scripts/kernel-doc index e8fff6a525..1cdece23fb 100755 --- a/scripts/kernel-doc +++ b/scripts/kernel-doc @@ -1801,6 +1801,11 @@ sub process_proto_function($$) { $prototype =~ s@/\*.*?\*/@@gos; # strip comments. $prototype =~ s@[\r\n]+@ @gos; # strip newlines/cr's. $prototype =~ s@^\s+@@gos; # strip leading spaces + + # Handle prototypes for function pointers like: + # int (*pcs_config)(struct foo) + $prototype =~ s@^(\S+\s+)\(\s*\*(\S+)\)@$1$2@gos; + if ($prototype =~ /SYSCALL_DEFINE/) { syscall_munge(); } From 86cba21743bed485a9474696afb5dbb3d3372ea1 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Tue, 17 Nov 2020 17:52:53 +0100 Subject: [PATCH 092/113] scripts/kernel-doc: optionally treat warnings as errors The kbuild bot recently added the W=1 option, which triggered documentation cleanups to squelch hundreds of kernel-doc warnings. To make sure new kernel contributions don't add regressions to kernel-doc descriptors, this patch suggests an option to treat warnings as errors in CI/automated tests. A -Werror command-line option is added to the kernel-doc script. When this option is set, the script will return the number of warnings found. The caller can then treat this positive return value as an error and stop the build. Using this command line option is however not straightforward when the kernel-doc script is called from other scripts. To align with typical kernel compilation or documentation generation, the Werror option is also set by checking the KCFLAGS environment variable, or if KDOC_WERROR is defined, as in the following examples: KCFLAGS="-Wall -Werror" make W=1 sound/ KCFLAGS="-Wall -Werror" make W=1 drivers/soundwire/ KDOC_WERROR=1 make htmldocs Note that in the last example the documentation build does not stop, only an additional log is provided. Credits to Randy Dunlap for suggesting the use of environment variables. Suggested-by: Randy Dunlap Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20200728162040.92467-1-pierre-louis.bossart@linux.intel.com Signed-off-by: Jonathan Corbet Signed-off-by: Paolo Bonzini Message-Id: <20201117165312.118257-11-pbonzini@redhat.com> Signed-off-by: Paolo Bonzini --- scripts/kernel-doc | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/scripts/kernel-doc b/scripts/kernel-doc index 1cdece23fb..eb635eb94c 100755 --- a/scripts/kernel-doc +++ b/scripts/kernel-doc @@ -83,6 +83,7 @@ Output selection modifiers: Other parameters: -v Verbose output, more warnings and other information. -h Print this help. + -Werror Treat warnings as errors. EOF print $message; @@ -275,6 +276,7 @@ my $kernelversion; my $dohighlight = ""; my $verbose = 0; +my $Werror = 0; my $output_mode = "rst"; my $output_preformatted = 0; my $no_doc_sections = 0; @@ -322,6 +324,18 @@ if (defined($ENV{'KBUILD_VERBOSE'})) { $verbose = "$ENV{'KBUILD_VERBOSE'}"; } +if (defined($ENV{'KDOC_WERROR'})) { + $Werror = "$ENV{'KDOC_WERROR'}"; +} + +if (defined($ENV{'KCFLAGS'})) { + my $kcflags = "$ENV{'KCFLAGS'}"; + + if ($kcflags =~ /Werror/) { + $Werror = 1; + } +} + # Generated docbook code is inserted in a template at a point where # docbook v3.1 requires a non-zero sequence of RefEntry's; see: # https://www.oasis-open.org/docbook/documentation/reference/html/refentry.html @@ -436,6 +450,8 @@ while ($ARGV[0] =~ m/^--?(.*)/) { push(@export_file_list, $file); } elsif ($cmd eq "v") { $verbose = 1; + } elsif ($cmd eq "Werror") { + $Werror = 1; } elsif (($cmd eq "h") || ($cmd eq "help")) { usage(); } elsif ($cmd eq 'no-doc-sections') { @@ -2292,4 +2308,9 @@ if ($verbose && $warnings) { print STDERR "$warnings warnings\n"; } -exit($output_mode eq "none" ? 0 : $errors); +if ($Werror && $warnings) { + print STDERR "$warnings warnings as Errors\n"; + exit($warnings); +} else { + exit($output_mode eq "none" ? 0 : $errors) +} From 697f668ad1f9e8aae6bb0666a367a1849f84f896 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 17 Nov 2020 17:52:54 +0100 Subject: [PATCH 093/113] kernel-doc: include line numbers for function prototypes This should solve bad error reports like this one: ./include/linux/iio/iio.h:0: WARNING: Unknown target name: "devm". Signed-off-by: Mauro Carvalho Chehab Link: https://lore.kernel.org/r/56eed0ba50cd726236acd12b11b55ce54854c5ea.1599660067.git.mchehab+huawei@kernel.org Signed-off-by: Jonathan Corbet Signed-off-by: Paolo Bonzini Message-Id: <20201117165312.118257-12-pbonzini@redhat.com> Signed-off-by: Paolo Bonzini --- scripts/kernel-doc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/scripts/kernel-doc b/scripts/kernel-doc index eb635eb94c..3fd6f3925e 100755 --- a/scripts/kernel-doc +++ b/scripts/kernel-doc @@ -1624,6 +1624,8 @@ sub dump_function($$) { my $file = shift; my $noret = 0; + print_lineno($.); + $prototype =~ s/^static +//; $prototype =~ s/^extern +//; $prototype =~ s/^asmlinkage +//; From 5c51f435cbcb4fe0717733ec093bb942617dcf4f Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Tue, 17 Nov 2020 17:52:55 +0100 Subject: [PATCH 094/113] kernel-doc: add support for ____cacheline_aligned attribute Subroutine dump_struct uses type attributes to check if the struct syntax is valid. Then, it removes all attributes before using it for output. `____cacheline_aligned` is an attribute that is not included in both steps. Add it, since it is used by kernel structs. Based on previous patch to add ____cacheline_aligned_in_smp. Motivated by patches to reorder this attribute to before the variable name. Whilst we could do that in all cases, that would be a massive change and it is more common in the kernel to place this particular attribute after the variable name. A quick grep suggests approximately 400 instances of which 341 have this attribute just before a semicolon and hence after the variable name. Signed-off-by: Jonathan Cameron Cc: Lee Jones Link: https://lore.kernel.org/r/20200910185415.653139-1-jic23@kernel.org Signed-off-by: Jonathan Corbet Signed-off-by: Paolo Bonzini Message-Id: <20201117165312.118257-13-pbonzini@redhat.com> Signed-off-by: Paolo Bonzini --- scripts/kernel-doc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scripts/kernel-doc b/scripts/kernel-doc index 3fd6f3925e..c4c5640ded 100755 --- a/scripts/kernel-doc +++ b/scripts/kernel-doc @@ -1113,7 +1113,7 @@ sub dump_struct($$) { my $x = shift; my $file = shift; - if ($x =~ /(struct|union)\s+(\w+)\s*\{(.*)\}(\s*(__packed|__aligned|____cacheline_aligned_in_smp|__attribute__\s*\(\([a-z0-9,_\s\(\)]*\)\)))*/) { + if ($x =~ /(struct|union)\s+(\w+)\s*\{(.*)\}(\s*(__packed|__aligned|____cacheline_aligned_in_smp|____cacheline_aligned|__attribute__\s*\(\([a-z0-9,_\s\(\)]*\)\)))*/) { my $decl_type = $1; $declaration_name = $2; my $members = $3; @@ -1129,6 +1129,7 @@ sub dump_struct($$) { $members =~ s/\s*__packed\s*/ /gos; $members =~ s/\s*CRYPTO_MINALIGN_ATTR/ /gos; $members =~ s/\s*____cacheline_aligned_in_smp/ /gos; + $members =~ s/\s*____cacheline_aligned/ /gos; # replace DECLARE_BITMAP $members =~ s/__ETHTOOL_DECLARE_LINK_MODE_MASK\s*\(([^\)]+)\)/DECLARE_BITMAP($1, __ETHTOOL_LINK_MODE_MASK_NBITS)/gos; From 306b015cfb9394199d062a0d2ff7534d37d54510 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 17 Nov 2020 17:52:56 +0100 Subject: [PATCH 095/113] scripts: kernel-doc: add support for typedef enum The PHY kernel-doc markup has gained support for documenting a typedef enum. However, right now the parser was not prepared for it. So, add support for parsing it. Fixes: 4069a572d423 ("net: phy: Document core PHY structures") Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Paolo Bonzini Message-Id: <20201117165312.118257-14-pbonzini@redhat.com> Signed-off-by: Paolo Bonzini --- scripts/kernel-doc | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/scripts/kernel-doc b/scripts/kernel-doc index c4c5640ded..073f72c7da 100755 --- a/scripts/kernel-doc +++ b/scripts/kernel-doc @@ -1295,14 +1295,22 @@ sub show_warnings($$) { sub dump_enum($$) { my $x = shift; my $file = shift; + my $members; + $x =~ s@/\*.*?\*/@@gos; # strip comments. # strip #define macros inside enums $x =~ s@#\s*((define|ifdef)\s+|endif)[^;]*;@@gos; - if ($x =~ /enum\s+(\w*)\s*\{(.*)\}/) { + if ($x =~ /typedef\s+enum\s*\{(.*)\}\s*(\w*)\s*;/) { + $declaration_name = $2; + $members = $1; + } elsif ($x =~ /enum\s+(\w*)\s*\{(.*)\}/) { $declaration_name = $1; - my $members = $2; + $members = $2; + } + + if ($declaration_name) { my %_members; $members =~ s/\s+$//; @@ -1337,8 +1345,7 @@ sub dump_enum($$) { 'sections' => \%sections, 'purpose' => $declaration_purpose }); - } - else { + } else { print STDERR "${file}:$.: error: Cannot parse enum!\n"; ++$errors; } From a832c9844de991f75fa5af3247ddd7205ef823d9 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Tue, 17 Nov 2020 17:52:57 +0100 Subject: [PATCH 096/113] Revert "scripts/kerneldoc: For Sphinx 3 use c:macro for macros with arguments" This reverts commit 92bb29f9b2c3d4a98eef5f0db935d4be291eec72. We will replace the commit with the fix from Linux. Signed-off-by: Paolo Bonzini Message-Id: <20201117165312.118257-15-pbonzini@redhat.com> Signed-off-by: Paolo Bonzini --- scripts/kernel-doc | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-) diff --git a/scripts/kernel-doc b/scripts/kernel-doc index 073f72c7da..cb603532ed 100755 --- a/scripts/kernel-doc +++ b/scripts/kernel-doc @@ -860,23 +860,7 @@ sub output_function_rst(%) { output_highlight_rst($args{'purpose'}); $start = "\n\n**Syntax**\n\n ``"; } else { - if ((split(/\./, $sphinx_version))[0] >= 3) { - # Sphinx 3 and later distinguish macros and functions and - # complain if you use c:function with something that's not - # syntactically valid as a function declaration. - # We assume that anything with a return type is a function - # and anything without is a macro. - if ($args{'functiontype'} ne "") { - print ".. c:function:: "; - } else { - print ".. c:macro:: "; - } - } else { - # Older Sphinx don't support documenting macros that take - # arguments with c:macro, and don't complain about the use - # of c:function for this. - print ".. c:function:: "; - } + print ".. c:function:: "; } if ($args{'functiontype'} ne "") { $start .= $args{'functiontype'} . " " . $args{'function'} . " ("; From 46ae6e8f8225cc8e1aef13831e850154f3fd8ae6 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Tue, 17 Nov 2020 17:52:58 +0100 Subject: [PATCH 097/113] Revert "kernel-doc: Use c:struct for Sphinx 3.0 and later" This reverts commit 152d1967f650f67b7ece3a5dda77d48069d72647. We will replace the commit with the fix from Linux. Signed-off-by: Paolo Bonzini Message-Id: <20201117165312.118257-16-pbonzini@redhat.com> Signed-off-by: Paolo Bonzini --- docs/sphinx/kerneldoc.py | 1 - scripts/kernel-doc | 16 +--------------- 2 files changed, 1 insertion(+), 16 deletions(-) diff --git a/docs/sphinx/kerneldoc.py b/docs/sphinx/kerneldoc.py index 9124fcbff1..c0180e02a2 100644 --- a/docs/sphinx/kerneldoc.py +++ b/docs/sphinx/kerneldoc.py @@ -102,7 +102,6 @@ def run(self): env.note_dependency(os.path.abspath(f)) cmd += ['-export-file', f] - cmd += ['-sphinx-version', sphinx.__version__] cmd += [filename] try: diff --git a/scripts/kernel-doc b/scripts/kernel-doc index cb603532ed..60f75cd176 100755 --- a/scripts/kernel-doc +++ b/scripts/kernel-doc @@ -71,8 +71,6 @@ Output selection (mutually exclusive): DOC: sections. May be specified multiple times. Output selection modifiers: - -sphinx-version VER Generate rST syntax for the specified Sphinx version. - Only works with reStructuredTextFormat. -no-doc-sections Do not output DOC: sections. -enable-lineno Enable output of #define LINENO lines. Only works with reStructuredText format. @@ -294,7 +292,6 @@ use constant { }; my $output_selection = OUTPUT_ALL; my $show_not_found = 0; # No longer used -my $sphinx_version = "0.0"; # if not specified, assume old my @export_file_list; @@ -460,8 +457,6 @@ while ($ARGV[0] =~ m/^--?(.*)/) { $enable_lineno = 1; } elsif ($cmd eq 'show-not-found') { $show_not_found = 1; # A no-op but don't fail - } elsif ($cmd eq 'sphinx-version') { - $sphinx_version = shift @ARGV; } else { # Unknown argument usage(); @@ -989,16 +984,7 @@ sub output_struct_rst(%) { my $oldprefix = $lineprefix; my $name = $args{'type'} . " " . $args{'struct'}; - # Sphinx 3.0 and up will emit warnings for "c:type:: struct Foo". - # It wants to see "c:struct:: Foo" (and will add the word 'struct' in - # the rendered output). - if ((split(/\./, $sphinx_version))[0] >= 3) { - my $sname = $name; - $sname =~ s/^struct //; - print "\n\n.. c:struct:: " . $sname . "\n\n"; - } else { - print "\n\n.. c:type:: " . $name . "\n\n"; - } + print "\n\n.. c:type:: " . $name . "\n\n"; print_lineno($declaration_start_line); $lineprefix = " "; output_highlight_rst($args{'purpose'}); From 6d3a3cfc2f1ca323b671ecdb48f4b9ec73583ea4 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 17 Nov 2020 17:52:59 +0100 Subject: [PATCH 098/113] scripts: kernel-doc: make it more compatible with Sphinx 3.x With Sphinx 3.x, the ".. c:type:" tag was changed to accept either: .. c:type:: typedef-like declaration .. c:type:: name Using it for other types (including functions) don't work anymore. So, there are newer tags for macro, enum, struct, union, and others, which doesn't exist on older versions. Add a check for the Sphinx version and change the produced tags accordingly. Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Paolo Bonzini Message-Id: <20201117165312.118257-17-pbonzini@redhat.com> Signed-off-by: Paolo Bonzini --- scripts/kernel-doc | 71 ++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 65 insertions(+), 6 deletions(-) diff --git a/scripts/kernel-doc b/scripts/kernel-doc index 60f75cd176..771367a6ab 100755 --- a/scripts/kernel-doc +++ b/scripts/kernel-doc @@ -271,6 +271,8 @@ if ($#ARGV == -1) { } my $kernelversion; +my $sphinx_major; + my $dohighlight = ""; my $verbose = 0; @@ -465,6 +467,43 @@ while ($ARGV[0] =~ m/^--?(.*)/) { # continue execution near EOF; +# The C domain dialect changed on Sphinx 3. So, we need to check the +# version in order to produce the right tags. +sub findprog($) +{ + foreach(split(/:/, $ENV{PATH})) { + return "$_/$_[0]" if(-x "$_/$_[0]"); + } +} + +sub get_sphinx_version() +{ + my $ver; + my $major = 1; + + my $cmd = "sphinx-build"; + if (!findprog($cmd)) { + my $cmd = "sphinx-build3"; + return $major if (!findprog($cmd)); + } + + open IN, "$cmd --version 2>&1 |"; + while () { + if (m/^\s*sphinx-build\s+([\d]+)\.([\d\.]+)(\+\/[\da-f]+)?$/) { + $major=$1; + last; + } + # Sphinx 1.2.x uses a different format + if (m/^\s*Sphinx.*\s+([\d]+)\.([\d\.]+)$/) { + $major=$1; + last; + } + } + close IN; + + return $major; +} + # get kernel version from env sub get_kernel_version() { my $version = 'unknown kernel version'; @@ -848,7 +887,11 @@ sub output_function_rst(%) { my $start = ""; if ($args{'typedef'}) { - print ".. c:type:: ". $args{'function'} . "\n\n"; + if ($sphinx_major < 3) { + print ".. c:type:: ". $args{'function'} . "\n\n"; + } else { + print ".. c:function:: ". $args{'function'} . "\n\n"; + } print_lineno($declaration_start_line); print " **Typedef**: "; $lineprefix = ""; @@ -938,9 +981,14 @@ sub output_enum_rst(%) { my ($parameter); my $oldprefix = $lineprefix; my $count; - my $name = "enum " . $args{'enum'}; - print "\n\n.. c:type:: " . $name . "\n\n"; + if ($sphinx_major < 3) { + my $name = "enum " . $args{'enum'}; + print "\n\n.. c:type:: " . $name . "\n\n"; + } else { + my $name = $args{'enum'}; + print "\n\n.. c:enum:: " . $name . "\n\n"; + } print_lineno($declaration_start_line); $lineprefix = " "; output_highlight_rst($args{'purpose'}); @@ -966,8 +1014,13 @@ sub output_typedef_rst(%) { my %args = %{$_[0]}; my ($parameter); my $oldprefix = $lineprefix; - my $name = "typedef " . $args{'typedef'}; + my $name; + if ($sphinx_major < 3) { + $name = "typedef " . $args{'typedef'}; + } else { + $name = $args{'typedef'}; + } print "\n\n.. c:type:: " . $name . "\n\n"; print_lineno($declaration_start_line); $lineprefix = " "; @@ -982,9 +1035,14 @@ sub output_struct_rst(%) { my %args = %{$_[0]}; my ($parameter); my $oldprefix = $lineprefix; - my $name = $args{'type'} . " " . $args{'struct'}; - print "\n\n.. c:type:: " . $name . "\n\n"; + if ($sphinx_major < 3) { + my $name = $args{'type'} . " " . $args{'struct'}; + print "\n\n.. c:type:: " . $name . "\n\n"; + } else { + my $name = $args{'struct'}; + print "\n\n.. c:struct:: " . $name . "\n\n"; + } print_lineno($declaration_start_line); $lineprefix = " "; output_highlight_rst($args{'purpose'}); @@ -2242,6 +2300,7 @@ sub process_file($) { } +$sphinx_major = get_sphinx_version(); $kernelversion = get_kernel_version(); # generate a sequence of code that will splice in highlighting information From 60ef7c1801b02cf6ec0fa12906e0f1386ca7ab00 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 17 Nov 2020 17:53:00 +0100 Subject: [PATCH 099/113] scripts: kernel-doc: use a less pedantic markup for funcs on Sphinx 3.x Unfortunately, Sphinx 3.x parser for c functions is too pedantic: https://github.com/sphinx-doc/sphinx/issues/8241 While it could be relaxed with some configurations, there are several corner cases that it would make it hard to maintain, and will require teaching conf.py about several macros. So, let's instead use the :c:macro notation. This will produce an output that it is not as nice as currently, but it should still be acceptable, and will provide cross-references, removing thousands of warnings when building with newer versions of Sphinx. Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Paolo Bonzini Message-Id: <20201117165312.118257-18-pbonzini@redhat.com> Signed-off-by: Paolo Bonzini --- scripts/kernel-doc | 34 ++++++++++++++++++++++++---------- 1 file changed, 24 insertions(+), 10 deletions(-) diff --git a/scripts/kernel-doc b/scripts/kernel-doc index 771367a6ab..75ddd3b5e6 100755 --- a/scripts/kernel-doc +++ b/scripts/kernel-doc @@ -886,19 +886,29 @@ sub output_function_rst(%) { my $oldprefix = $lineprefix; my $start = ""; - if ($args{'typedef'}) { - if ($sphinx_major < 3) { + if ($sphinx_major < 3) { + if ($args{'typedef'}) { print ".. c:type:: ". $args{'function'} . "\n\n"; + print_lineno($declaration_start_line); + print " **Typedef**: "; + $lineprefix = ""; + output_highlight_rst($args{'purpose'}); + $start = "\n\n**Syntax**\n\n ``"; } else { - print ".. c:function:: ". $args{'function'} . "\n\n"; + print ".. c:function:: "; } - print_lineno($declaration_start_line); - print " **Typedef**: "; - $lineprefix = ""; - output_highlight_rst($args{'purpose'}); - $start = "\n\n**Syntax**\n\n ``"; } else { - print ".. c:function:: "; + print ".. c:macro:: ". $args{'function'} . "\n\n"; + + if ($args{'typedef'}) { + print_lineno($declaration_start_line); + print " **Typedef**: "; + $lineprefix = ""; + output_highlight_rst($args{'purpose'}); + $start = "\n\n**Syntax**\n\n ``"; + } else { + print "``"; + } } if ($args{'functiontype'} ne "") { $start .= $args{'functiontype'} . " " . $args{'function'} . " ("; @@ -925,7 +935,11 @@ sub output_function_rst(%) { if ($args{'typedef'}) { print ");``\n\n"; } else { - print ")\n\n"; + if ($sphinx_major < 3) { + print ")\n\n"; + } else { + print ")``\n"; + } print_lineno($declaration_start_line); $lineprefix = " "; output_highlight_rst($args{'purpose'}); From 5abfaa6a7f5b19a3c6eee5a5d1d5aed4e58c0d9d Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 17 Nov 2020 17:53:01 +0100 Subject: [PATCH 100/113] scripts: kernel-doc: fix troubles with line counts There's currently a bug with the way kernel-doc script counts line numbers that can be seen with: $ ./scripts/kernel-doc -rst -enable-lineno include/linux/math64.h >all && ./scripts/kernel-doc -rst -internal -enable-lineno include/linux/math64.h >int && diff -U0 int all --- int 2020-09-28 12:58:08.927486808 +0200 +++ all 2020-09-28 12:58:08.905486845 +0200 @@ -1 +1 @@ -#define LINENO 27 +#define LINENO 26 @@ -3 +3 @@ -#define LINENO 16 +#define LINENO 15 @@ -9 +9 @@ -#define LINENO 17 +#define LINENO 16 ... This is happening with perl version 5.30.3, but I'm not so sure if this is a perl bug, or if this is due to something else. In any case, fixing it is easy. Basically, when "-internal" parameter is used, the process_export_file() function opens the handle "IN". This makes the line number to be incremented, as the handler for the main open is also "IN". Fix the problem by using a different handler for the main open(). While here, add a missing close for it. Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Paolo Bonzini Message-Id: <20201117165312.118257-19-pbonzini@redhat.com> Signed-off-by: Paolo Bonzini --- scripts/kernel-doc | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/scripts/kernel-doc b/scripts/kernel-doc index 75ddd3b5e6..f33a4b1cc7 100755 --- a/scripts/kernel-doc +++ b/scripts/kernel-doc @@ -2268,7 +2268,7 @@ sub process_file($) { $file = map_filename($orig_file); - if (!open(IN,"<$file")) { + if (!open(IN_FILE,"<$file")) { print STDERR "Error: Cannot open file $file\n"; ++$errors; return; @@ -2277,9 +2277,9 @@ sub process_file($) { $. = 1; $section_counter = 0; - while () { + while () { while (s/\\\s*$//) { - $_ .= ; + $_ .= ; } # Replace tabs by spaces while ($_ =~ s/\t+/' ' x (length($&) * 8 - length($`) % 8)/e) {}; @@ -2311,6 +2311,7 @@ sub process_file($) { print STDERR "${file}:1: warning: no structured comments found\n"; } } + close IN_FILE; } From 78c8c92c5da30f2134da28196f40ab13ca9f778a Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 17 Nov 2020 17:53:02 +0100 Subject: [PATCH 101/113] scripts: kernel-doc: reimplement -nofunction argument Right now, the build system doesn't use -nofunction, as it is pretty much useless, because it doesn't consider the other output modes (extern, internal), working only with all. Also, it is limited to exclude functions. Re-implement it in order to allow excluding any symbols from the document output, no matter what mode is used. The parameter was also renamed to "-nosymbol", as it express better its meaning. Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Paolo Bonzini Message-Id: <20201117165312.118257-20-pbonzini@redhat.com> Signed-off-by: Paolo Bonzini --- scripts/kernel-doc | 44 +++++++++++++++++++++----------------------- 1 file changed, 21 insertions(+), 23 deletions(-) diff --git a/scripts/kernel-doc b/scripts/kernel-doc index f33a4b1cc7..35d60af834 100755 --- a/scripts/kernel-doc +++ b/scripts/kernel-doc @@ -66,9 +66,8 @@ Output selection (mutually exclusive): -function NAME Only output documentation for the given function(s) or DOC: section title(s). All other functions and DOC: sections are ignored. May be specified multiple times. - -nofunction NAME Do NOT output documentation for the given function(s); - only output documentation for the other functions and - DOC: sections. May be specified multiple times. + -nosymbol NAME Exclude the specified symbols from the output + documentation. May be specified multiple times. Output selection modifiers: -no-doc-sections Do not output DOC: sections. @@ -288,9 +287,8 @@ my $modulename = "Kernel API"; use constant { OUTPUT_ALL => 0, # output all symbols and doc sections OUTPUT_INCLUDE => 1, # output only specified symbols - OUTPUT_EXCLUDE => 2, # output everything except specified symbols - OUTPUT_EXPORTED => 3, # output exported symbols - OUTPUT_INTERNAL => 4, # output non-exported symbols + OUTPUT_EXPORTED => 2, # output exported symbols + OUTPUT_INTERNAL => 3, # output non-exported symbols }; my $output_selection = OUTPUT_ALL; my $show_not_found = 0; # No longer used @@ -315,6 +313,7 @@ my $man_date = ('January', 'February', 'March', 'April', 'May', 'June', # CAVEAT EMPTOR! Some of the others I localised may not want to be, which # could cause "use of undefined value" or other bugs. my ($function, %function_table, %parametertypes, $declaration_purpose); +my %nosymbol_table = (); my $declaration_start_line; my ($type, $declaration_name, $return_type); my ($newsection, $newcontents, $prototype, $brcount, %source_map); @@ -434,10 +433,9 @@ while ($ARGV[0] =~ m/^--?(.*)/) { $output_selection = OUTPUT_INCLUDE; $function = shift @ARGV; $function_table{$function} = 1; - } elsif ($cmd eq "nofunction") { # output all except specific functions - $output_selection = OUTPUT_EXCLUDE; - $function = shift @ARGV; - $function_table{$function} = 1; + } elsif ($cmd eq "nosymbol") { # Exclude specific symbols + my $symbol = shift @ARGV; + $nosymbol_table{$symbol} = 1; } elsif ($cmd eq "export") { # only exported symbols $output_selection = OUTPUT_EXPORTED; %function_table = (); @@ -570,11 +568,11 @@ sub dump_doc_section { return; } + return if (defined($nosymbol_table{$name})); + if (($output_selection == OUTPUT_ALL) || - ($output_selection == OUTPUT_INCLUDE && - defined($function_table{$name})) || - ($output_selection == OUTPUT_EXCLUDE && - !defined($function_table{$name}))) + (($output_selection == OUTPUT_INCLUDE) && + defined($function_table{$name}))) { dump_section($file, $name, $contents); output_blockhead({'sectionlist' => \@sectionlist, @@ -800,6 +798,8 @@ sub output_blockhead_rst(%) { my ($parameter, $section); foreach $section (@{$args{'sectionlist'}}) { + next if (defined($nosymbol_table{$section})); + if ($output_selection != OUTPUT_INCLUDE) { print "**$section**\n\n"; } @@ -1115,12 +1115,14 @@ sub output_declaration { my $name = shift; my $functype = shift; my $func = "output_${functype}_$output_mode"; + + return if (defined($nosymbol_table{$name})); + if (($output_selection == OUTPUT_ALL) || (($output_selection == OUTPUT_INCLUDE || $output_selection == OUTPUT_EXPORTED) && defined($function_table{$name})) || - (($output_selection == OUTPUT_EXCLUDE || - $output_selection == OUTPUT_INTERNAL) && + ($output_selection == OUTPUT_INTERNAL && !($functype eq "function" && defined($function_table{$name})))) { &$func(@_); @@ -1301,6 +1303,8 @@ sub show_warnings($$) { my $functype = shift; my $name = shift; + return 0 if (defined($nosymbol_table{$name})); + return 1 if ($output_selection == OUTPUT_ALL); if ($output_selection == OUTPUT_EXPORTED) { @@ -1324,13 +1328,6 @@ sub show_warnings($$) { return 0; } } - if ($output_selection == OUTPUT_EXCLUDE) { - if (!defined($function_table{$name})) { - return 1; - } else { - return 0; - } - } die("Please add the new output type at show_warnings()"); } @@ -1952,6 +1949,7 @@ sub process_export_file($) { while () { if (/$export_symbol/) { + next if (defined($nosymbol_table{$2})); $function_table{$2} = 1; } } From 3999ffcf132e0dc39c9cce1a616f2f4c5fbdc630 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 17 Nov 2020 17:53:03 +0100 Subject: [PATCH 102/113] scripts: kernel-doc: fix typedef identification Some typedef expressions are output as normal functions. As we need to be clearer about the type with Sphinx 3.x, detect such cases. While here, fix a wrongly-indented block. Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Paolo Bonzini Message-Id: <20201117165312.118257-21-pbonzini@redhat.com> Signed-off-by: Paolo Bonzini --- scripts/kernel-doc | 62 ++++++++++++++++++++++++++++++---------------- 1 file changed, 40 insertions(+), 22 deletions(-) diff --git a/scripts/kernel-doc b/scripts/kernel-doc index 35d60af834..0c31e9ad66 100755 --- a/scripts/kernel-doc +++ b/scripts/kernel-doc @@ -1748,30 +1748,48 @@ sub dump_function($$) { return; } - my $prms = join " ", @parameterlist; - check_sections($file, $declaration_name, "function", $sectcheck, $prms); + my $prms = join " ", @parameterlist; + check_sections($file, $declaration_name, "function", $sectcheck, $prms); - # This check emits a lot of warnings at the moment, because many - # functions don't have a 'Return' doc section. So until the number - # of warnings goes sufficiently down, the check is only performed in - # verbose mode. - # TODO: always perform the check. - if ($verbose && !$noret) { - check_return_section($file, $declaration_name, $return_type); - } + # This check emits a lot of warnings at the moment, because many + # functions don't have a 'Return' doc section. So until the number + # of warnings goes sufficiently down, the check is only performed in + # verbose mode. + # TODO: always perform the check. + if ($verbose && !$noret) { + check_return_section($file, $declaration_name, $return_type); + } - output_declaration($declaration_name, - 'function', - {'function' => $declaration_name, - 'module' => $modulename, - 'functiontype' => $return_type, - 'parameterlist' => \@parameterlist, - 'parameterdescs' => \%parameterdescs, - 'parametertypes' => \%parametertypes, - 'sectionlist' => \@sectionlist, - 'sections' => \%sections, - 'purpose' => $declaration_purpose - }); + # The function parser can be called with a typedef parameter. + # Handle it. + if ($return_type =~ /typedef/) { + output_declaration($declaration_name, + 'function', + {'function' => $declaration_name, + 'typedef' => 1, + 'module' => $modulename, + 'functiontype' => $return_type, + 'parameterlist' => \@parameterlist, + 'parameterdescs' => \%parameterdescs, + 'parametertypes' => \%parametertypes, + 'sectionlist' => \@sectionlist, + 'sections' => \%sections, + 'purpose' => $declaration_purpose + }); + } else { + output_declaration($declaration_name, + 'function', + {'function' => $declaration_name, + 'module' => $modulename, + 'functiontype' => $return_type, + 'parameterlist' => \@parameterlist, + 'parameterdescs' => \%parameterdescs, + 'parametertypes' => \%parametertypes, + 'sectionlist' => \@sectionlist, + 'sections' => \%sections, + 'purpose' => $declaration_purpose + }); + } } sub reset_state { From 0c77185233391cf984192efa4caa77c37579e159 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 17 Nov 2020 17:53:04 +0100 Subject: [PATCH 103/113] scripts: kernel-doc: don't mangle with parameter list While kernel-doc needs to parse parameters in order to identify its name, it shouldn't be touching the type, as parsing it is very difficult, and errors happen. One current error is when parsing this parameter: const u32 (*tab)[256] Found at ./lib/crc32.c, on this function: u32 __pure crc32_be_generic (u32 crc, unsigned char const *p, size_t len, const u32 (*tab)[256], u32 polynomial); The current logic mangles it, producing this output: const u32 ( *tab That's something that it is not recognizeable. So, instead, let's push the argument as-is, and use it when printing the function prototype and when describing each argument. Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Paolo Bonzini Message-Id: <20201117165312.118257-22-pbonzini@redhat.com> Signed-off-by: Paolo Bonzini --- scripts/kernel-doc | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/scripts/kernel-doc b/scripts/kernel-doc index 0c31e9ad66..478037f736 100755 --- a/scripts/kernel-doc +++ b/scripts/kernel-doc @@ -655,10 +655,10 @@ sub output_function_man(%) { $type = $args{'parametertypes'}{$parameter}; if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) { # pointer-to-function - print ".BI \"" . $parenth . $1 . "\" " . $parameter . " \") (" . $2 . ")" . $post . "\"\n"; + print ".BI \"" . $parenth . $1 . "\" " . " \") (" . $2 . ")" . $post . "\"\n"; } else { $type =~ s/([^\*])$/$1 /; - print ".BI \"" . $parenth . $type . "\" " . $parameter . " \"" . $post . "\"\n"; + print ".BI \"" . $parenth . $type . "\" " . " \"" . $post . "\"\n"; } $count++; $parenth = ""; @@ -929,7 +929,7 @@ sub output_function_rst(%) { # pointer-to-function print $1 . $parameter . ") (" . $2 . ")"; } else { - print $type . " " . $parameter; + print $type; } } if ($args{'typedef'}) { @@ -954,7 +954,7 @@ sub output_function_rst(%) { $type = $args{'parametertypes'}{$parameter}; if ($type ne "") { - print "``$type $parameter``\n"; + print "``$type``\n"; } else { print "``$parameter``\n"; } @@ -1479,7 +1479,7 @@ sub create_parameterlist($$$$) { # Treat preprocessor directive as a typeless variable just to fill # corresponding data structures "correctly". Catch it later in # output_* subs. - push_parameter($arg, "", $file); + push_parameter($arg, "", "", $file); } elsif ($arg =~ m/\(.+\)\s*\(/) { # pointer-to-function $arg =~ tr/#/,/; @@ -1488,7 +1488,7 @@ sub create_parameterlist($$$$) { $type = $arg; $type =~ s/([^\(]+\(\*?)\s*$param/$1/; save_struct_actual($param); - push_parameter($param, $type, $file, $declaration_name); + push_parameter($param, $type, $arg, $file, $declaration_name); } elsif ($arg) { $arg =~ s/\s*:\s*/:/g; $arg =~ s/\s*\[/\[/g; @@ -1513,26 +1513,28 @@ sub create_parameterlist($$$$) { foreach $param (@args) { if ($param =~ m/^(\*+)\s*(.*)/) { save_struct_actual($2); - push_parameter($2, "$type $1", $file, $declaration_name); + + push_parameter($2, "$type $1", $arg, $file, $declaration_name); } elsif ($param =~ m/(.*?):(\d+)/) { if ($type ne "") { # skip unnamed bit-fields save_struct_actual($1); - push_parameter($1, "$type:$2", $file, $declaration_name) + push_parameter($1, "$type:$2", $arg, $file, $declaration_name) } } else { save_struct_actual($param); - push_parameter($param, $type, $file, $declaration_name); + push_parameter($param, $type, $arg, $file, $declaration_name); } } } } } -sub push_parameter($$$$) { +sub push_parameter($$$$$) { my $param = shift; my $type = shift; + my $org_arg = shift; my $file = shift; my $declaration_name = shift; @@ -1596,8 +1598,8 @@ sub push_parameter($$$$) { # "[blah" in a parameter string; ###$param =~ s/\s*//g; push @parameterlist, $param; - $type =~ s/\s\s+/ /g; - $parametertypes{$param} = $type; + $org_arg =~ s/\s\s+/ /g; + $parametertypes{$param} = $org_arg; } sub check_sections($$$$$) { From 486966e4a4e2cc0647e01f9902b8c1752c44d38e Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 17 Nov 2020 17:53:05 +0100 Subject: [PATCH 104/113] scripts: kernel-doc: allow passing desired Sphinx C domain dialect When kernel-doc is called via kerneldoc.py, there's no need to auto-detect the Sphinx version, as the Sphinx module already knows it. So, add an optional parameter to allow changing the Sphinx dialect. As kernel-doc can also be manually called, keep the auto-detection logic if the parameter was not specified. On such case, emit a warning if sphinx-build can't be found at PATH. I ended using a suggestion from Joe for using a more readable regex, instead of using a complex one with a hidden group like: m/^(\d+)\.(\d+)(?:\.?(\d+)?)/ in order to get the optional argument. Thanks-to: Joe Perches Suggested-by: Jonathan Corbet Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Paolo Bonzini Message-Id: <20201117165312.118257-23-pbonzini@redhat.com> Signed-off-by: Paolo Bonzini --- docs/sphinx/kerneldoc.py | 5 ++++ scripts/kernel-doc | 51 +++++++++++++++++++++++++++++++++------- 2 files changed, 48 insertions(+), 8 deletions(-) diff --git a/docs/sphinx/kerneldoc.py b/docs/sphinx/kerneldoc.py index c0180e02a2..079aadced3 100644 --- a/docs/sphinx/kerneldoc.py +++ b/docs/sphinx/kerneldoc.py @@ -69,6 +69,11 @@ def run(self): env = self.state.document.settings.env cmd = env.config.kerneldoc_bin + ['-rst', '-enable-lineno'] + # Pass the version string to kernel-doc, as it needs to use a different + # dialect, depending what the C domain supports for each specific + # Sphinx versions + cmd += ['-sphinx-version', sphinx.__version__] + filename = env.config.kerneldoc_srctree + '/' + self.arguments[0] export_file_patterns = [] diff --git a/scripts/kernel-doc b/scripts/kernel-doc index 478037f736..667ad3169c 100755 --- a/scripts/kernel-doc +++ b/scripts/kernel-doc @@ -56,6 +56,13 @@ Output format selection (mutually exclusive): -rst Output reStructuredText format. -none Do not output documentation, only warnings. +Output format selection modifier (affects only ReST output): + + -sphinx-version Use the ReST C domain dialect compatible with an + specific Sphinx Version. + If not specified, kernel-doc will auto-detect using + the sphinx-build version found on PATH. + Output selection (mutually exclusive): -export Only output documentation for symbols that have been exported using EXPORT_SYMBOL() or EXPORT_SYMBOL_GPL() @@ -270,7 +277,7 @@ if ($#ARGV == -1) { } my $kernelversion; -my $sphinx_major; +my ($sphinx_major, $sphinx_minor, $sphinx_patch); my $dohighlight = ""; @@ -457,6 +464,23 @@ while ($ARGV[0] =~ m/^--?(.*)/) { $enable_lineno = 1; } elsif ($cmd eq 'show-not-found') { $show_not_found = 1; # A no-op but don't fail + } elsif ($cmd eq "sphinx-version") { + my $ver_string = shift @ARGV; + if ($ver_string =~ m/^(\d+)(\.\d+)?(\.\d+)?/) { + $sphinx_major = $1; + if (defined($2)) { + $sphinx_minor = substr($2,1); + } else { + $sphinx_minor = 0; + } + if (defined($3)) { + $sphinx_patch = substr($3,1) + } else { + $sphinx_patch = 0; + } + } else { + die "Sphinx version should either major.minor or major.minor.patch format\n"; + } } else { # Unknown argument usage(); @@ -477,29 +501,37 @@ sub findprog($) sub get_sphinx_version() { my $ver; - my $major = 1; my $cmd = "sphinx-build"; if (!findprog($cmd)) { my $cmd = "sphinx-build3"; - return $major if (!findprog($cmd)); + if (!findprog($cmd)) { + $sphinx_major = 1; + $sphinx_minor = 2; + $sphinx_patch = 0; + printf STDERR "Warning: Sphinx version not found. Using default (Sphinx version %d.%d.%d)\n", + $sphinx_major, $sphinx_minor, $sphinx_patch; + return; + } } open IN, "$cmd --version 2>&1 |"; while () { if (m/^\s*sphinx-build\s+([\d]+)\.([\d\.]+)(\+\/[\da-f]+)?$/) { - $major=$1; + $sphinx_major = $1; + $sphinx_minor = $2; + $sphinx_patch = $3; last; } # Sphinx 1.2.x uses a different format if (m/^\s*Sphinx.*\s+([\d]+)\.([\d\.]+)$/) { - $major=$1; + $sphinx_major = $1; + $sphinx_minor = $2; + $sphinx_patch = $3; last; } } close IN; - - return $major; } # get kernel version from env @@ -2333,7 +2365,10 @@ sub process_file($) { } -$sphinx_major = get_sphinx_version(); +if ($output_mode eq "rst") { + get_sphinx_version() if (!$sphinx_major); +} + $kernelversion = get_kernel_version(); # generate a sequence of code that will splice in highlighting information From 4f5f16a193abbb15abfde9e6c18d4115d7168bd2 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 17 Nov 2020 17:53:06 +0100 Subject: [PATCH 105/113] scripts: kernel-doc: fix line number handling Address several issues related to pointing to the wrong line number: 1) ensure that line numbers will always be initialized When section is the default (Description), the line number is not initializing, producing this: $ ./scripts/kernel-doc --enable-lineno ./drivers/media/v4l2-core/v4l2-mem2mem.c|less **Description** #define LINENO 0 In case of streamoff or release called on any context, 1] If the context is currently running, then abort job will be called 2] If the context is queued, then the context will be removed from the job_queue Which is not right. Ensure that the line number will always be there. After applied, the result now points to the right location: **Description** #define LINENO 410 In case of streamoff or release called on any context, 1] If the context is currently running, then abort job will be called 2] If the context is queued, then the context will be removed from the job_queue 2) The line numbers for function prototypes are always + 1, because it is taken at the line after handling the prototype. Change the logic to point to the next line after the /** */ block; 3) The "DOC:" line number should point to the same line as this markup is found, and not to the next one. Probably part of the issues were due to a but that was causing the line number offset to be incremented by one, if --export were used. Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Paolo Bonzini Message-Id: <20201117165312.118257-24-pbonzini@redhat.com> Signed-off-by: Paolo Bonzini --- scripts/kernel-doc | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/scripts/kernel-doc b/scripts/kernel-doc index 667ad3169c..98752164eb 100755 --- a/scripts/kernel-doc +++ b/scripts/kernel-doc @@ -1705,7 +1705,7 @@ sub dump_function($$) { my $file = shift; my $noret = 0; - print_lineno($.); + print_lineno($new_start_line); $prototype =~ s/^static +//; $prototype =~ s/^extern +//; @@ -2033,7 +2033,7 @@ sub process_name($$) { if (/$doc_block/o) { $state = STATE_DOCBLOCK; $contents = ""; - $new_start_line = $. + 1; + $new_start_line = $.; if ( $1 eq "" ) { $section = $section_intro; @@ -2116,6 +2116,7 @@ sub process_body($$) { if ($state == STATE_BODY_WITH_BLANK_LINE && /^\s*\*\s?\S/) { dump_section($file, $section, $contents); $section = $section_default; + $new_start_line = $.; $contents = ""; } @@ -2171,6 +2172,7 @@ sub process_body($$) { $prototype = ""; $state = STATE_PROTO; $brcount = 0; + $new_start_line = $. + 1; } elsif (/$doc_content/) { if ($1 eq "") { if ($section eq $section_context) { From ac3617d90c38d7169698908198be1398c7edc693 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 17 Nov 2020 17:53:07 +0100 Subject: [PATCH 106/113] scripts: kernel-doc: try to use c:function if possible There are a few namespace clashes by using c:macro everywhere: basically, when using it, we can't have something like: .. c:struct:: pwm_capture .. c:macro:: pwm_capture So, we need to use, instead: .. c:function:: int pwm_capture (struct pwm_device * pwm, struct pwm_capture * result, unsigned long timeout) for the function declaration. The kernel-doc change was proposed by Jakob Lykke Andersen here: https://github.com/jakobandersen/linux_docs/commit/6fd2076ec001cca7466857493cd678df4dfe4a65 Although I did a different implementation. Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Paolo Bonzini Message-Id: <20201117165312.118257-25-pbonzini@redhat.com> Signed-off-by: Paolo Bonzini --- scripts/kernel-doc | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/scripts/kernel-doc b/scripts/kernel-doc index 98752164eb..2d56c46933 100755 --- a/scripts/kernel-doc +++ b/scripts/kernel-doc @@ -917,6 +917,7 @@ sub output_function_rst(%) { my ($parameter, $section); my $oldprefix = $lineprefix; my $start = ""; + my $is_macro = 0; if ($sphinx_major < 3) { if ($args{'typedef'}) { @@ -926,11 +927,17 @@ sub output_function_rst(%) { $lineprefix = ""; output_highlight_rst($args{'purpose'}); $start = "\n\n**Syntax**\n\n ``"; + $is_macro = 1; } else { print ".. c:function:: "; } } else { - print ".. c:macro:: ". $args{'function'} . "\n\n"; + if ($args{'typedef'} || $args{'functiontype'} eq "") { + $is_macro = 1; + print ".. c:macro:: ". $args{'function'} . "\n\n"; + } else { + print ".. c:function:: "; + } if ($args{'typedef'}) { print_lineno($declaration_start_line); @@ -939,7 +946,7 @@ sub output_function_rst(%) { output_highlight_rst($args{'purpose'}); $start = "\n\n**Syntax**\n\n ``"; } else { - print "``"; + print "``" if ($is_macro); } } if ($args{'functiontype'} ne "") { @@ -964,14 +971,12 @@ sub output_function_rst(%) { print $type; } } - if ($args{'typedef'}) { - print ");``\n\n"; + if ($is_macro) { + print ")``\n\n"; } else { - if ($sphinx_major < 3) { - print ")\n\n"; - } else { - print ")``\n"; - } + print ")\n\n"; + } + if (!$args{'typedef'}) { print_lineno($declaration_start_line); $lineprefix = " "; output_highlight_rst($args{'purpose'}); From 47da500a7edcdd3626997ea5c0c11a502631e3dc Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Tue, 17 Nov 2020 17:53:08 +0100 Subject: [PATCH 107/113] Revert "kernel-doc: Handle function typedefs without asterisks" This reverts commit 3cd3c5193cde5242e243c25759f85802e267994f. We will replace the commit with the fix from Linux. Signed-off-by: Paolo Bonzini Message-Id: <20201117165312.118257-26-pbonzini@redhat.com> Signed-off-by: Paolo Bonzini --- scripts/kernel-doc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/kernel-doc b/scripts/kernel-doc index 2d56c46933..780aee4e92 100755 --- a/scripts/kernel-doc +++ b/scripts/kernel-doc @@ -1434,7 +1434,7 @@ sub dump_typedef($$) { $x =~ s@/\*.*?\*/@@gos; # strip comments. # Parse function prototypes - if ($x =~ /typedef\s+(\w+\s*\**)\s*\(\*?\s*(\w\S+)\s*\)\s*\((.*)\);/ || + if ($x =~ /typedef\s+(\w+\s*\**)\s*\(\*\s*(\w\S+)\s*\)\s*\((.*)\);/ || $x =~ /typedef\s+(\w+\s*\**)\s*(\w\S+)\s*\s*\((.*)\);/) { # Function typedefs From 3e72dc01358106b9606ca8cbaf3dedbb0e53addf Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Tue, 17 Nov 2020 17:53:09 +0100 Subject: [PATCH 108/113] Revert "kernel-doc: Handle function typedefs that return pointers" This reverts commit 19ab6044be0c55d529e875e3ee16fdd5c3b54d33. We will replace the commit with the fix from Linux. Signed-off-by: Paolo Bonzini Message-Id: <20201117165312.118257-27-pbonzini@redhat.com> Signed-off-by: Paolo Bonzini --- scripts/kernel-doc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/kernel-doc b/scripts/kernel-doc index 780aee4e92..d3a289628c 100755 --- a/scripts/kernel-doc +++ b/scripts/kernel-doc @@ -1434,8 +1434,8 @@ sub dump_typedef($$) { $x =~ s@/\*.*?\*/@@gos; # strip comments. # Parse function prototypes - if ($x =~ /typedef\s+(\w+\s*\**)\s*\(\*\s*(\w\S+)\s*\)\s*\((.*)\);/ || - $x =~ /typedef\s+(\w+\s*\**)\s*(\w\S+)\s*\s*\((.*)\);/) { + if ($x =~ /typedef\s+(\w+)\s*\(\*\s*(\w\S+)\s*\)\s*\((.*)\);/ || + $x =~ /typedef\s+(\w+)\s*(\w\S+)\s*\s*\((.*)\);/) { # Function typedefs $return_type = $1; From 01a7917d9bd4fcf2805f1cfb2288c65fe4619303 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 17 Nov 2020 17:53:10 +0100 Subject: [PATCH 109/113] scripts: kernel-doc: fix typedef parsing The include/linux/genalloc.h file defined this typedef: typedef unsigned long (*genpool_algo_t)(unsigned long *map,unsigned long size,unsigned long start,unsigned int nr,void *data, struct gen_pool *pool, unsigned long start_addr); Because it has a type composite of two words (unsigned long), the parser gets the typedef name wrong: .. c:macro:: long **Typedef**: Allocation callback function type definition Fix the regex in order to accept composite types when defining a typedef for a function pointer. Signed-off-by: Mauro Carvalho Chehab Link: https://lore.kernel.org/r/328e8018041cc44f7a1684e57f8d111230761c4f.1603792384.git.mchehab+huawei@kernel.org Signed-off-by: Jonathan Corbet Signed-off-by: Paolo Bonzini Message-Id: <20201117165312.118257-28-pbonzini@redhat.com> Signed-off-by: Paolo Bonzini --- scripts/kernel-doc | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/scripts/kernel-doc b/scripts/kernel-doc index d3a289628c..862b77686e 100755 --- a/scripts/kernel-doc +++ b/scripts/kernel-doc @@ -1434,13 +1434,14 @@ sub dump_typedef($$) { $x =~ s@/\*.*?\*/@@gos; # strip comments. # Parse function prototypes - if ($x =~ /typedef\s+(\w+)\s*\(\*\s*(\w\S+)\s*\)\s*\((.*)\);/ || - $x =~ /typedef\s+(\w+)\s*(\w\S+)\s*\s*\((.*)\);/) { + if ($x =~ /typedef((?:\s+[\w\*]+){1,8})\s*\(\*?\s*(\w\S+)\s*\)\s*\((.*)\);/ || + $x =~ /typedef((?:\s+[\w\*]+\s+){1,8})\s*\*?(\w\S+)\s*\s*\((.*)\);/) { # Function typedefs $return_type = $1; $declaration_name = $2; my $args = $3; + $return_type =~ s/^\s+//; create_parameterlist($args, ',', $file, $declaration_name); From e495a1b26cd2f39b2808fd644f4da15db22340b0 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 17 Nov 2020 17:53:11 +0100 Subject: [PATCH 110/113] scripts: kernel-doc: split typedef complex regex The typedef regex for function prototypes are very complex. Split them into 3 separate regex and then join them using qr. Signed-off-by: Mauro Carvalho Chehab Link: https://lore.kernel.org/r/3a4af999a0d62d4ab9dfae1cdefdfcad93383356.1603792384.git.mchehab+huawei@kernel.org Signed-off-by: Jonathan Corbet Signed-off-by: Paolo Bonzini Message-Id: <20201117165312.118257-29-pbonzini@redhat.com> Signed-off-by: Paolo Bonzini --- scripts/kernel-doc | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/scripts/kernel-doc b/scripts/kernel-doc index 862b77686e..524fc626ed 100755 --- a/scripts/kernel-doc +++ b/scripts/kernel-doc @@ -1427,17 +1427,21 @@ sub dump_enum($$) { } } +my $typedef_type = qr { ((?:\s+[\w\*]+){1,8})\s* }x; +my $typedef_ident = qr { \*?\s*(\w\S+)\s* }x; +my $typedef_args = qr { \s*\((.*)\); }x; + +my $typedef1 = qr { typedef$typedef_type\($typedef_ident\)$typedef_args }x; +my $typedef2 = qr { typedef$typedef_type$typedef_ident$typedef_args }x; + sub dump_typedef($$) { my $x = shift; my $file = shift; $x =~ s@/\*.*?\*/@@gos; # strip comments. - # Parse function prototypes - if ($x =~ /typedef((?:\s+[\w\*]+){1,8})\s*\(\*?\s*(\w\S+)\s*\)\s*\((.*)\);/ || - $x =~ /typedef((?:\s+[\w\*]+\s+){1,8})\s*\*?(\w\S+)\s*\s*\((.*)\);/) { - - # Function typedefs + # Parse function typedef prototypes + if ($x =~ $typedef1 || $x =~ $typedef2) { $return_type = $1; $declaration_name = $2; my $args = $3; From a1b8a57a0e114571b66baf6a6b8bd1c3f1f00d83 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 17 Nov 2020 17:53:12 +0100 Subject: [PATCH 111/113] scripts: kernel-doc: use :c:union when needed Sphinx C domain code after 3.2.1 will start complaning if :c:struct would be used for an union type: .../Documentation/gpu/drm-kms-helpers:352: ../drivers/video/hdmi.c:851: WARNING: C 'identifier' cross-reference uses wrong tag: reference name is 'union hdmi_infoframe' but found name is 'struct hdmi_infoframe'. Full reference name is 'union hdmi_infoframe'. Full found name is 'struct hdmi_infoframe'. So, let's address this issue too in advance, in order to avoid future issues. Signed-off-by: Mauro Carvalho Chehab Link: https://lore.kernel.org/r/6e4ec3eec914df62389a299797a3880ae4490f35.1603791716.git.mchehab+huawei@kernel.org Signed-off-by: Jonathan Corbet Signed-off-by: Paolo Bonzini Message-Id: <20201117165312.118257-30-pbonzini@redhat.com> Signed-off-by: Paolo Bonzini --- scripts/kernel-doc | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/scripts/kernel-doc b/scripts/kernel-doc index 524fc626ed..b95bae3654 100755 --- a/scripts/kernel-doc +++ b/scripts/kernel-doc @@ -1092,7 +1092,11 @@ sub output_struct_rst(%) { print "\n\n.. c:type:: " . $name . "\n\n"; } else { my $name = $args{'struct'}; - print "\n\n.. c:struct:: " . $name . "\n\n"; + if ($args{'type'} eq 'union') { + print "\n\n.. c:union:: " . $name . "\n\n"; + } else { + print "\n\n.. c:struct:: " . $name . "\n\n"; + } } print_lineno($declaration_start_line); $lineprefix = " "; From 07d7186c309b55f89d51fb50a0eaa332b8c0d5d8 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 30 Nov 2020 07:17:45 -0500 Subject: [PATCH 112/113] Revert "docs: temporarily disable the kernel-doc extension" This reverts commit fd68a72875cf318f4310726f842139119c5f45d5. We're done with the update of kernel-doc and we can restore kernel-doc's functionality. Signed-off-by: Paolo Bonzini Signed-off-by: Paolo Bonzini --- docs/sphinx/kerneldoc.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/docs/sphinx/kerneldoc.py b/docs/sphinx/kerneldoc.py index 079aadced3..bf44215016 100644 --- a/docs/sphinx/kerneldoc.py +++ b/docs/sphinx/kerneldoc.py @@ -80,9 +80,6 @@ def run(self): # Tell sphinx of the dependency env.note_dependency(os.path.abspath(filename)) - # Disabled temporarily while scripts/kernel-doc is updated - return [] - tab_width = self.options.get('tab-width', self.state.document.settings.tab_width) # FIXME: make this nicer and more robust against errors From 953d0c333e2825656ba1ec5bd1c18bc53485b39c Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 30 Nov 2020 07:21:12 -0500 Subject: [PATCH 113/113] scripts: kernel-doc: remove unnecessary change wrt Linux A comment in kernel-doc mentions QEMU's qatomic_set macro, but since this code originated in Linux we should just revert it and stay as close to the kernel's copy of the script as possible. The change was introduced (more or less unintentionally) in QEMU commit commit d73415a31547, which did a global search-and-replace of QEMU's atomic access macros. Suggested-by: Peter Maydell Signed-off-by: Paolo Bonzini --- scripts/kernel-doc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/kernel-doc b/scripts/kernel-doc index b95bae3654..4b19851b2d 100755 --- a/scripts/kernel-doc +++ b/scripts/kernel-doc @@ -1758,7 +1758,7 @@ sub dump_function($$) { # If you mess with these regexps, it's a good idea to check that # the following functions' documentation still comes out right: # - parport_register_device (function pointer parameters) - # - qatomic_set (macro) + # - atomic_set (macro) # - pci_match_device, __copy_to_user (long return type) if ($define && $prototype =~ m/^()([a-zA-Z0-9_~:]+)\s+/) {