Kyösti Mälkki has uploaded this change for review. ( https://review.coreboot.org/c/coreboot/+/55187 )
Change subject: cpu/x86/lapic: Add lapic_update32() helper ......................................................................
cpu/x86/lapic: Add lapic_update32() helper
Change-Id: I57c5d85d3098f9d59f26f427fe16829e4e769194 Signed-off-by: Kyösti Mälkki kyosti.malkki@gmail.com --- M src/cpu/x86/lapic/lapic.c M src/include/cpu/x86/lapic.h 2 files changed, 32 insertions(+), 27 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/87/55187/1
diff --git a/src/cpu/x86/lapic/lapic.c b/src/cpu/x86/lapic/lapic.c index 09dd003..468a5dc 100644 --- a/src/cpu/x86/lapic/lapic.c +++ b/src/cpu/x86/lapic/lapic.c @@ -2,10 +2,7 @@
#include <cpu/x86/lapic.h> #include <console/console.h> - -#if !CONFIG(XAPIC_ONLY) -#error "BUG: lapic_write_around() needs to be fixed for X2APIC." -#endif +#include <stdint.h>
void lapic_virtual_wire_mode_init(void) { @@ -25,31 +22,20 @@ /* * Set Task Priority to 'accept all'. */ - lapic_write_around(LAPIC_TASKPRI, - lapic_read_around(LAPIC_TASKPRI) & ~LAPIC_TPRI_MASK); + lapic_update32(LAPIC_TASKPRI, ~LAPIC_TPRI_MASK, 0);
/* Put the local APIC in virtual wire mode */ - lapic_write_around(LAPIC_SPIV, - (lapic_read_around(LAPIC_SPIV) & ~(LAPIC_VECTOR_MASK)) - | LAPIC_SPIV_ENABLE); - lapic_write_around(LAPIC_LVT0, - (lapic_read_around(LAPIC_LVT0) & - ~(LAPIC_LVT_MASKED | LAPIC_LVT_LEVEL_TRIGGER | - LAPIC_LVT_REMOTE_IRR | LAPIC_INPUT_POLARITY | - LAPIC_SEND_PENDING | LAPIC_LVT_RESERVED_1 | - LAPIC_DELIVERY_MODE_MASK)) - | (LAPIC_LVT_REMOTE_IRR | LAPIC_SEND_PENDING | - LAPIC_DELIVERY_MODE_EXTINT) - ); - lapic_write_around(LAPIC_LVT1, - (lapic_read_around(LAPIC_LVT1) & - ~(LAPIC_LVT_MASKED | LAPIC_LVT_LEVEL_TRIGGER | - LAPIC_LVT_REMOTE_IRR | LAPIC_INPUT_POLARITY | - LAPIC_SEND_PENDING | LAPIC_LVT_RESERVED_1 | - LAPIC_DELIVERY_MODE_MASK)) - | (LAPIC_LVT_REMOTE_IRR | LAPIC_SEND_PENDING | - LAPIC_DELIVERY_MODE_NMI) - ); + lapic_update32(LAPIC_SPIV, ~LAPIC_VECTOR_MASK, LAPIC_SPIV_ENABLE); + + uint32_t mask = LAPIC_LVT_MASKED | LAPIC_LVT_LEVEL_TRIGGER | LAPIC_LVT_REMOTE_IRR | + LAPIC_INPUT_POLARITY | LAPIC_SEND_PENDING | LAPIC_LVT_RESERVED_1 | + LAPIC_DELIVERY_MODE_MASK; + + lapic_update32(LAPIC_LVT0, ~mask, LAPIC_LVT_REMOTE_IRR | LAPIC_SEND_PENDING | + LAPIC_DELIVERY_MODE_EXTINT); + + lapic_update32(LAPIC_LVT1, ~mask, LAPIC_LVT_REMOTE_IRR | LAPIC_SEND_PENDING | + LAPIC_DELIVERY_MODE_NMI);
printk(BIOS_DEBUG, " apic_id: 0x%x ", lapicid()); printk(BIOS_INFO, "done.\n"); diff --git a/src/include/cpu/x86/lapic.h b/src/include/cpu/x86/lapic.h index c23680b..bb62077 100644 --- a/src/include/cpu/x86/lapic.h +++ b/src/include/cpu/x86/lapic.h @@ -92,6 +92,25 @@ xapic_write(reg, v); }
+static __always_inline void lapic_update32(unsigned int reg, uint32_t mask, uint32_t or) +{ + if (is_x2apic_mode()) { + uint32_t index; + msr_t msr; + index = X2APIC_MSR_BASE_ADDRESS + (uint32_t)(reg >> 4); + msr = rdmsr(index); + msr.lo &= mask; + msr.lo |= or; + wrmsr(index, msr); + } else { + uint32_t value; + value = xapic_read(reg); + value &= mask; + value |= or; + xapic_write_atomic(reg, value); + } +} + static __always_inline void lapic_wait_icr_idle(void) { do { } while (lapic_read(LAPIC_ICR) & LAPIC_ICR_BUSY);