1/* 2 * AMD K7 Powernow driver. 3 * (C) 2003 Dave Jones on behalf of SuSE Labs. 4 * (C) 2003-2004 Dave Jones <davej@redhat.com> 5 * 6 * Licensed under the terms of the GNU GPL License version 2. 7 * Based upon datasheets & sample CPUs kindly provided by AMD. 8 * 9 * Errata 5: 10 * CPU may fail to execute a FID/VID change in presence of interrupt. 11 * - We cli/sti on stepping A0 CPUs around the FID/VID transition. 12 * Errata 15: 13 * CPU with half frequency multipliers may hang upon wakeup from disconnect. 14 * - We disable half multipliers if ACPI is used on A0 stepping CPUs. 15 */ 16 17#include <linux/kernel.h> 18#include <linux/module.h> 19#include <linux/moduleparam.h> 20#include <linux/init.h> 21#include <linux/cpufreq.h> 22#include <linux/slab.h> 23#include <linux/string.h> 24#include <linux/dmi.h> 25#include <linux/timex.h> 26#include <linux/io.h> 27 28#include <asm/timer.h> /* Needed for recalibrate_cpu_khz() */ 29#include <asm/msr.h> 30#include <asm/system.h> 31 32#ifdef CONFIG_X86_POWERNOW_K7_ACPI 33#include <linux/acpi.h> 34#include <acpi/processor.h> 35#endif 36 37#include "powernow-k7.h" 38 39#define PFX "powernow: " 40 41 42struct psb_s { 43 u8 signature[10]; 44 u8 tableversion; 45 u8 flags; 46 u16 settlingtime; 47 u8 reserved1; 48 u8 numpst; 49}; 50 51struct pst_s { 52 u32 cpuid; 53 u8 fsbspeed; 54 u8 maxfid; 55 u8 startvid; 56 u8 numpstates; 57}; 58 59#ifdef CONFIG_X86_POWERNOW_K7_ACPI 60union powernow_acpi_control_t { 61 struct { 62 unsigned long fid:5, 63 vid:5, 64 sgtc:20, 65 res1:2; 66 } bits; 67 unsigned long val; 68}; 69#endif 70 71#ifdef CONFIG_CPU_FREQ_DEBUG 72/* divide by 1000 to get VCore voltage in V. */ 73static const int mobile_vid_table[32] = { 74 2000, 1950, 1900, 1850, 1800, 1750, 1700, 1650, 75 1600, 1550, 1500, 1450, 1400, 1350, 1300, 0, 76 1275, 1250, 1225, 1200, 1175, 1150, 1125, 1100, 77 1075, 1050, 1025, 1000, 975, 950, 925, 0, 78}; 79#endif 80 81/* divide by 10 to get FID. */ 82static const int fid_codes[32] = { 83 110, 115, 120, 125, 50, 55, 60, 65, 84 70, 75, 80, 85, 90, 95, 100, 105, 85 30, 190, 40, 200, 130, 135, 140, 210, 86 150, 225, 160, 165, 170, 180, -1, -1, 87}; 88 89/* This parameter is used in order to force ACPI instead of legacy method for 90 * configuration purpose. 91 */ 92 93static int acpi_force; 94 95static struct cpufreq_frequency_table *powernow_table; 96 97static unsigned int can_scale_bus; 98static unsigned int can_scale_vid; 99static unsigned int minimum_speed = -1; 100static unsigned int maximum_speed; 101static unsigned int number_scales; 102static unsigned int fsb; 103static unsigned int latency; 104static char have_a0; 105 106#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, \ 107 "powernow-k7", msg) 108 109static int check_fsb(unsigned int fsbspeed) 110{ 111 int delta; 112 unsigned int f = fsb / 1000; 113 114 delta = (fsbspeed > f) ? fsbspeed - f : f - fsbspeed; 115 return delta < 5; 116} 117 118static int check_powernow(void) 119{ 120 struct cpuinfo_x86 *c = &cpu_data(0); 121 unsigned int maxei, eax, ebx, ecx, edx; 122 123 if ((c->x86_vendor != X86_VENDOR_AMD) || (c->x86 != 6)) { 124#ifdef MODULE 125 printk(KERN_INFO PFX "This module only works with " 126 "AMD K7 CPUs\n"); 127#endif 128 return 0; 129 } 130 131 /* Get maximum capabilities */ 132 maxei = cpuid_eax(0x80000000); 133 if (maxei < 0x80000007) { /* Any powernow info ? */ 134#ifdef MODULE 135 printk(KERN_INFO PFX "No powernow capabilities detected\n"); 136#endif 137 return 0; 138 } 139 140 if ((c->x86_model == 6) && (c->x86_mask == 0)) { 141 printk(KERN_INFO PFX "K7 660[A0] core detected, " 142 "enabling errata workarounds\n"); 143 have_a0 = 1; 144 } 145 146 cpuid(0x80000007, &eax, &ebx, &ecx, &edx); 147 148 /* Check we can actually do something before we say anything.*/ 149 if (!(edx & (1 << 1 | 1 << 2))) 150 return 0; 151 152 printk(KERN_INFO PFX "PowerNOW! Technology present. Can scale: "); 153 154 if (edx & 1 << 1) { 155 printk("frequency"); 156 can_scale_bus = 1; 157 } 158 159 if ((edx & (1 << 1 | 1 << 2)) == 0x6) 160 printk(" and "); 161 162 if (edx & 1 << 2) { 163 printk("voltage"); 164 can_scale_vid = 1; 165 } 166 167 printk(".\n"); 168 return 1; 169} 170 171#ifdef CONFIG_X86_POWERNOW_K7_ACPI 172static void invalidate_entry(unsigned int entry) 173{ 174 powernow_table[entry].frequency = CPUFREQ_ENTRY_INVALID; 175} 176#endif 177 178static int get_ranges(unsigned char *pst) 179{ 180 unsigned int j; 181 unsigned int speed; 182 u8 fid, vid; 183 184 powernow_table = kzalloc((sizeof(struct cpufreq_frequency_table) * 185 (number_scales + 1)), GFP_KERNEL); 186 if (!powernow_table) 187 return -ENOMEM; 188 189 for (j = 0 ; j < number_scales; j++) { 190 fid = *pst++; 191 192 powernow_table[j].frequency = (fsb * fid_codes[fid]) / 10; 193 powernow_table[j].index = fid; /* lower 8 bits */ 194 195 speed = powernow_table[j].frequency; 196 197 if ((fid_codes[fid] % 10) == 5) { 198#ifdef CONFIG_X86_POWERNOW_K7_ACPI 199 if (have_a0 == 1) 200 invalidate_entry(j); 201#endif 202 } 203 204 if (speed < minimum_speed) 205 minimum_speed = speed; 206 if (speed > maximum_speed) 207 maximum_speed = speed; 208 209 vid = *pst++; 210 powernow_table[j].index |= (vid << 8); /* upper 8 bits */ 211 212 dprintk(" FID: 0x%x (%d.%dx [%dMHz]) " 213 "VID: 0x%x (%d.%03dV)\n", fid, fid_codes[fid] / 10, 214 fid_codes[fid] % 10, speed/1000, vid, 215 mobile_vid_table[vid]/1000, 216 mobile_vid_table[vid]%1000); 217 } 218 powernow_table[number_scales].frequency = CPUFREQ_TABLE_END; 219 powernow_table[number_scales].index = 0; 220 221 return 0; 222} 223 224 225static void change_FID(int fid) 226{ 227 union msr_fidvidctl fidvidctl; 228 229 rdmsrl(MSR_K7_FID_VID_CTL, fidvidctl.val); 230 if (fidvidctl.bits.FID != fid) { 231 fidvidctl.bits.SGTC = latency; 232 fidvidctl.bits.FID = fid; 233 fidvidctl.bits.VIDC = 0; 234 fidvidctl.bits.FIDC = 1; 235 wrmsrl(MSR_K7_FID_VID_CTL, fidvidctl.val); 236 } 237} 238 239 240static void change_VID(int vid) 241{ 242 union msr_fidvidctl fidvidctl; 243 244 rdmsrl(MSR_K7_FID_VID_CTL, fidvidctl.val); 245 if (fidvidctl.bits.VID != vid) { 246 fidvidctl.bits.SGTC = latency; 247 fidvidctl.bits.VID = vid; 248 fidvidctl.bits.FIDC = 0; 249 fidvidctl.bits.VIDC = 1; 250 wrmsrl(MSR_K7_FID_VID_CTL, fidvidctl.val); 251 } 252} 253 254 255static void change_speed(unsigned int index) 256{ 257 u8 fid, vid; 258 struct cpufreq_freqs freqs; 259 union msr_fidvidstatus fidvidstatus; 260 int cfid; 261 262 /* fid are the lower 8 bits of the index we stored into 263 * the cpufreq frequency table in powernow_decode_bios, 264 * vid are the upper 8 bits. 265 */ 266 267 fid = powernow_table[index].index & 0xFF; 268 vid = (powernow_table[index].index & 0xFF00) >> 8; 269 270 freqs.cpu = 0; 271 272 rdmsrl(MSR_K7_FID_VID_STATUS, fidvidstatus.val); 273 cfid = fidvidstatus.bits.CFID; 274 freqs.old = fsb * fid_codes[cfid] / 10; 275 276 freqs.new = powernow_table[index].frequency; 277 278 cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); 279 280 /* Now do the magic poking into the MSRs. */ 281 282 if (have_a0 == 1) /* A0 errata 5 */ 283 local_irq_disable(); 284 285 if (freqs.old > freqs.new) { 286 /* Going down, so change FID first */ 287 change_FID(fid); 288 change_VID(vid); 289 } else { 290 /* Going up, so change VID first */ 291 change_VID(vid); 292 change_FID(fid); 293 } 294 295 296 if (have_a0 == 1) 297 local_irq_enable(); 298 299 cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); 300} 301 302 303#ifdef CONFIG_X86_POWERNOW_K7_ACPI 304 305static struct acpi_processor_performance *acpi_processor_perf; 306 307static int powernow_acpi_init(void) 308{ 309 int i; 310 int retval = 0; 311 union powernow_acpi_control_t pc; 312 313 if (acpi_processor_perf != NULL && powernow_table != NULL) { 314 retval = -EINVAL; 315 goto err0; 316 } 317 318 acpi_processor_perf = kzalloc(sizeof(struct acpi_processor_performance), 319 GFP_KERNEL); 320 if (!acpi_processor_perf) { 321 retval = -ENOMEM; 322 goto err0; 323 } 324 325 if (!zalloc_cpumask_var(&acpi_processor_perf->shared_cpu_map, 326 GFP_KERNEL)) { 327 retval = -ENOMEM; 328 goto err05; 329 } 330 331 if (acpi_processor_register_performance(acpi_processor_perf, 0)) { 332 retval = -EIO; 333 goto err1; 334 } 335 336 if (acpi_processor_perf->control_register.space_id != 337 ACPI_ADR_SPACE_FIXED_HARDWARE) { 338 retval = -ENODEV; 339 goto err2; 340 } 341 342 if (acpi_processor_perf->status_register.space_id != 343 ACPI_ADR_SPACE_FIXED_HARDWARE) { 344 retval = -ENODEV; 345 goto err2; 346 } 347 348 number_scales = acpi_processor_perf->state_count; 349 350 if (number_scales < 2) { 351 retval = -ENODEV; 352 goto err2; 353 } 354 355 powernow_table = kzalloc((sizeof(struct cpufreq_frequency_table) * 356 (number_scales + 1)), GFP_KERNEL); 357 if (!powernow_table) { 358 retval = -ENOMEM; 359 goto err2; 360 } 361 362 pc.val = (unsigned long) acpi_processor_perf->states[0].control; 363 for (i = 0; i < number_scales; i++) { 364 u8 fid, vid; 365 struct acpi_processor_px *state = 366 &acpi_processor_perf->states[i]; 367 unsigned int speed, speed_mhz; 368 369 pc.val = (unsigned long) state->control; 370 dprintk("acpi: P%d: %d MHz %d mW %d uS control %08x SGTC %d\n", 371 i, 372 (u32) state->core_frequency, 373 (u32) state->power, 374 (u32) state->transition_latency, 375 (u32) state->control, 376 pc.bits.sgtc); 377 378 vid = pc.bits.vid; 379 fid = pc.bits.fid; 380 381 powernow_table[i].frequency = fsb * fid_codes[fid] / 10; 382 powernow_table[i].index = fid; /* lower 8 bits */ 383 powernow_table[i].index |= (vid << 8); /* upper 8 bits */ 384 385 speed = powernow_table[i].frequency; 386 speed_mhz = speed / 1000; 387 388 /* processor_perflib will multiply the MHz value by 1000 to 389 * get a KHz value (e.g. 1266000). However, powernow-k7 works 390 * with true KHz values (e.g. 1266768). To ensure that all 391 * powernow frequencies are available, we must ensure that 392 * ACPI doesn't restrict them, so we round up the MHz value 393 * to ensure that perflib's computed KHz value is greater than 394 * or equal to powernow's KHz value. 395 */ 396 if (speed % 1000 > 0) 397 speed_mhz++; 398 399 if ((fid_codes[fid] % 10) == 5) { 400 if (have_a0 == 1) 401 invalidate_entry(i); 402 } 403 404 dprintk(" FID: 0x%x (%d.%dx [%dMHz]) " 405 "VID: 0x%x (%d.%03dV)\n", fid, fid_codes[fid] / 10, 406 fid_codes[fid] % 10, speed_mhz, vid, 407 mobile_vid_table[vid]/1000, 408 mobile_vid_table[vid]%1000); 409 410 if (state->core_frequency != speed_mhz) { 411 state->core_frequency = speed_mhz; 412 dprintk(" Corrected ACPI frequency to %d\n", 413 speed_mhz); 414 } 415 416 if (latency < pc.bits.sgtc) 417 latency = pc.bits.sgtc; 418 419 if (speed < minimum_speed) 420 minimum_speed = speed; 421 if (speed > maximum_speed) 422 maximum_speed = speed; 423 } 424 425 powernow_table[i].frequency = CPUFREQ_TABLE_END; 426 powernow_table[i].index = 0; 427 428 /* notify BIOS that we exist */ 429 acpi_processor_notify_smm(THIS_MODULE); 430 431 return 0; 432 433err2: 434 acpi_processor_unregister_performance(acpi_processor_perf, 0); 435err1: 436 free_cpumask_var(acpi_processor_perf->shared_cpu_map); 437err05: 438 kfree(acpi_processor_perf); 439err0: 440 printk(KERN_WARNING PFX "ACPI perflib can not be used on " 441 "this platform\n"); 442 acpi_processor_perf = NULL; 443 return retval; 444} 445#else 446static int powernow_acpi_init(void) 447{ 448 printk(KERN_INFO PFX "no support for ACPI processor found." 449 " Please recompile your kernel with ACPI processor\n"); 450 return -EINVAL; 451} 452#endif 453 454static void print_pst_entry(struct pst_s *pst, unsigned int j) 455{ 456 dprintk("PST:%d (@%p)\n", j, pst); 457 dprintk(" cpuid: 0x%x fsb: %d maxFID: 0x%x startvid: 0x%x\n", 458 pst->cpuid, pst->fsbspeed, pst->maxfid, pst->startvid); 459} 460 461static int powernow_decode_bios(int maxfid, int startvid) 462{ 463 struct psb_s *psb; 464 struct pst_s *pst; 465 unsigned int i, j; 466 unsigned char *p; 467 unsigned int etuple; 468 unsigned int ret; 469 470 etuple = cpuid_eax(0x80000001); 471 472 for (i = 0xC0000; i < 0xffff0 ; i += 16) { 473 474 p = phys_to_virt(i); 475 476 if (memcmp(p, "AMDK7PNOW!", 10) == 0) { 477 dprintk("Found PSB header at %p\n", p); 478 psb = (struct psb_s *) p; 479 dprintk("Table version: 0x%x\n", psb->tableversion); 480 if (psb->tableversion != 0x12) { 481 printk(KERN_INFO PFX "Sorry, only v1.2 tables" 482 " supported right now\n"); 483 return -ENODEV; 484 } 485 486 dprintk("Flags: 0x%x\n", psb->flags); 487 if ((psb->flags & 1) == 0) 488 dprintk("Mobile voltage regulator\n"); 489 else 490 dprintk("Desktop voltage regulator\n"); 491 492 latency = psb->settlingtime; 493 if (latency < 100) { 494 printk(KERN_INFO PFX "BIOS set settling time " 495 "to %d microseconds. " 496 "Should be at least 100. " 497 "Correcting.\n", latency); 498 latency = 100; 499 } 500 dprintk("Settling Time: %d microseconds.\n", 501 psb->settlingtime); 502 dprintk("Has %d PST tables. (Only dumping ones " 503 "relevant to this CPU).\n", 504 psb->numpst); 505 506 p += sizeof(struct psb_s); 507 508 pst = (struct pst_s *) p; 509 510 for (j = 0; j < psb->numpst; j++) { 511 pst = (struct pst_s *) p; 512 number_scales = pst->numpstates; 513 514 if ((etuple == pst->cpuid) && 515 check_fsb(pst->fsbspeed) && 516 (maxfid == pst->maxfid) && 517 (startvid == pst->startvid)) { 518 print_pst_entry(pst, j); 519 p = (char *)pst + sizeof(struct pst_s); 520 ret = get_ranges(p); 521 return ret; 522 } else { 523 unsigned int k; 524 p = (char *)pst + sizeof(struct pst_s); 525 for (k = 0; k < number_scales; k++) 526 p += 2; 527 } 528 } 529 printk(KERN_INFO PFX "No PST tables match this cpuid " 530 "(0x%x)\n", etuple); 531 printk(KERN_INFO PFX "This is indicative of a broken " 532 "BIOS.\n"); 533 534 return -EINVAL; 535 } 536 p++; 537 } 538 539 return -ENODEV; 540} 541 542 543static int powernow_target(struct cpufreq_policy *policy, 544 unsigned int target_freq, 545 unsigned int relation) 546{ 547 unsigned int newstate; 548 549 if (cpufreq_frequency_table_target(policy, powernow_table, target_freq, 550 relation, &newstate)) 551 return -EINVAL; 552 553 change_speed(newstate); 554 555 return 0; 556} 557 558 559static int powernow_verify(struct cpufreq_policy *policy) 560{ 561 return cpufreq_frequency_table_verify(policy, powernow_table); 562} 563 564/* 565 * We use the fact that the bus frequency is somehow 566 * a multiple of 100000/3 khz, then we compute sgtc according 567 * to this multiple. 568 * That way, we match more how AMD thinks all of that work. 569 * We will then get the same kind of behaviour already tested under 570 * the "well-known" other OS. 571 */ 572static int __cpuinit fixup_sgtc(void) 573{ 574 unsigned int sgtc; 575 unsigned int m; 576 577 m = fsb / 3333; 578 if ((m % 10) >= 5) 579 m += 5; 580 581 m /= 10; 582 583 sgtc = 100 * m * latency; 584 sgtc = sgtc / 3; 585 if (sgtc > 0xfffff) { 586 printk(KERN_WARNING PFX "SGTC too large %d\n", sgtc); 587 sgtc = 0xfffff; 588 } 589 return sgtc; 590} 591 592static unsigned int powernow_get(unsigned int cpu) 593{ 594 union msr_fidvidstatus fidvidstatus; 595 unsigned int cfid; 596 597 if (cpu) 598 return 0; 599 rdmsrl(MSR_K7_FID_VID_STATUS, fidvidstatus.val); 600 cfid = fidvidstatus.bits.CFID; 601 602 return fsb * fid_codes[cfid] / 10; 603} 604 605 606static int __cpuinit acer_cpufreq_pst(const struct dmi_system_id *d) 607{ 608 printk(KERN_WARNING PFX 609 "%s laptop with broken PST tables in BIOS detected.\n", 610 d->ident); 611 printk(KERN_WARNING PFX 612 "You need to downgrade to 3A21 (09/09/2002), or try a newer " 613 "BIOS than 3A71 (01/20/2003)\n"); 614 printk(KERN_WARNING PFX 615 "cpufreq scaling has been disabled as a result of this.\n"); 616 return 0; 617} 618 619/* 620 * Some Athlon laptops have really fucked PST tables. 621 * A BIOS update is all that can save them. 622 * Mention this, and disable cpufreq. 623 */ 624static struct dmi_system_id __cpuinitdata powernow_dmi_table[] = { 625 { 626 .callback = acer_cpufreq_pst, 627 .ident = "Acer Aspire", 628 .matches = { 629 DMI_MATCH(DMI_SYS_VENDOR, "Insyde Software"), 630 DMI_MATCH(DMI_BIOS_VERSION, "3A71"), 631 }, 632 }, 633 { } 634}; 635 636static int __cpuinit powernow_cpu_init(struct cpufreq_policy *policy) 637{ 638 union msr_fidvidstatus fidvidstatus; 639 int result; 640 641 if (policy->cpu != 0) 642 return -ENODEV; 643 644 rdmsrl(MSR_K7_FID_VID_STATUS, fidvidstatus.val); 645 646 recalibrate_cpu_khz(); 647 648 fsb = (10 * cpu_khz) / fid_codes[fidvidstatus.bits.CFID]; 649 if (!fsb) { 650 printk(KERN_WARNING PFX "can not determine bus frequency\n"); 651 return -EINVAL; 652 } 653 dprintk("FSB: %3dMHz\n", fsb/1000); 654 655 if (dmi_check_system(powernow_dmi_table) || acpi_force) { 656 printk(KERN_INFO PFX "PSB/PST known to be broken. " 657 "Trying ACPI instead\n"); 658 result = powernow_acpi_init(); 659 } else { 660 result = powernow_decode_bios(fidvidstatus.bits.MFID, 661 fidvidstatus.bits.SVID); 662 if (result) { 663 printk(KERN_INFO PFX "Trying ACPI perflib\n"); 664 maximum_speed = 0; 665 minimum_speed = -1; 666 latency = 0; 667 result = powernow_acpi_init(); 668 if (result) { 669 printk(KERN_INFO PFX 670 "ACPI and legacy methods failed\n"); 671 } 672 } else { 673 /* SGTC use the bus clock as timer */ 674 latency = fixup_sgtc(); 675 printk(KERN_INFO PFX "SGTC: %d\n", latency); 676 } 677 } 678 679 if (result) 680 return result; 681 682 printk(KERN_INFO PFX "Minimum speed %d MHz. Maximum speed %d MHz.\n", 683 minimum_speed/1000, maximum_speed/1000); 684 685 policy->cpuinfo.transition_latency = 686 cpufreq_scale(2000000UL, fsb, latency); 687 688 policy->cur = powernow_get(0); 689 690 cpufreq_frequency_table_get_attr(powernow_table, policy->cpu); 691 692 return cpufreq_frequency_table_cpuinfo(policy, powernow_table); 693} 694 695static int powernow_cpu_exit(struct cpufreq_policy *policy) 696{ 697 cpufreq_frequency_table_put_attr(policy->cpu); 698 699#ifdef CONFIG_X86_POWERNOW_K7_ACPI 700 if (acpi_processor_perf) { 701 acpi_processor_unregister_performance(acpi_processor_perf, 0); 702 free_cpumask_var(acpi_processor_perf->shared_cpu_map); 703 kfree(acpi_processor_perf); 704 } 705#endif 706 707 kfree(powernow_table); 708 return 0; 709} 710 711static struct freq_attr *powernow_table_attr[] = { 712 &cpufreq_freq_attr_scaling_available_freqs, 713 NULL, 714}; 715 716static struct cpufreq_driver powernow_driver = { 717 .verify = powernow_verify, 718 .target = powernow_target, 719 .get = powernow_get, 720#ifdef CONFIG_X86_POWERNOW_K7_ACPI 721 .bios_limit = acpi_processor_get_bios_limit, 722#endif 723 .init = powernow_cpu_init, 724 .exit = powernow_cpu_exit, 725 .name = "powernow-k7", 726 .owner = THIS_MODULE, 727 .attr = powernow_table_attr, 728}; 729 730static int __init powernow_init(void) 731{ 732 if (check_powernow() == 0) 733 return -ENODEV; 734 return cpufreq_register_driver(&powernow_driver); 735} 736 737 738static void __exit powernow_exit(void) 739{ 740 cpufreq_unregister_driver(&powernow_driver); 741} 742 743module_param(acpi_force, int, 0444); 744MODULE_PARM_DESC(acpi_force, "Force ACPI to be used."); 745 746MODULE_AUTHOR("Dave Jones <davej@redhat.com>"); 747MODULE_DESCRIPTION("Powernow driver for AMD K7 processors."); 748MODULE_LICENSE("GPL"); 749 750late_initcall(powernow_init); 751module_exit(powernow_exit); 752