mirror of
https://github.com/hermitcore/libhermit.git
synced 2025-03-09 00:00:03 +01:00
revise code, stop x2APIC support if Linux doesn't use it
This commit is contained in:
parent
60fd64381d
commit
03551659d4
4 changed files with 119 additions and 48 deletions
|
@ -194,6 +194,8 @@ extern "C" {
|
|||
/// SwapGS GS shadow
|
||||
#define MSR_KERNEL_GS_BASE 0xc0000102
|
||||
|
||||
#define MSR_XAPIC_ENABLE (1UL << 11)
|
||||
#define MSR_X2APIC_ENABLE (1UL << 10)
|
||||
#define MSR_IA32_MISC_ENABLE 0x000001a0
|
||||
#define MSR_IA32_FEATURE_CONTROL 0x0000003a
|
||||
|
||||
|
|
|
@ -150,6 +150,48 @@ int apic_is_enabled(void)
|
|||
return (lapic && initialized);
|
||||
}
|
||||
|
||||
static inline void x2apic_disable(void)
|
||||
{
|
||||
uint64_t msr;
|
||||
|
||||
if (!has_x2apic())
|
||||
return;
|
||||
|
||||
msr = rdmsr(MSR_APIC_BASE);
|
||||
if (!(msr & MSR_X2APIC_ENABLE)) {
|
||||
kprintf("X2APIC already disabled!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Disable xapic and x2apic first and then reenable xapic mode */
|
||||
wrmsr(MSR_APIC_BASE, msr & ~(MSR_X2APIC_ENABLE | MSR_XAPIC_ENABLE));
|
||||
wrmsr(MSR_APIC_BASE, msr & ~MSR_X2APIC_ENABLE);
|
||||
|
||||
kprintf("Disable X2APIC support\n");
|
||||
lapic_read = lapic_read_default;
|
||||
lapic_write = lapic_write_default;
|
||||
}
|
||||
|
||||
static inline void x2apic_enable(void)
|
||||
{
|
||||
uint64_t msr;
|
||||
|
||||
if (!has_x2apic())
|
||||
return;
|
||||
|
||||
msr = rdmsr(MSR_APIC_BASE);
|
||||
if (msr & MSR_X2APIC_ENABLE) {
|
||||
kprintf("X2APIC already enabled!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
wrmsr(MSR_APIC_BASE, msr | MSR_X2APIC_ENABLE);
|
||||
|
||||
kprintf("Enable X2APIC support!\n");
|
||||
lapic_read = lapic_read_msr;
|
||||
lapic_write = lapic_write_msr;
|
||||
}
|
||||
|
||||
/*
|
||||
* Send a 'End of Interrupt' command to the APIC
|
||||
*/
|
||||
|
@ -303,6 +345,8 @@ static int lapic_reset(void)
|
|||
if (!lapic)
|
||||
return -ENXIO;
|
||||
|
||||
x2apic_enable();
|
||||
|
||||
max_lvt = apic_lvt_entries();
|
||||
|
||||
lapic_write(APIC_SVR, 0x17F); // enable the apic and connect to the idt entry 127
|
||||
|
@ -543,15 +587,16 @@ check_lapic:
|
|||
kprintf("Found APIC at 0x%x\n", lapic);
|
||||
|
||||
if (has_x2apic()) {
|
||||
kprintf("Enable X2APIC support!\n");
|
||||
wrmsr(MSR_APIC_BASE, lapic | 0xD00);
|
||||
lapic_read = lapic_read_msr;
|
||||
lapic_write = lapic_write_msr;
|
||||
x2apic_enable();
|
||||
} else {
|
||||
page_map(LAPIC_ADDR, (size_t)lapic & PAGE_MASK, 1, PG_GLOBAL | PG_RW | PG_PCD);
|
||||
vma_add(LAPIC_ADDR, LAPIC_ADDR + PAGE_SIZE, VMA_READ | VMA_WRITE);
|
||||
lapic = LAPIC_ADDR;
|
||||
kprintf("Map APIC to 0x%x\n", lapic);
|
||||
if (page_map(LAPIC_ADDR, (size_t)lapic & PAGE_MASK, 1, PG_GLOBAL | PG_RW | PG_PCD)) {
|
||||
kprintf("Failed to map APIC to 0x%x\n", LAPIC_ADDR);
|
||||
goto out;
|
||||
} else {
|
||||
kprintf("Mapped APIC 0x%x to 0x%x\n", lapic, LAPIC_ADDR);
|
||||
vma_add(LAPIC_ADDR, LAPIC_ADDR + PAGE_SIZE, VMA_READ | VMA_WRITE);
|
||||
lapic = LAPIC_ADDR;
|
||||
}
|
||||
}
|
||||
|
||||
kprintf("Maximum LVT Entry: 0x%x\n", apic_lvt_entries());
|
||||
|
@ -592,8 +637,7 @@ extern atomic_int32_t current_boot_id;
|
|||
#if MAX_CORES > 1
|
||||
int smp_start(void)
|
||||
{
|
||||
if (has_x2apic()) // enable x2APIC support
|
||||
wrmsr(MSR_APIC_BASE, lapic | 0xD00);
|
||||
x2apic_enable();
|
||||
|
||||
// reset APIC and set id
|
||||
lapic_reset();
|
||||
|
@ -645,7 +689,7 @@ int ipi_tlb_flush(void)
|
|||
if (atomic_int32_read(&cpu_online) == 1)
|
||||
return 0;
|
||||
|
||||
if (BUILTIN_EXPECT(has_x2apic(), 1)) {
|
||||
if (has_x2apic()) {
|
||||
flags = irq_nested_disable();
|
||||
for(i=0; i<MAX_APIC_CORES; i++)
|
||||
{
|
||||
|
@ -703,26 +747,27 @@ int apic_send_ipi(uint64_t dest, uint8_t irq)
|
|||
uint32_t j;
|
||||
uint8_t flags;
|
||||
|
||||
if (BUILTIN_EXPECT(has_x2apic(), 1)) {
|
||||
if (has_x2apic()) {
|
||||
flags = irq_nested_disable();
|
||||
//kprintf("send IPI %d to %lld\n", (int)irq, dest);
|
||||
wrmsr(0x830, (dest << 32)|APIC_INT_ASSERT|APIC_DM_FIXED|irq);
|
||||
irq_nested_enable(flags);
|
||||
} else {
|
||||
if (lapic_read(APIC_ICR1) & APIC_ICR_BUSY) {
|
||||
kputs("ERROR: previous send not complete");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
flags = irq_nested_disable();
|
||||
|
||||
while (lapic_read(APIC_ICR1) & APIC_ICR_BUSY) {
|
||||
PAUSE;
|
||||
}
|
||||
|
||||
//kprintf("send IPI %d to %lld\n", (int)irq, dest);
|
||||
set_ipi_dest((uint32_t)dest);
|
||||
lapic_write(APIC_ICR1, APIC_INT_ASSERT|APIC_DM_FIXED|irq);
|
||||
|
||||
j = 0;
|
||||
while((lapic_read(APIC_ICR1) & APIC_ICR_BUSY) && (j < 1000))
|
||||
while((lapic_read(APIC_ICR1) & APIC_ICR_BUSY) && (j < 1000)) {
|
||||
j++; // wait for it to finish, give up eventualy tho
|
||||
PAUSE;
|
||||
}
|
||||
|
||||
irq_nested_enable(flags);
|
||||
}
|
||||
|
@ -735,19 +780,23 @@ static void apic_err_handler(struct state *s)
|
|||
kprintf("Got APIC error 0x%x\n", lapic_read(APIC_ESR));
|
||||
}
|
||||
|
||||
static void apic_shutdown(struct state *s)
|
||||
extern uint32_t disable_x2apic;
|
||||
|
||||
void shutdown_system(void)
|
||||
{
|
||||
int if_bootprocessor = (apic_processors[boot_processor]->id == apic_cpu_id());
|
||||
|
||||
irq_disable();
|
||||
|
||||
if (if_bootprocessor) {
|
||||
kprintf("Receive an IPI to shutdown HermitCore\n");
|
||||
kprintf("Try to shutdown HermitCore\n");
|
||||
|
||||
while(atomic_int32_read(&cpu_online) != 1)
|
||||
PAUSE;
|
||||
|
||||
network_shutdown();
|
||||
|
||||
kprintf("Diable APIC timer\n");
|
||||
kprintf("Disable APIC timer\n");
|
||||
}
|
||||
|
||||
apic_disable_timer();
|
||||
|
@ -757,16 +806,29 @@ static void apic_shutdown(struct state *s)
|
|||
|
||||
lapic_write(APIC_LVT_TSR, 0x10000); // disable thermal sensor interrupt
|
||||
lapic_write(APIC_LVT_PMC, 0x10000); // disable performance counter interrupt
|
||||
lapic_write(APIC_SVR, 0x00); // disable the apic
|
||||
lapic_write(APIC_SVR, 0x00); // disable the apic
|
||||
|
||||
// disable x2APIC
|
||||
if (if_bootprocessor && disable_x2apic)
|
||||
x2apic_disable();
|
||||
|
||||
if (if_bootprocessor)
|
||||
kprintf("System goes down...\n");
|
||||
flush_cache();
|
||||
atomic_int32_dec(&cpu_online);
|
||||
|
||||
HALT;
|
||||
kprintf("Ups, we should never reach this point!\n");
|
||||
while(1);
|
||||
while(1) {
|
||||
HALT;
|
||||
}
|
||||
}
|
||||
|
||||
volatile uint32_t go_down = 0;
|
||||
|
||||
static void apic_shutdown(struct state * s)
|
||||
{
|
||||
go_down = 1;
|
||||
|
||||
kputs("Receive shutdown interrupt\n");
|
||||
}
|
||||
|
||||
static void apic_lint0(struct state * s)
|
||||
|
|
|
@ -65,6 +65,7 @@ align 4
|
|||
global header_start_address
|
||||
global heap_size
|
||||
global header_size
|
||||
global disable_x2apic
|
||||
base dq 0
|
||||
limit dq 0
|
||||
cpu_freq dd 0
|
||||
|
@ -83,6 +84,7 @@ align 4
|
|||
possible_isles dd 1
|
||||
heap_start_address dq 0
|
||||
header_start_address dq 0
|
||||
disable_x2apic dd 1
|
||||
|
||||
; Bootstrap page tables are used during the initialization.
|
||||
align 4096
|
||||
|
|
|
@ -140,30 +140,8 @@ int timer_wait(unsigned int ticks)
|
|||
while(rdtsc() - start < 1000000) ; \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* Sets up the system clock by installing the timer handler
|
||||
* into IRQ0
|
||||
*/
|
||||
int timer_init(void)
|
||||
static int pit_init(void)
|
||||
{
|
||||
/*
|
||||
* Installs 'timer_handler' for the PIC and APIC timer,
|
||||
* only one handler will be later used.
|
||||
*/
|
||||
irq_install_handler(32, timer_handler);
|
||||
irq_install_handler(123, timer_handler);
|
||||
irq_install_handler(121, wakeup_handler);
|
||||
|
||||
#ifdef DYNAMIC_TICKS
|
||||
if (has_rdtscp())
|
||||
last_rdtsc = rdtscp(NULL);
|
||||
else
|
||||
last_rdtsc = rdtsc();
|
||||
#endif
|
||||
|
||||
if (cpu_freq) // do we need to configure the timer?
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* Port 0x43 is for initializing the PIT:
|
||||
*
|
||||
|
@ -189,3 +167,30 @@ int timer_init(void)
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Sets up the system clock by installing the timer handler
|
||||
* into IRQ0
|
||||
*/
|
||||
int timer_init(void)
|
||||
{
|
||||
/*
|
||||
* Installs 'timer_handler' for the PIC and APIC timer,
|
||||
* only one handler will be later used.
|
||||
*/
|
||||
irq_install_handler(32, timer_handler);
|
||||
irq_install_handler(123, timer_handler);
|
||||
irq_install_handler(121, wakeup_handler);
|
||||
|
||||
#ifdef DYNAMIC_TICKS
|
||||
if (has_rdtscp())
|
||||
last_rdtsc = rdtscp(NULL);
|
||||
else
|
||||
last_rdtsc = rdtsc();
|
||||
#endif
|
||||
|
||||
if (cpu_freq) // do we need to configure the timer?
|
||||
return 0;
|
||||
|
||||
return pit_init();
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue