mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-08-08 02:40:28 +00:00
[metal] Enable & implement IRQ 0, in legacy 8259 mode
This commit is contained in:
parent
97b8dd5d0a
commit
7dace0b171
12 changed files with 282 additions and 10 deletions
|
@ -26,8 +26,7 @@
|
|||
|
||||
__static_yoink("vga_console");
|
||||
__static_yoink("_idt");
|
||||
__static_yoink("_AcpiMadtFlags");
|
||||
__static_yoink("_AcpiBootFlags");
|
||||
__static_yoink("_irq");
|
||||
__static_yoink("EfiMain");
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
|
@ -38,6 +37,12 @@ int main(int argc, char *argv[]) {
|
|||
for (i = 0; i < argc; ++i) {
|
||||
printf("argv[%d] = \"%s\"\n", i, argv[i]);
|
||||
}
|
||||
for (i = 1; i <= 50; ++i) {
|
||||
printf("%d ", i);
|
||||
fflush(stdout);
|
||||
asm volatile("hlt");
|
||||
}
|
||||
printf("\n");
|
||||
printf("\e[92;44mHello World!\e[0m %d\n", 1 / (x + y - 3));
|
||||
for (;;)
|
||||
;
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/kprintf.h"
|
||||
#include "libc/irq/irq.internal.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/runtime/pc.internal.h"
|
||||
|
||||
|
@ -33,14 +34,6 @@
|
|||
|
||||
#define ISR_STK_SZ 0x10000
|
||||
#define ISR_STK_ALIGN 0x10
|
||||
// Interrupt stack to use for IRQs. TODO.
|
||||
#define IRQ_IST 1
|
||||
// Interrupt stack to use for CPU exceptions.
|
||||
#define EXCEP_IST 2
|
||||
|
||||
// Interrupt numbers to use for IRQs 0 & 8. TODO: implement these!
|
||||
#define IRQ0 0x20
|
||||
#define IRQ8 0x28
|
||||
|
||||
.init.start 100,_init_isr
|
||||
push %rdi
|
||||
|
|
|
@ -49,3 +49,13 @@ _AcpiIoApics:
|
|||
.skip 8
|
||||
.endobj _AcpiIoApics,globl
|
||||
.previous
|
||||
.rodata
|
||||
/* Yoinking _acpi from another module will link in ACPI support... */
|
||||
_acpi:
|
||||
.endobj _acpi,globl
|
||||
.previous
|
||||
/*
|
||||
* ...& also link in additional code needed for switching to legacy
|
||||
* BIOS-style interrupt handling.
|
||||
*/
|
||||
.yoink _ApicDisableAll
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include "libc/log/color.internal.h"
|
||||
|
||||
/**
|
||||
* @internal
|
||||
* AcpiStatus values.
|
||||
*/
|
||||
#define kAcpiOk 0x0000
|
||||
|
@ -13,11 +14,13 @@
|
|||
#define kAcpiExBadChecksum 0x2003
|
||||
|
||||
/**
|
||||
* @internal
|
||||
* Flags for AcpiTableMadt::Flags.
|
||||
*/
|
||||
#define kAcpiMadtPcAtCompat 0x0001
|
||||
|
||||
/**
|
||||
* @internal
|
||||
* Flags for AcpiTableFadt::BootFlags.
|
||||
*/
|
||||
#define kAcpiFadtLegacyDevices 0x0001
|
||||
|
@ -28,6 +31,7 @@
|
|||
#define kAcpiFadtNoCmosRtc 0x0020
|
||||
|
||||
/**
|
||||
* @internal
|
||||
* Values for AcpiSubtableHeader::Type under an AcpiTableMadt.
|
||||
*/
|
||||
#define kAcpiMadtLocalApic 0
|
||||
|
@ -37,6 +41,7 @@
|
|||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
|
||||
/**
|
||||
* @internal
|
||||
* @fileoverview Declarations for bare metal code to interact with ACPI
|
||||
*
|
||||
* @see UEFI Forum, Inc. Advanced Configuration and Power Interface (ACPI)
|
||||
|
|
56
libc/irq/apic.c
Normal file
56
libc/irq/apic.c
Normal file
|
@ -0,0 +1,56 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ This is free and unencumbered software released into the public domain. │
|
||||
│ │
|
||||
│ Anyone is free to copy, modify, publish, use, compile, sell, or │
|
||||
│ distribute this software, either in source code form or as a compiled │
|
||||
│ binary, for any purpose, commercial or non-commercial, and by any │
|
||||
│ means. │
|
||||
│ │
|
||||
│ In jurisdictions that recognize copyright laws, the author or authors │
|
||||
│ of this software dedicate any and all copyright interest in the │
|
||||
│ software to the public domain. We make this dedication for the benefit │
|
||||
│ of the public at large and to the detriment of our heirs and │
|
||||
│ successors. We intend this dedication to be an overt act of │
|
||||
│ relinquishment in perpetuity of all present and future rights to this │
|
||||
│ software under copyright law. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, │
|
||||
│ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF │
|
||||
│ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. │
|
||||
│ IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR │
|
||||
│ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, │
|
||||
│ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR │
|
||||
│ OTHER DEALINGS IN THE SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/dce.h"
|
||||
#include "libc/inttypes.h"
|
||||
#include "libc/irq/acpi.internal.h"
|
||||
#include "libc/irq/apic.internal.h"
|
||||
|
||||
#ifdef __x86_64__
|
||||
|
||||
/**
|
||||
* @internal
|
||||
* Disables all I/O APIC interrupts.
|
||||
*/
|
||||
textstartup void _ApicDisableAll(void) {
|
||||
const AcpiMadtIoApic **icp = _AcpiIoApics, *ic;
|
||||
HwIoApic *hwic;
|
||||
size_t n = _AcpiNumIoApics;
|
||||
unsigned intin;
|
||||
uint32_t conf;
|
||||
while (n-- != 0) {
|
||||
ic = *icp++;
|
||||
hwic = _AcpiOsMapUncachedMemory((uintptr_t)ic->Address, sizeof(HwIoApic));
|
||||
ACPI_INFO("stopping I/O APIC @ %p", hwic);
|
||||
for (intin = 0; intin < 24; ++intin) {
|
||||
hwic->rIoRegSel = IoApicRedTblLo(intin);
|
||||
conf = hwic->rIoWin;
|
||||
hwic->rIoWin = conf | kIoApicRedTblMasked;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* __x86_64__ */
|
34
libc/irq/apic.internal.h
Normal file
34
libc/irq/apic.internal.h
Normal file
|
@ -0,0 +1,34 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_IRQ_APIC_INTERNAL_H_
|
||||
#define COSMOPOLITAN_LIBC_IRQ_APIC_INTERNAL_H_
|
||||
|
||||
/**
|
||||
* @internal
|
||||
* @fileoverview Declarations for bare metal code to interact with I/O APICs
|
||||
*
|
||||
* @see Intel Corporation. 82093AA I/O Advanced Programmable Interrupt
|
||||
* Controller (IOAPIC), 1996. Intel order number 290566-001.
|
||||
*/
|
||||
|
||||
#define IoApicRedTblLo(INTIN) (0x10 + 2 * (INTIN))
|
||||
#define IoApicRedTblHi(INTIN) (0x11 + 2 * (INTIN))
|
||||
#define kIoApicRedTblMasked (1 << 16)
|
||||
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
/**
|
||||
* @internal
|
||||
* Structure of memory-mapped registers for an I/O APIC.
|
||||
*/
|
||||
typedef struct {
|
||||
volatile uint32_t rIoRegSel; /* register select (index) */
|
||||
volatile uint32_t :32, :32, :32;
|
||||
volatile uint32_t rIoWin; /* register data */
|
||||
} HwIoApic;
|
||||
|
||||
extern void _ApicDisableAll(void);
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_LIBC_IRQ_APIC_INTERNAL_H_ */
|
67
libc/irq/irq-8259.c
Normal file
67
libc/irq/irq-8259.c
Normal file
|
@ -0,0 +1,67 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ This is free and unencumbered software released into the public domain. │
|
||||
│ │
|
||||
│ Anyone is free to copy, modify, publish, use, compile, sell, or │
|
||||
│ distribute this software, either in source code form or as a compiled │
|
||||
│ binary, for any purpose, commercial or non-commercial, and by any │
|
||||
│ means. │
|
||||
│ │
|
||||
│ In jurisdictions that recognize copyright laws, the author or authors │
|
||||
│ of this software dedicate any and all copyright interest in the │
|
||||
│ software to the public domain. We make this dedication for the benefit │
|
||||
│ of the public at large and to the detriment of our heirs and │
|
||||
│ successors. We intend this dedication to be an overt act of │
|
||||
│ relinquishment in perpetuity of all present and future rights to this │
|
||||
│ software under copyright law. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, │
|
||||
│ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF │
|
||||
│ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. │
|
||||
│ IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR │
|
||||
│ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, │
|
||||
│ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR │
|
||||
│ OTHER DEALINGS IN THE SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/weaken.h"
|
||||
#include "libc/inttypes.h"
|
||||
#include "libc/irq/acpi.internal.h"
|
||||
#include "libc/irq/apic.internal.h"
|
||||
#include "libc/irq/irq.internal.h"
|
||||
#include "libc/runtime/pc.internal.h"
|
||||
|
||||
#ifdef __x86_64__
|
||||
|
||||
textstartup void _Irq8259Init(void) {
|
||||
if (_weaken(_ApicDisableAll)) _weaken(_ApicDisableAll)();
|
||||
ACPI_INFO("starting 8259 IRQs");
|
||||
outb(PIC1_CMD, PIC_INIT | PIC_IC4); /* ICW1 */
|
||||
outb(PIC2_CMD, PIC_INIT | PIC_IC4);
|
||||
outb(PIC1_DATA, IRQ0); /* ICW2 */
|
||||
outb(PIC2_DATA, IRQ8);
|
||||
outb(PIC1_DATA, 1 << 2); /* ICW3 — connect master IRQ 2 to */
|
||||
outb(PIC2_DATA, 1 << 1); /* (slave) IRQ 9 */
|
||||
outb(PIC1_DATA, PIC_UPM); /* ICW4 */
|
||||
outb(PIC2_DATA, PIC_UPM);
|
||||
/* Set IRQ masks. */
|
||||
outb(PIC1_DATA, ~(1 << 0)); /* OCW1 — allow IRQ 0 on PIC 1 */
|
||||
outb(PIC2_DATA, ~0);
|
||||
/* Send EOIs for good measure. */
|
||||
outb(PIC1_CMD, PIC_EOI);
|
||||
outb(PIC2_CMD, PIC_EOI);
|
||||
enable();
|
||||
}
|
||||
|
||||
textstartup void _IrqHwInit(void) {
|
||||
if (!_weaken(_AcpiMadtFlags) ||
|
||||
(_AcpiMadtFlags & kAcpiMadtPcAtCompat) != 0) {
|
||||
_Irq8259Init();
|
||||
} else {
|
||||
/* TODO */
|
||||
ACPI_FATAL("machine does not support 8259 IRQ handling");
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* __x86_64__ */
|
63
libc/irq/irq-init.S
Normal file
63
libc/irq/irq-init.S
Normal file
|
@ -0,0 +1,63 @@
|
|||
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
|
||||
│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ This is free and unencumbered software released into the public domain. │
|
||||
│ │
|
||||
│ Anyone is free to copy, modify, publish, use, compile, sell, or │
|
||||
│ distribute this software, either in source code form or as a compiled │
|
||||
│ binary, for any purpose, commercial or non-commercial, and by any │
|
||||
│ means. │
|
||||
│ │
|
||||
│ In jurisdictions that recognize copyright laws, the author or authors │
|
||||
│ of this software dedicate any and all copyright interest in the │
|
||||
│ software to the public domain. We make this dedication for the benefit │
|
||||
│ of the public at large and to the detriment of our heirs and │
|
||||
│ successors. We intend this dedication to be an overt act of │
|
||||
│ relinquishment in perpetuity of all present and future rights to this │
|
||||
│ software under copyright law. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, │
|
||||
│ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF │
|
||||
│ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. │
|
||||
│ IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR │
|
||||
│ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, │
|
||||
│ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR │
|
||||
│ OTHER DEALINGS IN THE SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/dce.h"
|
||||
#include "libc/irq/irq.internal.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/runtime/pc.internal.h"
|
||||
|
||||
.init.start 320,_init_irq
|
||||
testb IsMetal()
|
||||
jz 9f
|
||||
push %rdi
|
||||
push %rsi
|
||||
ezlea _idt+IRQ0*0x10,di # fill IDT entry for IRQ 0
|
||||
ezlea _irq0_isr,dx
|
||||
mov %edx,%eax
|
||||
stosw
|
||||
mov %cs,%eax
|
||||
stosw
|
||||
mov %rdx,%rax
|
||||
mov $0b1000111000000000|IRQ_IST,%ax
|
||||
stosl
|
||||
shr $32,%rax
|
||||
stosq
|
||||
call _IrqHwInit # bring up interrupt controller(s) &
|
||||
# enable interrupts
|
||||
pop %rsi
|
||||
pop %rdi
|
||||
9:
|
||||
.init.end 320,_init_irq
|
||||
_irq0_isr:
|
||||
push %rax
|
||||
mov $PIC_EOI,%al
|
||||
out %al,$PIC1_CMD
|
||||
pop %rax
|
||||
iretq
|
||||
.rodata
|
||||
_irq:
|
||||
.endobj _irq,globl
|
||||
.previous
|
12
libc/irq/irq.internal.h
Normal file
12
libc/irq/irq.internal.h
Normal file
|
@ -0,0 +1,12 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_IRQ_IRQ_INTERNAL_H_
|
||||
#define COSMOPOLITAN_LIBC_IRQ_IRQ_INTERNAL_H_
|
||||
|
||||
/**
|
||||
* @internal
|
||||
* Interrupt numbers to use for legacy BIOS style IRQs 0 & 8.
|
||||
* TODO: implement these!
|
||||
*/
|
||||
#define IRQ0 0x20
|
||||
#define IRQ8 0x28
|
||||
|
||||
#endif /* COSMOPOLITAN_LIBC_IRQ_IRQ_INTERNAL_H_ */
|
|
@ -1,3 +1,4 @@
|
|||
|
||||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
|
@ -36,6 +37,8 @@
|
|||
/* TODO: Why can't we change CR3? Could it really need PML5T? */
|
||||
/* TODO: Why does QEMU in UEFI mode take ten seconds to boot? */
|
||||
|
||||
__static_yoink("_acpi");
|
||||
|
||||
struct EfiArgs {
|
||||
char *Args[0x400 / sizeof(char *)];
|
||||
char ArgBlock[0xC00];
|
||||
|
|
|
@ -122,6 +122,18 @@
|
|||
#define GDT_LONG_DATA 48
|
||||
#define GDT_LONG_TSS 56
|
||||
|
||||
#define IRQ_IST 1 /* interrupt stack table (IST) entry to use for IRQs */
|
||||
#define EXCEP_IST 2 /* IST entry to use for CPU exceptions */
|
||||
|
||||
/*
|
||||
* @see Intel Corporation. 8259A Programmable Interrupt Controller (8259A/
|
||||
* 8259A-2). 1988. Intel order number 231468-003.
|
||||
* @see IBM. Technical Reference for the IBM Personal Computer AT. 1985,
|
||||
* Section 5: System BIOS, p. 5-34. https://archive.org/details/
|
||||
* IBMPCATIBM5170TechnicalReference6280070SEP85/page/n205/mode/2up .
|
||||
* @see Intel Corporation. 82371FB (PIIX) and 82371SB (PIIX3) PCI ISA IDE
|
||||
* Xcelerator. 1997. Intel order number 290550-002.
|
||||
*/
|
||||
#define PIC1 0x20 /* IO base address for master PIC */
|
||||
#define PIC2 0xA0 /* IO base address for slave PIC */
|
||||
#define PIC1_CMD PIC1
|
||||
|
@ -129,6 +141,9 @@
|
|||
#define PIC2_CMD PIC2
|
||||
#define PIC2_DATA (PIC2 + 1)
|
||||
#define PIC_EOI 0x20 /* End-of-interrupt command code */
|
||||
#define PIC_INIT 0x10 /* ICW1 initialize */
|
||||
#define PIC_IC4 0x01 /* ICW1 initialize needs ICW4 */
|
||||
#define PIC_UPM 0x01 /* ICW4 microprocessor mode (8086/8088 vs. 8085) */
|
||||
#define PIC_READ_IRR 0x0a /* OCW3 irq ready next CMD read */
|
||||
#define PIC_READ_ISR 0x0b /* OCW3 irq service next CMD read */
|
||||
|
||||
|
@ -223,6 +238,14 @@ forceinline void outb(unsigned short port, unsigned char byte) {
|
|||
: "a"(byte), "dN"(port));
|
||||
}
|
||||
|
||||
forceinline void disable(void) {
|
||||
asm volatile("cli" : : : "memory");
|
||||
}
|
||||
|
||||
forceinline void enable(void) {
|
||||
asm volatile("sti" : : : "memory");
|
||||
}
|
||||
|
||||
#define __clear_page(page) \
|
||||
({ \
|
||||
long di, cx; \
|
||||
|
|
|
@ -38,6 +38,7 @@ LIBC_RUNTIME_A_DIRECTDEPS = \
|
|||
LIBC_ELF \
|
||||
LIBC_FMT \
|
||||
LIBC_INTRIN \
|
||||
LIBC_IRQ \
|
||||
LIBC_NEXGEN32E \
|
||||
LIBC_NT_ADVAPI32 \
|
||||
LIBC_NT_KERNEL32 \
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue