arch/x86: Fix sending ICIs to more than one cluster, send one at a time.
The structure of a logical APIC destination is made up of a 16-bit bitfield of cluster-local IDs, as well as a 16-bit cluster ID. When sending an ICI to multiple cores in different clusters, these cannot simply be ORed together. Fixes #17233 Change-Id: Ifa84da51eccd85c1eff529749ffa00bc2159899e Reviewed-on: https://review.haiku-os.org/c/haiku/+/6919 Tested-by: Commit checker robot <no-reply+buildbot@haiku-os.org> Reviewed-by: Jérôme Duval <jerome.duval@gmail.com>
This commit is contained in:
parent
908afdaae4
commit
46b8479173
@ -1,4 +1,5 @@
|
||||
/*
|
||||
* Copyright 2023, Puck Meerburg, puck@puckipedia.com.
|
||||
* Copyright 2013, Paweł Dziepak, pdziepak@quarnos.org.
|
||||
* Copyright 2002-2005, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
@ -132,42 +133,14 @@ arch_smp_per_cpu_init(kernel_args *args, int32 cpu)
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
arch_smp_send_multicast_ici(CPUSet& cpuSet)
|
||||
static void
|
||||
send_multicast_ici_physical(CPUSet& cpuSet)
|
||||
{
|
||||
#if KDEBUG
|
||||
if (are_interrupts_enabled())
|
||||
panic("arch_smp_send_multicast_ici: called with interrupts enabled");
|
||||
#endif
|
||||
|
||||
memory_write_barrier();
|
||||
|
||||
int32 i = 0;
|
||||
int32 cpuCount = smp_get_num_cpus();
|
||||
int32 currentCpu = smp_get_current_cpu();
|
||||
|
||||
int32 logicalModeCPUs;
|
||||
if (x2apic_available())
|
||||
logicalModeCPUs = cpuCount;
|
||||
else
|
||||
logicalModeCPUs = std::min(cpuCount, int32(8));
|
||||
|
||||
uint32 destination = 0;
|
||||
for (; i < logicalModeCPUs; i++) {
|
||||
if (cpuSet.GetBit(i) && i != smp_get_current_cpu())
|
||||
destination |= gCPU[i].arch.logical_apic_id;
|
||||
}
|
||||
|
||||
uint32 mode = ICI_VECTOR | APIC_DELIVERY_MODE_FIXED
|
||||
| APIC_INTR_COMMAND_1_ASSERT
|
||||
| APIC_INTR_COMMAND_1_DEST_MODE_LOGICAL
|
||||
| APIC_INTR_COMMAND_1_DEST_FIELD;
|
||||
|
||||
while (!apic_interrupt_delivered())
|
||||
cpu_pause();
|
||||
apic_set_interrupt_command(destination, mode);
|
||||
|
||||
for (; i < cpuCount; i++) {
|
||||
if (cpuSet.GetBit(i)) {
|
||||
for (int32 i = 0; i < cpuCount; i++) {
|
||||
if (cpuSet.GetBit(i) && i != currentCpu) {
|
||||
uint32 destination = sCPUAPICIds[i];
|
||||
uint32 mode = ICI_VECTOR | APIC_DELIVERY_MODE_FIXED
|
||||
| APIC_INTR_COMMAND_1_ASSERT
|
||||
@ -182,6 +155,44 @@ arch_smp_send_multicast_ici(CPUSet& cpuSet)
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
arch_smp_send_multicast_ici(CPUSet& cpuSet)
|
||||
{
|
||||
#if KDEBUG
|
||||
if (are_interrupts_enabled())
|
||||
panic("arch_smp_send_multicast_ici: called with interrupts enabled");
|
||||
#endif
|
||||
|
||||
memory_write_barrier();
|
||||
|
||||
if (!x2apic_available()) {
|
||||
send_multicast_ici_physical(cpuSet);
|
||||
return;
|
||||
}
|
||||
|
||||
// WRMSR on the x2APIC MSRs is neither serializing, nor a load-store
|
||||
// operation, requiring both memory serialization *and* a load fence, which is
|
||||
// the only way to ensure the MSR doesn't get executed before the write
|
||||
// barrier.
|
||||
memory_read_barrier();
|
||||
|
||||
int32 cpuCount = smp_get_num_cpus();
|
||||
int32 currentCpu = smp_get_current_cpu();
|
||||
|
||||
uint32 mode = ICI_VECTOR | APIC_DELIVERY_MODE_FIXED
|
||||
| APIC_INTR_COMMAND_1_ASSERT
|
||||
| APIC_INTR_COMMAND_1_DEST_MODE_LOGICAL
|
||||
| APIC_INTR_COMMAND_1_DEST_FIELD;
|
||||
|
||||
for (int32 i = 0; i < cpuCount; i++) {
|
||||
if (!cpuSet.GetBit(i) || i == currentCpu)
|
||||
continue;
|
||||
|
||||
apic_set_interrupt_command(gCPU[i].arch.logical_apic_id, mode);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
arch_smp_send_broadcast_ici(void)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user