Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  gic_v3_its.c   Sprache: C

 
// SPDX-License-Identifier: GPL-2.0
/*
 * Guest ITS library, generously donated by drivers/irqchip/irq-gic-v3-its.c
 * over in the kernel tree.
 */


#include <linux/kvm.h>
#include <linux/sizes.h>
#include <asm/kvm_para.h>
#include <asm/kvm.h>

#include "kvm_util.h"
#include "vgic.h"
#include "gic.h"
#include "gic_v3.h"
#include "processor.h"

static u64 its_read_u64(unsigned long offset)
{
 return readq_relaxed(GITS_BASE_GVA + offset);
}

static void its_write_u64(unsigned long offset, u64 val)
{
 writeq_relaxed(val, GITS_BASE_GVA + offset);
}

static u32 its_read_u32(unsigned long offset)
{
 return readl_relaxed(GITS_BASE_GVA + offset);
}

static void its_write_u32(unsigned long offset, u32 val)
{
 writel_relaxed(val, GITS_BASE_GVA + offset);
}

static unsigned long its_find_baser(unsigned int type)
{
 int i;

 for (i = 0; i < GITS_BASER_NR_REGS; i++) {
  u64 baser;
  unsigned long offset = GITS_BASER + (i * sizeof(baser));

  baser = its_read_u64(offset);
  if (GITS_BASER_TYPE(baser) == type)
   return offset;
 }

 GUEST_FAIL("Couldn't find an ITS BASER of type %u", type);
 return -1;
}

static void its_install_table(unsigned int type, vm_paddr_t base, size_t size)
{
 unsigned long offset = its_find_baser(type);
 u64 baser;

 baser = ((size / SZ_64K) - 1) |
  GITS_BASER_PAGE_SIZE_64K |
  GITS_BASER_InnerShareable |
  base |
  GITS_BASER_RaWaWb |
  GITS_BASER_VALID;

 its_write_u64(offset, baser);
}

static void its_install_cmdq(vm_paddr_t base, size_t size)
{
 u64 cbaser;

 cbaser = ((size / SZ_4K) - 1) |
   GITS_CBASER_InnerShareable |
   base |
   GITS_CBASER_RaWaWb |
   GITS_CBASER_VALID;

 its_write_u64(GITS_CBASER, cbaser);
}

void its_init(vm_paddr_t coll_tbl, size_t coll_tbl_sz,
       vm_paddr_t device_tbl, size_t device_tbl_sz,
       vm_paddr_t cmdq, size_t cmdq_size)
{
 u32 ctlr;

 its_install_table(GITS_BASER_TYPE_COLLECTION, coll_tbl, coll_tbl_sz);
 its_install_table(GITS_BASER_TYPE_DEVICE, device_tbl, device_tbl_sz);
 its_install_cmdq(cmdq, cmdq_size);

 ctlr = its_read_u32(GITS_CTLR);
 ctlr |= GITS_CTLR_ENABLE;
 its_write_u32(GITS_CTLR, ctlr);
}

struct its_cmd_block {
 union {
  u64 raw_cmd[4];
  __le64 raw_cmd_le[4];
 };
};

static inline void its_fixup_cmd(struct its_cmd_block *cmd)
{
 /* Let's fixup BE commands */
 cmd->raw_cmd_le[0] = cpu_to_le64(cmd->raw_cmd[0]);
 cmd->raw_cmd_le[1] = cpu_to_le64(cmd->raw_cmd[1]);
 cmd->raw_cmd_le[2] = cpu_to_le64(cmd->raw_cmd[2]);
 cmd->raw_cmd_le[3] = cpu_to_le64(cmd->raw_cmd[3]);
}

static void its_mask_encode(u64 *raw_cmd, u64 val, int h, int l)
{
 u64 mask = GENMASK_ULL(h, l);
 *raw_cmd &= ~mask;
 *raw_cmd |= (val << l) & mask;
}

static void its_encode_cmd(struct its_cmd_block *cmd, u8 cmd_nr)
{
 its_mask_encode(&cmd->raw_cmd[0], cmd_nr, 7, 0);
}

static void its_encode_devid(struct its_cmd_block *cmd, u32 devid)
{
 its_mask_encode(&cmd->raw_cmd[0], devid, 63, 32);
}

