linux/arch/powerpc/kvm/book3s_xics.h
<<
>>
Prefs
   1/*
   2 * Copyright 2012 Michael Ellerman, IBM Corporation.
   3 * Copyright 2012 Benjamin Herrenschmidt, IBM Corporation
   4 *
   5 * This program is free software; you can redistribute it and/or modify
   6 * it under the terms of the GNU General Public License, version 2, as
   7 * published by the Free Software Foundation.
   8 */
   9
  10#ifndef _KVM_PPC_BOOK3S_XICS_H
  11#define _KVM_PPC_BOOK3S_XICS_H
  12
  13/*
  14 * We use a two-level tree to store interrupt source information.
  15 * There are up to 1024 ICS nodes, each of which can represent
  16 * 1024 sources.
  17 */
  18#define KVMPPC_XICS_MAX_ICS_ID  1023
  19#define KVMPPC_XICS_ICS_SHIFT   10
  20#define KVMPPC_XICS_IRQ_PER_ICS (1 << KVMPPC_XICS_ICS_SHIFT)
  21#define KVMPPC_XICS_SRC_MASK    (KVMPPC_XICS_IRQ_PER_ICS - 1)
  22
  23/*
  24 * Interrupt source numbers below this are reserved, for example
  25 * 0 is "no interrupt", and 2 is used for IPIs.
  26 */
  27#define KVMPPC_XICS_FIRST_IRQ   16
  28#define KVMPPC_XICS_NR_IRQS     ((KVMPPC_XICS_MAX_ICS_ID + 1) * \
  29                                 KVMPPC_XICS_IRQ_PER_ICS)
  30
  31/* Priority value to use for disabling an interrupt */
  32#define MASKED  0xff
  33
  34/* State for one irq source */
  35struct ics_irq_state {
  36        u32 number;
  37        u32 server;
  38        u8  priority;
  39        u8  saved_priority;
  40        u8  resend;
  41        u8  masked_pending;
  42        u8  asserted; /* Only for LSI */
  43        u8  exists;
  44};
  45
  46/* Atomic ICP state, updated with a single compare & swap */
  47union kvmppc_icp_state {
  48        unsigned long raw;
  49        struct {
  50                u8 out_ee:1;
  51                u8 need_resend:1;
  52                u8 cppr;
  53                u8 mfrr;
  54                u8 pending_pri;
  55                u32 xisr;
  56        };
  57};
  58
  59/* One bit per ICS */
  60#define ICP_RESEND_MAP_SIZE     (KVMPPC_XICS_MAX_ICS_ID / BITS_PER_LONG + 1)
  61
  62struct kvmppc_icp {
  63        struct kvm_vcpu *vcpu;
  64        unsigned long server_num;
  65        union kvmppc_icp_state state;
  66        unsigned long resend_map[ICP_RESEND_MAP_SIZE];
  67
  68        /* Real mode might find something too hard, here's the action
  69         * it might request from virtual mode
  70         */
  71#define XICS_RM_KICK_VCPU       0x1
  72#define XICS_RM_CHECK_RESEND    0x2
  73#define XICS_RM_REJECT          0x4
  74        u32 rm_action;
  75        struct kvm_vcpu *rm_kick_target;
  76        u32  rm_reject;
  77
  78        /* Debug stuff for real mode */
  79        union kvmppc_icp_state rm_dbgstate;
  80        struct kvm_vcpu *rm_dbgtgt;
  81};
  82
  83struct kvmppc_ics {
  84        struct mutex lock;
  85        u16 icsid;
  86        struct ics_irq_state irq_state[KVMPPC_XICS_IRQ_PER_ICS];
  87};
  88
  89struct kvmppc_xics {
  90        struct kvm *kvm;
  91        struct kvm_device *dev;
  92        struct dentry *dentry;
  93        u32 max_icsid;
  94        bool real_mode;
  95        bool real_mode_dbg;
  96        struct kvmppc_ics *ics[KVMPPC_XICS_MAX_ICS_ID + 1];
  97};
  98
  99static inline struct kvmppc_icp *kvmppc_xics_find_server(struct kvm *kvm,
 100                                                         u32 nr)
 101{
 102        struct kvm_vcpu *vcpu = NULL;
 103        int i;
 104
 105        kvm_for_each_vcpu(i, vcpu, kvm) {
 106                if (vcpu->arch.icp && nr == vcpu->arch.icp->server_num)
 107                        return vcpu->arch.icp;
 108        }
 109        return NULL;
 110}
 111
 112static inline struct kvmppc_ics *kvmppc_xics_find_ics(struct kvmppc_xics *xics,
 113                                                      u32 irq, u16 *source)
 114{
 115        u32 icsid = irq >> KVMPPC_XICS_ICS_SHIFT;
 116        u16 src = irq & KVMPPC_XICS_SRC_MASK;
 117        struct kvmppc_ics *ics;
 118
 119        if (source)
 120                *source = src;
 121        if (icsid > KVMPPC_XICS_MAX_ICS_ID)
 122                return NULL;
 123        ics = xics->ics[icsid];
 124        if (!ics)
 125                return NULL;
 126        return ics;
 127}
 128
 129
 130#endif /* _KVM_PPC_BOOK3S_XICS_H */
 131