# # Copyright (C) 2006-2011 OpenWrt.org # # This is free software, licensed under the GNU General Public License v2. # See /LICENSE for more information. # CRYPTO_MENU:=Cryptographic API modules CRYPTO_MODULES = \ ALGAPI2=crypto_algapi \ BLKCIPHER2=crypto_blkcipher CRYPTOMGR_MODULES = \ AEAD2=aead \ MANAGER2=cryptomgr \ crypto_confvar=CONFIG_CRYPTO_$(word 1,$(subst =,$(space),$(1))) crypto_file=$(LINUX_DIR)/crypto/$(word 2,$(subst =,$(space),$(1))).ko crypto_name=$(if $(findstring y,$($(call crypto_confvar,$(1)))),,$(word 2,$(subst =,$(space),$(1)))) define KernelPackage/crypto-core SUBMENU:=$(CRYPTO_MENU) TITLE:=Core CryptoAPI modules KCONFIG:= \ CONFIG_CRYPTO=y \ CONFIG_CRYPTO_HW=y \ CONFIG_CRYPTO_BLKCIPHER \ CONFIG_CRYPTO_ALGAPI \ $(foreach mod,$(CRYPTO_MODULES),$(call crypto_confvar,$(mod))) FILES:=$(foreach mod,$(CRYPTO_MODULES),$(call crypto_file,$(mod))) endef $(eval $(call KernelPackage,crypto-core)) define AddDepends/crypto SUBMENU:=$(CRYPTO_MENU) DEPENDS+=+kmod-crypto-core $(1) endef define KernelPackage/crypto-hash TITLE:=CryptoAPI hash support KCONFIG:=CONFIG_CRYPTO_HASH FILES:=$(LINUX_DIR)/crypto/crypto_hash.ko AUTOLOAD:=$(call AutoLoad,02,crypto_hash,1) $(call AddDepends/crypto) endef $(eval $(call KernelPackage,crypto-hash)) define KernelPackage/crypto-manager TITLE:=CryptoAPI algorithm manager DEPENDS:=+kmod-crypto-hash +kmod-crypto-pcompress KCONFIG:= \ CONFIG_CRYPTO_AEAD \ CONFIG_CRYPTO_MANAGER \ $(foreach mod,$(CRYPTOMGR_MODULES),$(call crypto_confvar,$(mod))) FILES:=$(foreach mod,$(CRYPTOMGR_MODULES),$(call crypto_file,$(mod))) $(call AddDepends/crypto) endef $(eval $(call KernelPackage,crypto-manager)) define KernelPackage/crypto-pcompress TITLE:=CryptoAPI Partial (de)compression operations KCONFIG:= \ CONFIG_CRYPTO_PCOMP=y \ CONFIG_CRYPTO_PCOMP2 FILES:=$(LINUX_DIR)/crypto/pcompress.ko AUTOLOAD:=$(call AutoLoad,09,pcompress) $(call AddDepends/crypto) endef $(eval $(call KernelPackage,crypto-pcompress)) define KernelPackage/crypto-user TITLE:=CryptoAPI userspace interface DEPENDS:=+kmod-crypto-hash +kmod-crypto-manager KCONFIG:= \ CONFIG_CRYPTO_USER_API \ CONFIG_CRYPTO_USER_API_HASH \ CONFIG_CRYPTO_USER_API_SKCIPHER FILES:= \ $(LINUX_DIR)/crypto/af_alg.ko \ $(LINUX_DIR)/crypto/algif_hash.ko \ $(LINUX_DIR)/crypto/algif_skcipher.ko AUTOLOAD:=$(call AutoLoad,09,af_alg algif_hash algif_skcipher) $(call AddDepends/crypto) endef $(eval $(call KernelPackage,crypto-user)) define KernelPackage/crypto-wq TITLE:=CryptoAPI work queue handling KCONFIG:=CONFIG_CRYPTO_WORKQUEUE FILES:=$(LINUX_DIR)/crypto/crypto_wq.ko AUTOLOAD:=$(call AutoLoad,09,crypto_wq) $(call AddDepends/crypto) endef $(eval $(call KernelPackage,crypto-wq)) define KernelPackage/crypto-rng TITLE:=CryptoAPI random number generation KCONFIG:=CONFIG_CRYPTO_RNG2 FILES:= \ $(LINUX_DIR)/crypto/rng.ko \ $(LINUX_DIR)/crypto/krng.ko AUTOLOAD:=$(call AutoLoad,09,rng krng) $(call AddDepends/crypto) endef $(eval $(call KernelPackage,crypto-rng)) define KernelPackage/crypto-iv TITLE:=CryptoAPI initialization vectors DEPENDS:=+kmod-crypto-manager +kmod-crypto-rng +kmod-crypto-wq KCONFIG:= CONFIG_CRYPTO_BLKCIPHER2 FILES:= \ $(LINUX_DIR)/crypto/eseqiv.ko \ $(LINUX_DIR)/crypto/chainiv.ko AUTOLOAD:=$(call AutoLoad,10,eseqiv chainiv) $(call AddDepends/crypto) endef $(eval $(call KernelPackage,crypto-iv)) define KernelPackage/crypto-hw-talitos TITLE:=Freescale integrated security engine (SEC) driver DEPENDS:=+kmod-crypto-aes +kmod-crypto-manager +kmod-crypto-hash +kmod-random-core KCONFIG:= \ CONFIG_CRYPTO_DEV_TALITOS FILES:= \ $(LINUX_DIR)/drivers/crypto/talitos.ko AUTOLOAD:=$(call AutoLoad,09,talitos) $(call AddDepends/crypto) endef $(eval $(call KernelPackage,crypto-hw-talitos)) define KernelPackage/crypto-hw-padlock TITLE:=VIA PadLock ACE with AES/SHA hw crypto module DEPENDS:=+kmod-crypto-aes +kmod-crypto-manager KCONFIG:= \ CONFIG_CRYPTO_DEV_PADLOCK \ CONFIG_CRYPTO_DEV_PADLOCK_AES \ CONFIG_CRYPTO_DEV_PADLOCK_SHA FILES:= \ $(LINUX_DIR)/drivers/crypto/padlock-aes.ko \ $(LINUX_DIR)/drivers/crypto/padlock-sha.ko AUTOLOAD:=$(call AutoLoad,09,padlock-aes padlock-sha) $(call AddDepends/crypto) endef $(eval $(call KernelPackage,crypto-hw-padlock)) define KernelPackage/crypto-hw-geode TITLE:=AMD Geode hardware crypto module DEPENDS:=+kmod-crypto-manager KCONFIG:= \ CONFIG_CRYPTO_DEV_GEODE FILES:=$(LINUX_DIR)/drivers/crypto/geode-aes.ko AUTOLOAD:=$(call AutoLoad,09,geode-aes) $(call AddDepends/crypto) endef $(eval $(call KernelPackage,crypto-hw-geode)) define KernelPackage/crypto-hw-hifn-795x TITLE:=HIFN 795x crypto accelerator DEPENDS:=+kmod-random-core +kmod-crypto-manager KCONFIG:= \ CONFIG_CRYPTO_DEV_HIFN_795X \ CONFIG_CRYPTO_DEV_HIFN_795X_RNG=y FILES:=$(LINUX_DIR)/drivers/crypto/hifn_795x.ko AUTOLOAD:=$(call AutoLoad,09,hifn_795x) $(call AddDepends/crypto,+kmod-crypto-des) endef $(eval $(call KernelPackage,crypto-hw-hifn-795x)) define KernelPackage/crypto-hw-ppc4xx TITLE:=AMCC PPC4xx hardware crypto module DEPENDS:=@TARGET_ppc40x||TARGET_ppc44x KCONFIG:= \ CONFIG_CRYPTO_DEV_PPC4XX FILES:=$(LINUX_DIR)/drivers/crypto/amcc/crypto4xx.ko AUTOLOAD:=$(call AutoLoad,90,crypto4xx) $(call AddDepends/crypto,+kmod-crypto-manager +kmod-crypto-hash) endef define KernelPackage/crypto-hw-ppc4xx/description Kernel support for the AMCC PPC4xx HW crypto engine. endef $(eval $(call KernelPackage,crypto-hw-ppc4xx)) define KernelPackage/crypto-hw-omap TITLE:=TI OMAP hardware crypto modules DEPENDS:=@TARGET_omap KCONFIG:= \ CONFIG_CRYPTO_DEV_OMAP_AES \ CONFIG_CRYPTO_DEV_OMAP_DES \ CONFIG_CRYPTO_DEV_OMAP_SHAM FILES:= \ $(LINUX_DIR)/drivers/crypto/omap-aes.ko \ $(LINUX_DIR)/drivers/crypto/omap-des.ko \ $(LINUX_DIR)/drivers/crypto/omap-sham.ko AUTOLOAD:=$(call AutoLoad,90,omap-aes omap-des omap-sham) $(call AddDepends/crypto,+kmod-crypto-manager +kmod-crypto-hash) endef define KernelPackage/crypto-hw-omap/description Kernel support for the TI OMAP HW crypto engine. endef $(eval $(call KernelPackage,crypto-hw-omap)) define KernelPackage/crypto-aes TITLE:=AES cipher CryptoAPI module KCONFIG:=CONFIG_CRYPTO_AES CONFIG_CRYPTO_AES_586 FILES:=$(LINUX_DIR)/crypto/aes_generic.ko AUTOLOAD:=$(call AutoLoad,09,aes_generic) $(call AddDepends/crypto) endef define KernelPackage/crypto-aes/x86 FILES+=$(LINUX_DIR)/arch/x86/crypto/aes-i586.ko AUTOLOAD:=$(call AutoLoad,09,aes-i586) endef $(eval $(call KernelPackage,crypto-aes)) define KernelPackage/crypto-arc4 TITLE:=ARC4 (RC4) cipher CryptoAPI module KCONFIG:=CONFIG_CRYPTO_ARC4 FILES:=$(LINUX_DIR)/crypto/arc4.ko AUTOLOAD:=$(call AutoLoad,09,arc4) $(call AddDepends/crypto) endef $(eval $(call KernelPackage,crypto-arc4)) define KernelPackage/crypto-authenc TITLE:=Combined mode wrapper for IPsec DEPENDS:=+kmod-crypto-manager KCONFIG:=CONFIG_CRYPTO_AUTHENC FILES:=$(LINUX_DIR)/crypto/authenc.ko AUTOLOAD:=$(call AutoLoad,09,authenc) $(call AddDepends/crypto) endef $(eval $(call KernelPackage,crypto-authenc)) define KernelPackage/crypto-cbc TITLE:=Cipher Block Chaining CryptoAPI module DEPENDS:=+kmod-crypto-manager KCONFIG:=CONFIG_CRYPTO_CBC FILES:=$(LINUX_DIR)/crypto/cbc.ko AUTOLOAD:=$(call AutoLoad,09,cbc) $(call AddDepends/crypto) endef $(eval $(call KernelPackage,crypto-cbc)) define KernelPackage/crypto-crc32c TITLE:=CRC32c CRC module DEPENDS:=+kmod-crypto-hash KCONFIG:=CONFIG_CRYPTO_CRC32C FILES:=$(LINUX_DIR)/crypto/crc32c.ko AUTOLOAD:=$(call AutoLoad,04,crc32c,1) $(call AddDepends/crypto) endef $(eval $(call KernelPackage,crypto-crc32c)) define KernelPackage/crypto-des TITLE:=DES/3DES cipher CryptoAPI module KCONFIG:=CONFIG_CRYPTO_DES FILES:=$(LINUX_DIR)/crypto/des_generic.ko AUTOLOAD:=$(call AutoLoad,09,des_generic) $(call AddDepends/crypto) endef $(eval $(call KernelPackage,crypto-des)) define KernelPackage/crypto-deflate TITLE:=Deflate compression CryptoAPI module DEPENDS:=+kmod-lib-zlib KCONFIG:=CONFIG_CRYPTO_DEFLATE FILES:=$(LINUX_DIR)/crypto/deflate.ko AUTOLOAD:=$(call AutoLoad,09,deflate) $(call AddDepends/crypto) endef $(eval $(call KernelPackage,crypto-deflate)) define KernelPackage/crypto-ecb TITLE:=Electronic CodeBook CryptoAPI module DEPENDS:=+kmod-crypto-manager KCONFIG:=CONFIG_CRYPTO_ECB FILES:=$(LINUX_DIR)/crypto/ecb.ko AUTOLOAD:=$(call AutoLoad,09,ecb) $(call AddDepends/crypto) endef $(eval $(call KernelPackage,crypto-ecb)) define KernelPackage/crypto-hmac TITLE:=HMAC digest CryptoAPI module DEPENDS:=+kmod-crypto-hash KCONFIG:=CONFIG_CRYPTO_HMAC FILES:=$(LINUX_DIR)/crypto/hmac.ko DEPENDS:=+kmod-crypto-manager AUTOLOAD:=$(call AutoLoad,09,hmac) $(call AddDepends/crypto) endef $(eval $(call KernelPackage,crypto-hmac)) define KernelPackage/crypto-md4 TITLE:=MD4 digest CryptoAPI module DEPENDS:=+kmod-crypto-hash KCONFIG:=CONFIG_CRYPTO_MD4 FILES:=$(LINUX_DIR)/crypto/md4.ko AUTOLOAD:=$(call AutoLoad,09,md4) $(call AddDepends/crypto) endef $(eval $(call KernelPackage,crypto-md4)) define KernelPackage/crypto-md5 TITLE:=MD5 digest CryptoAPI module DEPENDS:=+kmod-crypto-hash KCONFIG:=CONFIG_CRYPTO_MD5 FILES:=$(LINUX_DIR)/crypto/md5.ko AUTOLOAD:=$(call AutoLoad,09,md5) $(call AddDepends/crypto) endef $(eval $(call KernelPackage,crypto-md5)) define KernelPackage/crypto-michael-mic TITLE:=Michael MIC keyed digest CryptoAPI module DEPENDS:=+kmod-crypto-hash KCONFIG:=CONFIG_CRYPTO_MICHAEL_MIC FILES:=$(LINUX_DIR)/crypto/michael_mic.ko AUTOLOAD:=$(call AutoLoad,09,michael_mic) $(call AddDepends/crypto) endef $(eval $(call KernelPackage,crypto-michael-mic)) define KernelPackage/crypto-sha1 TITLE:=SHA1 digest CryptoAPI module DEPENDS:=+kmod-crypto-hash KCONFIG:=CONFIG_CRYPTO_SHA1 FILES:=$(LINUX_DIR)/crypto/sha1_generic.ko AUTOLOAD:=$(call AutoLoad,09,sha1_generic) $(call AddDepends/crypto) endef $(eval $(call KernelPackage,crypto-sha1)) define KernelPackage/crypto-sha256 TITLE:=SHA224 SHA256 digest CryptoAPI module DEPENDS:=+kmod-crypto-hash KCONFIG:=CONFIG_CRYPTO_SHA256 FILES:=$(LINUX_DIR)/crypto/sha256_generic.ko AUTOLOAD:=$(call AutoLoad,09,sha256_generic) $(call AddDepends/crypto) endef $(eval $(call KernelPackage,crypto-sha256)) ifeq ($(strip $(call CompareKernelPatchVer,$(KERNEL_PATCHVER),ge,3.6.0)),1) camellia_mod_suffix=_generic endif ifeq ($(strip $(call CompareKernelPatchVer,$(KERNEL_PATCHVER),ge,3.7.0)),1) cast56_mod_suffix=_generic endif define KernelPackage/crypto-misc TITLE:=Other CryptoAPI modules DEPENDS:=+kmod-crypto-manager KCONFIG:= \ CONFIG_CRYPTO_ANUBIS \ CONFIG_CRYPTO_BLOWFISH \ CONFIG_CRYPTO_CAMELLIA \ CONFIG_CRYPTO_CAST5 \ CONFIG_CRYPTO_CAST6 \ CONFIG_CRYPTO_FCRYPT \ CONFIG_CRYPTO_KHAZAD \ CONFIG_CRYPTO_SERPENT \ CONFIG_CRYPTO_SHA512 \ CONFIG_CRYPTO_TEA \ CONFIG_CRYPTO_TGR192 \ CONFIG_CRYPTO_TWOFISH \ CONFIG_CRYPTO_TWOFISH_COMMON \ CONFIG_CRYPTO_TWOFISH_586 \ CONFIG_CRYPTO_WP512 FILES:= \ $(LINUX_DIR)/crypto/anubis.ko \ $(LINUX_DIR)/crypto/camellia$(camellia_mod_suffix).ko \ $(if $(call kernel_patchver_ge,3.7),$(LINUX_DIR)/crypto/cast_common.ko) \ $(LINUX_DIR)/crypto/cast5$(cast56_mod_suffix).ko \ $(LINUX_DIR)/crypto/cast6$(cast56_mod_suffix).ko \ $(LINUX_DIR)/crypto/fcrypt.ko \ $(LINUX_DIR)/crypto/khazad.ko \ $(LINUX_DIR)/crypto/sha512_generic.ko \ $(LINUX_DIR)/crypto/tea.ko \ $(LINUX_DIR)/crypto/tgr192.ko \ $(LINUX_DIR)/crypto/twofish_common.ko \ $(LINUX_DIR)/crypto/wp512.ko \ $(LINUX_DIR)/crypto/twofish_generic.ko \ $(LINUX_DIR)/crypto/blowfish_common.ko \ $(LINUX_DIR)/crypto/blowfish_generic.ko \ $(LINUX_DIR)/crypto/serpent_generic.ko $(call AddDepends/crypto) endef define KernelPackage/crypto-misc/x86 FILES+=$(LINUX_DIR)/arch/x86/crypto/twofish-i586.ko endef $(eval $(call KernelPackage,crypto-misc)) define KernelPackage/crypto-ocf TITLE:=OCF modules DEPENDS:=+@OPENSSL_ENGINE_CRYPTO @!TARGET_uml +kmod-crypto-manager KCONFIG:= \ CONFIG_OCF_OCF \ CONFIG_OCF_CRYPTODEV \ CONFIG_OCF_CRYPTOSOFT \ CONFIG_OCF_FIPS=y \ CONFIG_OCF_RANDOMHARVEST=y FILES:= \ $(LINUX_DIR)/crypto/ocf/ocf.ko \ $(LINUX_DIR)/crypto/ocf/cryptodev.ko \ $(LINUX_DIR)/crypto/ocf/cryptosoft.ko AUTOLOAD:=$(call AutoLoad,09, \ ocf \ cryptodev \ cryptosoft \ ) $(call AddDepends/crypto) endef $(eval $(call KernelPackage,crypto-ocf)) define KernelPackage/crypto-ocf-hifn7751 TITLE:=OCF support for Hifn 6500/7751/7811/795x, Invertex AEON and NetSec 7751 devices DEPENDS:=+@OPENSSL_ENGINE_CRYPTO @PCI_SUPPORT @!TARGET_uml kmod-crypto-ocf KCONFIG:=CONFIG_OCF_HIFN FILES:=$(LINUX_DIR)/crypto/ocf/hifn/hifn7751.ko AUTOLOAD:=$(call AutoLoad,10,hifn7751) $(call AddDepends/crypto) endef $(eval $(call KernelPackage,crypto-ocf-hifn7751)) define KernelPackage/crypto-ocf-hifnhipp TITLE:=OCF support for Hifn 7855/8155 devices DEPENDS:=+@OPENSSL_ENGINE_CRYPTO @PCI_SUPPORT @!TARGET_uml kmod-crypto-ocf KCONFIG:=CONFIG_OCF_HIFNHIPP FILES:=$(LINUX_DIR)/crypto/ocf/hifn/hifnHIPP.ko AUTOLOAD:=$(call AutoLoad,10,hifnHIPP) $(call AddDepends/crypto) endef $(eval $(call KernelPackage,crypto-ocf-hifnhipp)) define KernelPackage/crypto-null TITLE:=Null CryptoAPI module KCONFIG:=CONFIG_CRYPTO_NULL FILES:=$(LINUX_DIR)/crypto/crypto_null.ko AUTOLOAD:=$(call AutoLoad,09,crypto_null) $(call AddDepends/crypto,+kmod-crypto-manager) endef $(eval $(call KernelPackage,crypto-null)) define KernelPackage/crypto-test TITLE:=Test CryptoAPI module KCONFIG:=CONFIG_CRYPTO_TEST FILES:=$(LINUX_DIR)/crypto/tcrypt.ko $(call AddDepends/crypto,+kmod-crypto-manager) endef $(eval $(call KernelPackage,crypto-test)) define KernelPackage/crypto-xts TITLE:=XTS cipher CryptoAPI module DEPENDS:=+kmod-crypto-manager KCONFIG:= \ CONFIG_CRYPTO_GF128MUL \ CONFIG_CRYPTO_XTS FILES:= \ $(LINUX_DIR)/crypto/xts.ko \ $(LINUX_DIR)/crypto/gf128mul.ko AUTOLOAD:=$(call AutoLoad,09, \ gf128mul \ xts \ ) $(call AddDepends/crypto) endef $(eval $(call KernelPackage,crypto-xts)) define KernelPackage/crypto-mv-cesa TITLE:=Marvell crypto engine DEPENDS:=+kmod-crypto-manager +kmod-crypto-aes @TARGET_kirkwood||TARGET_orion||TARGET_mvebu KCONFIG:=CONFIG_CRYPTO_DEV_MV_CESA FILES:=$(LINUX_DIR)/drivers/crypto/mv_cesa.ko AUTOLOAD:=$(call AutoLoad,09,mv_cesa) $(call AddDepends/crypto) endef $(eval $(call KernelPackage,crypto-mv-cesa)) >335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832
/****************************************************************************
 * (C) 2002-2003 - Rolf Neugebauer - Intel Research Cambridge
 * (C) 2002-2003 University of Cambridge
 * (C) 2004      - Mark Williamson - Intel Research Cambridge
 ****************************************************************************
 *
 *        File: common/schedule.c
 *      Author: Rolf Neugebauer & Keir Fraser
 *              Updated for generic API by Mark Williamson
 * 
 * Description: Generic CPU scheduling code
 *              implements support functionality for the Xen scheduler API.
 *
 */

