From d882ff37ec2ca4698341ca07dc51686f5f9e42df Mon Sep 17 00:00:00 2001 From: "Hu, Hebo" Date: Wed, 20 Mar 2019 15:56:31 +0800 Subject: core/minute-ia: add IA32/x86 arch related data structure definitions includes GDT, LDT, IDT, and TSS tables data structures definitions BUG=b:122364080 BRANCH=none TEST=tested on arcada Change-Id: I2e9fea21501a16485fbc4e05163c1f2ffbbc17f4 Signed-off-by: Hu, Hebo Reviewed-on: https://chromium-review.googlesource.com/1531275 Commit-Ready: Hebo Hu Tested-by: Jett Rink Reviewed-by: Jack Rosenthal Reviewed-by: Jett Rink Reviewed-by: Hebo Hu --- core/minute-ia/ia_structs.h | 161 ++++++++++++++++++++++++++++++++++++++++++++ core/minute-ia/init.S | 35 +++++----- core/minute-ia/interrupts.c | 59 ++++++++-------- core/minute-ia/interrupts.h | 17 ----- 4 files changed, 204 insertions(+), 68 deletions(-) create mode 100644 core/minute-ia/ia_structs.h (limited to 'core') diff --git a/core/minute-ia/ia_structs.h b/core/minute-ia/ia_structs.h new file mode 100644 index 0000000000..08447cb242 --- /dev/null +++ b/core/minute-ia/ia_structs.h @@ -0,0 +1,161 @@ +/* Copyright 2019 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef __CROS_EC_IA_STRUCTS_H +#define __CROS_EC_IA_STRUCTS_H + +#ifndef __ASSEMBLER__ + +#include + + +/** + * IA32/x86 architecture related data structure definitions. + * including: Global Descriptor Table (GDT), Local Descriptor Table (LDT), + * Interrupt Descriptor Table (IDT) and Task State Segment (TSS) + * see: https://en.wikipedia.org/wiki/Global_Descriptor_Table + * https://en.wikipedia.org/wiki/Interrupt_descriptor_table + * https://en.wikipedia.org/wiki/Task_state_segment + */ + +/* GDT entry descriptor */ +struct gdt_entry { + union { + struct { + uint32_t dword_lo; /* lower dword */ + uint32_t dword_up; /* upper dword */ + }; + struct { + uint16_t limit_lw; /* limit (0:15) */ + uint16_t base_addr_lw; /* base address (0:15) */ + uint8_t base_addr_mb; /* base address (16:23) */ + uint8_t flags; /* flags */ + uint8_t limit_ub; /* limit (16:19) */ + uint8_t base_addr_ub; /* base address (24:31) */ + }; + }; + +} __packed; + +typedef struct gdt_entry ldt_entry; + +/* GDT header */ +struct gdt_header { + uint16_t limit; /* GDT limit size */ + struct gdt_entry *entries; /* pointer to GDT entries */ +} __packed; + +/* IDT entry descriptor */ +struct idt_entry { + union { + struct { + uint32_t dword_lo; /* lower dword */ + uint32_t dword_up; /* upper dword */ + }; + + struct { + uint16_t offset_lw; /* offset (0:15) */ + uint16_t seg_selector; /* segment selector */ + uint8_t zero; /* must be set to zero */ + uint8_t flags; /* flags */ + uint16_t offset_uw; /* offset (16:31) */ + }; + }; +} __packed; + +/* IDT header */ +struct idt_header { + uint16_t limit; /* IDT limit size */ + struct idt_entry *entries; /* pointer to IDT entries */ +} __packed; + +/* TSS entry descriptor */ +struct tss_entry { + uint16_t prev_task_link; + uint16_t reserved1; + uint8_t *esp0; + uint16_t ss0; + uint16_t reserved2; + uint8_t *esp1; + uint16_t ss1; + int16_t reserved3; + uint8_t *esp2; + uint16_t ss2; + uint16_t reserved4; + uint32_t cr3; + int32_t eip; + uint32_t eflags; + uint32_t eax; + uint32_t ecx; + int32_t edx; + uint32_t ebx; + uint32_t esp; + uint32_t ebp; + uint32_t esi; + uint32_t edi; + int16_t es; + uint16_t reserved5; + uint16_t cs; + uint16_t reserved6; + uint16_t ss; + uint16_t reserved7; + uint16_t ds; + uint16_t reserved8; + uint16_t fs; + uint16_t reserved9; + uint16_t gs; + uint16_t reserved10; + uint16_t ldt_seg_selector; + uint16_t reserved11; + uint16_t trap_debug; + /* offset from TSS base for I/O perms */ + uint16_t iomap_base_addr; +} __packed; + +#endif + +/* code segment flag, E/R, Present = 1, DPL = 0, Acesssed = 1 */ +#define GDT_DESC_CODE_FLAGS (0x9B) + +/* data segment flag, R/W, Present = 1, DPL = 0, Acesssed = 1 */ +#define GDT_DESC_DATA_FLAGS (0x93) + +/* TSS segment limit size */ +#define GDT_DESC_TSS_LIMIT (0x67) + +/* TSS segment flag, Present = 1, DPL = 0, Acesssed = 1 */ +#define GDT_DESC_TSS_FLAGS (0x89) + +/* LDT segment flag, Present = 1, DPL = 0 */ +#define GDT_DESC_LDT_FLAGS (0x82) + +/* IDT descriptor flag, Present = 1, DPL = 0, 32-bit interrupt gate */ +#define IDT_DESC_FLAGS (0x8E) + +/** + * macros helper to create a GDT entry descriptor + * set default 4096-byte pages for granularity + * base: 32bit base address + * limit: 32bit limit size of bytes (will covert to unit of 4096-byte pages) + * flags: 8bit flags + */ +#define GEN_GDT_DESC_LO(base, limit, flags) \ + ((((limit) >> 12) & 0xFFFF) | (((base) & 0xFFFF) << 16)) + +#define GEN_GDT_DESC_UP(base, limit, flags) \ + ((((base) >> 16) & 0xFF) | (((flags) << 8) & 0xFF00) | \ + (((limit) >> 12) & 0xFF0000) | ((base) & 0xFF000000) | 0xc00000) + + +/** + * macro helper to create a IDT entry descriptor + */ +#define GEN_IDT_DESC_LO(offset, selector, flags) \ + (((uint32_t)(offset) & 0xFFFF) | (((selector) & 0xFFFF) << 16)) + +#define GEN_IDT_DESC_UP(offset, selector, flags) \ + (((uint32_t)(offset) & 0xFFFF0000) | (((flags) & 0xFF) << 8)) + +#endif /* __CROS_EC_IA_STRUCTS_H */ diff --git a/core/minute-ia/init.S b/core/minute-ia/init.S index 907efe6913..8a5ec8e4e2 100644 --- a/core/minute-ia/init.S +++ b/core/minute-ia/init.S @@ -7,6 +7,7 @@ #include "config.h" #include "interrupts.h" +#include "ia_structs.h" .equ CR0_NW, (1 << 29) .equ CR0_CD, (1 << 30) @@ -25,7 +26,7 @@ .word def_irq_low # low 16 bits of default_int_handler .word code_seg .byte 0 - .byte IDT_FLAGS + .byte IDT_DESC_FLAGS .word def_irq_high # high 16 bits of default_int_handler .endm @@ -292,26 +293,20 @@ interrupt_descriptor # 255 __gdt: # Entry 0: Null descriptor - .word 0x0000 - .word 0x0000 - .byte 0x00 - .byte 0x00 - .byte 0x00 - .byte 0x00 + .long 0x0 + .long 0x0 # Entry 1: Code descriptor - .word 0xffff # Limit: xffff - .word 0x0000 # Base: xxxx0000 - .byte 0x00 # Base: xx00xxxx - .byte 0x9b # Code E/R, Present, DPL0, Acesssed=1 - .byte 0xcf # Limit fxxxx, Page Gra, 32 bit - .byte 0x00 # Base: 00xxxxxx - # Entry 0: Data descriptor - .word 0xffff # Limit: xffff - .word 0x0000 # Base: xxxx0000 - .byte 0x00 # Base: xx00xxxx - .byte 0x93 # Data R/W, Present, DPL0, Acesssed=1 - .byte 0xcf # Limit fxxxx, Page Gra, 32 bit - .byte 0x00 # Base: 00xxxxxx + # Base: 0x0 + # Limit: 0xffffffff + # Flags: 0x9b (Code E/R, Present, DPL0, Acessed=1) + .long GEN_GDT_DESC_LO(0x0, 0xffffffff, GDT_DESC_CODE_FLAGS) + .long GEN_GDT_DESC_UP(0x0, 0xffffffff, GDT_DESC_CODE_FLAGS) + # Entry 2: Data descriptor + # Base: 0x0 + # Limit: 0xffffffff + # Flags: 0x93 (Data R/W, Present, DPL0, Acessed=1) + .long GEN_GDT_DESC_LO(0x0, 0xffffffff, GDT_DESC_DATA_FLAGS) + .long GEN_GDT_DESC_UP(0x0, 0xffffffff, GDT_DESC_DATA_FLAGS) #.section .data __idt_ptr: diff --git a/core/minute-ia/interrupts.c b/core/minute-ia/interrupts.c index dab6ab5e99..ed455e699f 100644 --- a/core/minute-ia/interrupts.c +++ b/core/minute-ia/interrupts.c @@ -12,6 +12,7 @@ #include "task_defs.h" #include "irq_handler.h" #include "console.h" +#include "ia_structs.h" /* Console output macros */ #define CPUTS(outstr) cputs(CC_SYSTEM, outstr) @@ -19,7 +20,7 @@ #define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ## args) /* The IDT - initialized in init.S */ -extern IDT_entry __idt[NUM_VECTORS]; +extern struct idt_entry __idt[NUM_VECTORS]; /* To count the interrupt nesting depth. Usually it is not nested */ volatile uint32_t __in_isr; @@ -149,16 +150,12 @@ DEFINE_EXN_HANDLER(20); void set_interrupt_gate(uint8_t num, isr_handler_t func, uint8_t flags) { uint16_t code_segment; - uint32_t base = (uint32_t) func; - - __idt[num].ISR_low = (uint16_t) (base & USHRT_MAX); - __idt[num].ISR_high = (uint16_t) ((base >> 16UL) & USHRT_MAX); /* When the flat model is used the CS will never change. */ __asm volatile ("mov %%cs, %0":"=r" (code_segment)); - __idt[num].segment_selector = code_segment; - __idt[num].zero = 0; - __idt[num].flags = flags; + + __idt[num].dword_lo = GEN_IDT_DESC_LO(func, code_segment, flags); + __idt[num].dword_up = GEN_IDT_DESC_UP(func, code_segment, flags); } /** @@ -312,11 +309,11 @@ void init_interrupts(void) /* Setup gates for IRQs declared by drivers using DECLARE_IRQ */ for (; p < __irq_data_end; p++) - set_interrupt_gate(IRQ_TO_VEC(p->irq), p->routine, IDT_FLAGS); + set_interrupt_gate(IRQ_TO_VEC(p->irq), p->routine, IDT_DESC_FLAGS); /* Setup gate for LAPIC_LVT_ERROR vector */ set_interrupt_gate(LAPIC_LVT_ERROR_VECTOR, _lapic_error_handler, - IDT_FLAGS); + IDT_DESC_FLAGS); /* Mask all interrupts by default in IOAPIC */ for (entry = 0; entry < max_entries; entry++) @@ -332,29 +329,29 @@ void init_interrupts(void) system_irqs[entry].polarity | system_irqs[entry].trigger); - set_interrupt_gate(ISH_TS_VECTOR, __switchto, IDT_FLAGS); + set_interrupt_gate(ISH_TS_VECTOR, __switchto, IDT_DESC_FLAGS); /* Bind exception handlers to print panic message */ - set_interrupt_gate(0, exception_panic_0, IDT_FLAGS); - set_interrupt_gate(1, exception_panic_1, IDT_FLAGS); - set_interrupt_gate(2, exception_panic_2, IDT_FLAGS); - set_interrupt_gate(3, exception_panic_3, IDT_FLAGS); - set_interrupt_gate(4, exception_panic_4, IDT_FLAGS); - set_interrupt_gate(5, exception_panic_5, IDT_FLAGS); - set_interrupt_gate(6, exception_panic_6, IDT_FLAGS); - set_interrupt_gate(7, exception_panic_7, IDT_FLAGS); - set_interrupt_gate(8, exception_panic_8, IDT_FLAGS); - set_interrupt_gate(9, exception_panic_9, IDT_FLAGS); - set_interrupt_gate(10, exception_panic_10, IDT_FLAGS); - set_interrupt_gate(11, exception_panic_11, IDT_FLAGS); - set_interrupt_gate(12, exception_panic_12, IDT_FLAGS); - set_interrupt_gate(13, exception_panic_13, IDT_FLAGS); - set_interrupt_gate(14, exception_panic_14, IDT_FLAGS); - set_interrupt_gate(16, exception_panic_16, IDT_FLAGS); - set_interrupt_gate(17, exception_panic_17, IDT_FLAGS); - set_interrupt_gate(18, exception_panic_18, IDT_FLAGS); - set_interrupt_gate(19, exception_panic_19, IDT_FLAGS); - set_interrupt_gate(20, exception_panic_20, IDT_FLAGS); + set_interrupt_gate(0, exception_panic_0, IDT_DESC_FLAGS); + set_interrupt_gate(1, exception_panic_1, IDT_DESC_FLAGS); + set_interrupt_gate(2, exception_panic_2, IDT_DESC_FLAGS); + set_interrupt_gate(3, exception_panic_3, IDT_DESC_FLAGS); + set_interrupt_gate(4, exception_panic_4, IDT_DESC_FLAGS); + set_interrupt_gate(5, exception_panic_5, IDT_DESC_FLAGS); + set_interrupt_gate(6, exception_panic_6, IDT_DESC_FLAGS); + set_interrupt_gate(7, exception_panic_7, IDT_DESC_FLAGS); + set_interrupt_gate(8, exception_panic_8, IDT_DESC_FLAGS); + set_interrupt_gate(9, exception_panic_9, IDT_DESC_FLAGS); + set_interrupt_gate(10, exception_panic_10, IDT_DESC_FLAGS); + set_interrupt_gate(11, exception_panic_11, IDT_DESC_FLAGS); + set_interrupt_gate(12, exception_panic_12, IDT_DESC_FLAGS); + set_interrupt_gate(13, exception_panic_13, IDT_DESC_FLAGS); + set_interrupt_gate(14, exception_panic_14, IDT_DESC_FLAGS); + set_interrupt_gate(16, exception_panic_16, IDT_DESC_FLAGS); + set_interrupt_gate(17, exception_panic_17, IDT_DESC_FLAGS); + set_interrupt_gate(18, exception_panic_18, IDT_DESC_FLAGS); + set_interrupt_gate(19, exception_panic_19, IDT_DESC_FLAGS); + set_interrupt_gate(20, exception_panic_20, IDT_DESC_FLAGS); /* Note: At reset, ID field is already set to 0 in APIC ID register */ diff --git a/core/minute-ia/interrupts.h b/core/minute-ia/interrupts.h index d962afccf0..1a5e44d1ee 100644 --- a/core/minute-ia/interrupts.h +++ b/core/minute-ia/interrupts.h @@ -37,14 +37,6 @@ typedef struct { #define DEST_APIC_ID 0 #define NUM_VECTORS 256 -/* Default flags setting for entries in the IDT. - * 7 - Present bit - * 6:5 - Descriptor privilege level - * 4 - Storage segment (0 for interrupt gate) - * 3:0 - Gate type (1110 = Interrupt gate) - */ -#define IDT_FLAGS 0x8E - /* APIC bit definitions. */ #define APIC_DIV_16 0x03 #define APIC_ENABLE_BIT (1UL << 8UL) @@ -52,15 +44,6 @@ typedef struct { #define APIC_LVT_ERROR REG32(ISH_LAPIC_BASE + 0x370UL) #ifndef __ASSEMBLER__ -/* Interrupt descriptor entry */ -struct IDT_entry_t { - uint16_t ISR_low; /* Low 16 bits of handler address. */ - uint16_t segment_selector; /* Flat model means this is not changed. */ - uint8_t zero; /* Must be set to zero. */ - uint8_t flags; /* Flags for this entry. */ - uint16_t ISR_high; /* High 16 bits of handler address. */ -} __attribute__ ((packed)); -typedef struct IDT_entry_t IDT_entry; typedef void (*isr_handler_t) (void); -- cgit v1.2.1