static void its_encode_event_id(struct its_cmd_block *cmd, u32 id)
{
 its_mask_encode(&cmd->raw_cmd[1], id, 31, 0);
}

static void its_encode_phys_id(struct its_cmd_block *cmd, u32 phys_id)
{
 its_mask_encode(&cmd->raw_cmd[1], phys_id, 63, 32);
}

static void its_encode_size(struct its_cmd_block *cmd, u8 size)
{
 its_mask_encode(&cmd->raw_cmd[1], size, 4, 0);
}

static void its_encode_itt(struct its_cmd_block *cmd, u64 itt_addr)
{
 its_mask_encode(&cmd->raw_cmd[2], itt_addr >> 8, 51, 8);
}

static void its_encode_valid(struct its_cmd_block *cmd, int valid)
{
 its_mask_encode(&cmd->raw_cmd[2], !!valid, 63, 63);
}

static void its_encode_target(struct its_cmd_block *cmd, u64 target_addr)
{
 its_mask_encode(&cmd->raw_cmd[2], target_addr >> 16, 51, 16);
}

static void its_encode_collection(struct its_cmd_block *cmd, u16 col)
{
 its_mask_encode(&cmd->raw_cmd[2], col, 15, 0);
}

#define GITS_CMDQ_POLL_ITERATIONS 0

static void its_send_cmd(void *cmdq_base, struct its_cmd_block *cmd)
{
 u64 cwriter = its_read_u64(GITS_CWRITER);
 struct its_cmd_block *dst = cmdq_base + cwriter;
 u64 cbaser = its_read_u64(GITS_CBASER);
 size_t cmdq_size;
 u64 next;
 int i;

 cmdq_size = ((cbaser & 0xFF) + 1) * SZ_4K;

 its_fixup_cmd(cmd);

 WRITE_ONCE(*dst, *cmd);
 dsb(ishst);
 next = (cwriter + sizeof(*cmd)) % cmdq_size;
 its_write_u64(GITS_CWRITER, next);

 /*
 * Polling isn't necessary considering KVM's ITS emulation at the time
 * of writing this, as the CMDQ is processed synchronously after a write
 * to CWRITER.
 */

 for (i = 0; its_read_u64(GITS_CREADR) != next; i++) {
  __GUEST_ASSERT(i < GITS_CMDQ_POLL_ITERATIONS,
          "ITS didn't process command at offset %lu after %d iterations\n",
          cwriter, i);

  cpu_relax();
 }
}

void its_send_mapd_cmd(void *cmdq_base, u32 device_id, vm_paddr_t itt_base,
         size_t itt_size, bool valid)
{
 struct its_cmd_block cmd = {};

 its_encode_cmd(&cmd, GITS_CMD_MAPD);
 its_encode_devid(&cmd, device_id);
 its_encode_size(&cmd, ilog2(itt_size) - 1);
 its_encode_itt(&cmd, itt_base);
 its_encode_valid(&cmd, valid);

 its_send_cmd(cmdq_base, &cmd);
}

void its_send_mapc_cmd(void *cmdq_base, u32 vcpu_id, u32 collection_id, bool valid)
{
 struct its_cmd_block cmd = {};

 its_encode_cmd(&cmd, GITS_CMD_MAPC);
 its_encode_collection(&cmd, collection_id);
 its_encode_target(&cmd, vcpu_id);
 its_encode_valid(&cmd, valid);

 its_send_cmd(cmdq_base, &cmd);
}

void its_send_mapti_cmd(void *cmdq_base, u32 device_id, u32 event_id,
   u32 collection_id, u32 intid)
{
 struct its_cmd_block cmd = {};

 its_encode_cmd(&cmd, GITS_CMD_MAPTI);
 its_encode_devid(&cmd, device_id);
 its_encode_event_id(&cmd, event_id);
 its_encode_phys_id(&cmd, intid);
 its_encode_collection(&cmd, collection_id);

 its_send_cmd(cmdq_base, &cmd);
}

void its_send_invall_cmd(void *cmdq_base, u32 collection_id)
{
 struct its_cmd_block cmd = {};

 its_encode_cmd(&cmd, GITS_CMD_INVALL);
 its_encode_collection(&cmd, collection_id);

 its_send_cmd(cmdq_base, &cmd);
}

Messung V0.5
C=93 H=90 G=91

¤ Dauer der Verarbeitung: 0.1 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge