Changeset b9e97fb in mainline for arch/amd64/src/pm.c


Ignore:
Timestamp:
2005-08-31T10:53:34Z (20 years ago)
Author:
Ondrej Palkovsky <ondrap@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
8f91729
Parents:
9756131
Message:

Better types for ia32 drivers, so that they can be reused in amd64.
Build script cleanup amd64.
New code / not working yet / in amd64.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • arch/amd64/src/pm.c

    r9756131 rb9e97fb  
    3030#include <arch/mm/page.h>
    3131#include <arch/types.h>
    32 
     32#include <arch/interrupt.h>
     33#include <arch/asm.h>
     34
     35#include <config.h>
     36
     37#include <memstr.h>
     38#include <mm/heap.h>
     39#include <debug.h>
    3340
    3441/*
     
    7279          .longmode    = 1,
    7380          .special     = 0,
    74           .granularity = 0,
     81          .granularity = 1,
    7582          .base_24_31  = 0 },
    7683        /* UDATA descriptor */
     
    96103          .granularity = 1,
    97104          .base_24_31  = 0 },
    98         /* TSS descriptor - set up will be completed later */
     105        /* TSS descriptor - set up will be completed later,
     106         * on AMD64 it is 64-bit - 2 items in table */
     107        { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
    99108        { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
    100109};
    101110
     111struct ptr_16_64 gdtr = {.limit = sizeof(gdtr), .base= (__u64) &gdtr };
     112
    102113struct idescriptor idt[IDT_ITEMS];
    103114
    104115static struct tss tss;
    105116
    106 /* Does not compile correctly if it does not exist */
     117/* TODO: Does not compile correctly if it does not exist ???? */
    107118int __attribute__ ((section ("K_DATA_START"))) __fake;
     119
     120void gdt_tss_setbase(struct descriptor *d, __address base)
     121{
     122        struct tss_descriptor *td = (struct tss_descriptor *) d;
     123
     124        td->base_0_15 = base & 0xffff;
     125        td->base_16_23 = ((base) >> 16) & 0xff;
     126        td->base_24_31 = ((base) >> 24) & 0xff;
     127        td->base_32_63 = ((base) >> 32);
     128}
     129
     130void gdt_tss_setlimit(struct descriptor *d, __u32 limit)
     131{
     132        struct tss_descriptor *td = (struct tss_descriptor *) d;
     133
     134        td->limit_0_15 = limit & 0xffff;
     135        td->limit_16_19 = (limit >> 16) & 0xf;
     136}
     137
     138void idt_setoffset(struct idescriptor *d, __address offset)
     139{
     140        /*
     141         * Offset is a linear address.
     142         */
     143        d->offset_0_15 = offset & 0xffff;
     144        d->offset_16_31 = offset >> 16 & 0xffff;
     145        d->offset_32_63 = offset >> 32;
     146}
     147
     148void tss_initialize(struct tss *t)
     149{
     150        memsetb((__address) t, sizeof(struct tss), 0);
     151}
     152
     153/*
     154 * This function takes care of proper setup of IDT and IDTR.
     155 */
     156void idt_init(void)
     157{
     158        struct idescriptor *d;
     159        int i;
     160
     161        for (i = 0; i < IDT_ITEMS; i++) {
     162                d = &idt[i];
     163
     164                d->unused = 0;
     165                d->selector = idtselector(KTEXT_DES);
     166
     167                d->present = 1;
     168                d->type = AR_INTERRUPT; /* masking interrupt */
     169
     170                if (i == VECTOR_SYSCALL) {
     171                        /*
     172                         * The syscall interrupt gate must be calleable from userland.
     173                         */
     174                        d->dpl |= PL_USER;
     175                }
     176               
     177                idt_setoffset(d, ((__address) interrupt_handlers) + i*interrupt_handler_size);
     178                trap_register(i, null_interrupt);
     179        }
     180        trap_register(13, gp_fault);
     181        trap_register( 7, nm_fault);
     182        trap_register(12, ss_fault);
     183}
     184
     185
     186/* Clean IOPL(12,13) and NT(14) flags in EFLAGS register */
     187static void clean_IOPL_NT_flags(void)
     188{
     189        asm
     190        (
     191                "pushfq;"
     192                "pop %%rax;"
     193                "and $~(0x7000),%%rax;"
     194                "pushq %%rax;"
     195                "popfq;"
     196                :
     197                :
     198                :"%rax"
     199        );
     200}
     201
     202/* Clean AM(18) flag in CR0 register */
     203static void clean_AM_flag(void)
     204{
     205        asm
     206        (
     207                "mov %%cr0,%%rax;"
     208                "and $~(0x40000),%%rax;"
     209                "mov %%rax,%%cr0;"
     210                :
     211                :
     212                :"%rax"
     213        );
     214}
     215
     216void pm_init(void)
     217{
     218        struct descriptor *gdt_p = (struct descriptor *) PA2KA(gdtr.base);
     219        struct tss_descriptor *tss_d;
     220
     221        /*
     222         * Each CPU has its private GDT and TSS.
     223         * All CPUs share one IDT.
     224         */
     225
     226        if (config.cpu_active == 1) {
     227                idt_init();
     228                /*
     229                 * NOTE: bootstrap CPU has statically allocated TSS, because
     230                 * the heap hasn't been initialized so far.
     231                 */
     232                tss_p = &tss;
     233        }
     234        else {
     235                tss_p = (struct tss *) malloc(sizeof(struct tss));
     236                if (!tss_p)
     237                        panic("could not allocate TSS\n");
     238        }
     239
     240        tss_initialize(tss_p);
     241
     242        tss_d = (struct tss_descriptor *) &gdt_p[TSS_DES];
     243        tss_d[TSS_DES].present = 1;
     244        tss_d[TSS_DES].type = AR_TSS;
     245        tss_d[TSS_DES].dpl = PL_KERNEL;
     246       
     247        gdt_tss_setbase(&gdt_p[TSS_DES], (__address) tss_p);
     248        gdt_tss_setlimit(&gdt_p[TSS_DES], sizeof(struct tss) - 1);
     249
     250        /*
     251         * As of this moment, the current CPU has its own GDT pointing
     252         * to its own TSS. We just need to load the TR register.
     253         */
     254        __asm__("ltr %0" : : "r" ((__u16) gdtselector(TSS_DES)));
     255       
     256        clean_IOPL_NT_flags();    /* Disable I/O on nonprivileged levels */
     257        clean_AM_flag();          /* Disable alignment check */
     258}
Note: See TracChangeset for help on using the changeset viewer.