Commit 625efab1 authored by Jes Sorensen's avatar Jes Sorensen Committed by Rusty Russell

Move i386 part of core.c to x86/core.c.

Separate i386 architecture specific from core.c and move it to
x86/core.c and add x86/lguest.h header file to match.
Signed-off-by: default avatarJes Sorensen <jes@sgi.com>
Signed-off-by: default avatarRusty Russell <rusty@rustcorp.com.au>
parent 56adbe9d
...@@ -65,6 +65,7 @@ ...@@ -65,6 +65,7 @@
#include <asm/e820.h> #include <asm/e820.h>
#include <asm/mce.h> #include <asm/mce.h>
#include <asm/io.h> #include <asm/io.h>
#include <asm/i387.h>
/*G:010 Welcome to the Guest! /*G:010 Welcome to the Guest!
* *
......
...@@ -6,7 +6,7 @@ obj-$(CONFIG_LGUEST) += lg.o ...@@ -6,7 +6,7 @@ obj-$(CONFIG_LGUEST) += lg.o
lg-y = core.o hypercalls.o page_tables.o interrupts_and_traps.o \ lg-y = core.o hypercalls.o page_tables.o interrupts_and_traps.o \
segments.o io.o lguest_user.o segments.o io.o lguest_user.o
lg-$(CONFIG_X86_32) += x86/switcher_32.o lg-$(CONFIG_X86_32) += x86/switcher_32.o x86/core.o
Preparation Preparation!: PREFIX=P Preparation Preparation!: PREFIX=P
Guest: PREFIX=G Guest: PREFIX=G
......
This diff is collapsed.
...@@ -165,7 +165,7 @@ void maybe_do_interrupt(struct lguest *lg) ...@@ -165,7 +165,7 @@ void maybe_do_interrupt(struct lguest *lg)
/* Look at the IDT entry the Guest gave us for this interrupt. The /* Look at the IDT entry the Guest gave us for this interrupt. The
* first 32 (FIRST_EXTERNAL_VECTOR) entries are for traps, so we skip * first 32 (FIRST_EXTERNAL_VECTOR) entries are for traps, so we skip
* over them. */ * over them. */
idt = &lg->idt[FIRST_EXTERNAL_VECTOR+irq]; idt = &lg->arch.idt[FIRST_EXTERNAL_VECTOR+irq];
/* If they don't have a handler (yet?), we just ignore it */ /* If they don't have a handler (yet?), we just ignore it */
if (idt_present(idt->a, idt->b)) { if (idt_present(idt->a, idt->b)) {
/* OK, mark it no longer pending and deliver it. */ /* OK, mark it no longer pending and deliver it. */
...@@ -197,14 +197,14 @@ int deliver_trap(struct lguest *lg, unsigned int num) ...@@ -197,14 +197,14 @@ int deliver_trap(struct lguest *lg, unsigned int num)
{ {
/* Trap numbers are always 8 bit, but we set an impossible trap number /* Trap numbers are always 8 bit, but we set an impossible trap number
* for traps inside the Switcher, so check that here. */ * for traps inside the Switcher, so check that here. */
if (num >= ARRAY_SIZE(lg->idt)) if (num >= ARRAY_SIZE(lg->arch.idt))
return 0; return 0;
/* Early on the Guest hasn't set the IDT entries (or maybe it put a /* Early on the Guest hasn't set the IDT entries (or maybe it put a
* bogus one in): if we fail here, the Guest will be killed. */ * bogus one in): if we fail here, the Guest will be killed. */
if (!idt_present(lg->idt[num].a, lg->idt[num].b)) if (!idt_present(lg->arch.idt[num].a, lg->arch.idt[num].b))
return 0; return 0;
set_guest_interrupt(lg, lg->idt[num].a, lg->idt[num].b, has_err(num)); set_guest_interrupt(lg, lg->arch.idt[num].a, lg->arch.idt[num].b, has_err(num));
return 1; return 1;
} }
...@@ -341,10 +341,10 @@ void load_guest_idt_entry(struct lguest *lg, unsigned int num, u32 lo, u32 hi) ...@@ -341,10 +341,10 @@ void load_guest_idt_entry(struct lguest *lg, unsigned int num, u32 lo, u32 hi)
lg->changed |= CHANGED_IDT; lg->changed |= CHANGED_IDT;
/* Check that the Guest doesn't try to step outside the bounds. */ /* Check that the Guest doesn't try to step outside the bounds. */
if (num >= ARRAY_SIZE(lg->idt)) if (num >= ARRAY_SIZE(lg->arch.idt))
kill_guest(lg, "Setting idt entry %u", num); kill_guest(lg, "Setting idt entry %u", num);
else else
set_trap(lg, &lg->idt[num], num, lo, hi); set_trap(lg, &lg->arch.idt[num], num, lo, hi);
} }
/* The default entry for each interrupt points into the Switcher routines which /* The default entry for each interrupt points into the Switcher routines which
...@@ -387,7 +387,7 @@ void copy_traps(const struct lguest *lg, struct desc_struct *idt, ...@@ -387,7 +387,7 @@ void copy_traps(const struct lguest *lg, struct desc_struct *idt,
/* We can simply copy the direct traps, otherwise we use the default /* We can simply copy the direct traps, otherwise we use the default
* ones in the Switcher: they will return to the Host. */ * ones in the Switcher: they will return to the Host. */
for (i = 0; i < ARRAY_SIZE(lg->idt); i++) { for (i = 0; i < ARRAY_SIZE(lg->arch.idt); i++) {
/* If no Guest can ever override this trap, leave it alone. */ /* If no Guest can ever override this trap, leave it alone. */
if (!direct_trap(i)) if (!direct_trap(i))
continue; continue;
...@@ -396,8 +396,8 @@ void copy_traps(const struct lguest *lg, struct desc_struct *idt, ...@@ -396,8 +396,8 @@ void copy_traps(const struct lguest *lg, struct desc_struct *idt,
* Interrupt gates (type 14) disable interrupts as they are * Interrupt gates (type 14) disable interrupts as they are
* entered, which we never let the Guest do. Not present * entered, which we never let the Guest do. Not present
* entries (type 0x0) also can't go direct, of course. */ * entries (type 0x0) also can't go direct, of course. */
if (idt_type(lg->idt[i].a, lg->idt[i].b) == 0xF) if (idt_type(lg->arch.idt[i].a, lg->arch.idt[i].b) == 0xF)
idt[i] = lg->idt[i]; idt[i] = lg->arch.idt[i];
else else
/* Reset it to the default. */ /* Reset it to the default. */
default_idt_entry(&idt[i], i, def[i]); default_idt_entry(&idt[i], i, def[i]);
......
#ifndef _LGUEST_H #ifndef _LGUEST_H
#define _LGUEST_H #define _LGUEST_H
#include <asm/desc.h>
#define GDT_ENTRY_LGUEST_CS 10
#define GDT_ENTRY_LGUEST_DS 11
#define LGUEST_CS (GDT_ENTRY_LGUEST_CS * 8)
#define LGUEST_DS (GDT_ENTRY_LGUEST_DS * 8)
#ifndef __ASSEMBLY__ #ifndef __ASSEMBLY__
#include <linux/types.h> #include <linux/types.h>
#include <linux/init.h> #include <linux/init.h>
...@@ -18,34 +11,12 @@ ...@@ -18,34 +11,12 @@
#include <linux/wait.h> #include <linux/wait.h>
#include <linux/err.h> #include <linux/err.h>
#include <asm/semaphore.h> #include <asm/semaphore.h>
#include "irq_vectors.h"
#define GUEST_PL 1
struct lguest_regs #include <asm/lguest.h>
{
/* Manually saved part. */
unsigned long ebx, ecx, edx;
unsigned long esi, edi, ebp;
unsigned long gs;
unsigned long eax;
unsigned long fs, ds, es;
unsigned long trapnum, errcode;
/* Trap pushed part */
unsigned long eip;
unsigned long cs;
unsigned long eflags;
unsigned long esp;
unsigned long ss;
};
void free_pagetables(void); void free_pagetables(void);
int init_pagetables(struct page **switcher_page, unsigned int pages); int init_pagetables(struct page **switcher_page, unsigned int pages);
/* Full 4G segment descriptors, suitable for CS and DS. */
#define FULL_EXEC_SEGMENT ((struct desc_struct){0x0000ffff, 0x00cf9b00})
#define FULL_SEGMENT ((struct desc_struct){0x0000ffff, 0x00cf9300})
struct lguest_dma_info struct lguest_dma_info
{ {
struct list_head list; struct list_head list;
...@@ -98,23 +69,6 @@ struct pgdir ...@@ -98,23 +69,6 @@ struct pgdir
spgd_t *pgdir; spgd_t *pgdir;
}; };
/* This is a guest-specific page (mapped ro) into the guest. */
struct lguest_ro_state
{
/* Host information we need to restore when we switch back. */
u32 host_cr3;
struct Xgt_desc_struct host_idt_desc;
struct Xgt_desc_struct host_gdt_desc;
u32 host_sp;
/* Fields which are used when guest is running. */
struct Xgt_desc_struct guest_idt_desc;
struct Xgt_desc_struct guest_gdt_desc;
struct i386_hw_tss guest_tss;
struct desc_struct guest_idt[IDT_ENTRIES];
struct desc_struct guest_gdt[GDT_ENTRIES];
};
/* We have two pages shared with guests, per cpu. */ /* We have two pages shared with guests, per cpu. */
struct lguest_pages struct lguest_pages
{ {
...@@ -180,11 +134,7 @@ struct lguest ...@@ -180,11 +134,7 @@ struct lguest
/* Dead? */ /* Dead? */
const char *dead; const char *dead;
/* The GDT entries copied into lguest_ro_state when running. */ struct lguest_arch arch;
struct desc_struct gdt[GDT_ENTRIES];
/* The IDT entries: some copied into lguest_ro_state when running. */
struct desc_struct idt[IDT_ENTRIES];
/* Virtual clock device */ /* Virtual clock device */
struct hrtimer hrt; struct hrtimer hrt;
...@@ -239,6 +189,15 @@ void map_switcher_in_guest(struct lguest *lg, struct lguest_pages *pages); ...@@ -239,6 +189,15 @@ void map_switcher_in_guest(struct lguest *lg, struct lguest_pages *pages);
int demand_page(struct lguest *info, unsigned long cr2, int errcode); int demand_page(struct lguest *info, unsigned long cr2, int errcode);
void pin_page(struct lguest *lg, unsigned long vaddr); void pin_page(struct lguest *lg, unsigned long vaddr);
/* <arch>/core.c: */
void lguest_arch_host_init(void);
void lguest_arch_host_fini(void);
void lguest_arch_run_guest(struct lguest *lg);
void lguest_arch_handle_trap(struct lguest *lg);
/* <arch>/switcher.S: */
extern char start_switcher_text[], end_switcher_text[], switch_to_guest[];
/* lguest_user.c: */ /* lguest_user.c: */
int lguest_device_init(void); int lguest_device_init(void);
void lguest_device_remove(void); void lguest_device_remove(void);
......
...@@ -73,14 +73,14 @@ static void fixup_gdt_table(struct lguest *lg, unsigned start, unsigned end) ...@@ -73,14 +73,14 @@ static void fixup_gdt_table(struct lguest *lg, unsigned start, unsigned end)
/* Segment descriptors contain a privilege level: the Guest is /* Segment descriptors contain a privilege level: the Guest is
* sometimes careless and leaves this as 0, even though it's * sometimes careless and leaves this as 0, even though it's
* running at privilege level 1. If so, we fix it here. */ * running at privilege level 1. If so, we fix it here. */
if ((lg->gdt[i].b & 0x00006000) == 0) if ((lg->arch.gdt[i].b & 0x00006000) == 0)
lg->gdt[i].b |= (GUEST_PL << 13); lg->arch.gdt[i].b |= (GUEST_PL << 13);
/* Each descriptor has an "accessed" bit. If we don't set it /* Each descriptor has an "accessed" bit. If we don't set it
* now, the CPU will try to set it when the Guest first loads * now, the CPU will try to set it when the Guest first loads
* that entry into a segment register. But the GDT isn't * that entry into a segment register. But the GDT isn't
* writable by the Guest, so bad things can happen. */ * writable by the Guest, so bad things can happen. */
lg->gdt[i].b |= 0x00000100; lg->arch.gdt[i].b |= 0x00000100;
} }
} }
...@@ -106,12 +106,12 @@ void setup_default_gdt_entries(struct lguest_ro_state *state) ...@@ -106,12 +106,12 @@ void setup_default_gdt_entries(struct lguest_ro_state *state)
void setup_guest_gdt(struct lguest *lg) void setup_guest_gdt(struct lguest *lg)
{ {
/* Start with full 0-4G segments... */ /* Start with full 0-4G segments... */
lg->gdt[GDT_ENTRY_KERNEL_CS] = FULL_EXEC_SEGMENT; lg->arch.gdt[GDT_ENTRY_KERNEL_CS] = FULL_EXEC_SEGMENT;
lg->gdt[GDT_ENTRY_KERNEL_DS] = FULL_SEGMENT; lg->arch.gdt[GDT_ENTRY_KERNEL_DS] = FULL_SEGMENT;
/* ...except the Guest is allowed to use them, so set the privilege /* ...except the Guest is allowed to use them, so set the privilege
* level appropriately in the flags. */ * level appropriately in the flags. */
lg->gdt[GDT_ENTRY_KERNEL_CS].b |= (GUEST_PL << 13); lg->arch.gdt[GDT_ENTRY_KERNEL_CS].b |= (GUEST_PL << 13);
lg->gdt[GDT_ENTRY_KERNEL_DS].b |= (GUEST_PL << 13); lg->arch.gdt[GDT_ENTRY_KERNEL_DS].b |= (GUEST_PL << 13);
} }
/* Like the IDT, we never simply use the GDT the Guest gives us. We set up the /* Like the IDT, we never simply use the GDT the Guest gives us. We set up the
...@@ -126,7 +126,7 @@ void copy_gdt_tls(const struct lguest *lg, struct desc_struct *gdt) ...@@ -126,7 +126,7 @@ void copy_gdt_tls(const struct lguest *lg, struct desc_struct *gdt)
unsigned int i; unsigned int i;
for (i = GDT_ENTRY_TLS_MIN; i <= GDT_ENTRY_TLS_MAX; i++) for (i = GDT_ENTRY_TLS_MIN; i <= GDT_ENTRY_TLS_MAX; i++)
gdt[i] = lg->gdt[i]; gdt[i] = lg->arch.gdt[i];
} }
/* This is the full version */ /* This is the full version */
...@@ -138,7 +138,7 @@ void copy_gdt(const struct lguest *lg, struct desc_struct *gdt) ...@@ -138,7 +138,7 @@ void copy_gdt(const struct lguest *lg, struct desc_struct *gdt)
* replaced. See ignored_gdt() above. */ * replaced. See ignored_gdt() above. */
for (i = 0; i < GDT_ENTRIES; i++) for (i = 0; i < GDT_ENTRIES; i++)
if (!ignored_gdt(i)) if (!ignored_gdt(i))
gdt[i] = lg->gdt[i]; gdt[i] = lg->arch.gdt[i];
} }
/* This is where the Guest asks us to load a new GDT (LHCALL_LOAD_GDT). */ /* This is where the Guest asks us to load a new GDT (LHCALL_LOAD_GDT). */
...@@ -146,12 +146,12 @@ void load_guest_gdt(struct lguest *lg, unsigned long table, u32 num) ...@@ -146,12 +146,12 @@ void load_guest_gdt(struct lguest *lg, unsigned long table, u32 num)
{ {
/* We assume the Guest has the same number of GDT entries as the /* We assume the Guest has the same number of GDT entries as the
* Host, otherwise we'd have to dynamically allocate the Guest GDT. */ * Host, otherwise we'd have to dynamically allocate the Guest GDT. */
if (num > ARRAY_SIZE(lg->gdt)) if (num > ARRAY_SIZE(lg->arch.gdt))
kill_guest(lg, "too many gdt entries %i", num); kill_guest(lg, "too many gdt entries %i", num);
/* We read the whole thing in, then fix it up. */ /* We read the whole thing in, then fix it up. */
lgread(lg, lg->gdt, table, num * sizeof(lg->gdt[0])); lgread(lg, lg->arch.gdt, table, num * sizeof(lg->arch.gdt[0]));
fixup_gdt_table(lg, 0, ARRAY_SIZE(lg->gdt)); fixup_gdt_table(lg, 0, ARRAY_SIZE(lg->arch.gdt));
/* Mark that the GDT changed so the core knows it has to copy it again, /* Mark that the GDT changed so the core knows it has to copy it again,
* even if the Guest is run on the same CPU. */ * even if the Guest is run on the same CPU. */
lg->changed |= CHANGED_GDT; lg->changed |= CHANGED_GDT;
...@@ -159,7 +159,7 @@ void load_guest_gdt(struct lguest *lg, unsigned long table, u32 num) ...@@ -159,7 +159,7 @@ void load_guest_gdt(struct lguest *lg, unsigned long table, u32 num)
void guest_load_tls(struct lguest *lg, unsigned long gtls) void guest_load_tls(struct lguest *lg, unsigned long gtls)
{ {
struct desc_struct *tls = &lg->gdt[GDT_ENTRY_TLS_MIN]; struct desc_struct *tls = &lg->arch.gdt[GDT_ENTRY_TLS_MIN];
lgread(lg, tls, gtls, sizeof(*tls)*GDT_ENTRY_TLS_ENTRIES); lgread(lg, tls, gtls, sizeof(*tls)*GDT_ENTRY_TLS_ENTRIES);
fixup_gdt_table(lg, GDT_ENTRY_TLS_MIN, GDT_ENTRY_TLS_MAX+1); fixup_gdt_table(lg, GDT_ENTRY_TLS_MIN, GDT_ENTRY_TLS_MAX+1);
......
This diff is collapsed.
...@@ -48,7 +48,8 @@ ...@@ -48,7 +48,8 @@
#include <linux/linkage.h> #include <linux/linkage.h>
#include <asm/asm-offsets.h> #include <asm/asm-offsets.h>
#include <asm/page.h> #include <asm/page.h>
#include "../lg.h" #include <asm/segment.h>
#include <asm/lguest.h>
// We mark the start of the code to copy // We mark the start of the code to copy
// It's placed in .text tho it's never run here // It's placed in .text tho it's never run here
......
#ifndef _X86_LGUEST_H
#define _X86_LGUEST_H
#define GDT_ENTRY_LGUEST_CS 10
#define GDT_ENTRY_LGUEST_DS 11
#define LGUEST_CS (GDT_ENTRY_LGUEST_CS * 8)
#define LGUEST_DS (GDT_ENTRY_LGUEST_DS * 8)
#ifndef __ASSEMBLY__
#include <asm/desc.h>
#define GUEST_PL 1
/* Every guest maps the core switcher code. */
#define SHARED_SWITCHER_PAGES \
DIV_ROUND_UP(end_switcher_text - start_switcher_text, PAGE_SIZE)
/* Pages for switcher itself, then two pages per cpu */
#define TOTAL_SWITCHER_PAGES (SHARED_SWITCHER_PAGES + 2 * NR_CPUS)
/* We map at -4M for ease of mapping into the guest (one PTE page). */
#define SWITCHER_ADDR 0xFFC00000
/* Found in switcher.S */
extern unsigned long default_idt_entries[];
struct lguest_regs
{
/* Manually saved part. */
unsigned long ebx, ecx, edx;
unsigned long esi, edi, ebp;
unsigned long gs;
unsigned long eax;
unsigned long fs, ds, es;
unsigned long trapnum, errcode;
/* Trap pushed part */
unsigned long eip;
unsigned long cs;
unsigned long eflags;
unsigned long esp;
unsigned long ss;
};
/* This is a guest-specific page (mapped ro) into the guest. */
struct lguest_ro_state
{
/* Host information we need to restore when we switch back. */
u32 host_cr3;
struct Xgt_desc_struct host_idt_desc;
struct Xgt_desc_struct host_gdt_desc;
u32 host_sp;
/* Fields which are used when guest is running. */
struct Xgt_desc_struct guest_idt_desc;
struct Xgt_desc_struct guest_gdt_desc;
struct i386_hw_tss guest_tss;
struct desc_struct guest_idt[IDT_ENTRIES];
struct desc_struct guest_gdt[GDT_ENTRIES];
};
struct lguest_arch
{
/* The GDT entries copied into lguest_ro_state when running. */
struct desc_struct gdt[GDT_ENTRIES];
/* The IDT entries: some copied into lguest_ro_state when running. */
struct desc_struct idt[IDT_ENTRIES];
/* The address of the last guest-visible pagefault (ie. cr2). */
unsigned long last_pagefault;
};
static inline void lguest_set_ts(void)
{
u32 cr0;
cr0 = read_cr0();
if (!(cr0 & 8))
write_cr0(cr0|8);
}
/* Full 4G segment descriptors, suitable for CS and DS. */
#define FULL_EXEC_SEGMENT ((struct desc_struct){0x0000ffff, 0x00cf9b00})
#define FULL_SEGMENT ((struct desc_struct){0x0000ffff, 0x00cf9300})
#endif /* __ASSEMBLY__ */
#endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment