summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHu, Hebo <hebo.hu@intel.com>2019-03-20 15:56:31 +0800
committerchrome-bot <chrome-bot@chromium.org>2019-04-02 23:16:11 -0700
commitd882ff37ec2ca4698341ca07dc51686f5f9e42df (patch)
tree5c7433f8561f0588e87e065424202bfc44ec0cb2
parent95bfcd20a42cfccad02f4f76edfdf9684520fca7 (diff)
downloadchrome-ec-d882ff37ec2ca4698341ca07dc51686f5f9e42df.tar.gz
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 <hebo.hu@intel.com> Reviewed-on: https://chromium-review.googlesource.com/1531275 Commit-Ready: Hebo Hu <hebo.hu@intel.corp-partner.google.com> Tested-by: Jett Rink <jettrink@chromium.org> Reviewed-by: Jack Rosenthal <jrosenth@chromium.org> Reviewed-by: Jett Rink <jettrink@chromium.org> Reviewed-by: Hebo Hu <hebo.hu@intel.corp-partner.google.com>
-rw-r--r--core/minute-ia/ia_structs.h161
-rw-r--r--core/minute-ia/init.S35
-rw-r--r--core/minute-ia/interrupts.c59
-rw-r--r--core/minute-ia/interrupts.h17
4 files changed, 204 insertions, 68 deletions
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 <stdint.h>
+
+
+/**
+ * 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);