bitkeeper revision 1.170 (3e9c936fXyHEI0NKOWQkP9tHN4sbqw)

Many files:
  Finished virtualisation of x86 LDT. Xenolinux now exports this to applications (eg. for use by linuxthreads).
This commit is contained in:
kaf24@scramble.cl.cam.ac.uk committed 2003-04-15 23:19:11 +00:00
1 parent 6b34a2bd55
commit 005c272397
17 files changed
+290 -370

No files matched your search

+36 -76
View File
@@ -7,31 +7,7 @@ longer-term goals.
-- Keir (16/3/03)
1. ASSIGNING DOMAINS TO PROCESSORS
----------------------------------
More intelligent assignment of domains to processors. In
particular, we don't play well with hyperthreading: we will assign
domains to virtual processors on the same package, rather then
spreading them across processor packages.
What we need to do is port code from Linux which stores information on
relationships between processors in the system (eg. which ones are
siblings in the same package). We then use this to balance domains
across packages, and across virtual processors within a package.
2. PROPER DESTRUCTION OF DOMAINS
--------------------------------
Currently we do not free resources when destroying a domain. This is
because they may be tied up in subsystems, and there is no way of
pulling them back in a safe manner.
The fix is probably to reference count resources and automatically
free them when the count reaches zero. We may get away with one count
per domain (for all its resources). When this reaches zero we know it
is safe to free everything: block-device rings, network rings, and all
the rest.
3. FIX HANDLING OF NETWORK RINGS
1. FIX HANDLING OF NETWORK RINGS
--------------------------------
Handling of the transmit rings is currently very broken (for example,
sending an inter-domain packet will wedge the hypervisor). This is
@@ -44,7 +20,39 @@ order to requests, just as we already do with block-device
rings. We'll need to add an opaque identifier to ring entries,
allowing matching of requests and responses, but that's about it.
4. NETWORK CHECKSUM OFFLOAD
2. ACCURATE TIMERS AND WALL-CLOCK TIME
--------------------------------------
Currently our long-term timebase free runs on CPU0, with no external
calibration. We should run ntpd on domain 0 and allow this to warp
Xen's timebase. Once this is done, we can have a timebase per CPU and
not worry about relative drift (since they'll all get sync'ed
periodically by ntp).
3. ASSIGNING DOMAINS TO PROCESSORS
----------------------------------
More intelligent assignment of domains to processors. In
particular, we don't play well with hyperthreading: we will assign
domains to virtual processors on the same package, rather then
spreading them across processor packages.
What we need to do is port code from Linux which stores information on
relationships between processors in the system (eg. which ones are
siblings in the same package). We then use this to balance domains
across packages, and across virtual processors within a package.
4. PROPER DESTRUCTION OF DOMAINS
--------------------------------
Currently we do not free resources when destroying a domain. This is
because they may be tied up in subsystems, and there is no way of
pulling them back in a safe manner.
The fix is probably to reference count resources and automatically
free them when the count reaches zero. We may get away with one count
per domain (for all its resources). When this reaches zero we know it
is safe to free everything: block-device rings, network rings, and all
the rest.
5. NETWORK CHECKSUM OFFLOAD
---------------------------
All the NICs that we support can checksum packets on behalf of guest
OSes. We need to add appropriate flags to and from each domain to
@@ -52,17 +60,6 @@ indicate, on transmit, which packets need the checksum added and, on
receive, which packets have been checked out as okay. We can steal
Linux's interface, which is entirely sane given NIC limitations.
5. GDT AND LDT VIRTUALISATION
-----------------------------
We do not allow modification of the GDT, or any use of the LDT. This
is necessary for support of unmodified applications (eg. Linux uses
LDT in threaded applications, while Windows needs to update GDT
entries).
I have some text on how to do this:
/usr/groups/xeno/discussion-docs/memory_management/segment_tables.txt
It's already half implemented, but the rest is still to do.
6. DOMAIN 0 MANAGEMENT DAEMON
-----------------------------
A better control daemon is required for domain 0, which keeps proper
@@ -70,15 +67,7 @@ track of machine resources and can make sensible policy choices. This
may require support in Xen; for example, notifications (eg. DOMn is
killed), and requests (eg. can DOMn allocate x frames of memory?).
7. ACCURATE TIMERS AND WALL-CLOCK TIME
--------------------------------------
Currently our long-term timebase free runs on CPU0, with no external
calibration. We should run ntpd on domain 0 and allow this to warp
Xen's timebase. Once this is done, we can have a timebase per CPU and
not worry about relative drift (since they'll all get sync'ed
periodically by ntp).
8. MODULE SUPPORT FOR XEN
7. MODULE SUPPORT FOR XEN
-------------------------
Network and blkdev drivers are bloating Xen. At some point we want to
build drivers as modules, stick them in a cheesy ramfs, then relocate
@@ -90,7 +79,7 @@ which drivers to load.
Most of the hard stuff (relocating and the like) is done for us by
Linux's module system.
9. NEW DESIGN FEATURES
8. NEW DESIGN FEATURES
----------------------
This includes the last-chance page cache, and the unified buffer cache.
@@ -99,35 +88,6 @@ This includes the last-chance page cache, and the unified buffer cache.
Graveyard
*********
Following is some description how some of the above might be
implemented. Some of it is superceded and/or out of date, so follow
with caution.
Segment descriptor tables
-------------------------
We want to allow guest OSes to specify GDT and LDT tables using their
own pages of memory (just like with page tables). So allow the following:
* new_table_entry(ptr, val)
[Allows insertion of a code, data, or LDT descriptor into given
location. Can simply be checked then poked, with no need to look at
page type.]
* new_GDT() -- relevent virtual pages are resolved to frames. Either
(i) page not present; or (ii) page is only mapped read-only and checks
out okay (then marked as special page). Old table is resolved first,
and the pages are unmarked (no longer special type).
* new_LDT() -- same as for new_GDT(), with same special page type.
Page table updates must be hooked, so we look for updates to virtual page
addresses in the GDT/LDT range. If map to not present, then old physpage
has type_count decremented. If map to present, ensure read-only, check the
page, and set special type.
Merge set_{LDT,GDT} into update_baseptr, by passing four args:
update_baseptrs(mask, ptab, gdttab, ldttab);
Update of ptab requires update of gtab (or set to internal default).
Update of gtab requires update of ltab (or set to internal default).
The hypervisor page cache
-------------------------
This will allow guest OSes to make use of spare pages in the system, but
+14 -27
View File
@@ -87,43 +87,30 @@ continue_boot_cpu:
xor %eax,%eax
rep stosb
/* Copy all modules (dom0 + initrd if presetn) to safety, above 48MB */
/* Copy all modules (dom0 + initrd if present) out of the Xen heap */
mov (%esp),%eax
cmp $0x2BADB002,%eax
jne 2f /* skip if magic no good */
sub $__PAGE_OFFSET,%ebx /* turn back into a physaddr */
mov 0x14(%ebx),%edi /* mbi->mods_count */
dec %edi /* count-- */
jb 2f /* if num modules was zero !!! */
jne skip_dom0_copy
sub $__PAGE_OFFSET,%ebx /* turn back into a phys addr */
mov 0x14(%ebx),%edi /* mb->mods_count */
dec %edi /* mbi->mods_count-- */
jb skip_dom0_copy /* skip if no modules */
mov 0x18(%ebx),%eax /* mbi->mods_addr */
mov (%eax),%ebx /* mod[0]->mod_start */
shl $4,%edi /* count*16 */
mov (%eax),%ebx /* %ebx = mod[0]->mod_start */
shl $4,%edi
add %edi,%eax
mov 0x4(%eax),%eax /* mod[mod_count-1]->end */
mov 0x4(%eax),%eax /* %eax = mod[mod_count-1]->end */
mov %eax,%ecx
sub %ebx,%ecx /* length in byte */
sub %ebx,%ecx /* %ecx = byte len of all mods */
mov $(MAX_DIRECTMAP_ADDRESS), %edi
add %ecx, %edi /* src + length */
shr $2,%ecx /* ecx is length/4 */
1:
sub $4,%eax /* eax = src, edi = dst */
add %ecx, %edi /* %edi = src + length */
shr $2,%ecx /* %ecx = length/4 */
1: sub $4,%eax /* %eax = src, %edi = dst */
sub $4,%edi
mov (%eax),%ebx
mov %ebx,(%edi)
loop 1b
2:
skip_dom0_copy:
/* Initialize low and high mappings of all memory with 4MB pages */
mov $idle0_pg_table-__PAGE_OFFSET,%edi
+107 -67
View File
@@ -19,12 +19,14 @@
* 18(%esp) - %eax
* 1C(%esp) - %ds
* 20(%esp) - %es
* 24(%esp) - orig_eax
* 28(%esp) - %eip
* 2C(%esp) - %cs
* 30(%esp) - %eflags
* 34(%esp) - %oldesp
* 38(%esp) - %oldss
* 24(%esp) - %fs
* 28(%esp) - %gs
* 2C(%esp) - orig_eax
* 30(%esp) - %eip
* 34(%esp) - %cs
* 38(%esp) - %eflags
* 3C(%esp) - %oldesp
* 40(%esp) - %oldss
*
* "current" is in register %ebx during any slow entries.
*/
@@ -56,13 +58,14 @@
* of the frame does an inter-privilege interrupt-return.
*
* Note that the "failsafe callback" uses a special stackframe:
* { return_DS, return_ES, return_EIP, return_CS, return_EFLAGS, ... }
* That is, original values for DS/ES are placed on stack rather than
* in DS/ES themselves. Why? It saves us loading them, only to have them
* { return_DS, return_ES, return_FS, return_GS, return_EIP,
* return_CS, return_EFLAGS[, return_ESP, return_SS] }
* That is, original values for DS/ES/FS/GS are placed on stack rather than
* in DS/ES/FS/GS themselves. Why? It saves us loading them, only to have them
* saved/restored in guest OS. Furthermore, if we load them we may cause
* a fault if they are invalid, which is a hassle to deal with. We avoid
* that problem if we don't load them :-) This property allows us to use
* the failsafe callback as a fallback: if we ever fault on loading DS/ES
* the failsafe callback as a fallback: if we ever fault on loading DS/ES/FS/GS
* on return to ring != 0, we can simply package it up as a return via
* the failsafe callback, and let the guest OS sort it out (perhaps by
* killing an application process). Note that we also do this for any
@@ -90,12 +93,14 @@ EBP = 0x14
EAX = 0x18
DS = 0x1C
ES = 0x20
ORIG_EAX = 0x24
EIP = 0x28
CS = 0x2C
EFLAGS = 0x30
OLDESP = 0x34
OLDSS = 0x38
FS = 0x24
GS = 0x28
ORIG_EAX = 0x2C
EIP = 0x30
CS = 0x34
EFLAGS = 0x38
OLDESP = 0x3C
OLDSS = 0x40
/* Offsets in task_struct */
PROCESSOR = 0
@@ -113,14 +118,14 @@ EVENTS = 0
EVENTS_ENABLE = 4
/* Offsets in guest_trap_bounce */
GTB_ERROR_CODE = 0
GTB_CR2 = 4
GTB_FLAGS = 8
GTB_CS = 10
GTB_EIP = 12
GTBF_TRAP = 1
GTBF_TRAP_NOCODE = 2
GTBF_TRAP_CR2 = 4
GTB_ERROR_CODE = 0
GTB_CR2 = 4
GTB_FLAGS = 8
GTB_CS = 10
GTB_EIP = 12
GTBF_TRAP = 1
GTBF_TRAP_NOCODE = 2
GTBF_TRAP_CR2 = 4
CF_MASK = 0x00000001
IF_MASK = 0x00000200
@@ -128,6 +133,8 @@ NT_MASK = 0x00004000
#define SAVE_ALL \
cld; \
pushl %gs; \
pushl %fs; \
pushl %es; \
pushl %ds; \
pushl %eax; \
@@ -139,7 +146,8 @@ NT_MASK = 0x00004000
pushl %ebx; \
movl $(__HYPERVISOR_DS),%edx; \
movl %edx,%ds; \
movl %edx,%es;
movl %edx,%es; \
sti;
#define RESTORE_ALL \
popl %ebx; \
@@ -151,13 +159,17 @@ NT_MASK = 0x00004000
popl %eax; \
1: popl %ds; \
2: popl %es; \
3: popl %fs; \
4: popl %gs; \
addl $4,%esp; \
3: iret; \
5: iret; \
.section .fixup,"ax"; \
6: subl $4,%esp; \
pushl %es; \
5: pushl %ds; \
4: pushl %eax; \
10: subl $4,%esp; \
pushl %gs; \
9: pushl %fs; \
8: pushl %es; \
7: pushl %ds; \
6: pushl %eax; \
pushl %ebp; \
pushl %edi; \
pushl %esi; \
@@ -172,9 +184,11 @@ NT_MASK = 0x00004000
.previous; \
.section __ex_table,"a"; \
.align 4; \
.long 1b,4b; \
.long 2b,5b; \
.long 3b,6b; \
.long 1b,6b; \
.long 2b,7b; \
.long 3b,8b; \
.long 4b,9b; \
.long 5b,10b; \
.previous
#define GET_CURRENT(reg) \
@@ -315,7 +329,22 @@ process_hyp_events:
/* No special register assumptions */
failsafe_callback:
GET_CURRENT(%ebx)
# Check that we are actually returning to ring != 0 because
# we may fault when returning to another ring 0 activation.
# This can only occur when restoring FS and GS, which can be avoided
# by zeroing those registers and trying again. The outermost ring 0
# activation will do a full failsafe callback to the guest OS.
# Note that the outermost activation certainly has the "bad" selector
# value saved away, since interrupts are always disabled in ring 0
# until all segment registers have been saved.
movb CS(%esp),%al
test $3,%al
jnz 1f
xorl %eax,%eax
movl %eax,FS(%esp)
movl %eax,GS(%esp)
jmp restore_all
1: GET_CURRENT(%ebx)
mov PROCESSOR(%ebx),%eax
shl $4,%eax
lea guest_trap_bounce(%eax),%edx
@@ -324,11 +353,15 @@ failsafe_callback:
movl FAILSAFE_SEL(%ebx),%eax
movw %ax,GTB_CS(%edx)
call create_bounce_frame
subl $8,%esi # add DS/ES to failsafe stack frame
subl $16,%esi # add DS/ES/FS/GS to failsafe stack frame
movl DS(%esp),%eax
FAULT1: movl %eax,(%esi)
movl ES(%esp),%eax
FAULT2: movl %eax,4(%esi)
movl FS(%esp),%eax
FAULT3: movl %eax,8(%esi)
movl GS(%esp),%eax
FAULT4: movl %eax,12(%esi)
movl %esi,OLDESP(%esp)
popl %ebx
popl %ecx
@@ -337,8 +370,8 @@ FAULT2: movl %eax,4(%esi)
popl %edi
popl %ebp
popl %eax
addl $12,%esp
FAULT3: iret
addl $20,%esp # skip DS/ES/FS/GS/ORIG_EAX
FAULT5: iret
/* CREATE A BASIC EXCEPTION FRAME ON GUEST OS (RING-1) STACK: */
@@ -354,25 +387,25 @@ create_bounce_frame:
shll $8,%eax /* multiply by 256 */
addl $init_tss + 12,%eax
movl (%eax),%esi /* tss->esp1 */
FAULT4: movl 4(%eax),%ds /* tss->ss1 */
FAULT6: movl 4(%eax),%ds /* tss->ss1 */
/* base of stack frame must contain ss/esp (inter-priv iret) */
subl $8,%esi
movl OLDESP+4(%esp),%eax
FAULT5: movl %eax,(%esi)
FAULT7: movl %eax,(%esi)
movl OLDSS+4(%esp),%eax
FAULT6: movl %eax,4(%esi)
FAULT8: movl %eax,4(%esi)
jmp 2f
1: /* obtain ss/esp from oldss/oldesp -- a ring-1 activation exists */
movl OLDESP+4(%esp),%esi
FAULT7: movl OLDSS+4(%esp),%ds
FAULT9: movl OLDSS+4(%esp),%ds
2: /* Construct a stack frame: EFLAGS, CS/EIP */
subl $12,%esi
movl EIP+4(%esp),%eax
FAULT8: movl %eax,(%esi)
FAULT10:movl %eax,(%esi)
movl CS+4(%esp),%eax
FAULT9: movl %eax,4(%esi)
FAULT11:movl %eax,4(%esi)
movl EFLAGS+4(%esp),%eax
FAULT10:movl %eax,8(%esi)
FAULT12:movl %eax,8(%esi)
/* Rewrite our stack frame and return to ring 1. */
/* IA32 Ref. Vol. 3: TF, VM, RF and NT flags are cleared on trap. */
andl $0xfffcbeff,%eax
@@ -390,16 +423,18 @@ FAULT10:movl %eax,8(%esi)
.align 4
.long FAULT1, kill_domain_fixup3 # Fault writing to ring-1 stack
.long FAULT2, kill_domain_fixup3 # Fault writing to ring-1 stack
.long FAULT3, kill_domain_fixup1 # Fault executing failsafe iret
.long FAULT4, kill_domain_fixup2 # Fault loading ring-1 stack selector
.long FAULT5, kill_domain_fixup2 # Fault writing to ring-1 stack
.long FAULT6, kill_domain_fixup2 # Fault writing to ring-1 stack
.long FAULT7, kill_domain_fixup2 # Fault loading ring-1 stack selector
.long FAULT3, kill_domain_fixup3 # Fault writing to ring-1 stack
.long FAULT4, kill_domain_fixup3 # Fault writing to ring-1 stack
.long FAULT5, kill_domain_fixup1 # Fault executing failsafe iret
.long FAULT6, kill_domain_fixup2 # Fault loading ring-1 stack selector
.long FAULT7, kill_domain_fixup2 # Fault writing to ring-1 stack
.long FAULT8, kill_domain_fixup2 # Fault writing to ring-1 stack
.long FAULT9, kill_domain_fixup2 # Fault writing to ring-1 stack
.long FAULT9, kill_domain_fixup2 # Fault loading ring-1 stack selector
.long FAULT10,kill_domain_fixup2 # Fault writing to ring-1 stack
.long FAULT11,kill_domain_fixup3 # Fault writing to ring-1 stack
.long FAULT12,kill_domain_fixup3 # Fault writing to ring-1 stack
.long FAULT11,kill_domain_fixup2 # Fault writing to ring-1 stack
.long FAULT12,kill_domain_fixup2 # Fault writing to ring-1 stack
.long FAULT13,kill_domain_fixup3 # Fault writing to ring-1 stack
.long FAULT14,kill_domain_fixup3 # Fault writing to ring-1 stack
.previous
# This handler kills domains which experience unrecoverable faults.
@@ -429,12 +464,12 @@ process_guest_exception_and_events:
jnz 2f
subl $4,%esi # push error_code onto guest frame
movl %es:GTB_ERROR_CODE(%edx),%eax
FAULT11:movl %eax,(%esi)
FAULT13:movl %eax,(%esi)
test $GTBF_TRAP_CR2,%cl
jz 1f
subl $4,%esi # push %cr2 onto guest frame
movl %es:GTB_CR2(%edx),%eax
FAULT12:movl %eax,(%esi)
FAULT14:movl %eax,(%esi)
1: movl %esi,OLDESP(%esp)
2: push %es # unclobber %ds
pop %ds
@@ -463,31 +498,36 @@ ENTRY(divide_error)
pushl $ SYMBOL_NAME(do_divide_error)
ALIGN
error_code:
pushl %fs
pushl %es
pushl %ds
pushl %eax
xorl %eax,%eax
xorl %eax,%eax
pushl %ebp
pushl %edi
pushl %esi
pushl %edx
decl %eax # eax = -1
decl %eax # eax = -1
pushl %ecx
pushl %ebx
cld
movl %es,%ecx
movl ORIG_EAX(%esp), %esi # get the error code
movl ES(%esp), %edi # get the function address
movl %eax, ORIG_EAX(%esp)
movl %ecx, ES(%esp)
movl %esp,%edx
movl %gs,%ecx
movl ORIG_EAX(%esp), %esi # get the error code
movl GS(%esp), %edi # get the function address
movl %eax, ORIG_EAX(%esp)
movl %ecx, GS(%esp)
movl %esp,%edx
pushl %esi # push the error code
pushl %edx # push the pt_regs pointer
movl $(__HYPERVISOR_DS),%edx
movl %edx,%ds
movl %edx,%es
movl $(__HYPERVISOR_DS),%edx
movl %edx,%ds
movl %edx,%es
GET_CURRENT(%ebx)
call *%edi
addl $8,%esp
call *%edi
# NB. We reenable interrupts AFTER exception processing, as that is
# required by the page fault handler (needs to save %cr2)
sti
addl $8,%esp
jmp ret_from_exception
ENTRY(coprocessor_error)
+3
View File
@@ -227,6 +227,9 @@ long do_set_gdt(unsigned long *frame_list, unsigned int entries)
current->mm.perdomain_pt[i] = mk_l1_pgentry(0);
if ( pfn == 0 ) continue;
page = frame_table + pfn;
ASSERT((page->flags & PG_type_mask) == PGT_gdt_page);
ASSERT((page->flags & PG_domain_mask) == current->domain);
ASSERT((page->type_count != 0) && (page->tot_count != 0));
put_page_type(page);
put_page_tot(page);
}
+5 -18
View File
@@ -199,8 +199,9 @@ void show_regs(struct pt_regs * regs)
regs->eax,regs->ebx,regs->ecx,regs->edx);
printk("ESI: %08lx EDI: %08lx EBP: %08lx",
regs->esi, regs->edi, regs->ebp);
printk(" DS: %04x ES: %04x\n",
0xffff & regs->xds,0xffff & regs->xes);
printk(" DS: %04x ES: %04x FS: %04x GS: %04x\n",
0xffff & regs->xds, 0xffff & regs->xes,
0xffff & regs->xfs, 0xffff & regs->xgs);
__asm__("movl %%cr0, %0": "=r" (cr0));
__asm__("movl %%cr2, %0": "=r" (cr2));
@@ -260,7 +261,7 @@ void new_thread(struct task_struct *p,
* [EAX,EBX,ECX,EDX,EDI,EBP are zero]
*/
p->thread.fs = p->thread.gs = FLAT_RING1_DS;
regs->xds = regs->xes = regs->xss = FLAT_RING1_DS;
regs->xds = regs->xes = regs->xfs = regs->xgs = regs->xss = FLAT_RING1_DS;
regs->xcs = FLAT_RING1_CS;
regs->eip = start_pc;
regs->esp = start_stack;
@@ -313,8 +314,7 @@ void new_thread(struct task_struct *p,
/* NB. prev_p passed in %eax, next_p passed in %edx */
void __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
{
struct thread_struct *prev = &prev_p->thread,
*next = &next_p->thread;
struct thread_struct *next = &next_p->thread;
struct tss_struct *tss = init_tss + smp_processor_id();
unlazy_fpu(prev_p);
@@ -327,23 +327,10 @@ void __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
tss->esp1 = next->esp1;
tss->ss1 = next->ss1;
/*
* Save away %fs and %gs. No need to save %es and %ds, as
* those are always kernel segments while inside the kernel.
*/
asm volatile("movl %%fs,%0":"=m" (*(int *)&prev->fs));
asm volatile("movl %%gs,%0":"=m" (*(int *)&prev->gs));
/* Switch GDT and LDT. */
__asm__ __volatile__ ("lgdt %0" : "=m" (*next_p->mm.gdt));
load_LDT();
/*
* Restore %fs and %gs.
*/
loadsegment(fs, next->fs);
loadsegment(gs, next->gs);
/*
* Now maybe reload the debug registers
*/
+43 -55
View File
@@ -159,8 +159,9 @@ void show_registers(struct pt_regs *regs)
regs->eax, regs->ebx, regs->ecx, regs->edx);
printk("esi: %08lx edi: %08lx ebp: %08lx esp: %08lx\n",
regs->esi, regs->edi, regs->ebp, esp);
printk("ds: %04x es: %04x ss: %04x\n",
regs->xds & 0xffff, regs->xes & 0xffff, ss);
printk("ds: %04x es: %04x fs: %04x gs: %04x ss: %04x\n",
regs->xds & 0xffff, regs->xes & 0xffff,
regs->xfs & 0xffff, regs->xgs & 0xffff, ss);
show_stack(&regs->esp);
}
@@ -170,10 +171,11 @@ spinlock_t die_lock = SPIN_LOCK_UNLOCKED;
void die(const char * str, struct pt_regs * regs, long err)
{
spin_lock_irq(&die_lock);
unsigned long flags;
spin_lock_irqsave(&die_lock, flags);
printk("%s: %04lx,%04lx\n", str, err >> 16, err & 0xffff);
show_registers(regs);
spin_unlock_irq(&die_lock);
spin_unlock_irqrestore(&die_lock, flags);
panic("HYPERVISOR DEATH!!\n");
}
@@ -205,6 +207,7 @@ static void inline do_trap(int trapnr, char *str,
if ( (fixup = search_exception_table(regs->eip)) != 0 )
{
regs->eip = fixup;
regs->xfs = regs->xgs = 0;
return;
}
@@ -264,9 +267,6 @@ asmlinkage void do_page_fault(struct pt_regs *regs, long error_code)
bounce_fault:
if ( (regs->xcs &3) == 1 )
printk("Fault at %08x (%08x)\n", addr, regs->eip); /* XXX */
ti = p->thread.traps + 14;
gtb->flags = GTBF_TRAP_CR2; /* page fault pushes %cr2 */
gtb->cr2 = addr;
@@ -285,7 +285,7 @@ asmlinkage void do_page_fault(struct pt_regs *regs, long error_code)
off = addr - LDT_VIRT_START;
addr = p->mm.ldt_base + off;
spin_lock_irq(&p->page_lock);
spin_lock(&p->page_lock);
pl2e = map_domain_mem(pagetable_val(p->mm.pagetable));
l2e = l2_pgentry_val(pl2e[l2_table_offset(addr)]);
@@ -303,34 +303,30 @@ asmlinkage void do_page_fault(struct pt_regs *regs, long error_code)
if ( (page->flags & PG_type_mask) != PGT_ldt_page )
{
if ( page->type_count != 0 )
{ /* XXX */
printk("BOGO TYPE %08lx %ld\n", page->flags, page->type_count);
goto unlock_and_bounce_fault;
}
/* Check all potential LDT entries in the page. */
ldt_page = map_domain_mem(l1e & PAGE_MASK);
for ( i = 0; i < 512; i++ )
if ( !check_descriptor(ldt_page[i*2], ldt_page[i*2+1]) )
{ /* XXX */
printk("Bad desc!!!!!\n");
goto unlock_and_bounce_fault;
}
unmap_domain_mem(ldt_page);
page->flags &= ~PG_type_mask;
page->flags |= PGT_ldt_page;
get_page_type(page);
get_page_tot(page);
}
p->mm.perdomain_pt[l1_table_offset(off)+16] = mk_l1_pgentry(l1e);
get_page_type(page);
get_page_tot(page);
p->mm.perdomain_pt[l1_table_offset(off)+16] = mk_l1_pgentry(l1e|_PAGE_RW);
spin_unlock_irq(&p->page_lock);
spin_unlock(&p->page_lock);
return;
unlock_and_bounce_fault:
spin_unlock_irq(&p->page_lock);
spin_unlock(&p->page_lock);
goto bounce_fault;
@@ -339,6 +335,7 @@ asmlinkage void do_page_fault(struct pt_regs *regs, long error_code)
if ( (fixup = search_exception_table(regs->eip)) != 0 )
{
regs->eip = fixup;
regs->xfs = regs->xgs = 0;
return;
}
@@ -420,8 +417,8 @@ asmlinkage void do_general_protection(struct pt_regs *regs, long error_code)
if ( (fixup = search_exception_table(regs->eip)) != 0 )
{
printk("Hmmmm %08lx -> %08lx (%04lx)\n", regs->eip, fixup, error_code);
regs->eip = fixup;
regs->xfs = regs->xgs = 0;
return;
}
@@ -565,31 +562,14 @@ do { \
"3" ((char *) (addr)),"2" (__HYPERVISOR_CS << 16)); \
} while (0)
/*
* This needs to use 'idt_table' rather than 'idt', and
* thus use the _nonmapped_ version of the IDT, as the
* Pentium F0 0F bugfix can have resulted in the mapped
* IDT being write-protected.
*/
void set_intr_gate(unsigned int n, void *addr)
{
_set_gate(idt_table+n,14,0,addr);
}
static void __init set_trap_gate(unsigned int n, void *addr)
{
_set_gate(idt_table+n,15,0,addr);
}
static void __init set_system_gate(unsigned int n, void *addr)
{
_set_gate(idt_table+n,15,3,addr);
}
static void __init set_call_gate(void *a, void *addr)
{
_set_gate(a,12,3,addr);
_set_gate(idt_table+n,14,3,addr);
}
#define _set_seg_desc(gate_addr,type,dpl,base,limit) {\
@@ -620,29 +600,37 @@ void set_tss_desc(unsigned int n, void *addr)
void __init trap_init(void)
{
set_trap_gate(0,&divide_error);
set_trap_gate(1,&debug);
/*
* Note that interrupt gates are always used, rather than trap gates. We
* must have interrupts disabled until DS/ES/FS/GS are saved because the
* first activation must have the "bad" value(s) for these registers and
* we may lose them if another activation is installed before they are
* saved. The page-fault handler also needs interrupts disabled until %cr2
* has been read and saved on the stack.
*/
set_intr_gate(0,&divide_error);
set_intr_gate(1,&debug);
set_intr_gate(2,&nmi);
set_system_gate(3,&int3); /* usable from all privilege levels */
set_system_gate(4,&overflow); /* usable from all privilege levels */
set_trap_gate(5,&bounds);
set_trap_gate(6,&invalid_op);
set_trap_gate(7,&device_not_available);
set_trap_gate(8,&double_fault);
set_trap_gate(9,&coprocessor_segment_overrun);
set_trap_gate(10,&invalid_TSS);
set_trap_gate(11,&segment_not_present);
set_trap_gate(12,&stack_segment);
set_trap_gate(13,&general_protection);
set_intr_gate(5,&bounds);
set_intr_gate(6,&invalid_op);
set_intr_gate(7,&device_not_available);
set_intr_gate(8,&double_fault);
set_intr_gate(9,&coprocessor_segment_overrun);
set_intr_gate(10,&invalid_TSS);
set_intr_gate(11,&segment_not_present);
set_intr_gate(12,&stack_segment);
set_intr_gate(13,&general_protection);
set_intr_gate(14,&page_fault);
set_trap_gate(15,&spurious_interrupt_bug);
set_trap_gate(16,&coprocessor_error);
set_trap_gate(17,&alignment_check);
set_trap_gate(18,&machine_check);
set_trap_gate(19,&simd_coprocessor_error);
set_intr_gate(15,&spurious_interrupt_bug);
set_intr_gate(16,&coprocessor_error);
set_intr_gate(17,&alignment_check);
set_intr_gate(18,&machine_check);
set_intr_gate(19,&simd_coprocessor_error);
/* Only ring 1 can access monitor services. */
_set_gate(idt_table+HYPERVISOR_CALL_VECTOR,15,1,&hypervisor_call);
_set_gate(idt_table+HYPERVISOR_CALL_VECTOR,14,1,&hypervisor_call);
/* CPU0 uses the master IDT. */
idt_tables[0] = idt_table;
+26 -30
View File
@@ -392,20 +392,19 @@ int setup_guestos(struct task_struct *p, dom0_newdomain_t *params,
/* Sanity! */
if ( p->domain != 0 ) BUG();
/* This is all a bit grim. We've moved the modules to the "safe"
physical memory region above MAP_DIRECTMAP_ADDRESS (48MB). Later
in this routeine, we're going to copy it down into the region
that's actually been allocated to domain 0. This is highly likely
to be overlapping, so we use a forward copy.
/*
* This is all a bit grim. We've moved the modules to the "safe" physical
* memory region above MAP_DIRECTMAP_ADDRESS (48MB). Later in this
* routeine, we're going to copy it down into the region that's actually
* been allocated to domain 0. This is highly likely to be overlapping, so
* we use a forward copy.
*
* MAP_DIRECTMAP_ADDRESS should be safe. The worst case is a machine with
* 4GB and lots of network/disk cards that allocate loads of buffers.
* We'll have to revist this if we ever support PAE (64GB).
*/
MAP_DIRECTMAP_ADDRESS should be safe. The worst case is a machine
with 4GB and lots of network/disk cards that allocate loads of
buffers. We'll have to revist this if we ever support PAE (64GB).
*/
data_start = map_domain_mem( (unsigned long) phy_data_start );
data_start = map_domain_mem((unsigned long)phy_data_start);
if ( strncmp(data_start, "XenoGues", 8) )
{
@@ -480,7 +479,7 @@ int setup_guestos(struct task_struct *p, dom0_newdomain_t *params,
if ( count < p->tot_pages )
{
page = frame_table + (cur_address >> PAGE_SHIFT);
page->flags = dom | PGT_writeable_page;
page->flags = dom | PGT_writeable_page | PG_need_flush;
page->type_count = page->tot_count = 1;
/* Set up the MPT entry. */
machine_to_phys_mapping[cur_address >> PAGE_SHIFT] = count;
@@ -558,24 +557,21 @@ int setup_guestos(struct task_struct *p, dom0_newdomain_t *params,
__write_cr3_counted(pagetable_val(p->mm.pagetable));
/* Copy the guest OS image. */
src = (char *)(phy_data_start + 12);
vsrc= (char *)(data_start + 12); /* data_start invalid after first page*/
dst = (char *)virt_load_address;
src = (char *)(phy_data_start + 12);
vsrc = (char *)(data_start + 12); /* data_start invalid after first page*/
dst = (char *)virt_load_address;
while ( src < (phy_data_start+data_len) )
{
{
*dst++ = *vsrc++;
src++;
if ( (((unsigned long)src) & (PAGE_SIZE-1)) == 0 )
{
{
unmap_domain_mem( vsrc-1 );
vsrc = map_domain_mem( (unsigned long)src );
}
}
}
}
unmap_domain_mem( vsrc );
printk("copy done\n");
/* Set up start info area. */
memset(virt_startinfo_address, 0, sizeof(*virt_startinfo_address));
virt_startinfo_address->nr_pages = p->tot_pages;
@@ -585,13 +581,13 @@ int setup_guestos(struct task_struct *p, dom0_newdomain_t *params,
((p->tot_pages - 1) << PAGE_SHIFT);
if ( initrd_len )
{
{
virt_startinfo_address->mod_start = (unsigned long)dst-initrd_len;
virt_startinfo_address->mod_len = initrd_len;
printk("Initrd len 0x%x, start at 0x%08x\n",
virt_startinfo_address->mod_len, virt_startinfo_address->mod_start);
}
printk("Initrd len 0x%lx, start at 0x%08lx\n",
virt_startinfo_address->mod_len,
virt_startinfo_address->mod_start);
}
/* Add virtual network interfaces and point to them in startinfo. */
while (params->num_vifs-- > 0) {
+9 -9
View File
@@ -192,18 +192,18 @@ void cmain (unsigned long magic, multiboot_info_t *mbi)
new_dom = do_newdomain(0, 0);
if ( new_dom == NULL ) panic("Error creating domain 0\n");
/* We're going to setup domain0 using the module(s) that we
stashed safely above our MAX_DIRECTMAP_ADDRESS in boot/Boot.S
The second module, if present, is an initrd ramdisk
/*
* We're going to setup domain0 using the module(s) that we stashed safely
* above our MAX_DIRECTMAP_ADDRESS in boot/Boot.S The second module, if
* present, is an initrd ramdisk
*/
if ( setup_guestos(new_dom,
&dom0_params,
MAX_DIRECTMAP_ADDRESS,
mod[mbi->mods_count-1].mod_end - mod[0].mod_start, __va(mod[0].string),
(mbi->mods_count==2)?
(mod[1].mod_end - mod[1].mod_start):0)
(char *)MAX_DIRECTMAP_ADDRESS,
mod[mbi->mods_count-1].mod_end - mod[0].mod_start,
__va(mod[0].string),
(mbi->mods_count == 2) ?
(mod[1].mod_end - mod[1].mod_start):0)
!= 0 ) panic("Could not set up DOM0 guest OS\n");
update_dom_time(new_dom->shared_info);
+4 -1
View File
@@ -176,7 +176,7 @@
#include <asm/uaccess.h>
#include <asm/domain_page.h>
#if 1
#if 0
#define MEM_LOG(_f, _a...) printk("DOM%d: (file=memory.c, line=%d) " _f "\n", current->domain, __LINE__, ## _a )
#else
#define MEM_LOG(_f, _a...) ((void)0)
@@ -724,6 +724,9 @@ static int do_extended_command(unsigned long ptr, unsigned long val)
if ( pfn == 0 ) continue;
current->mm.perdomain_pt[i] = mk_l1_pgentry(0);
page = frame_table + pfn;
ASSERT((page->flags & PG_type_mask) == PGT_ldt_page);
ASSERT((page->flags & PG_domain_mask) == current->domain);
ASSERT((page->type_count != 0) && (page->tot_count != 0));
put_page_type(page);
put_page_tot(page);
}
+1 -1
View File
@@ -394,7 +394,7 @@ asmlinkage void schedule(void)
#ifndef NDEBUG
if (r_time < ctx_allow) {
printk("[%02d]: %lx\n", this_cpu, r_time);
printk("[%02d]: %lx\n", this_cpu, (unsigned long)r_time);
dump_rqueue(&schedule_data[this_cpu].runqueue, "foo");
}
#endif
+2
View File
@@ -102,6 +102,8 @@ extern char _stext, _etext;
#define SAVE_ALL \
"cld\n\t" \
"pushl %gs\n\t" \
"pushl %fs\n\t" \
"pushl %es\n\t" \
"pushl %ds\n\t" \
"pushl %eax\n\t" \
+2 -35
View File
@@ -1,28 +1,6 @@
#ifndef _I386_PTRACE_H
#define _I386_PTRACE_H
#define EBX 0
#define ECX 1
#define EDX 2
#define ESI 3
#define EDI 4
#define EBP 5
#define EAX 6
#define DS 7
#define ES 8
#define FS 9
#define GS 10
#define ORIG_EAX 11
#define EIP 12
#define CS 13
#define EFL 14
#define UESP 15
#define SS 16
#define FRAME_SIZE 17
/* this struct defines the way the registers are stored on the
stack during a system call. */
struct pt_regs {
long ebx;
long ecx;
@@ -33,6 +11,8 @@ struct pt_regs {
long eax;
int xds;
int xes;
int xfs;
int xgs;
long orig_eax;
long eip;
int xcs;
@@ -41,19 +21,6 @@ struct pt_regs {
int xss;
};
/* Arbitrarily choose the same ptrace numbers as used by the Sparc code. */
#define PTRACE_GETREGS 12
#define PTRACE_SETREGS 13
#define PTRACE_GETFPREGS 14
#define PTRACE_SETFPREGS 15
#define PTRACE_GETFPXREGS 18
#define PTRACE_SETFPXREGS 19
#define PTRACE_SETOPTIONS 21
/* options set using PTRACE_SETOPTIONS */
#define PTRACE_O_TRACESYSGOOD 0x00000001
enum EFLAGS {
EF_CF = 0x00000001,
EF_PF = 0x00000004,
+5 -27
View File
@@ -4,8 +4,9 @@
#include <xeno/config.h>
#include <asm/bitops.h>
struct task_struct; /* one of the stranger aspects of C forward declarations.. */
extern void FASTCALL(__switch_to(struct task_struct *prev, struct task_struct *next));
struct task_struct;
extern void FASTCALL(__switch_to(struct task_struct *prev,
struct task_struct *next));
#define prepare_to_switch() do { } while(0)
#define switch_to(prev,next) do { \
@@ -33,30 +34,7 @@ extern void FASTCALL(__switch_to(struct task_struct *prev, struct task_struct *n
:"memory"); \
} while (0)
/*
* Load a segment. Fall back on loading the zero
* segment if something goes wrong..
*/
#define loadsegment(seg,value) \
asm volatile("\n" \
"1:\t" \
"movl %0,%%" #seg "\n" \
"2:\n" \
".section .fixup,\"ax\"\n" \
"3:\t" \
"pushl $0\n\t" \
"popl %%" #seg "\n\t" \
"jmp 2b\n" \
".previous\n" \
".section __ex_table,\"a\"\n\t" \
".align 4\n\t" \
".long 1b,3b\n" \
".previous" \
: :"m" (*(unsigned int *)&(value)))
/*
* Clear and set 'TS' bit respectively
*/
/* Clear and set 'TS' bit respectively */
#define clts() __asm__ __volatile__ ("clts")
#define read_cr0() ({ \
unsigned int __dummy; \
@@ -152,7 +130,7 @@ static inline void __set_64bit_var (unsigned long long *ptr,
/*
* Note: no "lock" prefix even on SMP: xchg always implies lock anyway
* Note 2: xchg has side effect, so that attribute volatile is necessary,
* but generally the primitive is invalid, *ptr is output argument. --ANK
* but generally the primitive is invalid, *ptr is output argument. --ANK
*/
static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int size)
{
+15 -13
View File
@@ -67,12 +67,14 @@ typedef struct pfn_info {
#define REFCNT_PIN_BIT 0x40000000UL
#define get_page_tot(p) ((p)->tot_count++)
#define put_page_tot(p) (--(p)->tot_count)
#define put_page_tot(p) \
({ ASSERT((p)->tot_count != 0); --(p)->tot_count; })
#define page_tot_count(p) ((p)->tot_count)
#define set_page_tot_count(p,v) ((p)->tot_count = v)
#define get_page_type(p) ((p)->type_count++)
#define put_page_type(p) (--(p)->type_count)
#define put_page_type(p) \
({ ASSERT((p)->type_count != 0); --(p)->type_count; })
#define page_type_count(p) ((p)->type_count)
#define set_page_type_count(p,v) ((p)->type_count = v)
@@ -95,18 +97,18 @@ typedef struct pfn_info {
#define PGT_gdt_page (5<<24) /* using this page in a GDT? */
#define PGT_ldt_page (6<<24) /* using this page in an LDT? */
#define PGT_writeable_page (7<<24) /* has writable mappings of this page? */
#define PGT_net_rx_buf (8<<24) /* this page has been pirated by the net code. */
#define PGT_net_rx_buf (8<<24) /* this page taken by the net code. */
/*
* This bit indicates that the TLB must be flushed when the type count of this
* frame drops to zero. This is needed on current x86 processors only for
* frames which have guestos-accessible writeable mappings. In this case we must
* prevent stale TLB entries allowing the frame to be written if it used for a
* page table, for example.
* frames which have guestos-accessible writeable mappings. In this case we
* must prevent stale TLB entries allowing the frame to be written if it used
* for a page table, for example.
*
* We have this bit because the writeable type is actually also used to pin a page
* when it is used as a disk read buffer. This doesn't require a TLB flush because
* the frame never has a mapping in the TLB.
* We have this bit because the writeable type is actually also used to pin a
* page when it is used as a disk read buffer. This doesn't require a TLB flush
* because the frame never has a mapping in the TLB.
*/
#define PG_need_flush (1<<28)
@@ -114,10 +116,10 @@ typedef struct pfn_info {
#define PageSetSlab(page) set_bit(PG_slab, &(page)->flags)
#define PageClearSlab(page) clear_bit(PG_slab, &(page)->flags)
#define SHARE_PFN_WITH_DOMAIN(_pfn, _dom) \
do { \
(_pfn)->flags = (_dom) | PGT_writeable_page; \
(_pfn)->tot_count = (_pfn)->type_count = 1; \
#define SHARE_PFN_WITH_DOMAIN(_pfn, _dom) \
do { \
(_pfn)->flags = (_dom) | PGT_writeable_page | PG_need_flush; \
(_pfn)->tot_count = (_pfn)->type_count = 2; \
} while ( 0 )
#define UNSHARE_PFN(_pfn) \
+2 -2
View File
@@ -80,8 +80,8 @@ struct task_struct {
* Return vectors pushed to us by guest OS.
* The stack frame for events is exactly that of an x86 hardware interrupt.
* The stack frame for a failsafe callback is augmented with saved values
* for segment registers %ds and %es:
* %ds, %es, %eip, %cs, %eflags [, %oldesp, %oldss]
* for segment registers %ds, %es, %fs and %gs:
* %ds, %es, %fs, %gs, %eip, %cs, %eflags [, %oldesp, %oldss]
*/
unsigned long event_selector; /* 20: entry CS */
unsigned long event_address; /* 24: entry EIP */
+1 -2
View File
@@ -521,7 +521,7 @@ void deliver_packet(struct sk_buff *skb, net_vif_t *vif)
g_pfn->tot_count = g_pfn->type_count = 0;
h_pfn->flags = g_pfn->flags & ~PG_type_mask;
if (*g_pte & _PAGE_RW) h_pfn->flags |= PGT_writeable_page;
if (*g_pte & _PAGE_RW) h_pfn->flags |= PGT_writeable_page | PG_need_flush;
g_pfn->flags = 0;
/* Point the guest at the new machine frame. */
@@ -567,7 +567,6 @@ int netif_rx(struct sk_buff *skb)
local_irq_save(flags);
ASSERT(skb->skb_type == SKB_ZERO_COPY);
ASSERT((skb->data - skb->head) == (18 + ETH_HLEN));
/*
* Offset will include 16 bytes padding from dev_alloc_skb, 14 bytes for
@@ -373,13 +373,19 @@ critical_fixup_table:
ENTRY(failsafe_callback)
1: pop %ds
2: pop %es
3: iret
3: pop %fs
4: pop %gs
5: iret
.section .fixup,"ax"; \
4: movl $0,(%esp); \
6: movl $0,(%esp); \
jmp 1b; \
5: movl $0,(%esp); \
7: movl $0,(%esp); \
jmp 2b; \
6: pushl %ss; \
8: movl $0,(%esp); \
jmp 3b; \
9: movl $0,(%esp); \
jmp 4b; \
10: pushl %ss; \
popl %ds; \
pushl %ss; \
popl %es; \
@@ -388,9 +394,11 @@ ENTRY(failsafe_callback)
.previous; \
.section __ex_table,"a";\
.align 4; \
.long 1b,4b; \
.long 2b,5b; \
.long 3b,6b; \
.long 1b,6b; \
.long 2b,7b; \
.long 3b,8b; \
.long 4b,9b; \
.long 5b,10b; \
.previous
ENTRY(coprocessor_error)
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.