|
@@ -103,6 +103,7 @@ struct its_device {
|
|
|
|
|
|
/* the head for the list of ITTEs */
|
|
|
struct list_head itt_head;
|
|
|
+ u32 num_eventid_bits;
|
|
|
u32 device_id;
|
|
|
};
|
|
|
|
|
@@ -224,6 +225,8 @@ static struct its_ite *find_ite(struct vgic_its *its, u32 device_id,
|
|
|
|
|
|
#define GIC_LPI_OFFSET 8192
|
|
|
|
|
|
+#define VITS_TYPER_IDBITS 16
|
|
|
+
|
|
|
/*
|
|
|
* Finds and returns a collection in the ITS collection table.
|
|
|
* Must be called with the its_lock mutex held.
|
|
@@ -424,7 +427,7 @@ static unsigned long vgic_mmio_read_its_typer(struct kvm *kvm,
|
|
|
* DevBits low - as least for the time being.
|
|
|
*/
|
|
|
reg |= 0x0f << GITS_TYPER_DEVBITS_SHIFT;
|
|
|
- reg |= 0x0f << GITS_TYPER_IDBITS_SHIFT;
|
|
|
+ reg |= GIC_ENCODE_SZ(VITS_TYPER_IDBITS, 5) << GITS_TYPER_IDBITS_SHIFT;
|
|
|
reg |= GIC_ENCODE_SZ(abi->ite_esz, 4) << GITS_TYPER_ITT_ENTRY_SIZE_SHIFT;
|
|
|
|
|
|
return extract_bytes(reg, addr & 7, len);
|
|
@@ -595,6 +598,7 @@ static u64 its_cmd_mask_field(u64 *its_cmd, int word, int shift, int size)
|
|
|
|
|
|
#define its_cmd_get_command(cmd) its_cmd_mask_field(cmd, 0, 0, 8)
|
|
|
#define its_cmd_get_deviceid(cmd) its_cmd_mask_field(cmd, 0, 32, 32)
|
|
|
+#define its_cmd_get_size(cmd) (its_cmd_mask_field(cmd, 1, 0, 5) + 1)
|
|
|
#define its_cmd_get_id(cmd) its_cmd_mask_field(cmd, 1, 0, 32)
|
|
|
#define its_cmd_get_physical_id(cmd) its_cmd_mask_field(cmd, 1, 32, 32)
|
|
|
#define its_cmd_get_collection(cmd) its_cmd_mask_field(cmd, 2, 0, 16)
|
|
@@ -785,6 +789,9 @@ static int vgic_its_cmd_handle_mapi(struct kvm *kvm, struct vgic_its *its,
|
|
|
if (!device)
|
|
|
return E_ITS_MAPTI_UNMAPPED_DEVICE;
|
|
|
|
|
|
+ if (event_id >= BIT_ULL(device->num_eventid_bits))
|
|
|
+ return E_ITS_MAPTI_ID_OOR;
|
|
|
+
|
|
|
if (its_cmd_get_command(its_cmd) == GITS_CMD_MAPTI)
|
|
|
lpi_nr = its_cmd_get_physical_id(its_cmd);
|
|
|
else
|
|
@@ -865,11 +872,15 @@ static int vgic_its_cmd_handle_mapd(struct kvm *kvm, struct vgic_its *its,
|
|
|
{
|
|
|
u32 device_id = its_cmd_get_deviceid(its_cmd);
|
|
|
bool valid = its_cmd_get_validbit(its_cmd);
|
|
|
+ u8 num_eventid_bits = its_cmd_get_size(its_cmd);
|
|
|
struct its_device *device;
|
|
|
|
|
|
if (!vgic_its_check_id(its, its->baser_device_table, device_id))
|
|
|
return E_ITS_MAPD_DEVICE_OOR;
|
|
|
|
|
|
+ if (valid && num_eventid_bits > VITS_TYPER_IDBITS)
|
|
|
+ return E_ITS_MAPD_ITTSIZE_OOR;
|
|
|
+
|
|
|
device = find_its_device(its, device_id);
|
|
|
|
|
|
/*
|
|
@@ -892,6 +903,8 @@ static int vgic_its_cmd_handle_mapd(struct kvm *kvm, struct vgic_its *its,
|
|
|
return -ENOMEM;
|
|
|
|
|
|
device->device_id = device_id;
|
|
|
+ device->num_eventid_bits = num_eventid_bits;
|
|
|
+
|
|
|
INIT_LIST_HEAD(&device->itt_head);
|
|
|
|
|
|
list_add_tail(&device->dev_list, &its->device_list);
|