1
0
Fork 0
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:
Stefan Lankes 2016-02-14 15:24:01 +01:00
parent 60fd64381d
commit 03551659d4
4 changed files with 119 additions and 48 deletions

View file

@ -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

View file

@ -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)

View file

@ -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

View file

@ -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();
}