aboutsummaryrefslogtreecommitdiffstats
path: root/util/git-hooks/pre-push
diff options
context:
space:
mode:
authorAngel Pons <th3fanbus@gmail.com>2021-04-18 13:19:51 +0000
committerNico Huber <nico.h@gmx.de>2021-04-22 11:24:29 +0000
commit02be851a63ee23fd0f9e8103504a61d26a48afc5 (patch)
treef0e5d459d80f12a8d53daf2dfe36a4507bae7612 /util/git-hooks/pre-push
parent3c97998aea8bced868fc73dfed7561fdf3382466 (diff)
downloadflashrom-02be851a63ee23fd0f9e8103504a61d26a48afc5.tar.gz
flashrom-02be851a63ee23fd0f9e8103504a61d26a48afc5.tar.bz2
flashrom-02be851a63ee23fd0f9e8103504a61d26a48afc5.zip
Revert "Makefile: Explicitly set '-std=c99'"
This reverts commit 5e5c3f15efe262ff23642dd543faf6a9dbb3bbdb. Reason for revert: Breaks building on PowerPC, NetBSD, DJGPP, and it is possible that SPARC fails to build as well. Change-Id: I57b5125207de3fd156dface67cba605da893d6aa Signed-off-by: Angel Pons <th3fanbus@gmail.com> Reviewed-on: https://review.coreboot.org/c/flashrom/+/52425 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Anastasia Klimchuk <aklm@chromium.org> Reviewed-by: Edward O'Callaghan <quasisec@chromium.org> Reviewed-by: Nico Huber <nico.h@gmx.de>
Diffstat (limited to 'util/git-hooks/pre-push')
0 files changed, 0 insertions, 0 deletions
17'>117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264
/*
 * vmx_intercept.c: Handle performance critical I/O packets in hypervisor space
 * Copyright (c) 2004, Intel Corporation.
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms and conditions of the GNU General Public License,
 * version 2, as published by the Free Software Foundation.
 *
 * This program is distributed in the hope it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 * more details.
 *
 * You should have received a copy of the GNU General Public License along with
 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
 * Place - Suite 330, Boston, MA 02111-1307 USA.
 *
 */

#include <xen/config.h>
#include <xen/types.h>
#include <asm/vmx.h>
#include <asm/vmx_platform.h>
#include <asm/vmx_virpit.h>
#include <asm/vmx_intercept.h>
#include <public/io/ioreq.h>

#include <xen/lib.h>
#include <xen/sched.h>
#include <asm/current.h>

#ifdef CONFIG_VMX

/* for intercepting io request after vm_exit, return value: 0--not handle; 1--handled */
int vmx_io_intercept(ioreq_t *p)
{
    struct vcpu *d = current;
    struct vmx_handler_t *handler = &(d->arch.arch_vmx.vmx_platform.vmx_handler);
    int i;
    unsigned long addr, offset;
    for (i = 0; i < handler->num_slot; i++) {
        addr   = handler->hdl_list[i].addr;
        offset = handler->hdl_list[i].offset;
        if (p->addr >= addr &&
	    p->addr <  addr + offset)
	    return handler->hdl_list[i].action(p);
    }
    return 0;
}

int register_io_handler(unsigned long addr, unsigned long offset, intercept_action_t action)
{
    struct vcpu *d = current;
    struct vmx_handler_t *handler = &(d->arch.arch_vmx.vmx_platform.vmx_handler);
    int num = handler->num_slot;

    if (num >= MAX_IO_HANDLER) {
        printk("no extra space, register io interceptor failed!\n");
        domain_crash_synchronous();
    }

    handler->hdl_list[num].addr = addr;
    handler->hdl_list[num].offset = offset;
    handler->hdl_list[num].action = action;
    handler->num_slot++;
    return 1;

}

static void pit_cal_count(struct vmx_virpit_t *vpit)
{
    unsigned int usec_delta = (unsigned int)((NOW() - vpit->inject_point) / 1000);
    if (usec_delta > vpit->period * 1000)
        VMX_DBG_LOG(DBG_LEVEL_1, "VMX_PIT:long time has passed from last injection!");
    vpit->count = vpit->init_val - ((usec_delta * PIT_FREQ / 1000000) % vpit->init_val );
}

static void pit_latch_io(struct vmx_virpit_t *vpit)
{
    pit_cal_count(vpit);

    switch(vpit->read_state) {
    case MSByte:
        vpit->count_MSB_latched=1;
        break;
    case LSByte:
        vpit->count_LSB_latched=1;
        break;
    case LSByte_multiple:
        vpit->count_LSB_latched=1;
        vpit->count_MSB_latched=1;
        break;
    case MSByte_multiple:
        VMX_DBG_LOG(DBG_LEVEL_1, "VMX_PIT:latch PIT counter before MSB_multiple!");
        vpit->read_state=LSByte_multiple;
        vpit->count_LSB_latched=1;
        vpit->count_MSB_latched=1;
        break;
    default:
        BUG();
    }
}

