Message ID | 7eff63284f877abacf0251dcbc355e929bd03e18.1581048597.git.psampat@linux.ibm.com |
---|---|
State | Changes Requested |
Headers | show |
Series | Support for Self Save API in OPAL | expand |
Context | Check | Description |
---|---|---|
snowpatch_ozlabs/apply_patch | success | Successfully applied on branch master (179d53dfcca30436777b0c748d530a979bbc8a45) |
snowpatch_ozlabs/snowpatch_job_snowpatch-skiboot | success | Test snowpatch/job/snowpatch-skiboot on branch master |
snowpatch_ozlabs/snowpatch_job_snowpatch-skiboot-dco | success | Signed-off-by present |
On Fri, Feb 7, 2020 at 3:21 PM Pratik Rajesh Sampat <psampat@linux.ibm.com> wrote: > > Support for self save and self restore interface is advertised in the > device tree, along with the list of SPRs it supports for each. > > The Special Purpose Register identification is encoded in a 2048 bitmask > structure, where each bit signifies the identification key of that SPR > which is consistent with that of the POWER architecture set for that > register. Please answer the questions I asked the last time I reviewed this: https://patchwork.ozlabs.org/patch/1174835/#2278701 Since then I've also forgotten what the difference between self-restore and the existing API is. So can you add something to doc/power-management.rst to describe the relationship between the current API, self-restore, and self-save? The new device-tree bindings need to be documented in doc/device-tree/ibm,opal/power-mgt/ too. The cover letter of the series covers some of that, but actual documentation is sorely needed. > Signed-off-by: Pratik Rajesh Sampat <psampat@linux.ibm.com> > --- > hw/slw.c | 83 +++++++++++++++++++++++++++++++++ > include/skiboot.h | 1 + > libpore/p8_pore_table_gen_api.H | 1 + > 3 files changed, 85 insertions(+) > > diff --git a/hw/slw.c b/hw/slw.c > index 5efa2168..087a8619 100644 > --- a/hw/slw.c > +++ b/hw/slw.c > @@ -23,12 +23,15 @@ > #include <nvram.h> > #include <sbe-p8.h> > #include <xive.h> > +#include <bitmap.h> > > #include <p9_stop_api.H> > #include <p8_pore_table_gen_api.H> > #include <sbe_xip_image.h> > > static uint32_t slw_saved_reset[0x100]; > +#define MAX_RESET_PATCH_SIZE 64 unused? > +#define SPR_BITMAP_LENGTH 2048 > > static bool slw_current_le = false; > > @@ -750,6 +753,84 @@ static void slw_late_init_p9(struct proc_chip *chip) > } > } > > +/* Add device tree properties to determine self-save | restore */ > +void add_cpu_self_save_properties() should be: void add_cpu_self_save_properties(void) > +{ > + int i; > + struct dt_node *self_restore, *self_save, *power_mgt; > + bitmap_t *self_restore_map, *self_save_map; declarations should be sorted reverse christmas tree order. i.e. longest at the top, shortest at the bottom. > + > + const uint64_t self_restore_regs[] = { > + P8_SPR_HRMOR, > + P8_SPR_HMEER, > + P8_SPR_PMICR, > + P8_SPR_PMCR, > + P8_SPR_HID0, > + P8_SPR_HID1, > + P8_SPR_HID4, > + P8_SPR_HID5, > + P8_SPR_HSPRG0, > + P8_SPR_LPCR, > + P8_SPR_PSSCR, > + P8_MSR_MSR > + }; > + > + const uint64_t self_save_regs[] = { > + P9_STOP_SPR_DAWR, > + P9_STOP_SPR_HSPRG0, > + P9_STOP_SPR_LDBAR, > + P9_STOP_SPR_LPCR, > + P9_STOP_SPR_PSSCR, > + P9_STOP_SPR_MSR, > + P9_STOP_SPR_HRMOR, > + P9_STOP_SPR_HMEER, > + P9_STOP_SPR_PMCR, > + P9_STOP_SPR_PTCR > + }; Again, where did these sets of registers come from? > + self_save_map = zalloc(BITMAP_BYTES(SPR_BITMAP_LENGTH)); > + self_restore_map = zalloc(BITMAP_BYTES(SPR_BITMAP_LENGTH)); In general I prefer people avoid doing allocations until they're actually needed. If any of the checks below fail then we've done a bunch of work for no reason so... do the checks first? > + for (i = 0; i < ARRAY_SIZE(self_save_regs); i++) > + bitmap_set_bit(*self_save_map, self_save_regs[i]); > + > + for (i = 0; i < ARRAY_SIZE(self_restore_regs); i++) > + bitmap_set_bit(*self_restore_map, self_restore_regs[i]); > + > + power_mgt = dt_find_by_path(dt_root, "/ibm,opal/power-mgt"); > + if (!power_mgt) { > + prerror("OCC: dt node /ibm,opal/power-mgt not found\n"); > + goto bail; > + } > + > + self_restore = dt_new(power_mgt, "self-restore"); > + if (!self_restore) { > + prerror("OCC: Failed to create self restore node"); > + goto bail; > + } > + dt_add_property_string(self_restore, "status", "enabled"); > + > + dt_add_property(self_restore, "sprn-bitmask", *self_restore_map, > + SPR_BITMAP_LENGTH / 8); > + > + self_save = dt_new(power_mgt, "self-save"); > + if (!self_save) { > + prerror("OCC: Failed to create self save node"); > + goto bail; > + } > + if (proc_gen == proc_gen_p9) { > + dt_add_property_string(self_save, "status", "enabled"); > + > + dt_add_property(self_save, "sprn-bitmask", *self_save_map, > + SPR_BITMAP_LENGTH / 8); If skiboot is compiled as little endian this is going to break. It works today because we always build skiboot BE, but that may not always be true. > + } else { > + dt_add_property_string(self_save, "status", "disabled"); I still don't understand why we're adding anything to the DT if the feature isn't supported. > + } > +bail: > + free(self_save_map); > + free(self_restore_map); > +} > + > /* Add device tree properties to describe idle states */ > void add_cpu_idle_state_properties(void) > { > @@ -1563,4 +1644,6 @@ void slw_init(void) > } > } > add_cpu_idle_state_properties(); > + if (has_deep_states) > + add_cpu_self_save_properties(); > } > diff --git a/include/skiboot.h b/include/skiboot.h > index 072ce589..676211ad 100644 > --- a/include/skiboot.h > +++ b/include/skiboot.h > @@ -209,6 +209,7 @@ extern void early_uart_init(void); > extern void homer_init(void); > extern void slw_init(void); > extern void add_cpu_idle_state_properties(void); > +extern void add_cpu_self_save_properties(void); > extern void lpc_rtc_init(void); > > /* flash support */ > diff --git a/libpore/p8_pore_table_gen_api.H b/libpore/p8_pore_table_gen_api.H > index 63081ca5..d72fee90 100644 > --- a/libpore/p8_pore_table_gen_api.H > +++ b/libpore/p8_pore_table_gen_api.H > @@ -233,6 +233,7 @@ enum { > P8_SPR_HRMOR = 313, > P8_SPR_HMEER = 337, > P8_SPR_PMICR = 852, > + P8_SPR_PSSCR = 855, > P8_SPR_PMCR = 884, > P8_SPR_HID0 = 1008, > P8_SPR_HID1 = 1009, > -- > 2.24.1 > > _______________________________________________ > Skiboot mailing list > Skiboot@lists.ozlabs.org > https://lists.ozlabs.org/listinfo/skiboot
Hello Oliver, Thanks for the review. On 10/02/20 7:43 am, Oliver O'Halloran wrote: > On Fri, Feb 7, 2020 at 3:21 PM Pratik Rajesh Sampat > <psampat@linux.ibm.com> wrote: >> Support for self save and self restore interface is advertised in the >> device tree, along with the list of SPRs it supports for each. >> >> The Special Purpose Register identification is encoded in a 2048 bitmask >> structure, where each bit signifies the identification key of that SPR >> which is consistent with that of the POWER architecture set for that >> register. > Please answer the questions I asked the last time I reviewed this: > https://patchwork.ozlabs.org/patch/1174835/#2278701 Sure, I'll address them as they come further in the patch. > Since then I've also forgotten what the difference between > self-restore and the existing API is. So can you add something to > doc/power-management.rst to describe the relationship between the > current API, self-restore, and self-save? The new device-tree bindings > need to be documented in doc/device-tree/ibm,opal/power-mgt/ too. The > cover letter of the series covers some of that, but actual > documentation is sorely needed. Right, I'll add more description in the documentation and make sure it's complete >> +#define MAX_RESET_PATCH_SIZE 64 > unused? Yeah, I got rid of it. Sorry about that > >> + >> + const uint64_t self_restore_regs[] = { >> + P8_SPR_HRMOR, >> + P8_SPR_HMEER, >> + P8_SPR_PMICR, >> + P8_SPR_PMCR, >> + P8_SPR_HID0, >> + P8_SPR_HID1, >> + P8_SPR_HID4, >> + P8_SPR_HID5, >> + P8_SPR_HSPRG0, >> + P8_SPR_LPCR, >> + P8_SPR_PSSCR, >> + P8_MSR_MSR >> + }; >> + >> + const uint64_t self_save_regs[] = { >> + P9_STOP_SPR_DAWR, >> + P9_STOP_SPR_HSPRG0, >> + P9_STOP_SPR_LDBAR, >> + P9_STOP_SPR_LPCR, >> + P9_STOP_SPR_PSSCR, >> + P9_STOP_SPR_MSR, >> + P9_STOP_SPR_HRMOR, >> + P9_STOP_SPR_HMEER, >> + P9_STOP_SPR_PMCR, >> + P9_STOP_SPR_PTCR >> + }; > Again, where did these sets of registers come from? > These are the set of registers that are supported by the pore engine. Although our kernel only needs a subset of them, the whole list is sent out to indicate what is supported. >> + self_save_map = zalloc(BITMAP_BYTES(SPR_BITMAP_LENGTH)); >> + self_restore_map = zalloc(BITMAP_BYTES(SPR_BITMAP_LENGTH)); > In general I prefer people avoid doing allocations until they're > actually needed. If any of the checks below fail then we've done a > bunch of work for no reason so... do the checks first? Yeah makes sense, I can move the allocations down later when I really need them. It will also get rid of all the goto bail and I can just use a return instead. > >> + dt_add_property_string(self_restore, "status", "enabled"); >> + >> + dt_add_property(self_restore, "sprn-bitmask", *self_restore_map, >> + SPR_BITMAP_LENGTH / 8); >> + >> + self_save = dt_new(power_mgt, "self-save"); >> + if (!self_save) { >> + prerror("OCC: Failed to create self save node"); >> + goto bail; >> + } >> + if (proc_gen == proc_gen_p9) { >> + dt_add_property_string(self_save, "status", "enabled"); >> + >> + dt_add_property(self_save, "sprn-bitmask", *self_save_map, >> + SPR_BITMAP_LENGTH / 8); > If skiboot is compiled as little endian this is going to break. It > works today because we always build skiboot BE, but that may not > always be true. > Okay, I think I understand what you mean. I should run my bitmask through a loop 32 bits at a time with a be32_to_cpu while populating it? >> + } else { >> + dt_add_property_string(self_save, "status", "disabled"); > I still don't understand why we're adding anything to the DT if the > feature isn't supported. Today in the kernel, if the node doesn't exist we assume that we are running an older firmware on a newer kernel and make the self-restore call as it was always supported in legacy. Now let's take an example of a case where self-restore is actually unsupported, in that case if the node does not exist the kernel will assume it does and make the call anyways to see it fail later. Not that it is a bad thing for it to fail later and then cut support for stop states, however, I'm trying to avoid this try-catch scenario. If you feel that I should let it fail and handle it later, I'll do that instead. If you consider opposite scenario instead, that we allow self-restore only if the node is present, then using legacy skiboot deep stop states will be disabled which is again an undesired behavior. -- Pratik
On Mon, Feb 10, 2020 at 4:41 PM Pratik Sampat <psampat@linux.ibm.com> wrote: > > Hello Oliver, Thanks for the review. > > > On 10/02/20 7:43 am, Oliver O'Halloran wrote: > > On Fri, Feb 7, 2020 at 3:21 PM Pratik Rajesh Sampat > > <psampat@linux.ibm.com> wrote: > >> Support for self save and self restore interface is advertised in the > >> device tree, along with the list of SPRs it supports for each. > >> > >> The Special Purpose Register identification is encoded in a 2048 bitmask > >> structure, where each bit signifies the identification key of that SPR > >> which is consistent with that of the POWER architecture set for that > >> register. > > Please answer the questions I asked the last time I reviewed this: > > https://patchwork.ozlabs.org/patch/1174835/#2278701 > > Sure, I'll address them as they come further in the patch. > > > Since then I've also forgotten what the difference between > > self-restore and the existing API is. So can you add something to > > doc/power-management.rst to describe the relationship between the > > current API, self-restore, and self-save? The new device-tree bindings > > need to be documented in doc/device-tree/ibm,opal/power-mgt/ too. The > > cover letter of the series covers some of that, but actual > > documentation is sorely needed. > > Right, I'll add more description in the documentation and make sure it's > complete > > >> +#define MAX_RESET_PATCH_SIZE 64 > > unused? > > Yeah, I got rid of it. Sorry about that > > > > >> + > >> + const uint64_t self_restore_regs[] = { > >> + P8_SPR_HRMOR, > >> + P8_SPR_HMEER, > >> + P8_SPR_PMICR, > >> + P8_SPR_PMCR, > >> + P8_SPR_HID0, > >> + P8_SPR_HID1, > >> + P8_SPR_HID4, > >> + P8_SPR_HID5, > >> + P8_SPR_HSPRG0, > >> + P8_SPR_LPCR, > >> + P8_SPR_PSSCR, > >> + P8_MSR_MSR > >> + }; > >> + > >> + const uint64_t self_save_regs[] = { > >> + P9_STOP_SPR_DAWR, > >> + P9_STOP_SPR_HSPRG0, > >> + P9_STOP_SPR_LDBAR, > >> + P9_STOP_SPR_LPCR, > >> + P9_STOP_SPR_PSSCR, > >> + P9_STOP_SPR_MSR, > >> + P9_STOP_SPR_HRMOR, > >> + P9_STOP_SPR_HMEER, > >> + P9_STOP_SPR_PMCR, > >> + P9_STOP_SPR_PTCR > >> + }; > > Again, where did these sets of registers come from? > > > These are the set of registers that are supported by the pore engine. Although > our kernel only needs a subset of them, the whole list is sent out to indicate > what is supported. That doesn't really help. I'll assume that by "pore" you mean what's in libpore/p9_*.[CH] which writes a pile of stuff into the HOMER, but what consumes that? What I want to know is whether updates to some other bit of firmware can change the list of supported registers or not. > >> + self_save_map = zalloc(BITMAP_BYTES(SPR_BITMAP_LENGTH)); > >> + self_restore_map = zalloc(BITMAP_BYTES(SPR_BITMAP_LENGTH)); > > In general I prefer people avoid doing allocations until they're > > actually needed. If any of the checks below fail then we've done a > > bunch of work for no reason so... do the checks first? > > Yeah makes sense, I can move the allocations down later when I really need them. > It will also get rid of all the goto bail and I can just use a return instead. > > > > >> + dt_add_property_string(self_restore, "status", "enabled"); > >> + > >> + dt_add_property(self_restore, "sprn-bitmask", *self_restore_map, > >> + SPR_BITMAP_LENGTH / 8); > >> + > >> + self_save = dt_new(power_mgt, "self-save"); > >> + if (!self_save) { > >> + prerror("OCC: Failed to create self save node"); > >> + goto bail; > >> + } > >> + if (proc_gen == proc_gen_p9) { > >> + dt_add_property_string(self_save, "status", "enabled"); > >> + > >> + dt_add_property(self_save, "sprn-bitmask", *self_save_map, > >> + SPR_BITMAP_LENGTH / 8); > > If skiboot is compiled as little endian this is going to break. It > > works today because we always build skiboot BE, but that may not > > always be true. > > > Okay, I think I understand what you mean. I should run my bitmask through a > loop 32 bits at a time with a be32_to_cpu while populating it? Pretty much. You can check if it works by building skiboot in LE mode using: make clean && make LITTLE_ENDIAN=1 > > >> + } else { > >> + dt_add_property_string(self_save, "status", "disabled"); > > I still don't understand why we're adding anything to the DT if the > > feature isn't supported. > > Today in the kernel, if the node doesn't exist we assume that we are running an > older firmware on a newer kernel and make the self-restore call as it was > always supported in legacy. > > Now let's take an example of a case where self-restore is actually unsupported, > in that case if the node does not exist the kernel will assume it does and make > the call anyways to see it fail later. The case I'm concerned about is old-kernel / new-firmware since the legacy API is going to be broken if there's no self-restore capability. This series seems to be ignoring that fact when we're populating the DT so an older kernel is going to assume the legacy API is supported. What is the fallout from that? > Not that it is a bad thing for it to fail later and then cut support for stop > states, however, I'm trying to avoid this try-catch scenario. If you feel that > I should let it fail and handle it later, I'll do that instead. > > If you consider opposite scenario instead, that we allow self-restore only if > the node is present, then using legacy skiboot deep stop states will be > disabled which is again an undesired behavior. > > -- > > Pratik >
>>> Again, where did these sets of registers come from? >>> >> These are the set of registers that are supported by the pore engine. Although >> our kernel only needs a subset of them, the whole list is sent out to indicate >> what is supported. > That doesn't really help. I'll assume that by "pore" you mean what's > in libpore/p9_*.[CH] which writes a pile of stuff into the HOMER, but > what consumes that? What I want to know is whether updates to some > other bit of firmware can change the list of supported registers or > not. Well this is a list that the firmware currently supports. There is nothing to stop them from making changes to the support. The solution is that our self save now has support for versioning. So whenever something changes, the versions are updated and the compatibility of the SPRs can be determined and updated accordingly. >>>> + self_save_map = zalloc(BITMAP_BYTES(SPR_BITMAP_LENGTH)); >>>> + self_restore_map = zalloc(BITMAP_BYTES(SPR_BITMAP_LENGTH)); >>> In general I prefer people avoid doing allocations until they're >>> actually needed. If any of the checks below fail then we've done a >>> bunch of work for no reason so... do the checks first? >> Yeah makes sense, I can move the allocations down later when I really need them. >> It will also get rid of all the goto bail and I can just use a return instead. >> >>>> + dt_add_property_string(self_restore, "status", "enabled"); >>>> + >>>> + dt_add_property(self_restore, "sprn-bitmask", *self_restore_map, >>>> + SPR_BITMAP_LENGTH / 8); >>>> + >>>> + self_save = dt_new(power_mgt, "self-save"); >>>> + if (!self_save) { >>>> + prerror("OCC: Failed to create self save node"); >>>> + goto bail; >>>> + } >>>> + if (proc_gen == proc_gen_p9) { >>>> + dt_add_property_string(self_save, "status", "enabled"); >>>> + >>>> + dt_add_property(self_save, "sprn-bitmask", *self_save_map, >>>> + SPR_BITMAP_LENGTH / 8); >>> If skiboot is compiled as little endian this is going to break. It >>> works today because we always build skiboot BE, but that may not >>> always be true. >>> >> Okay, I think I understand what you mean. I should run my bitmask through a >> loop 32 bits at a time with a be32_to_cpu while populating it? > Pretty much. You can check if it works by building skiboot in LE mode > using: make clean && make LITTLE_ENDIAN=1 Sure. I'll try that out >>>> + } else { >>>> + dt_add_property_string(self_save, "status", "disabled"); >>> I still don't understand why we're adding anything to the DT if the >>> feature isn't supported. >> Today in the kernel, if the node doesn't exist we assume that we are running an >> older firmware on a newer kernel and make the self-restore call as it was >> always supported in legacy. >> >> Now let's take an example of a case where self-restore is actually unsupported, >> in that case if the node does not exist the kernel will assume it does and make >> the call anyways to see it fail later. > The case I'm concerned about is old-kernel / new-firmware since the > legacy API is going to be broken if there's no self-restore > capability. This series seems to be ignoring that fact when we're > populating the DT so an older kernel is going to assume the legacy API > is supported. What is the fallout from that? Your case is perfectly valid. However, isn't this what happens currently too? If for some reason, the self-restore call fails today, the kernel does handle the consequences. The try-catch sort of an approach is inevitable in this scenario as there is no way from which the kernel can know. I don't mind getting rid of it. I'll do a through test once to see if there's a corner case I'm missing and I'll remove it then. Thanks Pratik
diff --git a/hw/slw.c b/hw/slw.c index 5efa2168..087a8619 100644 --- a/hw/slw.c +++ b/hw/slw.c @@ -23,12 +23,15 @@ #include <nvram.h> #include <sbe-p8.h> #include <xive.h> +#include <bitmap.h> #include <p9_stop_api.H> #include <p8_pore_table_gen_api.H> #include <sbe_xip_image.h> static uint32_t slw_saved_reset[0x100]; +#define MAX_RESET_PATCH_SIZE 64 +#define SPR_BITMAP_LENGTH 2048 static bool slw_current_le = false; @@ -750,6 +753,84 @@ static void slw_late_init_p9(struct proc_chip *chip) } } +/* Add device tree properties to determine self-save | restore */ +void add_cpu_self_save_properties() +{ + int i; + struct dt_node *self_restore, *self_save, *power_mgt; + bitmap_t *self_restore_map, *self_save_map; + + const uint64_t self_restore_regs[] = { + P8_SPR_HRMOR, + P8_SPR_HMEER, + P8_SPR_PMICR, + P8_SPR_PMCR, + P8_SPR_HID0, + P8_SPR_HID1, + P8_SPR_HID4, + P8_SPR_HID5, + P8_SPR_HSPRG0, + P8_SPR_LPCR, + P8_SPR_PSSCR, + P8_MSR_MSR + }; + + const uint64_t self_save_regs[] = { + P9_STOP_SPR_DAWR, + P9_STOP_SPR_HSPRG0, + P9_STOP_SPR_LDBAR, + P9_STOP_SPR_LPCR, + P9_STOP_SPR_PSSCR, + P9_STOP_SPR_MSR, + P9_STOP_SPR_HRMOR, + P9_STOP_SPR_HMEER, + P9_STOP_SPR_PMCR, + P9_STOP_SPR_PTCR + }; + + self_save_map = zalloc(BITMAP_BYTES(SPR_BITMAP_LENGTH)); + self_restore_map = zalloc(BITMAP_BYTES(SPR_BITMAP_LENGTH)); + + for (i = 0; i < ARRAY_SIZE(self_save_regs); i++) + bitmap_set_bit(*self_save_map, self_save_regs[i]); + + for (i = 0; i < ARRAY_SIZE(self_restore_regs); i++) + bitmap_set_bit(*self_restore_map, self_restore_regs[i]); + + power_mgt = dt_find_by_path(dt_root, "/ibm,opal/power-mgt"); + if (!power_mgt) { + prerror("OCC: dt node /ibm,opal/power-mgt not found\n"); + goto bail; + } + + self_restore = dt_new(power_mgt, "self-restore"); + if (!self_restore) { + prerror("OCC: Failed to create self restore node"); + goto bail; + } + dt_add_property_string(self_restore, "status", "enabled"); + + dt_add_property(self_restore, "sprn-bitmask", *self_restore_map, + SPR_BITMAP_LENGTH / 8); + + self_save = dt_new(power_mgt, "self-save"); + if (!self_save) { + prerror("OCC: Failed to create self save node"); + goto bail; + } + if (proc_gen == proc_gen_p9) { + dt_add_property_string(self_save, "status", "enabled"); + + dt_add_property(self_save, "sprn-bitmask", *self_save_map, + SPR_BITMAP_LENGTH / 8); + } else { + dt_add_property_string(self_save, "status", "disabled"); + } +bail: + free(self_save_map); + free(self_restore_map); +} + /* Add device tree properties to describe idle states */ void add_cpu_idle_state_properties(void) { @@ -1563,4 +1644,6 @@ void slw_init(void) } } add_cpu_idle_state_properties(); + if (has_deep_states) + add_cpu_self_save_properties(); } diff --git a/include/skiboot.h b/include/skiboot.h index 072ce589..676211ad 100644 --- a/include/skiboot.h +++ b/include/skiboot.h @@ -209,6 +209,7 @@ extern void early_uart_init(void); extern void homer_init(void); extern void slw_init(void); extern void add_cpu_idle_state_properties(void); +extern void add_cpu_self_save_properties(void); extern void lpc_rtc_init(void); /* flash support */ diff --git a/libpore/p8_pore_table_gen_api.H b/libpore/p8_pore_table_gen_api.H index 63081ca5..d72fee90 100644 --- a/libpore/p8_pore_table_gen_api.H +++ b/libpore/p8_pore_table_gen_api.H @@ -233,6 +233,7 @@ enum { P8_SPR_HRMOR = 313, P8_SPR_HMEER = 337, P8_SPR_PMICR = 852, + P8_SPR_PSSCR = 855, P8_SPR_PMCR = 884, P8_SPR_HID0 = 1008, P8_SPR_HID1 = 1009,
Support for self save and self restore interface is advertised in the device tree, along with the list of SPRs it supports for each. The Special Purpose Register identification is encoded in a 2048 bitmask structure, where each bit signifies the identification key of that SPR which is consistent with that of the POWER architecture set for that register. Signed-off-by: Pratik Rajesh Sampat <psampat@linux.ibm.com> --- hw/slw.c | 83 +++++++++++++++++++++++++++++++++ include/skiboot.h | 1 + libpore/p8_pore_table_gen_api.H | 1 + 3 files changed, 85 insertions(+)