PERFORCE change 137384 for review
Robert Watson
rwatson at FreeBSD.org
Tue Mar 11 07:58:22 UTC 2008
http://perforce.freebsd.org/chv.cgi?CH=137384
Change 137384 by rwatson at rwatson_cinnamon on 2008/03/11 07:58:19
Integrate zcopybpf branch.
Affected files ...
.. //depot/projects/zcopybpf/src/sys/amd64/amd64/legacy.c#4 integrate
.. //depot/projects/zcopybpf/src/sys/amd64/amd64/mp_machdep.c#8 integrate
.. //depot/projects/zcopybpf/src/sys/boot/i386/btx/btx/btx.S#3 integrate
.. //depot/projects/zcopybpf/src/sys/conf/files#20 integrate
.. //depot/projects/zcopybpf/src/sys/dev/acpica/acpi.c#10 integrate
.. //depot/projects/zcopybpf/src/sys/dev/cpufreq/ichss.c#2 integrate
.. //depot/projects/zcopybpf/src/sys/dev/msk/if_msk.c#11 integrate
.. //depot/projects/zcopybpf/src/sys/dev/vr/if_vr.c#1 branch
.. //depot/projects/zcopybpf/src/sys/dev/vr/if_vrreg.h#1 branch
.. //depot/projects/zcopybpf/src/sys/dev/wpi/if_wpi.c#6 integrate
.. //depot/projects/zcopybpf/src/sys/dev/wpi/if_wpireg.h#3 integrate
.. //depot/projects/zcopybpf/src/sys/dev/wpi/if_wpivar.h#2 integrate
.. //depot/projects/zcopybpf/src/sys/i386/cpufreq/est.c#3 integrate
.. //depot/projects/zcopybpf/src/sys/i386/i386/legacy.c#4 integrate
.. //depot/projects/zcopybpf/src/sys/i386/i386/mp_machdep.c#10 integrate
.. //depot/projects/zcopybpf/src/sys/kern/kern_synch.c#9 integrate
.. //depot/projects/zcopybpf/src/sys/kern/sched_4bsd.c#10 integrate
.. //depot/projects/zcopybpf/src/sys/kern/sched_ule.c#16 integrate
.. //depot/projects/zcopybpf/src/sys/kern/subr_bus.c#9 integrate
.. //depot/projects/zcopybpf/src/sys/kern/subr_smp.c#8 integrate
.. //depot/projects/zcopybpf/src/sys/modules/vr/Makefile#2 integrate
.. //depot/projects/zcopybpf/src/sys/netsmb/smb_conn.h#3 integrate
.. //depot/projects/zcopybpf/src/sys/pc98/conf/GENERIC#10 integrate
.. //depot/projects/zcopybpf/src/sys/pci/if_vr.c#6 delete
.. //depot/projects/zcopybpf/src/sys/pci/if_vrreg.h#3 delete
.. //depot/projects/zcopybpf/src/sys/security/audit/audit_worker.c#6 integrate
.. //depot/projects/zcopybpf/src/sys/sparc64/conf/GENERIC#9 integrate
.. //depot/projects/zcopybpf/src/sys/sun4v/sun4v/mp_machdep.c#5 integrate
.. //depot/projects/zcopybpf/src/sys/sys/sched.h#4 integrate
.. //depot/projects/zcopybpf/src/sys/ufs/ffs/ffs_softdep.c#11 integrate
Differences ...
==== //depot/projects/zcopybpf/src/sys/amd64/amd64/legacy.c#4 (text+ko) ====
@@ -28,7 +28,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/amd64/amd64/legacy.c,v 1.61 2007/09/30 11:05:13 marius Exp $");
+__FBSDID("$FreeBSD: src/sys/amd64/amd64/legacy.c,v 1.62 2008/03/10 22:18:06 jhb Exp $");
/*
* This code implements a system driver for legacy systems that do not
@@ -132,20 +132,10 @@
legacy_attach(device_t dev)
{
device_t child;
- int i;
- /* First, attach the CPU pseudo-driver. */
- for (i = 0; i <= mp_maxid; i++)
- if (!CPU_ABSENT(i)) {
- child = BUS_ADD_CHILD(dev, 0, "cpu", i);
- if (child == NULL)
- panic("legacy_attach cpu");
- device_probe_and_attach(child);
- }
-
/*
- * Second, let our child driver's identify any child devices that
- * they can find. Once that is done attach any devices that we
+ * Let our child drivers identify any child devices that they
+ * can find. Once that is done attach any devices that we
* found.
*/
bus_generic_probe(dev);
@@ -241,6 +231,7 @@
* Legacy CPU attachment when ACPI is not available. Drivers like
* cpufreq(4) hang off this.
*/
+static void cpu_identify(driver_t *driver, device_t parent);
static int cpu_read_ivar(device_t dev, device_t child, int index,
uintptr_t *result);
static device_t cpu_add_child(device_t bus, int order, const char *name,
@@ -254,6 +245,7 @@
static device_method_t cpu_methods[] = {
/* Device interface */
+ DEVMETHOD(device_identify, cpu_identify),
DEVMETHOD(device_probe, bus_generic_probe),
DEVMETHOD(device_attach, bus_generic_attach),
DEVMETHOD(device_detach, bus_generic_detach),
@@ -287,6 +279,25 @@
static devclass_t cpu_devclass;
DRIVER_MODULE(cpu, legacy, cpu_driver, cpu_devclass, 0, 0);
+static void
+cpu_identify(driver_t *driver, device_t parent)
+{
+ device_t child;
+ int i;
+
+ /*
+ * Attach a cpuX device for each CPU. We use an order of 150
+ * so that these devices are attached after the Host-PCI
+ * bridges (which are added at order 100).
+ */
+ for (i = 0; i <= mp_maxid; i++)
+ if (!CPU_ABSENT(i)) {
+ child = BUS_ADD_CHILD(parent, 150, "cpu", i);
+ if (child == NULL)
+ panic("legacy_attach cpu");
+ }
+}
+
static device_t
cpu_add_child(device_t bus, int order, const char *name, int unit)
{
==== //depot/projects/zcopybpf/src/sys/amd64/amd64/mp_machdep.c#8 (text+ko) ====
@@ -25,7 +25,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/amd64/amd64/mp_machdep.c,v 1.288 2008/03/02 07:58:40 jeff Exp $");
+__FBSDID("$FreeBSD: src/sys/amd64/amd64/mp_machdep.c,v 1.289 2008/03/10 01:32:48 jeff Exp $");
#include "opt_cpu.h"
#include "opt_kstack_pages.h"
@@ -950,15 +950,8 @@
ipi_bitmap = atomic_readandclear_int(&cpu_ipi_pending[cpu]);
- if (ipi_bitmap & (1 << IPI_PREEMPT)) {
- struct thread *running_thread = curthread;
- thread_lock(running_thread);
- if (running_thread->td_critnest > 1)
- running_thread->td_owepreempt = 1;
- else
- mi_switch(SW_INVOL | SW_PREEMPT, NULL);
- thread_unlock(running_thread);
- }
+ if (ipi_bitmap & (1 << IPI_PREEMPT))
+ sched_preempt(curthread);
/* Nothing to do for AST */
}
==== //depot/projects/zcopybpf/src/sys/boot/i386/btx/btx/btx.S#3 (text+ko) ====
@@ -12,7 +12,7 @@
* warranties of merchantability and fitness for a particular
* purpose.
*
- * $FreeBSD: src/sys/boot/i386/btx/btx/btx.S,v 1.45 2008/02/27 23:35:39 jhb Exp $
+ * $FreeBSD: src/sys/boot/i386/btx/btx/btx.S,v 1.46 2008/03/10 21:43:31 jhb Exp $
*/
/*
@@ -21,11 +21,11 @@
.set MEM_BTX,0x1000 # Start of BTX memory
.set MEM_ESP0,0x1800 # Supervisor stack
.set MEM_BUF,0x1800 # Scratch buffer
- .set MEM_ESP1,0x1e00 # Link stack
- .set MEM_IDT,0x1e00 # IDT
- .set MEM_TSS,0x1f98 # TSS
- .set MEM_MAP,0x2000 # I/O bit map
- .set MEM_TSS_END,0x3fff # Page directory
+ .set MEM_ESPR,0x5e00 # Real mode stack
+ .set MEM_IDT,0x5e00 # IDT
+ .set MEM_TSS,0x5f98 # TSS
+ .set MEM_MAP,0x6000 # I/O bit map
+ .set MEM_TSS_END,0x7fff # End of TSS
.set MEM_ORG,0x9000 # BTX code
.set MEM_USR,0xa000 # Start of user memory
/*
@@ -48,7 +48,6 @@
*/
.set TSS_ESP0,0x4 # PL 0 ESP
.set TSS_SS0,0x8 # PL 0 SS
- .set TSS_ESP1,0xc # PL 1 ESP
.set TSS_MAP,0x66 # I/O bit map base
/*
* System calls.
@@ -56,10 +55,20 @@
.set SYS_EXIT,0x0 # Exit
.set SYS_EXEC,0x1 # Exec
/*
- * V86 constants.
+ * Fields in V86 interface structure.
+ */
+ .set V86_CTL,0x0 # Control flags
+ .set V86_ADDR,0x4 # Int number/address
+ .set V86_ES,0x8 # V86 ES
+ .set V86_DS,0xc # V86 DS
+ .set V86_FS,0x10 # V86 FS
+ .set V86_GS,0x14 # V86 GS
+/*
+ * V86 control flags.
*/
- .set V86_FLG,0x208eff # V86 flag mask
- .set V86_STK,0x400 # V86 stack allowance
+ .set V86F_ADDR,0x10000 # Segment:offset address
+ .set V86F_CALLF,0x20000 # Emulate far call
+ .set V86F_FLAGS,0x40000 # Return flags
/*
* Dump format control bytes.
*/
@@ -77,7 +86,6 @@
* BIOS Data Area locations.
*/
.set BDA_MEM,0x413 # Free memory
- .set BDA_KEYFLAGS,0x417 # Keyboard shift-state flags
.set BDA_SCR,0x449 # Video mode
.set BDA_POS,0x450 # Cursor position
.set BDA_BOOT,0x472 # Boot howto flag
@@ -85,7 +93,6 @@
* Derivations, for brevity.
*/
.set _ESP0H,MEM_ESP0>>0x8 # Byte 1 of ESP0
- .set _ESP1H,MEM_ESP1>>0x8 # Byte 1 of ESP1
.set _TSSIO,MEM_MAP-MEM_TSS # TSS I/O base
.set _TSSLM,MEM_TSS_END-MEM_TSS # TSS limit
.set _IDTLM,MEM_TSS-MEM_IDT-1 # IDT limit
@@ -102,7 +109,7 @@
.byte 0xe # Header size
.ascii "BTX" # Magic
.byte 0x1 # Major version
- .byte 0x1 # Minor version
+ .byte 0x2 # Minor version
.byte BTX_FLAGS # Flags
.word PAG_CNT-MEM_ORG>>0xc # Paging control
.word break-start # Text size
@@ -123,13 +130,24 @@
*/
mov $MEM_IDT,%di # Memory to initialize
mov $(MEM_ORG-MEM_IDT)/2,%cx # Words to zero
- push %di # Save
rep # Zero-fill
stosw # memory
- pop %di # Restore
+/*
+ * Update real mode IDT for reflecting hardware interrupts.
+ */
+ mov $intr20,%bx # Address first handler
+ mov $0x10,%cx # Number of handlers
+ mov $0x20*4,%di # First real mode IDT entry
+init.0: mov %bx,(%di) # Store IP
+ inc %di # Address next
+ inc %di # entry
+ stosw # Store CS
+ add $4,%bx # Next handler
+ loop init.0 # Next IRQ
/*
* Create IDT.
*/
+ mov $MEM_IDT,%di
mov $idtctl,%si # Control string
init.1: lodsb # Get entry
cbw # count
@@ -155,7 +173,6 @@
*/
init.4: movb $_ESP0H,TSS_ESP0+1(%di) # Set ESP0
movb $SEL_SDATA,TSS_SS0(%di) # Set SS0
- movb $_ESP1H,TSS_ESP1+1(%di) # Set ESP1
movb $_TSSIO,TSS_MAP(%di) # Set I/O bit map base
/*
* Bring up the system.
@@ -281,10 +298,6 @@
retw # To caller
.code32
/*
- * Initiate return from V86 mode to user mode.
- */
-inthlt: hlt # To supervisor mode
-/*
* Exception jump table.
*/
intx00: push $0x0 # Int 0x0: #DE
@@ -310,18 +323,12 @@
push $0xc # Int 0xc: #SS
jmp except # Stack segment fault
push $0xd # Int 0xd: #GP
- jmp ex_v86 # General protection
+ jmp except # General protection
push $0xe # Int 0xe: #PF
jmp except # Page fault
intx10: push $0x10 # Int 0x10: #MF
jmp ex_noc # Floating-point error
/*
- * Handle #GP exception.
- */
-ex_v86: testb $0x2,0x12(%esp,1) # V86 mode?
- jz except # No
- jmp v86mon # To monitor
-/*
* Save a zero error code.
*/
ex_noc: pushl (%esp,1) # Duplicate int no
@@ -333,24 +340,17 @@
pushl %ds # Save
pushl %es # most
pusha # registers
- movb $0x6,%al # Push loop count
- testb $0x2,0x3a(%esp,1) # V86 mode?
- jnz except.1 # Yes
pushl %gs # Set GS
pushl %fs # Set FS
pushl %ds # Set DS
pushl %es # Set ES
- movb $0x2,%al # Push loop count
cmpw $SEL_SCODE,0x44(%esp,1) # Supervisor mode?
jne except.1 # No
pushl %ss # Set SS
- leal 0x50(%esp,1),%eax # Set
- pushl %eax # ESP
jmp except.2 # Join common code
-except.1: pushl 0x50(%esp,1) # Set GS, FS, DS, ES
- decb %al # (if V86 mode), and
- jne except.1 # SS, ESP
-except.2: push $SEL_SDATA # Set up
+except.1: pushl 0x50(%esp,1) # Set SS
+except.2: pushl 0x50(%esp,1) # Set ESP
+ push $SEL_SDATA # Set up
popl %ds # to
pushl %ds # address
popl %es # data
@@ -374,234 +374,6 @@
except.2a: jmp exit # Exit
except.3: leal 0x8(%esp,1),%esp # Discard err, int no
iret # From interrupt
-/*
- * Return to user mode from V86 mode.
- */
-intrtn: cld # String ops inc
- pushl %ds # Address
- popl %es # data
- leal 0x3c(%ebp),%edx # V86 Segment registers
- movl MEM_TSS+TSS_ESP1,%esi # Link stack pointer
- lodsl # INT_V86 args pointer
- movl %esi,%ebx # Saved exception frame
- testl %eax,%eax # INT_V86 args?
- jz intrtn.2 # No
- movl $MEM_USR,%edi # User base
- movl 0x1c(%esi),%ebx # User ESP
- movl %eax,(%edi,%ebx,1) # Restore to user stack
- leal 0x8(%edi,%eax,1),%edi # Arg segment registers
- testb $0x4,-0x6(%edi) # Return flags?
- jz intrtn.1 # No
- movl 0x30(%ebp),%eax # Get V86 flags
- movw %ax,0x18(%esi) # Set user flags
-intrtn.1: leal 0x10(%esi),%ebx # Saved exception frame
- xchgl %edx,%esi # Segment registers
- movb $0x4,%cl # Update seg regs
- rep # in INT_V86
- movsl # args
-intrtn.2: xchgl %edx,%esi # Segment registers
- leal 0x28(%ebp),%edi # Set up seg
- movb $0x4,%cl # regs for
- rep # later
- movsl # pop
- xchgl %ebx,%esi # Restore exception
- movb $0x5,%cl # frame to
- rep # supervisor
- movsl # stack
- movl %esi,MEM_TSS+TSS_ESP1 # Link stack pointer
- popa # Restore
- leal 0x8(%esp,1),%esp # Discard err, int no
- popl %es # Restore
- popl %ds # user
- popl %fs # segment
- popl %gs # registers
- iret # To user mode
-/*
- * V86 monitor.
- */
-v86mon: cld # String ops inc
- pushl $SEL_SDATA # Set up for
- popl %ds # flat addressing
- pusha # Save registers
- movl %esp,%ebp # Address stack frame
- movzwl 0x2c(%ebp),%edi # Load V86 CS
- shll $0x4,%edi # To linear
- movl 0x28(%ebp),%esi # Load V86 IP
- addl %edi,%esi # Code pointer
- xorl %ecx,%ecx # Zero
- movb $0x2,%cl # 16-bit operands
- xorl %eax,%eax # Zero
-v86mon.1: lodsb # Get opcode
- cmpb $0x66,%al # Operand size prefix?
- jne v86mon.2 # No
- movb $0x4,%cl # 32-bit operands
- jmp v86mon.1 # Continue
-v86mon.2: cmpb $0xf4,%al # HLT?
- jne v86mon.3 # No
- cmpl $inthlt+0x1,%esi # Is inthlt?
- jne v86mon.7 # No (ignore)
- jmp intrtn # Return to user mode
-v86mon.3: cmpb $0xf,%al # Prefixed instruction?
- jne v86mon.4 # No
- cmpb $0x09,(%esi) # Is it a WBINVD?
- je v86wbinvd # Yes
- cmpb $0x30,(%esi) # Is it a WRMSR?
- je v86wrmsr # Yes
- cmpb $0x32,(%esi) # Is it a RDMSR?
- je v86rdmsr # Yes
- cmpb $0x20,(%esi) # Is this a MOV reg,CRx?
- je v86mov # Yes
-v86mon.4: cmpb $0xfa,%al # CLI?
- je v86cli # Yes
- cmpb $0xfb,%al # STI?
- je v86sti # Yes
- cmpb $0xcc,%al # INT3?
- je v86mon.7 # Yes, ignore
- movzwl 0x38(%ebp),%ebx # Load V86 SS
- shll $0x4,%ebx # To offset
- pushl %ebx # Save
- addl 0x34(%ebp),%ebx # Add V86 SP
- movl 0x30(%ebp),%edx # Load V86 flags
- cmpb $0x9c,%al # PUSHF/PUSHFD?
- je v86pushf # Yes
- cmpb $0x9d,%al # POPF/POPFD?
- je v86popf # Yes
- cmpb $0xcd,%al # INT imm8?
- je v86intn # Yes
- cmpb $0xcf,%al # IRET/IRETD?
- je v86iret # Yes
- popl %ebx # Restore
- popa # Restore
- jmp except # Handle exception
-v86mon.5: movl %edx,0x30(%ebp) # Save V86 flags
-v86mon.6: popl %edx # V86 SS adjustment
- subl %edx,%ebx # Save V86
- movl %ebx,0x34(%ebp) # SP
-v86mon.7: subl %edi,%esi # From linear
- movl %esi,0x28(%ebp) # Save V86 IP
- popa # Restore
- leal 0x8(%esp,1),%esp # Discard int no, error
- iret # To V86 mode
-/*
- * Emulate MOV reg,CRx.
- */
-v86mov: movb 0x1(%esi),%bl # Fetch Mod R/M byte
- testb $0x10,%bl # Read CR2 or CR3?
- jnz v86mov.1 # Yes
- movl %cr0,%eax # Read CR0
- testb $0x20,%bl # Read CR4 instead?
- jz v86mov.2 # No
- movl %cr4,%eax # Read CR4
- jmp v86mov.2
-v86mov.1: movl %cr2,%eax # Read CR2
- testb $0x08,%bl # Read CR3 instead?
- jz v86mov.2 # No
- movl %cr3,%eax # Read CR3
-v86mov.2: andl $0x7,%ebx # Compute offset in
- shl $2,%ebx # frame of destination
- neg %ebx # register
- movl %eax,0x1c(%ebp,%ebx,1) # Store CR to reg
- incl %esi # Adjust IP
-/*
- * Return from emulating a 0x0f prefixed instruction
- */
-v86preret: incl %esi # Adjust IP
- jmp v86mon.7 # Finish up
-/*
- * Emulate WBINVD
- */
-v86wbinvd: wbinvd # Write back and invalidate
- # cache
- jmp v86preret # Finish up
-/*
- * Emulate WRMSR
- */
-v86wrmsr: movl 0x18(%ebp),%ecx # Get user's %ecx (MSR to write)
- movl 0x14(%ebp),%edx # Load the value
- movl 0x1c(%ebp),%eax # to write
- wrmsr # Write MSR
- jmp v86preret # Finish up
-/*
- * Emulate RDMSR
- */
-v86rdmsr: movl 0x18(%ebp),%ecx # MSR to read
- rdmsr # Read the MSR
- movl %eax,0x1c(%ebp) # Return the value of
- movl %edx,0x14(%ebp) # the MSR to the user
- jmp v86preret # Finish up
-/*
- * Emulate CLI.
- */
-v86cli: andb $~0x2,0x31(%ebp) # Clear IF
- jmp v86mon.7 # Finish up
-/*
- * Emulate STI.
- */
-v86sti: orb $0x2,0x31(%ebp) # Set IF
- jmp v86mon.7 # Finish up
-/*
- * Emulate PUSHF/PUSHFD.
- */
-v86pushf: subl %ecx,%ebx # Adjust SP
- cmpb $0x4,%cl # 32-bit
- je v86pushf.1 # Yes
- data16 # 16-bit
-v86pushf.1: movl %edx,(%ebx) # Save flags
- jmp v86mon.6 # Finish up
-/*
- * Emulate IRET/IRETD.
- */
-v86iret: movzwl (%ebx),%esi # Load V86 IP
- movzwl 0x2(%ebx),%edi # Load V86 CS
- leal 0x4(%ebx),%ebx # Adjust SP
- movl %edi,0x2c(%ebp) # Save V86 CS
- xorl %edi,%edi # No ESI adjustment
-/*
- * Emulate POPF/POPFD (and remainder of IRET/IRETD).
- */
-v86popf: cmpb $0x4,%cl # 32-bit?
- je v86popf.1 # Yes
- movl %edx,%eax # Initialize
- data16 # 16-bit
-v86popf.1: movl (%ebx),%eax # Load flags
- addl %ecx,%ebx # Adjust SP
- andl $V86_FLG,%eax # Merge
- andl $~V86_FLG,%edx # the
- orl %eax,%edx # flags
- jmp v86mon.5 # Finish up
-/*
- * trap int 15, function 87
- * reads %es:%si from saved registers on stack to find a GDT containing
- * source and destination locations
- * reads count of words from saved %cx
- * returns success by setting %ah to 0
- */
-int15_87: pushl %esi # Save
- pushl %edi # registers
- movl 0x3C(%ebp),%edi # Load ES
- movzwl 0x4(%ebp),%eax # Load user's SI
- shll $0x4,%edi # EDI = (ES << 4) +
- addl %eax,%edi # SI
- movl 0x11(%edi),%eax # Read base of
- movb 0x17(%edi),%al # GDT entry
- ror $8,%eax # for source
- xchgl %eax,%esi # into %esi
- movl 0x19(%edi),%eax # Read base of
- movb 0x1f(%edi),%al # GDT entry for
- ror $8,%eax # destination
- xchgl %eax,%edi # into %edi
- pushl %ds # Make:
- popl %es # es = ds
- movzwl 0x18(%ebp),%ecx # Get user's CX
- shll $0x1,%ecx # Convert count from words
- rep # repeat...
- movsb # perform copy.
- popl %edi # Restore
- popl %esi # registers
- movb $0x0,0x1d(%ebp) # set ah = 0 to indicate
- # success
- andb $0xfe,%dl # clear CF
- jmp v86mon.5 # Finish up
/*
* Reboot the machine by setting the reboot flag and exiting
@@ -610,37 +382,8 @@
jmp exit # Terminate BTX and reboot
/*
- * Emulate INT imm8... also make sure to check if it's int 15/87
+ * Protected Mode Hardware interrupt jump table.
*/
-v86intn: lodsb # Get int no
- cmpb $0x19,%al # is it int 19?
- je reboot # yes, reboot the machine
- cmpb $0x15,%al # is it int 15?
- jne v86intn.1 # no, skip parse
- cmpb $0x87,0x1d(%ebp) # is it the memcpy subfunction?
- je int15_87 # yes
- cmpw $0x4f53,0x1c(%ebp) # is it the delete key callout?
- jne v86intn.1 # no, handle the int normally
- movb BDA_KEYFLAGS,%ch # get the shift key state
- andb $0xc,%ch # mask off just Ctrl and Alt
- cmpb $0xc,%ch # are both Ctrl and Alt down?
- je reboot # yes, reboot the machine
-v86intn.1: subl %edi,%esi # From
- shrl $0x4,%edi # linear
- movw %dx,-0x2(%ebx) # Save flags
- movw %di,-0x4(%ebx) # Save CS
- leal -0x6(%ebx),%ebx # Adjust SP
- movw %si,(%ebx) # Save IP
- shll $0x2,%eax # Scale
- movzwl (%eax),%esi # Load IP
- movzwl 0x2(%eax),%edi # Load CS
- movl %edi,0x2c(%ebp) # Save CS
- xorl %edi,%edi # No ESI adjustment
- andb $~0x1,%dh # Clear TF
- jmp v86mon.5 # Finish up
-/*
- * Hardware interrupt jump table.
- */
intx20: push $0x8 # Int 0x20: IRQ0
jmp int_hw # V86 int 0x8
push $0x9 # Int 0x21: IRQ1
@@ -673,127 +416,239 @@
jmp int_hw # V86 int 0x76
push $0x77 # Int 0x2f: IRQ15
jmp int_hw # V86 int 0x77
+
/*
- * Reflect hardware interrupts.
+ * Invoke real mode interrupt/function call from user mode with arguments.
*/
-int_hw: testb $0x2,0xe(%esp,1) # V86 mode?
- jz intusr # No
- pushl $SEL_SDATA # Address
- popl %ds # data
- xchgl %eax,(%esp,1) # Swap EAX, int no
- pushl %ebp # Address
- movl %esp,%ebp # stack frame
- pushl %ebx # Save
- shll $0x2,%eax # Get int
- movl (%eax),%eax # vector
- subl $0x6,0x14(%ebp) # Adjust V86 ESP
- movzwl 0x18(%ebp),%ebx # V86 SS
- shll $0x4,%ebx # * 0x10
- addl 0x14(%ebp),%ebx # + V86 ESP
- xchgw %ax,0x8(%ebp) # Swap V86 IP
- rorl $0x10,%eax # Swap words
- xchgw %ax,0xc(%ebp) # Swap V86 CS
- roll $0x10,%eax # Swap words
- movl %eax,(%ebx) # CS:IP for IRET
- movl 0x10(%ebp),%eax # V86 flags
- movw %ax,0x4(%ebx) # Flags for IRET
- andb $~0x3,0x11(%ebp) # Clear IF, TF
- popl %ebx # Restore
- popl %ebp # saved
- popl %eax # registers
- iret # To V86 mode
+intx31: pushl $-1 # Dummy int no for btx_v86
/*
- * Invoke V86 interrupt from user mode, with arguments.
+ * Invoke real mode interrupt/function call from protected mode.
+ *
+ * We place a trampoline on the user stack that will return to rret_tramp
+ * which will reenter protected mode and then finally return to the user
+ * client.
+ *
+ * Kernel frame %esi points to: Real mode stack frame at MEM_ESPR:
+ *
+ * -0x00 user %ss -0x04 kernel %esp (with full frame)
+ * -0x04 user %esp -0x08 btx_v86 pointer
+ * -0x08 user %eflags -0x0c flags (only used if interrupt)
+ * -0x0c user %cs -0x10 real mode CS:IP return trampoline
+ * -0x10 user %eip -0x12 real mode flags
+ * -0x14 int no -0x16 real mode CS:IP (target)
+ * -0x18 %eax
+ * -0x1c %ecx
+ * -0x20 %edx
+ * -0x24 %ebx
+ * -0x28 %esp
+ * -0x2c %ebp
+ * -0x30 %esi
+ * -0x34 %edi
+ * -0x38 %gs
+ * -0x3c %fs
+ * -0x40 %ds
+ * -0x44 %es
*/
-intx31: stc # Have btx_v86
- pushl %eax # Missing int no
-/*
- * Invoke V86 interrupt from user mode.
- */
-intusr: std # String ops dec
- pushl %eax # Expand
- pushl %eax # stack
- pushl %eax # frame
- pusha # Save
+int_hw: cld # String ops inc
+ pusha # Save gp regs
pushl %gs # Save
- movl %esp,%eax # seg regs
- pushl %fs # and
- pushl %ds # point
- pushl %es # to them
+ pushl %fs # seg
+ pushl %ds # regs
+ pushl %es
push $SEL_SDATA # Set up
popl %ds # to
pushl %ds # address
popl %es # data
+ leal 0x44(%esp,1),%esi # Base of frame
+ movl -0x14(%esi),%eax # Get Int no
+ cmpl $-1,%eax # Hardware interrupt?
+ jne intusr.2 # Yes
+/*
+ * v86 calls save the btx_v86 pointer on the real mode stack and read the
+ * address and flags from the btx_v86 structure.
+ */
movl $MEM_USR,%ebx # User base
movl %ebx,%edx # address
- jc intusr.1 # If btx_v86
- xorl %edx,%edx # Control flags
- xorl %ebp,%ebp # btx_v86 pointer
-intusr.1: leal 0x50(%esp,1),%esi # Base of frame
- pushl %esi # Save
addl -0x4(%esi),%ebx # User ESP
- movl MEM_TSS+TSS_ESP1,%edi # Link stack pointer
- leal -0x4(%edi),%edi # Adjust for push
- xorl %ecx,%ecx # Zero
- movb $0x5,%cl # Push exception
- rep # frame on
- movsl # link stack
- xchgl %eax,%esi # Saved seg regs
- movl 0x40(%esp,1),%eax # Get int no
- testl %edx,%edx # Have btx_v86?
- jz intusr.2 # No
movl (%ebx),%ebp # btx_v86 pointer
- movb $0x4,%cl # Count
- addl %ecx,%ebx # Adjust for pop
- rep # Push saved seg regs
- movsl # on link stack
addl %ebp,%edx # Flatten btx_v86 ptr
- leal 0x14(%edx),%esi # Seg regs pointer
- movl 0x4(%edx),%eax # Get int no/address
- movzwl 0x2(%edx),%edx # Get control flags
-intusr.2: movl %ebp,(%edi) # Push btx_v86 and
- movl %edi,MEM_TSS+TSS_ESP1 # save link stack ptr
- popl %edi # Base of frame
- xchgl %eax,%ebp # Save intno/address
- movl 0x48(%esp,1),%eax # Get flags
- testb $0x2,%dl # Simulate CALLF?
- jnz intusr.3 # Yes
- decl %ebx # Push flags
- decl %ebx # on V86
- movw %ax,(%ebx) # stack
-intusr.3: movb $0x4,%cl # Count
- subl %ecx,%ebx # Push return address
- movl $inthlt,(%ebx) # on V86 stack
- rep # Copy seg regs to
- movsl # exception frame
- xchgl %eax,%ecx # Save flags
- movl %ebx,%eax # User ESP
- subl $V86_STK,%eax # Less bytes
- ja intusr.4 # to
- xorl %eax,%eax # keep
-intusr.4: shrl $0x4,%eax # Gives segment
- stosl # Set SS
- shll $0x4,%eax # To bytes
- xchgl %eax,%ebx # Swap
- subl %ebx,%eax # Gives offset
- stosl # Set ESP
- xchgl %eax,%ecx # Get flags
- btsl $0x11,%eax # Set VM
- andb $~0x1,%ah # Clear TF
- stosl # Set EFL
- xchgl %eax,%ebp # Get int no/address
- testb $0x1,%dl # Address?
- jnz intusr.5 # Yes
+ movl %edx,MEM_ESPR-0x08 # Save btx_v86 ptr
+ movl -0x08(%esi),%ebx # Pass user flags to
+ movw %bx,MEM_ESPR-0x12 # real mode target
+ movl V86_ADDR(%edx),%eax # Get int no/address
+ movl V86_CTL(%edx),%edx # Get control flags
+ jmp intusr.3 # Skip hardware interrupt
+/*
+ * Hardware interrupts store a NULL btx_v86 pointer and use the address
+ * (interrupt number) from the stack with empty flags. Also, we clear
+ * the segment registers for the interrupt handler and ensure interrupts
+ * are disabled when the interrupt handler is invoked.
+ */
+intusr.2: xorl %edx,%edx # Control flags
+ movl %edx,MEM_ESPR-0x08 # NULL btx_v86 ptr
+ movl %edx,-0x38(%esi) # Real mode %gs of 0
+ movl %edx,-0x3c(%esi) # Real mode %fs of 0
+ movl %edx,-0x40(%esi) # Real mode %ds of 0
+ movl %edx,-0x44(%esi) # Real mode %es of 0
+ movl -0x08(%esi),%ebx # Pass user flags with
+ andl $~0x200,%ebx # interrupts disabled
+ movw %bx,MEM_ESPR-0x12 # to real mode target
+/*
+ * %eax now holds either the interrupt number or segment:offset of function.
+ * %edx now holds the V86F_* flags.
+ */
+intusr.3: testl $V86F_ADDR,%edx # Segment:offset?
+ jnz intusr.4 # Yes
shll $0x2,%eax # Scale
movl (%eax),%eax # Load int vector
-intusr.5: movl %eax,%ecx # Save
- shrl $0x10,%eax # Gives segment
- stosl # Set CS
- movw %cx,%ax # Restore
- stosl # Set EIP
- leal 0x10(%esp,1),%esp # Discard seg regs
- popa # Restore
- iret # To V86 mode
+ jmp intusr.5 # Skip CALLF test
+intusr.4: testl $V86F_CALLF,%edx # Far call?
+ jnz intusr.5 # Ok
+ movl %edx,0x30(%esp,1) # Place VM86 flags in int no
+ movl $badvm86,%esi # Display bad
+ call putstr # VM86 call
+ popl %es # Restore
+ popl %ds # seg
+ popl %fs # regs
+ popl %gs
+ popal # Restore gp regs
+ jmp ex_noc # Panic
+/*
+ * If this is a v86 call, copy the seg regs out of the btx_v86 structure.
+ */
+intusr.5: movl MEM_ESPR-0x08,%ecx # Get btx_v86 ptr
+ jecxz intusr.6 # Skip for hardware ints
+ leal -0x44(%esi),%edi # %edi => kernel stack seg regs
+ pushl %esi # Save
+ leal V86_ES(%ecx),%esi # %esi => btx_v86 seg regs
+ movl $4,%ecx # Copy seg regs
+ rep # from btx_v86
+ movsl # to kernel stack
+ popl %esi # Restore
+intusr.6: movl %esp,MEM_ESPR-0x04 # Save kernel stack pointer
+ movl -0x08(%esi),%ebx # Copy user flags to real
+ movl %ebx,MEM_ESPR-0x0c # mode return trampoline
+ movl $rret_tramp,%ebx # Set return trampoline
+ movl %ebx,MEM_ESPR-0x10 # CS:IP
+ movl %eax,MEM_ESPR-0x16 # Real mode target CS:IP
+ ljmpw $SEL_RCODE,$intusr.7 # Change to 16-bit segment
+ .code16
+intusr.7: movl %cr0,%eax # Leave
+ dec %al # protected
+ movl %eax,%cr0 # mode
+ ljmpw $0x0,$intusr.8
+intusr.8: xorw %ax,%ax # Reset %ds
+ movw %ax,%ds # and
+ movw %ax,%ss # %ss
+ lidt ivtdesc # Set IVT
+ popl %es # Restore
+ popl %ds # seg
+ popl %fs # regs
+ popl %gs
+ popal # Restore gp regs
+ movw $MEM_ESPR-0x16,%sp # Switch to real mode stack
+ iret # Call target routine
+/*
+ * For the return to real mode we setup a stack frame like this on the real
+ * mode stack. Note that callf calls won't pop off the flags, but we just
+ * ignore that by repositioning %sp to be just above the btx_v86 pointer
+ * so it is aligned. The stack is relative to MEM_ESPR.
+ *
+ * -0x04 kernel %esp
+ * -0x08 btx_v86
+ * -0x0c %eax
+ * -0x10 %ecx
+ * -0x14 %edx
+ * -0x18 %ebx
+ * -0x1c %esp
+ * -0x20 %ebp
+ * -0x24 %esi
+ * -0x28 %edi
+ * -0x2c %gs
+ * -0x30 %fs
+ * -0x34 %ds
+ * -0x38 %es
+ * -0x3c %eflags
+ */
+rret_tramp: movw $MEM_ESPR-0x08,%sp # Reset stack pointer
+ pushal # Save gp regs
+ pushl %gs # Save
+ pushl %fs # seg
+ pushl %ds # regs
+ pushl %es
+ pushfl # Save %eflags
+ cli # Disable interrupts
+ std # String ops dec
+ xorw %ax,%ax # Reset seg
+ movw %ax,%ds # regs
+ movw %ax,%es # (%ss is already 0)
+ lidt idtdesc # Set IDT
+ lgdt gdtdesc # Set GDT
+ mov %cr0,%eax # Switch to protected
+ inc %ax # mode
+ mov %eax,%cr0 #
+ ljmp $SEL_SCODE,$rret_tramp.1 # To 32-bit code
+ .code32
+rret_tramp.1: xorl %ecx,%ecx # Zero
+ movb $SEL_SDATA,%cl # Setup
+ movw %cx,%ss # 32-bit
+ movw %cx,%ds # seg
+ movw %cx,%es # regs
+ movl MEM_ESPR-0x04,%esp # Switch to kernel stack
+ leal 0x44(%esp,1),%esi # Base of frame
+ andb $~0x2,tss_desc+0x5 # Clear TSS busy
+ movb $SEL_TSS,%cl # Set task
+ ltr %cx # register
+/*
+ * Now we are back in protected mode. Copy the registers off of the real
+ * mode stack onto the kernel stack. Also, initialize all the seg regs on
+ * the kernel stack.
+ *
+ * Note that the %esp in the kernel stack after this is garbage, but popa
+ * ignores it, so we don't have to fix it up.
+ */
+ leal -0x18(%esi),%edi # Kernel stack GP regs
+ pushl %esi # Save
+ movl $MEM_ESPR-0x0c,%esi # Real mode stack GP regs
+ movl $8,%ecx # Copy GP regs from
+ rep # real mode stack
+ movsl # to kernel stack
+ popl %esi # Restore
+ movl $SEL_UDATA,%eax # Selector for data seg regs
+ movl $4,%ecx # Initialize %ds,
+ rep # %es, %fs, and
+ stosl # %gs
+/*
+ * If this was a V86 call, copy the saved seg regs on the real mode stack
+ * back over to the btx_v86 structure. Also, conditionally update the saved
+ * eflags on the kernel stack based on the flags from the user.
+ */
+ movl MEM_ESPR-0x08,%ecx # Get btx_v86 ptr
+ jecxz rret_tramp.3 # Skip for hardware ints
+ leal V86_GS(%ecx),%edi # %edi => btx_v86 seg regs
+ pushl %esi # Save
+ leal MEM_ESPR-0x2c,%esi # %esi => real mode seg regs
+ xchgl %ecx,%edx # Save btx_v86 ptr
+ movl $4,%ecx # Copy seg regs
+ rep # from real mode stack
+ movsl # to btx_v86
+ popl %esi # Restore
+ movl V86_CTL(%edx),%edx # Read V86 control flags
+ testl $V86F_FLAGS,%edx # User wants flags?
+ jz rret_tramp.3 # No
+ movl MEM_ESPR-0x3c,%eax # Read real mode flags
+ movw %ax,-0x08(%esi) # Update user flags (low 16)
+/*
+ * Return to the user task
+ */
+rret_tramp.3: popl %es # Restore
+ popl %ds # seg
+ popl %fs # regs
+ popl %gs
+ popal # Restore gp regs
+ addl $4,%esp # Discard int no
+ iret # Return to user mode
+
/*
* System Call.
*/
@@ -1035,6 +890,61 @@
ret # To caller
#endif
+ .code16
+/*
+ * Real Mode Hardware interrupt jump table.
+ */
+intr20: push $0x8 # Int 0x20: IRQ0
+ jmp int_hwr # V86 int 0x8
+ push $0x9 # Int 0x21: IRQ1
+ jmp int_hwr # V86 int 0x9
+ push $0xa # Int 0x22: IRQ2
+ jmp int_hwr # V86 int 0xa
+ push $0xb # Int 0x23: IRQ3
+ jmp int_hwr # V86 int 0xb
+ push $0xc # Int 0x24: IRQ4
+ jmp int_hwr # V86 int 0xc
+ push $0xd # Int 0x25: IRQ5
+ jmp int_hwr # V86 int 0xd
+ push $0xe # Int 0x26: IRQ6
+ jmp int_hwr # V86 int 0xe
+ push $0xf # Int 0x27: IRQ7
+ jmp int_hwr # V86 int 0xf
+ push $0x70 # Int 0x28: IRQ8
+ jmp int_hwr # V86 int 0x70
+ push $0x71 # Int 0x29: IRQ9
+ jmp int_hwr # V86 int 0x71
+ push $0x72 # Int 0x2a: IRQ10
+ jmp int_hwr # V86 int 0x72
+ push $0x73 # Int 0x2b: IRQ11
+ jmp int_hwr # V86 int 0x73
+ push $0x74 # Int 0x2c: IRQ12
+ jmp int_hwr # V86 int 0x74
+ push $0x75 # Int 0x2d: IRQ13
+ jmp int_hwr # V86 int 0x75
+ push $0x76 # Int 0x2e: IRQ14
+ jmp int_hwr # V86 int 0x76
+ push $0x77 # Int 0x2f: IRQ15
+ jmp int_hwr # V86 int 0x77
+/*
+ * Reflect hardware interrupts in real mode.
+ */
+int_hwr: push %ax # Save
+ push %ds # Save
+ push %bp # Save
+ mov %sp,%bp # Address stack frame
+ xchg %bx,6(%bp) # Swap BX, int no
+ xor %ax,%ax # Set %ds:%bx to
+ shl $2,%bx # point to
+ mov %ax,%ds # IDT entry
+ mov (%bx),%ax # Load IP
+ mov 2(%bx),%bx # Load CS
+ xchg %ax,4(%bp) # Swap saved %ax,%bx with
+ xchg %bx,6(%bp) # CS:IP of handler
+ pop %bp # Restore
>>> TRUNCATED FOR MAIL (1000 lines) <<<
More information about the p4-projects
mailing list