#ifndef COMPAT
#include <xen/config.h>
#include <xen/init.h>
#include <xen/lib.h>
#include <xen/sched.h>
#include <xen/domain.h>
#include <xen/delay.h>
#include <xen/event.h>
#include <xen/time.h>
#include <xen/timer.h>
#include <xen/perfc.h>
#include <xen/sched-if.h>
#include <xen/softirq.h>
#include <xen/trace.h>
#include <xen/mm.h>
#include <xen/errno.h>
#include <xen/guest_access.h>
#include <xen/multicall.h>
#include <public/sched.h>
#include <xsm/xsm.h>

/* opt_sched: scheduler - default to credit */
static char opt_sched[10] = "credit";
string_param("sched", opt_sched);

#define TIME_SLOP      (s32)MICROSECS(50)     /* allow time to slip a bit */

/* Various timer handlers. */
static void s_timer_fn(void *unused);
static void vcpu_periodic_timer_fn(void *data);
static void vcpu_singleshot_timer_fn(void *data);
static void poll_timer_fn(void *data);

/* This is global for now so that private implementations can reach it */
DEFINE_PER_CPU(struct schedule_data, schedule_data);

extern struct scheduler sched_sedf_def;
extern struct scheduler sched_credit_def;
static struct scheduler *schedulers[] = { 
    &sched_sedf_def,
    &sched_credit_def,
    NULL
};

