Module Name: src Committed By: cherry Date: Sun Sep 23 01:00:00 UTC 2018
Modified Files: src/sys/arch/amd64/amd64: db_interface.c machdep.c src/sys/arch/amd64/include: segments.h src/sys/arch/i386/i386: machdep.c src/sys/arch/i386/include: segments.h src/sys/arch/x86/x86: idt.c lapic.c src/sys/arch/xen/x86: xenfunc.c Log Message: Make XEN use the same api as native, for idt vector allocation and registration. lidt() placed in xenfunc() on maxv@ suggestion. There should be no functional change due to this commit. Tested on amd64 native and XEN. To generate a diff of this commit: cvs rdiff -u -r1.33 -r1.34 src/sys/arch/amd64/amd64/db_interface.c cvs rdiff -u -r1.318 -r1.319 src/sys/arch/amd64/amd64/machdep.c cvs rdiff -u -r1.34 -r1.35 src/sys/arch/amd64/include/segments.h cvs rdiff -u -r1.808 -r1.809 src/sys/arch/i386/i386/machdep.c cvs rdiff -u -r1.64 -r1.65 src/sys/arch/i386/include/segments.h cvs rdiff -u -r1.6 -r1.7 src/sys/arch/x86/x86/idt.c cvs rdiff -u -r1.66 -r1.67 src/sys/arch/x86/x86/lapic.c cvs rdiff -u -r1.19 -r1.20 src/sys/arch/xen/x86/xenfunc.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/arch/amd64/amd64/db_interface.c diff -u src/sys/arch/amd64/amd64/db_interface.c:1.33 src/sys/arch/amd64/amd64/db_interface.c:1.34 --- src/sys/arch/amd64/amd64/db_interface.c:1.33 Tue Apr 3 07:20:52 2018 +++ src/sys/arch/amd64/amd64/db_interface.c Sun Sep 23 00:59:59 2018 @@ -1,4 +1,4 @@ -/* $NetBSD: db_interface.c,v 1.33 2018/04/03 07:20:52 christos Exp $ */ +/* $NetBSD: db_interface.c,v 1.34 2018/09/23 00:59:59 cherry Exp $ */ /* * Mach Operating System @@ -33,7 +33,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: db_interface.c,v 1.33 2018/04/03 07:20:52 christos Exp $"); +__KERNEL_RCSID(0, "$NetBSD: db_interface.c,v 1.34 2018/09/23 00:59:59 cherry Exp $"); #include "opt_ddb.h" #include "opt_multiprocessor.h" @@ -113,7 +113,7 @@ db_machine_init(void) handler = &Xintr_x2apic_ddbipi; #endif ddb_vec = idt_vec_alloc(0xf0, 0xff); - setgate(&idt[ddb_vec], handler, 1, SDT_SYS386IGT, SEL_KPL, + set_idtgate(&idt[ddb_vec], handler, 1, SDT_SYS386IGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); #else /* Initialised as part of xen_ipi_init() */ Index: src/sys/arch/amd64/amd64/machdep.c diff -u src/sys/arch/amd64/amd64/machdep.c:1.318 src/sys/arch/amd64/amd64/machdep.c:1.319 --- src/sys/arch/amd64/amd64/machdep.c:1.318 Wed Aug 29 16:26:25 2018 +++ src/sys/arch/amd64/amd64/machdep.c Sun Sep 23 00:59:59 2018 @@ -1,4 +1,4 @@ -/* $NetBSD: machdep.c,v 1.318 2018/08/29 16:26:25 maxv Exp $ */ +/* $NetBSD: machdep.c,v 1.319 2018/09/23 00:59:59 cherry Exp $ */ /* * Copyright (c) 1996, 1997, 1998, 2000, 2006, 2007, 2008, 2011 @@ -110,7 +110,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.318 2018/08/29 16:26:25 maxv Exp $"); +__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.319 2018/09/23 00:59:59 cherry Exp $"); #include "opt_modular.h" #include "opt_user_ldt.h" @@ -1397,11 +1397,6 @@ setregs(struct lwp *l, struct exec_packa /* * Initialize segments and descriptor tables */ - -#ifdef XEN -struct trap_info *xen_idt; -int xen_idt_idx; -#endif char *ldtstore; char *gdtstore; @@ -1486,15 +1481,10 @@ set_sys_segment(struct sys_segment_descr void cpu_init_idt(void) { -#ifndef XEN struct region_descriptor region; setregion(®ion, idt, NIDT * sizeof(idt[0]) - 1); lidt(®ion); -#else - if (HYPERVISOR_set_trap_table(xen_idt)) - panic("HYPERVISOR_set_trap_table() failed"); -#endif } #define IDTVEC(name) __CONCAT(X, name) @@ -1681,7 +1671,6 @@ init_x86_64(paddr_t first_avail) extern vaddr_t lwp0uarea; #ifndef XEN extern paddr_t local_apic_pa; - int ist; #endif KASSERT(first_avail % PAGE_SIZE == 0); @@ -1806,12 +1795,7 @@ init_x86_64(paddr_t first_avail) pmap_update(pmap_kernel()); -#ifndef XEN - idt = (struct gate_descriptor *)idt_vaddr; -#else - xen_idt = (struct trap_info *)idt_vaddr; - xen_idt_idx = 0; -#endif + idt = (idt_descriptor_t *)idt_vaddr; gdtstore = (char *)gdt_vaddr; ldtstore = (char *)ldt_vaddr; @@ -1870,8 +1854,14 @@ init_x86_64(paddr_t first_avail) /* CPU-specific IDT exceptions. */ for (x = 0; x < NCPUIDT; x++) { -#ifndef XEN + int sel, ist; + + /* Reset to default. Special cases below */ + sel = SEL_KPL; + ist = 0; + idt_vec_reserve(x); + switch (x) { case 1: /* DB */ ist = 4; @@ -1879,56 +1869,31 @@ init_x86_64(paddr_t first_avail) case 2: /* NMI */ ist = 3; break; + case 3: + case 4: + sel = SEL_UPL; + break; case 8: /* double fault */ ist = 2; break; - default: - ist = 0; - break; - } - setgate(&idt[x], x86_exceptions[x], ist, SDT_SYS386IGT, - (x == 3 || x == 4) ? SEL_UPL : SEL_KPL, - GSEL(GCODE_SEL, SEL_KPL)); -#else /* XEN */ - pmap_changeprot_local(idt_vaddr, VM_PROT_READ|VM_PROT_WRITE); - idt_vec_reserve(x); - xen_idt[xen_idt_idx].vector = x; - - switch (x) { - case 2: /* NMI */ +#ifdef XEN case 18: /* MCA */ - TI_SET_IF(&(xen_idt[xen_idt_idx]), 2); - break; - case 3: - case 4: - xen_idt[xen_idt_idx].flags = SEL_UPL; + sel |= 0x4; /* Auto EOI/mask */ break; +#endif /* XEN */ default: - xen_idt[xen_idt_idx].flags = SEL_KPL; break; } - xen_idt[xen_idt_idx].cs = GSEL(GCODE_SEL, SEL_KPL); - xen_idt[xen_idt_idx].address = - (unsigned long)x86_exceptions[x]; - xen_idt_idx++; -#endif /* XEN */ + set_idtgate(&idt[x], x86_exceptions[x], ist, SDT_SYS386IGT, + sel, GSEL(GCODE_SEL, SEL_KPL)); } /* new-style interrupt gate for syscalls */ -#ifndef XEN idt_vec_reserve(128); - setgate(&idt[128], &IDTVEC(osyscall), 0, SDT_SYS386IGT, SEL_UPL, + set_idtgate(&idt[128], &IDTVEC(osyscall), 0, SDT_SYS386IGT, SEL_UPL, GSEL(GCODE_SEL, SEL_KPL)); -#else - idt_vec_reserve(128); - xen_idt[xen_idt_idx].vector = 128; - xen_idt[xen_idt_idx].flags = SEL_KPL; - xen_idt[xen_idt_idx].cs = GSEL(GCODE_SEL, SEL_KPL); - xen_idt[xen_idt_idx].address = (unsigned long) &IDTVEC(osyscall); - xen_idt_idx++; - pmap_changeprot_local(idt_vaddr, VM_PROT_READ); -#endif /* XEN */ + kpreempt_enable(); setregion(®ion, gdtstore, DYNSEL_START - 1); Index: src/sys/arch/amd64/include/segments.h diff -u src/sys/arch/amd64/include/segments.h:1.34 src/sys/arch/amd64/include/segments.h:1.35 --- src/sys/arch/amd64/include/segments.h:1.34 Sun Dec 31 08:29:38 2017 +++ src/sys/arch/amd64/include/segments.h Sun Sep 23 00:59:59 2018 @@ -1,4 +1,4 @@ -/* $NetBSD: segments.h,v 1.34 2017/12/31 08:29:38 maxv Exp $ */ +/* $NetBSD: segments.h,v 1.35 2018/09/23 00:59:59 cherry Exp $ */ /* * Copyright (c) 1990 The Regents of the University of California. @@ -234,15 +234,18 @@ struct region_descriptor { #ifdef _KERNEL #ifdef XEN -extern struct trap_info *idt; +typedef struct trap_info idt_descriptor_t; #else -extern struct gate_descriptor *idt; -#endif +typedef struct gate_descriptor idt_descriptor_t; +#endif /* XEN */ +extern idt_descriptor_t *idt; extern char *gdtstore; extern char *ldtstore; void setgate(struct gate_descriptor *, void *, int, int, int, int); void unsetgate(struct gate_descriptor *); +void set_idtgate(idt_descriptor_t *, void *, int, int, int, int); +void unset_idtgate(idt_descriptor_t *); void setregion(struct region_descriptor *, void *, uint16_t); void set_sys_segment(struct sys_segment_descriptor *, void *, size_t, int, int, int); Index: src/sys/arch/i386/i386/machdep.c diff -u src/sys/arch/i386/i386/machdep.c:1.808 src/sys/arch/i386/i386/machdep.c:1.809 --- src/sys/arch/i386/i386/machdep.c:1.808 Thu Jul 26 09:29:08 2018 +++ src/sys/arch/i386/i386/machdep.c Sun Sep 23 00:59:59 2018 @@ -1,4 +1,4 @@ -/* $NetBSD: machdep.c,v 1.808 2018/07/26 09:29:08 maxv Exp $ */ +/* $NetBSD: machdep.c,v 1.809 2018/09/23 00:59:59 cherry Exp $ */ /* * Copyright (c) 1996, 1997, 1998, 2000, 2004, 2006, 2008, 2009, 2017 @@ -67,7 +67,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.808 2018/07/26 09:29:08 maxv Exp $"); +__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.809 2018/09/23 00:59:59 cherry Exp $"); #include "opt_beep.h" #include "opt_compat_freebsd.h" @@ -580,7 +580,7 @@ cpu_set_tss_gates(struct cpu_info *ci) SDT_SYS386TSS, SEL_KPL, 0, 0); ci->ci_gdt[GTRAPTSS_SEL].sd = sd; - setgate(&idt[8], NULL, 0, SDT_SYSTASKGT, SEL_KPL, + set_idtgate(&idt[8], NULL, 0, SDT_SYSTASKGT, SEL_KPL, GSEL(GTRAPTSS_SEL, SEL_KPL)); #if defined(DDB) && defined(MULTIPROCESSOR) @@ -602,7 +602,7 @@ cpu_set_tss_gates(struct cpu_info *ci) SDT_SYS386TSS, SEL_KPL, 0, 0); ci->ci_gdt[GIPITSS_SEL].sd = sd; - setgate(&idt[ddb_vec], NULL, 0, SDT_SYSTASKGT, SEL_KPL, + set_idtgate(&idt[ddb_vec], NULL, 0, SDT_SYSTASKGT, SEL_KPL, GSEL(GIPITSS_SEL, SEL_KPL)); #endif } @@ -960,23 +960,15 @@ setsegment(struct segment_descriptor *sd extern vector IDTVEC(syscall); extern vector *IDTVEC(exceptions)[]; #ifdef XEN -#define MAX_XEN_IDT 128 -trap_info_t xen_idt[MAX_XEN_IDT]; -int xen_idt_idx; extern union descriptor tmpgdt[]; #endif void cpu_init_idt(void) { -#ifndef XEN struct region_descriptor region; setregion(®ion, pentium_idt, NIDT * sizeof(idt[0]) - 1); lidt(®ion); -#else - if (HYPERVISOR_set_trap_table(xen_idt)) - panic("HYPERVISOR_set_trap_table %p failed\n", xen_idt); -#endif } void @@ -1342,62 +1334,47 @@ init386(paddr_t first_avail) ldtstore[LUCODEBIG_SEL] = gdtstore[GUCODEBIG_SEL]; ldtstore[LUDATA_SEL] = gdtstore[GUDATA_SEL]; -#ifndef XEN /* exceptions */ for (x = 0; x < 32; x++) { - idt_vec_reserve(x); - setgate(&idt[x], IDTVEC(exceptions)[x], 0, SDT_SYS386IGT, - (x == 3 || x == 4) ? SEL_UPL : SEL_KPL, - GSEL(GCODE_SEL, SEL_KPL)); - } - - /* new-style interrupt gate for syscalls */ - idt_vec_reserve(128); - setgate(&idt[128], &IDTVEC(syscall), 0, SDT_SYS386IGT, SEL_UPL, - GSEL(GCODE_SEL, SEL_KPL)); - - setregion(®ion, gdtstore, NGDT * sizeof(gdtstore[0]) - 1); - lgdt(®ion); + /* Reset to default. Special cases below */ + int sel; +#ifdef XEN + sel = SEL_XEN; +#else + sel = SEL_KPL; +#endif /* XEN */ - cpu_init_idt(); -#else /* !XEN */ - memset(xen_idt, 0, sizeof(trap_info_t) * MAX_XEN_IDT); - xen_idt_idx = 0; - for (x = 0; x < 32; x++) { - KASSERT(xen_idt_idx < MAX_XEN_IDT); idt_vec_reserve(x); - xen_idt[xen_idt_idx].vector = x; - switch (x) { + switch (x) { +#ifdef XEN case 2: /* NMI */ case 18: /* MCA */ - TI_SET_IF(&(xen_idt[xen_idt_idx]), 2); + sel |= 0x4; /* Auto EOI/mask */ break; +#endif /* XEN */ case 3: case 4: - xen_idt[xen_idt_idx].flags = SEL_UPL; + sel = SEL_UPL; break; default: - xen_idt[xen_idt_idx].flags = SEL_XEN; break; } - - xen_idt[xen_idt_idx].cs = GSEL(GCODE_SEL, SEL_KPL); - xen_idt[xen_idt_idx].address = - (uint32_t)IDTVEC(exceptions)[x]; - xen_idt_idx++; + set_istgate(&idt[x], IDTVEC(exceptions)[x], 0, SDT_SYS386IGT, + sel, GSEL(GCODE_SEL, SEL_KPL)); } - KASSERT(xen_idt_idx < MAX_XEN_IDT); + + /* new-style interrupt gate for syscalls */ idt_vec_reserve(128); - xen_idt[xen_idt_idx].vector = 128; - xen_idt[xen_idt_idx].flags = SEL_UPL; - xen_idt[xen_idt_idx].cs = GSEL(GCODE_SEL, SEL_KPL); - xen_idt[xen_idt_idx].address = (uint32_t)&IDTVEC(syscall); - xen_idt_idx++; - KASSERT(xen_idt_idx < MAX_XEN_IDT); + set_istgate(&idt[128], &IDTVEC(syscall), 0, SDT_SYS386IGT, SEL_UPL, + GSEL(GCODE_SEL, SEL_KPL)); + + setregion(®ion, gdtstore, NGDT * sizeof(gdtstore[0]) - 1); + lgdt(®ion); + + cpu_init_idt(); lldt(GSEL(GLDT_SEL, SEL_KPL)); cpu_init_idt(); -#endif /* XEN */ init386_ksyms(); Index: src/sys/arch/i386/include/segments.h diff -u src/sys/arch/i386/include/segments.h:1.64 src/sys/arch/i386/include/segments.h:1.65 --- src/sys/arch/i386/include/segments.h:1.64 Sun Dec 31 08:29:38 2017 +++ src/sys/arch/i386/include/segments.h Sun Sep 23 00:59:59 2018 @@ -1,4 +1,4 @@ -/* $NetBSD: segments.h,v 1.64 2017/12/31 08:29:38 maxv Exp $ */ +/* $NetBSD: segments.h,v 1.65 2018/09/23 00:59:59 cherry Exp $ */ /*- * Copyright (c) 1990 The Regents of the University of California. @@ -191,14 +191,23 @@ struct region_descriptor { #endif #ifdef _KERNEL +#ifdef XEN +typedef struct trap_info idt_descriptor_t; +#else +typedef struct gate_descriptor idt_descriptor_t; +#endif /* XEN */ +extern idt_descriptor_t *idt; extern union descriptor *gdtstore, *ldtstore; extern struct gate_descriptor *idt; void setgate(struct gate_descriptor *, void *, int, int, int, int); +void set_idtgate(idt_descriptor_t *, void *, int, int, int); +void unset_idtgate(idt_descriptor_t *); void setregion(struct region_descriptor *, void *, size_t); void setsegment(struct segment_descriptor *, const void *, size_t, int, int, int, int); void unsetgate(struct gate_descriptor *); + void cpu_init_idt(void); void update_descriptor(union descriptor *, union descriptor *); Index: src/sys/arch/x86/x86/idt.c diff -u src/sys/arch/x86/x86/idt.c:1.6 src/sys/arch/x86/x86/idt.c:1.7 --- src/sys/arch/x86/x86/idt.c:1.6 Sat Nov 4 08:50:47 2017 +++ src/sys/arch/x86/x86/idt.c Sun Sep 23 00:59:59 2018 @@ -1,4 +1,4 @@ -/* $NetBSD: idt.c,v 1.6 2017/11/04 08:50:47 cherry Exp $ */ +/* $NetBSD: idt.c,v 1.7 2018/09/23 00:59:59 cherry Exp $ */ /*- * Copyright (c) 1996, 1997, 1998, 2000, 2009 The NetBSD Foundation, Inc. @@ -65,7 +65,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: idt.c,v 1.6 2017/11/04 08:50:47 cherry Exp $"); +__KERNEL_RCSID(0, "$NetBSD: idt.c,v 1.7 2018/09/23 00:59:59 cherry Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -73,16 +73,85 @@ __KERNEL_RCSID(0, "$NetBSD: idt.c,v 1.6 #include <sys/cpu.h> #include <sys/atomic.h> -#include <machine/segments.h> +#include <uvm/uvm.h> -/* On xen PV this is just numberspace management - used in x86/intr.c */ -#if !defined(XEN) +#include <machine/segments.h> -struct gate_descriptor *idt; -#endif +/* + * XEN PV and native have a different idea of what idt entries should + * look like. + */ +idt_descriptor_t *idt; static char idt_allocmap[NIDT]; +/* Normalise across XEN PV and native */ +#if defined(XEN) + +void +set_idtgate(idt_descriptor_t *xen_idd, void *function, int ist, + int type, int dpl, int sel) +{ + /* + * Find the page boundary in which the descriptor resides. + * We make an assumption here, that the descriptor is part of + * a table (array), which fits in a page and is page aligned. + * + * This assumption is from the usecases at early startup in + * machine/machdep.c + * + * Thus this function may not work in the "general" case of a + * randomly located idt entry template (for eg:). + */ + + vaddr_t xen_idt_vaddr = ((vaddr_t) xen_idd) & ~PAGE_MASK; + + //kpreempt_disable(); + /* Make it writeable, so we can update the values. */ + pmap_changeprot_local(xen_idt_vaddr, VM_PROT_READ|VM_PROT_WRITE); + + xen_idd->cs = sel; + xen_idd->address = (unsigned long) function; + xen_idd->flags = dpl; + + /* + * Again we make the assumption that the descriptor is + * implicitly part of an idt, which we infer as + * xen_idt_vaddr. (See above). + */ + xen_idd->vector = xen_idd - (idt_descriptor_t *)xen_idt_vaddr; + + /* Back to read-only, as it should be. */ + pmap_changeprot_local(xen_idt_vaddr, VM_PROT_READ); + //kpreempt_enable(); +} +void +unset_idtgate(idt_descriptor_t *xen_idd) +{ + vaddr_t xen_idt_vaddr = ((vaddr_t) xen_idd) & PAGE_MASK; + + /* Make it writeable, so we can update the values. */ + pmap_changeprot_local(xen_idt_vaddr, VM_PROT_READ|VM_PROT_WRITE); + + /* Zero it */ + memset(xen_idd, 0, sizeof (*xen_idd)); + + /* Back to read-only, as it should be. */ + pmap_changeprot_local(xen_idt_vaddr, VM_PROT_READ); +} +#else +void +set_idtgate(idt_descriptor_t *idd, void *function, int ist, int type, int dpl, int sel) +{ + setgate(idd, function, ist, type, dpl, sel); +} +void +unset_idtgate(idt_descriptor_t *idd) +{ + unsetgate(idd); +} +#endif + /* * Allocate an IDT vector slot within the given range. * cpu_lock will be held unless single threaded during early boot. @@ -123,10 +192,8 @@ idt_vec_set(int vec, void (*function)(vo { KASSERT(idt_allocmap[vec] == 1); -#if !defined(XEN) - setgate(&idt[vec], function, 0, SDT_SYS386IGT, SEL_KPL, - GSEL(GCODE_SEL, SEL_KPL)); -#endif + set_idtgate(&idt[vec], function, 0, SDT_SYS386IGT, SEL_KPL, + GSEL(GCODE_SEL, SEL_KPL)); } /* @@ -136,9 +203,7 @@ void idt_vec_free(int vec) { -#if !defined(XEN) - unsetgate(&idt[vec]); -#endif + unset_idtgate(&idt[vec]); idt_allocmap[vec] = 0; } Index: src/sys/arch/x86/x86/lapic.c diff -u src/sys/arch/x86/x86/lapic.c:1.66 src/sys/arch/x86/x86/lapic.c:1.67 --- src/sys/arch/x86/x86/lapic.c:1.66 Tue Apr 3 07:20:52 2018 +++ src/sys/arch/x86/x86/lapic.c Sun Sep 23 00:59:59 2018 @@ -1,4 +1,4 @@ -/* $NetBSD: lapic.c,v 1.66 2018/04/03 07:20:52 christos Exp $ */ +/* $NetBSD: lapic.c,v 1.67 2018/09/23 00:59:59 cherry Exp $ */ /*- * Copyright (c) 2000, 2008 The NetBSD Foundation, Inc. @@ -32,7 +32,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: lapic.c,v 1.66 2018/04/03 07:20:52 christos Exp $"); +__KERNEL_RCSID(0, "$NetBSD: lapic.c,v 1.67 2018/09/23 00:59:59 cherry Exp $"); #include "acpica.h" #include "ioapic.h" @@ -335,7 +335,7 @@ lapic_setup_bsp(paddr_t lapic_base) #endif #if defined(DDB) && defined(MULTIPROCESSOR) #ifdef __x86_64__ - setgate(&idt[ddb_vec], &Xintr_x2apic_ddbipi, 1, SDT_SYS386IGT, + set_idtgate(&idt[ddb_vec], &Xintr_x2apic_ddbipi, 1, SDT_SYS386IGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); #else /* Set DDB IPI handler in cpu_set_tss_gates() when cpu0 is attached. */ Index: src/sys/arch/xen/x86/xenfunc.c diff -u src/sys/arch/xen/x86/xenfunc.c:1.19 src/sys/arch/xen/x86/xenfunc.c:1.20 --- src/sys/arch/xen/x86/xenfunc.c:1.19 Thu Jul 26 15:06:14 2018 +++ src/sys/arch/xen/x86/xenfunc.c Sun Sep 23 00:59:59 2018 @@ -1,4 +1,4 @@ -/* $NetBSD: xenfunc.c,v 1.19 2018/07/26 15:06:14 maxv Exp $ */ +/* $NetBSD: xenfunc.c,v 1.20 2018/09/23 00:59:59 cherry Exp $ */ /* * Copyright (c) 2004 Christian Limpach. @@ -26,7 +26,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: xenfunc.c,v 1.19 2018/07/26 15:06:14 maxv Exp $"); +__KERNEL_RCSID(0, "$NetBSD: xenfunc.c,v 1.20 2018/09/23 00:59:59 cherry Exp $"); #include <sys/param.h> @@ -52,6 +52,46 @@ invlpg(vaddr_t addr) } void +lidt(struct region_descriptor *rd) +{ + /* + * We need to do this because we can't assume kmem_alloc(9) + * will be available at the boot stage when this is called. + */ + static char xen_idt_page[PAGE_SIZE] __attribute__((__aligned__ (PAGE_SIZE))); + + struct trap_info *xen_idt = (void * )xen_idt_page; + int xen_idt_idx = 0; + + struct trap_info * idd = (void *) rd->rd_base; + const int nidt = rd->rd_limit / (sizeof *idd); + + int i; + + /* + * Sweep in all initialised entries, consolidate them back to + * back in the requestor array. + */ + for (i = 0; i < nidt; i++) { + if (idd->address == 0) /* Skip gap */ + continue; + + /* Copy over entry */ + xen_idt[xen_idt_idx++] = idd[i]; + } + + /* page needs to be r/o */ + pmap_changeprot_local((vaddr_t) xen_idt, VM_PROT_READ); + + /* Hook it up in the hypervisor */ + if (HYPERVISOR_set_trap_table(xen_idt)) + panic("HYPERVISOR_set_trap_table() failed"); + + /* reset */ + pmap_changeprot_local((vaddr_t) xen_idt, VM_PROT_READ|VM_PROT_WRITE); +} + +void lldt(u_short sel) { #ifndef __x86_64__