2 ** Copyright 2001-2004, Travis Geiselbrecht. All rights reserved.

3 ** Distributed under the terms of the NewOS License.

25 /* a few debug functions that get added to the kernel debugger menu */

26 static void dbg_in ( int argc , char ** argv ); argcargv

27 static void dbg_out ( int argc , char ** argv ); argcargv

29 static struct tss ** tss ; tsstss

30 static int * tss_loaded ; tss_loaded

32 /* tss to switch to a special 'task' on the double fault handler */

33 static struct tss double_fault_tss ; tss double_fault_tss

34 static uint32 double_fault_stack [ 1024 ]; uint32 double_fault_stack

36 static desc_table * gdt = 0 ; desc_tablegdt

38 /* cpu vendor info */

39 struct cpu_vendor_info { cpu_vendor_info

40 const char * vendor ; vendor

41 const char * ident_string [ 2 ]; ident_string

44 static const struct cpu_vendor_info vendor_info [ VENDOR_NUM ] = { cpu_vendor_info vendor_infoVENDOR_NUM

48 { "UMC" , { "UMC UMC UMC" } },

53 { "NSC" , { "Geode by NSC" } },

56 /* fsave vs fxsave function pointers */

57 static void (* fsave_swap_func )( void * old_fpu_state , void * new_fpu_state ); fsave_swap_funcold_fpu_statenew_fpu_state

58 static void (* fsave_func )( void * fpu_state ); fsave_funcfpu_state

59 static void (* frstor_func )( void * fpu_state ); frstor_funcfpu_state

61 int arch_cpu_preboot_init ( kernel_args * ka ) kernel_argska

63 write_dr3 ( 0 );

64 return 0 ;

67 static void make_feature_string ( cpu_ent * cpu , char * str ) cpu_entcpustr

[ 0 ] = 0 ; 70 str

72 if ( cpu -> arch . feature [ FEATURE_COMMON ] & X86_FPU ) cpuarchfeatureFEATURE_COMMONX86_FPU

73 strcat ( str , "fpu " ); str

74 if ( cpu -> arch . feature [ FEATURE_COMMON ] & X86_VME ) cpuarchfeatureFEATURE_COMMONX86_VME

75 strcat ( str , "vme " ); str

76 if ( cpu -> arch . feature [ FEATURE_COMMON ] & X86_DE ) cpuarchfeatureFEATURE_COMMONX86_DE

77 strcat ( str , "de " ); str

78 if ( cpu -> arch . feature [ FEATURE_COMMON ] & X86_PSE ) cpuarchfeatureFEATURE_COMMONX86_PSE

79 strcat ( str , "pse " ); str

80 if ( cpu -> arch . feature [ FEATURE_COMMON ] & X86_TSC ) cpuarchfeatureFEATURE_COMMONX86_TSC

81 strcat ( str , "tsc " ); str

82 if ( cpu -> arch . feature [ FEATURE_COMMON ] & X86_MSR ) cpuarchfeatureFEATURE_COMMONX86_MSR

83 strcat ( str , "msr " ); str

84 if ( cpu -> arch . feature [ FEATURE_COMMON ] & X86_PAE ) cpuarchfeatureFEATURE_COMMONX86_PAE

85 strcat ( str , "pae " ); str

86 if ( cpu -> arch . feature [ FEATURE_COMMON ] & X86_MCE ) cpuarchfeatureFEATURE_COMMONX86_MCE

87 strcat ( str , "mce " ); str

88 if ( cpu -> arch . feature [ FEATURE_COMMON ] & X86_CX8 ) cpuarchfeatureFEATURE_COMMONX86_CX8

89 strcat ( str , "cx8 " ); str

90 if ( cpu -> arch . feature [ FEATURE_COMMON ] & X86_APIC ) cpuarchfeatureFEATURE_COMMONX86_APIC

91 strcat ( str , "apic " ); str

92 if ( cpu -> arch . feature [ FEATURE_COMMON ] & X86_SEP ) cpuarchfeatureFEATURE_COMMONX86_SEP

93 strcat ( str , "sep " ); str

94 if ( cpu -> arch . feature [ FEATURE_COMMON ] & X86_MTRR ) cpuarchfeatureFEATURE_COMMONX86_MTRR

95 strcat ( str , "mtrr " ); str

96 if ( cpu -> arch . feature [ FEATURE_COMMON ] & X86_PGE ) cpuarchfeatureFEATURE_COMMONX86_PGE

97 strcat ( str , "pge " ); str

98 if ( cpu -> arch . feature [ FEATURE_COMMON ] & X86_MCA ) cpuarchfeatureFEATURE_COMMONX86_MCA

99 strcat ( str , "mca " ); str

100 if ( cpu -> arch . feature [ FEATURE_COMMON ] & X86_CMOV ) cpuarchfeatureFEATURE_COMMONX86_CMOV

101 strcat ( str , "cmov " ); str

102 if ( cpu -> arch . feature [ FEATURE_COMMON ] & X86_PAT ) cpuarchfeatureFEATURE_COMMONX86_PAT

103 strcat ( str , "pat " ); str

104 if ( cpu -> arch . feature [ FEATURE_COMMON ] & X86_PSE36 ) cpuarchfeatureFEATURE_COMMONX86_PSE36

105 strcat ( str , "pse36 " ); str

106 if ( cpu -> arch . feature [ FEATURE_COMMON ] & X86_PSN ) cpuarchfeatureFEATURE_COMMONX86_PSN

107 strcat ( str , "psn " ); str

108 if ( cpu -> arch . feature [ FEATURE_COMMON ] & X86_CLFSH ) cpuarchfeatureFEATURE_COMMONX86_CLFSH

109 strcat ( str , "clfsh " ); str

110 if ( cpu -> arch . feature [ FEATURE_COMMON ] & X86_DS ) cpuarchfeatureFEATURE_COMMONX86_DS

111 strcat ( str , "ds " ); str

112 if ( cpu -> arch . feature [ FEATURE_COMMON ] & X86_ACPI ) cpuarchfeatureFEATURE_COMMONX86_ACPI

113 strcat ( str , "acpi " ); str

114 if ( cpu -> arch . feature [ FEATURE_COMMON ] & X86_MMX ) cpuarchfeatureFEATURE_COMMONX86_MMX

115 strcat ( str , "mmx " ); str

116 if ( cpu -> arch . feature [ FEATURE_COMMON ] & X86_FXSR ) cpuarchfeatureFEATURE_COMMONX86_FXSR

117 strcat ( str , "fxsr " ); str

118 if ( cpu -> arch . feature [ FEATURE_COMMON ] & X86_SSE ) cpuarchfeatureFEATURE_COMMONX86_SSE

119 strcat ( str , "sse " ); str

120 if ( cpu -> arch . feature [ FEATURE_COMMON ] & X86_SSE2 ) cpuarchfeatureFEATURE_COMMONX86_SSE2

121 strcat ( str , "sse2 " ); str

122 if ( cpu -> arch . feature [ FEATURE_COMMON ] & X86_SS ) cpuarchfeatureFEATURE_COMMONX86_SS

123 strcat ( str , "ss " ); str

124 if ( cpu -> arch . feature [ FEATURE_COMMON ] & X86_HTT ) cpuarchfeatureFEATURE_COMMONX86_HTT

125 strcat ( str , "htt " ); str

126 if ( cpu -> arch . feature [ FEATURE_COMMON ] & X86_TM ) cpuarchfeatureFEATURE_COMMONX86_TM

127 strcat ( str , "tm " ); str

128 if ( cpu -> arch . feature [ FEATURE_COMMON ] & X86_PBE ) cpuarchfeatureFEATURE_COMMONX86_PBE

129 strcat ( str , "pbe " ); str

130 if ( cpu -> arch . feature [ FEATURE_EXT ] & X86_EXT_SSE3 ) cpuarchfeatureFEATURE_EXTX86_EXT_SSE3

131 strcat ( str , "sse3 " ); str

132 if ( cpu -> arch . feature [ FEATURE_EXT ] & X86_EXT_MONITOR ) cpuarchfeatureFEATURE_EXTX86_EXT_MONITOR

133 strcat ( str , "monitor " ); str

134 if ( cpu -> arch . feature [ FEATURE_EXT ] & X86_EXT_DSCPL ) cpuarchfeatureFEATURE_EXTX86_EXT_DSCPL

135 strcat ( str , "dscpl " ); str

136 if ( cpu -> arch . feature [ FEATURE_EXT ] & X86_EXT_EST ) cpuarchfeatureFEATURE_EXTX86_EXT_EST

137 strcat ( str , "est " ); str

138 if ( cpu -> arch . feature [ FEATURE_EXT ] & X86_EXT_TM2 ) cpuarchfeatureFEATURE_EXTX86_EXT_TM2

139 strcat ( str , "tm2 " ); str

140 if ( cpu -> arch . feature [ FEATURE_EXT ] & X86_EXT_CNXTID ) cpuarchfeatureFEATURE_EXTX86_EXT_CNXTID

141 strcat ( str , "cnxtid " ); str

142 if ( cpu -> arch . feature [ FEATURE_EXT_AMD ] & X86_AMD_EXT_SYSCALL ) cpuarchfeatureFEATURE_EXT_AMDX86_AMD_EXT_SYSCALL

143 strcat ( str , "syscall " ); str

144 if ( cpu -> arch . feature [ FEATURE_EXT_AMD ] & X86_AMD_EXT_NX ) cpuarchfeatureFEATURE_EXT_AMDX86_AMD_EXT_NX

145 strcat ( str , "nx " ); str

146 if ( cpu -> arch . feature [ FEATURE_EXT_AMD ] & X86_AMD_EXT_MMXEXT ) cpuarchfeatureFEATURE_EXT_AMDX86_AMD_EXT_MMXEXT

147 strcat ( str , "mmxext " ); str

148 if ( cpu -> arch . feature [ FEATURE_EXT_AMD ] & X86_AMD_EXT_FFXSR ) cpuarchfeatureFEATURE_EXT_AMDX86_AMD_EXT_FFXSR

149 strcat ( str , "ffxsr " ); str

150 if ( cpu -> arch . feature [ FEATURE_EXT_AMD ] & X86_AMD_EXT_LONG ) cpuarchfeatureFEATURE_EXT_AMDX86_AMD_EXT_LONG

151 strcat ( str , "long " ); str

152 if ( cpu -> arch . feature [ FEATURE_EXT_AMD ] & X86_AMD_EXT_3DNOWEXT ) cpuarchfeatureFEATURE_EXT_AMDX86_AMD_EXT_3DNOWEXT

153 strcat ( str , "3dnowext " ); str

154 if ( cpu -> arch . feature [ FEATURE_EXT_AMD ] & X86_AMD_EXT_3DNOW ) cpuarchfeatureFEATURE_EXT_AMDX86_AMD_EXT_3DNOW

155 strcat ( str , "3dnow " ); str

158 static int detect_cpu ( kernel_args * ka , int curr_cpu ) kernel_argskacurr_cpu

160 unsigned int data [ 4 ]; data

161 char vendor_str [ 17 ]; vendor_str

162 int i ;

165 // clear out the cpu info data

-> arch . feature [ FEATURE_COMMON ] = 0 ; 168 cpuarchfeatureFEATURE_COMMON

-> arch . feature [ FEATURE_EXT ] = 0 ; 169 cpuarchfeatureFEATURE_EXT

-> arch . feature [ FEATURE_EXT_AMD ] = 0 ; 170 cpuarchfeatureFEATURE_EXT_AMD

-> arch . model_name [ 0 ] = 0 ; 171 cpuarchmodel_name

173 // print some fun data

174 i386_cpuid ( 0 , data ); data

176 // build the vendor string

177 memset ( vendor_str , 0 , sizeof ( vendor_str )); vendor_strvendor_str

178 *( unsigned int *)& vendor_str [ 0 ] = data [ 1 ]; vendor_strdata

179 *( unsigned int *)& vendor_str [ 4 ] = data [ 3 ]; vendor_strdata

180 *( unsigned int *)& vendor_str [ 8 ] = data [ 2 ]; vendor_strdata

182 // get the family, model, stepping

183 i386_cpuid ( 1 , data ); data

-> arch . family = ( data [ 0 ] >> 8 ) & 0xf ; 184 cpuarchfamilydata

-> arch . model = ( data [ 0 ] >> 4 ) & 0xf ; 185 cpuarchmodeldata

-> arch . stepping = data [ 0 ] & 0xf ; 186 cpuarchsteppingdata

187 dprintf ( "CPU %d: family %d model %d stepping %d, string '%s'

" ,

, cpu -> arch . family , cpu -> arch . model , cpu -> arch . stepping , vendor_str ); 188 curr_cpucpuarchfamilycpuarchmodelcpuarchsteppingvendor_str

189 kprintf ( "CPU %d: family %d model %d stepping %d, string '%s'

" ,

, cpu -> arch . family , cpu -> arch . model , cpu -> arch . stepping , vendor_str ); 190 curr_cpucpuarchfamilycpuarchmodelcpuarchsteppingvendor_str

192 // figure out what vendor we have here

194 for ( i = 0 ; i < VENDOR_NUM ; i ++) { VENDOR_NUM

195 if (! strcmp ( vendor_str , vendor_info [ i ]. ident_string [ 0 ])) { vendor_strvendor_infoident_string

-> arch . vendor = i ; 196 cpuarchvendor

-> arch . vendor_name = vendor_info [ i ]. vendor ; 197 cpuarchvendor_namevendor_infovendor

198 break ;

200 if (! strcmp ( vendor_str , vendor_info [ i ]. ident_string [ 1 ])) { vendor_strvendor_infoident_string

-> arch . vendor = i ; 201 cpuarchvendor

-> arch . vendor_name = vendor_info [ i ]. vendor ; 202 cpuarchvendor_namevendor_infovendor

203 break ;

207 // see if we can get the model name

208 i386_cpuid ( 0x80000000 , data ); data

209 if ( data [ 0 ] >= 0x80000004 ) { data

210 // build the model string

211 memset ( cpu -> arch . model_name , 0 , sizeof ( cpu -> arch . model_name )); cpuarchmodel_namecpuarchmodel_name

212 i386_cpuid ( 0x80000002 , data ); data

213 memcpy ( cpu -> arch . model_name , data , sizeof ( data )); cpuarchmodel_namedatadata

214 i386_cpuid ( 0x80000003 , data ); data

215 memcpy ( cpu -> arch . model_name + 16 , data , sizeof ( data )); cpuarchmodel_namedatadata

216 i386_cpuid ( 0x80000004 , data ); data

217 memcpy ( cpu -> arch . model_name + 32 , data , sizeof ( data )); cpuarchmodel_namedatadata

219 // some cpus return a right-justified string

220 for ( i = 0 ; cpu -> arch . model_name [ i ] == ' ' ; i ++) cpuarchmodel_name

222 if ( i > 0 ) {

223 memmove ( cpu -> arch . model_name , cpuarchmodel_name

224 & cpu -> arch . model_name [ i ], cpuarchmodel_name

225 strlen (& cpu -> arch . model_name [ i ]) + 1 ); cpuarchmodel_name

228 dprintf ( "CPU %d: vendor '%s' model name '%s'

" ,

, cpu -> arch . vendor_name , cpu -> arch . model_name ); 229 curr_cpucpuarchvendor_namecpuarchmodel_name

230 kprintf ( "CPU %d: vendor '%s' model name '%s'

" ,

, cpu -> arch . vendor_name , cpu -> arch . model_name ); 231 curr_cpucpuarchvendor_namecpuarchmodel_name

232 } else {

233 strcpy ( cpu -> arch . model_name , "unknown" ); cpuarchmodel_name

236 // load feature bits

237 i386_cpuid ( 1 , data ); data

-> arch . feature [ FEATURE_COMMON ] = data [ 3 ]; // edx 238 cpuarchfeatureFEATURE_COMMONdata

-> arch . feature [ FEATURE_EXT ] = data [ 2 ]; // ecx 239 cpuarchfeatureFEATURE_EXTdata

240 if ( cpu -> arch . vendor == VENDOR_AMD ) { cpuarchvendorVENDOR_AMD

241 i386_cpuid ( 0x80000001 , data ); data

-> arch . feature [ FEATURE_EXT_AMD ] = data [ 3 ]; // edx 242 cpuarchfeatureFEATURE_EXT_AMDdata

245 make_feature_string ( cpu , cpu -> arch . feature_string ); cpucpuarchfeature_string

246 dprintf ( "CPU %d: features: %s

" , curr_cpu , cpu -> arch . feature_string ); curr_cpucpuarchfeature_string

247 kprintf ( "CPU %d: features: %s

" , curr_cpu , cpu -> arch . feature_string ); curr_cpucpuarchfeature_string

249 return 0 ;

252 int arch_cpu_init ( kernel_args * ka ) kernel_argska

254 setup_system_time ( ka -> arch_args . system_time_cv_factor ); kaarch_argssystem_time_cv_factor

256 return 0 ;

259 int arch_cpu_init_percpu ( kernel_args * ka , int curr_cpu ) kernel_argskacurr_cpu

261 detect_cpu ( ka , curr_cpu ); kacurr_cpu

263 return 0 ;

266 int arch_cpu_init2 ( kernel_args * ka ) kernel_argska

269 struct tss_descriptor * tss_d ; tss_descriptortss_d

270 unsigned int i ;

272 // account for the segment descriptors

274 vm_create_anonymous_region ( vm_get_kernel_aspace_id (), "gdt" , ( void **)& gdt , gdt

277 i386_selector_init ( gdt ); // pass the new gdt gdt

= kmalloc ( sizeof ( struct tss *) * ka -> num_cpus ); 279 tsstsskanum_cpus

280 if ( tss == NULL ) { tssNULL

281 panic ( "arch_cpu_init2: could not allocate buffer for tss pointers

" );

282 return ERR_NO_MEMORY ; ERR_NO_MEMORY

= kmalloc ( sizeof ( int ) * ka -> num_cpus ); 285 tss_loadedkanum_cpus

286 if ( tss == NULL ) { tssNULL

287 panic ( "arch_cpu_init2: could not allocate buffer for tss booleans

" );

288 return ERR_NO_MEMORY ; ERR_NO_MEMORY

290 memset ( tss_loaded , 0 , sizeof ( int ) * ka -> num_cpus ); tss_loadedkanum_cpus

292 for ( i = 0 ; i < ka -> num_cpus ; i ++) { kanum_cpus

293 char tss_name [ 16 ]; tss_name

295 sprintf ( tss_name , "tss%d" , i ); tss_name

= vm_create_anonymous_region ( vm_get_kernel_aspace_id (), tss_name , ( void **)& tss [ i ], 296 ridtss_nametss

298 if ( rid < 0 ) { rid

299 panic ( "arch_cpu_init2: unable to create region for tss

" );

300 return ERR_NO_MEMORY ; ERR_NO_MEMORY

303 memset ( tss [ i ], 0 , sizeof ( struct tss )); tsstss

306 // add TSS descriptor for this new TSS

= ( struct tss_descriptor *)& gdt [ 6 + i ]; 307 tss_dtss_descriptorgdt

-> limit_00_15 = sizeof ( struct tss ) & 0xffff ; 308 tss_dlimit_00_15tss

-> limit_19_16 = 0 ; // not this long 309 tss_dlimit_19_16

-> base_00_15 = ( addr_t ) tss [ i ] & 0xffff ; 310 tss_dbase_00_15addr_ttss

-> base_23_16 = (( addr_t ) tss [ i ] >> 16 ) & 0xff ; 311 tss_dbase_23_16addr_ttss

-> base_31_24 = ( addr_t ) tss [ i ] >> 24 ; 312 tss_dbase_31_24addr_ttss

324 /* set up the double fault tss */

325 memset (& double_fault_tss , 0 , sizeof ( double_fault_tss )); double_fault_tssdouble_fault_tss

. sp0 = ( uint32 ) double_fault_stack + sizeof ( double_fault_stack ); 326 double_fault_tsssp0uint32double_fault_stackdouble_fault_stack

328 read_cr3 ( double_fault_tss . cr3 ); // copy the current cr3 to the double fault cr3 double_fault_tsscr3

. eip = ( uint32 )& trap8 ; 329 double_fault_tsseipuint32trap8

= ( struct tss_descriptor *)& gdt [ 5 ]; 338 tss_dtss_descriptorgdt

-> limit_00_15 = sizeof ( struct tss ) & 0xffff ; 339 tss_dlimit_00_15tss

-> limit_19_16 = 0 ; // not this long 340 tss_dlimit_19_16

-> type = 0x9 ; // tss descriptor, not busy 344 tss_dtype

353 i386_set_task_gate ( 8 , DOUBLE_FAULT_TSS ); DOUBLE_FAULT_TSS

355 /* decide if we should use f* or fx* fpu save/restore instructions */

356 if ( i386_check_feature ( X86_FXSR , FEATURE_COMMON )) { X86_FXSRFEATURE_COMMON

360 } else {

366 // enable lazy fpu

367 unsigned int cr0 ; cr0

368 read_cr0 ( cr0 ); cr0

|= 0x2 ; // monitor coprocessor bit 369 cr0

370 write_cr0 ( cr0 ); cr0

372 // set up a few debug commands (in, out)

376 return 0 ;

379 bool i386_check_feature ( uint32 feature , enum i386_feature_type type ) uint32 featurei386_feature_type type

382 return cpu -> arch . feature [ type ] & feature ; cpuarchfeaturetypefeature

387 return gdt ; gdt

390 void i386_set_kstack ( addr_t kstack ) addr_t kstack

392 int curr_cpu = smp_get_current_cpu (); curr_cpu

394 // dprintf("i386_set_kstack: kstack 0x%x, cpu %d

", kstack, curr_cpu);

395 if ( tss_loaded [ curr_cpu ] == 0 ) { tss_loadedcurr_cpu

396 short seg = ( TSS + 8 * curr_cpu ); segTSScurr_cpu

397 asm ( "movw %0, %%ax;"

398 "ltr %%ax;" : : "r" ( seg ) : "eax" ); seg

406 void i386_save_fpu_context ( void * fpu_state ) fpu_state

411 void i386_load_fpu_context ( void * fpu_state ) fpu_state

416 void i386_swap_fpu_context ( void * old_fpu_state , void * new_fpu_state ) old_fpu_statenew_fpu_state

421 void arch_cpu_invalidate_TLB_range ( addr_t start , addr_t end ) addr_t startaddr_t end

423 int num_pages = end / PAGE_SIZE - start / PAGE_SIZE ; num_pagesendPAGE_SIZEstartPAGE_SIZE

424 while ( num_pages -- >= 0 ) { num_pages

425 invalidate_TLB ( start ); start

430 void arch_cpu_invalidate_TLB_list ( addr_t pages [], int num_pages ) addr_t pagesnum_pages

432 int i ;

433 for ( i = 0 ; i < num_pages ; i ++) { num_pages

434 invalidate_TLB ( pages [ i ]); pages

438 int arch_cpu_user_memcpy ( void * to , const void * from , size_t size , addr_t * fault_handler ) tofromsizeaddr_tfault_handler

440 char * tmp = ( char *) to ; tmpto

441 char * s = ( char *) from ; from

443 * fault_handler = ( addr_t )&& error ; fault_handleraddr_terror

445 while ( size --) size

446 * tmp ++ = * s ++; tmp

448 * fault_handler = 0 ; fault_handler

450 return 0 ;

452 * fault_handler = 0 ; fault_handler

453 return ERR_VM_BAD_USER_MEMORY ; ERR_VM_BAD_USER_MEMORY

456 int arch_cpu_user_strcpy ( char * to , const char * from , addr_t * fault_handler ) tofromaddr_tfault_handler

458 * fault_handler = ( addr_t )&& error ; fault_handleraddr_terror

460 while ((* to ++ = * from ++) != '\0' ) tofrom

463 * fault_handler = 0 ; fault_handler

465 return 0 ;

467 * fault_handler = 0 ; fault_handler

468 return ERR_VM_BAD_USER_MEMORY ; ERR_VM_BAD_USER_MEMORY

471 int arch_cpu_user_strncpy ( char * to , const char * from , size_t size , addr_t * fault_handler ) tofromsizeaddr_tfault_handler

473 * fault_handler = ( addr_t )&& error ; fault_handleraddr_terror

475 while ( size -- && (* to ++ = * from ++) != '\0' ) sizetofrom

478 * fault_handler = 0 ; fault_handler

480 return 0 ;

482 * fault_handler = 0 ; fault_handler

483 return ERR_VM_BAD_USER_MEMORY ; ERR_VM_BAD_USER_MEMORY

486 int arch_cpu_user_memset ( void * s , char c , size_t count , addr_t * fault_handler ) countaddr_tfault_handler

488 char * xs = ( char *) s ; xs

490 * fault_handler = ( addr_t )&& error ; fault_handleraddr_terror

492 while ( count --) count

493 * xs ++ = c ; xs

495 * fault_handler = 0 ; fault_handler

497 return 0 ;

499 * fault_handler = 0 ; fault_handler

500 return ERR_VM_BAD_USER_MEMORY ; ERR_VM_BAD_USER_MEMORY

503 void arch_cpu_idle ( void )

505 switch ( smp_get_num_cpus ()) {

506 case 0 :

507 panic ( "You need at least 1 CPU to run NewOS

" );

508 case 1 :

509 asm ( "hlt" );

510 default :

511 break ;

515 void arch_cpu_sync_icache ( void * address , size_t len ) addresslen

517 // instruction cache is always consistent on x86

520 static void dbg_in ( int argc , char ** argv ) argcargv

522 int value ; value

523 int port ; port

525 if ( argc < 2 ) { argc

526 dprintf ( "not enough args

usage: %s (1|2|4) port

" , argv [ 0 ]); argv

527 return ;

= atoul ( argv [ 2 ]); 530 portargv

532 switch ( argv [ 1 ][ 0 ]) { argv

533 case '1' :

534 case 'b' :

= in8 ( port ); 535 valueport

536 break ;

537 case '2' :

538 case 'h' :

= in16 ( port ); 539 valueport

540 break ;

541 case '4' :

542 case 'w' :

= in32 ( port ); 543 valueport

544 break ;

545 default :

546 dprintf ( "invalid width argument

" );

547 return ;

549 dprintf ( "I/O port 0x%x = 0x%x

" , port , value ); portvalue

552 static void dbg_out ( int argc , char ** argv ) argcargv

554 int value ; value

555 int port ; port

557 if ( argc < 3 ) { argc

558 dprintf ( "not enough args

usage: %s (1|2|4) port value

" , argv [ 0 ]); argv

559 return ;

= atoul ( argv [ 2 ]); 562 portargv

= atoul ( argv [ 3 ]); 563 valueargv

565 switch ( argv [ 1 ][ 0 ]) { argv

566 case '1' :

567 case 'b' :

568 out8 ( value , port ); valueport

569 break ;

570 case '2' :

571 case 'h' :

572 out16 ( value , port ); valueport

573 break ;

574 case '4' :

575 case 'w' :

576 out32 ( value , port ); valueport

577 break ;

578 default :

579 dprintf ( "invalid width argument

" );

580 return ;