static struct scheduler ops;

#define SCHED_OP(fn, ...)                                 \
         (( ops.fn != NULL ) ? ops.fn( __VA_ARGS__ )      \
          : (typeof(ops.fn(__VA_ARGS__)))0 )

static inline void vcpu_runstate_change(
    struct vcpu *v, int new_state, s_time_t new_entry_time)
{
    ASSERT(v->runstate.state != new_state);
    ASSERT(spin_is_locked(&per_cpu(schedule_data,v->processor).schedule_lock));

    v->runstate.time[v->runstate.state] +=
        new_entry_time - v->runstate.state_entry_time;
    v->runstate.state_entry_time = new_entry_time;
    v->runstate.state = new_state;
}

void vcpu_runstate_get(struct vcpu *v, struct vcpu_runstate_info *runstate)
{
    if ( likely(v == current) )
    {
        /* Fast lock-free path. */
        memcpy(runstate, &v->runstate, sizeof(*runstate));
        ASSERT(runstate->state == RUNSTATE_running);
        runstate->time[RUNSTATE_running] += NOW() - runstate->state_entry_time;
    }
    else
    {
        vcpu_schedule_lock_irq(v);
        memcpy(runstate, &v->runstate, sizeof(*runstate));
        runstate->time[runstate->state] += NOW() - runstate->state_entry_time;
        vcpu_schedule_unlock_irq(v);
    }
}

