mirror of
https://github.com/xen-project/xen.git
synced 2026-10-29 18:50:05 +01:00
bitkeeper revision 1.478.1.1 (3f815149k7sE-z_IK6MG5eHi34m-Qg)
Minimal guest OS (based on some old code from Keir)
This commit is contained in:
1 parent
922fddb035
commit
f2c4c1d4e8
26 files changed
+9357
No files matched your search
@@ -1,5 +1,13 @@
|
||||
#!/bin/sh -x
|
||||
set -e
|
||||
test -L mini-os/h/hypervisor-ifs/block.h
|
||||
rm mini-os/h/hypervisor-ifs/block.h
|
||||
test -L mini-os/h/hypervisor-ifs/hypervisor-if.h
|
||||
rm mini-os/h/hypervisor-ifs/hypervisor-if.h
|
||||
test -L mini-os/h/hypervisor-ifs/kbd.h
|
||||
rm mini-os/h/hypervisor-ifs/kbd.h
|
||||
test -L mini-os/h/hypervisor-ifs/network.h
|
||||
rm mini-os/h/hypervisor-ifs/network.h
|
||||
test -L xenolinux-sparse
|
||||
rm xenolinux-sparse
|
||||
(find -depth -type d -print | xargs -r rmdir 2>/dev/null) || true
|
||||
|
||||
@@ -1,5 +1,12 @@
|
||||
#!/bin/sh -x
|
||||
set -e
|
||||
mkdir -p mini-os
|
||||
mkdir -p mini-os/h
|
||||
mkdir -p mini-os/h/hypervisor-ifs
|
||||
ln -s ../../../xen/include/hypervisor-ifs/block.h mini-os/h/hypervisor-ifs/block.h
|
||||
ln -s ../../../xen/include/hypervisor-ifs/hypervisor-if.h mini-os/h/hypervisor-ifs/hypervisor-if.h
|
||||
ln -s ../../../xen/include/hypervisor-ifs/kbd.h mini-os/h/hypervisor-ifs/kbd.h
|
||||
ln -s ../../../xen/include/hypervisor-ifs/network.h mini-os/h/hypervisor-ifs/network.h
|
||||
ln -s xenolinux-2.4.22-sparse xenolinux-sparse
|
||||
(find -depth -type d -print | xargs -r rmdir 2>/dev/null) || true
|
||||
exit 0
|
||||
@@ -6,6 +6,33 @@
|
||||
3f5ef5a24IaQasQE2tyMxrfxskMmvw README
|
||||
3f5ef5a2l4kfBYSQTUaOyyD76WROZQ README.CD
|
||||
3f69d8abYB1vMyD_QVDvzxy5Zscf1A TODO
|
||||
3f815144d1vI2777JI-dO4wk49Iw7g mini-os/Makefile
|
||||
3f815144zTnCV5591ulIJQrpe5b-5Q mini-os/README
|
||||
3f815144wiiDekmfMl9LIPIvhR83Uw mini-os/entry.S
|
||||
3f815144r7AHj8GPvc3Nl1L9OSsWIg mini-os/events.c
|
||||
3f815144h-Chna6E38yo40jqU95G1Q mini-os/h/events.h
|
||||
3f815144oqr2OlUDzE2GfkKX5Hcxqg mini-os/h/hypervisor-ifs/block.h
|
||||
3f8151443nGXvfUTFG67VXOIH8P4lg mini-os/h/hypervisor-ifs/hypervisor-if.h
|
||||
3f81514417ZlYqiRdM_AHPy7G11htA mini-os/h/hypervisor-ifs/kbd.h
|
||||
3f815144J3ZfU5am03Td7Wjfrz30qQ mini-os/h/hypervisor-ifs/network.h
|
||||
3f8151445bYdgThGHQPeOW49PsrJ_A mini-os/h/hypervisor.h
|
||||
3f815144f2Vg3qb6tiwt2VZad-DWsg mini-os/h/lib.h
|
||||
3f815144iqXtdYup_pyfPSmDZuvZcg mini-os/h/list.h
|
||||
3f81514437EzzRWAnZl4_Ej1oznMjg mini-os/h/mm.h
|
||||
3f815144nbSjjT1h4m99-QPbeSWY0Q mini-os/h/os.h
|
||||
3f815144L1t0AevJt2JDXPegv6JTrw mini-os/h/time.h
|
||||
3f815144UxddtL0ICCKisN-NDHNFaA mini-os/h/types.h
|
||||
3f815145W2mamPMclRLOzm5B38vWUQ mini-os/head.S
|
||||
3f815145LqcH11TCEZbAvcjarckkJw mini-os/hypervisor.c
|
||||
3f815145vwnmxhCwN7dMRWv_XFtXbg mini-os/kernel.c
|
||||
3f8151451k5emQAlRe80JdIvfSN4VA mini-os/lib/malloc.c
|
||||
3f815145Mb9WSKjOPsYTLsPIvPyy4Q mini-os/lib/math.c
|
||||
3f8151454rEuPjN74V2Bcu65RLnM-Q mini-os/lib/printf.c
|
||||
3f815145MQZrUJV0iRmTK2KIhwB2wg mini-os/lib/string.c
|
||||
3f815145CB8XdPUqsmhAjSDFuwOoqA mini-os/mm.c
|
||||
3f815145vGYx1WY79voKkZB9yKwJKQ mini-os/time.c
|
||||
3f815145xlKBAQmal9oces3G_Mvxqw mini-os/traps.c
|
||||
3f815145AYE58Kpmsj5U7oHDpVDZJA mini-os/vmlinux.lds
|
||||
3f776bd1Hy9rn69ntXBhPReUFw9IEA tools/Makefile
|
||||
3e6377b24eQqYMsDi9XrFkIgTzZ47A tools/balloon/Makefile
|
||||
3e6377d6eiFjF1hHIS6JEIOFk62xSA tools/balloon/README
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
|
||||
CC := gcc
|
||||
LD := ld
|
||||
# Linker should relocate monitor to this address
|
||||
MONITOR_BASE := 0xE0100000
|
||||
CFLAGS := -fno-builtin -O3 -Wall -Ih/
|
||||
|
||||
TARGET := image.final
|
||||
|
||||
LOBJS:= lib/malloc.o lib/math.o lib/printf.o lib/string.o
|
||||
OBJS := entry.o kernel.o traps.o hypervisor.o mm.o events.o time.o ${LOBJS}
|
||||
|
||||
HINTF := h/hypervisor-ifs/hypervisor-if.h
|
||||
HDRS := h/os.h h/types.h h/hypervisor.h h/mm.h h/events.h h/time.h h/lib.h $(HINTF)
|
||||
|
||||
default: $(TARGET)
|
||||
|
||||
$(TARGET): head.o $(OBJS)
|
||||
# Image will load at 0xC0000000. First bytes from head.o
|
||||
#$(LD) -N -Ttext 0xC0000000 head.o $(OBJS) -o image.elf
|
||||
$(LD) -N -T vmlinux.lds head.o $(OBJS) -o image.elf
|
||||
# Guest OS header -- first 8 bytes are identifier 'XenoGues'.
|
||||
echo -e -n 'XenoGues' >$@
|
||||
# Guest OS header -- next 4 bytes are load address (0xC0000000).
|
||||
echo -e -n '\000\000\000\300' >>$@
|
||||
# Create a raw bag of bytes from the ELF image.
|
||||
objcopy -O binary -R .note -R .comment image.elf image.raw
|
||||
# Guest OS header is immediately followed by raw OS image.
|
||||
cat image.raw >>$@
|
||||
#gzip -f -9 $@
|
||||
|
||||
clean:
|
||||
rm -f *.o *~ core image.elf image.raw image.final image.final.gz
|
||||
|
||||
%.o: %.c $(HDRS) Makefile
|
||||
$(CC) $(CFLAGS) -c $< -o $@
|
||||
|
||||
%.o: %.S $(HDRS) Makefile
|
||||
$(CC) $(CFLAGS) -D__ASSEMBLY__ -c $< -o $@
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
Minimal OS
|
||||
----------
|
||||
|
||||
This shows some of the stuff that any guest OS will have to set up.
|
||||
|
||||
This includes:
|
||||
|
||||
* installing a virtual exception table
|
||||
* handling virtual exceptions
|
||||
* handling asynchronous events
|
||||
* enabling/disabling async events
|
||||
* parsing start_info struct at start-of-day
|
||||
* registering virtual interrupt handlers (for timer interrupts)
|
||||
* a simple page and memory allocator
|
||||
* minimal libc support
|
||||
|
||||
Stuff it doesn't show:
|
||||
|
||||
* modifying page tables
|
||||
* network code
|
||||
* block-device code
|
||||
|
||||
|
||||
- to build it just type make.
|
||||
|
||||
- copy image.final somewhere where dom0 can access it
|
||||
|
||||
- in dom0
|
||||
# xi_create 16000 test
|
||||
<domid>
|
||||
# xi_build <domid> image.final 0
|
||||
# xi_start <domid>
|
||||
|
||||
this prints out a bunch of stuff and then every 1000 timer interrupts the
|
||||
system time.
|
||||
+348
@@ -0,0 +1,348 @@
|
||||
/*
|
||||
* linux/arch/i386/entry.S
|
||||
*
|
||||
* Copyright (C) 1991, 1992 Linus Torvalds
|
||||
*
|
||||
* Adjusted for XenoLinux use by K A Frasier
|
||||
* Adjusted for Xen minimal os by R Neugebauer
|
||||
*/
|
||||
|
||||
|
||||
#include <os.h>
|
||||
|
||||
EBX = 0x00
|
||||
ECX = 0x04
|
||||
EDX = 0x08
|
||||
ESI = 0x0C
|
||||
EDI = 0x10
|
||||
EBP = 0x14
|
||||
EAX = 0x18
|
||||
DS = 0x1C
|
||||
ES = 0x20
|
||||
ORIG_EAX = 0x24
|
||||
EIP = 0x28
|
||||
CS = 0x2C
|
||||
EFLAGS = 0x30
|
||||
OLDESP = 0x34
|
||||
OLDSS = 0x38
|
||||
|
||||
CF_MASK = 0x00000001
|
||||
IF_MASK = 0x00000200
|
||||
NT_MASK = 0x00004000
|
||||
|
||||
/* Declare a globally-visible label */
|
||||
#define ENTRY(X) .globl X ; X :
|
||||
|
||||
/* A Linux hangover. Just ignore it. */
|
||||
#define SYMBOL_NAME(X) X
|
||||
|
||||
#define SAVE_ALL \
|
||||
cld; \
|
||||
pushl %es; \
|
||||
pushl %ds; \
|
||||
pushl %eax; \
|
||||
pushl %ebp; \
|
||||
pushl %edi; \
|
||||
pushl %esi; \
|
||||
pushl %edx; \
|
||||
pushl %ecx; \
|
||||
pushl %ebx; \
|
||||
movl $(__KERNEL_DS),%edx; \
|
||||
movl %edx,%ds; \
|
||||
movl %edx,%es;
|
||||
|
||||
#define RESTORE_ALL \
|
||||
popl %ebx; \
|
||||
popl %ecx; \
|
||||
popl %edx; \
|
||||
popl %esi; \
|
||||
popl %edi; \
|
||||
popl %ebp; \
|
||||
popl %eax; \
|
||||
1: popl %ds; \
|
||||
2: popl %es; \
|
||||
addl $4,%esp; \
|
||||
3: iret; \
|
||||
.section .fixup,"ax"; \
|
||||
4: movl $0,(%esp); \
|
||||
jmp 1b; \
|
||||
5: movl $0,(%esp); \
|
||||
jmp 2b; \
|
||||
6: pushl %ss; \
|
||||
popl %ds; \
|
||||
pushl %ss; \
|
||||
popl %es; \
|
||||
pushl $11; \
|
||||
call do_exit; \
|
||||
.previous; \
|
||||
.section __ex_table,"a";\
|
||||
.align 4; \
|
||||
.long 1b,4b; \
|
||||
.long 2b,5b; \
|
||||
.long 3b,6b; \
|
||||
.previous
|
||||
|
||||
ENTRY(divide_error)
|
||||
pushl $0 # no error code
|
||||
pushl $ SYMBOL_NAME(do_divide_error)
|
||||
.align 4
|
||||
error_code:
|
||||
pushl %ds
|
||||
pushl %eax
|
||||
xorl %eax,%eax
|
||||
pushl %ebp
|
||||
pushl %edi
|
||||
pushl %esi
|
||||
pushl %edx
|
||||
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
|
||||
pushl %esi # push the error code
|
||||
pushl %edx # push the pt_regs pointer
|
||||
movl $(__KERNEL_DS),%edx
|
||||
movl %edx,%ds
|
||||
movl %edx,%es
|
||||
call *%edi
|
||||
addl $8,%esp
|
||||
|
||||
# These are the tests Linux makes before exiting the OS back to userland.
|
||||
# At these point preeemption may occur, or signals may get delivered.
|
||||
ret_to_user_tests:
|
||||
# cmpl $0,need_resched(%ebx)
|
||||
# jne reschedule
|
||||
# cmpl $0,sigpending(%ebx)
|
||||
# je safesti
|
||||
jmp safesti
|
||||
|
||||
|
||||
ret_from_exception:
|
||||
movb CS(%esp),%cl
|
||||
test $2,%cl # slow return to ring 2 or 3
|
||||
jne ret_to_user_tests
|
||||
RESTORE_ALL
|
||||
|
||||
# A note on the "critical region" in our callback handler.
|
||||
# We want to avoid stacking callback handlers due to events occurring
|
||||
# during handling of the last event. To do this, we keep events disabled
|
||||
# until weve done all processing. HOWEVER, we must enable events before
|
||||
# popping the stack frame (cant be done atomically) and so it would still
|
||||
# be possible to get enough handler activations to overflow the stack.
|
||||
# Although unlikely, bugs of that kind are hard to track down, so wed
|
||||
# like to avoid the possibility.
|
||||
# So, on entry to the handler we detect whether we interrupted an
|
||||
# existing activation in its critical region -- if so, we pop the current
|
||||
# activation and restart the handler using the previous one.
|
||||
ENTRY(hypervisor_callback)
|
||||
pushl %eax
|
||||
SAVE_ALL
|
||||
movl EIP(%esp),%eax
|
||||
cmpl $scrit,%eax
|
||||
jb 11f
|
||||
cmpl $ecrit,%eax
|
||||
jb critical_region_fixup
|
||||
11: push %esp
|
||||
call do_hypervisor_callback
|
||||
add $4,%esp
|
||||
movl SYMBOL_NAME(HYPERVISOR_shared_info),%esi
|
||||
xorl %eax,%eax
|
||||
movb CS(%esp),%cl
|
||||
test $2,%cl # slow return to ring 2 or 3
|
||||
jne ret_to_user_tests
|
||||
safesti:btsl $31,4(%esi) # reenable event callbacks
|
||||
scrit: /**** START OF CRITICAL REGION ****/
|
||||
cmpl %eax,(%esi)
|
||||
jne 14f # process more events if necessary...
|
||||
RESTORE_ALL
|
||||
14: btrl %eax,4(%esi)
|
||||
jmp 11b
|
||||
ecrit: /**** END OF CRITICAL REGION ****/
|
||||
# [How we do the fixup]. We want to merge the current stack frame with the
|
||||
# just-interrupted frame. How we do this depends on where in the critical
|
||||
# region the interrupted handler was executing, and so how many saved
|
||||
# registers are in each frame. We do this quickly using the lookup table
|
||||
# 'critical_fixup_table'. For each byte offset in the critical region, it
|
||||
# provides the number of bytes which have already been popped from the
|
||||
# interrupted stack frame.
|
||||
critical_region_fixup:
|
||||
addl $critical_fixup_table-scrit,%eax
|
||||
movzbl (%eax),%eax # %eax contains num bytes popped
|
||||
mov %esp,%esi
|
||||
add %eax,%esi # %esi points at end of src region
|
||||
mov %esp,%edi
|
||||
add $0x34,%edi # %edi points at end of dst region
|
||||
mov %eax,%ecx
|
||||
shr $2,%ecx # convert words to bytes
|
||||
je 16f # skip loop if nothing to copy
|
||||
15: subl $4,%esi # pre-decrementing copy loop
|
||||
subl $4,%edi
|
||||
movl (%esi),%eax
|
||||
movl %eax,(%edi)
|
||||
loop 15b
|
||||
16: movl %edi,%esp # final %edi is top of merged stack
|
||||
jmp 11b
|
||||
|
||||
critical_fixup_table:
|
||||
.byte 0x00,0x00 # cmpl %eax,(%esi)
|
||||
.byte 0x00,0x00 # jne 14f
|
||||
.byte 0x00 # pop %ebx
|
||||
.byte 0x04 # pop %ecx
|
||||
.byte 0x08 # pop %edx
|
||||
.byte 0x0c # pop %esi
|
||||
.byte 0x10 # pop %edi
|
||||
.byte 0x14 # pop %ebp
|
||||
.byte 0x18 # pop %eax
|
||||
.byte 0x1c # pop %ds
|
||||
.byte 0x20 # pop %es
|
||||
.byte 0x24,0x24,0x24 # add $4,%esp
|
||||
.byte 0x28 # iret
|
||||
.byte 0x00,0x00,0x00,0x00,0x00 # btrl $31,4(%esi)
|
||||
.byte 0x00,0x00 # jmp 11b
|
||||
|
||||
# Hypervisor uses this for application faults while it executes.
|
||||
ENTRY(failsafe_callback)
|
||||
1: pop %ds
|
||||
2: pop %es
|
||||
3: pop %fs
|
||||
4: pop %gs
|
||||
5: iret
|
||||
.section .fixup,"ax"; \
|
||||
6: movl $0,(%esp); \
|
||||
jmp 1b; \
|
||||
7: movl $0,(%esp); \
|
||||
jmp 2b; \
|
||||
8: movl $0,(%esp); \
|
||||
jmp 3b; \
|
||||
9: movl $0,(%esp); \
|
||||
jmp 4b; \
|
||||
10: pushl %ss; \
|
||||
popl %ds; \
|
||||
pushl %ss; \
|
||||
popl %es; \
|
||||
pushl $11; \
|
||||
call do_exit; \
|
||||
.previous; \
|
||||
.section __ex_table,"a";\
|
||||
.align 4; \
|
||||
.long 1b,6b; \
|
||||
.long 2b,7b; \
|
||||
.long 3b,8b; \
|
||||
.long 4b,9b; \
|
||||
.long 5b,10b; \
|
||||
.previous
|
||||
|
||||
ENTRY(coprocessor_error)
|
||||
pushl $0
|
||||
pushl $ SYMBOL_NAME(do_coprocessor_error)
|
||||
jmp error_code
|
||||
|
||||
ENTRY(simd_coprocessor_error)
|
||||
pushl $0
|
||||
pushl $ SYMBOL_NAME(do_simd_coprocessor_error)
|
||||
jmp error_code
|
||||
|
||||
ENTRY(device_not_available)
|
||||
pushl $-1 # mark this as an int
|
||||
SAVE_ALL
|
||||
#call SYMBOL_NAME(math_state_restore)
|
||||
jmp ret_from_exception
|
||||
|
||||
ENTRY(debug)
|
||||
pushl $0
|
||||
pushl $ SYMBOL_NAME(do_debug)
|
||||
jmp error_code
|
||||
|
||||
ENTRY(int3)
|
||||
pushl $0
|
||||
pushl $ SYMBOL_NAME(do_int3)
|
||||
jmp error_code
|
||||
|
||||
ENTRY(overflow)
|
||||
pushl $0
|
||||
pushl $ SYMBOL_NAME(do_overflow)
|
||||
jmp error_code
|
||||
|
||||
ENTRY(bounds)
|
||||
pushl $0
|
||||
pushl $ SYMBOL_NAME(do_bounds)
|
||||
jmp error_code
|
||||
|
||||
ENTRY(invalid_op)
|
||||
pushl $0
|
||||
pushl $ SYMBOL_NAME(do_invalid_op)
|
||||
jmp error_code
|
||||
|
||||
ENTRY(coprocessor_segment_overrun)
|
||||
pushl $0
|
||||
pushl $ SYMBOL_NAME(do_coprocessor_segment_overrun)
|
||||
jmp error_code
|
||||
|
||||
ENTRY(double_fault)
|
||||
pushl $ SYMBOL_NAME(do_double_fault)
|
||||
jmp error_code
|
||||
|
||||
ENTRY(invalid_TSS)
|
||||
pushl $ SYMBOL_NAME(do_invalid_TSS)
|
||||
jmp error_code
|
||||
|
||||
ENTRY(segment_not_present)
|
||||
pushl $ SYMBOL_NAME(do_segment_not_present)
|
||||
jmp error_code
|
||||
|
||||
ENTRY(stack_segment)
|
||||
pushl $ SYMBOL_NAME(do_stack_segment)
|
||||
jmp error_code
|
||||
|
||||
ENTRY(general_protection)
|
||||
pushl $ SYMBOL_NAME(do_general_protection)
|
||||
jmp error_code
|
||||
|
||||
ENTRY(alignment_check)
|
||||
pushl $ SYMBOL_NAME(do_alignment_check)
|
||||
jmp error_code
|
||||
|
||||
# This handler is special, because it gets an extra value on its stack,
|
||||
# which is the linear faulting address.
|
||||
ENTRY(page_fault)
|
||||
pushl %ds
|
||||
pushl %eax
|
||||
xorl %eax,%eax
|
||||
pushl %ebp
|
||||
pushl %edi
|
||||
pushl %esi
|
||||
pushl %edx
|
||||
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 faulting address
|
||||
movl %eax, ORIG_EAX(%esp)
|
||||
movl %ecx, ES(%esp)
|
||||
movl %esp,%edx
|
||||
pushl %edi # push the faulting address
|
||||
pushl %esi # push the error code
|
||||
pushl %edx # push the pt_regs pointer
|
||||
movl $(__KERNEL_DS),%edx
|
||||
movl %edx,%ds
|
||||
movl %edx,%es
|
||||
call SYMBOL_NAME(do_page_fault)
|
||||
addl $12,%esp
|
||||
jmp ret_from_exception
|
||||
|
||||
ENTRY(machine_check)
|
||||
pushl $0
|
||||
pushl $ SYMBOL_NAME(do_machine_check)
|
||||
jmp error_code
|
||||
|
||||
ENTRY(spurious_interrupt_bug)
|
||||
pushl $0
|
||||
pushl $ SYMBOL_NAME(do_spurious_interrupt_bug)
|
||||
jmp error_code
|
||||
@@ -0,0 +1,106 @@
|
||||
/* -*- Mode:C; c-basic-offset:4; tab-width:4 -*-
|
||||
****************************************************************************
|
||||
* (C) 2003 - Rolf Neugebauer - Intel Research Cambridge
|
||||
****************************************************************************
|
||||
*
|
||||
* File: events.c
|
||||
* Author: Rolf Neugebauer (neugebar@dcs.gla.ac.uk)
|
||||
* Changes:
|
||||
*
|
||||
* Date: Jul 2003
|
||||
*
|
||||
* Environment: Xen Minimal OS
|
||||
* Description: Deal with events
|
||||
*
|
||||
****************************************************************************
|
||||
* $Id: c-insert.c,v 1.7 2002/11/08 16:04:34 rn Exp $
|
||||
****************************************************************************
|
||||
*/
|
||||
|
||||
#include <os.h>
|
||||
#include <hypervisor.h>
|
||||
#include <events.h>
|
||||
#include <lib.h>
|
||||
|
||||
static ev_action_t ev_actions[NR_EVS];
|
||||
void default_handler(int ev, struct pt_regs *regs);
|
||||
|
||||
|
||||
/*
|
||||
* demux events to different handlers
|
||||
*/
|
||||
asmlinkage unsigned int do_event(int ev, struct pt_regs *regs)
|
||||
{
|
||||
ev_action_t *action;
|
||||
|
||||
if (ev >= NR_EVS) {
|
||||
printk("Large event number %d\n", ev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
action = &ev_actions[ev];
|
||||
action->count++;
|
||||
ack_hypervisor_event(ev);
|
||||
|
||||
if (!action->handler)
|
||||
goto out;
|
||||
|
||||
if (action->status & EVS_DISABLED)
|
||||
goto out;
|
||||
|
||||
/* call the handler */
|
||||
action->handler(ev, regs);
|
||||
|
||||
out:
|
||||
return 1;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* add a handler
|
||||
*/
|
||||
unsigned int add_ev_action( int ev, void (*handler)(int, struct pt_regs *) )
|
||||
{
|
||||
if (ev_actions[ev].handler) {
|
||||
printk ("event[%d] already handled by %p", ev, ev_actions[ev].handler);
|
||||
return 0;
|
||||
}
|
||||
|
||||
ev_actions[ev].handler = handler;
|
||||
return 1;
|
||||
}
|
||||
|
||||
unsigned int enable_ev_action( int ev )
|
||||
{
|
||||
if (!ev_actions[ev].handler) {
|
||||
printk ("enable event[%d], no handler installed", ev);
|
||||
return 0;
|
||||
}
|
||||
ev_actions[ev].status &= ~EVS_DISABLED;
|
||||
return 1;
|
||||
}
|
||||
|
||||
unsigned int disable_ev_action( int ev )
|
||||
{
|
||||
ev_actions[ev].status |= EVS_DISABLED;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* initially all events are without a handler and disabled
|
||||
*/
|
||||
void init_events(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* inintialise event handler */
|
||||
for ( i = 0; i < NR_EVS; i++ )
|
||||
{
|
||||
ev_actions[i].status = EVS_DISABLED;
|
||||
ev_actions[i].handler = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void default_handler(int ev, struct pt_regs *regs) {
|
||||
printk("X[%d] ", ev);
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
/* -*- Mode:C; c-basic-offset:4; tab-width:4 -*-
|
||||
****************************************************************************
|
||||
* (C) 2003 - Rolf Neugebauer - Intel Research Cambridge
|
||||
****************************************************************************
|
||||
*
|
||||
* File: events.h
|
||||
* Author: Rolf Neugebauer (neugebar@dcs.gla.ac.uk)
|
||||
* Changes:
|
||||
*
|
||||
* Date: Jul 2003
|
||||
*
|
||||
* Environment: Xen Minimal OS
|
||||
* Description: deal with events
|
||||
*
|
||||
****************************************************************************
|
||||
* $Id: h-insert.h,v 1.4 2002/11/08 16:03:55 rn Exp $
|
||||
****************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef _EVENTS_H_
|
||||
#define _EVENTS_H_
|
||||
|
||||
/* _EVENT_* are defined in hypervisor-if.h */
|
||||
#define EV_BLKDEV _EVENT_BLKDEV
|
||||
#define EV_TIMER _EVENT_TIMER
|
||||
#define EV_DIE _EVENT_DIE
|
||||
#define EV_DEBUG _EVENT_DEBUG
|
||||
#define EV_NET _EVENT_NET
|
||||
#define EV_PS2 _EVENT_PS2
|
||||
|
||||
#define NR_EVS (sizeof(HYPERVISOR_shared_info->events) * 8)
|
||||
|
||||
/* ev handler status */
|
||||
#define EVS_INPROGRESS 1 /* Event handler active - do not enter! */
|
||||
#define EVS_DISABLED 2 /* Event disabled - do not enter! */
|
||||
#define EVS_PENDING 4 /* Event pending - replay on enable */
|
||||
#define EVS_REPLAY 8 /* Event has been replayed but not acked yet */
|
||||
|
||||
/* this represents a event handler. Chaining or sharing is not allowed */
|
||||
typedef struct _ev_action_t {
|
||||
void (*handler)(int, struct pt_regs *);
|
||||
unsigned int status; /* IRQ status */
|
||||
u32 count;
|
||||
} ev_action_t;
|
||||
|
||||
/* prototypes */
|
||||
unsigned int do_event(int ev, struct pt_regs *regs);
|
||||
unsigned int add_ev_action( int ev, void (*handler)(int, struct pt_regs *) );
|
||||
unsigned int enable_ev_action( int ev );
|
||||
unsigned int disable_ev_action( int ev );
|
||||
void init_events(void);
|
||||
|
||||
#endif /* _EVENTS_H_ */
|
||||
@@ -0,0 +1,266 @@
|
||||
|
||||
/******************************************************************************
|
||||
* hypervisor.h
|
||||
*
|
||||
* Linux-specific hypervisor handling.
|
||||
*
|
||||
* Adjusted by R Neugebauer for Xen minimal OS
|
||||
*
|
||||
* Copyright (c) 2002, K A Fraser
|
||||
*/
|
||||
|
||||
#ifndef _HYPERVISOR_H_
|
||||
#define _HYPERVISOR_H_
|
||||
|
||||
#include <types.h>
|
||||
|
||||
/* include the hypervisor interface */
|
||||
#include <hypervisor-ifs/network.h>
|
||||
#include <hypervisor-ifs/block.h>
|
||||
#include <hypervisor-ifs/hypervisor-if.h>
|
||||
|
||||
|
||||
/*
|
||||
* a placeholder for the start of day information passed up from the hypervisor
|
||||
*/
|
||||
union start_info_union
|
||||
{
|
||||
start_info_t start_info;
|
||||
char padding[512];
|
||||
};
|
||||
extern union start_info_union start_info_union;
|
||||
#define start_info (start_info_union.start_info)
|
||||
|
||||
|
||||
/* hypervisor.c */
|
||||
void do_hypervisor_callback(struct pt_regs *regs);
|
||||
void enable_hypervisor_event(unsigned int ev);
|
||||
void disable_hypervisor_event(unsigned int ev);
|
||||
void ack_hypervisor_event(unsigned int ev);
|
||||
|
||||
/*
|
||||
* Assembler stubs for hyper-calls.
|
||||
*/
|
||||
|
||||
static inline int HYPERVISOR_set_trap_table(trap_info_t *table)
|
||||
{
|
||||
int ret;
|
||||
__asm__ __volatile__ (
|
||||
TRAP_INSTR
|
||||
: "=a" (ret) : "0" (__HYPERVISOR_set_trap_table),
|
||||
"b" (table) );
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline int HYPERVISOR_pt_update(page_update_request_t *req, int count)
|
||||
{
|
||||
int ret;
|
||||
__asm__ __volatile__ (
|
||||
TRAP_INSTR
|
||||
: "=a" (ret) : "0" (__HYPERVISOR_pt_update),
|
||||
"b" (req), "c" (count) );
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline int HYPERVISOR_console_write(const char *str, int count)
|
||||
{
|
||||
int ret;
|
||||
__asm__ __volatile__ (
|
||||
TRAP_INSTR
|
||||
: "=a" (ret) : "0" (__HYPERVISOR_console_write),
|
||||
"b" (str), "c" (count) );
|
||||
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline int HYPERVISOR_set_gdt(unsigned long *frame_list, int entries)
|
||||
{
|
||||
int ret;
|
||||
__asm__ __volatile__ (
|
||||
TRAP_INSTR
|
||||
: "=a" (ret) : "0" (__HYPERVISOR_set_gdt),
|
||||
"b" (frame_list), "c" (entries) );
|
||||
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline int HYPERVISOR_stack_switch(unsigned long ss, unsigned long esp)
|
||||
{
|
||||
int ret;
|
||||
__asm__ __volatile__ (
|
||||
TRAP_INSTR
|
||||
: "=a" (ret) : "0" (__HYPERVISOR_stack_switch),
|
||||
"b" (ss), "c" (esp) : "memory" );
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline int HYPERVISOR_set_callbacks(
|
||||
unsigned long event_selector, unsigned long event_address,
|
||||
unsigned long failsafe_selector, unsigned long failsafe_address)
|
||||
{
|
||||
int ret;
|
||||
__asm__ __volatile__ (
|
||||
TRAP_INSTR
|
||||
: "=a" (ret) : "0" (__HYPERVISOR_set_callbacks),
|
||||
"b" (event_selector), "c" (event_address),
|
||||
"d" (failsafe_selector), "S" (failsafe_address) : "memory" );
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline int HYPERVISOR_net_update(void)
|
||||
{
|
||||
int ret;
|
||||
__asm__ __volatile__ (
|
||||
TRAP_INSTR
|
||||
: "=a" (ret) : "0" (__HYPERVISOR_net_update) );
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline int HYPERVISOR_fpu_taskswitch(void)
|
||||
{
|
||||
int ret;
|
||||
__asm__ __volatile__ (
|
||||
TRAP_INSTR
|
||||
: "=a" (ret) : "0" (__HYPERVISOR_fpu_taskswitch) );
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline int HYPERVISOR_yield(void)
|
||||
{
|
||||
int ret;
|
||||
__asm__ __volatile__ (
|
||||
TRAP_INSTR
|
||||
: "=a" (ret) : "0" (__HYPERVISOR_yield) );
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline int HYPERVISOR_exit(void)
|
||||
{
|
||||
int ret;
|
||||
__asm__ __volatile__ (
|
||||
TRAP_INSTR
|
||||
: "=a" (ret) : "0" (__HYPERVISOR_exit) );
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline int HYPERVISOR_dom0_op(void *dom0_op)
|
||||
{
|
||||
int ret;
|
||||
__asm__ __volatile__ (
|
||||
TRAP_INSTR
|
||||
: "=a" (ret) : "0" (__HYPERVISOR_dom0_op),
|
||||
"b" (dom0_op) : "memory" );
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline int HYPERVISOR_network_op(void *network_op)
|
||||
{
|
||||
int ret;
|
||||
__asm__ __volatile__ (
|
||||
TRAP_INSTR
|
||||
: "=a" (ret) : "0" (__HYPERVISOR_network_op),
|
||||
"b" (network_op) );
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline int HYPERVISOR_block_io_op(void)
|
||||
{
|
||||
int ret;
|
||||
__asm__ __volatile__ (
|
||||
TRAP_INSTR
|
||||
: "=a" (ret) : "0" (__HYPERVISOR_block_io_op) );
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline int HYPERVISOR_set_debugreg(int reg, unsigned long value)
|
||||
{
|
||||
int ret;
|
||||
__asm__ __volatile__ (
|
||||
TRAP_INSTR
|
||||
: "=a" (ret) : "0" (__HYPERVISOR_set_debugreg),
|
||||
"b" (reg), "c" (value) );
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline unsigned long HYPERVISOR_get_debugreg(int reg)
|
||||
{
|
||||
unsigned long ret;
|
||||
__asm__ __volatile__ (
|
||||
TRAP_INSTR
|
||||
: "=a" (ret) : "0" (__HYPERVISOR_get_debugreg),
|
||||
"b" (reg) );
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline int HYPERVISOR_update_descriptor(
|
||||
unsigned long pa, unsigned long word1, unsigned long word2)
|
||||
{
|
||||
int ret;
|
||||
__asm__ __volatile__ (
|
||||
TRAP_INSTR
|
||||
: "=a" (ret) : "0" (__HYPERVISOR_update_descriptor),
|
||||
"b" (pa), "c" (word1), "d" (word2) );
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline int HYPERVISOR_set_fast_trap(int idx)
|
||||
{
|
||||
int ret;
|
||||
__asm__ __volatile__ (
|
||||
TRAP_INSTR
|
||||
: "=a" (ret) : "0" (__HYPERVISOR_set_fast_trap),
|
||||
"b" (idx) );
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline int HYPERVISOR_dom_mem_op(void *dom_mem_op)
|
||||
{
|
||||
int ret;
|
||||
__asm__ __volatile__ (
|
||||
TRAP_INSTR
|
||||
: "=a" (ret) : "0" (__HYPERVISOR_dom_mem_op),
|
||||
"b" (dom_mem_op) : "memory" );
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline int HYPERVISOR_multicall(void *call_list, int nr_calls)
|
||||
{
|
||||
int ret;
|
||||
__asm__ __volatile__ (
|
||||
TRAP_INSTR
|
||||
: "=a" (ret) : "0" (__HYPERVISOR_multicall),
|
||||
"b" (call_list), "c" (nr_calls) : "memory" );
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline long HYPERVISOR_kbd_op(unsigned char op, unsigned char val)
|
||||
{
|
||||
int ret;
|
||||
__asm__ __volatile__ (
|
||||
TRAP_INSTR
|
||||
: "=a" (ret) : "0" (__HYPERVISOR_kbd_op),
|
||||
"b" (op), "c" (val) );
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif /* __HYPERVISOR_H__ */
|
||||
+129
@@ -0,0 +1,129 @@
|
||||
/* -*- Mode:C; c-basic-offset:4; tab-width:4 -*-
|
||||
****************************************************************************
|
||||
* (C) 2003 - Rolf Neugebauer - Intel Research Cambridge
|
||||
****************************************************************************
|
||||
*
|
||||
* File: lib.h
|
||||
* Author: Rolf Neugebauer (neugebar@dcs.gla.ac.uk)
|
||||
* Changes:
|
||||
*
|
||||
* Date: Aug 2003
|
||||
*
|
||||
* Environment: Xen Minimal OS
|
||||
* Description: Random useful library functions, contains some freebsd stuff
|
||||
*
|
||||
****************************************************************************
|
||||
* $Id: h-insert.h,v 1.4 2002/11/08 16:03:55 rn Exp $
|
||||
****************************************************************************
|
||||
*
|
||||
*-
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. 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.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
|
||||
*
|
||||
* @(#)stdarg.h 8.1 (Berkeley) 6/10/93
|
||||
* $FreeBSD: src/sys/i386/include/stdarg.h,v 1.10 1999/08/28 00:44:26 peter Exp $
|
||||
*/
|
||||
|
||||
#ifndef _LIB_H_
|
||||
#define _LIB_H_
|
||||
|
||||
|
||||
/* variadic function support */
|
||||
typedef char *va_list;
|
||||
#define __va_size(type) \
|
||||
(((sizeof(type) + sizeof(int) - 1) / sizeof(int)) * sizeof(int))
|
||||
#ifdef __GNUC__
|
||||
#define va_start(ap, last) \
|
||||
((ap) = (va_list)__builtin_next_arg(last))
|
||||
#else
|
||||
#define va_start(ap, last) \
|
||||
((ap) = (va_list)&(last) + __va_size(last))
|
||||
#endif
|
||||
#define va_arg(ap, type) \
|
||||
(*(type *)((ap) += __va_size(type), (ap) - __va_size(type)))
|
||||
#define va_end(ap)
|
||||
|
||||
|
||||
/* printing */
|
||||
#define printk printf
|
||||
#define kprintf printf
|
||||
int printf(const char *fmt, ...);
|
||||
int vprintf(const char *fmt, va_list ap);
|
||||
int sprintf(char *buf, const char *cfmt, ...);
|
||||
int vsprintf(char *buf, const char *cfmt, va_list ap);
|
||||
|
||||
/* string and memory manipulation */
|
||||
int memcmp(const void *cs, const void *ct, size_t count);
|
||||
void *memcpy(void *dest, const void *src, size_t count);
|
||||
int strncmp(const char *cs, const char *ct, size_t count);
|
||||
int strcmp(const char *cs, const char *ct);
|
||||
char *strcpy(char *dest, const char *src);
|
||||
char *strncpy(char *dest, const char *src, size_t count);
|
||||
void *memset(void *s,int c, size_t count);
|
||||
size_t strnlen(const char *s, size_t count);
|
||||
size_t strlen(const char *s);
|
||||
char *strchr(const char *s, int c);
|
||||
char *strstr(const char *s1, const char *s2);
|
||||
|
||||
|
||||
/* dlmalloc functions */
|
||||
struct mallinfo {
|
||||
int arena; /* non-mmapped space allocated from system */
|
||||
int ordblks; /* number of free chunks */
|
||||
int smblks; /* number of fastbin blocks */
|
||||
int hblks; /* number of mmapped regions */
|
||||
int hblkhd; /* space in mmapped regions */
|
||||
int usmblks; /* maximum total allocated space */
|
||||
int fsmblks; /* space available in freed fastbin blocks */
|
||||
int uordblks; /* total allocated space */
|
||||
int fordblks; /* total free space */
|
||||
int keepcost; /* top-most, releasable (via malloc_trim) space */
|
||||
};
|
||||
|
||||
void *malloc(size_t n);
|
||||
void *calloc(size_t n_elements, size_t element_size);
|
||||
void free(void* p);
|
||||
void *realloc(void* p, size_t n);
|
||||
void *memalign(size_t alignment, size_t n);
|
||||
void *valloc(size_t n);
|
||||
struct mallinfo mallinfo();
|
||||
int mallopt(int parameter_number, int parameter_value);
|
||||
|
||||
void **independent_calloc(size_t n_elements, size_t size, void* chunks[]);
|
||||
void **independent_comalloc(size_t n_elements, size_t sizes[], void* chunks[]);
|
||||
void *pvalloc(size_t n);
|
||||
void cfree(void* p);
|
||||
int malloc_trim(size_t pad);
|
||||
size_t malloc_usable_size(void* p);
|
||||
void malloc_stats();
|
||||
|
||||
|
||||
#endif /* _LIB_H_ */
|
||||
@@ -0,0 +1,164 @@
|
||||
#ifndef _LINUX_LIST_H
|
||||
#define _LINUX_LIST_H
|
||||
|
||||
#define ASSERT(x) ((void)0)
|
||||
|
||||
/*
|
||||
* Simple doubly linked list implementation.
|
||||
*
|
||||
* Some of the internal functions ("__xxx") are useful when
|
||||
* manipulating whole lists rather than single entries, as
|
||||
* sometimes we already know the next/prev entries and we can
|
||||
* generate better code by using them directly rather than
|
||||
* using the generic single-entry routines.
|
||||
*/
|
||||
|
||||
struct list_head {
|
||||
struct list_head *next, *prev;
|
||||
};
|
||||
|
||||
#define LIST_HEAD_INIT(name) { &(name), &(name) }
|
||||
|
||||
#define LIST_HEAD(name) \
|
||||
struct list_head name = LIST_HEAD_INIT(name)
|
||||
|
||||
#define INIT_LIST_HEAD(ptr) do { \
|
||||
(ptr)->next = (ptr); (ptr)->prev = (ptr); \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* Insert a new entry between two known consecutive entries.
|
||||
*
|
||||
* This is only for internal list manipulation where we know
|
||||
* the prev/next entries already!
|
||||
*/
|
||||
static __inline__ void __list_add(struct list_head * new,
|
||||
struct list_head * prev,
|
||||
struct list_head * next)
|
||||
{
|
||||
next->prev = new;
|
||||
new->next = next;
|
||||
new->prev = prev;
|
||||
prev->next = new;
|
||||
}
|
||||
|
||||
/**
|
||||
* list_add - add a new entry
|
||||
* @new: new entry to be added
|
||||
* @head: list head to add it after
|
||||
*
|
||||
* Insert a new entry after the specified head.
|
||||
* This is good for implementing stacks.
|
||||
*/
|
||||
static __inline__ void list_add(struct list_head *new, struct list_head *head)
|
||||
{
|
||||
__list_add(new, head, head->next);
|
||||
}
|
||||
|
||||
/**
|
||||
* list_add_tail - add a new entry
|
||||
* @new: new entry to be added
|
||||
* @head: list head to add it before
|
||||
*
|
||||
* Insert a new entry before the specified head.
|
||||
* This is useful for implementing queues.
|
||||
*/
|
||||
static __inline__ void list_add_tail(struct list_head *new, struct list_head *head)
|
||||
{
|
||||
__list_add(new, head->prev, head);
|
||||
}
|
||||
|
||||
/*
|
||||
* Delete a list entry by making the prev/next entries
|
||||
* point to each other.
|
||||
*
|
||||
* This is only for internal list manipulation where we know
|
||||
* the prev/next entries already!
|
||||
*/
|
||||
static __inline__ void __list_del(struct list_head * prev,
|
||||
struct list_head * next)
|
||||
{
|
||||
next->prev = prev;
|
||||
prev->next = next;
|
||||
}
|
||||
|
||||
/**
|
||||
* list_del - deletes entry from list.
|
||||
* @entry: the element to delete from the list.
|
||||
* Note: list_empty on entry does not return true after this, the entry is in an undefined state.
|
||||
*/
|
||||
static __inline__ void list_del(struct list_head *entry)
|
||||
{
|
||||
ASSERT(entry->next->prev == entry);
|
||||
ASSERT(entry->prev->next == entry);
|
||||
__list_del(entry->prev, entry->next);
|
||||
}
|
||||
|
||||
/**
|
||||
* list_del_init - deletes entry from list and reinitialize it.
|
||||
* @entry: the element to delete from the list.
|
||||
*/
|
||||
static __inline__ void list_del_init(struct list_head *entry)
|
||||
{
|
||||
__list_del(entry->prev, entry->next);
|
||||
INIT_LIST_HEAD(entry);
|
||||
}
|
||||
|
||||
/**
|
||||
* list_empty - tests whether a list is empty
|
||||
* @head: the list to test.
|
||||
*/
|
||||
static __inline__ int list_empty(struct list_head *head)
|
||||
{
|
||||
return head->next == head;
|
||||
}
|
||||
|
||||
/**
|
||||
* list_splice - join two lists
|
||||
* @list: the new list to add.
|
||||
* @head: the place to add it in the first list.
|
||||
*/
|
||||
static __inline__ void list_splice(struct list_head *list, struct list_head *head)
|
||||
{
|
||||
struct list_head *first = list->next;
|
||||
|
||||
if (first != list) {
|
||||
struct list_head *last = list->prev;
|
||||
struct list_head *at = head->next;
|
||||
|
||||
first->prev = head;
|
||||
head->next = first;
|
||||
|
||||
last->next = at;
|
||||
at->prev = last;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* list_entry - get the struct for this entry
|
||||
* @ptr: the &struct list_head pointer.
|
||||
* @type: the type of the struct this is embedded in.
|
||||
* @member: the name of the list_struct within the struct.
|
||||
*/
|
||||
#define list_entry(ptr, type, member) \
|
||||
((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member)))
|
||||
|
||||
/**
|
||||
* list_for_each - iterate over a list
|
||||
* @pos: the &struct list_head to use as a loop counter.
|
||||
* @head: the head for your list.
|
||||
*/
|
||||
#define list_for_each(pos, head) \
|
||||
for (pos = (head)->next; pos != (head); pos = pos->next)
|
||||
|
||||
/**
|
||||
* list_for_each_safe - iterate over a list safe against removal of list entry
|
||||
* @pos: the &struct list_head to use as a loop counter.
|
||||
* @n: another &struct list_head to use as temporary storage
|
||||
* @head: the head for your list.
|
||||
*/
|
||||
#define list_for_each_safe(pos, n, head) \
|
||||
for (pos = (head)->next, n = pos->next; pos != (head); \
|
||||
pos = n, n = pos->next)
|
||||
|
||||
#endif
|
||||
+107
@@ -0,0 +1,107 @@
|
||||
/* -*- Mode:C; c-basic-offset:4; tab-width:4 -*-
|
||||
****************************************************************************
|
||||
* (C) 2003 - Rolf Neugebauer - Intel Research Cambridge
|
||||
****************************************************************************
|
||||
*
|
||||
* File: mm.h
|
||||
* Author: Rolf Neugebauer (neugebar@dcs.gla.ac.uk)
|
||||
* Changes:
|
||||
*
|
||||
* Date: Aug 2003
|
||||
*
|
||||
* Environment:
|
||||
* Description:
|
||||
*
|
||||
****************************************************************************
|
||||
* $Id: h-insert.h,v 1.4 2002/11/08 16:03:55 rn Exp $
|
||||
****************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef _MM_H_
|
||||
#define _MM_H_
|
||||
|
||||
/* PAGE_SHIFT determines the page size */
|
||||
#define PAGE_SHIFT 12
|
||||
#define PAGE_SIZE (1UL << PAGE_SHIFT)
|
||||
#define PAGE_MASK (~(PAGE_SIZE-1))
|
||||
|
||||
|
||||
#define PFN_UP(x) (((x) + PAGE_SIZE-1) >> PAGE_SHIFT)
|
||||
#define PFN_DOWN(x) ((x) >> PAGE_SHIFT)
|
||||
#define PFN_PHYS(x) ((x) << PAGE_SHIFT)
|
||||
|
||||
|
||||
/* to align the pointer to the (next) page boundary */
|
||||
#define PAGE_ALIGN(addr) (((addr)+PAGE_SIZE-1)&PAGE_MASK)
|
||||
|
||||
|
||||
extern unsigned long *phys_to_machine_mapping;
|
||||
#define pfn_to_mfn(_pfn) (phys_to_machine_mapping[(_pfn)])
|
||||
#define mfn_to_pfn(_mfn) (machine_to_phys_mapping[(_mfn)])
|
||||
static inline unsigned long phys_to_machine(unsigned long phys)
|
||||
{
|
||||
unsigned long machine = pfn_to_mfn(phys >> PAGE_SHIFT);
|
||||
machine = (machine << PAGE_SHIFT) | (phys & ~PAGE_MASK);
|
||||
return machine;
|
||||
}
|
||||
static inline unsigned long machine_to_phys(unsigned long machine)
|
||||
{
|
||||
unsigned long phys = mfn_to_pfn(machine >> PAGE_SHIFT);
|
||||
phys = (phys << PAGE_SHIFT) | (machine & ~PAGE_MASK);
|
||||
return phys;
|
||||
}
|
||||
|
||||
/* VIRT <-> MACHINE conversion */
|
||||
#define virt_to_machine(_a) (phys_to_machine(__pa(_a)))
|
||||
#define machine_to_virt(_m) (__va(machine_to_phys(_m)))
|
||||
|
||||
/*
|
||||
* This handles the memory map.. We could make this a config
|
||||
* option, but too many people screw it up, and too few need
|
||||
* it.
|
||||
*
|
||||
* A __PAGE_OFFSET of 0xC0000000 means that the kernel has
|
||||
* a virtual address space of one gigabyte, which limits the
|
||||
* amount of physical memory you can use to about 950MB.
|
||||
*
|
||||
* If you want more physical memory than this then see the CONFIG_HIGHMEM4G
|
||||
* and CONFIG_HIGHMEM64G options in the kernel configuration.
|
||||
*/
|
||||
|
||||
#define __PAGE_OFFSET (0xC0000000)
|
||||
|
||||
#define PAGE_OFFSET ((unsigned long)__PAGE_OFFSET)
|
||||
#define __pa(x) ((unsigned long)(x)-PAGE_OFFSET)
|
||||
#define __va(x) ((void *)((unsigned long)(x)+PAGE_OFFSET))
|
||||
#define virt_to_page(kaddr) (mem_map + (__pa(kaddr) >> PAGE_SHIFT))
|
||||
#define VALID_PAGE(page) ((page - mem_map) < max_mapnr)
|
||||
|
||||
#define VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | VM_EXEC | \
|
||||
VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
|
||||
|
||||
|
||||
/* prototypes */
|
||||
void init_mm();
|
||||
void release_bytes_to_allocator(unsigned long min, unsigned long max);
|
||||
unsigned long __get_free_pages(int order);
|
||||
void __free_pages(unsigned long p, int order);
|
||||
#define get_free_pages(_o) (__get_free_pages(_o))
|
||||
#define get_free_page() (__get_free_pages(0))
|
||||
#define free_pages(_p,_o) (__free_pages(_p,_o))
|
||||
#define free_page(_p) (__free_pages(_p,0))
|
||||
|
||||
static __inline__ int get_order(unsigned long size)
|
||||
{
|
||||
int order;
|
||||
|
||||
size = (size-1) >> (PAGE_SHIFT-1);
|
||||
order = -1;
|
||||
do {
|
||||
size >>= 1;
|
||||
order++;
|
||||
} while (size);
|
||||
return order;
|
||||
}
|
||||
|
||||
|
||||
#endif /* _MM_H_ */
|
||||
+270
@@ -0,0 +1,270 @@
|
||||
/******************************************************************************
|
||||
* os.h
|
||||
*
|
||||
* random collection of macros and definition
|
||||
*/
|
||||
|
||||
#ifndef _OS_H_
|
||||
#define _OS_H_
|
||||
|
||||
|
||||
#define NULL 0
|
||||
|
||||
/*
|
||||
* These are the segment descriptors provided for us by the hypervisor.
|
||||
* For now, these are hardwired -- guest OSes cannot update the GDT
|
||||
* or LDT.
|
||||
*
|
||||
* It shouldn't be hard to support descriptor-table frobbing -- let me
|
||||
* know if the BSD or XP ports require flexibility here.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* these are also defined in hypervisor-if.h but can't be pulled in as
|
||||
* they are used in start of day assembly. Need to clean up the .h files
|
||||
* a bit more...
|
||||
*/
|
||||
|
||||
#ifndef FLAT_RING1_CS
|
||||
#define FLAT_RING1_CS 0x0819
|
||||
#define FLAT_RING1_DS 0x0821
|
||||
#define FLAT_RING3_CS 0x082b
|
||||
#define FLAT_RING3_DS 0x0833
|
||||
#endif
|
||||
|
||||
#define __KERNEL_CS FLAT_RING1_CS
|
||||
#define __KERNEL_DS FLAT_RING1_DS
|
||||
|
||||
/* Everything below this point is not included by assembler (.S) files. */
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
#include <types.h>
|
||||
#include <hypervisor-ifs/hypervisor-if.h>
|
||||
|
||||
|
||||
/* this struct defines the way the registers are stored on the
|
||||
stack during an exception or interrupt. */
|
||||
struct pt_regs {
|
||||
long ebx;
|
||||
long ecx;
|
||||
long edx;
|
||||
long esi;
|
||||
long edi;
|
||||
long ebp;
|
||||
long eax;
|
||||
int xds;
|
||||
int xes;
|
||||
long orig_eax;
|
||||
long eip;
|
||||
int xcs;
|
||||
long eflags;
|
||||
long esp;
|
||||
int xss;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* STI/CLI equivalents. These basically set and clear the virtual
|
||||
* event_enable flag in teh shared_info structure. Note that when
|
||||
* the enable bit is set, there may be pending events to be handled.
|
||||
* We may therefore call into do_hypervisor_callback() directly.
|
||||
*/
|
||||
#define unlikely(x) __builtin_expect((x),0)
|
||||
#define __save_flags(x) \
|
||||
do { \
|
||||
(x) = test_bit(EVENTS_MASTER_ENABLE_BIT, \
|
||||
&HYPERVISOR_shared_info->events_mask); \
|
||||
barrier(); \
|
||||
} while (0)
|
||||
|
||||
#define __restore_flags(x) \
|
||||
do { \
|
||||
shared_info_t *_shared = HYPERVISOR_shared_info; \
|
||||
if (x) set_bit(EVENTS_MASTER_ENABLE_BIT, &_shared->events_mask); \
|
||||
barrier(); \
|
||||
if ( unlikely(_shared->events) && (x) ) do_hypervisor_callback(NULL); \
|
||||
} while (0)
|
||||
|
||||
#define __cli() \
|
||||
do { \
|
||||
clear_bit(EVENTS_MASTER_ENABLE_BIT, &HYPERVISOR_shared_info->events_mask);\
|
||||
barrier(); \
|
||||
} while (0)
|
||||
|
||||
#define __sti() \
|
||||
do { \
|
||||
shared_info_t *_shared = HYPERVISOR_shared_info; \
|
||||
set_bit(EVENTS_MASTER_ENABLE_BIT, &_shared->events_mask); \
|
||||
barrier(); \
|
||||
if ( unlikely(_shared->events) ) do_hypervisor_callback(NULL); \
|
||||
} while (0)
|
||||
#define cli() __cli()
|
||||
#define sti() __sti()
|
||||
#define save_flags(x) __save_flags(x)
|
||||
#define restore_flags(x) __restore_flags(x)
|
||||
#define save_and_cli(x) __save_and_cli(x)
|
||||
#define save_and_sti(x) __save_and_sti(x)
|
||||
|
||||
|
||||
|
||||
/* This is a barrier for the compiler only, NOT the processor! */
|
||||
#define barrier() __asm__ __volatile__("": : :"memory")
|
||||
|
||||
#define LOCK_PREFIX ""
|
||||
#define LOCK ""
|
||||
#define ADDR (*(volatile long *) addr)
|
||||
/*
|
||||
* Make sure gcc doesn't try to be clever and move things around
|
||||
* on us. We need to use _exactly_ the address the user gave us,
|
||||
* not some alias that contains the same information.
|
||||
*/
|
||||
typedef struct { volatile int counter; } atomic_t;
|
||||
|
||||
|
||||
/*
|
||||
* This XCHG macro is straight from Linux. It is gross.
|
||||
*/
|
||||
#define xchg(ptr,v) \
|
||||
((__typeof__(*(ptr)))__xchg((unsigned long)(v),(ptr),sizeof(*(ptr))))
|
||||
struct __xchg_dummy { unsigned long a[100]; };
|
||||
#define __xg(x) ((struct __xchg_dummy *)(x))
|
||||
static inline unsigned long __xchg(unsigned long x, volatile void * ptr,
|
||||
int size)
|
||||
{
|
||||
switch (size) {
|
||||
case 1:
|
||||
__asm__ __volatile__("xchgb %b0,%1"
|
||||
:"=q" (x)
|
||||
:"m" (*__xg(ptr)), "0" (x)
|
||||
:"memory");
|
||||
break;
|
||||
case 2:
|
||||
__asm__ __volatile__("xchgw %w0,%1"
|
||||
:"=r" (x)
|
||||
:"m" (*__xg(ptr)), "0" (x)
|
||||
:"memory");
|
||||
break;
|
||||
case 4:
|
||||
__asm__ __volatile__("xchgl %0,%1"
|
||||
:"=r" (x)
|
||||
:"m" (*__xg(ptr)), "0" (x)
|
||||
:"memory");
|
||||
break;
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
/**
|
||||
* test_and_clear_bit - Clear a bit and return its old value
|
||||
* @nr: Bit to set
|
||||
* @addr: Address to count from
|
||||
*
|
||||
* This operation is atomic and cannot be reordered.
|
||||
* It also implies a memory barrier.
|
||||
*/
|
||||
static __inline__ int test_and_clear_bit(int nr, volatile void * addr)
|
||||
{
|
||||
int oldbit;
|
||||
|
||||
__asm__ __volatile__( LOCK_PREFIX
|
||||
"btrl %2,%1\n\tsbbl %0,%0"
|
||||
:"=r" (oldbit),"=m" (ADDR)
|
||||
:"Ir" (nr) : "memory");
|
||||
return oldbit;
|
||||
}
|
||||
|
||||
static __inline__ int constant_test_bit(int nr, const volatile void * addr)
|
||||
{
|
||||
return ((1UL << (nr & 31)) & (((const volatile unsigned int *) addr)[nr >> 5])) != 0;
|
||||
}
|
||||
|
||||
static __inline__ int variable_test_bit(int nr, volatile void * addr)
|
||||
{
|
||||
int oldbit;
|
||||
|
||||
__asm__ __volatile__(
|
||||
"btl %2,%1\n\tsbbl %0,%0"
|
||||
:"=r" (oldbit)
|
||||
:"m" (ADDR),"Ir" (nr));
|
||||
return oldbit;
|
||||
}
|
||||
|
||||
#define test_bit(nr,addr) \
|
||||
(__builtin_constant_p(nr) ? \
|
||||
constant_test_bit((nr),(addr)) : \
|
||||
variable_test_bit((nr),(addr)))
|
||||
|
||||
|
||||
/**
|
||||
* set_bit - Atomically set a bit in memory
|
||||
* @nr: the bit to set
|
||||
* @addr: the address to start counting from
|
||||
*
|
||||
* This function is atomic and may not be reordered. See __set_bit()
|
||||
* if you do not require the atomic guarantees.
|
||||
* Note that @nr may be almost arbitrarily large; this function is not
|
||||
* restricted to acting on a single-word quantity.
|
||||
*/
|
||||
static __inline__ void set_bit(int nr, volatile void * addr)
|
||||
{
|
||||
__asm__ __volatile__( LOCK_PREFIX
|
||||
"btsl %1,%0"
|
||||
:"=m" (ADDR)
|
||||
:"Ir" (nr));
|
||||
}
|
||||
|
||||
/**
|
||||
* clear_bit - Clears a bit in memory
|
||||
* @nr: Bit to clear
|
||||
* @addr: Address to start counting from
|
||||
*
|
||||
* clear_bit() is atomic and may not be reordered. However, it does
|
||||
* not contain a memory barrier, so if it is used for locking purposes,
|
||||
* you should call smp_mb__before_clear_bit() and/or smp_mb__after_clear_bit()
|
||||
* in order to ensure changes are visible on other processors.
|
||||
*/
|
||||
static __inline__ void clear_bit(int nr, volatile void * addr)
|
||||
{
|
||||
__asm__ __volatile__( LOCK_PREFIX
|
||||
"btrl %1,%0"
|
||||
:"=m" (ADDR)
|
||||
:"Ir" (nr));
|
||||
}
|
||||
|
||||
/**
|
||||
* atomic_inc - increment atomic variable
|
||||
* @v: pointer of type atomic_t
|
||||
*
|
||||
* Atomically increments @v by 1. Note that the guaranteed
|
||||
* useful range of an atomic_t is only 24 bits.
|
||||
*/
|
||||
static __inline__ void atomic_inc(atomic_t *v)
|
||||
{
|
||||
__asm__ __volatile__(
|
||||
LOCK "incl %0"
|
||||
:"=m" (v->counter)
|
||||
:"m" (v->counter));
|
||||
}
|
||||
|
||||
|
||||
/* useful hypervisor macros */
|
||||
|
||||
struct desc_struct {
|
||||
unsigned long a,b;
|
||||
};
|
||||
extern struct desc_struct default_ldt[];
|
||||
|
||||
#define asmlinkage __attribute__((regparm(0)))
|
||||
|
||||
/*
|
||||
* some random linux macros
|
||||
*/
|
||||
|
||||
#define rdtscll(val) \
|
||||
__asm__ __volatile__("rdtsc" : "=A" (val))
|
||||
|
||||
|
||||
#endif /* !__ASSEMBLY__ */
|
||||
|
||||
#endif /* _OS_H_ */
|
||||
@@ -0,0 +1,59 @@
|
||||
/* -*- Mode:C; c-basic-offset:4; tab-width:4 -*-
|
||||
****************************************************************************
|
||||
* (C) 2003 - Rolf Neugebauer - Intel Research Cambridge
|
||||
****************************************************************************
|
||||
*
|
||||
* File: time.h
|
||||
* Author: Rolf Neugebauer (neugebar@dcs.gla.ac.uk)
|
||||
* Changes:
|
||||
*
|
||||
* Date: Jul 2003
|
||||
*
|
||||
* Environment: Xen Minimal OS
|
||||
* Description: Time and timer functions
|
||||
*
|
||||
****************************************************************************
|
||||
* $Id: h-insert.h,v 1.4 2002/11/08 16:03:55 rn Exp $
|
||||
****************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef _TIME_H_
|
||||
#define _TIME_H_
|
||||
|
||||
#include <list.h>
|
||||
|
||||
/*
|
||||
* System Time
|
||||
* 64 bit value containing the nanoseconds elapsed since boot time.
|
||||
* This value is adjusted by frequency drift.
|
||||
* NOW() returns the current time.
|
||||
* The other macros are for convenience to approximate short intervals
|
||||
* of real time into system time
|
||||
*/
|
||||
typedef s64 s_time_t;
|
||||
#define NOW() ((s_time_t)get_s_time())
|
||||
#define SECONDS(_s) (((s_time_t)(_s)) * 1000000000UL )
|
||||
#define TENTHS(_ts) (((s_time_t)(_ts)) * 100000000UL )
|
||||
#define HUNDREDTHS(_hs) (((s_time_t)(_hs)) * 10000000UL )
|
||||
#define MILLISECS(_ms) (((s_time_t)(_ms)) * 1000000UL )
|
||||
#define MICROSECS(_us) (((s_time_t)(_us)) * 1000UL )
|
||||
#define Time_Max ((s_time_t) 0x7fffffffffffffffLL)
|
||||
#define FOREVER Time_Max
|
||||
|
||||
|
||||
/* wall clock time */
|
||||
typedef long time_t;
|
||||
typedef long suseconds_t;
|
||||
struct timeval {
|
||||
time_t tv_sec; /* seconds */
|
||||
suseconds_t tv_usec; /* microseconds */
|
||||
};
|
||||
|
||||
|
||||
/* prototypes */
|
||||
void init_time(void);
|
||||
s_time_t get_s_time(void);
|
||||
s_time_t get_v_time(void);
|
||||
void gettimeofday(struct timeval *tv);
|
||||
|
||||
#endif /* _TIME_H_ */
|
||||
@@ -0,0 +1,41 @@
|
||||
/* -*- Mode:C; c-basic-offset:4; tab-width:4 -*-
|
||||
****************************************************************************
|
||||
* (C) 2003 - Rolf Neugebauer - Intel Research Cambridge
|
||||
****************************************************************************
|
||||
*
|
||||
* File: types.h
|
||||
* Author: Rolf Neugebauer (neugebar@dcs.gla.ac.uk)
|
||||
* Changes:
|
||||
*
|
||||
* Date: May 2003
|
||||
*
|
||||
* Environment: Xeno Minimal OS
|
||||
* Description: a random collection of type definitions
|
||||
*
|
||||
****************************************************************************
|
||||
* $Id: h-insert.h,v 1.4 2002/11/08 16:03:55 rn Exp $
|
||||
****************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef _TYPES_H_
|
||||
#define _TYPES_H_
|
||||
|
||||
typedef signed char s8;
|
||||
typedef unsigned char u8;
|
||||
typedef signed short s16;
|
||||
typedef unsigned short u16;
|
||||
typedef signed int s32;
|
||||
typedef unsigned int u32;
|
||||
typedef signed long long s64;
|
||||
typedef unsigned long long u64;
|
||||
|
||||
typedef unsigned int size_t;
|
||||
|
||||
/* FreeBSD compat types */
|
||||
typedef unsigned char u_char;
|
||||
typedef unsigned int u_int;
|
||||
typedef unsigned long u_long;
|
||||
typedef long long quad_t;
|
||||
typedef unsigned long long u_quad_t;
|
||||
typedef unsigned int uintptr_t;
|
||||
#endif /* _TYPES_H_ */
|
||||
@@ -0,0 +1,46 @@
|
||||
#include <os.h>
|
||||
|
||||
/* Offsets in start_info structure */
|
||||
#define SHARED_INFO 4
|
||||
#define MOD_START 12
|
||||
#define MOD_LEN 16
|
||||
|
||||
#define ENTRY(X) .globl X ; X :
|
||||
|
||||
.globl _start
|
||||
_start:
|
||||
cld
|
||||
|
||||
lss stack_start,%esp
|
||||
|
||||
/* Copy any module somewhere safe before it's clobbered by BSS. */
|
||||
mov MOD_LEN(%esi),%ecx
|
||||
shr $2,%ecx
|
||||
jz 2f /* bail from copy loop if no module */
|
||||
|
||||
mov $_end,%edi
|
||||
add MOD_LEN(%esi),%edi
|
||||
mov MOD_START(%esi),%eax
|
||||
add MOD_LEN(%esi),%eax
|
||||
1: sub $4,%eax
|
||||
sub $4,%edi
|
||||
mov (%eax),%ebx
|
||||
mov %ebx,(%edi)
|
||||
loop 1b
|
||||
mov %edi,MOD_START(%esi)
|
||||
|
||||
/* Clear BSS first so that there are no surprises... */
|
||||
2: xorl %eax,%eax
|
||||
movl $__bss_start,%edi
|
||||
movl $_end,%ecx
|
||||
subl %edi,%ecx
|
||||
rep stosb
|
||||
|
||||
push %esi
|
||||
call start_kernel
|
||||
|
||||
|
||||
stack_start:
|
||||
.long stack+8192, __KERNEL_DS
|
||||
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
/******************************************************************************
|
||||
* hypervisor.c
|
||||
*
|
||||
* Communication to/from hypervisor.
|
||||
*
|
||||
* Copied from XenoLinux and adjusted by Rolf.Neugebauer@intel.com
|
||||
*
|
||||
* Copyright (c) 2002, K A Fraser
|
||||
*/
|
||||
|
||||
#include <os.h>
|
||||
#include <hypervisor.h>
|
||||
|
||||
static unsigned long event_mask = 0;
|
||||
static unsigned long ev_err_count;
|
||||
|
||||
void do_hypervisor_callback(struct pt_regs *regs)
|
||||
{
|
||||
unsigned long events, flags;
|
||||
shared_info_t *shared = HYPERVISOR_shared_info;
|
||||
|
||||
do {
|
||||
/* Specialised local_irq_save(). */
|
||||
flags = test_and_clear_bit(EVENTS_MASTER_ENABLE_BIT,
|
||||
&shared->events_mask);
|
||||
barrier();
|
||||
|
||||
events = xchg(&shared->events, 0);
|
||||
events &= event_mask;
|
||||
|
||||
/* 'events' now contains some pending events to handle. */
|
||||
__asm__ __volatile__ (
|
||||
" push %1 ;"
|
||||
" sub $4,%%esp ;"
|
||||
" jmp 2f ;"
|
||||
"1: btrl %%eax,%0 ;" /* clear bit */
|
||||
" mov %%eax,(%%esp) ;"
|
||||
" call do_event ;" /* do_event(event) */
|
||||
"2: bsfl %0,%%eax ;" /* %eax == bit # */
|
||||
" jnz 1b ;"
|
||||
" add $8,%%esp ;"
|
||||
/* we use %ebx because it is callee-saved */
|
||||
: : "b" (events), "r" (regs)
|
||||
/* clobbered by callback function calls */
|
||||
: "eax", "ecx", "edx", "memory" );
|
||||
|
||||
/* Specialised local_irq_restore(). */
|
||||
if ( flags ) set_bit(EVENTS_MASTER_ENABLE_BIT, &shared->events_mask);
|
||||
barrier();
|
||||
}
|
||||
while ( shared->events );
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Define interface to generic handling in irq.c
|
||||
*/
|
||||
|
||||
void enable_hypervisor_event(unsigned int ev)
|
||||
{
|
||||
set_bit(ev, &event_mask);
|
||||
set_bit(ev, &HYPERVISOR_shared_info->events_mask);
|
||||
if ( test_bit(EVENTS_MASTER_ENABLE_BIT,
|
||||
&HYPERVISOR_shared_info->events_mask) )
|
||||
do_hypervisor_callback(NULL);
|
||||
}
|
||||
|
||||
void disable_hypervisor_event(unsigned int ev)
|
||||
{
|
||||
clear_bit(ev, &event_mask);
|
||||
clear_bit(ev, &HYPERVISOR_shared_info->events_mask);
|
||||
}
|
||||
|
||||
void ack_hypervisor_event(unsigned int ev)
|
||||
{
|
||||
if ( !(event_mask & (1<<ev)) )
|
||||
{
|
||||
//printk("Unexpected hypervisor event %d\n", ev);
|
||||
atomic_inc((atomic_t *)&ev_err_count);
|
||||
}
|
||||
set_bit(ev, &HYPERVISOR_shared_info->events_mask);
|
||||
}
|
||||
@@ -0,0 +1,115 @@
|
||||
/******************************************************************************
|
||||
* kernel.c
|
||||
*
|
||||
* Assorted crap goes here, including the initial C entry point, jumped at
|
||||
* from head.S.
|
||||
*/
|
||||
|
||||
#include <os.h>
|
||||
#include <hypervisor.h>
|
||||
#include <mm.h>
|
||||
#include <events.h>
|
||||
#include <time.h>
|
||||
#include <types.h>
|
||||
#include <lib.h>
|
||||
|
||||
/*
|
||||
* Shared page for communicating with the hypervisor.
|
||||
* Events flags go here, for example.
|
||||
*/
|
||||
shared_info_t *HYPERVISOR_shared_info;
|
||||
|
||||
/*
|
||||
* This structure contains start-of-day info, such as pagetable base pointer,
|
||||
* address of the shared_info structure, and things like that.
|
||||
*/
|
||||
union start_info_union start_info_union;
|
||||
|
||||
/*
|
||||
* Just allocate the kernel stack here. SS:ESP is set up to point here
|
||||
* in head.S.
|
||||
*/
|
||||
char stack[8192];
|
||||
|
||||
|
||||
/* Assembler interface fns in entry.S. */
|
||||
void hypervisor_callback(void);
|
||||
void failsafe_callback(void);
|
||||
|
||||
/* default exit event handler */
|
||||
static void exit_handler(int ev, struct pt_regs *regs);
|
||||
|
||||
/*
|
||||
* INITIAL C ENTRY POINT.
|
||||
*/
|
||||
void start_kernel(start_info_t *si)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* Copy the start_info struct to a globally-accessible area. */
|
||||
memcpy(&start_info, si, sizeof(*si));
|
||||
|
||||
/* Grab the shared_info pointer and put it in a safe place. */
|
||||
HYPERVISOR_shared_info = start_info.shared_info;
|
||||
|
||||
/* Set up event and failsafe callback addresses. */
|
||||
HYPERVISOR_set_callbacks(
|
||||
__KERNEL_CS, (unsigned long)hypervisor_callback,
|
||||
__KERNEL_CS, (unsigned long)failsafe_callback);
|
||||
|
||||
|
||||
/* ENABLE EVENT DELIVERY. This is disabled at start of day. */
|
||||
__sti();
|
||||
|
||||
/* print out some useful information */
|
||||
printk("Xeno Minimal OS!\n");
|
||||
printk("start_info: %p\n", si);
|
||||
printk(" nr_pages: %lu", si->nr_pages);
|
||||
printk(" shared_inf: %p\n", si->shared_info);
|
||||
printk(" pt_base: %p", (void *)si->pt_base);
|
||||
printk(" mod_start: 0x%lx\n", si->mod_start);
|
||||
printk(" mod_len: %lu\n", si->mod_len);
|
||||
printk(" net_rings: ");
|
||||
for (i = 0; i < MAX_DOMAIN_VIFS; i++) {
|
||||
printk(" %lx", si->net_rings[i]);
|
||||
}; printk("\n");
|
||||
printk(" blk_ring: 0x%lx\n", si->blk_ring);
|
||||
printk(" dom_id: %d\n", si->dom_id);
|
||||
printk(" flags: 0x%lx\n", si->flags);
|
||||
printk(" cmd_line: %s\n", si->cmd_line ? (const char *)si->cmd_line : "NULL");
|
||||
|
||||
/* init memory management */
|
||||
init_mm();
|
||||
|
||||
/* set up events */
|
||||
init_events();
|
||||
|
||||
/* install some handlers */
|
||||
add_ev_action(EV_DIE, &exit_handler);
|
||||
enable_ev_action(EV_DIE);
|
||||
enable_hypervisor_event(EV_DIE);
|
||||
|
||||
/* init time and timers */
|
||||
init_time();
|
||||
|
||||
/* do nothing */
|
||||
for ( ; ; ) HYPERVISOR_yield();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* do_exit: This is called whenever an IRET fails in entry.S.
|
||||
* This will generally be because an application has got itself into
|
||||
* a really bad state (probably a bad CS or SS). It must be killed.
|
||||
* Of course, minimal OS doesn't have applications :-)
|
||||
*/
|
||||
|
||||
void do_exit(void)
|
||||
{
|
||||
printk("do_exit called!\n");
|
||||
for ( ;; ) ;
|
||||
}
|
||||
static void exit_handler(int ev, struct pt_regs *regs) {
|
||||
do_exit();
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,385 @@
|
||||
/* -*- Mode:C; c-basic-offset:4; tab-width:4 -*-
|
||||
****************************************************************************
|
||||
* (C) 2003 - Rolf Neugebauer - Intel Research Cambridge
|
||||
****************************************************************************
|
||||
*
|
||||
* File: math.c
|
||||
* Author: Rolf Neugebauer (neugebar@dcs.gla.ac.uk)
|
||||
* Changes:
|
||||
*
|
||||
* Date: Aug 2003
|
||||
*
|
||||
* Environment: Xen Minimal OS
|
||||
* Description: Library functions for 64bit arith and other
|
||||
* from freebsd, files in sys/libkern/ (qdivrem.c, etc)
|
||||
*
|
||||
****************************************************************************
|
||||
* $Id: c-insert.c,v 1.7 2002/11/08 16:04:34 rn Exp $
|
||||
****************************************************************************
|
||||
*-
|
||||
* Copyright (c) 1992, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This software was developed by the Computer Systems Engineering group
|
||||
* at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
|
||||
* contributed to Berkeley.
|
||||
*
|
||||
* 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.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
|
||||
*
|
||||
* $FreeBSD: src/sys/libkern/divdi3.c,v 1.6 1999/08/28 00:46:31 peter Exp $
|
||||
*/
|
||||
|
||||
#include <types.h>
|
||||
|
||||
/*
|
||||
* Depending on the desired operation, we view a `long long' (aka quad_t) in
|
||||
* one or more of the following formats.
|
||||
*/
|
||||
union uu {
|
||||
s64 q; /* as a (signed) quad */
|
||||
s64 uq; /* as an unsigned quad */
|
||||
long sl[2]; /* as two signed longs */
|
||||
unsigned long ul[2]; /* as two unsigned longs */
|
||||
};
|
||||
/* XXX RN: Yuck hardcoded endianess :) */
|
||||
#define _QUAD_HIGHWORD 1
|
||||
#define _QUAD_LOWWORD 0
|
||||
/*
|
||||
* Define high and low longwords.
|
||||
*/
|
||||
#define H _QUAD_HIGHWORD
|
||||
#define L _QUAD_LOWWORD
|
||||
|
||||
/*
|
||||
* Total number of bits in a quad_t and in the pieces that make it up.
|
||||
* These are used for shifting, and also below for halfword extraction
|
||||
* and assembly.
|
||||
*/
|
||||
#define CHAR_BIT 8 /* number of bits in a char */
|
||||
#define QUAD_BITS (sizeof(s64) * CHAR_BIT)
|
||||
#define LONG_BITS (sizeof(long) * CHAR_BIT)
|
||||
#define HALF_BITS (sizeof(long) * CHAR_BIT / 2)
|
||||
|
||||
/*
|
||||
* Extract high and low shortwords from longword, and move low shortword of
|
||||
* longword to upper half of long, i.e., produce the upper longword of
|
||||
* ((quad_t)(x) << (number_of_bits_in_long/2)). (`x' must actually be u_long.)
|
||||
*
|
||||
* These are used in the multiply code, to split a longword into upper
|
||||
* and lower halves, and to reassemble a product as a quad_t, shifted left
|
||||
* (sizeof(long)*CHAR_BIT/2).
|
||||
*/
|
||||
#define HHALF(x) ((x) >> HALF_BITS)
|
||||
#define LHALF(x) ((x) & ((1 << HALF_BITS) - 1))
|
||||
#define LHUP(x) ((x) << HALF_BITS)
|
||||
|
||||
/*
|
||||
* Multiprecision divide. This algorithm is from Knuth vol. 2 (2nd ed),
|
||||
* section 4.3.1, pp. 257--259.
|
||||
*/
|
||||
#define B (1 << HALF_BITS) /* digit base */
|
||||
|
||||
/* Combine two `digits' to make a single two-digit number. */
|
||||
#define COMBINE(a, b) (((u_long)(a) << HALF_BITS) | (b))
|
||||
|
||||
/* select a type for digits in base B: use unsigned short if they fit */
|
||||
#if ULONG_MAX == 0xffffffff && USHRT_MAX >= 0xffff
|
||||
typedef unsigned short digit;
|
||||
#else
|
||||
typedef u_long digit;
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* Shift p[0]..p[len] left `sh' bits, ignoring any bits that
|
||||
* `fall out' the left (there never will be any such anyway).
|
||||
* We may assume len >= 0. NOTE THAT THIS WRITES len+1 DIGITS.
|
||||
*/
|
||||
static void
|
||||
shl(register digit *p, register int len, register int sh)
|
||||
{
|
||||
register int i;
|
||||
|
||||
for (i = 0; i < len; i++)
|
||||
p[i] = LHALF(p[i] << sh) | (p[i + 1] >> (HALF_BITS - sh));
|
||||
p[i] = LHALF(p[i] << sh);
|
||||
}
|
||||
|
||||
/*
|
||||
* __qdivrem(u, v, rem) returns u/v and, optionally, sets *rem to u%v.
|
||||
*
|
||||
* We do this in base 2-sup-HALF_BITS, so that all intermediate products
|
||||
* fit within u_long. As a consequence, the maximum length dividend and
|
||||
* divisor are 4 `digits' in this base (they are shorter if they have
|
||||
* leading zeros).
|
||||
*/
|
||||
u64
|
||||
__qdivrem(uq, vq, arq)
|
||||
u64 uq, vq, *arq;
|
||||
{
|
||||
union uu tmp;
|
||||
digit *u, *v, *q;
|
||||
register digit v1, v2;
|
||||
u_long qhat, rhat, t;
|
||||
int m, n, d, j, i;
|
||||
digit uspace[5], vspace[5], qspace[5];
|
||||
|
||||
/*
|
||||
* Take care of special cases: divide by zero, and u < v.
|
||||
*/
|
||||
if (vq == 0) {
|
||||
/* divide by zero. */
|
||||
static volatile const unsigned int zero = 0;
|
||||
|
||||
tmp.ul[H] = tmp.ul[L] = 1 / zero;
|
||||
if (arq)
|
||||
*arq = uq;
|
||||
return (tmp.q);
|
||||
}
|
||||
if (uq < vq) {
|
||||
if (arq)
|
||||
*arq = uq;
|
||||
return (0);
|
||||
}
|
||||
u = &uspace[0];
|
||||
v = &vspace[0];
|
||||
q = &qspace[0];
|
||||
|
||||
/*
|
||||
* Break dividend and divisor into digits in base B, then
|
||||
* count leading zeros to determine m and n. When done, we
|
||||
* will have:
|
||||
* u = (u[1]u[2]...u[m+n]) sub B
|
||||
* v = (v[1]v[2]...v[n]) sub B
|
||||
* v[1] != 0
|
||||
* 1 < n <= 4 (if n = 1, we use a different division algorithm)
|
||||
* m >= 0 (otherwise u < v, which we already checked)
|
||||
* m + n = 4
|
||||
* and thus
|
||||
* m = 4 - n <= 2
|
||||
*/
|
||||
tmp.uq = uq;
|
||||
u[0] = 0;
|
||||
u[1] = HHALF(tmp.ul[H]);
|
||||
u[2] = LHALF(tmp.ul[H]);
|
||||
u[3] = HHALF(tmp.ul[L]);
|
||||
u[4] = LHALF(tmp.ul[L]);
|
||||
tmp.uq = vq;
|
||||
v[1] = HHALF(tmp.ul[H]);
|
||||
v[2] = LHALF(tmp.ul[H]);
|
||||
v[3] = HHALF(tmp.ul[L]);
|
||||
v[4] = LHALF(tmp.ul[L]);
|
||||
for (n = 4; v[1] == 0; v++) {
|
||||
if (--n == 1) {
|
||||
u_long rbj; /* r*B+u[j] (not root boy jim) */
|
||||
digit q1, q2, q3, q4;
|
||||
|
||||
/*
|
||||
* Change of plan, per exercise 16.
|
||||
* r = 0;
|
||||
* for j = 1..4:
|
||||
* q[j] = floor((r*B + u[j]) / v),
|
||||
* r = (r*B + u[j]) % v;
|
||||
* We unroll this completely here.
|
||||
*/
|
||||
t = v[2]; /* nonzero, by definition */
|
||||
q1 = u[1] / t;
|
||||
rbj = COMBINE(u[1] % t, u[2]);
|
||||
q2 = rbj / t;
|
||||
rbj = COMBINE(rbj % t, u[3]);
|
||||
q3 = rbj / t;
|
||||
rbj = COMBINE(rbj % t, u[4]);
|
||||
q4 = rbj / t;
|
||||
if (arq)
|
||||
*arq = rbj % t;
|
||||
tmp.ul[H] = COMBINE(q1, q2);
|
||||
tmp.ul[L] = COMBINE(q3, q4);
|
||||
return (tmp.q);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* By adjusting q once we determine m, we can guarantee that
|
||||
* there is a complete four-digit quotient at &qspace[1] when
|
||||
* we finally stop.
|
||||
*/
|
||||
for (m = 4 - n; u[1] == 0; u++)
|
||||
m--;
|
||||
for (i = 4 - m; --i >= 0;)
|
||||
q[i] = 0;
|
||||
q += 4 - m;
|
||||
|
||||
/*
|
||||
* Here we run Program D, translated from MIX to C and acquiring
|
||||
* a few minor changes.
|
||||
*
|
||||
* D1: choose multiplier 1 << d to ensure v[1] >= B/2.
|
||||
*/
|
||||
d = 0;
|
||||
for (t = v[1]; t < B / 2; t <<= 1)
|
||||
d++;
|
||||
if (d > 0) {
|
||||
shl(&u[0], m + n, d); /* u <<= d */
|
||||
shl(&v[1], n - 1, d); /* v <<= d */
|
||||
}
|
||||
/*
|
||||
* D2: j = 0.
|
||||
*/
|
||||
j = 0;
|
||||
v1 = v[1]; /* for D3 -- note that v[1..n] are constant */
|
||||
v2 = v[2]; /* for D3 */
|
||||
do {
|
||||
register digit uj0, uj1, uj2;
|
||||
|
||||
/*
|
||||
* D3: Calculate qhat (\^q, in TeX notation).
|
||||
* Let qhat = min((u[j]*B + u[j+1])/v[1], B-1), and
|
||||
* let rhat = (u[j]*B + u[j+1]) mod v[1].
|
||||
* While rhat < B and v[2]*qhat > rhat*B+u[j+2],
|
||||
* decrement qhat and increase rhat correspondingly.
|
||||
* Note that if rhat >= B, v[2]*qhat < rhat*B.
|
||||
*/
|
||||
uj0 = u[j + 0]; /* for D3 only -- note that u[j+...] change */
|
||||
uj1 = u[j + 1]; /* for D3 only */
|
||||
uj2 = u[j + 2]; /* for D3 only */
|
||||
if (uj0 == v1) {
|
||||
qhat = B;
|
||||
rhat = uj1;
|
||||
goto qhat_too_big;
|
||||
} else {
|
||||
u_long nn = COMBINE(uj0, uj1);
|
||||
qhat = nn / v1;
|
||||
rhat = nn % v1;
|
||||
}
|
||||
while (v2 * qhat > COMBINE(rhat, uj2)) {
|
||||
qhat_too_big:
|
||||
qhat--;
|
||||
if ((rhat += v1) >= B)
|
||||
break;
|
||||
}
|
||||
/*
|
||||
* D4: Multiply and subtract.
|
||||
* The variable `t' holds any borrows across the loop.
|
||||
* We split this up so that we do not require v[0] = 0,
|
||||
* and to eliminate a final special case.
|
||||
*/
|
||||
for (t = 0, i = n; i > 0; i--) {
|
||||
t = u[i + j] - v[i] * qhat - t;
|
||||
u[i + j] = LHALF(t);
|
||||
t = (B - HHALF(t)) & (B - 1);
|
||||
}
|
||||
t = u[j] - t;
|
||||
u[j] = LHALF(t);
|
||||
/*
|
||||
* D5: test remainder.
|
||||
* There is a borrow if and only if HHALF(t) is nonzero;
|
||||
* in that (rare) case, qhat was too large (by exactly 1).
|
||||
* Fix it by adding v[1..n] to u[j..j+n].
|
||||
*/
|
||||
if (HHALF(t)) {
|
||||
qhat--;
|
||||
for (t = 0, i = n; i > 0; i--) { /* D6: add back. */
|
||||
t += u[i + j] + v[i];
|
||||
u[i + j] = LHALF(t);
|
||||
t = HHALF(t);
|
||||
}
|
||||
u[j] = LHALF(u[j] + t);
|
||||
}
|
||||
q[j] = qhat;
|
||||
} while (++j <= m); /* D7: loop on j. */
|
||||
|
||||
/*
|
||||
* If caller wants the remainder, we have to calculate it as
|
||||
* u[m..m+n] >> d (this is at most n digits and thus fits in
|
||||
* u[m+1..m+n], but we may need more source digits).
|
||||
*/
|
||||
if (arq) {
|
||||
if (d) {
|
||||
for (i = m + n; i > m; --i)
|
||||
u[i] = (u[i] >> d) |
|
||||
LHALF(u[i - 1] << (HALF_BITS - d));
|
||||
u[i] = 0;
|
||||
}
|
||||
tmp.ul[H] = COMBINE(uspace[1], uspace[2]);
|
||||
tmp.ul[L] = COMBINE(uspace[3], uspace[4]);
|
||||
*arq = tmp.q;
|
||||
}
|
||||
|
||||
tmp.ul[H] = COMBINE(qspace[1], qspace[2]);
|
||||
tmp.ul[L] = COMBINE(qspace[3], qspace[4]);
|
||||
return (tmp.q);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Divide two signed quads.
|
||||
* ??? if -1/2 should produce -1 on this machine, this code is wrong
|
||||
*/
|
||||
s64
|
||||
__divdi3(s64 a, s64 b)
|
||||
{
|
||||
u64 ua, ub, uq;
|
||||
int neg;
|
||||
|
||||
if (a < 0)
|
||||
ua = -(u64)a, neg = 1;
|
||||
else
|
||||
ua = a, neg = 0;
|
||||
if (b < 0)
|
||||
ub = -(u64)b, neg ^= 1;
|
||||
else
|
||||
ub = b;
|
||||
uq = __qdivrem(ua, ub, (u64 *)0);
|
||||
return (neg ? -uq : uq);
|
||||
}
|
||||
|
||||
/*
|
||||
* Divide two unsigned quads.
|
||||
*/
|
||||
u64
|
||||
__udivdi3(a, b)
|
||||
u64 a, b;
|
||||
{
|
||||
return (__qdivrem(a, b, (u64 *)0));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Return remainder after dividing two unsigned quads.
|
||||
*/
|
||||
u_quad_t
|
||||
__umoddi3(a, b)
|
||||
u_quad_t a, b;
|
||||
{
|
||||
u_quad_t r;
|
||||
|
||||
(void)__qdivrem(a, b, &r);
|
||||
return (r);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,470 @@
|
||||
/* -*- Mode:C; c-basic-offset:4; tab-width:4 -*-
|
||||
****************************************************************************
|
||||
* (C) 2003 - Rolf Neugebauer - Intel Research Cambridge
|
||||
****************************************************************************
|
||||
*
|
||||
* File: printf.c
|
||||
* Author: Rolf Neugebauer (neugebar@dcs.gla.ac.uk)
|
||||
* Changes:
|
||||
*
|
||||
* Date: Aug 2003
|
||||
*
|
||||
* Environment: Xen Minimal OS
|
||||
* Description: Library functions for printing
|
||||
* (freebsd port, mainly sys/subr_prf.c)
|
||||
*
|
||||
****************************************************************************
|
||||
* $Id: c-insert.c,v 1.7 2002/11/08 16:04:34 rn Exp $
|
||||
****************************************************************************
|
||||
*
|
||||
*-
|
||||
* Copyright (c) 1992, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This software was developed by the Computer Systems Engineering group
|
||||
* at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
|
||||
* contributed to Berkeley.
|
||||
*
|
||||
* 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.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
|
||||
*
|
||||
* $FreeBSD: src/sys/libkern/divdi3.c,v 1.6 1999/08/28 00:46:31 peter Exp $
|
||||
*/
|
||||
|
||||
#include <os.h>
|
||||
#include <types.h>
|
||||
#include <hypervisor.h>
|
||||
#include <lib.h>
|
||||
|
||||
/****************************************************************************
|
||||
* RN: printf family of routines
|
||||
* taken mainly from sys/subr_prf.c
|
||||
****************************************************************************/
|
||||
char const hex2ascii_data[] = "0123456789abcdefghijklmnopqrstuvwxyz";
|
||||
#define hex2ascii(hex) (hex2ascii_data[hex])
|
||||
#define NBBY 8 /* number of bits in a byte */
|
||||
#define MAXNBUF (sizeof(quad_t) * NBBY + 1)
|
||||
|
||||
static int kvprintf(char const *fmt, void *arg, int radix, va_list ap);
|
||||
|
||||
|
||||
int
|
||||
printf(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
int retval;
|
||||
static char printk_buf[1024];
|
||||
|
||||
va_start(ap, fmt);
|
||||
retval = kvprintf(fmt, printk_buf, 10, ap);
|
||||
printk_buf[retval] = '\0';
|
||||
va_end(ap);
|
||||
(void)HYPERVISOR_console_write(printk_buf, strlen(printk_buf));
|
||||
return retval;
|
||||
}
|
||||
|
||||
int
|
||||
vprintf(const char *fmt, va_list ap)
|
||||
{
|
||||
int retval;
|
||||
static char printk_buf[1024];
|
||||
retval = kvprintf(fmt, printk_buf, 10, ap);
|
||||
printk_buf[retval] = '\0';
|
||||
(void)HYPERVISOR_console_write(printk_buf, strlen(printk_buf));
|
||||
return retval;
|
||||
}
|
||||
|
||||
int
|
||||
sprintf(char *buf, const char *cfmt, ...)
|
||||
{
|
||||
int retval;
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, cfmt);
|
||||
retval = kvprintf(cfmt, (void *)buf, 10, ap);
|
||||
buf[retval] = '\0';
|
||||
va_end(ap);
|
||||
return retval;
|
||||
}
|
||||
|
||||
int
|
||||
vsprintf(char *buf, const char *cfmt, va_list ap)
|
||||
{
|
||||
int retval;
|
||||
|
||||
retval = kvprintf(cfmt, (void *)buf, 10, ap);
|
||||
buf[retval] = '\0';
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Put a NUL-terminated ASCII number (base <= 36) in a buffer in reverse
|
||||
* order; return an optional length and a pointer to the last character
|
||||
* written in the buffer (i.e., the first character of the string).
|
||||
* The buffer pointed to by `nbuf' must have length >= MAXNBUF.
|
||||
*/
|
||||
static char *
|
||||
ksprintn(nbuf, ul, base, lenp)
|
||||
char *nbuf;
|
||||
u_long ul;
|
||||
int base, *lenp;
|
||||
{
|
||||
char *p;
|
||||
|
||||
p = nbuf;
|
||||
*p = '\0';
|
||||
do {
|
||||
*++p = hex2ascii(ul % base);
|
||||
} while (ul /= base);
|
||||
if (lenp)
|
||||
*lenp = p - nbuf;
|
||||
return (p);
|
||||
}
|
||||
/* ksprintn, but for a quad_t. */
|
||||
static char *
|
||||
ksprintqn(nbuf, uq, base, lenp)
|
||||
char *nbuf;
|
||||
u_quad_t uq;
|
||||
int base, *lenp;
|
||||
{
|
||||
char *p;
|
||||
|
||||
p = nbuf;
|
||||
*p = '\0';
|
||||
do {
|
||||
*++p = hex2ascii(uq % base);
|
||||
} while (uq /= base);
|
||||
if (lenp)
|
||||
*lenp = p - nbuf;
|
||||
return (p);
|
||||
}
|
||||
|
||||
/*
|
||||
* Scaled down version of printf(3).
|
||||
*
|
||||
* Two additional formats:
|
||||
*
|
||||
* The format %b is supported to decode error registers.
|
||||
* Its usage is:
|
||||
*
|
||||
* printf("reg=%b\n", regval, "<base><arg>*");
|
||||
*
|
||||
* where <base> is the output base expressed as a control character, e.g.
|
||||
* \10 gives octal; \20 gives hex. Each arg is a sequence of characters,
|
||||
* the first of which gives the bit number to be inspected (origin 1), and
|
||||
* the next characters (up to a control character, i.e. a character <= 32),
|
||||
* give the name of the register. Thus:
|
||||
*
|
||||
* kvprintf("reg=%b\n", 3, "\10\2BITTWO\1BITONE\n");
|
||||
*
|
||||
* would produce output:
|
||||
*
|
||||
* reg=3<BITTWO,BITONE>
|
||||
*
|
||||
* XXX: %D -- Hexdump, takes pointer and separator string:
|
||||
* ("%6D", ptr, ":") -> XX:XX:XX:XX:XX:XX
|
||||
* ("%*D", len, ptr, " " -> XX XX XX XX ...
|
||||
*/
|
||||
|
||||
/* RN: This normally takes a function for output.
|
||||
* we always print to a string and the use HYPERCALL for write to console */
|
||||
static int
|
||||
kvprintf(char const *fmt, void *arg, int radix, va_list ap)
|
||||
{
|
||||
|
||||
#define PCHAR(c) {int cc=(c); *d++ = cc; retval++; }
|
||||
|
||||
char nbuf[MAXNBUF];
|
||||
char *p, *q, *d;
|
||||
u_char *up;
|
||||
int ch, n;
|
||||
u_long ul;
|
||||
u_quad_t uq;
|
||||
int base, lflag, qflag, tmp, width, ladjust, sharpflag, neg, sign, dot;
|
||||
int dwidth;
|
||||
char padc;
|
||||
int retval = 0;
|
||||
|
||||
ul = 0;
|
||||
uq = 0;
|
||||
d = (char *) arg;
|
||||
|
||||
if (fmt == NULL)
|
||||
fmt = "(fmt null)\n";
|
||||
|
||||
if (radix < 2 || radix > 36)
|
||||
radix = 10;
|
||||
|
||||
for (;;) {
|
||||
padc = ' ';
|
||||
width = 0;
|
||||
while ((ch = (u_char)*fmt++) != '%') {
|
||||
if (ch == '\0')
|
||||
return retval;
|
||||
PCHAR(ch);
|
||||
}
|
||||
qflag = 0; lflag = 0; ladjust = 0; sharpflag = 0; neg = 0;
|
||||
sign = 0; dot = 0; dwidth = 0;
|
||||
reswitch: switch (ch = (u_char)*fmt++) {
|
||||
case '.':
|
||||
dot = 1;
|
||||
goto reswitch;
|
||||
case '#':
|
||||
sharpflag = 1;
|
||||
goto reswitch;
|
||||
case '+':
|
||||
sign = 1;
|
||||
goto reswitch;
|
||||
case '-':
|
||||
ladjust = 1;
|
||||
goto reswitch;
|
||||
case '%':
|
||||
PCHAR(ch);
|
||||
break;
|
||||
case '*':
|
||||
if (!dot) {
|
||||
width = va_arg(ap, int);
|
||||
if (width < 0) {
|
||||
ladjust = !ladjust;
|
||||
width = -width;
|
||||
}
|
||||
} else {
|
||||
dwidth = va_arg(ap, int);
|
||||
}
|
||||
goto reswitch;
|
||||
case '0':
|
||||
if (!dot) {
|
||||
padc = '0';
|
||||
goto reswitch;
|
||||
}
|
||||
case '1': case '2': case '3': case '4':
|
||||
case '5': case '6': case '7': case '8': case '9':
|
||||
for (n = 0;; ++fmt) {
|
||||
n = n * 10 + ch - '0';
|
||||
ch = *fmt;
|
||||
if (ch < '0' || ch > '9')
|
||||
break;
|
||||
}
|
||||
if (dot)
|
||||
dwidth = n;
|
||||
else
|
||||
width = n;
|
||||
goto reswitch;
|
||||
case 'b':
|
||||
ul = va_arg(ap, int);
|
||||
p = va_arg(ap, char *);
|
||||
for (q = ksprintn(nbuf, ul, *p++, NULL); *q;)
|
||||
PCHAR(*q--);
|
||||
|
||||
if (!ul)
|
||||
break;
|
||||
|
||||
for (tmp = 0; *p;) {
|
||||
n = *p++;
|
||||
if (ul & (1 << (n - 1))) {
|
||||
PCHAR(tmp ? ',' : '<');
|
||||
for (; (n = *p) > ' '; ++p)
|
||||
PCHAR(n);
|
||||
tmp = 1;
|
||||
} else
|
||||
for (; *p > ' '; ++p)
|
||||
continue;
|
||||
}
|
||||
if (tmp)
|
||||
PCHAR('>');
|
||||
break;
|
||||
case 'c':
|
||||
PCHAR(va_arg(ap, int));
|
||||
break;
|
||||
case 'D':
|
||||
up = va_arg(ap, u_char *);
|
||||
p = va_arg(ap, char *);
|
||||
if (!width)
|
||||
width = 16;
|
||||
while(width--) {
|
||||
PCHAR(hex2ascii(*up >> 4));
|
||||
PCHAR(hex2ascii(*up & 0x0f));
|
||||
up++;
|
||||
if (width)
|
||||
for (q=p;*q;q++)
|
||||
PCHAR(*q);
|
||||
}
|
||||
break;
|
||||
case 'd':
|
||||
if (qflag)
|
||||
uq = va_arg(ap, quad_t);
|
||||
else if (lflag)
|
||||
ul = va_arg(ap, long);
|
||||
else
|
||||
ul = va_arg(ap, int);
|
||||
sign = 1;
|
||||
base = 10;
|
||||
goto number;
|
||||
case 'l':
|
||||
if (lflag) {
|
||||
lflag = 0;
|
||||
qflag = 1;
|
||||
} else
|
||||
lflag = 1;
|
||||
goto reswitch;
|
||||
case 'o':
|
||||
if (qflag)
|
||||
uq = va_arg(ap, u_quad_t);
|
||||
else if (lflag)
|
||||
ul = va_arg(ap, u_long);
|
||||
else
|
||||
ul = va_arg(ap, u_int);
|
||||
base = 8;
|
||||
goto nosign;
|
||||
case 'p':
|
||||
ul = (uintptr_t)va_arg(ap, void *);
|
||||
base = 16;
|
||||
sharpflag = (width == 0);
|
||||
goto nosign;
|
||||
case 'q':
|
||||
qflag = 1;
|
||||
goto reswitch;
|
||||
case 'n':
|
||||
case 'r':
|
||||
if (qflag)
|
||||
uq = va_arg(ap, u_quad_t);
|
||||
else if (lflag)
|
||||
ul = va_arg(ap, u_long);
|
||||
else
|
||||
ul = sign ?
|
||||
(u_long)va_arg(ap, int) : va_arg(ap, u_int);
|
||||
base = radix;
|
||||
goto number;
|
||||
case 's':
|
||||
p = va_arg(ap, char *);
|
||||
if (p == NULL)
|
||||
p = "(null)";
|
||||
if (!dot)
|
||||
n = strlen (p);
|
||||
else
|
||||
for (n = 0; n < dwidth && p[n]; n++)
|
||||
continue;
|
||||
|
||||
width -= n;
|
||||
|
||||
if (!ladjust && width > 0)
|
||||
while (width--)
|
||||
PCHAR(padc);
|
||||
while (n--)
|
||||
PCHAR(*p++);
|
||||
if (ladjust && width > 0)
|
||||
while (width--)
|
||||
PCHAR(padc);
|
||||
break;
|
||||
case 'u':
|
||||
if (qflag)
|
||||
uq = va_arg(ap, u_quad_t);
|
||||
else if (lflag)
|
||||
ul = va_arg(ap, u_long);
|
||||
else
|
||||
ul = va_arg(ap, u_int);
|
||||
base = 10;
|
||||
goto nosign;
|
||||
case 'x':
|
||||
case 'X':
|
||||
if (qflag)
|
||||
uq = va_arg(ap, u_quad_t);
|
||||
else if (lflag)
|
||||
ul = va_arg(ap, u_long);
|
||||
else
|
||||
ul = va_arg(ap, u_int);
|
||||
base = 16;
|
||||
goto nosign;
|
||||
case 'z':
|
||||
if (qflag)
|
||||
uq = va_arg(ap, u_quad_t);
|
||||
else if (lflag)
|
||||
ul = va_arg(ap, u_long);
|
||||
else
|
||||
ul = sign ?
|
||||
(u_long)va_arg(ap, int) : va_arg(ap, u_int);
|
||||
base = 16;
|
||||
goto number;
|
||||
nosign: sign = 0;
|
||||
number:
|
||||
if (qflag) {
|
||||
if (sign && (quad_t)uq < 0) {
|
||||
neg = 1;
|
||||
uq = -(quad_t)uq;
|
||||
}
|
||||
p = ksprintqn(nbuf, uq, base, &tmp);
|
||||
} else {
|
||||
if (sign && (long)ul < 0) {
|
||||
neg = 1;
|
||||
ul = -(long)ul;
|
||||
}
|
||||
p = ksprintn(nbuf, ul, base, &tmp);
|
||||
}
|
||||
if (sharpflag && (qflag ? uq != 0 : ul != 0)) {
|
||||
if (base == 8)
|
||||
tmp++;
|
||||
else if (base == 16)
|
||||
tmp += 2;
|
||||
}
|
||||
if (neg)
|
||||
tmp++;
|
||||
|
||||
if (!ladjust && width && (width -= tmp) > 0)
|
||||
while (width--)
|
||||
PCHAR(padc);
|
||||
if (neg)
|
||||
PCHAR('-');
|
||||
if (sharpflag && (qflag ? uq != 0 : ul != 0)) {
|
||||
if (base == 8) {
|
||||
PCHAR('0');
|
||||
} else if (base == 16) {
|
||||
PCHAR('0');
|
||||
PCHAR('x');
|
||||
}
|
||||
}
|
||||
|
||||
while (*p)
|
||||
PCHAR(*p--);
|
||||
|
||||
if (ladjust && width && (width -= tmp) > 0)
|
||||
while (width--)
|
||||
PCHAR(padc);
|
||||
|
||||
break;
|
||||
default:
|
||||
PCHAR('%');
|
||||
if (lflag)
|
||||
PCHAR('l');
|
||||
PCHAR(ch);
|
||||
break;
|
||||
}
|
||||
}
|
||||
#undef PCHAR
|
||||
}
|
||||
|
||||
@@ -0,0 +1,142 @@
|
||||
/* -*- Mode:C; c-basic-offset:4; tab-width:4 -*-
|
||||
****************************************************************************
|
||||
* (C) 2003 - Rolf Neugebauer - Intel Research Cambridge
|
||||
****************************************************************************
|
||||
*
|
||||
* File: string.c
|
||||
* Author: Rolf Neugebauer (neugebar@dcs.gla.ac.uk)
|
||||
* Changes:
|
||||
*
|
||||
* Date: Aug 2003
|
||||
*
|
||||
* Environment: Xen Minimal OS
|
||||
* Description: Library function for string and memory manipulation
|
||||
* Origin unknown
|
||||
*
|
||||
****************************************************************************
|
||||
* $Id: c-insert.c,v 1.7 2002/11/08 16:04:34 rn Exp $
|
||||
****************************************************************************
|
||||
*/
|
||||
|
||||
#include <os.h>
|
||||
#include <types.h>
|
||||
#include <lib.h>
|
||||
|
||||
int memcmp(const void * cs,const void * ct,size_t count)
|
||||
{
|
||||
const unsigned char *su1, *su2;
|
||||
signed char res = 0;
|
||||
|
||||
for( su1 = cs, su2 = ct; 0 < count; ++su1, ++su2, count--)
|
||||
if ((res = *su1 - *su2) != 0)
|
||||
break;
|
||||
return res;
|
||||
}
|
||||
|
||||
void * memcpy(void * dest,const void *src,size_t count)
|
||||
{
|
||||
char *tmp = (char *) dest, *s = (char *) src;
|
||||
|
||||
while (count--)
|
||||
*tmp++ = *s++;
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
int strncmp(const char * cs,const char * ct,size_t count)
|
||||
{
|
||||
register signed char __res = 0;
|
||||
|
||||
while (count) {
|
||||
if ((__res = *cs - *ct++) != 0 || !*cs++)
|
||||
break;
|
||||
count--;
|
||||
}
|
||||
|
||||
return __res;
|
||||
}
|
||||
|
||||
int strcmp(const char * cs,const char * ct)
|
||||
{
|
||||
register signed char __res;
|
||||
|
||||
while (1) {
|
||||
if ((__res = *cs - *ct++) != 0 || !*cs++)
|
||||
break;
|
||||
}
|
||||
|
||||
return __res;
|
||||
}
|
||||
|
||||
char * strcpy(char * dest,const char *src)
|
||||
{
|
||||
char *tmp = dest;
|
||||
|
||||
while ((*dest++ = *src++) != '\0')
|
||||
/* nothing */;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
char * strncpy(char * dest,const char *src,size_t count)
|
||||
{
|
||||
char *tmp = dest;
|
||||
|
||||
while (count-- && (*dest++ = *src++) != '\0')
|
||||
/* nothing */;
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
void * memset(void * s,int c,size_t count)
|
||||
{
|
||||
char *xs = (char *) s;
|
||||
|
||||
while (count--)
|
||||
*xs++ = c;
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
size_t strnlen(const char * s, size_t count)
|
||||
{
|
||||
const char *sc;
|
||||
|
||||
for (sc = s; count-- && *sc != '\0'; ++sc)
|
||||
/* nothing */;
|
||||
return sc - s;
|
||||
}
|
||||
|
||||
size_t strlen(const char * s)
|
||||
{
|
||||
const char *sc;
|
||||
|
||||
for (sc = s; *sc != '\0'; ++sc)
|
||||
/* nothing */;
|
||||
return sc - s;
|
||||
}
|
||||
|
||||
char * strchr(const char * s, int c)
|
||||
{
|
||||
for(; *s != (char) c; ++s)
|
||||
if (*s == '\0')
|
||||
return NULL;
|
||||
return (char *) s;
|
||||
}
|
||||
|
||||
char * strstr(const char * s1,const char * s2)
|
||||
{
|
||||
int l1, l2;
|
||||
|
||||
l2 = strlen(s2);
|
||||
if (!l2)
|
||||
return (char *) s1;
|
||||
l1 = strlen(s1);
|
||||
while (l1 >= l2) {
|
||||
l1--;
|
||||
if (!memcmp(s1,s2,l2))
|
||||
return (char *) s1;
|
||||
s1++;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
+375
@@ -0,0 +1,375 @@
|
||||
/* -*- Mode:C; c-basic-offset:4; tab-width:4 -*-
|
||||
****************************************************************************
|
||||
* (C) 2003 - Rolf Neugebauer - Intel Research Cambridge
|
||||
****************************************************************************
|
||||
*
|
||||
* File: mm.c
|
||||
* Author: Rolf Neugebauer (neugebar@dcs.gla.ac.uk)
|
||||
* Changes:
|
||||
*
|
||||
* Date: Aug 2003
|
||||
*
|
||||
* Environment: Xen Minimal OS
|
||||
* Description: memory management related functions
|
||||
* contains buddy page allocator from Xen.
|
||||
*
|
||||
****************************************************************************
|
||||
* $Id: c-insert.c,v 1.7 2002/11/08 16:04:34 rn Exp $
|
||||
****************************************************************************
|
||||
*/
|
||||
|
||||
|
||||
#include <os.h>
|
||||
#include <hypervisor.h>
|
||||
#include <mm.h>
|
||||
#include <types.h>
|
||||
#include <lib.h>
|
||||
|
||||
unsigned long *phys_to_machine_mapping;
|
||||
extern char *stack;
|
||||
extern char _text, _etext, _edata, _end;
|
||||
|
||||
static void init_page_allocator(unsigned long min, unsigned long max);
|
||||
|
||||
void init_mm(void)
|
||||
{
|
||||
|
||||
unsigned long start_pfn, max_pfn, max_free_pfn;
|
||||
|
||||
unsigned long *pgd = (unsigned long *)start_info.pt_base;
|
||||
|
||||
printk("MM: Init\n");
|
||||
|
||||
printk(" _text: %p\n", &_text);
|
||||
printk(" _etext: %p\n", &_etext);
|
||||
printk(" _edata: %p\n", &_edata);
|
||||
printk(" stack start: %p\n", &stack);
|
||||
printk(" _end: %p\n", &_end);
|
||||
|
||||
/* set up minimal memory infos */
|
||||
start_pfn = PFN_UP(__pa(&_end));
|
||||
max_pfn = start_info.nr_pages;
|
||||
|
||||
printk(" start_pfn: %lx\n", start_pfn);
|
||||
printk(" max_pfn: %lx\n", max_pfn);
|
||||
|
||||
/*
|
||||
* we know where free tables start (start_pfn) and how many we
|
||||
* have (max_pfn).
|
||||
*
|
||||
* Currently the hypervisor stores page tables it providesin the
|
||||
* high region of the this memory range.
|
||||
*
|
||||
* next we work out how far down this goes (max_free_pfn)
|
||||
*
|
||||
* XXX this assumes the hypervisor provided page tables to be in
|
||||
* the upper region of our initial memory. I don't know if this
|
||||
* is always true.
|
||||
*/
|
||||
|
||||
max_free_pfn = PFN_DOWN(__pa(pgd));
|
||||
{
|
||||
unsigned long *pgd = (unsigned long *)start_info.pt_base;
|
||||
unsigned long pte;
|
||||
int i;
|
||||
printk(" pgd(pa(pgd)): %lx(%lx)", (u_long)pgd, __pa(pgd));
|
||||
|
||||
for ( i = 0; i < (HYPERVISOR_VIRT_START>>22); i++ )
|
||||
{
|
||||
unsigned long pgde = *pgd++;
|
||||
if ( !(pgde & 1) ) continue;
|
||||
pte = machine_to_phys(pgde & PAGE_MASK);
|
||||
printk(" PT(%x): %lx(%lx)", i, (u_long)__va(pte), pte);
|
||||
if (PFN_DOWN(pte) <= max_free_pfn)
|
||||
max_free_pfn = PFN_DOWN(pte);
|
||||
}
|
||||
}
|
||||
max_free_pfn--;
|
||||
printk(" max_free_pfn: %lx\n", max_free_pfn);
|
||||
|
||||
/*
|
||||
* now we can initialise the page allocator
|
||||
*/
|
||||
printk("MM: Initialise page allocator for %lx(%lx)-%lx(%lx)\n",
|
||||
(u_long)__va(PFN_PHYS(start_pfn)), PFN_PHYS(start_pfn),
|
||||
(u_long)__va(PFN_PHYS(max_free_pfn)), PFN_PHYS(max_free_pfn));
|
||||
init_page_allocator(PFN_PHYS(start_pfn), PFN_PHYS(max_free_pfn));
|
||||
|
||||
|
||||
/* Now initialise the physical->machine mapping table. */
|
||||
|
||||
|
||||
printk("MM: done\n");
|
||||
|
||||
|
||||
}
|
||||
|
||||
/*********************
|
||||
* ALLOCATION BITMAP
|
||||
* One bit per page of memory. Bit set => page is allocated.
|
||||
*/
|
||||
|
||||
static unsigned long *alloc_bitmap;
|
||||
#define PAGES_PER_MAPWORD (sizeof(unsigned long) * 8)
|
||||
|
||||
#define allocated_in_map(_pn) \
|
||||
(alloc_bitmap[(_pn)/PAGES_PER_MAPWORD] & (1<<((_pn)&(PAGES_PER_MAPWORD-1))))
|
||||
|
||||
|
||||
/*
|
||||
* Hint regarding bitwise arithmetic in map_{alloc,free}:
|
||||
* -(1<<n) sets all bits >= n.
|
||||
* (1<<n)-1 sets all bits < n.
|
||||
* Variable names in map_{alloc,free}:
|
||||
* *_idx == Index into `alloc_bitmap' array.
|
||||
* *_off == Bit offset within an element of the `alloc_bitmap' array.
|
||||
*/
|
||||
|
||||
static void map_alloc(unsigned long first_page, unsigned long nr_pages)
|
||||
{
|
||||
unsigned long start_off, end_off, curr_idx, end_idx;
|
||||
|
||||
curr_idx = first_page / PAGES_PER_MAPWORD;
|
||||
start_off = first_page & (PAGES_PER_MAPWORD-1);
|
||||
end_idx = (first_page + nr_pages) / PAGES_PER_MAPWORD;
|
||||
end_off = (first_page + nr_pages) & (PAGES_PER_MAPWORD-1);
|
||||
|
||||
if ( curr_idx == end_idx )
|
||||
{
|
||||
alloc_bitmap[curr_idx] |= ((1<<end_off)-1) & -(1<<start_off);
|
||||
}
|
||||
else
|
||||
{
|
||||
alloc_bitmap[curr_idx] |= -(1<<start_off);
|
||||
while ( ++curr_idx < end_idx ) alloc_bitmap[curr_idx] = ~0L;
|
||||
alloc_bitmap[curr_idx] |= (1<<end_off)-1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void map_free(unsigned long first_page, unsigned long nr_pages)
|
||||
{
|
||||
unsigned long start_off, end_off, curr_idx, end_idx;
|
||||
|
||||
curr_idx = first_page / PAGES_PER_MAPWORD;
|
||||
start_off = first_page & (PAGES_PER_MAPWORD-1);
|
||||
end_idx = (first_page + nr_pages) / PAGES_PER_MAPWORD;
|
||||
end_off = (first_page + nr_pages) & (PAGES_PER_MAPWORD-1);
|
||||
|
||||
if ( curr_idx == end_idx )
|
||||
{
|
||||
alloc_bitmap[curr_idx] &= -(1<<end_off) | ((1<<start_off)-1);
|
||||
}
|
||||
else
|
||||
{
|
||||
alloc_bitmap[curr_idx] &= (1<<start_off)-1;
|
||||
while ( ++curr_idx != end_idx ) alloc_bitmap[curr_idx] = 0;
|
||||
alloc_bitmap[curr_idx] &= -(1<<end_off);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*************************
|
||||
* BINARY BUDDY ALLOCATOR
|
||||
*/
|
||||
|
||||
typedef struct chunk_head_st chunk_head_t;
|
||||
typedef struct chunk_tail_st chunk_tail_t;
|
||||
|
||||
struct chunk_head_st {
|
||||
chunk_head_t *next;
|
||||
chunk_head_t **pprev;
|
||||
int level;
|
||||
};
|
||||
|
||||
struct chunk_tail_st {
|
||||
int level;
|
||||
};
|
||||
|
||||
/* Linked lists of free chunks of different powers-of-two in size. */
|
||||
#define FREELIST_SIZE ((sizeof(void*)<<3)-PAGE_SHIFT)
|
||||
static chunk_head_t *free_head[FREELIST_SIZE];
|
||||
static chunk_head_t free_tail[FREELIST_SIZE];
|
||||
#define FREELIST_EMPTY(_l) ((_l)->next == NULL)
|
||||
|
||||
#define round_pgdown(_p) ((_p)&PAGE_MASK)
|
||||
#define round_pgup(_p) (((_p)+(PAGE_SIZE-1))&PAGE_MASK)
|
||||
|
||||
|
||||
/*
|
||||
* Initialise allocator, placing addresses [@min,@max] in free pool.
|
||||
* @min and @max are PHYSICAL addresses.
|
||||
*/
|
||||
static void init_page_allocator(unsigned long min, unsigned long max)
|
||||
{
|
||||
int i;
|
||||
unsigned long range, bitmap_size;
|
||||
chunk_head_t *ch;
|
||||
chunk_tail_t *ct;
|
||||
|
||||
for ( i = 0; i < FREELIST_SIZE; i++ )
|
||||
{
|
||||
free_head[i] = &free_tail[i];
|
||||
free_tail[i].pprev = &free_head[i];
|
||||
free_tail[i].next = NULL;
|
||||
}
|
||||
|
||||
min = round_pgup (min);
|
||||
max = round_pgdown(max);
|
||||
|
||||
/* Allocate space for the allocation bitmap. */
|
||||
bitmap_size = (max+1) >> (PAGE_SHIFT+3);
|
||||
bitmap_size = round_pgup(bitmap_size);
|
||||
alloc_bitmap = (unsigned long *)__va(min);
|
||||
min += bitmap_size;
|
||||
range = max - min;
|
||||
|
||||
/* All allocated by default. */
|
||||
memset(alloc_bitmap, ~0, bitmap_size);
|
||||
/* Free up the memory we've been given to play with. */
|
||||
map_free(min>>PAGE_SHIFT, range>>PAGE_SHIFT);
|
||||
|
||||
/* The buddy lists are addressed in high memory. */
|
||||
min += PAGE_OFFSET;
|
||||
max += PAGE_OFFSET;
|
||||
|
||||
while ( range != 0 )
|
||||
{
|
||||
/*
|
||||
* Next chunk is limited by alignment of min, but also
|
||||
* must not be bigger than remaining range.
|
||||
*/
|
||||
for ( i = PAGE_SHIFT; (1<<(i+1)) <= range; i++ )
|
||||
if ( min & (1<<i) ) break;
|
||||
|
||||
|
||||
ch = (chunk_head_t *)min;
|
||||
min += (1<<i);
|
||||
range -= (1<<i);
|
||||
ct = (chunk_tail_t *)min-1;
|
||||
i -= PAGE_SHIFT;
|
||||
ch->level = i;
|
||||
ch->next = free_head[i];
|
||||
ch->pprev = &free_head[i];
|
||||
ch->next->pprev = &ch->next;
|
||||
free_head[i] = ch;
|
||||
ct->level = i;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Release a PHYSICAL address range to the allocator. */
|
||||
void release_bytes_to_allocator(unsigned long min, unsigned long max)
|
||||
{
|
||||
min = round_pgup (min) + PAGE_OFFSET;
|
||||
max = round_pgdown(max) + PAGE_OFFSET;
|
||||
|
||||
while ( min < max )
|
||||
{
|
||||
__free_pages(min, 0);
|
||||
min += PAGE_SIZE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Allocate 2^@order contiguous pages. Returns a VIRTUAL address. */
|
||||
unsigned long __get_free_pages(int order)
|
||||
{
|
||||
int i;
|
||||
chunk_head_t *alloc_ch, *spare_ch;
|
||||
chunk_tail_t *spare_ct;
|
||||
|
||||
|
||||
/* Find smallest order which can satisfy the request. */
|
||||
for ( i = order; i < FREELIST_SIZE; i++ ) {
|
||||
if ( !FREELIST_EMPTY(free_head[i]) )
|
||||
break;
|
||||
}
|
||||
|
||||
if ( i == FREELIST_SIZE ) goto no_memory;
|
||||
|
||||
/* Unlink a chunk. */
|
||||
alloc_ch = free_head[i];
|
||||
free_head[i] = alloc_ch->next;
|
||||
alloc_ch->next->pprev = alloc_ch->pprev;
|
||||
|
||||
/* We may have to break the chunk a number of times. */
|
||||
while ( i != order )
|
||||
{
|
||||
/* Split into two equal parts. */
|
||||
i--;
|
||||
spare_ch = (chunk_head_t *)((char *)alloc_ch + (1<<(i+PAGE_SHIFT)));
|
||||
spare_ct = (chunk_tail_t *)((char *)spare_ch + (1<<(i+PAGE_SHIFT)))-1;
|
||||
|
||||
/* Create new header for spare chunk. */
|
||||
spare_ch->level = i;
|
||||
spare_ch->next = free_head[i];
|
||||
spare_ch->pprev = &free_head[i];
|
||||
spare_ct->level = i;
|
||||
|
||||
/* Link in the spare chunk. */
|
||||
spare_ch->next->pprev = &spare_ch->next;
|
||||
free_head[i] = spare_ch;
|
||||
}
|
||||
|
||||
map_alloc(__pa(alloc_ch)>>PAGE_SHIFT, 1<<order);
|
||||
|
||||
return((unsigned long)alloc_ch);
|
||||
|
||||
no_memory:
|
||||
|
||||
printk("Cannot handle page request order %d!\n", order);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Free 2^@order pages at VIRTUAL address @p. */
|
||||
void __free_pages(unsigned long p, int order)
|
||||
{
|
||||
unsigned long size = 1 << (order + PAGE_SHIFT);
|
||||
chunk_head_t *ch;
|
||||
chunk_tail_t *ct;
|
||||
unsigned long pagenr = __pa(p) >> PAGE_SHIFT;
|
||||
|
||||
map_free(pagenr, 1<<order);
|
||||
|
||||
/* Merge chunks as far as possible. */
|
||||
for ( ; ; )
|
||||
{
|
||||
if ( (p & size) )
|
||||
{
|
||||
/* Merge with predecessor block? */
|
||||
if ( allocated_in_map(pagenr-1) ) break;
|
||||
ct = (chunk_tail_t *)p - 1;
|
||||
if ( ct->level != order ) break;
|
||||
ch = (chunk_head_t *)(p - size);
|
||||
p -= size;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Merge with successor block? */
|
||||
if ( allocated_in_map(pagenr+(1<<order)) ) break;
|
||||
ch = (chunk_head_t *)(p + size);
|
||||
if ( ch->level != order ) break;
|
||||
}
|
||||
|
||||
/* Okay, unlink the neighbour. */
|
||||
*ch->pprev = ch->next;
|
||||
ch->next->pprev = ch->pprev;
|
||||
|
||||
order++;
|
||||
size <<= 1;
|
||||
}
|
||||
|
||||
/* Okay, add the final chunk to the appropriate free list. */
|
||||
ch = (chunk_head_t *)p;
|
||||
ct = (chunk_tail_t *)(p+size)-1;
|
||||
ct->level = order;
|
||||
ch->level = order;
|
||||
ch->pprev = &free_head[order];
|
||||
ch->next = free_head[order];
|
||||
ch->next->pprev = &ch->next;
|
||||
free_head[order] = ch;
|
||||
}
|
||||
+149
@@ -0,0 +1,149 @@
|
||||
/* -*- Mode:C; c-basic-offset:4; tab-width:4 -*-
|
||||
****************************************************************************
|
||||
* (C) 2003 - Rolf Neugebauer - Intel Research Cambridge
|
||||
****************************************************************************
|
||||
*
|
||||
* File: time.c
|
||||
* Author: Rolf Neugebauer (neugebar@dcs.gla.ac.uk)
|
||||
* Changes:
|
||||
*
|
||||
* Date: Jul 2003
|
||||
*
|
||||
* Environment: Xen Minimal OS
|
||||
* Description: Simple time and timer functions
|
||||
*
|
||||
****************************************************************************
|
||||
* $Id: c-insert.c,v 1.7 2002/11/08 16:04:34 rn Exp $
|
||||
****************************************************************************
|
||||
*/
|
||||
|
||||
|
||||
#include <os.h>
|
||||
#include <types.h>
|
||||
#include <hypervisor.h>
|
||||
#include <events.h>
|
||||
#include <time.h>
|
||||
#include <lib.h>
|
||||
|
||||
/************************************************************************
|
||||
* Time functions
|
||||
*************************************************************************/
|
||||
|
||||
static unsigned int rdtsc_bitshift;
|
||||
static u32 st_scale_f;
|
||||
static u32 st_scale_i;
|
||||
static u32 shadow_st_pcc;
|
||||
static s_time_t shadow_st;
|
||||
static u32 shadow_wc_version=0;
|
||||
static long shadow_tv_sec;
|
||||
static long shadow_tv_usec;
|
||||
static s_time_t shadow_wc_timestamp;
|
||||
|
||||
/*
|
||||
* System time.
|
||||
* We need to read the values from the shared info page "atomically"
|
||||
* and use the cycle counter value as the "version" number. Clashes
|
||||
* should be very rare.
|
||||
*/
|
||||
inline s_time_t get_s_time(void)
|
||||
{
|
||||
s32 delta_tsc;
|
||||
u32 low;
|
||||
u64 delta, tsc;
|
||||
u32 version;
|
||||
u64 cpu_freq, scale;
|
||||
|
||||
/* check if our values are still up-to-date */
|
||||
while ( (version = HYPERVISOR_shared_info->wc_version) !=
|
||||
shadow_wc_version )
|
||||
{
|
||||
barrier();
|
||||
|
||||
shadow_wc_version = version;
|
||||
shadow_tv_sec = HYPERVISOR_shared_info->tv_sec;
|
||||
shadow_tv_usec = HYPERVISOR_shared_info->tv_usec;
|
||||
shadow_wc_timestamp = HYPERVISOR_shared_info->wc_timestamp;
|
||||
shadow_st_pcc = HYPERVISOR_shared_info->st_timestamp;
|
||||
shadow_st = HYPERVISOR_shared_info->system_time;
|
||||
|
||||
rdtsc_bitshift = HYPERVISOR_shared_info->rdtsc_bitshift;
|
||||
cpu_freq = HYPERVISOR_shared_info->cpu_freq;
|
||||
|
||||
/* XXX cpu_freq as u32 limits it to 4.29 GHz. Get a better do_div! */
|
||||
scale = 1000000000LL << (32 + rdtsc_bitshift);
|
||||
scale /= cpu_freq;
|
||||
st_scale_f = scale & 0xffffffff;
|
||||
st_scale_i = scale >> 32;
|
||||
|
||||
barrier();
|
||||
}
|
||||
|
||||
rdtscll(tsc);
|
||||
low = (u32)(tsc >> rdtsc_bitshift);
|
||||
delta_tsc = (s32)(low - shadow_st_pcc);
|
||||
if ( unlikely(delta_tsc < 0) ) delta_tsc = 0;
|
||||
delta = ((u64)delta_tsc * st_scale_f);
|
||||
delta >>= 32;
|
||||
delta += ((u64)delta_tsc * st_scale_i);
|
||||
|
||||
return shadow_st + delta;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Wallclock time.
|
||||
* Based on what the hypervisor tells us, extrapolated using system time.
|
||||
* Again need to read a number of values from the shared page "atomically".
|
||||
* this time using a version number.
|
||||
*/
|
||||
void gettimeofday(struct timeval *tv)
|
||||
{
|
||||
long usec, sec;
|
||||
u64 now;
|
||||
|
||||
now = get_s_time();
|
||||
usec = ((unsigned long)(now-shadow_wc_timestamp))/1000;
|
||||
sec = shadow_tv_sec;
|
||||
usec += shadow_tv_usec;
|
||||
|
||||
while ( usec >= 1000000 )
|
||||
{
|
||||
usec -= 1000000;
|
||||
sec++;
|
||||
}
|
||||
|
||||
tv->tv_sec = sec;
|
||||
tv->tv_usec = usec;
|
||||
}
|
||||
|
||||
|
||||
static void timer_handler(int ev, struct pt_regs *regs)
|
||||
{
|
||||
static int i;
|
||||
s_time_t now;
|
||||
|
||||
i++;
|
||||
if (i >= 1000) {
|
||||
now = get_s_time();
|
||||
printf("T(%lld)\n", now);
|
||||
i = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void init_time(void)
|
||||
{
|
||||
u64 __cpu_khz;
|
||||
unsigned long cpu_khz;
|
||||
|
||||
__cpu_khz = HYPERVISOR_shared_info->cpu_freq;
|
||||
cpu_khz = (u32) (__cpu_khz/1000);
|
||||
|
||||
printk("Xen reported: %lu.%03lu MHz processor.\n",
|
||||
cpu_khz / 1000, cpu_khz % 1000);
|
||||
|
||||
add_ev_action(EV_TIMER, &timer_handler);
|
||||
enable_ev_action(EV_TIMER);
|
||||
enable_hypervisor_event(EV_TIMER);
|
||||
|
||||
}
|
||||
+150
@@ -0,0 +1,150 @@
|
||||
|
||||
#include <os.h>
|
||||
#include <hypervisor.h>
|
||||
#include <lib.h>
|
||||
|
||||
/*
|
||||
* These are assembler stubs in entry.S.
|
||||
* They are the actual entry points for virtual exceptions.
|
||||
*/
|
||||
void divide_error(void);
|
||||
void debug(void);
|
||||
void int3(void);
|
||||
void overflow(void);
|
||||
void bounds(void);
|
||||
void invalid_op(void);
|
||||
void device_not_available(void);
|
||||
void double_fault(void);
|
||||
void coprocessor_segment_overrun(void);
|
||||
void invalid_TSS(void);
|
||||
void segment_not_present(void);
|
||||
void stack_segment(void);
|
||||
void general_protection(void);
|
||||
void page_fault(void);
|
||||
void coprocessor_error(void);
|
||||
void simd_coprocessor_error(void);
|
||||
void alignment_check(void);
|
||||
void spurious_interrupt_bug(void);
|
||||
void machine_check(void);
|
||||
|
||||
/*
|
||||
* C handlers here have their parameter-list constructed by the
|
||||
* assembler stubs above. Each one gets a pointer to a list
|
||||
* of register values (to be restored at end of exception).
|
||||
* Some will also receive an error code -- this is the code that
|
||||
* was generated by the processor for the underlying real exception.
|
||||
*
|
||||
* Note that the page-fault exception is special. It also receives
|
||||
* the faulting linear address. Normally this would be found in
|
||||
* register CR2, but that is not accessible in a virtualised OS.
|
||||
*/
|
||||
|
||||
static void inline do_trap(int trapnr, char *str,
|
||||
struct pt_regs * regs, long error_code)
|
||||
{
|
||||
printk("Trap\n");
|
||||
}
|
||||
|
||||
#define DO_ERROR(trapnr, str, name) \
|
||||
void do_##name(struct pt_regs * regs, long error_code) \
|
||||
{ \
|
||||
do_trap(trapnr, str, regs, error_code); \
|
||||
}
|
||||
|
||||
#define DO_ERROR_INFO(trapnr, str, name, sicode, siaddr) \
|
||||
void do_##name(struct pt_regs * regs, long error_code) \
|
||||
{ \
|
||||
do_trap(trapnr, str, regs, error_code); \
|
||||
}
|
||||
|
||||
DO_ERROR_INFO( 0, "divide error", divide_error, FPE_INTDIV, regs->eip)
|
||||
DO_ERROR( 3, "int3", int3)
|
||||
DO_ERROR( 4, "overflow", overflow)
|
||||
DO_ERROR( 5, "bounds", bounds)
|
||||
DO_ERROR_INFO( 6, "invalid operand", invalid_op, ILL_ILLOPN, regs->eip)
|
||||
DO_ERROR( 7, "device not available", device_not_available)
|
||||
DO_ERROR( 8, "double fault", double_fault)
|
||||
DO_ERROR( 9, "coprocessor segment overrun", coprocessor_segment_overrun)
|
||||
DO_ERROR(10, "invalid TSS", invalid_TSS)
|
||||
DO_ERROR(11, "segment not present", segment_not_present)
|
||||
DO_ERROR(12, "stack segment", stack_segment)
|
||||
DO_ERROR_INFO(17, "alignment check", alignment_check, BUS_ADRALN, 0)
|
||||
DO_ERROR(18, "machine check", machine_check)
|
||||
|
||||
void do_page_fault(struct pt_regs * regs, long error_code,
|
||||
unsigned long address)
|
||||
{
|
||||
printk("Page fault\n");
|
||||
}
|
||||
|
||||
void do_general_protection(struct pt_regs * regs, long error_code)
|
||||
{
|
||||
printk("GPF\n");
|
||||
}
|
||||
|
||||
|
||||
void do_debug(struct pt_regs * regs, long error_code)
|
||||
{
|
||||
printk("Debug exception\n");
|
||||
#define TF_MASK 0x100
|
||||
regs->eflags &= ~TF_MASK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void do_coprocessor_error(struct pt_regs * regs, long error_code)
|
||||
{
|
||||
printk("Copro error\n");
|
||||
}
|
||||
|
||||
void simd_math_error(void *eip)
|
||||
{
|
||||
printk("SIMD error\n");
|
||||
}
|
||||
|
||||
void do_simd_coprocessor_error(struct pt_regs * regs,
|
||||
long error_code)
|
||||
{
|
||||
printk("SIMD copro error\n");
|
||||
}
|
||||
|
||||
void do_spurious_interrupt_bug(struct pt_regs * regs,
|
||||
long error_code)
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
* Submit a virtual IDT to teh hypervisor. This consists of tuples
|
||||
* (interrupt vector, privilege ring, CS:EIP of handler).
|
||||
* The 'privilege ring' field specifies the least-privileged ring that
|
||||
* can trap to that vector using a software-interrupt instruction (INT).
|
||||
*/
|
||||
static trap_info_t trap_table[] = {
|
||||
{ 0, 0, __KERNEL_CS, (unsigned long)divide_error },
|
||||
{ 1, 0, __KERNEL_CS, (unsigned long)debug },
|
||||
{ 3, 3, __KERNEL_CS, (unsigned long)int3 },
|
||||
{ 4, 3, __KERNEL_CS, (unsigned long)overflow },
|
||||
{ 5, 3, __KERNEL_CS, (unsigned long)bounds },
|
||||
{ 6, 0, __KERNEL_CS, (unsigned long)invalid_op },
|
||||
{ 7, 0, __KERNEL_CS, (unsigned long)device_not_available },
|
||||
{ 8, 0, __KERNEL_CS, (unsigned long)double_fault },
|
||||
{ 9, 0, __KERNEL_CS, (unsigned long)coprocessor_segment_overrun },
|
||||
{ 10, 0, __KERNEL_CS, (unsigned long)invalid_TSS },
|
||||
{ 11, 0, __KERNEL_CS, (unsigned long)segment_not_present },
|
||||
{ 12, 0, __KERNEL_CS, (unsigned long)stack_segment },
|
||||
{ 13, 0, __KERNEL_CS, (unsigned long)general_protection },
|
||||
{ 14, 0, __KERNEL_CS, (unsigned long)page_fault },
|
||||
{ 15, 0, __KERNEL_CS, (unsigned long)spurious_interrupt_bug },
|
||||
{ 16, 0, __KERNEL_CS, (unsigned long)coprocessor_error },
|
||||
{ 17, 0, __KERNEL_CS, (unsigned long)alignment_check },
|
||||
{ 18, 0, __KERNEL_CS, (unsigned long)machine_check },
|
||||
{ 19, 0, __KERNEL_CS, (unsigned long)simd_coprocessor_error },
|
||||
{ 0, 0, 0, 0 }
|
||||
};
|
||||
|
||||
|
||||
|
||||
void trap_init(void)
|
||||
{
|
||||
HYPERVISOR_set_trap_table(trap_table);
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
/* ld script to make i386 Linux kernel
|
||||
* Written by Martin Mares <mj@atrey.karlin.mff.cuni.cz>;
|
||||
*/
|
||||
OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
|
||||
OUTPUT_ARCH(i386)
|
||||
ENTRY(_start)
|
||||
SECTIONS
|
||||
{
|
||||
. = 0xC0000000 + 0x000000;
|
||||
_text = .; /* Text and read-only data */
|
||||
.text : {
|
||||
*(.text)
|
||||
*(.fixup)
|
||||
*(.gnu.warning)
|
||||
} = 0x9090
|
||||
|
||||
_etext = .; /* End of text section */
|
||||
|
||||
.rodata : { *(.rodata) *(.rodata.*) }
|
||||
.kstrtab : { *(.kstrtab) }
|
||||
|
||||
. = ALIGN(16); /* Exception table */
|
||||
__start___ex_table = .;
|
||||
__ex_table : { *(__ex_table) }
|
||||
__stop___ex_table = .;
|
||||
|
||||
__start___ksymtab = .; /* Kernel symbol table */
|
||||
__ksymtab : { *(__ksymtab) }
|
||||
__stop___ksymtab = .;
|
||||
|
||||
.data : { /* Data */
|
||||
*(.data)
|
||||
CONSTRUCTORS
|
||||
}
|
||||
|
||||
_edata = .; /* End of data section */
|
||||
|
||||
. = ALIGN(8192); /* init_task */
|
||||
.data.init_task : { *(.data.init_task) }
|
||||
|
||||
. = ALIGN(4096); /* Init code and data */
|
||||
__init_begin = .;
|
||||
.text.init : { *(.text.init) }
|
||||
.data.init : { *(.data.init) }
|
||||
. = ALIGN(16);
|
||||
__setup_start = .;
|
||||
.setup.init : { *(.setup.init) }
|
||||
__setup_end = .;
|
||||
__initcall_start = .;
|
||||
.initcall.init : { *(.initcall.init) }
|
||||
__initcall_end = .;
|
||||
. = ALIGN(4096);
|
||||
__init_end = .;
|
||||
|
||||
. = ALIGN(4096);
|
||||
.data.page_aligned : { *(.data.idt) }
|
||||
|
||||
. = ALIGN(32);
|
||||
.data.cacheline_aligned : { *(.data.cacheline_aligned) }
|
||||
|
||||
__bss_start = .; /* BSS */
|
||||
.bss : {
|
||||
*(.bss)
|
||||
}
|
||||
_end = . ;
|
||||
|
||||
/* Sections to be discarded */
|
||||
/DISCARD/ : {
|
||||
*(.text.exit)
|
||||
*(.data.exit)
|
||||
*(.exitcall.exit)
|
||||
}
|
||||
|
||||
/* Stabs debugging sections. */
|
||||
.stab 0 : { *(.stab) }
|
||||
.stabstr 0 : { *(.stabstr) }
|
||||
.stab.excl 0 : { *(.stab.excl) }
|
||||
.stab.exclstr 0 : { *(.stab.exclstr) }
|
||||
.stab.index 0 : { *(.stab.index) }
|
||||
.stab.indexstr 0 : { *(.stab.indexstr) }
|
||||
.comment 0 : { *(.comment) }
|
||||
}
|
||||