interrupt_controller: program local APIC LDR register for xAPIC
If IO APIC is in logical destination mode, local APICs compare their logical APIC ID defined in LDR (Logical Destination Register) with the destination code sent with the interrupt to determine whether or not to accept the incoming interrupt. This patch programs LDR in xAPIC mode to support IO APIC logical mode. The local APIC ID from local APIC ID register can't be used as the 'logical APIC ID' because LAPIC ID may not be consecutive numbers hence it makes it impossible for LDR to encode 8 IDs within 8 bits. This patch chooses 0 for BSP, and for APs, cpu_number which is the index to x86_cpuboot[], which ultimately assigned in z_smp_init[]. Signed-off-by: Zide Chen <zide.chen@intel.com>
This commit is contained in:
parent
e91e7fc3d5
commit
87b65c5ac2
4 changed files with 25 additions and 3 deletions
|
@ -236,6 +236,9 @@ __csSet:
|
|||
lidt z_x86_idt /* load 32-bit operand size IDT */
|
||||
|
||||
#ifdef CONFIG_LOAPIC
|
||||
/* For BSP, cpu_number is 0 */
|
||||
xorl %eax, %eax
|
||||
pushl %eax
|
||||
call z_loapic_enable
|
||||
#endif
|
||||
|
||||
|
|
|
@ -144,7 +144,8 @@ FUNC_NORETURN void z_x86_cpu_init(struct x86_cpuboot *cpuboot)
|
|||
{
|
||||
x86_sse_init(NULL);
|
||||
|
||||
z_loapic_enable();
|
||||
/* The internal cpu_number is the index to x86_cpuboot[] */
|
||||
z_loapic_enable((unsigned char)(cpuboot - x86_cpuboot));
|
||||
|
||||
#ifdef CONFIG_USERSPACE
|
||||
/* Set landing site for 'syscall' instruction */
|
||||
|
|
|
@ -71,10 +71,27 @@ static u32_t loapic_device_power_state = DEVICE_PM_ACTIVE_STATE;
|
|||
* Called from early assembly layer (e.g., crt0.S).
|
||||
*/
|
||||
|
||||
void z_loapic_enable(void)
|
||||
void z_loapic_enable(unsigned char cpu_number)
|
||||
{
|
||||
s32_t loApicMaxLvt; /* local APIC Max LVT */
|
||||
|
||||
#ifndef CONFIG_X2APIC
|
||||
/*
|
||||
* in xAPIC and flat model, bits 24-31 in LDR (Logical APIC ID) are
|
||||
* bitmap of target logical APIC ID and it supports maximum 8 local
|
||||
* APICs.
|
||||
*
|
||||
* The logical APIC ID could be arbitrarily selected by system software
|
||||
* and is different from local APIC ID in local APIC ID register.
|
||||
*
|
||||
* We choose 0 for BSP, and the index to x86_cpuboot[] for secondary
|
||||
* CPUs.
|
||||
*
|
||||
* in X2APIC, LDR is read-only.
|
||||
*/
|
||||
x86_write_xapic(LOAPIC_LDR, 1 << (cpu_number + 24));
|
||||
#endif
|
||||
|
||||
/*
|
||||
* enable the local APIC. note that we use xAPIC mode here, since
|
||||
* x2APIC access is not enabled until the next step (if at all).
|
||||
|
@ -99,6 +116,7 @@ void z_loapic_enable(void)
|
|||
/* reset the DFR, TPR, TIMER_CONFIG, and TIMER_ICR */
|
||||
|
||||
#ifndef CONFIG_X2APIC
|
||||
/* Flat model */
|
||||
x86_write_loapic(LOAPIC_DFR, 0xffffffff); /* no DFR in x2APIC mode */
|
||||
#endif
|
||||
|
||||
|
|
|
@ -54,7 +54,7 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern void z_loapic_enable(void);
|
||||
extern void z_loapic_enable(unsigned char cpu_number);
|
||||
extern void z_loapic_int_vec_set(unsigned int irq, unsigned int vector);
|
||||
extern void z_loapic_irq_enable(unsigned int irq);
|
||||
extern void z_loapic_irq_disable(unsigned int irq);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue