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/boards.h"
19 #include "hw/remote/machine.h"
20 #include "hw/remote/iohub.h"
21 #include "qemu/main-loop.h"
23 void remote_iohub_init(RemoteIOHubState
*iohub
)
27 memset(&iohub
->irqfds
, 0, sizeof(iohub
->irqfds
));
28 memset(&iohub
->resamplefds
, 0, sizeof(iohub
->resamplefds
));
30 for (pirq
= 0; pirq
< REMOTE_IOHUB_NB_PIRQS
; pirq
++) {
31 qemu_mutex_init(&iohub
->irq_level_lock
[pirq
]);
32 iohub
->irq_level
[pirq
] = 0;
33 event_notifier_init_fd(&iohub
->irqfds
[pirq
], -1);
34 event_notifier_init_fd(&iohub
->resamplefds
[pirq
], -1);
38 void remote_iohub_finalize(RemoteIOHubState
*iohub
)
42 for (pirq
= 0; pirq
< REMOTE_IOHUB_NB_PIRQS
; pirq
++) {
43 qemu_set_fd_handler(event_notifier_get_fd(&iohub
->resamplefds
[pirq
]),
45 event_notifier_cleanup(&iohub
->irqfds
[pirq
]);
46 event_notifier_cleanup(&iohub
->resamplefds
[pirq
]);
47 qemu_mutex_destroy(&iohub
->irq_level_lock
[pirq
]);
51 int remote_iohub_map_irq(PCIDevice
*pci_dev
, int intx
)
53 return pci_dev
->devfn
;
56 void remote_iohub_set_irq(void *opaque
, int pirq
, int level
)
58 RemoteIOHubState
*iohub
= opaque
;
61 assert(pirq
< PCI_DEVFN_MAX
);
63 QEMU_LOCK_GUARD(&iohub
->irq_level_lock
[pirq
]);
66 if (++iohub
->irq_level
[pirq
] == 1) {
67 event_notifier_set(&iohub
->irqfds
[pirq
]);
69 } else if (iohub
->irq_level
[pirq
] > 0) {
70 iohub
->irq_level
[pirq
]--;
74 static void intr_resample_handler(void *opaque
)
76 ResampleToken
*token
= opaque
;
77 RemoteIOHubState
*iohub
= token
->iohub
;
82 s
= event_notifier_test_and_clear(&iohub
->resamplefds
[pirq
]);
86 QEMU_LOCK_GUARD(&iohub
->irq_level_lock
[pirq
]);
88 if (iohub
->irq_level
[pirq
]) {
89 event_notifier_set(&iohub
->irqfds
[pirq
]);
93 void process_set_irqfd_msg(PCIDevice
*pci_dev
, MPQemuMsg
*msg
)
95 RemoteMachineState
*machine
= REMOTE_MACHINE(current_machine
);
96 RemoteIOHubState
*iohub
= &machine
->iohub
;
99 intx
= pci_get_byte(pci_dev
->config
+ PCI_INTERRUPT_PIN
) - 1;
101 pirq
= remote_iohub_map_irq(pci_dev
, intx
);
103 if (event_notifier_get_fd(&iohub
->irqfds
[pirq
]) != -1) {
104 qemu_set_fd_handler(event_notifier_get_fd(&iohub
->resamplefds
[pirq
]),
106 event_notifier_cleanup(&iohub
->irqfds
[pirq
]);
107 event_notifier_cleanup(&iohub
->resamplefds
[pirq
]);
108 memset(&iohub
->token
[pirq
], 0, sizeof(ResampleToken
));
111 event_notifier_init_fd(&iohub
->irqfds
[pirq
], msg
->fds
[0]);
112 event_notifier_init_fd(&iohub
->resamplefds
[pirq
], msg
->fds
[1]);
114 iohub
->token
[pirq
].iohub
= iohub
;
115 iohub
->token
[pirq
].pirq
= pirq
;
117 qemu_set_fd_handler(msg
->fds
[1], intr_resample_handler
, NULL
,
118 &iohub
->token
[pirq
]);