4 * Copyright © 2018, 2021 Oracle and/or its affiliates.
6 * This work is licensed under the terms of the GNU GPL, version 2 or later.
7 * See the COPYING file in the top-level directory.
11 #include "qemu/osdep.h"
12 #include "qemu-common.h"
14 #include "hw/pci/pci.h"
15 #include "hw/pci/pci_ids.h"
16 #include "hw/pci/pci_bus.h"
17 #include "qemu/thread.h"
18 #include "hw/remote/machine.h"
19 #include "hw/remote/iohub.h"
20 #include "qemu/main-loop.h"
22 void remote_iohub_init(RemoteIOHubState
*iohub
)
26 memset(&iohub
->irqfds
, 0, sizeof(iohub
->irqfds
));
27 memset(&iohub
->resamplefds
, 0, sizeof(iohub
->resamplefds
));
29 for (pirq
= 0; pirq
< REMOTE_IOHUB_NB_PIRQS
; pirq
++) {
30 qemu_mutex_init(&iohub
->irq_level_lock
[pirq
]);
31 iohub
->irq_level
[pirq
] = 0;
32 event_notifier_init_fd(&iohub
->irqfds
[pirq
], -1);
33 event_notifier_init_fd(&iohub
->resamplefds
[pirq
], -1);
37 void remote_iohub_finalize(RemoteIOHubState
*iohub
)
41 for (pirq
= 0; pirq
< REMOTE_IOHUB_NB_PIRQS
; pirq
++) {
42 qemu_set_fd_handler(event_notifier_get_fd(&iohub
->resamplefds
[pirq
]),
44 event_notifier_cleanup(&iohub
->irqfds
[pirq
]);
45 event_notifier_cleanup(&iohub
->resamplefds
[pirq
]);
46 qemu_mutex_destroy(&iohub
->irq_level_lock
[pirq
]);
50 int remote_iohub_map_irq(PCIDevice
*pci_dev
, int intx
)
52 return pci_dev
->devfn
;
55 void remote_iohub_set_irq(void *opaque
, int pirq
, int level
)
57 RemoteIOHubState
*iohub
= opaque
;
60 assert(pirq
< PCI_DEVFN_MAX
);
62 QEMU_LOCK_GUARD(&iohub
->irq_level_lock
[pirq
]);
65 if (++iohub
->irq_level
[pirq
] == 1) {
66 event_notifier_set(&iohub
->irqfds
[pirq
]);
68 } else if (iohub
->irq_level
[pirq
] > 0) {
69 iohub
->irq_level
[pirq
]--;
73 static void intr_resample_handler(void *opaque
)
75 ResampleToken
*token
= opaque
;
76 RemoteIOHubState
*iohub
= token
->iohub
;
81 s
= event_notifier_test_and_clear(&iohub
->resamplefds
[pirq
]);
85 QEMU_LOCK_GUARD(&iohub
->irq_level_lock
[pirq
]);
87 if (iohub
->irq_level
[pirq
]) {
88 event_notifier_set(&iohub
->irqfds
[pirq
]);
92 void process_set_irqfd_msg(PCIDevice
*pci_dev
, MPQemuMsg
*msg
)
94 RemoteMachineState
*machine
= REMOTE_MACHINE(current_machine
);
95 RemoteIOHubState
*iohub
= &machine
->iohub
;
98 intx
= pci_get_byte(pci_dev
->config
+ PCI_INTERRUPT_PIN
) - 1;
100 pirq
= remote_iohub_map_irq(pci_dev
, intx
);
102 if (event_notifier_get_fd(&iohub
->irqfds
[pirq
]) != -1) {
103 qemu_set_fd_handler(event_notifier_get_fd(&iohub
->resamplefds
[pirq
]),
105 event_notifier_cleanup(&iohub
->irqfds
[pirq
]);
106 event_notifier_cleanup(&iohub
->resamplefds
[pirq
]);
107 memset(&iohub
->token
[pirq
], 0, sizeof(ResampleToken
));
110 event_notifier_init_fd(&iohub
->irqfds
[pirq
], msg
->fds
[0]);
111 event_notifier_init_fd(&iohub
->resamplefds
[pirq
], msg
->fds
[1]);
113 iohub
->token
[pirq
].iohub
= iohub
;
114 iohub
->token
[pirq
].pirq
= pirq
;
116 qemu_set_fd_handler(msg
->fds
[1], intr_resample_handler
, NULL
,
117 &iohub
->token
[pirq
]);