/****************************************************************************** * Arch-specific dom0_ops.c * * Process command requests from domain-0 guest OS. * * Copyright (c) 2002, K A Fraser */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "cpu/mtrr/mtrr.h" #define TRC_DOM0OP_ENTER_BASE 0x00020000 #define TRC_DOM0OP_LEAVE_BASE 0x00030000 static int msr_cpu_mask; static unsigned long msr_addr; static unsigned long msr_lo; static unsigned long msr_hi; static void write_msr_for(void *unused) { if ( ((1 << smp_processor_id()) & msr_cpu_mask) ) (void)wrmsr_safe(msr_addr, msr_lo, msr_hi); } static void read_msr_for(void *unused) { if ( ((1 << smp_processor_id()) & msr_cpu_mask) ) (void)rdmsr_safe(msr_addr, msr_lo, msr_hi); } long arch_do_dom0_op(struct dom0_op *op, XEN_GUEST_HANDLE(dom0_op_t) u_dom0_op) { long ret = 0; switch ( op->cmd ) { case DOM0_MSR: { if ( op->u.msr.write ) { msr_cpu_mask = op->u.msr.cpu_mask; msr_addr = op->u.msr.msr; msr_lo = op->u.msr.in1; msr_hi = op->u.msr.in2; smp_call_function(write_msr_for, NULL, 1, 1); write_msr_for(NULL); } else { msr_cpu_mask = op->u.msr.cpu_mask; msr_addr = op->u.msr.msr; smp_call_function(read_msr_for, NULL, 1, 1); read_msr_for(NULL); op->u.msr.out1 = msr_lo; op->u.msr.out2 = msr_hi; copy_to_guest(u_dom0_op, op, 1); } ret = 0; } break; case DOM0_SHADOW_CONTROL: { struct domain *d; ret = -ESRCH; d = find_domain_by_id(op->u.shadow_control.domain); if ( d != NULL ) { ret = shadow_mode_control(d, &op->u.shadow_control); put_domain(d); copy_to_guest(u_dom0_op, op, 1); } } break; case DOM0_ADD_MEMTYPE: { ret = mtrr_add_page( op->u.add_memtype.mfn, op->u.add_memtype.nr_mfns, op->u.add_memtype.type, 1); if ( ret > 0 ) { op->u.add_memtype.handle = 0; op->u.add_memtype.reg = ret; (void)copy_to_guest(u_dom0_op, op, 1); ret = 0; } } break; case DOM0_DEL_MEMTYPE: { if (op->u.del_memtype.handle == 0 /* mtrr/main.c otherwise does a lookup */ && (int)op->u.del_memtype.reg >= 0) { ret = mtrr_del_page(op->u.del_memtype.reg, 0, 0); if (ret > 0) ret = 0; } else ret = -EINVAL; } break; case DOM0_READ_MEMTYPE: { unsigned long mfn; unsigned int nr_mfns; mtrr_type type; ret = -EINVAL; if ( op->u.read_memtype.reg < num_var_ranges ) { mtrr_if->get(op->u.read_memtype.reg, &mfn, &nr_mfns, &type); op->u.read_memtype.mfn = mfn; op->u.read_memtype.nr_mfns = nr_mfns; op->u.read_memtype.type = type; (void)copy_to_guest(u_dom0_op, op, 1); ret = 0; } } break; case DOM0_MICROCODE: { extern int microcode_update(void *buf, unsigned long len); ret = microcode_update(op->u.microcode.data.p, op->u.microcode.length); } break; case DOM0_IOPORT_PERMISSION: { struct domain *d; unsigned int fp = op->u.ioport_permission.first_port; unsigned int np = op->u.ioport_permission.nr_ports; ret = -EINVAL; if ( (fp + np) > 65536 ) break; ret = -ESRCH; if ( unlikely((d = find_domain_by_id( op->u.ioport_permission.domain)) == NULL) ) break; if ( np == 0 ) ret = 0; else if ( op->u.ioport_permission.allow_access ) ret = ioports_permit_access(d, fp, fp + np - 1); else ret = ioports_deny_access(d, fp, fp + np - 1); put_domain(d); } break; case DOM0_PHYSINFO: { dom0_physinfo_t *pi = &op->u.physinfo; pi->threads_per_core = cpus_weight(cpu_sibling_map[0]); pi->cores_per_socket = cpus_weight(cpu_core_map[0]) / pi->threads_per_core; pi->sockets_per_node = num_online_cpus() / cpus_weight(cpu_core_map[0]); pi->nr_nodes = 1; pi->total_pages = total_pages; pi->free_pages = avail_domheap_pages(); pi->cpu_khz = cpu_khz; memset(pi->hw_cap, 0, sizeof(pi->hw_cap)); memcpy(pi->hw_cap, boot_cpu_data.x86_capability, NCAPINTS*4); ret = 0; if ( copy_to_guest(u_dom0_op, op, 1) ) ret = -EFAULT; } break; case DOM0_GETPAGEFRAMEINFO: { struct page_info *page; unsigned long mfn = op->u.getpageframeinfo.mfn; domid_t dom = op->u.getpageframeinfo.domain; struct domain *d; ret = -EINVAL; if ( unlikely(!mfn_valid(mfn)) || unlikely((d = find_domain_by_id(dom)) == NULL) ) break; page = mfn_to_page(mfn); if ( likely(get_page(page, d)) ) { ret = 0; op->u.getpageframeinfo.type = NOTAB; if ( (page->u.inuse.type_info & PGT_count_mask) != 0 ) { switch ( page->u.inuse.type_info & PGT_type_mask ) { case PGT_l1_page_table: op->u.getpageframeinfo.type = L1TAB; break; case PGT_l2_page_table: op->u.getpageframeinfo.type = L2TAB; break; case PGT_l3_page_table: op->u.getpageframeinfo.type = L3TAB; break; case PGT_l4_page_table: op->u.getpageframeinfo.type = L4TAB; break; } } put_page(page); } put_domain(d); copy_to_guest(u_dom0_op, op, 1); } break; case DOM0_GETPAGEFRAMEINFO2: { #define GPF2_BATCH (PAGE_SIZE / sizeof(unsigned long)) int n,j; int num = op->u.getpageframeinfo2.num; domid_t dom = op->u.getpageframeinfo2.domain; struct domain *d; unsigned long *l_arr; ret = -ESRCH; if ( unlikely((d = find_domain_by_id(dom)) ==
import os
import configparser
import pytest

