Re: [RFC PATCH v4] ptp: Add vDSO-style vmclock support

2024-07-17 Thread David Woodhouse
On Tue, 2024-07-16 at 15:20 +0200, Peter Hilber wrote:
> On 16.07.24 14:32, David Woodhouse wrote:
> > On 16 July 2024 12:54:52 BST, Peter Hilber  
> > wrote:
> > > On 11.07.24 09:50, David Woodhouse wrote:
> > > > On Thu, 2024-07-11 at 09:25 +0200, Peter Hilber wrote:
> > > > > 
> > > > > IMHO this phrasing is better, since it directly refers to the state 
> > > > > of the
> > > > > structure.
> > > > 
> > > > Thanks. I'll update it.
> > > > 
> > > > > AFAIU if there would be abnormal delays in store buffers, causing some
> > > > > driver to still see the old clock for some time, the monotonicity 
> > > > > could be
> > > > > violated:
> > > > > 
> > > > > 1. device writes new, much slower clock to store buffer
> > > > > 2. some time passes
> > > > > 3. driver reads old, much faster clock
> > > > > 4. device writes store buffer to cache
> > > > > 5. driver reads new, much slower clock
> > > > > 
> > > > > But I hope such delays do not occur.
> > > > 
> > > > For the case of the hypervisor←→guest interface this should be handled
> > > > by the use of memory barriers and the seqcount lock.
> > > > 
> > > > The guest driver reads the seqcount, performs a read memory barrier,
> > > > then reads the contents of the structure. Then performs *another* read
> > > > memory barrier, and checks the seqcount hasn't changed:
> > > > https://git.infradead.org/?p=users/dwmw2/linux.git;a=blob;f=drivers/ptp/ptp_vmclock.c;hb=vmclock#l351
> > > > 
> > > > The converse happens with write barriers on the hypervisor side:
> > > > https://git.infradead.org/?p=users/dwmw2/qemu.git;a=blob;f=hw/acpi/vmclock.c;hb=vmclock#l68
> > > 
> > > My point is that, looking at the above steps 1. - 5.:
> > > 
> > > 3. read HW counter, smp_rmb, read seqcount
> > > 4. store seqcount, smp_wmb, stores, smp_wmb, store seqcount become 
> > > effective
> > > 5. read seqcount, smp_rmb, read HW counter
> > > 
> > > AFAIU this would still be a theoretical problem suggesting the use of
> > > stronger barriers.
> > 
> > This seems like a bug on the guest side. The HW counter needs to be read 
> > *within* the (paired, matching) seqcount reads, not before or after.
> > 
> > 
> 
> There would be paired reads:
> 
> 1. device writes new, much slower clock to store buffer
> 2. some time passes
> 3. read seqcount, smp_rmb, ..., read HW counter, smp_rmb, read seqcount
> 4. store seqcount, smp_wmb, stores, smp_wmb, store seqcount all become
>    effective only now
> 5. read seqcount, smp_rmb, read HW counter, ..., smp_rmb, read seqcount
> 
> I just omitted the parts which do not necessarily need to happen close to
> 4. for the monotonicity to be violated. My point is that 1. could become
> visible to other cores long after it happened on the local core (during
> 4.).

Oh, I see. That would be a bug on the device side then. And as you say,
it could be fixed by using the appropriate barriers. Or my alternative
of just documenting "Don't Do That Then".



smime.p7s
Description: S/MIME cryptographic signature


Re: [RFC PATCH v4] ptp: Add vDSO-style vmclock support

2024-07-17 Thread David Woodhouse
On Tue, 2024-07-16 at 13:54 +0200, Peter Hilber wrote:
> On 08.07.24 11:27, David Woodhouse wrote:
> > +
> > +   /*
> > +    * Time according to time_type field above.
> > +    */
> > +   uint64_t time_sec;  /* Seconds since time_type epoch */
> > +   uint64_t time_frac_sec; /* (seconds >> 64) */
> > +   uint64_t time_esterror_picosec; /* (± picoseconds) */
> > +   uint64_t time_maxerror_picosec; /* (± picoseconds) */
> 
> Is this unsigned or signed?

The field itself is unsigned, as it provides the absolute value of the
error (which can be in either direction). Probably better just to drop
the ± from the comment.

Julien is now back from vacation and I'm expecting to see his opinion
on whether we can change that to nanoseconds for consistency.


smime.p7s
Description: S/MIME cryptographic signature


Re: [RFC PATCH v4] ptp: Add vDSO-style vmclock support

2024-07-16 Thread David Woodhouse
On 16 July 2024 12:54:52 BST, Peter Hilber  wrote:
>On 11.07.24 09:50, David Woodhouse wrote:
>> On Thu, 2024-07-11 at 09:25 +0200, Peter Hilber wrote:
>>>
>>> IMHO this phrasing is better, since it directly refers to the state of the
>>> structure.
>> 
>> Thanks. I'll update it.
>> 
>>> AFAIU if there would be abnormal delays in store buffers, causing some
>>> driver to still see the old clock for some time, the monotonicity could be
>>> violated:
>>>
>>> 1. device writes new, much slower clock to store buffer
>>> 2. some time passes
>>> 3. driver reads old, much faster clock
>>> 4. device writes store buffer to cache
>>> 5. driver reads new, much slower clock
>>>
>>> But I hope such delays do not occur.
>> 
>> For the case of the hypervisor←→guest interface this should be handled
>> by the use of memory barriers and the seqcount lock.
>> 
>> The guest driver reads the seqcount, performs a read memory barrier,
>> then reads the contents of the structure. Then performs *another* read
>> memory barrier, and checks the seqcount hasn't changed:
>> https://git.infradead.org/?p=users/dwmw2/linux.git;a=blob;f=drivers/ptp/ptp_vmclock.c;hb=vmclock#l351
>> 
>> The converse happens with write barriers on the hypervisor side:
>> https://git.infradead.org/?p=users/dwmw2/qemu.git;a=blob;f=hw/acpi/vmclock.c;hb=vmclock#l68
>
>My point is that, looking at the above steps 1. - 5.:
>
>3. read HW counter, smp_rmb, read seqcount
>4. store seqcount, smp_wmb, stores, smp_wmb, store seqcount become effective
>5. read seqcount, smp_rmb, read HW counter
>
>AFAIU this would still be a theoretical problem suggesting the use of
>stronger barriers.

This seems like a bug on the guest side. The HW counter needs to be read 
*within* the (paired, matching) seqcount reads, not before or after.





Re: More than 255 vcpus Windows VM setup without viommu ?

2024-07-11 Thread David Woodhouse
On Thu, 2024-07-11 at 08:26 +0100, David Woodhouse wrote:
> 
> I used identical command lines on both, and on each host I got the same
> result with all of '-cpu host', '-cpu EPYC' and -cpu Skylake-Server'.
> It's the *host* that makes the difference, not the CPUID presented to
> the guest.

Actually... it turns out QEMU isn't really advertising the CPUID we ask
it to. Leaf zero still does say 'AuthenticAMD' vs. GenuineIntel'
according to the *host* it's running on, regardless of the -cpu option.

And it is indeed *just* that which seems to trigger the Windows bug,
setting IRQ2 to point somewhere bogus:

vtd_ir_remap_msi_req addr 0xfee4 data 0x0 sid 0x do_fault 0
vtd_ir_remap_msi (addr 0xfee4, data 0x0) -> (addr 0xfee4, data 0x0)
kvm_irqchip_update_msi_route Updating MSI route virq=2

While in the happy case it does use a remappable format MSI message.
Not direct to vector 209 on CPU0 as I said before; I think that's IRTE
entry #209 which maps to vector 209 on CPU1.

vtd_ir_remap_msi_req addr 0xfee00010 data 0xd1 sid 0x do_fault 0
vtd_ir_irte_get index 0 low 0x0 high 0x100d10005
vtd_ir_remap index 0 trigger 0 vector 209 deliver 0 dest 0x1 mode 1
vtd_ir_remap_type IOAPIC
vtd_ir_remap_msi (addr 0xfee00010, data 0xd1) -> (addr 0xfee01004, data 0x40d1)

So it looks like Windows doesn't actually cope with Intel IRQ remapping
when it sees and AMD CPU, which is suboptimal.

So to support >255 vCPUs on AMD without having to also do *DMA*
translation, either we need to come up with a trick like the "no
supported address widths" we use for dma-translation=off on Intel, or
we see if we can persuade Windows to use the 15-bit MSI support.


Looking at the Linux guest support, it seems to look just at the HyperV
CPUID leaves 0x4081 and 0x4082. QEMU knows of those only for
SYNDBG; Sandesh do you want to try setting the
HYPERV_VS_PROPERTIES_EAX_EXTENDED_IOAPIC_RTE bit that Linux looks for,
and see how that affects Windows guests (with no emulated IOMMU)?



smime.p7s
Description: S/MIME cryptographic signature


Re: [RFC PATCH v4] ptp: Add vDSO-style vmclock support

2024-07-11 Thread David Woodhouse
On Thu, 2024-07-11 at 09:25 +0200, Peter Hilber wrote:
> 
> IMHO this phrasing is better, since it directly refers to the state of the
> structure.

Thanks. I'll update it.

> AFAIU if there would be abnormal delays in store buffers, causing some
> driver to still see the old clock for some time, the monotonicity could be
> violated:
> 
> 1. device writes new, much slower clock to store buffer
> 2. some time passes
> 3. driver reads old, much faster clock
> 4. device writes store buffer to cache
> 5. driver reads new, much slower clock
> 
> But I hope such delays do not occur.

For the case of the hypervisor←→guest interface this should be handled
by the use of memory barriers and the seqcount lock.

The guest driver reads the seqcount, performs a read memory barrier,
then reads the contents of the structure. Then performs *another* read
memory barrier, and checks the seqcount hasn't changed:
https://git.infradead.org/?p=users/dwmw2/linux.git;a=blob;f=drivers/ptp/ptp_vmclock.c;hb=vmclock#l351

The converse happens with write barriers on the hypervisor side:
https://git.infradead.org/?p=users/dwmw2/qemu.git;a=blob;f=hw/acpi/vmclock.c;hb=vmclock#l68

Do we need to think harder about the ordering across a real PCI bus? It
isn't entirely unreasonable for this to be implemented in hardware if
we eventually add a counter_id value for a bus-visible counter like the
Intel Always Running Timer (ART). I'm also OK with saying that device
implementations may only provide the shared memory structure if they
can ensure memory ordering.


smime.p7s
Description: S/MIME cryptographic signature


Re: More than 255 vcpus Windows VM setup without viommu ?

2024-07-11 Thread David Woodhouse
On Mon, 2024-07-08 at 10:13 +0100, David Woodhouse wrote:
> On Wed, 2024-07-03 at 16:01 +, Sandesh Patel wrote:
> > > 
> > > Interesting. What exactly has Windows *done* in those MSI entries?
> > > That might give a clue about how to support it.

I repeated my experiment with interrupt-only remapping (no DMA
remapping). On two hosts:



vendor_id   : AuthenticAMD
cpu family  : 25
model   : 17
model name  : AMD EPYC 9R14 96-Core Processor

vendor_id   : GenuineIntel
cpu family  : 6
model   : 143
model name  : Intel(R) Xeon(R) Platinum 8488C

I used identical command lines on both, and on each host I got the same
result with all of '-cpu host', '-cpu EPYC' and -cpu Skylake-Server'.
It's the *host* that makes the difference, not the CPUID presented to
the guest.

On the Intel host it boots:

$ ./qemu-system-x86_64 -accel kvm,kernel-irqchip=split -cdrom 
~/Win10_22H2_EnglishInternational_x64v1.iso  -m 16G -M q35 -smp 
2,cores=12,threads=2,maxcpus=288 -accel kvm,kernel-irqchip=split -device 
intel-iommu,intremap=on,dma-translation=off -cpu Skylake-Server --trace 
vtd_ir_\* --trace apic\* --trace kvm_irqchip\*  
qemu-system-x86_64: -accel kvm,kernel-irqchip=split: warning: Number of 
hotpluggable cpus requested (288) exceeds the recommended cpus supported by KVM 
(192)
kvm_irqchip_add_msi_route dev N/A vector 0 virq 0
kvm_irqchip_add_msi_route dev N/A vector 0 virq 1
kvm_irqchip_add_msi_route dev N/A vector 0 virq 2
kvm_irqchip_add_msi_route dev N/A vector 0 virq 3
kvm_irqchip_add_msi_route dev N/A vector 0 virq 4
kvm_irqchip_add_msi_route dev N/A vector 0 virq 5
kvm_irqchip_add_msi_route dev N/A vector 0 virq 6
kvm_irqchip_add_msi_route dev N/A vector 0 virq 7
kvm_irqchip_add_msi_route dev N/A vector 0 virq 8
kvm_irqchip_add_msi_route dev N/A vector 0 virq 9
kvm_irqchip_add_msi_route dev N/A vector 0 virq 10
kvm_irqchip_add_msi_route dev N/A vector 0 virq 11
kvm_irqchip_add_msi_route dev N/A vector 0 virq 12
kvm_irqchip_add_msi_route dev N/A vector 0 virq 13
kvm_irqchip_add_msi_route dev N/A vector 0 virq 14
kvm_irqchip_add_msi_route dev N/A vector 0 virq 15
kvm_irqchip_add_msi_route dev N/A vector 0 virq 16
kvm_irqchip_add_msi_route dev N/A vector 0 virq 17
kvm_irqchip_add_msi_route dev N/A vector 0 virq 18
kvm_irqchip_add_msi_route dev N/A vector 0 virq 19
kvm_irqchip_add_msi_route dev N/A vector 0 virq 20
kvm_irqchip_add_msi_route dev N/A vector 0 virq 21
kvm_irqchip_add_msi_route dev N/A vector 0 virq 22
kvm_irqchip_add_msi_route dev N/A vector 0 virq 23
kvm_irqchip_commit_routes 
qemu-system-x86_64: warning: host doesn't support requested feature: 
CPUID.07H:EBX.hle [bit 4]
qemu-system-x86_64: warning: host doesn't support requested feature: 
CPUID.07H:EBX.rtm [bit 11]
qemu-system-x86_64: warning: host doesn't support requested feature: 
CPUID.07H:EBX.hle [bit 4]
qemu-system-x86_64: warning: host doesn't support requested feature: 
CPUID.07H:EBX.rtm [bit 11]
kvm_irqchip_commit_routes 
kvm_irqchip_commit_routes 
kvm_irqchip_commit_routes 
kvm_irqchip_commit_routes 
kvm_irqchip_commit_routes 
kvm_irqchip_commit_routes 
kvm_irqchip_commit_routes 
kvm_irqchip_commit_routes 
kvm_irqchip_commit_routes 
kvm_irqchip_commit_routes 
kvm_irqchip_commit_routes 
kvm_irqchip_commit_routes 
kvm_irqchip_commit_routes 
kvm_irqchip_commit_routes 
kvm_irqchip_commit_routes 
kvm_irqchip_commit_routes 
kvm_irqchip_commit_routes 
kvm_irqchip_commit_routes 
kvm_irqchip_commit_routes 
kvm_irqchip_commit_routes 
kvm_irqchip_commit_routes 
kvm_irqchip_commit_routes 
kvm_irqchip_commit_routes 
kvm_irqchip_commit_routes 
kvm_irqchip_commit_routes 
kvm_irqchip_commit_routes 
kvm_irqchip_commit_routes 
kvm_irqchip_commit_routes 
kvm_irqchip_commit_routes 
kvm_irqchip_commit_routes 
kvm_irqchip_commit_routes 
kvm_irqchip_commit_routes 
kvm_irqchip_commit_routes 
kvm_irqchip_commit_routes 
kvm_irqchip_commit_routes 
kvm_irqchip_commit_routes 
kvm_irqchip_commit_routes 
kvm_irqchip_commit_routes 
kvm_irqchip_commit_routes 
kvm_irqchip_commit_routes 
kvm_irqchip_commit_routes 
kvm_irqchip_commit_routes 
kvm_irqchip_commit_routes 
kvm_irqchip_commit_routes 
kvm_irqchip_commit_routes 
kvm_irqchip_commit_routes 
kvm_irqchip_commit_routes 
kvm_irqchip_commit_routes 
kvm_irqchip_commit_routes 
kvm_irqchip_commit_routes 
kvm_irqchip_commit_routes 
kvm_irqchip_commit_routes 
vtd_ir_enable enable 1
kvm_irqchip_commit_routes 
kvm_irqchip_commit_routes 
vtd_ir_remap_msi_req addr 0xfee00010 data 0xd1 sid 0x do_fault 0
vtd_ir_irte_get index 0 low 0x0 high 0x100d10005
vtd_ir_remap index 0 trigger 0 vector 209 deliver 0 dest 0x1 mode 1
vtd_ir_remap_type IOAPIC
vtd_ir_remap_msi (addr 0xfee00010, data 0xd1) -> (addr 0xfee01004, data 0x40d1)
kvm_irqchip_update_msi_route Updating MSI route virq=2
kvm_irqchip_commit_routes 
vtd_ir_remap_msi_req addr 0xfee00010 data 0xd1 sid 0x do_fault 0
vtd_ir_irte_get index 0 low 0x0 high 0x100d10005
vtd_ir_remap index 0 trigger 0 vec

Re: [RFC PATCH v4] ptp: Add vDSO-style vmclock support

