1/*- 2 * Copyright (c) 2014 Antti Kantee. All Rights Reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS 14 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 15 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 16 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 17 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 18 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 19 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 20 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 23 * SUCH DAMAGE. 24 */ 25 26#include <hw/types.h> 27#include <hw/kernel.h> 28 29#include <bmk-core/core.h> 30#include <bmk-core/sched.h> 31 32/* 33 * i386 MD descriptors, assimilated from NetBSD sys/arch/i386/include/segments.h 34 */ 35 36struct region_descriptor { 37 unsigned short rd_limit:16; 38 unsigned int rd_base:32; 39} __attribute__((__packed__)); 40 41struct gate_descriptor { 42 unsigned gd_looffset:16; 43 unsigned gd_selector:16; 44 unsigned gd_stkcpy:5; 45 unsigned gd_xx:3; 46 unsigned gd_type:5; 47 unsigned gd_dpl:2; 48 unsigned gd_p:1; 49 unsigned gd_hioffset:16; 50} __attribute__((__packed__)); 51 52static struct gate_descriptor idt[256]; 53 54/* interrupt-not-service-routine */ 55void cpu_insr(void); 56 57void 58x86_fillgate(int num, void *fun, int unused) 59{ 60 struct gate_descriptor *gd = &idt[num]; 61 62 gd->gd_hioffset = (unsigned long)fun >> 16; 63 gd->gd_looffset = (unsigned long)fun; 64 65 /* i was born lucky */ 66 gd->gd_selector = 0x8; 67 gd->gd_stkcpy = 0; 68 gd->gd_xx = 0; 69 gd->gd_type = 14; 70 gd->gd_dpl = 0; 71 gd->gd_p = 1; 72} 73 74struct segment_descriptor { 75 unsigned sd_lolimit:16; 76 unsigned sd_lobase:24; 77 unsigned sd_type:5; 78 unsigned sd_dpl:2; 79 unsigned sd_p:1; 80 unsigned sd_hilimit:4; 81 unsigned sd_xx:2; 82 unsigned sd_def32:1; 83 unsigned sd_gran:1; 84 unsigned sd_hibase:8; 85} __attribute__((__packed__)); 86 87#define SDT_MEMRWA 19 /* memory read write accessed */ 88#define SDT_MEMERA 27 /* memory execute read accessed */ 89 90#define SEGMENT_CODE 1 91#define SEGMENT_DATA 2 92#define SEGMENT_GS 3 93 94#define SEG_BYTEGRAN 0 95#define SEG_PAGEGRAN 1 96 97static struct segment_descriptor gdt[4]; 98 99static void 100fillsegment(struct segment_descriptor *sd, int type) 101{ 102 103 sd->sd_lobase = 0; 104 sd->sd_hibase = 0; 105 106 sd->sd_lolimit = 0xffff; 107 sd->sd_hilimit = 0xf; 108 109 sd->sd_type = type; 110 111 /* i was born luckier */ 112 sd->sd_dpl = 0; 113 sd->sd_p = 1; 114 sd->sd_xx = 0; 115 sd->sd_def32 = 1; 116 sd->sd_gran = SEG_PAGEGRAN; 117} 118 119static void 120adjustgs(uintptr_t p) 121{ 122 struct segment_descriptor *sd = &gdt[SEGMENT_GS]; 123 124 sd->sd_lobase = p & 0xffffff; 125 sd->sd_hibase = (p >> 24) & 0xff; 126 127 __asm__ __volatile__("mov %0, %%gs" :: "r"(8*SEGMENT_GS)); 128} 129 130/* 131 * This routine fills out the interrupt descriptors so that 132 * we can handle interrupts without involving a jump to hyperspace. 133 */ 134void 135cpu_init(void) 136{ 137 struct region_descriptor region; 138 139 fillsegment(&gdt[SEGMENT_CODE], SDT_MEMERA); 140 fillsegment(&gdt[SEGMENT_DATA], SDT_MEMRWA); 141 fillsegment(&gdt[SEGMENT_GS], SDT_MEMRWA); 142 143 region.rd_limit = sizeof(gdt)-1; 144 region.rd_base = (unsigned int)(uintptr_t)(void *)gdt; 145 cpu_lgdt(®ion); 146 147 x86_initidt(); 148 region.rd_limit = sizeof(idt)-1; 149 region.rd_base = (unsigned int)(uintptr_t)(void *)idt; 150 cpu_lidt(®ion); 151 152 x86_initpic(); 153 154 x86_initclocks(); 155} 156 157void 158bmk_platform_cpu_sched_settls(struct bmk_tcb *next) 159{ 160 161 adjustgs(next->btcb_tp); 162} 163