[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [tyndur-devel] [PATCH 4/4] kernel2: GDT für AMD64



On Sun, Dec 30, 2012 at 08:01:34PM +0100, Andreas Freimuth wrote:
>  + amd64/gdt.c: ordentliche GDT angelegt und init-Funktionen implementiert
>  * amd64/loader/startup.S: die SYSCALL- und SYSRET-Instruktion geht von einer
>    bestimmten Reihenfolge der Segmente aus, deshalb sollte das
>    64-Bit-Code-Segment auf der 0x18 hinter dem Data-Segment landen.
>  - amd64/header.S: das Laden der GDT entfernt, da das in der init-Funktion
>    geschieht
>  * amd64/smp/trampoline.S: das richtige Segment nach CS laden
> 
> Signed-off-by: Andreas Freimuth <m.nemo@xxxxxxx>
> ---
>  src/kernel2/src/arch/amd64/gdt.c            | 134 ++++++++++++++++++++++++++++
>  src/kernel2/src/arch/amd64/header.S         |  29 ------
>  src/kernel2/src/arch/amd64/loader/startup.S |  42 +++------
>  src/kernel2/src/arch/amd64/smp/trampoline.S |  32 +------
>  4 files changed, 147 insertions(+), 90 deletions(-)
>  create mode 100644 src/kernel2/src/arch/amd64/gdt.c
> 
> diff --git a/src/kernel2/src/arch/amd64/gdt.c b/src/kernel2/src/arch/amd64/gdt.c
> new file mode 100644
> index 0000000..5e7bd60
> --- /dev/null
> +++ b/src/kernel2/src/arch/amd64/gdt.c
> @@ -0,0 +1,134 @@
> +/*
> + * Copyright © 2012 The týndur Project. All rights reserved.
> + *
> + * Redistribution and use in source and binary forms, with or without
> + * modification, are permitted provided that the following conditions
> + * are met:
> + * 1. Redistributions of source code must retain the above copyright
> + *    notice, this list of conditions and the following disclaimer.
> + * 2. Redistributions in binary form must reproduce the above copyright
> + *    notice, this list of conditions and the following disclaimer in the
> + *    documentation and/or other materials provided with the distribution.
> + *
> + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
> + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
> + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
> + * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
> + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
> + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
> + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
> + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
> + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
> + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
> + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
> + */
> +
> +#include <stdint.h>
> +
> +#include "gdt.h"
> +
> +#define SEGMENT_DATA    0x0000120000000000ULL
> +#define SEGMENT_CODE    0x0000180000000000ULL
> +#define SEGMENT_TSS     0x0000090000000000ULL
> +#define SEGMENT_USER    0x0000600000000000ULL
> +#define SEGMENT_PRESENT 0x0000800000000000ULL
> +#define SEGMENT_LM      0x0020000000000000ULL
> +#define SEGMENT_32BIT   0x0040000000000000ULL
> +#define SEGMENT_GRAN    0x0080000000000000ULL
> +#define SEGMENT_BASE(x)   (((x & 0xffffULL) << 16) | ((x & 0xff0000ULL) << 16) | ((x & 0xff000000ULL) << 32))
> +#define SEGMENT_BASE64(x) ((x >> 32) & 0xffffffffULL)
> +#define SEGMENT_SIZE(x)   ((x & 0xffffULL) | ((x & 0xf0000ULL) << 32))
> +
> +typedef union Descriptor {
> +    struct { /// Segment descriptor
> +        uint16_t size1;
> +        uint16_t base1;
> +        uint8_t base2;
> +        uint8_t type:4;
> +        uint8_t seg:1;
> +        uint8_t dpl:2;
> +        uint8_t present:1;
> +        uint8_t size2:4;
> +        uint8_t avl:1;
> +        uint8_t longMode:1;
> +        uint8_t operandSize:1;
> +        uint8_t granularity:1;
> +        uint8_t base3;
> +    } __attribute__((__packed__)) segment;
> +
> +    struct { /// TSS descriptor
> +        uint16_t limit1;
> +        uint16_t base1;
> +        uint8_t base2;
> +        uint8_t type:4;
> +        uint8_t seg:1;
> +        uint8_t dpl:2;
> +        uint8_t present:1;
> +        uint8_t limit2;
> +        uint8_t base3;
> +    } __attribute__((__packed__)) tss;
> +
> +    struct { /// Callgate descriptor
> +        uint16_t offset1;
> +        uint16_t selector;
> +        uint8_t count:5;
> +        uint8_t reserved:3;
> +        uint8_t type:4;
> +        uint8_t seg:1;
> +        uint8_t dpl:2;
> +        uint8_t present:1;
> +        uint16_t offset2;
> +    } __attribute__((__packed__)) callgate;
> +
> +    uint64_t u64;
> +
> +} Descriptor;

Bitfelder sind böse, es ist nämlich nicht genau definiert, in welcher
Reihenfolge die Bits innerhalb eines Bytes kommen.

Das macht deinem Code nicht aus, weil du sowieso nur ber .u64 arbeitest,
aber dann müsstest du die Bitfelder ja auch gar nicht erst deklarieren
;-)

