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"
13 #include "hw/pci/pci.h"
14 #include "hw/pci/pci_ids.h"
15 #include "hw/pci/pci_bus.h"
16 #include "qemu/thread.h"
17 #include "hw/remote/machine.h"
18 #include "hw/remote/iohub.h"
19 #include "qemu/main-loop.h"
21 void remote_iohub_init(RemoteIOHubState
*iohub
)
25 memset(&iohub
->irqfds
, 0, sizeof(iohub
->irqfds
));
26 memset(&iohub
->resamplefds
, 0, sizeof(iohub
->resamplefds
));
28 for (pirq
= 0; pirq
< REMOTE_IOHUB_NB_PIRQS
; pirq
++) {
29 qemu_mutex_init(&iohub
->irq_level_lock
[pirq
]);
30 iohub
->irq_level
[pirq
] = 0;
31 event_notifier_init_fd(&iohub
->irqfds
[pirq
], -1);
32 event_notifier_init_fd(&iohub
->resamplefds
[pirq
], -1);
36 void remote_iohub_finalize(RemoteIOHubState
*iohub
)
40 for (pirq
= 0; pirq
< REMOTE_IOHUB_NB_PIRQS
; pirq
++) {
41 qemu_set_fd_handler(event_notifier_get_fd(&iohub
->resamplefds
[pirq
]),
43 event_notifier_cleanup(&iohub
->irqfds
[pirq
]);
44 event_notifier_cleanup(&iohub
->resamplefds
[pirq
]);
45 qemu_mutex_destroy(&iohub
->irq_level_lock
[pirq
]);
49 int remote_iohub_map_irq(PCIDevice
*pci_dev
, int intx
)
51 return pci_dev
->devfn
;
54 void remote_iohub_set_irq(void *opaque
, int pirq
, int level
)
56 RemoteIOHubState
*iohub
= opaque
;
59 assert(pirq
< PCI_DEVFN_MAX
);
61 QEMU_LOCK_GUARD(&iohub
->irq_level_lock
[pirq
]);
64 if (++iohub
->irq_level
[pirq
] == 1) {
65 event_notifier_set(&iohub
->irqfds
[pirq
]);
67 } else if (iohub
->irq_level
[pirq
] > 0) {
68 iohub
->irq_level
[pirq
]--;
72 static void intr_resample_handler(void *opaque
)
74 ResampleToken
*token
= opaque
;
75 RemoteIOHubState
*iohub
= token
->iohub
;
80 s
= event_notifier_test_and_clear(&iohub
->resamplefds
[pirq
]);
84 QEMU_LOCK_GUARD(&iohub
->irq_level_lock
[pirq
]);
86 if (iohub
->irq_level
[pirq
]) {
87 event_notifier_set(&iohub
->irqfds
[pirq
]);
91 void process_set_irqfd_msg(PCIDevice
*pci_dev
, MPQemuMsg
*msg
)
93 RemoteMachineState
*machine
= REMOTE_MACHINE(current_machine
);
94 RemoteIOHubState
*iohub
= &machine
->iohub
;
97 intx
= pci_get_byte(pci_dev
->config
+ PCI_INTERRUPT_PIN
) - 1;
99 pirq
= remote_iohub_map_irq(pci_dev
, intx
);
101 if (event_notifier_get_fd(&iohub
->irqfds
[pirq
]) != -1) {
102 qemu_set_fd_handler(event_notifier_get_fd(&iohub
->resamplefds
[pirq
]),
104 event_notifier_cleanup(&iohub
->irqfds
[pirq
]);
105 event_notifier_cleanup(&iohub
->resamplefds
[pirq
]);
106 memset(&iohub
->token
[pirq
], 0, sizeof(ResampleToken
));
109 event_notifier_init_fd(&iohub
->irqfds
[pirq
], msg
->fds
[0]);
110 event_notifier_init_fd(&iohub
->resamplefds
[pirq
], msg
->fds
[1]);
112 iohub
->token
[pirq
].iohub
= iohub
;
113 iohub
->token
[pirq
].pirq
= pirq
;
115 qemu_set_fd_handler(msg
->fds
[1], intr_resample_handler
, NULL
,
116 &iohub
->token
[pirq
]);