kernel/x86: Add locking around IO-APIC register accesses.
On SMP systems, we may call ioapic_assign_interrupt_to_cpu from multiple CPUs at a time, at least under low-latency mode. May fix #18588. Change-Id: Ie76e4127b05a8abc5f411d7719997dcfff9c2ff0 Reviewed-on: https://review.haiku-os.org/c/haiku/+/11491 Reviewed-by: waddlesplash <[email protected]>
This commit is contained in:
committed by
waddlesplash
parent
02fad68b15
commit
d2fee32bba
@@ -16,6 +16,7 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <cpu.h>
|
#include <cpu.h>
|
||||||
|
#include <util/AutoLock.h>
|
||||||
|
|
||||||
#include <arch/x86/apic.h>
|
#include <arch/x86/apic.h>
|
||||||
#include <arch/x86/arch_int.h>
|
#include <arch/x86/arch_int.h>
|
||||||
@@ -102,6 +103,7 @@ struct ioapic {
|
|||||||
uint64 level_triggered_mask;
|
uint64 level_triggered_mask;
|
||||||
uint64 nmi_mask;
|
uint64 nmi_mask;
|
||||||
|
|
||||||
|
spinlock registers_lock;
|
||||||
area_id register_area;
|
area_id register_area;
|
||||||
ioapic_registers* registers;
|
ioapic_registers* registers;
|
||||||
|
|
||||||
@@ -254,6 +256,7 @@ ioapic_assign_interrupt_to_cpu(int32 gsi, int32 cpu)
|
|||||||
struct ioapic* ioapic = find_ioapic(gsi);
|
struct ioapic* ioapic = find_ioapic(gsi);
|
||||||
if (ioapic == NULL)
|
if (ioapic == NULL)
|
||||||
return;
|
return;
|
||||||
|
SpinLocker _(ioapic->registers_lock);
|
||||||
|
|
||||||
uint32 apicid = x86_get_cpu_apic_id(cpu);
|
uint32 apicid = x86_get_cpu_apic_id(cpu);
|
||||||
|
|
||||||
@@ -282,6 +285,7 @@ ioapic_enable_io_interrupt(int32 gsi)
|
|||||||
struct ioapic* ioapic = find_ioapic(gsi);
|
struct ioapic* ioapic = find_ioapic(gsi);
|
||||||
if (ioapic == NULL)
|
if (ioapic == NULL)
|
||||||
return;
|
return;
|
||||||
|
SpinLocker _(ioapic->registers_lock);
|
||||||
|
|
||||||
x86_set_irq_source(gsi, IRQ_SOURCE_IOAPIC);
|
x86_set_irq_source(gsi, IRQ_SOURCE_IOAPIC);
|
||||||
|
|
||||||
@@ -301,6 +305,7 @@ ioapic_disable_io_interrupt(int32 gsi)
|
|||||||
struct ioapic* ioapic = find_ioapic(gsi);
|
struct ioapic* ioapic = find_ioapic(gsi);
|
||||||
if (ioapic == NULL)
|
if (ioapic == NULL)
|
||||||
return;
|
return;
|
||||||
|
SpinLocker _(ioapic->registers_lock);
|
||||||
|
|
||||||
uint8 pin = gsi - ioapic->global_interrupt_base;
|
uint8 pin = gsi - ioapic->global_interrupt_base;
|
||||||
TRACE("ioapic_disable_io_interrupt: gsi %" B_PRId32
|
TRACE("ioapic_disable_io_interrupt: gsi %" B_PRId32
|
||||||
@@ -318,6 +323,7 @@ ioapic_configure_io_interrupt(int32 gsi, uint32 config)
|
|||||||
struct ioapic* ioapic = find_ioapic(gsi);
|
struct ioapic* ioapic = find_ioapic(gsi);
|
||||||
if (ioapic == NULL)
|
if (ioapic == NULL)
|
||||||
return;
|
return;
|
||||||
|
InterruptsSpinLocker _(ioapic->registers_lock);
|
||||||
|
|
||||||
uint8 pin = gsi - ioapic->global_interrupt_base;
|
uint8 pin = gsi - ioapic->global_interrupt_base;
|
||||||
TRACE("ioapic_configure_io_interrupt: gsi %" B_PRId32
|
TRACE("ioapic_configure_io_interrupt: gsi %" B_PRId32
|
||||||
@@ -332,6 +338,7 @@ ioapic_configure_io_interrupt(int32 gsi, uint32 config)
|
|||||||
static status_t
|
static status_t
|
||||||
ioapic_map_ioapic(struct ioapic& ioapic, phys_addr_t physicalAddress)
|
ioapic_map_ioapic(struct ioapic& ioapic, phys_addr_t physicalAddress)
|
||||||
{
|
{
|
||||||
|
ioapic.registers_lock = B_SPINLOCK_INITIALIZER;
|
||||||
ioapic.register_area = vm_map_physical_memory(B_SYSTEM_TEAM, "io-apic",
|
ioapic.register_area = vm_map_physical_memory(B_SYSTEM_TEAM, "io-apic",
|
||||||
(void**)&ioapic.registers, ioapic.registers != NULL ? B_EXACT_ADDRESS
|
(void**)&ioapic.registers, ioapic.registers != NULL ? B_EXACT_ADDRESS
|
||||||
: B_ANY_KERNEL_ADDRESS, B_PAGE_SIZE, B_KERNEL_READ_AREA
|
: B_ANY_KERNEL_ADDRESS, B_PAGE_SIZE, B_KERNEL_READ_AREA
|
||||||
|
|||||||
Reference in New Issue
Block a user