1/*
2 * Copyright 2020, Data61, CSIRO (ABN 41 687 119 230)
3 *
4 * SPDX-License-Identifier: GPL-2.0-only
5 */
6
7#pragma once
8
9#include <config.h>
10#include <arch/machine.h>
11
12BOOT_CODE bool_t x2apic_is_enabled(void);
13
14#ifdef CONFIG_X2APIC
15typedef enum _apic_reg_t {
16    APIC_ID             = 0x802,
17    APIC_VERSION        = 0x803,
18    APIC_TASK_PRIO      = 0x808,
19    APIC_PROC_PRIO      = 0x80A,
20    APIC_EOI            = 0x80B,
21    APIC_LOGICAL_DEST   = 0x80D,
22    APIC_SVR            = 0x80F,
23    APIC_ISR_BASE       = 0x810,
24    APIC_TMR_BASE       = 0x818,
25    APIC_IRR_BASE       = 0x820,
26    APIC_ERR_STATUS     = 0x828,
27    APIC_ICR            = 0x830,
28    APIC_LVT_TIMER      = 0x832,
29    APIC_LVT_THERMAL    = 0x833,
30    APIC_LVT_PERF_CNTR  = 0x834,
31    APIC_LVT_LINT0      = 0x835,
32    APIC_LVT_LINT1      = 0x836,
33    APIC_LVT_ERROR      = 0x837,
34    APIC_TIMER_COUNT    = 0x838,
35    APIC_TIMER_CURRENT  = 0x839,
36    APIC_TIMER_DIVIDE   = 0x83E
37} apic_reg_t;
38
39#define X2APIC_LDR_CLUSTER_SHIFT   16
40#define X2APIC_LDR_ID_MASK         16
41
42static inline uint32_t apic_read_reg(apic_reg_t reg)
43{
44    return x86_rdmsr_low(reg);
45}
46
47static inline void apic_write_reg(apic_reg_t reg, uint32_t val)
48{
49    x86_wrmsr(reg, val);
50}
51
52static inline logical_id_t apic_get_logical_id(void)
53{
54    return apic_read_reg(APIC_LOGICAL_DEST);
55}
56
57static inline word_t apic_get_cluster(logical_id_t logical_id)
58{
59    return logical_id >> X2APIC_LDR_CLUSTER_SHIFT;
60}
61
62static inline void apic_write_icr(word_t high, word_t low)
63{
64    uint64_t icr = ((uint64_t)high << 32) | low;
65    x86_wrmsr(APIC_ICR, icr);
66}
67
68#define IPI_ICR_BARRIER  asm volatile("mfence" ::: "memory")
69#define IPI_MEM_BARRIER  IPI_ICR_BARRIER
70#endif /* CONFIG_X2APIC */
71