here = os.path.abspath(os.path.dirname(__file__))


enable_coverage = False
coverage_values = []
coverage_passed = True
no_full_cov = []


def pytest_addoption(parser):
    parser.addoption('--full-cov',
                     action='append',
                     dest='full_cov',
                     default=[],
                     help="Require full test coverage of 100%% for this module/path/filename (multi-allowed). Default: none")

    parser.addoption('--no-full-cov',
                     action='append',
                     dest='no_full_cov',
                     default=[],
                     help="Exclude file from a parent 100%% coverage requirement (multi-allowed). Default: none")


def pytest_configure(config):
    global enable_coverage
    global no_full_cov

    enable_coverage = (
        len(config.getoption('file_or_dir')) == 0 and
        len(config.getoption('full_cov')) > 0 and
        config.pluginmanager.getplugin("_cov") is not None and
        config.pluginmanager.getplugin("_cov").cov_controller is not None and
        config.pluginmanager.getplugin("_cov").cov_controller.cov is not None
    )

    c = configparser.ConfigParser()
    c.read(os.path.join(here, "..", "setup.cfg"))
    fs = c['tool:full_coverage']['exclude'].split('\n')
    no_full_cov = config.option.no_full_cov + [f.strip() for f in fs]


@pytest.hookimpl(hookwrapper=True)
def pytest_runtestloop(session):
    global enable_coverage
    global coverage_values
    global coverage_passed
    global no_full_cov

    if not enable_coverage:
        yield
        return

    cov = pytest.config.pluginmanager.getplugin("_cov").cov_controller.cov

    if os.name == 'nt':
        cov.exclude('pragma: windows no cover')

    yield

    coverage_values = dict([(name, 0) for name in pytest.config.option.full_cov])

    prefix = os.getcwd()

    excluded_files = [os.path.normpath(f) for f in no_full_cov]
    measured_files = [os.path.normpath(os.path.relpath(f, prefix)) for f in cov.get_data().measured_files()]
    measured_files = [f for f in measured_files if not any(f.startswith(excluded_f) for excluded_f in excluded_files)]

    for name in coverage_values.keys():
        files = [f for f in measured_files if f.startswith(os.path.normpath(name))]
        try:
            with open(os.devnull, 'w') as null:
                overall = cov.report(files, ignore_errors=True, file=null)
                singles = [(s, cov.report(s, ignore_errors=True, file=null)) for s in files]
                coverage_values[name] = (overall, singles)
        except:
            pass

    if any(v < 100 for v, _ in coverage_values.values()):
        # make sure we get the EXIT_TESTSFAILED exit code
        session.testsfailed += 1
        coverage_passed = False


def pytest_terminal_summary(terminalreporter, exitstatus):
    global enable_coverage
    global coverage_values
    global coverage_passed
    global no_full_cov

    if not enable_coverage:
        return

    terminalreporter.write('\n')
    if not coverage_passed:
        markup = {'red': True, 'bold': True}
        msg = "FAIL: Full test coverage not reached!\n"
        terminalreporter.write(msg, **markup)

        for name in sorted(coverage_values.keys()):
            msg = 'Coverage for {}: {:.2f}%\n'.format(name, coverage_values[name][0])
            if coverage_values[name][0] < 100:
                markup = {'red': True, 'bold': True}
                for s, v in sorted(coverage_values[name][1]):
                    if v < 100:
                        msg += '  {}: {:.2f}%\n'.format(s, v)
            else:
                markup = {'green': True}
            terminalreporter.write(msg, **markup)
    else:
        msg = 'SUCCESS: Full test coverage reached in modules and files:\n'
        msg += '{}\n\n'.format('\n'.join(pytest.config.option.full_cov))
        terminalreporter.write(msg, green=True)

    msg = '\nExcluded files:\n'
    for s in sorted(no_full_cov):
        msg += "  {}\n".format(s)
    terminalreporter.write(msg)