2024-07-10 Thread David Woodhouse
On Wed, 2024-07-10 at 15:07 +0200, Peter Hilber wrote:
> On 08.07.24 11:27, David Woodhouse wrote:
> > From: David Woodhouse 
> > 
> > The vmclock "device" provides a shared memory region with precision clock
> > information. By using shared memory, it is safe across Live Migration.
> > 
> > Like the KVM PTP clock, this can convert TSC-based cross timestamps into
> > KVM clock values. Unlike the KVM PTP clock, it does so only when such is
> > actually helpful.
> > 
> > The memory region of the device is also exposed to userspace so it can be
> > read or memory mapped by application which need reliable notification of
> > clock disruptions.
> > 
> > Signed-off-by: David Woodhouse 
> 
> [...]
> 
> > +
> > +struct vmclock_abi {
> > +   /* CONSTANT FIELDS */
> > +   uint32_t magic;
> > +#define VMCLOCK_MAGIC  0x4b4c4356 /* "VCLK" */
> > +   uint32_t size;  /* Size of region containing this structure 
> > */
> > +   uint16_t version;   /* 1 */
> > +   uint8_t counter_id; /* Matches VIRTIO_RTC_COUNTER_xxx except 
> > INVALID */
> > +#define VMCLOCK_COUNTER_ARM_VCNT   0
> > +#define VMCLOCK_COUNTER_X86_TSC1
> > +#define VMCLOCK_COUNTER_INVALID0xff
> > +   uint8_t time_type; /* Matches VIRTIO_RTC_TYPE_xxx */
> > +#define VMCLOCK_TIME_UTC   0   /* Since 1970-01-01 
> > 00:00:00z */
> > +#define VMCLOCK_TIME_TAI   1   /* Since 1970-01-01 
> > 00:00:00z */
> > +#define VMCLOCK_TIME_MONOTONIC 2   /* Since undefined 
> > epoch */
> > +#define VMCLOCK_TIME_INVALID_SMEARED   3   /* Not supported */
> > +#define VMCLOCK_TIME_INVALID_MAYBE_SMEARED 4   /* Not supported */
> > +
> > +   /* NON-CONSTANT FIELDS PROTECTED BY SEQCOUNT LOCK */
> > +   uint32_t seq_count; /* Low bit means an update is in progress */
> > +   /*
> > +    * This field changes to another non-repeating value when the CPU
> > +    * counter is disrupted, for example on live migration. This lets
> > +    * the guest know that it should discard any calibration it has
> > +    * performed of the counter against external sources (NTP/PTP/etc.).
> > +    */
> > +   uint64_t disruption_marker;
> > +   uint64_t flags;
> > +   /* Indicates that the tai_offset_sec field is valid */
> > +#define VMCLOCK_FLAG_TAI_OFFSET_VALID  (1 << 0)
> > +   /*
> > +    * Optionally used to notify guests of pending maintenance events.
> > +    * A guest which provides latency-sensitive services may wish to
> > +    * remove itself from service if an event is coming up. Two flags
> > +    * indicate the approximate imminence of the event.
> > +    */
> > +#define VMCLOCK_FLAG_DISRUPTION_SOON   (1 << 1) /* About a day */
> > +#define VMCLOCK_FLAG_DISRUPTION_IMMINENT   (1 << 2) /* About an hour */
> > +#define VMCLOCK_FLAG_PERIOD_ESTERROR_VALID (1 << 3)
> > +#define VMCLOCK_FLAG_PERIOD_MAXERROR_VALID (1 << 4)
> > +#define VMCLOCK_FLAG_TIME_ESTERROR_VALID   (1 << 5)
> > +#define VMCLOCK_FLAG_TIME_MAXERROR_VALID   (1 << 6)
> > +   /*
> > +    * Even regardless of leap seconds, the time presented through this
> > +    * mechanism may not be strictly monotonic. If the counter slows 
> > down
> > +    * and the host adapts to this discovery, the time calculated from
> > +    * the value of the counter immediately after an update to this
> > +    * structure, may appear to be *earlier* than a calculation just
> > +    * before the update (while the counter was believed to be running
> > +    * faster than it now is). A guest operating system will typically
> > +    * *skew* its own system clock back towards the reference clock
> > +    * exposed here, rather than following this clock directly. If,
> > +    * however, this structure is being populated from such a system
> > +    * clock which is already handled in such a fashion and the results
> > +    * *are* guaranteed to be monotonic, such monotonicity can be
> > +    * advertised by setting this bit.
> > +    */
> 
> I wonder if this might be difficult to define in a standard.

I'm sure we could do better than my attempt above, but surely it isn't
*so* hard to define monotonicity?

> Is there a need to define device and driver behavior in more detail? What
> would

[PATCH] net: Reinstate '-net nic, model=help' output as documented in man page

2024-07-09 Thread David Woodhouse
From: David Woodhouse 

While refactoring the NIC initialization code, I broke '-net nic,model=help'
which no longer outputs a list of available NIC models.

Fixes: 2cdeca04adab ("net: report list of available models according to 
platform")
Signed-off-by: David Woodhouse 
---
 net/net.c | 25 ++---
 1 file changed, 22 insertions(+), 3 deletions(-)

diff --git a/net/net.c b/net/net.c
index 6938da05e0..2eb8bc9c0b 100644
--- a/net/net.c
+++ b/net/net.c
@@ -1139,6 +1139,21 @@ NICInfo *qemu_find_nic_info(const char *typename, bool 
match_default,
 return NULL;
 }
 
+static bool is_nic_model_help_option(const char *model)
+{
+if (model && is_help_option(model)) {
+/*
+ * Trigger the help output by instantiating the hash table which
+ * will gather tha available models as they get registered.
+ */
+if (!nic_model_help) {
+nic_model_help = g_hash_table_new_full(g_str_hash, g_str_equal,
+   g_free, NULL);
+}
+return true;
+}
+return false;
+}
 
 /* "I have created a device. Please configure it if you can" */
 bool qemu_configure_nic_device(DeviceState *dev, bool match_default,
@@ -1722,6 +1737,12 @@ void net_check_clients(void)
 
 static int net_init_client(void *dummy, QemuOpts *opts, Error **errp)
 {
+const char *model = qemu_opt_get_del(opts, "model");
+
+if (is_nic_model_help_option(model)) {
+return 0;
+}
+
 return net_client_init(opts, false, errp);
 }
 
@@ -1778,9 +1799,7 @@ static int net_param_nic(void *dummy, QemuOpts *opts, 
Error **errp)
 memset(ni, 0, sizeof(*ni));
 ni->model = qemu_opt_get_del(opts, "model");
 
-if (!nic_model_help && !g_strcmp0(ni->model, "help")) {
-nic_model_help = g_hash_table_new_full(g_str_hash, g_str_equal,
-   g_free, NULL);
+if (is_nic_model_help_option(ni->model)) {
 return 0;
 }
 
-- 
2.44.0




[RFC PATCH v4] ptp: Add vDSO-style vmclock support

2024-07-08 Thread David Woodhouse
From: David Woodhouse 

The vmclock "device" provides a shared memory region with precision clock
information. By using shared memory, it is safe across Live Migration.

Like the KVM PTP clock, this can convert TSC-based cross timestamps into
KVM clock values. Unlike the KVM PTP clock, it does so only when such is
actually helpful.

The memory region of the device is also exposed to userspace so it can be
read or memory mapped by application which need reliable notification of
clock disruptions.

Signed-off-by: David Woodhouse 
---

QEMU implementation at
https://git.infradead.org/users/dwmw2/qemu.git/shortlog/refs/heads/vmclock

Remaining questions/TODO for virtio-rtc adoption:
 • Use of signed integer for tai_offset field
 • Explicit little-endianness
 • Is picoseconds the right unit for absolute error (I was going to make
   this (seconds>>64) but that actually reduces the *range* that can be
   expressed).
 • Are the clock_status values sensible?

v4:
 • Add esterror fields, MONOTONIC flag.
 • Reduce seq_count to 32 bits
 • Expand size to permit 64KiB pages
 • Align with virtio-rtc fields, values and leap handling
 • Drop gettime() method (since we have gettimex())
 • Add leap second smearing hint
 • Use a real _CRS on the ACPI device

v3: (wrong patch sent)

v2:
 • Add gettimex64() support
 • Convert TSC values to KVM clock when appropriate
 • Require int128 support
 • Add counter_period_shift
 • Add timeout when seq_count is invalid
 • Add flags field
 • Better comments in vmclock ABI structure
 • Explicitly forbid smearing (as clock rates would need to change)


 drivers/ptp/Kconfig  |  13 +
 drivers/ptp/Makefile |   1 +
 drivers/ptp/ptp_vmclock.c| 567 +++
 include/uapi/linux/vmclock-abi.h | 187 ++
 4 files changed, 768 insertions(+)
 create mode 100644 drivers/ptp/ptp_vmclock.c
 create mode 100644 include/uapi/linux/vmclock-abi.h

diff --git a/drivers/ptp/Kconfig b/drivers/ptp/Kconfig
index 604541dcb320..e98c9767e0ef 100644
--- a/drivers/ptp/Kconfig
+++ b/drivers/ptp/Kconfig
@@ -131,6 +131,19 @@ config PTP_1588_CLOCK_KVM
  To compile this driver as a module, choose M here: the module
  will be called ptp_kvm.
 
+config PTP_1588_CLOCK_VMCLOCK
+   tristate "Virtual machine PTP clock"
+   depends on X86_TSC || ARM_ARCH_TIMER
+   depends on PTP_1588_CLOCK && ACPI && ARCH_SUPPORTS_INT128
+   default y
+   help
+ This driver adds support for using a virtual precision clock
+ advertised by the hypervisor. This clock is only useful in virtual
+ machines where such a device is present.
+
+ To compile this driver as a module, choose M here: the module
+ will be called ptp_vmclock.
+
 config PTP_1588_CLOCK_IDT82P33
tristate "IDT 82P33xxx PTP clock"
depends on PTP_1588_CLOCK && I2C
diff --git a/drivers/ptp/Makefile b/drivers/ptp/Makefile
index 68bf02078053..01b5cd91eb61 100644
--- a/drivers/ptp/Makefile
+++ b/drivers/ptp/Makefile
@@ -11,6 +11,7 @@ obj-$(CONFIG_PTP_1588_CLOCK_DTE)  += ptp_dte.o
 obj-$(CONFIG_PTP_1588_CLOCK_INES)  += ptp_ines.o
 obj-$(CONFIG_PTP_1588_CLOCK_PCH)   += ptp_pch.o
 obj-$(CONFIG_PTP_1588_CLOCK_KVM)   += ptp_kvm.o
+obj-$(CONFIG_PTP_1588_CLOCK_VMCLOCK)   += ptp_vmclock.o
 obj-$(CONFIG_PTP_1588_CLOCK_QORIQ) += ptp-qoriq.o
 ptp-qoriq-y+= ptp_qoriq.o
 ptp-qoriq-$(CONFIG_DEBUG_FS)   += ptp_qoriq_debugfs.o
diff --git a/drivers/ptp/ptp_vmclock.c b/drivers/ptp/ptp_vmclock.c
new file mode 100644
index ..30f15d7753bb
--- /dev/null
+++ b/drivers/ptp/ptp_vmclock.c
@@ -0,0 +1,567 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Virtual PTP 1588 clock for use with LM-safe VMclock device.
+ *
+ * Copyright © 2024 Amazon.com, Inc. or its affiliates.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+
+#include 
+
+#ifdef CONFIG_X86
+#include 
+#include 
+#endif
+
+#ifdef CONFIG_KVM_GUEST
+#define SUPPORT_KVMCLOCK
+#endif
+
+static DEFINE_IDA(vmclock_ida);
+
+ACPI_MODULE_NAME("vmclock");
+
+struct vmclock_state {
+   struct resource res;
+   struct vmclock_abi *clk;
+   struct miscdevice miscdev;
+   struct ptp_clock_info ptp_clock_info;
+   struct ptp_clock *ptp_clock;
+   enum clocksource_ids cs_id, sys_cs_id;
+   int index;
+   char *name;
+};
+
+#define VMCLOCK_MAX_WAIT ms_to_ktime(100)
+
+/*
+ * Multiply a 64-bit count by a 64-bit tick 'period' in units of seconds >> 64
+ * and add the fractional second part of the reference time.
+ *
+ * The result is a 128-bit value, the top 64 bits of which are seconds, and
+ * the low 64 bits are (seconds >> 64).
+ *
+ * If __int128 isn't available, perform the calculation 32 bits at a time to
+ * avoid overflo

Re: [RFC PATCH v3] ptp: Add vDSO-style vmclock support

2024-07-08 Thread David Woodhouse
On Mon, 2024-07-08 at 10:17 +0100, Simon Horman wrote:
> Hi David,
> 
> As per my comment on v2, although it is harmless in this case,
> it would be nicer to use strscpy() here and avoid fortification
> warnings.
> 

Oh, pants! I have fixed that; must have sent the wrong version.
V4 coming up shortly. With git-send-email this time.

Thanks.


smime.p7s
Description: S/MIME cryptographic signature


Re: More than 255 vcpus Windows VM setup without viommu ?

2024-07-08 Thread David Woodhouse
On Wed, 2024-07-03 at 16:01 +, Sandesh Patel wrote:
> > 
> > Interesting. What exactly has Windows *done* in those MSI entries?
> > That
> > might give a clue about how to support it.
> 
> The KVM_SET_GSI_ROUTING ioctl calls kvm_set_routing_entry function in
> kvm.
> 
> int kvm_set_routing_entry(struct kvm *kvm, struct
> kvm_kernel_irq_routing_entry *e,
>                              const struct kvm_irq_routing_entry *ue)
> {
> 
> switch (ue->type) {
> case KVM_IRQ_ROUTING_MSI:
>              e->set = kvm_set_msi;
>              e->msi.address_lo = ue->u.msi.address_lo;
>              e->msi.address_hi = ue->u.msi.address_hi;
>              e->msi.data = ue->u.msi.data;
> 
>              if (kvm_msi_route_invalid(kvm, e))
>                  return -EINVAL;
>             break;
> }
> }
> 
> static inline bool kvm_msi_route_invalid(struct kvm *kvm,
>          struct kvm_kernel_irq_routing_entry *e)
> {
>     return kvm->arch.x2apic_format && (e->msi.address_hi & 0xff);
> }
> 
> That means msi.address_hi must have 0 in the last byte.
> 
> Qemu function kvm_arch_fixup_msi_route is responsible for
> fixing msi.address_hi value in 
> msi routing entry that is passed to kvm.
> This function got msi.addr_hi:  0x0 in input when iommu was enabled
> and msi.addr_hi:  0x1
> when viommu was not enabled for one of the entry. The same value was
> returned in the output. 
> and saved as routing entry.

That's after QEMU has translated it though. Precisely which MSI is
this, belonging to which device, and what exactly did Windows write to
the MSI table?

If *Windows* put anything into the high address bits, that isn't even
targeted at the APIC, and it would be an attempt at writing to actual
memory. I suspect that isn't the case.

Can you make kvm_arch_fixup_msi_route() print the actual address and
data directly from the guest? 



smime.p7s
Description: S/MIME cryptographic signature


[RFC PATCH v3] ptp: Add vDSO-style vmclock support

2024-07-06 Thread David Woodhouse
From: David Woodhouse 

The vmclock "device" provides a shared memory region with precision clock
information. By using shared memory, it is safe across Live Migration.

Like the KVM PTP clock, this can convert TSC-based cross timestamps into
KVM clock values. Unlike the KVM PTP clock, it does so only when such is
actually helpful.

The memory region of the device is also exposed to userspace so it can be
read or memory mapped by application which need reliable notification of
clock disruptions.

The shared memory structure is intended to be adopted into the nascent
virtio-rtc specification (since one might consider a virtio-rtc
specification that doesn't fix the live migration problem to be not fit
for purpose). It can also be presented via a simple ACPI device.

Signed-off-by: David Woodhouse 
---
QEMU implementation at 
https://git.infradead.org/users/dwmw2/qemu.git/shortlog/refs/heads/vmclock

Remaining questions/TODO for virtio-rtc adoption:
 • Use of signed integer for tai_offset field
 • Explicit little-endianness
 • Is picoseconds the right unit for absolute error (I was going to make
   this (seconds>>64) but that actually reduces the *range* that can be
   expressed).
 • Are the clock_status values sensible?

v3:
 • Add esterror fields
 • Reduce seq_count to 32 bits
 • Expand size to permit 64KiB pages
 • Align with virtio-rtc fields, values and leap handling
 • Drop gettime() method (since we have gettimex())
 • Add leap second smearing hint
 • Use a real _CRS on the ACPI device

v2: 
 • Add gettimex64() support
 • Convert TSC values to KVM clock when appropriate
 • Require int128 support
 • Add counter_period_shift
 • Add timeout when seq_count is invalid
 • Add flags field
 • Better comments in vmclock ABI structure
 • Explicitly forbid smearing (as clock rates would need to change)

 drivers/ptp/Kconfig  |  13 +
 drivers/ptp/Makefile |   1 +
 drivers/ptp/ptp_vmclock.c| 516 +++
 include/uapi/linux/vmclock.h | 138 ++
 4 files changed, 668 insertions(+)
 create mode 100644 drivers/ptp/ptp_vmclock.c
 create mode 100644 include/uapi/linux/vmclock.h

diff --git a/drivers/ptp/Kconfig b/drivers/ptp/Kconfig
index 604541dcb320..e98c9767e0ef 100644
--- a/drivers/ptp/Kconfig
+++ b/drivers/ptp/Kconfig
@@ -131,6 +131,19 @@ config PTP_1588_CLOCK_KVM
  To compile this driver as a module, choose M here: the module
  will be called ptp_kvm.
 
+config PTP_1588_CLOCK_VMCLOCK
+   tristate "Virtual machine PTP clock"
+   depends on X86_TSC || ARM_ARCH_TIMER
+   depends on PTP_1588_CLOCK && ACPI && ARCH_SUPPORTS_INT128
+   default y
+   help
+ This driver adds support for using a virtual precision clock
+ advertised by the hypervisor. This clock is only useful in virtual
+ machines where such a device is present.
+
+ To compile this driver as a module, choose M here: the module
+ will be called ptp_vmclock.
+
 config PTP_1588_CLOCK_IDT82P33
tristate "IDT 82P33xxx PTP clock"
depends on PTP_1588_CLOCK && I2C
diff --git a/drivers/ptp/Makefile b/drivers/ptp/Makefile
index 68bf02078053..01b5cd91eb61 100644
--- a/drivers/ptp/Makefile
+++ b/drivers/ptp/Makefile
@@ -11,6 +11,7 @@ obj-$(CONFIG_PTP_1588_CLOCK_DTE)  += ptp_dte.o
 obj-$(CONFIG_PTP_1588_CLOCK_INES)  += ptp_ines.o
 obj-$(CONFIG_PTP_1588_CLOCK_PCH)   += ptp_pch.o
 obj-$(CONFIG_PTP_1588_CLOCK_KVM)   += ptp_kvm.o
+obj-$(CONFIG_PTP_1588_CLOCK_VMCLOCK)   += ptp_vmclock.o
 obj-$(CONFIG_PTP_1588_CLOCK_QORIQ) += ptp-qoriq.o
 ptp-qoriq-y+= ptp_qoriq.o
 ptp-qoriq-$(CONFIG_DEBUG_FS)   += ptp_qoriq_debugfs.o
diff --git a/drivers/ptp/ptp_vmclock.c b/drivers/ptp/ptp_vmclock.c
new file mode 100644
index ..e19c2eed8009
--- /dev/null
+++ b/drivers/ptp/ptp_vmclock.c
@@ -0,0 +1,516 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Virtual PTP 1588 clock for use with LM-safe VMclock device.
+ *
+ * Copyright © 2024 Amazon.com, Inc. or its affiliates.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+
+#ifdef CONFIG_X86
+#include 
+#include 
+#endif
+
+static DEFINE_IDA(vmclock_ida);
+
+ACPI_MODULE_NAME("vmclock");
+
+struct vmclock_state {
+   phys_addr_t phys_addr;
+   struct vmclock_abi *clk;
+   struct miscdevice miscdev;
+   struct ptp_clock_info ptp_clock_info;
+   struct ptp_clock *ptp_clock;
+   enum clocksource_ids cs_id, sys_cs_id;
+   int index;
+   char *name;
+};
+
+#define VMCLOCK_MAX_WAIT ms_to_ktime(100)
+
+/*
+ * Multiply a 64-bit count by a 64-bit tick 'period' in units of seconds >> 64
+ * and add the fractional second part of the reference time.
+ *
+ * The result is a 128-bit value, the top 64 bits of which are seconds, and
+ * the low 64 bits are (sec

Re: [PULL v3 58/85] hw/i386/fw_cfg: Add etc/e820 to fw_cfg late

2024-07-04 Thread David Woodhouse
On Wed, 2024-07-03 at 18:48 -0400, Michael S. Tsirkin wrote:
> From: David Woodhouse 

Oops, that was supposed to be

From: David Woodhouse 

Not the end of the world if it's too late to change it. 


smime.p7s
Description: S/MIME cryptographic signature


Re: More than 255 vcpus Windows VM setup without viommu ?

2024-07-02 Thread David Woodhouse
On Tue, 2024-07-02 at 05:17 +, Sandesh Patel wrote:
> Hi All,
> Is it possible to setup a large Windows VM (say 512 vcpus) without
> adding viommu (EIM=on, IR=on)?
> When I try to power such VM, the qemu process crashes with error-
> ```
> qemu-kvm: ../accel/kvm/kvm-all.c:1837: kvm_irqchip_commit_routes: Assertion 
> `ret == 0’ failed
> 

Interesting. What exactly has Windows *done* in those MSI entries? That
might give a clue about how to support it.

> 
> The VM boots fine if we attach a vIOMMU but adding a vIOMMU can
> potentially result in IO performance loss in guest.
> I was interested to know if someone could boot a large Windows VM by
> some other means like kvm-msi-ext-dest-id.

I worked with Microsoft folks when I was defining the msi-ext-dest-id
support, and Hyper-V does it exactly the same way. But that's on the
*hypervisor* side. At the time, I don't believe Windows as a guest was
planning to use it. 

But I actually thought Windows worked OK without being able to direct
external interrupts to all vCPUs, so it didn't matter?


> Overheads of viommu have been shown for example in -
> https://static.sched.com/hosted_files/kvmforum2021/da/vIOMMU%20KVM%20
> Forum%202021%20-%20v4.pdf

Isn't that for DMA translation though? If you give the guest an
intel_iommu with dma_translation=off then it should *only* do interrupt
remapping.


smime.p7s
Description: S/MIME cryptographic signature


[RFC PATCH] hw/acpi: Add vmclock device

2024-06-28 Thread David Woodhouse
From: David Woodhouse 

The vmclock device addresses the problem of live migration with precision
clocks. The tolerances of a hardware counter (e.g. TSC) are typically
around ±50PPM. We use NTP/PTP/PPS to discipline that counter against an
external source of 'real' time, and track the precise frequency of the
counter as it changes with environmental conditions.

When a guest is live migrated, anything it knows about the frequency of
the underlying counter becomes invalid. It may move from a host where
the counter running at -50PPM of its nominal frequency, to a host where
it runs at +50PPM. There will also be a step change in the value of the
counter, as the correctness of its absolute value at migration is
limited by the accuracy of the source and destination host's time
synchronization.

The device exposes a shared memory region to guests, which can be mapped
all the way to userspace. In the first phase, this merely advertises a
'disruption_marker', which indicates that the guest should throw away any
NTP synchronization it thinks it has, and start again.

Because can be exposed all the way to userspace, applications can still
use time from a vDSO 'system call', and check the disruption marker to
be sure that their timestamp is indeed truthful.

The structure also allows for the precise time, as known by the host, to
be exposed directly to guests so that they don't have to wait for NTP to
resync from scratch.

Signed-off-by: David Woodhouse 
---

Guest kernel support at 
https://git.infradead.org/users/dwmw2/linux.git/shortlog/refs/heads/vmclock
and discussion at
https://lore.kernel.org/lkml/51dcda5b675fb68c54b74fd19c408a3a086fc412.ca...@infradead.org/

 hw/acpi/Kconfig   |   5 ++
 hw/acpi/meson.build   |   1 +
 hw/acpi/vmclock-abi.h | 175 +
 hw/acpi/vmclock.c | 177 ++
 hw/i386/Kconfig   |   1 +
 hw/i386/acpi-build.c  |  10 ++-
 include/hw/acpi/vmclock.h |  34 
 7 files changed, 402 insertions(+), 1 deletion(-)
 create mode 100644 hw/acpi/vmclock-abi.h
 create mode 100644 hw/acpi/vmclock.c
 create mode 100644 include/hw/acpi/vmclock.h

diff --git a/hw/acpi/Kconfig b/hw/acpi/Kconfig
index e07d3204eb..1d4e9f0845 100644
--- a/hw/acpi/Kconfig
+++ b/hw/acpi/Kconfig
@@ -60,6 +60,11 @@ config ACPI_VMGENID
 default y
 depends on PC
 
+config ACPI_VMCLOCK
+bool
+default y
+depends on PC
+
 config ACPI_VIOT
 bool
 depends on ACPI
diff --git a/hw/acpi/meson.build b/hw/acpi/meson.build
index fa5c07db90..77566ae8a8 100644
--- a/hw/acpi/meson.build
+++ b/hw/acpi/meson.build
@@ -16,6 +16,7 @@ acpi_ss.add(when: 'CONFIG_ACPI_NVDIMM', if_false: 
files('acpi-nvdimm-stub.c'))
 acpi_ss.add(when: 'CONFIG_ACPI_PCI', if_true: files('pci.c'))
 acpi_ss.add(when: 'CONFIG_ACPI_CXL', if_true: files('cxl.c'), if_false: 
files('cxl-stub.c'))
 acpi_ss.add(when: 'CONFIG_ACPI_VMGENID', if_true: files('vmgenid.c'))
+acpi_ss.add(when: 'CONFIG_ACPI_VMCLOCK', if_true: files('vmclock.c'))
 acpi_ss.add(when: 'CONFIG_ACPI_HW_REDUCED', if_true: 
files('generic_event_device.c'))
 acpi_ss.add(when: 'CONFIG_ACPI_HMAT', if_true: files('hmat.c'))
 acpi_ss.add(when: 'CONFIG_ACPI_APEI', if_true: files('ghes.c'), if_false: 
files('ghes-stub.c'))
diff --git a/hw/acpi/vmclock-abi.h b/hw/acpi/vmclock-abi.h
new file mode 100644
index 00..3f6473c3d9
--- /dev/null
+++ b/hw/acpi/vmclock-abi.h
@@ -0,0 +1,175 @@
+/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR 
BSD-2-Clause) */
+
+/*
+ * This structure provides a vDSO-style clock to VM guests, exposing the
+ * relationship (or lack thereof) between the CPU clock (TSC, timebase, arch
+ * counter, etc.) and real time. It is designed to address the problem of
+ * live migration, which other clock enlightenments do not.
+ *
+ * When a guest is live migrated, this affects the clock in two ways.
+ *
+ * First, even between identical hosts the actual frequency of the underlying
+ * counter will change within the tolerances of its specification (typically
+ * ±50PPM, or 4 seconds a day). The frequency also varies over time on the
+ * same host, but can be tracked by NTP as it generally varies slowly. With
+ * live migration there is a step change in the frequency, with no warning.
+ *
+ * Second, there may be a step change in the value of the counter itself, as
+ * its accuracy is limited by the precision of the NTP synchronization on the
+ * source and destination hosts.
+ *
+ * So any calibration (NTP, PTP, etc.) which the guest has done on the source
+ * host before migration is invalid, and needs to be redone on the new host.
+ *
+ * In its most basic mode, this structure provides only an indication to the
+ * guest that live migration has occurred. This allows the guest to know that
+ * its clock is invalid and take remedial action. For applications that need
+ * reliable accurate timestamps (e.g. distributed databases), the structure
+ * can

[PATCH v2] hw/i386/fw_cfg: Add etc/e820 to fw_cfg late

2024-06-19 Thread David Woodhouse
In e820_add_entry() the e820_table is reallocated with g_renew() to make
space for a new entry. However, fw_cfg_arch_create() just uses the
existing e820_table pointer. This leads to a use-after-free if anything
adds a new entry after fw_cfg is set up.

Shift the addition of the etc/e820 file to the machine done notifier, via
a new fw_cfg_add_e820() function.

Also make e820_table private and use an e820_get_table() accessor function
for it, which sets a flag that will trigger an assert() for any *later*
attempts to add to the table.

Make e820_add_entry() return void, as most callers don't check for error
anyway.

Signed-off-by: David Woodhouse 
---
v2: Make the table static and introduce e820_get_table(), use assert()

 hw/i386/e820_memory_layout.c | 16 +++-
 hw/i386/e820_memory_layout.h |  8 ++--
 hw/i386/fw_cfg.c | 18 +-
 hw/i386/fw_cfg.h |  1 +
 hw/i386/microvm.c|  4 ++--
 hw/i386/pc.c |  1 +
 target/i386/kvm/kvm.c|  6 +-
 target/i386/kvm/xen-emu.c|  7 +--
 8 files changed, 32 insertions(+), 29 deletions(-)

diff --git a/hw/i386/e820_memory_layout.c b/hw/i386/e820_memory_layout.c
index 06970ac44a..0d549accbf 100644
--- a/hw/i386/e820_memory_layout.c
+++ b/hw/i386/e820_memory_layout.c
@@ -11,22 +11,28 @@
 #include "e820_memory_layout.h"
 
 static size_t e820_entries;
-struct e820_entry *e820_table;
+static struct e820_entry *e820_table;
+static gboolean e820_done;
 
-int e820_add_entry(uint64_t address, uint64_t length, uint32_t type)
+void e820_add_entry(uint64_t address, uint64_t length, uint32_t type)
 {
+assert(!e820_done);
+
 /* new "etc/e820" file -- include ram and reserved entries */
 e820_table = g_renew(struct e820_entry, e820_table, e820_entries + 1);
 e820_table[e820_entries].address = cpu_to_le64(address);
 e820_table[e820_entries].length = cpu_to_le64(length);
 e820_table[e820_entries].type = cpu_to_le32(type);
 e820_entries++;
-
-return e820_entries;
 }
 
-int e820_get_num_entries(void)
+int e820_get_table(struct e820_entry **table)
 {
+e820_done = true;
+
+if (table)
+*table = e820_table;
+
 return e820_entries;
 }
 
diff --git a/hw/i386/e820_memory_layout.h b/hw/i386/e820_memory_layout.h
index 7c239aa033..b50acfa201 100644
--- a/hw/i386/e820_memory_layout.h
+++ b/hw/i386/e820_memory_layout.h
@@ -22,13 +22,9 @@ struct e820_entry {
 uint32_t type;
 } QEMU_PACKED __attribute((__aligned__(4)));
 
-extern struct e820_entry *e820_table;
-
-int e820_add_entry(uint64_t address, uint64_t length, uint32_t type);
-int e820_get_num_entries(void);
+void e820_add_entry(uint64_t address, uint64_t length, uint32_t type);
 bool e820_get_entry(int index, uint32_t type,
 uint64_t *address, uint64_t *length);
-
-
+int e820_get_table(struct e820_entry **table);
 
 #endif
diff --git a/hw/i386/fw_cfg.c b/hw/i386/fw_cfg.c
index 6e0d9945d0..1eb6729b9c 100644
--- a/hw/i386/fw_cfg.c
+++ b/hw/i386/fw_cfg.c
@@ -48,6 +48,15 @@ const char *fw_cfg_arch_key_name(uint16_t key)
 return NULL;
 }
 
+/* Add etc/e820 late, once all regions should be present */
+void fw_cfg_add_e820(FWCfgState *fw_cfg)
+{
+struct e820_entry *table;
+int nr_e820 = e820_get_table();
+
+fw_cfg_add_file(fw_cfg, "etc/e820", table, nr_e820 * sizeof(*table));
+}
+
 void fw_cfg_build_smbios(PCMachineState *pcms, FWCfgState *fw_cfg,
  SmbiosEntryPointType ep_type)
 {
@@ -60,6 +69,7 @@ void fw_cfg_build_smbios(PCMachineState *pcms, FWCfgState 
*fw_cfg,
 PCMachineClass *pcmc = PC_MACHINE_GET_CLASS(pcms);
 MachineClass *mc = MACHINE_GET_CLASS(pcms);
 X86CPU *cpu = X86_CPU(ms->possible_cpus->cpus[0].cpu);
+int nr_e820;
 
 if (pcmc->smbios_defaults) {
 /* These values are guest ABI, do not change */
@@ -79,8 +89,9 @@ void fw_cfg_build_smbios(PCMachineState *pcms, FWCfgState 
*fw_cfg,
 }
 
 /* build the array of physical mem area from e820 table */
-mem_array = g_malloc0(sizeof(*mem_array) * e820_get_num_entries());
-for (i = 0, array_count = 0; i < e820_get_num_entries(); i++) {
+nr_e820 = e820_get_table(NULL);
+mem_array = g_malloc0(sizeof(*mem_array) * nr_e820);
+for (i = 0, array_count = 0; i < nr_e820; i++) {
 uint64_t addr, len;
 
 if (e820_get_entry(i, E820_RAM, , )) {
@@ -139,9 +150,6 @@ FWCfgState *fw_cfg_arch_create(MachineState *ms,
 #endif
 fw_cfg_add_i32(fw_cfg, FW_CFG_IRQ0_OVERRIDE, 1);
 
-fw_cfg_add_file(fw_cfg, "etc/e820", e820_table,
-sizeof(struct e820_entry) * e820_get_num_entries());
-
 fw_cfg_add_bytes(fw_cfg, FW_CFG_HPET, _cfg, sizeof(hpet_cfg));
 /* allocate memory for the NUMA channel: one (64bit) word for the number
  * of nodes, one word for each VCPU->node and one word for each node to
diff --git a/hw/i386/fw_cfg.h b/hw/i386/fw_cfg.h
index 92e

Re: [PATCH] hw/i386/fw_cfg: Add etc/e820 to fw_cfg late

2024-06-17 Thread David Woodhouse
On Mon, 2024-06-17 at 15:15 +0100, Peter Maydell wrote:
> On Mon, 17 Jun 2024 at 14:46, David Woodhouse  wrote:
> > 
> > From: David Woodhouse 
> > 
> > In e820_add_entry() the e820_table is reallocated with g_renew() to make
> > space for a new entry. However, fw_cfg_arch_create() just uses the existing
> > e820_table pointer.
> > 
> > This leads to a use-after-free if anything adds a new entry after fw_cfg
> > is set up. Shift the addition of the etc/e820 file to the machine done
> > notifier, and add a sanity check to ensure that e820_table isn't
> > modified after the pointer gets stashed.
> 
> Given that e820_add_entry() will happily g_renew() the memory,
> it seems a bit bug-prone to have e820_table be a global variable.
> Maybe we should have an e820_add_fw_cfg_file() which does the
> 
>     fw_cfg_add_file(fw_cfg, "etc/e820", e820_table,
>     sizeof(struct e820_entry) * e820_get_num_entries());
> 
> -- that would then let us make e820_table be file-local, and so
> it's then easy to audit that all the functions that look at
> e820_table check that the table has been finalized first (because
> they're all in this one file).

Yeah, I pondered that, but wasn't sure I wanted to add a dependency on
fw_cfg directly in the e820 code. So I pondered making e820_table
static and using an accessor function... but then figured that since
there's *already* an accessor for the table size, I could just use
that.

I suppose we could have a single function which returns both the table
pointer *and* its size. It's a slight cleanup, but seemed like more
churn that it was worth, and being C obviously it can't literally
*return* both, so it just gets slightly ugly. Happy to do it if you
feel strongly.

> > Signed-off-by: David Woodhouse 
> > ---
> >  hw/i386/e820_memory_layout.c | 8 
> >  hw/i386/fw_cfg.c | 7 ---
> >  hw/i386/microvm.c    | 5 +++--
> >  3 files changed, 15 insertions(+), 5 deletions(-)
> > 
> > diff --git a/hw/i386/e820_memory_layout.c b/hw/i386/e820_memory_layout.c
> > index 06970ac44a..c96515909e 100644
> > --- a/hw/i386/e820_memory_layout.c
> > +++ b/hw/i386/e820_memory_layout.c
> > @@ -8,13 +8,20 @@
> > 
> >  #include "qemu/osdep.h"
> >  #include "qemu/bswap.h"
> > +#include "qemu/error-report.h"
> >  #include "e820_memory_layout.h"
> > 
> >  static size_t e820_entries;
> >  struct e820_entry *e820_table;
> > +static gboolean e820_done;
> > 
> >  int e820_add_entry(uint64_t address, uint64_t length, uint32_t type)
> >  {
> > +    if (e820_done) {
> > +    warn_report("warning: E820 modified after being consumed");
> > +    return -1;
> > +    }
> 
> I think this should be a fatal error (i.e. assert) -- it should
> never happen, and always would be a bug in QEMU somewhere.

OK.

> Currently e820_add_entry() returns the number of entries
> currently present. Of the various callsites, almost all ignore
> the return value. Two treat it as a "negative means error"
> situation (with an error handling path that's currently dead code):
> target/i386/kvm/kvm.c and target/i386/kvm/xen-emu.c.
> 
> My suggestion is that we make e820_add_entry() return void,
> and remove that dead error handling path.

Ack.


smime.p7s
Description: S/MIME cryptographic signature


[PATCH] hw/i386/fw_cfg: Add etc/e820 to fw_cfg late

2024-06-17 Thread David Woodhouse
From: David Woodhouse 

In e820_add_entry() the e820_table is reallocated with g_renew() to make
space for a new entry. However, fw_cfg_arch_create() just uses the existing
e820_table pointer.

This leads to a use-after-free if anything adds a new entry after fw_cfg
is set up. Shift the addition of the etc/e820 file to the machine done
notifier, and add a sanity check to ensure that e820_table isn't
modified after the pointer gets stashed.

Signed-off-by: David Woodhouse 
---
 hw/i386/e820_memory_layout.c | 8 
 hw/i386/fw_cfg.c | 7 ---
 hw/i386/microvm.c| 5 +++--
 3 files changed, 15 insertions(+), 5 deletions(-)

diff --git a/hw/i386/e820_memory_layout.c b/hw/i386/e820_memory_layout.c
index 06970ac44a..c96515909e 100644
--- a/hw/i386/e820_memory_layout.c
+++ b/hw/i386/e820_memory_layout.c
@@ -8,13 +8,20 @@
 
 #include "qemu/osdep.h"
 #include "qemu/bswap.h"
+#include "qemu/error-report.h"
 #include "e820_memory_layout.h"
 
 static size_t e820_entries;
 struct e820_entry *e820_table;
+static gboolean e820_done;
 
 int e820_add_entry(uint64_t address, uint64_t length, uint32_t type)
 {
+if (e820_done) {
+warn_report("warning: E820 modified after being consumed");
+return -1;
+}
+
 /* new "etc/e820" file -- include ram and reserved entries */
 e820_table = g_renew(struct e820_entry, e820_table, e820_entries + 1);
 e820_table[e820_entries].address = cpu_to_le64(address);
@@ -27,6 +34,7 @@ int e820_add_entry(uint64_t address, uint64_t length, 
uint32_t type)
 
 int e820_get_num_entries(void)
 {
+e820_done = true;
 return e820_entries;
 }
 
diff --git a/hw/i386/fw_cfg.c b/hw/i386/fw_cfg.c
index 6e0d9945d0..e046ad1a54 100644
--- a/hw/i386/fw_cfg.c
+++ b/hw/i386/fw_cfg.c
@@ -102,6 +102,10 @@ void fw_cfg_build_smbios(PCMachineState *pcms, FWCfgState 
*fw_cfg,
 smbios_anchor, smbios_anchor_len);
 }
 #endif
+
+/* Add etc/e820 late, once all regions should be present */
+fw_cfg_add_file(fw_cfg, "etc/e820", e820_table,
+sizeof(struct e820_entry) * e820_get_num_entries());
 }
 
 FWCfgState *fw_cfg_arch_create(MachineState *ms,
@@ -139,9 +143,6 @@ FWCfgState *fw_cfg_arch_create(MachineState *ms,
 #endif
 fw_cfg_add_i32(fw_cfg, FW_CFG_IRQ0_OVERRIDE, 1);
 
-fw_cfg_add_file(fw_cfg, "etc/e820", e820_table,
-sizeof(struct e820_entry) * e820_get_num_entries());
-
 fw_cfg_add_bytes(fw_cfg, FW_CFG_HPET, _cfg, sizeof(hpet_cfg));
 /* allocate memory for the NUMA channel: one (64bit) word for the number
  * of nodes, one word for each VCPU->node and one word for each node to
diff --git a/hw/i386/microvm.c b/hw/i386/microvm.c
index fec63cacfa..89b2abcebf 100644
--- a/hw/i386/microvm.c
+++ b/hw/i386/microvm.c
@@ -324,8 +324,6 @@ static void microvm_memory_init(MicrovmMachineState *mms)
 fw_cfg_add_i16(fw_cfg, FW_CFG_MAX_CPUS, machine->smp.max_cpus);
 fw_cfg_add_i64(fw_cfg, FW_CFG_RAM_SIZE, (uint64_t)machine->ram_size);
 fw_cfg_add_i32(fw_cfg, FW_CFG_IRQ0_OVERRIDE, 1);
-fw_cfg_add_file(fw_cfg, "etc/e820", e820_table,
-sizeof(struct e820_entry) * e820_get_num_entries());
 
 rom_set_fw(fw_cfg);
 
@@ -586,9 +584,12 @@ static void microvm_machine_done(Notifier *notifier, void 
*data)
 {
 MicrovmMachineState *mms = container_of(notifier, MicrovmMachineState,
 machine_done);
+X86MachineState *x86ms = X86_MACHINE(mms);
 
 acpi_setup_microvm(mms);
 dt_setup_microvm(mms);
+fw_cfg_add_file(x86ms->fw_cfg, "etc/e820", e820_table,
+sizeof(struct e820_entry) * e820_get_num_entries());
 }
 
 static void microvm_powerdown_req(Notifier *notifier, void *data)
-- 
2.44.0




smime.p7s
Description: S/MIME cryptographic signature


Re: [RFC PATCH-for-9.0 v2 09/19] hw/block/xen_blkif: Align structs with QEMU_ALIGNED() instead of #pragma

2024-03-27 Thread David Woodhouse
On 27 March 2024 13:31:52 GMT, Anthony PERARD  wrote:
>On Tue, Nov 14, 2023 at 03:38:05PM +0100, Philippe Mathieu-Daudé wrote:
>> Except imported source files, QEMU code base uses
>> the QEMU_ALIGNED() macro to align its structures.
>
>This patch only convert the alignment, but discard pack. We need both or
>the struct is changed.

Which means we need some build-time asserts on struct size and field offsets. 
That should never have passed a build test.




Re: Unmapping KVM Guest Memory from Host Kernel

2024-03-08 Thread David Woodhouse
On Fri, 2024-03-08 at 09:35 -0800, David Matlack wrote:
> I think what James is looking for (and what we are also interested
> in), is _eliminating_ the ability to access guest memory from the
> direct map entirely. And in general, eliminate the ability to access
> guest memory in as many ways as possible.

Well, pKVM does that... 


smime.p7s
Description: S/MIME cryptographic signature


Re: [PATCH 2/2] tests/qtest/npcm7xx_emc-test: Connect all NICs to a backend

2024-02-06 Thread David Woodhouse
On Tue, 2024-02-06 at 17:12 +, Peter Maydell wrote:
> Currently QEMU will warn if there is a NIC on the board that
> is not connected to a backend. By default the '-nic user' will
> get used for all NICs, but if you manually connect a specific
> NIC to a specific backend, then the other NICs on the board
> have no backend and will be warned about:
> 
> qemu-system-arm: warning: nic npcm7xx-emc.1 has no peer
> qemu-system-arm: warning: nic npcm-gmac.0 has no peer
> qemu-system-arm: warning: nic npcm-gmac.1 has no peer
> 
> So suppress those warnings by manually connecting every NIC
> on the board to some backend.
> 
> Signed-off-by: Peter Maydell 

Reviewed-by: David Woodhouse 


... although do we want to expand this test to cover the GMACs? 


smime.p7s
Description: S/MIME cryptographic signature


Re: [PATCH 1/2] hw/arm/npcm7xx: Call qemu_configure_nic_device() for GMAC modules

2024-02-06 Thread David Woodhouse
On Tue, 2024-02-06 at 17:12 +, Peter Maydell wrote:
> The patchset adding the GMAC ethernet to this SoC crossed in the
> mail with the patchset cleaning up the NIC handling. When we
> create the GMAC modules we must call qemu_configure_nic_device()
> so that the user has the opportunity to use the -nic commandline
> option to create a network backend and connect it to the GMACs.
> 
> Add the missing call.
> 
> Fixes: 21e5326a7c ("hw/arm: Add GMAC devices to NPCM7XX SoC")
> Signed-off-by: Peter Maydell 

Reviewed-by: David Woodhouse 


smime.p7s
Description: S/MIME cryptographic signature


Re: [PULL 00/47] nic-config.for-upstream queue

2024-02-02 Thread David Woodhouse
On Fri, 2024-02-02 at 16:15 +, Peter Maydell wrote:
> On Fri, 2 Feb 2024 at 16:01, David Woodhouse  wrote:
> > 
> > What is the next step? Post the full series as a v5, or perhaps just
> > the single fixed patch which is now at
> > https://git.infradead.org/?p=users/dwmw2/qemu.git;a=commitdiff;h=2c20b4ee96db
> > 
> > ... and then another pull request?
> 
> If that diff above is the only change, then:
>  * roll a new pullrequest with the fix squashed into the appropriate patch
>  * have the subject marker be "PULL v2"
>  * you can send just the cover-letter and the one patch that has changed,
>    you don't need to resend the entire series (though it's not a big
>    deal if you do send the whole set of mails again)

Done, thank you.

> > The docs are fairly clear that pull
> > requests can't have even minor changes that haven't been posted
> > separately... and I guess the above incremental doesn't count?
> 
> Which bit of the docs is that? It's not our actual practice,
> so we should really fix the wording. The principle is "don't
> stick code into pullreqs that hasn't been through the review
> process", but in practice especially for submaintainers who
> know the system it's not uncommon to say "I'm going to
> squash change X in and take this" or similar rather than
> forcing submitters to do another round of sending out patches.
> There should be *something* on the list to say this change was
> put in, but eg the exchange in this email thread is fine for that.

I think I was looking at
https://www.qemu.org/docs/master/devel/submitting-a-pull-request.html
where it says "In particular if you’ve corrected issues in one round of
code review, you need to send your fixed patch series as normal to the
list; you can’t put it in a pull request until it’s gone through.
(Extremely trivial fixes may be OK to just fix in passing, but if in
doubt err on the side of not.)"

I think the doc is actually fine and I was just reading it too
conservatively. I have been making a conscious effort to pay attention,
follow the process and fit in, rather than just turning up and doing
whatever comes naturally from decades of working on open source. (I do
not *promise* that will last.)




smime.p7s
Description: S/MIME cryptographic signature


[PULL v2 38/47] hw/net/lasi_i82596: use qemu_create_nic_device()

2024-02-02 Thread David Woodhouse
From: David Woodhouse 

Create the device only if there is a corresponding NIC config for it.
Remove the explicit check on nd_table[0].used from hw/hppa/machine.c
which (since commit d8a3220005d7) tries to do the same thing.

The lasi_82596 support has been disabled since it was first introduced,
since enable_lasi_lan() has always been zero. This allows the user to
enable it by explicitly requesting a NIC model 'lasi_82596' or just
using the alias 'lasi'. Otherwise, it defaults to a PCI NIC as before.

Signed-off-by: David Woodhouse 
Reviewed-by: Thomas Huth 
---
 hw/hppa/machine.c   |  9 -
 hw/net/lasi_i82596.c| 12 +++-
 include/hw/net/lasi_82596.h |  4 ++--
 3 files changed, 13 insertions(+), 12 deletions(-)

diff --git a/hw/hppa/machine.c b/hw/hppa/machine.c
index a1045b48cc..eb78c46ff1 100644
--- a/hw/hppa/machine.c
+++ b/hw/hppa/machine.c
@@ -362,14 +362,13 @@ static void machine_HP_common_init_tail(MachineState 
*machine, PCIBus *pci_bus,
 }
 
 /* Network setup. */
-if (nd_table[0].used && enable_lasi_lan()) {
+if (lasi_dev) {
 lasi_82596_init(addr_space, translate(NULL, LASI_LAN_HPA),
-qdev_get_gpio_in(lasi_dev, LASI_IRQ_LAN_HPA));
+qdev_get_gpio_in(lasi_dev, LASI_IRQ_LAN_HPA),
+enable_lasi_lan());
 }
 
-if (!enable_lasi_lan()) {
-pci_init_nic_devices(pci_bus, mc->default_nic);
-}
+pci_init_nic_devices(pci_bus, mc->default_nic);
 
 /* BMC board: HP Powerbar SP2 Diva (with console only) */
 pci_dev = pci_new(-1, "pci-serial");
diff --git a/hw/net/lasi_i82596.c b/hw/net/lasi_i82596.c
index 09e830ba5f..fcf7fae941 100644
--- a/hw/net/lasi_i82596.c
+++ b/hw/net/lasi_i82596.c
@@ -118,19 +118,21 @@ static void lasi_82596_realize(DeviceState *dev, Error 
**errp)
 i82596_common_init(dev, s, _lasi_82596_info);
 }
 
-SysBusI82596State *lasi_82596_init(MemoryRegion *addr_space,
-  hwaddr hpa, qemu_irq lan_irq)
+SysBusI82596State *lasi_82596_init(MemoryRegion *addr_space, hwaddr hpa,
+   qemu_irq lan_irq, gboolean match_default)
 {
 DeviceState *dev;
 SysBusI82596State *s;
 static const MACAddr HP_MAC = {
 .a = { 0x08, 0x00, 0x09, 0xef, 0x34, 0xf6 } };
 
-qemu_check_nic_model(_table[0], TYPE_LASI_82596);
-dev = qdev_new(TYPE_LASI_82596);
+dev = qemu_create_nic_device(TYPE_LASI_82596, match_default, "lasi");
+if (!dev) {
+return NULL;
+}
+
 s = SYSBUS_I82596(dev);
 s->state.irq = lan_irq;
-qdev_set_nic_properties(dev, _table[0]);
 sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), _fatal);
 s->state.conf.macaddr = HP_MAC; /* set HP MAC prefix */
 
diff --git a/include/hw/net/lasi_82596.h b/include/hw/net/lasi_82596.h
index 3ef2f47ba2..439356ec19 100644
--- a/include/hw/net/lasi_82596.h
+++ b/include/hw/net/lasi_82596.h
@@ -25,7 +25,7 @@ struct SysBusI82596State {
 int val_index:1;
 };
 
-SysBusI82596State *lasi_82596_init(MemoryRegion *addr_space,
-hwaddr hpa, qemu_irq irq);
+SysBusI82596State *lasi_82596_init(MemoryRegion *addr_space, hwaddr hpa,
+   qemu_irq irq, gboolean match_default);
 
 #endif
-- 
2.43.0




[PULL v2 00/47] nic-config-2 queue

2024-02-02 Thread David Woodhouse
From: David Woodhouse 

The following changes since commit c3709fde5955d13f6d4f86ab46ef3cc2288ca65e:

  Merge tag 'pull-aspeed-20240201' of https://github.com/legoater/qemu into 
staging (2024-02-01 14:42:11 +)

are available in the Git repository at:

  git://git.infradead.org/users/dwmw2/qemu.git tags/pull-nic-config-2-20240202

for you to fetch changes up to e8c5c4525cbbd7207c085732cfd1e67d8f3d662a:

  net: make nb_nics and nd_table[] static in net/net.c (2024-02-02 16:23:48 
+)


Rework matching of network devices to -nic options (v2)


David Woodhouse (47):
  net: add qemu_{configure,create}_nic_device(), qemu_find_nic_info()
  net: report list of available models according to platform
  net: add qemu_create_nic_bus_devices()
  hw/pci: add pci_init_nic_devices(), pci_init_nic_in_slot()
  hw/i386/pc: use qemu_get_nic_info() and pci_init_nic_devices()
  hw/xen: use qemu_create_nic_bus_devices() to instantiate Xen NICs
  hw/alpha/dp264: use pci_init_nic_devices()
  hw/arm/sbsa-ref: use pci_init_nic_devices()
  hw/arm/virt: use pci_init_nic_devices()
  hw/hppa: use pci_init_nic_devices()
  hw/loongarch: use pci_init_nic_devices()
  hw/mips/fuloong2e: use pci_init_nic_devices()
  hw/mips/malta: use pci_init_nic_devices()
  hw/mips/loongson3_virt: use pci_init_nic_devices()
  hw/ppc/prep: use pci_init_nic_devices()
  hw/ppc/spapr: use qemu_get_nic_info() and pci_init_nic_devices()
  hw/ppc: use pci_init_nic_devices()
  hw/sh4/r2d: use pci_init_nic_devices()
  hw/sparc64/sun4u: use pci_init_nic_devices()
  hw/xtensa/virt: use pci_init_nic_devices()
  hw/arm/allwinner: use qemu_configure_nic_device()
  hw/arm/aspeed: use qemu_configure_nic_device()
  hw/arm/exynos4: use qemu_create_nic_device()
  hw/arm/fsl: use qemu_configure_nic_device()
  hw/net/smc91c111: use qemu_configure_nic_device()
  hw/net/lan9118: use qemu_configure_nic_device()
  hw/arm/highbank: use qemu_create_nic_device()
  hw/arm/npcm7xx: use qemu_configure_nic_device, allow emc0/emc1 as aliases
  hw/arm/stellaris: use qemu_find_nic_info()
  hw/arm: use qemu_configure_nic_device()
  hw/net/etraxfs-eth: use qemu_configure_nic_device()
  hw/m68k/mcf5208: use qemu_create_nic_device()
  hw/m68k/q800: use qemu_find_nic_info()
  hw/microblaze: use qemu_configure_nic_device()
  hw/mips/mipssim: use qemu_create_nic_device()
  hw/mips/jazz: use qemu_find_nic_info()
  hw/net/lasi_i82596: Re-enable build
  hw/net/lasi_i82596: use qemu_create_nic_device()
  hw/openrisc/openrisc_sim: use qemu_create_nic_device()
  hw/riscv: use qemu_configure_nic_device()
  hw/s390x/s390-virtio-ccw: use qemu_create_nic_device()
  hw/sparc/sun4m: use qemu_find_nic_info()
  hw/xtensa/xtfpga: use qemu_create_nic_device()
  net: remove qemu_check_nic_model()
  hw/pci: remove pci_nic_init_nofail()
  net: remove qemu_show_nic_models(), qemu_find_nic_model()
  net: make nb_nics and nd_table[] static in net/net.c

 hw/alpha/dp264.c |   4 +-
 hw/arm/allwinner-a10.c   |   6 +-
 hw/arm/allwinner-h3.c|   6 +-
 hw/arm/allwinner-r40.c   |  27 +---
 hw/arm/aspeed.c  |   9 +-
 hw/arm/exynos4_boards.c  |   6 +-
 hw/arm/fsl-imx25.c   |   2 +-
 hw/arm/fsl-imx6.c|   2 +-
 hw/arm/fsl-imx6ul.c  |   2 +-
 hw/arm/fsl-imx7.c|   2 +-
 hw/arm/gumstix.c |   6 +-
 hw/arm/highbank.c|  12 +-
 hw/arm/integratorcp.c|   5 +-
 hw/arm/kzm.c |   4 +-
 hw/arm/mainstone.c   |   3 +-
 hw/arm/mps2-tz.c |   8 +-
 hw/arm/mps2.c|   2 +-
 hw/arm/msf2-soc.c|   6 +-
 hw/arm/musicpal.c|   3 +-
 hw/arm/npcm7xx.c |  16 +-
 hw/arm/realview.c|  25 ++-
 hw/arm/sbsa-ref.c|   4 +-
 hw/arm/stellaris.c   |  30 +++-
 hw/arm/versatilepb.c |  15 +-
 hw/arm/vexpress.c|   4 +-
 hw/arm/virt.c|   4 +-
 hw/arm/xilinx_zynq.c |  11 +-
 hw/arm/xlnx-versal.c |   7 +-
 hw/arm/xlnx-zynqmp.c |   8 +-
 hw/cris/axis_dev88.c |   9 +-
 hw/hppa/machine.c|  12 +-
 hw/i386/pc.c |  38 +++--
 hw/i386/pc_piix.c|   2 +-
 hw/i386/pc_q35.c |   2 +-
 hw/loongarch/virt.c

[PATCH v4.1 38/47] hw/net/lasi_i82596: use qemu_create_nic_device()

2024-02-02 Thread David Woodhouse
From: David Woodhouse 


Create the device only if there is a corresponding NIC config for it.
Remove the explicit check on nd_table[0].used from hw/hppa/machine.c
which (since commit d8a3220005d7) tries to do the same thing.

The lasi_82596 support has been disabled since it was first introduced,
since enable_lasi_lan() has always been zero. This allows the user to
enable it by explicitly requesting a NIC model 'lasi_82596' or just
using the alias 'lasi'. Otherwise, it defaults to a PCI NIC as before.

Signed-off-by: David Woodhouse 
Reviewed-by: Thomas Huth 
---
v4.1: Only attempt to find GPIOs on the lasi_dev if it exists. This
  was theoretically broken already, but enable_lasi_dev() is
  hard-coded to zero, so adding the user override to enable it
  is what actually exposed the bug.

(Not reposting the whole series for that)

 hw/hppa/machine.c   |  9 -
 hw/net/lasi_i82596.c| 12 +++-
 include/hw/net/lasi_82596.h |  4 ++--
 3 files changed, 13 insertions(+), 12 deletions(-)

diff --git a/hw/hppa/machine.c b/hw/hppa/machine.c
index a1045b48cc..eb78c46ff1 100644
--- a/hw/hppa/machine.c
+++ b/hw/hppa/machine.c
@@ -362,14 +362,13 @@ static void machine_HP_common_init_tail(MachineState 
*machine, PCIBus *pci_bus,
 }
 
 /* Network setup. */
-if (nd_table[0].used && enable_lasi_lan()) {
+if (lasi_dev) {
 lasi_82596_init(addr_space, translate(NULL, LASI_LAN_HPA),
-qdev_get_gpio_in(lasi_dev, LASI_IRQ_LAN_HPA));
+qdev_get_gpio_in(lasi_dev, LASI_IRQ_LAN_HPA),
+enable_lasi_lan());
 }
 
-if (!enable_lasi_lan()) {
-pci_init_nic_devices(pci_bus, mc->default_nic);
-}
+pci_init_nic_devices(pci_bus, mc->default_nic);
 
 /* BMC board: HP Powerbar SP2 Diva (with console only) */
 pci_dev = pci_new(-1, "pci-serial");
diff --git a/hw/net/lasi_i82596.c b/hw/net/lasi_i82596.c
index 09e830ba5f..fcf7fae941 100644
--- a/hw/net/lasi_i82596.c
+++ b/hw/net/lasi_i82596.c
@@ -118,19 +118,21 @@ static void lasi_82596_realize(DeviceState *dev, Error 
**errp)
 i82596_common_init(dev, s, _lasi_82596_info);
 }
 
-SysBusI82596State *lasi_82596_init(MemoryRegion *addr_space,
-  hwaddr hpa, qemu_irq lan_irq)
+SysBusI82596State *lasi_82596_init(MemoryRegion *addr_space, hwaddr hpa,
+   qemu_irq lan_irq, gboolean match_default)
 {
 DeviceState *dev;
 SysBusI82596State *s;
 static const MACAddr HP_MAC = {
 .a = { 0x08, 0x00, 0x09, 0xef, 0x34, 0xf6 } };
 
-qemu_check_nic_model(_table[0], TYPE_LASI_82596);
-dev = qdev_new(TYPE_LASI_82596);
+dev = qemu_create_nic_device(TYPE_LASI_82596, match_default, "lasi");
+if (!dev) {
+return NULL;
+}
+
 s = SYSBUS_I82596(dev);
 s->state.irq = lan_irq;
-qdev_set_nic_properties(dev, _table[0]);
 sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), _fatal);
 s->state.conf.macaddr = HP_MAC; /* set HP MAC prefix */
 
diff --git a/include/hw/net/lasi_82596.h b/include/hw/net/lasi_82596.h
index 3ef2f47ba2..439356ec19 100644
--- a/include/hw/net/lasi_82596.h
+++ b/include/hw/net/lasi_82596.h
@@ -25,7 +25,7 @@ struct SysBusI82596State {
 int val_index:1;
 };
 
-SysBusI82596State *lasi_82596_init(MemoryRegion *addr_space,
-hwaddr hpa, qemu_irq irq);
+SysBusI82596State *lasi_82596_init(MemoryRegion *addr_space, hwaddr hpa,
+   qemu_irq irq, gboolean match_default);
 
 #endif
-- 
2.34.1




smime.p7s
Description: S/MIME cryptographic signature


Re: [PULL 00/47] nic-config.for-upstream queue

2024-02-02 Thread David Woodhouse
On Fri, 2024-02-02 at 15:32 +, Peter Maydell wrote:
> 
> $ ./build/all/qemu-system-hppa -M C3700
> Segmentation fault (core dumped)

Ah, got it. Some HPPA machine types don't have a lasi_dev.


--- a/hw/hppa/machine.c
+++ b/hw/hppa/machine.c
@@ -362,9 +362,11 @@ static void machine_HP_common_init_tail(MachineState 
*machine, PCIBus *pci_bus,
 }
 
 /* Network setup. */
-lasi_82596_init(addr_space, translate(NULL, LASI_LAN_HPA),
-qdev_get_gpio_in(lasi_dev, LASI_IRQ_LAN_HPA),
-enable_lasi_lan());
+if (lasi_dev) {
+lasi_82596_init(addr_space, translate(NULL, LASI_LAN_HPA),
+qdev_get_gpio_in(lasi_dev, LASI_IRQ_LAN_HPA),
+enable_lasi_lan());
+}
 
 pci_init_nic_devices(pci_bus, mc->default_nic);
 
New pipeline running (FWIW) at
https://gitlab.com/dwmw2/qemu/-/pipelines/1162635873

What is the next step? Post the full series as a v5, or perhaps just
the single fixed patch which is now at
https://git.infradead.org/?p=users/dwmw2/qemu.git;a=commitdiff;h=2c20b4ee96db

... and then another pull request? The docs are fairly clear that pull
requests can't have even minor changes that haven't been posted
separately... and I guess the above incremental doesn't count?

Sorry for the noise.


smime.p7s
Description: S/MIME cryptographic signature


Re: [PULL 00/47] nic-config.for-upstream queue

2024-02-02 Thread David Woodhouse
On Fri, 2024-02-02 at 15:32 +, Peter Maydell wrote:
> 
> This fails "make check' because some of the qom-test and
> test-hmp checks fail when the QEMU binary segfaults.
> 
> https://gitlab.com/qemu-project/qemu/-/jobs/6084552256
> https://gitlab.com/qemu-project/qemu/-/jobs/6084044180

Thanks.  Any idea why that didn't show up in my own pipeline?
https://gitlab.com/dwmw2/qemu/-/pipelines/1160949234

(The only difference in that tree is a last minute Reviewed-by:)
 
> Reproduces on an x86-64 host if you do a build and 'make check'
> for all target archs.
> 
> Generally this kind of segfault is because some machine type
> segfaults on startup. For instance:
> 
> $ ./build/all/qemu-system-hppa -M C3700
> Segmentation fault (core dumped)
> 
> (It's possible that's the only machine type that has a
> problem; I haven't tried to exhaustively check.)

Sorry about that. I'll go improve my test coverage...


smime.p7s
Description: S/MIME cryptographic signature


[PULL 07/47] hw/alpha/dp264: use pci_init_nic_devices()

2024-02-01 Thread David Woodhouse
From: David Woodhouse 

Signed-off-by: David Woodhouse 
Reviewed-by: Thomas Huth 
---
 hw/alpha/dp264.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/hw/alpha/dp264.c b/hw/alpha/dp264.c
index 03495e1e60..52a1fa310b 100644
--- a/hw/alpha/dp264.c
+++ b/hw/alpha/dp264.c
@@ -124,9 +124,7 @@ static void clipper_init(MachineState *machine)
 pci_vga_init(pci_bus);
 
 /* Network setup.  e1000 is good enough, failing Tulip support.  */
-for (i = 0; i < nb_nics; i++) {
-pci_nic_init_nofail(_table[i], pci_bus, mc->default_nic, NULL);
-}
+pci_init_nic_devices(pci_bus, mc->default_nic);
 
 /* Super I/O */
 isa_create_simple(isa_bus, TYPE_SMC37C669_SUPERIO);
-- 
2.43.0




[PULL 15/47] hw/ppc/prep: use pci_init_nic_devices()

2024-02-01 Thread David Woodhouse
From: David Woodhouse 

Previously, the first PCI NIC would be placed in PCI slot 3 and the rest
would be dynamically assigned. Even if the user overrode the default NIC
type and made it something other than PCNet.

Now, the first PCNet NIC (that is, anything not explicitly specified
to be anything different) will go to slot 3 even if it isn't the first
NIC specified on the command line. And anything else will be dynamically
assigned.

Signed-off-by: David Woodhouse 
Reviewed-by: Thomas Huth 
---
 hw/ppc/prep.c | 8 +++-
 1 file changed, 3 insertions(+), 5 deletions(-)

diff --git a/hw/ppc/prep.c b/hw/ppc/prep.c
index 137276bcb9..1a6cd05c61 100644
--- a/hw/ppc/prep.c
+++ b/hw/ppc/prep.c
@@ -241,7 +241,6 @@ static void ibm_40p_init(MachineState *machine)
 ISADevice *isa_dev;
 ISABus *isa_bus;
 void *fw_cfg;
-int i;
 uint32_t kernel_base = 0, initrd_base = 0;
 long kernel_size = 0, initrd_size = 0;
 char boot_device;
@@ -336,10 +335,9 @@ static void ibm_40p_init(MachineState *machine)
 /* XXX: s3-trio at PCI_DEVFN(2, 0) */
 pci_vga_init(pci_bus);
 
-for (i = 0; i < nb_nics; i++) {
-pci_nic_init_nofail(_table[i], pci_bus, mc->default_nic,
-i == 0 ? "3" : NULL);
-}
+/* First PCNET device at PCI_DEVFN(3, 0) */
+pci_init_nic_in_slot(pci_bus, mc->default_nic, NULL, "3");
+pci_init_nic_devices(pci_bus, mc->default_nic);
 }
 
 /* Prepare firmware configuration for OpenBIOS */
-- 
2.43.0




[PULL 01/47] net: add qemu_{configure, create}_nic_device(), qemu_find_nic_info()

2024-02-01 Thread David Woodhouse
From: David Woodhouse 

Most code which directly accesses nd_table[] and nb_nics uses them for
one of two things. Either "I have created a NIC device and I'd like a
configuration for it", or "I will create a NIC device *if* there is a
configuration for it".  With some variants on the theme around whether
they actually *check* if the model specified in the configuration is
the right one.

Provide functions which perform both of those, allowing platforms to
be a little more consistent and as a step towards making nd_table[]
and nb_nics private to the net code.

One might argue that platforms ought to be consistent about whether
they create the unconfigured devices or not, but making significant
user-visible changes is explicitly *not* the intent right now.

The new functions leave the 'model' field of the NICInfo as NULL after
using it for the default NIC model, unlike the qemu_check_nic_model()
function which does set nd->model to match default_model explicitly.
This is acceptable because there is no code which consumes nd->model
except this NIC-matching code in net/net.c, and no reasonable excuse
for any code wanting to use nd->model in future.

Also export the qemu_find_nic_info() helper, as some platforms have
special cases they need to handle.

Signed-off-by: David Woodhouse 
Reviewed-by: Paul Durrant 
Reviewed-by: Thomas Huth 
---
 include/net/net.h | 40 +
 net/net.c | 51 +++
 2 files changed, 91 insertions(+)

diff --git a/include/net/net.h b/include/net/net.h
index ffbd2c8d56..dff1872b4d 100644
--- a/include/net/net.h
+++ b/include/net/net.h
@@ -207,7 +207,47 @@ int qemu_show_nic_models(const char *arg, const char 
*const *models);
 void qemu_check_nic_model(NICInfo *nd, const char *model);
 int qemu_find_nic_model(NICInfo *nd, const char * const *models,
 const char *default_model);
+/**
+ * qemu_find_nic_info: Obtain NIC configuration information
+ * @typename: Name of device object type
+ * @match_default: Match NIC configurations with no model specified
+ * @alias: Additional model string to match (for user convenience and
+ * backward compatibility).
+ *
+ * Search for a NIC configuration matching the NIC model constraints.
+ */
+NICInfo *qemu_find_nic_info(const char *typename, bool match_default,
+const char *alias);
+/**
+ * qemu_configure_nic_device: Apply NIC configuration to a given device
+ * @dev: Network device to be configured
+ * @match_default: Match NIC configurations with no model specified
+ * @alias: Additional model string to match
+ *
+ * Search for a NIC configuration for the provided device, using the
+ * additionally specified matching constraints. If found, apply the
+ * configuration using qdev_set_nic_properties() and return %true.
+ *
+ * This is used by platform code which creates the device anyway,
+ * regardless of whether there is a configuration for it. This tends
+ * to be platforms which ignore `--nodefaults` and create net devices
+ * anyway, for example because the Ethernet device on that board is
+ * always physically present.
+ */
+bool qemu_configure_nic_device(DeviceState *dev, bool match_default,
+   const char *alias);
 
+/**
+ * qemu_create_nic_device: Create a NIC device if a configuration exists for it
+ * @typename: Object typename of network device
+ * @match_default: Match NIC configurations with no model specified
+ * @alias: Additional model string to match
+ *
+ * Search for a NIC configuration for the provided device type. If found,
+ * create an object of the corresponding type and return it.
+ */
+DeviceState *qemu_create_nic_device(const char *typename, bool match_default,
+const char *alias);
 void print_net_client(Monitor *mon, NetClientState *nc);
 void net_socket_rs_init(SocketReadState *rs,
 SocketReadStateFinalize *finalize,
diff --git a/net/net.c b/net/net.c
index 0520bc1681..aeb7f573fc 100644
--- a/net/net.c
+++ b/net/net.c
@@ -1087,6 +1087,57 @@ static int net_init_nic(const Netdev *netdev, const char 
*name,
 return idx;
 }
 
+NICInfo *qemu_find_nic_info(const char *typename, bool match_default,
+const char *alias)
+{
+NICInfo *nd;
+int i;
+
+for (i = 0; i < nb_nics; i++) {
+nd = _table[i];
+
+if (!nd->used || nd->instantiated) {
+continue;
+}
+
+if ((match_default && !nd->model) || !g_strcmp0(nd->model, typename)
+|| (alias && !g_strcmp0(nd->model, alias))) {
+return nd;
+}
+}
+return NULL;
+}
+
+
+/* "I have created a device. Please configure it if you can" */
+bool qemu_configure_nic_device(DeviceState *dev, bool match_default,
+   const char *alias

[PULL 05/47] hw/i386/pc: use qemu_get_nic_info() and pci_init_nic_devices()

2024-02-01 Thread David Woodhouse
From: David Woodhouse 

Eliminate direct access to nd_table[] and nb_nics by processing the the
Xen and ISA NICs first and then calling pci_init_nic_devices() for the
rest.

Signed-off-by: David Woodhouse 
Reviewed-by: Paul Durrant 
---
 hw/i386/pc.c| 31 +++
 include/hw/net/ne2000-isa.h |  2 --
 2 files changed, 19 insertions(+), 14 deletions(-)

diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index 803244e5cc..ebb0b1c667 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -654,15 +654,19 @@ static const int ne2000_io[NE2000_NB_MAX] = { 0x300, 
0x320, 0x340, 0x360,
   0x280, 0x380 };
 static const int ne2000_irq[NE2000_NB_MAX] = { 9, 10, 11, 3, 4, 5 };
 
-static void pc_init_ne2k_isa(ISABus *bus, NICInfo *nd)
+static gboolean pc_init_ne2k_isa(ISABus *bus, NICInfo *nd, Error **errp)
 {
 static int nb_ne2k = 0;
 
-if (nb_ne2k == NE2000_NB_MAX)
-return;
+if (nb_ne2k == NE2000_NB_MAX) {
+error_setg(errp,
+   "maximum number of ISA NE2000 devices exceeded");
+return false;
+}
 isa_ne2000_init(bus, ne2000_io[nb_ne2k],
 ne2000_irq[nb_ne2k], nd);
 nb_ne2k++;
+return true;
 }
 
 void pc_acpi_smi_interrupt(void *opaque, int irq, int level)
@@ -1297,23 +1301,26 @@ void pc_nic_init(PCMachineClass *pcmc, ISABus *isa_bus, 
PCIBus *pci_bus,
  BusState *xen_bus)
 {
 MachineClass *mc = MACHINE_CLASS(pcmc);
-int i;
+bool default_is_ne2k = g_str_equal(mc->default_nic, TYPE_ISA_NE2000);
+NICInfo *nd;
 
 rom_set_order_override(FW_CFG_ORDER_OVERRIDE_NIC);
-for (i = 0; i < nb_nics; i++) {
-NICInfo *nd = _table[i];
-const char *model = nd->model ? nd->model : mc->default_nic;
 
-if (xen_bus && (!nd->model || g_str_equal(model, "xen-net-device"))) {
+if (xen_bus) {
+while ((nd = qemu_find_nic_info("xen-net-device", true, NULL))) {
 DeviceState *dev = qdev_new("xen-net-device");
 qdev_set_nic_properties(dev, nd);
 qdev_realize_and_unref(dev, xen_bus, _fatal);
-} else if (g_str_equal(model, "ne2k_isa")) {
-pc_init_ne2k_isa(isa_bus, nd);
-} else {
-pci_nic_init_nofail(nd, pci_bus, model, NULL);
 }
 }
+
+while ((nd = qemu_find_nic_info(TYPE_ISA_NE2000, default_is_ne2k, NULL))) {
+pc_init_ne2k_isa(isa_bus, nd, _fatal);
+}
+
+/* Anything remaining should be a PCI NIC */
+pci_init_nic_devices(pci_bus, mc->default_nic);
+
 rom_reset_order_override();
 }
 
diff --git a/include/hw/net/ne2000-isa.h b/include/hw/net/ne2000-isa.h
index af59ee0b02..73bae10ad1 100644
--- a/include/hw/net/ne2000-isa.h
+++ b/include/hw/net/ne2000-isa.h
@@ -22,8 +22,6 @@ static inline ISADevice *isa_ne2000_init(ISABus *bus, int 
base, int irq,
 {
 ISADevice *d;
 
-qemu_check_nic_model(nd, "ne2k_isa");
-
 d = isa_try_new(TYPE_ISA_NE2000);
 if (d) {
 DeviceState *dev = DEVICE(d);
-- 
2.43.0




[PULL 32/47] hw/m68k/mcf5208: use qemu_create_nic_device()

2024-02-01 Thread David Woodhouse
From: David Woodhouse 

Signed-off-by: David Woodhouse 
Reviewed-by: Thomas Huth 
---
 hw/m68k/mcf5208.c | 19 ++-
 1 file changed, 6 insertions(+), 13 deletions(-)

diff --git a/hw/m68k/mcf5208.c b/hw/m68k/mcf5208.c
index d22d8536db..0cfb806c20 100644
--- a/hw/m68k/mcf5208.c
+++ b/hw/m68k/mcf5208.c
@@ -206,16 +206,16 @@ static void mcf5208_sys_init(MemoryRegion *address_space, 
qemu_irq *pic)
 }
 }
 
-static void mcf_fec_init(MemoryRegion *sysmem, NICInfo *nd, hwaddr base,
- qemu_irq *irqs)
+static void mcf_fec_init(MemoryRegion *sysmem, hwaddr base, qemu_irq *irqs)
 {
 DeviceState *dev;
 SysBusDevice *s;
 int i;
 
-qemu_check_nic_model(nd, TYPE_MCF_FEC_NET);
-dev = qdev_new(TYPE_MCF_FEC_NET);
-qdev_set_nic_properties(dev, nd);
+dev = qemu_create_nic_device(TYPE_MCF_FEC_NET, true, NULL);
+if (!dev) {
+return;
+}
 
 s = SYS_BUS_DEVICE(dev);
 sysbus_realize_and_unref(s, _fatal);
@@ -267,14 +267,7 @@ static void mcf5208evb_init(MachineState *machine)
 
 mcf5208_sys_init(address_space_mem, pic);
 
-if (nb_nics > 1) {
-error_report("Too many NICs");
-exit(1);
-}
-if (nd_table[0].used) {
-mcf_fec_init(address_space_mem, _table[0],
- 0xfc03, pic + 36);
-}
+mcf_fec_init(address_space_mem, 0xfc03, pic + 36);
 
 g_free(pic);
 
-- 
2.43.0




[PULL 08/47] hw/arm/sbsa-ref: use pci_init_nic_devices()

2024-02-01 Thread David Woodhouse
From: David Woodhouse 

Signed-off-by: David Woodhouse 
Reviewed-by: Leif Lindholm 
---
 hw/arm/sbsa-ref.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/hw/arm/sbsa-ref.c b/hw/arm/sbsa-ref.c
index 85cb68d546..f2adf30337 100644
--- a/hw/arm/sbsa-ref.c
+++ b/hw/arm/sbsa-ref.c
@@ -673,9 +673,7 @@ static void create_pcie(SBSAMachineState *sms)
 
 pci = PCI_HOST_BRIDGE(dev);
 if (pci->bus) {
-for (i = 0; i < nb_nics; i++) {
-pci_nic_init_nofail(_table[i], pci->bus, mc->default_nic, NULL);
-}
+pci_init_nic_devices(pci->bus, mc->default_nic);
 }
 
 pci_create_simple(pci->bus, -1, "bochs-display");
-- 
2.43.0




[PULL 37/47] hw/net/lasi_i82596: Re-enable build

2024-02-01 Thread David Woodhouse
From: David Woodhouse 

When converting to the shiny build-system-du-jour, a typo prevented the
last_i82596 driver from being built. Correct the config option name to
re-enable the build. And include "sysemu/sysemu.h" so it actually builds.

Fixes: b1419fa66558 ("meson: convert hw/net")
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/2144
Signed-off-by: David Woodhouse 
Reviewed-by: Thomas Huth 
---
 hw/net/lasi_i82596.c | 1 +
 hw/net/meson.build   | 2 +-
 2 files changed, 2 insertions(+), 1 deletion(-)

diff --git a/hw/net/lasi_i82596.c b/hw/net/lasi_i82596.c
index 6a3147fe2d..09e830ba5f 100644
--- a/hw/net/lasi_i82596.c
+++ b/hw/net/lasi_i82596.c
@@ -14,6 +14,7 @@
 #include "qapi/error.h"
 #include "qemu/timer.h"
 #include "hw/sysbus.h"
+#include "sysemu/sysemu.h"
 #include "net/eth.h"
 #include "hw/net/lasi_82596.h"
 #include "hw/net/i82596.h"
diff --git a/hw/net/meson.build b/hw/net/meson.build
index 9afceb0619..2b426d3d5a 100644
--- a/hw/net/meson.build
+++ b/hw/net/meson.build
@@ -33,7 +33,7 @@ system_ss.add(when: 'CONFIG_MARVELL_88W8618', if_true: 
files('mv88w8618_eth.c'))
 system_ss.add(when: 'CONFIG_CADENCE', if_true: files('cadence_gem.c'))
 system_ss.add(when: 'CONFIG_STELLARIS_ENET', if_true: 
files('stellaris_enet.c'))
 system_ss.add(when: 'CONFIG_LANCE', if_true: files('lance.c'))
-system_ss.add(when: 'CONFIG_LASI_I82596', if_true: files('lasi_i82596.c'))
+system_ss.add(when: 'CONFIG_LASI_82596', if_true: files('lasi_i82596.c'))
 system_ss.add(when: 'CONFIG_I82596_COMMON', if_true: files('i82596.c'))
 system_ss.add(when: 'CONFIG_SUNHME', if_true: files('sunhme.c'))
 system_ss.add(when: 'CONFIG_FTGMAC100', if_true: files('ftgmac100.c'))
-- 
2.43.0




[PULL 00/47] nic-config.for-upstream queue

2024-02-01 Thread David Woodhouse
The following changes since commit 14639717bf379480e937716fcaf1e72b47fd4c5f:

  Merge tag 'pull-trivial-patches' of https://gitlab.com/mjt0k/qemu into 
staging (2024-01-31 19:53:45 +)

are available in the Git repository at:

  git://git.infradead.org/users/dwmw2/qemu.git 
tags/pull-nic-config.for-upstream-20240201

for you to fetch changes up to 5382a24c9b0be4391ea91b020bb72ad15c05cc88:

  net: make nb_nics and nd_table[] static in net/net.c (2024-02-01 16:21:52 
+)


Rework matching of network devices to -nic options


David Woodhouse (47):
  net: add qemu_{configure,create}_nic_device(), qemu_find_nic_info()
  net: report list of available models according to platform
  net: add qemu_create_nic_bus_devices()
  hw/pci: add pci_init_nic_devices(), pci_init_nic_in_slot()
  hw/i386/pc: use qemu_get_nic_info() and pci_init_nic_devices()
  hw/xen: use qemu_create_nic_bus_devices() to instantiate Xen NICs
  hw/alpha/dp264: use pci_init_nic_devices()
  hw/arm/sbsa-ref: use pci_init_nic_devices()
  hw/arm/virt: use pci_init_nic_devices()
  hw/hppa: use pci_init_nic_devices()
  hw/loongarch: use pci_init_nic_devices()
  hw/mips/fuloong2e: use pci_init_nic_devices()
  hw/mips/malta: use pci_init_nic_devices()
  hw/mips/loongson3_virt: use pci_init_nic_devices()
  hw/ppc/prep: use pci_init_nic_devices()
  hw/ppc/spapr: use qemu_get_nic_info() and pci_init_nic_devices()
  hw/ppc: use pci_init_nic_devices()
  hw/sh4/r2d: use pci_init_nic_devices()
  hw/sparc64/sun4u: use pci_init_nic_devices()
  hw/xtensa/virt: use pci_init_nic_devices()
  hw/arm/allwinner: use qemu_configure_nic_device()
  hw/arm/aspeed: use qemu_configure_nic_device()
  hw/arm/exynos4: use qemu_create_nic_device()
  hw/arm/fsl: use qemu_configure_nic_device()
  hw/net/smc91c111: use qemu_configure_nic_device()
  hw/net/lan9118: use qemu_configure_nic_device()
  hw/arm/highbank: use qemu_create_nic_device()
  hw/arm/npcm7xx: use qemu_configure_nic_device, allow emc0/emc1 as aliases
  hw/arm/stellaris: use qemu_find_nic_info()
  hw/arm: use qemu_configure_nic_device()
  hw/net/etraxfs-eth: use qemu_configure_nic_device()
  hw/m68k/mcf5208: use qemu_create_nic_device()
  hw/m68k/q800: use qemu_find_nic_info()
  hw/microblaze: use qemu_configure_nic_device()
  hw/mips/mipssim: use qemu_create_nic_device()
  hw/mips/jazz: use qemu_find_nic_info()
  hw/net/lasi_i82596: Re-enable build
  hw/net/lasi_i82596: use qemu_create_nic_device()
  hw/openrisc/openrisc_sim: use qemu_create_nic_device()
  hw/riscv: use qemu_configure_nic_device()
  hw/s390x/s390-virtio-ccw: use qemu_create_nic_device()
  hw/sparc/sun4m: use qemu_find_nic_info()
  hw/xtensa/xtfpga: use qemu_create_nic_device()
  net: remove qemu_check_nic_model()
  hw/pci: remove pci_nic_init_nofail()
  net: remove qemu_show_nic_models(), qemu_find_nic_model()
  net: make nb_nics and nd_table[] static in net/net.c

 hw/alpha/dp264.c |   4 +-
 hw/arm/allwinner-a10.c   |   6 +-
 hw/arm/allwinner-h3.c|   6 +-
 hw/arm/allwinner-r40.c   |  27 +---
 hw/arm/aspeed.c  |   9 +-
 hw/arm/exynos4_boards.c  |   6 +-
 hw/arm/fsl-imx25.c   |   2 +-
 hw/arm/fsl-imx6.c|   2 +-
 hw/arm/fsl-imx6ul.c  |   2 +-
 hw/arm/fsl-imx7.c|   2 +-
 hw/arm/gumstix.c |   6 +-
 hw/arm/highbank.c|  12 +-
 hw/arm/integratorcp.c|   5 +-
 hw/arm/kzm.c |   4 +-
 hw/arm/mainstone.c   |   3 +-
 hw/arm/mps2-tz.c |   8 +-
 hw/arm/mps2.c|   2 +-
 hw/arm/msf2-soc.c|   6 +-
 hw/arm/musicpal.c|   3 +-
 hw/arm/npcm7xx.c |  16 +-
 hw/arm/realview.c|  25 ++-
 hw/arm/sbsa-ref.c|   4 +-
 hw/arm/stellaris.c   |  30 +++-
 hw/arm/versatilepb.c |  15 +-
 hw/arm/vexpress.c|   4 +-
 hw/arm/virt.c|   4 +-
 hw/arm/xilinx_zynq.c |  11 +-
 hw/arm/xlnx-versal.c |   7 +-
 hw/arm/xlnx-zynqmp.c |   8 +-
 hw/cris/axis_dev88.c |   9 +-
 hw/hppa/machine.c|  14 +-
 hw/i386/pc.c |  38 +++--
 hw/i386/pc_piix.c|   2 +-
 hw/i386/pc_q35.c |   2 +-
 hw/loongarch/virt.c  |   4 +-
 hw/m68k

[PULL 17/47] hw/ppc: use pci_init_nic_devices()

2024-02-01 Thread David Woodhouse
From: David Woodhouse 

Signed-off-by: David Woodhouse 
Reviewed-by: Thomas Huth 
---
 hw/ppc/e500.c  |  4 +---
 hw/ppc/mac_newworld.c  |  4 +---
 hw/ppc/mac_oldworld.c  |  4 +---
 hw/ppc/ppc440_bamboo.c | 14 +-
 4 files changed, 8 insertions(+), 18 deletions(-)

diff --git a/hw/ppc/e500.c b/hw/ppc/e500.c
index 566f1200dd..3bd12b54ab 100644
--- a/hw/ppc/e500.c
+++ b/hw/ppc/e500.c
@@ -1079,9 +1079,7 @@ void ppce500_init(MachineState *machine)
 
 if (pci_bus) {
 /* Register network interfaces. */
-for (i = 0; i < nb_nics; i++) {
-pci_nic_init_nofail(_table[i], pci_bus, mc->default_nic, NULL);
-}
+pci_init_nic_devices(pci_bus, mc->default_nic);
 }
 
 /* Register spinning region */
diff --git a/hw/ppc/mac_newworld.c b/hw/ppc/mac_newworld.c
index 535710314a..b36dbaf2b6 100644
--- a/hw/ppc/mac_newworld.c
+++ b/hw/ppc/mac_newworld.c
@@ -444,9 +444,7 @@ static void ppc_core99_init(MachineState *machine)
 graphic_depth = 15;
 }
 
-for (i = 0; i < nb_nics; i++) {
-pci_nic_init_nofail(_table[i], pci_bus, mc->default_nic, NULL);
-}
+pci_init_nic_devices(pci_bus, mc->default_nic);
 
 /* The NewWorld NVRAM is not located in the MacIO device */
 if (kvm_enabled() && qemu_real_host_page_size() > 4096) {
diff --git a/hw/ppc/mac_oldworld.c b/hw/ppc/mac_oldworld.c
index 9acc7adfc9..1981d3d8f6 100644
--- a/hw/ppc/mac_oldworld.c
+++ b/hw/ppc/mac_oldworld.c
@@ -277,9 +277,7 @@ static void ppc_heathrow_init(MachineState *machine)
 
 pci_vga_init(pci_bus);
 
-for (i = 0; i < nb_nics; i++) {
-pci_nic_init_nofail(_table[i], pci_bus, mc->default_nic, NULL);
-}
+pci_init_nic_devices(pci_bus, mc->default_nic);
 
 /* MacIO IDE */
 ide_drive_get(hd, ARRAY_SIZE(hd));
diff --git a/hw/ppc/ppc440_bamboo.c b/hw/ppc/ppc440_bamboo.c
index a189942de4..c75c3083e6 100644
--- a/hw/ppc/ppc440_bamboo.c
+++ b/hw/ppc/ppc440_bamboo.c
@@ -161,7 +161,6 @@ static void bamboo_init(MachineState *machine)
 DeviceState *uicdev;
 SysBusDevice *uicsbd;
 int success;
-int i;
 
 if (kvm_enabled()) {
 error_report("machine %s does not support the KVM accelerator",
@@ -234,14 +233,11 @@ static void bamboo_init(MachineState *machine)
 }
 
 if (pcibus) {
-/* Register network interfaces. */
-for (i = 0; i < nb_nics; i++) {
-/*
- * There are no PCI NICs on the Bamboo board, but there are
- * PCI slots, so we can pick whatever default model we want.
- */
-pci_nic_init_nofail(_table[i], pcibus, mc->default_nic, NULL);
-}
+/*
+ * There are no PCI NICs on the Bamboo board, but there are
+ * PCI slots, so we can pick whatever default model we want.
+ */
+pci_init_nic_devices(pcibus, mc->default_nic);
 }
 
 /* Load kernel. */
-- 
2.43.0




[PULL 24/47] hw/arm/fsl: use qemu_configure_nic_device()

2024-02-01 Thread David Woodhouse
From: David Woodhouse 

Signed-off-by: David Woodhouse 
Reviewed-by: Thomas Huth 
---
 hw/arm/fsl-imx25.c  | 2 +-
 hw/arm/fsl-imx6.c   | 2 +-
 hw/arm/fsl-imx6ul.c | 2 +-
 hw/arm/fsl-imx7.c   | 2 +-
 4 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/hw/arm/fsl-imx25.c b/hw/arm/fsl-imx25.c
index 4a49507ef1..5ed87edfe4 100644
--- a/hw/arm/fsl-imx25.c
+++ b/hw/arm/fsl-imx25.c
@@ -171,7 +171,7 @@ static void fsl_imx25_realize(DeviceState *dev, Error 
**errp)
 
 object_property_set_uint(OBJECT(>fec), "phy-num", s->phy_num,
  _abort);
-qdev_set_nic_properties(DEVICE(>fec), _table[0]);
+qemu_configure_nic_device(DEVICE(>fec), true, NULL);
 
 if (!sysbus_realize(SYS_BUS_DEVICE(>fec), errp)) {
 return;
diff --git a/hw/arm/fsl-imx6.c b/hw/arm/fsl-imx6.c
index b7f93d8d9c..85748cb233 100644
--- a/hw/arm/fsl-imx6.c
+++ b/hw/arm/fsl-imx6.c
@@ -388,7 +388,7 @@ static void fsl_imx6_realize(DeviceState *dev, Error **errp)
 
 object_property_set_uint(OBJECT(>eth), "phy-num", s->phy_num,
  _abort);
-qdev_set_nic_properties(DEVICE(>eth), _table[0]);
+qemu_configure_nic_device(DEVICE(>eth), true, NULL);
 if (!sysbus_realize(SYS_BUS_DEVICE(>eth), errp)) {
 return;
 }
diff --git a/hw/arm/fsl-imx6ul.c b/hw/arm/fsl-imx6ul.c
index 343bd65d1b..19f443570b 100644
--- a/hw/arm/fsl-imx6ul.c
+++ b/hw/arm/fsl-imx6ul.c
@@ -473,7 +473,7 @@ static void fsl_imx6ul_realize(DeviceState *dev, Error 
**errp)
  s->phy_num[i], _abort);
 object_property_set_uint(OBJECT(>eth[i]), "tx-ring-num",
  FSL_IMX6UL_ETH_NUM_TX_RINGS, _abort);
-qdev_set_nic_properties(DEVICE(>eth[i]), _table[i]);
+qemu_configure_nic_device(DEVICE(>eth[i]), true, NULL);
 sysbus_realize(SYS_BUS_DEVICE(>eth[i]), _abort);
 
 sysbus_mmio_map(SYS_BUS_DEVICE(>eth[i]), 0,
diff --git a/hw/arm/fsl-imx7.c b/hw/arm/fsl-imx7.c
index 5728109491..9f2ef34555 100644
--- a/hw/arm/fsl-imx7.c
+++ b/hw/arm/fsl-imx7.c
@@ -447,7 +447,7 @@ static void fsl_imx7_realize(DeviceState *dev, Error **errp)
  s->phy_num[i], _abort);
 object_property_set_uint(OBJECT(>eth[i]), "tx-ring-num",
  FSL_IMX7_ETH_NUM_TX_RINGS, _abort);
-qdev_set_nic_properties(DEVICE(>eth[i]), _table[i]);
+qemu_configure_nic_device(DEVICE(>eth[i]), true, NULL);
 sysbus_realize(SYS_BUS_DEVICE(>eth[i]), _abort);
 
 sysbus_mmio_map(SYS_BUS_DEVICE(>eth[i]), 0, FSL_IMX7_ENETn_ADDR[i]);
-- 
2.43.0




[PULL 41/47] hw/s390x/s390-virtio-ccw: use qemu_create_nic_device()

2024-02-01 Thread David Woodhouse
From: David Woodhouse 

Signed-off-by: David Woodhouse 
Acked-by: Thomas Huth 
---
 hw/s390x/s390-virtio-ccw.c | 11 ++-
 1 file changed, 2 insertions(+), 9 deletions(-)

diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c
index c99682b07d..62804cc228 100644
--- a/hw/s390x/s390-virtio-ccw.c
+++ b/hw/s390x/s390-virtio-ccw.c
@@ -229,16 +229,9 @@ static void s390_init_ipl_dev(const char *kernel_filename,
 
 static void s390_create_virtio_net(BusState *bus, const char *name)
 {
-int i;
-
-for (i = 0; i < nb_nics; i++) {
-NICInfo *nd = _table[i];
-DeviceState *dev;
-
-qemu_check_nic_model(nd, "virtio");
+DeviceState *dev;
 
-dev = qdev_new(name);
-qdev_set_nic_properties(dev, nd);
+while ((dev = qemu_create_nic_device(name, true, "virtio"))) {
 qdev_realize_and_unref(dev, bus, _fatal);
 }
 }
-- 
2.43.0




[PULL 33/47] hw/m68k/q800: use qemu_find_nic_info()

2024-02-01 Thread David Woodhouse
From: David Woodhouse 

If a corresponding NIC configuration was found, it will have a MAC address
already assigned, so use that. Else, generate and assign a default one.

Using qemu_find_nic_info() is simpler than the alternative of using
qemu_configure_nic_device() and then having to fetch the "mac" property
as a string and convert it.

Signed-off-by: David Woodhouse 
Reviewed-by: Thomas Huth 
---
 hw/m68k/q800.c | 29 -
 1 file changed, 16 insertions(+), 13 deletions(-)

diff --git a/hw/m68k/q800.c b/hw/m68k/q800.c
index b80a3b6d5f..fa7683bf76 100644
--- a/hw/m68k/q800.c
+++ b/hw/m68k/q800.c
@@ -48,6 +48,7 @@
 #include "hw/display/macfb.h"
 #include "hw/block/swim.h"
 #include "net/net.h"
+#include "net/util.h"
 #include "qapi/error.h"
 #include "qemu/error-report.h"
 #include "sysemu/qtest.h"
@@ -270,6 +271,8 @@ static void q800_machine_init(MachineState *machine)
 BusState *adb_bus;
 NubusBus *nubus;
 DriveInfo *dinfo;
+NICInfo *nd;
+MACAddr mac;
 uint8_t rng_seed[32];
 
 linux_boot = (kernel_filename != NULL);
@@ -370,13 +373,6 @@ static void q800_machine_init(MachineState *machine)
 
 /* MACSONIC */
 
-if (nb_nics > 1) {
-error_report("q800 can only have one ethernet interface");
-exit(1);
-}
-
-qemu_check_nic_model(_table[0], "dp83932");
-
 /*
  * MacSonic driver needs an Apple MAC address
  * Valid prefix are:
@@ -386,14 +382,21 @@ static void q800_machine_init(MachineState *machine)
  * 08:00:07 Apple
  * (Q800 use the last one)
  */
-nd_table[0].macaddr.a[0] = 0x08;
-nd_table[0].macaddr.a[1] = 0x00;
-nd_table[0].macaddr.a[2] = 0x07;
-
 object_initialize_child(OBJECT(machine), "dp8393x", >dp8393x,
 TYPE_DP8393X);
 dev = DEVICE(>dp8393x);
-qdev_set_nic_properties(dev, _table[0]);
+nd = qemu_find_nic_info(TYPE_DP8393X, true, "dp83932");
+if (nd) {
+qdev_set_nic_properties(dev, nd);
+memcpy(mac.a, nd->macaddr.a, sizeof(mac.a));
+} else {
+qemu_macaddr_default_if_unset();
+}
+mac.a[0] = 0x08;
+mac.a[1] = 0x00;
+mac.a[2] = 0x07;
+qdev_prop_set_macaddr(dev, "mac", mac.a);
+
 qdev_prop_set_uint8(dev, "it_shift", 2);
 qdev_prop_set_bit(dev, "big_endian", true);
 object_property_set_link(OBJECT(dev), "dma_mr",
@@ -414,7 +417,7 @@ static void q800_machine_init(MachineState *machine)
 prom = memory_region_get_ram_ptr(>dp8393x_prom);
 checksum = 0;
 for (i = 0; i < 6; i++) {
-prom[i] = revbit8(nd_table[0].macaddr.a[i]);
+prom[i] = revbit8(mac.a[i]);
 checksum ^= prom[i];
 }
 prom[7] = 0xff - checksum;
-- 
2.43.0




[PULL 43/47] hw/xtensa/xtfpga: use qemu_create_nic_device()

2024-02-01 Thread David Woodhouse
From: David Woodhouse 

Signed-off-by: David Woodhouse 
Reviewed-by: Thomas Huth 
---
 hw/xtensa/xtfpga.c | 13 ++---
 1 file changed, 6 insertions(+), 7 deletions(-)

diff --git a/hw/xtensa/xtfpga.c b/hw/xtensa/xtfpga.c
index fbad1c83a3..f49e6591dc 100644
--- a/hw/xtensa/xtfpga.c
+++ b/hw/xtensa/xtfpga.c
@@ -141,14 +141,16 @@ static void xtfpga_net_init(MemoryRegion *address_space,
 hwaddr base,
 hwaddr descriptors,
 hwaddr buffers,
-qemu_irq irq, NICInfo *nd)
+qemu_irq irq)
 {
 DeviceState *dev;
 SysBusDevice *s;
 MemoryRegion *ram;
 
-dev = qdev_new("open_eth");
-qdev_set_nic_properties(dev, nd);
+dev = qemu_create_nic_device("open_eth", true, NULL);
+if (!dev) {
+return;
+}
 
 s = SYS_BUS_DEVICE(dev);
 sysbus_realize_and_unref(s, _fatal);
@@ -301,10 +303,7 @@ static void xtfpga_init(const XtfpgaBoardDesc *board, 
MachineState *machine)
 memory_region_add_subregion(system_memory, board->io[1], io);
 }
 xtfpga_fpga_init(system_io, 0x0d02, freq);
-if (nd_table[0].used) {
-xtfpga_net_init(system_io, 0x0d03, 0x0d030400, 0x0d80,
-extints[1], nd_table);
-}
+xtfpga_net_init(system_io, 0x0d03, 0x0d030400, 0x0d80, extints[1]);
 
 serial_mm_init(system_io, 0x0d050020, 2, extints[0],
115200, serial_hd(0), DEVICE_NATIVE_ENDIAN);
-- 
2.43.0




[PULL 25/47] hw/net/smc91c111: use qemu_configure_nic_device()

2024-02-01 Thread David Woodhouse
From: David Woodhouse 

Some callers instantiate the device unconditionally, others will do so only
if there is a NICInfo to go with it. This appears to be fairly random, but
preserve the existing behaviour of each caller for now.

Signed-off-by: David Woodhouse 
Reviewed-by: Thomas Huth 
---
 hw/arm/gumstix.c   |  6 ++
 hw/arm/integratorcp.c  |  5 +++--
 hw/arm/mainstone.c |  3 +--
 hw/arm/realview.c  | 25 ++---
 hw/arm/versatilepb.c   | 15 ---
 hw/net/smc91c111.c |  5 ++---
 include/hw/net/smc91c111.h |  2 +-
 7 files changed, 23 insertions(+), 38 deletions(-)

diff --git a/hw/arm/gumstix.c b/hw/arm/gumstix.c
index 3f2bcaa24e..d5de5409e1 100644
--- a/hw/arm/gumstix.c
+++ b/hw/arm/gumstix.c
@@ -73,8 +73,7 @@ static void connex_init(MachineState *machine)
   FLASH_SECTOR_SIZE, 2, 0, 0, 0, 0, 0);
 
 /* Interrupt line of NIC is connected to GPIO line 36 */
-smc91c111_init(_table[0], 0x04000300,
-qdev_get_gpio_in(cpu->gpio, 36));
+smc91c111_init(0x04000300, qdev_get_gpio_in(cpu->gpio, 36));
 }
 
 static void verdex_init(MachineState *machine)
@@ -97,8 +96,7 @@ static void verdex_init(MachineState *machine)
   FLASH_SECTOR_SIZE, 2, 0, 0, 0, 0, 0);
 
 /* Interrupt line of NIC is connected to GPIO line 99 */
-smc91c111_init(_table[0], 0x04000300,
-qdev_get_gpio_in(cpu->gpio, 99));
+smc91c111_init(0x04000300, qdev_get_gpio_in(cpu->gpio, 99));
 }
 
 static void connex_class_init(ObjectClass *oc, void *data)
diff --git a/hw/arm/integratorcp.c b/hw/arm/integratorcp.c
index 793262eca8..f016d20485 100644
--- a/hw/arm/integratorcp.c
+++ b/hw/arm/integratorcp.c
@@ -666,8 +666,9 @@ static void integratorcp_init(MachineState *machine)
 sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, 0x1d00);
 sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, pic[25]);
 
-if (nd_table[0].used)
-smc91c111_init(_table[0], 0xc800, pic[27]);
+if (qemu_find_nic_info("smc91c111", true, NULL)) {
+smc91c111_init(0xc800, pic[27]);
+}
 
 sysbus_create_simple("pl110", 0xc000, pic[22]);
 
diff --git a/hw/arm/mainstone.c b/hw/arm/mainstone.c
index fc14e05060..d2e2e68aa3 100644
--- a/hw/arm/mainstone.c
+++ b/hw/arm/mainstone.c
@@ -152,8 +152,7 @@ static void mainstone_common_init(MachineState *machine,
 qdev_get_gpio_in(mst_irq, S1_IRQ),
 qdev_get_gpio_in(mst_irq, S1_CD_IRQ));
 
-smc91c111_init(_table[0], MST_ETH_PHYS,
-qdev_get_gpio_in(mst_irq, ETHERNET_IRQ));
+smc91c111_init(MST_ETH_PHYS, qdev_get_gpio_in(mst_irq, ETHERNET_IRQ));
 
 mainstone_binfo.board_id = arm_id;
 arm_load_kernel(mpu->cpu, machine, _binfo);
diff --git a/hw/arm/realview.c b/hw/arm/realview.c
index 566deff9ce..c6bd6e5961 100644
--- a/hw/arm/realview.c
+++ b/hw/arm/realview.c
@@ -90,7 +90,6 @@ static void realview_init(MachineState *machine,
 I2CBus *i2c;
 int n;
 unsigned int smp_cpus = machine->smp.cpus;
-int done_nic = 0;
 qemu_irq cpu_irq[4];
 int is_mpcore = 0;
 int is_pb = 0;
@@ -296,24 +295,20 @@ static void realview_init(MachineState *machine,
 n--;
 }
 }
-for(n = 0; n < nb_nics; n++) {
-nd = _table[n];
-
-if (!done_nic && (!nd->model ||
-strcmp(nd->model, is_pb ? "lan9118" : "smc91c111") == 0)) {
-if (is_pb) {
-lan9118_init(nd, 0x4e00, pic[28]);
-} else {
-smc91c111_init(nd, 0x4e00, pic[28]);
-}
-done_nic = 1;
+
+nd = qemu_find_nic_info(is_pb ? "lan9118" : "smc91c111", true, NULL);
+if (nd) {
+if (is_pb) {
+lan9118_init(nd, 0x4e00, pic[28]);
 } else {
-if (pci_bus) {
-pci_nic_init_nofail(nd, pci_bus, "rtl8139", NULL);
-}
+smc91c111_init(0x4e00, pic[28]);
 }
 }
 
+if (pci_bus) {
+pci_init_nic_devices(pci_bus, "rtl8139");
+}
+
 dev = sysbus_create_simple(TYPE_ARM_SBCON_I2C, 0x10002000, NULL);
 i2c = (I2CBus *)qdev_get_child_bus(dev, "i2c");
 i2c_slave_create_simple(i2c, "ds1338", 0x68);
diff --git a/hw/arm/versatilepb.c b/hw/arm/versatilepb.c
index 1d813aa23b..d10b75dfdb 100644
--- a/hw/arm/versatilepb.c
+++ b/hw/arm/versatilepb.c
@@ -192,10 +192,8 @@ static void versatile_init(MachineState *machine, int 
board_id)
 SysBusDevice *busdev;
 DeviceState *pl041;
 PCIBus *pci_bus;
-NICInfo *nd;
 I2CBus *i2c;
 int n;
-int done_smc = 0;
 DriveInfo *dinfo;
 
 if (machine->ram_size > 0x1000) {
@@ -263,16 +261,11 @@ static void versatile_init(MachineState *machine, int 
board_id)
 sysbus_connect_i

[PULL 38/47] hw/net/lasi_i82596: use qemu_create_nic_device()

2024-02-01 Thread David Woodhouse
From: David Woodhouse 

Create the device only if there is a corresponding NIC config for it.
Remove the explicit check on nd_table[0].used from hw/hppa/machine.c
which (since commit d8a3220005d7) tries to do the same thing.

The lasi_82596 support has been disabled since it was first introduced,
since enable_lasi_lan() has always been zero. This allows the user to
enable it by explicitly requesting a NIC model 'lasi_82596' or just
using the alias 'lasi'. Otherwise, it defaults to a PCI NIC as before.

Signed-off-by: David Woodhouse 
Reviewed-by: Thomas Huth 
---
 hw/hppa/machine.c   | 11 ---
 hw/net/lasi_i82596.c| 12 +++-
 include/hw/net/lasi_82596.h |  4 ++--
 3 files changed, 13 insertions(+), 14 deletions(-)

diff --git a/hw/hppa/machine.c b/hw/hppa/machine.c
index a1045b48cc..5ae4f176f6 100644
--- a/hw/hppa/machine.c
+++ b/hw/hppa/machine.c
@@ -362,14 +362,11 @@ static void machine_HP_common_init_tail(MachineState 
*machine, PCIBus *pci_bus,
 }
 
 /* Network setup. */
-if (nd_table[0].used && enable_lasi_lan()) {
-lasi_82596_init(addr_space, translate(NULL, LASI_LAN_HPA),
-qdev_get_gpio_in(lasi_dev, LASI_IRQ_LAN_HPA));
-}
+lasi_82596_init(addr_space, translate(NULL, LASI_LAN_HPA),
+qdev_get_gpio_in(lasi_dev, LASI_IRQ_LAN_HPA),
+enable_lasi_lan());
 
-if (!enable_lasi_lan()) {
-pci_init_nic_devices(pci_bus, mc->default_nic);
-}
+pci_init_nic_devices(pci_bus, mc->default_nic);
 
 /* BMC board: HP Powerbar SP2 Diva (with console only) */
 pci_dev = pci_new(-1, "pci-serial");
diff --git a/hw/net/lasi_i82596.c b/hw/net/lasi_i82596.c
index 09e830ba5f..fcf7fae941 100644
--- a/hw/net/lasi_i82596.c
+++ b/hw/net/lasi_i82596.c
@@ -118,19 +118,21 @@ static void lasi_82596_realize(DeviceState *dev, Error 
**errp)
 i82596_common_init(dev, s, _lasi_82596_info);
 }
 
-SysBusI82596State *lasi_82596_init(MemoryRegion *addr_space,
-  hwaddr hpa, qemu_irq lan_irq)
+SysBusI82596State *lasi_82596_init(MemoryRegion *addr_space, hwaddr hpa,
+   qemu_irq lan_irq, gboolean match_default)
 {
 DeviceState *dev;
 SysBusI82596State *s;
 static const MACAddr HP_MAC = {
 .a = { 0x08, 0x00, 0x09, 0xef, 0x34, 0xf6 } };
 
-qemu_check_nic_model(_table[0], TYPE_LASI_82596);
-dev = qdev_new(TYPE_LASI_82596);
+dev = qemu_create_nic_device(TYPE_LASI_82596, match_default, "lasi");
+if (!dev) {
+return NULL;
+}
+
 s = SYSBUS_I82596(dev);
 s->state.irq = lan_irq;
-qdev_set_nic_properties(dev, _table[0]);
 sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), _fatal);
 s->state.conf.macaddr = HP_MAC; /* set HP MAC prefix */
 
diff --git a/include/hw/net/lasi_82596.h b/include/hw/net/lasi_82596.h
index 3ef2f47ba2..439356ec19 100644
--- a/include/hw/net/lasi_82596.h
+++ b/include/hw/net/lasi_82596.h
@@ -25,7 +25,7 @@ struct SysBusI82596State {
 int val_index:1;
 };
 
-SysBusI82596State *lasi_82596_init(MemoryRegion *addr_space,
-hwaddr hpa, qemu_irq irq);
+SysBusI82596State *lasi_82596_init(MemoryRegion *addr_space, hwaddr hpa,
+   qemu_irq irq, gboolean match_default);
 
 #endif
-- 
2.43.0




[PULL 04/47] hw/pci: add pci_init_nic_devices(), pci_init_nic_in_slot()

2024-02-01 Thread David Woodhouse
From: David Woodhouse 

The loop over nd_table[] to add PCI NICs is repeated in quite a few
places. Add a helper function to do it.

Some platforms also try to instantiate a specific model in a specific
slot, to match the real hardware. Add pci_init_nic_in_slot() for that
purpose.

Signed-off-by: David Woodhouse 
Reviewed-by: Paul Durrant 
---
 hw/pci/pci.c | 45 
 include/hw/pci/pci.h |  4 +++-
 2 files changed, 48 insertions(+), 1 deletion(-)

diff --git a/hw/pci/pci.c b/hw/pci/pci.c
index 76080af580..5849606f66 100644
--- a/hw/pci/pci.c
+++ b/hw/pci/pci.c
@@ -1925,6 +1925,51 @@ PCIDevice *pci_nic_init_nofail(NICInfo *nd, PCIBus 
*rootbus,
 return pci_dev;
 }
 
+void pci_init_nic_devices(PCIBus *bus, const char *default_model)
+{
+qemu_create_nic_bus_devices(>qbus, TYPE_PCI_DEVICE, default_model,
+"virtio", "virtio-net-pci");
+}
+
+bool pci_init_nic_in_slot(PCIBus *rootbus, const char *model,
+  const char *alias, const char *devaddr)
+{
+NICInfo *nd = qemu_find_nic_info(model, true, alias);
+int dom, busnr, devfn;
+PCIDevice *pci_dev;
+unsigned slot;
+PCIBus *bus;
+
+if (!nd) {
+return false;
+}
+
+if (!devaddr || pci_parse_devaddr(devaddr, , , , NULL) < 0) 
{
+error_report("Invalid PCI device address %s for device %s",
+ devaddr, model);
+exit(1);
+}
+
+if (dom != 0) {
+error_report("No support for non-zero PCI domains");
+exit(1);
+}
+
+devfn = PCI_DEVFN(slot, 0);
+
+bus = pci_find_bus_nr(rootbus, busnr);
+if (!bus) {
+error_report("Invalid PCI device address %s for device %s",
+ devaddr, model);
+exit(1);
+}
+
+pci_dev = pci_new(devfn, model);
+qdev_set_nic_properties(_dev->qdev, nd);
+pci_realize_and_unref(pci_dev, bus, _fatal);
+return true;
+}
+
 PCIDevice *pci_vga_init(PCIBus *bus)
 {
 vga_interface_created = true;
diff --git a/include/hw/pci/pci.h b/include/hw/pci/pci.h
index fa6313aabc..6ff0b95a02 100644
--- a/include/hw/pci/pci.h
+++ b/include/hw/pci/pci.h
@@ -317,7 +317,9 @@ void pci_device_reset(PCIDevice *dev);
 PCIDevice *pci_nic_init_nofail(NICInfo *nd, PCIBus *rootbus,
const char *default_model,
const char *default_devaddr);
-
+void pci_init_nic_devices(PCIBus *bus, const char *default_model);
+bool pci_init_nic_in_slot(PCIBus *rootbus, const char *default_model,
+  const char *alias, const char *devaddr);
 PCIDevice *pci_vga_init(PCIBus *bus);
 
 static inline PCIBus *pci_get_bus(const PCIDevice *dev)
-- 
2.43.0




[PULL 34/47] hw/microblaze: use qemu_configure_nic_device()

2024-02-01 Thread David Woodhouse
From: David Woodhouse 

Signed-off-by: David Woodhouse 
Reviewed-by: Thomas Huth 
---
 hw/microblaze/petalogix_ml605_mmu.c  | 3 +--
 hw/microblaze/petalogix_s3adsp1800_mmu.c | 3 +--
 2 files changed, 2 insertions(+), 4 deletions(-)

diff --git a/hw/microblaze/petalogix_ml605_mmu.c 
b/hw/microblaze/petalogix_ml605_mmu.c
index fb7889cf67..0f5fabc32e 100644
--- a/hw/microblaze/petalogix_ml605_mmu.c
+++ b/hw/microblaze/petalogix_ml605_mmu.c
@@ -133,7 +133,6 @@ petalogix_ml605_init(MachineState *machine)
 sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, irq[TIMER_IRQ]);
 
 /* axi ethernet and dma initialization. */
-qemu_check_nic_model(_table[0], "xlnx.axi-ethernet");
 eth0 = qdev_new("xlnx.axi-ethernet");
 dma = qdev_new("xlnx.axi-dma");
 
@@ -145,7 +144,7 @@ petalogix_ml605_init(MachineState *machine)
   "axistream-connected-target", NULL);
 cs = object_property_get_link(OBJECT(dma),
   "axistream-control-connected-target", NULL);
-qdev_set_nic_properties(eth0, _table[0]);
+qemu_configure_nic_device(eth0, true, NULL);
 qdev_prop_set_uint32(eth0, "rxmem", 0x1000);
 qdev_prop_set_uint32(eth0, "txmem", 0x1000);
 object_property_set_link(OBJECT(eth0), "axistream-connected", ds,
diff --git a/hw/microblaze/petalogix_s3adsp1800_mmu.c 
b/hw/microblaze/petalogix_s3adsp1800_mmu.c
index 505639c298..dad46bd7f9 100644
--- a/hw/microblaze/petalogix_s3adsp1800_mmu.c
+++ b/hw/microblaze/petalogix_s3adsp1800_mmu.c
@@ -114,9 +114,8 @@ petalogix_s3adsp1800_init(MachineState *machine)
 sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, TIMER_BASEADDR);
 sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, irq[TIMER_IRQ]);
 
-qemu_check_nic_model(_table[0], "xlnx.xps-ethernetlite");
 dev = qdev_new("xlnx.xps-ethernetlite");
-qdev_set_nic_properties(dev, _table[0]);
+qemu_configure_nic_device(dev, true, NULL);
 qdev_prop_set_uint32(dev, "tx-ping-pong", 0);
 qdev_prop_set_uint32(dev, "rx-ping-pong", 0);
 sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), _fatal);
-- 
2.43.0




[PULL 36/47] hw/mips/jazz: use qemu_find_nic_info()

2024-02-01 Thread David Woodhouse
From: David Woodhouse 

Signed-off-by: David Woodhouse 
Reviewed-by: Thomas Huth 
---
 hw/mips/jazz.c | 15 +++
 1 file changed, 7 insertions(+), 8 deletions(-)

diff --git a/hw/mips/jazz.c b/hw/mips/jazz.c
index 0d2348aa5a..5bf3e328db 100644
--- a/hw/mips/jazz.c
+++ b/hw/mips/jazz.c
@@ -119,15 +119,19 @@ static const MemoryRegionOps dma_dummy_ops = {
 .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
-static void mips_jazz_init_net(NICInfo *nd, IOMMUMemoryRegion *rc4030_dma_mr,
+static void mips_jazz_init_net(IOMMUMemoryRegion *rc4030_dma_mr,
DeviceState *rc4030, MemoryRegion *dp8393x_prom)
 {
 DeviceState *dev;
 SysBusDevice *sysbus;
 int checksum, i;
 uint8_t *prom;
+NICInfo *nd;
 
-qemu_check_nic_model(nd, "dp83932");
+nd = qemu_find_nic_info("dp8393x", true, "dp82932");
+if (!nd) {
+return;
+}
 
 dev = qdev_new("dp8393x");
 qdev_set_nic_properties(dev, nd);
@@ -324,12 +328,7 @@ static void mips_jazz_init(MachineState *machine,
 }
 
 /* Network controller */
-if (nb_nics == 1) {
-mips_jazz_init_net(_table[0], rc4030_dma_mr, rc4030, dp8393x_prom);
-} else if (nb_nics > 1) {
-error_report("This machine only supports one NIC");
-exit(1);
-}
+mips_jazz_init_net(rc4030_dma_mr, rc4030, dp8393x_prom);
 
 /* SCSI adapter */
 dev = qdev_new(TYPE_SYSBUS_ESP);
-- 
2.43.0




[PULL 02/47] net: report list of available models according to platform

2024-02-01 Thread David Woodhouse
From: David Woodhouse 

By noting the models for which a configuration was requested, we can give
the user an accurate list of which NIC models were actually available on
the platform/configuration that was otherwise chosen.

Signed-off-by: David Woodhouse 
Reviewed-by: Paul Durrant 
---
 net/net.c | 94 +++
 1 file changed, 94 insertions(+)

diff --git a/net/net.c b/net/net.c
index aeb7f573fc..962904eaef 100644
--- a/net/net.c
+++ b/net/net.c
@@ -75,6 +75,8 @@ typedef QSIMPLEQ_HEAD(, NetdevQueueEntry) NetdevQueue;
 
 static NetdevQueue nd_queue = QSIMPLEQ_HEAD_INITIALIZER(nd_queue);
 
+static GHashTable *nic_model_help;
+
 /***/
 /* network device redirectors */
 
@@ -1087,12 +1089,94 @@ static int net_init_nic(const Netdev *netdev, const 
char *name,
 return idx;
 }
 
+static gboolean add_nic_result(gpointer key, gpointer value, gpointer 
user_data)
+{
+GPtrArray *results = user_data;
+GPtrArray *alias_list = value;
+const char *model = key;
+char *result;
+
+if (!alias_list) {
+result = g_strdup(model);
+} else {
+GString *result_str = g_string_new(model);
+int i;
+
+g_string_append(result_str, " (aka ");
+for (i = 0; i < alias_list->len; i++) {
+if (i) {
+g_string_append(result_str, ", ");
+}
+g_string_append(result_str, alias_list->pdata[i]);
+}
+g_string_append(result_str, ")");
+result = result_str->str;
+g_string_free(result_str, false);
+g_ptr_array_unref(alias_list);
+}
+g_ptr_array_add(results, result);
+return true;
+}
+
+static int model_cmp(char **a, char **b)
+{
+return strcmp(*a, *b);
+}
+
+static void show_nic_models(void)
+{
+GPtrArray *results = g_ptr_array_new();
+int i;
+
+g_hash_table_foreach_remove(nic_model_help, add_nic_result, results);
+g_ptr_array_sort(results, (GCompareFunc)model_cmp);
+
+printf("Available NIC models for this configuration:\n");
+for (i = 0 ; i < results->len; i++) {
+printf("%s\n", (char *)results->pdata[i]);
+}
+g_hash_table_unref(nic_model_help);
+nic_model_help = NULL;
+}
+
+static void add_nic_model_help(const char *model, const char *alias)
+{
+GPtrArray *alias_list = NULL;
+
+if (g_hash_table_lookup_extended(nic_model_help, model, NULL,
+ (gpointer *)_list)) {
+/* Already exists, no alias to add: return */
+if (!alias) {
+return;
+}
+if (alias_list) {
+/* Check if this alias is already in the list. Add if not. */
+if (!g_ptr_array_find_with_equal_func(alias_list, alias,
+  g_str_equal, NULL)) {
+g_ptr_array_add(alias_list, g_strdup(alias));
+}
+return;
+}
+}
+/* Either this model wasn't in the list already, or a first alias added */
+if (alias) {
+alias_list = g_ptr_array_new();
+g_ptr_array_set_free_func(alias_list, g_free);
+g_ptr_array_add(alias_list, g_strdup(alias));
+}
+g_hash_table_replace(nic_model_help, g_strdup(model), alias_list);
+}
+
 NICInfo *qemu_find_nic_info(const char *typename, bool match_default,
 const char *alias)
 {
 NICInfo *nd;
 int i;
 
+if (nic_model_help) {
+add_nic_model_help(typename, alias);
+}
+
 for (i = 0; i < nb_nics; i++) {
 nd = _table[i];
 
@@ -1606,6 +1690,10 @@ void net_check_clients(void)
 NetClientState *nc;
 int i;
 
+if (nic_model_help) {
+show_nic_models();
+exit(0);
+}
 net_hub_check_clients();
 
 QTAILQ_FOREACH(nc, _clients, next) {
@@ -1685,6 +1773,12 @@ static int net_param_nic(void *dummy, QemuOpts *opts, 
Error **errp)
 memset(ni, 0, sizeof(*ni));
 ni->model = qemu_opt_get_del(opts, "model");
 
+if (!nic_model_help && !g_strcmp0(ni->model, "help")) {
+nic_model_help = g_hash_table_new_full(g_str_hash, g_str_equal,
+   g_free, NULL);
+return 0;
+}
+
 /* Create an ID if the user did not specify one */
 nd_id = g_strdup(qemu_opts_id(opts));
 if (!nd_id) {
-- 
2.43.0




[PULL 42/47] hw/sparc/sun4m: use qemu_find_nic_info()

2024-02-01 Thread David Woodhouse
From: David Woodhouse 

Obtain the MAC address from the NIC configuration if there is one, or
generate one explicitly so that it can be placed in the PROM.

Signed-off-by: David Woodhouse 
Reviewed-by: Thomas Huth 
---
 hw/sparc/sun4m.c | 20 ++--
 1 file changed, 14 insertions(+), 6 deletions(-)

diff --git a/hw/sparc/sun4m.c b/hw/sparc/sun4m.c
index 550af01690..e782c8ec7a 100644
--- a/hw/sparc/sun4m.c
+++ b/hw/sparc/sun4m.c
@@ -299,13 +299,15 @@ static void *iommu_init(hwaddr addr, uint32_t version, 
qemu_irq irq)
 
 static void *sparc32_dma_init(hwaddr dma_base,
   hwaddr esp_base, qemu_irq espdma_irq,
-  hwaddr le_base, qemu_irq ledma_irq, NICInfo *nd)
+  hwaddr le_base, qemu_irq ledma_irq,
+  MACAddr *mac)
 {
 DeviceState *dma;
 ESPDMADeviceState *espdma;
 LEDMADeviceState *ledma;
 SysBusESPState *esp;
 SysBusPCNetState *lance;
+NICInfo *nd = qemu_find_nic_info("lance", true, NULL);
 
 dma = qdev_new(TYPE_SPARC32_DMA);
 espdma = SPARC32_ESPDMA_DEVICE(object_resolve_path_component(
@@ -320,7 +322,14 @@ static void *sparc32_dma_init(hwaddr dma_base,
 
 lance = SYSBUS_PCNET(object_resolve_path_component(
  OBJECT(ledma), "lance"));
-qdev_set_nic_properties(DEVICE(lance), nd);
+
+if (nd) {
+qdev_set_nic_properties(DEVICE(lance), nd);
+memcpy(mac->a, nd->macaddr.a, sizeof(mac->a));
+} else {
+qemu_macaddr_default_if_unset(mac);
+qdev_prop_set_macaddr(DEVICE(lance), "mac", mac->a);
+}
 
 sysbus_realize_and_unref(SYS_BUS_DEVICE(dma), _fatal);
 sysbus_mmio_map(SYS_BUS_DEVICE(dma), 0, dma_base);
@@ -823,7 +832,7 @@ static void sun4m_hw_init(MachineState *machine)
 unsigned int smp_cpus = machine->smp.cpus;
 unsigned int max_cpus = machine->smp.max_cpus;
 HostMemoryBackend *ram_memdev = machine->memdev;
-NICInfo *nd = _table[0];
+MACAddr hostid;
 
 if (machine->ram_size > hwdef->max_mem) {
 error_report("Too much memory for this machine: %" PRId64 ","
@@ -884,10 +893,9 @@ static void sun4m_hw_init(MachineState *machine)
 hwdef->iommu_pad_base, hwdef->iommu_pad_len);
 }
 
-qemu_check_nic_model(nd, TYPE_LANCE);
 sparc32_dma_init(hwdef->dma_base,
  hwdef->esp_base, slavio_irq[18],
- hwdef->le_base, slavio_irq[16], nd);
+ hwdef->le_base, slavio_irq[16], );
 
 if (graphic_depth != 8 && graphic_depth != 24) {
 error_report("Unsupported depth: %d", graphic_depth);
@@ -1039,7 +1047,7 @@ static void sun4m_hw_init(MachineState *machine)
 machine->initrd_filename,
 machine->ram_size, _size);
 
-nvram_init(nvram, (uint8_t *)>macaddr, machine->kernel_cmdline,
+nvram_init(nvram, hostid.a, machine->kernel_cmdline,
machine->boot_config.order, machine->ram_size, kernel_size,
graphic_width, graphic_height, graphic_depth,
hwdef->nvram_machine_id, "Sun4m");
-- 
2.43.0




[PULL 46/47] net: remove qemu_show_nic_models(), qemu_find_nic_model()

2024-02-01 Thread David Woodhouse
From: David Woodhouse 

These old functions can be removed now too. Let net_param_nic() print
the full set of network devices directly, and also make it note that a
list more specific to this platform/config will be available by using
'-nic model=help' instead.

Signed-off-by: David Woodhouse 
Reviewed-by: Thomas Huth 
---
 include/net/net.h |  3 ---
 net/net.c | 39 ++-
 2 files changed, 6 insertions(+), 36 deletions(-)

diff --git a/include/net/net.h b/include/net/net.h
index 00ee1af7ab..588ee55f28 100644
--- a/include/net/net.h
+++ b/include/net/net.h
@@ -203,9 +203,6 @@ void qemu_set_vnet_hdr_len(NetClientState *nc, int len);
 int qemu_set_vnet_le(NetClientState *nc, bool is_le);
 int qemu_set_vnet_be(NetClientState *nc, bool is_be);
 void qemu_macaddr_default_if_unset(MACAddr *macaddr);
-int qemu_show_nic_models(const char *arg, const char *const *models);
-int qemu_find_nic_model(NICInfo *nd, const char * const *models,
-const char *default_model);
 /**
  * qemu_find_nic_info: Obtain NIC configuration information
  * @typename: Name of device object type
diff --git a/net/net.c b/net/net.c
index ffd4b42d5a..d705e9b0fd 100644
--- a/net/net.c
+++ b/net/net.c
@@ -977,38 +977,6 @@ GPtrArray *qemu_get_nic_models(const char *device_type)
 return nic_models;
 }
 
-int qemu_show_nic_models(const char *arg, const char *const *models)
-{
-int i;
-
-if (!arg || !is_help_option(arg)) {
-return 0;
-}
-
-printf("Available NIC models:\n");
-for (i = 0 ; models[i]; i++) {
-printf("%s\n", models[i]);
-}
-return 1;
-}
-
-int qemu_find_nic_model(NICInfo *nd, const char * const *models,
-const char *default_model)
-{
-int i;
-
-if (!nd->model)
-nd->model = g_strdup(default_model);
-
-for (i = 0 ; models[i]; i++) {
-if (strcmp(nd->model, models[i]) == 0)
-return i;
-}
-
-error_report("Unsupported NIC model: %s", nd->model);
-return -1;
-}
-
 static int net_init_nic(const Netdev *netdev, const char *name,
 NetClientState *peer, Error **errp)
 {
@@ -1791,9 +1759,14 @@ static int net_param_nic(void *dummy, QemuOpts *opts, 
Error **errp)
 }
 if (is_help_option(type)) {
 GPtrArray *nic_models = qemu_get_nic_models(TYPE_DEVICE);
+int i;
 show_netdevs();
 printf("\n");
-qemu_show_nic_models(type, (const char **)nic_models->pdata);
+printf("Available NIC models "
+   "(use -nic model=help for a filtered list):\n");
+for (i = 0 ; nic_models->pdata[i]; i++) {
+printf("%s\n", (char *)nic_models->pdata[i]);
+}
 g_ptr_array_free(nic_models, true);
 exit(0);
 }
-- 
2.43.0




[PULL 22/47] hw/arm/aspeed: use qemu_configure_nic_device()

2024-02-01 Thread David Woodhouse
From: David Woodhouse 

Signed-off-by: David Woodhouse 
Acked-by: Cédric Le Goater 
Reviewed-by: Cédric Le Goater 
---
 hw/arm/aspeed.c | 9 -
 1 file changed, 4 insertions(+), 5 deletions(-)

diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c
index cc59176563..bed5e4f40b 100644
--- a/hw/arm/aspeed.c
+++ b/hw/arm/aspeed.c
@@ -356,7 +356,6 @@ static void aspeed_machine_init(MachineState *machine)
 AspeedMachineClass *amc = ASPEED_MACHINE_GET_CLASS(machine);
 AspeedSoCClass *sc;
 int i;
-NICInfo *nd = _table[0];
 
 bmc->soc = ASPEED_SOC(object_new(amc->soc_name));
 object_property_add_child(OBJECT(machine), "soc", OBJECT(bmc->soc));
@@ -371,10 +370,10 @@ static void aspeed_machine_init(MachineState *machine)
  _fatal);
 
 for (i = 0; i < sc->macs_num; i++) {
-if ((amc->macs_mask & (1 << i)) && nd->used) {
-qemu_check_nic_model(nd, TYPE_FTGMAC100);
-qdev_set_nic_properties(DEVICE(>soc->ftgmac100[i]), nd);
-nd++;
+if ((amc->macs_mask & (1 << i)) &&
+!qemu_configure_nic_device(DEVICE(>soc->ftgmac100[i]),
+   true, NULL)) {
+break; /* No configs left; stop asking */
 }
 }
 
-- 
2.43.0




[PULL 20/47] hw/xtensa/virt: use pci_init_nic_devices()

2024-02-01 Thread David Woodhouse
From: David Woodhouse 

Signed-off-by: David Woodhouse 
Reviewed-by: Thomas Huth 
---
 hw/xtensa/virt.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/hw/xtensa/virt.c b/hw/xtensa/virt.c
index a6cf646e99..5310a88861 100644
--- a/hw/xtensa/virt.c
+++ b/hw/xtensa/virt.c
@@ -102,9 +102,7 @@ static void create_pcie(MachineState *ms, CPUXtensaState 
*env, int irq_base,
 
 pci = PCI_HOST_BRIDGE(dev);
 if (pci->bus) {
-for (i = 0; i < nb_nics; i++) {
-pci_nic_init_nofail(_table[i], pci->bus, mc->default_nic, NULL);
-}
+pci_init_nic_devices(pci->bus, mc->default_nic);
 }
 }
 
-- 
2.43.0




[PULL 28/47] hw/arm/npcm7xx: use qemu_configure_nic_device, allow emc0/emc1 as aliases

2024-02-01 Thread David Woodhouse
From: David Woodhouse 

Also update the test to specify which device to attach the test socket
to, and remove the comment lamenting the fact that we can't do so.

Signed-off-by: David Woodhouse 
Reviewed-by: Thomas Huth 
---
 hw/arm/npcm7xx.c   | 16 +---
 tests/qtest/npcm7xx_emc-test.c | 18 --
 2 files changed, 13 insertions(+), 21 deletions(-)

diff --git a/hw/arm/npcm7xx.c b/hw/arm/npcm7xx.c
index e3243a520d..bdc609b5fb 100644
--- a/hw/arm/npcm7xx.c
+++ b/hw/arm/npcm7xx.c
@@ -656,8 +656,9 @@ static void npcm7xx_realize(DeviceState *dev, Error **errp)
 
 /*
  * EMC Modules. Cannot fail.
- * The mapping of the device to its netdev backend works as follows:
- * emc[i] = nd_table[i]
+ * Use the available NIC configurations in order, allowing 'emc0' and
+ * 'emc1' to by used as aliases for the model= parameter to override.
+ *
  * This works around the inability to specify the netdev property for the
  * emc device: it's not pluggable and thus the -device option can't be
  * used.
@@ -665,12 +666,13 @@ static void npcm7xx_realize(DeviceState *dev, Error 
**errp)
 QEMU_BUILD_BUG_ON(ARRAY_SIZE(npcm7xx_emc_addr) != ARRAY_SIZE(s->emc));
 QEMU_BUILD_BUG_ON(ARRAY_SIZE(s->emc) != 2);
 for (i = 0; i < ARRAY_SIZE(s->emc); i++) {
-s->emc[i].emc_num = i;
 SysBusDevice *sbd = SYS_BUS_DEVICE(>emc[i]);
-if (nd_table[i].used) {
-qemu_check_nic_model(_table[i], TYPE_NPCM7XX_EMC);
-qdev_set_nic_properties(DEVICE(sbd), _table[i]);
-}
+char alias[6];
+
+s->emc[i].emc_num = i;
+snprintf(alias, sizeof(alias), "emc%u", i);
+qemu_configure_nic_device(DEVICE(sbd), true, alias);
+
 /*
  * The device exists regardless of whether it's connected to a QEMU
  * netdev backend. So always instantiate it even if there is no
diff --git a/tests/qtest/npcm7xx_emc-test.c b/tests/qtest/npcm7xx_emc-test.c
index b046f1d76a..f7646fae2c 100644
--- a/tests/qtest/npcm7xx_emc-test.c
+++ b/tests/qtest/npcm7xx_emc-test.c
@@ -225,21 +225,11 @@ static int *packet_test_init(int module_num, GString 
*cmd_line)
 g_assert_cmpint(ret, != , -1);
 
 /*
- * KISS and use -nic. We specify two nics (both emc{0,1}) because there's
- * currently no way to specify only emc1: The driver implicitly relies on
- * emc[i] == nd_table[i].
+ * KISS and use -nic. The driver accepts 'emc0' and 'emc1' as aliases
+ * in the 'model' field to specify the device to match.
  */
-if (module_num == 0) {
-g_string_append_printf(cmd_line,
-   " -nic socket,fd=%d,model=" TYPE_NPCM7XX_EMC " "
-   " -nic user,model=" TYPE_NPCM7XX_EMC " ",
-   test_sockets[1]);
-} else {
-g_string_append_printf(cmd_line,
-   " -nic user,model=" TYPE_NPCM7XX_EMC " "
-   " -nic socket,fd=%d,model=" TYPE_NPCM7XX_EMC " 
",
-   test_sockets[1]);
-}
+g_string_append_printf(cmd_line, " -nic socket,fd=%d,model=emc%d ",
+   test_sockets[1], module_num);
 
 g_test_queue_destroy(packet_test_clear, test_sockets);
 return test_sockets;
-- 
2.43.0




[PULL 31/47] hw/net/etraxfs-eth: use qemu_configure_nic_device()

2024-02-01 Thread David Woodhouse
From: David Woodhouse 

Signed-off-by: David Woodhouse 
Reviewed-by: Thomas Huth 
---
 hw/cris/axis_dev88.c  | 9 -
 hw/net/etraxfs_eth.c  | 5 ++---
 include/hw/cris/etraxfs.h | 2 +-
 3 files changed, 7 insertions(+), 9 deletions(-)

diff --git a/hw/cris/axis_dev88.c b/hw/cris/axis_dev88.c
index d82050d927..5556634921 100644
--- a/hw/cris/axis_dev88.c
+++ b/hw/cris/axis_dev88.c
@@ -308,15 +308,14 @@ void axisdev88_init(MachineState *machine)
 
 /* Add the two ethernet blocks.  */
 dma_eth = g_malloc0(sizeof dma_eth[0] * 4); /* Allocate 4 channels.  */
-etraxfs_eth_init(_table[0], 0x30034000, 1, _eth[0], _eth[1]);
-if (nb_nics > 1) {
-etraxfs_eth_init(_table[1], 0x30036000, 2, _eth[2], 
_eth[3]);
-}
 
+etraxfs_eth_init(0x30034000, 1, _eth[0], _eth[1]);
 /* The DMA Connector block is missing, hardwire things for now.  */
 etraxfs_dmac_connect_client(etraxfs_dmac, 0, _eth[0]);
 etraxfs_dmac_connect_client(etraxfs_dmac, 1, _eth[1]);
-if (nb_nics > 1) {
+
+if (qemu_find_nic_info("etraxfs-eth", true, "fseth")) {
+etraxfs_eth_init(0x30036000, 2, _eth[2], _eth[3]);
 etraxfs_dmac_connect_client(etraxfs_dmac, 6, _eth[2]);
 etraxfs_dmac_connect_client(etraxfs_dmac, 7, _eth[3]);
 }
diff --git a/hw/net/etraxfs_eth.c b/hw/net/etraxfs_eth.c
index ba57a978d1..5faf20c782 100644
--- a/hw/net/etraxfs_eth.c
+++ b/hw/net/etraxfs_eth.c
@@ -647,15 +647,14 @@ static void etraxfs_eth_class_init(ObjectClass *klass, 
void *data)
 
 /* Instantiate an ETRAXFS Ethernet MAC.  */
 DeviceState *
-etraxfs_eth_init(NICInfo *nd, hwaddr base, int phyaddr,
+etraxfs_eth_init(hwaddr base, int phyaddr,
  struct etraxfs_dma_client *dma_out,
  struct etraxfs_dma_client *dma_in)
 {
 DeviceState *dev;
-qemu_check_nic_model(nd, "fseth");
 
 dev = qdev_new("etraxfs-eth");
-qdev_set_nic_properties(dev, nd);
+qemu_configure_nic_device(dev, true, "fseth");
 qdev_prop_set_uint32(dev, "phyaddr", phyaddr);
 
 /*
diff --git a/include/hw/cris/etraxfs.h b/include/hw/cris/etraxfs.h
index 467b529dc0..012c4e9974 100644
--- a/include/hw/cris/etraxfs.h
+++ b/include/hw/cris/etraxfs.h
@@ -31,7 +31,7 @@
 #include "hw/sysbus.h"
 #include "qapi/error.h"
 
-DeviceState *etraxfs_eth_init(NICInfo *nd, hwaddr base, int phyaddr,
+DeviceState *etraxfs_eth_init(hwaddr base, int phyaddr,
   struct etraxfs_dma_client *dma_out,
   struct etraxfs_dma_client *dma_in);
 
-- 
2.43.0




[PULL 16/47] hw/ppc/spapr: use qemu_get_nic_info() and pci_init_nic_devices()

2024-02-01 Thread David Woodhouse
From: David Woodhouse 

Avoid directly referencing nd_table[] by first instantiating any
spapr-vlan devices using a qemu_get_nic_info() loop, then calling
pci_init_nic_devices() to do the rest.

No functional change intended.

Signed-off-by: David Woodhouse 
Reviewed-by: Thomas Huth 
---
 hw/ppc/spapr.c | 18 +-
 1 file changed, 5 insertions(+), 13 deletions(-)

diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index e8dabc8614..0d72d286d8 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -2796,6 +2796,7 @@ static void spapr_machine_init(MachineState *machine)
 MemoryRegion *sysmem = get_system_memory();
 long load_limit, fw_size;
 Error *resize_hpt_err = NULL;
+NICInfo *nd;
 
 if (!filename) {
 error_report("Could not find LPAR firmware '%s'", bios_name);
@@ -2996,21 +2997,12 @@ static void spapr_machine_init(MachineState *machine)
 
 phb = spapr_create_default_phb();
 
-for (i = 0; i < nb_nics; i++) {
-NICInfo *nd = _table[i];
-
-if (!nd->model) {
-nd->model = g_strdup("spapr-vlan");
-}
-
-if (g_str_equal(nd->model, "spapr-vlan") ||
-g_str_equal(nd->model, "ibmveth")) {
-spapr_vlan_create(spapr->vio_bus, nd);
-} else {
-pci_nic_init_nofail(_table[i], phb->bus, nd->model, NULL);
-}
+while ((nd = qemu_find_nic_info("spapr-vlan", true, "ibmveth"))) {
+spapr_vlan_create(spapr->vio_bus, nd);
 }
 
+pci_init_nic_devices(phb->bus, NULL);
+
 for (i = 0; i <= drive_get_max_bus(IF_SCSI); i++) {
 spapr_vscsi_create(spapr->vio_bus);
 }
-- 
2.43.0




[PULL 11/47] hw/loongarch: use pci_init_nic_devices()

2024-02-01 Thread David Woodhouse
From: David Woodhouse 

Signed-off-by: David Woodhouse 
Reviewed-by: Song Gao 
---
 hw/loongarch/virt.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c
index c9a680e61a..0ad7d8c887 100644
--- a/hw/loongarch/virt.c
+++ b/hw/loongarch/virt.c
@@ -504,9 +504,7 @@ static void loongarch_devices_init(DeviceState *pch_pic, 
LoongArchMachineState *
 fdt_add_uart_node(lams);
 
 /* Network init */
-for (i = 0; i < nb_nics; i++) {
-pci_nic_init_nofail(_table[i], pci_bus, mc->default_nic, NULL);
-}
+pci_init_nic_devices(pci_bus, mc->default_nic);
 
 /*
  * There are some invalid guest memory access.
-- 
2.43.0




[PULL 35/47] hw/mips/mipssim: use qemu_create_nic_device()

2024-02-01 Thread David Woodhouse
From: David Woodhouse 

The MIPS SIM platform instantiates its NIC only if a corresponding
configuration exists for it. Use qemu_create_nic_device() function for
that.

Signed-off-by: David Woodhouse 
Reviewed-by: Thomas Huth 
---
 hw/mips/mipssim.c | 13 +++--
 1 file changed, 7 insertions(+), 6 deletions(-)

diff --git a/hw/mips/mipssim.c b/hw/mips/mipssim.c
index 01e323904d..16af31648e 100644
--- a/hw/mips/mipssim.c
+++ b/hw/mips/mipssim.c
@@ -118,13 +118,15 @@ static void main_cpu_reset(void *opaque)
 }
 }
 
-static void mipsnet_init(int base, qemu_irq irq, NICInfo *nd)
+static void mipsnet_init(int base, qemu_irq irq)
 {
 DeviceState *dev;
 SysBusDevice *s;
 
-dev = qdev_new("mipsnet");
-qdev_set_nic_properties(dev, nd);
+dev = qemu_create_nic_device("mipsnet", true, NULL);
+if (!dev) {
+return;
+}
 
 s = SYS_BUS_DEVICE(dev);
 sysbus_realize_and_unref(s, _fatal);
@@ -225,9 +227,8 @@ mips_mipssim_init(MachineState *machine)
   sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 0));
 }
 
-if (nd_table[0].used)
-/* MIPSnet uses the MIPS CPU INT0, which is interrupt 2. */
-mipsnet_init(0x4200, env->irq[2], _table[0]);
+/* MIPSnet uses the MIPS CPU INT0, which is interrupt 2. */
+mipsnet_init(0x4200, env->irq[2]);
 }
 
 static void mips_mipssim_machine_init(MachineClass *mc)
-- 
2.43.0




[PULL 13/47] hw/mips/malta: use pci_init_nic_devices()

2024-02-01 Thread David Woodhouse
From: David Woodhouse 

The Malta board setup code would previously place the first NIC into PCI
slot 11 if was a PCNet card, and the rest (including the first if it was
anything other than a PCNet card) would be dynamically assigned.

Now it will place any PCNet NIC into slot 11, and then anything else will
be dynamically assigned.

Signed-off-by: David Woodhouse 
Reviewed-by: Thomas Huth 
---
 hw/mips/malta.c | 15 +++
 1 file changed, 3 insertions(+), 12 deletions(-)

diff --git a/hw/mips/malta.c b/hw/mips/malta.c
index d22bb1edef..af74008c82 100644
--- a/hw/mips/malta.c
+++ b/hw/mips/malta.c
@@ -612,18 +612,9 @@ static MaltaFPGAState *malta_fpga_init(MemoryRegion 
*address_space,
 /* Network support */
 static void network_init(PCIBus *pci_bus)
 {
-int i;
-
-for (i = 0; i < nb_nics; i++) {
-NICInfo *nd = _table[i];
-const char *default_devaddr = NULL;
-
-if (i == 0 && (!nd->model || strcmp(nd->model, "pcnet") == 0))
-/* The malta board has a PCNet card using PCI SLOT 11 */
-default_devaddr = "0b";
-
-pci_nic_init_nofail(nd, pci_bus, "pcnet", default_devaddr);
-}
+/* The malta board has a PCNet card using PCI SLOT 11 */
+pci_init_nic_in_slot(pci_bus, "pcnet", NULL, "0b");
+pci_init_nic_devices(pci_bus, "pcnet");
 }
 
 static void bl_setup_gt64120_jump_kernel(void **p, uint64_t run_addr,
-- 
2.43.0




[PULL 12/47] hw/mips/fuloong2e: use pci_init_nic_devices()

2024-02-01 Thread David Woodhouse
From: David Woodhouse 

The previous behaviour was: *if* the first NIC specified on the command
line was an RTL8139 (or unspecified model) then it gets assigned to PCI
slot 7, which is where the Fuloong board had an RTL8139. All other
devices (including the first, if it was specified as anything other than
an rtl8319) get dynamically assigned on the bus.

The new behaviour is subtly different: If the first NIC was given a
specific model *other* than rtl8139, and a subsequent NIC was not,
then the rtl8139 (or unspecified) NIC will go to slot 7 and the rest
will be dynamically assigned.

Signed-off-by: David Woodhouse 
Reviewed-by: Thomas Huth 
---
 hw/mips/fuloong2e.c | 16 +++-
 1 file changed, 3 insertions(+), 13 deletions(-)

diff --git a/hw/mips/fuloong2e.c b/hw/mips/fuloong2e.c
index 97b2c8ed8e..a45aac368c 100644
--- a/hw/mips/fuloong2e.c
+++ b/hw/mips/fuloong2e.c
@@ -201,19 +201,9 @@ static void main_cpu_reset(void *opaque)
 /* Network support */
 static void network_init(PCIBus *pci_bus)
 {
-int i;
-
-for (i = 0; i < nb_nics; i++) {
-NICInfo *nd = _table[i];
-const char *default_devaddr = NULL;
-
-if (i == 0 && (!nd->model || strcmp(nd->model, "rtl8139") == 0)) {
-/* The Fuloong board has a RTL8139 card using PCI SLOT 7 */
-default_devaddr = "07";
-}
-
-pci_nic_init_nofail(nd, pci_bus, "rtl8139", default_devaddr);
-}
+/* The Fuloong board has a RTL8139 card using PCI SLOT 7 */
+pci_init_nic_in_slot(pci_bus, "rtl8139", NULL, "07");
+pci_init_nic_devices(pci_bus, "rtl8139");
 }
 
 static void mips_fuloong2e_init(MachineState *machine)
-- 
2.43.0




[PULL 27/47] hw/arm/highbank: use qemu_create_nic_device()

2024-02-01 Thread David Woodhouse
From: David Woodhouse 

Signed-off-by: David Woodhouse 
Reviewed-by: Thomas Huth 
---
 hw/arm/highbank.c | 12 +---
 1 file changed, 5 insertions(+), 7 deletions(-)

diff --git a/hw/arm/highbank.c b/hw/arm/highbank.c
index e6e27d69af..e12374766e 100644
--- a/hw/arm/highbank.c
+++ b/hw/arm/highbank.c
@@ -297,19 +297,17 @@ static void calxeda_init(MachineState *machine, enum 
cxmachines machine_id)
 
 sysbus_create_simple(TYPE_SYSBUS_AHCI, 0xffe08000, pic[83]);
 
-if (nd_table[0].used) {
-qemu_check_nic_model(_table[0], "xgmac");
-dev = qdev_new("xgmac");
-qdev_set_nic_properties(dev, _table[0]);
+dev = qemu_create_nic_device("xgmac", true, NULL);
+if (dev) {
 sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), _fatal);
 sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, 0xfff5);
 sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, pic[77]);
 sysbus_connect_irq(SYS_BUS_DEVICE(dev), 1, pic[78]);
 sysbus_connect_irq(SYS_BUS_DEVICE(dev), 2, pic[79]);
+}
 
-qemu_check_nic_model(_table[1], "xgmac");
-dev = qdev_new("xgmac");
-qdev_set_nic_properties(dev, _table[1]);
+dev = qemu_create_nic_device("xgmac", true, NULL);
+if (dev) {
 sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), _fatal);
 sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, 0xfff51000);
 sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, pic[80]);
-- 
2.43.0




[PULL 03/47] net: add qemu_create_nic_bus_devices()

2024-02-01 Thread David Woodhouse
From: David Woodhouse 

This will instantiate any NICs which live on a given bus type. Each bus
is allowed *one* substitution (for PCI it's virtio → virtio-net-pci, for
Xen it's xen → xen-net-device; no point in overengineering it unless we
actually want more).

Signed-off-by: David Woodhouse 
Reviewed-by: Paul Durrant 
Reviewed-by: Thomas Huth 
---
 include/net/net.h | 22 
 net/net.c | 53 +++
 2 files changed, 75 insertions(+)

diff --git a/include/net/net.h b/include/net/net.h
index dff1872b4d..728ca965af 100644
--- a/include/net/net.h
+++ b/include/net/net.h
@@ -248,6 +248,28 @@ bool qemu_configure_nic_device(DeviceState *dev, bool 
match_default,
  */
 DeviceState *qemu_create_nic_device(const char *typename, bool match_default,
 const char *alias);
+
+/*
+ * qemu_create_nic_bus_devices: Create configured NIC devices for a given bus
+ * @bus: Bus on which to create devices
+ * @parent_type: Object type for devices to be created (e.g. TYPE_PCI_DEVICE)
+ * @default_model: Object type name for default NIC model (or %NULL)
+ * @alias: Additional model string to replace, for user convenience
+ * @alias_target: Actual object type name to be used in place of @alias
+ *
+ * Instantiate dynamic NICs on a given bus, typically a PCI bus. This scans
+ * for available NIC configurations which either specify a model which is
+ * a child type of @parent_type, or which do not specify a model when
+ * @default_model is non-NULL. Each device is instantiated on the given @bus.
+ *
+ * A single substitution is supported, e.g. "xen" → "xen-net-device" for the
+ * Xen bus, or "virtio" → "virtio-net-pci" for PCI. This allows the user to
+ * specify a more understandable "model=" parameter on the command line, not
+ * only the real object typename.
+ */
+void qemu_create_nic_bus_devices(BusState *bus, const char *parent_type,
+ const char *default_model,
+ const char *alias, const char *alias_target);
 void print_net_client(Monitor *mon, NetClientState *nc);
 void net_socket_rs_init(SocketReadState *rs,
 SocketReadStateFinalize *finalize,
diff --git a/net/net.c b/net/net.c
index 962904eaef..4651b3f443 100644
--- a/net/net.c
+++ b/net/net.c
@@ -1223,6 +1223,59 @@ DeviceState *qemu_create_nic_device(const char 
*typename, bool match_default,
 return dev;
 }
 
+void qemu_create_nic_bus_devices(BusState *bus, const char *parent_type,
+ const char *default_model,
+ const char *alias, const char *alias_target)
+{
+GPtrArray *nic_models = qemu_get_nic_models(parent_type);
+const char *model;
+DeviceState *dev;
+NICInfo *nd;
+int i;
+
+if (nic_model_help) {
+if (alias_target) {
+add_nic_model_help(alias_target, alias);
+}
+for (i = 0; i < nic_models->len - 1; i++) {
+add_nic_model_help(nic_models->pdata[i], NULL);
+}
+}
+
+/* Drop the NULL terminator which would make g_str_equal() unhappy */
+nic_models->len--;
+
+for (i = 0; i < nb_nics; i++) {
+nd = _table[i];
+
+if (!nd->used || nd->instantiated) {
+continue;
+}
+
+model = nd->model ? nd->model : default_model;
+if (!model) {
+continue;
+}
+
+/* Each bus type is allowed *one* substitution */
+if (g_str_equal(model, alias)) {
+model = alias_target;
+}
+
+if (!g_ptr_array_find_with_equal_func(nic_models, model,
+  g_str_equal, NULL)) {
+/* This NIC does not live on this bus. */
+continue;
+}
+
+dev = qdev_new(model);
+qdev_set_nic_properties(dev, nd);
+qdev_realize_and_unref(dev, bus, _fatal);
+}
+
+g_ptr_array_free(nic_models, true);
+}
+
 static int (* const net_client_init_fun[NET_CLIENT_DRIVER__MAX])(
 const Netdev *netdev,
 const char *name,
-- 
2.43.0




[PULL 09/47] hw/arm/virt: use pci_init_nic_devices()

2024-02-01 Thread David Woodhouse
From: David Woodhouse 

Signed-off-by: David Woodhouse 
Reviewed-by: Thomas Huth 
---
 hw/arm/virt.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index e6ead2c5c8..368c2a415a 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -1457,9 +1457,7 @@ static void create_pcie(VirtMachineState *vms)
 pci->bypass_iommu = vms->default_bus_bypass_iommu;
 vms->bus = pci->bus;
 if (vms->bus) {
-for (i = 0; i < nb_nics; i++) {
-pci_nic_init_nofail(_table[i], pci->bus, mc->default_nic, NULL);
-}
+pci_init_nic_devices(pci->bus, mc->default_nic);
 }
 
 nodename = vms->pciehb_nodename = g_strdup_printf("/pcie@%" PRIx64, base);
-- 
2.43.0




[PULL 10/47] hw/hppa: use pci_init_nic_devices()

2024-02-01 Thread David Woodhouse
From: David Woodhouse 

Signed-off-by: David Woodhouse 
Reviewed-by: Thomas Huth 
---
 hw/hppa/machine.c | 7 ++-
 1 file changed, 2 insertions(+), 5 deletions(-)

diff --git a/hw/hppa/machine.c b/hw/hppa/machine.c
index 9e611620cc..a1045b48cc 100644
--- a/hw/hppa/machine.c
+++ b/hw/hppa/machine.c
@@ -342,7 +342,6 @@ static void machine_HP_common_init_tail(MachineState 
*machine, PCIBus *pci_bus,
 uint64_t kernel_entry = 0, kernel_low, kernel_high;
 MemoryRegion *addr_space = get_system_memory();
 MemoryRegion *rom_region;
-long i;
 unsigned int smp_cpus = machine->smp.cpus;
 SysBusDevice *s;
 
@@ -368,10 +367,8 @@ static void machine_HP_common_init_tail(MachineState 
*machine, PCIBus *pci_bus,
 qdev_get_gpio_in(lasi_dev, LASI_IRQ_LAN_HPA));
 }
 
-for (i = 0; i < nb_nics; i++) {
-if (!enable_lasi_lan()) {
-pci_nic_init_nofail(_table[i], pci_bus, mc->default_nic, NULL);
-}
+if (!enable_lasi_lan()) {
+pci_init_nic_devices(pci_bus, mc->default_nic);
 }
 
 /* BMC board: HP Powerbar SP2 Diva (with console only) */
-- 
2.43.0




[PULL 21/47] hw/arm/allwinner: use qemu_configure_nic_device()

2024-02-01 Thread David Woodhouse
From: David Woodhouse 

Signed-off-by: David Woodhouse 
Reviewed-by: Thomas Huth 
---
 hw/arm/allwinner-a10.c |  6 +-
 hw/arm/allwinner-h3.c  |  6 +-
 hw/arm/allwinner-r40.c | 27 ++-
 3 files changed, 4 insertions(+), 35 deletions(-)

diff --git a/hw/arm/allwinner-a10.c b/hw/arm/allwinner-a10.c
index 581dd45edf..57d5d80159 100644
--- a/hw/arm/allwinner-a10.c
+++ b/hw/arm/allwinner-a10.c
@@ -138,11 +138,7 @@ static void aw_a10_realize(DeviceState *dev, Error **errp)
 sysbus_realize(SYS_BUS_DEVICE(>dramc), _fatal);
 sysbus_mmio_map(SYS_BUS_DEVICE(>dramc), 0, AW_A10_DRAMC_BASE);
 
-/* FIXME use qdev NIC properties instead of nd_table[] */
-if (nd_table[0].used) {
-qemu_check_nic_model(_table[0], TYPE_AW_EMAC);
-qdev_set_nic_properties(DEVICE(>emac), _table[0]);
-}
+qemu_configure_nic_device(DEVICE(>emac), true, NULL);
 if (!sysbus_realize(SYS_BUS_DEVICE(>emac), errp)) {
 return;
 }
diff --git a/hw/arm/allwinner-h3.c b/hw/arm/allwinner-h3.c
index 380e0ec11d..6870c3fe96 100644
--- a/hw/arm/allwinner-h3.c
+++ b/hw/arm/allwinner-h3.c
@@ -371,11 +371,7 @@ static void allwinner_h3_realize(DeviceState *dev, Error 
**errp)
   "sd-bus");
 
 /* EMAC */
-/* FIXME use qdev NIC properties instead of nd_table[] */
-if (nd_table[0].used) {
-qemu_check_nic_model(_table[0], TYPE_AW_SUN8I_EMAC);
-qdev_set_nic_properties(DEVICE(>emac), _table[0]);
-}
+qemu_configure_nic_device(DEVICE(>emac), true, NULL);
 object_property_set_link(OBJECT(>emac), "dma-memory",
  OBJECT(get_system_memory()), _fatal);
 sysbus_realize(SYS_BUS_DEVICE(>emac), _fatal);
diff --git a/hw/arm/allwinner-r40.c b/hw/arm/allwinner-r40.c
index eef1fc196e..b8c7202133 100644
--- a/hw/arm/allwinner-r40.c
+++ b/hw/arm/allwinner-r40.c
@@ -318,7 +318,6 @@ static void allwinner_r40_init(Object *obj)
 
 static void allwinner_r40_realize(DeviceState *dev, Error **errp)
 {
-const char *r40_nic_models[] = { "gmac", "emac", NULL };
 AwR40State *s = AW_R40(dev);
 
 /* CPUs */
@@ -512,31 +511,8 @@ static void allwinner_r40_realize(DeviceState *dev, Error 
**errp)
 sysbus_mmio_map(SYS_BUS_DEVICE(>dramc), 2,
 s->memmap[AW_R40_DEV_DRAMPHY]);
 
-/* nic support gmac and emac */
-for (int i = 0; i < ARRAY_SIZE(r40_nic_models) - 1; i++) {
-NICInfo *nic = _table[i];
-
-if (!nic->used) {
-continue;
-}
-if (qemu_show_nic_models(nic->model, r40_nic_models)) {
-exit(0);
-}
-
-switch (qemu_find_nic_model(nic, r40_nic_models, r40_nic_models[0])) {
-case 0: /* gmac */
-qdev_set_nic_properties(DEVICE(>gmac), nic);
-break;
-case 1: /* emac */
-qdev_set_nic_properties(DEVICE(>emac), nic);
-break;
-default:
-exit(1);
-break;
-}
-}
-
 /* GMAC */
+qemu_configure_nic_device(DEVICE(>gmac), true, "gmac");
 object_property_set_link(OBJECT(>gmac), "dma-memory",
  OBJECT(get_system_memory()), 
_fatal);
 sysbus_realize(SYS_BUS_DEVICE(>gmac), _fatal);
@@ -545,6 +521,7 @@ static void allwinner_r40_realize(DeviceState *dev, Error 
**errp)
qdev_get_gpio_in(DEVICE(>gic), AW_R40_GIC_SPI_GMAC));
 
 /* EMAC */
+qemu_configure_nic_device(DEVICE(>emac), true, "emac");
 sysbus_realize(SYS_BUS_DEVICE(>emac), _fatal);
 sysbus_mmio_map(SYS_BUS_DEVICE(>emac), 0, s->memmap[AW_R40_DEV_EMAC]);
 sysbus_connect_irq(SYS_BUS_DEVICE(>emac), 0,
-- 
2.43.0




[PULL 14/47] hw/mips/loongson3_virt: use pci_init_nic_devices()

2024-02-01 Thread David Woodhouse
From: David Woodhouse 

Signed-off-by: David Woodhouse 
Reviewed-by: Thomas Huth 
---
 hw/mips/loongson3_virt.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/hw/mips/loongson3_virt.c b/hw/mips/loongson3_virt.c
index 33eae01eca..caedde2df0 100644
--- a/hw/mips/loongson3_virt.c
+++ b/hw/mips/loongson3_virt.c
@@ -451,9 +451,7 @@ static inline void loongson3_virt_devices_init(MachineState 
*machine,
 usb_create_simple(usb_bus_find(-1), "usb-tablet");
 }
 
-for (i = 0; i < nb_nics; i++) {
-pci_nic_init_nofail(_table[i], pci_bus, mc->default_nic, NULL);
-}
+pci_init_nic_devices(pci_bus, mc->default_nic);
 }
 
 static void mips_loongson3_virt_init(MachineState *machine)
-- 
2.43.0




[PULL 44/47] net: remove qemu_check_nic_model()

2024-02-01 Thread David Woodhouse
From: David Woodhouse 

There are no callers of this function any more, as they have all been
converted to qemu_{create,configure}_nic_device().

Signed-off-by: David Woodhouse 
Reviewed-by: Thomas Huth 
---
 include/net/net.h |  1 -
 net/net.c | 13 -
 2 files changed, 14 deletions(-)

diff --git a/include/net/net.h b/include/net/net.h
index 728ca965af..00ee1af7ab 100644
--- a/include/net/net.h
+++ b/include/net/net.h
@@ -204,7 +204,6 @@ int qemu_set_vnet_le(NetClientState *nc, bool is_le);
 int qemu_set_vnet_be(NetClientState *nc, bool is_be);
 void qemu_macaddr_default_if_unset(MACAddr *macaddr);
 int qemu_show_nic_models(const char *arg, const char *const *models);
-void qemu_check_nic_model(NICInfo *nd, const char *model);
 int qemu_find_nic_model(NICInfo *nd, const char * const *models,
 const char *default_model);
 /**
diff --git a/net/net.c b/net/net.c
index 4651b3f443..ffd4b42d5a 100644
--- a/net/net.c
+++ b/net/net.c
@@ -992,19 +992,6 @@ int qemu_show_nic_models(const char *arg, const char 
*const *models)
 return 1;
 }
 
-void qemu_check_nic_model(NICInfo *nd, const char *model)
-{
-const char *models[2];
-
-models[0] = model;
-models[1] = NULL;
-
-if (qemu_show_nic_models(nd->model, models))
-exit(0);
-if (qemu_find_nic_model(nd, models, model) < 0)
-exit(1);
-}
-
 int qemu_find_nic_model(NICInfo *nd, const char * const *models,
 const char *default_model)
 {
-- 
2.43.0




[PULL 30/47] hw/arm: use qemu_configure_nic_device()

2024-02-01 Thread David Woodhouse
From: David Woodhouse 

Signed-off-by: David Woodhouse 
Reviewed-by: Thomas Huth 
---
 hw/arm/mps2-tz.c |  8 ++--
 hw/arm/msf2-soc.c|  6 +-
 hw/arm/musicpal.c|  3 +--
 hw/arm/xilinx_zynq.c | 11 ---
 hw/arm/xlnx-versal.c |  7 +--
 hw/arm/xlnx-zynqmp.c |  8 +---
 6 files changed, 10 insertions(+), 33 deletions(-)

diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
index 5d8cdc1a4c..a2d18afd79 100644
--- a/hw/arm/mps2-tz.c
+++ b/hw/arm/mps2-tz.c
@@ -503,14 +503,12 @@ static MemoryRegion *make_eth_dev(MPS2TZMachineState 
*mms, void *opaque,
   const PPCExtraData *extradata)
 {
 SysBusDevice *s;
-NICInfo *nd = _table[0];
 
 /* In hardware this is a LAN9220; the LAN9118 is software compatible
  * except that it doesn't support the checksum-offload feature.
  */
-qemu_check_nic_model(nd, "lan9118");
 mms->lan9118 = qdev_new(TYPE_LAN9118);
-qdev_set_nic_properties(mms->lan9118, nd);
+qemu_configure_nic_device(mms->lan9118, true, NULL);
 
 s = SYS_BUS_DEVICE(mms->lan9118);
 sysbus_realize_and_unref(s, _fatal);
@@ -528,7 +526,6 @@ static MemoryRegion *make_eth_usb(MPS2TZMachineState *mms, 
void *opaque,
  * irqs[] is the ethernet IRQ.
  */
 SysBusDevice *s;
-NICInfo *nd = _table[0];
 
 memory_region_init(>eth_usb_container, OBJECT(mms),
"mps2-tz-eth-usb-container", 0x20);
@@ -537,9 +534,8 @@ static MemoryRegion *make_eth_usb(MPS2TZMachineState *mms, 
void *opaque,
  * In hardware this is a LAN9220; the LAN9118 is software compatible
  * except that it doesn't support the checksum-offload feature.
  */
-qemu_check_nic_model(nd, "lan9118");
 mms->lan9118 = qdev_new(TYPE_LAN9118);
-qdev_set_nic_properties(mms->lan9118, nd);
+qemu_configure_nic_device(mms->lan9118, true, NULL);
 
 s = SYS_BUS_DEVICE(mms->lan9118);
 sysbus_realize_and_unref(s, _fatal);
diff --git a/hw/arm/msf2-soc.c b/hw/arm/msf2-soc.c
index b5fe9f364d..35bf1d64e1 100644
--- a/hw/arm/msf2-soc.c
+++ b/hw/arm/msf2-soc.c
@@ -197,12 +197,8 @@ static void m2sxxx_soc_realize(DeviceState *dev_soc, Error 
**errp)
 g_free(bus_name);
 }
 
-/* FIXME use qdev NIC properties instead of nd_table[] */
-if (nd_table[0].used) {
-qemu_check_nic_model(_table[0], TYPE_MSS_EMAC);
-qdev_set_nic_properties(DEVICE(>emac), _table[0]);
-}
 dev = DEVICE(>emac);
+qemu_configure_nic_device(dev, true, NULL);
 object_property_set_link(OBJECT(>emac), "ahb-bus",
  OBJECT(get_system_memory()), _abort);
 if (!sysbus_realize(SYS_BUS_DEVICE(>emac), errp)) {
diff --git a/hw/arm/musicpal.c b/hw/arm/musicpal.c
index 0fe0160b48..2020f73a57 100644
--- a/hw/arm/musicpal.c
+++ b/hw/arm/musicpal.c
@@ -1277,9 +1277,8 @@ static void musicpal_init(MachineState *machine)
 }
 sysbus_create_simple(TYPE_MV88W8618_FLASHCFG, MP_FLASHCFG_BASE, NULL);
 
-qemu_check_nic_model(_table[0], "mv88w8618");
 dev = qdev_new(TYPE_MV88W8618_ETH);
-qdev_set_nic_properties(dev, _table[0]);
+qemu_configure_nic_device(dev, true, "mv88w8618");
 object_property_set_link(OBJECT(dev), "dma-memory",
  OBJECT(get_system_memory()), _fatal);
 sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), _fatal);
diff --git a/hw/arm/xilinx_zynq.c b/hw/arm/xilinx_zynq.c
index 66d0de139f..35fa804b7d 100644
--- a/hw/arm/xilinx_zynq.c
+++ b/hw/arm/xilinx_zynq.c
@@ -109,16 +109,13 @@ static void zynq_write_board_setup(ARMCPU *cpu,
 
 static struct arm_boot_info zynq_binfo = {};
 
-static void gem_init(NICInfo *nd, uint32_t base, qemu_irq irq)
+static void gem_init(uint32_t base, qemu_irq irq)
 {
 DeviceState *dev;
 SysBusDevice *s;
 
 dev = qdev_new(TYPE_CADENCE_GEM);
-if (nd->used) {
-qemu_check_nic_model(nd, TYPE_CADENCE_GEM);
-qdev_set_nic_properties(dev, nd);
-}
+qemu_configure_nic_device(dev, true, NULL);
 object_property_set_int(OBJECT(dev), "phy-addr", 7, _abort);
 s = SYS_BUS_DEVICE(dev);
 sysbus_realize_and_unref(s, _fatal);
@@ -280,8 +277,8 @@ static void zynq_init(MachineState *machine)
 sysbus_create_varargs("cadence_ttc", 0xF8002000,
 pic[69-IRQ_OFFSET], pic[70-IRQ_OFFSET], pic[71-IRQ_OFFSET], NULL);
 
-gem_init(_table[0], 0xE000B000, pic[54-IRQ_OFFSET]);
-gem_init(_table[1], 0xE000C000, pic[77-IRQ_OFFSET]);
+gem_init(0xE000B000, pic[54 - IRQ_OFFSET]);
+gem_init(0xE000C000, pic[77 - IRQ_OFFSET]);
 
 for (n = 0; n < 2; n++) {
 int hci_irq = n ? 79 : 56;
diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c
index 2798df3730..50cb0606cb 100644
--- a/hw/arm/xlnx-versal.c
+++ b/hw/arm/xlnx-versal.c
@@ -256,18 +256,13 @@ static void versal_create_gems(Versal *s, qemu_irq *pic)

[PULL 19/47] hw/sparc64/sun4u: use pci_init_nic_devices()

2024-02-01 Thread David Woodhouse
From: David Woodhouse 

The first sunhme NIC gets placed a function 1 on slot 1 of PCI bus A,
and the rest are dynamically assigned on PCI bus B.

Previously, any PCI NIC would get the special treatment purely by
virtue of being first in the list.

Signed-off-by: David Woodhouse 
Reviewed-by: Thomas Huth 
---
 hw/sparc64/sun4u.c | 27 ---
 1 file changed, 8 insertions(+), 19 deletions(-)

diff --git a/hw/sparc64/sun4u.c b/hw/sparc64/sun4u.c
index 24d53bf5fd..eda9b58a21 100644
--- a/hw/sparc64/sun4u.c
+++ b/hw/sparc64/sun4u.c
@@ -639,29 +639,18 @@ static void sun4uv_init(MemoryRegion *address_space_mem,
 
 memset(, 0, sizeof(MACAddr));
 onboard_nic = false;
-for (i = 0; i < nb_nics; i++) {
-PCIBus *bus;
-nd = _table[i];
-
-if (!nd->model || strcmp(nd->model, mc->default_nic) == 0) {
-if (!onboard_nic) {
-pci_dev = pci_new_multifunction(PCI_DEVFN(1, 1), 
mc->default_nic);
-bus = pci_busA;
-memcpy(, >macaddr.a, sizeof(MACAddr));
-onboard_nic = true;
-} else {
-pci_dev = pci_new(-1, mc->default_nic);
-bus = pci_busB;
-}
-} else {
-pci_dev = pci_new(-1, nd->model);
-bus = pci_busB;
-}
 
+nd = qemu_find_nic_info(mc->default_nic, true, NULL);
+if (nd) {
+pci_dev = pci_new_multifunction(PCI_DEVFN(1, 1), mc->default_nic);
 dev = _dev->qdev;
 qdev_set_nic_properties(dev, nd);
-pci_realize_and_unref(pci_dev, bus, _fatal);
+pci_realize_and_unref(pci_dev, pci_busA, _fatal);
+
+memcpy(, >macaddr.a, sizeof(MACAddr));
+onboard_nic = true;
 }
+pci_init_nic_devices(pci_busB, mc->default_nic);
 
 /* If we don't have an onboard NIC, grab a default MAC address so that
  * we have a valid machine id */
-- 
2.43.0




[PULL 29/47] hw/arm/stellaris: use qemu_find_nic_info()

2024-02-01 Thread David Woodhouse
From: David Woodhouse 

Rather than just using qemu_configure_nic_device(), populate the MAC
address in the system-registers device by peeking at the NICInfo before
it's assigned to the device.

Generate the MAC address early, if there is no matching -nic option.
Otherwise the MAC address wouldn't be generated until net_client_init1()
runs.

Signed-off-by: David Woodhouse 
Reviewed-by: Thomas Huth 
---
 hw/arm/stellaris.c | 30 ++
 1 file changed, 22 insertions(+), 8 deletions(-)

diff --git a/hw/arm/stellaris.c b/hw/arm/stellaris.c
index d18b1144af..34c5a86ac2 100644
--- a/hw/arm/stellaris.c
+++ b/hw/arm/stellaris.c
@@ -1028,7 +1028,8 @@ static void stellaris_init(MachineState *ms, 
stellaris_board_info *board)
 DeviceState *ssys_dev;
 int i;
 int j;
-const uint8_t *macaddr;
+NICInfo *nd;
+MACAddr mac;
 
 MemoryRegion *sram = g_new(MemoryRegion, 1);
 MemoryRegion *flash = g_new(MemoryRegion, 1);
@@ -1051,12 +1052,22 @@ static void stellaris_init(MachineState *ms, 
stellaris_board_info *board)
  * need its sysclk output.
  */
 ssys_dev = qdev_new(TYPE_STELLARIS_SYS);
-/* Most devices come preprogrammed with a MAC address in the user data. */
-macaddr = nd_table[0].macaddr.a;
+
+/*
+ * Most devices come preprogrammed with a MAC address in the user data.
+ * Generate a MAC address now, if there isn't a matching -nic for it.
+ */
+nd = qemu_find_nic_info("stellaris_enet", true, "stellaris");
+if (nd) {
+memcpy(mac.a, nd->macaddr.a, sizeof(mac.a));
+} else {
+qemu_macaddr_default_if_unset();
+}
+
 qdev_prop_set_uint32(ssys_dev, "user0",
- macaddr[0] | (macaddr[1] << 8) | (macaddr[2] << 16));
+ mac.a[0] | (mac.a[1] << 8) | (mac.a[2] << 16));
 qdev_prop_set_uint32(ssys_dev, "user1",
- macaddr[3] | (macaddr[4] << 8) | (macaddr[5] << 16));
+ mac.a[3] | (mac.a[4] << 8) | (mac.a[5] << 16));
 qdev_prop_set_uint32(ssys_dev, "did0", board->did0);
 qdev_prop_set_uint32(ssys_dev, "did1", board->did1);
 qdev_prop_set_uint32(ssys_dev, "dc0", board->dc0);
@@ -1269,10 +1280,13 @@ static void stellaris_init(MachineState *ms, 
stellaris_board_info *board)
 if (board->dc4 & (1 << 28)) {
 DeviceState *enet;
 
-qemu_check_nic_model(_table[0], "stellaris");
-
 enet = qdev_new("stellaris_enet");
-qdev_set_nic_properties(enet, _table[0]);
+if (nd) {
+qdev_set_nic_properties(enet, nd);
+} else {
+qdev_prop_set_macaddr(enet, "mac", mac.a);
+}
+
 sysbus_realize_and_unref(SYS_BUS_DEVICE(enet), _fatal);
 sysbus_mmio_map(SYS_BUS_DEVICE(enet), 0, 0x40048000);
 sysbus_connect_irq(SYS_BUS_DEVICE(enet), 0, qdev_get_gpio_in(nvic, 
42));
-- 
2.43.0




[PULL 40/47] hw/riscv: use qemu_configure_nic_device()

2024-02-01 Thread David Woodhouse
From: David Woodhouse 

Signed-off-by: David Woodhouse 
Reviewed-by: Thomas Huth 
---
 hw/riscv/microchip_pfsoc.c | 14 ++
 hw/riscv/sifive_u.c|  7 +--
 2 files changed, 3 insertions(+), 18 deletions(-)

diff --git a/hw/riscv/microchip_pfsoc.c b/hw/riscv/microchip_pfsoc.c
index b775aa8946..7725dfbde5 100644
--- a/hw/riscv/microchip_pfsoc.c
+++ b/hw/riscv/microchip_pfsoc.c
@@ -202,7 +202,6 @@ static void microchip_pfsoc_soc_realize(DeviceState *dev, 
Error **errp)
 MemoryRegion *envm_data = g_new(MemoryRegion, 1);
 MemoryRegion *qspi_xip_mem = g_new(MemoryRegion, 1);
 char *plic_hart_config;
-NICInfo *nd;
 int i;
 
 sysbus_realize(SYS_BUS_DEVICE(>e_cpus), _abort);
@@ -411,17 +410,8 @@ static void microchip_pfsoc_soc_realize(DeviceState *dev, 
Error **errp)
 memmap[MICROCHIP_PFSOC_USB].size);
 
 /* GEMs */
-
-nd = _table[0];
-if (nd->used) {
-qemu_check_nic_model(nd, TYPE_CADENCE_GEM);
-qdev_set_nic_properties(DEVICE(>gem0), nd);
-}
-nd = _table[1];
-if (nd->used) {
-qemu_check_nic_model(nd, TYPE_CADENCE_GEM);
-qdev_set_nic_properties(DEVICE(>gem1), nd);
-}
+qemu_configure_nic_device(DEVICE(>gem0), true, NULL);
+qemu_configure_nic_device(DEVICE(>gem1), true, NULL);
 
 object_property_set_int(OBJECT(>gem0), "revision", GEM_REVISION, errp);
 object_property_set_int(OBJECT(>gem0), "phy-addr", 8, errp);
diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c
index ec76dce6c9..5207ec1fa5 100644
--- a/hw/riscv/sifive_u.c
+++ b/hw/riscv/sifive_u.c
@@ -789,7 +789,6 @@ static void sifive_u_soc_realize(DeviceState *dev, Error 
**errp)
 MemoryRegion *l2lim_mem = g_new(MemoryRegion, 1);
 char *plic_hart_config;
 int i, j;
-NICInfo *nd = _table[0];
 
 qdev_prop_set_uint32(DEVICE(>u_cpus), "num-harts", ms->smp.cpus - 1);
 qdev_prop_set_uint32(DEVICE(>u_cpus), "hartid-base", 1);
@@ -893,11 +892,7 @@ static void sifive_u_soc_realize(DeviceState *dev, Error 
**errp)
 }
 sysbus_mmio_map(SYS_BUS_DEVICE(>otp), 0, memmap[SIFIVE_U_DEV_OTP].base);
 
-/* FIXME use qdev NIC properties instead of nd_table[] */
-if (nd->used) {
-qemu_check_nic_model(nd, TYPE_CADENCE_GEM);
-qdev_set_nic_properties(DEVICE(>gem), nd);
-}
+qemu_configure_nic_device(DEVICE(>gem), true, NULL);
 object_property_set_int(OBJECT(>gem), "revision", GEM_REVISION,
 _abort);
 if (!sysbus_realize(SYS_BUS_DEVICE(>gem), errp)) {
-- 
2.43.0




[PULL 45/47] hw/pci: remove pci_nic_init_nofail()

2024-02-01 Thread David Woodhouse
From: David Woodhouse 

This function is no longer used, as all its callers have been converted
to use pci_init_nic_devices() instead.

Signed-off-by: David Woodhouse 
Reviewed-by: Thomas Huth 
---
 hw/pci/pci.c | 72 
 include/hw/pci/pci.h |  3 --
 2 files changed, 75 deletions(-)

diff --git a/hw/pci/pci.c b/hw/pci/pci.c
index 5849606f66..449abfb182 100644
--- a/hw/pci/pci.c
+++ b/hw/pci/pci.c
@@ -1853,78 +1853,6 @@ const pci_class_desc *get_class_desc(int class)
 return desc;
 }
 
-/* Initialize a PCI NIC.  */
-PCIDevice *pci_nic_init_nofail(NICInfo *nd, PCIBus *rootbus,
-   const char *default_model,
-   const char *default_devaddr)
-{
-const char *devaddr = nd->devaddr ? nd->devaddr : default_devaddr;
-GPtrArray *pci_nic_models;
-PCIBus *bus;
-PCIDevice *pci_dev;
-DeviceState *dev;
-int devfn;
-int i;
-int dom, busnr;
-unsigned slot;
-
-if (nd->model && !strcmp(nd->model, "virtio")) {
-g_free(nd->model);
-nd->model = g_strdup("virtio-net-pci");
-}
-
-pci_nic_models = qemu_get_nic_models(TYPE_PCI_DEVICE);
-
-if (qemu_show_nic_models(nd->model, (const char **)pci_nic_models->pdata)) 
{
-exit(0);
-}
-
-i = qemu_find_nic_model(nd, (const char **)pci_nic_models->pdata,
-default_model);
-if (i < 0) {
-exit(1);
-}
-
-if (!rootbus) {
-error_report("No primary PCI bus");
-exit(1);
-}
-
-assert(!rootbus->parent_dev);
-
-if (!devaddr) {
-devfn = -1;
-busnr = 0;
-} else {
-if (pci_parse_devaddr(devaddr, , , , NULL) < 0) {
-error_report("Invalid PCI device address %s for device %s",
- devaddr, nd->model);
-exit(1);
-}
-
-if (dom != 0) {
-error_report("No support for non-zero PCI domains");
-exit(1);
-}
-
-devfn = PCI_DEVFN(slot, 0);
-}
-
-bus = pci_find_bus_nr(rootbus, busnr);
-if (!bus) {
-error_report("Invalid PCI device address %s for device %s",
- devaddr, nd->model);
-exit(1);
-}
-
-pci_dev = pci_new(devfn, nd->model);
-dev = _dev->qdev;
-qdev_set_nic_properties(dev, nd);
-pci_realize_and_unref(pci_dev, bus, _fatal);
-g_ptr_array_free(pci_nic_models, true);
-return pci_dev;
-}
-
 void pci_init_nic_devices(PCIBus *bus, const char *default_model)
 {
 qemu_create_nic_bus_devices(>qbus, TYPE_PCI_DEVICE, default_model,
diff --git a/include/hw/pci/pci.h b/include/hw/pci/pci.h
index 6ff0b95a02..eaa3fc99d8 100644
--- a/include/hw/pci/pci.h
+++ b/include/hw/pci/pci.h
@@ -314,9 +314,6 @@ void pci_device_set_intx_routing_notifier(PCIDevice *dev,
   PCIINTxRoutingNotifier notifier);
 void pci_device_reset(PCIDevice *dev);
 
-PCIDevice *pci_nic_init_nofail(NICInfo *nd, PCIBus *rootbus,
-   const char *default_model,
-   const char *default_devaddr);
 void pci_init_nic_devices(PCIBus *bus, const char *default_model);
 bool pci_init_nic_in_slot(PCIBus *rootbus, const char *default_model,
   const char *alias, const char *devaddr);
-- 
2.43.0




[PULL 18/47] hw/sh4/r2d: use pci_init_nic_devices()

2024-02-01 Thread David Woodhouse
From: David Woodhouse 

Previously, the first PCI NIC would be assigned to slot 2 even if the
user override the model and made it something other than an rtl8139
which is the default. Everything else would be dynamically assigned.

Now, the first rtl8139 gets slot 2 and everything else is dynamic.

Signed-off-by: David Woodhouse 
Reviewed-by: Yoshinori Sato 
---
 hw/sh4/r2d.c | 6 ++
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/hw/sh4/r2d.c b/hw/sh4/r2d.c
index 4944994e9c..e9f316a6ce 100644
--- a/hw/sh4/r2d.c
+++ b/hw/sh4/r2d.c
@@ -240,7 +240,6 @@ static void r2d_init(MachineState *machine)
 MemoryRegion *sdram = g_new(MemoryRegion, 1);
 qemu_irq *irq;
 DriveInfo *dinfo;
-int i;
 DeviceState *dev;
 SysBusDevice *busdev;
 MemoryRegion *address_space_mem = get_system_memory();
@@ -309,9 +308,8 @@ static void r2d_init(MachineState *machine)
   0x555, 0x2aa, 0);
 
 /* NIC: rtl8139 on-board, and 2 slots. */
-for (i = 0; i < nb_nics; i++)
-pci_nic_init_nofail(_table[i], pci_bus,
-mc->default_nic, i == 0 ? "2" : NULL);
+pci_init_nic_in_slot(pci_bus, mc->default_nic, NULL, "2");
+pci_init_nic_devices(pci_bus, mc->default_nic);
 
 /* USB keyboard */
 usb_create_simple(usb_bus_find(-1), "usb-kbd");
-- 
2.43.0




[PULL 47/47] net: make nb_nics and nd_table[] static in net/net.c

2024-02-01 Thread David Woodhouse
From: David Woodhouse 

Also remove the stale declaration of host_net_devices; the actual
definition was removed long ago in commit 7cc28cb06104 ("net: Remove
the deprecated 'host_net_add' and 'host_net_remove' HMP commands")

Signed-off-by: David Woodhouse 
Reviewed-by: Thomas Huth 
---
 include/net/net.h | 4 
 net/net.c | 3 +++
 system/globals.c  | 2 --
 3 files changed, 3 insertions(+), 6 deletions(-)

diff --git a/include/net/net.h b/include/net/net.h
index 588ee55f28..b1f9b35fcc 100644
--- a/include/net/net.h
+++ b/include/net/net.h
@@ -301,10 +301,6 @@ struct NICInfo {
 int nvectors;
 };
 
-extern int nb_nics;
-extern NICInfo nd_table[MAX_NICS];
-extern const char *host_net_devices[];
-
 /* from net.c */
 extern NetClientStateList net_clients;
 bool netdev_is_modern(const char *optstr);
diff --git a/net/net.c b/net/net.c
index d705e9b0fd..a2f0c828bb 100644
--- a/net/net.c
+++ b/net/net.c
@@ -77,6 +77,9 @@ static NetdevQueue nd_queue = 
QSIMPLEQ_HEAD_INITIALIZER(nd_queue);
 
 static GHashTable *nic_model_help;
 
+static int nb_nics;
+static NICInfo nd_table[MAX_NICS];
+
 /***/
 /* network device redirectors */
 
diff --git a/system/globals.c b/system/globals.c
index e83b5428d1..b6d4e72530 100644
--- a/system/globals.c
+++ b/system/globals.c
@@ -36,8 +36,6 @@ int display_opengl;
 const char* keyboard_layout;
 bool enable_mlock;
 bool enable_cpu_pm;
-int nb_nics;
-NICInfo nd_table[MAX_NICS];
 int autostart = 1;
 int vga_interface_type = VGA_NONE;
 bool vga_interface_created;
-- 
2.43.0




[PULL 26/47] hw/net/lan9118: use qemu_configure_nic_device()

2024-02-01 Thread David Woodhouse
From: David Woodhouse 

Some callers instantiate the device unconditionally, others will do so only
if there is a NICInfo to go with it. This appears to be fairly random, but
preseve the existing behaviour for now.

Signed-off-by: David Woodhouse 
Reviewed-by: Thomas Huth 
---
 hw/arm/kzm.c | 4 ++--
 hw/arm/mps2.c| 2 +-
 hw/arm/realview.c| 6 ++
 hw/arm/vexpress.c| 4 ++--
 hw/net/lan9118.c | 5 ++---
 include/hw/net/lan9118.h | 2 +-
 6 files changed, 10 insertions(+), 13 deletions(-)

diff --git a/hw/arm/kzm.c b/hw/arm/kzm.c
index 9be91ebeaa..2ccd6f8a76 100644
--- a/hw/arm/kzm.c
+++ b/hw/arm/kzm.c
@@ -113,8 +113,8 @@ static void kzm_init(MachineState *machine)
 alias_offset += ram[i].size;
 }
 
-if (nd_table[0].used) {
-lan9118_init(_table[0], KZM_LAN9118_ADDR,
+if (qemu_find_nic_info("lan9118", true, NULL)) {
+lan9118_init(KZM_LAN9118_ADDR,
  qdev_get_gpio_in(DEVICE(>soc.avic), 52));
 }
 
diff --git a/hw/arm/mps2.c b/hw/arm/mps2.c
index bd873cc5de..50919ee46d 100644
--- a/hw/arm/mps2.c
+++ b/hw/arm/mps2.c
@@ -456,7 +456,7 @@ static void mps2_common_init(MachineState *machine)
 /* In hardware this is a LAN9220; the LAN9118 is software compatible
  * except that it doesn't support the checksum-offload feature.
  */
-lan9118_init(_table[0], mmc->ethernet_base,
+lan9118_init(mmc->ethernet_base,
  qdev_get_gpio_in(armv7m,
   mmc->fpga_type == FPGA_AN511 ? 47 : 13));
 
diff --git a/hw/arm/realview.c b/hw/arm/realview.c
index c6bd6e5961..9058f5b414 100644
--- a/hw/arm/realview.c
+++ b/hw/arm/realview.c
@@ -85,7 +85,6 @@ static void realview_init(MachineState *machine,
 SysBusDevice *busdev;
 qemu_irq pic[64];
 PCIBus *pci_bus = NULL;
-NICInfo *nd;
 DriveInfo *dinfo;
 I2CBus *i2c;
 int n;
@@ -296,10 +295,9 @@ static void realview_init(MachineState *machine,
 }
 }
 
-nd = qemu_find_nic_info(is_pb ? "lan9118" : "smc91c111", true, NULL);
-if (nd) {
+if (qemu_find_nic_info(is_pb ? "lan9118" : "smc91c111", true, NULL)) {
 if (is_pb) {
-lan9118_init(nd, 0x4e00, pic[28]);
+lan9118_init(0x4e00, pic[28]);
 } else {
 smc91c111_init(0x4e00, pic[28]);
 }
diff --git a/hw/arm/vexpress.c b/hw/arm/vexpress.c
index f1b45245d5..e5fb3ab1f9 100644
--- a/hw/arm/vexpress.c
+++ b/hw/arm/vexpress.c
@@ -679,8 +679,8 @@ static void vexpress_common_init(MachineState *machine)
 memory_region_add_subregion(sysmem, map[VE_VIDEORAM], >vram);
 
 /* 0x4e00 LAN9118 Ethernet */
-if (nd_table[0].used) {
-lan9118_init(_table[0], map[VE_ETHERNET], pic[15]);
+if (qemu_find_nic_info("lan9118", true, NULL)) {
+lan9118_init(map[VE_ETHERNET], pic[15]);
 }
 
 /* VE_USB: not modelled */
diff --git a/hw/net/lan9118.c b/hw/net/lan9118.c
index 598dd79e17..47ff25b441 100644
--- a/hw/net/lan9118.c
+++ b/hw/net/lan9118.c
@@ -1408,14 +1408,13 @@ static void lan9118_register_types(void)
 
 /* Legacy helper function.  Should go away when machine config files are
implemented.  */
-void lan9118_init(NICInfo *nd, uint32_t base, qemu_irq irq)
+void lan9118_init(uint32_t base, qemu_irq irq)
 {
 DeviceState *dev;
 SysBusDevice *s;
 
-qemu_check_nic_model(nd, "lan9118");
 dev = qdev_new(TYPE_LAN9118);
-qdev_set_nic_properties(dev, nd);
+qemu_configure_nic_device(dev, true, NULL);
 s = SYS_BUS_DEVICE(dev);
 sysbus_realize_and_unref(s, _fatal);
 sysbus_mmio_map(s, 0, base);
diff --git a/include/hw/net/lan9118.h b/include/hw/net/lan9118.h
index 3d0c67f339..4bf9da7a63 100644
--- a/include/hw/net/lan9118.h
+++ b/include/hw/net/lan9118.h
@@ -15,6 +15,6 @@
 
 #define TYPE_LAN9118 "lan9118"
 
-void lan9118_init(NICInfo *, uint32_t, qemu_irq);
+void lan9118_init(uint32_t, qemu_irq);
 
 #endif
-- 
2.43.0




[PULL 39/47] hw/openrisc/openrisc_sim: use qemu_create_nic_device()

2024-02-01 Thread David Woodhouse
From: David Woodhouse 

Signed-off-by: David Woodhouse 
Reviewed-by: Thomas Huth 
---
 hw/openrisc/openrisc_sim.c | 18 +-
 1 file changed, 9 insertions(+), 9 deletions(-)

diff --git a/hw/openrisc/openrisc_sim.c b/hw/openrisc/openrisc_sim.c
index 35da123aef..bffd6f721f 100644
--- a/hw/openrisc/openrisc_sim.c
+++ b/hw/openrisc/openrisc_sim.c
@@ -170,7 +170,7 @@ static void openrisc_create_fdt(Or1ksimState *state,
 
 static void openrisc_sim_net_init(Or1ksimState *state, hwaddr base, hwaddr 
size,
   int num_cpus, OpenRISCCPU *cpus[],
-  int irq_pin, NICInfo *nd)
+  int irq_pin)
 {
 void *fdt = state->fdt;
 DeviceState *dev;
@@ -178,8 +178,10 @@ static void openrisc_sim_net_init(Or1ksimState *state, 
hwaddr base, hwaddr size,
 char *nodename;
 int i;
 
-dev = qdev_new("open_eth");
-qdev_set_nic_properties(dev, nd);
+dev = qemu_create_nic_device("open_eth", true, NULL);
+if (!dev) {
+return;
+}
 
 s = SYS_BUS_DEVICE(dev);
 sysbus_realize_and_unref(s, _fatal);
@@ -313,12 +315,10 @@ static void openrisc_sim_init(MachineState *machine)
 openrisc_create_fdt(state, or1ksim_memmap, smp_cpus, machine->ram_size,
 machine->kernel_cmdline);
 
-if (nd_table[0].used) {
-openrisc_sim_net_init(state, or1ksim_memmap[OR1KSIM_ETHOC].base,
-  or1ksim_memmap[OR1KSIM_ETHOC].size,
-  smp_cpus, cpus,
-  OR1KSIM_ETHOC_IRQ, nd_table);
-}
+openrisc_sim_net_init(state, or1ksim_memmap[OR1KSIM_ETHOC].base,
+  or1ksim_memmap[OR1KSIM_ETHOC].size,
+  smp_cpus, cpus,
+  OR1KSIM_ETHOC_IRQ);
 
 if (smp_cpus > 1) {
 openrisc_sim_ompic_init(state, or1ksim_memmap[OR1KSIM_OMPIC].base,
-- 
2.43.0




[PULL 06/47] hw/xen: use qemu_create_nic_bus_devices() to instantiate Xen NICs

2024-02-01 Thread David Woodhouse
From: David Woodhouse 

When instantiating XenBus itself, for each NIC which is configured with
either the model unspecified, or set to to "xen" or "xen-net-device",
create a corresponding xen-net-device for it.

Now we can revert the previous more hackish version which relied on the
platform code explicitly registering the NICs on its own XenBus, having
returned the BusState* from xen_bus_init() itself.

This also fixes the setup for Xen PV guests, which was previously broken
in various ways and never actually managed to peer with the netdev.

Signed-off-by: David Woodhouse 
Reviewed-by: Paul Durrant 
---
 hw/i386/pc.c| 13 ++---
 hw/i386/pc_piix.c   |  2 +-
 hw/i386/pc_q35.c|  2 +-
 hw/xen/xen-bus.c|  6 --
 hw/xen/xen_devconfig.c  | 25 -
 hw/xenpv/xen_machine_pv.c   |  9 -
 include/hw/i386/pc.h|  4 +---
 include/hw/xen/xen-bus.h|  2 +-
 include/hw/xen/xen-legacy-backend.h |  1 -
 9 files changed, 10 insertions(+), 54 deletions(-)

diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index ebb0b1c667..196827531a 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -1269,7 +1269,7 @@ void pc_basic_device_init(struct PCMachineState *pcms,
 if (pcms->bus) {
 pci_create_simple(pcms->bus, -1, "xen-platform");
 }
-pcms->xenbus = xen_bus_init();
+xen_bus_init();
 xen_be_init();
 }
 #endif
@@ -1297,8 +1297,7 @@ void pc_basic_device_init(struct PCMachineState *pcms,
 pcms->vmport != ON_OFF_AUTO_ON);
 }
 
-void pc_nic_init(PCMachineClass *pcmc, ISABus *isa_bus, PCIBus *pci_bus,
- BusState *xen_bus)
+void pc_nic_init(PCMachineClass *pcmc, ISABus *isa_bus, PCIBus *pci_bus)
 {
 MachineClass *mc = MACHINE_CLASS(pcmc);
 bool default_is_ne2k = g_str_equal(mc->default_nic, TYPE_ISA_NE2000);
@@ -1306,14 +1305,6 @@ void pc_nic_init(PCMachineClass *pcmc, ISABus *isa_bus, 
PCIBus *pci_bus,
 
 rom_set_order_override(FW_CFG_ORDER_OVERRIDE_NIC);
 
-if (xen_bus) {
-while ((nd = qemu_find_nic_info("xen-net-device", true, NULL))) {
-DeviceState *dev = qdev_new("xen-net-device");
-qdev_set_nic_properties(dev, nd);
-qdev_realize_and_unref(dev, xen_bus, _fatal);
-}
-}
-
 while ((nd = qemu_find_nic_info(TYPE_ISA_NE2000, default_is_ne2k, NULL))) {
 pc_init_ne2k_isa(isa_bus, nd, _fatal);
 }
diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c
index abfcfe4d2b..70d12bb1b5 100644
--- a/hw/i386/pc_piix.c
+++ b/hw/i386/pc_piix.c
@@ -339,7 +339,7 @@ static void pc_init1(MachineState *machine,
 pc_basic_device_init(pcms, isa_bus, x86ms->gsi, rtc_state, true,
  0x4);
 
-pc_nic_init(pcmc, isa_bus, pci_bus, pcms->xenbus);
+pc_nic_init(pcmc, isa_bus, pci_bus);
 
 if (pcmc->pci_enabled) {
 pc_cmos_init(pcms, idebus[0], idebus[1], rtc_state);
diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c
index f43d5142b8..7ca3f465e0 100644
--- a/hw/i386/pc_q35.c
+++ b/hw/i386/pc_q35.c
@@ -340,7 +340,7 @@ static void pc_q35_init(MachineState *machine)
 
 /* the rest devices to which pci devfn is automatically assigned */
 pc_vga_init(isa_bus, host_bus);
-pc_nic_init(pcmc, isa_bus, host_bus, pcms->xenbus);
+pc_nic_init(pcmc, isa_bus, host_bus);
 
 if (machine->nvdimms_state->is_enabled) {
 nvdimm_init_acpi_state(machine->nvdimms_state, system_io,
diff --git a/hw/xen/xen-bus.c b/hw/xen/xen-bus.c
index 4973e7d9c9..fb82cc33e4 100644
--- a/hw/xen/xen-bus.c
+++ b/hw/xen/xen-bus.c
@@ -19,6 +19,7 @@
 #include "qapi/error.h"
 #include "qapi/qmp/qdict.h"
 #include "sysemu/sysemu.h"
+#include "net/net.h"
 #include "trace.h"
 
 static char *xen_device_get_backend_path(XenDevice *xendev)
@@ -1133,7 +1134,7 @@ static void xen_register_types(void)
 
 type_init(xen_register_types)
 
-BusState *xen_bus_init(void)
+void xen_bus_init(void)
 {
 DeviceState *dev = qdev_new(TYPE_XEN_BRIDGE);
 BusState *bus = qbus_new(TYPE_XEN_BUS, dev, NULL);
@@ -1141,5 +1142,6 @@ BusState *xen_bus_init(void)
 sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), _fatal);
 qbus_set_bus_hotplug_handler(bus);
 
-return bus;
+qemu_create_nic_bus_devices(bus, TYPE_XEN_DEVICE, "xen-net-device",
+"xen", "xen-net-device");
 }
diff --git a/hw/xen/xen_devconfig.c b/hw/xen/xen_devconfig.c
index 3f77c675c6..2150869f60 100644
--- a/hw/xen/xen_devconfig.c
+++ b/hw/xen/xen_devconfig.c
@@ -46,31 +46,6 @@ static int xen_config_dev_all(char *fe, char *be)
 
 /* - */
 
-int xen_config_dev_nic(NICInfo *nic)
-{
-char fe[256], be[256];
-c

[PULL 23/47] hw/arm/exynos4: use qemu_create_nic_device()

2024-02-01 Thread David Woodhouse
From: David Woodhouse 

Signed-off-by: David Woodhouse 
Reviewed-by: Thomas Huth 
---
 hw/arm/exynos4_boards.c | 6 ++
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/hw/arm/exynos4_boards.c b/hw/arm/exynos4_boards.c
index b0e13eb4f0..003992189b 100644
--- a/hw/arm/exynos4_boards.c
+++ b/hw/arm/exynos4_boards.c
@@ -76,10 +76,8 @@ static void lan9215_init(uint32_t base, qemu_irq irq)
 SysBusDevice *s;
 
 /* This should be a 9215 but the 9118 is close enough */
-if (nd_table[0].used) {
-qemu_check_nic_model(_table[0], "lan9118");
-dev = qdev_new(TYPE_LAN9118);
-qdev_set_nic_properties(dev, _table[0]);
+dev = qemu_create_nic_device(TYPE_LAN9118, true, NULL);
+if (dev) {
 qdev_prop_set_uint32(dev, "mode_16bit", 1);
 s = SYS_BUS_DEVICE(dev);
 sysbus_realize_and_unref(s, _fatal);
-- 
2.43.0




Re: [PATCH v4 33/47] hw/m68k/q800: use qemu_find_nic_info()

2024-02-01 Thread David Woodhouse
On Thu, 2024-02-01 at 11:30 +0100, Thomas Huth wrote:
> On 31/01/2024 15.18, David Woodhouse wrote:
> > On Wed, 2024-01-31 at 13:18 +0100, Thomas Huth wrote:
> > > Don't we have to change nd->macaddr.a[0 to 2] with this hard-coded
> > > MAC-prefix, too?
> > 
> > I don't think so.
> > 
> > We either get the MAC address from 'nd' if that exists, or generate a
> > new MAC address with qemu_macaddr_default_if_unset().
> > 
> > Then we override the OUI in the actual device. We don't care about 'nd'
> > any more at that point.
> 
> I just double-checked, and yes, you're right, so:
> 
> Reviewed-by: Thomas Huth 

Thank you, just just about completes my set. Every patch now has a
Reviewed-by: except two of them (hw/s390x/s390-virtio-ccw and
hw/arm/aspeed) which only have an Acked-by: 

I think according to The Rules I just need a maintainer to *tell* me to
send a pull request and then I'm allowed to do so?


smime.p7s
Description: S/MIME cryptographic signature


Re: [PATCH v4 33/47] hw/m68k/q800: use qemu_find_nic_info()

2024-01-31 Thread David Woodhouse
On Wed, 2024-01-31 at 13:18 +0100, Thomas Huth wrote:
> 
> > @@ -386,14 +382,21 @@ static void q800_machine_init(MachineState
> > *machine)
> >     * 08:00:07 Apple
> >     * (Q800 use the last one)
> >     */
> > -    nd_table[0].macaddr.a[0] = 0x08;
> > -    nd_table[0].macaddr.a[1] = 0x00;
> > -    nd_table[0].macaddr.a[2] = 0x07;
> > -
> >    object_initialize_child(OBJECT(machine), "dp8393x", 
> > >dp8393x,
> >    TYPE_DP8393X);
> >    dev = DEVICE(>dp8393x);
> > -    qdev_set_nic_properties(dev, _table[0]);
> > +    nd = qemu_find_nic_info(TYPE_DP8393X, true, "dp83932");
> > +    if (nd) {
> > +    qdev_set_nic_properties(dev, nd);
> > +    memcpy(mac.a, nd->macaddr.a, sizeof(mac.a));
> > +    } else {
> > +    qemu_macaddr_default_if_unset();
> > +    }
> > +    mac.a[0] = 0x08;
> > +    mac.a[1] = 0x00;
> > +    mac.a[2] = 0x07;
> 
> Don't we have to change nd->macaddr.a[0 to 2] with this hard-coded 
> MAC-prefix, too?

I don't think so.

We either get the MAC address from 'nd' if that exists, or generate a
new MAC address with qemu_macaddr_default_if_unset().

Then we override the OUI in the actual device. We don't care about 'nd'
any more at that point.


smime.p7s
Description: S/MIME cryptographic signature


Re: [PATCH v4 29/47] hw/arm/stellaris: use qemu_find_nic_info()

2024-01-31 Thread David Woodhouse
On Wed, 2024-01-31 at 13:13 +0100, Thomas Huth wrote:
> 
> >    qdev_prop_set_uint32(ssys_dev, "user0",
> > - macaddr[0] | (macaddr[1] << 8) | (macaddr[2] << 
> > 16));
> > + mac.a[0] | (mac.a[1] << 8) | (mac.a[2] << 16));
> >    qdev_prop_set_uint32(ssys_dev, "user1",
> > - macaddr[3] | (macaddr[4] << 8) | (macaddr[5] << 
> > 16));
> > + mac.a[3] | (mac.a[4] << 8) | (mac.a[5] << 16));
> 
> Out of scope of your patch, but I wonder why we didn't use 
> qdev_prop_set_macaddr() with an according MAC address property for this 
> device...?

Yeah. I suppose it could have done. But strictly speaking, it *isn't* a
MAC address on the underlying PROM device; it's just two 32-bit
registers. Which each happen to contain 24 bits of the MAC address.



smime.p7s
Description: S/MIME cryptographic signature


[PATCH v4] doc/sphinx/hxtool.py: add optional label argument to SRST directive

2024-01-30 Thread David Woodhouse
From: David Woodhouse 

We can't just embed labels directly into files like qemu-options.hx which
are included from multiple top-level rST files, because Sphinx sees the
labels as duplicate: https://github.com/sphinx-doc/sphinx/issues/9707

So add an optional argument to the SRST directive which causes a label
of the form '.. _DOCNAME-HXFILE-LABEL:' to be emitted, where 'DOCNAME'
is the name of the top level rST file, 'HXFILE' is the filename of the
.hx file, and 'LABEL' is the text provided within the 'SRST()' directive.
Using the DOCNAME of the top-level rST document means that it is unique
even when the .hx file is included from two different documents, as is
the case for qemu-options.hx

Now where the Xen PV documentation refers to the documentation for the
-initrd command line option, it can emit a link directly to it as
''.

Signed-off-by: David Woodhouse 
Reviewed-by: Paul Durrant 
Reviewed-by: Peter Maydell 
---
v4:
 • Wrap long lines to shut checkpatch up

v3:
 • Include DOCNAME in label
 • Drop emitrefs option which is no longer needed

v2:
 • Invoke parse_srst() unconditionally
 • Change emitted label to include basename of .hx file
 • Describe it in docs/devel/docs.rst


 docs/devel/docs.rst  | 12 ++--
 docs/sphinx/hxtool.py| 16 
 docs/system/i386/xen.rst |  3 ++-
 qemu-options.hx  |  2 +-
 4 files changed, 29 insertions(+), 4 deletions(-)

diff --git a/docs/devel/docs.rst b/docs/devel/docs.rst
index 7da067905b..50ff0d67f8 100644
--- a/docs/devel/docs.rst
+++ b/docs/devel/docs.rst
@@ -30,6 +30,13 @@ nor the documentation output.
 
 ``SRST`` starts a reStructuredText section. Following lines
 are put into the documentation verbatim, and discarded from the C output.
+The alternative form ``SRST()`` is used to define a label which can be
+referenced from elsewhere in the rST documentation. The label will take
+the form , where ``DOCNAME`` is the name of the
+top level rST file, ``HXFILE`` is the filename of the .hx file without
+the ``.hx`` extension, and ``LABEL`` is the text provided within the
+``SRST()`` directive. For example,
+.
 
 ``ERST`` ends the documentation section started with ``SRST``,
 and switches back to a C code section.
@@ -53,8 +60,9 @@ text, but in ``hmp-commands.hx`` the C code sections are 
elements
 of an array of structs of type ``HMPCommand`` which define the
 name, behaviour and help text for each monitor command.
 
-In the file ``qemu-options.hx``, do not try to define a
+In the file ``qemu-options.hx``, do not try to explicitly define a
 reStructuredText label within a documentation section. This file
 is included into two separate Sphinx documents, and some
 versions of Sphinx will complain about the duplicate label
-that results.
+that results. Use the ``SRST()`` directive documented above, to
+emit an unambiguous label.
diff --git a/docs/sphinx/hxtool.py b/docs/sphinx/hxtool.py
index 9f6b9d87dc..3729084a36 100644
--- a/docs/sphinx/hxtool.py
+++ b/docs/sphinx/hxtool.py
@@ -78,6 +78,14 @@ def parse_archheading(file, lnum, line):
 serror(file, lnum, "Invalid ARCHHEADING line")
 return match.group(1)
 
+def parse_srst(file, lnum, line):
+"""Handle an SRST directive"""
+# The input should be either "SRST", or "SRST(label)".
+match = re.match(r'SRST(\((.*?)\))?', line)
+if match is None:
+serror(file, lnum, "Invalid SRST line")
+return match.group(2)
+
 class HxtoolDocDirective(Directive):
 """Extract rST fragments from the specified .hx file"""
 required_argument = 1
@@ -113,6 +121,14 @@ def run(self):
 serror(hxfile, lnum, 'expected ERST, found SRST')
 else:
 state = HxState.RST
+label = parse_srst(hxfile, lnum, line)
+if label:
+rstlist.append("", hxfile, lnum - 1)
+# Build label as _DOCNAME-HXNAME-LABEL
+hx = os.path.splitext(os.path.basename(hxfile))[0]
+refline = ".. _" + env.docname + "-" + hx + \
+"-" + label + ":"
+rstlist.append(refline, hxfile, lnum - 1)
 elif directive == 'ERST':
 if state == HxState.CTEXT:
 serror(hxfile, lnum, 'expected SRST, found ERST')
diff --git a/docs/system/i386/xen.rst b/docs/system/i386/xen.rst
index 81898768ba..46db5f34c1 100644
--- a/docs/system/i386/xen.rst
+++ b/docs/system/i386/xen.rst
@@ -132,7 +132,8 @@ The example above provides the guest kernel command line 
after a separator
 (" ``--`` ") on the Xen command line, and does not provide the guest kernel
 with an actual initramfs, which would need to listed as a second multiboo

Re: [PATCH v3] doc/sphinx/hxtool.py: add optional label argument to SRST directive

2024-01-30 Thread David Woodhouse
On Tue, 2024-01-30 at 17:55 +, Peter Maydell wrote:
> 
> This looks good so
> Reviewed-by: Peter Maydell 

Thanks.

> but something has got mangled somewhere: patchew can't apply it:
> https://patchew.org/QEMU/4114f7204e892316d66be8f810eb5b8de4c0f75f.ca...@infradead.org/
> and patches doesn't like it either. In both cases git am barfs with
> 
> error: corrupt patch at line 23
> 
> I'm guessing it doesn't like the quoted-printable encoding.

Nah, QP really ought to be fine. The problem is that for some reason
Evolution has decided to replace space characters with non-breaking-
space characters. That is a new and strange pathology... in a version
of Evolution that I haven't updated for over a year.

I'll send a v4 with git-send-email, as checkpatch was whinging about
line lengths anyway.


smime.p7s
Description: S/MIME cryptographic signature


Re: [PATCH v3 00/46] Rework matching of network devices to -nic options

2024-01-28 Thread David Woodhouse
On Fri, 2024-01-26 at 17:51 +0100, Thomas Huth wrote:
> On 25/01/2024 01.38, Jason Wang wrote:
> > On Wed, Jan 24, 2024 at 9:14 PM David Woodhouse  wrote:
> > > 
> > > Hi Jason,
> > > 
> > > I think this series probably lives or dies with you. I think it's a
> > > worthwhile cleanup, but I no longer have an immediate need for it; I
> > > shipped a slightly ugly workaround in QEMU 8.2.
> > > 
> > > Please could you let me know if it's worth persisting with it?
> > 
> > Yes it is.
> 
> Agreed! It would be great of getting rid of the ugly global nd_table[] 
> finally!
> 
> > Thomas, I remember you've done tweaks for -nic in the past. would you
> > like to review this series?
> 
> I tried to skim through the patches today, some nits here and there, but 
> nothing sever, so IMHO it should be fine once they are fixed.

Thank you for the reviews! I think I've covered everything in v4 which
I posted yesterday, except possible one Reviewed-by: tag went AWOL
which I'll round up for next time.


smime.p7s
Description: S/MIME cryptographic signature


[PATCH v3] doc/sphinx/hxtool.py: add optional label argument to SRST directive

2024-01-27 Thread David Woodhouse
From: David Woodhouse 

We can't just embed labels directly into files like qemu-options.hx which
are included from multiple top-level rST files, because Sphinx sees the
labels as duplicate: https://github.com/sphinx-doc/sphinx/issues/9707

So add an optional argument to the SRST directive which causes a label
of the form '.. _DOCNAME-HXFILE-LABEL:' to be emitted, where 'DOCNAME'
is the name of the top level rST file, 'HXFILE' is the filename of the
.hx file, and 'LABEL' is the text provided within the 'SRST()' directive.
Using the DOCNAME of the top-level rST document means that it is unique
even when the .hx file is included from two different documents, as is
the case for qemu-options.hx

Now where the Xen PV documentation refers to the documentation for the
-initrd command line option, it can emit a link directly to it as
''.

Signed-off-by: David Woodhouse 
Reviewed-by: Paul Durrant 
---
v3:
 • Include DOCNAME in label
 • Drop emitrefs option which is no longer needed

v2:
 • Invoke parse_srst() unconditionally
 • Change emitted label to include basename of .hx file
 • Describe it in docs/devel/docs.rst


 docs/devel/docs.rst  | 12 ++--
 docs/sphinx/hxtool.py    | 14 ++
 docs/system/i386/xen.rst |  3 ++-
 qemu-options.hx  |  2 +-
 4 files changed, 27 insertions(+), 4 deletions(-)

diff --git a/docs/devel/docs.rst b/docs/devel/docs.rst
index 7da067905b..50ff0d67f8 100644
--- a/docs/devel/docs.rst
+++ b/docs/devel/docs.rst
@@ -30,6 +30,13 @@ nor the documentation output.
 
 ``SRST`` starts a reStructuredText section. Following lines
 are put into the documentation verbatim, and discarded from the C output.
+The alternative form ``SRST()`` is used to define a label which can be
+referenced from elsewhere in the rST documentation. The label will take
+the form , where ``DOCNAME`` is the name of the
+top level rST file, ``HXFILE`` is the filename of the .hx file without
+the ``.hx`` extension, and ``LABEL`` is the text provided within the
+``SRST()`` directive. For example,
+.
 
 ``ERST`` ends the documentation section started with ``SRST``,
 and switches back to a C code section.
@@ -53,8 +60,9 @@ text, but in ``hmp-commands.hx`` the C code sections are 
elements
 of an array of structs of type ``HMPCommand`` which define the
 name, behaviour and help text for each monitor command.
 
-In the file ``qemu-options.hx``, do not try to define a
+In the file ``qemu-options.hx``, do not try to explicitly define a
 reStructuredText label within a documentation section. This file
 is included into two separate Sphinx documents, and some
 versions of Sphinx will complain about the duplicate label
-that results.
+that results. Use the ``SRST()`` directive documented above, to
+emit an unambiguous label.
diff --git a/docs/sphinx/hxtool.py b/docs/sphinx/hxtool.py
index 9f6b9d87dc..e997d47d85 100644
--- a/docs/sphinx/hxtool.py
+++ b/docs/sphinx/hxtool.py
@@ -78,6 +78,14 @@ def parse_archheading(file, lnum, line):
 serror(file, lnum, "Invalid ARCHHEADING line")
 return match.group(1)
 
+def parse_srst(file, lnum, line):
+    """Handle an SRST directive"""
+    # The input should be either "SRST", or "SRST(label)".
+    match = re.match(r'SRST(\((.*?)\))?', line)
+    if match is None:
+    serror(file, lnum, "Invalid SRST line")
+    return match.group(2)
+
 class HxtoolDocDirective(Directive):
 """Extract rST fragments from the specified .hx file"""
 required_argument = 1
@@ -113,6 +121,12 @@ def run(self):
 serror(hxfile, lnum, 'expected ERST, found SRST')
 else:
 state = HxState.RST
+    label = parse_srst(hxfile, lnum, line)
+    if label:
+    basename = 
os.path.splitext(os.path.basename(hxfile))[0]
+    rstlist.append("", hxfile, lnum - 1)
+    refline = ".. _" + env.docname + "-" + basename + 
"-" + label + ":"
+    rstlist.append(refline, hxfile, lnum - 1)
 elif directive == 'ERST':
 if state == HxState.CTEXT:
 serror(hxfile, lnum, 'expected SRST, found ERST')
diff --git a/docs/system/i386/xen.rst b/docs/system/i386/xen.rst
index 81898768ba..46db5f34c1 100644
--- a/docs/system/i386/xen.rst
+++ b/docs/system/i386/xen.rst
@@ -132,7 +132,8 @@ The example above provides the guest kernel command line 
after a separator
 (" ``--`` ") on the Xen command line, and does not provide the guest kernel
 with an actual initramfs, which would need to listed as a second multiboot
 module. For more complicated alternatives, see the command line
-documentation for the ``-initrd`` option.
+:ref:`documentation ` for the
+``-initrd`` option.
 

Re: [PATCH] doc/sphinx/hxtool.py: add optional label argument to SRST directive

2024-01-27 Thread David Woodhouse
On Tue, 2023-12-12 at 15:04 +, Peter Maydell wrote:
> 
> > --- a/docs/system/i386/xen.rst
> > +++ b/docs/system/i386/xen.rst
> > @@ -132,7 +132,7 @@ The example above provides the guest kernel command 
> > line after a separator
> >   (" ``--`` ") on the Xen command line, and does not provide the guest 
> > kernel
> >   with an actual initramfs, which would need to listed as a second multiboot
> >   module. For more complicated alternatives, see the command line
> > -documentation for the ``-initrd`` option.
> > +:ref:`documentation ` for the ``-initrd`` option.
> 
> I think we should include the hxfile basename in the label name
> we generate. We also don't need to say "label", it's implicitly a
> label. Then when we refer to things we can say
>    
>    
> 
> and it's fairly readable what we're referring back to.
> 
> (We could alternatively have the emitrefs option take an argument
> for what to use in label names. I don't have a strong view on
> which would be better.)

Hm, wait... I did this as you suggest in v2 but can I also use this
trick to eliminate the 'emitrefs' option altogether?

Remember, the problem was that qemu-options.hx gets included *both*
from invocation.rst and from qemu-manpage.rst, so the label gets
emitted twice and is thus ambiguous. The 'emitrefs' option prevented it
from being emitted, but is one more hoop to jump through for the next
person who wants to use this facility. As I mentioned the 'emitrefs'
flag in the documentation, the "if it needs documenting, FIX IT"
instinct kicked in hard...

What if we build the top-level filename into the label, e.g.
  invocation-qemu-options-initrd

Then we don't need 'emitrefs' at all.


smime.p7s
Description: S/MIME cryptographic signature


Re: [PATCH v2 10/23] target/i386: Prefer fast cpu_env() over slower CPU QOM cast macro

2024-01-27 Thread David Woodhouse
On Fri, 2024-01-26 at 23:03 +0100, Philippe Mathieu-Daudé wrote:
> Mechanical patch produced running the command documented
> in scripts/coccinelle/cpu_env.cocci_template header.
> 
> Signed-off-by: Philippe Mathieu-Daudé 
> ---

For the KVM/Xen parts

Acked-by: David Woodhouse 


smime.p7s
Description: S/MIME cryptographic signature


[PATCH v4 28/47] hw/arm/npcm7xx: use qemu_configure_nic_device, allow emc0/emc1 as aliases

2024-01-26 Thread David Woodhouse
From: David Woodhouse 

Also update the test to specify which device to attach the test socket
to, and remove the comment lamenting the fact that we can't do so.

Signed-off-by: David Woodhouse 
---
 hw/arm/npcm7xx.c   | 16 +---
 tests/qtest/npcm7xx_emc-test.c | 18 --
 2 files changed, 13 insertions(+), 21 deletions(-)

diff --git a/hw/arm/npcm7xx.c b/hw/arm/npcm7xx.c
index 15ff21d047..ee395864e4 100644
--- a/hw/arm/npcm7xx.c
+++ b/hw/arm/npcm7xx.c
@@ -655,8 +655,9 @@ static void npcm7xx_realize(DeviceState *dev, Error **errp)
 
 /*
  * EMC Modules. Cannot fail.
- * The mapping of the device to its netdev backend works as follows:
- * emc[i] = nd_table[i]
+ * Use the available NIC configurations in order, allowing 'emc0' and
+ * 'emc1' to by used as aliases for the model= parameter to override.
+ *
  * This works around the inability to specify the netdev property for the
  * emc device: it's not pluggable and thus the -device option can't be
  * used.
@@ -664,12 +665,13 @@ static void npcm7xx_realize(DeviceState *dev, Error 
**errp)
 QEMU_BUILD_BUG_ON(ARRAY_SIZE(npcm7xx_emc_addr) != ARRAY_SIZE(s->emc));
 QEMU_BUILD_BUG_ON(ARRAY_SIZE(s->emc) != 2);
 for (i = 0; i < ARRAY_SIZE(s->emc); i++) {
-s->emc[i].emc_num = i;
 SysBusDevice *sbd = SYS_BUS_DEVICE(>emc[i]);
-if (nd_table[i].used) {
-qemu_check_nic_model(_table[i], TYPE_NPCM7XX_EMC);
-qdev_set_nic_properties(DEVICE(sbd), _table[i]);
-}
+char alias[6];
+
+s->emc[i].emc_num = i;
+snprintf(alias, sizeof(alias), "emc%u", i);
+qemu_configure_nic_device(DEVICE(sbd), true, alias);
+
 /*
  * The device exists regardless of whether it's connected to a QEMU
  * netdev backend. So always instantiate it even if there is no
diff --git a/tests/qtest/npcm7xx_emc-test.c b/tests/qtest/npcm7xx_emc-test.c
index b046f1d76a..f7646fae2c 100644
--- a/tests/qtest/npcm7xx_emc-test.c
+++ b/tests/qtest/npcm7xx_emc-test.c
@@ -225,21 +225,11 @@ static int *packet_test_init(int module_num, GString 
*cmd_line)
 g_assert_cmpint(ret, != , -1);
 
 /*
- * KISS and use -nic. We specify two nics (both emc{0,1}) because there's
- * currently no way to specify only emc1: The driver implicitly relies on
- * emc[i] == nd_table[i].
+ * KISS and use -nic. The driver accepts 'emc0' and 'emc1' as aliases
+ * in the 'model' field to specify the device to match.
  */
-if (module_num == 0) {
-g_string_append_printf(cmd_line,
-   " -nic socket,fd=%d,model=" TYPE_NPCM7XX_EMC " "
-   " -nic user,model=" TYPE_NPCM7XX_EMC " ",
-   test_sockets[1]);
-} else {
-g_string_append_printf(cmd_line,
-   " -nic user,model=" TYPE_NPCM7XX_EMC " "
-   " -nic socket,fd=%d,model=" TYPE_NPCM7XX_EMC " 
",
-   test_sockets[1]);
-}
+g_string_append_printf(cmd_line, " -nic socket,fd=%d,model=emc%d ",
+   test_sockets[1], module_num);
 
 g_test_queue_destroy(packet_test_clear, test_sockets);
 return test_sockets;
-- 
2.43.0




[PATCH v4 43/47] hw/xtensa/xtfpga: use qemu_create_nic_device()

2024-01-26 Thread David Woodhouse
From: David Woodhouse 

Signed-off-by: David Woodhouse 
Reviewed-by: Thomas Huth 
---
 hw/xtensa/xtfpga.c | 13 ++---
 1 file changed, 6 insertions(+), 7 deletions(-)

diff --git a/hw/xtensa/xtfpga.c b/hw/xtensa/xtfpga.c
index fbad1c83a3..f49e6591dc 100644
--- a/hw/xtensa/xtfpga.c
+++ b/hw/xtensa/xtfpga.c
@@ -141,14 +141,16 @@ static void xtfpga_net_init(MemoryRegion *address_space,
 hwaddr base,
 hwaddr descriptors,
 hwaddr buffers,
-qemu_irq irq, NICInfo *nd)
+qemu_irq irq)
 {
 DeviceState *dev;
 SysBusDevice *s;
 MemoryRegion *ram;
 
-dev = qdev_new("open_eth");
-qdev_set_nic_properties(dev, nd);
+dev = qemu_create_nic_device("open_eth", true, NULL);
+if (!dev) {
+return;
+}
 
 s = SYS_BUS_DEVICE(dev);
 sysbus_realize_and_unref(s, _fatal);
@@ -301,10 +303,7 @@ static void xtfpga_init(const XtfpgaBoardDesc *board, 
MachineState *machine)
 memory_region_add_subregion(system_memory, board->io[1], io);
 }
 xtfpga_fpga_init(system_io, 0x0d02, freq);
-if (nd_table[0].used) {
-xtfpga_net_init(system_io, 0x0d03, 0x0d030400, 0x0d80,
-extints[1], nd_table);
-}
+xtfpga_net_init(system_io, 0x0d03, 0x0d030400, 0x0d80, extints[1]);
 
 serial_mm_init(system_io, 0x0d050020, 2, extints[0],
115200, serial_hd(0), DEVICE_NATIVE_ENDIAN);
-- 
2.43.0




[PATCH v4 13/47] hw/mips/malta: use pci_init_nic_devices()

2024-01-26 Thread David Woodhouse
From: David Woodhouse 

The Malta board setup code would previously place the first NIC into PCI
slot 11 if was a PCNet card, and the rest (including the first if it was
anything other than a PCNet card) would be dynamically assigned.

Now it will place any PCNet NIC into slot 11, and then anything else will
be dynamically assigned.

Signed-off-by: David Woodhouse 
Reviewed-by: Thomas Huth 
---
 hw/mips/malta.c | 15 +++
 1 file changed, 3 insertions(+), 12 deletions(-)

diff --git a/hw/mips/malta.c b/hw/mips/malta.c
index d22bb1edef..af74008c82 100644
--- a/hw/mips/malta.c
+++ b/hw/mips/malta.c
@@ -612,18 +612,9 @@ static MaltaFPGAState *malta_fpga_init(MemoryRegion 
*address_space,
 /* Network support */
 static void network_init(PCIBus *pci_bus)
 {
-int i;
-
-for (i = 0; i < nb_nics; i++) {
-NICInfo *nd = _table[i];
-const char *default_devaddr = NULL;
-
-if (i == 0 && (!nd->model || strcmp(nd->model, "pcnet") == 0))
-/* The malta board has a PCNet card using PCI SLOT 11 */
-default_devaddr = "0b";
-
-pci_nic_init_nofail(nd, pci_bus, "pcnet", default_devaddr);
-}
+/* The malta board has a PCNet card using PCI SLOT 11 */
+pci_init_nic_in_slot(pci_bus, "pcnet", NULL, "0b");
+pci_init_nic_devices(pci_bus, "pcnet");
 }
 
 static void bl_setup_gt64120_jump_kernel(void **p, uint64_t run_addr,
-- 
2.43.0




[PATCH v4 14/47] hw/mips/loongson3_virt: use pci_init_nic_devices()

2024-01-26 Thread David Woodhouse
From: David Woodhouse 

Signed-off-by: David Woodhouse 
Reviewed-by: Thomas Huth 
---
 hw/mips/loongson3_virt.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/hw/mips/loongson3_virt.c b/hw/mips/loongson3_virt.c
index 33eae01eca..caedde2df0 100644
--- a/hw/mips/loongson3_virt.c
+++ b/hw/mips/loongson3_virt.c
@@ -451,9 +451,7 @@ static inline void loongson3_virt_devices_init(MachineState 
*machine,
 usb_create_simple(usb_bus_find(-1), "usb-tablet");
 }
 
-for (i = 0; i < nb_nics; i++) {
-pci_nic_init_nofail(_table[i], pci_bus, mc->default_nic, NULL);
-}
+pci_init_nic_devices(pci_bus, mc->default_nic);
 }
 
 static void mips_loongson3_virt_init(MachineState *machine)
-- 
2.43.0




[PATCH v4 01/47] net: add qemu_{configure, create}_nic_device(), qemu_find_nic_info()

2024-01-26 Thread David Woodhouse
From: David Woodhouse 

Most code which directly accesses nd_table[] and nb_nics uses them for
one of two things. Either "I have created a NIC device and I'd like a
configuration for it", or "I will create a NIC device *if* there is a
configuration for it".  With some variants on the theme around whether
they actually *check* if the model specified in the configuration is
the right one.

Provide functions which perform both of those, allowing platforms to
be a little more consistent and as a step towards making nd_table[]
and nb_nics private to the net code.

One might argue that platforms ought to be consistent about whether
they create the unconfigured devices or not, but making significant
user-visible changes is explicitly *not* the intent right now.

The new functions leave the 'model' field of the NICInfo as NULL after
using it for the default NIC model, unlike the qemu_check_nic_model()
function which does set nd->model to match default_model explicitly.
This is acceptable because there is no code which consumes nd->model
except this NIC-matching code in net/net.c, and no reasonable excuse
for any code wanting to use nd->model in future.

Also export the qemu_find_nic_info() helper, as some platforms have
special cases they need to handle.

Signed-off-by: David Woodhouse 
Reviewed-by: Paul Durrant 
Reviewed-by: Thomas Huth 
---
 include/net/net.h | 40 +
 net/net.c | 51 +++
 2 files changed, 91 insertions(+)

diff --git a/include/net/net.h b/include/net/net.h
index ffbd2c8d56..dff1872b4d 100644
--- a/include/net/net.h
+++ b/include/net/net.h
@@ -207,7 +207,47 @@ int qemu_show_nic_models(const char *arg, const char 
*const *models);
 void qemu_check_nic_model(NICInfo *nd, const char *model);
 int qemu_find_nic_model(NICInfo *nd, const char * const *models,
 const char *default_model);
+/**
+ * qemu_find_nic_info: Obtain NIC configuration information
+ * @typename: Name of device object type
+ * @match_default: Match NIC configurations with no model specified
+ * @alias: Additional model string to match (for user convenience and
+ * backward compatibility).
+ *
+ * Search for a NIC configuration matching the NIC model constraints.
+ */
+NICInfo *qemu_find_nic_info(const char *typename, bool match_default,
+const char *alias);
+/**
+ * qemu_configure_nic_device: Apply NIC configuration to a given device
+ * @dev: Network device to be configured
+ * @match_default: Match NIC configurations with no model specified
+ * @alias: Additional model string to match
+ *
+ * Search for a NIC configuration for the provided device, using the
+ * additionally specified matching constraints. If found, apply the
+ * configuration using qdev_set_nic_properties() and return %true.
+ *
+ * This is used by platform code which creates the device anyway,
+ * regardless of whether there is a configuration for it. This tends
+ * to be platforms which ignore `--nodefaults` and create net devices
+ * anyway, for example because the Ethernet device on that board is
+ * always physically present.
+ */
+bool qemu_configure_nic_device(DeviceState *dev, bool match_default,
+   const char *alias);
 
+/**
+ * qemu_create_nic_device: Create a NIC device if a configuration exists for it
+ * @typename: Object typename of network device
+ * @match_default: Match NIC configurations with no model specified
+ * @alias: Additional model string to match
+ *
+ * Search for a NIC configuration for the provided device type. If found,
+ * create an object of the corresponding type and return it.
+ */
+DeviceState *qemu_create_nic_device(const char *typename, bool match_default,
+const char *alias);
 void print_net_client(Monitor *mon, NetClientState *nc);
 void net_socket_rs_init(SocketReadState *rs,
 SocketReadStateFinalize *finalize,
diff --git a/net/net.c b/net/net.c
index 0520bc1681..aeb7f573fc 100644
--- a/net/net.c
+++ b/net/net.c
@@ -1087,6 +1087,57 @@ static int net_init_nic(const Netdev *netdev, const char 
*name,
 return idx;
 }
 
+NICInfo *qemu_find_nic_info(const char *typename, bool match_default,
+const char *alias)
+{
+NICInfo *nd;
+int i;
+
+for (i = 0; i < nb_nics; i++) {
+nd = _table[i];
+
+if (!nd->used || nd->instantiated) {
+continue;
+}
+
+if ((match_default && !nd->model) || !g_strcmp0(nd->model, typename)
+|| (alias && !g_strcmp0(nd->model, alias))) {
+return nd;
+}
+}
+return NULL;
+}
+
+
+/* "I have created a device. Please configure it if you can" */
+bool qemu_configure_nic_device(DeviceState *dev, bool match_default,
+   const char *alias

[PATCH v4 46/47] net: remove qemu_show_nic_models(), qemu_find_nic_model()

2024-01-26 Thread David Woodhouse
From: David Woodhouse 

These old functions can be removed now too. Let net_param_nic() print
the full set of network devices directly, and also make it note that a
list more specific to this platform/config will be available by using
'-nic model=help' instead.

Signed-off-by: David Woodhouse 
---
 include/net/net.h |  3 ---
 net/net.c | 39 ++-
 2 files changed, 6 insertions(+), 36 deletions(-)

diff --git a/include/net/net.h b/include/net/net.h
index 00ee1af7ab..588ee55f28 100644
--- a/include/net/net.h
+++ b/include/net/net.h
@@ -203,9 +203,6 @@ void qemu_set_vnet_hdr_len(NetClientState *nc, int len);
 int qemu_set_vnet_le(NetClientState *nc, bool is_le);
 int qemu_set_vnet_be(NetClientState *nc, bool is_be);
 void qemu_macaddr_default_if_unset(MACAddr *macaddr);
-int qemu_show_nic_models(const char *arg, const char *const *models);
-int qemu_find_nic_model(NICInfo *nd, const char * const *models,
-const char *default_model);
 /**
  * qemu_find_nic_info: Obtain NIC configuration information
  * @typename: Name of device object type
diff --git a/net/net.c b/net/net.c
index ffd4b42d5a..d705e9b0fd 100644
--- a/net/net.c
+++ b/net/net.c
@@ -977,38 +977,6 @@ GPtrArray *qemu_get_nic_models(const char *device_type)
 return nic_models;
 }
 
-int qemu_show_nic_models(const char *arg, const char *const *models)
-{
-int i;
-
-if (!arg || !is_help_option(arg)) {
-return 0;
-}
-
-printf("Available NIC models:\n");
-for (i = 0 ; models[i]; i++) {
-printf("%s\n", models[i]);
-}
-return 1;
-}
-
-int qemu_find_nic_model(NICInfo *nd, const char * const *models,
-const char *default_model)
-{
-int i;
-
-if (!nd->model)
-nd->model = g_strdup(default_model);
-
-for (i = 0 ; models[i]; i++) {
-if (strcmp(nd->model, models[i]) == 0)
-return i;
-}
-
-error_report("Unsupported NIC model: %s", nd->model);
-return -1;
-}
-
 static int net_init_nic(const Netdev *netdev, const char *name,
 NetClientState *peer, Error **errp)
 {
@@ -1791,9 +1759,14 @@ static int net_param_nic(void *dummy, QemuOpts *opts, 
Error **errp)
 }
 if (is_help_option(type)) {
 GPtrArray *nic_models = qemu_get_nic_models(TYPE_DEVICE);
+int i;
 show_netdevs();
 printf("\n");
-qemu_show_nic_models(type, (const char **)nic_models->pdata);
+printf("Available NIC models "
+   "(use -nic model=help for a filtered list):\n");
+for (i = 0 ; nic_models->pdata[i]; i++) {
+printf("%s\n", (char *)nic_models->pdata[i]);
+}
 g_ptr_array_free(nic_models, true);
 exit(0);
 }
-- 
2.43.0




[PATCH v4 39/47] hw/openrisc/openrisc_sim: use qemu_create_nic_device()

2024-01-26 Thread David Woodhouse
From: David Woodhouse 

Signed-off-by: David Woodhouse 
---
 hw/openrisc/openrisc_sim.c | 18 +-
 1 file changed, 9 insertions(+), 9 deletions(-)

diff --git a/hw/openrisc/openrisc_sim.c b/hw/openrisc/openrisc_sim.c
index 35da123aef..bffd6f721f 100644
--- a/hw/openrisc/openrisc_sim.c
+++ b/hw/openrisc/openrisc_sim.c
@@ -170,7 +170,7 @@ static void openrisc_create_fdt(Or1ksimState *state,
 
 static void openrisc_sim_net_init(Or1ksimState *state, hwaddr base, hwaddr 
size,
   int num_cpus, OpenRISCCPU *cpus[],
-  int irq_pin, NICInfo *nd)
+  int irq_pin)
 {
 void *fdt = state->fdt;
 DeviceState *dev;
@@ -178,8 +178,10 @@ static void openrisc_sim_net_init(Or1ksimState *state, 
hwaddr base, hwaddr size,
 char *nodename;
 int i;
 
-dev = qdev_new("open_eth");
-qdev_set_nic_properties(dev, nd);
+dev = qemu_create_nic_device("open_eth", true, NULL);
+if (!dev) {
+return;
+}
 
 s = SYS_BUS_DEVICE(dev);
 sysbus_realize_and_unref(s, _fatal);
@@ -313,12 +315,10 @@ static void openrisc_sim_init(MachineState *machine)
 openrisc_create_fdt(state, or1ksim_memmap, smp_cpus, machine->ram_size,
 machine->kernel_cmdline);
 
-if (nd_table[0].used) {
-openrisc_sim_net_init(state, or1ksim_memmap[OR1KSIM_ETHOC].base,
-  or1ksim_memmap[OR1KSIM_ETHOC].size,
-  smp_cpus, cpus,
-  OR1KSIM_ETHOC_IRQ, nd_table);
-}
+openrisc_sim_net_init(state, or1ksim_memmap[OR1KSIM_ETHOC].base,
+  or1ksim_memmap[OR1KSIM_ETHOC].size,
+  smp_cpus, cpus,
+  OR1KSIM_ETHOC_IRQ);
 
 if (smp_cpus > 1) {
 openrisc_sim_ompic_init(state, or1ksim_memmap[OR1KSIM_OMPIC].base,
-- 
2.43.0




[PATCH v4 18/47] hw/sh4/r2d: use pci_init_nic_devices()

2024-01-26 Thread David Woodhouse
From: David Woodhouse 

Previously, the first PCI NIC would be assigned to slot 2 even if the
user override the model and made it something other than an rtl8139
which is the default. Everything else would be dynamically assigned.

Now, the first rtl8139 gets slot 2 and everything else is dynamic.

Signed-off-by: David Woodhouse 
Reviewed-by: Yoshinori Sato 
---
 hw/sh4/r2d.c | 6 ++
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/hw/sh4/r2d.c b/hw/sh4/r2d.c
index 4944994e9c..e9f316a6ce 100644
--- a/hw/sh4/r2d.c
+++ b/hw/sh4/r2d.c
@@ -240,7 +240,6 @@ static void r2d_init(MachineState *machine)
 MemoryRegion *sdram = g_new(MemoryRegion, 1);
 qemu_irq *irq;
 DriveInfo *dinfo;
-int i;
 DeviceState *dev;
 SysBusDevice *busdev;
 MemoryRegion *address_space_mem = get_system_memory();
@@ -309,9 +308,8 @@ static void r2d_init(MachineState *machine)
   0x555, 0x2aa, 0);
 
 /* NIC: rtl8139 on-board, and 2 slots. */
-for (i = 0; i < nb_nics; i++)
-pci_nic_init_nofail(_table[i], pci_bus,
-mc->default_nic, i == 0 ? "2" : NULL);
+pci_init_nic_in_slot(pci_bus, mc->default_nic, NULL, "2");
+pci_init_nic_devices(pci_bus, mc->default_nic);
 
 /* USB keyboard */
 usb_create_simple(usb_bus_find(-1), "usb-kbd");
-- 
2.43.0




[PATCH v4 45/47] hw/pci: remove pci_nic_init_nofail()

2024-01-26 Thread David Woodhouse
From: David Woodhouse 

This function is no longer used, as all its callers have been converted
to use pci_init_nic_devices() instead.

Signed-off-by: David Woodhouse 
Reviewed-by: Thomas Huth 
---
 hw/pci/pci.c | 72 
 include/hw/pci/pci.h |  3 --
 2 files changed, 75 deletions(-)

diff --git a/hw/pci/pci.c b/hw/pci/pci.c
index 5849606f66..449abfb182 100644
--- a/hw/pci/pci.c
+++ b/hw/pci/pci.c
@@ -1853,78 +1853,6 @@ const pci_class_desc *get_class_desc(int class)
 return desc;
 }
 
-/* Initialize a PCI NIC.  */
-PCIDevice *pci_nic_init_nofail(NICInfo *nd, PCIBus *rootbus,
-   const char *default_model,
-   const char *default_devaddr)
-{
-const char *devaddr = nd->devaddr ? nd->devaddr : default_devaddr;
-GPtrArray *pci_nic_models;
-PCIBus *bus;
-PCIDevice *pci_dev;
-DeviceState *dev;
-int devfn;
-int i;
-int dom, busnr;
-unsigned slot;
-
-if (nd->model && !strcmp(nd->model, "virtio")) {
-g_free(nd->model);
-nd->model = g_strdup("virtio-net-pci");
-}
-
-pci_nic_models = qemu_get_nic_models(TYPE_PCI_DEVICE);
-
-if (qemu_show_nic_models(nd->model, (const char **)pci_nic_models->pdata)) 
{
-exit(0);
-}
-
-i = qemu_find_nic_model(nd, (const char **)pci_nic_models->pdata,
-default_model);
-if (i < 0) {
-exit(1);
-}
-
-if (!rootbus) {
-error_report("No primary PCI bus");
-exit(1);
-}
-
-assert(!rootbus->parent_dev);
-
-if (!devaddr) {
-devfn = -1;
-busnr = 0;
-} else {
-if (pci_parse_devaddr(devaddr, , , , NULL) < 0) {
-error_report("Invalid PCI device address %s for device %s",
- devaddr, nd->model);
-exit(1);
-}
-
-if (dom != 0) {
-error_report("No support for non-zero PCI domains");
-exit(1);
-}
-
-devfn = PCI_DEVFN(slot, 0);
-}
-
-bus = pci_find_bus_nr(rootbus, busnr);
-if (!bus) {
-error_report("Invalid PCI device address %s for device %s",
- devaddr, nd->model);
-exit(1);
-}
-
-pci_dev = pci_new(devfn, nd->model);
-dev = _dev->qdev;
-qdev_set_nic_properties(dev, nd);
-pci_realize_and_unref(pci_dev, bus, _fatal);
-g_ptr_array_free(pci_nic_models, true);
-return pci_dev;
-}
-
 void pci_init_nic_devices(PCIBus *bus, const char *default_model)
 {
 qemu_create_nic_bus_devices(>qbus, TYPE_PCI_DEVICE, default_model,
diff --git a/include/hw/pci/pci.h b/include/hw/pci/pci.h
index 6ff0b95a02..eaa3fc99d8 100644
--- a/include/hw/pci/pci.h
+++ b/include/hw/pci/pci.h
@@ -314,9 +314,6 @@ void pci_device_set_intx_routing_notifier(PCIDevice *dev,
   PCIINTxRoutingNotifier notifier);
 void pci_device_reset(PCIDevice *dev);
 
-PCIDevice *pci_nic_init_nofail(NICInfo *nd, PCIBus *rootbus,
-   const char *default_model,
-   const char *default_devaddr);
 void pci_init_nic_devices(PCIBus *bus, const char *default_model);
 bool pci_init_nic_in_slot(PCIBus *rootbus, const char *default_model,
   const char *alias, const char *devaddr);
-- 
2.43.0




[PATCH v4 06/47] hw/xen: use qemu_create_nic_bus_devices() to instantiate Xen NICs

2024-01-26 Thread David Woodhouse
From: David Woodhouse 

When instantiating XenBus itself, for each NIC which is configured with
either the model unspecified, or set to to "xen" or "xen-net-device",
create a corresponding xen-net-device for it.

Now we can revert the previous more hackish version which relied on the
platform code explicitly registering the NICs on its own XenBus, having
returned the BusState* from xen_bus_init() itself.

This also fixes the setup for Xen PV guests, which was previously broken
in various ways and never actually managed to peer with the netdev.

Signed-off-by: David Woodhouse 
Reviewed-by: Paul Durrant 
---
 hw/i386/pc.c| 13 ++---
 hw/i386/pc_piix.c   |  2 +-
 hw/i386/pc_q35.c|  2 +-
 hw/xen/xen-bus.c|  6 --
 hw/xen/xen_devconfig.c  | 25 -
 hw/xenpv/xen_machine_pv.c   |  9 -
 include/hw/i386/pc.h|  4 +---
 include/hw/xen/xen-bus.h|  2 +-
 include/hw/xen/xen-legacy-backend.h |  1 -
 9 files changed, 10 insertions(+), 54 deletions(-)

diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index ebb0b1c667..196827531a 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -1269,7 +1269,7 @@ void pc_basic_device_init(struct PCMachineState *pcms,
 if (pcms->bus) {
 pci_create_simple(pcms->bus, -1, "xen-platform");
 }
-pcms->xenbus = xen_bus_init();
+xen_bus_init();
 xen_be_init();
 }
 #endif
@@ -1297,8 +1297,7 @@ void pc_basic_device_init(struct PCMachineState *pcms,
 pcms->vmport != ON_OFF_AUTO_ON);
 }
 
-void pc_nic_init(PCMachineClass *pcmc, ISABus *isa_bus, PCIBus *pci_bus,
- BusState *xen_bus)
+void pc_nic_init(PCMachineClass *pcmc, ISABus *isa_bus, PCIBus *pci_bus)
 {
 MachineClass *mc = MACHINE_CLASS(pcmc);
 bool default_is_ne2k = g_str_equal(mc->default_nic, TYPE_ISA_NE2000);
@@ -1306,14 +1305,6 @@ void pc_nic_init(PCMachineClass *pcmc, ISABus *isa_bus, 
PCIBus *pci_bus,
 
 rom_set_order_override(FW_CFG_ORDER_OVERRIDE_NIC);
 
-if (xen_bus) {
-while ((nd = qemu_find_nic_info("xen-net-device", true, NULL))) {
-DeviceState *dev = qdev_new("xen-net-device");
-qdev_set_nic_properties(dev, nd);
-qdev_realize_and_unref(dev, xen_bus, _fatal);
-}
-}
-
 while ((nd = qemu_find_nic_info(TYPE_ISA_NE2000, default_is_ne2k, NULL))) {
 pc_init_ne2k_isa(isa_bus, nd, _fatal);
 }
diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c
index abfcfe4d2b..70d12bb1b5 100644
--- a/hw/i386/pc_piix.c
+++ b/hw/i386/pc_piix.c
@@ -339,7 +339,7 @@ static void pc_init1(MachineState *machine,
 pc_basic_device_init(pcms, isa_bus, x86ms->gsi, rtc_state, true,
  0x4);
 
-pc_nic_init(pcmc, isa_bus, pci_bus, pcms->xenbus);
+pc_nic_init(pcmc, isa_bus, pci_bus);
 
 if (pcmc->pci_enabled) {
 pc_cmos_init(pcms, idebus[0], idebus[1], rtc_state);
diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c
index f43d5142b8..7ca3f465e0 100644
--- a/hw/i386/pc_q35.c
+++ b/hw/i386/pc_q35.c
@@ -340,7 +340,7 @@ static void pc_q35_init(MachineState *machine)
 
 /* the rest devices to which pci devfn is automatically assigned */
 pc_vga_init(isa_bus, host_bus);
-pc_nic_init(pcmc, isa_bus, host_bus, pcms->xenbus);
+pc_nic_init(pcmc, isa_bus, host_bus);
 
 if (machine->nvdimms_state->is_enabled) {
 nvdimm_init_acpi_state(machine->nvdimms_state, system_io,
diff --git a/hw/xen/xen-bus.c b/hw/xen/xen-bus.c
index 4973e7d9c9..fb82cc33e4 100644
--- a/hw/xen/xen-bus.c
+++ b/hw/xen/xen-bus.c
@@ -19,6 +19,7 @@
 #include "qapi/error.h"
 #include "qapi/qmp/qdict.h"
 #include "sysemu/sysemu.h"
+#include "net/net.h"
 #include "trace.h"
 
 static char *xen_device_get_backend_path(XenDevice *xendev)
@@ -1133,7 +1134,7 @@ static void xen_register_types(void)
 
 type_init(xen_register_types)
 
-BusState *xen_bus_init(void)
+void xen_bus_init(void)
 {
 DeviceState *dev = qdev_new(TYPE_XEN_BRIDGE);
 BusState *bus = qbus_new(TYPE_XEN_BUS, dev, NULL);
@@ -1141,5 +1142,6 @@ BusState *xen_bus_init(void)
 sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), _fatal);
 qbus_set_bus_hotplug_handler(bus);
 
-return bus;
+qemu_create_nic_bus_devices(bus, TYPE_XEN_DEVICE, "xen-net-device",
+"xen", "xen-net-device");
 }
diff --git a/hw/xen/xen_devconfig.c b/hw/xen/xen_devconfig.c
index 3f77c675c6..2150869f60 100644
--- a/hw/xen/xen_devconfig.c
+++ b/hw/xen/xen_devconfig.c
@@ -46,31 +46,6 @@ static int xen_config_dev_all(char *fe, char *be)
 
 /* - */
 
-int xen_config_dev_nic(NICInfo *nic)
-{
-char fe[256], be[256];
-c

[PATCH v4 17/47] hw/ppc: use pci_init_nic_devices()

2024-01-26 Thread David Woodhouse
From: David Woodhouse 

Signed-off-by: David Woodhouse 
Reviewed-by: Thomas Huth 
---
 hw/ppc/e500.c  |  4 +---
 hw/ppc/mac_newworld.c  |  4 +---
 hw/ppc/mac_oldworld.c  |  4 +---
 hw/ppc/ppc440_bamboo.c | 14 +-
 4 files changed, 8 insertions(+), 18 deletions(-)

diff --git a/hw/ppc/e500.c b/hw/ppc/e500.c
index 566f1200dd..3bd12b54ab 100644
--- a/hw/ppc/e500.c
+++ b/hw/ppc/e500.c
@@ -1079,9 +1079,7 @@ void ppce500_init(MachineState *machine)
 
 if (pci_bus) {
 /* Register network interfaces. */
-for (i = 0; i < nb_nics; i++) {
-pci_nic_init_nofail(_table[i], pci_bus, mc->default_nic, NULL);
-}
+pci_init_nic_devices(pci_bus, mc->default_nic);
 }
 
 /* Register spinning region */
diff --git a/hw/ppc/mac_newworld.c b/hw/ppc/mac_newworld.c
index 535710314a..b36dbaf2b6 100644
--- a/hw/ppc/mac_newworld.c
+++ b/hw/ppc/mac_newworld.c
@@ -444,9 +444,7 @@ static void ppc_core99_init(MachineState *machine)
 graphic_depth = 15;
 }
 
-for (i = 0; i < nb_nics; i++) {
-pci_nic_init_nofail(_table[i], pci_bus, mc->default_nic, NULL);
-}
+pci_init_nic_devices(pci_bus, mc->default_nic);
 
 /* The NewWorld NVRAM is not located in the MacIO device */
 if (kvm_enabled() && qemu_real_host_page_size() > 4096) {
diff --git a/hw/ppc/mac_oldworld.c b/hw/ppc/mac_oldworld.c
index 9acc7adfc9..1981d3d8f6 100644
--- a/hw/ppc/mac_oldworld.c
+++ b/hw/ppc/mac_oldworld.c
@@ -277,9 +277,7 @@ static void ppc_heathrow_init(MachineState *machine)
 
 pci_vga_init(pci_bus);
 
-for (i = 0; i < nb_nics; i++) {
-pci_nic_init_nofail(_table[i], pci_bus, mc->default_nic, NULL);
-}
+pci_init_nic_devices(pci_bus, mc->default_nic);
 
 /* MacIO IDE */
 ide_drive_get(hd, ARRAY_SIZE(hd));
diff --git a/hw/ppc/ppc440_bamboo.c b/hw/ppc/ppc440_bamboo.c
index a189942de4..c75c3083e6 100644
--- a/hw/ppc/ppc440_bamboo.c
+++ b/hw/ppc/ppc440_bamboo.c
@@ -161,7 +161,6 @@ static void bamboo_init(MachineState *machine)
 DeviceState *uicdev;
 SysBusDevice *uicsbd;
 int success;
-int i;
 
 if (kvm_enabled()) {
 error_report("machine %s does not support the KVM accelerator",
@@ -234,14 +233,11 @@ static void bamboo_init(MachineState *machine)
 }
 
 if (pcibus) {
-/* Register network interfaces. */
-for (i = 0; i < nb_nics; i++) {
-/*
- * There are no PCI NICs on the Bamboo board, but there are
- * PCI slots, so we can pick whatever default model we want.
- */
-pci_nic_init_nofail(_table[i], pcibus, mc->default_nic, NULL);
-}
+/*
+ * There are no PCI NICs on the Bamboo board, but there are
+ * PCI slots, so we can pick whatever default model we want.
+ */
+pci_init_nic_devices(pcibus, mc->default_nic);
 }
 
 /* Load kernel. */
-- 
2.43.0




[PATCH v4 23/47] hw/arm/exynos4: use qemu_create_nic_device()

2024-01-26 Thread David Woodhouse
From: David Woodhouse 

Signed-off-by: David Woodhouse 
Reviewed-by: Thomas Huth 
---
 hw/arm/exynos4_boards.c | 6 ++
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/hw/arm/exynos4_boards.c b/hw/arm/exynos4_boards.c
index b0e13eb4f0..003992189b 100644
--- a/hw/arm/exynos4_boards.c
+++ b/hw/arm/exynos4_boards.c
@@ -76,10 +76,8 @@ static void lan9215_init(uint32_t base, qemu_irq irq)
 SysBusDevice *s;
 
 /* This should be a 9215 but the 9118 is close enough */
-if (nd_table[0].used) {
-qemu_check_nic_model(_table[0], "lan9118");
-dev = qdev_new(TYPE_LAN9118);
-qdev_set_nic_properties(dev, _table[0]);
+dev = qemu_create_nic_device(TYPE_LAN9118, true, NULL);
+if (dev) {
 qdev_prop_set_uint32(dev, "mode_16bit", 1);
 s = SYS_BUS_DEVICE(dev);
 sysbus_realize_and_unref(s, _fatal);
-- 
2.43.0




[PATCH v4 24/47] hw/arm/fsl: use qemu_configure_nic_device()

2024-01-26 Thread David Woodhouse
From: David Woodhouse 

Signed-off-by: David Woodhouse 
Reviewed-by: Thomas Huth 
---
 hw/arm/fsl-imx25.c  | 2 +-
 hw/arm/fsl-imx6.c   | 2 +-
 hw/arm/fsl-imx6ul.c | 2 +-
 hw/arm/fsl-imx7.c   | 2 +-
 4 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/hw/arm/fsl-imx25.c b/hw/arm/fsl-imx25.c
index 9d2fb75a68..a24fa7b443 100644
--- a/hw/arm/fsl-imx25.c
+++ b/hw/arm/fsl-imx25.c
@@ -170,7 +170,7 @@ static void fsl_imx25_realize(DeviceState *dev, Error 
**errp)
 
 object_property_set_uint(OBJECT(>fec), "phy-num", s->phy_num,
  _abort);
-qdev_set_nic_properties(DEVICE(>fec), _table[0]);
+qemu_configure_nic_device(DEVICE(>fec), true, NULL);
 
 if (!sysbus_realize(SYS_BUS_DEVICE(>fec), errp)) {
 return;
diff --git a/hw/arm/fsl-imx6.c b/hw/arm/fsl-imx6.c
index af2e982b05..afe9a59a81 100644
--- a/hw/arm/fsl-imx6.c
+++ b/hw/arm/fsl-imx6.c
@@ -383,7 +383,7 @@ static void fsl_imx6_realize(DeviceState *dev, Error **errp)
 
 object_property_set_uint(OBJECT(>eth), "phy-num", s->phy_num,
  _abort);
-qdev_set_nic_properties(DEVICE(>eth), _table[0]);
+qemu_configure_nic_device(DEVICE(>eth), true, NULL);
 if (!sysbus_realize(SYS_BUS_DEVICE(>eth), errp)) {
 return;
 }
diff --git a/hw/arm/fsl-imx6ul.c b/hw/arm/fsl-imx6ul.c
index e37b69a5e1..ca3dd439ec 100644
--- a/hw/arm/fsl-imx6ul.c
+++ b/hw/arm/fsl-imx6ul.c
@@ -442,7 +442,7 @@ static void fsl_imx6ul_realize(DeviceState *dev, Error 
**errp)
  s->phy_num[i], _abort);
 object_property_set_uint(OBJECT(>eth[i]), "tx-ring-num",
  FSL_IMX6UL_ETH_NUM_TX_RINGS, _abort);
-qdev_set_nic_properties(DEVICE(>eth[i]), _table[i]);
+qemu_configure_nic_device(DEVICE(>eth[i]), true, NULL);
 sysbus_realize(SYS_BUS_DEVICE(>eth[i]), _abort);
 
 sysbus_mmio_map(SYS_BUS_DEVICE(>eth[i]), 0,
diff --git a/hw/arm/fsl-imx7.c b/hw/arm/fsl-imx7.c
index 474cfdc87c..1acbe065db 100644
--- a/hw/arm/fsl-imx7.c
+++ b/hw/arm/fsl-imx7.c
@@ -446,7 +446,7 @@ static void fsl_imx7_realize(DeviceState *dev, Error **errp)
  s->phy_num[i], _abort);
 object_property_set_uint(OBJECT(>eth[i]), "tx-ring-num",
  FSL_IMX7_ETH_NUM_TX_RINGS, _abort);
-qdev_set_nic_properties(DEVICE(>eth[i]), _table[i]);
+qemu_configure_nic_device(DEVICE(>eth[i]), true, NULL);
 sysbus_realize(SYS_BUS_DEVICE(>eth[i]), _abort);
 
 sysbus_mmio_map(SYS_BUS_DEVICE(>eth[i]), 0, FSL_IMX7_ENETn_ADDR[i]);
-- 
2.43.0




[PATCH v4 07/47] hw/alpha/dp264: use pci_init_nic_devices()

2024-01-26 Thread David Woodhouse
From: David Woodhouse 

Signed-off-by: David Woodhouse 
Reviewed-by: Thomas Huth 
---
 hw/alpha/dp264.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/hw/alpha/dp264.c b/hw/alpha/dp264.c
index 03495e1e60..52a1fa310b 100644
--- a/hw/alpha/dp264.c
+++ b/hw/alpha/dp264.c
@@ -124,9 +124,7 @@ static void clipper_init(MachineState *machine)
 pci_vga_init(pci_bus);
 
 /* Network setup.  e1000 is good enough, failing Tulip support.  */
-for (i = 0; i < nb_nics; i++) {
-pci_nic_init_nofail(_table[i], pci_bus, mc->default_nic, NULL);
-}
+pci_init_nic_devices(pci_bus, mc->default_nic);
 
 /* Super I/O */
 isa_create_simple(isa_bus, TYPE_SMC37C669_SUPERIO);
-- 
2.43.0




[PATCH v4 41/47] hw/s390x/s390-virtio-ccw: use qemu_create_nic_device()

2024-01-26 Thread David Woodhouse
From: David Woodhouse 

Signed-off-by: David Woodhouse 
Acked-by: Thomas Huth 
---
 hw/s390x/s390-virtio-ccw.c | 11 ++-
 1 file changed, 2 insertions(+), 9 deletions(-)

diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c
index c99682b07d..62804cc228 100644
--- a/hw/s390x/s390-virtio-ccw.c
+++ b/hw/s390x/s390-virtio-ccw.c
@@ -229,16 +229,9 @@ static void s390_init_ipl_dev(const char *kernel_filename,
 
 static void s390_create_virtio_net(BusState *bus, const char *name)
 {
-int i;
-
-for (i = 0; i < nb_nics; i++) {
-NICInfo *nd = _table[i];
-DeviceState *dev;
-
-qemu_check_nic_model(nd, "virtio");
+DeviceState *dev;
 
-dev = qdev_new(name);
-qdev_set_nic_properties(dev, nd);
+while ((dev = qemu_create_nic_device(name, true, "virtio"))) {
 qdev_realize_and_unref(dev, bus, _fatal);
 }
 }
-- 
2.43.0




  1   2   3   4   5   6   7   8   9   10   >