diff --git a/aux/qemu_amd64.sh b/aux/qemu_amd64.sh index 7c5e62d..0d9ff52 100755 --- a/aux/qemu_amd64.sh +++ b/aux/qemu_amd64.sh @@ -1,3 +1,5 @@ #!/bin/sh -qemu-system-x86_64 -M q35 -m 4G -serial mon:stdio -enable-kvm -cdrom mop3.iso +set -x + +qemu-system-x86_64 -M q35 -m 4G -serial stdio -enable-kvm -cdrom mop3.iso $@ diff --git a/kernel/amd64/apic.c b/kernel/amd64/apic.c index ef5a6a4..c8aaba5 100644 --- a/kernel/amd64/apic.c +++ b/kernel/amd64/apic.c @@ -1,8 +1,11 @@ #include +#include +#include #include #include #include #include +#include #include #include #include @@ -11,12 +14,22 @@ #define IOAPICS_MAX 24 #define INTERRUPT_SRC_OVERRIDES_MAX 24 +#define LAPIC_ID 0x20 /* ID */ +#define LAPIC_EOI 0xB0 /* End of interrupt */ +#define LAPIC_SIVR 0xF0 /* Spurious interrupt vector register */ +#define LAPIC_ICR 0x300 +#define LAPIC_LVTTR 0x320 /* LVT timer register */ +#define LAPIC_TIMICT 0x380 /* Initial count register */ +#define LAPIC_TIMCCT 0x390 /* Current count register */ +#define LAPIC_DCR 0x3E0 /* Divide config register */ + static struct acpi_madt_ioapic apics[IOAPICS_MAX]; /* clang-format off */ static struct acpi_madt_interrupt_source_override intr_src_overrides[INTERRUPT_SRC_OVERRIDES_MAX]; /* clang-format on */ static size_t ioapic_entries = 0; static size_t intr_src_override_entries = 0; +static uintptr_t lapic_mmio_base = 0; extern void amd64_spin (void); @@ -37,13 +50,13 @@ static struct acpi_madt_ioapic* amd64_ioapic_find (uint8_t irq) { for (size_t i = 0; i < ioapic_entries; i++) { apic = &apics[i]; uint32_t version = amd64_ioapic_read ((uintptr_t)hhdm->offset + (uintptr_t)apic->address, 1); - uint32_t max = (version >> 16); + uint32_t max = ((version >> 16) & 0xFF); - if ((apic->gsi_base <= irq) && ((apic->gsi_base + max) > irq)) - break; + if ((irq >= apic->gsi_base) && (irq <= (apic->gsi_base + max))) + return apic; } - return apic; + return NULL; } void amd64_ioapic_route_irq (uint8_t vec, uint8_t irq, uint64_t flags, uint64_t lapic_id) { @@ -65,7 +78,12 @@ void amd64_ioapic_route_irq (uint8_t vec, uint8_t irq, uint64_t flags, uint64_t if (found_override) { uint8_t polarity = ((override->flags & 0x03) == 0x03) ? 1 : 0; uint8_t mode = (((override->flags >> 2) & 0x03) == 0x03) ? 1 : 0; - calc_flags = (lapic_id << 56) | (mode << 15) | (polarity << 14) | (vec & 0xFF) | flags; + calc_flags |= (uint64_t)mode << 15; + calc_flags |= (uint64_t)polarity << 13; + + calc_flags |= flags; + } else { + calc_flags |= flags; } apic = amd64_ioapic_find (irq); @@ -137,7 +155,7 @@ void amd64_ioapic_init (void) { struct acpi_madt_ioapic* ioapic = (struct acpi_madt_ioapic*)current; mm_map_kernel_page ((uintptr_t)ioapic->address, (uintptr_t)hhdm->offset + (uintptr_t)ioapic->address, - MM_PG_USER | MM_PG_RW); + MM_PG_PRESENT | MM_PG_RW); apics[ioapic_entries++] = *ioapic; } break; case ACPI_MADT_ENTRY_TYPE_INTERRUPT_SOURCE_OVERRIDE: { @@ -150,3 +168,60 @@ void amd64_ioapic_init (void) { current = (struct acpi_entry_hdr*)((uintptr_t)current + current->length); } } + +static uintptr_t amd64_lapic_base (void) { return lapic_mmio_base; } + +static void amd64_lapic_write (uint32_t reg, uint32_t value) { + *(volatile uint32_t*)(amd64_lapic_base () + reg) = value; +} + +static uint32_t amd64_lapic_read (uint32_t reg) { + return *(volatile uint32_t*)(amd64_lapic_base () + reg); +} + +uint32_t amd64_lapic_id (void) { return amd64_lapic_read (LAPIC_ID) >> 24; } + +void amd64_lapic_eoi (void) { amd64_lapic_write (LAPIC_EOI, 0); } + +void amd64_lapic_tick (uint32_t tick) { amd64_lapic_write (LAPIC_TIMICT, tick); } + +static uint32_t amd64_lapic_calibrate (uint32_t us) { + amd64_lapic_write (LAPIC_DCR, 0x03); + + amd64_lapic_write (LAPIC_LVTTR, 0x20 | (1 << 16)); + + amd64_lapic_write (LAPIC_TIMICT, 0xFFFFFFFF); + + sleep_micro (us); + + uint32_t ticks = 0xFFFFFFFF - amd64_lapic_read (LAPIC_TIMCCT); + + return ticks; +} + +static void amd64_lapic_start (uint32_t ticks) { + amd64_lapic_write (LAPIC_DCR, 0x03); + + amd64_lapic_write (LAPIC_LVTTR, 0x20 | (1 << 17)); + + amd64_lapic_write (LAPIC_TIMICT, ticks); +} + +uint64_t amd64_lapic_init (uint32_t us) { + struct limine_hhdm_response* hhdm = limine_hhdm_request.response; + + amd64_wrmsr (MSR_APIC_BASE, amd64_rdmsr (MSR_APIC_BASE) | (1 << 11)); + + uintptr_t lapic_paddr = amd64_rdmsr (MSR_APIC_BASE) & 0xFFFFF000; + lapic_mmio_base = lapic_paddr + (uintptr_t)hhdm->offset; + + mm_map_kernel_page (lapic_paddr, lapic_mmio_base, MM_PG_PRESENT | MM_PG_RW | MM_PD_LOCK); + + amd64_lapic_write (LAPIC_SIVR, 0xFF | (1 << 8)); + + uint32_t ticks = amd64_lapic_calibrate (us); + + amd64_lapic_start (ticks); + + return ticks; +} diff --git a/kernel/amd64/apic.h b/kernel/amd64/apic.h index 5af1eb6..1cdcfec 100644 --- a/kernel/amd64/apic.h +++ b/kernel/amd64/apic.h @@ -8,4 +8,9 @@ void amd64_ioapic_mask (uint8_t irq); void amd64_ioapic_unmask (uint8_t irq); void amd64_ioapic_init (void); +uint32_t amd64_lapic_id (void); +void amd64_lapic_tick (uint32_t tick); +void amd64_lapic_eoi (void); +uint64_t amd64_lapic_init (uint32_t us); + #endif // _KERNEL_AMD64_APIC_H diff --git a/kernel/amd64/bootmain.c b/kernel/amd64/bootmain.c index c8d8765..6567c76 100644 --- a/kernel/amd64/bootmain.c +++ b/kernel/amd64/bootmain.c @@ -1,13 +1,15 @@ #include +#include #include #include -#include #include +#include #include #include #include #include #include +#include #include #include @@ -15,8 +17,16 @@ ALIGNED (16) static uint8_t uacpi_memory_buffer[UACPI_MEMORY_BUFFER_MAX]; +void ack (void* arg) { + (void)arg; + debugprintf (". %u\n", thiscpu->id); +} + void bootmain (void) { - amd64_init (); + struct cpu* bsp_cpu = cpu_make (); + cpu_assign (bsp_cpu->id); + + amd64_init (bsp_cpu, false); amd64_debug_init (); pmm_init (); mm_init (); @@ -26,14 +36,11 @@ void bootmain (void) { amd64_ioapic_init (); amd64_hpet_init (); - /* int* a = malloc (sizeof (int)); */ - /* *a = 6969; */ - /* DEBUG ("a=%p, *a=%d\n", a, *a); */ + smp_init (); - for (size_t i = 0; i < 1000; i++) { - DEBUG ("i=%zu\n", i); - sleep_micro (1000000); - } + irq_attach (&ack, NULL, 32 + 0); + + __asm__ volatile ("sti"); for (;;) ; diff --git a/kernel/amd64/debug.c b/kernel/amd64/debug.c index 455c88e..4bb03cd 100644 --- a/kernel/amd64/debug.c +++ b/kernel/amd64/debug.c @@ -3,11 +3,14 @@ #include #include #include +#include #include #define PORT_COM1 0x03F8 #define BUFFER_SIZE 1024 +spin_lock_t serial_lock = SPIN_LOCK_INIT; + static bool amd64_debug_serial_tx_empty (void) { return (bool)(amd64_io_inb (PORT_COM1 + 5) & 0x20); } @@ -30,10 +33,15 @@ void debugprintf (const char* fmt, ...) { buffer[sizeof (buffer) - 1] = '\0'; const char* p = buffer; + + spin_lock (&serial_lock); + while (*p) { amd64_debug_serial_write (*p); p++; } + + spin_unlock (&serial_lock); } void amd64_debug_init (void) { diff --git a/kernel/amd64/flags.mk b/kernel/amd64/flags.mk index 707c344..07c4f10 100644 --- a/kernel/amd64/flags.mk +++ b/kernel/amd64/flags.mk @@ -1,6 +1,10 @@ cflags += --target=x86_64-pc-none-elf \ -mno-sse \ - -mno-avx + -mno-sse2 \ + -mno-avx \ + -mno-mmx \ + -mno-80387 \ + -mno-red-zone ldflags += --target=x86_64-pc-none-elf \ -Wl,-zmax-page-size=0x1000 diff --git a/kernel/amd64/gdt.h b/kernel/amd64/gdt.h new file mode 100644 index 0000000..e906119 --- /dev/null +++ b/kernel/amd64/gdt.h @@ -0,0 +1,29 @@ +#ifndef _KERNEL_AMD64_GDT_H +#define _KERNEL_AMD64_GDT_H + +#include +#include + +#define KSTACK_SIZE (16 * 1024) + +struct gdt_entry { + uint16_t limitlow; + uint16_t baselow; + uint8_t basemid; + uint8_t access; + uint8_t gran; + uint8_t basehigh; +} PACKED; + +struct gdt_ptr { + uint16_t limit; + uint64_t base; +} PACKED; + +struct gdt_extended { + struct gdt_entry old[5]; + struct gdt_entry tsslow; + struct gdt_entry tsshigh; +} PACKED; + +#endif // _KERNEL_AMD64_GDT_H diff --git a/kernel/amd64/init.c b/kernel/amd64/init.c index 16327bd..f135463 100644 --- a/kernel/amd64/init.c +++ b/kernel/amd64/init.c @@ -1,6 +1,6 @@ #include #include -#include +#include #include #include #include @@ -14,33 +14,6 @@ #define TSS 0x80 #define TSS_PRESENT 0x89 -#define KSTACK_SIZE (8 * 1024) - -struct gdt_entry { - uint16_t limitlow; - uint16_t baselow; - uint8_t basemid; - uint8_t access; - uint8_t gran; - uint8_t basehigh; -} PACKED; - -struct gdt_ptr { - uint16_t limit; - uint64_t base; -} PACKED; - -struct gdt_extended { - struct gdt_entry old[5]; - struct gdt_entry tsslow; - struct gdt_entry tsshigh; -} PACKED; - -ALIGNED (16) static volatile uint8_t kernel_stack[KSTACK_SIZE]; -ALIGNED (16) static volatile uint8_t except_stack[KSTACK_SIZE]; -ALIGNED (16) static volatile uint8_t irq_stack[KSTACK_SIZE]; -ALIGNED (16) static volatile struct gdt_extended gdt; - static void amd64_gdt_set (volatile struct gdt_entry* ent, uint32_t base, uint32_t limit, uint8_t acc, uint8_t gran) { ent->baselow = (base & 0xFFFF); @@ -51,39 +24,39 @@ static void amd64_gdt_set (volatile struct gdt_entry* ent, uint32_t base, uint32 ent->access = acc; } -static void amd64_gdt_init (void) { - volatile struct tss* tss = amd64_get_tss (); +static void amd64_gdt_init (struct cpu* cpu) { + volatile struct tss* tss = &cpu->tss; + volatile struct gdt_extended* gdt = &cpu->gdt; - memset ((void*)&gdt, 0, sizeof (gdt)); - memset ((void*)kernel_stack, 0, sizeof (kernel_stack)); + memset ((void*)gdt, 0, sizeof (*gdt)); memset ((void*)tss, 0, sizeof (*tss)); tss->iopb_off = sizeof (*tss); - tss->rsp0 = (uint64_t)((uintptr_t)kernel_stack + sizeof (kernel_stack)); - tss->ist[0] = (uint64_t)((uintptr_t)except_stack + sizeof (except_stack)); - tss->ist[1] = (uint64_t)((uintptr_t)irq_stack + sizeof (irq_stack)); + tss->rsp0 = (uint64_t)((uintptr_t)cpu->kernel_stack + sizeof (cpu->kernel_stack)); + tss->ist[0] = (uint64_t)((uintptr_t)cpu->except_stack + sizeof (cpu->except_stack)); + tss->ist[1] = (uint64_t)((uintptr_t)cpu->irq_stack + sizeof (cpu->irq_stack)); - uint64_t tssbase = (uint64_t)&tss; + uint64_t tssbase = (uint64_t)tss; uint64_t tsslimit = sizeof (*tss) - 1; - amd64_gdt_set (&gdt.old[0], 0, 0, 0, 0); - amd64_gdt_set (&gdt.old[1], 0, 0xFFFFF, 0x9A, 0xA0); - amd64_gdt_set (&gdt.old[2], 0, 0xFFFFF, 0x92, 0xC0); - amd64_gdt_set (&gdt.old[3], 0, 0xFFFFF, 0xFA, 0xA0); - amd64_gdt_set (&gdt.old[4], 0, 0xFFFFF, 0xF2, 0xC0); - amd64_gdt_set (&gdt.tsslow, (tssbase & 0xFFFFFFFF), tsslimit, TSS_PRESENT | TSS, 0); + amd64_gdt_set (&gdt->old[0], 0, 0, 0, 0); + amd64_gdt_set (&gdt->old[1], 0, 0xFFFFF, 0x9A, 0xA0); + amd64_gdt_set (&gdt->old[2], 0, 0xFFFFF, 0x92, 0xC0); + amd64_gdt_set (&gdt->old[3], 0, 0xFFFFF, 0xFA, 0xA0); + amd64_gdt_set (&gdt->old[4], 0, 0xFFFFF, 0xF2, 0xC0); + amd64_gdt_set (&gdt->tsslow, (tssbase & 0xFFFFFFFF), tsslimit, TSS_PRESENT | TSS, 0); uint32_t tssbasehigh = (tssbase >> 32); - gdt.tsshigh.limitlow = (tssbasehigh & 0xFFFF); - gdt.tsshigh.baselow = (tssbasehigh >> 16) & 0xFFFF; - gdt.tsshigh.basemid = 0; - gdt.tsshigh.basehigh = 0; - gdt.tsshigh.access = 0; - gdt.tsshigh.gran = 0; + gdt->tsshigh.limitlow = (tssbasehigh & 0xFFFF); + gdt->tsshigh.baselow = (tssbasehigh >> 16) & 0xFFFF; + gdt->tsshigh.basemid = 0; + gdt->tsshigh.basehigh = 0; + gdt->tsshigh.access = 0; + gdt->tsshigh.gran = 0; struct gdt_ptr gdtr; - gdtr.limit = sizeof (gdt) - 1; - gdtr.base = (uint64_t)&gdt; + gdtr.limit = sizeof (*gdt) - 1; + gdtr.base = (uint64_t)gdt; __asm__ volatile ("lgdt %0" ::"m"(gdtr) : "memory"); __asm__ volatile ("pushq %[kcode]\n" @@ -102,7 +75,10 @@ static void amd64_gdt_init (void) { __asm__ volatile ("ltr %0" ::"r"((uint16_t)GDT_TSS)); } -void amd64_init (void) { - amd64_gdt_init (); - amd64_intr_init (); +void amd64_init (struct cpu* cpu, bool load_idt) { + amd64_gdt_init (cpu); + if (load_idt) + amd64_load_idt (); + else + amd64_intr_init (); } diff --git a/kernel/amd64/init.h b/kernel/amd64/init.h index e58f580..97225d1 100644 --- a/kernel/amd64/init.h +++ b/kernel/amd64/init.h @@ -1,6 +1,8 @@ #ifndef _KERNEL_AMD64_INIT_H #define _KERNEL_AMD64_INIT_H -void amd64_init (void); +#include + +void amd64_init (struct cpu* cpu, bool load_idt); #endif // _KERNEL_AMD64_INIT_H diff --git a/kernel/amd64/intr.c b/kernel/amd64/intr.c index 8856f1c..51de923 100644 --- a/kernel/amd64/intr.c +++ b/kernel/amd64/intr.c @@ -1,9 +1,13 @@ +#include #include #include #include +#include #include #include #include +#include +#include /* 8259 PIC defs. */ #define PIC1 0x20 @@ -77,20 +81,23 @@ static void amd64_init_pic (void) { #undef IO_OP } -static void amd64_idt_set (volatile struct idt_entry* ent, uint64_t handler, uint8_t flags, uint8_t ist) { +static void amd64_idt_set (volatile struct idt_entry* ent, uint64_t handler, uint8_t flags, + uint8_t ist) { ent->intrlow = (handler & 0xFFFF); ent->kernel_cs = 0x08; // GDT_KCODE (init.c) - ent->ist = 0; + ent->ist = ist; ent->attrs = flags; ent->intrmid = ((handler >> 16) & 0xFFFF); ent->intrhigh = ((handler >> 32) & 0xFFFFFFFF); ent->resv = 0; } +void amd64_load_idt (void) { __asm__ volatile ("lidt %0" ::"m"(idt)); } + static void amd64_idt_init (void) { memset ((void*)idt_entries, 0, sizeof (idt_entries)); -#define IDT_ENTRY(n, ist) \ +#define IDT_ENTRY(n, ist) \ extern void amd64_intr##n (void); \ amd64_idt_set (&idt_entries[(n)], (uint64_t)&amd64_intr##n, 0x8E, (ist)) IDT_ENTRY (0, 0); @@ -146,8 +153,7 @@ static void amd64_idt_init (void) { idt.limit = sizeof (idt_entries) - 1; idt.base = (uint64_t)idt_entries; - __asm__ volatile ("lidt %0" ::"m"(idt)); - __asm__ volatile ("sti"); + amd64_load_idt (); } static void amd64_intr_exception (struct saved_regs* regs) { @@ -179,6 +185,14 @@ void amd64_intr_handler (void* stack_ptr) { if (regs->trap <= 31) { amd64_intr_exception (regs); + } else if (regs->trap >= 32) { + amd64_lapic_eoi (); + + __asm__ volatile ("sti"); + + irq_invoke_each (regs->trap); + + __asm__ volatile ("cli"); } else { DEBUG ("unknown trap %lu\n", regs->trap); } @@ -188,3 +202,36 @@ void amd64_intr_init (void) { amd64_init_pic (); amd64_idt_init (); } + +/* Aux. */ + +static uint64_t amd64_irq_save_flags (void) { + uint64_t rflags; + __asm__ volatile ("pushfq; cli; popq %0" : "=r"(rflags)::"memory", "cc"); + return rflags; +} + +static void amd64_irq_restore_flags (uint64_t rflags) { + if (rflags & (1ULL << 9)) + __asm__ volatile ("sti"); +} + +void irq_save (void) { + /* before smp init. */ + if (thiscpu == NULL) + return; + + int prev = atomic_fetch_add_explicit (&thiscpu->irq_ctx.nesting, 1, memory_order_acq_rel); + if (prev == 0) + thiscpu->irq_ctx.rflags = amd64_irq_save_flags (); +} + +void irq_restore (void) { + /* before smp init. */ + if (thiscpu == NULL) + return; + + int prev = atomic_fetch_sub_explicit (&thiscpu->irq_ctx.nesting, 1, memory_order_acq_rel); + if (prev == 1) + amd64_irq_restore_flags (thiscpu->irq_ctx.rflags); +} diff --git a/kernel/amd64/intr.h b/kernel/amd64/intr.h index db7e3f2..5717a7a 100644 --- a/kernel/amd64/intr.h +++ b/kernel/amd64/intr.h @@ -31,6 +31,7 @@ struct saved_regs { uint64_t ss; } PACKED; +void amd64_load_idt (void); void amd64_intr_init (void); #endif // _KERNEL_AMD64_INTR_H diff --git a/kernel/amd64/intr_stub.S b/kernel/amd64/intr_stub.S index 2885727..c7222da 100644 --- a/kernel/amd64/intr_stub.S +++ b/kernel/amd64/intr_stub.S @@ -1,8 +1,5 @@ .extern amd64_intr_handler -dupa: - jmp dupa - #define err(z) \ pushq $z; @@ -36,7 +33,7 @@ dupa: popq %r10; \ popq %r9; \ popq %r8; \ - pushq %rbx; \ + popq %rbx; \ popq %rbp; \ popq %rdi; \ popq %rsi; \ @@ -52,9 +49,12 @@ dupa: push_regs; \ cld; \ movq %rsp, %rdi; \ + movq %rsp, %rax; \ + subq $8, %rsp; \ andq $~0xF, %rsp; \ + movq %rax, (%rsp); \ callq amd64_intr_handler; \ - movq %rdi, %rsp; \ + movq (%rsp), %rsp; \ pop_regs; \ addq $16, %rsp; \ iretq; diff --git a/kernel/amd64/mm.c b/kernel/amd64/mm.c index bbddd17..3031e58 100644 --- a/kernel/amd64/mm.c +++ b/kernel/amd64/mm.c @@ -24,6 +24,10 @@ static uintptr_t amd64_current_cr3 (void) { return cr3; } +void amd64_load_kernel_cr3 (void) { + __asm__ volatile ("movq %0, %%cr3" ::"r"(kernel_pd.cr3_paddr) : "memory"); +} + static struct pg_index amd64_mm_page_index (uint64_t vaddr) { struct pg_index ret; diff --git a/kernel/amd64/mm.h b/kernel/amd64/mm.h index 11ec58b..24f01ff 100644 --- a/kernel/amd64/mm.h +++ b/kernel/amd64/mm.h @@ -11,4 +11,6 @@ struct pd { uintptr_t cr3_paddr; }; +void amd64_load_kernel_cr3 (void); + #endif // _KERNEL_AMD64_MM_H diff --git a/kernel/amd64/msr-index.h b/kernel/amd64/msr-index.h new file mode 100644 index 0000000..afe8875 --- /dev/null +++ b/kernel/amd64/msr-index.h @@ -0,0 +1,1093 @@ +#ifndef __ASM_MSR_INDEX_H +#define __ASM_MSR_INDEX_H + +/* +Valid-License-Identifier: GPL-2.0-only +Valid-License-Identifier: GPL-2.0-or-later + +SPDX-URL: https://spdx.org/licenses/GPL-2.0-only.html +SPDX-URL: https://spdx.org/licenses/GPL-2.0-or-later.html + +Deprecated-Identifier: GPL-2.0 +Deprecated-Identifier: GPL-2.0+ + +Usage-Guide: + + To use this license in source code, put one of the following SPDX + tag/value pairs into a comment according to the placement + guidelines in the licensing rules documentation. + + For 'GNU General Public License (GPL) version 2 only' use: + SPDX-License-Identifier: GPL-2.0-only + + For 'GNU General Public License (GPL) version 2 or any later version' use: + SPDX-License-Identifier: GPL-2.0-or-later + + The deprecated tags should not be used for any new additions. Where + possible, their existing uses should be phased out. + +License-Text: + + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. +*/ + +/* + * CPU model specific register (MSR) numbers + * + * Definitions for an MSR should follow this style: + * + * #define MSR_$NAME 0x$INDEX + * #define $NAME_$FIELD1 (_AC($X, ULL) << $POS1) + * #define $NAME_$FIELD2 (_AC($Y, ULL) << $POS2) + * + * Blocks of related constants should be sorted by MSR index. The constant + * names should be as concise as possible, and the bit names may have an + * abbreviated name. Exceptions will be considered on a case-by-case basis. + */ + +#define _AC(X, Y) (X##Y) + +#define MSR_P5_MC_ADDR 0 +#define MSR_P5_MC_TYPE 0x00000001 + +#define MSR_APIC_BASE 0x0000001b +#define APIC_BASE_BSP (_AC (1, ULL) << 8) +#define APIC_BASE_EXTD (_AC (1, ULL) << 10) +#define APIC_BASE_ENABLE (_AC (1, ULL) << 11) +#define APIC_BASE_ADDR_MASK _AC (0x000ffffffffff000, ULL) + +#define MSR_TEST_CTRL 0x00000033 +#define TEST_CTRL_SPLITLOCK_DETECT (_AC (1, ULL) << 29) +#define TEST_CTRL_SPLITLOCK_DISABLE (_AC (1, ULL) << 31) + +#define MSR_INTEL_CORE_THREAD_COUNT 0x00000035 +#define MSR_CTC_THREAD_MASK 0x0000ffff +#define MSR_CTC_CORE_MASK _AC (0xffff0000, U) + +#define MSR_SPEC_CTRL 0x00000048 +#define SPEC_CTRL_IBRS (_AC (1, ULL) << 0) +#define SPEC_CTRL_STIBP (_AC (1, ULL) << 1) +#define SPEC_CTRL_SSBD (_AC (1, ULL) << 2) +#define SPEC_CTRL_IPRED_DIS_U (_AC (1, ULL) << 3) +#define SPEC_CTRL_IPRED_DIS_S (_AC (1, ULL) << 4) +#define SPEC_CTRL_RRSBA_DIS_U (_AC (1, ULL) << 5) +#define SPEC_CTRL_RRSBA_DIS_S (_AC (1, ULL) << 6) +#define SPEC_CTRL_PSFD (_AC (1, ULL) << 7) +#define SPEC_CTRL_DDP_DIS_U (_AC (1, ULL) << 8) +#define SPEC_CTRL_BHI_DIS_S (_AC (1, ULL) << 10) + +#define MSR_PRED_CMD 0x00000049 +#define PRED_CMD_IBPB (_AC (1, ULL) << 0) +#define PRED_CMD_SBPB (_AC (1, ULL) << 7) + +#define MSR_PPIN_CTL 0x0000004e +#define PPIN_LOCKOUT (_AC (1, ULL) << 0) +#define PPIN_ENABLE (_AC (1, ULL) << 1) +#define MSR_PPIN 0x0000004f + +#define MSR_MISC_PACKAGE_CTRL 0x000000bc +#define PGK_CTRL_ENERGY_FILTER_EN (_AC (1, ULL) << 0) + +#define MSR_PB_OPT_CTRL 0x000000bf +#define PB_OPT_IBPB_ALT (_AC (1, ULL) << 0) + +#define MSR_CORE_CAPABILITIES 0x000000cf +#define CORE_CAPS_SPLITLOCK_DETECT (_AC (1, ULL) << 5) + +#define MSR_PKG_CST_CONFIG_CONTROL 0x000000e2 +#define NHM_C3_AUTO_DEMOTE (_AC (1, ULL) << 25) +#define NHM_C1_AUTO_DEMOTE (_AC (1, ULL) << 26) +#define ATM_LNC_C6_AUTO_DEMOTE (_AC (1, ULL) << 25) +#define SNB_C3_AUTO_UNDEMOTE (_AC (1, ULL) << 27) +#define SNB_C1_AUTO_UNDEMOTE (_AC (1, ULL) << 28) + +#define MSR_ARCH_CAPABILITIES 0x0000010a +#define ARCH_CAPS_RDCL_NO (_AC (1, ULL) << 0) +#define ARCH_CAPS_EIBRS (_AC (1, ULL) << 1) +#define ARCH_CAPS_RSBA (_AC (1, ULL) << 2) +#define ARCH_CAPS_SKIP_L1DFL (_AC (1, ULL) << 3) +#define ARCH_CAPS_SSB_NO (_AC (1, ULL) << 4) +#define ARCH_CAPS_MDS_NO (_AC (1, ULL) << 5) +#define ARCH_CAPS_IF_PSCHANGE_MC_NO (_AC (1, ULL) << 6) +#define ARCH_CAPS_TSX_CTRL (_AC (1, ULL) << 7) +#define ARCH_CAPS_TAA_NO (_AC (1, ULL) << 8) +#define ARCH_CAPS_MISC_PACKAGE_CTRL (_AC (1, ULL) << 10) +#define ARCH_CAPS_ENERGY_FILTERING (_AC (1, ULL) << 11) +#define ARCH_CAPS_DOITM (_AC (1, ULL) << 12) +#define ARCH_CAPS_SBDR_SSDP_NO (_AC (1, ULL) << 13) +#define ARCH_CAPS_FBSDP_NO (_AC (1, ULL) << 14) +#define ARCH_CAPS_PSDP_NO (_AC (1, ULL) << 15) +#define ARCH_CAPS_FB_CLEAR (_AC (1, ULL) << 17) +#define ARCH_CAPS_FB_CLEAR_CTRL (_AC (1, ULL) << 18) +#define ARCH_CAPS_RRSBA (_AC (1, ULL) << 19) +#define ARCH_CAPS_BHI_NO (_AC (1, ULL) << 20) +#define ARCH_CAPS_PBRSB_NO (_AC (1, ULL) << 24) +#define ARCH_CAPS_GDS_CTRL (_AC (1, ULL) << 25) +#define ARCH_CAPS_GDS_NO (_AC (1, ULL) << 26) +#define ARCH_CAPS_RFDS_NO (_AC (1, ULL) << 27) +#define ARCH_CAPS_RFDS_CLEAR (_AC (1, ULL) << 28) + +#define MSR_FLUSH_CMD 0x0000010b +#define FLUSH_CMD_L1D (_AC (1, ULL) << 0) + +#define MSR_TSX_FORCE_ABORT 0x0000010f +#define TSX_FORCE_ABORT_RTM (_AC (1, ULL) << 0) +#define TSX_CPUID_CLEAR (_AC (1, ULL) << 1) +#define TSX_ENABLE_RTM (_AC (1, ULL) << 2) + +#define MSR_TSX_CTRL 0x00000122 +#define TSX_CTRL_RTM_DISABLE (_AC (1, ULL) << 0) +#define TSX_CTRL_CPUID_CLEAR (_AC (1, ULL) << 1) + +#define MSR_MCU_OPT_CTRL 0x00000123 +#define MCU_OPT_CTRL_RNGDS_MITG_DIS (_AC (1, ULL) << 0) +#define MCU_OPT_CTRL_RTM_ALLOW (_AC (1, ULL) << 1) +#define MCU_OPT_CTRL_RTM_LOCKED (_AC (1, ULL) << 2) +#define MCU_OPT_CTRL_FB_CLEAR_DIS (_AC (1, ULL) << 3) +#define MCU_OPT_CTRL_GDS_MIT_DIS (_AC (1, ULL) << 4) +#define MCU_OPT_CTRL_GDS_MIT_LOCK (_AC (1, ULL) << 5) + +#define MSR_FRED_RSP_SL0 0x000001cc +#define MSR_FRED_RSP_SL1 0x000001cd +#define MSR_FRED_RSP_SL2 0x000001ce +#define MSR_FRED_RSP_SL3 0x000001cf +#define MSR_FRED_STK_LVLS 0x000001d0 +#define MSR_FRED_SSP_SL0 MSR_PL0_SSP +#define MSR_FRED_SSP_SL1 0x000001d1 +#define MSR_FRED_SSP_SL2 0x000001d2 +#define MSR_FRED_SSP_SL3 0x000001d3 +#define MSR_FRED_CONFIG 0x000001d4 + +#define MSR_RTIT_OUTPUT_BASE 0x00000560 +#define MSR_RTIT_OUTPUT_MASK 0x00000561 +#define MSR_RTIT_CTL 0x00000570 +#define RTIT_CTL_TRACE_EN (_AC (1, ULL) << 0) +#define RTIT_CTL_CYC_EN (_AC (1, ULL) << 1) +#define RTIT_CTL_OS (_AC (1, ULL) << 2) +#define RTIT_CTL_USR (_AC (1, ULL) << 3) +#define RTIT_CTL_PWR_EVT_EN (_AC (1, ULL) << 4) +#define RTIT_CTL_FUP_ON_PTW (_AC (1, ULL) << 5) +#define RTIT_CTL_FABRIC_EN (_AC (1, ULL) << 6) +#define RTIT_CTL_CR3_FILTER (_AC (1, ULL) << 7) +#define RTIT_CTL_TOPA (_AC (1, ULL) << 8) +#define RTIT_CTL_MTC_EN (_AC (1, ULL) << 9) +#define RTIT_CTL_TSC_EN (_AC (1, ULL) << 10) +#define RTIT_CTL_DIS_RETC (_AC (1, ULL) << 11) +#define RTIT_CTL_PTW_EN (_AC (1, ULL) << 12) +#define RTIT_CTL_BRANCH_EN (_AC (1, ULL) << 13) +#define RTIT_CTL_MTC_FREQ (_AC (0xf, ULL) << 14) +#define RTIT_CTL_CYC_THRESH (_AC (0xf, ULL) << 19) +#define RTIT_CTL_PSB_FREQ (_AC (0xf, ULL) << 24) +#define RTIT_CTL_ADDR(n) (_AC (0xf, ULL) << (32 + 4 * (n))) +#define MSR_RTIT_STATUS 0x00000571 +#define RTIT_STATUS_FILTER_EN (_AC (1, ULL) << 0) +#define RTIT_STATUS_CONTEXT_EN (_AC (1, ULL) << 1) +#define RTIT_STATUS_TRIGGER_EN (_AC (1, ULL) << 2) +#define RTIT_STATUS_ERROR (_AC (1, ULL) << 4) +#define RTIT_STATUS_STOPPED (_AC (1, ULL) << 5) +#define RTIT_STATUS_BYTECNT (_AC (0x1ffff, ULL) << 32) +#define MSR_RTIT_CR3_MATCH 0x00000572 +#define MSR_RTIT_ADDR_A(n) (0x00000580 + (n) * 2) +#define MSR_RTIT_ADDR_B(n) (0x00000581 + (n) * 2) + +#define MSR_U_CET 0x000006a0 +#define MSR_S_CET 0x000006a2 +#define CET_SHSTK_EN (_AC (1, ULL) << 0) +#define CET_WRSS_EN (_AC (1, ULL) << 1) +#define CET_ENDBR_EN (_AC (1, ULL) << 2) + +#define MSR_PL0_SSP 0x000006a4 +#define MSR_PL1_SSP 0x000006a5 +#define MSR_PL2_SSP 0x000006a6 +#define MSR_PL3_SSP 0x000006a7 +#define MSR_ISST 0x000006a8 + +#define MSR_PKRS 0x000006e1 + +#define MSR_PM_ENABLE 0x00000770 +#define PM_ENABLE_HWP_ENABLE BIT (0, ULL) + +#define MSR_HWP_CAPABILITIES 0x00000771 +#define MSR_HWP_INTERRUPT 0x00000773 +#define MSR_HWP_REQUEST 0x00000774 +#define MSR_HWP_STATUS 0x00000777 + +#define MSR_X2APIC_FIRST 0x00000800 +#define MSR_X2APIC_LAST 0x000008ff + +#define MSR_X2APIC_TPR 0x00000808 +#define MSR_X2APIC_PPR 0x0000080a +#define MSR_X2APIC_EOI 0x0000080b +#define MSR_X2APIC_TMICT 0x00000838 +#define MSR_X2APIC_TMCCT 0x00000839 +#define MSR_X2APIC_SELF 0x0000083f + +#define MSR_PASID 0x00000d93 +#define PASID_PASID_MASK 0x000fffff +#define PASID_VALID (_AC (1, ULL) << 31) + +#define MSR_PKG_HDC_CTL 0x00000db0 +#define PKG_HDC_CTL_HDC_PKG_ENABLE BIT (0, ULL) +#define MSR_PM_CTL1 0x00000db1 +#define PM_CTL1_HDC_ALLOW_BLOCK BIT (0, ULL) + +#define MSR_MCU_CONTROL 0x00001406 +#define MCU_CONTROL_LOCK (_AC (1, ULL) << 0) +#define MCU_CONTROL_DIS_MCU_LOAD (_AC (1, ULL) << 1) +#define MCU_CONTROL_EN_SMM_BYPASS (_AC (1, ULL) << 2) + +#define MSR_UARCH_MISC_CTRL 0x00001b01 +#define UARCH_CTRL_DOITM (_AC (1, ULL) << 0) + +#define MSR_EFER _AC (0xc0000080, U) /* Extended Feature Enable Register */ +#define EFER_SCE (_AC (1, ULL) << 0) /* SYSCALL Enable */ +#define EFER_LME (_AC (1, ULL) << 8) /* Long Mode Enable */ +#define EFER_LMA (_AC (1, ULL) << 10) /* Long Mode Active */ +#define EFER_NXE (_AC (1, ULL) << 11) /* No Execute Enable */ +#define EFER_SVME (_AC (1, ULL) << 12) /* Secure Virtual Machine Enable */ +#define EFER_FFXSE (_AC (1, ULL) << 14) /* Fast FXSAVE/FXRSTOR */ +#define EFER_AIBRSE (_AC (1, ULL) << 21) /* Automatic IBRS Enable */ + +#define EFER_KNOWN_MASK \ + (EFER_SCE | EFER_LME | EFER_LMA | EFER_NXE | EFER_SVME | EFER_FFXSE | EFER_AIBRSE) + +#define MSR_STAR _AC (0xc0000081, U) /* legacy mode SYSCALL target */ +#define MSR_LSTAR _AC (0xc0000082, U) /* long mode SYSCALL target */ +#define MSR_CSTAR _AC (0xc0000083, U) /* compat mode SYSCALL target */ +#define MSR_SYSCALL_MASK _AC (0xc0000084, U) /* EFLAGS mask for syscall */ +#define MSR_FS_BASE _AC (0xc0000100, U) /* 64bit FS base */ +#define MSR_GS_BASE _AC (0xc0000101, U) /* 64bit GS base */ +#define MSR_SHADOW_GS_BASE _AC (0xc0000102, U) /* SwapGS GS shadow */ +#define MSR_TSC_AUX _AC (0xc0000103, U) /* Auxiliary TSC */ + +#define MSR_K8_SYSCFG _AC (0xc0010010, U) +#define SYSCFG_MTRR_FIX_DRAM_EN (_AC (1, ULL) << 18) +#define SYSCFG_MTRR_FIX_DRAM_MOD_EN (_AC (1, ULL) << 19) +#define SYSCFG_MTRR_VAR_DRAM_EN (_AC (1, ULL) << 20) +#define SYSCFG_MTRR_TOM2_EN (_AC (1, ULL) << 21) +#define SYSCFG_TOM2_FORCE_WB (_AC (1, ULL) << 22) + +#define MSR_K8_IORR_BASE0 _AC (0xc0010016, U) +#define MSR_K8_IORR_MASK0 _AC (0xc0010017, U) +#define MSR_K8_IORR_BASE1 _AC (0xc0010018, U) +#define MSR_K8_IORR_MASK1 _AC (0xc0010019, U) + +#define MSR_K8_TSEG_BASE _AC (0xc0010112, U) /* AMD doc: SMMAddr */ +#define MSR_K8_TSEG_MASK _AC (0xc0010113, U) /* AMD doc: SMMMask */ + +#define MSR_K8_VM_CR _AC (0xc0010114, U) +#define VM_CR_INIT_REDIRECTION (_AC (1, ULL) << 1) +#define VM_CR_SVM_DISABLE (_AC (1, ULL) << 4) + +#define MSR_VIRT_SPEC_CTRL _AC (0xc001011f, U) /* Layout matches MSR_SPEC_CTRL */ + +#define MSR_AMD_CSTATE_CFG 0xc0010296U + +#define MSR_AMD_CPPC_CAP1 0xc00102b0U +#define MSR_AMD_CPPC_ENABLE 0xc00102b1U +#define AMD_CPPC_ENABLE (_AC (1, ULL) << 0) +#define MSR_AMD_CPPC_REQ 0xc00102b3U +#define AMD_CPPC_EPP_MASK (_AC (0xff, ULL) << 24) + +/* + * Legacy MSR constants in need of cleanup. No new MSRs below this comment. + */ + +/* Intel MSRs. Some also available on other CPUs */ +#define MSR_IA32_PERFCTR0 0x000000c1 +#define MSR_IA32_A_PERFCTR0 0x000004c1 +#define MSR_FSB_FREQ 0x000000cd + +#define MSR_MTRRcap 0x000000fe +#define MTRRcap_VCNT 0x000000ff + +#define MSR_IA32_BBL_CR_CTL 0x00000119 + +#define MSR_IA32_SYSENTER_CS 0x00000174 +#define MSR_IA32_SYSENTER_ESP 0x00000175 +#define MSR_IA32_SYSENTER_EIP 0x00000176 + +#define MSR_IA32_MCG_CAP 0x00000179 +#define MSR_IA32_MCG_STATUS 0x0000017a +#define MSR_IA32_MCG_CTL 0x0000017b +#define MSR_IA32_MCG_EXT_CTL 0x000004d0 + +#define MSR_IA32_PEBS_ENABLE 0x000003f1 +#define MSR_IA32_DS_AREA 0x00000600 +#define MSR_IA32_PERF_CAPABILITIES 0x00000345 +/* Lower 6 bits define the format of the address in the LBR stack */ +#define MSR_IA32_PERF_CAP_LBR_FORMAT 0x3f + +#define MSR_IA32_BNDCFGS 0x00000d90 +#define IA32_BNDCFGS_ENABLE 0x00000001 +#define IA32_BNDCFGS_PRESERVE 0x00000002 +#define IA32_BNDCFGS_RESERVED 0x00000ffc + +#define MSR_IA32_XSS 0x00000da0 + +#define MSR_MTRRfix64K_00000 0x00000250 +#define MSR_MTRRfix16K_80000 0x00000258 +#define MSR_MTRRfix16K_A0000 0x00000259 +#define MSR_MTRRfix4K_C0000 0x00000268 +#define MSR_MTRRfix4K_C8000 0x00000269 +#define MSR_MTRRfix4K_D0000 0x0000026a +#define MSR_MTRRfix4K_D8000 0x0000026b +#define MSR_MTRRfix4K_E0000 0x0000026c +#define MSR_MTRRfix4K_E8000 0x0000026d +#define MSR_MTRRfix4K_F0000 0x0000026e +#define MSR_MTRRfix4K_F8000 0x0000026f +#define MSR_MTRRdefType 0x000002ff +#define MTRRdefType_FE (1u << 10) +#define MTRRdefType_E (1u << 11) + +#define MSR_IA32_DEBUGCTLMSR 0x000001d9 +#define IA32_DEBUGCTLMSR_LBR (1 << 0) /* Last Branch Record */ +#define IA32_DEBUGCTLMSR_BTF (1 << 1) /* Single Step on Branches */ +#define IA32_DEBUGCTLMSR_TR (1 << 6) /* Trace Message Enable */ +#define IA32_DEBUGCTLMSR_BTS (1 << 7) /* Branch Trace Store */ +#define IA32_DEBUGCTLMSR_BTINT (1 << 8) /* Branch Trace Interrupt */ +#define IA32_DEBUGCTLMSR_BTS_OFF_OS (1 << 9) /* BTS off if CPL 0 */ +#define IA32_DEBUGCTLMSR_BTS_OFF_USR (1 << 10) /* BTS off if CPL > 0 */ +#define IA32_DEBUGCTLMSR_RTM (1 << 15) /* RTM debugging enable */ + +#define MSR_IA32_LASTBRANCHFROMIP 0x000001db +#define MSR_IA32_LASTBRANCHTOIP 0x000001dc +#define MSR_IA32_LASTINTFROMIP 0x000001dd +#define MSR_IA32_LASTINTTOIP 0x000001de + +#define MSR_IA32_POWER_CTL 0x000001fc + +#define MSR_IA32_MTRR_PHYSBASE(n) (0x00000200 + 2 * (n)) +#define MSR_IA32_MTRR_PHYSMASK(n) (0x00000201 + 2 * (n)) + +#define MSR_IA32_CR_PAT 0x00000277 +#define MSR_IA32_CR_PAT_RESET 0x0007040600070406ULL + +#define MSR_IA32_MC0_CTL 0x00000400 +#define MSR_IA32_MC0_STATUS 0x00000401 +#define MSR_IA32_MC0_ADDR 0x00000402 +#define MSR_IA32_MC0_MISC 0x00000403 +#define MSR_IA32_MC0_CTL2 0x00000280 +#define CMCI_EN (1UL << 30) +#define CMCI_THRESHOLD_MASK 0x7FFF + +#define MSR_AMD64_MC0_MASK 0xc0010044U + +#define MSR_IA32_MCx_CTL(x) (MSR_IA32_MC0_CTL + 4 * (x)) +#define MSR_IA32_MCx_STATUS(x) (MSR_IA32_MC0_STATUS + 4 * (x)) +#define MSR_IA32_MCx_ADDR(x) (MSR_IA32_MC0_ADDR + 4 * (x)) +#define MSR_IA32_MCx_MISC(x) (MSR_IA32_MC0_MISC + 4 * (x)) +#define MSR_IA32_MCx_CTL2(x) (MSR_IA32_MC0_CTL2 + (x)) + +#define MSR_AMD64_MCx_MASK(x) (MSR_AMD64_MC0_MASK + (x)) + +/* MSRs & bits used for VMX enabling */ +#define MSR_IA32_VMX_BASIC 0x480 +#define MSR_IA32_VMX_PINBASED_CTLS 0x481 +#define MSR_IA32_VMX_PROCBASED_CTLS 0x482 +#define MSR_IA32_VMX_EXIT_CTLS 0x483 +#define MSR_IA32_VMX_ENTRY_CTLS 0x484 +#define MSR_IA32_VMX_MISC 0x485 +#define MSR_IA32_VMX_CR0_FIXED0 0x486 +#define MSR_IA32_VMX_CR0_FIXED1 0x487 +#define MSR_IA32_VMX_CR4_FIXED0 0x488 +#define MSR_IA32_VMX_CR4_FIXED1 0x489 +#define MSR_IA32_VMX_VMCS_ENUM 0x48a +#define MSR_IA32_VMX_PROCBASED_CTLS2 0x48b +#define MSR_IA32_VMX_EPT_VPID_CAP 0x48c +#define MSR_IA32_VMX_TRUE_PINBASED_CTLS 0x48d +#define MSR_IA32_VMX_TRUE_PROCBASED_CTLS 0x48e +#define MSR_IA32_VMX_TRUE_EXIT_CTLS 0x48f +#define MSR_IA32_VMX_TRUE_ENTRY_CTLS 0x490 +#define MSR_IA32_VMX_VMFUNC 0x491 +#define MSR_IA32_VMX_PROCBASED_CTLS3 0x492 + +/* K7/K8 MSRs. Not complete. See the architecture manual for a more + complete list. */ +#define MSR_K7_EVNTSEL0 0xc0010000U +#define MSR_K7_PERFCTR0 0xc0010004U +#define MSR_K7_EVNTSEL1 0xc0010001U +#define MSR_K7_PERFCTR1 0xc0010005U +#define MSR_K7_EVNTSEL2 0xc0010002U +#define MSR_K7_PERFCTR2 0xc0010006U +#define MSR_K7_EVNTSEL3 0xc0010003U +#define MSR_K7_PERFCTR3 0xc0010007U +#define MSR_K8_TOP_MEM1 0xc001001aU +#define MSR_K8_TOP_MEM2 0xc001001dU + +#define MSR_K8_HWCR 0xc0010015U +#define K8_HWCR_TSC_FREQ_SEL (1ULL << 24) +#define K8_HWCR_CPUID_USER_DIS (1ULL << 35) + +#define MSR_K7_FID_VID_CTL 0xc0010041U +#define MSR_K7_FID_VID_STATUS 0xc0010042U +#define MSR_K8_PSTATE_LIMIT 0xc0010061U +#define MSR_K8_PSTATE_CTRL 0xc0010062U +#define MSR_K8_PSTATE_STATUS 0xc0010063U +#define MSR_K8_PSTATE0 0xc0010064U +#define MSR_K8_PSTATE1 0xc0010065U +#define MSR_K8_PSTATE2 0xc0010066U +#define MSR_K8_PSTATE3 0xc0010067U +#define MSR_K8_PSTATE4 0xc0010068U +#define MSR_K8_PSTATE5 0xc0010069U +#define MSR_K8_PSTATE6 0xc001006AU +#define MSR_K8_PSTATE7 0xc001006BU +#define MSR_K8_ENABLE_C1E 0xc0010055U +#define MSR_K8_VM_HSAVE_PA 0xc0010117U + +#define MSR_AMD_FAM15H_EVNTSEL0 0xc0010200U +#define MSR_AMD_FAM15H_PERFCTR0 0xc0010201U +#define MSR_AMD_FAM15H_EVNTSEL1 0xc0010202U +#define MSR_AMD_FAM15H_PERFCTR1 0xc0010203U +#define MSR_AMD_FAM15H_EVNTSEL2 0xc0010204U +#define MSR_AMD_FAM15H_PERFCTR2 0xc0010205U +#define MSR_AMD_FAM15H_EVNTSEL3 0xc0010206U +#define MSR_AMD_FAM15H_PERFCTR3 0xc0010207U +#define MSR_AMD_FAM15H_EVNTSEL4 0xc0010208U +#define MSR_AMD_FAM15H_PERFCTR4 0xc0010209U +#define MSR_AMD_FAM15H_EVNTSEL5 0xc001020aU +#define MSR_AMD_FAM15H_PERFCTR5 0xc001020bU + +#define MSR_AMD_L7S0_FEATURE_MASK 0xc0011002U +#define MSR_AMD_THRM_FEATURE_MASK 0xc0011003U +#define MSR_K8_FEATURE_MASK 0xc0011004U +#define MSR_K8_EXT_FEATURE_MASK 0xc0011005U + +/* AMD64 MSRs */ +#define MSR_AMD64_NB_CFG 0xc001001fU +#define AMD64_NB_CFG_CF8_EXT_ENABLE_BIT 46 +#define MSR_AMD64_LS_CFG 0xc0011020U +#define MSR_AMD64_IC_CFG 0xc0011021U +#define MSR_AMD64_DC_CFG 0xc0011022U +#define MSR_AMD64_DE_CFG 0xc0011029U +#define AMD64_DE_CFG_LFENCE_SERIALISE (_AC (1, ULL) << 1) +#define MSR_AMD64_EX_CFG 0xc001102cU +#define MSR_AMD64_BP_CFG 0xc001102eU +#define BP_CFG_SPEC_REDUCE (_AC (1, ULL) << 4) +#define MSR_AMD64_DE_CFG2 0xc00110e3U + +#define MSR_AMD64_DR0_ADDRESS_MASK 0xc0011027U +#define MSR_AMD64_DR1_ADDRESS_MASK 0xc0011019U +#define MSR_AMD64_DR2_ADDRESS_MASK 0xc001101aU +#define MSR_AMD64_DR3_ADDRESS_MASK 0xc001101bU + +/* AMD Family10h machine check MSRs */ +#define MSR_F10_MC4_MISC1 0xc0000408U +#define MSR_F10_MC4_MISC2 0xc0000409U +#define MSR_F10_MC4_MISC3 0xc000040AU + +/* AMD Family10h Bus Unit MSRs */ +#define MSR_F10_BU_CFG 0xc0011023U +#define MSR_F10_BU_CFG2 0xc001102aU + +/* Other AMD Fam10h MSRs */ +#define MSR_FAM10H_MMIO_CONF_BASE 0xc0010058U +#define FAM10H_MMIO_CONF_ENABLE (1 << 0) +#define FAM10H_MMIO_CONF_BUSRANGE_MASK 0xf +#define FAM10H_MMIO_CONF_BUSRANGE_SHIFT 2 +#define FAM10H_MMIO_CONF_BASE_MASK 0xfffffffULL +#define FAM10H_MMIO_CONF_BASE_SHIFT 20 + +/* AMD Microcode MSRs */ +#define MSR_AMD_PATCHLEVEL 0x0000008b +#define MSR_AMD_PATCHLOADER 0xc0010020U + +/* AMD TSC RATE MSR */ +#define MSR_AMD64_TSC_RATIO 0xc0000104U + +/* AMD Lightweight Profiling MSRs */ +#define MSR_AMD64_LWP_CFG 0xc0000105U +#define MSR_AMD64_LWP_CBADDR 0xc0000106U + +/* AMD OS Visible Workaround MSRs */ +#define MSR_AMD_OSVW_ID_LENGTH 0xc0010140U +#define MSR_AMD_OSVW_STATUS 0xc0010141U + +/* AMD Protected Processor Inventory Number */ +#define MSR_AMD_PPIN_CTL 0xc00102f0U +#define MSR_AMD_PPIN 0xc00102f1U + +/* VIA Cyrix defined MSRs*/ +#define MSR_VIA_FCR 0x00001107 +#define MSR_VIA_RNG 0x0000110b + +/* Intel defined MSRs. */ +#define MSR_IA32_TSC 0x00000010 +#define MSR_IA32_PLATFORM_ID 0x00000017 +#define MSR_IA32_EBL_CR_POWERON 0x0000002a +#define MSR_IA32_EBC_FREQUENCY_ID 0x0000002c + +#define MSR_IA32_FEATURE_CONTROL 0x0000003a +#define IA32_FEATURE_CONTROL_LOCK 0x0001 +#define IA32_FEATURE_CONTROL_ENABLE_VMXON_INSIDE_SMX 0x0002 +#define IA32_FEATURE_CONTROL_ENABLE_VMXON_OUTSIDE_SMX 0x0004 +#define IA32_FEATURE_CONTROL_SENTER_PARAM_CTL 0x7f00 +#define IA32_FEATURE_CONTROL_ENABLE_SENTER 0x8000 +#define IA32_FEATURE_CONTROL_SGX_ENABLE 0x40000 +#define IA32_FEATURE_CONTROL_LMCE_ON 0x100000 + +#define MSR_IA32_TSC_ADJUST 0x0000003b + +#define MSR_IA32_UCODE_WRITE 0x00000079 +#define MSR_IA32_UCODE_REV 0x0000008b + +#define MSR_IA32_PERF_STATUS 0x00000198 +#define MSR_IA32_PERF_CTL 0x00000199 + +#define MSR_IA32_MPERF 0x000000e7 +#define MSR_IA32_APERF 0x000000e8 + +#define MSR_IA32_THERM_CONTROL 0x0000019a +#define MSR_IA32_THERM_INTERRUPT 0x0000019b +#define MSR_IA32_THERM_STATUS 0x0000019c +#define MSR_IA32_MISC_ENABLE 0x000001a0 +#define MSR_IA32_MISC_ENABLE_FAST_STRING (1 << 0) +#define MSR_IA32_MISC_ENABLE_PERF_AVAIL (1 << 7) +#define MSR_IA32_MISC_ENABLE_BTS_UNAVAIL (1 << 11) +#define MSR_IA32_MISC_ENABLE_PEBS_UNAVAIL (1 << 12) +#define MSR_IA32_MISC_ENABLE_MONITOR_ENABLE (1 << 18) +#define MSR_IA32_MISC_ENABLE_LIMIT_CPUID (1 << 22) +#define MSR_IA32_MISC_ENABLE_XTPR_DISABLE (1 << 23) +#define MSR_IA32_MISC_ENABLE_XD_DISABLE (_AC (1, ULL) << 34) +#define MSR_IA32_MISC_ENABLE_TURBO_DISENGAGE (_AC (1, ULL) << 38) + +#define MSR_IA32_TSC_DEADLINE 0x000006E0 +#define MSR_IA32_ENERGY_PERF_BIAS 0x000001b0 + +/* Platform Shared Resource MSRs */ +#define MSR_IA32_CMT_EVTSEL 0x00000c8d +#define MSR_IA32_CMT_EVTSEL_UE_MASK 0x0000ffff +#define MSR_IA32_CMT_CTR 0x00000c8e +#define MSR_IA32_PSR_ASSOC 0x00000c8f +#define MSR_IA32_PSR_L3_QOS_CFG 0x00000c81 +#define MSR_IA32_PSR_L3_MASK(n) (0x00000c90 + (n)) +#define MSR_IA32_PSR_L3_MASK_CODE(n) (0x00000c90 + (n) * 2 + 1) +#define MSR_IA32_PSR_L3_MASK_DATA(n) (0x00000c90 + (n) * 2) +#define MSR_IA32_PSR_L2_MASK(n) (0x00000d10 + (n)) +#define MSR_IA32_PSR_MBA_MASK(n) (0x00000d50 + (n)) + +/* Intel Model 6 */ +#define MSR_P6_PERFCTR(n) (0x000000c1 + (n)) +#define MSR_P6_EVNTSEL(n) (0x00000186 + (n)) + +/* P4/Xeon+ specific */ +#define MSR_IA32_MCG_EAX 0x00000180 +#define MSR_IA32_MCG_EBX 0x00000181 +#define MSR_IA32_MCG_ECX 0x00000182 +#define MSR_IA32_MCG_EDX 0x00000183 +#define MSR_IA32_MCG_ESI 0x00000184 +#define MSR_IA32_MCG_EDI 0x00000185 +#define MSR_IA32_MCG_EBP 0x00000186 +#define MSR_IA32_MCG_ESP 0x00000187 +#define MSR_IA32_MCG_EFLAGS 0x00000188 +#define MSR_IA32_MCG_EIP 0x00000189 +#define MSR_IA32_MCG_MISC 0x0000018a +#define MSR_IA32_MCG_R8 0x00000190 +#define MSR_IA32_MCG_R9 0x00000191 +#define MSR_IA32_MCG_R10 0x00000192 +#define MSR_IA32_MCG_R11 0x00000193 +#define MSR_IA32_MCG_R12 0x00000194 +#define MSR_IA32_MCG_R13 0x00000195 +#define MSR_IA32_MCG_R14 0x00000196 +#define MSR_IA32_MCG_R15 0x00000197 + +/* Pentium IV performance counter MSRs */ +#define MSR_P4_BPU_PERFCTR0 0x00000300 +#define MSR_P4_BPU_PERFCTR1 0x00000301 +#define MSR_P4_BPU_PERFCTR2 0x00000302 +#define MSR_P4_BPU_PERFCTR3 0x00000303 +#define MSR_P4_MS_PERFCTR0 0x00000304 +#define MSR_P4_MS_PERFCTR1 0x00000305 +#define MSR_P4_MS_PERFCTR2 0x00000306 +#define MSR_P4_MS_PERFCTR3 0x00000307 +#define MSR_P4_FLAME_PERFCTR0 0x00000308 +#define MSR_P4_FLAME_PERFCTR1 0x00000309 +#define MSR_P4_FLAME_PERFCTR2 0x0000030a +#define MSR_P4_FLAME_PERFCTR3 0x0000030b +#define MSR_P4_IQ_PERFCTR0 0x0000030c +#define MSR_P4_IQ_PERFCTR1 0x0000030d +#define MSR_P4_IQ_PERFCTR2 0x0000030e +#define MSR_P4_IQ_PERFCTR3 0x0000030f +#define MSR_P4_IQ_PERFCTR4 0x00000310 +#define MSR_P4_IQ_PERFCTR5 0x00000311 +#define MSR_P4_BPU_CCCR0 0x00000360 +#define MSR_P4_BPU_CCCR1 0x00000361 +#define MSR_P4_BPU_CCCR2 0x00000362 +#define MSR_P4_BPU_CCCR3 0x00000363 +#define MSR_P4_MS_CCCR0 0x00000364 +#define MSR_P4_MS_CCCR1 0x00000365 +#define MSR_P4_MS_CCCR2 0x00000366 +#define MSR_P4_MS_CCCR3 0x00000367 +#define MSR_P4_FLAME_CCCR0 0x00000368 +#define MSR_P4_FLAME_CCCR1 0x00000369 +#define MSR_P4_FLAME_CCCR2 0x0000036a +#define MSR_P4_FLAME_CCCR3 0x0000036b +#define MSR_P4_IQ_CCCR0 0x0000036c +#define MSR_P4_IQ_CCCR1 0x0000036d +#define MSR_P4_IQ_CCCR2 0x0000036e +#define MSR_P4_IQ_CCCR3 0x0000036f +#define MSR_P4_IQ_CCCR4 0x00000370 +#define MSR_P4_IQ_CCCR5 0x00000371 +#define MSR_P4_ALF_ESCR0 0x000003ca +#define MSR_P4_ALF_ESCR1 0x000003cb +#define MSR_P4_BPU_ESCR0 0x000003b2 +#define MSR_P4_BPU_ESCR1 0x000003b3 +#define MSR_P4_BSU_ESCR0 0x000003a0 +#define MSR_P4_BSU_ESCR1 0x000003a1 +#define MSR_P4_CRU_ESCR0 0x000003b8 +#define MSR_P4_CRU_ESCR1 0x000003b9 +#define MSR_P4_CRU_ESCR2 0x000003cc +#define MSR_P4_CRU_ESCR3 0x000003cd +#define MSR_P4_CRU_ESCR4 0x000003e0 +#define MSR_P4_CRU_ESCR5 0x000003e1 +#define MSR_P4_DAC_ESCR0 0x000003a8 +#define MSR_P4_DAC_ESCR1 0x000003a9 +#define MSR_P4_FIRM_ESCR0 0x000003a4 +#define MSR_P4_FIRM_ESCR1 0x000003a5 +#define MSR_P4_FLAME_ESCR0 0x000003a6 +#define MSR_P4_FLAME_ESCR1 0x000003a7 +#define MSR_P4_FSB_ESCR0 0x000003a2 +#define MSR_P4_FSB_ESCR1 0x000003a3 +#define MSR_P4_IQ_ESCR0 0x000003ba +#define MSR_P4_IQ_ESCR1 0x000003bb +#define MSR_P4_IS_ESCR0 0x000003b4 +#define MSR_P4_IS_ESCR1 0x000003b5 +#define MSR_P4_ITLB_ESCR0 0x000003b6 +#define MSR_P4_ITLB_ESCR1 0x000003b7 +#define MSR_P4_IX_ESCR0 0x000003c8 +#define MSR_P4_IX_ESCR1 0x000003c9 +#define MSR_P4_MOB_ESCR0 0x000003aa +#define MSR_P4_MOB_ESCR1 0x000003ab +#define MSR_P4_MS_ESCR0 0x000003c0 +#define MSR_P4_MS_ESCR1 0x000003c1 +#define MSR_P4_PMH_ESCR0 0x000003ac +#define MSR_P4_PMH_ESCR1 0x000003ad +#define MSR_P4_RAT_ESCR0 0x000003bc +#define MSR_P4_RAT_ESCR1 0x000003bd +#define MSR_P4_SAAT_ESCR0 0x000003ae +#define MSR_P4_SAAT_ESCR1 0x000003af +#define MSR_P4_SSU_ESCR0 0x000003be +#define MSR_P4_SSU_ESCR1 0x000003bf /* guess: not in manual */ + +#define MSR_P4_TBPU_ESCR0 0x000003c2 +#define MSR_P4_TBPU_ESCR1 0x000003c3 +#define MSR_P4_TC_ESCR0 0x000003c4 +#define MSR_P4_TC_ESCR1 0x000003c5 +#define MSR_P4_U2L_ESCR0 0x000003b0 +#define MSR_P4_U2L_ESCR1 0x000003b1 + +/* Netburst (P4) last-branch recording */ +#define MSR_P4_LER_FROM_LIP 0x000001d7 +#define MSR_P4_LER_TO_LIP 0x000001d8 +#define MSR_P4_LASTBRANCH_TOS 0x000001da +#define MSR_P4_LASTBRANCH_0 0x000001db +#define NUM_MSR_P4_LASTBRANCH 4 +#define MSR_P4_LASTBRANCH_0_FROM_LIP 0x00000680 +#define MSR_P4_LASTBRANCH_0_TO_LIP 0x000006c0 +#define NUM_MSR_P4_LASTBRANCH_FROM_TO 16 + +/* Core 2 and Atom last-branch recording */ +#define MSR_C2_LASTBRANCH_TOS 0x000001c9 +#define MSR_C2_LASTBRANCH_0_FROM_IP 0x00000040 +#define MSR_C2_LASTBRANCH_0_TO_IP 0x00000060 +#define NUM_MSR_C2_LASTBRANCH_FROM_TO 4 +#define NUM_MSR_ATOM_LASTBRANCH_FROM_TO 8 + +/* Nehalem (and newer) last-branch recording */ +#define MSR_NHL_LBR_SELECT 0x000001c8 +#define MSR_NHL_LASTBRANCH_TOS 0x000001c9 + +/* Skylake (and newer) last-branch recording */ +#define MSR_SKL_LASTBRANCH_0_FROM_IP 0x00000680 +#define MSR_SKL_LASTBRANCH_0_TO_IP 0x000006c0 +#define MSR_SKL_LASTBRANCH_0_INFO 0x00000dc0 +#define NUM_MSR_SKL_LASTBRANCH 32 + +/* Silvermont (and newer) last-branch recording */ +#define MSR_SM_LBR_SELECT 0x000001c8 +#define MSR_SM_LASTBRANCH_TOS 0x000001c9 + +/* Goldmont last-branch recording */ +#define MSR_GM_LASTBRANCH_0_FROM_IP 0x00000680 +#define MSR_GM_LASTBRANCH_0_TO_IP 0x000006c0 +#define NUM_MSR_GM_LASTBRANCH_FROM_TO 32 + +/* Intel Core-based CPU performance counters */ +#define MSR_CORE_PERF_FIXED_CTR0 0x00000309 +#define MSR_CORE_PERF_FIXED_CTR1 0x0000030a +#define MSR_CORE_PERF_FIXED_CTR2 0x0000030b +#define MSR_CORE_PERF_FIXED_CTR_CTRL 0x0000038d +#define MSR_CORE_PERF_GLOBAL_STATUS 0x0000038e +#define MSR_CORE_PERF_GLOBAL_CTRL 0x0000038f +#define MSR_CORE_PERF_GLOBAL_OVF_CTRL 0x00000390 + +/* Intel cpuid spoofing MSRs */ +#define MSR_INTEL_MASK_V1_CPUID1 0x00000478 + +#define MSR_INTEL_MASK_V2_CPUID1 0x00000130 +#define MSR_INTEL_MASK_V2_CPUID80000001 0x00000131 + +#define MSR_INTEL_MASK_V3_CPUID1 0x00000132 +#define MSR_INTEL_MASK_V3_CPUID80000001 0x00000133 +#define MSR_INTEL_MASK_V3_CPUIDD_01 0x00000134 + +/* Intel cpuid faulting MSRs */ +#define MSR_INTEL_PLATFORM_INFO 0x000000ce +#define _MSR_PLATFORM_INFO_CPUID_FAULTING 31 +#define MSR_PLATFORM_INFO_CPUID_FAULTING (1ULL << _MSR_PLATFORM_INFO_CPUID_FAULTING) + +#define MSR_INTEL_MISC_FEATURES_ENABLES 0x00000140 +#define _MSR_MISC_FEATURES_CPUID_FAULTING 0 +#define MSR_MISC_FEATURES_CPUID_FAULTING (1ULL << _MSR_MISC_FEATURES_CPUID_FAULTING) + +#define MSR_CC6_DEMOTION_POLICY_CONFIG 0x00000668 +#define MSR_MC6_DEMOTION_POLICY_CONFIG 0x00000669 + +/* Interrupt Response Limit */ +#define MSR_PKGC3_IRTL 0x0000060a +#define MSR_PKGC6_IRTL 0x0000060b +#define MSR_PKGC7_IRTL 0x0000060c +#define MSR_PKGC8_IRTL 0x00000633 +#define MSR_PKGC9_IRTL 0x00000634 +#define MSR_PKGC10_IRTL 0x00000635 + +#endif /* __ASM_MSR_INDEX_H */ diff --git a/kernel/amd64/msr.h b/kernel/amd64/msr.h index d1ccfdf..5c3d325 100644 --- a/kernel/amd64/msr.h +++ b/kernel/amd64/msr.h @@ -3,6 +3,9 @@ #include +#define MSR_FS_BASE 0xC0000100 +#define MSR_GS_BASE 0xC0000101 + uint64_t amd64_rdmsr (uint32_t msr); void amd64_wrmsr (uint32_t msr, uint64_t value); diff --git a/kernel/amd64/smp.c b/kernel/amd64/smp.c new file mode 100644 index 0000000..5c84f75 --- /dev/null +++ b/kernel/amd64/smp.c @@ -0,0 +1,72 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static uint32_t cpu_counter = 0; +static spin_lock_t cpu_counter_lock = SPIN_LOCK_INIT; +static struct cpu cpus[CPUS_MAX]; + +struct cpu* cpu_make (void) { + spin_lock (&cpu_counter_lock); + int id = cpu_counter++; + spin_unlock (&cpu_counter_lock); + + struct cpu* cpu = &cpus[id]; + + memset (cpu, 0, sizeof (*cpu)); + cpu->id = id; + + return cpu_get (id); +} + +struct cpu* cpu_get (uint32_t id) { + if (id >= CPUS_MAX) + return NULL; + + return &cpus[id]; +} + +uint32_t cpu_id (void) { return (uint32_t)amd64_rdmsr (MSR_GS_BASE); } + +void cpu_assign (uint32_t id) { amd64_wrmsr (MSR_GS_BASE, (uint64_t)id); } + +static void amd64_smp_bootstrap (struct limine_mp_info* mp_info) { + amd64_load_kernel_cr3 (); + + struct cpu* cpu = cpu_make (); + cpu_assign (cpu->id); + + amd64_init (cpu, true); /* gdt + idt */ + + thiscpu->lapic_ticks = amd64_lapic_init (2500); + amd64_lapic_tick (thiscpu->lapic_ticks); + + DEBUG ("CPU %u is online!\n", thiscpu->id); + + __asm__ volatile ("sti"); + + for (;;) + ; +} + +void smp_init (void) { + thiscpu->lapic_ticks = amd64_lapic_init (2500); + + struct limine_mp_response* mp = limine_mp_request.response; + + for (size_t i = 0; i < mp->cpu_count; i++) { + if (mp->cpus[i]->lapic_id != thiscpu->id) { + DEBUG ("Trying CPU %u\n", mp->cpus[i]->lapic_id); + mp->cpus[i]->goto_address = &amd64_smp_bootstrap; + } + } +} diff --git a/kernel/amd64/smp.h b/kernel/amd64/smp.h new file mode 100644 index 0000000..3dd26f5 --- /dev/null +++ b/kernel/amd64/smp.h @@ -0,0 +1,32 @@ +#ifndef _KERNEL_AMD64_SMP_H +#define _KERNEL_AMD64_SMP_H + +#include +#include +#include +#include + +#define CPUS_MAX 32 + +struct cpu { + uint64_t lapic_ticks; + uint32_t id; + struct { + uint64_t rflags; + atomic_int nesting; + } irq_ctx; + volatile uint8_t kernel_stack[KSTACK_SIZE] ALIGNED (16); + volatile uint8_t except_stack[KSTACK_SIZE] ALIGNED (16); + volatile uint8_t irq_stack[KSTACK_SIZE] ALIGNED (16); + volatile struct gdt_extended gdt ALIGNED (16); + volatile struct tss tss; +}; + +struct cpu* cpu_make (void); +struct cpu* cpu_get (uint32_t id); +void cpu_assign (uint32_t id); +uint32_t cpu_id (void); + +#define thiscpu (cpu_get (cpu_id ())) + +#endif // _KERNEL_AMD64_SMP_H diff --git a/kernel/amd64/src.mk b/kernel/amd64/src.mk index 5e8e04a..f9fb3e6 100644 --- a/kernel/amd64/src.mk +++ b/kernel/amd64/src.mk @@ -9,7 +9,8 @@ c += amd64/bootmain.c \ amd64/msr.c \ amd64/hpet.c \ amd64/mm.c \ - amd64/time.c + amd64/time.c \ + amd64/smp.c S += amd64/intr_stub.S \ amd64/spin.S @@ -27,4 +28,5 @@ o += amd64/bootmain.o \ amd64/msr.o \ amd64/hpet.o \ amd64/mm.o \ - amd64/time.o + amd64/time.o \ + amd64/smp.o diff --git a/kernel/amd64/time.c b/kernel/amd64/time.c index afe922a..7065d95 100644 --- a/kernel/amd64/time.c +++ b/kernel/amd64/time.c @@ -1,7 +1,5 @@ +#include #include #include -#include -void sleep_micro (size_t us) { - amd64_hpet_sleep_micro (us); -} +void sleep_micro (size_t us) { amd64_hpet_sleep_micro (us); } diff --git a/kernel/irq/.gitignore b/kernel/irq/.gitignore new file mode 100644 index 0000000..5761abc --- /dev/null +++ b/kernel/irq/.gitignore @@ -0,0 +1 @@ +*.o diff --git a/kernel/irq/irq.c b/kernel/irq/irq.c new file mode 100644 index 0000000..4ce057a --- /dev/null +++ b/kernel/irq/irq.c @@ -0,0 +1,59 @@ +#include +#include +#include +#include +#include + +#if defined(__x86_64__) +#include +#endif + +/* TODO: figure out a generic way to work with IRQs */ + +static struct irq* irqs = NULL; +static spin_lock_t irqs_lock; + +bool irq_attach (void (*func) (void*), void* arg, uint32_t irq_num) { + struct irq* irq = malloc (sizeof (*irq)); + if (irq == NULL) { + return false; + } + + irq->func = func; + irq->arg = arg; + irq->irq_num = irq_num; + + spin_lock (&irqs_lock); + linklist_append (struct irq*, irqs, irq); + spin_unlock (&irqs_lock); + +#if defined(__x86_64__) + amd64_ioapic_route_irq (irq_num, irq_num - 0x20, 0, amd64_lapic_id ()); +#endif + + return true; +} + +void irq_detach (void (*func) (void*)) { + spin_lock (&irqs_lock); + + struct irq *irq, *irq_tmp; + linklist_foreach (irqs, irq, irq_tmp) { + if ((uintptr_t)irq->func == (uintptr_t)func) + linklist_remove (struct irq*, irqs, irq); + } + + spin_unlock (&irqs_lock); +} + +void irq_invoke_each (uint32_t irq_num) { + spin_lock (&irqs_lock); + + struct irq *irq, *irq_tmp; + linklist_foreach (irqs, irq, irq_tmp) { + if (irq->irq_num == irq_num) + irq->func (irq->arg); + } + + spin_unlock (&irqs_lock); +} diff --git a/kernel/irq/irq.h b/kernel/irq/irq.h new file mode 100644 index 0000000..e0e355b --- /dev/null +++ b/kernel/irq/irq.h @@ -0,0 +1,18 @@ +#ifndef _KERNEL_IRQ_IRQ_H +#define _KERNEL_IRQ_IRQ_H + +#include + +struct irq { + struct irq* next; + + void (*func) (void*); + void* arg; + uint32_t irq_num; +}; + +bool irq_attach (void (*func) (void*), void* arg, uint32_t irq_num); +void irq_detach (void (*func) (void*)); +void irq_invoke_each (uint32_t irq_num); + +#endif // _KERNEL_IRQ_IRQ_H diff --git a/kernel/irq/src.mk b/kernel/irq/src.mk new file mode 100644 index 0000000..bc164de --- /dev/null +++ b/kernel/irq/src.mk @@ -0,0 +1,3 @@ +c += irq/irq.c + +o += irq/irq.o diff --git a/kernel/libk/list.h b/kernel/libk/list.h new file mode 100644 index 0000000..7462723 --- /dev/null +++ b/kernel/libk/list.h @@ -0,0 +1,208 @@ +#ifndef _KERNEL_LIBK_LIST_H +#define _KERNEL_LIBK_LIST_H + +#define dlinklist_append(type, head, new) \ + do { \ + if ((new) != NULL) { \ + (new)->next = NULL; \ + if ((head) != NULL) { \ + type __tmp = (head); \ + while (__tmp->next != NULL) { \ + __tmp = __tmp->next; \ + } \ + __tmp->next = (new); \ + (new)->prev = __tmp; \ + } else { \ + (new)->prev = NULL; \ + (head) = (new); \ + } \ + } \ + } while (0) + +#define dlinklist_prepend(head, new) \ + do { \ + if ((new) != NULL) { \ + (new)->prev = NULL; \ + (new)->next = (head); \ + if ((head) != NULL) { \ + (head)->prev = (new); \ + } \ + (head) = (new); \ + } \ + } while (0) + +#define dlinklist_remove(head, ele) \ + do { \ + if ((ele) != NULL) { \ + if ((ele)->prev != NULL) { \ + (ele)->prev->next = (ele)->next; \ + } else { \ + (head) = (ele)->next; \ + } \ + if ((ele)->next != NULL) { \ + (ele)->next->prev = (ele)->prev; \ + } \ + (ele)->next = NULL; \ + (ele)->prev = NULL; \ + } \ + } while (0) + +#define dlinklist_find(type, head, out, propname, propvalue) \ + do { \ + (out) = NULL; \ + type __tmp = (head); \ + while (__tmp) { \ + if (__tmp->propname == (propvalue)) { \ + (out) = __tmp; \ + break; \ + } \ + __tmp = __tmp->next; \ + } \ + } while (0) + +#define dlinklist_foreach(head, var, tmp) \ + for (var = (head), tmp = (var ? var->next : NULL); var != NULL; \ + var = tmp, tmp = (var ? var->next : NULL)) + +#define dlinklist_foreach_index(head, var, tmp, idx) \ + for ((idx) = 0, var = (head), tmp = (var ? var->next : NULL); var != NULL; \ + var = tmp, tmp = (var ? var->next : NULL), (idx)++) + +#define dlinklist_foreach_index_limit(head, var, tmp, idx, max) \ + for ((idx) = 0, var = (head), tmp = (var ? var->next : NULL); var != NULL && (idx) < (max); \ + var = tmp, tmp = (var ? var->next : NULL), (idx)++) + +#define dlinklist_back(type, head, out) \ + do { \ + (out) = NULL; \ + if ((head) != NULL) { \ + type __tmp = (head); \ + while (__tmp->next != NULL) { \ + __tmp = __tmp->next; \ + } \ + (out) = __tmp; \ + } \ + } while (0) + +#define dlinklist_front(type, head, out) \ + do { \ + (out) = NULL; \ + if ((head) != NULL) { \ + type __tmp = (head); \ + while (__tmp->prev != NULL) { \ + __tmp = __tmp->prev; \ + } \ + (out) = __tmp; \ + } \ + } while (0) + +#define dlinklist_insert_after(head, pos, new) \ + do { \ + if ((pos) != NULL && (new) != NULL) { \ + (new)->prev = (pos); \ + (new)->next = (pos)->next; \ + if ((pos)->next != NULL) { \ + (pos)->next->prev = (new); \ + } \ + (pos)->next = (new); \ + } else if ((pos) == NULL && (head) == NULL) { \ + (new)->prev = NULL; \ + (new)->next = NULL; \ + (head) = (new); \ + } \ + } while (0) + +#define dlinklist_insert_before(head, pos, new) \ + do { \ + if ((pos) != NULL && (new) != NULL) { \ + (new)->next = (pos); \ + (new)->prev = (pos)->prev; \ + if ((pos)->prev != NULL) { \ + (pos)->prev->next = (new); \ + } else { \ + (head) = (new); \ + } \ + (pos)->prev = (new); \ + } else if ((pos) == NULL && (head) == NULL) { \ + (new)->prev = NULL; \ + (new)->next = NULL; \ + (head) = (new); \ + } \ + } while (0) + +#define linklist_append(type, head, new) \ + do { \ + if ((new) != NULL) { \ + if ((head) != NULL) { \ + type __tmp; \ + (new)->next = NULL; \ + __tmp = (head); \ + while (__tmp->next != NULL) { \ + __tmp = __tmp->next; \ + } \ + __tmp->next = (new); \ + } else { \ + (new)->next = NULL; \ + (head) = (new); \ + } \ + } \ + } while (0) + +#define linklist_remove(type, head, ele) \ + do { \ + if ((head) != NULL && (ele) != NULL) { \ + type __cur = (head); \ + type __prev = NULL; \ + while (__cur != NULL && __cur != (ele)) { \ + __prev = __cur; \ + __cur = __cur->next; \ + } \ + if (__cur == (ele)) { \ + if (__prev != NULL) { \ + __prev->next = __cur->next; \ + } else { \ + (head) = __cur->next; \ + } \ + (ele)->next = NULL; \ + } \ + } \ + } while (0) + +#define linklist_find(type, head, out, propname, propvalue) \ + do { \ + (out) = NULL; \ + type __tmp = (head); \ + while (__tmp) { \ + if (__tmp->propname == (propvalue)) { \ + (out) = __tmp; \ + break; \ + } \ + __tmp = __tmp->next; \ + } \ + } while (0) + +#define linklist_foreach(head, var, tmp) \ + for (var = (head), tmp = (var ? var->next : NULL); var != NULL; \ + var = tmp, tmp = (var ? var->next : NULL)) + +#define linklist_foreach_index(head, var, tmp, idx) \ + for ((idx) = 0, var = (head), tmp = (var ? var->next : NULL); var != NULL; \ + var = tmp, tmp = (var ? var->next : NULL), (idx)++) + +#define linklist_foreach_index_limit(head, var, tmp, idx, max) \ + for ((idx) = 0, var = (head), tmp = (var ? var->next : NULL); var != NULL && (idx) < (max); \ + var = tmp, tmp = (var ? var->next : NULL), (idx)++) + +#define linklist_back(type, head, out) \ + do { \ + (out) = NULL; \ + if ((head) != NULL) { \ + type __tmp = (head); \ + while (__tmp->next != NULL) { \ + __tmp = __tmp->next; \ + } \ + (out) = __tmp; \ + } \ + } while (0) + +#endif // _KERNEL_LIBK_LIST_H diff --git a/kernel/limine/requests.c b/kernel/limine/requests.c index 8aa3728..22ca739 100644 --- a/kernel/limine/requests.c +++ b/kernel/limine/requests.c @@ -18,3 +18,4 @@ volatile uint64_t limine_requests_end_marker[] = LIMINE_REQUESTS_END_MARKER; DECL_REQ (hhdm, HHDM); DECL_REQ (memmap, MEMMAP); DECL_REQ (rsdp, RSDP); +DECL_REQ (mp, MP); diff --git a/kernel/limine/requests.h b/kernel/limine/requests.h index 4fbe306..44d074a 100644 --- a/kernel/limine/requests.h +++ b/kernel/limine/requests.h @@ -8,5 +8,6 @@ EXTERN_REQ (hhdm); EXTERN_REQ (memmap); EXTERN_REQ (rsdp); +EXTERN_REQ (mp); #endif // _KERNEL_LIMINE_REQUESTS_H diff --git a/kernel/src.mk b/kernel/src.mk index 24efc4f..525518c 100644 --- a/kernel/src.mk +++ b/kernel/src.mk @@ -4,3 +4,4 @@ include sync/src.mk include mm/src.mk include limine/src.mk include uACPI/src.mk +include irq/src.mk diff --git a/kernel/sync/spin_lock.c b/kernel/sync/spin_lock.c index 9889096..955d7c1 100644 --- a/kernel/sync/spin_lock.c +++ b/kernel/sync/spin_lock.c @@ -1,10 +1,17 @@ #include #include +#include #include void spin_lock (spin_lock_t* sl) { + irq_save (); + while (atomic_flag_test_and_set_explicit (sl, memory_order_acquire)) spin_lock_relax (); } -void spin_unlock (spin_lock_t* sl) { atomic_flag_clear_explicit (sl, memory_order_release); } +void spin_unlock (spin_lock_t* sl) { + atomic_flag_clear_explicit (sl, memory_order_release); + + irq_restore (); +} diff --git a/kernel/sys/irq.h b/kernel/sys/irq.h new file mode 100644 index 0000000..a545b13 --- /dev/null +++ b/kernel/sys/irq.h @@ -0,0 +1,7 @@ +#ifndef _KERNEL_SYS_IRQ_H +#define _KERNEL_SYS_IRQ_H + +void irq_save (void); +void irq_restore (void); + +#endif // _KERNEL_SYS_IRQ_H diff --git a/kernel/sys/smp.h b/kernel/sys/smp.h new file mode 100644 index 0000000..bb1a5ec --- /dev/null +++ b/kernel/sys/smp.h @@ -0,0 +1,10 @@ +#ifndef _KERNEL_SYS_SMP_H +#define _KERNEL_SYS_SMP_H + +#if defined(__x86_64__) +#include +#endif + +void smp_init (void); + +#endif // _KERNEL_SYS_SMP_H