root/drivers/gpu/drm/vboxvideo/vbox_hgsmi.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. hgsmi_hash_process
  2. hgsmi_hash_end
  3. hgsmi_checksum
  4. hgsmi_buffer_alloc
  5. hgsmi_buffer_free
  6. hgsmi_buffer_submit

   1 // SPDX-License-Identifier: MIT
   2 /*
   3  * Copyright (C) 2017 Oracle Corporation
   4  * Authors: Hans de Goede <hdegoede@redhat.com>
   5  */
   6 
   7 #include "vbox_drv.h"
   8 #include "vboxvideo_vbe.h"
   9 #include "hgsmi_defs.h"
  10 
  11 /* One-at-a-Time Hash from http://www.burtleburtle.net/bob/hash/doobs.html */
  12 static u32 hgsmi_hash_process(u32 hash, const u8 *data, int size)
  13 {
  14         while (size--) {
  15                 hash += *data++;
  16                 hash += (hash << 10);
  17                 hash ^= (hash >> 6);
  18         }
  19 
  20         return hash;
  21 }
  22 
  23 static u32 hgsmi_hash_end(u32 hash)
  24 {
  25         hash += (hash << 3);
  26         hash ^= (hash >> 11);
  27         hash += (hash << 15);
  28 
  29         return hash;
  30 }
  31 
  32 /* Not really a checksum but that is the naming used in all vbox code */
  33 static u32 hgsmi_checksum(u32 offset,
  34                           const struct hgsmi_buffer_header *header,
  35                           const struct hgsmi_buffer_tail *tail)
  36 {
  37         u32 checksum;
  38 
  39         checksum = hgsmi_hash_process(0, (u8 *)&offset, sizeof(offset));
  40         checksum = hgsmi_hash_process(checksum, (u8 *)header, sizeof(*header));
  41         /* 4 -> Do not checksum the checksum itself */
  42         checksum = hgsmi_hash_process(checksum, (u8 *)tail, 4);
  43 
  44         return hgsmi_hash_end(checksum);
  45 }
  46 
  47 void *hgsmi_buffer_alloc(struct gen_pool *guest_pool, size_t size,
  48                          u8 channel, u16 channel_info)
  49 {
  50         struct hgsmi_buffer_header *h;
  51         struct hgsmi_buffer_tail *t;
  52         size_t total_size;
  53         dma_addr_t offset;
  54 
  55         total_size = size + sizeof(*h) + sizeof(*t);
  56         h = gen_pool_dma_alloc(guest_pool, total_size, &offset);
  57         if (!h)
  58                 return NULL;
  59 
  60         t = (struct hgsmi_buffer_tail *)((u8 *)h + sizeof(*h) + size);
  61 
  62         h->flags = HGSMI_BUFFER_HEADER_F_SEQ_SINGLE;
  63         h->data_size = size;
  64         h->channel = channel;
  65         h->channel_info = channel_info;
  66         memset(&h->u.header_data, 0, sizeof(h->u.header_data));
  67 
  68         t->reserved = 0;
  69         t->checksum = hgsmi_checksum(offset, h, t);
  70 
  71         return (u8 *)h + sizeof(*h);
  72 }
  73 
  74 void hgsmi_buffer_free(struct gen_pool *guest_pool, void *buf)
  75 {
  76         struct hgsmi_buffer_header *h =
  77                 (struct hgsmi_buffer_header *)((u8 *)buf - sizeof(*h));
  78         size_t total_size = h->data_size + sizeof(*h) +
  79                                              sizeof(struct hgsmi_buffer_tail);
  80 
  81         gen_pool_free(guest_pool, (unsigned long)h, total_size);
  82 }
  83 
  84 int hgsmi_buffer_submit(struct gen_pool *guest_pool, void *buf)
  85 {
  86         phys_addr_t offset;
  87 
  88         offset = gen_pool_virt_to_phys(guest_pool, (unsigned long)buf -
  89                                        sizeof(struct hgsmi_buffer_header));
  90         outl(offset, VGA_PORT_HGSMI_GUEST);
  91         /* Make the compiler aware that the host has changed memory. */
  92         mb();
  93 
  94         return 0;
  95 }

/* [<][>][^][v][top][bottom][index][help] */