1*433d6423SLionel Sambuc/* sections */ 2*433d6423SLionel Sambuc 3*433d6423SLionel Sambuc 4*433d6423SLionel Sambuc#include <minix/config.h> 5*433d6423SLionel Sambuc#include <minix/const.h> 6*433d6423SLionel Sambuc#include <machine/asm.h> 7*433d6423SLionel Sambuc#include <machine/interrupt.h> 8*433d6423SLionel Sambuc#include <machine/vm.h> 9*433d6423SLionel Sambuc#include "archconst.h" 10*433d6423SLionel Sambuc#include "kernel/const.h" 11*433d6423SLionel Sambuc#include "sconst.h" 12*433d6423SLionel Sambuc#include <machine/multiboot.h> 13*433d6423SLionel Sambuc 14*433d6423SLionel Sambuc 15*433d6423SLionel Sambuc/* Easy way to make functions */ 16*433d6423SLionel Sambuc 17*433d6423SLionel Sambuc/* Make a function of the form func(arg) */ 18*433d6423SLionel Sambuc 19*433d6423SLionel Sambuc#define STACKARG 8(%ebp) 20*433d6423SLionel Sambuc 21*433d6423SLionel Sambuc#define ARG_EAX_ACTION(FUNCTION, ACTION) ;\ 22*433d6423SLionel SambucENTRY(FUNCTION) ;\ 23*433d6423SLionel Sambuc push %ebp ;\ 24*433d6423SLionel Sambuc mov %esp, %ebp ;\ 25*433d6423SLionel Sambuc mov STACKARG, %eax ;\ 26*433d6423SLionel Sambuc ACTION ;\ 27*433d6423SLionel Sambuc pop %ebp ;\ 28*433d6423SLionel Sambuc ret 29*433d6423SLionel Sambuc 30*433d6423SLionel Sambuc/* Make a function of the form ret = func() */ 31*433d6423SLionel Sambuc#define ARG_EAX_RETURN(FUNCTION, EXPR) ;\ 32*433d6423SLionel SambucENTRY(FUNCTION) ;\ 33*433d6423SLionel Sambuc push %ebp ;\ 34*433d6423SLionel Sambuc mov %esp, %ebp ;\ 35*433d6423SLionel Sambuc mov EXPR, %eax ;\ 36*433d6423SLionel Sambuc pop %ebp ;\ 37*433d6423SLionel Sambuc ret 38*433d6423SLionel Sambuc 39*433d6423SLionel Sambuc/* Make a function of the form ret = func() */ 40*433d6423SLionel Sambuc#define ARG_EAX_SET(FUNCTION, DEST) ;\ 41*433d6423SLionel SambucENTRY(FUNCTION) ;\ 42*433d6423SLionel Sambuc push %ebp ;\ 43*433d6423SLionel Sambuc mov %esp, %ebp ;\ 44*433d6423SLionel Sambuc mov STACKARG, %eax ;\ 45*433d6423SLionel Sambuc mov %eax, DEST ;\ 46*433d6423SLionel Sambuc jmp 0f /* a jump is required for some sets */ ;\ 47*433d6423SLionel Sambuc0: pop %ebp ;\ 48*433d6423SLionel Sambuc ret 49*433d6423SLionel Sambuc 50*433d6423SLionel Sambuc/* Make a function of the form ret = func() */ 51*433d6423SLionel Sambuc#define ARG_AX_SET(FUNCTION, DEST) ;\ 52*433d6423SLionel SambucENTRY(FUNCTION) ;\ 53*433d6423SLionel Sambuc push %ebp ;\ 54*433d6423SLionel Sambuc mov %esp, %ebp ;\ 55*433d6423SLionel Sambuc mov STACKARG, %eax ;\ 56*433d6423SLionel Sambuc mov %ax, DEST ;\ 57*433d6423SLionel Sambuc jmp 0f /* a jump is required for some sets */ ;\ 58*433d6423SLionel Sambuc0: pop %ebp ;\ 59*433d6423SLionel Sambuc ret 60*433d6423SLionel Sambuc 61*433d6423SLionel Sambuc/* 62*433d6423SLionel Sambuc * This file contains a number of assembly code utility routines needed by the 63*433d6423SLionel Sambuc * kernel. 64*433d6423SLionel Sambuc */ 65*433d6423SLionel Sambuc 66*433d6423SLionel SambucENTRY(__main) 67*433d6423SLionel Sambuc ret 68*433d6423SLionel Sambuc 69*433d6423SLionel Sambuc 70*433d6423SLionel Sambuc/*===========================================================================*/ 71*433d6423SLionel Sambuc/* phys_insw */ 72*433d6423SLionel Sambuc/*===========================================================================*/ 73*433d6423SLionel Sambuc/* 74*433d6423SLionel Sambuc * PUBLIC void phys_insw(Port_t port, phys_bytes buf, size_t count); 75*433d6423SLionel Sambuc * Input an array from an I/O port. Absolute address version of insw(). 76*433d6423SLionel Sambuc */ 77*433d6423SLionel Sambuc/* transfer data from (disk controller) port to memory */ 78*433d6423SLionel SambucENTRY(phys_insw) 79*433d6423SLionel Sambuc push %ebp 80*433d6423SLionel Sambuc mov %esp, %ebp 81*433d6423SLionel Sambuc cld 82*433d6423SLionel Sambuc push %edi 83*433d6423SLionel Sambuc 84*433d6423SLionel Sambuc mov 8(%ebp), %edx /* port to read from */ 85*433d6423SLionel Sambuc mov 12(%ebp), %edi /* destination addr */ 86*433d6423SLionel Sambuc mov 16(%ebp), %ecx /* byte count */ 87*433d6423SLionel Sambuc shr $1, %ecx /* word count */ 88*433d6423SLionel Sambuc rep insw /* input many words */ 89*433d6423SLionel Sambuc pop %edi 90*433d6423SLionel Sambuc pop %ebp 91*433d6423SLionel Sambuc ret 92*433d6423SLionel Sambuc 93*433d6423SLionel Sambuc 94*433d6423SLionel Sambuc/*===========================================================================*/ 95*433d6423SLionel Sambuc/* phys_insb */ 96*433d6423SLionel Sambuc/*===========================================================================*/ 97*433d6423SLionel Sambuc/* 98*433d6423SLionel Sambuc * PUBLIC void phys_insb(Port_t port, phys_bytes buf, size_t count); 99*433d6423SLionel Sambuc * Input an array from an I/O port. Absolute address version of insb(). 100*433d6423SLionel Sambuc */ 101*433d6423SLionel Sambuc/* transfer data from (disk controller) port to memory byte by byte */ 102*433d6423SLionel SambucENTRY(phys_insb) 103*433d6423SLionel Sambuc push %ebp 104*433d6423SLionel Sambuc mov %esp, %ebp 105*433d6423SLionel Sambuc cld 106*433d6423SLionel Sambuc push %edi 107*433d6423SLionel Sambuc 108*433d6423SLionel Sambuc mov 8(%ebp), %edx /* port to read from */ 109*433d6423SLionel Sambuc mov 12(%ebp), %edi /* destination addr */ 110*433d6423SLionel Sambuc mov 16(%ebp), %ecx /* byte count */ 111*433d6423SLionel Sambuc rep insb /* input many bytes */ 112*433d6423SLionel Sambuc pop %edi 113*433d6423SLionel Sambuc pop %ebp 114*433d6423SLionel Sambuc ret 115*433d6423SLionel Sambuc 116*433d6423SLionel Sambuc 117*433d6423SLionel Sambuc/*===========================================================================*/ 118*433d6423SLionel Sambuc/* phys_outsw */ 119*433d6423SLionel Sambuc/*===========================================================================*/ 120*433d6423SLionel Sambuc/* 121*433d6423SLionel Sambuc * PUBLIC void phys_outsw(Port_t port, phys_bytes buf, size_t count); 122*433d6423SLionel Sambuc * Output an array to an I/O port. Absolute address version of outsw(). 123*433d6423SLionel Sambuc */ 124*433d6423SLionel Sambuc/* transfer data from memory to (disk controller) port */ 125*433d6423SLionel SambucENTRY(phys_outsw) 126*433d6423SLionel Sambuc push %ebp 127*433d6423SLionel Sambuc mov %esp, %ebp 128*433d6423SLionel Sambuc cld 129*433d6423SLionel Sambuc push %esi 130*433d6423SLionel Sambuc 131*433d6423SLionel Sambuc mov 8(%ebp), %edx /* port to write to */ 132*433d6423SLionel Sambuc mov 12(%ebp), %esi /* source addr */ 133*433d6423SLionel Sambuc mov 16(%ebp), %ecx /* byte count */ 134*433d6423SLionel Sambuc shr $1, %ecx /* word count */ 135*433d6423SLionel Sambuc rep outsw /* output many words */ 136*433d6423SLionel Sambuc pop %esi 137*433d6423SLionel Sambuc pop %ebp 138*433d6423SLionel Sambuc ret 139*433d6423SLionel Sambuc 140*433d6423SLionel Sambuc 141*433d6423SLionel Sambuc/*===========================================================================*/ 142*433d6423SLionel Sambuc/* phys_outsb */ 143*433d6423SLionel Sambuc/*===========================================================================*/ 144*433d6423SLionel Sambuc/* 145*433d6423SLionel Sambuc * PUBLIC void phys_outsb(Port_t port, phys_bytes buf, size_t count); 146*433d6423SLionel Sambuc * Output an array to an I/O port. Absolute address version of outsb(). 147*433d6423SLionel Sambuc */ 148*433d6423SLionel Sambuc/* transfer data from memory to (disk controller) port byte by byte */ 149*433d6423SLionel SambucENTRY(phys_outsb) 150*433d6423SLionel Sambuc push %ebp 151*433d6423SLionel Sambuc mov %esp, %ebp 152*433d6423SLionel Sambuc cld 153*433d6423SLionel Sambuc push %esi 154*433d6423SLionel Sambuc 155*433d6423SLionel Sambuc mov 8(%ebp), %edx /* port to write to */ 156*433d6423SLionel Sambuc mov 12(%ebp), %esi /* source addr */ 157*433d6423SLionel Sambuc mov 16(%ebp), %ecx /* byte count */ 158*433d6423SLionel Sambuc rep outsb /* output many bytes */ 159*433d6423SLionel Sambuc pop %esi 160*433d6423SLionel Sambuc pop %ebp 161*433d6423SLionel Sambuc ret 162*433d6423SLionel Sambuc 163*433d6423SLionel Sambuc 164*433d6423SLionel Sambuc/*===========================================================================*/ 165*433d6423SLionel Sambuc/* phys_copy */ 166*433d6423SLionel Sambuc/*===========================================================================*/ 167*433d6423SLionel Sambuc/* 168*433d6423SLionel Sambuc * PUBLIC phys_bytes phys_copy(phys_bytes source, phys_bytes destination, 169*433d6423SLionel Sambuc * phys_bytes bytecount); 170*433d6423SLionel Sambuc * Copy a block of data from anywhere to anywhere in physical memory. 171*433d6423SLionel Sambuc */ 172*433d6423SLionel Sambuc/* es edi esi eip src dst len */ 173*433d6423SLionel SambucENTRY(phys_copy) 174*433d6423SLionel Sambuc push %ebp 175*433d6423SLionel Sambuc mov %esp, %ebp 176*433d6423SLionel Sambuc 177*433d6423SLionel Sambuc cld 178*433d6423SLionel Sambuc push %esi 179*433d6423SLionel Sambuc push %edi 180*433d6423SLionel Sambuc 181*433d6423SLionel Sambuc mov 8(%ebp), %esi 182*433d6423SLionel Sambuc mov 12(%ebp), %edi 183*433d6423SLionel Sambuc mov 16(%ebp), %eax 184*433d6423SLionel Sambuc 185*433d6423SLionel Sambuc cmp $10, %eax /* avoid align overhead for small counts */ 186*433d6423SLionel Sambuc jb pc_small 187*433d6423SLionel Sambuc mov %esi, %ecx /* align source, hope target is too */ 188*433d6423SLionel Sambuc neg %ecx 189*433d6423SLionel Sambuc and $3, %ecx /* count for alignment */ 190*433d6423SLionel Sambuc sub %ecx, %eax 191*433d6423SLionel Sambuc 192*433d6423SLionel Sambuc rep movsb (%esi), (%edi) 193*433d6423SLionel Sambuc mov %eax, %ecx 194*433d6423SLionel Sambuc shr $2, %ecx /* count of dwords */ 195*433d6423SLionel Sambuc 196*433d6423SLionel Sambuc rep movsl (%esi), (%edi) 197*433d6423SLionel Sambuc and $3, %eax 198*433d6423SLionel Sambucpc_small: 199*433d6423SLionel Sambuc xchg %eax, %ecx /* remainder */ 200*433d6423SLionel Sambuc 201*433d6423SLionel Sambuc rep movsb (%esi), (%edi) 202*433d6423SLionel Sambuc 203*433d6423SLionel Sambuc mov $0, %eax /* 0 means: no fault */ 204*433d6423SLionel SambucLABEL(phys_copy_fault) /* kernel can send us here */ 205*433d6423SLionel Sambuc pop %edi 206*433d6423SLionel Sambuc pop %esi 207*433d6423SLionel Sambuc pop %ebp 208*433d6423SLionel Sambuc ret 209*433d6423SLionel Sambuc 210*433d6423SLionel SambucLABEL(phys_copy_fault_in_kernel) /* kernel can send us here */ 211*433d6423SLionel Sambuc pop %edi 212*433d6423SLionel Sambuc pop %esi 213*433d6423SLionel Sambuc pop %ebp 214*433d6423SLionel Sambuc mov %cr2, %eax 215*433d6423SLionel Sambuc ret 216*433d6423SLionel Sambuc 217*433d6423SLionel Sambuc 218*433d6423SLionel Sambuc/*===========================================================================*/ 219*433d6423SLionel Sambuc/* copy_msg_from_user */ 220*433d6423SLionel Sambuc/*===========================================================================*/ 221*433d6423SLionel Sambuc/* 222*433d6423SLionel Sambuc * int copy_msg_from_user(message * user_mbuf, message * dst); 223*433d6423SLionel Sambuc * 224*433d6423SLionel Sambuc * Copies a message of 64 bytes from user process space to a kernel buffer. This 225*433d6423SLionel Sambuc * function assumes that the process address space is installed (cr3 loaded). 226*433d6423SLionel Sambuc * 227*433d6423SLionel Sambuc * This function from the callers point of view either succeeds or returns an 228*433d6423SLionel Sambuc * error which gives the caller a chance to respond accordingly. In fact it 229*433d6423SLionel Sambuc * either succeeds or if it generates a pagefault, general protection or other 230*433d6423SLionel Sambuc * exception, the trap handler has to redirect the execution to 231*433d6423SLionel Sambuc * __user_copy_msg_pointer_failure where the error is reported to the caller 232*433d6423SLionel Sambuc * without resolving the pagefault. It is not kernel's problem to deal with 233*433d6423SLionel Sambuc * wrong pointers from userspace and the caller should return an error to 234*433d6423SLionel Sambuc * userspace as if wrong values or request were passed to the kernel 235*433d6423SLionel Sambuc */ 236*433d6423SLionel SambucENTRY(copy_msg_from_user) 237*433d6423SLionel Sambuc /* load the source pointer */ 238*433d6423SLionel Sambuc mov 4(%esp), %ecx 239*433d6423SLionel Sambuc /* load the destination pointer */ 240*433d6423SLionel Sambuc mov 8(%esp), %edx 241*433d6423SLionel Sambuc 242*433d6423SLionel Sambuc/* mov 0*4(%ecx), %eax 243*433d6423SLionel Sambuc mov %eax, 0*4(%edx) */ 244*433d6423SLionel Sambuc mov 1*4(%ecx), %eax 245*433d6423SLionel Sambuc mov %eax, 1*4(%edx) 246*433d6423SLionel Sambuc mov 2*4(%ecx), %eax 247*433d6423SLionel Sambuc mov %eax, 2*4(%edx) 248*433d6423SLionel Sambuc mov 3*4(%ecx), %eax 249*433d6423SLionel Sambuc mov %eax, 3*4(%edx) 250*433d6423SLionel Sambuc mov 4*4(%ecx), %eax 251*433d6423SLionel Sambuc mov %eax, 4*4(%edx) 252*433d6423SLionel Sambuc mov 5*4(%ecx), %eax 253*433d6423SLionel Sambuc mov %eax, 5*4(%edx) 254*433d6423SLionel Sambuc mov 6*4(%ecx), %eax 255*433d6423SLionel Sambuc mov %eax, 6*4(%edx) 256*433d6423SLionel Sambuc mov 7*4(%ecx), %eax 257*433d6423SLionel Sambuc mov %eax, 7*4(%edx) 258*433d6423SLionel Sambuc mov 8*4(%ecx), %eax 259*433d6423SLionel Sambuc mov %eax, 8*4(%edx) 260*433d6423SLionel Sambuc 261*433d6423SLionel Sambuc mov 9*4(%ecx), %eax 262*433d6423SLionel Sambuc mov %eax, 9*4(%edx) 263*433d6423SLionel Sambuc mov 10*4(%ecx), %eax 264*433d6423SLionel Sambuc mov %eax, 10*4(%edx) 265*433d6423SLionel Sambuc mov 11*4(%ecx), %eax 266*433d6423SLionel Sambuc mov %eax, 11*4(%edx) 267*433d6423SLionel Sambuc mov 12*4(%ecx), %eax 268*433d6423SLionel Sambuc mov %eax, 12*4(%edx) 269*433d6423SLionel Sambuc mov 13*4(%ecx), %eax 270*433d6423SLionel Sambuc mov %eax, 13*4(%edx) 271*433d6423SLionel Sambuc mov 14*4(%ecx), %eax 272*433d6423SLionel Sambuc mov %eax, 14*4(%edx) 273*433d6423SLionel Sambuc mov 15*4(%ecx), %eax 274*433d6423SLionel Sambuc mov %eax, 15*4(%edx) 275*433d6423SLionel Sambuc 276*433d6423SLionel SambucLABEL(__copy_msg_from_user_end) 277*433d6423SLionel Sambuc movl $0, %eax 278*433d6423SLionel Sambuc ret 279*433d6423SLionel Sambuc 280*433d6423SLionel Sambuc/*===========================================================================*/ 281*433d6423SLionel Sambuc/* copy_msg_to_user */ 282*433d6423SLionel Sambuc/*===========================================================================*/ 283*433d6423SLionel Sambuc/* 284*433d6423SLionel Sambuc * void copy_msg_to_user(message * src, message * user_mbuf); 285*433d6423SLionel Sambuc * 286*433d6423SLionel Sambuc * Copies a message of 64 bytes to user process space from a kernel buffer. 287*433d6423SLionel Sambuc * 288*433d6423SLionel Sambuc * All the other copy_msg_from_user() comments apply here as well! 289*433d6423SLionel Sambuc */ 290*433d6423SLionel SambucENTRY(copy_msg_to_user) 291*433d6423SLionel Sambuc /* load the source pointer */ 292*433d6423SLionel Sambuc mov 4(%esp), %ecx 293*433d6423SLionel Sambuc /* load the destination pointer */ 294*433d6423SLionel Sambuc mov 8(%esp), %edx 295*433d6423SLionel Sambuc 296*433d6423SLionel Sambuc mov 0*4(%ecx), %eax 297*433d6423SLionel Sambuc mov %eax, 0*4(%edx) 298*433d6423SLionel Sambuc mov 1*4(%ecx), %eax 299*433d6423SLionel Sambuc mov %eax, 1*4(%edx) 300*433d6423SLionel Sambuc mov 2*4(%ecx), %eax 301*433d6423SLionel Sambuc mov %eax, 2*4(%edx) 302*433d6423SLionel Sambuc mov 3*4(%ecx), %eax 303*433d6423SLionel Sambuc mov %eax, 3*4(%edx) 304*433d6423SLionel Sambuc mov 4*4(%ecx), %eax 305*433d6423SLionel Sambuc mov %eax, 4*4(%edx) 306*433d6423SLionel Sambuc mov 5*4(%ecx), %eax 307*433d6423SLionel Sambuc mov %eax, 5*4(%edx) 308*433d6423SLionel Sambuc mov 6*4(%ecx), %eax 309*433d6423SLionel Sambuc mov %eax, 6*4(%edx) 310*433d6423SLionel Sambuc mov 7*4(%ecx), %eax 311*433d6423SLionel Sambuc mov %eax, 7*4(%edx) 312*433d6423SLionel Sambuc mov 8*4(%ecx), %eax 313*433d6423SLionel Sambuc mov %eax, 8*4(%edx) 314*433d6423SLionel Sambuc 315*433d6423SLionel Sambuc 316*433d6423SLionel Sambuc mov 9*4(%ecx), %eax 317*433d6423SLionel Sambuc mov %eax, 9*4(%edx) 318*433d6423SLionel Sambuc mov 10*4(%ecx), %eax 319*433d6423SLionel Sambuc mov %eax, 10*4(%edx) 320*433d6423SLionel Sambuc mov 11*4(%ecx), %eax 321*433d6423SLionel Sambuc mov %eax, 11*4(%edx) 322*433d6423SLionel Sambuc mov 12*4(%ecx), %eax 323*433d6423SLionel Sambuc mov %eax, 12*4(%edx) 324*433d6423SLionel Sambuc mov 13*4(%ecx), %eax 325*433d6423SLionel Sambuc mov %eax, 13*4(%edx) 326*433d6423SLionel Sambuc mov 14*4(%ecx), %eax 327*433d6423SLionel Sambuc mov %eax, 14*4(%edx) 328*433d6423SLionel Sambuc mov 15*4(%ecx), %eax 329*433d6423SLionel Sambuc mov %eax, 15*4(%edx) 330*433d6423SLionel Sambuc 331*433d6423SLionel SambucLABEL(__copy_msg_to_user_end) 332*433d6423SLionel Sambuc movl $0, %eax 333*433d6423SLionel Sambuc ret 334*433d6423SLionel Sambuc 335*433d6423SLionel Sambuc/* 336*433d6423SLionel Sambuc * if a function from a selected set of copies from or to userspace fails, it is 337*433d6423SLionel Sambuc * because of a wrong pointer supplied by the userspace. We have to clean up and 338*433d6423SLionel Sambuc * and return -1 to indicated that something wrong has happend. The place it was 339*433d6423SLionel Sambuc * called from has to handle this situation. The exception handler redirect us 340*433d6423SLionel Sambuc * here to continue, clean up and report the error 341*433d6423SLionel Sambuc */ 342*433d6423SLionel SambucENTRY(__user_copy_msg_pointer_failure) 343*433d6423SLionel Sambuc movl $-1, %eax 344*433d6423SLionel Sambuc ret 345*433d6423SLionel Sambuc 346*433d6423SLionel Sambuc/*===========================================================================*/ 347*433d6423SLionel Sambuc/* phys_memset */ 348*433d6423SLionel Sambuc/*===========================================================================*/ 349*433d6423SLionel Sambuc/* 350*433d6423SLionel Sambuc * PUBLIC void phys_memset(phys_bytes dst, unsigned long pattern, 351*433d6423SLionel Sambuc * phys_bytes bytecount); 352*433d6423SLionel Sambuc * Fill a block of physical memory with pattern. 353*433d6423SLionel Sambuc */ 354*433d6423SLionel SambucENTRY(phys_memset) 355*433d6423SLionel Sambuc push %ebp 356*433d6423SLionel Sambuc mov %esp, %ebp 357*433d6423SLionel Sambuc push %edi 358*433d6423SLionel Sambuc cld 359*433d6423SLionel Sambuc 360*433d6423SLionel Sambuc mov 8(%ebp), %edi 361*433d6423SLionel Sambuc mov 16(%ebp), %ecx 362*433d6423SLionel Sambuc mov 12(%ebp), %eax 363*433d6423SLionel Sambuc shr $2, %ecx 364*433d6423SLionel Sambuc rep stosl 365*433d6423SLionel Sambuc 366*433d6423SLionel Sambuc/* Any remaining bytes? */ 367*433d6423SLionel Sambuc mov 16(%ebp), %ecx 368*433d6423SLionel Sambuc and $3, %ecx 369*433d6423SLionel Sambuc rep stosb 370*433d6423SLionel Sambuc 371*433d6423SLionel SambucLABEL(memset_fault) /* kernel can send us here */ 372*433d6423SLionel Sambuc mov $0, %eax /* 0 means: no fault */ 373*433d6423SLionel Sambuc pop %edi 374*433d6423SLionel Sambuc pop %ebp 375*433d6423SLionel Sambuc ret 376*433d6423SLionel Sambuc 377*433d6423SLionel SambucLABEL(memset_fault_in_kernel) /* kernel can send us here */ 378*433d6423SLionel Sambuc pop %edi 379*433d6423SLionel Sambuc pop %ebp 380*433d6423SLionel Sambuc mov %cr2, %eax 381*433d6423SLionel Sambuc ret 382*433d6423SLionel Sambuc 383*433d6423SLionel Sambuc/*===========================================================================*/ 384*433d6423SLionel Sambuc/* x86_triplefault */ 385*433d6423SLionel Sambuc/*===========================================================================*/ 386*433d6423SLionel Sambuc/* 387*433d6423SLionel Sambuc * PUBLIC void x86_triplefault(); 388*433d6423SLionel Sambuc * Reset the system by loading IDT with offset 0 and interrupting. 389*433d6423SLionel Sambuc */ 390*433d6423SLionel SambucENTRY(x86_triplefault) 391*433d6423SLionel Sambuc lidt idt_zero 392*433d6423SLionel Sambuc int $3 /* anything goes, the 386 will not like it */ 393*433d6423SLionel Sambuc.data 394*433d6423SLionel Sambucidt_zero: 395*433d6423SLionel Sambuc.long 0, 0 396*433d6423SLionel Sambuc.text 397*433d6423SLionel Sambuc 398*433d6423SLionel Sambuc 399*433d6423SLionel Sambuc/*===========================================================================*/ 400*433d6423SLionel Sambuc/* halt_cpu */ 401*433d6423SLionel Sambuc/*===========================================================================*/ 402*433d6423SLionel Sambuc/* 403*433d6423SLionel Sambuc * PUBLIC void halt_cpu(void); 404*433d6423SLionel Sambuc * reanables interrupts and puts the cpu in the halts state. Once an interrupt 405*433d6423SLionel Sambuc * is handled the execution resumes by disabling interrupts and continues 406*433d6423SLionel Sambuc */ 407*433d6423SLionel SambucENTRY(halt_cpu) 408*433d6423SLionel Sambuc sti 409*433d6423SLionel Sambuc hlt /* interrupts enabled only after this instruction is executed! */ 410*433d6423SLionel Sambuc /* 411*433d6423SLionel Sambuc * interrupt handlers make sure that the interrupts are disabled when we 412*433d6423SLionel Sambuc * get here so we take only _one_ interrupt after halting the CPU 413*433d6423SLionel Sambuc */ 414*433d6423SLionel Sambuc ret 415*433d6423SLionel Sambuc 416*433d6423SLionel Sambuc/*===========================================================================*/ 417*433d6423SLionel Sambuc/* poweroff_vmware_clihlt */ 418*433d6423SLionel Sambuc/*===========================================================================*/ 419*433d6423SLionel Sambuc/* 420*433d6423SLionel Sambuc * PUBLIC void poweroff_vmware_clihlt(void); 421*433d6423SLionel Sambuc * VMware detects this peculiar sequence and forces the virtual machine off 422*433d6423SLionel Sambuc * when the parameter gui.exitOnCLIHLT is set to TRUE. 423*433d6423SLionel Sambuc * Otherwise this sequence just hangs the CPU, requiring a power down action. 424*433d6423SLionel Sambuc */ 425*433d6423SLionel SambucENTRY(poweroff_vmware_clihlt) 426*433d6423SLionel Sambuc#ifndef NO_VMWARE_DETECTION 427*433d6423SLionel Sambuc mov $1, %eax 428*433d6423SLionel Sambuc cpuid 429*433d6423SLionel Sambuc test $[1<<31], %ecx /* "virtualized" */ 430*433d6423SLionel Sambuc jz 1f /* always 0 on real hardware */ 431*433d6423SLionel Sambuc mov $0x40000000, %eax /* select hypervisor-use leaf */ 432*433d6423SLionel Sambuc cpuid 433*433d6423SLionel Sambuc cmp $0x61774D56, %ebx /* ASCII "VMwa" */ 434*433d6423SLionel Sambuc jne 1f 435*433d6423SLionel Sambuc cmp $0x4D566572, %ecx /* ASCII "reVM" */ 436*433d6423SLionel Sambuc jne 1f 437*433d6423SLionel Sambuc cmp $0x65726177, %edx /* ASCII "ware" */ 438*433d6423SLionel Sambuc jne 1f 439*433d6423SLionel Sambuc /* we are virtualized by some VMware product! */ 440*433d6423SLionel Sambuc#endif 441*433d6423SLionel Sambuc cli 442*433d6423SLionel Sambuc hlt 443*433d6423SLionel Sambuc1: ret 444*433d6423SLionel Sambuc 445*433d6423SLionel Sambuc/*===========================================================================*/ 446*433d6423SLionel Sambuc/* read_flags */ 447*433d6423SLionel Sambuc/*===========================================================================*/ 448*433d6423SLionel Sambuc/* 449*433d6423SLionel Sambuc * PUBLIC unsigned long read_cpu_flags(void); 450*433d6423SLionel Sambuc * Read CPU status flags from C. 451*433d6423SLionel Sambuc */ 452*433d6423SLionel SambucENTRY(read_cpu_flags) 453*433d6423SLionel Sambuc pushf 454*433d6423SLionel Sambuc mov (%esp), %eax 455*433d6423SLionel Sambuc add $4, %esp 456*433d6423SLionel Sambuc ret 457*433d6423SLionel Sambuc 458*433d6423SLionel SambucENTRY(read_ds) 459*433d6423SLionel Sambuc mov $0, %eax 460*433d6423SLionel Sambuc mov %ds, %ax 461*433d6423SLionel Sambuc ret 462*433d6423SLionel Sambuc 463*433d6423SLionel SambucENTRY(read_cs) 464*433d6423SLionel Sambuc mov $0, %eax 465*433d6423SLionel Sambuc mov %cs, %ax 466*433d6423SLionel Sambuc ret 467*433d6423SLionel Sambuc 468*433d6423SLionel SambucENTRY(read_ss) 469*433d6423SLionel Sambuc mov $0, %eax 470*433d6423SLionel Sambuc mov %ss, %ax 471*433d6423SLionel Sambuc ret 472*433d6423SLionel Sambuc 473*433d6423SLionel Sambuc/*===========================================================================*/ 474*433d6423SLionel Sambuc/* fpu_routines */ 475*433d6423SLionel Sambuc/*===========================================================================*/ 476*433d6423SLionel Sambuc 477*433d6423SLionel Sambuc/* non-waiting FPU initialization */ 478*433d6423SLionel SambucENTRY(fninit) 479*433d6423SLionel Sambuc fninit 480*433d6423SLionel Sambuc ret 481*433d6423SLionel Sambuc 482*433d6423SLionel SambucENTRY(clts) 483*433d6423SLionel Sambuc clts 484*433d6423SLionel Sambuc ret 485*433d6423SLionel Sambuc 486*433d6423SLionel Sambuc/* store status word (non-waiting) */ 487*433d6423SLionel SambucENTRY(fnstsw) 488*433d6423SLionel Sambuc xor %eax, %eax 489*433d6423SLionel Sambuc 490*433d6423SLionel Sambuc /* DO NOT CHANGE THE OPERAND!!! gas2ack does not handle it yet */ 491*433d6423SLionel Sambuc fnstsw %ax 492*433d6423SLionel Sambuc ret 493*433d6423SLionel Sambuc 494*433d6423SLionel Sambuc/*===========================================================================*/ 495*433d6423SLionel Sambuc/* fxrstor */ 496*433d6423SLionel Sambuc/*===========================================================================*/ 497*433d6423SLionel SambucENTRY(fxrstor) 498*433d6423SLionel Sambuc mov 4(%esp), %eax 499*433d6423SLionel Sambuc fxrstor (%eax) 500*433d6423SLionel SambucENTRY(__fxrstor_end) 501*433d6423SLionel Sambuc xor %eax, %eax 502*433d6423SLionel Sambuc ret 503*433d6423SLionel Sambuc 504*433d6423SLionel Sambuc/*===========================================================================*/ 505*433d6423SLionel Sambuc/* frstor */ 506*433d6423SLionel Sambuc/*===========================================================================*/ 507*433d6423SLionel SambucENTRY(frstor) 508*433d6423SLionel Sambuc mov 4(%esp), %eax 509*433d6423SLionel Sambuc frstor (%eax) 510*433d6423SLionel SambucENTRY(__frstor_end) 511*433d6423SLionel Sambuc xor %eax, %eax 512*433d6423SLionel Sambuc ret 513*433d6423SLionel Sambuc 514*433d6423SLionel Sambuc/* Shared exception handler for both fxrstor and frstor. */ 515*433d6423SLionel SambucENTRY(__frstor_failure) 516*433d6423SLionel Sambuc mov $1, %eax 517*433d6423SLionel Sambuc ret 518*433d6423SLionel Sambuc 519*433d6423SLionel Sambuc/* Read/write control registers */ 520*433d6423SLionel SambucARG_EAX_RETURN(read_cr0, %cr0); 521*433d6423SLionel SambucARG_EAX_RETURN(read_cr2, %cr2); 522*433d6423SLionel SambucARG_EAX_RETURN(read_cr3, %cr3); 523*433d6423SLionel SambucARG_EAX_RETURN(read_cr4, %cr4); 524*433d6423SLionel SambucARG_EAX_SET(write_cr4, %cr4); 525*433d6423SLionel SambucARG_EAX_SET(write_cr0, %cr0); 526*433d6423SLionel SambucARG_EAX_SET(write_cr3, %cr3); 527*433d6423SLionel Sambuc 528*433d6423SLionel Sambuc/* Read/write various descriptor tables */ 529*433d6423SLionel SambucARG_EAX_ACTION(x86_ltr, ltr STACKARG ); 530*433d6423SLionel SambucARG_EAX_ACTION(x86_lidt, lidtl (%eax)); 531*433d6423SLionel SambucARG_EAX_ACTION(x86_lgdt, lgdt (%eax)); 532*433d6423SLionel SambucARG_EAX_ACTION(x86_lldt, lldt STACKARG); 533*433d6423SLionel SambucARG_EAX_ACTION(x86_sgdt, sgdt (%eax)); 534*433d6423SLionel SambucARG_EAX_ACTION(x86_sidt, sidt (%eax)); 535*433d6423SLionel Sambuc 536*433d6423SLionel Sambuc/* Load segments */ 537*433d6423SLionel SambucARG_AX_SET(x86_load_ds, %ds) 538*433d6423SLionel SambucARG_AX_SET(x86_load_es, %es) 539*433d6423SLionel SambucARG_AX_SET(x86_load_fs, %fs) 540*433d6423SLionel SambucARG_AX_SET(x86_load_gs, %gs) 541*433d6423SLionel SambucARG_AX_SET(x86_load_ss, %ss) 542*433d6423SLionel Sambuc 543*433d6423SLionel Sambuc/* FPU */ 544*433d6423SLionel SambucARG_EAX_ACTION(fnsave, fnsave (%eax) ; fwait); 545*433d6423SLionel SambucARG_EAX_ACTION(fxsave, fxsave (%eax)); 546*433d6423SLionel SambucARG_EAX_ACTION(fnstcw, fnstcw (%eax)); 547*433d6423SLionel Sambuc 548*433d6423SLionel Sambuc/* invlpg */ 549*433d6423SLionel SambucARG_EAX_ACTION(i386_invlpg, invlpg (%eax)); 550*433d6423SLionel Sambuc 551*433d6423SLionel SambucENTRY(x86_load_kerncs) 552*433d6423SLionel Sambuc push %ebp 553*433d6423SLionel Sambuc mov %esp, %ebp 554*433d6423SLionel Sambuc mov 8(%ebp), %eax 555*433d6423SLionel Sambuc jmp $KERN_CS_SELECTOR, $newcs 556*433d6423SLionel Sambucnewcs: 557*433d6423SLionel Sambuc pop %ebp 558*433d6423SLionel Sambuc ret 559*433d6423SLionel Sambuc 560*433d6423SLionel Sambuc/* 561*433d6423SLionel Sambuc * Read the Model Specific Register (MSR) of IA32 architecture 562*433d6423SLionel Sambuc * 563*433d6423SLionel Sambuc * void ia32_msr_read(u32_t reg, u32_t * hi, u32_t * lo) 564*433d6423SLionel Sambuc */ 565*433d6423SLionel SambucENTRY(ia32_msr_read) 566*433d6423SLionel Sambuc push %ebp 567*433d6423SLionel Sambuc mov %esp, %ebp 568*433d6423SLionel Sambuc 569*433d6423SLionel Sambuc mov 8(%ebp), %ecx 570*433d6423SLionel Sambuc rdmsr 571*433d6423SLionel Sambuc mov 12(%ebp), %ecx 572*433d6423SLionel Sambuc mov %edx, (%ecx) 573*433d6423SLionel Sambuc mov 16(%ebp), %ecx 574*433d6423SLionel Sambuc mov %eax, (%ecx) 575*433d6423SLionel Sambuc 576*433d6423SLionel Sambuc pop %ebp 577*433d6423SLionel Sambuc ret 578*433d6423SLionel Sambuc 579*433d6423SLionel Sambuc/* 580*433d6423SLionel Sambuc * Write the Model Specific Register (MSR) of IA32 architecture 581*433d6423SLionel Sambuc * 582*433d6423SLionel Sambuc * void ia32_msr_write(u32_t reg, u32_t hi, u32_t lo) 583*433d6423SLionel Sambuc */ 584*433d6423SLionel SambucENTRY(ia32_msr_write) 585*433d6423SLionel Sambuc push %ebp 586*433d6423SLionel Sambuc mov %esp, %ebp 587*433d6423SLionel Sambuc 588*433d6423SLionel Sambuc mov 12(%ebp), %edx 589*433d6423SLionel Sambuc mov 16(%ebp), %eax 590*433d6423SLionel Sambuc mov 8(%ebp), %ecx 591*433d6423SLionel Sambuc wrmsr 592*433d6423SLionel Sambuc 593*433d6423SLionel Sambuc pop %ebp 594*433d6423SLionel Sambuc ret 595*433d6423SLionel Sambuc 596*433d6423SLionel Sambuc/*===========================================================================*/ 597*433d6423SLionel Sambuc/* __switch_address_space */ 598*433d6423SLionel Sambuc/*===========================================================================*/ 599*433d6423SLionel Sambuc/* PUBLIC void __switch_address_space(struct proc *p, struct ** ptproc) 600*433d6423SLionel Sambuc * 601*433d6423SLionel Sambuc * sets the %cr3 register to the supplied value if it is not already set to the 602*433d6423SLionel Sambuc * same value in which case it would only result in an extra TLB flush which is 603*433d6423SLionel Sambuc * not desirable 604*433d6423SLionel Sambuc */ 605*433d6423SLionel SambucENTRY(__switch_address_space) 606*433d6423SLionel Sambuc /* read the process pointer */ 607*433d6423SLionel Sambuc mov 4(%esp), %edx 608*433d6423SLionel Sambuc /* get the new cr3 value */ 609*433d6423SLionel Sambuc movl P_CR3(%edx), %eax 610*433d6423SLionel Sambuc /* test if the new cr3 != NULL */ 611*433d6423SLionel Sambuc cmpl $0, %eax 612*433d6423SLionel Sambuc je 0f 613*433d6423SLionel Sambuc 614*433d6423SLionel Sambuc /* 615*433d6423SLionel Sambuc * test if the cr3 is loaded with the current value to avoid unnecessary 616*433d6423SLionel Sambuc * TLB flushes 617*433d6423SLionel Sambuc */ 618*433d6423SLionel Sambuc mov %cr3, %ecx 619*433d6423SLionel Sambuc cmp %ecx, %eax 620*433d6423SLionel Sambuc je 0f 621*433d6423SLionel Sambuc mov %eax, %cr3 622*433d6423SLionel Sambuc /* get ptproc */ 623*433d6423SLionel Sambuc mov 8(%esp), %eax 624*433d6423SLionel Sambuc mov %edx, (%eax) 625*433d6423SLionel Sambuc0: 626*433d6423SLionel Sambuc ret 627*433d6423SLionel Sambuc 628*433d6423SLionel Sambuc/* acknowledge just the master PIC */ 629*433d6423SLionel SambucENTRY(eoi_8259_master) 630*433d6423SLionel Sambuc movb $END_OF_INT, %al 631*433d6423SLionel Sambuc outb $INT_CTL 632*433d6423SLionel Sambuc ret 633*433d6423SLionel Sambuc 634*433d6423SLionel Sambuc/* we have to acknowledge both PICs */ 635*433d6423SLionel SambucENTRY(eoi_8259_slave) 636*433d6423SLionel Sambuc movb $END_OF_INT, %al 637*433d6423SLionel Sambuc outb $INT_CTL 638*433d6423SLionel Sambuc outb $INT2_CTL 639*433d6423SLionel Sambuc ret 640*433d6423SLionel Sambuc 641*433d6423SLionel Sambuc/* in some cases we need to force TLB update, reloading cr3 does the trick */ 642*433d6423SLionel SambucENTRY(refresh_tlb) 643*433d6423SLionel Sambuc mov %cr3, %eax 644*433d6423SLionel Sambuc mov %eax, %cr3 645*433d6423SLionel Sambuc ret 646*433d6423SLionel Sambuc 647*433d6423SLionel Sambuc#ifdef CONFIG_SMP 648*433d6423SLionel Sambuc 649*433d6423SLionel Sambuc/*===========================================================================*/ 650*433d6423SLionel Sambuc/* smp_get_htt */ 651*433d6423SLionel Sambuc/*===========================================================================*/ 652*433d6423SLionel Sambuc/* PUBLIC int smp_get_htt(void); */ 653*433d6423SLionel Sambuc/* return true if the processor is hyper-threaded. */ 654*433d6423SLionel SambucENTRY(smp_get_htt) 655*433d6423SLionel Sambuc push %ebp 656*433d6423SLionel Sambuc mov %esp, %ebp 657*433d6423SLionel Sambuc pushf 658*433d6423SLionel Sambuc pop %eax 659*433d6423SLionel Sambuc mov %eax, %ebx 660*433d6423SLionel Sambuc and $0x200000, %eax 661*433d6423SLionel Sambuc je 0f 662*433d6423SLionel Sambuc mov $0x1, %eax 663*433d6423SLionel Sambuc/* FIXME don't use the byte code */ 664*433d6423SLionel Sambuc.byte 0x0f, 0xa2 /* opcode for cpuid */ 665*433d6423SLionel Sambuc mov %edx, %eax 666*433d6423SLionel Sambuc pop %ebp 667*433d6423SLionel Sambuc ret 668*433d6423SLionel Sambuc0: 669*433d6423SLionel Sambuc xor %eax, %eax 670*433d6423SLionel Sambuc pop %ebp 671*433d6423SLionel Sambuc ret 672*433d6423SLionel Sambuc 673*433d6423SLionel Sambuc/*===========================================================================*/ 674*433d6423SLionel Sambuc/* smp_get_num_htt */ 675*433d6423SLionel Sambuc/*===========================================================================*/ 676*433d6423SLionel Sambuc/* PUBLIC int smp_get_num_htt(void); */ 677*433d6423SLionel Sambuc/* Get the number of hyper-threaded processor cores */ 678*433d6423SLionel SambucENTRY(smp_get_num_htt) 679*433d6423SLionel Sambuc push %ebp 680*433d6423SLionel Sambuc mov %esp, %ebp 681*433d6423SLionel Sambuc pushf 682*433d6423SLionel Sambuc pop %eax 683*433d6423SLionel Sambuc mov %eax, %ebx 684*433d6423SLionel Sambuc and $0x200000, %eax 685*433d6423SLionel Sambuc je 0f 686*433d6423SLionel Sambuc mov $0x1, %eax 687*433d6423SLionel Sambuc/* FIXME don't use the byte code */ 688*433d6423SLionel Sambuc.byte 0x0f, 0xa2 /* opcode for cpuid */ 689*433d6423SLionel Sambuc mov %ebx, %eax 690*433d6423SLionel Sambuc pop %ebp 691*433d6423SLionel Sambuc ret 692*433d6423SLionel Sambuc0: 693*433d6423SLionel Sambuc xor %eax, %eax 694*433d6423SLionel Sambuc pop %ebp 695*433d6423SLionel Sambuc ret 696*433d6423SLionel Sambuc 697*433d6423SLionel Sambuc/*===========================================================================*/ 698*433d6423SLionel Sambuc/* smp_get_cores */ 699*433d6423SLionel Sambuc/*===========================================================================*/ 700*433d6423SLionel Sambuc/* PUBLIC int smp_get_cores(void); */ 701*433d6423SLionel Sambuc/* Get the number of cores. */ 702*433d6423SLionel SambucENTRY(smp_get_cores) 703*433d6423SLionel Sambuc push %ebp 704*433d6423SLionel Sambuc mov %esp, %ebp 705*433d6423SLionel Sambuc pushf 706*433d6423SLionel Sambuc pop %eax 707*433d6423SLionel Sambuc mov %eax, %ebx 708*433d6423SLionel Sambuc and $0x200000, %eax 709*433d6423SLionel Sambuc je 0f 710*433d6423SLionel Sambuc push %ecx 711*433d6423SLionel Sambuc xor %ecx, %ecx 712*433d6423SLionel Sambuc mov $0x4, %eax 713*433d6423SLionel Sambuc/* FIXME don't use the byte code */ 714*433d6423SLionel Sambuc.byte 0x0f, 0xa2 /* opcode for cpuid */ 715*433d6423SLionel Sambuc pop %ebp 716*433d6423SLionel Sambuc ret 717*433d6423SLionel Sambuc0: 718*433d6423SLionel Sambuc xor %eax, %eax 719*433d6423SLionel Sambuc pop %ebp 720*433d6423SLionel Sambuc ret 721*433d6423SLionel Sambuc 722*433d6423SLionel Sambuc/*===========================================================================*/ 723*433d6423SLionel Sambuc/* arch_spinlock_lock */ 724*433d6423SLionel Sambuc/*===========================================================================*/ 725*433d6423SLionel Sambuc/* void arch_spinlock_lock (u32_t *lock_data) 726*433d6423SLionel Sambuc * { 727*433d6423SLionel Sambuc * while (test_and_set(lock_data) == 1) 728*433d6423SLionel Sambuc * while (*lock_data == 1) 729*433d6423SLionel Sambuc * ; 730*433d6423SLionel Sambuc * } 731*433d6423SLionel Sambuc * eax register is clobbered. 732*433d6423SLionel Sambuc */ 733*433d6423SLionel SambucENTRY(arch_spinlock_lock) 734*433d6423SLionel Sambuc mov 4(%esp), %eax 735*433d6423SLionel Sambuc mov $1, %edx 736*433d6423SLionel Sambuc2: 737*433d6423SLionel Sambuc mov $1, %ecx 738*433d6423SLionel Sambuc xchg %ecx, (%eax) 739*433d6423SLionel Sambuc test %ecx, %ecx 740*433d6423SLionel Sambuc je 0f 741*433d6423SLionel Sambuc 742*433d6423SLionel Sambuc cmp $(1<< 16), %edx 743*433d6423SLionel Sambuc je 1f 744*433d6423SLionel Sambuc shl %edx 745*433d6423SLionel Sambuc1: 746*433d6423SLionel Sambuc mov %edx, %ecx 747*433d6423SLionel Sambuc3: 748*433d6423SLionel Sambuc pause 749*433d6423SLionel Sambuc sub $1, %ecx 750*433d6423SLionel Sambuc test %ecx, %ecx 751*433d6423SLionel Sambuc jz 2b 752*433d6423SLionel Sambuc jmp 3b 753*433d6423SLionel Sambuc0: 754*433d6423SLionel Sambuc mfence 755*433d6423SLionel Sambuc ret 756*433d6423SLionel Sambuc 757*433d6423SLionel Sambuc/*===========================================================================*/ 758*433d6423SLionel Sambuc/* arch_spinlock_unlock */ 759*433d6423SLionel Sambuc/*===========================================================================*/ 760*433d6423SLionel Sambuc/* * void arch_spinlock_unlock (unsigned int *lockp) */ 761*433d6423SLionel Sambuc/* spin lock release routine. */ 762*433d6423SLionel SambucENTRY(arch_spinlock_unlock) 763*433d6423SLionel Sambuc mov 4(%esp), %eax 764*433d6423SLionel Sambuc mov $0, %ecx 765*433d6423SLionel Sambuc xchg %ecx, (%eax) 766*433d6423SLionel Sambuc mfence 767*433d6423SLionel Sambuc ret 768*433d6423SLionel Sambuc 769*433d6423SLionel Sambuc#endif /* CONFIG_SMP */ 770*433d6423SLionel Sambuc 771*433d6423SLionel Sambuc/*===========================================================================*/ 772*433d6423SLionel Sambuc/* mfence */ 773*433d6423SLionel Sambuc/*===========================================================================*/ 774*433d6423SLionel Sambuc/* PUBLIC void mfence (void); */ 775*433d6423SLionel Sambuc/* architecture specific memory barrier routine. */ 776*433d6423SLionel SambucENTRY(mfence) 777*433d6423SLionel Sambuc mfence 778*433d6423SLionel Sambuc ret 779*433d6423SLionel Sambuc 780*433d6423SLionel Sambuc/*===========================================================================*/ 781*433d6423SLionel Sambuc/* arch_pause */ 782*433d6423SLionel Sambuc/*===========================================================================*/ 783*433d6423SLionel Sambuc/* PUBLIC void arch_pause (void); */ 784*433d6423SLionel Sambuc/* architecture specific pause routine. */ 785*433d6423SLionel SambucENTRY(arch_pause) 786*433d6423SLionel Sambuc pause 787*433d6423SLionel Sambuc ret 788*433d6423SLionel Sambuc 789*433d6423SLionel Sambuc/*===========================================================================*/ 790*433d6423SLionel Sambuc/* read_ebp */ 791*433d6423SLionel Sambuc/*===========================================================================*/ 792*433d6423SLionel Sambuc/* PUBLIC u16_t cpuid(void) */ 793*433d6423SLionel SambucENTRY(read_ebp) 794*433d6423SLionel Sambuc mov %ebp, %eax 795*433d6423SLionel Sambuc ret 796*433d6423SLionel Sambuc 797*433d6423SLionel SambucENTRY(interrupts_enable) 798*433d6423SLionel Sambuc sti 799*433d6423SLionel Sambuc ret 800*433d6423SLionel Sambuc 801*433d6423SLionel SambucENTRY(interrupts_disable) 802*433d6423SLionel Sambuc cli 803*433d6423SLionel Sambuc ret 804*433d6423SLionel Sambuc 805*433d6423SLionel Sambuc 806*433d6423SLionel Sambuc/* 807*433d6423SLionel Sambuc * void switch_k_stack(void * esp, void (* continuation)(void)); 808*433d6423SLionel Sambuc * 809*433d6423SLionel Sambuc * sets the current stack pointer to the given value and continues execution at 810*433d6423SLionel Sambuc * the given address 811*433d6423SLionel Sambuc */ 812*433d6423SLionel SambucENTRY(switch_k_stack) 813*433d6423SLionel Sambuc /* get the arguments from the stack */ 814*433d6423SLionel Sambuc mov 8(%esp), %eax 815*433d6423SLionel Sambuc mov 4(%esp), %ecx 816*433d6423SLionel Sambuc mov $0, %ebp /* reset %ebp for stack trace */ 817*433d6423SLionel Sambuc mov %ecx, %esp /* set the new stack */ 818*433d6423SLionel Sambuc jmp *%eax /* and jump to the continuation */ 819*433d6423SLionel Sambuc 820*433d6423SLionel Sambuc /* NOT_REACHABLE */ 821*433d6423SLionel Sambuc0: jmp 0b 822*433d6423SLionel Sambuc 823*433d6423SLionel Sambuc.data 824*433d6423SLionel Sambucidt_ptr: 825*433d6423SLionel Sambuc .short 0x3ff 826*433d6423SLionel Sambuc .long 0x0 827*433d6423SLionel Sambuc 828*433d6423SLionel Sambucldtsel: 829*433d6423SLionel Sambuc .long LDT_SELECTOR 830