int sched_init_vcpu(struct vcpu *v, unsigned int processor) 
{
    struct domain *d = v->domain;

    /*
     * Initialize processor and affinity settings. The idler, and potentially
     * domain-0 VCPUs, are pinned onto their respective physical CPUs.
     */
    v->processor = processor;
    if ( is_idle_domain(d) || d->is_pinned )
        v->cpu_affinity = cpumask_of_cpu(processor);
    else
        cpus_setall(v->cpu_affinity);

    /* Initialise the per-vcpu timers. */
    init_timer(&v->periodic_timer, vcpu_periodic_timer_fn,
               v, v->processor);
    init_timer(&v->singleshot_timer, vcpu_singleshot_timer_fn,
               v, v->processor);
    init_timer(&v->poll_timer, poll_timer_fn,
               v, v->processor);

    /* Idle VCPUs are scheduled immediately. */
    if ( is_idle_domain(d) )
    {
        per_cpu(schedule_data, v->processor).curr = v;
        per_cpu(schedule_data, v->processor).idle = v;
        v->is_running = 1;
    }

    TRACE_2D(TRC_SCHED_DOM_ADD, v->domain->domain_id, v->vcpu_id);

    return SCHED_OP(init_vcpu, v);
}

void sched_destroy_vcpu(struct vcpu *v)
{
    kill_timer(&v->periodic_timer);
    kill_timer(&v->singleshot_timer);
    kill_timer(&v->poll_timer);
    SCHED_OP(destroy_vcpu, v);
}