Wir benutzen auch tendenziell keine typedefs und großgeschriebene
Typnamen, wobei das in der codestil.txt nicht explizit drinsteht und ich
deswegen nicht lang deswegen rummache, wenn du es so schöner findest...

> +
> +struct {
> +    uint16_t limit;
> +    uintptr_t base;
> +} gdtr;
> +
> +/// Global Descritpor Table

Hier ist wohl irgendein Sonderzeichen nach dem ///

> +static Descriptor gdt[9] = {
> +    // NULL Deskriptor
> +    { .u64 = 0 },
> +
> +    // Kernel Code-Segment 32Bit
> +    { .u64 = SEGMENT_BASE(0LL) | SEGMENT_SIZE(0xfffffLL) | SEGMENT_GRAN |
> +            SEGMENT_CODE | SEGMENT_32BIT | SEGMENT_PRESENT },
> +
> +    // Kernel Data-Segment
> +    { .u64 = SEGMENT_BASE(0LL) | SEGMENT_SIZE(0xfffffLL) | SEGMENT_GRAN |
> +            SEGMENT_DATA | SEGMENT_32BIT | SEGMENT_PRESENT },
> +
> +    // Kernel Code-Segment 64Bit
> +    { .u64 = SEGMENT_CODE | SEGMENT_LM | SEGMENT_PRESENT },
> +
> +    // User Code-Segment 32Bit
> +    { .u64 = SEGMENT_BASE(0LL) | SEGMENT_SIZE(0xfffffLL) | SEGMENT_GRAN |
> +            SEGMENT_CODE | SEGMENT_32BIT | SEGMENT_USER | SEGMENT_PRESENT },
> +
> +    // User Data-Segment
> +    { .u64 = SEGMENT_BASE(0LL) | SEGMENT_SIZE(0xfffffLL) | SEGMENT_GRAN |
> +            SEGMENT_DATA | SEGMENT_32BIT | SEGMENT_USER | SEGMENT_PRESENT },
> +
> +    // User Code-Segment 64Bit
> +    { .u64 = SEGMENT_CODE | SEGMENT_LM | SEGMENT_USER | SEGMENT_PRESENT },
> +
> +    // Task State - Segment
> +    { .u64 = SEGMENT_BASE((uintptr_t) 0 /*TODO*/) |
> +            SEGMENT_SIZE(0x67) | SEGMENT_TSS | SEGMENT_PRESENT },
> +    { .u64 = SEGMENT_BASE64((uintptr_t) 0 /*TODO*/) }
> +};

Das habe ich genausowenig geprüft wie den Assemblercode unten, aber wenn
es bootet, wird es schon richtig sein. :-)

Kevin