static int pit_read_io(struct vmx_virpit_t *vpit)
{
    if(vpit->count_LSB_latched) {
        /* Read Least Significant Byte */
        if(vpit->read_state==LSByte_multiple) {
            vpit->read_state=MSByte_multiple;
        }
        vpit->count_LSB_latched=0;
        return (vpit->count & 0xFF);
    } else if(vpit->count_MSB_latched) {
        /* Read Most Significant Byte */
        if(vpit->read_state==MSByte_multiple) {
            vpit->read_state=LSByte_multiple;
        }
        vpit->count_MSB_latched=0;
        return ((vpit->count>>8) & 0xFF);
    } else {
        /* Unlatched Count Read */
        VMX_DBG_LOG(DBG_LEVEL_1, "VMX_PIT: unlatched read");
        pit_cal_count(vpit);
        if(!(vpit->read_state & 0x1)) {
            /* Read Least Significant Byte */
            if(vpit->read_state==LSByte_multiple) {
                vpit->read_state=MSByte_multiple;
            }
            return (vpit->count & 0xFF);
        } else {
            /* Read Most Significant Byte */
            if(vpit->read_state==MSByte_multiple) {
                vpit->read_state=LSByte_multiple;
            }
            return ((vpit->count>>8) & 0xFF);
        }
    }
}

/* vmx_io_assist light-weight version, specific to PIT DM */ 
static void resume_pit_io(ioreq_t *p)
{
    struct cpu_user_regs *regs = guest_cpu_user_regs();
    unsigned long old_eax = regs->eax;
    p->state = STATE_INVALID;

    switch(p->size) {
    case 1:
        regs->eax = (old_eax & 0xffffff00) | (p->u.data & 0xff);
        break;
    case 2:
        regs->eax = (old_eax & 0xffff0000) | (p->u.data & 0xffff);
        break;
    case 4:
        regs->eax = (p->u.data & 0xffffffff);
        break;
    default:
        BUG();
    }
}

/* the intercept action for PIT DM retval:0--not handled; 1--handled */
int intercept_pit_io(ioreq_t *p)
{
    struct vcpu *d = current;
    struct vmx_virpit_t *vpit = &(d->arch.arch_vmx.vmx_platform.vmx_pit);

    if (p->size != 1 ||
        p->pdata_valid ||
        p->port_mm)
        return 0;
    
    if (p->addr == 0x43 &&
	p->dir == 0 &&				/* write */
        ((p->u.data >> 4) & 0x3) == 0 &&	/* latch command */
        ((p->u.data >> 6) & 0x3) == (vpit->channel)) {/* right channel */
        pit_latch_io(vpit);
	return 1;
    }

    if (p->addr == (0x40 + vpit->channel) &&
	p->dir == 1) {	/* read */
        p->u.data = pit_read_io(vpit);
        resume_pit_io(p);
	return 1;
    }

    return 0;
}

/* hooks function for the PIT initialization response iopacket */
static void pit_timer_fn(void *data)
{
    struct vmx_virpit_t *vpit = data;

    /* Set the pending intr bit, and send evtchn notification to myself. */
    if (test_and_set_bit(vpit->vector, vpit->intr_bitmap))
        vpit->pending_intr_nr++; /* already set, then count the pending intr */

    set_ac_timer(&vpit->pit_timer, NOW() + MILLISECS(vpit->period));
}


/* Only some PIT operations such as load init counter need a hypervisor hook.
 * leave all other operations in user space DM
 */
void vmx_hooks_assist(struct vcpu *d)
{
    vcpu_iodata_t *vio = (vcpu_iodata_t *) d->arch.arch_vmx.vmx_platform.shared_page_va;
    ioreq_t *p = &vio->vp_ioreq;
    unsigned long *intr = &(vio->vp_intr[0]);
    struct vmx_virpit_t *vpit = &(d->arch.arch_vmx.vmx_platform.vmx_pit);
    int rw_mode;

    /* load init count*/
    if (p->state == STATE_IORESP_HOOK) { 
        /* init count for this channel */
        vpit->init_val = (p->u.data & 0xFFFF) ; 
        /* frequency(ms) of pit */
        vpit->period = DIV_ROUND(((vpit->init_val) * 1000), PIT_FREQ); 
        if (vpit->period < 1) {
            printk("VMX_PIT: guest programmed too small an init_val: %x\n",
                   vpit->init_val);
            vpit->period = 1;
        }
        vpit->vector = ((p->u.data >> 16) & 0xFF);
        vpit->channel = ((p->u.data >> 24) & 0x3);
        vpit->first_injected = 0;

	vpit->count_LSB_latched = 0;
	vpit->count_MSB_latched = 0;

        rw_mode = ((p->u.data >> 26) & 0x3);
        switch(rw_mode) {
        case 0x1:
            vpit->read_state=LSByte;
            break;
        case 0x2:
            vpit->read_state=MSByte;
            break;
        case 0x3:
            vpit->read_state=LSByte_multiple;
            break;
        default:
            printk("VMX_PIT:wrong PIT rw_mode!\n");
            break;
        }

        vpit->intr_bitmap = intr;

        /* set up the actimer */
        init_ac_timer(&vpit->pit_timer, pit_timer_fn, vpit, 0);
        pit_timer_fn(vpit); /* timer seed */

        /*restore the state*/
        p->state = STATE_IORESP_READY;

	/* register handler to intercept the PIT io when vm_exit */
	register_io_handler(0x40, 4, intercept_pit_io); 
    }

}

#endif /* CONFIG_VMX */