int sched_init_domain(struct domain *d)
{
    return SCHED_OP(init_domain, d);
}

void sched_destroy_domain(struct domain *d)
{
    SCHED_OP(destroy_domain, d);
}

void vcpu_sleep_nosync(struct vcpu *v)
{
    unsigned long flags;

    vcpu_schedule_lock_irqsave(v, flags);

    if ( likely(!vcpu_runnable(v)) )
    {
        if ( v->runstate.state == RUNSTATE_runnable )
            vcpu_runstate_change(v, RUNSTATE_offline, NOW());

        SCHED_OP(sleep, v);
    }

    vcpu_schedule_unlock_irqrestore(v, flags);

    TRACE_2D(TRC_SCHED_SLEEP, v->domain->domain_id, v->vcpu_id);
}

void vcpu_sleep_sync(struct vcpu *v)
{
    vcpu_sleep_nosync(v);

    while ( !vcpu_runnable(v) && v->is_running )
        cpu_relax();

    sync_vcpu_execstate(v);
}

void vcpu_wake(struct vcpu *v)
{
    unsigned long flags;

    vcpu_schedule_lock_irqsave(v, flags);

    if ( likely(vcpu_runnable(v)) )
    {
        if ( v->runstate.state >= RUNSTATE_blocked )
            vcpu_runstate_change(v, RUNSTATE_runnable, NOW());
        SCHED_OP(wake, v);
    }
    else if ( !test_bit(_VPF_blocked, &v->pause_flags) )
    {
        if ( v->runstate.state == RUNSTATE_blocked )
            vcpu_runstate_change(v, RUNSTATE_offline, NOW());
    }

    vcpu_schedule_unlock_irqrestore(v, flags);

    TRACE_2D(TRC_SCHED_WAKE, v->domain->domain_id, v->vcpu_id);
}

static void vcpu_migrate(struct vcpu *v)
{
    unsigned long flags;
    int old_cpu;

    vcpu_schedule_lock_irqsave(v, flags);

    /*
     * NB. Check of v->running happens /after/ setting migration flag
     * because they both happen in (different) spinlock regions, and those
     * regions are strictly serialised.
     */
    if ( v->is_running ||
         !test_and_clear_bit(_VPF_migrating, &v->pause_flags) )
    {
        vcpu_schedule_unlock_irqrestore(v, flags);
        return;
    }

    /* Switch to new CPU, then unlock old CPU. */
    old_cpu = v->processor;
    v->processor = SCHED_OP(pick_cpu, v);
    spin_unlock_irqrestore(
        &per_cpu(schedule_data, old_cpu).schedule_lock, flags);

    /* Wake on new CPU. */
    vcpu_wake(v);
}

/*
 * Force a VCPU through a deschedule/reschedule path.
 * For example, using this when setting the periodic timer period means that
 * most periodic-timer state need only be touched from within the scheduler
 * which can thus be done without need for synchronisation.
 */
void vcpu_force_reschedule(struct vcpu *v)