Signed-off-by: Bryan O'Donoghue <pure.logic@xxxxxxxxxxxxxxxxx>
Since you have Intel (C) below and then your own, are you the sole author?
+config IMR
+ tristate "Isolated Memory Region support"
+ default m
+ depends on IOSF_MBI
+ ---help---
+ This option enables support for Isolated Memory Regions.
It supports manipulating them specifically, correct? No support is needed to
trigger an IMR violation and reboot the system, that happens in
hardware/firmware without any OS involvement.
So we're specifically providing the means to manipulate the IMRs.
+/*
+ * Right now IMRs are not reported via CPUID though it'd be really great if
+ * future silicon did report via CPUID for this feature bringing it in-line with
+ * other similar features - like MTRRs, MSRs etc.
I think we can drop the editorializing :-)
/*
* Unfortunately, IMRs are not reported via CPUID, unlike MTRRs, MSRs, etc.
* Define a macro analogous to cpu_has_x type features.
*/
+/* Definition of read/write masks from published BSP code */
+#define IMR_READ_ACCESS_ALL 0xBFFFFFFF
+#define IMR_WRITE_ACCESS_ALL 0xFFFFFFFF
+
+/* Number of IMRs provided by Quark X1000 SoC */
+#define QUARK_X1000_IMR_NUM 0x07
Hrm, I thought there were 8?
Also in the datasheet here:
https://communities.intel.com/servlet/JiveServlet/previewBody/21828-102-2-25120/329676_QuarkDatasheet.pdf
+ *
+ * addr_lo
+ * 31 Lock bit
+ * 30 Enable bit - not implemented on Quark X1000
With the exception of bit 30, also marked as reserved per the above datasheet.
+struct imr {
+ u32 addr_lo;
+ u32 addr_hi;
+ u32 rmask;
+ u32 wmask;
+};
+
+#define IMR_NUM_REGS (sizeof(struct imr)/sizeof(u32))
Perhaps call the imr imr_regs so nobody breaks this in the future by adding
something other than a u32 to it? Alternatively, use a datatype that enforces
this... like the union Andy suggested...
+#define IMR_SHIFT 8
+#define imr_to_phys(x) (x << IMR_SHIFT)
+#define phys_to_imr(x) (x >> IMR_SHIFT)
+
+/**
+ * imr_enabled
+ * Determines if an IMR is enabled based on address range
+ *
+ * @imr: Pointer to IMR descriptor
+ * @return true if IMR enabled false if disabled
+ */
+static int imr_enabled(struct imr *imr)
+{
+ return (imr_to_phys(imr->addr_lo) && imr_to_phys(imr->addr_hi));
What are testing here? You have bit 30 marked as "Enabled" above (but it isn't
in the datasheet). With Reserved bits in each register, this test for non-zero
doesn't seem robust.
+ /* Error out if we have an overlap or no free IMR entries */
According to the datasheet, overlapping ranges are valid, and access must be
granted by all IMRs associated with a given address. Why declare an overlap as
invalid here?