Skip to content

Commit

Permalink
apic: add proper R/W interface for ICR register
Browse files Browse the repository at this point in the history
Signed-off-by: Pawel Wieczorkiewicz <[email protected]>
  • Loading branch information
wipawel committed Nov 10, 2020
1 parent 938c5b5 commit 1e1efee
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 22 deletions.
21 changes: 17 additions & 4 deletions arch/x86/apic.c
Original file line number Diff line number Diff line change
Expand Up @@ -78,13 +78,26 @@ void apic_write(unsigned int reg, uint64_t val) {
BUG();
}

void apic_icr_write(uint64_t val) {
apic_icr_t apic_icr_read(void) {
apic_icr_t icr;

if (apic_mode == APIC_MODE_XAPIC) {
icr.icr0 = apic_read(APIC_ICR0);
icr.icr1 = apic_read(APIC_ICR1);
}
else if (apic_mode == APIC_MODE_X2APIC)
icr.reg = apic_read(APIC_ICR0);

return icr;
}

void apic_icr_write(const apic_icr_t *icr) {
if (apic_mode == APIC_MODE_XAPIC) {
apic_mmio_write(APIC_ICR1, (uint32_t)(val >> 32));
apic_mmio_write(APIC_ICR0, (uint32_t) val);
apic_mmio_write(XAPIC_REG(APIC_ICR1), icr->icr0);
apic_mmio_write(XAPIC_REG(APIC_ICR0), icr->icr1);
}
else
apic_msr_write(MSR_X2APIC_REGS + (APIC_ICR0 >> 4), val);
apic_msr_write(X2APIC_REG(APIC_ICR0), icr->reg);
}

apic_mode_t apic_get_mode(void) { return apic_mode; }
Expand Down
29 changes: 18 additions & 11 deletions include/arch/x86/apic.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,15 +32,6 @@
/* Local APIC definitions */
#define APIC_SPIV_APIC_ENABLED 0x00100

#define APIC_DM_NMI 0x00400
#define APIC_DM_INIT 0x00500
#define APIC_DM_STARTUP 0x00600
#define APIC_ICR_BUSY 0x01000
#define APIC_DISABLE 0x10000
#define APIC_DEST_SELF 0x40000

#define GET_APIC_DEST_FIELD(x) (((x) >> 24) & 0xFF)
#define SET_APIC_DEST_FIELD(x) ((x) << 24)
#define MSR_X2APIC_REGS 0x800U

#ifndef __ASSEMBLY__
Expand Down Expand Up @@ -465,8 +456,9 @@ typedef union apic_self_ipi apic_self_ipi_t;
extern uint64_t apic_read(unsigned int reg);
extern void apic_write(unsigned int reg, uint64_t val);
extern apic_mode_t apic_get_mode(void);
extern void apic_icr_write(uint64_t val);
extern void init_apic(unsigned int cpu, apic_mode_t mode);
extern apic_icr_t apic_icr_read(void);
extern void apic_icr_write(const apic_icr_t *icr);

/* Static declarations */

Expand All @@ -487,8 +479,23 @@ static inline void *apic_get_base(apic_base_t apic_base) {
}

static inline void apic_wait_ready(void) {
while (apic_read(APIC_ICR0) & APIC_ICR_BUSY)
apic_icr_t icr;

do {
icr = apic_icr_read();
if (icr.deliv_status == APIC_DELIV_STATUS_IDLE)
return;
cpu_relax();
} while (true);
}

static inline void apic_icr_set_dest(apic_icr_t *icr, uint32_t dest) {
apic_mode_t mode = apic_get_mode();

if (mode == APIC_MODE_XAPIC)
icr->xapic_dest = dest;
else if (mode == APIC_MODE_X2APIC)
icr->x2apic_dest = dest;
}

static inline void apic_EOI(void) { apic_write(APIC_EOI, APIC_EOI_SIGNAL); }
Expand Down
19 changes: 12 additions & 7 deletions smp/smp.c
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,7 @@ void __noreturn ap_startup(void) {
}

static __text_init void boot_cpu(unsigned int cpu) {
percpu_t *percpu = get_percpu_page(cpu);
uint64_t icr;
apic_icr_t icr;

if (PERCPU_GET(bsp))
return;
Expand All @@ -76,16 +75,22 @@ static __text_init void boot_cpu(unsigned int cpu) {

dprintk("Starting AP: %u\n", cpu);

/* Set ICR2 part */
icr = (_ul(SET_APIC_DEST_FIELD(percpu->apic_id)) << 32);
icr = apic_icr_read();
apic_icr_set_dest(&icr, PERCPU_GET(apic_id));

/* Wake up the secondary processor: INIT-SIPI-SIPI... */
icr.deliv_mode = APIC_DELIV_MODE_INIT;
apic_wait_ready();
apic_icr_write(icr | APIC_DM_INIT);
apic_icr_write(&icr);

icr.deliv_mode = APIC_DELIV_MODE_SIPI;
icr.vector = GET_SIPI_VECTOR(ap_start);
apic_wait_ready();
apic_icr_write(icr | (APIC_DM_STARTUP | GET_SIPI_VECTOR(ap_start)));
apic_icr_write(&icr);

apic_wait_ready();
apic_icr_write(icr | (APIC_DM_STARTUP | GET_SIPI_VECTOR(ap_start)));
apic_icr_write(&icr);

apic_wait_ready();

while (!ap_callin)
Expand Down

0 comments on commit 1e1efee

Please sign in to comment.