NetBSD/sys/arch/xen/x86/xenfunc.c
jym d94742232d Welcome PAE inside i386 current.
This patch is inspired by work previously done by Jeremy Morse, ported by me
to -current, merged with the work previously done for port-xen, together with
additionals fixes and improvements.

PAE option is disabled by default in GENERIC (but will be enabled in ALL in
the next few days).

In quick, PAE switches the CPU to a mode where physical addresses become
36 bits (64 GiB). Virtual address space remains at 32 bits (4 GiB). To cope
with the increased size of the physical address, they are manipulated as
64 bits variables by kernel and MMU.

When supported by the CPU, it also allows the use of the NX/XD bit that
provides no-execution right enforcement on a per physical page basis.

Notes:

- reworked locore.S

- introduce cpu_load_pmap(), used to switch pmap for the curcpu. Due to the
different handling of pmap mappings with PAE vs !PAE, Xen vs native, details
are hidden within this function. This helps calling it from assembly,
as some features, like BIOS calls, switch to pmap_kernel before mapping
trampoline code in low memory.

- some changes in bioscall and kvm86_call, to reflect the above.

- the L3 is "pinned" per-CPU, and is only manipulated by a
reduced set of functions within pmap. To track the L3, I added two
elements to struct cpu_info, namely ci_l3_pdirpa (PA of the L3), and
ci_l3_pdir (the L3 VA). Rest of the code considers that it runs "just
like" a normal i386, except that the L2 is 4 pages long (PTP_LEVELS is
still 2).

- similar to the ci_pae_l3_pdir{,pa} variables, amd64's xen_current_user_pgd
becomes an element of cpu_info (slowly paving the way for MP world).

- bootinfo_source struct declaration is modified, to cope with paddr_t size
change with PAE (it is not correct to assume that bs_addr is a paddr_t when
compiled with PAE - it should remain 32 bits). bs_addrs is now a
void * array (in bootloader's code under i386/stand/, the bs_addrs
is a physaddr_t, which is an unsigned long).

- fixes in multiboot code (same reason as bootinfo): paddr_t size
change. I used Elf32_* types, use RELOC() where necessary, and move the
memcpy() functions out of the if/else if (I do not expect sym and str tables
to overlap with ELF).

- 64 bits atomic functions for pmap

- all pmap_pdirpa access are now done through the pmap_pdirpa macro. It
hides the L3/L2 stuff from PAE, as well as the pm_pdirpa change in
struct pmap (it now becomes a PDP_SIZE array, with or without PAE).

- manipulation of recursive mappings ( PDIR_SLOT_{,A}PTEs ) is done via
loops on PDP_SIZE.

See also http://mail-index.netbsd.org/port-i386/2010/07/17/msg002062.html

No objection raised on port-i386@ and port-xen@R for about a week.

XXX kvm(3) will be fixed in another patch to properly handle both PAE and !PAE
kernel dumps (VA => PA macros are slightly different, and need proper 64 bits
PA support in kvm_i386).

XXX Mixing PAE and !PAE modules may lead to unwanted/unexpected results. This
cannot be solved easily, and needs lots of thinking before being declared
safe (paddr_t/bus_addr_t size handling, PD/PT macros abstractions).
2010-07-24 00:45:54 +00:00

152 lines
3.0 KiB
C

/* $NetBSD: xenfunc.c,v 1.11 2010/07/24 00:45:56 jym Exp $ */
/*
*
* Copyright (c) 2004 Christian Limpach.
* 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 AUTHOR ``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 AUTHOR 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 <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: xenfunc.c,v 1.11 2010/07/24 00:45:56 jym Exp $");
#include <sys/param.h>
#include <uvm/uvm_extern.h>
#include <machine/intr.h>
#include <machine/vmparam.h>
#include <machine/pmap.h>
#include <xen/xen.h>
#include <xen/hypervisor.h>
//#include <xen/evtchn.h>
#include <xen/xenpmap.h>
#include <machine/pte.h>
#ifdef XENDEBUG_LOW
#define __PRINTK(x) printk x
#else
#define __PRINTK(x)
#endif
void xen_set_ldt(vaddr_t, uint32_t);
void
invlpg(vaddr_t addr)
{
int s = splvm();
xpq_queue_invlpg(addr);
splx(s);
}
void
lldt(u_short sel)
{
#ifndef __x86_64__
struct cpu_info *ci;
ci = curcpu();
if (ci->ci_curldt == sel)
return;
/* __PRINTK(("ldt %x\n", IDXSELN(sel))); */
if (sel == GSEL(GLDT_SEL, SEL_KPL))
xen_set_ldt((vaddr_t)ldt, NLDT);
else
xen_set_ldt(ci->ci_gdt[IDXSELN(sel)].ld.ld_base,
ci->ci_gdt[IDXSELN(sel)].ld.ld_entries);
ci->ci_curldt = sel;
#endif
}
void
ltr(u_short sel)
{
__PRINTK(("XXX ltr not supported\n"));
}
void
lcr0(u_long val)
{
__PRINTK(("XXX lcr0 not supported\n"));
}
u_long
rcr0(void)
{
__PRINTK(("XXX rcr0 not supported\n"));
return 0;
}
#ifndef __x86_64__
void
lcr3(vaddr_t val)
{
int s = splvm();
xpq_queue_pt_switch(xpmap_ptom_masked(val));
splx(s);
}
#endif
void
tlbflush(void)
{
int s = splvm();
xpq_queue_tlb_flush();
splx(s);
}
void
tlbflushg(void)
{
tlbflush();
}
vaddr_t
rdr6(void)
{
u_int val;
val = HYPERVISOR_get_debugreg(6);
return val;
}
void
ldr6(vaddr_t val)
{
HYPERVISOR_set_debugreg(6, val);
}
void
wbinvd(void)
{
xpq_flush_cache();
}
vaddr_t
rcr2(void)
{
return curcpu()->ci_vcpu->arch.cr2;
}